#include <openssl/ocsp.h>
#include <openssl/dh.h>
#include <openssl/async.h>
+#include <openssl/kdf.h>
#include <openssl/ct.h>
#include <openssl/trace.h>
#include <openssl/core_names.h>
goto err;
}
+ if ((ret->hmac = EVP_MAC_fetch(libctx, "HMAC", propq)) == NULL)
+ goto err;
+ if ((ret->sha256 = EVP_MD_fetch(libctx, "SHA2-256", propq)) == NULL)
+ goto err;
+ if ((ret->tktenc = EVP_CIPHER_fetch(libctx, "AES-256-CBC", propq)) == NULL)
+ goto err;
+#if defined(OPENSSL_HAVE_TLS1PRF)
+ if ((ret->tls1prf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_TLS1_PRF, propq)) == NULL)
+ goto err;
+#endif
+
ret->method = meth;
ret->min_proto_version = 0;
ret->max_proto_version = 0;
goto err;
}
- /*
- * If these aren't available from the provider we'll get NULL returns.
- * That's fine but will cause errors later if SSLv3 is negotiated
- */
- ERR_set_mark();
- ret->md5 = EVP_MD_fetch(libctx, "MD5", propq);
- ret->sha1 = EVP_MD_fetch(libctx, "SHA1", propq);
- ERR_pop_to_mark();
-
if ((ret->ca_names = sk_X509_NAME_new_null()) == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
goto err;
if (a->sessions != NULL)
SSL_CTX_flush_sessions_ex(a, 0);
+ EVP_MAC_free(a->hmac);
+ EVP_MD_free(a->sha256);
+ EVP_CIPHER_free(a->tktenc);
+#ifdef OPENSSL_HAVE_TLS1PRF
+ EVP_KDF_free(a->tls1prf);
+#endif
+
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data);
lh_SSL_SESSION_free(a->sessions);
X509_STORE_free(a->cert_store);
OPENSSL_free(a->ext.alpn);
OPENSSL_secure_clear_free(a->ext.secure, sizeof(*a->ext.secure));
- ssl_evp_md_free(a->md5);
- ssl_evp_md_free(a->sha1);
-
for (j = 0; j < SSL_ENC_NUM_IDX; j++)
ssl_evp_cipher_free(a->ssl_cipher_methods[j]);
for (j = 0; j < SSL_MD_NUM_IDX; j++)
#endif
} SSL_HMAC;
-SSL_HMAC *ssl_hmac_new(const SSL_CTX *ctx);
-void ssl_hmac_free(SSL_HMAC *ctx);
+SSL_HMAC *ssl_hmac_construct(const SSL_CTX *ctx, SSL_HMAC *hctx);
+void ssl_hmac_destruct(SSL_HMAC *ctx);
#ifndef OPENSSL_NO_DEPRECATED_3_0
HMAC_CTX *ssl_hmac_get0_HMAC_CTX(SSL_HMAC *ctx);
#endif
#define TLS_GROUP_FFDHE_FOR_TLS1_3 (TLS_GROUP_FFDHE | TLS_GROUP_ONLY_FOR_TLS1_3)
+#if !defined(OPENSSL_NO_TLS1) \
+ || !defined(OPENSSL_NO_TLS1_1) \
+ || !defined(OPENSSL_NO_TLS1_2) \
+ || !defined(OPENSSL_NO_DTLS1) \
+ || !defined(OPENSSL_NO_DTLS1_2)
+#define OPENSSL_HAVE_TLS1PRF
+#endif
+
struct ssl_ctx_st {
OSSL_LIB_CTX *libctx;
STACK_OF(SSL_CIPHER) *tls13_ciphersuites;
struct x509_store_st /* X509_STORE */ *cert_store;
LHASH_OF(SSL_SESSION) *sessions;
+ EVP_MAC *hmac;
+ EVP_MD *sha256;
+ EVP_CIPHER *tktenc;
+#ifdef OPENSSL_HAVE_TLS1PRF
+ EVP_KDF *tls1prf;
+#endif
/*
* Most session-ids that will be cached, default is
* SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited.
int ssl_evp_md_up_ref(const EVP_MD *md);
void ssl_evp_md_free(const EVP_MD *md);
-int ssl_hmac_old_new(SSL_HMAC *ret);
-void ssl_hmac_old_free(SSL_HMAC *ctx);
+SSL_HMAC *ssl_hmac_old_construct(SSL_HMAC *ret);
+void ssl_hmac_old_destruct(SSL_HMAC *ctx);
int ssl_hmac_old_init(SSL_HMAC *ctx, void *key, size_t len, char *md);
int ssl_hmac_old_update(SSL_HMAC *ctx, const unsigned char *data, size_t len);
int ssl_hmac_old_final(SSL_HMAC *ctx, unsigned char *md, size_t *len);
unsigned int sess_len;
RAW_EXTENSION *exts = NULL;
PACKET nonce;
- EVP_MD *sha256 = NULL;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
PACKET_null_init(&nonce);
* We choose the former approach because this fits in with assumptions
* elsewhere in OpenSSL. The session ID is set to the SHA256 hash of the
* ticket.
- */
- sha256 = EVP_MD_fetch(sctx->libctx, "SHA2-256", sctx->propq);
- if (sha256 == NULL) {
- /* Error is already recorded */
- SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
- goto err;
- }
- /*
+ *
* 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,
s->session->session_id, &sess_len,
- sha256, NULL)) {
+ sctx->sha256, NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
- EVP_MD_free(sha256);
- sha256 = NULL;
s->session->session_id_length = sess_len;
s->session->not_resumable = 0;
return MSG_PROCESS_CONTINUE_READING;
err:
- EVP_MD_free(sha256);
OPENSSL_free(exts);
return MSG_PROCESS_ERROR;
}
{
unsigned char *senc = NULL;
EVP_CIPHER_CTX *ctx = NULL;
- SSL_HMAC *hctx = NULL;
+ SSL_HMAC hctx, *constructed_hctx = NULL;
unsigned char *p, *encdata1, *encdata2, *macdata1, *macdata2;
const unsigned char *const_p;
int len, slen_full, slen, lenfinal;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
- hctx = ssl_hmac_new(tctx);
- if (hctx == NULL) {
+ if ((constructed_hctx = ssl_hmac_construct(tctx, &hctx)) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_SSL_LIB);
goto err;
}
if (tctx->ext.ticket_key_evp_cb != NULL)
ret = tctx->ext.ticket_key_evp_cb(ssl, key_name, iv, ctx,
- ssl_hmac_get0_EVP_MAC_CTX(hctx),
+ ssl_hmac_get0_EVP_MAC_CTX(&hctx),
1);
#ifndef OPENSSL_NO_DEPRECATED_3_0
else if (tctx->ext.ticket_key_cb != NULL)
/* if 0 is returned, write an empty ticket */
ret = tctx->ext.ticket_key_cb(ssl, key_name, iv, ctx,
- ssl_hmac_get0_HMAC_CTX(hctx), 1);
+ ssl_hmac_get0_HMAC_CTX(&hctx), 1);
#endif
if (ret == 0) {
}
OPENSSL_free(senc);
EVP_CIPHER_CTX_free(ctx);
- ssl_hmac_free(hctx);
+ ssl_hmac_destruct(constructed_hctx);
return CON_FUNC_SUCCESS;
}
if (ret < 0) {
goto err;
}
} else {
- EVP_CIPHER *cipher = EVP_CIPHER_fetch(sctx->libctx, "AES-256-CBC",
- sctx->propq);
-
- if (cipher == NULL) {
- /* Error is already recorded */
- SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
- goto err;
- }
-
- iv_len = EVP_CIPHER_get_iv_length(cipher);
+ iv_len = EVP_CIPHER_get_iv_length(sctx->tktenc);
if (iv_len < 0
|| RAND_bytes_ex(sctx->libctx, iv, iv_len, 0) <= 0
- || !EVP_EncryptInit_ex(ctx, cipher, NULL,
+ || !EVP_EncryptInit_ex(ctx, sctx->tktenc, NULL,
tctx->ext.secure->tick_aes_key, iv)
- || !ssl_hmac_init(hctx, tctx->ext.secure->tick_hmac_key,
+ || !ssl_hmac_init(&hctx, tctx->ext.secure->tick_hmac_key,
sizeof(tctx->ext.secure->tick_hmac_key),
"SHA256")) {
- EVP_CIPHER_free(cipher);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
- EVP_CIPHER_free(cipher);
memcpy(key_name, tctx->ext.tick_key_name,
sizeof(tctx->ext.tick_key_name));
}
|| encdata1 + len != encdata2
|| len + lenfinal > slen + EVP_MAX_BLOCK_LENGTH
|| !WPACKET_get_total_written(pkt, &macendoffset)
- || !ssl_hmac_update(hctx,
+ || !ssl_hmac_update(&hctx,
(unsigned char *)s->init_buf->data + macoffset,
macendoffset - macoffset)
|| !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &macdata1)
- || !ssl_hmac_final(hctx, macdata1, &hlen, EVP_MAX_MD_SIZE)
+ || !ssl_hmac_final(&hctx, macdata1, &hlen, EVP_MAX_MD_SIZE)
|| hlen > EVP_MAX_MD_SIZE
|| !WPACKET_allocate_bytes(pkt, hlen, &macdata2)
|| macdata1 != macdata2) {
err:
OPENSSL_free(senc);
EVP_CIPHER_CTX_free(ctx);
- ssl_hmac_free(hctx);
+ ssl_hmac_destruct(constructed_hctx);
return ok;
}
unsigned char *out, size_t olen, int fatal)
{
const EVP_MD *md = ssl_prf_md(s);
- EVP_KDF *kdf;
EVP_KDF_CTX *kctx = NULL;
- OSSL_PARAM params[9], *p = params;
- const char *mdname;
if (md == NULL) {
/* Should never happen */
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
- kdf = EVP_KDF_fetch(SSL_CONNECTION_GET_CTX(s)->libctx,
- OSSL_KDF_NAME_TLS1_PRF,
- SSL_CONNECTION_GET_CTX(s)->propq);
- if (kdf == NULL)
- goto err;
- kctx = EVP_KDF_CTX_new(kdf);
- EVP_KDF_free(kdf);
+#ifdef OPENSSL_HAVE_TLS1PRF
+ kctx = EVP_KDF_CTX_new(SSL_CONNECTION_GET_CTX(s)->tls1prf);
if (kctx == NULL)
goto err;
- mdname = EVP_MD_get0_name(md);
+
+ const char *mdname = EVP_MD_get0_name(md);
+ OSSL_PARAM params[9], *p = params;
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
(char *)mdname, 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SECRET,
}
err:
+#endif
if (fatal)
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
else
SSL_TICKET_STATUS ret = SSL_TICKET_FATAL_ERR_OTHER;
size_t mlen;
unsigned char tick_hmac[EVP_MAX_MD_SIZE];
- SSL_HMAC *hctx = NULL;
+ SSL_HMAC hctx, *constructed_hctx = NULL;
EVP_CIPHER_CTX *ctx = NULL;
SSL_CTX *tctx = s->session_ctx;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
}
/* Initialize session ticket encryption and HMAC contexts */
- hctx = ssl_hmac_new(tctx);
- if (hctx == NULL) {
+
+ if ((constructed_hctx = ssl_hmac_construct(tctx, &hctx)) == NULL) {
ret = SSL_TICKET_FATAL_ERR_MALLOC;
goto end;
}
nctick,
nctick + TLSEXT_KEYNAME_LENGTH,
ctx,
- ssl_hmac_get0_EVP_MAC_CTX(hctx),
+ ssl_hmac_get0_EVP_MAC_CTX(&hctx),
0);
#ifndef OPENSSL_NO_DEPRECATED_3_0
else if (tctx->ext.ticket_key_cb != NULL)
/* if 0 is returned, write an empty ticket */
rv = tctx->ext.ticket_key_cb(SSL_CONNECTION_GET_USER_SSL(s), nctick,
nctick + TLSEXT_KEYNAME_LENGTH,
- ctx, ssl_hmac_get0_HMAC_CTX(hctx), 0);
+ ctx, ssl_hmac_get0_HMAC_CTX(&hctx), 0);
#endif
if (rv < 0) {
ret = SSL_TICKET_FATAL_ERR_OTHER;
if (rv == 2)
renew_ticket = 1;
} else {
- EVP_CIPHER *aes256cbc = NULL;
-
/* Check key name matches */
if (memcmp(etick, tctx->ext.tick_key_name,
TLSEXT_KEYNAME_LENGTH)
goto end;
}
- aes256cbc = EVP_CIPHER_fetch(sctx->libctx, "AES-256-CBC",
- sctx->propq);
- if (aes256cbc == NULL
- || ssl_hmac_init(hctx, tctx->ext.secure->tick_hmac_key,
- sizeof(tctx->ext.secure->tick_hmac_key),
- "SHA256")
+ if (ssl_hmac_init(&hctx, tctx->ext.secure->tick_hmac_key,
+ sizeof(tctx->ext.secure->tick_hmac_key), "SHA256")
<= 0
- || EVP_DecryptInit_ex(ctx, aes256cbc, NULL,
+ || EVP_DecryptInit_ex(ctx, tctx->tktenc, NULL,
tctx->ext.secure->tick_aes_key,
etick + TLSEXT_KEYNAME_LENGTH)
<= 0) {
- EVP_CIPHER_free(aes256cbc);
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
- EVP_CIPHER_free(aes256cbc);
if (SSL_CONNECTION_IS_TLS13(s))
renew_ticket = 1;
}
* Attempt to process session ticket, first conduct sanity and integrity
* checks on ticket.
*/
- mlen = ssl_hmac_size(hctx);
+ mlen = ssl_hmac_size(&hctx);
if (mlen == 0) {
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
eticklen -= mlen;
/* Check HMAC of encrypted ticket */
- if (ssl_hmac_update(hctx, etick, eticklen) <= 0
- || ssl_hmac_final(hctx, tick_hmac, NULL, sizeof(tick_hmac)) <= 0) {
+ if (ssl_hmac_update(&hctx, etick, eticklen) <= 0
+ || ssl_hmac_final(&hctx, tick_hmac, NULL, sizeof(tick_hmac)) <= 0) {
ret = SSL_TICKET_FATAL_ERR_OTHER;
goto end;
}
end:
EVP_CIPHER_CTX_free(ctx);
- ssl_hmac_free(hctx);
+ ssl_hmac_destruct(constructed_hctx);
/*
* If set, the decrypt_ticket_cb() is called unless a fatal error was
/*
* Helper functions for HMAC access with legacy support included.
*/
-SSL_HMAC *ssl_hmac_new(const SSL_CTX *ctx)
+SSL_HMAC *ssl_hmac_construct(const SSL_CTX *ctx, SSL_HMAC *hctx)
{
- SSL_HMAC *ret = OPENSSL_zalloc(sizeof(*ret));
- EVP_MAC *mac = NULL;
-
- if (ret == NULL)
+ if (hctx == NULL)
return NULL;
+ hctx->ctx = NULL;
#ifndef OPENSSL_NO_DEPRECATED_3_0
+ hctx->old_ctx = NULL;
if (ctx->ext.ticket_key_evp_cb == NULL
- && ctx->ext.ticket_key_cb != NULL) {
- if (!ssl_hmac_old_new(ret))
- goto err;
- return ret;
- }
+ && ctx->ext.ticket_key_cb != NULL)
+ return ssl_hmac_old_construct(hctx);
#endif
- mac = EVP_MAC_fetch(ctx->libctx, "HMAC", ctx->propq);
- if (mac == NULL || (ret->ctx = EVP_MAC_CTX_new(mac)) == NULL)
- goto err;
- EVP_MAC_free(mac);
- return ret;
-err:
- EVP_MAC_CTX_free(ret->ctx);
- EVP_MAC_free(mac);
- OPENSSL_free(ret);
- return NULL;
+ hctx->ctx = EVP_MAC_CTX_new(ctx->hmac);
+ return hctx->ctx != NULL ? hctx : NULL;
}
-void ssl_hmac_free(SSL_HMAC *ctx)
+void ssl_hmac_destruct(SSL_HMAC *ctx)
{
if (ctx != NULL) {
EVP_MAC_CTX_free(ctx->ctx);
#ifndef OPENSSL_NO_DEPRECATED_3_0
- ssl_hmac_old_free(ctx);
+ ssl_hmac_old_destruct(ctx);
#endif
- OPENSSL_free(ctx);
}
}
* be removed.
*/
#ifndef OPENSSL_NO_DEPRECATED_3_0
-int ssl_hmac_old_new(SSL_HMAC *ret)
+SSL_HMAC *ssl_hmac_old_construct(SSL_HMAC *ret)
{
ret->old_ctx = HMAC_CTX_new();
- if (ret->old_ctx == NULL)
- return 0;
-
- return 1;
+ return ret->old_ctx != NULL ? ret : NULL;
}
-void ssl_hmac_old_free(SSL_HMAC *ctx)
+void ssl_hmac_old_destruct(SSL_HMAC *ctx)
{
HMAC_CTX_free(ctx->old_ctx);
}