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