[openssl] master update

beldmit at gmail.com beldmit at gmail.com
Tue May 19 10:03:33 UTC 2020


The branch master has been updated
       via  5a5530a29abcf5d7ab7194d73b3807d568b06cbd (commit)
       via  0e139a02d59323e5d9c0ad87ea9c8c3914696b83 (commit)
       via  092a5c71f1cba1173f17c2cd4ff5607069b0d3bb (commit)
      from  5a29b6286f8ccafc2ed9a026b0e8d4bd6d0396e6 (commit)


- Log -----------------------------------------------------------------
commit 5a5530a29abcf5d7ab7194d73b3807d568b06cbd
Author: Dmitry Belyavskiy <beldmit at gmail.com>
Date:   Mon Mar 30 18:09:24 2020 +0300

    New Russian TLS 1.2 implementation
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/11442)

commit 0e139a02d59323e5d9c0ad87ea9c8c3914696b83
Author: Dmitry Belyavskiy <beldmit at gmail.com>
Date:   Fri May 8 14:17:11 2020 +0300

    GOST-related objects changes
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/11442)

commit 092a5c71f1cba1173f17c2cd4ff5607069b0d3bb
Author: Dmitry Belyavskiy <beldmit at gmail.com>
Date:   Mon Mar 30 18:04:07 2020 +0300

    Constants for new GOST TLS 1.2 ciphersuites
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/11442)

-----------------------------------------------------------------------

Summary of changes:
 crypto/err/openssl.txt       |   2 +
 crypto/objects/obj_dat.h     |   9 ++-
 crypto/objects/obj_mac.num   |   1 +
 crypto/objects/objects.txt   |   1 +
 include/openssl/evp.h        |   3 +
 include/openssl/obj_mac.h    |   4 ++
 include/openssl/ssl.h        |   3 +
 include/openssl/sslerr.h     |   4 +-
 ssl/record/ssl3_record.c     |  34 +++++++++-
 ssl/s3_lib.c                 |  48 +++++++++++++--
 ssl/ssl_ciph.c               |  51 ++++++++++++---
 ssl/ssl_err.c                |   4 +-
 ssl/ssl_lib.c                |   4 +-
 ssl/ssl_local.h              |  19 +++++-
 ssl/statem/extensions_srvr.c |   4 +-
 ssl/statem/statem_clnt.c     | 143 +++++++++++++++++++++++++++++++++++++++++++
 ssl/statem/statem_local.h    |   5 ++
 ssl/statem/statem_srvr.c     |  92 ++++++++++++++++++++++++++++
 ssl/t1_enc.c                 |  18 +++++-
 ssl/t1_lib.c                 |  17 ++++-
 ssl/t1_trce.c                |  17 ++++-
 21 files changed, 451 insertions(+), 32 deletions(-)

diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 4451ba95a1..1b2c94b0a2 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -1527,6 +1527,7 @@ SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC:427:tls_construct_change_cipher_spec
 SSL_F_TLS_CONSTRUCT_CKE_DHE:404:tls_construct_cke_dhe
 SSL_F_TLS_CONSTRUCT_CKE_ECDHE:405:tls_construct_cke_ecdhe
 SSL_F_TLS_CONSTRUCT_CKE_GOST:406:tls_construct_cke_gost
+SSL_F_TLS_CONSTRUCT_CKE_GOST18:641:
 SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE:407:tls_construct_cke_psk_preamble
 SSL_F_TLS_CONSTRUCT_CKE_RSA:409:tls_construct_cke_rsa
 SSL_F_TLS_CONSTRUCT_CKE_SRP:410:tls_construct_cke_srp
@@ -1658,6 +1659,7 @@ SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC:363:tls_process_change_cipher_spec
 SSL_F_TLS_PROCESS_CKE_DHE:411:tls_process_cke_dhe
 SSL_F_TLS_PROCESS_CKE_ECDHE:412:tls_process_cke_ecdhe
 SSL_F_TLS_PROCESS_CKE_GOST:413:tls_process_cke_gost
+SSL_F_TLS_PROCESS_CKE_GOST18:642:
 SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE:414:tls_process_cke_psk_preamble
 SSL_F_TLS_PROCESS_CKE_RSA:415:tls_process_cke_rsa
 SSL_F_TLS_PROCESS_CKE_SRP:416:tls_process_cke_srp
diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
index 6fa22174c0..decf33ef9b 100644
--- a/crypto/objects/obj_dat.h
+++ b/crypto/objects/obj_dat.h
@@ -1088,7 +1088,7 @@ static const unsigned char so[7845] = {
     0x2B,0x06,0x01,0x05,0x05,0x07,0x08,0x08,       /* [ 7836] OBJ_NAIRealm */
 };
 
