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