1use foreign_types::{ForeignType, ForeignTypeRef};
44use libc::{c_int, c_long};
45use openssl_macros::corresponds;
46use std::ffi::CString;
47use std::fmt;
48use std::mem;
49use std::ptr;
50
51use crate::bio::MemBioSlice;
52use crate::dh::Dh;
53use crate::dsa::Dsa;
54use crate::ec::EcKey;
55use crate::error::ErrorStack;
56use crate::ffi;
57use crate::rsa::Rsa;
58use crate::try_int;
59use crate::util::{invoke_passwd_cb, CallbackState};
60use crate::{cvt, cvt_0i, cvt_p};
61
62pub enum Params {}
64
65pub enum Public {}
67
68pub enum Private {}
70
71#[derive(Debug, Copy, Clone, PartialEq, Eq)]
73pub struct Id(c_int);
74
75impl Id {
76 pub const RSA: Id = Id(ffi::EVP_PKEY_RSA);
77 pub const RSAPSS: Id = Id(ffi::EVP_PKEY_RSA_PSS);
78 pub const DSA: Id = Id(ffi::EVP_PKEY_DSA);
79 pub const DH: Id = Id(ffi::EVP_PKEY_DH);
80 pub const EC: Id = Id(ffi::EVP_PKEY_EC);
81 pub const ED25519: Id = Id(ffi::EVP_PKEY_ED25519);
82 pub const ED448: Id = Id(ffi::EVP_PKEY_ED448);
83 pub const X25519: Id = Id(ffi::EVP_PKEY_X25519);
84 pub const X448: Id = Id(ffi::EVP_PKEY_X448);
85
86 #[must_use]
88 pub fn from_raw(value: c_int) -> Id {
89 Id(value)
90 }
91
92 #[allow(clippy::trivially_copy_pass_by_ref)]
94 #[must_use]
95 pub fn as_raw(&self) -> c_int {
96 self.0
97 }
98}
99
100#[allow(clippy::missing_safety_doc)]
102pub unsafe trait HasParams {}
103
104unsafe impl HasParams for Params {}
105
106unsafe impl<T> HasParams for T where T: HasPublic {}
107
108#[allow(clippy::missing_safety_doc)]
110pub unsafe trait HasPublic {}
111
112unsafe impl HasPublic for Public {}
113
114unsafe impl<T> HasPublic for T where T: HasPrivate {}
115
116#[allow(clippy::missing_safety_doc)]
118pub unsafe trait HasPrivate {}
119
120unsafe impl HasPrivate for Private {}
121
122generic_foreign_type_and_impl_send_sync! {
123 type CType = ffi::EVP_PKEY;
124 fn drop = ffi::EVP_PKEY_free;
125
126 pub struct PKey<T>;
128 pub struct PKeyRef<T>;
130}
131
132impl<T> ToOwned for PKeyRef<T> {
133 type Owned = PKey<T>;
134
135 fn to_owned(&self) -> PKey<T> {
136 unsafe {
137 EVP_PKEY_up_ref(self.as_ptr());
138 PKey::from_ptr(self.as_ptr())
139 }
140 }
141}
142
143impl<T> PKeyRef<T> {
144 #[corresponds(EVP_PKEY_get1_RSA)]
146 pub fn rsa(&self) -> Result<Rsa<T>, ErrorStack> {
147 unsafe {
148 let rsa = cvt_p(ffi::EVP_PKEY_get1_RSA(self.as_ptr()))?;
149 Ok(Rsa::from_ptr(rsa))
150 }
151 }
152
153 #[corresponds(EVP_PKEY_get1_DSA)]
155 pub fn dsa(&self) -> Result<Dsa<T>, ErrorStack> {
156 unsafe {
157 let dsa = cvt_p(ffi::EVP_PKEY_get1_DSA(self.as_ptr()))?;
158 Ok(Dsa::from_ptr(dsa))
159 }
160 }
161
162 #[corresponds(EVP_PKEY_get1_DH)]
164 pub fn dh(&self) -> Result<Dh<T>, ErrorStack> {
165 unsafe {
166 let dh = cvt_p(ffi::EVP_PKEY_get1_DH(self.as_ptr()))?;
167 Ok(Dh::from_ptr(dh))
168 }
169 }
170
171 #[corresponds(EVP_PKEY_get1_EC_KEY)]
173 pub fn ec_key(&self) -> Result<EcKey<T>, ErrorStack> {
174 unsafe {
175 let ec_key = cvt_p(ffi::EVP_PKEY_get1_EC_KEY(self.as_ptr()))?;
176 Ok(EcKey::from_ptr(ec_key))
177 }
178 }
179
180 #[corresponds(EVP_PKEY_id)]
182 #[must_use]
183 pub fn id(&self) -> Id {
184 unsafe { Id::from_raw(ffi::EVP_PKEY_id(self.as_ptr())) }
185 }
186
187 #[corresponds(EVP_PKEY_size)]
189 #[must_use]
190 pub fn size(&self) -> usize {
191 unsafe { ffi::EVP_PKEY_size(self.as_ptr()) as usize }
192 }
193}
194
195impl<T> PKeyRef<T>
196where
197 T: HasPublic,
198{
199 to_pem! {
200 #[corresponds(PEM_write_bio_PUBKEY)]
204 public_key_to_pem,
205 ffi::PEM_write_bio_PUBKEY
206 }
207
208 to_der! {
209 #[corresponds(i2d_PUBKEY)]
211 public_key_to_der,
212 ffi::i2d_PUBKEY
213 }
214
215 #[must_use]
220 pub fn bits(&self) -> u32 {
221 unsafe { ffi::EVP_PKEY_bits(self.as_ptr()) as u32 }
222 }
223
224 #[must_use]
226 pub fn public_eq<U>(&self, other: &PKeyRef<U>) -> bool
227 where
228 U: HasPublic,
229 {
230 unsafe { ffi::EVP_PKEY_cmp(self.as_ptr(), other.as_ptr()) == 1 }
231 }
232
233 #[corresponds(EVP_PKEY_get_raw_public_key)]
235 pub fn raw_public_key_len(&self) -> Result<usize, ErrorStack> {
236 unsafe {
237 let mut size = 0;
238 _ = cvt_0i(ffi::EVP_PKEY_get_raw_public_key(
239 self.as_ptr(),
240 std::ptr::null_mut(),
241 &mut size,
242 ))?;
243 Ok(size)
244 }
245 }
246
247 #[corresponds(EVP_PKEY_get_raw_public_key)]
251 pub fn raw_public_key<'a>(&self, out: &'a mut [u8]) -> Result<&'a [u8], ErrorStack> {
252 unsafe {
253 let mut size = out.len();
254 _ = cvt_0i(ffi::EVP_PKEY_get_raw_public_key(
255 self.as_ptr(),
256 out.as_mut_ptr(),
257 &mut size,
258 ))?;
259 Ok(&out[..size])
260 }
261 }
262}
263
264impl<T> PKeyRef<T>
265where
266 T: HasPrivate,
267{
268 private_key_to_pem! {
269 #[corresponds(PEM_write_bio_PKCS8PrivateKey)]
273 private_key_to_pem_pkcs8,
274 #[corresponds(PEM_write_bio_PKCS8PrivateKey)]
278 private_key_to_pem_pkcs8_passphrase,
279 ffi::PEM_write_bio_PKCS8PrivateKey
280 }
281
282 to_der! {
283 #[corresponds(i2d_PrivateKey)]
285 private_key_to_der,
286 ffi::i2d_PrivateKey
287 }
288
289 private_key_to_pem! {
292 #[corresponds(i2d_PKCS8PrivateKey_bio)]
294 private_key_to_der_pkcs8,
295 #[corresponds(i2d_PKCS8PrivateKey_bio)]
297 private_key_to_der_pkcs8_passphrase,
298 ffi::i2d_PKCS8PrivateKey_bio
299 }
300
301 #[corresponds(EVP_PKEY_get_raw_private_key)]
303 pub fn raw_private_key_len(&self) -> Result<usize, ErrorStack> {
304 unsafe {
305 let mut size = 0;
306 _ = cvt_0i(ffi::EVP_PKEY_get_raw_private_key(
307 self.as_ptr(),
308 std::ptr::null_mut(),
309 &mut size,
310 ))?;
311 Ok(size)
312 }
313 }
314
315 #[corresponds(EVP_PKEY_get_raw_private_key)]
319 pub fn raw_private_key<'a>(&self, out: &'a mut [u8]) -> Result<&'a [u8], ErrorStack> {
320 unsafe {
321 let mut size = out.len();
322 _ = cvt_0i(ffi::EVP_PKEY_get_raw_private_key(
323 self.as_ptr(),
324 out.as_mut_ptr(),
325 &mut size,
326 ))?;
327 Ok(&out[..size])
328 }
329 }
330}
331
332impl<T> fmt::Debug for PKey<T> {
333 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
334 let alg = match self.id() {
335 Id::RSA => "RSA",
336 Id::RSAPSS => "RSAPSS",
337 Id::DSA => "DSA",
338 Id::DH => "DH",
339 Id::EC => "EC",
340 Id::ED25519 => "Ed25519",
341 Id::ED448 => "Ed448",
342 _ => "unknown",
343 };
344 fmt.debug_struct("PKey").field("algorithm", &alg).finish()
345 }
347}
348
349impl<T> Clone for PKey<T> {
350 fn clone(&self) -> PKey<T> {
351 PKeyRef::to_owned(self)
352 }
353}
354
355impl<T> PKey<T> {
356 #[corresponds(EVP_PKEY_assign_RSA)]
358 pub fn from_rsa(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> {
359 unsafe {
360 let evp = cvt_p(ffi::EVP_PKEY_new())?;
361 let pkey = PKey::from_ptr(evp);
362 cvt(ffi::EVP_PKEY_assign(
363 pkey.0,
364 ffi::EVP_PKEY_RSA,
365 rsa.as_ptr().cast(),
366 ))?;
367 mem::forget(rsa);
368 Ok(pkey)
369 }
370 }
371
372 #[corresponds(EVP_PKEY_assign_EC_KEY)]
374 pub fn from_ec_key(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> {
375 unsafe {
376 let evp = cvt_p(ffi::EVP_PKEY_new())?;
377 let pkey = PKey::from_ptr(evp);
378 cvt(ffi::EVP_PKEY_assign(
379 pkey.0,
380 ffi::EVP_PKEY_EC,
381 ec_key.as_ptr().cast(),
382 ))?;
383 mem::forget(ec_key);
384 Ok(pkey)
385 }
386 }
387}
388
389impl PKey<Private> {
390 #[corresponds(EVP_PKEY_keygen)]
400 pub fn generate(id: Id) -> Result<PKey<Private>, ErrorStack> {
401 unsafe {
402 ffi::init();
403
404 let ctx = cvt_p(ffi::EVP_PKEY_CTX_new_id(id.as_raw(), ptr::null_mut()))?;
405
406 let result = (|| {
407 cvt(ffi::EVP_PKEY_keygen_init(ctx))?;
408
409 let mut pkey = ptr::null_mut();
410 cvt(ffi::EVP_PKEY_keygen(ctx, &mut pkey))?;
411
412 Ok(PKey::from_ptr(pkey))
413 })();
414
415 ffi::EVP_PKEY_CTX_free(ctx);
416 result
417 }
418 }
419
420 private_key_from_pem! {
421 #[corresponds(PEM_read_bio_PrivateKey)]
423 private_key_from_pem,
424
425 #[corresponds(PEM_read_bio_PrivateKey)]
427 private_key_from_pem_passphrase,
428
429 #[corresponds(PEM_read_bio_PrivateKey)]
433 private_key_from_pem_callback,
434 PKey<Private>,
435 ffi::PEM_read_bio_PrivateKey
436 }
437
438 from_der! {
439 #[corresponds(d2i_AutoPrivateKey)]
445 private_key_from_der,
446 PKey<Private>,
447 ffi::d2i_AutoPrivateKey,
448 ::libc::c_long
449 }
450
451 pub fn private_key_from_pkcs8(der: &[u8]) -> Result<PKey<Private>, ErrorStack> {
455 unsafe {
456 ffi::init();
457 let len = der.len().min(c_long::MAX as usize) as c_long;
458 let p8inf = cvt_p(ffi::d2i_PKCS8_PRIV_KEY_INFO(
459 ptr::null_mut(),
460 &mut der.as_ptr(),
461 len,
462 ))?;
463 let res = cvt_p(ffi::EVP_PKCS82PKEY(p8inf)).map(|p| PKey::from_ptr(p));
464 ffi::PKCS8_PRIV_KEY_INFO_free(p8inf);
465 res
466 }
467 }
468
469 pub fn private_key_from_pkcs8_callback<F>(
475 der: &[u8],
476 callback: F,
477 ) -> Result<PKey<Private>, ErrorStack>
478 where
479 F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,
480 {
481 unsafe {
482 ffi::init();
483 let mut cb = CallbackState::new(callback);
484 let bio = MemBioSlice::new(der)?;
485 cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
486 bio.as_ptr(),
487 ptr::null_mut(),
488 Some(invoke_passwd_cb::<F>),
489 std::ptr::addr_of_mut!(cb).cast(),
490 ))
491 .map(|p| PKey::from_ptr(p))
492 }
493 }
494
495 pub fn private_key_from_pkcs8_passphrase(
502 der: &[u8],
503 passphrase: &[u8],
504 ) -> Result<PKey<Private>, ErrorStack> {
505 unsafe {
506 ffi::init();
507 let bio = MemBioSlice::new(der)?;
508 let passphrase = CString::new(passphrase).map_err(ErrorStack::internal_error)?;
509 cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
510 bio.as_ptr(),
511 ptr::null_mut(),
512 None,
513 passphrase.as_ptr().cast_mut().cast(),
514 ))
515 .map(|p| PKey::from_ptr(p))
516 }
517 }
518}
519
520impl PKey<Public> {
521 from_pem! {
522 #[corresponds(PEM_read_bio_PUBKEY)]
526 public_key_from_pem,
527 PKey<Public>,
528 ffi::PEM_read_bio_PUBKEY
529 }
530
531 from_der! {
532 #[corresponds(d2i_PUBKEY)]
534 public_key_from_der,
535 PKey<Public>,
536 ffi::d2i_PUBKEY,
537 ::libc::c_long
538 }
539}
540
541use crate::ffi::EVP_PKEY_up_ref;
542
543#[cfg(test)]
544mod tests {
545 use hex::FromHex as _;
546
547 use crate::derive::Deriver;
548 use crate::ec::EcKey;
549 use crate::nid::Nid;
550 use crate::rsa::Rsa;
551 use crate::symm::Cipher;
552
553 use super::*;
554
555 #[test]
556 fn test_to_password() {
557 let rsa = Rsa::generate(2048).unwrap();
558 let pkey = PKey::from_rsa(rsa).unwrap();
559 let pem = pkey
560 .private_key_to_pem_pkcs8_passphrase(Cipher::aes_128_cbc(), b"foobar")
561 .unwrap();
562 PKey::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
563 assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
564 }
565
566 #[test]
567 fn test_unencrypted_pkcs8() {
568 let key = include_bytes!("../test/pkcs8-nocrypt.der");
569 PKey::private_key_from_pkcs8(key).unwrap();
570 }
571
572 #[test]
573 fn test_encrypted_pkcs8_passphrase() {
574 let key = include_bytes!("../test/pkcs8.der");
575 PKey::private_key_from_pkcs8_passphrase(key, b"mypass").unwrap();
576 }
577
578 #[test]
579 fn test_encrypted_pkcs8_callback() {
580 let mut password_queried = false;
581 let key = include_bytes!("../test/pkcs8.der");
582 PKey::private_key_from_pkcs8_callback(key, |password| {
583 password_queried = true;
584 password[..6].copy_from_slice(b"mypass");
585 Ok(6)
586 })
587 .unwrap();
588 assert!(password_queried);
589 }
590
591 #[test]
592 fn test_private_key_from_pem() {
593 let key = include_bytes!("../test/key.pem");
594 PKey::private_key_from_pem(key).unwrap();
595 }
596
597 #[test]
598 fn test_public_key_from_pem() {
599 let key = include_bytes!("../test/key.pem.pub");
600 PKey::public_key_from_pem(key).unwrap();
601 }
602
603 #[test]
604 fn test_public_key_from_der() {
605 let key = include_bytes!("../test/key.der.pub");
606 PKey::public_key_from_der(key).unwrap();
607 }
608
609 #[test]
610 fn test_private_key_from_der() {
611 let key = include_bytes!("../test/key.der");
612 PKey::private_key_from_der(key).unwrap();
613 }
614
615 #[test]
616 fn test_pem() {
617 let key = include_bytes!("../test/key.pem");
618 let key = PKey::private_key_from_pem(key).unwrap();
619
620 let priv_key = key.private_key_to_pem_pkcs8().unwrap();
621 let pub_key = key.public_key_to_pem().unwrap();
622
623 assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY"));
626 assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY"));
627 }
628
629 #[test]
630 fn test_der_pkcs8() {
631 let key = include_bytes!("../test/key.der");
632 let key = PKey::private_key_from_der(key).unwrap();
633
634 let priv_key = key.private_key_to_der_pkcs8().unwrap();
635
636 assert_eq!(hex::encode(&priv_key[4..=6]), "020100"); assert_eq!(hex::encode(&priv_key[9..=19]), "06092a864886f70d010101"); }
640
641 #[test]
642 fn test_rsa_accessor() {
643 let rsa = Rsa::generate(2048).unwrap();
644 let pkey = PKey::from_rsa(rsa).unwrap();
645 pkey.rsa().unwrap();
646 assert_eq!(pkey.id(), Id::RSA);
647 assert!(pkey.dsa().is_err());
648 }
649
650 #[test]
651 fn test_ec_key_accessor() {
652 let ec_key = EcKey::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
653 let pkey = PKey::from_ec_key(ec_key).unwrap();
654 pkey.ec_key().unwrap();
655 assert_eq!(pkey.id(), Id::EC);
656 assert!(pkey.rsa().is_err());
657 }
658
659 #[test]
660 fn test_raw_accessors() {
661 const ED25519_PRIVATE_KEY_DER: &str = concat!(
662 "302e020100300506032b6570042204207c8c6497f9960d5595d7815f550569e5",
663 "f77764ac97e63e339aaa68cc1512b683"
664 );
665 let pkey =
666 PKey::private_key_from_der(&Vec::from_hex(ED25519_PRIVATE_KEY_DER).unwrap()).unwrap();
667 assert_eq!(pkey.id(), Id::ED25519);
668
669 let priv_len = pkey.raw_private_key_len().unwrap();
670 assert_eq!(priv_len, 32);
671 let mut raw_private_key_buf = [0; 40];
672 let raw_private_key = pkey.raw_private_key(&mut raw_private_key_buf).unwrap();
673 assert_eq!(raw_private_key.len(), 32);
674 assert_ne!(raw_private_key, [0; 32]);
675 pkey.raw_private_key(&mut [0; 5])
676 .expect_err("buffer too small");
677
678 let pub_len = pkey.raw_public_key_len().unwrap();
679 assert_eq!(pub_len, 32);
680 let mut raw_public_key_buf = [0; 40];
681 let raw_public_key = pkey.raw_public_key(&mut raw_public_key_buf).unwrap();
682 assert_eq!(raw_public_key.len(), 32);
683 assert_ne!(raw_public_key, [0; 32]);
684 assert_ne!(raw_public_key, raw_private_key);
685 pkey.raw_public_key(&mut [0; 5])
686 .expect_err("buffer too small");
687 }
688
689 #[test]
690 fn test_generate_x25519() {
691 let key = PKey::generate(Id::X25519).unwrap();
692 assert_eq!(key.id(), Id::X25519);
693
694 let mut pubkey = [0u8; 32];
695 assert_eq!(key.raw_public_key(&mut pubkey).unwrap().len(), 32);
696 }
697
698 #[test]
699 fn test_generate_x25519_derivation() {
700 let alice = PKey::generate(Id::X25519).unwrap();
701 let bob = PKey::generate(Id::X25519).unwrap();
702
703 let mut alice_deriver = Deriver::new(&alice).unwrap();
704 alice_deriver.set_peer(&bob).unwrap();
705 let shared_alice = alice_deriver.derive_to_vec().unwrap();
706
707 let mut bob_deriver = Deriver::new(&bob).unwrap();
708 bob_deriver.set_peer(&alice).unwrap();
709 let shared_bob = bob_deriver.derive_to_vec().unwrap();
710
711 assert!(!shared_alice.is_empty());
712 assert_eq!(shared_alice, shared_bob);
713 }
714
715 #[test]
716 fn test_generate_invalid_id() {
717 assert!(PKey::generate(Id::from_raw(0)).is_err());
718 }
719}