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 <memory>
8 #include <utility>
9 
10 #include "base/memory/ptr_util.h"
11 #include "base/numerics/safe_math.h"
12 #include "net/cert/internal/cert_error_params.h"
13 #include "net/cert/internal/cert_errors.h"
14 #include "net/der/input.h"
15 #include "net/der/parse_values.h"
16 #include "net/der/parser.h"
17 #include "third_party/boringssl/src/include/openssl/bytestring.h"
18 #include "third_party/boringssl/src/include/openssl/digest.h"
19 
20 namespace net {
21 
22 namespace {
23 
24 // md2WithRSAEncryption
25 // In dotted notation: 1.2.840.113549.1.1.2
26 const uint8_t kOidMd2WithRsaEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
27                                             0x0d, 0x01, 0x01, 0x02};
28 
29 // md4WithRSAEncryption
30 // In dotted notation: 1.2.840.113549.1.1.3
31 const uint8_t kOidMd4WithRsaEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
32                                             0x0d, 0x01, 0x01, 0x03};
33 
34 // md5WithRSAEncryption
35 // In dotted notation: 1.2.840.113549.1.1.4
36 const uint8_t kOidMd5WithRsaEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
37                                             0x0d, 0x01, 0x01, 0x04};
38 
39 // From RFC 5912:
40 //
41 //     sha1WithRSAEncryption OBJECT IDENTIFIER ::= {
42 //      iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
43 //      pkcs-1(1) 5 }
44 //
45 // In dotted notation: 1.2.840.113549.1.1.5
46 const uint8_t kOidSha1WithRsaEncryption[] =
47     {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05};
48 
49 // sha1WithRSASignature is a deprecated equivalent of
50 // sha1WithRSAEncryption.
51 //
52 // It originates from the NIST Open Systems Environment (OSE)
53 // Implementor's Workshop (OIW).
54 //
55 // It is supported for compatibility with Microsoft's certificate APIs and
56 // tools, particularly makecert.exe, which default(ed/s) to this OID for SHA-1.
57 //
58 // See also: https://bugzilla.mozilla.org/show_bug.cgi?id=1042479
59 //
60 // In dotted notation: 1.3.14.3.2.29
61 const uint8_t kOidSha1WithRsaSignature[] = {0x2b, 0x0e, 0x03, 0x02, 0x1d};
62 
63 // From RFC 5912:
64 //
65 //     pkcs-1  OBJECT IDENTIFIER  ::=
66 //         { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
67 
68 // From RFC 5912:
69 //
70 //     sha256WithRSAEncryption  OBJECT IDENTIFIER  ::=  { pkcs-1 11 }
71 //
72 // In dotted notation: 1.2.840.113549.1.1.11
73 const uint8_t kOidSha256WithRsaEncryption[] =
74     {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b};
75 
76 // From RFC 5912:
77 //
78 //     sha384WithRSAEncryption  OBJECT IDENTIFIER  ::=  { pkcs-1 12 }
79 //
80 // In dotted notation: 1.2.840.113549.1.1.11
81 const uint8_t kOidSha384WithRsaEncryption[] =
82     {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c};
83 
84 // From RFC 5912:
85 //
86 //     sha512WithRSAEncryption  OBJECT IDENTIFIER  ::=  { pkcs-1 13 }
87 //
88 // In dotted notation: 1.2.840.113549.1.1.13
89 const uint8_t kOidSha512WithRsaEncryption[] =
90     {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d};
91 
92 // From RFC 5912:
93 //
94 //     ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
95 //      iso(1) member-body(2) us(840) ansi-X9-62(10045)
96 //      signatures(4) 1 }
97 //
98 // In dotted notation: 1.2.840.10045.4.1
99 const uint8_t kOidEcdsaWithSha1[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01};
100 
101 // From RFC 5912:
102 //
103 //     ecdsa-with-SHA256 OBJECT IDENTIFIER ::= {
104 //      iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
105 //      ecdsa-with-SHA2(3) 2 }
106 //
107 // In dotted notation: 1.2.840.10045.4.3.2
108 const uint8_t kOidEcdsaWithSha256[] =
109     {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02};
110 
111 // From RFC 5912:
112 //
113 //     ecdsa-with-SHA384 OBJECT IDENTIFIER ::= {
114 //      iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
115 //      ecdsa-with-SHA2(3) 3 }
116 //
117 // In dotted notation: 1.2.840.10045.4.3.3
118 const uint8_t kOidEcdsaWithSha384[] =
119     {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03};
120 
121 // From RFC 5912:
122 //
123 //     ecdsa-with-SHA512 OBJECT IDENTIFIER ::= {
124 //      iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
125 //      ecdsa-with-SHA2(3) 4 }
126 //
127 // In dotted notation: 1.2.840.10045.4.3.4
128 const uint8_t kOidEcdsaWithSha512[] =
129     {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04};
130 
131 // From RFC 5912:
132 //
133 //     id-RSASSA-PSS  OBJECT IDENTIFIER  ::=  { pkcs-1 10 }
134 //
135 // In dotted notation: 1.2.840.113549.1.1.10
136 const uint8_t kOidRsaSsaPss[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
137                                  0x0d, 0x01, 0x01, 0x0a};
138 
139 // From RFC 5912:
140 //
141 //     dsa-with-sha1 OBJECT IDENTIFIER ::=  {
142 //      iso(1) member-body(2) us(840) x9-57(10040) x9algorithm(4) 3 }
143 //
144 // In dotted notation: 1.2.840.10040.4.3
145 const uint8_t kOidDsaWithSha1[] = {0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x03};
146 
147 // From RFC 5912:
148 //
149 //     dsa-with-sha256 OBJECT IDENTIFIER  ::=  {
150 //      joint-iso-ccitt(2) country(16) us(840) organization(1) gov(101)
151 //      csor(3) algorithms(4) id-dsa-with-sha2(3) 2 }
152 //
153 // In dotted notation: 2.16.840.1.101.3.4.3.2
154 const uint8_t kOidDsaWithSha256[] = {0x60, 0x86, 0x48, 0x01, 0x65,
155                                      0x03, 0x04, 0x03, 0x02};
156 
157 // From RFC 5912:
158 //
159 //     id-mgf1  OBJECT IDENTIFIER  ::=  { pkcs-1 8 }
160 //
161 // In dotted notation: 1.2.840.113549.1.1.8
162 const uint8_t kOidMgf1[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
163                             0x0d, 0x01, 0x01, 0x08};
164 
165 // RFC 5280 section 4.1.1.2 defines signatureAlgorithm as:
166 //
167 //     AlgorithmIdentifier  ::=  SEQUENCE  {
168 //          algorithm               OBJECT IDENTIFIER,
169 //          parameters              ANY DEFINED BY algorithm OPTIONAL  }
ParseAlgorithmIdentifier(const der::Input & input,der::Input * algorithm,der::Input * parameters)170 WARN_UNUSED_RESULT bool ParseAlgorithmIdentifier(const der::Input& input,
171                                                  der::Input* algorithm,
172                                                  der::Input* parameters) {
173   der::Parser parser(input);
174 
175   der::Parser algorithm_identifier_parser;
176   if (!parser.ReadSequence(&algorithm_identifier_parser))
177     return false;
178 
179   // There shouldn't be anything after the sequence. This is by definition,
180   // as the input to this function is expected to be a single
181   // AlgorithmIdentifier.
182   if (parser.HasMore())
183     return false;
184 
185   if (!algorithm_identifier_parser.ReadTag(der::kOid, algorithm))
186     return false;
187 
188   // Read the optional parameters to a der::Input. The parameters can be at
189   // most one TLV (for instance NULL or a sequence).
190   //
191   // Note that nothing is allowed after the single optional "parameters" TLV.
192   // This is because RFC 5912's notation for AlgorithmIdentifier doesn't
193   // explicitly list an extension point after "parameters".
194   *parameters = der::Input();
195   if (algorithm_identifier_parser.HasMore() &&
196       !algorithm_identifier_parser.ReadRawTLV(parameters)) {
197     return false;
198   }
199   return !algorithm_identifier_parser.HasMore();
200 }
201 
202 // Returns true if |input| is empty.
IsEmpty(const der::Input & input)203 WARN_UNUSED_RESULT bool IsEmpty(const der::Input& input) {
204   return input.Length() == 0;
205 }
206 
207 // Returns true if the entirety of the input is a NULL value.
IsNull(const der::Input & input)208 WARN_UNUSED_RESULT bool IsNull(const der::Input& input) {
209   der::Parser parser(input);
210   der::Input null_value;
211   if (!parser.ReadTag(der::kNull, &null_value))
212     return false;
213 
214   // NULL values are TLV encoded; the value is expected to be empty.
215   if (!IsEmpty(null_value))
216     return false;
217 
218   // By definition of this function, the entire input must be a NULL.
219   return !parser.HasMore();
220 }
221 
222 // Parses an RSA PKCS#1 v1.5 signature algorithm given the DER-encoded
223 // "parameters" from the parsed AlgorithmIdentifier, and the hash algorithm
224 // that was implied by the AlgorithmIdentifier's OID.
225 //
226 // Returns a nullptr on failure.
227 //
228 // RFC 5912 requires that the parameters for RSA PKCS#1 v1.5 algorithms be NULL
229 // ("PARAMS TYPE NULL ARE required"), however an empty parameter is also
230 // allowed for compatibility with non-compliant OCSP responders:
231 //
232 //     sa-rsaWithSHA1 SIGNATURE-ALGORITHM ::= {
233 //      IDENTIFIER sha1WithRSAEncryption
234 //      PARAMS TYPE NULL ARE required
235 //      HASHES { mda-sha1 }
236 //      PUBLIC-KEYS { pk-rsa }
237 //      SMIME-CAPS {IDENTIFIED BY sha1WithRSAEncryption }
238 //     }
239 //
240 //     sa-sha256WithRSAEncryption SIGNATURE-ALGORITHM ::= {
241 //         IDENTIFIER sha256WithRSAEncryption
242 //         PARAMS TYPE NULL ARE required
243 //         HASHES { mda-sha256 }
244 //         PUBLIC-KEYS { pk-rsa }
245 //         SMIME-CAPS { IDENTIFIED BY sha256WithRSAEncryption }
246 //     }
247 //
248 //     sa-sha384WithRSAEncryption SIGNATURE-ALGORITHM ::= {
249 //         IDENTIFIER sha384WithRSAEncryption
250 //         PARAMS TYPE NULL ARE required
251 //         HASHES { mda-sha384 }
252 //         PUBLIC-KEYS { pk-rsa }
253 //         SMIME-CAPS { IDENTIFIED BY sha384WithRSAEncryption }
254 //     }
255 //
256 //     sa-sha512WithRSAEncryption SIGNATURE-ALGORITHM ::= {
257 //         IDENTIFIER sha512WithRSAEncryption
258 //         PARAMS TYPE NULL ARE required
259 //         HASHES { mda-sha512 }
260 //         PUBLIC-KEYS { pk-rsa }
261 //         SMIME-CAPS { IDENTIFIED BY sha512WithRSAEncryption }
262 //     }
ParseRsaPkcs1(DigestAlgorithm digest,const der::Input & params)263 std::unique_ptr<SignatureAlgorithm> ParseRsaPkcs1(DigestAlgorithm digest,
264                                                   const der::Input& params) {
265   // TODO(svaldez): Add warning about non-strict parsing.
266   if (!IsNull(params) && !IsEmpty(params))
267     return nullptr;
268 
269   return SignatureAlgorithm::CreateRsaPkcs1(digest);
270 }
271 
272 // Parses a DSA signature algorithm given the DER-encoded
273 // "parameters" from the parsed AlgorithmIdentifier, and the hash algorithm
274 // that was implied by the AlgorithmIdentifier's OID.
275 //
276 // Returns a nullptr on failure.
277 //
278 // RFC 5912 requires that the parameters for DSA algorithms be absent.
ParseDsa(DigestAlgorithm digest,const der::Input & params)279 std::unique_ptr<SignatureAlgorithm> ParseDsa(DigestAlgorithm digest,
280                                              const der::Input& params) {
281   // TODO(svaldez): Add warning about non-strict parsing.
282   if (!IsNull(params) && !IsEmpty(params))
283     return nullptr;
284 
285   return SignatureAlgorithm::CreateDsa(digest);
286 }
287 
288 // Parses an ECDSA signature algorithm given the DER-encoded "parameters" from
289 // the parsed AlgorithmIdentifier, and the hash algorithm that was implied by
290 // the AlgorithmIdentifier's OID.
291 //
292 // On failure returns a nullptr.
293 //
294 // RFC 5912 requires that the parameters for ECDSA algorithms be absent
295 // ("PARAMS TYPE NULL ARE absent"):
296 //
297 //     sa-ecdsaWithSHA1 SIGNATURE-ALGORITHM ::= {
298 //      IDENTIFIER ecdsa-with-SHA1
299 //      VALUE ECDSA-Sig-Value
300 //      PARAMS TYPE NULL ARE absent
301 //      HASHES { mda-sha1 }
302 //      PUBLIC-KEYS { pk-ec }
303 //      SMIME-CAPS {IDENTIFIED BY ecdsa-with-SHA1 }
304 //     }
305 //
306 //     sa-ecdsaWithSHA256 SIGNATURE-ALGORITHM ::= {
307 //      IDENTIFIER ecdsa-with-SHA256
308 //      VALUE ECDSA-Sig-Value
309 //      PARAMS TYPE NULL ARE absent
310 //      HASHES { mda-sha256 }
311 //      PUBLIC-KEYS { pk-ec }
312 //      SMIME-CAPS { IDENTIFIED BY ecdsa-with-SHA256 }
313 //     }
314 //
315 //     sa-ecdsaWithSHA384 SIGNATURE-ALGORITHM ::= {
316 //      IDENTIFIER ecdsa-with-SHA384
317 //      VALUE ECDSA-Sig-Value
318 //      PARAMS TYPE NULL ARE absent
319 //      HASHES { mda-sha384 }
320 //      PUBLIC-KEYS { pk-ec }
321 //      SMIME-CAPS { IDENTIFIED BY ecdsa-with-SHA384 }
322 //     }
323 //
324 //     sa-ecdsaWithSHA512 SIGNATURE-ALGORITHM ::= {
325 //      IDENTIFIER ecdsa-with-SHA512
326 //      VALUE ECDSA-Sig-Value
327 //      PARAMS TYPE NULL ARE absent
328 //      HASHES { mda-sha512 }
329 //      PUBLIC-KEYS { pk-ec }
330 //      SMIME-CAPS { IDENTIFIED BY ecdsa-with-SHA512 }
331 //     }
ParseEcdsa(DigestAlgorithm digest,const der::Input & params)332 std::unique_ptr<SignatureAlgorithm> ParseEcdsa(DigestAlgorithm digest,
333                                                const der::Input& params) {
334   if (!IsEmpty(params))
335     return nullptr;
336 
337   return SignatureAlgorithm::CreateEcdsa(digest);
338 }
339 
340 // Parses a MaskGenAlgorithm as defined by RFC 5912:
341 //
342 //     MaskGenAlgorithm ::= AlgorithmIdentifier{ALGORITHM,
343 //                             {PKCS1MGFAlgorithms}}
344 //
345 //     mgf1SHA1 MaskGenAlgorithm ::= {
346 //         algorithm id-mgf1,
347 //         parameters HashAlgorithm : sha1Identifier
348 //     }
349 //
350 //     --
351 //     --  Define the set of mask generation functions
352 //     --
353 //     --  If the identifier is id-mgf1, any of the listed hash
354 //     --    algorithms may be used.
355 //     --
356 //
357 //     PKCS1MGFAlgorithms ALGORITHM ::= {
358 //         { IDENTIFIER id-mgf1 PARAMS TYPE HashAlgorithm ARE required },
359 //         ...
360 //     }
361 //
362 // Note that the possible mask gen algorithms is extensible. However at present
363 // the only function supported is MGF1, as that is the singular mask gen
364 // function defined by RFC 4055 / RFC 5912.
ParseMaskGenAlgorithm(const der::Input input,DigestAlgorithm * mgf1_hash)365 WARN_UNUSED_RESULT bool ParseMaskGenAlgorithm(const der::Input input,
366                                               DigestAlgorithm* mgf1_hash) {
367   der::Input oid;
368   der::Input params;
369   if (!ParseAlgorithmIdentifier(input, &oid, &params))
370     return false;
371 
372   // MGF1 is the only supported mask generation algorithm.
373   if (oid != der::Input(kOidMgf1))
374     return false;
375 
376   return ParseHashAlgorithm(params, mgf1_hash);
377 }
378 
379 // Consumes an optional, explicitly-tagged INTEGER from |parser|, using the
380 // indicated context-specific class number. Values greater than 32-bits will be
381 // rejected.
382 //
383 // Returns true on success and sets |*present| to true if the field was present.
ReadOptionalContextSpecificUint32(der::Parser * parser,uint8_t class_number,uint32_t * out,bool * present)384 WARN_UNUSED_RESULT bool ReadOptionalContextSpecificUint32(der::Parser* parser,
385                                                           uint8_t class_number,
386                                                           uint32_t* out,
387                                                           bool* present) {
388   der::Input value;
389   bool has_value;
390 
391   // Read the context specific value.
392   if (!parser->ReadOptionalTag(der::ContextSpecificConstructed(class_number),
393                                &value, &has_value)) {
394     return false;
395   }
396 
397   if (has_value) {
398     // Parse the integer contained in it.
399     der::Parser number_parser(value);
400     uint64_t uint64_value;
401 
402     if (!number_parser.ReadUint64(&uint64_value))
403       return false;
404     if (number_parser.HasMore())
405       return false;
406 
407     // Cast the number to a uint32_t
408     base::CheckedNumeric<uint32_t> casted(uint64_value);
409     if (!casted.IsValid())
410       return false;
411     *out = casted.ValueOrDie();
412   }
413 
414   *present = has_value;
415   return true;
416 }
417 
418 // Parses the parameters for an RSASSA-PSS signature algorithm, as defined by
419 // RFC 5912:
420 //
421 //     sa-rsaSSA-PSS SIGNATURE-ALGORITHM ::= {
422 //         IDENTIFIER id-RSASSA-PSS
423 //         PARAMS TYPE RSASSA-PSS-params ARE required
424 //         HASHES { mda-sha1 | mda-sha224 | mda-sha256 | mda-sha384
425 //                      | mda-sha512 }
426 //         PUBLIC-KEYS { pk-rsa | pk-rsaSSA-PSS }
427 //         SMIME-CAPS { IDENTIFIED BY id-RSASSA-PSS }
428 //     }
429 //
430 //     RSASSA-PSS-params  ::=  SEQUENCE  {
431 //         hashAlgorithm     [0] HashAlgorithm DEFAULT sha1Identifier,
432 //         maskGenAlgorithm  [1] MaskGenAlgorithm DEFAULT mgf1SHA1,
433 //         saltLength        [2] INTEGER DEFAULT 20,
434 //         trailerField      [3] INTEGER DEFAULT 1
435 //     }
436 //
437 // Which is to say the parameters MUST be present, and of type
438 // RSASSA-PSS-params.
ParseRsaPss(const der::Input & params)439 std::unique_ptr<SignatureAlgorithm> ParseRsaPss(const der::Input& params) {
440   der::Parser parser(params);
441   der::Parser params_parser;
442   if (!parser.ReadSequence(&params_parser))
443     return nullptr;
444 
445   // There shouldn't be anything after the sequence (by definition the
446   // parameters is a single sequence).
447   if (parser.HasMore())
448     return nullptr;
449 
450   bool has_field;
451   der::Input field;
452 
453   // Parse:
454   //     hashAlgorithm     [0] HashAlgorithm DEFAULT sha1Identifier,
455   DigestAlgorithm hash = DigestAlgorithm::Sha1;
456   if (!params_parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &field,
457                                      &has_field)) {
458     return nullptr;
459   }
460   if (has_field && !ParseHashAlgorithm(field, &hash))
461     return nullptr;
462 
463   // Parse:
464   //     maskGenAlgorithm  [1] MaskGenAlgorithm DEFAULT mgf1SHA1,
465   DigestAlgorithm mgf1_hash = DigestAlgorithm::Sha1;
466   if (!params_parser.ReadOptionalTag(der::ContextSpecificConstructed(1), &field,
467                                      &has_field)) {
468     return nullptr;
469   }
470   if (has_field && !ParseMaskGenAlgorithm(field, &mgf1_hash))
471     return nullptr;
472 
473   // Parse:
474   //     saltLength        [2] INTEGER DEFAULT 20,
475   uint32_t salt_length = 20u;
476   if (!ReadOptionalContextSpecificUint32(&params_parser, 2, &salt_length,
477                                          &has_field)) {
478     return nullptr;
479   }
480 
481   // Parse:
482   //     trailerField      [3] INTEGER DEFAULT 1
483   uint32_t trailer_field = 1u;
484   if (!ReadOptionalContextSpecificUint32(&params_parser, 3, &trailer_field,
485                                          &has_field)) {
486     return nullptr;
487   }
488 
489   // RFC 4055 says that the trailer field must be 1:
490   //
491   //     The trailerField field is an integer.  It provides
492   //     compatibility with IEEE Std 1363a-2004 [P1363A].  The value
493   //     MUST be 1, which represents the trailer field with hexadecimal
494   //     value 0xBC.  Other trailer fields, including the trailer field
495   //     composed of HashID concatenated with 0xCC that is specified in
496   //     IEEE Std 1363a, are not supported.  Implementations that
497   //     perform signature generation MUST omit the trailerField field,
498   //     indicating that the default trailer field value was used.
499   //     Implementations that perform signature validation MUST
500   //     recognize both a present trailerField field with value 1 and an
501   //     absent trailerField field.
502   if (trailer_field != 1)
503     return nullptr;
504 
505   // There must not be any unconsumed data left. (RFC 5912 does not explicitly
506   // include an extensibility point for RSASSA-PSS-params)
507   if (params_parser.HasMore())
508     return nullptr;
509 
510   return SignatureAlgorithm::CreateRsaPss(hash, mgf1_hash, salt_length);
511 }
512 
513 DEFINE_CERT_ERROR_ID(kUnknownAlgorithmIdentifierOid,
514                      "Unknown AlgorithmIdentifier OID");
515 
516 }  // namespace
517 
ParseHashAlgorithm(const der::Input & input,DigestAlgorithm * out)518 WARN_UNUSED_RESULT bool ParseHashAlgorithm(const der::Input& input,
519                                            DigestAlgorithm* out) {
520   CBS cbs;
521   CBS_init(&cbs, input.UnsafeData(), input.Length());
522   const EVP_MD* md = EVP_parse_digest_algorithm(&cbs);
523 
524   if (md == EVP_sha1()) {
525     *out = DigestAlgorithm::Sha1;
526   } else if (md == EVP_sha256()) {
527     *out = DigestAlgorithm::Sha256;
528   } else if (md == EVP_sha384()) {
529     *out = DigestAlgorithm::Sha384;
530   } else if (md == EVP_sha512()) {
531     *out = DigestAlgorithm::Sha512;
532   } else {
533     // TODO(eroman): Support MD2, MD4, MD5 for completeness?
534     // Unsupported digest algorithm.
535     return false;
536   }
537 
538   return true;
539 }
540 
RsaPssParameters(DigestAlgorithm mgf1_hash,uint32_t salt_length)541 RsaPssParameters::RsaPssParameters(DigestAlgorithm mgf1_hash,
542                                    uint32_t salt_length)
543     : mgf1_hash_(mgf1_hash), salt_length_(salt_length) {
544 }
545 
546 SignatureAlgorithm::~SignatureAlgorithm() = default;
547 
Create(const der::Input & algorithm_identifier,CertErrors * errors)548 std::unique_ptr<SignatureAlgorithm> SignatureAlgorithm::Create(
549     const der::Input& algorithm_identifier,
550     CertErrors* errors) {
551   // TODO(crbug.com/634443): Add useful error information.
552 
553   der::Input oid;
554   der::Input params;
555   if (!ParseAlgorithmIdentifier(algorithm_identifier, &oid, &params))
556     return nullptr;
557 
558   // TODO(eroman): Each OID is tested for equality in order, which is not
559   // particularly efficient.
560 
561   if (oid == der::Input(kOidSha1WithRsaEncryption))
562     return ParseRsaPkcs1(DigestAlgorithm::Sha1, params);
563 
564   if (oid == der::Input(kOidSha256WithRsaEncryption))
565     return ParseRsaPkcs1(DigestAlgorithm::Sha256, params);
566 
567   if (oid == der::Input(kOidSha384WithRsaEncryption))
568     return ParseRsaPkcs1(DigestAlgorithm::Sha384, params);
569 
570   if (oid == der::Input(kOidSha512WithRsaEncryption))
571     return ParseRsaPkcs1(DigestAlgorithm::Sha512, params);
572 
573   if (oid == der::Input(kOidEcdsaWithSha1))
574     return ParseEcdsa(DigestAlgorithm::Sha1, params);
575 
576   if (oid == der::Input(kOidEcdsaWithSha256))
577     return ParseEcdsa(DigestAlgorithm::Sha256, params);
578 
579   if (oid == der::Input(kOidEcdsaWithSha384))
580     return ParseEcdsa(DigestAlgorithm::Sha384, params);
581 
582   if (oid == der::Input(kOidEcdsaWithSha512))
583     return ParseEcdsa(DigestAlgorithm::Sha512, params);
584 
585   if (oid == der::Input(kOidRsaSsaPss))
586     return ParseRsaPss(params);
587 
588   if (oid == der::Input(kOidSha1WithRsaSignature))
589     return ParseRsaPkcs1(DigestAlgorithm::Sha1, params);
590 
591   if (oid == der::Input(kOidMd2WithRsaEncryption))
592     return ParseRsaPkcs1(DigestAlgorithm::Md2, params);
593 
594   if (oid == der::Input(kOidMd4WithRsaEncryption))
595     return ParseRsaPkcs1(DigestAlgorithm::Md4, params);
596 
597   if (oid == der::Input(kOidMd5WithRsaEncryption))
598     return ParseRsaPkcs1(DigestAlgorithm::Md5, params);
599 
600   if (oid == der::Input(kOidDsaWithSha1))
601     return ParseDsa(DigestAlgorithm::Sha1, params);
602 
603   if (oid == der::Input(kOidDsaWithSha256))
604     return ParseDsa(DigestAlgorithm::Sha256, params);
605 
606   // Unknown OID.
607   if (errors) {
608     errors->AddError(kUnknownAlgorithmIdentifierOid,
609                      CreateCertErrorParams2Der("oid", oid, "params", params));
610   }
611   return nullptr;
612 }
613 
CreateRsaPkcs1(DigestAlgorithm digest)614 std::unique_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateRsaPkcs1(
615     DigestAlgorithm digest) {
616   return base::WrapUnique(
617       new SignatureAlgorithm(SignatureAlgorithmId::RsaPkcs1, digest, nullptr));
618 }
619 
CreateDsa(DigestAlgorithm digest)620 std::unique_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateDsa(
621     DigestAlgorithm digest) {
622   return base::WrapUnique(
623       new SignatureAlgorithm(SignatureAlgorithmId::Dsa, digest, nullptr));
624 }
625 
CreateEcdsa(DigestAlgorithm digest)626 std::unique_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateEcdsa(
627     DigestAlgorithm digest) {
628   return base::WrapUnique(
629       new SignatureAlgorithm(SignatureAlgorithmId::Ecdsa, digest, nullptr));
630 }
631 
CreateRsaPss(DigestAlgorithm digest,DigestAlgorithm mgf1_hash,uint32_t salt_length)632 std::unique_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateRsaPss(
633     DigestAlgorithm digest,
634     DigestAlgorithm mgf1_hash,
635     uint32_t salt_length) {
636   return base::WrapUnique(new SignatureAlgorithm(
637       SignatureAlgorithmId::RsaPss, digest,
638       std::make_unique<RsaPssParameters>(mgf1_hash, salt_length)));
639 }
640 
ParamsForRsaPss() const641 const RsaPssParameters* SignatureAlgorithm::ParamsForRsaPss() const {
642   if (algorithm_ == SignatureAlgorithmId::RsaPss)
643     return static_cast<RsaPssParameters*>(params_.get());
644   return nullptr;
645 }
646 
IsEquivalent(const der::Input & alg1_tlv,const der::Input & alg2_tlv)647 bool SignatureAlgorithm::IsEquivalent(const der::Input& alg1_tlv,
648                                       const der::Input& alg2_tlv) {
649   if (alg1_tlv == alg2_tlv)
650     return true;
651 
652   std::unique_ptr<SignatureAlgorithm> alg1 = Create(alg1_tlv, nullptr);
653   std::unique_ptr<SignatureAlgorithm> alg2 = Create(alg2_tlv, nullptr);
654 
655   // Do checks that apply to all algorithms.
656   if (!alg1 || !alg2 || (alg1->algorithm() != alg2->algorithm()) ||
657       (alg1->digest() != alg2->digest())) {
658     return false;
659   }
660 
661   // Check algorithm-specific parameters for equality.
662   switch (alg1->algorithm()) {
663     case SignatureAlgorithmId::RsaPkcs1:
664     case SignatureAlgorithmId::Ecdsa:
665     case SignatureAlgorithmId::Dsa:
666       DCHECK(!alg1->has_params());
667       DCHECK(!alg2->has_params());
668       return true;
669     case SignatureAlgorithmId::RsaPss: {
670       const RsaPssParameters* params1 = alg1->ParamsForRsaPss();
671       const RsaPssParameters* params2 = alg2->ParamsForRsaPss();
672       return params1 && params2 &&
673              (params1->salt_length() == params2->salt_length()) &&
674              (params1->mgf1_hash() == params2->mgf1_hash());
675     }
676   }
677 
678   return false;
679 }
680 
SignatureAlgorithm(SignatureAlgorithmId algorithm,DigestAlgorithm digest,std::unique_ptr<SignatureAlgorithmParameters> params)681 SignatureAlgorithm::SignatureAlgorithm(
682     SignatureAlgorithmId algorithm,
683     DigestAlgorithm digest,
684     std::unique_ptr<SignatureAlgorithmParameters> params)
685     : algorithm_(algorithm), digest_(digest), params_(std::move(params)) {}
686 
687 }  // namespace net
688