1#![cfg_attr(
24 not(any(boringssl, awslc)),
25 doc = r#"\
26Generate a CMAC key
27
28```
29use openssl::pkey_ctx::PkeyCtx;
30use openssl::pkey::Id;
31use openssl::cipher::Cipher;
32
33let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap();
34ctx.keygen_init().unwrap();
35ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap();
36ctx.set_keygen_mac_key(b"0123456789abcdef").unwrap();
37let cmac_key = ctx.keygen().unwrap();
38```"#
39)]
40
41use crate::bn::BigNumRef;
68#[cfg(not(any(boringssl, awslc)))]
69use crate::cipher::CipherRef;
70use crate::error::ErrorStack;
71use crate::md::MdRef;
72use crate::nid::Nid;
73use crate::pkey::{HasPrivate, HasPublic, Id, PKey, PKeyRef, Params, Private};
74use crate::rsa::Padding;
75use crate::sign::RsaPssSaltlen;
76use crate::{cvt, cvt_p};
77use cfg_if::cfg_if;
78use foreign_types::{ForeignType, ForeignTypeRef};
79use libc::c_int;
80#[cfg(ossl320)]
81use libc::c_uint;
82use openssl_macros::corresponds;
83use std::convert::TryFrom;
84use std::ptr;
85
86#[cfg(any(ossl111, boringssl, libressl360, awslc))]
88pub struct HkdfMode(c_int);
89
90#[cfg(any(ossl111, boringssl, libressl360, awslc))]
91impl HkdfMode {
92 pub const EXTRACT_THEN_EXPAND: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND);
97
98 pub const EXTRACT_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY);
103
104 pub const EXPAND_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXPAND_ONLY);
110}
111
112#[cfg(ossl320)]
114#[derive(Debug, PartialEq)]
115pub struct NonceType(c_uint);
116
117#[cfg(ossl320)]
118impl NonceType {
119 pub const RANDOM_K: Self = NonceType(0);
122
123 pub const DETERMINISTIC_K: Self = NonceType(1);
125}
126
127generic_foreign_type_and_impl_send_sync! {
128 type CType = ffi::EVP_PKEY_CTX;
129 fn drop = ffi::EVP_PKEY_CTX_free;
130
131 pub struct PkeyCtx<T>;
133 pub struct PkeyCtxRef<T>;
135}
136
137impl<T> PkeyCtx<T> {
138 #[corresponds(EVP_PKEY_CTX_new)]
140 #[inline]
141 pub fn new(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack> {
142 unsafe {
143 let ptr = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?;
144 Ok(PkeyCtx::from_ptr(ptr))
145 }
146 }
147}
148
149impl PkeyCtx<()> {
150 #[corresponds(EVP_PKEY_CTX_new_id)]
152 #[inline]
153 pub fn new_id(id: Id) -> Result<Self, ErrorStack> {
154 unsafe {
155 let ptr = cvt_p(ffi::EVP_PKEY_CTX_new_id(id.as_raw(), ptr::null_mut()))?;
156 Ok(PkeyCtx::from_ptr(ptr))
157 }
158 }
159}
160
161impl<T> PkeyCtxRef<T>
162where
163 T: HasPublic,
164{
165 #[corresponds(EVP_PKEY_encrypt_init)]
167 #[inline]
168 pub fn encrypt_init(&mut self) -> Result<(), ErrorStack> {
169 unsafe {
170 cvt(ffi::EVP_PKEY_encrypt_init(self.as_ptr()))?;
171 }
172
173 Ok(())
174 }
175
176 #[corresponds(EVP_PKEY_verify_init)]
178 #[inline]
179 pub fn verify_init(&mut self) -> Result<(), ErrorStack> {
180 unsafe {
181 cvt(ffi::EVP_PKEY_verify_init(self.as_ptr()))?;
182 }
183
184 Ok(())
185 }
186
187 #[corresponds(EVP_PKEY_verify_recover_init)]
189 #[inline]
190 pub fn verify_recover_init(&mut self) -> Result<(), ErrorStack> {
191 unsafe {
192 cvt(ffi::EVP_PKEY_verify_recover_init(self.as_ptr()))?;
193 }
194
195 Ok(())
196 }
197
198 #[corresponds(EVP_PKEY_encrypt)]
203 #[inline]
204 pub fn encrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
205 let mut written = to.as_ref().map_or(0, |b| b.len());
206 unsafe {
207 cvt(ffi::EVP_PKEY_encrypt(
208 self.as_ptr(),
209 to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
210 &mut written,
211 from.as_ptr(),
212 from.len(),
213 ))?;
214 }
215
216 Ok(written)
217 }
218
219 pub fn encrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> {
221 let base = out.len();
222 let len = self.encrypt(from, None)?;
223 out.resize(base + len, 0);
224 let len = self.encrypt(from, Some(&mut out[base..]))?;
225 out.truncate(base + len);
226 Ok(len)
227 }
228
229 #[corresponds(EVP_PKEY_verify)]
240 #[inline]
241 pub fn verify(&mut self, data: &[u8], sig: &[u8]) -> Result<bool, ErrorStack> {
242 unsafe {
243 let r = ffi::EVP_PKEY_verify(
244 self.as_ptr(),
245 sig.as_ptr(),
246 sig.len(),
247 data.as_ptr(),
248 data.len(),
249 );
250 if r <= 0 {
256 let errors = ErrorStack::get();
257 if !errors.errors().is_empty() {
258 return Err(errors);
259 }
260 }
261
262 Ok(r == 1)
263 }
264 }
265
266 #[corresponds(EVP_PKEY_verify_recover)]
272 #[inline]
273 pub fn verify_recover(
274 &mut self,
275 sig: &[u8],
276 to: Option<&mut [u8]>,
277 ) -> Result<usize, ErrorStack> {
278 let mut written = to.as_ref().map_or(0, |b| b.len());
279 unsafe {
280 cvt(ffi::EVP_PKEY_verify_recover(
281 self.as_ptr(),
282 to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
283 &mut written,
284 sig.as_ptr(),
285 sig.len(),
286 ))?;
287 }
288
289 Ok(written)
290 }
291}
292
293impl<T> PkeyCtxRef<T>
294where
295 T: HasPrivate,
296{
297 #[corresponds(EVP_PKEY_decrypt_init)]
299 #[inline]
300 pub fn decrypt_init(&mut self) -> Result<(), ErrorStack> {
301 unsafe {
302 cvt(ffi::EVP_PKEY_decrypt_init(self.as_ptr()))?;
303 }
304
305 Ok(())
306 }
307
308 #[corresponds(EVP_PKEY_sign_init)]
310 #[inline]
311 pub fn sign_init(&mut self) -> Result<(), ErrorStack> {
312 unsafe {
313 cvt(ffi::EVP_PKEY_sign_init(self.as_ptr()))?;
314 }
315
316 Ok(())
317 }
318
319 #[corresponds(EVP_PKEY_derive_set_peer)]
321 pub fn derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack>
322 where
323 U: HasPublic,
324 {
325 unsafe {
326 cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), key.as_ptr()))?;
327 }
328
329 Ok(())
330 }
331
332 #[corresponds(EVP_PKEY_decrypt)]
337 #[inline]
338 pub fn decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
339 let mut written = to.as_ref().map_or(0, |b| b.len());
340 unsafe {
341 cvt(ffi::EVP_PKEY_decrypt(
342 self.as_ptr(),
343 to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
344 &mut written,
345 from.as_ptr(),
346 from.len(),
347 ))?;
348 }
349
350 Ok(written)
351 }
352
353 pub fn decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> {
355 let base = out.len();
356 let len = self.decrypt(from, None)?;
357 out.resize(base + len, 0);
358 let len = self.decrypt(from, Some(&mut out[base..]))?;
359 out.truncate(base + len);
360 Ok(len)
361 }
362
363 #[corresponds(EVP_PKEY_sign)]
373 #[inline]
374 pub fn sign(&mut self, data: &[u8], sig: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
375 let mut written = sig.as_ref().map_or(0, |b| b.len());
376 unsafe {
377 cvt(ffi::EVP_PKEY_sign(
378 self.as_ptr(),
379 sig.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
380 &mut written,
381 data.as_ptr(),
382 data.len(),
383 ))?;
384 }
385
386 Ok(written)
387 }
388
389 pub fn sign_to_vec(&mut self, data: &[u8], sig: &mut Vec<u8>) -> Result<usize, ErrorStack> {
391 let base = sig.len();
392 let len = self.sign(data, None)?;
393 sig.resize(base + len, 0);
394 let len = self.sign(data, Some(&mut sig[base..]))?;
395 sig.truncate(base + len);
396 Ok(len)
397 }
398}
399
400impl<T> PkeyCtxRef<T> {
401 #[corresponds(EVP_PKEY_derive_init)]
403 #[inline]
404 pub fn derive_init(&mut self) -> Result<(), ErrorStack> {
405 unsafe {
406 cvt(ffi::EVP_PKEY_derive_init(self.as_ptr()))?;
407 }
408
409 Ok(())
410 }
411
412 #[corresponds(EVP_PKEY_keygen_init)]
414 #[inline]
415 pub fn keygen_init(&mut self) -> Result<(), ErrorStack> {
416 unsafe {
417 cvt(ffi::EVP_PKEY_keygen_init(self.as_ptr()))?;
418 }
419
420 Ok(())
421 }
422
423 #[corresponds(EVP_PKEY_paramgen_init)]
425 #[inline]
426 pub fn paramgen_init(&mut self) -> Result<(), ErrorStack> {
427 unsafe {
428 cvt(ffi::EVP_PKEY_paramgen_init(self.as_ptr()))?;
429 }
430
431 Ok(())
432 }
433
434 #[corresponds(EVP_PKEY_CTX_set_signature_md)]
439 #[inline]
440 pub fn set_signature_md(&self, md: &MdRef) -> Result<(), ErrorStack> {
441 unsafe {
442 cvt(ffi::EVP_PKEY_CTX_set_signature_md(
443 self.as_ptr(),
444 md.as_ptr(),
445 ))?;
446 }
447 Ok(())
448 }
449
450 #[corresponds(EVP_PKEY_CTX_set_dh_paramgen_prime_len)]
454 #[cfg(not(any(boringssl, awslc_fips)))]
455 #[inline]
456 pub fn set_dh_paramgen_prime_len(&mut self, bits: u32) -> Result<(), ErrorStack> {
457 unsafe {
458 cvt(ffi::EVP_PKEY_CTX_set_dh_paramgen_prime_len(
459 self.as_ptr(),
460 bits as i32,
461 ))?;
462 }
463
464 Ok(())
465 }
466
467 #[corresponds(EVP_PKEY_CTX_set_dh_paramgen_generator)]
471 #[cfg(not(any(boringssl, awslc_fips)))]
472 #[inline]
473 pub fn set_dh_paramgen_generator(&mut self, bits: u32) -> Result<(), ErrorStack> {
474 unsafe {
475 cvt(ffi::EVP_PKEY_CTX_set_dh_paramgen_generator(
476 self.as_ptr(),
477 bits as i32,
478 ))?;
479 }
480
481 Ok(())
482 }
483
484 #[corresponds(EVP_PKEY_CTX_set_dsa_paramgen_bits)]
488 #[inline]
489 pub fn set_dsa_paramgen_bits(&mut self, bits: u32) -> Result<(), ErrorStack> {
490 unsafe {
491 cvt(ffi::EVP_PKEY_CTX_set_dsa_paramgen_bits(
492 self.as_ptr(),
493 bits as i32,
494 ))?;
495 }
496
497 Ok(())
498 }
499
500 #[corresponds(EVP_PKEY_CTX_set_ec_paramgen_curve_nid)]
504 #[inline]
505 pub fn set_ec_paramgen_curve_nid(&mut self, nid: Nid) -> Result<(), ErrorStack> {
506 unsafe {
507 cvt(ffi::EVP_PKEY_CTX_set_ec_paramgen_curve_nid(
508 self.as_ptr(),
509 nid.as_raw(),
510 ))?;
511 }
512
513 Ok(())
514 }
515
516 #[corresponds(EVP_PKEY_CTX_get_rsa_padding)]
520 #[inline]
521 pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
522 let mut pad = 0;
523 unsafe {
524 cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))?;
525 }
526
527 Ok(Padding::from_raw(pad))
528 }
529
530 #[corresponds(EVP_PKEY_CTX_set_rsa_padding)]
534 #[inline]
535 pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
536 unsafe {
537 cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
538 self.as_ptr(),
539 padding.as_raw(),
540 ))?;
541 }
542
543 Ok(())
544 }
545
546 #[corresponds(EVP_PKEY_CTX_set_rsa_keygen_bits)]
550 #[inline]
551 pub fn set_rsa_keygen_bits(&mut self, bits: u32) -> Result<(), ErrorStack> {
552 unsafe {
553 cvt(ffi::EVP_PKEY_CTX_set_rsa_keygen_bits(
554 self.as_ptr(),
555 bits as i32,
556 ))?;
557 }
558
559 Ok(())
560 }
561
562 #[corresponds(EVP_PKEY_CTX_set1_rsa_keygen_pubexp)]
566 #[inline]
567 pub fn set_rsa_keygen_pubexp(&mut self, pubexp: &BigNumRef) -> Result<(), ErrorStack> {
568 unsafe {
569 cfg_if! {
570 if #[cfg(ossl300)] {
571 cvt(ffi::EVP_PKEY_CTX_set1_rsa_keygen_pubexp(
572 self.as_ptr(),
573 pubexp.as_ptr(),
574 ))?;
575 } else {
576 cvt(ffi::EVP_PKEY_CTX_set_rsa_keygen_pubexp(
577 self.as_ptr(),
578 cvt_p(ffi::BN_dup(pubexp.as_ptr()))?,
580 ))?;
581 }
582 }
583 }
584
585 Ok(())
586 }
587
588 #[corresponds(EVP_PKEY_CTX_set_rsa_pss_saltlen)]
592 #[inline]
593 pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> {
594 unsafe {
595 cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen(
596 self.as_ptr(),
597 len.as_raw(),
598 ))
599 .map(|_| ())
600 }
601 }
602
603 #[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)]
607 #[inline]
608 pub fn set_rsa_mgf1_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
609 unsafe {
610 cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
611 self.as_ptr(),
612 md.as_ptr(),
613 ))?;
614 }
615
616 Ok(())
617 }
618
619 #[corresponds(EVP_PKEY_CTX_set_rsa_oaep_md)]
623 #[inline]
624 pub fn set_rsa_oaep_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
625 unsafe {
626 cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
627 self.as_ptr(),
628 md.as_ptr() as *mut _,
629 ))?;
630 }
631
632 Ok(())
633 }
634
635 #[corresponds(EVP_PKEY_CTX_set0_rsa_oaep_label)]
639 pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> {
640 use crate::LenType;
641 let len = LenType::try_from(label.len()).unwrap();
642
643 unsafe {
644 let p = cvt_p(ffi::OPENSSL_malloc(label.len() as _))?;
645 ptr::copy_nonoverlapping(label.as_ptr(), p as *mut _, label.len());
646
647 let r = cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label(
648 self.as_ptr(),
649 p as *mut _,
650 len,
651 ));
652 if r.is_err() {
653 ffi::OPENSSL_free(p);
654 }
655 r?;
656 }
657
658 Ok(())
659 }
660
661 #[cfg(not(any(boringssl, awslc)))]
663 #[corresponds(EVP_PKEY_CTX_ctrl)]
664 #[inline]
665 pub fn set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack> {
666 unsafe {
667 cvt(ffi::EVP_PKEY_CTX_ctrl(
668 self.as_ptr(),
669 -1,
670 ffi::EVP_PKEY_OP_KEYGEN,
671 ffi::EVP_PKEY_CTRL_CIPHER,
672 0,
673 cipher.as_ptr() as *mut _,
674 ))?;
675 }
676
677 Ok(())
678 }
679
680 #[cfg(not(any(boringssl, awslc)))]
682 #[corresponds(EVP_PKEY_CTX_ctrl)]
683 #[inline]
684 pub fn set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
685 let len = c_int::try_from(key.len()).unwrap();
686
687 unsafe {
688 cvt(ffi::EVP_PKEY_CTX_ctrl(
689 self.as_ptr(),
690 -1,
691 ffi::EVP_PKEY_OP_KEYGEN,
692 ffi::EVP_PKEY_CTRL_SET_MAC_KEY,
693 len,
694 key.as_ptr() as *mut _,
695 ))?;
696 }
697
698 Ok(())
699 }
700
701 #[corresponds(EVP_PKEY_CTX_set_hkdf_md)]
705 #[cfg(any(ossl110, boringssl, libressl360, awslc))]
706 #[inline]
707 pub fn set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack> {
708 unsafe {
709 cvt(ffi::EVP_PKEY_CTX_set_hkdf_md(
710 self.as_ptr(),
711 digest.as_ptr(),
712 ))?;
713 }
714
715 Ok(())
716 }
717
718 #[corresponds(EVP_PKEY_CTX_set_hkdf_mode)]
728 #[cfg(any(ossl111, libressl360))]
729 #[inline]
730 pub fn set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack> {
731 unsafe {
732 cvt(ffi::EVP_PKEY_CTX_set_hkdf_mode(self.as_ptr(), mode.0))?;
733 }
734
735 Ok(())
736 }
737
738 #[corresponds(EVP_PKEY_CTX_hkdf_mode)]
748 #[cfg(any(boringssl, awslc))]
749 #[inline]
750 pub fn set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack> {
751 unsafe {
752 cvt(ffi::EVP_PKEY_CTX_hkdf_mode(self.as_ptr(), mode.0))?;
753 }
754
755 Ok(())
756 }
757
758 #[corresponds(EVP_PKEY_CTX_set1_hkdf_key)]
767 #[cfg(any(ossl110, boringssl, libressl360, awslc))]
768 #[inline]
769 pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
770 #[cfg(not(any(boringssl, awslc)))]
771 let len = c_int::try_from(key.len()).unwrap();
772 #[cfg(any(boringssl, awslc))]
773 let len = key.len();
774
775 unsafe {
776 cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key(
777 self.as_ptr(),
778 key.as_ptr(),
779 len,
780 ))?;
781 }
782
783 Ok(())
784 }
785
786 #[corresponds(EVP_PKEY_CTX_set1_hkdf_salt)]
792 #[cfg(any(ossl110, boringssl, libressl360, awslc))]
793 #[inline]
794 pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> {
795 #[cfg(not(any(boringssl, awslc)))]
796 let len = c_int::try_from(salt.len()).unwrap();
797 #[cfg(any(boringssl, awslc))]
798 let len = salt.len();
799
800 unsafe {
801 cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt(
802 self.as_ptr(),
803 salt.as_ptr(),
804 len,
805 ))?;
806 }
807
808 Ok(())
809 }
810
811 #[corresponds(EVP_PKEY_CTX_add1_hkdf_info)]
817 #[cfg(any(ossl110, boringssl, libressl360, awslc))]
818 #[inline]
819 pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> {
820 #[cfg(not(any(boringssl, awslc)))]
821 let len = c_int::try_from(info.len()).unwrap();
822 #[cfg(any(boringssl, awslc))]
823 let len = info.len();
824
825 unsafe {
826 cvt(ffi::EVP_PKEY_CTX_add1_hkdf_info(
827 self.as_ptr(),
828 info.as_ptr(),
829 len,
830 ))?;
831 }
832
833 Ok(())
834 }
835
836 #[corresponds(EVP_PKEY_derive)]
840 #[allow(unused_mut)]
841 pub fn derive(&mut self, mut buf: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
842 #[cfg(any(all(ossl110, not(ossl300)), libressl))]
867 {
868 if let Some(b) = buf.as_deref_mut() {
869 let mut required = 0;
870 let probe_ok = unsafe {
871 ffi::EVP_PKEY_derive(self.as_ptr(), ptr::null_mut(), &mut required) == 1
872 };
873 if !probe_ok {
874 let _ = ErrorStack::get();
875 } else if required != usize::MAX && b.len() < required {
876 let mut temp = vec![0u8; required];
877 let mut len = required;
878 unsafe {
879 cvt(ffi::EVP_PKEY_derive(
880 self.as_ptr(),
881 temp.as_mut_ptr(),
882 &mut len,
883 ))?;
884 }
885 let copy_len = b.len().min(len);
886 b[..copy_len].copy_from_slice(&temp[..copy_len]);
887 return Ok(copy_len);
888 }
889 }
890 }
891 let mut len = buf.as_ref().map_or(0, |b| b.len());
892 unsafe {
893 cvt(ffi::EVP_PKEY_derive(
894 self.as_ptr(),
895 buf.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
896 &mut len,
897 ))?;
898 }
899
900 Ok(len)
901 }
902
903 pub fn derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack> {
905 let base = buf.len();
906 let len = self.derive(None)?;
907 buf.resize(base + len, 0);
908 let len = self.derive(Some(&mut buf[base..]))?;
909 buf.truncate(base + len);
910 Ok(len)
911 }
912
913 #[corresponds(EVP_PKEY_keygen)]
915 #[inline]
916 pub fn keygen(&mut self) -> Result<PKey<Private>, ErrorStack> {
917 unsafe {
918 let mut key = ptr::null_mut();
919 cvt(ffi::EVP_PKEY_keygen(self.as_ptr(), &mut key))?;
920 Ok(PKey::from_ptr(key))
921 }
922 }
923
924 #[corresponds(EVP_PKEY_paramgen)]
926 #[inline]
927 pub fn paramgen(&mut self) -> Result<PKey<Params>, ErrorStack> {
928 unsafe {
929 let mut key = ptr::null_mut();
930 cvt(ffi::EVP_PKEY_paramgen(self.as_ptr(), &mut key))?;
931 Ok(PKey::from_ptr(key))
932 }
933 }
934
935 #[cfg(ossl320)]
942 #[corresponds(EVP_PKEY_CTX_set_params)]
943 pub fn set_nonce_type(&mut self, nonce_type: NonceType) -> Result<(), ErrorStack> {
944 let nonce_field_name = c"nonce-type";
945 let mut nonce_type = nonce_type.0;
946 unsafe {
947 let param_nonce =
948 ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type);
949 let param_end = ffi::OSSL_PARAM_construct_end();
950
951 let params = [param_nonce, param_end];
952 cvt(ffi::EVP_PKEY_CTX_set_params(self.as_ptr(), params.as_ptr()))?;
953 }
954 Ok(())
955 }
956
957 #[cfg(ossl320)]
964 #[corresponds(EVP_PKEY_CTX_get_params)]
965 pub fn nonce_type(&mut self) -> Result<NonceType, ErrorStack> {
966 let nonce_field_name = c"nonce-type";
967 let mut nonce_type: c_uint = 0;
968 unsafe {
969 let param_nonce =
970 ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type);
971 let param_end = ffi::OSSL_PARAM_construct_end();
972
973 let mut params = [param_nonce, param_end];
974 cvt(ffi::EVP_PKEY_CTX_get_params(
975 self.as_ptr(),
976 params.as_mut_ptr(),
977 ))?;
978 }
979 Ok(NonceType(nonce_type))
980 }
981
982 #[cfg(ossl350)]
987 #[corresponds(EVP_PKEY_CTX_set_params)]
988 pub fn set_context_string(&mut self, context: &[u8]) -> Result<(), ErrorStack> {
989 let mut builder = crate::ossl_param::OsslParamBuilder::new()?;
990 builder.add_octet_string(c"context-string", context)?;
991 let params = builder.to_param()?;
992 unsafe {
993 cvt(ffi::EVP_PKEY_CTX_set_params(self.as_ptr(), params.as_ptr()))?;
994 }
995 Ok(())
996 }
997}
998
999#[cfg(test)]
1000mod test {
1001 use super::*;
1002 use crate::bn::BigNum;
1003 #[cfg(not(any(boringssl, awslc)))]
1004 use crate::cipher::Cipher;
1005 use crate::ec::{EcGroup, EcKey};
1006 use crate::hash::{hash, MessageDigest};
1007 use crate::md::Md;
1008 #[cfg(ossl350)]
1009 use crate::md_ctx::MdCtx;
1010 use crate::nid::Nid;
1011 #[cfg(ossl350)]
1012 use crate::pkey::KeyType;
1013 use crate::pkey::PKey;
1014 use crate::rsa::Rsa;
1015 use crate::sign::Verifier;
1016 #[cfg(not(boringssl))]
1017 use cfg_if::cfg_if;
1018
1019 #[test]
1020 fn rsa() {
1021 let key = include_bytes!("../test/rsa.pem");
1022 let rsa = Rsa::private_key_from_pem(key).unwrap();
1023 let pkey = PKey::from_rsa(rsa).unwrap();
1024
1025 let mut ctx = PkeyCtx::new(&pkey).unwrap();
1026 ctx.encrypt_init().unwrap();
1027 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1028
1029 let pt = "hello world".as_bytes();
1030 let mut ct = vec![];
1031 ctx.encrypt_to_vec(pt, &mut ct).unwrap();
1032
1033 ctx.decrypt_init().unwrap();
1034 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1035
1036 let mut out = vec![];
1037 ctx.decrypt_to_vec(&ct, &mut out).unwrap();
1038
1039 assert_eq!(pt, out);
1040 }
1041
1042 #[test]
1043 fn rsa_oaep() {
1044 let key = include_bytes!("../test/rsa.pem");
1045 let rsa = Rsa::private_key_from_pem(key).unwrap();
1046 let pkey = PKey::from_rsa(rsa).unwrap();
1047
1048 let mut ctx = PkeyCtx::new(&pkey).unwrap();
1049 ctx.encrypt_init().unwrap();
1050 ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
1051 ctx.set_rsa_oaep_md(Md::sha256()).unwrap();
1052 ctx.set_rsa_mgf1_md(Md::sha256()).unwrap();
1053
1054 let pt = "hello world".as_bytes();
1055 let mut ct = vec![];
1056 ctx.encrypt_to_vec(pt, &mut ct).unwrap();
1057
1058 ctx.decrypt_init().unwrap();
1059 ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
1060 ctx.set_rsa_oaep_md(Md::sha256()).unwrap();
1061 ctx.set_rsa_mgf1_md(Md::sha256()).unwrap();
1062
1063 let mut out = vec![];
1064 ctx.decrypt_to_vec(&ct, &mut out).unwrap();
1065
1066 assert_eq!(pt, out);
1067 }
1068
1069 #[test]
1070 fn rsa_sign() {
1071 let key = include_bytes!("../test/rsa.pem");
1072 let rsa = Rsa::private_key_from_pem(key).unwrap();
1073 let pkey = PKey::from_rsa(rsa).unwrap();
1074
1075 let mut ctx = PkeyCtx::new(&pkey).unwrap();
1076 ctx.sign_init().unwrap();
1077 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1078 ctx.set_signature_md(Md::sha384()).unwrap();
1079
1080 let msg = b"hello world";
1081 let digest = hash(MessageDigest::sha384(), msg).unwrap();
1082 let mut signature = vec![];
1083 ctx.sign_to_vec(&digest, &mut signature).unwrap();
1084
1085 let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap();
1086 verifier.update(msg).unwrap();
1087 assert!(matches!(verifier.verify(&signature), Ok(true)));
1088 }
1089
1090 #[test]
1091 fn rsa_sign_pss() {
1092 let key = include_bytes!("../test/rsa.pem");
1093 let rsa = Rsa::private_key_from_pem(key).unwrap();
1094 let pkey = PKey::from_rsa(rsa).unwrap();
1095
1096 let mut ctx = PkeyCtx::new(&pkey).unwrap();
1097 ctx.sign_init().unwrap();
1098 ctx.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
1099 ctx.set_signature_md(Md::sha384()).unwrap();
1100 ctx.set_rsa_pss_saltlen(RsaPssSaltlen::custom(14)).unwrap();
1101
1102 let msg = b"hello world";
1103 let digest = hash(MessageDigest::sha384(), msg).unwrap();
1104 let mut signature = vec![];
1105 ctx.sign_to_vec(&digest, &mut signature).unwrap();
1106
1107 let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap();
1108 verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
1109 verifier
1110 .set_rsa_pss_saltlen(RsaPssSaltlen::custom(14))
1111 .unwrap();
1112 verifier.update(msg).unwrap();
1113 assert!(matches!(verifier.verify(&signature), Ok(true)));
1114 }
1115
1116 #[test]
1117 fn derive() {
1118 let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
1119 let key1 = EcKey::generate(&group).unwrap();
1120 let key1 = PKey::from_ec_key(key1).unwrap();
1121 let key2 = EcKey::generate(&group).unwrap();
1122 let key2 = PKey::from_ec_key(key2).unwrap();
1123
1124 let mut ctx = PkeyCtx::new(&key1).unwrap();
1125 ctx.derive_init().unwrap();
1126 ctx.derive_set_peer(&key2).unwrap();
1127
1128 let mut buf = vec![];
1129 ctx.derive_to_vec(&mut buf).unwrap();
1130 }
1131
1132 #[test]
1133 #[cfg(any(ossl111, libressl370))]
1134 fn derive_undersized_buffer() {
1135 let key1 = PKey::generate_x25519().unwrap();
1141 let key2 = PKey::generate_x25519().unwrap();
1142
1143 let mut ctx = PkeyCtx::new(&key1).unwrap();
1144 ctx.derive_init().unwrap();
1145 ctx.derive_set_peer(&key2).unwrap();
1146
1147 let mut buf = [0u8; 4];
1148 let result = ctx.derive(Some(&mut buf));
1149 #[cfg(any(all(ossl110, not(ossl300)), libressl))]
1150 assert_eq!(result.unwrap(), 4);
1151 #[cfg(all(ossl300, not(libressl)))]
1152 assert!(result.is_err());
1153 }
1154
1155 #[test]
1156 #[cfg(not(any(boringssl, awslc)))]
1157 fn cmac_keygen() {
1158 let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap();
1159 ctx.keygen_init().unwrap();
1160 ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap();
1161 ctx.set_keygen_mac_key(&hex::decode("9294727a3638bb1c13f48ef8158bfc9d").unwrap())
1162 .unwrap();
1163 ctx.keygen().unwrap();
1164 }
1165
1166 #[test]
1167 #[cfg(not(any(boringssl, awslc_fips)))]
1168 fn dh_paramgen() {
1169 let mut ctx = PkeyCtx::new_id(Id::DH).unwrap();
1170 ctx.paramgen_init().unwrap();
1171 ctx.set_dh_paramgen_prime_len(512).unwrap();
1172 ctx.set_dh_paramgen_generator(2).unwrap();
1173 let params = ctx.paramgen().unwrap();
1174
1175 assert_eq!(params.size(), 64);
1176 }
1177
1178 #[test]
1179 #[cfg(not(boringssl))]
1180 fn dsa_paramgen() {
1181 let mut ctx = PkeyCtx::new_id(Id::DSA).unwrap();
1182 ctx.paramgen_init().unwrap();
1183 ctx.set_dsa_paramgen_bits(2048).unwrap();
1184 let params = ctx.paramgen().unwrap();
1185
1186 let size = {
1187 cfg_if! {
1188 if #[cfg(awslc)] {
1189 72
1190 } else if #[cfg(libressl)] {
1191 48
1192 } else {
1193 64
1194 }
1195 }
1196 };
1197 assert_eq!(params.size(), size);
1198 }
1199
1200 #[test]
1201 fn ec_keygen() {
1202 let mut ctx = PkeyCtx::new_id(Id::EC).unwrap();
1203 ctx.paramgen_init().unwrap();
1204 ctx.set_ec_paramgen_curve_nid(Nid::X9_62_PRIME256V1)
1205 .unwrap();
1206 let params = ctx.paramgen().unwrap();
1207
1208 assert_eq!(params.size(), 72);
1209 }
1210
1211 #[test]
1212 fn rsa_keygen() {
1213 let pubexp = BigNum::from_u32(65537).unwrap();
1214 let mut ctx = PkeyCtx::new_id(Id::RSA).unwrap();
1215 ctx.keygen_init().unwrap();
1216 ctx.set_rsa_keygen_pubexp(&pubexp).unwrap();
1217 ctx.set_rsa_keygen_bits(2048).unwrap();
1218 let key = ctx.keygen().unwrap();
1219
1220 assert_eq!(key.bits(), 2048);
1221 }
1222
1223 #[test]
1224 #[cfg(any(ossl110, boringssl, libressl360, awslc))]
1225 fn hkdf() {
1226 let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
1227 ctx.derive_init().unwrap();
1228 ctx.set_hkdf_md(Md::sha256()).unwrap();
1229 ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap())
1230 .unwrap();
1231 ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap())
1232 .unwrap();
1233 ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap())
1234 .unwrap();
1235 let mut out = [0; 42];
1236 ctx.derive(Some(&mut out)).unwrap();
1237
1238 assert_eq!(
1239 &out[..],
1240 hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865")
1241 .unwrap()
1242 );
1243 }
1244
1245 #[test]
1246 #[cfg(any(ossl111, libressl360))]
1247 fn hkdf_expand() {
1248 let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
1249 ctx.derive_init().unwrap();
1250 ctx.set_hkdf_mode(HkdfMode::EXPAND_ONLY).unwrap();
1251 ctx.set_hkdf_md(Md::sha256()).unwrap();
1252 ctx.set_hkdf_key(
1253 &hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
1254 .unwrap(),
1255 )
1256 .unwrap();
1257 ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap())
1258 .unwrap();
1259 let mut out = [0; 42];
1260 ctx.derive(Some(&mut out)).unwrap();
1261
1262 assert_eq!(
1263 &out[..],
1264 hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865")
1265 .unwrap()
1266 );
1267 }
1268
1269 #[test]
1270 #[cfg(any(ossl111, libressl360))]
1271 fn hkdf_extract() {
1272 let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
1273 ctx.derive_init().unwrap();
1274 ctx.set_hkdf_mode(HkdfMode::EXTRACT_ONLY).unwrap();
1275 ctx.set_hkdf_md(Md::sha256()).unwrap();
1276 ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap())
1277 .unwrap();
1278 ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap())
1279 .unwrap();
1280 let mut out = vec![];
1281 ctx.derive_to_vec(&mut out).unwrap();
1282
1283 assert_eq!(
1284 &out[..],
1285 hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
1286 .unwrap()
1287 );
1288 }
1289
1290 #[test]
1291 fn verify_fail() {
1292 let key1 = Rsa::generate(4096).unwrap();
1293 let key1 = PKey::from_rsa(key1).unwrap();
1294
1295 let data = b"Some Crypto Text";
1296
1297 let mut ctx = PkeyCtx::new(&key1).unwrap();
1298 ctx.sign_init().unwrap();
1299 let mut signature = vec![];
1300 ctx.sign_to_vec(data, &mut signature).unwrap();
1301
1302 let bad_data = b"Some Crypto text";
1303
1304 ctx.verify_init().unwrap();
1305 let valid = ctx.verify(bad_data, &signature);
1306 assert!(matches!(valid, Ok(false) | Err(_)));
1307 assert!(ErrorStack::get().errors().is_empty());
1308 }
1309
1310 #[test]
1311 fn verify_fail_ec() {
1312 let key1 =
1313 EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap();
1314 let key1 = PKey::from_ec_key(key1).unwrap();
1315
1316 let data = b"Some Crypto Text";
1317 let mut ctx = PkeyCtx::new(&key1).unwrap();
1318 ctx.verify_init().unwrap();
1319 assert!(matches!(ctx.verify(data, &[0; 64]), Ok(false) | Err(_)));
1320 assert!(ErrorStack::get().errors().is_empty());
1321 }
1322
1323 #[test]
1324 fn test_verify_recover() {
1325 let key = Rsa::generate(2048).unwrap();
1326 let key = PKey::from_rsa(key).unwrap();
1327
1328 let digest = [
1329 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
1330 24, 25, 26, 27, 28, 29, 30, 31,
1331 ];
1332
1333 let mut ctx = PkeyCtx::new(&key).unwrap();
1334 ctx.sign_init().unwrap();
1335 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1336 ctx.set_signature_md(Md::sha256()).unwrap();
1337 let mut signature = vec![];
1338 ctx.sign_to_vec(&digest, &mut signature).unwrap();
1339
1340 let mut ctx = PkeyCtx::new(&key).unwrap();
1342 ctx.verify_recover_init().unwrap();
1343 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1344 ctx.set_signature_md(Md::sha256()).unwrap();
1345 let length = ctx.verify_recover(&signature, None).unwrap();
1346 let mut result_buf = vec![0; length];
1347 let length = ctx
1348 .verify_recover(&signature, Some(&mut result_buf))
1349 .unwrap();
1350 assert_eq!(length, digest.len());
1351 assert_eq!(result_buf[..length], digest);
1353
1354 let mut ctx = PkeyCtx::new(&key).unwrap();
1356 ctx.verify_recover_init().unwrap();
1357 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1358 let length = ctx.verify_recover(&signature, None).unwrap();
1359 let mut result_buf = vec![0; length];
1360 let length = ctx
1361 .verify_recover(&signature, Some(&mut result_buf))
1362 .unwrap();
1363 assert_eq!(length, 51);
1365 assert_eq!(result_buf[length - digest.len()..length], digest);
1367 }
1368
1369 #[test]
1370 #[cfg(ossl320)]
1371 fn set_nonce_type() {
1372 let key1 =
1373 EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap();
1374 let key1 = PKey::from_ec_key(key1).unwrap();
1375
1376 let mut ctx = PkeyCtx::new(&key1).unwrap();
1377 ctx.sign_init().unwrap();
1378 ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap();
1379 let nonce_type = ctx.nonce_type().unwrap();
1380 assert_eq!(nonce_type, NonceType::DETERMINISTIC_K);
1381 assert!(ErrorStack::get().errors().is_empty());
1382 }
1383
1384 #[test]
1387 #[cfg(ossl320)]
1388 fn ecdsa_deterministic_signature() {
1389 let private_key_pem = "-----BEGIN PRIVATE KEY-----
1390MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCDJr6nYRbp1FmtcIVdnsdaTTlDD2zbo
1391mxJ7imIrEg9nIQ==
1392-----END PRIVATE KEY-----";
1393
1394 let key1 = EcKey::private_key_from_pem(private_key_pem.as_bytes()).unwrap();
1395 let key1 = PKey::from_ec_key(key1).unwrap();
1396 let input = "sample";
1397 let expected_output = hex::decode("3046022100EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716022100F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8").unwrap();
1398
1399 let hashed_input = hash(MessageDigest::sha256(), input.as_bytes()).unwrap();
1400 let mut ctx = PkeyCtx::new(&key1).unwrap();
1401 ctx.sign_init().unwrap();
1402 ctx.set_signature_md(Md::sha256()).unwrap();
1403 ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap();
1404
1405 let mut output = vec![];
1406 ctx.sign_to_vec(&hashed_input, &mut output).unwrap();
1407 assert_eq!(output, expected_output);
1408 assert!(ErrorStack::get().errors().is_empty());
1409 }
1410
1411 #[test]
1412 #[cfg(ossl350)]
1413 fn set_context_string_mldsa() {
1414 let xi = hex::decode("f696484048ec21f96cf50a56d0759c448f3779752f0383d37449690694cf7a68")
1417 .unwrap();
1418 let msg = hex::decode("6dbbc4375136df3b07f7c70e639e223e").unwrap();
1419 let ctx = hex::decode("480c658c0cb3e040bde084345cef0df7").unwrap();
1420 let expected_sig = hex::decode("0e9e903efe9d51ef5356b9794e52cf55cbfde58596f7e81faafe2921928279aab3ec9ba9a072c2c68adc72f0c2946fd4f5adb4c722a2f0e55676f1c79cbdc1d8afd19cf86156b5f7f8d012cd8245fb03fe30c62ea63110a722782367983030afadd16391b345f00d9c6d9750ae4b7099d5fcb66b944a213cf4881fa0f806e293554e869205e3e8e9abe67d0749d8c72fb882d3f3d1512f3077845787050527bde82da3cfc8ae9d0ab7827281a14f2bf6131cb79d27f4c781d0e8e42da9fdecb5be1979c9ccde17f1cc5b94f2f8e0a93d3e085ec72e221ca7d6bdad712a2c649b7bfdd0ad02306dd49cbdc298d4b23e73db05aa6a8b1514396e3032fe512d8cf58c5b61a546e1de56d98ad98c6d6a81db9865566a7cad4d533cb1d7770f2807819bb436e89045f8ac363aa6af27b5b7488d2303b10ba6e80e61ec0b8ae5850c96edeaf97ed2ebe64f77df8708c31bc6f6d4598dfc7c7ddb12b16b85adac7d8f1c2d961983ca2db804e3062c8e94d37c97181abfa111529adf15ed04dc403e9758d545cee70e868c222ed724d0f9483d7d2c5c44ad28662382ec40b7949ce08a6acb69d05a90d52ce487ce8fb6b5e5b91a2187d021ece47700f2f8eb5d2eb8e86000f14b978a051009c54ab1f1b90daa1d0d6711249d766d91a5f8c8604568bfc2f52822c52d625f451c194a5cfa4151b4fda81873e5f444144344eb75410033e2ba3d77850cae4b34495943a3880e273bb8842295ad853d1c7055a290e5ca084ba993c18810a85392ba042b7efe1e002c923723a43cc7b2dedca6123beebc4968ce42bb10d19111b3f77f519c19e9fc8111616dfd53b01eee401af9530568ffe98164e2d2e220a66422efb00bc90b07e48804c67db44f79e0595ad4a31e9b760c01e9fc239fabf55837316d7a13fd069f86563936e7b61ccb7d0dee4bd93e6b129c7da92a4516b7fa263cb6bf5940228312973b442f305dcfc40f843be2da8d693450f9ecf339bc9419f543a2fa0d4dc7793aced11d8e50d68003c2bd0212a7af1a5cfd7e8e54f14d8c627b3cd9558fbab33bf6209e485e59a9c9feecc54caa2dfece838b97b313c169cf27404cfc6dc5174856300208e10244183b2fcd28d34d67228eb9611b8f739a112178dc143fda2b8e64417e0f4c18f875eff34ec80a0fe04b5016473385a3e9c7b863b49ca05ebc3a34724a99488eba3dd49608da335a2acda60a91f3b8fb04ca30de481c0e1f17af2f13227b183345250b523257e08b58e15eb7b22a82ce581e63310a35cffb159ec276ecf3fac1ccefc23389de6c29b7e4454987611b315fb7684c72376ba448161cd82bc6a924095097c897b414750df37d34bbd2844979fbbdf68110afc3e14cce7cf963c375c92dcf65e4d633093bb8094052f8e9e6c4f3f650e9082f7346867794474a89f74e543714a5ad03ba003ffc1c716d56fb6078798e68ad4072d7db5099d0eb2c7ffdf21bcb4308965c13e0e1bd36bfab7c4267fa0c02ac393e70883b734027b9b087dabcd2c9bb65d9f769eae934c2b0415b2a5f2d7933e259ba51b2bd82fc08aa496e5fd3c4c0668e432dda489b4b9626006a2a958c0758624544279336421e92c477b09b968137686b68c5fbee84629b2c6b5506ad42198eefe6dfed5273fd74387faec972120aeaf85bec1491293362ebb2bda24eb7b3632c0950cf16f793fb333ca0025f57ce51b141cdc34456bfce530b417b00b574cbd4d13be8ef48fd3326948f7adc5b1f0398fcf0281e040407b3f9b7f79e4f1e89fb5eca34c9b387b0db3a5e98e253b999cd4c1616fd7e3fd26aa896c2118fe1e92499ddf5ff1125377a59987e84e03181262f7ad843b61b6450d92372cbcac16ba5b9b8d8deee7781f841672d91f336ce220fbfff7e32d61c98f5249e67bfef35edc3d9c3630b4f956c44c4a3e93f851c7775b64d759f2632b5ee38f0f3fff016a1fd3999b50c4f1de82cec0f11c34e494d51ad34df7bd812899daec5dfbd1b8405baf261e1da7898ba1dc1ced8afa4c23d662859d8a68205b62b6f908e2411d3a125e71442f74fc08b02e65195a63f198e1cb6c408e6a1b157d2a4b85a792cac2a07ddaea79c5858ce0ebdcdeab199483e2367f9b4785344447dca9251eb3df906cf4934228c4c028495f00e130722e175243791680bf540ca60e4c17c910637f6db35c1670d5c6d7e8264fa97fa540c870c87d1aa441599ee6fe6c22eabf8fc49c824b3bfac6491a2349ea33c4cb6cb19c0facb7d0cdb62db2ba56a5c337f9fe7b4ab5936275f98fe487b6c4805be709f67456caebd3043737a5974b0ca932b19c435bed01010c4617d350d803ff22dbbb3442189d9f81a0e5b47edfa4ea0a832fb14d27b19be226b42910ed10ac2d404abd96262bde3c391b238fa9bcfd3734275dacfc411811e01b1178750c745fe9462740c3f91f130535a7feb6be25b34a3314666ebaef01f5ec8b656add9b87e59c5bae71153e91be21505f27246035ec6c2569d7f165723a169cda18aaadb1481d84976da019a149b02f5b1f9b8c090a8115ecb3be65423aa1461e35c804a411b1cb191a8734233ca7a42acaee8eb4f451aa3089b9542a3c65e92a3a74b14443d1a8d72846fa7846098ec3233d2553ed4ab542c8c425cbabb94bb2fdb5223acb999ba31a19a0ff9b646fc4297832d36722e0af0c03899c8ce17c79303b091512f0106b4285e6e8faf09325f0bc3d8d724575c9556931a4dc34c93d81a79f25199ed712a97309630b5635ae067edd4e17be9d4e194905f8d3c7c6ad93bd219beac7c389f62f8adec30a72bcbc15e8586b9e2b057140eb95fadd960389230edb3925dd9a7deb86f72502ffcebbe9a65a99e6cecf61823f9cd326f298b9430a0f476e57093895e26b0375c327b29c3e37f14474af815dd90cfbc8e61fc2f0b528b3db0e5a5407db99c3c5c2862e3b68084305e93c79f1b962a6a5d28c76969e1d5d1e82ad831ee1b6238208890db7006b395771e34c1a0d25ebf651273ba3d495417033163b46f6a176b79c446c92ebbed4bc84f0e1effc0b38d3e269cd39f392472f1634acd1bd178a8ea5a54e045c45e19d54bc286e9fb0e324c30e00593529aa28f7b66288144ba6db9ff9f368565944bf776e93e27741fd7ded89144bad8a3c1287498973d7cd8d883fe3012db6af76e9ee1dfc189e1e7f97f1e23b288c5776de731b286a80fa349b09db359a5cfafc83c46de3b43cfe9e96270e18749a3af460d1312c4eb058935f13eaa29e8836877a88734356a816b319178776310086551003227f0b191aa6058cf8209de79cf106d57c4b769f142054ccc16b0348bf620f1a28dca8ff02e11fdae7cd155383b59e4acdfc53795786b759b5a03abb1b25adccf711e30ce1b783dbf75421d6ca5e146c6deca0da3078575c936063131c14f57ec4eef5fa5047f3e3be6fe2d3940878f905ee5c7e46cfa43575b64b6a5f71eb715e2cf1aa514df138234317b401d57f1a61ff08a0eedaa6b4370e61003532fffabfbe368eb465230b7f25c80bf73ae239b9deb8ce54b64bfc06820c01507aa2d9a8a6a9f5ed2d8912b4e1b43192baee1e10df1c15c88f7fb4381cac124848b55549239e2f1acc7a4352c4aeb56307d670ea52217b272345effaba37c04dccf9f4d8a9c89e2d51ee3cfd8a53e369256800af40e230d2c554114e99db275e8f8dc34ad6f2ecca886e018bce9822041a9196d4efe9ec952ae2ff4fc8256084923075295a82034909942c87b64e5bb941eae7de6cba2540c594b3f1f4a24d6fc25d1182a88b9e6dc4616a3a76d03523e8c34c71684d8c5e5be134402df6153e9230f6e013ec6131e5af35a4b8c5aa227b2452cc8232bbc904d4b822eeddf96c89b16af80856afe9d5a66f914b81b2d52efc451e6f3d92cfba8070a9b3957e74db749c1b94dc5acd950b6a553909229fd916a1cfd56701f57a0971224070eb24d3718a665dda9b4ca9171ffbdfea55ef194f91ecc61d04cf5068cb3b7e481073b9396e8ec349e5257db91f0f00d9df9d3b465ca93c15c9efefb9aed057343eb169b206aa0db60db319801899a2b6527e1f97263444599b555dab700dffc302d6767385f982c78b4932ca12a16d575752b915b034dd69f3473c52097fc6078dd7ef6462b820bee65980510367235191d900033f13b7e2bd43cd423fbed47aa54377f67be5583c1c385c659449bf202032502d2db40101cdb5543ddfcea652c5b3c711d932c2c22ec67256b194e5bcab3ae054d02b22e7193c7c32aa3a958822cd5917117f53569ad42a5b30a64781355d22ff3bb70b76430b7e8e538df4c5411a09e6fecc4086d86aebfe497315056d11660165b47383302d6461a7f0f2d0c6e894c33c71c1c4eaa715d55ec369bbf7d86623a7b2b76bed3b1356ed80f8a1ee77229ab6cddd96eaa724fa740b480ae6fb1768c67adc5ce85dcf0f46026fdcdb4f346c60c2478f6da4b33fc06a0645fb5629b80e96d6f78aa4ae1c5cefefb24912de843f509e9609fc969be9a66c28d5608d6bcdc6bc0e6ca5752142e196679935fc745f1a84fed03d47276e29ffefa61b4232b737583c1c2e93752a7acbac2f747698b9b023a4000122a706c758fd300000000000000000000000000000000000000000000000000080f13161a1e").unwrap();
1421
1422 let key = PKey::private_key_from_seed(None, KeyType::ML_DSA_65, None, &xi).unwrap();
1423
1424 let mut md_ctx = MdCtx::new().unwrap();
1426 let pkey_ctx = md_ctx.digest_verify_init(None, &key).unwrap();
1427 pkey_ctx.set_context_string(&ctx).unwrap();
1428 assert!(md_ctx.digest_verify(&msg, &expected_sig).unwrap());
1429
1430 let mut md_ctx = MdCtx::new().unwrap();
1432 let pkey_ctx = md_ctx.digest_sign_init(None, &key).unwrap();
1433 pkey_ctx.set_context_string(&ctx).unwrap();
1434 let mut sig = vec![];
1435 md_ctx.digest_sign_to_vec(&msg, &mut sig).unwrap();
1436
1437 let mut md_ctx = MdCtx::new().unwrap();
1438 let pkey_ctx = md_ctx.digest_verify_init(None, &key).unwrap();
1439 pkey_ctx.set_context_string(&ctx).unwrap();
1440 assert!(md_ctx.digest_verify(&msg, &sig).unwrap());
1441
1442 assert!(ErrorStack::get().errors().is_empty());
1443 }
1444}