CVE-2022-29242 (published 2022-05-24T15:15Z)

GOST engine is a reference implementation of the Russian GOST crypto algorithms for OpenSSL. TLS clients using GOST engine when ciphersuite `TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC` is agreed and the server uses 512 bit GOST secret keys are vulnerable to buffer overflow. GOST engine version 3.0.1 contains a patch for this issue. Disabling ciphersuite `TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC` is a possible workaround.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-120
cwe_name: Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')
description: The product copies an input buffer to an output buffer without verifying that the size of the input buffer is less than the size of the output buffer, leading to a buffer overflow.
extended_description: A buffer overflow condition exists when a product attempts to put more data in a buffer than it can hold, or when it attempts to put data in a memory area outside of the boundaries of a buffer. The simplest type of error, and the most common cause of buffer overflows, is the "classic" case in which the product copies the buffer without restricting how much is copied. Other variants exist, but the existence of a classic overflow strongly suggests that the programmer is not considering even the most basic of security protections.
         

Fix information:
repo_url: https://github.com/gost-engine/engine
commit_details: repo_url: https://github.com/gost-engine/engine
author: Dmitry Belyavskiy
author_date: 2022-05-21 20:20:20+02:00
msg: On unpacking key blob output buffer size should be fixed

Related: CVE-2022-29242
repository: repo_url: https://github.com/gost-engine/engine
repo_name: gost-engine/engine
description: A reference implementation of the Russian GOST crypto algorithms for OpenSSL
repo_language: C
owner: gost-engine
file_changes: filename: gost_ec_keyx.c
change_type: ModificationType.MODIFY
diff: @@ -589,10 +589,6 @@ static int pkey_GOST_ECcp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key,
     EVP_PKEY *eph_key = NULL, *peerkey = NULL;
     int dgst_nid = NID_undef;
 
-    if (!key) {
-        *key_len = 32;
-        return 1;
-    }
     gkt = d2i_GOST_KEY_TRANSPORT(NULL, (const unsigned char **)&p, in_len);
     if (!gkt) {
         GOSTerr(GOST_F_PKEY_GOST_ECCP_DECRYPT,
@@ -652,6 +648,7 @@ static int pkey_GOST_ECcp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key,
         goto err;
     }
 
+    *key_len = 32;
     ret = 1;
  err:
     OPENSSL_cleanse(sharedKey, sizeof(sharedKey));
@@ -701,10 +698,6 @@ static int pkey_gost2018_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key,
         return -1;
         break;
     }
-    if (!key) {
-        *key_len = 32;
-        return 1;
-    }
 
     pst = d2i_PSKeyTransport_gost(NULL, (const unsigned char **)&p, in_len);
     if (!pst) {
@@ -731,7 +724,7 @@ static int pkey_gost2018_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key,
        ret = 0;
        goto err;
     }
-  
+
     if (data->shared_ukm_size == 0 && pst->ukm != NULL) {
         if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_SET_IV,
         ASN1_STRING_length(pst->ukm), (void *)ASN1_STRING_get0_data(pst->ukm)) < 0) {
@@ -756,6 +749,7 @@ static int pkey_gost2018_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key,
         goto err;
     }
 
+    *key_len = 32;
     ret = 1;
  err:
     OPENSSL_cleanse(expkeys, sizeof(expkeys));
@@ -768,6 +762,17 @@ int pkey_gost_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key,
                       size_t *key_len, const unsigned char *in, size_t in_len)
 {
     struct gost_pmeth_data *gctx = EVP_PKEY_CTX_get_data(pctx);
+
+    if (key == NULL) {
+        *key_len = 32;
+        return 1;
+    }
+
+    if (key != NULL && *key_len < 32) {
+        GOSTerr(GOST_F_PKEY_GOST2018_ENCRYPT, GOST_R_INVALID_BUFFER_SIZE);
+        return 0;
+    }
+
     switch (gctx->cipher_nid)
     {
         case NID_id_Gost28147_89:

programming_language: C
repo_url: https://github.com/gost-engine/engine
commit_details: repo_url: https://github.com/gost-engine/engine
author: Dmitry Belyavskiy
author_date: 2022-05-21 20:06:47+02:00
msg: Fix buffer overrun in creating key transport blob according to RFC 9189, 4.2.4.2

Resolves: CVE-2022-29242
repository: repo_url: https://github.com/gost-engine/engine
repo_name: gost-engine/engine
description: A reference implementation of the Russian GOST crypto algorithms for OpenSSL
repo_language: C
owner: gost-engine
file_changes: filename: gost_ec_keyx.c
change_type: ModificationType.MODIFY
diff: @@ -292,6 +292,8 @@ static int pkey_GOST_ECcp_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out,
     int key_is_ephemeral = 1;
     gost_ctx cctx;
     EVP_PKEY *sec_key = EVP_PKEY_CTX_get0_peerkey(pctx);
+    int res_len = 0;
+
     if (data->shared_ukm_size) {
         memcpy(ukm, data->shared_ukm, 8);
     } else {
@@ -373,8 +375,26 @@ static int pkey_GOST_ECcp_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out,
             goto err;
         }
     }
-    if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt, out ? &out : NULL)) > 0)
+    res_len = i2d_GOST_KEY_TRANSPORT(gkt, NULL);
+    if (res_len <= 0) {
+        GOSTerr(GOST_F_PKEY_GOST_ECCP_ENCRYPT, ERR_R_ASN1_LIB);
+        goto err;
+    }
+
+    if (out == NULL) {
+        *out_len = res_len;
         ret = 1;
+    } else {
+        if ((size_t)res_len > *out_len) {
+            GOSTerr(GOST_F_PKEY_GOST_ECCP_ENCRYPT, GOST_R_INVALID_BUFFER_SIZE);
+            goto err;
+        }
+        if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt, &out)) > 0)
+            ret = 1;
+        else
+            GOSTerr(GOST_F_PKEY_GOST_ECCP_ENCRYPT, ERR_R_ASN1_LIB);
+    }
+
     OPENSSL_cleanse(shared_key, sizeof(shared_key));
     GOST_KEY_TRANSPORT_free(gkt);
     return ret;

