[PATCH 08/10] md, cipher: allow internal users to skip fast random poll

Jussi Kivilinna <[email protected]> Sun, 2 Aug 2026 12:55:13 +0300
Newsgroups gmane.comp.encryption.gpg.libgcrypt.devel
Message-ID <[email protected]>
* cipher/md.c (md_open): Add 'fast_rnd_poll' parameter.
(_gcry_md_open_internal): New.
(_gcry_md_open): Forward to '_gcry_md_open_internal'.
(_gcry_md_hash_buffer, _gcry_md_hash_buffers_extract): Do not poll on
the one-shot fallback path.
* cipher/cipher.c (_gcry_cipher_open_internal): Add 'fast_rnd_poll'
parameter.
(_gcry_cipher_open): Request poll.
* src/cipher.h (_gcry_cipher_open_internal): Move declaration...
* src/gcrypt-int.h (_gcry_cipher_open_internal): ...to here.
(_gcry_md_open_internal): New.
* cipher/kyber.c (shake128_init): Open handle without poll.
* cipher/dilithium.c (shake128_init, shake256_init): Likewise.
* cipher/des.c (selftest): Likewise.
* cipher/dsa-common.c (_gcry_dsa_gen_rfc6979_k): Likewise.
* cipher/ecc-sm2.c (kdf_x9_63, _gcry_ecc_sm2_encrypt)
(_gcry_ecc_sm2_decrypt): Likewise.
* cipher/ecc.c (test_keys_fips, selftest_hash_sign): Likewise.
* cipher/hash-common.c (_gcry_hash_selftest_check_one): Likewise.
* cipher/pubkey.c (_gcry_pk_get_keygrip): Likewise.
* cipher/rijndael.c (selftest_fips_128_38a): Likewise.
* cipher/rsa-common.c (mgf1, _gcry_rsa_pss_encode)
(_gcry_rsa_pss_verify): Likewise.
* cipher/rsa.c (test_keys_fips, selftest_hash_sign_2048): Likewise.
* random/random-drbg.c (drbg_hash_init, drbg_hmac_init, drbg_sym_init):
Likewise.
* src/fips.c (hmac256_check): Likewise.
* cipher/mceliece6688128f.c (crypto_xof_shake256): Use
'_gcry_md_hash_buffers_extract'.
* cipher/mceliece6688128f.sh: Likewise.
* cipher/kdf.c (openpgp_s2k, _gcry_kdf_pkdf2, prng_aes_ctr_init)
(onestep_kdf_open, x963_kdf_open): Use internal interface and keep
poll.
* cipher/mac-cmac.c (cmac_open): Likewise.
* cipher/mac-gmac.c (gmac_open): Likewise.
* cipher/mac-hmac.c (hmac_open, check_one): Likewise.
* cipher/mac-poly1305.c (poly1305mac_open): Likewise.
--

'md_open' and 'cipher_open' call '_gcry_fast_random_poll', which takes
pool lock, reads RDRAND and mixes CSPRNG pool. ML-KEM and ML-DSA
route SHAKE through the md interface and open one handle per polynomial,
so ML-DSA-87 key generation paid for 72 polls and ML-KEM-768 for nine on
every operation. Poll exists for applications that never call
'gcry_control(GCRYCTL_FAST_POLL)' and adds nothing for handles
that the library opens for its own hashing.

Benchmark on AMD Ryzen 9 9950X3D, usec/operation, quick random enabled
to exclude entropy gathering:

                      before    after   speedup
 ML-KEM-512   keygen   22.70    18.57     1.22x
              encap    23.70    19.45     1.22x
              decap    24.13    20.03     1.20x
 ML-KEM-768   keygen   38.02    28.63     1.33x
              encap    37.79    28.34     1.33x
              decap    40.53    30.75     1.32x
 ML-KEM-1024  keygen   58.70    41.91     1.40x
              encap    56.40    39.95     1.41x
              decap    61.22    44.73     1.37x
 ML-DSA-44    keygen   59.22    33.96     1.74x
              sign    191.90   143.90     1.33x
              verify   56.76    35.79     1.59x
 ML-DSA-65    keygen   98.62    54.58     1.81x
              sign    304.21   225.64     1.35x
              verify   95.11    57.64     1.65x
 ML-DSA-87    keygen  164.97    90.05     1.83x
              sign    377.63   275.93     1.37x
              verify  157.23    95.03     1.65x

