libressl/0085-ssl-support-IV-increments-for-GOST-CTR-OMAC-ciphersu.patch
Mikhail Novosyolov faac7d3eaa Add gost-new patches sponsored by ROSA Linux
TODO: add tests
2020-08-05 12:58:06 +03:00

177 lines
5.6 KiB
Diff

From a7c432fd088bbf6bc256fe96236c8e0a01322de5 Mon Sep 17 00:00:00 2001
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
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 <dbaryshkov@gmail.com>
---
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