1use crate::mldsa::{H, MLDSA_MU_LEN, MLDSA_RND_LEN, MLDSATrait};
67use crate::mldsa::{
68 MLDSA44_BETA, MLDSA44_C_TILDE, MLDSA44_ETA, MLDSA44_FULL_SK_LEN, MLDSA44_GAMMA1,
69 MLDSA44_GAMMA1_MASK_LEN, MLDSA44_GAMMA2, MLDSA44_LAMBDA, MLDSA44_LAMBDA_over_4, MLDSA44_OMEGA,
70 MLDSA44_PK_LEN, MLDSA44_POLY_ETA_PACKED_LEN, MLDSA44_POLY_W1_PACKED_LEN,
71 MLDSA44_POLY_Z_PACKED_LEN, MLDSA44_S1_PACKED_LEN, MLDSA44_S2_PACKED_LEN, MLDSA44_SIG_LEN,
72 MLDSA44_SK_LEN, MLDSA44_TAU, MLDSA44_k, MLDSA44_l,
73};
74use crate::mldsa::{MLDSA44_T1_PACKED_LEN, MLDSA65_T1_PACKED_LEN, MLDSA87_T1_PACKED_LEN};
75use crate::mldsa::{
76 MLDSA65_BETA, MLDSA65_C_TILDE, MLDSA65_ETA, MLDSA65_FULL_SK_LEN, MLDSA65_GAMMA1,
77 MLDSA65_GAMMA1_MASK_LEN, MLDSA65_GAMMA2, MLDSA65_LAMBDA, MLDSA65_LAMBDA_over_4, MLDSA65_OMEGA,
78 MLDSA65_PK_LEN, MLDSA65_POLY_ETA_PACKED_LEN, MLDSA65_POLY_W1_PACKED_LEN,
79 MLDSA65_POLY_Z_PACKED_LEN, MLDSA65_S1_PACKED_LEN, MLDSA65_S2_PACKED_LEN, MLDSA65_SIG_LEN,
80 MLDSA65_SK_LEN, MLDSA65_TAU, MLDSA65_k, MLDSA65_l,
81};
82use crate::mldsa::{
83 MLDSA87_BETA, MLDSA87_C_TILDE, MLDSA87_ETA, MLDSA87_FULL_SK_LEN, MLDSA87_GAMMA1,
84 MLDSA87_GAMMA1_MASK_LEN, MLDSA87_GAMMA2, MLDSA87_LAMBDA, MLDSA87_LAMBDA_over_4, MLDSA87_OMEGA,
85 MLDSA87_PK_LEN, MLDSA87_POLY_ETA_PACKED_LEN, MLDSA87_POLY_W1_PACKED_LEN,
86 MLDSA87_POLY_Z_PACKED_LEN, MLDSA87_S1_PACKED_LEN, MLDSA87_S2_PACKED_LEN, MLDSA87_SIG_LEN,
87 MLDSA87_SK_LEN, MLDSA87_TAU, MLDSA87_k, MLDSA87_l,
88};
89use crate::mldsa_keys::{MLDSAPrivateKeyInternalTrait, MLDSAPublicKeyInternalTrait};
90use crate::{
91 MLDSA, MLDSA44PrivateKey, MLDSA44PublicKey, MLDSA65PrivateKey, MLDSA65PublicKey,
92 MLDSA87PrivateKey, MLDSA87PublicKey, MLDSAPrivateKeyTrait, MLDSAPublicKeyTrait,
93};
94use bouncycastle_core::errors::SignatureError;
95use bouncycastle_core::key_material::KeyMaterial;
96use bouncycastle_core::traits::{
97 Algorithm, Hash, PHSignature, RNG, SecurityStrength, Signature, XOF,
98};
99use bouncycastle_rng::HashDRBG_SHA512;
100use bouncycastle_sha2::{SHA256, SHA512};
101use core::marker::PhantomData;
102
103#[allow(unused_imports)]
105use crate::mldsa::MuBuilder;
106
107const SHA256_OID: &[u8] = &[0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01];
108const SHA512_OID: &[u8] = &[0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03];
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 SHA256_OID,
133 MLDSA44_PK_LEN,
134 MLDSA44_SK_LEN,
135 MLDSA44_FULL_SK_LEN,
136 MLDSA44_SIG_LEN,
137 MLDSA44PublicKey,
138 MLDSA44PrivateKey,
139 MLDSA44_TAU,
140 MLDSA44_LAMBDA,
141 MLDSA44_GAMMA1,
142 MLDSA44_GAMMA2,
143 MLDSA44_k,
144 MLDSA44_l,
145 MLDSA44_ETA,
146 MLDSA44_BETA,
147 MLDSA44_OMEGA,
148 MLDSA44_C_TILDE,
149 MLDSA44_POLY_Z_PACKED_LEN,
150 MLDSA44_POLY_W1_PACKED_LEN,
151 MLDSA44_S1_PACKED_LEN,
152 MLDSA44_S2_PACKED_LEN,
153 MLDSA44_T1_PACKED_LEN,
154 MLDSA44_POLY_ETA_PACKED_LEN,
155 MLDSA44_LAMBDA_over_4,
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 SHA256_OID,
170 MLDSA65_PK_LEN,
171 MLDSA65_SK_LEN,
172 MLDSA65_FULL_SK_LEN,
173 MLDSA65_SIG_LEN,
174 MLDSA65PublicKey,
175 MLDSA65PrivateKey,
176 MLDSA65_TAU,
177 MLDSA65_LAMBDA,
178 MLDSA65_GAMMA1,
179 MLDSA65_GAMMA2,
180 MLDSA65_k,
181 MLDSA65_l,
182 MLDSA65_ETA,
183 MLDSA65_BETA,
184 MLDSA65_OMEGA,
185 MLDSA65_C_TILDE,
186 MLDSA65_POLY_Z_PACKED_LEN,
187 MLDSA65_POLY_W1_PACKED_LEN,
188 MLDSA65_S1_PACKED_LEN,
189 MLDSA65_S2_PACKED_LEN,
190 MLDSA65_T1_PACKED_LEN,
191 MLDSA65_POLY_ETA_PACKED_LEN,
192 MLDSA65_LAMBDA_over_4,
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 SHA256_OID,
207 MLDSA87_PK_LEN,
208 MLDSA87_SK_LEN,
209 MLDSA87_FULL_SK_LEN,
210 MLDSA87_SIG_LEN,
211 MLDSA87PublicKey,
212 MLDSA87PrivateKey,
213 MLDSA87_TAU,
214 MLDSA87_LAMBDA,
215 MLDSA87_GAMMA1,
216 MLDSA87_GAMMA2,
217 MLDSA87_k,
218 MLDSA87_l,
219 MLDSA87_ETA,
220 MLDSA87_BETA,
221 MLDSA87_OMEGA,
222 MLDSA87_C_TILDE,
223 MLDSA87_POLY_Z_PACKED_LEN,
224 MLDSA87_POLY_W1_PACKED_LEN,
225 MLDSA87_S1_PACKED_LEN,
226 MLDSA87_S2_PACKED_LEN,
227 MLDSA87_T1_PACKED_LEN,
228 MLDSA87_POLY_ETA_PACKED_LEN,
229 MLDSA87_LAMBDA_over_4,
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 SHA512_OID,
244 MLDSA44_PK_LEN,
245 MLDSA44_SK_LEN,
246 MLDSA44_FULL_SK_LEN,
247 MLDSA44_SIG_LEN,
248 MLDSA44PublicKey,
249 MLDSA44PrivateKey,
250 MLDSA44_TAU,
251 MLDSA44_LAMBDA,
252 MLDSA44_GAMMA1,
253 MLDSA44_GAMMA2,
254 MLDSA44_k,
255 MLDSA44_l,
256 MLDSA44_ETA,
257 MLDSA44_BETA,
258 MLDSA44_OMEGA,
259 MLDSA44_C_TILDE,
260 MLDSA44_POLY_Z_PACKED_LEN,
261 MLDSA44_POLY_W1_PACKED_LEN,
262 MLDSA44_S1_PACKED_LEN,
263 MLDSA44_S2_PACKED_LEN,
264 MLDSA44_T1_PACKED_LEN,
265 MLDSA44_POLY_ETA_PACKED_LEN,
266 MLDSA44_LAMBDA_over_4,
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}
274
275#[allow(non_camel_case_types)]
277pub type HashMLDSA65_with_SHA512 = HashMLDSA<
278 SHA512,
279 64,
280 SHA512_OID,
281 MLDSA65_PK_LEN,
282 MLDSA65_SK_LEN,
283 MLDSA65_FULL_SK_LEN,
284 MLDSA65_SIG_LEN,
285 MLDSA65PublicKey,
286 MLDSA65PrivateKey,
287 MLDSA65_TAU,
288 MLDSA65_LAMBDA,
289 MLDSA65_GAMMA1,
290 MLDSA65_GAMMA2,
291 MLDSA65_k,
292 MLDSA65_l,
293 MLDSA65_ETA,
294 MLDSA65_BETA,
295 MLDSA65_OMEGA,
296 MLDSA65_C_TILDE,
297 MLDSA65_POLY_Z_PACKED_LEN,
298 MLDSA65_POLY_W1_PACKED_LEN,
299 MLDSA65_S1_PACKED_LEN,
300 MLDSA65_S2_PACKED_LEN,
301 MLDSA65_T1_PACKED_LEN,
302 MLDSA65_POLY_ETA_PACKED_LEN,
303 MLDSA65_LAMBDA_over_4,
304 MLDSA65_GAMMA1_MASK_LEN,
305>;
306
307impl Algorithm for HashMLDSA65_with_SHA512 {
308 const ALG_NAME: &'static str = HASH_ML_DSA_65_WITH_SHA512_NAME;
309 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_192bit;
310}
311
312#[allow(non_camel_case_types)]
314pub type HashMLDSA87_with_SHA512 = HashMLDSA<
315 SHA512,
316 64,
317 SHA512_OID,
318 MLDSA87_PK_LEN,
319 MLDSA87_SK_LEN,
320 MLDSA87_FULL_SK_LEN,
321 MLDSA87_SIG_LEN,
322 MLDSA87PublicKey,
323 MLDSA87PrivateKey,
324 MLDSA87_TAU,
325 MLDSA87_LAMBDA,
326 MLDSA87_GAMMA1,
327 MLDSA87_GAMMA2,
328 MLDSA87_k,
329 MLDSA87_l,
330 MLDSA87_ETA,
331 MLDSA87_BETA,
332 MLDSA87_OMEGA,
333 MLDSA87_C_TILDE,
334 MLDSA87_POLY_Z_PACKED_LEN,
335 MLDSA87_POLY_W1_PACKED_LEN,
336 MLDSA87_S1_PACKED_LEN,
337 MLDSA87_S2_PACKED_LEN,
338 MLDSA87_T1_PACKED_LEN,
339 MLDSA87_POLY_ETA_PACKED_LEN,
340 MLDSA87_LAMBDA_over_4,
341 MLDSA87_GAMMA1_MASK_LEN,
342>;
343
344impl Algorithm for HashMLDSA87_with_SHA512 {
345 const ALG_NAME: &'static str = HASH_ML_DSA_87_WITH_SHA512_NAME;
346 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_256bit;
347}
348
349pub struct HashMLDSA<
356 HASH: Hash + Default,
357 const HASH_LEN: usize,
358 const oid: &'static [u8],
359 const PK_LEN: usize,
360 const SK_LEN: usize,
361 const FULL_SK_LEN: usize,
362 const SIG_LEN: usize,
363 PK: MLDSAPublicKeyTrait<k, T1_PACKED_LEN, PK_LEN>
364 + MLDSAPublicKeyInternalTrait<k, T1_PACKED_LEN, PK_LEN>,
365 SK: MLDSAPrivateKeyTrait<
366 k,
367 l,
368 S1_PACKED_LEN,
369 S2_PACKED_LEN,
370 T1_PACKED_LEN,
371 PK_LEN,
372 SK_LEN,
373 FULL_SK_LEN,
374 > + MLDSAPrivateKeyInternalTrait<
375 LAMBDA,
376 GAMMA2,
377 k,
378 l,
379 ETA,
380 S1_PACKED_LEN,
381 S2_PACKED_LEN,
382 PK_LEN,
383 SK_LEN,
384 >,
385 const TAU: i32,
386 const LAMBDA: i32,
387 const GAMMA1: i32,
388 const GAMMA2: i32,
389 const k: usize,
390 const l: usize,
391 const ETA: usize,
392 const BETA: i32,
393 const OMEGA: i32,
394 const C_TILDE: usize,
395 const POLY_Z_PACKED_LEN: usize,
396 const POLY_W1_PACKED_LEN: usize,
397 const S1_PACKED_LEN: usize,
398 const S2_PACKED_LEN: usize,
399 const T1_PACKED_LEN: usize,
400 const POLY_ETA_PACKED_LEN: usize,
401 const LAMBDA_over_4: usize,
402 const GAMMA1_MASK_LEN: usize,
403> {
404 _phantom: PhantomData<(PK, SK)>,
405
406 signer_rnd: Option<[u8; MLDSA_RND_LEN]>,
407
408 sk: Option<SK>,
410
411 seed: Option<KeyMaterial<32>>,
413
414 pk: Option<PK>,
416
417 hash: HASH,
419
420 ctx: [u8; 255],
423 ctx_len: usize,
424}
425
426impl<
427 HASH: Hash + Default,
428 const PH_LEN: usize,
429 const oid: &'static [u8],
430 const PK_LEN: usize,
431 const SK_LEN: usize,
432 const FULL_SK_LEN: usize,
433 const SIG_LEN: usize,
434 PK: MLDSAPublicKeyTrait<k, T1_PACKED_LEN, PK_LEN>
435 + MLDSAPublicKeyInternalTrait<k, T1_PACKED_LEN, PK_LEN>,
436 SK: MLDSAPrivateKeyTrait<
437 k,
438 l,
439 S1_PACKED_LEN,
440 S2_PACKED_LEN,
441 T1_PACKED_LEN,
442 PK_LEN,
443 SK_LEN,
444 FULL_SK_LEN,
445 > + MLDSAPrivateKeyInternalTrait<
446 LAMBDA,
447 GAMMA2,
448 k,
449 l,
450 ETA,
451 S1_PACKED_LEN,
452 S2_PACKED_LEN,
453 PK_LEN,
454 SK_LEN,
455 >,
456 const TAU: i32,
457 const LAMBDA: i32,
458 const GAMMA1: i32,
459 const GAMMA2: i32,
460 const k: usize,
461 const l: usize,
462 const ETA: usize,
463 const BETA: i32,
464 const OMEGA: i32,
465 const C_TILDE: usize,
466 const POLY_Z_PACKED_LEN: usize,
467 const POLY_W1_PACKED_LEN: usize,
468 const S1_PACKED_LEN: usize,
469 const S2_PACKED_LEN: usize,
470 const T1_PACKED_LEN: usize,
471 const POLY_ETA_PACKED_LEN: usize,
472 const LAMBDA_over_4: usize,
473 const GAMMA1_MASK_LEN: usize,
474>
475 HashMLDSA<
476 HASH,
477 PH_LEN,
478 oid,
479 PK_LEN,
480 SK_LEN,
481 FULL_SK_LEN,
482 SIG_LEN,
483 PK,
484 SK,
485 TAU,
486 LAMBDA,
487 GAMMA1,
488 GAMMA2,
489 k,
490 l,
491 ETA,
492 BETA,
493 OMEGA,
494 C_TILDE,
495 POLY_Z_PACKED_LEN,
496 POLY_W1_PACKED_LEN,
497 S1_PACKED_LEN,
498 S2_PACKED_LEN,
499 T1_PACKED_LEN,
500 POLY_ETA_PACKED_LEN,
501 LAMBDA_over_4,
502 GAMMA1_MASK_LEN,
503 >
504{
505 pub fn keygen_from_seed(seed: &KeyMaterial<32>) -> Result<(PK, SK), SignatureError> {
507 MLDSA::<
508 PK_LEN,
509 SK_LEN,
510 FULL_SK_LEN,
511 SIG_LEN,
512 PK,
513 SK,
514 TAU,
515 LAMBDA,
516 GAMMA1,
517 GAMMA2,
518 k,
519 l,
520 ETA,
521 BETA,
522 OMEGA,
523 C_TILDE,
524 POLY_Z_PACKED_LEN,
525 POLY_W1_PACKED_LEN,
526 S1_PACKED_LEN,
527 S2_PACKED_LEN,
528 T1_PACKED_LEN,
529 POLY_ETA_PACKED_LEN,
530 LAMBDA_over_4,
531 GAMMA1_MASK_LEN,
532 >::keygen_internal(seed)
533 }
534
535 pub fn sign_ph_deterministic(
549 sk: &SK,
550 ctx: Option<&[u8]>,
551 ph: &[u8; PH_LEN],
552 rnd: [u8; 32],
553 ) -> Result<[u8; SIG_LEN], SignatureError> {
554 let mut out: [u8; SIG_LEN] = [0u8; SIG_LEN];
555 Self::sign_ph_deterministic_out(sk, ctx, ph, rnd, &mut out)?;
556 Ok(out)
557 }
558
559 pub fn sign_ph_deterministic_out(
572 sk: &SK,
573 ctx: Option<&[u8]>,
574 ph: &[u8; PH_LEN],
575 rnd: [u8; 32],
576 output: &mut [u8; SIG_LEN],
577 ) -> Result<usize, SignatureError> {
578 let ctx = if ctx.is_some() { ctx.unwrap() } else { &[] };
579
580 if ctx.len() > 255 {
583 return Err(SignatureError::LengthError("ctx value is longer than 255 bytes"));
584 }
585
586 let mut h = H::new();
589 h.absorb(&sk.tr());
590
591 h.absorb(&[1u8]);
595 h.absorb(&[ctx.len() as u8]);
596 h.absorb(ctx);
597 h.absorb(oid);
598 h.absorb(ph);
599 let mut mu = [0u8; MLDSA_MU_LEN];
600 let bytes_written = h.squeeze_out(&mut mu);
601 debug_assert_eq!(bytes_written, MLDSA_MU_LEN);
602
603 let bytes_written = MLDSA::<
605 PK_LEN,
606 SK_LEN,
607 FULL_SK_LEN,
608 SIG_LEN,
609 PK,
610 SK,
611 TAU,
612 LAMBDA,
613 GAMMA1,
614 GAMMA2,
615 k,
616 l,
617 ETA,
618 BETA,
619 OMEGA,
620 C_TILDE,
621 POLY_Z_PACKED_LEN,
622 POLY_W1_PACKED_LEN,
623 S1_PACKED_LEN,
624 S2_PACKED_LEN,
625 T1_PACKED_LEN,
626 POLY_ETA_PACKED_LEN,
627 LAMBDA_over_4,
628 GAMMA1_MASK_LEN,
629 >::sign_mu_deterministic_out(sk, &mu, rnd, output)?;
630
631 Ok(bytes_written)
632 }
633
634 pub fn set_signer_rnd(&mut self, rnd: [u8; 32]) {
638 self.signer_rnd = Some(rnd);
639 }
640
641 fn parse_ctx(ctx: Option<&[u8]>) -> Result<([u8; 255], usize), SignatureError> {
642 if ctx.is_some() {
643 if ctx.unwrap().len() > 255 {
646 return Err(SignatureError::LengthError("ctx value is longer than 255 bytes"));
647 }
648
649 let mut ctx_buf = [0u8; 255];
650 ctx_buf[..ctx.unwrap().len()].copy_from_slice(ctx.unwrap());
651 Ok((ctx_buf, ctx.unwrap().len()))
652 } else {
653 Ok(([0u8; 255], 0))
654 }
655 }
656
657 pub fn sign_init_from_seed(
660 seed: &KeyMaterial<32>,
661 ctx: Option<&[u8]>,
662 ) -> Result<Self, SignatureError> {
663 let (ctx, ctx_len) = Self::parse_ctx(ctx)?;
664 Ok(Self {
665 _phantom: PhantomData,
666 signer_rnd: None,
667 sk: None,
668 seed: Some(seed.clone()),
669 pk: None,
670 hash: HASH::default(),
671 ctx,
672 ctx_len,
673 })
674 }
675}
676
677impl<
678 HASH: Hash + Default,
679 PK: MLDSAPublicKeyTrait<k, T1_PACKED_LEN, PK_LEN>
680 + MLDSAPublicKeyInternalTrait<k, T1_PACKED_LEN, PK_LEN>,
681 SK: MLDSAPrivateKeyTrait<
682 k,
683 l,
684 S1_PACKED_LEN,
685 S2_PACKED_LEN,
686 T1_PACKED_LEN,
687 PK_LEN,
688 SK_LEN,
689 FULL_SK_LEN,
690 > + MLDSAPrivateKeyInternalTrait<
691 LAMBDA,
692 GAMMA2,
693 k,
694 l,
695 ETA,
696 S1_PACKED_LEN,
697 S2_PACKED_LEN,
698 PK_LEN,
699 SK_LEN,
700 >,
701 const PH_LEN: usize,
702 const oid: &'static [u8],
703 const PK_LEN: usize,
704 const SK_LEN: usize,
705 const FULL_SK_LEN: usize,
706 const SIG_LEN: usize,
707 const TAU: i32,
708 const LAMBDA: i32,
709 const GAMMA1: i32,
710 const GAMMA2: i32,
711 const k: usize,
712 const l: usize,
713 const ETA: usize,
714 const BETA: i32,
715 const OMEGA: i32,
716 const C_TILDE: usize,
717 const POLY_Z_PACKED_LEN: usize,
718 const POLY_W1_PACKED_LEN: usize,
719 const S1_PACKED_LEN: usize,
720 const S2_PACKED_LEN: usize,
721 const T1_PACKED_LEN: usize,
722 const POLY_ETA_PACKED_LEN: usize,
723 const LAMBDA_over_4: usize,
724 const GAMMA1_MASK_LEN: usize,
725> Signature<PK, SK, PK_LEN, SK_LEN, SIG_LEN>
726 for HashMLDSA<
727 HASH,
728 PH_LEN,
729 oid,
730 PK_LEN,
731 SK_LEN,
732 FULL_SK_LEN,
733 SIG_LEN,
734 PK,
735 SK,
736 TAU,
737 LAMBDA,
738 GAMMA1,
739 GAMMA2,
740 k,
741 l,
742 ETA,
743 BETA,
744 OMEGA,
745 C_TILDE,
746 POLY_Z_PACKED_LEN,
747 POLY_W1_PACKED_LEN,
748 S1_PACKED_LEN,
749 S2_PACKED_LEN,
750 T1_PACKED_LEN,
751 POLY_ETA_PACKED_LEN,
752 LAMBDA_over_4,
753 GAMMA1_MASK_LEN,
754 >
755{
756 fn keygen() -> Result<(PK, SK), SignatureError> {
758 MLDSA::<
759 PK_LEN,
760 SK_LEN,
761 FULL_SK_LEN,
762 SIG_LEN,
763 PK,
764 SK,
765 TAU,
766 LAMBDA,
767 GAMMA1,
768 GAMMA2,
769 k,
770 l,
771 ETA,
772 BETA,
773 OMEGA,
774 C_TILDE,
775 POLY_Z_PACKED_LEN,
776 POLY_W1_PACKED_LEN,
777 S1_PACKED_LEN,
778 S2_PACKED_LEN,
779 T1_PACKED_LEN,
780 POLY_ETA_PACKED_LEN,
781 LAMBDA_over_4,
782 GAMMA1_MASK_LEN,
783 >::keygen()
784 }
785
786 fn sign(sk: &SK, msg: &[u8], ctx: Option<&[u8]>) -> Result<[u8; SIG_LEN], SignatureError> {
789 let mut out = [0u8; SIG_LEN];
790 Self::sign_out(sk, msg, ctx, &mut out)?;
791
792 Ok(out)
793 }
794
795 fn sign_out(
796 sk: &SK,
797 msg: &[u8],
798 ctx: Option<&[u8]>,
799 output: &mut [u8; SIG_LEN],
800 ) -> Result<usize, SignatureError> {
801 let mut ph_m = [0u8; PH_LEN];
802 _ = HASH::default().hash_out(msg, &mut ph_m);
803 Self::sign_ph_out(sk, &ph_m, ctx, output)
804 }
805
806 fn sign_init(sk: &SK, ctx: Option<&[u8]>) -> Result<Self, SignatureError> {
807 let (ctx, ctx_len) = Self::parse_ctx(ctx)?;
808 Ok(Self {
809 _phantom: PhantomData,
810 signer_rnd: None,
811 sk: Some(sk.clone()),
812 seed: None,
813 pk: None,
814 hash: HASH::default(),
815 ctx,
816 ctx_len,
817 })
818 }
819
820 fn sign_update(&mut self, msg_chunk: &[u8]) {
821 self.hash.do_update(msg_chunk);
822 }
823
824 fn sign_final(self) -> Result<[u8; SIG_LEN], SignatureError> {
825 let mut out = [0u8; SIG_LEN];
826 self.sign_final_out(&mut out)?;
827 Ok(out)
828 }
829
830 fn sign_final_out(self, output: &mut [u8; SIG_LEN]) -> Result<usize, SignatureError> {
831 let ph: [u8; PH_LEN] = self.hash.do_final().try_into().unwrap();
832
833 if self.sk.is_none() && self.seed.is_none() {
834 return Err(SignatureError::GenericError(
835 "Somehow you managed to construct a streaming signer without a private key, impressive!",
836 ));
837 }
838
839 if output.len() < SIG_LEN {
840 return Err(SignatureError::LengthError(
841 "Output buffer insufficient size to hold signature",
842 ));
843 }
844 let output_sized: &mut [u8; SIG_LEN] = output[..SIG_LEN].as_mut().try_into().unwrap();
845
846 if self.sk.is_some() {
847 if self.signer_rnd.is_none() {
848 Self::sign_ph_out(
849 &self.sk.unwrap(),
850 &ph,
851 Some(&self.ctx[..self.ctx_len]),
852 output_sized,
853 )
854 } else {
855 Self::sign_ph_deterministic_out(
856 &self.sk.unwrap(),
857 Some(&self.ctx[..self.ctx_len]),
858 &ph,
859 self.signer_rnd.unwrap(),
860 output_sized,
861 )
862 }
863 } else if self.seed.is_some() {
864 let rnd = if self.signer_rnd.is_some() {
865 self.signer_rnd.unwrap()
866 } else {
867 let mut rnd: [u8; MLDSA_RND_LEN] = [0u8; MLDSA_RND_LEN];
868 HashDRBG_SHA512::new_from_os().next_bytes_out(&mut rnd)?;
869 rnd
870 };
871 let (_pk, sk) = Self::keygen_from_seed(&self.seed.unwrap())?;
874 Self::sign_ph_deterministic_out(
875 &sk,
876 Some(&self.ctx[..self.ctx_len]),
877 &ph,
878 rnd,
879 output_sized,
880 )
881 } else {
882 unreachable!()
883 }
884 }
885
886 fn verify(pk: &PK, msg: &[u8], ctx: Option<&[u8]>, sig: &[u8]) -> Result<(), SignatureError> {
887 let mut ph_m = [0u8; PH_LEN];
888 _ = HASH::default().hash_out(msg, &mut ph_m);
889
890 Self::verify_ph(pk, &ph_m, ctx, sig)
891 }
892
893 fn verify_init(pk: &PK, ctx: Option<&[u8]>) -> Result<Self, SignatureError> {
894 let (ctx, ctx_len) = Self::parse_ctx(ctx)?;
895 Ok(Self {
896 _phantom: Default::default(),
897 signer_rnd: None,
898 sk: None,
899 seed: None,
900 pk: Some(pk.clone()),
901 hash: HASH::default(),
902 ctx,
903 ctx_len,
904 })
905 }
906
907 fn verify_update(&mut self, msg_chunk: &[u8]) {
908 self.hash.do_update(msg_chunk);
909 }
910
911 fn verify_final(self, sig: &[u8]) -> Result<(), SignatureError> {
912 assert!(
913 self.pk.is_some(),
914 "Somehow you managed to construct a streaming verifier without a public key, impressive!"
915 );
916 let ph: [u8; PH_LEN] = self.hash.do_final().try_into().unwrap();
917 Self::verify_ph(&self.pk.unwrap(), &ph, Some(&self.ctx[..self.ctx_len]), &sig[..SIG_LEN])
918 }
919}
920
921impl<
922 HASH: Hash + Default,
923 const PH_LEN: usize,
924 const oid: &'static [u8],
925 const PK_LEN: usize,
926 const SK_LEN: usize,
927 const FULL_SK_LEN: usize,
928 const SIG_LEN: usize,
929 PK: MLDSAPublicKeyTrait<k, T1_PACKED_LEN, PK_LEN>
930 + MLDSAPublicKeyInternalTrait<k, T1_PACKED_LEN, PK_LEN>,
931 SK: MLDSAPrivateKeyTrait<
932 k,
933 l,
934 S1_PACKED_LEN,
935 S2_PACKED_LEN,
936 T1_PACKED_LEN,
937 PK_LEN,
938 SK_LEN,
939 FULL_SK_LEN,
940 > + MLDSAPrivateKeyInternalTrait<
941 LAMBDA,
942 GAMMA2,
943 k,
944 l,
945 ETA,
946 S1_PACKED_LEN,
947 S2_PACKED_LEN,
948 PK_LEN,
949 SK_LEN,
950 >,
951 const TAU: i32,
952 const LAMBDA: i32,
953 const GAMMA1: i32,
954 const GAMMA2: i32,
955 const k: usize,
956 const l: usize,
957 const ETA: usize,
958 const BETA: i32,
959 const OMEGA: i32,
960 const C_TILDE: usize,
961 const POLY_Z_PACKED_LEN: usize,
962 const POLY_W1_PACKED_LEN: usize,
963 const S1_PACKED_LEN: usize,
964 const S2_PACKED_LEN: usize,
965 const T1_PACKED_LEN: usize,
966 const POLY_ETA_PACKED_LEN: usize,
967 const LAMBDA_over_4: usize,
968 const GAMMA1_MASK_LEN: usize,
969> PHSignature<PK, SK, PK_LEN, SK_LEN, SIG_LEN, PH_LEN>
970 for HashMLDSA<
971 HASH,
972 PH_LEN,
973 oid,
974 PK_LEN,
975 SK_LEN,
976 FULL_SK_LEN,
977 SIG_LEN,
978 PK,
979 SK,
980 TAU,
981 LAMBDA,
982 GAMMA1,
983 GAMMA2,
984 k,
985 l,
986 ETA,
987 BETA,
988 OMEGA,
989 C_TILDE,
990 POLY_Z_PACKED_LEN,
991 POLY_W1_PACKED_LEN,
992 S1_PACKED_LEN,
993 S2_PACKED_LEN,
994 T1_PACKED_LEN,
995 POLY_ETA_PACKED_LEN,
996 LAMBDA_over_4,
997 GAMMA1_MASK_LEN,
998 >
999{
1000 fn sign_ph(
1001 sk: &SK,
1002 ph: &[u8; PH_LEN],
1003 ctx: Option<&[u8]>,
1004 ) -> Result<[u8; SIG_LEN], SignatureError> {
1005 let mut out = [0u8; SIG_LEN];
1006 Self::sign_out(sk, ph, ctx, &mut out)?;
1007
1008 Ok(out)
1009 }
1010
1011 fn sign_ph_out(
1016 sk: &SK,
1017 ph: &[u8; PH_LEN],
1018 ctx: Option<&[u8]>,
1019 output: &mut [u8; SIG_LEN],
1020 ) -> Result<usize, SignatureError> {
1021 if output.len() < SIG_LEN {
1022 return Err(SignatureError::LengthError(
1023 "Output buffer insufficient size to hold signature",
1024 ));
1025 }
1026
1027 let mut rnd: [u8; MLDSA_RND_LEN] = [0u8; MLDSA_RND_LEN];
1028 HashDRBG_SHA512::new_from_os().next_bytes_out(&mut rnd)?;
1029 Self::sign_ph_deterministic_out(sk, ctx, ph, rnd, output)
1030 }
1031
1032 fn verify_ph(
1033 pk: &PK,
1034 ph: &[u8; PH_LEN],
1035 ctx: Option<&[u8]>,
1036 sig: &[u8],
1037 ) -> Result<(), SignatureError> {
1038 if sig.len() != SIG_LEN {
1039 return Err(SignatureError::LengthError("Signature value is not the correct length."));
1040 }
1041 let sig_sized = &sig.try_into().unwrap();
1042
1043 let ctx = if ctx.is_some() { ctx.unwrap() } else { &[] };
1044
1045 if ctx.len() > 255 {
1048 return Err(SignatureError::LengthError("ctx value is longer than 255 bytes"));
1049 }
1050
1051 let mut h = H::new();
1054 h.absorb(&pk.compute_tr());
1055
1056 h.absorb(&[1u8]);
1060 h.absorb(&[ctx.len() as u8]);
1061 h.absorb(ctx);
1062 h.absorb(oid);
1063 h.absorb(ph);
1064 let mut mu = [0u8; MLDSA_MU_LEN];
1065 _ = h.squeeze_out(&mut mu);
1066
1067 if MLDSA::<
1068 PK_LEN,
1069 SK_LEN,
1070 FULL_SK_LEN,
1071 SIG_LEN,
1072 PK,
1073 SK,
1074 TAU,
1075 LAMBDA,
1076 GAMMA1,
1077 GAMMA2,
1078 k,
1079 l,
1080 ETA,
1081 BETA,
1082 OMEGA,
1083 C_TILDE,
1084 POLY_Z_PACKED_LEN,
1085 POLY_W1_PACKED_LEN,
1086 S1_PACKED_LEN,
1087 S2_PACKED_LEN,
1088 T1_PACKED_LEN,
1089 POLY_ETA_PACKED_LEN,
1090 LAMBDA_over_4,
1091 GAMMA1_MASK_LEN,
1092 >::verify_mu_internal(pk, &mu, sig_sized)
1093 {
1094 Ok(())
1095 } else {
1096 Err(SignatureError::SignatureVerificationFailed)
1097 }
1098 }
1099}