OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/cert/internal/signature_algorithm.h" | 5 #include "net/cert/internal/signature_algorithm.h" |
6 | 6 |
| 7 #include "base/numerics/safe_math.h" |
7 #include "net/der/input.h" | 8 #include "net/der/input.h" |
| 9 #include "net/der/parse_values.h" |
8 #include "net/der/parser.h" | 10 #include "net/der/parser.h" |
9 | 11 |
10 namespace net { | 12 namespace net { |
11 | 13 |
12 namespace { | 14 namespace { |
13 | 15 |
14 // From RFC 5912: | 16 // From RFC 5912: |
15 // | 17 // |
16 // sha1WithRSAEncryption OBJECT IDENTIFIER ::= { | 18 // sha1WithRSAEncryption OBJECT IDENTIFIER ::= { |
17 // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) | 19 // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 // From RFC 5912: | 98 // From RFC 5912: |
97 // | 99 // |
98 // ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { | 100 // ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { |
99 // iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) | 101 // iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) |
100 // ecdsa-with-SHA2(3) 4 } | 102 // ecdsa-with-SHA2(3) 4 } |
101 // | 103 // |
102 // In dotted notation: 1.2.840.10045.4.3.4 | 104 // In dotted notation: 1.2.840.10045.4.3.4 |
103 const uint8_t kOidEcdsaWithSha512[] = | 105 const uint8_t kOidEcdsaWithSha512[] = |
104 {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04}; | 106 {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04}; |
105 | 107 |
| 108 // From RFC 5912: |
| 109 // |
| 110 // id-RSASSA-PSS OBJECT IDENTIFIER ::= { pkcs-1 10 } |
| 111 // |
| 112 // In dotted notation: 1.2.840.113549.1.1.10 |
| 113 const uint8_t kOidRsaSsaPss[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, |
| 114 0x0d, 0x01, 0x01, 0x0a}; |
| 115 |
| 116 // From RFC 5912: |
| 117 // |
| 118 // id-sha1 OBJECT IDENTIFIER ::= { |
| 119 // iso(1) identified-organization(3) oiw(14) secsig(3) |
| 120 // algorithm(2) 26 } |
| 121 // |
| 122 // In dotted notation: 1.3.14.3.2.26 |
| 123 const uint8_t kOidSha1[] = {0x2B, 0x0E, 0x03, 0x02, 0x1A}; |
| 124 |
| 125 // From RFC 5912: |
| 126 // |
| 127 // id-sha256 OBJECT IDENTIFIER ::= |
| 128 // { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) |
| 129 // csor(3) nistAlgorithms(4) hashalgs(2) 1 } |
| 130 // |
| 131 // In dotted notation: 2.16.840.1.101.3.4.2.1 |
| 132 const uint8_t kOidSha256[] = {0x60, 0x86, 0x48, 0x01, 0x65, |
| 133 0x03, 0x04, 0x02, 0x01}; |
| 134 |
| 135 // From RFC 5912: |
| 136 // |
| 137 // id-sha384 OBJECT IDENTIFIER ::= |
| 138 // { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) |
| 139 // csor(3) nistAlgorithms(4) hashalgs(2) 2 } |
| 140 // |
| 141 // In dotted notation: 2.16.840.1.101.3.4.2.2 |
| 142 const uint8_t kOidSha384[] = {0x60, 0x86, 0x48, 0x01, 0x65, |
| 143 0x03, 0x04, 0x02, 0x02}; |
| 144 |
| 145 // From RFC 5912: |
| 146 // |
| 147 // id-sha512 OBJECT IDENTIFIER ::= |
| 148 // { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) |
| 149 // csor(3) nistAlgorithms(4) hashalgs(2) 3 } |
| 150 // |
| 151 // In dotted notation: 2.16.840.1.101.3.4.2.3 |
| 152 const uint8_t kOidSha512[] = {0x60, 0x86, 0x48, 0x01, 0x65, |
| 153 0x03, 0x04, 0x02, 0x03}; |
| 154 |
| 155 // From RFC 5912: |
| 156 // |
| 157 // id-mgf1 OBJECT IDENTIFIER ::= { pkcs-1 8 } |
| 158 // |
| 159 // In dotted notation: 1.2.840.113549.1.1.8 |
| 160 const uint8_t kOidMgf1[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, |
| 161 0x0d, 0x01, 0x01, 0x08}; |
| 162 |
106 // RFC 5280 section 4.1.1.2 defines signatureAlgorithm as: | 163 // RFC 5280 section 4.1.1.2 defines signatureAlgorithm as: |
107 // | 164 // |
108 // AlgorithmIdentifier ::= SEQUENCE { | 165 // AlgorithmIdentifier ::= SEQUENCE { |
109 // algorithm OBJECT IDENTIFIER, | 166 // algorithm OBJECT IDENTIFIER, |
110 // parameters ANY DEFINED BY algorithm OPTIONAL } | 167 // parameters ANY DEFINED BY algorithm OPTIONAL } |
111 WARN_UNUSED_RESULT bool ParseAlgorithmIdentifier(const der::Input& input, | 168 WARN_UNUSED_RESULT bool ParseAlgorithmIdentifier(const der::Input& input, |
112 der::Input* algorithm, | 169 der::Input* algorithm, |
113 der::Input* parameters) { | 170 der::Input* parameters) { |
114 der::Parser parser(input); | 171 der::Parser parser(input); |
115 | 172 |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 // SMIME-CAPS { IDENTIFIED BY ecdsa-with-SHA512 } | 310 // SMIME-CAPS { IDENTIFIED BY ecdsa-with-SHA512 } |
254 // } | 311 // } |
255 scoped_ptr<SignatureAlgorithm> ParseEcdsa(DigestAlgorithm digest, | 312 scoped_ptr<SignatureAlgorithm> ParseEcdsa(DigestAlgorithm digest, |
256 const der::Input& params) { | 313 const der::Input& params) { |
257 if (!IsEmpty(params)) | 314 if (!IsEmpty(params)) |
258 return nullptr; | 315 return nullptr; |
259 | 316 |
260 return SignatureAlgorithm::CreateEcdsa(digest); | 317 return SignatureAlgorithm::CreateEcdsa(digest); |
261 } | 318 } |
262 | 319 |
| 320 // Parses a HashAlgorithm as defined by RFC 5912: |
| 321 // |
| 322 // HashAlgorithm ::= AlgorithmIdentifier{DIGEST-ALGORITHM, |
| 323 // {HashAlgorithms}} |
| 324 // |
| 325 // HashAlgorithms DIGEST-ALGORITHM ::= { |
| 326 // { IDENTIFIER id-sha1 PARAMS TYPE NULL ARE preferredPresent } | |
| 327 // { IDENTIFIER id-sha224 PARAMS TYPE NULL ARE preferredPresent } | |
| 328 // { IDENTIFIER id-sha256 PARAMS TYPE NULL ARE preferredPresent } | |
| 329 // { IDENTIFIER id-sha384 PARAMS TYPE NULL ARE preferredPresent } | |
| 330 // { IDENTIFIER id-sha512 PARAMS TYPE NULL ARE preferredPresent } |
| 331 // } |
| 332 WARN_UNUSED_RESULT bool ParseHashAlgorithm(const der::Input input, |
| 333 DigestAlgorithm* out) { |
| 334 der::Input oid; |
| 335 der::Input params; |
| 336 if (!ParseAlgorithmIdentifier(input, &oid, ¶ms)) |
| 337 return false; |
| 338 |
| 339 DigestAlgorithm hash; |
| 340 |
| 341 if (oid.Equals(der::Input(kOidSha1))) { |
| 342 hash = DigestAlgorithm::Sha1; |
| 343 } else if (oid.Equals(der::Input(kOidSha256))) { |
| 344 hash = DigestAlgorithm::Sha256; |
| 345 } else if (oid.Equals(der::Input(kOidSha384))) { |
| 346 hash = DigestAlgorithm::Sha384; |
| 347 } else if (oid.Equals(der::Input(kOidSha512))) { |
| 348 hash = DigestAlgorithm::Sha512; |
| 349 } else { |
| 350 // Unsupported digest algorithm. |
| 351 return false; |
| 352 } |
| 353 |
| 354 // From RFC 5912: "PARAMS TYPE NULL ARE preferredPresent". Which is to say |
| 355 // the can either be absent, or NULL. |
| 356 if (!IsEmpty(params) && !IsNull(params)) |
| 357 return false; |
| 358 |
| 359 *out = hash; |
| 360 return true; |
| 361 } |
| 362 |
| 363 // Parses a MaskGenAlgorithm as defined by RFC 5912: |
| 364 // |
| 365 // MaskGenAlgorithm ::= AlgorithmIdentifier{ALGORITHM, |
| 366 // {PKCS1MGFAlgorithms}} |
| 367 // |
| 368 // mgf1SHA1 MaskGenAlgorithm ::= { |
| 369 // algorithm id-mgf1, |
| 370 // parameters HashAlgorithm : sha1Identifier |
| 371 // } |
| 372 // |
| 373 // -- |
| 374 // -- Define the set of mask generation functions |
| 375 // -- |
| 376 // -- If the identifier is id-mgf1, any of the listed hash |
| 377 // -- algorithms may be used. |
| 378 // -- |
| 379 // |
| 380 // PKCS1MGFAlgorithms ALGORITHM ::= { |
| 381 // { IDENTIFIER id-mgf1 PARAMS TYPE HashAlgorithm ARE required }, |
| 382 // ... |
| 383 // } |
| 384 // |
| 385 // Note that the possible mask gen algorithms is extensible. However at present |
| 386 // the only function supported is MGF1, as that is the singular mask gen |
| 387 // function defined by RFC 4055 / RFC 5912. |
| 388 WARN_UNUSED_RESULT bool ParseMaskGenAlgorithm(const der::Input input, |
| 389 DigestAlgorithm* mgf1_hash) { |
| 390 der::Input oid; |
| 391 der::Input params; |
| 392 if (!ParseAlgorithmIdentifier(input, &oid, ¶ms)) |
| 393 return false; |
| 394 |
| 395 // MGF1 is the only supported mask generation algorithm. |
| 396 if (!oid.Equals(der::Input(kOidMgf1))) |
| 397 return false; |
| 398 |
| 399 return ParseHashAlgorithm(params, mgf1_hash); |
| 400 } |
| 401 |
| 402 // Consumes an optional, explicitly-tagged INTEGER from |parser|, using the |
| 403 // indicated context-specific class number. Values greater than 32-bits will be |
| 404 // rejected. |
| 405 // |
| 406 // Returns true on success and sets |*present| to true if the field was present. |
| 407 WARN_UNUSED_RESULT bool ReadOptionalContextSpecificUint32(der::Parser* parser, |
| 408 uint8_t class_number, |
| 409 uint32_t* out, |
| 410 bool* present) { |
| 411 der::Input value; |
| 412 bool has_value; |
| 413 |
| 414 // Read the context specific value. |
| 415 if (!parser->ReadOptionalTag(der::ContextSpecificConstructed(class_number), |
| 416 &value, &has_value)) { |
| 417 return false; |
| 418 } |
| 419 |
| 420 if (has_value) { |
| 421 // Parse the integer contained in it. |
| 422 der::Parser number_parser(value); |
| 423 uint64_t uint64_value; |
| 424 |
| 425 if (!number_parser.ReadUint64(&uint64_value)) |
| 426 return false; |
| 427 if (number_parser.HasMore()) |
| 428 return false; |
| 429 |
| 430 // Cast the number to a uint32_t |
| 431 base::CheckedNumeric<uint32_t> casted(uint64_value); |
| 432 if (!casted.IsValid()) |
| 433 return false; |
| 434 *out = casted.ValueOrDie(); |
| 435 } |
| 436 |
| 437 *present = has_value; |
| 438 return true; |
| 439 } |
| 440 |
| 441 // Parses the parameters for an RSASSA-PSS signature algorithm, as defined by |
| 442 // RFC 5912: |
| 443 // |
| 444 // sa-rsaSSA-PSS SIGNATURE-ALGORITHM ::= { |
| 445 // IDENTIFIER id-RSASSA-PSS |
| 446 // PARAMS TYPE RSASSA-PSS-params ARE required |
| 447 // HASHES { mda-sha1 | mda-sha224 | mda-sha256 | mda-sha384 |
| 448 // | mda-sha512 } |
| 449 // PUBLIC-KEYS { pk-rsa | pk-rsaSSA-PSS } |
| 450 // SMIME-CAPS { IDENTIFIED BY id-RSASSA-PSS } |
| 451 // } |
| 452 // |
| 453 // RSASSA-PSS-params ::= SEQUENCE { |
| 454 // hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, |
| 455 // maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1, |
| 456 // saltLength [2] INTEGER DEFAULT 20, |
| 457 // trailerField [3] INTEGER DEFAULT 1 |
| 458 // } |
| 459 // |
| 460 // Which is to say the parameters MUST be present, and of type |
| 461 // RSASSA-PSS-params. |
| 462 scoped_ptr<SignatureAlgorithm> ParseRsaPss(const der::Input& params) { |
| 463 der::Parser parser(params); |
| 464 der::Parser params_parser; |
| 465 if (!parser.ReadSequence(¶ms_parser)) |
| 466 return nullptr; |
| 467 |
| 468 // There shouldn't be anything after the sequence (by definition the |
| 469 // parameters is a single sequence). |
| 470 if (parser.HasMore()) |
| 471 return nullptr; |
| 472 |
| 473 bool has_field; |
| 474 der::Input field; |
| 475 |
| 476 // Parse: |
| 477 // hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, |
| 478 DigestAlgorithm hash = DigestAlgorithm::Sha1; |
| 479 if (!params_parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &field, |
| 480 &has_field)) { |
| 481 return nullptr; |
| 482 } |
| 483 if (has_field && !ParseHashAlgorithm(field, &hash)) |
| 484 return nullptr; |
| 485 |
| 486 // Parse: |
| 487 // maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1, |
| 488 DigestAlgorithm mgf1_hash = DigestAlgorithm::Sha1; |
| 489 if (!params_parser.ReadOptionalTag(der::ContextSpecificConstructed(1), &field, |
| 490 &has_field)) { |
| 491 return nullptr; |
| 492 } |
| 493 if (has_field && !ParseMaskGenAlgorithm(field, &mgf1_hash)) |
| 494 return nullptr; |
| 495 |
| 496 // Parse: |
| 497 // saltLength [2] INTEGER DEFAULT 20, |
| 498 uint32_t salt_length = 20u; |
| 499 if (!ReadOptionalContextSpecificUint32(¶ms_parser, 2, &salt_length, |
| 500 &has_field)) { |
| 501 return nullptr; |
| 502 } |
| 503 |
| 504 // Parse: |
| 505 // trailerField [3] INTEGER DEFAULT 1 |
| 506 uint32_t trailer_field = 1u; |
| 507 if (!ReadOptionalContextSpecificUint32(¶ms_parser, 3, &trailer_field, |
| 508 &has_field)) { |
| 509 return nullptr; |
| 510 } |
| 511 |
| 512 // RFC 4055 says that the trailer field must be 1: |
| 513 // |
| 514 // The trailerField field is an integer. It provides |
| 515 // compatibility with IEEE Std 1363a-2004 [P1363A]. The value |
| 516 // MUST be 1, which represents the trailer field with hexadecimal |
| 517 // value 0xBC. Other trailer fields, including the trailer field |
| 518 // composed of HashID concatenated with 0xCC that is specified in |
| 519 // IEEE Std 1363a, are not supported. Implementations that |
| 520 // perform signature generation MUST omit the trailerField field, |
| 521 // indicating that the default trailer field value was used. |
| 522 // Implementations that perform signature validation MUST |
| 523 // recognize both a present trailerField field with value 1 and an |
| 524 // absent trailerField field. |
| 525 if (trailer_field != 1) |
| 526 return nullptr; |
| 527 |
| 528 // There must not be any unconsumed data left. (RFC 5912 does not explicitly |
| 529 // include an extensibility point for RSASSA-PSS-params) |
| 530 if (params_parser.HasMore()) |
| 531 return nullptr; |
| 532 |
| 533 return SignatureAlgorithm::CreateRsaPss(hash, mgf1_hash, salt_length); |
| 534 } |
| 535 |
263 } // namespace | 536 } // namespace |
264 | 537 |
265 RsaPssParameters::RsaPssParameters(DigestAlgorithm mgf1_hash, | 538 RsaPssParameters::RsaPssParameters(DigestAlgorithm mgf1_hash, |
266 uint32_t salt_length) | 539 uint32_t salt_length) |
267 : mgf1_hash_(mgf1_hash), salt_length_(salt_length) { | 540 : mgf1_hash_(mgf1_hash), salt_length_(salt_length) { |
268 } | 541 } |
269 | 542 |
270 bool RsaPssParameters::Equals(const RsaPssParameters* other) const { | 543 bool RsaPssParameters::Equals(const RsaPssParameters* other) const { |
271 return mgf1_hash_ == other->mgf1_hash_ && salt_length_ == other->salt_length_; | 544 return mgf1_hash_ == other->mgf1_hash_ && salt_length_ == other->salt_length_; |
272 } | 545 } |
(...skipping 28 matching lines...) Expand all Loading... |
301 | 574 |
302 if (oid.Equals(der::Input(kOidEcdsaWithSha256))) | 575 if (oid.Equals(der::Input(kOidEcdsaWithSha256))) |
303 return ParseEcdsa(DigestAlgorithm::Sha256, params); | 576 return ParseEcdsa(DigestAlgorithm::Sha256, params); |
304 | 577 |
305 if (oid.Equals(der::Input(kOidEcdsaWithSha384))) | 578 if (oid.Equals(der::Input(kOidEcdsaWithSha384))) |
306 return ParseEcdsa(DigestAlgorithm::Sha384, params); | 579 return ParseEcdsa(DigestAlgorithm::Sha384, params); |
307 | 580 |
308 if (oid.Equals(der::Input(kOidEcdsaWithSha512))) | 581 if (oid.Equals(der::Input(kOidEcdsaWithSha512))) |
309 return ParseEcdsa(DigestAlgorithm::Sha512, params); | 582 return ParseEcdsa(DigestAlgorithm::Sha512, params); |
310 | 583 |
311 // TODO(eroman): Add parsing of RSASSA-PSS | 584 if (oid.Equals(der::Input(kOidRsaSsaPss))) |
| 585 return ParseRsaPss(params); |
312 | 586 |
313 if (oid.Equals(der::Input(kOidSha1WithRsaSignature))) | 587 if (oid.Equals(der::Input(kOidSha1WithRsaSignature))) |
314 return ParseRsaPkcs1(DigestAlgorithm::Sha1, params); | 588 return ParseRsaPkcs1(DigestAlgorithm::Sha1, params); |
315 | 589 |
316 return nullptr; // Unsupported OID. | 590 return nullptr; // Unsupported OID. |
317 } | 591 } |
318 | 592 |
319 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateRsaPkcs1( | 593 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateRsaPkcs1( |
320 DigestAlgorithm digest) { | 594 DigestAlgorithm digest) { |
321 return make_scoped_ptr( | 595 return make_scoped_ptr( |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 } | 646 } |
373 | 647 |
374 SignatureAlgorithm::SignatureAlgorithm( | 648 SignatureAlgorithm::SignatureAlgorithm( |
375 SignatureAlgorithmId algorithm, | 649 SignatureAlgorithmId algorithm, |
376 DigestAlgorithm digest, | 650 DigestAlgorithm digest, |
377 scoped_ptr<SignatureAlgorithmParameters> params) | 651 scoped_ptr<SignatureAlgorithmParameters> params) |
378 : algorithm_(algorithm), digest_(digest), params_(params.Pass()) { | 652 : algorithm_(algorithm), digest_(digest), params_(params.Pass()) { |
379 } | 653 } |
380 | 654 |
381 } // namespace net | 655 } // namespace net |
OLD | NEW |