/*
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* Copyright 2005 Nokia. All rights reserved.
*
#include <openssl/trace.h>
#include <openssl/core_names.h>
#include <openssl/param_build.h>
-#include <internal/cryptlib.h>
+#include "internal/cryptlib.h"
static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s, PACKET *pkt);
static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt);
}
if (mt == SSL3_MT_CERTIFICATE_REQUEST) {
#if DTLS_MAX_VERSION_INTERNAL != DTLS1_2_VERSION
-# error TODO(DTLS1.3): Restore digest for PHA before adding message.
+ /* Restore digest for PHA before adding message.*/
+# error Internal DTLS version error
#endif
if (!SSL_IS_DTLS(s) && s->post_handshake_auth == SSL_PHA_EXT_SENT) {
s->post_handshake_auth = SSL_PHA_REQUESTED;
return CCS_MAX_LENGTH;
case TLS_ST_CR_SESSION_TICKET:
- return SSL3_RT_MAX_PLAIN_LENGTH;
+ return (SSL_IS_TLS13(s)) ? SESSION_TICKET_MAX_LENGTH_TLS13
+ : SESSION_TICKET_MAX_LENGTH_TLS12;
case TLS_ST_CR_FINISHED:
return FINISHED_MAX_LENGTH;
}
/*
- * Process a message that the client has been received from the server.
+ * Process a message that the client has received from the server.
*/
MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt)
{
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
+ case TLS_ST_CR_CERT:
+ return tls_post_process_server_certificate(s, wst);
+
case TLS_ST_CR_CERT_VRFY:
case TLS_ST_CR_CERT_REQ:
return tls_prepare_client_certificate(s, wst);
session_id = s->tmp_session_id;
if (s->hello_retry_request == SSL_HRR_NONE
&& RAND_bytes_ex(s->ctx->libctx, s->tmp_session_id,
- sess_id_len) <= 0) {
+ sess_id_len, 0) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
OPENSSL_free(extensions);
extensions = NULL;
- if (s->ext.tls13_cookie_len == 0
-#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
- && s->s3.tmp.pkey != NULL
-#endif
- ) {
+ if (s->ext.tls13_cookie_len == 0 && s->s3.tmp.pkey != NULL) {
/*
* We didn't receive a cookie or a new key_share so the next
* ClientHello will not change
return MSG_PROCESS_ERROR;
}
+/* prepare server cert verification by setting s->session->peer_chain from pkt */
MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
{
- int i;
- MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
unsigned long cert_list_len, cert_len;
X509 *x = NULL;
const unsigned char *certstart, *certbytes;
- STACK_OF(X509) *sk = NULL;
- EVP_PKEY *pkey = NULL;
- size_t chainidx, certidx;
+ size_t chainidx;
unsigned int context = 0;
- const SSL_CERT_LOOKUP *clu;
- if ((sk = sk_X509_new_null()) == NULL) {
+ if ((s->session->peer_chain = sk_X509_new_null()) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
OPENSSL_free(rawexts);
}
- if (!sk_X509_push(sk, x)) {
+ if (!sk_X509_push(s->session->peer_chain, x)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
x = NULL;
}
+ return MSG_PROCESS_CONTINUE_PROCESSING;
- i = ssl_verify_cert_chain(s, sk);
+ err:
+ X509_free(x);
+ OSSL_STACK_OF_X509_free(s->session->peer_chain);
+ s->session->peer_chain = NULL;
+ return MSG_PROCESS_ERROR;
+}
+
+/*
+ * Verify the s->session->peer_chain and check server cert type.
+ * On success set s->session->peer and s->session->verify_result.
+ * Else the peer certificate verification callback may request retry.
+ */
+WORK_STATE tls_post_process_server_certificate(SSL *s, WORK_STATE wst)
+{
+ X509 *x;
+ EVP_PKEY *pkey = NULL;
+ const SSL_CERT_LOOKUP *clu;
+ size_t certidx;
+ int i;
+
+ i = ssl_verify_cert_chain(s, s->session->peer_chain);
+ if (i == -1) {
+ s->rwstate = SSL_RETRY_VERIFY;
+ return WORK_MORE_A;
+ }
/*
* The documented interface is that SSL_VERIFY_PEER should be set in order
* for client side verification of the server certificate to take place.
* (less clean) historic behaviour of performing validation if any flag is
* set. The *documented* interface remains the same.
*/
- if (s->verify_mode != SSL_VERIFY_NONE && i <= 0) {
+ if (s->verify_mode != SSL_VERIFY_NONE && i == 0) {
SSLfatal(s, ssl_x509err2alert(s->verify_result),
SSL_R_CERTIFICATE_VERIFY_FAILED);
- goto err;
+ return WORK_ERROR;
}
ERR_clear_error(); /* but we keep s->verify_result */
- if (i > 1) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, i);
- goto err;
- }
- s->session->peer_chain = sk;
/*
* Inconsistency alert: cert_chain does include the peer's certificate,
* which we don't include in statem_srvr.c
*/
- x = sk_X509_value(sk, 0);
- sk = NULL;
+ x = sk_X509_value(s->session->peer_chain, 0);
pkey = X509_get0_pubkey(x);
if (pkey == NULL || EVP_PKEY_missing_parameters(pkey)) {
- x = NULL;
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
- goto err;
+ return WORK_ERROR;
}
if ((clu = ssl_cert_lookup_by_pkey(pkey, &certidx)) == NULL) {
- x = NULL;
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
- goto err;
+ return WORK_ERROR;
}
/*
* Check certificate type is consistent with ciphersuite. For TLS 1.3
*/
if (!SSL_IS_TLS13(s)) {
if ((clu->amask & s->s3.tmp.new_cipher->algorithm_auth) == 0) {
- x = NULL;
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_CERTIFICATE_TYPE);
- goto err;
+ return WORK_ERROR;
}
}
- s->session->peer_type = certidx;
X509_free(s->session->peer);
X509_up_ref(x);
s->session->peer = x;
s->session->verify_result = s->verify_result;
- x = NULL;
/* Save the current hash state for when we receive the CertificateVerify */
if (SSL_IS_TLS13(s)
sizeof(s->cert_verify_hash),
&s->cert_verify_hash_len)) {
/* SSLfatal() already called */;
- goto err;
+ return WORK_ERROR;
}
-
- ret = MSG_PROCESS_CONTINUE_READING;
-
- err:
- X509_free(x);
- sk_X509_pop_free(sk, X509_free);
- return ret;
+ return WORK_FINISHED_CONTINUE;
}
static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt)
return 0;
}
- /* TODO(size_t): Convert BN_bin2bn() calls */
if ((s->srp_ctx.N =
BN_bin2bn(PACKET_data(&prime),
(int)PACKET_remaining(&prime), NULL)) == NULL
return 0;
}
- /* TODO(size_t): Convert these calls */
p = BN_bin2bn(PACKET_data(&prime), (int)PACKET_remaining(&prime), NULL);
g = BN_bin2bn(PACKET_data(&generator), (int)PACKET_remaining(&generator),
NULL);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- if (EVP_PKEY_key_fromdata_init(pctx) <= 0
- || EVP_PKEY_fromdata(pctx, &peer_tmp, params) <= 0) {
+ if (EVP_PKEY_fromdata_init(pctx) <= 0
+ || EVP_PKEY_fromdata(pctx, &peer_tmp, EVP_PKEY_KEYPAIR, params) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_DH_VALUE);
goto err;
}
EVP_PKEY_CTX_free(pctx);
pctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, peer_tmp, s->ctx->propq);
if (pctx == NULL
- || EVP_PKEY_param_check(pctx) != 1
+ /*
+ * EVP_PKEY_param_check() will verify that the DH params are using
+ * a safe prime. In this context, because we're using ephemeral DH,
+ * we're ok with it not being a safe prime.
+ * EVP_PKEY_param_check_quick() skips the safe prime check.
+ */
+ || EVP_PKEY_param_check_quick(pctx) != 1
|| EVP_PKEY_public_check(pctx) != 1) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_DH_VALUE);
goto err;
}
- if (!ssl_security(s, SSL_SECOP_TMP_DH, EVP_PKEY_security_bits(peer_tmp),
+ if (!ssl_security(s, SSL_SECOP_TMP_DH,
+ EVP_PKEY_get_security_bits(peer_tmp),
0, peer_tmp)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_DH_KEY_TOO_SMALL);
goto err;
err:
OSSL_PARAM_BLD_free(tmpl);
- OSSL_PARAM_BLD_free_params(params);
+ OSSL_PARAM_free(params);
EVP_PKEY_free(peer_tmp);
EVP_PKEY_CTX_free(pctx);
BN_free(p);
static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
{
-#ifndef OPENSSL_NO_EC
PACKET encoded_pt;
unsigned int curve_type, curve_id;
*pkey = X509_get0_pubkey(s->session->peer);
/* else anonymous ECDH, so no certificate or pkey. */
+ /* Cache the agreed upon group in the SSL_SESSION */
+ s->session->kex_group = curve_id;
return 1;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
}
MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
save_param_start = *pkt;
-#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
EVP_PKEY_free(s->s3.peer_tmp);
s->s3.peer_tmp = NULL;
-#endif
if (alg_k & SSL_PSK) {
if (!tls_process_ske_psk_preamble(s, pkt)) {
}
if (SSL_USE_SIGALGS(s))
OSSL_TRACE1(TLS, "USING TLSv1.2 HASH %s\n",
- md == NULL ? "n/a" : EVP_MD_name(md));
+ md == NULL ? "n/a" : EVP_MD_get0_name(md));
if (!PACKET_get_length_prefixed_2(pkt, &signature)
|| PACKET_remaining(pkt) != 0) {
}
if (EVP_DigestVerifyInit_ex(md_ctx, &pctx,
- md == NULL ? NULL : EVP_MD_name(md),
- s->ctx->libctx, s->ctx->propq, pkey) <= 0) {
+ md == NULL ? NULL : EVP_MD_get0_name(md),
+ s->ctx->libctx, s->ctx->propq, pkey,
+ NULL) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
s->s3.tmp.ctype_len = 0;
OPENSSL_free(s->pha_context);
s->pha_context = NULL;
+ s->pha_context_len = 0;
if (!PACKET_get_length_prefixed_1(pkt, &reqctx) ||
!PACKET_memdup(&reqctx, &s->pha_context, &s->pha_context_len)) {
s->session = new_sess;
}
- /*
- * Technically the cast to long here is not guaranteed by the C standard -
- * but we use it elsewhere, so this should be ok.
- */
- s->session->time = (long)time(NULL);
+ s->session->time = time(NULL);
+ ssl_session_calculate_timeout(s->session);
OPENSSL_free(s->session->ext.tick);
s->session->ext.tick = NULL;
goto err;
}
/*
- * TODO(size_t): we use sess_len here because EVP_Digest expects an int
+ * We use sess_len here because EVP_Digest expects an int
* but s->session->session_id_length is a size_t
*/
if (!EVP_Digest(s->session->ext.tick, ticklen,
/* This is a standalone message in TLSv1.3, so there is no more to read */
if (SSL_IS_TLS13(s)) {
const EVP_MD *md = ssl_handshake_md(s);
- int hashleni = EVP_MD_size(md);
+ int hashleni = EVP_MD_get_size(md);
size_t hashlen;
static const unsigned char nonce_label[] = "resumption";
}
s->ext.ocsp.resp = OPENSSL_malloc(resplen);
if (s->ext.ocsp.resp == NULL) {
+ s->ext.ocsp.resp_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
return 0;
}
+ s->ext.ocsp.resp_len = resplen;
if (!PACKET_copy_bytes(pkt, s->ext.ocsp.resp, resplen)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
- s->ext.ocsp.resp_len = resplen;
return 1;
}
return 0;
}
if (ret < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_R_OCSP_CALLBACK_FAILURE);
return 0;
}
}
}
#ifndef OPENSSL_NO_SRP
if (s->s3.tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
- if (SRP_Calc_A_param(s) <= 0) {
+ if (ssl_srp_calc_a_param_intern(s) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_SRP_A_CALC);
return MSG_PROCESS_ERROR;
}
if (psklen > PSK_MAX_PSK_LEN) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, ERR_R_INTERNAL_ERROR);
+ psklen = PSK_MAX_PSK_LEN; /* Avoid overrunning the array on cleanse */
goto err;
} else if (psklen == 0) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_PSK_IDENTITY_NOT_FOUND);
pms[0] = s->client_version >> 8;
pms[1] = s->client_version & 0xff;
- /* TODO(size_t): Convert this function */
- if (RAND_bytes_ex(s->ctx->libctx, pms + 2, (int)(pmslen - 2)) <= 0) {
+ if (RAND_bytes_ex(s->ctx->libctx, pms + 2, pmslen - 2, 0) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
* stack, we need to zero pad the DHE pub key to the same length
* as the prime.
*/
- prime_len = EVP_PKEY_size(ckey);
+ prime_len = EVP_PKEY_get_size(ckey);
pad_len = prime_len - encoded_pub_len;
if (pad_len > 0) {
if (!WPACKET_sub_allocate_bytes_u16(pkt, pad_len, &keybytes)) {
static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt)
{
-#ifndef OPENSSL_NO_EC
unsigned char *encodedPoint = NULL;
size_t encoded_pt_len = 0;
EVP_PKEY *ckey = NULL, *skey = NULL;
OPENSSL_free(encodedPoint);
EVP_PKEY_free(ckey);
return ret;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
}
static int tls_construct_cke_gost(SSL *s, WPACKET *pkt)
if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0
/* Generate session key
- * TODO(size_t): Convert this function
*/
- || RAND_bytes_ex(s->ctx->libctx, pms, (int)pmslen) <= 0) {
+ || RAND_bytes_ex(s->ctx->libctx, pms, pmslen, 0) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
};
}
#ifndef OPENSSL_NO_GOST
-int gost18_cke_cipher_nid(const SSL *s)
+int ossl_gost18_cke_cipher_nid(const SSL *s)
{
if ((s->s3.tmp.new_cipher->algorithm_enc & SSL_MAGMA) != 0)
return NID_magma_ctr;
return NID_undef;
}
-int gost_ukm(const SSL *s, unsigned char *dgst_buf)
+int ossl_gost_ukm(const SSL *s, unsigned char *dgst_buf)
{
EVP_MD_CTX * hash = NULL;
unsigned int md_len;
unsigned char *pms = NULL;
size_t pmslen = 0;
size_t msglen;
- int cipher_nid = gost18_cke_cipher_nid(s);
+ int cipher_nid = ossl_gost18_cke_cipher_nid(s);
if (cipher_nid == NID_undef) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
- if (gost_ukm(s, rnd_dgst) <= 0) {
+ if (ossl_gost_ukm(s, rnd_dgst) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
goto err;
}
- if (RAND_bytes_ex(s->ctx->libctx, pms, (int)pmslen) <= 0) {
+ if (RAND_bytes_ex(s->ctx->libctx, pms, pmslen, 0) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
return 0;
}
- if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0 ) {
+ if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
};
err:
OPENSSL_clear_free(s->s3.tmp.pms, s->s3.tmp.pmslen);
s->s3.tmp.pms = NULL;
+ s->s3.tmp.pmslen = 0;
#ifndef OPENSSL_NO_PSK
OPENSSL_clear_free(s->s3.tmp.psk, s->s3.tmp.psklen);
s->s3.tmp.psk = NULL;
+ s->s3.tmp.psklen = 0;
#endif
return 0;
}
err:
OPENSSL_clear_free(pms, pmslen);
s->s3.tmp.pms = NULL;
+ s->s3.tmp.pmslen = 0;
return 0;
}
return 0;
}
-#ifndef OPENSSL_NO_EC
if (clu->amask & SSL_aECDSA) {
if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s))
return 1;
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_BAD_ECC_CERT);
return 0;
}
-#endif
+
if (alg_k & (SSL_kRSA | SSL_kRSAPSK) && idx != SSL_PKEY_RSA) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_MISSING_RSA_ENCRYPTING_CERT);
return 0;
}
-#ifndef OPENSSL_NO_DH
+
if ((alg_k & SSL_kDHE) && (s->s3.peer_tmp == NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
-#endif
return 1;
}