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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +56 -0
- data/CHANGELOG.md +50 -0
- data/GET_STARTED.md +374 -30
- data/README.md +59 -195
- data/SECURITY.md +101 -82
- data/ext/pqcrypto/extconf.rb +85 -9
- data/ext/pqcrypto/mldsa_api.h +71 -1
- data/ext/pqcrypto/mlkem_api.h +24 -0
- data/ext/pqcrypto/pq_externalmu.c +310 -0
- data/ext/pqcrypto/pqcrypto_ruby_secure.c +784 -85
- data/ext/pqcrypto/pqcrypto_secure.c +179 -72
- data/ext/pqcrypto/pqcrypto_secure.h +103 -7
- data/ext/pqcrypto/pqcrypto_version.h +7 -0
- data/ext/pqcrypto/vendor/.vendored +1 -1
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/Makefile +8 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/LICENSE +5 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/Makefile +19 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/Makefile.Microsoft_nmake +23 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/api.h +18 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/cbd.c +83 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/cbd.h +11 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/indcpa.c +327 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/indcpa.h +22 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/kem.c +164 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/kem.h +23 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/ntt.c +146 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/ntt.h +14 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/params.h +36 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/poly.c +311 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/poly.h +37 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/polyvec.c +198 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/polyvec.h +26 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/reduce.c +41 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/reduce.h +13 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/symmetric-shake.c +71 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/symmetric.h +30 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/verify.c +67 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-1024/clean/verify.h +13 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/LICENSE +5 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/Makefile +19 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/Makefile.Microsoft_nmake +23 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/api.h +18 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/cbd.c +108 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/cbd.h +11 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/indcpa.c +327 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/indcpa.h +22 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/kem.c +164 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/kem.h +23 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/ntt.c +146 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/ntt.h +14 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/params.h +36 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/poly.c +299 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/poly.h +37 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/polyvec.c +188 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/polyvec.h +26 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/reduce.c +41 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/reduce.h +13 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/symmetric-shake.c +71 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/symmetric.h +30 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/verify.c +67 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-512/clean/verify.h +13 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/Makefile +19 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/LICENSE +5 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/Makefile +19 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/Makefile.Microsoft_nmake +23 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/api.h +50 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/ntt.c +98 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/ntt.h +10 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/packing.c +261 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/packing.h +31 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/params.h +44 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/poly.c +848 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/poly.h +52 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/polyvec.c +415 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/polyvec.h +65 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/reduce.c +69 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/reduce.h +17 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/rounding.c +98 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/rounding.h +14 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/sign.c +407 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/sign.h +47 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/symmetric-shake.c +26 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-44/clean/symmetric.h +34 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/Makefile +19 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/LICENSE +5 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/Makefile +19 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/Makefile.Microsoft_nmake +23 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/api.h +50 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/ntt.c +98 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/ntt.h +10 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/packing.c +261 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/packing.h +31 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/params.h +44 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/poly.c +823 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/poly.h +52 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/polyvec.c +415 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/polyvec.h +65 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/reduce.c +69 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/reduce.h +17 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/rounding.c +92 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/rounding.h +14 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/sign.c +407 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/sign.h +47 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/symmetric-shake.c +26 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-87/clean/symmetric.h +34 -0
- data/lib/pq_crypto/algorithm_registry.rb +200 -0
- data/lib/pq_crypto/hybrid_kem.rb +1 -12
- data/lib/pq_crypto/kem.rb +104 -13
- data/lib/pq_crypto/pkcs8.rb +387 -0
- data/lib/pq_crypto/serialization.rb +1 -14
- data/lib/pq_crypto/signature.rb +231 -13
- data/lib/pq_crypto/spki.rb +131 -0
- data/lib/pq_crypto/version.rb +1 -1
- data/lib/pq_crypto.rb +90 -19
- data/script/vendor_libs.rb +4 -0
- metadata +99 -3
|
@@ -70,6 +70,12 @@ static VALUE ePQCryptoVerificationError;
|
|
|
70
70
|
|
|
71
71
|
__attribute__((noreturn)) static void pq_raise_general_error(int err);
|
|
72
72
|
|
|
73
|
+
static const char *const PQC_CONTAINER_ALGORITHMS[] = {
|
|
74
|
+
"ml_kem_768",
|
|
75
|
+
"ml_kem_768_x25519_xwing",
|
|
76
|
+
"ml_dsa_65",
|
|
77
|
+
};
|
|
78
|
+
|
|
73
79
|
static const char *pq_algorithm_symbol_to_cstr(VALUE algorithm) {
|
|
74
80
|
ID id;
|
|
75
81
|
if (SYMBOL_P(algorithm)) {
|
|
@@ -78,42 +84,64 @@ static const char *pq_algorithm_symbol_to_cstr(VALUE algorithm) {
|
|
|
78
84
|
VALUE str = StringValue(algorithm);
|
|
79
85
|
id = rb_intern_str(str);
|
|
80
86
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
for (size_t i = 0; i < sizeof(PQC_CONTAINER_ALGORITHMS) / sizeof(PQC_CONTAINER_ALGORITHMS[0]);
|
|
88
|
+
++i) {
|
|
89
|
+
if (id == rb_intern(PQC_CONTAINER_ALGORITHMS[i])) {
|
|
90
|
+
return PQC_CONTAINER_ALGORITHMS[i];
|
|
91
|
+
}
|
|
92
|
+
}
|
|
87
93
|
rb_raise(rb_eArgError, "Unsupported serialization algorithm");
|
|
88
94
|
}
|
|
89
95
|
|
|
90
96
|
static VALUE pq_algorithm_cstr_to_symbol(const char *algorithm) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
for (size_t i = 0; i < sizeof(PQC_CONTAINER_ALGORITHMS) / sizeof(PQC_CONTAINER_ALGORITHMS[0]);
|
|
98
|
+
++i) {
|
|
99
|
+
if (strcmp(algorithm, PQC_CONTAINER_ALGORITHMS[i]) == 0) {
|
|
100
|
+
return ID2SYM(rb_intern(PQC_CONTAINER_ALGORITHMS[i]));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
97
103
|
rb_raise(rb_eArgError, "Unsupported serialization algorithm");
|
|
98
104
|
}
|
|
99
105
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
106
|
+
#define PQ_KEM_KEYPAIR_NOGVL_VARIANTS(X) \
|
|
107
|
+
X(ml_kem, mlkem) \
|
|
108
|
+
X(ml_kem_512, mlkem512) \
|
|
109
|
+
X(ml_kem_1024, mlkem1024)
|
|
110
|
+
|
|
111
|
+
#define PQ_DEFINE_KEM_KEYPAIR_NOGVL(rb_name, c_name) \
|
|
112
|
+
static void *pq_##rb_name##_keypair_nogvl(void *arg) { \
|
|
113
|
+
kem_keypair_call_t *call = (kem_keypair_call_t *)arg; \
|
|
114
|
+
call->result = pq_##c_name##_keypair(call->public_key, call->secret_key); \
|
|
115
|
+
return NULL; \
|
|
116
|
+
} \
|
|
117
|
+
static void *pq_##rb_name##_keypair_from_seed_nogvl(void *arg) { \
|
|
118
|
+
kem_keypair_call_t *call = (kem_keypair_call_t *)arg; \
|
|
119
|
+
call->result = \
|
|
120
|
+
pq_##c_name##_keypair_from_seed(call->public_key, call->secret_key, call->seed); \
|
|
121
|
+
return NULL; \
|
|
122
|
+
}
|
|
105
123
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
124
|
+
PQ_KEM_KEYPAIR_NOGVL_VARIANTS(PQ_DEFINE_KEM_KEYPAIR_NOGVL)
|
|
125
|
+
|
|
126
|
+
#undef PQ_DEFINE_KEM_KEYPAIR_NOGVL
|
|
127
|
+
|
|
128
|
+
#define PQ_DEFINE_KEM_ENCAP_DECAP_NOGVL(rb_name, c_name) \
|
|
129
|
+
static void *pq_##rb_name##_encapsulate_nogvl(void *arg) { \
|
|
130
|
+
kem_encapsulate_call_t *call = (kem_encapsulate_call_t *)arg; \
|
|
131
|
+
call->result = \
|
|
132
|
+
pq_##c_name##_encapsulate(call->ciphertext, call->shared_secret, call->public_key); \
|
|
133
|
+
return NULL; \
|
|
134
|
+
} \
|
|
135
|
+
static void *pq_##rb_name##_decapsulate_nogvl(void *arg) { \
|
|
136
|
+
kem_decapsulate_call_t *call = (kem_decapsulate_call_t *)arg; \
|
|
137
|
+
call->result = \
|
|
138
|
+
pq_##c_name##_decapsulate(call->shared_secret, call->ciphertext, call->secret_key); \
|
|
139
|
+
return NULL; \
|
|
140
|
+
}
|
|
111
141
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return NULL;
|
|
116
|
-
}
|
|
142
|
+
PQ_KEM_KEYPAIR_NOGVL_VARIANTS(PQ_DEFINE_KEM_ENCAP_DECAP_NOGVL)
|
|
143
|
+
|
|
144
|
+
#undef PQ_DEFINE_KEM_ENCAP_DECAP_NOGVL
|
|
117
145
|
|
|
118
146
|
static void *pq_testing_ml_kem_keypair_nogvl(void *arg) {
|
|
119
147
|
kem_keypair_call_t *call = (kem_keypair_call_t *)arg;
|
|
@@ -122,12 +150,17 @@ static void *pq_testing_ml_kem_keypair_nogvl(void *arg) {
|
|
|
122
150
|
return NULL;
|
|
123
151
|
}
|
|
124
152
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
call->
|
|
129
|
-
|
|
130
|
-
|
|
153
|
+
#define PQ_DEFINE_KEM_TESTING_ENCAP_NOGVL(rb_name, c_name) \
|
|
154
|
+
static void *pq_testing_##rb_name##_encapsulate_nogvl(void *arg) { \
|
|
155
|
+
kem_encapsulate_call_t *call = (kem_encapsulate_call_t *)arg; \
|
|
156
|
+
call->result = pq_testing_##c_name##_encapsulate_from_seed( \
|
|
157
|
+
call->ciphertext, call->shared_secret, call->public_key, call->seed, call->seed_len); \
|
|
158
|
+
return NULL; \
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
PQ_KEM_KEYPAIR_NOGVL_VARIANTS(PQ_DEFINE_KEM_TESTING_ENCAP_NOGVL)
|
|
162
|
+
|
|
163
|
+
#undef PQ_DEFINE_KEM_TESTING_ENCAP_NOGVL
|
|
131
164
|
|
|
132
165
|
static void *pq_hybrid_kem_keypair_nogvl(void *arg) {
|
|
133
166
|
kem_keypair_call_t *call = (kem_keypair_call_t *)arg;
|
|
@@ -149,18 +182,45 @@ static void *pq_hybrid_kem_decapsulate_nogvl(void *arg) {
|
|
|
149
182
|
return NULL;
|
|
150
183
|
}
|
|
151
184
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
185
|
+
#define PQ_DEFINE_SIGN_KEYPAIR_NOGVL(rb_name, c_call) \
|
|
186
|
+
static void *pq_##rb_name##_nogvl(void *arg) { \
|
|
187
|
+
sign_keypair_call_t *call = (sign_keypair_call_t *)arg; \
|
|
188
|
+
call->result = c_call(call->public_key, call->secret_key); \
|
|
189
|
+
return NULL; \
|
|
190
|
+
}
|
|
157
191
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
192
|
+
PQ_DEFINE_SIGN_KEYPAIR_NOGVL(sign_keypair, pq_sign_keypair)
|
|
193
|
+
PQ_DEFINE_SIGN_KEYPAIR_NOGVL(mldsa_44_sign_keypair, pq_mldsa44_sign_keypair)
|
|
194
|
+
PQ_DEFINE_SIGN_KEYPAIR_NOGVL(mldsa_87_sign_keypair, pq_mldsa87_sign_keypair)
|
|
195
|
+
|
|
196
|
+
#undef PQ_DEFINE_SIGN_KEYPAIR_NOGVL
|
|
197
|
+
|
|
198
|
+
#define PQ_DEFINE_SIGN_KEYPAIR_FROM_SEED_NOGVL(rb_name, c_call) \
|
|
199
|
+
static void *pq_##rb_name##_nogvl(void *arg) { \
|
|
200
|
+
sign_keypair_call_t *call = (sign_keypair_call_t *)arg; \
|
|
201
|
+
call->result = c_call(call->public_key, call->secret_key, call->seed); \
|
|
202
|
+
return NULL; \
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
PQ_DEFINE_SIGN_KEYPAIR_FROM_SEED_NOGVL(mldsa_44_keypair_from_seed, pq_mldsa44_keypair_from_seed)
|
|
206
|
+
PQ_DEFINE_SIGN_KEYPAIR_FROM_SEED_NOGVL(mldsa_keypair_from_seed, pq_mldsa_keypair_from_seed)
|
|
207
|
+
PQ_DEFINE_SIGN_KEYPAIR_FROM_SEED_NOGVL(mldsa_87_keypair_from_seed, pq_mldsa87_keypair_from_seed)
|
|
208
|
+
|
|
209
|
+
#undef PQ_DEFINE_SIGN_KEYPAIR_FROM_SEED_NOGVL
|
|
210
|
+
|
|
211
|
+
#define PQ_DEFINE_SIGN_NOGVL(rb_name, c_call) \
|
|
212
|
+
static void *pq_##rb_name##_nogvl(void *arg) { \
|
|
213
|
+
sign_call_t *call = (sign_call_t *)arg; \
|
|
214
|
+
call->result = c_call(call->signature, &call->signature_len, call->message, \
|
|
215
|
+
call->message_len, call->secret_key); \
|
|
216
|
+
return NULL; \
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
PQ_DEFINE_SIGN_NOGVL(sign, pq_sign)
|
|
220
|
+
PQ_DEFINE_SIGN_NOGVL(mldsa_44_sign, pq_mldsa44_sign)
|
|
221
|
+
PQ_DEFINE_SIGN_NOGVL(mldsa_87_sign, pq_mldsa87_sign)
|
|
222
|
+
|
|
223
|
+
#undef PQ_DEFINE_SIGN_NOGVL
|
|
164
224
|
|
|
165
225
|
static void *pq_testing_sign_keypair_nogvl(void *arg) {
|
|
166
226
|
sign_keypair_call_t *call = (sign_keypair_call_t *)arg;
|
|
@@ -177,12 +237,43 @@ static void *pq_testing_sign_nogvl(void *arg) {
|
|
|
177
237
|
return NULL;
|
|
178
238
|
}
|
|
179
239
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
}
|
|
240
|
+
#define PQ_DEFINE_TESTING_KEYPAIR_FROM_SEED(rb_name, c_call) \
|
|
241
|
+
static void *pq_testing_##rb_name##_keypair_nogvl(void *arg) { \
|
|
242
|
+
sign_keypair_call_t *call = (sign_keypair_call_t *)arg; \
|
|
243
|
+
call->result = c_call(call->public_key, call->secret_key, call->seed, call->seed_len); \
|
|
244
|
+
return NULL; \
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
#define PQ_DEFINE_TESTING_SIGN_FROM_SEED(rb_name, c_call) \
|
|
248
|
+
static void *pq_testing_##rb_name##_sign_nogvl(void *arg) { \
|
|
249
|
+
sign_call_t *call = (sign_call_t *)arg; \
|
|
250
|
+
call->result = c_call(call->signature, &call->signature_len, call->message, \
|
|
251
|
+
call->message_len, call->secret_key, call->seed, call->seed_len); \
|
|
252
|
+
return NULL; \
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
PQ_DEFINE_TESTING_KEYPAIR_FROM_SEED(mldsa_44, pq_testing_mldsa44_keypair_from_seed)
|
|
256
|
+
PQ_DEFINE_TESTING_KEYPAIR_FROM_SEED(mldsa_87, pq_testing_mldsa87_keypair_from_seed)
|
|
257
|
+
|
|
258
|
+
PQ_DEFINE_TESTING_SIGN_FROM_SEED(mldsa_44, pq_testing_mldsa44_sign_from_seed)
|
|
259
|
+
PQ_DEFINE_TESTING_SIGN_FROM_SEED(mldsa_87, pq_testing_mldsa87_sign_from_seed)
|
|
260
|
+
|
|
261
|
+
#undef PQ_DEFINE_TESTING_KEYPAIR_FROM_SEED
|
|
262
|
+
#undef PQ_DEFINE_TESTING_SIGN_FROM_SEED
|
|
263
|
+
|
|
264
|
+
#define PQ_DEFINE_VERIFY_NOGVL(rb_name, c_call) \
|
|
265
|
+
static void *pq_##rb_name##_nogvl(void *arg) { \
|
|
266
|
+
verify_call_t *call = (verify_call_t *)arg; \
|
|
267
|
+
call->result = c_call(call->signature, call->signature_len, call->message, \
|
|
268
|
+
call->message_len, call->public_key); \
|
|
269
|
+
return NULL; \
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
PQ_DEFINE_VERIFY_NOGVL(verify, pq_verify)
|
|
273
|
+
PQ_DEFINE_VERIFY_NOGVL(mldsa_44_verify, pq_mldsa44_verify)
|
|
274
|
+
PQ_DEFINE_VERIFY_NOGVL(mldsa_87_verify, pq_mldsa87_verify)
|
|
275
|
+
|
|
276
|
+
#undef PQ_DEFINE_VERIFY_NOGVL
|
|
186
277
|
|
|
187
278
|
static uint8_t *pq_alloc_buffer(size_t len) {
|
|
188
279
|
if (len == 0) {
|
|
@@ -223,6 +314,10 @@ static void pq_wipe_and_free(uint8_t *buffer, size_t len) {
|
|
|
223
314
|
}
|
|
224
315
|
}
|
|
225
316
|
|
|
317
|
+
static void pq_free_buffer(uint8_t *buffer) {
|
|
318
|
+
free(buffer);
|
|
319
|
+
}
|
|
320
|
+
|
|
226
321
|
static void pq_validate_bytes_argument(VALUE value, size_t expected_len, const char *what) {
|
|
227
322
|
StringValue(value);
|
|
228
323
|
if ((size_t)RSTRING_LEN(value) != expected_len) {
|
|
@@ -465,24 +560,73 @@ __attribute__((noreturn)) static void pq_raise_general_error(int err) {
|
|
|
465
560
|
}
|
|
466
561
|
}
|
|
467
562
|
|
|
468
|
-
static VALUE
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
PQ_MLKEM_SECRETKEYBYTES);
|
|
472
|
-
}
|
|
563
|
+
static VALUE pq_run_kem_keypair_from_seed(void *(*nogvl)(void *), VALUE seed, size_t public_key_len,
|
|
564
|
+
size_t secret_key_len) {
|
|
565
|
+
StringValue(seed);
|
|
473
566
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
PQ_MLKEM_CIPHERTEXTBYTES, PQ_MLKEM_SHAREDSECRETBYTES);
|
|
478
|
-
}
|
|
567
|
+
if ((size_t)RSTRING_LEN(seed) != 64) {
|
|
568
|
+
rb_raise(rb_eArgError, "ML-KEM seed must be 64 bytes (FIPS 203 d||z)");
|
|
569
|
+
}
|
|
479
570
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
571
|
+
kem_keypair_call_t call = {0};
|
|
572
|
+
size_t seed_len = 0;
|
|
573
|
+
call.public_key = pq_alloc_buffer(public_key_len);
|
|
574
|
+
call.secret_key = pq_alloc_buffer(secret_key_len);
|
|
575
|
+
call.seed = pq_copy_ruby_string(seed, &seed_len);
|
|
576
|
+
call.seed_len = seed_len;
|
|
577
|
+
|
|
578
|
+
rb_thread_call_without_gvl(nogvl, &call, NULL, NULL);
|
|
579
|
+
pq_wipe_and_free((uint8_t *)call.seed, call.seed_len);
|
|
580
|
+
|
|
581
|
+
if (call.result != PQ_SUCCESS) {
|
|
582
|
+
pq_wipe_and_free(call.secret_key, secret_key_len);
|
|
583
|
+
free(call.public_key);
|
|
584
|
+
pq_raise_general_error(call.result);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
VALUE result = rb_ary_new2(2);
|
|
588
|
+
rb_ary_push(result, pq_string_from_buffer(call.public_key, public_key_len));
|
|
589
|
+
rb_ary_push(result, pq_string_from_buffer(call.secret_key, secret_key_len));
|
|
590
|
+
|
|
591
|
+
free(call.public_key);
|
|
592
|
+
pq_wipe_and_free(call.secret_key, secret_key_len);
|
|
593
|
+
return result;
|
|
484
594
|
}
|
|
485
595
|
|
|
596
|
+
#define PQ_RUBY_KEM_VARIANTS(X) \
|
|
597
|
+
X(ml_kem, PQ_MLKEM_PUBLICKEYBYTES, PQ_MLKEM_SECRETKEYBYTES, PQ_MLKEM_CIPHERTEXTBYTES, \
|
|
598
|
+
PQ_MLKEM_SHAREDSECRETBYTES) \
|
|
599
|
+
X(ml_kem_512, MLKEM512_PUBLICKEYBYTES, MLKEM512_SECRETKEYBYTES, MLKEM512_CIPHERTEXTBYTES, \
|
|
600
|
+
MLKEM512_SHAREDSECRETBYTES) \
|
|
601
|
+
X(ml_kem_1024, MLKEM1024_PUBLICKEYBYTES, MLKEM1024_SECRETKEYBYTES, MLKEM1024_CIPHERTEXTBYTES, \
|
|
602
|
+
MLKEM1024_SHAREDSECRETBYTES)
|
|
603
|
+
|
|
604
|
+
#define PQ_DEFINE_RUBY_KEM(rb_name, pk_bytes, sk_bytes, ct_bytes, ss_bytes) \
|
|
605
|
+
static VALUE pqcrypto_##rb_name##_keypair(VALUE self) { \
|
|
606
|
+
(void)self; \
|
|
607
|
+
return pq_run_kem_keypair(pq_##rb_name##_keypair_nogvl, pk_bytes, sk_bytes); \
|
|
608
|
+
} \
|
|
609
|
+
static VALUE pqcrypto_##rb_name##_keypair_from_seed(VALUE self, VALUE seed) { \
|
|
610
|
+
(void)self; \
|
|
611
|
+
return pq_run_kem_keypair_from_seed(pq_##rb_name##_keypair_from_seed_nogvl, seed, \
|
|
612
|
+
pk_bytes, sk_bytes); \
|
|
613
|
+
} \
|
|
614
|
+
static VALUE pqcrypto_##rb_name##_encapsulate(VALUE self, VALUE public_key) { \
|
|
615
|
+
(void)self; \
|
|
616
|
+
return pq_run_kem_encapsulate(pq_##rb_name##_encapsulate_nogvl, public_key, pk_bytes, \
|
|
617
|
+
ct_bytes, ss_bytes); \
|
|
618
|
+
} \
|
|
619
|
+
static VALUE pqcrypto_##rb_name##_decapsulate(VALUE self, VALUE ciphertext, \
|
|
620
|
+
VALUE secret_key) { \
|
|
621
|
+
(void)self; \
|
|
622
|
+
return pq_run_kem_decapsulate(pq_##rb_name##_decapsulate_nogvl, ciphertext, ct_bytes, \
|
|
623
|
+
secret_key, sk_bytes, ss_bytes); \
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
PQ_RUBY_KEM_VARIANTS(PQ_DEFINE_RUBY_KEM)
|
|
627
|
+
|
|
628
|
+
#undef PQ_DEFINE_RUBY_KEM
|
|
629
|
+
|
|
486
630
|
static VALUE pqcrypto_hybrid_kem_keypair(VALUE self) {
|
|
487
631
|
(void)self;
|
|
488
632
|
return pq_run_kem_keypair(pq_hybrid_kem_keypair_nogvl, PQ_HYBRID_PUBLICKEYBYTES,
|
|
@@ -573,6 +717,61 @@ static VALUE pqcrypto__test_ml_kem_encapsulate_from_seed(VALUE self, VALUE publi
|
|
|
573
717
|
return result;
|
|
574
718
|
}
|
|
575
719
|
|
|
720
|
+
static VALUE pq_run_test_kem_encapsulate_from_seed(void *(*nogvl)(void *), VALUE public_key,
|
|
721
|
+
VALUE seed, size_t public_key_len,
|
|
722
|
+
size_t ciphertext_len,
|
|
723
|
+
size_t shared_secret_len) {
|
|
724
|
+
pq_validate_bytes_argument(public_key, public_key_len, "public key");
|
|
725
|
+
StringValue(seed);
|
|
726
|
+
|
|
727
|
+
if ((size_t)RSTRING_LEN(seed) != 32) {
|
|
728
|
+
rb_raise(rb_eArgError, "Deterministic test seed must be 32 bytes");
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
kem_encapsulate_call_t call = {0};
|
|
732
|
+
size_t public_key_copy_len = 0;
|
|
733
|
+
size_t seed_len = 0;
|
|
734
|
+
call.public_key = pq_copy_ruby_string(public_key, &public_key_copy_len);
|
|
735
|
+
call.ciphertext = pq_alloc_buffer(ciphertext_len);
|
|
736
|
+
call.shared_secret = pq_alloc_buffer(shared_secret_len);
|
|
737
|
+
call.seed = pq_copy_ruby_string(seed, &seed_len);
|
|
738
|
+
call.seed_len = seed_len;
|
|
739
|
+
|
|
740
|
+
rb_thread_call_without_gvl(nogvl, &call, NULL, NULL);
|
|
741
|
+
pq_wipe_and_free((uint8_t *)call.public_key, public_key_copy_len);
|
|
742
|
+
pq_wipe_and_free((uint8_t *)call.seed, call.seed_len);
|
|
743
|
+
|
|
744
|
+
if (call.result != PQ_SUCCESS) {
|
|
745
|
+
pq_wipe_and_free(call.shared_secret, shared_secret_len);
|
|
746
|
+
free(call.ciphertext);
|
|
747
|
+
pq_raise_general_error(call.result);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
VALUE result = rb_ary_new2(2);
|
|
751
|
+
rb_ary_push(result, pq_string_from_buffer(call.ciphertext, ciphertext_len));
|
|
752
|
+
rb_ary_push(result, pq_string_from_buffer(call.shared_secret, shared_secret_len));
|
|
753
|
+
|
|
754
|
+
free(call.ciphertext);
|
|
755
|
+
pq_wipe_and_free(call.shared_secret, shared_secret_len);
|
|
756
|
+
return result;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
static VALUE pqcrypto__test_ml_kem_512_encapsulate_from_seed(VALUE self, VALUE public_key,
|
|
760
|
+
VALUE seed) {
|
|
761
|
+
(void)self;
|
|
762
|
+
return pq_run_test_kem_encapsulate_from_seed(
|
|
763
|
+
pq_testing_ml_kem_512_encapsulate_nogvl, public_key, seed, MLKEM512_PUBLICKEYBYTES,
|
|
764
|
+
MLKEM512_CIPHERTEXTBYTES, MLKEM512_SHAREDSECRETBYTES);
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
static VALUE pqcrypto__test_ml_kem_1024_encapsulate_from_seed(VALUE self, VALUE public_key,
|
|
768
|
+
VALUE seed) {
|
|
769
|
+
(void)self;
|
|
770
|
+
return pq_run_test_kem_encapsulate_from_seed(
|
|
771
|
+
pq_testing_ml_kem_1024_encapsulate_nogvl, public_key, seed, MLKEM1024_PUBLICKEYBYTES,
|
|
772
|
+
MLKEM1024_CIPHERTEXTBYTES, MLKEM1024_SHAREDSECRETBYTES);
|
|
773
|
+
}
|
|
774
|
+
|
|
576
775
|
static VALUE pqcrypto__test_sign_keypair_from_seed(VALUE self, VALUE seed) {
|
|
577
776
|
(void)self;
|
|
578
777
|
StringValue(seed);
|
|
@@ -628,56 +827,187 @@ static VALUE pqcrypto__test_sign_from_seed(VALUE self, VALUE message, VALUE secr
|
|
|
628
827
|
|
|
629
828
|
rb_thread_call_without_gvl(pq_testing_sign_nogvl, &call, NULL, NULL);
|
|
630
829
|
|
|
631
|
-
|
|
830
|
+
pq_free_buffer(call.message);
|
|
632
831
|
pq_wipe_and_free((uint8_t *)call.secret_key, secret_key_len);
|
|
633
832
|
pq_wipe_and_free((uint8_t *)call.seed, call.seed_len);
|
|
634
833
|
|
|
635
834
|
if (call.result != PQ_SUCCESS) {
|
|
636
|
-
|
|
835
|
+
pq_free_buffer(call.signature);
|
|
637
836
|
pq_raise_general_error(call.result);
|
|
638
837
|
}
|
|
639
838
|
|
|
640
839
|
VALUE result = pq_string_from_buffer(call.signature, call.signature_len);
|
|
641
|
-
|
|
840
|
+
pq_free_buffer(call.signature);
|
|
642
841
|
return result;
|
|
643
842
|
}
|
|
644
843
|
|
|
645
|
-
static VALUE
|
|
844
|
+
static VALUE pq_run_test_sign_keypair_from_seed(void *(*nogvl)(void *), VALUE seed,
|
|
845
|
+
size_t public_key_len, size_t secret_key_len) {
|
|
846
|
+
StringValue(seed);
|
|
847
|
+
|
|
848
|
+
if ((size_t)RSTRING_LEN(seed) != 32) {
|
|
849
|
+
rb_raise(rb_eArgError, "Deterministic test seed must be 32 bytes");
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
sign_keypair_call_t call = {0};
|
|
853
|
+
size_t seed_len = 0;
|
|
854
|
+
call.public_key = pq_alloc_buffer(public_key_len);
|
|
855
|
+
call.secret_key = pq_alloc_buffer(secret_key_len);
|
|
856
|
+
call.seed = pq_copy_ruby_string(seed, &seed_len);
|
|
857
|
+
call.seed_len = seed_len;
|
|
858
|
+
|
|
859
|
+
rb_thread_call_without_gvl(nogvl, &call, NULL, NULL);
|
|
860
|
+
pq_wipe_and_free((uint8_t *)call.seed, call.seed_len);
|
|
861
|
+
|
|
862
|
+
if (call.result != PQ_SUCCESS) {
|
|
863
|
+
pq_wipe_and_free(call.secret_key, secret_key_len);
|
|
864
|
+
free(call.public_key);
|
|
865
|
+
pq_raise_general_error(call.result);
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
VALUE result = rb_ary_new2(2);
|
|
869
|
+
rb_ary_push(result, pq_string_from_buffer(call.public_key, public_key_len));
|
|
870
|
+
rb_ary_push(result, pq_string_from_buffer(call.secret_key, secret_key_len));
|
|
871
|
+
|
|
872
|
+
free(call.public_key);
|
|
873
|
+
pq_wipe_and_free(call.secret_key, secret_key_len);
|
|
874
|
+
return result;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
static VALUE pqcrypto__test_ml_dsa_44_keypair_from_seed(VALUE self, VALUE seed) {
|
|
646
878
|
(void)self;
|
|
647
|
-
return
|
|
648
|
-
|
|
879
|
+
return pq_run_test_sign_keypair_from_seed(pq_testing_mldsa_44_keypair_nogvl, seed,
|
|
880
|
+
MLDSA44_PUBLICKEYBYTES, MLDSA44_SECRETKEYBYTES);
|
|
649
881
|
}
|
|
650
882
|
|
|
651
|
-
static VALUE
|
|
883
|
+
static VALUE pqcrypto__test_ml_dsa_87_keypair_from_seed(VALUE self, VALUE seed) {
|
|
652
884
|
(void)self;
|
|
653
|
-
|
|
885
|
+
return pq_run_test_sign_keypair_from_seed(pq_testing_mldsa_87_keypair_nogvl, seed,
|
|
886
|
+
MLDSA87_PUBLICKEYBYTES, MLDSA87_SECRETKEYBYTES);
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
#define PQ_RUBY_MLDSA_KEYPAIR_FROM_SEED_VARIANTS(X) \
|
|
890
|
+
X(ml_dsa_44, mldsa_44_keypair_from_seed, MLDSA44_PUBLICKEYBYTES, MLDSA44_SECRETKEYBYTES) \
|
|
891
|
+
X(ml_dsa, mldsa_keypair_from_seed, PQ_MLDSA_PUBLICKEYBYTES, PQ_MLDSA_SECRETKEYBYTES) \
|
|
892
|
+
X(ml_dsa_87, mldsa_87_keypair_from_seed, MLDSA87_PUBLICKEYBYTES, MLDSA87_SECRETKEYBYTES)
|
|
893
|
+
|
|
894
|
+
#define PQ_DEFINE_RUBY_MLDSA_KEYPAIR_FROM_SEED(rb_name, nogvl_suffix, pk_bytes, sk_bytes) \
|
|
895
|
+
static VALUE pqcrypto_##rb_name##_keypair_from_seed(VALUE self, VALUE seed) { \
|
|
896
|
+
(void)self; \
|
|
897
|
+
return pq_run_test_sign_keypair_from_seed(pq_##nogvl_suffix##_nogvl, seed, pk_bytes, \
|
|
898
|
+
sk_bytes); \
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
PQ_RUBY_MLDSA_KEYPAIR_FROM_SEED_VARIANTS(PQ_DEFINE_RUBY_MLDSA_KEYPAIR_FROM_SEED)
|
|
902
|
+
|
|
903
|
+
#undef PQ_DEFINE_RUBY_MLDSA_KEYPAIR_FROM_SEED
|
|
904
|
+
|
|
905
|
+
static VALUE pq_run_test_sign_from_seed(void *(*nogvl)(void *), VALUE message, VALUE secret_key,
|
|
906
|
+
VALUE seed, size_t secret_key_len, size_t signature_len) {
|
|
907
|
+
pq_validate_bytes_argument(secret_key, secret_key_len, "secret key");
|
|
908
|
+
StringValue(seed);
|
|
909
|
+
|
|
910
|
+
if ((size_t)RSTRING_LEN(seed) != 32) {
|
|
911
|
+
rb_raise(rb_eArgError, "Deterministic test seed must be 32 bytes");
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
sign_call_t call = {0};
|
|
915
|
+
size_t secret_key_copy_len = 0;
|
|
916
|
+
size_t seed_len = 0;
|
|
917
|
+
call.secret_key = pq_copy_ruby_string(secret_key, &secret_key_copy_len);
|
|
918
|
+
call.signature_len = signature_len;
|
|
919
|
+
call.signature = pq_alloc_buffer(signature_len);
|
|
920
|
+
call.message = pq_copy_ruby_string(message, &call.message_len);
|
|
921
|
+
call.seed = pq_copy_ruby_string(seed, &seed_len);
|
|
922
|
+
call.seed_len = seed_len;
|
|
923
|
+
|
|
924
|
+
rb_thread_call_without_gvl(nogvl, &call, NULL, NULL);
|
|
925
|
+
|
|
926
|
+
pq_free_buffer(call.message);
|
|
927
|
+
pq_wipe_and_free((uint8_t *)call.secret_key, secret_key_copy_len);
|
|
928
|
+
pq_wipe_and_free((uint8_t *)call.seed, call.seed_len);
|
|
929
|
+
|
|
930
|
+
if (call.result != PQ_SUCCESS) {
|
|
931
|
+
pq_free_buffer(call.signature);
|
|
932
|
+
pq_raise_general_error(call.result);
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
VALUE result = pq_string_from_buffer(call.signature, call.signature_len);
|
|
936
|
+
pq_free_buffer(call.signature);
|
|
937
|
+
return result;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
static VALUE pqcrypto__test_ml_dsa_44_sign_from_seed(VALUE self, VALUE message, VALUE secret_key,
|
|
941
|
+
VALUE seed) {
|
|
942
|
+
(void)self;
|
|
943
|
+
return pq_run_test_sign_from_seed(pq_testing_mldsa_44_sign_nogvl, message, secret_key, seed,
|
|
944
|
+
MLDSA44_SECRETKEYBYTES, MLDSA44_BYTES);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
static VALUE pqcrypto__test_ml_dsa_87_sign_from_seed(VALUE self, VALUE message, VALUE secret_key,
|
|
948
|
+
VALUE seed) {
|
|
949
|
+
(void)self;
|
|
950
|
+
return pq_run_test_sign_from_seed(pq_testing_mldsa_87_sign_nogvl, message, secret_key, seed,
|
|
951
|
+
MLDSA87_SECRETKEYBYTES, MLDSA87_BYTES);
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
#define PQ_DEFINE_RUBY_MLDSA_KEYPAIR(rb_name, nogvl_stem, pk_bytes, sk_bytes) \
|
|
955
|
+
static VALUE pqcrypto_##rb_name(VALUE self) { \
|
|
956
|
+
(void)self; \
|
|
957
|
+
return pq_run_sign_keypair(pq_##nogvl_stem##_nogvl, pk_bytes, sk_bytes); \
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
PQ_DEFINE_RUBY_MLDSA_KEYPAIR(sign_keypair, sign_keypair, PQ_MLDSA_PUBLICKEYBYTES,
|
|
961
|
+
PQ_MLDSA_SECRETKEYBYTES)
|
|
962
|
+
PQ_DEFINE_RUBY_MLDSA_KEYPAIR(ml_dsa_44_keypair, mldsa_44_sign_keypair, MLDSA44_PUBLICKEYBYTES,
|
|
963
|
+
MLDSA44_SECRETKEYBYTES)
|
|
964
|
+
PQ_DEFINE_RUBY_MLDSA_KEYPAIR(ml_dsa_87_keypair, mldsa_87_sign_keypair, MLDSA87_PUBLICKEYBYTES,
|
|
965
|
+
MLDSA87_SECRETKEYBYTES)
|
|
966
|
+
|
|
967
|
+
#undef PQ_DEFINE_RUBY_MLDSA_KEYPAIR
|
|
968
|
+
|
|
969
|
+
static VALUE pq_run_sign(void *(*nogvl)(void *), VALUE message, VALUE secret_key,
|
|
970
|
+
size_t secret_key_len_expected, size_t signature_len_expected) {
|
|
971
|
+
pq_validate_bytes_argument(secret_key, secret_key_len_expected, "secret key");
|
|
654
972
|
|
|
655
973
|
sign_call_t call = {0};
|
|
656
974
|
size_t secret_key_len = 0;
|
|
657
975
|
call.secret_key = pq_copy_ruby_string(secret_key, &secret_key_len);
|
|
658
|
-
call.signature_len =
|
|
659
|
-
call.signature = pq_alloc_buffer(
|
|
976
|
+
call.signature_len = signature_len_expected;
|
|
977
|
+
call.signature = pq_alloc_buffer(signature_len_expected);
|
|
660
978
|
call.message = pq_copy_ruby_string(message, &call.message_len);
|
|
661
979
|
|
|
662
|
-
rb_nogvl(
|
|
980
|
+
rb_nogvl(nogvl, &call, NULL, NULL, RB_NOGVL_OFFLOAD_SAFE);
|
|
663
981
|
|
|
664
|
-
|
|
982
|
+
pq_free_buffer(call.message);
|
|
665
983
|
pq_wipe_and_free((uint8_t *)call.secret_key, secret_key_len);
|
|
666
984
|
|
|
667
985
|
if (call.result != PQ_SUCCESS) {
|
|
668
|
-
|
|
986
|
+
pq_free_buffer(call.signature);
|
|
669
987
|
pq_raise_general_error(call.result);
|
|
670
988
|
}
|
|
671
989
|
|
|
672
990
|
VALUE result = pq_string_from_buffer(call.signature, call.signature_len);
|
|
673
|
-
|
|
991
|
+
pq_free_buffer(call.signature);
|
|
674
992
|
return result;
|
|
675
993
|
}
|
|
676
994
|
|
|
677
|
-
|
|
678
|
-
(
|
|
995
|
+
#define PQ_DEFINE_RUBY_MLDSA_SIGN(rb_name, nogvl_stem, sk_bytes, sig_bytes) \
|
|
996
|
+
static VALUE pqcrypto_##rb_name(VALUE self, VALUE message, VALUE secret_key) { \
|
|
997
|
+
(void)self; \
|
|
998
|
+
return pq_run_sign(pq_##nogvl_stem##_nogvl, message, secret_key, sk_bytes, sig_bytes); \
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
PQ_DEFINE_RUBY_MLDSA_SIGN(sign, sign, PQ_MLDSA_SECRETKEYBYTES, PQ_MLDSA_BYTES)
|
|
1002
|
+
PQ_DEFINE_RUBY_MLDSA_SIGN(ml_dsa_44_sign, mldsa_44_sign, MLDSA44_SECRETKEYBYTES, MLDSA44_BYTES)
|
|
1003
|
+
PQ_DEFINE_RUBY_MLDSA_SIGN(ml_dsa_87_sign, mldsa_87_sign, MLDSA87_SECRETKEYBYTES, MLDSA87_BYTES)
|
|
1004
|
+
|
|
1005
|
+
#undef PQ_DEFINE_RUBY_MLDSA_SIGN
|
|
1006
|
+
|
|
1007
|
+
static VALUE pq_run_verify(void *(*nogvl)(void *), VALUE message, VALUE signature, VALUE public_key,
|
|
1008
|
+
size_t public_key_len_expected) {
|
|
679
1009
|
StringValue(signature);
|
|
680
|
-
pq_validate_bytes_argument(public_key,
|
|
1010
|
+
pq_validate_bytes_argument(public_key, public_key_len_expected, "public key");
|
|
681
1011
|
|
|
682
1012
|
verify_call_t call = {0};
|
|
683
1013
|
size_t public_key_len = 0;
|
|
@@ -687,11 +1017,11 @@ static VALUE pqcrypto_verify(VALUE self, VALUE message, VALUE signature, VALUE p
|
|
|
687
1017
|
call.signature_len = signature_len;
|
|
688
1018
|
call.message = pq_copy_ruby_string(message, &call.message_len);
|
|
689
1019
|
|
|
690
|
-
rb_nogvl(
|
|
1020
|
+
rb_nogvl(nogvl, &call, NULL, NULL, RB_NOGVL_OFFLOAD_SAFE);
|
|
691
1021
|
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
1022
|
+
pq_free_buffer(call.message);
|
|
1023
|
+
pq_free_buffer((uint8_t *)call.public_key);
|
|
1024
|
+
pq_free_buffer((uint8_t *)call.signature);
|
|
695
1025
|
|
|
696
1026
|
if (call.result == PQ_SUCCESS) {
|
|
697
1027
|
return Qtrue;
|
|
@@ -702,6 +1032,19 @@ static VALUE pqcrypto_verify(VALUE self, VALUE message, VALUE signature, VALUE p
|
|
|
702
1032
|
pq_raise_general_error(call.result);
|
|
703
1033
|
}
|
|
704
1034
|
|
|
1035
|
+
#define PQ_DEFINE_RUBY_MLDSA_VERIFY(rb_name, nogvl_stem, pk_bytes) \
|
|
1036
|
+
static VALUE pqcrypto_##rb_name(VALUE self, VALUE message, VALUE signature, \
|
|
1037
|
+
VALUE public_key) { \
|
|
1038
|
+
(void)self; \
|
|
1039
|
+
return pq_run_verify(pq_##nogvl_stem##_nogvl, message, signature, public_key, pk_bytes); \
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
PQ_DEFINE_RUBY_MLDSA_VERIFY(verify, verify, PQ_MLDSA_PUBLICKEYBYTES)
|
|
1043
|
+
PQ_DEFINE_RUBY_MLDSA_VERIFY(ml_dsa_44_verify, mldsa_44_verify, MLDSA44_PUBLICKEYBYTES)
|
|
1044
|
+
PQ_DEFINE_RUBY_MLDSA_VERIFY(ml_dsa_87_verify, mldsa_87_verify, MLDSA87_PUBLICKEYBYTES)
|
|
1045
|
+
|
|
1046
|
+
#undef PQ_DEFINE_RUBY_MLDSA_VERIFY
|
|
1047
|
+
|
|
705
1048
|
static VALUE pqcrypto_ct_equals(VALUE self, VALUE a, VALUE b) {
|
|
706
1049
|
(void)self;
|
|
707
1050
|
StringValue(a);
|
|
@@ -731,19 +1074,319 @@ static VALUE pqcrypto_version(VALUE self) {
|
|
|
731
1074
|
return rb_str_new_cstr(pq_version());
|
|
732
1075
|
}
|
|
733
1076
|
|
|
1077
|
+
typedef struct {
|
|
1078
|
+
void *builder;
|
|
1079
|
+
} mu_builder_wrapper_t;
|
|
1080
|
+
|
|
1081
|
+
typedef struct {
|
|
1082
|
+
int result;
|
|
1083
|
+
void *builder;
|
|
1084
|
+
const uint8_t *chunk;
|
|
1085
|
+
size_t chunk_len;
|
|
1086
|
+
} mu_absorb_call_t;
|
|
1087
|
+
|
|
1088
|
+
typedef struct {
|
|
1089
|
+
int result;
|
|
1090
|
+
void *builder;
|
|
1091
|
+
uint8_t *mu_out;
|
|
1092
|
+
} mu_finalize_call_t;
|
|
1093
|
+
|
|
1094
|
+
typedef struct {
|
|
1095
|
+
int result;
|
|
1096
|
+
uint8_t *signature;
|
|
1097
|
+
size_t signature_len;
|
|
1098
|
+
const uint8_t *mu;
|
|
1099
|
+
const uint8_t *secret_key;
|
|
1100
|
+
} sign_mu_call_t;
|
|
1101
|
+
|
|
1102
|
+
typedef struct {
|
|
1103
|
+
int result;
|
|
1104
|
+
const uint8_t *signature;
|
|
1105
|
+
size_t signature_len;
|
|
1106
|
+
const uint8_t *mu;
|
|
1107
|
+
const uint8_t *public_key;
|
|
1108
|
+
} verify_mu_call_t;
|
|
1109
|
+
|
|
1110
|
+
static void mu_builder_wrapper_free(void *ptr) {
|
|
1111
|
+
mu_builder_wrapper_t *wrapper = (mu_builder_wrapper_t *)ptr;
|
|
1112
|
+
if (wrapper == NULL) {
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
if (wrapper->builder != NULL) {
|
|
1116
|
+
pq_mu_builder_release(wrapper->builder);
|
|
1117
|
+
wrapper->builder = NULL;
|
|
1118
|
+
}
|
|
1119
|
+
xfree(wrapper);
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
static size_t mu_builder_wrapper_size(const void *ptr) {
|
|
1123
|
+
(void)ptr;
|
|
1124
|
+
return sizeof(mu_builder_wrapper_t);
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
static const rb_data_type_t mu_builder_data_type = {
|
|
1128
|
+
.wrap_struct_name = "PQCrypto::MLDSA::MuBuilder",
|
|
1129
|
+
.function =
|
|
1130
|
+
{
|
|
1131
|
+
.dmark = NULL,
|
|
1132
|
+
.dfree = mu_builder_wrapper_free,
|
|
1133
|
+
.dsize = mu_builder_wrapper_size,
|
|
1134
|
+
.dcompact = NULL,
|
|
1135
|
+
.reserved = {NULL},
|
|
1136
|
+
},
|
|
1137
|
+
.parent = NULL,
|
|
1138
|
+
.data = NULL,
|
|
1139
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
|
1140
|
+
};
|
|
1141
|
+
|
|
1142
|
+
static mu_builder_wrapper_t *mu_builder_unwrap(VALUE obj) {
|
|
1143
|
+
mu_builder_wrapper_t *wrapper;
|
|
1144
|
+
TypedData_Get_Struct(obj, mu_builder_wrapper_t, &mu_builder_data_type, wrapper);
|
|
1145
|
+
if (wrapper == NULL || wrapper->builder == NULL) {
|
|
1146
|
+
rb_raise(ePQCryptoError, "mu builder used after release");
|
|
1147
|
+
}
|
|
1148
|
+
return wrapper;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
static VALUE pqcrypto__native_mldsa_extract_tr(VALUE self, VALUE secret_key) {
|
|
1152
|
+
(void)self;
|
|
1153
|
+
pq_validate_bytes_argument(secret_key, PQ_MLDSA_SECRETKEYBYTES, "secret key");
|
|
1154
|
+
|
|
1155
|
+
uint8_t tr[PQ_MLDSA_TRBYTES];
|
|
1156
|
+
int rc = pq_mldsa_extract_tr_from_secret_key(tr, (const uint8_t *)RSTRING_PTR(secret_key));
|
|
1157
|
+
if (rc != PQ_SUCCESS) {
|
|
1158
|
+
pq_secure_wipe(tr, sizeof(tr));
|
|
1159
|
+
pq_raise_general_error(rc);
|
|
1160
|
+
}
|
|
1161
|
+
VALUE result = pq_string_from_buffer(tr, sizeof(tr));
|
|
1162
|
+
pq_secure_wipe(tr, sizeof(tr));
|
|
1163
|
+
return result;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
static VALUE pqcrypto__native_mldsa_compute_tr(VALUE self, VALUE public_key) {
|
|
1167
|
+
(void)self;
|
|
1168
|
+
pq_validate_bytes_argument(public_key, PQ_MLDSA_PUBLICKEYBYTES, "public key");
|
|
1169
|
+
|
|
1170
|
+
uint8_t tr[PQ_MLDSA_TRBYTES];
|
|
1171
|
+
int rc = pq_mldsa_compute_tr_from_public_key(tr, (const uint8_t *)RSTRING_PTR(public_key));
|
|
1172
|
+
if (rc != PQ_SUCCESS) {
|
|
1173
|
+
pq_raise_general_error(rc);
|
|
1174
|
+
}
|
|
1175
|
+
return pq_string_from_buffer(tr, sizeof(tr));
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
static VALUE pqcrypto__native_mldsa_mu_builder_new(VALUE self, VALUE tr, VALUE ctx) {
|
|
1179
|
+
(void)self;
|
|
1180
|
+
pq_validate_bytes_argument(tr, PQ_MLDSA_TRBYTES, "tr");
|
|
1181
|
+
StringValue(ctx);
|
|
1182
|
+
|
|
1183
|
+
size_t ctxlen = (size_t)RSTRING_LEN(ctx);
|
|
1184
|
+
if (ctxlen > 255) {
|
|
1185
|
+
rb_raise(rb_eArgError, "ML-DSA context length must be <= 255 bytes");
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
void *builder = pq_mu_builder_new();
|
|
1189
|
+
if (builder == NULL) {
|
|
1190
|
+
rb_raise(rb_eNoMemError, "Memory allocation failed (mu builder)");
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
int rc = pq_mu_builder_init(builder, (const uint8_t *)RSTRING_PTR(tr),
|
|
1194
|
+
(const uint8_t *)RSTRING_PTR(ctx), ctxlen);
|
|
1195
|
+
if (rc != PQ_SUCCESS) {
|
|
1196
|
+
pq_mu_builder_release(builder);
|
|
1197
|
+
pq_raise_general_error(rc);
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
mu_builder_wrapper_t *wrapper;
|
|
1201
|
+
VALUE obj =
|
|
1202
|
+
TypedData_Make_Struct(rb_cObject, mu_builder_wrapper_t, &mu_builder_data_type, wrapper);
|
|
1203
|
+
wrapper->builder = builder;
|
|
1204
|
+
return obj;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
static void *pq_mu_absorb_nogvl(void *arg) {
|
|
1208
|
+
mu_absorb_call_t *call = (mu_absorb_call_t *)arg;
|
|
1209
|
+
call->result = pq_mu_builder_absorb(call->builder, call->chunk, call->chunk_len);
|
|
1210
|
+
return NULL;
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
static VALUE pqcrypto__native_mldsa_mu_builder_update(VALUE self, VALUE builder_obj, VALUE chunk) {
|
|
1214
|
+
(void)self;
|
|
1215
|
+
mu_builder_wrapper_t *wrapper = mu_builder_unwrap(builder_obj);
|
|
1216
|
+
StringValue(chunk);
|
|
1217
|
+
|
|
1218
|
+
size_t chunk_len = (size_t)RSTRING_LEN(chunk);
|
|
1219
|
+
if (chunk_len == 0) {
|
|
1220
|
+
return Qnil;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
uint8_t *copy = pq_alloc_buffer(chunk_len);
|
|
1224
|
+
memcpy(copy, RSTRING_PTR(chunk), chunk_len);
|
|
1225
|
+
|
|
1226
|
+
mu_absorb_call_t call = {0};
|
|
1227
|
+
call.builder = wrapper->builder;
|
|
1228
|
+
call.chunk = copy;
|
|
1229
|
+
call.chunk_len = chunk_len;
|
|
1230
|
+
|
|
1231
|
+
rb_nogvl(pq_mu_absorb_nogvl, &call, NULL, NULL, RB_NOGVL_OFFLOAD_SAFE);
|
|
1232
|
+
free(copy);
|
|
1233
|
+
|
|
1234
|
+
if (call.result != PQ_SUCCESS) {
|
|
1235
|
+
pq_raise_general_error(call.result);
|
|
1236
|
+
}
|
|
1237
|
+
return Qnil;
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
static void *pq_mu_finalize_nogvl(void *arg) {
|
|
1241
|
+
mu_finalize_call_t *call = (mu_finalize_call_t *)arg;
|
|
1242
|
+
call->result = pq_mu_builder_finalize(call->builder, call->mu_out);
|
|
1243
|
+
return NULL;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
static VALUE pqcrypto__native_mldsa_mu_builder_finalize(VALUE self, VALUE builder_obj) {
|
|
1247
|
+
(void)self;
|
|
1248
|
+
mu_builder_wrapper_t *wrapper = mu_builder_unwrap(builder_obj);
|
|
1249
|
+
|
|
1250
|
+
uint8_t mu[PQ_MLDSA_MUBYTES];
|
|
1251
|
+
|
|
1252
|
+
mu_finalize_call_t call = {0};
|
|
1253
|
+
call.builder = wrapper->builder;
|
|
1254
|
+
call.mu_out = mu;
|
|
1255
|
+
|
|
1256
|
+
rb_nogvl(pq_mu_finalize_nogvl, &call, NULL, NULL, RB_NOGVL_OFFLOAD_SAFE);
|
|
1257
|
+
|
|
1258
|
+
if (call.result != PQ_SUCCESS) {
|
|
1259
|
+
pq_mu_builder_release(wrapper->builder);
|
|
1260
|
+
}
|
|
1261
|
+
wrapper->builder = NULL;
|
|
1262
|
+
|
|
1263
|
+
if (call.result != PQ_SUCCESS) {
|
|
1264
|
+
pq_secure_wipe(mu, sizeof(mu));
|
|
1265
|
+
pq_raise_general_error(call.result);
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
VALUE result = pq_string_from_buffer(mu, sizeof(mu));
|
|
1269
|
+
pq_secure_wipe(mu, sizeof(mu));
|
|
1270
|
+
return result;
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
static VALUE pqcrypto__native_mldsa_mu_builder_release(VALUE self, VALUE builder_obj) {
|
|
1274
|
+
(void)self;
|
|
1275
|
+
mu_builder_wrapper_t *wrapper;
|
|
1276
|
+
TypedData_Get_Struct(builder_obj, mu_builder_wrapper_t, &mu_builder_data_type, wrapper);
|
|
1277
|
+
if (wrapper != NULL && wrapper->builder != NULL) {
|
|
1278
|
+
pq_mu_builder_release(wrapper->builder);
|
|
1279
|
+
wrapper->builder = NULL;
|
|
1280
|
+
}
|
|
1281
|
+
return Qnil;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
static void *pq_sign_mu_nogvl(void *arg) {
|
|
1285
|
+
sign_mu_call_t *call = (sign_mu_call_t *)arg;
|
|
1286
|
+
call->result = pq_sign_mu(call->signature, &call->signature_len, call->mu, call->secret_key);
|
|
1287
|
+
return NULL;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
static VALUE pqcrypto__native_mldsa_sign_mu(VALUE self, VALUE mu, VALUE secret_key) {
|
|
1291
|
+
(void)self;
|
|
1292
|
+
pq_validate_bytes_argument(mu, PQ_MLDSA_MUBYTES, "mu");
|
|
1293
|
+
pq_validate_bytes_argument(secret_key, PQ_MLDSA_SECRETKEYBYTES, "secret key");
|
|
1294
|
+
|
|
1295
|
+
sign_mu_call_t call = {0};
|
|
1296
|
+
size_t secret_key_len = 0;
|
|
1297
|
+
size_t mu_len = 0;
|
|
1298
|
+
uint8_t *mu_copy = pq_copy_ruby_string(mu, &mu_len);
|
|
1299
|
+
uint8_t *sk_copy = pq_copy_ruby_string(secret_key, &secret_key_len);
|
|
1300
|
+
|
|
1301
|
+
call.mu = mu_copy;
|
|
1302
|
+
call.secret_key = sk_copy;
|
|
1303
|
+
call.signature_len = PQ_MLDSA_BYTES;
|
|
1304
|
+
call.signature = pq_alloc_buffer(PQ_MLDSA_BYTES);
|
|
1305
|
+
|
|
1306
|
+
rb_nogvl(pq_sign_mu_nogvl, &call, NULL, NULL, RB_NOGVL_OFFLOAD_SAFE);
|
|
1307
|
+
|
|
1308
|
+
pq_wipe_and_free(mu_copy, mu_len);
|
|
1309
|
+
pq_wipe_and_free(sk_copy, secret_key_len);
|
|
1310
|
+
|
|
1311
|
+
if (call.result != PQ_SUCCESS) {
|
|
1312
|
+
pq_free_buffer(call.signature);
|
|
1313
|
+
pq_raise_general_error(call.result);
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
VALUE result = pq_string_from_buffer(call.signature, call.signature_len);
|
|
1317
|
+
pq_free_buffer(call.signature);
|
|
1318
|
+
return result;
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
static void *pq_verify_mu_nogvl(void *arg) {
|
|
1322
|
+
verify_mu_call_t *call = (verify_mu_call_t *)arg;
|
|
1323
|
+
call->result = pq_verify_mu(call->signature, call->signature_len, call->mu, call->public_key);
|
|
1324
|
+
return NULL;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
static VALUE pqcrypto__native_mldsa_verify_mu(VALUE self, VALUE mu, VALUE signature,
|
|
1328
|
+
VALUE public_key) {
|
|
1329
|
+
(void)self;
|
|
1330
|
+
StringValue(signature);
|
|
1331
|
+
pq_validate_bytes_argument(mu, PQ_MLDSA_MUBYTES, "mu");
|
|
1332
|
+
pq_validate_bytes_argument(public_key, PQ_MLDSA_PUBLICKEYBYTES, "public key");
|
|
1333
|
+
|
|
1334
|
+
verify_mu_call_t call = {0};
|
|
1335
|
+
size_t public_key_len = 0;
|
|
1336
|
+
size_t signature_len = 0;
|
|
1337
|
+
size_t mu_len = 0;
|
|
1338
|
+
uint8_t *mu_copy = pq_copy_ruby_string(mu, &mu_len);
|
|
1339
|
+
uint8_t *pk_copy = pq_copy_ruby_string(public_key, &public_key_len);
|
|
1340
|
+
uint8_t *sig_copy = pq_copy_ruby_string(signature, &signature_len);
|
|
1341
|
+
|
|
1342
|
+
call.mu = mu_copy;
|
|
1343
|
+
call.public_key = pk_copy;
|
|
1344
|
+
call.signature = sig_copy;
|
|
1345
|
+
call.signature_len = signature_len;
|
|
1346
|
+
|
|
1347
|
+
rb_nogvl(pq_verify_mu_nogvl, &call, NULL, NULL, RB_NOGVL_OFFLOAD_SAFE);
|
|
1348
|
+
pq_wipe_and_free(mu_copy, mu_len);
|
|
1349
|
+
pq_free_buffer(pk_copy);
|
|
1350
|
+
pq_free_buffer(sig_copy);
|
|
1351
|
+
|
|
1352
|
+
if (call.result == PQ_SUCCESS) {
|
|
1353
|
+
return Qtrue;
|
|
1354
|
+
}
|
|
1355
|
+
if (call.result == PQ_ERROR_VERIFY) {
|
|
1356
|
+
return Qfalse;
|
|
1357
|
+
}
|
|
1358
|
+
pq_raise_general_error(call.result);
|
|
1359
|
+
}
|
|
1360
|
+
|
|
734
1361
|
static void define_constants(void) {
|
|
1362
|
+
rb_define_const(mPQCrypto, "ML_KEM_512_PUBLIC_KEY_BYTES", INT2NUM(MLKEM512_PUBLICKEYBYTES));
|
|
1363
|
+
rb_define_const(mPQCrypto, "ML_KEM_512_SECRET_KEY_BYTES", INT2NUM(MLKEM512_SECRETKEYBYTES));
|
|
1364
|
+
rb_define_const(mPQCrypto, "ML_KEM_512_CIPHERTEXT_BYTES", INT2NUM(MLKEM512_CIPHERTEXTBYTES));
|
|
1365
|
+
rb_define_const(mPQCrypto, "ML_KEM_512_SHARED_SECRET_BYTES",
|
|
1366
|
+
INT2NUM(MLKEM512_SHAREDSECRETBYTES));
|
|
735
1367
|
rb_define_const(mPQCrypto, "ML_KEM_PUBLIC_KEY_BYTES", INT2NUM(PQ_MLKEM_PUBLICKEYBYTES));
|
|
736
1368
|
rb_define_const(mPQCrypto, "ML_KEM_SECRET_KEY_BYTES", INT2NUM(PQ_MLKEM_SECRETKEYBYTES));
|
|
737
1369
|
rb_define_const(mPQCrypto, "ML_KEM_CIPHERTEXT_BYTES", INT2NUM(PQ_MLKEM_CIPHERTEXTBYTES));
|
|
738
1370
|
rb_define_const(mPQCrypto, "ML_KEM_SHARED_SECRET_BYTES", INT2NUM(PQ_MLKEM_SHAREDSECRETBYTES));
|
|
1371
|
+
rb_define_const(mPQCrypto, "ML_KEM_1024_PUBLIC_KEY_BYTES", INT2NUM(MLKEM1024_PUBLICKEYBYTES));
|
|
1372
|
+
rb_define_const(mPQCrypto, "ML_KEM_1024_SECRET_KEY_BYTES", INT2NUM(MLKEM1024_SECRETKEYBYTES));
|
|
1373
|
+
rb_define_const(mPQCrypto, "ML_KEM_1024_CIPHERTEXT_BYTES", INT2NUM(MLKEM1024_CIPHERTEXTBYTES));
|
|
1374
|
+
rb_define_const(mPQCrypto, "ML_KEM_1024_SHARED_SECRET_BYTES",
|
|
1375
|
+
INT2NUM(MLKEM1024_SHAREDSECRETBYTES));
|
|
739
1376
|
rb_define_const(mPQCrypto, "HYBRID_KEM_PUBLIC_KEY_BYTES", INT2NUM(PQ_HYBRID_PUBLICKEYBYTES));
|
|
740
1377
|
rb_define_const(mPQCrypto, "HYBRID_KEM_SECRET_KEY_BYTES", INT2NUM(PQ_HYBRID_SECRETKEYBYTES));
|
|
741
1378
|
rb_define_const(mPQCrypto, "HYBRID_KEM_CIPHERTEXT_BYTES", INT2NUM(PQ_HYBRID_CIPHERTEXTBYTES));
|
|
742
1379
|
rb_define_const(mPQCrypto, "HYBRID_KEM_SHARED_SECRET_BYTES",
|
|
743
1380
|
INT2NUM(PQ_HYBRID_SHAREDSECRETBYTES));
|
|
1381
|
+
rb_define_const(mPQCrypto, "SIGN_44_PUBLIC_KEY_BYTES", INT2NUM(MLDSA44_PUBLICKEYBYTES));
|
|
1382
|
+
rb_define_const(mPQCrypto, "SIGN_44_SECRET_KEY_BYTES", INT2NUM(MLDSA44_SECRETKEYBYTES));
|
|
1383
|
+
rb_define_const(mPQCrypto, "SIGN_44_BYTES", INT2NUM(MLDSA44_BYTES));
|
|
744
1384
|
rb_define_const(mPQCrypto, "SIGN_PUBLIC_KEY_BYTES", INT2NUM(PQ_MLDSA_PUBLICKEYBYTES));
|
|
745
1385
|
rb_define_const(mPQCrypto, "SIGN_SECRET_KEY_BYTES", INT2NUM(PQ_MLDSA_SECRETKEYBYTES));
|
|
746
1386
|
rb_define_const(mPQCrypto, "SIGN_BYTES", INT2NUM(PQ_MLDSA_BYTES));
|
|
1387
|
+
rb_define_const(mPQCrypto, "SIGN_87_PUBLIC_KEY_BYTES", INT2NUM(MLDSA87_PUBLICKEYBYTES));
|
|
1388
|
+
rb_define_const(mPQCrypto, "SIGN_87_SECRET_KEY_BYTES", INT2NUM(MLDSA87_SECRETKEYBYTES));
|
|
1389
|
+
rb_define_const(mPQCrypto, "SIGN_87_BYTES", INT2NUM(MLDSA87_BYTES));
|
|
747
1390
|
}
|
|
748
1391
|
|
|
749
1392
|
static VALUE pqcrypto_public_key_to_pqc_container_der(VALUE self, VALUE algorithm,
|
|
@@ -801,12 +1444,40 @@ void Init_pqcrypto_secure(void) {
|
|
|
801
1444
|
pqcrypto__test_ml_kem_keypair_from_seed, 1);
|
|
802
1445
|
rb_define_module_function(mPQCrypto, "__test_ml_kem_encapsulate_from_seed",
|
|
803
1446
|
pqcrypto__test_ml_kem_encapsulate_from_seed, 2);
|
|
1447
|
+
rb_define_module_function(mPQCrypto, "__test_ml_kem_512_encapsulate_from_seed",
|
|
1448
|
+
pqcrypto__test_ml_kem_512_encapsulate_from_seed, 2);
|
|
1449
|
+
rb_define_module_function(mPQCrypto, "__test_ml_kem_1024_encapsulate_from_seed",
|
|
1450
|
+
pqcrypto__test_ml_kem_1024_encapsulate_from_seed, 2);
|
|
804
1451
|
rb_define_module_function(mPQCrypto, "__test_sign_keypair_from_seed",
|
|
805
1452
|
pqcrypto__test_sign_keypair_from_seed, 1);
|
|
1453
|
+
rb_define_module_function(mPQCrypto, "__test_ml_dsa_44_keypair_from_seed",
|
|
1454
|
+
pqcrypto__test_ml_dsa_44_keypair_from_seed, 1);
|
|
1455
|
+
rb_define_module_function(mPQCrypto, "__test_ml_dsa_87_keypair_from_seed",
|
|
1456
|
+
pqcrypto__test_ml_dsa_87_keypair_from_seed, 1);
|
|
806
1457
|
rb_define_module_function(mPQCrypto, "__test_sign_from_seed", pqcrypto__test_sign_from_seed, 3);
|
|
1458
|
+
rb_define_module_function(mPQCrypto, "__test_ml_dsa_44_sign_from_seed",
|
|
1459
|
+
pqcrypto__test_ml_dsa_44_sign_from_seed, 3);
|
|
1460
|
+
rb_define_module_function(mPQCrypto, "__test_ml_dsa_87_sign_from_seed",
|
|
1461
|
+
pqcrypto__test_ml_dsa_87_sign_from_seed, 3);
|
|
807
1462
|
rb_define_module_function(mPQCrypto, "ml_kem_keypair", pqcrypto_ml_kem_keypair, 0);
|
|
1463
|
+
rb_define_module_function(mPQCrypto, "ml_kem_keypair_from_seed",
|
|
1464
|
+
pqcrypto_ml_kem_keypair_from_seed, 1);
|
|
808
1465
|
rb_define_module_function(mPQCrypto, "ml_kem_encapsulate", pqcrypto_ml_kem_encapsulate, 1);
|
|
809
1466
|
rb_define_module_function(mPQCrypto, "ml_kem_decapsulate", pqcrypto_ml_kem_decapsulate, 2);
|
|
1467
|
+
rb_define_module_function(mPQCrypto, "ml_kem_512_keypair", pqcrypto_ml_kem_512_keypair, 0);
|
|
1468
|
+
rb_define_module_function(mPQCrypto, "ml_kem_512_keypair_from_seed",
|
|
1469
|
+
pqcrypto_ml_kem_512_keypair_from_seed, 1);
|
|
1470
|
+
rb_define_module_function(mPQCrypto, "ml_kem_512_encapsulate", pqcrypto_ml_kem_512_encapsulate,
|
|
1471
|
+
1);
|
|
1472
|
+
rb_define_module_function(mPQCrypto, "ml_kem_512_decapsulate", pqcrypto_ml_kem_512_decapsulate,
|
|
1473
|
+
2);
|
|
1474
|
+
rb_define_module_function(mPQCrypto, "ml_kem_1024_keypair", pqcrypto_ml_kem_1024_keypair, 0);
|
|
1475
|
+
rb_define_module_function(mPQCrypto, "ml_kem_1024_keypair_from_seed",
|
|
1476
|
+
pqcrypto_ml_kem_1024_keypair_from_seed, 1);
|
|
1477
|
+
rb_define_module_function(mPQCrypto, "ml_kem_1024_encapsulate",
|
|
1478
|
+
pqcrypto_ml_kem_1024_encapsulate, 1);
|
|
1479
|
+
rb_define_module_function(mPQCrypto, "ml_kem_1024_decapsulate",
|
|
1480
|
+
pqcrypto_ml_kem_1024_decapsulate, 2);
|
|
810
1481
|
rb_define_module_function(mPQCrypto, "hybrid_kem_keypair", pqcrypto_hybrid_kem_keypair, 0);
|
|
811
1482
|
rb_define_module_function(mPQCrypto, "hybrid_kem_encapsulate", pqcrypto_hybrid_kem_encapsulate,
|
|
812
1483
|
1);
|
|
@@ -815,6 +1486,18 @@ void Init_pqcrypto_secure(void) {
|
|
|
815
1486
|
rb_define_module_function(mPQCrypto, "sign_keypair", pqcrypto_sign_keypair, 0);
|
|
816
1487
|
rb_define_module_function(mPQCrypto, "sign", pqcrypto_sign, 2);
|
|
817
1488
|
rb_define_module_function(mPQCrypto, "verify", pqcrypto_verify, 3);
|
|
1489
|
+
rb_define_module_function(mPQCrypto, "ml_dsa_44_keypair", pqcrypto_ml_dsa_44_keypair, 0);
|
|
1490
|
+
rb_define_module_function(mPQCrypto, "ml_dsa_44_keypair_from_seed",
|
|
1491
|
+
pqcrypto_ml_dsa_44_keypair_from_seed, 1);
|
|
1492
|
+
rb_define_module_function(mPQCrypto, "ml_dsa_keypair_from_seed",
|
|
1493
|
+
pqcrypto_ml_dsa_keypair_from_seed, 1);
|
|
1494
|
+
rb_define_module_function(mPQCrypto, "ml_dsa_44_sign", pqcrypto_ml_dsa_44_sign, 2);
|
|
1495
|
+
rb_define_module_function(mPQCrypto, "ml_dsa_44_verify", pqcrypto_ml_dsa_44_verify, 3);
|
|
1496
|
+
rb_define_module_function(mPQCrypto, "ml_dsa_87_keypair", pqcrypto_ml_dsa_87_keypair, 0);
|
|
1497
|
+
rb_define_module_function(mPQCrypto, "ml_dsa_87_keypair_from_seed",
|
|
1498
|
+
pqcrypto_ml_dsa_87_keypair_from_seed, 1);
|
|
1499
|
+
rb_define_module_function(mPQCrypto, "ml_dsa_87_sign", pqcrypto_ml_dsa_87_sign, 2);
|
|
1500
|
+
rb_define_module_function(mPQCrypto, "ml_dsa_87_verify", pqcrypto_ml_dsa_87_verify, 3);
|
|
818
1501
|
rb_define_module_function(mPQCrypto, "ct_equals", pqcrypto_ct_equals, 2);
|
|
819
1502
|
rb_define_module_function(mPQCrypto, "secure_wipe", pqcrypto_secure_wipe, 1);
|
|
820
1503
|
rb_define_module_function(mPQCrypto, "version", pqcrypto_version, 0);
|
|
@@ -834,6 +1517,22 @@ void Init_pqcrypto_secure(void) {
|
|
|
834
1517
|
pqcrypto_secret_key_from_pqc_container_der, 1);
|
|
835
1518
|
rb_define_module_function(mPQCrypto, "secret_key_from_pqc_container_pem",
|
|
836
1519
|
pqcrypto_secret_key_from_pqc_container_pem, 1);
|
|
1520
|
+
rb_define_module_function(mPQCrypto, "_native_mldsa_extract_tr",
|
|
1521
|
+
pqcrypto__native_mldsa_extract_tr, 1);
|
|
1522
|
+
rb_define_module_function(mPQCrypto, "_native_mldsa_compute_tr",
|
|
1523
|
+
pqcrypto__native_mldsa_compute_tr, 1);
|
|
1524
|
+
rb_define_module_function(mPQCrypto, "_native_mldsa_mu_builder_new",
|
|
1525
|
+
pqcrypto__native_mldsa_mu_builder_new, 2);
|
|
1526
|
+
rb_define_module_function(mPQCrypto, "_native_mldsa_mu_builder_update",
|
|
1527
|
+
pqcrypto__native_mldsa_mu_builder_update, 2);
|
|
1528
|
+
rb_define_module_function(mPQCrypto, "_native_mldsa_mu_builder_finalize",
|
|
1529
|
+
pqcrypto__native_mldsa_mu_builder_finalize, 1);
|
|
1530
|
+
rb_define_module_function(mPQCrypto, "_native_mldsa_mu_builder_release",
|
|
1531
|
+
pqcrypto__native_mldsa_mu_builder_release, 1);
|
|
1532
|
+
rb_define_module_function(mPQCrypto, "_native_mldsa_sign_mu", pqcrypto__native_mldsa_sign_mu,
|
|
1533
|
+
2);
|
|
1534
|
+
rb_define_module_function(mPQCrypto, "_native_mldsa_verify_mu",
|
|
1535
|
+
pqcrypto__native_mldsa_verify_mu, 3);
|
|
837
1536
|
|
|
838
1537
|
define_constants();
|
|
839
1538
|
}
|