1use crate::mldsa::{H, MLDSA_MU_LEN, MLDSA_RND_LEN, MLDSATrait};
69use crate::mldsa::{
70 MLDSA44_BETA, MLDSA44_C_TILDE, MLDSA44_ETA, MLDSA44_FULL_SK_LEN, MLDSA44_GAMMA1,
71 MLDSA44_GAMMA1_MASK_LEN, MLDSA44_GAMMA1_MINUS_BETA, MLDSA44_GAMMA2, MLDSA44_GAMMA2_MINUS_BETA,
72 MLDSA44_LAMBDA, MLDSA44_LAMBDA_over_4, MLDSA44_OMEGA, MLDSA44_PK_LEN,
73 MLDSA44_POLY_W1_PACKED_LEN, MLDSA44_POLY_Z_PACKED_LEN, MLDSA44_S1_PACKED_LEN,
74 MLDSA44_S2_PACKED_LEN, MLDSA44_SIG_LEN, MLDSA44_SK_LEN, MLDSA44_TAU, MLDSA44_k, MLDSA44_l,
75};
76use crate::mldsa::{MLDSA44_T1_PACKED_LEN, MLDSA65_T1_PACKED_LEN, MLDSA87_T1_PACKED_LEN};
77use crate::mldsa::{
78 MLDSA65_BETA, MLDSA65_C_TILDE, MLDSA65_ETA, MLDSA65_FULL_SK_LEN, MLDSA65_GAMMA1,
79 MLDSA65_GAMMA1_MASK_LEN, MLDSA65_GAMMA1_MINUS_BETA, MLDSA65_GAMMA2, MLDSA65_GAMMA2_MINUS_BETA,
80 MLDSA65_LAMBDA, MLDSA65_LAMBDA_over_4, MLDSA65_OMEGA, MLDSA65_PK_LEN,
81 MLDSA65_POLY_W1_PACKED_LEN, MLDSA65_POLY_Z_PACKED_LEN, MLDSA65_S1_PACKED_LEN,
82 MLDSA65_S2_PACKED_LEN, MLDSA65_SIG_LEN, MLDSA65_SK_LEN, MLDSA65_TAU, MLDSA65_k, MLDSA65_l,
83};
84use crate::mldsa::{
85 MLDSA87_BETA, MLDSA87_C_TILDE, MLDSA87_ETA, MLDSA87_FULL_SK_LEN, MLDSA87_GAMMA1,
86 MLDSA87_GAMMA1_MASK_LEN, MLDSA87_GAMMA1_MINUS_BETA, MLDSA87_GAMMA2, MLDSA87_GAMMA2_MINUS_BETA,
87 MLDSA87_LAMBDA, MLDSA87_LAMBDA_over_4, MLDSA87_OMEGA, MLDSA87_PK_LEN,
88 MLDSA87_POLY_W1_PACKED_LEN, MLDSA87_POLY_Z_PACKED_LEN, MLDSA87_S1_PACKED_LEN,
89 MLDSA87_S2_PACKED_LEN, MLDSA87_SIG_LEN, MLDSA87_SK_LEN, MLDSA87_TAU, MLDSA87_k, MLDSA87_l,
90};
91use crate::mldsa_keys::{MLDSAPrivateKeyInternalTrait, MLDSAPublicKeyInternalTrait};
92use crate::{
93 MLDSA, MLDSA44PrivateKey, MLDSA44PublicKey, MLDSA65PrivateKey, MLDSA65PublicKey,
94 MLDSA87PrivateKey, MLDSA87PublicKey, MLDSAPrivateKeyTrait, MLDSAPublicKeyTrait,
95};
96use bouncycastle_core::errors::SignatureError;
97use bouncycastle_core::key_material::KeyMaterial;
98use bouncycastle_core::traits::{
99 Algorithm, AlgorithmOID, Hash, PHSignatureVerifier, PHSigner, RNG, SecurityStrength,
100 SignatureVerifier, Signer, XOF,
101};
102use bouncycastle_rng::HashDRBG_SHA512;
103use bouncycastle_sha2::{SHA256, SHA512};
104use core::marker::PhantomData;
105
106#[allow(unused_imports)]
108use crate::mldsa::MuBuilder;
109
110pub const HASH_ML_DSA_44_with_SHA256_NAME: &str = "HashML-DSA-44_with_SHA256";
114pub const HASH_ML_DSA_65_WITH_SHA256_NAME: &str = "HashML-DSA-65_with_SHA256";
116pub const HASH_ML_DSA_87_with_SHA256_NAME: &str = "HashML-DSA-87_with_SHA256";
118pub const HASH_ML_DSA_44_with_SHA512_NAME: &str = "HashML-DSA-44_with_SHA512";
120pub const HASH_ML_DSA_65_WITH_SHA512_NAME: &str = "HashML-DSA-65_with_SHA512";
122pub const HASH_ML_DSA_87_WITH_SHA512_NAME: &str = "HashML-DSA-87_with_SHA512";
124
125#[allow(non_camel_case_types)]
129pub type HashMLDSA44_with_SHA256 = HashMLDSA<
130 SHA256,
131 32,
132 MLDSA44_PK_LEN,
133 MLDSA44_SK_LEN,
134 MLDSA44_FULL_SK_LEN,
135 MLDSA44_SIG_LEN,
136 MLDSA44PublicKey,
137 MLDSA44PrivateKey,
138 MLDSA44_TAU,
139 MLDSA44_LAMBDA,
140 MLDSA44_GAMMA1,
141 MLDSA44_GAMMA2,
142 MLDSA44_k,
143 MLDSA44_l,
144 MLDSA44_ETA,
145 MLDSA44_BETA,
146 MLDSA44_OMEGA,
147 MLDSA44_C_TILDE,
148 MLDSA44_POLY_Z_PACKED_LEN,
149 MLDSA44_POLY_W1_PACKED_LEN,
150 MLDSA44_S1_PACKED_LEN,
151 MLDSA44_S2_PACKED_LEN,
152 MLDSA44_T1_PACKED_LEN,
153 MLDSA44_LAMBDA_over_4,
154 MLDSA44_GAMMA1_MINUS_BETA,
155 MLDSA44_GAMMA2_MINUS_BETA,
156 MLDSA44_GAMMA1_MASK_LEN,
157>;
158
159impl Algorithm for HashMLDSA44_with_SHA256 {
160 const ALG_NAME: &'static str = HASH_ML_DSA_44_with_SHA256_NAME;
161 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_128bit;
162}
163
164#[allow(non_camel_case_types)]
166pub type HashMLDSA65_with_SHA256 = HashMLDSA<
167 SHA256,
168 32,
169 MLDSA65_PK_LEN,
170 MLDSA65_SK_LEN,
171 MLDSA65_FULL_SK_LEN,
172 MLDSA65_SIG_LEN,
173 MLDSA65PublicKey,
174 MLDSA65PrivateKey,
175 MLDSA65_TAU,
176 MLDSA65_LAMBDA,
177 MLDSA65_GAMMA1,
178 MLDSA65_GAMMA2,
179 MLDSA65_k,
180 MLDSA65_l,
181 MLDSA65_ETA,
182 MLDSA65_BETA,
183 MLDSA65_OMEGA,
184 MLDSA65_C_TILDE,
185 MLDSA65_POLY_Z_PACKED_LEN,
186 MLDSA65_POLY_W1_PACKED_LEN,
187 MLDSA65_S1_PACKED_LEN,
188 MLDSA65_S2_PACKED_LEN,
189 MLDSA65_T1_PACKED_LEN,
190 MLDSA65_LAMBDA_over_4,
191 MLDSA65_GAMMA1_MINUS_BETA,
192 MLDSA65_GAMMA2_MINUS_BETA,
193 MLDSA65_GAMMA1_MASK_LEN,
194>;
195
196impl Algorithm for HashMLDSA65_with_SHA256 {
197 const ALG_NAME: &'static str = HASH_ML_DSA_65_WITH_SHA256_NAME;
198 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_128bit;
199}
200
201#[allow(non_camel_case_types)]
203pub type HashMLDSA87_with_SHA256 = HashMLDSA<
204 SHA256,
205 32,
206 MLDSA87_PK_LEN,
207 MLDSA87_SK_LEN,
208 MLDSA87_FULL_SK_LEN,
209 MLDSA87_SIG_LEN,
210 MLDSA87PublicKey,
211 MLDSA87PrivateKey,
212 MLDSA87_TAU,
213 MLDSA87_LAMBDA,
214 MLDSA87_GAMMA1,
215 MLDSA87_GAMMA2,
216 MLDSA87_k,
217 MLDSA87_l,
218 MLDSA87_ETA,
219 MLDSA87_BETA,
220 MLDSA87_OMEGA,
221 MLDSA87_C_TILDE,
222 MLDSA87_POLY_Z_PACKED_LEN,
223 MLDSA87_POLY_W1_PACKED_LEN,
224 MLDSA87_S1_PACKED_LEN,
225 MLDSA87_S2_PACKED_LEN,
226 MLDSA87_T1_PACKED_LEN,
227 MLDSA87_LAMBDA_over_4,
228 MLDSA87_GAMMA1_MINUS_BETA,
229 MLDSA87_GAMMA2_MINUS_BETA,
230 MLDSA87_GAMMA1_MASK_LEN,
231>;
232
233impl Algorithm for HashMLDSA87_with_SHA256 {
234 const ALG_NAME: &'static str = HASH_ML_DSA_87_with_SHA256_NAME;
235 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_128bit;
236}
237
238#[allow(non_camel_case_types)]
240pub type HashMLDSA44_with_SHA512 = HashMLDSA<
241 SHA512,
242 64,
243 MLDSA44_PK_LEN,
244 MLDSA44_SK_LEN,
245 MLDSA44_FULL_SK_LEN,
246 MLDSA44_SIG_LEN,
247 MLDSA44PublicKey,
248 MLDSA44PrivateKey,
249 MLDSA44_TAU,
250 MLDSA44_LAMBDA,
251 MLDSA44_GAMMA1,
252 MLDSA44_GAMMA2,
253 MLDSA44_k,
254 MLDSA44_l,
255 MLDSA44_ETA,
256 MLDSA44_BETA,
257 MLDSA44_OMEGA,
258 MLDSA44_C_TILDE,
259 MLDSA44_POLY_Z_PACKED_LEN,
260 MLDSA44_POLY_W1_PACKED_LEN,
261 MLDSA44_S1_PACKED_LEN,
262 MLDSA44_S2_PACKED_LEN,
263 MLDSA44_T1_PACKED_LEN,
264 MLDSA44_LAMBDA_over_4,
265 MLDSA44_GAMMA1_MINUS_BETA,
266 MLDSA44_GAMMA2_MINUS_BETA,
267 MLDSA44_GAMMA1_MASK_LEN,
268>;
269
270impl Algorithm for HashMLDSA44_with_SHA512 {
271 const ALG_NAME: &'static str = HASH_ML_DSA_44_with_SHA512_NAME;
272 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_128bit;
273}
274impl AlgorithmOID for HashMLDSA44_with_SHA512 {
276 const OID: &'static [u32] = &[2, 16, 840, 1, 101, 3, 4, 3, 32];
277 const OID_DER: &'static [u8] =
278 &[0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x20];
279}
280
281#[allow(non_camel_case_types)]
283pub type HashMLDSA65_with_SHA512 = HashMLDSA<
284 SHA512,
285 64,
286 MLDSA65_PK_LEN,
287 MLDSA65_SK_LEN,
288 MLDSA65_FULL_SK_LEN,
289 MLDSA65_SIG_LEN,
290 MLDSA65PublicKey,
291 MLDSA65PrivateKey,
292 MLDSA65_TAU,
293 MLDSA65_LAMBDA,
294 MLDSA65_GAMMA1,
295 MLDSA65_GAMMA2,
296 MLDSA65_k,
297 MLDSA65_l,
298 MLDSA65_ETA,
299 MLDSA65_BETA,
300 MLDSA65_OMEGA,
301 MLDSA65_C_TILDE,
302 MLDSA65_POLY_Z_PACKED_LEN,
303 MLDSA65_POLY_W1_PACKED_LEN,
304 MLDSA65_S1_PACKED_LEN,
305 MLDSA65_S2_PACKED_LEN,
306 MLDSA65_T1_PACKED_LEN,
307 MLDSA65_LAMBDA_over_4,
308 MLDSA65_GAMMA1_MINUS_BETA,
309 MLDSA65_GAMMA2_MINUS_BETA,
310 MLDSA65_GAMMA1_MASK_LEN,
311>;
312
313impl Algorithm for HashMLDSA65_with_SHA512 {
314 const ALG_NAME: &'static str = HASH_ML_DSA_65_WITH_SHA512_NAME;
315 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_192bit;
316}
317impl AlgorithmOID for HashMLDSA65_with_SHA512 {
319 const OID: &'static [u32] = &[2, 16, 840, 1, 101, 3, 4, 3, 33];
320 const OID_DER: &'static [u8] =
321 &[0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x21];
322}
323
324#[allow(non_camel_case_types)]
326pub type HashMLDSA87_with_SHA512 = HashMLDSA<
327 SHA512,
328 64,
329 MLDSA87_PK_LEN,
330 MLDSA87_SK_LEN,
331 MLDSA87_FULL_SK_LEN,
332 MLDSA87_SIG_LEN,
333 MLDSA87PublicKey,
334 MLDSA87PrivateKey,
335 MLDSA87_TAU,
336 MLDSA87_LAMBDA,
337 MLDSA87_GAMMA1,
338 MLDSA87_GAMMA2,
339 MLDSA87_k,
340 MLDSA87_l,
341 MLDSA87_ETA,
342 MLDSA87_BETA,
343 MLDSA87_OMEGA,
344 MLDSA87_C_TILDE,
345 MLDSA87_POLY_Z_PACKED_LEN,
346 MLDSA87_POLY_W1_PACKED_LEN,
347 MLDSA87_S1_PACKED_LEN,
348 MLDSA87_S2_PACKED_LEN,
349 MLDSA87_T1_PACKED_LEN,
350 MLDSA87_LAMBDA_over_4,
351 MLDSA87_GAMMA1_MINUS_BETA,
352 MLDSA87_GAMMA2_MINUS_BETA,
353 MLDSA87_GAMMA1_MASK_LEN,
354>;
355
356impl Algorithm for HashMLDSA87_with_SHA512 {
357 const ALG_NAME: &'static str = HASH_ML_DSA_87_WITH_SHA512_NAME;
358 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_256bit;
359}
360impl AlgorithmOID for HashMLDSA87_with_SHA512 {
362 const OID: &'static [u32] = &[2, 16, 840, 1, 101, 3, 4, 3, 34];
363 const OID_DER: &'static [u8] =
364 &[0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x22];
365}
366
367pub struct HashMLDSA<
374 HASH: Hash + AlgorithmOID + Default,
375 const HASH_LEN: usize,
376 const PK_LEN: usize,
377 const SK_LEN: usize,
378 const FULL_SK_LEN: usize,
379 const SIG_LEN: usize,
380 PK: MLDSAPublicKeyTrait<k, T1_PACKED_LEN, PK_LEN>
381 + MLDSAPublicKeyInternalTrait<k, T1_PACKED_LEN, PK_LEN>,
382 SK: MLDSAPrivateKeyTrait<
383 k,
384 l,
385 S1_PACKED_LEN,
386 S2_PACKED_LEN,
387 T1_PACKED_LEN,
388 PK_LEN,
389 SK_LEN,
390 FULL_SK_LEN,
391 > + MLDSAPrivateKeyInternalTrait<
392 LAMBDA,
393 GAMMA2,
394 k,
395 l,
396 ETA,
397 S1_PACKED_LEN,
398 S2_PACKED_LEN,
399 PK_LEN,
400 SK_LEN,
401 >,
402 const TAU: i32,
403 const LAMBDA: i32,
404 const GAMMA1: i32,
405 const GAMMA2: i32,
406 const k: usize,
407 const l: usize,
408 const ETA: usize,
409 const BETA: i32,
410 const OMEGA: i32,
411 const C_TILDE: usize,
412 const POLY_Z_PACKED_LEN: usize,
413 const POLY_W1_PACKED_LEN: usize,
414 const S1_PACKED_LEN: usize,
415 const S2_PACKED_LEN: usize,
416 const T1_PACKED_LEN: usize,
417 const LAMBDA_over_4: usize,
418 const GAMMA1_MINUS_BETA: i32,
419 const GAMMA2_MINUS_BETA: i32,
420 const GAMMA1_MASK_LEN: usize,
421> {
422 _phantom: PhantomData<(PK, SK)>,
423
424 signer_rnd: Option<[u8; MLDSA_RND_LEN]>,
425
426 sk: Option<SK>,
428
429 seed: Option<KeyMaterial<32>>,
431
432 pk: Option<PK>,
434
435 hash: HASH,
437
438 ctx: [u8; 255],
441 ctx_len: usize,
442}
443
444impl<
445 HASH: Hash + AlgorithmOID + Default,
446 const PH_LEN: usize,
447 const PK_LEN: usize,
448 const SK_LEN: usize,
449 const FULL_SK_LEN: usize,
450 const SIG_LEN: usize,
451 PK: MLDSAPublicKeyTrait<k, T1_PACKED_LEN, PK_LEN>
452 + MLDSAPublicKeyInternalTrait<k, T1_PACKED_LEN, PK_LEN>,
453 SK: MLDSAPrivateKeyTrait<
454 k,
455 l,
456 S1_PACKED_LEN,
457 S2_PACKED_LEN,
458 T1_PACKED_LEN,
459 PK_LEN,
460 SK_LEN,
461 FULL_SK_LEN,
462 > + MLDSAPrivateKeyInternalTrait<
463 LAMBDA,
464 GAMMA2,
465 k,
466 l,
467 ETA,
468 S1_PACKED_LEN,
469 S2_PACKED_LEN,
470 PK_LEN,
471 SK_LEN,
472 >,
473 const TAU: i32,
474 const LAMBDA: i32,
475 const GAMMA1: i32,
476 const GAMMA2: i32,
477 const k: usize,
478 const l: usize,
479 const ETA: usize,
480 const BETA: i32,
481 const OMEGA: i32,
482 const C_TILDE: usize,
483 const POLY_Z_PACKED_LEN: usize,
484 const POLY_W1_PACKED_LEN: usize,
485 const S1_PACKED_LEN: usize,
486 const S2_PACKED_LEN: usize,
487 const T1_PACKED_LEN: usize,
488 const LAMBDA_over_4: usize,
489 const GAMMA1_MINUS_BETA: i32,
490 const GAMMA2_MINUS_BETA: i32,
491 const GAMMA1_MASK_LEN: usize,
492>
493 HashMLDSA<
494 HASH,
495 PH_LEN,
496 PK_LEN,
497 SK_LEN,
498 FULL_SK_LEN,
499 SIG_LEN,
500 PK,
501 SK,
502 TAU,
503 LAMBDA,
504 GAMMA1,
505 GAMMA2,
506 k,
507 l,
508 ETA,
509 BETA,
510 OMEGA,
511 C_TILDE,
512 POLY_Z_PACKED_LEN,
513 POLY_W1_PACKED_LEN,
514 S1_PACKED_LEN,
515 S2_PACKED_LEN,
516 T1_PACKED_LEN,
517 LAMBDA_over_4,
518 GAMMA1_MINUS_BETA,
519 GAMMA2_MINUS_BETA,
520 GAMMA1_MASK_LEN,
521 >
522{
523 pub fn keygen() -> Result<(PK, SK), SignatureError> {
530 MLDSA::<
531 PK_LEN,
532 SK_LEN,
533 FULL_SK_LEN,
534 SIG_LEN,
535 PK,
536 SK,
537 TAU,
538 LAMBDA,
539 GAMMA1,
540 GAMMA2,
541 k,
542 l,
543 ETA,
544 BETA,
545 OMEGA,
546 C_TILDE,
547 POLY_Z_PACKED_LEN,
548 POLY_W1_PACKED_LEN,
549 S1_PACKED_LEN,
550 S2_PACKED_LEN,
551 T1_PACKED_LEN,
552 LAMBDA_over_4,
553 GAMMA1_MINUS_BETA,
554 GAMMA2_MINUS_BETA,
555 GAMMA1_MASK_LEN,
556 >::keygen()
557 }
558
559 pub fn keygen_from_seed(seed: &KeyMaterial<32>) -> Result<(PK, SK), SignatureError> {
561 MLDSA::<
562 PK_LEN,
563 SK_LEN,
564 FULL_SK_LEN,
565 SIG_LEN,
566 PK,
567 SK,
568 TAU,
569 LAMBDA,
570 GAMMA1,
571 GAMMA2,
572 k,
573 l,
574 ETA,
575 BETA,
576 OMEGA,
577 C_TILDE,
578 POLY_Z_PACKED_LEN,
579 POLY_W1_PACKED_LEN,
580 S1_PACKED_LEN,
581 S2_PACKED_LEN,
582 T1_PACKED_LEN,
583 LAMBDA_over_4,
584 GAMMA1_MINUS_BETA,
585 GAMMA2_MINUS_BETA,
586 GAMMA1_MASK_LEN,
587 >::keygen_internal(seed)
588 }
589
590 pub fn sign_ph_deterministic(
604 sk: &SK,
605 ctx: Option<&[u8]>,
606 ph: &[u8; PH_LEN],
607 rnd: [u8; 32],
608 ) -> Result<[u8; SIG_LEN], SignatureError> {
609 let mut out: [u8; SIG_LEN] = [0u8; SIG_LEN];
610 Self::sign_ph_deterministic_out(sk, ctx, ph, rnd, &mut out)?;
611 Ok(out)
612 }
613
614 pub fn sign_ph_deterministic_out(
627 sk: &SK,
628 ctx: Option<&[u8]>,
629 ph: &[u8; PH_LEN],
630 rnd: [u8; 32],
631 output: &mut [u8; SIG_LEN],
632 ) -> Result<usize, SignatureError> {
633 let ctx = if ctx.is_some() { ctx.unwrap() } else { &[] };
634
635 if ctx.len() > 255 {
638 return Err(SignatureError::LengthError("ctx value is longer than 255 bytes"));
639 }
640
641 output.fill(0);
642
643 let mut h = H::new();
646 h.absorb(&sk.tr()).expect("absorb before squeeze is infallible");
647
648 h.absorb(&[1u8]).expect("absorb before squeeze is infallible");
652 h.absorb(&[ctx.len() as u8]).expect("absorb before squeeze is infallible");
653 h.absorb(ctx).expect("absorb before squeeze is infallible");
654 h.absorb(HASH::OID_DER).expect("absorb before squeeze is infallible");
655 h.absorb(ph).expect("absorb before squeeze is infallible");
656 let mut mu = [0u8; MLDSA_MU_LEN];
657 let bytes_written = h.squeeze_out(&mut mu);
658 debug_assert_eq!(bytes_written, MLDSA_MU_LEN);
659
660 let bytes_written = MLDSA::<
662 PK_LEN,
663 SK_LEN,
664 FULL_SK_LEN,
665 SIG_LEN,
666 PK,
667 SK,
668 TAU,
669 LAMBDA,
670 GAMMA1,
671 GAMMA2,
672 k,
673 l,
674 ETA,
675 BETA,
676 OMEGA,
677 C_TILDE,
678 POLY_Z_PACKED_LEN,
679 POLY_W1_PACKED_LEN,
680 S1_PACKED_LEN,
681 S2_PACKED_LEN,
682 T1_PACKED_LEN,
683 LAMBDA_over_4,
684 GAMMA1_MINUS_BETA,
685 GAMMA2_MINUS_BETA,
686 GAMMA1_MASK_LEN,
687 >::sign_mu_deterministic_out(sk, &mu, rnd, output)?;
688
689 Ok(bytes_written)
690 }
691
692 pub fn set_signer_rnd(&mut self, rnd: [u8; 32]) {
696 self.signer_rnd = Some(rnd);
697 }
698
699 fn parse_ctx(ctx: Option<&[u8]>) -> Result<([u8; 255], usize), SignatureError> {
700 if ctx.is_some() {
701 if ctx.unwrap().len() > 255 {
704 return Err(SignatureError::LengthError("ctx value is longer than 255 bytes"));
705 }
706
707 let mut ctx_buf = [0u8; 255];
708 ctx_buf[..ctx.unwrap().len()].copy_from_slice(ctx.unwrap());
709 Ok((ctx_buf, ctx.unwrap().len()))
710 } else {
711 Ok(([0u8; 255], 0))
712 }
713 }
714
715 pub fn sign_init_from_seed(
718 seed: &KeyMaterial<32>,
719 ctx: Option<&[u8]>,
720 ) -> Result<Self, SignatureError> {
721 let (ctx, ctx_len) = Self::parse_ctx(ctx)?;
722 Ok(Self {
723 _phantom: PhantomData,
724 signer_rnd: None,
725 sk: None,
726 seed: Some(seed.clone()),
727 pk: None,
728 hash: HASH::default(),
729 ctx,
730 ctx_len,
731 })
732 }
733}
734
735impl<
736 HASH: Hash + AlgorithmOID + Default,
737 PK: MLDSAPublicKeyTrait<k, T1_PACKED_LEN, PK_LEN>
738 + MLDSAPublicKeyInternalTrait<k, T1_PACKED_LEN, PK_LEN>,
739 SK: MLDSAPrivateKeyTrait<
740 k,
741 l,
742 S1_PACKED_LEN,
743 S2_PACKED_LEN,
744 T1_PACKED_LEN,
745 PK_LEN,
746 SK_LEN,
747 FULL_SK_LEN,
748 > + MLDSAPrivateKeyInternalTrait<
749 LAMBDA,
750 GAMMA2,
751 k,
752 l,
753 ETA,
754 S1_PACKED_LEN,
755 S2_PACKED_LEN,
756 PK_LEN,
757 SK_LEN,
758 >,
759 const PH_LEN: usize,
760 const PK_LEN: usize,
761 const SK_LEN: usize,
762 const FULL_SK_LEN: usize,
763 const SIG_LEN: usize,
764 const TAU: i32,
765 const LAMBDA: i32,
766 const GAMMA1: i32,
767 const GAMMA2: i32,
768 const k: usize,
769 const l: usize,
770 const ETA: usize,
771 const BETA: i32,
772 const OMEGA: i32,
773 const C_TILDE: usize,
774 const POLY_Z_PACKED_LEN: usize,
775 const POLY_W1_PACKED_LEN: usize,
776 const S1_PACKED_LEN: usize,
777 const S2_PACKED_LEN: usize,
778 const T1_PACKED_LEN: usize,
779 const LAMBDA_over_4: usize,
780 const GAMMA1_MINUS_BETA: i32,
781 const GAMMA2_MINUS_BETA: i32,
782 const GAMMA1_MASK_LEN: usize,
783> Signer<SK, SK_LEN, SIG_LEN>
784 for HashMLDSA<
785 HASH,
786 PH_LEN,
787 PK_LEN,
788 SK_LEN,
789 FULL_SK_LEN,
790 SIG_LEN,
791 PK,
792 SK,
793 TAU,
794 LAMBDA,
795 GAMMA1,
796 GAMMA2,
797 k,
798 l,
799 ETA,
800 BETA,
801 OMEGA,
802 C_TILDE,
803 POLY_Z_PACKED_LEN,
804 POLY_W1_PACKED_LEN,
805 S1_PACKED_LEN,
806 S2_PACKED_LEN,
807 T1_PACKED_LEN,
808 LAMBDA_over_4,
809 GAMMA1_MINUS_BETA,
810 GAMMA2_MINUS_BETA,
811 GAMMA1_MASK_LEN,
812 >
813{
814 fn sign(sk: &SK, msg: &[u8], ctx: Option<&[u8]>) -> Result<[u8; SIG_LEN], SignatureError> {
817 let mut out = [0u8; SIG_LEN];
818 Self::sign_out(sk, msg, ctx, &mut out)?;
819
820 Ok(out)
821 }
822
823 fn sign_out(
824 sk: &SK,
825 msg: &[u8],
826 ctx: Option<&[u8]>,
827 output: &mut [u8; SIG_LEN],
828 ) -> Result<usize, SignatureError> {
829 output.fill(0);
830
831 let mut ph_m = [0u8; PH_LEN];
832 _ = HASH::default().hash_out(msg, &mut ph_m);
833 Self::sign_ph_out(sk, &ph_m, ctx, output)
834 }
835
836 fn sign_init(sk: &SK, ctx: Option<&[u8]>) -> Result<Self, SignatureError> {
837 let (ctx, ctx_len) = Self::parse_ctx(ctx)?;
838 Ok(Self {
839 _phantom: PhantomData,
840 signer_rnd: None,
841 sk: Some(sk.clone()),
842 seed: None,
843 pk: None,
844 hash: HASH::default(),
845 ctx,
846 ctx_len,
847 })
848 }
849
850 fn sign_update(&mut self, msg_chunk: &[u8]) {
851 self.hash.do_update(msg_chunk);
852 }
853
854 fn sign_final(self) -> Result<[u8; SIG_LEN], SignatureError> {
855 let mut out = [0u8; SIG_LEN];
856 self.sign_final_out(&mut out)?;
857 Ok(out)
858 }
859
860 fn sign_final_out(self, output: &mut [u8; SIG_LEN]) -> Result<usize, SignatureError> {
861 let ph: [u8; PH_LEN] = self.hash.do_final().try_into().unwrap();
862
863 if self.sk.is_none() && self.seed.is_none() {
864 return Err(SignatureError::GenericError(
865 "Somehow you managed to construct a streaming signer without a private key, impressive!",
866 ));
867 }
868
869 output.fill(0);
870
871 if self.sk.is_some() {
872 if self.signer_rnd.is_none() {
873 Self::sign_ph_out(&self.sk.unwrap(), &ph, Some(&self.ctx[..self.ctx_len]), output)
874 } else {
875 Self::sign_ph_deterministic_out(
876 &self.sk.unwrap(),
877 Some(&self.ctx[..self.ctx_len]),
878 &ph,
879 self.signer_rnd.unwrap(),
880 output,
881 )
882 }
883 } else if self.seed.is_some() {
884 let rnd = if self.signer_rnd.is_some() {
885 self.signer_rnd.unwrap()
886 } else {
887 let mut rnd: [u8; MLDSA_RND_LEN] = [0u8; MLDSA_RND_LEN];
888 HashDRBG_SHA512::new_from_os().next_bytes_out(&mut rnd)?;
889 rnd
890 };
891 let (_pk, sk) = Self::keygen_from_seed(&self.seed.unwrap())?;
894 Self::sign_ph_deterministic_out(&sk, Some(&self.ctx[..self.ctx_len]), &ph, rnd, output)
895 } else {
896 unreachable!()
897 }
898 }
899}
900
901impl<
902 HASH: Hash + AlgorithmOID + Default,
903 PK: MLDSAPublicKeyTrait<k, T1_PACKED_LEN, PK_LEN>
904 + MLDSAPublicKeyInternalTrait<k, T1_PACKED_LEN, PK_LEN>,
905 SK: MLDSAPrivateKeyTrait<
906 k,
907 l,
908 S1_PACKED_LEN,
909 S2_PACKED_LEN,
910 T1_PACKED_LEN,
911 PK_LEN,
912 SK_LEN,
913 FULL_SK_LEN,
914 > + MLDSAPrivateKeyInternalTrait<
915 LAMBDA,
916 GAMMA2,
917 k,
918 l,
919 ETA,
920 S1_PACKED_LEN,
921 S2_PACKED_LEN,
922 PK_LEN,
923 SK_LEN,
924 >,
925 const PH_LEN: usize,
926 const PK_LEN: usize,
927 const SK_LEN: usize,
928 const FULL_SK_LEN: usize,
929 const SIG_LEN: usize,
930 const TAU: i32,
931 const LAMBDA: i32,
932 const GAMMA1: i32,
933 const GAMMA2: i32,
934 const k: usize,
935 const l: usize,
936 const ETA: usize,
937 const BETA: i32,
938 const OMEGA: i32,
939 const C_TILDE: usize,
940 const POLY_Z_PACKED_LEN: usize,
941 const POLY_W1_PACKED_LEN: usize,
942 const S1_PACKED_LEN: usize,
943 const S2_PACKED_LEN: usize,
944 const T1_PACKED_LEN: usize,
945 const LAMBDA_over_4: usize,
946 const GAMMA1_MINUS_BETA: i32,
947 const GAMMA2_MINUS_BETA: i32,
948 const GAMMA1_MASK_LEN: usize,
949> SignatureVerifier<PK, PK_LEN, SIG_LEN>
950 for HashMLDSA<
951 HASH,
952 PH_LEN,
953 PK_LEN,
954 SK_LEN,
955 FULL_SK_LEN,
956 SIG_LEN,
957 PK,
958 SK,
959 TAU,
960 LAMBDA,
961 GAMMA1,
962 GAMMA2,
963 k,
964 l,
965 ETA,
966 BETA,
967 OMEGA,
968 C_TILDE,
969 POLY_Z_PACKED_LEN,
970 POLY_W1_PACKED_LEN,
971 S1_PACKED_LEN,
972 S2_PACKED_LEN,
973 T1_PACKED_LEN,
974 LAMBDA_over_4,
975 GAMMA1_MINUS_BETA,
976 GAMMA2_MINUS_BETA,
977 GAMMA1_MASK_LEN,
978 >
979{
980 fn verify(pk: &PK, msg: &[u8], ctx: Option<&[u8]>, sig: &[u8]) -> Result<(), SignatureError> {
981 let mut ph_m = [0u8; PH_LEN];
982 _ = HASH::default().hash_out(msg, &mut ph_m);
983
984 Self::verify_ph(pk, &ph_m, ctx, sig)
985 }
986
987 fn verify_init(pk: &PK, ctx: Option<&[u8]>) -> Result<Self, SignatureError> {
988 let (ctx, ctx_len) = Self::parse_ctx(ctx)?;
989 Ok(Self {
990 _phantom: Default::default(),
991 signer_rnd: None,
992 sk: None,
993 seed: None,
994 pk: Some(pk.clone()),
995 hash: HASH::default(),
996 ctx,
997 ctx_len,
998 })
999 }
1000
1001 fn verify_update(&mut self, msg_chunk: &[u8]) {
1002 self.hash.do_update(msg_chunk);
1003 }
1004
1005 fn verify_final(self, sig: &[u8]) -> Result<(), SignatureError> {
1006 assert!(
1007 self.pk.is_some(),
1008 "Somehow you managed to construct a streaming verifier without a public key, impressive!"
1009 );
1010 let ph: [u8; PH_LEN] = self.hash.do_final().try_into().unwrap();
1011 Self::verify_ph(&self.pk.unwrap(), &ph, Some(&self.ctx[..self.ctx_len]), &sig[..SIG_LEN])
1012 }
1013}
1014
1015impl<
1016 HASH: Hash + AlgorithmOID + Default,
1017 const PH_LEN: usize,
1018 const PK_LEN: usize,
1019 const SK_LEN: usize,
1020 const FULL_SK_LEN: usize,
1021 const SIG_LEN: usize,
1022 PK: MLDSAPublicKeyTrait<k, T1_PACKED_LEN, PK_LEN>
1023 + MLDSAPublicKeyInternalTrait<k, T1_PACKED_LEN, PK_LEN>,
1024 SK: MLDSAPrivateKeyTrait<
1025 k,
1026 l,
1027 S1_PACKED_LEN,
1028 S2_PACKED_LEN,
1029 T1_PACKED_LEN,
1030 PK_LEN,
1031 SK_LEN,
1032 FULL_SK_LEN,
1033 > + MLDSAPrivateKeyInternalTrait<
1034 LAMBDA,
1035 GAMMA2,
1036 k,
1037 l,
1038 ETA,
1039 S1_PACKED_LEN,
1040 S2_PACKED_LEN,
1041 PK_LEN,
1042 SK_LEN,
1043 >,
1044 const TAU: i32,
1045 const LAMBDA: i32,
1046 const GAMMA1: i32,
1047 const GAMMA2: i32,
1048 const k: usize,
1049 const l: usize,
1050 const ETA: usize,
1051 const BETA: i32,
1052 const OMEGA: i32,
1053 const C_TILDE: usize,
1054 const POLY_Z_PACKED_LEN: usize,
1055 const POLY_W1_PACKED_LEN: usize,
1056 const S1_PACKED_LEN: usize,
1057 const S2_PACKED_LEN: usize,
1058 const T1_PACKED_LEN: usize,
1059 const LAMBDA_over_4: usize,
1060 const GAMMA1_MINUS_BETA: i32,
1061 const GAMMA2_MINUS_BETA: i32,
1062 const GAMMA1_MASK_LEN: usize,
1063> PHSigner<PK, SK, PK_LEN, SK_LEN, SIG_LEN, PH_LEN>
1064 for HashMLDSA<
1065 HASH,
1066 PH_LEN,
1067 PK_LEN,
1068 SK_LEN,
1069 FULL_SK_LEN,
1070 SIG_LEN,
1071 PK,
1072 SK,
1073 TAU,
1074 LAMBDA,
1075 GAMMA1,
1076 GAMMA2,
1077 k,
1078 l,
1079 ETA,
1080 BETA,
1081 OMEGA,
1082 C_TILDE,
1083 POLY_Z_PACKED_LEN,
1084 POLY_W1_PACKED_LEN,
1085 S1_PACKED_LEN,
1086 S2_PACKED_LEN,
1087 T1_PACKED_LEN,
1088 LAMBDA_over_4,
1089 GAMMA1_MINUS_BETA,
1090 GAMMA2_MINUS_BETA,
1091 GAMMA1_MASK_LEN,
1092 >
1093{
1094 fn sign_ph(
1095 sk: &SK,
1096 ph: &[u8; PH_LEN],
1097 ctx: Option<&[u8]>,
1098 ) -> Result<[u8; SIG_LEN], SignatureError> {
1099 let mut out = [0u8; SIG_LEN];
1100 Self::sign_ph_out(sk, ph, ctx, &mut out)?;
1101
1102 Ok(out)
1103 }
1104
1105 fn sign_ph_out(
1110 sk: &SK,
1111 ph: &[u8; PH_LEN],
1112 ctx: Option<&[u8]>,
1113 output: &mut [u8; SIG_LEN],
1114 ) -> Result<usize, SignatureError> {
1115 output.fill(0);
1116
1117 let mut rnd: [u8; MLDSA_RND_LEN] = [0u8; MLDSA_RND_LEN];
1118 HashDRBG_SHA512::new_from_os().next_bytes_out(&mut rnd)?;
1119 Self::sign_ph_deterministic_out(sk, ctx, ph, rnd, output)
1120 }
1121}
1122
1123impl<
1124 HASH: Hash + AlgorithmOID + Default,
1125 const PH_LEN: usize,
1126 const PK_LEN: usize,
1127 const SK_LEN: usize,
1128 const FULL_SK_LEN: usize,
1129 const SIG_LEN: usize,
1130 PK: MLDSAPublicKeyTrait<k, T1_PACKED_LEN, PK_LEN>
1131 + MLDSAPublicKeyInternalTrait<k, T1_PACKED_LEN, PK_LEN>,
1132 SK: MLDSAPrivateKeyTrait<
1133 k,
1134 l,
1135 S1_PACKED_LEN,
1136 S2_PACKED_LEN,
1137 T1_PACKED_LEN,
1138 PK_LEN,
1139 SK_LEN,
1140 FULL_SK_LEN,
1141 > + MLDSAPrivateKeyInternalTrait<
1142 LAMBDA,
1143 GAMMA2,
1144 k,
1145 l,
1146 ETA,
1147 S1_PACKED_LEN,
1148 S2_PACKED_LEN,
1149 PK_LEN,
1150 SK_LEN,
1151 >,
1152 const TAU: i32,
1153 const LAMBDA: i32,
1154 const GAMMA1: i32,
1155 const GAMMA2: i32,
1156 const k: usize,
1157 const l: usize,
1158 const ETA: usize,
1159 const BETA: i32,
1160 const OMEGA: i32,
1161 const C_TILDE: usize,
1162 const POLY_Z_PACKED_LEN: usize,
1163 const POLY_W1_PACKED_LEN: usize,
1164 const S1_PACKED_LEN: usize,
1165 const S2_PACKED_LEN: usize,
1166 const T1_PACKED_LEN: usize,
1167 const LAMBDA_over_4: usize,
1168 const GAMMA1_MINUS_BETA: i32,
1169 const GAMMA2_MINUS_BETA: i32,
1170 const GAMMA1_MASK_LEN: usize,
1171> PHSignatureVerifier<PK, PK_LEN, SIG_LEN, PH_LEN>
1172 for HashMLDSA<
1173 HASH,
1174 PH_LEN,
1175 PK_LEN,
1176 SK_LEN,
1177 FULL_SK_LEN,
1178 SIG_LEN,
1179 PK,
1180 SK,
1181 TAU,
1182 LAMBDA,
1183 GAMMA1,
1184 GAMMA2,
1185 k,
1186 l,
1187 ETA,
1188 BETA,
1189 OMEGA,
1190 C_TILDE,
1191 POLY_Z_PACKED_LEN,
1192 POLY_W1_PACKED_LEN,
1193 S1_PACKED_LEN,
1194 S2_PACKED_LEN,
1195 T1_PACKED_LEN,
1196 LAMBDA_over_4,
1197 GAMMA1_MINUS_BETA,
1198 GAMMA2_MINUS_BETA,
1199 GAMMA1_MASK_LEN,
1200 >
1201{
1202 fn verify_ph(
1203 pk: &PK,
1204 ph: &[u8; PH_LEN],
1205 ctx: Option<&[u8]>,
1206 sig: &[u8],
1207 ) -> Result<(), SignatureError> {
1208 if sig.len() != SIG_LEN {
1209 return Err(SignatureError::LengthError("Signature value is not the correct length."));
1210 }
1211 let sig_sized = &sig.try_into().unwrap();
1212
1213 let ctx = if ctx.is_some() { ctx.unwrap() } else { &[] };
1214
1215 if ctx.len() > 255 {
1218 return Err(SignatureError::LengthError("ctx value is longer than 255 bytes"));
1219 }
1220
1221 let mut h = H::new();
1224 h.absorb(&pk.compute_tr()).expect("absorb before squeeze is infallible");
1225
1226 h.absorb(&[1u8]).expect("absorb before squeeze is infallible");
1230 h.absorb(&[ctx.len() as u8]).expect("absorb before squeeze is infallible");
1231 h.absorb(ctx).expect("absorb before squeeze is infallible");
1232 h.absorb(HASH::OID_DER).expect("absorb before squeeze is infallible");
1233 h.absorb(ph).expect("absorb before squeeze is infallible");
1234 let mut mu = [0u8; MLDSA_MU_LEN];
1235 _ = h.squeeze_out(&mut mu);
1236
1237 MLDSA::<
1238 PK_LEN,
1239 SK_LEN,
1240 FULL_SK_LEN,
1241 SIG_LEN,
1242 PK,
1243 SK,
1244 TAU,
1245 LAMBDA,
1246 GAMMA1,
1247 GAMMA2,
1248 k,
1249 l,
1250 ETA,
1251 BETA,
1252 OMEGA,
1253 C_TILDE,
1254 POLY_Z_PACKED_LEN,
1255 POLY_W1_PACKED_LEN,
1256 S1_PACKED_LEN,
1257 S2_PACKED_LEN,
1258 T1_PACKED_LEN,
1259 LAMBDA_over_4,
1260 GAMMA1_MINUS_BETA,
1261 GAMMA2_MINUS_BETA,
1262 GAMMA1_MASK_LEN,
1263 >::verify_mu(pk, &mu, sig_sized)
1264 }
1265}