From 9ec9fe6cc4d0ceab436a418dd1e52132967bb9c7 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Tue, 21 Jan 2020 10:32:59 +0100 Subject: GOSTR341194: mark as insecure for digital signatures 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 --- lib/algorithms/mac.c | 7 +++++-- lib/crypto-selftests-pk.c | 13 ++++++++++--- tests/cert-tests/data/gost-cert-nogost.pem | 17 ++++++++++++++++- tests/cert-tests/data/gost-cert.pem | 1 + tests/cert-tests/data/grfc.crt | 1 + tests/cert-tests/pkcs7 | 9 +++++++++ tests/privkey-keygen.c | 6 +++++- tests/sign-is-secure.c | 3 ++- tests/test-chains.h | 6 ++++-- tests/x509sign-verify-common.h | 5 +++-- 10 files changed, 56 insertions(+), 12 deletions(-) diff --git a/lib/algorithms/mac.c b/lib/algorithms/mac.c index edd6e10acc..a9b0358ac0 100644 --- a/lib/algorithms/mac.c +++ b/lib/algorithms/mac.c @@ -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, diff --git a/lib/crypto-selftests-pk.c b/lib/crypto-selftests-pk.c index 7bdb0973ff..f336ddc062 100644 --- a/lib/crypto-selftests-pk.c +++ b/lib/crypto-selftests-pk.c @@ -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; diff --git a/tests/cert-tests/data/gost-cert-nogost.pem b/tests/cert-tests/data/gost-cert-nogost.pem index 76fcd3d8b9..cd9459f9fb 100644 --- a/tests/cert-tests/data/gost-cert-nogost.pem +++ b/tests/cert-tests/data/gost-cert-nogost.pem @@ -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 diff --git a/tests/cert-tests/data/gost-cert.pem b/tests/cert-tests/data/gost-cert.pem index bec29b8bb5..cd9459f9fb 100644 --- a/tests/cert-tests/data/gost-cert.pem +++ b/tests/cert-tests/data/gost-cert.pem @@ -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 diff --git a/tests/cert-tests/data/grfc.crt b/tests/cert-tests/data/grfc.crt index c7af541b5f..20f587ea6e 100644 --- a/tests/cert-tests/data/grfc.crt +++ b/tests/cert-tests/data/grfc.crt @@ -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 diff --git a/tests/cert-tests/pkcs7 b/tests/cert-tests/pkcs7 index eed9f068a2..5951a7312b 100755 --- a/tests/cert-tests/pkcs7 +++ b/tests/cert-tests/pkcs7 @@ -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} diff --git a/tests/privkey-keygen.c b/tests/privkey-keygen.c index 31634bd095..565beccb20 100644 --- a/tests/privkey-keygen.c +++ b/tests/privkey-keygen.c @@ -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"); diff --git a/tests/sign-is-secure.c b/tests/sign-is-secure.c index 729e5024b3..3c2d18d93a 100644 --- a/tests/sign-is-secure.c +++ b/tests/sign-is-secure.c @@ -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