summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/libcrypto/Makefile5
-rw-r--r--src/lib/libcrypto/arch/aarch64/opensslconf.h10
-rw-r--r--src/lib/libcrypto/arch/alpha/opensslconf.h10
-rw-r--r--src/lib/libcrypto/arch/amd64/Makefile.inc12
-rw-r--r--src/lib/libcrypto/arch/amd64/crypto_arch.h9
-rw-r--r--src/lib/libcrypto/arch/amd64/crypto_cpu_caps.c6
-rw-r--r--src/lib/libcrypto/arch/amd64/opensslconf.h10
-rw-r--r--src/lib/libcrypto/arch/arm/opensslconf.h10
-rw-r--r--src/lib/libcrypto/arch/hppa/opensslconf.h10
-rw-r--r--src/lib/libcrypto/arch/i386/opensslconf.h10
-rw-r--r--src/lib/libcrypto/arch/m88k/opensslconf.h10
-rw-r--r--src/lib/libcrypto/arch/mips64/opensslconf.h10
-rw-r--r--src/lib/libcrypto/arch/powerpc/opensslconf.h10
-rw-r--r--src/lib/libcrypto/arch/powerpc64/opensslconf.h10
-rw-r--r--src/lib/libcrypto/arch/riscv64/opensslconf.h10
-rw-r--r--src/lib/libcrypto/arch/sh/opensslconf.h10
-rw-r--r--src/lib/libcrypto/arch/sparc64/opensslconf.h10
-rw-r--r--src/lib/libcrypto/asn1/tasn_fre.c7
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_add.S51
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_cmadd.S32
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_cmul.S28
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_modadd.S112
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_modsub.S99
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_mul.S25
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_mul_4_8.S187
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_mul_4_8_alt.S8
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_mul_6_12.S223
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_mul_6_12_alt.S199
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_mul_8_16.S273
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_mul_8_16_alt.S9
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_sqr.S29
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_sqr_4_8.S158
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_sqr_4_8_alt.S8
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_sqr_6_12.S227
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_sqr_6_12_alt.S210
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_sqr_8_16.S311
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_sqr_8_16_alt.S7
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bignum_sub.S47
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bn_arch.c109
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/bn_arch.h7
-rw-r--r--src/lib/libcrypto/bn/arch/amd64/word_clz.S6
-rw-r--r--src/lib/libcrypto/bn/bn_mul.c4
-rw-r--r--src/lib/libcrypto/bn/bn_sqr.c4
-rw-r--r--src/lib/libcrypto/bn/s2n_bignum.h793
-rw-r--r--src/lib/libcrypto/bn/s2n_bignum_internal.h35
-rw-r--r--src/lib/libcrypto/cert.pem340
-rw-r--r--src/lib/libcrypto/hidden/crypto_namespace.h6
-rw-r--r--src/lib/libcrypto/hidden/openssl/mlkem.h40
-rw-r--r--src/lib/libcrypto/mlkem/mlkem.c416
-rw-r--r--src/lib/libcrypto/mlkem/mlkem.h329
-rw-r--r--src/lib/libcrypto/mlkem/mlkem1024.c71
-rw-r--r--src/lib/libcrypto/mlkem/mlkem768.c73
-rw-r--r--src/lib/libcrypto/mlkem/mlkem_internal.h331
-rw-r--r--src/lib/libcrypto/mlkem/mlkem_key.c200
-rw-r--r--src/lib/libcrypto/rc4/rc4.c269
-rw-r--r--src/lib/libcrypto/x509/x509.h3
-rw-r--r--src/lib/libcrypto/x509/x509_policy.c5
57 files changed, 4103 insertions, 1350 deletions
diff --git a/src/lib/libcrypto/Makefile b/src/lib/libcrypto/Makefile
index b0ab507983..459b0c9235 100644
--- a/src/lib/libcrypto/Makefile
+++ b/src/lib/libcrypto/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.241 2025/07/16 15:59:26 tb Exp $ 1# $OpenBSD: Makefile,v 1.242 2025/08/14 15:48:48 beck Exp $
2 2
3LIB= crypto 3LIB= crypto
4LIBREBUILD=y 4LIBREBUILD=y
@@ -374,8 +374,10 @@ SRCS+= md4.c
374SRCS+= md5.c 374SRCS+= md5.c
375 375
376# mlkem/ 376# mlkem/
377SRCS+= mlkem.c
377SRCS+= mlkem768.c 378SRCS+= mlkem768.c
378SRCS+= mlkem1024.c 379SRCS+= mlkem1024.c
380SRCS+= mlkem_key.c
379 381
380# modes/ 382# modes/
381SRCS+= cbc128.c 383SRCS+= cbc128.c
@@ -668,6 +670,7 @@ HDRS=\
668 ${LCRYPTO_SRC}/lhash/lhash.h \ 670 ${LCRYPTO_SRC}/lhash/lhash.h \
669 ${LCRYPTO_SRC}/md4/md4.h \ 671 ${LCRYPTO_SRC}/md4/md4.h \
670 ${LCRYPTO_SRC}/md5/md5.h \ 672 ${LCRYPTO_SRC}/md5/md5.h \
673 ${LCRYPTO_SRC}/mlkem/mlkem.h \
671 ${LCRYPTO_SRC}/modes/modes.h \ 674 ${LCRYPTO_SRC}/modes/modes.h \
672 ${LCRYPTO_SRC}/objects/objects.h \ 675 ${LCRYPTO_SRC}/objects/objects.h \
673 ${LCRYPTO_SRC}/ocsp/ocsp.h \ 676 ${LCRYPTO_SRC}/ocsp/ocsp.h \
diff --git a/src/lib/libcrypto/arch/aarch64/opensslconf.h b/src/lib/libcrypto/arch/aarch64/opensslconf.h
index 868066c75e..c31bcc01ad 100644
--- a/src/lib/libcrypto/arch/aarch64/opensslconf.h
+++ b/src/lib/libcrypto/arch/aarch64/opensslconf.h
@@ -11,13 +11,3 @@
11#define OPENSSL_LINE __LINE__ 11#define OPENSSL_LINE __LINE__
12#endif 12#endif
13#endif 13#endif
14
15#if defined(HEADER_RC4_H)
16#if !defined(RC4_CHUNK)
17/*
18 * This enables code handling data aligned at natural CPU word
19 * boundary. See crypto/rc4/rc4_enc.c for further details.
20 */
21#define RC4_CHUNK unsigned long
22#endif
23#endif
diff --git a/src/lib/libcrypto/arch/alpha/opensslconf.h b/src/lib/libcrypto/arch/alpha/opensslconf.h
index 868066c75e..c31bcc01ad 100644
--- a/src/lib/libcrypto/arch/alpha/opensslconf.h
+++ b/src/lib/libcrypto/arch/alpha/opensslconf.h
@@ -11,13 +11,3 @@
11#define OPENSSL_LINE __LINE__ 11#define OPENSSL_LINE __LINE__
12#endif 12#endif
13#endif 13#endif
14
15#if defined(HEADER_RC4_H)
16#if !defined(RC4_CHUNK)
17/*
18 * This enables code handling data aligned at natural CPU word
19 * boundary. See crypto/rc4/rc4_enc.c for further details.
20 */
21#define RC4_CHUNK unsigned long
22#endif
23#endif
diff --git a/src/lib/libcrypto/arch/amd64/Makefile.inc b/src/lib/libcrypto/arch/amd64/Makefile.inc
index 649c507189..de9666afdb 100644
--- a/src/lib/libcrypto/arch/amd64/Makefile.inc
+++ b/src/lib/libcrypto/arch/amd64/Makefile.inc
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile.inc,v 1.41 2025/06/28 12:39:10 jsing Exp $ 1# $OpenBSD: Makefile.inc,v 1.42 2025/08/14 15:12:53 jsing Exp $
2 2
3# amd64-specific libcrypto build rules 3# amd64-specific libcrypto build rules
4 4
@@ -26,11 +26,21 @@ SRCS += bn_arch.c
26SRCS += bignum_add.S 26SRCS += bignum_add.S
27SRCS += bignum_cmadd.S 27SRCS += bignum_cmadd.S
28SRCS += bignum_cmul.S 28SRCS += bignum_cmul.S
29SRCS += bignum_modadd.S
30SRCS += bignum_modsub.S
29SRCS += bignum_mul.S 31SRCS += bignum_mul.S
32SRCS += bignum_mul_4_8.S
30SRCS += bignum_mul_4_8_alt.S 33SRCS += bignum_mul_4_8_alt.S
34SRCS += bignum_mul_6_12.S
35SRCS += bignum_mul_6_12_alt.S
36SRCS += bignum_mul_8_16.S
31SRCS += bignum_mul_8_16_alt.S 37SRCS += bignum_mul_8_16_alt.S
32SRCS += bignum_sqr.S 38SRCS += bignum_sqr.S
39SRCS += bignum_sqr_4_8.S
33SRCS += bignum_sqr_4_8_alt.S 40SRCS += bignum_sqr_4_8_alt.S
41SRCS += bignum_sqr_6_12.S
42SRCS += bignum_sqr_6_12_alt.S
43SRCS += bignum_sqr_8_16.S
34SRCS += bignum_sqr_8_16_alt.S 44SRCS += bignum_sqr_8_16_alt.S
35SRCS += bignum_sub.S 45SRCS += bignum_sub.S
36SRCS += word_clz.S 46SRCS += word_clz.S
diff --git a/src/lib/libcrypto/arch/amd64/crypto_arch.h b/src/lib/libcrypto/arch/amd64/crypto_arch.h
index e869fbba35..a8f64cf235 100644
--- a/src/lib/libcrypto/arch/amd64/crypto_arch.h
+++ b/src/lib/libcrypto/arch/amd64/crypto_arch.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: crypto_arch.h,v 1.13 2025/07/22 09:18:02 jsing Exp $ */ 1/* $OpenBSD: crypto_arch.h,v 1.14 2025/08/14 15:11:01 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2024 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2024 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -26,9 +26,10 @@
26extern uint64_t crypto_cpu_caps_amd64; 26extern uint64_t crypto_cpu_caps_amd64;
27#endif 27#endif
28 28
29#define CRYPTO_CPU_CAPS_AMD64_AES (1ULL << 0) 29#define CRYPTO_CPU_CAPS_AMD64_ADX (1ULL << 0)
30#define CRYPTO_CPU_CAPS_AMD64_CLMUL (1ULL << 1) 30#define CRYPTO_CPU_CAPS_AMD64_AES (1ULL << 1)
31#define CRYPTO_CPU_CAPS_AMD64_SHA (1ULL << 2) 31#define CRYPTO_CPU_CAPS_AMD64_CLMUL (1ULL << 2)
32#define CRYPTO_CPU_CAPS_AMD64_SHA (1ULL << 3)
32 33
33#ifndef OPENSSL_NO_ASM 34#ifndef OPENSSL_NO_ASM
34 35
diff --git a/src/lib/libcrypto/arch/amd64/crypto_cpu_caps.c b/src/lib/libcrypto/arch/amd64/crypto_cpu_caps.c
index 0bc440d34f..51a2da4616 100644
--- a/src/lib/libcrypto/arch/amd64/crypto_cpu_caps.c
+++ b/src/lib/libcrypto/arch/amd64/crypto_cpu_caps.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: crypto_cpu_caps.c,v 1.7 2025/07/22 09:18:02 jsing Exp $ */ 1/* $OpenBSD: crypto_cpu_caps.c,v 1.8 2025/08/14 15:11:01 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2024 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2024 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -119,6 +119,10 @@ crypto_cpu_caps_init(void)
119 if (max_cpuid >= 7) { 119 if (max_cpuid >= 7) {
120 cpuid(7, NULL, &ebx, NULL, NULL); 120 cpuid(7, NULL, &ebx, NULL, NULL);
121 121
122 /* Intel ADX feature bit - ebx[19]. */
123 if (((ebx >> 19) & 1) != 0)
124 crypto_cpu_caps_amd64 |= CRYPTO_CPU_CAPS_AMD64_ADX;
125
122 /* Intel SHA extensions feature bit - ebx[29]. */ 126 /* Intel SHA extensions feature bit - ebx[29]. */
123 if (((ebx >> 29) & 1) != 0) 127 if (((ebx >> 29) & 1) != 0)
124 crypto_cpu_caps_amd64 |= CRYPTO_CPU_CAPS_AMD64_SHA; 128 crypto_cpu_caps_amd64 |= CRYPTO_CPU_CAPS_AMD64_SHA;
diff --git a/src/lib/libcrypto/arch/amd64/opensslconf.h b/src/lib/libcrypto/arch/amd64/opensslconf.h
index 868066c75e..c31bcc01ad 100644
--- a/src/lib/libcrypto/arch/amd64/opensslconf.h
+++ b/src/lib/libcrypto/arch/amd64/opensslconf.h
@@ -11,13 +11,3 @@
11#define OPENSSL_LINE __LINE__ 11#define OPENSSL_LINE __LINE__
12#endif 12#endif
13#endif 13#endif
14
15#if defined(HEADER_RC4_H)
16#if !defined(RC4_CHUNK)
17/*
18 * This enables code handling data aligned at natural CPU word
19 * boundary. See crypto/rc4/rc4_enc.c for further details.
20 */
21#define RC4_CHUNK unsigned long
22#endif
23#endif
diff --git a/src/lib/libcrypto/arch/arm/opensslconf.h b/src/lib/libcrypto/arch/arm/opensslconf.h
index dcbe113864..c31bcc01ad 100644
--- a/src/lib/libcrypto/arch/arm/opensslconf.h
+++ b/src/lib/libcrypto/arch/arm/opensslconf.h
@@ -11,13 +11,3 @@
11#define OPENSSL_LINE __LINE__ 11#define OPENSSL_LINE __LINE__
12#endif 12#endif
13#endif 13#endif
14
15#if defined(HEADER_RC4_H)
16#if !defined(RC4_CHUNK)
17/*
18 * This enables code handling data aligned at natural CPU word
19 * boundary. See crypto/rc4/rc4_enc.c for further details.
20 */
21#undef RC4_CHUNK
22#endif
23#endif
diff --git a/src/lib/libcrypto/arch/hppa/opensslconf.h b/src/lib/libcrypto/arch/hppa/opensslconf.h
index dcbe113864..c31bcc01ad 100644
--- a/src/lib/libcrypto/arch/hppa/opensslconf.h
+++ b/src/lib/libcrypto/arch/hppa/opensslconf.h
@@ -11,13 +11,3 @@
11#define OPENSSL_LINE __LINE__ 11#define OPENSSL_LINE __LINE__
12#endif 12#endif
13#endif 13#endif
14
15#if defined(HEADER_RC4_H)
16#if !defined(RC4_CHUNK)
17/*
18 * This enables code handling data aligned at natural CPU word
19 * boundary. See crypto/rc4/rc4_enc.c for further details.
20 */
21#undef RC4_CHUNK
22#endif
23#endif
diff --git a/src/lib/libcrypto/arch/i386/opensslconf.h b/src/lib/libcrypto/arch/i386/opensslconf.h
index dcbe113864..c31bcc01ad 100644
--- a/src/lib/libcrypto/arch/i386/opensslconf.h
+++ b/src/lib/libcrypto/arch/i386/opensslconf.h
@@ -11,13 +11,3 @@
11#define OPENSSL_LINE __LINE__ 11#define OPENSSL_LINE __LINE__
12#endif 12#endif
13#endif 13#endif
14
15#if defined(HEADER_RC4_H)
16#if !defined(RC4_CHUNK)
17/*
18 * This enables code handling data aligned at natural CPU word
19 * boundary. See crypto/rc4/rc4_enc.c for further details.
20 */
21#undef RC4_CHUNK
22#endif
23#endif
diff --git a/src/lib/libcrypto/arch/m88k/opensslconf.h b/src/lib/libcrypto/arch/m88k/opensslconf.h
index dcbe113864..c31bcc01ad 100644
--- a/src/lib/libcrypto/arch/m88k/opensslconf.h
+++ b/src/lib/libcrypto/arch/m88k/opensslconf.h
@@ -11,13 +11,3 @@
11#define OPENSSL_LINE __LINE__ 11#define OPENSSL_LINE __LINE__
12#endif 12#endif
13#endif 13#endif
14
15#if defined(HEADER_RC4_H)
16#if !defined(RC4_CHUNK)
17/*
18 * This enables code handling data aligned at natural CPU word
19 * boundary. See crypto/rc4/rc4_enc.c for further details.
20 */
21#undef RC4_CHUNK
22#endif
23#endif
diff --git a/src/lib/libcrypto/arch/mips64/opensslconf.h b/src/lib/libcrypto/arch/mips64/opensslconf.h
index 868066c75e..c31bcc01ad 100644
--- a/src/lib/libcrypto/arch/mips64/opensslconf.h
+++ b/src/lib/libcrypto/arch/mips64/opensslconf.h
@@ -11,13 +11,3 @@
11#define OPENSSL_LINE __LINE__ 11#define OPENSSL_LINE __LINE__
12#endif 12#endif
13#endif 13#endif
14
15#if defined(HEADER_RC4_H)
16#if !defined(RC4_CHUNK)
17/*
18 * This enables code handling data aligned at natural CPU word
19 * boundary. See crypto/rc4/rc4_enc.c for further details.
20 */
21#define RC4_CHUNK unsigned long
22#endif
23#endif
diff --git a/src/lib/libcrypto/arch/powerpc/opensslconf.h b/src/lib/libcrypto/arch/powerpc/opensslconf.h
index dcbe113864..c31bcc01ad 100644
--- a/src/lib/libcrypto/arch/powerpc/opensslconf.h
+++ b/src/lib/libcrypto/arch/powerpc/opensslconf.h
@@ -11,13 +11,3 @@
11#define OPENSSL_LINE __LINE__ 11#define OPENSSL_LINE __LINE__
12#endif 12#endif
13#endif 13#endif
14
15#if defined(HEADER_RC4_H)
16#if !defined(RC4_CHUNK)
17/*
18 * This enables code handling data aligned at natural CPU word
19 * boundary. See crypto/rc4/rc4_enc.c for further details.
20 */
21#undef RC4_CHUNK
22#endif
23#endif
diff --git a/src/lib/libcrypto/arch/powerpc64/opensslconf.h b/src/lib/libcrypto/arch/powerpc64/opensslconf.h
index 868066c75e..c31bcc01ad 100644
--- a/src/lib/libcrypto/arch/powerpc64/opensslconf.h
+++ b/src/lib/libcrypto/arch/powerpc64/opensslconf.h
@@ -11,13 +11,3 @@
11#define OPENSSL_LINE __LINE__ 11#define OPENSSL_LINE __LINE__
12#endif 12#endif
13#endif 13#endif
14
15#if defined(HEADER_RC4_H)
16#if !defined(RC4_CHUNK)
17/*
18 * This enables code handling data aligned at natural CPU word
19 * boundary. See crypto/rc4/rc4_enc.c for further details.
20 */
21#define RC4_CHUNK unsigned long
22#endif
23#endif
diff --git a/src/lib/libcrypto/arch/riscv64/opensslconf.h b/src/lib/libcrypto/arch/riscv64/opensslconf.h
index 868066c75e..c31bcc01ad 100644
--- a/src/lib/libcrypto/arch/riscv64/opensslconf.h
+++ b/src/lib/libcrypto/arch/riscv64/opensslconf.h
@@ -11,13 +11,3 @@
11#define OPENSSL_LINE __LINE__ 11#define OPENSSL_LINE __LINE__
12#endif 12#endif
13#endif 13#endif
14
15#if defined(HEADER_RC4_H)
16#if !defined(RC4_CHUNK)
17/*
18 * This enables code handling data aligned at natural CPU word
19 * boundary. See crypto/rc4/rc4_enc.c for further details.
20 */
21#define RC4_CHUNK unsigned long
22#endif
23#endif
diff --git a/src/lib/libcrypto/arch/sh/opensslconf.h b/src/lib/libcrypto/arch/sh/opensslconf.h
index dcbe113864..c31bcc01ad 100644
--- a/src/lib/libcrypto/arch/sh/opensslconf.h
+++ b/src/lib/libcrypto/arch/sh/opensslconf.h
@@ -11,13 +11,3 @@
11#define OPENSSL_LINE __LINE__ 11#define OPENSSL_LINE __LINE__
12#endif 12#endif
13#endif 13#endif
14
15#if defined(HEADER_RC4_H)
16#if !defined(RC4_CHUNK)
17/*
18 * This enables code handling data aligned at natural CPU word
19 * boundary. See crypto/rc4/rc4_enc.c for further details.
20 */
21#undef RC4_CHUNK
22#endif
23#endif
diff --git a/src/lib/libcrypto/arch/sparc64/opensslconf.h b/src/lib/libcrypto/arch/sparc64/opensslconf.h
index 868066c75e..c31bcc01ad 100644
--- a/src/lib/libcrypto/arch/sparc64/opensslconf.h
+++ b/src/lib/libcrypto/arch/sparc64/opensslconf.h
@@ -11,13 +11,3 @@
11#define OPENSSL_LINE __LINE__ 11#define OPENSSL_LINE __LINE__
12#endif 12#endif
13#endif 13#endif
14
15#if defined(HEADER_RC4_H)
16#if !defined(RC4_CHUNK)
17/*
18 * This enables code handling data aligned at natural CPU word
19 * boundary. See crypto/rc4/rc4_enc.c for further details.
20 */
21#define RC4_CHUNK unsigned long
22#endif
23#endif
diff --git a/src/lib/libcrypto/asn1/tasn_fre.c b/src/lib/libcrypto/asn1/tasn_fre.c
index 0e259a13ab..c3de668483 100644
--- a/src/lib/libcrypto/asn1/tasn_fre.c
+++ b/src/lib/libcrypto/asn1/tasn_fre.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tasn_fre.c,v 1.24 2024/12/11 11:22:06 tb Exp $ */ 1/* $OpenBSD: tasn_fre.c,v 1.25 2025/08/14 19:02:17 tb Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2000. 3 * project 2000.
4 */ 4 */
@@ -147,8 +147,9 @@ asn1_item_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
147 return; 147 return;
148 } 148 }
149 asn1_enc_cleanup(pval, it); 149 asn1_enc_cleanup(pval, it);
150 /* If we free up as normal we will invalidate any 150 /*
151 * ANY DEFINED BY field and we wont be able to 151 * If we free up as normal, we will invalidate any
152 * ANY DEFINED BY field and we won't be able to
152 * determine the type of the field it defines. So 153 * determine the type of the field it defines. So
153 * free up in reverse order. 154 * free up in reverse order.
154 */ 155 */
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_add.S b/src/lib/libcrypto/bn/arch/amd64/bignum_add.S
index 5fe4aae7a1..1d4e6d08ef 100644
--- a/src/lib/libcrypto/bn/arch/amd64/bignum_add.S
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_add.S
@@ -1,3 +1,5 @@
1// $OpenBSD: bignum_add.S,v 1.7 2025/08/11 14:13:56 jsing Exp $
2//
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// 4//
3// Permission to use, copy, modify, and/or distribute this software for any 5// Permission to use, copy, modify, and/or distribute this software for any
@@ -16,9 +18,8 @@
16// Add, z := x + y 18// Add, z := x + y
17// Inputs x[m], y[n]; outputs function return (carry-out) and z[p] 19// Inputs x[m], y[n]; outputs function return (carry-out) and z[p]
18// 20//
19// extern uint64_t bignum_add 21// extern uint64_t bignum_add(uint64_t p, uint64_t *z, uint64_t m,
20// (uint64_t p, uint64_t *z, 22// const uint64_t *x, uint64_t n, const uint64_t *y);
21// uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
22// 23//
23// Does the z := x + y operation, truncating modulo p words in general and 24// Does the z := x + y operation, truncating modulo p words in general and
24// returning a top carry (0 or 1) in the p'th place, only adding the input 25// returning a top carry (0 or 1) in the p'th place, only adding the input
@@ -49,7 +50,7 @@
49 50
50 51
51S2N_BN_SYMBOL(bignum_add): 52S2N_BN_SYMBOL(bignum_add):
52 _CET_ENDBR 53 _CET_ENDBR
53 54
54#if WINDOWS_ABI 55#if WINDOWS_ABI
55 push rdi 56 push rdi
@@ -75,7 +76,7 @@ S2N_BN_SYMBOL(bignum_add):
75 cmp p, n 76 cmp p, n
76 cmovc n, p 77 cmovc n, p
77 cmp m, n 78 cmp m, n
78 jc ylonger 79 jc bignum_add_ylonger
79 80
80// The case where x is longer or of the same size (p >= m >= n) 81// The case where x is longer or of the same size (p >= m >= n)
81 82
@@ -83,27 +84,27 @@ S2N_BN_SYMBOL(bignum_add):
83 sub m, n 84 sub m, n
84 inc m 85 inc m
85 test n, n 86 test n, n
86 jz xtest 87 jz bignum_add_xtest
87xmainloop: 88bignum_add_xmainloop:
88 mov a, [x+8*i] 89 mov a, [x+8*i]
89 adc a, [y+8*i] 90 adc a, [y+8*i]
90 mov [z+8*i],a 91 mov [z+8*i],a
91 inc i 92 inc i
92 dec n 93 dec n
93 jnz xmainloop 94 jnz bignum_add_xmainloop
94 jmp xtest 95 jmp bignum_add_xtest
95xtoploop: 96bignum_add_xtoploop:
96 mov a, [x+8*i] 97 mov a, [x+8*i]
97 adc a, 0 98 adc a, 0
98 mov [z+8*i],a 99 mov [z+8*i],a
99 inc i 100 inc i
100xtest: 101bignum_add_xtest:
101 dec m 102 dec m
102 jnz xtoploop 103 jnz bignum_add_xtoploop
103 mov ashort, 0 104 mov ashort, 0
104 adc a, 0 105 adc a, 0
105 test p, p 106 test p, p
106 jnz tails 107 jnz bignum_add_tails
107#if WINDOWS_ABI 108#if WINDOWS_ABI
108 pop rsi 109 pop rsi
109 pop rdi 110 pop rdi
@@ -112,30 +113,30 @@ xtest:
112 113
113// The case where y is longer (p >= n > m) 114// The case where y is longer (p >= n > m)
114 115
115ylonger: 116bignum_add_ylonger:
116 117
117 sub p, n 118 sub p, n
118 sub n, m 119 sub n, m
119 test m, m 120 test m, m
120 jz ytoploop 121 jz bignum_add_ytoploop
121ymainloop: 122bignum_add_ymainloop:
122 mov a, [x+8*i] 123 mov a, [x+8*i]
123 adc a, [y+8*i] 124 adc a, [y+8*i]
124 mov [z+8*i],a 125 mov [z+8*i],a
125 inc i 126 inc i
126 dec m 127 dec m
127 jnz ymainloop 128 jnz bignum_add_ymainloop
128ytoploop: 129bignum_add_ytoploop:
129 mov a, [y+8*i] 130 mov a, [y+8*i]
130 adc a, 0 131 adc a, 0
131 mov [z+8*i],a 132 mov [z+8*i],a
132 inc i 133 inc i
133 dec n 134 dec n
134 jnz ytoploop 135 jnz bignum_add_ytoploop
135 mov ashort, 0 136 mov ashort, 0
136 adc a, 0 137 adc a, 0
137 test p, p 138 test p, p
138 jnz tails 139 jnz bignum_add_tails
139#if WINDOWS_ABI 140#if WINDOWS_ABI
140 pop rsi 141 pop rsi
141 pop rdi 142 pop rdi
@@ -144,16 +145,16 @@ ytoploop:
144 145
145// Adding a non-trivial tail, when p > max(m,n) 146// Adding a non-trivial tail, when p > max(m,n)
146 147
147tails: 148bignum_add_tails:
148 mov [z+8*i],a 149 mov [z+8*i],a
149 xor a, a 150 xor a, a
150 jmp tail 151 jmp bignum_add_tail
151tailloop: 152bignum_add_tailloop:
152 mov [z+8*i],a 153 mov [z+8*i],a
153tail: 154bignum_add_tail:
154 inc i 155 inc i
155 dec p 156 dec p
156 jnz tailloop 157 jnz bignum_add_tailloop
157#if WINDOWS_ABI 158#if WINDOWS_ABI
158 pop rsi 159 pop rsi
159 pop rdi 160 pop rdi
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_cmadd.S b/src/lib/libcrypto/bn/arch/amd64/bignum_cmadd.S
index 25ba17bce2..a611919603 100644
--- a/src/lib/libcrypto/bn/arch/amd64/bignum_cmadd.S
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_cmadd.S
@@ -1,3 +1,5 @@
1// $OpenBSD: bignum_cmadd.S,v 1.7 2025/08/11 14:13:56 jsing Exp $
2//
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// 4//
3// Permission to use, copy, modify, and/or distribute this software for any 5// Permission to use, copy, modify, and/or distribute this software for any
@@ -16,8 +18,8 @@
16// Multiply-add with single-word multiplier, z := z + c * y 18// Multiply-add with single-word multiplier, z := z + c * y
17// Inputs c, y[n]; outputs function return (carry-out) and z[k] 19// Inputs c, y[n]; outputs function return (carry-out) and z[k]
18// 20//
19// extern uint64_t bignum_cmadd 21// extern uint64_t bignum_cmadd(uint64_t k, uint64_t *z, uint64_t c, uint64_t n,
20// (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y); 22// const uint64_t *y);
21// 23//
22// Does the "z := z + c * y" operation where y is n digits, result z is p. 24// Does the "z := z + c * y" operation where y is n digits, result z is p.
23// Truncates the result in general. 25// Truncates the result in general.
@@ -54,7 +56,7 @@
54 56
55 57
56S2N_BN_SYMBOL(bignum_cmadd): 58S2N_BN_SYMBOL(bignum_cmadd):
57 _CET_ENDBR 59 _CET_ENDBR
58 60
59#if WINDOWS_ABI 61#if WINDOWS_ABI
60 push rdi 62 push rdi
@@ -82,7 +84,7 @@ S2N_BN_SYMBOL(bignum_cmadd):
82 84
83 xor h, h 85 xor h, h
84 test n, n 86 test n, n
85 jz end 87 jz bignum_cmadd_end
86 88
87// Move c into a safer register as multiplies overwrite rdx 89// Move c into a safer register as multiplies overwrite rdx
88 90
@@ -96,11 +98,11 @@ S2N_BN_SYMBOL(bignum_cmadd):
96 mov h, rdx 98 mov h, rdx
97 mov ishort, 1 99 mov ishort, 1
98 dec n 100 dec n
99 jz hightail 101 jz bignum_cmadd_hightail
100 102
101// Main loop, where we always have CF + previous high part h to add in 103// Main loop, where we always have CF + previous high part h to add in
102 104
103loop: 105bignum_cmadd_loop:
104 adc h, [z+8*i] 106 adc h, [z+8*i]
105 sbb r, r 107 sbb r, r
106 mov rax, [x+8*i] 108 mov rax, [x+8*i]
@@ -111,36 +113,36 @@ loop:
111 mov h, rdx 113 mov h, rdx
112 inc i 114 inc i
113 dec n 115 dec n
114 jnz loop 116 jnz bignum_cmadd_loop
115 117
116hightail: 118bignum_cmadd_hightail:
117 adc h, 0 119 adc h, 0
118 120
119// Propagate the carry all the way to the end with h as extra carry word 121// Propagate the carry all the way to the end with h as extra carry word
120 122
121tail: 123bignum_cmadd_tail:
122 test p, p 124 test p, p
123 jz end 125 jz bignum_cmadd_end
124 126
125 add [z+8*i], h 127 add [z+8*i], h
126 mov hshort, 0 128 mov hshort, 0
127 inc i 129 inc i
128 dec p 130 dec p
129 jz highend 131 jz bignum_cmadd_highend
130 132
131tloop: 133bignum_cmadd_tloop:
132 adc [z+8*i], h 134 adc [z+8*i], h
133 inc i 135 inc i
134 dec p 136 dec p
135 jnz tloop 137 jnz bignum_cmadd_tloop
136 138
137highend: 139bignum_cmadd_highend:
138 140
139 adc h, 0 141 adc h, 0
140 142
141// Return the high/carry word 143// Return the high/carry word
142 144
143end: 145bignum_cmadd_end:
144 mov rax, h 146 mov rax, h
145 147
146 pop rbx 148 pop rbx
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_cmul.S b/src/lib/libcrypto/bn/arch/amd64/bignum_cmul.S
index 12f785d63a..eb71d9da44 100644
--- a/src/lib/libcrypto/bn/arch/amd64/bignum_cmul.S
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_cmul.S
@@ -1,3 +1,5 @@
1// $OpenBSD: bignum_cmul.S,v 1.7 2025/08/11 14:13:56 jsing Exp $
2//
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// 4//
3// Permission to use, copy, modify, and/or distribute this software for any 5// Permission to use, copy, modify, and/or distribute this software for any
@@ -16,8 +18,8 @@
16// Multiply by a single word, z := c * y 18// Multiply by a single word, z := c * y
17// Inputs c, y[n]; outputs function return (carry-out) and z[k] 19// Inputs c, y[n]; outputs function return (carry-out) and z[k]
18// 20//
19// extern uint64_t bignum_cmul 21// extern uint64_t bignum_cmul(uint64_t k, uint64_t *z, uint64_t c, uint64_t n,
20// (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y); 22// const uint64_t *y);
21// 23//
22// Does the "z := c * y" operation where y is n digits, result z is p. 24// Does the "z := c * y" operation where y is n digits, result z is p.
23// Truncates the result in general unless p >= n + 1. 25// Truncates the result in general unless p >= n + 1.
@@ -51,7 +53,7 @@
51 53
52 54
53S2N_BN_SYMBOL(bignum_cmul): 55S2N_BN_SYMBOL(bignum_cmul):
54 _CET_ENDBR 56 _CET_ENDBR
55 57
56#if WINDOWS_ABI 58#if WINDOWS_ABI
57 push rdi 59 push rdi
@@ -76,7 +78,7 @@ S2N_BN_SYMBOL(bignum_cmul):
76 xor h, h 78 xor h, h
77 xor i, i 79 xor i, i
78 test n, n 80 test n, n
79 jz tail 81 jz bignum_cmul_tail
80 82
81// Move c into a safer register as multiplies overwrite rdx 83// Move c into a safer register as multiplies overwrite rdx
82 84
@@ -90,11 +92,11 @@ S2N_BN_SYMBOL(bignum_cmul):
90 mov h, rdx 92 mov h, rdx
91 inc i 93 inc i
92 cmp i, n 94 cmp i, n
93 jz tail 95 jz bignum_cmul_tail
94 96
95// Main loop doing the multiplications 97// Main loop doing the multiplications
96 98
97loop: 99bignum_cmul_loop:
98 mov rax, [x+8*i] 100 mov rax, [x+8*i]
99 mul c 101 mul c
100 add rax, h 102 add rax, h
@@ -103,28 +105,28 @@ loop:
103 mov h, rdx 105 mov h, rdx
104 inc i 106 inc i
105 cmp i, n 107 cmp i, n
106 jc loop 108 jc bignum_cmul_loop
107 109
108// Add a tail when the destination is longer 110// Add a tail when the destination is longer
109 111
110tail: 112bignum_cmul_tail:
111 cmp i, p 113 cmp i, p
112 jnc end 114 jnc bignum_cmul_end
113 mov [z+8*i], h 115 mov [z+8*i], h
114 xor h, h 116 xor h, h
115 inc i 117 inc i
116 cmp i, p 118 cmp i, p
117 jnc end 119 jnc bignum_cmul_end
118 120
119tloop: 121bignum_cmul_tloop:
120 mov [z+8*i], h 122 mov [z+8*i], h
121 inc i 123 inc i
122 cmp i, p 124 cmp i, p
123 jc tloop 125 jc bignum_cmul_tloop
124 126
125// Return the high/carry word 127// Return the high/carry word
126 128
127end: 129bignum_cmul_end:
128 mov rax, h 130 mov rax, h
129 131
130#if WINDOWS_ABI 132#if WINDOWS_ABI
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_modadd.S b/src/lib/libcrypto/bn/arch/amd64/bignum_modadd.S
new file mode 100644
index 0000000000..baf27fdc7f
--- /dev/null
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_modadd.S
@@ -0,0 +1,112 @@
1// $OpenBSD: bignum_modadd.S,v 1.4 2025/08/12 10:23:40 jsing Exp $
2//
3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4//
5// Permission to use, copy, modify, and/or distribute this software for any
6// purpose with or without fee is hereby granted, provided that the above
7// copyright notice and this permission notice appear in all copies.
8//
9// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17// ----------------------------------------------------------------------------
18// Add modulo m, z := (x + y) mod m, assuming x and y reduced
19// Inputs x[k], y[k], m[k]; output z[k]
20//
21// extern void bignum_modadd(uint64_t k, uint64_t *z, const uint64_t *x,
22// const uint64_t *y, const uint64_t *m);
23//
24// Standard x86-64 ABI: RDI = k, RSI = z, RDX = x, RCX = y, R8 = m
25// Microsoft x64 ABI: RCX = k, RDX = z, R8 = x, R9 = y, [RSP+40] = m
26// ----------------------------------------------------------------------------
27
28#include "s2n_bignum_internal.h"
29
30 .intel_syntax noprefix
31 S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_modadd)
32 S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_modadd)
33 .text
34
35#define k rdi
36#define z rsi
37#define x rdx
38#define y rcx
39#define m r8
40#define i r9
41#define j r10
42#define a rax
43#define c r11
44
45S2N_BN_SYMBOL(bignum_modadd):
46 _CET_ENDBR
47
48#if WINDOWS_ABI
49 push rdi
50 push rsi
51 mov rdi, rcx
52 mov rsi, rdx
53 mov rdx, r8
54 mov rcx, r9
55 mov r8, [rsp+56]
56#endif
57
58// If k = 0 do nothing
59
60 test k, k
61 jz bignum_modadd_end
62
63// First just add (c::z) := x + y
64
65 xor c, c
66 mov j, k
67 xor i, i
68bignum_modadd_addloop:
69 mov a, [x+8*i]
70 adc a, [y+8*i]
71 mov [z+8*i], a
72 inc i
73 dec j
74 jnz bignum_modadd_addloop
75 adc c, 0
76
77// Now do a comparison subtraction (c::z) - m, recording mask for (c::z) >= m
78
79 mov j, k
80 xor i, i
81bignum_modadd_cmploop:
82 mov a, [z+8*i]
83 sbb a, [m+8*i]
84 inc i
85 dec j
86 jnz bignum_modadd_cmploop
87 sbb c, 0
88 not c
89
90// Now do a masked subtraction z := z - [c] * m
91
92 xor i, i
93bignum_modadd_subloop:
94 mov a, [m+8*i]
95 and a, c
96 neg j
97 sbb [z+8*i], a
98 sbb j, j
99 inc i
100 cmp i, k
101 jc bignum_modadd_subloop
102
103bignum_modadd_end:
104#if WINDOWS_ABI
105 pop rsi
106 pop rdi
107#endif
108 ret
109
110#if defined(__linux__) && defined(__ELF__)
111.section .note.GNU-stack,"",%progbits
112#endif
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_modsub.S b/src/lib/libcrypto/bn/arch/amd64/bignum_modsub.S
new file mode 100644
index 0000000000..63b3230e35
--- /dev/null
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_modsub.S
@@ -0,0 +1,99 @@
1// $OpenBSD: bignum_modsub.S,v 1.4 2025/08/12 10:23:40 jsing Exp $
2//
3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4//
5// Permission to use, copy, modify, and/or distribute this software for any
6// purpose with or without fee is hereby granted, provided that the above
7// copyright notice and this permission notice appear in all copies.
8//
9// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17// ----------------------------------------------------------------------------
18// Subtract modulo m, z := (x - y) mod m, assuming x and y reduced
19// Inputs x[k], y[k], m[k]; output z[k]
20//
21// extern void bignum_modsub(uint64_t k, uint64_t *z, const uint64_t *x,
22// const uint64_t *y, const uint64_t *m);
23//
24// Standard x86-64 ABI: RDI = k, RSI = z, RDX = x, RCX = y, R8 = m
25// Microsoft x64 ABI: RCX = k, RDX = z, R8 = x, R9 = y, [RSP+40] = m
26// ----------------------------------------------------------------------------
27
28#include "s2n_bignum_internal.h"
29
30 .intel_syntax noprefix
31 S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_modsub)
32 S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_modsub)
33 .text
34
35#define k rdi
36#define z rsi
37#define x rdx
38#define y rcx
39#define m r8
40#define i r9
41#define j r10
42#define a rax
43#define c r11
44
45S2N_BN_SYMBOL(bignum_modsub):
46 _CET_ENDBR
47
48#if WINDOWS_ABI
49 push rdi
50 push rsi
51 mov rdi, rcx
52 mov rsi, rdx
53 mov rdx, r8
54 mov rcx, r9
55 mov r8, [rsp+56]
56#endif
57
58// If k = 0 do nothing
59
60 test k, k
61 jz bignum_modsub_end
62
63// Subtract z := x - y and record a mask for the carry x - y < 0
64
65 xor c, c
66 mov j, k
67 xor i, i
68bignum_modsub_subloop:
69 mov a, [x+8*i]
70 sbb a, [y+8*i]
71 mov [z+8*i], a
72 inc i
73 dec j
74 jnz bignum_modsub_subloop
75 sbb c, c
76
77// Now do a masked addition z := z + [c] * m
78
79 xor i, i
80bignum_modsub_addloop:
81 mov a, [m+8*i]
82 and a, c
83 neg j
84 adc [z+8*i], a
85 sbb j, j
86 inc i
87 cmp i, k
88 jc bignum_modsub_addloop
89
90bignum_modsub_end:
91#if WINDOWS_ABI
92 pop rsi
93 pop rdi
94#endif
95 ret
96
97#if defined(__linux__) && defined(__ELF__)
98.section .note.GNU-stack,"",%progbits
99#endif
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_mul.S b/src/lib/libcrypto/bn/arch/amd64/bignum_mul.S
index a3552679a2..538cce9af7 100644
--- a/src/lib/libcrypto/bn/arch/amd64/bignum_mul.S
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_mul.S
@@ -1,3 +1,5 @@
1// $OpenBSD: bignum_mul.S,v 1.7 2025/08/11 14:13:56 jsing Exp $
2//
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// 4//
3// Permission to use, copy, modify, and/or distribute this software for any 5// Permission to use, copy, modify, and/or distribute this software for any
@@ -16,9 +18,8 @@
16// Multiply z := x * y 18// Multiply z := x * y
17// Inputs x[m], y[n]; output z[k] 19// Inputs x[m], y[n]; output z[k]
18// 20//
19// extern void bignum_mul 21// extern void bignum_mul(uint64_t k, uint64_t *z, uint64_t m, const uint64_t *x,
20// (uint64_t k, uint64_t *z, 22// uint64_t n, const uint64_t *y);
21// uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
22// 23//
23// Does the "z := x * y" operation where x is m digits, y is n, result z is k. 24// Does the "z := x * y" operation where x is m digits, y is n, result z is k.
24// Truncates the result in general unless k >= m + n 25// Truncates the result in general unless k >= m + n
@@ -59,7 +60,7 @@
59 60
60 61
61S2N_BN_SYMBOL(bignum_mul): 62S2N_BN_SYMBOL(bignum_mul):
62 _CET_ENDBR 63 _CET_ENDBR
63 64
64#if WINDOWS_ABI 65#if WINDOWS_ABI
65 push rdi 66 push rdi
@@ -88,7 +89,7 @@ S2N_BN_SYMBOL(bignum_mul):
88// If we did a multiply-add variant, however, then we could 89// If we did a multiply-add variant, however, then we could
89 90
90 test p, p 91 test p, p
91 jz end 92 jz bignum_mul_end
92 93
93// Set initial 2-part sum to zero (we zero c inside the body) 94// Set initial 2-part sum to zero (we zero c inside the body)
94 95
@@ -99,7 +100,7 @@ S2N_BN_SYMBOL(bignum_mul):
99 100
100 xor k, k 101 xor k, k
101 102
102outerloop: 103bignum_mul_outerloop:
103 104
104// Zero our carry term first; we eventually want it and a zero is useful now 105// Zero our carry term first; we eventually want it and a zero is useful now
105// Set a = max 0 (k + 1 - n), i = min (k + 1) m 106// Set a = max 0 (k + 1 - n), i = min (k + 1) m
@@ -125,11 +126,11 @@ outerloop:
125 mov d, k 126 mov d, k
126 sub d, i 127 sub d, i
127 sub i, a 128 sub i, a
128 jbe innerend 129 jbe bignum_mul_innerend
129 lea x,[rcx+8*a] 130 lea x,[rcx+8*a]
130 lea y,[r9+8*d-8] 131 lea y,[r9+8*d-8]
131 132
132innerloop: 133bignum_mul_innerloop:
133 mov rax, [y+8*i] 134 mov rax, [y+8*i]
134 mul QWORD PTR [x] 135 mul QWORD PTR [x]
135 add x, 8 136 add x, 8
@@ -137,9 +138,9 @@ innerloop:
137 adc h, rdx 138 adc h, rdx
138 adc c, 0 139 adc c, 0
139 dec i 140 dec i
140 jnz innerloop 141 jnz bignum_mul_innerloop
141 142
142innerend: 143bignum_mul_innerend:
143 144
144 mov [z], l 145 mov [z], l
145 mov l, h 146 mov l, h
@@ -147,9 +148,9 @@ innerend:
147 add z, 8 148 add z, 8
148 149
149 cmp k, p 150 cmp k, p
150 jc outerloop 151 jc bignum_mul_outerloop
151 152
152end: 153bignum_mul_end:
153 pop r15 154 pop r15
154 pop r14 155 pop r14
155 pop r13 156 pop r13
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_mul_4_8.S b/src/lib/libcrypto/bn/arch/amd64/bignum_mul_4_8.S
new file mode 100644
index 0000000000..d6ad514020
--- /dev/null
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_mul_4_8.S
@@ -0,0 +1,187 @@
1// $OpenBSD: bignum_mul_4_8.S,v 1.4 2025/08/12 10:23:40 jsing Exp $
2//
3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4//
5// Permission to use, copy, modify, and/or distribute this software for any
6// purpose with or without fee is hereby granted, provided that the above
7// copyright notice and this permission notice appear in all copies.
8//
9// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17// ----------------------------------------------------------------------------
18// Multiply z := x * y
19// Inputs x[4], y[4]; output z[8]
20//
21// extern void bignum_mul_4_8(uint64_t z[static 8], const uint64_t x[static 4],
22// const uint64_t y[static 4]);
23//
24// Standard x86-64 ABI: RDI = z, RSI = x, RDX = y
25// Microsoft x64 ABI: RCX = z, RDX = x, R8 = y
26// ----------------------------------------------------------------------------
27
28#include "s2n_bignum_internal.h"
29
30 .intel_syntax noprefix
31 S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_mul_4_8)
32 S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_mul_4_8)
33 .text
34
35// These are actually right
36
37#define z rdi
38#define x rsi
39
40// Copied in or set up
41
42#define y rcx
43
44// A zero register
45
46#define zero rbp
47#define zeroe ebp
48
49// Add in x[i] * rdx to the (i,i+1) position with the register window
50// Would be nice to have conditional expressions reg[i], reg[i+1] ...
51
52.macro mulpadd arg1,arg2
53 mulx rbx, rax, [x+8*\arg2]
54.if ((\arg1 + \arg2) % 4 == 0)
55 adcx r8, rax
56 adox r9, rbx
57.elseif ((\arg1 + \arg2) % 4 == 1)
58 adcx r9, rax
59 adox r10, rbx
60.elseif ((\arg1 + \arg2) % 4 == 2)
61 adcx r10, rax
62 adox r11, rbx
63.elseif ((\arg1 + \arg2) % 4 == 3)
64 adcx r11, rax
65 adox r8, rbx
66.endif
67
68.endm
69
70
71// Add in the whole j'th row
72
73.macro addrow arg1
74 mov rdx, [y+8*\arg1]
75 xor zeroe, zeroe
76
77 mulpadd \arg1, 0
78
79.if (\arg1 % 4 == 0)
80 mov [z+8*\arg1],r8
81.elseif (\arg1 % 4 == 1)
82 mov [z+8*\arg1],r9
83.elseif (\arg1 % 4 == 2)
84 mov [z+8*\arg1],r10
85.elseif (\arg1 % 4 == 3)
86 mov [z+8*\arg1],r11
87.endif
88
89 mulpadd \arg1, 1
90 mulpadd \arg1, 2
91
92.if (\arg1 % 4 == 0)
93 mulx r8, rax, [x+24]
94 adcx r11, rax
95 adox r8, zero
96 adcx r8, zero
97.elseif (\arg1 % 4 == 1)
98 mulx r9, rax, [x+24]
99 adcx r8, rax
100 adox r9, zero
101 adcx r9, zero
102.elseif (\arg1 % 4 == 2)
103 mulx r10, rax, [x+24]
104 adcx r9, rax
105 adox r10, zero
106 adcx r10, zero
107.elseif (\arg1 % 4 == 3)
108 mulx r11, rax, [x+24]
109 adcx r10, rax
110 adox r11, zero
111 adcx r11, zero
112.endif
113
114.endm
115
116
117
118S2N_BN_SYMBOL(bignum_mul_4_8):
119 _CET_ENDBR
120
121#if WINDOWS_ABI
122 push rdi
123 push rsi
124 mov rdi, rcx
125 mov rsi, rdx
126 mov rdx, r8
127#endif
128
129// Save more registers to play with
130
131 push rbp
132 push rbx
133
134// Copy y into a safe register to start with
135
136 mov y, rdx
137
138// Zero a register, which also makes sure we don't get a fake carry-in
139
140 xor zeroe, zeroe
141
142// Do the zeroth row, which is a bit different
143// Write back the zero-zero product and then accumulate
144// r8,r11,r10,r9 as y[0] * x from 1..4
145
146 mov rdx, [y]
147
148 mulx r9, r8, [x]
149 mov [z], r8
150
151 mulx r10, rbx, [x+8]
152 adcx r9, rbx
153
154 mulx r11, rbx, [x+16]
155 adcx r10, rbx
156
157 mulx r8, rbx, [x+24]
158 adcx r11, rbx
159 adcx r8, zero
160
161// Now all the other rows in a uniform pattern
162
163 addrow 1
164 addrow 2
165 addrow 3
166
167// Now write back the additional columns
168
169 mov [z+32], r8
170 mov [z+40], r9
171 mov [z+48], r10
172 mov [z+56], r11
173
174// Restore registers and return
175
176 pop rbx
177 pop rbp
178
179#if WINDOWS_ABI
180 pop rsi
181 pop rdi
182#endif
183 ret
184
185#if defined(__linux__) && defined(__ELF__)
186.section .note.GNU-stack,"",%progbits
187#endif
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_mul_4_8_alt.S b/src/lib/libcrypto/bn/arch/amd64/bignum_mul_4_8_alt.S
index 70ff69e372..2592d1d658 100644
--- a/src/lib/libcrypto/bn/arch/amd64/bignum_mul_4_8_alt.S
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_mul_4_8_alt.S
@@ -1,3 +1,5 @@
1// $OpenBSD: bignum_mul_4_8_alt.S,v 1.7 2025/08/11 14:13:56 jsing Exp $
2//
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// 4//
3// Permission to use, copy, modify, and/or distribute this software for any 5// Permission to use, copy, modify, and/or distribute this software for any
@@ -16,8 +18,8 @@
16// Multiply z := x * y 18// Multiply z := x * y
17// Inputs x[4], y[4]; output z[8] 19// Inputs x[4], y[4]; output z[8]
18// 20//
19// extern void bignum_mul_4_8_alt 21// extern void bignum_mul_4_8_alt(uint64_t z[static 8], const uint64_t x[static 4],
20// (uint64_t z[static 8], uint64_t x[static 4], uint64_t y[static 4]); 22// const uint64_t y[static 4]);
21// 23//
22// Standard x86-64 ABI: RDI = z, RSI = x, RDX = y 24// Standard x86-64 ABI: RDI = z, RSI = x, RDX = y
23// Microsoft x64 ABI: RCX = z, RDX = x, R8 = y 25// Microsoft x64 ABI: RCX = z, RDX = x, R8 = y
@@ -72,7 +74,7 @@
72 adc h, rdx 74 adc h, rdx
73 75
74S2N_BN_SYMBOL(bignum_mul_4_8_alt): 76S2N_BN_SYMBOL(bignum_mul_4_8_alt):
75 _CET_ENDBR 77 _CET_ENDBR
76 78
77#if WINDOWS_ABI 79#if WINDOWS_ABI
78 push rdi 80 push rdi
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_mul_6_12.S b/src/lib/libcrypto/bn/arch/amd64/bignum_mul_6_12.S
new file mode 100644
index 0000000000..56cbdf06e0
--- /dev/null
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_mul_6_12.S
@@ -0,0 +1,223 @@
1// $OpenBSD: bignum_mul_6_12.S,v 1.4 2025/08/12 10:23:40 jsing Exp $
2//
3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4//
5// Permission to use, copy, modify, and/or distribute this software for any
6// purpose with or without fee is hereby granted, provided that the above
7// copyright notice and this permission notice appear in all copies.
8//
9// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17// ----------------------------------------------------------------------------
18// Multiply z := x * y
19// Inputs x[6], y[6]; output z[12]
20//
21// extern void bignum_mul_6_12(uint64_t z[static 12], const uint64_t x[static 6],
22// const uint64_t y[static 6]);
23//
24// Standard x86-64 ABI: RDI = z, RSI = x, RDX = y
25// Microsoft x64 ABI: RCX = z, RDX = x, R8 = y
26// ----------------------------------------------------------------------------
27
28#include "s2n_bignum_internal.h"
29
30 .intel_syntax noprefix
31 S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_mul_6_12)
32 S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_mul_6_12)
33 .text
34
35// These are actually right
36
37#define z rdi
38#define x rsi
39
40// Copied in or set up
41
42#define y rcx
43
44// A zero register
45
46#define zero rbp
47#define zeroe ebp
48
49// Add in x[i] * rdx to the (i,i+1) position with the register window
50// Would be nice to have conditional expressions reg[i], reg[i+1] ...
51
52.macro mulpadd arg1,arg2
53 mulx rbx, rax, [x+8*\arg2]
54.if ((\arg1 + \arg2) % 6 == 0)
55 adcx r8, rax
56 adox r9, rbx
57.elseif ((\arg1 + \arg2) % 6 == 1)
58 adcx r9, rax
59 adox r10, rbx
60.elseif ((\arg1 + \arg2) % 6 == 2)
61 adcx r10, rax
62 adox r11, rbx
63.elseif ((\arg1 + \arg2) % 6 == 3)
64 adcx r11, rax
65 adox r12, rbx
66.elseif ((\arg1 + \arg2) % 6 == 4)
67 adcx r12, rax
68 adox r13, rbx
69.elseif ((\arg1 + \arg2) % 6 == 5)
70 adcx r13, rax
71 adox r8, rbx
72.endif
73
74.endm
75
76
77// Add in the whole j'th row
78
79.macro addrow arg1
80 mov rdx, [y+8*\arg1]
81 xor zeroe, zeroe
82
83 mulpadd \arg1, 0
84
85.if (\arg1 % 6 == 0)
86 mov [z+8*\arg1],r8
87.elseif (\arg1 % 6 == 1)
88 mov [z+8*\arg1],r9
89.elseif (\arg1 % 6 == 2)
90 mov [z+8*\arg1],r10
91.elseif (\arg1 % 6 == 3)
92 mov [z+8*\arg1],r11
93.elseif (\arg1 % 6 == 4)
94 mov [z+8*\arg1],r12
95.elseif (\arg1 % 6 == 5)
96 mov [z+8*\arg1],r13
97.endif
98
99 mulpadd \arg1, 1
100 mulpadd \arg1, 2
101 mulpadd \arg1, 3
102 mulpadd \arg1, 4
103
104.if (\arg1 % 6 == 0)
105 mulx r8, rax, [x+40]
106 adcx r13, rax
107 adox r8, zero
108 adcx r8, zero
109.elseif (\arg1 % 6 == 1)
110 mulx r9, rax, [x+40]
111 adcx r8, rax
112 adox r9, zero
113 adcx r9, zero
114.elseif (\arg1 % 6 == 2)
115 mulx r10, rax, [x+40]
116 adcx r9, rax
117 adox r10, zero
118 adcx r10, zero
119.elseif (\arg1 % 6 == 3)
120 mulx r11, rax, [x+40]
121 adcx r10, rax
122 adox r11, zero
123 adcx r11, zero
124.elseif (\arg1 % 6 == 4)
125 mulx r12, rax, [x+40]
126 adcx r11, rax
127 adox r12, zero
128 adcx r12, zero
129.elseif (\arg1 % 6 == 5)
130 mulx r13, rax, [x+40]
131 adcx r12, rax
132 adox r13, zero
133 adcx r13, zero
134.endif
135
136.endm
137
138
139
140S2N_BN_SYMBOL(bignum_mul_6_12):
141 _CET_ENDBR
142
143#if WINDOWS_ABI
144 push rdi
145 push rsi
146 mov rdi, rcx
147 mov rsi, rdx
148 mov rdx, r8
149#endif
150
151// Save more registers to play with
152
153 push rbp
154 push rbx
155 push r12
156 push r13
157
158// Copy y into a safe register to start with
159
160 mov y, rdx
161
162// Zero a register, which also makes sure we don't get a fake carry-in
163
164 xor zeroe, zeroe
165
166// Do the zeroth row, which is a bit different
167// Write back the zero-zero product and then accumulate
168// r8,r13,r12,r11,r10,r9 as y[0] * x from 1..6
169
170 mov rdx, [y]
171
172 mulx r9, r8, [x]
173 mov [z], r8
174
175 mulx r10, rbx, [x+8]
176 adcx r9, rbx
177
178 mulx r11, rbx, [x+16]
179 adcx r10, rbx
180
181 mulx r12, rbx, [x+24]
182 adcx r11, rbx
183
184 mulx r13, rbx, [x+32]
185 adcx r12, rbx
186
187 mulx r8, rbx, [x+40]
188 adcx r13, rbx
189 adcx r8, zero
190
191// Now all the other rows in a uniform pattern
192
193 addrow 1
194 addrow 2
195 addrow 3
196 addrow 4
197 addrow 5
198
199// Now write back the additional columns
200
201 mov [z+48], r8
202 mov [z+56], r9
203 mov [z+64], r10
204 mov [z+72], r11
205 mov [z+80], r12
206 mov [z+88], r13
207
208// Restore registers and return
209
210 pop r13
211 pop r12
212 pop rbx
213 pop rbp
214
215#if WINDOWS_ABI
216 pop rsi
217 pop rdi
218#endif
219 ret
220
221#if defined(__linux__) && defined(__ELF__)
222.section .note.GNU-stack,"",%progbits
223#endif
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_mul_6_12_alt.S b/src/lib/libcrypto/bn/arch/amd64/bignum_mul_6_12_alt.S
new file mode 100644
index 0000000000..077c52b38e
--- /dev/null
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_mul_6_12_alt.S
@@ -0,0 +1,199 @@
1// $OpenBSD: bignum_mul_6_12_alt.S,v 1.4 2025/08/12 10:23:40 jsing Exp $
2//
3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4//
5// Permission to use, copy, modify, and/or distribute this software for any
6// purpose with or without fee is hereby granted, provided that the above
7// copyright notice and this permission notice appear in all copies.
8//
9// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17// ----------------------------------------------------------------------------
18// Multiply z := x * y
19// Inputs x[6], y[6]; output z[12]
20//
21// extern void bignum_mul_6_12_alt(uint64_t z[static 12],
22// const uint64_t x[static 6],
23// const uint64_t y[static 6]);
24//
25// Standard x86-64 ABI: RDI = z, RSI = x, RDX = y
26// Microsoft x64 ABI: RCX = z, RDX = x, R8 = y
27// ----------------------------------------------------------------------------
28
29#include "s2n_bignum_internal.h"
30
31 .intel_syntax noprefix
32 S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_mul_6_12_alt)
33 S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_mul_6_12_alt)
34 .text
35
36// These are actually right
37
38#define z rdi
39#define x rsi
40
41// This is moved from rdx to free it for muls
42
43#define y rcx
44
45// Other variables used as a rotating 3-word window to add terms to
46
47#define t0 r8
48#define t1 r9
49#define t2 r10
50
51// Macro for the key "multiply and add to (c,h,l)" step
52
53#define combadd(c,h,l,numa,numb) \
54 mov rax, numa; \
55 mul QWORD PTR numb; \
56 add l, rax; \
57 adc h, rdx; \
58 adc c, 0
59
60// A minutely shorter form for when c = 0 initially
61
62#define combadz(c,h,l,numa,numb) \
63 mov rax, numa; \
64 mul QWORD PTR numb; \
65 add l, rax; \
66 adc h, rdx; \
67 adc c, c
68
69// A short form where we don't expect a top carry
70
71#define combads(h,l,numa,numb) \
72 mov rax, numa; \
73 mul QWORD PTR numb; \
74 add l, rax; \
75 adc h, rdx
76
77S2N_BN_SYMBOL(bignum_mul_6_12_alt):
78 _CET_ENDBR
79
80#if WINDOWS_ABI
81 push rdi
82 push rsi
83 mov rdi, rcx
84 mov rsi, rdx
85 mov rdx, r8
86#endif
87
88// Copy y into a safe register to start with
89
90 mov y, rdx
91
92// Result term 0
93
94 mov rax, [x]
95 mul QWORD PTR [y]
96
97 mov [z], rax
98 mov t0, rdx
99 xor t1, t1
100
101// Result term 1
102
103 xor t2, t2
104 combads(t1,t0,[x],[y+8])
105 combadz(t2,t1,t0,[x+8],[y])
106 mov [z+8], t0
107
108// Result term 2
109
110 xor t0, t0
111 combadz(t0,t2,t1,[x],[y+16])
112 combadd(t0,t2,t1,[x+8],[y+8])
113 combadd(t0,t2,t1,[x+16],[y])
114 mov [z+16], t1
115
116// Result term 3
117
118 xor t1, t1
119 combadz(t1,t0,t2,[x],[y+24])
120 combadd(t1,t0,t2,[x+8],[y+16])
121 combadd(t1,t0,t2,[x+16],[y+8])
122 combadd(t1,t0,t2,[x+24],[y])
123 mov [z+24], t2
124
125// Result term 4
126
127 xor t2, t2
128 combadz(t2,t1,t0,[x],[y+32])
129 combadd(t2,t1,t0,[x+8],[y+24])
130 combadd(t2,t1,t0,[x+16],[y+16])
131 combadd(t2,t1,t0,[x+24],[y+8])
132 combadd(t2,t1,t0,[x+32],[y])
133 mov [z+32], t0
134
135// Result term 5
136
137 xor t0, t0
138 combadz(t0,t2,t1,[x],[y+40])
139 combadd(t0,t2,t1,[x+8],[y+32])
140 combadd(t0,t2,t1,[x+16],[y+24])
141 combadd(t0,t2,t1,[x+24],[y+16])
142 combadd(t0,t2,t1,[x+32],[y+8])
143 combadd(t0,t2,t1,[x+40],[y])
144 mov [z+40], t1
145
146// Result term 6
147
148 xor t1, t1
149 combadz(t1,t0,t2,[x+8],[y+40])
150 combadd(t1,t0,t2,[x+16],[y+32])
151 combadd(t1,t0,t2,[x+24],[y+24])
152 combadd(t1,t0,t2,[x+32],[y+16])
153 combadd(t1,t0,t2,[x+40],[y+8])
154 mov [z+48], t2
155
156// Result term 7
157
158 xor t2, t2
159 combadz(t2,t1,t0,[x+16],[y+40])
160 combadd(t2,t1,t0,[x+24],[y+32])
161 combadd(t2,t1,t0,[x+32],[y+24])
162 combadd(t2,t1,t0,[x+40],[y+16])
163 mov [z+56], t0
164
165// Result term 8
166
167 xor t0, t0
168 combadz(t0,t2,t1,[x+24],[y+40])
169 combadd(t0,t2,t1,[x+32],[y+32])
170 combadd(t0,t2,t1,[x+40],[y+24])
171 mov [z+64], t1
172
173// Result term 9
174
175 xor t1, t1
176 combadz(t1,t0,t2,[x+32],[y+40])
177 combadd(t1,t0,t2,[x+40],[y+32])
178 mov [z+72], t2
179
180// Result term 10
181
182 combads(t1,t0,[x+40],[y+40])
183 mov [z+80], t0
184
185// Result term 11
186
187 mov [z+88], t1
188
189// Return
190
191#if WINDOWS_ABI
192 pop rsi
193 pop rdi
194#endif
195 ret
196
197#if defined(__linux__) && defined(__ELF__)
198.section .note.GNU-stack,"",%progbits
199#endif
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_mul_8_16.S b/src/lib/libcrypto/bn/arch/amd64/bignum_mul_8_16.S
new file mode 100644
index 0000000000..faa0196d8e
--- /dev/null
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_mul_8_16.S
@@ -0,0 +1,273 @@
1// $OpenBSD: bignum_mul_8_16.S,v 1.4 2025/08/12 10:23:40 jsing Exp $
2//
3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4//
5// Permission to use, copy, modify, and/or distribute this software for any
6// purpose with or without fee is hereby granted, provided that the above
7// copyright notice and this permission notice appear in all copies.
8//
9// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17// ----------------------------------------------------------------------------
18// Multiply z := x * y
19// Inputs x[8], y[8]; output z[16]
20//
21// extern void bignum_mul_8_16(uint64_t z[static 16], const uint64_t x[static 8],
22// const uint64_t y[static 8]);
23//
24// Standard x86-64 ABI: RDI = z, RSI = x, RDX = y
25// Microsoft x64 ABI: RCX = z, RDX = x, R8 = y
26// ----------------------------------------------------------------------------
27
28#include "s2n_bignum_internal.h"
29
30 .intel_syntax noprefix
31 S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_mul_8_16)
32 S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_mul_8_16)
33 .text
34
35// These are actually right
36
37#define z rdi
38#define x rsi
39
40// Copied in or set up
41
42#define y rcx
43
44// A zero register
45
46#define zero rbp
47#define zeroe ebp
48
49// mulpadd i, j adds x[i] * rdx (now assumed = y[j]) into the window at i+j
50
51.macro mulpadd arg1,arg2
52 mulx rbx, rax, [x+8*\arg1]
53.if ((\arg1 + \arg2) % 8 == 0)
54 adcx r8, rax
55 adox r9, rbx
56.elseif ((\arg1 + \arg2) % 8 == 1)
57 adcx r9, rax
58 adox r10, rbx
59.elseif ((\arg1 + \arg2) % 8 == 2)
60 adcx r10, rax
61 adox r11, rbx
62.elseif ((\arg1 + \arg2) % 8 == 3)
63 adcx r11, rax
64 adox r12, rbx
65.elseif ((\arg1 + \arg2) % 8 == 4)
66 adcx r12, rax
67 adox r13, rbx
68.elseif ((\arg1 + \arg2) % 8 == 5)
69 adcx r13, rax
70 adox r14, rbx
71.elseif ((\arg1 + \arg2) % 8 == 6)
72 adcx r14, rax
73 adox r15, rbx
74.elseif ((\arg1 + \arg2) % 8 == 7)
75 adcx r15, rax
76 adox r8, rbx
77.endif
78
79.endm
80
81// mulpade i, j adds x[i] * rdx (now assumed = y[j]) into the window at i+j
82// but re-creates the top word assuming nothing to add there
83
84.macro mulpade arg1,arg2
85.if ((\arg1 + \arg2) % 8 == 0)
86 mulx r9, rax, [x+8*\arg1]
87 adcx r8, rax
88 adox r9, zero
89.elseif ((\arg1 + \arg2) % 8 == 1)
90 mulx r10, rax, [x+8*\arg1]
91 adcx r9, rax
92 adox r10, zero
93.elseif ((\arg1 + \arg2) % 8 == 2)
94 mulx r11, rax, [x+8*\arg1]
95 adcx r10, rax
96 adox r11, zero
97.elseif ((\arg1 + \arg2) % 8 == 3)
98 mulx r12, rax, [x+8*\arg1]
99 adcx r11, rax
100 adox r12, zero
101.elseif ((\arg1 + \arg2) % 8 == 4)
102 mulx r13, rax, [x+8*\arg1]
103 adcx r12, rax
104 adox r13, zero
105.elseif ((\arg1 + \arg2) % 8 == 5)
106 mulx r14, rax, [x+8*\arg1]
107 adcx r13, rax
108 adox r14, zero
109.elseif ((\arg1 + \arg2) % 8 == 6)
110 mulx r15, rax, [x+8*\arg1]
111 adcx r14, rax
112 adox r15, zero
113.elseif ((\arg1 + \arg2) % 8 == 7)
114 mulx r8, rax, [x+8*\arg1]
115 adcx r15, rax
116 adox r8, zero
117.endif
118
119.endm
120
121// Add in the whole j'th row
122
123.macro addrow arg1
124 mov rdx, [y+8*\arg1]
125 xor zeroe, zeroe
126
127 mulpadd 0, \arg1
128
129.if (\arg1 % 8 == 0)
130 mov [z+8*\arg1],r8
131.elseif (\arg1 % 8 == 1)
132 mov [z+8*\arg1],r9
133.elseif (\arg1 % 8 == 2)
134 mov [z+8*\arg1],r10
135.elseif (\arg1 % 8 == 3)
136 mov [z+8*\arg1],r11
137.elseif (\arg1 % 8 == 4)
138 mov [z+8*\arg1],r12
139.elseif (\arg1 % 8 == 5)
140 mov [z+8*\arg1],r13
141.elseif (\arg1 % 8 == 6)
142 mov [z+8*\arg1],r14
143.elseif (\arg1 % 8 == 7)
144 mov [z+8*\arg1],r15
145.endif
146
147 mulpadd 1, \arg1
148 mulpadd 2, \arg1
149 mulpadd 3, \arg1
150 mulpadd 4, \arg1
151 mulpadd 5, \arg1
152 mulpadd 6, \arg1
153 mulpade 7, \arg1
154
155.if (\arg1 % 8 == 0)
156 adc r8, zero
157.elseif (\arg1 % 8 == 1)
158 adc r9, zero
159.elseif (\arg1 % 8 == 2)
160 adc r10, zero
161.elseif (\arg1 % 8 == 3)
162 adc r11, zero
163.elseif (\arg1 % 8 == 4)
164 adc r12, zero
165.elseif (\arg1 % 8 == 5)
166 adc r13, zero
167.elseif (\arg1 % 8 == 6)
168 adc r14, zero
169.elseif (\arg1 % 8 == 7)
170 adc r15, zero
171.endif
172
173.endm
174
175
176S2N_BN_SYMBOL(bignum_mul_8_16):
177 _CET_ENDBR
178
179#if WINDOWS_ABI
180 push rdi
181 push rsi
182 mov rdi, rcx
183 mov rsi, rdx
184 mov rdx, r8
185#endif
186
187// Save more registers to play with
188
189 push rbp
190 push rbx
191 push r12
192 push r13
193 push r14
194 push r15
195
196// Copy y into a safe register to start with
197
198 mov y, rdx
199
200// Zero a register, which also makes sure we don't get a fake carry-in
201
202 xor zeroe, zeroe
203
204// Do the zeroth row, which is a bit different
205// Write back the zero-zero product and then accumulate
206// r8,r15,r14,r13,r12,r11,r10,r9 as y[0] * x from 1..8
207
208 mov rdx, [y]
209
210 mulx r9, r8, [x]
211 mov [z], r8
212
213 mulx r10, rbx, [x+8]
214 adc r9, rbx
215
216 mulx r11, rbx, [x+16]
217 adc r10, rbx
218
219 mulx r12, rbx, [x+24]
220 adc r11, rbx
221
222 mulx r13, rbx, [x+32]
223 adc r12, rbx
224
225 mulx r14, rbx, [x+40]
226 adc r13, rbx
227
228 mulx r15, rbx, [x+48]
229 adc r14, rbx
230
231 mulx r8, rbx, [x+56]
232 adc r15, rbx
233 adc r8, zero
234
235// Now all the other rows in a uniform pattern
236
237 addrow 1
238 addrow 2
239 addrow 3
240 addrow 4
241 addrow 5
242 addrow 6
243 addrow 7
244
245// Now write back the additional columns
246
247 mov [z+64], r8
248 mov [z+72], r9
249 mov [z+80], r10
250 mov [z+88], r11
251 mov [z+96], r12
252 mov [z+104], r13
253 mov [z+112], r14
254 mov [z+120], r15
255
256// Real epilog
257
258 pop r15
259 pop r14
260 pop r13
261 pop r12
262 pop rbx
263 pop rbp
264
265#if WINDOWS_ABI
266 pop rsi
267 pop rdi
268#endif
269 ret
270
271#if defined(__linux__) && defined(__ELF__)
272.section .note.GNU-stack,"",%progbits
273#endif
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_mul_8_16_alt.S b/src/lib/libcrypto/bn/arch/amd64/bignum_mul_8_16_alt.S
index 066403b074..0e30b9170f 100644
--- a/src/lib/libcrypto/bn/arch/amd64/bignum_mul_8_16_alt.S
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_mul_8_16_alt.S
@@ -1,3 +1,5 @@
1// $OpenBSD: bignum_mul_8_16_alt.S,v 1.7 2025/08/11 14:13:56 jsing Exp $
2//
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// 4//
3// Permission to use, copy, modify, and/or distribute this software for any 5// Permission to use, copy, modify, and/or distribute this software for any
@@ -16,8 +18,9 @@
16// Multiply z := x * y 18// Multiply z := x * y
17// Inputs x[8], y[8]; output z[16] 19// Inputs x[8], y[8]; output z[16]
18// 20//
19// extern void bignum_mul_8_16_alt 21// extern void bignum_mul_8_16_alt(uint64_t z[static 16],
20// (uint64_t z[static 16], uint64_t x[static 8], uint64_t y[static 8]); 22// const uint64_t x[static 8],
23// const uint64_t y[static 8]);
21// 24//
22// Standard x86-64 ABI: RDI = z, RSI = x, RDX = y 25// Standard x86-64 ABI: RDI = z, RSI = x, RDX = y
23// Microsoft x64 ABI: RCX = z, RDX = x, R8 = y 26// Microsoft x64 ABI: RCX = z, RDX = x, R8 = y
@@ -72,7 +75,7 @@
72 adc h, rdx 75 adc h, rdx
73 76
74S2N_BN_SYMBOL(bignum_mul_8_16_alt): 77S2N_BN_SYMBOL(bignum_mul_8_16_alt):
75 _CET_ENDBR 78 _CET_ENDBR
76 79
77#if WINDOWS_ABI 80#if WINDOWS_ABI
78 push rdi 81 push rdi
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_sqr.S b/src/lib/libcrypto/bn/arch/amd64/bignum_sqr.S
index 54e3f59442..86f1af2ac4 100644
--- a/src/lib/libcrypto/bn/arch/amd64/bignum_sqr.S
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_sqr.S
@@ -1,3 +1,5 @@
1// $OpenBSD: bignum_sqr.S,v 1.7 2025/08/11 14:13:56 jsing Exp $
2//
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// 4//
3// Permission to use, copy, modify, and/or distribute this software for any 5// Permission to use, copy, modify, and/or distribute this software for any
@@ -16,8 +18,7 @@
16// Square z := x^2 18// Square z := x^2
17// Input x[n]; output z[k] 19// Input x[n]; output z[k]
18// 20//
19// extern void bignum_sqr 21// extern void bignum_sqr(uint64_t k, uint64_t *z, uint64_t n, const uint64_t *x);
20// (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x);
21// 22//
22// Does the "z := x^2" operation where x is n digits and result z is k. 23// Does the "z := x^2" operation where x is n digits and result z is k.
23// Truncates the result in general unless k >= 2 * n 24// Truncates the result in general unless k >= 2 * n
@@ -62,7 +63,7 @@
62#define llshort ebp 63#define llshort ebp
63 64
64S2N_BN_SYMBOL(bignum_sqr): 65S2N_BN_SYMBOL(bignum_sqr):
65 _CET_ENDBR 66 _CET_ENDBR
66 67
67#if WINDOWS_ABI 68#if WINDOWS_ABI
68 push rdi 69 push rdi
@@ -86,7 +87,7 @@ S2N_BN_SYMBOL(bignum_sqr):
86// If p = 0 the result is trivial and nothing needs doing 87// If p = 0 the result is trivial and nothing needs doing
87 88
88 test p, p 89 test p, p
89 jz end 90 jz bignum_sqr_end
90 91
91// initialize (hh,ll) = 0 92// initialize (hh,ll) = 0
92 93
@@ -97,7 +98,7 @@ S2N_BN_SYMBOL(bignum_sqr):
97 98
98 xor k, k 99 xor k, k
99 100
100outerloop: 101bignum_sqr_outerloop:
101 102
102// First let bot = MAX 0 (k + 1 - n) and top = MIN (k + 1) n 103// First let bot = MAX 0 (k + 1 - n) and top = MIN (k + 1) n
103// We want to accumulate all x[i] * x[k - i] for bot <= i < top 104// We want to accumulate all x[i] * x[k - i] for bot <= i < top
@@ -122,7 +123,7 @@ outerloop:
122// If htop <= bot then main doubled part of the sum is empty 123// If htop <= bot then main doubled part of the sum is empty
123 124
124 cmp i, htop 125 cmp i, htop
125 jnc nosumming 126 jnc bignum_sqr_nosumming
126 127
127// Use a moving pointer for [y] = x[k-i] for the cofactor 128// Use a moving pointer for [y] = x[k-i] for the cofactor
128 129
@@ -132,7 +133,7 @@ outerloop:
132 133
133// Do the main part of the sum x[i] * x[k - i] for 2 * i < k 134// Do the main part of the sum x[i] * x[k - i] for 2 * i < k
134 135
135innerloop: 136bignum_sqr_innerloop:
136 mov a, [x+8*i] 137 mov a, [x+8*i]
137 mul QWORD PTR [y] 138 mul QWORD PTR [y]
138 add l, a 139 add l, a
@@ -141,7 +142,7 @@ innerloop:
141 sub y, 8 142 sub y, 8
142 inc i 143 inc i
143 cmp i, htop 144 cmp i, htop
144 jc innerloop 145 jc bignum_sqr_innerloop
145 146
146// Now double it 147// Now double it
147 148
@@ -151,11 +152,11 @@ innerloop:
151 152
152// If k is even (which means 2 * i = k) and i < n add the extra x[i]^2 term 153// If k is even (which means 2 * i = k) and i < n add the extra x[i]^2 term
153 154
154nosumming: 155bignum_sqr_nosumming:
155 test k, 1 156 test k, 1
156 jnz innerend 157 jnz bignum_sqr_innerend
157 cmp i, n 158 cmp i, n
158 jnc innerend 159 jnc bignum_sqr_innerend
159 160
160 mov a, [x+8*i] 161 mov a, [x+8*i]
161 mul a 162 mul a
@@ -165,7 +166,7 @@ nosumming:
165 166
166// Now add the local sum into the global sum, store and shift 167// Now add the local sum into the global sum, store and shift
167 168
168innerend: 169bignum_sqr_innerend:
169 add l, ll 170 add l, ll
170 mov [z+8*k], l 171 mov [z+8*k], l
171 adc h, hh 172 adc h, hh
@@ -175,11 +176,11 @@ innerend:
175 176
176 inc k 177 inc k
177 cmp k, p 178 cmp k, p
178 jc outerloop 179 jc bignum_sqr_outerloop
179 180
180// Restore registers and return 181// Restore registers and return
181 182
182end: 183bignum_sqr_end:
183 pop r15 184 pop r15
184 pop r14 185 pop r14
185 pop r13 186 pop r13
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_4_8.S b/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_4_8.S
new file mode 100644
index 0000000000..25664782f7
--- /dev/null
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_4_8.S
@@ -0,0 +1,158 @@
1// $OpenBSD: bignum_sqr_4_8.S,v 1.4 2025/08/12 10:23:40 jsing Exp $
2//
3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4//
5// Permission to use, copy, modify, and/or distribute this software for any
6// purpose with or without fee is hereby granted, provided that the above
7// copyright notice and this permission notice appear in all copies.
8//
9// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17// ----------------------------------------------------------------------------
18// Square, z := x^2
19// Input x[4]; output z[8]
20//
21// extern void bignum_sqr_4_8(uint64_t z[static 8], const uint64_t x[static 4]);
22//
23// Standard x86-64 ABI: RDI = z, RSI = x
24// Microsoft x64 ABI: RCX = z, RDX = x
25// ----------------------------------------------------------------------------
26
27#include "s2n_bignum_internal.h"
28
29 .intel_syntax noprefix
30 S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sqr_4_8)
31 S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sqr_4_8)
32 .text
33
34// These are actually right
35
36#define z rdi
37#define x rsi
38
39// A zero register
40
41#define zero rbp
42#define zeroe ebp
43
44// Other registers
45
46#define d1 r8
47#define d2 r9
48#define d3 r10
49#define d4 r11
50#define d5 r12
51#define d6 r13
52
53
54
55S2N_BN_SYMBOL(bignum_sqr_4_8):
56 _CET_ENDBR
57
58#if WINDOWS_ABI
59 push rdi
60 push rsi
61 mov rdi, rcx
62 mov rsi, rdx
63#endif
64
65// Save more registers to play with
66
67 push rbp
68 push r12
69 push r13
70
71// Set up an initial window [d6;...d1] = [23;03;01]
72
73 mov rdx, [x]
74 mulx d2, d1, [x+8]
75 mulx d4, d3, [x+24]
76 mov rdx, [x+16]
77 mulx d6, d5, [x+24]
78
79// Clear our zero register, and also initialize the flags for the carry chain
80
81 xor zeroe, zeroe
82
83// Chain in the addition of 02 + 12 + 13 to that window (no carry-out possible)
84// This gives all the "heterogeneous" terms of the squaring ready to double
85
86 mulx rcx, rax, [x]
87 adcx d2, rax
88 adox d3, rcx
89 mulx rcx, rax, [x+8]
90 adcx d3, rax
91 adox d4, rcx
92 mov rdx, [x+24]
93 mulx rcx, rax, [x+8]
94 adcx d4, rax
95 adox d5, rcx
96 adcx d5, zero
97 adox d6, zero
98 adcx d6, zero
99
100// In principle this is otiose as CF and OF carries are absorbed at this point
101// However it seems helpful for the OOO engine to be told it's a fresh start
102
103 xor zeroe, zeroe
104
105// Double and add to the 00 + 11 + 22 + 33 terms
106//
107// We could use shift-double but this seems tidier and in larger squarings
108// it was actually more efficient. I haven't experimented with this small
109// case to see how much that matters. Note: the writeback here is sprinkled
110// into the sequence in such a way that things still work if z = x, i.e. if
111// the output overwrites the input buffer and beyond.
112
113 mov rdx, [x]
114 mulx rdx, rax, rdx
115 mov [z], rax
116 adcx d1, d1
117 adox d1, rdx
118 mov rdx, [x+8]
119 mov [z+8], d1
120 mulx rdx, rax, rdx
121 adcx d2, d2
122 adox d2, rax
123 adcx d3, d3
124 adox d3, rdx
125 mov rdx, [x+16]
126 mov [z+16], d2
127 mulx rdx, rax, rdx
128 adcx d4, d4
129 adox d4, rax
130 adcx d5, d5
131 adox d5, rdx
132 mov rdx, [x+24]
133 mov [z+24], d3
134 mulx rdx, rax, rdx
135 mov [z+32], d4
136 adcx d6, d6
137 mov [z+40], d5
138 adox d6, rax
139 mov [z+48], d6
140 adcx rdx, zero
141 adox rdx, zero
142 mov [z+56], rdx
143
144// Restore saved registers and return
145
146 pop r13
147 pop r12
148 pop rbp
149
150#if WINDOWS_ABI
151 pop rsi
152 pop rdi
153#endif
154 ret
155
156#if defined(__linux__) && defined(__ELF__)
157.section .note.GNU-stack,"",%progbits
158#endif
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_4_8_alt.S b/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_4_8_alt.S
index 7c534ae907..7eafac3284 100644
--- a/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_4_8_alt.S
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_4_8_alt.S
@@ -1,3 +1,5 @@
1// $OpenBSD: bignum_sqr_4_8_alt.S,v 1.7 2025/08/11 14:13:56 jsing Exp $
2//
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// 4//
3// Permission to use, copy, modify, and/or distribute this software for any 5// Permission to use, copy, modify, and/or distribute this software for any
@@ -16,8 +18,8 @@
16// Square, z := x^2 18// Square, z := x^2
17// Input x[4]; output z[8] 19// Input x[4]; output z[8]
18// 20//
19// extern void bignum_sqr_4_8_alt 21// extern void bignum_sqr_4_8_alt(uint64_t z[static 8],
20// (uint64_t z[static 8], uint64_t x[static 4]); 22// const uint64_t x[static 4]);
21// 23//
22// Standard x86-64 ABI: RDI = z, RSI = x 24// Standard x86-64 ABI: RDI = z, RSI = x
23// Microsoft x64 ABI: RCX = z, RDX = x 25// Microsoft x64 ABI: RCX = z, RDX = x
@@ -71,7 +73,7 @@
71 adc c, 0 73 adc c, 0
72 74
73S2N_BN_SYMBOL(bignum_sqr_4_8_alt): 75S2N_BN_SYMBOL(bignum_sqr_4_8_alt):
74 _CET_ENDBR 76 _CET_ENDBR
75 77
76#if WINDOWS_ABI 78#if WINDOWS_ABI
77 push rdi 79 push rdi
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_6_12.S b/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_6_12.S
new file mode 100644
index 0000000000..3f055e8b75
--- /dev/null
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_6_12.S
@@ -0,0 +1,227 @@
1// $OpenBSD: bignum_sqr_6_12.S,v 1.4 2025/08/12 10:23:40 jsing Exp $
2//
3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4//
5// Permission to use, copy, modify, and/or distribute this software for any
6// purpose with or without fee is hereby granted, provided that the above
7// copyright notice and this permission notice appear in all copies.
8//
9// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17// ----------------------------------------------------------------------------
18// Square, z := x^2
19// Input x[6]; output z[12]
20//
21// extern void bignum_sqr_6_12(uint64_t z[static 12], const uint64_t x[static 6]);
22//
23// Standard x86-64 ABI: RDI = z, RSI = x
24// Microsoft x64 ABI: RCX = z, RDX = x
25// ----------------------------------------------------------------------------
26
27#include "s2n_bignum_internal.h"
28
29 .intel_syntax noprefix
30 S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sqr_6_12)
31 S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sqr_6_12)
32 .text
33
34// These are actually right
35
36#define z rdi
37#define x rsi
38
39// A zero register
40
41#define zero rbp
42#define zeroe ebp
43
44// Other registers
45
46#define d1 r8
47#define d2 r9
48#define d3 r10
49#define d4 r11
50#define d5 r12
51#define d6 r13
52#define d7 r14
53#define d8 r15
54#define d9 rbx
55
56// Care is needed: re-using the zero register
57
58#define d10 rbp
59
60
61S2N_BN_SYMBOL(bignum_sqr_6_12):
62 _CET_ENDBR
63
64#if WINDOWS_ABI
65 push rdi
66 push rsi
67 mov rdi, rcx
68 mov rsi, rdx
69#endif
70
71// Save more registers to play with
72
73 push rbp
74 push rbx
75 push r12
76 push r13
77 push r14
78 push r15
79
80// Set up an initial window [d8;...d1] = [34;05;03;01]
81
82 mov rdx, [x]
83 mulx d2, d1, [x+8]
84 mulx d4, d3, [x+24]
85 mulx d6, d5, [x+40]
86 mov rdx, [x+24]
87 mulx d8, d7, [x+32]
88
89// Clear our zero register, and also initialize the flags for the carry chain
90
91 xor zeroe, zeroe
92
93// Chain in the addition of 02 + 12 + 13 + 14 + 15 to that window
94// (no carry-out possible since we add it to the top of a product)
95
96 mov rdx, [x+16]
97 mulx rcx, rax, [x]
98 adcx d2, rax
99 adox d3, rcx
100 mulx rcx, rax, [x+8]
101 adcx d3, rax
102 adox d4, rcx
103 mov rdx, [x+8]
104 mulx rcx, rax, [x+24]
105 adcx d4, rax
106 adox d5, rcx
107 mulx rcx, rax, [x+32]
108 adcx d5, rax
109 adox d6, rcx
110 mulx rcx, rax, [x+40]
111 adcx d6, rax
112 adox d7, rcx
113 adcx d7, zero
114 adox d8, zero
115 adcx d8, zero
116
117// Again zero out the flags. Actually they are already cleared but it may
118// help decouple these in the OOO engine not to wait for the chain above
119
120 xor zeroe, zeroe
121
122// Now chain in the 04 + 23 + 24 + 25 + 35 + 45 terms
123// We are running out of registers and here our zero register is not zero!
124
125 mov rdx, [x+32]
126 mulx rcx, rax, [x]
127 adcx d4, rax
128 adox d5, rcx
129 mov rdx, [x+16]
130 mulx rcx, rax, [x+24]
131 adcx d5, rax
132 adox d6, rcx
133 mulx rcx, rax, [x+32]
134 adcx d6, rax
135 adox d7, rcx
136 mulx rcx, rax, [x+40]
137 adcx d7, rax
138 adox d8, rcx
139 mov rdx, [x+24]
140 mulx d9, rax, [x+40]
141 adcx d8, rax
142 adox d9, zero
143 mov rdx, [x+32]
144 mulx d10, rax, [x+40]
145 adcx d9, rax
146 mov eax, 0
147 adox d10, rax
148 adcx d10, rax
149
150// Again, just for a clear fresh start for the flags
151
152 xor eax, eax
153
154// Double and add to the 00 + 11 + 22 + 33 + 44 + 55 terms
155//
156// We could use shift-double but this seems tidier and in larger squarings
157// it was actually more efficient. I haven't experimented with this small
158// case to see how much that matters. Note: the writeback here is sprinkled
159// into the sequence in such a way that things still work if z = x, i.e. if
160// the output overwrites the input buffer and beyond.
161
162 mov rdx, [x]
163 mulx rdx, rax, rdx
164 mov [z], rax
165 adcx d1, d1
166 adox d1, rdx
167 mov rdx, [x+8]
168 mov [z+8], d1
169 mulx rdx, rax, rdx
170 adcx d2, d2
171 adox d2, rax
172 adcx d3, d3
173 adox d3, rdx
174 mov rdx, [x+16]
175 mov [z+16], d2
176 mulx rdx, rax, rdx
177 adcx d4, d4
178 adox d4, rax
179 adcx d5, d5
180 adox d5, rdx
181 mov rdx, [x+24]
182 mov [z+24], d3
183 mulx rdx, rax, rdx
184 adcx d6, d6
185 adox d6, rax
186 adcx d7, d7
187 adox d7, rdx
188 mov rdx, [x+32]
189 mov [z+32], d4
190 mulx rdx, rax, rdx
191 adcx d8, d8
192 adox d8, rax
193 adcx d9, d9
194 adox d9, rdx
195 mov rdx, [x+40]
196 mov [z+40], d5
197 mulx rdx, rax, rdx
198 mov [z+48], d6
199 adcx d10, d10
200 mov [z+56], d7
201 adox d10, rax
202 mov [z+64], d8
203 mov eax, 0
204 mov [z+72], d9
205 adcx rdx, rax
206 mov [z+80], d10
207 adox rdx, rax
208 mov [z+88], rdx
209
210// Restore saved registers and return
211
212 pop r15
213 pop r14
214 pop r13
215 pop r12
216 pop rbx
217 pop rbp
218
219#if WINDOWS_ABI
220 pop rsi
221 pop rdi
222#endif
223 ret
224
225#if defined(__linux__) && defined(__ELF__)
226.section .note.GNU-stack,"",%progbits
227#endif
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_6_12_alt.S b/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_6_12_alt.S
new file mode 100644
index 0000000000..eb43b0a15b
--- /dev/null
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_6_12_alt.S
@@ -0,0 +1,210 @@
1// $OpenBSD: bignum_sqr_6_12_alt.S,v 1.4 2025/08/12 10:23:40 jsing Exp $
2//
3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4//
5// Permission to use, copy, modify, and/or distribute this software for any
6// purpose with or without fee is hereby granted, provided that the above
7// copyright notice and this permission notice appear in all copies.
8//
9// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17// ----------------------------------------------------------------------------
18// Square, z := x^2
19// Input x[6]; output z[12]
20//
21// extern void bignum_sqr_6_12_alt(uint64_t z[static 12],
22// const uint64_t x[static 6]);
23//
24// Standard x86-64 ABI: RDI = z, RSI = x
25// Microsoft x64 ABI: RCX = z, RDX = x
26// ----------------------------------------------------------------------------
27
28#include "s2n_bignum_internal.h"
29
30 .intel_syntax noprefix
31 S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sqr_6_12_alt)
32 S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sqr_6_12_alt)
33 .text
34
35// Input arguments
36
37#define z rdi
38#define x rsi
39
40// Other variables used as a rotating 3-word window to add terms to
41
42#define t0 r8
43#define t1 r9
44#define t2 r10
45
46// Additional temporaries for local windows to share doublings
47
48#define u0 rcx
49#define u1 r11
50
51// Macro for the key "multiply and add to (c,h,l)" step
52
53#define combadd(c,h,l,numa,numb) \
54 mov rax, numa; \
55 mul QWORD PTR numb; \
56 add l, rax; \
57 adc h, rdx; \
58 adc c, 0
59
60// Set up initial window (c,h,l) = numa * numb
61
62#define combaddz(c,h,l,numa,numb) \
63 mov rax, numa; \
64 mul QWORD PTR numb; \
65 xor c, c; \
66 mov l, rax; \
67 mov h, rdx
68
69// Doubling step (c,h,l) = 2 * (c,hh,ll) + (0,h,l)
70
71#define doubladd(c,h,l,hh,ll) \
72 add ll, ll; \
73 adc hh, hh; \
74 adc c, c; \
75 add l, ll; \
76 adc h, hh; \
77 adc c, 0
78
79// Square term incorporation (c,h,l) += numba^2
80
81#define combadd1(c,h,l,numa) \
82 mov rax, numa; \
83 mul rax; \
84 add l, rax; \
85 adc h, rdx; \
86 adc c, 0
87
88// A short form where we don't expect a top carry
89
90#define combads(h,l,numa) \
91 mov rax, numa; \
92 mul rax; \
93 add l, rax; \
94 adc h, rdx
95
96// A version doubling directly before adding, for single non-square terms
97
98#define combadd2(c,h,l,numa,numb) \
99 mov rax, numa; \
100 mul QWORD PTR numb; \
101 add rax, rax; \
102 adc rdx, rdx; \
103 adc c, 0; \
104 add l, rax; \
105 adc h, rdx; \
106 adc c, 0
107
108S2N_BN_SYMBOL(bignum_sqr_6_12_alt):
109 _CET_ENDBR
110
111#if WINDOWS_ABI
112 push rdi
113 push rsi
114 mov rdi, rcx
115 mov rsi, rdx
116#endif
117
118// Result term 0
119
120 mov rax, [x]
121 mul rax
122
123 mov [z], rax
124 mov t0, rdx
125 xor t1, t1
126
127// Result term 1
128
129 xor t2, t2
130 combadd2(t2,t1,t0,[x],[x+8])
131 mov [z+8], t0
132
133// Result term 2
134
135 xor t0, t0
136 combadd1(t0,t2,t1,[x+8])
137 combadd2(t0,t2,t1,[x],[x+16])
138 mov [z+16], t1
139
140// Result term 3
141
142 combaddz(t1,u1,u0,[x],[x+24])
143 combadd(t1,u1,u0,[x+8],[x+16])
144 doubladd(t1,t0,t2,u1,u0)
145 mov [z+24], t2
146
147// Result term 4
148
149 combaddz(t2,u1,u0,[x],[x+32])
150 combadd(t2,u1,u0,[x+8],[x+24])
151 doubladd(t2,t1,t0,u1,u0)
152 combadd1(t2,t1,t0,[x+16])
153 mov [z+32], t0
154
155// Result term 5
156
157 combaddz(t0,u1,u0,[x],[x+40])
158 combadd(t0,u1,u0,[x+8],[x+32])
159 combadd(t0,u1,u0,[x+16],[x+24])
160 doubladd(t0,t2,t1,u1,u0)
161 mov [z+40], t1
162
163// Result term 6
164
165 combaddz(t1,u1,u0,[x+8],[x+40])
166 combadd(t1,u1,u0,[x+16],[x+32])
167 doubladd(t1,t0,t2,u1,u0)
168 combadd1(t1,t0,t2,[x+24])
169 mov [z+48], t2
170
171// Result term 7
172
173 combaddz(t2,u1,u0,[x+16],[x+40])
174 combadd(t2,u1,u0,[x+24],[x+32])
175 doubladd(t2,t1,t0,u1,u0)
176 mov [z+56], t0
177
178// Result term 8
179
180 xor t0, t0
181 combadd2(t0,t2,t1,[x+24],[x+40])
182 combadd1(t0,t2,t1,[x+32])
183 mov [z+64], t1
184
185// Result term 9
186
187 xor t1, t1
188 combadd2(t1,t0,t2,[x+32],[x+40])
189 mov [z+72], t2
190
191// Result term 10
192
193 combads(t1,t0,[x+40])
194 mov [z+80], t0
195
196// Result term 11
197
198 mov [z+88], t1
199
200// Return
201
202#if WINDOWS_ABI
203 pop rsi
204 pop rdi
205#endif
206 ret
207
208#if defined(__linux__) && defined(__ELF__)
209.section .note.GNU-stack,"",%progbits
210#endif
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_8_16.S b/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_8_16.S
new file mode 100644
index 0000000000..41277b5b6a
--- /dev/null
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_8_16.S
@@ -0,0 +1,311 @@
1// $OpenBSD: bignum_sqr_8_16.S,v 1.4 2025/08/12 10:23:40 jsing Exp $
2//
3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4//
5// Permission to use, copy, modify, and/or distribute this software for any
6// purpose with or without fee is hereby granted, provided that the above
7// copyright notice and this permission notice appear in all copies.
8//
9// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17// ----------------------------------------------------------------------------
18// Square, z := x^2
19// Input x[8]; output z[16]
20//
21// extern void bignum_sqr_8_16(uint64_t z[static 16], const uint64_t x[static 8]);
22//
23// Standard x86-64 ABI: RDI = z, RSI = x
24// Microsoft x64 ABI: RCX = z, RDX = x
25// ----------------------------------------------------------------------------
26
27#include "s2n_bignum_internal.h"
28
29 .intel_syntax noprefix
30 S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sqr_8_16)
31 S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sqr_8_16)
32 .text
33
34// These are actually right
35
36#define z rdi
37#define x rsi
38
39// A zero register
40
41#define zero rbp
42#define zeroe ebp
43
44// mulpadd i, j adds rdx * x[i] into the window at the i+j point
45
46.macro mulpadd arg1,arg2
47 mulx rcx, rax, [x+8*\arg1]
48.if ((\arg1 + \arg2) % 8 == 0)
49 adcx r8, rax
50 adox r9, rcx
51.elseif ((\arg1 + \arg2) % 8 == 1)
52 adcx r9, rax
53 adox r10, rcx
54.elseif ((\arg1 + \arg2) % 8 == 2)
55 adcx r10, rax
56 adox r11, rcx
57.elseif ((\arg1 + \arg2) % 8 == 3)
58 adcx r11, rax
59 adox r12, rcx
60.elseif ((\arg1 + \arg2) % 8 == 4)
61 adcx r12, rax
62 adox r13, rcx
63.elseif ((\arg1 + \arg2) % 8 == 5)
64 adcx r13, rax
65 adox r14, rcx
66.elseif ((\arg1 + \arg2) % 8 == 6)
67 adcx r14, rax
68 adox r15, rcx
69.elseif ((\arg1 + \arg2) % 8 == 7)
70 adcx r15, rax
71 adox r8, rcx
72.endif
73
74.endm
75
76// mulpade i, j adds rdx * x[i] into the window at i+j
77// but re-creates the top word assuming nothing to add there
78
79.macro mulpade arg1,arg2
80.if ((\arg1 + \arg2) % 8 == 0)
81 mulx r9, rax, [x+8*\arg1]
82 adcx r8, rax
83 adox r9, zero
84.elseif ((\arg1 + \arg2) % 8 == 1)
85 mulx r10, rax, [x+8*\arg1]
86 adcx r9, rax
87 adox r10, zero
88.elseif ((\arg1 + \arg2) % 8 == 2)
89 mulx r11, rax, [x+8*\arg1]
90 adcx r10, rax
91 adox r11, zero
92.elseif ((\arg1 + \arg2) % 8 == 3)
93 mulx r12, rax, [x+8*\arg1]
94 adcx r11, rax
95 adox r12, zero
96.elseif ((\arg1 + \arg2) % 8 == 4)
97 mulx r13, rax, [x+8*\arg1]
98 adcx r12, rax
99 adox r13, zero
100.elseif ((\arg1 + \arg2) % 8 == 5)
101 mulx r14, rax, [x+8*\arg1]
102 adcx r13, rax
103 adox r14, zero
104.elseif ((\arg1 + \arg2) % 8 == 6)
105 mulx r15, rax, [x+8*\arg1]
106 adcx r14, rax
107 adox r15, zero
108.elseif ((\arg1 + \arg2) % 8 == 7)
109 mulx r8, rax, [x+8*\arg1]
110 adcx r15, rax
111 adox r8, zero
112.endif
113
114.endm
115
116.macro diagonals
117
118 xor zeroe, zeroe
119
120// Set initial window [r8..r10] + 2 wb = 10 + 20 + 30 + 40 + 50 + 60 + 70
121
122 mov rdx, [x]
123 mulx rax, r9, [x+8]
124 mov [z+8], r9
125 mulx rcx, r10, [x+16]
126 adcx r10, rax
127 mov [z+16], r10
128 mulx rax, r11, [x+24]
129 adcx r11, rcx
130 mulx rcx, r12, [x+32]
131 adcx r12, rax
132 mulx rax, r13, [x+40]
133 adcx r13, rcx
134 mulx rcx, r14, [x+48]
135 adcx r14, rax
136 mulx r8, r15, [x+56]
137 adcx r15, rcx
138 adcx r8, zero
139
140// Add in the next diagonal = 21 + 31 + 41 + 51 + 61 + 71 + 54
141
142 xor zeroe, zeroe
143 mov rdx, [x+8]
144 mulpadd 2, 1
145 mov [z+24], r11
146 mulpadd 3, 1
147 mov [z+32], r12
148 mulpadd 4, 1
149 mulpadd 5, 1
150 mulpadd 6, 1
151 mulpade 7, 1
152 mov rdx, [x+32]
153 mulpade 5, 4
154 adcx r10, zero
155
156// And the next one = 32 + 42 + 52 + 62 + 72 + 64 + 65
157
158 xor zeroe, zeroe
159 mov rdx, [x+16]
160 mulpadd 3, 2
161 mov [z+40], r13
162 mulpadd 4, 2
163 mov [z+48], r14
164 mulpadd 5, 2
165 mulpadd 6, 2
166 mulpadd 7, 2
167 mov rdx, [x+48]
168 mulpade 4, 6
169 mulpade 5, 6
170 adcx r12, zero
171
172// And the final one = 43 + 53 + 63 + 73 + 74 + 75 + 76
173
174 xor zeroe, zeroe
175 mov rdx, [x+24]
176 mulpadd 4, 3
177 mov [z+56], r15
178 mulpadd 5, 3
179 mov [z+64], r8
180 mulpadd 6, 3
181 mulpadd 7, 3
182 mov rdx, [x+56]
183 mulpadd 4, 7
184 mulpade 5, 7
185 mulpade 6, 7
186 adcx r14, zero
187
188// Double and add things; use z[1]..z[8] and thereafter the registers
189// r9..r15 which haven't been written back yet
190
191 xor zeroe, zeroe
192 mov rdx, [x]
193 mulx rcx, rax, rdx
194 mov [z], rax
195 mov rax, [z+8]
196 adcx rax, rax
197 adox rax, rcx
198 mov [z+8], rax
199
200 mov rax, [z+16]
201 mov rdx, [x+8]
202 mulx rcx, rdx, rdx
203 adcx rax, rax
204 adox rax, rdx
205 mov [z+16], rax
206 mov rax, [z+24]
207 adcx rax, rax
208 adox rax, rcx
209 mov [z+24], rax
210
211 mov rax, [z+32]
212 mov rdx, [x+16]
213 mulx rcx, rdx, rdx
214 adcx rax, rax
215 adox rax, rdx
216 mov [z+32], rax
217 mov rax, [z+40]
218 adcx rax, rax
219 adox rax, rcx
220 mov [z+40], rax
221
222 mov rax, [z+48]
223 mov rdx, [x+24]
224 mulx rcx, rdx, rdx
225 adcx rax, rax
226 adox rax, rdx
227 mov [z+48], rax
228 mov rax, [z+56]
229 adcx rax, rax
230 adox rax, rcx
231 mov [z+56], rax
232
233 mov rax, [z+64]
234 mov rdx, [x+32]
235 mulx rcx, rdx, rdx
236 adcx rax, rax
237 adox rax, rdx
238 mov [z+64], rax
239 adcx r9, r9
240 adox r9, rcx
241 mov [z+72], r9
242
243 mov rdx, [x+40]
244 mulx rcx, rdx, rdx
245 adcx r10, r10
246 adox r10, rdx
247 mov [z+80], r10
248 adcx r11, r11
249 adox r11, rcx
250 mov [z+88], r11
251
252 mov rdx, [x+48]
253 mulx rcx, rdx, rdx
254 adcx r12, r12
255 adox r12, rdx
256 mov [z+96], r12
257 adcx r13, r13
258 adox r13, rcx
259 mov [z+104], r13
260
261 mov rdx, [x+56]
262 mulx r15, rdx, rdx
263 adcx r14, r14
264 adox r14, rdx
265 mov [z+112], r14
266 adcx r15, zero
267 adox r15, zero
268 mov [z+120], r15
269
270.endm
271
272
273S2N_BN_SYMBOL(bignum_sqr_8_16):
274 _CET_ENDBR
275
276#if WINDOWS_ABI
277 push rdi
278 push rsi
279 mov rdi, rcx
280 mov rsi, rdx
281#endif
282
283// Save more registers to play with
284
285 push rbp
286 push r12
287 push r13
288 push r14
289 push r15
290
291// Do the multiplication
292
293 diagonals
294
295// Real epilog
296
297 pop r15
298 pop r14
299 pop r13
300 pop r12
301 pop rbp
302
303#if WINDOWS_ABI
304 pop rsi
305 pop rdi
306#endif
307 ret
308
309#if defined(__linux__) && defined(__ELF__)
310.section .note.GNU-stack,"",%progbits
311#endif
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_8_16_alt.S b/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_8_16_alt.S
index ac0b6f96c2..cb10ba2a12 100644
--- a/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_8_16_alt.S
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_sqr_8_16_alt.S
@@ -1,3 +1,5 @@
1// $OpenBSD: bignum_sqr_8_16_alt.S,v 1.7 2025/08/11 14:13:56 jsing Exp $
2//
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// 4//
3// Permission to use, copy, modify, and/or distribute this software for any 5// Permission to use, copy, modify, and/or distribute this software for any
@@ -16,7 +18,8 @@
16// Square, z := x^2 18// Square, z := x^2
17// Input x[8]; output z[16] 19// Input x[8]; output z[16]
18// 20//
19// extern void bignum_sqr_8_16_alt (uint64_t z[static 16], uint64_t x[static 8]); 21// extern void bignum_sqr_8_16_alt(uint64_t z[static 16],
22// const uint64_t x[static 8]);
20// 23//
21// Standard x86-64 ABI: RDI = z, RSI = x 24// Standard x86-64 ABI: RDI = z, RSI = x
22// Microsoft x64 ABI: RCX = z, RDX = x 25// Microsoft x64 ABI: RCX = z, RDX = x
@@ -103,7 +106,7 @@
103 adc c, 0 106 adc c, 0
104 107
105S2N_BN_SYMBOL(bignum_sqr_8_16_alt): 108S2N_BN_SYMBOL(bignum_sqr_8_16_alt):
106 _CET_ENDBR 109 _CET_ENDBR
107 110
108#if WINDOWS_ABI 111#if WINDOWS_ABI
109 push rdi 112 push rdi
diff --git a/src/lib/libcrypto/bn/arch/amd64/bignum_sub.S b/src/lib/libcrypto/bn/arch/amd64/bignum_sub.S
index 3ff8a30510..7324d3a71e 100644
--- a/src/lib/libcrypto/bn/arch/amd64/bignum_sub.S
+++ b/src/lib/libcrypto/bn/arch/amd64/bignum_sub.S
@@ -1,3 +1,5 @@
1// $OpenBSD: bignum_sub.S,v 1.7 2025/08/11 14:13:56 jsing Exp $
2//
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// 4//
3// Permission to use, copy, modify, and/or distribute this software for any 5// Permission to use, copy, modify, and/or distribute this software for any
@@ -16,9 +18,8 @@
16// Subtract, z := x - y 18// Subtract, z := x - y
17// Inputs x[m], y[n]; outputs function return (carry-out) and z[p] 19// Inputs x[m], y[n]; outputs function return (carry-out) and z[p]
18// 20//
19// extern uint64_t bignum_sub 21// extern uint64_t bignum_sub(uint64_t p, uint64_t *z, uint64_t m,
20// (uint64_t p, uint64_t *z, 22// const uint64_t *x, uint64_t n, const uint64_t *y);
21// uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
22// 23//
23// Does the z := x - y operation, truncating modulo p words in general and 24// Does the z := x - y operation, truncating modulo p words in general and
24// returning a top borrow (0 or 1) in the p'th place, only subtracting input 25// returning a top borrow (0 or 1) in the p'th place, only subtracting input
@@ -49,7 +50,7 @@
49 50
50 51
51S2N_BN_SYMBOL(bignum_sub): 52S2N_BN_SYMBOL(bignum_sub):
52 _CET_ENDBR 53 _CET_ENDBR
53 54
54#if WINDOWS_ABI 55#if WINDOWS_ABI
55 push rdi 56 push rdi
@@ -75,7 +76,7 @@ S2N_BN_SYMBOL(bignum_sub):
75 cmp p, n 76 cmp p, n
76 cmovc n, p 77 cmovc n, p
77 cmp m, n 78 cmp m, n
78 jc ylonger 79 jc bignum_sub_ylonger
79 80
80// The case where x is longer or of the same size (p >= m >= n) 81// The case where x is longer or of the same size (p >= m >= n)
81 82
@@ -83,32 +84,32 @@ S2N_BN_SYMBOL(bignum_sub):
83 sub m, n 84 sub m, n
84 inc m 85 inc m
85 test n, n 86 test n, n
86 jz xtest 87 jz bignum_sub_xtest
87xmainloop: 88bignum_sub_xmainloop:
88 mov a, [x+8*i] 89 mov a, [x+8*i]
89 sbb a, [y+8*i] 90 sbb a, [y+8*i]
90 mov [z+8*i],a 91 mov [z+8*i],a
91 inc i 92 inc i
92 dec n 93 dec n
93 jnz xmainloop 94 jnz bignum_sub_xmainloop
94 jmp xtest 95 jmp bignum_sub_xtest
95xtoploop: 96bignum_sub_xtoploop:
96 mov a, [x+8*i] 97 mov a, [x+8*i]
97 sbb a, 0 98 sbb a, 0
98 mov [z+8*i],a 99 mov [z+8*i],a
99 inc i 100 inc i
100xtest: 101bignum_sub_xtest:
101 dec m 102 dec m
102 jnz xtoploop 103 jnz bignum_sub_xtoploop
103 sbb a, a 104 sbb a, a
104 test p, p 105 test p, p
105 jz tailskip 106 jz bignum_sub_tailskip
106tailloop: 107bignum_sub_tailloop:
107 mov [z+8*i],a 108 mov [z+8*i],a
108 inc i 109 inc i
109 dec p 110 dec p
110 jnz tailloop 111 jnz bignum_sub_tailloop
111tailskip: 112bignum_sub_tailskip:
112 neg a 113 neg a
113#if WINDOWS_ABI 114#if WINDOWS_ABI
114 pop rsi 115 pop rsi
@@ -118,29 +119,29 @@ tailskip:
118 119
119// The case where y is longer (p >= n > m) 120// The case where y is longer (p >= n > m)
120 121
121ylonger: 122bignum_sub_ylonger:
122 123
123 sub p, n 124 sub p, n
124 sub n, m 125 sub n, m
125 test m, m 126 test m, m
126 jz ytoploop 127 jz bignum_sub_ytoploop
127ymainloop: 128bignum_sub_ymainloop:
128 mov a, [x+8*i] 129 mov a, [x+8*i]
129 sbb a, [y+8*i] 130 sbb a, [y+8*i]
130 mov [z+8*i],a 131 mov [z+8*i],a
131 inc i 132 inc i
132 dec m 133 dec m
133 jnz ymainloop 134 jnz bignum_sub_ymainloop
134ytoploop: 135bignum_sub_ytoploop:
135 mov ashort, 0 136 mov ashort, 0
136 sbb a, [y+8*i] 137 sbb a, [y+8*i]
137 mov [z+8*i],a 138 mov [z+8*i],a
138 inc i 139 inc i
139 dec n 140 dec n
140 jnz ytoploop 141 jnz bignum_sub_ytoploop
141 sbb a, a 142 sbb a, a
142 test p, p 143 test p, p
143 jnz tailloop 144 jnz bignum_sub_tailloop
144 neg a 145 neg a
145#if WINDOWS_ABI 146#if WINDOWS_ABI
146 pop rsi 147 pop rsi
diff --git a/src/lib/libcrypto/bn/arch/amd64/bn_arch.c b/src/lib/libcrypto/bn/arch/amd64/bn_arch.c
index 8eb3670def..9ff8920ca2 100644
--- a/src/lib/libcrypto/bn/arch/amd64/bn_arch.c
+++ b/src/lib/libcrypto/bn/arch/amd64/bn_arch.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_arch.c,v 1.8 2025/08/05 15:01:13 jsing Exp $ */ 1/* $OpenBSD: bn_arch.c,v 1.12 2025/08/14 15:29:17 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2023 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -19,6 +19,7 @@
19 19
20#include "bn_arch.h" 20#include "bn_arch.h"
21#include "bn_local.h" 21#include "bn_local.h"
22#include "crypto_arch.h"
22#include "s2n_bignum.h" 23#include "s2n_bignum.h"
23 24
24#ifdef HAVE_BN_ADD 25#ifdef HAVE_BN_ADD
@@ -26,8 +27,8 @@ BN_ULONG
26bn_add(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len, const BN_ULONG *b, 27bn_add(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len, const BN_ULONG *b,
27 int b_len) 28 int b_len)
28{ 29{
29 return bignum_add(r_len, (uint64_t *)r, a_len, (uint64_t *)a, 30 return bignum_add(r_len, (uint64_t *)r, a_len, (const uint64_t *)a,
30 b_len, (uint64_t *)b); 31 b_len, (const uint64_t *)b);
31} 32}
32#endif 33#endif
33 34
@@ -36,8 +37,8 @@ bn_add(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len, const BN_ULONG *b,
36BN_ULONG 37BN_ULONG
37bn_add_words(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd, int n) 38bn_add_words(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd, int n)
38{ 39{
39 return bignum_add(n, (uint64_t *)rd, n, (uint64_t *)ad, n, 40 return bignum_add(n, (uint64_t *)rd, n, (const uint64_t *)ad, n,
40 (uint64_t *)bd); 41 (const uint64_t *)bd);
41} 42}
42#endif 43#endif
43 44
@@ -46,8 +47,8 @@ BN_ULONG
46bn_sub(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len, const BN_ULONG *b, 47bn_sub(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len, const BN_ULONG *b,
47 int b_len) 48 int b_len)
48{ 49{
49 return bignum_sub(r_len, (uint64_t *)r, a_len, (uint64_t *)a, 50 return bignum_sub(r_len, (uint64_t *)r, a_len, (const uint64_t *)a,
50 b_len, (uint64_t *)b); 51 b_len, (const uint64_t *)b);
51} 52}
52#endif 53#endif
53 54
@@ -55,8 +56,28 @@ bn_sub(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len, const BN_ULONG *b,
55BN_ULONG 56BN_ULONG
56bn_sub_words(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd, int n) 57bn_sub_words(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd, int n)
57{ 58{
58 return bignum_sub(n, (uint64_t *)rd, n, (uint64_t *)ad, n, 59 return bignum_sub(n, (uint64_t *)rd, n, (const uint64_t *)ad, n,
59 (uint64_t *)bd); 60 (const uint64_t *)bd);
61}
62#endif
63
64#ifdef HAVE_BN_MOD_ADD_WORDS
65void
66bn_mod_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
67 const BN_ULONG *m, size_t n)
68{
69 bignum_modadd(n, (uint64_t *)r, (const uint64_t *)a,
70 (const uint64_t *)b, (const uint64_t *)m);
71}
72#endif
73
74#ifdef HAVE_BN_MOD_SUB_WORDS
75void
76bn_mod_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
77 const BN_ULONG *m, size_t n)
78{
79 bignum_modsub(n, (uint64_t *)r, (const uint64_t *)a,
80 (const uint64_t *)b, (const uint64_t *)m);
60} 81}
61#endif 82#endif
62 83
@@ -64,7 +85,7 @@ bn_sub_words(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd, int n)
64BN_ULONG 85BN_ULONG
65bn_mul_add_words(BN_ULONG *rd, const BN_ULONG *ad, int num, BN_ULONG w) 86bn_mul_add_words(BN_ULONG *rd, const BN_ULONG *ad, int num, BN_ULONG w)
66{ 87{
67 return bignum_cmadd(num, (uint64_t *)rd, w, num, (uint64_t *)ad); 88 return bignum_cmadd(num, (uint64_t *)rd, w, num, (const uint64_t *)ad);
68} 89}
69#endif 90#endif
70 91
@@ -72,7 +93,7 @@ bn_mul_add_words(BN_ULONG *rd, const BN_ULONG *ad, int num, BN_ULONG w)
72BN_ULONG 93BN_ULONG
73bn_mul_words(BN_ULONG *rd, const BN_ULONG *ad, int num, BN_ULONG w) 94bn_mul_words(BN_ULONG *rd, const BN_ULONG *ad, int num, BN_ULONG w)
74{ 95{
75 return bignum_cmul(num, (uint64_t *)rd, w, num, (uint64_t *)ad); 96 return bignum_cmul(num, (uint64_t *)rd, w, num, (const uint64_t *)ad);
76} 97}
77#endif 98#endif
78 99
@@ -80,8 +101,29 @@ bn_mul_words(BN_ULONG *rd, const BN_ULONG *ad, int num, BN_ULONG w)
80void 101void
81bn_mul_comba4(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd) 102bn_mul_comba4(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd)
82{ 103{
83 /* XXX - consider using non-alt on CPUs that have the ADX extension. */ 104 if ((crypto_cpu_caps_amd64 & CRYPTO_CPU_CAPS_AMD64_ADX) != 0) {
84 bignum_mul_4_8_alt((uint64_t *)rd, (uint64_t *)ad, (uint64_t *)bd); 105 bignum_mul_4_8((uint64_t *)rd, (const uint64_t *)ad,
106 (const uint64_t *)bd);
107 return;
108 }
109
110 bignum_mul_4_8_alt((uint64_t *)rd, (const uint64_t *)ad,
111 (const uint64_t *)bd);
112}
113#endif
114
115#ifdef HAVE_BN_MUL_COMBA6
116void
117bn_mul_comba6(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd)
118{
119 if ((crypto_cpu_caps_amd64 & CRYPTO_CPU_CAPS_AMD64_ADX) != 0) {
120 bignum_mul_6_12((uint64_t *)rd, (const uint64_t *)ad,
121 (const uint64_t *)bd);
122 return;
123 }
124
125 bignum_mul_6_12_alt((uint64_t *)rd, (const uint64_t *)ad,
126 (const uint64_t *)bd);
85} 127}
86#endif 128#endif
87 129
@@ -89,8 +131,14 @@ bn_mul_comba4(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd)
89void 131void
90bn_mul_comba8(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd) 132bn_mul_comba8(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd)
91{ 133{
92 /* XXX - consider using non-alt on CPUs that have the ADX extension. */ 134 if ((crypto_cpu_caps_amd64 & CRYPTO_CPU_CAPS_AMD64_ADX) != 0) {
93 bignum_mul_8_16_alt((uint64_t *)rd, (uint64_t *)ad, (uint64_t *)bd); 135 bignum_mul_8_16((uint64_t *)rd, (const uint64_t *)ad,
136 (const uint64_t *)bd);
137 return;
138 }
139
140 bignum_mul_8_16_alt((uint64_t *)rd, (const uint64_t *)ad,
141 (const uint64_t *)bd);
94} 142}
95#endif 143#endif
96 144
@@ -98,7 +146,7 @@ bn_mul_comba8(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd)
98int 146int
99bn_sqr(BIGNUM *r, const BIGNUM *a, int r_len, BN_CTX *ctx) 147bn_sqr(BIGNUM *r, const BIGNUM *a, int r_len, BN_CTX *ctx)
100{ 148{
101 bignum_sqr(r_len, (uint64_t *)r->d, a->top, (uint64_t *)a->d); 149 bignum_sqr(r_len, (uint64_t *)r->d, a->top, (const uint64_t *)a->d);
102 150
103 return 1; 151 return 1;
104} 152}
@@ -108,8 +156,25 @@ bn_sqr(BIGNUM *r, const BIGNUM *a, int r_len, BN_CTX *ctx)
108void 156void
109bn_sqr_comba4(BN_ULONG *rd, const BN_ULONG *ad) 157bn_sqr_comba4(BN_ULONG *rd, const BN_ULONG *ad)
110{ 158{
111 /* XXX - consider using non-alt on CPUs that have the ADX extension. */ 159 if ((crypto_cpu_caps_amd64 & CRYPTO_CPU_CAPS_AMD64_ADX) != 0) {
112 bignum_sqr_4_8_alt((uint64_t *)rd, (uint64_t *)ad); 160 bignum_sqr_4_8((uint64_t *)rd, (const uint64_t *)ad);
161 return;
162 }
163
164 bignum_sqr_4_8_alt((uint64_t *)rd, (const uint64_t *)ad);
165}
166#endif
167
168#ifdef HAVE_BN_SQR_COMBA6
169void
170bn_sqr_comba6(BN_ULONG *rd, const BN_ULONG *ad)
171{
172 if ((crypto_cpu_caps_amd64 & CRYPTO_CPU_CAPS_AMD64_ADX) != 0) {
173 bignum_sqr_6_12((uint64_t *)rd, (const uint64_t *)ad);
174 return;
175 }
176
177 bignum_sqr_6_12_alt((uint64_t *)rd, (const uint64_t *)ad);
113} 178}
114#endif 179#endif
115 180
@@ -117,8 +182,12 @@ bn_sqr_comba4(BN_ULONG *rd, const BN_ULONG *ad)
117void 182void
118bn_sqr_comba8(BN_ULONG *rd, const BN_ULONG *ad) 183bn_sqr_comba8(BN_ULONG *rd, const BN_ULONG *ad)
119{ 184{
120 /* XXX - consider using non-alt on CPUs that have the ADX extension. */ 185 if ((crypto_cpu_caps_amd64 & CRYPTO_CPU_CAPS_AMD64_ADX) != 0) {
121 bignum_sqr_8_16_alt((uint64_t *)rd, (uint64_t *)ad); 186 bignum_sqr_8_16((uint64_t *)rd, (const uint64_t *)ad);
187 return;
188 }
189
190 bignum_sqr_8_16_alt((uint64_t *)rd, (const uint64_t *)ad);
122} 191}
123#endif 192#endif
124 193
diff --git a/src/lib/libcrypto/bn/arch/amd64/bn_arch.h b/src/lib/libcrypto/bn/arch/amd64/bn_arch.h
index 927cd75208..7359f993a7 100644
--- a/src/lib/libcrypto/bn/arch/amd64/bn_arch.h
+++ b/src/lib/libcrypto/bn/arch/amd64/bn_arch.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_arch.h,v 1.14 2024/03/26 06:09:25 jsing Exp $ */ 1/* $OpenBSD: bn_arch.h,v 1.16 2025/08/14 15:22:54 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2023 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -27,13 +27,18 @@
27 27
28#define HAVE_BN_DIV_WORDS 28#define HAVE_BN_DIV_WORDS
29 29
30#define HAVE_BN_MOD_ADD_WORDS
31#define HAVE_BN_MOD_SUB_WORDS
32
30#define HAVE_BN_MUL_ADD_WORDS 33#define HAVE_BN_MUL_ADD_WORDS
31#define HAVE_BN_MUL_COMBA4 34#define HAVE_BN_MUL_COMBA4
35#define HAVE_BN_MUL_COMBA6
32#define HAVE_BN_MUL_COMBA8 36#define HAVE_BN_MUL_COMBA8
33#define HAVE_BN_MUL_WORDS 37#define HAVE_BN_MUL_WORDS
34 38
35#define HAVE_BN_SQR 39#define HAVE_BN_SQR
36#define HAVE_BN_SQR_COMBA4 40#define HAVE_BN_SQR_COMBA4
41#define HAVE_BN_SQR_COMBA6
37#define HAVE_BN_SQR_COMBA8 42#define HAVE_BN_SQR_COMBA8
38 43
39#define HAVE_BN_SUB 44#define HAVE_BN_SUB
diff --git a/src/lib/libcrypto/bn/arch/amd64/word_clz.S b/src/lib/libcrypto/bn/arch/amd64/word_clz.S
index 3926fcd4b0..705fbdbbda 100644
--- a/src/lib/libcrypto/bn/arch/amd64/word_clz.S
+++ b/src/lib/libcrypto/bn/arch/amd64/word_clz.S
@@ -1,3 +1,5 @@
1// $OpenBSD: word_clz.S,v 1.7 2025/08/11 14:13:56 jsing Exp $
2//
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// 4//
3// Permission to use, copy, modify, and/or distribute this software for any 5// Permission to use, copy, modify, and/or distribute this software for any
@@ -16,7 +18,7 @@
16// Count leading zero bits in a single word 18// Count leading zero bits in a single word
17// Input a; output function return 19// Input a; output function return
18// 20//
19// extern uint64_t word_clz (uint64_t a); 21// extern uint64_t word_clz(uint64_t a);
20// 22//
21// Standard x86-64 ABI: RDI = a, returns RAX 23// Standard x86-64 ABI: RDI = a, returns RAX
22// Microsoft x64 ABI: RCX = a, returns RAX 24// Microsoft x64 ABI: RCX = a, returns RAX
@@ -30,7 +32,7 @@
30 .text 32 .text
31 33
32S2N_BN_SYMBOL(word_clz): 34S2N_BN_SYMBOL(word_clz):
33 _CET_ENDBR 35 _CET_ENDBR
34 36
35#if WINDOWS_ABI 37#if WINDOWS_ABI
36 push rdi 38 push rdi
diff --git a/src/lib/libcrypto/bn/bn_mul.c b/src/lib/libcrypto/bn/bn_mul.c
index 70f6534b8f..a30d05fb02 100644
--- a/src/lib/libcrypto/bn/bn_mul.c
+++ b/src/lib/libcrypto/bn/bn_mul.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_mul.c,v 1.42 2025/08/05 15:06:13 jsing Exp $ */ 1/* $OpenBSD: bn_mul.c,v 1.43 2025/08/14 15:15:04 jsing Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -407,6 +407,8 @@ BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
407 407
408 if (a->top == 4 && b->top == 4) { 408 if (a->top == 4 && b->top == 4) {
409 bn_mul_comba4(rr->d, a->d, b->d); 409 bn_mul_comba4(rr->d, a->d, b->d);
410 } else if (a->top == 6 && b->top == 6) {
411 bn_mul_comba6(rr->d, a->d, b->d);
410 } else if (a->top == 8 && b->top == 8) { 412 } else if (a->top == 8 && b->top == 8) {
411 bn_mul_comba8(rr->d, a->d, b->d); 413 bn_mul_comba8(rr->d, a->d, b->d);
412 } else { 414 } else {
diff --git a/src/lib/libcrypto/bn/bn_sqr.c b/src/lib/libcrypto/bn/bn_sqr.c
index ab1282e3b1..2f7f71f819 100644
--- a/src/lib/libcrypto/bn/bn_sqr.c
+++ b/src/lib/libcrypto/bn/bn_sqr.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_sqr.c,v 1.37 2025/08/05 15:08:13 jsing Exp $ */ 1/* $OpenBSD: bn_sqr.c,v 1.38 2025/08/14 15:15:04 jsing Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -326,6 +326,8 @@ BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
326 326
327 if (a->top == 4) { 327 if (a->top == 4) {
328 bn_sqr_comba4(rr->d, a->d); 328 bn_sqr_comba4(rr->d, a->d);
329 } else if (a->top == 6) {
330 bn_sqr_comba6(rr->d, a->d);
329 } else if (a->top == 8) { 331 } else if (a->top == 8) {
330 bn_sqr_comba8(rr->d, a->d); 332 bn_sqr_comba8(rr->d, a->d);
331 } else { 333 } else {
diff --git a/src/lib/libcrypto/bn/s2n_bignum.h b/src/lib/libcrypto/bn/s2n_bignum.h
index ce6e8cdc94..7d77894cdc 100644
--- a/src/lib/libcrypto/bn/s2n_bignum.h
+++ b/src/lib/libcrypto/bn/s2n_bignum.h
@@ -1,3 +1,5 @@
1// $OpenBSD: s2n_bignum.h,v 1.4 2025/08/12 10:01:37 jsing Exp $
2//
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// 4//
3// Permission to use, copy, modify, and/or distribute this software for any 5// Permission to use, copy, modify, and/or distribute this software for any
@@ -34,182 +36,240 @@
34// throughput, generally offering higher performance there. 36// throughput, generally offering higher performance there.
35// ---------------------------------------------------------------------------- 37// ----------------------------------------------------------------------------
36 38
39
40#if defined(_MSC_VER) || !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L || defined(__STDC_NO_VLA__)
41#define S2N_BIGNUM_STATIC
42#else
43#define S2N_BIGNUM_STATIC static
44#endif
45
37// Add, z := x + y 46// Add, z := x + y
38// Inputs x[m], y[n]; outputs function return (carry-out) and z[p] 47// Inputs x[m], y[n]; outputs function return (carry-out) and z[p]
39extern uint64_t bignum_add (uint64_t p, uint64_t *z, uint64_t m, uint64_t *x, uint64_t n, uint64_t *y); 48extern uint64_t bignum_add (uint64_t p, uint64_t *z, uint64_t m, const uint64_t *x, uint64_t n, const uint64_t *y);
40 49
41// Add modulo p_25519, z := (x + y) mod p_25519, assuming x and y reduced 50// Add modulo p_25519, z := (x + y) mod p_25519, assuming x and y reduced
42// Inputs x[4], y[4]; output z[4] 51// Inputs x[4], y[4]; output z[4]
43extern void bignum_add_p25519 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]); 52extern void bignum_add_p25519 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
44 53
45// Add modulo p_256, z := (x + y) mod p_256, assuming x and y reduced 54// Add modulo p_256, z := (x + y) mod p_256, assuming x and y reduced
46// Inputs x[4], y[4]; output z[4] 55// Inputs x[4], y[4]; output z[4]
47extern void bignum_add_p256 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]); 56extern void bignum_add_p256 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
48 57
49// Add modulo p_256k1, z := (x + y) mod p_256k1, assuming x and y reduced 58// Add modulo p_256k1, z := (x + y) mod p_256k1, assuming x and y reduced
50// Inputs x[4], y[4]; output z[4] 59// Inputs x[4], y[4]; output z[4]
51extern void bignum_add_p256k1 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]); 60extern void bignum_add_p256k1 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
52 61
53// Add modulo p_384, z := (x + y) mod p_384, assuming x and y reduced 62// Add modulo p_384, z := (x + y) mod p_384, assuming x and y reduced
54// Inputs x[6], y[6]; output z[6] 63// Inputs x[6], y[6]; output z[6]
55extern void bignum_add_p384 (uint64_t z[static 6], uint64_t x[static 6], uint64_t y[static 6]); 64extern void bignum_add_p384 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6], const uint64_t y[S2N_BIGNUM_STATIC 6]);
56 65
57// Add modulo p_521, z := (x + y) mod p_521, assuming x and y reduced 66// Add modulo p_521, z := (x + y) mod p_521, assuming x and y reduced
58// Inputs x[9], y[9]; output z[9] 67// Inputs x[9], y[9]; output z[9]
59extern void bignum_add_p521 (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]); 68extern void bignum_add_p521 (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9], const uint64_t y[S2N_BIGNUM_STATIC 9]);
69
70// Add modulo p_sm2, z := (x + y) mod p_sm2, assuming x and y reduced
71// Inputs x[4], y[4]; output z[4]
72extern void bignum_add_sm2 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
60 73
61// Compute "amontification" constant z :== 2^{128k} (congruent mod m) 74// Compute "amontification" constant z :== 2^{128k} (congruent mod m)
62// Input m[k]; output z[k]; temporary buffer t[>=k] 75// Input m[k]; output z[k]; temporary buffer t[>=k]
63extern void bignum_amontifier (uint64_t k, uint64_t *z, uint64_t *m, uint64_t *t); 76extern void bignum_amontifier (uint64_t k, uint64_t *z, const uint64_t *m, uint64_t *t);
64 77
65// Almost-Montgomery multiply, z :== (x * y / 2^{64k}) (congruent mod m) 78// Almost-Montgomery multiply, z :== (x * y / 2^{64k}) (congruent mod m)
66// Inputs x[k], y[k], m[k]; output z[k] 79// Inputs x[k], y[k], m[k]; output z[k]
67extern void bignum_amontmul (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y, uint64_t *m); 80extern void bignum_amontmul (uint64_t k, uint64_t *z, const uint64_t *x, const uint64_t *y, const uint64_t *m);
68 81
69// Almost-Montgomery reduce, z :== (x' / 2^{64p}) (congruent mod m) 82// Almost-Montgomery reduce, z :== (x' / 2^{64p}) (congruent mod m)
70// Inputs x[n], m[k], p; output z[k] 83// Inputs x[n], m[k], p; output z[k]
71extern void bignum_amontredc (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t *m, uint64_t p); 84extern void bignum_amontredc (uint64_t k, uint64_t *z, uint64_t n, const uint64_t *x, const uint64_t *m, uint64_t p);
72 85
73// Almost-Montgomery square, z :== (x^2 / 2^{64k}) (congruent mod m) 86// Almost-Montgomery square, z :== (x^2 / 2^{64k}) (congruent mod m)
74// Inputs x[k], m[k]; output z[k] 87// Inputs x[k], m[k]; output z[k]
75extern void bignum_amontsqr (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *m); 88extern void bignum_amontsqr (uint64_t k, uint64_t *z, const uint64_t *x, const uint64_t *m);
76 89
77// Convert 4-digit (256-bit) bignum to/from big-endian form 90// Convert 4-digit (256-bit) bignum to/from big-endian form
78// Input x[4]; output z[4] 91// Input x[4]; output z[4]
79extern void bignum_bigendian_4 (uint64_t z[static 4], uint64_t x[static 4]); 92extern void bignum_bigendian_4 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
80 93
81// Convert 6-digit (384-bit) bignum to/from big-endian form 94// Convert 6-digit (384-bit) bignum to/from big-endian form
82// Input x[6]; output z[6] 95// Input x[6]; output z[6]
83extern void bignum_bigendian_6 (uint64_t z[static 6], uint64_t x[static 6]); 96extern void bignum_bigendian_6 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
84 97
85// Select bitfield starting at bit n with length l <= 64 98// Select bitfield starting at bit n with length l <= 64
86// Inputs x[k], n, l; output function return 99// Inputs x[k], n, l; output function return
87extern uint64_t bignum_bitfield (uint64_t k, uint64_t *x, uint64_t n, uint64_t l); 100extern uint64_t bignum_bitfield (uint64_t k, const uint64_t *x, uint64_t n, uint64_t l);
88 101
89// Return size of bignum in bits 102// Return size of bignum in bits
90// Input x[k]; output function return 103// Input x[k]; output function return
91extern uint64_t bignum_bitsize (uint64_t k, uint64_t *x); 104extern uint64_t bignum_bitsize (uint64_t k, const uint64_t *x);
92 105
93// Divide by a single (nonzero) word, z := x / m and return x mod m 106// Divide by a single (nonzero) word, z := x / m and return x mod m
94// Inputs x[n], m; outputs function return (remainder) and z[k] 107// Inputs x[n], m; outputs function return (remainder) and z[k]
95extern uint64_t bignum_cdiv (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t m); 108extern uint64_t bignum_cdiv (uint64_t k, uint64_t *z, uint64_t n, const uint64_t *x, uint64_t m);
96 109
97// Divide by a single word, z := x / m when known to be exact 110// Divide by a single word, z := x / m when known to be exact
98// Inputs x[n], m; output z[k] 111// Inputs x[n], m; output z[k]
99extern void bignum_cdiv_exact (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t m); 112extern void bignum_cdiv_exact (uint64_t k, uint64_t *z, uint64_t n, const uint64_t *x, uint64_t m);
100 113
101// Count leading zero digits (64-bit words) 114// Count leading zero digits (64-bit words)
102// Input x[k]; output function return 115// Input x[k]; output function return
103extern uint64_t bignum_cld (uint64_t k, uint64_t *x); 116extern uint64_t bignum_cld (uint64_t k, const uint64_t *x);
104 117
105// Count leading zero bits 118// Count leading zero bits
106// Input x[k]; output function return 119// Input x[k]; output function return
107extern uint64_t bignum_clz (uint64_t k, uint64_t *x); 120extern uint64_t bignum_clz (uint64_t k, const uint64_t *x);
108 121
109// Multiply-add with single-word multiplier, z := z + c * y 122// Multiply-add with single-word multiplier, z := z + c * y
110// Inputs c, y[n]; outputs function return (carry-out) and z[k] 123// Inputs c, y[n]; outputs function return (carry-out) and z[k]
111extern uint64_t bignum_cmadd (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y); 124extern uint64_t bignum_cmadd (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, const uint64_t *y);
112 125
113// Negated multiply-add with single-word multiplier, z := z - c * y 126// Negated multiply-add with single-word multiplier, z := z - c * y
114// Inputs c, y[n]; outputs function return (negative carry-out) and z[k] 127// Inputs c, y[n]; outputs function return (negative carry-out) and z[k]
115extern uint64_t bignum_cmnegadd (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y); 128extern uint64_t bignum_cmnegadd (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, const uint64_t *y);
116 129
117// Find modulus of bignum w.r.t. single nonzero word m, returning x mod m 130// Find modulus of bignum w.r.t. single nonzero word m, returning x mod m
118// Input x[k], m; output function return 131// Input x[k], m; output function return
119extern uint64_t bignum_cmod (uint64_t k, uint64_t *x, uint64_t m); 132extern uint64_t bignum_cmod (uint64_t k, const uint64_t *x, uint64_t m);
120 133
121// Multiply by a single word, z := c * y 134// Multiply by a single word, z := c * y
122// Inputs c, y[n]; outputs function return (carry-out) and z[k] 135// Inputs c, y[n]; outputs function return (carry-out) and z[k]
123extern uint64_t bignum_cmul (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y); 136extern uint64_t bignum_cmul (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, const uint64_t *y);
124 137
125// Multiply by a single word modulo p_25519, z := (c * x) mod p_25519, assuming x reduced 138// Multiply by a single word modulo p_25519, z := (c * x) mod p_25519, assuming x reduced
126// Inputs c, x[4]; output z[4] 139// Inputs c, x[4]; output z[4]
127extern void bignum_cmul_p25519 (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]); 140extern void bignum_cmul_p25519 (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t c, const uint64_t x[S2N_BIGNUM_STATIC 4]);
128extern void bignum_cmul_p25519_alt (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]); 141extern void bignum_cmul_p25519_alt (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t c, const uint64_t x[S2N_BIGNUM_STATIC 4]);
129 142
130// Multiply by a single word modulo p_256, z := (c * x) mod p_256, assuming x reduced 143// Multiply by a single word modulo p_256, z := (c * x) mod p_256, assuming x reduced
131// Inputs c, x[4]; output z[4] 144// Inputs c, x[4]; output z[4]
132extern void bignum_cmul_p256 (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]); 145extern void bignum_cmul_p256 (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t c, const uint64_t x[S2N_BIGNUM_STATIC 4]);
133extern void bignum_cmul_p256_alt (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]); 146extern void bignum_cmul_p256_alt (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t c, const uint64_t x[S2N_BIGNUM_STATIC 4]);
134 147
135// Multiply by a single word modulo p_256k1, z := (c * x) mod p_256k1, assuming x reduced 148// Multiply by a single word modulo p_256k1, z := (c * x) mod p_256k1, assuming x reduced
136// Inputs c, x[4]; output z[4] 149// Inputs c, x[4]; output z[4]
137extern void bignum_cmul_p256k1 (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]); 150extern void bignum_cmul_p256k1 (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t c, const uint64_t x[S2N_BIGNUM_STATIC 4]);
138extern void bignum_cmul_p256k1_alt (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]); 151extern void bignum_cmul_p256k1_alt (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t c, const uint64_t x[S2N_BIGNUM_STATIC 4]);
139 152
140// Multiply by a single word modulo p_384, z := (c * x) mod p_384, assuming x reduced 153// Multiply by a single word modulo p_384, z := (c * x) mod p_384, assuming x reduced
141// Inputs c, x[6]; output z[6] 154// Inputs c, x[6]; output z[6]
142extern void bignum_cmul_p384 (uint64_t z[static 6], uint64_t c, uint64_t x[static 6]); 155extern void bignum_cmul_p384 (uint64_t z[S2N_BIGNUM_STATIC 6], uint64_t c, const uint64_t x[S2N_BIGNUM_STATIC 6]);
143extern void bignum_cmul_p384_alt (uint64_t z[static 6], uint64_t c, uint64_t x[static 6]); 156extern void bignum_cmul_p384_alt (uint64_t z[S2N_BIGNUM_STATIC 6], uint64_t c, const uint64_t x[S2N_BIGNUM_STATIC 6]);
144 157
145// Multiply by a single word modulo p_521, z := (c * x) mod p_521, assuming x reduced 158// Multiply by a single word modulo p_521, z := (c * x) mod p_521, assuming x reduced
146// Inputs c, x[9]; output z[9] 159// Inputs c, x[9]; output z[9]
147extern void bignum_cmul_p521 (uint64_t z[static 9], uint64_t c, uint64_t x[static 9]); 160extern void bignum_cmul_p521 (uint64_t z[S2N_BIGNUM_STATIC 9], uint64_t c, const uint64_t x[S2N_BIGNUM_STATIC 9]);
148extern void bignum_cmul_p521_alt (uint64_t z[static 9], uint64_t c, uint64_t x[static 9]); 161extern void bignum_cmul_p521_alt (uint64_t z[S2N_BIGNUM_STATIC 9], uint64_t c, const uint64_t x[S2N_BIGNUM_STATIC 9]);
162
163// Multiply by a single word modulo p_sm2, z := (c * x) mod p_sm2, assuming x reduced
164// Inputs c, x[4]; output z[4]
165extern void bignum_cmul_sm2 (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t c, const uint64_t x[S2N_BIGNUM_STATIC 4]);
166extern void bignum_cmul_sm2_alt (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t c, const uint64_t x[S2N_BIGNUM_STATIC 4]);
149 167
150// Test bignums for coprimality, gcd(x,y) = 1 168// Test bignums for coprimality, gcd(x,y) = 1
151// Inputs x[m], y[n]; output function return; temporary buffer t[>=2*max(m,n)] 169// Inputs x[m], y[n]; output function return; temporary buffer t[>=2*max(m,n)]
152extern uint64_t bignum_coprime (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y, uint64_t *t); 170extern uint64_t bignum_coprime (uint64_t m, const uint64_t *x, uint64_t n, const uint64_t *y, uint64_t *t);
153 171
154// Copy bignum with zero-extension or truncation, z := x 172// Copy bignum with zero-extension or truncation, z := x
155// Input x[n]; output z[k] 173// Input x[n]; output z[k]
156extern void bignum_copy (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x); 174extern void bignum_copy (uint64_t k, uint64_t *z, uint64_t n, const uint64_t *x);
175
176// Given table: uint64_t[height*width], copy table[idx*width...(idx+1)*width-1]
177// into z[0..width-1].
178// This function is constant-time with respect to the value of `idx`. This is
179// achieved by reading the whole table and using the bit-masking to get the
180// `idx`-th row.
181// Input table[height*width]; output z[width]
182extern void bignum_copy_row_from_table (uint64_t *z, const uint64_t *table, uint64_t height,
183 uint64_t width, uint64_t idx);
184
185// Given table: uint64_t[height*width], copy table[idx*width...(idx+1)*width-1]
186// into z[0..width-1]. width must be a multiple of 8.
187// This function is constant-time with respect to the value of `idx`. This is
188// achieved by reading the whole table and using the bit-masking to get the
189// `idx`-th row.
190// Input table[height*width]; output z[width]
191extern void bignum_copy_row_from_table_8n (uint64_t *z, const uint64_t *table,
192 uint64_t height, uint64_t width, uint64_t idx);
193
194// Given table: uint64_t[height*16], copy table[idx*16...(idx+1)*16-1] into z[0..row-1].
195// This function is constant-time with respect to the value of `idx`. This is
196// achieved by reading the whole table and using the bit-masking to get the
197// `idx`-th row.
198// Input table[height*16]; output z[16]
199extern void bignum_copy_row_from_table_16 (uint64_t *z, const uint64_t *table,
200 uint64_t height, uint64_t idx);
201
202// Given table: uint64_t[height*32], copy table[idx*32...(idx+1)*32-1] into z[0..row-1].
203// This function is constant-time with respect to the value of `idx`. This is
204// achieved by reading the whole table and using the bit-masking to get the
205// `idx`-th row.
206// Input table[height*32]; output z[32]
207extern void bignum_copy_row_from_table_32 (uint64_t *z, const uint64_t *table,
208 uint64_t height, uint64_t idx);
157 209
158// Count trailing zero digits (64-bit words) 210// Count trailing zero digits (64-bit words)
159// Input x[k]; output function return 211// Input x[k]; output function return
160extern uint64_t bignum_ctd (uint64_t k, uint64_t *x); 212extern uint64_t bignum_ctd (uint64_t k, const uint64_t *x);
161 213
162// Count trailing zero bits 214// Count trailing zero bits
163// Input x[k]; output function return 215// Input x[k]; output function return
164extern uint64_t bignum_ctz (uint64_t k, uint64_t *x); 216extern uint64_t bignum_ctz (uint64_t k, const uint64_t *x);
165 217
166// Convert from almost-Montgomery form, z := (x / 2^256) mod p_256 218// Convert from almost-Montgomery form, z := (x / 2^256) mod p_256
167// Input x[4]; output z[4] 219// Input x[4]; output z[4]
168extern void bignum_deamont_p256 (uint64_t z[static 4], uint64_t x[static 4]); 220extern void bignum_deamont_p256 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
169extern void bignum_deamont_p256_alt (uint64_t z[static 4], uint64_t x[static 4]); 221extern void bignum_deamont_p256_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
170 222
171// Convert from almost-Montgomery form, z := (x / 2^256) mod p_256k1 223// Convert from almost-Montgomery form, z := (x / 2^256) mod p_256k1
172// Input x[4]; output z[4] 224// Input x[4]; output z[4]
173extern void bignum_deamont_p256k1 (uint64_t z[static 4], uint64_t x[static 4]); 225extern void bignum_deamont_p256k1 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
174 226
175// Convert from almost-Montgomery form, z := (x / 2^384) mod p_384 227// Convert from almost-Montgomery form, z := (x / 2^384) mod p_384
176// Input x[6]; output z[6] 228// Input x[6]; output z[6]
177extern void bignum_deamont_p384 (uint64_t z[static 6], uint64_t x[static 6]); 229extern void bignum_deamont_p384 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
178extern void bignum_deamont_p384_alt (uint64_t z[static 6], uint64_t x[static 6]); 230extern void bignum_deamont_p384_alt (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
179 231
180// Convert from almost-Montgomery form z := (x / 2^576) mod p_521 232// Convert from almost-Montgomery form z := (x / 2^576) mod p_521
181// Input x[9]; output z[9] 233// Input x[9]; output z[9]
182extern void bignum_deamont_p521 (uint64_t z[static 9], uint64_t x[static 9]); 234extern void bignum_deamont_p521 (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9]);
235
236// Convert from almost-Montgomery form z := (x / 2^256) mod p_sm2
237// Input x[4]; output z[4]
238extern void bignum_deamont_sm2 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
183 239
184// Convert from (almost-)Montgomery form z := (x / 2^{64k}) mod m 240// Convert from (almost-)Montgomery form z := (x / 2^{64k}) mod m
185// Inputs x[k], m[k]; output z[k] 241// Inputs x[k], m[k]; output z[k]
186extern void bignum_demont (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *m); 242extern void bignum_demont (uint64_t k, uint64_t *z, const uint64_t *x, const uint64_t *m);
187 243
188// Convert from Montgomery form z := (x / 2^256) mod p_256, assuming x reduced 244// Convert from Montgomery form z := (x / 2^256) mod p_256, assuming x reduced
189// Input x[4]; output z[4] 245// Input x[4]; output z[4]
190extern void bignum_demont_p256 (uint64_t z[static 4], uint64_t x[static 4]); 246extern void bignum_demont_p256 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
191extern void bignum_demont_p256_alt (uint64_t z[static 4], uint64_t x[static 4]); 247extern void bignum_demont_p256_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
192 248
193// Convert from Montgomery form z := (x / 2^256) mod p_256k1, assuming x reduced 249// Convert from Montgomery form z := (x / 2^256) mod p_256k1, assuming x reduced
194// Input x[4]; output z[4] 250// Input x[4]; output z[4]
195extern void bignum_demont_p256k1 (uint64_t z[static 4], uint64_t x[static 4]); 251extern void bignum_demont_p256k1 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
196 252
197// Convert from Montgomery form z := (x / 2^384) mod p_384, assuming x reduced 253// Convert from Montgomery form z := (x / 2^384) mod p_384, assuming x reduced
198// Input x[6]; output z[6] 254// Input x[6]; output z[6]
199extern void bignum_demont_p384 (uint64_t z[static 6], uint64_t x[static 6]); 255extern void bignum_demont_p384 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
200extern void bignum_demont_p384_alt (uint64_t z[static 6], uint64_t x[static 6]); 256extern void bignum_demont_p384_alt (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
201 257
202// Convert from Montgomery form z := (x / 2^576) mod p_521, assuming x reduced 258// Convert from Montgomery form z := (x / 2^576) mod p_521, assuming x reduced
203// Input x[9]; output z[9] 259// Input x[9]; output z[9]
204extern void bignum_demont_p521 (uint64_t z[static 9], uint64_t x[static 9]); 260extern void bignum_demont_p521 (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9]);
261
262// Convert from Montgomery form z := (x / 2^256) mod p_sm2, assuming x reduced
263// Input x[4]; output z[4]
264extern void bignum_demont_sm2 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
205 265
206// Select digit x[n] 266// Select digit x[n]
207// Inputs x[k], n; output function return 267// Inputs x[k], n; output function return
208extern uint64_t bignum_digit (uint64_t k, uint64_t *x, uint64_t n); 268extern uint64_t bignum_digit (uint64_t k, const uint64_t *x, uint64_t n);
209 269
210// Return size of bignum in digits (64-bit word) 270// Return size of bignum in digits (64-bit word)
211// Input x[k]; output function return 271// Input x[k]; output function return
212extern uint64_t bignum_digitsize (uint64_t k, uint64_t *x); 272extern uint64_t bignum_digitsize (uint64_t k, const uint64_t *x);
213 273
214// Divide bignum by 10: z' := z div 10, returning remainder z mod 10 274// Divide bignum by 10: z' := z div 10, returning remainder z mod 10
215// Inputs z[k]; outputs function return (remainder) and z[k] 275// Inputs z[k]; outputs function return (remainder) and z[k]
@@ -217,294 +277,391 @@ extern uint64_t bignum_divmod10 (uint64_t k, uint64_t *z);
217 277
218// Double modulo p_25519, z := (2 * x) mod p_25519, assuming x reduced 278// Double modulo p_25519, z := (2 * x) mod p_25519, assuming x reduced
219// Input x[4]; output z[4] 279// Input x[4]; output z[4]
220extern void bignum_double_p25519 (uint64_t z[static 4], uint64_t x[static 4]); 280extern void bignum_double_p25519 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
221 281
222// Double modulo p_256, z := (2 * x) mod p_256, assuming x reduced 282// Double modulo p_256, z := (2 * x) mod p_256, assuming x reduced
223// Input x[4]; output z[4] 283// Input x[4]; output z[4]
224extern void bignum_double_p256 (uint64_t z[static 4], uint64_t x[static 4]); 284extern void bignum_double_p256 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
225 285
226// Double modulo p_256k1, z := (2 * x) mod p_256k1, assuming x reduced 286// Double modulo p_256k1, z := (2 * x) mod p_256k1, assuming x reduced
227// Input x[4]; output z[4] 287// Input x[4]; output z[4]
228extern void bignum_double_p256k1 (uint64_t z[static 4], uint64_t x[static 4]); 288extern void bignum_double_p256k1 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
229 289
230// Double modulo p_384, z := (2 * x) mod p_384, assuming x reduced 290// Double modulo p_384, z := (2 * x) mod p_384, assuming x reduced
231// Input x[6]; output z[6] 291// Input x[6]; output z[6]
232extern void bignum_double_p384 (uint64_t z[static 6], uint64_t x[static 6]); 292extern void bignum_double_p384 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
233 293
234// Double modulo p_521, z := (2 * x) mod p_521, assuming x reduced 294// Double modulo p_521, z := (2 * x) mod p_521, assuming x reduced
235// Input x[9]; output z[9] 295// Input x[9]; output z[9]
236extern void bignum_double_p521 (uint64_t z[static 9], uint64_t x[static 9]); 296extern void bignum_double_p521 (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9]);
297
298// Double modulo p_sm2, z := (2 * x) mod p_sm2, assuming x reduced
299// Input x[4]; output z[4]
300extern void bignum_double_sm2 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
237 301
238// Extended Montgomery reduce, returning results in input-output buffer 302// Extended Montgomery reduce, returning results in input-output buffer
239// Inputs z[2*k], m[k], w; outputs function return (extra result bit) and z[2*k] 303// Inputs z[2*k], m[k], w; outputs function return (extra result bit) and z[2*k]
240extern uint64_t bignum_emontredc (uint64_t k, uint64_t *z, uint64_t *m, uint64_t w); 304extern uint64_t bignum_emontredc (uint64_t k, uint64_t *z, const uint64_t *m, uint64_t w);
241 305
242// Extended Montgomery reduce in 8-digit blocks, results in input-output buffer 306// Extended Montgomery reduce in 8-digit blocks, results in input-output buffer
243// Inputs z[2*k], m[k], w; outputs function return (extra result bit) and z[2*k] 307// Inputs z[2*k], m[k], w; outputs function return (extra result bit) and z[2*k]
244extern uint64_t bignum_emontredc_8n (uint64_t k, uint64_t *z, uint64_t *m, uint64_t w); 308extern uint64_t bignum_emontredc_8n (uint64_t k, uint64_t *z, const uint64_t *m, uint64_t w);
309// Inputs z[2*k], m[k], w; outputs function return (extra result bit) and z[2*k]
310// Temporary buffer m_precalc[12*(k/4-1)]
311extern uint64_t bignum_emontredc_8n_cdiff (uint64_t k, uint64_t *z, const uint64_t *m,
312 uint64_t w, uint64_t *m_precalc);
245 313
246// Test bignums for equality, x = y 314// Test bignums for equality, x = y
247// Inputs x[m], y[n]; output function return 315// Inputs x[m], y[n]; output function return
248extern uint64_t bignum_eq (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y); 316extern uint64_t bignum_eq (uint64_t m, const uint64_t *x, uint64_t n, const uint64_t *y);
249 317
250// Test bignum for even-ness 318// Test bignum for even-ness
251// Input x[k]; output function return 319// Input x[k]; output function return
252extern uint64_t bignum_even (uint64_t k, uint64_t *x); 320extern uint64_t bignum_even (uint64_t k, const uint64_t *x);
253 321
254// Convert 4-digit (256-bit) bignum from big-endian bytes 322// Convert 4-digit (256-bit) bignum from big-endian bytes
255// Input x[32] (bytes); output z[4] 323// Input x[32] (bytes); output z[4]
256extern void bignum_frombebytes_4 (uint64_t z[static 4], uint8_t x[static 32]); 324extern void bignum_frombebytes_4 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint8_t x[S2N_BIGNUM_STATIC 32]);
257 325
258// Convert 6-digit (384-bit) bignum from big-endian bytes 326// Convert 6-digit (384-bit) bignum from big-endian bytes
259// Input x[48] (bytes); output z[6] 327// Input x[48] (bytes); output z[6]
260extern void bignum_frombebytes_6 (uint64_t z[static 6], uint8_t x[static 48]); 328extern void bignum_frombebytes_6 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint8_t x[S2N_BIGNUM_STATIC 48]);
261 329
262// Convert 4-digit (256-bit) bignum from little-endian bytes 330// Convert 4-digit (256-bit) bignum from little-endian bytes
263// Input x[32] (bytes); output z[4] 331// Input x[32] (bytes); output z[4]
264extern void bignum_fromlebytes_4 (uint64_t z[static 4], uint8_t x[static 32]); 332extern void bignum_fromlebytes_4 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint8_t x[S2N_BIGNUM_STATIC 32]);
265 333
266// Convert 6-digit (384-bit) bignum from little-endian bytes 334// Convert 6-digit (384-bit) bignum from little-endian bytes
267// Input x[48] (bytes); output z[6] 335// Input x[48] (bytes); output z[6]
268extern void bignum_fromlebytes_6 (uint64_t z[static 6], uint8_t x[static 48]); 336extern void bignum_fromlebytes_6 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint8_t x[S2N_BIGNUM_STATIC 48]);
269 337
270// Convert little-endian bytes to 9-digit 528-bit bignum 338// Convert little-endian bytes to 9-digit 528-bit bignum
271// Input x[66] (bytes); output z[9] 339// Input x[66] (bytes); output z[9]
272extern void bignum_fromlebytes_p521 (uint64_t z[static 9],uint8_t x[static 66]); 340extern void bignum_fromlebytes_p521 (uint64_t z[S2N_BIGNUM_STATIC 9],const uint8_t x[S2N_BIGNUM_STATIC 66]);
273 341
274// Compare bignums, x >= y 342// Compare bignums, x >= y
275// Inputs x[m], y[n]; output function return 343// Inputs x[m], y[n]; output function return
276extern uint64_t bignum_ge (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y); 344extern uint64_t bignum_ge (uint64_t m, const uint64_t *x, uint64_t n, const uint64_t *y);
277 345
278// Compare bignums, x > y 346// Compare bignums, x > y
279// Inputs x[m], y[n]; output function return 347// Inputs x[m], y[n]; output function return
280extern uint64_t bignum_gt (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y); 348extern uint64_t bignum_gt (uint64_t m, const uint64_t *x, uint64_t n, const uint64_t *y);
281 349
282// Halve modulo p_256, z := (x / 2) mod p_256, assuming x reduced 350// Halve modulo p_256, z := (x / 2) mod p_256, assuming x reduced
283// Input x[4]; output z[4] 351// Input x[4]; output z[4]
284extern void bignum_half_p256 (uint64_t z[static 4], uint64_t x[static 4]); 352extern void bignum_half_p256 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
285 353
286// Halve modulo p_256k1, z := (x / 2) mod p_256k1, assuming x reduced 354// Halve modulo p_256k1, z := (x / 2) mod p_256k1, assuming x reduced
287// Input x[4]; output z[4] 355// Input x[4]; output z[4]
288extern void bignum_half_p256k1 (uint64_t z[static 4], uint64_t x[static 4]); 356extern void bignum_half_p256k1 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
289 357
290// Halve modulo p_384, z := (x / 2) mod p_384, assuming x reduced 358// Halve modulo p_384, z := (x / 2) mod p_384, assuming x reduced
291// Input x[6]; output z[6] 359// Input x[6]; output z[6]
292extern void bignum_half_p384 (uint64_t z[static 6], uint64_t x[static 6]); 360extern void bignum_half_p384 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
293 361
294// Halve modulo p_521, z := (x / 2) mod p_521, assuming x reduced 362// Halve modulo p_521, z := (x / 2) mod p_521, assuming x reduced
295// Input x[9]; output z[9] 363// Input x[9]; output z[9]
296extern void bignum_half_p521 (uint64_t z[static 9], uint64_t x[static 9]); 364extern void bignum_half_p521 (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9]);
365
366// Halve modulo p_sm2, z := (x / 2) mod p_sm2, assuming x reduced
367// Input x[4]; output z[4]
368extern void bignum_half_sm2 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
369
370// Modular inverse modulo p_25519 = 2^255 - 19
371// Input x[4]; output z[4]
372extern void bignum_inv_p25519(uint64_t z[S2N_BIGNUM_STATIC 4],const uint64_t x[S2N_BIGNUM_STATIC 4]);
373
374// Modular inverse modulo p_256 = 2^256 - 2^224 + 2^192 + 2^96 - 1
375// Input x[4]; output z[4]
376extern void bignum_inv_p256(uint64_t z[S2N_BIGNUM_STATIC 4],const uint64_t x[S2N_BIGNUM_STATIC 4]);
377
378// Modular inverse modulo p_384 = 2^384 - 2^128 - 2^96 + 2^32 - 1
379// Input x[6]; output z[6]
380extern void bignum_inv_p384(uint64_t z[S2N_BIGNUM_STATIC 6],const uint64_t x[S2N_BIGNUM_STATIC 6]);
381
382// Modular inverse modulo p_521 = 2^521 - 1
383// Input x[9]; output z[9]
384extern void bignum_inv_p521(uint64_t z[S2N_BIGNUM_STATIC 9],const uint64_t x[S2N_BIGNUM_STATIC 9]);
385
386// Modular inverse modulo p_sm2 = 2^256 - 2^224 - 2^96 + 2^64 - 1
387// Input x[4]; output z[4]
388extern void bignum_inv_sm2(uint64_t z[S2N_BIGNUM_STATIC 4],const uint64_t x[S2N_BIGNUM_STATIC 4]);
389
390// Inverse square root modulo p_25519
391// Input x[4]; output function return (Legendre symbol) and z[4]
392extern int64_t bignum_invsqrt_p25519(uint64_t z[S2N_BIGNUM_STATIC 4],const uint64_t x[S2N_BIGNUM_STATIC 4]);
393extern int64_t bignum_invsqrt_p25519_alt(uint64_t z[S2N_BIGNUM_STATIC 4],const uint64_t x[S2N_BIGNUM_STATIC 4]);
297 394
298// Test bignum for zero-ness, x = 0 395// Test bignum for zero-ness, x = 0
299// Input x[k]; output function return 396// Input x[k]; output function return
300extern uint64_t bignum_iszero (uint64_t k, uint64_t *x); 397extern uint64_t bignum_iszero (uint64_t k, const uint64_t *x);
301 398
302// Multiply z := x * y 399// Multiply z := x * y
303// Inputs x[16], y[16]; output z[32]; temporary buffer t[>=32] 400// Inputs x[16], y[16]; output z[32]; temporary buffer t[>=32]
304extern void bignum_kmul_16_32 (uint64_t z[static 32], uint64_t x[static 16], uint64_t y[static 16], uint64_t t[static 32]); 401extern void bignum_kmul_16_32 (uint64_t z[S2N_BIGNUM_STATIC 32], const uint64_t x[S2N_BIGNUM_STATIC 16], const uint64_t y[S2N_BIGNUM_STATIC 16], uint64_t t[S2N_BIGNUM_STATIC 32]);
305 402
306// Multiply z := x * y 403// Multiply z := x * y
307// Inputs x[32], y[32]; output z[64]; temporary buffer t[>=96] 404// Inputs x[32], y[32]; output z[64]; temporary buffer t[>=96]
308extern void bignum_kmul_32_64 (uint64_t z[static 64], uint64_t x[static 32], uint64_t y[static 32], uint64_t t[static 96]); 405extern void bignum_kmul_32_64 (uint64_t z[S2N_BIGNUM_STATIC 64], const uint64_t x[S2N_BIGNUM_STATIC 32], const uint64_t y[S2N_BIGNUM_STATIC 32], uint64_t t[S2N_BIGNUM_STATIC 96]);
309 406
310// Square, z := x^2 407// Square, z := x^2
311// Input x[16]; output z[32]; temporary buffer t[>=24] 408// Input x[16]; output z[32]; temporary buffer t[>=24]
312extern void bignum_ksqr_16_32 (uint64_t z[static 32], uint64_t x[static 16], uint64_t t[static 24]); 409extern void bignum_ksqr_16_32 (uint64_t z[S2N_BIGNUM_STATIC 32], const uint64_t x[S2N_BIGNUM_STATIC 16], uint64_t t[S2N_BIGNUM_STATIC 24]);
313 410
314// Square, z := x^2 411// Square, z := x^2
315// Input x[32]; output z[64]; temporary buffer t[>=72] 412// Input x[32]; output z[64]; temporary buffer t[>=72]
316extern void bignum_ksqr_32_64 (uint64_t z[static 64], uint64_t x[static 32], uint64_t t[static 72]); 413extern void bignum_ksqr_32_64 (uint64_t z[S2N_BIGNUM_STATIC 64], const uint64_t x[S2N_BIGNUM_STATIC 32], uint64_t t[S2N_BIGNUM_STATIC 72]);
317 414
318// Compare bignums, x <= y 415// Compare bignums, x <= y
319// Inputs x[m], y[n]; output function return 416// Inputs x[m], y[n]; output function return
320extern uint64_t bignum_le (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y); 417extern uint64_t bignum_le (uint64_t m, const uint64_t *x, uint64_t n, const uint64_t *y);
321 418
322// Convert 4-digit (256-bit) bignum to/from little-endian form 419// Convert 4-digit (256-bit) bignum to/from little-endian form
323// Input x[4]; output z[4] 420// Input x[4]; output z[4]
324extern void bignum_littleendian_4 (uint64_t z[static 4], uint64_t x[static 4]); 421extern void bignum_littleendian_4 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
325 422
326// Convert 6-digit (384-bit) bignum to/from little-endian form 423// Convert 6-digit (384-bit) bignum to/from little-endian form
327// Input x[6]; output z[6] 424// Input x[6]; output z[6]
328extern void bignum_littleendian_6 (uint64_t z[static 6], uint64_t x[static 6]); 425extern void bignum_littleendian_6 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
329 426
330// Compare bignums, x < y 427// Compare bignums, x < y
331// Inputs x[m], y[n]; output function return 428// Inputs x[m], y[n]; output function return
332extern uint64_t bignum_lt (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y); 429extern uint64_t bignum_lt (uint64_t m, const uint64_t *x, uint64_t n, const uint64_t *y);
333 430
334// Multiply-add, z := z + x * y 431// Multiply-add, z := z + x * y
335// Inputs x[m], y[n]; outputs function return (carry-out) and z[k] 432// Inputs x[m], y[n]; outputs function return (carry-out) and z[k]
336extern uint64_t bignum_madd (uint64_t k, uint64_t *z, uint64_t m, uint64_t *x, uint64_t n, uint64_t *y); 433extern uint64_t bignum_madd (uint64_t k, uint64_t *z, uint64_t m, const uint64_t *x, uint64_t n, const uint64_t *y);
434
435// Multiply-add modulo the order of the curve25519/edwards25519 basepoint
436// Inputs x[4], y[4], c[4]; output z[4]
437extern void bignum_madd_n25519 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4], const uint64_t c[S2N_BIGNUM_STATIC 4]);
438extern void bignum_madd_n25519_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4], const uint64_t c[S2N_BIGNUM_STATIC 4]);
439
440// Reduce modulo group order, z := x mod m_25519
441// Input x[4]; output z[4]
442extern void bignum_mod_m25519_4 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
443
444// Reduce modulo basepoint order, z := x mod n_25519
445// Input x[k]; output z[4]
446extern void bignum_mod_n25519 (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t k, const uint64_t *x);
447
448// Reduce modulo basepoint order, z := x mod n_25519
449// Input x[4]; output z[4]
450extern void bignum_mod_n25519_4 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
337 451
338// Reduce modulo group order, z := x mod n_256 452// Reduce modulo group order, z := x mod n_256
339// Input x[k]; output z[4] 453// Input x[k]; output z[4]
340extern void bignum_mod_n256 (uint64_t z[static 4], uint64_t k, uint64_t *x); 454extern void bignum_mod_n256 (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t k, const uint64_t *x);
341extern void bignum_mod_n256_alt (uint64_t z[static 4], uint64_t k, uint64_t *x); 455extern void bignum_mod_n256_alt (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t k, const uint64_t *x);
342 456
343// Reduce modulo group order, z := x mod n_256 457// Reduce modulo group order, z := x mod n_256
344// Input x[4]; output z[4] 458// Input x[4]; output z[4]
345extern void bignum_mod_n256_4 (uint64_t z[static 4], uint64_t x[static 4]); 459extern void bignum_mod_n256_4 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
346 460
347// Reduce modulo group order, z := x mod n_256k1 461// Reduce modulo group order, z := x mod n_256k1
348// Input x[4]; output z[4] 462// Input x[4]; output z[4]
349extern void bignum_mod_n256k1_4 (uint64_t z[static 4], uint64_t x[static 4]); 463extern void bignum_mod_n256k1_4 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
350 464
351// Reduce modulo group order, z := x mod n_384 465// Reduce modulo group order, z := x mod n_384
352// Input x[k]; output z[6] 466// Input x[k]; output z[6]
353extern void bignum_mod_n384 (uint64_t z[static 6], uint64_t k, uint64_t *x); 467extern void bignum_mod_n384 (uint64_t z[S2N_BIGNUM_STATIC 6], uint64_t k, const uint64_t *x);
354extern void bignum_mod_n384_alt (uint64_t z[static 6], uint64_t k, uint64_t *x); 468extern void bignum_mod_n384_alt (uint64_t z[S2N_BIGNUM_STATIC 6], uint64_t k, const uint64_t *x);
355 469
356// Reduce modulo group order, z := x mod n_384 470// Reduce modulo group order, z := x mod n_384
357// Input x[6]; output z[6] 471// Input x[6]; output z[6]
358extern void bignum_mod_n384_6 (uint64_t z[static 6], uint64_t x[static 6]); 472extern void bignum_mod_n384_6 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
359 473
360// Reduce modulo group order, z := x mod n_521 474// Reduce modulo group order, z := x mod n_521
361// Input x[9]; output z[9] 475// Input x[9]; output z[9]
362extern void bignum_mod_n521_9 (uint64_t z[static 9], uint64_t x[static 9]); 476extern void bignum_mod_n521_9 (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9]);
363extern void bignum_mod_n521_9_alt (uint64_t z[static 9], uint64_t x[static 9]); 477extern void bignum_mod_n521_9_alt (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9]);
478
479// Reduce modulo group order, z := x mod n_sm2
480// Input x[k]; output z[4]
481extern void bignum_mod_nsm2 (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t k, const uint64_t *x);
482extern void bignum_mod_nsm2_alt (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t k, const uint64_t *x);
483
484// Reduce modulo group order, z := x mod n_sm2
485// Input x[4]; output z[4]
486extern void bignum_mod_nsm2_4 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
364 487
365// Reduce modulo field characteristic, z := x mod p_25519 488// Reduce modulo field characteristic, z := x mod p_25519
366// Input x[4]; output z[4] 489// Input x[4]; output z[4]
367extern void bignum_mod_p25519_4 (uint64_t z[static 4], uint64_t x[static 4]); 490extern void bignum_mod_p25519_4 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
368 491
369// Reduce modulo field characteristic, z := x mod p_256 492// Reduce modulo field characteristic, z := x mod p_256
370// Input x[k]; output z[4] 493// Input x[k]; output z[4]
371extern void bignum_mod_p256 (uint64_t z[static 4], uint64_t k, uint64_t *x); 494extern void bignum_mod_p256 (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t k, const uint64_t *x);
372extern void bignum_mod_p256_alt (uint64_t z[static 4], uint64_t k, uint64_t *x); 495extern void bignum_mod_p256_alt (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t k, const uint64_t *x);
373 496
374// Reduce modulo field characteristic, z := x mod p_256 497// Reduce modulo field characteristic, z := x mod p_256
375// Input x[4]; output z[4] 498// Input x[4]; output z[4]
376extern void bignum_mod_p256_4 (uint64_t z[static 4], uint64_t x[static 4]); 499extern void bignum_mod_p256_4 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
377 500
378// Reduce modulo field characteristic, z := x mod p_256k1 501// Reduce modulo field characteristic, z := x mod p_256k1
379// Input x[4]; output z[4] 502// Input x[4]; output z[4]
380extern void bignum_mod_p256k1_4 (uint64_t z[static 4], uint64_t x[static 4]); 503extern void bignum_mod_p256k1_4 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
381 504
382// Reduce modulo field characteristic, z := x mod p_384 505// Reduce modulo field characteristic, z := x mod p_384
383// Input x[k]; output z[6] 506// Input x[k]; output z[6]
384extern void bignum_mod_p384 (uint64_t z[static 6], uint64_t k, uint64_t *x); 507extern void bignum_mod_p384 (uint64_t z[S2N_BIGNUM_STATIC 6], uint64_t k, const uint64_t *x);
385extern void bignum_mod_p384_alt (uint64_t z[static 6], uint64_t k, uint64_t *x); 508extern void bignum_mod_p384_alt (uint64_t z[S2N_BIGNUM_STATIC 6], uint64_t k, const uint64_t *x);
386 509
387// Reduce modulo field characteristic, z := x mod p_384 510// Reduce modulo field characteristic, z := x mod p_384
388// Input x[6]; output z[6] 511// Input x[6]; output z[6]
389extern void bignum_mod_p384_6 (uint64_t z[static 6], uint64_t x[static 6]); 512extern void bignum_mod_p384_6 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
390 513
391// Reduce modulo field characteristic, z := x mod p_521 514// Reduce modulo field characteristic, z := x mod p_521
392// Input x[9]; output z[9] 515// Input x[9]; output z[9]
393extern void bignum_mod_p521_9 (uint64_t z[static 9], uint64_t x[static 9]); 516extern void bignum_mod_p521_9 (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9]);
517
518// Reduce modulo field characteristic, z := x mod p_sm2
519// Input x[k]; output z[4]
520extern void bignum_mod_sm2 (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t k, const uint64_t *x);
521
522// Reduce modulo field characteristic, z := x mod p_sm2
523// Input x[4]; output z[4]
524extern void bignum_mod_sm2_4 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
394 525
395// Add modulo m, z := (x + y) mod m, assuming x and y reduced 526// Add modulo m, z := (x + y) mod m, assuming x and y reduced
396// Inputs x[k], y[k], m[k]; output z[k] 527// Inputs x[k], y[k], m[k]; output z[k]
397extern void bignum_modadd (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y, uint64_t *m); 528extern void bignum_modadd (uint64_t k, uint64_t *z, const uint64_t *x, const uint64_t *y, const uint64_t *m);
398 529
399// Double modulo m, z := (2 * x) mod m, assuming x reduced 530// Double modulo m, z := (2 * x) mod m, assuming x reduced
400// Inputs x[k], m[k]; output z[k] 531// Inputs x[k], m[k]; output z[k]
401extern void bignum_moddouble (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *m); 532extern void bignum_moddouble (uint64_t k, uint64_t *z, const uint64_t *x, const uint64_t *m);
533
534// Modular exponentiation for arbitrary odd modulus, z := (a^p) mod m
535// Inputs a[k], p[k], m[k]; output z[k], temporary buffer t[>=3*k]
536extern void bignum_modexp(uint64_t k,uint64_t *z, const uint64_t *a,const uint64_t *p,const uint64_t *m,uint64_t *t);
402 537
403// Compute "modification" constant z := 2^{64k} mod m 538// Compute "modification" constant z := 2^{64k} mod m
404// Input m[k]; output z[k]; temporary buffer t[>=k] 539// Input m[k]; output z[k]; temporary buffer t[>=k]
405extern void bignum_modifier (uint64_t k, uint64_t *z, uint64_t *m, uint64_t *t); 540extern void bignum_modifier (uint64_t k, uint64_t *z, const uint64_t *m, uint64_t *t);
406 541
407// Invert modulo m, z = (1/a) mod b, assuming b is an odd number > 1, a coprime to b 542// Invert modulo m, z = (1/a) mod b, assuming b is an odd number > 1, a coprime to b
408// Inputs a[k], b[k]; output z[k]; temporary buffer t[>=3*k] 543// Inputs a[k], b[k]; output z[k]; temporary buffer t[>=3*k]
409extern void bignum_modinv (uint64_t k, uint64_t *z, uint64_t *a, uint64_t *b, uint64_t *t); 544extern void bignum_modinv (uint64_t k, uint64_t *z, const uint64_t *a, const uint64_t *b, uint64_t *t);
410 545
411// Optionally negate modulo m, z := (-x) mod m (if p nonzero) or z := x (if p zero), assuming x reduced 546// Optionally negate modulo m, z := (-x) mod m (if p nonzero) or z := x (if p zero), assuming x reduced
412// Inputs p, x[k], m[k]; output z[k] 547// Inputs p, x[k], m[k]; output z[k]
413extern void bignum_modoptneg (uint64_t k, uint64_t *z, uint64_t p, uint64_t *x, uint64_t *m); 548extern void bignum_modoptneg (uint64_t k, uint64_t *z, uint64_t p, const uint64_t *x, const uint64_t *m);
414 549
415// Subtract modulo m, z := (x - y) mod m, assuming x and y reduced 550// Subtract modulo m, z := (x - y) mod m, assuming x and y reduced
416// Inputs x[k], y[k], m[k]; output z[k] 551// Inputs x[k], y[k], m[k]; output z[k]
417extern void bignum_modsub (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y, uint64_t *m); 552extern void bignum_modsub (uint64_t k, uint64_t *z, const uint64_t *x, const uint64_t *y, const uint64_t *m);
418 553
419// Compute "montification" constant z := 2^{128k} mod m 554// Compute "montification" constant z := 2^{128k} mod m
420// Input m[k]; output z[k]; temporary buffer t[>=k] 555// Input m[k]; output z[k]; temporary buffer t[>=k]
421extern void bignum_montifier (uint64_t k, uint64_t *z, uint64_t *m, uint64_t *t); 556extern void bignum_montifier (uint64_t k, uint64_t *z, const uint64_t *m, uint64_t *t);
557
558// Montgomery inverse modulo p_256 = 2^256 - 2^224 + 2^192 + 2^96 - 1
559// Input x[4]; output z[4]
560extern void bignum_montinv_p256(uint64_t z[S2N_BIGNUM_STATIC 4],const uint64_t x[S2N_BIGNUM_STATIC 4]);
561
562// Montgomery inverse modulo p_384 = 2^384 - 2^128 - 2^96 + 2^32 - 1
563// Input x[6]; output z[6]
564extern void bignum_montinv_p384(uint64_t z[S2N_BIGNUM_STATIC 6],const uint64_t x[S2N_BIGNUM_STATIC 6]);
565
566// Montgomery inverse modulo p_sm2 = 2^256 - 2^224 - 2^96 + 2^64 - 1
567// Input x[4]; output z[4]
568extern void bignum_montinv_sm2(uint64_t z[S2N_BIGNUM_STATIC 4],const uint64_t x[S2N_BIGNUM_STATIC 4]);
422 569
423// Montgomery multiply, z := (x * y / 2^{64k}) mod m 570// Montgomery multiply, z := (x * y / 2^{64k}) mod m
424// Inputs x[k], y[k], m[k]; output z[k] 571// Inputs x[k], y[k], m[k]; output z[k]
425extern void bignum_montmul (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y, uint64_t *m); 572extern void bignum_montmul (uint64_t k, uint64_t *z, const uint64_t *x, const uint64_t *y, const uint64_t *m);
426 573
427// Montgomery multiply, z := (x * y / 2^256) mod p_256 574// Montgomery multiply, z := (x * y / 2^256) mod p_256
428// Inputs x[4], y[4]; output z[4] 575// Inputs x[4], y[4]; output z[4]
429extern void bignum_montmul_p256 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]); 576extern void bignum_montmul_p256 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
430extern void bignum_montmul_p256_alt (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]); 577extern void bignum_montmul_p256_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
431 578
432// Montgomery multiply, z := (x * y / 2^256) mod p_256k1 579// Montgomery multiply, z := (x * y / 2^256) mod p_256k1
433// Inputs x[4], y[4]; output z[4] 580// Inputs x[4], y[4]; output z[4]
434extern void bignum_montmul_p256k1 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]); 581extern void bignum_montmul_p256k1 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
435extern void bignum_montmul_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]); 582extern void bignum_montmul_p256k1_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
436 583
437// Montgomery multiply, z := (x * y / 2^384) mod p_384 584// Montgomery multiply, z := (x * y / 2^384) mod p_384
438// Inputs x[6], y[6]; output z[6] 585// Inputs x[6], y[6]; output z[6]
439extern void bignum_montmul_p384 (uint64_t z[static 6], uint64_t x[static 6], uint64_t y[static 6]); 586extern void bignum_montmul_p384 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6], const uint64_t y[S2N_BIGNUM_STATIC 6]);
440extern void bignum_montmul_p384_alt (uint64_t z[static 6], uint64_t x[static 6], uint64_t y[static 6]); 587extern void bignum_montmul_p384_alt (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6], const uint64_t y[S2N_BIGNUM_STATIC 6]);
441 588
442// Montgomery multiply, z := (x * y / 2^576) mod p_521 589// Montgomery multiply, z := (x * y / 2^576) mod p_521
443// Inputs x[9], y[9]; output z[9] 590// Inputs x[9], y[9]; output z[9]
444extern void bignum_montmul_p521 (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]); 591extern void bignum_montmul_p521 (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9], const uint64_t y[S2N_BIGNUM_STATIC 9]);
445extern void bignum_montmul_p521_alt (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]); 592extern void bignum_montmul_p521_alt (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9], const uint64_t y[S2N_BIGNUM_STATIC 9]);
593
594// Montgomery multiply, z := (x * y / 2^256) mod p_sm2
595// Inputs x[4], y[4]; output z[4]
596extern void bignum_montmul_sm2 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
597extern void bignum_montmul_sm2_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
446 598
447// Montgomery reduce, z := (x' / 2^{64p}) MOD m 599// Montgomery reduce, z := (x' / 2^{64p}) MOD m
448// Inputs x[n], m[k], p; output z[k] 600// Inputs x[n], m[k], p; output z[k]
449extern void bignum_montredc (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t *m, uint64_t p); 601extern void bignum_montredc (uint64_t k, uint64_t *z, uint64_t n, const uint64_t *x, const uint64_t *m, uint64_t p);
450 602
451// Montgomery square, z := (x^2 / 2^{64k}) mod m 603// Montgomery square, z := (x^2 / 2^{64k}) mod m
452// Inputs x[k], m[k]; output z[k] 604// Inputs x[k], m[k]; output z[k]
453extern void bignum_montsqr (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *m); 605extern void bignum_montsqr (uint64_t k, uint64_t *z, const uint64_t *x, const uint64_t *m);
454 606
455// Montgomery square, z := (x^2 / 2^256) mod p_256 607// Montgomery square, z := (x^2 / 2^256) mod p_256
456// Input x[4]; output z[4] 608// Input x[4]; output z[4]
457extern void bignum_montsqr_p256 (uint64_t z[static 4], uint64_t x[static 4]); 609extern void bignum_montsqr_p256 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
458extern void bignum_montsqr_p256_alt (uint64_t z[static 4], uint64_t x[static 4]); 610extern void bignum_montsqr_p256_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
459 611
460// Montgomery square, z := (x^2 / 2^256) mod p_256k1 612// Montgomery square, z := (x^2 / 2^256) mod p_256k1
461// Input x[4]; output z[4] 613// Input x[4]; output z[4]
462extern void bignum_montsqr_p256k1 (uint64_t z[static 4], uint64_t x[static 4]); 614extern void bignum_montsqr_p256k1 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
463extern void bignum_montsqr_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4]); 615extern void bignum_montsqr_p256k1_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
464 616
465// Montgomery square, z := (x^2 / 2^384) mod p_384 617// Montgomery square, z := (x^2 / 2^384) mod p_384
466// Input x[6]; output z[6] 618// Input x[6]; output z[6]
467extern void bignum_montsqr_p384 (uint64_t z[static 6], uint64_t x[static 6]); 619extern void bignum_montsqr_p384 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
468extern void bignum_montsqr_p384_alt (uint64_t z[static 6], uint64_t x[static 6]); 620extern void bignum_montsqr_p384_alt (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
469 621
470// Montgomery square, z := (x^2 / 2^576) mod p_521 622// Montgomery square, z := (x^2 / 2^576) mod p_521
471// Input x[9]; output z[9] 623// Input x[9]; output z[9]
472extern void bignum_montsqr_p521 (uint64_t z[static 9], uint64_t x[static 9]); 624extern void bignum_montsqr_p521 (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9]);
473extern void bignum_montsqr_p521_alt (uint64_t z[static 9], uint64_t x[static 9]); 625extern void bignum_montsqr_p521_alt (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9]);
626
627// Montgomery square, z := (x^2 / 2^256) mod p_sm2
628// Input x[4]; output z[4]
629extern void bignum_montsqr_sm2 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
630extern void bignum_montsqr_sm2_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
474 631
475// Multiply z := x * y 632// Multiply z := x * y
476// Inputs x[m], y[n]; output z[k] 633// Inputs x[m], y[n]; output z[k]
477extern void bignum_mul (uint64_t k, uint64_t *z, uint64_t m, uint64_t *x, uint64_t n, uint64_t *y); 634extern void bignum_mul (uint64_t k, uint64_t *z, uint64_t m, const uint64_t *x, uint64_t n, const uint64_t *y);
478 635
479// Multiply z := x * y 636// Multiply z := x * y
480// Inputs x[4], y[4]; output z[8] 637// Inputs x[4], y[4]; output z[8]
481extern void bignum_mul_4_8 (uint64_t z[static 8], uint64_t x[static 4], uint64_t y[static 4]); 638extern void bignum_mul_4_8 (uint64_t z[S2N_BIGNUM_STATIC 8], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
482extern void bignum_mul_4_8_alt (uint64_t z[static 8], uint64_t x[static 4], uint64_t y[static 4]); 639extern void bignum_mul_4_8_alt (uint64_t z[S2N_BIGNUM_STATIC 8], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
483 640
484// Multiply z := x * y 641// Multiply z := x * y
485// Inputs x[6], y[6]; output z[12] 642// Inputs x[6], y[6]; output z[12]
486extern void bignum_mul_6_12 (uint64_t z[static 12], uint64_t x[static 6], uint64_t y[static 6]); 643extern void bignum_mul_6_12 (uint64_t z[S2N_BIGNUM_STATIC 12], const uint64_t x[S2N_BIGNUM_STATIC 6], const uint64_t y[S2N_BIGNUM_STATIC 6]);
487extern void bignum_mul_6_12_alt (uint64_t z[static 12], uint64_t x[static 6], uint64_t y[static 6]); 644extern void bignum_mul_6_12_alt (uint64_t z[S2N_BIGNUM_STATIC 12], const uint64_t x[S2N_BIGNUM_STATIC 6], const uint64_t y[S2N_BIGNUM_STATIC 6]);
488 645
489// Multiply z := x * y 646// Multiply z := x * y
490// Inputs x[8], y[8]; output z[16] 647// Inputs x[8], y[8]; output z[16]
491extern void bignum_mul_8_16 (uint64_t z[static 16], uint64_t x[static 8], uint64_t y[static 8]); 648extern void bignum_mul_8_16 (uint64_t z[S2N_BIGNUM_STATIC 16], const uint64_t x[S2N_BIGNUM_STATIC 8], const uint64_t y[S2N_BIGNUM_STATIC 8]);
492extern void bignum_mul_8_16_alt (uint64_t z[static 16], uint64_t x[static 8], uint64_t y[static 8]); 649extern void bignum_mul_8_16_alt (uint64_t z[S2N_BIGNUM_STATIC 16], const uint64_t x[S2N_BIGNUM_STATIC 8], const uint64_t y[S2N_BIGNUM_STATIC 8]);
493 650
494// Multiply modulo p_25519, z := (x * y) mod p_25519 651// Multiply modulo p_25519, z := (x * y) mod p_25519
495// Inputs x[4], y[4]; output z[4] 652// Inputs x[4], y[4]; output z[4]
496extern void bignum_mul_p25519 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]); 653extern void bignum_mul_p25519 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
497extern void bignum_mul_p25519_alt (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]); 654extern void bignum_mul_p25519_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
498 655
499// Multiply modulo p_256k1, z := (x * y) mod p_256k1 656// Multiply modulo p_256k1, z := (x * y) mod p_256k1
500// Inputs x[4], y[4]; output z[4] 657// Inputs x[4], y[4]; output z[4]
501extern void bignum_mul_p256k1 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]); 658extern void bignum_mul_p256k1 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
502extern void bignum_mul_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]); 659extern void bignum_mul_p256k1_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
503 660
504// Multiply modulo p_521, z := (x * y) mod p_521, assuming x and y reduced 661// Multiply modulo p_521, z := (x * y) mod p_521, assuming x and y reduced
505// Inputs x[9], y[9]; output z[9] 662// Inputs x[9], y[9]; output z[9]
506extern void bignum_mul_p521 (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]); 663extern void bignum_mul_p521 (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9], const uint64_t y[S2N_BIGNUM_STATIC 9]);
507extern void bignum_mul_p521_alt (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]); 664extern void bignum_mul_p521_alt (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9], const uint64_t y[S2N_BIGNUM_STATIC 9]);
508 665
509// Multiply bignum by 10 and add word: z := 10 * z + d 666// Multiply bignum by 10 and add word: z := 10 * z + d
510// Inputs z[k], d; outputs function return (carry) and z[k] 667// Inputs z[k], d; outputs function return (carry) and z[k]
@@ -512,55 +669,59 @@ extern uint64_t bignum_muladd10 (uint64_t k, uint64_t *z, uint64_t d);
512 669
513// Multiplex/select z := x (if p nonzero) or z := y (if p zero) 670// Multiplex/select z := x (if p nonzero) or z := y (if p zero)
514// Inputs p, x[k], y[k]; output z[k] 671// Inputs p, x[k], y[k]; output z[k]
515extern void bignum_mux (uint64_t p, uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y); 672extern void bignum_mux (uint64_t p, uint64_t k, uint64_t *z, const uint64_t *x, const uint64_t *y);
516 673
517// 256-bit multiplex/select z := x (if p nonzero) or z := y (if p zero) 674// 256-bit multiplex/select z := x (if p nonzero) or z := y (if p zero)
518// Inputs p, x[4], y[4]; output z[4] 675// Inputs p, x[4], y[4]; output z[4]
519extern void bignum_mux_4 (uint64_t p, uint64_t z[static 4],uint64_t x[static 4], uint64_t y[static 4]); 676extern void bignum_mux_4 (uint64_t p, uint64_t z[S2N_BIGNUM_STATIC 4],const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
520 677
521// 384-bit multiplex/select z := x (if p nonzero) or z := y (if p zero) 678// 384-bit multiplex/select z := x (if p nonzero) or z := y (if p zero)
522// Inputs p, x[6], y[6]; output z[6] 679// Inputs p, x[6], y[6]; output z[6]
523extern void bignum_mux_6 (uint64_t p, uint64_t z[static 6],uint64_t x[static 6], uint64_t y[static 6]); 680extern void bignum_mux_6 (uint64_t p, uint64_t z[S2N_BIGNUM_STATIC 6],const uint64_t x[S2N_BIGNUM_STATIC 6], const uint64_t y[S2N_BIGNUM_STATIC 6]);
524 681
525// Select element from 16-element table, z := xs[k*i] 682// Select element from 16-element table, z := xs[k*i]
526// Inputs xs[16*k], i; output z[k] 683// Inputs xs[16*k], i; output z[k]
527extern void bignum_mux16 (uint64_t k, uint64_t *z, uint64_t *xs, uint64_t i); 684extern void bignum_mux16 (uint64_t k, uint64_t *z, const uint64_t *xs, uint64_t i);
528 685
529// Negate modulo p_25519, z := (-x) mod p_25519, assuming x reduced 686// Negate modulo p_25519, z := (-x) mod p_25519, assuming x reduced
530// Input x[4]; output z[4] 687// Input x[4]; output z[4]
531extern void bignum_neg_p25519 (uint64_t z[static 4], uint64_t x[static 4]); 688extern void bignum_neg_p25519 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
532 689
533// Negate modulo p_256, z := (-x) mod p_256, assuming x reduced 690// Negate modulo p_256, z := (-x) mod p_256, assuming x reduced
534// Input x[4]; output z[4] 691// Input x[4]; output z[4]
535extern void bignum_neg_p256 (uint64_t z[static 4], uint64_t x[static 4]); 692extern void bignum_neg_p256 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
536 693
537// Negate modulo p_256k1, z := (-x) mod p_256k1, assuming x reduced 694// Negate modulo p_256k1, z := (-x) mod p_256k1, assuming x reduced
538// Input x[4]; output z[4] 695// Input x[4]; output z[4]
539extern void bignum_neg_p256k1 (uint64_t z[static 4], uint64_t x[static 4]); 696extern void bignum_neg_p256k1 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
540 697
541// Negate modulo p_384, z := (-x) mod p_384, assuming x reduced 698// Negate modulo p_384, z := (-x) mod p_384, assuming x reduced
542// Input x[6]; output z[6] 699// Input x[6]; output z[6]
543extern void bignum_neg_p384 (uint64_t z[static 6], uint64_t x[static 6]); 700extern void bignum_neg_p384 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
544 701
545// Negate modulo p_521, z := (-x) mod p_521, assuming x reduced 702// Negate modulo p_521, z := (-x) mod p_521, assuming x reduced
546// Input x[9]; output z[9] 703// Input x[9]; output z[9]
547extern void bignum_neg_p521 (uint64_t z[static 9], uint64_t x[static 9]); 704extern void bignum_neg_p521 (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9]);
705
706// Negate modulo p_sm2, z := (-x) mod p_sm2, assuming x reduced
707// Input x[4]; output z[4]
708extern void bignum_neg_sm2 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
548 709
549// Negated modular inverse, z := (-1/x) mod 2^{64k} 710// Negated modular inverse, z := (-1/x) mod 2^{64k}
550// Input x[k]; output z[k] 711// Input x[k]; output z[k]
551extern void bignum_negmodinv (uint64_t k, uint64_t *z, uint64_t *x); 712extern void bignum_negmodinv (uint64_t k, uint64_t *z, const uint64_t *x);
552 713
553// Test bignum for nonzero-ness x =/= 0 714// Test bignum for nonzero-ness x =/= 0
554// Input x[k]; output function return 715// Input x[k]; output function return
555extern uint64_t bignum_nonzero (uint64_t k, uint64_t *x); 716extern uint64_t bignum_nonzero (uint64_t k, const uint64_t *x);
556 717
557// Test 256-bit bignum for nonzero-ness x =/= 0 718// Test 256-bit bignum for nonzero-ness x =/= 0
558// Input x[4]; output function return 719// Input x[4]; output function return
559extern uint64_t bignum_nonzero_4(uint64_t x[static 4]); 720extern uint64_t bignum_nonzero_4(const uint64_t x[S2N_BIGNUM_STATIC 4]);
560 721
561// Test 384-bit bignum for nonzero-ness x =/= 0 722// Test 384-bit bignum for nonzero-ness x =/= 0
562// Input x[6]; output function return 723// Input x[6]; output function return
563extern uint64_t bignum_nonzero_6(uint64_t x[static 6]); 724extern uint64_t bignum_nonzero_6(const uint64_t x[S2N_BIGNUM_STATIC 6]);
564 725
565// Normalize bignum in-place by shifting left till top bit is 1 726// Normalize bignum in-place by shifting left till top bit is 1
566// Input z[k]; outputs function return (bits shifted left) and z[k] 727// Input z[k]; outputs function return (bits shifted left) and z[k]
@@ -568,7 +729,7 @@ extern uint64_t bignum_normalize (uint64_t k, uint64_t *z);
568 729
569// Test bignum for odd-ness 730// Test bignum for odd-ness
570// Input x[k]; output function return 731// Input x[k]; output function return
571extern uint64_t bignum_odd (uint64_t k, uint64_t *x); 732extern uint64_t bignum_odd (uint64_t k, const uint64_t *x);
572 733
573// Convert single digit to bignum, z := n 734// Convert single digit to bignum, z := n
574// Input n; output z[k] 735// Input n; output z[k]
@@ -576,39 +737,43 @@ extern void bignum_of_word (uint64_t k, uint64_t *z, uint64_t n);
576 737
577// Optionally add, z := x + y (if p nonzero) or z := x (if p zero) 738// Optionally add, z := x + y (if p nonzero) or z := x (if p zero)
578// Inputs x[k], p, y[k]; outputs function return (carry-out) and z[k] 739// Inputs x[k], p, y[k]; outputs function return (carry-out) and z[k]
579extern uint64_t bignum_optadd (uint64_t k, uint64_t *z, uint64_t *x, uint64_t p, uint64_t *y); 740extern uint64_t bignum_optadd (uint64_t k, uint64_t *z, const uint64_t *x, uint64_t p, const uint64_t *y);
580 741
581// Optionally negate, z := -x (if p nonzero) or z := x (if p zero) 742// Optionally negate, z := -x (if p nonzero) or z := x (if p zero)
582// Inputs p, x[k]; outputs function return (nonzero input) and z[k] 743// Inputs p, x[k]; outputs function return (nonzero input) and z[k]
583extern uint64_t bignum_optneg (uint64_t k, uint64_t *z, uint64_t p, uint64_t *x); 744extern uint64_t bignum_optneg (uint64_t k, uint64_t *z, uint64_t p, const uint64_t *x);
584 745
585// Optionally negate modulo p_25519, z := (-x) mod p_25519 (if p nonzero) or z := x (if p zero), assuming x reduced 746// Optionally negate modulo p_25519, z := (-x) mod p_25519 (if p nonzero) or z := x (if p zero), assuming x reduced
586// Inputs p, x[4]; output z[4] 747// Inputs p, x[4]; output z[4]
587extern void bignum_optneg_p25519 (uint64_t z[static 4], uint64_t p, uint64_t x[static 4]); 748extern void bignum_optneg_p25519 (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t p, const uint64_t x[S2N_BIGNUM_STATIC 4]);
588 749
589// Optionally negate modulo p_256, z := (-x) mod p_256 (if p nonzero) or z := x (if p zero), assuming x reduced 750// Optionally negate modulo p_256, z := (-x) mod p_256 (if p nonzero) or z := x (if p zero), assuming x reduced
590// Inputs p, x[4]; output z[4] 751// Inputs p, x[4]; output z[4]
591extern void bignum_optneg_p256 (uint64_t z[static 4], uint64_t p, uint64_t x[static 4]); 752extern void bignum_optneg_p256 (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t p, const uint64_t x[S2N_BIGNUM_STATIC 4]);
592 753
593// Optionally negate modulo p_256k1, z := (-x) mod p_256k1 (if p nonzero) or z := x (if p zero), assuming x reduced 754// Optionally negate modulo p_256k1, z := (-x) mod p_256k1 (if p nonzero) or z := x (if p zero), assuming x reduced
594// Inputs p, x[4]; output z[4] 755// Inputs p, x[4]; output z[4]
595extern void bignum_optneg_p256k1 (uint64_t z[static 4], uint64_t p, uint64_t x[static 4]); 756extern void bignum_optneg_p256k1 (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t p, const uint64_t x[S2N_BIGNUM_STATIC 4]);
596 757
597// Optionally negate modulo p_384, z := (-x) mod p_384 (if p nonzero) or z := x (if p zero), assuming x reduced 758// Optionally negate modulo p_384, z := (-x) mod p_384 (if p nonzero) or z := x (if p zero), assuming x reduced
598// Inputs p, x[6]; output z[6] 759// Inputs p, x[6]; output z[6]
599extern void bignum_optneg_p384 (uint64_t z[static 6], uint64_t p, uint64_t x[static 6]); 760extern void bignum_optneg_p384 (uint64_t z[S2N_BIGNUM_STATIC 6], uint64_t p, const uint64_t x[S2N_BIGNUM_STATIC 6]);
600 761
601// Optionally negate modulo p_521, z := (-x) mod p_521 (if p nonzero) or z := x (if p zero), assuming x reduced 762// Optionally negate modulo p_521, z := (-x) mod p_521 (if p nonzero) or z := x (if p zero), assuming x reduced
602// Inputs p, x[9]; output z[9] 763// Inputs p, x[9]; output z[9]
603extern void bignum_optneg_p521 (uint64_t z[static 9], uint64_t p, uint64_t x[static 9]); 764extern void bignum_optneg_p521 (uint64_t z[S2N_BIGNUM_STATIC 9], uint64_t p, const uint64_t x[S2N_BIGNUM_STATIC 9]);
765
766// Optionally negate modulo p_sm2, z := (-x) mod p_sm2 (if p nonzero) or z := x (if p zero), assuming x reduced
767// Inputs p, x[4]; output z[4]
768extern void bignum_optneg_sm2 (uint64_t z[S2N_BIGNUM_STATIC 4], uint64_t p, const uint64_t x[S2N_BIGNUM_STATIC 4]);
604 769
605// Optionally subtract, z := x - y (if p nonzero) or z := x (if p zero) 770// Optionally subtract, z := x - y (if p nonzero) or z := x (if p zero)
606// Inputs x[k], p, y[k]; outputs function return (carry-out) and z[k] 771// Inputs x[k], p, y[k]; outputs function return (carry-out) and z[k]
607extern uint64_t bignum_optsub (uint64_t k, uint64_t *z, uint64_t *x, uint64_t p, uint64_t *y); 772extern uint64_t bignum_optsub (uint64_t k, uint64_t *z, const uint64_t *x, uint64_t p, const uint64_t *y);
608 773
609// Optionally subtract or add, z := x + sgn(p) * y interpreting p as signed 774// Optionally subtract or add, z := x + sgn(p) * y interpreting p as signed
610// Inputs x[k], p, y[k]; outputs function return (carry-out) and z[k] 775// Inputs x[k], p, y[k]; outputs function return (carry-out) and z[k]
611extern uint64_t bignum_optsubadd (uint64_t k, uint64_t *z, uint64_t *x, uint64_t p, uint64_t *y); 776extern uint64_t bignum_optsubadd (uint64_t k, uint64_t *z, const uint64_t *x, uint64_t p, const uint64_t *y);
612 777
613// Return bignum of power of 2, z := 2^n 778// Return bignum of power of 2, z := 2^n
614// Input n; output z[k] 779// Input n; output z[k]
@@ -616,216 +781,376 @@ extern void bignum_pow2 (uint64_t k, uint64_t *z, uint64_t n);
616 781
617// Shift bignum left by c < 64 bits z := x * 2^c 782// Shift bignum left by c < 64 bits z := x * 2^c
618// Inputs x[n], c; outputs function return (carry-out) and z[k] 783// Inputs x[n], c; outputs function return (carry-out) and z[k]
619extern uint64_t bignum_shl_small (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t c); 784extern uint64_t bignum_shl_small (uint64_t k, uint64_t *z, uint64_t n, const uint64_t *x, uint64_t c);
620 785
621// Shift bignum right by c < 64 bits z := floor(x / 2^c) 786// Shift bignum right by c < 64 bits z := floor(x / 2^c)
622// Inputs x[n], c; outputs function return (bits shifted out) and z[k] 787// Inputs x[n], c; outputs function return (bits shifted out) and z[k]
623extern uint64_t bignum_shr_small (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t c); 788extern uint64_t bignum_shr_small (uint64_t k, uint64_t *z, uint64_t n, const uint64_t *x, uint64_t c);
624 789
625// Square, z := x^2 790// Square, z := x^2
626// Input x[n]; output z[k] 791// Input x[n]; output z[k]
627extern void bignum_sqr (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x); 792extern void bignum_sqr (uint64_t k, uint64_t *z, uint64_t n, const uint64_t *x);
628 793
629// Square, z := x^2 794// Square, z := x^2
630// Input x[4]; output z[8] 795// Input x[4]; output z[8]
631extern void bignum_sqr_4_8 (uint64_t z[static 8], uint64_t x[static 4]); 796extern void bignum_sqr_4_8 (uint64_t z[S2N_BIGNUM_STATIC 8], const uint64_t x[S2N_BIGNUM_STATIC 4]);
632extern void bignum_sqr_4_8_alt (uint64_t z[static 8], uint64_t x[static 4]); 797extern void bignum_sqr_4_8_alt (uint64_t z[S2N_BIGNUM_STATIC 8], const uint64_t x[S2N_BIGNUM_STATIC 4]);
633 798
634// Square, z := x^2 799// Square, z := x^2
635// Input x[6]; output z[12] 800// Input x[6]; output z[12]
636extern void bignum_sqr_6_12 (uint64_t z[static 12], uint64_t x[static 6]); 801extern void bignum_sqr_6_12 (uint64_t z[S2N_BIGNUM_STATIC 12], const uint64_t x[S2N_BIGNUM_STATIC 6]);
637extern void bignum_sqr_6_12_alt (uint64_t z[static 12], uint64_t x[static 6]); 802extern void bignum_sqr_6_12_alt (uint64_t z[S2N_BIGNUM_STATIC 12], const uint64_t x[S2N_BIGNUM_STATIC 6]);
638 803
639// Square, z := x^2 804// Square, z := x^2
640// Input x[8]; output z[16] 805// Input x[8]; output z[16]
641extern void bignum_sqr_8_16 (uint64_t z[static 16], uint64_t x[static 8]); 806extern void bignum_sqr_8_16 (uint64_t z[S2N_BIGNUM_STATIC 16], const uint64_t x[S2N_BIGNUM_STATIC 8]);
642extern void bignum_sqr_8_16_alt (uint64_t z[static 16], uint64_t x[static 8]); 807extern void bignum_sqr_8_16_alt (uint64_t z[S2N_BIGNUM_STATIC 16], const uint64_t x[S2N_BIGNUM_STATIC 8]);
643 808
644// Square modulo p_25519, z := (x^2) mod p_25519 809// Square modulo p_25519, z := (x^2) mod p_25519
645// Input x[4]; output z[4] 810// Input x[4]; output z[4]
646extern void bignum_sqr_p25519 (uint64_t z[static 4], uint64_t x[static 4]); 811extern void bignum_sqr_p25519 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
647extern void bignum_sqr_p25519_alt (uint64_t z[static 4], uint64_t x[static 4]); 812extern void bignum_sqr_p25519_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
648 813
649// Square modulo p_256k1, z := (x^2) mod p_256k1 814// Square modulo p_256k1, z := (x^2) mod p_256k1
650// Input x[4]; output z[4] 815// Input x[4]; output z[4]
651extern void bignum_sqr_p256k1 (uint64_t z[static 4], uint64_t x[static 4]); 816extern void bignum_sqr_p256k1 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
652extern void bignum_sqr_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4]); 817extern void bignum_sqr_p256k1_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
653 818
654// Square modulo p_521, z := (x^2) mod p_521, assuming x reduced 819// Square modulo p_521, z := (x^2) mod p_521, assuming x reduced
655// Input x[9]; output z[9] 820// Input x[9]; output z[9]
656extern void bignum_sqr_p521 (uint64_t z[static 9], uint64_t x[static 9]); 821extern void bignum_sqr_p521 (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9]);
657extern void bignum_sqr_p521_alt (uint64_t z[static 9], uint64_t x[static 9]); 822extern void bignum_sqr_p521_alt (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9]);
823
824// Square root modulo p_25519
825// Input x[4]; output function return (Legendre symbol) and z[4]
826extern int64_t bignum_sqrt_p25519(uint64_t z[S2N_BIGNUM_STATIC 4],const uint64_t x[S2N_BIGNUM_STATIC 4]);
827extern int64_t bignum_sqrt_p25519_alt(uint64_t z[S2N_BIGNUM_STATIC 4],const uint64_t x[S2N_BIGNUM_STATIC 4]);
658 828
659// Subtract, z := x - y 829// Subtract, z := x - y
660// Inputs x[m], y[n]; outputs function return (carry-out) and z[p] 830// Inputs x[m], y[n]; outputs function return (carry-out) and z[p]
661extern uint64_t bignum_sub (uint64_t p, uint64_t *z, uint64_t m, uint64_t *x, uint64_t n, uint64_t *y); 831extern uint64_t bignum_sub (uint64_t p, uint64_t *z, uint64_t m, const uint64_t *x, uint64_t n, const uint64_t *y);
662 832
663// Subtract modulo p_25519, z := (x - y) mod p_25519, assuming x and y reduced 833// Subtract modulo p_25519, z := (x - y) mod p_25519, assuming x and y reduced
664// Inputs x[4], y[4]; output z[4] 834// Inputs x[4], y[4]; output z[4]
665extern void bignum_sub_p25519 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]); 835extern void bignum_sub_p25519 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
666 836
667// Subtract modulo p_256, z := (x - y) mod p_256, assuming x and y reduced 837// Subtract modulo p_256, z := (x - y) mod p_256, assuming x and y reduced
668// Inputs x[4], y[4]; output z[4] 838// Inputs x[4], y[4]; output z[4]
669extern void bignum_sub_p256 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]); 839extern void bignum_sub_p256 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
670 840
671// Subtract modulo p_256k1, z := (x - y) mod p_256k1, assuming x and y reduced 841// Subtract modulo p_256k1, z := (x - y) mod p_256k1, assuming x and y reduced
672// Inputs x[4], y[4]; output z[4] 842// Inputs x[4], y[4]; output z[4]
673extern void bignum_sub_p256k1 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]); 843extern void bignum_sub_p256k1 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
674 844
675// Subtract modulo p_384, z := (x - y) mod p_384, assuming x and y reduced 845// Subtract modulo p_384, z := (x - y) mod p_384, assuming x and y reduced
676// Inputs x[6], y[6]; output z[6] 846// Inputs x[6], y[6]; output z[6]
677extern void bignum_sub_p384 (uint64_t z[static 6], uint64_t x[static 6], uint64_t y[static 6]); 847extern void bignum_sub_p384 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6], const uint64_t y[S2N_BIGNUM_STATIC 6]);
678 848
679// Subtract modulo p_521, z := (x - y) mod p_521, assuming x and y reduced 849// Subtract modulo p_521, z := (x - y) mod p_521, assuming x and y reduced
680// Inputs x[9], y[9]; output z[9] 850// Inputs x[9], y[9]; output z[9]
681extern void bignum_sub_p521 (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]); 851extern void bignum_sub_p521 (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9], const uint64_t y[S2N_BIGNUM_STATIC 9]);
852
853// Subtract modulo p_sm2, z := (x - y) mod p_sm2, assuming x and y reduced
854// Inputs x[4], y[4]; output z[4]
855extern void bignum_sub_sm2 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4], const uint64_t y[S2N_BIGNUM_STATIC 4]);
682 856
683// Convert 4-digit (256-bit) bignum to big-endian bytes 857// Convert 4-digit (256-bit) bignum to big-endian bytes
684// Input x[4]; output z[32] (bytes) 858// Input x[4]; output z[32] (bytes)
685extern void bignum_tobebytes_4 (uint8_t z[static 32], uint64_t x[static 4]); 859extern void bignum_tobebytes_4 (uint8_t z[S2N_BIGNUM_STATIC 32], const uint64_t x[S2N_BIGNUM_STATIC 4]);
686 860
687// Convert 6-digit (384-bit) bignum to big-endian bytes 861// Convert 6-digit (384-bit) bignum to big-endian bytes
688// Input x[6]; output z[48] (bytes) 862// Input x[6]; output z[48] (bytes)
689extern void bignum_tobebytes_6 (uint8_t z[static 48], uint64_t x[static 6]); 863extern void bignum_tobebytes_6 (uint8_t z[S2N_BIGNUM_STATIC 48], const uint64_t x[S2N_BIGNUM_STATIC 6]);
690 864
691// Convert 4-digit (256-bit) bignum to little-endian bytes 865// Convert 4-digit (256-bit) bignum to little-endian bytes
692// Input x[4]; output z[32] (bytes) 866// Input x[4]; output z[32] (bytes)
693extern void bignum_tolebytes_4 (uint8_t z[static 32], uint64_t x[static 4]); 867extern void bignum_tolebytes_4 (uint8_t z[S2N_BIGNUM_STATIC 32], const uint64_t x[S2N_BIGNUM_STATIC 4]);
694 868
695// Convert 6-digit (384-bit) bignum to little-endian bytes 869// Convert 6-digit (384-bit) bignum to little-endian bytes
696// Input x[6]; output z[48] (bytes) 870// Input x[6]; output z[48] (bytes)
697extern void bignum_tolebytes_6 (uint8_t z[static 48], uint64_t x[static 6]); 871extern void bignum_tolebytes_6 (uint8_t z[S2N_BIGNUM_STATIC 48], const uint64_t x[S2N_BIGNUM_STATIC 6]);
698 872
699// Convert 9-digit 528-bit bignum to little-endian bytes 873// Convert 9-digit 528-bit bignum to little-endian bytes
700// Input x[6]; output z[66] (bytes) 874// Input x[6]; output z[66] (bytes)
701extern void bignum_tolebytes_p521 (uint8_t z[static 66], uint64_t x[static 9]); 875extern void bignum_tolebytes_p521 (uint8_t z[S2N_BIGNUM_STATIC 66], const uint64_t x[S2N_BIGNUM_STATIC 9]);
702 876
703// Convert to Montgomery form z := (2^256 * x) mod p_256 877// Convert to Montgomery form z := (2^256 * x) mod p_256
704// Input x[4]; output z[4] 878// Input x[4]; output z[4]
705extern void bignum_tomont_p256 (uint64_t z[static 4], uint64_t x[static 4]); 879extern void bignum_tomont_p256 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
706extern void bignum_tomont_p256_alt (uint64_t z[static 4], uint64_t x[static 4]); 880extern void bignum_tomont_p256_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
707 881
708// Convert to Montgomery form z := (2^256 * x) mod p_256k1 882// Convert to Montgomery form z := (2^256 * x) mod p_256k1
709// Input x[4]; output z[4] 883// Input x[4]; output z[4]
710extern void bignum_tomont_p256k1 (uint64_t z[static 4], uint64_t x[static 4]); 884extern void bignum_tomont_p256k1 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
711extern void bignum_tomont_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4]); 885extern void bignum_tomont_p256k1_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
712 886
713// Convert to Montgomery form z := (2^384 * x) mod p_384 887// Convert to Montgomery form z := (2^384 * x) mod p_384
714// Input x[6]; output z[6] 888// Input x[6]; output z[6]
715extern void bignum_tomont_p384 (uint64_t z[static 6], uint64_t x[static 6]); 889extern void bignum_tomont_p384 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
716extern void bignum_tomont_p384_alt (uint64_t z[static 6], uint64_t x[static 6]); 890extern void bignum_tomont_p384_alt (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
717 891
718// Convert to Montgomery form z := (2^576 * x) mod p_521 892// Convert to Montgomery form z := (2^576 * x) mod p_521
719// Input x[9]; output z[9] 893// Input x[9]; output z[9]
720extern void bignum_tomont_p521 (uint64_t z[static 9], uint64_t x[static 9]); 894extern void bignum_tomont_p521 (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9]);
895
896// Convert to Montgomery form z := (2^256 * x) mod p_sm2
897// Input x[4]; output z[4]
898extern void bignum_tomont_sm2 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
721 899
722// Triple modulo p_256, z := (3 * x) mod p_256 900// Triple modulo p_256, z := (3 * x) mod p_256
723// Input x[4]; output z[4] 901// Input x[4]; output z[4]
724extern void bignum_triple_p256 (uint64_t z[static 4], uint64_t x[static 4]); 902extern void bignum_triple_p256 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
725extern void bignum_triple_p256_alt (uint64_t z[static 4], uint64_t x[static 4]); 903extern void bignum_triple_p256_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
726 904
727// Triple modulo p_256k1, z := (3 * x) mod p_256k1 905// Triple modulo p_256k1, z := (3 * x) mod p_256k1
728// Input x[4]; output z[4] 906// Input x[4]; output z[4]
729extern void bignum_triple_p256k1 (uint64_t z[static 4], uint64_t x[static 4]); 907extern void bignum_triple_p256k1 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
730extern void bignum_triple_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4]); 908extern void bignum_triple_p256k1_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
731 909
732// Triple modulo p_384, z := (3 * x) mod p_384 910// Triple modulo p_384, z := (3 * x) mod p_384
733// Input x[6]; output z[6] 911// Input x[6]; output z[6]
734extern void bignum_triple_p384 (uint64_t z[static 6], uint64_t x[static 6]); 912extern void bignum_triple_p384 (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
735extern void bignum_triple_p384_alt (uint64_t z[static 6], uint64_t x[static 6]); 913extern void bignum_triple_p384_alt (uint64_t z[S2N_BIGNUM_STATIC 6], const uint64_t x[S2N_BIGNUM_STATIC 6]);
736 914
737// Triple modulo p_521, z := (3 * x) mod p_521, assuming x reduced 915// Triple modulo p_521, z := (3 * x) mod p_521, assuming x reduced
738// Input x[9]; output z[9] 916// Input x[9]; output z[9]
739extern void bignum_triple_p521 (uint64_t z[static 9], uint64_t x[static 9]); 917extern void bignum_triple_p521 (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9]);
740extern void bignum_triple_p521_alt (uint64_t z[static 9], uint64_t x[static 9]); 918extern void bignum_triple_p521_alt (uint64_t z[S2N_BIGNUM_STATIC 9], const uint64_t x[S2N_BIGNUM_STATIC 9]);
919
920// Triple modulo p_sm2, z := (3 * x) mod p_sm2
921// Input x[4]; output z[4]
922extern void bignum_triple_sm2 (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
923extern void bignum_triple_sm2_alt (uint64_t z[S2N_BIGNUM_STATIC 4], const uint64_t x[S2N_BIGNUM_STATIC 4]);
741 924
742// Montgomery ladder step for curve25519 925// Montgomery ladder step for curve25519
743// Inputs point[8], pp[16], b; output rr[16] 926// Inputs point[8], pp[16], b; output rr[16]
744extern void curve25519_ladderstep(uint64_t rr[16],uint64_t point[8],uint64_t pp[16],uint64_t b); 927extern void curve25519_ladderstep(uint64_t rr[16],const uint64_t point[8],const uint64_t pp[16],uint64_t b);
745extern void curve25519_ladderstep_alt(uint64_t rr[16],uint64_t point[8],uint64_t pp[16],uint64_t b); 928extern void curve25519_ladderstep_alt(uint64_t rr[16],const uint64_t point[8],const uint64_t pp[16],uint64_t b);
746 929
747// Projective scalar multiplication, x coordinate only, for curve25519 930// Projective scalar multiplication, x coordinate only, for curve25519
748// Inputs scalar[4], point[4]; output res[8] 931// Inputs scalar[4], point[4]; output res[8]
749extern void curve25519_pxscalarmul(uint64_t res[static 8],uint64_t scalar[static 4],uint64_t point[static 4]); 932extern void curve25519_pxscalarmul(uint64_t res[S2N_BIGNUM_STATIC 8],const uint64_t scalar[S2N_BIGNUM_STATIC 4],const uint64_t point[S2N_BIGNUM_STATIC 4]);
750extern void curve25519_pxscalarmul_alt(uint64_t res[static 8],uint64_t scalar[static 4],uint64_t point[static 4]); 933extern void curve25519_pxscalarmul_alt(uint64_t res[S2N_BIGNUM_STATIC 8],const uint64_t scalar[S2N_BIGNUM_STATIC 4],const uint64_t point[S2N_BIGNUM_STATIC 4]);
751 934
752// x25519 function for curve25519 935// x25519 function for curve25519
753// Inputs scalar[4], point[4]; output res[4] 936// Inputs scalar[4], point[4]; output res[4]
754extern void curve25519_x25519(uint64_t res[static 4],uint64_t scalar[static 4],uint64_t point[static 4]); 937extern void curve25519_x25519(uint64_t res[S2N_BIGNUM_STATIC 4],const uint64_t scalar[S2N_BIGNUM_STATIC 4],const uint64_t point[S2N_BIGNUM_STATIC 4]);
755extern void curve25519_x25519_alt(uint64_t res[static 4],uint64_t scalar[static 4],uint64_t point[static 4]); 938extern void curve25519_x25519_alt(uint64_t res[S2N_BIGNUM_STATIC 4],const uint64_t scalar[S2N_BIGNUM_STATIC 4],const uint64_t point[S2N_BIGNUM_STATIC 4]);
939
940// x25519 function for curve25519 (byte array arguments)
941// Inputs scalar[32] (bytes), point[32] (bytes); output res[32] (bytes)
942extern void curve25519_x25519_byte(uint8_t res[S2N_BIGNUM_STATIC 32],const uint8_t scalar[S2N_BIGNUM_STATIC 32],const uint8_t point[S2N_BIGNUM_STATIC 32]);
943extern void curve25519_x25519_byte_alt(uint8_t res[S2N_BIGNUM_STATIC 32],const uint8_t scalar[S2N_BIGNUM_STATIC 32],const uint8_t point[S2N_BIGNUM_STATIC 32]);
756 944
757// x25519 function for curve25519 on base element 9 945// x25519 function for curve25519 on base element 9
758// Input scalar[4]; output res[4] 946// Input scalar[4]; output res[4]
759extern void curve25519_x25519base(uint64_t res[static 4],uint64_t scalar[static 4]); 947extern void curve25519_x25519base(uint64_t res[S2N_BIGNUM_STATIC 4],const uint64_t scalar[S2N_BIGNUM_STATIC 4]);
760extern void curve25519_x25519base_alt(uint64_t res[static 4],uint64_t scalar[static 4]); 948extern void curve25519_x25519base_alt(uint64_t res[S2N_BIGNUM_STATIC 4],const uint64_t scalar[S2N_BIGNUM_STATIC 4]);
949
950// x25519 function for curve25519 on base element 9 (byte array arguments)
951// Input scalar[32] (bytes); output res[32] (bytes)
952extern void curve25519_x25519base_byte(uint8_t res[S2N_BIGNUM_STATIC 32],const uint8_t scalar[S2N_BIGNUM_STATIC 32]);
953extern void curve25519_x25519base_byte_alt(uint8_t res[S2N_BIGNUM_STATIC 32],const uint8_t scalar[S2N_BIGNUM_STATIC 32]);
954
955// Decode compressed 256-bit form of edwards25519 point
956// Input c[32] (bytes); output function return and z[8]
957extern uint64_t edwards25519_decode(uint64_t z[S2N_BIGNUM_STATIC 8], const uint8_t c[S2N_BIGNUM_STATIC 32]);
958extern uint64_t edwards25519_decode_alt(uint64_t z[S2N_BIGNUM_STATIC 8], const uint8_t c[S2N_BIGNUM_STATIC 32]);
959
960// Encode edwards25519 point into compressed form as 256-bit number
961// Input p[8]; output z[32] (bytes)
962extern void edwards25519_encode(uint8_t z[S2N_BIGNUM_STATIC 32], const uint64_t p[S2N_BIGNUM_STATIC 8]);
761 963
762// Extended projective addition for edwards25519 964// Extended projective addition for edwards25519
763// Inputs p1[16], p2[16]; output p3[16] 965// Inputs p1[16], p2[16]; output p3[16]
764extern void edwards25519_epadd(uint64_t p3[static 16],uint64_t p1[static 16],uint64_t p2[static 16]); 966extern void edwards25519_epadd(uint64_t p3[S2N_BIGNUM_STATIC 16],const uint64_t p1[S2N_BIGNUM_STATIC 16],const uint64_t p2[S2N_BIGNUM_STATIC 16]);
765extern void edwards25519_epadd_alt(uint64_t p3[static 16],uint64_t p1[static 16],uint64_t p2[static 16]); 967extern void edwards25519_epadd_alt(uint64_t p3[S2N_BIGNUM_STATIC 16],const uint64_t p1[S2N_BIGNUM_STATIC 16],const uint64_t p2[S2N_BIGNUM_STATIC 16]);
766 968
767// Extended projective doubling for edwards25519 969// Extended projective doubling for edwards25519
768// Inputs p1[12]; output p3[16] 970// Inputs p1[12]; output p3[16]
769extern void edwards25519_epdouble(uint64_t p3[static 16],uint64_t p1[static 12]); 971extern void edwards25519_epdouble(uint64_t p3[S2N_BIGNUM_STATIC 16],const uint64_t p1[S2N_BIGNUM_STATIC 12]);
770extern void edwards25519_epdouble_alt(uint64_t p3[static 16],uint64_t p1[static 12]); 972extern void edwards25519_epdouble_alt(uint64_t p3[S2N_BIGNUM_STATIC 16],const uint64_t p1[S2N_BIGNUM_STATIC 12]);
771 973
772// Projective doubling for edwards25519 974// Projective doubling for edwards25519
773// Inputs p1[12]; output p3[12] 975// Inputs p1[12]; output p3[12]
774extern void edwards25519_pdouble(uint64_t p3[static 12],uint64_t p1[static 12]); 976extern void edwards25519_pdouble(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12]);
775extern void edwards25519_pdouble_alt(uint64_t p3[static 12],uint64_t p1[static 12]); 977extern void edwards25519_pdouble_alt(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12]);
776 978
777// Extended projective + precomputed mixed addition for edwards25519 979// Extended projective + precomputed mixed addition for edwards25519
778// Inputs p1[16], p2[12]; output p3[16] 980// Inputs p1[16], p2[12]; output p3[16]
779extern void edwards25519_pepadd(uint64_t p3[static 16],uint64_t p1[static 16],uint64_t p2[static 12]); 981extern void edwards25519_pepadd(uint64_t p3[S2N_BIGNUM_STATIC 16],const uint64_t p1[S2N_BIGNUM_STATIC 16],const uint64_t p2[S2N_BIGNUM_STATIC 12]);
780extern void edwards25519_pepadd_alt(uint64_t p3[static 16],uint64_t p1[static 16],uint64_t p2[static 12]); 982extern void edwards25519_pepadd_alt(uint64_t p3[S2N_BIGNUM_STATIC 16],const uint64_t p1[S2N_BIGNUM_STATIC 16],const uint64_t p2[S2N_BIGNUM_STATIC 12]);
983
984// Scalar multiplication by standard basepoint for edwards25519 (Ed25519)
985// Input scalar[4]; output res[8]
986extern void edwards25519_scalarmulbase(uint64_t res[S2N_BIGNUM_STATIC 8],const uint64_t scalar[S2N_BIGNUM_STATIC 4]);
987extern void edwards25519_scalarmulbase_alt(uint64_t res[S2N_BIGNUM_STATIC 8],const uint64_t scalar[S2N_BIGNUM_STATIC 4]);
988
989// Double scalar multiplication for edwards25519, fresh and base point
990// Input scalar[4], point[8], bscalar[4]; output res[8]
991extern void edwards25519_scalarmuldouble(uint64_t res[S2N_BIGNUM_STATIC 8],const uint64_t scalar[S2N_BIGNUM_STATIC 4], const uint64_t point[S2N_BIGNUM_STATIC 8],const uint64_t bscalar[S2N_BIGNUM_STATIC 4]);
992extern void edwards25519_scalarmuldouble_alt(uint64_t res[S2N_BIGNUM_STATIC 8],const uint64_t scalar[S2N_BIGNUM_STATIC 4], const uint64_t point[S2N_BIGNUM_STATIC 8],const uint64_t bscalar[S2N_BIGNUM_STATIC 4]);
993
994// Scalar product of 2-element polynomial vectors in NTT domain, with mulcache
995// Inputs a[512], b[512], bt[256] (signed 16-bit words); output r[256] (signed 16-bit words)
996extern void mlkem_basemul_k2(int16_t r[S2N_BIGNUM_STATIC 256],const int16_t a[S2N_BIGNUM_STATIC 512],const int16_t b[S2N_BIGNUM_STATIC 512],const int16_t bt[S2N_BIGNUM_STATIC 256]);
997
998// Scalar product of 3-element polynomial vectors in NTT domain, with mulcache
999// Inputs a[768], b[768], bt[384] (signed 16-bit words); output r[256] (signed 16-bit words)
1000extern void mlkem_basemul_k3(int16_t r[S2N_BIGNUM_STATIC 256],const int16_t a[S2N_BIGNUM_STATIC 768],const int16_t b[S2N_BIGNUM_STATIC 768],const int16_t bt[S2N_BIGNUM_STATIC 384]);
1001
1002// Scalar product of 4-element polynomial vectors in NTT domain, with mulcache
1003// Inputs a[1024], b[1024], bt[512] (signed 16-bit words); output r[256] (signed 16-bit words)
1004extern void mlkem_basemul_k4(int16_t r[S2N_BIGNUM_STATIC 256],const int16_t a[S2N_BIGNUM_STATIC 1024],const int16_t b[S2N_BIGNUM_STATIC 1024],const int16_t bt[S2N_BIGNUM_STATIC 512]);
1005
1006// Inverse number-theoretic transform from ML-KEM
1007// Input a[256] (signed 16-bit words), z_01234[80] (signed 16-bit words), z_56[384] (signed 16-bit words); output a[256] (signed 16-bit words)
1008extern void mlkem_intt(int16_t a[S2N_BIGNUM_STATIC 256],const int16_t z_01234[S2N_BIGNUM_STATIC 80],const int16_t z_56[S2N_BIGNUM_STATIC 384]);
1009
1010// Precompute the mulcache data for a polynomial in the NTT domain
1011// Inputs a[256], z[128] and t[128] (signed 16-bit words); output x[128] (signed 16-bit words)
1012extern void mlkem_mulcache_compute(int16_t x[S2N_BIGNUM_STATIC 128],const int16_t a[S2N_BIGNUM_STATIC 256],const int16_t z[S2N_BIGNUM_STATIC 128],const int16_t t[S2N_BIGNUM_STATIC 128]);
1013
1014// Forward number-theoretic transform from ML-KEM
1015// Input a[256] (signed 16-bit words), z_01234[80] (signed 16-bit words), z_56[384] (signed 16-bit words); output a[256] (signed 16-bit words)
1016extern void mlkem_ntt(int16_t a[S2N_BIGNUM_STATIC 256],const int16_t z_01234[S2N_BIGNUM_STATIC 80],const int16_t z_56[S2N_BIGNUM_STATIC 384]);
1017
1018// Canonical modular reduction of polynomial coefficients for ML-KEM
1019// Input a[256] (signed 16-bit words); output a[256] (signed 16-bit words)
1020extern void mlkem_reduce(int16_t a[S2N_BIGNUM_STATIC 256]);
1021
1022// Pack ML-KEM polynomial coefficients as 12-bit numbers
1023// Input a[256] (signed 16-bit words); output r[384] (bytes)
1024extern void mlkem_tobytes(uint8_t r[S2N_BIGNUM_STATIC 384],const int16_t a[S2N_BIGNUM_STATIC 256]);
1025
1026// Conversion of ML-KEM polynomial coefficients to Montgomery form
1027// Input a[256] (signed 16-bit words); output a[256] (signed 16-bit words)
1028extern void mlkem_tomont(int16_t a[S2N_BIGNUM_STATIC 256]);
1029
1030// Uniform rejection sampling for ML-KEM
1031// Inputs *buf (unsigned bytes), buflen, table (unsigned bytes); output r[256] (signed 16-bit words), return
1032extern uint64_t mlkem_rej_uniform_VARIABLE_TIME(int16_t r[S2N_BIGNUM_STATIC 256],const uint8_t *buf,uint64_t buflen,const uint8_t *table);
781 1033
782// Point addition on NIST curve P-256 in Montgomery-Jacobian coordinates 1034// Point addition on NIST curve P-256 in Montgomery-Jacobian coordinates
783// Inputs p1[12], p2[12]; output p3[12] 1035// Inputs p1[12], p2[12]; output p3[12]
784extern void p256_montjadd(uint64_t p3[static 12],uint64_t p1[static 12],uint64_t p2[static 12]); 1036extern void p256_montjadd(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12],const uint64_t p2[S2N_BIGNUM_STATIC 12]);
1037extern void p256_montjadd_alt(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12],const uint64_t p2[S2N_BIGNUM_STATIC 12]);
785 1038
786// Point doubling on NIST curve P-256 in Montgomery-Jacobian coordinates 1039// Point doubling on NIST curve P-256 in Montgomery-Jacobian coordinates
787// Inputs p1[12]; output p3[12] 1040// Inputs p1[12]; output p3[12]
788extern void p256_montjdouble(uint64_t p3[static 12],uint64_t p1[static 12]); 1041extern void p256_montjdouble(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12]);
1042extern void p256_montjdouble_alt(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12]);
789 1043
790// Point mixed addition on NIST curve P-256 in Montgomery-Jacobian coordinates 1044// Point mixed addition on NIST curve P-256 in Montgomery-Jacobian coordinates
791// Inputs p1[12], p2[8]; output p3[12] 1045// Inputs p1[12], p2[8]; output p3[12]
792extern void p256_montjmixadd(uint64_t p3[static 12],uint64_t p1[static 12],uint64_t p2[static 8]); 1046extern void p256_montjmixadd(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12],const uint64_t p2[S2N_BIGNUM_STATIC 8]);
1047extern void p256_montjmixadd_alt(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12],const uint64_t p2[S2N_BIGNUM_STATIC 8]);
1048
1049// Montgomery-Jacobian form scalar multiplication for P-256
1050// Input scalar[4], point[12]; output res[12]
1051extern void p256_montjscalarmul(uint64_t res[S2N_BIGNUM_STATIC 12],const uint64_t scalar[S2N_BIGNUM_STATIC 4],const uint64_t point[S2N_BIGNUM_STATIC 12]);
1052extern void p256_montjscalarmul_alt(uint64_t res[S2N_BIGNUM_STATIC 12],const uint64_t scalar[S2N_BIGNUM_STATIC 4],const uint64_t point[S2N_BIGNUM_STATIC 12]);
1053
1054// Scalar multiplication for NIST curve P-256
1055// Input scalar[4], point[8]; output res[8]
1056extern void p256_scalarmul(uint64_t res[S2N_BIGNUM_STATIC 8],const uint64_t scalar[S2N_BIGNUM_STATIC 4],const uint64_t point[S2N_BIGNUM_STATIC 8]);
1057extern void p256_scalarmul_alt(uint64_t res[S2N_BIGNUM_STATIC 8],const uint64_t scalar[S2N_BIGNUM_STATIC 4],const uint64_t point[S2N_BIGNUM_STATIC 8]);
1058
1059// Scalar multiplication for precomputed point on NIST curve P-256
1060// Input scalar[4], blocksize, table[]; output res[8]
1061extern void p256_scalarmulbase(uint64_t res[S2N_BIGNUM_STATIC 8],const uint64_t scalar[S2N_BIGNUM_STATIC 4],uint64_t blocksize,const uint64_t *table);
1062extern void p256_scalarmulbase_alt(uint64_t res[S2N_BIGNUM_STATIC 8],const uint64_t scalar[S2N_BIGNUM_STATIC 4],uint64_t blocksize,const uint64_t *table);
793 1063
794// Point addition on NIST curve P-384 in Montgomery-Jacobian coordinates 1064// Point addition on NIST curve P-384 in Montgomery-Jacobian coordinates
795// Inputs p1[18], p2[18]; output p3[18] 1065// Inputs p1[18], p2[18]; output p3[18]
796extern void p384_montjadd(uint64_t p3[static 18],uint64_t p1[static 18],uint64_t p2[static 18]); 1066extern void p384_montjadd(uint64_t p3[S2N_BIGNUM_STATIC 18],const uint64_t p1[S2N_BIGNUM_STATIC 18],const uint64_t p2[S2N_BIGNUM_STATIC 18]);
1067extern void p384_montjadd_alt(uint64_t p3[S2N_BIGNUM_STATIC 18],const uint64_t p1[S2N_BIGNUM_STATIC 18],const uint64_t p2[S2N_BIGNUM_STATIC 18]);
797 1068
798// Point doubling on NIST curve P-384 in Montgomery-Jacobian coordinates 1069// Point doubling on NIST curve P-384 in Montgomery-Jacobian coordinates
799// Inputs p1[18]; output p3[18] 1070// Inputs p1[18]; output p3[18]
800extern void p384_montjdouble(uint64_t p3[static 18],uint64_t p1[static 18]); 1071extern void p384_montjdouble(uint64_t p3[S2N_BIGNUM_STATIC 18],const uint64_t p1[S2N_BIGNUM_STATIC 18]);
1072extern void p384_montjdouble_alt(uint64_t p3[S2N_BIGNUM_STATIC 18],const uint64_t p1[S2N_BIGNUM_STATIC 18]);
801 1073
802// Point mixed addition on NIST curve P-384 in Montgomery-Jacobian coordinates 1074// Point mixed addition on NIST curve P-384 in Montgomery-Jacobian coordinates
803// Inputs p1[18], p2[12]; output p3[18] 1075// Inputs p1[18], p2[12]; output p3[18]
804extern void p384_montjmixadd(uint64_t p3[static 18],uint64_t p1[static 18],uint64_t p2[static 12]); 1076extern void p384_montjmixadd(uint64_t p3[S2N_BIGNUM_STATIC 18],const uint64_t p1[S2N_BIGNUM_STATIC 18],const uint64_t p2[S2N_BIGNUM_STATIC 12]);
1077extern void p384_montjmixadd_alt(uint64_t p3[S2N_BIGNUM_STATIC 18],const uint64_t p1[S2N_BIGNUM_STATIC 18],const uint64_t p2[S2N_BIGNUM_STATIC 12]);
1078
1079// Montgomery-Jacobian form scalar multiplication for P-384
1080// Input scalar[6], point[18]; output res[18]
1081extern void p384_montjscalarmul(uint64_t res[S2N_BIGNUM_STATIC 18],const uint64_t scalar[S2N_BIGNUM_STATIC 6],const uint64_t point[S2N_BIGNUM_STATIC 18]);
1082extern void p384_montjscalarmul_alt(uint64_t res[S2N_BIGNUM_STATIC 18],const uint64_t scalar[S2N_BIGNUM_STATIC 6],const uint64_t point[S2N_BIGNUM_STATIC 18]);
805 1083
806// Point addition on NIST curve P-521 in Jacobian coordinates 1084// Point addition on NIST curve P-521 in Jacobian coordinates
807// Inputs p1[27], p2[27]; output p3[27] 1085// Inputs p1[27], p2[27]; output p3[27]
808extern void p521_jadd(uint64_t p3[static 27],uint64_t p1[static 27],uint64_t p2[static 27]); 1086extern void p521_jadd(uint64_t p3[S2N_BIGNUM_STATIC 27],const uint64_t p1[S2N_BIGNUM_STATIC 27],const uint64_t p2[S2N_BIGNUM_STATIC 27]);
1087extern void p521_jadd_alt(uint64_t p3[S2N_BIGNUM_STATIC 27],const uint64_t p1[S2N_BIGNUM_STATIC 27],const uint64_t p2[S2N_BIGNUM_STATIC 27]);
809 1088
810// Point doubling on NIST curve P-521 in Jacobian coordinates 1089// Point doubling on NIST curve P-521 in Jacobian coordinates
811// Input p1[27]; output p3[27] 1090// Input p1[27]; output p3[27]
812extern void p521_jdouble(uint64_t p3[static 27],uint64_t p1[static 27]); 1091extern void p521_jdouble(uint64_t p3[S2N_BIGNUM_STATIC 27],const uint64_t p1[S2N_BIGNUM_STATIC 27]);
1092extern void p521_jdouble_alt(uint64_t p3[S2N_BIGNUM_STATIC 27],const uint64_t p1[S2N_BIGNUM_STATIC 27]);
813 1093
814// Point mixed addition on NIST curve P-521 in Jacobian coordinates 1094// Point mixed addition on NIST curve P-521 in Jacobian coordinates
815// Inputs p1[27], p2[18]; output p3[27] 1095// Inputs p1[27], p2[18]; output p3[27]
816extern void p521_jmixadd(uint64_t p3[static 27],uint64_t p1[static 27],uint64_t p2[static 18]); 1096extern void p521_jmixadd(uint64_t p3[S2N_BIGNUM_STATIC 27],const uint64_t p1[S2N_BIGNUM_STATIC 27],const uint64_t p2[S2N_BIGNUM_STATIC 18]);
1097extern void p521_jmixadd_alt(uint64_t p3[S2N_BIGNUM_STATIC 27],const uint64_t p1[S2N_BIGNUM_STATIC 27],const uint64_t p2[S2N_BIGNUM_STATIC 18]);
1098
1099// Jacobian form scalar multiplication for P-521
1100// Input scalar[9], point[27]; output res[27]
1101extern void p521_jscalarmul(uint64_t res[S2N_BIGNUM_STATIC 27],const uint64_t scalar[S2N_BIGNUM_STATIC 9],const uint64_t point[S2N_BIGNUM_STATIC 27]);
1102extern void p521_jscalarmul_alt(uint64_t res[S2N_BIGNUM_STATIC 27],const uint64_t scalar[S2N_BIGNUM_STATIC 9],const uint64_t point[S2N_BIGNUM_STATIC 27]);
817 1103
818// Point addition on SECG curve secp256k1 in Jacobian coordinates 1104// Point addition on SECG curve secp256k1 in Jacobian coordinates
819// Inputs p1[12], p2[12]; output p3[12] 1105// Inputs p1[12], p2[12]; output p3[12]
820extern void secp256k1_jadd(uint64_t p3[static 12],uint64_t p1[static 12],uint64_t p2[static 12]); 1106extern void secp256k1_jadd(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12],const uint64_t p2[S2N_BIGNUM_STATIC 12]);
1107extern void secp256k1_jadd_alt(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12],const uint64_t p2[S2N_BIGNUM_STATIC 12]);
821 1108
822// Point doubling on SECG curve secp256k1 in Jacobian coordinates 1109// Point doubling on SECG curve secp256k1 in Jacobian coordinates
823// Input p1[12]; output p3[12] 1110// Input p1[12]; output p3[12]
824extern void secp256k1_jdouble(uint64_t p3[static 12],uint64_t p1[static 12]); 1111extern void secp256k1_jdouble(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12]);
1112extern void secp256k1_jdouble_alt(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12]);
825 1113
826// Point mixed addition on SECG curve secp256k1 in Jacobian coordinates 1114// Point mixed addition on SECG curve secp256k1 in Jacobian coordinates
827// Inputs p1[12], p2[8]; output p3[12] 1115// Inputs p1[12], p2[8]; output p3[12]
828extern void secp256k1_jmixadd(uint64_t p3[static 12],uint64_t p1[static 12],uint64_t p2[static 8]); 1116extern void secp256k1_jmixadd(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12],const uint64_t p2[S2N_BIGNUM_STATIC 8]);
1117extern void secp256k1_jmixadd_alt(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12],const uint64_t p2[S2N_BIGNUM_STATIC 8]);
1118
1119// Keccak-f1600 permutation for SHA3
1120// Inputs a[25], rc[24]; output a[25]
1121extern void sha3_keccak_f1600(uint64_t a[S2N_BIGNUM_STATIC 25],const uint64_t rc[S2N_BIGNUM_STATIC 24]);
1122extern void sha3_keccak_f1600_alt(uint64_t a[S2N_BIGNUM_STATIC 25],const uint64_t rc[S2N_BIGNUM_STATIC 24]);
1123
1124// Batched 2-way Keccak-f1600 permutation for SHA3
1125// Inputs a[50], rc[24]; output a[50]
1126extern void sha3_keccak2_f1600(uint64_t a[S2N_BIGNUM_STATIC 50],const uint64_t rc[S2N_BIGNUM_STATIC 24]);
1127extern void sha3_keccak2_f1600_alt(uint64_t a[S2N_BIGNUM_STATIC 50],const uint64_t rc[S2N_BIGNUM_STATIC 24]);
1128
1129// Batched 4-way Keccak-f1600 permutation for SHA3
1130// Inputs a[100], rc[24]; output a[100]
1131extern void sha3_keccak4_f1600(uint64_t a[S2N_BIGNUM_STATIC 100],const uint64_t rc[S2N_BIGNUM_STATIC 24]);
1132extern void sha3_keccak4_f1600_alt(uint64_t a[S2N_BIGNUM_STATIC 100],const uint64_t rc[S2N_BIGNUM_STATIC 24]);
1133extern void sha3_keccak4_f1600_alt2(uint64_t a[S2N_BIGNUM_STATIC 100],const uint64_t rc[S2N_BIGNUM_STATIC 24]);
1134
1135// Point addition on CC curve SM2 in Montgomery-Jacobian coordinates
1136// Inputs p1[12], p2[12]; output p3[12]
1137extern void sm2_montjadd(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12],const uint64_t p2[S2N_BIGNUM_STATIC 12]);
1138extern void sm2_montjadd_alt(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12],const uint64_t p2[S2N_BIGNUM_STATIC 12]);
1139
1140// Point doubling on CC curve SM2 in Montgomery-Jacobian coordinates
1141// Inputs p1[12]; output p3[12]
1142extern void sm2_montjdouble(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12]);
1143extern void sm2_montjdouble_alt(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12]);
1144
1145// Point mixed addition on CC curve SM2 in Montgomery-Jacobian coordinates
1146// Inputs p1[12], p2[8]; output p3[12]
1147extern void sm2_montjmixadd(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12],const uint64_t p2[S2N_BIGNUM_STATIC 8]);
1148extern void sm2_montjmixadd_alt(uint64_t p3[S2N_BIGNUM_STATIC 12],const uint64_t p1[S2N_BIGNUM_STATIC 12],const uint64_t p2[S2N_BIGNUM_STATIC 8]);
1149
1150// Montgomery-Jacobian form scalar multiplication for CC curve SM2
1151// Input scalar[4], point[12]; output res[12]
1152extern void sm2_montjscalarmul(uint64_t res[S2N_BIGNUM_STATIC 12],const uint64_t scalar[S2N_BIGNUM_STATIC 4],const uint64_t point[S2N_BIGNUM_STATIC 12]);
1153extern void sm2_montjscalarmul_alt(uint64_t res[S2N_BIGNUM_STATIC 12],const uint64_t scalar[S2N_BIGNUM_STATIC 4],const uint64_t point[S2N_BIGNUM_STATIC 12]);
829 1154
830// Reverse the bytes in a single word 1155// Reverse the bytes in a single word
831// Input a; output function return 1156// Input a; output function return
@@ -839,6 +1164,10 @@ extern uint64_t word_clz (uint64_t a);
839// Input a; output function return 1164// Input a; output function return
840extern uint64_t word_ctz (uint64_t a); 1165extern uint64_t word_ctz (uint64_t a);
841 1166
1167// Perform 59 "divstep" iterations and return signed matrix of updates
1168// Inputs d, f, g; output m[2][2] and function return
1169extern int64_t word_divstep59(int64_t m[2][2],int64_t d,uint64_t f,uint64_t g);
1170
842// Return maximum of two unsigned 64-bit words 1171// Return maximum of two unsigned 64-bit words
843// Inputs a, b; output function return 1172// Inputs a, b; output function return
844extern uint64_t word_max (uint64_t a, uint64_t b); 1173extern uint64_t word_max (uint64_t a, uint64_t b);
@@ -851,6 +1180,10 @@ extern uint64_t word_min (uint64_t a, uint64_t b);
851// Input a; output function return 1180// Input a; output function return
852extern uint64_t word_negmodinv (uint64_t a); 1181extern uint64_t word_negmodinv (uint64_t a);
853 1182
1183// Count number of set bits in a single 64-bit word (population count)
1184// Input a; output function return
1185extern uint64_t word_popcount (uint64_t a);
1186
854// Single-word reciprocal, 2^64 + ret = ceil(2^128/a) - 1 if MSB of "a" is set 1187// Single-word reciprocal, 2^64 + ret = ceil(2^128/a) - 1 if MSB of "a" is set
855// Input a; output function return 1188// Input a; output function return
856extern uint64_t word_recip (uint64_t a); 1189extern uint64_t word_recip (uint64_t a);
diff --git a/src/lib/libcrypto/bn/s2n_bignum_internal.h b/src/lib/libcrypto/bn/s2n_bignum_internal.h
index b82db7d019..37eebb4fd6 100644
--- a/src/lib/libcrypto/bn/s2n_bignum_internal.h
+++ b/src/lib/libcrypto/bn/s2n_bignum_internal.h
@@ -1,3 +1,5 @@
1// $OpenBSD: s2n_bignum_internal.h,v 1.5 2025/08/12 10:01:37 jsing Exp $
2//
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// 4//
3// Permission to use, copy, modify, and/or distribute this software for any 5// Permission to use, copy, modify, and/or distribute this software for any
@@ -14,14 +16,14 @@
14 16
15#ifdef __APPLE__ 17#ifdef __APPLE__
16# define S2N_BN_SYMBOL(NAME) _##NAME 18# define S2N_BN_SYMBOL(NAME) _##NAME
19# if defined(__AARCH64EL__) || defined(__ARMEL__)
20# define __LF %%
21# else
22# define __LF ;
23# endif
17#else 24#else
18# define S2N_BN_SYMBOL(name) name 25# define S2N_BN_SYMBOL(name) name
19#endif 26# define __LF ;
20
21#ifdef __CET__
22# include <cet.h>
23#else
24# define _CET_ENDBR
25#endif 27#endif
26 28
27#define S2N_BN_SYM_VISIBILITY_DIRECTIVE(name) .globl S2N_BN_SYMBOL(name) 29#define S2N_BN_SYM_VISIBILITY_DIRECTIVE(name) .globl S2N_BN_SYMBOL(name)
@@ -34,3 +36,24 @@
34#else 36#else
35# define S2N_BN_SYM_PRIVACY_DIRECTIVE(name) /* NO-OP: S2N_BN_SYM_PRIVACY_DIRECTIVE */ 37# define S2N_BN_SYM_PRIVACY_DIRECTIVE(name) /* NO-OP: S2N_BN_SYM_PRIVACY_DIRECTIVE */
36#endif 38#endif
39
40// Enable indirect branch tracking support unless explicitly disabled
41// with -DNO_IBT. If the platform supports CET, simply inherit this from
42// the usual header. Otherwise manually define _CET_ENDBR, used at each
43// x86 entry point, to be the ENDBR64 instruction, with an explicit byte
44// sequence for compilers/assemblers that don't know about it. Note that
45// it is safe to use ENDBR64 on all platforms, since the encoding is by
46// design interpreted as a NOP on all pre-CET x86_64 processors. The only
47// downside is a small increase in code size and potentially a modest
48// slowdown from executing one more instruction.
49
50#if NO_IBT
51# if defined(_CET_ENDBR)
52# error "The s2n-bignum build option NO_IBT was configured, but _CET_ENDBR is defined in this compilation unit. That is weird, so failing the build."
53# endif
54# define _CET_ENDBR
55#elif defined(__CET__)
56# include <cet.h>
57#elif !defined(_CET_ENDBR)
58# define _CET_ENDBR .byte 0xf3,0x0f,0x1e,0xfa
59#endif
diff --git a/src/lib/libcrypto/cert.pem b/src/lib/libcrypto/cert.pem
index a7fd3519fb..aadf2deb9b 100644
--- a/src/lib/libcrypto/cert.pem
+++ b/src/lib/libcrypto/cert.pem
@@ -1,4 +1,4 @@
1# $OpenBSD: cert.pem,v 1.31 2025/03/16 07:44:35 tb Exp $ 1# $OpenBSD: cert.pem,v 1.32 2025/08/06 09:45:53 sthen Exp $
2### /C=ES/CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 2### /C=ES/CN=Autoridad de Certificacion Firmaprofesional CIF A62634068
3 3
4=== /C=ES/CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 4=== /C=ES/CN=Autoridad de Certificacion Firmaprofesional CIF A62634068
@@ -960,49 +960,6 @@ AgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA
96043j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== 96043j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w==
961-----END CERTIFICATE----- 961-----END CERTIFICATE-----
962 962
963### Baltimore
964
965=== /C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore CyberTrust Root
966Certificate:
967 Data:
968 Version: 3 (0x2)
969 Serial Number: 33554617 (0x20000b9)
970 Signature Algorithm: sha1WithRSAEncryption
971 Validity
972 Not Before: May 12 18:46:00 2000 GMT
973 Not After : May 12 23:59:00 2025 GMT
974 Subject: C=IE, O=Baltimore, OU=CyberTrust, CN=Baltimore CyberTrust Root
975 X509v3 extensions:
976 X509v3 Subject Key Identifier:
977 E5:9D:59:30:82:47:58:CC:AC:FA:08:54:36:86:7B:3A:B5:04:4D:F0
978 X509v3 Basic Constraints: critical
979 CA:TRUE, pathlen:3
980 X509v3 Key Usage: critical
981 Certificate Sign, CRL Sign
982SHA1 Fingerprint=D4:DE:20:D0:5E:66:FC:53:FE:1A:50:88:2C:78:DB:28:52:CA:E4:74
983SHA256 Fingerprint=16:AF:57:A9:F6:76:B0:AB:12:60:95:AA:5E:BA:DE:F2:2A:B3:11:19:D6:44:AC:95:CD:4B:93:DB:F3:F2:6A:EB
984-----BEGIN CERTIFICATE-----
985MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
986RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
987VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
988DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
989ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
990VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
991mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
992IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
993mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
994XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
995dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
996jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
997BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
998DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
9999hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
1000jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
1001Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
1002ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
1003R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
1004-----END CERTIFICATE-----
1005
1006### Buypass AS-983163327 963### Buypass AS-983163327
1007 964
1008=== /C=NO/O=Buypass AS-983163327/CN=Buypass Class 2 Root CA 965=== /C=NO/O=Buypass AS-983163327/CN=Buypass Class 2 Root CA
@@ -1728,61 +1685,6 @@ v64fG9PiO/yzcnMcmyiQiRM9HcEARwmWmjgb3bHPDcK0RPOWlc4yOo80nOAXx17O
1728rg3bhzjlP1v9mxnhMUF6cKojawHhRUzNlM47ni3niAIi9G7oyOzWPPO5std3eqx7 1685rg3bhzjlP1v9mxnhMUF6cKojawHhRUzNlM47ni3niAIi9G7oyOzWPPO5std3eqx7
1729-----END CERTIFICATE----- 1686-----END CERTIFICATE-----
1730 1687
1731### Comodo CA Limited
1732
1733=== /C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=AAA Certificate Services
1734Certificate:
1735 Data:
1736 Version: 3 (0x2)
1737 Serial Number: 1 (0x1)
1738 Signature Algorithm: sha1WithRSAEncryption
1739 Validity
1740 Not Before: Jan 1 00:00:00 2004 GMT
1741 Not After : Dec 31 23:59:59 2028 GMT
1742 Subject: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=AAA Certificate Services
1743 X509v3 extensions:
1744 X509v3 Subject Key Identifier:
1745 A0:11:0A:23:3E:96:F1:07:EC:E2:AF:29:EF:82:A5:7F:D0:30:A4:B4
1746 X509v3 Key Usage: critical
1747 Certificate Sign, CRL Sign
1748 X509v3 Basic Constraints: critical
1749 CA:TRUE
1750 X509v3 CRL Distribution Points:
1751
1752 Full Name:
1753 URI:http://crl.comodoca.com/AAACertificateServices.crl
1754
1755 Full Name:
1756 URI:http://crl.comodo.net/AAACertificateServices.crl
1757
1758SHA1 Fingerprint=D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49
1759SHA256 Fingerprint=D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4
1760-----BEGIN CERTIFICATE-----
1761MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb
1762MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
1763GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj
1764YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL
1765MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
1766BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM
1767GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
1768ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua
1769BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe
17703M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4
1771YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR
1772rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm
1773ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU
1774oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
1775MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v
1776QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t
1777b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF
1778AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q
1779GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
1780Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2
1781G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi
1782l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
1783smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
1784-----END CERTIFICATE-----
1785
1786### Cybertrust Japan Co., Ltd. 1688### Cybertrust Japan Co., Ltd.
1787 1689
1788=== /C=JP/O=Cybertrust Japan Co., Ltd./CN=SecureSign Root CA12 1690=== /C=JP/O=Cybertrust Japan Co., Ltd./CN=SecureSign Root CA12
@@ -3070,53 +2972,6 @@ eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m
30700vdXcDazv/wor3ElhVsT/h5/WrQ8 29720vdXcDazv/wor3ElhVsT/h5/WrQ8
3071-----END CERTIFICATE----- 2973-----END CERTIFICATE-----
3072 2974
3073### Entrust.net
3074
3075=== /O=Entrust.net/OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Certification Authority (2048)
3076Certificate:
3077 Data:
3078 Version: 3 (0x2)
3079 Serial Number: 946069240 (0x3863def8)
3080 Signature Algorithm: sha1WithRSAEncryption
3081 Validity
3082 Not Before: Dec 24 17:50:51 1999 GMT
3083 Not After : Jul 24 14:15:12 2029 GMT
3084 Subject: O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification Authority (2048)
3085 X509v3 extensions:
3086 X509v3 Key Usage: critical
3087 Certificate Sign, CRL Sign
3088 X509v3 Basic Constraints: critical
3089 CA:TRUE
3090 X509v3 Subject Key Identifier:
3091 55:E4:81:D1:11:80:BE:D8:89:B9:08:A3:31:F9:A1:24:09:16:B9:70
3092SHA1 Fingerprint=50:30:06:09:1D:97:D4:F5:AE:39:F7:CB:E7:92:7D:7D:65:2D:34:31
3093SHA256 Fingerprint=6D:C4:71:72:E0:1C:BC:B0:BF:62:58:0D:89:5F:E2:B8:AC:9A:D4:F8:73:80:1E:0C:10:B9:C8:37:D2:1E:B1:77
3094-----BEGIN CERTIFICATE-----
3095MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
3096RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
3097bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
3098IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
3099ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3
3100MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
3101LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
3102YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
3103A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
3104MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
3105K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
3106sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
3107MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
3108XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
3109HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
31104QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
3111HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub
3112j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo
3113U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
3114zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b
3115u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+
3116bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er
3117fF6adulZkMV8gzURZVE=
3118-----END CERTIFICATE-----
3119
3120### FNMT-RCM 2975### FNMT-RCM
3121 2976
3122=== /C=ES/O=FNMT-RCM/OU=AC RAIZ FNMT-RCM 2977=== /C=ES/O=FNMT-RCM/OU=AC RAIZ FNMT-RCM
@@ -3559,47 +3414,6 @@ u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP
3559N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3 3414N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3
3560vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6 3415vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6
3561-----END CERTIFICATE----- 3416-----END CERTIFICATE-----
3562=== /C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
3563Certificate:
3564 Data:
3565 Version: 3 (0x2)
3566 Serial Number:
3567 04:00:00:00:00:01:15:4b:5a:c3:94
3568 Signature Algorithm: sha1WithRSAEncryption
3569 Validity
3570 Not Before: Sep 1 12:00:00 1998 GMT
3571 Not After : Jan 28 12:00:00 2028 GMT
3572 Subject: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
3573 X509v3 extensions:
3574 X509v3 Key Usage: critical
3575 Certificate Sign, CRL Sign
3576 X509v3 Basic Constraints: critical
3577 CA:TRUE
3578 X509v3 Subject Key Identifier:
3579 60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B
3580SHA1 Fingerprint=B1:BC:96:8B:D4:F4:9D:62:2A:A8:9A:81:F2:15:01:52:A4:1D:82:9C
3581SHA256 Fingerprint=EB:D4:10:40:E4:BB:3E:C7:42:C9:E3:81:D3:1E:F2:A4:1A:48:B6:68:5C:96:E7:CE:F3:C1:DF:6C:D4:33:1C:99
3582-----BEGIN CERTIFICATE-----
3583MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
3584A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
3585b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
3586MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
3587YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
3588aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
3589jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
3590xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
35911Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
3592snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
3593U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
35949iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
3595BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
3596AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
3597yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
359838NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
3599AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
3600DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
3601HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
3602-----END CERTIFICATE-----
3603 3417
3604### GoDaddy.com, Inc. 3418### GoDaddy.com, Inc.
3605 3419
@@ -5481,52 +5295,6 @@ CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
5481 5295
5482### Starfield Technologies, Inc. 5296### Starfield Technologies, Inc.
5483 5297
5484=== /C=US/O=Starfield Technologies, Inc./OU=Starfield Class 2 Certification Authority
5485Certificate:
5486 Data:
5487 Version: 3 (0x2)
5488 Serial Number: 0 (0x0)
5489 Signature Algorithm: sha1WithRSAEncryption
5490 Validity
5491 Not Before: Jun 29 17:39:16 2004 GMT
5492 Not After : Jun 29 17:39:16 2034 GMT
5493 Subject: C=US, O=Starfield Technologies, Inc., OU=Starfield Class 2 Certification Authority
5494 X509v3 extensions:
5495 X509v3 Subject Key Identifier:
5496 BF:5F:B7:D1:CE:DD:1F:86:F4:5B:55:AC:DC:D7:10:C2:0E:A9:88:E7
5497 X509v3 Authority Key Identifier:
5498 keyid:BF:5F:B7:D1:CE:DD:1F:86:F4:5B:55:AC:DC:D7:10:C2:0E:A9:88:E7
5499 DirName:/C=US/O=Starfield Technologies, Inc./OU=Starfield Class 2 Certification Authority
5500 serial:00
5501
5502 X509v3 Basic Constraints:
5503 CA:TRUE
5504SHA1 Fingerprint=AD:7E:1C:28:B0:64:EF:8F:60:03:40:20:14:C3:D0:E3:37:0E:B5:8A
5505SHA256 Fingerprint=14:65:FA:20:53:97:B8:76:FA:A6:F0:A9:95:8E:55:90:E4:0F:CC:7F:AA:4F:B7:C2:C8:67:75:21:FB:5F:B6:58
5506-----BEGIN CERTIFICATE-----
5507MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
5508MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
5509U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
5510NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
5511ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
5512ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
5513DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
55148MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
5515+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
5516X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
5517K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
55181W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
5519A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
5520zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
5521YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
5522bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
5523DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
5524L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
5525eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
5526xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
5527VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
5528WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
5529-----END CERTIFICATE-----
5530=== /C=US/ST=Arizona/L=Scottsdale/O=Starfield Technologies, Inc./CN=Starfield Root Certificate Authority - G2 5298=== /C=US/ST=Arizona/L=Scottsdale/O=Starfield Technologies, Inc./CN=Starfield Root Certificate Authority - G2
5531Certificate: 5299Certificate:
5532 Data: 5300 Data:
@@ -6020,55 +5788,6 @@ HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx
6020SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= 5788SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
6021-----END CERTIFICATE----- 5789-----END CERTIFICATE-----
6022 5790
6023### The Go Daddy Group, Inc.
6024
6025=== /C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
6026Certificate:
6027 Data:
6028 Version: 3 (0x2)
6029 Serial Number: 0 (0x0)
6030 Signature Algorithm: sha1WithRSAEncryption
6031 Validity
6032 Not Before: Jun 29 17:06:20 2004 GMT
6033 Not After : Jun 29 17:06:20 2034 GMT
6034 Subject: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority
6035 X509v3 extensions:
6036 X509v3 Subject Key Identifier:
6037 D2:C4:B0:D2:91:D4:4C:11:71:B3:61:CB:3D:A1:FE:DD:A8:6A:D4:E3
6038 X509v3 Authority Key Identifier:
6039 keyid:D2:C4:B0:D2:91:D4:4C:11:71:B3:61:CB:3D:A1:FE:DD:A8:6A:D4:E3
6040 DirName:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
6041 serial:00
6042
6043 X509v3 Basic Constraints:
6044 CA:TRUE
6045SHA1 Fingerprint=27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4
6046SHA256 Fingerprint=C3:84:6B:F2:4B:9E:93:CA:64:27:4C:0E:C6:7C:1E:CC:5E:02:4F:FC:AC:D2:D7:40:19:35:0E:81:FE:54:6A:E4
6047-----BEGIN CERTIFICATE-----
6048MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
6049MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
6050YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
6051MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
6052ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
6053MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
6054ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
6055PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
6056wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
6057EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
6058avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
6059YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
6060sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
6061/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
6062IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
6063YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
6064ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
6065OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
6066TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
6067HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
6068dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
6069ReYNnyicsbkqWletNw+vHX/bvZ8=
6070-----END CERTIFICATE-----
6071
6072### The USERTRUST Network 5791### The USERTRUST Network
6073 5792
6074=== /C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust ECC Certification Authority 5793=== /C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust ECC Certification Authority
@@ -6669,63 +6388,6 @@ rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV
6669Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 6388Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9
6670-----END CERTIFICATE----- 6389-----END CERTIFICATE-----
6671 6390
6672### XRamp Security Services Inc
6673
6674=== /C=US/OU=www.xrampsecurity.com/O=XRamp Security Services Inc/CN=XRamp Global Certification Authority
6675Certificate:
6676 Data:
6677 Version: 3 (0x2)
6678 Serial Number:
6679 50:94:6c:ec:18:ea:d5:9c:4d:d5:97:ef:75:8f:a0:ad
6680 Signature Algorithm: sha1WithRSAEncryption
6681 Validity
6682 Not Before: Nov 1 17:14:04 2004 GMT
6683 Not After : Jan 1 05:37:19 2035 GMT
6684 Subject: C=US, OU=www.xrampsecurity.com, O=XRamp Security Services Inc, CN=XRamp Global Certification Authority
6685 X509v3 extensions:
6686 1.3.6.1.4.1.311.20.2:
6687 ...C.A
6688 X509v3 Key Usage:
6689 Digital Signature, Certificate Sign, CRL Sign
6690 X509v3 Basic Constraints: critical
6691 CA:TRUE
6692 X509v3 Subject Key Identifier:
6693 C6:4F:A2:3D:06:63:84:09:9C:CE:62:E4:04:AC:8D:5C:B5:E9:B6:1B
6694 X509v3 CRL Distribution Points:
6695
6696 Full Name:
6697 URI:http://crl.xrampsecurity.com/XGCA.crl
6698
6699 1.3.6.1.4.1.311.21.1:
6700 ...
6701SHA1 Fingerprint=B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6
6702SHA256 Fingerprint=CE:CD:DC:90:50:99:D8:DA:DF:C5:B1:D2:09:B7:37:CB:E2:C1:8C:FB:2C:10:C0:FF:0B:CF:0D:32:86:FC:1A:A2
6703-----BEGIN CERTIFICATE-----
6704MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB
6705gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk
6706MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY
6707UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx
6708NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3
6709dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy
6710dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
6711dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6
671238eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP
6713KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q
6714DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4
6715qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa
6716JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi
6717PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P
6718BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs
6719jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0
6720eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD
6721ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR
6722vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
6723qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa
6724IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy
6725i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ
6726O+7ETPTsJ3xCwnR8gooJybQDJbw=
6727-----END CERTIFICATE-----
6728
6729### certSIGN 6391### certSIGN
6730 6392
6731=== /C=RO/O=certSIGN/OU=certSIGN ROOT CA 6393=== /C=RO/O=certSIGN/OU=certSIGN ROOT CA
diff --git a/src/lib/libcrypto/hidden/crypto_namespace.h b/src/lib/libcrypto/hidden/crypto_namespace.h
index 741ad08549..43c8718ed0 100644
--- a/src/lib/libcrypto/hidden/crypto_namespace.h
+++ b/src/lib/libcrypto/hidden/crypto_namespace.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: crypto_namespace.h,v 1.4 2024/07/11 21:31:52 miod Exp $ */ 1/* $OpenBSD: crypto_namespace.h,v 1.5 2025/08/18 16:00:05 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2016 Philip Guenther <guenther@openbsd.org> 3 * Copyright (c) 2016 Philip Guenther <guenther@openbsd.org>
4 * 4 *
@@ -45,7 +45,11 @@
45# define LCRYPTO_UNUSED(x) 45# define LCRYPTO_UNUSED(x)
46# define LCRYPTO_USED(x) 46# define LCRYPTO_USED(x)
47# define LCRYPTO_ALIAS1(pre,x) 47# define LCRYPTO_ALIAS1(pre,x)
48#ifdef _MSC_VER
49# define LCRYPTO_ALIAS(x)
50#else
48# define LCRYPTO_ALIAS(x) asm("") 51# define LCRYPTO_ALIAS(x) asm("")
52#endif /* _MSC_VER */
49#endif 53#endif
50 54
51#endif /* _LIBCRYPTO_CRYPTO_NAMESPACE_H_ */ 55#endif /* _LIBCRYPTO_CRYPTO_NAMESPACE_H_ */
diff --git a/src/lib/libcrypto/hidden/openssl/mlkem.h b/src/lib/libcrypto/hidden/openssl/mlkem.h
index 8cd80eb3af..3807b3fa1e 100644
--- a/src/lib/libcrypto/hidden/openssl/mlkem.h
+++ b/src/lib/libcrypto/hidden/openssl/mlkem.h
@@ -1,6 +1,6 @@
1/* $OpenBSD: mlkem.h,v 1.4 2024/12/20 15:10:31 tb Exp $ */ 1/* $OpenBSD: mlkem.h,v 1.5 2025/08/14 15:48:48 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2024 Bob Beck <beck@obtuse.com> 3 * Copyright (c) 2025 Bob Beck <beck@openbsd.org>
4 * 4 *
5 * Permission to use, copy, modify, and distribute this software for any 5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -18,9 +18,6 @@
18#ifndef _LIBCRYPTO_MLKEM_H 18#ifndef _LIBCRYPTO_MLKEM_H
19#define _LIBCRYPTO_MLKEM_H 19#define _LIBCRYPTO_MLKEM_H
20 20
21/* Undo when making public */
22#ifdef LIBRESSL_HAS_MLKEM
23
24#ifndef _MSC_VER 21#ifndef _MSC_VER
25#include_next <openssl/mlkem.h> 22#include_next <openssl/mlkem.h>
26#else 23#else
@@ -28,22 +25,21 @@
28#endif 25#endif
29#include "crypto_namespace.h" 26#include "crypto_namespace.h"
30 27
31LCRYPTO_USED(MLKEM768_generate_key); 28LCRYPTO_USED(MLKEM_private_key_new);
32LCRYPTO_USED(MLKEM768_public_from_private); 29LCRYPTO_USED(MLKEM_private_key_free);
33LCRYPTO_USED(MLKEM768_encap); 30LCRYPTO_USED(MLKEM_private_key_ciphertext_length);
34LCRYPTO_USED(MLKEM768_decap); 31LCRYPTO_USED(MLKEM_private_key_encoded_length);
35LCRYPTO_USED(MLKEM768_marshal_public_key); 32LCRYPTO_USED(MLKEM_public_key_new);
36LCRYPTO_USED(MLKEM768_parse_public_key); 33LCRYPTO_USED(MLKEM_public_key_free);
37LCRYPTO_USED(MLKEM768_private_key_from_seed); 34LCRYPTO_USED(MLKEM_public_key_ciphertext_length);
38LCRYPTO_USED(MLKEM768_parse_private_key); 35LCRYPTO_USED(MLKEM_public_key_encoded_length);
39LCRYPTO_USED(MLKEM1024_generate_key); 36LCRYPTO_USED(MLKEM_generate_key);
40LCRYPTO_USED(MLKEM1024_public_from_private); 37LCRYPTO_USED(MLKEM_private_key_from_seed);
41LCRYPTO_USED(MLKEM1024_encap); 38LCRYPTO_USED(MLKEM_public_from_private);
42LCRYPTO_USED(MLKEM1024_decap); 39LCRYPTO_USED(MLKEM_encap);
43LCRYPTO_USED(MLKEM1024_marshal_public_key); 40LCRYPTO_USED(MLKEM_decap);
44LCRYPTO_USED(MLKEM1024_parse_public_key); 41LCRYPTO_USED(MLKEM_marshal_public_key);
45LCRYPTO_USED(MLKEM1024_private_key_from_seed); 42LCRYPTO_USED(MLKEM_parse_public_key);
46LCRYPTO_USED(MLKEM1024_parse_private_key); 43LCRYPTO_USED(MLKEM_parse_private_key);
47#endif /* LIBRESSL_HAS_MLKEM */
48 44
49#endif /* _LIBCRYPTO_MLKEM_H */ 45#endif /* _LIBCRYPTO_MLKEM_H */
diff --git a/src/lib/libcrypto/mlkem/mlkem.c b/src/lib/libcrypto/mlkem/mlkem.c
new file mode 100644
index 0000000000..bf53e5d77a
--- /dev/null
+++ b/src/lib/libcrypto/mlkem/mlkem.c
@@ -0,0 +1,416 @@
1/* $OpenBSD: mlkem.c,v 1.2 2025/08/14 16:04:01 beck Exp $ */
2/*
3 * Copyright (c) 2025, Bob Beck <beck@obtuse.com>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
14 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
15 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17#include <stdlib.h>
18
19#include <openssl/mlkem.h>
20#include "mlkem_internal.h"
21
22static inline int
23private_key_is_new(const MLKEM_private_key *key)
24{
25 return (key != NULL &&
26 key->state == MLKEM_PRIVATE_KEY_UNINITIALIZED &&
27 (key->rank == RANK768 || key->rank == RANK1024));
28}
29
30static inline int
31private_key_is_valid(const MLKEM_private_key *key)
32{
33 return (key != NULL &&
34 key->state == MLKEM_PRIVATE_KEY_INITIALIZED &&
35 (key->rank == RANK768 || key->rank == RANK1024));
36}
37
38static inline int
39public_key_is_new(const MLKEM_public_key *key)
40{
41 return (key != NULL &&
42 key->state == MLKEM_PUBLIC_KEY_UNINITIALIZED &&
43 (key->rank == RANK768 || key->rank == RANK1024));
44}
45
46static inline int
47public_key_is_valid(const MLKEM_public_key *key)
48{
49 return (key != NULL &&
50 key->state == MLKEM_PUBLIC_KEY_INITIALIZED &&
51 (key->rank == RANK768 || key->rank == RANK1024));
52}
53
54/*
55 * ML-KEM operations
56 */
57
58int
59MLKEM_generate_key_external_entropy(MLKEM_private_key *private_key,
60 uint8_t **out_encoded_public_key, size_t *out_encoded_public_key_len,
61 const uint8_t *entropy)
62{
63 uint8_t *k = NULL;
64 size_t k_len = 0;
65 int ret = 0;
66
67 if (*out_encoded_public_key != NULL)
68 goto err;
69
70 if (!private_key_is_new(private_key))
71 goto err;
72
73 k_len = MLKEM768_PUBLIC_KEY_BYTES;
74 if (private_key->rank == RANK1024)
75 k_len = MLKEM1024_PUBLIC_KEY_BYTES;
76
77 if ((k = calloc(1, k_len)) == NULL)
78 goto err;
79
80 switch (private_key->rank) {
81 case RANK768:
82 if (!MLKEM768_generate_key_external_entropy(k, private_key,
83 entropy))
84 goto err;
85 break;
86 case RANK1024:
87 if (!MLKEM1024_generate_key_external_entropy(k, private_key,
88 entropy))
89 goto err;
90 break;
91 }
92
93 private_key->state = MLKEM_PRIVATE_KEY_INITIALIZED;
94
95 *out_encoded_public_key = k;
96 *out_encoded_public_key_len = k_len;
97 k = NULL;
98
99 ret = 1;
100
101 err:
102 freezero(k, k_len);
103
104 return ret;
105}
106
107int
108MLKEM_generate_key(MLKEM_private_key *private_key,
109 uint8_t **out_encoded_public_key, size_t *out_encoded_public_key_len,
110 uint8_t **out_optional_seed, size_t *out_optional_seed_len)
111{
112 uint8_t *entropy_buf = NULL;
113 int ret = 0;
114
115 if (*out_encoded_public_key != NULL)
116 goto err;
117
118 if (out_optional_seed != NULL && *out_optional_seed != NULL)
119 goto err;
120
121 if ((entropy_buf = calloc(1, MLKEM_SEED_LENGTH)) == NULL)
122 goto err;
123
124 arc4random_buf(entropy_buf, MLKEM_SEED_LENGTH);
125 if (!MLKEM_generate_key_external_entropy(private_key,
126 out_encoded_public_key, out_encoded_public_key_len,
127 entropy_buf))
128 goto err;
129
130 if (out_optional_seed != NULL) {
131 *out_optional_seed = entropy_buf;
132 *out_optional_seed_len = MLKEM_SEED_LENGTH;
133 entropy_buf = NULL;
134 }
135
136 ret = 1;
137
138 err:
139 freezero(entropy_buf, MLKEM_SEED_LENGTH);
140
141 return ret;
142}
143LCRYPTO_ALIAS(MLKEM_generate_key);
144
145int
146MLKEM_private_key_from_seed(MLKEM_private_key *private_key,
147 const uint8_t *seed, size_t seed_len)
148{
149 int ret = 0;
150
151 if (!private_key_is_new(private_key))
152 goto err;
153
154 if (seed_len != MLKEM_SEED_LENGTH)
155 goto err;
156
157 switch (private_key->rank) {
158 case RANK768:
159 if (!MLKEM768_private_key_from_seed(seed,
160 seed_len, private_key))
161 goto err;
162 break;
163 case RANK1024:
164 if (!MLKEM1024_private_key_from_seed(private_key,
165 seed, seed_len))
166 goto err;
167 break;
168 }
169
170 private_key->state = MLKEM_PRIVATE_KEY_INITIALIZED;
171
172 ret = 1;
173
174 err:
175
176 return ret;
177}
178LCRYPTO_ALIAS(MLKEM_private_key_from_seed);
179
180int
181MLKEM_public_from_private(const MLKEM_private_key *private_key,
182 MLKEM_public_key *public_key)
183{
184 if (!private_key_is_valid(private_key))
185 return 0;
186 if (!public_key_is_new(public_key))
187 return 0;
188 if (public_key->rank != private_key->rank)
189 return 0;
190 switch (private_key->rank) {
191 case RANK768:
192 MLKEM768_public_from_private(private_key, public_key);
193 break;
194 case RANK1024:
195 MLKEM1024_public_from_private(private_key, public_key);
196 break;
197 }
198
199 public_key->state = MLKEM_PUBLIC_KEY_INITIALIZED;
200
201 return 1;
202}
203LCRYPTO_ALIAS(MLKEM_public_from_private);
204
205int
206MLKEM_encap_external_entropy(const MLKEM_public_key *public_key,
207 const uint8_t *entropy, uint8_t **out_ciphertext,
208 size_t *out_ciphertext_len, uint8_t **out_shared_secret,
209 size_t *out_shared_secret_len)
210{
211 uint8_t *secret = NULL;
212 uint8_t *ciphertext = NULL;
213 size_t ciphertext_len = 0;
214 int ret = 0;
215
216 if (*out_ciphertext != NULL)
217 goto err;
218
219 if (*out_shared_secret != NULL)
220 goto err;
221
222 if (!public_key_is_valid(public_key))
223 goto err;
224
225 if ((secret = calloc(1, MLKEM_SHARED_SECRET_LENGTH)) == NULL)
226 goto err;
227
228 ciphertext_len = MLKEM_public_key_ciphertext_length(public_key);
229
230 if ((ciphertext = calloc(1, ciphertext_len)) == NULL)
231 goto err;
232
233 switch (public_key->rank) {
234 case RANK768:
235 MLKEM768_encap_external_entropy(ciphertext, secret, public_key,
236 entropy);
237 break;
238
239 case RANK1024:
240 MLKEM1024_encap_external_entropy(ciphertext, secret, public_key,
241 entropy);
242 break;
243 }
244 *out_ciphertext = ciphertext;
245 *out_ciphertext_len = ciphertext_len;
246 ciphertext = NULL;
247 *out_shared_secret = secret;
248 *out_shared_secret_len = MLKEM_SHARED_SECRET_LENGTH;
249 secret = NULL;
250
251 ret = 1;
252
253 err:
254 freezero(secret, MLKEM_SHARED_SECRET_LENGTH);
255 freezero(ciphertext, ciphertext_len);
256
257 return ret;
258}
259
260int
261MLKEM_encap(const MLKEM_public_key *public_key,
262 uint8_t **out_ciphertext, size_t *out_ciphertext_len,
263 uint8_t **out_shared_secret, size_t *out_shared_secret_len)
264{
265 uint8_t entropy[MLKEM_ENCAP_ENTROPY];
266
267 arc4random_buf(entropy, MLKEM_ENCAP_ENTROPY);
268
269 return MLKEM_encap_external_entropy(public_key, entropy, out_ciphertext,
270 out_ciphertext_len, out_shared_secret, out_shared_secret_len);
271}
272LCRYPTO_ALIAS(MLKEM_encap);
273
274int
275MLKEM_decap(const MLKEM_private_key *private_key,
276 const uint8_t *ciphertext, size_t ciphertext_len,
277 uint8_t **out_shared_secret, size_t *out_shared_secret_len)
278{
279 uint8_t *s = NULL;
280 int ret = 0;
281
282 if (*out_shared_secret != NULL)
283 goto err;
284
285 if (!private_key_is_valid(private_key))
286 goto err;
287
288 if (ciphertext_len != MLKEM_private_key_ciphertext_length(private_key))
289 goto err;
290
291 if ((s = calloc(1, MLKEM_SHARED_SECRET_LENGTH)) == NULL)
292 goto err;
293
294 switch (private_key->rank) {
295 case RANK768:
296 MLKEM768_decap(private_key, ciphertext, ciphertext_len, s);
297 break;
298
299 case RANK1024:
300 MLKEM1024_decap(private_key, ciphertext, ciphertext_len, s);
301 break;
302 }
303
304 *out_shared_secret = s;
305 *out_shared_secret_len = MLKEM_SHARED_SECRET_LENGTH;
306 s = NULL;
307
308 ret = 1;
309
310 err:
311 freezero(s, MLKEM_SHARED_SECRET_LENGTH);
312
313 return ret;
314}
315LCRYPTO_ALIAS(MLKEM_decap);
316
317int
318MLKEM_marshal_public_key(const MLKEM_public_key *public_key, uint8_t **out,
319 size_t *out_len)
320{
321 if (*out != NULL)
322 return 0;
323
324 if (!public_key_is_valid(public_key))
325 return 0;
326
327 switch (public_key->rank) {
328 case RANK768:
329 return MLKEM768_marshal_public_key(public_key, out, out_len);
330 case RANK1024:
331 return MLKEM1024_marshal_public_key(public_key, out, out_len);
332 default:
333 return 0;
334 }
335}
336LCRYPTO_ALIAS(MLKEM_marshal_public_key);
337
338/*
339 * Not exposed publicly, becuase the NIST private key format is gigantisch, and
340 * seeds should be used instead. Used for the NIST tests.
341 */
342int
343MLKEM_marshal_private_key(const MLKEM_private_key *private_key, uint8_t **out,
344 size_t *out_len)
345{
346 if (*out != NULL)
347 return 0;
348
349 if (!private_key_is_valid(private_key))
350 return 0;
351
352 switch (private_key->rank) {
353 case RANK768:
354 return MLKEM768_marshal_private_key(private_key, out, out_len);
355 case RANK1024:
356 return MLKEM1024_marshal_private_key(private_key, out, out_len);
357 default:
358 return 0;
359 }
360}
361
362int
363MLKEM_parse_public_key(MLKEM_public_key *public_key, const uint8_t *in,
364 size_t in_len)
365{
366 if (!public_key_is_new(public_key))
367 return 0;
368
369 if (in_len != MLKEM_public_key_encoded_length(public_key))
370 return 0;
371
372 switch (public_key->rank) {
373 case RANK768:
374 if (!MLKEM768_parse_public_key(in, in_len,
375 public_key))
376 return 0;
377 break;
378 case RANK1024:
379 if (!MLKEM1024_parse_public_key(in, in_len,
380 public_key))
381 return 0;
382 break;
383 }
384
385 public_key->state = MLKEM_PUBLIC_KEY_INITIALIZED;
386
387 return 1;
388}
389LCRYPTO_ALIAS(MLKEM_parse_public_key);
390
391int
392MLKEM_parse_private_key(MLKEM_private_key *private_key, const uint8_t *in,
393 size_t in_len)
394{
395 if (!private_key_is_new(private_key))
396 return 0;
397
398 if (in_len != MLKEM_private_key_encoded_length(private_key))
399 return 0;
400
401 switch (private_key->rank) {
402 case RANK768:
403 if (!MLKEM768_parse_private_key(in, in_len, private_key))
404 return 0;
405 break;
406 case RANK1024:
407 if (!MLKEM1024_parse_private_key(in, in_len, private_key))
408 return 0;
409 break;
410 }
411
412 private_key->state = MLKEM_PRIVATE_KEY_INITIALIZED;
413
414 return 1;
415}
416LCRYPTO_ALIAS(MLKEM_parse_private_key);
diff --git a/src/lib/libcrypto/mlkem/mlkem.h b/src/lib/libcrypto/mlkem/mlkem.h
index a2c5d7fed0..31d4858195 100644
--- a/src/lib/libcrypto/mlkem/mlkem.h
+++ b/src/lib/libcrypto/mlkem/mlkem.h
@@ -1,6 +1,6 @@
1/* $OpenBSD: mlkem.h,v 1.6 2025/05/19 06:47:40 beck Exp $ */ 1/* $OpenBSD: mlkem.h,v 1.7 2025/08/14 15:48:48 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2024, Google Inc. 3 * Copyright (c) 2025 Bob Beck <beck@obtuse.com>
4 * 4 *
5 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -26,253 +26,202 @@ extern "C" {
26#endif 26#endif
27 27
28/* 28/*
29 * ML-KEM-768 29 * ML-KEM constants
30 *
31 * This implements the Module-Lattice-Based Key-Encapsulation Mechanism from
32 * https://csrc.nist.gov/pubs/fips/204/final
33 */ 30 */
34 31
35/* 32#define RANK768 3
36 * MLKEM768_public_key contains a ML-KEM-768 public key. The contents of this 33#define RANK1024 4
37 * object should never leave the address space since the format is unstable.
38 */
39struct MLKEM768_public_key {
40 union {
41 uint8_t bytes[512 * (3 + 9) + 32 + 32];
42 uint16_t alignment;
43 } opaque;
44};
45
46/*
47 * MLKEM768_private_key contains a ML-KEM-768 private key. The contents of this
48 * object should never leave the address space since the format is unstable.
49 */
50struct MLKEM768_private_key {
51 union {
52 uint8_t bytes[512 * (3 + 3 + 9) + 32 + 32 + 32];
53 uint16_t alignment;
54 } opaque;
55};
56 34
57/* 35/*
58 * MLKEM768_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM768 public 36 * ML-KEM keys
59 * key.
60 */ 37 */
61#define MLKEM768_PUBLIC_KEY_BYTES 1184
62 38
63/* MLKEM_SEED_BYTES is the number of bytes in an ML-KEM seed. */ 39typedef struct MLKEM_private_key_st MLKEM_private_key;
64#define MLKEM_SEED_BYTES 64 40typedef struct MLKEM_public_key_st MLKEM_public_key;
65 41
66/* 42/*
67 * MLKEM_SHARED_SECRET_BYTES is the number of bytes in the ML-KEM768 shared 43 * MLKEM_private_key_new allocates a new uninitialized ML-KEM private key for
68 * secret. Although the round-3 specification has a variable-length output, the 44 * |rank|, which must be RANK768 or RANK1024. It returns a pointer to an
69 * final ML-KEM construction is expected to use a fixed 32-byte output. To 45 * allocated structure suitable for holding a generated private key of the
70 * simplify the future transition, we apply the same restriction. 46 * corresponding rank on success, NULL is returned on failure. The caller is
47 * responsible for deallocating the resulting key with |MLKEM_private_key_free|.
71 */ 48 */
72#define MLKEM_SHARED_SECRET_BYTES 32 49MLKEM_private_key *MLKEM_private_key_new(int rank);
73 50
74/* 51/*
75 * MLKEM_generate_key generates a random public/private key pair, writes the 52 * MLKEM_private_key_free zeroes and frees all memory for |key| if |key| is
76 * encoded public key to |out_encoded_public_key| and sets |out_private_key| to 53 * non NULL. If |key| is NULL it does nothing and returns.
77 * the private key. If |optional_out_seed| is not NULL then the seed used to
78 * generate the private key is written to it.
79 */ 54 */
80int MLKEM768_generate_key( 55void MLKEM_private_key_free(MLKEM_private_key *key);
81 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES],
82 uint8_t optional_out_seed[MLKEM_SEED_BYTES],
83 struct MLKEM768_private_key *out_private_key);
84 56
85/* 57/*
86 * MLKEM768_private_key_from_seed derives a private key from a seed that was 58 * MLKEM_private_key_encoded_length the number of bytes used by the encoded form
87 * generated by |MLKEM768_generate_key|. It fails and returns 0 if |seed_len| is 59 * of |key|. Thie corresponds to the length of the buffer allocated for the
88 * incorrect, otherwise it writes |*out_private_key| and returns 1. 60 * encoded_public_key from |MLKEM_marshal_private_key|. Zero is returned if
61 * |key| is NULL or has an invalid rank.
89 */ 62 */
90int MLKEM768_private_key_from_seed(struct MLKEM768_private_key *out_private_key, 63size_t MLKEM_private_key_encoded_length(const MLKEM_private_key *key);
91 const uint8_t *seed, size_t seed_len);
92 64
93/* 65/*
94 * MLKEM_public_from_private sets |*out_public_key| to the public key that 66 * MLKEM_private_key_ciphertext_length returns the number of bytes of ciphertext
95 * corresponds to |private_key|. (This is faster than parsing the output of 67 * required to decrypt a shared secret with |key| using |MLKEM_decap|. Zero is
96 * |MLKEM_generate_key| if, for some reason, you need to encapsulate to a key 68 * returned if |key| is NULL or has an invalid rank.
97 * that was just generated.)
98 */ 69 */
99void MLKEM768_public_from_private(struct MLKEM768_public_key *out_public_key, 70size_t MLKEM_private_key_ciphertext_length(const MLKEM_private_key *key);
100 const struct MLKEM768_private_key *private_key);
101
102/* MLKEM768_CIPHERTEXT_BYTES is number of bytes in the ML-KEM768 ciphertext. */
103#define MLKEM768_CIPHERTEXT_BYTES 1088
104 71
105/* 72/*
106 * MLKEM768_encap encrypts a random shared secret for |public_key|, writes the 73 * MLKEM_public_key_new allocates a new uninitialized ML-KEM public key for
107 * ciphertext to |out_ciphertext|, and writes the random shared secret to 74 * |rank|, which must be RANK768 or RANK1024. It returns a pointer to an
108 * |out_shared_secret|. 75 * allocated structure suitable for holding a generated public key of the
76 * corresponding rank on success, NULL is returned on failure. The caller is
77 * responsible for deallocating the resulting key with |MLKEM_public_key_free|.
109 */ 78 */
110void MLKEM768_encap(uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES], 79MLKEM_public_key *MLKEM_public_key_new(int rank);
111 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
112 const struct MLKEM768_public_key *public_key);
113 80
114/* 81/*
115 * MLKEM768_decap decrypts a shared secret from |ciphertext| using |private_key| 82 * MLKEM_public_key_free zeros and deallocates all memory for |key| if |key| is
116 * and writes it to |out_shared_secret|. If |ciphertext_len| is incorrect it 83 * non NULL. If |key| is NULL it does nothing and returns.
117 * returns 0, otherwise it rreturns 1. If |ciphertext| is invalid,
118 * |out_shared_secret| is filled with a key that will always be the same for the
119 * same |ciphertext| and |private_key|, but which appears to be random unless
120 * one has access to |private_key|. These alternatives occur in constant time.
121 * Any subsequent symmetric encryption using |out_shared_secret| must use an
122 * authenticated encryption scheme in order to discover the decapsulation
123 * failure.
124 */ 84 */
125int MLKEM768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 85void MLKEM_public_key_free(MLKEM_public_key *key);
126 const uint8_t *ciphertext, size_t ciphertext_len,
127 const struct MLKEM768_private_key *private_key);
128
129/* Serialisation of keys. */
130 86
131/* 87/*
132 * MLKEM768_marshal_public_key serializes |public_key| to |out| in the standard 88 * MLKEM_public_key_encoded_length the number of bytes used by the encoded form
133 * format for ML-KEM public keys. It returns one on success or zero on allocation 89 * of |key|. Thie corresponds to the length of the buffer allocated for the
134 * error. 90 * encoded_public_key from |MLKEM_generate_key| or |MLKEM_marshal_public_key|.
91 * Zero is returned if |key| is NULL or has an invalid rank.
135 */ 92 */
136int MLKEM768_marshal_public_key(uint8_t **output, size_t *output_len, 93size_t MLKEM_public_key_encoded_length(const MLKEM_public_key *key);
137 const struct MLKEM768_public_key *public_key);
138 94
139/* 95/*
140 * MLKEM768_parse_public_key parses a public key, in the format generated by 96 * MLKEM_public_key_cipertext_length returns the number of bytes produced as the
141 * |MLKEM_marshal_public_key|, from |in| and writes the result to 97 * ciphertext when encrypting a shared secret with |key| using |MLKEM_encap|. Zero
142 * |out_public_key|. It returns one on success or zero on parse error or if 98 * is returned if |key| is NULL or has an invalid rank.
143 * there are trailing bytes in |in|.
144 */ 99 */
145int MLKEM768_parse_public_key(struct MLKEM768_public_key *out_public_key, 100size_t MLKEM_public_key_ciphertext_length(const MLKEM_public_key *key);
146 const uint8_t *input, size_t input_len);
147 101
148/* 102/*
149 * MLKEM_parse_private_key parses a private key, in the format generated by 103 * ML-KEM operations
150 * |MLKEM_marshal_private_key|, from |in| and writes the result to
151 * |out_private_key|. It returns one on success or zero on parse error or if
152 * there are trailing bytes in |in|. This formate is verbose and should be avoided.
153 * Private keys should be stored as seeds and parsed using |MLKEM768_private_key_from_seed|.
154 */ 104 */
155int MLKEM768_parse_private_key(struct MLKEM768_private_key *out_private_key,
156 const uint8_t *input, size_t input_len);
157 105
158/* 106/*
159 * ML-KEM-1024 107 * MLKEM_generate_key generates a random private/public key pair, initializing
108 * |private_key|. It returns one on success, and zero on failure or error.
109 * |private_key| must be a new uninitialized key. |*out_encoded_public_key| and
110 * |*out_optional_seed|, if provided, must have the value of NULL. On success, a
111 * pointer to the encoded public key of the correct size for |key| is returned
112 * in |out_encoded_public_key|, and the length in bytes of
113 * |*out_encoded_public_key| is returned in |out_encoded_public_key_len|. If
114 * |out_optional_seed| is not NULL, a pointer to the seed used to generate the
115 * private key is returned in |*out_optional_seed| and the length in bytes of
116 * the seed is returned in |*out_optional_seed_len|. The caller is responsible
117 * for freeing the values returned in |out_encoded_public_key|, and
118 * |out_optional_seed|.
160 * 119 *
161 * ML-KEM-1024 also exists. You should prefer ML-KEM-768 where possible. 120 * In the event a private key needs to be saved, The normal best practice is to
162 */ 121 * save |out_optional_seed| as the private key, along with the ML-KEM rank value.
163 122 * An MLKEM_private_key of the correct rank can then be constructed using
164/* 123 * |MLKEM_private_key_from_seed|.
165 * MLKEM1024_public_key contains an ML-KEM-1024 public key. The contents of this
166 * object should never leave the address space since the format is unstable.
167 */
168struct MLKEM1024_public_key {
169 union {
170 uint8_t bytes[512 * (4 + 16) + 32 + 32];
171 uint16_t alignment;
172 } opaque;
173};
174
175/*
176 * MLKEM1024_private_key contains a ML-KEM-1024 private key. The contents of
177 * this object should never leave the address space since the format is
178 * unstable.
179 */
180struct MLKEM1024_private_key {
181 union {
182 uint8_t bytes[512 * (4 + 4 + 16) + 32 + 32 + 32];
183 uint16_t alignment;
184 } opaque;
185};
186
187/*
188 * MLKEM1024_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM-1024
189 * public key.
190 */ 124 */
191#define MLKEM1024_PUBLIC_KEY_BYTES 1568 125int MLKEM_generate_key(MLKEM_private_key *private_key,
126 uint8_t **out_encoded_public_key, size_t *out_encoded_public_key_len,
127 uint8_t **out_optional_seed, size_t *out_optional_seed_len);
192 128
193/* 129/*
194 * MLKEM1024_generate_key generates a random public/private key pair, writes the 130 * MLKEM_private_key_from_seed derives a private key from a seed that was
195 * encoded public key to |out_encoded_public_key| and sets |out_private_key| to 131 * generated by |MLKEM_generate_key| initializing |private_key|. It returns one
196 * the private key. If |optional_out_seed| is not NULL then the seed used to 132 * on success, and zero on failure or error. |private_key| must be a new
197 * generate the private key is written to it. 133 * uninitialized key. |seed_len| must be MLKEM_SEED_LENGTH.
134 *
135 * For |private_key| to match the key generated by |MLKEM_generate_key|,
136 * |private_key| must have been created with the same rank as used when generating
137 * the key.
198 */ 138 */
199int MLKEM1024_generate_key( 139int MLKEM_private_key_from_seed(MLKEM_private_key *private_key,
200 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES], 140 const uint8_t *seed, size_t seed_len);
201 uint8_t optional_out_seed[MLKEM_SEED_BYTES],
202 struct MLKEM1024_private_key *out_private_key);
203 141
204/* 142/*
205 * MLKEM1024_private_key_from_seed derives a private key from a seed that was 143 * MLKEM_public_from_private initializes |public_key| with the public key that
206 * generated by |MLKEM1024_generate_key|. It fails and returns 0 if |seed_len| 144 * corresponds to |private_key|. It returns one on success and zero on
207 * is incorrect, otherwise it writes |*out_private_key| and returns 1. 145 * error. This is faster than parsing the output of |MLKEM_generate_key| if, for
146 * some reason, you need to encapsulate to a key that was just
147 * generated. |private key| must be a new uninitialized key, of the same rank as
148 * |public_key|.
208 */ 149 */
209int MLKEM1024_private_key_from_seed( 150int MLKEM_public_from_private(const MLKEM_private_key *private_key,
210 struct MLKEM1024_private_key *out_private_key, const uint8_t *seed, 151 MLKEM_public_key *public_key);
211 size_t seed_len);
212 152
213/* 153/*
214 * MLKEM1024_public_from_private sets |*out_public_key| to the public key that 154 * MLKEM_encap encrypts a random shared secret for an initialized
215 * corresponds to |private_key|. (This is faster than parsing the output of 155 * |public_key|. It returns one on success, and zero on failure or error. |*out
216 * |MLKEM1024_generate_key| if, for some reason, you need to encapsulate to a 156 * ciphertext| and |*out_shared_secret| must have the value NULL. On success, a
217 * key that was just generated.) 157 * pointer to the ciphertext of the correct size for |key| is returned in
158 * |out_ciphertext|, the length in bytes of |*out_ciphertext| is returned in
159 * |*out_ciphertext_len|, a pointer to the random shared secret is returned in
160 * |out_shared_secret|, and the length in bytes of |*out_shared_secret| is
161 * returned in |*out_ciphtertext_len|. The caller is responsible for zeroing and
162 * freeing the values returned in |out_ciphertext| and |out_shared_secret|
218 */ 163 */
219void MLKEM1024_public_from_private(struct MLKEM1024_public_key *out_public_key, 164int MLKEM_encap(const MLKEM_public_key *public_key,
220 const struct MLKEM1024_private_key *private_key); 165 uint8_t **out_ciphertext, size_t *out_ciphertext_len,
221 166 uint8_t **out_shared_secret, size_t *out_shared_secret_len);
222/* MLKEM1024_CIPHERTEXT_BYTES is number of bytes in the ML-KEM-1024 ciphertext. */
223#define MLKEM1024_CIPHERTEXT_BYTES 1568
224 167
225/* 168/*
226 * MLKEM1024_encap encrypts a random shared secret for |public_key|, writes the 169 * MLKEM_decap decrypts a shared secret from |ciphertext| using an initialized
227 * ciphertext to |out_ciphertext|, and writes the random shared secret to 170 * |private_key|. It returns a pointer to the shared secret|out_shared_secret|
228 * |out_shared_secret|. 171 * and the length in bytes of |*out_shared_secret| in |*out_shared_secret_len|.
229 */ 172 *
230void MLKEM1024_encap(uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES], 173 * If |ciphertext_len| is incorrect for |private_key|, |*out_shared_secret| is
231 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 174 * not NULL, or memory can not be allocated, it returns zero, otherwise it
232 const struct MLKEM1024_public_key *public_key); 175 * returns one. If |ciphertext| is invalid, a pointer is returned in
233 176 * |out_shared_secret| pointing to a key that will always be the same for the
234/* 177 * same |ciphertext| and |private_key|, but which appears to be random unless
235 * MLKEM1024_decap decrypts a shared secret from |ciphertext| using 178 * one has access to |private_key|. These alternatives occur in constant time.
236 * |private_key| and writes it to |out_shared_secret|. If |ciphertext_len| is 179 * Any subsequent symmetric encryption using |out_shared_secret| must use an
237 * incorrect it returns 0, otherwise it returns 1. If |ciphertext| is invalid 180 * authenticated encryption scheme in order to discover the decapsulation
238 * (but of the correct length), |out_shared_secret| is filled with a key that 181 * failure. The caller is responsible for zeroing and freeing the value returned
239 * will always be the same for the same |ciphertext| and |private_key|, but 182 * in |out_shared_secret|.
240 * which appears to be random unless one has access to |private_key|. These
241 * alternatives occur in constant time. Any subsequent symmetric encryption
242 * using |out_shared_secret| must use an authenticated encryption scheme in
243 * order to discover the decapsulation failure.
244 */ 183 */
245int MLKEM1024_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 184int MLKEM_decap(const MLKEM_private_key *private_key,
246 const uint8_t *ciphertext, size_t ciphertext_len, 185 const uint8_t *ciphertext, size_t ciphertext_len,
247 const struct MLKEM1024_private_key *private_key); 186 uint8_t **out_shared_secret, size_t *out_shared_secret_len);
187
188/* Serialization of ML-KEM keys. */
248 189
249/* 190/*
250 * Serialisation of ML-KEM-1024 keys. 191 * MLKEM_marshal_public_key serializes an initialized |public_key| in the
251 * MLKEM1024_marshal_public_key serializes |public_key| to |out| in the standard 192 * standard format for ML-KEM public keys. It returns one on success or zero on
252 * format for ML-KEM-1024 public keys. It returns one on success or zero on 193 * allocation error or failure. |*out| must have the value NULL. On success a
253 * allocation error. 194 * pointer is returned in |out| to the encoded public key matching |public_key|,
195 * and a pointer to the length in bytes of the encoded public key is stored in
196 * |out_len|. The caller is responsible for freeing the values returned in
197 * |out|.
254 */ 198 */
255int MLKEM1024_marshal_public_key(uint8_t **output, size_t *output_len, 199int MLKEM_marshal_public_key(const MLKEM_public_key *public_key, uint8_t **out,
256 const struct MLKEM1024_public_key *public_key); 200 size_t *out_len);
257 201
258/* 202/*
259 * MLKEM1024_parse_public_key parses a public key, in the format generated by 203 * MLKEM_parse_public_key parses a public key, in the format generated by
260 * |MLKEM1024_marshal_public_key|, from |in| and writes the result to 204 * |MLKEM_marshal_public_key|, from |in|. It returns one on success or zero on
261 * |out_public_key|. It returns one on success or zero on parse error or if 205 * error or failure. |public_key| must be a new uninitialized key. |in_len| must
262 * there are trailing bytes in |in|. 206 * be the correct length for the encoded format of |public_key. On success
207 * |public_key| is initialized to the value parsed from |in|.
263 */ 208 */
264int MLKEM1024_parse_public_key(struct MLKEM1024_public_key *out_public_key, 209int MLKEM_parse_public_key(MLKEM_public_key *public_key, const uint8_t *in,
265 const uint8_t *input, size_t input_len); 210 size_t in_len);
266 211
267/* 212/*
268 * MLKEM1024_parse_private_key parses a private key, in NIST's format for 213 * MLKEM_parse_private_key parses a private key, in the format generated by
269 * private keys, from |in| and writes the result to |out_private_key|. It 214 * |MLKEM_marshal_private_key|, from |in|. It returns one on success or zero on
270 * returns one on success or zero on parse error or if there are trailing bytes 215 * error or failure. |private_key| must be a new uninitialized key. |in_len|
271 * in |in|. This format is verbose and should be avoided. Private keys should be 216 * must be the correct length for the encoded format of |private_key. On success
272 * stored as seeds and parsed using |MLKEM1024_private_key_from_seed|. 217 * |private_key| is initialized to the value parsed from |in|.
218 *
219 * This format is wastefully verbose and should be avoided. Private keys should
220 * be stored as seeds from |MLKEM_generate_key|, and then parsed using
221 * |MLKEM_private_key_from_seed|.
273 */ 222 */
274int MLKEM1024_parse_private_key(struct MLKEM1024_private_key *out_private_key, 223int MLKEM_parse_private_key(MLKEM_private_key *private_key, const uint8_t *in,
275 const uint8_t *input, size_t input_len); 224 size_t in_len);
276 225
277#if defined(__cplusplus) 226#if defined(__cplusplus)
278} 227}
diff --git a/src/lib/libcrypto/mlkem/mlkem1024.c b/src/lib/libcrypto/mlkem/mlkem1024.c
index 26c4716539..8f4f41f8ff 100644
--- a/src/lib/libcrypto/mlkem/mlkem1024.c
+++ b/src/lib/libcrypto/mlkem/mlkem1024.c
@@ -1,7 +1,7 @@
1/* $OpenBSD: mlkem1024.c,v 1.11 2025/05/21 02:18:11 kenjiro Exp $ */ 1/* $OpenBSD: mlkem1024.c,v 1.12 2025/08/14 15:48:48 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2024, Google Inc. 3 * Copyright (c) 2024, Google Inc.
4 * Copyright (c) 2024, Bob Beck <beck@obtuse.com> 4 * Copyright (c) 2024, 2025 Bob Beck <beck@obtuse.com>
5 * 5 *
6 * Permission to use, copy, modify, and/or distribute this software for any 6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above 7 * purpose with or without fee is hereby granted, provided that the above
@@ -20,18 +20,14 @@
20#include <stdlib.h> 20#include <stdlib.h>
21#include <string.h> 21#include <string.h>
22 22
23#include "bytestring.h" 23#include <openssl/mlkem.h>
24#include "mlkem.h"
25 24
25#include "bytestring.h"
26#include "sha3_internal.h" 26#include "sha3_internal.h"
27#include "mlkem_internal.h" 27#include "mlkem_internal.h"
28#include "constant_time.h" 28#include "constant_time.h"
29#include "crypto_internal.h" 29#include "crypto_internal.h"
30 30
31/* Remove later */
32#undef LCRYPTO_ALIAS
33#define LCRYPTO_ALIAS(A)
34
35/* 31/*
36 * See 32 * See
37 * https://csrc.nist.gov/pubs/fips/203/final 33 * https://csrc.nist.gov/pubs/fips/203/final
@@ -80,7 +76,6 @@ kdf(uint8_t out[MLKEM_SHARED_SECRET_BYTES], const uint8_t failure_secret[32],
80} 76}
81 77
82#define DEGREE 256 78#define DEGREE 256
83#define RANK1024 4
84 79
85static const size_t kBarrettMultiplier = 5039; 80static const size_t kBarrettMultiplier = 5039;
86static const unsigned kBarrettShift = 24; 81static const unsigned kBarrettShift = 24;
@@ -809,9 +804,11 @@ struct public_key {
809CTASSERT(sizeof(struct MLKEM1024_public_key) == sizeof(struct public_key)); 804CTASSERT(sizeof(struct MLKEM1024_public_key) == sizeof(struct public_key));
810 805
811static struct public_key * 806static struct public_key *
812public_key_1024_from_external(const struct MLKEM1024_public_key *external) 807public_key_1024_from_external(const MLKEM_public_key *external)
813{ 808{
814 return (struct public_key *)external; 809 if (external->rank != RANK1024)
810 return NULL;
811 return (struct public_key *)external->key_1024;
815} 812}
816 813
817struct private_key { 814struct private_key {
@@ -823,9 +820,11 @@ struct private_key {
823CTASSERT(sizeof(struct MLKEM1024_private_key) == sizeof(struct private_key)); 820CTASSERT(sizeof(struct MLKEM1024_private_key) == sizeof(struct private_key));
824 821
825static struct private_key * 822static struct private_key *
826private_key_1024_from_external(const struct MLKEM1024_private_key *external) 823private_key_1024_from_external(const MLKEM_private_key *external)
827{ 824{
828 return (struct private_key *)external; 825 if (external->rank != RANK1024)
826 return NULL;
827 return (struct private_key *)external->key_1024;
829} 828}
830 829
831/* 830/*
@@ -835,7 +834,7 @@ private_key_1024_from_external(const struct MLKEM1024_private_key *external)
835int 834int
836MLKEM1024_generate_key(uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES], 835MLKEM1024_generate_key(uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES],
837 uint8_t optional_out_seed[MLKEM_SEED_BYTES], 836 uint8_t optional_out_seed[MLKEM_SEED_BYTES],
838 struct MLKEM1024_private_key *out_private_key) 837 MLKEM_private_key *out_private_key)
839{ 838{
840 uint8_t entropy_buf[MLKEM_SEED_BYTES]; 839 uint8_t entropy_buf[MLKEM_SEED_BYTES];
841 uint8_t *entropy = optional_out_seed != NULL ? optional_out_seed : 840 uint8_t *entropy = optional_out_seed != NULL ? optional_out_seed :
@@ -845,10 +844,9 @@ MLKEM1024_generate_key(uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES
845 return MLKEM1024_generate_key_external_entropy(out_encoded_public_key, 844 return MLKEM1024_generate_key_external_entropy(out_encoded_public_key,
846 out_private_key, entropy); 845 out_private_key, entropy);
847} 846}
848LCRYPTO_ALIAS(MLKEM1024_generate_key);
849 847
850int 848int
851MLKEM1024_private_key_from_seed(struct MLKEM1024_private_key *out_private_key, 849MLKEM1024_private_key_from_seed(MLKEM_private_key *out_private_key,
852 const uint8_t *seed, size_t seed_len) 850 const uint8_t *seed, size_t seed_len)
853{ 851{
854 uint8_t public_key_bytes[MLKEM1024_PUBLIC_KEY_BYTES]; 852 uint8_t public_key_bytes[MLKEM1024_PUBLIC_KEY_BYTES];
@@ -859,7 +857,6 @@ MLKEM1024_private_key_from_seed(struct MLKEM1024_private_key *out_private_key,
859 return MLKEM1024_generate_key_external_entropy(public_key_bytes, 857 return MLKEM1024_generate_key_external_entropy(public_key_bytes,
860 out_private_key, seed); 858 out_private_key, seed);
861} 859}
862LCRYPTO_ALIAS(MLKEM1024_private_key_from_seed);
863 860
864static int 861static int
865mlkem_marshal_public_key(CBB *out, const struct public_key *pub) 862mlkem_marshal_public_key(CBB *out, const struct public_key *pub)
@@ -872,7 +869,7 @@ mlkem_marshal_public_key(CBB *out, const struct public_key *pub)
872int 869int
873MLKEM1024_generate_key_external_entropy( 870MLKEM1024_generate_key_external_entropy(
874 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES], 871 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES],
875 struct MLKEM1024_private_key *out_private_key, 872 MLKEM_private_key *out_private_key,
876 const uint8_t entropy[MLKEM_SEED_BYTES]) 873 const uint8_t entropy[MLKEM_SEED_BYTES])
877{ 874{
878 struct private_key *priv = private_key_1024_from_external( 875 struct private_key *priv = private_key_1024_from_external(
@@ -920,8 +917,8 @@ MLKEM1024_generate_key_external_entropy(
920} 917}
921 918
922void 919void
923MLKEM1024_public_from_private(struct MLKEM1024_public_key *out_public_key, 920MLKEM1024_public_from_private(const MLKEM_private_key *private_key,
924 const struct MLKEM1024_private_key *private_key) 921 MLKEM_public_key *out_public_key)
925{ 922{
926 struct public_key *const pub = public_key_1024_from_external( 923 struct public_key *const pub = public_key_1024_from_external(
927 out_public_key); 924 out_public_key);
@@ -930,7 +927,6 @@ MLKEM1024_public_from_private(struct MLKEM1024_public_key *out_public_key,
930 927
931 *pub = priv->pub; 928 *pub = priv->pub;
932} 929}
933LCRYPTO_ALIAS(MLKEM1024_public_from_private);
934 930
935/* 931/*
936 * Encrypts a message with given randomness to the ciphertext in |out|. Without 932 * Encrypts a message with given randomness to the ciphertext in |out|. Without
@@ -972,9 +968,9 @@ encrypt_cpa(uint8_t out[MLKEM1024_CIPHERTEXT_BYTES],
972 968
973/* Calls MLKEM1024_encap_external_entropy| with random bytes */ 969/* Calls MLKEM1024_encap_external_entropy| with random bytes */
974void 970void
975MLKEM1024_encap(uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES], 971MLKEM1024_encap(const MLKEM_public_key *public_key,
976 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 972 uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES],
977 const struct MLKEM1024_public_key *public_key) 973 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES])
978{ 974{
979 uint8_t entropy[MLKEM_ENCAP_ENTROPY]; 975 uint8_t entropy[MLKEM_ENCAP_ENTROPY];
980 976
@@ -982,14 +978,13 @@ MLKEM1024_encap(uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES],
982 MLKEM1024_encap_external_entropy(out_ciphertext, out_shared_secret, 978 MLKEM1024_encap_external_entropy(out_ciphertext, out_shared_secret,
983 public_key, entropy); 979 public_key, entropy);
984} 980}
985LCRYPTO_ALIAS(MLKEM1024_encap);
986 981
987/* See section 6.2 of the spec. */ 982/* See section 6.2 of the spec. */
988void 983void
989MLKEM1024_encap_external_entropy( 984MLKEM1024_encap_external_entropy(
990 uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES], 985 uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES],
991 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 986 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
992 const struct MLKEM1024_public_key *public_key, 987 const MLKEM_public_key *public_key,
993 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]) 988 const uint8_t entropy[MLKEM_ENCAP_ENTROPY])
994{ 989{
995 const struct public_key *pub = public_key_1024_from_external(public_key); 990 const struct public_key *pub = public_key_1024_from_external(public_key);
@@ -1025,10 +1020,10 @@ decrypt_cpa(uint8_t out[32], const struct private_key *priv,
1025 1020
1026/* See section 6.3 */ 1021/* See section 6.3 */
1027int 1022int
1028MLKEM1024_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 1023MLKEM1024_decap(const MLKEM_private_key *private_key,
1029 const uint8_t *ciphertext, size_t ciphertext_len, 1024 const uint8_t *ciphertext, size_t ciphertext_len,
1030 const struct MLKEM1024_private_key *private_key) 1025 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES])
1031{ 1026 {
1032 const struct private_key *priv = private_key_1024_from_external( 1027 const struct private_key *priv = private_key_1024_from_external(
1033 private_key); 1028 private_key);
1034 uint8_t expected_ciphertext[MLKEM1024_CIPHERTEXT_BYTES]; 1029 uint8_t expected_ciphertext[MLKEM1024_CIPHERTEXT_BYTES];
@@ -1059,11 +1054,10 @@ MLKEM1024_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
1059 1054
1060 return 1; 1055 return 1;
1061} 1056}
1062LCRYPTO_ALIAS(MLKEM1024_decap);
1063 1057
1064int 1058int
1065MLKEM1024_marshal_public_key(uint8_t **output, size_t *output_len, 1059MLKEM1024_marshal_public_key(const MLKEM_public_key *public_key,
1066 const struct MLKEM1024_public_key *public_key) 1060 uint8_t **output, size_t *output_len)
1067{ 1061{
1068 int ret = 0; 1062 int ret = 0;
1069 CBB cbb; 1063 CBB cbb;
@@ -1083,7 +1077,6 @@ MLKEM1024_marshal_public_key(uint8_t **output, size_t *output_len,
1083 1077
1084 return ret; 1078 return ret;
1085} 1079}
1086LCRYPTO_ALIAS(MLKEM1024_marshal_public_key);
1087 1080
1088/* 1081/*
1089 * mlkem_parse_public_key_no_hash parses |in| into |pub| but doesn't calculate 1082 * mlkem_parse_public_key_no_hash parses |in| into |pub| but doesn't calculate
@@ -1107,8 +1100,8 @@ mlkem_parse_public_key_no_hash(struct public_key *pub, CBS *in)
1107} 1100}
1108 1101
1109int 1102int
1110MLKEM1024_parse_public_key(struct MLKEM1024_public_key *public_key, 1103MLKEM1024_parse_public_key(const uint8_t *input, size_t input_len,
1111 const uint8_t *input, size_t input_len) 1104 MLKEM_public_key *public_key)
1112{ 1105{
1113 struct public_key *pub = public_key_1024_from_external(public_key); 1106 struct public_key *pub = public_key_1024_from_external(public_key);
1114 CBS cbs; 1107 CBS cbs;
@@ -1123,10 +1116,9 @@ MLKEM1024_parse_public_key(struct MLKEM1024_public_key *public_key,
1123 1116
1124 return 1; 1117 return 1;
1125} 1118}
1126LCRYPTO_ALIAS(MLKEM1024_parse_public_key);
1127 1119
1128int 1120int
1129MLKEM1024_marshal_private_key(const struct MLKEM1024_private_key *private_key, 1121MLKEM1024_marshal_private_key(const MLKEM_private_key *private_key,
1130 uint8_t **out_private_key, size_t *out_private_key_len) 1122 uint8_t **out_private_key, size_t *out_private_key_len)
1131{ 1123{
1132 const struct private_key *const priv = private_key_1024_from_external( 1124 const struct private_key *const priv = private_key_1024_from_external(
@@ -1160,8 +1152,8 @@ MLKEM1024_marshal_private_key(const struct MLKEM1024_private_key *private_key,
1160} 1152}
1161 1153
1162int 1154int
1163MLKEM1024_parse_private_key(struct MLKEM1024_private_key *out_private_key, 1155MLKEM1024_parse_private_key(const uint8_t *input, size_t input_len,
1164 const uint8_t *input, size_t input_len) 1156 MLKEM_private_key *out_private_key)
1165{ 1157{
1166 struct private_key *const priv = private_key_1024_from_external( 1158 struct private_key *const priv = private_key_1024_from_external(
1167 out_private_key); 1159 out_private_key);
@@ -1189,4 +1181,3 @@ MLKEM1024_parse_private_key(struct MLKEM1024_private_key *out_private_key,
1189 1181
1190 return 1; 1182 return 1;
1191} 1183}
1192LCRYPTO_ALIAS(MLKEM1024_parse_private_key);
diff --git a/src/lib/libcrypto/mlkem/mlkem768.c b/src/lib/libcrypto/mlkem/mlkem768.c
index 653b92d8d8..1a44b9413f 100644
--- a/src/lib/libcrypto/mlkem/mlkem768.c
+++ b/src/lib/libcrypto/mlkem/mlkem768.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mlkem768.c,v 1.12 2025/05/20 00:30:38 beck Exp $ */ 1/* $OpenBSD: mlkem768.c,v 1.13 2025/08/14 15:48:48 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2024, Google Inc. 3 * Copyright (c) 2024, Google Inc.
4 * Copyright (c) 2024, Bob Beck <beck@obtuse.com> 4 * Copyright (c) 2024, Bob Beck <beck@obtuse.com>
@@ -19,19 +19,16 @@
19#include <assert.h> 19#include <assert.h>
20#include <stdlib.h> 20#include <stdlib.h>
21#include <string.h> 21#include <string.h>
22#include <stdio.h>
22 23
23#include "bytestring.h" 24#include <openssl/mlkem.h>
24#include "mlkem.h"
25 25
26#include "bytestring.h"
26#include "sha3_internal.h" 27#include "sha3_internal.h"
27#include "mlkem_internal.h" 28#include "mlkem_internal.h"
28#include "constant_time.h" 29#include "constant_time.h"
29#include "crypto_internal.h" 30#include "crypto_internal.h"
30 31
31/* Remove later */
32#undef LCRYPTO_ALIAS
33#define LCRYPTO_ALIAS(A)
34
35/* 32/*
36 * See 33 * See
37 * https://csrc.nist.gov/pubs/fips/203/final 34 * https://csrc.nist.gov/pubs/fips/203/final
@@ -80,7 +77,6 @@ kdf(uint8_t out[MLKEM_SHARED_SECRET_BYTES], const uint8_t failure_secret[32],
80} 77}
81 78
82#define DEGREE 256 79#define DEGREE 256
83#define RANK768 3
84 80
85static const size_t kBarrettMultiplier = 5039; 81static const size_t kBarrettMultiplier = 5039;
86static const unsigned kBarrettShift = 24; 82static const unsigned kBarrettShift = 24;
@@ -809,9 +805,11 @@ struct public_key {
809CTASSERT(sizeof(struct MLKEM768_public_key) == sizeof(struct public_key)); 805CTASSERT(sizeof(struct MLKEM768_public_key) == sizeof(struct public_key));
810 806
811static struct public_key * 807static struct public_key *
812public_key_768_from_external(const struct MLKEM768_public_key *external) 808public_key_768_from_external(const MLKEM_public_key *external)
813{ 809{
814 return (struct public_key *)external; 810 if (external->rank != RANK768)
811 return NULL;
812 return (struct public_key *)external->key_768;
815} 813}
816 814
817struct private_key { 815struct private_key {
@@ -823,9 +821,11 @@ struct private_key {
823CTASSERT(sizeof(struct MLKEM768_private_key) == sizeof(struct private_key)); 821CTASSERT(sizeof(struct MLKEM768_private_key) == sizeof(struct private_key));
824 822
825static struct private_key * 823static struct private_key *
826private_key_768_from_external(const struct MLKEM768_private_key *external) 824private_key_768_from_external(const MLKEM_private_key *external)
827{ 825{
828 return (struct private_key *)external; 826 if (external->rank != RANK768)
827 return NULL;
828 return (struct private_key *)external->key_768;
829} 829}
830 830
831/* 831/*
@@ -835,7 +835,7 @@ private_key_768_from_external(const struct MLKEM768_private_key *external)
835int 835int
836MLKEM768_generate_key(uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES], 836MLKEM768_generate_key(uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES],
837 uint8_t optional_out_seed[MLKEM_SEED_BYTES], 837 uint8_t optional_out_seed[MLKEM_SEED_BYTES],
838 struct MLKEM768_private_key *out_private_key) 838 MLKEM_private_key *out_private_key)
839{ 839{
840 uint8_t entropy_buf[MLKEM_SEED_BYTES]; 840 uint8_t entropy_buf[MLKEM_SEED_BYTES];
841 uint8_t *entropy = optional_out_seed != NULL ? optional_out_seed : 841 uint8_t *entropy = optional_out_seed != NULL ? optional_out_seed :
@@ -845,12 +845,12 @@ MLKEM768_generate_key(uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES],
845 return MLKEM768_generate_key_external_entropy(out_encoded_public_key, 845 return MLKEM768_generate_key_external_entropy(out_encoded_public_key,
846 out_private_key, entropy); 846 out_private_key, entropy);
847} 847}
848LCRYPTO_ALIAS(MLKEM768_generate_key);
849 848
850int 849int
851MLKEM768_private_key_from_seed(struct MLKEM768_private_key *out_private_key, 850MLKEM768_private_key_from_seed(const uint8_t *seed, size_t seed_len,
852 const uint8_t *seed, size_t seed_len) 851 MLKEM_private_key *out_private_key)
853{ 852{
853 /* XXX stack */
854 uint8_t public_key_bytes[MLKEM768_PUBLIC_KEY_BYTES]; 854 uint8_t public_key_bytes[MLKEM768_PUBLIC_KEY_BYTES];
855 855
856 if (seed_len != MLKEM_SEED_BYTES) { 856 if (seed_len != MLKEM_SEED_BYTES) {
@@ -859,7 +859,6 @@ MLKEM768_private_key_from_seed(struct MLKEM768_private_key *out_private_key,
859 return MLKEM768_generate_key_external_entropy(public_key_bytes, 859 return MLKEM768_generate_key_external_entropy(public_key_bytes,
860 out_private_key, seed); 860 out_private_key, seed);
861} 861}
862LCRYPTO_ALIAS(MLKEM768_private_key_from_seed);
863 862
864static int 863static int
865mlkem_marshal_public_key(CBB *out, const struct public_key *pub) 864mlkem_marshal_public_key(CBB *out, const struct public_key *pub)
@@ -872,7 +871,7 @@ mlkem_marshal_public_key(CBB *out, const struct public_key *pub)
872int 871int
873MLKEM768_generate_key_external_entropy( 872MLKEM768_generate_key_external_entropy(
874 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES], 873 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES],
875 struct MLKEM768_private_key *out_private_key, 874 MLKEM_private_key *out_private_key,
876 const uint8_t entropy[MLKEM_SEED_BYTES]) 875 const uint8_t entropy[MLKEM_SEED_BYTES])
877{ 876{
878 struct private_key *priv = private_key_768_from_external( 877 struct private_key *priv = private_key_768_from_external(
@@ -920,9 +919,8 @@ MLKEM768_generate_key_external_entropy(
920} 919}
921 920
922void 921void
923MLKEM768_public_from_private(struct MLKEM768_public_key *out_public_key, 922MLKEM768_public_from_private(const MLKEM_private_key *private_key,
924 const struct MLKEM768_private_key *private_key) 923 MLKEM_public_key *out_public_key) {
925{
926 struct public_key *const pub = public_key_768_from_external( 924 struct public_key *const pub = public_key_768_from_external(
927 out_public_key); 925 out_public_key);
928 const struct private_key *const priv = private_key_768_from_external( 926 const struct private_key *const priv = private_key_768_from_external(
@@ -930,7 +928,6 @@ MLKEM768_public_from_private(struct MLKEM768_public_key *out_public_key,
930 928
931 *pub = priv->pub; 929 *pub = priv->pub;
932} 930}
933LCRYPTO_ALIAS(MLKEM768_public_from_private);
934 931
935/* 932/*
936 * Encrypts a message with given randomness to the ciphertext in |out|. Without 933 * Encrypts a message with given randomness to the ciphertext in |out|. Without
@@ -972,9 +969,9 @@ encrypt_cpa(uint8_t out[MLKEM768_CIPHERTEXT_BYTES],
972 969
973/* Calls MLKEM768_encap_external_entropy| with random bytes */ 970/* Calls MLKEM768_encap_external_entropy| with random bytes */
974void 971void
975MLKEM768_encap(uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES], 972MLKEM768_encap(const MLKEM_public_key *public_key,
976 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 973 uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES],
977 const struct MLKEM768_public_key *public_key) 974 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES])
978{ 975{
979 uint8_t entropy[MLKEM_ENCAP_ENTROPY]; 976 uint8_t entropy[MLKEM_ENCAP_ENTROPY];
980 977
@@ -982,14 +979,13 @@ MLKEM768_encap(uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES],
982 MLKEM768_encap_external_entropy(out_ciphertext, 979 MLKEM768_encap_external_entropy(out_ciphertext,
983 out_shared_secret, public_key, entropy); 980 out_shared_secret, public_key, entropy);
984} 981}
985LCRYPTO_ALIAS(MLKEM768_encap);
986 982
987/* See section 6.2 of the spec. */ 983/* See section 6.2 of the spec. */
988void 984void
989MLKEM768_encap_external_entropy( 985MLKEM768_encap_external_entropy(
990 uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES], 986 uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES],
991 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 987 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
992 const struct MLKEM768_public_key *public_key, 988 const MLKEM_public_key *public_key,
993 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]) 989 const uint8_t entropy[MLKEM_ENCAP_ENTROPY])
994{ 990{
995 const struct public_key *pub = public_key_768_from_external(public_key); 991 const struct public_key *pub = public_key_768_from_external(public_key);
@@ -1025,9 +1021,8 @@ decrypt_cpa(uint8_t out[32], const struct private_key *priv,
1025 1021
1026/* See section 6.3 */ 1022/* See section 6.3 */
1027int 1023int
1028MLKEM768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 1024MLKEM768_decap(const MLKEM_private_key *private_key, const uint8_t *ciphertext,
1029 const uint8_t *ciphertext, size_t ciphertext_len, 1025 size_t ciphertext_len, uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES])
1030 const struct MLKEM768_private_key *private_key)
1031{ 1026{
1032 const struct private_key *priv = private_key_768_from_external( 1027 const struct private_key *priv = private_key_768_from_external(
1033 private_key); 1028 private_key);
@@ -1059,11 +1054,10 @@ MLKEM768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
1059 1054
1060 return 1; 1055 return 1;
1061} 1056}
1062LCRYPTO_ALIAS(MLKEM768_decap);
1063 1057
1064int 1058int
1065MLKEM768_marshal_public_key(uint8_t **output, size_t *output_len, 1059MLKEM768_marshal_public_key(const MLKEM_public_key *public_key,
1066 const struct MLKEM768_public_key *public_key) 1060 uint8_t **output, size_t *output_len)
1067{ 1061{
1068 int ret = 0; 1062 int ret = 0;
1069 CBB cbb; 1063 CBB cbb;
@@ -1083,7 +1077,6 @@ MLKEM768_marshal_public_key(uint8_t **output, size_t *output_len,
1083 1077
1084 return ret; 1078 return ret;
1085} 1079}
1086LCRYPTO_ALIAS(MLKEM768_marshal_public_key);
1087 1080
1088/* 1081/*
1089 * mlkem_parse_public_key_no_hash parses |in| into |pub| but doesn't calculate 1082 * mlkem_parse_public_key_no_hash parses |in| into |pub| but doesn't calculate
@@ -1107,8 +1100,8 @@ mlkem_parse_public_key_no_hash(struct public_key *pub, CBS *in)
1107} 1100}
1108 1101
1109int 1102int
1110MLKEM768_parse_public_key(struct MLKEM768_public_key *public_key, 1103MLKEM768_parse_public_key(const uint8_t *input, size_t input_len,
1111 const uint8_t *input, size_t input_len) 1104 MLKEM_public_key *public_key)
1112{ 1105{
1113 struct public_key *pub = public_key_768_from_external(public_key); 1106 struct public_key *pub = public_key_768_from_external(public_key);
1114 CBS cbs; 1107 CBS cbs;
@@ -1123,10 +1116,9 @@ MLKEM768_parse_public_key(struct MLKEM768_public_key *public_key,
1123 1116
1124 return 1; 1117 return 1;
1125} 1118}
1126LCRYPTO_ALIAS(MLKEM768_parse_public_key);
1127 1119
1128int 1120int
1129MLKEM768_marshal_private_key(const struct MLKEM768_private_key *private_key, 1121MLKEM768_marshal_private_key(const MLKEM_private_key *private_key,
1130 uint8_t **out_private_key, size_t *out_private_key_len) 1122 uint8_t **out_private_key, size_t *out_private_key_len)
1131{ 1123{
1132 const struct private_key *const priv = private_key_768_from_external( 1124 const struct private_key *const priv = private_key_768_from_external(
@@ -1160,8 +1152,8 @@ MLKEM768_marshal_private_key(const struct MLKEM768_private_key *private_key,
1160} 1152}
1161 1153
1162int 1154int
1163MLKEM768_parse_private_key(struct MLKEM768_private_key *out_private_key, 1155MLKEM768_parse_private_key(const uint8_t *input, size_t input_len,
1164 const uint8_t *input, size_t input_len) 1156 MLKEM_private_key *out_private_key)
1165{ 1157{
1166 struct private_key *const priv = private_key_768_from_external( 1158 struct private_key *const priv = private_key_768_from_external(
1167 out_private_key); 1159 out_private_key);
@@ -1189,4 +1181,3 @@ MLKEM768_parse_private_key(struct MLKEM768_private_key *out_private_key,
1189 1181
1190 return 1; 1182 return 1;
1191} 1183}
1192LCRYPTO_ALIAS(MLKEM768_parse_private_key);
diff --git a/src/lib/libcrypto/mlkem/mlkem_internal.h b/src/lib/libcrypto/mlkem/mlkem_internal.h
index 1e051970a8..776f8aac17 100644
--- a/src/lib/libcrypto/mlkem/mlkem_internal.h
+++ b/src/lib/libcrypto/mlkem/mlkem_internal.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: mlkem_internal.h,v 1.7 2025/05/20 00:33:40 beck Exp $ */ 1/* $OpenBSD: mlkem_internal.h,v 1.8 2025/08/14 15:48:48 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2023, Google Inc. 3 * Copyright (c) 2023, Google Inc.
4 * 4 *
@@ -26,6 +26,253 @@ extern "C" {
26#endif 26#endif
27 27
28__BEGIN_HIDDEN_DECLS 28__BEGIN_HIDDEN_DECLS
29/*
30 * MLKEM_SEED_LENGTH is the number of bytes in an ML-KEM seed. An ML-KEM
31 * seed is normally used to represent a private key.
32 */
33#define MLKEM_SEED_LENGTH 64
34
35/*
36 * MLKEM_SHARED_SECRET_LENGTH is the number of bytes in an ML-KEM shared
37 * secret.
38 */
39#define MLKEM_SHARED_SECRET_LENGTH 32
40
41/*
42 * |MLKEM_encap_external_entropy| behaves exactly like the public |MLKEM_encap|
43 * with the entropy provided by the caller. It is directly called internally
44 * and by tests.
45 */
46int
47MLKEM_encap_external_entropy(const MLKEM_public_key *public_key,
48 const uint8_t *entropy, uint8_t **out_ciphertext,
49 size_t *out_ciphertext_len, uint8_t **out_shared_secret,
50 size_t *out_shared_secret_len);
51
52/*
53 * |MLKEM_generate_key_external_entropy| behaves exactly like the public
54 * |MLKEM_generate_key| with the entropy provided by the caller.
55 * It is directly called internally and by tests.
56 */
57int
58MLKEM_generate_key_external_entropy(MLKEM_private_key *private_key,
59 uint8_t **out_encoded_public_key, size_t *out_encoded_public_key_len,
60 const uint8_t *entropy);
61/*
62 * Marshals a private key to encoded format, used for NIST tests.
63 */
64int MLKEM_marshal_private_key(const MLKEM_private_key *private_key,
65 uint8_t **out, size_t *out_len);
66
67/*
68 * ML-KEM-768
69 *
70 * This implements the Module-Lattice-Based Key-Encapsulation Mechanism from
71 * https://csrc.nist.gov/pubs/fips/204/final
72 */
73
74/*
75 * MLKEM768_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM768 public
76 * key.
77 */
78#define MLKEM768_PUBLIC_KEY_BYTES 1184
79
80/* MLKEM_SEED_BYTES is the number of bytes in an ML-KEM seed. */
81#define MLKEM_SEED_BYTES 64
82
83/*
84 * MLKEM_SHARED_SECRET_BYTES is the number of bytes in the ML-KEM768 shared
85 * secret. Although the round-3 specification has a variable-length output, the
86 * final ML-KEM construction is expected to use a fixed 32-byte output. To
87 * simplify the future transition, we apply the same restriction.
88 */
89#define MLKEM_SHARED_SECRET_BYTES 32
90
91/*
92 * MLKEM_generate_key generates a random public/private key pair, writes the
93 * encoded public key to |out_encoded_public_key| and sets |out_private_key| to
94 * the private key. If |optional_out_seed| is not NULL then the seed used to
95 * generate the private key is written to it.
96 */
97int MLKEM768_generate_key(
98 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES],
99 uint8_t optional_out_seed[MLKEM_SEED_BYTES],
100 MLKEM_private_key *out_private_key);
101
102/*
103 * MLKEM768_private_key_from_seed derives a private key from a seed that was
104 * generated by |MLKEM768_generate_key|. It fails and returns 0 if |seed_len| is
105 * incorrect, otherwise it writes |*out_private_key| and returns 1.
106 */
107int MLKEM768_private_key_from_seed(const uint8_t *seed, size_t seed_len,
108 MLKEM_private_key *out_private_key);
109
110/*
111 * MLKEM_public_from_private sets |*out_public_key| to the public key that
112 * corresponds to |private_key|. (This is faster than parsing the output of
113 * |MLKEM_generate_key| if, for some reason, you need to encapsulate to a key
114 * that was just generated.)
115 */
116void MLKEM768_public_from_private(const MLKEM_private_key *private_key,
117 MLKEM_public_key *out_public_key);
118
119/* MLKEM768_CIPHERTEXT_BYTES is number of bytes in the ML-KEM768 ciphertext. */
120#define MLKEM768_CIPHERTEXT_BYTES 1088
121
122/*
123 * MLKEM768_encap encrypts a random shared secret for |public_key|, writes the
124 * ciphertext to |out_ciphertext|, and writes the random shared secret to
125 * |out_shared_secret|.
126 */
127void MLKEM768_encap(const MLKEM_public_key *public_key,
128 uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES],
129 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES]);
130
131/*
132 * MLKEM768_decap decrypts a shared secret from |ciphertext| using |private_key|
133 * and writes it to |out_shared_secret|. If |ciphertext_len| is incorrect it
134 * returns 0, otherwise it rreturns 1. If |ciphertext| is invalid,
135 * |out_shared_secret| is filled with a key that will always be the same for the
136 * same |ciphertext| and |private_key|, but which appears to be random unless
137 * one has access to |private_key|. These alternatives occur in constant time.
138 * Any subsequent symmetric encryption using |out_shared_secret| must use an
139 * authenticated encryption scheme in order to discover the decapsulation
140 * failure.
141 */
142int MLKEM768_decap(const MLKEM_private_key *private_key,
143 const uint8_t *ciphertext, size_t ciphertext_len,
144 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES]);
145
146/* Serialisation of keys. */
147
148/*
149 * MLKEM768_marshal_public_key serializes |public_key| to |out| in the standard
150 * format for ML-KEM public keys. It returns one on success or zero on allocation
151 * error.
152 */
153int MLKEM768_marshal_public_key(const MLKEM_public_key *public_key,
154 uint8_t **output, size_t *output_len);
155
156/*
157 * MLKEM768_parse_public_key parses a public key, in the format generated by
158 * |MLKEM_marshal_public_key|, from |in| and writes the result to
159 * |out_public_key|. It returns one on success or zero on parse error or if
160 * there are trailing bytes in |in|.
161 */
162int MLKEM768_parse_public_key(const uint8_t *input, size_t input_len,
163 MLKEM_public_key *out_public_key);
164
165/*
166 * MLKEM_parse_private_key parses a private key, in the format generated by
167 * |MLKEM_marshal_private_key|, from |in| and writes the result to
168 * |out_private_key|. It returns one on success or zero on parse error or if
169 * there are trailing bytes in |in|. This formate is verbose and should be avoided.
170 * Private keys should be stored as seeds and parsed using |MLKEM768_private_key_from_seed|.
171 */
172int MLKEM768_parse_private_key(const uint8_t *input, size_t input_len,
173 MLKEM_private_key *out_private_key);
174
175/*
176 * ML-KEM-1024
177 *
178 * ML-KEM-1024 also exists. You should prefer ML-KEM-768 where possible.
179 */
180
181/*
182 * MLKEM1024_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM-1024
183 * public key.
184 */
185#define MLKEM1024_PUBLIC_KEY_BYTES 1568
186
187/*
188 * MLKEM1024_generate_key generates a random public/private key pair, writes the
189 * encoded public key to |out_encoded_public_key| and sets |out_private_key| to
190 * the private key. If |optional_out_seed| is not NULL then the seed used to
191 * generate the private key is written to it.
192 */
193int MLKEM1024_generate_key(
194 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES],
195 uint8_t optional_out_seed[MLKEM_SEED_BYTES],
196 MLKEM_private_key *out_private_key);
197
198/*
199 * MLKEM1024_private_key_from_seed derives a private key from a seed that was
200 * generated by |MLKEM1024_generate_key|. It fails and returns 0 if |seed_len|
201 * is incorrect, otherwise it writes |*out_private_key| and returns 1.
202 */
203int MLKEM1024_private_key_from_seed(
204 MLKEM_private_key *out_private_key, const uint8_t *seed,
205 size_t seed_len);
206
207/*
208 * MLKEM1024_public_from_private sets |*out_public_key| to the public key that
209 * corresponds to |private_key|. (This is faster than parsing the output of
210 * |MLKEM1024_generate_key| if, for some reason, you need to encapsulate to a
211 * key that was just generated.)
212 */
213void MLKEM1024_public_from_private(const MLKEM_private_key *private_key,
214 MLKEM_public_key *out_public_key);
215
216/* MLKEM1024_CIPHERTEXT_BYTES is number of bytes in the ML-KEM-1024 ciphertext. */
217#define MLKEM1024_CIPHERTEXT_BYTES 1568
218
219/*
220 * MLKEM1024_encap encrypts a random shared secret for |public_key|, writes the
221 * ciphertext to |out_ciphertext|, and writes the random shared secret to
222 * |out_shared_secret|.
223 */
224void MLKEM1024_encap(const MLKEM_public_key *public_key,
225 uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES],
226 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES]);
227
228
229/*
230 * MLKEM1024_decap decrypts a shared secret from |ciphertext| using
231 * |private_key| and writes it to |out_shared_secret|. If |ciphertext_len| is
232 * incorrect it returns 0, otherwise it returns 1. If |ciphertext| is invalid
233 * (but of the correct length), |out_shared_secret| is filled with a key that
234 * will always be the same for the same |ciphertext| and |private_key|, but
235 * which appears to be random unless one has access to |private_key|. These
236 * alternatives occur in constant time. Any subsequent symmetric encryption
237 * using |out_shared_secret| must use an authenticated encryption scheme in
238 * order to discover the decapsulation failure.
239 */
240int MLKEM1024_decap(const MLKEM_private_key *private_key,
241 const uint8_t *ciphertext, size_t ciphertext_len,
242 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES]);
243
244/*
245 * Serialisation of ML-KEM-1024 keys.
246 * MLKEM1024_marshal_public_key serializes |public_key| to |out| in the standard
247 * format for ML-KEM-1024 public keys. It returns one on success or zero on
248 * allocation error.
249 */
250int MLKEM1024_marshal_public_key(const MLKEM_public_key *public_key,
251 uint8_t **output, size_t *output_len);
252
253
254/*
255 * MLKEM1024_parse_public_key parses a public key, in the format generated by
256 * |MLKEM1024_marshal_public_key|, from |in| and writes the result to
257 * |out_public_key|. It returns one on success or zero on parse error or if
258 * there are trailing bytes in |in|.
259 */
260int MLKEM1024_parse_public_key(const uint8_t *input, size_t input_len,
261 MLKEM_public_key *out_public_key);
262
263
264/*
265 * MLKEM1024_parse_private_key parses a private key, in NIST's format for
266 * private keys, from |in| and writes the result to |out_private_key|. It
267 * returns one on success or zero on parse error or if there are trailing bytes
268 * in |in|. This format is verbose and should be avoided. Private keys should be
269 * stored as seeds and parsed using |MLKEM1024_private_key_from_seed|.
270 */
271int MLKEM1024_parse_private_key(const uint8_t *input, size_t input_len,
272 MLKEM_private_key *out_private_key);
273
274
275/* XXXX Truly internal stuff below, also in need of de-duping */
29 276
30/* 277/*
31 * MLKEM_ENCAP_ENTROPY is the number of bytes of uniformly random entropy 278 * MLKEM_ENCAP_ENTROPY is the number of bytes of uniformly random entropy
@@ -35,6 +282,49 @@ __BEGIN_HIDDEN_DECLS
35#define MLKEM_ENCAP_ENTROPY 32 282#define MLKEM_ENCAP_ENTROPY 32
36 283
37/* 284/*
285 * MLKEM768_public_key contains a ML-KEM-768 public key. The contents of this
286 * object should never leave the address space since the format is unstable.
287 */
288struct MLKEM768_public_key {
289 union {
290 uint8_t bytes[512 * (3 + 9) + 32 + 32];
291 uint16_t alignment;
292 } opaque;
293};
294
295/*
296 * MLKEM768_private_key contains a ML-KEM-768 private key. The contents of this
297 * object should never leave the address space since the format is unstable.
298 */
299struct MLKEM768_private_key {
300 union {
301 uint8_t bytes[512 * (3 + 3 + 9) + 32 + 32 + 32];
302 uint16_t alignment;
303 } opaque;
304};
305
306/* Public opaque ML-KEM key structures. */
307
308#define MLKEM_PUBLIC_KEY_UNINITIALIZED 1
309#define MLKEM_PUBLIC_KEY_INITIALIZED 2
310#define MLKEM_PRIVATE_KEY_UNINITIALIZED 3
311#define MLKEM_PRIVATE_KEY_INITIALIZED 4
312
313struct MLKEM_public_key_st {
314 uint16_t rank;
315 int state;
316 struct MLKEM768_public_key *key_768;
317 struct MLKEM1024_public_key *key_1024;
318};
319
320struct MLKEM_private_key_st {
321 uint16_t rank;
322 int state;
323 struct MLKEM768_private_key *key_768;
324 struct MLKEM1024_private_key *key_1024;
325};
326
327/*
38 * MLKEM768_generate_key_external_entropy is a deterministic function to create a 328 * MLKEM768_generate_key_external_entropy is a deterministic function to create a
39 * pair of ML-KEM 768 keys, using the supplied entropy. The entropy needs to be 329 * pair of ML-KEM 768 keys, using the supplied entropy. The entropy needs to be
40 * uniformly random generated. This function is should only be used for tests, 330 * uniformly random generated. This function is should only be used for tests,
@@ -43,7 +333,7 @@ __BEGIN_HIDDEN_DECLS
43 */ 333 */
44int MLKEM768_generate_key_external_entropy( 334int MLKEM768_generate_key_external_entropy(
45 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES], 335 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES],
46 struct MLKEM768_private_key *out_private_key, 336 MLKEM_private_key *out_private_key,
47 const uint8_t entropy[MLKEM_SEED_BYTES]); 337 const uint8_t entropy[MLKEM_SEED_BYTES]);
48 338
49/* 339/*
@@ -57,11 +347,11 @@ int MLKEM768_generate_key_external_entropy(
57 * format for ML-KEM private keys. It returns one on success or zero on 347 * format for ML-KEM private keys. It returns one on success or zero on
58 * allocation error. 348 * allocation error.
59 */ 349 */
60int MLKEM768_marshal_private_key(const struct MLKEM768_private_key *private_key, 350int MLKEM768_marshal_private_key(const MLKEM_private_key *private_key,
61 uint8_t **out_private_key, size_t *out_private_key_len); 351 uint8_t **out_private_key, size_t *out_private_key_len);
62 352
63/* 353/*
64 * MLKEM_encap_external_entropy behaves like |MLKEM_encap|, but uses 354 * MLKEM768_encap_external_entropy behaves like |MLKEM768_encap|, but uses
65 * |MLKEM_ENCAP_ENTROPY| bytes of |entropy| for randomization. The decapsulating 355 * |MLKEM_ENCAP_ENTROPY| bytes of |entropy| for randomization. The decapsulating
66 * side will be able to recover |entropy| in full. This function should only be 356 * side will be able to recover |entropy| in full. This function should only be
67 * used for tests, regular callers should use the non-deterministic 357 * used for tests, regular callers should use the non-deterministic
@@ -70,9 +360,34 @@ int MLKEM768_marshal_private_key(const struct MLKEM768_private_key *private_key,
70void MLKEM768_encap_external_entropy( 360void MLKEM768_encap_external_entropy(
71 uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES], 361 uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES],
72 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 362 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
73 const struct MLKEM768_public_key *public_key, 363 const MLKEM_public_key *public_key,
74 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]); 364 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]);
75 365
366
367/*
368 * MLKEM1024_public_key contains an ML-KEM-1024 public key. The contents of this
369 * object should never leave the address space since the format is unstable.
370 */
371struct MLKEM1024_public_key {
372 union {
373 uint8_t bytes[512 * (4 + 16) + 32 + 32];
374 uint16_t alignment;
375 } opaque;
376};
377
378/*
379 * MLKEM1024_private_key contains a ML-KEM-1024 private key. The contents of
380 * this object should never leave the address space since the format is
381 * unstable.
382 */
383struct MLKEM1024_private_key {
384 union {
385 uint8_t bytes[512 * (4 + 4 + 16) + 32 + 32 + 32];
386 uint16_t alignment;
387 } opaque;
388};
389
390
76/* 391/*
77 * MLKEM1024_generate_key_external_entropy is a deterministic function to create a 392 * MLKEM1024_generate_key_external_entropy is a deterministic function to create a
78 * pair of ML-KEM 1024 keys, using the supplied entropy. The entropy needs to be 393 * pair of ML-KEM 1024 keys, using the supplied entropy. The entropy needs to be
@@ -82,7 +397,7 @@ void MLKEM768_encap_external_entropy(
82 */ 397 */
83int MLKEM1024_generate_key_external_entropy( 398int MLKEM1024_generate_key_external_entropy(
84 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES], 399 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES],
85 struct MLKEM1024_private_key *out_private_key, 400 MLKEM_private_key *out_private_key,
86 const uint8_t entropy[MLKEM_SEED_BYTES]); 401 const uint8_t entropy[MLKEM_SEED_BYTES]);
87 402
88/* 403/*
@@ -97,7 +412,7 @@ int MLKEM1024_generate_key_external_entropy(
97 * allocation error. 412 * allocation error.
98 */ 413 */
99int MLKEM1024_marshal_private_key( 414int MLKEM1024_marshal_private_key(
100 const struct MLKEM1024_private_key *private_key, uint8_t **out_private_key, 415 const MLKEM_private_key *private_key, uint8_t **out_private_key,
101 size_t *out_private_key_len); 416 size_t *out_private_key_len);
102 417
103/* 418/*
@@ -110,7 +425,7 @@ int MLKEM1024_marshal_private_key(
110void MLKEM1024_encap_external_entropy( 425void MLKEM1024_encap_external_entropy(
111 uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES], 426 uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES],
112 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 427 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
113 const struct MLKEM1024_public_key *public_key, 428 const MLKEM_public_key *public_key,
114 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]); 429 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]);
115 430
116__END_HIDDEN_DECLS 431__END_HIDDEN_DECLS
diff --git a/src/lib/libcrypto/mlkem/mlkem_key.c b/src/lib/libcrypto/mlkem/mlkem_key.c
new file mode 100644
index 0000000000..051d8f2b88
--- /dev/null
+++ b/src/lib/libcrypto/mlkem/mlkem_key.c
@@ -0,0 +1,200 @@
1/* $OpenBSD: mlkem_key.c,v 1.1 2025/08/14 15:48:48 beck Exp $ */
2/*
3 * Copyright (c) 2025 Bob Beck <beck@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <stdlib.h>
19#include <string.h>
20
21#include <openssl/mlkem.h>
22
23#include "mlkem_internal.h"
24
25MLKEM_private_key *
26MLKEM_private_key_new(int rank)
27{
28 struct MLKEM1024_private_key *key_1024 = NULL;
29 struct MLKEM768_private_key *key_768 = NULL;
30 MLKEM_private_key *key = NULL;
31 MLKEM_private_key *ret = NULL;
32
33 if ((key = calloc(1, sizeof(MLKEM_private_key))) == NULL)
34 goto err;
35
36 switch (rank) {
37 case RANK768:
38 if ((key_768 = calloc(1, sizeof(*key_768))) ==
39 NULL)
40 goto err;
41 key->key_768 = key_768;
42 break;
43 case RANK1024:
44 if ((key_1024 = calloc(1, sizeof(*key_1024))) ==
45 NULL)
46 goto err;
47 key->key_1024 = key_1024;
48 break;
49 default:
50 goto err;
51 }
52 key->rank = rank;
53 key->state = MLKEM_PRIVATE_KEY_UNINITIALIZED;
54
55 ret = key;
56 key= NULL;
57
58 err:
59 MLKEM_private_key_free(key);
60
61 return ret;
62}
63LCRYPTO_ALIAS(MLKEM_private_key_new);
64
65void
66MLKEM_private_key_free(MLKEM_private_key *key)
67{
68 if (key == NULL)
69 return;
70
71 freezero(key->key_768, sizeof(*key->key_768));
72 freezero(key->key_1024, sizeof(*key->key_1024));
73 freezero(key, sizeof(*key));
74}
75LCRYPTO_ALIAS(MLKEM_private_key_free);
76
77size_t
78MLKEM_private_key_encoded_length(const MLKEM_private_key *key)
79{
80 if (key == NULL)
81 return 0;
82
83 switch (key->rank) {
84 case RANK768:
85 return MLKEM768_PRIVATE_KEY_BYTES;
86 case RANK1024:
87 return MLKEM1024_PRIVATE_KEY_BYTES;
88 default:
89 return 0;
90 }
91 return 0;
92}
93LCRYPTO_ALIAS(MLKEM_private_key_encoded_length);
94
95size_t
96MLKEM_private_key_ciphertext_length(const MLKEM_private_key *key)
97{
98 if (key == NULL)
99 return 0;
100
101 switch (key->rank) {
102 case RANK768:
103 return MLKEM768_CIPHERTEXT_BYTES;
104 case RANK1024:
105 return MLKEM1024_CIPHERTEXT_BYTES;
106 default:
107 return 0;
108 }
109 return 0;
110}
111LCRYPTO_ALIAS(MLKEM_private_key_ciphertext_length);
112
113MLKEM_public_key *
114MLKEM_public_key_new(int rank)
115{
116 struct MLKEM1024_public_key *key_1024 = NULL;
117 struct MLKEM768_public_key *key_768 = NULL;
118 MLKEM_public_key *key = NULL;
119 MLKEM_public_key *ret = NULL;
120
121 if ((key = calloc(1, sizeof(MLKEM_public_key))) == NULL)
122 goto err;
123
124 switch (rank) {
125 case RANK768:
126 if ((key_768 = calloc(1, sizeof(*key_768))) ==
127 NULL)
128 goto err;
129 key->key_768 = key_768;
130 break;
131 case RANK1024:
132 if ((key_1024 = calloc(1, sizeof(*key_1024))) ==
133 NULL)
134 goto err;
135 key->key_1024 = key_1024;
136 break;
137 default:
138 goto err;
139 }
140
141 key->rank = rank;
142 key->state = MLKEM_PUBLIC_KEY_UNINITIALIZED;
143
144 ret = key;
145 key = NULL;
146
147 err:
148 MLKEM_public_key_free(key);
149
150 return ret;
151}
152LCRYPTO_ALIAS(MLKEM_public_key_new);
153
154void
155MLKEM_public_key_free(MLKEM_public_key *key)
156{
157 if (key == NULL)
158 return;
159
160 freezero(key->key_768, sizeof(*key->key_768));
161 freezero(key->key_1024, sizeof(*key->key_1024));
162 freezero(key, sizeof(*key));
163}
164LCRYPTO_ALIAS(MLKEM_public_key_free);
165
166size_t
167MLKEM_public_key_encoded_length(const MLKEM_public_key *key)
168{
169 if (key == NULL)
170 return 0;
171
172 switch (key->rank) {
173 case RANK768:
174 return MLKEM768_PUBLIC_KEY_BYTES;
175 case RANK1024:
176 return MLKEM1024_PUBLIC_KEY_BYTES;
177 default:
178 return 0;
179 }
180 return 0;
181}
182LCRYPTO_ALIAS(MLKEM_public_key_encoded_length);
183
184size_t
185MLKEM_public_key_ciphertext_length(const MLKEM_public_key *key)
186{
187 if (key == NULL)
188 return 0;
189
190 switch (key->rank) {
191 case RANK768:
192 return MLKEM768_CIPHERTEXT_BYTES;
193 case RANK1024:
194 return MLKEM1024_CIPHERTEXT_BYTES;
195 default:
196 return 0;
197 }
198 return 0;
199}
200LCRYPTO_ALIAS(MLKEM_public_key_ciphertext_length);
diff --git a/src/lib/libcrypto/rc4/rc4.c b/src/lib/libcrypto/rc4/rc4.c
index 56ed43cba7..69b7d0a815 100644
--- a/src/lib/libcrypto/rc4/rc4.c
+++ b/src/lib/libcrypto/rc4/rc4.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: rc4.c,v 1.13 2025/01/27 14:02:32 jsing Exp $ */ 1/* $OpenBSD: rc4.c,v 1.15 2025/08/17 08:04:25 jsing Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -57,234 +57,123 @@
57 */ 57 */
58 58
59#include <endian.h> 59#include <endian.h>
60#include <stdint.h>
60 61
61#include <openssl/rc4.h> 62#include <openssl/rc4.h>
62 63
63#include "crypto_arch.h" 64#include "crypto_arch.h"
64 65
65/* RC4 as implemented from a posting from
66 * Newsgroups: sci.crypt
67 * From: sterndark@netcom.com (David Sterndark)
68 * Subject: RC4 Algorithm revealed.
69 * Message-ID: <sternCvKL4B.Hyy@netcom.com>
70 * Date: Wed, 14 Sep 1994 06:35:31 GMT
71 */
72
73#ifdef HAVE_RC4_INTERNAL 66#ifdef HAVE_RC4_INTERNAL
74void rc4_internal(RC4_KEY *key, size_t len, const unsigned char *indata, 67void rc4_internal(RC4_KEY *key, size_t len, const uint8_t *in,
75 unsigned char *outdata); 68 uint8_t *out);
76 69
77#else 70#else
78static void 71static inline RC4_INT
79rc4_internal(RC4_KEY *key, size_t len, const unsigned char *indata, 72rc4_step(RC4_INT *d, RC4_INT *x, RC4_INT *y)
80 unsigned char *outdata)
81{ 73{
82 RC4_INT *d; 74 RC4_INT tx, ty;
83 RC4_INT x, y,tx, ty;
84 size_t i;
85 75
86 x = key->x; 76 *x = (*x + 1) & 0xff;
87 y = key->y; 77 tx = d[*x];
88 d = key->data; 78 *y = (tx + *y) & 0xff;
79 d[*x] = ty = d[*y];
80 d[*y] = tx;
89 81
90#if defined(RC4_CHUNK) 82 return d[(tx + ty) & 0xff];
91 /* 83}
92 * The original reason for implementing this(*) was the fact that
93 * pre-21164a Alpha CPUs don't have byte load/store instructions
94 * and e.g. a byte store has to be done with 64-bit load, shift,
95 * and, or and finally 64-bit store. Peaking data and operating
96 * at natural word size made it possible to reduce amount of
97 * instructions as well as to perform early read-ahead without
98 * suffering from RAW (read-after-write) hazard. This resulted
99 * in ~40%(**) performance improvement on 21064 box with gcc.
100 * But it's not only Alpha users who win here:-) Thanks to the
101 * early-n-wide read-ahead this implementation also exhibits
102 * >40% speed-up on SPARC and 20-30% on 64-bit MIPS (depending
103 * on sizeof(RC4_INT)).
104 *
105 * (*) "this" means code which recognizes the case when input
106 * and output pointers appear to be aligned at natural CPU
107 * word boundary
108 * (**) i.e. according to 'apps/openssl speed rc4' benchmark,
109 * crypto/rc4/rc4speed.c exhibits almost 70% speed-up...
110 *
111 * Caveats.
112 *
113 * - RC4_CHUNK="unsigned long long" should be a #1 choice for
114 * UltraSPARC. Unfortunately gcc generates very slow code
115 * (2.5-3 times slower than one generated by Sun's WorkShop
116 * C) and therefore gcc (at least 2.95 and earlier) should
117 * always be told that RC4_CHUNK="unsigned long".
118 *
119 * <appro@fy.chalmers.se>
120 */
121 84
122# define RC4_STEP ( \ 85#if BYTE_ORDER == BIG_ENDIAN
123 x=(x+1) &0xff, \ 86static inline uint64_t
124 tx=d[x], \ 87rc4_chunk(RC4_INT *d, RC4_INT *x, RC4_INT *y)
125 y=(tx+y)&0xff, \ 88{
126 ty=d[y], \ 89 uint64_t chunk = 0;
127 d[y]=tx, \ 90 size_t i;
128 d[x]=ty, \
129 (RC4_CHUNK)d[(tx+ty)&0xff]\
130 )
131 91
132 if ((((size_t)indata & (sizeof(RC4_CHUNK) - 1)) | 92 for (i = 0; i < 8; i++)
133 ((size_t)outdata & (sizeof(RC4_CHUNK) - 1))) == 0 ) { 93 chunk = chunk << 8 | (uint64_t)rc4_step(d, x, y);
134 RC4_CHUNK ichunk, otp; 94
95 return chunk;
96}
135 97
136 /*
137 * I reckon we can afford to implement both endian
138 * cases and to decide which way to take at run-time
139 * because the machine code appears to be very compact
140 * and redundant 1-2KB is perfectly tolerable (i.e.
141 * in case the compiler fails to eliminate it:-). By
142 * suggestion from Terrel Larson <terr@terralogic.net>.
143 *
144 * Special notes.
145 *
146 * - compilers (those I've tried) don't seem to have
147 * problems eliminating either the operators guarded
148 * by "if (sizeof(RC4_CHUNK)==8)" or the condition
149 * expressions themselves so I've got 'em to replace
150 * corresponding #ifdefs from the previous version;
151 * - I chose to let the redundant switch cases when
152 * sizeof(RC4_CHUNK)!=8 be (were also #ifdefed
153 * before);
154 * - in case you wonder "&(sizeof(RC4_CHUNK)*8-1)" in
155 * [LB]ESHFT guards against "shift is out of range"
156 * warnings when sizeof(RC4_CHUNK)!=8
157 *
158 * <appro@fy.chalmers.se>
159 */
160#if BYTE_ORDER == BIG_ENDIAN
161# define BESHFT(c) (((sizeof(RC4_CHUNK)-(c)-1)*8)&(sizeof(RC4_CHUNK)*8-1))
162 for (; len & (0 - sizeof(RC4_CHUNK)); len -= sizeof(RC4_CHUNK)) {
163 ichunk = *(RC4_CHUNK *)indata;
164 otp = RC4_STEP << BESHFT(0);
165 otp |= RC4_STEP << BESHFT(1);
166 otp |= RC4_STEP << BESHFT(2);
167 otp |= RC4_STEP << BESHFT(3);
168 if (sizeof(RC4_CHUNK) == 8) {
169 otp |= RC4_STEP << BESHFT(4);
170 otp |= RC4_STEP << BESHFT(5);
171 otp |= RC4_STEP << BESHFT(6);
172 otp |= RC4_STEP << BESHFT(7);
173 }
174 *(RC4_CHUNK *)outdata = otp^ichunk;
175 indata += sizeof(RC4_CHUNK);
176 outdata += sizeof(RC4_CHUNK);
177 }
178#else 98#else
179# define LESHFT(c) (((c)*8)&(sizeof(RC4_CHUNK)*8-1)) 99static inline uint64_t
180 for (; len & (0 - sizeof(RC4_CHUNK)); len -= sizeof(RC4_CHUNK)) { 100rc4_chunk(RC4_INT *d, RC4_INT *x, RC4_INT *y)
181 ichunk = *(RC4_CHUNK *)indata; 101{
182 otp = RC4_STEP; 102 uint64_t chunk = 0;
183 otp |= RC4_STEP << 8; 103 size_t i;
184 otp |= RC4_STEP << 16; 104
185 otp |= RC4_STEP << 24; 105 for (i = 0; i < 8; i++)
186 if (sizeof(RC4_CHUNK) == 8) { 106 chunk |= (uint64_t)rc4_step(d, x, y) << (i * 8);
187 otp |= RC4_STEP << LESHFT(4); 107
188 otp |= RC4_STEP << LESHFT(5); 108 return chunk;
189 otp |= RC4_STEP << LESHFT(6); 109}
190 otp |= RC4_STEP << LESHFT(7);
191 }
192 *(RC4_CHUNK *)outdata = otp ^ ichunk;
193 indata += sizeof(RC4_CHUNK);
194 outdata += sizeof(RC4_CHUNK);
195 }
196#endif
197 }
198#endif 110#endif
199#define RC4_LOOP(in,out) \
200 x=((x+1)&0xff); \
201 tx=d[x]; \
202 y=(tx+y)&0xff; \
203 d[x]=ty=d[y]; \
204 d[y]=tx; \
205 (out) = d[(tx+ty)&0xff]^ (in);
206 111
207 i = len >> 3; 112static void
208 if (i) { 113rc4_internal(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out)
209 for (;;) { 114{
210 RC4_LOOP(indata[0], outdata[0]); 115 RC4_INT *d, x, y;
211 RC4_LOOP(indata[1], outdata[1]); 116 size_t i;
212 RC4_LOOP(indata[2], outdata[2]);
213 RC4_LOOP(indata[3], outdata[3]);
214 RC4_LOOP(indata[4], outdata[4]);
215 RC4_LOOP(indata[5], outdata[5]);
216 RC4_LOOP(indata[6], outdata[6]);
217 RC4_LOOP(indata[7], outdata[7]);
218 117
219 indata += 8; 118 x = key->x;
220 outdata += 8; 119 y = key->y;
120 d = key->data;
121
122 /* Process uint64_t chunks if 8 byte aligned. */
123 if ((((size_t)in | (size_t)out) % 8) == 0) {
124 while (len >= 8) {
125 *(uint64_t *)out = *(const uint64_t *)in ^ rc4_chunk(d, &x, &y);
221 126
222 if (--i == 0) 127 in += 8;
223 break; 128 out += 8;
129 len -= 8;
224 } 130 }
225 } 131 }
226 i = len&0x07; 132
227 if (i) { 133 while (len >= 8) {
228 for (;;) { 134 for (i = 0; i < 8; i++)
229 RC4_LOOP(indata[0], outdata[0]); 135 out[i] = rc4_step(d, &x, &y) ^ in[i];
230 if (--i == 0) 136
231 break; 137 in += 8;
232 RC4_LOOP(indata[1], outdata[1]); 138 out += 8;
233 if (--i == 0) 139 len -= 8;
234 break;
235 RC4_LOOP(indata[2], outdata[2]);
236 if (--i == 0)
237 break;
238 RC4_LOOP(indata[3], outdata[3]);
239 if (--i == 0)
240 break;
241 RC4_LOOP(indata[4], outdata[4]);
242 if (--i == 0)
243 break;
244 RC4_LOOP(indata[5], outdata[5]);
245 if (--i == 0)
246 break;
247 RC4_LOOP(indata[6], outdata[6]);
248 if (--i == 0)
249 break;
250 }
251 } 140 }
141 for (i = 0; i < len; i++)
142 out[i] = rc4_step(d, &x, &y) ^ in[i];
143
252 key->x = x; 144 key->x = x;
253 key->y = y; 145 key->y = y;
254} 146}
255#endif 147#endif
256 148
257#ifdef HAVE_RC4_SET_KEY_INTERNAL 149#ifdef HAVE_RC4_SET_KEY_INTERNAL
258void rc4_set_key_internal(RC4_KEY *key, int len, const unsigned char *data); 150void rc4_set_key_internal(RC4_KEY *key, int len, const uint8_t *data);
259 151
260#else 152#else
261static inline void 153static inline void
262rc4_set_key_internal(RC4_KEY *key, int len, const unsigned char *data) 154rc4_set_key_internal(RC4_KEY *key, int len, const uint8_t *data)
263{ 155{
264 RC4_INT tmp; 156 RC4_INT *d, tmp;
265 int id1, id2; 157 int idx1, idx2;
266 RC4_INT *d; 158 int i, j;
267 unsigned int i;
268 159
269 d = &(key->data[0]); 160 d = key->data;
270 key->x = 0; 161 key->x = 0;
271 key->y = 0; 162 key->y = 0;
272 id1 = id2 = 0; 163 idx1 = idx2 = 0;
273
274#define SK_LOOP(d,n) { \
275 tmp=d[(n)]; \
276 id2 = (data[id1] + tmp + id2) & 0xff; \
277 if (++id1 == len) id1=0; \
278 d[(n)]=d[id2]; \
279 d[id2]=tmp; }
280 164
281 for (i = 0; i < 256; i++) 165 for (i = 0; i < 256; i++)
282 d[i] = i; 166 d[i] = i;
283 for (i = 0; i < 256; i += 4) { 167 for (i = 0; i < 256; i += 4) {
284 SK_LOOP(d, i + 0); 168 for (j = 0; j < 4; j++) {
285 SK_LOOP(d, i + 1); 169 tmp = d[i + j];
286 SK_LOOP(d, i + 2); 170 idx2 = (data[idx1] + tmp + idx2) & 0xff;
287 SK_LOOP(d, i + 3); 171 d[i + j] = d[idx2];
172 d[idx2] = tmp;
173
174 if (++idx1 == len)
175 idx1 = 0;
176 }
288 } 177 }
289} 178}
290#endif 179#endif
diff --git a/src/lib/libcrypto/x509/x509.h b/src/lib/libcrypto/x509/x509.h
index 729a06d0ed..4148a6398e 100644
--- a/src/lib/libcrypto/x509/x509.h
+++ b/src/lib/libcrypto/x509/x509.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509.h,v 1.123 2025/07/16 15:59:26 tb Exp $ */ 1/* $OpenBSD: x509.h,v 1.124 2025/08/10 06:36:45 beck Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -995,6 +995,7 @@ void ERR_load_X509_strings(void);
995#define X509_R_ERR_ASN1_LIB 102 995#define X509_R_ERR_ASN1_LIB 102
996#define X509_R_INVALID_DIRECTORY 113 996#define X509_R_INVALID_DIRECTORY 113
997#define X509_R_INVALID_FIELD_NAME 119 997#define X509_R_INVALID_FIELD_NAME 119
998#define X509_R_INVALID_POLICY_EXTENSION 201
998#define X509_R_INVALID_TRUST 123 999#define X509_R_INVALID_TRUST 123
999#define X509_R_INVALID_VERSION 137 1000#define X509_R_INVALID_VERSION 137
1000#define X509_R_KEY_TYPE_MISMATCH 115 1001#define X509_R_KEY_TYPE_MISMATCH 115
diff --git a/src/lib/libcrypto/x509/x509_policy.c b/src/lib/libcrypto/x509/x509_policy.c
index 8267e8dc49..2df965aad1 100644
--- a/src/lib/libcrypto/x509/x509_policy.c
+++ b/src/lib/libcrypto/x509/x509_policy.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_policy.c,v 1.32 2025/05/10 05:54:39 tb Exp $ */ 1/* $OpenBSD: x509_policy.c,v 1.33 2025/08/10 06:36:45 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2022, Google Inc. 3 * Copyright (c) 2022, Google Inc.
4 * 4 *
@@ -27,9 +27,6 @@
27#include "x509_internal.h" 27#include "x509_internal.h"
28#include "x509_local.h" 28#include "x509_local.h"
29 29
30/* XXX move to proper place */
31#define X509_R_INVALID_POLICY_EXTENSION 201
32
33/* 30/*
34 * This file computes the X.509 policy tree, as described in RFC 5280, 31 * This file computes the X.509 policy tree, as described in RFC 5280,
35 * section 6.1 and RFC 9618. It differs in that: 32 * section 6.1 and RFC 9618. It differs in that: