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