kpqc 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 (191) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +21 -0
  4. data/README.md +174 -0
  5. data/Rakefile +57 -0
  6. data/THIRD_PARTY_NOTICES.md +53 -0
  7. data/ext/kpqc/aimer128f/extconf.rb +4 -0
  8. data/ext/kpqc/aimer128s/extconf.rb +4 -0
  9. data/ext/kpqc/aimer192f/extconf.rb +4 -0
  10. data/ext/kpqc/aimer192s/extconf.rb +4 -0
  11. data/ext/kpqc/aimer256f/extconf.rb +4 -0
  12. data/ext/kpqc/aimer256s/extconf.rb +4 -0
  13. data/ext/kpqc/extconf_helper.rb +93 -0
  14. data/ext/kpqc/haetae2/extconf.rb +4 -0
  15. data/ext/kpqc/haetae3/extconf.rb +4 -0
  16. data/ext/kpqc/haetae5/extconf.rb +4 -0
  17. data/ext/kpqc/module.c +195 -0
  18. data/ext/kpqc/ntruplus1152/extconf.rb +4 -0
  19. data/ext/kpqc/ntruplus768/extconf.rb +4 -0
  20. data/ext/kpqc/ntruplus864/extconf.rb +4 -0
  21. data/ext/kpqc/randombytes.c +107 -0
  22. data/ext/kpqc/smaugt128/extconf.rb +4 -0
  23. data/ext/kpqc/smaugt192/extconf.rb +4 -0
  24. data/ext/kpqc/smaugt256/extconf.rb +4 -0
  25. data/ext/kpqc/timer/extconf.rb +4 -0
  26. data/kpqc.gemspec +41 -0
  27. data/lib/kpqc/aimer.rb +38 -0
  28. data/lib/kpqc/api.rb +129 -0
  29. data/lib/kpqc/haetae.rb +25 -0
  30. data/lib/kpqc/ntruplus.rb +25 -0
  31. data/lib/kpqc/smaugt.rb +29 -0
  32. data/lib/kpqc/types.rb +103 -0
  33. data/lib/kpqc/version.rb +6 -0
  34. data/lib/kpqc.rb +33 -0
  35. data/test/algorithm_test.rb +111 -0
  36. data/test/api_test.rb +52 -0
  37. data/test/interop.mjs +34 -0
  38. data/test/interop_test.rb +82 -0
  39. data/test/kat/aimer128f.rsp +10 -0
  40. data/test/kat/aimer128s.rsp +10 -0
  41. data/test/kat/aimer192f.rsp +10 -0
  42. data/test/kat/aimer192s.rsp +10 -0
  43. data/test/kat/aimer256f.rsp +10 -0
  44. data/test/kat/aimer256s.rsp +10 -0
  45. data/test/kat/haetae2.rsp +10 -0
  46. data/test/kat/haetae3.rsp +10 -0
  47. data/test/kat/haetae5.rsp +10 -0
  48. data/test/kat/ntruplus1152.rsp +8 -0
  49. data/test/kat/ntruplus768.rsp +8 -0
  50. data/test/kat/ntruplus864.rsp +8 -0
  51. data/test/kat/smaugt128.rsp +8 -0
  52. data/test/kat/smaugt192.rsp +8 -0
  53. data/test/kat/smaugt256.rsp +8 -0
  54. data/test/kat/timer.rsp +8 -0
  55. data/test/kat_drbg.rb +155 -0
  56. data/test/kat_test.rb +99 -0
  57. data/test/test_helper.rb +21 -0
  58. data/vendor/AIMer/LICENSE +21 -0
  59. data/vendor/AIMer/aim2.c +163 -0
  60. data/vendor/AIMer/aim2.h +36 -0
  61. data/vendor/AIMer/aim2_constant.h +74 -0
  62. data/vendor/AIMer/api.h +42 -0
  63. data/vendor/AIMer/common/crypto_declassify.h +7 -0
  64. data/vendor/AIMer/common/fips202.c +878 -0
  65. data/vendor/AIMer/common/fips202.h +166 -0
  66. data/vendor/AIMer/common/rng.h +56 -0
  67. data/vendor/AIMer/field.h +43 -0
  68. data/vendor/AIMer/field128.c +454 -0
  69. data/vendor/AIMer/field192.c +485 -0
  70. data/vendor/AIMer/field256.c +564 -0
  71. data/vendor/AIMer/hash.c +50 -0
  72. data/vendor/AIMer/hash.h +37 -0
  73. data/vendor/AIMer/params/params-aimer-128f.h +34 -0
  74. data/vendor/AIMer/params/params-aimer-128s.h +34 -0
  75. data/vendor/AIMer/params/params-aimer-192f.h +34 -0
  76. data/vendor/AIMer/params/params-aimer-192s.h +34 -0
  77. data/vendor/AIMer/params/params-aimer-256f.h +34 -0
  78. data/vendor/AIMer/params/params-aimer-256s.h +34 -0
  79. data/vendor/AIMer/params.h +5 -0
  80. data/vendor/AIMer/sign.c +631 -0
  81. data/vendor/AIMer/sign.h +40 -0
  82. data/vendor/AIMer/tree.c +75 -0
  83. data/vendor/AIMer/tree.h +26 -0
  84. data/vendor/HAETAE/LICENSE +22 -0
  85. data/vendor/HAETAE/include/api.h +54 -0
  86. data/vendor/HAETAE/include/common.h +12 -0
  87. data/vendor/HAETAE/include/config.h +42 -0
  88. data/vendor/HAETAE/include/decompose.h +19 -0
  89. data/vendor/HAETAE/include/encoding.h +20 -0
  90. data/vendor/HAETAE/include/fft.h +26 -0
  91. data/vendor/HAETAE/include/fips202.h +40 -0
  92. data/vendor/HAETAE/include/fixpoint.h +125 -0
  93. data/vendor/HAETAE/include/ntt.h +16 -0
  94. data/vendor/HAETAE/include/packing.h +58 -0
  95. data/vendor/HAETAE/include/params.h +117 -0
  96. data/vendor/HAETAE/include/poly.h +65 -0
  97. data/vendor/HAETAE/include/polyfix.h +65 -0
  98. data/vendor/HAETAE/include/polymat.h +32 -0
  99. data/vendor/HAETAE/include/polyvec.h +131 -0
  100. data/vendor/HAETAE/include/randombytes.h +39 -0
  101. data/vendor/HAETAE/include/rans_byte.h +335 -0
  102. data/vendor/HAETAE/include/reduce.h +31 -0
  103. data/vendor/HAETAE/include/sampler.h +23 -0
  104. data/vendor/HAETAE/include/symmetric.h +52 -0
  105. data/vendor/HAETAE/src/decompose.c +73 -0
  106. data/vendor/HAETAE/src/encoding.c +700 -0
  107. data/vendor/HAETAE/src/fft.c +235 -0
  108. data/vendor/HAETAE/src/fips202.c +745 -0
  109. data/vendor/HAETAE/src/fixpoint.c +143 -0
  110. data/vendor/HAETAE/src/ntt.c +98 -0
  111. data/vendor/HAETAE/src/packing.c +595 -0
  112. data/vendor/HAETAE/src/poly.c +371 -0
  113. data/vendor/HAETAE/src/polyfix.c +298 -0
  114. data/vendor/HAETAE/src/polymat.c +82 -0
  115. data/vendor/HAETAE/src/polyvec.c +534 -0
  116. data/vendor/HAETAE/src/reduce.c +96 -0
  117. data/vendor/HAETAE/src/sampler.c +310 -0
  118. data/vendor/HAETAE/src/sign.c +558 -0
  119. data/vendor/HAETAE/src/symmetric-shake.c +50 -0
  120. data/vendor/NTRUplus/LICENSE +21 -0
  121. data/vendor/NTRUplus/NTRU+1152/api.h +24 -0
  122. data/vendor/NTRUplus/NTRU+1152/fips202/fips202.c +878 -0
  123. data/vendor/NTRUplus/NTRU+1152/fips202/fips202.h +166 -0
  124. data/vendor/NTRUplus/NTRU+1152/kem.c +286 -0
  125. data/vendor/NTRUplus/NTRU+1152/ntt.c +394 -0
  126. data/vendor/NTRUplus/NTRU+1152/ntt.h +16 -0
  127. data/vendor/NTRUplus/NTRU+1152/params.h +18 -0
  128. data/vendor/NTRUplus/NTRU+1152/poly.c +318 -0
  129. data/vendor/NTRUplus/NTRU+1152/poly.h +31 -0
  130. data/vendor/NTRUplus/NTRU+1152/randombytes.h +9 -0
  131. data/vendor/NTRUplus/NTRU+1152/symmetric.c +39 -0
  132. data/vendor/NTRUplus/NTRU+1152/symmetric.h +12 -0
  133. data/vendor/NTRUplus/NTRU+768/api.h +24 -0
  134. data/vendor/NTRUplus/NTRU+768/fips202/fips202.c +878 -0
  135. data/vendor/NTRUplus/NTRU+768/fips202/fips202.h +166 -0
  136. data/vendor/NTRUplus/NTRU+768/kem.c +286 -0
  137. data/vendor/NTRUplus/NTRU+768/ntt.c +379 -0
  138. data/vendor/NTRUplus/NTRU+768/ntt.h +16 -0
  139. data/vendor/NTRUplus/NTRU+768/params.h +18 -0
  140. data/vendor/NTRUplus/NTRU+768/poly.c +320 -0
  141. data/vendor/NTRUplus/NTRU+768/poly.h +31 -0
  142. data/vendor/NTRUplus/NTRU+768/randombytes.h +9 -0
  143. data/vendor/NTRUplus/NTRU+768/symmetric.c +39 -0
  144. data/vendor/NTRUplus/NTRU+768/symmetric.h +12 -0
  145. data/vendor/NTRUplus/NTRU+864/api.h +24 -0
  146. data/vendor/NTRUplus/NTRU+864/fips202/fips202.c +878 -0
  147. data/vendor/NTRUplus/NTRU+864/fips202/fips202.h +166 -0
  148. data/vendor/NTRUplus/NTRU+864/kem.c +286 -0
  149. data/vendor/NTRUplus/NTRU+864/ntt.c +383 -0
  150. data/vendor/NTRUplus/NTRU+864/ntt.h +16 -0
  151. data/vendor/NTRUplus/NTRU+864/params.h +18 -0
  152. data/vendor/NTRUplus/NTRU+864/poly.c +314 -0
  153. data/vendor/NTRUplus/NTRU+864/poly.h +31 -0
  154. data/vendor/NTRUplus/NTRU+864/randombytes.h +9 -0
  155. data/vendor/NTRUplus/NTRU+864/symmetric.c +39 -0
  156. data/vendor/NTRUplus/NTRU+864/symmetric.h +12 -0
  157. data/vendor/SMAUG-T/LICENSE +22 -0
  158. data/vendor/SMAUG-T/include/api.h +37 -0
  159. data/vendor/SMAUG-T/include/cbd.h +15 -0
  160. data/vendor/SMAUG-T/include/ciphertext.h +45 -0
  161. data/vendor/SMAUG-T/include/common.h +12 -0
  162. data/vendor/SMAUG-T/include/config.h +48 -0
  163. data/vendor/SMAUG-T/include/dg.h +28 -0
  164. data/vendor/SMAUG-T/include/fips202.h +41 -0
  165. data/vendor/SMAUG-T/include/hash.h +21 -0
  166. data/vendor/SMAUG-T/include/hwt.h +28 -0
  167. data/vendor/SMAUG-T/include/indcpa.h +33 -0
  168. data/vendor/SMAUG-T/include/key.h +34 -0
  169. data/vendor/SMAUG-T/include/pack.h +78 -0
  170. data/vendor/SMAUG-T/include/packring.h +50 -0
  171. data/vendor/SMAUG-T/include/params.h +84 -0
  172. data/vendor/SMAUG-T/include/poly.h +41 -0
  173. data/vendor/SMAUG-T/include/randombytes.h +11 -0
  174. data/vendor/SMAUG-T/include/toomcook.h +14 -0
  175. data/vendor/SMAUG-T/include/verify.h +16 -0
  176. data/vendor/SMAUG-T/src/cbd.c +159 -0
  177. data/vendor/SMAUG-T/src/ciphertext.c +95 -0
  178. data/vendor/SMAUG-T/src/dg.c +112 -0
  179. data/vendor/SMAUG-T/src/fips202.c +745 -0
  180. data/vendor/SMAUG-T/src/hash.c +15 -0
  181. data/vendor/SMAUG-T/src/hwt.c +121 -0
  182. data/vendor/SMAUG-T/src/indcpa.c +187 -0
  183. data/vendor/SMAUG-T/src/kem.c +194 -0
  184. data/vendor/SMAUG-T/src/key.c +102 -0
  185. data/vendor/SMAUG-T/src/pack.c +349 -0
  186. data/vendor/SMAUG-T/src/packring.c +503 -0
  187. data/vendor/SMAUG-T/src/poly.c +200 -0
  188. data/vendor/SMAUG-T/src/toomcook.c +256 -0
  189. data/vendor/SMAUG-T/src/verify.c +48 -0
  190. data/vendor/SOURCES.json +130 -0
  191. metadata +280 -0
