From 6da2bfbafdce6ef876fe8645a01da835831f1f2a Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 18 Apr 2020 18:42:12 +0300 Subject: [PATCH 87/87] ssl: add support for TLSTREE rekeying CTR-OMAC ciphersuites use TLSTREE rekeying to change keys regularly. Handle TLSTREE rekeying for those ciphersuites. Sponsored by ROSA Linux Signed-off-by: Dmitry Baryshkov --- src/lib/libssl/s3_lib.c | 18 +++++++++++++++-- src/lib/libssl/ssl.h | 6 ++++++ src/lib/libssl/ssl_lib.c | 14 +++++++++++++ src/lib/libssl/ssl_locl.h | 4 ++++ src/lib/libssl/t1_enc.c | 42 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 82 insertions(+), 2 deletions(-) diff --git a/src/lib/libssl/s3_lib.c b/src/lib/libssl/s3_lib.c index ba87e9101..2636cfd4f 100644 --- a/src/lib/libssl/s3_lib.c +++ b/src/lib/libssl/s3_lib.c @@ -169,6 +169,18 @@ */ #define FIXED_NONCE_LEN(x) (((x / 2) & 0xf) << 24) +static const TLSTREE_CONST tlstree_magma_ctr_omac = { + .c1 = UINT64_C(0xFFFFFFC000000000), + .c2 = UINT64_C(0xFFFFFFFFFE000000), + .c3 = UINT64_C(0xFFFFFFFFFFFFF000), +}; + +static const TLSTREE_CONST tlstree_kuznyechik_ctr_omac = { + .c1 = UINT64_C(0xFFFFFFFF00000000), + .c2 = UINT64_C(0xFFFFFFFFFFF80000), + .c3 = UINT64_C(0xFFFFFFFFFFFFFFC0), +}; + /* list of available SSLv3 ciphers (sorted by id) */ SSL_CIPHER ssl3_ciphers[] = { @@ -1318,7 +1330,8 @@ SSL_CIPHER ssl3_ciphers[] = { .algo_strength = SSL_HIGH, .algorithm2 = SSL_HANDSHAKE_MAC_STREEBOG256|TLS1_PRF_STREEBOG256|TLS1_NONCE_ADD_SEQUENCE, .strength_bits = 256, - .alg_bits = 256 + .alg_bits = 256, + .tlstree = &tlstree_kuznyechik_ctr_omac, }, /* Cipher C101 */ @@ -1334,7 +1347,8 @@ SSL_CIPHER ssl3_ciphers[] = { .algo_strength = SSL_HIGH, .algorithm2 = SSL_HANDSHAKE_MAC_STREEBOG256|TLS1_PRF_STREEBOG256|TLS1_NONCE_ADD_SEQUENCE, .strength_bits = 256, - .alg_bits = 256 + .alg_bits = 256, + .tlstree = &tlstree_magma_ctr_omac, }, /* Cipher C102 */ diff --git a/src/lib/libssl/ssl.h b/src/lib/libssl/ssl.h index 1c5e174b8..a9f414224 100644 --- a/src/lib/libssl/ssl.h +++ b/src/lib/libssl/ssl.h @@ -153,6 +153,8 @@ #include +#include + #ifndef OPENSSL_NO_DEPRECATED #include #include @@ -397,6 +399,10 @@ struct ssl_cipher_st { unsigned long algorithm2; /* Extra flags */ int strength_bits; /* Number of bits really used */ int alg_bits; /* Number of bits for algorithm */ + +#ifndef OPENSSL_NO_GOST + const TLSTREE_CONST *tlstree; /* TLSTREE parameters */ +#endif }; diff --git a/src/lib/libssl/ssl_lib.c b/src/lib/libssl/ssl_lib.c index c989d802c..a54c01dc7 100644 --- a/src/lib/libssl/ssl_lib.c +++ b/src/lib/libssl/ssl_lib.c @@ -2545,6 +2545,13 @@ ssl_clear_cipher_read_state(SSL *s) free(s->internal->aead_read_ctx); s->internal->aead_read_ctx = NULL; } + +#ifndef OPENSSL_NO_GOST + if (S3I(s)->read.tlstree_cipher != NULL) + TLSTREE_CTX_free(S3I(s)->read.tlstree_cipher); + if (S3I(s)->read.tlstree_mac != NULL) + TLSTREE_CTX_free(S3I(s)->read.tlstree_mac); +#endif } void @@ -2561,6 +2568,13 @@ ssl_clear_cipher_write_state(SSL *s) free(s->internal->aead_write_ctx); s->internal->aead_write_ctx = NULL; } + +#ifndef OPENSSL_NO_GOST + if (S3I(s)->write.tlstree_cipher != NULL) + TLSTREE_CTX_free(S3I(s)->write.tlstree_cipher); + if (S3I(s)->write.tlstree_mac != NULL) + TLSTREE_CTX_free(S3I(s)->write.tlstree_mac); +#endif } /* Fix this function so that it takes an optional type parameter */ diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h index dc291ae4f..6871b01a9 100644 --- a/src/lib/libssl/ssl_locl.h +++ b/src/lib/libssl/ssl_locl.h @@ -811,6 +811,10 @@ typedef struct ssl3_rw_state_internal_st { unsigned char mac_secret[EVP_MAX_MD_SIZE]; int cipher_iv_size; unsigned char cipher_iv[EVP_MAX_IV_LENGTH]; +#ifndef OPENSSL_NO_GOST + TLSTREE_CTX *tlstree_cipher; + TLSTREE_CTX *tlstree_mac; +#endif } SSL3_RW_STATE_INTERNAL; typedef struct ssl3_state_internal_st { diff --git a/src/lib/libssl/t1_enc.c b/src/lib/libssl/t1_enc.c index 7ed6825a1..a4219599d 100644 --- a/src/lib/libssl/t1_enc.c +++ b/src/lib/libssl/t1_enc.c @@ -411,6 +411,7 @@ tls1_change_cipher_state_cipher(SSL *s, char is_read, const EVP_MD *mac; const EVP_CIPHER *mac_cipher; int mac_type; + SSL3_RW_STATE_INTERNAL *rws; cipher = S3I(s)->tmp.new_sym_enc; mac = S3I(s)->tmp.new_hash; @@ -426,6 +427,7 @@ tls1_change_cipher_state_cipher(SSL *s, char is_read, if ((mac_ctx = EVP_MD_CTX_new()) == NULL) goto err; s->read_hash = mac_ctx; + rws = &S3I(s)->read; } else { /* * DTLS fragments retain a pointer to the compression, cipher @@ -443,6 +445,7 @@ tls1_change_cipher_state_cipher(SSL *s, char is_read, if ((mac_ctx = EVP_MD_CTX_new()) == NULL) goto err; s->internal->write_hash = mac_ctx; + rws = &S3I(s)->write; } EVP_CipherInit_ex(cipher_ctx, cipher, NULL, key, iv, !is_read); @@ -465,6 +468,24 @@ tls1_change_cipher_state_cipher(SSL *s, char is_read, else s->internal->write_mac_size = mac_size; +#ifndef OPENSSL_NO_GOST + if (s->session->cipher->tlstree) { + rws->tlstree_cipher = TLSTREE_CTX_new(); + rws->tlstree_mac = TLSTREE_CTX_new(); + if (rws->tlstree_cipher == NULL || + rws->tlstree_mac == NULL || + !TLSTREE_Init(rws->tlstree_cipher, + s->session->cipher->tlstree, + EVP_streebog256(), NULL, + key, key_len) || + !TLSTREE_Init(rws->tlstree_mac, + s->session->cipher->tlstree, + EVP_streebog256(), NULL, + mac_secret, mac_secret_size)) + goto err; + } +#endif + if (S3I(s)->hs.new_cipher->algorithm_enc == SSL_eGOST2814789CNT) { int nid; if (S3I(s)->hs.new_cipher->algorithm2 & SSL_HANDSHAKE_MAC_GOST94) @@ -904,6 +925,14 @@ tls1_enc(SSL *s, int send) return 0; } +#ifndef OPENSSL_NO_GOST + if (rws->tlstree_cipher != NULL) { + unsigned char tmp[EVP_MAX_KEY_LENGTH]; + if (!TLSTREE_GET(rws->tlstree_cipher, rws->sequence, tmp) || + !EVP_CipherInit_ex(ds, NULL, NULL, tmp, NULL, -1)) + return 0; + } +#endif if (add_nonce) { unsigned char new_iv[EVP_MAX_IV_LENGTH]; int iv_size = rws->cipher_iv_size; @@ -974,6 +1003,7 @@ tls1_mac(SSL *ssl, unsigned char *md, int send) int stream_mac = ssl->session && ssl->session->cipher ? ssl->session->cipher->algorithm2 & TLS1_STREAM_MAC : 0; + SSL3_RW_STATE_INTERNAL *rws; int t; if (send) { @@ -981,11 +1011,13 @@ tls1_mac(SSL *ssl, unsigned char *md, int send) seq = &(ssl->s3->internal->write.sequence[0]); hash = ssl->internal->write_hash; t = ssl->internal->write_mac_size; + rws = &S3I(ssl)->write; } else { rec = &(ssl->s3->internal->rrec); seq = &(ssl->s3->internal->read.sequence[0]); hash = ssl->read_hash; t = ssl->read_mac_size; + rws = &S3I(ssl)->read; } OPENSSL_assert(t >= 0); @@ -1028,6 +1060,16 @@ tls1_mac(SSL *ssl, unsigned char *md, int send) ssl->s3->internal->read.mac_secret_size)) return -1; } else { +#ifndef OPENSSL_NO_GOST + if (rws->tlstree_mac != NULL) { + unsigned char tmp[EVP_MAX_KEY_LENGTH]; + if (mac_ctx->pctx == NULL || + !TLSTREE_GET(rws->tlstree_mac, seq, tmp) || + EVP_PKEY_CTX_ctrl(mac_ctx->pctx, -1, EVP_PKEY_OP_SIGNCTX, + EVP_PKEY_CTRL_SET_MAC_KEY, rws->mac_secret_size, tmp) <= 0) + return -1; + } +#endif EVP_DigestSignUpdate(mac_ctx, header, sizeof(header)); EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length); t = EVP_DigestSignFinal(mac_ctx, md, &md_size); -- 2.17.1