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)] 43 use crate::bio::{MemBio, MemBioSlice}; 44 #[cfg(ossl110)] 45 use crate::cipher::CipherRef; 46 use crate::dh::Dh; 47 use crate::dsa::Dsa; 48 use crate::ec::EcKey; 49 use crate::error::ErrorStack; 50 #[cfg(any(boringssl, ossl110))] 51 use crate::pkey_ctx::PkeyCtx; 52 use crate::rsa::Rsa; 53 use crate::symm::Cipher; 54 use crate::util::{invoke_passwd_cb, CallbackState}; 55 use crate::{cvt, cvt_p}; 56 use cfg_if::cfg_if; 57 use foreign_types::{ForeignType, ForeignTypeRef}; 58 use libc::{c_int, c_long}; 59 use openssl_macros::corresponds; 60 use std::convert::TryFrom; 61 use std::ffi::CString; 62 use std::fmt; 63 use std::mem; 64 use std::ptr; 65 66 /// A tag type indicating that a key only has parameters. 67 pub enum Params {} 68 69 /// A tag type indicating that a key only has public components. 70 pub enum Public {} 71 72 /// A tag type indicating that a key has private components. 73 pub enum Private {} 74 75 /// An identifier of a kind of key. 76 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 77 pub struct Id(c_int); 78 79 impl Id { 80 pub const RSA: Id = Id(ffi::EVP_PKEY_RSA); 81 #[cfg(not(boringssl))] 82 pub const HMAC: Id = Id(ffi::EVP_PKEY_HMAC); 83 #[cfg(not(boringssl))] 84 pub const CMAC: Id = Id(ffi::EVP_PKEY_CMAC); 85 pub const DSA: Id = Id(ffi::EVP_PKEY_DSA); 86 pub const DH: Id = Id(ffi::EVP_PKEY_DH); 87 pub const EC: Id = Id(ffi::EVP_PKEY_EC); 88 89 #[cfg(ossl110)] 90 pub const HKDF: Id = Id(ffi::EVP_PKEY_HKDF); 91 92 #[cfg(any(boringssl, ossl111))] 93 pub const ED25519: Id = Id(ffi::EVP_PKEY_ED25519); 94 #[cfg(ossl111)] 95 pub const ED448: Id = Id(ffi::EVP_PKEY_ED448); 96 #[cfg(any(boringssl, ossl111))] 97 pub const X25519: Id = Id(ffi::EVP_PKEY_X25519); 98 #[cfg(ossl111)] 99 pub const X448: Id = Id(ffi::EVP_PKEY_X448); 100 101 /// Creates a `Id` from an integer representation. from_raw(value: c_int) -> Id102 pub fn from_raw(value: c_int) -> Id { 103 Id(value) 104 } 105 106 /// Returns the integer representation of the `Id`. 107 #[allow(clippy::trivially_copy_pass_by_ref)] as_raw(&self) -> c_int108 pub fn as_raw(&self) -> c_int { 109 self.0 110 } 111 } 112 113 /// A trait indicating that a key has parameters. 114 pub unsafe trait HasParams {} 115 116 unsafe impl HasParams for Params {} 117 118 unsafe impl<T> HasParams for T where T: HasPublic {} 119 120 /// A trait indicating that a key has public components. 121 pub unsafe trait HasPublic {} 122 123 unsafe impl HasPublic for Public {} 124 125 unsafe impl<T> HasPublic for T where T: HasPrivate {} 126 127 /// A trait indicating that a key has private components. 128 pub unsafe trait HasPrivate {} 129 130 unsafe impl HasPrivate for Private {} 131 132 generic_foreign_type_and_impl_send_sync! { 133 type CType = ffi::EVP_PKEY; 134 fn drop = ffi::EVP_PKEY_free; 135 136 /// A public or private key. 137 pub struct PKey<T>; 138 /// Reference to `PKey`. 139 pub struct PKeyRef<T>; 140 } 141 142 impl<T> ToOwned for PKeyRef<T> { 143 type Owned = PKey<T>; 144 to_owned(&self) -> PKey<T>145 fn to_owned(&self) -> PKey<T> { 146 unsafe { 147 EVP_PKEY_up_ref(self.as_ptr()); 148 PKey::from_ptr(self.as_ptr()) 149 } 150 } 151 } 152 153 impl<T> PKeyRef<T> { 154 /// Returns a copy of the internal RSA key. 155 #[corresponds(EVP_PKEY_get1_RSA)] rsa(&self) -> Result<Rsa<T>, ErrorStack>156 pub fn rsa(&self) -> Result<Rsa<T>, ErrorStack> { 157 unsafe { 158 let rsa = cvt_p(ffi::EVP_PKEY_get1_RSA(self.as_ptr()))?; 159 Ok(Rsa::from_ptr(rsa)) 160 } 161 } 162 163 /// Returns a copy of the internal DSA key. 164 #[corresponds(EVP_PKEY_get1_DSA)] dsa(&self) -> Result<Dsa<T>, ErrorStack>165 pub fn dsa(&self) -> Result<Dsa<T>, ErrorStack> { 166 unsafe { 167 let dsa = cvt_p(ffi::EVP_PKEY_get1_DSA(self.as_ptr()))?; 168 Ok(Dsa::from_ptr(dsa)) 169 } 170 } 171 172 /// Returns a copy of the internal DH key. 173 #[corresponds(EVP_PKEY_get1_DH)] dh(&self) -> Result<Dh<T>, ErrorStack>174 pub fn dh(&self) -> Result<Dh<T>, ErrorStack> { 175 unsafe { 176 let dh = cvt_p(ffi::EVP_PKEY_get1_DH(self.as_ptr()))?; 177 Ok(Dh::from_ptr(dh)) 178 } 179 } 180 181 /// Returns a copy of the internal elliptic curve key. 182 #[corresponds(EVP_PKEY_get1_EC_KEY)] ec_key(&self) -> Result<EcKey<T>, ErrorStack>183 pub fn ec_key(&self) -> Result<EcKey<T>, ErrorStack> { 184 unsafe { 185 let ec_key = cvt_p(ffi::EVP_PKEY_get1_EC_KEY(self.as_ptr()))?; 186 Ok(EcKey::from_ptr(ec_key)) 187 } 188 } 189 190 /// Returns the `Id` that represents the type of this key. 191 #[corresponds(EVP_PKEY_id)] id(&self) -> Id192 pub fn id(&self) -> Id { 193 unsafe { Id::from_raw(ffi::EVP_PKEY_id(self.as_ptr())) } 194 } 195 196 /// Returns the maximum size of a signature in bytes. 197 #[corresponds(EVP_PKEY_size)] size(&self) -> usize198 pub fn size(&self) -> usize { 199 unsafe { ffi::EVP_PKEY_size(self.as_ptr()) as usize } 200 } 201 } 202 203 impl<T> PKeyRef<T> 204 where 205 T: HasPublic, 206 { 207 to_pem! { 208 /// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure. 209 /// 210 /// The output will have a header of `-----BEGIN PUBLIC KEY-----`. 211 #[corresponds(PEM_write_bio_PUBKEY)] 212 public_key_to_pem, 213 ffi::PEM_write_bio_PUBKEY 214 } 215 216 to_der! { 217 /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure. 218 #[corresponds(i2d_PUBKEY)] 219 public_key_to_der, 220 ffi::i2d_PUBKEY 221 } 222 223 /// Returns the size of the key. 224 /// 225 /// This corresponds to the bit length of the modulus of an RSA key, and the bit length of the 226 /// group order for an elliptic curve key, for example. 227 #[corresponds(EVP_PKEY_bits)] bits(&self) -> u32228 pub fn bits(&self) -> u32 { 229 unsafe { ffi::EVP_PKEY_bits(self.as_ptr()) as u32 } 230 } 231 232 ///Returns the number of security bits. 233 /// 234 ///Bits of security is defined in NIST SP800-57. 235 #[corresponds(EVP_PKEY_security_bits)] 236 #[cfg(any(ossl110, libressl360))] security_bits(&self) -> u32237 pub fn security_bits(&self) -> u32 { 238 unsafe { ffi::EVP_PKEY_security_bits(self.as_ptr()) as u32 } 239 } 240 241 /// Compares the public component of this key with another. 242 #[corresponds(EVP_PKEY_cmp)] public_eq<U>(&self, other: &PKeyRef<U>) -> bool where U: HasPublic,243 pub fn public_eq<U>(&self, other: &PKeyRef<U>) -> bool 244 where 245 U: HasPublic, 246 { 247 unsafe { ffi::EVP_PKEY_cmp(self.as_ptr(), other.as_ptr()) == 1 } 248 } 249 250 /// Raw byte representation of a public key. 251 /// 252 /// This function only works for algorithms that support raw public keys. 253 /// Currently this is: [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`]. 254 #[corresponds(EVP_PKEY_get_raw_public_key)] 255 #[cfg(any(boringssl, ossl111))] raw_public_key(&self) -> Result<Vec<u8>, ErrorStack>256 pub fn raw_public_key(&self) -> Result<Vec<u8>, ErrorStack> { 257 unsafe { 258 let mut len = 0; 259 cvt(ffi::EVP_PKEY_get_raw_public_key( 260 self.as_ptr(), 261 ptr::null_mut(), 262 &mut len, 263 ))?; 264 let mut buf = vec![0u8; len]; 265 cvt(ffi::EVP_PKEY_get_raw_public_key( 266 self.as_ptr(), 267 buf.as_mut_ptr(), 268 &mut len, 269 ))?; 270 buf.truncate(len); 271 Ok(buf) 272 } 273 } 274 } 275 276 impl<T> PKeyRef<T> 277 where 278 T: HasPrivate, 279 { 280 private_key_to_pem! { 281 /// Serializes the private key to a PEM-encoded PKCS#8 PrivateKeyInfo structure. 282 /// 283 /// The output will have a header of `-----BEGIN PRIVATE KEY-----`. 284 #[corresponds(PEM_write_bio_PKCS8PrivateKey)] 285 private_key_to_pem_pkcs8, 286 /// Serializes the private key to a PEM-encoded PKCS#8 EncryptedPrivateKeyInfo structure. 287 /// 288 /// The output will have a header of `-----BEGIN ENCRYPTED PRIVATE KEY-----`. 289 #[corresponds(PEM_write_bio_PKCS8PrivateKey)] 290 private_key_to_pem_pkcs8_passphrase, 291 ffi::PEM_write_bio_PKCS8PrivateKey 292 } 293 294 to_der! { 295 /// Serializes the private key to a DER-encoded key type specific format. 296 #[corresponds(i2d_PrivateKey)] 297 private_key_to_der, 298 ffi::i2d_PrivateKey 299 } 300 301 /// Raw byte representation of a private key. 302 /// 303 /// This function only works for algorithms that support raw private keys. 304 /// Currently this is: [`Id::HMAC`], [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`]. 305 #[corresponds(EVP_PKEY_get_raw_private_key)] 306 #[cfg(any(boringssl, ossl111))] raw_private_key(&self) -> Result<Vec<u8>, ErrorStack>307 pub fn raw_private_key(&self) -> Result<Vec<u8>, ErrorStack> { 308 unsafe { 309 let mut len = 0; 310 cvt(ffi::EVP_PKEY_get_raw_private_key( 311 self.as_ptr(), 312 ptr::null_mut(), 313 &mut len, 314 ))?; 315 let mut buf = vec![0u8; len]; 316 cvt(ffi::EVP_PKEY_get_raw_private_key( 317 self.as_ptr(), 318 buf.as_mut_ptr(), 319 &mut len, 320 ))?; 321 buf.truncate(len); 322 Ok(buf) 323 } 324 } 325 326 /// Serializes a private key into a DER-formatted PKCS#8, using the supplied password to 327 /// encrypt the key. 328 /// 329 /// # Panics 330 /// 331 /// Panics if `passphrase` contains an embedded null. 332 #[corresponds(i2d_PKCS8PrivateKey_bio)] private_key_to_pkcs8_passphrase( &self, cipher: Cipher, passphrase: &[u8], ) -> Result<Vec<u8>, ErrorStack>333 pub fn private_key_to_pkcs8_passphrase( 334 &self, 335 cipher: Cipher, 336 passphrase: &[u8], 337 ) -> Result<Vec<u8>, ErrorStack> { 338 unsafe { 339 let bio = MemBio::new()?; 340 let len = passphrase.len(); 341 let passphrase = CString::new(passphrase).unwrap(); 342 cvt(ffi::i2d_PKCS8PrivateKey_bio( 343 bio.as_ptr(), 344 self.as_ptr(), 345 cipher.as_ptr(), 346 passphrase.as_ptr() as *const _ as *mut _, 347 len as ::libc::c_int, 348 None, 349 ptr::null_mut(), 350 ))?; 351 352 Ok(bio.get_buf().to_owned()) 353 } 354 } 355 } 356 357 impl<T> fmt::Debug for PKey<T> { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result358 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 359 let alg = match self.id() { 360 Id::RSA => "RSA", 361 #[cfg(not(boringssl))] 362 Id::HMAC => "HMAC", 363 Id::DSA => "DSA", 364 Id::DH => "DH", 365 Id::EC => "EC", 366 #[cfg(ossl111)] 367 Id::ED25519 => "Ed25519", 368 #[cfg(ossl111)] 369 Id::ED448 => "Ed448", 370 _ => "unknown", 371 }; 372 fmt.debug_struct("PKey").field("algorithm", &alg).finish() 373 // TODO: Print details for each specific type of key 374 } 375 } 376 377 impl<T> Clone for PKey<T> { clone(&self) -> PKey<T>378 fn clone(&self) -> PKey<T> { 379 PKeyRef::to_owned(self) 380 } 381 } 382 383 impl<T> PKey<T> { 384 /// Creates a new `PKey` containing an RSA key. 385 #[corresponds(EVP_PKEY_assign_RSA)] from_rsa(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack>386 pub fn from_rsa(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> { 387 unsafe { 388 let evp = cvt_p(ffi::EVP_PKEY_new())?; 389 let pkey = PKey::from_ptr(evp); 390 cvt(ffi::EVP_PKEY_assign( 391 pkey.0, 392 ffi::EVP_PKEY_RSA, 393 rsa.as_ptr() as *mut _, 394 ))?; 395 mem::forget(rsa); 396 Ok(pkey) 397 } 398 } 399 400 /// Creates a new `PKey` containing a DSA key. 401 #[corresponds(EVP_PKEY_assign_DSA)] from_dsa(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack>402 pub fn from_dsa(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> { 403 unsafe { 404 let evp = cvt_p(ffi::EVP_PKEY_new())?; 405 let pkey = PKey::from_ptr(evp); 406 cvt(ffi::EVP_PKEY_assign( 407 pkey.0, 408 ffi::EVP_PKEY_DSA, 409 dsa.as_ptr() as *mut _, 410 ))?; 411 mem::forget(dsa); 412 Ok(pkey) 413 } 414 } 415 416 /// Creates a new `PKey` containing a Diffie-Hellman key. 417 #[corresponds(EVP_PKEY_assign_DH)] from_dh(dh: Dh<T>) -> Result<PKey<T>, ErrorStack>418 pub fn from_dh(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> { 419 unsafe { 420 let evp = cvt_p(ffi::EVP_PKEY_new())?; 421 let pkey = PKey::from_ptr(evp); 422 cvt(ffi::EVP_PKEY_assign( 423 pkey.0, 424 ffi::EVP_PKEY_DH, 425 dh.as_ptr() as *mut _, 426 ))?; 427 mem::forget(dh); 428 Ok(pkey) 429 } 430 } 431 432 /// Creates a new `PKey` containing an elliptic curve key. 433 #[corresponds(EVP_PKEY_assign_EC_KEY)] from_ec_key(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack>434 pub fn from_ec_key(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> { 435 unsafe { 436 let evp = cvt_p(ffi::EVP_PKEY_new())?; 437 let pkey = PKey::from_ptr(evp); 438 cvt(ffi::EVP_PKEY_assign( 439 pkey.0, 440 ffi::EVP_PKEY_EC, 441 ec_key.as_ptr() as *mut _, 442 ))?; 443 mem::forget(ec_key); 444 Ok(pkey) 445 } 446 } 447 } 448 449 impl PKey<Private> { 450 /// Creates a new `PKey` containing an HMAC key. 451 /// 452 /// # Note 453 /// 454 /// To compute HMAC values, use the `sign` module. 455 #[corresponds(EVP_PKEY_new_mac_key)] 456 #[cfg(not(boringssl))] hmac(key: &[u8]) -> Result<PKey<Private>, ErrorStack>457 pub fn hmac(key: &[u8]) -> Result<PKey<Private>, ErrorStack> { 458 unsafe { 459 assert!(key.len() <= c_int::max_value() as usize); 460 let key = cvt_p(ffi::EVP_PKEY_new_mac_key( 461 ffi::EVP_PKEY_HMAC, 462 ptr::null_mut(), 463 key.as_ptr() as *const _, 464 key.len() as c_int, 465 ))?; 466 Ok(PKey::from_ptr(key)) 467 } 468 } 469 470 /// Creates a new `PKey` containing a CMAC key. 471 /// 472 /// Requires OpenSSL 1.1.0 or newer. 473 /// 474 /// # Note 475 /// 476 /// To compute CMAC values, use the `sign` module. 477 #[cfg(all(not(boringssl), ossl110))] 478 #[allow(clippy::trivially_copy_pass_by_ref)] cmac(cipher: &Cipher, key: &[u8]) -> Result<PKey<Private>, ErrorStack>479 pub fn cmac(cipher: &Cipher, key: &[u8]) -> Result<PKey<Private>, ErrorStack> { 480 let mut ctx = PkeyCtx::new_id(Id::CMAC)?; 481 ctx.keygen_init()?; 482 ctx.set_keygen_cipher(unsafe { CipherRef::from_ptr(cipher.as_ptr() as *mut _) })?; 483 ctx.set_keygen_mac_key(key)?; 484 ctx.keygen() 485 } 486 487 #[cfg(any(boringssl, ossl111))] generate_eddsa(id: Id) -> Result<PKey<Private>, ErrorStack>488 fn generate_eddsa(id: Id) -> Result<PKey<Private>, ErrorStack> { 489 let mut ctx = PkeyCtx::new_id(id)?; 490 ctx.keygen_init()?; 491 ctx.keygen() 492 } 493 494 /// Generates a new private X25519 key. 495 /// 496 /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`]. 497 /// 498 /// # Examples 499 /// 500 /// ``` 501 /// # fn main() -> Result<(), Box<dyn std::error::Error>> { 502 /// use openssl::pkey::{PKey, Id}; 503 /// use openssl::derive::Deriver; 504 /// 505 /// let public = // ... 506 /// # &PKey::generate_x25519()?.raw_public_key()?; 507 /// let public_key = PKey::public_key_from_raw_bytes(public, Id::X25519)?; 508 /// 509 /// let key = PKey::generate_x25519()?; 510 /// let mut deriver = Deriver::new(&key)?; 511 /// deriver.set_peer(&public_key)?; 512 /// 513 /// let secret = deriver.derive_to_vec()?; 514 /// assert_eq!(secret.len(), 32); 515 /// # Ok(()) } 516 /// ``` 517 #[cfg(any(boringssl, ossl111))] generate_x25519() -> Result<PKey<Private>, ErrorStack>518 pub fn generate_x25519() -> Result<PKey<Private>, ErrorStack> { 519 PKey::generate_eddsa(Id::X25519) 520 } 521 522 /// Generates a new private X448 key. 523 /// 524 /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`]. 525 /// 526 /// # Examples 527 /// 528 /// ``` 529 /// # fn main() -> Result<(), Box<dyn std::error::Error>> { 530 /// use openssl::pkey::{PKey, Id}; 531 /// use openssl::derive::Deriver; 532 /// 533 /// let public = // ... 534 /// # &PKey::generate_x448()?.raw_public_key()?; 535 /// let public_key = PKey::public_key_from_raw_bytes(public, Id::X448)?; 536 /// 537 /// let key = PKey::generate_x448()?; 538 /// let mut deriver = Deriver::new(&key)?; 539 /// deriver.set_peer(&public_key)?; 540 /// 541 /// let secret = deriver.derive_to_vec()?; 542 /// assert_eq!(secret.len(), 56); 543 /// # Ok(()) } 544 /// ``` 545 #[cfg(ossl111)] generate_x448() -> Result<PKey<Private>, ErrorStack>546 pub fn generate_x448() -> Result<PKey<Private>, ErrorStack> { 547 PKey::generate_eddsa(Id::X448) 548 } 549 550 /// Generates a new private Ed25519 key. 551 /// 552 /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`]. 553 /// 554 /// # Examples 555 /// 556 /// ``` 557 /// # fn main() -> Result<(), Box<dyn std::error::Error>> { 558 /// use openssl::pkey::{PKey, Id}; 559 /// use openssl::sign::Signer; 560 /// 561 /// let key = PKey::generate_ed25519()?; 562 /// let public_key = key.raw_public_key()?; 563 /// 564 /// let mut signer = Signer::new_without_digest(&key)?; 565 /// let digest = // ... 566 /// # &vec![0; 32]; 567 /// let signature = signer.sign_oneshot_to_vec(digest)?; 568 /// assert_eq!(signature.len(), 64); 569 /// # Ok(()) } 570 /// ``` 571 #[cfg(any(boringssl, ossl111))] generate_ed25519() -> Result<PKey<Private>, ErrorStack>572 pub fn generate_ed25519() -> Result<PKey<Private>, ErrorStack> { 573 PKey::generate_eddsa(Id::ED25519) 574 } 575 576 /// Generates a new private Ed448 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_ed448()?; 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(), 114); 595 /// # Ok(()) } 596 /// ``` 597 #[cfg(ossl111)] generate_ed448() -> Result<PKey<Private>, ErrorStack>598 pub fn generate_ed448() -> Result<PKey<Private>, ErrorStack> { 599 PKey::generate_eddsa(Id::ED448) 600 } 601 602 /// Generates a new EC key using the provided curve. 603 /// 604 /// Requires OpenSSL 3.0.0 or newer. 605 #[corresponds(EVP_EC_gen)] 606 #[cfg(ossl300)] ec_gen(curve: &str) -> Result<PKey<Private>, ErrorStack>607 pub fn ec_gen(curve: &str) -> Result<PKey<Private>, ErrorStack> { 608 ffi::init(); 609 610 let curve = CString::new(curve).unwrap(); 611 unsafe { 612 let ptr = cvt_p(ffi::EVP_EC_gen(curve.as_ptr()))?; 613 Ok(PKey::from_ptr(ptr)) 614 } 615 } 616 617 private_key_from_pem! { 618 /// Deserializes a private key from a PEM-encoded key type specific format. 619 #[corresponds(PEM_read_bio_PrivateKey)] 620 private_key_from_pem, 621 622 /// Deserializes a private key from a PEM-encoded encrypted key type specific format. 623 #[corresponds(PEM_read_bio_PrivateKey)] 624 private_key_from_pem_passphrase, 625 626 /// Deserializes a private key from a PEM-encoded encrypted key type specific format. 627 /// 628 /// The callback should fill the password into the provided buffer and return its length. 629 #[corresponds(PEM_read_bio_PrivateKey)] 630 private_key_from_pem_callback, 631 PKey<Private>, 632 ffi::PEM_read_bio_PrivateKey 633 } 634 635 from_der! { 636 /// Decodes a DER-encoded private key. 637 /// 638 /// This function will attempt to automatically detect the underlying key format, and 639 /// supports the unencrypted PKCS#8 PrivateKeyInfo structures as well as key type specific 640 /// formats. 641 #[corresponds(d2i_AutoPrivateKey)] 642 private_key_from_der, 643 PKey<Private>, 644 ffi::d2i_AutoPrivateKey 645 } 646 647 /// Deserializes a DER-formatted PKCS#8 unencrypted private key. 648 /// 649 /// This method is mainly for interoperability reasons. Encrypted keyfiles should be preferred. private_key_from_pkcs8(der: &[u8]) -> Result<PKey<Private>, ErrorStack>650 pub fn private_key_from_pkcs8(der: &[u8]) -> Result<PKey<Private>, ErrorStack> { 651 unsafe { 652 ffi::init(); 653 let len = der.len().min(c_long::max_value() as usize) as c_long; 654 let p8inf = cvt_p(ffi::d2i_PKCS8_PRIV_KEY_INFO( 655 ptr::null_mut(), 656 &mut der.as_ptr(), 657 len, 658 ))?; 659 let res = cvt_p(ffi::EVP_PKCS82PKEY(p8inf)).map(|p| PKey::from_ptr(p)); 660 ffi::PKCS8_PRIV_KEY_INFO_free(p8inf); 661 res 662 } 663 } 664 665 /// Deserializes a DER-formatted PKCS#8 private key, using a callback to retrieve the password 666 /// if the key is encrypted. 667 /// 668 /// The callback should copy the password into the provided buffer and return the number of 669 /// bytes written. 670 #[corresponds(d2i_PKCS8PrivateKey_bio)] private_key_from_pkcs8_callback<F>( der: &[u8], callback: F, ) -> Result<PKey<Private>, ErrorStack> where F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,671 pub fn private_key_from_pkcs8_callback<F>( 672 der: &[u8], 673 callback: F, 674 ) -> Result<PKey<Private>, ErrorStack> 675 where 676 F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>, 677 { 678 unsafe { 679 ffi::init(); 680 let mut cb = CallbackState::new(callback); 681 let bio = MemBioSlice::new(der)?; 682 cvt_p(ffi::d2i_PKCS8PrivateKey_bio( 683 bio.as_ptr(), 684 ptr::null_mut(), 685 Some(invoke_passwd_cb::<F>), 686 &mut cb as *mut _ as *mut _, 687 )) 688 .map(|p| PKey::from_ptr(p)) 689 } 690 } 691 692 /// Deserializes a DER-formatted PKCS#8 private key, using the supplied password if the key is 693 /// encrypted. 694 /// 695 /// # Panics 696 /// 697 /// Panics if `passphrase` contains an embedded null. 698 #[corresponds(d2i_PKCS8PrivateKey_bio)] private_key_from_pkcs8_passphrase( der: &[u8], passphrase: &[u8], ) -> Result<PKey<Private>, ErrorStack>699 pub fn private_key_from_pkcs8_passphrase( 700 der: &[u8], 701 passphrase: &[u8], 702 ) -> Result<PKey<Private>, ErrorStack> { 703 unsafe { 704 ffi::init(); 705 let bio = MemBioSlice::new(der)?; 706 let passphrase = CString::new(passphrase).unwrap(); 707 cvt_p(ffi::d2i_PKCS8PrivateKey_bio( 708 bio.as_ptr(), 709 ptr::null_mut(), 710 None, 711 passphrase.as_ptr() as *const _ as *mut _, 712 )) 713 .map(|p| PKey::from_ptr(p)) 714 } 715 } 716 717 /// Creates a private key from its raw byte representation 718 /// 719 /// Algorithm types that support raw private keys are HMAC, X25519, ED25519, X448 or ED448 720 #[corresponds(EVP_PKEY_new_raw_private_key)] 721 #[cfg(any(boringssl, ossl111))] private_key_from_raw_bytes( bytes: &[u8], key_type: Id, ) -> Result<PKey<Private>, ErrorStack>722 pub fn private_key_from_raw_bytes( 723 bytes: &[u8], 724 key_type: Id, 725 ) -> Result<PKey<Private>, ErrorStack> { 726 unsafe { 727 ffi::init(); 728 cvt_p(ffi::EVP_PKEY_new_raw_private_key( 729 key_type.as_raw(), 730 ptr::null_mut(), 731 bytes.as_ptr(), 732 bytes.len(), 733 )) 734 .map(|p| PKey::from_ptr(p)) 735 } 736 } 737 } 738 739 impl PKey<Public> { 740 from_pem! { 741 /// Decodes a PEM-encoded SubjectPublicKeyInfo structure. 742 /// 743 /// The input should have a header of `-----BEGIN PUBLIC KEY-----`. 744 #[corresponds(PEM_read_bio_PUBKEY)] 745 public_key_from_pem, 746 PKey<Public>, 747 ffi::PEM_read_bio_PUBKEY 748 } 749 750 from_der! { 751 /// Decodes a DER-encoded SubjectPublicKeyInfo structure. 752 #[corresponds(d2i_PUBKEY)] 753 public_key_from_der, 754 PKey<Public>, 755 ffi::d2i_PUBKEY 756 } 757 758 /// Creates a public key from its raw byte representation 759 /// 760 /// Algorithm types that support raw public keys are X25519, ED25519, X448 or ED448 761 #[corresponds(EVP_PKEY_new_raw_public_key)] 762 #[cfg(any(boringssl, ossl111))] public_key_from_raw_bytes( bytes: &[u8], key_type: Id, ) -> Result<PKey<Public>, ErrorStack>763 pub fn public_key_from_raw_bytes( 764 bytes: &[u8], 765 key_type: Id, 766 ) -> Result<PKey<Public>, ErrorStack> { 767 unsafe { 768 ffi::init(); 769 cvt_p(ffi::EVP_PKEY_new_raw_public_key( 770 key_type.as_raw(), 771 ptr::null_mut(), 772 bytes.as_ptr(), 773 bytes.len(), 774 )) 775 .map(|p| PKey::from_ptr(p)) 776 } 777 } 778 } 779 780 cfg_if! { 781 if #[cfg(any(boringssl, ossl110, libressl270))] { 782 use ffi::EVP_PKEY_up_ref; 783 } else { 784 #[allow(bad_style)] 785 unsafe extern "C" fn EVP_PKEY_up_ref(pkey: *mut ffi::EVP_PKEY) { 786 ffi::CRYPTO_add_lock( 787 &mut (*pkey).references, 788 1, 789 ffi::CRYPTO_LOCK_EVP_PKEY, 790 "pkey.rs\0".as_ptr() as *const _, 791 line!() as c_int, 792 ); 793 } 794 } 795 } 796 797 impl<T> TryFrom<EcKey<T>> for PKey<T> { 798 type Error = ErrorStack; 799 try_from(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack>800 fn try_from(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> { 801 PKey::from_ec_key(ec_key) 802 } 803 } 804 805 impl<T> TryFrom<PKey<T>> for EcKey<T> { 806 type Error = ErrorStack; 807 try_from(pkey: PKey<T>) -> Result<EcKey<T>, ErrorStack>808 fn try_from(pkey: PKey<T>) -> Result<EcKey<T>, ErrorStack> { 809 pkey.ec_key() 810 } 811 } 812 813 impl<T> TryFrom<Rsa<T>> for PKey<T> { 814 type Error = ErrorStack; 815 try_from(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack>816 fn try_from(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> { 817 PKey::from_rsa(rsa) 818 } 819 } 820 821 impl<T> TryFrom<PKey<T>> for Rsa<T> { 822 type Error = ErrorStack; 823 try_from(pkey: PKey<T>) -> Result<Rsa<T>, ErrorStack>824 fn try_from(pkey: PKey<T>) -> Result<Rsa<T>, ErrorStack> { 825 pkey.rsa() 826 } 827 } 828 829 impl<T> TryFrom<Dsa<T>> for PKey<T> { 830 type Error = ErrorStack; 831 try_from(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack>832 fn try_from(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> { 833 PKey::from_dsa(dsa) 834 } 835 } 836 837 impl<T> TryFrom<PKey<T>> for Dsa<T> { 838 type Error = ErrorStack; 839 try_from(pkey: PKey<T>) -> Result<Dsa<T>, ErrorStack>840 fn try_from(pkey: PKey<T>) -> Result<Dsa<T>, ErrorStack> { 841 pkey.dsa() 842 } 843 } 844 845 impl<T> TryFrom<Dh<T>> for PKey<T> { 846 type Error = ErrorStack; 847 try_from(dh: Dh<T>) -> Result<PKey<T>, ErrorStack>848 fn try_from(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> { 849 PKey::from_dh(dh) 850 } 851 } 852 853 impl<T> TryFrom<PKey<T>> for Dh<T> { 854 type Error = ErrorStack; 855 try_from(pkey: PKey<T>) -> Result<Dh<T>, ErrorStack>856 fn try_from(pkey: PKey<T>) -> Result<Dh<T>, ErrorStack> { 857 pkey.dh() 858 } 859 } 860 861 #[cfg(test)] 862 mod tests { 863 use std::convert::TryInto; 864 865 #[cfg(not(boringssl))] 866 use crate::dh::Dh; 867 use crate::dsa::Dsa; 868 use crate::ec::EcKey; 869 use crate::nid::Nid; 870 use crate::rsa::Rsa; 871 use crate::symm::Cipher; 872 873 use super::*; 874 875 #[cfg(ossl111)] 876 use crate::rand::rand_bytes; 877 878 #[test] test_to_password()879 fn test_to_password() { 880 let rsa = Rsa::generate(2048).unwrap(); 881 let pkey = PKey::from_rsa(rsa).unwrap(); 882 let pem = pkey 883 .private_key_to_pem_pkcs8_passphrase(Cipher::aes_128_cbc(), b"foobar") 884 .unwrap(); 885 PKey::private_key_from_pem_passphrase(&pem, b"foobar").unwrap(); 886 assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err()); 887 } 888 889 #[test] test_unencrypted_pkcs8()890 fn test_unencrypted_pkcs8() { 891 let key = include_bytes!("../test/pkcs8-nocrypt.der"); 892 PKey::private_key_from_pkcs8(key).unwrap(); 893 } 894 895 #[test] test_encrypted_pkcs8_passphrase()896 fn test_encrypted_pkcs8_passphrase() { 897 let key = include_bytes!("../test/pkcs8.der"); 898 PKey::private_key_from_pkcs8_passphrase(key, b"mypass").unwrap(); 899 900 let rsa = Rsa::generate(2048).unwrap(); 901 let pkey = PKey::from_rsa(rsa).unwrap(); 902 let der = pkey 903 .private_key_to_pkcs8_passphrase(Cipher::aes_128_cbc(), b"mypass") 904 .unwrap(); 905 let pkey2 = PKey::private_key_from_pkcs8_passphrase(&der, b"mypass").unwrap(); 906 assert_eq!( 907 pkey.private_key_to_der().unwrap(), 908 pkey2.private_key_to_der().unwrap() 909 ); 910 } 911 912 #[test] test_encrypted_pkcs8_callback()913 fn test_encrypted_pkcs8_callback() { 914 let mut password_queried = false; 915 let key = include_bytes!("../test/pkcs8.der"); 916 PKey::private_key_from_pkcs8_callback(key, |password| { 917 password_queried = true; 918 password[..6].copy_from_slice(b"mypass"); 919 Ok(6) 920 }) 921 .unwrap(); 922 assert!(password_queried); 923 } 924 925 #[test] test_private_key_from_pem()926 fn test_private_key_from_pem() { 927 let key = include_bytes!("../test/key.pem"); 928 PKey::private_key_from_pem(key).unwrap(); 929 } 930 931 #[test] test_public_key_from_pem()932 fn test_public_key_from_pem() { 933 let key = include_bytes!("../test/key.pem.pub"); 934 PKey::public_key_from_pem(key).unwrap(); 935 } 936 937 #[test] test_public_key_from_der()938 fn test_public_key_from_der() { 939 let key = include_bytes!("../test/key.der.pub"); 940 PKey::public_key_from_der(key).unwrap(); 941 } 942 943 #[test] test_private_key_from_der()944 fn test_private_key_from_der() { 945 let key = include_bytes!("../test/key.der"); 946 PKey::private_key_from_der(key).unwrap(); 947 } 948 949 #[test] test_pem()950 fn test_pem() { 951 let key = include_bytes!("../test/key.pem"); 952 let key = PKey::private_key_from_pem(key).unwrap(); 953 954 let priv_key = key.private_key_to_pem_pkcs8().unwrap(); 955 let pub_key = key.public_key_to_pem().unwrap(); 956 957 // As a super-simple verification, just check that the buffers contain 958 // the `PRIVATE KEY` or `PUBLIC KEY` strings. 959 assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY")); 960 assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY")); 961 } 962 963 #[test] test_rsa_accessor()964 fn test_rsa_accessor() { 965 let rsa = Rsa::generate(2048).unwrap(); 966 let pkey = PKey::from_rsa(rsa).unwrap(); 967 pkey.rsa().unwrap(); 968 assert_eq!(pkey.id(), Id::RSA); 969 assert!(pkey.dsa().is_err()); 970 } 971 972 #[test] test_dsa_accessor()973 fn test_dsa_accessor() { 974 let dsa = Dsa::generate(2048).unwrap(); 975 let pkey = PKey::from_dsa(dsa).unwrap(); 976 pkey.dsa().unwrap(); 977 assert_eq!(pkey.id(), Id::DSA); 978 assert!(pkey.rsa().is_err()); 979 } 980 981 #[test] 982 #[cfg(not(boringssl))] test_dh_accessor()983 fn test_dh_accessor() { 984 let dh = include_bytes!("../test/dhparams.pem"); 985 let dh = Dh::params_from_pem(dh).unwrap(); 986 let pkey = PKey::from_dh(dh).unwrap(); 987 pkey.dh().unwrap(); 988 assert_eq!(pkey.id(), Id::DH); 989 assert!(pkey.rsa().is_err()); 990 } 991 992 #[test] test_ec_key_accessor()993 fn test_ec_key_accessor() { 994 let ec_key = EcKey::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); 995 let pkey = PKey::from_ec_key(ec_key).unwrap(); 996 pkey.ec_key().unwrap(); 997 assert_eq!(pkey.id(), Id::EC); 998 assert!(pkey.rsa().is_err()); 999 } 1000 1001 #[test] test_rsa_conversion()1002 fn test_rsa_conversion() { 1003 let rsa = Rsa::generate(2048).unwrap(); 1004 let pkey: PKey<Private> = rsa.clone().try_into().unwrap(); 1005 let rsa_: Rsa<Private> = pkey.try_into().unwrap(); 1006 // Eq is missing 1007 assert_eq!(rsa.p(), rsa_.p()); 1008 assert_eq!(rsa.q(), rsa_.q()); 1009 } 1010 1011 #[test] test_dsa_conversion()1012 fn test_dsa_conversion() { 1013 let dsa = Dsa::generate(2048).unwrap(); 1014 let pkey: PKey<Private> = dsa.clone().try_into().unwrap(); 1015 let dsa_: Dsa<Private> = pkey.try_into().unwrap(); 1016 // Eq is missing 1017 assert_eq!(dsa.priv_key(), dsa_.priv_key()); 1018 } 1019 1020 #[test] test_ec_key_conversion()1021 fn test_ec_key_conversion() { 1022 let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::X9_62_PRIME256V1).unwrap(); 1023 let ec_key = EcKey::generate(&group).unwrap(); 1024 let pkey: PKey<Private> = ec_key.clone().try_into().unwrap(); 1025 let ec_key_: EcKey<Private> = pkey.try_into().unwrap(); 1026 // Eq is missing 1027 assert_eq!(ec_key.private_key(), ec_key_.private_key()); 1028 } 1029 1030 #[test] 1031 #[cfg(any(ossl110, libressl360))] test_security_bits()1032 fn test_security_bits() { 1033 let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::SECP521R1).unwrap(); 1034 let ec_key = EcKey::generate(&group).unwrap(); 1035 let pkey: PKey<Private> = ec_key.try_into().unwrap(); 1036 1037 assert_eq!(pkey.security_bits(), 256); 1038 } 1039 1040 #[test] 1041 #[cfg(not(boringssl))] test_dh_conversion()1042 fn test_dh_conversion() { 1043 let dh_params = include_bytes!("../test/dhparams.pem"); 1044 let dh_params = Dh::params_from_pem(dh_params).unwrap(); 1045 let dh = dh_params.generate_key().unwrap(); 1046 1047 // Clone is missing for Dh, save the parameters 1048 let p = dh.prime_p().to_owned().unwrap(); 1049 let q = dh.prime_q().map(|q| q.to_owned().unwrap()); 1050 let g = dh.generator().to_owned().unwrap(); 1051 1052 let pkey: PKey<Private> = dh.try_into().unwrap(); 1053 let dh_: Dh<Private> = pkey.try_into().unwrap(); 1054 1055 // Eq is missing 1056 assert_eq!(&p, dh_.prime_p()); 1057 assert_eq!(q, dh_.prime_q().map(|q| q.to_owned().unwrap())); 1058 assert_eq!(&g, dh_.generator()); 1059 } 1060 1061 #[cfg(ossl111)] test_raw_public_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id)1062 fn test_raw_public_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) { 1063 // Generate a new key 1064 let key = gen().unwrap(); 1065 1066 // Get the raw bytes, and create a new key from the raw bytes 1067 let raw = key.raw_public_key().unwrap(); 1068 let from_raw = PKey::public_key_from_raw_bytes(&raw, key_type).unwrap(); 1069 1070 // Compare the der encoding of the original and raw / restored public key 1071 assert_eq!( 1072 key.public_key_to_der().unwrap(), 1073 from_raw.public_key_to_der().unwrap() 1074 ); 1075 } 1076 1077 #[cfg(ossl111)] test_raw_private_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id)1078 fn test_raw_private_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) { 1079 // Generate a new key 1080 let key = gen().unwrap(); 1081 1082 // Get the raw bytes, and create a new key from the raw bytes 1083 let raw = key.raw_private_key().unwrap(); 1084 let from_raw = PKey::private_key_from_raw_bytes(&raw, key_type).unwrap(); 1085 1086 // Compare the der encoding of the original and raw / restored public key 1087 assert_eq!( 1088 key.private_key_to_der().unwrap(), 1089 from_raw.private_key_to_der().unwrap() 1090 ); 1091 } 1092 1093 #[cfg(ossl111)] 1094 #[test] test_raw_public_key_bytes()1095 fn test_raw_public_key_bytes() { 1096 test_raw_public_key(PKey::generate_x25519, Id::X25519); 1097 test_raw_public_key(PKey::generate_ed25519, Id::ED25519); 1098 test_raw_public_key(PKey::generate_x448, Id::X448); 1099 test_raw_public_key(PKey::generate_ed448, Id::ED448); 1100 } 1101 1102 #[cfg(ossl111)] 1103 #[test] test_raw_private_key_bytes()1104 fn test_raw_private_key_bytes() { 1105 test_raw_private_key(PKey::generate_x25519, Id::X25519); 1106 test_raw_private_key(PKey::generate_ed25519, Id::ED25519); 1107 test_raw_private_key(PKey::generate_x448, Id::X448); 1108 test_raw_private_key(PKey::generate_ed448, Id::ED448); 1109 } 1110 1111 #[cfg(ossl111)] 1112 #[test] test_raw_hmac()1113 fn test_raw_hmac() { 1114 let mut test_bytes = vec![0u8; 32]; 1115 rand_bytes(&mut test_bytes).unwrap(); 1116 1117 let hmac_key = PKey::hmac(&test_bytes).unwrap(); 1118 assert!(hmac_key.raw_public_key().is_err()); 1119 1120 let key_bytes = hmac_key.raw_private_key().unwrap(); 1121 assert_eq!(key_bytes, test_bytes); 1122 } 1123 1124 #[cfg(ossl111)] 1125 #[test] test_raw_key_fail()1126 fn test_raw_key_fail() { 1127 // Getting a raw byte representation will not work with Nist curves 1128 let group = crate::ec::EcGroup::from_curve_name(Nid::SECP256K1).unwrap(); 1129 let ec_key = EcKey::generate(&group).unwrap(); 1130 let pkey = PKey::from_ec_key(ec_key).unwrap(); 1131 assert!(pkey.raw_private_key().is_err()); 1132 assert!(pkey.raw_public_key().is_err()); 1133 } 1134 1135 #[cfg(ossl300)] 1136 #[test] test_ec_gen()1137 fn test_ec_gen() { 1138 let key = PKey::ec_gen("prime256v1").unwrap(); 1139 assert!(key.ec_key().is_ok()); 1140 } 1141 } 1142