1#![allow(clippy::missing_safety_doc)]
43use crate::bio::{MemBio, MemBioSlice};
44#[cfg(ossl110)]
45use crate::cipher::CipherRef;
46use crate::dh::Dh;
47use crate::dsa::Dsa;
48use crate::ec::EcKey;
49use crate::error::ErrorStack;
50#[cfg(any(ossl110, boringssl, libressl370, awslc))]
51use crate::pkey_ctx::PkeyCtx;
52use crate::rsa::Rsa;
53use crate::symm::Cipher;
54use crate::util::{invoke_passwd_cb, CallbackState};
55use crate::{cvt, cvt_p};
56use cfg_if::cfg_if;
57use foreign_types::{ForeignType, ForeignTypeRef};
58use libc::{c_int, c_long};
59use openssl_macros::corresponds;
60use std::convert::{TryFrom, TryInto};
61use std::ffi::CString;
62use std::fmt;
63#[cfg(all(not(any(boringssl, awslc)), ossl110))]
64use std::mem;
65use std::ptr;
66
67pub enum Params {}
69
70pub enum Public {}
72
73pub enum Private {}
75
76#[derive(Debug, Copy, Clone, PartialEq, Eq)]
78pub struct Id(c_int);
79
80impl Id {
81 pub const RSA: Id = Id(ffi::EVP_PKEY_RSA);
82 #[cfg(any(ossl111, libressl310, boringssl, awslc))]
83 pub const RSA_PSS: Id = Id(ffi::EVP_PKEY_RSA_PSS);
84 #[cfg(not(boringssl))]
85 pub const HMAC: Id = Id(ffi::EVP_PKEY_HMAC);
86 #[cfg(not(any(boringssl, awslc)))]
87 pub const CMAC: Id = Id(ffi::EVP_PKEY_CMAC);
88 pub const DSA: Id = Id(ffi::EVP_PKEY_DSA);
89 pub const DH: Id = Id(ffi::EVP_PKEY_DH);
90 #[cfg(ossl110)]
91 pub const DHX: Id = Id(ffi::EVP_PKEY_DHX);
92 pub const EC: Id = Id(ffi::EVP_PKEY_EC);
93 #[cfg(ossl111)]
94 pub const SM2: Id = Id(ffi::EVP_PKEY_SM2);
95
96 #[cfg(any(ossl110, boringssl, libressl360, awslc))]
97 pub const HKDF: Id = Id(ffi::EVP_PKEY_HKDF);
98
99 #[cfg(any(ossl111, boringssl, libressl370, awslc))]
100 pub const ED25519: Id = Id(ffi::EVP_PKEY_ED25519);
101 #[cfg(ossl111)]
102 pub const ED448: Id = Id(ffi::EVP_PKEY_ED448);
103 #[cfg(any(ossl111, boringssl, libressl370, awslc))]
104 pub const X25519: Id = Id(ffi::EVP_PKEY_X25519);
105 #[cfg(ossl111)]
106 pub const X448: Id = Id(ffi::EVP_PKEY_X448);
107 #[cfg(ossl111)]
108 pub const POLY1305: Id = Id(ffi::EVP_PKEY_POLY1305);
109
110 pub fn from_raw(value: c_int) -> Id {
112 Id(value)
113 }
114
115 #[allow(clippy::trivially_copy_pass_by_ref)]
117 pub fn as_raw(&self) -> c_int {
118 self.0
119 }
120}
121
122pub unsafe trait HasParams {}
124
125unsafe impl HasParams for Params {}
126
127unsafe impl<T> HasParams for T where T: HasPublic {}
128
129pub unsafe trait HasPublic {}
131
132unsafe impl HasPublic for Public {}
133
134unsafe impl<T> HasPublic for T where T: HasPrivate {}
135
136pub unsafe trait HasPrivate {}
138
139unsafe impl HasPrivate for Private {}
140
141generic_foreign_type_and_impl_send_sync! {
142 type CType = ffi::EVP_PKEY;
143 fn drop = ffi::EVP_PKEY_free;
144
145 pub struct PKey<T>;
147 pub struct PKeyRef<T>;
149}
150
151impl<T> ToOwned for PKeyRef<T> {
152 type Owned = PKey<T>;
153
154 fn to_owned(&self) -> PKey<T> {
155 unsafe {
156 EVP_PKEY_up_ref(self.as_ptr());
157 PKey::from_ptr(self.as_ptr())
158 }
159 }
160}
161
162impl<T> PKeyRef<T> {
163 #[corresponds(EVP_PKEY_get1_RSA)]
165 pub fn rsa(&self) -> Result<Rsa<T>, ErrorStack> {
166 unsafe {
167 let rsa = cvt_p(ffi::EVP_PKEY_get1_RSA(self.as_ptr()))?;
168 Ok(Rsa::from_ptr(rsa))
169 }
170 }
171
172 #[corresponds(EVP_PKEY_get1_DSA)]
174 pub fn dsa(&self) -> Result<Dsa<T>, ErrorStack> {
175 unsafe {
176 let dsa = cvt_p(ffi::EVP_PKEY_get1_DSA(self.as_ptr()))?;
177 Ok(Dsa::from_ptr(dsa))
178 }
179 }
180
181 #[corresponds(EVP_PKEY_get1_DH)]
183 pub fn dh(&self) -> Result<Dh<T>, ErrorStack> {
184 unsafe {
185 let dh = cvt_p(ffi::EVP_PKEY_get1_DH(self.as_ptr()))?;
186 Ok(Dh::from_ptr(dh))
187 }
188 }
189
190 #[corresponds(EVP_PKEY_get1_EC_KEY)]
192 pub fn ec_key(&self) -> Result<EcKey<T>, ErrorStack> {
193 unsafe {
194 let ec_key = cvt_p(ffi::EVP_PKEY_get1_EC_KEY(self.as_ptr()))?;
195 Ok(EcKey::from_ptr(ec_key))
196 }
197 }
198
199 #[corresponds(EVP_PKEY_id)]
201 pub fn id(&self) -> Id {
202 unsafe { Id::from_raw(ffi::EVP_PKEY_id(self.as_ptr())) }
203 }
204
205 #[corresponds(EVP_PKEY_size)]
207 pub fn size(&self) -> usize {
208 unsafe { ffi::EVP_PKEY_size(self.as_ptr()) as usize }
209 }
210}
211
212impl<T> PKeyRef<T>
213where
214 T: HasPublic,
215{
216 to_pem! {
217 #[corresponds(PEM_write_bio_PUBKEY)]
221 public_key_to_pem,
222 ffi::PEM_write_bio_PUBKEY
223 }
224
225 to_der! {
226 #[corresponds(i2d_PUBKEY)]
228 public_key_to_der,
229 ffi::i2d_PUBKEY
230 }
231
232 #[corresponds(EVP_PKEY_bits)]
237 pub fn bits(&self) -> u32 {
238 unsafe { ffi::EVP_PKEY_bits(self.as_ptr()) as u32 }
239 }
240
241 #[corresponds(EVP_PKEY_security_bits)]
245 #[cfg(any(ossl110, libressl360))]
246 pub fn security_bits(&self) -> u32 {
247 unsafe { ffi::EVP_PKEY_security_bits(self.as_ptr()) as u32 }
248 }
249
250 #[corresponds(EVP_PKEY_cmp)]
252 pub fn public_eq<U>(&self, other: &PKeyRef<U>) -> bool
253 where
254 U: HasPublic,
255 {
256 let res = unsafe { ffi::EVP_PKEY_cmp(self.as_ptr(), other.as_ptr()) == 1 };
257 let _ = ErrorStack::get();
260 res
261 }
262
263 #[corresponds(EVP_PKEY_get_raw_public_key)]
268 #[cfg(any(ossl111, boringssl, libressl370, awslc))]
269 pub fn raw_public_key(&self) -> Result<Vec<u8>, ErrorStack> {
270 unsafe {
271 let mut len = 0;
272 cvt(ffi::EVP_PKEY_get_raw_public_key(
273 self.as_ptr(),
274 ptr::null_mut(),
275 &mut len,
276 ))?;
277 let mut buf = vec![0u8; len];
278 cvt(ffi::EVP_PKEY_get_raw_public_key(
279 self.as_ptr(),
280 buf.as_mut_ptr(),
281 &mut len,
282 ))?;
283 buf.truncate(len);
284 Ok(buf)
285 }
286 }
287}
288
289impl<T> PKeyRef<T>
290where
291 T: HasPrivate,
292{
293 private_key_to_pem! {
294 #[corresponds(PEM_write_bio_PKCS8PrivateKey)]
298 private_key_to_pem_pkcs8,
299 #[corresponds(PEM_write_bio_PKCS8PrivateKey)]
303 private_key_to_pem_pkcs8_passphrase,
304 ffi::PEM_write_bio_PKCS8PrivateKey
305 }
306
307 to_der! {
308 #[corresponds(i2d_PrivateKey)]
310 private_key_to_der,
311 ffi::i2d_PrivateKey
312 }
313
314 #[corresponds(EVP_PKEY_get_raw_private_key)]
319 #[cfg(any(ossl111, boringssl, libressl370, awslc))]
320 pub fn raw_private_key(&self) -> Result<Vec<u8>, ErrorStack> {
321 unsafe {
322 let mut len = 0;
323 cvt(ffi::EVP_PKEY_get_raw_private_key(
324 self.as_ptr(),
325 ptr::null_mut(),
326 &mut len,
327 ))?;
328 let mut buf = vec![0u8; len];
329 cvt(ffi::EVP_PKEY_get_raw_private_key(
330 self.as_ptr(),
331 buf.as_mut_ptr(),
332 &mut len,
333 ))?;
334 buf.truncate(len);
335 Ok(buf)
336 }
337 }
338
339 #[corresponds(i2d_PKCS8PrivateKey_bio)]
341 pub fn private_key_to_pkcs8(&self) -> Result<Vec<u8>, ErrorStack> {
342 unsafe {
343 let bio = MemBio::new()?;
344 cvt(ffi::i2d_PKCS8PrivateKey_bio(
345 bio.as_ptr(),
346 self.as_ptr(),
347 ptr::null(),
348 ptr::null_mut(),
349 0,
350 None,
351 ptr::null_mut(),
352 ))?;
353
354 Ok(bio.get_buf().to_owned())
355 }
356 }
357
358 #[corresponds(i2d_PKCS8PrivateKey_bio)]
361 pub fn private_key_to_pkcs8_passphrase(
362 &self,
363 cipher: Cipher,
364 passphrase: &[u8],
365 ) -> Result<Vec<u8>, ErrorStack> {
366 unsafe {
367 let bio = MemBio::new()?;
368 cvt(ffi::i2d_PKCS8PrivateKey_bio(
369 bio.as_ptr(),
370 self.as_ptr(),
371 cipher.as_ptr(),
372 passphrase.as_ptr() as *const _ as *mut _,
373 passphrase.len().try_into().unwrap(),
374 None,
375 ptr::null_mut(),
376 ))?;
377
378 Ok(bio.get_buf().to_owned())
379 }
380 }
381}
382
383impl<T> fmt::Debug for PKey<T> {
384 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
385 let alg = match self.id() {
386 Id::RSA => "RSA",
387 #[cfg(any(ossl111, libressl310, boringssl, awslc))]
388 Id::RSA_PSS => "RSA-PSS",
389 #[cfg(not(boringssl))]
390 Id::HMAC => "HMAC",
391 #[cfg(not(any(boringssl, awslc)))]
392 Id::CMAC => "CMAC",
393 Id::DSA => "DSA",
394 Id::DH => "DH",
395 #[cfg(ossl110)]
396 Id::DHX => "DHX",
397 Id::EC => "EC",
398 #[cfg(ossl111)]
399 Id::SM2 => "SM2",
400 #[cfg(any(ossl110, boringssl, libressl360, awslc))]
401 Id::HKDF => "HKDF",
402 #[cfg(any(ossl111, boringssl, libressl370, awslc))]
403 Id::ED25519 => "Ed25519",
404 #[cfg(ossl111)]
405 Id::ED448 => "Ed448",
406 #[cfg(any(ossl111, boringssl, libressl370, awslc))]
407 Id::X25519 => "X25519",
408 #[cfg(ossl111)]
409 Id::X448 => "X448",
410 #[cfg(ossl111)]
411 Id::POLY1305 => "POLY1305",
412 _ => "unknown",
413 };
414 fmt.debug_struct("PKey").field("algorithm", &alg).finish()
415 }
417}
418
419impl<T> Clone for PKey<T> {
420 fn clone(&self) -> PKey<T> {
421 PKeyRef::to_owned(self)
422 }
423}
424
425impl<T> PKey<T> {
426 #[corresponds(EVP_PKEY_set1_RSA)]
428 pub fn from_rsa(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> {
429 unsafe {
432 let evp = cvt_p(ffi::EVP_PKEY_new())?;
433 let pkey = PKey::from_ptr(evp);
434 cvt(ffi::EVP_PKEY_set1_RSA(pkey.0, rsa.as_ptr()))?;
435 Ok(pkey)
436 }
437 }
438
439 #[corresponds(EVP_PKEY_set1_DSA)]
441 pub fn from_dsa(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> {
442 unsafe {
443 let evp = cvt_p(ffi::EVP_PKEY_new())?;
444 let pkey = PKey::from_ptr(evp);
445 cvt(ffi::EVP_PKEY_set1_DSA(pkey.0, dsa.as_ptr()))?;
446 Ok(pkey)
447 }
448 }
449
450 #[corresponds(EVP_PKEY_set1_DH)]
452 #[cfg(not(boringssl))]
453 pub fn from_dh(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
454 unsafe {
455 let evp = cvt_p(ffi::EVP_PKEY_new())?;
456 let pkey = PKey::from_ptr(evp);
457 cvt(ffi::EVP_PKEY_set1_DH(pkey.0, dh.as_ptr()))?;
458 Ok(pkey)
459 }
460 }
461
462 #[cfg(all(not(any(boringssl, awslc)), ossl110))]
464 pub fn from_dhx(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
465 unsafe {
466 let evp = cvt_p(ffi::EVP_PKEY_new())?;
467 let pkey = PKey::from_ptr(evp);
468 cvt(ffi::EVP_PKEY_assign(
469 pkey.0,
470 ffi::EVP_PKEY_DHX,
471 dh.as_ptr().cast(),
472 ))?;
473 mem::forget(dh);
474 Ok(pkey)
475 }
476 }
477
478 #[corresponds(EVP_PKEY_set1_EC_KEY)]
480 pub fn from_ec_key(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> {
481 unsafe {
482 let evp = cvt_p(ffi::EVP_PKEY_new())?;
483 let pkey = PKey::from_ptr(evp);
484 cvt(ffi::EVP_PKEY_set1_EC_KEY(pkey.0, ec_key.as_ptr()))?;
485 Ok(pkey)
486 }
487 }
488}
489
490impl PKey<Private> {
491 #[corresponds(EVP_PKEY_new_mac_key)]
497 #[cfg(not(boringssl))]
498 pub fn hmac(key: &[u8]) -> Result<PKey<Private>, ErrorStack> {
499 #[cfg(awslc)]
500 let key_len = key.len();
501 #[cfg(not(awslc))]
502 let key_len = key.len() as c_int;
503 unsafe {
504 assert!(key.len() <= c_int::MAX as usize);
505 let key = cvt_p(ffi::EVP_PKEY_new_mac_key(
506 ffi::EVP_PKEY_HMAC,
507 ptr::null_mut(),
508 key.as_ptr() as *const _,
509 key_len,
510 ))?;
511 Ok(PKey::from_ptr(key))
512 }
513 }
514
515 #[cfg(all(not(any(boringssl, awslc)), ossl110))]
523 #[allow(clippy::trivially_copy_pass_by_ref)]
524 pub fn cmac(cipher: &Cipher, key: &[u8]) -> Result<PKey<Private>, ErrorStack> {
525 let mut ctx = PkeyCtx::new_id(Id::CMAC)?;
526 ctx.keygen_init()?;
527 ctx.set_keygen_cipher(unsafe { CipherRef::from_ptr(cipher.as_ptr() as *mut _) })?;
528 ctx.set_keygen_mac_key(key)?;
529 ctx.keygen()
530 }
531
532 #[cfg(any(ossl111, boringssl, libressl370, awslc))]
533 fn generate_eddsa(id: Id) -> Result<PKey<Private>, ErrorStack> {
534 let mut ctx = PkeyCtx::new_id(id)?;
535 ctx.keygen_init()?;
536 ctx.keygen()
537 }
538
539 #[cfg(any(ossl111, boringssl, libressl370, awslc))]
563 pub fn generate_x25519() -> Result<PKey<Private>, ErrorStack> {
564 PKey::generate_eddsa(Id::X25519)
565 }
566
567 #[cfg(ossl111)]
591 pub fn generate_x448() -> Result<PKey<Private>, ErrorStack> {
592 PKey::generate_eddsa(Id::X448)
593 }
594
595 #[cfg(any(ossl111, boringssl, libressl370, awslc))]
617 pub fn generate_ed25519() -> Result<PKey<Private>, ErrorStack> {
618 PKey::generate_eddsa(Id::ED25519)
619 }
620
621 #[cfg(ossl111)]
643 pub fn generate_ed448() -> Result<PKey<Private>, ErrorStack> {
644 PKey::generate_eddsa(Id::ED448)
645 }
646
647 #[corresponds(EVP_EC_gen)]
651 #[cfg(ossl300)]
652 pub fn ec_gen(curve: &str) -> Result<PKey<Private>, ErrorStack> {
653 ffi::init();
654
655 let curve = CString::new(curve).unwrap();
656 unsafe {
657 let ptr = cvt_p(ffi::EVP_EC_gen(curve.as_ptr()))?;
658 Ok(PKey::from_ptr(ptr))
659 }
660 }
661
662 private_key_from_pem! {
663 #[corresponds(PEM_read_bio_PrivateKey)]
665 private_key_from_pem,
666
667 #[corresponds(PEM_read_bio_PrivateKey)]
669 private_key_from_pem_passphrase,
670
671 #[corresponds(PEM_read_bio_PrivateKey)]
675 private_key_from_pem_callback,
676 PKey<Private>,
677 ffi::PEM_read_bio_PrivateKey
678 }
679
680 from_der! {
681 #[corresponds(d2i_AutoPrivateKey)]
687 private_key_from_der,
688 PKey<Private>,
689 ffi::d2i_AutoPrivateKey
690 }
691
692 pub fn private_key_from_pkcs8(der: &[u8]) -> Result<PKey<Private>, ErrorStack> {
696 unsafe {
697 ffi::init();
698 let len = der.len().min(c_long::MAX as usize) as c_long;
699 let p8inf = cvt_p(ffi::d2i_PKCS8_PRIV_KEY_INFO(
700 ptr::null_mut(),
701 &mut der.as_ptr(),
702 len,
703 ))?;
704 let res = cvt_p(ffi::EVP_PKCS82PKEY(p8inf)).map(|p| PKey::from_ptr(p));
705 ffi::PKCS8_PRIV_KEY_INFO_free(p8inf);
706 res
707 }
708 }
709
710 #[corresponds(d2i_PKCS8PrivateKey_bio)]
716 pub fn private_key_from_pkcs8_callback<F>(
717 der: &[u8],
718 callback: F,
719 ) -> Result<PKey<Private>, ErrorStack>
720 where
721 F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,
722 {
723 unsafe {
724 ffi::init();
725 let mut cb = CallbackState::new(callback);
726 let bio = MemBioSlice::new(der)?;
727 cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
728 bio.as_ptr(),
729 ptr::null_mut(),
730 Some(invoke_passwd_cb::<F>),
731 &mut cb as *mut _ as *mut _,
732 ))
733 .map(|p| PKey::from_ptr(p))
734 }
735 }
736
737 #[corresponds(d2i_PKCS8PrivateKey_bio)]
744 pub fn private_key_from_pkcs8_passphrase(
745 der: &[u8],
746 passphrase: &[u8],
747 ) -> Result<PKey<Private>, ErrorStack> {
748 unsafe {
749 ffi::init();
750 let bio = MemBioSlice::new(der)?;
751 let passphrase = CString::new(passphrase).unwrap();
752 cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
753 bio.as_ptr(),
754 ptr::null_mut(),
755 None,
756 passphrase.as_ptr() as *const _ as *mut _,
757 ))
758 .map(|p| PKey::from_ptr(p))
759 }
760 }
761
762 #[corresponds(EVP_PKEY_new_raw_private_key)]
766 #[cfg(any(ossl111, boringssl, libressl370, awslc))]
767 pub fn private_key_from_raw_bytes(
768 bytes: &[u8],
769 key_type: Id,
770 ) -> Result<PKey<Private>, ErrorStack> {
771 unsafe {
772 ffi::init();
773 cvt_p(ffi::EVP_PKEY_new_raw_private_key(
774 key_type.as_raw(),
775 ptr::null_mut(),
776 bytes.as_ptr(),
777 bytes.len(),
778 ))
779 .map(|p| PKey::from_ptr(p))
780 }
781 }
782}
783
784impl PKey<Public> {
785 private_key_from_pem! {
786 #[corresponds(PEM_read_bio_PUBKEY)]
790 public_key_from_pem,
791
792 #[corresponds(PEM_read_bio_PUBKEY)]
794 public_key_from_pem_passphrase,
795
796 #[corresponds(PEM_read_bio_PrivateKey)]
800 public_key_from_pem_callback,
801 PKey<Public>,
802 ffi::PEM_read_bio_PUBKEY
803 }
804
805 from_der! {
806 #[corresponds(d2i_PUBKEY)]
808 public_key_from_der,
809 PKey<Public>,
810 ffi::d2i_PUBKEY
811 }
812
813 #[corresponds(EVP_PKEY_new_raw_public_key)]
817 #[cfg(any(ossl111, boringssl, libressl370, awslc))]
818 pub fn public_key_from_raw_bytes(
819 bytes: &[u8],
820 key_type: Id,
821 ) -> Result<PKey<Public>, ErrorStack> {
822 unsafe {
823 ffi::init();
824 cvt_p(ffi::EVP_PKEY_new_raw_public_key(
825 key_type.as_raw(),
826 ptr::null_mut(),
827 bytes.as_ptr(),
828 bytes.len(),
829 ))
830 .map(|p| PKey::from_ptr(p))
831 }
832 }
833}
834
835cfg_if! {
836 if #[cfg(any(boringssl, ossl110, libressl270, awslc))] {
837 use ffi::EVP_PKEY_up_ref;
838 } else {
839 #[allow(bad_style)]
840 unsafe extern "C" fn EVP_PKEY_up_ref(pkey: *mut ffi::EVP_PKEY) {
841 ffi::CRYPTO_add_lock(
842 &mut (*pkey).references,
843 1,
844 ffi::CRYPTO_LOCK_EVP_PKEY,
845 "pkey.rs\0".as_ptr() as *const _,
846 line!() as c_int,
847 );
848 }
849 }
850}
851
852impl<T> TryFrom<EcKey<T>> for PKey<T> {
853 type Error = ErrorStack;
854
855 fn try_from(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> {
856 PKey::from_ec_key(ec_key)
857 }
858}
859
860impl<T> TryFrom<PKey<T>> for EcKey<T> {
861 type Error = ErrorStack;
862
863 fn try_from(pkey: PKey<T>) -> Result<EcKey<T>, ErrorStack> {
864 pkey.ec_key()
865 }
866}
867
868impl<T> TryFrom<Rsa<T>> for PKey<T> {
869 type Error = ErrorStack;
870
871 fn try_from(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> {
872 PKey::from_rsa(rsa)
873 }
874}
875
876impl<T> TryFrom<PKey<T>> for Rsa<T> {
877 type Error = ErrorStack;
878
879 fn try_from(pkey: PKey<T>) -> Result<Rsa<T>, ErrorStack> {
880 pkey.rsa()
881 }
882}
883
884impl<T> TryFrom<Dsa<T>> for PKey<T> {
885 type Error = ErrorStack;
886
887 fn try_from(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> {
888 PKey::from_dsa(dsa)
889 }
890}
891
892impl<T> TryFrom<PKey<T>> for Dsa<T> {
893 type Error = ErrorStack;
894
895 fn try_from(pkey: PKey<T>) -> Result<Dsa<T>, ErrorStack> {
896 pkey.dsa()
897 }
898}
899
900#[cfg(not(boringssl))]
901impl<T> TryFrom<Dh<T>> for PKey<T> {
902 type Error = ErrorStack;
903
904 fn try_from(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
905 PKey::from_dh(dh)
906 }
907}
908
909impl<T> TryFrom<PKey<T>> for Dh<T> {
910 type Error = ErrorStack;
911
912 fn try_from(pkey: PKey<T>) -> Result<Dh<T>, ErrorStack> {
913 pkey.dh()
914 }
915}
916
917#[cfg(test)]
918mod tests {
919 use std::convert::TryInto;
920
921 #[cfg(not(boringssl))]
922 use crate::dh::Dh;
923 use crate::dsa::Dsa;
924 use crate::ec::EcKey;
925 use crate::error::Error;
926 use crate::nid::Nid;
927 use crate::rsa::Rsa;
928 use crate::symm::Cipher;
929
930 use super::*;
931
932 #[cfg(any(ossl111, awslc))]
933 use crate::rand::rand_bytes;
934
935 #[test]
936 fn test_to_password() {
937 let rsa = Rsa::generate(2048).unwrap();
938 let pkey = PKey::from_rsa(rsa).unwrap();
939 let pem = pkey
940 .private_key_to_pem_pkcs8_passphrase(Cipher::aes_128_cbc(), b"foobar")
941 .unwrap();
942 PKey::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
943 assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
944 }
945
946 #[test]
947 fn test_unencrypted_pkcs8() {
948 let key = include_bytes!("../test/pkcs8-nocrypt.der");
949 let pkey = PKey::private_key_from_pkcs8(key).unwrap();
950 let serialized = pkey.private_key_to_pkcs8().unwrap();
951 let pkey2 = PKey::private_key_from_pkcs8(&serialized).unwrap();
952
953 assert_eq!(
954 pkey2.private_key_to_der().unwrap(),
955 pkey.private_key_to_der().unwrap()
956 );
957 }
958
959 #[test]
960 fn test_encrypted_pkcs8_passphrase() {
961 let key = include_bytes!("../test/pkcs8.der");
962 PKey::private_key_from_pkcs8_passphrase(key, b"mypass").unwrap();
963
964 let rsa = Rsa::generate(2048).unwrap();
965 let pkey = PKey::from_rsa(rsa).unwrap();
966 let der = pkey
967 .private_key_to_pkcs8_passphrase(Cipher::aes_128_cbc(), b"mypass")
968 .unwrap();
969 let pkey2 = PKey::private_key_from_pkcs8_passphrase(&der, b"mypass").unwrap();
970 assert_eq!(
971 pkey.private_key_to_der().unwrap(),
972 pkey2.private_key_to_der().unwrap()
973 );
974 }
975
976 #[test]
977 fn test_encrypted_pkcs8_callback() {
978 let mut password_queried = false;
979 let key = include_bytes!("../test/pkcs8.der");
980 PKey::private_key_from_pkcs8_callback(key, |password| {
981 password_queried = true;
982 password[..6].copy_from_slice(b"mypass");
983 Ok(6)
984 })
985 .unwrap();
986 assert!(password_queried);
987 }
988
989 #[test]
990 fn test_private_key_from_pem() {
991 let key = include_bytes!("../test/key.pem");
992 PKey::private_key_from_pem(key).unwrap();
993 }
994
995 #[test]
996 fn test_public_key_from_pem() {
997 let key = include_bytes!("../test/key.pem.pub");
998 PKey::public_key_from_pem(key).unwrap();
999 }
1000
1001 #[test]
1002 fn test_public_key_from_der() {
1003 let key = include_bytes!("../test/key.der.pub");
1004 PKey::public_key_from_der(key).unwrap();
1005 }
1006
1007 #[test]
1008 fn test_private_key_from_der() {
1009 let key = include_bytes!("../test/key.der");
1010 PKey::private_key_from_der(key).unwrap();
1011 }
1012
1013 #[test]
1014 fn test_pem() {
1015 let key = include_bytes!("../test/key.pem");
1016 let key = PKey::private_key_from_pem(key).unwrap();
1017
1018 let priv_key = key.private_key_to_pem_pkcs8().unwrap();
1019 let pub_key = key.public_key_to_pem().unwrap();
1020
1021 assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY"));
1024 assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY"));
1025 }
1026
1027 #[test]
1028 fn test_rsa_accessor() {
1029 let rsa = Rsa::generate(2048).unwrap();
1030 let pkey = PKey::from_rsa(rsa).unwrap();
1031 pkey.rsa().unwrap();
1032 assert_eq!(pkey.id(), Id::RSA);
1033 assert!(pkey.dsa().is_err());
1034 }
1035
1036 #[test]
1037 fn test_dsa_accessor() {
1038 let dsa = Dsa::generate(2048).unwrap();
1039 let pkey = PKey::from_dsa(dsa).unwrap();
1040 pkey.dsa().unwrap();
1041 assert_eq!(pkey.id(), Id::DSA);
1042 assert!(pkey.rsa().is_err());
1043 }
1044
1045 #[test]
1046 #[cfg(not(boringssl))]
1047 fn test_dh_accessor() {
1048 let dh = include_bytes!("../test/dhparams.pem");
1049 let dh = Dh::params_from_pem(dh).unwrap();
1050 let pkey = PKey::from_dh(dh).unwrap();
1051 pkey.dh().unwrap();
1052 assert_eq!(pkey.id(), Id::DH);
1053 assert!(pkey.rsa().is_err());
1054 }
1055
1056 #[test]
1057 fn test_ec_key_accessor() {
1058 let ec_key = EcKey::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
1059 let pkey = PKey::from_ec_key(ec_key).unwrap();
1060 pkey.ec_key().unwrap();
1061 assert_eq!(pkey.id(), Id::EC);
1062 assert!(pkey.rsa().is_err());
1063 }
1064
1065 #[test]
1066 fn test_rsa_conversion() {
1067 let rsa = Rsa::generate(2048).unwrap();
1068 let pkey: PKey<Private> = rsa.clone().try_into().unwrap();
1069 let rsa_: Rsa<Private> = pkey.try_into().unwrap();
1070 assert_eq!(rsa.p(), rsa_.p());
1072 assert_eq!(rsa.q(), rsa_.q());
1073 }
1074
1075 #[test]
1076 fn test_dsa_conversion() {
1077 let dsa = Dsa::generate(2048).unwrap();
1078 let pkey: PKey<Private> = dsa.clone().try_into().unwrap();
1079 let dsa_: Dsa<Private> = pkey.try_into().unwrap();
1080 assert_eq!(dsa.priv_key(), dsa_.priv_key());
1082 }
1083
1084 #[test]
1085 fn test_ec_key_conversion() {
1086 let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::X9_62_PRIME256V1).unwrap();
1087 let ec_key = EcKey::generate(&group).unwrap();
1088 let pkey: PKey<Private> = ec_key.clone().try_into().unwrap();
1089 let ec_key_: EcKey<Private> = pkey.try_into().unwrap();
1090 assert_eq!(ec_key.private_key(), ec_key_.private_key());
1092 }
1093
1094 #[test]
1095 #[cfg(any(ossl110, libressl360))]
1096 fn test_security_bits() {
1097 let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::SECP521R1).unwrap();
1098 let ec_key = EcKey::generate(&group).unwrap();
1099 let pkey: PKey<Private> = ec_key.try_into().unwrap();
1100
1101 assert_eq!(pkey.security_bits(), 256);
1102 }
1103
1104 #[test]
1105 #[cfg(not(boringssl))]
1106 fn test_dh_conversion() {
1107 let dh_params = include_bytes!("../test/dhparams.pem");
1108 let dh_params = Dh::params_from_pem(dh_params).unwrap();
1109 let dh = dh_params.generate_key().unwrap();
1110
1111 let p = dh.prime_p().to_owned().unwrap();
1113 let q = dh.prime_q().map(|q| q.to_owned().unwrap());
1114 let g = dh.generator().to_owned().unwrap();
1115
1116 let pkey: PKey<Private> = dh.try_into().unwrap();
1117 let dh_: Dh<Private> = pkey.try_into().unwrap();
1118
1119 assert_eq!(&p, dh_.prime_p());
1121 assert_eq!(q, dh_.prime_q().map(|q| q.to_owned().unwrap()));
1122 assert_eq!(&g, dh_.generator());
1123 }
1124
1125 #[cfg(any(ossl111, boringssl, libressl370, awslc))]
1126 fn test_raw_public_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) {
1127 let key = gen().unwrap();
1129
1130 let raw = key.raw_public_key().unwrap();
1132 let from_raw = PKey::public_key_from_raw_bytes(&raw, key_type).unwrap();
1133
1134 assert_eq!(
1136 key.public_key_to_der().unwrap(),
1137 from_raw.public_key_to_der().unwrap()
1138 );
1139 }
1140
1141 #[cfg(any(ossl111, boringssl, libressl370, awslc))]
1142 fn test_raw_private_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) {
1143 let key = gen().unwrap();
1145
1146 let raw = key.raw_private_key().unwrap();
1148 let from_raw = PKey::private_key_from_raw_bytes(&raw, key_type).unwrap();
1149
1150 assert_eq!(
1152 key.private_key_to_pkcs8().unwrap(),
1153 from_raw.private_key_to_pkcs8().unwrap()
1154 );
1155 }
1156
1157 #[cfg(any(ossl111, boringssl, libressl370, awslc))]
1158 #[test]
1159 fn test_raw_public_key_bytes() {
1160 test_raw_public_key(PKey::generate_x25519, Id::X25519);
1161 test_raw_public_key(PKey::generate_ed25519, Id::ED25519);
1162 #[cfg(not(any(boringssl, libressl370, awslc)))]
1163 test_raw_public_key(PKey::generate_x448, Id::X448);
1164 #[cfg(not(any(boringssl, libressl370, awslc)))]
1165 test_raw_public_key(PKey::generate_ed448, Id::ED448);
1166 }
1167
1168 #[cfg(any(ossl111, boringssl, libressl370, awslc))]
1169 #[test]
1170 fn test_raw_private_key_bytes() {
1171 test_raw_private_key(PKey::generate_x25519, Id::X25519);
1172 test_raw_private_key(PKey::generate_ed25519, Id::ED25519);
1173 #[cfg(not(any(boringssl, libressl370, awslc)))]
1174 test_raw_private_key(PKey::generate_x448, Id::X448);
1175 #[cfg(not(any(boringssl, libressl370, awslc)))]
1176 test_raw_private_key(PKey::generate_ed448, Id::ED448);
1177 }
1178
1179 #[cfg(any(ossl111, awslc))]
1180 #[test]
1181 fn test_raw_hmac() {
1182 let mut test_bytes = vec![0u8; 32];
1183 rand_bytes(&mut test_bytes).unwrap();
1184
1185 let hmac_key = PKey::hmac(&test_bytes).unwrap();
1186 assert!(hmac_key.raw_public_key().is_err());
1187
1188 let key_bytes = hmac_key.raw_private_key().unwrap();
1189 assert_eq!(key_bytes, test_bytes);
1190 }
1191
1192 #[cfg(any(ossl111, awslc))]
1193 #[test]
1194 fn test_raw_key_fail() {
1195 let group = crate::ec::EcGroup::from_curve_name(Nid::SECP256K1).unwrap();
1197 let ec_key = EcKey::generate(&group).unwrap();
1198 let pkey = PKey::from_ec_key(ec_key).unwrap();
1199 assert!(pkey.raw_private_key().is_err());
1200 assert!(pkey.raw_public_key().is_err());
1201 }
1202
1203 #[cfg(ossl300)]
1204 #[test]
1205 fn test_ec_gen() {
1206 let key = PKey::ec_gen("prime256v1").unwrap();
1207 assert!(key.ec_key().is_ok());
1208 }
1209
1210 #[test]
1211 fn test_public_eq() {
1212 let rsa = Rsa::generate(2048).unwrap();
1213 let pkey1 = PKey::from_rsa(rsa).unwrap();
1214
1215 let group = crate::ec::EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
1216 let ec_key = EcKey::generate(&group).unwrap();
1217 let pkey2 = PKey::from_ec_key(ec_key).unwrap();
1218
1219 assert!(!pkey1.public_eq(&pkey2));
1220 assert!(Error::get().is_none());
1221 }
1222}