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