-#define NUM_NID 1218
+#define NUM_NID 1219
 static const ASN1_OBJECT nid_objs[NUM_NID] = {
     {"UNDEF", "undefined", NID_undef},
     {"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]},
@@ -2308,9 +2308,10 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = {
     {"modp_4096", "modp_4096", NID_modp_4096},
     {"modp_6144", "modp_6144", NID_modp_6144},
     {"modp_8192", "modp_8192", NID_modp_8192},
+    {"KxGOST18", "kx-gost18", NID_kx_gost18},
 };
 
-#define NUM_SN 1209
+#define NUM_SN 1210
 static const unsigned int sn_objs[NUM_SN] = {
      364,    /* "AD_DVCS" */
      419,    /* "AES-128-CBC" */
@@ -2489,6 +2490,7 @@ static const unsigned int sn_objs[NUM_SN] = {
     1038,    /* "KxECDHE" */
     1040,    /* "KxECDHE-PSK" */
     1045,    /* "KxGOST" */
+    1218,    /* "KxGOST18" */
     1043,    /* "KxPSK" */
     1037,    /* "KxRSA" */
     1042,    /* "KxRSA_PSK" */
@@ -3523,7 +3525,7 @@ static const unsigned int sn_objs[NUM_SN] = {
     1093,    /* "x509ExtAdmission" */
 };
 
-#define NUM_LN 1209
+#define NUM_LN 1210
 static const unsigned int ln_objs[NUM_LN] = {
      363,    /* "AD Time Stamping" */
      405,    /* "ANSI X9.62" */
@@ -4334,6 +4336,7 @@ static const unsigned int ln_objs[NUM_LN] = {
     1038,    /* "kx-ecdhe" */
     1040,    /* "kx-ecdhe-psk" */
     1045,    /* "kx-gost" */
+    1218,    /* "kx-gost18" */
     1043,    /* "kx-psk" */
     1037,    /* "kx-rsa" */
     1042,    /* "kx-rsa-psk" */
diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num
index aaf77099b3..6d2c0d74a8 100644
--- a/crypto/objects/obj_mac.num
+++ b/crypto/objects/obj_mac.num
@@ -1215,3 +1215,4 @@ modp_3072		1214
 modp_4096		1215
 modp_6144		1216
 modp_8192		1217
+kx_gost18		1218
diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt
index a9ccf7eded..b19454209b 100644
--- a/crypto/objects/objects.txt
+++ b/crypto/objects/objects.txt
@@ -1648,6 +1648,7 @@ id-pkinit 5                     : pkInitKDC             : Signing KDC Response
                             : KxPSK        : kx-psk
                             : KxSRP        : kx-srp
                             : KxGOST       : kx-gost
+                            : KxGOST18     : kx-gost18
                             : KxANY        : kx-any
 
 # NIDs for cipher authentication
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index fe2e440a8b..ea305c2cf0 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -153,6 +153,7 @@ int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd,
 #  define EVP_MD_CTRL_DIGALGID                    0x1
 #  define EVP_MD_CTRL_MICALG                      0x2
 #  define EVP_MD_CTRL_XOF_LEN                     0x3
+#  define EVP_MD_CTRL_TLSTREE                     0x4
 
 /* Minimum Algorithm specific ctrl value */
 
@@ -382,6 +383,8 @@ int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
 # define         EVP_CTRL_PROCESS_UNPROTECTED            0x28
 /* Get the supplementary wrap cipher */
 #define          EVP_CTRL_GET_WRAP_CIPHER                0x29
+/* TLSTREE key diversification */
+#define          EVP_CTRL_TLSTREE                        0x2A
 
 /* Padding modes */
 #define EVP_PADDING_PKCS7       1
diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h
index 0f6741b590..0f9adc9b6a 100644
--- a/include/openssl/obj_mac.h
+++ b/include/openssl/obj_mac.h
@@ -5102,6 +5102,10 @@
 #define LN_kx_gost              "kx-gost"
 #define NID_kx_gost             1045
 
+#define SN_kx_gost18            "KxGOST18"
+#define LN_kx_gost18            "kx-gost18"
+#define NID_kx_gost18           1218
+
 #define SN_kx_any               "KxANY"
 #define LN_kx_any               "kx-any"
 #define NID_kx_any              1063
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 74d4e305e1..05755b014d 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -87,6 +87,7 @@ extern "C" {
 # define SSL_TXT_kECDHEPSK       "kECDHEPSK"
 # define SSL_TXT_kDHEPSK         "kDHEPSK"
 # define SSL_TXT_kGOST           "kGOST"
+# define SSL_TXT_kGOST18         "kGOST18"
 # define SSL_TXT_kSRP            "kSRP"
 
 # define SSL_TXT_aRSA            "aRSA"
@@ -933,6 +934,8 @@ __owur int SSL_extension_supported(unsigned int ext_type);
 
 # define SSL_MAC_FLAG_READ_MAC_STREAM 1
 # define SSL_MAC_FLAG_WRITE_MAC_STREAM 2
+# define SSL_MAC_FLAG_READ_MAC_TLSTREE 4
+# define SSL_MAC_FLAG_WRITE_MAC_TLSTREE 8
 
 /*
  * A callback for logging out TLS key material. This callback should log out
diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h
index 47667f9a0a..bbce792c72 100644
--- a/include/openssl/sslerr.h
+++ b/include/openssl/sslerr.h
@@ -298,6 +298,7 @@ int ERR_load_SSL_strings(void);
 #  define SSL_F_TLS_CONSTRUCT_CKE_DHE                      0
 #  define SSL_F_TLS_CONSTRUCT_CKE_ECDHE                    0
 #  define SSL_F_TLS_CONSTRUCT_CKE_GOST                     0
+#  define SSL_F_TLS_CONSTRUCT_CKE_GOST18                   0
 #  define SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE             0
 #  define SSL_F_TLS_CONSTRUCT_CKE_RSA                      0
 #  define SSL_F_TLS_CONSTRUCT_CKE_SRP                      0
@@ -422,6 +423,7 @@ int ERR_load_SSL_strings(void);
 #  define SSL_F_TLS_PROCESS_CKE_DHE                        0
 #  define SSL_F_TLS_PROCESS_CKE_ECDHE                      0
 #  define SSL_F_TLS_PROCESS_CKE_GOST                       0
+#  define SSL_F_TLS_PROCESS_CKE_GOST18                     0
 #  define SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE               0
 #  define SSL_F_TLS_PROCESS_CKE_RSA                        0
 #  define SSL_F_TLS_PROCESS_CKE_SRP                        0
@@ -457,6 +459,7 @@ int ERR_load_SSL_strings(void);
 /*
  * SSL reason codes.
  */
+# define SSL_R_ALGORITHM_FETCH_FAILED                     295
 # define SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY        291
 # define SSL_R_APP_DATA_IN_HANDSHAKE                      100
 # define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
@@ -556,7 +559,6 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_EXTRA_DATA_IN_MESSAGE                      153
 # define SSL_R_EXT_LENGTH_MISMATCH                        163
 # define SSL_R_FAILED_TO_INIT_ASYNC                       405
-# define SSL_R_ALGORITHM_FETCH_FAILED                     295
 # define SSL_R_FRAGMENTED_CLIENT_HELLO                    401
 # define SSL_R_GOT_A_FIN_BEFORE_A_CCS                     154
 # define SSL_R_HTTPS_PROXY_REQUEST                        155
diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c
index 24b42098db..a2f7f848d1 100644
--- a/ssl/record/ssl3_record.c
+++ b/ssl/record/ssl3_record.c
@@ -977,6 +977,8 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
     unsigned char padval;
     int imac_size;
     const EVP_CIPHER *enc;
+    int tlstree_enc = sending ? (s->mac_flags & SSL_MAC_FLAG_WRITE_MAC_TLSTREE)
+                              : (s->mac_flags & SSL_MAC_FLAG_READ_MAC_TLSTREE);
 
     if (n_recs == 0) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
@@ -1156,6 +1158,27 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
             }
         }
 
+        if (!SSL_IS_DTLS(s) && tlstree_enc) {
+            unsigned char *seq;
+            int decrement_seq = 0;
+
+            /*
+             * When sending, seq is incremented after MAC calculation.
+             * So if we are in ETM mode, we use seq 'as is' in the ctrl-function.
+             * Otherwise we have to decrease it in the implementation
+             */
+            if (sending && !SSL_WRITE_ETM(s))
+                decrement_seq = 1;
+
+            seq = sending ? RECORD_LAYER_get_write_sequence(&s->rlayer)
+                          : RECORD_LAYER_get_read_sequence(&s->rlayer);
+            if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_TLSTREE, decrement_seq, seq) <= 0) {
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
+                         ERR_R_INTERNAL_ERROR);
+              return -1;
+            }
+        }
+
         /* TODO(size_t): Convert this call */
         tmpr = EVP_Cipher(ds, recs[0].data, recs[0].input,
                           (unsigned int)reclen[0]);
@@ -1319,8 +1342,10 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
     int i;
     EVP_MD_CTX *hmac = NULL, *mac_ctx;
     unsigned char header[13];
-    int stream_mac = (sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM)
-                      : (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM));
+    int stream_mac = sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM)
+                             : (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM);
+    int tlstree_mac = sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_TLSTREE)
+                              : (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_TLSTREE);
     int t;
 
     if (sending) {
@@ -1348,6 +1373,11 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
         mac_ctx = hmac;
     }
 
