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 ] |
141 | pub fn new(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack> { |
142 | unsafe { |
143 | let ptr: *mut EVP_PKEY_CTX = cvt_p(ffi::EVP_PKEY_CTX_new(k:pkey.as_ptr(), e: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 ] |
153 | pub fn new_id(id: Id) -> Result<Self, ErrorStack> { |
154 | unsafe { |
155 | let ptr: *mut EVP_PKEY_CTX = cvt_p(ffi::EVP_PKEY_CTX_new_id(id:id.as_raw(), e: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 ] |
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 ] |
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 ] |
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 ] |
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`]. |
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 ] |
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 ] |
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 ] |
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 ] |
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)] |
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 ] |
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`]. |
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 ] |
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`]. |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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))] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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)] |
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`]. |
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 ] |
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)] |
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)] |
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 ] |
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))] |
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 ] |
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 ] |
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 ] |
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))] |
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))] |
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))] |
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))] |
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 ] |
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 ] |
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 ] |
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)] |
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)] |
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 | |