1 | //! Message signatures. |
2 | //! |
3 | //! The `Signer` allows for the computation of cryptographic signatures of |
4 | //! data given a private key. The `Verifier` can then be used with the |
5 | //! corresponding public key to verify the integrity and authenticity of that |
6 | //! data given the signature. |
7 | //! |
8 | //! # Examples |
9 | //! |
10 | //! Sign and verify data given an RSA keypair: |
11 | //! |
12 | //! ```rust |
13 | //! use openssl::sign::{Signer, Verifier}; |
14 | //! use openssl::rsa::Rsa; |
15 | //! use openssl::pkey::PKey; |
16 | //! use openssl::hash::MessageDigest; |
17 | //! |
18 | //! // Generate a keypair |
19 | //! let keypair = Rsa::generate(2048).unwrap(); |
20 | //! let keypair = PKey::from_rsa(keypair).unwrap(); |
21 | //! |
22 | //! let data = b"hello, world!" ; |
23 | //! let data2 = b"hola, mundo!" ; |
24 | //! |
25 | //! // Sign the data |
26 | //! let mut signer = Signer::new(MessageDigest::sha256(), &keypair).unwrap(); |
27 | //! signer.update(data).unwrap(); |
28 | //! signer.update(data2).unwrap(); |
29 | //! let signature = signer.sign_to_vec().unwrap(); |
30 | //! |
31 | //! // Verify the data |
32 | //! let mut verifier = Verifier::new(MessageDigest::sha256(), &keypair).unwrap(); |
33 | //! verifier.update(data).unwrap(); |
34 | //! verifier.update(data2).unwrap(); |
35 | //! assert!(verifier.verify(&signature).unwrap()); |
36 | //! ``` |
37 | |
38 | #![cfg_attr ( |
39 | not(boringssl), |
40 | doc = r#"\ |
41 | |
42 | Compute an HMAC: |
43 | |
44 | ```rust |
45 | use openssl::hash::MessageDigest; |
46 | use openssl::memcmp; |
47 | use openssl::pkey::PKey; |
48 | use openssl::sign::Signer; |
49 | |
50 | // Create a PKey |
51 | let key = PKey::hmac(b"my secret").unwrap(); |
52 | |
53 | let data = b"hello, world!"; |
54 | let data2 = b"hola, mundo!"; |
55 | |
56 | // Compute the HMAC |
57 | let mut signer = Signer::new(MessageDigest::sha256(), &key).unwrap(); |
58 | signer.update(data).unwrap(); |
59 | signer.update(data2).unwrap(); |
60 | let hmac = signer.sign_to_vec().unwrap(); |
61 | |
62 | // `Verifier` cannot be used with HMACs; use the `memcmp::eq` function instead |
63 | // |
64 | // Do not simply check for equality with `==`! |
65 | # let target = hmac.clone(); |
66 | assert!(memcmp::eq(&hmac, &target)); |
67 | ```"# |
68 | )] |
69 | |
70 | use cfg_if::cfg_if; |
71 | use foreign_types::ForeignTypeRef; |
72 | use libc::c_int; |
73 | use std::io::{self, Write}; |
74 | use std::marker::PhantomData; |
75 | use std::ptr; |
76 | |
77 | use crate::error::ErrorStack; |
78 | use crate::hash::MessageDigest; |
79 | use crate::pkey::{HasPrivate, HasPublic, PKeyRef}; |
80 | use crate::rsa::Padding; |
81 | use crate::{cvt, cvt_p}; |
82 | |
83 | cfg_if! { |
84 | if #[cfg(any(ossl110, libressl382))] { |
85 | use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new}; |
86 | } else { |
87 | use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free}; |
88 | } |
89 | } |
90 | |
91 | /// Salt lengths that must be used with `set_rsa_pss_saltlen`. |
92 | pub struct RsaPssSaltlen(c_int); |
93 | |
94 | impl RsaPssSaltlen { |
95 | /// Returns the integer representation of `RsaPssSaltlen`. |
96 | pub(crate) fn as_raw(&self) -> c_int { |
97 | self.0 |
98 | } |
99 | |
100 | /// Sets the salt length to the given value. |
101 | pub fn custom(val: c_int) -> RsaPssSaltlen { |
102 | RsaPssSaltlen(val) |
103 | } |
104 | |
105 | /// The salt length is set to the digest length. |
106 | /// Corresponds to the special value `-1`. |
107 | pub const DIGEST_LENGTH: RsaPssSaltlen = RsaPssSaltlen(-1); |
108 | /// The salt length is set to the maximum permissible value. |
109 | /// Corresponds to the special value `-2`. |
110 | pub const MAXIMUM_LENGTH: RsaPssSaltlen = RsaPssSaltlen(-2); |
111 | } |
112 | |
113 | /// A type which computes cryptographic signatures of data. |
114 | pub struct Signer<'a> { |
115 | md_ctx: *mut ffi::EVP_MD_CTX, |
116 | pctx: *mut ffi::EVP_PKEY_CTX, |
117 | _p: PhantomData<&'a ()>, |
118 | } |
119 | |
120 | unsafe impl Sync for Signer<'_> {} |
121 | unsafe impl Send for Signer<'_> {} |
122 | |
123 | impl Drop for Signer<'_> { |
124 | fn drop(&mut self) { |
125 | // pkey_ctx is owned by the md_ctx, so no need to explicitly free it. |
126 | unsafe { |
127 | EVP_MD_CTX_free(self.md_ctx); |
128 | } |
129 | } |
130 | } |
131 | |
132 | #[allow (clippy::len_without_is_empty)] |
133 | impl Signer<'_> { |
134 | /// Creates a new `Signer`. |
135 | /// |
136 | /// This cannot be used with Ed25519 or Ed448 keys. Please refer to |
137 | /// `new_without_digest`. |
138 | /// |
139 | /// OpenSSL documentation at [`EVP_DigestSignInit`]. |
140 | /// |
141 | /// [`EVP_DigestSignInit`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestSignInit.html |
142 | pub fn new<'a, T>(type_: MessageDigest, pkey: &PKeyRef<T>) -> Result<Signer<'a>, ErrorStack> |
143 | where |
144 | T: HasPrivate, |
145 | { |
146 | Self::new_intern(Some(type_), pkey) |
147 | } |
148 | |
149 | /// Creates a new `Signer` without a digest. |
150 | /// |
151 | /// This is the only way to create a `Verifier` for Ed25519 or Ed448 keys. |
152 | /// It can also be used to create a CMAC. |
153 | /// |
154 | /// OpenSSL documentation at [`EVP_DigestSignInit`]. |
155 | /// |
156 | /// [`EVP_DigestSignInit`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestSignInit.html |
157 | pub fn new_without_digest<'a, T>(pkey: &PKeyRef<T>) -> Result<Signer<'a>, ErrorStack> |
158 | where |
159 | T: HasPrivate, |
160 | { |
161 | Self::new_intern(None, pkey) |
162 | } |
163 | |
164 | fn new_intern<'a, T>( |
165 | type_: Option<MessageDigest>, |
166 | pkey: &PKeyRef<T>, |
167 | ) -> Result<Signer<'a>, ErrorStack> |
168 | where |
169 | T: HasPrivate, |
170 | { |
171 | unsafe { |
172 | ffi::init(); |
173 | |
174 | let ctx = cvt_p(EVP_MD_CTX_new())?; |
175 | let mut pctx: *mut ffi::EVP_PKEY_CTX = ptr::null_mut(); |
176 | let r = ffi::EVP_DigestSignInit( |
177 | ctx, |
178 | &mut pctx, |
179 | type_.map(|t| t.as_ptr()).unwrap_or(ptr::null()), |
180 | ptr::null_mut(), |
181 | pkey.as_ptr(), |
182 | ); |
183 | if r != 1 { |
184 | EVP_MD_CTX_free(ctx); |
185 | return Err(ErrorStack::get()); |
186 | } |
187 | |
188 | assert!(!pctx.is_null()); |
189 | |
190 | Ok(Signer { |
191 | md_ctx: ctx, |
192 | pctx, |
193 | _p: PhantomData, |
194 | }) |
195 | } |
196 | } |
197 | |
198 | /// Returns the RSA padding mode in use. |
199 | /// |
200 | /// This is only useful for RSA keys. |
201 | /// |
202 | /// This corresponds to `EVP_PKEY_CTX_get_rsa_padding`. |
203 | pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> { |
204 | unsafe { |
205 | let mut pad = 0; |
206 | cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad)) |
207 | .map(|_| Padding::from_raw(pad)) |
208 | } |
209 | } |
210 | |
211 | /// Sets the RSA padding mode. |
212 | /// |
213 | /// This is only useful for RSA keys. |
214 | /// |
215 | /// This corresponds to [`EVP_PKEY_CTX_set_rsa_padding`]. |
216 | /// |
217 | /// [`EVP_PKEY_CTX_set_rsa_padding`]: https://www.openssl.org/docs/manmaster/crypto/EVP_PKEY_CTX_set_rsa_padding.html |
218 | pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> { |
219 | unsafe { |
220 | cvt(ffi::EVP_PKEY_CTX_set_rsa_padding( |
221 | self.pctx, |
222 | padding.as_raw(), |
223 | )) |
224 | .map(|_| ()) |
225 | } |
226 | } |
227 | |
228 | /// Sets the RSA PSS salt length. |
229 | /// |
230 | /// This is only useful for RSA keys. |
231 | /// |
232 | /// This corresponds to [`EVP_PKEY_CTX_set_rsa_pss_saltlen`]. |
233 | /// |
234 | /// [`EVP_PKEY_CTX_set_rsa_pss_saltlen`]: https://www.openssl.org/docs/manmaster/crypto/EVP_PKEY_CTX_set_rsa_pss_saltlen.html |
235 | pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> { |
236 | unsafe { |
237 | cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen( |
238 | self.pctx, |
239 | len.as_raw(), |
240 | )) |
241 | .map(|_| ()) |
242 | } |
243 | } |
244 | |
245 | /// Sets the RSA MGF1 algorithm. |
246 | /// |
247 | /// This is only useful for RSA keys. |
248 | /// |
249 | /// This corresponds to [`EVP_PKEY_CTX_set_rsa_mgf1_md`]. |
250 | /// |
251 | /// [`EVP_PKEY_CTX_set_rsa_mgf1_md`]: https://www.openssl.org/docs/manmaster/man7/RSA-PSS.html |
252 | pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> { |
253 | unsafe { |
254 | cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md( |
255 | self.pctx, |
256 | md.as_ptr() as *mut _, |
257 | )) |
258 | .map(|_| ()) |
259 | } |
260 | } |
261 | |
262 | /// Feeds more data into the `Signer`. |
263 | /// |
264 | /// Please note that PureEdDSA (Ed25519 and Ed448 keys) do not support streaming. |
265 | /// Use `sign_oneshot` instead. |
266 | /// |
267 | /// OpenSSL documentation at [`EVP_DigestUpdate`]. |
268 | /// |
269 | /// [`EVP_DigestUpdate`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestInit.html |
270 | pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> { |
271 | unsafe { |
272 | cvt(ffi::EVP_DigestUpdate( |
273 | self.md_ctx, |
274 | buf.as_ptr() as *const _, |
275 | buf.len(), |
276 | )) |
277 | .map(|_| ()) |
278 | } |
279 | } |
280 | |
281 | /// Computes an upper bound on the signature length. |
282 | /// |
283 | /// The actual signature may be shorter than this value. Check the return value of |
284 | /// `sign` to get the exact length. |
285 | /// |
286 | /// OpenSSL documentation at [`EVP_DigestSignFinal`]. |
287 | /// |
288 | /// [`EVP_DigestSignFinal`]: https://www.openssl.org/docs/manmaster/crypto/EVP_DigestSignFinal.html |
289 | pub fn len(&self) -> Result<usize, ErrorStack> { |
290 | self.len_intern() |
291 | } |
292 | |
293 | #[cfg (all(not(ossl111), not(boringssl), not(libressl370)))] |
294 | fn len_intern(&self) -> Result<usize, ErrorStack> { |
295 | unsafe { |
296 | let mut len = 0; |
297 | cvt(ffi::EVP_DigestSignFinal( |
298 | self.md_ctx, |
299 | ptr::null_mut(), |
300 | &mut len, |
301 | ))?; |
302 | Ok(len) |
303 | } |
304 | } |
305 | |
306 | #[cfg (any(ossl111, boringssl, libressl370))] |
307 | fn len_intern(&self) -> Result<usize, ErrorStack> { |
308 | unsafe { |
309 | let mut len = 0; |
310 | cvt(ffi::EVP_DigestSign( |
311 | self.md_ctx, |
312 | ptr::null_mut(), |
313 | &mut len, |
314 | ptr::null(), |
315 | 0, |
316 | ))?; |
317 | Ok(len) |
318 | } |
319 | } |
320 | |
321 | /// Writes the signature into the provided buffer, returning the number of bytes written. |
322 | /// |
323 | /// This method will fail if the buffer is not large enough for the signature. Use the `len` |
324 | /// method to get an upper bound on the required size. |
325 | /// |
326 | /// OpenSSL documentation at [`EVP_DigestSignFinal`]. |
327 | /// |
328 | /// [`EVP_DigestSignFinal`]: https://www.openssl.org/docs/manmaster/crypto/EVP_DigestSignFinal.html |
329 | pub fn sign(&self, buf: &mut [u8]) -> Result<usize, ErrorStack> { |
330 | unsafe { |
331 | let mut len = buf.len(); |
332 | cvt(ffi::EVP_DigestSignFinal( |
333 | self.md_ctx, |
334 | buf.as_mut_ptr() as *mut _, |
335 | &mut len, |
336 | ))?; |
337 | Ok(len) |
338 | } |
339 | } |
340 | |
341 | /// Returns the signature. |
342 | /// |
343 | /// This is a simple convenience wrapper over `len` and `sign`. |
344 | pub fn sign_to_vec(&self) -> Result<Vec<u8>, ErrorStack> { |
345 | let mut buf = vec![0; self.len()?]; |
346 | let len = self.sign(&mut buf)?; |
347 | // The advertised length is not always equal to the real length for things like DSA |
348 | buf.truncate(len); |
349 | Ok(buf) |
350 | } |
351 | |
352 | /// Signs the data in `data_buf` and writes the signature into the buffer `sig_buf`, returning the |
353 | /// number of bytes written. |
354 | /// |
355 | /// For PureEdDSA (Ed25519 and Ed448 keys), this is the only way to sign data. |
356 | /// |
357 | /// This method will fail if the buffer is not large enough for the signature. Use the `len` |
358 | /// method to get an upper bound on the required size. |
359 | /// |
360 | /// OpenSSL documentation at [`EVP_DigestSign`]. |
361 | /// |
362 | /// [`EVP_DigestSign`]: https://www.openssl.org/docs/man1.1.1/man3/EVP_DigestSign.html |
363 | #[cfg (any(ossl111, boringssl, libressl370))] |
364 | pub fn sign_oneshot( |
365 | &mut self, |
366 | sig_buf: &mut [u8], |
367 | data_buf: &[u8], |
368 | ) -> Result<usize, ErrorStack> { |
369 | unsafe { |
370 | let mut sig_len = sig_buf.len(); |
371 | cvt(ffi::EVP_DigestSign( |
372 | self.md_ctx, |
373 | sig_buf.as_mut_ptr() as *mut _, |
374 | &mut sig_len, |
375 | data_buf.as_ptr() as *const _, |
376 | data_buf.len(), |
377 | ))?; |
378 | Ok(sig_len) |
379 | } |
380 | } |
381 | |
382 | /// Returns the signature. |
383 | /// |
384 | /// This is a simple convenience wrapper over `len` and `sign_oneshot`. |
385 | #[cfg (any(ossl111, boringssl, libressl370))] |
386 | pub fn sign_oneshot_to_vec(&mut self, data_buf: &[u8]) -> Result<Vec<u8>, ErrorStack> { |
387 | let mut sig_buf = vec![0; self.len()?]; |
388 | let len = self.sign_oneshot(&mut sig_buf, data_buf)?; |
389 | // The advertised length is not always equal to the real length for things like DSA |
390 | sig_buf.truncate(len); |
391 | Ok(sig_buf) |
392 | } |
393 | } |
394 | |
395 | impl<'a> Write for Signer<'a> { |
396 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
397 | self.update(buf)?; |
398 | Ok(buf.len()) |
399 | } |
400 | |
401 | fn flush(&mut self) -> io::Result<()> { |
402 | Ok(()) |
403 | } |
404 | } |
405 | |
406 | /// A type which can be used to verify the integrity and authenticity |
407 | /// of data given the signature. |
408 | pub struct Verifier<'a> { |
409 | md_ctx: *mut ffi::EVP_MD_CTX, |
410 | pctx: *mut ffi::EVP_PKEY_CTX, |
411 | pkey_pd: PhantomData<&'a ()>, |
412 | } |
413 | |
414 | unsafe impl<'a> Sync for Verifier<'a> {} |
415 | unsafe impl<'a> Send for Verifier<'a> {} |
416 | |
417 | impl<'a> Drop for Verifier<'a> { |
418 | fn drop(&mut self) { |
419 | // pkey_ctx is owned by the md_ctx, so no need to explicitly free it. |
420 | unsafe { |
421 | EVP_MD_CTX_free(self.md_ctx); |
422 | } |
423 | } |
424 | } |
425 | |
426 | /// A type which verifies cryptographic signatures of data. |
427 | impl<'a> Verifier<'a> { |
428 | /// Creates a new `Verifier`. |
429 | /// |
430 | /// This cannot be used with Ed25519 or Ed448 keys. Please refer to |
431 | /// [`Verifier::new_without_digest`]. |
432 | /// |
433 | /// OpenSSL documentation at [`EVP_DigestVerifyInit`]. |
434 | /// |
435 | /// [`EVP_DigestVerifyInit`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestVerifyInit.html |
436 | pub fn new<T>(type_: MessageDigest, pkey: &'a PKeyRef<T>) -> Result<Verifier<'a>, ErrorStack> |
437 | where |
438 | T: HasPublic, |
439 | { |
440 | Verifier::new_intern(Some(type_), pkey) |
441 | } |
442 | |
443 | /// Creates a new `Verifier` without a digest. |
444 | /// |
445 | /// This is the only way to create a `Verifier` for Ed25519 or Ed448 keys. |
446 | /// |
447 | /// OpenSSL documentation at [`EVP_DigestVerifyInit`]. |
448 | /// |
449 | /// [`EVP_DigestVerifyInit`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestVerifyInit.html |
450 | pub fn new_without_digest<T>(pkey: &'a PKeyRef<T>) -> Result<Verifier<'a>, ErrorStack> |
451 | where |
452 | T: HasPublic, |
453 | { |
454 | Verifier::new_intern(None, pkey) |
455 | } |
456 | |
457 | fn new_intern<T>( |
458 | type_: Option<MessageDigest>, |
459 | pkey: &'a PKeyRef<T>, |
460 | ) -> Result<Verifier<'a>, ErrorStack> |
461 | where |
462 | T: HasPublic, |
463 | { |
464 | unsafe { |
465 | ffi::init(); |
466 | |
467 | let ctx = cvt_p(EVP_MD_CTX_new())?; |
468 | let mut pctx: *mut ffi::EVP_PKEY_CTX = ptr::null_mut(); |
469 | let r = ffi::EVP_DigestVerifyInit( |
470 | ctx, |
471 | &mut pctx, |
472 | type_.map(|t| t.as_ptr()).unwrap_or(ptr::null()), |
473 | ptr::null_mut(), |
474 | pkey.as_ptr(), |
475 | ); |
476 | if r != 1 { |
477 | EVP_MD_CTX_free(ctx); |
478 | return Err(ErrorStack::get()); |
479 | } |
480 | |
481 | assert!(!pctx.is_null()); |
482 | |
483 | Ok(Verifier { |
484 | md_ctx: ctx, |
485 | pctx, |
486 | pkey_pd: PhantomData, |
487 | }) |
488 | } |
489 | } |
490 | |
491 | /// Returns the RSA padding mode in use. |
492 | /// |
493 | /// This is only useful for RSA keys. |
494 | /// |
495 | /// This corresponds to `EVP_PKEY_CTX_get_rsa_padding`. |
496 | pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> { |
497 | unsafe { |
498 | let mut pad = 0; |
499 | cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad)) |
500 | .map(|_| Padding::from_raw(pad)) |
501 | } |
502 | } |
503 | |
504 | /// Sets the RSA padding mode. |
505 | /// |
506 | /// This is only useful for RSA keys. |
507 | /// |
508 | /// This corresponds to [`EVP_PKEY_CTX_set_rsa_padding`]. |
509 | /// |
510 | /// [`EVP_PKEY_CTX_set_rsa_padding`]: https://www.openssl.org/docs/manmaster/crypto/EVP_PKEY_CTX_set_rsa_padding.html |
511 | pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> { |
512 | unsafe { |
513 | cvt(ffi::EVP_PKEY_CTX_set_rsa_padding( |
514 | self.pctx, |
515 | padding.as_raw(), |
516 | )) |
517 | .map(|_| ()) |
518 | } |
519 | } |
520 | |
521 | /// Sets the RSA PSS salt length. |
522 | /// |
523 | /// This is only useful for RSA keys. |
524 | /// |
525 | /// This corresponds to [`EVP_PKEY_CTX_set_rsa_pss_saltlen`]. |
526 | /// |
527 | /// [`EVP_PKEY_CTX_set_rsa_pss_saltlen`]: https://www.openssl.org/docs/manmaster/crypto/EVP_PKEY_CTX_set_rsa_pss_saltlen.html |
528 | pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> { |
529 | unsafe { |
530 | cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen( |
531 | self.pctx, |
532 | len.as_raw(), |
533 | )) |
534 | .map(|_| ()) |
535 | } |
536 | } |
537 | |
538 | /// Sets the RSA MGF1 algorithm. |
539 | /// |
540 | /// This is only useful for RSA keys. |
541 | /// |
542 | /// This corresponds to [`EVP_PKEY_CTX_set_rsa_mgf1_md`]. |
543 | /// |
544 | /// [`EVP_PKEY_CTX_set_rsa_mgf1_md`]: https://www.openssl.org/docs/manmaster/man7/RSA-PSS.html |
545 | pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> { |
546 | unsafe { |
547 | cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md( |
548 | self.pctx, |
549 | md.as_ptr() as *mut _, |
550 | )) |
551 | .map(|_| ()) |
552 | } |
553 | } |
554 | |
555 | /// Feeds more data into the `Verifier`. |
556 | /// |
557 | /// Please note that PureEdDSA (Ed25519 and Ed448 keys) do not support streaming. |
558 | /// Use [`Verifier::verify_oneshot`] instead. |
559 | /// |
560 | /// OpenSSL documentation at [`EVP_DigestUpdate`]. |
561 | /// |
562 | /// [`EVP_DigestUpdate`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestInit.html |
563 | pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> { |
564 | unsafe { |
565 | cvt(ffi::EVP_DigestUpdate( |
566 | self.md_ctx, |
567 | buf.as_ptr() as *const _, |
568 | buf.len(), |
569 | )) |
570 | .map(|_| ()) |
571 | } |
572 | } |
573 | |
574 | /// Determines if the data fed into the `Verifier` matches the provided signature. |
575 | /// |
576 | /// OpenSSL documentation at [`EVP_DigestVerifyFinal`]. |
577 | /// |
578 | /// [`EVP_DigestVerifyFinal`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestVerifyFinal.html |
579 | pub fn verify(&self, signature: &[u8]) -> Result<bool, ErrorStack> { |
580 | unsafe { |
581 | let r = |
582 | EVP_DigestVerifyFinal(self.md_ctx, signature.as_ptr() as *mut _, signature.len()); |
583 | match r { |
584 | 1 => Ok(true), |
585 | 0 => { |
586 | ErrorStack::get(); // discard error stack |
587 | Ok(false) |
588 | } |
589 | _ => Err(ErrorStack::get()), |
590 | } |
591 | } |
592 | } |
593 | |
594 | /// Determines if the data given in `buf` matches the provided signature. |
595 | /// |
596 | /// OpenSSL documentation at [`EVP_DigestVerify`]. |
597 | /// |
598 | /// [`EVP_DigestVerify`]: https://www.openssl.org/docs/man1.1.1/man3/EVP_DigestVerify.html |
599 | #[cfg (any(ossl111, boringssl, libressl370))] |
600 | pub fn verify_oneshot(&mut self, signature: &[u8], buf: &[u8]) -> Result<bool, ErrorStack> { |
601 | unsafe { |
602 | let r = ffi::EVP_DigestVerify( |
603 | self.md_ctx, |
604 | signature.as_ptr() as *const _, |
605 | signature.len(), |
606 | buf.as_ptr() as *const _, |
607 | buf.len(), |
608 | ); |
609 | match r { |
610 | 1 => Ok(true), |
611 | 0 => { |
612 | ErrorStack::get(); |
613 | Ok(false) |
614 | } |
615 | _ => Err(ErrorStack::get()), |
616 | } |
617 | } |
618 | } |
619 | } |
620 | |
621 | impl<'a> Write for Verifier<'a> { |
622 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
623 | self.update(buf)?; |
624 | Ok(buf.len()) |
625 | } |
626 | |
627 | fn flush(&mut self) -> io::Result<()> { |
628 | Ok(()) |
629 | } |
630 | } |
631 | |
632 | #[cfg (not(ossl101))] |
633 | use ffi::EVP_DigestVerifyFinal; |
634 | |
635 | #[cfg (ossl101)] |
636 | #[allow (bad_style)] |
637 | unsafe fn EVP_DigestVerifyFinal( |
638 | ctx: *mut ffi::EVP_MD_CTX, |
639 | sigret: *const ::libc::c_uchar, |
640 | siglen: ::libc::size_t, |
641 | ) -> ::libc::c_int { |
642 | ffi::EVP_DigestVerifyFinal(ctx, sigret as *mut _, siglen) |
643 | } |
644 | |
645 | #[cfg (test)] |
646 | mod test { |
647 | use hex::{self, FromHex}; |
648 | #[cfg (not(boringssl))] |
649 | use std::iter; |
650 | |
651 | use crate::ec::{EcGroup, EcKey}; |
652 | use crate::hash::MessageDigest; |
653 | use crate::nid::Nid; |
654 | use crate::pkey::PKey; |
655 | use crate::rsa::{Padding, Rsa}; |
656 | #[cfg (ossl111)] |
657 | use crate::sign::RsaPssSaltlen; |
658 | use crate::sign::{Signer, Verifier}; |
659 | |
660 | const INPUT: &str = |
661 | "65794a68624763694f694a53557a49314e694a392e65794a7063334d694f694a71623255694c41304b49434a6c\ |
662 | 654841694f6a457a4d4441344d546b7a4f44417344516f67496d6830644841364c79396c654746746347786c4c\ |
663 | 6d4e76625339706331397962323930496a7030636e566c6651" ; |
664 | |
665 | const SIGNATURE: &str = |
666 | "702e218943e88fd11eb5d82dbf7845f34106ae1b81fff7731116add1717d83656d420afd3c96eedd73a2663e51\ |
667 | 66687b000b87226e0187ed1073f945e582adfcef16d85a798ee8c66ddb3db8975b17d09402beedd5d9d9700710\ |
668 | 8db28160d5f8040ca7445762b81fbe7ff9d92e0ae76f24f25b33bbe6f44ae61eb1040acb20044d3ef9128ed401\ |
669 | 30795bd4bd3b41eecad066ab651981fde48df77f372dc38b9fafdd3befb18b5da3cc3c2eb02f9e3a41d612caad\ |
670 | 15911273a05f23b9e838faaf849d698429ef5a1e88798236c3d40e604522a544c8f27a7a2db80663d16cf7caea\ |
671 | 56de405cb2215a45b2c25566b55ac1a748a070dfc8a32a469543d019eefb47" ; |
672 | |
673 | #[test ] |
674 | fn rsa_sign() { |
675 | let key = include_bytes!("../test/rsa.pem" ); |
676 | let private_key = Rsa::private_key_from_pem(key).unwrap(); |
677 | let pkey = PKey::from_rsa(private_key).unwrap(); |
678 | |
679 | let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap(); |
680 | assert_eq!(signer.rsa_padding().unwrap(), Padding::PKCS1); |
681 | signer.set_rsa_padding(Padding::PKCS1).unwrap(); |
682 | signer.update(&Vec::from_hex(INPUT).unwrap()).unwrap(); |
683 | let result = signer.sign_to_vec().unwrap(); |
684 | |
685 | assert_eq!(hex::encode(result), SIGNATURE); |
686 | } |
687 | |
688 | #[test ] |
689 | fn rsa_verify_ok() { |
690 | let key = include_bytes!("../test/rsa.pem" ); |
691 | let private_key = Rsa::private_key_from_pem(key).unwrap(); |
692 | let pkey = PKey::from_rsa(private_key).unwrap(); |
693 | |
694 | let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap(); |
695 | assert_eq!(verifier.rsa_padding().unwrap(), Padding::PKCS1); |
696 | verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap(); |
697 | assert!(verifier.verify(&Vec::from_hex(SIGNATURE).unwrap()).unwrap()); |
698 | } |
699 | |
700 | #[test ] |
701 | fn rsa_verify_invalid() { |
702 | let key = include_bytes!("../test/rsa.pem" ); |
703 | let private_key = Rsa::private_key_from_pem(key).unwrap(); |
704 | let pkey = PKey::from_rsa(private_key).unwrap(); |
705 | |
706 | let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap(); |
707 | verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap(); |
708 | verifier.update(b"foobar" ).unwrap(); |
709 | assert!(!verifier.verify(&Vec::from_hex(SIGNATURE).unwrap()).unwrap()); |
710 | } |
711 | |
712 | #[cfg (not(boringssl))] |
713 | fn test_hmac(ty: MessageDigest, tests: &[(Vec<u8>, Vec<u8>, Vec<u8>)]) { |
714 | for (key, data, res) in tests.iter() { |
715 | let pkey = PKey::hmac(key).unwrap(); |
716 | let mut signer = Signer::new(ty, &pkey).unwrap(); |
717 | signer.update(data).unwrap(); |
718 | assert_eq!(signer.sign_to_vec().unwrap(), *res); |
719 | } |
720 | } |
721 | |
722 | #[test ] |
723 | #[cfg (not(boringssl))] |
724 | fn hmac_md5() { |
725 | // test vectors from RFC 2202 |
726 | let tests: [(Vec<u8>, Vec<u8>, Vec<u8>); 7] = [ |
727 | ( |
728 | iter::repeat(0x0b_u8).take(16).collect(), |
729 | b"Hi There" .to_vec(), |
730 | Vec::from_hex("9294727a3638bb1c13f48ef8158bfc9d" ).unwrap(), |
731 | ), |
732 | ( |
733 | b"Jefe" .to_vec(), |
734 | b"what do ya want for nothing?" .to_vec(), |
735 | Vec::from_hex("750c783e6ab0b503eaa86e310a5db738" ).unwrap(), |
736 | ), |
737 | ( |
738 | iter::repeat(0xaa_u8).take(16).collect(), |
739 | iter::repeat(0xdd_u8).take(50).collect(), |
740 | Vec::from_hex("56be34521d144c88dbb8c733f0e8b3f6" ).unwrap(), |
741 | ), |
742 | ( |
743 | Vec::from_hex("0102030405060708090a0b0c0d0e0f10111213141516171819" ).unwrap(), |
744 | iter::repeat(0xcd_u8).take(50).collect(), |
745 | Vec::from_hex("697eaf0aca3a3aea3a75164746ffaa79" ).unwrap(), |
746 | ), |
747 | ( |
748 | iter::repeat(0x0c_u8).take(16).collect(), |
749 | b"Test With Truncation" .to_vec(), |
750 | Vec::from_hex("56461ef2342edc00f9bab995690efd4c" ).unwrap(), |
751 | ), |
752 | ( |
753 | iter::repeat(0xaa_u8).take(80).collect(), |
754 | b"Test Using Larger Than Block-Size Key - Hash Key First" .to_vec(), |
755 | Vec::from_hex("6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd" ).unwrap(), |
756 | ), |
757 | ( |
758 | iter::repeat(0xaa_u8).take(80).collect(), |
759 | b"Test Using Larger Than Block-Size Key \ |
760 | and Larger Than One Block-Size Data" |
761 | .to_vec(), |
762 | Vec::from_hex("6f630fad67cda0ee1fb1f562db3aa53e" ).unwrap(), |
763 | ), |
764 | ]; |
765 | |
766 | test_hmac(MessageDigest::md5(), &tests); |
767 | } |
768 | |
769 | #[test ] |
770 | #[cfg (not(boringssl))] |
771 | fn hmac_sha1() { |
772 | // test vectors from RFC 2202 |
773 | let tests: [(Vec<u8>, Vec<u8>, Vec<u8>); 7] = [ |
774 | ( |
775 | iter::repeat(0x0b_u8).take(20).collect(), |
776 | b"Hi There" .to_vec(), |
777 | Vec::from_hex("b617318655057264e28bc0b6fb378c8ef146be00" ).unwrap(), |
778 | ), |
779 | ( |
780 | b"Jefe" .to_vec(), |
781 | b"what do ya want for nothing?" .to_vec(), |
782 | Vec::from_hex("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79" ).unwrap(), |
783 | ), |
784 | ( |
785 | iter::repeat(0xaa_u8).take(20).collect(), |
786 | iter::repeat(0xdd_u8).take(50).collect(), |
787 | Vec::from_hex("125d7342b9ac11cd91a39af48aa17b4f63f175d3" ).unwrap(), |
788 | ), |
789 | ( |
790 | Vec::from_hex("0102030405060708090a0b0c0d0e0f10111213141516171819" ).unwrap(), |
791 | iter::repeat(0xcd_u8).take(50).collect(), |
792 | Vec::from_hex("4c9007f4026250c6bc8414f9bf50c86c2d7235da" ).unwrap(), |
793 | ), |
794 | ( |
795 | iter::repeat(0x0c_u8).take(20).collect(), |
796 | b"Test With Truncation" .to_vec(), |
797 | Vec::from_hex("4c1a03424b55e07fe7f27be1d58bb9324a9a5a04" ).unwrap(), |
798 | ), |
799 | ( |
800 | iter::repeat(0xaa_u8).take(80).collect(), |
801 | b"Test Using Larger Than Block-Size Key - Hash Key First" .to_vec(), |
802 | Vec::from_hex("aa4ae5e15272d00e95705637ce8a3b55ed402112" ).unwrap(), |
803 | ), |
804 | ( |
805 | iter::repeat(0xaa_u8).take(80).collect(), |
806 | b"Test Using Larger Than Block-Size Key \ |
807 | and Larger Than One Block-Size Data" |
808 | .to_vec(), |
809 | Vec::from_hex("e8e99d0f45237d786d6bbaa7965c7808bbff1a91" ).unwrap(), |
810 | ), |
811 | ]; |
812 | |
813 | test_hmac(MessageDigest::sha1(), &tests); |
814 | } |
815 | |
816 | #[test ] |
817 | #[cfg (ossl110)] |
818 | fn test_cmac() { |
819 | let cipher = crate::symm::Cipher::aes_128_cbc(); |
820 | let key = Vec::from_hex("9294727a3638bb1c13f48ef8158bfc9d" ).unwrap(); |
821 | let pkey = PKey::cmac(&cipher, &key).unwrap(); |
822 | let mut signer = Signer::new_without_digest(&pkey).unwrap(); |
823 | |
824 | let data = b"Hi There" ; |
825 | signer.update(data as &[u8]).unwrap(); |
826 | |
827 | let expected = vec![ |
828 | 136, 101, 61, 167, 61, 30, 248, 234, 124, 166, 196, 157, 203, 52, 171, 19, |
829 | ]; |
830 | assert_eq!(signer.sign_to_vec().unwrap(), expected); |
831 | } |
832 | |
833 | #[test ] |
834 | fn ec() { |
835 | let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); |
836 | let key = EcKey::generate(&group).unwrap(); |
837 | let key = PKey::from_ec_key(key).unwrap(); |
838 | |
839 | let mut signer = Signer::new(MessageDigest::sha256(), &key).unwrap(); |
840 | signer.update(b"hello world" ).unwrap(); |
841 | let signature = signer.sign_to_vec().unwrap(); |
842 | |
843 | let mut verifier = Verifier::new(MessageDigest::sha256(), &key).unwrap(); |
844 | verifier.update(b"hello world" ).unwrap(); |
845 | assert!(verifier.verify(&signature).unwrap()); |
846 | } |
847 | |
848 | #[test ] |
849 | #[cfg (any(ossl111, boringssl, libressl370))] |
850 | fn eddsa() { |
851 | let key = PKey::generate_ed25519().unwrap(); |
852 | |
853 | let mut signer = Signer::new_without_digest(&key).unwrap(); |
854 | let signature = signer.sign_oneshot_to_vec(b"hello world" ).unwrap(); |
855 | |
856 | let mut verifier = Verifier::new_without_digest(&key).unwrap(); |
857 | assert!(verifier.verify_oneshot(&signature, b"hello world" ).unwrap()); |
858 | } |
859 | |
860 | #[test ] |
861 | #[cfg (ossl111)] |
862 | fn rsa_sign_verify() { |
863 | let key = include_bytes!("../test/rsa.pem" ); |
864 | let private_key = Rsa::private_key_from_pem(key).unwrap(); |
865 | let pkey = PKey::from_rsa(private_key).unwrap(); |
866 | |
867 | let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap(); |
868 | signer.set_rsa_padding(Padding::PKCS1_PSS).unwrap(); |
869 | assert_eq!(signer.rsa_padding().unwrap(), Padding::PKCS1_PSS); |
870 | signer |
871 | .set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH) |
872 | .unwrap(); |
873 | signer.set_rsa_mgf1_md(MessageDigest::sha256()).unwrap(); |
874 | signer.update(&Vec::from_hex(INPUT).unwrap()).unwrap(); |
875 | let signature = signer.sign_to_vec().unwrap(); |
876 | |
877 | let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap(); |
878 | verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap(); |
879 | verifier |
880 | .set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH) |
881 | .unwrap(); |
882 | verifier.set_rsa_mgf1_md(MessageDigest::sha256()).unwrap(); |
883 | verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap(); |
884 | assert!(verifier.verify(&signature).unwrap()); |
885 | } |
886 | } |
887 | |