+    if (!SSL_IS_DTLS(ssl) && tlstree_mac && EVP_MD_CTX_ctrl(mac_ctx, EVP_MD_CTRL_TLSTREE, 0, seq) <= 0) {
+        EVP_MD_CTX_free(hmac);
+        return 0;
+    }
+
     if (SSL_IS_DTLS(ssl)) {
         unsigned char dtlsseq[8], *p = dtlsseq;
 
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 2b49e7e51a..054fc468ed 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -2687,6 +2687,38 @@ static SSL_CIPHER ssl3_ciphers[] = {
      0,
      0,
      },
+    {
+     1,
+     "GOST2012-KUZNYECHIK-KUZNYECHIKOMAC",
+     NULL,
+     0x0300C100,
+     SSL_kGOST18,
+     SSL_aGOST12,
+     SSL_KUZNYECHIK,
+     SSL_KUZNYECHIKOMAC,
+     TLS1_2_VERSION, TLS1_2_VERSION,
+     0, 0,
+     SSL_HIGH,
+     SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_TLSTREE,
+     256,
+     256,
+     },
+    {
+     1,
+     "GOST2012-MAGMA-MAGMAOMAC",
+     NULL,
+     0x0300C101,
+     SSL_kGOST18,
+     SSL_aGOST12,
+     SSL_MAGMA,
+     SSL_MAGMAOMAC,
+     TLS1_2_VERSION, TLS1_2_VERSION,
+     0, 0,
+     SSL_HIGH,
+     SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_TLSTREE,
+     256,
+     256,
+     },
 #endif                          /* OPENSSL_NO_GOST */
 
 #ifndef OPENSSL_NO_IDEA
@@ -4374,11 +4406,17 @@ int ssl3_get_req_cert_type(SSL *s, WPACKET *pkt)
 
 #ifndef OPENSSL_NO_GOST
     if (s->version >= TLS1_VERSION && (alg_k & SSL_kGOST))
-            return WPACKET_put_bytes_u8(pkt, TLS_CT_GOST01_SIGN)
-                    && WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_IANA_SIGN)
-                    && WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_IANA_512_SIGN)
-                    && WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_LEGACY_SIGN)
-                    && WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_LEGACY_512_SIGN);
+        if (!WPACKET_put_bytes_u8(pkt, TLS_CT_GOST01_SIGN)
+            || !WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_IANA_SIGN)
+            || !WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_IANA_512_SIGN)
+            || !WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_LEGACY_SIGN)
+            || !WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_LEGACY_512_SIGN))
+            return 0;
+
+    if (s->version >= TLS1_2_VERSION && (alg_k & SSL_kGOST18))
+        if (!WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_IANA_SIGN)
+            || !WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_IANA_512_SIGN))
+            return 0;
 #endif
 
     if ((s->version == SSL3_VERSION) && (alg_k & SSL_kDHE)) {
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 7b3a5e7c89..ec2dabc89a 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -56,6 +56,8 @@ static const ssl_cipher_table ssl_cipher_table_cipher[SSL_ENC_NUM_IDX] = {
     {SSL_CHACHA20POLY1305, NID_chacha20_poly1305}, /* SSL_ENC_CHACHA_IDX 19 */
     {SSL_ARIA128GCM, NID_aria_128_gcm}, /* SSL_ENC_ARIA128GCM_IDX 20 */
     {SSL_ARIA256GCM, NID_aria_256_gcm}, /* SSL_ENC_ARIA256GCM_IDX 21 */
+    {SSL_MAGMA, NID_magma_ctr_acpkm}, /* SSL_ENC_MAGMA_IDX */
+    {SSL_KUZNYECHIK, NID_kuznyechik_ctr_acpkm}, /* SSL_ENC_KUZNYECHIK_IDX */
 };
 
 #define SSL_COMP_NULL_IDX       0
@@ -81,7 +83,9 @@ static const ssl_cipher_table ssl_cipher_table_mac[SSL_MD_NUM_IDX] = {
     {SSL_GOST12_512, NID_id_GostR3411_2012_512}, /* SSL_MD_GOST12_512_IDX 8 */
     {0, NID_md5_sha1},          /* SSL_MD_MD5_SHA1_IDX 9 */
     {0, NID_sha224},            /* SSL_MD_SHA224_IDX 10 */
-    {0, NID_sha512}             /* SSL_MD_SHA512_IDX 11 */
+    {0, NID_sha512},            /* SSL_MD_SHA512_IDX 11 */
+    {SSL_MAGMAOMAC, NID_magma_mac}, /* sSL_MD_MAGMAOMAC_IDX */
+    {SSL_KUZNYECHIKOMAC, NID_kuznyechik_mac} /* SSL_MD_KUZNYECHIKOMAC_IDX */
 };
 
 /* *INDENT-OFF* */
@@ -95,6 +99,7 @@ static const ssl_cipher_table ssl_cipher_table_kx[] = {
     {SSL_kPSK,      NID_kx_psk},
     {SSL_kSRP,      NID_kx_srp},
     {SSL_kGOST,     NID_kx_gost},
+    {SSL_kGOST18,   NID_kx_gost18},
     {SSL_kANY,      NID_kx_any}
 };
 
@@ -138,8 +143,8 @@ static int ssl_mac_pkey_id[SSL_MD_NUM_IDX] = {
     EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC, NID_undef,
     /* GOST2012_512 */
     EVP_PKEY_HMAC,
-    /* MD5/SHA1, SHA224, SHA512 */
-    NID_undef, NID_undef, NID_undef
+    /* MD5/SHA1, SHA224, SHA512, MAGMAOMAC, KUZNYECHIKOMAC */
+    NID_undef, NID_undef, NID_undef, NID_undef, NID_undef
 };
 
 #define CIPHER_ADD      1
@@ -193,6 +198,7 @@ static const SSL_CIPHER cipher_aliases[] = {
     {0, SSL_TXT_kDHEPSK, NULL, 0, SSL_kDHEPSK},
     {0, SSL_TXT_kSRP, NULL, 0, SSL_kSRP},
     {0, SSL_TXT_kGOST, NULL, 0, SSL_kGOST},
+    {0, SSL_TXT_kGOST18, NULL, 0, SSL_kGOST18},
 
     /* server authentication aliases */
     {0, SSL_TXT_aRSA, NULL, 0, 0, SSL_aRSA},
@@ -226,7 +232,8 @@ static const SSL_CIPHER cipher_aliases[] = {
     {0, SSL_TXT_IDEA, NULL, 0, 0, 0, SSL_IDEA},
     {0, SSL_TXT_SEED, NULL, 0, 0, 0, SSL_SEED},
     {0, SSL_TXT_eNULL, NULL, 0, 0, 0, SSL_eNULL},
-    {0, SSL_TXT_GOST, NULL, 0, 0, 0, SSL_eGOST2814789CNT | SSL_eGOST2814789CNT12},
+    {0, SSL_TXT_GOST, NULL, 0, 0, 0,
+     SSL_eGOST2814789CNT | SSL_eGOST2814789CNT12 | SSL_MAGMA | SSL_KUZNYECHIK},
     {0, SSL_TXT_AES128, NULL, 0, 0, 0,
      SSL_AES128 | SSL_AES128GCM | SSL_AES128CCM | SSL_AES128CCM8},
     {0, SSL_TXT_AES256, NULL, 0, 0, 0,
@@ -381,24 +388,38 @@ int ssl_load_ciphers(SSL_CTX *ctx)
      * Check for presence of GOST 34.10 algorithms, and if they are not
      * present, disable appropriate auth and key exchange
      */
-    ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX] = get_optional_pkey_id("gost-mac");
+    ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX] = get_optional_pkey_id(SN_id_Gost28147_89_MAC);
     if (ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX])
         ctx->ssl_mac_secret_size[SSL_MD_GOST89MAC_IDX] = 32;
     else
         disabled_mac_mask |= SSL_GOST89MAC;
 
     ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX] =
