1//! Public/private key processing.
2//!
3//! Asymmetric public key algorithms solve the problem of establishing and sharing
4//! secret keys to securely send and receive messages.
5//! This system uses a pair of keys: a public key, which can be freely
6//! distributed, and a private key, which is kept to oneself. An entity may
7//! encrypt information using a user's public key. The encrypted information can
8//! only be deciphered using that user's private key.
9//!
10//! This module offers support for five popular algorithms:
11//!
12//! * RSA
13//!
14//! * DSA
15//!
16//! * Diffie-Hellman
17//!
18//! * Elliptic Curves
19//!
20//! * HMAC
21//!
22//! These algorithms rely on hard mathematical problems - namely integer factorization,
23//! discrete logarithms, and elliptic curve relationships - that currently do not
24//! yield efficient solutions. This property ensures the security of these
25//! cryptographic algorithms.
26//!
27//! # Example
28//!
29//! Generate a 2048-bit RSA public/private key pair and print the public key.
30//!
31//! ```rust
32//! use openssl::rsa::Rsa;
33//! use openssl::pkey::PKey;
34//! use std::str;
35//!
36//! let rsa = Rsa::generate(2048).unwrap();
37//! let pkey = PKey::from_rsa(rsa).unwrap();
38//!
39//! let pub_key: Vec<u8> = pkey.public_key_to_pem().unwrap();
40//! println!("{:?}", str::from_utf8(pub_key.as_slice()).unwrap());
41//! ```
42#![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;
63use std::mem;
64use std::ptr;
65
66/// A tag type indicating that a key only has parameters.
67pub enum Params {}
68
69/// A tag type indicating that a key only has public components.
70pub enum Public {}
71
72/// A tag type indicating that a key has private components.
73pub enum Private {}
74
75/// An identifier of a kind of key.
76#[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, libressl310, boringssl))]
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(boringssl))]
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))]
96 pub const HKDF: Id = Id(ffi::EVP_PKEY_HKDF);
97
98 #[cfg(any(ossl111, boringssl, libressl370))]
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))]
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 /// Creates a `Id` from an integer representation.
110 pub fn from_raw(value: c_int) -> Id {
111 Id(value)
112 }
113
114 /// Returns the integer representation of the `Id`.
115 #[allow(clippy::trivially_copy_pass_by_ref)]
116 pub fn as_raw(&self) -> c_int {
117 self.0
118 }
119}
120
121/// A trait indicating that a key has parameters.
122pub unsafe trait HasParams {}
123
124unsafe impl HasParams for Params {}
125
126unsafe impl<T> HasParams for T where T: HasPublic {}
127
128/// A trait indicating that a key has public components.
129pub unsafe trait HasPublic {}
130
131unsafe impl HasPublic for Public {}
132
133unsafe impl<T> HasPublic for T where T: HasPrivate {}
134
135/// A trait indicating that a key has private components.
136pub 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 /// A public or private key.
145 pub struct PKey<T>;
146 /// Reference to `PKey`.
147 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 /// Returns a copy of the internal RSA key.
163 #[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 /// Returns a copy of the internal DSA key.
172 #[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 /// Returns a copy of the internal DH key.
181 #[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 /// Returns a copy of the internal elliptic curve key.
190 #[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 /// Returns the `Id` that represents the type of this key.
199 #[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 /// Returns the maximum size of a signature in bytes.
205 #[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 /// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
217 ///
218 /// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
219 #[corresponds(PEM_write_bio_PUBKEY)]
220 public_key_to_pem,
221 ffi::PEM_write_bio_PUBKEY
222 }
223
224 to_der! {
225 /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
226 #[corresponds(i2d_PUBKEY)]
227 public_key_to_der,
228 ffi::i2d_PUBKEY
229 }
230
231 /// Returns the size of the key.
232 ///
233 /// This corresponds to the bit length of the modulus of an RSA key, and the bit length of the
234 /// group order for an elliptic curve key, for example.
235 #[corresponds(EVP_PKEY_bits)]
236 pub fn bits(&self) -> u32 {
237 unsafe { ffi::EVP_PKEY_bits(self.as_ptr()) as u32 }
238 }
239
240 ///Returns the number of security bits.
241 ///
242 ///Bits of security is defined in NIST SP800-57.
243 #[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 /// Compares the public component of this key with another.
250 #[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 // Clear the stack. OpenSSL will put an error on the stack when the
257 // keys are different types in some situations.
258 let _ = ErrorStack::get();
259 res
260 }
261
262 /// Raw byte representation of a public key.
263 ///
264 /// This function only works for algorithms that support raw public keys.
265 /// Currently this is: [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`].
266 #[corresponds(EVP_PKEY_get_raw_public_key)]
267 #[cfg(any(ossl111, boringssl, libressl370))]
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 /// Serializes the private key to a PEM-encoded PKCS#8 PrivateKeyInfo structure.
294 ///
295 /// The output will have a header of `-----BEGIN PRIVATE KEY-----`.
296 #[corresponds(PEM_write_bio_PKCS8PrivateKey)]
297 private_key_to_pem_pkcs8,
298 /// Serializes the private key to a PEM-encoded PKCS#8 EncryptedPrivateKeyInfo structure.
299 ///
300 /// The output will have a header of `-----BEGIN ENCRYPTED PRIVATE KEY-----`.
301 #[corresponds(PEM_write_bio_PKCS8PrivateKey)]
302 private_key_to_pem_pkcs8_passphrase,
303 ffi::PEM_write_bio_PKCS8PrivateKey
304 }
305
306 to_der! {
307 /// Serializes the private key to a DER-encoded key type specific format.
308 #[corresponds(i2d_PrivateKey)]
309 private_key_to_der,
310 ffi::i2d_PrivateKey
311 }
312
313 /// Raw byte representation of a private key.
314 ///
315 /// This function only works for algorithms that support raw private keys.
316 /// Currently this is: [`Id::HMAC`], [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`].
317 #[corresponds(EVP_PKEY_get_raw_private_key)]
318 #[cfg(any(ossl111, boringssl, libressl370))]
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 /// Serializes a private key into an unencrypted DER-formatted PKCS#8
339 #[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 /// Serializes a private key into a DER-formatted PKCS#8, using the supplied password to
358 /// encrypt the key.
359 #[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: &str = match self.id() {
385 Id::RSA => "RSA",
386 #[cfg(not(boringssl))]
387 Id::HMAC => "HMAC",
388 Id::DSA => "DSA",
389 Id::DH => "DH",
390 Id::EC => "EC",
391 #[cfg(ossl111)]
392 Id::ED25519 => "Ed25519",
393 #[cfg(ossl111)]
394 Id::ED448 => "Ed448",
395 _ => "unknown",
396 };
397 fmt.debug_struct("PKey").field(name:"algorithm", &alg).finish()
398 // TODO: Print details for each specific type of key
399 }
400}
401
402impl<T> Clone for PKey<T> {
403 fn clone(&self) -> PKey<T> {
404 PKeyRef::to_owned(self)
405 }
406}
407
408impl<T> PKey<T> {
409 /// Creates a new `PKey` containing an RSA key.
410 #[corresponds(EVP_PKEY_assign_RSA)]
411 pub fn from_rsa(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> {
412 unsafe {
413 let evp = cvt_p(ffi::EVP_PKEY_new())?;
414 let pkey = PKey::from_ptr(evp);
415 cvt(ffi::EVP_PKEY_assign_RSA(pkey.0, rsa.as_ptr()))?;
416 mem::forget(rsa);
417 Ok(pkey)
418 }
419 }
420
421 /// Creates a new `PKey` containing a DSA key.
422 #[corresponds(EVP_PKEY_assign_DSA)]
423 pub fn from_dsa(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> {
424 unsafe {
425 let evp = cvt_p(ffi::EVP_PKEY_new())?;
426 let pkey = PKey::from_ptr(evp);
427 cvt(ffi::EVP_PKEY_assign_DSA(pkey.0, dsa.as_ptr()))?;
428 mem::forget(dsa);
429 Ok(pkey)
430 }
431 }
432
433 /// Creates a new `PKey` containing a Diffie-Hellman key.
434 #[corresponds(EVP_PKEY_assign_DH)]
435 #[cfg(not(boringssl))]
436 pub fn from_dh(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
437 unsafe {
438 let evp = cvt_p(ffi::EVP_PKEY_new())?;
439 let pkey = PKey::from_ptr(evp);
440 cvt(ffi::EVP_PKEY_assign_DH(pkey.0, dh.as_ptr()))?;
441 mem::forget(dh);
442 Ok(pkey)
443 }
444 }
445
446 /// Creates a new `PKey` containing a Diffie-Hellman key with type DHX.
447 #[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 /// Creates a new `PKey` containing an elliptic curve key.
463 #[corresponds(EVP_PKEY_assign_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_assign_EC_KEY(pkey.0, ec_key.as_ptr()))?;
469 mem::forget(ec_key);
470 Ok(pkey)
471 }
472 }
473}
474
475impl PKey<Private> {
476 /// Creates a new `PKey` containing an HMAC key.
477 ///
478 /// # Note
479 ///
480 /// To compute HMAC values, use the `sign` module.
481 #[corresponds(EVP_PKEY_new_mac_key)]
482 #[cfg(not(boringssl))]
483 pub fn hmac(key: &[u8]) -> Result<PKey<Private>, ErrorStack> {
484 unsafe {
485 assert!(key.len() <= c_int::max_value() as usize);
486 let key = cvt_p(ffi::EVP_PKEY_new_mac_key(
487 ffi::EVP_PKEY_HMAC,
488 ptr::null_mut(),
489 key.as_ptr() as *const _,
490 key.len() as c_int,
491 ))?;
492 Ok(PKey::from_ptr(key))
493 }
494 }
495
496 /// Creates a new `PKey` containing a CMAC key.
497 ///
498 /// Requires OpenSSL 1.1.0 or newer.
499 ///
500 /// # Note
501 ///
502 /// To compute CMAC values, use the `sign` module.
503 #[cfg(all(not(boringssl), ossl110))]
504 #[allow(clippy::trivially_copy_pass_by_ref)]
505 pub fn cmac(cipher: &Cipher, key: &[u8]) -> Result<PKey<Private>, ErrorStack> {
506 let mut ctx = PkeyCtx::new_id(Id::CMAC)?;
507 ctx.keygen_init()?;
508 ctx.set_keygen_cipher(unsafe { CipherRef::from_ptr(cipher.as_ptr() as *mut _) })?;
509 ctx.set_keygen_mac_key(key)?;
510 ctx.keygen()
511 }
512
513 #[cfg(any(ossl111, boringssl, libressl370))]
514 fn generate_eddsa(id: Id) -> Result<PKey<Private>, ErrorStack> {
515 let mut ctx = PkeyCtx::new_id(id)?;
516 ctx.keygen_init()?;
517 ctx.keygen()
518 }
519
520 /// Generates a new private X25519 key.
521 ///
522 /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
523 ///
524 /// # Examples
525 ///
526 /// ```
527 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
528 /// use openssl::pkey::{PKey, Id};
529 /// use openssl::derive::Deriver;
530 ///
531 /// let public = // ...
532 /// # &PKey::generate_x25519()?.raw_public_key()?;
533 /// let public_key = PKey::public_key_from_raw_bytes(public, Id::X25519)?;
534 ///
535 /// let key = PKey::generate_x25519()?;
536 /// let mut deriver = Deriver::new(&key)?;
537 /// deriver.set_peer(&public_key)?;
538 ///
539 /// let secret = deriver.derive_to_vec()?;
540 /// assert_eq!(secret.len(), 32);
541 /// # Ok(()) }
542 /// ```
543 #[cfg(any(ossl111, boringssl, libressl370))]
544 pub fn generate_x25519() -> Result<PKey<Private>, ErrorStack> {
545 PKey::generate_eddsa(Id::X25519)
546 }
547
548 /// Generates a new private X448 key.
549 ///
550 /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
551 ///
552 /// # Examples
553 ///
554 /// ```
555 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
556 /// use openssl::pkey::{PKey, Id};
557 /// use openssl::derive::Deriver;
558 ///
559 /// let public = // ...
560 /// # &PKey::generate_x448()?.raw_public_key()?;
561 /// let public_key = PKey::public_key_from_raw_bytes(public, Id::X448)?;
562 ///
563 /// let key = PKey::generate_x448()?;
564 /// let mut deriver = Deriver::new(&key)?;
565 /// deriver.set_peer(&public_key)?;
566 ///
567 /// let secret = deriver.derive_to_vec()?;
568 /// assert_eq!(secret.len(), 56);
569 /// # Ok(()) }
570 /// ```
571 #[cfg(ossl111)]
572 pub fn generate_x448() -> Result<PKey<Private>, ErrorStack> {
573 PKey::generate_eddsa(Id::X448)
574 }
575
576 /// Generates a new private Ed25519 key.
577 ///
578 /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
579 ///
580 /// # Examples
581 ///
582 /// ```
583 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
584 /// use openssl::pkey::{PKey, Id};
585 /// use openssl::sign::Signer;
586 ///
587 /// let key = PKey::generate_ed25519()?;
588 /// let public_key = key.raw_public_key()?;
589 ///
590 /// let mut signer = Signer::new_without_digest(&key)?;
591 /// let digest = // ...
592 /// # &vec![0; 32];
593 /// let signature = signer.sign_oneshot_to_vec(digest)?;
594 /// assert_eq!(signature.len(), 64);
595 /// # Ok(()) }
596 /// ```
597 #[cfg(any(ossl111, boringssl, libressl370))]
598 pub fn generate_ed25519() -> Result<PKey<Private>, ErrorStack> {
599 PKey::generate_eddsa(Id::ED25519)
600 }
601
602 /// Generates a new private Ed448 key.
603 ///
604 /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
605 ///
606 /// # Examples
607 ///
608 /// ```
609 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
610 /// use openssl::pkey::{PKey, Id};
611 /// use openssl::sign::Signer;
612 ///
613 /// let key = PKey::generate_ed448()?;
614 /// let public_key = key.raw_public_key()?;
615 ///
616 /// let mut signer = Signer::new_without_digest(&key)?;
617 /// let digest = // ...
618 /// # &vec![0; 32];
619 /// let signature = signer.sign_oneshot_to_vec(digest)?;
620 /// assert_eq!(signature.len(), 114);
621 /// # Ok(()) }
622 /// ```
623 #[cfg(ossl111)]
624 pub fn generate_ed448() -> Result<PKey<Private>, ErrorStack> {
625 PKey::generate_eddsa(Id::ED448)
626 }
627
628 /// Generates a new EC key using the provided curve.
629 ///
630 /// Requires OpenSSL 3.0.0 or newer.
631 #[corresponds(EVP_EC_gen)]
632 #[cfg(ossl300)]
633 pub fn ec_gen(curve: &str) -> Result<PKey<Private>, ErrorStack> {
634 ffi::init();
635
636 let curve = CString::new(curve).unwrap();
637 unsafe {
638 let ptr = cvt_p(ffi::EVP_EC_gen(curve.as_ptr()))?;
639 Ok(PKey::from_ptr(ptr))
640 }
641 }
642
643 private_key_from_pem! {
644 /// Deserializes a private key from a PEM-encoded key type specific format.
645 #[corresponds(PEM_read_bio_PrivateKey)]
646 private_key_from_pem,
647
648 /// Deserializes a private key from a PEM-encoded encrypted key type specific format.
649 #[corresponds(PEM_read_bio_PrivateKey)]
650 private_key_from_pem_passphrase,
651
652 /// Deserializes a private key from a PEM-encoded encrypted key type specific format.
653 ///
654 /// The callback should fill the password into the provided buffer and return its length.
655 #[corresponds(PEM_read_bio_PrivateKey)]
656 private_key_from_pem_callback,
657 PKey<Private>,
658 ffi::PEM_read_bio_PrivateKey
659 }
660
661 from_der! {
662 /// Decodes a DER-encoded private key.
663 ///
664 /// This function will attempt to automatically detect the underlying key format, and
665 /// supports the unencrypted PKCS#8 PrivateKeyInfo structures as well as key type specific
666 /// formats.
667 #[corresponds(d2i_AutoPrivateKey)]
668 private_key_from_der,
669 PKey<Private>,
670 ffi::d2i_AutoPrivateKey
671 }
672
673 /// Deserializes a DER-formatted PKCS#8 unencrypted private key.
674 ///
675 /// This method is mainly for interoperability reasons. Encrypted keyfiles should be preferred.
676 pub fn private_key_from_pkcs8(der: &[u8]) -> Result<PKey<Private>, ErrorStack> {
677 unsafe {
678 ffi::init();
679 let len = der.len().min(c_long::max_value() as usize) as c_long;
680 let p8inf = cvt_p(ffi::d2i_PKCS8_PRIV_KEY_INFO(
681 ptr::null_mut(),
682 &mut der.as_ptr(),
683 len,
684 ))?;
685 let res = cvt_p(ffi::EVP_PKCS82PKEY(p8inf)).map(|p| PKey::from_ptr(p));
686 ffi::PKCS8_PRIV_KEY_INFO_free(p8inf);
687 res
688 }
689 }
690
691 /// Deserializes a DER-formatted PKCS#8 private key, using a callback to retrieve the password
692 /// if the key is encrypted.
693 ///
694 /// The callback should copy the password into the provided buffer and return the number of
695 /// bytes written.
696 #[corresponds(d2i_PKCS8PrivateKey_bio)]
697 pub fn private_key_from_pkcs8_callback<F>(
698 der: &[u8],
699 callback: F,
700 ) -> Result<PKey<Private>, ErrorStack>
701 where
702 F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,
703 {
704 unsafe {
705 ffi::init();
706 let mut cb = CallbackState::new(callback);
707 let bio = MemBioSlice::new(der)?;
708 cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
709 bio.as_ptr(),
710 ptr::null_mut(),
711 Some(invoke_passwd_cb::<F>),
712 &mut cb as *mut _ as *mut _,
713 ))
714 .map(|p| PKey::from_ptr(p))
715 }
716 }
717
718 /// Deserializes a DER-formatted PKCS#8 private key, using the supplied password if the key is
719 /// encrypted.
720 ///
721 /// # Panics
722 ///
723 /// Panics if `passphrase` contains an embedded null.
724 #[corresponds(d2i_PKCS8PrivateKey_bio)]
725 pub fn private_key_from_pkcs8_passphrase(
726 der: &[u8],
727 passphrase: &[u8],
728 ) -> Result<PKey<Private>, ErrorStack> {
729 unsafe {
730 ffi::init();
731 let bio = MemBioSlice::new(der)?;
732 let passphrase = CString::new(passphrase).unwrap();
733 cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
734 bio.as_ptr(),
735 ptr::null_mut(),
736 None,
737 passphrase.as_ptr() as *const _ as *mut _,
738 ))
739 .map(|p| PKey::from_ptr(p))
740 }
741 }
742
743 /// Creates a private key from its raw byte representation
744 ///
745 /// Algorithm types that support raw private keys are HMAC, X25519, ED25519, X448 or ED448
746 #[corresponds(EVP_PKEY_new_raw_private_key)]
747 #[cfg(any(ossl111, boringssl, libressl370))]
748 pub fn private_key_from_raw_bytes(
749 bytes: &[u8],
750 key_type: Id,
751 ) -> Result<PKey<Private>, ErrorStack> {
752 unsafe {
753 ffi::init();
754 cvt_p(ffi::EVP_PKEY_new_raw_private_key(
755 key_type.as_raw(),
756 ptr::null_mut(),
757 bytes.as_ptr(),
758 bytes.len(),
759 ))
760 .map(|p| PKey::from_ptr(p))
761 }
762 }
763}
764
765impl PKey<Public> {
766 private_key_from_pem! {
767 /// Decodes a PEM-encoded SubjectPublicKeyInfo structure.
768 ///
769 /// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
770 #[corresponds(PEM_read_bio_PUBKEY)]
771 public_key_from_pem,
772
773 /// Decodes a PEM-encoded SubjectPublicKeyInfo structure.
774 #[corresponds(PEM_read_bio_PUBKEY)]
775 public_key_from_pem_passphrase,
776
777 /// Decodes a PEM-encoded SubjectPublicKeyInfo structure.
778 ///
779 /// The callback should fill the password into the provided buffer and return its length.
780 #[corresponds(PEM_read_bio_PrivateKey)]
781 public_key_from_pem_callback,
782 PKey<Public>,
783 ffi::PEM_read_bio_PUBKEY
784 }
785
786 from_der! {
787 /// Decodes a DER-encoded SubjectPublicKeyInfo structure.
788 #[corresponds(d2i_PUBKEY)]
789 public_key_from_der,
790 PKey<Public>,
791 ffi::d2i_PUBKEY
792 }
793
794 /// Creates a public key from its raw byte representation
795 ///
796 /// Algorithm types that support raw public keys are X25519, ED25519, X448 or ED448
797 #[corresponds(EVP_PKEY_new_raw_public_key)]
798 #[cfg(any(ossl111, boringssl, libressl370))]
799 pub fn public_key_from_raw_bytes(
800 bytes: &[u8],
801 key_type: Id,
802 ) -> Result<PKey<Public>, ErrorStack> {
803 unsafe {
804 ffi::init();
805 cvt_p(ffi::EVP_PKEY_new_raw_public_key(
806 key_type.as_raw(),
807 ptr::null_mut(),
808 bytes.as_ptr(),
809 bytes.len(),
810 ))
811 .map(|p| PKey::from_ptr(p))
812 }
813 }
814}
815
816cfg_if! {
817 if #[cfg(any(boringssl, ossl110, libressl270))] {
818 use ffi::EVP_PKEY_up_ref;
819 } else {
820 #[allow(bad_style)]
821 unsafe extern "C" fn EVP_PKEY_up_ref(pkey: *mut ffi::EVP_PKEY) {
822 ffi::CRYPTO_add_lock(
823 &mut (*pkey).references,
824 1,
825 ffi::CRYPTO_LOCK_EVP_PKEY,
826 "pkey.rs\0".as_ptr() as *const _,
827 line!() as c_int,
828 );
829 }
830 }
831}
832
833impl<T> TryFrom<EcKey<T>> for PKey<T> {
834 type Error = ErrorStack;
835
836 fn try_from(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> {
837 PKey::from_ec_key(ec_key)
838 }
839}
840
841impl<T> TryFrom<PKey<T>> for EcKey<T> {
842 type Error = ErrorStack;
843
844 fn try_from(pkey: PKey<T>) -> Result<EcKey<T>, ErrorStack> {
845 pkey.ec_key()
846 }
847}
848
849impl<T> TryFrom<Rsa<T>> for PKey<T> {
850 type Error = ErrorStack;
851
852 fn try_from(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> {
853 PKey::from_rsa(rsa)
854 }
855}
856
857impl<T> TryFrom<PKey<T>> for Rsa<T> {
858 type Error = ErrorStack;
859
860 fn try_from(pkey: PKey<T>) -> Result<Rsa<T>, ErrorStack> {
861 pkey.rsa()
862 }
863}
864
865impl<T> TryFrom<Dsa<T>> for PKey<T> {
866 type Error = ErrorStack;
867
868 fn try_from(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> {
869 PKey::from_dsa(dsa)
870 }
871}
872
873impl<T> TryFrom<PKey<T>> for Dsa<T> {
874 type Error = ErrorStack;
875
876 fn try_from(pkey: PKey<T>) -> Result<Dsa<T>, ErrorStack> {
877 pkey.dsa()
878 }
879}
880
881#[cfg(not(boringssl))]
882impl<T> TryFrom<Dh<T>> for PKey<T> {
883 type Error = ErrorStack;
884
885 fn try_from(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
886 PKey::from_dh(dh)
887 }
888}
889
890impl<T> TryFrom<PKey<T>> for Dh<T> {
891 type Error = ErrorStack;
892
893 fn try_from(pkey: PKey<T>) -> Result<Dh<T>, ErrorStack> {
894 pkey.dh()
895 }
896}
897
898#[cfg(test)]
899mod tests {
900 use std::convert::TryInto;
901
902 #[cfg(not(boringssl))]
903 use crate::dh::Dh;
904 use crate::dsa::Dsa;
905 use crate::ec::EcKey;
906 use crate::error::Error;
907 use crate::nid::Nid;
908 use crate::rsa::Rsa;
909 use crate::symm::Cipher;
910
911 use super::*;
912
913 #[cfg(ossl111)]
914 use crate::rand::rand_bytes;
915
916 #[test]
917 fn test_to_password() {
918 let rsa = Rsa::generate(2048).unwrap();
919 let pkey = PKey::from_rsa(rsa).unwrap();
920 let pem = pkey
921 .private_key_to_pem_pkcs8_passphrase(Cipher::aes_128_cbc(), b"foobar")
922 .unwrap();
923 PKey::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
924 assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
925 }
926
927 #[test]
928 fn test_unencrypted_pkcs8() {
929 let key = include_bytes!("../test/pkcs8-nocrypt.der");
930 let pkey = PKey::private_key_from_pkcs8(key).unwrap();
931 let serialized = pkey.private_key_to_pkcs8().unwrap();
932 let pkey2 = PKey::private_key_from_pkcs8(&serialized).unwrap();
933
934 assert_eq!(
935 pkey2.private_key_to_der().unwrap(),
936 pkey.private_key_to_der().unwrap()
937 );
938 }
939
940 #[test]
941 fn test_encrypted_pkcs8_passphrase() {
942 let key = include_bytes!("../test/pkcs8.der");
943 PKey::private_key_from_pkcs8_passphrase(key, b"mypass").unwrap();
944
945 let rsa = Rsa::generate(2048).unwrap();
946 let pkey = PKey::from_rsa(rsa).unwrap();
947 let der = pkey
948 .private_key_to_pkcs8_passphrase(Cipher::aes_128_cbc(), b"mypass")
949 .unwrap();
950 let pkey2 = PKey::private_key_from_pkcs8_passphrase(&der, b"mypass").unwrap();
951 assert_eq!(
952 pkey.private_key_to_der().unwrap(),
953 pkey2.private_key_to_der().unwrap()
954 );
955 }
956
957 #[test]
958 fn test_encrypted_pkcs8_callback() {
959 let mut password_queried = false;
960 let key = include_bytes!("../test/pkcs8.der");
961 PKey::private_key_from_pkcs8_callback(key, |password| {
962 password_queried = true;
963 password[..6].copy_from_slice(b"mypass");
964 Ok(6)
965 })
966 .unwrap();
967 assert!(password_queried);
968 }
969
970 #[test]
971 fn test_private_key_from_pem() {
972 let key = include_bytes!("../test/key.pem");
973 PKey::private_key_from_pem(key).unwrap();
974 }
975
976 #[test]
977 fn test_public_key_from_pem() {
978 let key = include_bytes!("../test/key.pem.pub");
979 PKey::public_key_from_pem(key).unwrap();
980 }
981
982 #[test]
983 fn test_public_key_from_der() {
984 let key = include_bytes!("../test/key.der.pub");
985 PKey::public_key_from_der(key).unwrap();
986 }
987
988 #[test]
989 fn test_private_key_from_der() {
990 let key = include_bytes!("../test/key.der");
991 PKey::private_key_from_der(key).unwrap();
992 }
993
994 #[test]
995 fn test_pem() {
996 let key = include_bytes!("../test/key.pem");
997 let key = PKey::private_key_from_pem(key).unwrap();
998
999 let priv_key = key.private_key_to_pem_pkcs8().unwrap();
1000 let pub_key = key.public_key_to_pem().unwrap();
1001
1002 // As a super-simple verification, just check that the buffers contain
1003 // the `PRIVATE KEY` or `PUBLIC KEY` strings.
1004 assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY"));
1005 assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY"));
1006 }
1007
1008 #[test]
1009 fn test_rsa_accessor() {
1010 let rsa = Rsa::generate(2048).unwrap();
1011 let pkey = PKey::from_rsa(rsa).unwrap();
1012 pkey.rsa().unwrap();
1013 assert_eq!(pkey.id(), Id::RSA);
1014 assert!(pkey.dsa().is_err());
1015 }
1016
1017 #[test]
1018 fn test_dsa_accessor() {
1019 let dsa = Dsa::generate(2048).unwrap();
1020 let pkey = PKey::from_dsa(dsa).unwrap();
1021 pkey.dsa().unwrap();
1022 assert_eq!(pkey.id(), Id::DSA);
1023 assert!(pkey.rsa().is_err());
1024 }
1025
1026 #[test]
1027 #[cfg(not(boringssl))]
1028 fn test_dh_accessor() {
1029 let dh = include_bytes!("../test/dhparams.pem");
1030 let dh = Dh::params_from_pem(dh).unwrap();
1031 let pkey = PKey::from_dh(dh).unwrap();
1032 pkey.dh().unwrap();
1033 assert_eq!(pkey.id(), Id::DH);
1034 assert!(pkey.rsa().is_err());
1035 }
1036
1037 #[test]
1038 fn test_ec_key_accessor() {
1039 let ec_key = EcKey::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
1040 let pkey = PKey::from_ec_key(ec_key).unwrap();
1041 pkey.ec_key().unwrap();
1042 assert_eq!(pkey.id(), Id::EC);
1043 assert!(pkey.rsa().is_err());
1044 }
1045
1046 #[test]
1047 fn test_rsa_conversion() {
1048 let rsa = Rsa::generate(2048).unwrap();
1049 let pkey: PKey<Private> = rsa.clone().try_into().unwrap();
1050 let rsa_: Rsa<Private> = pkey.try_into().unwrap();
1051 // Eq is missing
1052 assert_eq!(rsa.p(), rsa_.p());
1053 assert_eq!(rsa.q(), rsa_.q());
1054 }
1055
1056 #[test]
1057 fn test_dsa_conversion() {
1058 let dsa = Dsa::generate(2048).unwrap();
1059 let pkey: PKey<Private> = dsa.clone().try_into().unwrap();
1060 let dsa_: Dsa<Private> = pkey.try_into().unwrap();
1061 // Eq is missing
1062 assert_eq!(dsa.priv_key(), dsa_.priv_key());
1063 }
1064
1065 #[test]
1066 fn test_ec_key_conversion() {
1067 let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::X9_62_PRIME256V1).unwrap();
1068 let ec_key = EcKey::generate(&group).unwrap();
1069 let pkey: PKey<Private> = ec_key.clone().try_into().unwrap();
1070 let ec_key_: EcKey<Private> = pkey.try_into().unwrap();
1071 // Eq is missing
1072 assert_eq!(ec_key.private_key(), ec_key_.private_key());
1073 }
1074
1075 #[test]
1076 #[cfg(any(ossl110, libressl360))]
1077 fn test_security_bits() {
1078 let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::SECP521R1).unwrap();
1079 let ec_key = EcKey::generate(&group).unwrap();
1080 let pkey: PKey<Private> = ec_key.try_into().unwrap();
1081
1082 assert_eq!(pkey.security_bits(), 256);
1083 }
1084
1085 #[test]
1086 #[cfg(not(boringssl))]
1087 fn test_dh_conversion() {
1088 let dh_params = include_bytes!("../test/dhparams.pem");
1089 let dh_params = Dh::params_from_pem(dh_params).unwrap();
1090 let dh = dh_params.generate_key().unwrap();
1091
1092 // Clone is missing for Dh, save the parameters
1093 let p = dh.prime_p().to_owned().unwrap();
1094 let q = dh.prime_q().map(|q| q.to_owned().unwrap());
1095 let g = dh.generator().to_owned().unwrap();
1096
1097 let pkey: PKey<Private> = dh.try_into().unwrap();
1098 let dh_: Dh<Private> = pkey.try_into().unwrap();
1099
1100 // Eq is missing
1101 assert_eq!(&p, dh_.prime_p());
1102 assert_eq!(q, dh_.prime_q().map(|q| q.to_owned().unwrap()));
1103 assert_eq!(&g, dh_.generator());
1104 }
1105
1106 #[cfg(any(ossl111, boringssl, libressl370))]
1107 fn test_raw_public_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) {
1108 // Generate a new key
1109 let key = gen().unwrap();
1110
1111 // Get the raw bytes, and create a new key from the raw bytes
1112 let raw = key.raw_public_key().unwrap();
1113 let from_raw = PKey::public_key_from_raw_bytes(&raw, key_type).unwrap();
1114
1115 // Compare the der encoding of the original and raw / restored public key
1116 assert_eq!(
1117 key.public_key_to_der().unwrap(),
1118 from_raw.public_key_to_der().unwrap()
1119 );
1120 }
1121
1122 #[cfg(any(ossl111, boringssl, libressl370))]
1123 fn test_raw_private_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) {
1124 // Generate a new key
1125 let key = gen().unwrap();
1126
1127 // Get the raw bytes, and create a new key from the raw bytes
1128 let raw = key.raw_private_key().unwrap();
1129 let from_raw = PKey::private_key_from_raw_bytes(&raw, key_type).unwrap();
1130
1131 // Compare the der encoding of the original and raw / restored public key
1132 assert_eq!(
1133 key.private_key_to_pkcs8().unwrap(),
1134 from_raw.private_key_to_pkcs8().unwrap()
1135 );
1136 }
1137
1138 #[cfg(any(ossl111, boringssl, libressl370))]
1139 #[test]
1140 fn test_raw_public_key_bytes() {
1141 test_raw_public_key(PKey::generate_x25519, Id::X25519);
1142 test_raw_public_key(PKey::generate_ed25519, Id::ED25519);
1143 #[cfg(all(not(boringssl), not(libressl370)))]
1144 test_raw_public_key(PKey::generate_x448, Id::X448);
1145 #[cfg(all(not(boringssl), not(libressl370)))]
1146 test_raw_public_key(PKey::generate_ed448, Id::ED448);
1147 }
1148
1149 #[cfg(any(ossl111, boringssl, libressl370))]
1150 #[test]
1151 fn test_raw_private_key_bytes() {
1152 test_raw_private_key(PKey::generate_x25519, Id::X25519);
1153 test_raw_private_key(PKey::generate_ed25519, Id::ED25519);
1154 #[cfg(all(not(boringssl), not(libressl370)))]
1155 test_raw_private_key(PKey::generate_x448, Id::X448);
1156 #[cfg(all(not(boringssl), not(libressl370)))]
1157 test_raw_private_key(PKey::generate_ed448, Id::ED448);
1158 }
1159
1160 #[cfg(ossl111)]
1161 #[test]
1162 fn test_raw_hmac() {
1163 let mut test_bytes = vec![0u8; 32];
1164 rand_bytes(&mut test_bytes).unwrap();
1165
1166 let hmac_key = PKey::hmac(&test_bytes).unwrap();
1167 assert!(hmac_key.raw_public_key().is_err());
1168
1169 let key_bytes = hmac_key.raw_private_key().unwrap();
1170 assert_eq!(key_bytes, test_bytes);
1171 }
1172
1173 #[cfg(ossl111)]
1174 #[test]
1175 fn test_raw_key_fail() {
1176 // Getting a raw byte representation will not work with Nist curves
1177 let group = crate::ec::EcGroup::from_curve_name(Nid::SECP256K1).unwrap();
1178 let ec_key = EcKey::generate(&group).unwrap();
1179 let pkey = PKey::from_ec_key(ec_key).unwrap();
1180 assert!(pkey.raw_private_key().is_err());
1181 assert!(pkey.raw_public_key().is_err());
1182 }
1183
1184 #[cfg(ossl300)]
1185 #[test]
1186 fn test_ec_gen() {
1187 let key = PKey::ec_gen("prime256v1").unwrap();
1188 assert!(key.ec_key().is_ok());
1189 }
1190
1191 #[test]
1192 fn test_public_eq() {
1193 let rsa = Rsa::generate(2048).unwrap();
1194 let pkey1 = PKey::from_rsa(rsa).unwrap();
1195
1196 let group = crate::ec::EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
1197 let ec_key = EcKey::generate(&group).unwrap();
1198 let pkey2 = PKey::from_ec_key(ec_key).unwrap();
1199
1200 assert!(!pkey1.public_eq(&pkey2));
1201 assert!(Error::get().is_none());
1202 }
1203}
1204