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 43 use cfg_if::cfg_if; 44 use foreign_types::{ForeignType, ForeignTypeRef}; 45 use libc::{c_int, c_long}; 46 use std::convert::TryFrom; 47 use std::ffi::CString; 48 use std::fmt; 49 use std::mem; 50 use std::ptr; 51 52 use crate::bio::MemBioSlice; 53 use crate::dh::Dh; 54 use crate::dsa::Dsa; 55 use crate::ec::EcKey; 56 use crate::error::ErrorStack; 57 use crate::rsa::Rsa; 58 #[cfg(ossl110)] 59 use crate::symm::Cipher; 60 use crate::util::{invoke_passwd_cb, CallbackState}; 61 use crate::{cvt, cvt_p}; 62 63 /// A tag type indicating that a key only has parameters. 64 pub enum Params {} 65 66 /// A tag type indicating that a key only has public components. 67 pub enum Public {} 68 69 /// A tag type indicating that a key has private components. 70 pub enum Private {} 71 72 /// An identifier of a kind of key. 73 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 74 pub struct Id(c_int); 75 76 impl Id { 77 pub const RSA: Id = Id(ffi::EVP_PKEY_RSA); 78 pub const HMAC: Id = Id(ffi::EVP_PKEY_HMAC); 79 pub const DSA: Id = Id(ffi::EVP_PKEY_DSA); 80 pub const DH: Id = Id(ffi::EVP_PKEY_DH); 81 pub const EC: Id = Id(ffi::EVP_PKEY_EC); 82 83 #[cfg(ossl111)] 84 pub const ED25519: Id = Id(ffi::EVP_PKEY_ED25519); 85 #[cfg(ossl111)] 86 pub const ED448: Id = Id(ffi::EVP_PKEY_ED448); 87 #[cfg(ossl111)] 88 pub const X25519: Id = Id(ffi::EVP_PKEY_X25519); 89 #[cfg(ossl111)] 90 pub const X448: Id = Id(ffi::EVP_PKEY_X448); 91 92 /// Creates a `Id` from an integer representation. from_raw(value: c_int) -> Id93 pub fn from_raw(value: c_int) -> Id { 94 Id(value) 95 } 96 97 /// Returns the integer representation of the `Id`. 98 #[allow(clippy::trivially_copy_pass_by_ref)] as_raw(&self) -> c_int99 pub fn as_raw(&self) -> c_int { 100 self.0 101 } 102 } 103 104 /// A trait indicating that a key has parameters. 105 pub unsafe trait HasParams {} 106 107 unsafe impl HasParams for Params {} 108 109 unsafe impl<T> HasParams for T where T: HasPublic {} 110 111 /// A trait indicating that a key has public components. 112 pub unsafe trait HasPublic {} 113 114 unsafe impl HasPublic for Public {} 115 116 unsafe impl<T> HasPublic for T where T: HasPrivate {} 117 118 /// A trait indicating that a key has private components. 119 pub unsafe trait HasPrivate {} 120 121 unsafe impl HasPrivate for Private {} 122 123 generic_foreign_type_and_impl_send_sync! { 124 type CType = ffi::EVP_PKEY; 125 fn drop = ffi::EVP_PKEY_free; 126 127 /// A public or private key. 128 pub struct PKey<T>; 129 /// Reference to `PKey`. 130 pub struct PKeyRef<T>; 131 } 132 133 impl<T> ToOwned for PKeyRef<T> { 134 type Owned = PKey<T>; 135 to_owned(&self) -> PKey<T>136 fn to_owned(&self) -> PKey<T> { 137 unsafe { 138 EVP_PKEY_up_ref(self.as_ptr()); 139 PKey::from_ptr(self.as_ptr()) 140 } 141 } 142 } 143 144 impl<T> PKeyRef<T> { 145 /// Returns a copy of the internal RSA key. 146 /// 147 /// This corresponds to [`EVP_PKEY_get1_RSA`]. 148 /// 149 /// [`EVP_PKEY_get1_RSA`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_get1_RSA.html rsa(&self) -> Result<Rsa<T>, ErrorStack>150 pub fn rsa(&self) -> Result<Rsa<T>, ErrorStack> { 151 unsafe { 152 let rsa = cvt_p(ffi::EVP_PKEY_get1_RSA(self.as_ptr()))?; 153 Ok(Rsa::from_ptr(rsa)) 154 } 155 } 156 157 /// Returns a copy of the internal DSA key. 158 /// 159 /// This corresponds to [`EVP_PKEY_get1_DSA`]. 160 /// 161 /// [`EVP_PKEY_get1_DSA`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_get1_DSA.html dsa(&self) -> Result<Dsa<T>, ErrorStack>162 pub fn dsa(&self) -> Result<Dsa<T>, ErrorStack> { 163 unsafe { 164 let dsa = cvt_p(ffi::EVP_PKEY_get1_DSA(self.as_ptr()))?; 165 Ok(Dsa::from_ptr(dsa)) 166 } 167 } 168 169 /// Returns a copy of the internal DH key. 170 /// 171 /// This corresponds to [`EVP_PKEY_get1_DH`]. 172 /// 173 /// [`EVP_PKEY_get1_DH`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_get1_DH.html 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 /// 183 /// This corresponds to [`EVP_PKEY_get1_EC_KEY`]. 184 /// 185 /// [`EVP_PKEY_get1_EC_KEY`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_get1_EC_KEY.html ec_key(&self) -> Result<EcKey<T>, ErrorStack>186 pub fn ec_key(&self) -> Result<EcKey<T>, ErrorStack> { 187 unsafe { 188 let ec_key = cvt_p(ffi::EVP_PKEY_get1_EC_KEY(self.as_ptr()))?; 189 Ok(EcKey::from_ptr(ec_key)) 190 } 191 } 192 193 /// Returns the `Id` that represents the type of this key. 194 /// 195 /// This corresponds to [`EVP_PKEY_id`]. 196 /// 197 /// [`EVP_PKEY_id`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_id.html id(&self) -> Id198 pub fn id(&self) -> Id { 199 unsafe { Id::from_raw(ffi::EVP_PKEY_id(self.as_ptr())) } 200 } 201 202 /// Returns the maximum size of a signature in bytes. 203 /// 204 /// This corresponds to [`EVP_PKEY_size`]. 205 /// 206 /// [`EVP_PKEY_size`]: https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_size.html size(&self) -> usize207 pub fn size(&self) -> usize { 208 unsafe { ffi::EVP_PKEY_size(self.as_ptr()) as usize } 209 } 210 } 211 212 impl<T> PKeyRef<T> 213 where 214 T: HasPublic, 215 { 216 to_pem! { 217 /// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure. 218 /// 219 /// The output will have a header of `-----BEGIN PUBLIC KEY-----`. 220 /// 221 /// This corresponds to [`PEM_write_bio_PUBKEY`]. 222 /// 223 /// [`PEM_write_bio_PUBKEY`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_PUBKEY.html 224 public_key_to_pem, 225 ffi::PEM_write_bio_PUBKEY 226 } 227 228 to_der! { 229 /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure. 230 /// 231 /// This corresponds to [`i2d_PUBKEY`]. 232 /// 233 /// [`i2d_PUBKEY`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_PUBKEY.html 234 public_key_to_der, 235 ffi::i2d_PUBKEY 236 } 237 238 /// Returns the size of the key. 239 /// 240 /// This corresponds to the bit length of the modulus of an RSA key, and the bit length of the 241 /// group order for an elliptic curve key, for example. bits(&self) -> u32242 pub fn bits(&self) -> u32 { 243 unsafe { ffi::EVP_PKEY_bits(self.as_ptr()) as u32 } 244 } 245 246 /// Compares the public component of this key with another. public_eq<U>(&self, other: &PKeyRef<U>) -> bool where U: HasPublic,247 pub fn public_eq<U>(&self, other: &PKeyRef<U>) -> bool 248 where 249 U: HasPublic, 250 { 251 unsafe { ffi::EVP_PKEY_cmp(self.as_ptr(), other.as_ptr()) == 1 } 252 } 253 } 254 255 impl<T> PKeyRef<T> 256 where 257 T: HasPrivate, 258 { 259 private_key_to_pem! { 260 /// Serializes the private key to a PEM-encoded PKCS#8 PrivateKeyInfo structure. 261 /// 262 /// The output will have a header of `-----BEGIN PRIVATE KEY-----`. 263 /// 264 /// This corresponds to [`PEM_write_bio_PKCS8PrivateKey`]. 265 /// 266 /// [`PEM_write_bio_PKCS8PrivateKey`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_write_bio_PKCS8PrivateKey.html 267 private_key_to_pem_pkcs8, 268 /// Serializes the private key to a PEM-encoded PKCS#8 EncryptedPrivateKeyInfo structure. 269 /// 270 /// The output will have a header of `-----BEGIN ENCRYPTED PRIVATE KEY-----`. 271 /// 272 /// This corresponds to [`PEM_write_bio_PKCS8PrivateKey`]. 273 /// 274 /// [`PEM_write_bio_PKCS8PrivateKey`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_write_bio_PKCS8PrivateKey.html 275 private_key_to_pem_pkcs8_passphrase, 276 ffi::PEM_write_bio_PKCS8PrivateKey 277 } 278 279 to_der! { 280 /// Serializes the private key to a DER-encoded key type specific format. 281 /// 282 /// This corresponds to [`i2d_PrivateKey`]. 283 /// 284 /// [`i2d_PrivateKey`]: https://www.openssl.org/docs/man1.0.2/crypto/i2d_PrivateKey.html 285 private_key_to_der, 286 ffi::i2d_PrivateKey 287 } 288 } 289 290 impl<T> fmt::Debug for PKey<T> { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result291 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 292 let alg = match self.id() { 293 Id::RSA => "RSA", 294 Id::HMAC => "HMAC", 295 Id::DSA => "DSA", 296 Id::DH => "DH", 297 Id::EC => "EC", 298 #[cfg(ossl111)] 299 Id::ED25519 => "Ed25519", 300 #[cfg(ossl111)] 301 Id::ED448 => "Ed448", 302 _ => "unknown", 303 }; 304 fmt.debug_struct("PKey").field("algorithm", &alg).finish() 305 // TODO: Print details for each specific type of key 306 } 307 } 308 309 impl<T> Clone for PKey<T> { clone(&self) -> PKey<T>310 fn clone(&self) -> PKey<T> { 311 PKeyRef::to_owned(self) 312 } 313 } 314 315 impl<T> PKey<T> { 316 /// Creates a new `PKey` containing an RSA key. 317 /// 318 /// This corresponds to [`EVP_PKEY_assign_RSA`]. 319 /// 320 /// [`EVP_PKEY_assign_RSA`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_assign_RSA.html from_rsa(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack>321 pub fn from_rsa(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> { 322 unsafe { 323 let evp = cvt_p(ffi::EVP_PKEY_new())?; 324 let pkey = PKey::from_ptr(evp); 325 cvt(ffi::EVP_PKEY_assign( 326 pkey.0, 327 ffi::EVP_PKEY_RSA, 328 rsa.as_ptr() as *mut _, 329 ))?; 330 mem::forget(rsa); 331 Ok(pkey) 332 } 333 } 334 335 /// Creates a new `PKey` containing a DSA key. 336 /// 337 /// This corresponds to [`EVP_PKEY_assign_DSA`]. 338 /// 339 /// [`EVP_PKEY_assign_DSA`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_assign_DSA.html from_dsa(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack>340 pub fn from_dsa(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> { 341 unsafe { 342 let evp = cvt_p(ffi::EVP_PKEY_new())?; 343 let pkey = PKey::from_ptr(evp); 344 cvt(ffi::EVP_PKEY_assign( 345 pkey.0, 346 ffi::EVP_PKEY_DSA, 347 dsa.as_ptr() as *mut _, 348 ))?; 349 mem::forget(dsa); 350 Ok(pkey) 351 } 352 } 353 354 /// Creates a new `PKey` containing a Diffie-Hellman key. 355 /// 356 /// This corresponds to [`EVP_PKEY_assign_DH`]. 357 /// 358 /// [`EVP_PKEY_assign_DH`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_assign_DH.html from_dh(dh: Dh<T>) -> Result<PKey<T>, ErrorStack>359 pub fn from_dh(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> { 360 unsafe { 361 let evp = cvt_p(ffi::EVP_PKEY_new())?; 362 let pkey = PKey::from_ptr(evp); 363 cvt(ffi::EVP_PKEY_assign( 364 pkey.0, 365 ffi::EVP_PKEY_DH, 366 dh.as_ptr() as *mut _, 367 ))?; 368 mem::forget(dh); 369 Ok(pkey) 370 } 371 } 372 373 /// Creates a new `PKey` containing an elliptic curve key. 374 /// 375 /// This corresponds to [`EVP_PKEY_assign_EC_KEY`]. 376 /// 377 /// [`EVP_PKEY_assign_EC_KEY`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_assign_EC_KEY.html from_ec_key(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack>378 pub fn from_ec_key(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> { 379 unsafe { 380 let evp = cvt_p(ffi::EVP_PKEY_new())?; 381 let pkey = PKey::from_ptr(evp); 382 cvt(ffi::EVP_PKEY_assign( 383 pkey.0, 384 ffi::EVP_PKEY_EC, 385 ec_key.as_ptr() as *mut _, 386 ))?; 387 mem::forget(ec_key); 388 Ok(pkey) 389 } 390 } 391 } 392 393 impl PKey<Private> { 394 /// Creates a new `PKey` containing an HMAC key. 395 /// 396 /// # Note 397 /// 398 /// To compute HMAC values, use the `sign` module. hmac(key: &[u8]) -> Result<PKey<Private>, ErrorStack>399 pub fn hmac(key: &[u8]) -> Result<PKey<Private>, ErrorStack> { 400 unsafe { 401 assert!(key.len() <= c_int::max_value() as usize); 402 let key = cvt_p(ffi::EVP_PKEY_new_mac_key( 403 ffi::EVP_PKEY_HMAC, 404 ptr::null_mut(), 405 key.as_ptr() as *const _, 406 key.len() as c_int, 407 ))?; 408 Ok(PKey::from_ptr(key)) 409 } 410 } 411 412 /// Creates a new `PKey` containing a CMAC key. 413 /// 414 /// Requires OpenSSL 1.1.0 or newer. 415 /// 416 /// # Note 417 /// 418 /// To compute CMAC values, use the `sign` module. 419 #[cfg(ossl110)] 420 #[allow(clippy::trivially_copy_pass_by_ref)] cmac(cipher: &Cipher, key: &[u8]) -> Result<PKey<Private>, ErrorStack>421 pub fn cmac(cipher: &Cipher, key: &[u8]) -> Result<PKey<Private>, ErrorStack> { 422 unsafe { 423 assert!(key.len() <= c_int::max_value() as usize); 424 let kctx = cvt_p(ffi::EVP_PKEY_CTX_new_id( 425 ffi::EVP_PKEY_CMAC, 426 ptr::null_mut(), 427 ))?; 428 429 let ret = (|| { 430 cvt(ffi::EVP_PKEY_keygen_init(kctx))?; 431 432 // Set cipher for cmac 433 cvt(ffi::EVP_PKEY_CTX_ctrl( 434 kctx, 435 -1, 436 ffi::EVP_PKEY_OP_KEYGEN, 437 ffi::EVP_PKEY_CTRL_CIPHER, 438 0, 439 cipher.as_ptr() as *mut _, 440 ))?; 441 442 // Set the key data 443 cvt(ffi::EVP_PKEY_CTX_ctrl( 444 kctx, 445 -1, 446 ffi::EVP_PKEY_OP_KEYGEN, 447 ffi::EVP_PKEY_CTRL_SET_MAC_KEY, 448 key.len() as c_int, 449 key.as_ptr() as *mut _, 450 ))?; 451 Ok(()) 452 })(); 453 454 if let Err(e) = ret { 455 // Free memory 456 ffi::EVP_PKEY_CTX_free(kctx); 457 return Err(e); 458 } 459 460 // Generate key 461 let mut key = ptr::null_mut(); 462 let ret = cvt(ffi::EVP_PKEY_keygen(kctx, &mut key)); 463 464 // Free memory 465 ffi::EVP_PKEY_CTX_free(kctx); 466 467 if let Err(e) = ret { 468 return Err(e); 469 } 470 471 Ok(PKey::from_ptr(key)) 472 } 473 } 474 475 #[cfg(ossl111)] generate_eddsa(nid: c_int) -> Result<PKey<Private>, ErrorStack>476 fn generate_eddsa(nid: c_int) -> Result<PKey<Private>, ErrorStack> { 477 unsafe { 478 let kctx = cvt_p(ffi::EVP_PKEY_CTX_new_id(nid, ptr::null_mut()))?; 479 let ret = cvt(ffi::EVP_PKEY_keygen_init(kctx)); 480 if let Err(e) = ret { 481 ffi::EVP_PKEY_CTX_free(kctx); 482 return Err(e); 483 } 484 let mut key = ptr::null_mut(); 485 let ret = cvt(ffi::EVP_PKEY_keygen(kctx, &mut key)); 486 487 ffi::EVP_PKEY_CTX_free(kctx); 488 489 if let Err(e) = ret { 490 return Err(e); 491 } 492 493 Ok(PKey::from_ptr(key)) 494 } 495 } 496 497 /// Generates a new private Ed25519 key 498 #[cfg(ossl111)] generate_x25519() -> Result<PKey<Private>, ErrorStack>499 pub fn generate_x25519() -> Result<PKey<Private>, ErrorStack> { 500 PKey::generate_eddsa(ffi::EVP_PKEY_X25519) 501 } 502 503 /// Generates a new private Ed448 key 504 #[cfg(ossl111)] generate_x448() -> Result<PKey<Private>, ErrorStack>505 pub fn generate_x448() -> Result<PKey<Private>, ErrorStack> { 506 PKey::generate_eddsa(ffi::EVP_PKEY_X448) 507 } 508 509 /// Generates a new private Ed25519 key 510 #[cfg(ossl111)] generate_ed25519() -> Result<PKey<Private>, ErrorStack>511 pub fn generate_ed25519() -> Result<PKey<Private>, ErrorStack> { 512 PKey::generate_eddsa(ffi::EVP_PKEY_ED25519) 513 } 514 515 /// Generates a new private Ed448 key 516 #[cfg(ossl111)] generate_ed448() -> Result<PKey<Private>, ErrorStack>517 pub fn generate_ed448() -> Result<PKey<Private>, ErrorStack> { 518 PKey::generate_eddsa(ffi::EVP_PKEY_ED448) 519 } 520 521 private_key_from_pem! { 522 /// Deserializes a private key from a PEM-encoded key type specific format. 523 /// 524 /// This corresponds to [`PEM_read_bio_PrivateKey`]. 525 /// 526 /// [`PEM_read_bio_PrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_read_bio_PrivateKey.html 527 private_key_from_pem, 528 529 /// Deserializes a private key from a PEM-encoded encrypted key type specific format. 530 /// 531 /// This corresponds to [`PEM_read_bio_PrivateKey`]. 532 /// 533 /// [`PEM_read_bio_PrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_read_bio_PrivateKey.html 534 private_key_from_pem_passphrase, 535 536 /// Deserializes a private key from a PEM-encoded encrypted key type specific format. 537 /// 538 /// The callback should fill the password into the provided buffer and return its length. 539 /// 540 /// This corresponds to [`PEM_read_bio_PrivateKey`]. 541 /// 542 /// [`PEM_read_bio_PrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_read_bio_PrivateKey.html 543 private_key_from_pem_callback, 544 PKey<Private>, 545 ffi::PEM_read_bio_PrivateKey 546 } 547 548 from_der! { 549 /// Decodes a DER-encoded private key. 550 /// 551 /// This function will automatically attempt to detect the underlying key format, and 552 /// supports the unencrypted PKCS#8 PrivateKeyInfo structures as well as key type specific 553 /// formats. 554 /// 555 /// This corresponds to [`d2i_AutoPrivateKey`]. 556 /// 557 /// [`d2i_AutoPrivateKey`]: https://www.openssl.org/docs/man1.0.2/crypto/d2i_AutoPrivateKey.html 558 private_key_from_der, 559 PKey<Private>, 560 ffi::d2i_AutoPrivateKey 561 } 562 563 /// Deserializes a DER-formatted PKCS#8 unencrypted private key. 564 /// 565 /// This method is mainly for interoperability reasons. Encrypted keyfiles should be preferred. private_key_from_pkcs8(der: &[u8]) -> Result<PKey<Private>, ErrorStack>566 pub fn private_key_from_pkcs8(der: &[u8]) -> Result<PKey<Private>, ErrorStack> { 567 unsafe { 568 ffi::init(); 569 let len = der.len().min(c_long::max_value() as usize) as c_long; 570 let p8inf = cvt_p(ffi::d2i_PKCS8_PRIV_KEY_INFO( 571 ptr::null_mut(), 572 &mut der.as_ptr(), 573 len, 574 ))?; 575 let res = cvt_p(ffi::EVP_PKCS82PKEY(p8inf)).map(|p| PKey::from_ptr(p)); 576 ffi::PKCS8_PRIV_KEY_INFO_free(p8inf); 577 res 578 } 579 } 580 581 /// Deserializes a DER-formatted PKCS#8 private key, using a callback to retrieve the password 582 /// if the key is encrpyted. 583 /// 584 /// The callback should copy the password into the provided buffer and return the number of 585 /// bytes written. private_key_from_pkcs8_callback<F>( der: &[u8], callback: F, ) -> Result<PKey<Private>, ErrorStack> where F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,586 pub fn private_key_from_pkcs8_callback<F>( 587 der: &[u8], 588 callback: F, 589 ) -> Result<PKey<Private>, ErrorStack> 590 where 591 F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>, 592 { 593 unsafe { 594 ffi::init(); 595 let mut cb = CallbackState::new(callback); 596 let bio = MemBioSlice::new(der)?; 597 cvt_p(ffi::d2i_PKCS8PrivateKey_bio( 598 bio.as_ptr(), 599 ptr::null_mut(), 600 Some(invoke_passwd_cb::<F>), 601 &mut cb as *mut _ as *mut _, 602 )) 603 .map(|p| PKey::from_ptr(p)) 604 } 605 } 606 607 /// Deserializes a DER-formatted PKCS#8 private key, using the supplied password if the key is 608 /// encrypted. 609 /// 610 /// # Panics 611 /// 612 /// Panics if `passphrase` contains an embedded null. private_key_from_pkcs8_passphrase( der: &[u8], passphrase: &[u8], ) -> Result<PKey<Private>, ErrorStack>613 pub fn private_key_from_pkcs8_passphrase( 614 der: &[u8], 615 passphrase: &[u8], 616 ) -> Result<PKey<Private>, ErrorStack> { 617 unsafe { 618 ffi::init(); 619 let bio = MemBioSlice::new(der)?; 620 let passphrase = CString::new(passphrase).unwrap(); 621 cvt_p(ffi::d2i_PKCS8PrivateKey_bio( 622 bio.as_ptr(), 623 ptr::null_mut(), 624 None, 625 passphrase.as_ptr() as *const _ as *mut _, 626 )) 627 .map(|p| PKey::from_ptr(p)) 628 } 629 } 630 } 631 632 impl PKey<Public> { 633 from_pem! { 634 /// Decodes a PEM-encoded SubjectPublicKeyInfo structure. 635 /// 636 /// The input should have a header of `-----BEGIN PUBLIC KEY-----`. 637 /// 638 /// This corresponds to [`PEM_read_bio_PUBKEY`]. 639 /// 640 /// [`PEM_read_bio_PUBKEY`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_PUBKEY.html 641 public_key_from_pem, 642 PKey<Public>, 643 ffi::PEM_read_bio_PUBKEY 644 } 645 646 from_der! { 647 /// Decodes a DER-encoded SubjectPublicKeyInfo structure. 648 /// 649 /// This corresponds to [`d2i_PUBKEY`]. 650 /// 651 /// [`d2i_PUBKEY`]: https://www.openssl.org/docs/man1.1.0/crypto/d2i_PUBKEY.html 652 public_key_from_der, 653 PKey<Public>, 654 ffi::d2i_PUBKEY 655 } 656 } 657 658 cfg_if! { 659 if #[cfg(any(ossl110, libressl270))] { 660 use ffi::EVP_PKEY_up_ref; 661 } else { 662 #[allow(bad_style)] 663 unsafe extern "C" fn EVP_PKEY_up_ref(pkey: *mut ffi::EVP_PKEY) { 664 ffi::CRYPTO_add_lock( 665 &mut (*pkey).references, 666 1, 667 ffi::CRYPTO_LOCK_EVP_PKEY, 668 "pkey.rs\0".as_ptr() as *const _, 669 line!() as c_int, 670 ); 671 } 672 } 673 } 674 675 impl<T> TryFrom<EcKey<T>> for PKey<T> { 676 type Error = ErrorStack; 677 try_from(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack>678 fn try_from(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> { 679 PKey::from_ec_key(ec_key) 680 } 681 } 682 683 impl<T> TryFrom<PKey<T>> for EcKey<T> { 684 type Error = ErrorStack; 685 try_from(pkey: PKey<T>) -> Result<EcKey<T>, ErrorStack>686 fn try_from(pkey: PKey<T>) -> Result<EcKey<T>, ErrorStack> { 687 pkey.ec_key() 688 } 689 } 690 691 impl<T> TryFrom<Rsa<T>> for PKey<T> { 692 type Error = ErrorStack; 693 try_from(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack>694 fn try_from(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> { 695 PKey::from_rsa(rsa) 696 } 697 } 698 699 impl<T> TryFrom<PKey<T>> for Rsa<T> { 700 type Error = ErrorStack; 701 try_from(pkey: PKey<T>) -> Result<Rsa<T>, ErrorStack>702 fn try_from(pkey: PKey<T>) -> Result<Rsa<T>, ErrorStack> { 703 pkey.rsa() 704 } 705 } 706 707 impl<T> TryFrom<Dsa<T>> for PKey<T> { 708 type Error = ErrorStack; 709 try_from(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack>710 fn try_from(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> { 711 PKey::from_dsa(dsa) 712 } 713 } 714 715 impl<T> TryFrom<PKey<T>> for Dsa<T> { 716 type Error = ErrorStack; 717 try_from(pkey: PKey<T>) -> Result<Dsa<T>, ErrorStack>718 fn try_from(pkey: PKey<T>) -> Result<Dsa<T>, ErrorStack> { 719 pkey.dsa() 720 } 721 } 722 723 impl<T> TryFrom<Dh<T>> for PKey<T> { 724 type Error = ErrorStack; 725 try_from(dh: Dh<T>) -> Result<PKey<T>, ErrorStack>726 fn try_from(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> { 727 PKey::from_dh(dh) 728 } 729 } 730 731 impl<T> TryFrom<PKey<T>> for Dh<T> { 732 type Error = ErrorStack; 733 try_from(pkey: PKey<T>) -> Result<Dh<T>, ErrorStack>734 fn try_from(pkey: PKey<T>) -> Result<Dh<T>, ErrorStack> { 735 pkey.dh() 736 } 737 } 738 739 #[cfg(test)] 740 mod tests { 741 use std::convert::TryInto; 742 743 use crate::dh::Dh; 744 use crate::dsa::Dsa; 745 use crate::ec::EcKey; 746 use crate::nid::Nid; 747 use crate::rsa::Rsa; 748 use crate::symm::Cipher; 749 750 use super::*; 751 752 #[test] test_to_password()753 fn test_to_password() { 754 let rsa = Rsa::generate(2048).unwrap(); 755 let pkey = PKey::from_rsa(rsa).unwrap(); 756 let pem = pkey 757 .private_key_to_pem_pkcs8_passphrase(Cipher::aes_128_cbc(), b"foobar") 758 .unwrap(); 759 PKey::private_key_from_pem_passphrase(&pem, b"foobar").unwrap(); 760 assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err()); 761 } 762 763 #[test] test_unencrypted_pkcs8()764 fn test_unencrypted_pkcs8() { 765 let key = include_bytes!("../test/pkcs8-nocrypt.der"); 766 PKey::private_key_from_pkcs8(key).unwrap(); 767 } 768 769 #[test] test_encrypted_pkcs8_passphrase()770 fn test_encrypted_pkcs8_passphrase() { 771 let key = include_bytes!("../test/pkcs8.der"); 772 PKey::private_key_from_pkcs8_passphrase(key, b"mypass").unwrap(); 773 } 774 775 #[test] test_encrypted_pkcs8_callback()776 fn test_encrypted_pkcs8_callback() { 777 let mut password_queried = false; 778 let key = include_bytes!("../test/pkcs8.der"); 779 PKey::private_key_from_pkcs8_callback(key, |password| { 780 password_queried = true; 781 password[..6].copy_from_slice(b"mypass"); 782 Ok(6) 783 }) 784 .unwrap(); 785 assert!(password_queried); 786 } 787 788 #[test] test_private_key_from_pem()789 fn test_private_key_from_pem() { 790 let key = include_bytes!("../test/key.pem"); 791 PKey::private_key_from_pem(key).unwrap(); 792 } 793 794 #[test] test_public_key_from_pem()795 fn test_public_key_from_pem() { 796 let key = include_bytes!("../test/key.pem.pub"); 797 PKey::public_key_from_pem(key).unwrap(); 798 } 799 800 #[test] test_public_key_from_der()801 fn test_public_key_from_der() { 802 let key = include_bytes!("../test/key.der.pub"); 803 PKey::public_key_from_der(key).unwrap(); 804 } 805 806 #[test] test_private_key_from_der()807 fn test_private_key_from_der() { 808 let key = include_bytes!("../test/key.der"); 809 PKey::private_key_from_der(key).unwrap(); 810 } 811 812 #[test] test_pem()813 fn test_pem() { 814 let key = include_bytes!("../test/key.pem"); 815 let key = PKey::private_key_from_pem(key).unwrap(); 816 817 let priv_key = key.private_key_to_pem_pkcs8().unwrap(); 818 let pub_key = key.public_key_to_pem().unwrap(); 819 820 // As a super-simple verification, just check that the buffers contain 821 // the `PRIVATE KEY` or `PUBLIC KEY` strings. 822 assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY")); 823 assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY")); 824 } 825 826 #[test] test_rsa_accessor()827 fn test_rsa_accessor() { 828 let rsa = Rsa::generate(2048).unwrap(); 829 let pkey = PKey::from_rsa(rsa).unwrap(); 830 pkey.rsa().unwrap(); 831 assert_eq!(pkey.id(), Id::RSA); 832 assert!(pkey.dsa().is_err()); 833 } 834 835 #[test] test_dsa_accessor()836 fn test_dsa_accessor() { 837 let dsa = Dsa::generate(2048).unwrap(); 838 let pkey = PKey::from_dsa(dsa).unwrap(); 839 pkey.dsa().unwrap(); 840 assert_eq!(pkey.id(), Id::DSA); 841 assert!(pkey.rsa().is_err()); 842 } 843 844 #[test] test_dh_accessor()845 fn test_dh_accessor() { 846 let dh = include_bytes!("../test/dhparams.pem"); 847 let dh = Dh::params_from_pem(dh).unwrap(); 848 let pkey = PKey::from_dh(dh).unwrap(); 849 pkey.dh().unwrap(); 850 assert_eq!(pkey.id(), Id::DH); 851 assert!(pkey.rsa().is_err()); 852 } 853 854 #[test] test_ec_key_accessor()855 fn test_ec_key_accessor() { 856 let ec_key = EcKey::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); 857 let pkey = PKey::from_ec_key(ec_key).unwrap(); 858 pkey.ec_key().unwrap(); 859 assert_eq!(pkey.id(), Id::EC); 860 assert!(pkey.rsa().is_err()); 861 } 862 863 #[test] test_rsa_conversion()864 fn test_rsa_conversion() { 865 let rsa = Rsa::generate(2048).unwrap(); 866 let pkey: PKey<Private> = rsa.clone().try_into().unwrap(); 867 let rsa_: Rsa<Private> = pkey.try_into().unwrap(); 868 // Eq is missing 869 assert_eq!(rsa.p(), rsa_.p()); 870 assert_eq!(rsa.q(), rsa_.q()); 871 } 872 873 #[test] test_dsa_conversion()874 fn test_dsa_conversion() { 875 let dsa = Dsa::generate(2048).unwrap(); 876 let pkey: PKey<Private> = dsa.clone().try_into().unwrap(); 877 let dsa_: Dsa<Private> = pkey.try_into().unwrap(); 878 // Eq is missing 879 assert_eq!(dsa.priv_key(), dsa_.priv_key()); 880 } 881 882 #[test] test_ec_key_conversion()883 fn test_ec_key_conversion() { 884 let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::X9_62_PRIME256V1).unwrap(); 885 let ec_key = EcKey::generate(&group).unwrap(); 886 let pkey: PKey<Private> = ec_key.clone().try_into().unwrap(); 887 let ec_key_: EcKey<Private> = pkey.try_into().unwrap(); 888 // Eq is missing 889 assert_eq!(ec_key.private_key(), ec_key_.private_key()); 890 } 891 892 #[test] test_dh_conversion()893 fn test_dh_conversion() { 894 let dh_params = include_bytes!("../test/dhparams.pem"); 895 let dh_params = Dh::params_from_pem(dh_params).unwrap(); 896 let dh = dh_params.generate_key().unwrap(); 897 898 // Clone is missing for Dh, save the parameters 899 let p = dh.prime_p().to_owned().unwrap(); 900 let q = dh.prime_q().map(|q| q.to_owned().unwrap()); 901 let g = dh.generator().to_owned().unwrap(); 902 903 let pkey: PKey<Private> = dh.try_into().unwrap(); 904 let dh_: Dh<Private> = pkey.try_into().unwrap(); 905 906 // Eq is missing 907 assert_eq!(&p, dh_.prime_p()); 908 assert_eq!(q, dh_.prime_q().map(|q| q.to_owned().unwrap())); 909 assert_eq!(&g, dh_.generator()); 910 } 911 } 912