• 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};
17 
18 #[cfg(feature = "alloc")]
19 use crate::rand;
20 
21 /// Common features of both RSA padding encoding and RSA padding verification.
22 pub trait Padding: 'static + Sync + crate::sealed::Sealed + core::fmt::Debug {
23     // The digest algorithm used for digesting the message (and maybe for
24     // other things).
digest_alg(&self) -> &'static digest::Algorithm25     fn digest_alg(&self) -> &'static digest::Algorithm;
26 }
27 
28 /// An RSA signature encoding as described in [RFC 3447 Section 8].
29 ///
30 /// [RFC 3447 Section 8]: https://tools.ietf.org/html/rfc3447#section-8
31 #[cfg(feature = "alloc")]
32 pub trait RsaEncoding: Padding {
33     #[doc(hidden)]
encode( &self, m_hash: &digest::Digest, m_out: &mut [u8], mod_bits: bits::BitLength, rng: &dyn rand::SecureRandom, ) -> Result<(), error::Unspecified>34     fn encode(
35         &self,
36         m_hash: &digest::Digest,
37         m_out: &mut [u8],
38         mod_bits: bits::BitLength,
39         rng: &dyn rand::SecureRandom,
40     ) -> Result<(), error::Unspecified>;
41 }
42 
43 /// Verification of an RSA signature encoding as described in
44 /// [RFC 3447 Section 8].
45 ///
46 /// [RFC 3447 Section 8]: https://tools.ietf.org/html/rfc3447#section-8
47 pub trait Verification: Padding {
verify( &self, m_hash: &digest::Digest, m: &mut untrusted::Reader, mod_bits: bits::BitLength, ) -> Result<(), error::Unspecified>48     fn verify(
49         &self,
50         m_hash: &digest::Digest,
51         m: &mut untrusted::Reader,
52         mod_bits: bits::BitLength,
53     ) -> Result<(), error::Unspecified>;
54 }
55 
56 /// PKCS#1 1.5 padding as described in [RFC 3447 Section 8.2].
57 ///
58 /// See "`RSA_PSS_*` Details\" in `ring::signature`'s module-level
59 /// documentation for more details.
60 ///
61 /// [RFC 3447 Section 8.2]: https://tools.ietf.org/html/rfc3447#section-8.2
62 #[derive(Debug)]
63 pub struct PKCS1 {
64     digest_alg: &'static digest::Algorithm,
65     digestinfo_prefix: &'static [u8],
66 }
67 
68 impl crate::sealed::Sealed for PKCS1 {}
69 
70 impl Padding for PKCS1 {
digest_alg(&self) -> &'static digest::Algorithm71     fn digest_alg(&self) -> &'static digest::Algorithm {
72         self.digest_alg
73     }
74 }
75 
76 #[cfg(feature = "alloc")]
77 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>78     fn encode(
79         &self,
80         m_hash: &digest::Digest,
81         m_out: &mut [u8],
82         _mod_bits: bits::BitLength,
83         _rng: &dyn rand::SecureRandom,
84     ) -> Result<(), error::Unspecified> {
85         pkcs1_encode(&self, m_hash, m_out);
86         Ok(())
87     }
88 }
89 
90 impl Verification for PKCS1 {
verify( &self, m_hash: &digest::Digest, m: &mut untrusted::Reader, mod_bits: bits::BitLength, ) -> Result<(), error::Unspecified>91     fn verify(
92         &self,
93         m_hash: &digest::Digest,
94         m: &mut untrusted::Reader,
95         mod_bits: bits::BitLength,
96     ) -> Result<(), error::Unspecified> {
97         // `mod_bits.as_usize_bytes_rounded_up() <=
98         //      PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN` is ensured by `verify_rsa_()`.
99         let mut calculated = [0u8; PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN];
100         let calculated = &mut calculated[..mod_bits.as_usize_bytes_rounded_up()];
101         pkcs1_encode(&self, m_hash, calculated);
102         if m.read_bytes_to_end() != *calculated {
103             return Err(error::Unspecified);
104         }
105         Ok(())
106     }
107 }
108 
109 // Implement padding procedure per EMSA-PKCS1-v1_5,
110 // https://tools.ietf.org/html/rfc3447#section-9.2. This is used by both
111 // verification and signing so it needs to be able to handle moduli of the
112 // minimum and maximum sizes for both operations.
pkcs1_encode(pkcs1: &PKCS1, m_hash: &digest::Digest, m_out: &mut [u8])113 fn pkcs1_encode(pkcs1: &PKCS1, m_hash: &digest::Digest, m_out: &mut [u8]) {
114     let em = m_out;
115 
116     let digest_len = pkcs1.digestinfo_prefix.len() + pkcs1.digest_alg.output_len;
117 
118     // The specification requires at least 8 bytes of padding. Since we
119     // disallow keys smaller than 1024 bits, this should always be true.
120     assert!(em.len() >= digest_len + 11);
121     let pad_len = em.len() - digest_len - 3;
122     em[0] = 0;
123     em[1] = 1;
124     for i in 0..pad_len {
125         em[2 + i] = 0xff;
126     }
127     em[2 + pad_len] = 0;
128 
129     let (digest_prefix, digest_dst) = em[3 + pad_len..].split_at_mut(pkcs1.digestinfo_prefix.len());
130     digest_prefix.copy_from_slice(pkcs1.digestinfo_prefix);
131     digest_dst.copy_from_slice(m_hash.as_ref());
132 }
133 
134 macro_rules! rsa_pkcs1_padding {
135     ( $PADDING_ALGORITHM:ident, $digest_alg:expr, $digestinfo_prefix:expr,
136       $doc_str:expr ) => {
137         #[doc=$doc_str]
138         pub static $PADDING_ALGORITHM: PKCS1 = PKCS1 {
139             digest_alg: $digest_alg,
140             digestinfo_prefix: $digestinfo_prefix,
141         };
142     };
143 }
144 
145 rsa_pkcs1_padding!(
146     RSA_PKCS1_SHA1_FOR_LEGACY_USE_ONLY,
147     &digest::SHA1_FOR_LEGACY_USE_ONLY,
148     &SHA1_PKCS1_DIGESTINFO_PREFIX,
149     "PKCS#1 1.5 padding using SHA-1 for RSA signatures."
150 );
151 rsa_pkcs1_padding!(
152     RSA_PKCS1_SHA256,
153     &digest::SHA256,
154     &SHA256_PKCS1_DIGESTINFO_PREFIX,
155     "PKCS#1 1.5 padding using SHA-256 for RSA signatures."
156 );
157 rsa_pkcs1_padding!(
158     RSA_PKCS1_SHA384,
159     &digest::SHA384,
160     &SHA384_PKCS1_DIGESTINFO_PREFIX,
161     "PKCS#1 1.5 padding using SHA-384 for RSA signatures."
162 );
163 rsa_pkcs1_padding!(
164     RSA_PKCS1_SHA512,
165     &digest::SHA512,
166     &SHA512_PKCS1_DIGESTINFO_PREFIX,
167     "PKCS#1 1.5 padding using SHA-512 for RSA signatures."
168 );
169 
170 macro_rules! pkcs1_digestinfo_prefix {
171     ( $name:ident, $digest_len:expr, $digest_oid_len:expr,
172       [ $( $digest_oid:expr ),* ] ) => {
173         static $name: [u8; 2 + 8 + $digest_oid_len] = [
174             der::Tag::Sequence as u8, 8 + $digest_oid_len + $digest_len,
175                 der::Tag::Sequence as u8, 2 + $digest_oid_len + 2,
176                     der::Tag::OID as u8, $digest_oid_len, $( $digest_oid ),*,
177                     der::Tag::Null as u8, 0,
178                 der::Tag::OctetString as u8, $digest_len,
179         ];
180     }
181 }
182 
183 pkcs1_digestinfo_prefix!(
184     SHA1_PKCS1_DIGESTINFO_PREFIX,
185     20,
186     5,
187     [0x2b, 0x0e, 0x03, 0x02, 0x1a]
188 );
189 
190 pkcs1_digestinfo_prefix!(
191     SHA256_PKCS1_DIGESTINFO_PREFIX,
192     32,
193     9,
194     [0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01]
195 );
196 
197 pkcs1_digestinfo_prefix!(
198     SHA384_PKCS1_DIGESTINFO_PREFIX,
199     48,
200     9,
201     [0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02]
202 );
203 
204 pkcs1_digestinfo_prefix!(
205     SHA512_PKCS1_DIGESTINFO_PREFIX,
206     64,
207     9,
208     [0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03]
209 );
210 
211 /// RSA PSS padding as described in [RFC 3447 Section 8.1].
212 ///
213 /// See "`RSA_PSS_*` Details\" in `ring::signature`'s module-level
214 /// documentation for more details.
215 ///
216 /// [RFC 3447 Section 8.1]: https://tools.ietf.org/html/rfc3447#section-8.1
217 #[derive(Debug)]
218 pub struct PSS {
219     digest_alg: &'static digest::Algorithm,
220 }
221 
222 impl crate::sealed::Sealed for PSS {}
223 
224 // Maximum supported length of the salt in bytes.
225 // In practice, this is constrained by the maximum digest length.
226 const MAX_SALT_LEN: usize = digest::MAX_OUTPUT_LEN;
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         // Step 4.
265         let mut salt = [0u8; MAX_SALT_LEN];
266         let salt = &mut salt[..metrics.s_len];
267         rng.fill(salt)?;
268 
269         // Step 5 and 6.
270         let h_hash = pss_digest(self.digest_alg, m_hash, salt);
271 
272         // Re-order steps 7, 8, 9 and 10 so that we first output the db mask
273         // into `em`, and then XOR the value of db.
274 
275         // Step 9. First output the mask into the out buffer.
276         let (mut masked_db, digest_terminator) = em.split_at_mut(metrics.db_len);
277         mgf1(self.digest_alg, h_hash.as_ref(), &mut masked_db)?;
278 
279         {
280             // Steps 7.
281             let masked_db = masked_db.iter_mut();
282             // `PS` is all zero bytes, so skipping `ps_len` bytes is equivalent
283             // to XORing `PS` onto `db`.
284             let mut masked_db = masked_db.skip(metrics.ps_len);
285 
286             // Step 8.
287             *(masked_db.next().ok_or(error::Unspecified)?) ^= 0x01;
288 
289             // Step 10.
290             for (masked_db_b, salt_b) in masked_db.zip(salt) {
291                 *masked_db_b ^= *salt_b;
292             }
293         }
294 
295         // Step 11.
296         masked_db[0] &= metrics.top_byte_mask;
297 
298         // Step 12.
299         digest_terminator[..metrics.h_len].copy_from_slice(h_hash.as_ref());
300         digest_terminator[metrics.h_len] = 0xbc;
301 
302         Ok(())
303     }
304 }
305 
306 impl Verification for PSS {
307     // RSASSA-PSS-VERIFY from https://tools.ietf.org/html/rfc3447#section-8.1.2
308     // 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>309     fn verify(
310         &self,
311         m_hash: &digest::Digest,
312         m: &mut untrusted::Reader,
313         mod_bits: bits::BitLength,
314     ) -> Result<(), error::Unspecified> {
315         let metrics = PSSMetrics::new(self.digest_alg, mod_bits)?;
316 
317         // RSASSA-PSS-VERIFY Step 2(c). The `m` this function is given is the
318         // big-endian-encoded value of `m` from the specification, padded to
319         // `k` bytes, where `k` is the length in bytes of the public modulus.
320         // The spec. says "Note that emLen will be one less than k if
321         // modBits - 1 is divisible by 8 and equal to k otherwise," where `k`
322         // is the length in octets of the RSA public modulus `n`. In other
323         // words, `em` might have an extra leading zero byte that we need to
324         // strip before we start the PSS decoding steps which is an artifact of
325         // the `Verification` interface.
326         if metrics.top_byte_mask == 0xff {
327             if m.read_byte()? != 0 {
328                 return Err(error::Unspecified);
329             }
330         };
331         let em = m;
332 
333         // The rest of this function is EMSA-PSS-VERIFY from
334         // https://tools.ietf.org/html/rfc3447#section-9.1.2.
335 
336         // Steps 1 and 2 are done by the caller to produce `m_hash`.
337 
338         // Step 3 is done by `PSSMetrics::new()` above.
339 
340         // Step 5, out of order.
341         let masked_db = em.read_bytes(metrics.db_len)?;
342         let h_hash = em.read_bytes(metrics.h_len)?;
343 
344         // Step 4.
345         if em.read_byte()? != 0xbc {
346             return Err(error::Unspecified);
347         }
348 
349         // Step 7.
350         let mut db = [0u8; PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN];
351         let db = &mut db[..metrics.db_len];
352 
353         mgf1(self.digest_alg, h_hash.as_slice_less_safe(), db)?;
354 
355         masked_db.read_all(error::Unspecified, |masked_bytes| {
356             // Step 6. Check the top bits of first byte are zero.
357             let b = masked_bytes.read_byte()?;
358             if b & !metrics.top_byte_mask != 0 {
359                 return Err(error::Unspecified);
360             }
361             db[0] ^= b;
362 
363             // Step 8.
364             for i in 1..db.len() {
365                 db[i] ^= masked_bytes.read_byte()?;
366             }
367             Ok(())
368         })?;
369 
370         // Step 9.
371         db[0] &= metrics.top_byte_mask;
372 
373         // Step 10.
374         let ps_len = metrics.ps_len;
375         for i in 0..ps_len {
376             if db[i] != 0 {
377                 return Err(error::Unspecified);
378             }
379         }
380         if db[metrics.ps_len] != 1 {
381             return Err(error::Unspecified);
382         }
383 
384         // Step 11.
385         let salt = &db[(db.len() - metrics.s_len)..];
386 
387         // Step 12 and 13.
388         let h_prime = pss_digest(self.digest_alg, m_hash, salt);
389 
390         // Step 14.
391         if h_hash != *h_prime.as_ref() {
392             return Err(error::Unspecified);
393         }
394 
395         Ok(())
396     }
397 }
398 
399 struct PSSMetrics {
400     #[cfg_attr(not(feature = "alloc"), allow(dead_code))]
401     em_len: usize,
402     db_len: usize,
403     ps_len: usize,
404     s_len: usize,
405     h_len: usize,
406     top_byte_mask: u8,
407 }
408 
409 impl PSSMetrics {
new( digest_alg: &'static digest::Algorithm, mod_bits: bits::BitLength, ) -> Result<PSSMetrics, error::Unspecified>410     fn new(
411         digest_alg: &'static digest::Algorithm,
412         mod_bits: bits::BitLength,
413     ) -> Result<PSSMetrics, error::Unspecified> {
414         let em_bits = mod_bits.try_sub_1()?;
415         let em_len = em_bits.as_usize_bytes_rounded_up();
416         let leading_zero_bits = (8 * em_len) - em_bits.as_usize_bits();
417         debug_assert!(leading_zero_bits < 8);
418         let top_byte_mask = 0xffu8 >> leading_zero_bits;
419 
420         let h_len = digest_alg.output_len;
421 
422         // We require the salt length to be equal to the digest length.
423         let s_len = h_len;
424 
425         // Step 3 of both `EMSA-PSS-ENCODE` is `EMSA-PSS-VERIFY` requires that
426         // we reject inputs where "emLen < hLen + sLen + 2". The definition of
427         // `emBits` in RFC 3447 Sections 9.1.1 and 9.1.2 says `emBits` must be
428         // "at least 8hLen + 8sLen + 9". Since 9 bits requires two bytes, these
429         // two conditions are equivalent. 9 bits are required as the 0x01
430         // before the salt requires 1 bit and the 0xbc after the digest
431         // requires 8 bits.
432         let db_len = em_len.checked_sub(1 + s_len).ok_or(error::Unspecified)?;
433         let ps_len = db_len.checked_sub(h_len + 1).ok_or(error::Unspecified)?;
434 
435         debug_assert!(em_bits.as_usize_bits() >= (8 * h_len) + (8 * s_len) + 9);
436 
437         Ok(PSSMetrics {
438             em_len,
439             db_len,
440             ps_len,
441             s_len,
442             h_len,
443             top_byte_mask,
444         })
445     }
446 }
447 
448 // Mask-generating function MGF1 as described in
449 // https://tools.ietf.org/html/rfc3447#appendix-B.2.1.
mgf1( digest_alg: &'static digest::Algorithm, seed: &[u8], mask: &mut [u8], ) -> Result<(), error::Unspecified>450 fn mgf1(
451     digest_alg: &'static digest::Algorithm,
452     seed: &[u8],
453     mask: &mut [u8],
454 ) -> Result<(), error::Unspecified> {
455     let digest_len = digest_alg.output_len;
456 
457     // Maximum counter value is the value of (mask_len / digest_len) rounded up.
458     let ctr_max = (mask.len() - 1) / digest_len;
459     assert!(ctr_max <= u32::max_value() as usize);
460     for (i, mask_chunk) in mask.chunks_mut(digest_len).enumerate() {
461         let mut ctx = digest::Context::new(digest_alg);
462         ctx.update(seed);
463         ctx.update(&u32::to_be_bytes(i as u32));
464         let digest = ctx.finish();
465         let mask_chunk_len = mask_chunk.len();
466         mask_chunk.copy_from_slice(&digest.as_ref()[..mask_chunk_len]);
467     }
468 
469     Ok(())
470 }
471 
pss_digest( digest_alg: &'static digest::Algorithm, m_hash: &digest::Digest, salt: &[u8], ) -> digest::Digest472 fn pss_digest(
473     digest_alg: &'static digest::Algorithm,
474     m_hash: &digest::Digest,
475     salt: &[u8],
476 ) -> digest::Digest {
477     // Fixed prefix.
478     const PREFIX_ZEROS: [u8; 8] = [0u8; 8];
479 
480     // Encoding step 5 and 6, Verification step 12 and 13.
481     let mut ctx = digest::Context::new(digest_alg);
482     ctx.update(&PREFIX_ZEROS);
483     ctx.update(m_hash.as_ref());
484     ctx.update(salt);
485     ctx.finish()
486 }
487 
488 macro_rules! rsa_pss_padding {
489     ( $PADDING_ALGORITHM:ident, $digest_alg:expr, $doc_str:expr ) => {
490         #[doc=$doc_str]
491         pub static $PADDING_ALGORITHM: PSS = PSS {
492             digest_alg: $digest_alg,
493         };
494     };
495 }
496 
497 rsa_pss_padding!(
498     RSA_PSS_SHA256,
499     &digest::SHA256,
500     "RSA PSS padding using SHA-256 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_SHA384,
506     &digest::SHA384,
507     "RSA PSS padding using SHA-384 for RSA signatures.\n\nSee
508                  \"`RSA_PSS_*` Details\" in `ring::signature`'s module-level
509                  documentation for more details."
510 );
511 rsa_pss_padding!(
512     RSA_PSS_SHA512,
513     &digest::SHA512,
514     "RSA PSS padding using SHA-512 for RSA signatures.\n\nSee
515                  \"`RSA_PSS_*` Details\" in `ring::signature`'s module-level
516                  documentation for more details."
517 );
518 
519 #[cfg(test)]
520 mod test {
521     use super::*;
522     use crate::{digest, error, test};
523     use alloc::vec;
524 
525     #[test]
test_pss_padding_verify()526     fn test_pss_padding_verify() {
527         test::run(
528             test_file!("rsa_pss_padding_tests.txt"),
529             |section, test_case| {
530                 assert_eq!(section, "");
531 
532                 let digest_name = test_case.consume_string("Digest");
533                 let alg = match digest_name.as_ref() {
534                     "SHA256" => &RSA_PSS_SHA256,
535                     "SHA384" => &RSA_PSS_SHA384,
536                     "SHA512" => &RSA_PSS_SHA512,
537                     _ => panic!("Unsupported digest: {}", digest_name),
538                 };
539 
540                 let msg = test_case.consume_bytes("Msg");
541                 let msg = untrusted::Input::from(&msg);
542                 let m_hash = digest::digest(alg.digest_alg(), msg.as_slice_less_safe());
543 
544                 let encoded = test_case.consume_bytes("EM");
545                 let encoded = untrusted::Input::from(&encoded);
546 
547                 // Salt is recomputed in verification algorithm.
548                 let _ = test_case.consume_bytes("Salt");
549 
550                 let bit_len = test_case.consume_usize_bits("Len");
551                 let is_valid = test_case.consume_string("Result") == "P";
552 
553                 let actual_result =
554                     encoded.read_all(error::Unspecified, |m| alg.verify(&m_hash, m, bit_len));
555                 assert_eq!(actual_result.is_ok(), is_valid);
556 
557                 Ok(())
558             },
559         );
560     }
561 
562     // Tests PSS encoding for various public modulus lengths.
563     #[cfg(feature = "alloc")]
564     #[test]
test_pss_padding_encode()565     fn test_pss_padding_encode() {
566         test::run(
567             test_file!("rsa_pss_padding_tests.txt"),
568             |section, test_case| {
569                 assert_eq!(section, "");
570 
571                 let digest_name = test_case.consume_string("Digest");
572                 let alg = match digest_name.as_ref() {
573                     "SHA256" => &RSA_PSS_SHA256,
574                     "SHA384" => &RSA_PSS_SHA384,
575                     "SHA512" => &RSA_PSS_SHA512,
576                     _ => panic!("Unsupported digest: {}", digest_name),
577                 };
578 
579                 let msg = test_case.consume_bytes("Msg");
580                 let salt = test_case.consume_bytes("Salt");
581                 let encoded = test_case.consume_bytes("EM");
582                 let bit_len = test_case.consume_usize_bits("Len");
583                 let expected_result = test_case.consume_string("Result");
584 
585                 // Only test the valid outputs
586                 if expected_result != "P" {
587                     return Ok(());
588                 }
589 
590                 let rng = test::rand::FixedSliceRandom { bytes: &salt };
591 
592                 let mut m_out = vec![0u8; bit_len.as_usize_bytes_rounded_up()];
593                 let digest = digest::digest(alg.digest_alg(), &msg);
594                 alg.encode(&digest, &mut m_out, bit_len, &rng).unwrap();
595                 assert_eq!(m_out, encoded);
596 
597                 Ok(())
598             },
599         );
600     }
601 }
602