xref: /aosp_15_r20/external/cronet/third_party/boringssl/src/pki/signature_algorithm.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2015 The Chromium Authors
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 "signature_algorithm.h"
6 
7 #include <openssl/bytestring.h>
8 #include <openssl/digest.h>
9 
10 #include "input.h"
11 #include "parse_values.h"
12 #include "parser.h"
13 
14 namespace bssl {
15 
16 namespace {
17 
18 // From RFC 5912:
19 //
20 //     sha1WithRSAEncryption OBJECT IDENTIFIER ::= {
21 //      iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
22 //      pkcs-1(1) 5 }
23 //
24 // In dotted notation: 1.2.840.113549.1.1.5
25 const uint8_t kOidSha1WithRsaEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
26                                              0x0d, 0x01, 0x01, 0x05};
27 
28 // sha1WithRSASignature is a deprecated equivalent of
29 // sha1WithRSAEncryption.
30 //
31 // It originates from the NIST Open Systems Environment (OSE)
32 // Implementor's Workshop (OIW).
33 //
34 // It is supported for compatibility with Microsoft's certificate APIs and
35 // tools, particularly makecert.exe, which default(ed/s) to this OID for SHA-1.
36 //
37 // See also: https://bugzilla.mozilla.org/show_bug.cgi?id=1042479
38 //
39 // In dotted notation: 1.3.14.3.2.29
40 const uint8_t kOidSha1WithRsaSignature[] = {0x2b, 0x0e, 0x03, 0x02, 0x1d};
41 
42 // From RFC 5912:
43 //
44 //     pkcs-1  OBJECT IDENTIFIER  ::=
45 //         { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
46 
47 // From RFC 5912:
48 //
49 //     sha256WithRSAEncryption  OBJECT IDENTIFIER  ::=  { pkcs-1 11 }
50 //
51 // In dotted notation: 1.2.840.113549.1.1.11
52 const uint8_t kOidSha256WithRsaEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
53                                                0x0d, 0x01, 0x01, 0x0b};
54 
55 // From RFC 5912:
56 //
57 //     sha384WithRSAEncryption  OBJECT IDENTIFIER  ::=  { pkcs-1 12 }
58 //
59 // In dotted notation: 1.2.840.113549.1.1.11
60 const uint8_t kOidSha384WithRsaEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
61                                                0x0d, 0x01, 0x01, 0x0c};
62 
63 // From RFC 5912:
64 //
65 //     sha512WithRSAEncryption  OBJECT IDENTIFIER  ::=  { pkcs-1 13 }
66 //
67 // In dotted notation: 1.2.840.113549.1.1.13
68 const uint8_t kOidSha512WithRsaEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
69                                                0x0d, 0x01, 0x01, 0x0d};
70 
71 // From RFC 5912:
72 //
73 //     ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
74 //      iso(1) member-body(2) us(840) ansi-X9-62(10045)
75 //      signatures(4) 1 }
76 //
77 // In dotted notation: 1.2.840.10045.4.1
78 const uint8_t kOidEcdsaWithSha1[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01};
79 
80 // From RFC 5912:
81 //
82 //     ecdsa-with-SHA256 OBJECT IDENTIFIER ::= {
83 //      iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
84 //      ecdsa-with-SHA2(3) 2 }
85 //
86 // In dotted notation: 1.2.840.10045.4.3.2
87 const uint8_t kOidEcdsaWithSha256[] = {0x2a, 0x86, 0x48, 0xce,
88                                        0x3d, 0x04, 0x03, 0x02};
89 
90 // From RFC 5912:
91 //
92 //     ecdsa-with-SHA384 OBJECT IDENTIFIER ::= {
93 //      iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
94 //      ecdsa-with-SHA2(3) 3 }
95 //
96 // In dotted notation: 1.2.840.10045.4.3.3
97 const uint8_t kOidEcdsaWithSha384[] = {0x2a, 0x86, 0x48, 0xce,
98                                        0x3d, 0x04, 0x03, 0x03};
99 
100 // From RFC 5912:
101 //
102 //     ecdsa-with-SHA512 OBJECT IDENTIFIER ::= {
103 //      iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
104 //      ecdsa-with-SHA2(3) 4 }
105 //
106 // In dotted notation: 1.2.840.10045.4.3.4
107 const uint8_t kOidEcdsaWithSha512[] = {0x2a, 0x86, 0x48, 0xce,
108                                        0x3d, 0x04, 0x03, 0x04};
109 
110 // From RFC 5912:
111 //
112 //     id-RSASSA-PSS  OBJECT IDENTIFIER  ::=  { pkcs-1 10 }
113 //
114 // In dotted notation: 1.2.840.113549.1.1.10
115 const uint8_t kOidRsaSsaPss[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
116                                  0x0d, 0x01, 0x01, 0x0a};
117 
118 // From RFC 5912:
119 //
120 //     id-mgf1  OBJECT IDENTIFIER  ::=  { pkcs-1 8 }
121 //
122 // In dotted notation: 1.2.840.113549.1.1.8
123 const uint8_t kOidMgf1[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
124                             0x0d, 0x01, 0x01, 0x08};
125 
126 // Returns true if the entirety of the input is a NULL value.
IsNull(der::Input input)127 [[nodiscard]] bool IsNull(der::Input input) {
128   der::Parser parser(input);
129   der::Input null_value;
130   if (!parser.ReadTag(CBS_ASN1_NULL, &null_value)) {
131     return false;
132   }
133 
134   // NULL values are TLV encoded; the value is expected to be empty.
135   if (!null_value.empty()) {
136     return false;
137   }
138 
139   // By definition of this function, the entire input must be a NULL.
140   return !parser.HasMore();
141 }
142 
IsNullOrEmpty(der::Input input)143 [[nodiscard]] bool IsNullOrEmpty(der::Input input) {
144   return IsNull(input) || input.empty();
145 }
146 
147 // Parses a MaskGenAlgorithm as defined by RFC 5912:
148 //
149 //     MaskGenAlgorithm ::= AlgorithmIdentifier{ALGORITHM,
150 //                             {PKCS1MGFAlgorithms}}
151 //
152 //     mgf1SHA1 MaskGenAlgorithm ::= {
153 //         algorithm id-mgf1,
154 //         parameters HashAlgorithm : sha1Identifier
155 //     }
156 //
157 //     --
158 //     --  Define the set of mask generation functions
159 //     --
160 //     --  If the identifier is id-mgf1, any of the listed hash
161 //     --    algorithms may be used.
162 //     --
163 //
164 //     PKCS1MGFAlgorithms ALGORITHM ::= {
165 //         { IDENTIFIER id-mgf1 PARAMS TYPE HashAlgorithm ARE required },
166 //         ...
167 //     }
168 //
169 // Note that the possible mask gen algorithms is extensible. However at present
170 // the only function supported is MGF1, as that is the singular mask gen
171 // function defined by RFC 4055 / RFC 5912.
ParseMaskGenAlgorithm(const der::Input input,DigestAlgorithm * mgf1_hash)172 [[nodiscard]] bool ParseMaskGenAlgorithm(const der::Input input,
173                                          DigestAlgorithm *mgf1_hash) {
174   der::Input oid;
175   der::Input params;
176   if (!ParseAlgorithmIdentifier(input, &oid, &params)) {
177     return false;
178   }
179 
180   // MGF1 is the only supported mask generation algorithm.
181   if (oid != der::Input(kOidMgf1)) {
182     return false;
183   }
184 
185   return ParseHashAlgorithm(params, mgf1_hash);
186 }
187 
188 // Parses the parameters for an RSASSA-PSS signature algorithm, as defined by
189 // RFC 5912:
190 //
191 //     sa-rsaSSA-PSS SIGNATURE-ALGORITHM ::= {
192 //         IDENTIFIER id-RSASSA-PSS
193 //         PARAMS TYPE RSASSA-PSS-params ARE required
194 //         HASHES { mda-sha1 | mda-sha224 | mda-sha256 | mda-sha384
195 //                      | mda-sha512 }
196 //         PUBLIC-KEYS { pk-rsa | pk-rsaSSA-PSS }
197 //         SMIME-CAPS { IDENTIFIED BY id-RSASSA-PSS }
198 //     }
199 //
200 //     RSASSA-PSS-params  ::=  SEQUENCE  {
201 //         hashAlgorithm     [0] HashAlgorithm DEFAULT sha1Identifier,
202 //         maskGenAlgorithm  [1] MaskGenAlgorithm DEFAULT mgf1SHA1,
203 //         saltLength        [2] INTEGER DEFAULT 20,
204 //         trailerField      [3] INTEGER DEFAULT 1
205 //     }
206 //
207 // Which is to say the parameters MUST be present, and of type
208 // RSASSA-PSS-params. Additionally, we only support the RSA-PSS parameter
209 // combinations representable by TLS 1.3 (RFC 8446).
210 //
211 // Note also that DER encoding (ITU-T X.690 section 11.5) prohibits
212 // specifying default values explicitly. The parameter should instead be
213 // omitted to indicate a default value.
ParseRsaPss(der::Input params)214 std::optional<SignatureAlgorithm> ParseRsaPss(der::Input params) {
215   der::Parser parser(params);
216   der::Parser params_parser;
217   if (!parser.ReadSequence(&params_parser)) {
218     return std::nullopt;
219   }
220 
221   // There shouldn't be anything after the sequence (by definition the
222   // parameters is a single sequence).
223   if (parser.HasMore()) {
224     return std::nullopt;
225   }
226 
227   // The default values for hashAlgorithm, maskGenAlgorithm, and saltLength
228   // correspond to SHA-1, which we do not support with RSA-PSS, so treat them as
229   // required fields. Explicitly-specified defaults will be rejected later, when
230   // we limit combinations. Additionally, as the trailerField is required to be
231   // the default, we simply ignore it and reject it as any other trailing data.
232   //
233   //     hashAlgorithm     [0] HashAlgorithm DEFAULT sha1Identifier,
234   //     maskGenAlgorithm  [1] MaskGenAlgorithm DEFAULT mgf1SHA1,
235   //     saltLength        [2] INTEGER DEFAULT 20,
236   //     trailerField      [3] INTEGER DEFAULT 1
237   der::Input field;
238   DigestAlgorithm hash, mgf1_hash;
239   der::Parser salt_length_parser;
240   uint64_t salt_length;
241   if (!params_parser.ReadTag(
242           CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, &field) ||
243       !ParseHashAlgorithm(field, &hash) ||
244       !params_parser.ReadTag(
245           CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1, &field) ||
246       !ParseMaskGenAlgorithm(field, &mgf1_hash) ||
247       !params_parser.ReadConstructed(
248           CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 2,
249           &salt_length_parser) ||
250       !salt_length_parser.ReadUint64(&salt_length) ||
251       salt_length_parser.HasMore() || params_parser.HasMore()) {
252     return std::nullopt;
253   }
254 
255   // Only combinations of RSASSA-PSS-params specified by TLS 1.3 (RFC 8446) are
256   // supported.
257   if (hash != mgf1_hash) {
258     return std::nullopt;  // TLS 1.3 always matches MGF-1 and message hash.
259   }
260   if (hash == DigestAlgorithm::Sha256 && salt_length == 32) {
261     return SignatureAlgorithm::kRsaPssSha256;
262   }
263   if (hash == DigestAlgorithm::Sha384 && salt_length == 48) {
264     return SignatureAlgorithm::kRsaPssSha384;
265   }
266   if (hash == DigestAlgorithm::Sha512 && salt_length == 64) {
267     return SignatureAlgorithm::kRsaPssSha512;
268   }
269 
270   return std::nullopt;
271 }
272 
273 }  // namespace
274 
ParseAlgorithmIdentifier(der::Input input,der::Input * algorithm,der::Input * parameters)275 [[nodiscard]] bool ParseAlgorithmIdentifier(der::Input input,
276                                             der::Input *algorithm,
277                                             der::Input *parameters) {
278   der::Parser parser(input);
279 
280   der::Parser algorithm_identifier_parser;
281   if (!parser.ReadSequence(&algorithm_identifier_parser)) {
282     return false;
283   }
284 
285   // There shouldn't be anything after the sequence. This is by definition,
286   // as the input to this function is expected to be a single
287   // AlgorithmIdentifier.
288   if (parser.HasMore()) {
289     return false;
290   }
291 
292   if (!algorithm_identifier_parser.ReadTag(CBS_ASN1_OBJECT, algorithm)) {
293     return false;
294   }
295 
296   // Read the optional parameters to a der::Input. The parameters can be at
297   // most one TLV (for instance NULL or a sequence).
298   //
299   // Note that nothing is allowed after the single optional "parameters" TLV.
300   // This is because RFC 5912's notation for AlgorithmIdentifier doesn't
301   // explicitly list an extension point after "parameters".
302   *parameters = der::Input();
303   if (algorithm_identifier_parser.HasMore() &&
304       !algorithm_identifier_parser.ReadRawTLV(parameters)) {
305     return false;
306   }
307   return !algorithm_identifier_parser.HasMore();
308 }
309 
ParseHashAlgorithm(der::Input input,DigestAlgorithm * out)310 [[nodiscard]] bool ParseHashAlgorithm(der::Input input, DigestAlgorithm *out) {
311   CBS cbs;
312   CBS_init(&cbs, input.data(), input.size());
313   const EVP_MD *md = EVP_parse_digest_algorithm(&cbs);
314 
315   if (md == EVP_sha1()) {
316     *out = DigestAlgorithm::Sha1;
317   } else if (md == EVP_sha256()) {
318     *out = DigestAlgorithm::Sha256;
319   } else if (md == EVP_sha384()) {
320     *out = DigestAlgorithm::Sha384;
321   } else if (md == EVP_sha512()) {
322     *out = DigestAlgorithm::Sha512;
323   } else {
324     // TODO(eroman): Support MD2, MD4, MD5 for completeness?
325     // Unsupported digest algorithm.
326     return false;
327   }
328 
329   return true;
330 }
331 
ParseSignatureAlgorithm(der::Input algorithm_identifier)332 std::optional<SignatureAlgorithm> ParseSignatureAlgorithm(
333     der::Input algorithm_identifier) {
334   der::Input oid;
335   der::Input params;
336   if (!ParseAlgorithmIdentifier(algorithm_identifier, &oid, &params)) {
337     return std::nullopt;
338   }
339 
340   // TODO(eroman): Each OID is tested for equality in order, which is not
341   // particularly efficient.
342 
343   // RFC 5912 requires that the parameters for RSA PKCS#1 v1.5 algorithms be
344   // NULL ("PARAMS TYPE NULL ARE required"), however an empty parameter is also
345   // allowed for compatibility with non-compliant OCSP responders.
346   //
347   // TODO(svaldez): Add warning about non-strict parsing.
348   if (oid == der::Input(kOidSha1WithRsaEncryption) && IsNullOrEmpty(params)) {
349     return SignatureAlgorithm::kRsaPkcs1Sha1;
350   }
351   if (oid == der::Input(kOidSha256WithRsaEncryption) && IsNullOrEmpty(params)) {
352     return SignatureAlgorithm::kRsaPkcs1Sha256;
353   }
354   if (oid == der::Input(kOidSha384WithRsaEncryption) && IsNullOrEmpty(params)) {
355     return SignatureAlgorithm::kRsaPkcs1Sha384;
356   }
357   if (oid == der::Input(kOidSha512WithRsaEncryption) && IsNullOrEmpty(params)) {
358     return SignatureAlgorithm::kRsaPkcs1Sha512;
359   }
360   if (oid == der::Input(kOidSha1WithRsaSignature) && IsNullOrEmpty(params)) {
361     return SignatureAlgorithm::kRsaPkcs1Sha1;
362   }
363 
364   // RFC 5912 requires that the parameters for ECDSA algorithms be absent
365   // ("PARAMS TYPE NULL ARE absent"):
366   if (oid == der::Input(kOidEcdsaWithSha1) && params.empty()) {
367     return SignatureAlgorithm::kEcdsaSha1;
368   }
369   if (oid == der::Input(kOidEcdsaWithSha256) && params.empty()) {
370     return SignatureAlgorithm::kEcdsaSha256;
371   }
372   if (oid == der::Input(kOidEcdsaWithSha384) && params.empty()) {
373     return SignatureAlgorithm::kEcdsaSha384;
374   }
375   if (oid == der::Input(kOidEcdsaWithSha512) && params.empty()) {
376     return SignatureAlgorithm::kEcdsaSha512;
377   }
378 
379   if (oid == der::Input(kOidRsaSsaPss)) {
380     return ParseRsaPss(params);
381   }
382 
383   // Unknown signature algorithm.
384   return std::nullopt;
385 }
386 
GetTlsServerEndpointDigestAlgorithm(SignatureAlgorithm alg)387 std::optional<DigestAlgorithm> GetTlsServerEndpointDigestAlgorithm(
388     SignatureAlgorithm alg) {
389   // See RFC 5929, section 4.1. RFC 5929 breaks the signature algorithm
390   // abstraction by trying to extract individual digest algorithms. (While
391   // common, this is not a universal property of signature algorithms.) We
392   // implement this within the library, so callers do not need to condition over
393   // all algorithms.
394   switch (alg) {
395     // If the single digest algorithm is SHA-1, use SHA-256.
396     case SignatureAlgorithm::kRsaPkcs1Sha1:
397     case SignatureAlgorithm::kEcdsaSha1:
398       return DigestAlgorithm::Sha256;
399 
400     case SignatureAlgorithm::kRsaPkcs1Sha256:
401     case SignatureAlgorithm::kEcdsaSha256:
402       return DigestAlgorithm::Sha256;
403 
404     case SignatureAlgorithm::kRsaPkcs1Sha384:
405     case SignatureAlgorithm::kEcdsaSha384:
406       return DigestAlgorithm::Sha384;
407 
408     case SignatureAlgorithm::kRsaPkcs1Sha512:
409     case SignatureAlgorithm::kEcdsaSha512:
410       return DigestAlgorithm::Sha512;
411 
412     // It is ambiguous whether hash-matching RSASSA-PSS instantiations count as
413     // using one or multiple digests, but the corresponding digest is the only
414     // reasonable interpretation.
415     case SignatureAlgorithm::kRsaPssSha256:
416       return DigestAlgorithm::Sha256;
417     case SignatureAlgorithm::kRsaPssSha384:
418       return DigestAlgorithm::Sha384;
419     case SignatureAlgorithm::kRsaPssSha512:
420       return DigestAlgorithm::Sha512;
421   }
422   return std::nullopt;
423 }
424 
425 }  // namespace bssl
426