@@ -0,0 +1,631 @@
1
+ /* kpqc-py: propagate OS entropy failures (2026-09-06). */
2
+ // SPDX-License-Identifier: MIT
3
+
4
+ #include "api.h"
5
+ #include "aim2.h"
6
+ #include "field.h"
7
+ #include "hash.h"
8
+ #include "params.h"
9
+ #include "sign.h"
10
+ #include "tree.h"
11
+ #include "common/crypto_declassify.h"
12
+ #include "common/rng.h"
13
+ #include <stddef.h>
14
+ #include <stdint.h>
15
+ #include <stdlib.h>
16
+ #include <string.h>
17
+
18
+ static void commit_and_expand_tape(tape_t *tape, uint8_t *commit,
19
+ const uint8_t *salt,
20
+ size_t rep, size_t party,
21
+ const uint8_t *seed)
22
+ {
23
+ hash_instance ctx;
24
+
25
+ hash_init_prefix(&ctx, HASH_PREFIX_5);
26
+ hash_update(&ctx, salt, AIMER_SALT_SIZE);
27
+ hash_update(&ctx, (const uint8_t*)&rep, sizeof(uint8_t));
28
+ hash_update(&ctx, (const uint8_t*)&party, sizeof(uint8_t));
29
+ hash_update(&ctx, seed, AIMER_SEED_SIZE);
30
+ hash_final(&ctx);
31
+
32
+ hash_squeeze(&ctx, commit, AIMER_COMMIT_SIZE);
33
+ hash_squeeze(&ctx, (uint8_t *)tape, sizeof(tape_t));
34
+ hash_ctx_release(&ctx);
35
+ }
36
+
37
+ // committing to the seeds and the execution views of the parties
38
+ static int run_phase_1(signature_t *sign,
39
+ uint8_t commits[AIMER_T][AIMER_N][AIMER_COMMIT_SIZE],
40
+ uint8_t nodes[AIMER_T][2 * AIMER_N - 1][AIMER_SEED_SIZE],
41
+ mult_chk_t mult_chk[AIMER_T][AIMER_N],
42
+ gf alpha_v_shares[AIMER_T][2][AIMER_N],
43
+ const uint8_t *sk, const uint8_t *rnd,
44
+ const uint8_t *m, size_t mlen,
45
+ const uint8_t *pre, size_t prelen)
46
+ {
47
+ gf pt_gf = {0,}, ct_gf = {0,};
48
+ gf_from_bytes(pt_gf, sk);
49
+ gf_from_bytes(ct_gf, sk + AIM2_NUM_BYTES_FIELD + AIM2_IV_SIZE);
50
+
51
+ // message pre-hashing
52
+ hash_instance ctx;
53
+ hash_init_prefix(&ctx, HASH_PREFIX_0);
54
+ hash_update(&ctx, sk + AIM2_NUM_BYTES_FIELD,
55
+ AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD);
56
+ hash_update(&ctx, pre, prelen);
57
+ hash_update(&ctx, m, mlen);
58
+ hash_final(&ctx);
59
+
60
+ uint8_t mu[AIMER_COMMIT_SIZE];
61
+ hash_squeeze(&ctx, mu, AIMER_COMMIT_SIZE);
62
+ hash_ctx_release(&ctx);
63
+
64
+ // compute first L sboxes' outputs
65
+ gf sbox_outputs[AIMER_L];
66
+ aim2_sbox_outputs(sbox_outputs, pt_gf);
67
+
68
+ // derive the binary matrix and the vector from the initial vector
69
+ gf(*matrix_A)[AIM2_NUM_BITS_FIELD] = malloc(sizeof(*matrix_A) * AIMER_L);
70
+ if (matrix_A == NULL)
71
+ {
72
+ return -2;
73
+ }
74
+ gf vector_b = {0,};
75
+ aim2_generate_linear(matrix_A, vector_b, sk + AIM2_NUM_BYTES_FIELD);
76
+
77
+ // generate salt
78
+ hash_init_prefix(&ctx, HASH_PREFIX_3);
79
+ hash_update(&ctx, sk, AIM2_NUM_BYTES_FIELD);
80
+ hash_update(&ctx, mu, AIMER_COMMIT_SIZE);
81
+ hash_update(&ctx, rnd, SECURITY_BYTES);
82
+ hash_final(&ctx);
83
+ hash_squeeze(&ctx, sign->salt, AIMER_SALT_SIZE);
84
+
85
+ // generate root seeds
86
+ uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE];
87
+ hash_squeeze(&ctx, root_seeds[0], sizeof(root_seeds));
88
+ hash_ctx_release(&ctx);
89
+
90
+ // hash_instance for h_1
91
+ hash_init_prefix(&ctx, HASH_PREFIX_1);
92
+ hash_update(&ctx, mu, AIMER_COMMIT_SIZE);
93
+ hash_update(&ctx, sign->salt, AIMER_SALT_SIZE);
94
+
95
+ for (size_t rep = 0; rep < AIMER_T; rep++)
96
+ {
97
+ // compute parties' seeds using binary tree
98
+ expand_tree(nodes[rep], sign->salt, rep, root_seeds[rep]);
99
+
100
+ // initialize adjustment values
101
+ tape_t delta, tape;
102
+ memset(&delta, 0, sizeof(tape_t));
103
+
104
+ for (size_t party = 0; party < AIMER_N; party++)
105
+ {
106
+ // generate execution views and commitments
107
+ commit_and_expand_tape(&tape, commits[rep][party], sign->salt, rep, party,
108
+ nodes[rep][party + AIMER_N - 1]);
109
+
110
+ // compute offsets
111
+ gf_add(delta.pt_share, delta.pt_share, tape.pt_share);
112
+ for (size_t i = 0; i < AIMER_L; i++)
113
+ {
114
+ gf_add(delta.t_shares[i], delta.t_shares[i], tape.t_shares[i]);
115
+ }
116
+ gf_add(delta.a_share, delta.a_share, tape.a_share);
117
+ gf_add(delta.c_share, delta.c_share, tape.c_share);
118
+ gf_set0(mult_chk[rep][party].x_shares[AIMER_L]);
119
+
120
+ // adjust the last share and prepare the proof and h_1
121
+ if (party == AIMER_N - 1)
122
+ {
123
+ gf_add(delta.pt_share, delta.pt_share, pt_gf);
124
+ gf_to_bytes(sign->proofs[rep].delta_pt_bytes, delta.pt_share);
125
+ gf_add(tape.pt_share, delta.pt_share, tape.pt_share);
126
+
127
+ for (size_t i = 0; i < AIMER_L; i++)
128
+ {
129
+ gf_add(delta.t_shares[i], delta.t_shares[i], sbox_outputs[i]);
130
+ gf_to_bytes(sign->proofs[rep].delta_ts_bytes[i], delta.t_shares[i]);
131
+ gf_add(tape.t_shares[i], delta.t_shares[i], tape.t_shares[i]);
132
+ }
133
+
134
+ gf_mul_add(delta.c_share, pt_gf, delta.a_share);
135
+ gf_to_bytes(sign->proofs[rep].delta_c_bytes, delta.c_share);
136
+ gf_add(tape.c_share, delta.c_share, tape.c_share);
137
+
138
+ gf_copy(mult_chk[rep][party].x_shares[AIMER_L], vector_b);
139
+ }
140
+
141
+ // run the MPC simulation and prepare the mult check inputs
142
+ gf_copy(mult_chk[rep][party].pt_share, tape.pt_share);
143
+ for (size_t i = 0; i < AIMER_L; i++)
144
+ {
145
+ gf_copy(mult_chk[rep][party].x_shares[i], tape.t_shares[i]);
146
+ }
147
+ gf_copy(alpha_v_shares[rep][0][party], tape.a_share);
148
+ gf_copy(alpha_v_shares[rep][1][party], tape.c_share);
149
+
150
+ crypto_declassify(ct_gf, sizeof(ct_gf));
151
+ aim2_mpc(&mult_chk[rep][party],
152
+ (const gf(*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_gf);
153
+ }
154
+ hash_update(&ctx, (const uint8_t*)commits[rep], AIMER_COMMIT_SIZE * AIMER_N);
155
+
156
+ // NOTE: depend on the order of values in proof_t
157
+ hash_update(&ctx, sign->proofs[rep].delta_pt_bytes,
158
+ AIM2_NUM_BYTES_FIELD * (AIMER_L + 2));
159
+ }
160
+
161
+ // commit to salt, (all commitments of parties' seeds,
162
+ // delta_pt, delta_t, delta_c) for all repetitions
163
+ hash_final(&ctx);
164
+ hash_squeeze(&ctx, sign->h_1, AIMER_COMMIT_SIZE);
165
+ hash_ctx_release(&ctx);
166
+
167
+ free(matrix_A);
168
+ return 0;
169
+ }
170
+
171
+ static void run_phase_2_and_3(signature_t *sign,
172
+ gf alpha_v_shares[AIMER_T][2][AIMER_N],
173
+ const mult_chk_t mult_chk[AIMER_T][AIMER_N])
174
+ {
175
+ gf epsilons[AIMER_L + 1];
176
+
177
+ hash_instance ctx_e;
178
+ hash_init(&ctx_e);
179
+ hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE);
180
+ hash_final(&ctx_e);
181
+
182
+ hash_instance ctx;
183
+ hash_init_prefix(&ctx, HASH_PREFIX_2);
184
+ hash_update(&ctx, sign->h_1, AIMER_COMMIT_SIZE);
185
+ hash_update(&ctx, sign->salt, AIMER_SALT_SIZE);
186
+
187
+ gf alpha = {0,};
188
+ for (size_t rep = 0; rep < AIMER_T; rep++)
189
+ {
190
+ gf_set0(alpha);
191
+ hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons));
192
+
193
+ crypto_declassify(epsilons, sizeof(epsilons));
194
+ for (size_t party = 0; party < AIMER_N; party++)
195
+ {
196
+ // alpha_share = a_share + sum x_share[i] * eps[i]
197
+ // v_share = c_share - pt_share * alpha + sum z_share[i] * eps[i]
198
+ for (size_t ell = 0; ell < AIMER_L + 1; ell++)
199
+ {
200
+ gf_mul_add(alpha_v_shares[rep][0][party],
201
+ mult_chk[rep][party].x_shares[ell], epsilons[ell]);
202
+ gf_mul_add(alpha_v_shares[rep][1][party],
203
+ mult_chk[rep][party].z_shares[ell], epsilons[ell]);
204
+ }
205
+ gf_add(alpha, alpha, alpha_v_shares[rep][0][party]);
206
+ }
207
+
208
+ // alpha is opened, so we can finish calculating v_share
209
+ crypto_declassify(alpha, sizeof(alpha));
210
+ for (size_t party = 0; party < AIMER_N; party++)
211
+ {
212
+ gf_mul_add(alpha_v_shares[rep][1][party],
213
+ mult_chk[rep][party].pt_share, alpha);
214
+ }
215
+ hash_update(&ctx, (const uint8_t *)alpha_v_shares[rep],
216
+ AIM2_NUM_BYTES_FIELD * 2 * AIMER_N);
217
+ }
218
+ hash_final(&ctx);
219
+ hash_squeeze(&ctx, sign->h_2, AIMER_COMMIT_SIZE);
220
+ hash_ctx_release(&ctx);
221
+ hash_ctx_release(&ctx_e);
222
+ }
223
+
224
+ ////////////////////////////////////////////////////////////////////////////////
225
+ void crypto_sign_keypair_internal(uint8_t *pk, uint8_t *sk,
226
+ const uint8_t *pt, const uint8_t *iv)
227
+ {
228
+ aim2(pk + AIM2_IV_SIZE, pt, iv);
229
+
230
+ memcpy(pk, iv, AIM2_IV_SIZE);
231
+ memcpy(sk, pt, AIM2_NUM_BYTES_FIELD);
232
+ memcpy(sk + AIM2_NUM_BYTES_FIELD, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD);
233
+ }
234
+
235
+ int crypto_sign_keypair(uint8_t *pk, uint8_t *sk)
236
+ {
237
+ if (!pk || !sk)
238
+ {
239
+ return -1;
240
+ }
241
+
242
+ uint8_t pt[AIM2_NUM_BYTES_FIELD];
243
+ uint8_t iv[AIM2_IV_SIZE];
244
+
245
+ if (randombytes(pt, AIM2_NUM_BYTES_FIELD) != 0) return -1;
246
+ if (randombytes(iv, AIM2_IV_SIZE) != 0) return -1;
247
+ crypto_sign_keypair_internal(pk, sk, pt, iv);
248
+
249
+ return 0;
250
+ }
251
+
252
+ int crypto_sign_signature_internal(uint8_t *sig, size_t *siglen,
253
+ const uint8_t *m, size_t mlen,
254
+ const uint8_t *pre, size_t prelen,
255
+ const uint8_t *rnd, const uint8_t *sk)
256
+ {
257
+ signature_t *sign = (signature_t *)sig;
258
+
259
+ //////////////////////////////////////////////////////////////////////////
260
+ // Phase 1: Committing to the seeds and the execution views of parties. //
261
+ //////////////////////////////////////////////////////////////////////////
262
+
263
+ // nodes for seed trees
264
+ uint8_t (*nodes)[2 * AIMER_N - 1][AIMER_SEED_SIZE] =
265
+ malloc(sizeof(*nodes) * AIMER_T);
266
+
267
+ // commitments for seeds
268
+ uint8_t (*commits)[AIMER_N][AIMER_COMMIT_SIZE] =
269
+ malloc(sizeof(*commits) * AIMER_T);
270
+
271
+ // multiplication check inputs
272
+ mult_chk_t (*mult_chk)[AIMER_N] = calloc(AIMER_T, sizeof(*mult_chk));
273
+
274
+ // multiplication check outputs
275
+ gf(*alpha_v_shares)[2][AIMER_N] = calloc(AIMER_T, sizeof(*alpha_v_shares));
276
+
277
+ if (nodes == NULL || commits == NULL || mult_chk == NULL ||
278
+ alpha_v_shares == NULL)
279
+ {
280
+ free(nodes);
281
+ free(commits);
282
+ free(mult_chk);
283
+ free(alpha_v_shares);
284
+ return -2;
285
+ }
286
+
287
+ // commitments for phase 1
288
+ if (run_phase_1(sign, commits, nodes, mult_chk, alpha_v_shares, sk, rnd,
289
+ m, mlen, pre, prelen) != 0)
290
+ {
291
+ free(nodes);
292
+ free(commits);
293
+ free(mult_chk);
294
+ free(alpha_v_shares);
295
+ return -2;
296
+ }
297
+
298
+ /////////////////////////////////////////////////////////////////
299
+ // Phase 2, 3: Challenging and committing to the simulation of //
300
+ // the multiplication checking protocol. //
301
+ /////////////////////////////////////////////////////////////////
302
+
303
+ // compute the commitment of phase 3
304
+ run_phase_2_and_3(sign, alpha_v_shares,
305
+ (const mult_chk_t (*)[AIMER_N])mult_chk);
306
+
307
+ //////////////////////////////////////////////////////
308
+ // Phase 4: Challenging views of the MPC protocols. //
309
+ //////////////////////////////////////////////////////
310
+
311
+ hash_instance ctx;
312
+ hash_init(&ctx);
313
+ hash_update(&ctx, sign->h_2, AIMER_COMMIT_SIZE);
314
+ hash_final(&ctx);
315
+
316
+ uint8_t indices[AIMER_T]; // AIMER_N <= 256
317
+ hash_squeeze(&ctx, indices, AIMER_T);
318
+ hash_ctx_release(&ctx);
319
+ for (size_t rep = 0; rep < AIMER_T; rep++)
320
+ {
321
+ indices[rep] &= (1 << AIMER_LOGN) - 1;
322
+ }
323
+
324
+ //////////////////////////////////////////////////////
325
+ // Phase 5: Opening the views of the MPC protocols. //
326
+ //////////////////////////////////////////////////////
327
+
328
+ crypto_declassify(indices, sizeof(indices));
329
+ for (size_t rep = 0; rep < AIMER_T; rep++)
330
+ {
331
+ size_t i_bar = indices[rep];
332
+ reveal_all_but(sign->proofs[rep].reveal_path,
333
+ (const uint8_t (*)[AIMER_SEED_SIZE])nodes[rep], i_bar);
334
+ memcpy(sign->proofs[rep].missing_commitment, commits[rep][i_bar],
335
+ AIMER_COMMIT_SIZE);
336
+ gf_to_bytes(sign->proofs[rep].missing_alpha_share_bytes,
337
+ alpha_v_shares[rep][0][i_bar]);
338
+ }
339
+ *siglen = CRYPTO_BYTES;
340
+
341
+ free(nodes);
342
+ free(commits);
343
+ free(mult_chk);
344
+ free(alpha_v_shares);
345
+ return 0;
346
+ }
347
+
348
+ int crypto_sign_signature(uint8_t *sig, size_t *siglen,
349
+ const uint8_t *m, size_t mlen,
350
+ const uint8_t *ctx, size_t ctxlen, const uint8_t *sk)
351
+ {
352
+ if (ctxlen > 255)
353
+ {
354
+ return -1;
355
+ }
356
+
357
+ uint8_t prefix[256];
358
+ uint8_t randomness[SECURITY_BYTES];
359
+
360
+ prefix[0] = ctxlen;
361
+ for (size_t i = 0; i < ctxlen; i++)
362
+ {
363
+ prefix[1 + i] = ctx[i];
364
+ }
365
+
366
+ #ifdef RANDOMIZED_SIGNING
367
+ if (randombytes(randomness, SECURITY_BYTES) != 0) return -1;
368
+ #else
369
+ for (size_t i = 0; i < SECURITY_BYTES; i++)
370
+ {
371
+ randomness[i] = 0;
372
+ }
373
+ #endif
374
+
375
+ return crypto_sign_signature_internal(sig, siglen, m, mlen, prefix,
376
+ 1 + ctxlen, randomness, sk);
377
+ }
378
+
379
+ int crypto_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen,
380
+ const uint8_t *ctx, size_t ctxlen, const uint8_t *sk)
381
+ {
382
+ int ret;
383
+ ret = crypto_sign_signature(sm + mlen, smlen, m, mlen, ctx, ctxlen, sk);
384
+
385
+ if (ret != 0)
386
+ {
387
+ *smlen = 0;
388
+ return ret;
389
+ }
390
+
391
+ memcpy(sm, m, mlen);
392
+ *smlen += mlen;
393
+
394
+ return ret;
395
+ }
396
+
397
+ int crypto_sign_verify_internal(const uint8_t *sig, size_t siglen,
398
+ const uint8_t *m, size_t mlen,
399
+ const uint8_t *pre, size_t prelen,
400
+ const uint8_t *pk)
401
+ {
402
+ if (siglen != CRYPTO_BYTES)
403
+ {
404
+ return -1;
405
+ }
406
+
407
+ const signature_t *sign = (const signature_t *)sig;
408
+
409
+ gf ct_gf = {0,};
410
+ gf_from_bytes(ct_gf, pk + AIM2_IV_SIZE);
411
+
412
+ // derive the binary matrix and the vector from the initial vector
413
+ gf(*matrix_A)[AIM2_NUM_BITS_FIELD] = malloc(sizeof(*matrix_A) * AIMER_L);
414
+ uint8_t (*nodes)[AIMER_SEED_SIZE] =
415
+ malloc(sizeof(*nodes) * (2 * AIMER_N - 2));
416
+ gf *pt_shares = malloc(AIMER_N * sizeof(gf));
417
+ gf *alpha_shares = malloc(AIMER_N * sizeof(gf));
418
+ gf *v_shares = malloc(AIMER_N * sizeof(gf));
419
+ if (matrix_A == NULL || nodes == NULL || pt_shares == NULL ||
420
+ alpha_shares == NULL || v_shares == NULL)
421
+ {
422
+ free(matrix_A);
423
+ free(nodes);
424
+ free(pt_shares);
425
+ free(alpha_shares);
426
+ free(v_shares);
427
+ return -2;
428
+ }
429
+ gf vector_b = {0,};
430
+ aim2_generate_linear(matrix_A, vector_b, pk);
431
+
432
+ hash_instance ctx_e, ctx_h1, ctx_h2;
433
+
434
+ // indices = Expand(h_2)
435
+ hash_init(&ctx_e);
436
+ hash_update(&ctx_e, sign->h_2, AIMER_COMMIT_SIZE);
437
+ hash_final(&ctx_e);
438
+
439
+ uint8_t indices[AIMER_T]; // AIMER_N <= 256
440
+ hash_squeeze(&ctx_e, indices, AIMER_T);
441
+ hash_ctx_release(&ctx_e);
442
+ for (size_t rep = 0; rep < AIMER_T; rep++)
443
+ {
444
+ indices[rep] &= (1 << AIMER_LOGN) - 1;
445
+ }
446
+
447
+ // epsilons = Expand(h_1)
448
+ hash_init(&ctx_e);
449
+ hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE);
450
+ hash_final(&ctx_e);
451
+
452
+ // message pre-hashing
453
+ uint8_t mu[AIMER_COMMIT_SIZE];
454
+ hash_init_prefix(&ctx_h1, HASH_PREFIX_0);
455
+ hash_update(&ctx_h1, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD);
456
+ hash_update(&ctx_h1, pre, prelen);
457
+ hash_update(&ctx_h1, m, mlen);
458
+ hash_final(&ctx_h1);
459
+ hash_squeeze(&ctx_h1, mu, AIMER_COMMIT_SIZE);
460
+ hash_ctx_release(&ctx_h1);
461
+
462
+ // ready for computing h_1' and h_2'
463
+ hash_init_prefix(&ctx_h1, HASH_PREFIX_1);
464
+ hash_update(&ctx_h1, mu, AIMER_COMMIT_SIZE);
465
+ hash_update(&ctx_h1, sign->salt, AIMER_SALT_SIZE);
466
+
467
+ hash_init_prefix(&ctx_h2, HASH_PREFIX_2);
468
+ hash_update(&ctx_h2, sign->h_1, AIMER_COMMIT_SIZE);
469
+ hash_update(&ctx_h2, sign->salt, AIMER_SALT_SIZE);
470
+
471
+ for (size_t rep = 0; rep < AIMER_T; rep++)
472
+ {
473
+ size_t i_bar = indices[rep];
474
+ reconstruct_tree(nodes, sign->salt, sign->proofs[rep].reveal_path,
475
+ rep, i_bar);
476
+
477
+ gf epsilons[AIMER_L + 1];
478
+ hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons));
479
+
480
+ gf alpha = {0,};
481
+ for (size_t party = 0; party < AIMER_N; party++)
482
+ {
483
+ if (party == i_bar)
484
+ {
485
+ hash_update(&ctx_h1, sign->proofs[rep].missing_commitment,
486
+ AIMER_COMMIT_SIZE);
487
+ gf_from_bytes(alpha_shares[i_bar],
488
+ sign->proofs[rep].missing_alpha_share_bytes);
489
+ gf_add(alpha, alpha, alpha_shares[i_bar]);
490
+ continue;
491
+ }
492
+
493
+ tape_t tape;
494
+ uint8_t commit[AIMER_COMMIT_SIZE];
495
+ commit_and_expand_tape(&tape, commit, sign->salt, rep, party,
496
+ nodes[AIMER_N + party - 2]);
497
+ hash_update(&ctx_h1, commit, AIMER_COMMIT_SIZE);
498
+
499
+ // adjust last shares
500
+ mult_chk_t mult_chk;
501
+ memset(&mult_chk, 0, sizeof(mult_chk_t));
502
+ if (party == AIMER_N - 1)
503
+ {
504
+ gf temp = {0,};
505
+
506
+ gf_from_bytes(temp, sign->proofs[rep].delta_pt_bytes);
507
+ gf_add(tape.pt_share, tape.pt_share, temp);
508
+
509
+ for (size_t ell = 0; ell < AIMER_L; ell++)
510
+ {
511
+ gf_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[ell]);
512
+ gf_add(tape.t_shares[ell], tape.t_shares[ell], temp);
513
+ }
514
+
515
+ gf_from_bytes(temp, sign->proofs[rep].delta_c_bytes);
516
+ gf_add(tape.c_share, tape.c_share, temp);
517
+
518
+ gf_copy(mult_chk.x_shares[AIMER_L], vector_b);
519
+ }
520
+
521
+ // run the MPC simulation and prepare the mult check inputs
522
+ for (size_t ell = 0; ell < AIMER_L; ell++)
523
+ {
524
+ gf_copy(mult_chk.x_shares[ell], tape.t_shares[ell]);
525
+ }
526
+ gf_copy(pt_shares[party], tape.pt_share);
527
+ gf_copy(alpha_shares[party], tape.a_share);
528
+ gf_copy(v_shares[party], tape.c_share);
529
+ aim2_mpc(&mult_chk, (const gf(*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_gf);
530
+
531
+ for (size_t ell = 0; ell < AIMER_L + 1; ell++)
532
+ {
533
+ gf_mul_add(alpha_shares[party], mult_chk.x_shares[ell], epsilons[ell]);
534
+ gf_mul_add(v_shares[party], mult_chk.z_shares[ell], epsilons[ell]);
535
+ }
536
+ gf_add(alpha, alpha, alpha_shares[party]);
537
+ }
538
+
539
+ // alpha is opened, so we can finish calculating v_share
540
+ gf_set0(v_shares[i_bar]);
541
+ for (size_t party = 0; party < AIMER_N; party++)
542
+ {
543
+ if (party == i_bar)
544
+ {
545
+ continue;
546
+ }
547
+
548
+ gf_mul_add(v_shares[party], pt_shares[party], alpha);
549
+ gf_add(v_shares[i_bar], v_shares[i_bar], v_shares[party]);
550
+ }
551
+
552
+ // v is opened
553
+ hash_update(&ctx_h2, (const uint8_t *)alpha_shares, AIMER_N * sizeof(gf));
554
+ hash_update(&ctx_h2, (const uint8_t *)v_shares, AIMER_N * sizeof(gf));
555
+
556
+ // NOTE: depend on the order of values in proof_t
557
+ hash_update(&ctx_h1, sign->proofs[rep].delta_pt_bytes,
558
+ AIM2_NUM_BYTES_FIELD * (AIMER_L + 2));
559
+ }
560
+ hash_ctx_release(&ctx_e);
561
+
562
+ uint8_t h_1_prime[AIMER_COMMIT_SIZE];
563
+ hash_final(&ctx_h1);
564
+ hash_squeeze(&ctx_h1, h_1_prime, AIMER_COMMIT_SIZE);
565
+ hash_ctx_release(&ctx_h1);
566
+
567
+ uint8_t h_2_prime[AIMER_COMMIT_SIZE];
568
+ hash_final(&ctx_h2);
569
+ hash_squeeze(&ctx_h2, h_2_prime, AIMER_COMMIT_SIZE);
570
+ hash_ctx_release(&ctx_h2);
571
+
572
+ free(matrix_A);
573
+ free(nodes);
574
+ free(pt_shares);
575
+ free(alpha_shares);
576
+ free(v_shares);
577
+
578
+ if (memcmp(h_1_prime, sign->h_1, AIMER_COMMIT_SIZE) != 0 ||
579
+ memcmp(h_2_prime, sign->h_2, AIMER_COMMIT_SIZE) != 0)
580
+ {
581
+ return -1;
582
+ }
583
+
584
+ return 0;
585
+ }
586
+
587
+ int crypto_sign_verify(const uint8_t *sig, size_t siglen,
588
+ const uint8_t *m, size_t mlen,
589
+ const uint8_t *ctx, size_t ctxlen, const uint8_t *pk)
590
+ {
591
+ if (ctxlen > 255)
592
+ {
593
+ return -1;
594
+ }
595
+
596
+ uint8_t prefix[256];
597
+
598
+ prefix[0] = ctxlen;
599
+ for (size_t i = 0; i < ctxlen; i++)
600
+ {
601
+ prefix[1 + i] = ctx[i];
602
+ }
603
+
604
+ return crypto_sign_verify_internal(sig, siglen, m, mlen, prefix, 1 + ctxlen,
605
+ pk);
606
+ }
607
+
608
+ int crypto_sign_open(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen,
609
+ const uint8_t *ctx, size_t ctxlen, const uint8_t *pk)
610
+ {
611
+ if (smlen < CRYPTO_BYTES)
612
+ {
613
+ return -1;
614
+ }
615
+
616
+ const size_t message_len = smlen - CRYPTO_BYTES;
617
+ const uint8_t *message = sm;
618
+ const uint8_t *signature = sm + message_len;
619
+
620
+ int ret = crypto_sign_verify(signature, CRYPTO_BYTES, message, message_len,
621
+ ctx, ctxlen, pk);
622
+ if (ret != 0)
623
+ {
624
+ return ret;
625
+ }
626
+
627
+ memmove(m, message, message_len);
628
+ *mlen = message_len;
629
+
630
+ return 0;
631
+ }
@@ -0,0 +1,40 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ #ifndef SIGN_H
4
+ #define SIGN_H
5
+
6
+ #include "field.h"
7
+ #include "hash.h"
8
+ #include "params.h"
9
+ #include <stddef.h>
10
+ #include <stdint.h>
11
+
12
+ #define RANDOMIZED_SIGNING
13
+
14
+ typedef struct tape_t
15
+ {
16
+ gf pt_share;
17
+ gf t_shares[AIMER_L];
18
+ gf a_share;
19
+ gf c_share;
20
+ } tape_t;
21
+
22
+ typedef struct proof_t
23
+ {
24
+ uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE];
25
+ uint8_t missing_commitment[AIMER_COMMIT_SIZE];
26
+ uint8_t delta_pt_bytes[AIM2_NUM_BYTES_FIELD];
27
+ uint8_t delta_ts_bytes[AIMER_L][AIM2_NUM_BYTES_FIELD];
28
+ uint8_t delta_c_bytes[AIM2_NUM_BYTES_FIELD];
29
+ uint8_t missing_alpha_share_bytes[AIM2_NUM_BYTES_FIELD];
30
+ } proof_t;
31
+
32
+ typedef struct signature_t
33
+ {
34
+ uint8_t salt[AIMER_SALT_SIZE];
35
+ uint8_t h_1[AIMER_COMMIT_SIZE];
36
+ uint8_t h_2[AIMER_COMMIT_SIZE];
37
+ proof_t proofs[AIMER_T];
38
+ } signature_t;
39
+
40
+ #endif // SIGN_H