]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
GOSTR341194: mark as insecure for digital signatures
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Tue, 21 Jan 2020 09:32:59 +0000 (10:32 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 26 Jan 2020 20:10:37 +0000 (21:10 +0100)
Although there are no practical attacks known on the algorithm, the practical
strength of the algorithm is weaker than the theoritical. In addition this algorithm
is already considered legacy, and as such mark it as insecure for digital
signatures to reduce the attack surface.

Relates: #909

Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
lib/algorithms/mac.c
lib/crypto-selftests-pk.c
tests/cert-tests/data/gost-cert-nogost.pem
tests/cert-tests/data/gost-cert.pem
tests/cert-tests/data/grfc.crt
tests/cert-tests/pkcs7
tests/privkey-keygen.c
tests/sign-is-secure.c
tests/test-chains.h
tests/x509sign-verify-common.h

index edd6e10acc7db98d335928ff89358467ef71d039..a9b0358ac03aa5b3bb12e9f280314da9145f752a 100644 (file)
@@ -132,14 +132,17 @@ mac_entry_st hash_algorithms[] = {
         .id = GNUTLS_MAC_RMD160,
         .output_size = 20,
         .key_size = 20,
-        .block_size = 64},
+        .block_size = 64
+       },
        {.name = "GOSTR341194",
         .oid = HASH_OID_GOST_R_3411_94,
         .mac_oid = MAC_OID_GOST_R_3411_94,
         .id = GNUTLS_MAC_GOSTR_94,
         .output_size = 32,
         .key_size = 32,
-        .block_size = 32},
+        .block_size = 32,
+        .flags = GNUTLS_MAC_FLAG_PREIMAGE_INSECURE
+       },
        {.name = "STREEBOG-256",
         .oid = HASH_OID_STREEBOG_256,
         .mac_oid = MAC_OID_STREEBOG_256,
index 7bdb0973ffb736eea0a12250dfa58352352008e1..f336ddc06241efbf59c66543b417c47cff7c7872 100644 (file)
@@ -210,12 +210,16 @@ static int test_sig(gnutls_pk_algorithm_t pk,
        gnutls_privkey_t key;
        gnutls_pubkey_t pub = NULL;
        char param_name[32];
+       unsigned vflags = 0;
 
        if (pk == GNUTLS_PK_EC || pk == GNUTLS_PK_GOST_01 ||
            pk == GNUTLS_PK_GOST_12_256 || pk == GNUTLS_PK_GOST_12_512) {
                snprintf(param_name, sizeof(param_name), "%s",
                         gnutls_ecc_curve_get_name(GNUTLS_BITS_TO_CURVE
                                                   (bits)));
+
+               if (sigalgo == GNUTLS_SIGN_GOST_94)
+                       vflags |= GNUTLS_VERIFY_ALLOW_BROKEN;
        } else {
                snprintf(param_name, sizeof(param_name), "%u", bits);
        }
@@ -267,7 +271,7 @@ static int test_sig(gnutls_pk_algorithm_t pk,
        }
 
        ret =
-           gnutls_pubkey_verify_data2(pub, sigalgo, 0,
+           gnutls_pubkey_verify_data2(pub, sigalgo, vflags,
                                       &signed_data, &sig);
        if (ret < 0) {
                ret = GNUTLS_E_SELF_TEST_ERROR;
@@ -276,7 +280,7 @@ static int test_sig(gnutls_pk_algorithm_t pk,
        }
 
        ret =
-           gnutls_pubkey_verify_data2(pub, sigalgo, 0,
+           gnutls_pubkey_verify_data2(pub, sigalgo, vflags,
                                       &bad_data, &sig);
 
        if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED) {
@@ -426,12 +430,15 @@ static int test_known_sig(gnutls_pk_algorithm_t pk, unsigned bits,
        gnutls_pubkey_t pub = NULL;
        gnutls_privkey_t key;
        char param_name[32];
+       unsigned vflags = 0;
 
        if (pk == GNUTLS_PK_EC || pk == GNUTLS_PK_GOST_01 ||
            pk == GNUTLS_PK_GOST_12_256 || pk == GNUTLS_PK_GOST_12_512) {
                snprintf(param_name, sizeof(param_name), "%s",
                         gnutls_ecc_curve_get_name(GNUTLS_BITS_TO_CURVE
                                                   (bits)));
+               if (dig == GNUTLS_DIG_GOSTR_94)
+                       vflags |= GNUTLS_VERIFY_ALLOW_BROKEN;
        } else {
                snprintf(param_name, sizeof(param_name), "%u", bits);
        }
@@ -503,7 +510,7 @@ static int test_known_sig(gnutls_pk_algorithm_t pk, unsigned bits,
        }
 
        ret =
-           gnutls_pubkey_verify_data2(pub, gnutls_pk_to_sign(pk, dig), 0,
+           gnutls_pubkey_verify_data2(pub, gnutls_pk_to_sign(pk, dig), vflags,
                                       &signed_data, &ssig);
        if (ret < 0) {
                ret = GNUTLS_E_SELF_TEST_ERROR;
index 76fcd3d8b91c79e617ce572eecddead3d98ab643..cd9459f9fb071260d873162471d368076b4d53ae 100644 (file)
@@ -6,8 +6,17 @@ X.509 Certificate Information:
                Not Before: Fri Aug 17 06:47:36 UTC 2012
                Not After: Sat Aug 17 06:47:36 UTC 2013
        Subject: CN=SuperTerm0000001,OU=SuperPlat Terminals,O=SuperPlat,L=Moscow,ST=Russia,C=RU
-error importing public key: The curve is unsupported
        Subject Public Key Algorithm: GOST R 34.10-2001
+       Algorithm Security Level: High (256 bits)
+               Curve:  CryptoPro-A
+               Digest: GOSTR341194
+               ParamSet: CryptoPro-A
+               X:
+                       e0:35:f2:a8:40:cf:ea:25:63:b5:c1:eb:fa:fd:1d:7f
+                       45:d6:2a:31:96:56:35:75:25:19:f6:62:69:db:da:eb
+               Y:
+                       57:41:b2:c1:e2:1f:7b:d0:13:c8:dd:eb:9f:ba:cb:42
+                       a3:63:c7:0b:f4:e9:24:d7:dd:e9:34:8d:12:18:67:d8
        Extensions:
                Basic Constraints (not critical):
                        Certificate Authority (CA): FALSE
@@ -19,6 +28,7 @@ error importing public key: The curve is unsupported
                Authority Key Identifier (not critical):
                        9875a3b785c1641b23344d9bfbae0c2a256b44eb
        Signature Algorithm: GOSTR341001
+warning: signed using a broken signature algorithm that can be forged.
        Signature:
                8f:37:24:fd:be:f0:37:d9:f3:1a:5c:31:5e:33:ef:35
                61:93:07:03:3d:4d:e8:2c:1b:39:a2:6c:d4:2f:85:35
@@ -28,6 +38,11 @@ Other Information:
        Fingerprint:
                sha1:621f34c4fdd7e93f9b8f18224ba0bcd1c63a4771
                sha256:ac6ecf4e7a876edf3e61f538d6061353c2015bfbdf60370492f7404d7f09e13a
+       Public Key ID:
+               sha1:43757042dae9e9f5fa92cc2d2cbf4950f28a7bd0
+               sha256:cee4a59e7803bafb101af8e39e5355d7895e3b85e7616fe624d48f2c51e8bdbf
+       Public Key PIN:
+               pin-sha256:zuSlnngDuvsQGvjjnlNV14leO4XnYW/mJNSPLFHovb8=
 
 -----BEGIN CERTIFICATE-----
 MIICXjCCAgugAwIBAgICAR8wCgYGKoUDAgIDBQAwdDELMAkGA1UEBhMCUlUxDzAN
index bec29b8bb501c99c614f29ed2ebc3eceb6225d35..cd9459f9fb071260d873162471d368076b4d53ae 100644 (file)
@@ -28,6 +28,7 @@ X.509 Certificate Information:
                Authority Key Identifier (not critical):
                        9875a3b785c1641b23344d9bfbae0c2a256b44eb
        Signature Algorithm: GOSTR341001
+warning: signed using a broken signature algorithm that can be forged.
        Signature:
                8f:37:24:fd:be:f0:37:d9:f3:1a:5c:31:5e:33:ef:35
                61:93:07:03:3d:4d:e8:2c:1b:39:a2:6c:d4:2f:85:35
index c7af541b5fe9551a6ed73b71725e89a7aac13aba..20f587ea6ed1a4a23b2b7f95dfe34ae7bfad74f9 100644 (file)
@@ -41,6 +41,7 @@ X.509 Certificate Information:
                        1.2.643.100.113.2
                        2.5.29.32.0
        Signature Algorithm: GOSTR341001
+warning: signed using a broken signature algorithm that can be forged.
        Signature:
                bd:95:dd:5f:3a:2b:74:a5:29:62:20:c2:24:a8:8b:a0
                13:1a:21:f5:4a:d6:2e:b1:3f:f5:50:e9:96:a0:a2:c9
index eed9f068a281cf09cc254e6a65627dbd09ecd5b9..5951a7312b1b00482611594dbf771bba1a8b5490 100755 (executable)
@@ -330,6 +330,15 @@ then
        ${VALGRIND} "${CERTTOOL}" --p7-verify --load-certificate "${srcdir}/../../doc/credentials/x509/cert-gost01.pem" <"${OUTFILE}"
        rc=$?
 
+       if test "${rc}" != "1"; then
+               echo "${FILE}: PKCS7 struct signing succeeded verification with broken algo"
+               exit ${rc}
+       fi
+
+       FILE="gost01-signing-verify"
+       ${VALGRIND} "${CERTTOOL}" --p7-verify --verify-allow-broken --load-certificate "${srcdir}/../../doc/credentials/x509/cert-gost01.pem" <"${OUTFILE}"
+       rc=$?
+
        if test "${rc}" != "0"; then
                echo "${FILE}: PKCS7 struct signing failed verification"
                exit ${rc}
index 31634bd0958b1e1a46ae3576a0aaf64c36ec6c5d..565beccb20524d44ce58a7c7412d300ee9848617 100644 (file)
@@ -64,6 +64,7 @@ static void sign_verify_data(gnutls_pk_algorithm_t algorithm, gnutls_x509_privke
        gnutls_pubkey_t pubkey;
        gnutls_datum_t signature;
        gnutls_digest_algorithm_t digest;
+       unsigned vflags = 0;
 
        assert(gnutls_privkey_init(&privkey) >= 0);
 
@@ -81,6 +82,9 @@ static void sign_verify_data(gnutls_pk_algorithm_t algorithm, gnutls_x509_privke
        if (ret < 0)
                fail("gnutls_pubkey_get_preferred_hash_algorithm\n");
 
+       if (digest == GNUTLS_DIG_GOSTR_94)
+               vflags |= GNUTLS_VERIFY_ALLOW_BROKEN;
+
        /* sign arbitrary data */
        ret = gnutls_privkey_sign_data(privkey, digest, 0,
                                        &raw_data, &signature);
@@ -89,7 +93,7 @@ static void sign_verify_data(gnutls_pk_algorithm_t algorithm, gnutls_x509_privke
 
        /* verify data */
        ret = gnutls_pubkey_verify_data2(pubkey, gnutls_pk_to_sign(gnutls_pubkey_get_pk_algorithm(pubkey, NULL),digest),
-                               0, &raw_data, &signature);
+                                        vflags, &raw_data, &signature);
        if (ret < 0)
                fail("gnutls_pubkey_verify_data2\n");
 
index 729e5024b331324bcbb04e58a9be61e9ea09b6c0..3c2d18d93a33a7ba1f09bd9a6c96c6d3ec9336a1 100644 (file)
@@ -85,13 +85,14 @@ void doit(void)
 
        CHECK_INSECURE_SIG(GNUTLS_SIGN_RSA_MD5);
        CHECK_INSECURE_SIG(GNUTLS_SIGN_RSA_MD2);
+       CHECK_INSECURE_SIG(GNUTLS_SIGN_GOST_94);
 
        for (i=1;i<GNUTLS_SIGN_MAX;i++) {
 #ifndef ALLOW_SHA1
                if (i==GNUTLS_SIGN_RSA_SHA1||i==GNUTLS_SIGN_DSA_SHA1||i==GNUTLS_SIGN_ECDSA_SHA1)
                        continue;
 #endif
-               if (i==GNUTLS_SIGN_RSA_MD5||i==GNUTLS_SIGN_RSA_MD2||i==GNUTLS_SIGN_UNKNOWN)
+               if (i==GNUTLS_SIGN_GOST_94||i==GNUTLS_SIGN_RSA_MD5||i==GNUTLS_SIGN_RSA_MD2||i==GNUTLS_SIGN_UNKNOWN)
                        continue;
                /* skip any unused elements */
                if (gnutls_sign_algorithm_get_name(i)==NULL)
index fe118717d4442f3de7f24eac956e41fb632f8e2d..b0e44c8e174f4745fda1bea9467e37a0d751e052 100644 (file)
@@ -4153,8 +4153,10 @@ static struct
   { "rsa pss: chain with changing hashes - ok", rsa_pss_chain_sha512_sha384_sha256_ok, &rsa_pss_chain_sha512_sha384_sha256_ok[3], 0, 0, 0, 1501159136},
   { "no subject id: chain with missing subject id, but valid auth id - ok", chain_with_no_subject_id_in_ca_ok, &chain_with_no_subject_id_in_ca_ok[4], 0, 0, 0, 1537518468},
 #ifdef ENABLE_GOST
-  { "gost 34.10-01 - ok", gost01, &gost01[2], 0, 0, 0, 1466612070, 1},
-  { "gost 34.10-01 - not ok (due to profile)", gost01, &gost01[2], GNUTLS_PROFILE_TO_VFLAGS(GNUTLS_PROFILE_ULTRA),
+  { "gost 34.10-01 - ok", gost01, &gost01[2], GNUTLS_VERIFY_ALLOW_BROKEN, 0, 0, 1466612070, 1},
+  { "gost 34.10-01 - not ok (due to gostr94)", gost01, &gost01[2], 0,
+    GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID, NULL, 1466612070, 1},
+  { "gost 34.10-01 - not ok (due to profile)", gost01, &gost01[2], GNUTLS_VERIFY_ALLOW_BROKEN|GNUTLS_PROFILE_TO_VFLAGS(GNUTLS_PROFILE_ULTRA),
     GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID, NULL, 1466612070, 1},
   { "gost 34.10-12-256 - ok", gost12_256, &gost12_256[0], 0, 0, 0, 1466612070, 1},
   { "gost 34.10-12-512 - ok", gost12_512, &gost12_512[0], 0, 0, 0, 1466612070, 1},
index 80aea5cd632f373cb7d0a3a7086bbc785cf3e048..6b7498586b4f640ffc9748f239637086ba72da66 100644 (file)
@@ -114,9 +114,10 @@ void test_sig(gnutls_pk_algorithm_t pk, unsigned hash, unsigned bits)
                vflags |= GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1;
        } else if (hash == GNUTLS_DIG_SHA256)
                hash_data = &sha256_data;
-       else if (hash == GNUTLS_DIG_GOSTR_94)
+       else if (hash == GNUTLS_DIG_GOSTR_94) {
                hash_data = &gostr94_data;
-       else if (hash == GNUTLS_DIG_STREEBOG_256)
+               vflags |= GNUTLS_VERIFY_ALLOW_BROKEN;
+       } else if (hash == GNUTLS_DIG_STREEBOG_256)
                hash_data = &streebog256_data;
        else if (hash == GNUTLS_DIG_STREEBOG_512)
                hash_data = &streebog512_data;