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.
Files changed (128) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +88 -0
  4. data/ext/mldsa_gh_native/extconf.rb +14 -0
  5. data/ext/mldsa_gh_native/mldsa_gh_native.c +222 -0
  6. data/ext/mldsa_gh_native/mldsa_gh_native_all.c +24 -0
  7. data/ext/mldsa_gh_native/mldsa_gh_native_all.h +26 -0
  8. data/ext/mldsa_gh_native/vendor/mldsa-native/BUILDING.md +108 -0
  9. data/ext/mldsa_gh_native/vendor/mldsa-native/LICENSE +305 -0
  10. data/ext/mldsa_gh_native/vendor/mldsa-native/README.md +247 -0
  11. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/README.md +23 -0
  12. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/mldsa_native.c +803 -0
  13. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/mldsa_native.h +956 -0
  14. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/mldsa_native_asm.S +830 -0
  15. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/mldsa_native_config.h +855 -0
  16. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/cbmc.h +233 -0
  17. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/common.h +301 -0
  18. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/context.h +152 -0
  19. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/ct.c +21 -0
  20. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/ct.h +373 -0
  21. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/debug.c +75 -0
  22. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/debug.h +125 -0
  23. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/fips202.c +270 -0
  24. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/fips202.h +224 -0
  25. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/fips202x4.c +187 -0
  26. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/fips202x4.h +125 -0
  27. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.c +510 -0
  28. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.h +110 -0
  29. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/auto.h +85 -0
  30. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/fips202_native_aarch64.h +69 -0
  31. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_aarch64_asm.S +378 -0
  32. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_aarch64_asm.S +207 -0
  33. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_aarch64_asm.S +262 -0
  34. 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
  35. 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
  36. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccakf1600_round_constants.c +47 -0
  37. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_scalar.h +27 -0
  38. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_v84a.h +36 -0
  39. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x2_v84a.h +40 -0
  40. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_scalar.h +32 -0
  41. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_v84a_scalar.h +37 -0
  42. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/api.h +129 -0
  43. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/README.md +10 -0
  44. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/mve.h +67 -0
  45. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/fips202_native_armv81m.h +37 -0
  46. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.S +717 -0
  47. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.c +42 -0
  48. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_state_extract_bytes_mve.S +334 -0
  49. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_state_xor_bytes_mve.S +355 -0
  50. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccakf1600_round_constants.c +53 -0
  51. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/auto.h +35 -0
  52. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/keccak_f1600_x4_avx2.h +34 -0
  53. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/fips202_native_x86_64.h +45 -0
  54. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/keccak_f1600_x4_avx2_asm.S +488 -0
  55. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/keccakf1600_constants.c +52 -0
  56. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/meta.h +314 -0
  57. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/aarch64_zetas.c +248 -0
  58. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/arith_native_aarch64.h +367 -0
  59. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_intt_aarch64_asm.S +786 -0
  60. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_ntt_aarch64_asm.S +686 -0
  61. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_pointwise_montgomery_aarch64_asm.S +106 -0
  62. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_caddq_aarch64_asm.S +69 -0
  63. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_chknorm_aarch64_asm.S +76 -0
  64. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_decompose_32_aarch64_asm.S +108 -0
  65. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_decompose_88_aarch64_asm.S +108 -0
  66. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_use_hint_32_aarch64_asm.S +125 -0
  67. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_use_hint_88_aarch64_asm.S +133 -0
  68. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_polyvecl_pointwise_acc_montgomery_l4_aarch64_asm.S +157 -0
  69. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_polyvecl_pointwise_acc_montgomery_l5_aarch64_asm.S +173 -0
  70. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_polyvecl_pointwise_acc_montgomery_l7_aarch64_asm.S +205 -0
  71. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_polyz_unpack_17_aarch64_asm.S +103 -0
  72. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_polyz_unpack_19_aarch64_asm.S +100 -0
  73. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_rej_uniform_aarch64_asm.S +222 -0
  74. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_rej_uniform_eta2_aarch64_asm.S +170 -0
  75. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_rej_uniform_eta4_aarch64_asm.S +163 -0
  76. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_table.c +52 -0
  77. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta_table.c +547 -0
  78. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_table.c +63 -0
  79. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/api.h +617 -0
  80. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/meta.h +24 -0
  81. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/meta.h +323 -0
  82. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/arith_native_x86_64.h +330 -0
  83. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.c +157 -0
  84. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.h +27 -0
  85. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_intt_avx2_asm.S +2333 -0
  86. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_ntt_avx2_asm.S +2405 -0
  87. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_nttunpack_avx2_asm.S +254 -0
  88. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_pointwise_acc_l4_avx2_asm.S +173 -0
  89. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_pointwise_acc_l5_avx2_asm.S +189 -0
  90. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_pointwise_acc_l7_avx2_asm.S +221 -0
  91. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_pointwise_avx2_asm.S +158 -0
  92. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_caddq_avx2_asm.S +199 -0
  93. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_chknorm_avx2_asm.S +176 -0
  94. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_decompose_32_avx2_asm.S +490 -0
  95. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_decompose_88_avx2_asm.S +489 -0
  96. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_use_hint_32_avx2_asm.S +123 -0
  97. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_use_hint_88_avx2_asm.S +125 -0
  98. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_polyz_unpack_17_avx2_asm.S +355 -0
  99. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_polyz_unpack_19_avx2_asm.S +355 -0
  100. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_rej_uniform_avx2_asm.S +132 -0
  101. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_rej_uniform_eta2_avx2_asm.S +205 -0
  102. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_rej_uniform_eta4_avx2_asm.S +176 -0
  103. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_table.c +161 -0
  104. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/packing.c +213 -0
  105. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/packing.h +277 -0
  106. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/params.h +153 -0
  107. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/poly.c +1066 -0
  108. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/poly.h +464 -0
  109. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/poly_kl.c +910 -0
  110. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/poly_kl.h +367 -0
  111. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/polyvec.c +509 -0
  112. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/polyvec.h +435 -0
  113. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/polyvec_lazy.c +311 -0
  114. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/polyvec_lazy.h +652 -0
  115. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/randombytes.h +26 -0
  116. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/reduce.h +144 -0
  117. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/rounding.h +265 -0
  118. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/sign.c +1720 -0
  119. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/sign.h +850 -0
  120. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/symmetric.h +68 -0
  121. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/sys.h +327 -0
  122. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/zetas.inc +55 -0
  123. data/lib/mldsa/parameter_set.rb +82 -0
  124. data/lib/mldsa/signing_key.rb +147 -0
  125. data/lib/mldsa/verify_key.rb +72 -0
  126. data/lib/mldsa/version.rb +7 -0
  127. data/lib/mldsa_gh.rb +93 -0
  128. 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 */