[PATCH 06/10] sntrup761: read random values with single call

Jussi Kivilinna <[email protected]> Sun, 2 Aug 2026 12:55:11 +0300
Newsgroups gmane.comp.encryption.gpg.libgcrypt.devel
Message-ID <[email protected]>
* cipher/sntrup761.c: Include "bithelp.h".
(urandom32): Remove.
(Short_random, Small_random): Fill 32-bit array with one call to random
function instead of reading four bytes at a time.
--

'urandom32' requested four bytes per call and both callers looped over
all p coefficients, so generating one polynomial made 761 separate calls
to the random function. With libgcrypt CSPRNG each of those takes pool
lock, pool mix and hash operation, which dominated encapsulation time.

Benchmark on AMD Ryzen 9 9950X3D, SNTRUP761 usec/operation, quick
random disabled ('base' being state before this patch series):

             |     base   before    after   speedup    total
 keygen      |  37971.9   9480.2   2900.4     3.27x   13.09x
 encap       |   7355.8   4468.2   1184.7     3.77x    6.21x
 decap       |  12207.1   3325.4   3322.4     1.00x    3.67x

Signed-off-by: Jussi Kivilinna <[email protected]>
---
 cipher/sntrup761.c | 22 ++++++----------------
 1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/cipher/sntrup761.c b/cipher/sntrup761.c
index 11366f8f..94229d79 100644
--- a/cipher/sntrup761.c
+++ b/cipher/sntrup761.c
@@ -34,6 +34,7 @@
 #endif
 
 #include "sntrup761.h"
+#include "bithelp.h"
 #include "const-time.h"
 
 /* from supercop-20201130/crypto_sort/int32/portable4/int32_minmax.inc */
@@ -698,38 +699,27 @@ Hash_prefix (unsigned char *out, int b, const unsigned char *in, int inlen)
 
 /* ----- higher-level randomness */
 
-static uint32_t
-urandom32 (void *random_ctx, sntrup761_random_func * random)
-{
-  unsigned char c[4];
-  uint32_t out[4];
-
-  random (random_ctx, 4, c);
-  out[0] = (uint32_t) c[0];
-  out[1] = ((uint32_t) c[1]) << 8;
-  out[2] = ((uint32_t) c[2]) << 16;
-  out[3] = ((uint32_t) c[3]) << 24;
-  return out[0] + out[1] + out[2] + out[3];
-}
-
 static void
 Short_random (small * out, void *random_ctx, sntrup761_random_func * random)
 {
   uint32_t L[p];
   int i;
 
+  random (random_ctx, sizeof (L), (uint8_t *)L);
   for (i = 0; i < p; ++i)
-    L[i] = urandom32 (random_ctx, random);
+    L[i] = le_bswap32 (L[i]);
   Short_fromlist (out, L);
 }
 
 static void
 Small_random (small * out, void *random_ctx, sntrup761_random_func * random)
 {
+  uint32_t L[p];
   int i;
 
+  random (random_ctx, sizeof (L), (uint8_t *)L);
   for (i = 0; i < p; ++i)
-    out[i] = (((urandom32 (random_ctx, random) & 0x3fffffff) * 3) >> 30) - 1;
+    out[i] = (((le_bswap32 (L[i]) & 0x3fffffff) * 3) >> 30) - 1;
 }
 
 /* ----- Streamlined NTRU Prime Core */
-- 
2.53.0