Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / net / cert / internal / parse_certificate.cc
blob9535459bb8ad27ccb39b0807e24d210d4c5212ff
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.
5 #include "net/cert/internal/parse_certificate.h"
7 #include "net/der/input.h"
8 #include "net/der/parse_values.h"
9 #include "net/der/parser.h"
11 namespace net {
13 namespace {
15 // Returns true if |input| is a SEQUENCE and nothing else.
16 WARN_UNUSED_RESULT bool IsSequenceTLV(const der::Input& input) {
17 der::Parser parser(input);
18 der::Parser unused_sequence_parser;
19 if (!parser.ReadSequence(&unused_sequence_parser))
20 return false;
21 // Should by a single SEQUENCE by definition of the function.
22 return !parser.HasMore();
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.
27 WARN_UNUSED_RESULT bool ReadSequenceTLV(der::Parser* parser, der::Input* out) {
28 return parser->ReadRawTLV(out) && IsSequenceTLV(*out);
31 // Parses a Version according to RFC 5280:
33 // Version ::= INTEGER { v1(0), v2(1), v3(2) }
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):
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;
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;
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();
69 // Returns true if the given serial number (CertificateSerialNumber in RFC 5280)
70 // is valid:
72 // CertificateSerialNumber ::= INTEGER
74 // The input to this function is the (unverified) value octets of the INTEGER.
75 // This function will verify that:
77 // * The octets are a valid DER-encoding of an INTEGER (for instance, minimal
78 // encoding length).
80 // * No more than 20 octets are used.
82 // Note that it DOES NOT reject non-positive values (zero or negative).
84 // For reference, here is what RFC 5280 section 4.1.2.2 says:
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.
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 if (!der::IsValidInteger(value, &unused_negative))
97 return false;
99 // Check if the serial number is too long per RFC 5280.
100 if (value.Length() > 20)
101 return false;
103 return true;
106 // Consumes a "Time" value (as defined by RFC 5280) from |parser|. On success
107 // writes the result to |*out| and returns true. On failure no guarantees are
108 // made about the state of |parser|.
110 // From RFC 5280:
112 // Time ::= CHOICE {
113 // utcTime UTCTime,
114 // generalTime GeneralizedTime }
115 WARN_UNUSED_RESULT bool ReadTime(der::Parser* parser,
116 der::GeneralizedTime* out) {
117 der::Input value;
118 der::Tag tag;
120 if (!parser->ReadTagAndValue(&tag, &value))
121 return false;
123 if (tag == der::kUtcTime)
124 return der::ParseUTCTime(value, out);
126 if (tag == der::kGeneralizedTime)
127 return der::ParseGeneralizedTime(value, out);
129 // Unrecognized tag.
130 return false;
133 // Parses a DER-encoded "Validity" as specified by RFC 5280. Returns true on
134 // success and sets the results in |not_before| and |not_after|:
136 // Validity ::= SEQUENCE {
137 // notBefore Time,
138 // notAfter Time }
140 // Note that upon success it is NOT guaranteed that |*not_before <= *not_after|.
141 bool ParseValidity(const der::Input& validity_tlv,
142 der::GeneralizedTime* not_before,
143 der::GeneralizedTime* not_after) {
144 der::Parser parser(validity_tlv);
146 // Validity ::= SEQUENCE {
147 der::Parser validity_parser;
148 if (!parser.ReadSequence(&validity_parser))
149 return false;
151 // notBefore Time,
152 if (!ReadTime(&validity_parser, not_before))
153 return false;
155 // notAfter Time }
156 if (!ReadTime(&validity_parser, not_after))
157 return false;
159 // By definition the input was a single Validity sequence, so there shouldn't
160 // be unconsumed data.
161 if (parser.HasMore())
162 return false;
164 // The Validity type does not have an extension point.
165 if (validity_parser.HasMore())
166 return false;
168 // Note that RFC 5280 doesn't require notBefore to be <=
169 // notAfter, so that will not be considered a "parsing" error here. Instead it
170 // will be considered an expired certificate later when testing against the
171 // current timestamp.
172 return true;
175 } // namespace
177 ParsedTbsCertificate::ParsedTbsCertificate() {}
179 ParsedTbsCertificate::~ParsedTbsCertificate() {}
181 bool ParseCertificate(const der::Input& certificate_tlv,
182 ParsedCertificate* out) {
183 der::Parser parser(certificate_tlv);
185 // Certificate ::= SEQUENCE {
186 der::Parser certificate_parser;
187 if (!parser.ReadSequence(&certificate_parser))
188 return false;
190 // tbsCertificate TBSCertificate,
191 if (!ReadSequenceTLV(&certificate_parser, &out->tbs_certificate_tlv))
192 return false;
194 // signatureAlgorithm AlgorithmIdentifier,
195 if (!ReadSequenceTLV(&certificate_parser, &out->signature_algorithm_tlv))
196 return false;
198 // signatureValue BIT STRING }
199 if (!certificate_parser.ReadBitString(&out->signature_value))
200 return false;
202 // There isn't an extension point at the end of Certificate.
203 if (certificate_parser.HasMore())
204 return false;
206 // By definition the input was a single Certificate, so there shouldn't be
207 // unconsumed data.
208 if (parser.HasMore())
209 return false;
211 return true;
214 // From RFC 5280 section 4.1:
216 // TBSCertificate ::= SEQUENCE {
217 // version [0] EXPLICIT Version DEFAULT v1,
218 // serialNumber CertificateSerialNumber,
219 // signature AlgorithmIdentifier,
220 // issuer Name,
221 // validity Validity,
222 // subject Name,
223 // subjectPublicKeyInfo SubjectPublicKeyInfo,
224 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
225 // -- If present, version MUST be v2 or v3
226 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
227 // -- If present, version MUST be v2 or v3
228 // extensions [3] EXPLICIT Extensions OPTIONAL
229 // -- If present, version MUST be v3
230 // }
231 bool ParseTbsCertificate(const der::Input& tbs_tlv, ParsedTbsCertificate* out) {
232 der::Parser parser(tbs_tlv);
234 // Certificate ::= SEQUENCE {
235 der::Parser tbs_parser;
236 if (!parser.ReadSequence(&tbs_parser))
237 return false;
239 // version [0] EXPLICIT Version DEFAULT v1,
240 der::Input version;
241 bool has_version;
242 if (!tbs_parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &version,
243 &has_version)) {
244 return false;
246 if (has_version) {
247 if (!ParseVersion(version, &out->version))
248 return false;
249 if (out->version == CertificateVersion::V1) {
250 // The correct way to specify v1 is to omit the version field since v1 is
251 // the DEFAULT.
252 return false;
254 } else {
255 out->version = CertificateVersion::V1;
258 // serialNumber CertificateSerialNumber,
259 if (!tbs_parser.ReadTag(der::kInteger, &out->serial_number))
260 return false;
261 if (!VerifySerialNumber(out->serial_number))
262 return false;
264 // signature AlgorithmIdentifier,
265 if (!ReadSequenceTLV(&tbs_parser, &out->signature_algorithm_tlv))
266 return false;
268 // issuer Name,
269 if (!ReadSequenceTLV(&tbs_parser, &out->issuer_tlv))
270 return false;
272 // validity Validity,
273 der::Input validity_tlv;
274 if (!tbs_parser.ReadRawTLV(&validity_tlv))
275 return false;
276 if (!ParseValidity(validity_tlv, &out->validity_not_before,
277 &out->validity_not_after)) {
278 return false;
281 // subject Name,
282 if (!ReadSequenceTLV(&tbs_parser, &out->subject_tlv))
283 return false;
285 // subjectPublicKeyInfo SubjectPublicKeyInfo,
286 if (!ReadSequenceTLV(&tbs_parser, &out->spki_tlv))
287 return false;
289 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
290 // -- If present, version MUST be v2 or v3
291 der::Input issuer_unique_id;
292 if (!tbs_parser.ReadOptionalTag(der::ContextSpecificPrimitive(1),
293 &issuer_unique_id,
294 &out->has_issuer_unique_id)) {
295 return false;
297 if (out->has_issuer_unique_id) {
298 if (!der::ParseBitString(issuer_unique_id, &out->issuer_unique_id))
299 return false;
300 if (out->version != CertificateVersion::V2 &&
301 out->version != CertificateVersion::V3) {
302 return false;
306 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
307 // -- If present, version MUST be v2 or v3
308 der::Input subject_unique_id;
309 if (!tbs_parser.ReadOptionalTag(der::ContextSpecificPrimitive(2),
310 &subject_unique_id,
311 &out->has_subject_unique_id)) {
312 return false;
314 if (out->has_subject_unique_id) {
315 if (!der::ParseBitString(subject_unique_id, &out->subject_unique_id))
316 return false;
317 if (out->version != CertificateVersion::V2 &&
318 out->version != CertificateVersion::V3) {
319 return false;
323 // extensions [3] EXPLICIT Extensions OPTIONAL
324 // -- If present, version MUST be v3
325 if (!tbs_parser.ReadOptionalTag(der::ContextSpecificConstructed(3),
326 &out->extensions_tlv, &out->has_extensions)) {
327 return false;
329 if (out->has_extensions) {
330 // extensions_tlv must be a single element. Also check that it is a
331 // SEQUENCE.
332 if (!IsSequenceTLV(out->extensions_tlv))
333 return false;
334 if (out->version != CertificateVersion::V3)
335 return false;
338 // Note that there IS an extension point at the end of TBSCertificate
339 // (according to RFC 5912), so from that interpretation, unconsumed data would
340 // be allowed in |tbs_parser|.
342 // However because only v1, v2, and v3 certificates are supported by the
343 // parsing, there shouldn't be any subsequent data in those versions, so
344 // reject.
345 if (tbs_parser.HasMore())
346 return false;
348 // By definition the input was a single TBSCertificate, so there shouldn't be
349 // unconsumed data.
350 if (parser.HasMore())
351 return false;
353 return true;
356 } // namespace net