uint16_t epoch,
unsigned char *secret,
size_t secretlen,
+ unsigned char *snkey,
unsigned char *key,
size_t keylen,
unsigned char *iv,
size_t ivlen,
unsigned char *mackey,
size_t mackeylen,
+ const EVP_CIPHER *snciph,
+ size_t snoffs,
const EVP_CIPHER *ciph,
size_t taglen,
int mactype,
/* Special value for method supporting multiple versions */
# define DTLS_ANY_VERSION 0x1FFFF
-/* lengths of messages */
+/* DTLS records and messages lengths and offsets */
# define DTLS1_COOKIE_LENGTH 255
+# define DTLS1_RT_HEADER_SEQ_OFFS 5
# define DTLS1_RT_HEADER_LENGTH 13
# define DTLS1_HM_HEADER_LENGTH 12
* Reset the record layer - but this time we can use the record we just
* buffered in s->rlayer.rrlnext
*/
- if (!ssl_set_new_record_layer(s,
- DTLS_ANY_VERSION,
+ if (!ssl_set_new_record_layer(s, DTLS_ANY_VERSION,
OSSL_RECORD_DIRECTION_READ,
OSSL_RECORD_PROTECTION_LEVEL_NONE, NULL, 0,
- NULL, 0, NULL, 0, NULL, 0, NULL, 0,
- NID_undef, NULL, NULL, NULL)) {
+ NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL,
+ 0, NID_undef, NULL, NULL, NULL)) {
/* SSLfatal already called */
ret = -1;
goto end;
quic_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
int role, int direction, int level, uint16_t epoch,
unsigned char *secret, size_t secretlen,
- unsigned char *key, size_t keylen, unsigned char *iv,
- size_t ivlen, unsigned char *mackey, size_t mackeylen,
+ unsigned char *snkey, unsigned char *key, size_t keylen,
+ unsigned char *iv, size_t ivlen,
+ unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *snciph, size_t snoffs,
const EVP_CIPHER *ciph, size_t taglen,
int mactype,
const EVP_MD *md, COMP_METHOD *comp,
return 0;
}
+/* rfc9147 section 4.2.3 */
+int dtls_crypt_sequence_number(EVP_CIPHER_CTX *ctx, unsigned char *seq,
+ unsigned char *rec_data, size_t rec_data_offs)
+{
+ unsigned char mask[16];
+ int outlen, inlen;
+ unsigned char *iv, *in;
+ size_t i;
+ size_t seq_len = 6;
+
+ if (ossl_assert(sizeof(mask) > rec_data_offs))
+ inlen = (int)(sizeof(mask) - rec_data_offs);
+ else
+ return 0;
+
+ iv = rec_data_offs == 0 ? NULL : rec_data;
+ in = rec_data + rec_data_offs;
+ memset(mask, 0, sizeof(mask));
+
+ if (!ossl_assert(inlen >= 0)
+ || (size_t)inlen > sizeof(mask)
+ || EVP_CipherInit_ex2(ctx, NULL, NULL, iv, 1, NULL) <= 0
+ || EVP_CipherUpdate(ctx, mask, &outlen, in, inlen) <= 0
+ || outlen != inlen
+ || EVP_CipherFinal_ex(ctx, mask + outlen, &outlen) <= 0
+ || outlen != 0)
+ return 0;
+
+ for (i = 0; i < seq_len; i++)
+ seq[i] ^= mask[i];
+
+ OPENSSL_cleanse(mask, sizeof(mask));
+
+ return 1;
+}
+
/*-
* Call this to get a new input record.
* It will return <= 0 if more data is needed, normally due to an error
/* set state for later operations */
rl->rstate = SSL_ST_READ_HEADER;
+ /*
+ * rfc9147:
+ * This procedure requires the ciphertext length to be at least 16 bytes.
+ * Receivers MUST reject shorter records as if they had failed deprotection
+ * TODO(DTLSv1.3): This check will need to be modified when support for variable
+ * length headers is added.
+ */
+ if (rl->sn_enc_ctx != NULL
+ && (rl->packet_length < DTLS1_RT_HEADER_LENGTH + 16
+ || !dtls_crypt_sequence_number(rl->sn_enc_ctx, &(rl->sequence[2]),
+ rl->packet + DTLS1_RT_HEADER_LENGTH,
+ rl->sn_enc_offs))) {
+ /* sequence number encryption failed dump record */
+ rr->length = 0;
+ rl->packet_length = 0;
+ goto again;
+ }
+
/* match epochs. NULL means the packet is dropped on the floor */
bitmap = dtls_get_bitmap(rl, rr, &is_next_epoch);
if (bitmap == NULL) {
dtls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
int role, int direction, int level, uint16_t epoch,
unsigned char *secret, size_t secretlen,
- unsigned char *key, size_t keylen, unsigned char *iv,
- size_t ivlen, unsigned char *mackey, size_t mackeylen,
+ unsigned char *snkey, unsigned char *key, size_t keylen,
+ unsigned char *iv, size_t ivlen,
+ unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *snciph, size_t snoffs,
const EVP_CIPHER *ciph, size_t taglen,
int mactype,
const EVP_MD *md, COMP_METHOD *comp,
goto err;
}
- ret = (*retrl)->funcs->set_crypto_state(*retrl, level, key, keylen, iv,
- ivlen, mackey, mackeylen, ciph,
- taglen, mactype, md, comp);
+ ret = (*retrl)->funcs->set_crypto_state(*retrl, level, snkey, key, keylen,
+ iv, ivlen, mackey, mackeylen,
+ snciph, snoffs, ciph, taglen, mactype, md,
+ comp);
err:
if (ret != OSSL_RECORD_RETURN_SUCCESS) {
#endif /* OPENSSL_SYS_LINUX */
static int ktls_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
+ unsigned char *snkey,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *snciph, size_t snoffs,
const EVP_CIPHER *ciph,
size_t taglen,
int mactype,
ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
int role, int direction, int level, uint16_t epoch,
unsigned char *secret, size_t secretlen,
- unsigned char *key, size_t keylen, unsigned char *iv,
- size_t ivlen, unsigned char *mackey, size_t mackeylen,
+ unsigned char *snkey, unsigned char *key, size_t keylen,
+ unsigned char *iv, size_t ivlen,
+ unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *snciph, size_t snoffs,
const EVP_CIPHER *ciph, size_t taglen,
int mactype,
const EVP_MD *md, COMP_METHOD *comp,
(*retrl)->funcs = &ossl_ktls_funcs;
- ret = (*retrl)->funcs->set_crypto_state(*retrl, level, key, keylen, iv,
- ivlen, mackey, mackeylen, ciph,
- taglen, mactype, md, comp);
+ ret = (*retrl)->funcs->set_crypto_state(*retrl, level, snkey, key, keylen,
+ iv, ivlen, mackey, mackeylen,
+ snciph, snoffs, ciph, taglen, mactype, md,
+ comp);
if (ret != OSSL_RECORD_RETURN_SUCCESS) {
OPENSSL_free(*retrl);
* alternative record layer.
*/
int (*set_crypto_state)(OSSL_RECORD_LAYER *rl, int level,
+ unsigned char *snkey,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *snciph, size_t snoffs,
const EVP_CIPHER *ciph,
size_t taglen,
int mactype,
/* cryptographic state */
EVP_CIPHER_CTX *enc_ctx;
+ /* cryptographic state for DTLS sequence numbers */
+ EVP_CIPHER_CTX *sn_enc_ctx;
+ size_t sn_enc_offs;
/* TLSv1.3 MAC ctx, only used with integrity-only cipher */
EVP_MAC_CTX *mac_ctx;
int tls_default_read_n(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
int clearold, size_t *readbytes);
int tls_get_more_records(OSSL_RECORD_LAYER *rl);
+
+int dtls_crypt_sequence_number(EVP_CIPHER_CTX *ctx, unsigned char *seq,
+ unsigned char *rec_data, size_t rec_data_offs);
int dtls_get_more_records(OSSL_RECORD_LAYER *rl);
int dtls_prepare_record_header(OSSL_RECORD_LAYER *rl,
#include "recmethod_local.h"
static int ssl3_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
+ unsigned char *snkey,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *snciph, size_t snoffs,
const EVP_CIPHER *ciph,
size_t taglen,
int mactype,
#include "recmethod_local.h"
static int tls13_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
+ unsigned char *snkey,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *snciph, size_t snoffs,
const EVP_CIPHER *ciph,
size_t taglen,
int mactype,
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return OSSL_RECORD_RETURN_FATAL;
}
+
+ if (rl->isdtls && snciph != NULL) {
+ EVP_CIPHER_CTX *sn_ciph_ctx;
+
+ sn_ciph_ctx = rl->sn_enc_ctx = EVP_CIPHER_CTX_new();
+
+ if (sn_ciph_ctx == NULL) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
+ return OSSL_RECORD_RETURN_FATAL;
+ }
+
+ rl->sn_enc_offs = snoffs;
+
+ if (EVP_CIPHER_CTX_set_padding(sn_ciph_ctx, 0)
+ || EVP_CipherInit_ex(sn_ciph_ctx, snciph, NULL,
+ snkey, NULL, 1) <= 0) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
+ return OSSL_RECORD_RETURN_FATAL;
+ }
+ }
+
end:
return OSSL_RECORD_RETURN_SUCCESS;
}
#include "recmethod_local.h"
static int tls1_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
+ unsigned char *snkey,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *snciph, size_t snoffs,
const EVP_CIPHER *ciph,
size_t taglen,
int mactype,
tls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
int role, int direction, int level, uint16_t epoch,
unsigned char *secret, size_t secretlen,
- unsigned char *key, size_t keylen, unsigned char *iv,
- size_t ivlen, unsigned char *mackey, size_t mackeylen,
+ unsigned char *snkey, unsigned char *key, size_t keylen,
+ unsigned char *iv, size_t ivlen,
+ unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *snciph, size_t snoffs,
const EVP_CIPHER *ciph, size_t taglen,
int mactype,
const EVP_MD *md, COMP_METHOD *comp,
goto err;
}
- ret = (*retrl)->funcs->set_crypto_state(*retrl, level, key, keylen, iv,
- ivlen, mackey, mackeylen, ciph,
- taglen, mactype, md, comp);
+ ret = (*retrl)->funcs->set_crypto_state(*retrl, level, snkey, key, keylen,
+ iv, ivlen, mackey, mackeylen,
+ snciph, snoffs, ciph, taglen, mactype, md,
+ comp);
err:
if (ret != OSSL_RECORD_RETURN_SUCCESS) {
tls_release_write_buffer(rl);
EVP_CIPHER_CTX_free(rl->enc_ctx);
+ EVP_CIPHER_CTX_free(rl->sn_enc_ctx);
EVP_MAC_CTX_free(rl->mac_ctx);
EVP_MD_CTX_free(rl->md_ctx);
#ifndef OPENSSL_NO_COMP
return 0;
}
+ if (rl->sn_enc_ctx != NULL) {
+ unsigned char *recordstart;
+
+ recordstart = WPACKET_get_curr(thispkt) - len - headerlen;
+
+ if (!dtls_crypt_sequence_number(rl->sn_enc_ctx, recordstart + DTLS1_RT_HEADER_SEQ_OFFS,
+ recordstart + DTLS1_RT_HEADER_LENGTH,
+ rl->sn_enc_offs)) {
+ RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+
if (rl->msg_callback != NULL) {
unsigned char *recordstart;
const int version1_3 = rl->isdtls ? DTLS1_3_VERSION : TLS1_3_VERSION;
#define MIN_SSL2_RECORD_LEN 9
static int tls_any_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
+ unsigned char *snkey,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *snciph, size_t snoffs,
const EVP_CIPHER *ciph,
size_t taglen,
int mactype,
? DTLS_ANY_VERSION : TLS_ANY_VERSION,
OSSL_RECORD_DIRECTION_READ,
OSSL_RECORD_PROTECTION_LEVEL_NONE, NULL, 0,
- NULL, 0, NULL, 0, NULL, 0, NULL, 0,
- NID_undef, NULL, NULL, NULL);
+ NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL,
+ 0, NID_undef, NULL, NULL, NULL);
ret &= ssl_set_new_record_layer(rl->s,
SSL_CONNECTION_IS_DTLS(rl->s)
? DTLS_ANY_VERSION : TLS_ANY_VERSION,
OSSL_RECORD_DIRECTION_WRITE,
OSSL_RECORD_PROTECTION_LEVEL_NONE, NULL, 0,
- NULL, 0, NULL, 0, NULL, 0, NULL, 0,
- NID_undef, NULL, NULL, NULL);
+ NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL,
+ 0, NID_undef, NULL, NULL, NULL);
/* SSLfatal already called in the event of failure */
return ret;
int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
int direction, int level,
unsigned char *secret, size_t secretlen,
+ unsigned char *snkey,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *snciph, size_t snoffs,
const EVP_CIPHER *ciph, size_t taglen,
int mactype, const EVP_MD *md,
const SSL_COMP *comp, const EVP_MD *kdfdigest)
rlret = meth->new_record_layer(sctx->libctx, sctx->propq, version,
s->server, direction, level, epoch,
- secret, secretlen, key, keylen, iv,
- ivlen, mackey, mackeylen, ciph, taglen,
- mactype, md, compm, kdfdigest, prev,
+ secret, secretlen, snkey, key, keylen,
+ iv,
+ ivlen, mackey, mackeylen, snciph, snoffs, ciph,
+ taglen, mactype, md, compm, kdfdigest,
+ prev,
thisbio, next, NULL, NULL, settings,
options, rlayer_dispatch_tmp, s,
s->rlayer.rlarg, &newrl);
int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
int direction, int level,
unsigned char *secret, size_t secretlen,
+ unsigned char *snkey,
unsigned char *key, size_t keylen,
- unsigned char *iv, size_t ivlen,
+ unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *snciph, size_t snoffs,
const EVP_CIPHER *ciph, size_t taglen,
int mactype, const EVP_MD *md,
const SSL_COMP *comp, const EVP_MD *kdfdigest);
goto err;
}
- if (!ssl_set_new_record_layer(s, SSL3_VERSION,
- direction,
+ if (!ssl_set_new_record_layer(s, SSL3_VERSION, direction,
OSSL_RECORD_PROTECTION_LEVEL_APPLICATION,
- NULL, 0, key, key_len, iv, iv_len, mac_secret,
- md_len, ciph, 0, NID_undef, md, comp, NULL)) {
+ NULL, 0, NULL, key, key_len, iv, iv_len,
+ mac_secret, md_len, NULL, 0, ciph, 0, NID_undef,
+ md, comp, NULL)) {
/* SSLfatal already called */
goto err;
}
if (s->s3.tmp.key_block_length != 0)
return 1;
- if (!ssl_cipher_get_evp(SSL_CONNECTION_GET_CTX(s), s->session, &c, &hash,
- NULL, NULL, &comp, 0)) {
+ if (!ssl_cipher_get_evp(SSL_CONNECTION_GET_CTX(s), s->session, NULL, NULL, &c,
+ &hash, NULL, NULL, &comp, 0)) {
/* Error is already recorded */
SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
return 0;
sc->s3.tmp.pkey = NULL;
ssl_evp_cipher_free(sc->s3.tmp.new_sym_enc);
+ ssl_evp_cipher_free(sc->s3.tmp.new_sym_enc_sn);
ssl_evp_md_free(sc->s3.tmp.new_hash);
OPENSSL_free(sc->s3.tmp.ctype);
return 1;
}
+int ssl_cipher_get_evp_cipher_sn(SSL_CTX *ctx, const SSL_CIPHER *sslc,
+ const EVP_CIPHER **enc, size_t *inputoffs)
+{
+ int i = ssl_cipher_info_lookup(ssl_cipher_table_cipher, sslc->algorithm_enc);
+
+ if (i == -1) {
+ *enc = NULL;
+ } else {
+ if (i == SSL_ENC_NULL_IDX) {
+ /*
+ * We assume we don't care about this coming from an ENGINE so
+ * just do a normal EVP_CIPHER_fetch instead of
+ * ssl_evp_cipher_fetch()
+ */
+ *enc = EVP_CIPHER_fetch(ctx->libctx, "NULL", ctx->propq);
+ } else {
+ int ecbnid = NID_undef;
+
+ *enc = NULL;
+
+ if ((sslc->algorithm_enc & SSL_AES128_ANY) != 0) {
+ ecbnid = NID_aes_128_ecb;
+ *inputoffs = 0;
+ } else if ((sslc->algorithm_enc & SSL_AES256_ANY) != 0) {
+ ecbnid = NID_aes_256_ecb;
+ *inputoffs = 0;
+ } else if (ossl_assert((sslc->algorithm_enc & SSL_CHACHA20) != 0)) {
+ ecbnid = NID_chacha20;
+ *inputoffs = 4;
+ }
+
+ if (ecbnid != NID_undef)
+ *enc = ssl_evp_cipher_fetch(ctx->libctx, ecbnid, ctx->propq);
+ }
+
+ if (*enc == NULL)
+ return 0;
+ }
+ return 1;
+}
+
int ssl_cipher_get_evp(SSL_CTX *ctx, const SSL_SESSION *s,
- const EVP_CIPHER **enc, const EVP_MD **md,
+ const EVP_CIPHER **snenc, size_t *snencoffs,
+ const EVP_CIPHER **enc,
+ const EVP_MD **md,
int *mac_pkey_type, size_t *mac_secret_size,
SSL_COMP **comp, int use_etm)
{
if ((enc == NULL) || (md == NULL))
return 0;
- if (!ssl_cipher_get_evp_cipher(ctx, c, enc))
+ if (!ssl_cipher_get_evp_cipher(ctx, c, enc)
+ || (snenc != NULL
+ && !ssl_cipher_get_evp_cipher_sn(ctx, c, snenc, snencoffs)))
return 0;
if (!ssl_cipher_get_evp_md_mac(ctx, c, md, mac_pkey_type,
mac_secret_size)) {
ssl_evp_cipher_free(*enc);
+
+ if (snenc != NULL)
+ ssl_evp_cipher_free(*snenc);
+
return 0;
}
# define SSL_AESGCM (SSL_AES128GCM | SSL_AES256GCM)
# define SSL_AESCCM (SSL_AES128CCM | SSL_AES256CCM | SSL_AES128CCM8 | SSL_AES256CCM8)
# define SSL_AES (SSL_AES128|SSL_AES256|SSL_AESGCM|SSL_AESCCM)
+# define SSL_AES128_ANY (SSL_AES128 | SSL_AES128CCM | SSL_AES128CCM8 \
+ | SSL_AES128GCM)
+# define SSL_AES256_ANY (SSL_AES256 | SSL_AES256CCM | SSL_AES256CCM8 \
+ | SSL_AES256GCM)
# define SSL_CAMELLIA (SSL_CAMELLIA128|SSL_CAMELLIA256)
# define SSL_CHACHA20 (SSL_CHACHA20POLY1305)
# define SSL_ARIAGCM (SSL_ARIA128GCM | SSL_ARIA256GCM)
size_t key_block_length;
unsigned char *key_block;
const EVP_CIPHER *new_sym_enc;
+ const EVP_CIPHER *new_sym_enc_sn;
+ size_t new_sym_enc_sn_offs;
const EVP_MD *new_hash;
int new_mac_pkey_type;
size_t new_mac_secret_size;
void ssl_update_cache(SSL_CONNECTION *s, int mode);
__owur int ssl_cipher_get_evp_cipher(SSL_CTX *ctx, const SSL_CIPHER *sslc,
const EVP_CIPHER **enc);
+__owur int ssl_cipher_get_evp_cipher_sn(SSL_CTX *ctx, const SSL_CIPHER *sslc,
+ const EVP_CIPHER **enc, size_t *inputoffs);
__owur int ssl_cipher_get_evp_md_mac(SSL_CTX *ctx, const SSL_CIPHER *sslc,
const EVP_MD **md,
int *mac_pkey_type, size_t *mac_secret_size);
-__owur int ssl_cipher_get_evp(SSL_CTX *ctxc, const SSL_SESSION *s,
- const EVP_CIPHER **enc, const EVP_MD **md,
+__owur int ssl_cipher_get_evp(SSL_CTX *ctx, const SSL_SESSION *s,
+ const EVP_CIPHER **snenc, size_t *snencoffs,
+ const EVP_CIPHER **enc,
+ const EVP_MD **md,
int *mac_pkey_type, size_t *mac_secret_size,
SSL_COMP **comp, int use_etm);
__owur int ssl_cipher_get_overhead(const SSL_CIPHER *c, size_t *mac_overhead,
if (x->compress_meth != 0) {
SSL_COMP *comp = NULL;
- if (!ssl_cipher_get_evp(NULL, x, NULL, NULL, NULL, NULL, &comp, 0))
+ if (!ssl_cipher_get_evp(NULL, x, NULL, NULL, NULL, NULL, NULL, NULL, &comp, 0))
goto err;
if (comp == NULL) {
if (BIO_printf(bp, "\n Compression: %d", x->compress_meth) <= 0)
TLS_ANY_VERSION,
OSSL_RECORD_DIRECTION_WRITE,
OSSL_RECORD_PROTECTION_LEVEL_NONE,
- NULL, 0, NULL, 0, NULL, 0, NULL, 0,
- NULL, 0, NID_undef, NULL, NULL,
- NULL)) {
+ NULL, 0, NULL, NULL, 0, NULL, 0,
+ NULL, 0, NULL, 0, NULL, 0, NID_undef,
+ NULL, NULL, NULL)) {
/* SSLfatal already called */
return WORK_ERROR;
}
&& !ssl_set_new_record_layer(s, versionany,
OSSL_RECORD_DIRECTION_WRITE,
OSSL_RECORD_PROTECTION_LEVEL_NONE,
- NULL, 0, NULL, 0, NULL, 0, NULL, 0,
- NULL, 0, NID_undef, NULL, NULL, NULL)) {
+ NULL, 0, NULL, NULL, 0, NULL, 0, NULL,
+ 0, NULL, 0, NULL, 0, NID_undef, NULL,
+ NULL, NULL)) {
/* SSLfatal already called */
goto err;
}
dtls1_increment_epoch(s, which);
if (!ssl_set_new_record_layer(s, s->version, direction,
- OSSL_RECORD_PROTECTION_LEVEL_APPLICATION,
- NULL, 0, key, cl, iv, (size_t)k, mac_secret,
- mac_secret_size, c, taglen, mac_type,
- m, comp, NULL)) {
+ OSSL_RECORD_PROTECTION_LEVEL_APPLICATION,
+ NULL, 0, NULL, key, cl, iv, (size_t)k,
+ mac_secret, mac_secret_size, NULL, 0, c, taglen,
+ mac_type, m, comp, NULL)) {
/* SSLfatal already called */
goto err;
}
if (s->s3.tmp.key_block_length != 0)
return 1;
- if (!ssl_cipher_get_evp(SSL_CONNECTION_GET_CTX(s), s->session, &c, &hash,
- &mac_type, &mac_secret_size, &comp,
+ if (!ssl_cipher_get_evp(SSL_CONNECTION_GET_CTX(s), s->session, NULL, NULL, &c,
+ &hash, &mac_type, &mac_secret_size, &comp,
s->ext.use_etm)) {
/* Error is already recorded */
SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
sizeof(finishedlabel) - 1, NULL, 0, fin, finlen, 1);
}
+/*
+ * Given a |secret| generate a |snkey| of length |snkeylen| bytes. Returns 1 on
+ * success 0 on failure. (rfc9147 section 4.2.3)
+ */
+static int dtls13_derive_snkey(SSL_CONNECTION *s, const EVP_MD *md,
+ const unsigned char *secret,
+ unsigned char *snkey, size_t keylen)
+{
+ /* ASCII: "sn", in hex for EBCDIC compatibility */
+ static const unsigned char sn_str[] = "\x73\x6E";
+
+ return tls13_hkdf_expand(s, md, secret, sn_str, sizeof(sn_str) - 1,
+ NULL, 0, snkey, keylen, 1);
+}
+
/*
* Given the previous secret |prevsecret| and a new input secret |insecret| of
* length |insecretlen|, generate a new secret and store it in the location
int tls13_setup_key_block(SSL_CONNECTION *s)
{
const EVP_CIPHER *c;
+ const EVP_CIPHER *snc = NULL, **p_snc = SSL_CONNECTION_IS_DTLS(s) ? &snc : NULL;
+ size_t snoffs;
const EVP_MD *hash;
int mac_type = NID_undef;
size_t mac_secret_size = 0;
s->session->cipher = s->s3.tmp.new_cipher;
- if (!ssl_cipher_get_evp(SSL_CONNECTION_GET_CTX(s), s->session, &c, &hash,
- &mac_type, &mac_secret_size, NULL, 0)) {
+ if (!ssl_cipher_get_evp(SSL_CONNECTION_GET_CTX(s), s->session, p_snc, &snoffs, &c,
+ &hash, &mac_type, &mac_secret_size, NULL, 0)) {
/* Error is already recorded */
SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
return 0;
ssl_evp_cipher_free(s->s3.tmp.new_sym_enc);
s->s3.tmp.new_sym_enc = c;
+ ssl_evp_cipher_free(s->s3.tmp.new_sym_enc_sn);
+ s->s3.tmp.new_sym_enc_sn = snc;
+ s->s3.tmp.new_sym_enc_sn_offs = snoffs;
ssl_evp_md_free(s->s3.tmp.new_hash);
s->s3.tmp.new_hash = hash;
s->s3.tmp.new_mac_pkey_type = mac_type;
const unsigned char *hash,
const unsigned char *label,
size_t labellen, unsigned char *secret,
+ unsigned char *snkey,
unsigned char *key, size_t *keylen,
unsigned char **iv, size_t *ivlen,
size_t *taglen)
}
if (!tls13_derive_key(s, md, secret, key, *keylen)
- || !tls13_derive_iv(s, md, secret, *iv, *ivlen)) {
+ || !tls13_derive_iv(s, md, secret, *iv, *ivlen)
+ || (SSL_CONNECTION_IS_DTLS(s)
+ && !dtls13_derive_snkey(s, md, secret, snkey, *keylen))) {
/* SSLfatal() already called */
return 0;
}
unsigned char iv_intern[EVP_MAX_IV_LENGTH];
unsigned char *iv = iv_intern;
unsigned char key[EVP_MAX_KEY_LENGTH];
+ unsigned char snkey[EVP_MAX_KEY_LENGTH];
+ size_t sn_input_offs = 0;
unsigned char secret[EVP_MAX_MD_SIZE];
unsigned char hashval[EVP_MAX_MD_SIZE];
unsigned char *hash = hashval;
size_t labellen, hashlen = 0;
int ret = 0;
const EVP_MD *md = NULL, *mac_md = NULL;
- const EVP_CIPHER *cipher = NULL;
+ const EVP_CIPHER *cipher = NULL, *sncipher = NULL;
int mac_pkey_type = NID_undef;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
size_t keylen, ivlen = EVP_MAX_IV_LENGTH, taglen;
* This ups the ref count on cipher so we better make sure we free
* it again
*/
- if (!ssl_cipher_get_evp_cipher(sctx, sslcipher, &cipher)) {
+ if (!ssl_cipher_get_evp_cipher(sctx, sslcipher, &cipher)
+ || (SSL_CONNECTION_IS_DTLS(s)
+ && !ssl_cipher_get_evp_cipher_sn(sctx, sslcipher, &sncipher,
+ &sn_input_offs))) {
/* Error is already recorded */
SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
goto err;
if ((which & SSL3_CC_EARLY) == 0) {
md = ssl_handshake_md(s);
cipher = s->s3.tmp.new_sym_enc;
+ sncipher = s->s3.tmp.new_sym_enc_sn;
+ sn_input_offs = s->s3.tmp.new_sym_enc_sn_offs;
mac_md = s->s3.tmp.new_hash;
mac_pkey_type = s->s3.tmp.new_mac_pkey_type;
if (!ssl3_digest_cached_records(s, 1)
goto err;
if (!derive_secret_key_and_iv(s, md, cipher, mac_pkey_type, mac_md,
- insecret, hash, label, labellen, secret, key,
- &keylen, &iv, &ivlen, &taglen)) {
+ insecret, hash, label, labellen, secret,
+ snkey, key, &keylen, &iv, &ivlen, &taglen)) {
/* SSLfatal() already called */
goto err;
}
}
}
- if (!ssl_set_new_record_layer(s, s->version,
- direction,
- level, secret, hashlen, key, keylen, iv,
- ivlen, NULL, 0, cipher, taglen,
+ if (!ssl_set_new_record_layer(s, s->version, direction, level, secret,
+ hashlen, snkey, key, keylen, iv, ivlen,
+ NULL, 0, sncipher, sn_input_offs, cipher, taglen,
mac_pkey_type, mac_md, NULL, md)) {
/* SSLfatal already called */
goto err;
if ((EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) == 0)
ssl_evp_md_free(mac_md);
ssl_evp_cipher_free(cipher);
+ ssl_evp_cipher_free(sncipher);
}
OPENSSL_cleanse(key, sizeof(key));
+ OPENSSL_cleanse(snkey, sizeof(snkey));
OPENSSL_cleanse(secret, sizeof(secret));
if (iv != iv_intern)
OPENSSL_free(iv);
const EVP_MD *md = ssl_handshake_md(s);
size_t hashlen;
unsigned char key[EVP_MAX_KEY_LENGTH];
+ unsigned char snkey[EVP_MAX_KEY_LENGTH];
unsigned char *insecret;
unsigned char secret[EVP_MAX_MD_SIZE];
char *log_label;
s->s3.tmp.new_mac_pkey_type, s->s3.tmp.new_hash,
insecret, NULL,
application_traffic,
- sizeof(application_traffic) - 1, secret, key,
- &keylen, &iv, &ivlen, &taglen)) {
+ sizeof(application_traffic) - 1, secret, snkey,
+ key, &keylen, &iv, &ivlen, &taglen)) {
/* SSLfatal() already called */
goto err;
}
if (SSL_CONNECTION_IS_DTLS(s))
dtls1_increment_epoch(s, which);
- if (!ssl_set_new_record_layer(s, s->version,
- direction,
- OSSL_RECORD_PROTECTION_LEVEL_APPLICATION,
- insecret, hashlen, key, keylen, iv, ivlen, NULL, 0,
- s->s3.tmp.new_sym_enc, taglen, NID_undef, NULL,
- NULL, md)) {
+ if (!ssl_set_new_record_layer(s, s->version, direction,
+ OSSL_RECORD_PROTECTION_LEVEL_APPLICATION,
+ insecret, hashlen, snkey, key, keylen,
+ iv, ivlen, NULL, 0,
+ s->s3.tmp.new_sym_enc_sn, s->s3.tmp.new_sym_enc_sn_offs,
+ s->s3.tmp.new_sym_enc,
+ taglen, NID_undef, NULL, NULL, md)) {
/* SSLfatal already called */
goto err;
}
ret = 1;
err:
OPENSSL_cleanse(key, sizeof(key));
+ OPENSSL_cleanse(snkey, sizeof(snkey));
OPENSSL_cleanse(secret, sizeof(secret));
if (iv != iv_intern)
OPENSSL_free(iv);
NULL, NULL, TLS1_3_VERSION, OSSL_RECORD_ROLE_SERVER,
OSSL_RECORD_DIRECTION_WRITE,
OSSL_RECORD_PROTECTION_LEVEL_APPLICATION, 0, NULL, 0,
- key, 16, iv, ivlen, NULL, 0, EVP_aes_128_gcm(),
+ NULL, key, 16, iv, ivlen, NULL, 0, NULL, 0,
+ EVP_aes_128_gcm(),
EVP_GCM_TLS_TAG_LEN, 0, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
&wrl)))
NULL, NULL, TLS1_3_VERSION, OSSL_RECORD_ROLE_SERVER,
OSSL_RECORD_DIRECTION_READ,
OSSL_RECORD_PROTECTION_LEVEL_APPLICATION, 0, NULL, 0,
- key, 16, iv, ivlen, NULL, 0, EVP_aes_128_gcm(),
+ NULL, key, 16, iv, ivlen, NULL, 0, NULL, 0,
+ EVP_aes_128_gcm(),
EVP_GCM_TLS_TAG_LEN, 0, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
&rrl)))
return EVP_sha256();
}
+int ssl_cipher_get_evp_cipher_sn(SSL_CTX *ctx, const SSL_CIPHER *sslc,
+ const EVP_CIPHER **enc, size_t *inputoffs) {
+ return 0;
+}
+
int ssl_cipher_get_evp_cipher(SSL_CTX *ctx, const SSL_CIPHER *sslc,
const EVP_CIPHER **enc)
{
}
int ssl_cipher_get_evp(SSL_CTX *ctx, const SSL_SESSION *s,
- const EVP_CIPHER **enc, const EVP_MD **md,
+ const EVP_CIPHER **snenc, size_t *snencoffs,
+ const EVP_CIPHER **enc,
+ const EVP_MD **md,
int *mac_pkey_type, size_t *mac_secret_size,
SSL_COMP **comp, int use_etm)
int ssl_set_new_record_layer(SSL_CONNECTION *s, int version, int direction,
int level, unsigned char *secret, size_t secretlen,
+ unsigned char *snkey,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *snciph, size_t snoffs,
const EVP_CIPHER *ciph, size_t taglen,
int mactype, const EVP_MD *md,
const SSL_COMP *comp, const EVP_MD *kdfdigest)