programming_language: C
repo_url: https://github.com/gost-engine/engine
commit_details: repo_url: https://github.com/gost-engine/engine
author: Dmitry Belyavskiy
author_date: 2022-05-20 18:13:50+02:00
msg: Fix buffer overrun in creating key transport blob according to RFC 9189, 4.2.4.1

Resolves: CVE-2022-29242
repository: repo_url: https://github.com/gost-engine/engine
repo_name: gost-engine/engine
description: A reference implementation of the Russian GOST crypto algorithms for OpenSSL
repo_language: C
owner: gost-engine
file_changes: filename: e_gost_err.c
change_type: ModificationType.MODIFY
diff: @@ -141,6 +141,7 @@ static ERR_STRING_DATA GOST_str_reasons[] = {
     {ERR_PACK(0, 0, GOST_R_ERROR_SETTING_PEER_KEY), "error setting peer key"},
     {ERR_PACK(0, 0, GOST_R_INCOMPATIBLE_ALGORITHMS), "incompatible algorithms"},
     {ERR_PACK(0, 0, GOST_R_INCOMPATIBLE_PEER_KEY), "incompatible peer key"},
+    {ERR_PACK(0, 0, GOST_R_INVALID_BUFFER_SIZE), "invalid buffer size"},
     {ERR_PACK(0, 0, GOST_R_INVALID_CIPHER), "invalid cipher"},
     {ERR_PACK(0, 0, GOST_R_INVALID_CIPHER_PARAMS), "invalid cipher params"},
     {ERR_PACK(0, 0, GOST_R_INVALID_CIPHER_PARAM_OID),

programming_language: C
filename: e_gost_err.h
change_type: ModificationType.MODIFY
diff: @@ -115,6 +115,7 @@ void ERR_GOST_error(int function, int reason, char *file, int line);
 # define GOST_R_ERROR_SETTING_PEER_KEY                    139
 # define GOST_R_INCOMPATIBLE_ALGORITHMS                   108
 # define GOST_R_INCOMPATIBLE_PEER_KEY                     109
+# define GOST_R_INVALID_BUFFER_SIZE                       140
 # define GOST_R_INVALID_CIPHER                            134
 # define GOST_R_INVALID_CIPHER_PARAMS                     110
 # define GOST_R_INVALID_CIPHER_PARAM_OID                  111

programming_language: Shell
filename: gost_ec_keyx.c
change_type: ModificationType.MODIFY
diff: @@ -406,6 +406,7 @@ static int pkey_gost2018_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out,
     int exp_len = 0, iv_len = 0;
     unsigned char *exp_buf = NULL;
     int key_is_ephemeral = 0;
+    int res_len = 0;
 
     switch (data->cipher_nid) {
     case NID_magma_ctr:
@@ -499,8 +500,26 @@ static int pkey_gost2018_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out,
         goto err;
     }
 
-    if ((*out_len = i2d_PSKeyTransport_gost(pst, out ? &out : NULL)) > 0)
+    res_len = i2d_PSKeyTransport_gost(pst, NULL);
+    if (res_len <= 0) {
+        GOSTerr(GOST_F_PKEY_GOST2018_ENCRYPT, ERR_R_ASN1_LIB);
+        goto err;
+    }
+
+    if (out == NULL) {
+        *out_len = res_len;
         ret = 1;
+    } else {
+        if ((size_t)res_len > *out_len) {
+            GOSTerr(GOST_F_PKEY_GOST2018_ENCRYPT, GOST_R_INVALID_BUFFER_SIZE);
+            goto err;
+        }
+        if ((*out_len = i2d_PSKeyTransport_gost(pst, &out)) > 0)
+            ret = 1;
+        else
+            GOSTerr(GOST_F_PKEY_GOST2018_ENCRYPT, ERR_R_ASN1_LIB);
+    }
+
  err:
     OPENSSL_cleanse(expkeys, sizeof(expkeys));
     if (key_is_ephemeral)

programming_language: C