-        get_optional_pkey_id("gost-mac-12");
+        get_optional_pkey_id(SN_gost_mac_12);
     if (ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX])
         ctx->ssl_mac_secret_size[SSL_MD_GOST89MAC12_IDX] = 32;
     else
         disabled_mac_mask |= SSL_GOST89MAC12;
 
-    if (!get_optional_pkey_id("gost2001"))
+    ssl_mac_pkey_id[SSL_MD_MAGMAOMAC_IDX] =
+        get_optional_pkey_id(SN_magma_mac);
+    if (ssl_mac_pkey_id[SSL_MD_MAGMAOMAC_IDX])
+        ctx->ssl_mac_secret_size[SSL_MD_MAGMAOMAC_IDX] = 32;
+    else
+        disabled_mac_mask |= SSL_MAGMAOMAC;
+
+    ssl_mac_pkey_id[SSL_MD_KUZNYECHIKOMAC_IDX] =
+        get_optional_pkey_id(SN_kuznyechik_mac);
+    if (ssl_mac_pkey_id[SSL_MD_KUZNYECHIKOMAC_IDX])
+        ctx->ssl_mac_secret_size[SSL_MD_KUZNYECHIKOMAC_IDX] = 32;
+    else
+        disabled_mac_mask |= SSL_KUZNYECHIKOMAC;
+
+    if (!get_optional_pkey_id(SN_id_GostR3410_2001))
         disabled_auth_mask |= SSL_aGOST01 | SSL_aGOST12;
