Chromium Code Reviews| 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 size_t unused_numeric_length; | |
| 97 if (!der::IsValidInteger(value, &unused_negative, &unused_numeric_length)) | |
| 98 return false; | |
| 99 | |
| 100 // Check if the serial number is too long per RFC 5280. | |
| 101 if (value.Length() > 20) | |
| 102 return false; | |
| 103 | |
| 104 return true; | |
| 105 } | |
| 106 | |
| 31 } // namespace | 107 } // namespace |
| 32 | 108 |
| 109 ParsedTbsCertificate::ParsedTbsCertificate() | |
| 110 : version(CertificateVersion::V1), | |
| 111 has_issuer_unique_id(false), | |
| 112 has_subject_unique_id(false), | |
| 113 has_extensions(false) {} | |
|
davidben
2015/08/17 21:16:02
Optional: Non-static initializers are allowed now,
eroman
2015/08/18 00:20:50
Done.
As an aside, I have gotten feedback from R
davidben
2015/08/18 00:22:56
Interesting! I'm pretty sure I've gotten feedback
eroman
2015/08/18 00:35:52
As an aside: I understand member initializers bett
| |
| 114 | |
| 115 ParsedTbsCertificate::~ParsedTbsCertificate() {} | |
| 116 | |
| 33 bool ParseCertificate(const der::Input& certificate_tlv, | 117 bool ParseCertificate(const der::Input& certificate_tlv, |
| 34 ParsedCertificate* out) { | 118 ParsedCertificate* out) { |
| 35 der::Parser parser(certificate_tlv); | 119 der::Parser parser(certificate_tlv); |
| 36 | 120 |
| 37 // Certificate ::= SEQUENCE { | 121 // Certificate ::= SEQUENCE { |
| 38 der::Parser certificate_parser; | 122 der::Parser certificate_parser; |
| 39 if (!parser.ReadSequence(&certificate_parser)) | 123 if (!parser.ReadSequence(&certificate_parser)) |
| 40 return false; | 124 return false; |
| 41 | 125 |
| 42 // tbsCertificate TBSCertificate, | 126 // tbsCertificate TBSCertificate, |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 56 return false; | 140 return false; |
| 57 | 141 |
| 58 // By definition the input was a single Certificate, so there shouldn't be | 142 // By definition the input was a single Certificate, so there shouldn't be |
| 59 // unconsumed data. | 143 // unconsumed data. |
| 60 if (parser.HasMore()) | 144 if (parser.HasMore()) |
| 61 return false; | 145 return false; |
| 62 | 146 |
| 63 return true; | 147 return true; |
| 64 } | 148 } |
| 65 | 149 |
| 150 // From RFC 5280 section 4.1: | |
| 151 // | |
| 152 // TBSCertificate ::= SEQUENCE { | |
| 153 // version [0] EXPLICIT Version DEFAULT v1, | |
| 154 // serialNumber CertificateSerialNumber, | |
| 155 // signature AlgorithmIdentifier, | |
| 156 // issuer Name, | |
| 157 // validity Validity, | |
| 158 // subject Name, | |
| 159 // subjectPublicKeyInfo SubjectPublicKeyInfo, | |
| 160 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, | |
| 161 // -- If present, version MUST be v2 or v3 | |
| 162 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, | |
| 163 // -- If present, version MUST be v2 or v3 | |
| 164 // extensions [3] EXPLICIT Extensions OPTIONAL | |
| 165 // -- If present, version MUST be v3 | |
| 166 // } | |
| 167 bool ParseTbsCertificate(const der::Input& tbs_tlv, ParsedTbsCertificate* out) { | |
| 168 der::Parser parser(tbs_tlv); | |
| 169 | |
| 170 // Certificate ::= SEQUENCE { | |
| 171 der::Parser tbs_parser; | |
| 172 if (!parser.ReadSequence(&tbs_parser)) | |
| 173 return false; | |
| 174 | |
| 175 // version [0] EXPLICIT Version DEFAULT v1, | |
| 176 der::Input version; | |
| 177 bool has_version; | |
| 178 if (!tbs_parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &version, | |
| 179 &has_version)) { | |
| 180 return false; | |
| 181 } | |
| 182 if (has_version) { | |
| 183 if (!ParseVersion(version, &out->version)) | |
| 184 return false; | |
| 185 if (out->version == CertificateVersion::V1) { | |
| 186 // The correct way to specify v1 is to omit the version field since v1 is | |
| 187 // the DEFAULT. | |
| 188 return false; | |
| 189 } | |
| 190 } else { | |
| 191 out->version = CertificateVersion::V1; | |
| 192 } | |
| 193 | |
| 194 // serialNumber CertificateSerialNumber, | |
| 195 if (!tbs_parser.ReadTag(der::kInteger, &out->serial_number)) | |
| 196 return false; | |
| 197 if (!VerifySerialNumber(out->serial_number)) | |
| 198 return false; | |
| 199 | |
| 200 // signature AlgorithmIdentifier, | |
| 201 if (!ReadSequenceTLV(&tbs_parser, &out->signature_algorithm_tlv)) | |
| 202 return false; | |
| 203 | |
| 204 // issuer Name, | |
| 205 if (!ReadSequenceTLV(&tbs_parser, &out->issuer_tlv)) | |
| 206 return false; | |
| 207 | |
| 208 // validity Validity, | |
| 209 if (!ReadSequenceTLV(&tbs_parser, &out->validity_tlv)) | |
| 210 return false; | |
| 211 | |
| 212 // subject Name, | |
| 213 if (!ReadSequenceTLV(&tbs_parser, &out->subject_tlv)) | |
| 214 return false; | |
| 215 | |
| 216 // subjectPublicKeyInfo SubjectPublicKeyInfo, | |
| 217 if (!ReadSequenceTLV(&tbs_parser, &out->spki_tlv)) | |
| 218 return false; | |
| 219 | |
| 220 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, | |
| 221 // -- If present, version MUST be v2 or v3 | |
| 222 der::Input issuer_unique_id; | |
| 223 if (!tbs_parser.ReadOptionalTag(der::ContextSpecificPrimitive(1), | |
| 224 &issuer_unique_id, | |
| 225 &out->has_issuer_unique_id)) { | |
| 226 return false; | |
| 227 } | |
| 228 if (out->has_issuer_unique_id) { | |
| 229 if (!der::ParseBitString(issuer_unique_id, &out->issuer_unique_id)) | |
| 230 return false; | |
| 231 if (out->version != CertificateVersion::V2 && | |
| 232 out->version != CertificateVersion::V3) { | |
| 233 return false; | |
| 234 } | |
| 235 } | |
| 236 | |
| 237 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, | |
| 238 // -- If present, version MUST be v2 or v3 | |
| 239 der::Input subject_unique_id; | |
| 240 if (!tbs_parser.ReadOptionalTag(der::ContextSpecificPrimitive(2), | |
| 241 &subject_unique_id, | |
| 242 &out->has_subject_unique_id)) { | |
| 243 return false; | |
| 244 } | |
| 245 if (out->has_subject_unique_id) { | |
| 246 if (!der::ParseBitString(subject_unique_id, &out->subject_unique_id)) | |
| 247 return false; | |
| 248 if (out->version != CertificateVersion::V2 && | |
| 249 out->version != CertificateVersion::V3) { | |
| 250 return false; | |
| 251 } | |
| 252 } | |
| 253 | |
| 254 // extensions [3] EXPLICIT Extensions OPTIONAL | |
| 255 // -- If present, version MUST be v3 | |
| 256 if (!tbs_parser.ReadOptionalTag(der::ContextSpecificConstructed(3), | |
| 257 &out->extensions_tlv, &out->has_extensions)) { | |
| 258 return false; | |
| 259 } | |
| 260 if (out->has_extensions) { | |
| 261 // extensions_tlv must be a single element. Also check that it is a | |
| 262 // SEQUENCE. | |
| 263 if (!IsSequenceTLV(out->extensions_tlv)) | |
| 264 return false; | |
| 265 if (out->version != CertificateVersion::V3) | |
| 266 return false; | |
| 267 } | |
| 268 | |
| 269 // Note that there IS an extension point at the end of TBSCertificate | |
| 270 // (according to RFC 5912), so from that interpretation, unconsumed data would | |
| 271 // be allowed in |tbs_parser|. | |
| 272 // | |
| 273 // However because only v1, v2, and v3 certificates are supported by the | |
| 274 // parsing, there shouldn't be any subsequent data in those versions, so | |
| 275 // reject. | |
| 276 if (tbs_parser.HasMore()) | |
| 277 return false; | |
| 278 | |
| 279 // By definition the input was a single TBSCertificate, so there shouldn't be | |
| 280 // unconsumed data. | |
| 281 if (parser.HasMore()) | |
| 282 return false; | |
| 283 | |
| 284 return true; | |
| 285 } | |
| 286 | |
| 66 } // namespace net | 287 } // namespace net |
| OLD | NEW |