Signed-off-by: Jussi Kivilinna <[email protected]>
---
 cipher/cipher.c            |  8 +++++---
 cipher/des.c               |  2 +-
 cipher/dilithium.c         |  4 ++--
 cipher/dsa-common.c        |  3 ++-
 cipher/ecc-sm2.c           |  6 +++---
 cipher/ecc.c               |  4 ++--
 cipher/hash-common.c       |  2 +-
 cipher/kdf.c               | 15 +++++++++------
 cipher/kyber.c             |  2 +-
 cipher/mac-cmac.c          |  2 +-
 cipher/mac-gmac.c          |  2 +-
 cipher/mac-hmac.c          |  4 ++--
 cipher/mac-poly1305.c      |  2 +-
 cipher/mceliece6688128f.c  | 14 ++++++++------
 cipher/mceliece6688128f.sh | 14 ++++++++------
 cipher/md.c                | 32 +++++++++++++++++++++-----------
 cipher/pubkey.c            |  2 +-
 cipher/rijndael.c          |  6 ++++--
 cipher/rsa-common.c        |  6 +++---
 cipher/rsa.c               |  4 ++--
 random/random-drbg.c       | 14 ++++++++------
 src/cipher.h               |  5 -----
 src/fips.c                 |  2 +-
 src/gcrypt-int.h           |  6 ++++++
 24 files changed, 93 insertions(+), 68 deletions(-)

diff --git a/cipher/cipher.c b/cipher/cipher.c
index fc130907..72227714 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
@@ -497,7 +497,7 @@ _gcry_cipher_open (gcry_cipher_hd_t *handle,
   if (mode >= GCRY_CIPHER_MODE_INTERNAL)
     rc = GPG_ERR_INV_CIPHER_MODE;
   else
-    rc = _gcry_cipher_open_internal (&h, algo, mode, flags);
+    rc = _gcry_cipher_open_internal (&h, algo, mode, flags, 1);
 
   *handle = rc ? NULL : h;
 
@@ -567,7 +567,8 @@ _gcry_cipher_mode_fips_compliance (int mode)
 
 gcry_err_code_t
 _gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
-			    int algo, int mode, unsigned int flags)
+			    int algo, int mode, unsigned int flags,
+			    int fast_rnd_poll)
 {
   int secure = !!(flags & GCRY_CIPHER_SECURE);
   gcry_cipher_spec_t *spec;
@@ -576,7 +577,8 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
 
   /* If the application missed to call the random poll function, we do
      it here to ensure that it is used once in a while. */
-  _gcry_fast_random_poll ();
+  if (fast_rnd_poll)
+    _gcry_fast_random_poll ();
 
   spec = spec_from_algo (algo);
   if (!spec)
diff --git a/cipher/des.c b/cipher/des.c
index c28fcf5a..dcdf6a2c 100644
--- a/cipher/des.c
+++ b/cipher/des.c
@@ -1217,7 +1217,7 @@ selftest (void)
     unsigned char *p;
     gcry_md_hd_t h;
 
-    if (_gcry_md_open (&h, GCRY_MD_SHA1, 0))
+    if (_gcry_md_open_internal (&h, GCRY_MD_SHA1, 0, 0))
       return "SHA1 not available";
 
     for (i = 0; i < 64; ++i)
diff --git a/cipher/dilithium.c b/cipher/dilithium.c
index 212c4afe..c5e12fb1 100644
--- a/cipher/dilithium.c
+++ b/cipher/dilithium.c
@@ -276,7 +276,7 @@ shake128_init (keccak_state *state)
 {
   gcry_err_code_t ec;
 
-  ec = _gcry_md_open (&state->h, GCRY_MD_SHAKE128, 0);
+  ec = _gcry_md_open_internal (&state->h, GCRY_MD_SHAKE128, 0, 0);
   if (ec)
     log_fatal ("internal md_open failed: %d\n", ec);
 }
@@ -310,7 +310,7 @@ shake256_init (keccak_state *state)
 {
   gcry_err_code_t ec;
 
-  ec = _gcry_md_open (&state->h, GCRY_MD_SHAKE256, 0);
+  ec = _gcry_md_open_internal (&state->h, GCRY_MD_SHAKE256, 0, 0);
   if (ec)
     log_fatal ("internal md_open failed: %d\n", ec);
 }
diff --git a/cipher/dsa-common.c b/cipher/dsa-common.c
index 82b9c9dc..4924bff6 100644
--- a/cipher/dsa-common.c
+++ b/cipher/dsa-common.c
@@ -245,7 +245,8 @@ _gcry_dsa_gen_rfc6979_k (gcry_mpi_t *r_k,
     goto leave;
 
   /* Create a handle to compute the HMACs.  */
-  rc = _gcry_md_open (&hd, halgo, (GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC));
+  rc = _gcry_md_open_internal (&hd, halgo,
+			       (GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC), 0);
   if (rc)
     goto leave;
 
diff --git a/cipher/ecc-sm2.c b/cipher/ecc-sm2.c
index 8c3241e4..6625c590 100644
--- a/cipher/ecc-sm2.c
+++ b/cipher/ecc-sm2.c
@@ -49,7 +49,7 @@ kdf_x9_63 (int algo, const void *in, size_t inlen, void *out, size_t outlen)
   size_t rlen = outlen;
   size_t len;
 
-  rc = _gcry_md_open (&hd, algo, 0);
+  rc = _gcry_md_open_internal (&hd, algo, 0, 0);
   if (rc)
     return rc;
 
@@ -174,7 +174,7 @@ _gcry_ecc_sm2_encrypt (gcry_sexp_t *r_ciph, gcry_mpi_t input, mpi_ec_t ec)
 
   /* hash(x2 || IN || y2) */
   mdlen = _gcry_md_get_algo_dlen (algo);
-  rc = _gcry_md_open (&md, algo, 0);
+  rc = _gcry_md_open_internal (&md, algo, 0, 0);
   if (rc)
     goto leave;
   _gcry_md_write (md, raw, MPI_NBYTES(x2));
@@ -317,7 +317,7 @@ _gcry_ecc_sm2_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t data_list, mpi_ec_t ec)
 
     /* Hash(x2 || IN || y2) == C3 */
     mdlen = _gcry_md_get_algo_dlen (algo);
-    rc = _gcry_md_open (&md, algo, 0);
+    rc = _gcry_md_open_internal (&md, algo, 0, 0);
     if (rc)
       goto leave_main;
     _gcry_md_write (md, raw, MPI_NBYTES(x2));
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 95dc0535..18ef5837 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -427,7 +427,7 @@ test_keys_fips (gcry_sexp_t skey)
   _gcry_randomize (plaintext, sizeof plaintext, GCRY_WEAK_RANDOM);
 
   /* Open MD context and feed the random data in */
-  rc = _gcry_md_open (&hd, GCRY_MD_SHA256, 0);
+  rc = _gcry_md_open_internal (&hd, GCRY_MD_SHA256, 0, 0);
   if (rc)
     {
       log_error ("ECDSA operation: failed to initialize MD context: %s\n", gpg_strerror (rc));
@@ -2069,7 +2069,7 @@ selftest_hash_sign (gcry_sexp_t pkey, gcry_sexp_t skey, const char *tmpl,
   gcry_mpi_t calculated_s = NULL;
   int cmp;
 
-  err = _gcry_md_open (&hd, md_algo, 0);
+  err = _gcry_md_open_internal (&hd, md_algo, 0, 0);
   if (err)
     {
       errtxt = "gcry_md_open failed";
diff --git a/cipher/hash-common.c b/cipher/hash-common.c
index 03cd11f0..1b0ee64e 100644
--- a/cipher/hash-common.c
+++ b/cipher/hash-common.c
@@ -56,7 +56,7 @@ _gcry_hash_selftest_check_one (int algo,
   if (_gcry_md_get_algo_dlen (algo) != expectlen)
     expect_xof = 1;
 
-  err = _gcry_md_open (&hd, algo, 0);
+  err = _gcry_md_open_internal (&hd, algo, 0, 0);
   if (err)
     return "gcry_md_open failed";
 
diff --git a/cipher/kdf.c b/cipher/kdf.c
index 66eff6c6..644888fc 100644
--- a/cipher/kdf.c
+++ b/cipher/kdf.c
@@ -54,7 +54,8 @@ openpgp_s2k (const void *passphrase, size_t passphraselen,
 
   secmode = _gcry_is_secure (passphrase) || _gcry_is_secure (keybuffer);
 
-  ec = _gcry_md_open (&md, hashalgo, secmode? GCRY_MD_FLAG_SECURE : 0);
+  ec = _gcry_md_open_internal (&md, hashalgo,
+                              secmode? GCRY_MD_FLAG_SECURE : 0, 1);
   if (ec)
     return ec;
 
@@ -173,8 +174,9 @@ _gcry_kdf_pkdf2 (const void *passphrase, size_t passphraselen,
   tbuf = sbuf + saltlen + 4;
   ubuf = tbuf + hlen;
 
-  ec = _gcry_md_open (&md, hashalgo, (GCRY_MD_FLAG_HMAC
-                                      | (secmode?GCRY_MD_FLAG_SECURE:0)));
+  ec = _gcry_md_open_internal (&md, hashalgo,
+                               (GCRY_MD_FLAG_HMAC
+                                | (secmode?GCRY_MD_FLAG_SECURE:0)), 1);
   if (ec)
     {
       xfree (sbuf);
@@ -991,7 +993,8 @@ prng_aes_ctr_init (gcry_cipher_hd_t *hd_p, balloon_ctx_t b,
   blklen = _gcry_cipher_get_algo_blklen (cipher_algo);
 
   b->md_spec->hash_buffers (key, b->blklen, iov, iov_count);
-  ec = _gcry_cipher_open (&hd, cipher_algo, GCRY_CIPHER_MODE_CTR, 0);
+  ec = _gcry_cipher_open_internal (&hd, cipher_algo, GCRY_CIPHER_MODE_CTR,
+                                   0, 1);
   if (ec)
     return ec;
 
@@ -1465,7 +1468,7 @@ onestep_kdf_open (gcry_kdf_hd_t *hd, int hashalgo,
       xfree (o);
       return GPG_ERR_DIGEST_ALGO;
     }
-  ec = _gcry_md_open (&o->md, hashalgo, 0);
+  ec = _gcry_md_open_internal (&o->md, hashalgo, 0, 1);
   if (ec)
     {
       xfree (o);
@@ -1925,7 +1928,7 @@ x963_kdf_open (gcry_kdf_hd_t *hd, int hashalgo,
       xfree (o);
       return GPG_ERR_DIGEST_ALGO;
     }
-  ec = _gcry_md_open (&o->md, hashalgo, 0);
+  ec = _gcry_md_open_internal (&o->md, hashalgo, 0, 1);
   if (ec)
     {
       xfree (o);
diff --git a/cipher/kyber.c b/cipher/kyber.c
index dcb7e671..82d906f1 100644
--- a/cipher/kyber.c
+++ b/cipher/kyber.c
@@ -215,7 +215,7 @@ shake128_init (keccak_state *state)
 {
   gcry_err_code_t ec;
 
-  ec = _gcry_md_open (&state->h, GCRY_MD_SHAKE128, 0);
+  ec = _gcry_md_open_internal (&state->h, GCRY_MD_SHAKE128, 0, 0);
   if (ec)
     log_fatal ("internal md_open failed: %d\n", ec);
 }
diff --git a/cipher/mac-cmac.c b/cipher/mac-cmac.c
index 2274bd8e..04757750 100644
--- a/cipher/mac-cmac.c
+++ b/cipher/mac-cmac.c
@@ -79,7 +79,7 @@ cmac_open (gcry_mac_hd_t h)
   flags = (secure ? GCRY_CIPHER_SECURE : 0);
 
   err = _gcry_cipher_open_internal (&hd, cipher_algo, GCRY_CIPHER_MODE_CMAC,
-                                    flags);
+                                    flags, 1);
   if (err)
     return err;
 
diff --git a/cipher/mac-gmac.c b/cipher/mac-gmac.c
index b5610c44..a6c725c7 100644
--- a/cipher/mac-gmac.c
+++ b/cipher/mac-gmac.c
@@ -66,7 +66,7 @@ gmac_open (gcry_mac_hd_t h)
   flags = (secure ? GCRY_CIPHER_SECURE : 0);
 
   err = _gcry_cipher_open_internal (&hd, cipher_algo, GCRY_CIPHER_MODE_GCM,
-                                    flags);
+                                    flags, 1);
   if (err)
     return err;
 
diff --git a/cipher/mac-hmac.c b/cipher/mac-hmac.c
index 94fe2c9f..31ee4a46 100644
--- a/cipher/mac-hmac.c
+++ b/cipher/mac-hmac.c
@@ -115,7 +115,7 @@ hmac_open (gcry_mac_hd_t h)
   flags = GCRY_MD_FLAG_HMAC;
   flags |= (secure ? GCRY_MD_FLAG_SECURE : 0);
 
-  err = _gcry_md_open (&hd, md_algo, flags);
+  err = _gcry_md_open_internal (&hd, md_algo, flags, 1);
   if (err)
     return err;
 
@@ -255,7 +255,7 @@ check_one (int algo,
       if (_gcry_md_get_algo_dlen (algo) != expectlen)
         return "invalid tests data";
     }
-  if (_gcry_md_open (&hd, algo, GCRY_MD_FLAG_HMAC))
+  if (_gcry_md_open_internal (&hd, algo, GCRY_MD_FLAG_HMAC, 1))
     return "gcry_md_open failed";
   if (_gcry_md_setkey (hd, key, keylen))
     {
diff --git a/cipher/mac-poly1305.c b/cipher/mac-poly1305.c
index dfaef446..53782bec 100644
--- a/cipher/mac-poly1305.c
+++ b/cipher/mac-poly1305.c
@@ -92,7 +92,7 @@ poly1305mac_open (gcry_mac_hd_t h)
     }
 
   err = _gcry_cipher_open_internal (&mac_ctx->hd, cipher_algo,
-				    GCRY_CIPHER_MODE_ECB, flags);
+				    GCRY_CIPHER_MODE_ECB, flags, 1);
   if (err)
     goto err_free;
 
diff --git a/cipher/mceliece6688128f.c b/cipher/mceliece6688128f.c
index 3130c0cc..99bb4b4d 100644
--- a/cipher/mceliece6688128f.c
+++ b/cipher/mceliece6688128f.c
@@ -144,15 +144,17 @@ randombytes (uint8_t *out, size_t outlen)
 static void crypto_xof_shake256(unsigned char *h,long long hlen,
 				const unsigned char *m,long long mlen)
 {
-  gcry_md_hd_t mdh;
+  gcry_buffer_t iov =
+  {
+    .data = (void *)m,
+    .off = 0,
+    .len = mlen
+  };
   gcry_err_code_t ec;
 
-  ec = _gcry_md_open (&mdh, GCRY_MD_SHAKE256, 0);
+  ec = _gcry_md_hash_buffers_extract (GCRY_MD_SHAKE256, 0, h, hlen, &iov, 1);
   if (ec)
-    log_fatal ("internal md_open failed: %d\n", ec);
-  _gcry_md_write (mdh, m, mlen);
-  _gcry_md_extract (mdh, GCRY_MD_SHAKE256, h, hlen);
-  _gcry_md_close (mdh);
+    log_fatal ("internal shake256 failed: %d\n", ec);
 }
 /* from libmceliece-20230612/include-build/crypto_declassify.h */
 #ifndef crypto_declassify_h
diff --git a/cipher/mceliece6688128f.sh b/cipher/mceliece6688128f.sh
index 84245432..34917b98 100755
--- a/cipher/mceliece6688128f.sh
+++ b/cipher/mceliece6688128f.sh
@@ -138,15 +138,17 @@ randombytes (uint8_t *out, size_t outlen)
 static void crypto_xof_shake256(unsigned char *h,long long hlen,
 				const unsigned char *m,long long mlen)
 {
-  gcry_md_hd_t mdh;
+  gcry_buffer_t iov =
+  {
+    .data = (void *)m,
+    .off = 0,
+    .len = mlen
+  };
   gcry_err_code_t ec;
 
-  ec = _gcry_md_open (&mdh, GCRY_MD_SHAKE256, 0);
+  ec = _gcry_md_hash_buffers_extract (GCRY_MD_SHAKE256, 0, h, hlen, &iov, 1);
   if (ec)
-    log_fatal ("internal md_open failed: %d\n", ec);
-  _gcry_md_write (mdh, m, mlen);
-  _gcry_md_extract (mdh, GCRY_MD_SHAKE256, h, hlen);
-  _gcry_md_close (mdh);
+    log_fatal ("internal shake256 failed: %d\n", ec);
 }
 EOF
 N=16
diff --git a/cipher/md.c b/cipher/md.c
index 183f36cc..839f84f1 100644
--- a/cipher/md.c
+++ b/cipher/md.c
@@ -481,7 +481,7 @@ check_digest_algo (int algo)
  * may be 0.
  */
 static gcry_err_code_t
-md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
+md_open (gcry_md_hd_t *h, int algo, unsigned int flags, int fast_rnd_poll)
 {
   gcry_err_code_t err = 0;
   int secure = !!(flags & GCRY_MD_FLAG_SECURE);
@@ -539,7 +539,8 @@ md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
   if (! err)
     {
       /* Hmmm, should we really do that? - yes [-wk] */
-      _gcry_fast_random_poll ();
+      if (fast_rnd_poll)
+	_gcry_fast_random_poll ();
 
       if (algo)
 	{
@@ -555,13 +556,10 @@ md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
   return err;
 }
 
-/* Create a message digest object for algorithm ALGO.  FLAGS may be
-   given as an bitwise OR of the gcry_md_flags values.  ALGO may be
-   given as 0 if the algorithms to be used are later set using
-   gcry_md_enable. H is guaranteed to be a valid handle or NULL on
-   error.  */
+
 gcry_err_code_t
-_gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
+_gcry_md_open_internal (gcry_md_hd_t *h, int algo, unsigned int flags,
+                        int fast_rnd_poll)
 {
   gcry_err_code_t rc;
   gcry_md_hd_t hd;
@@ -571,7 +569,7 @@ _gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
                  | GCRY_MD_FLAG_BUGEMU1)))
     rc = GPG_ERR_INV_ARG;
   else
-    rc = md_open (&hd, algo, flags);
+    rc = md_open (&hd, algo, flags, fast_rnd_poll);
 
   if (!rc && fips_mode ())
     {
@@ -613,6 +611,18 @@ _gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
 }
 
 
+/* Create a message digest object for algorithm ALGO.  FLAGS may be
+   given as an bitwise OR of the gcry_md_flags values.  ALGO may be
+   given as 0 if the algorithms to be used are later set using
+   gcry_md_enable. H is guaranteed to be a valid handle or NULL on
+   error.  */
+gcry_err_code_t
+_gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
+{
+  return _gcry_md_open_internal(h, algo, flags, 1);
+}
+
+
 
 static gcry_err_code_t
 md_enable (gcry_md_hd_t hd, int algorithm)
@@ -1406,7 +1416,7 @@ _gcry_md_hash_buffer (int algo, void *digest,
       gcry_md_hd_t h;
       gpg_err_code_t err;
 
-      err = md_open (&h, algo, 0);
+      err = md_open (&h, algo, 0, 0);
       if (err)
         log_bug ("gcry_md_open failed for algo %d: %s",
                 algo, gpg_strerror (gcry_error(err)));
@@ -1487,7 +1497,7 @@ _gcry_md_hash_buffers_extract (int algo, unsigned int flags, void *digest,
       gcry_md_hd_t h;
       gpg_err_code_t rc;
 
-      rc = md_open (&h, algo, (hmac? GCRY_MD_FLAG_HMAC:0));
+      rc = md_open (&h, algo, (hmac? GCRY_MD_FLAG_HMAC:0), 0);
       if (rc)
         return rc;
 
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index 7120c24f..3f05b862 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -1034,7 +1034,7 @@ _gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
   if (!elems)
     goto fail; /* No grip parameter.  */
 
-  if (_gcry_md_open (&md, GCRY_MD_SHA1, 0))
+  if (_gcry_md_open_internal (&md, GCRY_MD_SHA1, 0, 0))
     goto fail;
 
   if (spec->comp_keygrip)
diff --git a/cipher/rijndael.c b/cipher/rijndael.c
index cf7f4c23..647334c9 100644
--- a/cipher/rijndael.c
+++ b/cipher/rijndael.c
@@ -2049,10 +2049,12 @@ selftest_fips_128_38a (int requested_mode)
   if (tvi == DIM (tv))
     Fail ("no test data for this mode");
 
-  err = _gcry_cipher_open (&hdenc, GCRY_CIPHER_AES, tv[tvi].mode, 0);
+  err = _gcry_cipher_open_internal (&hdenc, GCRY_CIPHER_AES, tv[tvi].mode, 0,
+				    0);
   if (err)
     Fail ("open");
-  err = _gcry_cipher_open (&hddec, GCRY_CIPHER_AES, tv[tvi].mode, 0);
+  err = _gcry_cipher_open_internal (&hddec, GCRY_CIPHER_AES, tv[tvi].mode, 0,
+				    0);
   if (err)
     Fail ("open");
   err = _gcry_cipher_setkey (hdenc, tv[tvi].key,  sizeof tv[tvi].key);
diff --git a/cipher/rsa-common.c b/cipher/rsa-common.c
index c1d2dcd5..6427b853 100644
--- a/cipher/rsa-common.c
+++ b/cipher/rsa-common.c
@@ -435,7 +435,7 @@ mgf1 (unsigned char *output, size_t outlen, unsigned char *seed, size_t seedlen,
   gcry_md_hd_t hd;
   gcry_err_code_t err;
 
-  err = _gcry_md_open (&hd, algo, 0);
+  err = _gcry_md_open_internal (&hd, algo, 0, 0);
   if (err)
     return err;
 
@@ -834,7 +834,7 @@ _gcry_rsa_pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo,
 
   /* This code is implemented as described by rfc-3447 9.1.1.  */
 
-  rc = _gcry_md_open (&hd, algo, 0);
+  rc = _gcry_md_open_internal (&hd, algo, 0, 0);
   if (rc)
     return rc;
 
@@ -1005,7 +1005,7 @@ _gcry_rsa_pss_verify (gcry_mpi_t value, int hashed_already,
 
   /* This code is implemented as described by rfc-3447 9.1.2.  */
 
-  rc = _gcry_md_open (&hd, algo, 0);
+  rc = _gcry_md_open_internal (&hd, algo, 0, 0);
   if (rc)
     return rc;
 
diff --git a/cipher/rsa.c b/cipher/rsa.c
index e3b1891c..9bc0a899 100644
--- a/cipher/rsa.c
+++ b/cipher/rsa.c
@@ -192,7 +192,7 @@ test_keys_fips (gcry_sexp_t skey)
   _gcry_randomize (plaintext, sizeof plaintext, GCRY_WEAK_RANDOM);
 
   /* Open MD context and feed the random data in */
-  ec = _gcry_md_open (&hd, GCRY_MD_SHA256, 0);
+  ec = _gcry_md_open_internal (&hd, GCRY_MD_SHA256, 0, 0);
   if (ec)
     goto leave;
   _gcry_md_write (hd, plaintext, sizeof(plaintext));
@@ -1924,7 +1924,7 @@ selftest_hash_sign_2048 (gcry_sexp_t pkey, gcry_sexp_t skey)
   gcry_mpi_t ref_mpi = NULL;
   gcry_mpi_t sig_mpi = NULL;
 
-  err = _gcry_md_open (&hd, md_algo, 0);
+  err = _gcry_md_open_internal (&hd, md_algo, 0, 0);
   if (err)
     {
       errtxt = "gcry_md_open failed";
diff --git a/random/random-drbg.c b/random/random-drbg.c
index 323c0dd9..bb7d7b95 100644
--- a/random/random-drbg.c
+++ b/random/random-drbg.c
@@ -2529,7 +2529,7 @@ drbg_hash_init (drbg_state_t drbg)
   gcry_md_hd_t hd;
   gpg_error_t err;
 
-  err = _gcry_md_open (&hd, drbg->core->backend_cipher, 0);
+  err = _gcry_md_open_internal (&hd, drbg->core->backend_cipher, 0, 0);
   if (err)
     return err;
 
@@ -2544,7 +2544,8 @@ drbg_hmac_init (drbg_state_t drbg)
   gcry_md_hd_t hd;
   gpg_error_t err;
 
-  err = _gcry_md_open (&hd, drbg->core->backend_cipher, GCRY_MD_FLAG_HMAC);
+  err = _gcry_md_open_internal (&hd, drbg->core->backend_cipher,
+				GCRY_MD_FLAG_HMAC, 0);
   if (err)
     return err;
 
@@ -2598,8 +2599,8 @@ drbg_sym_init (drbg_state_t drbg)
   gcry_cipher_hd_t hd;
   gpg_error_t err;
 
-  err = _gcry_cipher_open (&hd, drbg->core->backend_cipher,
-			   GCRY_CIPHER_MODE_ECB, 0);
+  err = _gcry_cipher_open_internal (&hd, drbg->core->backend_cipher,
+				    GCRY_CIPHER_MODE_ECB, 0, 0);
   if (err)
     {
       drbg_sym_fini (drbg);
@@ -2607,8 +2608,9 @@ drbg_sym_init (drbg_state_t drbg)
     }
   drbg->priv_data = hd;
 
-  err = _gcry_cipher_open (&drbg->ctr_handle, drbg->core->backend_cipher,
-			   GCRY_CIPHER_MODE_CTR, 0);
+  err = _gcry_cipher_open_internal (&drbg->ctr_handle,
+				    drbg->core->backend_cipher,
+				    GCRY_CIPHER_MODE_CTR, 0, 0);
   if (err)
     {
       drbg_sym_fini (drbg);
diff --git a/src/cipher.h b/src/cipher.h
index 14cb6fc6..46311c8b 100644
--- a/src/cipher.h
+++ b/src/cipher.h
@@ -108,11 +108,6 @@ enum gcry_cipher_internal_modes
   };
 
 
-/*-- cipher.c --*/
-gcry_err_code_t _gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
-					    int algo, int mode,
-					    unsigned int flags);
-
 /*-- cipher-cmac.c --*/
 gcry_err_code_t _gcry_cipher_cmac_authenticate
 /*           */ (gcry_cipher_hd_t c, const unsigned char *abuf, size_t abuflen);
diff --git a/src/fips.c b/src/fips.c
index d1aff8a5..c5ccf4f4 100644
--- a/src/fips.c
+++ b/src/fips.c
@@ -930,7 +930,7 @@ hmac256_check (const char *filename, const char *key)
       return err;
     }
 
-  err = _gcry_md_open (&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
+  err = _gcry_md_open_internal (&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC, 0);
   if (err)
     {
       fclose (fp);
diff --git a/src/gcrypt-int.h b/src/gcrypt-int.h
index a0861f8a..2f120e22 100644
--- a/src/gcrypt-int.h
+++ b/src/gcrypt-int.h
@@ -49,6 +49,10 @@ typedef struct mpi_ec_ctx_s *mpi_ec_t;
 
 gpg_err_code_t _gcry_cipher_open (gcry_cipher_hd_t *handle,
                                   int algo, int mode, unsigned int flags);
+gcry_err_code_t _gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
+                                            int algo, int mode,
+                                            unsigned int flags,
+                                            int fast_rnd_poll);
 void _gcry_cipher_close (gcry_cipher_hd_t h);
 gpg_err_code_t _gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer,
                              size_t buflen);
@@ -145,6 +149,8 @@ gpg_err_code_t _gcry_pk_get_single_data (gcry_ctx_t *r_ctx,
                                          size_t *r_len);
 
 gpg_err_code_t _gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags);
+gcry_err_code_t _gcry_md_open_internal (gcry_md_hd_t *h, int algo,
+                                        unsigned int flags, int fast_rnd_poll);
 void _gcry_md_close (gcry_md_hd_t hd);
 gpg_err_code_t _gcry_md_enable (gcry_md_hd_t hd, int algo);
 gpg_err_code_t _gcry_md_copy (gcry_md_hd_t *bhd, gcry_md_hd_t ahd);
-- 
2.53.0