-    if (!get_optional_pkey_id("gost2012_256"))
+    if (!get_optional_pkey_id(SN_id_GostR3410_2012_256))
         disabled_auth_mask |= SSL_aGOST12;
-    if (!get_optional_pkey_id("gost2012_512"))
+    if (!get_optional_pkey_id(SN_id_GostR3410_2012_512))
         disabled_auth_mask |= SSL_aGOST12;
     /*
      * Disable GOST key exchange if no GOST signature algs are available *
@@ -407,6 +428,9 @@ int ssl_load_ciphers(SSL_CTX *ctx)
         (SSL_aGOST01 | SSL_aGOST12))
         disabled_mkey_mask |= SSL_kGOST;
 
+    if ((disabled_auth_mask & SSL_aGOST12) ==  SSL_aGOST12)
+        disabled_mkey_mask |= SSL_kGOST18;
+
     return 1;
 }
 
@@ -1695,6 +1719,9 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
     case SSL_kGOST:
         kx = "GOST";
         break;
+    case SSL_kGOST18:
+        kx = "GOST18";
+        break;
     case SSL_kANY:
         kx = "any";
         break;
@@ -1798,6 +1825,12 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
     case SSL_eGOST2814789CNT12:
         enc = "GOST89(256)";
         break;
+    case SSL_MAGMA:
+        enc = "MAGMA";
+        break;
+    case SSL_KUZNYECHIK:
+        enc = "KUZNYECHIK";
+        break;
     case SSL_CHACHA20POLY1305:
         enc = "CHACHA20/POLY1305(256)";
         break;
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 85d9dd8448..30643c33b4 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -14,6 +14,8 @@
 #ifndef OPENSSL_NO_ERR
 
 static const ERR_STRING_DATA SSL_str_reasons[] = {
+    {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ALGORITHM_FETCH_FAILED),
+    "algorithm fetch failed"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY),
     "application data after close notify"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_APP_DATA_IN_HANDSHAKE),
@@ -171,8 +173,6 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
     "ext length mismatch"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_FAILED_TO_INIT_ASYNC),
     "failed to init async"},
-    {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ALGORITHM_FETCH_FAILED),
-     "algorithm fetch failed"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_FRAGMENTED_CLIENT_HELLO),
     "fragmented client hello"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_GOT_A_FIN_BEFORE_A_CCS),
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index fef50eea7f..dafec3d5c7 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -3495,11 +3495,11 @@ void ssl_set_masks(SSL *s)
 
 #ifndef OPENSSL_NO_GOST
     if (ssl_has_cert(s, SSL_PKEY_GOST12_512)) {
-        mask_k |= SSL_kGOST;
+        mask_k |= SSL_kGOST | SSL_kGOST18;
         mask_a |= SSL_aGOST12;
     }
     if (ssl_has_cert(s, SSL_PKEY_GOST12_256)) {
-        mask_k |= SSL_kGOST;
+        mask_k |= SSL_kGOST | SSL_kGOST18;
         mask_a |= SSL_aGOST12;
     }
     if (ssl_has_cert(s, SSL_PKEY_GOST01)) {
diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h
index e938504d3e..083141931c 100644
--- a/ssl/ssl_local.h
+++ b/ssl/ssl_local.h
@@ -180,6 +180,8 @@
 # define SSL_kRSAPSK             0x00000040U
 # define SSL_kECDHEPSK           0x00000080U
 # define SSL_kDHEPSK             0x00000100U
+/* GOST KDF key exchange, draft-smyshlyaev-tls12-gost-suites */
+# define SSL_kGOST18             0x00000200U
 
 /* all PSK */
 
@@ -234,6 +236,8 @@
 # define SSL_CHACHA20POLY1305    0x00080000U
 # define SSL_ARIA128GCM          0x00100000U
 # define SSL_ARIA256GCM          0x00200000U
