OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/cert/internal/signature_algorithm.h" |
| 6 |
| 7 #include "net/der/input.h" |
| 8 #include "net/der/parser.h" |
| 9 |
| 10 namespace net { |
| 11 |
| 12 namespace { |
| 13 |
| 14 // From RFC 5912: |
| 15 // |
| 16 // sha1WithRSAEncryption OBJECT IDENTIFIER ::= { |
| 17 // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) |
| 18 // pkcs-1(1) 5 } |
| 19 // |
| 20 // In dotted notation: 1.2.840.113549.1.1.5 |
| 21 const uint8_t kOidSha1WithRsaEncryption[] = |
| 22 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05}; |
| 23 |
| 24 // From RFC 5912: |
| 25 // |
| 26 // pkcs-1 OBJECT IDENTIFIER ::= |
| 27 // { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } |
| 28 |
| 29 // From RFC 5912: |
| 30 // |
| 31 // sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 } |
| 32 // |
| 33 // In dotted notation: 1.2.840.113549.1.1.11 |
| 34 const uint8_t kOidSha256WithRsaEncryption[] = |
| 35 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b}; |
| 36 |
| 37 // From RFC 5912: |
| 38 // |
| 39 // sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 } |
| 40 // |
| 41 // In dotted notation: 1.2.840.113549.1.1.11 |
| 42 const uint8_t kOidSha384WithRsaEncryption[] = |
| 43 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c}; |
| 44 |
| 45 // From RFC 5912: |
| 46 // |
| 47 // sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 } |
| 48 // |
| 49 // In dotted notation: 1.2.840.113549.1.1.13 |
| 50 const uint8_t kOidSha512WithRsaEncryption[] = |
| 51 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d}; |
| 52 |
| 53 // From RFC 5912: |
| 54 // |
| 55 // ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { |
| 56 // iso(1) member-body(2) us(840) ansi-X9-62(10045) |
| 57 // signatures(4) 1 } |
| 58 // |
| 59 // In dotted notation: 1.2.840.10045.4.1 |
| 60 const uint8_t kOidEcdsaWithSha1[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01}; |
| 61 |
| 62 // From RFC 5912: |
| 63 // |
| 64 // ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { |
| 65 // iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) |
| 66 // ecdsa-with-SHA2(3) 2 } |
| 67 // |
| 68 // In dotted notation: 1.2.840.10045.4.3.2 |
| 69 const uint8_t kOidEcdsaWithSha256[] = |
| 70 {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02}; |
| 71 |
| 72 // From RFC 5912: |
| 73 // |
| 74 // ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { |
| 75 // iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) |
| 76 // ecdsa-with-SHA2(3) 3 } |
| 77 // |
| 78 // In dotted notation: 1.2.840.10045.4.3.3 |
| 79 const uint8_t kOidEcdsaWithSha384[] = |
| 80 {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03}; |
| 81 |
| 82 // From RFC 5912: |
| 83 // |
| 84 // ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { |
| 85 // iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) |
| 86 // ecdsa-with-SHA2(3) 4 } |
| 87 // |
| 88 // In dotted notation: 1.2.840.10045.4.3.4 |
| 89 const uint8_t kOidEcdsaWithSha512[] = |
| 90 {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04}; |
| 91 |
| 92 // RFC 5280 section 4.1.1.2 defines signatureAlgorithm as: |
| 93 // |
| 94 // AlgorithmIdentifier ::= SEQUENCE { |
| 95 // algorithm OBJECT IDENTIFIER, |
| 96 // parameters ANY DEFINED BY algorithm OPTIONAL } |
| 97 WARN_UNUSED_RESULT bool ParseAlgorithmIdentifier(const der::Input& input, |
| 98 der::Input* algorithm, |
| 99 der::Input* parameters) { |
| 100 der::Parser parser(input); |
| 101 |
| 102 der::Parser algorithm_identifier_parser; |
| 103 if (!parser.ReadSequence(&algorithm_identifier_parser)) |
| 104 return false; |
| 105 |
| 106 // There shouldn't be anything after the sequence. This is by definition, |
| 107 // as the input to this function is expected to be a single |
| 108 // AlgorithmIdentifier. |
| 109 if (parser.HasMore()) |
| 110 return false; |
| 111 |
| 112 if (!algorithm_identifier_parser.ReadTag(der::kOid, algorithm)) |
| 113 return false; |
| 114 |
| 115 // Read the optional parameters to a der::Input. The parameters can be at |
| 116 // most one TLV (for instance NULL or a sequence). |
| 117 // |
| 118 // Note that nothing is allowed after the single optional "parameters" TLV. |
| 119 // This is because RFC 5912's notation for AlgorithmIdentifier doesn't |
| 120 // explicitly list an extension point after "parameters". |
| 121 *parameters = der::Input(); |
| 122 if (algorithm_identifier_parser.HasMore() && |
| 123 !algorithm_identifier_parser.ReadRawTLV(parameters)) { |
| 124 return false; |
| 125 } |
| 126 return !algorithm_identifier_parser.HasMore(); |
| 127 } |
| 128 |
| 129 // Returns true if |input| is empty. |
| 130 WARN_UNUSED_RESULT bool IsEmpty(const der::Input& input) { |
| 131 return input.Length() == 0; |
| 132 } |
| 133 |
| 134 // Returns true if the entirety of the input is a NULL value. |
| 135 WARN_UNUSED_RESULT bool IsNull(const der::Input& input) { |
| 136 der::Parser parser(input); |
| 137 der::Input null_value; |
| 138 if (!parser.ReadTag(der::kNull, &null_value)) |
| 139 return false; |
| 140 |
| 141 // NULL values are TLV encoded; the value is expected to be empty. |
| 142 if (!IsEmpty(null_value)) |
| 143 return false; |
| 144 |
| 145 // By definition of this function, the entire input must be a NULL. |
| 146 return !parser.HasMore(); |
| 147 } |
| 148 |
| 149 // Parses an RSA PKCS#1 v1.5 signature algorithm given the DER-encoded |
| 150 // "parameters" from the parsed AlgorithmIdentifier, and the hash algorithm |
| 151 // that was implied by the AlgorithmIdentifier's OID. |
| 152 // |
| 153 // Returns a nullptr on failure. |
| 154 // |
| 155 // RFC 5912 requires that the parameters for RSA PKCS#1 v1.5 algorithms be NULL |
| 156 // ("PARAMS TYPE NULL ARE required"): |
| 157 // |
| 158 // sa-rsaWithSHA1 SIGNATURE-ALGORITHM ::= { |
| 159 // IDENTIFIER sha1WithRSAEncryption |
| 160 // PARAMS TYPE NULL ARE required |
| 161 // HASHES { mda-sha1 } |
| 162 // PUBLIC-KEYS { pk-rsa } |
| 163 // SMIME-CAPS {IDENTIFIED BY sha1WithRSAEncryption } |
| 164 // } |
| 165 // |
| 166 // sa-sha256WithRSAEncryption SIGNATURE-ALGORITHM ::= { |
| 167 // IDENTIFIER sha256WithRSAEncryption |
| 168 // PARAMS TYPE NULL ARE required |
| 169 // HASHES { mda-sha256 } |
| 170 // PUBLIC-KEYS { pk-rsa } |
| 171 // SMIME-CAPS { IDENTIFIED BY sha256WithRSAEncryption } |
| 172 // } |
| 173 // |
| 174 // sa-sha384WithRSAEncryption SIGNATURE-ALGORITHM ::= { |
| 175 // IDENTIFIER sha384WithRSAEncryption |
| 176 // PARAMS TYPE NULL ARE required |
| 177 // HASHES { mda-sha384 } |
| 178 // PUBLIC-KEYS { pk-rsa } |
| 179 // SMIME-CAPS { IDENTIFIED BY sha384WithRSAEncryption } |
| 180 // } |
| 181 // |
| 182 // sa-sha512WithRSAEncryption SIGNATURE-ALGORITHM ::= { |
| 183 // IDENTIFIER sha512WithRSAEncryption |
| 184 // PARAMS TYPE NULL ARE required |
| 185 // HASHES { mda-sha512 } |
| 186 // PUBLIC-KEYS { pk-rsa } |
| 187 // SMIME-CAPS { IDENTIFIED BY sha512WithRSAEncryption } |
| 188 // } |
| 189 scoped_ptr<SignatureAlgorithm> ParseRsaPkcs1(DigestAlgorithm digest, |
| 190 const der::Input& params) { |
| 191 if (!IsNull(params)) |
| 192 return nullptr; |
| 193 |
| 194 return SignatureAlgorithm::CreateRsaPkcs1(digest); |
| 195 } |
| 196 |
| 197 // Parses an ECDSA signature algorithm given the DER-encoded "parameters" from |
| 198 // the parsed AlgorithmIdentifier, and the hash algorithm that was implied by |
| 199 // the AlgorithmIdentifier's OID. |
| 200 // |
| 201 // On failure returns a nullptr. |
| 202 // |
| 203 // RFC 5912 requires that the parameters for ECDSA algorithms be absent |
| 204 // ("PARAMS TYPE NULL ARE absent"): |
| 205 // |
| 206 // sa-ecdsaWithSHA1 SIGNATURE-ALGORITHM ::= { |
| 207 // IDENTIFIER ecdsa-with-SHA1 |
| 208 // VALUE ECDSA-Sig-Value |
| 209 // PARAMS TYPE NULL ARE absent |
| 210 // HASHES { mda-sha1 } |
| 211 // PUBLIC-KEYS { pk-ec } |
| 212 // SMIME-CAPS {IDENTIFIED BY ecdsa-with-SHA1 } |
| 213 // } |
| 214 // |
| 215 // sa-ecdsaWithSHA256 SIGNATURE-ALGORITHM ::= { |
| 216 // IDENTIFIER ecdsa-with-SHA256 |
| 217 // VALUE ECDSA-Sig-Value |
| 218 // PARAMS TYPE NULL ARE absent |
| 219 // HASHES { mda-sha256 } |
| 220 // PUBLIC-KEYS { pk-ec } |
| 221 // SMIME-CAPS { IDENTIFIED BY ecdsa-with-SHA256 } |
| 222 // } |
| 223 // |
| 224 // sa-ecdsaWithSHA384 SIGNATURE-ALGORITHM ::= { |
| 225 // IDENTIFIER ecdsa-with-SHA384 |
| 226 // VALUE ECDSA-Sig-Value |
| 227 // PARAMS TYPE NULL ARE absent |
| 228 // HASHES { mda-sha384 } |
| 229 // PUBLIC-KEYS { pk-ec } |
| 230 // SMIME-CAPS { IDENTIFIED BY ecdsa-with-SHA384 } |
| 231 // } |
| 232 // |
| 233 // sa-ecdsaWithSHA512 SIGNATURE-ALGORITHM ::= { |
| 234 // IDENTIFIER ecdsa-with-SHA512 |
| 235 // VALUE ECDSA-Sig-Value |
| 236 // PARAMS TYPE NULL ARE absent |
| 237 // HASHES { mda-sha512 } |
| 238 // PUBLIC-KEYS { pk-ec } |
| 239 // SMIME-CAPS { IDENTIFIED BY ecdsa-with-SHA512 } |
| 240 // } |
| 241 scoped_ptr<SignatureAlgorithm> ParseEcdsa(DigestAlgorithm digest, |
| 242 const der::Input& params) { |
| 243 if (!IsEmpty(params)) |
| 244 return nullptr; |
| 245 |
| 246 return SignatureAlgorithm::CreateEcdsa(digest); |
| 247 } |
| 248 |
| 249 } // namespace |
| 250 |
| 251 RsaPssParameters::RsaPssParameters(DigestAlgorithm mgf1_hash, |
| 252 uint32_t salt_length) |
| 253 : mgf1_hash_(mgf1_hash), salt_length_(salt_length) { |
| 254 } |
| 255 |
| 256 bool RsaPssParameters::Equals(const RsaPssParameters* other) const { |
| 257 return mgf1_hash_ == other->mgf1_hash_ && salt_length_ == other->salt_length_; |
| 258 } |
| 259 |
| 260 SignatureAlgorithm::~SignatureAlgorithm() { |
| 261 } |
| 262 |
| 263 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateFromDer( |
| 264 const der::Input& algorithm_identifier) { |
| 265 der::Input oid; |
| 266 der::Input params; |
| 267 if (!ParseAlgorithmIdentifier(algorithm_identifier, &oid, ¶ms)) |
| 268 return nullptr; |
| 269 |
| 270 // TODO(eroman): Each OID is tested for equality in order, which is not |
| 271 // particularly efficient. |
| 272 |
| 273 if (oid.Equals(der::Input(kOidSha1WithRsaEncryption))) |
| 274 return ParseRsaPkcs1(DigestAlgorithm::Sha1, params); |
| 275 |
| 276 if (oid.Equals(der::Input(kOidSha256WithRsaEncryption))) |
| 277 return ParseRsaPkcs1(DigestAlgorithm::Sha256, params); |
| 278 |
| 279 if (oid.Equals(der::Input(kOidSha384WithRsaEncryption))) |
| 280 return ParseRsaPkcs1(DigestAlgorithm::Sha384, params); |
| 281 |
| 282 if (oid.Equals(der::Input(kOidSha512WithRsaEncryption))) |
| 283 return ParseRsaPkcs1(DigestAlgorithm::Sha512, params); |
| 284 |
| 285 if (oid.Equals(der::Input(kOidEcdsaWithSha1))) |
| 286 return ParseEcdsa(DigestAlgorithm::Sha1, params); |
| 287 |
| 288 if (oid.Equals(der::Input(kOidEcdsaWithSha256))) |
| 289 return ParseEcdsa(DigestAlgorithm::Sha256, params); |
| 290 |
| 291 if (oid.Equals(der::Input(kOidEcdsaWithSha384))) |
| 292 return ParseEcdsa(DigestAlgorithm::Sha384, params); |
| 293 |
| 294 if (oid.Equals(der::Input(kOidEcdsaWithSha512))) |
| 295 return ParseEcdsa(DigestAlgorithm::Sha512, params); |
| 296 |
| 297 // TODO(eroman): Add parsing of RSASSA-PSS |
| 298 |
| 299 return nullptr; // Unsupported OID. |
| 300 } |
| 301 |
| 302 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateRsaPkcs1( |
| 303 DigestAlgorithm digest) { |
| 304 return make_scoped_ptr( |
| 305 new SignatureAlgorithm(SignatureAlgorithmId::RsaPkcs1, digest, nullptr)); |
| 306 } |
| 307 |
| 308 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateEcdsa( |
| 309 DigestAlgorithm digest) { |
| 310 return make_scoped_ptr( |
| 311 new SignatureAlgorithm(SignatureAlgorithmId::Ecdsa, digest, nullptr)); |
| 312 } |
| 313 |
| 314 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateRsaPss( |
| 315 DigestAlgorithm digest, |
| 316 DigestAlgorithm mgf1_hash, |
| 317 uint32_t salt_length) { |
| 318 return make_scoped_ptr(new SignatureAlgorithm( |
| 319 SignatureAlgorithmId::RsaPss, digest, |
| 320 make_scoped_ptr(new RsaPssParameters(mgf1_hash, salt_length)))); |
| 321 } |
| 322 |
| 323 bool SignatureAlgorithm::Equals(const SignatureAlgorithm& other) const { |
| 324 if (algorithm_ != other.algorithm_) |
| 325 return false; |
| 326 |
| 327 if (digest_ != other.digest_) |
| 328 return false; |
| 329 |
| 330 // Check that the parameters are equal. |
| 331 switch (algorithm_) { |
| 332 case SignatureAlgorithmId::RsaPss: { |
| 333 const RsaPssParameters* params1 = ParamsForRsaPss(); |
| 334 const RsaPssParameters* params2 = other.ParamsForRsaPss(); |
| 335 if (!params1 || !params2 || !params1->Equals(params2)) |
| 336 return false; |
| 337 break; |
| 338 } |
| 339 |
| 340 // There shouldn't be any parameters. |
| 341 case SignatureAlgorithmId::RsaPkcs1: |
| 342 case SignatureAlgorithmId::Ecdsa: |
| 343 if (params_ || other.params_) |
| 344 return false; |
| 345 break; |
| 346 } |
| 347 |
| 348 return true; |
| 349 } |
| 350 |
| 351 const RsaPssParameters* SignatureAlgorithm::ParamsForRsaPss() const { |
| 352 if (algorithm_ == SignatureAlgorithmId::RsaPss) |
| 353 return static_cast<RsaPssParameters*>(params_.get()); |
| 354 return nullptr; |
| 355 } |
| 356 |
| 357 SignatureAlgorithm::SignatureAlgorithm( |
| 358 SignatureAlgorithmId algorithm, |
| 359 DigestAlgorithm digest, |
| 360 scoped_ptr<SignatureAlgorithmParameters> params) |
| 361 : algorithm_(algorithm), digest_(digest), params_(params.Pass()) { |
| 362 } |
| 363 |
| 364 } // namespace net |
OLD | NEW |