TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2
};
-/* The client's default curves / the server's 'auto' curves. */
-static const unsigned char eccurves_auto[] = {
+/* The default curves */
+static const unsigned char eccurves_default[] = {
/* Prefer P-256 which has the fastest and most secure implementations. */
0, 23, /* secp256r1 (23) */
/* Other >= 256-bit prime curves. */
pcurveslen = s->tlsext_ellipticcurvelist_length;
}
if (!*pcurves) {
- if (!s->server || s->cert->ecdh_tmp_auto) {
- *pcurves = eccurves_auto;
- pcurveslen = sizeof(eccurves_auto);
- } else {
- *pcurves = eccurves_all;
- pcurveslen = sizeof(eccurves_all);
- }
+ *pcurves = eccurves_default;
+ pcurveslen = sizeof(eccurves_default);
}
}
}
/*-
- * Return |nmatch|th shared curve or NID_undef if there is no match.
- * For nmatch == -1, return number of matches
+ * For nmatch >= 0, return the NID of the |nmatch|th shared curve or NID_undef
+ * if there is no match.
+ * For nmatch == -1, return number of matches
* For nmatch == -2, return the NID of the curve to use for
* an EC tmp key, or NID_undef if there is no match.
*/
}
# ifndef OPENSSL_NO_EC
-/* Check EC temporary key is compatible with client extensions */
+/*
+ * tls1_check_ec_tmp_key - Check EC temporary key compatiblity
+ * @s: SSL connection
+ * @cid: Cipher ID we're considering using
+ *
+ * Checks that the kECDHE cipher suite we're considering using
+ * is compatible with the client extensions.
+ *
+ * Returns 0 when the cipher can't be used or 1 when it can.
+ */
int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
{
- unsigned char curve_id[2];
- EC_KEY *ec = s->cert->ecdh_tmp;
# ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
/* Allow any curve: not just those peer supports */
if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL)
* curves permitted.
*/
if (tls1_suiteb(s)) {
+ unsigned char curve_id[2];
/* Curve to check determined by ciphersuite */
if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
curve_id[1] = TLSEXT_curve_P_256;
/* Check this curve is acceptable */
if (!tls1_check_ec_key(s, curve_id, NULL))
return 0;
- /* If auto or setting curve from callback assume OK */
- if (s->cert->ecdh_tmp_auto || s->cert->ecdh_tmp_cb)
- return 1;
- /* Otherwise check curve is acceptable */
- else {
- unsigned char curve_tmp[2];
- if (!ec)
- return 0;
- if (!tls1_set_ec_id(curve_tmp, NULL, ec))
- return 0;
- if (!curve_tmp[0] || curve_tmp[1] == curve_id[1])
- return 1;
- return 0;
- }
-
- }
- if (s->cert->ecdh_tmp_auto) {
- /* Need a shared curve */
- if (tls1_shared_curve(s, 0))
- return 1;
- else
- return 0;
- }
- if (!ec) {
- if (s->cert->ecdh_tmp_cb)
- return 1;
- else
- return 0;
+ return 1;
}
- if (!tls1_set_ec_id(curve_id, NULL, ec))
- return 0;
-/* Set this to allow use of invalid curves for testing */
-# if 0
- return 1;
-# else
- return tls1_check_ec_key(s, curve_id, NULL);
-# endif
+ /* Need a shared curve */
+ if (tls1_shared_curve(s, 0))
+ return 1;
+ return 0;
}
# endif /* OPENSSL_NO_EC */
return s->cert->conf_sigalgslen;
} else {
*psigs = tls12_sigalgs;
-#ifndef OPENSSL_NO_GOST
- /*
- * We expect that GOST 2001 signature and GOST 34.11-94 hash are present in all engines
- * and GOST 2012 algorithms are not always present.
- * It may change when the old algorithms are deprecated.
- */
- if ((EVP_get_digestbynid(NID_id_GostR3411_94) != NULL)
- && (EVP_get_digestbynid(NID_id_GostR3411_2012_256) == NULL)) {
- return sizeof(tls12_sigalgs) - 4;
- } else if (EVP_get_digestbynid(NID_id_GostR3411_94) == NULL) {
- return sizeof(tls12_sigalgs) - 6;
- }
return sizeof(tls12_sigalgs);
-#else
- return sizeof(tls12_sigalgs);
-#endif
}
}
}
}
#endif
- if (!s->hit && s->session->flags & SSL_SESS_FLAG_EXTMS) {
+ if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) {
s2n(TLSEXT_TYPE_extended_master_secret, ret);
s2n(0, ret);
}
else if (type == TLSEXT_TYPE_encrypt_then_mac)
s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
#endif
- else if (type == TLSEXT_TYPE_extended_master_secret) {
- if (!s->hit)
- s->session->flags |= SSL_SESS_FLAG_EXTMS;
- }
+ /*
+ * Note: extended master secret extension handled in
+ * tls_check_serverhello_tlsext_early()
+ */
+
/*
* If this ClientHello extension was unhandled and this is a
* nonresumed connection, check whether the extension is a custom
s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
#endif
+ s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
+
if (!PACKET_get_net_2(pkt, &length))
goto ri_check;
}
#endif
else if (type == TLSEXT_TYPE_extended_master_secret) {
+ s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
if (!s->hit)
s->session->flags |= SSL_SESS_FLAG_EXTMS;
}
return 0;
}
+ if (s->hit) {
+ /*
+ * Check extended master secret extension is consistent with
+ * original session.
+ */
+ if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) !=
+ !(s->session->flags & SSL_SESS_FLAG_EXTMS)) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, SSL_R_INCONSISTENT_EXTMS);
+ return 0;
+ }
+ }
+
return 1;
}
/*-
* Since the server cache lookup is done early on in the processing of the
- * ClientHello, and other operations depend on the result, we need to handle
- * any TLS session ticket extension at the same time.
+ * ClientHello and other operations depend on the result some extensions
+ * need to be handled at the same time.
+ *
+ * Two extensions are currently handled, session ticket and extended master
+ * secret.
*
* session_id: ClientHello session ID.
* ext: ClientHello extensions (including length prefix)
* 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.
+ *
+ * For extended master secret flag is set if the extension is present.
+ *
*/
-int tls1_process_ticket(SSL *s, const PACKET *ext, const PACKET *session_id,
- SSL_SESSION **ret)
+int tls_check_serverhello_tlsext_early(SSL *s, const PACKET *ext,
+ const PACKET *session_id,
+ SSL_SESSION **ret)
{
unsigned int i;
PACKET local_ext = *ext;
int retv = -1;
+ int have_ticket = 0;
+ int use_ticket = tls_use_ticket(s);
+
*ret = NULL;
s->tlsext_ticket_expected = 0;
+ s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
/*
* If tickets disabled behave as if no ticket present to permit stateful
* resumption.
*/
- if (!tls_use_ticket(s))
- return 0;
if ((s->version <= SSL3_VERSION))
return 0;
retv = 0;
goto end;
}
- if (type == TLSEXT_TYPE_session_ticket) {
+ if (type == TLSEXT_TYPE_session_ticket && use_ticket) {
int r;
unsigned char *etick;
+ /* Duplicate extension */
+ if (have_ticket != 0) {
+ retv = -1;
+ goto end;
+ }
+ have_ticket = 1;
+
if (size == 0) {
/*
* The client will accept a ticket but doesn't currently have
*/
s->tlsext_ticket_expected = 1;
retv = 1;
- goto end;
+ continue;
}
if (s->tls_session_secret_cb) {
/*
* calculate the master secret later.
*/
retv = 2;
- goto end;
+ continue;
}
if (!PACKET_get_bytes(&local_ext, &etick, size)) {
/* Shouldn't ever happen */
retv = -1;
break;
}
- goto end;
+ continue;
} else {
+ if (type == TLSEXT_TYPE_extended_master_secret)
+ s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
if (!PACKET_forward(&local_ext, size)) {
retv = -1;
goto end;
}
}
}
- retv = 0;
+ if (have_ticket == 0)
+ retv = 0;
end:
return retv;
}
* 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.
const unsigned char *p;
int slen, mlen, renew_ticket = 0;
unsigned char tick_hmac[EVP_MAX_MD_SIZE];
- HMAC_CTX hctx;
+ HMAC_CTX *hctx = NULL;
EVP_CIPHER_CTX ctx;
SSL_CTX *tctx = s->initial_ctx;
/* Need at least keyname + iv + some encrypted data */
if (eticklen < 48)
return 2;
/* Initialize session ticket encryption and HMAC contexts */
- HMAC_CTX_init(&hctx);
+ hctx = HMAC_CTX_new();
+ if (hctx == NULL)
+ return -2;
EVP_CIPHER_CTX_init(&ctx);
if (tctx->tlsext_ticket_key_cb) {
unsigned char *nctick = (unsigned char *)etick;
int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16,
- &ctx, &hctx, 0);
+ &ctx, hctx, 0);
if (rv < 0)
return -1;
if (rv == 0)
/* Check key name matches */
if (memcmp(etick, tctx->tlsext_tick_key_name, 16))
return 2;
- if (HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
+ if (HMAC_Init_ex(hctx, tctx->tlsext_tick_hmac_key, 16,
EVP_sha256(), NULL) <= 0
|| EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
tctx->tlsext_tick_aes_key,
* Attempt to process session ticket, first conduct sanity and integrity
* checks on ticket.
*/
- mlen = HMAC_size(&hctx);
+ mlen = HMAC_size(hctx);
if (mlen < 0) {
goto err;
}
eticklen -= mlen;
/* Check HMAC of encrypted ticket */
- if (HMAC_Update(&hctx, etick, eticklen) <= 0
- || HMAC_Final(&hctx, tick_hmac, NULL) <= 0) {
+ if (HMAC_Update(hctx, etick, eticklen) <= 0
+ || HMAC_Final(hctx, tick_hmac, NULL) <= 0) {
goto err;
}
- HMAC_CTX_cleanup(&hctx);
+ HMAC_CTX_free(hctx);
if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) {
EVP_CIPHER_CTX_cleanup(&ctx);
return 2;
return 2;
err:
EVP_CIPHER_CTX_cleanup(&ctx);
- HMAC_CTX_cleanup(&hctx);
+ HMAC_CTX_free(hctx);
return -1;
}