OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/cert/internal/parse_certificate.h" | 5 #include "net/cert/internal/parse_certificate.h" |
6 | 6 |
7 #include "net/der/input.h" | 7 #include "net/der/input.h" |
8 #include "net/der/parse_values.h" | 8 #include "net/der/parse_values.h" |
9 #include "net/der/parser.h" | 9 #include "net/der/parser.h" |
10 | 10 |
(...skipping 10 matching lines...) Expand all Loading... | |
21 // Should by a single SEQUENCE by definition of the function. | 21 // Should by a single SEQUENCE by definition of the function. |
22 return !parser.HasMore(); | 22 return !parser.HasMore(); |
23 } | 23 } |
24 | 24 |
25 // Reads a SEQUENCE from |parser| and writes the full tag-length-value into | 25 // Reads a SEQUENCE from |parser| and writes the full tag-length-value into |
26 // |out|. On failure |parser| may or may not have been advanced. | 26 // |out|. On failure |parser| may or may not have been advanced. |
27 WARN_UNUSED_RESULT bool ReadSequenceTLV(der::Parser* parser, der::Input* out) { | 27 WARN_UNUSED_RESULT bool ReadSequenceTLV(der::Parser* parser, der::Input* out) { |
28 return parser->ReadRawTLV(out) && IsSequenceTLV(*out); | 28 return parser->ReadRawTLV(out) && IsSequenceTLV(*out); |
29 } | 29 } |
30 | 30 |
31 // Parses a Version according to RFC 5280: | |
32 // | |
33 // Version ::= INTEGER { v1(0), v2(1), v3(2) } | |
34 // | |
35 // No value other that v1, v2, or v3 is allowed (and if given will fail). RFC | |
36 // 5280 minimally requires the handling of v3 (and overwhelmingly these are the | |
37 // certificate versions in use today): | |
38 // | |
39 // Implementations SHOULD be prepared to accept any version certificate. | |
40 // At a minimum, conforming implementations MUST recognize version 3 | |
41 // certificates. | |
42 WARN_UNUSED_RESULT bool ParseVersion(const der::Input& in, | |
43 CertificateVersion* version) { | |
44 der::Parser parser(in); | |
45 uint64_t version64; | |
46 if (!parser.ReadUint64(&version64)) | |
47 return false; | |
48 | |
49 switch (version64) { | |
50 case 0: | |
51 *version = CertificateVersion::V1; | |
52 break; | |
53 case 1: | |
54 *version = CertificateVersion::V2; | |
55 break; | |
56 case 2: | |
57 *version = CertificateVersion::V3; | |
58 break; | |
59 default: | |
60 // Don't allow any other version identifier. | |
61 return false; | |
62 } | |
63 | |
64 // By definition the input to this function was a single INTEGER, so there | |
65 // shouldn't be anything else after it. | |
66 return !parser.HasMore(); | |
67 } | |
68 | |
69 // Returns true if the given serial number (CertificateSerialNumber in RFC 5280) | |
70 // is valid: | |
71 // | |
72 // CertificateSerialNumber ::= INTEGER | |
73 // | |
74 // The input to this function is the (unverified) value octets of the INTEGER. | |
75 // This function will verify that: | |
76 // | |
77 // * The octets are a valid DER-encoding of an INTEGER (for instance, minimal | |
78 // encoding length). | |
79 // | |
80 // * No more than 20 octets are used. | |
81 // | |
82 // Note that it DOES NOT reject non-positive values (zero or negative). | |
83 // | |
84 // For reference, here is what RFC 5280 section 4.1.2.2 says: | |
85 // | |
86 // Given the uniqueness requirements above, serial numbers can be | |
87 // expected to contain long integers. Certificate users MUST be able to | |
88 // handle serialNumber values up to 20 octets. Conforming CAs MUST NOT | |
89 // use serialNumber values longer than 20 octets. | |
90 // | |
91 // Note: Non-conforming CAs may issue certificates with serial numbers | |
92 // that are negative or zero. Certificate users SHOULD be prepared to | |
93 // gracefully handle such certificates. | |
94 WARN_UNUSED_RESULT bool VerifySerialNumber(const der::Input& value) { | |
95 bool unused_negative; | |
96 size_t unused_numeric_length; | |
97 if (!der::IsValidInteger(value, &unused_negative, &unused_numeric_length)) | |
98 return false; | |
99 | |
100 // Check if the serial number is too long per RFC 5280. | |
101 if (value.Length() > 20) | |
102 return false; | |
103 | |
104 return true; | |
105 } | |
106 | |
31 } // namespace | 107 } // namespace |
32 | 108 |
109 ParsedTbsCertificate::ParsedTbsCertificate() | |
110 : version(CertificateVersion::V1), | |
111 has_issuer_unique_id(false), | |
112 has_subject_unique_id(false), | |
113 has_extensions(false) {} | |
davidben
2015/08/17 21:16:02
Optional: Non-static initializers are allowed now,
eroman
2015/08/18 00:20:50
Done.
As an aside, I have gotten feedback from R
davidben
2015/08/18 00:22:56
Interesting! I'm pretty sure I've gotten feedback
eroman
2015/08/18 00:35:52
As an aside: I understand member initializers bett
| |
114 | |
115 ParsedTbsCertificate::~ParsedTbsCertificate() {} | |
116 | |
33 bool ParseCertificate(const der::Input& certificate_tlv, | 117 bool ParseCertificate(const der::Input& certificate_tlv, |
34 ParsedCertificate* out) { | 118 ParsedCertificate* out) { |
35 der::Parser parser(certificate_tlv); | 119 der::Parser parser(certificate_tlv); |
36 | 120 |
37 // Certificate ::= SEQUENCE { | 121 // Certificate ::= SEQUENCE { |
38 der::Parser certificate_parser; | 122 der::Parser certificate_parser; |
39 if (!parser.ReadSequence(&certificate_parser)) | 123 if (!parser.ReadSequence(&certificate_parser)) |
40 return false; | 124 return false; |
41 | 125 |
42 // tbsCertificate TBSCertificate, | 126 // tbsCertificate TBSCertificate, |
(...skipping 13 matching lines...) Expand all Loading... | |
56 return false; | 140 return false; |
57 | 141 |
58 // By definition the input was a single Certificate, so there shouldn't be | 142 // By definition the input was a single Certificate, so there shouldn't be |
59 // unconsumed data. | 143 // unconsumed data. |
60 if (parser.HasMore()) | 144 if (parser.HasMore()) |
61 return false; | 145 return false; |
62 | 146 |
63 return true; | 147 return true; |
64 } | 148 } |
65 | 149 |
150 // From RFC 5280 section 4.1: | |
151 // | |
152 // TBSCertificate ::= SEQUENCE { | |
153 // version [0] EXPLICIT Version DEFAULT v1, | |
154 // serialNumber CertificateSerialNumber, | |
155 // signature AlgorithmIdentifier, | |
156 // issuer Name, | |
157 // validity Validity, | |
158 // subject Name, | |
159 // subjectPublicKeyInfo SubjectPublicKeyInfo, | |
160 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, | |
161 // -- If present, version MUST be v2 or v3 | |
162 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, | |
163 // -- If present, version MUST be v2 or v3 | |
164 // extensions [3] EXPLICIT Extensions OPTIONAL | |
165 // -- If present, version MUST be v3 | |
166 // } | |
167 bool ParseTbsCertificate(const der::Input& tbs_tlv, ParsedTbsCertificate* out) { | |
168 der::Parser parser(tbs_tlv); | |
169 | |
170 // Certificate ::= SEQUENCE { | |
171 der::Parser tbs_parser; | |
172 if (!parser.ReadSequence(&tbs_parser)) | |
173 return false; | |
174 | |
175 // version [0] EXPLICIT Version DEFAULT v1, | |
176 der::Input version; | |
177 bool has_version; | |
178 if (!tbs_parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &version, | |
179 &has_version)) { | |
180 return false; | |
181 } | |
182 if (has_version) { | |
183 if (!ParseVersion(version, &out->version)) | |
184 return false; | |
185 if (out->version == CertificateVersion::V1) { | |
186 // The correct way to specify v1 is to omit the version field since v1 is | |
187 // the DEFAULT. | |
188 return false; | |
189 } | |
190 } else { | |
191 out->version = CertificateVersion::V1; | |
192 } | |
193 | |
194 // serialNumber CertificateSerialNumber, | |
195 if (!tbs_parser.ReadTag(der::kInteger, &out->serial_number)) | |
196 return false; | |
197 if (!VerifySerialNumber(out->serial_number)) | |
198 return false; | |
199 | |
200 // signature AlgorithmIdentifier, | |
201 if (!ReadSequenceTLV(&tbs_parser, &out->signature_algorithm_tlv)) | |
202 return false; | |
203 | |
204 // issuer Name, | |
205 if (!ReadSequenceTLV(&tbs_parser, &out->issuer_tlv)) | |
206 return false; | |
207 | |
208 // validity Validity, | |
209 if (!ReadSequenceTLV(&tbs_parser, &out->validity_tlv)) | |
210 return false; | |
211 | |
212 // subject Name, | |
213 if (!ReadSequenceTLV(&tbs_parser, &out->subject_tlv)) | |
214 return false; | |
215 | |
216 // subjectPublicKeyInfo SubjectPublicKeyInfo, | |
217 if (!ReadSequenceTLV(&tbs_parser, &out->spki_tlv)) | |
218 return false; | |
219 | |
220 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, | |
221 // -- If present, version MUST be v2 or v3 | |
222 der::Input issuer_unique_id; | |
223 if (!tbs_parser.ReadOptionalTag(der::ContextSpecificPrimitive(1), | |
224 &issuer_unique_id, | |
225 &out->has_issuer_unique_id)) { | |
226 return false; | |
227 } | |
228 if (out->has_issuer_unique_id) { | |
229 if (!der::ParseBitString(issuer_unique_id, &out->issuer_unique_id)) | |
230 return false; | |
231 if (out->version != CertificateVersion::V2 && | |
232 out->version != CertificateVersion::V3) { | |
233 return false; | |
234 } | |
235 } | |
236 | |
237 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, | |
238 // -- If present, version MUST be v2 or v3 | |
239 der::Input subject_unique_id; | |
240 if (!tbs_parser.ReadOptionalTag(der::ContextSpecificPrimitive(2), | |
241 &subject_unique_id, | |
242 &out->has_subject_unique_id)) { | |
243 return false; | |
244 } | |
245 if (out->has_subject_unique_id) { | |
246 if (!der::ParseBitString(subject_unique_id, &out->subject_unique_id)) | |
247 return false; | |
248 if (out->version != CertificateVersion::V2 && | |
249 out->version != CertificateVersion::V3) { | |
250 return false; | |
251 } | |
252 } | |
253 | |
254 // extensions [3] EXPLICIT Extensions OPTIONAL | |
255 // -- If present, version MUST be v3 | |
256 if (!tbs_parser.ReadOptionalTag(der::ContextSpecificConstructed(3), | |
257 &out->extensions_tlv, &out->has_extensions)) { | |
258 return false; | |
259 } | |
260 if (out->has_extensions) { | |
261 // extensions_tlv must be a single element. Also check that it is a | |
262 // SEQUENCE. | |
263 if (!IsSequenceTLV(out->extensions_tlv)) | |
264 return false; | |
265 if (out->version != CertificateVersion::V3) | |
266 return false; | |
267 } | |
268 | |
269 // Note that there IS an extension point at the end of TBSCertificate | |
270 // (according to RFC 5912), so from that interpretation, unconsumed data would | |
271 // be allowed in |tbs_parser|. | |
272 // | |
273 // However because only v1, v2, and v3 certificates are supported by the | |
274 // parsing, there shouldn't be any subsequent data in those versions, so | |
275 // reject. | |
276 if (tbs_parser.HasMore()) | |
277 return false; | |
278 | |
279 // By definition the input was a single TBSCertificate, so there shouldn't be | |
280 // unconsumed data. | |
281 if (parser.HasMore()) | |
282 return false; | |
283 | |
284 return true; | |
285 } | |
286 | |
66 } // namespace net | 287 } // namespace net |
OLD | NEW |