OLD | NEW |
---|---|
(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)) | |
Ryan Sleevi
2015/07/16 03:46:37
I'm still nervous this is going to cause issues. W
eroman
2015/07/16 05:23:06
Understood.
When I get back I will see what it ta
| |
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 SignatureAlgorithmParameters* other) const { | |
257 const RsaPssParameters* params = static_cast<const RsaPssParameters*>(other); | |
258 return mgf1_hash_ == params->mgf1_hash_ && | |
259 salt_length_ == params->salt_length_; | |
260 } | |
261 | |
262 SignatureAlgorithm::~SignatureAlgorithm() { | |
263 } | |
264 | |
265 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateFromDer( | |
266 const der::Input& algorithm_identifier) { | |
267 der::Input oid; | |
268 der::Input params; | |
269 if (!ParseAlgorithmIdentifier(algorithm_identifier, &oid, ¶ms)) | |
270 return nullptr; | |
271 | |
272 // TODO(eroman): Each OID is tested for equality in order, which is not | |
273 // particularly efficient. | |
274 | |
275 if (oid.Equals(der::Input(kOidSha1WithRsaEncryption))) | |
276 return ParseRsaPkcs1(DigestAlgorithm::Sha1, params); | |
277 | |
278 if (oid.Equals(der::Input(kOidSha256WithRsaEncryption))) | |
279 return ParseRsaPkcs1(DigestAlgorithm::Sha256, params); | |
280 | |
281 if (oid.Equals(der::Input(kOidSha384WithRsaEncryption))) | |
282 return ParseRsaPkcs1(DigestAlgorithm::Sha384, params); | |
283 | |
284 if (oid.Equals(der::Input(kOidSha512WithRsaEncryption))) | |
285 return ParseRsaPkcs1(DigestAlgorithm::Sha512, params); | |
286 | |
287 if (oid.Equals(der::Input(kOidEcdsaWithSha1))) | |
288 return ParseEcdsa(DigestAlgorithm::Sha1, params); | |
289 | |
290 if (oid.Equals(der::Input(kOidEcdsaWithSha256))) | |
291 return ParseEcdsa(DigestAlgorithm::Sha256, params); | |
292 | |
293 if (oid.Equals(der::Input(kOidEcdsaWithSha384))) | |
294 return ParseEcdsa(DigestAlgorithm::Sha384, params); | |
295 | |
296 if (oid.Equals(der::Input(kOidEcdsaWithSha512))) | |
297 return ParseEcdsa(DigestAlgorithm::Sha512, params); | |
298 | |
299 // TODO(eroman): Add parsing of RSASSA-PSS | |
300 | |
301 return nullptr; // Unsupported OID. | |
302 } | |
303 | |
304 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateRsaPkcs1( | |
305 DigestAlgorithm digest) { | |
306 return make_scoped_ptr( | |
307 new SignatureAlgorithm(SignatureAlgorithmId::RsaPkcs1, digest, nullptr)); | |
308 } | |
309 | |
310 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateEcdsa( | |
311 DigestAlgorithm digest) { | |
312 return make_scoped_ptr( | |
313 new SignatureAlgorithm(SignatureAlgorithmId::Ecdsa, digest, nullptr)); | |
314 } | |
315 | |
316 scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateRsaPss( | |
317 DigestAlgorithm digest, | |
318 DigestAlgorithm mgf1_hash, | |
319 uint32_t salt_length) { | |
320 return make_scoped_ptr(new SignatureAlgorithm( | |
321 SignatureAlgorithmId::RsaPss, digest, | |
322 make_scoped_ptr(new RsaPssParameters(mgf1_hash, salt_length)))); | |
323 } | |
324 | |
325 bool SignatureAlgorithm::Equals(const SignatureAlgorithm& other) const { | |
326 if (algorithm_ != other.algorithm_) | |
327 return false; | |
328 | |
329 if (digest_ != other.digest_) | |
330 return false; | |
331 | |
332 if (!params_ != !other.params_) | |
333 return false; | |
334 | |
335 if (params_ && !params_->Equals(other.params_.get())) | |
336 return false; | |
337 | |
338 return true; | |
339 } | |
340 | |
341 const RsaPssParameters* SignatureAlgorithm::ParamsForRsaPss() const { | |
342 if (algorithm_ == SignatureAlgorithmId::RsaPss) | |
343 return static_cast<RsaPssParameters*>(params_.get()); | |
344 return nullptr; | |
345 } | |
346 | |
347 SignatureAlgorithm::SignatureAlgorithm( | |
348 SignatureAlgorithmId algorithm, | |
349 DigestAlgorithm digest, | |
350 scoped_ptr<SignatureAlgorithmParameters> params) | |
351 : algorithm_(algorithm), digest_(digest), params_(params.Pass()) { | |
352 } | |
353 | |
354 } // namespace net | |
OLD | NEW |