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 28 matching lines...) Expand all Loading... | |
143 // ... | 169 // ... |
144 // subjectPublicKeyInfo SubjectPublicKeyInfo, | 170 // subjectPublicKeyInfo SubjectPublicKeyInfo, |
145 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, | 171 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, |
146 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, | 172 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, |
147 // extensions [3] EXPLICIT Extensions OPTIONAL | 173 // extensions [3] EXPLICIT Extensions OPTIONAL |
148 | 174 |
149 // subjectPublicKeyInfo | 175 // subjectPublicKeyInfo |
150 if (!GetElement(&cert, kSEQUENCE, NULL)) | 176 if (!GetElement(&cert, kSEQUENCE, NULL)) |
151 return false; | 177 return false; |
152 // issuerUniqueID | 178 // issuerUniqueID |
153 GetElement(&cert, kCompound | kContextSpecific | 1, NULL); | 179 if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 1, NULL)) |
180 return false; | |
154 // subjectUniqueID | 181 // subjectUniqueID |
155 GetElement(&cert, kCompound | kContextSpecific | 2, NULL); | 182 if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 2, NULL)) |
183 return false; | |
156 | 184 |
157 base::StringPiece extensions_seq; | 185 base::StringPiece extensions_seq; |
158 if (!GetElement(&cert, kCompound | kContextSpecific | 3, | 186 if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 3, |
159 &extensions_seq)) { | 187 &extensions_seq)) { |
160 // If there are no extensions, then there are no CRL URLs. | 188 return false; |
189 } | |
190 | |
191 if (extensions_seq.empty()) | |
161 return true; | 192 return true; |
162 } | |
163 | 193 |
164 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension | 194 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension |
165 // Extension ::= SEQUENCE { | 195 // Extension ::= SEQUENCE { |
166 // extnID OBJECT IDENTIFIER, | 196 // extnID OBJECT IDENTIFIER, |
167 // critical BOOLEAN DEFAULT FALSE, | 197 // critical BOOLEAN DEFAULT FALSE, |
168 // extnValue OCTET STRING | 198 // extnValue OCTET STRING |
169 | 199 |
170 // |extensions_seq| was EXPLICITly tagged, so we still need to remove the | 200 // |extensions_seq| was EXPLICITly tagged, so we still need to remove the |
171 // ASN.1 SEQUENCE header. | 201 // ASN.1 SEQUENCE header. |
172 base::StringPiece extensions; | 202 base::StringPiece extensions; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
211 base::StringPiece distribution_points; | 241 base::StringPiece distribution_points; |
212 if (!GetElement(&extension_value, kSEQUENCE, &distribution_points)) | 242 if (!GetElement(&extension_value, kSEQUENCE, &distribution_points)) |
213 return false; | 243 return false; |
214 | 244 |
215 while (distribution_points.size() > 0) { | 245 while (distribution_points.size() > 0) { |
216 base::StringPiece distrib_point; | 246 base::StringPiece distrib_point; |
217 if (!GetElement(&distribution_points, kSEQUENCE, &distrib_point)) | 247 if (!GetElement(&distribution_points, kSEQUENCE, &distrib_point)) |
218 return false; | 248 return false; |
219 | 249 |
220 base::StringPiece name; | 250 base::StringPiece name; |
221 if (!GetElement(&distrib_point, kContextSpecific | kCompound | 0, | 251 if (!GetElement(&distrib_point, kContextSpecific | kConstructed | 0, |
222 &name)) { | 252 &name)) { |
223 // If it doesn't contain a name then we skip it. | 253 // If it doesn't contain a name then we skip it. |
224 continue; | 254 continue; |
225 } | 255 } |
226 | 256 |
227 if (GetElement(&distrib_point, kContextSpecific | 1, NULL)) { | 257 if (GetElement(&distrib_point, kContextSpecific | 1, NULL)) { |
228 // If it contains a subset of reasons then we skip it. We aren't | 258 // 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 | 259 // interested in subsets of CRLs and the RFC states that there MUST be |
230 // a CRL that covers all reasons. | 260 // a CRL that covers all reasons. |
231 continue; | 261 continue; |
232 } | 262 } |
233 | 263 |
234 if (GetElement(&distrib_point, kContextSpecific | kCompound | 2, NULL)) { | 264 if (GetElement(&distrib_point, |
265 kContextSpecific | kConstructed | 2, NULL)) { | |
235 // If it contains a alternative issuer, then we skip it. | 266 // If it contains a alternative issuer, then we skip it. |
236 continue; | 267 continue; |
237 } | 268 } |
238 | 269 |
239 // DistributionPointName ::= CHOICE { | 270 // DistributionPointName ::= CHOICE { |
240 // fullName [0] GeneralNames, | 271 // fullName [0] GeneralNames, |
241 // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } | 272 // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } |
242 base::StringPiece general_names; | 273 base::StringPiece general_names; |
243 if (!GetElement(&name, kContextSpecific | kCompound | 0, &general_names)) | 274 if (!GetElement(&name, |
275 kContextSpecific | kConstructed | 0, &general_names)) { | |
244 continue; | 276 continue; |
277 } | |
245 | 278 |
246 // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName | 279 // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName |
247 // GeneralName ::= CHOICE { | 280 // GeneralName ::= CHOICE { |
248 // ... | 281 // ... |
249 // uniformResourceIdentifier [6] IA5String, | 282 // uniformResourceIdentifier [6] IA5String, |
250 // ... | 283 // ... |
251 while (general_names.size() > 0) { | 284 while (general_names.size() > 0) { |
252 base::StringPiece url; | 285 base::StringPiece url; |
253 if (GetElement(&general_names, kContextSpecific | 6, &url)) { | 286 if (GetElement(&general_names, kContextSpecific | 6, &url)) { |
254 urls_out->push_back(url); | 287 urls_out->push_back(url); |
255 } else { | 288 } else { |
256 if (!GetElement(&general_names, kAny, NULL)) | 289 if (!GetElement(&general_names, kAny, NULL)) { |
290 urls_out->clear(); | |
257 return false; | 291 return false; |
wtc
2011/06/07 18:17:54
I think some other "return false" statements also
| |
292 } | |
258 } | 293 } |
259 } | 294 } |
260 } | 295 } |
261 } | 296 } |
262 | 297 |
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 |