+# define SSL_MAGMA               0x00400000U
+# define SSL_KUZNYECHIK          0x00800000U
 
 # define SSL_AESGCM              (SSL_AES128GCM | SSL_AES256GCM)
 # define SSL_AESCCM              (SSL_AES128CCM | SSL_AES256CCM | SSL_AES128CCM8 | SSL_AES256CCM8)
@@ -256,6 +260,8 @@
 # define SSL_GOST12_256          0x00000080U
 # define SSL_GOST89MAC12         0x00000100U
 # define SSL_GOST12_512          0x00000200U
+# define SSL_MAGMAOMAC           0x00000400U
+# define SSL_KUZNYECHIKOMAC      0x00000800U
 
 /*
  * When adding new digest in the ssl_ciph.c and increment SSL_MD_NUM_IDX make
@@ -274,7 +280,9 @@
 # define SSL_MD_MD5_SHA1_IDX 9
 # define SSL_MD_SHA224_IDX 10
 # define SSL_MD_SHA512_IDX 11
-# define SSL_MAX_DIGEST 12
+# define SSL_MD_MAGMAOMAC_IDX 12
+# define SSL_MD_KUZNYECHIKOMAC_IDX 13
+# define SSL_MAX_DIGEST 14
 
 #define SSL_MD_NUM_IDX  SSL_MAX_DIGEST
 
@@ -305,6 +313,11 @@
  * goes into algorithm2)
  */
 # define TLS1_STREAM_MAC 0x10000
+/*
+ * TLSTREE cipher/mac key derivation from draft-smyshlyaev-tls12-gost-suites
+ * (currently this also  goes into algorithm2)
+ */
+# define TLS1_TLSTREE 0x20000
 
 # define SSL_STRONG_MASK         0x0000001FU
 # define SSL_DEFAULT_MASK        0X00000020U
@@ -413,7 +426,9 @@
 # define SSL_ENC_CHACHA_IDX      19
 # define SSL_ENC_ARIA128GCM_IDX  20
 # define SSL_ENC_ARIA256GCM_IDX  21
-# define SSL_ENC_NUM_IDX         22
+# define SSL_ENC_MAGMA_IDX       22
+# define SSL_ENC_KUZNYECHIK_IDX  23
+# define SSL_ENC_NUM_IDX         24
 
 /*-
  * SSL_kRSA <- RSA_ENC
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index e33b671a05..aa71cec7e9 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -1648,7 +1648,9 @@ EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
     if (s->s3.tmp.new_cipher->algorithm_mac == SSL_AEAD
         || s->s3.tmp.new_cipher->algorithm_enc == SSL_RC4
         || s->s3.tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT
-        || s->s3.tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) {
+        || s->s3.tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12
+        || s->s3.tmp.new_cipher->algorithm_enc == SSL_MAGMA
+        || s->s3.tmp.new_cipher->algorithm_enc == SSL_KUZNYECHIK) {
         s->ext.use_etm = 0;
         return EXT_RETURN_NOT_SENT;
     }
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 4e43117ca2..67d8ae8ce6 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -3314,6 +3314,146 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt)
 #endif
 }
 
+#ifndef OPENSSL_NO_GOST
+int gost18_cke_cipher_nid(const SSL *s)
+{
+    if ((s->s3.tmp.new_cipher->algorithm_enc & SSL_MAGMA) != 0)
+        return NID_magma_ctr;
+    else if ((s->s3.tmp.new_cipher->algorithm_enc & SSL_KUZNYECHIK) != 0)
+        return NID_kuznyechik_ctr;
+
+    return NID_undef;
+}
+
+int gost_ukm(const SSL *s, unsigned char *dgst_buf)
+{
+    EVP_MD_CTX * hash = NULL;
+    unsigned int md_len;
+    const EVP_MD *md = ssl_evp_md_fetch(s->ctx->libctx, NID_id_GostR3411_2012_256, s->ctx->propq);
+
+    if (md == NULL)
+        return 0;
+
+    if ((hash = EVP_MD_CTX_new()) == NULL
+        || EVP_DigestInit(hash, md) <= 0
+        || EVP_DigestUpdate(hash, s->s3.client_random, SSL3_RANDOM_SIZE) <= 0
+        || EVP_DigestUpdate(hash, s->s3.server_random, SSL3_RANDOM_SIZE) <= 0
+        || EVP_DigestFinal_ex(hash, dgst_buf, &md_len) <= 0) {
+        EVP_MD_CTX_free(hash);
+        ssl_evp_md_free(md);
+        return 0;
+    }
+
+    EVP_MD_CTX_free(hash);
+    ssl_evp_md_free(md);
+    return 1;
+}
+#endif
+
+static int tls_construct_cke_gost18(SSL *s, WPACKET *pkt)
+{
+#ifndef OPENSSL_NO_GOST
+    /* GOST 2018 key exchange message creation */
+    unsigned char rnd_dgst[32], tmp[255];
+    EVP_PKEY_CTX *pkey_ctx = NULL;
+    X509 *peer_cert;
+    unsigned char *pms = NULL;
+    size_t pmslen = 0;
+    size_t msglen;
+    int cipher_nid = gost18_cke_cipher_nid(s);
+
+    if (cipher_nid == NID_undef) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+                 ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    if (gost_ukm(s, rnd_dgst) <= 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+                      ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
+
+    /* Pre-master secret - random bytes */
+    pmslen = 32;
+    pms = OPENSSL_malloc(pmslen);
+    if (pms == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+                 ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+
+    if (RAND_bytes_ex(s->ctx->libctx, pms, (int)pmslen) <= 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+                 ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
+
+     /* Get server certificate PKEY and create ctx from it */
+    peer_cert = s->session->peer;
+    if (peer_cert == NULL) {
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+               SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
+        return 0;
+    }
+
+    pkey_ctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, X509_get0_pubkey(peer_cert), s->ctx->propq);
+    if (pkey_ctx == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+                 ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+
+    if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0 ) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+                 ERR_R_INTERNAL_ERROR);
+        goto err;
+    };
+
+    /* Reuse EVP_PKEY_CTRL_SET_IV, make choice in engine code */
+    if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
+                          EVP_PKEY_CTRL_SET_IV, 32, rnd_dgst) < 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+                 SSL_R_LIBRARY_BUG);
+        goto err;
+    }
+
+    if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
+                          EVP_PKEY_CTRL_CIPHER, cipher_nid, NULL) < 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+                 SSL_R_LIBRARY_BUG);
+        goto err;
+    }
+
+    msglen = 255;
+    if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+                 SSL_R_LIBRARY_BUG);
+        goto err;
+    }
+
+    if (!WPACKET_memcpy(pkt, tmp, msglen)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+                 ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
+
+    EVP_PKEY_CTX_free(pkey_ctx);
+    s->s3.tmp.pms = pms;
+    s->s3.tmp.pmslen = pmslen;
+
+    return 1;
+ err:
+    EVP_PKEY_CTX_free(pkey_ctx);
+    OPENSSL_clear_free(pms, pmslen);
+    return 0;
+#else
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+             ERR_R_INTERNAL_ERROR);
+    return 0;
+#endif
+}
+
 static int tls_construct_cke_srp(SSL *s, WPACKET *pkt)
 {
 #ifndef OPENSSL_NO_SRP
@@ -3370,6 +3510,9 @@ int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt)
     } else if (alg_k & SSL_kGOST) {
         if (!tls_construct_cke_gost(s, pkt))
             goto err;
+    } else if (alg_k & SSL_kGOST18) {
+        if (!tls_construct_cke_gost18(s, pkt))
+            goto err;
     } else if (alg_k & SSL_kSRP) {
         if (!tls_construct_cke_srp(s, pkt))
             goto err;
diff --git a/ssl/statem/statem_local.h b/ssl/statem/statem_local.h
index f4242fa2a4..6a4708cee9 100644
--- a/ssl/statem/statem_local.h
+++ b/ssl/statem/statem_local.h
@@ -153,6 +153,11 @@ __owur MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt);
 __owur int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt);
 MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt);
 
