mldsa_gh 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +88 -0
- data/ext/mldsa_gh_native/extconf.rb +14 -0
- data/ext/mldsa_gh_native/mldsa_gh_native.c +222 -0
- data/ext/mldsa_gh_native/mldsa_gh_native_all.c +24 -0
- data/ext/mldsa_gh_native/mldsa_gh_native_all.h +26 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/BUILDING.md +108 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/LICENSE +305 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/README.md +247 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/README.md +23 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/mldsa_native.c +803 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/mldsa_native.h +956 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/mldsa_native_asm.S +830 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/mldsa_native_config.h +855 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/cbmc.h +233 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/common.h +301 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/context.h +152 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/ct.c +21 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/ct.h +373 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/debug.c +75 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/debug.h +125 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/fips202.c +270 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/fips202.h +224 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/fips202x4.c +187 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/fips202x4.h +125 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.c +510 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.h +110 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/auto.h +85 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/fips202_native_aarch64.h +69 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_aarch64_asm.S +378 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_aarch64_asm.S +207 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_aarch64_asm.S +262 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_aarch64_asm.S +1080 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_aarch64_asm.S +990 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccakf1600_round_constants.c +47 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_scalar.h +27 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_v84a.h +36 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x2_v84a.h +40 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_scalar.h +32 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_v84a_scalar.h +37 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/api.h +129 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/README.md +10 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/mve.h +67 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/fips202_native_armv81m.h +37 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.S +717 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.c +42 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_state_extract_bytes_mve.S +334 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_state_xor_bytes_mve.S +355 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccakf1600_round_constants.c +53 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/auto.h +35 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/keccak_f1600_x4_avx2.h +34 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/fips202_native_x86_64.h +45 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/keccak_f1600_x4_avx2_asm.S +488 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/keccakf1600_constants.c +52 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/meta.h +314 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/aarch64_zetas.c +248 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/arith_native_aarch64.h +367 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_intt_aarch64_asm.S +786 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_ntt_aarch64_asm.S +686 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_pointwise_montgomery_aarch64_asm.S +106 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_caddq_aarch64_asm.S +69 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_chknorm_aarch64_asm.S +76 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_decompose_32_aarch64_asm.S +108 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_decompose_88_aarch64_asm.S +108 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_use_hint_32_aarch64_asm.S +125 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_use_hint_88_aarch64_asm.S +133 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_polyvecl_pointwise_acc_montgomery_l4_aarch64_asm.S +157 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_polyvecl_pointwise_acc_montgomery_l5_aarch64_asm.S +173 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_polyvecl_pointwise_acc_montgomery_l7_aarch64_asm.S +205 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_polyz_unpack_17_aarch64_asm.S +103 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_polyz_unpack_19_aarch64_asm.S +100 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_rej_uniform_aarch64_asm.S +222 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_rej_uniform_eta2_aarch64_asm.S +170 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_rej_uniform_eta4_aarch64_asm.S +163 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_table.c +52 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta_table.c +547 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_table.c +63 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/api.h +617 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/meta.h +24 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/meta.h +323 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/arith_native_x86_64.h +330 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.c +157 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.h +27 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_intt_avx2_asm.S +2333 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_ntt_avx2_asm.S +2405 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_nttunpack_avx2_asm.S +254 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_pointwise_acc_l4_avx2_asm.S +173 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_pointwise_acc_l5_avx2_asm.S +189 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_pointwise_acc_l7_avx2_asm.S +221 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_pointwise_avx2_asm.S +158 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_caddq_avx2_asm.S +199 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_chknorm_avx2_asm.S +176 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_decompose_32_avx2_asm.S +490 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_decompose_88_avx2_asm.S +489 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_use_hint_32_avx2_asm.S +123 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_use_hint_88_avx2_asm.S +125 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_polyz_unpack_17_avx2_asm.S +355 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_polyz_unpack_19_avx2_asm.S +355 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_rej_uniform_avx2_asm.S +132 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_rej_uniform_eta2_avx2_asm.S +205 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_rej_uniform_eta4_avx2_asm.S +176 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_table.c +161 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/packing.c +213 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/packing.h +277 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/params.h +153 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/poly.c +1066 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/poly.h +464 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/poly_kl.c +910 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/poly_kl.h +367 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/polyvec.c +509 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/polyvec.h +435 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/polyvec_lazy.c +311 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/polyvec_lazy.h +652 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/randombytes.h +26 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/reduce.h +144 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/rounding.h +265 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/sign.c +1720 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/sign.h +850 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/symmetric.h +68 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/sys.h +327 -0
- data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/zetas.inc +55 -0
- data/lib/mldsa/parameter_set.rb +82 -0
- data/lib/mldsa/signing_key.rb +147 -0
- data/lib/mldsa/verify_key.rb +72 -0
- data/lib/mldsa/version.rb +7 -0
- data/lib/mldsa_gh.rb +93 -0
- metadata +225 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) The mldsa-native project authors
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/* References
|
|
7
|
+
* ==========
|
|
8
|
+
*
|
|
9
|
+
* - [FIPS204]
|
|
10
|
+
* FIPS 204 Module-Lattice-Based Digital Signature Standard
|
|
11
|
+
* National Institute of Standards and Technology
|
|
12
|
+
* https://csrc.nist.gov/pubs/fips/204/final
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
#ifndef MLD_REDUCE_H
|
|
16
|
+
#define MLD_REDUCE_H
|
|
17
|
+
|
|
18
|
+
#include "cbmc.h"
|
|
19
|
+
#include "common.h"
|
|
20
|
+
#include "ct.h"
|
|
21
|
+
#include "debug.h"
|
|
22
|
+
|
|
23
|
+
/* check-magic: -4186625 == pow(2,32,MLDSA_Q) */
|
|
24
|
+
#define MLD_MONT (-4186625)
|
|
25
|
+
|
|
26
|
+
/* Upper bound for domain of mld_reduce32() */
|
|
27
|
+
#define MLD_REDUCE32_DOMAIN_MAX (INT32_MAX - ((int32_t)1 << 22))
|
|
28
|
+
|
|
29
|
+
/* Absolute bound for range of mld_reduce32() */
|
|
30
|
+
/* check-magic: 6283009 == (MLD_REDUCE32_DOMAIN_MAX - 255 * MLDSA_Q + 1) */
|
|
31
|
+
#define MLD_REDUCE32_RANGE_MAX 6283009
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Generic Montgomery reduction; given a 64-bit integer a, computes a 32-bit
|
|
35
|
+
* integer congruent to a * R^-1 mod MLDSA_Q, where R=2^32.
|
|
36
|
+
*
|
|
37
|
+
* @spec{Implements @[FIPS204, Algorithm 49, MontgomeryReduce].}
|
|
38
|
+
*
|
|
39
|
+
* @param a Input integer to be reduced, of absolute value smaller or equal
|
|
40
|
+
* to INT64_MAX - 2^31 * MLDSA_Q.
|
|
41
|
+
*
|
|
42
|
+
* @return Integer congruent to a * R^-1 modulo MLDSA_Q, with absolute value
|
|
43
|
+
* <= |a| / 2^32 + MLDSA_Q / 2.
|
|
44
|
+
* In particular, if |a| < 2^31 * MLDSA_Q, the absolute value of the
|
|
45
|
+
* return value is < MLDSA_Q.
|
|
46
|
+
*/
|
|
47
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
48
|
+
static MLD_INLINE int32_t mld_montgomery_reduce(int64_t a)
|
|
49
|
+
__contract__(
|
|
50
|
+
/* We don't attempt to express an input-dependent output bound
|
|
51
|
+
* as the post-condition here, as all call-sites satisfy the
|
|
52
|
+
* absolute input bound 2^31 * MLDSA_Q and higher-level
|
|
53
|
+
* reasoning can be conducted using |return_value| < MLDSA_Q. */
|
|
54
|
+
requires(a > -(((int64_t)1 << 31) * MLDSA_Q) &&
|
|
55
|
+
a < (((int64_t)1 << 31) * MLDSA_Q))
|
|
56
|
+
ensures(return_value > -MLDSA_Q && return_value < MLDSA_Q)
|
|
57
|
+
)
|
|
58
|
+
{
|
|
59
|
+
/* check-magic: 58728449 == unsigned_mod(pow(MLDSA_Q, -1, 2^32), 2^32) */
|
|
60
|
+
const uint64_t QINV = 58728449;
|
|
61
|
+
|
|
62
|
+
/* Compute a*q^{-1} mod 2^32 in unsigned representatives */
|
|
63
|
+
const uint32_t a_reduced = mld_cast_int64_to_uint32(a);
|
|
64
|
+
const uint32_t a_inverted = (a_reduced * QINV) & UINT32_MAX;
|
|
65
|
+
|
|
66
|
+
/* Lift to signed canonical representative mod 2^32. */
|
|
67
|
+
const int32_t t = mld_cast_uint32_to_int32(a_inverted);
|
|
68
|
+
|
|
69
|
+
int64_t r;
|
|
70
|
+
|
|
71
|
+
mld_assert(a < +(INT64_MAX - (((int64_t)1 << 31) * MLDSA_Q)) &&
|
|
72
|
+
a > -(INT64_MAX - (((int64_t)1 << 31) * MLDSA_Q)));
|
|
73
|
+
|
|
74
|
+
r = a - (int64_t)t * MLDSA_Q;
|
|
75
|
+
|
|
76
|
+
/*
|
|
77
|
+
* PORTABILITY: Right-shift on a signed integer is, strictly-speaking,
|
|
78
|
+
* implementation-defined for negative left argument. Here,
|
|
79
|
+
* we assume it's sign-preserving "arithmetic" shift right. (C99 6.5.7 (5))
|
|
80
|
+
*/
|
|
81
|
+
r = r >> 32;
|
|
82
|
+
|
|
83
|
+
/* Bounds:
|
|
84
|
+
*
|
|
85
|
+
* By construction of the Montgomery multiplication, by the time we
|
|
86
|
+
* compute r >> 32, r is divisible by 2^32, and hence
|
|
87
|
+
*
|
|
88
|
+
* |r >> 32| = |r| / 2^32
|
|
89
|
+
* <= |a| / 2^32 + MLDSA_Q / 2
|
|
90
|
+
*
|
|
91
|
+
* (In general, we would only have |x >> n| <= ceil(|x| / 2^n)).
|
|
92
|
+
*
|
|
93
|
+
* In particular, if |a| < 2^31 * MLDSA_Q, then |return_value| < MLDSA_Q.
|
|
94
|
+
*/
|
|
95
|
+
return (int32_t)r;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* For finite field element a with a <= 2^{31} - 2^{22} - 1, compute
|
|
100
|
+
* r congruent to a (mod MLDSA_Q) such that
|
|
101
|
+
* -MLD_REDUCE32_RANGE_MAX <= r < MLD_REDUCE32_RANGE_MAX.
|
|
102
|
+
*
|
|
103
|
+
* @param a Finite field element.
|
|
104
|
+
*
|
|
105
|
+
* @return r.
|
|
106
|
+
*/
|
|
107
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
108
|
+
static MLD_INLINE int32_t mld_reduce32(int32_t a)
|
|
109
|
+
__contract__(
|
|
110
|
+
requires(a <= MLD_REDUCE32_DOMAIN_MAX)
|
|
111
|
+
ensures(return_value >= -MLD_REDUCE32_RANGE_MAX)
|
|
112
|
+
ensures(return_value < MLD_REDUCE32_RANGE_MAX)
|
|
113
|
+
)
|
|
114
|
+
{
|
|
115
|
+
int32_t t;
|
|
116
|
+
|
|
117
|
+
t = (a + ((int32_t)1 << 22)) >> 23;
|
|
118
|
+
t = a - t * MLDSA_Q;
|
|
119
|
+
mld_assert((t - a) % MLDSA_Q == 0);
|
|
120
|
+
return t;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Add MLDSA_Q if input coefficient is negative.
|
|
125
|
+
*
|
|
126
|
+
* @param a Finite field element.
|
|
127
|
+
*
|
|
128
|
+
* @return r.
|
|
129
|
+
*/
|
|
130
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
131
|
+
static MLD_INLINE int32_t mld_caddq(int32_t a)
|
|
132
|
+
__contract__(
|
|
133
|
+
requires(a > -MLDSA_Q)
|
|
134
|
+
requires(a < MLDSA_Q)
|
|
135
|
+
ensures(return_value >= 0)
|
|
136
|
+
ensures(return_value < MLDSA_Q)
|
|
137
|
+
ensures(return_value == ((a >= 0) ? a : (a + MLDSA_Q)))
|
|
138
|
+
)
|
|
139
|
+
{
|
|
140
|
+
return mld_ct_sel_int32(a + MLDSA_Q, a, mld_ct_cmask_neg_i32(a));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
#endif /* !MLD_REDUCE_H */
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) The mldsa-native project authors
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/* References
|
|
7
|
+
* ==========
|
|
8
|
+
*
|
|
9
|
+
* - [FIPS204]
|
|
10
|
+
* FIPS 204 Module-Lattice-Based Digital Signature Standard
|
|
11
|
+
* National Institute of Standards and Technology
|
|
12
|
+
* https://csrc.nist.gov/pubs/fips/204/final
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
#ifndef MLD_ROUNDING_H
|
|
16
|
+
#define MLD_ROUNDING_H
|
|
17
|
+
|
|
18
|
+
#include "cbmc.h"
|
|
19
|
+
#include "common.h"
|
|
20
|
+
#include "ct.h"
|
|
21
|
+
#include "debug.h"
|
|
22
|
+
|
|
23
|
+
/* Parameter set namespacing
|
|
24
|
+
* This is to facilitate building multiple instances
|
|
25
|
+
* of mldsa-native (e.g. with varying parameter sets)
|
|
26
|
+
* within a single compilation unit. */
|
|
27
|
+
#define mld_power2round MLD_ADD_PARAM_SET(mld_power2round)
|
|
28
|
+
#define mld_decompose MLD_ADD_PARAM_SET(mld_decompose)
|
|
29
|
+
#define mld_make_hint MLD_ADD_PARAM_SET(mld_make_hint)
|
|
30
|
+
#define mld_use_hint MLD_ADD_PARAM_SET(mld_use_hint)
|
|
31
|
+
/* End of parameter set namespacing */
|
|
32
|
+
|
|
33
|
+
#define MLD_2_POW_D (1 << MLDSA_D)
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* For finite field element a, compute a0, a1 such that
|
|
37
|
+
* a mod^+ MLDSA_Q = a1*2^MLDSA_D + a0 with
|
|
38
|
+
* -2^{MLDSA_D-1} < a0 <= 2^{MLDSA_D-1}. Assumes a to be standard
|
|
39
|
+
* representative.
|
|
40
|
+
*
|
|
41
|
+
* @spec{Implements @[FIPS204, Algorithm 35, Power2Round].}
|
|
42
|
+
*
|
|
43
|
+
* @reference{In the reference implementation, a1 is passed as a return value
|
|
44
|
+
* instead.}
|
|
45
|
+
*
|
|
46
|
+
* @param[out] a0 Pointer to output element a0.
|
|
47
|
+
* @param[out] a1 Pointer to output element a1.
|
|
48
|
+
* @param a Input element.
|
|
49
|
+
*/
|
|
50
|
+
static MLD_INLINE void mld_power2round(int32_t *a0, int32_t *a1, int32_t a)
|
|
51
|
+
__contract__(
|
|
52
|
+
requires(memory_no_alias(a0, sizeof(int32_t)))
|
|
53
|
+
requires(memory_no_alias(a1, sizeof(int32_t)))
|
|
54
|
+
requires(a >= 0 && a < MLDSA_Q)
|
|
55
|
+
assigns(memory_slice(a0, sizeof(int32_t)))
|
|
56
|
+
assigns(memory_slice(a1, sizeof(int32_t)))
|
|
57
|
+
ensures(*a0 > -(MLD_2_POW_D/2) && *a0 <= (MLD_2_POW_D/2))
|
|
58
|
+
ensures(*a1 >= 0 && *a1 <= (MLDSA_Q - 1) / MLD_2_POW_D)
|
|
59
|
+
ensures((*a1 * MLD_2_POW_D + *a0 - a) % MLDSA_Q == 0)
|
|
60
|
+
)
|
|
61
|
+
{
|
|
62
|
+
*a1 = (a + (1 << (MLDSA_D - 1)) - 1) >> MLDSA_D;
|
|
63
|
+
*a0 = a - (*a1 << MLDSA_D);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* For finite field element a, compute high and low bits a0, a1 such that
|
|
68
|
+
* a mod^+ MLDSA_Q = a1 * 2 * MLDSA_GAMMA2 + a0 with
|
|
69
|
+
* -MLDSA_GAMMA2 < a0 <= MLDSA_GAMMA2 except if
|
|
70
|
+
* a1 = (MLDSA_Q-1)/(MLDSA_GAMMA2*2) where we set a1 = 0 and
|
|
71
|
+
* -MLDSA_GAMMA2 <= a0 = a mod^+ MLDSA_Q - MLDSA_Q < 0. Assumes a to be
|
|
72
|
+
* standard representative.
|
|
73
|
+
*
|
|
74
|
+
* @spec{Implements @[FIPS204, Algorithm 36, Decompose].}
|
|
75
|
+
*
|
|
76
|
+
* @reference{In the reference implementation, a1 is passed as a return value
|
|
77
|
+
* instead.}
|
|
78
|
+
*
|
|
79
|
+
* @param[out] a0 Pointer to output element a0.
|
|
80
|
+
* @param[out] a1 Pointer to output element a1.
|
|
81
|
+
* @param a Input element.
|
|
82
|
+
*/
|
|
83
|
+
static MLD_INLINE void mld_decompose(int32_t *a0, int32_t *a1, int32_t a)
|
|
84
|
+
__contract__(
|
|
85
|
+
requires(memory_no_alias(a0, sizeof(int32_t)))
|
|
86
|
+
requires(memory_no_alias(a1, sizeof(int32_t)))
|
|
87
|
+
requires(a >= 0 && a < MLDSA_Q)
|
|
88
|
+
assigns(memory_slice(a0, sizeof(int32_t)))
|
|
89
|
+
assigns(memory_slice(a1, sizeof(int32_t)))
|
|
90
|
+
/* a0 = -MLDSA_GAMMA2 occurs exactly when a = MLDSA_Q - MLDSA_GAMMA2: the
|
|
91
|
+
* border case of Decompose where a1 = (MLDSA_Q-1)/(2*MLDSA_GAMMA2) is
|
|
92
|
+
* wrapped to 0 and a0 = a - MLDSA_Q (@[FIPS204, Algorithm 36, Decompose]) */
|
|
93
|
+
ensures(*a0 >= -MLDSA_GAMMA2 && *a0 <= MLDSA_GAMMA2)
|
|
94
|
+
ensures(*a1 >= 0 && *a1 < (MLDSA_Q-1)/(2*MLDSA_GAMMA2))
|
|
95
|
+
ensures((*a1 * 2 * MLDSA_GAMMA2 + *a0 - a) % MLDSA_Q == 0)
|
|
96
|
+
)
|
|
97
|
+
{
|
|
98
|
+
/*
|
|
99
|
+
* The goal is to compute f1 = round-(f / (2*GAMMA2)), which can be computed
|
|
100
|
+
* alternatively as round-(f / (128B)) = round-(ceil(f / 128) / B) where
|
|
101
|
+
* B = 2*GAMMA2 / 128. Here round-() denotes "round half down".
|
|
102
|
+
*
|
|
103
|
+
* The equality round-(f / (128B)) = round-(ceil(f / 128) / B) can deduced
|
|
104
|
+
* as follows. Since changing f to align-up(f, 128) can move f onto but not
|
|
105
|
+
* across a rounding boundary for division by 128*B (note that we need B to be
|
|
106
|
+
* even for this to work), and round- rounds down on the boundary, we have
|
|
107
|
+
*
|
|
108
|
+
* round-(f / (128B)) = round-(align-up(f, 128) / (128B))
|
|
109
|
+
* = round-((align-up(f, 128) / 128) / B)
|
|
110
|
+
* = round-(ceil(f / 128) / B).
|
|
111
|
+
*/
|
|
112
|
+
*a1 = (a + 127) >> 7;
|
|
113
|
+
/* We know a >= 0 and a < MLDSA_Q, so... */
|
|
114
|
+
/* check-magic: 65472 == round((MLDSA_Q-1)/128) */
|
|
115
|
+
mld_assert(*a1 >= 0 && *a1 <= 65472);
|
|
116
|
+
|
|
117
|
+
#if MLD_CONFIG_PARAMETER_SET == 44
|
|
118
|
+
/* check-magic: 1488 == 2 * intdiv(intdiv(MLDSA_Q - 1, 88), 128) */
|
|
119
|
+
/* check-magic: 11275 == floor(2**24 / 1488) */
|
|
120
|
+
/* check-magic: 1560281088 == 1 / (1 / 1488 - 11275 / 2**24) */
|
|
121
|
+
/*
|
|
122
|
+
* Compute f1 = round-(f1' / B) ≈ round(f1' * 11275 / 2^24). This is exact for
|
|
123
|
+
* 0 <= f1' < 2^16.
|
|
124
|
+
*
|
|
125
|
+
* To see this, consider the (signed) error f1' * (1 / B - 11275 / 2^24)
|
|
126
|
+
* between f1' / B and the (under-)approximation f1' * 11275 / 2^24. Because
|
|
127
|
+
* eps := 1 / B - 11275 / 2^24 is 1 / 1560281088 ≈ 2^(-30.54) < 2^(-30), we
|
|
128
|
+
* have 0 <= f1' * eps < 2^16 * 2^(-30) = 1 / 2^14 < 1 / 2^11 < 1 / B (note
|
|
129
|
+
* that f1' is non-negative).
|
|
130
|
+
*
|
|
131
|
+
* On the other hand, 1 / B is the spacing between the integral multiples
|
|
132
|
+
* of 1 / B, which includes all rounding boundaries n + 0.5 (since B is even).
|
|
133
|
+
* Hence, if f1' / B is not of the form n + 0.5, then it is at least 1 / B
|
|
134
|
+
* away from the nearest rounding boundary, so moving from f1' / B to
|
|
135
|
+
* f1' * 11275 / 2^24 does not affect the rounding result, no matter the type
|
|
136
|
+
* of rounding used in either side. In particular, we have round-(f1' / B) =
|
|
137
|
+
* round(f1' * 11275 / 2^24) as claimed.
|
|
138
|
+
*
|
|
139
|
+
* As for the remaining case where f1' / B _is_ of the form n + 0.5, because
|
|
140
|
+
* f1' * 11275 / 2^24 is slightly but strictly below f1' / B = n + 0.5 (note
|
|
141
|
+
* that f1' and thus the error f1' * eps cannot be 0 here), it is always
|
|
142
|
+
* rounded down to n. More precisely, we have round-(f1' / B) =
|
|
143
|
+
* round(f1' * 11275 / 2^24), where the round-down on the LHS is essential,
|
|
144
|
+
* and on the RHS the type of rounding again does not matter. This concludes
|
|
145
|
+
* the proof.
|
|
146
|
+
*
|
|
147
|
+
* See proofs/isabelle/compress for a formalization of the above argument.
|
|
148
|
+
*/
|
|
149
|
+
*a1 = (*a1 * 11275 + ((int32_t)1 << 23)) >> 24;
|
|
150
|
+
mld_assert(*a1 >= 0 && *a1 <= 44);
|
|
151
|
+
|
|
152
|
+
*a1 = mld_ct_sel_int32(0, *a1, mld_ct_cmask_neg_i32(43 - *a1));
|
|
153
|
+
mld_assert(*a1 >= 0 && *a1 <= 43);
|
|
154
|
+
#else /* MLD_CONFIG_PARAMETER_SET == 44 */
|
|
155
|
+
/* check-magic: 4092 == 2 * intdiv(intdiv(MLDSA_Q - 1, 32), 128) */
|
|
156
|
+
/* check-magic: 1025 == floor(2**22 / 4092) */
|
|
157
|
+
/* check-magic: 4290772992 == 1 / (1 / 4092 - 1025 / 2**22) */
|
|
158
|
+
/*
|
|
159
|
+
* Compute f1 = round-(f1' / B) ≈ round(f1' * 1025 / 2^22). This is exact for
|
|
160
|
+
* 0 <= f1' < 2^16. Following the same argument above, it suffices to show
|
|
161
|
+
* that f1' * eps < 1 / B, where eps := 1 / B - 1025 / 2^22. Indeed, we have
|
|
162
|
+
* eps = 1 / 4290772992 ≈ 2^(-31.99) < 2^(-31), therefore f1' * eps <
|
|
163
|
+
* 2^16 * 2^(-31) = 1 / 2^15 < 1 / 2^12 < 1 / B.
|
|
164
|
+
*/
|
|
165
|
+
*a1 = (*a1 * 1025 + ((int32_t)1 << 21)) >> 22;
|
|
166
|
+
mld_assert(*a1 >= 0 && *a1 <= 16);
|
|
167
|
+
|
|
168
|
+
*a1 &= 15;
|
|
169
|
+
mld_assert(*a1 >= 0 && *a1 <= 15);
|
|
170
|
+
|
|
171
|
+
#endif /* MLD_CONFIG_PARAMETER_SET != 44 */
|
|
172
|
+
|
|
173
|
+
*a0 = a - *a1 * 2 * MLDSA_GAMMA2;
|
|
174
|
+
*a0 = mld_ct_sel_int32(*a0 - MLDSA_Q, *a0,
|
|
175
|
+
mld_ct_cmask_neg_i32((MLDSA_Q - 1) / 2 - *a0));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Decide a single hint bit from the low part a0 and high part a1 of a
|
|
180
|
+
* coefficient: return 1 unless a0 lies in the range (-GAMMA2, GAMMA2] that
|
|
181
|
+
* LowBits would produce, with the boundary value -GAMMA2 also admitted when
|
|
182
|
+
* a1 == 0 (the Decompose border case).
|
|
183
|
+
*
|
|
184
|
+
* @note This is not a line-for-line implementation of FIPS 204's MakeHint(z, r)
|
|
185
|
+
* (@[FIPS204, Algorithm 39, MakeHint]), which takes two ring elements and
|
|
186
|
+
* returns [[HighBits(r) != HighBits(r + z)]]. Instead, it takes the already
|
|
187
|
+
* decomposed low/high parts (a0, a1) of a coefficient and decides the hint bit
|
|
188
|
+
* from them directly. As explained in the block comment of
|
|
189
|
+
* mld_attempt_signature_generation (sign.c), for the specific values that arise
|
|
190
|
+
* during signing -- a0 = w0 - cs2 + ct0 and a1 = w1 = HighBits(w) -- this is
|
|
191
|
+
* equivalent to the spec's MakeHint(-ct0, w - cs2 + ct0) coefficient-wise.
|
|
192
|
+
* Because it consumes (a0, a1) rather than (z, r), it relies on the caller
|
|
193
|
+
* having computed a compatible decomposition.
|
|
194
|
+
*
|
|
195
|
+
* @param a0 Low bits of input element.
|
|
196
|
+
* @param a1 High bits of input element.
|
|
197
|
+
*
|
|
198
|
+
* @return 1 if overflow, 0 otherwise.
|
|
199
|
+
*/
|
|
200
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
201
|
+
static MLD_INLINE unsigned int mld_make_hint(int32_t a0, int32_t a1)
|
|
202
|
+
__contract__(
|
|
203
|
+
ensures(return_value >= 0 && return_value <= 1)
|
|
204
|
+
ensures(return_value == (a0 > MLDSA_GAMMA2 || a0 < -MLDSA_GAMMA2 ||
|
|
205
|
+
(a0 == -MLDSA_GAMMA2 && a1 != 0)))
|
|
206
|
+
)
|
|
207
|
+
{
|
|
208
|
+
if (a0 > MLDSA_GAMMA2 || a0 < -MLDSA_GAMMA2 ||
|
|
209
|
+
(a0 == -MLDSA_GAMMA2 && a1 != 0))
|
|
210
|
+
{
|
|
211
|
+
return 1;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return 0;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Correct high bits according to hint.
|
|
219
|
+
*
|
|
220
|
+
* @spec{Implements @[FIPS204, Algorithm 40, UseHint].}
|
|
221
|
+
*
|
|
222
|
+
* @param a Input element.
|
|
223
|
+
* @param hint Hint bit.
|
|
224
|
+
*
|
|
225
|
+
* @return Corrected high bits.
|
|
226
|
+
*/
|
|
227
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
228
|
+
static MLD_INLINE int32_t mld_use_hint(int32_t a, int32_t hint)
|
|
229
|
+
__contract__(
|
|
230
|
+
requires(hint >= 0 && hint <= 1)
|
|
231
|
+
requires(a >= 0 && a < MLDSA_Q)
|
|
232
|
+
ensures(return_value >= 0 && return_value < (MLDSA_Q-1)/(2*MLDSA_GAMMA2))
|
|
233
|
+
)
|
|
234
|
+
{
|
|
235
|
+
int32_t a0, a1;
|
|
236
|
+
|
|
237
|
+
mld_decompose(&a0, &a1, a);
|
|
238
|
+
if (hint == 0)
|
|
239
|
+
{
|
|
240
|
+
return a1;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
#if MLD_CONFIG_PARAMETER_SET == 44
|
|
244
|
+
if (a0 > 0)
|
|
245
|
+
{
|
|
246
|
+
return (a1 == 43) ? 0 : a1 + 1;
|
|
247
|
+
}
|
|
248
|
+
else
|
|
249
|
+
{
|
|
250
|
+
return (a1 == 0) ? 43 : a1 - 1;
|
|
251
|
+
}
|
|
252
|
+
#else /* MLD_CONFIG_PARAMETER_SET == 44 */
|
|
253
|
+
if (a0 > 0)
|
|
254
|
+
{
|
|
255
|
+
return (a1 + 1) & 15;
|
|
256
|
+
}
|
|
257
|
+
else
|
|
258
|
+
{
|
|
259
|
+
return (a1 - 1) & 15;
|
|
260
|
+
}
|
|
261
|
+
#endif /* MLD_CONFIG_PARAMETER_SET != 44 */
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
#endif /* !MLD_ROUNDING_H */
|