Chromium Code Reviews| 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)) | |
|
Ryan Sleevi
2015/07/16 03:46:37
I'm still nervous this is going to cause issues. W
eroman
2015/07/16 05:23:06
Understood.
When I get back I will see what it ta
| |
| 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 SignatureAlgorithmParameters* other) const { | |
| 257 const RsaPssParameters* params = static_cast<const RsaPssParameters*>(other); | |
| 258 return mgf1_hash_ == params->mgf1_hash_ && | |
| 259 salt_length_ == params->salt_length_; | |
| 260 } | |
| 261 | |
| 262 SignatureAlgorithm::~SignatureAlgorithm() { | |
| 263 } | |
| 264 | |
| 265 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateFromDer( | |
| 266 const der::Input& algorithm_identifier) { | |
| 267 der::Input oid; | |
| 268 der::Input params; | |
| 269 if (!ParseAlgorithmIdentifier(algorithm_identifier, &oid, ¶ms)) | |
| 270 return nullptr; | |
| 271 | |
| 272 // TODO(eroman): Each OID is tested for equality in order, which is not | |
| 273 // particularly efficient. | |
| 274 | |
| 275 if (oid.Equals(der::Input(kOidSha1WithRsaEncryption))) | |
| 276 return ParseRsaPkcs1(DigestAlgorithm::Sha1, params); | |
| 277 | |
| 278 if (oid.Equals(der::Input(kOidSha256WithRsaEncryption))) | |
| 279 return ParseRsaPkcs1(DigestAlgorithm::Sha256, params); | |
| 280 | |
| 281 if (oid.Equals(der::Input(kOidSha384WithRsaEncryption))) | |
| 282 return ParseRsaPkcs1(DigestAlgorithm::Sha384, params); | |
| 283 | |
| 284 if (oid.Equals(der::Input(kOidSha512WithRsaEncryption))) | |
| 285 return ParseRsaPkcs1(DigestAlgorithm::Sha512, params); | |
| 286 | |
| 287 if (oid.Equals(der::Input(kOidEcdsaWithSha1))) | |
| 288 return ParseEcdsa(DigestAlgorithm::Sha1, params); | |
| 289 | |
| 290 if (oid.Equals(der::Input(kOidEcdsaWithSha256))) | |
| 291 return ParseEcdsa(DigestAlgorithm::Sha256, params); | |
| 292 | |
| 293 if (oid.Equals(der::Input(kOidEcdsaWithSha384))) | |
| 294 return ParseEcdsa(DigestAlgorithm::Sha384, params); | |
| 295 | |
| 296 if (oid.Equals(der::Input(kOidEcdsaWithSha512))) | |
| 297 return ParseEcdsa(DigestAlgorithm::Sha512, params); | |
| 298 | |
| 299 // TODO(eroman): Add parsing of RSASSA-PSS | |
| 300 | |
| 301 return nullptr; // Unsupported OID. | |
| 302 } | |
| 303 | |
| 304 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateRsaPkcs1( | |
| 305 DigestAlgorithm digest) { | |
| 306 return make_scoped_ptr( | |
| 307 new SignatureAlgorithm(SignatureAlgorithmId::RsaPkcs1, digest, nullptr)); | |
| 308 } | |
| 309 | |
| 310 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateEcdsa( | |
| 311 DigestAlgorithm digest) { | |
| 312 return make_scoped_ptr( | |
| 313 new SignatureAlgorithm(SignatureAlgorithmId::Ecdsa, digest, nullptr)); | |
| 314 } | |
| 315 | |
| 316 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateRsaPss( | |
| 317 DigestAlgorithm digest, | |
| 318 DigestAlgorithm mgf1_hash, | |
| 319 uint32_t salt_length) { | |
| 320 return make_scoped_ptr(new SignatureAlgorithm( | |
| 321 SignatureAlgorithmId::RsaPss, digest, | |
| 322 make_scoped_ptr(new RsaPssParameters(mgf1_hash, salt_length)))); | |
| 323 } | |
| 324 | |
| 325 bool SignatureAlgorithm::Equals(const SignatureAlgorithm& other) const { | |
| 326 if (algorithm_ != other.algorithm_) | |
| 327 return false; | |
| 328 | |
| 329 if (digest_ != other.digest_) | |
| 330 return false; | |
| 331 | |
| 332 if (!params_ != !other.params_) | |
| 333 return false; | |
| 334 | |
| 335 if (params_ && !params_->Equals(other.params_.get())) | |
| 336 return false; | |
| 337 | |
| 338 return true; | |
| 339 } | |
| 340 | |
| 341 const RsaPssParameters* SignatureAlgorithm::ParamsForRsaPss() const { | |
| 342 if (algorithm_ == SignatureAlgorithmId::RsaPss) | |
| 343 return static_cast<RsaPssParameters*>(params_.get()); | |
| 344 return nullptr; | |
| 345 } | |
| 346 | |
| 347 SignatureAlgorithm::SignatureAlgorithm( | |
| 348 SignatureAlgorithmId algorithm, | |
| 349 DigestAlgorithm digest, | |
| 350 scoped_ptr<SignatureAlgorithmParameters> params) | |
| 351 : algorithm_(algorithm), digest_(digest), params_(params.Pass()) { | |
| 352 } | |
| 353 | |
| 354 } // namespace net | |
| OLD | NEW |