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