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