Chromium Code Reviews| 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 #include "net/der/input.h" | 7 #include "net/der/input.h" |
| 8 #include "net/der/parser.h" | 8 #include "net/der/parser.h" |
| 9 | 9 |
| 10 namespace net { | 10 namespace net { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 63 return false; | 63 return false; |
| 64 // validity | 64 // validity |
| 65 if (!tbs_certificate->SkipTag(der::kSequence)) | 65 if (!tbs_certificate->SkipTag(der::kSequence)) |
| 66 return false; | 66 return false; |
| 67 // subject | 67 // subject |
| 68 if (!tbs_certificate->SkipTag(der::kSequence)) | 68 if (!tbs_certificate->SkipTag(der::kSequence)) |
| 69 return false; | 69 return false; |
| 70 return true; | 70 return true; |
| 71 } | 71 } |
| 72 | 72 |
| 73 // Parses input |in| which should point to the beginning of a | |
| 74 // Certificate. If parsing fails, this function returns false, with | |
| 75 // |*extensions_present| and |*extensions_parser| left in an undefined | |
| 76 // state. If parsing succeeds and extensions are present, this function | |
| 77 // sets |*extensions_present| to true and sets |*extensions_parser| | |
| 78 // ready to parse the Extensions. If extensions are not present, it sets | |
| 79 // |*extensions_present| to false and |*extensions_parser| is left in an | |
| 80 // undefined state. | |
| 81 bool SeekToExtensions(der::Input in, | |
| 82 bool* extensions_present, | |
| 83 der::Parser* extensions_parser) { | |
| 84 bool present; | |
| 85 der::Parser tbs_cert_parser; | |
| 86 if (!SeekToSPKI(in, &tbs_cert_parser)) | |
| 87 return false; | |
| 88 | |
| 89 // From RFC 5280, section 4.1 | |
| 90 // TBSCertificate ::= SEQUENCE { | |
| 91 // ... | |
| 92 // subjectPublicKeyInfo SubjectPublicKeyInfo, | |
| 93 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, | |
| 94 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, | |
| 95 // extensions [3] EXPLICIT Extensions OPTIONAL } | |
| 96 | |
| 97 // subjectPublicKeyInfo | |
| 98 if (!tbs_cert_parser.SkipTag(der::kSequence)) | |
| 99 return false; | |
| 100 // issuerUniqueID | |
| 101 if (!tbs_cert_parser.SkipOptionalTag( | |
| 102 der::kTagConstructed | der::kTagContextSpecific | 1, &present)) { | |
| 103 return false; | |
| 104 } | |
| 105 // subjectUniqueID | |
| 106 if (!tbs_cert_parser.SkipOptionalTag( | |
| 107 der::kTagConstructed | der::kTagContextSpecific | 2, &present)) { | |
| 108 return false; | |
| 109 } | |
| 110 | |
| 111 der::Input extensions; | |
| 112 if (!tbs_cert_parser.ReadOptionalTag( | |
| 113 der::kTagConstructed | der::kTagContextSpecific | 3, &extensions, | |
| 114 &present)) { | |
| 115 return false; | |
| 116 } | |
| 117 | |
| 118 if (!present) { | |
| 119 *extensions_present = false; | |
| 120 return true; | |
| 121 } | |
| 122 | |
| 123 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension | |
| 124 // Extension ::= SEQUENCE { | |
| 125 // extnID OBJECT IDENTIFIER, | |
| 126 // critical BOOLEAN DEFAULT FALSE, | |
| 127 // extnValue OCTET STRING } | |
| 128 | |
| 129 // |extensions| was EXPLICITly tagged, so we still need to remove the | |
| 130 // ASN.1 SEQUENCE header. | |
| 131 der::Parser explicit_extensions_parser(extensions); | |
| 132 if (!explicit_extensions_parser.ReadSequence(extensions_parser)) | |
| 133 return false; | |
| 134 | |
| 135 if (explicit_extensions_parser.HasMore()) | |
| 136 return false; | |
| 137 | |
| 138 *extensions_present = true; | |
| 139 return true; | |
| 140 } | |
| 141 | |
| 73 } // namespace | 142 } // namespace |
| 74 | 143 |
| 75 bool ExtractSPKIFromDERCert(base::StringPiece cert, | 144 bool ExtractSPKIFromDERCert(base::StringPiece cert, |
| 76 base::StringPiece* spki_out) { | 145 base::StringPiece* spki_out) { |
| 77 der::Parser parser; | 146 der::Parser parser; |
| 78 if (!SeekToSPKI(der::Input(cert), &parser)) | 147 if (!SeekToSPKI(der::Input(cert), &parser)) |
| 79 return false; | 148 return false; |
| 80 der::Input spki; | 149 der::Input spki; |
| 81 if (!parser.ReadRawTLV(&spki)) | 150 if (!parser.ReadRawTLV(&spki)) |
| 82 return false; | 151 return false; |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 111 return false; | 180 return false; |
| 112 *spk_out = spk.AsStringPiece(); | 181 *spk_out = spk.AsStringPiece(); |
| 113 return true; | 182 return true; |
| 114 } | 183 } |
| 115 | 184 |
| 116 | 185 |
| 117 bool ExtractCRLURLsFromDERCert(base::StringPiece cert, | 186 bool ExtractCRLURLsFromDERCert(base::StringPiece cert, |
| 118 std::vector<base::StringPiece>* urls_out) { | 187 std::vector<base::StringPiece>* urls_out) { |
| 119 urls_out->clear(); | 188 urls_out->clear(); |
| 120 std::vector<base::StringPiece> tmp_urls_out; | 189 std::vector<base::StringPiece> tmp_urls_out; |
| 121 | |
| 122 bool present; | 190 bool present; |
| 123 der::Parser tbs_cert_parser; | 191 der::Parser extensions_parser; |
| 124 if (!SeekToSPKI(der::Input(cert), &tbs_cert_parser)) | 192 if (!SeekToExtensions(der::Input(cert), &present, &extensions_parser)) |
| 125 return false; | 193 return false; |
| 126 | 194 |
| 127 // From RFC 5280, section 4.1 | 195 if (!present) { |
| 128 // TBSCertificate ::= SEQUENCE { | 196 LOG(ERROR) << "No extensions!"; |
|
eroman
2016/10/21 01:49:22
nit: Why add the log statement?
estark
2016/10/21 02:11:29
Doh, sorry, thought I deleted that. It's gone now.
| |
| 129 // ... | 197 return true; |
| 130 // subjectPublicKeyInfo SubjectPublicKeyInfo, | |
| 131 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, | |
| 132 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, | |
| 133 // extensions [3] EXPLICIT Extensions OPTIONAL } | |
| 134 | |
| 135 // subjectPublicKeyInfo | |
| 136 if (!tbs_cert_parser.SkipTag(der::kSequence)) | |
| 137 return false; | |
| 138 // issuerUniqueID | |
| 139 if (!tbs_cert_parser.SkipOptionalTag( | |
| 140 der::kTagConstructed | der::kTagContextSpecific | 1, &present)) { | |
| 141 return false; | |
| 142 } | 198 } |
| 143 // subjectUniqueID | |
| 144 if (!tbs_cert_parser.SkipOptionalTag( | |
| 145 der::kTagConstructed | der::kTagContextSpecific | 2, &present)) { | |
| 146 return false; | |
| 147 } | |
| 148 | |
| 149 der::Input extensions; | |
| 150 if (!tbs_cert_parser.ReadOptionalTag( | |
| 151 der::kTagConstructed | der::kTagContextSpecific | 3, &extensions, | |
| 152 &present)) { | |
| 153 return false; | |
| 154 } | |
| 155 | |
| 156 if (!present) | |
| 157 return true; | |
| 158 | |
| 159 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension | |
| 160 // Extension ::= SEQUENCE { | |
| 161 // extnID OBJECT IDENTIFIER, | |
| 162 // critical BOOLEAN DEFAULT FALSE, | |
| 163 // extnValue OCTET STRING } | |
| 164 | |
| 165 // |extensions| was EXPLICITly tagged, so we still need to remove the | |
| 166 // ASN.1 SEQUENCE header. | |
| 167 der::Parser explicit_extensions_parser(extensions); | |
| 168 der::Parser extensions_parser; | |
| 169 if (!explicit_extensions_parser.ReadSequence(&extensions_parser)) | |
| 170 return false; | |
| 171 | |
| 172 if (explicit_extensions_parser.HasMore()) | |
| 173 return false; | |
| 174 | 199 |
| 175 while (extensions_parser.HasMore()) { | 200 while (extensions_parser.HasMore()) { |
| 176 der::Parser extension_parser; | 201 der::Parser extension_parser; |
| 177 if (!extensions_parser.ReadSequence(&extension_parser)) | 202 if (!extensions_parser.ReadSequence(&extension_parser)) |
| 178 return false; | 203 return false; |
| 179 | 204 |
| 180 der::Input oid; | 205 der::Input oid; |
| 181 if (!extension_parser.ReadTag(der::kOid, &oid)) | 206 if (!extension_parser.ReadTag(der::kOid, &oid)) |
| 182 return false; | 207 return false; |
| 183 | 208 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 } | 307 } |
| 283 } | 308 } |
| 284 } | 309 } |
| 285 } | 310 } |
| 286 } | 311 } |
| 287 | 312 |
| 288 urls_out->swap(tmp_urls_out); | 313 urls_out->swap(tmp_urls_out); |
| 289 return true; | 314 return true; |
| 290 } | 315 } |
| 291 | 316 |
| 317 bool HasTLSFeatureExtension(base::StringPiece cert, | |
| 318 bool* has_tls_feature_extension) { | |
| 319 bool present; | |
| 320 der::Parser extensions_parser; | |
| 321 if (!SeekToExtensions(der::Input(cert), &present, &extensions_parser)) | |
| 322 return false; | |
| 323 if (!present) { | |
| 324 *has_tls_feature_extension = false; | |
| 325 return true; | |
| 326 } | |
| 327 | |
| 328 while (extensions_parser.HasMore()) { | |
| 329 der::Parser extension_parser; | |
| 330 if (!extensions_parser.ReadSequence(&extension_parser)) | |
| 331 return false; | |
| 332 | |
| 333 der::Input oid; | |
| 334 if (!extension_parser.ReadTag(der::kOid, &oid)) | |
| 335 return false; | |
| 336 | |
| 337 // kTLSFeatureExtensionOID is the DER encoding of the OID for the | |
| 338 // X.509 TLS Feature Extension. | |
| 339 static const uint8_t kTLSFeatureExtensionOID[] = {0x2B, 0x06, 0x01, 0x05, | |
| 340 0x05, 0x07, 0x01, 0x18}; | |
| 341 | |
| 342 if (oid == der::Input(kTLSFeatureExtensionOID)) { | |
| 343 *has_tls_feature_extension = true; | |
| 344 return true; | |
| 345 } | |
| 346 } | |
| 347 | |
| 348 *has_tls_feature_extension = false; | |
| 349 return true; | |
| 350 } | |
| 351 | |
| 292 } // namespace asn1 | 352 } // namespace asn1 |
| 293 | 353 |
| 294 } // namespace net | 354 } // namespace net |
| OLD | NEW |