Index: libgcrypt-1.8.2/cipher/dsa.c =================================================================== --- libgcrypt-1.8.2.orig/cipher/dsa.c +++ libgcrypt-1.8.2/cipher/dsa.c @@ -181,24 +181,91 @@ test_keys (DSA_secret_key *sk, unsigned /* Create a random plaintext. */ _gcry_mpi_randomize (data, qbits, GCRY_WEAK_RANDOM); - /* Sign DATA using the secret key. */ - sign (sig_a, sig_b, data, sk, 0, 0); + /* 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; + gcry_mpi_t s_sig_mpi = NULL; + unsigned char *buf = NULL; + size_t buflen; + + if (_gcry_md_open (&hd, GCRY_MD_SHA256, 0)) + { + log_debug ("gcry_pk_sign failed\n"); + goto leave; + } + + _gcry_mpi_aprint (GCRYMPI_FMT_STD, &buf, &buflen, data); + _gcry_md_write (hd, buf, buflen); + + xfree (buf); + + /* build DSA private key sexp in s_skey */ + sexp_build (&s_skey, NULL, "(private-key (dsa(p %m)(q %m)(g %m)(y %m)(x %m)))", + sk->p, sk->q, sk->g, sk->y, sk->x); + sexp_build (&s_hash, NULL, "(data (flags pkcs1)(hash-algo sha256))"); + if (_gcry_pk_sign_md (&r_sig, hd, s_hash, s_skey)) + { + log_debug ("gcry_pk_sign failed\n"); + goto leave; + } + + /* Check that the signature and the original plaintext differ. */ + if (_gcry_sexp_extract_param (r_sig, NULL, "rs", &r_sig_mpi, &s_sig_mpi, NULL)) + { + log_debug ("extracting signature data failed\n"); + goto leave; + } + + if ( !verify (r_sig_mpi, s_sig_mpi, data, &pk)) + { + log_debug ("Signature failed\n"); + goto leave; /* Signature matches but should not. */ + } + + _gcry_sexp_release (s_hash); + _gcry_md_close (hd); + + /* build DSA public key sexp in s_pkey */ + sexp_build (&s_pkey, NULL, "(public-key (dsa(p %m)(q %m)(g %m)(y %m)))", + pk.p, pk.q, pk.g, pk.y); + sexp_build (&s_hash, NULL, "(data (flags pkcs1)(hash-algo sha256))"); + + if (_gcry_md_open (&hd, GCRY_MD_SHA256, 0)) + log_debug ("gcry_md_open failed\n"); + + _gcry_mpi_aprint (GCRYMPI_FMT_STD, &buf, &buflen, data); + _gcry_md_write (hd, buf, buflen); + + xfree (buf); + + /* verify the signature */ + if (_gcry_pk_verify_md (r_sig, hd, s_hash, s_pkey)) + { + log_debug ("gcry_pk_verify failed\n"); + goto leave; /* Signature does not match. */ + } - /* Verify the signature using the public key. */ - if ( verify (sig_a, sig_b, data, &pk) ) - goto leave; /* Signature does not match. */ - - /* Modify the data and check that the signing fails. */ - mpi_add_ui (data, data, 1); - if ( !verify (sig_a, sig_b, data, &pk) ) - goto leave; /* Signature matches but should not. */ - - result = 0; /* The test succeeded. */ + result = 0; /* The test succeeded. */ leave: _gcry_mpi_release (sig_b); _gcry_mpi_release (sig_a); _gcry_mpi_release (data); + + _gcry_sexp_release (s_skey); + _gcry_sexp_release (s_pkey); + _gcry_sexp_release (s_hash); + _gcry_sexp_release (r_sig); + _gcry_mpi_release (r_sig_mpi); + _gcry_mpi_release (s_sig_mpi); + _gcry_md_close (hd); + return result; }