OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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/base/asn1_util.h" | 5 #include "net/base/asn1_util.h" |
6 | 6 |
7 namespace net { | 7 namespace net { |
8 | 8 |
9 namespace asn1 { | 9 namespace asn1 { |
10 | 10 |
11 bool ParseElement(base::StringPiece* in, | 11 bool ParseElement(base::StringPiece* in, |
12 unsigned tag_value, | 12 unsigned tag_value, |
13 base::StringPiece* out, | 13 base::StringPiece* out, |
14 unsigned *out_header_len) { | 14 unsigned *out_header_len) { |
15 const uint8* data = reinterpret_cast<const uint8*>(in->data()); | 15 const uint8* data = reinterpret_cast<const uint8*>(in->data()); |
16 | 16 |
| 17 // We don't support kAny and kOptional at the same time. |
| 18 if ((tag_value & kAny) && (tag_value & kOptional)) |
| 19 return false; |
| 20 |
| 21 if (in->empty() && (tag_value & kOptional)) { |
| 22 if (out_header_len) |
| 23 *out_header_len = 0; |
| 24 if (out) |
| 25 *out = base::StringPiece(); |
| 26 return true; |
| 27 } |
| 28 |
17 if (in->size() < 2) | 29 if (in->size() < 2) |
18 return false; | 30 return false; |
19 | 31 |
20 if (tag_value != kAny && static_cast<unsigned char>(data[0]) != tag_value) | 32 if (tag_value != kAny && |
| 33 static_cast<unsigned char>(data[0]) != (tag_value & 0xff)) { |
| 34 if (tag_value & kOptional) { |
| 35 if (out_header_len) |
| 36 *out_header_len = 0; |
| 37 if (out) |
| 38 *out = base::StringPiece(); |
| 39 return true; |
| 40 } |
21 return false; | 41 return false; |
| 42 } |
22 | 43 |
23 size_t len = 0; | 44 size_t len = 0; |
24 if ((data[1] & 0x80) == 0) { | 45 if ((data[1] & 0x80) == 0) { |
25 // short form length | 46 // short form length |
26 if (out_header_len) | 47 if (out_header_len) |
27 *out_header_len = 2; | 48 *out_header_len = 2; |
28 len = static_cast<size_t>(data[1]) + 2; | 49 len = static_cast<size_t>(data[1]) + 2; |
29 } else { | 50 } else { |
30 // long form length | 51 // long form length |
31 const unsigned num_bytes = data[1] & 0x7f; | 52 const unsigned num_bytes = data[1] & 0x7f; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 unsigned tag_value, | 85 unsigned tag_value, |
65 base::StringPiece* out) { | 86 base::StringPiece* out) { |
66 unsigned header_len; | 87 unsigned header_len; |
67 if (!ParseElement(in, tag_value, out, &header_len)) | 88 if (!ParseElement(in, tag_value, out, &header_len)) |
68 return false; | 89 return false; |
69 if (out) | 90 if (out) |
70 out->remove_prefix(header_len); | 91 out->remove_prefix(header_len); |
71 return true; | 92 return true; |
72 } | 93 } |
73 | 94 |
74 // SeekToSPKI changes |cert| so that it points to a suffix of the original | 95 // SeekToSPKI changes |cert| so that it points to a suffix of the |
75 // value where the suffix begins at the start of the ASN.1 SubjectPublicKeyInfo | 96 // TBSCertificate where the suffix begins at the start of the ASN.1 |
76 // value. | 97 // SubjectPublicKeyInfo value. |
77 static bool SeekToSPKI(base::StringPiece* cert) { | 98 static bool SeekToSPKI(base::StringPiece* cert) { |
78 // From RFC 5280, section 4.1 | 99 // From RFC 5280, section 4.1 |
79 // Certificate ::= SEQUENCE { | 100 // Certificate ::= SEQUENCE { |
80 // tbsCertificate TBSCertificate, | 101 // tbsCertificate TBSCertificate, |
81 // signatureAlgorithm AlgorithmIdentifier, | 102 // signatureAlgorithm AlgorithmIdentifier, |
82 // signatureValue BIT STRING } | 103 // signatureValue BIT STRING } |
83 | 104 |
84 // TBSCertificate ::= SEQUENCE { | 105 // TBSCertificate ::= SEQUENCE { |
85 // version [0] EXPLICIT Version DEFAULT v1, | 106 // version [0] EXPLICIT Version DEFAULT v1, |
86 // serialNumber CertificateSerialNumber, | 107 // serialNumber CertificateSerialNumber, |
87 // signature AlgorithmIdentifier, | 108 // signature AlgorithmIdentifier, |
88 // issuer Name, | 109 // issuer Name, |
89 // validity Validity, | 110 // validity Validity, |
90 // subject Name, | 111 // subject Name, |
91 // subjectPublicKeyInfo SubjectPublicKeyInfo, | 112 // subjectPublicKeyInfo SubjectPublicKeyInfo, |
92 | 113 |
93 base::StringPiece certificate; | 114 base::StringPiece certificate; |
94 if (!GetElement(cert, kSEQUENCE, &certificate)) | 115 if (!GetElement(cert, kSEQUENCE, &certificate)) |
95 return false; | 116 return false; |
96 | 117 |
| 118 // We don't allow junk after the certificate. |
| 119 if (!cert->empty()) |
| 120 return false; |
| 121 |
97 base::StringPiece tbs_certificate; | 122 base::StringPiece tbs_certificate; |
98 if (!GetElement(&certificate, kSEQUENCE, &tbs_certificate)) | 123 if (!GetElement(&certificate, kSEQUENCE, &tbs_certificate)) |
99 return false; | 124 return false; |
100 | 125 |
101 // The version is optional, so a failure to parse it is fine. | 126 if (!GetElement(&tbs_certificate, |
102 GetElement(&tbs_certificate, | 127 kOptional | kConstructed | kContextSpecific | 0, |
103 kCompound | kContextSpecific | 0, | 128 NULL)) { |
104 NULL); | 129 return false; |
| 130 } |
105 | 131 |
106 // serialNumber | 132 // serialNumber |
107 if (!GetElement(&tbs_certificate, kINTEGER, NULL)) | 133 if (!GetElement(&tbs_certificate, kINTEGER, NULL)) |
108 return false; | 134 return false; |
109 // signature | 135 // signature |
110 if (!GetElement(&tbs_certificate, kSEQUENCE, NULL)) | 136 if (!GetElement(&tbs_certificate, kSEQUENCE, NULL)) |
111 return false; | 137 return false; |
112 // issuer | 138 // issuer |
113 if (!GetElement(&tbs_certificate, kSEQUENCE, NULL)) | 139 if (!GetElement(&tbs_certificate, kSEQUENCE, NULL)) |
114 return false; | 140 return false; |
(...skipping 12 matching lines...) Expand all Loading... |
127 if (!SeekToSPKI(&cert)) | 153 if (!SeekToSPKI(&cert)) |
128 return false; | 154 return false; |
129 if (!ParseElement(&cert, kSEQUENCE, spki_out, NULL)) | 155 if (!ParseElement(&cert, kSEQUENCE, spki_out, NULL)) |
130 return false; | 156 return false; |
131 return true; | 157 return true; |
132 } | 158 } |
133 | 159 |
134 bool ExtractCRLURLsFromDERCert(base::StringPiece cert, | 160 bool ExtractCRLURLsFromDERCert(base::StringPiece cert, |
135 std::vector<base::StringPiece>* urls_out) { | 161 std::vector<base::StringPiece>* urls_out) { |
136 urls_out->clear(); | 162 urls_out->clear(); |
| 163 std::vector<base::StringPiece> tmp_urls_out; |
137 | 164 |
138 if (!SeekToSPKI(&cert)) | 165 if (!SeekToSPKI(&cert)) |
139 return false; | 166 return false; |
140 | 167 |
141 // From RFC 5280, section 4.1 | 168 // From RFC 5280, section 4.1 |
142 // TBSCertificate ::= SEQUENCE { | 169 // TBSCertificate ::= SEQUENCE { |
143 // ... | 170 // ... |
144 // subjectPublicKeyInfo SubjectPublicKeyInfo, | 171 // subjectPublicKeyInfo SubjectPublicKeyInfo, |
145 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, | 172 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, |
146 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, | 173 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, |
147 // extensions [3] EXPLICIT Extensions OPTIONAL | 174 // extensions [3] EXPLICIT Extensions OPTIONAL |
148 | 175 |
149 // subjectPublicKeyInfo | 176 // subjectPublicKeyInfo |
150 if (!GetElement(&cert, kSEQUENCE, NULL)) | 177 if (!GetElement(&cert, kSEQUENCE, NULL)) |
151 return false; | 178 return false; |
152 // issuerUniqueID | 179 // issuerUniqueID |
153 GetElement(&cert, kCompound | kContextSpecific | 1, NULL); | 180 if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 1, NULL)) |
| 181 return false; |
154 // subjectUniqueID | 182 // subjectUniqueID |
155 GetElement(&cert, kCompound | kContextSpecific | 2, NULL); | 183 if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 2, NULL)) |
| 184 return false; |
156 | 185 |
157 base::StringPiece extensions_seq; | 186 base::StringPiece extensions_seq; |
158 if (!GetElement(&cert, kCompound | kContextSpecific | 3, | 187 if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 3, |
159 &extensions_seq)) { | 188 &extensions_seq)) { |
160 // If there are no extensions, then there are no CRL URLs. | 189 return false; |
| 190 } |
| 191 |
| 192 if (extensions_seq.empty()) |
161 return true; | 193 return true; |
162 } | |
163 | 194 |
164 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension | 195 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension |
165 // Extension ::= SEQUENCE { | 196 // Extension ::= SEQUENCE { |
166 // extnID OBJECT IDENTIFIER, | 197 // extnID OBJECT IDENTIFIER, |
167 // critical BOOLEAN DEFAULT FALSE, | 198 // critical BOOLEAN DEFAULT FALSE, |
168 // extnValue OCTET STRING | 199 // extnValue OCTET STRING |
169 | 200 |
170 // |extensions_seq| was EXPLICITly tagged, so we still need to remove the | 201 // |extensions_seq| was EXPLICITly tagged, so we still need to remove the |
171 // ASN.1 SEQUENCE header. | 202 // ASN.1 SEQUENCE header. |
172 base::StringPiece extensions; | 203 base::StringPiece extensions; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 base::StringPiece distribution_points; | 242 base::StringPiece distribution_points; |
212 if (!GetElement(&extension_value, kSEQUENCE, &distribution_points)) | 243 if (!GetElement(&extension_value, kSEQUENCE, &distribution_points)) |
213 return false; | 244 return false; |
214 | 245 |
215 while (distribution_points.size() > 0) { | 246 while (distribution_points.size() > 0) { |
216 base::StringPiece distrib_point; | 247 base::StringPiece distrib_point; |
217 if (!GetElement(&distribution_points, kSEQUENCE, &distrib_point)) | 248 if (!GetElement(&distribution_points, kSEQUENCE, &distrib_point)) |
218 return false; | 249 return false; |
219 | 250 |
220 base::StringPiece name; | 251 base::StringPiece name; |
221 if (!GetElement(&distrib_point, kContextSpecific | kCompound | 0, | 252 if (!GetElement(&distrib_point, kContextSpecific | kConstructed | 0, |
222 &name)) { | 253 &name)) { |
223 // If it doesn't contain a name then we skip it. | 254 // If it doesn't contain a name then we skip it. |
224 continue; | 255 continue; |
225 } | 256 } |
226 | 257 |
227 if (GetElement(&distrib_point, kContextSpecific | 1, NULL)) { | 258 if (GetElement(&distrib_point, kContextSpecific | 1, NULL)) { |
228 // If it contains a subset of reasons then we skip it. We aren't | 259 // If it contains a subset of reasons then we skip it. We aren't |
229 // interested in subsets of CRLs and the RFC states that there MUST be | 260 // interested in subsets of CRLs and the RFC states that there MUST be |
230 // a CRL that covers all reasons. | 261 // a CRL that covers all reasons. |
231 continue; | 262 continue; |
232 } | 263 } |
233 | 264 |
234 if (GetElement(&distrib_point, kContextSpecific | kCompound | 2, NULL)) { | 265 if (GetElement(&distrib_point, |
| 266 kContextSpecific | kConstructed | 2, NULL)) { |
235 // If it contains a alternative issuer, then we skip it. | 267 // If it contains a alternative issuer, then we skip it. |
236 continue; | 268 continue; |
237 } | 269 } |
238 | 270 |
239 // DistributionPointName ::= CHOICE { | 271 // DistributionPointName ::= CHOICE { |
240 // fullName [0] GeneralNames, | 272 // fullName [0] GeneralNames, |
241 // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } | 273 // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } |
242 base::StringPiece general_names; | 274 base::StringPiece general_names; |
243 if (!GetElement(&name, kContextSpecific | kCompound | 0, &general_names)) | 275 if (!GetElement(&name, |
| 276 kContextSpecific | kConstructed | 0, &general_names)) { |
244 continue; | 277 continue; |
| 278 } |
245 | 279 |
246 // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName | 280 // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName |
247 // GeneralName ::= CHOICE { | 281 // GeneralName ::= CHOICE { |
248 // ... | 282 // ... |
249 // uniformResourceIdentifier [6] IA5String, | 283 // uniformResourceIdentifier [6] IA5String, |
250 // ... | 284 // ... |
251 while (general_names.size() > 0) { | 285 while (general_names.size() > 0) { |
252 base::StringPiece url; | 286 base::StringPiece url; |
253 if (GetElement(&general_names, kContextSpecific | 6, &url)) { | 287 if (GetElement(&general_names, kContextSpecific | 6, &url)) { |
254 urls_out->push_back(url); | 288 tmp_urls_out.push_back(url); |
255 } else { | 289 } else { |
256 if (!GetElement(&general_names, kAny, NULL)) | 290 if (!GetElement(&general_names, kAny, NULL)) |
257 return false; | 291 return false; |
258 } | 292 } |
259 } | 293 } |
260 } | 294 } |
261 } | 295 } |
262 | 296 |
| 297 urls_out->swap(tmp_urls_out); |
263 return true; | 298 return true; |
264 } | 299 } |
265 | 300 |
266 } // namespace asn1 | 301 } // namespace asn1 |
267 | 302 |
268 } // namespace net | 303 } // namespace net |
OLD | NEW |