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::sign::RsaPssSaltlen; 74 use crate::{cvt, cvt_p}; 75 use foreign_types::{ForeignType, ForeignTypeRef}; 76 #[cfg(not(boringssl))] 77 use libc::c_int; 78 #[cfg(ossl320)] 79 use libc::c_uint; 80 use openssl_macros::corresponds; 81 use std::convert::TryFrom; 82 #[cfg(ossl320)] 83 use std::ffi::CStr; 84 use std::ptr; 85 86 /// HKDF modes of operation. 87 #[cfg(any(ossl111, libressl360))] 88 pub struct HkdfMode(c_int); 89 90 #[cfg(any(ossl111, libressl360))] 91 impl HkdfMode { 92 /// This is the default mode. Calling [`derive`][PkeyCtxRef::derive] on a [`PkeyCtxRef`] set up 93 /// for HKDF will perform an extract followed by an expand operation in one go. The derived key 94 /// returned will be the result after the expand operation. The intermediate fixed-length 95 /// pseudorandom key K is not returned. 96 pub const EXTRACT_THEN_EXPAND: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND); 97 98 /// In this mode calling [`derive`][PkeyCtxRef::derive] will just perform the extract operation. 99 /// The value returned will be the intermediate fixed-length pseudorandom key K. 100 /// 101 /// The digest, key and salt values must be set before a key is derived or an error occurs. 102 pub const EXTRACT_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY); 103 104 /// In this mode calling [`derive`][PkeyCtxRef::derive] will just perform the expand operation. 105 /// The input key should be set to the intermediate fixed-length pseudorandom key K returned 106 /// from a previous extract operation. 107 /// 108 /// The digest, key and info values must be set before a key is derived or an error occurs. 109 pub const EXPAND_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXPAND_ONLY); 110 } 111 112 /// Nonce type for ECDSA and DSA. 113 #[cfg(ossl320)] 114 #[derive(Debug, PartialEq)] 115 pub struct NonceType(c_uint); 116 117 #[cfg(ossl320)] 118 impl NonceType { 119 /// This is the default mode. It uses a random value for the nonce k as defined in FIPS 186-4 Section 6.3 120 /// “Secret Number Generation”. 121 pub const RANDOM_K: Self = NonceType(0); 122 123 /// Uses a deterministic value for the nonce k as defined in RFC #6979 (See Section 3.2 “Generation of k”). 124 pub const DETERMINISTIC_K: Self = NonceType(1); 125 } 126 127 generic_foreign_type_and_impl_send_sync! { 128 type CType = ffi::EVP_PKEY_CTX; 129 fn drop = ffi::EVP_PKEY_CTX_free; 130 131 /// A context object which can perform asymmetric cryptography operations. 132 pub struct PkeyCtx<T>; 133 /// A reference to a [`PkeyCtx`]. 134 pub struct PkeyCtxRef<T>; 135 } 136 137 impl<T> PkeyCtx<T> { 138 /// Creates a new pkey context using the provided key. 139 #[corresponds(EVP_PKEY_CTX_new)] 140 #[inline] new(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack>141 pub fn new(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack> { 142 unsafe { 143 let ptr = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?; 144 Ok(PkeyCtx::from_ptr(ptr)) 145 } 146 } 147 } 148 149 impl PkeyCtx<()> { 150 /// Creates a new pkey context for the specified algorithm ID. 151 #[corresponds(EVP_PKEY_new_id)] 152 #[inline] new_id(id: Id) -> Result<Self, ErrorStack>153 pub fn new_id(id: Id) -> Result<Self, ErrorStack> { 154 unsafe { 155 let ptr = cvt_p(ffi::EVP_PKEY_CTX_new_id(id.as_raw(), ptr::null_mut()))?; 156 Ok(PkeyCtx::from_ptr(ptr)) 157 } 158 } 159 } 160 161 impl<T> PkeyCtxRef<T> 162 where 163 T: HasPublic, 164 { 165 /// Prepares the context for encryption using the public key. 166 #[corresponds(EVP_PKEY_encrypt_init)] 167 #[inline] encrypt_init(&mut self) -> Result<(), ErrorStack>168 pub fn encrypt_init(&mut self) -> Result<(), ErrorStack> { 169 unsafe { 170 cvt(ffi::EVP_PKEY_encrypt_init(self.as_ptr()))?; 171 } 172 173 Ok(()) 174 } 175 176 /// Prepares the context for signature verification using the public key. 177 #[corresponds(EVP_PKEY_verify_init)] 178 #[inline] verify_init(&mut self) -> Result<(), ErrorStack>179 pub fn verify_init(&mut self) -> Result<(), ErrorStack> { 180 unsafe { 181 cvt(ffi::EVP_PKEY_verify_init(self.as_ptr()))?; 182 } 183 184 Ok(()) 185 } 186 187 /// Prepares the context for signature recovery using the public key. 188 #[corresponds(EVP_PKEY_verify_recover_init)] 189 #[inline] verify_recover_init(&mut self) -> Result<(), ErrorStack>190 pub fn verify_recover_init(&mut self) -> Result<(), ErrorStack> { 191 unsafe { 192 cvt(ffi::EVP_PKEY_verify_recover_init(self.as_ptr()))?; 193 } 194 195 Ok(()) 196 } 197 198 /// Encrypts data using the public key. 199 /// 200 /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be 201 /// returned. 202 #[corresponds(EVP_PKEY_encrypt)] 203 #[inline] encrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack>204 pub fn encrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> { 205 let mut written = to.as_ref().map_or(0, |b| b.len()); 206 unsafe { 207 cvt(ffi::EVP_PKEY_encrypt( 208 self.as_ptr(), 209 to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 210 &mut written, 211 from.as_ptr(), 212 from.len(), 213 ))?; 214 } 215 216 Ok(written) 217 } 218 219 /// Like [`Self::encrypt`] but appends ciphertext to a [`Vec`]. encrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack>220 pub fn encrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> { 221 let base = out.len(); 222 let len = self.encrypt(from, None)?; 223 out.resize(base + len, 0); 224 let len = self.encrypt(from, Some(&mut out[base..]))?; 225 out.truncate(base + len); 226 Ok(len) 227 } 228 229 /// Verifies the signature of data using the public key. 230 /// 231 /// Returns `Ok(true)` if the signature is valid, `Ok(false)` if the signature is invalid, and `Err` if an error 232 /// occurred. 233 /// 234 /// # Note 235 /// 236 /// This verifies the signature of the *raw* data. It is more common to compute and verify the signature of the 237 /// cryptographic hash of an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do 238 /// that. 239 #[corresponds(EVP_PKEY_verify)] 240 #[inline] verify(&mut self, data: &[u8], sig: &[u8]) -> Result<bool, ErrorStack>241 pub fn verify(&mut self, data: &[u8], sig: &[u8]) -> Result<bool, ErrorStack> { 242 unsafe { 243 let r = ffi::EVP_PKEY_verify( 244 self.as_ptr(), 245 sig.as_ptr(), 246 sig.len(), 247 data.as_ptr(), 248 data.len(), 249 ); 250 // `EVP_PKEY_verify` is not terribly consistent about how it, 251 // reports errors. It does not clearly distinguish between 0 and 252 // -1, and may put errors on the stack in both cases. If there's 253 // errors on the stack, we return `Err()`, else we return 254 // `Ok(false)`. 255 if r <= 0 { 256 let errors = ErrorStack::get(); 257 if !errors.errors().is_empty() { 258 return Err(errors); 259 } 260 } 261 262 Ok(r == 1) 263 } 264 } 265 266 /// Recovers the original data signed by the private key. You almost 267 /// always want `verify` instead. 268 /// 269 /// Returns the number of bytes written to `to`, or the number of bytes 270 /// that would be written, if `to` is `None. 271 #[corresponds(EVP_PKEY_verify_recover)] 272 #[inline] verify_recover( &mut self, sig: &[u8], to: Option<&mut [u8]>, ) -> Result<usize, ErrorStack>273 pub fn verify_recover( 274 &mut self, 275 sig: &[u8], 276 to: Option<&mut [u8]>, 277 ) -> Result<usize, ErrorStack> { 278 let mut written = to.as_ref().map_or(0, |b| b.len()); 279 unsafe { 280 cvt(ffi::EVP_PKEY_verify_recover( 281 self.as_ptr(), 282 to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 283 &mut written, 284 sig.as_ptr(), 285 sig.len(), 286 ))?; 287 } 288 289 Ok(written) 290 } 291 } 292 293 impl<T> PkeyCtxRef<T> 294 where 295 T: HasPrivate, 296 { 297 /// Prepares the context for decryption using the private key. 298 #[corresponds(EVP_PKEY_decrypt_init)] 299 #[inline] decrypt_init(&mut self) -> Result<(), ErrorStack>300 pub fn decrypt_init(&mut self) -> Result<(), ErrorStack> { 301 unsafe { 302 cvt(ffi::EVP_PKEY_decrypt_init(self.as_ptr()))?; 303 } 304 305 Ok(()) 306 } 307 308 /// Prepares the context for signing using the private key. 309 #[corresponds(EVP_PKEY_sign_init)] 310 #[inline] sign_init(&mut self) -> Result<(), ErrorStack>311 pub fn sign_init(&mut self) -> Result<(), ErrorStack> { 312 unsafe { 313 cvt(ffi::EVP_PKEY_sign_init(self.as_ptr()))?; 314 } 315 316 Ok(()) 317 } 318 319 /// Sets the peer key used for secret derivation. 320 #[corresponds(EVP_PKEY_derive_set_peer)] derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack> where U: HasPublic,321 pub fn derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack> 322 where 323 U: HasPublic, 324 { 325 unsafe { 326 cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), key.as_ptr()))?; 327 } 328 329 Ok(()) 330 } 331 332 /// Decrypts data using the private key. 333 /// 334 /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be 335 /// returned. 336 #[corresponds(EVP_PKEY_decrypt)] 337 #[inline] decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack>338 pub fn decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> { 339 let mut written = to.as_ref().map_or(0, |b| b.len()); 340 unsafe { 341 cvt(ffi::EVP_PKEY_decrypt( 342 self.as_ptr(), 343 to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 344 &mut written, 345 from.as_ptr(), 346 from.len(), 347 ))?; 348 } 349 350 Ok(written) 351 } 352 353 /// Like [`Self::decrypt`] but appends plaintext to a [`Vec`]. decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack>354 pub fn decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> { 355 let base = out.len(); 356 let len = self.decrypt(from, None)?; 357 out.resize(base + len, 0); 358 let len = self.decrypt(from, Some(&mut out[base..]))?; 359 out.truncate(base + len); 360 Ok(len) 361 } 362 363 /// Signs the contents of `data`. 364 /// 365 /// If `sig` is set to `None`, an upper bound on the number of bytes required for the output buffer will be 366 /// returned. 367 /// 368 /// # Note 369 /// 370 /// This computes the signature of the *raw* bytes of `data`. It is more common to sign the cryptographic hash of 371 /// an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do that. 372 #[corresponds(EVP_PKEY_sign)] 373 #[inline] sign(&mut self, data: &[u8], sig: Option<&mut [u8]>) -> Result<usize, ErrorStack>374 pub fn sign(&mut self, data: &[u8], sig: Option<&mut [u8]>) -> Result<usize, ErrorStack> { 375 let mut written = sig.as_ref().map_or(0, |b| b.len()); 376 unsafe { 377 cvt(ffi::EVP_PKEY_sign( 378 self.as_ptr(), 379 sig.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 380 &mut written, 381 data.as_ptr(), 382 data.len(), 383 ))?; 384 } 385 386 Ok(written) 387 } 388 389 /// Like [`Self::sign`] but appends the signature to a [`Vec`]. sign_to_vec(&mut self, data: &[u8], sig: &mut Vec<u8>) -> Result<usize, ErrorStack>390 pub fn sign_to_vec(&mut self, data: &[u8], sig: &mut Vec<u8>) -> Result<usize, ErrorStack> { 391 let base = sig.len(); 392 let len = self.sign(data, None)?; 393 sig.resize(base + len, 0); 394 let len = self.sign(data, Some(&mut sig[base..]))?; 395 sig.truncate(base + len); 396 Ok(len) 397 } 398 } 399 400 impl<T> PkeyCtxRef<T> { 401 /// Prepares the context for shared secret derivation. 402 #[corresponds(EVP_PKEY_derive_init)] 403 #[inline] derive_init(&mut self) -> Result<(), ErrorStack>404 pub fn derive_init(&mut self) -> Result<(), ErrorStack> { 405 unsafe { 406 cvt(ffi::EVP_PKEY_derive_init(self.as_ptr()))?; 407 } 408 409 Ok(()) 410 } 411 412 /// Prepares the context for key generation. 413 #[corresponds(EVP_PKEY_keygen_init)] 414 #[inline] keygen_init(&mut self) -> Result<(), ErrorStack>415 pub fn keygen_init(&mut self) -> Result<(), ErrorStack> { 416 unsafe { 417 cvt(ffi::EVP_PKEY_keygen_init(self.as_ptr()))?; 418 } 419 420 Ok(()) 421 } 422 423 /// Sets which algorithm was used to compute the digest used in a 424 /// signature. With RSA signatures this causes the signature to be wrapped 425 /// in a `DigestInfo` structure. This is almost always what you want with 426 /// RSA signatures. 427 #[corresponds(EVP_PKEY_CTX_set_signature_md)] 428 #[inline] set_signature_md(&self, md: &MdRef) -> Result<(), ErrorStack>429 pub fn set_signature_md(&self, md: &MdRef) -> Result<(), ErrorStack> { 430 unsafe { 431 cvt(ffi::EVP_PKEY_CTX_set_signature_md( 432 self.as_ptr(), 433 md.as_ptr(), 434 ))?; 435 } 436 Ok(()) 437 } 438 439 /// Returns the RSA padding mode in use. 440 /// 441 /// This is only useful for RSA keys. 442 #[corresponds(EVP_PKEY_CTX_get_rsa_padding)] 443 #[inline] rsa_padding(&self) -> Result<Padding, ErrorStack>444 pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> { 445 let mut pad = 0; 446 unsafe { 447 cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))?; 448 } 449 450 Ok(Padding::from_raw(pad)) 451 } 452 453 /// Sets the RSA padding mode. 454 /// 455 /// This is only useful for RSA keys. 456 #[corresponds(EVP_PKEY_CTX_set_rsa_padding)] 457 #[inline] set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack>458 pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> { 459 unsafe { 460 cvt(ffi::EVP_PKEY_CTX_set_rsa_padding( 461 self.as_ptr(), 462 padding.as_raw(), 463 ))?; 464 } 465 466 Ok(()) 467 } 468 469 /// Sets the RSA PSS salt length. 470 /// 471 /// This is only useful for RSA keys. 472 #[corresponds(EVP_PKEY_CTX_set_rsa_pss_saltlen)] 473 #[inline] set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack>474 pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> { 475 unsafe { 476 cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen( 477 self.as_ptr(), 478 len.as_raw(), 479 )) 480 .map(|_| ()) 481 } 482 } 483 484 /// Sets the RSA MGF1 algorithm. 485 /// 486 /// This is only useful for RSA keys. 487 #[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)] 488 #[inline] set_rsa_mgf1_md(&mut self, md: &MdRef) -> Result<(), ErrorStack>489 pub fn set_rsa_mgf1_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> { 490 unsafe { 491 cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md( 492 self.as_ptr(), 493 md.as_ptr(), 494 ))?; 495 } 496 497 Ok(()) 498 } 499 500 /// Sets the RSA OAEP algorithm. 501 /// 502 /// This is only useful for RSA keys. 503 #[corresponds(EVP_PKEY_CTX_set_rsa_oaep_md)] 504 #[cfg(any(ossl102, libressl310, boringssl))] 505 #[inline] set_rsa_oaep_md(&mut self, md: &MdRef) -> Result<(), ErrorStack>506 pub fn set_rsa_oaep_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> { 507 unsafe { 508 cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md( 509 self.as_ptr(), 510 md.as_ptr() as *mut _, 511 ))?; 512 } 513 514 Ok(()) 515 } 516 517 /// Sets the RSA OAEP label. 518 /// 519 /// This is only useful for RSA keys. 520 #[corresponds(EVP_PKEY_CTX_set0_rsa_oaep_label)] 521 #[cfg(any(ossl102, libressl310, boringssl))] set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack>522 pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> { 523 use crate::LenType; 524 let len = LenType::try_from(label.len()).unwrap(); 525 526 unsafe { 527 let p = ffi::OPENSSL_malloc(label.len() as _); 528 ptr::copy_nonoverlapping(label.as_ptr(), p as *mut _, label.len()); 529 530 let r = cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label( 531 self.as_ptr(), 532 p as *mut _, 533 len, 534 )); 535 if r.is_err() { 536 ffi::OPENSSL_free(p); 537 } 538 r?; 539 } 540 541 Ok(()) 542 } 543 544 /// Sets the cipher used during key generation. 545 #[cfg(not(boringssl))] 546 #[corresponds(EVP_PKEY_CTX_ctrl)] 547 #[inline] set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack>548 pub fn set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack> { 549 unsafe { 550 cvt(ffi::EVP_PKEY_CTX_ctrl( 551 self.as_ptr(), 552 -1, 553 ffi::EVP_PKEY_OP_KEYGEN, 554 ffi::EVP_PKEY_CTRL_CIPHER, 555 0, 556 cipher.as_ptr() as *mut _, 557 ))?; 558 } 559 560 Ok(()) 561 } 562 563 /// Sets the key MAC key used during key generation. 564 #[cfg(not(boringssl))] 565 #[corresponds(EVP_PKEY_CTX_ctrl)] 566 #[inline] set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack>567 pub fn set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> { 568 let len = c_int::try_from(key.len()).unwrap(); 569 570 unsafe { 571 cvt(ffi::EVP_PKEY_CTX_ctrl( 572 self.as_ptr(), 573 -1, 574 ffi::EVP_PKEY_OP_KEYGEN, 575 ffi::EVP_PKEY_CTRL_SET_MAC_KEY, 576 len, 577 key.as_ptr() as *mut _, 578 ))?; 579 } 580 581 Ok(()) 582 } 583 584 /// Sets the digest used for HKDF derivation. 585 /// 586 /// Requires OpenSSL 1.1.0 or newer. 587 #[corresponds(EVP_PKEY_CTX_set_hkdf_md)] 588 #[cfg(any(ossl110, boringssl, libressl360))] 589 #[inline] set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack>590 pub fn set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack> { 591 unsafe { 592 cvt(ffi::EVP_PKEY_CTX_set_hkdf_md( 593 self.as_ptr(), 594 digest.as_ptr(), 595 ))?; 596 } 597 598 Ok(()) 599 } 600 601 /// Sets the HKDF mode of operation. 602 /// 603 /// Defaults to [`HkdfMode::EXTRACT_THEN_EXPAND`]. 604 /// 605 /// WARNING: Although this API calls it a "mode", HKDF-Extract and HKDF-Expand are distinct 606 /// operations with distinct inputs and distinct kinds of keys. Callers should not pass input 607 /// secrets for one operation into the other. 608 /// 609 /// Requires OpenSSL 1.1.1 or newer. 610 #[corresponds(EVP_PKEY_CTX_set_hkdf_mode)] 611 #[cfg(any(ossl111, libressl360))] 612 #[inline] set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack>613 pub fn set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack> { 614 unsafe { 615 cvt(ffi::EVP_PKEY_CTX_set_hkdf_mode(self.as_ptr(), mode.0))?; 616 } 617 618 Ok(()) 619 } 620 621 /// Sets the input material for HKDF generation as the "key". 622 /// 623 /// Which input is the key depends on the "mode" (see [`set_hkdf_mode`][Self::set_hkdf_mode]). 624 /// If [`HkdfMode::EXTRACT_THEN_EXPAND`] or [`HkdfMode::EXTRACT_ONLY`], this function specifies 625 /// the input keying material (IKM) for HKDF-Extract. If [`HkdfMode::EXPAND_ONLY`], it instead 626 /// specifies the pseudorandom key (PRK) for HKDF-Expand. 627 /// 628 /// Requires OpenSSL 1.1.0 or newer. 629 #[corresponds(EVP_PKEY_CTX_set1_hkdf_key)] 630 #[cfg(any(ossl110, boringssl, libressl360))] 631 #[inline] set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack>632 pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> { 633 #[cfg(not(boringssl))] 634 let len = c_int::try_from(key.len()).unwrap(); 635 #[cfg(boringssl)] 636 let len = key.len(); 637 638 unsafe { 639 cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key( 640 self.as_ptr(), 641 key.as_ptr(), 642 len, 643 ))?; 644 } 645 646 Ok(()) 647 } 648 649 /// Sets the salt value for HKDF generation. 650 /// 651 /// If performing HKDF-Expand only, this parameter is ignored. 652 /// 653 /// Requires OpenSSL 1.1.0 or newer. 654 #[corresponds(EVP_PKEY_CTX_set1_hkdf_salt)] 655 #[cfg(any(ossl110, boringssl, libressl360))] 656 #[inline] set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack>657 pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> { 658 #[cfg(not(boringssl))] 659 let len = c_int::try_from(salt.len()).unwrap(); 660 #[cfg(boringssl)] 661 let len = salt.len(); 662 663 unsafe { 664 cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt( 665 self.as_ptr(), 666 salt.as_ptr(), 667 len, 668 ))?; 669 } 670 671 Ok(()) 672 } 673 674 /// Appends info bytes for HKDF generation. 675 /// 676 /// If performing HKDF-Extract only, this parameter is ignored. 677 /// 678 /// Requires OpenSSL 1.1.0 or newer. 679 #[corresponds(EVP_PKEY_CTX_add1_hkdf_info)] 680 #[cfg(any(ossl110, boringssl, libressl360))] 681 #[inline] add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack>682 pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> { 683 #[cfg(not(boringssl))] 684 let len = c_int::try_from(info.len()).unwrap(); 685 #[cfg(boringssl)] 686 let len = info.len(); 687 688 unsafe { 689 cvt(ffi::EVP_PKEY_CTX_add1_hkdf_info( 690 self.as_ptr(), 691 info.as_ptr(), 692 len, 693 ))?; 694 } 695 696 Ok(()) 697 } 698 699 /// Derives a shared secret between two keys. 700 /// 701 /// If `buf` is set to `None`, an upper bound on the number of bytes required for the buffer will be returned. 702 #[corresponds(EVP_PKEY_derive)] derive(&mut self, buf: Option<&mut [u8]>) -> Result<usize, ErrorStack>703 pub fn derive(&mut self, buf: Option<&mut [u8]>) -> Result<usize, ErrorStack> { 704 let mut len = buf.as_ref().map_or(0, |b| b.len()); 705 unsafe { 706 cvt(ffi::EVP_PKEY_derive( 707 self.as_ptr(), 708 buf.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 709 &mut len, 710 ))?; 711 } 712 713 Ok(len) 714 } 715 716 /// Like [`Self::derive`] but appends the secret to a [`Vec`]. derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack>717 pub fn derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack> { 718 let base = buf.len(); 719 let len = self.derive(None)?; 720 buf.resize(base + len, 0); 721 let len = self.derive(Some(&mut buf[base..]))?; 722 buf.truncate(base + len); 723 Ok(len) 724 } 725 726 /// Generates a new public/private keypair. 727 #[corresponds(EVP_PKEY_keygen)] 728 #[inline] keygen(&mut self) -> Result<PKey<Private>, ErrorStack>729 pub fn keygen(&mut self) -> Result<PKey<Private>, ErrorStack> { 730 unsafe { 731 let mut key = ptr::null_mut(); 732 cvt(ffi::EVP_PKEY_keygen(self.as_ptr(), &mut key))?; 733 Ok(PKey::from_ptr(key)) 734 } 735 } 736 737 /// Sets the nonce type for a private key context. 738 /// 739 /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979). 740 /// 741 /// This is only useful for DSA and ECDSA. 742 /// Requires OpenSSL 3.2.0 or newer. 743 #[cfg(ossl320)] 744 #[corresponds(EVP_PKEY_CTX_set_params)] set_nonce_type(&mut self, nonce_type: NonceType) -> Result<(), ErrorStack>745 pub fn set_nonce_type(&mut self, nonce_type: NonceType) -> Result<(), ErrorStack> { 746 let nonce_field_name = CStr::from_bytes_with_nul(b"nonce-type\0").unwrap(); 747 let mut nonce_type = nonce_type.0; 748 unsafe { 749 let param_nonce = 750 ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type); 751 let param_end = ffi::OSSL_PARAM_construct_end(); 752 753 let params = [param_nonce, param_end]; 754 cvt(ffi::EVP_PKEY_CTX_set_params(self.as_ptr(), params.as_ptr()))?; 755 } 756 Ok(()) 757 } 758 759 /// Gets the nonce type for a private key context. 760 /// 761 /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979). 762 /// 763 /// This is only useful for DSA and ECDSA. 764 /// Requires OpenSSL 3.2.0 or newer. 765 #[cfg(ossl320)] 766 #[corresponds(EVP_PKEY_CTX_get_params)] nonce_type(&mut self) -> Result<NonceType, ErrorStack>767 pub fn nonce_type(&mut self) -> Result<NonceType, ErrorStack> { 768 let nonce_field_name = CStr::from_bytes_with_nul(b"nonce-type\0").unwrap(); 769 let mut nonce_type: c_uint = 0; 770 unsafe { 771 let param_nonce = 772 ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type); 773 let param_end = ffi::OSSL_PARAM_construct_end(); 774 775 let mut params = [param_nonce, param_end]; 776 cvt(ffi::EVP_PKEY_CTX_get_params( 777 self.as_ptr(), 778 params.as_mut_ptr(), 779 ))?; 780 } 781 Ok(NonceType(nonce_type)) 782 } 783 } 784 785 #[cfg(test)] 786 mod test { 787 use super::*; 788 #[cfg(not(boringssl))] 789 use crate::cipher::Cipher; 790 use crate::ec::{EcGroup, EcKey}; 791 use crate::hash::{hash, MessageDigest}; 792 use crate::md::Md; 793 use crate::nid::Nid; 794 use crate::pkey::PKey; 795 use crate::rsa::Rsa; 796 use crate::sign::Verifier; 797 798 #[test] rsa()799 fn rsa() { 800 let key = include_bytes!("../test/rsa.pem"); 801 let rsa = Rsa::private_key_from_pem(key).unwrap(); 802 let pkey = PKey::from_rsa(rsa).unwrap(); 803 804 let mut ctx = PkeyCtx::new(&pkey).unwrap(); 805 ctx.encrypt_init().unwrap(); 806 ctx.set_rsa_padding(Padding::PKCS1).unwrap(); 807 808 let pt = "hello world".as_bytes(); 809 let mut ct = vec![]; 810 ctx.encrypt_to_vec(pt, &mut ct).unwrap(); 811 812 ctx.decrypt_init().unwrap(); 813 ctx.set_rsa_padding(Padding::PKCS1).unwrap(); 814 815 let mut out = vec![]; 816 ctx.decrypt_to_vec(&ct, &mut out).unwrap(); 817 818 assert_eq!(pt, out); 819 } 820 821 #[test] 822 #[cfg(any(ossl102, libressl310, boringssl))] rsa_oaep()823 fn rsa_oaep() { 824 let key = include_bytes!("../test/rsa.pem"); 825 let rsa = Rsa::private_key_from_pem(key).unwrap(); 826 let pkey = PKey::from_rsa(rsa).unwrap(); 827 828 let mut ctx = PkeyCtx::new(&pkey).unwrap(); 829 ctx.encrypt_init().unwrap(); 830 ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap(); 831 ctx.set_rsa_oaep_md(Md::sha256()).unwrap(); 832 ctx.set_rsa_mgf1_md(Md::sha256()).unwrap(); 833 834 let pt = "hello world".as_bytes(); 835 let mut ct = vec![]; 836 ctx.encrypt_to_vec(pt, &mut ct).unwrap(); 837 838 ctx.decrypt_init().unwrap(); 839 ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap(); 840 ctx.set_rsa_oaep_md(Md::sha256()).unwrap(); 841 ctx.set_rsa_mgf1_md(Md::sha256()).unwrap(); 842 843 let mut out = vec![]; 844 ctx.decrypt_to_vec(&ct, &mut out).unwrap(); 845 846 assert_eq!(pt, out); 847 } 848 849 #[test] rsa_sign()850 fn rsa_sign() { 851 let key = include_bytes!("../test/rsa.pem"); 852 let rsa = Rsa::private_key_from_pem(key).unwrap(); 853 let pkey = PKey::from_rsa(rsa).unwrap(); 854 855 let mut ctx = PkeyCtx::new(&pkey).unwrap(); 856 ctx.sign_init().unwrap(); 857 ctx.set_rsa_padding(Padding::PKCS1).unwrap(); 858 ctx.set_signature_md(Md::sha384()).unwrap(); 859 860 let msg = b"hello world"; 861 let digest = hash(MessageDigest::sha384(), msg).unwrap(); 862 let mut signature = vec![]; 863 ctx.sign_to_vec(&digest, &mut signature).unwrap(); 864 865 let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap(); 866 verifier.update(msg).unwrap(); 867 assert!(matches!(verifier.verify(&signature), Ok(true))); 868 } 869 870 #[test] rsa_sign_pss()871 fn rsa_sign_pss() { 872 let key = include_bytes!("../test/rsa.pem"); 873 let rsa = Rsa::private_key_from_pem(key).unwrap(); 874 let pkey = PKey::from_rsa(rsa).unwrap(); 875 876 let mut ctx = PkeyCtx::new(&pkey).unwrap(); 877 ctx.sign_init().unwrap(); 878 ctx.set_rsa_padding(Padding::PKCS1_PSS).unwrap(); 879 ctx.set_signature_md(Md::sha384()).unwrap(); 880 ctx.set_rsa_pss_saltlen(RsaPssSaltlen::custom(14)).unwrap(); 881 882 let msg = b"hello world"; 883 let digest = hash(MessageDigest::sha384(), msg).unwrap(); 884 let mut signature = vec![]; 885 ctx.sign_to_vec(&digest, &mut signature).unwrap(); 886 887 let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap(); 888 verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap(); 889 verifier 890 .set_rsa_pss_saltlen(RsaPssSaltlen::custom(14)) 891 .unwrap(); 892 verifier.update(msg).unwrap(); 893 assert!(matches!(verifier.verify(&signature), Ok(true))); 894 } 895 896 #[test] derive()897 fn derive() { 898 let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); 899 let key1 = EcKey::generate(&group).unwrap(); 900 let key1 = PKey::from_ec_key(key1).unwrap(); 901 let key2 = EcKey::generate(&group).unwrap(); 902 let key2 = PKey::from_ec_key(key2).unwrap(); 903 904 let mut ctx = PkeyCtx::new(&key1).unwrap(); 905 ctx.derive_init().unwrap(); 906 ctx.derive_set_peer(&key2).unwrap(); 907 908 let mut buf = vec![]; 909 ctx.derive_to_vec(&mut buf).unwrap(); 910 } 911 912 #[test] 913 #[cfg(not(boringssl))] cmac_keygen()914 fn cmac_keygen() { 915 let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap(); 916 ctx.keygen_init().unwrap(); 917 ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap(); 918 ctx.set_keygen_mac_key(&hex::decode("9294727a3638bb1c13f48ef8158bfc9d").unwrap()) 919 .unwrap(); 920 ctx.keygen().unwrap(); 921 } 922 923 #[test] 924 #[cfg(any(ossl110, boringssl, libressl360))] hkdf()925 fn hkdf() { 926 let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap(); 927 ctx.derive_init().unwrap(); 928 ctx.set_hkdf_md(Md::sha256()).unwrap(); 929 ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap()) 930 .unwrap(); 931 ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap()) 932 .unwrap(); 933 ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap()) 934 .unwrap(); 935 let mut out = [0; 42]; 936 ctx.derive(Some(&mut out)).unwrap(); 937 938 assert_eq!( 939 &out[..], 940 hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865") 941 .unwrap() 942 ); 943 } 944 945 #[test] 946 #[cfg(any(ossl111, libressl360))] hkdf_expand()947 fn hkdf_expand() { 948 let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap(); 949 ctx.derive_init().unwrap(); 950 ctx.set_hkdf_mode(HkdfMode::EXPAND_ONLY).unwrap(); 951 ctx.set_hkdf_md(Md::sha256()).unwrap(); 952 ctx.set_hkdf_key( 953 &hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5") 954 .unwrap(), 955 ) 956 .unwrap(); 957 ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap()) 958 .unwrap(); 959 let mut out = [0; 42]; 960 ctx.derive(Some(&mut out)).unwrap(); 961 962 assert_eq!( 963 &out[..], 964 hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865") 965 .unwrap() 966 ); 967 } 968 969 #[test] 970 #[cfg(any(ossl111, libressl360))] hkdf_extract()971 fn hkdf_extract() { 972 let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap(); 973 ctx.derive_init().unwrap(); 974 ctx.set_hkdf_mode(HkdfMode::EXTRACT_ONLY).unwrap(); 975 ctx.set_hkdf_md(Md::sha256()).unwrap(); 976 ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap()) 977 .unwrap(); 978 ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap()) 979 .unwrap(); 980 let mut out = vec![]; 981 ctx.derive_to_vec(&mut out).unwrap(); 982 983 assert_eq!( 984 &out[..], 985 hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5") 986 .unwrap() 987 ); 988 } 989 990 #[test] verify_fail()991 fn verify_fail() { 992 let key1 = Rsa::generate(4096).unwrap(); 993 let key1 = PKey::from_rsa(key1).unwrap(); 994 995 let data = b"Some Crypto Text"; 996 997 let mut ctx = PkeyCtx::new(&key1).unwrap(); 998 ctx.sign_init().unwrap(); 999 let mut signature = vec![]; 1000 ctx.sign_to_vec(data, &mut signature).unwrap(); 1001 1002 let bad_data = b"Some Crypto text"; 1003 1004 ctx.verify_init().unwrap(); 1005 let valid = ctx.verify(bad_data, &signature); 1006 assert!(matches!(valid, Ok(false) | Err(_))); 1007 assert!(ErrorStack::get().errors().is_empty()); 1008 } 1009 1010 #[test] verify_fail_ec()1011 fn verify_fail_ec() { 1012 let key1 = 1013 EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap(); 1014 let key1 = PKey::from_ec_key(key1).unwrap(); 1015 1016 let data = b"Some Crypto Text"; 1017 let mut ctx = PkeyCtx::new(&key1).unwrap(); 1018 ctx.verify_init().unwrap(); 1019 assert!(matches!(ctx.verify(data, &[0; 64]), Ok(false) | Err(_))); 1020 assert!(ErrorStack::get().errors().is_empty()); 1021 } 1022 1023 #[test] test_verify_recover()1024 fn test_verify_recover() { 1025 let key = Rsa::generate(2048).unwrap(); 1026 let key = PKey::from_rsa(key).unwrap(); 1027 1028 let digest = [ 1029 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 1030 24, 25, 26, 27, 28, 29, 30, 31, 1031 ]; 1032 1033 let mut ctx = PkeyCtx::new(&key).unwrap(); 1034 ctx.sign_init().unwrap(); 1035 ctx.set_rsa_padding(Padding::PKCS1).unwrap(); 1036 ctx.set_signature_md(Md::sha256()).unwrap(); 1037 let mut signature = vec![]; 1038 ctx.sign_to_vec(&digest, &mut signature).unwrap(); 1039 1040 // Attempt recovery of just the digest. 1041 let mut ctx = PkeyCtx::new(&key).unwrap(); 1042 ctx.verify_recover_init().unwrap(); 1043 ctx.set_rsa_padding(Padding::PKCS1).unwrap(); 1044 ctx.set_signature_md(Md::sha256()).unwrap(); 1045 let length = ctx.verify_recover(&signature, None).unwrap(); 1046 let mut result_buf = vec![0; length]; 1047 let length = ctx 1048 .verify_recover(&signature, Some(&mut result_buf)) 1049 .unwrap(); 1050 assert_eq!(length, digest.len()); 1051 // result_buf contains the digest 1052 assert_eq!(result_buf[..length], digest); 1053 1054 // Attempt recovery of teh entire DigestInfo 1055 let mut ctx = PkeyCtx::new(&key).unwrap(); 1056 ctx.verify_recover_init().unwrap(); 1057 ctx.set_rsa_padding(Padding::PKCS1).unwrap(); 1058 let length = ctx.verify_recover(&signature, None).unwrap(); 1059 let mut result_buf = vec![0; length]; 1060 let length = ctx 1061 .verify_recover(&signature, Some(&mut result_buf)) 1062 .unwrap(); 1063 // 32-bytes of SHA256 digest + the ASN.1 DigestInfo structure == 51 bytes 1064 assert_eq!(length, 51); 1065 // The digest is the end of the DigestInfo structure. 1066 assert_eq!(result_buf[length - digest.len()..length], digest); 1067 } 1068 1069 #[test] 1070 #[cfg(ossl320)] set_nonce_type()1071 fn set_nonce_type() { 1072 let key1 = 1073 EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap(); 1074 let key1 = PKey::from_ec_key(key1).unwrap(); 1075 1076 let mut ctx = PkeyCtx::new(&key1).unwrap(); 1077 ctx.sign_init().unwrap(); 1078 ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap(); 1079 let nonce_type = ctx.nonce_type().unwrap(); 1080 assert_eq!(nonce_type, NonceType::DETERMINISTIC_K); 1081 assert!(ErrorStack::get().errors().is_empty()); 1082 } 1083 1084 // Test vector from 1085 // https://github.com/openssl/openssl/blob/openssl-3.2.0/test/recipes/30-test_evp_data/evppkey_ecdsa_rfc6979.txt 1086 #[test] 1087 #[cfg(ossl320)] ecdsa_deterministic_signature()1088 fn ecdsa_deterministic_signature() { 1089 let private_key_pem = "-----BEGIN PRIVATE KEY----- 1090 MDkCAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEHzAdAgEBBBhvqwNJNOTA/Jrmf1tWWanX0f79GH7g 1091 n9Q= 1092 -----END PRIVATE KEY-----"; 1093 1094 let key1 = EcKey::private_key_from_pem(private_key_pem.as_bytes()).unwrap(); 1095 let key1 = PKey::from_ec_key(key1).unwrap(); 1096 let input = "sample"; 1097 let expected_output = hex::decode("303502190098C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF021857A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64").unwrap(); 1098 1099 let hashed_input = hash(MessageDigest::sha1(), input.as_bytes()).unwrap(); 1100 let mut ctx = PkeyCtx::new(&key1).unwrap(); 1101 ctx.sign_init().unwrap(); 1102 ctx.set_signature_md(Md::sha1()).unwrap(); 1103 ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap(); 1104 1105 let mut output = vec![]; 1106 ctx.sign_to_vec(&hashed_input, &mut output).unwrap(); 1107 assert_eq!(output, expected_output); 1108 assert!(ErrorStack::get().errors().is_empty()); 1109 } 1110 } 1111