+#ifndef OPENSSL_NO_GOST
+/* These functions are used in GOST18 CKE, both for client and server */
+int gost18_cke_cipher_nid(const SSL *s);
+int gost_ukm(const SSL *s, unsigned char *dgst_buf);
+#endif
 
 /* Extension processing */
 
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index d1d86ea5e6..e5340b4e7f 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -3430,6 +3430,93 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt)
 #endif
 }
 
+static int tls_process_cke_gost18(SSL *s, PACKET *pkt)
+{
+#ifndef OPENSSL_NO_GOST
+    unsigned char rnd_dgst[32];
+    EVP_PKEY_CTX *pkey_ctx = NULL;
+    EVP_PKEY *pk = NULL;
+    unsigned char premaster_secret[32];
+    const unsigned char *start = NULL;
+    size_t outlen = 32, inlen = 0;
+    int ret = 0;
+    int cipher_nid = gost18_cke_cipher_nid(s);
+
+    if (cipher_nid == NID_undef) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+                 ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    if (gost_ukm(s, rnd_dgst) <= 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+                 ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
+
+    /* Get our certificate private key */
+    pk = s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey != NULL ?
+         s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey :
+         s->cert->pkeys[SSL_PKEY_GOST12_256].privatekey;
+    if (pk == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
+                 SSL_R_BAD_HANDSHAKE_STATE);
+        goto err;
+    }
+
+    pkey_ctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, pk, s->ctx->propq);
+    if (pkey_ctx == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
+                 ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
+                 ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
+
+    /* Reuse EVP_PKEY_CTRL_SET_IV, make choice in engine code depending on size */
+    if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_DECRYPT,
+                          EVP_PKEY_CTRL_SET_IV, 32, rnd_dgst) < 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
+                 SSL_R_LIBRARY_BUG);
+        goto err;
+    }
+
+    if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_DECRYPT,
+                          EVP_PKEY_CTRL_CIPHER, cipher_nid, NULL) < 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
+                 SSL_R_LIBRARY_BUG);
+        goto err;
+    }
+    inlen = PACKET_remaining(pkt);
+    start = PACKET_data(pkt);
+
+    if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start, inlen) <= 0) {
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
+                 SSL_R_DECRYPTION_FAILED);
+        goto err;
+    }
+    /* Generate master secret */
+    if (!ssl_generate_master_secret(s, premaster_secret,
+         sizeof(premaster_secret), 0)) {
+         /* SSLfatal() already called */
+         goto err;
+    }
+    ret = 1;
+
+ err:
+    EVP_PKEY_CTX_free(pkey_ctx);
+    return ret;
+#else
+    /* Should never happen */
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
+             ERR_R_INTERNAL_ERROR);
+    return 0;
+#endif
+}
+
 MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
 {
     unsigned long alg_k;
@@ -3480,6 +3567,11 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
             /* SSLfatal() already called */
             goto err;
         }
