From a7c432fd088bbf6bc256fe96236c8e0a01322de5 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 17 Apr 2020 23:14:53 +0300 Subject: [PATCH 85/87] ssl: support IV increments for GOST CTR-OMAC ciphersuites CTR-OMAC ciphersuites are defined so that for each record cipher IV is set to the one generated by key_block incremented by record's sequece number. Support handling this in the encryption layer. Signed-off-by: Dmitry Baryshkov --- src/lib/libssl/s3_lib.c | 4 ++-- src/lib/libssl/ssl_locl.h | 3 +++ src/lib/libssl/ssl_pkt.c | 7 +++++++ src/lib/libssl/t1_enc.c | 38 +++++++++++++++++++++++++++++--------- 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/lib/libssl/s3_lib.c b/src/lib/libssl/s3_lib.c index 106a2567a..ba87e9101 100644 --- a/src/lib/libssl/s3_lib.c +++ b/src/lib/libssl/s3_lib.c @@ -1316,7 +1316,7 @@ SSL_CIPHER ssl3_ciphers[] = { .algorithm_mac = SSL_KUZNYECHIK_OMAC, .algorithm_ssl = SSL_TLSV1_2, .algo_strength = SSL_HIGH, - .algorithm2 = SSL_HANDSHAKE_MAC_STREEBOG256|TLS1_PRF_STREEBOG256, + .algorithm2 = SSL_HANDSHAKE_MAC_STREEBOG256|TLS1_PRF_STREEBOG256|TLS1_NONCE_ADD_SEQUENCE, .strength_bits = 256, .alg_bits = 256 }, @@ -1332,7 +1332,7 @@ SSL_CIPHER ssl3_ciphers[] = { .algorithm_mac = SSL_MAGMA_OMAC, .algorithm_ssl = SSL_TLSV1_2, .algo_strength = SSL_HIGH, - .algorithm2 = SSL_HANDSHAKE_MAC_STREEBOG256|TLS1_PRF_STREEBOG256, + .algorithm2 = SSL_HANDSHAKE_MAC_STREEBOG256|TLS1_PRF_STREEBOG256|TLS1_NONCE_ADD_SEQUENCE, .strength_bits = 256, .alg_bits = 256 }, diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h index f4ad6b5ee..dc291ae4f 100644 --- a/src/lib/libssl/ssl_locl.h +++ b/src/lib/libssl/ssl_locl.h @@ -288,6 +288,7 @@ __BEGIN_HIDDEN_DECLS * (currently this also goes into algorithm2). */ #define TLS1_STREAM_MAC 0x04 +#define TLS1_NONCE_ADD_SEQUENCE 0x02 /* * SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_IN_RECORD is an algorithm2 flag that @@ -808,6 +809,8 @@ typedef struct ssl3_rw_state_internal_st { unsigned char sequence[SSL3_SEQUENCE_SIZE]; int mac_secret_size; unsigned char mac_secret[EVP_MAX_MD_SIZE]; + int cipher_iv_size; + unsigned char cipher_iv[EVP_MAX_IV_LENGTH]; } SSL3_RW_STATE_INTERNAL; typedef struct ssl3_state_internal_st { diff --git a/src/lib/libssl/ssl_pkt.c b/src/lib/libssl/ssl_pkt.c index 23a5509c3..e1cb249df 100644 --- a/src/lib/libssl/ssl_pkt.c +++ b/src/lib/libssl/ssl_pkt.c @@ -485,6 +485,7 @@ ssl3_get_record(SSL *s) } i = tls1_mac(s,md,0 /* not send */); + tls1_record_sequence_increment(S3I(s)->read.sequence); if (i < 0 || mac == NULL || timingsafe_memcmp(md, mac, (size_t)mac_size) != 0) enc_err = -1; @@ -702,6 +703,12 @@ ssl3_create_record(SSL *s, unsigned char *p, int type, const unsigned char *buf, /* tls1_enc can only have an error on read */ tls1_enc(s, 1); + /* Increment sequence after encrypting so that tls1_enc can use seq for + * nonce calculation */ + if (mac_size != 0) { + tls1_record_sequence_increment(S3I(s)->write.sequence); + } + /* record length after mac and block padding */ if (!CBB_add_u16(&cbb, wr->length)) goto err; diff --git a/src/lib/libssl/t1_enc.c b/src/lib/libssl/t1_enc.c index 4c726f73f..7ed6825a1 100644 --- a/src/lib/libssl/t1_enc.c +++ b/src/lib/libssl/t1_enc.c @@ -571,6 +571,8 @@ tls1_change_cipher_state(SSL *s, int which) memcpy(rws->mac_secret, mac_secret, mac_secret_size); rws->mac_secret_size = mac_secret_size; + memcpy(rws->cipher_iv, iv, iv_len); + rws->cipher_iv_size = iv_len; if (aead != NULL) { return tls1_change_cipher_state_aead(s, is_read, key, key_len, @@ -680,18 +682,21 @@ tls1_enc(SSL *s, int send) const EVP_CIPHER *enc; EVP_CIPHER_CTX *ds; SSL3_RECORD_INTERNAL *rec; - unsigned char *seq; + SSL3_RW_STATE_INTERNAL *rws; unsigned long l; int bs, i, j, k, ret, mac_size = 0; + int add_nonce = s->session && s->session->cipher ? + s->session->cipher->algorithm2 & TLS1_NONCE_ADD_SEQUENCE: + 0; if (send) { aead = s->internal->aead_write_ctx; rec = &S3I(s)->wrec; - seq = S3I(s)->write.sequence; + rws = &S3I(s)->write; } else { aead = s->internal->aead_read_ctx; rec = &S3I(s)->rrec; - seq = S3I(s)->read.sequence; + rws = &S3I(s)->read; } if (aead) { @@ -700,11 +705,11 @@ tls1_enc(SSL *s, int send) unsigned int nonce_used; if (SSL_IS_DTLS(s)) { - dtls1_build_sequence_number(ad, seq, + dtls1_build_sequence_number(ad, rws->sequence, send ? D1I(s)->w_epoch : D1I(s)->r_epoch); } else { - memcpy(ad, seq, SSL3_SEQUENCE_SIZE); - tls1_record_sequence_increment(seq); + memcpy(ad, rws->sequence, SSL3_SEQUENCE_SIZE); + tls1_record_sequence_increment(rws->sequence); } ad[8] = rec->type; @@ -899,6 +904,24 @@ tls1_enc(SSL *s, int send) return 0; } + if (add_nonce) { + unsigned char new_iv[EVP_MAX_IV_LENGTH]; + int iv_size = rws->cipher_iv_size; + unsigned char cf = 0, tmp; + + for (i = 1; i <= iv_size; i++) { + tmp = new_iv[iv_size - i] = + rws->cipher_iv[iv_size - i] + rws->sequence[SSL3_SEQUENCE_SIZE - i] + cf; + if (tmp != rws->cipher_iv[iv_size - i]) + cf = (tmp < rws->cipher_iv[iv_size - i]); + } + + if (!EVP_CipherInit_ex(ds, NULL, NULL, NULL, new_iv, -1)) { + SSLerror(s, ERR_R_EVP_LIB); + return -1; + } + } + i = EVP_Cipher(ds, rec->data, rec->input, l); if ((EVP_CIPHER_flags(ds->cipher) & EVP_CIPH_FLAG_CUSTOM_CIPHER) ? (i < 0) : (i == 0)) @@ -1014,9 +1037,6 @@ tls1_mac(SSL *ssl, unsigned char *md, int send) if (!stream_mac) EVP_MD_CTX_cleanup(&hmac); - if (!SSL_IS_DTLS(ssl)) - tls1_record_sequence_increment(seq); - return (md_size); } -- 2.17.1