• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015-2016 Brian Smith.
2 //
3 // Permission to use, copy, modify, and/or distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 
15 use super::PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN;
16 use crate::{bits, digest, error, io::der, polyfill};
17 
18 use core::convert::TryInto;
19 #[cfg(feature = "alloc")]
20 use {
21     crate::rand,
22     alloc::{boxed::Box, vec},
23 };
24 
25 /// Common features of both RSA padding encoding and RSA padding verification.
26 pub trait Padding: 'static + Sync + crate::sealed::Sealed + core::fmt::Debug {
27     // The digest algorithm used for digesting the message (and maybe for
28     // other things).
digest_alg(&self) -> &'static digest::Algorithm29     fn digest_alg(&self) -> &'static digest::Algorithm;
30 }
31 
32 /// An RSA signature encoding as described in [RFC 3447 Section 8].
33 ///
34 /// [RFC 3447 Section 8]: https://tools.ietf.org/html/rfc3447#section-8
35 #[cfg(feature = "alloc")]
36 pub trait RsaEncoding: Padding {
37     #[doc(hidden)]
encode( &self, m_hash: digest::Digest, m_out: &mut [u8], mod_bits: bits::BitLength, rng: &dyn rand::SecureRandom, ) -> Result<(), error::Unspecified>38     fn encode(
39         &self,
40         m_hash: digest::Digest,
41         m_out: &mut [u8],
42         mod_bits: bits::BitLength,
43         rng: &dyn rand::SecureRandom,
44     ) -> Result<(), error::Unspecified>;
45 }
46 
47 /// Verification of an RSA signature encoding as described in
48 /// [RFC 3447 Section 8].
49 ///
50 /// [RFC 3447 Section 8]: https://tools.ietf.org/html/rfc3447#section-8
51 pub trait Verification: Padding {
verify( &self, m_hash: digest::Digest, m: &mut untrusted::Reader, mod_bits: bits::BitLength, ) -> Result<(), error::Unspecified>52     fn verify(
53         &self,
54         m_hash: digest::Digest,
55         m: &mut untrusted::Reader,
56         mod_bits: bits::BitLength,
57     ) -> Result<(), error::Unspecified>;
58 }
59 
60 /// PKCS#1 1.5 padding as described in [RFC 3447 Section 8.2].
61 ///
62 /// See "`RSA_PSS_*` Details\" in `ring::signature`'s module-level
63 /// documentation for more details.
64 ///
65 /// [RFC 3447 Section 8.2]: https://tools.ietf.org/html/rfc3447#section-8.2
66 #[derive(Debug)]
67 pub struct PKCS1 {
68     digest_alg: &'static digest::Algorithm,
69     digestinfo_prefix: &'static [u8],
70 }
71 
72 impl crate::sealed::Sealed for PKCS1 {}
73 
74 impl Padding for PKCS1 {
digest_alg(&self) -> &'static digest::Algorithm75     fn digest_alg(&self) -> &'static digest::Algorithm {
76         self.digest_alg
77     }
78 }
79 
80 #[cfg(feature = "alloc")]
81 impl RsaEncoding for PKCS1 {
encode( &self, m_hash: digest::Digest, m_out: &mut [u8], _mod_bits: bits::BitLength, _rng: &dyn rand::SecureRandom, ) -> Result<(), error::Unspecified>82     fn encode(
83         &self,
84         m_hash: digest::Digest,
85         m_out: &mut [u8],
86         _mod_bits: bits::BitLength,
87         _rng: &dyn rand::SecureRandom,
88     ) -> Result<(), error::Unspecified> {
89         pkcs1_encode(&self, m_hash, m_out);
90         Ok(())
91     }
92 }
93 
94 impl Verification for PKCS1 {
verify( &self, m_hash: digest::Digest, m: &mut untrusted::Reader, mod_bits: bits::BitLength, ) -> Result<(), error::Unspecified>95     fn verify(
96         &self,
97         m_hash: digest::Digest,
98         m: &mut untrusted::Reader,
99         mod_bits: bits::BitLength,
100     ) -> Result<(), error::Unspecified> {
101         // `mod_bits.as_usize_bytes_rounded_up() <=
102         //      PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN` is ensured by `verify_rsa_()`.
103         let mut calculated = [0u8; PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN];
104         let calculated = &mut calculated[..mod_bits.as_usize_bytes_rounded_up()];
105         pkcs1_encode(&self, m_hash, calculated);
106         if m.read_bytes_to_end() != *calculated {
107             return Err(error::Unspecified);
108         }
109         Ok(())
110     }
111 }
112 
113 // Implement padding procedure per EMSA-PKCS1-v1_5,
114 // https://tools.ietf.org/html/rfc3447#section-9.2. This is used by both
115 // verification and signing so it needs to be able to handle moduli of the
116 // minimum and maximum sizes for both operations.
pkcs1_encode(pkcs1: &PKCS1, m_hash: digest::Digest, m_out: &mut [u8])117 fn pkcs1_encode(pkcs1: &PKCS1, m_hash: digest::Digest, m_out: &mut [u8]) {
118     let em = m_out;
119 
120     let digest_len = pkcs1.digestinfo_prefix.len() + pkcs1.digest_alg.output_len;
121 
122     // The specification requires at least 8 bytes of padding. Since we
123     // disallow keys smaller than 1024 bits, this should always be true.
124     assert!(em.len() >= digest_len + 11);
125     let pad_len = em.len() - digest_len - 3;
126     em[0] = 0;
127     em[1] = 1;
128     for i in 0..pad_len {
129         em[2 + i] = 0xff;
130     }
131     em[2 + pad_len] = 0;
132 
133     let (digest_prefix, digest_dst) = em[3 + pad_len..].split_at_mut(pkcs1.digestinfo_prefix.len());
134     digest_prefix.copy_from_slice(pkcs1.digestinfo_prefix);
135     digest_dst.copy_from_slice(m_hash.as_ref());
136 }
137 
138 macro_rules! rsa_pkcs1_padding {
139     ( $PADDING_ALGORITHM:ident, $digest_alg:expr, $digestinfo_prefix:expr,
140       $doc_str:expr ) => {
141         #[doc=$doc_str]
142         pub static $PADDING_ALGORITHM: PKCS1 = PKCS1 {
143             digest_alg: $digest_alg,
144             digestinfo_prefix: $digestinfo_prefix,
145         };
146     };
147 }
148 
149 rsa_pkcs1_padding!(
150     RSA_PKCS1_SHA1_FOR_LEGACY_USE_ONLY,
151     &digest::SHA1_FOR_LEGACY_USE_ONLY,
152     &SHA1_PKCS1_DIGESTINFO_PREFIX,
153     "PKCS#1 1.5 padding using SHA-1 for RSA signatures."
154 );
155 rsa_pkcs1_padding!(
156     RSA_PKCS1_SHA256,
157     &digest::SHA256,
158     &SHA256_PKCS1_DIGESTINFO_PREFIX,
159     "PKCS#1 1.5 padding using SHA-256 for RSA signatures."
160 );
161 rsa_pkcs1_padding!(
162     RSA_PKCS1_SHA384,
163     &digest::SHA384,
164     &SHA384_PKCS1_DIGESTINFO_PREFIX,
165     "PKCS#1 1.5 padding using SHA-384 for RSA signatures."
166 );
167 rsa_pkcs1_padding!(
168     RSA_PKCS1_SHA512,
169     &digest::SHA512,
170     &SHA512_PKCS1_DIGESTINFO_PREFIX,
171     "PKCS#1 1.5 padding using SHA-512 for RSA signatures."
172 );
173 
174 macro_rules! pkcs1_digestinfo_prefix {
175     ( $name:ident, $digest_len:expr, $digest_oid_len:expr,
176       [ $( $digest_oid:expr ),* ] ) => {
177         static $name: [u8; 2 + 8 + $digest_oid_len] = [
178             der::Tag::Sequence as u8, 8 + $digest_oid_len + $digest_len,
179                 der::Tag::Sequence as u8, 2 + $digest_oid_len + 2,
180                     der::Tag::OID as u8, $digest_oid_len, $( $digest_oid ),*,
181                     der::Tag::Null as u8, 0,
182                 der::Tag::OctetString as u8, $digest_len,
183         ];
184     }
185 }
186 
187 pkcs1_digestinfo_prefix!(
188     SHA1_PKCS1_DIGESTINFO_PREFIX,
189     20,
190     5,
191     [0x2b, 0x0e, 0x03, 0x02, 0x1a]
192 );
193 
194 pkcs1_digestinfo_prefix!(
195     SHA256_PKCS1_DIGESTINFO_PREFIX,
196     32,
197     9,
198     [0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01]
199 );
200 
201 pkcs1_digestinfo_prefix!(
202     SHA384_PKCS1_DIGESTINFO_PREFIX,
203     48,
204     9,
205     [0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02]
206 );
207 
208 pkcs1_digestinfo_prefix!(
209     SHA512_PKCS1_DIGESTINFO_PREFIX,
210     64,
211     9,
212     [0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03]
213 );
214 
215 /// RSA PSS padding as described in [RFC 3447 Section 8.1].
216 ///
217 /// See "`RSA_PSS_*` Details\" in `ring::signature`'s module-level
218 /// documentation for more details.
219 ///
220 /// [RFC 3447 Section 8.1]: https://tools.ietf.org/html/rfc3447#section-8.1
221 #[derive(Debug)]
222 pub struct PSS {
223     digest_alg: &'static digest::Algorithm,
224 }
225 
226 impl crate::sealed::Sealed for PSS {}
227 
228 impl Padding for PSS {
digest_alg(&self) -> &'static digest::Algorithm229     fn digest_alg(&self) -> &'static digest::Algorithm {
230         self.digest_alg
231     }
232 }
233 
234 impl RsaEncoding for PSS {
235     // Implement padding procedure per EMSA-PSS,
236     // https://tools.ietf.org/html/rfc3447#section-9.1.
encode( &self, m_hash: digest::Digest, m_out: &mut [u8], mod_bits: bits::BitLength, rng: &dyn rand::SecureRandom, ) -> Result<(), error::Unspecified>237     fn encode(
238         &self,
239         m_hash: digest::Digest,
240         m_out: &mut [u8],
241         mod_bits: bits::BitLength,
242         rng: &dyn rand::SecureRandom,
243     ) -> Result<(), error::Unspecified> {
244         let metrics = PSSMetrics::new(self.digest_alg, mod_bits)?;
245 
246         // The `m_out` this function fills is the big-endian-encoded value of `m`
247         // from the specification, padded to `k` bytes, where `k` is the length
248         // in bytes of the public modulus. The spec says "Note that emLen will
249         // be one less than k if modBits - 1 is divisible by 8 and equal to k
250         // otherwise." In other words we might need to prefix `em` with a
251         // leading zero byte to form a correct value of `m`.
252         let em = if metrics.top_byte_mask == 0xff {
253             m_out[0] = 0;
254             &mut m_out[1..]
255         } else {
256             m_out
257         };
258         assert_eq!(em.len(), metrics.em_len);
259 
260         // Steps 1 and 2 are done by the caller to produce `m_hash`.
261 
262         // Step 3 is done by `PSSMetrics::new()` above.
263 
264         {
265             let (db, digest_terminator) = em.split_at_mut(metrics.db_len);
266             let h;
267             {
268                 let separator_pos = db.len() - 1 - metrics.s_len;
269 
270                 // Step 4.
271                 let salt: &[u8] = {
272                     let salt = &mut db[(separator_pos + 1)..];
273                     rng.fill(salt)?; // salt
274                     salt
275                 };
276 
277                 // Step 5 and 6.
278                 h = pss_digest(self.digest_alg, m_hash, salt);
279 
280                 // Step 7.
281                 polyfill::slice::fill(&mut db[..separator_pos], 0); // ps
282 
283                 // Step 8.
284                 db[separator_pos] = 0x01;
285             };
286 
287             // Steps 9 and 10.
288             mgf1(self.digest_alg, h.as_ref(), db);
289 
290             // Step 11.
291             db[0] &= metrics.top_byte_mask;
292 
293             // Step 12.
294             digest_terminator[..metrics.h_len].copy_from_slice(h.as_ref());
295             digest_terminator[metrics.h_len] = 0xbc;
296         }
297 
298         // Step 12.
299 
300         Ok(())
301     }
302 }
303 
304 impl Verification for PSS {
305     // RSASSA-PSS-VERIFY from https://tools.ietf.org/html/rfc3447#section-8.1.2
306     // where steps 1, 2(a), and 2(b) have been done for us.
verify( &self, m_hash: digest::Digest, m: &mut untrusted::Reader, mod_bits: bits::BitLength, ) -> Result<(), error::Unspecified>307     fn verify(
308         &self,
309         m_hash: digest::Digest,
310         m: &mut untrusted::Reader,
311         mod_bits: bits::BitLength,
312     ) -> Result<(), error::Unspecified> {
313         let metrics = PSSMetrics::new(self.digest_alg, mod_bits)?;
314 
315         // RSASSA-PSS-VERIFY Step 2(c). The `m` this function is given is the
316         // big-endian-encoded value of `m` from the specification, padded to
317         // `k` bytes, where `k` is the length in bytes of the public modulus.
318         // The spec. says "Note that emLen will be one less than k if
319         // modBits - 1 is divisible by 8 and equal to k otherwise," where `k`
320         // is the length in octets of the RSA public modulus `n`. In other
321         // words, `em` might have an extra leading zero byte that we need to
322         // strip before we start the PSS decoding steps which is an artifact of
323         // the `Verification` interface.
324         if metrics.top_byte_mask == 0xff {
325             if m.read_byte()? != 0 {
326                 return Err(error::Unspecified);
327             }
328         };
329         let em = m;
330 
331         // The rest of this function is EMSA-PSS-VERIFY from
332         // https://tools.ietf.org/html/rfc3447#section-9.1.2.
333 
334         // Steps 1 and 2 are done by the caller to produce `m_hash`.
335 
336         // Step 3 is done by `PSSMetrics::new()` above.
337 
338         // Step 5, out of order.
339         let masked_db = em.read_bytes(metrics.db_len)?;
340         let h_hash = em.read_bytes(metrics.h_len)?;
341 
342         // Step 4.
343         if em.read_byte()? != 0xbc {
344             return Err(error::Unspecified);
345         }
346 
347         // Step 7.
348         let mut db = [0u8; PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN];
349         let db = &mut db[..metrics.db_len];
350 
351         mgf1(self.digest_alg, h_hash.as_slice_less_safe(), db);
352 
353         masked_db.read_all(error::Unspecified, |masked_bytes| {
354             // Step 6. Check the top bits of first byte are zero.
355             let b = masked_bytes.read_byte()?;
356             if b & !metrics.top_byte_mask != 0 {
357                 return Err(error::Unspecified);
358             }
359             db[0] ^= b;
360 
361             // Step 8.
362             for i in 1..db.len() {
363                 db[i] ^= masked_bytes.read_byte()?;
364             }
365             Ok(())
366         })?;
367 
368         // Step 9.
369         db[0] &= metrics.top_byte_mask;
370 
371         // Step 10.
372         let ps_len = metrics.ps_len;
373         for i in 0..ps_len {
374             if db[i] != 0 {
375                 return Err(error::Unspecified);
376             }
377         }
378         if db[metrics.ps_len] != 1 {
379             return Err(error::Unspecified);
380         }
381 
382         // Step 11.
383         let salt = &db[(db.len() - metrics.s_len)..];
384 
385         // Step 12 and 13.
386         let h_prime = pss_digest(self.digest_alg, m_hash, salt);
387 
388         // Step 14.
389         if h_hash != *h_prime.as_ref() {
390             return Err(error::Unspecified);
391         }
392 
393         Ok(())
394     }
395 }
396 
397 struct PSSMetrics {
398     #[cfg_attr(not(feature = "alloc"), allow(dead_code))]
399     em_len: usize,
400     db_len: usize,
401     ps_len: usize,
402     s_len: usize,
403     h_len: usize,
404     top_byte_mask: u8,
405 }
406 
407 impl PSSMetrics {
new( digest_alg: &'static digest::Algorithm, mod_bits: bits::BitLength, ) -> Result<Self, error::Unspecified>408     fn new(
409         digest_alg: &'static digest::Algorithm,
410         mod_bits: bits::BitLength,
411     ) -> Result<Self, error::Unspecified> {
412         let em_bits = mod_bits.try_sub_1()?;
413         let em_len = em_bits.as_usize_bytes_rounded_up();
414         let leading_zero_bits = (8 * em_len) - em_bits.as_usize_bits();
415         debug_assert!(leading_zero_bits < 8);
416         let top_byte_mask = 0xffu8 >> leading_zero_bits;
417 
418         let h_len = digest_alg.output_len;
419 
420         // We require the salt length to be equal to the digest length.
421         let s_len = h_len;
422 
423         // Step 3 of both `EMSA-PSS-ENCODE` is `EMSA-PSS-VERIFY` requires that
424         // we reject inputs where "emLen < hLen + sLen + 2". The definition of
425         // `emBits` in RFC 3447 Sections 9.1.1 and 9.1.2 says `emBits` must be
426         // "at least 8hLen + 8sLen + 9". Since 9 bits requires two bytes, these
427         // two conditions are equivalent. 9 bits are required as the 0x01
428         // before the salt requires 1 bit and the 0xbc after the digest
429         // requires 8 bits.
430         let db_len = em_len.checked_sub(1 + s_len).ok_or(error::Unspecified)?;
431         let ps_len = db_len.checked_sub(h_len + 1).ok_or(error::Unspecified)?;
432 
433         debug_assert!(em_bits.as_usize_bits() >= (8 * h_len) + (8 * s_len) + 9);
434 
435         Ok(Self {
436             em_len,
437             db_len,
438             ps_len,
439             s_len,
440             h_len,
441             top_byte_mask,
442         })
443     }
444 }
445 
446 // Mask-generating function MGF1 as described in
447 // https://tools.ietf.org/html/rfc3447#appendix-B.2.1.
mgf1(digest_alg: &'static digest::Algorithm, seed: &[u8], mask: &mut [u8])448 fn mgf1(digest_alg: &'static digest::Algorithm, seed: &[u8], mask: &mut [u8]) {
449     let digest_len = digest_alg.output_len;
450 
451     // Maximum counter value is the value of (mask_len / digest_len) rounded up.
452     for (i, mask_chunk) in mask.chunks_mut(digest_len).enumerate() {
453         let mut ctx = digest::Context::new(digest_alg);
454         ctx.update(seed);
455         // The counter will always fit in a `u32` because we reject absurdly
456         // long inputs very early.
457         ctx.update(&u32::to_be_bytes(i.try_into().unwrap()));
458         let digest = ctx.finish();
459         for (m, &d) in mask_chunk.iter_mut().zip(digest.as_ref().iter()) {
460             *m ^= d;
461         }
462     }
463 }
464 
pss_digest( digest_alg: &'static digest::Algorithm, m_hash: digest::Digest, salt: &[u8], ) -> digest::Digest465 fn pss_digest(
466     digest_alg: &'static digest::Algorithm,
467     m_hash: digest::Digest,
468     salt: &[u8],
469 ) -> digest::Digest {
470     // Fixed prefix.
471     const PREFIX_ZEROS: [u8; 8] = [0u8; 8];
472 
473     // Encoding step 5 and 6, Verification step 12 and 13.
474     let mut ctx = digest::Context::new(digest_alg);
475     ctx.update(&PREFIX_ZEROS);
476     ctx.update(m_hash.as_ref());
477     ctx.update(salt);
478     ctx.finish()
479 }
480 
481 macro_rules! rsa_pss_padding {
482     ( $PADDING_ALGORITHM:ident, $digest_alg:expr, $doc_str:expr ) => {
483         #[doc=$doc_str]
484         pub static $PADDING_ALGORITHM: PSS = PSS {
485             digest_alg: $digest_alg,
486         };
487     };
488 }
489 
490 rsa_pss_padding!(
491     RSA_PSS_SHA256,
492     &digest::SHA256,
493     "RSA PSS padding using SHA-256 for RSA signatures.\n\nSee
494                  \"`RSA_PSS_*` Details\" in `ring::signature`'s module-level
495                  documentation for more details."
496 );
497 rsa_pss_padding!(
498     RSA_PSS_SHA384,
499     &digest::SHA384,
500     "RSA PSS padding using SHA-384 for RSA signatures.\n\nSee
501                  \"`RSA_PSS_*` Details\" in `ring::signature`'s module-level
502                  documentation for more details."
503 );
504 rsa_pss_padding!(
505     RSA_PSS_SHA512,
506     &digest::SHA512,
507     "RSA PSS padding using SHA-512 for RSA signatures.\n\nSee
508                  \"`RSA_PSS_*` Details\" in `ring::signature`'s module-level
509                  documentation for more details."
510 );
511 
512 /// RSA OAEP encoding parameters.
513 #[derive(Debug, PartialEq, Eq)]
514 pub struct OaepEncoding {
515     digest_alg: &'static digest::Algorithm,
516 }
517 
518 impl crate::sealed::Sealed for OaepEncoding {}
519 impl super::Bounds for OaepEncoding {
n_min_bits(&self) -> bits::BitLength520     fn n_min_bits(&self) -> bits::BitLength {
521         bits::BitLength::from_usize_bits(2048)
522     }
523 
n_max_bits(&self) -> bits::BitLength524     fn n_max_bits(&self) -> bits::BitLength {
525         bits::BitLength::from_usize_bits(8192)
526     }
527 
e_min_value(&self) -> u64528     fn e_min_value(&self) -> u64 {
529         65537
530     }
531 }
532 
533 macro_rules! rsa_oaep_padding {
534     ( $PADDING_ALGORITHM:ident, $digest_alg:expr, $doc_str:expr ) => {
535         #[doc=$doc_str]
536         pub static $PADDING_ALGORITHM: OaepEncoding = OaepEncoding {
537             digest_alg: $digest_alg,
538         };
539     };
540 }
541 
542 // TODO: improve doc comments.
543 rsa_oaep_padding!(
544     RSA_OAEP_2048_8192_SHA1_FOR_LEGACY_USE_ONLY,
545     &digest::SHA1_FOR_LEGACY_USE_ONLY,
546     "RSA OAEP using SHA-1."
547 );
548 rsa_oaep_padding!(
549     RSA_OAEP_2048_8192_SHA256,
550     &digest::SHA256,
551     "RSA OAEP using SHA-256."
552 );
553 
554 #[cfg(test)]
555 mod test {
556     use super::*;
557     use crate::{digest, error, test};
558     use alloc::vec;
559 
560     #[test]
test_pss_padding_verify()561     fn test_pss_padding_verify() {
562         test::run(
563             test_file!("rsa_pss_padding_tests.txt"),
564             |section, test_case| {
565                 assert_eq!(section, "");
566 
567                 let digest_name = test_case.consume_string("Digest");
568                 let alg = match digest_name.as_ref() {
569                     "SHA256" => &RSA_PSS_SHA256,
570                     "SHA384" => &RSA_PSS_SHA384,
571                     "SHA512" => &RSA_PSS_SHA512,
572                     _ => panic!("Unsupported digest: {}", digest_name),
573                 };
574 
575                 let msg = test_case.consume_bytes("Msg");
576                 let msg = untrusted::Input::from(&msg);
577                 let m_hash = digest::digest(alg.digest_alg(), msg.as_slice_less_safe());
578 
579                 let encoded = test_case.consume_bytes("EM");
580                 let encoded = untrusted::Input::from(&encoded);
581 
582                 // Salt is recomputed in verification algorithm.
583                 let _ = test_case.consume_bytes("Salt");
584 
585                 let bit_len = test_case.consume_usize_bits("Len");
586                 let is_valid = test_case.consume_string("Result") == "P";
587 
588                 let actual_result =
589                     encoded.read_all(error::Unspecified, |m| alg.verify(m_hash, m, bit_len));
590                 assert_eq!(actual_result.is_ok(), is_valid);
591 
592                 Ok(())
593             },
594         );
595     }
596 
597     // Tests PSS encoding for various public modulus lengths.
598     #[cfg(feature = "alloc")]
599     #[test]
test_pss_padding_encode()600     fn test_pss_padding_encode() {
601         test::run(
602             test_file!("rsa_pss_padding_tests.txt"),
603             |section, test_case| {
604                 assert_eq!(section, "");
605 
606                 let digest_name = test_case.consume_string("Digest");
607                 let alg = match digest_name.as_ref() {
608                     "SHA256" => &RSA_PSS_SHA256,
609                     "SHA384" => &RSA_PSS_SHA384,
610                     "SHA512" => &RSA_PSS_SHA512,
611                     _ => panic!("Unsupported digest: {}", digest_name),
612                 };
613 
614                 let msg = test_case.consume_bytes("Msg");
615                 let salt = test_case.consume_bytes("Salt");
616                 let encoded = test_case.consume_bytes("EM");
617                 let bit_len = test_case.consume_usize_bits("Len");
618                 let expected_result = test_case.consume_string("Result");
619 
620                 // Only test the valid outputs
621                 if expected_result != "P" {
622                     return Ok(());
623                 }
624 
625                 let rng = test::rand::FixedSliceRandom { bytes: &salt };
626 
627                 let mut m_out = vec![0u8; bit_len.as_usize_bytes_rounded_up()];
628                 let digest = digest::digest(alg.digest_alg(), &msg);
629                 alg.encode(digest, &mut m_out, bit_len, &rng).unwrap();
630                 assert_eq!(m_out, encoded);
631 
632                 Ok(())
633             },
634         );
635     }
636 }
637 
oaep_decode<'in_out>( encoding: &'static OaepEncoding, in_out: &'in_out mut [u8], mod_bits: bits::BitLength, ) -> Result<&'in_out [u8], error::Unspecified>638 pub(in crate::rsa) fn oaep_decode<'in_out>(
639     encoding: &'static OaepEncoding,
640     in_out: &'in_out mut [u8],
641     mod_bits: bits::BitLength,
642 ) -> Result<&'in_out [u8], error::Unspecified> {
643     const L: &[u8] = &[];
644     let h_len = encoding.digest_alg.output_len;
645     let k = mod_bits.as_usize_bytes_rounded_up();
646 
647     // 1.a. is implicit given we don't support a non-empty `L`.
648 
649     // 1.b
650     if in_out.len() != k {
651         return Err(error::Unspecified);
652     }
653 
654     // 1.c
655     if k < (2 * h_len) + 2 {
656         return Err(error::Unspecified);
657     }
658 
659     // 3.a.
660     let l_hash = digest::digest(&encoding.digest_alg, L); // TODO: precompute
661 
662     // 3.b.
663     let (y, rest) = in_out.split_at_mut(1);
664     let y = y[0];
665     let (seed, db) = rest.split_at_mut(h_len);
666 
667     // 3.c and 3.d
668     mgf1(&encoding.digest_alg, db, seed);
669 
670     // 3.e. and 3.f.
671     mgf1(&encoding.digest_alg, seed, db);
672 
673     prefixed_extern! {
674         fn RSA_padding_check_oaep(
675             out_len: &mut crate::c::size_t,
676             y: u8,
677             db: *const u8,
678             db_len: crate::c::size_t,
679             phash: *const u8,
680             mdlen: crate::c::size_t,
681         ) -> crate::bssl::Result;
682     }
683 
684     let mut plaintext_len: crate::c::size_t = 0;
685     Result::from(unsafe {
686         RSA_padding_check_oaep(
687             &mut plaintext_len,
688             y,
689             db.as_ptr(),
690             db.len(),
691             l_hash.as_ref().as_ptr(),
692             l_hash.as_ref().len(),
693         )
694     })?;
695     let plaintext_start = db.len() - plaintext_len;
696 
697     Ok(&db[plaintext_start..]) // TODo
698 }
699 
700 #[cfg(feature = "alloc")]
oaep_encode( encoding: &'static OaepEncoding, plaintext: &[u8], mod_bits: bits::BitLength, rng: &dyn rand::SecureRandom, ) -> Result<Box<[u8]>, error::Unspecified>701 pub fn oaep_encode(
702     encoding: &'static OaepEncoding,
703     plaintext: &[u8],
704     mod_bits: bits::BitLength,
705     rng: &dyn rand::SecureRandom,
706 ) -> Result<Box<[u8]>, error::Unspecified> {
707     const L: &[u8] = &[];
708     let k = mod_bits.as_usize_bytes_rounded_up();
709     let h_len = encoding.digest_alg.output_len;
710 
711     // 1.a is implicitly done since `L` is fixed.
712 
713     // 1.b
714     if plaintext.len() > k - (2 * h_len) - 2 {
715         return Err(error::Unspecified);
716     }
717 
718     let mut em = vec![0u8; k].into_boxed_slice();
719     {
720         let (zero, rest) = em.split_at_mut(1);
721         debug_assert_eq!(zero, &[0]);
722         let (seed, db) = rest.split_at_mut(h_len);
723         let (l_hash, rest) = db.split_at_mut(h_len);
724         l_hash.copy_from_slice(digest::digest(&encoding.digest_alg, L).as_ref());
725         let m_index = rest.len() - plaintext.len();
726         let (ps, rest) = rest.split_at_mut(m_index - 1);
727         debug_assert!(ps.iter().all(|&b| b == 0));
728 
729         rest[0] = 0x01;
730         rest[1..].copy_from_slice(plaintext);
731 
732         // 2.d
733         rng.fill(seed)?;
734 
735         // 2.e and 2.f
736         mgf1(&encoding.digest_alg, seed, db);
737 
738         // 2.g and 2.h
739         mgf1(&encoding.digest_alg, db, seed);
740     }
741 
742     Ok(em)
743 }
744