pq_crypto 0.3.1 → 0.4.2

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 (117) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +56 -0
  3. data/CHANGELOG.md +50 -0
  4. data/GET_STARTED.md +374 -30
  5. data/README.md +59 -195
  6. data/SECURITY.md +101 -82
  7. data/ext/pqcrypto/extconf.rb +85 -9
  8. data/ext/pqcrypto/mldsa_api.h +71 -1
  9. data/ext/pqcrypto/mlkem_api.h +24 -0
  10. data/ext/pqcrypto/pq_externalmu.c +310 -0
  11. data/ext/pqcrypto/pqcrypto_ruby_secure.c +784 -85
  12. data/ext/pqcrypto/pqcrypto_secure.c +179 -72
  13. data/ext/pqcrypto/pqcrypto_secure.h +103 -7
  14. data/ext/pqcrypto/pqcrypto_version.h +7 -0
  15. data/ext/pqcrypto/vendor/.vendored +1 -1
  16. data/ext/pqcrypto/vendor/pqclean/common/keccak4x/Makefile +8 -0
  17. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/LICENSE +5 -0
  18. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/Makefile +19 -0
  19. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/Makefile.Microsoft_nmake +23 -0
  20. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/api.h +18 -0
  21. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/cbd.c +83 -0
  22. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/cbd.h +11 -0
  23. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/indcpa.c +327 -0
  24. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/indcpa.h +22 -0
  25. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/kem.c +164 -0
  26. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/kem.h +23 -0
  27. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/ntt.c +146 -0
  28. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/ntt.h +14 -0
  29. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/params.h +36 -0
  30. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/poly.c +311 -0
  31. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/poly.h +37 -0
  32. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/polyvec.c +198 -0
  33. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/polyvec.h +26 -0
  34. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/reduce.c +41 -0
  35. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/reduce.h +13 -0
  36. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/symmetric-shake.c +71 -0
  37. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/symmetric.h +30 -0
  38. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/verify.c +67 -0
  39. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/verify.h +13 -0
  40. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/LICENSE +5 -0
  41. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/Makefile +19 -0
  42. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/Makefile.Microsoft_nmake +23 -0
  43. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/api.h +18 -0
  44. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/cbd.c +108 -0
  45. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/cbd.h +11 -0
  46. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/indcpa.c +327 -0
  47. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/indcpa.h +22 -0
  48. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/kem.c +164 -0
  49. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/kem.h +23 -0
  50. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/ntt.c +146 -0
  51. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/ntt.h +14 -0
  52. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/params.h +36 -0
  53. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/poly.c +299 -0
  54. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/poly.h +37 -0
  55. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/polyvec.c +188 -0
  56. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/polyvec.h +26 -0
  57. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/reduce.c +41 -0
  58. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/reduce.h +13 -0
  59. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/symmetric-shake.c +71 -0
  60. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/symmetric.h +30 -0
  61. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/verify.c +67 -0
  62. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/verify.h +13 -0
  63. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/Makefile +19 -0
  64. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/LICENSE +5 -0
  65. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/Makefile +19 -0
  66. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/Makefile.Microsoft_nmake +23 -0
  67. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/api.h +50 -0
  68. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/ntt.c +98 -0
  69. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/ntt.h +10 -0
  70. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/packing.c +261 -0
  71. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/packing.h +31 -0
  72. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/params.h +44 -0
  73. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/poly.c +848 -0
  74. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/poly.h +52 -0
  75. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/polyvec.c +415 -0
  76. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/polyvec.h +65 -0
  77. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/reduce.c +69 -0
  78. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/reduce.h +17 -0
  79. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/rounding.c +98 -0
  80. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/rounding.h +14 -0
  81. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/sign.c +407 -0
  82. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/sign.h +47 -0
  83. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/symmetric-shake.c +26 -0
  84. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/symmetric.h +34 -0
  85. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/Makefile +19 -0
  86. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/LICENSE +5 -0
  87. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/Makefile +19 -0
  88. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/Makefile.Microsoft_nmake +23 -0
  89. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/api.h +50 -0
  90. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/ntt.c +98 -0
  91. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/ntt.h +10 -0
  92. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/packing.c +261 -0
  93. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/packing.h +31 -0
  94. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/params.h +44 -0
  95. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/poly.c +823 -0
  96. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/poly.h +52 -0
  97. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/polyvec.c +415 -0
  98. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/polyvec.h +65 -0
  99. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/reduce.c +69 -0
  100. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/reduce.h +17 -0
  101. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/rounding.c +92 -0
  102. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/rounding.h +14 -0
  103. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/sign.c +407 -0
  104. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/sign.h +47 -0
  105. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/symmetric-shake.c +26 -0
  106. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/symmetric.h +34 -0
  107. data/lib/pq_crypto/algorithm_registry.rb +200 -0
  108. data/lib/pq_crypto/hybrid_kem.rb +1 -12
  109. data/lib/pq_crypto/kem.rb +104 -13
  110. data/lib/pq_crypto/pkcs8.rb +387 -0
  111. data/lib/pq_crypto/serialization.rb +1 -14
  112. data/lib/pq_crypto/signature.rb +231 -13
  113. data/lib/pq_crypto/spki.rb +131 -0
  114. data/lib/pq_crypto/version.rb +1 -1
  115. data/lib/pq_crypto.rb +90 -19
  116. data/script/vendor_libs.rb +4 -0
  117. metadata +99 -3
