ml_dsa 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 (86) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +104 -0
  3. data/LICENSE +14 -0
  4. data/LICENSE-APACHE +185 -0
  5. data/LICENSE-MIT +21 -0
  6. data/README.md +234 -0
  7. data/ext/ml_dsa/extconf.rb +47 -0
  8. data/ext/ml_dsa/fips202.c +933 -0
  9. data/ext/ml_dsa/fips202.h +166 -0
  10. data/ext/ml_dsa/ml-dsa-44/clean/api.h +52 -0
  11. data/ext/ml_dsa/ml-dsa-44/clean/ntt.c +98 -0
  12. data/ext/ml_dsa/ml-dsa-44/clean/ntt.h +10 -0
  13. data/ext/ml_dsa/ml-dsa-44/clean/packing.c +261 -0
  14. data/ext/ml_dsa/ml-dsa-44/clean/packing.h +31 -0
  15. data/ext/ml_dsa/ml-dsa-44/clean/params.h +44 -0
  16. data/ext/ml_dsa/ml-dsa-44/clean/poly.c +848 -0
  17. data/ext/ml_dsa/ml-dsa-44/clean/poly.h +52 -0
  18. data/ext/ml_dsa/ml-dsa-44/clean/polyvec.c +415 -0
  19. data/ext/ml_dsa/ml-dsa-44/clean/polyvec.h +65 -0
  20. data/ext/ml_dsa/ml-dsa-44/clean/reduce.c +69 -0
  21. data/ext/ml_dsa/ml-dsa-44/clean/reduce.h +17 -0
  22. data/ext/ml_dsa/ml-dsa-44/clean/rounding.c +98 -0
  23. data/ext/ml_dsa/ml-dsa-44/clean/rounding.h +14 -0
  24. data/ext/ml_dsa/ml-dsa-44/clean/sign.c +417 -0
  25. data/ext/ml_dsa/ml-dsa-44/clean/sign.h +49 -0
  26. data/ext/ml_dsa/ml-dsa-44/clean/symmetric-shake.c +26 -0
  27. data/ext/ml_dsa/ml-dsa-44/clean/symmetric.h +34 -0
  28. data/ext/ml_dsa/ml-dsa-65/clean/api.h +52 -0
  29. data/ext/ml_dsa/ml-dsa-65/clean/ntt.c +98 -0
  30. data/ext/ml_dsa/ml-dsa-65/clean/ntt.h +10 -0
  31. data/ext/ml_dsa/ml-dsa-65/clean/packing.c +261 -0
  32. data/ext/ml_dsa/ml-dsa-65/clean/packing.h +31 -0
  33. data/ext/ml_dsa/ml-dsa-65/clean/params.h +44 -0
  34. data/ext/ml_dsa/ml-dsa-65/clean/poly.c +799 -0
  35. data/ext/ml_dsa/ml-dsa-65/clean/poly.h +52 -0
  36. data/ext/ml_dsa/ml-dsa-65/clean/polyvec.c +415 -0
  37. data/ext/ml_dsa/ml-dsa-65/clean/polyvec.h +65 -0
  38. data/ext/ml_dsa/ml-dsa-65/clean/reduce.c +69 -0
  39. data/ext/ml_dsa/ml-dsa-65/clean/reduce.h +17 -0
  40. data/ext/ml_dsa/ml-dsa-65/clean/rounding.c +92 -0
  41. data/ext/ml_dsa/ml-dsa-65/clean/rounding.h +14 -0
  42. data/ext/ml_dsa/ml-dsa-65/clean/sign.c +415 -0
  43. data/ext/ml_dsa/ml-dsa-65/clean/sign.h +49 -0
  44. data/ext/ml_dsa/ml-dsa-65/clean/symmetric-shake.c +26 -0
  45. data/ext/ml_dsa/ml-dsa-65/clean/symmetric.h +34 -0
  46. data/ext/ml_dsa/ml-dsa-87/clean/api.h +52 -0
  47. data/ext/ml_dsa/ml-dsa-87/clean/ntt.c +98 -0
  48. data/ext/ml_dsa/ml-dsa-87/clean/ntt.h +10 -0
  49. data/ext/ml_dsa/ml-dsa-87/clean/packing.c +261 -0
  50. data/ext/ml_dsa/ml-dsa-87/clean/packing.h +31 -0
  51. data/ext/ml_dsa/ml-dsa-87/clean/params.h +44 -0
  52. data/ext/ml_dsa/ml-dsa-87/clean/poly.c +823 -0
  53. data/ext/ml_dsa/ml-dsa-87/clean/poly.h +52 -0
  54. data/ext/ml_dsa/ml-dsa-87/clean/polyvec.c +415 -0
  55. data/ext/ml_dsa/ml-dsa-87/clean/polyvec.h +65 -0
  56. data/ext/ml_dsa/ml-dsa-87/clean/reduce.c +69 -0
  57. data/ext/ml_dsa/ml-dsa-87/clean/reduce.h +17 -0
  58. data/ext/ml_dsa/ml-dsa-87/clean/rounding.c +92 -0
  59. data/ext/ml_dsa/ml-dsa-87/clean/rounding.h +14 -0
  60. data/ext/ml_dsa/ml-dsa-87/clean/sign.c +415 -0
  61. data/ext/ml_dsa/ml-dsa-87/clean/sign.h +49 -0
  62. data/ext/ml_dsa/ml-dsa-87/clean/symmetric-shake.c +26 -0
  63. data/ext/ml_dsa/ml-dsa-87/clean/symmetric.h +34 -0
  64. data/ext/ml_dsa/ml_dsa_44_impl.c +10 -0
  65. data/ext/ml_dsa/ml_dsa_65_impl.c +10 -0
  66. data/ext/ml_dsa/ml_dsa_87_impl.c +10 -0
  67. data/ext/ml_dsa/ml_dsa_ext.c +1360 -0
  68. data/ext/ml_dsa/ml_dsa_impl_template.h +35 -0
  69. data/ext/ml_dsa/ml_dsa_internal.h +188 -0
  70. data/ext/ml_dsa/randombytes.c +48 -0
  71. data/ext/ml_dsa/randombytes.h +15 -0
  72. data/lib/ml_dsa/batch_builder.rb +57 -0
  73. data/lib/ml_dsa/config.rb +69 -0
  74. data/lib/ml_dsa/internal.rb +76 -0
  75. data/lib/ml_dsa/key_pair.rb +39 -0
  76. data/lib/ml_dsa/parameter_set.rb +89 -0
  77. data/lib/ml_dsa/public_key.rb +180 -0
  78. data/lib/ml_dsa/requests.rb +96 -0
  79. data/lib/ml_dsa/secret_key.rb +221 -0
  80. data/lib/ml_dsa/version.rb +5 -0
  81. data/lib/ml_dsa.rb +277 -0
  82. data/patches/README.md +55 -0
  83. data/patches/pqclean-explicit-rnd.patch +64 -0
  84. data/sig/ml_dsa.rbs +178 -0
  85. data/test/fixtures/kat_vectors.yaml +16 -0
  86. metadata +194 -0
