1use core::marker::PhantomData;
67use crate::mldsa::{H, MLDSATrait, MU_LEN, RND_LEN};
68use crate::mldsa::{
69 MLDSA44_BETA, MLDSA44_C_TILDE, MLDSA44_ETA, MLDSA44_GAMMA1, MLDSA44_GAMMA1_MASK_LEN,
70 MLDSA44_GAMMA2, MLDSA44_LAMBDA, MLDSA44_LAMBDA_over_4, MLDSA44_OMEGA, MLDSA44_PK_LEN,
71 MLDSA44_POLY_ETA_PACKED_LEN, MLDSA44_POLY_W1_PACKED_LEN, MLDSA44_POLY_Z_PACKED_LEN,
72 MLDSA44_SIG_LEN, MLDSA44_SK_LEN, MLDSA44_TAU, MLDSA44_S1_PACKED_LEN, MLDSA44_S2_PACKED_LEN, MLDSA44_k, MLDSA44_l,
73};
74use crate::mldsa::{
75 MLDSA65_BETA, MLDSA65_C_TILDE, MLDSA65_ETA, MLDSA65_GAMMA1, MLDSA65_GAMMA1_MASK_LEN,
76 MLDSA65_GAMMA2, MLDSA65_LAMBDA, MLDSA65_LAMBDA_over_4, MLDSA65_OMEGA, MLDSA65_PK_LEN,
77 MLDSA65_POLY_ETA_PACKED_LEN, MLDSA65_POLY_W1_PACKED_LEN, MLDSA65_POLY_Z_PACKED_LEN,
78 MLDSA65_SIG_LEN, MLDSA65_SK_LEN, MLDSA65_TAU, MLDSA65_S1_PACKED_LEN, MLDSA65_S2_PACKED_LEN, MLDSA65_k, MLDSA65_l,
79};
80use crate::mldsa::{
81 MLDSA87_BETA, MLDSA87_C_TILDE, MLDSA87_ETA, MLDSA87_GAMMA1, MLDSA87_GAMMA1_MASK_LEN,
82 MLDSA87_GAMMA2, MLDSA87_LAMBDA, MLDSA87_LAMBDA_over_4, MLDSA87_OMEGA, MLDSA87_PK_LEN,
83 MLDSA87_POLY_ETA_PACKED_LEN, MLDSA87_POLY_W1_PACKED_LEN, MLDSA87_POLY_Z_PACKED_LEN,
84 MLDSA87_SIG_LEN, MLDSA87_SK_LEN, MLDSA87_TAU, MLDSA87_S1_PACKED_LEN, MLDSA87_S2_PACKED_LEN, MLDSA87_k, MLDSA87_l,
85};
86use crate::mldsa::{MLDSA44_T1_PACKED_LEN, MLDSA65_T1_PACKED_LEN, MLDSA87_T1_PACKED_LEN};
87use crate::mldsa_keys::{MLDSAPrivateKeyInternalTrait, MLDSAPublicKeyInternalTrait};
88use crate::{MLDSA, MLDSA44PrivateKey, MLDSA44PublicKey, MLDSA65PrivateKey, MLDSA65PublicKey, MLDSA87PrivateKey, MLDSA87PublicKey, MLDSAPrivateKeyTrait, MLDSAPublicKeyTrait};
89use bouncycastle_core_interface::errors::SignatureError;
90use bouncycastle_core_interface::key_material::KeyMaterialSized;
91use bouncycastle_core_interface::traits::{Hash, PHSignature, RNG, Signature, XOF, Algorithm, SecurityStrength};
92use bouncycastle_rng::HashDRBG_SHA512;
93use bouncycastle_sha2::{SHA256, SHA512};
94
95#[allow(unused_imports)]
97use crate::mldsa::MuBuilder;
98
99const SHA256_OID: &[u8] = &[0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01];
100const SHA512_OID: &[u8] = &[0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03];
101
102pub const Hash_ML_DSA_44_with_SHA256_NAME: &str = "HashML-DSA-44_with_SHA256";
106pub const Hash_ML_DSA_65_with_SHA256_NAME: &str = "HashML-DSA-65_with_SHA256";
108pub const Hash_ML_DSA_87_with_SHA256_NAME: &str = "HashML-DSA-87_with_SHA256";
110pub const Hash_ML_DSA_44_with_SHA512_NAME: &str = "HashML-DSA-44_with_SHA512";
112pub const Hash_ML_DSA_65_with_SHA512_NAME: &str = "HashML-DSA-65_with_SHA512";
114pub const Hash_ML_DSA_87_with_SHA512_NAME: &str = "HashML-DSA-87_with_SHA512";
116
117#[allow(non_camel_case_types)]
121pub type HashMLDSA44_with_SHA256 = HashMLDSA<
122 SHA256,
123 32,
124 SHA256_OID,
125 MLDSA44_PK_LEN,
126 MLDSA44_SK_LEN,
127 MLDSA44_SIG_LEN,
128 MLDSA44PublicKey,
129 MLDSA44PrivateKey,
130 MLDSA44_TAU,
131 MLDSA44_LAMBDA,
132 MLDSA44_GAMMA1,
133 MLDSA44_GAMMA2,
134 MLDSA44_k,
135 MLDSA44_l,
136 MLDSA44_ETA,
137 MLDSA44_BETA,
138 MLDSA44_OMEGA,
139 MLDSA44_C_TILDE,
140 MLDSA44_POLY_Z_PACKED_LEN,
141 MLDSA44_POLY_W1_PACKED_LEN,
142 MLDSA44_S1_PACKED_LEN,
143 MLDSA44_S2_PACKED_LEN,
144 MLDSA44_T1_PACKED_LEN,
145 MLDSA44_POLY_ETA_PACKED_LEN,
146 MLDSA44_LAMBDA_over_4,
147 MLDSA44_GAMMA1_MASK_LEN,
148>;
149
150impl Algorithm for HashMLDSA44_with_SHA256 {
151 const ALG_NAME: &'static str = Hash_ML_DSA_44_with_SHA256_NAME;
152 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_128bit;
153}
154
155#[allow(non_camel_case_types)]
157pub type HashMLDSA65_with_SHA256 = HashMLDSA<
158 SHA256,
159 32,
160 SHA256_OID,
161 MLDSA65_PK_LEN,
162 MLDSA65_SK_LEN,
163 MLDSA65_SIG_LEN,
164 MLDSA65PublicKey,
165 MLDSA65PrivateKey,
166 MLDSA65_TAU,
167 MLDSA65_LAMBDA,
168 MLDSA65_GAMMA1,
169 MLDSA65_GAMMA2,
170 MLDSA65_k,
171 MLDSA65_l,
172 MLDSA65_ETA,
173 MLDSA65_BETA,
174 MLDSA65_OMEGA,
175 MLDSA65_C_TILDE,
176 MLDSA65_POLY_Z_PACKED_LEN,
177 MLDSA65_POLY_W1_PACKED_LEN,
178 MLDSA65_S1_PACKED_LEN,
179 MLDSA65_S2_PACKED_LEN,
180 MLDSA65_T1_PACKED_LEN,
181 MLDSA65_POLY_ETA_PACKED_LEN,
182 MLDSA65_LAMBDA_over_4,
183 MLDSA65_GAMMA1_MASK_LEN,
184>;
185
186impl Algorithm for HashMLDSA65_with_SHA256 {
187 const ALG_NAME: &'static str = Hash_ML_DSA_65_with_SHA256_NAME;
188 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_128bit;
189}
190
191#[allow(non_camel_case_types)]
193pub type HashMLDSA87_with_SHA256 = HashMLDSA<
194 SHA256,
195 32,
196 SHA256_OID,
197 MLDSA87_PK_LEN,
198 MLDSA87_SK_LEN,
199 MLDSA87_SIG_LEN,
200 MLDSA87PublicKey,
201 MLDSA87PrivateKey,
202 MLDSA87_TAU,
203 MLDSA87_LAMBDA,
204 MLDSA87_GAMMA1,
205 MLDSA87_GAMMA2,
206 MLDSA87_k,
207 MLDSA87_l,
208 MLDSA87_ETA,
209 MLDSA87_BETA,
210 MLDSA87_OMEGA,
211 MLDSA87_C_TILDE,
212 MLDSA87_POLY_Z_PACKED_LEN,
213 MLDSA87_POLY_W1_PACKED_LEN,
214 MLDSA87_S1_PACKED_LEN,
215 MLDSA87_S2_PACKED_LEN,
216 MLDSA87_T1_PACKED_LEN,
217 MLDSA87_POLY_ETA_PACKED_LEN,
218 MLDSA87_LAMBDA_over_4,
219 MLDSA87_GAMMA1_MASK_LEN,
220>;
221
222impl Algorithm for HashMLDSA87_with_SHA256 {
223 const ALG_NAME: &'static str = Hash_ML_DSA_87_with_SHA256_NAME;
224 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_128bit;
225}
226
227#[allow(non_camel_case_types)]
229pub type HashMLDSA44_with_SHA512 = HashMLDSA<
230 SHA512,
231 64,
232 SHA512_OID,
233 MLDSA44_PK_LEN,
234 MLDSA44_SK_LEN,
235 MLDSA44_SIG_LEN,
236 MLDSA44PublicKey,
237 MLDSA44PrivateKey,
238 MLDSA44_TAU,
239 MLDSA44_LAMBDA,
240 MLDSA44_GAMMA1,
241 MLDSA44_GAMMA2,
242 MLDSA44_k,
243 MLDSA44_l,
244 MLDSA44_ETA,
245 MLDSA44_BETA,
246 MLDSA44_OMEGA,
247 MLDSA44_C_TILDE,
248 MLDSA44_POLY_Z_PACKED_LEN,
249 MLDSA44_POLY_W1_PACKED_LEN,
250 MLDSA44_S1_PACKED_LEN,
251 MLDSA44_S2_PACKED_LEN,
252 MLDSA44_T1_PACKED_LEN,
253 MLDSA44_POLY_ETA_PACKED_LEN,
254 MLDSA44_LAMBDA_over_4,
255 MLDSA44_GAMMA1_MASK_LEN,
256>;
257
258impl Algorithm for HashMLDSA44_with_SHA512 {
259 const ALG_NAME: &'static str = Hash_ML_DSA_44_with_SHA512_NAME;
260 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_128bit;
261}
262
263#[allow(non_camel_case_types)]
265pub type HashMLDSA65_with_SHA512 = HashMLDSA<
266 SHA512,
267 64,
268 SHA512_OID,
269 MLDSA65_PK_LEN,
270 MLDSA65_SK_LEN,
271 MLDSA65_SIG_LEN,
272 MLDSA65PublicKey,
273 MLDSA65PrivateKey,
274 MLDSA65_TAU,
275 MLDSA65_LAMBDA,
276 MLDSA65_GAMMA1,
277 MLDSA65_GAMMA2,
278 MLDSA65_k,
279 MLDSA65_l,
280 MLDSA65_ETA,
281 MLDSA65_BETA,
282 MLDSA65_OMEGA,
283 MLDSA65_C_TILDE,
284 MLDSA65_POLY_Z_PACKED_LEN,
285 MLDSA65_POLY_W1_PACKED_LEN,
286 MLDSA65_S1_PACKED_LEN,
287 MLDSA65_S2_PACKED_LEN,
288 MLDSA65_T1_PACKED_LEN,
289 MLDSA65_POLY_ETA_PACKED_LEN,
290 MLDSA65_LAMBDA_over_4,
291 MLDSA65_GAMMA1_MASK_LEN,
292>;
293
294impl Algorithm for HashMLDSA65_with_SHA512 {
295 const ALG_NAME: &'static str = Hash_ML_DSA_65_with_SHA512_NAME;
296 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_192bit;
297}
298
299#[allow(non_camel_case_types)]
301pub type HashMLDSA87_with_SHA512 = HashMLDSA<
302 SHA512,
303 64,
304 SHA512_OID,
305 MLDSA87_PK_LEN,
306 MLDSA87_SK_LEN,
307 MLDSA87_SIG_LEN,
308 MLDSA87PublicKey,
309 MLDSA87PrivateKey,
310 MLDSA87_TAU,
311 MLDSA87_LAMBDA,
312 MLDSA87_GAMMA1,
313 MLDSA87_GAMMA2,
314 MLDSA87_k,
315 MLDSA87_l,
316 MLDSA87_ETA,
317 MLDSA87_BETA,
318 MLDSA87_OMEGA,
319 MLDSA87_C_TILDE,
320 MLDSA87_POLY_Z_PACKED_LEN,
321 MLDSA87_POLY_W1_PACKED_LEN,
322 MLDSA87_S1_PACKED_LEN,
323 MLDSA87_S2_PACKED_LEN,
324 MLDSA87_T1_PACKED_LEN,
325 MLDSA87_POLY_ETA_PACKED_LEN,
326 MLDSA87_LAMBDA_over_4,
327 MLDSA87_GAMMA1_MASK_LEN,
328>;
329
330impl Algorithm for HashMLDSA87_with_SHA512 {
331 const ALG_NAME: &'static str = Hash_ML_DSA_87_with_SHA512_NAME;
332 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_256bit;
333}
334
335pub struct HashMLDSA<
342 HASH: Hash + Default,
343 const HASH_LEN: usize,
344 const oid: &'static [u8],
345 const PK_LEN: usize,
346 const SK_LEN: usize,
347 const SIG_LEN: usize,
348 PK: MLDSAPublicKeyTrait<k, T1_PACKED_LEN, PK_LEN> + MLDSAPublicKeyInternalTrait<k, T1_PACKED_LEN, PK_LEN>,
349 SK: MLDSAPrivateKeyTrait<k, l, S1_PACKED_LEN, S2_PACKED_LEN, T1_PACKED_LEN, PK_LEN, SK_LEN>
350 + MLDSAPrivateKeyInternalTrait<LAMBDA, GAMMA2, k, l, ETA, S1_PACKED_LEN, S2_PACKED_LEN, PK_LEN, SK_LEN>,
351 const TAU: i32,
352 const LAMBDA: i32,
353 const GAMMA1: i32,
354 const GAMMA2: i32,
355 const k: usize,
356 const l: usize,
357 const ETA: usize,
358 const BETA: i32,
359 const OMEGA: i32,
360 const C_TILDE: usize,
361 const POLY_Z_PACKED_LEN: usize,
362 const POLY_W1_PACKED_LEN: usize,
363 const S1_PACKED_LEN: usize,
364 const S2_PACKED_LEN: usize,
365 const T1_PACKED_LEN: usize,
366 const POLY_ETA_PACKED_LEN: usize,
367 const LAMBDA_over_4: usize,
368 const GAMMA1_MASK_LEN: usize,
369> {
370 _phantom: PhantomData<(PK, SK)>,
371
372 signer_rnd: Option<[u8; RND_LEN]>,
373
374 sk: Option<SK>,
376
377 seed: Option<KeyMaterialSized<32>>,
379
380 pk: Option<PK>,
382
383 hash: HASH,
385
386 ctx: [u8; 255],
389 ctx_len: usize,
390}
391
392impl<
393 HASH: Hash + Default,
394 const PH_LEN: usize,
395 const oid: &'static [u8],
396 const PK_LEN: usize,
397 const SK_LEN: usize,
398 const SIG_LEN: usize,
399 PK: MLDSAPublicKeyTrait<k, T1_PACKED_LEN, PK_LEN> + MLDSAPublicKeyInternalTrait<k, T1_PACKED_LEN, PK_LEN>,
400 SK: MLDSAPrivateKeyTrait<k, l, S1_PACKED_LEN, S2_PACKED_LEN, T1_PACKED_LEN, PK_LEN, SK_LEN>
401 + MLDSAPrivateKeyInternalTrait<LAMBDA, GAMMA2, k, l, ETA, S1_PACKED_LEN, S2_PACKED_LEN, PK_LEN, SK_LEN>,
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 POLY_ETA_PACKED_LEN: usize,
418 const LAMBDA_over_4: usize,
419 const GAMMA1_MASK_LEN: usize,
420>
421 HashMLDSA<
422 HASH,
423 PH_LEN,
424 oid,
425 PK_LEN,
426 SK_LEN,
427 SIG_LEN,
428 PK,
429 SK,
430 TAU,
431 LAMBDA,
432 GAMMA1,
433 GAMMA2,
434 k,
435 l,
436 ETA,
437 BETA,
438 OMEGA,
439 C_TILDE,
440 POLY_Z_PACKED_LEN,
441 POLY_W1_PACKED_LEN,
442 S1_PACKED_LEN,
443 S2_PACKED_LEN,
444 T1_PACKED_LEN,
445 POLY_ETA_PACKED_LEN,
446 LAMBDA_over_4,
447 GAMMA1_MASK_LEN,
448 >
449{
450 pub fn keygen_from_seed(seed: &KeyMaterialSized<32>) -> Result<(PK, SK), SignatureError> {
452 MLDSA::<
453 PK_LEN,
454 SK_LEN,
455 SIG_LEN,
456 PK,
457 SK,
458 TAU,
459 LAMBDA,
460 GAMMA1,
461 GAMMA2,
462 k,
463 l,
464 ETA,
465 BETA,
466 OMEGA,
467 C_TILDE,
468 POLY_Z_PACKED_LEN,
469 POLY_W1_PACKED_LEN,
470 S1_PACKED_LEN,
471 S2_PACKED_LEN,
472 T1_PACKED_LEN,
473 POLY_ETA_PACKED_LEN,
474 LAMBDA_over_4,
475 GAMMA1_MASK_LEN,
476 >::keygen_internal(seed)
477 }
478
479 pub fn sign_ph_deterministic(
493 sk: &SK,
494 ctx: Option<&[u8]>,
495 ph: &[u8; PH_LEN],
496 rnd: [u8; 32],
497 ) -> Result<[u8; SIG_LEN], SignatureError> {
498 let mut out: [u8; SIG_LEN] = [0u8; SIG_LEN];
499 Self::sign_ph_deterministic_out(sk, ctx, ph, rnd, &mut out)?;
500 Ok(out)
501 }
502
503 pub fn sign_ph_deterministic_out(
516 sk: &SK,
517 ctx: Option<&[u8]>,
518 ph: &[u8; PH_LEN],
519 rnd: [u8; 32],
520 output: &mut [u8; SIG_LEN],
521 ) -> Result<usize, SignatureError> {
522 let ctx = if ctx.is_some() { ctx.unwrap() } else { &[] };
523
524 if ctx.len() > 255 {
527 return Err(SignatureError::LengthError("ctx value is longer than 255 bytes"));
528 }
529
530 let mut h = H::new();
533 h.absorb(&sk.tr());
534
535 h.absorb(&[1u8]);
539 h.absorb(&[ctx.len() as u8]);
540 h.absorb(ctx);
541 h.absorb(oid);
542 h.absorb(ph);
543 let mut mu = [0u8; MU_LEN];
544 let bytes_written = h.squeeze_out(&mut mu);
545 debug_assert_eq!(bytes_written, MU_LEN);
546
547 let bytes_written = MLDSA::<
549 PK_LEN,
550 SK_LEN,
551 SIG_LEN,
552 PK,
553 SK,
554 TAU,
555 LAMBDA,
556 GAMMA1,
557 GAMMA2,
558 k,
559 l,
560 ETA,
561 BETA,
562 OMEGA,
563 C_TILDE,
564 POLY_Z_PACKED_LEN,
565 POLY_W1_PACKED_LEN,
566 S1_PACKED_LEN,
567 S2_PACKED_LEN,
568 T1_PACKED_LEN,
569 POLY_ETA_PACKED_LEN,
570 LAMBDA_over_4,
571 GAMMA1_MASK_LEN,
572 >::sign_mu_deterministic_out(sk, &mu, rnd, output)?;
573
574 Ok(bytes_written)
575 }
576
577 pub fn set_signer_rnd(&mut self, rnd: [u8; 32]) {
581 self.signer_rnd = Some(rnd);
582 }
583
584 fn parse_ctx(ctx: Option<&[u8]>) -> Result<([u8; 255], usize), SignatureError> {
585 if ctx.is_some() {
586 if ctx.unwrap().len() > 255 {
589 return Err(SignatureError::LengthError("ctx value is longer than 255 bytes"));
590 }
591
592 let mut ctx_buf = [0u8; 255];
593 ctx_buf[..ctx.unwrap().len()].copy_from_slice(ctx.unwrap());
594 Ok((ctx_buf, ctx.unwrap().len()))
595 } else {
596 Ok(([0u8; 255], 0))
597 }
598 }
599
600 pub fn sign_init_from_seed(seed: &KeyMaterialSized<32>, ctx: Option<&[u8]>) -> Result<Self, SignatureError> {
603 let (ctx, ctx_len) = Self::parse_ctx(ctx)?;
604 Ok(
605 Self {
606 _phantom: PhantomData,
607 signer_rnd: None,
608 sk: None,
609 seed: Some(seed.clone()),
610 pk: None,
611 hash: HASH::default(),
612 ctx,
613 ctx_len,
614 }
615 )
616 }
617}
618
619impl<
620 HASH: Hash + Default,
621 PK: MLDSAPublicKeyTrait<k, T1_PACKED_LEN, PK_LEN> + MLDSAPublicKeyInternalTrait<k, T1_PACKED_LEN, PK_LEN>,
622 SK: MLDSAPrivateKeyTrait<k, l, S1_PACKED_LEN, S2_PACKED_LEN, T1_PACKED_LEN, PK_LEN, SK_LEN>
623 + MLDSAPrivateKeyInternalTrait<LAMBDA, GAMMA2, k, l, ETA, S1_PACKED_LEN, S2_PACKED_LEN, PK_LEN, SK_LEN>,
624 const PH_LEN: usize,
625 const oid: &'static [u8],
626 const PK_LEN: usize,
627 const SK_LEN: usize,
628 const SIG_LEN: usize,
629 const TAU: i32,
630 const LAMBDA: i32,
631 const GAMMA1: i32,
632 const GAMMA2: i32,
633 const k: usize,
634 const l: usize,
635 const ETA: usize,
636 const BETA: i32,
637 const OMEGA: i32,
638 const C_TILDE: usize,
639 const POLY_Z_PACKED_LEN: usize,
640 const POLY_W1_PACKED_LEN: usize,
641 const S1_PACKED_LEN: usize,
642 const S2_PACKED_LEN: usize,
643 const T1_PACKED_LEN: usize,
644 const POLY_ETA_PACKED_LEN: usize,
645 const LAMBDA_over_4: usize,
646 const GAMMA1_MASK_LEN: usize,
647> Signature<PK, SK>
648 for HashMLDSA<
649 HASH,
650 PH_LEN,
651 oid,
652 PK_LEN,
653 SK_LEN,
654 SIG_LEN,
655 PK,
656 SK,
657 TAU,
658 LAMBDA,
659 GAMMA1,
660 GAMMA2,
661 k,
662 l,
663 ETA,
664 BETA,
665 OMEGA,
666 C_TILDE,
667 POLY_Z_PACKED_LEN,
668 POLY_W1_PACKED_LEN,
669 S1_PACKED_LEN,
670 S2_PACKED_LEN,
671 T1_PACKED_LEN,
672 POLY_ETA_PACKED_LEN,
673 LAMBDA_over_4,
674 GAMMA1_MASK_LEN,
675 >
676{
677 fn keygen() -> Result<(PK, SK), SignatureError> {
679 MLDSA::<
680 PK_LEN,
681 SK_LEN,
682 SIG_LEN,
683 PK,
684 SK,
685 TAU,
686 LAMBDA,
687 GAMMA1,
688 GAMMA2,
689 k,
690 l,
691 ETA,
692 BETA,
693 OMEGA,
694 C_TILDE,
695 POLY_Z_PACKED_LEN,
696 POLY_W1_PACKED_LEN,
697 S1_PACKED_LEN,
698 S2_PACKED_LEN,
699 T1_PACKED_LEN,
700 POLY_ETA_PACKED_LEN,
701 LAMBDA_over_4,
702 GAMMA1_MASK_LEN,
703 >::keygen()
704 }
705
706 fn sign(sk: &SK, msg: &[u8], ctx: Option<&[u8]>) -> Result<Vec<u8>, SignatureError> {
709 let mut out = vec![0u8; SIG_LEN];
710 Self::sign_out(sk, msg, ctx, &mut out)?;
711
712 Ok(out)
713 }
714
715 fn sign_out(
716 sk: &SK,
717 msg: &[u8],
718 ctx: Option<&[u8]>,
719 output: &mut [u8],
720 ) -> Result<usize, SignatureError> {
721 let mut ph_m = [0u8; PH_LEN];
722 _ = HASH::default().hash_out(msg, &mut ph_m);
723 Self::sign_ph_out(sk, &ph_m, ctx, output)
724 }
725
726 fn sign_init(sk: &SK, ctx: Option<&[u8]>) -> Result<Self, SignatureError> {
727 let (ctx, ctx_len) = Self::parse_ctx(ctx)?;
728 Ok(
729 Self {
730 _phantom: PhantomData,
731 signer_rnd: None,
732 sk: Some(sk.clone()),
733 seed: None,
734 pk: None,
735 hash: HASH::default(),
736 ctx,
737 ctx_len,
738 }
739 )
740 }
741
742 fn sign_update(&mut self, msg_chunk: &[u8]) {
743 self.hash.do_update(msg_chunk);
744 }
745
746 fn sign_final(self) -> Result<Vec<u8>, SignatureError> {
747 let mut out = [0u8; SIG_LEN];
748 self.sign_final_out(&mut out)?;
749 Ok(Vec::from(out))
750 }
751
752 fn sign_final_out(self, output: &mut [u8]) -> Result<usize, SignatureError> {
753 let ph: [u8; PH_LEN] = self.hash.do_final().try_into().unwrap();
754
755 if self.sk.is_none() && self.seed.is_none() {
756 return Err(SignatureError::GenericError("Somehow you managed to construct a streaming signer without a private key, impressive!"))
757 }
758
759 if output.len() < SIG_LEN { return Err(SignatureError::LengthError("Output buffer insufficient size to hold signature")) }
760 let output_sized: &mut [u8; SIG_LEN] = output[..SIG_LEN].as_mut().try_into().unwrap();
761
762 if self.sk.is_some() {
763 if self.signer_rnd.is_none() {
764 Self::sign_ph_out(&self.sk.unwrap(), &ph, Some(&self.ctx[..self.ctx_len]), output_sized)
765 } else {
766 Self::sign_ph_deterministic_out(&self.sk.unwrap(), Some(&self.ctx[..self.ctx_len]), &ph, self.signer_rnd.unwrap(), output_sized)
767 }
768 } else if self.seed.is_some() {
769 let rnd = if self.signer_rnd.is_some() {
770 self.signer_rnd.unwrap()
771 } else {
772 let mut rnd: [u8; RND_LEN] = [0u8; RND_LEN];
773 HashDRBG_SHA512::new_from_os().next_bytes_out(&mut rnd)?;
774 rnd
775 };
776 let (_pk, sk) = Self::keygen_from_seed(&self.seed.unwrap())?;
779 Self::sign_ph_deterministic_out(&sk, Some(&self.ctx[..self.ctx_len]), &ph, rnd, output_sized)
780 } else { unreachable!() }
781 }
782
783 fn verify(pk: &PK, msg: &[u8], ctx: Option<&[u8]>, sig: &[u8]) -> Result<(), SignatureError> {
784 let mut ph_m = [0u8; PH_LEN];
785 _ = HASH::default().hash_out(msg, &mut ph_m);
786
787 Self::verify_ph(pk, &ph_m, ctx, sig)
788 }
789
790 fn verify_init(pk: &PK, ctx: Option<&[u8]>) -> Result<Self, SignatureError> {
791 let (ctx, ctx_len) = Self::parse_ctx(ctx)?;
792 Ok(
793 Self {
794 _phantom: Default::default(),
795 signer_rnd: None,
796 sk: None,
797 seed: None,
798 pk: Some(pk.clone()),
799 hash: HASH::default(),
800 ctx,
801 ctx_len,
802 }
803 )
804 }
805
806 fn verify_update(&mut self, msg_chunk: &[u8]) {
807 self.hash.do_update(msg_chunk);
808 }
809
810 fn verify_final(self, sig: &[u8]) -> Result<(), SignatureError> {
811 let ph: [u8; PH_LEN] = self.hash.do_final().try_into().unwrap();
812
813 assert!(self.pk.is_some(), "Somehow you managed to construct a streaming verifier without a public key, impressive!");
814
815 if sig.len() != SIG_LEN { return Err(SignatureError::LengthError("Signature value is not the correct length.")) }
816 Self::verify_ph(&self.pk.unwrap(), &ph, Some(&self.ctx[..self.ctx_len]), &sig[..SIG_LEN])
817 }
818}
819
820impl<
821 HASH: Hash + Default,
822 const PH_LEN: usize,
823 const oid: &'static [u8],
824 const PK_LEN: usize,
825 const SK_LEN: usize,
826 const SIG_LEN: usize,
827 PK: MLDSAPublicKeyTrait<k, T1_PACKED_LEN, PK_LEN> + MLDSAPublicKeyInternalTrait<k, T1_PACKED_LEN, PK_LEN>,
828 SK: MLDSAPrivateKeyTrait<k, l, S1_PACKED_LEN, S2_PACKED_LEN, T1_PACKED_LEN, PK_LEN, SK_LEN>
829 + MLDSAPrivateKeyInternalTrait<LAMBDA, GAMMA2, k, l, ETA, S1_PACKED_LEN, S2_PACKED_LEN, PK_LEN, SK_LEN>,
830 const TAU: i32,
831 const LAMBDA: i32,
832 const GAMMA1: i32,
833 const GAMMA2: i32,
834 const k: usize,
835 const l: usize,
836 const ETA: usize,
837 const BETA: i32,
838 const OMEGA: i32,
839 const C_TILDE: usize,
840 const POLY_Z_PACKED_LEN: usize,
841 const POLY_W1_PACKED_LEN: usize,
842 const S1_PACKED_LEN: usize,
843 const S2_PACKED_LEN: usize,
844 const T1_PACKED_LEN: usize,
845 const POLY_ETA_PACKED_LEN: usize,
846 const LAMBDA_over_4: usize,
847 const GAMMA1_MASK_LEN: usize,
848> PHSignature<PK, SK, PH_LEN>
849 for HashMLDSA<
850 HASH,
851 PH_LEN,
852 oid,
853 PK_LEN,
854 SK_LEN,
855 SIG_LEN,
856 PK,
857 SK,
858 TAU,
859 LAMBDA,
860 GAMMA1,
861 GAMMA2,
862 k,
863 l,
864 ETA,
865 BETA,
866 OMEGA,
867 C_TILDE,
868 POLY_Z_PACKED_LEN,
869 POLY_W1_PACKED_LEN,
870 S1_PACKED_LEN,
871 S2_PACKED_LEN,
872 T1_PACKED_LEN,
873 POLY_ETA_PACKED_LEN,
874 LAMBDA_over_4,
875 GAMMA1_MASK_LEN,
876 >
877{
878
879 fn sign_ph(sk: &SK, ph: &[u8; PH_LEN], ctx: Option<&[u8]>) -> Result<Vec<u8>, SignatureError> {
880 let mut out = vec![0u8; SIG_LEN];
881 Self::sign_out(sk, ph, ctx, &mut out)?;
882
883 Ok(out)
884 }
885
886 fn sign_ph_out(
891 sk: &SK,
892 ph: &[u8; PH_LEN],
893 ctx: Option<&[u8]>,
894 output: &mut [u8],
895 ) -> Result<usize, SignatureError> {
896 if output.len() < SIG_LEN {
897 return Err(SignatureError::LengthError(
898 "Output buffer insufficient size to hold signature",
899 ));
900 }
901 let output_sized: &mut [u8; SIG_LEN] = output[..SIG_LEN].as_mut().try_into().unwrap();
902
903 let mut rnd: [u8; RND_LEN] = [0u8; RND_LEN];
904 HashDRBG_SHA512::new_from_os().next_bytes_out(&mut rnd)?;
905 Self::sign_ph_deterministic_out(sk, ctx, ph, rnd, output_sized)
906 }
907
908 fn verify_ph(
909 pk: &PK,
910 ph: &[u8; PH_LEN],
911 ctx: Option<&[u8]>,
912 sig: &[u8],
913 ) -> Result<(), SignatureError> {
914 if sig.len() != SIG_LEN {
915 return Err(SignatureError::LengthError("Signature value is not the correct length."));
916 }
917
918 let ctx = if ctx.is_some() { ctx.unwrap() } else { &[] };
919
920 if ctx.len() > 255 {
923 return Err(SignatureError::LengthError("ctx value is longer than 255 bytes"));
924 }
925
926 let mut h = H::new();
929 h.absorb(&pk.compute_tr());
930
931 h.absorb(&[1u8]);
935 h.absorb(&[ctx.len() as u8]);
936 h.absorb(ctx);
937 h.absorb(oid);
938 h.absorb(ph);
939 let mut mu = [0u8; MU_LEN];
940 _ = h.squeeze_out(&mut mu);
941
942 if MLDSA::<
943 PK_LEN,
944 SK_LEN,
945 SIG_LEN,
946 PK,
947 SK,
948 TAU,
949 LAMBDA,
950 GAMMA1,
951 GAMMA2,
952 k,
953 l,
954 ETA,
955 BETA,
956 OMEGA,
957 C_TILDE,
958 POLY_Z_PACKED_LEN,
959 POLY_W1_PACKED_LEN,
960 S1_PACKED_LEN,
961 S2_PACKED_LEN,
962 T1_PACKED_LEN,
963 POLY_ETA_PACKED_LEN,
964 LAMBDA_over_4,
965 GAMMA1_MASK_LEN,
966 >::verify_mu_internal(pk, &mu, &sig[..SIG_LEN].try_into().unwrap())
967 {
968 Ok(())
969 } else {
970 Err(SignatureError::SignatureVerificationFailed)
971 }
972 }
973}