#include "ssl_locl.h"
#include <openssl/ct.h>
-static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, size_t ticklen,
- const unsigned char *sess_id, size_t sesslen,
- SSL_SESSION **psess);
-
SSL3_ENC_METHOD const TLSv1_enc_data = {
tls1_enc,
tls1_mac,
tls13_final_finish_mac,
TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
- tls1_alert_code,
+ tls13_alert_code,
tls1_export_keying_material,
SSL_ENC_FLAG_SIGALGS | SSL_ENC_FLAG_SHA256_PRF,
ssl3_set_handshake_header,
void tls1_free(SSL *s)
{
- OPENSSL_free(s->tlsext_session_ticket);
+ OPENSSL_free(s->ext.session_ticket);
ssl3_free(s);
}
0, 24, /* secp384r1 (24) */
};
-static const unsigned char eccurves_all[] = {
- 0, 29, /* X25519 (29) */
- 0, 23, /* secp256r1 (23) */
- 0, 25, /* secp521r1 (25) */
- 0, 24, /* secp384r1 (24) */
- 0, 26, /* brainpoolP256r1 (26) */
- 0, 27, /* brainpoolP384r1 (27) */
- 0, 28, /* brainpool512r1 (28) */
-
- /*
- * Remaining curves disabled by default but still permitted if set
- * via an explicit callback or parameters.
- */
- 0, 22, /* secp256k1 (22) */
- 0, 14, /* sect571r1 (14) */
- 0, 13, /* sect571k1 (13) */
- 0, 11, /* sect409k1 (11) */
- 0, 12, /* sect409r1 (12) */
- 0, 9, /* sect283k1 (9) */
- 0, 10, /* sect283r1 (10) */
- 0, 20, /* secp224k1 (20) */
- 0, 21, /* secp224r1 (21) */
- 0, 18, /* secp192k1 (18) */
- 0, 19, /* secp192r1 (19) */
- 0, 15, /* secp160k1 (15) */
- 0, 16, /* secp160r1 (16) */
- 0, 17, /* secp160r2 (17) */
- 0, 8, /* sect239k1 (8) */
- 0, 6, /* sect233k1 (6) */
- 0, 7, /* sect233r1 (7) */
- 0, 4, /* sect193r1 (4) */
- 0, 5, /* sect193r2 (5) */
- 0, 1, /* sect163k1 (1) */
- 0, 2, /* sect163r1 (2) */
- 0, 3, /* sect163r2 (3) */
-};
-
static const unsigned char suiteb_curves[] = {
0, TLSEXT_curve_P_256,
0, TLSEXT_curve_P_384
size_t *num_curves)
{
size_t pcurveslen = 0;
+
if (sess) {
- *pcurves = s->session->tlsext_supportedgroupslist;
- pcurveslen = s->session->tlsext_supportedgroupslist_length;
+ *pcurves = s->session->ext.supportedgroups;
+ pcurveslen = s->session->ext.supportedgroups_len;
} else {
/* For Suite B mode only include P-256, P-384 */
switch (tls1_suiteb(s)) {
pcurveslen = 2;
break;
default:
- *pcurves = s->tlsext_supportedgroupslist;
- pcurveslen = s->tlsext_supportedgroupslist_length;
+ *pcurves = s->ext.supportedgroups;
+ pcurveslen = s->ext.supportedgroups_len;
}
if (!*pcurves) {
*pcurves = eccurves_default;
SSLerr(SSL_F_TLS1_GET_CURVELIST, ERR_R_INTERNAL_ERROR);
*num_curves = 0;
return 0;
- } else {
- *num_curves = pcurveslen / 2;
- return 1;
}
+ *num_curves = pcurveslen / 2;
+ return 1;
}
/* See if curve is allowed by security callback */
const unsigned char *pref, *supp;
size_t num_pref, num_supp, i, j;
int k;
+
/* Can't do anything on client side */
if (s->server == 0)
return -1;
* these are acceptable due to previous checks.
*/
unsigned long cid = s->s3->tmp.new_cipher->id;
+
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
return NID_X9_62_prime256v1; /* P-256 */
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
* Avoid truncation. tls1_get_curvelist takes an int
* but s->options is a long...
*/
- if (!tls1_get_curvelist
- (s, (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) != 0, &supp,
- &num_supp))
+ if (!tls1_get_curvelist(s,
+ (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) != 0,
+ &supp, &num_supp))
/* In practice, NID_undef == 0 but let's be precise. */
return nmatch == -1 ? 0 : NID_undef;
- if (!tls1_get_curvelist
- (s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), &pref, &num_pref))
+ if (!tls1_get_curvelist(s,
+ (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) == 0,
+ &pref, &num_pref))
return nmatch == -1 ? 0 : NID_undef;
- /*
- * If the client didn't send the elliptic_curves extension all of them
- * are allowed.
- */
- if (num_supp == 0 && (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) != 0) {
- supp = eccurves_all;
- num_supp = sizeof(eccurves_all) / 2;
- } else if (num_pref == 0 &&
- (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) == 0) {
- pref = eccurves_all;
- num_pref = sizeof(eccurves_all) / 2;
- }
-
- k = 0;
- for (i = 0; i < num_pref; i++, pref += 2) {
+ for (k = 0, i = 0; i < num_pref; i++, pref += 2) {
const unsigned char *tsupp = supp;
+
for (j = 0; j < num_supp; j++, tsupp += 2) {
if (pref[0] == tsupp[0] && pref[1] == tsupp[1]) {
if (!tls_curve_allowed(s, pref, SSL_SECOP_CURVE_SHARED))
continue;
if (nmatch == k) {
int id = (pref[0] << 8) | pref[1];
+
return tls1_ec_curve_id2nid(id, NULL);
}
k++;
* If point formats extension present check it, otherwise everything is
* supported (see RFC4492).
*/
- if (comp_id && s->session->tlsext_ecpointformatlist) {
- pformats = s->session->tlsext_ecpointformatlist;
- num_formats = s->session->tlsext_ecpointformatlist_length;
+ if (comp_id && s->session->ext.ecpointformats) {
+ pformats = s->session->ext.ecpointformats;
+ num_formats = s->session->ext.ecpointformats_len;
for (i = 0; i < num_formats; i++, pformats++) {
if (*comp_id == *pformats)
break;
/*
* If we have a custom point format list use it otherwise use default
*/
- if (s->tlsext_ecpointformatlist) {
- *pformats = s->tlsext_ecpointformatlist;
- *num_formats = s->tlsext_ecpointformatlist_length;
+ if (s->ext.ecpointformats) {
+ *pformats = s->ext.ecpointformats;
+ *num_formats = s->ext.ecpointformats_len;
} else {
*pformats = ecformats_default;
/* For Suite B we don't support char2 fields */
* Check cert parameters compatible with extensions: currently just checks EC
* certificates have compatible curves and compression.
*/
-static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md)
+static int tls1_check_cert_param(SSL *s, X509 *x, int check_ee_md)
{
unsigned char comp_id, curve_id[2];
EVP_PKEY *pkey;
return 0;
/*
* Special case for suite B. We *MUST* sign using SHA256+P-256 or
- * SHA384+P-384, adjust digest if necessary.
+ * SHA384+P-384.
*/
- if (set_ee_md && tls1_suiteb(s)) {
+ if (check_ee_md && tls1_suiteb(s)) {
int check_md;
size_t i;
CERT *c = s->cert;
else
return 0; /* Should never happen */
for (i = 0; i < c->shared_sigalgslen; i++)
- if (check_md == c->shared_sigalgs[i].signandhash_nid)
+ if (check_md == c->shared_sigalgs[i]->sigandhash)
break;
if (i == c->shared_sigalgslen)
return 0;
- if (set_ee_md == 2) {
- if (check_md == NID_ecdsa_with_SHA256)
- s->s3->tmp.md[SSL_PKEY_ECC] = EVP_sha256();
- else
- s->s3->tmp.md[SSL_PKEY_ECC] = EVP_sha384();
- }
}
return rv;
}
#endif /* OPENSSL_NO_EC */
-/*
- * List of supported signature algorithms and hashes. Should make this
- * customisable at some point, for now include everything we support.
- */
+/* Default sigalg schemes */
+static const uint16_t tls12_sigalgs[] = {
+#ifndef OPENSSL_NO_EC
+ TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
+ TLSEXT_SIGALG_ecdsa_secp384r1_sha384,
+ TLSEXT_SIGALG_ecdsa_secp521r1_sha512,
+#endif
-#ifdef OPENSSL_NO_RSA
-# define tlsext_sigalg_rsa(md) /* */
-#else
-# define tlsext_sigalg_rsa(md) md, TLSEXT_signature_rsa,
+ TLSEXT_SIGALG_rsa_pss_sha256,
+ TLSEXT_SIGALG_rsa_pss_sha384,
+ TLSEXT_SIGALG_rsa_pss_sha512,
+
+ TLSEXT_SIGALG_rsa_pkcs1_sha256,
+ TLSEXT_SIGALG_rsa_pkcs1_sha384,
+ TLSEXT_SIGALG_rsa_pkcs1_sha512,
+
+#ifndef OPENSSL_NO_EC
+ TLSEXT_SIGALG_ecdsa_sha1,
#endif
+ TLSEXT_SIGALG_rsa_pkcs1_sha1,
+#ifndef OPENSSL_NO_DSA
+ TLSEXT_SIGALG_dsa_sha1,
-#ifdef OPENSSL_NO_DSA
-# define tlsext_sigalg_dsa(md) /* */
-#else
-# define tlsext_sigalg_dsa(md) md, TLSEXT_signature_dsa,
+ TLSEXT_SIGALG_dsa_sha256,
+ TLSEXT_SIGALG_dsa_sha384,
+ TLSEXT_SIGALG_dsa_sha512
#endif
+};
-#ifdef OPENSSL_NO_EC
-# define tlsext_sigalg_ecdsa(md)/* */
-#else
-# define tlsext_sigalg_ecdsa(md) md, TLSEXT_signature_ecdsa,
+#ifndef OPENSSL_NO_EC
+static const uint16_t suiteb_sigalgs[] = {
+ TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
+ TLSEXT_SIGALG_ecdsa_secp384r1_sha384
+};
#endif
-#define tlsext_sigalg(md) \
- tlsext_sigalg_rsa(md) \
- tlsext_sigalg_dsa(md) \
- tlsext_sigalg_ecdsa(md)
-
-static const unsigned char tls12_sigalgs[] = {
- tlsext_sigalg(TLSEXT_hash_sha512)
- tlsext_sigalg(TLSEXT_hash_sha384)
- tlsext_sigalg(TLSEXT_hash_sha256)
- tlsext_sigalg(TLSEXT_hash_sha224)
- tlsext_sigalg(TLSEXT_hash_sha1)
+static const SIGALG_LOOKUP sigalg_lookup_tbl[] = {
+#ifndef OPENSSL_NO_EC
+ {"ecdsa_secp256r1_sha256", TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
+ NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
+ NID_ecdsa_with_SHA256, NID_X9_62_prime256v1},
+ {"ecdsa_secp384r1_sha384", TLSEXT_SIGALG_ecdsa_secp384r1_sha384,
+ NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
+ NID_ecdsa_with_SHA384, NID_secp384r1},
+ {"ecdsa_secp521r1_sha512", TLSEXT_SIGALG_ecdsa_secp521r1_sha512,
+ NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
+ NID_ecdsa_with_SHA512, NID_secp521r1},
+ {NULL, TLSEXT_SIGALG_ecdsa_sha1,
+ NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
+ NID_ecdsa_with_SHA1, NID_undef},
+#endif
+ {"rsa_pss_sha256", TLSEXT_SIGALG_rsa_pss_sha256,
+ NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
+ NID_undef, NID_undef},
+ {"rsa_pss_sha384", TLSEXT_SIGALG_rsa_pss_sha384,
+ NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
+ NID_undef, NID_undef},
+ {"rsa_pss_sha512", TLSEXT_SIGALG_rsa_pss_sha512,
+ NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
+ NID_undef, NID_undef},
+ {"rsa_pkcs1_sha256", TLSEXT_SIGALG_rsa_pkcs1_sha256,
+ NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
+ NID_sha256WithRSAEncryption, NID_undef},
+ {"rsa_pkcs1_sha384", TLSEXT_SIGALG_rsa_pkcs1_sha384,
+ NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
+ NID_sha384WithRSAEncryption, NID_undef},
+ {"rsa_pkcs1_sha512", TLSEXT_SIGALG_rsa_pkcs1_sha512,
+ NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
+ NID_sha512WithRSAEncryption, NID_undef},
+ {"rsa_pkcs1_sha1", TLSEXT_SIGALG_rsa_pkcs1_sha1,
+ NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
+ NID_sha1WithRSAEncryption, NID_undef},
+#ifndef OPENSSL_NO_DSA
+ {NULL, TLSEXT_SIGALG_dsa_sha256,
+ NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
+ NID_dsa_with_SHA256, NID_undef},
+ {NULL, TLSEXT_SIGALG_dsa_sha384,
+ NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
+ NID_undef, NID_undef},
+ {NULL, TLSEXT_SIGALG_dsa_sha512,
+ NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
+ NID_undef, NID_undef},
+ {NULL, TLSEXT_SIGALG_dsa_sha1,
+ NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
+ NID_dsaWithSHA1, NID_undef},
+#endif
#ifndef OPENSSL_NO_GOST
- TLSEXT_hash_gostr3411, TLSEXT_signature_gostr34102001,
- TLSEXT_hash_gostr34112012_256, TLSEXT_signature_gostr34102012_256,
- TLSEXT_hash_gostr34112012_512, TLSEXT_signature_gostr34102012_512
+ {NULL, TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256,
+ NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX,
+ NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256,
+ NID_undef, NID_undef},
+ {NULL, TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512,
+ NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX,
+ NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512,
+ NID_undef, NID_undef},
+ {NULL, TLSEXT_SIGALG_gostr34102001_gostr3411,
+ NID_id_GostR3411_94, SSL_MD_GOST94_IDX,
+ NID_id_GostR3410_2001, SSL_PKEY_GOST01,
+ NID_undef, NID_undef}
#endif
};
+/* Legacy sigalgs for TLS < 1.2 RSA TLS signatures */
+static const SIGALG_LOOKUP legacy_rsa_sigalg = {
+ "rsa_pkcs1_md5_sha1", 0,
+ NID_md5_sha1, SSL_MD_MD5_SHA1_IDX,
+ EVP_PKEY_RSA, SSL_PKEY_RSA,
+ NID_undef, NID_undef
+};
-#ifndef OPENSSL_NO_EC
-static const unsigned char suiteb_sigalgs[] = {
- tlsext_sigalg_ecdsa(TLSEXT_hash_sha256)
- tlsext_sigalg_ecdsa(TLSEXT_hash_sha384)
+/*
+ * Default signature algorithm values used if signature algorithms not present.
+ * From RFC5246. Note: order must match certificate index order.
+ */
+static const uint16_t tls_default_sigalg[] = {
+ TLSEXT_SIGALG_rsa_pkcs1_sha1, /* SSL_PKEY_RSA */
+ TLSEXT_SIGALG_dsa_sha1, /* SSL_PKEY_DSA_SIGN */
+ TLSEXT_SIGALG_ecdsa_sha1, /* SSL_PKEY_ECC */
+ TLSEXT_SIGALG_gostr34102001_gostr3411, /* SSL_PKEY_GOST01 */
+ TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, /* SSL_PKEY_GOST12_256 */
+ TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 /* SSL_PKEY_GOST12_512 */
};
-#endif
-size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs)
+
+/* Lookup TLS signature algorithm */
+static const SIGALG_LOOKUP *tls1_lookup_sigalg(uint16_t sigalg)
+{
+ size_t i;
+ const SIGALG_LOOKUP *s;
+
+ for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
+ i++, s++) {
+ if (s->sigalg == sigalg)
+ return s;
+ }
+ return NULL;
+}
+/*
+ * Return a signature algorithm for TLS < 1.2 where the signature type
+ * is fixed by the certificate type.
+ */
+static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL *s, int idx)
+{
+ if (idx < 0 || idx >= (int)OSSL_NELEM(tls_default_sigalg))
+ return NULL;
+ if (SSL_USE_SIGALGS(s) || idx != SSL_PKEY_RSA) {
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(tls_default_sigalg[idx]);
+
+ if (lu == NULL || ssl_md(lu->hash_idx) == NULL) {
+ return NULL;
+ }
+ return lu;
+ }
+ return &legacy_rsa_sigalg;
+}
+/* Set peer sigalg based key type */
+int tls1_set_peer_legacy_sigalg(SSL *s, const EVP_PKEY *pkey)
+{
+ int idx = ssl_cert_type(NULL, pkey);
+
+ const SIGALG_LOOKUP *lu = tls1_get_legacy_sigalg(s, idx);
+ if (lu == NULL)
+ return 0;
+ s->s3->tmp.peer_sigalg = lu;
+ return 1;
+}
+
+size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs)
{
/*
* If Suite B mode use Suite B sigalgs only, ignore any other
switch (tls1_suiteb(s)) {
case SSL_CERT_FLAG_SUITEB_128_LOS:
*psigs = suiteb_sigalgs;
- return sizeof(suiteb_sigalgs);
+ return OSSL_NELEM(suiteb_sigalgs);
case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
*psigs = suiteb_sigalgs;
- return 2;
+ return 1;
case SSL_CERT_FLAG_SUITEB_192_LOS:
- *psigs = suiteb_sigalgs + 2;
- return 2;
+ *psigs = suiteb_sigalgs + 1;
+ return 1;
}
#endif
- /* If server use client authentication sigalgs if not NULL */
- if (s->server && s->cert->client_sigalgs) {
+ /*
+ * We use client_sigalgs (if not NULL) if we're a server
+ * and sending a certificate request or if we're a client and
+ * determining which shared algorithm to use.
+ */
+ if ((s->server == sent) && s->cert->client_sigalgs != NULL) {
*psigs = s->cert->client_sigalgs;
return s->cert->client_sigalgslen;
} else if (s->cert->conf_sigalgs) {
return s->cert->conf_sigalgslen;
} else {
*psigs = tls12_sigalgs;
- return sizeof(tls12_sigalgs);
+ return OSSL_NELEM(tls12_sigalgs);
}
}
/*
* Check signature algorithm is consistent with sent supported signature
- * algorithms and if so return relevant digest.
+ * algorithms and if so set relevant digest and signature scheme in
+ * s.
*/
-int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
- const unsigned char *sig, EVP_PKEY *pkey)
+int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
{
- const unsigned char *sent_sigs;
+ const uint16_t *sent_sigs;
+ const EVP_MD *md = NULL;
+ char sigalgstr[2];
size_t sent_sigslen, i;
- int sigalg = tls12_get_sigid(pkey);
+ int pkeyid = EVP_PKEY_id(pkey);
+ const SIGALG_LOOKUP *lu;
+
/* Should never happen */
- if (sigalg == -1)
+ if (pkeyid == -1)
return -1;
- /* Check key type is consistent with signature */
- if (sigalg != (int)sig[1]) {
+ if (SSL_IS_TLS13(s)) {
+ /* Disallow DSA for TLS 1.3 */
+ if (pkeyid == EVP_PKEY_DSA) {
+ SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
+ return 0;
+ }
+ /* Only allow PSS for TLS 1.3 */
+ if (pkeyid == EVP_PKEY_RSA)
+ pkeyid = EVP_PKEY_RSA_PSS;
+ }
+ lu = tls1_lookup_sigalg(sig);
+ /*
+ * Check sigalgs is known. Disallow SHA1 with TLS 1.3. Check key type is
+ * consistent with signature: RSA keys can be used for RSA-PSS
+ */
+ if (lu == NULL || (SSL_IS_TLS13(s) && lu->hash == NID_sha1)
+ || (pkeyid != lu->sig
+ && (lu->sig != EVP_PKEY_RSA_PSS || pkeyid != EVP_PKEY_RSA))) {
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
#ifndef OPENSSL_NO_EC
- if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) {
- unsigned char curve_id[2], comp_id;
- /* Check compression and curve matches extensions */
- if (!tls1_set_ec_id(curve_id, &comp_id, EVP_PKEY_get0_EC_KEY(pkey)))
- return 0;
- if (!s->server && !tls1_check_ec_key(s, curve_id, &comp_id)) {
- SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
- return 0;
- }
- /* If Suite B only P-384+SHA384 or P-256+SHA-256 allowed */
- if (tls1_suiteb(s)) {
- if (curve_id[0])
+ if (pkeyid == EVP_PKEY_EC) {
+ EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
+ int curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
+
+ if (SSL_IS_TLS13(s)) {
+ if (EC_KEY_get_conv_form(ec) != POINT_CONVERSION_UNCOMPRESSED) {
+ SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,
+ SSL_R_ILLEGAL_POINT_COMPRESSION);
+ return 0;
+ }
+ /* For TLS 1.3 check curve matches signature algorithm */
+ if (lu->curve != NID_undef && curve != lu->curve) {
+ SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
+ return 0;
+ }
+ } else {
+ unsigned char curve_id[2], comp_id;
+
+ /* Check compression and curve matches extensions */
+ if (!tls1_set_ec_id(curve_id, &comp_id, ec))
+ return 0;
+ if (!s->server && !tls1_check_ec_key(s, curve_id, &comp_id)) {
+ SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
return 0;
- if (curve_id[1] == TLSEXT_curve_P_256) {
- if (sig[0] != TLSEXT_hash_sha256) {
+ }
+ if (tls1_suiteb(s)) {
+ /* Check sigalg matches a permissible Suite B value */
+ if (sig != TLSEXT_SIGALG_ecdsa_secp256r1_sha256
+ && sig != TLSEXT_SIGALG_ecdsa_secp384r1_sha384) {
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,
- SSL_R_ILLEGAL_SUITEB_DIGEST);
+ SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
- } else if (curve_id[1] == TLSEXT_curve_P_384) {
- if (sig[0] != TLSEXT_hash_sha384) {
+ /*
+ * Suite B also requires P-256+SHA256 and P-384+SHA384:
+ * this matches the TLS 1.3 requirements so we can just
+ * check the curve is the expected TLS 1.3 value.
+ * If this fails an inappropriate digest is being used.
+ */
+ if (curve != lu->curve) {
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,
SSL_R_ILLEGAL_SUITEB_DIGEST);
return 0;
}
- } else
- return 0;
+ }
}
- } else if (tls1_suiteb(s))
+ } else if (tls1_suiteb(s)) {
return 0;
+ }
#endif
/* Check signature matches a type we sent */
- sent_sigslen = tls12_get_psigalgs(s, &sent_sigs);
- for (i = 0; i < sent_sigslen; i += 2, sent_sigs += 2) {
- if (sig[0] == sent_sigs[0] && sig[1] == sent_sigs[1])
+ sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
+ for (i = 0; i < sent_sigslen; i++, sent_sigs++) {
+ if (sig == *sent_sigs)
break;
}
/* Allow fallback to SHA1 if not strict mode */
- if (i == sent_sigslen
- && (sig[0] != TLSEXT_hash_sha1
- || s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) {
+ if (i == sent_sigslen && (lu->hash != NID_sha1
+ || s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) {
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
- *pmd = tls12_get_hash(sig[0]);
- if (*pmd == NULL) {
+ md = ssl_md(lu->hash_idx);
+ if (md == NULL) {
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_UNKNOWN_DIGEST);
return 0;
}
- /* Make sure security callback allows algorithm */
+ /*
+ * Make sure security callback allows algorithm. For historical reasons we
+ * have to pass the sigalg as a two byte char array.
+ */
+ sigalgstr[0] = (sig >> 8) & 0xff;
+ sigalgstr[1] = sig & 0xff;
if (!ssl_security(s, SSL_SECOP_SIGALG_CHECK,
- EVP_MD_size(*pmd) * 4, EVP_MD_type(*pmd), (void *)sig)) {
+ EVP_MD_size(md) * 4, EVP_MD_type(md),
+ (void *)sigalgstr)) {
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
- /*
- * Store the digest used so applications can retrieve it if they wish.
- */
- s->s3->tmp.peer_md = *pmd;
+ /* Store the sigalg the peer uses */
+ s->s3->tmp.peer_sigalg = lu;
+ return 1;
+}
+
+int SSL_get_peer_signature_type_nid(const SSL *s, int *pnid)
+{
+ if (s->s3->tmp.peer_sigalg == NULL)
+ return 0;
+ *pnid = s->s3->tmp.peer_sigalg->sig;
return 1;
}
* @s: SSL connection that you want to use the cipher on
* @c: cipher to check
* @op: Security check that you want to do
+ * @ecdhe: If set to 1 then TLSv1 ECDHE ciphers are also allowed in SSLv3
*
* Returns 1 when it's disabled, 0 when enabled.
*/
-int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op)
+int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op, int ecdhe)
{
if (c->algorithm_mkey & s->s3->tmp.mask_k
|| c->algorithm_auth & s->s3->tmp.mask_a)
return 1;
if (s->s3->tmp.max_ver == 0)
return 1;
- if (!SSL_IS_DTLS(s) && ((c->min_tls > s->s3->tmp.max_ver)
- || (c->max_tls < s->s3->tmp.min_ver)))
- return 1;
- if (SSL_IS_DTLS(s) && (DTLS_VERSION_GT(c->min_dtls, s->s3->tmp.max_ver)
- || DTLS_VERSION_LT(c->max_dtls, s->s3->tmp.min_ver)))
- return 1;
-
- return !ssl_security(s, op, c->strength_bits, 0, (void *)c);
-}
-
-int tls_use_ticket(SSL *s)
-{
- if ((s->options & SSL_OP_NO_TICKET) || SSL_IS_TLS13(s))
- return 0;
- return ssl_security(s, SSL_SECOP_TICKET, 0, 0, NULL);
-}
-
-int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al)
-{
-#ifndef OPENSSL_NO_EC
- const unsigned char *pcurves = NULL;
- size_t num_curves = 0;
- int using_ecc = 0;
- int min_version, max_version, reason;
-
- /* See if we support any ECC ciphersuites */
- if ((s->version >= TLS1_VERSION && s->version <= TLS1_3_VERSION)
- || SSL_IS_DTLS(s)) {
- int i;
- unsigned long alg_k, alg_a;
- STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s);
-
- for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) {
- const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
-
- alg_k = c->algorithm_mkey;
- alg_a = c->algorithm_auth;
- if ((alg_k & (SSL_kECDHE | SSL_kECDHEPSK))
- || (alg_a & SSL_aECDSA)
- || c->min_tls >= TLS1_3_VERSION) {
- using_ecc = 1;
- break;
- }
- }
- }
-#else
- if (SSL_IS_TLS13(s)) {
- /* Shouldn't happen! */
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-#endif
-
- /* Add RI if renegotiating */
- if (s->renegotiate) {
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_sub_memcpy_u8(pkt, s->s3->previous_client_finished,
- s->s3->previous_client_finished_len)
- || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- /* Only add RI for SSLv3 */
- if (s->client_version == SSL3_VERSION)
- goto done;
-
- if (s->tlsext_hostname != NULL) {
- /* Add TLS extension servername to the Client Hello message */
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
- /* Sub-packet for server_name extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- /* Sub-packet for servername list (always 1 hostname)*/
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_put_bytes_u8(pkt, TLSEXT_NAMETYPE_host_name)
- || !WPACKET_sub_memcpy_u16(pkt, s->tlsext_hostname,
- strlen(s->tlsext_hostname))
- || !WPACKET_close(pkt)
- || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-#ifndef OPENSSL_NO_SRP
- /* Add SRP username if there is one */
- if (s->srp_ctx.login != NULL) {
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_srp)
- /* Sub-packet for SRP extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_start_sub_packet_u8(pkt)
- /* login must not be zero...internal error if so */
- || !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)
- || !WPACKET_memcpy(pkt, s->srp_ctx.login,
- strlen(s->srp_ctx.login))
- || !WPACKET_close(pkt)
- || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-#endif
-
-#ifndef OPENSSL_NO_EC
- if (using_ecc) {
- /*
- * Add TLS extension ECPointFormats to the ClientHello message
- */
- const unsigned char *pformats, *pcurvestmp;
- size_t num_formats;
- size_t i;
-
- tls1_get_formatlist(s, &pformats, &num_formats);
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
- /* Sub-packet for formats extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_sub_memcpy_u8(pkt, pformats, num_formats)
- || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /*
- * Add TLS extension supported_groups to the ClientHello message
- */
- /* TODO(TLS1.3): Add support for DHE groups */
- pcurves = s->tlsext_supportedgroupslist;
- if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- pcurvestmp = pcurves;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups)
- /* Sub-packet for supported_groups extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_start_sub_packet_u16(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- /* Copy curve ID if supported */
- for (i = 0; i < num_curves; i++, pcurvestmp += 2) {
- if (tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) {
- if (!WPACKET_put_bytes_u8(pkt, pcurvestmp[0])
- || !WPACKET_put_bytes_u8(pkt, pcurvestmp[1])) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- }
- if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-#endif /* OPENSSL_NO_EC */
-
- if (tls_use_ticket(s)) {
- size_t ticklen;
- if (!s->new_session && s->session && s->session->tlsext_tick)
- ticklen = s->session->tlsext_ticklen;
- else if (s->session && s->tlsext_session_ticket &&
- s->tlsext_session_ticket->data) {
- ticklen = s->tlsext_session_ticket->length;
- s->session->tlsext_tick = OPENSSL_malloc(ticklen);
- if (s->session->tlsext_tick == NULL) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- memcpy(s->session->tlsext_tick,
- s->tlsext_session_ticket->data, ticklen);
- s->session->tlsext_ticklen = ticklen;
- } else
- ticklen = 0;
- if (ticklen == 0 && s->tlsext_session_ticket &&
- s->tlsext_session_ticket->data == NULL)
- goto skip_ext;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
- || !WPACKET_sub_memcpy_u16(pkt, s->session->tlsext_tick,
- ticklen)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- skip_ext:
-
- if (SSL_CLIENT_USE_SIGALGS(s)) {
- size_t salglen;
- const unsigned char *salg;
-
- salglen = tls12_get_psigalgs(s, &salg);
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signature_algorithms)
- /* Sub-packet for sig-algs extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- /* Sub-packet for the actual list */
- || !WPACKET_start_sub_packet_u16(pkt)
- || !tls12_copy_sigalgs(s, pkt, salg, salglen)
- || !WPACKET_close(pkt)
- || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-#ifndef OPENSSL_NO_OCSP
- if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) {
- int i;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
- /* Sub-packet for status request extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_put_bytes_u8(pkt, TLSEXT_STATUSTYPE_ocsp)
- /* Sub-packet for the ids */
- || !WPACKET_start_sub_packet_u16(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++) {
- unsigned char *idbytes;
- int idlen;
- OCSP_RESPID *id;
-
- id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
- idlen = i2d_OCSP_RESPID(id, NULL);
- if (idlen <= 0
- /* Sub-packet for an individual id */
- || !WPACKET_sub_allocate_bytes_u16(pkt, idlen, &idbytes)
- || i2d_OCSP_RESPID(id, &idbytes) != idlen) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- if (!WPACKET_close(pkt)
- || !WPACKET_start_sub_packet_u16(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if (s->tlsext_ocsp_exts) {
- unsigned char *extbytes;
- int extlen = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL);
-
- if (extlen < 0) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if (!WPACKET_allocate_bytes(pkt, extlen, &extbytes)
- || i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &extbytes)
- != extlen) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-#endif
-
-#ifndef OPENSSL_NO_NEXTPROTONEG
- if (s->ctx->next_proto_select_cb && !s->s3->tmp.finish_md_len) {
- /*
- * The client advertises an empty extension to indicate its support
- * for Next Protocol Negotiation
- */
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
- || !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-#endif
-
- /*
- * finish_md_len is non-zero during a renegotiation, so
- * this avoids sending ALPN during the renegotiation
- * (see longer comment below)
- */
- if (s->alpn_client_proto_list && !s->s3->tmp.finish_md_len) {
- if (!WPACKET_put_bytes_u16(pkt,
- TLSEXT_TYPE_application_layer_protocol_negotiation)
- /* Sub-packet ALPN extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_sub_memcpy_u16(pkt, s->alpn_client_proto_list,
- s->alpn_client_proto_list_len)
- || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- s->s3->alpn_sent = 1;
- }
-#ifndef OPENSSL_NO_SRTP
- if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)) {
- STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = SSL_get_srtp_profiles(s);
- SRTP_PROTECTION_PROFILE *prof;
- int i, ct;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
- /* Sub-packet for SRTP extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- /* Sub-packet for the protection profile list */
- || !WPACKET_start_sub_packet_u16(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- ct = sk_SRTP_PROTECTION_PROFILE_num(clnt);
- for (i = 0; i < ct; i++) {
- prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
- if (prof == NULL || !WPACKET_put_bytes_u16(pkt, prof->id)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- if (!WPACKET_close(pkt)
- /* Add an empty use_mki value */
- || !WPACKET_put_bytes_u8(pkt, 0)
- || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-#endif
- custom_ext_init(&s->cert->cli_ext);
- /* Add custom TLS Extensions to ClientHello */
- if (!custom_ext_add(s, 0, pkt, al)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)) {
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
- || !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-
-#ifndef OPENSSL_NO_CT
- if (s->ct_validation_callback != NULL) {
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signed_certificate_timestamp)
- || !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-#endif
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
- || !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- reason = ssl_get_client_min_max_version(s, &min_version, &max_version);
- if (reason != 0) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, reason);
- return 0;
- }
-
- /* TLS1.3 specific extensions */
- if (!SSL_IS_DTLS(s) && max_version >= TLS1_3_VERSION) {
- int currv;
- size_t i, sharessent = 0;
-
- /* TODO(TLS1.3): Should we add this extension for versions < TLS1.3? */
- /* supported_versions extension */
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_start_sub_packet_u8(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /*
- * TODO(TLS1.3): There is some discussion on the TLS list as to wheter
- * we should include versions <TLS1.2. For the moment we do. To be
- * reviewed later.
- */
- for (currv = max_version; currv >= min_version; currv--) {
- /* TODO(TLS1.3): Remove this first if clause prior to release!! */
- if (currv == TLS1_3_VERSION) {
- if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- } else if (!WPACKET_put_bytes_u16(pkt, currv)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
-
- /* key_share extension */
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
- /* Extension data sub-packet */
- || !WPACKET_start_sub_packet_u16(pkt)
- /* KeyShare list sub-packet */
- || !WPACKET_start_sub_packet_u16(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
+ if (!SSL_IS_DTLS(s)) {
+ int min_tls = c->min_tls;
/*
- * TODO(TLS1.3): Make the number of key_shares sent configurable. For
- * now, just send one
+ * For historical reasons we will allow ECHDE to be selected by a server
+ * in SSLv3 if we are a client
*/
- for (i = 0; i < num_curves && sharessent < 1; i++, pcurves += 2) {
- unsigned char *encodedPoint = NULL;
- unsigned int curve_id = 0;
- EVP_PKEY *key_share_key = NULL;
- size_t encodedlen;
+ if (min_tls == TLS1_VERSION && ecdhe
+ && (c->algorithm_mkey & (SSL_kECDHE | SSL_kECDHEPSK)) != 0)
+ min_tls = SSL3_VERSION;
- if (!tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED))
- continue;
-
- if (s->s3->tmp.pkey != NULL) {
- /* Shouldn't happen! */
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /* Generate a key for this key_share */
- curve_id = (pcurves[0] << 8) | pcurves[1];
- key_share_key = ssl_generate_pkey_curve(curve_id);
- if (key_share_key == NULL) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_EVP_LIB);
- return 0;
- }
-
- /* Encode the public key. */
- encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key,
- &encodedPoint);
- if (encodedlen == 0) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_EC_LIB);
- EVP_PKEY_free(key_share_key);
- return 0;
- }
-
- /* Create KeyShareEntry */
- if (!WPACKET_put_bytes_u16(pkt, curve_id)
- || !WPACKET_sub_memcpy_u16(pkt, encodedPoint, encodedlen)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT,
- ERR_R_INTERNAL_ERROR);
- EVP_PKEY_free(key_share_key);
- OPENSSL_free(encodedPoint);
- return 0;
- }
-
- /*
- * TODO(TLS1.3): When changing to send more than one key_share we're
- * going to need to be able to save more than one EVP_PKEY. For now
- * we reuse the existing tmp.pkey
- */
- s->s3->group_id = curve_id;
- s->s3->tmp.pkey = key_share_key;
- sharessent++;
- OPENSSL_free(encodedPoint);
- }
- if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-
- /*
- * Add padding to workaround bugs in F5 terminators. See
- * https://tools.ietf.org/html/draft-agl-tls-padding-03 NB: because this
- * code works out the length of all existing extensions it MUST always
- * appear last.
- */
- if (s->options & SSL_OP_TLSEXT_PADDING) {
- unsigned char *padbytes;
- size_t hlen;
-
- if (!WPACKET_get_total_written(pkt, &hlen)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (hlen > 0xff && hlen < 0x200) {
- hlen = 0x200 - hlen;
- if (hlen >= 4)
- hlen -= 4;
- else
- hlen = 0;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_padding)
- || !WPACKET_sub_allocate_bytes_u16(pkt, hlen, &padbytes)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- memset(padbytes, 0, hlen);
- }
+ if ((min_tls > s->s3->tmp.max_ver) || (c->max_tls < s->s3->tmp.min_ver))
+ return 1;
}
+ if (SSL_IS_DTLS(s) && (DTLS_VERSION_GT(c->min_dtls, s->s3->tmp.max_ver)
+ || DTLS_VERSION_LT(c->max_dtls, s->s3->tmp.min_ver)))
+ return 1;
- done:
- return 1;
-}
-
-int ssl_prepare_clienthello_tlsext(SSL *s)
-{
- s->s3->alpn_sent = 0;
- return 1;
+ return !ssl_security(s, op, c->strength_bits, 0, (void *)c);
}
-/* Initialise digests to default values */
-void ssl_set_default_md(SSL *s)
+int tls_use_ticket(SSL *s)
{
- const EVP_MD **pmd = s->s3->tmp.md;
-#ifndef OPENSSL_NO_DSA
- pmd[SSL_PKEY_DSA_SIGN] = ssl_md(SSL_MD_SHA1_IDX);
-#endif
-#ifndef OPENSSL_NO_RSA
- if (SSL_USE_SIGALGS(s))
- pmd[SSL_PKEY_RSA_SIGN] = ssl_md(SSL_MD_SHA1_IDX);
- else
- pmd[SSL_PKEY_RSA_SIGN] = ssl_md(SSL_MD_MD5_SHA1_IDX);
- pmd[SSL_PKEY_RSA_ENC] = pmd[SSL_PKEY_RSA_SIGN];
-#endif
-#ifndef OPENSSL_NO_EC
- pmd[SSL_PKEY_ECC] = ssl_md(SSL_MD_SHA1_IDX);
-#endif
-#ifndef OPENSSL_NO_GOST
- pmd[SSL_PKEY_GOST01] = ssl_md(SSL_MD_GOST94_IDX);
- pmd[SSL_PKEY_GOST12_256] = ssl_md(SSL_MD_GOST12_256_IDX);
- pmd[SSL_PKEY_GOST12_512] = ssl_md(SSL_MD_GOST12_512_IDX);
-#endif
+ if ((s->options & SSL_OP_NO_TICKET))
+ return 0;
+ return ssl_security(s, SSL_SECOP_TICKET, 0, 0, NULL);
}
int tls1_set_server_sigalgs(SSL *s)
OPENSSL_free(s->cert->shared_sigalgs);
s->cert->shared_sigalgs = NULL;
s->cert->shared_sigalgslen = 0;
- /* Clear certificate digests and validity flags */
- for (i = 0; i < SSL_PKEY_NUM; i++) {
- s->s3->tmp.md[i] = NULL;
+ /* Clear certificate validity flags */
+ for (i = 0; i < SSL_PKEY_NUM; i++)
s->s3->tmp.valid_flags[i] = 0;
- }
+ /*
+ * If peer sent no signature algorithms check to see if we support
+ * the default algorithm for each certificate type
+ */
+ if (s->s3->tmp.peer_sigalgs == NULL) {
+ const uint16_t *sent_sigs;
+ size_t sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
- /* If sigalgs received process it. */
- if (s->s3->tmp.peer_sigalgs) {
- if (!tls1_process_sigalgs(s)) {
- SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, ERR_R_MALLOC_FAILURE);
- al = SSL_AD_INTERNAL_ERROR;
- goto err;
- }
- /* Fatal error is no shared signature algorithms */
- if (!s->cert->shared_sigalgs) {
- SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS,
- SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS);
- al = SSL_AD_ILLEGAL_PARAMETER;
- goto err;
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ const SIGALG_LOOKUP *lu = tls1_get_legacy_sigalg(s, i);
+ size_t j;
+
+ if (lu == NULL)
+ continue;
+ /* Check default matches a type we sent */
+ for (j = 0; j < sent_sigslen; j++) {
+ if (lu->sigalg == sent_sigs[j]) {
+ s->s3->tmp.valid_flags[i] = CERT_PKEY_SIGN;
+ break;
+ }
+ }
}
- } else {
- ssl_set_default_md(s);
+ return 1;
}
- return 1;
+
+ if (!tls1_process_sigalgs(s)) {
+ SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, ERR_R_MALLOC_FAILURE);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+ if (s->cert->shared_sigalgs != NULL)
+ return 1;
+ /* Fatal error is no shared signature algorithms */
+ SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS);
+ al = SSL_AD_ILLEGAL_PARAMETER;
err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
return 0;
}
-/*
- * Given a list of extensions that we collected earlier, find one of a given
- * type and return it.
- *
- * |exts| is the set of extensions previously collected.
- * |numexts| is the number of extensions that we have.
- * |type| the type of the extension that we are looking for.
- *
- * Returns a pointer to the found RAW_EXTENSION data, or NULL if not found.
- */
-RAW_EXTENSION *tls_get_extension_by_type(RAW_EXTENSION *exts, size_t numexts,
- unsigned int type)
-{
- size_t loop;
-
- for (loop = 0; loop < numexts; loop++) {
- if (exts[loop].type == type)
- return &exts[loop];
- }
-
- return NULL;
-}
-
/*-
* Gets the ticket information supplied by the client if any.
*
*
* If s->tls_session_secret_cb is set then we are expecting a pre-shared key
* ciphersuite, in which case we have no use for session tickets and one will
- * never be decrypted, nor will s->tlsext_ticket_expected be set to 1.
+ * never be decrypted, nor will s->ext.ticket_expected be set to 1.
*
* Returns:
* -1: fatal error, either from parsing or decrypting the ticket.
* 3: a ticket was successfully decrypted and *ret was set.
*
* Side effects:
- * Sets s->tlsext_ticket_expected to 1 if the server will have to issue
+ * Sets s->ext.ticket_expected to 1 if the server will have to issue
* a new session ticket to the client because the client indicated support
* (and s->tls_session_secret_cb is NULL) but the client either doesn't have
* a session ticket or we couldn't use the one it gave us, or if
- * s->ctx->tlsext_ticket_key_cb asked to renew the client's ticket.
- * Otherwise, s->tlsext_ticket_expected is set to 0.
+ * s->ctx->ext.ticket_key_cb asked to renew the client's ticket.
+ * Otherwise, s->ext.ticket_expected is set to 0.
*/
-int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello,
- SSL_SESSION **ret)
+TICKET_RETURN tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello,
+ SSL_SESSION **ret)
{
int retv;
- const unsigned char *etick;
size_t size;
RAW_EXTENSION *ticketext;
*ret = NULL;
- s->tlsext_ticket_expected = 0;
+ s->ext.ticket_expected = 0;
/*
* If tickets disabled or not supported by the protocol version
* resumption.
*/
if (s->version <= SSL3_VERSION || !tls_use_ticket(s))
- return 0;
+ return TICKET_NONE;
- ticketext = tls_get_extension_by_type(hello->pre_proc_exts,
- hello->num_extensions,
- TLSEXT_TYPE_session_ticket);
- if (ticketext == NULL)
- return 0;
-
- ticketext->parsed = 1;
+ ticketext = &hello->pre_proc_exts[TLSEXT_IDX_session_ticket];
+ if (!ticketext->present)
+ return TICKET_NONE;
size = PACKET_remaining(&ticketext->data);
if (size == 0) {
* The client will accept a ticket but doesn't currently have
* one.
*/
- s->tlsext_ticket_expected = 1;
- return 1;
+ s->ext.ticket_expected = 1;
+ return TICKET_EMPTY;
}
- if (s->tls_session_secret_cb) {
+ if (s->ext.session_secret_cb) {
/*
* Indicate that the ticket couldn't be decrypted rather than
* generating the session from ticket now, trigger
* abbreviated handshake based on external mechanism to
* calculate the master secret later.
*/
- return 2;
- }
- if (!PACKET_get_bytes(&ticketext->data, &etick, size)) {
- /* Shouldn't ever happen */
- return -1;
+ return TICKET_NO_DECRYPT;
}
- retv = tls_decrypt_ticket(s, etick, size, hello->session_id,
- hello->session_id_len, ret);
+
+ retv = tls_decrypt_ticket(s, PACKET_data(&ticketext->data), size,
+ hello->session_id, hello->session_id_len, ret);
switch (retv) {
- case 2: /* ticket couldn't be decrypted */
- s->tlsext_ticket_expected = 1;
- return 2;
+ case TICKET_NO_DECRYPT:
+ s->ext.ticket_expected = 1;
+ return TICKET_NO_DECRYPT;
- case 3: /* ticket was decrypted */
- return 3;
+ case TICKET_SUCCESS:
+ return TICKET_SUCCESS;
- case 4: /* ticket decrypted but need to renew */
- s->tlsext_ticket_expected = 1;
- return 3;
+ case TICKET_SUCCESS_RENEW:
+ s->ext.ticket_expected = 1;
+ return TICKET_SUCCESS;
- default: /* fatal error */
- return -1;
+ default:
+ return TICKET_FATAL_ERR_OTHER;
}
}
* sesslen: the length of the session ID.
* psess: (output) on return, if a ticket was decrypted, then this is set to
* point to the resulting session.
- *
- * Returns:
- * -2: fatal error, malloc failure.
- * -1: fatal error, either from parsing or decrypting the ticket.
- * 2: the ticket couldn't be decrypted.
- * 3: a ticket was successfully decrypted and *psess was set.
- * 4: same as 3, but the ticket needs to be renewed.
*/
-static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
- size_t eticklen, const unsigned char *sess_id,
- size_t sesslen, SSL_SESSION **psess)
+TICKET_RETURN tls_decrypt_ticket(SSL *s, const unsigned char *etick,
+ size_t eticklen, const unsigned char *sess_id,
+ size_t sesslen, SSL_SESSION **psess)
{
SSL_SESSION *sess;
unsigned char *sdec;
const unsigned char *p;
- int slen, renew_ticket = 0, ret = -1, declen;
+ int slen, renew_ticket = 0, declen;
+ TICKET_RETURN ret = TICKET_FATAL_ERR_OTHER;
size_t mlen;
unsigned char tick_hmac[EVP_MAX_MD_SIZE];
HMAC_CTX *hctx = NULL;
EVP_CIPHER_CTX *ctx;
- SSL_CTX *tctx = s->initial_ctx;
+ SSL_CTX *tctx = s->session_ctx;
/* Initialize session ticket encryption and HMAC contexts */
hctx = HMAC_CTX_new();
if (hctx == NULL)
- return -2;
+ return TICKET_FATAL_ERR_MALLOC;
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL) {
- ret = -2;
+ ret = TICKET_FATAL_ERR_MALLOC;
goto err;
}
- if (tctx->tlsext_ticket_key_cb) {
+ if (tctx->ext.ticket_key_cb) {
unsigned char *nctick = (unsigned char *)etick;
- int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16,
+ int rv = tctx->ext.ticket_key_cb(s, nctick, nctick + 16,
ctx, hctx, 0);
if (rv < 0)
goto err;
if (rv == 0) {
- ret = 2;
+ ret = TICKET_NO_DECRYPT;
goto err;
}
if (rv == 2)
renew_ticket = 1;
} else {
/* Check key name matches */
- if (memcmp(etick, tctx->tlsext_tick_key_name,
- sizeof(tctx->tlsext_tick_key_name)) != 0) {
- ret = 2;
+ if (memcmp(etick, tctx->ext.tick_key_name,
+ sizeof(tctx->ext.tick_key_name)) != 0) {
+ ret = TICKET_NO_DECRYPT;
goto err;
}
- if (HMAC_Init_ex(hctx, tctx->tlsext_tick_hmac_key,
- sizeof(tctx->tlsext_tick_hmac_key),
+ if (HMAC_Init_ex(hctx, tctx->ext.tick_hmac_key,
+ sizeof(tctx->ext.tick_hmac_key),
EVP_sha256(), NULL) <= 0
|| EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL,
- tctx->tlsext_tick_aes_key,
- etick + sizeof(tctx->tlsext_tick_key_name)) <=
- 0) {
+ tctx->ext.tick_aes_key,
+ etick
+ + sizeof(tctx->ext.tick_key_name)) <= 0) {
goto err;
}
}
/* Sanity check ticket length: must exceed keyname + IV + HMAC */
if (eticklen <=
TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx) + mlen) {
- ret = 2;
+ ret = TICKET_NO_DECRYPT;
goto err;
}
eticklen -= mlen;
HMAC_CTX_free(hctx);
if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) {
EVP_CIPHER_CTX_free(ctx);
- return 2;
+ return TICKET_NO_DECRYPT;
}
/* Attempt to decrypt session data */
/* Move p after IV to start of encrypted ticket, update length */
- p = etick + 16 + EVP_CIPHER_CTX_iv_length(ctx);
- eticklen -= 16 + EVP_CIPHER_CTX_iv_length(ctx);
+ p = etick + TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx);
+ eticklen -= TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx);
sdec = OPENSSL_malloc(eticklen);
if (sdec == NULL || EVP_DecryptUpdate(ctx, sdec, &slen, p,
(int)eticklen) <= 0) {
EVP_CIPHER_CTX_free(ctx);
OPENSSL_free(sdec);
- return -1;
+ return TICKET_FATAL_ERR_OTHER;
}
if (EVP_DecryptFinal(ctx, sdec + slen, &declen) <= 0) {
EVP_CIPHER_CTX_free(ctx);
OPENSSL_free(sdec);
- return 2;
+ return TICKET_NO_DECRYPT;
}
slen += declen;
EVP_CIPHER_CTX_free(ctx);
p = sdec;
sess = d2i_SSL_SESSION(NULL, &p, slen);
+ slen -= p - sdec;
OPENSSL_free(sdec);
if (sess) {
+ /* Some additional consistency checks */
+ if (slen != 0 || sess->session_id_length != 0) {
+ SSL_SESSION_free(sess);
+ return TICKET_NO_DECRYPT;
+ }
/*
* The session ID, if non-empty, is used by some clients to detect
* that the ticket has been accepted. So we copy it to the session
sess->session_id_length = sesslen;
*psess = sess;
if (renew_ticket)
- return 4;
+ return TICKET_SUCCESS_RENEW;
else
- return 3;
+ return TICKET_SUCCESS;
}
ERR_clear_error();
/*
* For session parse failure, indicate that we need to send a new ticket.
*/
- return 2;
+ return TICKET_NO_DECRYPT;
err:
EVP_CIPHER_CTX_free(ctx);
HMAC_CTX_free(hctx);
return ret;
}
-/* Tables to translate from NIDs to TLS v1.2 ids */
-
-typedef struct {
- int nid;
- int id;
-} tls12_lookup;
-
-static const tls12_lookup tls12_md[] = {
- {NID_md5, TLSEXT_hash_md5},
- {NID_sha1, TLSEXT_hash_sha1},
- {NID_sha224, TLSEXT_hash_sha224},
- {NID_sha256, TLSEXT_hash_sha256},
- {NID_sha384, TLSEXT_hash_sha384},
- {NID_sha512, TLSEXT_hash_sha512},
- {NID_id_GostR3411_94, TLSEXT_hash_gostr3411},
- {NID_id_GostR3411_2012_256, TLSEXT_hash_gostr34112012_256},
- {NID_id_GostR3411_2012_512, TLSEXT_hash_gostr34112012_512},
-};
-
-static const tls12_lookup tls12_sig[] = {
- {EVP_PKEY_RSA, TLSEXT_signature_rsa},
- {EVP_PKEY_DSA, TLSEXT_signature_dsa},
- {EVP_PKEY_EC, TLSEXT_signature_ecdsa},
- {NID_id_GostR3410_2001, TLSEXT_signature_gostr34102001},
- {NID_id_GostR3410_2012_256, TLSEXT_signature_gostr34102012_256},
- {NID_id_GostR3410_2012_512, TLSEXT_signature_gostr34102012_512}
-};
-
-static int tls12_find_id(int nid, const tls12_lookup *table, size_t tlen)
-{
- size_t i;
- for (i = 0; i < tlen; i++) {
- if (table[i].nid == nid)
- return table[i].id;
- }
- return -1;
-}
-
-static int tls12_find_nid(int id, const tls12_lookup *table, size_t tlen)
-{
- size_t i;
- for (i = 0; i < tlen; i++) {
- if ((table[i].id) == id)
- return table[i].nid;
- }
- return NID_undef;
-}
-
-int tls12_get_sigandhash(WPACKET *pkt, const EVP_PKEY *pk, const EVP_MD *md)
-{
- int sig_id, md_id;
-
- if (md == NULL)
- return 0;
- md_id = tls12_find_id(EVP_MD_type(md), tls12_md, OSSL_NELEM(tls12_md));
- if (md_id == -1)
- return 0;
- sig_id = tls12_get_sigid(pk);
- if (sig_id == -1)
- return 0;
- if (!WPACKET_put_bytes_u8(pkt, md_id) || !WPACKET_put_bytes_u8(pkt, sig_id))
- return 0;
-
- return 1;
-}
-
-int tls12_get_sigid(const EVP_PKEY *pk)
-{
- return tls12_find_id(EVP_PKEY_id(pk), tls12_sig, OSSL_NELEM(tls12_sig));
-}
-
-typedef struct {
- int nid;
- int secbits;
- int md_idx;
- unsigned char tlsext_hash;
-} tls12_hash_info;
-
-static const tls12_hash_info tls12_md_info[] = {
- {NID_md5, 64, SSL_MD_MD5_IDX, TLSEXT_hash_md5},
- {NID_sha1, 80, SSL_MD_SHA1_IDX, TLSEXT_hash_sha1},
- {NID_sha224, 112, SSL_MD_SHA224_IDX, TLSEXT_hash_sha224},
- {NID_sha256, 128, SSL_MD_SHA256_IDX, TLSEXT_hash_sha256},
- {NID_sha384, 192, SSL_MD_SHA384_IDX, TLSEXT_hash_sha384},
- {NID_sha512, 256, SSL_MD_SHA512_IDX, TLSEXT_hash_sha512},
- {NID_id_GostR3411_94, 128, SSL_MD_GOST94_IDX, TLSEXT_hash_gostr3411},
- {NID_id_GostR3411_2012_256, 128, SSL_MD_GOST12_256_IDX,
- TLSEXT_hash_gostr34112012_256},
- {NID_id_GostR3411_2012_512, 256, SSL_MD_GOST12_512_IDX,
- TLSEXT_hash_gostr34112012_512},
-};
-
-static const tls12_hash_info *tls12_get_hash_info(unsigned char hash_alg)
-{
- unsigned int i;
- if (hash_alg == 0)
- return NULL;
-
- for (i = 0; i < OSSL_NELEM(tls12_md_info); i++) {
- if (tls12_md_info[i].tlsext_hash == hash_alg)
- return tls12_md_info + i;
- }
-
- return NULL;
-}
-
-const EVP_MD *tls12_get_hash(unsigned char hash_alg)
-{
- const tls12_hash_info *inf;
- if (hash_alg == TLSEXT_hash_md5 && FIPS_mode())
- return NULL;
- inf = tls12_get_hash_info(hash_alg);
- if (!inf)
- return NULL;
- return ssl_md(inf->md_idx);
-}
-
-static int tls12_get_pkey_idx(unsigned char sig_alg)
+static int tls12_get_pkey_idx(int sig_nid)
{
- switch (sig_alg) {
+ switch (sig_nid) {
#ifndef OPENSSL_NO_RSA
- case TLSEXT_signature_rsa:
- return SSL_PKEY_RSA_SIGN;
+ case EVP_PKEY_RSA:
+ return SSL_PKEY_RSA;
+ /*
+ * For now return RSA key for PSS. When we support PSS only keys
+ * this will need to be updated.
+ */
+ case EVP_PKEY_RSA_PSS:
+ return SSL_PKEY_RSA;
#endif
#ifndef OPENSSL_NO_DSA
- case TLSEXT_signature_dsa:
+ case EVP_PKEY_DSA:
return SSL_PKEY_DSA_SIGN;
#endif
#ifndef OPENSSL_NO_EC
- case TLSEXT_signature_ecdsa:
+ case EVP_PKEY_EC:
return SSL_PKEY_ECC;
#endif
#ifndef OPENSSL_NO_GOST
- case TLSEXT_signature_gostr34102001:
+ case NID_id_GostR3410_2001:
return SSL_PKEY_GOST01;
- case TLSEXT_signature_gostr34102012_256:
+ case NID_id_GostR3410_2012_256:
return SSL_PKEY_GOST12_256;
- case TLSEXT_signature_gostr34102012_512:
+ case NID_id_GostR3410_2012_512:
return SSL_PKEY_GOST12_512;
#endif
}
return -1;
}
-/* Convert TLS 1.2 signature algorithm extension values into NIDs */
-static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid,
- int *psignhash_nid, const unsigned char *data)
-{
- int sign_nid = NID_undef, hash_nid = NID_undef;
- if (!phash_nid && !psign_nid && !psignhash_nid)
- return;
- if (phash_nid || psignhash_nid) {
- hash_nid = tls12_find_nid(data[0], tls12_md, OSSL_NELEM(tls12_md));
- if (phash_nid)
- *phash_nid = hash_nid;
- }
- if (psign_nid || psignhash_nid) {
- sign_nid = tls12_find_nid(data[1], tls12_sig, OSSL_NELEM(tls12_sig));
- if (psign_nid)
- *psign_nid = sign_nid;
- }
- if (psignhash_nid) {
- if (sign_nid == NID_undef || hash_nid == NID_undef
- || OBJ_find_sigid_by_algs(psignhash_nid, hash_nid, sign_nid) <= 0)
- *psignhash_nid = NID_undef;
- }
-}
-
/* Check to see if a signature algorithm is allowed */
-static int tls12_sigalg_allowed(SSL *s, int op, const unsigned char *ptmp)
+static int tls12_sigalg_allowed(SSL *s, int op, const SIGALG_LOOKUP *lu)
{
- /* See if we have an entry in the hash table and it is enabled */
- const tls12_hash_info *hinf = tls12_get_hash_info(ptmp[0]);
- if (hinf == NULL || ssl_md(hinf->md_idx) == NULL)
+ unsigned char sigalgstr[2];
+ int secbits;
+
+ /* See if sigalgs is recognised and if hash is enabled */
+ if (lu == NULL || ssl_md(lu->hash_idx) == NULL)
+ return 0;
+ /* DSA is not allowed in TLS 1.3 */
+ if (SSL_IS_TLS13(s) && lu->sig == EVP_PKEY_DSA)
return 0;
/* See if public key algorithm allowed */
- if (tls12_get_pkey_idx(ptmp[1]) == -1)
+ if (tls12_get_pkey_idx(lu->sig) == -1)
return 0;
+ /* Security bits: half digest bits */
+ secbits = EVP_MD_size(ssl_md(lu->hash_idx)) * 4;
/* Finally see if security callback allows it */
- return ssl_security(s, op, hinf->secbits, hinf->nid, (void *)ptmp);
+ sigalgstr[0] = (lu->sigalg >> 8) & 0xff;
+ sigalgstr[1] = lu->sigalg & 0xff;
+ return ssl_security(s, op, secbits, lu->hash, (void *)sigalgstr);
}
/*
void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op)
{
- const unsigned char *sigalgs;
+ const uint16_t *sigalgs;
size_t i, sigalgslen;
int have_rsa = 0, have_dsa = 0, have_ecdsa = 0;
/*
* RSA, DSA, ECDSA. Do this for all versions not just TLS 1.2. To keep
* down calls to security callback only check if we have to.
*/
- sigalgslen = tls12_get_psigalgs(s, &sigalgs);
- for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) {
- switch (sigalgs[1]) {
+ sigalgslen = tls12_get_psigalgs(s, 1, &sigalgs);
+ for (i = 0; i < sigalgslen; i ++, sigalgs++) {
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*sigalgs);
+
+ if (lu == NULL)
+ continue;
+ switch (lu->sig) {
#ifndef OPENSSL_NO_RSA
- case TLSEXT_signature_rsa:
- if (!have_rsa && tls12_sigalg_allowed(s, op, sigalgs))
+ /* Any RSA-PSS signature algorithms also mean we allow RSA */
+ case EVP_PKEY_RSA_PSS:
+ case EVP_PKEY_RSA:
+ if (!have_rsa && tls12_sigalg_allowed(s, op, lu))
have_rsa = 1;
break;
#endif
#ifndef OPENSSL_NO_DSA
- case TLSEXT_signature_dsa:
- if (!have_dsa && tls12_sigalg_allowed(s, op, sigalgs))
+ case EVP_PKEY_DSA:
+ if (!have_dsa && tls12_sigalg_allowed(s, op, lu))
have_dsa = 1;
break;
#endif
#ifndef OPENSSL_NO_EC
- case TLSEXT_signature_ecdsa:
- if (!have_ecdsa && tls12_sigalg_allowed(s, op, sigalgs))
+ case EVP_PKEY_EC:
+ if (!have_ecdsa && tls12_sigalg_allowed(s, op, lu))
have_ecdsa = 1;
break;
#endif
}
int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
- const unsigned char *psig, size_t psiglen)
+ const uint16_t *psig, size_t psiglen)
{
size_t i;
+ int rv = 0;
- for (i = 0; i < psiglen; i += 2, psig += 2) {
- if (tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, psig)) {
- if (!WPACKET_put_bytes_u8(pkt, psig[0])
- || !WPACKET_put_bytes_u8(pkt, psig[1]))
- return 0;
- }
+ for (i = 0; i < psiglen; i++, psig++) {
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*psig);
+
+ if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu))
+ continue;
+ if (!WPACKET_put_bytes_u16(pkt, *psig))
+ return 0;
+ /*
+ * If TLS 1.3 must have at least one valid TLS 1.3 message
+ * signing algorithm: i.e. neither RSA nor SHA1
+ */
+ if (rv == 0 && (!SSL_IS_TLS13(s)
+ || (lu->sig != EVP_PKEY_RSA && lu->hash != NID_sha1)))
+ rv = 1;
}
- return 1;
+ if (rv == 0)
+ SSLerr(SSL_F_TLS12_COPY_SIGALGS, SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
+ return rv;
}
/* Given preference and allowed sigalgs set shared sigalgs */
-static size_t tls12_shared_sigalgs(SSL *s, TLS_SIGALGS *shsig,
- const unsigned char *pref, size_t preflen,
- const unsigned char *allow, size_t allowlen)
+static size_t tls12_shared_sigalgs(SSL *s, const SIGALG_LOOKUP **shsig,
+ const uint16_t *pref, size_t preflen,
+ const uint16_t *allow, size_t allowlen)
{
- const unsigned char *ptmp, *atmp;
+ const uint16_t *ptmp, *atmp;
size_t i, j, nmatch = 0;
- for (i = 0, ptmp = pref; i < preflen; i += 2, ptmp += 2) {
+ for (i = 0, ptmp = pref; i < preflen; i++, ptmp++) {
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*ptmp);
+
/* Skip disabled hashes or signature algorithms */
- if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, ptmp))
+ if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, lu))
continue;
- for (j = 0, atmp = allow; j < allowlen; j += 2, atmp += 2) {
- if (ptmp[0] == atmp[0] && ptmp[1] == atmp[1]) {
+ for (j = 0, atmp = allow; j < allowlen; j++, atmp++) {
+ if (*ptmp == *atmp) {
nmatch++;
- if (shsig) {
- shsig->rhash = ptmp[0];
- shsig->rsign = ptmp[1];
- tls1_lookup_sigalg(&shsig->hash_nid,
- &shsig->sign_nid,
- &shsig->signandhash_nid, ptmp);
- shsig++;
- }
+ if (shsig)
+ *shsig++ = lu;
break;
}
}
/* Set shared signature algorithms for SSL structures */
static int tls1_set_shared_sigalgs(SSL *s)
{
- const unsigned char *pref, *allow, *conf;
+ const uint16_t *pref, *allow, *conf;
size_t preflen, allowlen, conflen;
size_t nmatch;
- TLS_SIGALGS *salgs = NULL;
+ const SIGALG_LOOKUP **salgs = NULL;
CERT *c = s->cert;
unsigned int is_suiteb = tls1_suiteb(s);
conf = c->conf_sigalgs;
conflen = c->conf_sigalgslen;
} else
- conflen = tls12_get_psigalgs(s, &conf);
+ conflen = tls12_get_psigalgs(s, 0, &conf);
if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || is_suiteb) {
pref = conf;
preflen = conflen;
}
nmatch = tls12_shared_sigalgs(s, NULL, pref, preflen, allow, allowlen);
if (nmatch) {
- salgs = OPENSSL_malloc(nmatch * sizeof(TLS_SIGALGS));
+ salgs = OPENSSL_malloc(nmatch * sizeof(*salgs));
if (salgs == NULL)
return 0;
nmatch = tls12_shared_sigalgs(s, salgs, pref, preflen, allow, allowlen);
/* Set preferred digest for each key type */
-int tls1_save_sigalgs(SSL *s, const unsigned char *data, size_t dsize)
+int tls1_save_sigalgs(SSL *s, PACKET *pkt)
{
CERT *c = s->cert;
+ unsigned int stmp;
+ size_t size, i;
+
/* Extension ignored for inappropriate versions */
if (!SSL_USE_SIGALGS(s))
return 1;
if (!c)
return 0;
+ size = PACKET_remaining(pkt);
+
+ /* Invalid data length */
+ if (size == 0 || (size & 1) != 0)
+ return 0;
+
+ size >>= 1;
+
OPENSSL_free(s->s3->tmp.peer_sigalgs);
- s->s3->tmp.peer_sigalgs = OPENSSL_malloc(dsize);
+ s->s3->tmp.peer_sigalgs = OPENSSL_malloc(size
+ * sizeof(*s->s3->tmp.peer_sigalgs));
if (s->s3->tmp.peer_sigalgs == NULL)
return 0;
- s->s3->tmp.peer_sigalgslen = dsize;
- memcpy(s->s3->tmp.peer_sigalgs, data, dsize);
+ s->s3->tmp.peer_sigalgslen = size;
+ for (i = 0; i < size && PACKET_get_net_2(pkt, &stmp); i++)
+ s->s3->tmp.peer_sigalgs[i] = stmp;
+
+ if (i != size)
+ return 0;
+
return 1;
}
int tls1_process_sigalgs(SSL *s)
{
- int idx;
size_t i;
- const EVP_MD *md;
- const EVP_MD **pmd = s->s3->tmp.md;
uint32_t *pvalid = s->s3->tmp.valid_flags;
CERT *c = s->cert;
- TLS_SIGALGS *sigptr;
+
if (!tls1_set_shared_sigalgs(s))
return 0;
- for (i = 0, sigptr = c->shared_sigalgs;
- i < c->shared_sigalgslen; i++, sigptr++) {
- idx = tls12_get_pkey_idx(sigptr->rsign);
- if (idx > 0 && pmd[idx] == NULL) {
- md = tls12_get_hash(sigptr->rhash);
- pmd[idx] = md;
- pvalid[idx] = CERT_PKEY_EXPLICIT_SIGN;
- if (idx == SSL_PKEY_RSA_SIGN) {
- pvalid[SSL_PKEY_RSA_ENC] = CERT_PKEY_EXPLICIT_SIGN;
- pmd[SSL_PKEY_RSA_ENC] = md;
- }
- }
+ for (i = 0; i < SSL_PKEY_NUM; i++)
+ pvalid[i] = 0;
- }
- /*
- * In strict mode leave unset digests as NULL to indicate we can't use
- * the certificate for signing.
- */
- if (!(s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) {
- /*
- * Set any remaining keys to default values. NOTE: if alg is not
- * supported it stays as NULL.
- */
-#ifndef OPENSSL_NO_DSA
- if (pmd[SSL_PKEY_DSA_SIGN] == NULL)
- pmd[SSL_PKEY_DSA_SIGN] = EVP_sha1();
-#endif
-#ifndef OPENSSL_NO_RSA
- if (pmd[SSL_PKEY_RSA_SIGN] == NULL) {
- pmd[SSL_PKEY_RSA_SIGN] = EVP_sha1();
- pmd[SSL_PKEY_RSA_ENC] = EVP_sha1();
- }
-#endif
-#ifndef OPENSSL_NO_EC
- if (pmd[SSL_PKEY_ECC] == NULL)
- pmd[SSL_PKEY_ECC] = EVP_sha1();
-#endif
-#ifndef OPENSSL_NO_GOST
- if (pmd[SSL_PKEY_GOST01] == NULL)
- pmd[SSL_PKEY_GOST01] = EVP_get_digestbynid(NID_id_GostR3411_94);
- if (pmd[SSL_PKEY_GOST12_256] == NULL)
- pmd[SSL_PKEY_GOST12_256] =
- EVP_get_digestbynid(NID_id_GostR3411_2012_256);
- if (pmd[SSL_PKEY_GOST12_512] == NULL)
- pmd[SSL_PKEY_GOST12_512] =
- EVP_get_digestbynid(NID_id_GostR3411_2012_512);
-#endif
+ for (i = 0; i < c->shared_sigalgslen; i++) {
+ const SIGALG_LOOKUP *sigptr = c->shared_sigalgs[i];
+ int idx = sigptr->sig_idx;
+
+ /* Ignore PKCS1 based sig algs in TLSv1.3 */
+ if (SSL_IS_TLS13(s) && sigptr->sig == EVP_PKEY_RSA)
+ continue;
+ /* If not disabled indicate we can explicitly sign */
+ if (pvalid[idx] == 0 && tls12_get_pkey_idx(sigptr->sig) != -1)
+ pvalid[sigptr->sig_idx] = CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN;
}
return 1;
}
int *psign, int *phash, int *psignhash,
unsigned char *rsig, unsigned char *rhash)
{
- const unsigned char *psig = s->s3->tmp.peer_sigalgs;
- size_t numsigalgs = s->s3->tmp.peer_sigalgslen / 2;
+ uint16_t *psig = s->s3->tmp.peer_sigalgs;
+ size_t numsigalgs = s->s3->tmp.peer_sigalgslen;
if (psig == NULL || numsigalgs > INT_MAX)
return 0;
if (idx >= 0) {
- idx <<= 1;
- if (idx >= (int)s->s3->tmp.peer_sigalgslen)
+ const SIGALG_LOOKUP *lu;
+
+ if (idx >= (int)numsigalgs)
return 0;
psig += idx;
- if (rhash)
- *rhash = psig[0];
- if (rsig)
- *rsig = psig[1];
- tls1_lookup_sigalg(phash, psign, psignhash, psig);
+ if (rhash != NULL)
+ *rhash = (unsigned char)((*psig >> 8) & 0xff);
+ if (rsig != NULL)
+ *rsig = (unsigned char)(*psig & 0xff);
+ lu = tls1_lookup_sigalg(*psig);
+ if (psign != NULL)
+ *psign = lu != NULL ? lu->sig : NID_undef;
+ if (phash != NULL)
+ *phash = lu != NULL ? lu->hash : NID_undef;
+ if (psignhash != NULL)
+ *psignhash = lu != NULL ? lu->sigandhash : NID_undef;
}
return (int)numsigalgs;
}
int *psign, int *phash, int *psignhash,
unsigned char *rsig, unsigned char *rhash)
{
- TLS_SIGALGS *shsigalgs = s->cert->shared_sigalgs;
- if (!shsigalgs || idx >= (int)s->cert->shared_sigalgslen
- || s->cert->shared_sigalgslen > INT_MAX)
+ const SIGALG_LOOKUP *shsigalgs;
+ if (s->cert->shared_sigalgs == NULL
+ || idx < 0
+ || idx >= (int)s->cert->shared_sigalgslen
+ || s->cert->shared_sigalgslen > INT_MAX)
return 0;
- shsigalgs += idx;
- if (phash)
- *phash = shsigalgs->hash_nid;
- if (psign)
- *psign = shsigalgs->sign_nid;
- if (psignhash)
- *psignhash = shsigalgs->signandhash_nid;
- if (rsig)
- *rsig = shsigalgs->rsign;
- if (rhash)
- *rhash = shsigalgs->rhash;
+ shsigalgs = s->cert->shared_sigalgs[idx];
+ if (phash != NULL)
+ *phash = shsigalgs->hash;
+ if (psign != NULL)
+ *psign = shsigalgs->sig;
+ if (psignhash != NULL)
+ *psignhash = shsigalgs->sigandhash;
+ if (rsig != NULL)
+ *rsig = (unsigned char)(shsigalgs->sigalg & 0xff);
+ if (rhash != NULL)
+ *rhash = (unsigned char)((shsigalgs->sigalg >> 8) & 0xff);
return (int)s->cert->shared_sigalgslen;
}
-#define MAX_SIGALGLEN (TLSEXT_hash_num * TLSEXT_signature_num * 2)
+/* Maximum possible number of unique entries in sigalgs array */
+#define TLS_MAX_SIGALGCNT (OSSL_NELEM(sigalg_lookup_tbl) * 2)
typedef struct {
size_t sigalgcnt;
- int sigalgs[MAX_SIGALGLEN];
+ int sigalgs[TLS_MAX_SIGALGCNT];
} sig_cb_st;
static void get_sigorhash(int *psig, int *phash, const char *str)
{
if (strcmp(str, "RSA") == 0) {
*psig = EVP_PKEY_RSA;
+ } else if (strcmp(str, "RSA-PSS") == 0 || strcmp(str, "PSS") == 0) {
+ *psig = EVP_PKEY_RSA_PSS;
} else if (strcmp(str, "DSA") == 0) {
*psig = EVP_PKEY_DSA;
} else if (strcmp(str, "ECDSA") == 0) {
*phash = OBJ_ln2nid(str);
}
}
+/* Maximum length of a signature algorithm string component */
+#define TLS_MAX_SIGSTRING_LEN 40
static int sig_cb(const char *elem, int len, void *arg)
{
sig_cb_st *sarg = arg;
size_t i;
- char etmp[20], *p;
+ char etmp[TLS_MAX_SIGSTRING_LEN], *p;
int sig_alg = NID_undef, hash_alg = NID_undef;
if (elem == NULL)
return 0;
- if (sarg->sigalgcnt == MAX_SIGALGLEN)
+ if (sarg->sigalgcnt == TLS_MAX_SIGALGCNT)
return 0;
if (len > (int)(sizeof(etmp) - 1))
return 0;
memcpy(etmp, elem, len);
etmp[len] = 0;
p = strchr(etmp, '+');
- if (!p)
- return 0;
- *p = 0;
- p++;
- if (!*p)
- return 0;
-
- get_sigorhash(&sig_alg, &hash_alg, etmp);
- get_sigorhash(&sig_alg, &hash_alg, p);
+ /* See if we have a match for TLS 1.3 names */
+ if (p == NULL) {
+ const SIGALG_LOOKUP *s;
+
+ for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
+ i++, s++) {
+ if (s->name != NULL && strcmp(etmp, s->name) == 0) {
+ sig_alg = s->sig;
+ hash_alg = s->hash;
+ break;
+ }
+ }
+ } else {
+ *p = 0;
+ p++;
+ if (*p == 0)
+ return 0;
+ get_sigorhash(&sig_alg, &hash_alg, etmp);
+ get_sigorhash(&sig_alg, &hash_alg, p);
+ }
if (sig_alg == NID_undef || hash_alg == NID_undef)
return 0;
int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen, int client)
{
- unsigned char *sigalgs, *sptr;
- int rhash, rsign;
+ uint16_t *sigalgs, *sptr;
size_t i;
+
if (salglen & 1)
return 0;
- sigalgs = OPENSSL_malloc(salglen);
+ sigalgs = OPENSSL_malloc((salglen / 2) * sizeof(*sigalgs));
if (sigalgs == NULL)
return 0;
for (i = 0, sptr = sigalgs; i < salglen; i += 2) {
- rhash = tls12_find_id(*psig_nids++, tls12_md, OSSL_NELEM(tls12_md));
- rsign = tls12_find_id(*psig_nids++, tls12_sig, OSSL_NELEM(tls12_sig));
+ size_t j;
+ const SIGALG_LOOKUP *curr;
+ int md_id = *psig_nids++;
+ int sig_id = *psig_nids++;
+
+ for (j = 0, curr = sigalg_lookup_tbl; j < OSSL_NELEM(sigalg_lookup_tbl);
+ j++, curr++) {
+ if (curr->hash == md_id && curr->sig == sig_id) {
+ *sptr++ = curr->sigalg;
+ break;
+ }
+ }
- if (rhash == -1 || rsign == -1)
+ if (j == OSSL_NELEM(sigalg_lookup_tbl))
goto err;
- *sptr++ = rhash;
- *sptr++ = rsign;
}
if (client) {
OPENSSL_free(c->client_sigalgs);
c->client_sigalgs = sigalgs;
- c->client_sigalgslen = salglen;
+ c->client_sigalgslen = salglen / 2;
} else {
OPENSSL_free(c->conf_sigalgs);
c->conf_sigalgs = sigalgs;
- c->conf_sigalgslen = salglen;
+ c->conf_sigalgslen = salglen / 2;
}
return 1;
if (default_nid)
return sig_nid == default_nid ? 1 : 0;
for (i = 0; i < c->shared_sigalgslen; i++)
- if (sig_nid == c->shared_sigalgs[i].signandhash_nid)
+ if (sig_nid == c->shared_sigalgs[i]->sigandhash)
return 1;
return 0;
}
* attempting to use them.
*/
-/* Flags which need to be set for a certificate when stict mode not set */
+/* Flags which need to be set for a certificate when strict mode not set */
#define CERT_PKEY_VALID_FLAGS \
(CERT_PKEY_EE_SIGNATURE|CERT_PKEY_EE_PARAM)
*/
if (TLS1_get_version(s) >= TLS1_2_VERSION && strict_mode) {
int default_nid;
- unsigned char rsign = 0;
+ int rsign = 0;
if (s->s3->tmp.peer_sigalgs)
default_nid = 0;
/* If no sigalgs extension use defaults from RFC5246 */
else {
switch (idx) {
- case SSL_PKEY_RSA_ENC:
- case SSL_PKEY_RSA_SIGN:
- rsign = TLSEXT_signature_rsa;
+ case SSL_PKEY_RSA:
+ rsign = EVP_PKEY_RSA;
default_nid = NID_sha1WithRSAEncryption;
break;
case SSL_PKEY_DSA_SIGN:
- rsign = TLSEXT_signature_dsa;
+ rsign = EVP_PKEY_DSA;
default_nid = NID_dsaWithSHA1;
break;
case SSL_PKEY_ECC:
- rsign = TLSEXT_signature_ecdsa;
+ rsign = EVP_PKEY_EC;
default_nid = NID_ecdsa_with_SHA1;
break;
case SSL_PKEY_GOST01:
- rsign = TLSEXT_signature_gostr34102001;
+ rsign = NID_id_GostR3410_2001;
default_nid = NID_id_GostR3411_94_with_GostR3410_2001;
break;
case SSL_PKEY_GOST12_256:
- rsign = TLSEXT_signature_gostr34102012_256;
+ rsign = NID_id_GostR3410_2012_256;
default_nid = NID_id_tc26_signwithdigest_gost3410_2012_256;
break;
case SSL_PKEY_GOST12_512:
- rsign = TLSEXT_signature_gostr34102012_512;
+ rsign = NID_id_GostR3410_2012_512;
default_nid = NID_id_tc26_signwithdigest_gost3410_2012_512;
break;
*/
if (default_nid > 0 && c->conf_sigalgs) {
size_t j;
- const unsigned char *p = c->conf_sigalgs;
- for (j = 0; j < c->conf_sigalgslen; j += 2, p += 2) {
- if (p[0] == TLSEXT_hash_sha1 && p[1] == rsign)
+ const uint16_t *p = c->conf_sigalgs;
+ for (j = 0; j < c->conf_sigalgslen; j++, p++) {
+ const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*p);
+
+ if (lu != NULL && lu->hash == NID_sha1 && lu->sig == rsign)
break;
}
if (j == c->conf_sigalgslen) {
rv |= CERT_PKEY_EE_SIGNATURE | CERT_PKEY_CA_SIGNATURE;
skip_sigs:
/* Check cert parameters are consistent */
- if (tls1_check_cert_param(s, x, check_flags ? 1 : 2))
+ if (tls1_check_cert_param(s, x, 1))
rv |= CERT_PKEY_EE_PARAM;
else if (!check_flags)
goto end;
break;
}
if (check_type) {
- const unsigned char *ctypes;
- int ctypelen;
- if (c->ctypes) {
- ctypes = c->ctypes;
- ctypelen = (int)c->ctype_num;
- } else {
- ctypes = (unsigned char *)s->s3->tmp.ctype;
- ctypelen = s->s3->tmp.ctype_num;
- }
- for (i = 0; i < ctypelen; i++) {
- if (ctypes[i] == check_type) {
+ const uint8_t *ctypes = s->s3->tmp.ctype;
+ size_t j;
+
+ for (j = 0; j < s->s3->tmp.ctype_len; j++, ctypes++) {
+ if (*ctypes == check_type) {
rv |= CERT_PKEY_CERT_TYPE;
break;
}
}
if (!(rv & CERT_PKEY_CERT_TYPE) && !check_flags)
goto end;
- } else
+ } else {
rv |= CERT_PKEY_CERT_TYPE;
+ }
- ca_dn = s->s3->tmp.ca_names;
+ ca_dn = s->s3->tmp.peer_ca_names;
if (!sk_X509_NAME_num(ca_dn))
rv |= CERT_PKEY_ISSUER_NAME;
end:
- if (TLS1_get_version(s) >= TLS1_2_VERSION) {
- if (*pvalid & CERT_PKEY_EXPLICIT_SIGN)
- rv |= CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN;
- else if (s->s3->tmp.md[idx] != NULL)
- rv |= CERT_PKEY_SIGN;
- } else
+ if (TLS1_get_version(s) >= TLS1_2_VERSION)
+ rv |= *pvalid & (CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN);
+ else
rv |= CERT_PKEY_SIGN | CERT_PKEY_EXPLICIT_SIGN;
/*
* chain is invalid.
*/
if (!check_flags) {
- if (rv & CERT_PKEY_VALID)
+ if (rv & CERT_PKEY_VALID) {
*pvalid = rv;
- else {
- /* Preserve explicit sign flag, clear rest */
- *pvalid &= CERT_PKEY_EXPLICIT_SIGN;
+ } else {
+ /* Preserve sign and explicit sign flag, clear rest */
+ *pvalid &= CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN;
return 0;
}
}
/* Set validity of certificates in an SSL structure */
void tls1_set_cert_validity(SSL *s)
{
- tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_ENC);
- tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_SIGN);
+ tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DSA_SIGN);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ECC);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST01);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_512);
}
-/* User level utiity function to check a chain is suitable */
+/* User level utility function to check a chain is suitable */
int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain)
{
return tls1_check_chain(s, x, pk, chain, -1);
else
dh_secbits = 80;
} else {
- CERT_PKEY *cpk = ssl_get_server_send_pkey(s);
- dh_secbits = EVP_PKEY_security_bits(cpk->privatekey);
+ if (s->s3->tmp.cert == NULL)
+ return NULL;
+ dh_secbits = EVP_PKEY_security_bits(s->s3->tmp.cert->privatekey);
}
if (dh_secbits >= 128) {
}
/*
- * Check security of a chain, if sk includes the end entity certificate then
- * x is NULL. If vfy is 1 then we are verifying a peer chain and not sending
+ * Check security of a chain, if |sk| includes the end entity certificate then
+ * |x| is NULL. If |vfy| is 1 then we are verifying a peer chain and not sending
* one to the peer. Return values: 1 if ok otherwise error code to use
*/
}
return 1;
}
+
+/*
+ * Choose an appropriate signature algorithm based on available certificates
+ * Sets chosen certificate and signature algorithm.
+ *
+ * For servers if we fail to find a required certificate it is a fatal error
+ * and an appropriate error code is set and the TLS alert set in *al.
+ *
+ * For clients al is set to NULL. If a certificate is not suitable it is not
+ * a fatal error: we will either try another certificate or not present one
+ * to the server. In this case no error is set.
+ */
+int tls_choose_sigalg(SSL *s, int *al)
+{
+ int idx = -1;
+ const SIGALG_LOOKUP *lu = NULL;
+
+ s->s3->tmp.cert = NULL;
+ s->s3->tmp.sigalg = NULL;
+
+ if (SSL_IS_TLS13(s)) {
+ size_t i;
+#ifndef OPENSSL_NO_EC
+ int curve = -1, skip_ec = 0;
+#endif
+
+ /* Look for a certificate matching shared sigalgs */
+ for (i = 0; i < s->cert->shared_sigalgslen; i++) {
+ lu = s->cert->shared_sigalgs[i];
+
+ /* Skip SHA1, DSA and RSA if not PSS */
+ if (lu->hash == NID_sha1 || lu->sig == EVP_PKEY_DSA
+ || lu->sig == EVP_PKEY_RSA)
+ continue;
+ if (ssl_md(lu->hash_idx) == NULL)
+ continue;
+ idx = lu->sig_idx;
+ if (!ssl_has_cert(s, idx))
+ continue;
+ if (lu->sig == EVP_PKEY_EC) {
+#ifndef OPENSSL_NO_EC
+ if (curve == -1) {
+ EC_KEY *ec = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[idx].privatekey);
+
+ curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
+ if (EC_KEY_get_conv_form(ec)
+ != POINT_CONVERSION_UNCOMPRESSED)
+ skip_ec = 1;
+ }
+ if (skip_ec || (lu->curve != NID_undef && curve != lu->curve))
+ continue;
+#else
+ continue;
+#endif
+ }
+ break;
+ }
+ if (i == s->cert->shared_sigalgslen) {
+ if (al == NULL)
+ return 1;
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_CHOOSE_SIGALG,
+ SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
+ return 0;
+ }
+ } else {
+ if (s->server) {
+ /* Find index corresponding to ciphersuite */
+ idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
+ /* If no certificate for ciphersuite return */
+ if (idx == -1)
+ return 1;
+ if (idx == SSL_PKEY_GOST_EC) {
+ /* Work out which GOST certificate is available */
+ if (ssl_has_cert(s, SSL_PKEY_GOST12_512)) {
+ idx = SSL_PKEY_GOST12_512;
+ } else if (ssl_has_cert(s, SSL_PKEY_GOST12_256)) {
+ idx = SSL_PKEY_GOST12_256;
+ } else if (ssl_has_cert(s, SSL_PKEY_GOST01)) {
+ idx = SSL_PKEY_GOST01;
+ } else {
+ if (al == NULL)
+ return 1;
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ } else if (!ssl_has_cert(s, idx)) {
+ if (al == NULL)
+ return 1;
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ } else {
+ /* Find index for client certificate */
+ idx = s->cert->key - s->cert->pkeys;
+ if (!ssl_has_cert(s, idx))
+ return 1;
+ }
+
+ if (SSL_USE_SIGALGS(s)) {
+ if (s->s3->tmp.peer_sigalgs != NULL) {
+ size_t i;
+#ifndef OPENSSL_NO_EC
+ int curve;
+
+ /* For Suite B need to match signature algorithm to curve */
+ if (tls1_suiteb(s)) {
+ EC_KEY *ec = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[idx].privatekey);
+ curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
+ } else {
+ curve = -1;
+ }
+#endif
+
+ /*
+ * Find highest preference signature algorithm matching
+ * cert type
+ */
+ for (i = 0; i < s->cert->shared_sigalgslen; i++) {
+ lu = s->cert->shared_sigalgs[i];
+#ifdef OPENSSL_NO_EC
+ if (lu->sig_idx == idx)
+ break;
+#else
+ if (lu->sig_idx == idx
+ && (curve == -1 || lu->curve == curve))
+ break;
+#endif
+ if (idx == SSL_PKEY_RSA && lu->sig == EVP_PKEY_RSA_PSS)
+ break;
+ }
+ if (i == s->cert->shared_sigalgslen) {
+ if (al == NULL)
+ return 1;
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ } else {
+ /*
+ * If we have no sigalg use defaults
+ */
+ const uint16_t *sent_sigs;
+ size_t sent_sigslen, i;
+
+ if ((lu = tls1_get_legacy_sigalg(s, idx)) == NULL) {
+ if (al == NULL)
+ return 1;
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* Check signature matches a type we sent */
+ sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
+ for (i = 0; i < sent_sigslen; i++, sent_sigs++) {
+ if (lu->sigalg == *sent_sigs)
+ break;
+ }
+ if (i == sent_sigslen) {
+ if (al == NULL)
+ return 1;
+ SSLerr(SSL_F_TLS_CHOOSE_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ return 0;
+ }
+ }
+ } else {
+ if ((lu = tls1_get_legacy_sigalg(s, idx)) == NULL) {
+ if (al == NULL)
+ return 1;
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ }
+ if (idx == -1) {
+ if (al != NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
+ }
+ return 0;
+ }
+ s->s3->tmp.cert = &s->cert->pkeys[idx];
+ s->cert->key = s->s3->tmp.cert;
+ s->s3->tmp.sigalg = lu;
+ return 1;
+}