Index: libgcrypt-1.8.2/cipher/rsa.c =================================================================== --- libgcrypt-1.8.2.orig/cipher/rsa.c +++ libgcrypt-1.8.2/cipher/rsa.c @@ -159,27 +159,103 @@ test_keys (RSA_secret_key *sk, unsigned /* Create another random plaintext as data for signature checking. */ _gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM); - /* Use the RSA secret function to create a signature of the plaintext. */ - secret (signature, plaintext, sk); + /* Use the gcry_pk_sign_md API in order to comply with FIPS 140-2, + * which requires full signature operation for PCT (hashing + + * asymmetric operation */ + gcry_sexp_t s_skey = NULL; + gcry_sexp_t s_pkey = NULL; + gcry_sexp_t r_sig = NULL; + gcry_sexp_t s_hash = NULL; + gcry_md_hd_t hd = NULL; + gcry_mpi_t r_sig_mpi = NULL; + unsigned char *buf = NULL; + size_t buflen; - /* Use the RSA public function to verify this signature. */ - public (decr_plaintext, signature, &pk); - if (mpi_cmp (decr_plaintext, plaintext)) - goto leave; /* Signature does not match. */ - - /* Modify the signature and check that the signing fails. */ - mpi_add_ui (signature, signature, 1); - public (decr_plaintext, signature, &pk); - if (!mpi_cmp (decr_plaintext, plaintext)) - goto leave; /* Signature matches but should not. */ + if (_gcry_md_open (&hd, GCRY_MD_SHA256, 0)) + { + if (DBG_CIPHER) + log_debug ("gcry_pk_sign/open failed\n"); + goto leave_hash; + } + + _gcry_mpi_aprint (GCRYMPI_FMT_STD, &buf, &buflen, plaintext); + _gcry_md_write (hd, buf, buflen); + + xfree (buf); + buf = NULL; + + /* build RSA private key sexp in s_skey */ + sexp_build (&s_skey, NULL, + "(private-key (rsa(n %m)(e %m)(d %m)(p %m)(q %m)))", + sk->n, sk->e, sk->d, sk->p, sk->q); + sexp_build (&s_hash, NULL, + "(data (flags pkcs1)(hash-algo sha256))"); + + if (_gcry_pk_sign_md (&r_sig, hd, s_hash, s_skey)) + { + if (DBG_CIPHER) + log_debug ("gcry_pk_sign failed\n"); + goto leave_hash; + } + + /* Check that the signature and the original plaintext differ. */ + if (_gcry_sexp_extract_param (r_sig, "sig-val!rsa", "s", &r_sig_mpi, NULL)) + { + if (DBG_CIPHER) + log_debug ("extracting signature data failed\n"); + goto leave_hash; + } + + if (!mpi_cmp (r_sig_mpi, plaintext)) + { + if (DBG_CIPHER) + log_debug ("Signature failed\n"); + goto leave_hash; /* Signature and plaintext match but should not. */ + } + + _gcry_sexp_release (s_hash); + _gcry_md_close (hd); + + /* build RSA public key sexp in s_pkey */ + sexp_build (&s_pkey, NULL, "(public-key (rsa(n %m)(e %m)))", pk.n, pk.e); + sexp_build (&s_hash, NULL, "(data (flags pkcs1)(hash-algo sha256))"); + + if (_gcry_md_open (&hd, GCRY_MD_SHA256, 0)) + { + if (DBG_CIPHER) + log_debug ("gcry_md_open failed\n"); + } + + _gcry_mpi_aprint (GCRYMPI_FMT_STD, &buf, &buflen, plaintext); + _gcry_md_write (hd, buf, buflen); + + xfree (buf); + buf = NULL; + + /* verify the signature */ + if (_gcry_pk_verify_md (r_sig, hd, s_hash, s_pkey)) + { + if (DBG_CIPHER) + log_debug ("gcry_pk_verify failed\n"); + goto leave_hash; /* Signature does not match. */ + } result = 0; /* All tests succeeded. */ + leave_hash: + _gcry_sexp_release (s_skey); + _gcry_sexp_release (s_pkey); + _gcry_sexp_release (s_hash); + _gcry_sexp_release (r_sig); + _gcry_md_close (hd); + _gcry_mpi_release (r_sig_mpi); + leave: _gcry_mpi_release (signature); _gcry_mpi_release (decr_plaintext); _gcry_mpi_release (ciphertext); _gcry_mpi_release (plaintext); + return result; } @@ -1903,7 +1979,7 @@ selftest_encr_2048 (gcry_sexp_t pkey, gc /* This sexp trickery is to prevent the use of blinding. * The flag doesn't get inherited by encr, so we have to * derive a new sexp from the ciphertext */ - char buf[1024]; + unsigned char buf[1024]; memset(buf, 0, sizeof(buf)); err = _gcry_mpi_print (GCRYMPI_FMT_STD, buf, sizeof buf, NULL, ciphertext); if (err) @@ -2012,6 +2088,7 @@ selftests_rsa (selftest_report_func_t re sexp_release (skey); if (report) report ("pubkey", GCRY_PK_RSA, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; }