Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Side by Side Diff: net/cert/internal/signature_algorithm.cc

Issue 1218753002: Add DER parsing of AlgorithmId for signatures. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: de-virtualize Equals() Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 "net/der/input.h"
8 #include "net/der/parser.h"
9
10 namespace net {
11
12 namespace {
13
14 // From RFC 5912:
15 //
16 // sha1WithRSAEncryption OBJECT IDENTIFIER ::= {
17 // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
18 // pkcs-1(1) 5 }
19 //
20 // In dotted notation: 1.2.840.113549.1.1.5
21 const uint8_t kOidSha1WithRsaEncryption[] =
22 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05};
23
24 // From RFC 5912:
25 //
26 // pkcs-1 OBJECT IDENTIFIER ::=
27 // { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
28
29 // From RFC 5912:
30 //
31 // sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 }
32 //
33 // In dotted notation: 1.2.840.113549.1.1.11
34 const uint8_t kOidSha256WithRsaEncryption[] =
35 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b};
36
37 // From RFC 5912:
38 //
39 // sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 }
40 //
41 // In dotted notation: 1.2.840.113549.1.1.11
42 const uint8_t kOidSha384WithRsaEncryption[] =
43 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c};
44
45 // From RFC 5912:
46 //
47 // sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 }
48 //
49 // In dotted notation: 1.2.840.113549.1.1.13
50 const uint8_t kOidSha512WithRsaEncryption[] =
51 {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d};
52
53 // From RFC 5912:
54 //
55 // ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
56 // iso(1) member-body(2) us(840) ansi-X9-62(10045)
57 // signatures(4) 1 }
58 //
59 // In dotted notation: 1.2.840.10045.4.1
60 const uint8_t kOidEcdsaWithSha1[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01};
61
62 // From RFC 5912:
63 //
64 // ecdsa-with-SHA256 OBJECT IDENTIFIER ::= {
65 // iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
66 // ecdsa-with-SHA2(3) 2 }
67 //
68 // In dotted notation: 1.2.840.10045.4.3.2
69 const uint8_t kOidEcdsaWithSha256[] =
70 {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02};
71
72 // From RFC 5912:
73 //
74 // ecdsa-with-SHA384 OBJECT IDENTIFIER ::= {
75 // iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
76 // ecdsa-with-SHA2(3) 3 }
77 //
78 // In dotted notation: 1.2.840.10045.4.3.3
79 const uint8_t kOidEcdsaWithSha384[] =
80 {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03};
81
82 // From RFC 5912:
83 //
84 // ecdsa-with-SHA512 OBJECT IDENTIFIER ::= {
85 // iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
86 // ecdsa-with-SHA2(3) 4 }
87 //
88 // In dotted notation: 1.2.840.10045.4.3.4
89 const uint8_t kOidEcdsaWithSha512[] =
90 {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04};
91
92 // RFC 5280 section 4.1.1.2 defines signatureAlgorithm as:
93 //
94 // AlgorithmIdentifier ::= SEQUENCE {
95 // algorithm OBJECT IDENTIFIER,
96 // parameters ANY DEFINED BY algorithm OPTIONAL }
97 WARN_UNUSED_RESULT bool ParseAlgorithmIdentifier(const der::Input& input,
98 der::Input* algorithm,
99 der::Input* parameters) {
100 der::Parser parser(input);
101
102 der::Parser algorithm_identifier_parser;
103 if (!parser.ReadSequence(&algorithm_identifier_parser))
104 return false;
105
106 // There shouldn't be anything after the sequence. This is by definition,
107 // as the input to this function is expected to be a single
108 // AlgorithmIdentifier.
109 if (parser.HasMore())
110 return false;
111
112 if (!algorithm_identifier_parser.ReadTag(der::kOid, algorithm))
113 return false;
114
115 // Read the optional parameters to a der::Input. The parameters can be at
116 // most one TLV (for instance NULL or a sequence).
117 //
118 // Note that nothing is allowed after the single optional "parameters" TLV.
119 // This is because RFC 5912's notation for AlgorithmIdentifier doesn't
120 // explicitly list an extension point after "parameters".
121 *parameters = der::Input();
122 if (algorithm_identifier_parser.HasMore() &&
123 !algorithm_identifier_parser.ReadRawTLV(parameters)) {
124 return false;
125 }
126 return !algorithm_identifier_parser.HasMore();
127 }
128
129 // Returns true if |input| is empty.
130 WARN_UNUSED_RESULT bool IsEmpty(const der::Input& input) {
131 return input.Length() == 0;
132 }
133
134 // Returns true if the entirety of the input is a NULL value.
135 WARN_UNUSED_RESULT bool IsNull(const der::Input& input) {
136 der::Parser parser(input);
137 der::Input null_value;
138 if (!parser.ReadTag(der::kNull, &null_value))
139 return false;
140
141 // NULL values are TLV encoded; the value is expected to be empty.
142 if (!IsEmpty(null_value))
143 return false;
144
145 // By definition of this function, the entire input must be a NULL.
146 return !parser.HasMore();
147 }
148
149 // Parses an RSA PKCS#1 v1.5 signature algorithm given the DER-encoded
150 // "parameters" from the parsed AlgorithmIdentifier, and the hash algorithm
151 // that was implied by the AlgorithmIdentifier's OID.
152 //
153 // Returns a nullptr on failure.
154 //
155 // RFC 5912 requires that the parameters for RSA PKCS#1 v1.5 algorithms be NULL
156 // ("PARAMS TYPE NULL ARE required"):
157 //
158 // sa-rsaWithSHA1 SIGNATURE-ALGORITHM ::= {
159 // IDENTIFIER sha1WithRSAEncryption
160 // PARAMS TYPE NULL ARE required
161 // HASHES { mda-sha1 }
162 // PUBLIC-KEYS { pk-rsa }
163 // SMIME-CAPS {IDENTIFIED BY sha1WithRSAEncryption }
164 // }
165 //
166 // sa-sha256WithRSAEncryption SIGNATURE-ALGORITHM ::= {
167 // IDENTIFIER sha256WithRSAEncryption
168 // PARAMS TYPE NULL ARE required
169 // HASHES { mda-sha256 }
170 // PUBLIC-KEYS { pk-rsa }
171 // SMIME-CAPS { IDENTIFIED BY sha256WithRSAEncryption }
172 // }
173 //
174 // sa-sha384WithRSAEncryption SIGNATURE-ALGORITHM ::= {
175 // IDENTIFIER sha384WithRSAEncryption
176 // PARAMS TYPE NULL ARE required
177 // HASHES { mda-sha384 }
178 // PUBLIC-KEYS { pk-rsa }
179 // SMIME-CAPS { IDENTIFIED BY sha384WithRSAEncryption }
180 // }
181 //
182 // sa-sha512WithRSAEncryption SIGNATURE-ALGORITHM ::= {
183 // IDENTIFIER sha512WithRSAEncryption
184 // PARAMS TYPE NULL ARE required
185 // HASHES { mda-sha512 }
186 // PUBLIC-KEYS { pk-rsa }
187 // SMIME-CAPS { IDENTIFIED BY sha512WithRSAEncryption }
188 // }
189 scoped_ptr<SignatureAlgorithm> ParseRsaPkcs1(DigestAlgorithm digest,
190 const der::Input& params) {
191 if (!IsNull(params))
192 return nullptr;
193
194 return SignatureAlgorithm::CreateRsaPkcs1(digest);
195 }
196
197 // Parses an ECDSA signature algorithm given the DER-encoded "parameters" from
198 // the parsed AlgorithmIdentifier, and the hash algorithm that was implied by
199 // the AlgorithmIdentifier's OID.
200 //
201 // On failure returns a nullptr.
202 //
203 // RFC 5912 requires that the parameters for ECDSA algorithms be absent
204 // ("PARAMS TYPE NULL ARE absent"):
205 //
206 // sa-ecdsaWithSHA1 SIGNATURE-ALGORITHM ::= {
207 // IDENTIFIER ecdsa-with-SHA1
208 // VALUE ECDSA-Sig-Value
209 // PARAMS TYPE NULL ARE absent
210 // HASHES { mda-sha1 }
211 // PUBLIC-KEYS { pk-ec }
212 // SMIME-CAPS {IDENTIFIED BY ecdsa-with-SHA1 }
213 // }
214 //
215 // sa-ecdsaWithSHA256 SIGNATURE-ALGORITHM ::= {
216 // IDENTIFIER ecdsa-with-SHA256
217 // VALUE ECDSA-Sig-Value
218 // PARAMS TYPE NULL ARE absent
219 // HASHES { mda-sha256 }
220 // PUBLIC-KEYS { pk-ec }
221 // SMIME-CAPS { IDENTIFIED BY ecdsa-with-SHA256 }
222 // }
223 //
224 // sa-ecdsaWithSHA384 SIGNATURE-ALGORITHM ::= {
225 // IDENTIFIER ecdsa-with-SHA384
226 // VALUE ECDSA-Sig-Value
227 // PARAMS TYPE NULL ARE absent
228 // HASHES { mda-sha384 }
229 // PUBLIC-KEYS { pk-ec }
230 // SMIME-CAPS { IDENTIFIED BY ecdsa-with-SHA384 }
231 // }
232 //
233 // sa-ecdsaWithSHA512 SIGNATURE-ALGORITHM ::= {
234 // IDENTIFIER ecdsa-with-SHA512
235 // VALUE ECDSA-Sig-Value
236 // PARAMS TYPE NULL ARE absent
237 // HASHES { mda-sha512 }
238 // PUBLIC-KEYS { pk-ec }
239 // SMIME-CAPS { IDENTIFIED BY ecdsa-with-SHA512 }
240 // }
241 scoped_ptr<SignatureAlgorithm> ParseEcdsa(DigestAlgorithm digest,
242 const der::Input& params) {
243 if (!IsEmpty(params))
244 return nullptr;
245
246 return SignatureAlgorithm::CreateEcdsa(digest);
247 }
248
249 } // namespace
250
251 RsaPssParameters::RsaPssParameters(DigestAlgorithm mgf1_hash,
252 uint32_t salt_length)
253 : mgf1_hash_(mgf1_hash), salt_length_(salt_length) {
254 }
255
256 bool RsaPssParameters::Equals(const RsaPssParameters* other) const {
257 return mgf1_hash_ == other->mgf1_hash_ && salt_length_ == other->salt_length_;
258 }
259
260 SignatureAlgorithm::~SignatureAlgorithm() {
261 }
262
263 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateFromDer(
264 const der::Input& algorithm_identifier) {
265 der::Input oid;
266 der::Input params;
267 if (!ParseAlgorithmIdentifier(algorithm_identifier, &oid, &params))
268 return nullptr;
269
270 // TODO(eroman): Each OID is tested for equality in order, which is not
271 // particularly efficient.
272
273 if (oid.Equals(der::Input(kOidSha1WithRsaEncryption)))
274 return ParseRsaPkcs1(DigestAlgorithm::Sha1, params);
275
276 if (oid.Equals(der::Input(kOidSha256WithRsaEncryption)))
277 return ParseRsaPkcs1(DigestAlgorithm::Sha256, params);
278
279 if (oid.Equals(der::Input(kOidSha384WithRsaEncryption)))
280 return ParseRsaPkcs1(DigestAlgorithm::Sha384, params);
281
282 if (oid.Equals(der::Input(kOidSha512WithRsaEncryption)))
283 return ParseRsaPkcs1(DigestAlgorithm::Sha512, params);
284
285 if (oid.Equals(der::Input(kOidEcdsaWithSha1)))
286 return ParseEcdsa(DigestAlgorithm::Sha1, params);
287
288 if (oid.Equals(der::Input(kOidEcdsaWithSha256)))
289 return ParseEcdsa(DigestAlgorithm::Sha256, params);
290
291 if (oid.Equals(der::Input(kOidEcdsaWithSha384)))
292 return ParseEcdsa(DigestAlgorithm::Sha384, params);
293
294 if (oid.Equals(der::Input(kOidEcdsaWithSha512)))
295 return ParseEcdsa(DigestAlgorithm::Sha512, params);
296
297 // TODO(eroman): Add parsing of RSASSA-PSS
298
299 return nullptr; // Unsupported OID.
300 }
301
302 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateRsaPkcs1(
303 DigestAlgorithm digest) {
304 return make_scoped_ptr(
305 new SignatureAlgorithm(SignatureAlgorithmId::RsaPkcs1, digest, nullptr));
306 }
307
308 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateEcdsa(
309 DigestAlgorithm digest) {
310 return make_scoped_ptr(
311 new SignatureAlgorithm(SignatureAlgorithmId::Ecdsa, digest, nullptr));
312 }
313
314 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateRsaPss(
315 DigestAlgorithm digest,
316 DigestAlgorithm mgf1_hash,
317 uint32_t salt_length) {
318 return make_scoped_ptr(new SignatureAlgorithm(
319 SignatureAlgorithmId::RsaPss, digest,
320 make_scoped_ptr(new RsaPssParameters(mgf1_hash, salt_length))));
321 }
322
323 bool SignatureAlgorithm::Equals(const SignatureAlgorithm& other) const {
324 if (algorithm_ != other.algorithm_)
325 return false;
326
327 if (digest_ != other.digest_)
328 return false;
329
330 // Check that the parameters are equal.
331 switch (algorithm_) {
332 case SignatureAlgorithmId::RsaPss: {
333 const RsaPssParameters* params1 = ParamsForRsaPss();
334 const RsaPssParameters* params2 = other.ParamsForRsaPss();
335 if (!params1 || !params2 || !params1->Equals(params2))
336 return false;
337 break;
338 }
339
340 // There shouldn't be any parameters.
341 case SignatureAlgorithmId::RsaPkcs1:
342 case SignatureAlgorithmId::Ecdsa:
343 if (params_ || other.params_)
344 return false;
345 break;
346 }
347
348 return true;
349 }
350
351 const RsaPssParameters* SignatureAlgorithm::ParamsForRsaPss() const {
352 if (algorithm_ == SignatureAlgorithmId::RsaPss)
353 return static_cast<RsaPssParameters*>(params_.get());
354 return nullptr;
355 }
356
357 SignatureAlgorithm::SignatureAlgorithm(
358 SignatureAlgorithmId algorithm,
359 DigestAlgorithm digest,
360 scoped_ptr<SignatureAlgorithmParameters> params)
361 : algorithm_(algorithm), digest_(digest), params_(params.Pass()) {
362 }
363
364 } // namespace net
OLDNEW
« no previous file with comments | « net/cert/internal/signature_algorithm.h ('k') | net/cert/internal/signature_algorithm_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698