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)]
273 #[inline]
274 pub fn verify_recover(
275 &mut self,
276 sig: &[u8],
277 to: Option<&mut [u8]>,
278 ) -> Result<usize, ErrorStack> {
279 let mut written = to.as_ref().map_or(0, |b| b.len());
280 unsafe {
281 cvt(ffi::EVP_PKEY_verify_recover(
282 self.as_ptr(),
283 to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
284 &mut written,
285 sig.as_ptr(),
286 sig.len(),
287 ))?;
288 }
289
290 Ok(written)
291 }
292}
293
294impl<T> PkeyCtxRef<T>
295where
296 T: HasPrivate,
297{
298 #[corresponds(EVP_PKEY_decrypt_init)]
300 #[inline]
301 pub fn decrypt_init(&mut self) -> Result<(), ErrorStack> {
302 unsafe {
303 cvt(ffi::EVP_PKEY_decrypt_init(self.as_ptr()))?;
304 }
305
306 Ok(())
307 }
308
309 #[corresponds(EVP_PKEY_sign_init)]
311 #[inline]
312 pub fn sign_init(&mut self) -> Result<(), ErrorStack> {
313 unsafe {
314 cvt(ffi::EVP_PKEY_sign_init(self.as_ptr()))?;
315 }
316
317 Ok(())
318 }
319
320 #[corresponds(EVP_PKEY_derive_set_peer)]
322 pub fn derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack>
323 where
324 U: HasPublic,
325 {
326 unsafe {
327 cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), key.as_ptr()))?;
328 }
329
330 Ok(())
331 }
332
333 #[corresponds(EVP_PKEY_decrypt)]
338 #[inline]
339 pub fn decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
340 let mut written = to.as_ref().map_or(0, |b| b.len());
341 unsafe {
342 cvt(ffi::EVP_PKEY_decrypt(
343 self.as_ptr(),
344 to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
345 &mut written,
346 from.as_ptr(),
347 from.len(),
348 ))?;
349 }
350
351 Ok(written)
352 }
353
354 pub fn decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> {
356 let base = out.len();
357 let len = self.decrypt(from, None)?;
358 out.resize(base + len, 0);
359 let len = self.decrypt(from, Some(&mut out[base..]))?;
360 out.truncate(base + len);
361 Ok(len)
362 }
363
364 #[corresponds(EVP_PKEY_sign)]
374 #[inline]
375 pub fn sign(&mut self, data: &[u8], sig: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
376 let mut written = sig.as_ref().map_or(0, |b| b.len());
377 unsafe {
378 cvt(ffi::EVP_PKEY_sign(
379 self.as_ptr(),
380 sig.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
381 &mut written,
382 data.as_ptr(),
383 data.len(),
384 ))?;
385 }
386
387 Ok(written)
388 }
389
390 pub fn sign_to_vec(&mut self, data: &[u8], sig: &mut Vec<u8>) -> Result<usize, ErrorStack> {
392 let base = sig.len();
393 let len = self.sign(data, None)?;
394 sig.resize(base + len, 0);
395 let len = self.sign(data, Some(&mut sig[base..]))?;
396 sig.truncate(base + len);
397 Ok(len)
398 }
399}
400
401impl<T> PkeyCtxRef<T> {
402 #[corresponds(EVP_PKEY_derive_init)]
404 #[inline]
405 pub fn derive_init(&mut self) -> Result<(), ErrorStack> {
406 unsafe {
407 cvt(ffi::EVP_PKEY_derive_init(self.as_ptr()))?;
408 }
409
410 Ok(())
411 }
412
413 #[corresponds(EVP_PKEY_keygen_init)]
415 #[inline]
416 pub fn keygen_init(&mut self) -> Result<(), ErrorStack> {
417 unsafe {
418 cvt(ffi::EVP_PKEY_keygen_init(self.as_ptr()))?;
419 }
420
421 Ok(())
422 }
423
424 #[corresponds(EVP_PKEY_paramgen_init)]
426 #[inline]
427 pub fn paramgen_init(&mut self) -> Result<(), ErrorStack> {
428 unsafe {
429 cvt(ffi::EVP_PKEY_paramgen_init(self.as_ptr()))?;
430 }
431
432 Ok(())
433 }
434
435 #[corresponds(EVP_PKEY_CTX_set_signature_md)]
440 #[inline]
441 pub fn set_signature_md(&self, md: &MdRef) -> Result<(), ErrorStack> {
442 unsafe {
443 cvt(ffi::EVP_PKEY_CTX_set_signature_md(
444 self.as_ptr(),
445 md.as_ptr(),
446 ))?;
447 }
448 Ok(())
449 }
450
451 #[corresponds(EVP_PKEY_CTX_set_dh_paramgen_prime_len)]
455 #[cfg(not(boringssl))]
456 #[inline]
457 pub fn set_dh_paramgen_prime_len(&mut self, bits: u32) -> Result<(), ErrorStack> {
458 unsafe {
459 cvt(ffi::EVP_PKEY_CTX_set_dh_paramgen_prime_len(
460 self.as_ptr(),
461 bits as i32,
462 ))?;
463 }
464
465 Ok(())
466 }
467
468 #[corresponds(EVP_PKEY_CTX_set_dh_paramgen_generator)]
472 #[cfg(not(boringssl))]
473 #[inline]
474 pub fn set_dh_paramgen_generator(&mut self, bits: u32) -> Result<(), ErrorStack> {
475 unsafe {
476 cvt(ffi::EVP_PKEY_CTX_set_dh_paramgen_generator(
477 self.as_ptr(),
478 bits as i32,
479 ))?;
480 }
481
482 Ok(())
483 }
484
485 #[corresponds(EVP_PKEY_CTX_set_dsa_paramgen_bits)]
489 #[inline]
490 pub fn set_dsa_paramgen_bits(&mut self, bits: u32) -> Result<(), ErrorStack> {
491 unsafe {
492 cvt(ffi::EVP_PKEY_CTX_set_dsa_paramgen_bits(
493 self.as_ptr(),
494 bits as i32,
495 ))?;
496 }
497
498 Ok(())
499 }
500
501 #[corresponds(EVP_PKEY_CTX_set_ec_paramgen_curve_nid)]
505 #[inline]
506 pub fn set_ec_paramgen_curve_nid(&mut self, nid: Nid) -> Result<(), ErrorStack> {
507 unsafe {
508 cvt(ffi::EVP_PKEY_CTX_set_ec_paramgen_curve_nid(
509 self.as_ptr(),
510 nid.as_raw(),
511 ))?;
512 }
513
514 Ok(())
515 }
516
517 #[corresponds(EVP_PKEY_CTX_get_rsa_padding)]
521 #[inline]
522 pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
523 let mut pad = 0;
524 unsafe {
525 cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))?;
526 }
527
528 Ok(Padding::from_raw(pad))
529 }
530
531 #[corresponds(EVP_PKEY_CTX_set_rsa_padding)]
535 #[inline]
536 pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
537 unsafe {
538 cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
539 self.as_ptr(),
540 padding.as_raw(),
541 ))?;
542 }
543
544 Ok(())
545 }
546
547 #[corresponds(EVP_PKEY_CTX_set_rsa_keygen_bits)]
551 #[inline]
552 pub fn set_rsa_keygen_bits(&mut self, bits: u32) -> Result<(), ErrorStack> {
553 unsafe {
554 cvt(ffi::EVP_PKEY_CTX_set_rsa_keygen_bits(
555 self.as_ptr(),
556 bits as i32,
557 ))?;
558 }
559
560 Ok(())
561 }
562
563 #[corresponds(EVP_PKEY_CTX_set1_rsa_keygen_pubexp)]
567 #[inline]
568 pub fn set_rsa_keygen_pubexp(&mut self, pubexp: &BigNumRef) -> Result<(), ErrorStack> {
569 unsafe {
570 cfg_if! {
571 if #[cfg(ossl300)] {
572 cvt(ffi::EVP_PKEY_CTX_set1_rsa_keygen_pubexp(
573 self.as_ptr(),
574 pubexp.as_ptr(),
575 ))?;
576 } else {
577 cvt(ffi::EVP_PKEY_CTX_set_rsa_keygen_pubexp(
578 self.as_ptr(),
579 cvt_p(ffi::BN_dup(pubexp.as_ptr()))?,
581 ))?;
582 }
583 }
584 }
585
586 Ok(())
587 }
588
589 #[corresponds(EVP_PKEY_CTX_set_rsa_pss_saltlen)]
593 #[inline]
594 pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> {
595 unsafe {
596 cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen(
597 self.as_ptr(),
598 len.as_raw(),
599 ))
600 .map(|_| ())
601 }
602 }
603
604 #[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)]
608 #[inline]
609 pub fn set_rsa_mgf1_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
610 unsafe {
611 cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
612 self.as_ptr(),
613 md.as_ptr(),
614 ))?;
615 }
616
617 Ok(())
618 }
619
620 #[corresponds(EVP_PKEY_CTX_set_rsa_oaep_md)]
624 #[inline]
625 pub fn set_rsa_oaep_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
626 unsafe {
627 cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
628 self.as_ptr(),
629 md.as_ptr() as *mut _,
630 ))?;
631 }
632
633 Ok(())
634 }
635
636 #[corresponds(EVP_PKEY_CTX_set0_rsa_oaep_label)]
640 pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> {
641 use crate::LenType;
642 let len = LenType::try_from(label.len()).unwrap();
643
644 unsafe {
645 let p = cvt_p(ffi::OPENSSL_malloc(label.len() as _))?;
646 ptr::copy_nonoverlapping(label.as_ptr(), p as *mut _, label.len());
647
648 let r = cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label(
649 self.as_ptr(),
650 p as *mut _,
651 len,
652 ));
653 if r.is_err() {
654 ffi::OPENSSL_free(p);
655 }
656 r?;
657 }
658
659 Ok(())
660 }
661
662 #[cfg(not(any(boringssl, awslc)))]
664 #[corresponds(EVP_PKEY_CTX_ctrl)]
665 #[inline]
666 pub fn set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack> {
667 unsafe {
668 cvt(ffi::EVP_PKEY_CTX_ctrl(
669 self.as_ptr(),
670 -1,
671 ffi::EVP_PKEY_OP_KEYGEN,
672 ffi::EVP_PKEY_CTRL_CIPHER,
673 0,
674 cipher.as_ptr() as *mut _,
675 ))?;
676 }
677
678 Ok(())
679 }
680
681 #[cfg(not(any(boringssl, awslc)))]
683 #[corresponds(EVP_PKEY_CTX_ctrl)]
684 #[inline]
685 pub fn set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
686 let len = c_int::try_from(key.len()).unwrap();
687
688 unsafe {
689 cvt(ffi::EVP_PKEY_CTX_ctrl(
690 self.as_ptr(),
691 -1,
692 ffi::EVP_PKEY_OP_KEYGEN,
693 ffi::EVP_PKEY_CTRL_SET_MAC_KEY,
694 len,
695 key.as_ptr() as *mut _,
696 ))?;
697 }
698
699 Ok(())
700 }
701
702 #[corresponds(EVP_PKEY_CTX_set_hkdf_md)]
706 #[cfg(any(ossl110, boringssl, libressl360, awslc))]
707 #[inline]
708 pub fn set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack> {
709 unsafe {
710 cvt(ffi::EVP_PKEY_CTX_set_hkdf_md(
711 self.as_ptr(),
712 digest.as_ptr(),
713 ))?;
714 }
715
716 Ok(())
717 }
718
719 #[corresponds(EVP_PKEY_CTX_set_hkdf_mode)]
729 #[cfg(any(ossl111, libressl360))]
730 #[inline]
731 pub fn set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack> {
732 unsafe {
733 cvt(ffi::EVP_PKEY_CTX_set_hkdf_mode(self.as_ptr(), mode.0))?;
734 }
735
736 Ok(())
737 }
738
739 #[corresponds(EVP_PKEY_CTX_set1_hkdf_key)]
748 #[cfg(any(ossl110, boringssl, libressl360, awslc))]
749 #[inline]
750 pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
751 #[cfg(not(any(boringssl, awslc)))]
752 let len = c_int::try_from(key.len()).unwrap();
753 #[cfg(any(boringssl, awslc))]
754 let len = key.len();
755
756 unsafe {
757 cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key(
758 self.as_ptr(),
759 key.as_ptr(),
760 len,
761 ))?;
762 }
763
764 Ok(())
765 }
766
767 #[corresponds(EVP_PKEY_CTX_set1_hkdf_salt)]
773 #[cfg(any(ossl110, boringssl, libressl360, awslc))]
774 #[inline]
775 pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> {
776 #[cfg(not(any(boringssl, awslc)))]
777 let len = c_int::try_from(salt.len()).unwrap();
778 #[cfg(any(boringssl, awslc))]
779 let len = salt.len();
780
781 unsafe {
782 cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt(
783 self.as_ptr(),
784 salt.as_ptr(),
785 len,
786 ))?;
787 }
788
789 Ok(())
790 }
791
792 #[corresponds(EVP_PKEY_CTX_add1_hkdf_info)]
798 #[cfg(any(ossl110, boringssl, libressl360, awslc))]
799 #[inline]
800 pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> {
801 #[cfg(not(any(boringssl, awslc)))]
802 let len = c_int::try_from(info.len()).unwrap();
803 #[cfg(any(boringssl, awslc))]
804 let len = info.len();
805
806 unsafe {
807 cvt(ffi::EVP_PKEY_CTX_add1_hkdf_info(
808 self.as_ptr(),
809 info.as_ptr(),
810 len,
811 ))?;
812 }
813
814 Ok(())
815 }
816
817 #[corresponds(EVP_PKEY_derive)]
821 #[allow(unused_mut)]
822 pub fn derive(&mut self, mut buf: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
823 #[cfg(any(all(ossl110, not(ossl300)), libressl))]
848 {
849 if let Some(b) = buf.as_deref_mut() {
850 let mut required = 0;
851 let probe_ok = unsafe {
852 ffi::EVP_PKEY_derive(self.as_ptr(), ptr::null_mut(), &mut required) == 1
853 };
854 if !probe_ok {
855 let _ = ErrorStack::get();
856 } else if required != usize::MAX && b.len() < required {
857 let mut temp = vec![0u8; required];
858 let mut len = required;
859 unsafe {
860 cvt(ffi::EVP_PKEY_derive(
861 self.as_ptr(),
862 temp.as_mut_ptr(),
863 &mut len,
864 ))?;
865 }
866 let copy_len = b.len().min(len);
867 b[..copy_len].copy_from_slice(&temp[..copy_len]);
868 return Ok(copy_len);
869 }
870 }
871 }
872 let mut len = buf.as_ref().map_or(0, |b| b.len());
873 unsafe {
874 cvt(ffi::EVP_PKEY_derive(
875 self.as_ptr(),
876 buf.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
877 &mut len,
878 ))?;
879 }
880
881 Ok(len)
882 }
883
884 pub fn derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack> {
886 let base = buf.len();
887 let len = self.derive(None)?;
888 buf.resize(base + len, 0);
889 let len = self.derive(Some(&mut buf[base..]))?;
890 buf.truncate(base + len);
891 Ok(len)
892 }
893
894 #[corresponds(EVP_PKEY_keygen)]
896 #[inline]
897 pub fn keygen(&mut self) -> Result<PKey<Private>, ErrorStack> {
898 unsafe {
899 let mut key = ptr::null_mut();
900 cvt(ffi::EVP_PKEY_keygen(self.as_ptr(), &mut key))?;
901 Ok(PKey::from_ptr(key))
902 }
903 }
904
905 #[corresponds(EVP_PKEY_paramgen)]
907 #[inline]
908 pub fn paramgen(&mut self) -> Result<PKey<Params>, ErrorStack> {
909 unsafe {
910 let mut key = ptr::null_mut();
911 cvt(ffi::EVP_PKEY_paramgen(self.as_ptr(), &mut key))?;
912 Ok(PKey::from_ptr(key))
913 }
914 }
915
916 #[cfg(ossl320)]
923 #[corresponds(EVP_PKEY_CTX_set_params)]
924 pub fn set_nonce_type(&mut self, nonce_type: NonceType) -> Result<(), ErrorStack> {
925 let nonce_field_name = c"nonce-type";
926 let mut nonce_type = nonce_type.0;
927 unsafe {
928 let param_nonce =
929 ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type);
930 let param_end = ffi::OSSL_PARAM_construct_end();
931
932 let params = [param_nonce, param_end];
933 cvt(ffi::EVP_PKEY_CTX_set_params(self.as_ptr(), params.as_ptr()))?;
934 }
935 Ok(())
936 }
937
938 #[cfg(ossl320)]
945 #[corresponds(EVP_PKEY_CTX_get_params)]
946 pub fn nonce_type(&mut self) -> Result<NonceType, ErrorStack> {
947 let nonce_field_name = c"nonce-type";
948 let mut nonce_type: c_uint = 0;
949 unsafe {
950 let param_nonce =
951 ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type);
952 let param_end = ffi::OSSL_PARAM_construct_end();
953
954 let mut params = [param_nonce, param_end];
955 cvt(ffi::EVP_PKEY_CTX_get_params(
956 self.as_ptr(),
957 params.as_mut_ptr(),
958 ))?;
959 }
960 Ok(NonceType(nonce_type))
961 }
962
963 #[cfg(ossl350)]
968 #[corresponds(EVP_PKEY_CTX_set_params)]
969 pub fn set_context_string(&mut self, context: &[u8]) -> Result<(), ErrorStack> {
970 let mut builder = crate::ossl_param::OsslParamBuilder::new()?;
971 builder.add_octet_string(c"context-string", context)?;
972 let params = builder.to_param()?;
973 unsafe {
974 cvt(ffi::EVP_PKEY_CTX_set_params(self.as_ptr(), params.as_ptr()))?;
975 }
976 Ok(())
977 }
978}
979
980#[cfg(test)]
981mod test {
982 use super::*;
983 use crate::bn::BigNum;
984 #[cfg(not(any(boringssl, awslc)))]
985 use crate::cipher::Cipher;
986 use crate::ec::{EcGroup, EcKey};
987 use crate::hash::{hash, MessageDigest};
988 use crate::md::Md;
989 #[cfg(ossl350)]
990 use crate::md_ctx::MdCtx;
991 use crate::nid::Nid;
992 #[cfg(ossl350)]
993 use crate::pkey::KeyType;
994 use crate::pkey::PKey;
995 use crate::rsa::Rsa;
996 use crate::sign::Verifier;
997 #[cfg(not(boringssl))]
998 use cfg_if::cfg_if;
999
1000 #[test]
1001 fn rsa() {
1002 let key = include_bytes!("../test/rsa.pem");
1003 let rsa = Rsa::private_key_from_pem(key).unwrap();
1004 let pkey = PKey::from_rsa(rsa).unwrap();
1005
1006 let mut ctx = PkeyCtx::new(&pkey).unwrap();
1007 ctx.encrypt_init().unwrap();
1008 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1009
1010 let pt = "hello world".as_bytes();
1011 let mut ct = vec![];
1012 ctx.encrypt_to_vec(pt, &mut ct).unwrap();
1013
1014 ctx.decrypt_init().unwrap();
1015 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1016
1017 let mut out = vec![];
1018 ctx.decrypt_to_vec(&ct, &mut out).unwrap();
1019
1020 assert_eq!(pt, out);
1021 }
1022
1023 #[test]
1024 fn rsa_oaep() {
1025 let key = include_bytes!("../test/rsa.pem");
1026 let rsa = Rsa::private_key_from_pem(key).unwrap();
1027 let pkey = PKey::from_rsa(rsa).unwrap();
1028
1029 let mut ctx = PkeyCtx::new(&pkey).unwrap();
1030 ctx.encrypt_init().unwrap();
1031 ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
1032 ctx.set_rsa_oaep_md(Md::sha256()).unwrap();
1033 ctx.set_rsa_mgf1_md(Md::sha256()).unwrap();
1034
1035 let pt = "hello world".as_bytes();
1036 let mut ct = vec![];
1037 ctx.encrypt_to_vec(pt, &mut ct).unwrap();
1038
1039 ctx.decrypt_init().unwrap();
1040 ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
1041 ctx.set_rsa_oaep_md(Md::sha256()).unwrap();
1042 ctx.set_rsa_mgf1_md(Md::sha256()).unwrap();
1043
1044 let mut out = vec![];
1045 ctx.decrypt_to_vec(&ct, &mut out).unwrap();
1046
1047 assert_eq!(pt, out);
1048 }
1049
1050 #[test]
1051 fn rsa_sign() {
1052 let key = include_bytes!("../test/rsa.pem");
1053 let rsa = Rsa::private_key_from_pem(key).unwrap();
1054 let pkey = PKey::from_rsa(rsa).unwrap();
1055
1056 let mut ctx = PkeyCtx::new(&pkey).unwrap();
1057 ctx.sign_init().unwrap();
1058 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1059 ctx.set_signature_md(Md::sha384()).unwrap();
1060
1061 let msg = b"hello world";
1062 let digest = hash(MessageDigest::sha384(), msg).unwrap();
1063 let mut signature = vec![];
1064 ctx.sign_to_vec(&digest, &mut signature).unwrap();
1065
1066 let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap();
1067 verifier.update(msg).unwrap();
1068 assert!(matches!(verifier.verify(&signature), Ok(true)));
1069 }
1070
1071 #[test]
1072 fn rsa_sign_pss() {
1073 let key = include_bytes!("../test/rsa.pem");
1074 let rsa = Rsa::private_key_from_pem(key).unwrap();
1075 let pkey = PKey::from_rsa(rsa).unwrap();
1076
1077 let mut ctx = PkeyCtx::new(&pkey).unwrap();
1078 ctx.sign_init().unwrap();
1079 ctx.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
1080 ctx.set_signature_md(Md::sha384()).unwrap();
1081 ctx.set_rsa_pss_saltlen(RsaPssSaltlen::custom(14)).unwrap();
1082
1083 let msg = b"hello world";
1084 let digest = hash(MessageDigest::sha384(), msg).unwrap();
1085 let mut signature = vec![];
1086 ctx.sign_to_vec(&digest, &mut signature).unwrap();
1087
1088 let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap();
1089 verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
1090 verifier
1091 .set_rsa_pss_saltlen(RsaPssSaltlen::custom(14))
1092 .unwrap();
1093 verifier.update(msg).unwrap();
1094 assert!(matches!(verifier.verify(&signature), Ok(true)));
1095 }
1096
1097 #[test]
1098 fn derive() {
1099 let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
1100 let key1 = EcKey::generate(&group).unwrap();
1101 let key1 = PKey::from_ec_key(key1).unwrap();
1102 let key2 = EcKey::generate(&group).unwrap();
1103 let key2 = PKey::from_ec_key(key2).unwrap();
1104
1105 let mut ctx = PkeyCtx::new(&key1).unwrap();
1106 ctx.derive_init().unwrap();
1107 ctx.derive_set_peer(&key2).unwrap();
1108
1109 let mut buf = vec![];
1110 ctx.derive_to_vec(&mut buf).unwrap();
1111 }
1112
1113 #[test]
1114 #[cfg(any(ossl111, libressl370))]
1115 fn derive_undersized_buffer() {
1116 let key1 = PKey::generate_x25519().unwrap();
1122 let key2 = PKey::generate_x25519().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 = [0u8; 4];
1129 let result = ctx.derive(Some(&mut buf));
1130 #[cfg(any(all(ossl110, not(ossl300)), libressl))]
1131 assert_eq!(result.unwrap(), 4);
1132 #[cfg(all(ossl300, not(libressl)))]
1133 assert!(result.is_err());
1134 }
1135
1136 #[test]
1137 #[cfg(not(any(boringssl, awslc)))]
1138 fn cmac_keygen() {
1139 let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap();
1140 ctx.keygen_init().unwrap();
1141 ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap();
1142 ctx.set_keygen_mac_key(&hex::decode("9294727a3638bb1c13f48ef8158bfc9d").unwrap())
1143 .unwrap();
1144 ctx.keygen().unwrap();
1145 }
1146
1147 #[test]
1148 #[cfg(not(boringssl))]
1149 fn dh_paramgen() {
1150 let mut ctx = PkeyCtx::new_id(Id::DH).unwrap();
1151 ctx.paramgen_init().unwrap();
1152 ctx.set_dh_paramgen_prime_len(512).unwrap();
1153 ctx.set_dh_paramgen_generator(2).unwrap();
1154 let params = ctx.paramgen().unwrap();
1155
1156 assert_eq!(params.size(), 64);
1157 }
1158
1159 #[test]
1160 #[cfg(not(boringssl))]
1161 fn dsa_paramgen() {
1162 let mut ctx = PkeyCtx::new_id(Id::DSA).unwrap();
1163 ctx.paramgen_init().unwrap();
1164 ctx.set_dsa_paramgen_bits(2048).unwrap();
1165 let params = ctx.paramgen().unwrap();
1166
1167 let size = {
1168 cfg_if! {
1169 if #[cfg(awslc)] {
1170 72
1171 } else if #[cfg(libressl)] {
1172 48
1173 } else {
1174 64
1175 }
1176 }
1177 };
1178 assert_eq!(params.size(), size);
1179 }
1180
1181 #[test]
1182 fn ec_keygen() {
1183 let mut ctx = PkeyCtx::new_id(Id::EC).unwrap();
1184 ctx.paramgen_init().unwrap();
1185 ctx.set_ec_paramgen_curve_nid(Nid::X9_62_PRIME256V1)
1186 .unwrap();
1187 let params = ctx.paramgen().unwrap();
1188
1189 assert_eq!(params.size(), 72);
1190 }
1191
1192 #[test]
1193 fn rsa_keygen() {
1194 let pubexp = BigNum::from_u32(65537).unwrap();
1195 let mut ctx = PkeyCtx::new_id(Id::RSA).unwrap();
1196 ctx.keygen_init().unwrap();
1197 ctx.set_rsa_keygen_pubexp(&pubexp).unwrap();
1198 ctx.set_rsa_keygen_bits(2048).unwrap();
1199 let key = ctx.keygen().unwrap();
1200
1201 assert_eq!(key.bits(), 2048);
1202 }
1203
1204 #[test]
1205 #[cfg(any(ossl110, boringssl, libressl360, awslc))]
1206 fn hkdf() {
1207 let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
1208 ctx.derive_init().unwrap();
1209 ctx.set_hkdf_md(Md::sha256()).unwrap();
1210 ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap())
1211 .unwrap();
1212 ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap())
1213 .unwrap();
1214 ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap())
1215 .unwrap();
1216 let mut out = [0; 42];
1217 ctx.derive(Some(&mut out)).unwrap();
1218
1219 assert_eq!(
1220 &out[..],
1221 hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865")
1222 .unwrap()
1223 );
1224 }
1225
1226 #[test]
1227 #[cfg(any(ossl111, libressl360))]
1228 fn hkdf_expand() {
1229 let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
1230 ctx.derive_init().unwrap();
1231 ctx.set_hkdf_mode(HkdfMode::EXPAND_ONLY).unwrap();
1232 ctx.set_hkdf_md(Md::sha256()).unwrap();
1233 ctx.set_hkdf_key(
1234 &hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
1235 .unwrap(),
1236 )
1237 .unwrap();
1238 ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap())
1239 .unwrap();
1240 let mut out = [0; 42];
1241 ctx.derive(Some(&mut out)).unwrap();
1242
1243 assert_eq!(
1244 &out[..],
1245 hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865")
1246 .unwrap()
1247 );
1248 }
1249
1250 #[test]
1251 #[cfg(any(ossl111, libressl360))]
1252 fn hkdf_extract() {
1253 let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
1254 ctx.derive_init().unwrap();
1255 ctx.set_hkdf_mode(HkdfMode::EXTRACT_ONLY).unwrap();
1256 ctx.set_hkdf_md(Md::sha256()).unwrap();
1257 ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap())
1258 .unwrap();
1259 ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap())
1260 .unwrap();
1261 let mut out = vec![];
1262 ctx.derive_to_vec(&mut out).unwrap();
1263
1264 assert_eq!(
1265 &out[..],
1266 hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
1267 .unwrap()
1268 );
1269 }
1270
1271 #[test]
1272 fn verify_fail() {
1273 let key1 = Rsa::generate(4096).unwrap();
1274 let key1 = PKey::from_rsa(key1).unwrap();
1275
1276 let data = b"Some Crypto Text";
1277
1278 let mut ctx = PkeyCtx::new(&key1).unwrap();
1279 ctx.sign_init().unwrap();
1280 let mut signature = vec![];
1281 ctx.sign_to_vec(data, &mut signature).unwrap();
1282
1283 let bad_data = b"Some Crypto text";
1284
1285 ctx.verify_init().unwrap();
1286 let valid = ctx.verify(bad_data, &signature);
1287 assert!(matches!(valid, Ok(false) | Err(_)));
1288 assert!(ErrorStack::get().errors().is_empty());
1289 }
1290
1291 #[test]
1292 fn verify_fail_ec() {
1293 let key1 =
1294 EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap();
1295 let key1 = PKey::from_ec_key(key1).unwrap();
1296
1297 let data = b"Some Crypto Text";
1298 let mut ctx = PkeyCtx::new(&key1).unwrap();
1299 ctx.verify_init().unwrap();
1300 assert!(matches!(ctx.verify(data, &[0; 64]), Ok(false) | Err(_)));
1301 assert!(ErrorStack::get().errors().is_empty());
1302 }
1303
1304 #[test]
1305 fn test_verify_recover() {
1306 let key = Rsa::generate(2048).unwrap();
1307 let key = PKey::from_rsa(key).unwrap();
1308
1309 let digest = [
1310 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
1311 24, 25, 26, 27, 28, 29, 30, 31,
1312 ];
1313
1314 let mut ctx = PkeyCtx::new(&key).unwrap();
1315 ctx.sign_init().unwrap();
1316 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1317 ctx.set_signature_md(Md::sha256()).unwrap();
1318 let mut signature = vec![];
1319 ctx.sign_to_vec(&digest, &mut signature).unwrap();
1320
1321 let mut ctx = PkeyCtx::new(&key).unwrap();
1323 ctx.verify_recover_init().unwrap();
1324 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1325 ctx.set_signature_md(Md::sha256()).unwrap();
1326 let length = ctx.verify_recover(&signature, None).unwrap();
1327 let mut result_buf = vec![0; length];
1328 let length = ctx
1329 .verify_recover(&signature, Some(&mut result_buf))
1330 .unwrap();
1331 assert_eq!(length, digest.len());
1332 assert_eq!(result_buf[..length], digest);
1334
1335 let mut ctx = PkeyCtx::new(&key).unwrap();
1337 ctx.verify_recover_init().unwrap();
1338 ctx.set_rsa_padding(Padding::PKCS1).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, 51);
1346 assert_eq!(result_buf[length - digest.len()..length], digest);
1348 }
1349
1350 #[test]
1351 #[cfg(ossl320)]
1352 fn set_nonce_type() {
1353 let key1 =
1354 EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap();
1355 let key1 = PKey::from_ec_key(key1).unwrap();
1356
1357 let mut ctx = PkeyCtx::new(&key1).unwrap();
1358 ctx.sign_init().unwrap();
1359 ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap();
1360 let nonce_type = ctx.nonce_type().unwrap();
1361 assert_eq!(nonce_type, NonceType::DETERMINISTIC_K);
1362 assert!(ErrorStack::get().errors().is_empty());
1363 }
1364
1365 #[test]
1368 #[cfg(ossl320)]
1369 fn ecdsa_deterministic_signature() {
1370 let private_key_pem = "-----BEGIN PRIVATE KEY-----
1371MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCDJr6nYRbp1FmtcIVdnsdaTTlDD2zbo
1372mxJ7imIrEg9nIQ==
1373-----END PRIVATE KEY-----";
1374
1375 let key1 = EcKey::private_key_from_pem(private_key_pem.as_bytes()).unwrap();
1376 let key1 = PKey::from_ec_key(key1).unwrap();
1377 let input = "sample";
1378 let expected_output = hex::decode("3046022100EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716022100F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8").unwrap();
1379
1380 let hashed_input = hash(MessageDigest::sha256(), input.as_bytes()).unwrap();
1381 let mut ctx = PkeyCtx::new(&key1).unwrap();
1382 ctx.sign_init().unwrap();
1383 ctx.set_signature_md(Md::sha256()).unwrap();
1384 ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap();
1385
1386 let mut output = vec![];
1387 ctx.sign_to_vec(&hashed_input, &mut output).unwrap();
1388 assert_eq!(output, expected_output);
1389 assert!(ErrorStack::get().errors().is_empty());
1390 }
1391
1392 #[test]
1393 #[cfg(ossl350)]
1394 fn set_context_string_mldsa() {
1395 let xi = hex::decode("f696484048ec21f96cf50a56d0759c448f3779752f0383d37449690694cf7a68")
1398 .unwrap();
1399 let msg = hex::decode("6dbbc4375136df3b07f7c70e639e223e").unwrap();
1400 let ctx = hex::decode("480c658c0cb3e040bde084345cef0df7").unwrap();
1401 let expected_sig = hex::decode("0e9e903efe9d51ef5356b9794e52cf55cbfde58596f7e81faafe2921928279aab3ec9ba9a072c2c68adc72f0c2946fd4f5adb4c722a2f0e55676f1c79cbdc1d8afd19cf86156b5f7f8d012cd8245fb03fe30c62ea63110a722782367983030afadd16391b345f00d9c6d9750ae4b7099d5fcb66b944a213cf4881fa0f806e293554e869205e3e8e9abe67d0749d8c72fb882d3f3d1512f3077845787050527bde82da3cfc8ae9d0ab7827281a14f2bf6131cb79d27f4c781d0e8e42da9fdecb5be1979c9ccde17f1cc5b94f2f8e0a93d3e085ec72e221ca7d6bdad712a2c649b7bfdd0ad02306dd49cbdc298d4b23e73db05aa6a8b1514396e3032fe512d8cf58c5b61a546e1de56d98ad98c6d6a81db9865566a7cad4d533cb1d7770f2807819bb436e89045f8ac363aa6af27b5b7488d2303b10ba6e80e61ec0b8ae5850c96edeaf97ed2ebe64f77df8708c31bc6f6d4598dfc7c7ddb12b16b85adac7d8f1c2d961983ca2db804e3062c8e94d37c97181abfa111529adf15ed04dc403e9758d545cee70e868c222ed724d0f9483d7d2c5c44ad28662382ec40b7949ce08a6acb69d05a90d52ce487ce8fb6b5e5b91a2187d021ece47700f2f8eb5d2eb8e86000f14b978a051009c54ab1f1b90daa1d0d6711249d766d91a5f8c8604568bfc2f52822c52d625f451c194a5cfa4151b4fda81873e5f444144344eb75410033e2ba3d77850cae4b34495943a3880e273bb8842295ad853d1c7055a290e5ca084ba993c18810a85392ba042b7efe1e002c923723a43cc7b2dedca6123beebc4968ce42bb10d19111b3f77f519c19e9fc8111616dfd53b01eee401af9530568ffe98164e2d2e220a66422efb00bc90b07e48804c67db44f79e0595ad4a31e9b760c01e9fc239fabf55837316d7a13fd069f86563936e7b61ccb7d0dee4bd93e6b129c7da92a4516b7fa263cb6bf5940228312973b442f305dcfc40f843be2da8d693450f9ecf339bc9419f543a2fa0d4dc7793aced11d8e50d68003c2bd0212a7af1a5cfd7e8e54f14d8c627b3cd9558fbab33bf6209e485e59a9c9feecc54caa2dfece838b97b313c169cf27404cfc6dc5174856300208e10244183b2fcd28d34d67228eb9611b8f739a112178dc143fda2b8e64417e0f4c18f875eff34ec80a0fe04b5016473385a3e9c7b863b49ca05ebc3a34724a99488eba3dd49608da335a2acda60a91f3b8fb04ca30de481c0e1f17af2f13227b183345250b523257e08b58e15eb7b22a82ce581e63310a35cffb159ec276ecf3fac1ccefc23389de6c29b7e4454987611b315fb7684c72376ba448161cd82bc6a924095097c897b414750df37d34bbd2844979fbbdf68110afc3e14cce7cf963c375c92dcf65e4d633093bb8094052f8e9e6c4f3f650e9082f7346867794474a89f74e543714a5ad03ba003ffc1c716d56fb6078798e68ad4072d7db5099d0eb2c7ffdf21bcb4308965c13e0e1bd36bfab7c4267fa0c02ac393e70883b734027b9b087dabcd2c9bb65d9f769eae934c2b0415b2a5f2d7933e259ba51b2bd82fc08aa496e5fd3c4c0668e432dda489b4b9626006a2a958c0758624544279336421e92c477b09b968137686b68c5fbee84629b2c6b5506ad42198eefe6dfed5273fd74387faec972120aeaf85bec1491293362ebb2bda24eb7b3632c0950cf16f793fb333ca0025f57ce51b141cdc34456bfce530b417b00b574cbd4d13be8ef48fd3326948f7adc5b1f0398fcf0281e040407b3f9b7f79e4f1e89fb5eca34c9b387b0db3a5e98e253b999cd4c1616fd7e3fd26aa896c2118fe1e92499ddf5ff1125377a59987e84e03181262f7ad843b61b6450d92372cbcac16ba5b9b8d8deee7781f841672d91f336ce220fbfff7e32d61c98f5249e67bfef35edc3d9c3630b4f956c44c4a3e93f851c7775b64d759f2632b5ee38f0f3fff016a1fd3999b50c4f1de82cec0f11c34e494d51ad34df7bd812899daec5dfbd1b8405baf261e1da7898ba1dc1ced8afa4c23d662859d8a68205b62b6f908e2411d3a125e71442f74fc08b02e65195a63f198e1cb6c408e6a1b157d2a4b85a792cac2a07ddaea79c5858ce0ebdcdeab199483e2367f9b4785344447dca9251eb3df906cf4934228c4c028495f00e130722e175243791680bf540ca60e4c17c910637f6db35c1670d5c6d7e8264fa97fa540c870c87d1aa441599ee6fe6c22eabf8fc49c824b3bfac6491a2349ea33c4cb6cb19c0facb7d0cdb62db2ba56a5c337f9fe7b4ab5936275f98fe487b6c4805be709f67456caebd3043737a5974b0ca932b19c435bed01010c4617d350d803ff22dbbb3442189d9f81a0e5b47edfa4ea0a832fb14d27b19be226b42910ed10ac2d404abd96262bde3c391b238fa9bcfd3734275dacfc411811e01b1178750c745fe9462740c3f91f130535a7feb6be25b34a3314666ebaef01f5ec8b656add9b87e59c5bae71153e91be21505f27246035ec6c2569d7f165723a169cda18aaadb1481d84976da019a149b02f5b1f9b8c090a8115ecb3be65423aa1461e35c804a411b1cb191a8734233ca7a42acaee8eb4f451aa3089b9542a3c65e92a3a74b14443d1a8d72846fa7846098ec3233d2553ed4ab542c8c425cbabb94bb2fdb5223acb999ba31a19a0ff9b646fc4297832d36722e0af0c03899c8ce17c79303b091512f0106b4285e6e8faf09325f0bc3d8d724575c9556931a4dc34c93d81a79f25199ed712a97309630b5635ae067edd4e17be9d4e194905f8d3c7c6ad93bd219beac7c389f62f8adec30a72bcbc15e8586b9e2b057140eb95fadd960389230edb3925dd9a7deb86f72502ffcebbe9a65a99e6cecf61823f9cd326f298b9430a0f476e57093895e26b0375c327b29c3e37f14474af815dd90cfbc8e61fc2f0b528b3db0e5a5407db99c3c5c2862e3b68084305e93c79f1b962a6a5d28c76969e1d5d1e82ad831ee1b6238208890db7006b395771e34c1a0d25ebf651273ba3d495417033163b46f6a176b79c446c92ebbed4bc84f0e1effc0b38d3e269cd39f392472f1634acd1bd178a8ea5a54e045c45e19d54bc286e9fb0e324c30e00593529aa28f7b66288144ba6db9ff9f368565944bf776e93e27741fd7ded89144bad8a3c1287498973d7cd8d883fe3012db6af76e9ee1dfc189e1e7f97f1e23b288c5776de731b286a80fa349b09db359a5cfafc83c46de3b43cfe9e96270e18749a3af460d1312c4eb058935f13eaa29e8836877a88734356a816b319178776310086551003227f0b191aa6058cf8209de79cf106d57c4b769f142054ccc16b0348bf620f1a28dca8ff02e11fdae7cd155383b59e4acdfc53795786b759b5a03abb1b25adccf711e30ce1b783dbf75421d6ca5e146c6deca0da3078575c936063131c14f57ec4eef5fa5047f3e3be6fe2d3940878f905ee5c7e46cfa43575b64b6a5f71eb715e2cf1aa514df138234317b401d57f1a61ff08a0eedaa6b4370e61003532fffabfbe368eb465230b7f25c80bf73ae239b9deb8ce54b64bfc06820c01507aa2d9a8a6a9f5ed2d8912b4e1b43192baee1e10df1c15c88f7fb4381cac124848b55549239e2f1acc7a4352c4aeb56307d670ea52217b272345effaba37c04dccf9f4d8a9c89e2d51ee3cfd8a53e369256800af40e230d2c554114e99db275e8f8dc34ad6f2ecca886e018bce9822041a9196d4efe9ec952ae2ff4fc8256084923075295a82034909942c87b64e5bb941eae7de6cba2540c594b3f1f4a24d6fc25d1182a88b9e6dc4616a3a76d03523e8c34c71684d8c5e5be134402df6153e9230f6e013ec6131e5af35a4b8c5aa227b2452cc8232bbc904d4b822eeddf96c89b16af80856afe9d5a66f914b81b2d52efc451e6f3d92cfba8070a9b3957e74db749c1b94dc5acd950b6a553909229fd916a1cfd56701f57a0971224070eb24d3718a665dda9b4ca9171ffbdfea55ef194f91ecc61d04cf5068cb3b7e481073b9396e8ec349e5257db91f0f00d9df9d3b465ca93c15c9efefb9aed057343eb169b206aa0db60db319801899a2b6527e1f97263444599b555dab700dffc302d6767385f982c78b4932ca12a16d575752b915b034dd69f3473c52097fc6078dd7ef6462b820bee65980510367235191d900033f13b7e2bd43cd423fbed47aa54377f67be5583c1c385c659449bf202032502d2db40101cdb5543ddfcea652c5b3c711d932c2c22ec67256b194e5bcab3ae054d02b22e7193c7c32aa3a958822cd5917117f53569ad42a5b30a64781355d22ff3bb70b76430b7e8e538df4c5411a09e6fecc4086d86aebfe497315056d11660165b47383302d6461a7f0f2d0c6e894c33c71c1c4eaa715d55ec369bbf7d86623a7b2b76bed3b1356ed80f8a1ee77229ab6cddd96eaa724fa740b480ae6fb1768c67adc5ce85dcf0f46026fdcdb4f346c60c2478f6da4b33fc06a0645fb5629b80e96d6f78aa4ae1c5cefefb24912de843f509e9609fc969be9a66c28d5608d6bcdc6bc0e6ca5752142e196679935fc745f1a84fed03d47276e29ffefa61b4232b737583c1c2e93752a7acbac2f747698b9b023a4000122a706c758fd300000000000000000000000000000000000000000000000000080f13161a1e").unwrap();
1402
1403 let key = PKey::private_key_from_seed(None, KeyType::ML_DSA_65, None, &xi).unwrap();
1404
1405 let mut md_ctx = MdCtx::new().unwrap();
1407 let pkey_ctx = md_ctx.digest_verify_init(None, &key).unwrap();
1408 pkey_ctx.set_context_string(&ctx).unwrap();
1409 assert!(md_ctx.digest_verify(&msg, &expected_sig).unwrap());
1410
1411 let mut md_ctx = MdCtx::new().unwrap();
1413 let pkey_ctx = md_ctx.digest_sign_init(None, &key).unwrap();
1414 pkey_ctx.set_context_string(&ctx).unwrap();
1415 let mut sig = vec![];
1416 md_ctx.digest_sign_to_vec(&msg, &mut sig).unwrap();
1417
1418 let mut md_ctx = MdCtx::new().unwrap();
1419 let pkey_ctx = md_ctx.digest_verify_init(None, &key).unwrap();
1420 pkey_ctx.set_context_string(&ctx).unwrap();
1421 assert!(md_ctx.digest_verify(&msg, &sig).unwrap());
1422
1423 assert!(ErrorStack::get().errors().is_empty());
1424 }
1425}