1use crate::{
38 as_cbs, cbb_to_vec, initialized_boxed_struct, initialized_boxed_struct_fallible,
39 initialized_struct, with_output_vec, with_output_vec_fallible, FfiMutSlice, FfiSlice,
40 InvalidSignatureError,
41};
42use alloc::{boxed::Box, vec::Vec};
43use core::mem::MaybeUninit;
44
45pub struct PrivateKey65(Box<bssl_sys::MLDSA65_private_key>);
47
48pub struct PublicKey65(Box<bssl_sys::MLDSA65_public_key>);
50
51pub const PUBLIC_KEY_BYTES_65: usize = bssl_sys::MLDSA65_PUBLIC_KEY_BYTES as usize;
53
54pub const SIGNATURE_BYTES_65: usize = bssl_sys::MLDSA65_SIGNATURE_BYTES as usize;
56
57pub struct PrivateKey87(Box<bssl_sys::MLDSA87_private_key>);
59
60pub struct PublicKey87(Box<bssl_sys::MLDSA87_public_key>);
62
63pub const PUBLIC_KEY_BYTES_87: usize = bssl_sys::MLDSA87_PUBLIC_KEY_BYTES as usize;
65
66pub const SIGNATURE_BYTES_87: usize = bssl_sys::MLDSA87_SIGNATURE_BYTES as usize;
68
69pub const SEED_BYTES: usize = bssl_sys::MLDSA_SEED_BYTES as usize;
71
72pub const MU_BYTES: usize = bssl_sys::MLDSA_MU_BYTES as usize;
74
75impl PrivateKey65 {
76 pub fn generate() -> (Vec<u8>, Self, [u8; SEED_BYTES]) {
80 let mut public_key_bytes = Box::new_uninit_slice(PUBLIC_KEY_BYTES_65);
81 let mut seed = MaybeUninit::<[u8; SEED_BYTES]>::uninit();
82
83 let private_key = unsafe {
84 initialized_boxed_struct(|priv_key| {
86 let ok = bssl_sys::MLDSA65_generate_key(
87 public_key_bytes.as_mut_ptr() as *mut u8,
88 seed.as_mut_ptr() as *mut u8,
89 priv_key,
90 );
91 assert_eq!(ok, 1);
94 })
95 };
96
97 unsafe {
98 (
99 public_key_bytes.assume_init().into(),
102 Self(private_key),
103 seed.assume_init(),
104 )
105 }
106 }
107
108 pub fn from_seed(seed: &[u8; SEED_BYTES]) -> Self {
110 Self(unsafe {
111 initialized_boxed_struct(|priv_key| {
114 let ok = bssl_sys::MLDSA65_private_key_from_seed(
115 priv_key,
116 seed.as_ffi_ptr(),
117 seed.len(),
118 );
119 assert_eq!(ok, 1);
122 })
123 })
124 }
125
126 pub fn to_public_key(&self) -> PublicKey65 {
128 PublicKey65(unsafe {
129 initialized_boxed_struct(|pub_key| {
132 bssl_sys::MLDSA65_public_from_private(pub_key, &*self.0);
133 })
134 })
135 }
136
137 pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
139 unsafe {
140 with_output_vec(SIGNATURE_BYTES_65, |signature| {
143 let ok = bssl_sys::MLDSA65_sign(
144 signature,
145 &*self.0,
146 msg.as_ffi_ptr(),
147 msg.len(),
148 core::ptr::null(),
149 0,
150 );
151 assert_eq!(ok, 1);
154 SIGNATURE_BYTES_65
155 })
156 }
157 }
158
159 pub fn sign_with_context(&self, msg: &[u8], context: &[u8]) -> Option<Vec<u8>> {
163 unsafe {
164 with_output_vec_fallible(SIGNATURE_BYTES_65, |signature| {
167 if bssl_sys::MLDSA65_sign(
168 signature,
169 &*self.0,
170 msg.as_ffi_ptr(),
171 msg.len(),
172 context.as_ffi_ptr(),
173 context.len(),
174 ) == 1
175 {
176 Some(SIGNATURE_BYTES_65)
177 } else {
178 None
179 }
180 })
181 }
182 }
183
184 pub fn sign_prehashed(&self, prehash: Prehash65) -> Vec<u8> {
186 let representative = prehash.finalize();
187 unsafe {
188 with_output_vec(SIGNATURE_BYTES_65, |signature| {
192 let ok = bssl_sys::MLDSA65_sign_message_representative(
193 signature,
194 &*self.0,
195 representative.as_ffi_ptr(),
196 );
197 assert_eq!(ok, 1);
200 SIGNATURE_BYTES_65
201 })
202 }
203 }
204}
205
206impl PublicKey65 {
207 pub fn parse(encoded: &[u8]) -> Option<Self> {
209 let mut cbs = as_cbs(encoded);
210 unsafe {
211 initialized_boxed_struct_fallible(|pub_key| {
214 bssl_sys::MLDSA65_parse_public_key(pub_key, &mut cbs) == 1 && cbs.len == 0
215 })
216 }
217 .map(Self)
218 }
219
220 pub fn to_bytes(&self) -> Vec<u8> {
222 unsafe {
223 cbb_to_vec(PUBLIC_KEY_BYTES_65, |buf| {
224 let ok = bssl_sys::MLDSA65_marshal_public_key(buf, &*self.0);
225 assert_eq!(ok, 1);
229 })
230 }
231 }
232
233 pub fn verify(&self, msg: &[u8], signature: &[u8]) -> Result<(), InvalidSignatureError> {
235 unsafe {
236 let ok = bssl_sys::MLDSA65_verify(
237 &*self.0,
238 signature.as_ffi_ptr(),
239 signature.len(),
240 msg.as_ffi_ptr(),
241 msg.len(),
242 core::ptr::null(),
243 0,
244 );
245 if ok == 1 {
246 Ok(())
247 } else {
248 Err(InvalidSignatureError)
249 }
250 }
251 }
252
253 pub fn verify_with_context(
255 &self,
256 msg: &[u8],
257 signature: &[u8],
258 context: &[u8],
259 ) -> Result<(), InvalidSignatureError> {
260 unsafe {
261 let ok = bssl_sys::MLDSA65_verify(
262 &*self.0,
263 signature.as_ffi_ptr(),
264 signature.len(),
265 msg.as_ffi_ptr(),
266 msg.len(),
267 context.as_ffi_ptr(),
268 context.len(),
269 );
270 if ok == 1 {
271 Ok(())
272 } else {
273 Err(InvalidSignatureError)
274 }
275 }
276 }
277
278 pub fn verify_prehashed(
280 &self,
281 prehash: Prehash65,
282 signature: &[u8],
283 ) -> Result<(), InvalidSignatureError> {
284 let representative = prehash.finalize();
285 unsafe {
286 let ok = bssl_sys::MLDSA65_verify_message_representative(
287 &*self.0,
288 signature.as_ffi_ptr(),
289 signature.len(),
290 representative.as_ffi_ptr(),
291 );
292 if ok == 1 {
293 Ok(())
294 } else {
295 Err(InvalidSignatureError)
296 }
297 }
298 }
299
300 pub fn prehash(&self) -> Prehash65 {
302 unsafe {
303 initialized_struct(|prehash: *mut Prehash65| {
306 let ok = bssl_sys::MLDSA65_prehash_init(
307 &mut (*prehash).0,
308 &*self.0,
309 core::ptr::null(),
310 0,
311 );
312 assert_eq!(ok, 1);
315 })
316 }
317 }
318}
319
320pub struct Prehash65(bssl_sys::MLDSA65_prehash);
322
323impl Prehash65 {
324 pub fn update(&mut self, data: &[u8]) {
326 unsafe {
327 bssl_sys::MLDSA65_prehash_update(&mut self.0, data.as_ffi_ptr(), data.len());
330 }
331 }
332
333 fn finalize(mut self) -> [u8; MU_BYTES] {
335 let mut mu = [0u8; MU_BYTES];
336 unsafe {
337 bssl_sys::MLDSA65_prehash_finalize(mu.as_mut_ffi_ptr(), &mut self.0);
339 }
340 mu
341 }
342}
343
344#[cfg(feature = "std")]
345impl std::io::Write for Prehash65 {
346 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
347 self.update(buf);
348 Ok(buf.len())
349 }
350
351 fn flush(&mut self) -> std::io::Result<()> {
352 Ok(())
353 }
354}
355
356impl PrivateKey87 {
357 pub fn generate() -> (Vec<u8>, Self, [u8; SEED_BYTES]) {
361 let mut public_key_bytes = Box::new_uninit_slice(PUBLIC_KEY_BYTES_87);
362 let mut seed = MaybeUninit::<[u8; SEED_BYTES]>::uninit();
363
364 let private_key = unsafe {
365 initialized_boxed_struct(|priv_key| {
367 let ok = bssl_sys::MLDSA87_generate_key(
368 public_key_bytes.as_mut_ptr() as *mut u8,
369 seed.as_mut_ptr() as *mut u8,
370 priv_key,
371 );
372 assert_eq!(ok, 1);
375 })
376 };
377
378 unsafe {
379 (
380 public_key_bytes.assume_init().into(),
383 Self(private_key),
384 seed.assume_init(),
385 )
386 }
387 }
388
389 pub fn from_seed(seed: &[u8; SEED_BYTES]) -> Self {
391 Self(unsafe {
392 initialized_boxed_struct(|priv_key| {
395 let ok = bssl_sys::MLDSA87_private_key_from_seed(
396 priv_key,
397 seed.as_ffi_ptr(),
398 seed.len(),
399 );
400 assert_eq!(ok, 1);
403 })
404 })
405 }
406
407 pub fn to_public_key(&self) -> PublicKey87 {
409 PublicKey87(unsafe {
410 initialized_boxed_struct(|pub_key| {
413 bssl_sys::MLDSA87_public_from_private(pub_key, &*self.0);
414 })
415 })
416 }
417
418 pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
420 unsafe {
421 with_output_vec(SIGNATURE_BYTES_87, |signature| {
424 let ok = bssl_sys::MLDSA87_sign(
425 signature,
426 &*self.0,
427 msg.as_ffi_ptr(),
428 msg.len(),
429 core::ptr::null(),
430 0,
431 );
432 assert_eq!(ok, 1);
435 SIGNATURE_BYTES_87
436 })
437 }
438 }
439
440 pub fn sign_with_context(&self, msg: &[u8], context: &[u8]) -> Option<Vec<u8>> {
444 unsafe {
445 with_output_vec_fallible(SIGNATURE_BYTES_87, |signature| {
448 if bssl_sys::MLDSA87_sign(
449 signature,
450 &*self.0,
451 msg.as_ffi_ptr(),
452 msg.len(),
453 context.as_ffi_ptr(),
454 context.len(),
455 ) == 1
456 {
457 Some(SIGNATURE_BYTES_87)
458 } else {
459 None
460 }
461 })
462 }
463 }
464
465 pub fn sign_prehashed(&self, prehash: Prehash87) -> Vec<u8> {
467 let representative = prehash.finalize();
468 unsafe {
469 with_output_vec(SIGNATURE_BYTES_87, |signature| {
473 let ok = bssl_sys::MLDSA87_sign_message_representative(
474 signature,
475 &*self.0,
476 representative.as_ffi_ptr(),
477 );
478 assert_eq!(ok, 1);
481 SIGNATURE_BYTES_87
482 })
483 }
484 }
485}
486
487impl PublicKey87 {
488 pub fn parse(encoded: &[u8]) -> Option<Self> {
490 let mut cbs = as_cbs(encoded);
491 unsafe {
492 initialized_boxed_struct_fallible(|pub_key| {
495 bssl_sys::MLDSA87_parse_public_key(pub_key, &mut cbs) == 1 && cbs.len == 0
496 })
497 }
498 .map(Self)
499 }
500
501 pub fn to_bytes(&self) -> Vec<u8> {
503 unsafe {
504 cbb_to_vec(PUBLIC_KEY_BYTES_87, |buf| {
505 let ok = bssl_sys::MLDSA87_marshal_public_key(buf, &*self.0);
506 assert_eq!(ok, 1);
510 })
511 }
512 }
513
514 pub fn verify(&self, msg: &[u8], signature: &[u8]) -> Result<(), InvalidSignatureError> {
516 unsafe {
517 let ok = bssl_sys::MLDSA87_verify(
518 &*self.0,
519 signature.as_ffi_ptr(),
520 signature.len(),
521 msg.as_ffi_ptr(),
522 msg.len(),
523 core::ptr::null(),
524 0,
525 );
526 if ok == 1 {
527 Ok(())
528 } else {
529 Err(InvalidSignatureError)
530 }
531 }
532 }
533
534 pub fn verify_with_context(
536 &self,
537 msg: &[u8],
538 signature: &[u8],
539 context: &[u8],
540 ) -> Result<(), InvalidSignatureError> {
541 unsafe {
542 let ok = bssl_sys::MLDSA87_verify(
543 &*self.0,
544 signature.as_ffi_ptr(),
545 signature.len(),
546 msg.as_ffi_ptr(),
547 msg.len(),
548 context.as_ffi_ptr(),
549 context.len(),
550 );
551 if ok == 1 {
552 Ok(())
553 } else {
554 Err(InvalidSignatureError)
555 }
556 }
557 }
558
559 pub fn verify_prehashed(
561 &self,
562 prehash: Prehash87,
563 signature: &[u8],
564 ) -> Result<(), InvalidSignatureError> {
565 let representative = prehash.finalize();
566 unsafe {
567 let ok = bssl_sys::MLDSA87_verify_message_representative(
568 &*self.0,
569 signature.as_ffi_ptr(),
570 signature.len(),
571 representative.as_ffi_ptr(),
572 );
573 if ok == 1 {
574 Ok(())
575 } else {
576 Err(InvalidSignatureError)
577 }
578 }
579 }
580
581 pub fn prehash(&self) -> Prehash87 {
583 unsafe {
584 initialized_struct(|prehash: *mut Prehash87| {
587 let ok = bssl_sys::MLDSA87_prehash_init(
588 &mut (*prehash).0,
589 &*self.0,
590 core::ptr::null(),
591 0,
592 );
593 assert_eq!(ok, 1);
596 })
597 }
598 }
599}
600
601pub struct Prehash87(bssl_sys::MLDSA87_prehash);
603
604impl Prehash87 {
605 pub fn update(&mut self, data: &[u8]) {
607 unsafe {
608 bssl_sys::MLDSA87_prehash_update(&mut self.0, data.as_ffi_ptr(), data.len());
611 }
612 }
613
614 fn finalize(mut self) -> [u8; MU_BYTES] {
616 let mut mu = [0u8; MU_BYTES];
617 unsafe {
618 bssl_sys::MLDSA87_prehash_finalize(mu.as_mut_ffi_ptr(), &mut self.0);
620 }
621 mu
622 }
623}
624
625#[cfg(feature = "std")]
626impl std::io::Write for Prehash87 {
627 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
628 self.update(buf);
629 Ok(buf.len())
630 }
631
632 fn flush(&mut self) -> std::io::Result<()> {
633 Ok(())
634 }
635}
636
637#[cfg(test)]
638mod test {
639 use super::*;
640
641 #[test]
642 fn basic65() {
643 let (serialized_public_key, private_key, private_seed) = PrivateKey65::generate();
644 let public_key = PublicKey65::parse(&serialized_public_key).unwrap();
645 let message = &[0u8, 1, 2, 3];
646 let signature = private_key.sign(message);
647 let private_key2 = PrivateKey65::from_seed(&private_seed);
648 let mut signature2 = private_key2.sign(message);
649 assert!(public_key.verify(message, &signature).is_ok());
650 assert!(public_key.verify(message, &signature2).is_ok());
651
652 signature2[5] ^= 1;
653 assert!(public_key.verify(message, &signature2).is_err());
654
655 let context = b"context";
656 let signature3 = private_key.sign_with_context(message, context).unwrap();
657 assert!(public_key.verify(message, &signature3).is_err());
658 assert!(public_key
659 .verify_with_context(message, &signature3, context)
660 .is_ok());
661 }
662
663 #[test]
664 fn sign_prehashed65() {
665 let (serialized_public_key, private_key, _private_seed) = PrivateKey65::generate();
666 let public_key = PublicKey65::parse(&serialized_public_key).unwrap();
667 let message = &[0u8, 1, 2, 3, 4, 5, 6];
668
669 let mut prehash = public_key.prehash();
670 prehash.update(&message[0..2]);
671 prehash.update(&message[2..4]);
672 prehash.update(&message[4..]);
673 let mut signature = private_key.sign_prehashed(prehash);
674
675 assert!(public_key.verify(message, &signature).is_ok());
676 signature[5] ^= 1;
677 assert!(public_key.verify(message, &signature).is_err());
678 }
679
680 #[cfg(feature = "std")]
681 #[test]
682 fn sign_prehashed65_write() {
683 use std::io::Write;
684 let (serialized_public_key, private_key, _private_seed) = PrivateKey65::generate();
685 let public_key = PublicKey65::parse(&serialized_public_key).unwrap();
686 let message = &[0u8, 1, 2, 3, 4, 5, 6];
687
688 let mut prehash = public_key.prehash();
689 prehash.write(&message[0..2]).unwrap();
690 prehash.write(&message[2..4]).unwrap();
691 prehash.write(&message[4..]).unwrap();
692 prehash.flush().unwrap();
693 let mut signature = private_key.sign_prehashed(prehash);
694
695 assert!(public_key.verify(message, &signature).is_ok());
696 signature[5] ^= 1;
697 assert!(public_key.verify(message, &signature).is_err());
698 }
699
700 #[test]
701 fn verify_prehashed65() {
702 let (serialized_public_key, private_key, _private_seed) = PrivateKey65::generate();
703 let public_key = PublicKey65::parse(&serialized_public_key).unwrap();
704 let message = &[0u8, 1, 2, 3, 4, 5, 6];
705
706 let signature = private_key.sign(message);
707
708 let mut prehash = public_key.prehash();
709 prehash.update(&message[0..2]);
710 prehash.update(&message[2..4]);
711 assert!(public_key.verify_prehashed(prehash, &signature).is_err());
712
713 let mut prehash = public_key.prehash();
714 prehash.update(&message[0..2]);
715 prehash.update(&message[2..4]);
716 prehash.update(&message[4..]);
717 assert!(public_key.verify_prehashed(prehash, &signature).is_ok());
718 }
719
720 #[cfg(feature = "std")]
721 #[test]
722 fn verify_prehashed65_write() {
723 use std::io::Write;
724 let (serialized_public_key, private_key, _private_seed) = PrivateKey65::generate();
725 let public_key = PublicKey65::parse(&serialized_public_key).unwrap();
726 let message = &[0u8, 1, 2, 3, 4, 5, 6];
727
728 let signature = private_key.sign(message);
729
730 let mut prehash = public_key.prehash();
731 prehash.write(&message[0..2]).unwrap();
732 prehash.write(&message[2..4]).unwrap();
733 prehash.flush().unwrap();
734 assert!(public_key.verify_prehashed(prehash, &signature).is_err());
735
736 let mut prehash = public_key.prehash();
737 prehash.write(&message[0..2]).unwrap();
738 prehash.write(&message[2..4]).unwrap();
739 prehash.write(&message[4..]).unwrap();
740 prehash.flush().unwrap();
741 assert!(public_key.verify_prehashed(prehash, &signature).is_ok());
742 }
743
744 #[test]
745 fn marshal_public_key65() {
746 let (serialized_public_key, private_key, _) = PrivateKey65::generate();
747 let public_key = PublicKey65::parse(&serialized_public_key).unwrap();
748 assert_eq!(serialized_public_key, public_key.to_bytes());
749 assert_eq!(
750 serialized_public_key,
751 private_key.to_public_key().to_bytes()
752 );
753 }
754
755 #[test]
756 fn basic87() {
757 let (serialized_public_key, private_key, private_seed) = PrivateKey87::generate();
758 let public_key = PublicKey87::parse(&serialized_public_key).unwrap();
759 let message = &[0u8, 1, 2, 3];
760 let signature = private_key.sign(message);
761 let private_key2 = PrivateKey87::from_seed(&private_seed);
762 let mut signature2 = private_key2.sign(message);
763 assert!(public_key.verify(message, &signature).is_ok());
764 assert!(public_key.verify(message, &signature2).is_ok());
765
766 signature2[5] ^= 1;
767 assert!(public_key.verify(message, &signature2).is_err());
768
769 let context = b"context";
770 let signature3 = private_key.sign_with_context(message, context).unwrap();
771 assert!(public_key.verify(message, &signature3).is_err());
772 assert!(public_key
773 .verify_with_context(message, &signature3, context)
774 .is_ok());
775 }
776
777 #[test]
778 fn sign_prehashed87() {
779 let (serialized_public_key, private_key, _private_seed) = PrivateKey87::generate();
780 let public_key = PublicKey87::parse(&serialized_public_key).unwrap();
781 let message = &[0u8, 1, 2, 3, 4, 5, 6];
782
783 let mut prehash = public_key.prehash();
784 prehash.update(&message[0..2]);
785 prehash.update(&message[2..4]);
786 prehash.update(&message[4..]);
787 let mut signature = private_key.sign_prehashed(prehash);
788
789 assert!(public_key.verify(message, &signature).is_ok());
790 signature[5] ^= 1;
791 assert!(public_key.verify(message, &signature).is_err());
792 }
793
794 #[cfg(feature = "std")]
795 #[test]
796 fn sign_prehashed87_write() {
797 use std::io::Write;
798 let (serialized_public_key, private_key, _private_seed) = PrivateKey87::generate();
799 let public_key = PublicKey87::parse(&serialized_public_key).unwrap();
800 let message = &[0u8, 1, 2, 3, 4, 5, 6];
801
802 let mut prehash = public_key.prehash();
803 prehash.write(&message[0..2]).unwrap();
804 prehash.write(&message[2..4]).unwrap();
805 prehash.write(&message[4..]).unwrap();
806 prehash.flush().unwrap();
807 let mut signature = private_key.sign_prehashed(prehash);
808
809 assert!(public_key.verify(message, &signature).is_ok());
810 signature[5] ^= 1;
811 assert!(public_key.verify(message, &signature).is_err());
812 }
813
814 #[test]
815 fn verify_prehashed87() {
816 let (serialized_public_key, private_key, _private_seed) = PrivateKey87::generate();
817 let public_key = PublicKey87::parse(&serialized_public_key).unwrap();
818 let message = &[0u8, 1, 2, 3, 4, 5, 6];
819
820 let signature = private_key.sign(message);
821
822 let mut prehash = public_key.prehash();
823 prehash.update(&message[0..2]);
824 prehash.update(&message[2..4]);
825 assert!(public_key.verify_prehashed(prehash, &signature).is_err());
826
827 let mut prehash = public_key.prehash();
828 prehash.update(&message[0..2]);
829 prehash.update(&message[2..4]);
830 prehash.update(&message[4..]);
831 assert!(public_key.verify_prehashed(prehash, &signature).is_ok());
832 }
833
834 #[cfg(feature = "std")]
835 #[test]
836 fn verify_prehashed87_write() {
837 use std::io::Write;
838 let (serialized_public_key, private_key, _private_seed) = PrivateKey87::generate();
839 let public_key = PublicKey87::parse(&serialized_public_key).unwrap();
840 let message = &[0u8, 1, 2, 3, 4, 5, 6];
841
842 let signature = private_key.sign(message);
843
844 let mut prehash = public_key.prehash();
845 prehash.write(&message[0..2]).unwrap();
846 prehash.write(&message[2..4]).unwrap();
847 prehash.flush().unwrap();
848 assert!(public_key.verify_prehashed(prehash, &signature).is_err());
849
850 let mut prehash = public_key.prehash();
851 prehash.write(&message[0..2]).unwrap();
852 prehash.write(&message[2..4]).unwrap();
853 prehash.write(&message[4..]).unwrap();
854 prehash.flush().unwrap();
855 assert!(public_key.verify_prehashed(prehash, &signature).is_ok());
856 }
857
858 #[test]
859 fn marshal_public_key87() {
860 let (serialized_public_key, private_key, _) = PrivateKey87::generate();
861 let public_key = PublicKey87::parse(&serialized_public_key).unwrap();
862 assert_eq!(serialized_public_key, public_key.to_bytes());
863 assert_eq!(
864 serialized_public_key,
865 private_key.to_public_key().to_bytes()
866 );
867 }
868}