+    } else if (alg_k & SSL_kGOST18) {
+        if (!tls_process_cke_gost18(s, pkt)) {
+            /* SSLfatal() already called */
+            goto err;
+        }
     } else {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                  SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index 03eb050963..7f908f3b4c 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -180,6 +180,11 @@ int tls1_change_cipher_state(SSL *s, int which)
         else
             s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM;
 
+        if (s->s3.tmp.new_cipher->algorithm2 & TLS1_TLSTREE)
+            s->mac_flags |= SSL_MAC_FLAG_READ_MAC_TLSTREE;
+        else
+            s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_TLSTREE;
+
         if (s->enc_read_ctx != NULL) {
             reuse_dd = 1;
         } else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) {
@@ -230,6 +235,11 @@ int tls1_change_cipher_state(SSL *s, int which)
             s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM;
         else
             s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM;
+
+        if (s->s3.tmp.new_cipher->algorithm2 & TLS1_TLSTREE)
+            s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_TLSTREE;
+        else
+            s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_TLSTREE;
         if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s)) {
             reuse_dd = 1;
         } else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) {
@@ -617,6 +627,10 @@ size_t tls1_final_finish_mac(SSL *s, const char *str, size_t slen,
 {
     size_t hashlen;
     unsigned char hash[EVP_MAX_MD_SIZE];
+    size_t finished_size = TLS1_FINISH_MAC_LENGTH;
+
+    if (s->s3.tmp.new_cipher->algorithm_mkey & SSL_kGOST18)
+        finished_size = 32;
 
     if (!ssl3_digest_cached_records(s, 0)) {
         /* SSLfatal() already called */
@@ -630,12 +644,12 @@ size_t tls1_final_finish_mac(SSL *s, const char *str, size_t slen,
 
     if (!tls1_PRF(s, str, slen, hash, hashlen, NULL, 0, NULL, 0, NULL, 0,
                   s->session->master_key, s->session->master_key_length,
-                  out, TLS1_FINISH_MAC_LENGTH, 1)) {
+                  out, finished_size, 1)) {
         /* SSLfatal() already called */
         return 0;
     }
     OPENSSL_cleanse(hash, hashlen);
-    return TLS1_FINISH_MAC_LENGTH;
+    return finished_size;
 }
 
 int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 416ba28fb6..f3373dc6d5 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1001,6 +1001,21 @@ static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL *s, int idx)
                     }
                 }
             }
+            /*
+             * As both SSL_PKEY_GOST12_512 and SSL_PKEY_GOST12_256 indices can be used
+             * with new (aGOST12-only) ciphersuites, we should find out which one is available really.
+             */
+            else if (idx == SSL_PKEY_GOST12_256) {
+                int real_idx;
+
+                for (real_idx = SSL_PKEY_GOST12_512; real_idx >= SSL_PKEY_GOST12_256;
+                     real_idx--) {
+                     if (s->cert->pkeys[real_idx].privatekey != NULL) {
+                         idx = real_idx;
+                         break;
+                     }
+                }
+            }
         } else {
             idx = s->cert->key - s->cert->pkeys;
         }
@@ -1794,7 +1809,7 @@ static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu)
                 if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0))
                     continue;
 
-                if ((c->algorithm_mkey & SSL_kGOST) != 0)
+                if ((c->algorithm_mkey & (SSL_kGOST | SSL_kGOST18)) != 0)
                     break;
             }
             if (i == num)
diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c
index 9f018ce1ad..72e7b376c0 100644
--- a/ssl/t1_trce.c
+++ b/ssl/t1_trce.c
@@ -444,6 +444,9 @@ static const ssl_trace_tbl ssl_ciphers_tbl[] = {
     {0xFEFF, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"},
     {0xFF85, "LEGACY-GOST2012-GOST8912-GOST8912"},
     {0xFF87, "GOST2012-NULL-GOST12"},
+    {0xC100, "GOST2012-KUZNYECHIK-KUZNYECHIKOMAC"},
+    {0xC101, "GOST2012-MAGMA-MAGMAOMAC"},
+    {0xC102, "GOST2012-GOST8912-IANA"},
 };
 
 /* Compression methods */
@@ -593,7 +596,9 @@ static const ssl_trace_tbl ssl_ctype_tbl[] = {
     {20, "fortezza_dms"},
     {64, "ecdsa_sign"},
     {65, "rsa_fixed_ecdh"},
-    {66, "ecdsa_fixed_ecdh"}
+    {66, "ecdsa_fixed_ecdh"},
+    {67, "gost_sign256"},
+    {68, "gost_sign512"},
 };
 
 static const ssl_trace_tbl ssl_psk_kex_modes_tbl[] = {
@@ -1078,6 +1083,10 @@ static int ssl_get_keyex(const char **pname, const SSL *ssl)
         *pname = "GOST";
         return SSL_kGOST;
     }
+    if (alg_k & SSL_kGOST18) {
+        *pname = "GOST18";
+        return SSL_kGOST18;
+    }
     *pname = "UNKNOWN";
     return 0;
 }
@@ -1124,7 +1133,11 @@ static int ssl_print_client_keyex(BIO *bio, int indent, const SSL *ssl,
         ssl_print_hex(bio, indent + 2, "GostKeyTransportBlob", msg, msglen);
         msglen = 0;
         break;
-
+    case SSL_kGOST18:
+        ssl_print_hex(bio, indent + 2,
+                      "GOST-wrapped PreMasterSecret", msg, msglen);
+        msglen = 0;
+        break;
     }
 
     return !msglen;


More information about the openssl-commits mailing list