-/* 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
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;
/*
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;
}
int slen, mlen, renew_ticket = 0;
unsigned char tick_hmac[EVP_MAX_MD_SIZE];
HMAC_CTX *hctx = NULL;
- EVP_CIPHER_CTX ctx;
+ EVP_CIPHER_CTX *ctx;
SSL_CTX *tctx = s->initial_ctx;
/* Need at least keyname + iv + some encrypted data */
if (eticklen < 48)
hctx = HMAC_CTX_new();
if (hctx == NULL)
return -2;
- EVP_CIPHER_CTX_init(&ctx);
+ 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)
return 2;
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;
}
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);
+ 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