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