1 //! The asymmetric encryption context. 2 //! 3 //! # Examples 4 //! 5 //! Encrypt data with RSA 6 //! 7 //! ``` 8 //! use openssl::rsa::Rsa; 9 //! use openssl::pkey::PKey; 10 //! use openssl::pkey_ctx::PkeyCtx; 11 //! 12 //! let key = Rsa::generate(4096).unwrap(); 13 //! let key = PKey::from_rsa(key).unwrap(); 14 //! 15 //! let mut ctx = PkeyCtx::new(&key).unwrap(); 16 //! ctx.encrypt_init().unwrap(); 17 //! 18 //! let data = b"Some Crypto Text"; 19 //! let mut ciphertext = vec![]; 20 //! ctx.encrypt_to_vec(data, &mut ciphertext).unwrap(); 21 //! ``` 22 23 #![cfg_attr( 24 not(boringssl), 25 doc = r#"\ 26 Generate a CMAC key 27 28 ``` 29 use openssl::pkey_ctx::PkeyCtx; 30 use openssl::pkey::Id; 31 use openssl::cipher::Cipher; 32 33 let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap(); 34 ctx.keygen_init().unwrap(); 35 ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap(); 36 ctx.set_keygen_mac_key(b"0123456789abcdef").unwrap(); 37 let cmac_key = ctx.keygen().unwrap(); 38 ```"# 39 )] 40 41 //! 42 //! Sign and verify data with RSA 43 //! 44 //! ``` 45 //! use openssl::pkey_ctx::PkeyCtx; 46 //! use openssl::pkey::PKey; 47 //! use openssl::rsa::Rsa; 48 //! 49 //! // Generate a random RSA key. 50 //! let key = Rsa::generate(4096).unwrap(); 51 //! let key = PKey::from_rsa(key).unwrap(); 52 //! 53 //! let text = b"Some Crypto Text"; 54 //! 55 //! // Create the signature. 56 //! let mut ctx = PkeyCtx::new(&key).unwrap(); 57 //! ctx.sign_init().unwrap(); 58 //! let mut signature = vec![]; 59 //! ctx.sign_to_vec(text, &mut signature).unwrap(); 60 //! 61 //! // Verify the signature. 62 //! let mut ctx = PkeyCtx::new(&key).unwrap(); 63 //! ctx.verify_init().unwrap(); 64 //! let valid = ctx.verify(text, &signature).unwrap(); 65 //! assert!(valid); 66 //! ``` 67 #[cfg(not(boringssl))] 68 use crate::cipher::CipherRef; 69 use crate::error::ErrorStack; 70 use crate::md::MdRef; 71 use crate::pkey::{HasPrivate, HasPublic, Id, PKey, PKeyRef, Private}; 72 use crate::rsa::Padding; 73 use crate::{cvt, cvt_n, cvt_p}; 74 use foreign_types::{ForeignType, ForeignTypeRef}; 75 #[cfg(not(boringssl))] 76 use libc::c_int; 77 use openssl_macros::corresponds; 78 use std::convert::TryFrom; 79 use std::ptr; 80 81 /// HKDF modes of operation. 82 #[cfg(ossl111)] 83 pub struct HkdfMode(c_int); 84 85 #[cfg(ossl111)] 86 impl HkdfMode { 87 /// This is the default mode. Calling [`derive`][PkeyCtxRef::derive] on a [`PkeyCtxRef`] set up 88 /// for HKDF will perform an extract followed by an expand operation in one go. The derived key 89 /// returned will be the result after the expand operation. The intermediate fixed-length 90 /// pseudorandom key K is not returned. 91 pub const EXTRACT_THEN_EXPAND: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND); 92 93 /// In this mode calling [`derive`][PkeyCtxRef::derive] will just perform the extract operation. 94 /// The value returned will be the intermediate fixed-length pseudorandom key K. 95 /// 96 /// The digest, key and salt values must be set before a key is derived or an error occurs. 97 pub const EXTRACT_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY); 98 99 /// In this mode calling [`derive`][PkeyCtxRef::derive] will just perform the expand operation. 100 /// The input key should be set to the intermediate fixed-length pseudorandom key K returned 101 /// from a previous extract operation. 102 /// 103 /// The digest, key and info values must be set before a key is derived or an error occurs. 104 pub const EXPAND_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXPAND_ONLY); 105 } 106 107 generic_foreign_type_and_impl_send_sync! { 108 type CType = ffi::EVP_PKEY_CTX; 109 fn drop = ffi::EVP_PKEY_CTX_free; 110 111 /// A context object which can perform asymmetric cryptography operations. 112 pub struct PkeyCtx<T>; 113 /// A reference to a [`PkeyCtx`]. 114 pub struct PkeyCtxRef<T>; 115 } 116 117 impl<T> PkeyCtx<T> { 118 /// Creates a new pkey context using the provided key. 119 #[corresponds(EVP_PKEY_CTX_new)] 120 #[inline] new(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack>121 pub fn new(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack> { 122 unsafe { 123 let ptr = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?; 124 Ok(PkeyCtx::from_ptr(ptr)) 125 } 126 } 127 } 128 129 impl PkeyCtx<()> { 130 /// Creates a new pkey context for the specified algorithm ID. 131 #[corresponds(EVP_PKEY_new_id)] 132 #[inline] new_id(id: Id) -> Result<Self, ErrorStack>133 pub fn new_id(id: Id) -> Result<Self, ErrorStack> { 134 unsafe { 135 let ptr = cvt_p(ffi::EVP_PKEY_CTX_new_id(id.as_raw(), ptr::null_mut()))?; 136 Ok(PkeyCtx::from_ptr(ptr)) 137 } 138 } 139 } 140 141 impl<T> PkeyCtxRef<T> 142 where 143 T: HasPublic, 144 { 145 /// Prepares the context for encryption using the public key. 146 #[corresponds(EVP_PKEY_encrypt_init)] 147 #[inline] encrypt_init(&mut self) -> Result<(), ErrorStack>148 pub fn encrypt_init(&mut self) -> Result<(), ErrorStack> { 149 unsafe { 150 cvt(ffi::EVP_PKEY_encrypt_init(self.as_ptr()))?; 151 } 152 153 Ok(()) 154 } 155 156 /// Prepares the context for signature verification using the public key. 157 #[corresponds(EVP_PKEY_verify_init)] 158 #[inline] verify_init(&mut self) -> Result<(), ErrorStack>159 pub fn verify_init(&mut self) -> Result<(), ErrorStack> { 160 unsafe { 161 cvt(ffi::EVP_PKEY_verify_init(self.as_ptr()))?; 162 } 163 164 Ok(()) 165 } 166 167 /// Encrypts data using the public key. 168 /// 169 /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be 170 /// returned. 171 #[corresponds(EVP_PKEY_encrypt)] 172 #[inline] encrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack>173 pub fn encrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> { 174 let mut written = to.as_ref().map_or(0, |b| b.len()); 175 unsafe { 176 cvt(ffi::EVP_PKEY_encrypt( 177 self.as_ptr(), 178 to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 179 &mut written, 180 from.as_ptr(), 181 from.len(), 182 ))?; 183 } 184 185 Ok(written) 186 } 187 188 /// Like [`Self::encrypt`] but appends ciphertext to a [`Vec`]. encrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack>189 pub fn encrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> { 190 let base = out.len(); 191 let len = self.encrypt(from, None)?; 192 out.resize(base + len, 0); 193 let len = self.encrypt(from, Some(&mut out[base..]))?; 194 out.truncate(base + len); 195 Ok(len) 196 } 197 198 /// Verifies the signature of data using the public key. 199 /// 200 /// Returns `Ok(true)` if the signature is valid, `Ok(false)` if the signature is invalid, and `Err` if an error 201 /// occurred. 202 /// 203 /// # Note 204 /// 205 /// This verifies the signature of the *raw* data. It is more common to compute and verify the signature of the 206 /// cryptographic hash of an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do 207 /// that. 208 #[corresponds(EVP_PKEY_verify)] 209 #[inline] verify(&mut self, data: &[u8], sig: &[u8]) -> Result<bool, ErrorStack>210 pub fn verify(&mut self, data: &[u8], sig: &[u8]) -> Result<bool, ErrorStack> { 211 unsafe { 212 let r = cvt_n(ffi::EVP_PKEY_verify( 213 self.as_ptr(), 214 sig.as_ptr(), 215 sig.len(), 216 data.as_ptr(), 217 data.len(), 218 ))?; 219 Ok(r == 1) 220 } 221 } 222 } 223 224 impl<T> PkeyCtxRef<T> 225 where 226 T: HasPrivate, 227 { 228 /// Prepares the context for decryption using the private key. 229 #[corresponds(EVP_PKEY_decrypt_init)] 230 #[inline] decrypt_init(&mut self) -> Result<(), ErrorStack>231 pub fn decrypt_init(&mut self) -> Result<(), ErrorStack> { 232 unsafe { 233 cvt(ffi::EVP_PKEY_decrypt_init(self.as_ptr()))?; 234 } 235 236 Ok(()) 237 } 238 239 /// Prepares the context for signing using the private key. 240 #[corresponds(EVP_PKEY_sign_init)] 241 #[inline] sign_init(&mut self) -> Result<(), ErrorStack>242 pub fn sign_init(&mut self) -> Result<(), ErrorStack> { 243 unsafe { 244 cvt(ffi::EVP_PKEY_sign_init(self.as_ptr()))?; 245 } 246 247 Ok(()) 248 } 249 250 /// Sets the peer key used for secret derivation. 251 #[corresponds(EVP_PKEY_derive_set_peer)] derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack> where U: HasPublic,252 pub fn derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack> 253 where 254 U: HasPublic, 255 { 256 unsafe { 257 cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), key.as_ptr()))?; 258 } 259 260 Ok(()) 261 } 262 263 /// Decrypts data using the private key. 264 /// 265 /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be 266 /// returned. 267 #[corresponds(EVP_PKEY_decrypt)] 268 #[inline] decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack>269 pub fn decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> { 270 let mut written = to.as_ref().map_or(0, |b| b.len()); 271 unsafe { 272 cvt(ffi::EVP_PKEY_decrypt( 273 self.as_ptr(), 274 to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 275 &mut written, 276 from.as_ptr(), 277 from.len(), 278 ))?; 279 } 280 281 Ok(written) 282 } 283 284 /// Like [`Self::decrypt`] but appends plaintext to a [`Vec`]. decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack>285 pub fn decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> { 286 let base = out.len(); 287 let len = self.decrypt(from, None)?; 288 out.resize(base + len, 0); 289 let len = self.decrypt(from, Some(&mut out[base..]))?; 290 out.truncate(base + len); 291 Ok(len) 292 } 293 294 /// Signs the contents of `data`. 295 /// 296 /// If `sig` is set to `None`, an upper bound on the number of bytes required for the output buffer will be 297 /// returned. 298 /// 299 /// # Note 300 /// 301 /// This computes the signature of the *raw* bytes of `data`. It is more common to sign the cryptographic hash of 302 /// an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do that. 303 #[corresponds(EVP_PKEY_sign)] 304 #[inline] sign(&mut self, data: &[u8], sig: Option<&mut [u8]>) -> Result<usize, ErrorStack>305 pub fn sign(&mut self, data: &[u8], sig: Option<&mut [u8]>) -> Result<usize, ErrorStack> { 306 let mut written = sig.as_ref().map_or(0, |b| b.len()); 307 unsafe { 308 cvt(ffi::EVP_PKEY_sign( 309 self.as_ptr(), 310 sig.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 311 &mut written, 312 data.as_ptr(), 313 data.len(), 314 ))?; 315 } 316 317 Ok(written) 318 } 319 320 /// Like [`Self::sign`] but appends the signature to a [`Vec`]. sign_to_vec(&mut self, data: &[u8], sig: &mut Vec<u8>) -> Result<usize, ErrorStack>321 pub fn sign_to_vec(&mut self, data: &[u8], sig: &mut Vec<u8>) -> Result<usize, ErrorStack> { 322 let base = sig.len(); 323 let len = self.sign(data, None)?; 324 sig.resize(base + len, 0); 325 let len = self.sign(data, Some(&mut sig[base..]))?; 326 sig.truncate(base + len); 327 Ok(len) 328 } 329 } 330 331 impl<T> PkeyCtxRef<T> { 332 /// Prepares the context for shared secret derivation. 333 #[corresponds(EVP_PKEY_derive_init)] 334 #[inline] derive_init(&mut self) -> Result<(), ErrorStack>335 pub fn derive_init(&mut self) -> Result<(), ErrorStack> { 336 unsafe { 337 cvt(ffi::EVP_PKEY_derive_init(self.as_ptr()))?; 338 } 339 340 Ok(()) 341 } 342 343 /// Prepares the context for key generation. 344 #[corresponds(EVP_PKEY_keygen_init)] 345 #[inline] keygen_init(&mut self) -> Result<(), ErrorStack>346 pub fn keygen_init(&mut self) -> Result<(), ErrorStack> { 347 unsafe { 348 cvt(ffi::EVP_PKEY_keygen_init(self.as_ptr()))?; 349 } 350 351 Ok(()) 352 } 353 354 /// Returns the RSA padding mode in use. 355 /// 356 /// This is only useful for RSA keys. 357 #[corresponds(EVP_PKEY_CTX_get_rsa_padding)] 358 #[inline] rsa_padding(&self) -> Result<Padding, ErrorStack>359 pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> { 360 let mut pad = 0; 361 unsafe { 362 cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))?; 363 } 364 365 Ok(Padding::from_raw(pad)) 366 } 367 368 /// Sets the RSA padding mode. 369 /// 370 /// This is only useful for RSA keys. 371 #[corresponds(EVP_PKEY_CTX_set_rsa_padding)] 372 #[inline] set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack>373 pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> { 374 unsafe { 375 cvt(ffi::EVP_PKEY_CTX_set_rsa_padding( 376 self.as_ptr(), 377 padding.as_raw(), 378 ))?; 379 } 380 381 Ok(()) 382 } 383 384 /// Sets the RSA MGF1 algorithm. 385 /// 386 /// This is only useful for RSA keys. 387 #[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)] 388 #[inline] set_rsa_mgf1_md(&mut self, md: &MdRef) -> Result<(), ErrorStack>389 pub fn set_rsa_mgf1_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> { 390 unsafe { 391 cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md( 392 self.as_ptr(), 393 md.as_ptr(), 394 ))?; 395 } 396 397 Ok(()) 398 } 399 400 /// Sets the RSA OAEP algorithm. 401 /// 402 /// This is only useful for RSA keys. 403 #[corresponds(EVP_PKEY_CTX_set_rsa_oaep_md)] 404 #[cfg(any(ossl102, libressl310))] 405 #[inline] set_rsa_oaep_md(&mut self, md: &MdRef) -> Result<(), ErrorStack>406 pub fn set_rsa_oaep_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> { 407 unsafe { 408 cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md( 409 self.as_ptr(), 410 md.as_ptr() as *mut _, 411 ))?; 412 } 413 414 Ok(()) 415 } 416 417 /// Sets the RSA OAEP label. 418 /// 419 /// This is only useful for RSA keys. 420 #[corresponds(EVP_PKEY_CTX_set0_rsa_oaep_label)] 421 #[cfg(any(ossl102, libressl310, boringssl))] set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack>422 pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> { 423 use crate::LenType; 424 let len = LenType::try_from(label.len()).unwrap(); 425 426 unsafe { 427 let p = ffi::OPENSSL_malloc(label.len() as _); 428 ptr::copy_nonoverlapping(label.as_ptr(), p as *mut _, label.len()); 429 430 let r = cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label( 431 self.as_ptr(), 432 p as *mut _, 433 len, 434 )); 435 if r.is_err() { 436 ffi::OPENSSL_free(p); 437 } 438 r?; 439 } 440 441 Ok(()) 442 } 443 444 /// Sets the cipher used during key generation. 445 #[cfg(not(boringssl))] 446 #[corresponds(EVP_PKEY_CTX_ctrl)] 447 #[inline] set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack>448 pub fn set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack> { 449 unsafe { 450 cvt(ffi::EVP_PKEY_CTX_ctrl( 451 self.as_ptr(), 452 -1, 453 ffi::EVP_PKEY_OP_KEYGEN, 454 ffi::EVP_PKEY_CTRL_CIPHER, 455 0, 456 cipher.as_ptr() as *mut _, 457 ))?; 458 } 459 460 Ok(()) 461 } 462 463 /// Sets the key MAC key used during key generation. 464 #[cfg(not(boringssl))] 465 #[corresponds(EVP_PKEY_CTX_ctrl)] 466 #[inline] set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack>467 pub fn set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> { 468 let len = c_int::try_from(key.len()).unwrap(); 469 470 unsafe { 471 cvt(ffi::EVP_PKEY_CTX_ctrl( 472 self.as_ptr(), 473 -1, 474 ffi::EVP_PKEY_OP_KEYGEN, 475 ffi::EVP_PKEY_CTRL_SET_MAC_KEY, 476 len, 477 key.as_ptr() as *mut _, 478 ))?; 479 } 480 481 Ok(()) 482 } 483 484 /// Sets the digest used for HKDF derivation. 485 /// 486 /// Requires OpenSSL 1.1.0 or newer. 487 #[corresponds(EVP_PKEY_CTX_set_hkdf_md)] 488 #[cfg(ossl110)] 489 #[inline] set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack>490 pub fn set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack> { 491 unsafe { 492 cvt(ffi::EVP_PKEY_CTX_set_hkdf_md( 493 self.as_ptr(), 494 digest.as_ptr(), 495 ))?; 496 } 497 498 Ok(()) 499 } 500 501 /// Sets the HKDF mode of operation. 502 /// 503 /// Defaults to [`HkdfMode::EXTRACT_THEN_EXPAND`]. 504 /// 505 /// WARNING: Although this API calls it a "mode", HKDF-Extract and HKDF-Expand are distinct 506 /// operations with distinct inputs and distinct kinds of keys. Callers should not pass input 507 /// secrets for one operation into the other. 508 /// 509 /// Requires OpenSSL 1.1.1 or newer. 510 #[corresponds(EVP_PKEY_CTX_set_hkdf_mode)] 511 #[cfg(ossl111)] 512 #[inline] set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack>513 pub fn set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack> { 514 unsafe { 515 cvt(ffi::EVP_PKEY_CTX_set_hkdf_mode(self.as_ptr(), mode.0))?; 516 } 517 518 Ok(()) 519 } 520 521 /// Sets the input material for HKDF generation as the "key". 522 /// 523 /// Which input is the key depends on the "mode" (see [`set_hkdf_mode`][Self::set_hkdf_mode]). 524 /// If [`HkdfMode::EXTRACT_THEN_EXPAND`] or [`HkdfMode::EXTRACT_ONLY`], this function specifies 525 /// the input keying material (IKM) for HKDF-Extract. If [`HkdfMode::EXPAND_ONLY`], it instead 526 /// specifies the pseudorandom key (PRK) for HKDF-Expand. 527 /// 528 /// Requires OpenSSL 1.1.0 or newer. 529 #[corresponds(EVP_PKEY_CTX_set1_hkdf_key)] 530 #[cfg(ossl110)] 531 #[inline] set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack>532 pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> { 533 let len = c_int::try_from(key.len()).unwrap(); 534 535 unsafe { 536 cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key( 537 self.as_ptr(), 538 key.as_ptr(), 539 len, 540 ))?; 541 } 542 543 Ok(()) 544 } 545 546 /// Sets the salt value for HKDF generation. 547 /// 548 /// If performing HKDF-Expand only, this parameter is ignored. 549 /// 550 /// Requires OpenSSL 1.1.0 or newer. 551 #[corresponds(EVP_PKEY_CTX_set1_hkdf_salt)] 552 #[cfg(ossl110)] 553 #[inline] set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack>554 pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> { 555 let len = c_int::try_from(salt.len()).unwrap(); 556 557 unsafe { 558 cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt( 559 self.as_ptr(), 560 salt.as_ptr(), 561 len, 562 ))?; 563 } 564 565 Ok(()) 566 } 567 568 /// Appends info bytes for HKDF generation. 569 /// 570 /// If performing HKDF-Extract only, this parameter is ignored. 571 /// 572 /// Requires OpenSSL 1.1.0 or newer. 573 #[corresponds(EVP_PKEY_CTX_add1_hkdf_info)] 574 #[cfg(ossl110)] 575 #[inline] add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack>576 pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> { 577 let len = c_int::try_from(info.len()).unwrap(); 578 579 unsafe { 580 cvt(ffi::EVP_PKEY_CTX_add1_hkdf_info( 581 self.as_ptr(), 582 info.as_ptr(), 583 len, 584 ))?; 585 } 586 587 Ok(()) 588 } 589 590 /// Derives a shared secret between two keys. 591 /// 592 /// If `buf` is set to `None`, an upper bound on the number of bytes required for the buffer will be returned. 593 #[corresponds(EVP_PKEY_derive)] derive(&mut self, buf: Option<&mut [u8]>) -> Result<usize, ErrorStack>594 pub fn derive(&mut self, buf: Option<&mut [u8]>) -> Result<usize, ErrorStack> { 595 let mut len = buf.as_ref().map_or(0, |b| b.len()); 596 unsafe { 597 cvt(ffi::EVP_PKEY_derive( 598 self.as_ptr(), 599 buf.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 600 &mut len, 601 ))?; 602 } 603 604 Ok(len) 605 } 606 607 /// Like [`Self::derive`] but appends the secret to a [`Vec`]. derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack>608 pub fn derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack> { 609 let base = buf.len(); 610 let len = self.derive(None)?; 611 buf.resize(base + len, 0); 612 let len = self.derive(Some(&mut buf[base..]))?; 613 buf.truncate(base + len); 614 Ok(len) 615 } 616 617 /// Generates a new public/private keypair. 618 #[corresponds(EVP_PKEY_keygen)] 619 #[inline] keygen(&mut self) -> Result<PKey<Private>, ErrorStack>620 pub fn keygen(&mut self) -> Result<PKey<Private>, ErrorStack> { 621 unsafe { 622 let mut key = ptr::null_mut(); 623 cvt(ffi::EVP_PKEY_keygen(self.as_ptr(), &mut key))?; 624 Ok(PKey::from_ptr(key)) 625 } 626 } 627 } 628 629 #[cfg(test)] 630 mod test { 631 use super::*; 632 #[cfg(not(boringssl))] 633 use crate::cipher::Cipher; 634 use crate::ec::{EcGroup, EcKey}; 635 #[cfg(any(ossl102, libressl310))] 636 use crate::md::Md; 637 use crate::nid::Nid; 638 use crate::pkey::PKey; 639 use crate::rsa::Rsa; 640 641 #[test] rsa()642 fn rsa() { 643 let key = include_bytes!("../test/rsa.pem"); 644 let rsa = Rsa::private_key_from_pem(key).unwrap(); 645 let pkey = PKey::from_rsa(rsa).unwrap(); 646 647 let mut ctx = PkeyCtx::new(&pkey).unwrap(); 648 ctx.encrypt_init().unwrap(); 649 ctx.set_rsa_padding(Padding::PKCS1).unwrap(); 650 651 let pt = "hello world".as_bytes(); 652 let mut ct = vec![]; 653 ctx.encrypt_to_vec(pt, &mut ct).unwrap(); 654 655 ctx.decrypt_init().unwrap(); 656 ctx.set_rsa_padding(Padding::PKCS1).unwrap(); 657 658 let mut out = vec![]; 659 ctx.decrypt_to_vec(&ct, &mut out).unwrap(); 660 661 assert_eq!(pt, out); 662 } 663 664 #[test] 665 #[cfg(any(ossl102, libressl310))] rsa_oaep()666 fn rsa_oaep() { 667 let key = include_bytes!("../test/rsa.pem"); 668 let rsa = Rsa::private_key_from_pem(key).unwrap(); 669 let pkey = PKey::from_rsa(rsa).unwrap(); 670 671 let mut ctx = PkeyCtx::new(&pkey).unwrap(); 672 ctx.encrypt_init().unwrap(); 673 ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap(); 674 ctx.set_rsa_oaep_md(Md::sha256()).unwrap(); 675 ctx.set_rsa_mgf1_md(Md::sha256()).unwrap(); 676 677 let pt = "hello world".as_bytes(); 678 let mut ct = vec![]; 679 ctx.encrypt_to_vec(pt, &mut ct).unwrap(); 680 681 ctx.decrypt_init().unwrap(); 682 ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap(); 683 ctx.set_rsa_oaep_md(Md::sha256()).unwrap(); 684 ctx.set_rsa_mgf1_md(Md::sha256()).unwrap(); 685 686 let mut out = vec![]; 687 ctx.decrypt_to_vec(&ct, &mut out).unwrap(); 688 689 assert_eq!(pt, out); 690 } 691 692 #[test] derive()693 fn derive() { 694 let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); 695 let key1 = EcKey::generate(&group).unwrap(); 696 let key1 = PKey::from_ec_key(key1).unwrap(); 697 let key2 = EcKey::generate(&group).unwrap(); 698 let key2 = PKey::from_ec_key(key2).unwrap(); 699 700 let mut ctx = PkeyCtx::new(&key1).unwrap(); 701 ctx.derive_init().unwrap(); 702 ctx.derive_set_peer(&key2).unwrap(); 703 704 let mut buf = vec![]; 705 ctx.derive_to_vec(&mut buf).unwrap(); 706 } 707 708 #[test] 709 #[cfg(not(boringssl))] cmac_keygen()710 fn cmac_keygen() { 711 let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap(); 712 ctx.keygen_init().unwrap(); 713 ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap(); 714 ctx.set_keygen_mac_key(&hex::decode("9294727a3638bb1c13f48ef8158bfc9d").unwrap()) 715 .unwrap(); 716 ctx.keygen().unwrap(); 717 } 718 719 #[test] 720 #[cfg(ossl110)] hkdf()721 fn hkdf() { 722 let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap(); 723 ctx.derive_init().unwrap(); 724 ctx.set_hkdf_md(Md::sha256()).unwrap(); 725 ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap()) 726 .unwrap(); 727 ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap()) 728 .unwrap(); 729 ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap()) 730 .unwrap(); 731 let mut out = [0; 42]; 732 ctx.derive(Some(&mut out)).unwrap(); 733 734 assert_eq!( 735 &out[..], 736 hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865") 737 .unwrap() 738 ); 739 } 740 741 #[test] 742 #[cfg(ossl111)] hkdf_expand()743 fn hkdf_expand() { 744 let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap(); 745 ctx.derive_init().unwrap(); 746 ctx.set_hkdf_mode(HkdfMode::EXPAND_ONLY).unwrap(); 747 ctx.set_hkdf_md(Md::sha256()).unwrap(); 748 ctx.set_hkdf_key( 749 &hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5") 750 .unwrap(), 751 ) 752 .unwrap(); 753 ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap()) 754 .unwrap(); 755 let mut out = [0; 42]; 756 ctx.derive(Some(&mut out)).unwrap(); 757 758 assert_eq!( 759 &out[..], 760 hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865") 761 .unwrap() 762 ); 763 } 764 765 #[test] 766 #[cfg(ossl111)] hkdf_extract()767 fn hkdf_extract() { 768 let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap(); 769 ctx.derive_init().unwrap(); 770 ctx.set_hkdf_mode(HkdfMode::EXTRACT_ONLY).unwrap(); 771 ctx.set_hkdf_md(Md::sha256()).unwrap(); 772 ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap()) 773 .unwrap(); 774 ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap()) 775 .unwrap(); 776 let mut out = vec![]; 777 ctx.derive_to_vec(&mut out).unwrap(); 778 779 assert_eq!( 780 &out[..], 781 hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5") 782 .unwrap() 783 ); 784 } 785 786 #[test] verify_fail()787 fn verify_fail() { 788 let key1 = Rsa::generate(4096).unwrap(); 789 let key1 = PKey::from_rsa(key1).unwrap(); 790 791 let data = b"Some Crypto Text"; 792 793 let mut ctx = PkeyCtx::new(&key1).unwrap(); 794 ctx.sign_init().unwrap(); 795 let mut signature = vec![]; 796 ctx.sign_to_vec(data, &mut signature).unwrap(); 797 798 let bad_data = b"Some Crypto text"; 799 800 ctx.verify_init().unwrap(); 801 let valid = ctx.verify(bad_data, &signature).unwrap(); 802 assert!(!valid); 803 } 804 } 805