@@ -0,0 +1,92 @@
1
+ #include "params.h"
2
+ #include "rounding.h"
3
+ #include <stdint.h>
4
+
5
+ /*************************************************
6
+ * Name: PQCLEAN_MLDSA87_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_MLDSA87_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_MLDSA87_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_MLDSA87_CLEAN_decompose(int32_t *a0, int32_t a) {
40
+ int32_t a1;
41
+
42
+ a1 = (a + 127) >> 7;
43
+ a1 = (a1 * 1025 + (1 << 21)) >> 22;
44
+ a1 &= 15;
45
+
46
+ *a0 = a - a1 * 2 * GAMMA2;
47
+ *a0 -= (((Q - 1) / 2 - *a0) >> 31) & Q;
48
+ return a1;
49
+ }
50
+
51
+ /*************************************************
52
+ * Name: PQCLEAN_MLDSA87_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_MLDSA87_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_MLDSA87_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_MLDSA87_CLEAN_use_hint(int32_t a, unsigned int hint) {
81
+ int32_t a0, a1;
82
+
83
+ a1 = PQCLEAN_MLDSA87_CLEAN_decompose(&a0, a);
84
+ if (hint == 0) {
85
+ return a1;
86
+ }
87
+
88
+ if (a0 > 0) {
89
+ return (a1 + 1) & 15;
90
+ }
91
+ return (a1 - 1) & 15;
92
+ }
@@ -0,0 +1,14 @@
1
+ #ifndef PQCLEAN_MLDSA87_CLEAN_ROUNDING_H
2
+ #define PQCLEAN_MLDSA87_CLEAN_ROUNDING_H
3
+ #include "params.h"
4
+ #include <stdint.h>
5
+
6
+ int32_t PQCLEAN_MLDSA87_CLEAN_power2round(int32_t *a0, int32_t a);
7
+
8
+ int32_t PQCLEAN_MLDSA87_CLEAN_decompose(int32_t *a0, int32_t a);
9
+
10
+ unsigned int PQCLEAN_MLDSA87_CLEAN_make_hint(int32_t a0, int32_t a1);
11
+
12
+ int32_t PQCLEAN_MLDSA87_CLEAN_use_hint(int32_t a, unsigned int hint);
13
+
14
+ #endif
@@ -0,0 +1,407 @@
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
+
11
+ /*************************************************
12
+ * Name: PQCLEAN_MLDSA87_CLEAN_crypto_sign_keypair
13
+ *
14
+ * Description: Generates public and private key.
15
+ *
16
+ * Arguments: - uint8_t *pk: pointer to output public key (allocated
17
+ * array of PQCLEAN_MLDSA87_CLEAN_CRYPTO_PUBLICKEYBYTES bytes)
18
+ * - uint8_t *sk: pointer to output private key (allocated
19
+ * array of PQCLEAN_MLDSA87_CLEAN_CRYPTO_SECRETKEYBYTES bytes)
20
+ *
21
+ * Returns 0 (success)
22
+ **************************************************/
23
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk) {
24
+ uint8_t seedbuf[2 * SEEDBYTES + CRHBYTES];
25
+ uint8_t tr[TRBYTES];
26
+ const uint8_t *rho, *rhoprime, *key;
27
+ polyvecl mat[K];
28
+ polyvecl s1, s1hat;
29
+ polyveck s2, t1, t0;
30
+
31
+ /* Get randomness for rho, rhoprime and key */
32
+ randombytes(seedbuf, SEEDBYTES);
33
+ seedbuf[SEEDBYTES + 0] = K;
34
+ seedbuf[SEEDBYTES + 1] = L;
35
+ shake256(seedbuf, 2 * SEEDBYTES + CRHBYTES, seedbuf, SEEDBYTES + 2);
36
+ rho = seedbuf;
37
+ rhoprime = rho + SEEDBYTES;
38
+ key = rhoprime + CRHBYTES;
39
+
40
+ /* Expand matrix */
41
+ PQCLEAN_MLDSA87_CLEAN_polyvec_matrix_expand(mat, rho);
42
+
43
+ /* Sample short vectors s1 and s2 */
44
+ PQCLEAN_MLDSA87_CLEAN_polyvecl_uniform_eta(&s1, rhoprime, 0);
45
+ PQCLEAN_MLDSA87_CLEAN_polyveck_uniform_eta(&s2, rhoprime, L);
46
+
47
+ /* Matrix-vector multiplication */
48
+ s1hat = s1;
49
+ PQCLEAN_MLDSA87_CLEAN_polyvecl_ntt(&s1hat);
50
+ PQCLEAN_MLDSA87_CLEAN_polyvec_matrix_pointwise_montgomery(&t1, mat, &s1hat);
51
+ PQCLEAN_MLDSA87_CLEAN_polyveck_reduce(&t1);
52
+ PQCLEAN_MLDSA87_CLEAN_polyveck_invntt_tomont(&t1);
53
+
54
+ /* Add error vector s2 */
55
+ PQCLEAN_MLDSA87_CLEAN_polyveck_add(&t1, &t1, &s2);
56
+
57
+ /* Extract t1 and write public key */
58
+ PQCLEAN_MLDSA87_CLEAN_polyveck_caddq(&t1);
59
+ PQCLEAN_MLDSA87_CLEAN_polyveck_power2round(&t1, &t0, &t1);
60
+ PQCLEAN_MLDSA87_CLEAN_pack_pk(pk, rho, &t1);
61
+
62
+ /* Compute H(rho, t1) and write secret key */
63
+ shake256(tr, TRBYTES, pk, PQCLEAN_MLDSA87_CLEAN_CRYPTO_PUBLICKEYBYTES);
64
+ PQCLEAN_MLDSA87_CLEAN_pack_sk(sk, rho, tr, key, &t0, &s1, &s2);
65
+
66
+ return 0;
67
+ }
68
+
69
+ /*************************************************
70
+ * Name: crypto_sign_signature
71
+ *
72
+ * Description: Computes signature.
73
+ *
74
+ * Arguments: - uint8_t *sig: pointer to output signature (of length PQCLEAN_MLDSA87_CLEAN_CRYPTO_BYTES)
75
+ * - size_t *siglen: pointer to output length of signature
76
+ * - uint8_t *m: pointer to message to be signed
77
+ * - size_t mlen: length of message
78
+ * - uint8_t *ctx: pointer to context string
79
+ * - size_t ctxlen: length of context string
80
+ * - uint8_t *sk: pointer to bit-packed secret key
81
+ *
82
+ * Returns 0 (success) or -1 (context string too long)
83
+ **************************************************/
84
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign_signature_ctx(uint8_t *sig,
85
+ size_t *siglen,
86
+ const uint8_t *m,
87
+ size_t mlen,
88
+ const uint8_t *ctx,
89
+ size_t ctxlen,
90
+ const uint8_t *sk) {
91
+ unsigned int n;
92
+ uint8_t seedbuf[2 * SEEDBYTES + TRBYTES + RNDBYTES + 2 * CRHBYTES];
93
+ uint8_t *rho, *tr, *key, *mu, *rhoprime, *rnd;
94
+ uint16_t nonce = 0;
95
+ polyvecl mat[K], s1, y, z;
96
+ polyveck t0, s2, w1, w0, h;
97
+ poly cp;
98
+ shake256incctx state;
99
+
100
+ if (ctxlen > 255) {
101
+ return -1;
102
+ }
103
+
104
+ rho = seedbuf;
105
+ tr = rho + SEEDBYTES;
106
+ key = tr + TRBYTES;
107
+ rnd = key + SEEDBYTES;
108
+ mu = rnd + RNDBYTES;
109
+ rhoprime = mu + CRHBYTES;
110
+ PQCLEAN_MLDSA87_CLEAN_unpack_sk(rho, tr, key, &t0, &s1, &s2, sk);
111
+
112
+ /* Compute mu = CRH(tr, 0, ctxlen, ctx, msg) */
113
+ mu[0] = 0;
114
+ mu[1] = (uint8_t)ctxlen;
115
+ shake256_inc_init(&state);
116
+ shake256_inc_absorb(&state, tr, TRBYTES);
117
+ shake256_inc_absorb(&state, mu, 2);
118
+ shake256_inc_absorb(&state, ctx, ctxlen);
119
+ shake256_inc_absorb(&state, m, mlen);
120
+ shake256_inc_finalize(&state);
121
+ shake256_inc_squeeze(mu, CRHBYTES, &state);
122
+ shake256_inc_ctx_release(&state);
123
+
124
+ randombytes(rnd, RNDBYTES);
125
+ shake256(rhoprime, CRHBYTES, key, SEEDBYTES + RNDBYTES + CRHBYTES);
126
+
127
+ /* Expand matrix and transform vectors */
128
+ PQCLEAN_MLDSA87_CLEAN_polyvec_matrix_expand(mat, rho);
129
+ PQCLEAN_MLDSA87_CLEAN_polyvecl_ntt(&s1);
130
+ PQCLEAN_MLDSA87_CLEAN_polyveck_ntt(&s2);
131
+ PQCLEAN_MLDSA87_CLEAN_polyveck_ntt(&t0);
132
+
133
+ rej:
134
+ /* Sample intermediate vector y */
135
+ PQCLEAN_MLDSA87_CLEAN_polyvecl_uniform_gamma1(&y, rhoprime, nonce++);
136
+
137
+ /* Matrix-vector multiplication */
138
+ z = y;
139
+ PQCLEAN_MLDSA87_CLEAN_polyvecl_ntt(&z);
140
+ PQCLEAN_MLDSA87_CLEAN_polyvec_matrix_pointwise_montgomery(&w1, mat, &z);
141
+ PQCLEAN_MLDSA87_CLEAN_polyveck_reduce(&w1);
142
+ PQCLEAN_MLDSA87_CLEAN_polyveck_invntt_tomont(&w1);
143
+
144
+ /* Decompose w and call the random oracle */
145
+ PQCLEAN_MLDSA87_CLEAN_polyveck_caddq(&w1);
146
+ PQCLEAN_MLDSA87_CLEAN_polyveck_decompose(&w1, &w0, &w1);
147
+ PQCLEAN_MLDSA87_CLEAN_polyveck_pack_w1(sig, &w1);
148
+
149
+ shake256_inc_init(&state);
150
+ shake256_inc_absorb(&state, mu, CRHBYTES);
151
+ shake256_inc_absorb(&state, sig, K * POLYW1_PACKEDBYTES);
152
+ shake256_inc_finalize(&state);
153
+ shake256_inc_squeeze(sig, CTILDEBYTES, &state);
154
+ shake256_inc_ctx_release(&state);
155
+ PQCLEAN_MLDSA87_CLEAN_poly_challenge(&cp, sig);
156
+ PQCLEAN_MLDSA87_CLEAN_poly_ntt(&cp);
157
+
158
+ /* Compute z, reject if it reveals secret */
159
+ PQCLEAN_MLDSA87_CLEAN_polyvecl_pointwise_poly_montgomery(&z, &cp, &s1);
160
+ PQCLEAN_MLDSA87_CLEAN_polyvecl_invntt_tomont(&z);
161
+ PQCLEAN_MLDSA87_CLEAN_polyvecl_add(&z, &z, &y);
162
+ PQCLEAN_MLDSA87_CLEAN_polyvecl_reduce(&z);
163
+ if (PQCLEAN_MLDSA87_CLEAN_polyvecl_chknorm(&z, GAMMA1 - BETA)) {
164
+ goto rej;
165
+ }
166
+
167
+ /* Check that subtracting cs2 does not change high bits of w and low bits
168
+ * do not reveal secret information */
169
+ PQCLEAN_MLDSA87_CLEAN_polyveck_pointwise_poly_montgomery(&h, &cp, &s2);
170
+ PQCLEAN_MLDSA87_CLEAN_polyveck_invntt_tomont(&h);
171
+ PQCLEAN_MLDSA87_CLEAN_polyveck_sub(&w0, &w0, &h);
172
+ PQCLEAN_MLDSA87_CLEAN_polyveck_reduce(&w0);
173
+ if (PQCLEAN_MLDSA87_CLEAN_polyveck_chknorm(&w0, GAMMA2 - BETA)) {
174
+ goto rej;
175
+ }
176
+
177
+ /* Compute hints for w1 */
178
+ PQCLEAN_MLDSA87_CLEAN_polyveck_pointwise_poly_montgomery(&h, &cp, &t0);
179
+ PQCLEAN_MLDSA87_CLEAN_polyveck_invntt_tomont(&h);
180
+ PQCLEAN_MLDSA87_CLEAN_polyveck_reduce(&h);
181
+ if (PQCLEAN_MLDSA87_CLEAN_polyveck_chknorm(&h, GAMMA2)) {
182
+ goto rej;
183
+ }
184
+
185
+ PQCLEAN_MLDSA87_CLEAN_polyveck_add(&w0, &w0, &h);
186
+ n = PQCLEAN_MLDSA87_CLEAN_polyveck_make_hint(&h, &w0, &w1);
187
+ if (n > OMEGA) {
188
+ goto rej;
189
+ }
190
+
191
+ /* Write signature */
192
+ PQCLEAN_MLDSA87_CLEAN_pack_sig(sig, sig, &z, &h);
193
+ *siglen = PQCLEAN_MLDSA87_CLEAN_CRYPTO_BYTES;
194
+ return 0;
195
+ }
196
+
197
+ /*************************************************
198
+ * Name: crypto_sign
199
+ *
200
+ * Description: Compute signed message.
201
+ *
202
+ * Arguments: - uint8_t *sm: pointer to output signed message (allocated
203
+ * array with PQCLEAN_MLDSA87_CLEAN_CRYPTO_BYTES + mlen bytes),
204
+ * can be equal to m
205
+ * - size_t *smlen: pointer to output length of signed
206
+ * message
207
+ * - const uint8_t *m: pointer to message to be signed
208
+ * - size_t mlen: length of message
209
+ * - const uint8_t *ctx: pointer to context string
210
+ * - size_t ctxlen: length of context string
211
+ * - const uint8_t *sk: pointer to bit-packed secret key
212
+ *
213
+ * Returns 0 (success) or -1 (context string too long)
214
+ **************************************************/
215
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign_ctx(uint8_t *sm,
216
+ size_t *smlen,
217
+ const uint8_t *m,
218
+ size_t mlen,
219
+ const uint8_t *ctx,
220
+ size_t ctxlen,
221
+ const uint8_t *sk) {
222
+ int ret;
223
+ size_t i;
224
+
225
+ for (i = 0; i < mlen; ++i) {
226
+ sm[PQCLEAN_MLDSA87_CLEAN_CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i];
227
+ }
228
+ ret = PQCLEAN_MLDSA87_CLEAN_crypto_sign_signature_ctx(sm, smlen, sm + PQCLEAN_MLDSA87_CLEAN_CRYPTO_BYTES, mlen, ctx, ctxlen, sk);
229
+ *smlen += mlen;
230
+ return ret;
231
+ }
232
+
233
+ /*************************************************
234
+ * Name: crypto_sign_verify
235
+ *
236
+ * Description: Verifies signature.
237
+ *
238
+ * Arguments: - uint8_t *m: pointer to input signature
239
+ * - size_t siglen: length of signature
240
+ * - const uint8_t *m: pointer to message
241
+ * - size_t mlen: length of message
242
+ * - const uint8_t *ctx: pointer to context string
243
+ * - size_t ctxlen: length of context string
244
+ * - const uint8_t *pk: pointer to bit-packed public key
245
+ *
246
+ * Returns 0 if signature could be verified correctly and -1 otherwise
247
+ **************************************************/
248
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign_verify_ctx(const uint8_t *sig,
249
+ size_t siglen,
250
+ const uint8_t *m,
251
+ size_t mlen,
252
+ const uint8_t *ctx,
253
+ size_t ctxlen,
254
+ const uint8_t *pk) {
255
+ unsigned int i;
256
+ uint8_t buf[K * POLYW1_PACKEDBYTES];
257
+ uint8_t rho[SEEDBYTES];
258
+ uint8_t mu[CRHBYTES];
259
+ uint8_t c[CTILDEBYTES];
260
+ uint8_t c2[CTILDEBYTES];
261
+ poly cp;
262
+ polyvecl mat[K], z;
263
+ polyveck t1, w1, h;
264
+ shake256incctx state;
265
+
266
+ if (ctxlen > 255 || siglen != PQCLEAN_MLDSA87_CLEAN_CRYPTO_BYTES) {
267
+ return -1;
268
+ }
269
+
270
+ PQCLEAN_MLDSA87_CLEAN_unpack_pk(rho, &t1, pk);
271
+ if (PQCLEAN_MLDSA87_CLEAN_unpack_sig(c, &z, &h, sig)) {
272
+ return -1;
273
+ }
274
+ if (PQCLEAN_MLDSA87_CLEAN_polyvecl_chknorm(&z, GAMMA1 - BETA)) {
275
+ return -1;
276
+ }
277
+
278
+ /* Compute CRH(H(rho, t1), msg) */
279
+ shake256(mu, TRBYTES, pk, PQCLEAN_MLDSA87_CLEAN_CRYPTO_PUBLICKEYBYTES);
280
+ shake256_inc_init(&state);
281
+ shake256_inc_absorb(&state, mu, TRBYTES);
282
+ mu[0] = 0;
283
+ mu[1] = (uint8_t)ctxlen;
284
+ shake256_inc_absorb(&state, mu, 2);
285
+ shake256_inc_absorb(&state, ctx, ctxlen);
286
+ shake256_inc_absorb(&state, m, mlen);
287
+ shake256_inc_finalize(&state);
288
+ shake256_inc_squeeze(mu, CRHBYTES, &state);
289
+ shake256_inc_ctx_release(&state);
290
+
291
+ /* Matrix-vector multiplication; compute Az - c2^dt1 */
292
+ PQCLEAN_MLDSA87_CLEAN_poly_challenge(&cp, c);
293
+ PQCLEAN_MLDSA87_CLEAN_polyvec_matrix_expand(mat, rho);
294
+
295
+ PQCLEAN_MLDSA87_CLEAN_polyvecl_ntt(&z);
296
+ PQCLEAN_MLDSA87_CLEAN_polyvec_matrix_pointwise_montgomery(&w1, mat, &z);
297
+
298
+ PQCLEAN_MLDSA87_CLEAN_poly_ntt(&cp);
299
+ PQCLEAN_MLDSA87_CLEAN_polyveck_shiftl(&t1);
300
+ PQCLEAN_MLDSA87_CLEAN_polyveck_ntt(&t1);
301
+ PQCLEAN_MLDSA87_CLEAN_polyveck_pointwise_poly_montgomery(&t1, &cp, &t1);
302
+
303
+ PQCLEAN_MLDSA87_CLEAN_polyveck_sub(&w1, &w1, &t1);
304
+ PQCLEAN_MLDSA87_CLEAN_polyveck_reduce(&w1);
305
+ PQCLEAN_MLDSA87_CLEAN_polyveck_invntt_tomont(&w1);
306
+
307
+ /* Reconstruct w1 */
308
+ PQCLEAN_MLDSA87_CLEAN_polyveck_caddq(&w1);
309
+ PQCLEAN_MLDSA87_CLEAN_polyveck_use_hint(&w1, &w1, &h);
310
+ PQCLEAN_MLDSA87_CLEAN_polyveck_pack_w1(buf, &w1);
311
+
312
+ /* Call random oracle and verify challenge */
313
+ shake256_inc_init(&state);
314
+ shake256_inc_absorb(&state, mu, CRHBYTES);
315
+ shake256_inc_absorb(&state, buf, K * POLYW1_PACKEDBYTES);
316
+ shake256_inc_finalize(&state);
317
+ shake256_inc_squeeze(c2, CTILDEBYTES, &state);
318
+ shake256_inc_ctx_release(&state);
319
+ for (i = 0; i < CTILDEBYTES; ++i) {
320
+ if (c[i] != c2[i]) {
321
+ return -1;
322
+ }
323
+ }
324
+
325
+ return 0;
326
+ }
327
+
328
+ /*************************************************
329
+ * Name: crypto_sign_open
330
+ *
331
+ * Description: Verify signed message.
332
+ *
333
+ * Arguments: - uint8_t *m: pointer to output message (allocated
334
+ * array with smlen bytes), can be equal to sm
335
+ * - size_t *mlen: pointer to output length of message
336
+ * - const uint8_t *sm: pointer to signed message
337
+ * - size_t smlen: length of signed message
338
+ * - const uint8_t *ctx: pointer to context tring
339
+ * - size_t ctxlen: length of context string
340
+ * - const uint8_t *pk: pointer to bit-packed public key
341
+ *
342
+ * Returns 0 if signed message could be verified correctly and -1 otherwise
343
+ **************************************************/
344
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign_open_ctx(uint8_t *m,
345
+ size_t *mlen,
346
+ const uint8_t *sm,
347
+ size_t smlen,
348
+ const uint8_t *ctx,
349
+ size_t ctxlen,
350
+ const uint8_t *pk) {
351
+ size_t i;
352
+
353
+ if (smlen < PQCLEAN_MLDSA87_CLEAN_CRYPTO_BYTES) {
354
+ goto badsig;
355
+ }
356
+
357
+ *mlen = smlen - PQCLEAN_MLDSA87_CLEAN_CRYPTO_BYTES;
358
+ if (PQCLEAN_MLDSA87_CLEAN_crypto_sign_verify_ctx(sm, PQCLEAN_MLDSA87_CLEAN_CRYPTO_BYTES, sm + PQCLEAN_MLDSA87_CLEAN_CRYPTO_BYTES, *mlen, ctx, ctxlen, pk)) {
359
+ goto badsig;
360
+ } else {
361
+ /* All good, copy msg, return 0 */
362
+ for (i = 0; i < *mlen; ++i) {
363
+ m[i] = sm[PQCLEAN_MLDSA87_CLEAN_CRYPTO_BYTES + i];
364
+ }
365
+ return 0;
366
+ }
367
+
368
+ badsig:
369
+ /* Signature verification failed */
370
+ *mlen = 0;
371
+ for (i = 0; i < smlen; ++i) {
372
+ m[i] = 0;
373
+ }
374
+
375
+ return -1;
376
+ }
377
+
378
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign_signature(uint8_t *sig,
379
+ size_t *siglen,
380
+ const uint8_t *m,
381
+ size_t mlen,
382
+ const uint8_t *sk) {
383
+ return PQCLEAN_MLDSA87_CLEAN_crypto_sign_signature_ctx(sig, siglen, m, mlen, NULL, 0, sk);
384
+ }
385
+
386
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign(uint8_t *sm,
387
+ size_t *smlen,
388
+ const uint8_t *m,
389
+ size_t mlen,
390
+ const uint8_t *sk) {
391
+ return PQCLEAN_MLDSA87_CLEAN_crypto_sign_ctx(sm, smlen, m, mlen, NULL, 0, sk);
392
+ }
393
+
394
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign_verify(const uint8_t *sig,
395
+ size_t siglen,
396
+ const uint8_t *m,
397
+ size_t mlen,
398
+ const uint8_t *pk) {
399
+ return PQCLEAN_MLDSA87_CLEAN_crypto_sign_verify_ctx(sig, siglen, m, mlen, NULL, 0, pk);
400
+ }
401
+
402
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign_open(uint8_t *m,
403
+ size_t *mlen,
404
+ const uint8_t *sm, size_t smlen,
405
+ const uint8_t *pk) {
406
+ return PQCLEAN_MLDSA87_CLEAN_crypto_sign_open_ctx(m, mlen, sm, smlen, NULL, 0, pk);
407
+ }
@@ -0,0 +1,47 @@
1
+ #ifndef PQCLEAN_MLDSA87_CLEAN_SIGN_H
2
+ #define PQCLEAN_MLDSA87_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_MLDSA87_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk);
10
+
11
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign_signature_ctx(uint8_t *sig, size_t *siglen,
12
+ const uint8_t *m, size_t mlen,
13
+ const uint8_t *ctx, size_t ctxlen,
14
+ const uint8_t *sk);
15
+
16
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign_ctx(uint8_t *sm, size_t *smlen,
17
+ const uint8_t *m, size_t mlen,
18
+ const uint8_t *ctx, size_t ctxlen,
19
+ const uint8_t *sk);
20
+
21
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign_verify_ctx(const uint8_t *sig, size_t siglen,
22
+ const uint8_t *m, size_t mlen,
23
+ const uint8_t *ctx, size_t ctxlen,
24
+ const uint8_t *pk);
25
+
26
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign_open_ctx(uint8_t *m, size_t *mlen,
27
+ const uint8_t *sm, size_t smlen,
28
+ const uint8_t *ctx, size_t ctxlen,
29
+ const uint8_t *pk);
30
+
31
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen,
32
+ const uint8_t *m, size_t mlen,
33
+ const uint8_t *sk);
34
+
35
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen,
36
+ const uint8_t *m, size_t mlen,
37
+ const uint8_t *sk);
38
+
39
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen,
40
+ const uint8_t *m, size_t mlen,
41
+ const uint8_t *pk);
42
+
43
+ int PQCLEAN_MLDSA87_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen,
44
+ const uint8_t *sm, size_t smlen,
45
+ const uint8_t *pk);
46
+
47
+ #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_MLDSA87_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_MLDSA87_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_MLDSA87_CLEAN_SYMMETRIC_H
2
+ #define PQCLEAN_MLDSA87_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_MLDSA87_CLEAN_dilithium_shake128_stream_init(shake128incctx *state,
12
+ const uint8_t seed[SEEDBYTES],
13
+ uint16_t nonce);
14
+
15
+ void PQCLEAN_MLDSA87_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_MLDSA87_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_MLDSA87_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