/* Only used by SSLv3 */
unsigned char mac_secret[EVP_MAX_MD_SIZE];
+ /* TLSv1.3 static IV */
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+
+ size_t taglen;
+
/* Function pointers for version specific functions */
/* Function pointers for version specific functions */
struct record_functions_st *funcs;
return 1;
}
-static int tls_fail_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
- unsigned char *key, size_t keylen,
- unsigned char *iv, size_t ivlen,
- unsigned char *mackey, size_t mackeylen,
- const EVP_CIPHER *ciph,
- size_t taglen,
- /* TODO(RECLAYER): This probably should not be an int */
- int mactype,
- const EVP_MD *md,
- const SSL_COMP *comp,
- /* TODO(RECLAYER): Remove me */
- SSL_CONNECTION *s)
-{
- RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
-}
-
static int tls_any_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
return 1;
}
+static int tls13_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
+ unsigned char *key, size_t keylen,
+ unsigned char *iv, size_t ivlen,
+ unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *ciph,
+ size_t taglen,
+ /* TODO(RECLAYER): This probably should not be an int */
+ int mactype,
+ const EVP_MD *md,
+ const SSL_COMP *comp,
+ /* TODO(RECLAYER): Remove me */
+ SSL_CONNECTION *s)
+{
+ EVP_CIPHER_CTX *ciph_ctx;
+ int mode;
+
+ if (ivlen > sizeof(rl->iv)) {
+ RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ memcpy(rl->iv, iv, ivlen);
+
+ ciph_ctx = rl->enc_read_ctx = EVP_CIPHER_CTX_new();
+ if (ciph_ctx == NULL) {
+ RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ RECORD_LAYER_reset_read_sequence(&s->rlayer);
+ rl->taglen = taglen;
+
+ mode = EVP_CIPHER_get_mode(ciph);
+
+ if (EVP_DecryptInit_ex(ciph_ctx, ciph, NULL, NULL, NULL) <= 0
+ || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL)
+ || (mode == EVP_CIPH_CCM_MODE
+ && !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG, taglen, NULL))
+ || EVP_DecryptInit_ex(ciph_ctx, NULL, NULL, key, NULL) <= 0) {
+ RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ return 0;
+ }
+
+ return 1;
+}
+
static int tls_any_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, size_t n_recs,
int sending, SSL_MAC_BUF *macs, size_t macsize,
/* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s)
return 1;
}
+static int tls13_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, size_t n_recs,
+ int sending, SSL_MAC_BUF *mac, size_t macsize,
+ /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s)
+{
+ EVP_CIPHER_CTX *ctx;
+ unsigned char iv[EVP_MAX_IV_LENGTH], recheader[SSL3_RT_HEADER_LENGTH];
+ size_t ivlen, offset, loop, hdrlen;
+ unsigned char *staticiv;
+ unsigned char *seq;
+ int lenu, lenf;
+ SSL3_RECORD *rec = &recs[0];
+ WPACKET wpkt;
+ const EVP_CIPHER *cipher;
+ int mode;
+
+ if (n_recs != 1) {
+ /* Should not happen */
+ RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (sending) {
+ ctx = s->enc_write_ctx;
+ staticiv = s->write_iv;
+ seq = RECORD_LAYER_get_write_sequence(&s->rlayer);
+ } else {
+ ctx = rl->enc_read_ctx;
+ staticiv = rl->iv;
+ seq = RECORD_LAYER_get_read_sequence(&s->rlayer);
+ }
+
+ cipher = EVP_CIPHER_CTX_get0_cipher(ctx);
+ if (cipher == NULL) {
+ RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ mode = EVP_CIPHER_get_mode(cipher);
+
+ /*
+ * If we're sending an alert and ctx != NULL then we must be forcing
+ * plaintext alerts. If we're reading and ctx != NULL then we allow
+ * plaintext alerts at certain points in the handshake. If we've got this
+ * far then we have already validated that a plaintext alert is ok here.
+ */
+ if (ctx == NULL || rec->type == SSL3_RT_ALERT) {
+ memmove(rec->data, rec->input, rec->length);
+ rec->input = rec->data;
+ return 1;
+ }
+
+ ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
+
+ if (!sending) {
+ /*
+ * Take off tag. There must be at least one byte of content type as
+ * well as the tag
+ */
+ if (rec->length < rl->taglen + 1)
+ return 0;
+ rec->length -= rl->taglen;
+ }
+
+ /* Set up IV */
+ if (ivlen < SEQ_NUM_SIZE) {
+ /* Should not happen */
+ RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ offset = ivlen - SEQ_NUM_SIZE;
+ memcpy(iv, staticiv, offset);
+ for (loop = 0; loop < SEQ_NUM_SIZE; loop++)
+ iv[offset + loop] = staticiv[offset + loop] ^ seq[loop];
+
+ /* Increment the sequence counter */
+ for (loop = SEQ_NUM_SIZE; loop > 0; loop--) {
+ ++seq[loop - 1];
+ if (seq[loop - 1] != 0)
+ break;
+ }
+ if (loop == 0) {
+ /* Sequence has wrapped */
+ return 0;
+ }
+
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, sending) <= 0
+ || (!sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
+ rl->taglen,
+ rec->data + rec->length) <= 0)) {
+ RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* Set up the AAD */
+ if (!WPACKET_init_static_len(&wpkt, recheader, sizeof(recheader), 0)
+ || !WPACKET_put_bytes_u8(&wpkt, rec->type)
+ || !WPACKET_put_bytes_u16(&wpkt, rec->rec_version)
+ || !WPACKET_put_bytes_u16(&wpkt, rec->length + rl->taglen)
+ || !WPACKET_get_total_written(&wpkt, &hdrlen)
+ || hdrlen != SSL3_RT_HEADER_LENGTH
+ || !WPACKET_finish(&wpkt)) {
+ RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ WPACKET_cleanup(&wpkt);
+ return 0;
+ }
+
+ /*
+ * For CCM we must explicitly set the total plaintext length before we add
+ * any AAD.
+ */
+ if ((mode == EVP_CIPH_CCM_MODE
+ && EVP_CipherUpdate(ctx, NULL, &lenu, NULL,
+ (unsigned int)rec->length) <= 0)
+ || EVP_CipherUpdate(ctx, NULL, &lenu, recheader,
+ sizeof(recheader)) <= 0
+ || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input,
+ (unsigned int)rec->length) <= 0
+ || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0
+ || (size_t)(lenu + lenf) != rec->length) {
+ return 0;
+ }
+ if (sending) {
+ /* Add the tag */
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, rl->taglen,
+ rec->data + rec->length) <= 0) {
+ RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ rec->length += rl->taglen;
+ }
+
+ return 1;
+}
+
static const unsigned char ssl3_pad_1[48] = {
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
return ret;
}
-
struct record_functions_st tls_any_funcs = {
tls_any_set_crypto_state,
tls_any_cipher,
};
struct record_functions_st tls_1_3_funcs = {
- tls_fail_set_crypto_state,
- NULL,
+ tls13_set_crypto_state,
+ tls13_cipher,
NULL
};
}
if (SSL_CONNECTION_IS_TLS13(s)
- && s->enc_read_ctx != NULL
+ && rl->enc_read_ctx != NULL
&& !using_ktls) {
if (thisrr->type != SSL3_RT_APPLICATION_DATA
&& (thisrr->type != SSL3_RT_CHANGE_CIPHER_SPEC
* TODO(RECLAYER): Only call rl functions once TLSv1.3/SSLv3 is moved to new
* record layer code
*/
- if (!SSL_CONNECTION_IS_TLS13(s))
- enc_err = rl->funcs->cipher(rl, rr, num_recs, 0, macbufs, mac_size, s);
- else
- enc_err = ssl->method->ssl3_enc->enc(s, rr, num_recs, 0, macbufs, mac_size);
+ enc_err = rl->funcs->cipher(rl, rr, num_recs, 0, macbufs, mac_size, s);
/*-
* enc_err is:
}
if (SSL_CONNECTION_IS_TLS13(s)
- && s->enc_read_ctx != NULL
+ && rl->enc_read_ctx != NULL
&& thisrr->type != SSL3_RT_ALERT) {
/*
* The following logic are irrelevant in KTLS: the kernel provides
static void tls_free(OSSL_RECORD_LAYER *rl)
{
+ /* TODO(RECLAYER): Cleanse sensitive fields */
BIO_free(rl->bio);
OPENSSL_free(rl);
}
const unsigned char *hash,
const unsigned char *label,
size_t labellen, unsigned char *secret,
- unsigned char *key, unsigned char *iv,
+ unsigned char *key, size_t *keylen,
+ unsigned char *iv, size_t *ivlen,
+ size_t *taglen,
EVP_CIPHER_CTX *ciph_ctx)
{
- size_t ivlen, keylen, taglen;
int hashleni = EVP_MD_get_size(md);
size_t hashlen;
+ int mode;
/* Ensure cast to size_t is safe */
if (!ossl_assert(hashleni >= 0)) {
return 0;
}
- keylen = EVP_CIPHER_get_key_length(ciph);
- if (EVP_CIPHER_get_mode(ciph) == EVP_CIPH_CCM_MODE) {
+ *keylen = EVP_CIPHER_get_key_length(ciph);
+
+ mode = EVP_CIPHER_get_mode(ciph);
+ if (mode == EVP_CIPH_CCM_MODE) {
uint32_t algenc;
- ivlen = EVP_CCM_TLS_IV_LEN;
+ *ivlen = EVP_CCM_TLS_IV_LEN;
if (s->s3.tmp.new_cipher != NULL) {
algenc = s->s3.tmp.new_cipher->algorithm_enc;
} else if (s->session->cipher != NULL) {
return 0;
}
if (algenc & (SSL_AES128CCM8 | SSL_AES256CCM8))
- taglen = EVP_CCM8_TLS_TAG_LEN;
+ *taglen = EVP_CCM8_TLS_TAG_LEN;
else
- taglen = EVP_CCM_TLS_TAG_LEN;
+ *taglen = EVP_CCM_TLS_TAG_LEN;
} else {
- ivlen = EVP_CIPHER_get_iv_length(ciph);
- taglen = 0;
+ if (mode == EVP_CIPH_GCM_MODE) {
+ *taglen = EVP_GCM_TLS_TAG_LEN;
+ } else {
+ /* CHACHA20P-POLY1305 */
+ *taglen = EVP_CHACHAPOLY_TLS_TAG_LEN;
+ }
+ *ivlen = EVP_CIPHER_get_iv_length(ciph);
}
- if (!tls13_derive_key(s, md, secret, key, keylen)
- || !tls13_derive_iv(s, md, secret, iv, ivlen)) {
+ if (!tls13_derive_key(s, md, secret, key, *keylen)
+ || !tls13_derive_iv(s, md, secret, iv, *ivlen)) {
/* SSLfatal() already called */
return 0;
}
- if (EVP_CipherInit_ex(ciph_ctx, ciph, NULL, NULL, NULL, sending) <= 0
- || EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL) <= 0
- || (taglen != 0 && EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG,
- taglen, NULL) <= 0)
- || EVP_CipherInit_ex(ciph_ctx, NULL, NULL, key, NULL, -1) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
- return 0;
+ if (sending) {
+ if (EVP_CipherInit_ex(ciph_ctx, ciph, NULL, NULL, NULL, sending) <= 0
+ || EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, *ivlen, NULL) <= 0
+ || (mode == EVP_CIPH_CCM_MODE
+ && EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG, *taglen, NULL) <= 0)
+ || EVP_CipherInit_ex(ciph_ctx, NULL, NULL, key, NULL, -1) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ return 0;
+ }
}
return 1;
int tls13_change_cipher_state(SSL_CONNECTION *s, int which)
{
#ifdef CHARSET_EBCDIC
- static const unsigned char client_early_traffic[] = {0x63, 0x20, 0x65, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
- static const unsigned char client_handshake_traffic[] = {0x63, 0x20, 0x68, 0x73, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
- static const unsigned char client_application_traffic[] = {0x63, 0x20, 0x61, 0x70, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
- static const unsigned char server_handshake_traffic[] = {0x73, 0x20, 0x68, 0x73, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
- static const unsigned char server_application_traffic[] = {0x73, 0x20, 0x61, 0x70, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
- static const unsigned char exporter_master_secret[] = {0x65, 0x78, 0x70, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
- static const unsigned char resumption_master_secret[] = {0x72, 0x65, 0x73, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
- static const unsigned char early_exporter_master_secret[] = {0x65, 0x20, 0x65, 0x78, 0x70, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
+ static const unsigned char client_early_traffic[] = {0x63, 0x20, 0x65, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
+ static const unsigned char client_handshake_traffic[] = {0x63, 0x20, 0x68, 0x73, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
+ static const unsigned char client_application_traffic[] = {0x63, 0x20, 0x61, 0x70, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
+ static const unsigned char server_handshake_traffic[] = {0x73, 0x20, 0x68, 0x73, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
+ static const unsigned char server_application_traffic[] = {0x73, 0x20, 0x61, 0x70, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
+ static const unsigned char exporter_master_secret[] = {0x65, 0x78, 0x70, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
+ static const unsigned char resumption_master_secret[] = {0x72, 0x65, 0x73, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
+ static const unsigned char early_exporter_master_secret[] = {0x65, 0x20, 0x65, 0x78, 0x70, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
#else
static const unsigned char client_early_traffic[] = "c e traffic";
static const unsigned char client_handshake_traffic[] = "c hs traffic";
unsigned char *insecret;
unsigned char *finsecret = NULL;
const char *log_label = NULL;
- EVP_CIPHER_CTX *ciph_ctx;
+ EVP_CIPHER_CTX *ciph_ctx = NULL;
size_t finsecretlen = 0;
const unsigned char *label;
size_t labellen, hashlen = 0;
const EVP_MD *md = NULL;
const EVP_CIPHER *cipher = NULL;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
+ size_t keylen, ivlen, taglen;
#if !defined(OPENSSL_NO_KTLS) && defined(OPENSSL_KTLS_TLS13)
ktls_crypto_info_t crypto_info;
void *rl_sequence;
#endif
if (which & SSL3_CC_READ) {
- if (s->enc_read_ctx != NULL) {
- EVP_CIPHER_CTX_reset(s->enc_read_ctx);
- } else {
- s->enc_read_ctx = EVP_CIPHER_CTX_new();
- if (s->enc_read_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
- ciph_ctx = s->enc_read_ctx;
iv = s->read_iv;
RECORD_LAYER_reset_read_sequence(&s->rlayer);
if (!derive_secret_key_and_iv(s, which & SSL3_CC_WRITE, md, cipher,
insecret, hash, label, labellen, secret, key,
- iv, ciph_ctx)) {
+ &keylen, iv, &ivlen, &taglen, ciph_ctx)) {
/* SSLfatal() already called */
goto err;
}
s->statem.enc_write_state = ENC_WRITE_STATE_WRITE_PLAIN_ALERTS;
else
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
+
+ if ((which & SSL3_CC_READ) != 0) {
+ int level = (which & SSL3_CC_EARLY) != 0
+ ? OSSL_RECORD_PROTECTION_LEVEL_EARLY
+ : ((which &SSL3_CC_HANDSHAKE) != 0
+ ? OSSL_RECORD_PROTECTION_LEVEL_HANDSHAKE
+ : OSSL_RECORD_PROTECTION_LEVEL_APPLICATION);
+ s->rrlmethod->free(s->rrl);
+ s->rrl = s->rrlmethod->new_record_layer(sctx->libctx,
+ sctx->propq,
+ s->version, s->server,
+ OSSL_RECORD_DIRECTION_READ,
+ level, key, keylen, iv, ivlen,
+ NULL, 0, cipher, taglen,
+ NID_undef, NULL, NULL, s->rbio,
+ NULL, NULL, NULL, NULL, s);
+ if (s->rrl == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+
+
#ifndef OPENSSL_NO_KTLS
# if defined(OPENSSL_KTLS_TLS13)
if (!(which & SSL3_CC_APPLICATION)
unsigned char *insecret, *iv;
unsigned char secret[EVP_MAX_MD_SIZE];
EVP_CIPHER_CTX *ciph_ctx;
+ size_t keylen, ivlen, taglen;
int ret = 0;
+ SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
if (s->server == sending)
insecret = s->server_app_traffic_secret;
s->s3.tmp.new_sym_enc, insecret, NULL,
application_traffic,
sizeof(application_traffic) - 1, secret, key,
- iv, ciph_ctx)) {
+ &keylen, iv, &ivlen, &taglen, ciph_ctx)) {
/* SSLfatal() already called */
goto err;
}
memcpy(insecret, secret, hashlen);
+ if (!sending) {
+ s->rrlmethod->free(s->rrl);
+ s->rrl = s->rrlmethod->new_record_layer(sctx->libctx,
+ sctx->propq,
+ s->version, s->server,
+ OSSL_RECORD_DIRECTION_READ,
+ OSSL_RECORD_PROTECTION_LEVEL_APPLICATION,
+ key, keylen, iv, ivlen,
+ NULL, 0, s->s3.tmp.new_sym_enc,
+ taglen, NID_undef, NULL, NULL,
+ s->rbio, NULL, NULL, NULL, NULL,
+ s);
+ if (s->rrl == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+
+
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
ret = 1;
err: