[PATCH 09/17] cipher:dilithium: For _GCRYPT_IN_LIBGCRYPT, add *_close function.

NIIBE Yutaka via Gcrypt-devel <[email protected]> Sat, 28 Jun 2025 12:44:46 +0900
Newsgroups gmane.comp.encryption.gpg.libgcrypt.devel
Message-ID <479085097a97fc1eb750d65ae4403ae44022c326.1751080340.git.gniibe@fsij.org>
* cipher/dilithium-common.c (poly_uniform): Add stream128_close.
(poly_uniform_eta_2, poly_uniform_eta_4): Add stream256_close.
(poly_uniform_gamma1_17, poly_uniform_gamma1_19): Likewise.
* cipher/dilithium-dep.c (poly_challenge): Add shake256_close.
(crypto_sign_signature_internal): Likewise.
(crypto_sign_verify_internal): Likewise.
* cipher/dilithium.c [_GCRYPT_IN_LIBGCRYPT]: Add glue code
for shake128_* and shake256_*.

--

GnuPG-bug-id: 7640
Signed-off-by: NIIBE Yutaka <[email protected]>
---
 cipher/dilithium-common.c |   5 ++
 cipher/dilithium-dep.c    |   6 ++
 cipher/dilithium.c        | 181 ++++++++++++++++++++++++++++++++++----
 3 files changed, 175 insertions(+), 17 deletions(-)

_______________________________________________
Gcrypt-devel mailing list
[email protected]
https://lists.gnupg.org/mailman/listinfo/gcrypt-devel
0009-cipher-dilithium-For-_GCRYPT_IN_LIBGCRYPT-add-_close.patch (text/x-patch, 10.6 KB)
diff --git a/cipher/dilithium-common.c b/cipher/dilithium-common.c
index 2dfc4ba0..47d5f7d6 100644
--- a/cipher/dilithium-common.c
+++ b/cipher/dilithium-common.c
@@ -674,6 +674,7 @@ void poly_uniform(poly *a,
     buflen = STREAM128_BLOCKBYTES + off;
     ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen);
   }
+  stream128_close(&state);
 }
 
 /*************************************************
@@ -776,6 +777,7 @@ void poly_uniform_eta_2(poly *a,
     stream256_squeezeblocks(buf, 1, &state);
     ctr += rej_eta_2(a->coeffs + ctr, N - ctr, buf, STREAM256_BLOCKBYTES);
   }
+  stream256_close(&state);
 }
 #endif
 #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3
@@ -798,6 +800,7 @@ void poly_uniform_eta_4(poly *a,
     stream256_squeezeblocks(buf, 1, &state);
     ctr += rej_eta_4(a->coeffs + ctr, N - ctr, buf, STREAM256_BLOCKBYTES);
   }
+  stream256_close(&state);
 }
 #endif
 
@@ -825,6 +828,7 @@ void poly_uniform_gamma1_17(poly *a,
   stream256_init(&state, seed, nonce);
   stream256_squeezeblocks(buf, POLY_UNIFORM_GAMMA1_NBLOCKS_17, &state);
   polyz_unpack_17(a, buf);
+  stream256_close(&state);
 }
 #endif
 #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 || DILITHIUM_MODE == 5
@@ -840,6 +844,7 @@ void poly_uniform_gamma1_19(poly *a,
   stream256_init(&state, seed, nonce);
   stream256_squeezeblocks(buf, POLY_UNIFORM_GAMMA1_NBLOCKS_19, &state);
   polyz_unpack_19(a, buf);
+  stream256_close(&state);
 }
 #endif
 
diff --git a/cipher/dilithium-dep.c b/cipher/dilithium-dep.c
index e59cad55..569ffd5f 100644
--- a/cipher/dilithium-dep.c
+++ b/cipher/dilithium-dep.c
@@ -404,6 +404,7 @@ void poly_challenge(poly *c, const uint8_t seed[CTILDEBYTES]) {
     c->coeffs[b] = 1 - 2*(signs & 1);
     signs >>= 1;
   }
+  shake256_close(&state);
 }
 /*************** dilithium/ref/polyvec.c */
 
@@ -899,6 +900,7 @@ int crypto_sign_signature_internal(uint8_t *sig,
   shake256_absorb(&state, m, mlen);
   shake256_finalize(&state);
   shake256_squeeze(mu, CRHBYTES, &state);
+  shake256_close(&state);
 
   /* Compute rhoprime = CRH(key, rnd, mu) */
   shake256_init(&state);
@@ -907,6 +909,7 @@ int crypto_sign_signature_internal(uint8_t *sig,
   shake256_absorb(&state, mu, CRHBYTES);
   shake256_finalize(&state);
   shake256_squeeze(rhoprime, CRHBYTES, &state);
+  shake256_close(&state);
 
   /* Expand matrix and transform vectors */
   polyvec_matrix_expand(mat, rho);
@@ -935,6 +938,7 @@ rej:
   shake256_absorb(&state, sig, K*POLYW1_PACKEDBYTES);
   shake256_finalize(&state);
   shake256_squeeze(sig, CTILDEBYTES, &state);
+  shake256_close(&state);
   poly_challenge(&cp, sig);
   poly_ntt(&cp);
 
@@ -1107,6 +1111,7 @@ int crypto_sign_verify_internal(const uint8_t *sig,
   shake256_absorb(&state, m, mlen);
   shake256_finalize(&state);
   shake256_squeeze(mu, CRHBYTES, &state);
+  shake256_close(&state);
 
   /* Matrix-vector multiplication; compute Az - c2^dt1 */
   poly_challenge(&cp, c);
@@ -1135,6 +1140,7 @@ int crypto_sign_verify_internal(const uint8_t *sig,
   shake256_absorb(&state, buf, K*POLYW1_PACKEDBYTES);
   shake256_finalize(&state);
   shake256_squeeze(c2, CTILDEBYTES, &state);
+  shake256_close(&state);
   for(i = 0; i < CTILDEBYTES; ++i)
     if(c[i] != c2[i])
       return -1;
diff --git a/cipher/dilithium.c b/cipher/dilithium.c
index b9a16459..165b1117 100644
--- a/cipher/dilithium.c
+++ b/cipher/dilithium.c
@@ -43,37 +43,175 @@
 
   Dilithium Home: https://github.com/pq-crystals/dilithium.git
  */
-/*************** dilithium/ref/fips202.h */
-#define SHAKE128_RATE 168
-#define SHAKE256_RATE 136
-#define SHA3_256_RATE 136
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#ifdef _GCRYPT_IN_LIBGCRYPT
+#include <stdarg.h>
+#include <gpg-error.h>
+
+#include "types.h"
+#include "g10lib.h"
+#include "gcrypt-int.h"
+#include "const-time.h"
+
+#include "dilithium.h"
+
+static int crypto_sign_keypair_internal_2 (uint8_t *pk, uint8_t *sk,
+                                           const uint8_t seed[SEEDBYTES]);
+static int crypto_sign_keypair_internal_3 (uint8_t *pk, uint8_t *sk,
+                                           const uint8_t seed[SEEDBYTES]);
+static int crypto_sign_keypair_internal_5 (uint8_t *pk, uint8_t *sk,
+                                           const uint8_t seed[SEEDBYTES]);
+static int crypto_sign_signature_internal_2 (uint8_t *sig, size_t *siglen,
+                                             const uint8_t *m, size_t mlen,
+                                             const uint8_t *pre, size_t prelen,
+                                             const uint8_t rnd[RNDBYTES],
+                                             const uint8_t *sk);
+static int crypto_sign_signature_internal_3 (uint8_t *sig, size_t *siglen,
+                                             const uint8_t *m, size_t mlen,
+                                             const uint8_t *pre, size_t prelen,
+                                             const uint8_t rnd[RNDBYTES],
+                                             const uint8_t *sk);
+static int crypto_sign_signature_internal_5 (uint8_t *sig, size_t *siglen,
+                                             const uint8_t *m, size_t mlen,
+                                             const uint8_t *pre, size_t prelen,
+                                             const uint8_t rnd[RNDBYTES],
+                                             const uint8_t *sk);
+static int crypto_sign_verify_internal_2 (const uint8_t *sig, size_t siglen,
+                                          const uint8_t *m, size_t mlen,
+                                          const uint8_t *pre, size_t prelen,
+                                          const uint8_t *pk);
+static int crypto_sign_verify_internal_3 (const uint8_t *sig, size_t siglen,
+                                          const uint8_t *m, size_t mlen,
+                                          const uint8_t *pre, size_t prelen,
+                                          const uint8_t *pk);
+static int crypto_sign_verify_internal_5 (const uint8_t *sig, size_t siglen,
+                                          const uint8_t *m, size_t mlen,
+                                          const uint8_t *pre, size_t prelen,
+                                          const uint8_t *pk);
+
+typedef struct {
+  gcry_md_hd_t h;
+} keccak_state;
+
+static void
+shake128_init (keccak_state *state)
+{
+  gcry_err_code_t ec;
+
+  ec = _gcry_md_open (&state->h, GCRY_MD_SHAKE128, 0);
+  if (ec)
+    log_fatal ("internal md_open failed: %d\n", ec);
+}
+
+static void
+shake128_absorb (keccak_state *state, const uint8_t *in, size_t inlen)
+{
+  _gcry_md_write (state->h, in, inlen);
+}
+
+static void
+shake128_finalize (keccak_state *state)
+{
+  (void)state;
+}
+
+static void
+shake128_squeeze (uint8_t *out, size_t outlen, keccak_state *state)
+{
+  _gcry_md_extract (state->h, GCRY_MD_SHAKE128, out, outlen);
+}
+
+static void
+shake128_close (keccak_state *state)
+{
+  _gcry_md_close (state->h);
+}
+
+static void
+shake256_init (keccak_state *state)
+{
+  gcry_err_code_t ec;
+
+  ec = _gcry_md_open (&state->h, GCRY_MD_SHAKE256, 0);
+  if (ec)
+    log_fatal ("internal md_open failed: %d\n", ec);
+}
+
+static void
+shake256_absorb (keccak_state *state, const uint8_t *in, size_t inlen)
+{
+  _gcry_md_write (state->h, in, inlen);
+}
+
+static void
+shake256_finalize (keccak_state *state)
+{
+  (void)state;
+}
+
+static void
+shake256_squeeze (uint8_t *out, size_t outlen, keccak_state *state)
+{
+  _gcry_md_extract (state->h, GCRY_MD_SHAKE256, out, outlen);
+}
+
+static void
+shake256_close (keccak_state *state)
+{
+  _gcry_md_close (state->h);
+}
+
+static void
+shake256 (uint8_t *out, size_t outlen, const uint8_t *in,
+	  size_t inlen)
+{
+  gcry_buffer_t iov[1];
+
+  iov[0].size = 0;
+  iov[0].data = (uint8_t *)in;
+  iov[0].off = 0;
+  iov[0].len = inlen;
+
+  _gcry_md_hash_buffers_extract (GCRY_MD_SHAKE256, 0, out, outlen,
+                                 iov, 1);
+}
+#else
+#include "dilithium.h"
+
+#define DILITHIUM_RANDOMIZED_SIGNING
 
+/*************** dilithium/ref/randombytes.h */
+void randombytes (uint8_t *out, size_t outlen);
 
+/*************** dilithium/ref/fips202.h */
 typedef struct {
   uint64_t s[25];
   unsigned int pos;
 } keccak_state;
 
-extern const uint64_t KeccakF_RoundConstants[];
-
 void shake128_init(keccak_state *state);
 void shake128_absorb(keccak_state *state, const uint8_t *in, size_t inlen);
 void shake128_finalize(keccak_state *state);
 void shake128_squeeze(uint8_t *out, size_t outlen, keccak_state *state);
-void shake128_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen);
-void shake128_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state);
 
 void shake256_init(keccak_state *state);
 void shake256_absorb(keccak_state *state, const uint8_t *in, size_t inlen);
 void shake256_finalize(keccak_state *state);
 void shake256_squeeze(uint8_t *out, size_t outlen, keccak_state *state);
-void shake256_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen);
-void shake256_squeezeblocks(uint8_t *out, size_t nblocks,  keccak_state *state);
-
-void shake128(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen);
 void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen);
-void sha3_256(uint8_t h[32], const uint8_t *in, size_t inlen);
-void sha3_512(uint8_t h[64], const uint8_t *in, size_t inlen);
+#endif /* _GCRYPT_IN_LIBGCRYPT */
+
+/*************** dilithium/ref/fips202.h */
+#define SHAKE128_RATE 168
+#define SHAKE256_RATE 136
+#define SHA3_256_RATE 136
 
 /*************** dilithium/ref/params.h */
 #define SEEDBYTES 32
@@ -197,9 +335,6 @@ static void polyz_unpack(poly *r, const uint8_t *a);
 
 static void polyw1_pack(uint8_t *r, const poly *a);
 
-/*************** dilithium/ref/randombytes.h */
-void randombytes(uint8_t *out, size_t outlen);
-
 /*************** dilithium/ref/reduce.h */
 #define MONT -4186625 /* 2^32 % Q */
 #define QINV 58728449 /* q^(-1) mod 2^32 */
@@ -311,5 +446,17 @@ void dilithium_shake256_stream_init(keccak_state *state, const uint8_t seed[CRHB
   shake256_finalize(state);
 }
 
+/* Glue code */
+#define shake128_squeezeblocks(OUT, OUTBLOCKS, STATE) \
+	shake128_squeeze(OUT, SHAKE128_RATE*OUTBLOCKS, STATE)
+#define stream128_close(STATE) shake128_close(STATE)
+#define shake256_squeezeblocks(OUT, OUTBLOCKS, STATE) \
+	shake256_squeeze(OUT, SHAKE256_RATE*OUTBLOCKS, STATE)
+#define stream256_close(STATE) shake256_close(STATE)
+#ifndef _GCRYPT_IN_LIBGCRYPT
+static void shake256_close (keccak_state *state) { (void)state; }
+static void shake128_close (keccak_state *state) { (void)state; }
+#endif
+
 #include "dilithium-common.c"
 #include "dilithium-dep.c"