From 40d63d09b2d06631f4d2c3d1b167a620d50c99f8 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 5 Nov 2021 14:19:23 +0100 Subject: [PATCH 198/200] rsa: Check keylen constraints for key operations. * cipher/rsa.c (rsa_check_keysize): New. (generate_fips): Factor out the bits check. (rsa_encrypt): Add checking key length. (rsa_decrypt, rsa_sign, rsa_verify): Likewise. -- GnuPG-bug-id: 5512 Co-authored-by: NIIBE Yutaka Signed-off-by: Jakub Jelen --- cipher/rsa.c | 58 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 15 deletions(-) Index: libgcrypt-1.9.4/cipher/rsa.c =================================================================== --- libgcrypt-1.9.4.orig/cipher/rsa.c +++ libgcrypt-1.9.4/cipher/rsa.c @@ -301,14 +301,6 @@ generate_std (RSA_secret_key *sk, unsign gcry_mpi_t f; gcry_random_level_t random_level; - if (fips_mode ()) - { - if (nbits < 1024) - return GPG_ERR_INV_VALUE; - if (transient_key) - return GPG_ERR_INV_VALUE; - } - /* The random quality depends on the transient_key flag. */ random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; @@ -437,6 +429,17 @@ generate_std (RSA_secret_key *sk, unsign } +/* Check the RSA key length is acceptable for key generation or usage */ +static gpg_err_code_t +rsa_check_keysize (unsigned int nbits) +{ + if (fips_mode() && nbits < 2048) + return GPG_ERR_INV_VALUE; + + return GPG_ERR_NO_ERROR; +} + + /**************** * Generate a key pair with a key of size NBITS. * USE_E = 0 let Libcgrypt decide what exponent to use. @@ -466,12 +469,15 @@ generate_fips (RSA_secret_key *sk, unsig unsigned int pbits = nbits/2; unsigned int i; int pqswitch; - gpg_err_code_t ec = GPG_ERR_NO_PRIME; + gpg_err_code_t ec; if (nbits < 1024 || (nbits & 0x1FF)) return GPG_ERR_INV_VALUE; - if (fips_mode() && nbits < 2048) - return GPG_ERR_INV_VALUE; + ec = rsa_check_keysize (nbits); + if (ec) + return ec; + + ec = GPG_ERR_NO_PRIME; /* The random quality depends on the transient_key flag. */ random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; @@ -1360,9 +1366,13 @@ rsa_encrypt (gcry_sexp_t *r_ciph, gcry_s gcry_mpi_t data = NULL; RSA_public_key pk = {NULL, NULL}; gcry_mpi_t ciph = NULL; + unsigned int nbits = rsa_get_nbits (keyparms); + + rc = rsa_check_keysize (nbits); + if (rc) + return rc; - _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT, - rsa_get_nbits (keyparms)); + _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT, nbits); /* Extract the data. */ rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx); @@ -1432,9 +1442,13 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_ gcry_mpi_t plain = NULL; unsigned char *unpad = NULL; size_t unpadlen = 0; + unsigned int nbits = rsa_get_nbits (keyparms); - _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT, - rsa_get_nbits (keyparms)); + rc = rsa_check_keysize (nbits); + if (rc) + return rc; + + _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT, nbits); /* Extract the data. */ rc = _gcry_pk_util_preparse_encval (s_data, rsa_names, &l1, &ctx); @@ -1477,7 +1491,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_ mpi_fdiv_r (data, data, sk.n); /* Allocate MPI for the plaintext. */ - plain = mpi_snew (ctx.nbits); + plain = mpi_snew (nbits); /* We use blinding by default to mitigate timing attacks which can be practically mounted over the network as shown by Brumley and @@ -1485,7 +1499,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_ if ((ctx.flags & PUBKEY_FLAG_NO_BLINDING)) secret (plain, data, &sk); else - secret_blinded (plain, data, &sk, ctx.nbits); + secret_blinded (plain, data, &sk, nbits); if (DBG_CIPHER) log_printmpi ("rsa_decrypt res", plain); @@ -1494,7 +1508,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_ switch (ctx.encoding) { case PUBKEY_ENC_PKCS1: - rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, ctx.nbits, plain); + rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, nbits, plain); mpi_free (plain); plain = NULL; if (!rc) @@ -1503,7 +1517,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_ case PUBKEY_ENC_OAEP: rc = _gcry_rsa_oaep_decode (&unpad, &unpadlen, - ctx.nbits, ctx.hash_algo, + nbits, ctx.hash_algo, plain, ctx.label, ctx.labellen); mpi_free (plain); plain = NULL; @@ -1548,9 +1562,13 @@ rsa_sign (gcry_sexp_t *r_sig, gcry_sexp_ RSA_public_key pk; gcry_mpi_t sig = NULL; gcry_mpi_t result = NULL; + unsigned int nbits = rsa_get_nbits (keyparms); + + rc = rsa_check_keysize (nbits); + if (rc) + return rc; - _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN, - rsa_get_nbits (keyparms)); + _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN, nbits); /* Extract the data. */ rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx); @@ -1588,7 +1606,7 @@ rsa_sign (gcry_sexp_t *r_sig, gcry_sexp_ if ((ctx.flags & PUBKEY_FLAG_NO_BLINDING)) secret (sig, data, &sk); else - secret_blinded (sig, data, &sk, ctx.nbits); + secret_blinded (sig, data, &sk, nbits); if (DBG_CIPHER) log_printmpi ("rsa_sign res", sig); @@ -1650,9 +1668,13 @@ rsa_verify (gcry_sexp_t s_sig, gcry_sexp gcry_mpi_t data = NULL; RSA_public_key pk = { NULL, NULL }; gcry_mpi_t result = NULL; + unsigned int nbits = rsa_get_nbits (keyparms); + + rc = rsa_check_keysize (nbits); + if (rc) + return rc; - _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY, - rsa_get_nbits (keyparms)); + _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY, nbits); /* Extract the data. */ rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx); Index: libgcrypt-1.9.4/tests/basic.c =================================================================== --- libgcrypt-1.9.4.orig/tests/basic.c +++ libgcrypt-1.9.4/tests/basic.c @@ -14172,6 +14172,62 @@ check_pubkey (void) "\x4a\xa6\xf9\xeb\x23\xbf\xa9\x12\x2d\x5b" } }, { + GCRY_PK_RSA, FLAG_CRYPT | FLAG_SIGN | FLAG_GRIP, /* 2k RSA */ + { + "(private-key" + " (rsa" + " (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" + " 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" + " 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" + " 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" + " DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" + " 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" + " 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" + " 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6" + " CB#)\n" + " (e #010001#)\n" + " (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19" + " 8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93" + " 7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12" + " 771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F" + " 5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48" + " EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD" + " 69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84" + " 3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401" + " #)\n" + " (p #00C29D438F115825779631CD665A5739367F3E128ADC29766483A46CA80897E0" + " 79B32881860B8F9A6A04C2614A904F6F2578DAE13EA67CD60AE3D0AA00A1FF9B" + " 441485E44B2DC3D0B60260FBFE073B5AC72FAF67964DE15C8212C389D20DB9CF" + " 54AF6AEF5C4196EAA56495DD30CF709F499D5AB30CA35E086C2A1589D6283F17" + " 83#)\n" + " (q #00D1984135231CB243FE959C0CBEF551EDD986AD7BEDF71EDF447BE3DA27AF46" + " 79C974A6FA69E4D52FE796650623DE70622862713932AA2FD9F2EC856EAEAA77" + " 88B4EA6084DC81C902F014829B18EA8B2666EC41586818E0589E18876065F97E" + " 8D22CE2DA53A05951EC132DCEF41E70A9C35F4ACC268FFAC2ADF54FA1DA110B9" + " 19#)\n" + " (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04" + " 479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4" + " A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9" + " AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7" + " #)))\n", + + "(public-key\n" + " (rsa\n" + " (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" + " 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" + " 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" + " 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" + " DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" + " 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" + " 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" + " 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6" + " CB#)\n" + " (e #010001#)))\n", + + "\xe0\x08\x98\x9b\xb6\x44\xa2\x9a\x83\x37" + "\x47\xdd\x69\x55\xdb\x3a\xac\x89\x6e\x40"} + }, + { GCRY_PK_ELG, FLAG_SIGN | FLAG_CRYPT | FLAG_GRIP, { "(private-key\n"