/rust/registry/src/index.crates.io-1949cf8c6b5b557f/openssl-0.10.62/src/sign.rs
Line | Count | Source |
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 | 0 | pub(crate) fn as_raw(&self) -> c_int { |
97 | 0 | self.0 |
98 | 0 | } |
99 | | |
100 | | /// Sets the salt length to the given value. |
101 | 0 | pub fn custom(val: c_int) -> RsaPssSaltlen { |
102 | 0 | RsaPssSaltlen(val) |
103 | 0 | } |
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 | 0 | fn drop(&mut self) { |
125 | | // pkey_ctx is owned by the md_ctx, so no need to explicitly free it. |
126 | 0 | unsafe { |
127 | 0 | EVP_MD_CTX_free(self.md_ctx); |
128 | 0 | } |
129 | 0 | } |
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 | 0 | pub fn new<'a, T>(type_: MessageDigest, pkey: &PKeyRef<T>) -> Result<Signer<'a>, ErrorStack> |
143 | 0 | where |
144 | 0 | T: HasPrivate, |
145 | | { |
146 | 0 | Self::new_intern(Some(type_), pkey) |
147 | 0 | } |
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 | 0 | pub fn new_without_digest<'a, T>(pkey: &PKeyRef<T>) -> Result<Signer<'a>, ErrorStack> |
158 | 0 | where |
159 | 0 | T: HasPrivate, |
160 | | { |
161 | 0 | Self::new_intern(None, pkey) |
162 | 0 | } |
163 | | |
164 | 0 | fn new_intern<'a, T>( |
165 | 0 | type_: Option<MessageDigest>, |
166 | 0 | pkey: &PKeyRef<T>, |
167 | 0 | ) -> Result<Signer<'a>, ErrorStack> |
168 | 0 | where |
169 | 0 | T: HasPrivate, |
170 | | { |
171 | | unsafe { |
172 | 0 | ffi::init(); |
173 | | |
174 | 0 | let ctx = cvt_p(EVP_MD_CTX_new())?; |
175 | 0 | let mut pctx: *mut ffi::EVP_PKEY_CTX = ptr::null_mut(); |
176 | 0 | let r = ffi::EVP_DigestSignInit( |
177 | 0 | ctx, |
178 | 0 | &mut pctx, |
179 | 0 | type_.map(|t| t.as_ptr()).unwrap_or(ptr::null()), |
180 | 0 | ptr::null_mut(), |
181 | 0 | pkey.as_ptr(), |
182 | | ); |
183 | 0 | if r != 1 { |
184 | 0 | EVP_MD_CTX_free(ctx); |
185 | 0 | return Err(ErrorStack::get()); |
186 | 0 | } |
187 | | |
188 | 0 | assert!(!pctx.is_null()); |
189 | | |
190 | 0 | Ok(Signer { |
191 | 0 | md_ctx: ctx, |
192 | 0 | pctx, |
193 | 0 | _p: PhantomData, |
194 | 0 | }) |
195 | | } |
196 | 0 | } |
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 | 0 | pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> { |
204 | | unsafe { |
205 | 0 | let mut pad = 0; |
206 | 0 | cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad)) |
207 | 0 | .map(|_| Padding::from_raw(pad)) |
208 | | } |
209 | 0 | } |
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 | 0 | pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> { |
219 | | unsafe { |
220 | 0 | cvt(ffi::EVP_PKEY_CTX_set_rsa_padding( |
221 | 0 | self.pctx, |
222 | 0 | padding.as_raw(), |
223 | | )) |
224 | 0 | .map(|_| ()) |
225 | | } |
226 | 0 | } |
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 | 0 | pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> { |
236 | | unsafe { |
237 | 0 | cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen( |
238 | 0 | self.pctx, |
239 | 0 | len.as_raw(), |
240 | | )) |
241 | 0 | .map(|_| ()) |
242 | | } |
243 | 0 | } |
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 | 0 | pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> { |
253 | | unsafe { |
254 | 0 | cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md( |
255 | 0 | self.pctx, |
256 | 0 | md.as_ptr() as *mut _, |
257 | | )) |
258 | 0 | .map(|_| ()) |
259 | | } |
260 | 0 | } |
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 | 0 | pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> { |
271 | | unsafe { |
272 | 0 | cvt(ffi::EVP_DigestUpdate( |
273 | 0 | self.md_ctx, |
274 | 0 | buf.as_ptr() as *const _, |
275 | 0 | buf.len(), |
276 | | )) |
277 | 0 | .map(|_| ()) |
278 | | } |
279 | 0 | } |
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 | 0 | pub fn len(&self) -> Result<usize, ErrorStack> { |
290 | 0 | self.len_intern() |
291 | 0 | } |
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 | 0 | fn len_intern(&self) -> Result<usize, ErrorStack> { |
308 | | unsafe { |
309 | 0 | let mut len = 0; |
310 | 0 | cvt(ffi::EVP_DigestSign( |
311 | 0 | self.md_ctx, |
312 | 0 | ptr::null_mut(), |
313 | 0 | &mut len, |
314 | 0 | ptr::null(), |
315 | | 0, |
316 | 0 | ))?; |
317 | 0 | Ok(len) |
318 | | } |
319 | 0 | } |
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 | 0 | pub fn sign(&self, buf: &mut [u8]) -> Result<usize, ErrorStack> { |
330 | | unsafe { |
331 | 0 | let mut len = buf.len(); |
332 | 0 | cvt(ffi::EVP_DigestSignFinal( |
333 | 0 | self.md_ctx, |
334 | 0 | buf.as_mut_ptr() as *mut _, |
335 | 0 | &mut len, |
336 | 0 | ))?; |
337 | 0 | Ok(len) |
338 | | } |
339 | 0 | } |
340 | | |
341 | | /// Returns the signature. |
342 | | /// |
343 | | /// This is a simple convenience wrapper over `len` and `sign`. |
344 | 0 | pub fn sign_to_vec(&self) -> Result<Vec<u8>, ErrorStack> { |
345 | 0 | let mut buf = vec![0; self.len()?]; |
346 | 0 | let len = self.sign(&mut buf)?; |
347 | | // The advertised length is not always equal to the real length for things like DSA |
348 | 0 | buf.truncate(len); |
349 | 0 | Ok(buf) |
350 | 0 | } |
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 | 0 | pub fn sign_oneshot( |
365 | 0 | &mut self, |
366 | 0 | sig_buf: &mut [u8], |
367 | 0 | data_buf: &[u8], |
368 | 0 | ) -> Result<usize, ErrorStack> { |
369 | | unsafe { |
370 | 0 | let mut sig_len = sig_buf.len(); |
371 | 0 | cvt(ffi::EVP_DigestSign( |
372 | 0 | self.md_ctx, |
373 | 0 | sig_buf.as_mut_ptr() as *mut _, |
374 | 0 | &mut sig_len, |
375 | 0 | data_buf.as_ptr() as *const _, |
376 | 0 | data_buf.len(), |
377 | 0 | ))?; |
378 | 0 | Ok(sig_len) |
379 | | } |
380 | 0 | } |
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 | 0 | pub fn sign_oneshot_to_vec(&mut self, data_buf: &[u8]) -> Result<Vec<u8>, ErrorStack> { |
387 | 0 | let mut sig_buf = vec![0; self.len()?]; |
388 | 0 | 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 | 0 | sig_buf.truncate(len); |
391 | 0 | Ok(sig_buf) |
392 | 0 | } |
393 | | } |
394 | | |
395 | | impl<'a> Write for Signer<'a> { |
396 | 0 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
397 | 0 | self.update(buf)?; |
398 | 0 | Ok(buf.len()) |
399 | 0 | } |
400 | | |
401 | 0 | fn flush(&mut self) -> io::Result<()> { |
402 | 0 | Ok(()) |
403 | 0 | } |
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 | 0 | fn drop(&mut self) { |
419 | | // pkey_ctx is owned by the md_ctx, so no need to explicitly free it. |
420 | 0 | unsafe { |
421 | 0 | EVP_MD_CTX_free(self.md_ctx); |
422 | 0 | } |
423 | 0 | } |
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 | 0 | pub fn new<T>(type_: MessageDigest, pkey: &'a PKeyRef<T>) -> Result<Verifier<'a>, ErrorStack> |
437 | 0 | where |
438 | 0 | T: HasPublic, |
439 | | { |
440 | 0 | Verifier::new_intern(Some(type_), pkey) |
441 | 0 | } |
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 | 0 | pub fn new_without_digest<T>(pkey: &'a PKeyRef<T>) -> Result<Verifier<'a>, ErrorStack> |
451 | 0 | where |
452 | 0 | T: HasPublic, |
453 | | { |
454 | 0 | Verifier::new_intern(None, pkey) |
455 | 0 | } |
456 | | |
457 | 0 | fn new_intern<T>( |
458 | 0 | type_: Option<MessageDigest>, |
459 | 0 | pkey: &'a PKeyRef<T>, |
460 | 0 | ) -> Result<Verifier<'a>, ErrorStack> |
461 | 0 | where |
462 | 0 | T: HasPublic, |
463 | | { |
464 | | unsafe { |
465 | 0 | ffi::init(); |
466 | | |
467 | 0 | let ctx = cvt_p(EVP_MD_CTX_new())?; |
468 | 0 | let mut pctx: *mut ffi::EVP_PKEY_CTX = ptr::null_mut(); |
469 | 0 | let r = ffi::EVP_DigestVerifyInit( |
470 | 0 | ctx, |
471 | 0 | &mut pctx, |
472 | 0 | type_.map(|t| t.as_ptr()).unwrap_or(ptr::null()), |
473 | 0 | ptr::null_mut(), |
474 | 0 | pkey.as_ptr(), |
475 | | ); |
476 | 0 | if r != 1 { |
477 | 0 | EVP_MD_CTX_free(ctx); |
478 | 0 | return Err(ErrorStack::get()); |
479 | 0 | } |
480 | | |
481 | 0 | assert!(!pctx.is_null()); |
482 | | |
483 | 0 | Ok(Verifier { |
484 | 0 | md_ctx: ctx, |
485 | 0 | pctx, |
486 | 0 | pkey_pd: PhantomData, |
487 | 0 | }) |
488 | | } |
489 | 0 | } |
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 | 0 | pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> { |
497 | | unsafe { |
498 | 0 | let mut pad = 0; |
499 | 0 | cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad)) |
500 | 0 | .map(|_| Padding::from_raw(pad)) |
501 | | } |
502 | 0 | } |
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 | 0 | pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> { |
512 | | unsafe { |
513 | 0 | cvt(ffi::EVP_PKEY_CTX_set_rsa_padding( |
514 | 0 | self.pctx, |
515 | 0 | padding.as_raw(), |
516 | | )) |
517 | 0 | .map(|_| ()) |
518 | | } |
519 | 0 | } |
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 | 0 | pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> { |
529 | | unsafe { |
530 | 0 | cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen( |
531 | 0 | self.pctx, |
532 | 0 | len.as_raw(), |
533 | | )) |
534 | 0 | .map(|_| ()) |
535 | | } |
536 | 0 | } |
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 | 0 | pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> { |
546 | | unsafe { |
547 | 0 | cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md( |
548 | 0 | self.pctx, |
549 | 0 | md.as_ptr() as *mut _, |
550 | | )) |
551 | 0 | .map(|_| ()) |
552 | | } |
553 | 0 | } |
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 | 0 | pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> { |
564 | | unsafe { |
565 | 0 | cvt(ffi::EVP_DigestUpdate( |
566 | 0 | self.md_ctx, |
567 | 0 | buf.as_ptr() as *const _, |
568 | 0 | buf.len(), |
569 | | )) |
570 | 0 | .map(|_| ()) |
571 | | } |
572 | 0 | } |
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 | 0 | pub fn verify(&self, signature: &[u8]) -> Result<bool, ErrorStack> { |
580 | | unsafe { |
581 | 0 | let r = |
582 | 0 | EVP_DigestVerifyFinal(self.md_ctx, signature.as_ptr() as *mut _, signature.len()); |
583 | 0 | match r { |
584 | 0 | 1 => Ok(true), |
585 | | 0 => { |
586 | 0 | ErrorStack::get(); // discard error stack |
587 | 0 | Ok(false) |
588 | | } |
589 | 0 | _ => Err(ErrorStack::get()), |
590 | | } |
591 | | } |
592 | 0 | } |
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 | 0 | pub fn verify_oneshot(&mut self, signature: &[u8], buf: &[u8]) -> Result<bool, ErrorStack> { |
601 | | unsafe { |
602 | 0 | let r = ffi::EVP_DigestVerify( |
603 | 0 | self.md_ctx, |
604 | 0 | signature.as_ptr() as *const _, |
605 | 0 | signature.len(), |
606 | 0 | buf.as_ptr() as *const _, |
607 | 0 | buf.len(), |
608 | | ); |
609 | 0 | match r { |
610 | 0 | 1 => Ok(true), |
611 | | 0 => { |
612 | 0 | ErrorStack::get(); |
613 | 0 | Ok(false) |
614 | | } |
615 | 0 | _ => Err(ErrorStack::get()), |
616 | | } |
617 | | } |
618 | 0 | } |
619 | | } |
620 | | |
621 | | impl<'a> Write for Verifier<'a> { |
622 | 0 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
623 | 0 | self.update(buf)?; |
624 | 0 | Ok(buf.len()) |
625 | 0 | } |
626 | | |
627 | 0 | fn flush(&mut self) -> io::Result<()> { |
628 | 0 | Ok(()) |
629 | 0 | } |
630 | | } |
631 | | |
632 | | #[cfg(not(ossl101))] |
633 | | use ffi::EVP_DigestVerifyFinal; |
634 | | |
635 | | #[cfg(ossl101)] |
636 | | #[allow(bad_style)] |
637 | 0 | unsafe fn EVP_DigestVerifyFinal( |
638 | 0 | ctx: *mut ffi::EVP_MD_CTX, |
639 | 0 | sigret: *const ::libc::c_uchar, |
640 | 0 | siglen: ::libc::size_t, |
641 | 0 | ) -> ::libc::c_int { |
642 | 0 | ffi::EVP_DigestVerifyFinal(ctx, sigret as *mut _, siglen) |
643 | 0 | } |
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 | | } |