| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/asn1_util.h" | 5 #include "net/cert/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. | 17 // We don't support kAny and kOptional at the same time. |
| 18 if ((tag_value & kAny) && (tag_value & kOptional)) | 18 if ((tag_value & kAny) && (tag_value & kOptional)) |
| 19 return false; | 19 return false; |
| 20 | 20 |
| 21 if (in->empty() && (tag_value & kOptional)) { | 21 if (in->empty() && (tag_value & kOptional)) { |
| 22 if (out_header_len) | 22 if (out_header_len) |
| 23 *out_header_len = 0; | 23 *out_header_len = 0; |
| 24 if (out) | 24 if (out) |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 177 base::StringPiece algorithm; | 177 base::StringPiece algorithm; |
| 178 if (!asn1::GetElement(&spki_contents, asn1::kSEQUENCE, &algorithm)) | 178 if (!asn1::GetElement(&spki_contents, asn1::kSEQUENCE, &algorithm)) |
| 179 return false; | 179 return false; |
| 180 | 180 |
| 181 // Extract the subjectPublicKey field. | 181 // Extract the subjectPublicKey field. |
| 182 if (!asn1::GetElement(&spki_contents, asn1::kBITSTRING, spk_out)) | 182 if (!asn1::GetElement(&spki_contents, asn1::kBITSTRING, spk_out)) |
| 183 return false; | 183 return false; |
| 184 return true; | 184 return true; |
| 185 } | 185 } |
| 186 | 186 |
| 187 | |
| 188 bool ExtractCRLURLsFromDERCert(base::StringPiece cert, | 187 bool ExtractCRLURLsFromDERCert(base::StringPiece cert, |
| 189 std::vector<base::StringPiece>* urls_out) { | 188 std::vector<base::StringPiece>* urls_out) { |
| 190 urls_out->clear(); | 189 urls_out->clear(); |
| 191 std::vector<base::StringPiece> tmp_urls_out; | 190 std::vector<base::StringPiece> tmp_urls_out; |
| 192 | 191 |
| 193 if (!SeekToSPKI(&cert)) | 192 if (!SeekToSPKI(&cert)) |
| 194 return false; | 193 return false; |
| 195 | 194 |
| 196 // From RFC 5280, section 4.1 | 195 // From RFC 5280, section 4.1 |
| 197 // TBSCertificate ::= SEQUENCE { | 196 // TBSCertificate ::= SEQUENCE { |
| 198 // ... | 197 // ... |
| 199 // subjectPublicKeyInfo SubjectPublicKeyInfo, | 198 // subjectPublicKeyInfo SubjectPublicKeyInfo, |
| 200 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, | 199 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, |
| 201 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, | 200 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, |
| 202 // extensions [3] EXPLICIT Extensions OPTIONAL | 201 // extensions [3] EXPLICIT Extensions OPTIONAL |
| 203 | 202 |
| 204 // subjectPublicKeyInfo | 203 // subjectPublicKeyInfo |
| 205 if (!GetElement(&cert, kSEQUENCE, NULL)) | 204 if (!GetElement(&cert, kSEQUENCE, NULL)) |
| 206 return false; | 205 return false; |
| 207 // issuerUniqueID | 206 // issuerUniqueID |
| 208 if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 1, NULL)) | 207 if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 1, NULL)) |
| 209 return false; | 208 return false; |
| 210 // subjectUniqueID | 209 // subjectUniqueID |
| 211 if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 2, NULL)) | 210 if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 2, NULL)) |
| 212 return false; | 211 return false; |
| 213 | 212 |
| 214 base::StringPiece extensions_seq; | 213 base::StringPiece extensions_seq; |
| 215 if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 3, | 214 if (!GetElement(&cert, |
| 215 kOptional | kConstructed | kContextSpecific | 3, |
| 216 &extensions_seq)) { | 216 &extensions_seq)) { |
| 217 return false; | 217 return false; |
| 218 } | 218 } |
| 219 | 219 |
| 220 if (extensions_seq.empty()) | 220 if (extensions_seq.empty()) |
| 221 return true; | 221 return true; |
| 222 | 222 |
| 223 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension | 223 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension |
| 224 // Extension ::= SEQUENCE { | 224 // Extension ::= SEQUENCE { |
| 225 // extnID OBJECT IDENTIFIER, | 225 // extnID OBJECT IDENTIFIER, |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 base::StringPiece distribution_points; | 270 base::StringPiece distribution_points; |
| 271 if (!GetElement(&extension_value, kSEQUENCE, &distribution_points)) | 271 if (!GetElement(&extension_value, kSEQUENCE, &distribution_points)) |
| 272 return false; | 272 return false; |
| 273 | 273 |
| 274 while (distribution_points.size() > 0) { | 274 while (distribution_points.size() > 0) { |
| 275 base::StringPiece distrib_point; | 275 base::StringPiece distrib_point; |
| 276 if (!GetElement(&distribution_points, kSEQUENCE, &distrib_point)) | 276 if (!GetElement(&distribution_points, kSEQUENCE, &distrib_point)) |
| 277 return false; | 277 return false; |
| 278 | 278 |
| 279 base::StringPiece name; | 279 base::StringPiece name; |
| 280 if (!GetElement(&distrib_point, kContextSpecific | kConstructed | 0, | 280 if (!GetElement( |
| 281 &name)) { | 281 &distrib_point, kContextSpecific | kConstructed | 0, &name)) { |
| 282 // If it doesn't contain a name then we skip it. | 282 // If it doesn't contain a name then we skip it. |
| 283 continue; | 283 continue; |
| 284 } | 284 } |
| 285 | 285 |
| 286 if (GetElement(&distrib_point, kContextSpecific | 1, NULL)) { | 286 if (GetElement(&distrib_point, kContextSpecific | 1, NULL)) { |
| 287 // If it contains a subset of reasons then we skip it. We aren't | 287 // If it contains a subset of reasons then we skip it. We aren't |
| 288 // interested in subsets of CRLs and the RFC states that there MUST be | 288 // interested in subsets of CRLs and the RFC states that there MUST be |
| 289 // a CRL that covers all reasons. | 289 // a CRL that covers all reasons. |
| 290 continue; | 290 continue; |
| 291 } | 291 } |
| 292 | 292 |
| 293 if (GetElement(&distrib_point, | 293 if (GetElement( |
| 294 kContextSpecific | kConstructed | 2, NULL)) { | 294 &distrib_point, kContextSpecific | kConstructed | 2, NULL)) { |
| 295 // If it contains a alternative issuer, then we skip it. | 295 // If it contains a alternative issuer, then we skip it. |
| 296 continue; | 296 continue; |
| 297 } | 297 } |
| 298 | 298 |
| 299 // DistributionPointName ::= CHOICE { | 299 // DistributionPointName ::= CHOICE { |
| 300 // fullName [0] GeneralNames, | 300 // fullName [0] GeneralNames, |
| 301 // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } | 301 // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } |
| 302 base::StringPiece general_names; | 302 base::StringPiece general_names; |
| 303 if (!GetElement(&name, | 303 if (!GetElement( |
| 304 kContextSpecific | kConstructed | 0, &general_names)) { | 304 &name, kContextSpecific | kConstructed | 0, &general_names)) { |
| 305 continue; | 305 continue; |
| 306 } | 306 } |
| 307 | 307 |
| 308 // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName | 308 // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName |
| 309 // GeneralName ::= CHOICE { | 309 // GeneralName ::= CHOICE { |
| 310 // ... | 310 // ... |
| 311 // uniformResourceIdentifier [6] IA5String, | 311 // uniformResourceIdentifier [6] IA5String, |
| 312 // ... | 312 // ... |
| 313 while (general_names.size() > 0) { | 313 while (general_names.size() > 0) { |
| 314 base::StringPiece url; | 314 base::StringPiece url; |
| 315 if (GetElement(&general_names, kContextSpecific | 6, &url)) { | 315 if (GetElement(&general_names, kContextSpecific | 6, &url)) { |
| 316 tmp_urls_out.push_back(url); | 316 tmp_urls_out.push_back(url); |
| 317 } else { | 317 } else { |
| 318 if (!GetElement(&general_names, kAny, NULL)) | 318 if (!GetElement(&general_names, kAny, NULL)) |
| 319 return false; | 319 return false; |
| 320 } | 320 } |
| 321 } | 321 } |
| 322 } | 322 } |
| 323 } | 323 } |
| 324 | 324 |
| 325 urls_out->swap(tmp_urls_out); | 325 urls_out->swap(tmp_urls_out); |
| 326 return true; | 326 return true; |
| 327 } | 327 } |
| 328 | 328 |
| 329 } // namespace asn1 | 329 } // namespace asn1 |
| 330 | 330 |
| 331 } // namespace net | 331 } // namespace net |
| OLD | NEW |