1use crate::error::ErrorStack;
14use crate::bio::{MemBio, MemBioBuf};
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 { ptr: self.ptr, _role: PhantomData }
75 }
76}
77
78impl<T> Drop for Pkey<T> {
79 fn drop(&mut self) {
80 unsafe { sys::EVP_PKEY_free(self.ptr) };
81 }
82}
83
84impl<T: HasParams> Pkey<T> {
85 #[must_use]
91 pub unsafe fn from_ptr(ptr: *mut sys::EVP_PKEY) -> Self {
92 Pkey { ptr, _role: PhantomData }
93 }
94
95 #[must_use]
97 pub fn as_ptr(&self) -> *mut sys::EVP_PKEY {
98 self.ptr
99 }
100
101
102 #[must_use]
104 pub fn bits(&self) -> u32 {
105 u32::try_from(unsafe { sys::EVP_PKEY_get_bits(self.ptr) }).unwrap_or(0)
106 }
107
108 #[must_use]
110 pub fn security_bits(&self) -> u32 {
111 u32::try_from(unsafe { sys::EVP_PKEY_get_security_bits(self.ptr) }).unwrap_or(0)
112 }
113
114 #[must_use]
116 pub fn is_a(&self, name: &std::ffi::CStr) -> bool {
117 unsafe { sys::EVP_PKEY_is_a(self.ptr, name.as_ptr()) == 1 }
118 }
119
120 #[must_use]
125 pub fn public_eq<U: HasPublic>(&self, other: &Pkey<U>) -> bool
126 where
127 T: HasPublic,
128 {
129 unsafe { sys::EVP_PKEY_eq(self.ptr, other.ptr) == 1 }
130 }
131
132 pub fn get_params(&self, params: &mut crate::params::Params<'_>) -> Result<(), ErrorStack> {
139 crate::ossl_call!(sys::EVP_PKEY_get_params(self.ptr, params.as_mut_ptr()))
140 }
141
142 pub fn public_key_to_der(&self) -> Result<Vec<u8>, ErrorStack>
151 where
152 T: HasPublic,
153 {
154 let len = unsafe { sys::i2d_PUBKEY(self.ptr, std::ptr::null_mut()) };
156 if len < 0 {
157 return Err(ErrorStack::drain());
158 }
159 let mut buf = vec![0u8; usize::try_from(len).unwrap_or(0)];
162 let mut out_ptr = buf.as_mut_ptr();
163 let written = unsafe { sys::i2d_PUBKEY(self.ptr, std::ptr::addr_of_mut!(out_ptr)) };
164 if written < 0 {
165 return Err(ErrorStack::drain());
166 }
167 buf.truncate(usize::try_from(written).unwrap_or(0));
168 Ok(buf)
169 }
170}
171
172impl Pkey<Private> {
175 #[cfg(feature = "fips-provider")]
192 pub unsafe fn keydata(&self) -> *mut std::ffi::c_void {
193 self.ptr
197 .cast::<u8>()
198 .add(native_ossl_sys::fips_internal::EVP_PKEY_KEYDATA_OFFSET)
199 .cast::<*mut std::ffi::c_void>()
200 .read()
201 }
202
203 pub fn from_pem(pem: &[u8]) -> Result<Self, ErrorStack> {
209 let bio = MemBioBuf::new(pem)?;
210 let ptr = unsafe {
211 sys::PEM_read_bio_PrivateKey(bio.as_ptr(), std::ptr::null_mut(), None, std::ptr::null_mut())
212 };
213 if ptr.is_null() {
214 return Err(ErrorStack::drain());
215 }
216 Ok(unsafe { Pkey::from_ptr(ptr) })
217 }
218
219 pub fn to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
223 let mut bio = MemBio::new()?;
224 let rc = unsafe {
225 sys::PEM_write_bio_PrivateKey(
226 bio.as_ptr(),
227 self.ptr,
228 std::ptr::null(),
229 std::ptr::null_mut(),
230 0,
231 None,
232 std::ptr::null_mut(),
233 )
234 };
235 if rc != 1 {
236 return Err(ErrorStack::drain());
237 }
238 Ok(bio.into_vec())
239 }
240
241 pub fn from_pem_in(ctx: &Arc<crate::lib_ctx::LibCtx>, pem: &[u8]) -> Result<Self, ErrorStack> {
249 let bio = MemBioBuf::new(pem)?;
250 let ptr = unsafe {
251 sys::PEM_read_bio_PrivateKey_ex(
252 bio.as_ptr(),
253 std::ptr::null_mut(),
254 None,
255 std::ptr::null_mut(),
256 ctx.as_ptr(),
257 std::ptr::null(),
258 )
259 };
260 if ptr.is_null() {
261 return Err(ErrorStack::drain());
262 }
263 Ok(unsafe { Pkey::from_ptr(ptr) })
264 }
265
266 pub fn from_der(der: &[u8]) -> Result<Self, ErrorStack> {
272 let bio = MemBioBuf::new(der)?;
273 let ptr = unsafe { sys::d2i_PrivateKey_bio(bio.as_ptr(), std::ptr::null_mut()) };
274 if ptr.is_null() {
275 return Err(ErrorStack::drain());
276 }
277 Ok(unsafe { Pkey::from_ptr(ptr) })
278 }
279}
280
281impl Pkey<Public> {
284 pub fn from_pem(pem: &[u8]) -> Result<Self, ErrorStack> {
288 let bio = MemBioBuf::new(pem)?;
289 let ptr = unsafe {
290 sys::PEM_read_bio_PUBKEY(bio.as_ptr(), std::ptr::null_mut(), None, std::ptr::null_mut())
291 };
292 if ptr.is_null() {
293 return Err(ErrorStack::drain());
294 }
295 Ok(unsafe { Pkey::from_ptr(ptr) })
296 }
297
298 pub fn from_pem_in(ctx: &Arc<crate::lib_ctx::LibCtx>, pem: &[u8]) -> Result<Self, ErrorStack> {
306 let bio = MemBioBuf::new(pem)?;
307 let ptr = unsafe {
308 sys::PEM_read_bio_PUBKEY_ex(
309 bio.as_ptr(),
310 std::ptr::null_mut(),
311 None,
312 std::ptr::null_mut(),
313 ctx.as_ptr(),
314 std::ptr::null(),
315 )
316 };
317 if ptr.is_null() {
318 return Err(ErrorStack::drain());
319 }
320 Ok(unsafe { Pkey::from_ptr(ptr) })
321 }
322
323 pub fn from_der(der: &[u8]) -> Result<Self, ErrorStack> {
327 let bio = MemBioBuf::new(der)?;
328 let ptr = unsafe { sys::d2i_PUBKEY_bio(bio.as_ptr(), std::ptr::null_mut()) };
329 if ptr.is_null() {
330 return Err(ErrorStack::drain());
331 }
332 Ok(unsafe { Pkey::from_ptr(ptr) })
333 }
334
335 pub fn to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
339 let mut bio = MemBio::new()?;
340 let rc = unsafe { sys::PEM_write_bio_PUBKEY(bio.as_ptr(), self.ptr) };
341 if rc != 1 {
342 return Err(ErrorStack::drain());
343 }
344 Ok(bio.into_vec())
345 }
346}
347
348impl From<Pkey<Private>> for Pkey<Public> {
350 fn from(k: Pkey<Private>) -> Self {
351 unsafe { sys::EVP_PKEY_up_ref(k.ptr) };
352 Pkey { ptr: k.ptr, _role: PhantomData }
353 }
354}
355
356const PKEY_PUBLIC_KEY: i32 = 2;
360const PKEY_KEYPAIR: i32 = 3;
361
362fn pkey_fromdata(
364 ctx: Option<&Arc<crate::lib_ctx::LibCtx>>,
365 pkey_type: &std::ffi::CStr,
366 params: &crate::params::Params<'_>,
367 selection: i32,
368) -> Result<*mut sys::EVP_PKEY, ErrorStack> {
369 let libctx = ctx.map_or(std::ptr::null_mut(), |c| c.as_ptr());
370 let pctx = unsafe {
371 sys::EVP_PKEY_CTX_new_from_name(libctx, pkey_type.as_ptr(), std::ptr::null())
372 };
373 if pctx.is_null() {
374 return Err(ErrorStack::drain());
375 }
376 let rc = unsafe { sys::EVP_PKEY_fromdata_init(pctx) };
377 if rc != 1 {
378 unsafe { sys::EVP_PKEY_CTX_free(pctx) };
379 return Err(ErrorStack::drain());
380 }
381 let mut pkey: *mut sys::EVP_PKEY = std::ptr::null_mut();
382 let rc = unsafe {
383 sys::EVP_PKEY_fromdata(
384 pctx,
385 std::ptr::addr_of_mut!(pkey),
386 selection,
387 params.as_ptr().cast_mut(),
389 )
390 };
391 unsafe { sys::EVP_PKEY_CTX_free(pctx) };
392 if rc != 1 || pkey.is_null() {
393 return Err(ErrorStack::drain());
394 }
395 Ok(pkey)
396}
397
398fn pkey_todata(
400 ptr: *mut sys::EVP_PKEY,
401 selection: i32,
402) -> Result<crate::params::Params<'static>, ErrorStack> {
403 let mut out: *mut sys::OSSL_PARAM = std::ptr::null_mut();
404 let rc = unsafe { sys::EVP_PKEY_todata(ptr, selection, std::ptr::addr_of_mut!(out)) };
405 if rc != 1 || out.is_null() {
406 return Err(ErrorStack::drain());
407 }
408 Ok(unsafe { crate::params::Params::from_owned_ptr(out) })
411}
412
413impl Pkey<Private> {
414 pub fn from_params(
421 ctx: Option<&Arc<crate::lib_ctx::LibCtx>>,
422 pkey_type: &std::ffi::CStr,
423 params: &crate::params::Params<'_>,
424 ) -> Result<Self, ErrorStack> {
425 pkey_fromdata(ctx, pkey_type, params, PKEY_KEYPAIR)
426 .map(|ptr| unsafe { Pkey::from_ptr(ptr) })
427 }
428
429 pub fn export(&self) -> Result<crate::params::Params<'static>, ErrorStack> {
436 pkey_todata(self.ptr, PKEY_KEYPAIR)
437 }
438}
439
440impl Pkey<Public> {
441 pub fn from_params(
448 ctx: Option<&Arc<crate::lib_ctx::LibCtx>>,
449 pkey_type: &std::ffi::CStr,
450 params: &crate::params::Params<'_>,
451 ) -> Result<Self, ErrorStack> {
452 pkey_fromdata(ctx, pkey_type, params, PKEY_PUBLIC_KEY)
453 .map(|ptr| unsafe { Pkey::from_ptr(ptr) })
454 }
455
456 pub fn export(&self) -> Result<crate::params::Params<'static>, ErrorStack> {
462 pkey_todata(self.ptr, PKEY_PUBLIC_KEY)
463 }
464}
465
466pub struct KeygenCtx {
470 ptr: *mut sys::EVP_PKEY_CTX,
471}
472
473impl KeygenCtx {
474 pub fn new(name: &std::ffi::CStr) -> Result<Self, ErrorStack> {
480 let ptr = unsafe {
481 sys::EVP_PKEY_CTX_new_from_name(std::ptr::null_mut(), name.as_ptr(), std::ptr::null())
482 };
483 if ptr.is_null() {
484 return Err(ErrorStack::drain());
485 }
486 let rc = unsafe { sys::EVP_PKEY_keygen_init(ptr) };
487 if rc != 1 {
488 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
489 return Err(ErrorStack::drain());
490 }
491 Ok(KeygenCtx { ptr })
492 }
493
494 pub fn set_params(&mut self, params: &crate::params::Params<'_>) -> Result<(), ErrorStack> {
498 crate::ossl_call!(sys::EVP_PKEY_CTX_set_params(self.ptr, params.as_ptr()))
499 }
500
501 pub fn generate(&mut self) -> Result<Pkey<Private>, ErrorStack> {
505 let mut key: *mut sys::EVP_PKEY = std::ptr::null_mut();
506 crate::ossl_call!(sys::EVP_PKEY_keygen(self.ptr, std::ptr::addr_of_mut!(key)))?;
507 if key.is_null() {
508 return Err(ErrorStack::drain());
509 }
510 Ok(unsafe { Pkey::from_ptr(key) })
511 }
512}
513
514impl Drop for KeygenCtx {
515 fn drop(&mut self) {
516 unsafe { sys::EVP_PKEY_CTX_free(self.ptr) };
517 }
518}
519
520#[derive(Default)]
524pub struct SignInit<'a> {
525 pub digest: Option<&'a crate::digest::DigestAlg>,
527 pub params: Option<&'a crate::params::Params<'a>>,
529}
530
531pub struct Signer {
535 ctx: crate::digest::DigestCtx,
536 _key: Pkey<Private>,
538}
539
540impl Signer {
541 pub fn new(key: &Pkey<Private>, init: &SignInit<'_>) -> Result<Self, ErrorStack> {
545 let ctx = alloc_digest_ctx()?;
546 let md_name_ptr = if let Some(d) = init.digest {
548 let p = unsafe { sys::OBJ_nid2sn(d.nid()) };
549 if p.is_null() {
550 return Err(ErrorStack::drain());
551 }
552 p
553 } else {
554 std::ptr::null()
555 };
556 let params_ptr = init.params.map_or(crate::params::null_params(), crate::params::Params::as_ptr);
557 let rc = unsafe {
558 sys::EVP_DigestSignInit_ex(
559 ctx.as_ptr(),
560 std::ptr::null_mut(),
561 md_name_ptr,
562 std::ptr::null_mut(),
563 std::ptr::null(),
564 key.ptr,
565 params_ptr,
566 )
567 };
568 if rc != 1 {
569 return Err(ErrorStack::drain());
570 }
571 Ok(Signer { ctx, _key: key.clone() })
572 }
573
574 pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
578 crate::ossl_call!(sys::EVP_DigestSignUpdate(self.ctx.as_ptr(), data.as_ptr().cast(), data.len()))
579 }
580
581 pub fn finish(&mut self) -> Result<Vec<u8>, ErrorStack> {
588 let mut siglen: usize = 0;
590 let rc = unsafe {
591 sys::EVP_DigestSignFinal(
592 self.ctx.as_ptr(),
593 std::ptr::null_mut(),
594 std::ptr::addr_of_mut!(siglen),
595 )
596 };
597 if rc != 1 {
598 return Err(ErrorStack::drain());
599 }
600 let mut sig = vec![0u8; siglen];
601 let rc = unsafe {
602 sys::EVP_DigestSignFinal(
603 self.ctx.as_ptr(),
604 sig.as_mut_ptr(),
605 std::ptr::addr_of_mut!(siglen),
606 )
607 };
608 if rc != 1 {
609 return Err(ErrorStack::drain());
610 }
611 sig.truncate(siglen);
612 Ok(sig)
613 }
614
615 pub fn sign_oneshot(&mut self, data: &[u8]) -> Result<Vec<u8>, ErrorStack> {
622 let mut siglen: usize = 0;
624 let rc = unsafe {
625 sys::EVP_DigestSign(
626 self.ctx.as_ptr(),
627 std::ptr::null_mut(),
628 std::ptr::addr_of_mut!(siglen),
629 data.as_ptr(),
630 data.len(),
631 )
632 };
633 if rc != 1 {
634 return Err(ErrorStack::drain());
635 }
636 let mut sig = vec![0u8; siglen];
637 let rc = unsafe {
638 sys::EVP_DigestSign(
639 self.ctx.as_ptr(),
640 sig.as_mut_ptr(),
641 std::ptr::addr_of_mut!(siglen),
642 data.as_ptr(),
643 data.len(),
644 )
645 };
646 if rc != 1 {
647 return Err(ErrorStack::drain());
648 }
649 sig.truncate(siglen);
650 Ok(sig)
651 }
652}
653
654pub struct Verifier {
658 ctx: crate::digest::DigestCtx,
659 _key: Pkey<Public>,
660}
661
662impl Verifier {
663 pub fn new(key: &Pkey<Public>, init: &SignInit<'_>) -> Result<Self, ErrorStack> {
667 let ctx = alloc_digest_ctx()?;
668 let md_name_ptr = if let Some(d) = init.digest {
670 let p = unsafe { sys::OBJ_nid2sn(d.nid()) };
671 if p.is_null() {
672 return Err(ErrorStack::drain());
673 }
674 p
675 } else {
676 std::ptr::null()
677 };
678 let params_ptr = init.params.map_or(crate::params::null_params(), crate::params::Params::as_ptr);
679 let rc = unsafe {
680 sys::EVP_DigestVerifyInit_ex(
681 ctx.as_ptr(),
682 std::ptr::null_mut(),
683 md_name_ptr,
684 std::ptr::null_mut(),
685 std::ptr::null(),
686 key.ptr,
687 params_ptr,
688 )
689 };
690 if rc != 1 {
691 return Err(ErrorStack::drain());
692 }
693 Ok(Verifier { ctx, _key: key.clone() })
694 }
695
696 pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
700 crate::ossl_call!(sys::EVP_DigestVerifyUpdate(self.ctx.as_ptr(), data.as_ptr().cast(), data.len()))
701 }
702
703 pub fn verify(&mut self, signature: &[u8]) -> Result<bool, ErrorStack> {
713 let rc = unsafe {
714 sys::EVP_DigestVerifyFinal(
715 self.ctx.as_ptr(),
716 signature.as_ptr(),
717 signature.len(),
718 )
719 };
720 match rc {
721 1 => Ok(true),
722 0 => Ok(false),
723 _ => Err(ErrorStack::drain()),
724 }
725 }
726
727 pub fn verify_oneshot(&mut self, data: &[u8], signature: &[u8]) -> Result<bool, ErrorStack> {
733 let rc = unsafe {
734 sys::EVP_DigestVerify(
735 self.ctx.as_ptr(),
736 signature.as_ptr(),
737 signature.len(),
738 data.as_ptr(),
739 data.len(),
740 )
741 };
742 match rc {
743 1 => Ok(true),
744 0 => Ok(false),
745 _ => Err(ErrorStack::drain()),
746 }
747 }
748}
749
750fn alloc_digest_ctx() -> Result<crate::digest::DigestCtx, ErrorStack> {
755 let ctx_ptr = unsafe { sys::EVP_MD_CTX_new() };
756 if ctx_ptr.is_null() {
757 return Err(ErrorStack::drain());
758 }
759 Ok(unsafe { crate::digest::DigestCtx::from_ptr(ctx_ptr) })
761}
762
763pub struct DeriveCtx {
767 ptr: *mut sys::EVP_PKEY_CTX,
768}
769
770impl DeriveCtx {
771 pub fn new(key: &Pkey<Private>) -> Result<Self, ErrorStack> {
775 let ptr = unsafe {
776 sys::EVP_PKEY_CTX_new_from_pkey(std::ptr::null_mut(), key.ptr, std::ptr::null())
777 };
778 if ptr.is_null() {
779 return Err(ErrorStack::drain());
780 }
781 crate::ossl_call!(sys::EVP_PKEY_derive_init(ptr)).map_err(|e| {
782 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
783 e
784 })?;
785 Ok(DeriveCtx { ptr })
786 }
787
788 pub fn set_peer(&mut self, peer: &Pkey<Public>) -> Result<(), ErrorStack> {
792 crate::ossl_call!(sys::EVP_PKEY_derive_set_peer(self.ptr, peer.ptr))
793 }
794
795 pub fn derive(&mut self, out: &mut [u8]) -> Result<usize, ErrorStack> {
801 let mut len = out.len();
802 crate::ossl_call!(sys::EVP_PKEY_derive(
803 self.ptr,
804 out.as_mut_ptr(),
805 std::ptr::addr_of_mut!(len)
806 ))?;
807 Ok(len)
808 }
809
810 pub fn derive_len(&mut self) -> Result<usize, ErrorStack> {
814 let mut len: usize = 0;
815 crate::ossl_call!(sys::EVP_PKEY_derive(
816 self.ptr,
817 std::ptr::null_mut(),
818 std::ptr::addr_of_mut!(len)
819 ))?;
820 Ok(len)
821 }
822}
823
824impl Drop for DeriveCtx {
825 fn drop(&mut self) {
826 unsafe { sys::EVP_PKEY_CTX_free(self.ptr) };
827 }
828}
829
830pub struct PkeyEncryptCtx {
834 ptr: *mut sys::EVP_PKEY_CTX,
835}
836
837impl PkeyEncryptCtx {
838 pub fn new(key: &Pkey<Public>, params: Option<&crate::params::Params<'_>>) -> Result<Self, ErrorStack> {
848 let ptr = unsafe {
849 sys::EVP_PKEY_CTX_new_from_pkey(std::ptr::null_mut(), key.ptr, std::ptr::null())
850 };
851 if ptr.is_null() {
852 return Err(ErrorStack::drain());
853 }
854 crate::ossl_call!(sys::EVP_PKEY_encrypt_init(ptr)).map_err(|e| {
855 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
856 e
857 })?;
858 let ctx = PkeyEncryptCtx { ptr };
859 if let Some(p) = params {
860 crate::ossl_call!(sys::EVP_PKEY_CTX_set_params(ctx.ptr, p.as_ptr()))
861 .map_err(|e| { unsafe { sys::EVP_PKEY_CTX_free(ptr) }; e })?;
862 }
863 Ok(ctx)
864 }
865
866 pub fn set_params(&mut self, params: &crate::params::Params<'_>) -> Result<(), ErrorStack> {
870 crate::ossl_call!(sys::EVP_PKEY_CTX_set_params(self.ptr, params.as_ptr()))
871 }
872
873 pub fn encrypt(&mut self, plaintext: &[u8], ciphertext: &mut [u8]) -> Result<usize, ErrorStack> {
879 let mut outlen = ciphertext.len();
880 crate::ossl_call!(sys::EVP_PKEY_encrypt(
881 self.ptr,
882 ciphertext.as_mut_ptr(),
883 std::ptr::addr_of_mut!(outlen),
884 plaintext.as_ptr(),
885 plaintext.len()
886 ))?;
887 Ok(outlen)
888 }
889
890 pub fn encrypt_len(&mut self, plaintext_len: usize) -> Result<usize, ErrorStack> {
894 let mut outlen: usize = 0;
895 crate::ossl_call!(sys::EVP_PKEY_encrypt(
896 self.ptr,
897 std::ptr::null_mut(),
898 std::ptr::addr_of_mut!(outlen),
899 std::ptr::null(),
900 plaintext_len
901 ))?;
902 Ok(outlen)
903 }
904}
905
906impl Drop for PkeyEncryptCtx {
907 fn drop(&mut self) {
908 unsafe { sys::EVP_PKEY_CTX_free(self.ptr) };
909 }
910}
911
912pub struct PkeyDecryptCtx {
914 ptr: *mut sys::EVP_PKEY_CTX,
915}
916
917impl PkeyDecryptCtx {
918 pub fn new(key: &Pkey<Private>, params: Option<&crate::params::Params<'_>>) -> Result<Self, ErrorStack> {
924 let ptr = unsafe {
925 sys::EVP_PKEY_CTX_new_from_pkey(std::ptr::null_mut(), key.ptr, std::ptr::null())
926 };
927 if ptr.is_null() {
928 return Err(ErrorStack::drain());
929 }
930 crate::ossl_call!(sys::EVP_PKEY_decrypt_init(ptr)).map_err(|e| {
931 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
932 e
933 })?;
934 let ctx = PkeyDecryptCtx { ptr };
935 if let Some(p) = params {
936 crate::ossl_call!(sys::EVP_PKEY_CTX_set_params(ctx.ptr, p.as_ptr()))
937 .map_err(|e| { unsafe { sys::EVP_PKEY_CTX_free(ptr) }; e })?;
938 }
939 Ok(ctx)
940 }
941
942 pub fn set_params(&mut self, params: &crate::params::Params<'_>) -> Result<(), ErrorStack> {
946 crate::ossl_call!(sys::EVP_PKEY_CTX_set_params(self.ptr, params.as_ptr()))
947 }
948
949 pub fn decrypt(&mut self, ciphertext: &[u8], plaintext: &mut [u8]) -> Result<usize, ErrorStack> {
955 let mut outlen = plaintext.len();
956 crate::ossl_call!(sys::EVP_PKEY_decrypt(
957 self.ptr,
958 plaintext.as_mut_ptr(),
959 std::ptr::addr_of_mut!(outlen),
960 ciphertext.as_ptr(),
961 ciphertext.len()
962 ))?;
963 Ok(outlen)
964 }
965}
966
967impl Drop for PkeyDecryptCtx {
968 fn drop(&mut self) {
969 unsafe { sys::EVP_PKEY_CTX_free(self.ptr) };
970 }
971}
972
973#[cfg(ossl320)]
977pub struct EncapResult {
978 pub wrapped_key: Vec<u8>,
980 pub shared_secret: Vec<u8>,
982}
983
984#[cfg(ossl320)]
986pub struct EncapCtx {
987 ptr: *mut sys::EVP_PKEY_CTX,
988}
989
990#[cfg(ossl320)]
991impl EncapCtx {
992 pub fn new(key: &Pkey<Public>) -> Result<Self, ErrorStack> {
996 let ptr = unsafe {
997 sys::EVP_PKEY_CTX_new_from_pkey(std::ptr::null_mut(), key.ptr, std::ptr::null())
998 };
999 if ptr.is_null() {
1000 return Err(ErrorStack::drain());
1001 }
1002 crate::ossl_call!(sys::EVP_PKEY_encapsulate_init(ptr, std::ptr::null())).map_err(|e| {
1003 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
1004 e
1005 })?;
1006 Ok(EncapCtx { ptr })
1007 }
1008
1009 pub fn encapsulate(&mut self) -> Result<EncapResult, ErrorStack> {
1013 let mut wkeylen: usize = 0;
1014 let mut sslen: usize = 0;
1015 let rc = unsafe {
1017 sys::EVP_PKEY_encapsulate(
1018 self.ptr,
1019 std::ptr::null_mut(),
1020 std::ptr::addr_of_mut!(wkeylen),
1021 std::ptr::null_mut(),
1022 std::ptr::addr_of_mut!(sslen),
1023 )
1024 };
1025 if rc != 1 {
1026 return Err(ErrorStack::drain());
1027 }
1028 let mut wrapped_key = vec![0u8; wkeylen];
1029 let mut shared_secret = vec![0u8; sslen];
1030 crate::ossl_call!(sys::EVP_PKEY_encapsulate(
1031 self.ptr,
1032 wrapped_key.as_mut_ptr(),
1033 std::ptr::addr_of_mut!(wkeylen),
1034 shared_secret.as_mut_ptr(),
1035 std::ptr::addr_of_mut!(sslen)
1036 ))?;
1037 wrapped_key.truncate(wkeylen);
1038 shared_secret.truncate(sslen);
1039 Ok(EncapResult { wrapped_key, shared_secret })
1040 }
1041}
1042
1043#[cfg(ossl320)]
1044impl Drop for EncapCtx {
1045 fn drop(&mut self) {
1046 unsafe { sys::EVP_PKEY_CTX_free(self.ptr) };
1047 }
1048}
1049
1050#[cfg(ossl320)]
1052pub struct DecapCtx {
1053 ptr: *mut sys::EVP_PKEY_CTX,
1054}
1055
1056#[cfg(ossl320)]
1057impl DecapCtx {
1058 pub fn new(key: &Pkey<Private>) -> Result<Self, ErrorStack> {
1062 let ptr = unsafe {
1063 sys::EVP_PKEY_CTX_new_from_pkey(std::ptr::null_mut(), key.ptr, std::ptr::null())
1064 };
1065 if ptr.is_null() {
1066 return Err(ErrorStack::drain());
1067 }
1068 crate::ossl_call!(sys::EVP_PKEY_decapsulate_init(ptr, std::ptr::null())).map_err(|e| {
1069 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
1070 e
1071 })?;
1072 Ok(DecapCtx { ptr })
1073 }
1074
1075 pub fn decapsulate(&mut self, wrapped_key: &[u8]) -> Result<Vec<u8>, ErrorStack> {
1079 let mut sslen: usize = 0;
1080 let rc = unsafe {
1082 sys::EVP_PKEY_decapsulate(
1083 self.ptr,
1084 std::ptr::null_mut(),
1085 std::ptr::addr_of_mut!(sslen),
1086 wrapped_key.as_ptr(),
1087 wrapped_key.len(),
1088 )
1089 };
1090 if rc != 1 {
1091 return Err(ErrorStack::drain());
1092 }
1093 let mut ss = vec![0u8; sslen];
1094 crate::ossl_call!(sys::EVP_PKEY_decapsulate(
1095 self.ptr,
1096 ss.as_mut_ptr(),
1097 std::ptr::addr_of_mut!(sslen),
1098 wrapped_key.as_ptr(),
1099 wrapped_key.len()
1100 ))?;
1101 ss.truncate(sslen);
1102 Ok(ss)
1103 }
1104}
1105
1106#[cfg(ossl320)]
1107impl Drop for DecapCtx {
1108 fn drop(&mut self) {
1109 unsafe { sys::EVP_PKEY_CTX_free(self.ptr) };
1110 }
1111}
1112
1113pub struct RawSigner {
1125 ctx: *mut sys::EVP_PKEY_CTX,
1126}
1127
1128unsafe impl Send for RawSigner {}
1131
1132impl RawSigner {
1133 pub fn new(
1141 key: &Pkey<Private>,
1142 libctx: Option<&Arc<crate::lib_ctx::LibCtx>>,
1143 ) -> Result<Self, ErrorStack> {
1144 let lctx = libctx.map_or(std::ptr::null_mut(), |c| c.as_ptr());
1145 let ptr = unsafe {
1146 sys::EVP_PKEY_CTX_new_from_pkey(lctx, key.ptr, std::ptr::null())
1147 };
1148 if ptr.is_null() {
1149 return Err(ErrorStack::drain());
1150 }
1151 crate::ossl_call!(sys::EVP_PKEY_sign_init(ptr)).map_err(|e| {
1152 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
1153 e
1154 })?;
1155 Ok(RawSigner { ctx: ptr })
1156 }
1157
1158 pub fn set_params(&mut self, params: &crate::params::Params<'_>) -> Result<(), ErrorStack> {
1162 crate::ossl_call!(sys::EVP_PKEY_CTX_set_params(self.ctx, params.as_ptr()))
1163 }
1164
1165 pub fn sign_len(&mut self, tbs_len: usize) -> Result<usize, ErrorStack> {
1172 let mut siglen: usize = 0;
1173 crate::ossl_call!(sys::EVP_PKEY_sign(
1174 self.ctx,
1175 std::ptr::null_mut(),
1176 std::ptr::addr_of_mut!(siglen),
1177 std::ptr::null(),
1178 tbs_len,
1179 ))?;
1180 Ok(siglen)
1181 }
1182
1183 pub fn sign(&mut self, tbs: &[u8], sig: &mut [u8]) -> Result<usize, ErrorStack> {
1189 let mut siglen = sig.len();
1190 crate::ossl_call!(sys::EVP_PKEY_sign(
1191 self.ctx,
1192 sig.as_mut_ptr(),
1193 std::ptr::addr_of_mut!(siglen),
1194 tbs.as_ptr(),
1195 tbs.len(),
1196 ))?;
1197 Ok(siglen)
1198 }
1199
1200 pub fn sign_alloc(&mut self, tbs: &[u8]) -> Result<Vec<u8>, ErrorStack> {
1206 let siglen = self.sign_len(tbs.len())?;
1207 let mut sig = vec![0u8; siglen];
1208 let written = self.sign(tbs, &mut sig)?;
1209 sig.truncate(written);
1210 Ok(sig)
1211 }
1212}
1213
1214impl Drop for RawSigner {
1215 fn drop(&mut self) {
1216 unsafe { sys::EVP_PKEY_CTX_free(self.ctx) };
1217 }
1218}
1219
1220pub struct RawVerifier {
1227 ctx: *mut sys::EVP_PKEY_CTX,
1228}
1229
1230unsafe impl Send for RawVerifier {}
1231
1232impl RawVerifier {
1233 pub fn new<T: HasPublic>(
1237 key: &Pkey<T>,
1238 libctx: Option<&Arc<crate::lib_ctx::LibCtx>>,
1239 ) -> Result<Self, ErrorStack> {
1240 let lctx = libctx.map_or(std::ptr::null_mut(), |c| c.as_ptr());
1241 let ptr = unsafe {
1242 sys::EVP_PKEY_CTX_new_from_pkey(lctx, key.ptr, std::ptr::null())
1243 };
1244 if ptr.is_null() {
1245 return Err(ErrorStack::drain());
1246 }
1247 crate::ossl_call!(sys::EVP_PKEY_verify_init(ptr)).map_err(|e| {
1248 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
1249 e
1250 })?;
1251 Ok(RawVerifier { ctx: ptr })
1252 }
1253
1254 pub fn set_params(&mut self, params: &crate::params::Params<'_>) -> Result<(), ErrorStack> {
1258 crate::ossl_call!(sys::EVP_PKEY_CTX_set_params(self.ctx, params.as_ptr()))
1259 }
1260
1261 pub fn verify(&mut self, tbs: &[u8], sig: &[u8]) -> Result<(), ErrorStack> {
1267 crate::ossl_call!(sys::EVP_PKEY_verify(
1268 self.ctx,
1269 sig.as_ptr(),
1270 sig.len(),
1271 tbs.as_ptr(),
1272 tbs.len(),
1273 ))
1274 }
1275}
1276
1277impl Drop for RawVerifier {
1278 fn drop(&mut self) {
1279 unsafe { sys::EVP_PKEY_CTX_free(self.ctx) };
1280 }
1281}
1282
1283#[cfg(ossl320)]
1291pub struct SigAlg {
1292 ptr: *mut sys::EVP_SIGNATURE,
1293}
1294
1295#[cfg(ossl320)]
1297unsafe impl Send for SigAlg {}
1298#[cfg(ossl320)]
1299unsafe impl Sync for SigAlg {}
1300
1301#[cfg(ossl320)]
1302impl SigAlg {
1303 pub fn fetch(name: &std::ffi::CStr, props: Option<&std::ffi::CStr>) -> Result<Self, ErrorStack> {
1309 let props_ptr = props.map_or(std::ptr::null(), |p| p.as_ptr());
1310 let ptr = unsafe {
1311 sys::EVP_SIGNATURE_fetch(std::ptr::null_mut(), name.as_ptr(), props_ptr)
1312 };
1313 if ptr.is_null() {
1314 return Err(ErrorStack::drain());
1315 }
1316 Ok(SigAlg { ptr })
1317 }
1318
1319 pub fn fetch_in(
1323 ctx: &Arc<crate::lib_ctx::LibCtx>,
1324 name: &std::ffi::CStr,
1325 props: Option<&std::ffi::CStr>,
1326 ) -> Result<Self, ErrorStack> {
1327 let props_ptr = props.map_or(std::ptr::null(), |p| p.as_ptr());
1328 let ptr = unsafe {
1329 sys::EVP_SIGNATURE_fetch(ctx.as_ptr(), name.as_ptr(), props_ptr)
1330 };
1331 if ptr.is_null() {
1332 return Err(ErrorStack::drain());
1333 }
1334 Ok(SigAlg { ptr })
1335 }
1336}
1337
1338#[cfg(ossl320)]
1339impl Clone for SigAlg {
1340 fn clone(&self) -> Self {
1341 unsafe { sys::EVP_SIGNATURE_up_ref(self.ptr) };
1342 SigAlg { ptr: self.ptr }
1343 }
1344}
1345
1346#[cfg(ossl320)]
1347impl Drop for SigAlg {
1348 fn drop(&mut self) {
1349 unsafe { sys::EVP_SIGNATURE_free(self.ptr) };
1350 }
1351}
1352
1353#[cfg(ossl320)]
1366pub struct MessageSigner {
1367 ctx: *mut sys::EVP_PKEY_CTX,
1368}
1369
1370#[cfg(ossl320)]
1371unsafe impl Send for MessageSigner {}
1372
1373#[cfg(ossl320)]
1374impl MessageSigner {
1375 pub fn new(
1382 key: &Pkey<Private>,
1383 alg: &mut SigAlg,
1384 params: Option<&crate::params::Params<'_>>,
1385 ) -> Result<Self, ErrorStack> {
1386 let ptr = unsafe {
1387 sys::EVP_PKEY_CTX_new_from_pkey(std::ptr::null_mut(), key.ptr, std::ptr::null())
1388 };
1389 if ptr.is_null() {
1390 return Err(ErrorStack::drain());
1391 }
1392 let params_ptr = params.map_or(crate::params::null_params(), crate::params::Params::as_ptr);
1393 crate::ossl_call!(sys::EVP_PKEY_sign_message_init(ptr, alg.ptr, params_ptr))
1394 .map_err(|e| {
1395 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
1396 e
1397 })?;
1398 Ok(MessageSigner { ctx: ptr })
1399 }
1400
1401 pub fn supports_streaming(&mut self) -> bool {
1409 unsafe { sys::ERR_set_mark() };
1412 let probe: [u8; 0] = [];
1413 let rc = unsafe {
1414 sys::EVP_PKEY_sign_message_update(self.ctx, probe.as_ptr(), 0)
1415 };
1416 unsafe { sys::ERR_pop_to_mark() };
1417 rc == 1
1418 }
1419
1420 pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
1427 crate::ossl_call!(sys::EVP_PKEY_sign_message_update(
1428 self.ctx,
1429 data.as_ptr(),
1430 data.len(),
1431 ))
1432 }
1433
1434 pub fn sig_len(&mut self) -> Result<usize, ErrorStack> {
1441 let mut siglen: usize = 0;
1442 crate::ossl_call!(sys::EVP_PKEY_sign_message_final(
1443 self.ctx,
1444 std::ptr::null_mut(),
1445 std::ptr::addr_of_mut!(siglen),
1446 ))?;
1447 Ok(siglen)
1448 }
1449
1450 pub fn finish(self, sig: &mut [u8]) -> Result<usize, ErrorStack> {
1458 let mut siglen = sig.len();
1459 let rc = unsafe {
1460 sys::EVP_PKEY_sign_message_final(
1461 self.ctx,
1462 sig.as_mut_ptr(),
1463 std::ptr::addr_of_mut!(siglen),
1464 )
1465 };
1466 if rc != 1 {
1468 return Err(ErrorStack::drain());
1469 }
1470 Ok(siglen)
1471 }
1472
1473 pub fn sign_oneshot(self, data: &[u8], sig: &mut [u8]) -> Result<usize, ErrorStack> {
1480 let rc_upd = unsafe {
1482 sys::EVP_PKEY_sign_message_update(self.ctx, data.as_ptr(), data.len())
1483 };
1484 if rc_upd != 1 {
1485 return Err(ErrorStack::drain());
1487 }
1488 let mut siglen = sig.len();
1489 let rc_fin = unsafe {
1490 sys::EVP_PKEY_sign_message_final(
1491 self.ctx,
1492 sig.as_mut_ptr(),
1493 std::ptr::addr_of_mut!(siglen),
1494 )
1495 };
1496 if rc_fin != 1 {
1498 return Err(ErrorStack::drain());
1499 }
1500 Ok(siglen)
1501 }
1502}
1503
1504#[cfg(ossl320)]
1505impl Drop for MessageSigner {
1506 fn drop(&mut self) {
1507 unsafe { sys::EVP_PKEY_CTX_free(self.ctx) };
1508 }
1509}
1510
1511#[cfg(ossl320)]
1521pub struct MessageVerifier {
1522 ctx: *mut sys::EVP_PKEY_CTX,
1523}
1524
1525#[cfg(ossl320)]
1526unsafe impl Send for MessageVerifier {}
1527
1528#[cfg(ossl320)]
1529impl MessageVerifier {
1530 pub fn new<T: HasPublic>(
1534 key: &Pkey<T>,
1535 alg: &mut SigAlg,
1536 params: Option<&crate::params::Params<'_>>,
1537 ) -> Result<Self, ErrorStack> {
1538 let ptr = unsafe {
1539 sys::EVP_PKEY_CTX_new_from_pkey(std::ptr::null_mut(), key.ptr, std::ptr::null())
1540 };
1541 if ptr.is_null() {
1542 return Err(ErrorStack::drain());
1543 }
1544 let params_ptr = params.map_or(crate::params::null_params(), crate::params::Params::as_ptr);
1545 crate::ossl_call!(sys::EVP_PKEY_verify_message_init(ptr, alg.ptr, params_ptr))
1546 .map_err(|e| {
1547 unsafe { sys::EVP_PKEY_CTX_free(ptr) };
1548 e
1549 })?;
1550 Ok(MessageVerifier { ctx: ptr })
1551 }
1552
1553 pub fn set_params(&mut self, params: &crate::params::Params<'_>) -> Result<(), ErrorStack> {
1557 crate::ossl_call!(sys::EVP_PKEY_CTX_set_params(self.ctx, params.as_ptr()))
1558 }
1559
1560 pub fn set_signature(&mut self, sig: &[u8]) -> Result<(), ErrorStack> {
1567 crate::ossl_call!(sys::EVP_PKEY_CTX_set_signature(self.ctx, sig.as_ptr(), sig.len()))
1568 }
1569
1570 pub fn supports_streaming(&mut self) -> bool {
1575 unsafe { sys::ERR_set_mark() };
1576 let probe: [u8; 0] = [];
1577 let rc = unsafe {
1578 sys::EVP_PKEY_verify_message_update(self.ctx, probe.as_ptr(), 0)
1579 };
1580 unsafe { sys::ERR_pop_to_mark() };
1581 rc == 1
1582 }
1583
1584 pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
1588 crate::ossl_call!(sys::EVP_PKEY_verify_message_update(
1589 self.ctx,
1590 data.as_ptr(),
1591 data.len(),
1592 ))
1593 }
1594
1595 pub fn finish(self) -> Result<(), ErrorStack> {
1602 let rc = unsafe { sys::EVP_PKEY_verify_message_final(self.ctx) };
1603 if rc != 1 {
1605 return Err(ErrorStack::drain());
1606 }
1607 Ok(())
1608 }
1609
1610 pub fn verify_oneshot(self, data: &[u8], sig: &[u8]) -> Result<(), ErrorStack> {
1616 let rc_set = unsafe {
1617 sys::EVP_PKEY_CTX_set_signature(self.ctx, sig.as_ptr(), sig.len())
1618 };
1619 if rc_set != 1 {
1620 return Err(ErrorStack::drain());
1621 }
1622 let rc_upd = unsafe {
1623 sys::EVP_PKEY_verify_message_update(self.ctx, data.as_ptr(), data.len())
1624 };
1625 if rc_upd != 1 {
1626 return Err(ErrorStack::drain());
1627 }
1628 let rc_fin = unsafe { sys::EVP_PKEY_verify_message_final(self.ctx) };
1629 if rc_fin != 1 {
1631 return Err(ErrorStack::drain());
1632 }
1633 Ok(())
1634 }
1635}
1636
1637#[cfg(ossl320)]
1638impl Drop for MessageVerifier {
1639 fn drop(&mut self) {
1640 unsafe { sys::EVP_PKEY_CTX_free(self.ctx) };
1641 }
1642}
1643
1644#[cfg(test)]
1647mod tests {
1648 use super::*;
1649
1650 #[test]
1654 fn ed25519_sign_verify() {
1655 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
1656 let priv_key = kgen.generate().unwrap();
1657 let pub_key = Pkey::<Public>::from(priv_key.clone());
1658
1659 let msg = b"hello world";
1660 let init = SignInit::default();
1661
1662 let mut signer = Signer::new(&priv_key, &init).unwrap();
1663 let sig = signer.sign_oneshot(msg).unwrap();
1664 assert!(!sig.is_empty());
1665
1666 let mut verifier = Verifier::new(&pub_key, &init).unwrap();
1667 assert!(verifier.verify_oneshot(msg, &sig).unwrap());
1668 }
1669
1670 #[test]
1672 fn ed25519_verify_wrong_msg_fails() {
1673 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
1674 let priv_key = kgen.generate().unwrap();
1675 let pub_key = Pkey::<Public>::from(priv_key.clone());
1676
1677 let mut signer = Signer::new(&priv_key, &SignInit::default()).unwrap();
1678 let sig = signer.sign_oneshot(b"correct").unwrap();
1679
1680 let mut verifier = Verifier::new(&pub_key, &SignInit::default()).unwrap();
1681 assert!(!verifier.verify_oneshot(b"tampered", &sig).unwrap());
1682 }
1683
1684 #[test]
1686 fn x25519_derive() {
1687 let mut kgen_a = KeygenCtx::new(c"X25519").unwrap();
1688 let priv_a = kgen_a.generate().unwrap();
1689
1690 let mut kgen_b = KeygenCtx::new(c"X25519").unwrap();
1691 let priv_b = kgen_b.generate().unwrap();
1692 let pub_b = Pkey::<Public>::from(priv_b);
1693
1694 let mut derive = DeriveCtx::new(&priv_a).unwrap();
1695 derive.set_peer(&pub_b).unwrap();
1696 let len = derive.derive_len().unwrap();
1697 assert_eq!(len, 32); let mut ss = vec![0u8; len];
1700 let n = derive.derive(&mut ss).unwrap();
1701 assert_eq!(n, 32);
1702 assert_ne!(ss, [0u8; 32]);
1703 }
1704
1705 #[test]
1707 fn pem_round_trip() {
1708 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
1709 let priv_key = kgen.generate().unwrap();
1710
1711 let pem = priv_key.to_pem().unwrap();
1712 assert!(!pem.is_empty());
1713 assert!(pem.starts_with(b"-----BEGIN"));
1714
1715 let priv_key2 = Pkey::<Private>::from_pem(&pem).unwrap();
1716 assert_eq!(priv_key.bits(), priv_key2.bits());
1717 assert!(priv_key.is_a(c"ED25519"));
1718 }
1719
1720 #[test]
1722 fn ed25519_metadata() {
1723 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
1724 let key = kgen.generate().unwrap();
1725 assert_eq!(key.bits(), 256);
1726 assert_eq!(key.security_bits(), 128);
1727 assert!(key.is_a(c"ED25519"));
1728 }
1729
1730 #[test]
1732 fn ecdsa_p256_raw_sign_verify() {
1733 let mut kgen = KeygenCtx::new(c"EC").unwrap();
1735 let params = crate::params::ParamBuilder::new().unwrap()
1736 .push_utf8_string(c"group", c"P-256").unwrap()
1737 .build().unwrap();
1738 kgen.set_params(¶ms).unwrap();
1739 let priv_key = kgen.generate().unwrap();
1740 let pub_key = Pkey::<Public>::from(priv_key.clone());
1741
1742 let tbs: [u8; 32] = *b"0123456789abcdef0123456789abcdef";
1744
1745 let mut signer = RawSigner::new(&priv_key, None).unwrap();
1746 let sig = signer.sign_alloc(&tbs).unwrap();
1747 assert!(!sig.is_empty());
1748
1749 let mut verifier = RawVerifier::new(&pub_key, None).unwrap();
1750 verifier.verify(&tbs, &sig).unwrap();
1751 }
1752
1753 #[test]
1755 fn ecdsa_p256_raw_verify_tampered_fails() {
1756 let mut kgen = KeygenCtx::new(c"EC").unwrap();
1757 let params = crate::params::ParamBuilder::new().unwrap()
1758 .push_utf8_string(c"group", c"P-256").unwrap()
1759 .build().unwrap();
1760 kgen.set_params(¶ms).unwrap();
1761 let priv_key = kgen.generate().unwrap();
1762 let pub_key = Pkey::<Public>::from(priv_key.clone());
1763
1764 let tbs: [u8; 32] = *b"0123456789abcdef0123456789abcdef";
1765 let mut signer = RawSigner::new(&priv_key, None).unwrap();
1766 let mut sig = signer.sign_alloc(&tbs).unwrap();
1767 if let Some(b) = sig.last_mut() { *b ^= 0xff; }
1769
1770 let mut verifier = RawVerifier::new(&pub_key, None).unwrap();
1771 assert!(verifier.verify(&tbs, &sig).is_err());
1772 }
1773
1774 #[cfg(ossl320)]
1781 #[test]
1782 fn sig_alg_fetch_clone_drop() {
1783 let alg = SigAlg::fetch(c"ML-DSA-44", None).unwrap();
1784 let alg2 = alg.clone();
1785 drop(alg);
1786 drop(alg2); }
1788
1789 #[cfg(ossl320)]
1794 #[test]
1795 fn message_signer_construction_and_streaming_probe() {
1796 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
1797 let priv_key = kgen.generate().unwrap();
1798
1799 let mut alg = SigAlg::fetch(c"ED25519", None).unwrap();
1800 let mut signer = MessageSigner::new(&priv_key, &mut alg, None).unwrap();
1801
1802 let _streaming = signer.supports_streaming();
1804 assert_eq!(crate::error::ErrorStack::drain().errors().count(), 0);
1806 }
1807
1808 #[cfg(ossl320)]
1810 #[test]
1811 fn message_verifier_construction() {
1812 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
1813 let priv_key = kgen.generate().unwrap();
1814 let pub_key = Pkey::<Public>::from(priv_key.clone());
1815
1816 let mut alg = SigAlg::fetch(c"ED25519", None).unwrap();
1817 let _verifier = MessageVerifier::new(&pub_key, &mut alg, None).unwrap();
1818 }
1819
1820 #[test]
1822 fn pubkey_from_pem_in_roundtrip() {
1823 let mut kgen = KeygenCtx::new(c"ED25519").unwrap();
1825 let priv_key = kgen.generate().unwrap();
1826 let pub_pem = Pkey::<Public>::from(priv_key).to_pem().unwrap();
1827
1828 let lib_ctx = Arc::new(crate::lib_ctx::LibCtx::new().unwrap());
1830 let pub_key = Pkey::<Public>::from_pem_in(&lib_ctx, &pub_pem).unwrap();
1831
1832 assert!(!pub_key.to_pem().unwrap().is_empty());
1834 }
1835}