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::{super::PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN, mgf1, Padding, RsaEncoding, Verification};
16 use crate::{bits, digest, error, rand};
17 
18 /// RSA PSS padding as described in [RFC 3447 Section 8.1].
19 ///
20 /// See "`RSA_PSS_*` Details\" in `ring::signature`'s module-level
21 /// documentation for more details.
22 ///
23 /// [RFC 3447 Section 8.1]: https://tools.ietf.org/html/rfc3447#section-8.1
24 #[derive(Debug)]
25 pub struct PSS {
26     digest_alg: &'static digest::Algorithm,
27 }
28 
29 impl crate::sealed::Sealed for PSS {}
30 
31 impl Padding for PSS {
digest_alg(&self) -> &'static digest::Algorithm32     fn digest_alg(&self) -> &'static digest::Algorithm {
33         self.digest_alg
34     }
35 }
36 
37 impl RsaEncoding for PSS {
38     // Implement padding procedure per EMSA-PSS,
39     // 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>40     fn encode(
41         &self,
42         m_hash: digest::Digest,
43         m_out: &mut [u8],
44         mod_bits: bits::BitLength,
45         rng: &dyn rand::SecureRandom,
46     ) -> Result<(), error::Unspecified> {
47         let metrics = PSSMetrics::new(self.digest_alg, mod_bits)?;
48 
49         // The `m_out` this function fills is the big-endian-encoded value of `m`
50         // from the specification, padded to `k` bytes, where `k` is the length
51         // in bytes of the public modulus. The spec says "Note that emLen will
52         // be one less than k if modBits - 1 is divisible by 8 and equal to k
53         // otherwise." In other words we might need to prefix `em` with a
54         // leading zero byte to form a correct value of `m`.
55         let em = if metrics.top_byte_mask == 0xff {
56             m_out[0] = 0;
57             &mut m_out[1..]
58         } else {
59             m_out
60         };
61         assert_eq!(em.len(), metrics.em_len);
62 
63         // Steps 1 and 2 are done by the caller to produce `m_hash`.
64 
65         // Step 3 is done by `PSSMetrics::new()` above.
66 
67         let (db, digest_terminator) = em.split_at_mut(metrics.db_len);
68 
69         let separator_pos = db.len() - 1 - metrics.s_len;
70 
71         // Step 4.
72         let salt: &[u8] = {
73             let salt = &mut db[(separator_pos + 1)..];
74             rng.fill(salt)?; // salt
75             salt
76         };
77 
78         // Steps 5 and 6.
79         let h = pss_digest(self.digest_alg, m_hash, salt);
80 
81         // Step 7.
82         db[..separator_pos].fill(0); // ps
83 
84         // Step 8.
85         db[separator_pos] = 0x01;
86 
87         // Steps 9 and 10.
88         mgf1(self.digest_alg, h.as_ref(), db);
89 
90         // Step 11.
91         db[0] &= metrics.top_byte_mask;
92 
93         // Step 12.
94         digest_terminator[..metrics.h_len].copy_from_slice(h.as_ref());
95         digest_terminator[metrics.h_len] = 0xbc;
96 
97         Ok(())
98     }
99 }
100 
101 impl Verification for PSS {
102     // RSASSA-PSS-VERIFY from https://tools.ietf.org/html/rfc3447#section-8.1.2
103     // 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>104     fn verify(
105         &self,
106         m_hash: digest::Digest,
107         m: &mut untrusted::Reader,
108         mod_bits: bits::BitLength,
109     ) -> Result<(), error::Unspecified> {
110         let metrics = PSSMetrics::new(self.digest_alg, mod_bits)?;
111 
112         // RSASSA-PSS-VERIFY Step 2(c). The `m` this function is given is the
113         // big-endian-encoded value of `m` from the specification, padded to
114         // `k` bytes, where `k` is the length in bytes of the public modulus.
115         // The spec. says "Note that emLen will be one less than k if
116         // modBits - 1 is divisible by 8 and equal to k otherwise," where `k`
117         // is the length in octets of the RSA public modulus `n`. In other
118         // words, `em` might have an extra leading zero byte that we need to
119         // strip before we start the PSS decoding steps which is an artifact of
120         // the `Verification` interface.
121         if metrics.top_byte_mask == 0xff {
122             if m.read_byte()? != 0 {
123                 return Err(error::Unspecified);
124             }
125         };
126         let em = m;
127 
128         // The rest of this function is EMSA-PSS-VERIFY from
129         // https://tools.ietf.org/html/rfc3447#section-9.1.2.
130 
131         // Steps 1 and 2 are done by the caller to produce `m_hash`.
132 
133         // Step 3 is done by `PSSMetrics::new()` above.
134 
135         // Step 5, out of order.
136         let masked_db = em.read_bytes(metrics.db_len)?;
137         let h_hash = em.read_bytes(metrics.h_len)?;
138 
139         // Step 4.
140         if em.read_byte()? != 0xbc {
141             return Err(error::Unspecified);
142         }
143 
144         // Step 7.
145         let mut db = [0u8; PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN];
146         let db = &mut db[..metrics.db_len];
147 
148         mgf1(self.digest_alg, h_hash.as_slice_less_safe(), db);
149 
150         masked_db.read_all(error::Unspecified, |masked_bytes| {
151             // Step 6. Check the top bits of first byte are zero.
152             let b = masked_bytes.read_byte()?;
153             if b & !metrics.top_byte_mask != 0 {
154                 return Err(error::Unspecified);
155             }
156             db[0] ^= b;
157 
158             // Step 8.
159             for db in db[1..].iter_mut() {
160                 *db ^= masked_bytes.read_byte()?;
161             }
162             Ok(())
163         })?;
164 
165         // Step 9.
166         db[0] &= metrics.top_byte_mask;
167 
168         // Step 10.
169         let ps_len = metrics.ps_len;
170         if db[0..ps_len].iter().any(|&db| db != 0) {
171             return Err(error::Unspecified);
172         }
173         if db[metrics.ps_len] != 1 {
174             return Err(error::Unspecified);
175         }
176 
177         // Step 11.
178         let salt = &db[(db.len() - metrics.s_len)..];
179 
180         // Step 12 and 13.
181         let h_prime = pss_digest(self.digest_alg, m_hash, salt);
182 
183         // Step 14.
184         if h_hash.as_slice_less_safe() != h_prime.as_ref() {
185             return Err(error::Unspecified);
186         }
187 
188         Ok(())
189     }
190 }
191 
192 struct PSSMetrics {
193     #[cfg_attr(not(feature = "alloc"), allow(dead_code))]
194     em_len: usize,
195     db_len: usize,
196     ps_len: usize,
197     s_len: usize,
198     h_len: usize,
199     top_byte_mask: u8,
200 }
201 
202 impl PSSMetrics {
new( digest_alg: &'static digest::Algorithm, mod_bits: bits::BitLength, ) -> Result<Self, error::Unspecified>203     fn new(
204         digest_alg: &'static digest::Algorithm,
205         mod_bits: bits::BitLength,
206     ) -> Result<Self, error::Unspecified> {
207         let em_bits = mod_bits.try_sub_1()?;
208         let em_len = em_bits.as_usize_bytes_rounded_up();
209         let leading_zero_bits = (8 * em_len) - em_bits.as_usize_bits();
210         debug_assert!(leading_zero_bits < 8);
211         let top_byte_mask = 0xffu8 >> leading_zero_bits;
212 
213         let h_len = digest_alg.output_len();
214 
215         // We require the salt length to be equal to the digest length.
216         let s_len = h_len;
217 
218         // Step 3 of both `EMSA-PSS-ENCODE` is `EMSA-PSS-VERIFY` requires that
219         // we reject inputs where "emLen < hLen + sLen + 2". The definition of
220         // `emBits` in RFC 3447 Sections 9.1.1 and 9.1.2 says `emBits` must be
221         // "at least 8hLen + 8sLen + 9". Since 9 bits requires two bytes, these
222         // two conditions are equivalent. 9 bits are required as the 0x01
223         // before the salt requires 1 bit and the 0xbc after the digest
224         // requires 8 bits.
225         let db_len = em_len.checked_sub(1 + s_len).ok_or(error::Unspecified)?;
226         let ps_len = db_len.checked_sub(h_len + 1).ok_or(error::Unspecified)?;
227 
228         debug_assert!(em_bits.as_usize_bits() >= (8 * h_len) + (8 * s_len) + 9);
229 
230         Ok(Self {
231             em_len,
232             db_len,
233             ps_len,
234             s_len,
235             h_len,
236             top_byte_mask,
237         })
238     }
239 }
240 
pss_digest( digest_alg: &'static digest::Algorithm, m_hash: digest::Digest, salt: &[u8], ) -> digest::Digest241 fn pss_digest(
242     digest_alg: &'static digest::Algorithm,
243     m_hash: digest::Digest,
244     salt: &[u8],
245 ) -> digest::Digest {
246     // Fixed prefix.
247     const PREFIX_ZEROS: [u8; 8] = [0u8; 8];
248 
249     // Encoding step 5 and 6, Verification step 12 and 13.
250     let mut ctx = digest::Context::new(digest_alg);
251     ctx.update(&PREFIX_ZEROS);
252     ctx.update(m_hash.as_ref());
253     ctx.update(salt);
254     ctx.finish()
255 }
256 
257 macro_rules! rsa_pss_padding {
258     ( $vis:vis $PADDING_ALGORITHM:ident, $digest_alg:expr, $doc_str:expr ) => {
259         #[doc=$doc_str]
260         $vis static $PADDING_ALGORITHM: PSS = PSS {
261             digest_alg: $digest_alg,
262         };
263     };
264 }
265 
266 rsa_pss_padding!(
267     pub RSA_PSS_SHA256,
268     &digest::SHA256,
269     "RSA PSS padding using SHA-256 for RSA signatures.\n\nSee
270                  \"`RSA_PSS_*` Details\" in `ring::signature`'s module-level
271                  documentation for more details."
272 );
273 
274 rsa_pss_padding!(
275     pub RSA_PSS_SHA384,
276     &digest::SHA384,
277     "RSA PSS padding using SHA-384 for RSA signatures.\n\nSee
278                  \"`RSA_PSS_*` Details\" in `ring::signature`'s module-level
279                  documentation for more details."
280 );
281 
282 rsa_pss_padding!(
283     pub RSA_PSS_SHA512,
284     &digest::SHA512,
285     "RSA PSS padding using SHA-512 for RSA signatures.\n\nSee
286                  \"`RSA_PSS_*` Details\" in `ring::signature`'s module-level
287                  documentation for more details."
288 );
289