OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/internal/parse_certificate.h" | 5 #include "net/cert/internal/parse_certificate.h" |
6 | 6 |
7 #include "net/der/input.h" | 7 #include "net/der/input.h" |
8 #include "net/der/parse_values.h" | 8 #include "net/der/parse_values.h" |
9 #include "net/der/parser.h" | 9 #include "net/der/parser.h" |
10 | 10 |
(...skipping 10 matching lines...) Expand all Loading... |
21 // Should by a single SEQUENCE by definition of the function. | 21 // Should by a single SEQUENCE by definition of the function. |
22 return !parser.HasMore(); | 22 return !parser.HasMore(); |
23 } | 23 } |
24 | 24 |
25 // Reads a SEQUENCE from |parser| and writes the full tag-length-value into | 25 // Reads a SEQUENCE from |parser| and writes the full tag-length-value into |
26 // |out|. On failure |parser| may or may not have been advanced. | 26 // |out|. On failure |parser| may or may not have been advanced. |
27 WARN_UNUSED_RESULT bool ReadSequenceTLV(der::Parser* parser, der::Input* out) { | 27 WARN_UNUSED_RESULT bool ReadSequenceTLV(der::Parser* parser, der::Input* out) { |
28 return parser->ReadRawTLV(out) && IsSequenceTLV(*out); | 28 return parser->ReadRawTLV(out) && IsSequenceTLV(*out); |
29 } | 29 } |
30 | 30 |
| 31 // Parses a Version according to RFC 5280: |
| 32 // |
| 33 // Version ::= INTEGER { v1(0), v2(1), v3(2) } |
| 34 // |
| 35 // No value other that v1, v2, or v3 is allowed (and if given will fail). RFC |
| 36 // 5280 minimally requires the handling of v3 (and overwhelmingly these are the |
| 37 // certificate versions in use today): |
| 38 // |
| 39 // Implementations SHOULD be prepared to accept any version certificate. |
| 40 // At a minimum, conforming implementations MUST recognize version 3 |
| 41 // certificates. |
| 42 WARN_UNUSED_RESULT bool ParseVersion(const der::Input& in, |
| 43 CertificateVersion* version) { |
| 44 der::Parser parser(in); |
| 45 uint64_t version64; |
| 46 if (!parser.ReadUint64(&version64)) |
| 47 return false; |
| 48 |
| 49 switch (version64) { |
| 50 case 0: |
| 51 *version = CertificateVersion::V1; |
| 52 break; |
| 53 case 1: |
| 54 *version = CertificateVersion::V2; |
| 55 break; |
| 56 case 2: |
| 57 *version = CertificateVersion::V3; |
| 58 break; |
| 59 default: |
| 60 // Don't allow any other version identifier. |
| 61 return false; |
| 62 } |
| 63 |
| 64 // By definition the input to this function was a single INTEGER, so there |
| 65 // shouldn't be anything else after it. |
| 66 return !parser.HasMore(); |
| 67 } |
| 68 |
| 69 // Returns true if the given serial number (CertificateSerialNumber in RFC 5280) |
| 70 // is valid: |
| 71 // |
| 72 // CertificateSerialNumber ::= INTEGER |
| 73 // |
| 74 // The input to this function is the (unverified) value octets of the INTEGER. |
| 75 // This function will verify that: |
| 76 // |
| 77 // * The octets are a valid DER-encoding of an INTEGER (for instance, minimal |
| 78 // encoding length). |
| 79 // |
| 80 // * No more than 20 octets are used. |
| 81 // |
| 82 // Note that it DOES NOT reject non-positive values (zero or negative). |
| 83 // |
| 84 // For reference, here is what RFC 5280 section 4.1.2.2 says: |
| 85 // |
| 86 // Given the uniqueness requirements above, serial numbers can be |
| 87 // expected to contain long integers. Certificate users MUST be able to |
| 88 // handle serialNumber values up to 20 octets. Conforming CAs MUST NOT |
| 89 // use serialNumber values longer than 20 octets. |
| 90 // |
| 91 // Note: Non-conforming CAs may issue certificates with serial numbers |
| 92 // that are negative or zero. Certificate users SHOULD be prepared to |
| 93 // gracefully handle such certificates. |
| 94 WARN_UNUSED_RESULT bool VerifySerialNumber(const der::Input& value) { |
| 95 bool unused_negative; |
| 96 if (!der::IsValidInteger(value, &unused_negative)) |
| 97 return false; |
| 98 |
| 99 // Check if the serial number is too long per RFC 5280. |
| 100 if (value.Length() > 20) |
| 101 return false; |
| 102 |
| 103 return true; |
| 104 } |
| 105 |
31 } // namespace | 106 } // namespace |
32 | 107 |
| 108 ParsedTbsCertificate::ParsedTbsCertificate() {} |
| 109 |
| 110 ParsedTbsCertificate::~ParsedTbsCertificate() {} |
| 111 |
33 bool ParseCertificate(const der::Input& certificate_tlv, | 112 bool ParseCertificate(const der::Input& certificate_tlv, |
34 ParsedCertificate* out) { | 113 ParsedCertificate* out) { |
35 der::Parser parser(certificate_tlv); | 114 der::Parser parser(certificate_tlv); |
36 | 115 |
37 // Certificate ::= SEQUENCE { | 116 // Certificate ::= SEQUENCE { |
38 der::Parser certificate_parser; | 117 der::Parser certificate_parser; |
39 if (!parser.ReadSequence(&certificate_parser)) | 118 if (!parser.ReadSequence(&certificate_parser)) |
40 return false; | 119 return false; |
41 | 120 |
42 // tbsCertificate TBSCertificate, | 121 // tbsCertificate TBSCertificate, |
(...skipping 13 matching lines...) Expand all Loading... |
56 return false; | 135 return false; |
57 | 136 |
58 // By definition the input was a single Certificate, so there shouldn't be | 137 // By definition the input was a single Certificate, so there shouldn't be |
59 // unconsumed data. | 138 // unconsumed data. |
60 if (parser.HasMore()) | 139 if (parser.HasMore()) |
61 return false; | 140 return false; |
62 | 141 |
63 return true; | 142 return true; |
64 } | 143 } |
65 | 144 |
| 145 // From RFC 5280 section 4.1: |
| 146 // |
| 147 // TBSCertificate ::= SEQUENCE { |
| 148 // version [0] EXPLICIT Version DEFAULT v1, |
| 149 // serialNumber CertificateSerialNumber, |
| 150 // signature AlgorithmIdentifier, |
| 151 // issuer Name, |
| 152 // validity Validity, |
| 153 // subject Name, |
| 154 // subjectPublicKeyInfo SubjectPublicKeyInfo, |
| 155 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, |
| 156 // -- If present, version MUST be v2 or v3 |
| 157 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, |
| 158 // -- If present, version MUST be v2 or v3 |
| 159 // extensions [3] EXPLICIT Extensions OPTIONAL |
| 160 // -- If present, version MUST be v3 |
| 161 // } |
| 162 bool ParseTbsCertificate(const der::Input& tbs_tlv, ParsedTbsCertificate* out) { |
| 163 der::Parser parser(tbs_tlv); |
| 164 |
| 165 // Certificate ::= SEQUENCE { |
| 166 der::Parser tbs_parser; |
| 167 if (!parser.ReadSequence(&tbs_parser)) |
| 168 return false; |
| 169 |
| 170 // version [0] EXPLICIT Version DEFAULT v1, |
| 171 der::Input version; |
| 172 bool has_version; |
| 173 if (!tbs_parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &version, |
| 174 &has_version)) { |
| 175 return false; |
| 176 } |
| 177 if (has_version) { |
| 178 if (!ParseVersion(version, &out->version)) |
| 179 return false; |
| 180 if (out->version == CertificateVersion::V1) { |
| 181 // The correct way to specify v1 is to omit the version field since v1 is |
| 182 // the DEFAULT. |
| 183 return false; |
| 184 } |
| 185 } else { |
| 186 out->version = CertificateVersion::V1; |
| 187 } |
| 188 |
| 189 // serialNumber CertificateSerialNumber, |
| 190 if (!tbs_parser.ReadTag(der::kInteger, &out->serial_number)) |
| 191 return false; |
| 192 if (!VerifySerialNumber(out->serial_number)) |
| 193 return false; |
| 194 |
| 195 // signature AlgorithmIdentifier, |
| 196 if (!ReadSequenceTLV(&tbs_parser, &out->signature_algorithm_tlv)) |
| 197 return false; |
| 198 |
| 199 // issuer Name, |
| 200 if (!ReadSequenceTLV(&tbs_parser, &out->issuer_tlv)) |
| 201 return false; |
| 202 |
| 203 // validity Validity, |
| 204 if (!ReadSequenceTLV(&tbs_parser, &out->validity_tlv)) |
| 205 return false; |
| 206 |
| 207 // subject Name, |
| 208 if (!ReadSequenceTLV(&tbs_parser, &out->subject_tlv)) |
| 209 return false; |
| 210 |
| 211 // subjectPublicKeyInfo SubjectPublicKeyInfo, |
| 212 if (!ReadSequenceTLV(&tbs_parser, &out->spki_tlv)) |
| 213 return false; |
| 214 |
| 215 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, |
| 216 // -- If present, version MUST be v2 or v3 |
| 217 der::Input issuer_unique_id; |
| 218 if (!tbs_parser.ReadOptionalTag(der::ContextSpecificPrimitive(1), |
| 219 &issuer_unique_id, |
| 220 &out->has_issuer_unique_id)) { |
| 221 return false; |
| 222 } |
| 223 if (out->has_issuer_unique_id) { |
| 224 if (!der::ParseBitString(issuer_unique_id, &out->issuer_unique_id)) |
| 225 return false; |
| 226 if (out->version != CertificateVersion::V2 && |
| 227 out->version != CertificateVersion::V3) { |
| 228 return false; |
| 229 } |
| 230 } |
| 231 |
| 232 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, |
| 233 // -- If present, version MUST be v2 or v3 |
| 234 der::Input subject_unique_id; |
| 235 if (!tbs_parser.ReadOptionalTag(der::ContextSpecificPrimitive(2), |
| 236 &subject_unique_id, |
| 237 &out->has_subject_unique_id)) { |
| 238 return false; |
| 239 } |
| 240 if (out->has_subject_unique_id) { |
| 241 if (!der::ParseBitString(subject_unique_id, &out->subject_unique_id)) |
| 242 return false; |
| 243 if (out->version != CertificateVersion::V2 && |
| 244 out->version != CertificateVersion::V3) { |
| 245 return false; |
| 246 } |
| 247 } |
| 248 |
| 249 // extensions [3] EXPLICIT Extensions OPTIONAL |
| 250 // -- If present, version MUST be v3 |
| 251 if (!tbs_parser.ReadOptionalTag(der::ContextSpecificConstructed(3), |
| 252 &out->extensions_tlv, &out->has_extensions)) { |
| 253 return false; |
| 254 } |
| 255 if (out->has_extensions) { |
| 256 // extensions_tlv must be a single element. Also check that it is a |
| 257 // SEQUENCE. |
| 258 if (!IsSequenceTLV(out->extensions_tlv)) |
| 259 return false; |
| 260 if (out->version != CertificateVersion::V3) |
| 261 return false; |
| 262 } |
| 263 |
| 264 // Note that there IS an extension point at the end of TBSCertificate |
| 265 // (according to RFC 5912), so from that interpretation, unconsumed data would |
| 266 // be allowed in |tbs_parser|. |
| 267 // |
| 268 // However because only v1, v2, and v3 certificates are supported by the |
| 269 // parsing, there shouldn't be any subsequent data in those versions, so |
| 270 // reject. |
| 271 if (tbs_parser.HasMore()) |
| 272 return false; |
| 273 |
| 274 // By definition the input was a single TBSCertificate, so there shouldn't be |
| 275 // unconsumed data. |
| 276 if (parser.HasMore()) |
| 277 return false; |
| 278 |
| 279 return true; |
| 280 } |
| 281 |
66 } // namespace net | 282 } // namespace net |
OLD | NEW |