-/* ssl/t1_lib.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
void tls1_clear(SSL *s)
{
ssl3_clear(s);
- s->version = s->method->version;
+ if (s->method->version == TLS_ANY_VERSION)
+ s->version = TLS_MAX_VERSION;
+ else
+ s->version = s->method->version;
}
#ifndef OPENSSL_NO_EC
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.
*/
unsigned char comp_id, curve_id[2];
EVP_PKEY *pkey;
int rv;
- pkey = X509_get_pubkey(x);
+ pkey = X509_get0_pubkey(x);
if (!pkey)
return 0;
/* If not EC nothing to do */
- if (pkey->type != EVP_PKEY_EC) {
- EVP_PKEY_free(pkey);
+ if (EVP_PKEY_id(pkey) != EVP_PKEY_EC)
return 1;
- }
- rv = tls1_set_ec_id(curve_id, &comp_id, pkey->pkey.ec);
- EVP_PKEY_free(pkey);
+ rv = tls1_set_ec_id(curve_id, &comp_id, EVP_PKEY_get0_EC_KEY(pkey));
if (!rv)
return 0;
/*
}
# 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 assume OK */
- if (s->cert->ecdh_tmp_auto)
- 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) {
- 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 0;
}
#ifndef OPENSSL_NO_EC
- if (pkey->type == EVP_PKEY_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, pkey->pkey.ec))
+ 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);
* algorithms.
*/
if (s->s3->tmp.mask_a & SSL_aRSA)
- s->s3->tmp.mask_k |= SSL_kDHr | SSL_kECDHr;
- if (s->s3->tmp.mask_a & SSL_aDSS)
- s->s3->tmp.mask_k |= SSL_kDHd;
+ s->s3->tmp.mask_k |= SSL_kECDHr;
if (s->s3->tmp.mask_a & SSL_aECDSA)
s->s3->tmp.mask_k |= SSL_kECDHe;
# ifndef OPENSSL_NO_PSK
STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s);
for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) {
- SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
+ const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
alg_k = c->algorithm_mkey;
alg_a = c->algorithm_auth;
}
}
#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;
}
if (!s->hit && tlsext_servername == 1) {
if (s->tlsext_hostname) {
if (s->session->tlsext_hostname == NULL) {
- s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
+ s->session->tlsext_hostname = OPENSSL_strdup(s->tlsext_hostname);
if (!s->session->tlsext_hostname) {
*al = SSL_AD_UNRECOGNIZED_NAME;
return 0;
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;
}
initial_ctx->tlsext_servername_arg);
/*
- * If we've requested certificate status and we wont get one tell the
- * callback
+ * Ensure we get sensible values passed to tlsext_status_cb in the event
+ * that we don't receive a status message
*/
- if ((s->tlsext_status_type != -1) && !(s->tlsext_status_expected)
- && s->ctx && s->ctx->tlsext_status_cb) {
- int r;
- /*
- * Set resp to NULL, resplen to -1 so callback knows there is no
- * response.
- */
- OPENSSL_free(s->tlsext_ocsp_resp);
- s->tlsext_ocsp_resp = NULL;
- s->tlsext_ocsp_resplen = -1;
- r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
- if (r == 0) {
- al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
- ret = SSL_TLSEXT_ERR_ALERT_FATAL;
- }
- if (r < 0) {
- al = SSL_AD_INTERNAL_ERROR;
- ret = SSL_TLSEXT_ERR_ALERT_FATAL;
- }
- }
+ OPENSSL_free(s->tlsext_ocsp_resp);
+ s->tlsext_ocsp_resp = NULL;
+ s->tlsext_ocsp_resplen = -1;
switch (ret) {
case SSL_TLSEXT_ERR_ALERT_FATAL:
/*-
* 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;
- EVP_CIPHER_CTX ctx;
+ 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);
- EVP_CIPHER_CTX_init(&ctx);
+ hctx = HMAC_CTX_new();
+ if (hctx == NULL)
+ return -2;
+ ctx = EVP_CIPHER_CTX_new();
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,
+ || EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL,
tctx->tlsext_tick_aes_key,
etick + 16) <= 0) {
goto err;
* 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);
+ EVP_CIPHER_CTX_free(ctx);
return 2;
}
/* 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 + 16 + EVP_CIPHER_CTX_iv_length(ctx);
+ eticklen -= 16 + EVP_CIPHER_CTX_iv_length(ctx);
sdec = OPENSSL_malloc(eticklen);
if (sdec == NULL
- || EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen) <= 0) {
- EVP_CIPHER_CTX_cleanup(&ctx);
+ || EVP_DecryptUpdate(ctx, sdec, &slen, p, eticklen) <= 0) {
+ EVP_CIPHER_CTX_free(ctx);
return -1;
}
- if (EVP_DecryptFinal(&ctx, sdec + slen, &mlen) <= 0) {
- EVP_CIPHER_CTX_cleanup(&ctx);
+ if (EVP_DecryptFinal(ctx, sdec + slen, &mlen) <= 0) {
+ EVP_CIPHER_CTX_free(ctx);
OPENSSL_free(sdec);
return 2;
}
slen += mlen;
- EVP_CIPHER_CTX_cleanup(&ctx);
+ EVP_CIPHER_CTX_free(ctx);
+ ctx = NULL;
p = sdec;
sess = d2i_SSL_SESSION(NULL, &p, slen);
*/
return 2;
err:
- EVP_CIPHER_CTX_cleanup(&ctx);
- HMAC_CTX_cleanup(&hctx);
+ EVP_CIPHER_CTX_free(ctx);
+ HMAC_CTX_free(hctx);
return -1;
}
int tls12_get_sigid(const EVP_PKEY *pk)
{
- return tls12_find_id(pk->type, tls12_sig, OSSL_NELEM(tls12_sig));
+ return tls12_find_id(EVP_PKEY_id(pk), tls12_sig, OSSL_NELEM(tls12_sig));
}
typedef struct {
static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid,
int *psignhash_nid, const unsigned char *data)
{
- int sign_nid = 0, hash_nid = 0;
+ int sign_nid = NID_undef, hash_nid = NID_undef;
if (!phash_nid && !psign_nid && !psignhash_nid)
return;
if (phash_nid || psignhash_nid) {
*psign_nid = sign_nid;
}
if (psignhash_nid) {
- if (sign_nid && hash_nid)
- OBJ_find_sigid_by_algs(psignhash_nid, hash_nid, sign_nid);
- else
+ 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;
}
}
switch (idx) {
case SSL_PKEY_RSA_ENC:
case SSL_PKEY_RSA_SIGN:
- case SSL_PKEY_DH_RSA:
rsign = TLSEXT_signature_rsa;
default_nid = NID_sha1WithRSAEncryption;
break;
case SSL_PKEY_DSA_SIGN:
- case SSL_PKEY_DH_DSA:
rsign = TLSEXT_signature_dsa;
default_nid = NID_dsaWithSHA1;
break;
if (!s->server && strict_mode) {
STACK_OF(X509_NAME) *ca_dn;
int check_type = 0;
- switch (pk->type) {
+ switch (EVP_PKEY_id(pk)) {
case EVP_PKEY_RSA:
check_type = TLS_CT_RSA_SIGN;
break;
case EVP_PKEY_EC:
check_type = TLS_CT_ECDSA_SIGN;
break;
- case EVP_PKEY_DH:
- case EVP_PKEY_DHX:
- {
- int cert_type = X509_certificate_type(x, pk);
- if (cert_type & EVP_PKS_RSA)
- check_type = TLS_CT_RSA_FIXED_DH;
- if (cert_type & EVP_PKS_DSA)
- check_type = TLS_CT_DSS_FIXED_DH;
- }
}
if (check_type) {
const unsigned char *ctypes;
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_DSA_SIGN);
- tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DH_RSA);
- tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DH_DSA);
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_256);
static int ssl_security_cert_key(SSL *s, SSL_CTX *ctx, X509 *x, int op)
{
- int secbits;
- EVP_PKEY *pkey = X509_get_pubkey(x);
+ int secbits = -1;
+ EVP_PKEY *pkey = X509_get0_pubkey(x);
if (pkey) {
+ /*
+ * If no parameters this will return -1 and fail using the default
+ * security callback for any non-zero security level. This will
+ * reject keys which omit parameters but this only affects DSA and
+ * omission of parameters is never (?) done in practice.
+ */
secbits = EVP_PKEY_security_bits(pkey);
- EVP_PKEY_free(pkey);
- } else
- secbits = -1;
+ }
if (s)
return ssl_security(s, op, secbits, 0, x);
else