1 // Copyright (c) 2011 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/base/asn1_util.h"
6
7 namespace net {
8
9 namespace asn1 {
10
ParseElement(base::StringPiece * in,unsigned tag_value,base::StringPiece * out,unsigned * out_header_len)11 bool ParseElement(base::StringPiece* in,
12 unsigned tag_value,
13 base::StringPiece* out,
14 unsigned *out_header_len) {
15 const uint8* data = reinterpret_cast<const uint8*>(in->data());
16
17 if (in->size() < 2)
18 return false;
19
20 if (static_cast<unsigned char>(data[0]) != tag_value)
21 return false;
22
23 size_t len = 0;
24 if ((data[1] & 0x80) == 0) {
25 // short form length
26 if (out_header_len)
27 *out_header_len = 2;
28 len = static_cast<size_t>(data[1]) + 2;
29 } else {
30 // long form length
31 const unsigned num_bytes = data[1] & 0x7f;
32 if (num_bytes == 0 || num_bytes > 2)
33 return false;
34 if (in->size() < 2 + num_bytes)
35 return false;
36 len = data[2];
37 if (num_bytes == 2) {
38 if (len == 0) {
39 // the length encoding must be minimal.
40 return false;
41 }
42 len <<= 8;
43 len += data[3];
44 }
45 if (len < 128) {
46 // the length should have been encoded in short form. This distinguishes
47 // DER from BER encoding.
48 return false;
49 }
50 if (out_header_len)
51 *out_header_len = 2 + num_bytes;
52 len += 2 + num_bytes;
53 }
54
55 if (in->size() < len)
56 return false;
57 if (out)
58 *out = base::StringPiece(in->data(), len);
59 in->remove_prefix(len);
60 return true;
61 }
62
GetElement(base::StringPiece * in,unsigned tag_value,base::StringPiece * out)63 bool GetElement(base::StringPiece* in,
64 unsigned tag_value,
65 base::StringPiece* out) {
66 unsigned header_len;
67 if (!ParseElement(in, tag_value, out, &header_len))
68 return false;
69 if (out)
70 out->remove_prefix(header_len);
71 return true;
72 }
73
ExtractSPKIFromDERCert(base::StringPiece cert,base::StringPiece * spki_out)74 bool ExtractSPKIFromDERCert(base::StringPiece cert,
75 base::StringPiece* spki_out) {
76 // From RFC 5280, section 4.1
77 // Certificate ::= SEQUENCE {
78 // tbsCertificate TBSCertificate,
79 // signatureAlgorithm AlgorithmIdentifier,
80 // signatureValue BIT STRING }
81
82 // TBSCertificate ::= SEQUENCE {
83 // version [0] EXPLICIT Version DEFAULT v1,
84 // serialNumber CertificateSerialNumber,
85 // signature AlgorithmIdentifier,
86 // issuer Name,
87 // validity Validity,
88 // subject Name,
89 // subjectPublicKeyInfo SubjectPublicKeyInfo,
90
91 base::StringPiece certificate;
92 if (!asn1::GetElement(&cert, asn1::kSEQUENCE, &certificate))
93 return false;
94
95 base::StringPiece tbs_certificate;
96 if (!asn1::GetElement(&certificate, asn1::kSEQUENCE, &tbs_certificate))
97 return false;
98
99 // The version is optional, so a failure to parse it is fine.
100 asn1::GetElement(&tbs_certificate,
101 asn1::kCompound | asn1::kContextSpecific | 0,
102 NULL);
103
104 // serialNumber
105 if (!asn1::GetElement(&tbs_certificate, asn1::kINTEGER, NULL))
106 return false;
107 // signature
108 if (!asn1::GetElement(&tbs_certificate, asn1::kSEQUENCE, NULL))
109 return false;
110 // issuer
111 if (!asn1::GetElement(&tbs_certificate, asn1::kSEQUENCE, NULL))
112 return false;
113 // validity
114 if (!asn1::GetElement(&tbs_certificate, asn1::kSEQUENCE, NULL))
115 return false;
116 // subject
117 if (!asn1::GetElement(&tbs_certificate, asn1::kSEQUENCE, NULL))
118 return false;
119 // subjectPublicKeyInfo
120 if (!asn1::ParseElement(&tbs_certificate, asn1::kSEQUENCE, spki_out, NULL))
121 return false;
122 return true;
123 }
124
125 } // namespace asn1
126
127 } // namespace net
128