pq_crypto 0.5.3 → 0.6.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.
@@ -81,6 +81,8 @@ typedef struct {
81
81
  size_t signature_len;
82
82
  uint8_t *message;
83
83
  size_t message_len;
84
+ uint8_t *context;
85
+ size_t context_len;
84
86
  const uint8_t *secret_key;
85
87
  const uint8_t *seed;
86
88
  size_t seed_len;
@@ -92,6 +94,8 @@ typedef struct {
92
94
  size_t signature_len;
93
95
  uint8_t *message;
94
96
  size_t message_len;
97
+ uint8_t *context;
98
+ size_t context_len;
95
99
  const uint8_t *public_key;
96
100
  } verify_call_t;
97
101
 
@@ -153,6 +157,52 @@ static const char *const PQC_CONTAINER_ALGORITHMS[] = {
153
157
  static ID pqc_container_algorithm_ids[sizeof(PQC_CONTAINER_ALGORITHMS) /
154
158
  sizeof(PQC_CONTAINER_ALGORITHMS[0])];
155
159
 
160
+ typedef int (*pq_mldsa_pk_from_sk_fn)(uint8_t *, const uint8_t *);
161
+ typedef int (*pq_mldsa_signature_extmu_fn)(uint8_t *, size_t *, const uint8_t *, const uint8_t *);
162
+ typedef int (*pq_mldsa_verify_extmu_fn)(const uint8_t *, size_t, const uint8_t *, const uint8_t *);
163
+
164
+ typedef struct {
165
+ const char *name;
166
+ size_t public_key_len;
167
+ size_t secret_key_len;
168
+ size_t signature_len;
169
+ pq_mldsa_pk_from_sk_fn pk_from_sk;
170
+ pq_mldsa_signature_extmu_fn signature_extmu;
171
+ pq_mldsa_verify_extmu_fn verify_extmu;
172
+ } pq_mldsa_profile_t;
173
+
174
+ static const pq_mldsa_profile_t MLDSA_PROFILES[] = {
175
+ {"ml_dsa_44", MLDSA44_PUBLICKEYBYTES, MLDSA44_SECRETKEYBYTES, MLDSA44_BYTES,
176
+ pqcr_mldsa44_pk_from_sk, pqcr_mldsa44_signature_extmu, pqcr_mldsa44_verify_extmu},
177
+ {"ml_dsa_65", MLDSA65_PUBLICKEYBYTES, MLDSA65_SECRETKEYBYTES, MLDSA65_BYTES,
178
+ pqcr_mldsa65_pk_from_sk, pqcr_mldsa65_signature_extmu, pqcr_mldsa65_verify_extmu},
179
+ {"ml_dsa_87", MLDSA87_PUBLICKEYBYTES, MLDSA87_SECRETKEYBYTES, MLDSA87_BYTES,
180
+ pqcr_mldsa87_pk_from_sk, pqcr_mldsa87_signature_extmu, pqcr_mldsa87_verify_extmu},
181
+ };
182
+
183
+ static const pq_mldsa_profile_t *pq_mldsa_profile_from_value(VALUE algorithm) {
184
+ ID id;
185
+ const char *name;
186
+
187
+ if (!SYMBOL_P(algorithm)) {
188
+ rb_raise(rb_eArgError, "ML-DSA algorithm must be a Symbol");
189
+ }
190
+
191
+ id = SYM2ID(algorithm);
192
+ name = rb_id2name(id);
193
+ if (!name) {
194
+ rb_raise(rb_eArgError, "Invalid ML-DSA algorithm symbol");
195
+ }
196
+
197
+ for (size_t i = 0; i < sizeof(MLDSA_PROFILES) / sizeof(MLDSA_PROFILES[0]); ++i) {
198
+ if (strcmp(name, MLDSA_PROFILES[i].name) == 0) {
199
+ return &MLDSA_PROFILES[i];
200
+ }
201
+ }
202
+
203
+ rb_raise(ePQCryptoError, "Unsupported ML-DSA algorithm: %s", name);
204
+ }
205
+
156
206
  static void pq_init_algorithm_ids(void) {
157
207
  for (size_t i = 0; i < sizeof(PQC_CONTAINER_ALGORITHMS) / sizeof(PQC_CONTAINER_ALGORITHMS[0]);
158
208
  ++i) {
@@ -320,12 +370,13 @@ PQ_DEFINE_SIGN_KEYPAIR_FROM_SEED_NOGVL(mldsa_87_keypair_from_seed, pq_mldsa87_ke
320
370
 
321
371
  #undef PQ_DEFINE_SIGN_KEYPAIR_FROM_SEED_NOGVL
322
372
 
323
- #define PQ_DEFINE_SIGN_NOGVL(rb_name, c_call) \
324
- static void *pq_##rb_name##_nogvl(void *arg) { \
325
- sign_call_t *call = (sign_call_t *)arg; \
326
- call->result = c_call(call->signature, &call->signature_len, call->message, \
327
- call->message_len, call->secret_key); \
328
- return NULL; \
373
+ #define PQ_DEFINE_SIGN_NOGVL(rb_name, c_call) \
374
+ static void *pq_##rb_name##_nogvl(void *arg) { \
375
+ sign_call_t *call = (sign_call_t *)arg; \
376
+ call->result = \
377
+ c_call(call->signature, &call->signature_len, call->message, call->message_len, \
378
+ call->context, call->context_len, call->secret_key); \
379
+ return NULL; \
329
380
  }
330
381
 
331
382
  PQ_DEFINE_SIGN_NOGVL(sign, pq_sign)
@@ -373,12 +424,13 @@ PQ_DEFINE_TESTING_SIGN_FROM_SEED(mldsa_87, pq_testing_mldsa87_sign_from_seed)
373
424
  #undef PQ_DEFINE_TESTING_KEYPAIR_FROM_SEED
374
425
  #undef PQ_DEFINE_TESTING_SIGN_FROM_SEED
375
426
 
376
- #define PQ_DEFINE_VERIFY_NOGVL(rb_name, c_call) \
377
- static void *pq_##rb_name##_nogvl(void *arg) { \
378
- verify_call_t *call = (verify_call_t *)arg; \
379
- call->result = c_call(call->signature, call->signature_len, call->message, \
380
- call->message_len, call->public_key); \
381
- return NULL; \
427
+ #define PQ_DEFINE_VERIFY_NOGVL(rb_name, c_call) \
428
+ static void *pq_##rb_name##_nogvl(void *arg) { \
429
+ verify_call_t *call = (verify_call_t *)arg; \
430
+ call->result = \
431
+ c_call(call->signature, call->signature_len, call->message, call->message_len, \
432
+ call->context, call->context_len, call->public_key); \
433
+ return NULL; \
382
434
  }
383
435
 
384
436
  PQ_DEFINE_VERIFY_NOGVL(verify, pq_verify)
@@ -812,6 +864,26 @@ static VALUE pqcrypto_hybrid_kem_expand_secret_key_object(VALUE self, VALUE secr
812
864
  return obj;
813
865
  }
814
866
 
867
+ static VALUE pqcrypto_hybrid_kem_expanded_secret_key_wipe(VALUE self,
868
+ VALUE expanded_secret_key_obj) {
869
+ (void)self;
870
+ hybrid_expanded_key_wrapper_t *wrapper;
871
+
872
+ TypedData_Get_Struct(expanded_secret_key_obj, hybrid_expanded_key_wrapper_t,
873
+ &hybrid_expanded_key_data_type, wrapper);
874
+ if (!wrapper) {
875
+ return Qnil;
876
+ }
877
+
878
+ pq_secure_wipe(wrapper->expanded_secret_key, sizeof(wrapper->expanded_secret_key));
879
+ if (wrapper->x25519_private_pkey) {
880
+ EVP_PKEY_free(wrapper->x25519_private_pkey);
881
+ wrapper->x25519_private_pkey = NULL;
882
+ }
883
+
884
+ return Qnil;
885
+ }
886
+
815
887
  static VALUE pqcrypto_hybrid_kem_decapsulate(VALUE self, VALUE ciphertext, VALUE secret_key) {
816
888
  (void)self;
817
889
  return pq_run_kem_decapsulate(pq_hybrid_kem_decapsulate_nogvl, ciphertext,
@@ -1181,20 +1253,28 @@ PQ_DEFINE_RUBY_MLDSA_KEYPAIR(ml_dsa_87_keypair, mldsa_87_sign_keypair, MLDSA87_P
1181
1253
 
1182
1254
  #undef PQ_DEFINE_RUBY_MLDSA_KEYPAIR
1183
1255
 
1184
- static VALUE pq_run_sign(void *(*nogvl)(void *), VALUE message, VALUE secret_key,
1256
+ static VALUE pq_run_sign(void *(*nogvl)(void *), VALUE message, VALUE secret_key, VALUE context,
1185
1257
  size_t secret_key_len_expected, size_t signature_len_expected) {
1186
1258
  pq_validate_bytes_argument(secret_key, secret_key_len_expected, "secret key");
1259
+ StringValue(context);
1260
+ if (RSTRING_LEN(context) > 255) {
1261
+ rb_raise(rb_eArgError, "ML-DSA context length must be <= 255 bytes");
1262
+ }
1187
1263
 
1188
1264
  sign_call_t call = {0};
1189
1265
  size_t secret_key_len = 0;
1266
+ size_t context_len = 0;
1190
1267
  call.secret_key = pq_copy_ruby_string(secret_key, &secret_key_len);
1191
1268
  call.signature_len = signature_len_expected;
1192
1269
  call.signature = pq_alloc_buffer(signature_len_expected);
1193
1270
  call.message = pq_copy_ruby_string(message, &call.message_len);
1271
+ call.context = pq_copy_ruby_string(context, &context_len);
1272
+ call.context_len = context_len;
1194
1273
 
1195
1274
  rb_nogvl(nogvl, &call, NULL, NULL, PQ_RB_NOGVL_OFFLOAD_SAFE);
1196
1275
 
1197
1276
  pq_free_buffer(call.message);
1277
+ pq_free_buffer(call.context);
1198
1278
  pq_wipe_and_free((uint8_t *)call.secret_key, secret_key_len);
1199
1279
 
1200
1280
  if (call.result != PQ_SUCCESS) {
@@ -1207,10 +1287,16 @@ static VALUE pq_run_sign(void *(*nogvl)(void *), VALUE message, VALUE secret_key
1207
1287
  return result;
1208
1288
  }
1209
1289
 
1210
- #define PQ_DEFINE_RUBY_MLDSA_SIGN(rb_name, nogvl_stem, sk_bytes, sig_bytes) \
1211
- static VALUE pqcrypto_##rb_name(VALUE self, VALUE message, VALUE secret_key) { \
1212
- (void)self; \
1213
- return pq_run_sign(pq_##nogvl_stem##_nogvl, message, secret_key, sk_bytes, sig_bytes); \
1290
+ #define PQ_DEFINE_RUBY_MLDSA_SIGN(rb_name, nogvl_stem, sk_bytes, sig_bytes) \
1291
+ static VALUE pqcrypto_##rb_name(int argc, VALUE *argv, VALUE self) { \
1292
+ (void)self; \
1293
+ VALUE message, secret_key, context; \
1294
+ rb_scan_args(argc, argv, "21", &message, &secret_key, &context); \
1295
+ if (NIL_P(context)) { \
1296
+ context = rb_str_new("", 0); \
1297
+ } \
1298
+ return pq_run_sign(pq_##nogvl_stem##_nogvl, message, secret_key, context, sk_bytes, \
1299
+ sig_bytes); \
1214
1300
  }
1215
1301
 
1216
1302
  PQ_DEFINE_RUBY_MLDSA_SIGN(sign, sign, PQ_MLDSA_SECRETKEYBYTES, PQ_MLDSA_BYTES)
@@ -1220,21 +1306,29 @@ PQ_DEFINE_RUBY_MLDSA_SIGN(ml_dsa_87_sign, mldsa_87_sign, MLDSA87_SECRETKEYBYTES,
1220
1306
  #undef PQ_DEFINE_RUBY_MLDSA_SIGN
1221
1307
 
1222
1308
  static VALUE pq_run_verify(void *(*nogvl)(void *), VALUE message, VALUE signature, VALUE public_key,
1223
- size_t public_key_len_expected) {
1309
+ VALUE context, size_t public_key_len_expected) {
1224
1310
  StringValue(signature);
1225
1311
  pq_validate_bytes_argument(public_key, public_key_len_expected, "public key");
1312
+ StringValue(context);
1313
+ if (RSTRING_LEN(context) > 255) {
1314
+ rb_raise(rb_eArgError, "ML-DSA context length must be <= 255 bytes");
1315
+ }
1226
1316
 
1227
1317
  verify_call_t call = {0};
1228
1318
  size_t public_key_len = 0;
1229
1319
  size_t signature_len = 0;
1320
+ size_t context_len = 0;
1230
1321
  call.public_key = pq_copy_ruby_string(public_key, &public_key_len);
1231
1322
  call.signature = pq_copy_ruby_string(signature, &signature_len);
1232
1323
  call.signature_len = signature_len;
1233
1324
  call.message = pq_copy_ruby_string(message, &call.message_len);
1325
+ call.context = pq_copy_ruby_string(context, &context_len);
1326
+ call.context_len = context_len;
1234
1327
 
1235
1328
  rb_nogvl(nogvl, &call, NULL, NULL, PQ_RB_NOGVL_OFFLOAD_SAFE);
1236
1329
 
1237
1330
  pq_free_buffer(call.message);
1331
+ pq_free_buffer(call.context);
1238
1332
  pq_free_buffer((uint8_t *)call.public_key);
1239
1333
  pq_free_buffer((uint8_t *)call.signature);
1240
1334
 
@@ -1247,11 +1341,16 @@ static VALUE pq_run_verify(void *(*nogvl)(void *), VALUE message, VALUE signatur
1247
1341
  pq_raise_general_error(call.result);
1248
1342
  }
1249
1343
 
1250
- #define PQ_DEFINE_RUBY_MLDSA_VERIFY(rb_name, nogvl_stem, pk_bytes) \
1251
- static VALUE pqcrypto_##rb_name(VALUE self, VALUE message, VALUE signature, \
1252
- VALUE public_key) { \
1253
- (void)self; \
1254
- return pq_run_verify(pq_##nogvl_stem##_nogvl, message, signature, public_key, pk_bytes); \
1344
+ #define PQ_DEFINE_RUBY_MLDSA_VERIFY(rb_name, nogvl_stem, pk_bytes) \
1345
+ static VALUE pqcrypto_##rb_name(int argc, VALUE *argv, VALUE self) { \
1346
+ (void)self; \
1347
+ VALUE message, signature, public_key, context; \
1348
+ rb_scan_args(argc, argv, "31", &message, &signature, &public_key, &context); \
1349
+ if (NIL_P(context)) { \
1350
+ context = rb_str_new("", 0); \
1351
+ } \
1352
+ return pq_run_verify(pq_##nogvl_stem##_nogvl, message, signature, public_key, context, \
1353
+ pk_bytes); \
1255
1354
  }
1256
1355
 
1257
1356
  PQ_DEFINE_RUBY_MLDSA_VERIFY(verify, verify, PQ_MLDSA_PUBLICKEYBYTES)
@@ -1312,6 +1411,7 @@ typedef struct {
1312
1411
  size_t signature_len;
1313
1412
  const uint8_t *mu;
1314
1413
  const uint8_t *secret_key;
1414
+ pq_mldsa_signature_extmu_fn signature_extmu;
1315
1415
  } sign_mu_call_t;
1316
1416
 
1317
1417
  typedef struct {
@@ -1320,6 +1420,8 @@ typedef struct {
1320
1420
  size_t signature_len;
1321
1421
  const uint8_t *mu;
1322
1422
  const uint8_t *public_key;
1423
+ size_t expected_signature_len;
1424
+ pq_mldsa_verify_extmu_fn verify_extmu;
1323
1425
  } verify_mu_call_t;
1324
1426
 
1325
1427
  static void mu_builder_wrapper_free(void *ptr) {
@@ -1363,12 +1465,25 @@ static mu_builder_wrapper_t *mu_builder_unwrap(VALUE obj) {
1363
1465
  return wrapper;
1364
1466
  }
1365
1467
 
1366
- static VALUE pqcrypto__native_mldsa_extract_tr(VALUE self, VALUE secret_key) {
1468
+ static VALUE pqcrypto__native_mldsa_extract_tr(int argc, VALUE *argv, VALUE self) {
1367
1469
  (void)self;
1368
- pq_validate_bytes_argument(secret_key, PQ_MLDSA_SECRETKEYBYTES, "secret key");
1470
+ VALUE algorithm = ID2SYM(rb_intern("ml_dsa_65"));
1471
+ VALUE secret_key;
1472
+ if (argc == 1) {
1473
+ secret_key = argv[0];
1474
+ } else if (argc == 2) {
1475
+ algorithm = argv[0];
1476
+ secret_key = argv[1];
1477
+ } else {
1478
+ rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1..2)", argc);
1479
+ }
1480
+
1481
+ const pq_mldsa_profile_t *profile = pq_mldsa_profile_from_value(algorithm);
1482
+ pq_validate_bytes_argument(secret_key, profile->secret_key_len, "secret key");
1369
1483
 
1370
1484
  uint8_t tr[PQ_MLDSA_TRBYTES];
1371
- int rc = pq_mldsa_extract_tr_from_secret_key(tr, (const uint8_t *)RSTRING_PTR(secret_key));
1485
+ int rc = pq_mldsa_extract_tr_from_secret_key(tr, (const uint8_t *)RSTRING_PTR(secret_key),
1486
+ profile->public_key_len, profile->pk_from_sk);
1372
1487
  if (rc != PQ_SUCCESS) {
1373
1488
  pq_secure_wipe(tr, sizeof(tr));
1374
1489
  pq_raise_general_error(rc);
@@ -1378,12 +1493,25 @@ static VALUE pqcrypto__native_mldsa_extract_tr(VALUE self, VALUE secret_key) {
1378
1493
  return result;
1379
1494
  }
1380
1495
 
1381
- static VALUE pqcrypto__native_mldsa_compute_tr(VALUE self, VALUE public_key) {
1496
+ static VALUE pqcrypto__native_mldsa_compute_tr(int argc, VALUE *argv, VALUE self) {
1382
1497
  (void)self;
1383
- pq_validate_bytes_argument(public_key, PQ_MLDSA_PUBLICKEYBYTES, "public key");
1498
+ VALUE algorithm = ID2SYM(rb_intern("ml_dsa_65"));
1499
+ VALUE public_key;
1500
+ if (argc == 1) {
1501
+ public_key = argv[0];
1502
+ } else if (argc == 2) {
1503
+ algorithm = argv[0];
1504
+ public_key = argv[1];
1505
+ } else {
1506
+ rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1..2)", argc);
1507
+ }
1508
+
1509
+ const pq_mldsa_profile_t *profile = pq_mldsa_profile_from_value(algorithm);
1510
+ pq_validate_bytes_argument(public_key, profile->public_key_len, "public key");
1384
1511
 
1385
1512
  uint8_t tr[PQ_MLDSA_TRBYTES];
1386
- int rc = pq_mldsa_compute_tr_from_public_key(tr, (const uint8_t *)RSTRING_PTR(public_key));
1513
+ int rc = pq_mldsa_compute_tr_from_public_key(tr, (const uint8_t *)RSTRING_PTR(public_key),
1514
+ profile->public_key_len);
1387
1515
  if (rc != PQ_SUCCESS) {
1388
1516
  pq_raise_general_error(rc);
1389
1517
  }
@@ -1504,14 +1632,29 @@ static VALUE pqcrypto__native_mldsa_mu_builder_release(VALUE self, VALUE builder
1504
1632
 
1505
1633
  static void *pq_sign_mu_nogvl(void *arg) {
1506
1634
  sign_mu_call_t *call = (sign_mu_call_t *)arg;
1507
- call->result = pq_sign_mu(call->signature, &call->signature_len, call->mu, call->secret_key);
1635
+ call->result = pq_sign_mu(call->signature, &call->signature_len, call->mu, call->secret_key,
1636
+ call->signature_extmu);
1508
1637
  return NULL;
1509
1638
  }
1510
1639
 
1511
- static VALUE pqcrypto__native_mldsa_sign_mu(VALUE self, VALUE mu, VALUE secret_key) {
1640
+ static VALUE pqcrypto__native_mldsa_sign_mu(int argc, VALUE *argv, VALUE self) {
1512
1641
  (void)self;
1642
+ VALUE algorithm = ID2SYM(rb_intern("ml_dsa_65"));
1643
+ VALUE mu, secret_key;
1644
+ if (argc == 2) {
1645
+ mu = argv[0];
1646
+ secret_key = argv[1];
1647
+ } else if (argc == 3) {
1648
+ algorithm = argv[0];
1649
+ mu = argv[1];
1650
+ secret_key = argv[2];
1651
+ } else {
1652
+ rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 2..3)", argc);
1653
+ }
1654
+
1655
+ const pq_mldsa_profile_t *profile = pq_mldsa_profile_from_value(algorithm);
1513
1656
  pq_validate_bytes_argument(mu, PQ_MLDSA_MUBYTES, "mu");
1514
- pq_validate_bytes_argument(secret_key, PQ_MLDSA_SECRETKEYBYTES, "secret key");
1657
+ pq_validate_bytes_argument(secret_key, profile->secret_key_len, "secret key");
1515
1658
 
1516
1659
  sign_mu_call_t call = {0};
1517
1660
  size_t secret_key_len = 0;
@@ -1521,8 +1664,9 @@ static VALUE pqcrypto__native_mldsa_sign_mu(VALUE self, VALUE mu, VALUE secret_k
1521
1664
 
1522
1665
  call.mu = mu_copy;
1523
1666
  call.secret_key = sk_copy;
1524
- call.signature_len = PQ_MLDSA_BYTES;
1525
- call.signature = pq_alloc_buffer(PQ_MLDSA_BYTES);
1667
+ call.signature_extmu = profile->signature_extmu;
1668
+ call.signature_len = profile->signature_len;
1669
+ call.signature = pq_alloc_buffer(profile->signature_len);
1526
1670
 
1527
1671
  rb_nogvl(pq_sign_mu_nogvl, &call, NULL, NULL, PQ_RB_NOGVL_OFFLOAD_SAFE);
1528
1672
 
@@ -1541,16 +1685,32 @@ static VALUE pqcrypto__native_mldsa_sign_mu(VALUE self, VALUE mu, VALUE secret_k
1541
1685
 
1542
1686
  static void *pq_verify_mu_nogvl(void *arg) {
1543
1687
  verify_mu_call_t *call = (verify_mu_call_t *)arg;
1544
- call->result = pq_verify_mu(call->signature, call->signature_len, call->mu, call->public_key);
1688
+ call->result = pq_verify_mu(call->signature, call->signature_len, call->mu, call->public_key,
1689
+ call->expected_signature_len, call->verify_extmu);
1545
1690
  return NULL;
1546
1691
  }
1547
1692
 
1548
- static VALUE pqcrypto__native_mldsa_verify_mu(VALUE self, VALUE mu, VALUE signature,
1549
- VALUE public_key) {
1693
+ static VALUE pqcrypto__native_mldsa_verify_mu(int argc, VALUE *argv, VALUE self) {
1550
1694
  (void)self;
1695
+ VALUE algorithm = ID2SYM(rb_intern("ml_dsa_65"));
1696
+ VALUE mu, signature, public_key;
1697
+ if (argc == 3) {
1698
+ mu = argv[0];
1699
+ signature = argv[1];
1700
+ public_key = argv[2];
1701
+ } else if (argc == 4) {
1702
+ algorithm = argv[0];
1703
+ mu = argv[1];
1704
+ signature = argv[2];
1705
+ public_key = argv[3];
1706
+ } else {
1707
+ rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 3..4)", argc);
1708
+ }
1709
+
1710
+ const pq_mldsa_profile_t *profile = pq_mldsa_profile_from_value(algorithm);
1551
1711
  StringValue(signature);
1552
1712
  pq_validate_bytes_argument(mu, PQ_MLDSA_MUBYTES, "mu");
1553
- pq_validate_bytes_argument(public_key, PQ_MLDSA_PUBLICKEYBYTES, "public key");
1713
+ pq_validate_bytes_argument(public_key, profile->public_key_len, "public key");
1554
1714
 
1555
1715
  verify_mu_call_t call = {0};
1556
1716
  size_t public_key_len = 0;
@@ -1564,6 +1724,8 @@ static VALUE pqcrypto__native_mldsa_verify_mu(VALUE self, VALUE mu, VALUE signat
1564
1724
  call.public_key = pk_copy;
1565
1725
  call.signature = sig_copy;
1566
1726
  call.signature_len = signature_len;
1727
+ call.expected_signature_len = profile->signature_len;
1728
+ call.verify_extmu = profile->verify_extmu;
1567
1729
 
1568
1730
  rb_nogvl(pq_verify_mu_nogvl, &call, NULL, NULL, PQ_RB_NOGVL_OFFLOAD_SAFE);
1569
1731
  pq_wipe_and_free(mu_copy, mu_len);
@@ -1707,6 +1869,8 @@ void Init_pqcrypto_secure(void) {
1707
1869
  pqcrypto_hybrid_kem_expand_secret_key, 1);
1708
1870
  rb_define_module_function(mPQCrypto, "hybrid_kem_expand_secret_key_object",
1709
1871
  pqcrypto_hybrid_kem_expand_secret_key_object, 1);
1872
+ rb_define_module_function(mPQCrypto, "hybrid_kem_expanded_secret_key_wipe",
1873
+ pqcrypto_hybrid_kem_expanded_secret_key_wipe, 1);
1710
1874
  rb_define_module_function(mPQCrypto, "hybrid_kem_decapsulate", pqcrypto_hybrid_kem_decapsulate,
1711
1875
  2);
1712
1876
  rb_define_module_function(mPQCrypto, "hybrid_kem_decapsulate_expanded",
@@ -1714,20 +1878,20 @@ void Init_pqcrypto_secure(void) {
1714
1878
  rb_define_module_function(mPQCrypto, "hybrid_kem_decapsulate_expanded_object",
1715
1879
  pqcrypto_hybrid_kem_decapsulate_expanded_object, 2);
1716
1880
  rb_define_module_function(mPQCrypto, "sign_keypair", pqcrypto_sign_keypair, 0);
1717
- rb_define_module_function(mPQCrypto, "sign", pqcrypto_sign, 2);
1718
- rb_define_module_function(mPQCrypto, "verify", pqcrypto_verify, 3);
1881
+ rb_define_module_function(mPQCrypto, "sign", pqcrypto_sign, -1);
1882
+ rb_define_module_function(mPQCrypto, "verify", pqcrypto_verify, -1);
1719
1883
  rb_define_module_function(mPQCrypto, "ml_dsa_44_keypair", pqcrypto_ml_dsa_44_keypair, 0);
1720
1884
  rb_define_module_function(mPQCrypto, "ml_dsa_44_keypair_from_seed",
1721
1885
  pqcrypto_ml_dsa_44_keypair_from_seed, 1);
1722
1886
  rb_define_module_function(mPQCrypto, "ml_dsa_keypair_from_seed",
1723
1887
  pqcrypto_ml_dsa_keypair_from_seed, 1);
1724
- rb_define_module_function(mPQCrypto, "ml_dsa_44_sign", pqcrypto_ml_dsa_44_sign, 2);
1725
- rb_define_module_function(mPQCrypto, "ml_dsa_44_verify", pqcrypto_ml_dsa_44_verify, 3);
1888
+ rb_define_module_function(mPQCrypto, "ml_dsa_44_sign", pqcrypto_ml_dsa_44_sign, -1);
1889
+ rb_define_module_function(mPQCrypto, "ml_dsa_44_verify", pqcrypto_ml_dsa_44_verify, -1);
1726
1890
  rb_define_module_function(mPQCrypto, "ml_dsa_87_keypair", pqcrypto_ml_dsa_87_keypair, 0);
1727
1891
  rb_define_module_function(mPQCrypto, "ml_dsa_87_keypair_from_seed",
1728
1892
  pqcrypto_ml_dsa_87_keypair_from_seed, 1);
1729
- rb_define_module_function(mPQCrypto, "ml_dsa_87_sign", pqcrypto_ml_dsa_87_sign, 2);
1730
- rb_define_module_function(mPQCrypto, "ml_dsa_87_verify", pqcrypto_ml_dsa_87_verify, 3);
1893
+ rb_define_module_function(mPQCrypto, "ml_dsa_87_sign", pqcrypto_ml_dsa_87_sign, -1);
1894
+ rb_define_module_function(mPQCrypto, "ml_dsa_87_verify", pqcrypto_ml_dsa_87_verify, -1);
1731
1895
  rb_define_module_function(mPQCrypto, "ct_equals", pqcrypto_ct_equals, 2);
1732
1896
  rb_define_module_function(mPQCrypto, "secure_wipe", pqcrypto_secure_wipe, 1);
1733
1897
  rb_define_module_function(mPQCrypto, "version", pqcrypto_version, 0);
@@ -1748,9 +1912,9 @@ void Init_pqcrypto_secure(void) {
1748
1912
  rb_define_module_function(mPQCrypto, "secret_key_from_pqc_container_pem",
1749
1913
  pqcrypto_secret_key_from_pqc_container_pem, 1);
1750
1914
  rb_define_module_function(mPQCrypto, "_native_mldsa_extract_tr",
1751
- pqcrypto__native_mldsa_extract_tr, 1);
1915
+ pqcrypto__native_mldsa_extract_tr, -1);
1752
1916
  rb_define_module_function(mPQCrypto, "_native_mldsa_compute_tr",
1753
- pqcrypto__native_mldsa_compute_tr, 1);
1917
+ pqcrypto__native_mldsa_compute_tr, -1);
1754
1918
  rb_define_module_function(mPQCrypto, "_native_mldsa_mu_builder_new",
1755
1919
  pqcrypto__native_mldsa_mu_builder_new, 2);
1756
1920
  rb_define_module_function(mPQCrypto, "_native_mldsa_mu_builder_update",
@@ -1760,9 +1924,9 @@ void Init_pqcrypto_secure(void) {
1760
1924
  rb_define_module_function(mPQCrypto, "_native_mldsa_mu_builder_release",
1761
1925
  pqcrypto__native_mldsa_mu_builder_release, 1);
1762
1926
  rb_define_module_function(mPQCrypto, "_native_mldsa_sign_mu", pqcrypto__native_mldsa_sign_mu,
1763
- 2);
1927
+ -1);
1764
1928
  rb_define_module_function(mPQCrypto, "_native_mldsa_verify_mu",
1765
- pqcrypto__native_mldsa_verify_mu, 3);
1929
+ pqcrypto__native_mldsa_verify_mu, -1);
1766
1930
 
1767
1931
  define_constants();
1768
1932
  }