@@ -0,0 +1,98 @@
1
+ #include "params.h"
2
+ #include "rounding.h"
3
+ #include <stdint.h>
4
+
5
+ /*************************************************
6
+ * Name: PQCLEAN_MLDSA44_CLEAN_power2round
7
+ *
8
+ * Description: For finite field element a, compute a0, a1 such that
9
+ * a mod^+ Q = a1*2^D + a0 with -2^{D-1} < a0 <= 2^{D-1}.
10
+ * Assumes a to be standard representative.
11
+ *
12
+ * Arguments: - int32_t a: input element
13
+ * - int32_t *a0: pointer to output element a0
14
+ *
15
+ * Returns a1.
16
+ **************************************************/
17
+ int32_t PQCLEAN_MLDSA44_CLEAN_power2round(int32_t *a0, int32_t a) {
18
+ int32_t a1;
19
+
20
+ a1 = (a + (1 << (D - 1)) - 1) >> D;
21
+ *a0 = a - (a1 << D);
22
+ return a1;
23
+ }
24
+
25
+ /*************************************************
26
+ * Name: PQCLEAN_MLDSA44_CLEAN_decompose
27
+ *
28
+ * Description: For finite field element a, compute high and low bits a0, a1 such
29
+ * that a mod^+ Q = a1*ALPHA + a0 with -ALPHA/2 < a0 <= ALPHA/2 except
30
+ * if a1 = (Q-1)/ALPHA where we set a1 = 0 and
31
+ * -ALPHA/2 <= a0 = a mod^+ Q - Q < 0. Assumes a to be standard
32
+ * representative.
33
+ *
34
+ * Arguments: - int32_t a: input element
35
+ * - int32_t *a0: pointer to output element a0
36
+ *
37
+ * Returns a1.
38
+ **************************************************/
39
+ int32_t PQCLEAN_MLDSA44_CLEAN_decompose(int32_t *a0, int32_t a) {
40
+ int32_t a1;
41
+
42
+ a1 = (a + 127) >> 7;
43
+ a1 = (a1 * 11275 + (1 << 23)) >> 24;
44
+ a1 ^= ((43 - a1) >> 31) & a1;
45
+
46
+ *a0 = a - a1 * 2 * GAMMA2;
47
+ *a0 -= (((Q - 1) / 2 - *a0) >> 31) & Q;
48
+ return a1;
49
+ }
50
+
51
+ /*************************************************
52
+ * Name: PQCLEAN_MLDSA44_CLEAN_make_hint
53
+ *
54
+ * Description: Compute hint bit indicating whether the low bits of the
55
+ * input element overflow into the high bits.
56
+ *
57
+ * Arguments: - int32_t a0: low bits of input element
58
+ * - int32_t a1: high bits of input element
59
+ *
60
+ * Returns 1 if overflow.
61
+ **************************************************/
62
+ unsigned int PQCLEAN_MLDSA44_CLEAN_make_hint(int32_t a0, int32_t a1) {
63
+ if (a0 > GAMMA2 || a0 < -GAMMA2 || (a0 == -GAMMA2 && a1 != 0)) {
64
+ return 1;
65
+ }
66
+
67
+ return 0;
68
+ }
69
+
70
+ /*************************************************
71
+ * Name: PQCLEAN_MLDSA44_CLEAN_use_hint
72
+ *
73
+ * Description: Correct high bits according to hint.
74
+ *
75
+ * Arguments: - int32_t a: input element
76
+ * - unsigned int hint: hint bit
77
+ *
78
+ * Returns corrected high bits.
79
+ **************************************************/
80
+ int32_t PQCLEAN_MLDSA44_CLEAN_use_hint(int32_t a, unsigned int hint) {
81
+ int32_t a0, a1;
82
+
83
+ a1 = PQCLEAN_MLDSA44_CLEAN_decompose(&a0, a);
84
+ if (hint == 0) {
85
+ return a1;
86
+ }
87
+
88
+ if (a0 > 0) {
89
+ if (a1 == 43) {
90
+ return 0;
91
+ }
92
+ return a1 + 1;
93
+ }
94
+ if (a1 == 0) {
95
+ return 43;
96
+ }
97
+ return a1 - 1;
98
+ }
@@ -0,0 +1,14 @@
1
+ #ifndef PQCLEAN_MLDSA44_CLEAN_ROUNDING_H
2
+ #define PQCLEAN_MLDSA44_CLEAN_ROUNDING_H
3
+ #include "params.h"
4
+ #include <stdint.h>
5
+
6
+ int32_t PQCLEAN_MLDSA44_CLEAN_power2round(int32_t *a0, int32_t a);
7
+
8
+ int32_t PQCLEAN_MLDSA44_CLEAN_decompose(int32_t *a0, int32_t a);
9
+
10
+ unsigned int PQCLEAN_MLDSA44_CLEAN_make_hint(int32_t a0, int32_t a1);
11
+
12
+ int32_t PQCLEAN_MLDSA44_CLEAN_use_hint(int32_t a, unsigned int hint);
13
+
14
+ #endif
@@ -0,0 +1,417 @@
1
+ #include "fips202.h"
2
+ #include "packing.h"
3
+ #include "params.h"
4
+ #include "poly.h"
5
+ #include "polyvec.h"
6
+ #include "randombytes.h"
7
+ #include "sign.h"
8
+ #include "symmetric.h"
9
+ #include <stdint.h>
10
+ #include <string.h>
11
+
12
+ /*************************************************
13
+ * Name: PQCLEAN_MLDSA44_CLEAN_crypto_sign_keypair
14
+ *
15
+ * Description: Generates public and private key.
16
+ *
17
+ * Arguments: - uint8_t *pk: pointer to output public key (allocated
18
+ * array of PQCLEAN_MLDSA44_CLEAN_CRYPTO_PUBLICKEYBYTES bytes)
19
+ * - uint8_t *sk: pointer to output private key (allocated
20
+ * array of PQCLEAN_MLDSA44_CLEAN_CRYPTO_SECRETKEYBYTES bytes)
21
+ *
22
+ * Returns 0 (success)
23
+ **************************************************/
24
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk,
25
+ const uint8_t *seed_in) {
26
+ uint8_t seedbuf[2 * SEEDBYTES + CRHBYTES];
27
+ uint8_t tr[TRBYTES];
28
+ const uint8_t *rho, *rhoprime, *key;
29
+ polyvecl mat[K];
30
+ polyvecl s1, s1hat;
31
+ polyveck s2, t1, t0;
32
+
33
+ /* Caller provides the seed: OS-random for normal keygen,
34
+ * or a user-supplied seed for deterministic keygen. */
35
+ memcpy(seedbuf, seed_in, SEEDBYTES);
36
+ seedbuf[SEEDBYTES + 0] = K;
37
+ seedbuf[SEEDBYTES + 1] = L;
38
+ shake256(seedbuf, 2 * SEEDBYTES + CRHBYTES, seedbuf, SEEDBYTES + 2);
39
+ rho = seedbuf;
40
+ rhoprime = rho + SEEDBYTES;
41
+ key = rhoprime + CRHBYTES;
42
+
43
+ /* Expand matrix */
44
+ PQCLEAN_MLDSA44_CLEAN_polyvec_matrix_expand(mat, rho);
45
+
46
+ /* Sample short vectors s1 and s2 */
47
+ PQCLEAN_MLDSA44_CLEAN_polyvecl_uniform_eta(&s1, rhoprime, 0);
48
+ PQCLEAN_MLDSA44_CLEAN_polyveck_uniform_eta(&s2, rhoprime, L);
49
+
50
+ /* Matrix-vector multiplication */
51
+ s1hat = s1;
52
+ PQCLEAN_MLDSA44_CLEAN_polyvecl_ntt(&s1hat);
53
+ PQCLEAN_MLDSA44_CLEAN_polyvec_matrix_pointwise_montgomery(&t1, mat, &s1hat);
54
+ PQCLEAN_MLDSA44_CLEAN_polyveck_reduce(&t1);
55
+ PQCLEAN_MLDSA44_CLEAN_polyveck_invntt_tomont(&t1);
56
+
57
+ /* Add error vector s2 */
58
+ PQCLEAN_MLDSA44_CLEAN_polyveck_add(&t1, &t1, &s2);
59
+
60
+ /* Extract t1 and write public key */
61
+ PQCLEAN_MLDSA44_CLEAN_polyveck_caddq(&t1);
62
+ PQCLEAN_MLDSA44_CLEAN_polyveck_power2round(&t1, &t0, &t1);
63
+ PQCLEAN_MLDSA44_CLEAN_pack_pk(pk, rho, &t1);
64
+
65
+ /* Compute H(rho, t1) and write secret key */
66
+ shake256(tr, TRBYTES, pk, PQCLEAN_MLDSA44_CLEAN_CRYPTO_PUBLICKEYBYTES);
67
+ PQCLEAN_MLDSA44_CLEAN_pack_sk(sk, rho, tr, key, &t0, &s1, &s2);
68
+
69
+ return 0;
70
+ }
71
+
72
+ /*************************************************
73
+ * Name: crypto_sign_signature
74
+ *
75
+ * Description: Computes signature.
76
+ *
77
+ * Arguments: - uint8_t *sig: pointer to output signature (of length PQCLEAN_MLDSA44_CLEAN_CRYPTO_BYTES)
78
+ * - size_t *siglen: pointer to output length of signature
79
+ * - uint8_t *m: pointer to message to be signed
80
+ * - size_t mlen: length of message
81
+ * - uint8_t *ctx: pointer to context string
82
+ * - size_t ctxlen: length of context string
83
+ * - uint8_t *sk: pointer to bit-packed secret key
84
+ *
85
+ * Returns 0 (success) or -1 (context string too long)
86
+ **************************************************/
87
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign_signature_ctx(uint8_t *sig,
88
+ size_t *siglen,
89
+ const uint8_t *m,
90
+ size_t mlen,
91
+ const uint8_t *ctx,
92
+ size_t ctxlen,
93
+ const uint8_t *sk,
94
+ const uint8_t *rnd_in) {
95
+ unsigned int n;
96
+ uint8_t seedbuf[2 * SEEDBYTES + TRBYTES + RNDBYTES + 2 * CRHBYTES];
97
+ uint8_t *rho, *tr, *key, *mu, *rhoprime, *rnd;
98
+ uint16_t nonce = 0;
99
+ polyvecl mat[K], s1, y, z;
100
+ polyveck t0, s2, w1, w0, h;
101
+ poly cp;
102
+ shake256incctx state;
103
+
104
+ if (ctxlen > 255) {
105
+ return -1;
106
+ }
107
+
108
+ rho = seedbuf;
109
+ tr = rho + SEEDBYTES;
110
+ key = tr + TRBYTES;
111
+ rnd = key + SEEDBYTES;
112
+ mu = rnd + RNDBYTES;
113
+ rhoprime = mu + CRHBYTES;
114
+ PQCLEAN_MLDSA44_CLEAN_unpack_sk(rho, tr, key, &t0, &s1, &s2, sk);
115
+
116
+ /* Compute mu = CRH(tr, 0, ctxlen, ctx, msg) */
117
+ mu[0] = 0;
118
+ mu[1] = (uint8_t)ctxlen;
119
+ shake256_inc_init(&state);
120
+ shake256_inc_absorb(&state, tr, TRBYTES);
121
+ shake256_inc_absorb(&state, mu, 2);
122
+ shake256_inc_absorb(&state, ctx, ctxlen);
123
+ shake256_inc_absorb(&state, m, mlen);
124
+ shake256_inc_finalize(&state);
125
+ shake256_inc_squeeze(mu, CRHBYTES, &state);
126
+ shake256_inc_ctx_release(&state);
127
+
128
+ /* rnd_in is provided by the caller: OS-random for hedged signing,
129
+ * or 0^RNDBYTES for deterministic signing (FIPS 204 §3). */
130
+ memcpy(rnd, rnd_in, RNDBYTES);
131
+ shake256(rhoprime, CRHBYTES, key, SEEDBYTES + RNDBYTES + CRHBYTES);
132
+
133
+ /* Expand matrix and transform vectors */
134
+ PQCLEAN_MLDSA44_CLEAN_polyvec_matrix_expand(mat, rho);
135
+ PQCLEAN_MLDSA44_CLEAN_polyvecl_ntt(&s1);
136
+ PQCLEAN_MLDSA44_CLEAN_polyveck_ntt(&s2);
137
+ PQCLEAN_MLDSA44_CLEAN_polyveck_ntt(&t0);
138
+
139
+ rej:
140
+ /* Sample intermediate vector y */
141
+ PQCLEAN_MLDSA44_CLEAN_polyvecl_uniform_gamma1(&y, rhoprime, nonce++);
142
+
143
+ /* Matrix-vector multiplication */
144
+ z = y;
145
+ PQCLEAN_MLDSA44_CLEAN_polyvecl_ntt(&z);
146
+ PQCLEAN_MLDSA44_CLEAN_polyvec_matrix_pointwise_montgomery(&w1, mat, &z);
147
+ PQCLEAN_MLDSA44_CLEAN_polyveck_reduce(&w1);
148
+ PQCLEAN_MLDSA44_CLEAN_polyveck_invntt_tomont(&w1);
149
+
150
+ /* Decompose w and call the random oracle */
151
+ PQCLEAN_MLDSA44_CLEAN_polyveck_caddq(&w1);
152
+ PQCLEAN_MLDSA44_CLEAN_polyveck_decompose(&w1, &w0, &w1);
153
+ PQCLEAN_MLDSA44_CLEAN_polyveck_pack_w1(sig, &w1);
154
+
155
+ shake256_inc_init(&state);
156
+ shake256_inc_absorb(&state, mu, CRHBYTES);
157
+ shake256_inc_absorb(&state, sig, K * POLYW1_PACKEDBYTES);
158
+ shake256_inc_finalize(&state);
159
+ shake256_inc_squeeze(sig, CTILDEBYTES, &state);
160
+ shake256_inc_ctx_release(&state);
161
+ PQCLEAN_MLDSA44_CLEAN_poly_challenge(&cp, sig);
162
+ PQCLEAN_MLDSA44_CLEAN_poly_ntt(&cp);
163
+
164
+ /* Compute z, reject if it reveals secret */
165
+ PQCLEAN_MLDSA44_CLEAN_polyvecl_pointwise_poly_montgomery(&z, &cp, &s1);
166
+ PQCLEAN_MLDSA44_CLEAN_polyvecl_invntt_tomont(&z);
167
+ PQCLEAN_MLDSA44_CLEAN_polyvecl_add(&z, &z, &y);
168
+ PQCLEAN_MLDSA44_CLEAN_polyvecl_reduce(&z);
169
+ if (PQCLEAN_MLDSA44_CLEAN_polyvecl_chknorm(&z, GAMMA1 - BETA)) {
170
+ goto rej;
171
+ }
172
+
173
+ /* Check that subtracting cs2 does not change high bits of w and low bits
174
+ * do not reveal secret information */
175
+ PQCLEAN_MLDSA44_CLEAN_polyveck_pointwise_poly_montgomery(&h, &cp, &s2);
176
+ PQCLEAN_MLDSA44_CLEAN_polyveck_invntt_tomont(&h);
177
+ PQCLEAN_MLDSA44_CLEAN_polyveck_sub(&w0, &w0, &h);
178
+ PQCLEAN_MLDSA44_CLEAN_polyveck_reduce(&w0);
179
+ if (PQCLEAN_MLDSA44_CLEAN_polyveck_chknorm(&w0, GAMMA2 - BETA)) {
180
+ goto rej;
181
+ }
182
+
183
+ /* Compute hints for w1 */
184
+ PQCLEAN_MLDSA44_CLEAN_polyveck_pointwise_poly_montgomery(&h, &cp, &t0);
185
+ PQCLEAN_MLDSA44_CLEAN_polyveck_invntt_tomont(&h);
186
+ PQCLEAN_MLDSA44_CLEAN_polyveck_reduce(&h);
187
+ if (PQCLEAN_MLDSA44_CLEAN_polyveck_chknorm(&h, GAMMA2)) {
188
+ goto rej;
189
+ }
190
+
191
+ PQCLEAN_MLDSA44_CLEAN_polyveck_add(&w0, &w0, &h);
192
+ n = PQCLEAN_MLDSA44_CLEAN_polyveck_make_hint(&h, &w0, &w1);
193
+ if (n > OMEGA) {
194
+ goto rej;
195
+ }
196
+
197
+ /* Write signature */
198
+ PQCLEAN_MLDSA44_CLEAN_pack_sig(sig, sig, &z, &h);
199
+ *siglen = PQCLEAN_MLDSA44_CLEAN_CRYPTO_BYTES;
200
+ return 0;
201
+ }
202
+
203
+ /*************************************************
204
+ * Name: crypto_sign
205
+ *
206
+ * Description: Compute signed message.
207
+ *
208
+ * Arguments: - uint8_t *sm: pointer to output signed message (allocated
209
+ * array with PQCLEAN_MLDSA44_CLEAN_CRYPTO_BYTES + mlen bytes),
210
+ * can be equal to m
211
+ * - size_t *smlen: pointer to output length of signed
212
+ * message
213
+ * - const uint8_t *m: pointer to message to be signed
214
+ * - size_t mlen: length of message
215
+ * - const uint8_t *ctx: pointer to context string
216
+ * - size_t ctxlen: length of context string
217
+ * - const uint8_t *sk: pointer to bit-packed secret key
218
+ *
219
+ * Returns 0 (success) or -1 (context string too long)
220
+ **************************************************/
221
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign_ctx(uint8_t *sm,
222
+ size_t *smlen,
223
+ const uint8_t *m,
224
+ size_t mlen,
225
+ const uint8_t *ctx,
226
+ size_t ctxlen,
227
+ const uint8_t *sk) {
228
+ int ret;
229
+ size_t i;
230
+ uint8_t rnd[RNDBYTES];
231
+
232
+ randombytes(rnd, RNDBYTES);
233
+ for (i = 0; i < mlen; ++i) {
234
+ sm[PQCLEAN_MLDSA44_CLEAN_CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i];
235
+ }
236
+ ret = PQCLEAN_MLDSA44_CLEAN_crypto_sign_signature_ctx(sm, smlen, sm + PQCLEAN_MLDSA44_CLEAN_CRYPTO_BYTES, mlen, ctx, ctxlen, sk, rnd);
237
+ *smlen += mlen;
238
+ return ret;
239
+ }
240
+
241
+ /*************************************************
242
+ * Name: crypto_sign_verify
243
+ *
244
+ * Description: Verifies signature.
245
+ *
246
+ * Arguments: - uint8_t *m: pointer to input signature
247
+ * - size_t siglen: length of signature
248
+ * - const uint8_t *m: pointer to message
249
+ * - size_t mlen: length of message
250
+ * - const uint8_t *ctx: pointer to context string
251
+ * - size_t ctxlen: length of context string
252
+ * - const uint8_t *pk: pointer to bit-packed public key
253
+ *
254
+ * Returns 0 if signature could be verified correctly and -1 otherwise
255
+ **************************************************/
256
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign_verify_ctx(const uint8_t *sig,
257
+ size_t siglen,
258
+ const uint8_t *m,
259
+ size_t mlen,
260
+ const uint8_t *ctx,
261
+ size_t ctxlen,
262
+ const uint8_t *pk) {
263
+ unsigned int i;
264
+ uint8_t buf[K * POLYW1_PACKEDBYTES];
265
+ uint8_t rho[SEEDBYTES];
266
+ uint8_t mu[CRHBYTES];
267
+ uint8_t c[CTILDEBYTES];
268
+ uint8_t c2[CTILDEBYTES];
269
+ poly cp;
270
+ polyvecl mat[K], z;
271
+ polyveck t1, w1, h;
272
+ shake256incctx state;
273
+
274
+ if (ctxlen > 255 || siglen != PQCLEAN_MLDSA44_CLEAN_CRYPTO_BYTES) {
275
+ return -1;
276
+ }
277
+
278
+ PQCLEAN_MLDSA44_CLEAN_unpack_pk(rho, &t1, pk);
279
+ if (PQCLEAN_MLDSA44_CLEAN_unpack_sig(c, &z, &h, sig)) {
280
+ return -1;
281
+ }
282
+ if (PQCLEAN_MLDSA44_CLEAN_polyvecl_chknorm(&z, GAMMA1 - BETA)) {
283
+ return -1;
284
+ }
285
+
286
+ /* Compute CRH(H(rho, t1), msg) */
287
+ shake256(mu, TRBYTES, pk, PQCLEAN_MLDSA44_CLEAN_CRYPTO_PUBLICKEYBYTES);
288
+ shake256_inc_init(&state);
289
+ shake256_inc_absorb(&state, mu, TRBYTES);
290
+ mu[0] = 0;
291
+ mu[1] = (uint8_t)ctxlen;
292
+ shake256_inc_absorb(&state, mu, 2);
293
+ shake256_inc_absorb(&state, ctx, ctxlen);
294
+ shake256_inc_absorb(&state, m, mlen);
295
+ shake256_inc_finalize(&state);
296
+ shake256_inc_squeeze(mu, CRHBYTES, &state);
297
+ shake256_inc_ctx_release(&state);
298
+
299
+ /* Matrix-vector multiplication; compute Az - c2^dt1 */
300
+ PQCLEAN_MLDSA44_CLEAN_poly_challenge(&cp, c);
301
+ PQCLEAN_MLDSA44_CLEAN_polyvec_matrix_expand(mat, rho);
302
+
303
+ PQCLEAN_MLDSA44_CLEAN_polyvecl_ntt(&z);
304
+ PQCLEAN_MLDSA44_CLEAN_polyvec_matrix_pointwise_montgomery(&w1, mat, &z);
305
+
306
+ PQCLEAN_MLDSA44_CLEAN_poly_ntt(&cp);
307
+ PQCLEAN_MLDSA44_CLEAN_polyveck_shiftl(&t1);
308
+ PQCLEAN_MLDSA44_CLEAN_polyveck_ntt(&t1);
309
+ PQCLEAN_MLDSA44_CLEAN_polyveck_pointwise_poly_montgomery(&t1, &cp, &t1);
310
+
311
+ PQCLEAN_MLDSA44_CLEAN_polyveck_sub(&w1, &w1, &t1);
312
+ PQCLEAN_MLDSA44_CLEAN_polyveck_reduce(&w1);
313
+ PQCLEAN_MLDSA44_CLEAN_polyveck_invntt_tomont(&w1);
314
+
315
+ /* Reconstruct w1 */
316
+ PQCLEAN_MLDSA44_CLEAN_polyveck_caddq(&w1);
317
+ PQCLEAN_MLDSA44_CLEAN_polyveck_use_hint(&w1, &w1, &h);
318
+ PQCLEAN_MLDSA44_CLEAN_polyveck_pack_w1(buf, &w1);
319
+
320
+ /* Call random oracle and verify challenge */
321
+ shake256_inc_init(&state);
322
+ shake256_inc_absorb(&state, mu, CRHBYTES);
323
+ shake256_inc_absorb(&state, buf, K * POLYW1_PACKEDBYTES);
324
+ shake256_inc_finalize(&state);
325
+ shake256_inc_squeeze(c2, CTILDEBYTES, &state);
326
+ shake256_inc_ctx_release(&state);
327
+ for (i = 0; i < CTILDEBYTES; ++i) {
328
+ if (c[i] != c2[i]) {
329
+ return -1;
330
+ }
331
+ }
332
+
333
+ return 0;
334
+ }
335
+
336
+ /*************************************************
337
+ * Name: crypto_sign_open
338
+ *
339
+ * Description: Verify signed message.
340
+ *
341
+ * Arguments: - uint8_t *m: pointer to output message (allocated
342
+ * array with smlen bytes), can be equal to sm
343
+ * - size_t *mlen: pointer to output length of message
344
+ * - const uint8_t *sm: pointer to signed message
345
+ * - size_t smlen: length of signed message
346
+ * - const uint8_t *ctx: pointer to context tring
347
+ * - size_t ctxlen: length of context string
348
+ * - const uint8_t *pk: pointer to bit-packed public key
349
+ *
350
+ * Returns 0 if signed message could be verified correctly and -1 otherwise
351
+ **************************************************/
352
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign_open_ctx(uint8_t *m,
353
+ size_t *mlen,
354
+ const uint8_t *sm,
355
+ size_t smlen,
356
+ const uint8_t *ctx,
357
+ size_t ctxlen,
358
+ const uint8_t *pk) {
359
+ size_t i;
360
+
361
+ if (smlen < PQCLEAN_MLDSA44_CLEAN_CRYPTO_BYTES) {
362
+ goto badsig;
363
+ }
364
+
365
+ *mlen = smlen - PQCLEAN_MLDSA44_CLEAN_CRYPTO_BYTES;
366
+ if (PQCLEAN_MLDSA44_CLEAN_crypto_sign_verify_ctx(sm, PQCLEAN_MLDSA44_CLEAN_CRYPTO_BYTES, sm + PQCLEAN_MLDSA44_CLEAN_CRYPTO_BYTES, *mlen, ctx, ctxlen, pk)) {
367
+ goto badsig;
368
+ } else {
369
+ /* All good, copy msg, return 0 */
370
+ for (i = 0; i < *mlen; ++i) {
371
+ m[i] = sm[PQCLEAN_MLDSA44_CLEAN_CRYPTO_BYTES + i];
372
+ }
373
+ return 0;
374
+ }
375
+
376
+ badsig:
377
+ /* Signature verification failed */
378
+ *mlen = 0;
379
+ for (i = 0; i < smlen; ++i) {
380
+ m[i] = 0;
381
+ }
382
+
383
+ return -1;
384
+ }
385
+
386
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign_signature(uint8_t *sig,
387
+ size_t *siglen,
388
+ const uint8_t *m,
389
+ size_t mlen,
390
+ const uint8_t *sk) {
391
+ uint8_t rnd[RNDBYTES];
392
+ randombytes(rnd, RNDBYTES);
393
+ return PQCLEAN_MLDSA44_CLEAN_crypto_sign_signature_ctx(sig, siglen, m, mlen, NULL, 0, sk, rnd);
394
+ }
395
+
396
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign(uint8_t *sm,
397
+ size_t *smlen,
398
+ const uint8_t *m,
399
+ size_t mlen,
400
+ const uint8_t *sk) {
401
+ return PQCLEAN_MLDSA44_CLEAN_crypto_sign_ctx(sm, smlen, m, mlen, NULL, 0, sk);
402
+ }
403
+
404
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign_verify(const uint8_t *sig,
405
+ size_t siglen,
406
+ const uint8_t *m,
407
+ size_t mlen,
408
+ const uint8_t *pk) {
409
+ return PQCLEAN_MLDSA44_CLEAN_crypto_sign_verify_ctx(sig, siglen, m, mlen, NULL, 0, pk);
410
+ }
411
+
412
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign_open(uint8_t *m,
413
+ size_t *mlen,
414
+ const uint8_t *sm, size_t smlen,
415
+ const uint8_t *pk) {
416
+ return PQCLEAN_MLDSA44_CLEAN_crypto_sign_open_ctx(m, mlen, sm, smlen, NULL, 0, pk);
417
+ }
@@ -0,0 +1,49 @@
1
+ #ifndef PQCLEAN_MLDSA44_CLEAN_SIGN_H
2
+ #define PQCLEAN_MLDSA44_CLEAN_SIGN_H
3
+ #include "params.h"
4
+ #include "poly.h"
5
+ #include "polyvec.h"
6
+ #include <stddef.h>
7
+ #include <stdint.h>
8
+
9
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk,
10
+ const uint8_t *seed_in);
11
+
12
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign_signature_ctx(uint8_t *sig, size_t *siglen,
13
+ const uint8_t *m, size_t mlen,
14
+ const uint8_t *ctx, size_t ctxlen,
15
+ const uint8_t *sk,
16
+ const uint8_t *rnd_in);
17
+
18
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign_ctx(uint8_t *sm, size_t *smlen,
19
+ const uint8_t *m, size_t mlen,
20
+ const uint8_t *ctx, size_t ctxlen,
21
+ const uint8_t *sk);
22
+
23
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign_verify_ctx(const uint8_t *sig, size_t siglen,
24
+ const uint8_t *m, size_t mlen,
25
+ const uint8_t *ctx, size_t ctxlen,
26
+ const uint8_t *pk);
27
+
28
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign_open_ctx(uint8_t *m, size_t *mlen,
29
+ const uint8_t *sm, size_t smlen,
30
+ const uint8_t *ctx, size_t ctxlen,
31
+ const uint8_t *pk);
32
+
33
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen,
34
+ const uint8_t *m, size_t mlen,
35
+ const uint8_t *sk);
36
+
37
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen,
38
+ const uint8_t *m, size_t mlen,
39
+ const uint8_t *sk);
40
+
41
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen,
42
+ const uint8_t *m, size_t mlen,
43
+ const uint8_t *pk);
44
+
45
+ int PQCLEAN_MLDSA44_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen,
46
+ const uint8_t *sm, size_t smlen,
47
+ const uint8_t *pk);
48
+
49
+ #endif
@@ -0,0 +1,26 @@
1
+ #include "fips202.h"
2
+ #include "params.h"
3
+ #include "symmetric.h"
4
+ #include <stdint.h>
5
+
6
+ void PQCLEAN_MLDSA44_CLEAN_dilithium_shake128_stream_init(shake128incctx *state, const uint8_t seed[SEEDBYTES], uint16_t nonce) {
7
+ uint8_t t[2];
8
+ t[0] = (uint8_t) nonce;
9
+ t[1] = (uint8_t) (nonce >> 8);
10
+
11
+ shake128_inc_init(state);
12
+ shake128_inc_absorb(state, seed, SEEDBYTES);
13
+ shake128_inc_absorb(state, t, 2);
14
+ shake128_inc_finalize(state);
15
+ }
16
+
17
+ void PQCLEAN_MLDSA44_CLEAN_dilithium_shake256_stream_init(shake256incctx *state, const uint8_t seed[CRHBYTES], uint16_t nonce) {
18
+ uint8_t t[2];
19
+ t[0] = (uint8_t) nonce;
20
+ t[1] = (uint8_t) (nonce >> 8);
21
+
22
+ shake256_inc_init(state);
23
+ shake256_inc_absorb(state, seed, CRHBYTES);
24
+ shake256_inc_absorb(state, t, 2);
25
+ shake256_inc_finalize(state);
26
+ }
@@ -0,0 +1,34 @@
1
+ #ifndef PQCLEAN_MLDSA44_CLEAN_SYMMETRIC_H
2
+ #define PQCLEAN_MLDSA44_CLEAN_SYMMETRIC_H
3
+ #include "fips202.h"
4
+ #include "params.h"
5
+ #include <stdint.h>
6
+
7
+
8
+ typedef shake128incctx stream128_state;
9
+ typedef shake256incctx stream256_state;
10
+
11
+ void PQCLEAN_MLDSA44_CLEAN_dilithium_shake128_stream_init(shake128incctx *state,
12
+ const uint8_t seed[SEEDBYTES],
13
+ uint16_t nonce);
14
+
15
+ void PQCLEAN_MLDSA44_CLEAN_dilithium_shake256_stream_init(shake256incctx *state,
16
+ const uint8_t seed[CRHBYTES],
17
+ uint16_t nonce);
18
+
19
+ #define STREAM128_BLOCKBYTES SHAKE128_RATE
20
+ #define STREAM256_BLOCKBYTES SHAKE256_RATE
21
+
22
+ #define stream128_init(STATE, SEED, NONCE) \
23
+ PQCLEAN_MLDSA44_CLEAN_dilithium_shake128_stream_init(STATE, SEED, NONCE)
24
+ #define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) \
25
+ shake128_inc_squeeze(OUT, (OUTBLOCKS)*(SHAKE128_RATE), STATE)
26
+ #define stream128_release(STATE) shake128_inc_ctx_release(STATE)
27
+
28
+ #define stream256_init(STATE, SEED, NONCE) \
29
+ PQCLEAN_MLDSA44_CLEAN_dilithium_shake256_stream_init(STATE, SEED, NONCE)
30
+ #define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) \
31
+ shake256_inc_squeeze(OUT, (OUTBLOCKS)*(SHAKE256_RATE), STATE)
32
+ #define stream256_release(STATE) shake256_inc_ctx_release(STATE)
33
+
34
+ #endif
@@ -0,0 +1,52 @@
1
+ #ifndef PQCLEAN_MLDSA65_CLEAN_API_H
2
+ #define PQCLEAN_MLDSA65_CLEAN_API_H
3
+
4
+ #include <stddef.h>
5
+ #include <stdint.h>
6
+
7
+ #define PQCLEAN_MLDSA65_CLEAN_CRYPTO_PUBLICKEYBYTES 1952
8
+ #define PQCLEAN_MLDSA65_CLEAN_CRYPTO_SECRETKEYBYTES 4032
9
+ #define PQCLEAN_MLDSA65_CLEAN_CRYPTO_BYTES 3309
10
+ #define PQCLEAN_MLDSA65_CLEAN_CRYPTO_ALGNAME "ML-DSA-65"
11
+
12
+ int PQCLEAN_MLDSA65_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk,
13
+ const uint8_t *seed_in);
14
+
15
+ int PQCLEAN_MLDSA65_CLEAN_crypto_sign_signature_ctx(uint8_t *sig, size_t *siglen,
16
+ const uint8_t *m, size_t mlen,
17
+ const uint8_t *ctx, size_t ctxlen,
18
+ const uint8_t *sk,
19
+ const uint8_t *rnd_in);
20
+
21
+ int PQCLEAN_MLDSA65_CLEAN_crypto_sign_ctx(uint8_t *sm, size_t *smlen,
22
+ const uint8_t *m, size_t mlen,
23
+ const uint8_t *ctx, size_t ctxlen,
24
+ const uint8_t *sk);
25
+
26
+ int PQCLEAN_MLDSA65_CLEAN_crypto_sign_verify_ctx(const uint8_t *sig, size_t siglen,
27
+ const uint8_t *m, size_t mlen,
28
+ const uint8_t *ctx, size_t ctxlen,
29
+ const uint8_t *pk);
30
+
31
+ int PQCLEAN_MLDSA65_CLEAN_crypto_sign_open_ctx(uint8_t *m, size_t *mlen,
32
+ const uint8_t *sm, size_t smlen,
33
+ const uint8_t *ctx, size_t ctxlen,
34
+ const uint8_t *pk);
35
+
36
+ int PQCLEAN_MLDSA65_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen,
37
+ const uint8_t *m, size_t mlen,
38
+ const uint8_t *sk);
39
+
40
+ int PQCLEAN_MLDSA65_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen,
41
+ const uint8_t *m, size_t mlen,
42
+ const uint8_t *sk);
43
+
44
+ int PQCLEAN_MLDSA65_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen,
45
+ const uint8_t *m, size_t mlen,
46
+ const uint8_t *pk);
47
+
48
+ int PQCLEAN_MLDSA65_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen,
49
+ const uint8_t *sm, size_t smlen,
50
+ const uint8_t *pk);
51
+
52
+ #endif