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))]
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(boringssl), 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))]
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(boringssl))]
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))]
97 pub const HKDF: Id = Id(ffi::EVP_PKEY_HKDF);
98
99 #[cfg(any(ossl111, boringssl, libressl370))]
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))]
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))]
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))]
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(not(boringssl))]
388 Id::HMAC => "HMAC",
389 Id::DSA => "DSA",
390 Id::DH => "DH",
391 Id::EC => "EC",
392 #[cfg(ossl111)]
393 Id::ED25519 => "Ed25519",
394 #[cfg(ossl111)]
395 Id::ED448 => "Ed448",
396 _ => "unknown",
397 };
398 fmt.debug_struct("PKey").field("algorithm", &alg).finish()
399 }
401}
402
403impl<T> Clone for PKey<T> {
404 fn clone(&self) -> PKey<T> {
405 PKeyRef::to_owned(self)
406 }
407}
408
409impl<T> PKey<T> {
410 #[corresponds(EVP_PKEY_set1_RSA)]
412 pub fn from_rsa(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> {
413 unsafe {
416 let evp = cvt_p(ffi::EVP_PKEY_new())?;
417 let pkey = PKey::from_ptr(evp);
418 cvt(ffi::EVP_PKEY_set1_RSA(pkey.0, rsa.as_ptr()))?;
419 Ok(pkey)
420 }
421 }
422
423 #[corresponds(EVP_PKEY_set1_DSA)]
425 pub fn from_dsa(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> {
426 unsafe {
427 let evp = cvt_p(ffi::EVP_PKEY_new())?;
428 let pkey = PKey::from_ptr(evp);
429 cvt(ffi::EVP_PKEY_set1_DSA(pkey.0, dsa.as_ptr()))?;
430 Ok(pkey)
431 }
432 }
433
434 #[corresponds(EVP_PKEY_set1_DH)]
436 #[cfg(not(boringssl))]
437 pub fn from_dh(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
438 unsafe {
439 let evp = cvt_p(ffi::EVP_PKEY_new())?;
440 let pkey = PKey::from_ptr(evp);
441 cvt(ffi::EVP_PKEY_set1_DH(pkey.0, dh.as_ptr()))?;
442 Ok(pkey)
443 }
444 }
445
446 #[cfg(all(not(boringssl), ossl110))]
448 pub fn from_dhx(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
449 unsafe {
450 let evp = cvt_p(ffi::EVP_PKEY_new())?;
451 let pkey = PKey::from_ptr(evp);
452 cvt(ffi::EVP_PKEY_assign(
453 pkey.0,
454 ffi::EVP_PKEY_DHX,
455 dh.as_ptr().cast(),
456 ))?;
457 mem::forget(dh);
458 Ok(pkey)
459 }
460 }
461
462 #[corresponds(EVP_PKEY_set1_EC_KEY)]
464 pub fn from_ec_key(ec_key: EcKey<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_set1_EC_KEY(pkey.0, ec_key.as_ptr()))?;
469 Ok(pkey)
470 }
471 }
472}
473
474impl PKey<Private> {
475 #[corresponds(EVP_PKEY_new_mac_key)]
481 #[cfg(not(boringssl))]
482 pub fn hmac(key: &[u8]) -> Result<PKey<Private>, ErrorStack> {
483 unsafe {
484 assert!(key.len() <= c_int::MAX as usize);
485 let key = cvt_p(ffi::EVP_PKEY_new_mac_key(
486 ffi::EVP_PKEY_HMAC,
487 ptr::null_mut(),
488 key.as_ptr() as *const _,
489 key.len() as c_int,
490 ))?;
491 Ok(PKey::from_ptr(key))
492 }
493 }
494
495 #[cfg(all(not(boringssl), ossl110))]
503 #[allow(clippy::trivially_copy_pass_by_ref)]
504 pub fn cmac(cipher: &Cipher, key: &[u8]) -> Result<PKey<Private>, ErrorStack> {
505 let mut ctx = PkeyCtx::new_id(Id::CMAC)?;
506 ctx.keygen_init()?;
507 ctx.set_keygen_cipher(unsafe { CipherRef::from_ptr(cipher.as_ptr() as *mut _) })?;
508 ctx.set_keygen_mac_key(key)?;
509 ctx.keygen()
510 }
511
512 #[cfg(any(ossl111, boringssl, libressl370))]
513 fn generate_eddsa(id: Id) -> Result<PKey<Private>, ErrorStack> {
514 let mut ctx = PkeyCtx::new_id(id)?;
515 ctx.keygen_init()?;
516 ctx.keygen()
517 }
518
519 #[cfg(any(ossl111, boringssl, libressl370))]
543 pub fn generate_x25519() -> Result<PKey<Private>, ErrorStack> {
544 PKey::generate_eddsa(Id::X25519)
545 }
546
547 #[cfg(ossl111)]
571 pub fn generate_x448() -> Result<PKey<Private>, ErrorStack> {
572 PKey::generate_eddsa(Id::X448)
573 }
574
575 #[cfg(any(ossl111, boringssl, libressl370))]
597 pub fn generate_ed25519() -> Result<PKey<Private>, ErrorStack> {
598 PKey::generate_eddsa(Id::ED25519)
599 }
600
601 #[cfg(ossl111)]
623 pub fn generate_ed448() -> Result<PKey<Private>, ErrorStack> {
624 PKey::generate_eddsa(Id::ED448)
625 }
626
627 #[corresponds(EVP_EC_gen)]
631 #[cfg(ossl300)]
632 pub fn ec_gen(curve: &str) -> Result<PKey<Private>, ErrorStack> {
633 ffi::init();
634
635 let curve = CString::new(curve).unwrap();
636 unsafe {
637 let ptr = cvt_p(ffi::EVP_EC_gen(curve.as_ptr()))?;
638 Ok(PKey::from_ptr(ptr))
639 }
640 }
641
642 private_key_from_pem! {
643 #[corresponds(PEM_read_bio_PrivateKey)]
645 private_key_from_pem,
646
647 #[corresponds(PEM_read_bio_PrivateKey)]
649 private_key_from_pem_passphrase,
650
651 #[corresponds(PEM_read_bio_PrivateKey)]
655 private_key_from_pem_callback,
656 PKey<Private>,
657 ffi::PEM_read_bio_PrivateKey
658 }
659
660 from_der! {
661 #[corresponds(d2i_AutoPrivateKey)]
667 private_key_from_der,
668 PKey<Private>,
669 ffi::d2i_AutoPrivateKey
670 }
671
672 pub fn private_key_from_pkcs8(der: &[u8]) -> Result<PKey<Private>, ErrorStack> {
676 unsafe {
677 ffi::init();
678 let len = der.len().min(c_long::MAX as usize) as c_long;
679 let p8inf = cvt_p(ffi::d2i_PKCS8_PRIV_KEY_INFO(
680 ptr::null_mut(),
681 &mut der.as_ptr(),
682 len,
683 ))?;
684 let res = cvt_p(ffi::EVP_PKCS82PKEY(p8inf)).map(|p| PKey::from_ptr(p));
685 ffi::PKCS8_PRIV_KEY_INFO_free(p8inf);
686 res
687 }
688 }
689
690 #[corresponds(d2i_PKCS8PrivateKey_bio)]
696 pub fn private_key_from_pkcs8_callback<F>(
697 der: &[u8],
698 callback: F,
699 ) -> Result<PKey<Private>, ErrorStack>
700 where
701 F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,
702 {
703 unsafe {
704 ffi::init();
705 let mut cb = CallbackState::new(callback);
706 let bio = MemBioSlice::new(der)?;
707 cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
708 bio.as_ptr(),
709 ptr::null_mut(),
710 Some(invoke_passwd_cb::<F>),
711 &mut cb as *mut _ as *mut _,
712 ))
713 .map(|p| PKey::from_ptr(p))
714 }
715 }
716
717 #[corresponds(d2i_PKCS8PrivateKey_bio)]
724 pub fn private_key_from_pkcs8_passphrase(
725 der: &[u8],
726 passphrase: &[u8],
727 ) -> Result<PKey<Private>, ErrorStack> {
728 unsafe {
729 ffi::init();
730 let bio = MemBioSlice::new(der)?;
731 let passphrase = CString::new(passphrase).unwrap();
732 cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
733 bio.as_ptr(),
734 ptr::null_mut(),
735 None,
736 passphrase.as_ptr() as *const _ as *mut _,
737 ))
738 .map(|p| PKey::from_ptr(p))
739 }
740 }
741
742 #[corresponds(EVP_PKEY_new_raw_private_key)]
746 #[cfg(any(ossl111, boringssl, libressl370))]
747 pub fn private_key_from_raw_bytes(
748 bytes: &[u8],
749 key_type: Id,
750 ) -> Result<PKey<Private>, ErrorStack> {
751 unsafe {
752 ffi::init();
753 cvt_p(ffi::EVP_PKEY_new_raw_private_key(
754 key_type.as_raw(),
755 ptr::null_mut(),
756 bytes.as_ptr(),
757 bytes.len(),
758 ))
759 .map(|p| PKey::from_ptr(p))
760 }
761 }
762}
763
764impl PKey<Public> {
765 private_key_from_pem! {
766 #[corresponds(PEM_read_bio_PUBKEY)]
770 public_key_from_pem,
771
772 #[corresponds(PEM_read_bio_PUBKEY)]
774 public_key_from_pem_passphrase,
775
776 #[corresponds(PEM_read_bio_PrivateKey)]
780 public_key_from_pem_callback,
781 PKey<Public>,
782 ffi::PEM_read_bio_PUBKEY
783 }
784
785 from_der! {
786 #[corresponds(d2i_PUBKEY)]
788 public_key_from_der,
789 PKey<Public>,
790 ffi::d2i_PUBKEY
791 }
792
793 #[corresponds(EVP_PKEY_new_raw_public_key)]
797 #[cfg(any(ossl111, boringssl, libressl370))]
798 pub fn public_key_from_raw_bytes(
799 bytes: &[u8],
800 key_type: Id,
801 ) -> Result<PKey<Public>, ErrorStack> {
802 unsafe {
803 ffi::init();
804 cvt_p(ffi::EVP_PKEY_new_raw_public_key(
805 key_type.as_raw(),
806 ptr::null_mut(),
807 bytes.as_ptr(),
808 bytes.len(),
809 ))
810 .map(|p| PKey::from_ptr(p))
811 }
812 }
813}
814
815cfg_if! {
816 if #[cfg(any(boringssl, ossl110, libressl270))] {
817 use ffi::EVP_PKEY_up_ref;
818 } else {
819 #[allow(bad_style)]
820 unsafe extern "C" fn EVP_PKEY_up_ref(pkey: *mut ffi::EVP_PKEY) {
821 ffi::CRYPTO_add_lock(
822 &mut (*pkey).references,
823 1,
824 ffi::CRYPTO_LOCK_EVP_PKEY,
825 "pkey.rs\0".as_ptr() as *const _,
826 line!() as c_int,
827 );
828 }
829 }
830}
831
832impl<T> TryFrom<EcKey<T>> for PKey<T> {
833 type Error = ErrorStack;
834
835 fn try_from(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> {
836 PKey::from_ec_key(ec_key)
837 }
838}
839
840impl<T> TryFrom<PKey<T>> for EcKey<T> {
841 type Error = ErrorStack;
842
843 fn try_from(pkey: PKey<T>) -> Result<EcKey<T>, ErrorStack> {
844 pkey.ec_key()
845 }
846}
847
848impl<T> TryFrom<Rsa<T>> for PKey<T> {
849 type Error = ErrorStack;
850
851 fn try_from(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> {
852 PKey::from_rsa(rsa)
853 }
854}
855
856impl<T> TryFrom<PKey<T>> for Rsa<T> {
857 type Error = ErrorStack;
858
859 fn try_from(pkey: PKey<T>) -> Result<Rsa<T>, ErrorStack> {
860 pkey.rsa()
861 }
862}
863
864impl<T> TryFrom<Dsa<T>> for PKey<T> {
865 type Error = ErrorStack;
866
867 fn try_from(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> {
868 PKey::from_dsa(dsa)
869 }
870}
871
872impl<T> TryFrom<PKey<T>> for Dsa<T> {
873 type Error = ErrorStack;
874
875 fn try_from(pkey: PKey<T>) -> Result<Dsa<T>, ErrorStack> {
876 pkey.dsa()
877 }
878}
879
880#[cfg(not(boringssl))]
881impl<T> TryFrom<Dh<T>> for PKey<T> {
882 type Error = ErrorStack;
883
884 fn try_from(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
885 PKey::from_dh(dh)
886 }
887}
888
889impl<T> TryFrom<PKey<T>> for Dh<T> {
890 type Error = ErrorStack;
891
892 fn try_from(pkey: PKey<T>) -> Result<Dh<T>, ErrorStack> {
893 pkey.dh()
894 }
895}
896
897#[cfg(test)]
898mod tests {
899 use std::convert::TryInto;
900
901 #[cfg(not(boringssl))]
902 use crate::dh::Dh;
903 use crate::dsa::Dsa;
904 use crate::ec::EcKey;
905 use crate::error::Error;
906 use crate::nid::Nid;
907 use crate::rsa::Rsa;
908 use crate::symm::Cipher;
909
910 use super::*;
911
912 #[cfg(ossl111)]
913 use crate::rand::rand_bytes;
914
915 #[test]
916 fn test_to_password() {
917 let rsa = Rsa::generate(2048).unwrap();
918 let pkey = PKey::from_rsa(rsa).unwrap();
919 let pem = pkey
920 .private_key_to_pem_pkcs8_passphrase(Cipher::aes_128_cbc(), b"foobar")
921 .unwrap();
922 PKey::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
923 assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
924 }
925
926 #[test]
927 fn test_unencrypted_pkcs8() {
928 let key = include_bytes!("../test/pkcs8-nocrypt.der");
929 let pkey = PKey::private_key_from_pkcs8(key).unwrap();
930 let serialized = pkey.private_key_to_pkcs8().unwrap();
931 let pkey2 = PKey::private_key_from_pkcs8(&serialized).unwrap();
932
933 assert_eq!(
934 pkey2.private_key_to_der().unwrap(),
935 pkey.private_key_to_der().unwrap()
936 );
937 }
938
939 #[test]
940 fn test_encrypted_pkcs8_passphrase() {
941 let key = include_bytes!("../test/pkcs8.der");
942 PKey::private_key_from_pkcs8_passphrase(key, b"mypass").unwrap();
943
944 let rsa = Rsa::generate(2048).unwrap();
945 let pkey = PKey::from_rsa(rsa).unwrap();
946 let der = pkey
947 .private_key_to_pkcs8_passphrase(Cipher::aes_128_cbc(), b"mypass")
948 .unwrap();
949 let pkey2 = PKey::private_key_from_pkcs8_passphrase(&der, b"mypass").unwrap();
950 assert_eq!(
951 pkey.private_key_to_der().unwrap(),
952 pkey2.private_key_to_der().unwrap()
953 );
954 }
955
956 #[test]
957 fn test_encrypted_pkcs8_callback() {
958 let mut password_queried = false;
959 let key = include_bytes!("../test/pkcs8.der");
960 PKey::private_key_from_pkcs8_callback(key, |password| {
961 password_queried = true;
962 password[..6].copy_from_slice(b"mypass");
963 Ok(6)
964 })
965 .unwrap();
966 assert!(password_queried);
967 }
968
969 #[test]
970 fn test_private_key_from_pem() {
971 let key = include_bytes!("../test/key.pem");
972 PKey::private_key_from_pem(key).unwrap();
973 }
974
975 #[test]
976 fn test_public_key_from_pem() {
977 let key = include_bytes!("../test/key.pem.pub");
978 PKey::public_key_from_pem(key).unwrap();
979 }
980
981 #[test]
982 fn test_public_key_from_der() {
983 let key = include_bytes!("../test/key.der.pub");
984 PKey::public_key_from_der(key).unwrap();
985 }
986
987 #[test]
988 fn test_private_key_from_der() {
989 let key = include_bytes!("../test/key.der");
990 PKey::private_key_from_der(key).unwrap();
991 }
992
993 #[test]
994 fn test_pem() {
995 let key = include_bytes!("../test/key.pem");
996 let key = PKey::private_key_from_pem(key).unwrap();
997
998 let priv_key = key.private_key_to_pem_pkcs8().unwrap();
999 let pub_key = key.public_key_to_pem().unwrap();
1000
1001 assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY"));
1004 assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY"));
1005 }
1006
1007 #[test]
1008 fn test_rsa_accessor() {
1009 let rsa = Rsa::generate(2048).unwrap();
1010 let pkey = PKey::from_rsa(rsa).unwrap();
1011 pkey.rsa().unwrap();
1012 assert_eq!(pkey.id(), Id::RSA);
1013 assert!(pkey.dsa().is_err());
1014 }
1015
1016 #[test]
1017 fn test_dsa_accessor() {
1018 let dsa = Dsa::generate(2048).unwrap();
1019 let pkey = PKey::from_dsa(dsa).unwrap();
1020 pkey.dsa().unwrap();
1021 assert_eq!(pkey.id(), Id::DSA);
1022 assert!(pkey.rsa().is_err());
1023 }
1024
1025 #[test]
1026 #[cfg(not(boringssl))]
1027 fn test_dh_accessor() {
1028 let dh = include_bytes!("../test/dhparams.pem");
1029 let dh = Dh::params_from_pem(dh).unwrap();
1030 let pkey = PKey::from_dh(dh).unwrap();
1031 pkey.dh().unwrap();
1032 assert_eq!(pkey.id(), Id::DH);
1033 assert!(pkey.rsa().is_err());
1034 }
1035
1036 #[test]
1037 fn test_ec_key_accessor() {
1038 let ec_key = EcKey::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
1039 let pkey = PKey::from_ec_key(ec_key).unwrap();
1040 pkey.ec_key().unwrap();
1041 assert_eq!(pkey.id(), Id::EC);
1042 assert!(pkey.rsa().is_err());
1043 }
1044
1045 #[test]
1046 fn test_rsa_conversion() {
1047 let rsa = Rsa::generate(2048).unwrap();
1048 let pkey: PKey<Private> = rsa.clone().try_into().unwrap();
1049 let rsa_: Rsa<Private> = pkey.try_into().unwrap();
1050 assert_eq!(rsa.p(), rsa_.p());
1052 assert_eq!(rsa.q(), rsa_.q());
1053 }
1054
1055 #[test]
1056 fn test_dsa_conversion() {
1057 let dsa = Dsa::generate(2048).unwrap();
1058 let pkey: PKey<Private> = dsa.clone().try_into().unwrap();
1059 let dsa_: Dsa<Private> = pkey.try_into().unwrap();
1060 assert_eq!(dsa.priv_key(), dsa_.priv_key());
1062 }
1063
1064 #[test]
1065 fn test_ec_key_conversion() {
1066 let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::X9_62_PRIME256V1).unwrap();
1067 let ec_key = EcKey::generate(&group).unwrap();
1068 let pkey: PKey<Private> = ec_key.clone().try_into().unwrap();
1069 let ec_key_: EcKey<Private> = pkey.try_into().unwrap();
1070 assert_eq!(ec_key.private_key(), ec_key_.private_key());
1072 }
1073
1074 #[test]
1075 #[cfg(any(ossl110, libressl360))]
1076 fn test_security_bits() {
1077 let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::SECP521R1).unwrap();
1078 let ec_key = EcKey::generate(&group).unwrap();
1079 let pkey: PKey<Private> = ec_key.try_into().unwrap();
1080
1081 assert_eq!(pkey.security_bits(), 256);
1082 }
1083
1084 #[test]
1085 #[cfg(not(boringssl))]
1086 fn test_dh_conversion() {
1087 let dh_params = include_bytes!("../test/dhparams.pem");
1088 let dh_params = Dh::params_from_pem(dh_params).unwrap();
1089 let dh = dh_params.generate_key().unwrap();
1090
1091 let p = dh.prime_p().to_owned().unwrap();
1093 let q = dh.prime_q().map(|q| q.to_owned().unwrap());
1094 let g = dh.generator().to_owned().unwrap();
1095
1096 let pkey: PKey<Private> = dh.try_into().unwrap();
1097 let dh_: Dh<Private> = pkey.try_into().unwrap();
1098
1099 assert_eq!(&p, dh_.prime_p());
1101 assert_eq!(q, dh_.prime_q().map(|q| q.to_owned().unwrap()));
1102 assert_eq!(&g, dh_.generator());
1103 }
1104
1105 #[cfg(any(ossl111, boringssl, libressl370))]
1106 fn test_raw_public_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) {
1107 let key = gen().unwrap();
1109
1110 let raw = key.raw_public_key().unwrap();
1112 let from_raw = PKey::public_key_from_raw_bytes(&raw, key_type).unwrap();
1113
1114 assert_eq!(
1116 key.public_key_to_der().unwrap(),
1117 from_raw.public_key_to_der().unwrap()
1118 );
1119 }
1120
1121 #[cfg(any(ossl111, boringssl, libressl370))]
1122 fn test_raw_private_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) {
1123 let key = gen().unwrap();
1125
1126 let raw = key.raw_private_key().unwrap();
1128 let from_raw = PKey::private_key_from_raw_bytes(&raw, key_type).unwrap();
1129
1130 assert_eq!(
1132 key.private_key_to_pkcs8().unwrap(),
1133 from_raw.private_key_to_pkcs8().unwrap()
1134 );
1135 }
1136
1137 #[cfg(any(ossl111, boringssl, libressl370))]
1138 #[test]
1139 fn test_raw_public_key_bytes() {
1140 test_raw_public_key(PKey::generate_x25519, Id::X25519);
1141 test_raw_public_key(PKey::generate_ed25519, Id::ED25519);
1142 #[cfg(all(not(boringssl), not(libressl370)))]
1143 test_raw_public_key(PKey::generate_x448, Id::X448);
1144 #[cfg(all(not(boringssl), not(libressl370)))]
1145 test_raw_public_key(PKey::generate_ed448, Id::ED448);
1146 }
1147
1148 #[cfg(any(ossl111, boringssl, libressl370))]
1149 #[test]
1150 fn test_raw_private_key_bytes() {
1151 test_raw_private_key(PKey::generate_x25519, Id::X25519);
1152 test_raw_private_key(PKey::generate_ed25519, Id::ED25519);
1153 #[cfg(all(not(boringssl), not(libressl370)))]
1154 test_raw_private_key(PKey::generate_x448, Id::X448);
1155 #[cfg(all(not(boringssl), not(libressl370)))]
1156 test_raw_private_key(PKey::generate_ed448, Id::ED448);
1157 }
1158
1159 #[cfg(ossl111)]
1160 #[test]
1161 fn test_raw_hmac() {
1162 let mut test_bytes = vec![0u8; 32];
1163 rand_bytes(&mut test_bytes).unwrap();
1164
1165 let hmac_key = PKey::hmac(&test_bytes).unwrap();
1166 assert!(hmac_key.raw_public_key().is_err());
1167
1168 let key_bytes = hmac_key.raw_private_key().unwrap();
1169 assert_eq!(key_bytes, test_bytes);
1170 }
1171
1172 #[cfg(ossl111)]
1173 #[test]
1174 fn test_raw_key_fail() {
1175 let group = crate::ec::EcGroup::from_curve_name(Nid::SECP256K1).unwrap();
1177 let ec_key = EcKey::generate(&group).unwrap();
1178 let pkey = PKey::from_ec_key(ec_key).unwrap();
1179 assert!(pkey.raw_private_key().is_err());
1180 assert!(pkey.raw_public_key().is_err());
1181 }
1182
1183 #[cfg(ossl300)]
1184 #[test]
1185 fn test_ec_gen() {
1186 let key = PKey::ec_gen("prime256v1").unwrap();
1187 assert!(key.ec_key().is_ok());
1188 }
1189
1190 #[test]
1191 fn test_public_eq() {
1192 let rsa = Rsa::generate(2048).unwrap();
1193 let pkey1 = PKey::from_rsa(rsa).unwrap();
1194
1195 let group = crate::ec::EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
1196 let ec_key = EcKey::generate(&group).unwrap();
1197 let pkey2 = PKey::from_ec_key(ec_key).unwrap();
1198
1199 assert!(!pkey1.public_eq(&pkey2));
1200 assert!(Error::get().is_none());
1201 }
1202}