Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / net / cert / internal / signature_algorithm.cc
blob468fa16c3a62b8d8eb84fdbedabf6648ecff606f
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.
5 #include "net/cert/internal/signature_algorithm.h"
7 #include "base/numerics/safe_math.h"
8 #include "net/der/input.h"
9 #include "net/der/parse_values.h"
10 #include "net/der/parser.h"
12 namespace net {
14 namespace {
16 // From RFC 5912:
18 // sha1WithRSAEncryption OBJECT IDENTIFIER ::= {
19 // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
20 // pkcs-1(1) 5 }
22 // In dotted notation: 1.2.840.113549.1.1.5
23 const uint8_t kOidSha1WithRsaEncryption[] =
24 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05};
26 // sha1WithRSASignature is a deprecated equivalent of
27 // sha1WithRSAEncryption.
29 // It originates from the NIST Open Systems Environment (OSE)
30 // Implementor's Workshop (OIW).
32 // It is supported for compatibility with Microsoft's certificate APIs and
33 // tools, particularly makecert.exe, which default(ed/s) to this OID for SHA-1.
35 // See also: https://bugzilla.mozilla.org/show_bug.cgi?id=1042479
37 // In dotted notation: 1.3.14.3.2.29
38 const uint8_t kOidSha1WithRsaSignature[] = {0x2b, 0x0e, 0x03, 0x02, 0x1d};
40 // From RFC 5912:
42 // pkcs-1 OBJECT IDENTIFIER ::=
43 // { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
45 // From RFC 5912:
47 // sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 }
49 // In dotted notation: 1.2.840.113549.1.1.11
50 const uint8_t kOidSha256WithRsaEncryption[] =
51 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b};
53 // From RFC 5912:
55 // sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 }
57 // In dotted notation: 1.2.840.113549.1.1.11
58 const uint8_t kOidSha384WithRsaEncryption[] =
59 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c};
61 // From RFC 5912:
63 // sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 }
65 // In dotted notation: 1.2.840.113549.1.1.13
66 const uint8_t kOidSha512WithRsaEncryption[] =
67 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d};
69 // From RFC 5912:
71 // ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
72 // iso(1) member-body(2) us(840) ansi-X9-62(10045)
73 // signatures(4) 1 }
75 // In dotted notation: 1.2.840.10045.4.1
76 const uint8_t kOidEcdsaWithSha1[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01};
78 // From RFC 5912:
80 // ecdsa-with-SHA256 OBJECT IDENTIFIER ::= {
81 // iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
82 // ecdsa-with-SHA2(3) 2 }
84 // In dotted notation: 1.2.840.10045.4.3.2
85 const uint8_t kOidEcdsaWithSha256[] =
86 {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02};
88 // From RFC 5912:
90 // ecdsa-with-SHA384 OBJECT IDENTIFIER ::= {
91 // iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
92 // ecdsa-with-SHA2(3) 3 }
94 // In dotted notation: 1.2.840.10045.4.3.3
95 const uint8_t kOidEcdsaWithSha384[] =
96 {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03};
98 // From RFC 5912:
100 // ecdsa-with-SHA512 OBJECT IDENTIFIER ::= {
101 // iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
102 // ecdsa-with-SHA2(3) 4 }
104 // In dotted notation: 1.2.840.10045.4.3.4
105 const uint8_t kOidEcdsaWithSha512[] =
106 {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04};
108 // From RFC 5912:
110 // id-RSASSA-PSS OBJECT IDENTIFIER ::= { pkcs-1 10 }
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};
116 // From RFC 5912:
118 // id-sha1 OBJECT IDENTIFIER ::= {
119 // iso(1) identified-organization(3) oiw(14) secsig(3)
120 // algorithm(2) 26 }
122 // In dotted notation: 1.3.14.3.2.26
123 const uint8_t kOidSha1[] = {0x2B, 0x0E, 0x03, 0x02, 0x1A};
125 // From RFC 5912:
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 }
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};
135 // From RFC 5912:
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 }
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};
145 // From RFC 5912:
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 }
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};
155 // From RFC 5912:
157 // id-mgf1 OBJECT IDENTIFIER ::= { pkcs-1 8 }
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};
163 // RFC 5280 section 4.1.1.2 defines signatureAlgorithm as:
165 // AlgorithmIdentifier ::= SEQUENCE {
166 // algorithm OBJECT IDENTIFIER,
167 // parameters ANY DEFINED BY algorithm OPTIONAL }
168 WARN_UNUSED_RESULT bool ParseAlgorithmIdentifier(const der::Input& input,
169 der::Input* algorithm,
170 der::Input* parameters) {
171 der::Parser parser(input);
173 der::Parser algorithm_identifier_parser;
174 if (!parser.ReadSequence(&algorithm_identifier_parser))
175 return false;
177 // There shouldn't be anything after the sequence. This is by definition,
178 // as the input to this function is expected to be a single
179 // AlgorithmIdentifier.
180 if (parser.HasMore())
181 return false;
183 if (!algorithm_identifier_parser.ReadTag(der::kOid, algorithm))
184 return false;
186 // Read the optional parameters to a der::Input. The parameters can be at
187 // most one TLV (for instance NULL or a sequence).
189 // Note that nothing is allowed after the single optional "parameters" TLV.
190 // This is because RFC 5912's notation for AlgorithmIdentifier doesn't
191 // explicitly list an extension point after "parameters".
192 *parameters = der::Input();
193 if (algorithm_identifier_parser.HasMore() &&
194 !algorithm_identifier_parser.ReadRawTLV(parameters)) {
195 return false;
197 return !algorithm_identifier_parser.HasMore();
200 // Returns true if |input| is empty.
201 WARN_UNUSED_RESULT bool IsEmpty(const der::Input& input) {
202 return input.Length() == 0;
205 // Returns true if the entirety of the input is a NULL value.
206 WARN_UNUSED_RESULT bool IsNull(const der::Input& input) {
207 der::Parser parser(input);
208 der::Input null_value;
209 if (!parser.ReadTag(der::kNull, &null_value))
210 return false;
212 // NULL values are TLV encoded; the value is expected to be empty.
213 if (!IsEmpty(null_value))
214 return false;
216 // By definition of this function, the entire input must be a NULL.
217 return !parser.HasMore();
220 // Parses an RSA PKCS#1 v1.5 signature algorithm given the DER-encoded
221 // "parameters" from the parsed AlgorithmIdentifier, and the hash algorithm
222 // that was implied by the AlgorithmIdentifier's OID.
224 // Returns a nullptr on failure.
226 // RFC 5912 requires that the parameters for RSA PKCS#1 v1.5 algorithms be NULL
227 // ("PARAMS TYPE NULL ARE required"):
229 // sa-rsaWithSHA1 SIGNATURE-ALGORITHM ::= {
230 // IDENTIFIER sha1WithRSAEncryption
231 // PARAMS TYPE NULL ARE required
232 // HASHES { mda-sha1 }
233 // PUBLIC-KEYS { pk-rsa }
234 // SMIME-CAPS {IDENTIFIED BY sha1WithRSAEncryption }
235 // }
237 // sa-sha256WithRSAEncryption SIGNATURE-ALGORITHM ::= {
238 // IDENTIFIER sha256WithRSAEncryption
239 // PARAMS TYPE NULL ARE required
240 // HASHES { mda-sha256 }
241 // PUBLIC-KEYS { pk-rsa }
242 // SMIME-CAPS { IDENTIFIED BY sha256WithRSAEncryption }
243 // }
245 // sa-sha384WithRSAEncryption SIGNATURE-ALGORITHM ::= {
246 // IDENTIFIER sha384WithRSAEncryption
247 // PARAMS TYPE NULL ARE required
248 // HASHES { mda-sha384 }
249 // PUBLIC-KEYS { pk-rsa }
250 // SMIME-CAPS { IDENTIFIED BY sha384WithRSAEncryption }
251 // }
253 // sa-sha512WithRSAEncryption SIGNATURE-ALGORITHM ::= {
254 // IDENTIFIER sha512WithRSAEncryption
255 // PARAMS TYPE NULL ARE required
256 // HASHES { mda-sha512 }
257 // PUBLIC-KEYS { pk-rsa }
258 // SMIME-CAPS { IDENTIFIED BY sha512WithRSAEncryption }
259 // }
260 scoped_ptr<SignatureAlgorithm> ParseRsaPkcs1(DigestAlgorithm digest,
261 const der::Input& params) {
262 if (!IsNull(params))
263 return nullptr;
265 return SignatureAlgorithm::CreateRsaPkcs1(digest);
268 // Parses an ECDSA signature algorithm given the DER-encoded "parameters" from
269 // the parsed AlgorithmIdentifier, and the hash algorithm that was implied by
270 // the AlgorithmIdentifier's OID.
272 // On failure returns a nullptr.
274 // RFC 5912 requires that the parameters for ECDSA algorithms be absent
275 // ("PARAMS TYPE NULL ARE absent"):
277 // sa-ecdsaWithSHA1 SIGNATURE-ALGORITHM ::= {
278 // IDENTIFIER ecdsa-with-SHA1
279 // VALUE ECDSA-Sig-Value
280 // PARAMS TYPE NULL ARE absent
281 // HASHES { mda-sha1 }
282 // PUBLIC-KEYS { pk-ec }
283 // SMIME-CAPS {IDENTIFIED BY ecdsa-with-SHA1 }
284 // }
286 // sa-ecdsaWithSHA256 SIGNATURE-ALGORITHM ::= {
287 // IDENTIFIER ecdsa-with-SHA256
288 // VALUE ECDSA-Sig-Value
289 // PARAMS TYPE NULL ARE absent
290 // HASHES { mda-sha256 }
291 // PUBLIC-KEYS { pk-ec }
292 // SMIME-CAPS { IDENTIFIED BY ecdsa-with-SHA256 }
293 // }
295 // sa-ecdsaWithSHA384 SIGNATURE-ALGORITHM ::= {
296 // IDENTIFIER ecdsa-with-SHA384
297 // VALUE ECDSA-Sig-Value
298 // PARAMS TYPE NULL ARE absent
299 // HASHES { mda-sha384 }
300 // PUBLIC-KEYS { pk-ec }
301 // SMIME-CAPS { IDENTIFIED BY ecdsa-with-SHA384 }
302 // }
304 // sa-ecdsaWithSHA512 SIGNATURE-ALGORITHM ::= {
305 // IDENTIFIER ecdsa-with-SHA512
306 // VALUE ECDSA-Sig-Value
307 // PARAMS TYPE NULL ARE absent
308 // HASHES { mda-sha512 }
309 // PUBLIC-KEYS { pk-ec }
310 // SMIME-CAPS { IDENTIFIED BY ecdsa-with-SHA512 }
311 // }
312 scoped_ptr<SignatureAlgorithm> ParseEcdsa(DigestAlgorithm digest,
313 const der::Input& params) {
314 if (!IsEmpty(params))
315 return nullptr;
317 return SignatureAlgorithm::CreateEcdsa(digest);
320 // Parses a HashAlgorithm as defined by RFC 5912:
322 // HashAlgorithm ::= AlgorithmIdentifier{DIGEST-ALGORITHM,
323 // {HashAlgorithms}}
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, &params))
337 return false;
339 DigestAlgorithm hash;
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;
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;
359 *out = hash;
360 return true;
363 // Parses a MaskGenAlgorithm as defined by RFC 5912:
365 // MaskGenAlgorithm ::= AlgorithmIdentifier{ALGORITHM,
366 // {PKCS1MGFAlgorithms}}
368 // mgf1SHA1 MaskGenAlgorithm ::= {
369 // algorithm id-mgf1,
370 // parameters HashAlgorithm : sha1Identifier
371 // }
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 // --
380 // PKCS1MGFAlgorithms ALGORITHM ::= {
381 // { IDENTIFIER id-mgf1 PARAMS TYPE HashAlgorithm ARE required },
382 // ...
383 // }
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, &params))
393 return false;
395 // MGF1 is the only supported mask generation algorithm.
396 if (!oid.Equals(der::Input(kOidMgf1)))
397 return false;
399 return ParseHashAlgorithm(params, mgf1_hash);
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.
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;
414 // Read the context specific value.
415 if (!parser->ReadOptionalTag(der::ContextSpecificConstructed(class_number),
416 &value, &has_value)) {
417 return false;
420 if (has_value) {
421 // Parse the integer contained in it.
422 der::Parser number_parser(value);
423 uint64_t uint64_value;
425 if (!number_parser.ReadUint64(&uint64_value))
426 return false;
427 if (number_parser.HasMore())
428 return false;
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();
437 *present = has_value;
438 return true;
441 // Parses the parameters for an RSASSA-PSS signature algorithm, as defined by
442 // RFC 5912:
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 // }
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 // }
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(&params_parser))
466 return nullptr;
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;
473 bool has_field;
474 der::Input field;
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;
483 if (has_field && !ParseHashAlgorithm(field, &hash))
484 return nullptr;
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;
493 if (has_field && !ParseMaskGenAlgorithm(field, &mgf1_hash))
494 return nullptr;
496 // Parse:
497 // saltLength [2] INTEGER DEFAULT 20,
498 uint32_t salt_length = 20u;
499 if (!ReadOptionalContextSpecificUint32(&params_parser, 2, &salt_length,
500 &has_field)) {
501 return nullptr;
504 // Parse:
505 // trailerField [3] INTEGER DEFAULT 1
506 uint32_t trailer_field = 1u;
507 if (!ReadOptionalContextSpecificUint32(&params_parser, 3, &trailer_field,
508 &has_field)) {
509 return nullptr;
512 // RFC 4055 says that the trailer field must be 1:
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;
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;
533 return SignatureAlgorithm::CreateRsaPss(hash, mgf1_hash, salt_length);
536 } // namespace
538 RsaPssParameters::RsaPssParameters(DigestAlgorithm mgf1_hash,
539 uint32_t salt_length)
540 : mgf1_hash_(mgf1_hash), salt_length_(salt_length) {
543 bool RsaPssParameters::Equals(const RsaPssParameters* other) const {
544 return mgf1_hash_ == other->mgf1_hash_ && salt_length_ == other->salt_length_;
547 SignatureAlgorithm::~SignatureAlgorithm() {
550 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateFromDer(
551 const der::Input& algorithm_identifier) {
552 der::Input oid;
553 der::Input params;
554 if (!ParseAlgorithmIdentifier(algorithm_identifier, &oid, &params))
555 return nullptr;
557 // TODO(eroman): Each OID is tested for equality in order, which is not
558 // particularly efficient.
560 if (oid.Equals(der::Input(kOidSha1WithRsaEncryption)))
561 return ParseRsaPkcs1(DigestAlgorithm::Sha1, params);
563 if (oid.Equals(der::Input(kOidSha256WithRsaEncryption)))
564 return ParseRsaPkcs1(DigestAlgorithm::Sha256, params);
566 if (oid.Equals(der::Input(kOidSha384WithRsaEncryption)))
567 return ParseRsaPkcs1(DigestAlgorithm::Sha384, params);
569 if (oid.Equals(der::Input(kOidSha512WithRsaEncryption)))
570 return ParseRsaPkcs1(DigestAlgorithm::Sha512, params);
572 if (oid.Equals(der::Input(kOidEcdsaWithSha1)))
573 return ParseEcdsa(DigestAlgorithm::Sha1, params);
575 if (oid.Equals(der::Input(kOidEcdsaWithSha256)))
576 return ParseEcdsa(DigestAlgorithm::Sha256, params);
578 if (oid.Equals(der::Input(kOidEcdsaWithSha384)))
579 return ParseEcdsa(DigestAlgorithm::Sha384, params);
581 if (oid.Equals(der::Input(kOidEcdsaWithSha512)))
582 return ParseEcdsa(DigestAlgorithm::Sha512, params);
584 if (oid.Equals(der::Input(kOidRsaSsaPss)))
585 return ParseRsaPss(params);
587 if (oid.Equals(der::Input(kOidSha1WithRsaSignature)))
588 return ParseRsaPkcs1(DigestAlgorithm::Sha1, params);
590 return nullptr; // Unsupported OID.
593 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateRsaPkcs1(
594 DigestAlgorithm digest) {
595 return make_scoped_ptr(
596 new SignatureAlgorithm(SignatureAlgorithmId::RsaPkcs1, digest, nullptr));
599 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateEcdsa(
600 DigestAlgorithm digest) {
601 return make_scoped_ptr(
602 new SignatureAlgorithm(SignatureAlgorithmId::Ecdsa, digest, nullptr));
605 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateRsaPss(
606 DigestAlgorithm digest,
607 DigestAlgorithm mgf1_hash,
608 uint32_t salt_length) {
609 return make_scoped_ptr(new SignatureAlgorithm(
610 SignatureAlgorithmId::RsaPss, digest,
611 make_scoped_ptr(new RsaPssParameters(mgf1_hash, salt_length))));
614 bool SignatureAlgorithm::Equals(const SignatureAlgorithm& other) const {
615 if (algorithm_ != other.algorithm_)
616 return false;
618 if (digest_ != other.digest_)
619 return false;
621 // Check that the parameters are equal.
622 switch (algorithm_) {
623 case SignatureAlgorithmId::RsaPss: {
624 const RsaPssParameters* params1 = ParamsForRsaPss();
625 const RsaPssParameters* params2 = other.ParamsForRsaPss();
626 if (!params1 || !params2 || !params1->Equals(params2))
627 return false;
628 break;
631 // There shouldn't be any parameters.
632 case SignatureAlgorithmId::RsaPkcs1:
633 case SignatureAlgorithmId::Ecdsa:
634 if (params_ || other.params_)
635 return false;
636 break;
639 return true;
642 const RsaPssParameters* SignatureAlgorithm::ParamsForRsaPss() const {
643 if (algorithm_ == SignatureAlgorithmId::RsaPss)
644 return static_cast<RsaPssParameters*>(params_.get());
645 return nullptr;
648 SignatureAlgorithm::SignatureAlgorithm(
649 SignatureAlgorithmId algorithm,
650 DigestAlgorithm digest,
651 scoped_ptr<SignatureAlgorithmParameters> params)
652 : algorithm_(algorithm), digest_(digest), params_(params.Pass()) {
655 } // namespace net