Chromium Code Reviews| 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 |