1use crate::bio::{MemBio, MemBioBuf};
14use crate::error::ErrorStack;
15use native_ossl_sys as sys;
16use std::marker::PhantomData;
17use std::sync::Arc;
18
19pub struct Public;
23pub struct Private;
25pub struct Params;
27
28mod sealed {
29 pub trait HasParams {}
31 impl HasParams for super::Public {}
32 impl HasParams for super::Private {}
33 impl HasParams for super::Params {}
34
35 pub trait HasPublic: HasParams {}
37 impl HasPublic for super::Public {}
38 impl HasPublic for super::Private {}
39
40 pub trait HasPrivate: HasPublic {}
42 impl HasPrivate for super::Private {}
43}
44
45pub trait HasParams: sealed::HasParams {}
47impl<T: sealed::HasParams> HasParams for T {}
48
49pub trait HasPublic: sealed::HasPublic {}
51impl<T: sealed::HasPublic> HasPublic for T {}
52
53pub trait HasPrivate: sealed::HasPrivate {}
55impl<T: sealed::HasPrivate> HasPrivate for T {}
56
57pub struct Pkey<T> {
63 ptr: *mut sys::EVP_PKEY,
64 _role: PhantomData<T>,
65}
66
67unsafe impl<T> Send for Pkey<T> {}
69unsafe impl<T> Sync for Pkey<T> {}
70
71impl<T> Clone for Pkey<T> {
72 fn clone(&self) -> Self {
73 unsafe { sys::EVP_PKEY_up_ref(self.ptr) };
74 Pkey {
75 ptr: self.ptr,
76 _role: PhantomData,
77 }
78 }
79}
80
81impl<T> Drop for Pkey<T> {
82 fn drop(&mut self) {
83 unsafe { sys::EVP_PKEY_free(self.ptr) };
84 }
85}
86
87impl<T: HasParams> Pkey<T> {
88 #[must_use]
94 pub unsafe fn from_ptr(ptr: *mut sys::EVP_PKEY) -> Self {
95 Pkey {
96 ptr,
97 _role: PhantomData,
98 }
99 }
100
101 #[must_use]
103 pub fn as_ptr(&self) -> *mut sys::EVP_PKEY {
104 self.ptr
105 }
106
107 #[must_use]
109 pub fn bits(&self) -> u32 {
110 u32::try_from(unsafe { sys::EVP_PKEY_get_bits(self.ptr) }).unwrap_or(0)
111 }
112
113 #[must_use]
115 pub fn security_bits(&self) -> u32 {
116 u32::try_from(unsafe { sys::EVP_PKEY_get_security_bits(self.ptr) }).unwrap_or(0)
117 }
118
119 #[must_use]
121 pub fn is_a(&self, name: &std::ffi::CStr) -> bool {
122 unsafe { sys::EVP_PKEY_is_a(self.ptr, name.as_ptr()) == 1 }
123 }
124
125 #[must_use]
130 pub fn public_eq<U: HasPublic>(&self, other: &Pkey<U>) -> bool
131 where
132 T: HasPublic,
133 {
134 unsafe { sys::EVP_PKEY_eq(self.ptr, other.ptr) == 1 }
135 }
136
137 pub fn get_params(&self, params: &mut crate::params::Params<'_>) -> Result<(), ErrorStack> {
144 crate::ossl_call!(sys::EVP_PKEY_get_params(self.ptr, params.as_mut_ptr()))
145 }
146
147 pub fn public_key_to_der(&self) -> Result<Vec<u8>, ErrorStack>
156 where
157 T: HasPublic,
158 {
159 let len = unsafe { sys::i2d_PUBKEY(self.ptr, std::ptr::null_mut()) };
161 if len < 0 {
162 return Err(ErrorStack::drain());
163 }
164 let mut buf = vec![0u8; usize::try_from(len).unwrap_or(0)];
167 let mut out_ptr = buf.as_mut_ptr();
168 let written = unsafe { sys::i2d_PUBKEY(self.ptr, std::ptr::addr_of_mut!(out_ptr)) };
169 if written < 0 {
170 return Err(ErrorStack::drain());
171 }
172 buf.truncate(usize::try_from(written).unwrap_or(0));
173 Ok(buf)
174 }
175}
176
177impl Pkey<Private> {
180 #[cfg(feature = "fips-provider")]
197 pub unsafe fn keydata(&self) -> *mut std::ffi::c_void {
198 self.ptr
202 .cast::<u8>()
203 .add(native_ossl_sys::fips_internal::EVP_PKEY_KEYDATA_OFFSET)
204 .cast::<*mut std::ffi::c_void>()
205 .read()
206 }
207
208 pub fn from_pem(pem: &[u8]) -> Result<Self, ErrorStack> {
214 let bio = MemBioBuf::new(pem)?;
215 let ptr = unsafe {
216 sys::PEM_read_bio_PrivateKey(
217 bio.as_ptr(),
218 std::ptr::null_mut(),
219 None,
220 std::ptr::null_mut(),
221 )
222 };
223 if ptr.is_null() {
224 return Err(ErrorStack::drain());
225 }
226 Ok(unsafe { Pkey::from_ptr(ptr) })
227 }
228
229 pub fn to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
233 let mut bio = MemBio::new()?;
234 let rc = unsafe {
235 sys::PEM_write_bio_PrivateKey(
236 bio.as_ptr(),
237 self.ptr,
238 std::ptr::null(),
239 std::ptr::null_mut(),
240 0,
241 None,
242 std::ptr::null_mut(),
243 )
244 };
245 if rc != 1 {
246 return Err(ErrorStack::drain());
247 }
248 Ok(bio.into_vec())
249 }
250
251 pub fn from_pem_in(ctx: &Arc<crate::lib_ctx::LibCtx>, pem: &[u8]) -> Result<Self, ErrorStack> {
259 let bio = MemBioBuf::new(pem)?;
260 let ptr = unsafe {
261 sys::PEM_read_bio_PrivateKey_ex(
262 bio.as_ptr(),
263 std::ptr::null_mut(),
264 None,
265 std::ptr::null_mut(),
266 ctx.as_ptr(),
267 std::ptr::null(),
268 )
269 };
270 if ptr.is_null() {
271 return Err(ErrorStack::drain());
272 }
273 Ok(unsafe { Pkey::from_ptr(ptr) })
274 }
275
276 pub fn from_der(der: &[u8]) -> Result<Self, ErrorStack> {
282 let bio = MemBioBuf::new(der)?;
283 let ptr = unsafe { sys::d2i_PrivateKey_bio(bio.as_ptr(), std::ptr::null_mut()) };
284 if ptr.is_null() {
285 return Err(ErrorStack::drain());
286 }
287 Ok(unsafe { Pkey::from_ptr(ptr) })
288 }
289
290 pub fn from_pem_passphrase(pem: &[u8], passphrase: &[u8]) -> Result<Self, ErrorStack> {
298 extern "C" fn passwd_cb(
299 buf: *mut std::ffi::c_char,
300 size: std::ffi::c_int,
301 _rwflag: std::ffi::c_int,
302 u: *mut std::ffi::c_void,
303 ) -> std::ffi::c_int {
304 let pw: &[u8] = unsafe { *(u as *const &[u8]) };
306 let max_len = usize::try_from(size).unwrap_or(0);
308 let n = pw.len().min(max_len);
309 unsafe { std::ptr::copy_nonoverlapping(pw.as_ptr(), buf.cast::<u8>(), n) };
310 i32::try_from(n).unwrap()
312 }
313 let bio = MemBioBuf::new(pem)?;
314 let pw: &[u8] = passphrase;
315 let ptr = unsafe {
316 sys::PEM_read_bio_PrivateKey(
317 bio.as_ptr(),
318 std::ptr::null_mut(),
319 Some(passwd_cb),
320 std::ptr::addr_of!(pw).cast::<std::ffi::c_void>().cast_mut(),
321 )
322 };
323 if ptr.is_null() {
324 return Err(ErrorStack::drain());
325 }
326 Ok(unsafe { Pkey::from_ptr(ptr) })
327 }
328
329 pub fn to_pem_encrypted(
342 &self,
343 cipher: &crate::cipher::CipherAlg,
344 passphrase: &[u8],
345 ) -> Result<Vec<u8>, ErrorStack> {
346 let mut bio = MemBio::new()?;
347 let rc = unsafe {
348 sys::PEM_write_bio_PKCS8PrivateKey(
349 bio.as_ptr(),
350 self.ptr,
351 cipher.as_ptr(),
352 passphrase.as_ptr().cast(),
353 i32::try_from(passphrase.len()).expect("passphrase too long"),
354 None,
355 std::ptr::null_mut(),
356 )
357 };
358 if rc != 1 {
359 return Err(ErrorStack::drain());
360 }
361 Ok(bio.into_vec())
362 }
363
364 pub fn to_pkcs8_der(&self) -> Result<Vec<u8>, ErrorStack> {
373 let mut bio = MemBio::new()?;
374 let rc = unsafe { sys::i2d_PKCS8PrivateKeyInfo_bio(bio.as_ptr(), self.ptr) };
375 if rc != 1 {
376 return Err(ErrorStack::drain());
377 }
378 Ok(bio.into_vec())
379 }
380}
381
382impl Pkey<Public> {
385 pub fn from_pem(pem: &[u8]) -> Result<Self, ErrorStack> {
389 let bio = MemBioBuf::new(pem)?;
390 let ptr = unsafe {
391 sys::PEM_read_bio_PUBKEY(
392 bio.as_ptr(),
393 std::ptr::null_mut(),
394 None,
395 std::ptr::null_mut(),
396 )
397 };
398 if ptr.is_null() {
399 return Err(ErrorStack::drain());
400 }
401 Ok(unsafe { Pkey::from_ptr(ptr) })
402 }
403
404 pub fn from_pem_in(ctx: &Arc<crate::lib_ctx::LibCtx>, pem: &[u8]) -> Result<Self, ErrorStack> {
412 let bio = MemBioBuf::new(pem)?;
413 let ptr = unsafe {
414 sys::PEM_read_bio_PUBKEY_ex(
415 bio.as_ptr(),
416 std::ptr::null_mut(),
417 None,
418 std::ptr::null_mut(),
419 ctx.as_ptr(),
420 std::ptr::null(),
421 )
422 };
423 if ptr.is_null() {
424 return Err(ErrorStack::drain());
425 }
426 Ok(unsafe { Pkey::from_ptr(ptr) })
427 }
428
429 pub fn from_der(der: &[u8]) -> Result<Self, ErrorStack> {
433 let bio = MemBioBuf::new(der)?;
434 let ptr = unsafe { sys::d2i_PUBKEY_bio(bio.as_ptr(), std::ptr::null_mut()) };
435 if ptr.is_null() {
436 return Err(ErrorStack::drain());
437 }
438 Ok(unsafe { Pkey::from_ptr(ptr) })
439 }
440
441 pub fn to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
445 let mut bio = MemBio::new()?;
446 let rc = unsafe { sys::PEM_write_bio_PUBKEY(bio.as_ptr(), self.ptr) };
447 if rc != 1 {
448 return Err(ErrorStack::drain());
449 }
450 Ok(bio.into_vec())
451 }
452}
453
454impl From<Pkey<Private>> for Pkey<Public> {
456 fn from(k: Pkey<Private>) -> Self {
457 unsafe { sys::EVP_PKEY_up_ref(k.ptr) };
458 Pkey {
459 ptr: k.ptr,
460 _role: PhantomData,
461 }
462 }
463}
464
465const PKEY_PUBLIC_KEY: i32 = 0x86;
476const PKEY_KEYPAIR: i32 = 0x87;
477
478fn pkey_fromdata(
480 ctx: Option<&Arc<crate::lib_ctx::LibCtx>>,
481 pkey_type: &std::ffi::CStr,
482 params: &crate::params::Params<'_>,
483 selection: i32,
484) -> Result<*mut sys::EVP_PKEY, ErrorStack> {
485 let libctx = ctx.map_or(std::ptr::null_mut(), |c| c.as_ptr());
486 let pctx =
487 unsafe { sys::EVP_PKEY_CTX_new_from_name(libctx, pkey_type.as_ptr(), std::ptr::null()) };
488 if pctx.is_null() {
489 return Err(ErrorStack::drain());
490 }
491 let rc = unsafe { sys::EVP_PKEY_fromdata_init(pctx) };
492 if rc != 1 {
493 unsafe { sys::EVP_PKEY_CTX_free(pctx) };
494 return Err(ErrorStack::drain());
495 }
496 let mut pkey: *mut sys::EVP_PKEY = std::ptr::null_mut();
497 let rc = unsafe {
498 sys::EVP_PKEY_fromdata(
499 pctx,
500 std::ptr::addr_of_mut!(pkey),
501 selection,
502 params.as_ptr().cast_mut(),
504 )
505 };
506 unsafe { sys::EVP_PKEY_CTX_free(pctx) };
507 if rc != 1 || pkey.is_null() {
508 return Err(ErrorStack::drain());
509 }
510 Ok(pkey)
511}
512
513fn pkey_todata(
515 ptr: *mut sys::EVP_PKEY,
516 selection: i32,
517) -> Result<crate::params::Params<'static>, ErrorStack> {
518 let mut out: *mut sys::OSSL_PARAM = std::ptr::null_mut();
519 let rc = unsafe { sys::EVP_PKEY_todata(ptr, selection, std::ptr::addr_of_mut!(out)) };
520 if rc != 1 || out.is_null() {
521 return Err(ErrorStack::drain());
522 }
523 Ok(unsafe { crate::params::Params::from_owned_ptr(out) })
526}
527
528impl Pkey<Private> {
529 pub fn from_params(
536 ctx: Option<&Arc<crate::lib_ctx::LibCtx>>,
537 pkey_type: &std::ffi::CStr,
538 params: &crate::params::Params<'_>,
539 ) -> Result<Self, ErrorStack> {
540 pkey_fromdata(ctx, pkey_type, params, PKEY_KEYPAIR)
541 .map(|ptr| unsafe { Pkey::from_ptr(ptr) })
542 }
543
544 pub fn export(&self) -> Result<crate::params::Params<'static>, ErrorStack> {
551 pkey_todata(self.ptr, PKEY_KEYPAIR)
552 }
553}
554
555impl Pkey<Public> {
556 pub fn from_params(
563 ctx: Option<&Arc<crate::lib_ctx::LibCtx>>,
564 pkey_type: &std::ffi::CStr,
565 params: &crate::params::Params<'_>,
566 ) -> Result<Self, ErrorStack> {
567 pkey_fromdata(ctx, pkey_type, params, PKEY_PUBLIC_KEY)
568 .map(|ptr| unsafe { Pkey::from_ptr(ptr) })
569 }
570
571 pub fn export(&self) -> Result<crate::params::Params<'static>, ErrorStack> {
577 pkey_todata(self.ptr, PKEY_PUBLIC_KEY)
578 }
579}
580
581pub struct KeygenCtx {
585 ptr: *mut sys::EVP_PKEY_CTX,
586}
587
588impl KeygenCtx {
589 pub fn new(name: &std::ffi::CStr) -> Result<Self, ErrorStack> {
595 let ptr = unsafe {
596 sys::EVP_PKEY_CTX_new_from_name(std::ptr::null_mut(), name.as_ptr(), std::ptr::null())
597 };
598 if ptr.is_null() {
599 return Err(ErrorStack::drain());
600 }
601 let rc = unsafe { sys::EVP_PKEY_keygen_init(ptr) };
602 if rc != 1 {
603 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
604 return Err(ErrorStack::drain());
605 }
606 Ok(KeygenCtx { ptr })
607 }
608
609 pub fn set_params(&mut self, params: &crate::params::Params<'_>) -> Result<(), ErrorStack> {
613 crate::ossl_call!(sys::EVP_PKEY_CTX_set_params(self.ptr, params.as_ptr()))
614 }
615
616 pub fn generate(&mut self) -> Result<Pkey<Private>, ErrorStack> {
620 let mut key: *mut sys::EVP_PKEY = std::ptr::null_mut();
621 crate::ossl_call!(sys::EVP_PKEY_keygen(self.ptr, std::ptr::addr_of_mut!(key)))?;
622 if key.is_null() {
623 return Err(ErrorStack::drain());
624 }
625 Ok(unsafe { Pkey::from_ptr(key) })
626 }
627}
628
629impl Drop for KeygenCtx {
630 fn drop(&mut self) {
631 unsafe { sys::EVP_PKEY_CTX_free(self.ptr) };
632 }
633}
634
635#[derive(Default)]
639pub struct SignInit<'a> {
640 pub digest: Option<&'a crate::digest::DigestAlg>,
642 pub params: Option<&'a crate::params::Params<'a>>,
644}
645
646pub struct Signer {
650 ctx: crate::digest::DigestCtx,
651 _key: Pkey<Private>,
653}
654
655impl Signer {
656 pub fn new(key: &Pkey<Private>, init: &SignInit<'_>) -> Result<Self, ErrorStack> {
660 let ctx = alloc_digest_ctx()?;
661 let md_name_ptr = if let Some(d) = init.digest {
663 let p = unsafe { sys::OBJ_nid2sn(d.nid()) };
664 if p.is_null() {
665 return Err(ErrorStack::drain());
666 }
667 p
668 } else {
669 std::ptr::null()
670 };
671 let params_ptr = init
672 .params
673 .map_or(crate::params::null_params(), crate::params::Params::as_ptr);
674 let rc = unsafe {
675 sys::EVP_DigestSignInit_ex(
676 ctx.as_ptr(),
677 std::ptr::null_mut(),
678 md_name_ptr,
679 std::ptr::null_mut(),
680 std::ptr::null(),
681 key.ptr,
682 params_ptr,
683 )
684 };
685 if rc != 1 {
686 return Err(ErrorStack::drain());
687 }
688 Ok(Signer {
689 ctx,
690 _key: key.clone(),
691 })
692 }
693
694 pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
698 crate::ossl_call!(sys::EVP_DigestSignUpdate(
699 self.ctx.as_ptr(),
700 data.as_ptr().cast(),
701 data.len()
702 ))
703 }
704
705 pub fn finish(&mut self) -> Result<Vec<u8>, ErrorStack> {
712 let mut siglen: usize = 0;
714 let rc = unsafe {
715 sys::EVP_DigestSignFinal(
716 self.ctx.as_ptr(),
717 std::ptr::null_mut(),
718 std::ptr::addr_of_mut!(siglen),
719 )
720 };
721 if rc != 1 {
722 return Err(ErrorStack::drain());
723 }
724 let mut sig = vec![0u8; siglen];
725 let rc = unsafe {
726 sys::EVP_DigestSignFinal(
727 self.ctx.as_ptr(),
728 sig.as_mut_ptr(),
729 std::ptr::addr_of_mut!(siglen),
730 )
731 };
732 if rc != 1 {
733 return Err(ErrorStack::drain());
734 }
735 sig.truncate(siglen);
736 Ok(sig)
737 }
738
739 pub fn sign_oneshot(&mut self, data: &[u8]) -> Result<Vec<u8>, ErrorStack> {
746 let mut siglen: usize = 0;
748 let rc = unsafe {
749 sys::EVP_DigestSign(
750 self.ctx.as_ptr(),
751 std::ptr::null_mut(),
752 std::ptr::addr_of_mut!(siglen),
753 data.as_ptr(),
754 data.len(),
755 )
756 };
757 if rc != 1 {
758 return Err(ErrorStack::drain());
759 }
760 let mut sig = vec![0u8; siglen];
761 let rc = unsafe {
762 sys::EVP_DigestSign(
763 self.ctx.as_ptr(),
764 sig.as_mut_ptr(),
765 std::ptr::addr_of_mut!(siglen),
766 data.as_ptr(),
767 data.len(),
768 )
769 };
770 if rc != 1 {
771 return Err(ErrorStack::drain());
772 }
773 sig.truncate(siglen);
774 Ok(sig)
775 }
776}
777
778pub struct Verifier {
782 ctx: crate::digest::DigestCtx,
783 _key: Pkey<Public>,
784}
785
786impl Verifier {
787 pub fn new(key: &Pkey<Public>, init: &SignInit<'_>) -> Result<Self, ErrorStack> {
791 let ctx = alloc_digest_ctx()?;
792 let md_name_ptr = if let Some(d) = init.digest {
794 let p = unsafe { sys::OBJ_nid2sn(d.nid()) };
795 if p.is_null() {
796 return Err(ErrorStack::drain());
797 }
798 p
799 } else {
800 std::ptr::null()
801 };
802 let params_ptr = init
803 .params
804 .map_or(crate::params::null_params(), crate::params::Params::as_ptr);
805 let rc = unsafe {
806 sys::EVP_DigestVerifyInit_ex(
807 ctx.as_ptr(),
808 std::ptr::null_mut(),
809 md_name_ptr,
810 std::ptr::null_mut(),
811 std::ptr::null(),
812 key.ptr,
813 params_ptr,
814 )
815 };
816 if rc != 1 {
817 return Err(ErrorStack::drain());
818 }
819 Ok(Verifier {
820 ctx,
821 _key: key.clone(),
822 })
823 }
824
825 pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
829 crate::ossl_call!(sys::EVP_DigestVerifyUpdate(
830 self.ctx.as_ptr(),
831 data.as_ptr().cast(),
832 data.len()
833 ))
834 }
835
836 pub fn verify(&mut self, signature: &[u8]) -> Result<bool, ErrorStack> {
846 let rc = unsafe {
847 sys::EVP_DigestVerifyFinal(self.ctx.as_ptr(), signature.as_ptr(), signature.len())
848 };
849 match rc {
850 1 => Ok(true),
851 0 => Ok(false),
852 _ => Err(ErrorStack::drain()),
853 }
854 }
855
856 pub fn verify_oneshot(&mut self, data: &[u8], signature: &[u8]) -> Result<bool, ErrorStack> {
862 let rc = unsafe {
863 sys::EVP_DigestVerify(
864 self.ctx.as_ptr(),
865 signature.as_ptr(),
866 signature.len(),
867 data.as_ptr(),
868 data.len(),
869 )
870 };
871 match rc {
872 1 => Ok(true),
873 0 => Ok(false),
874 _ => Err(ErrorStack::drain()),
875 }
876 }
877}
878
879fn alloc_digest_ctx() -> Result<crate::digest::DigestCtx, ErrorStack> {
884 let ctx_ptr = unsafe { sys::EVP_MD_CTX_new() };
885 if ctx_ptr.is_null() {
886 return Err(ErrorStack::drain());
887 }
888 Ok(unsafe { crate::digest::DigestCtx::from_ptr(ctx_ptr) })
890}
891
892pub struct DeriveCtx {
896 ptr: *mut sys::EVP_PKEY_CTX,
897}
898
899impl DeriveCtx {
900 pub fn new(key: &Pkey<Private>) -> Result<Self, ErrorStack> {
904 let ptr = unsafe {
905 sys::EVP_PKEY_CTX_new_from_pkey(std::ptr::null_mut(), key.ptr, std::ptr::null())
906 };
907 if ptr.is_null() {
908 return Err(ErrorStack::drain());
909 }
910 crate::ossl_call!(sys::EVP_PKEY_derive_init(ptr)).map_err(|e| {
911 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
912 e
913 })?;
914 Ok(DeriveCtx { ptr })
915 }
916
917 pub fn set_peer(&mut self, peer: &Pkey<Public>) -> Result<(), ErrorStack> {
921 crate::ossl_call!(sys::EVP_PKEY_derive_set_peer(self.ptr, peer.ptr))
922 }
923
924 pub fn derive(&mut self, out: &mut [u8]) -> Result<usize, ErrorStack> {
930 let mut len = out.len();
931 crate::ossl_call!(sys::EVP_PKEY_derive(
932 self.ptr,
933 out.as_mut_ptr(),
934 std::ptr::addr_of_mut!(len)
935 ))?;
936 Ok(len)
937 }
938
939 pub fn derive_len(&mut self) -> Result<usize, ErrorStack> {
943 let mut len: usize = 0;
944 crate::ossl_call!(sys::EVP_PKEY_derive(
945 self.ptr,
946 std::ptr::null_mut(),
947 std::ptr::addr_of_mut!(len)
948 ))?;
949 Ok(len)
950 }
951}
952
953impl Drop for DeriveCtx {
954 fn drop(&mut self) {
955 unsafe { sys::EVP_PKEY_CTX_free(self.ptr) };
956 }
957}
958
959pub struct PkeyEncryptCtx {
963 ptr: *mut sys::EVP_PKEY_CTX,
964}
965
966impl PkeyEncryptCtx {
967 pub fn new(
977 key: &Pkey<Public>,
978 params: Option<&crate::params::Params<'_>>,
979 ) -> Result<Self, ErrorStack> {
980 let ptr = unsafe {
981 sys::EVP_PKEY_CTX_new_from_pkey(std::ptr::null_mut(), key.ptr, std::ptr::null())
982 };
983 if ptr.is_null() {
984 return Err(ErrorStack::drain());
985 }
986 crate::ossl_call!(sys::EVP_PKEY_encrypt_init(ptr)).map_err(|e| {
987 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
988 e
989 })?;
990 let ctx = PkeyEncryptCtx { ptr };
991 if let Some(p) = params {
992 crate::ossl_call!(sys::EVP_PKEY_CTX_set_params(ctx.ptr, p.as_ptr())).map_err(|e| {
993 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
994 e
995 })?;
996 }
997 Ok(ctx)
998 }
999
1000 pub fn set_params(&mut self, params: &crate::params::Params<'_>) -> Result<(), ErrorStack> {
1004 crate::ossl_call!(sys::EVP_PKEY_CTX_set_params(self.ptr, params.as_ptr()))
1005 }
1006
1007 pub fn encrypt(
1013 &mut self,
1014 plaintext: &[u8],
1015 ciphertext: &mut [u8],
1016 ) -> Result<usize, ErrorStack> {
1017 let mut outlen = ciphertext.len();
1018 crate::ossl_call!(sys::EVP_PKEY_encrypt(
1019 self.ptr,
1020 ciphertext.as_mut_ptr(),
1021 std::ptr::addr_of_mut!(outlen),
1022 plaintext.as_ptr(),
1023 plaintext.len()
1024 ))?;
1025 Ok(outlen)
1026 }
1027
1028 pub fn encrypt_len(&mut self, plaintext_len: usize) -> Result<usize, ErrorStack> {
1032 let mut outlen: usize = 0;
1033 crate::ossl_call!(sys::EVP_PKEY_encrypt(
1034 self.ptr,
1035 std::ptr::null_mut(),
1036 std::ptr::addr_of_mut!(outlen),
1037 std::ptr::null(),
1038 plaintext_len
1039 ))?;
1040 Ok(outlen)
1041 }
1042}
1043
1044impl Drop for PkeyEncryptCtx {
1045 fn drop(&mut self) {
1046 unsafe { sys::EVP_PKEY_CTX_free(self.ptr) };
1047 }
1048}
1049
1050pub struct PkeyDecryptCtx {
1052 ptr: *mut sys::EVP_PKEY_CTX,
1053}
1054
1055impl PkeyDecryptCtx {
1056 pub fn new(
1062 key: &Pkey<Private>,
1063 params: Option<&crate::params::Params<'_>>,
1064 ) -> Result<Self, ErrorStack> {
1065 let ptr = unsafe {
1066 sys::EVP_PKEY_CTX_new_from_pkey(std::ptr::null_mut(), key.ptr, std::ptr::null())
1067 };
1068 if ptr.is_null() {
1069 return Err(ErrorStack::drain());
1070 }
1071 crate::ossl_call!(sys::EVP_PKEY_decrypt_init(ptr)).map_err(|e| {
1072 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
1073 e
1074 })?;
1075 let ctx = PkeyDecryptCtx { ptr };
1076 if let Some(p) = params {
1077 crate::ossl_call!(sys::EVP_PKEY_CTX_set_params(ctx.ptr, p.as_ptr())).map_err(|e| {
1078 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
1079 e
1080 })?;
1081 }
1082 Ok(ctx)
1083 }
1084
1085 pub fn set_params(&mut self, params: &crate::params::Params<'_>) -> Result<(), ErrorStack> {
1089 crate::ossl_call!(sys::EVP_PKEY_CTX_set_params(self.ptr, params.as_ptr()))
1090 }
1091
1092 pub fn decrypt(
1098 &mut self,
1099 ciphertext: &[u8],
1100 plaintext: &mut [u8],
1101 ) -> Result<usize, ErrorStack> {
1102 let mut outlen = plaintext.len();
1103 crate::ossl_call!(sys::EVP_PKEY_decrypt(
1104 self.ptr,
1105 plaintext.as_mut_ptr(),
1106 std::ptr::addr_of_mut!(outlen),
1107 ciphertext.as_ptr(),
1108 ciphertext.len()
1109 ))?;
1110 Ok(outlen)
1111 }
1112}
1113
1114impl Drop for PkeyDecryptCtx {
1115 fn drop(&mut self) {
1116 unsafe { sys::EVP_PKEY_CTX_free(self.ptr) };
1117 }
1118}
1119
1120#[cfg(ossl320)]
1124pub struct EncapResult {
1125 pub wrapped_key: Vec<u8>,
1127 pub shared_secret: Vec<u8>,
1129}
1130
1131#[cfg(ossl320)]
1133pub struct EncapCtx {
1134 ptr: *mut sys::EVP_PKEY_CTX,
1135}
1136
1137#[cfg(ossl320)]
1138impl EncapCtx {
1139 pub fn new(key: &Pkey<Public>) -> Result<Self, ErrorStack> {
1143 let ptr = unsafe {
1144 sys::EVP_PKEY_CTX_new_from_pkey(std::ptr::null_mut(), key.ptr, std::ptr::null())
1145 };
1146 if ptr.is_null() {
1147 return Err(ErrorStack::drain());
1148 }
1149 crate::ossl_call!(sys::EVP_PKEY_encapsulate_init(ptr, std::ptr::null())).map_err(|e| {
1150 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
1151 e
1152 })?;
1153 Ok(EncapCtx { ptr })
1154 }
1155
1156 pub fn encapsulate(&mut self) -> Result<EncapResult, ErrorStack> {
1160 let mut wkeylen: usize = 0;
1161 let mut sslen: usize = 0;
1162 let rc = unsafe {
1164 sys::EVP_PKEY_encapsulate(
1165 self.ptr,
1166 std::ptr::null_mut(),
1167 std::ptr::addr_of_mut!(wkeylen),
1168 std::ptr::null_mut(),
1169 std::ptr::addr_of_mut!(sslen),
1170 )
1171 };
1172 if rc != 1 {
1173 return Err(ErrorStack::drain());
1174 }
1175 let mut wrapped_key = vec![0u8; wkeylen];
1176 let mut shared_secret = vec![0u8; sslen];
1177 crate::ossl_call!(sys::EVP_PKEY_encapsulate(
1178 self.ptr,
1179 wrapped_key.as_mut_ptr(),
1180 std::ptr::addr_of_mut!(wkeylen),
1181 shared_secret.as_mut_ptr(),
1182 std::ptr::addr_of_mut!(sslen)
1183 ))?;
1184 wrapped_key.truncate(wkeylen);
1185 shared_secret.truncate(sslen);
1186 Ok(EncapResult {
1187 wrapped_key,
1188 shared_secret,
1189 })
1190 }
1191}
1192
1193#[cfg(ossl320)]
1194impl Drop for EncapCtx {
1195 fn drop(&mut self) {
1196 unsafe { sys::EVP_PKEY_CTX_free(self.ptr) };
1197 }
1198}
1199
1200#[cfg(ossl320)]
1202pub struct DecapCtx {
1203 ptr: *mut sys::EVP_PKEY_CTX,
1204}
1205
1206#[cfg(ossl320)]
1207impl DecapCtx {
1208 pub fn new(key: &Pkey<Private>) -> Result<Self, ErrorStack> {
1212 let ptr = unsafe {
1213 sys::EVP_PKEY_CTX_new_from_pkey(std::ptr::null_mut(), key.ptr, std::ptr::null())
1214 };
1215 if ptr.is_null() {
1216 return Err(ErrorStack::drain());
1217 }
1218 crate::ossl_call!(sys::EVP_PKEY_decapsulate_init(ptr, std::ptr::null())).map_err(|e| {
1219 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
1220 e
1221 })?;
1222 Ok(DecapCtx { ptr })
1223 }
1224
1225 pub fn decapsulate(&mut self, wrapped_key: &[u8]) -> Result<Vec<u8>, ErrorStack> {
1229 let mut sslen: usize = 0;
1230 let rc = unsafe {
1232 sys::EVP_PKEY_decapsulate(
1233 self.ptr,
1234 std::ptr::null_mut(),
1235 std::ptr::addr_of_mut!(sslen),
1236 wrapped_key.as_ptr(),
1237 wrapped_key.len(),
1238 )
1239 };
1240 if rc != 1 {
1241 return Err(ErrorStack::drain());
1242 }
1243 let mut ss = vec![0u8; sslen];
1244 crate::ossl_call!(sys::EVP_PKEY_decapsulate(
1245 self.ptr,
1246 ss.as_mut_ptr(),
1247 std::ptr::addr_of_mut!(sslen),
1248 wrapped_key.as_ptr(),
1249 wrapped_key.len()
1250 ))?;
1251 ss.truncate(sslen);
1252 Ok(ss)
1253 }
1254}
1255
1256#[cfg(ossl320)]
1257impl Drop for DecapCtx {
1258 fn drop(&mut self) {
1259 unsafe { sys::EVP_PKEY_CTX_free(self.ptr) };
1260 }
1261}
1262
1263pub struct RawSigner {
1275 ctx: *mut sys::EVP_PKEY_CTX,
1276}
1277
1278unsafe impl Send for RawSigner {}
1281
1282impl RawSigner {
1283 pub fn new(
1291 key: &Pkey<Private>,
1292 libctx: Option<&Arc<crate::lib_ctx::LibCtx>>,
1293 ) -> Result<Self, ErrorStack> {
1294 let lctx = libctx.map_or(std::ptr::null_mut(), |c| c.as_ptr());
1295 let ptr = unsafe { sys::EVP_PKEY_CTX_new_from_pkey(lctx, key.ptr, std::ptr::null()) };
1296 if ptr.is_null() {
1297 return Err(ErrorStack::drain());
1298 }
1299 crate::ossl_call!(sys::EVP_PKEY_sign_init(ptr)).map_err(|e| {
1300 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
1301 e
1302 })?;
1303 Ok(RawSigner { ctx: ptr })
1304 }
1305
1306 pub fn set_params(&mut self, params: &crate::params::Params<'_>) -> Result<(), ErrorStack> {
1310 crate::ossl_call!(sys::EVP_PKEY_CTX_set_params(self.ctx, params.as_ptr()))
1311 }
1312
1313 pub fn sign_len(&mut self, tbs_len: usize) -> Result<usize, ErrorStack> {
1320 let mut siglen: usize = 0;
1321 crate::ossl_call!(sys::EVP_PKEY_sign(
1322 self.ctx,
1323 std::ptr::null_mut(),
1324 std::ptr::addr_of_mut!(siglen),
1325 std::ptr::null(),
1326 tbs_len,
1327 ))?;
1328 Ok(siglen)
1329 }
1330
1331 pub fn sign(&mut self, tbs: &[u8], sig: &mut [u8]) -> Result<usize, ErrorStack> {
1337 let mut siglen = sig.len();
1338 crate::ossl_call!(sys::EVP_PKEY_sign(
1339 self.ctx,
1340 sig.as_mut_ptr(),
1341 std::ptr::addr_of_mut!(siglen),
1342 tbs.as_ptr(),
1343 tbs.len(),
1344 ))?;
1345 Ok(siglen)
1346 }
1347
1348 pub fn sign_alloc(&mut self, tbs: &[u8]) -> Result<Vec<u8>, ErrorStack> {
1354 let siglen = self.sign_len(tbs.len())?;
1355 let mut sig = vec![0u8; siglen];
1356 let written = self.sign(tbs, &mut sig)?;
1357 sig.truncate(written);
1358 Ok(sig)
1359 }
1360}
1361
1362impl Drop for RawSigner {
1363 fn drop(&mut self) {
1364 unsafe { sys::EVP_PKEY_CTX_free(self.ctx) };
1365 }
1366}
1367
1368pub struct RawVerifier {
1375 ctx: *mut sys::EVP_PKEY_CTX,
1376}
1377
1378unsafe impl Send for RawVerifier {}
1379
1380impl RawVerifier {
1381 pub fn new<T: HasPublic>(
1385 key: &Pkey<T>,
1386 libctx: Option<&Arc<crate::lib_ctx::LibCtx>>,
1387 ) -> Result<Self, ErrorStack> {
1388 let lctx = libctx.map_or(std::ptr::null_mut(), |c| c.as_ptr());
1389 let ptr = unsafe { sys::EVP_PKEY_CTX_new_from_pkey(lctx, key.ptr, std::ptr::null()) };
1390 if ptr.is_null() {
1391 return Err(ErrorStack::drain());
1392 }
1393 crate::ossl_call!(sys::EVP_PKEY_verify_init(ptr)).map_err(|e| {
1394 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
1395 e
1396 })?;
1397 Ok(RawVerifier { ctx: ptr })
1398 }
1399
1400 pub fn set_params(&mut self, params: &crate::params::Params<'_>) -> Result<(), ErrorStack> {
1404 crate::ossl_call!(sys::EVP_PKEY_CTX_set_params(self.ctx, params.as_ptr()))
1405 }
1406
1407 pub fn verify(&mut self, tbs: &[u8], sig: &[u8]) -> Result<(), ErrorStack> {
1413 crate::ossl_call!(sys::EVP_PKEY_verify(
1414 self.ctx,
1415 sig.as_ptr(),
1416 sig.len(),
1417 tbs.as_ptr(),
1418 tbs.len(),
1419 ))
1420 }
1421}
1422
1423impl Drop for RawVerifier {
1424 fn drop(&mut self) {
1425 unsafe { sys::EVP_PKEY_CTX_free(self.ctx) };
1426 }
1427}
1428
1429#[cfg(ossl320)]
1437pub struct SigAlg {
1438 ptr: *mut sys::EVP_SIGNATURE,
1439}
1440
1441#[cfg(ossl320)]
1443unsafe impl Send for SigAlg {}
1444#[cfg(ossl320)]
1445unsafe impl Sync for SigAlg {}
1446
1447#[cfg(ossl320)]
1448impl SigAlg {
1449 pub fn fetch(
1455 name: &std::ffi::CStr,
1456 props: Option<&std::ffi::CStr>,
1457 ) -> Result<Self, ErrorStack> {
1458 let props_ptr = props.map_or(std::ptr::null(), std::ffi::CStr::as_ptr);
1459 let ptr =
1460 unsafe { sys::EVP_SIGNATURE_fetch(std::ptr::null_mut(), name.as_ptr(), props_ptr) };
1461 if ptr.is_null() {
1462 return Err(ErrorStack::drain());
1463 }
1464 Ok(SigAlg { ptr })
1465 }
1466
1467 pub fn fetch_in(
1471 ctx: &Arc<crate::lib_ctx::LibCtx>,
1472 name: &std::ffi::CStr,
1473 props: Option<&std::ffi::CStr>,
1474 ) -> Result<Self, ErrorStack> {
1475 let props_ptr = props.map_or(std::ptr::null(), std::ffi::CStr::as_ptr);
1476 let ptr = unsafe { sys::EVP_SIGNATURE_fetch(ctx.as_ptr(), name.as_ptr(), props_ptr) };
1477 if ptr.is_null() {
1478 return Err(ErrorStack::drain());
1479 }
1480 Ok(SigAlg { ptr })
1481 }
1482}
1483
1484#[cfg(ossl320)]
1485impl Clone for SigAlg {
1486 fn clone(&self) -> Self {
1487 unsafe { sys::EVP_SIGNATURE_up_ref(self.ptr) };
1488 SigAlg { ptr: self.ptr }
1489 }
1490}
1491
1492#[cfg(ossl320)]
1493impl Drop for SigAlg {
1494 fn drop(&mut self) {
1495 unsafe { sys::EVP_SIGNATURE_free(self.ptr) };
1496 }
1497}
1498
1499#[cfg(ossl320)]
1512pub struct MessageSigner {
1513 ctx: *mut sys::EVP_PKEY_CTX,
1514}
1515
1516#[cfg(ossl320)]
1517unsafe impl Send for MessageSigner {}
1518
1519#[cfg(ossl320)]
1520impl MessageSigner {
1521 pub fn new(
1528 key: &Pkey<Private>,
1529 alg: &mut SigAlg,
1530 params: Option<&crate::params::Params<'_>>,
1531 ) -> Result<Self, ErrorStack> {
1532 let ptr = unsafe {
1533 sys::EVP_PKEY_CTX_new_from_pkey(std::ptr::null_mut(), key.ptr, std::ptr::null())
1534 };
1535 if ptr.is_null() {
1536 return Err(ErrorStack::drain());
1537 }
1538 let params_ptr = params.map_or(crate::params::null_params(), crate::params::Params::as_ptr);
1539 crate::ossl_call!(sys::EVP_PKEY_sign_message_init(ptr, alg.ptr, params_ptr)).map_err(
1540 |e| {
1541 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
1542 e
1543 },
1544 )?;
1545 Ok(MessageSigner { ctx: ptr })
1546 }
1547
1548 pub fn supports_streaming(&mut self) -> bool {
1556 unsafe { sys::ERR_set_mark() };
1559 let probe: [u8; 0] = [];
1560 let rc = unsafe { sys::EVP_PKEY_sign_message_update(self.ctx, probe.as_ptr(), 0) };
1561 unsafe { sys::ERR_pop_to_mark() };
1562 rc == 1
1563 }
1564
1565 pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
1572 crate::ossl_call!(sys::EVP_PKEY_sign_message_update(
1573 self.ctx,
1574 data.as_ptr(),
1575 data.len(),
1576 ))
1577 }
1578
1579 pub fn sig_len(&mut self) -> Result<usize, ErrorStack> {
1586 let mut siglen: usize = 0;
1587 crate::ossl_call!(sys::EVP_PKEY_sign_message_final(
1588 self.ctx,
1589 std::ptr::null_mut(),
1590 std::ptr::addr_of_mut!(siglen),
1591 ))?;
1592 Ok(siglen)
1593 }
1594
1595 pub fn finish(self, sig: &mut [u8]) -> Result<usize, ErrorStack> {
1603 let mut siglen = sig.len();
1604 let rc = unsafe {
1605 sys::EVP_PKEY_sign_message_final(
1606 self.ctx,
1607 sig.as_mut_ptr(),
1608 std::ptr::addr_of_mut!(siglen),
1609 )
1610 };
1611 if rc != 1 {
1613 return Err(ErrorStack::drain());
1614 }
1615 Ok(siglen)
1616 }
1617
1618 pub fn sign_oneshot(self, data: &[u8], sig: &mut [u8]) -> Result<usize, ErrorStack> {
1625 let rc_upd =
1627 unsafe { sys::EVP_PKEY_sign_message_update(self.ctx, data.as_ptr(), data.len()) };
1628 if rc_upd != 1 {
1629 return Err(ErrorStack::drain());
1631 }
1632 let mut siglen = sig.len();
1633 let rc_fin = unsafe {
1634 sys::EVP_PKEY_sign_message_final(
1635 self.ctx,
1636 sig.as_mut_ptr(),
1637 std::ptr::addr_of_mut!(siglen),
1638 )
1639 };
1640 if rc_fin != 1 {
1642 return Err(ErrorStack::drain());
1643 }
1644 Ok(siglen)
1645 }
1646}
1647
1648#[cfg(ossl320)]
1649impl Drop for MessageSigner {
1650 fn drop(&mut self) {
1651 unsafe { sys::EVP_PKEY_CTX_free(self.ctx) };
1652 }
1653}
1654
1655#[cfg(ossl320)]
1665pub struct MessageVerifier {
1666 ctx: *mut sys::EVP_PKEY_CTX,
1667}
1668
1669#[cfg(ossl320)]
1670unsafe impl Send for MessageVerifier {}
1671
1672#[cfg(ossl320)]
1673impl MessageVerifier {
1674 pub fn new<T: HasPublic>(
1678 key: &Pkey<T>,
1679 alg: &mut SigAlg,
1680 params: Option<&crate::params::Params<'_>>,
1681 ) -> Result<Self, ErrorStack> {
1682 let ptr = unsafe {
1683 sys::EVP_PKEY_CTX_new_from_pkey(std::ptr::null_mut(), key.ptr, std::ptr::null())
1684 };
1685 if ptr.is_null() {
1686 return Err(ErrorStack::drain());
1687 }
1688 let params_ptr = params.map_or(crate::params::null_params(), crate::params::Params::as_ptr);
1689 crate::ossl_call!(sys::EVP_PKEY_verify_message_init(ptr, alg.ptr, params_ptr)).map_err(
1690 |e| {
1691 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
1692 e
1693 },
1694 )?;
1695 Ok(MessageVerifier { ctx: ptr })
1696 }
1697
1698 pub fn set_params(&mut self, params: &crate::params::Params<'_>) -> Result<(), ErrorStack> {
1702 crate::ossl_call!(sys::EVP_PKEY_CTX_set_params(self.ctx, params.as_ptr()))
1703 }
1704
1705 pub fn set_signature(&mut self, sig: &[u8]) -> Result<(), ErrorStack> {
1712 crate::ossl_call!(sys::EVP_PKEY_CTX_set_signature(
1713 self.ctx,
1714 sig.as_ptr(),
1715 sig.len()
1716 ))
1717 }
1718
1719 pub fn supports_streaming(&mut self) -> bool {
1724 unsafe { sys::ERR_set_mark() };
1725 let probe: [u8; 0] = [];
1726 let rc = unsafe { sys::EVP_PKEY_verify_message_update(self.ctx, probe.as_ptr(), 0) };
1727 unsafe { sys::ERR_pop_to_mark() };
1728 rc == 1
1729 }
1730
1731 pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
1735 crate::ossl_call!(sys::EVP_PKEY_verify_message_update(
1736 self.ctx,
1737 data.as_ptr(),
1738 data.len(),
1739 ))
1740 }
1741
1742 pub fn finish(self) -> Result<(), ErrorStack> {
1749 let rc = unsafe { sys::EVP_PKEY_verify_message_final(self.ctx) };
1750 if rc != 1 {
1752 return Err(ErrorStack::drain());
1753 }
1754 Ok(())
1755 }
1756
1757 pub fn verify_oneshot(self, data: &[u8], sig: &[u8]) -> Result<(), ErrorStack> {
1763 let rc_set = unsafe { sys::EVP_PKEY_CTX_set_signature(self.ctx, sig.as_ptr(), sig.len()) };
1764 if rc_set != 1 {
1765 return Err(ErrorStack::drain());
1766 }
1767 let rc_upd =
1768 unsafe { sys::EVP_PKEY_verify_message_update(self.ctx, data.as_ptr(), data.len()) };
1769 if rc_upd != 1 {
1770 return Err(ErrorStack::drain());
1771 }
1772 let rc_fin = unsafe { sys::EVP_PKEY_verify_message_final(self.ctx) };
1773 if rc_fin != 1 {
1775 return Err(ErrorStack::drain());
1776 }
1777 Ok(())
1778 }
1779}
1780
1781#[cfg(ossl320)]
1782impl Drop for MessageVerifier {
1783 fn drop(&mut self) {
1784 unsafe { sys::EVP_PKEY_CTX_free(self.ctx) };
1785 }
1786}
1787
1788#[cfg(test)]
1791mod tests {
1792 use super::*;
1793
1794 #[test]
1798 fn ed25519_sign_verify() {
1799 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
1800 let priv_key = kgen.generate().unwrap();
1801 let pub_key = Pkey::<Public>::from(priv_key.clone());
1802
1803 let msg = b"hello world";
1804 let init = SignInit::default();
1805
1806 let mut signer = Signer::new(&priv_key, &init).unwrap();
1807 let sig = signer.sign_oneshot(msg).unwrap();
1808 assert!(!sig.is_empty());
1809
1810 let mut verifier = Verifier::new(&pub_key, &init).unwrap();
1811 assert!(verifier.verify_oneshot(msg, &sig).unwrap());
1812 }
1813
1814 #[test]
1816 fn ed25519_verify_wrong_msg_fails() {
1817 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
1818 let priv_key = kgen.generate().unwrap();
1819 let pub_key = Pkey::<Public>::from(priv_key.clone());
1820
1821 let mut signer = Signer::new(&priv_key, &SignInit::default()).unwrap();
1822 let sig = signer.sign_oneshot(b"correct").unwrap();
1823
1824 let mut verifier = Verifier::new(&pub_key, &SignInit::default()).unwrap();
1825 assert!(!verifier.verify_oneshot(b"tampered", &sig).unwrap());
1826 }
1827
1828 #[test]
1830 fn x25519_derive() {
1831 let mut kgen_a = KeygenCtx::new(c"X25519").unwrap();
1832 let priv_a = kgen_a.generate().unwrap();
1833
1834 let mut kgen_b = KeygenCtx::new(c"X25519").unwrap();
1835 let priv_b = kgen_b.generate().unwrap();
1836 let pub_b = Pkey::<Public>::from(priv_b);
1837
1838 let mut derive = DeriveCtx::new(&priv_a).unwrap();
1839 derive.set_peer(&pub_b).unwrap();
1840 let len = derive.derive_len().unwrap();
1841 assert_eq!(len, 32); let mut ss = vec![0u8; len];
1844 let n = derive.derive(&mut ss).unwrap();
1845 assert_eq!(n, 32);
1846 assert_ne!(ss, [0u8; 32]);
1847 }
1848
1849 #[test]
1851 fn pem_round_trip() {
1852 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
1853 let priv_key = kgen.generate().unwrap();
1854
1855 let pem = priv_key.to_pem().unwrap();
1856 assert!(!pem.is_empty());
1857 assert!(pem.starts_with(b"-----BEGIN"));
1858
1859 let priv_key2 = Pkey::<Private>::from_pem(&pem).unwrap();
1860 assert_eq!(priv_key.bits(), priv_key2.bits());
1861 assert!(priv_key.is_a(c"ED25519"));
1862 }
1863
1864 #[test]
1866 fn ed25519_metadata() {
1867 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
1868 let key = kgen.generate().unwrap();
1869 assert_eq!(key.bits(), 256);
1870 assert_eq!(key.security_bits(), 128);
1871 assert!(key.is_a(c"ED25519"));
1872 }
1873
1874 #[test]
1876 fn ecdsa_p256_raw_sign_verify() {
1877 let mut kgen = KeygenCtx::new(c"EC").unwrap();
1879 let params = crate::params::ParamBuilder::new()
1880 .unwrap()
1881 .push_utf8_string(c"group", c"P-256")
1882 .unwrap()
1883 .build()
1884 .unwrap();
1885 kgen.set_params(¶ms).unwrap();
1886 let priv_key = kgen.generate().unwrap();
1887 let pub_key = Pkey::<Public>::from(priv_key.clone());
1888
1889 let tbs: [u8; 32] = *b"0123456789abcdef0123456789abcdef";
1891
1892 let mut signer = RawSigner::new(&priv_key, None).unwrap();
1893 let sig = signer.sign_alloc(&tbs).unwrap();
1894 assert!(!sig.is_empty());
1895
1896 let mut verifier = RawVerifier::new(&pub_key, None).unwrap();
1897 verifier.verify(&tbs, &sig).unwrap();
1898 }
1899
1900 #[test]
1902 fn ecdsa_p256_raw_verify_tampered_fails() {
1903 let mut kgen = KeygenCtx::new(c"EC").unwrap();
1904 let params = crate::params::ParamBuilder::new()
1905 .unwrap()
1906 .push_utf8_string(c"group", c"P-256")
1907 .unwrap()
1908 .build()
1909 .unwrap();
1910 kgen.set_params(¶ms).unwrap();
1911 let priv_key = kgen.generate().unwrap();
1912 let pub_key = Pkey::<Public>::from(priv_key.clone());
1913
1914 let tbs: [u8; 32] = *b"0123456789abcdef0123456789abcdef";
1915 let mut signer = RawSigner::new(&priv_key, None).unwrap();
1916 let mut sig = signer.sign_alloc(&tbs).unwrap();
1917 if let Some(b) = sig.last_mut() {
1919 *b ^= 0xff;
1920 }
1921
1922 let mut verifier = RawVerifier::new(&pub_key, None).unwrap();
1923 assert!(verifier.verify(&tbs, &sig).is_err());
1924 }
1925
1926 #[cfg(ossl320)]
1933 #[test]
1934 fn sig_alg_fetch_clone_drop() {
1935 let alg = SigAlg::fetch(c"ML-DSA-44", None).unwrap();
1936 let alg2 = alg.clone();
1937 drop(alg);
1938 drop(alg2); }
1940
1941 #[cfg(ossl320)]
1946 #[test]
1947 fn message_signer_construction_and_streaming_probe() {
1948 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
1949 let priv_key = kgen.generate().unwrap();
1950
1951 let mut alg = SigAlg::fetch(c"ED25519", None).unwrap();
1952 let mut signer = MessageSigner::new(&priv_key, &mut alg, None).unwrap();
1953
1954 let _streaming = signer.supports_streaming();
1956 assert_eq!(crate::error::ErrorStack::drain().errors().count(), 0);
1958 }
1959
1960 #[cfg(ossl320)]
1962 #[test]
1963 fn message_verifier_construction() {
1964 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
1965 let priv_key = kgen.generate().unwrap();
1966 let pub_key = Pkey::<Public>::from(priv_key.clone());
1967
1968 let mut alg = SigAlg::fetch(c"ED25519", None).unwrap();
1969 let _verifier = MessageVerifier::new(&pub_key, &mut alg, None).unwrap();
1970 }
1971
1972 #[test]
1974 fn encrypted_pem_round_trip() {
1975 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
1976 let key = kgen.generate().unwrap();
1977
1978 let cipher = crate::cipher::CipherAlg::fetch(c"AES-256-CBC", None).unwrap();
1979 let pem = key.to_pem_encrypted(&cipher, b"s3cret").unwrap();
1980 assert!(pem.starts_with(b"-----BEGIN ENCRYPTED PRIVATE KEY-----"));
1981
1982 let key2 = Pkey::<Private>::from_pem_passphrase(&pem, b"s3cret").unwrap();
1983 assert!(key.public_eq(&key2));
1984 }
1985
1986 #[test]
1988 fn encrypted_pem_wrong_passphrase_fails() {
1989 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
1990 let key = kgen.generate().unwrap();
1991
1992 let cipher = crate::cipher::CipherAlg::fetch(c"AES-256-CBC", None).unwrap();
1993 let pem = key.to_pem_encrypted(&cipher, b"correct").unwrap();
1994 assert!(Pkey::<Private>::from_pem_passphrase(&pem, b"wrong").is_err());
1995 }
1996
1997 #[test]
1999 fn pkcs8_der_round_trip() {
2000 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
2001 let key = kgen.generate().unwrap();
2002
2003 let der = key.to_pkcs8_der().unwrap();
2004 assert!(!der.is_empty());
2005
2006 let key2 = Pkey::<Private>::from_der(&der).unwrap();
2007 assert!(key.public_eq(&key2));
2008 }
2009
2010 #[test]
2012 fn pubkey_from_pem_in_roundtrip() {
2013 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
2015 let priv_key = kgen.generate().unwrap();
2016 let pub_pem = Pkey::<Public>::from(priv_key).to_pem().unwrap();
2017
2018 let lib_ctx = Arc::new(crate::lib_ctx::LibCtx::new().unwrap());
2020 let pub_key = Pkey::<Public>::from_pem_in(&lib_ctx, &pub_pem).unwrap();
2021
2022 assert!(!pub_key.to_pem().unwrap().is_empty());
2024 }
2025}