#ifndef OPENSSL_NO_EC
-typedef struct {
- int nid; /* Curve NID */
- int secbits; /* Bits of security (from SP800-57) */
- unsigned int flags; /* Flags: currently just field type */
-} tls_curve_info;
-
/*
* Table of curve information.
* Do not delete entries or reorder this array! It is used as a lookup
* table: the index of each entry is one less than the TLS curve id.
*/
-static const tls_curve_info nid_list[] = {
+static const TLS_GROUP_INFO nid_list[] = {
{NID_sect163k1, 80, TLS_CURVE_CHAR2}, /* sect163k1 (1) */
{NID_sect163r1, 80, TLS_CURVE_CHAR2}, /* sect163r1 (2) */
{NID_sect163r2, 80, TLS_CURVE_CHAR2}, /* sect163r2 (3) */
TLSEXT_curve_P_384
};
-int tls1_ec_curve_id2nid(uint16_t curve_id, unsigned int *pflags)
+const TLS_GROUP_INFO *tls1_group_id_lookup(uint16_t group_id)
{
- const tls_curve_info *cinfo;
/* ECC curves from RFC 4492 and RFC 7027 */
- if (curve_id < 1 || curve_id > OSSL_NELEM(nid_list))
- return 0;
- cinfo = nid_list + curve_id - 1;
- if (pflags)
- *pflags = cinfo->flags;
- return cinfo->nid;
+ if (group_id < 1 || group_id > OSSL_NELEM(nid_list))
+ return NULL;
+ return &nid_list[group_id - 1];
}
-uint16_t tls1_ec_nid2curve_id(int nid)
+static uint16_t tls1_nid2group_id(int nid)
{
size_t i;
for (i = 0; i < OSSL_NELEM(nid_list); i++) {
if (nid_list[i].nid == nid)
- return i + 1;
+ return (uint16_t)(i + 1);
}
return 0;
}
/*
- * Get curves list, if "sess" is set return client curves otherwise
- * preferred list.
- * Sets |num_curves| to the number of curves in the list, i.e.,
- * the length of |pcurves| is 2 * num_curves.
- * Returns 1 on success and 0 if the client curves list has invalid format.
- * The latter indicates an internal error: we should not be accepting such
- * lists in the first place.
+ * Set *pgroups to the supported groups list and *pgroupslen to
+ * the number of groups supported.
*/
-int tls1_get_curvelist(SSL *s, int sess, const uint16_t **pcurves,
- size_t *num_curves)
+void tls1_get_supported_groups(SSL *s, const uint16_t **pgroups,
+ size_t *pgroupslen)
{
- size_t pcurveslen = 0;
- if (sess) {
- *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)) {
- case SSL_CERT_FLAG_SUITEB_128_LOS:
- *pcurves = suiteb_curves;
- pcurveslen = OSSL_NELEM(suiteb_curves);
- break;
+ /* For Suite B mode only include P-256, P-384 */
+ switch (tls1_suiteb(s)) {
+ case SSL_CERT_FLAG_SUITEB_128_LOS:
+ *pgroups = suiteb_curves;
+ *pgroupslen = OSSL_NELEM(suiteb_curves);
+ break;
- case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
- *pcurves = suiteb_curves;
- pcurveslen = 1;
- break;
+ case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
+ *pgroups = suiteb_curves;
+ *pgroupslen = 1;
+ break;
- case SSL_CERT_FLAG_SUITEB_192_LOS:
- *pcurves = suiteb_curves + 2;
- pcurveslen = 1;
- break;
- default:
- *pcurves = s->ext.supportedgroups;
- pcurveslen = s->ext.supportedgroups_len;
- }
- if (!*pcurves) {
- *pcurves = eccurves_default;
- pcurveslen = OSSL_NELEM(eccurves_default);
+ case SSL_CERT_FLAG_SUITEB_192_LOS:
+ *pgroups = suiteb_curves + 1;
+ *pgroupslen = 1;
+ break;
+
+ default:
+ if (s->ext.supportedgroups == NULL) {
+ *pgroups = eccurves_default;
+ *pgroupslen = OSSL_NELEM(eccurves_default);
+ } else {
+ *pgroups = s->ext.supportedgroups;
+ *pgroupslen = s->ext.supportedgroups_len;
}
+ break;
}
-
- *num_curves = pcurveslen;
- return 1;
}
/* See if curve is allowed by security callback */
int tls_curve_allowed(SSL *s, uint16_t curve, int op)
{
- const tls_curve_info *cinfo;
+ const TLS_GROUP_INFO *cinfo = tls1_group_id_lookup(curve);
unsigned char ctmp[2];
- if (curve > 0xff)
- return 1;
- if (curve < 1 || curve > OSSL_NELEM(nid_list))
+
+ if (cinfo == NULL)
return 0;
- cinfo = &nid_list[curve - 1];
# ifdef OPENSSL_NO_EC2M
if (cinfo->flags & TLS_CURVE_CHAR2)
return 0;
return ssl_security(s, op, cinfo->secbits, cinfo->nid, (void *)ctmp);
}
-/* Check a curve is one of our preferences */
-int tls1_check_curve(SSL *s, const unsigned char *p, size_t len)
+/* Return 1 if "id" is in "list" */
+static int tls1_in_list(uint16_t id, const uint16_t *list, size_t listlen)
{
- const uint16_t *curves;
- uint16_t curve_id;
- size_t num_curves, i;
- unsigned int suiteb_flags = tls1_suiteb(s);
- if (len != 3 || p[0] != NAMED_CURVE_TYPE)
- return 0;
- curve_id = (p[1] << 8) | p[2];
- /* Check curve matches Suite B preferences */
- if (suiteb_flags) {
- unsigned long cid = s->s3->tmp.new_cipher->id;
- if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) {
- if (curve_id != TLSEXT_curve_P_256)
- return 0;
- } else if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) {
- if (curve_id != TLSEXT_curve_P_384)
- return 0;
- } else /* Should never happen */
- return 0;
- }
- if (!tls1_get_curvelist(s, 0, &curves, &num_curves))
- return 0;
- for (i = 0; i < num_curves; i++) {
- if (curve_id == curves[i])
- return tls_curve_allowed(s, curve_id, SSL_SECOP_CURVE_CHECK);
- }
+ size_t i;
+ for (i = 0; i < listlen; i++)
+ if (list[i] == id)
+ return 1;
return 0;
}
/*-
- * For nmatch >= 0, return the NID of the |nmatch|th shared group or NID_undef
+ * For nmatch >= 0, return the id of the |nmatch|th shared group or 0
* if there is no match.
* For nmatch == -1, return number of matches
- * For nmatch == -2, return the NID of the group to use for
- * an EC tmp key, or NID_undef if there is no match.
+ * For nmatch == -2, return the id of the group to use for
+ * a tmp key, or 0 if there is no match.
*/
-int tls1_shared_group(SSL *s, int nmatch)
+uint16_t tls1_shared_group(SSL *s, int nmatch)
{
const uint16_t *pref, *supp;
- size_t num_pref, num_supp, i, j;
+ size_t num_pref, num_supp, i;
int k;
/* Can't do anything on client side */
if (s->server == 0)
- return -1;
+ return 0;
if (nmatch == -2) {
if (tls1_suiteb(s)) {
/*
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 */
+ return TLSEXT_curve_P_256;
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
- return NID_secp384r1; /* P-384 */
+ return TLSEXT_curve_P_384;
/* Should never happen */
- return NID_undef;
+ return 0;
}
/* If not Suite B just return first preference shared curve */
nmatch = 0;
}
/*
- * Avoid truncation. tls1_get_curvelist takes an int
- * but s->options is a long...
+ * If server preference set, our groups are the preference order
+ * otherwise peer decides.
*/
- 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) == 0,
- &pref, &num_pref))
- return nmatch == -1 ? 0 : NID_undef;
+ if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
+ tls1_get_supported_groups(s, &pref, &num_pref);
+ tls1_get_peer_groups(s, &supp, &num_supp);
+ } else {
+ tls1_get_peer_groups(s, &pref, &num_pref);
+ tls1_get_supported_groups(s, &supp, &num_supp);
+ }
for (k = 0, i = 0; i < num_pref; i++) {
uint16_t id = pref[i];
- for (j = 0; j < num_supp; j++) {
- if (id == supp[j]) {
- if (!tls_curve_allowed(s, id, SSL_SECOP_CURVE_SHARED))
+ if (!tls1_in_list(id, supp, num_supp)
+ || !tls_curve_allowed(s, id, SSL_SECOP_CURVE_SHARED))
continue;
- if (nmatch == k)
- return tls1_ec_curve_id2nid(id, NULL);
- k++;
- }
- }
+ if (nmatch == k)
+ return id;
+ k++;
}
if (nmatch == -1)
return k;
/* Out of range (nmatch > k). */
- return NID_undef;
+ return 0;
}
int tls1_set_groups(uint16_t **pext, size_t *pextlen,
unsigned long idmask;
uint16_t id;
/* TODO(TLS1.3): Convert for DH groups */
- id = tls1_ec_nid2curve_id(groups[i]);
+ id = tls1_nid2group_id(groups[i]);
idmask = 1L << id;
if (!id || (dup_list & idmask)) {
OPENSSL_free(glist);
return 1;
return tls1_set_groups(pext, pextlen, ncb.nid_arr, ncb.nidcnt);
}
-
-/* For an EC key set TLS id and required compression based on parameters */
-static int tls1_set_ec_id(uint16_t *pcurve_id, unsigned char *comp_id,
- EC_KEY *ec)
+/* Return group id of a key */
+static uint16_t tls1_get_group_id(EVP_PKEY *pkey)
{
- int curve_nid;
+ EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
const EC_GROUP *grp;
- if (!ec)
+
+ if (ec == NULL)
return 0;
- /* Determine if it is a prime field */
grp = EC_KEY_get0_group(ec);
- if (!grp)
- return 0;
- /* Determine curve ID */
- curve_nid = EC_GROUP_get_curve_name(grp);
- *pcurve_id = tls1_ec_nid2curve_id(curve_nid);
- /* If no id return error: we don't support arbitrary explicit curves */
- if (*pcurve_id == 0)
- return 0;
- if (comp_id) {
- if (EC_KEY_get0_public_key(ec) == NULL)
- return 0;
- if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_UNCOMPRESSED) {
- *comp_id = TLSEXT_ECPOINTFORMAT_uncompressed;
- } else {
- if ((nid_list[*pcurve_id - 1].flags & TLS_CURVE_TYPE) == TLS_CURVE_PRIME)
- *comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
- else
- *comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
- }
- }
- return 1;
+ return tls1_nid2group_id(EC_GROUP_get_curve_name(grp));
}
-/* Check an EC key is compatible with extensions */
-static int tls1_check_ec_key(SSL *s, uint16_t curve_id, unsigned char *comp_id)
+/* Check a key is compatible with compression extension */
+static int tls1_check_pkey_comp(SSL *s, EVP_PKEY *pkey)
{
- const unsigned char *pformats;
- const uint16_t *pcurves;
- size_t num_formats, num_curves, i;
- int j;
+ const EC_KEY *ec;
+ const EC_GROUP *grp;
+ unsigned char comp_id;
+ size_t i;
+
+ /* If not an EC key nothing to check */
+ if (EVP_PKEY_id(pkey) != EVP_PKEY_EC)
+ return 1;
+ ec = EVP_PKEY_get0_EC_KEY(pkey);
+ grp = EC_KEY_get0_group(ec);
+
+ /* Get required compression id */
+ if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_UNCOMPRESSED) {
+ comp_id = TLSEXT_ECPOINTFORMAT_uncompressed;
+ } else if (SSL_IS_TLS13(s)) {
+ /* Compression not allowed in TLS 1.3 */
+ return 0;
+ } else {
+ int field_type = EC_METHOD_get_field_type(EC_GROUP_method_of(grp));
+
+ if (field_type == NID_X9_62_prime_field)
+ comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
+ else if (field_type == NID_X9_62_characteristic_two_field)
+ comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
+ else
+ return 0;
+ }
/*
* If point formats extension present check it, otherwise everything is
* supported (see RFC4492).
*/
- 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 (i == num_formats)
- return 0;
- }
- if (curve_id == 0)
+ if (s->session->ext.ecpointformats == NULL)
return 1;
- /* Check curve is consistent with client and server preferences */
- for (j = 0; j <= 1; j++) {
- if (!tls1_get_curvelist(s, j, &pcurves, &num_curves))
+
+ for (i = 0; i < s->session->ext.ecpointformats_len; i++) {
+ if (s->session->ext.ecpointformats[i] == comp_id)
+ return 1;
+ }
+ return 0;
+}
+
+/* Check a group id matches preferences */
+int tls1_check_group_id(SSL *s, uint16_t group_id)
+ {
+ const uint16_t *groups;
+ size_t groups_len;
+
+ if (group_id == 0)
+ return 0;
+
+ /* Check for Suite B compliance */
+ if (tls1_suiteb(s) && s->s3->tmp.new_cipher != NULL) {
+ unsigned long cid = s->s3->tmp.new_cipher->id;
+
+ if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) {
+ if (group_id != TLSEXT_curve_P_256)
+ return 0;
+ } else if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) {
+ if (group_id != TLSEXT_curve_P_384)
+ return 0;
+ } else {
+ /* Should never happen */
return 0;
- if (j == 1 && num_curves == 0) {
- /*
- * If we've not received any curves then skip this check.
- * RFC 4492 does not require the supported elliptic curves extension
- * so if it is not sent we can just choose any curve.
- * It is invalid to send an empty list in the elliptic curves
- * extension, so num_curves == 0 always means no extension.
- */
- break;
}
- for (i = 0; i < num_curves; i++) {
- if (pcurves[i] == curve_id)
- break;
- }
- if (i == num_curves)
- return 0;
- /* For clients can only check sent curve list */
- if (!s->server)
- break;
}
- return 1;
+
+ /* Check group is one of our preferences */
+ tls1_get_supported_groups(s, &groups, &groups_len);
+ if (!tls1_in_list(group_id, groups, groups_len))
+ return 0;
+
+ if (!tls_curve_allowed(s, group_id, SSL_SECOP_CURVE_CHECK))
+ return 0;
+
+ /* For clients, nothing more to check */
+ if (!s->server)
+ return 1;
+
+ /* Check group is one of peers preferences */
+ tls1_get_peer_groups(s, &groups, &groups_len);
+
+ /*
+ * RFC 4492 does not require the supported elliptic curves extension
+ * so if it is not sent we can just choose any curve.
+ * It is invalid to send an empty list in the supported groups
+ * extension, so groups_len == 0 always means no extension.
+ */
+ if (groups_len == 0)
+ return 1;
+ return tls1_in_list(group_id, groups, groups_len);
}
void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
*/
static int tls1_check_cert_param(SSL *s, X509 *x, int check_ee_md)
{
- unsigned char comp_id;
- uint16_t curve_id;
+ uint16_t group_id;
EVP_PKEY *pkey;
- int rv;
pkey = X509_get0_pubkey(x);
- if (!pkey)
+ if (pkey == NULL)
return 0;
/* If not EC nothing to do */
if (EVP_PKEY_id(pkey) != EVP_PKEY_EC)
return 1;
- rv = tls1_set_ec_id(&curve_id, &comp_id, EVP_PKEY_get0_EC_KEY(pkey));
- if (!rv)
+ /* Check compression */
+ if (!tls1_check_pkey_comp(s, pkey))
return 0;
- /*
- * Can't check curve_id for client certs as we don't have a supported
- * curves extension.
- */
- rv = tls1_check_ec_key(s, s->server ? curve_id : 0, &comp_id);
- if (!rv)
+ group_id = tls1_get_group_id(pkey);
+ if (!tls1_check_group_id(s, group_id))
return 0;
/*
* Special case for suite B. We *MUST* sign using SHA256+P-256 or
CERT *c = s->cert;
/* Check to see we have necessary signing algorithm */
- if (curve_id == TLSEXT_curve_P_256)
+ if (group_id == TLSEXT_curve_P_256)
check_md = NID_ecdsa_with_SHA256;
- else if (curve_id == TLSEXT_curve_P_384)
+ else if (group_id == TLSEXT_curve_P_384)
check_md = NID_ecdsa_with_SHA384;
else
return 0; /* Should never happen */
- for (i = 0; i < c->shared_sigalgslen; i++)
+ for (i = 0; i < c->shared_sigalgslen; i++) {
if (check_md == c->shared_sigalgs[i]->sigandhash)
- break;
- if (i == c->shared_sigalgslen)
- return 0;
+ return 1;;
+ }
+ return 0;
}
- return rv;
+ return 1;
}
/*
*/
int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
{
+ /* If not Suite B just need a shared group */
+ if (!tls1_suiteb(s))
+ return tls1_shared_group(s, 0) != 0;
/*
* If Suite B, AES128 MUST use P-256 and AES256 MUST use P-384, no other
* curves permitted.
*/
- if (tls1_suiteb(s)) {
- uint16_t curve_id;
-
- /* Curve to check determined by ciphersuite */
- if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
- curve_id = TLSEXT_curve_P_256;
- else if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
- curve_id = TLSEXT_curve_P_384;
- else
- return 0;
- /* Check this curve is acceptable */
- if (!tls1_check_ec_key(s, curve_id, NULL))
- return 0;
- return 1;
- }
- /* Need a shared curve */
- if (tls1_shared_group(s, 0))
- return 1;
+ if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
+ return tls1_check_group_id(s, TLSEXT_curve_P_256);
+ if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
+ return tls1_check_group_id(s, TLSEXT_curve_P_384);
+
return 0;
}
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);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG,
+ SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
/* Only allow PSS for TLS 1.3 */
|| (SSL_IS_TLS13(s) && (lu->hash == NID_sha1 || lu->hash == NID_sha224))
|| (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);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG,
+ SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
#ifndef OPENSSL_NO_EC
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 */
+ /* Check point compression is permitted */
+ if (!tls1_check_pkey_comp(s, pkey)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS12_CHECK_PEER_SIGALG,
+ SSL_R_ILLEGAL_POINT_COMPRESSION);
+ return 0;
+ }
+
+ /* For TLS 1.3 or Suite B check curve matches signature algorithm */
+ if (SSL_IS_TLS13(s) || tls1_suiteb(s)) {
+ EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
+ int curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
+
if (lu->curve != NID_undef && curve != lu->curve) {
- SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
return 0;
}
- } else {
- unsigned char comp_id;
- uint16_t curve_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);
+ }
+ if (!SSL_IS_TLS13(s)) {
+ /* Check curve matches extensions */
+ if (!tls1_check_group_id(s, tls1_get_group_id(pkey))) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
return 0;
}
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_WRONG_SIGNATURE_TYPE);
- return 0;
- }
- /*
- * 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);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS12_CHECK_PEER_SIGALG,
+ SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
}
}
} else if (tls1_suiteb(s)) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
+ SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
#endif
/* Allow fallback to SHA1 if not strict mode */
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);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
+ SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
if (!tls1_lookup_md(lu, &md)) {
- SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_UNKNOWN_DIGEST);
- return 0;
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
+ SSL_R_UNKNOWN_DIGEST);
+ return 0;
}
if (md != NULL) {
/*
if (!ssl_security(s, SSL_SECOP_SIGALG_CHECK,
EVP_MD_size(md) * 4, EVP_MD_type(md),
(void *)sigalgstr)) {
- SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
+ SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
}
int tls1_set_server_sigalgs(SSL *s)
{
- int al;
size_t i;
/* Clear any shared signature algorithms */
}
if (!tls1_process_sigalgs(s)) {
- SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, ERR_R_MALLOC_FAILURE);
- al = SSL_AD_INTERNAL_ERROR;
- goto err;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS1_SET_SERVER_SIGALGS, ERR_R_INTERNAL_ERROR);
+ return 0;
}
if (s->cert->shared_sigalgs != NULL)
return 1;
+
/* Fatal error if no shared signature algorithms */
- SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS);
- al = SSL_AD_HANDSHAKE_FAILURE;
- err:
- ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS1_SET_SERVER_SIGALGS,
+ SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS);
return 0;
}
* in disabled_mask.
*/
sigalgslen = tls12_get_psigalgs(s, 1, &sigalgs);
- for (i = 0; i < sigalgslen; i ++, sigalgs++) {
+ for (i = 0; i < sigalgslen; i++, sigalgs++) {
const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*sigalgs);
const SSL_CERT_LOOKUP *clu;
continue;
clu = ssl_cert_lookup_by_idx(lu->sig_idx);
+ if (clu == NULL)
+ continue;
/* If algorithm is disabled see if we can enable it */
if ((clu->amask & disabled_mask) != 0
* 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 servers if we fail to find a required certificate it is a fatal error,
+ * an appropriate error code is set and a TLS alert is sent.
*
- * For clients al is set to NULL. If a certificate is not suitable it is not
+ * For clients fatalerrs is set to 0. 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 tls_choose_sigalg(SSL *s, int fatalerrs)
{
const SIGALG_LOOKUP *lu = NULL;
int sig_idx = -1;
break;
}
if (i == s->cert->shared_sigalgslen) {
- if (al == NULL)
+ if (!fatalerrs)
return 1;
- *al = SSL_AD_HANDSHAKE_FAILURE;
- SSLerr(SSL_F_TLS_CHOOSE_SIGALG,
- SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CHOOSE_SIGALG,
+ SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
return 0;
}
} else {
break;
}
if (i == s->cert->shared_sigalgslen) {
- if (al == NULL)
+ if (!fatalerrs)
return 1;
- *al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CHOOSE_SIGALG,
+ ERR_R_INTERNAL_ERROR);
return 0;
}
} else {
size_t sent_sigslen, i;
if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
- if (al == NULL)
+ if (!fatalerrs)
return 1;
- *al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CHOOSE_SIGALG,
+ ERR_R_INTERNAL_ERROR);
return 0;
}
break;
}
if (i == sent_sigslen) {
- if (al == NULL)
+ if (!fatalerrs)
return 1;
- SSLerr(SSL_F_TLS_CHOOSE_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
- *al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_CHOOSE_SIGALG,
+ SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
}
} else {
if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
- if (al == NULL)
+ if (!fatalerrs)
return 1;
- *al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CHOOSE_SIGALG,
+ ERR_R_INTERNAL_ERROR);
return 0;
}
}
s->s3->tmp.sigalg = lu;
return 1;
}
+
+int SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode)
+{
+ if (mode != TLSEXT_max_fragment_length_DISABLED
+ && !IS_MAX_FRAGMENT_LENGTH_EXT_VALID(mode)) {
+ SSLerr(SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH,
+ SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
+ return 0;
+ }
+
+ ctx->ext.max_fragment_len_mode = mode;
+ return 1;
+}
+
+int SSL_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode)
+{
+ if (mode != TLSEXT_max_fragment_length_DISABLED
+ && !IS_MAX_FRAGMENT_LENGTH_EXT_VALID(mode)) {
+ SSLerr(SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH,
+ SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
+ return 0;
+ }
+
+ ssl->ext.max_fragment_len_mode = mode;
+ return 1;
+}
+
+uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *session)
+{
+ return session->ext.max_fragment_len_mode;
+}