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