Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <algorithm> | |
| 6 | |
| 7 #include "base/sha1.h" | |
| 8 #include "crypto/sha2.h" | |
| 9 #include "net/cert/internal/extended_key_usage.h" | |
| 10 #include "net/cert/internal/parse_ocsp.h" | |
| 11 #include "net/cert/internal/signature_policy.h" | |
| 12 #include "net/cert/internal/verify_name_match.h" | |
| 13 #include "net/cert/internal/verify_signed_data.h" | |
| 14 | |
| 15 namespace net { | |
| 16 | |
| 17 OCSPCertID::OCSPCertID() {} | |
| 18 OCSPCertID::~OCSPCertID() {} | |
| 19 | |
| 20 OCSPSingleResponse::OCSPSingleResponse() {} | |
| 21 OCSPSingleResponse::~OCSPSingleResponse() {} | |
| 22 | |
| 23 OCSPResponseData::OCSPResponseData() {} | |
| 24 OCSPResponseData::~OCSPResponseData() {} | |
| 25 | |
| 26 OCSPResponse::OCSPResponse() {} | |
| 27 OCSPResponse::~OCSPResponse() {} | |
| 28 | |
| 29 der::Input BasicOCSPResponseOid() { | |
| 30 // From RFC 6960: | |
| 31 // | |
| 32 // id-pkix-ocsp OBJECT IDENTIFIER ::= { id-ad-ocsp } | |
| 33 // id-pkix-ocsp-basic OBJECT IDENTIFIER ::= { id-pkix-ocsp 1 } | |
| 34 // | |
| 35 // In dotted notation: 1.3.6.1.5.5.7.48.1.1 | |
| 36 static const uint8_t oid[] = {0x2b, 0x06, 0x01, 0x05, 0x05, | |
| 37 0x07, 0x30, 0x01, 0x01}; | |
| 38 return der::Input(oid); | |
| 39 } | |
| 40 | |
| 41 // CertID ::= SEQUENCE { | |
| 42 // hashAlgorithm AlgorithmIdentifier, | |
| 43 // issuerNameHash OCTET STRING, -- Hash of issuer's DN | |
| 44 // issuerKeyHash OCTET STRING, -- Hash of issuer's public key | |
| 45 // serialNumber CertificateSerialNumber | |
| 46 // } | |
| 47 bool ParseOCSPCertID(const der::Input& raw_tlv, OCSPCertID* out) { | |
| 48 der::Parser outer_parser(raw_tlv); | |
| 49 der::Parser parser; | |
| 50 if (!outer_parser.ReadSequence(&parser)) | |
| 51 return false; | |
| 52 if (outer_parser.HasMore()) | |
| 53 return false; | |
| 54 | |
| 55 der::Input sigalg_tlv; | |
| 56 if (!parser.ReadRawTLV(&sigalg_tlv)) | |
| 57 return false; | |
| 58 if (!ParseHashAlgorithm(sigalg_tlv, &(out->hash_algorithm))) | |
| 59 return false; | |
| 60 if (!parser.ReadTag(der::kOctetString, &(out->issuer_name_hash))) | |
| 61 return false; | |
| 62 if (!parser.ReadTag(der::kOctetString, &(out->issuer_key_hash))) | |
| 63 return false; | |
| 64 if (!parser.ReadTag(der::kInteger, &(out->serial_number))) | |
| 65 return false; | |
| 66 if (!VerifySerialNumber(out->serial_number)) | |
| 67 return false; | |
| 68 | |
| 69 return !parser.HasMore(); | |
| 70 } | |
| 71 | |
| 72 namespace { | |
| 73 | |
| 74 // Parses |raw_tlv| to extract an OCSP RevokedInfo (RFC 6960) and stores the | |
| 75 // result in the OCSPCertStatus |out|. Returns whether the parsing was | |
| 76 // successful. | |
| 77 // | |
| 78 // RevokedInfo ::= SEQUENCE { | |
| 79 // revocationTime GeneralizedTime, | |
| 80 // revocationReason [0] EXPLICIT CRLReason OPTIONAL | |
| 81 // } | |
| 82 bool ParseRevokedInfo(const der::Input& raw_tlv, OCSPCertStatus* out) { | |
| 83 der::Parser parser(raw_tlv); | |
| 84 if (!parser.ReadGeneralizedTime(&(out->revocation_time))) | |
| 85 return false; | |
| 86 | |
| 87 der::Input reason_input; | |
| 88 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &reason_input, | |
| 89 &(out->has_reason))) { | |
| 90 return false; | |
| 91 } | |
| 92 if (out->has_reason) { | |
| 93 der::Parser reason_parser(reason_input); | |
| 94 der::Input reason_value_input; | |
| 95 uint8_t reason_value; | |
| 96 if (!reason_parser.ReadTag(der::kEnumerated, &reason_value_input)) | |
| 97 return false; | |
| 98 if (!der::ParseUint8(reason_value_input, &reason_value)) | |
| 99 return false; | |
| 100 if (reason_value > | |
| 101 static_cast<uint8_t>(OCSPCertStatus::RevocationReason::LAST)) { | |
| 102 return false; | |
| 103 } | |
| 104 out->revocation_reason = | |
| 105 static_cast<OCSPCertStatus::RevocationReason>(reason_value); | |
| 106 if (out->revocation_reason == OCSPCertStatus::RevocationReason::UNUSED) | |
| 107 return false; | |
| 108 if (reason_parser.HasMore()) | |
| 109 return false; | |
| 110 } | |
| 111 return !parser.HasMore(); | |
| 112 } | |
| 113 | |
| 114 // Parses |raw_tlv| to extract an OCSP CertStatus (RFC 6960) and stores the | |
| 115 // result in the OCSPCertStatus |out|. Returns whether the parsing was | |
| 116 // successful. | |
| 117 // | |
| 118 // CertStatus ::= CHOICE { | |
| 119 // good [0] IMPLICIT NULL, | |
| 120 // revoked [1] IMPLICIT RevokedInfo, | |
| 121 // unknown [2] IMPLICIT UnknownInfo | |
| 122 // } | |
| 123 // | |
| 124 // UnknownInfo ::= NULL | |
| 125 bool ParseCertStatus(const der::Input& raw_tlv, OCSPCertStatus* out) { | |
| 126 der::Parser parser(raw_tlv); | |
| 127 der::Tag status_tag; | |
| 128 der::Input status; | |
| 129 if (!parser.ReadTagAndValue(&status_tag, &status)) | |
| 130 return false; | |
| 131 | |
| 132 out->has_reason = false; | |
| 133 if (status_tag == der::ContextSpecificPrimitive(0)) { | |
| 134 out->status = OCSPCertStatus::Status::GOOD; | |
| 135 } else if (status_tag == der::ContextSpecificConstructed(1)) { | |
| 136 out->status = OCSPCertStatus::Status::REVOKED; | |
| 137 if (!ParseRevokedInfo(status, out)) | |
| 138 return false; | |
| 139 } else if (status_tag == der::ContextSpecificPrimitive(2)) { | |
| 140 out->status = OCSPCertStatus::Status::UNKNOWN; | |
| 141 } else { | |
| 142 return false; | |
| 143 } | |
| 144 | |
| 145 return !parser.HasMore(); | |
| 146 } | |
| 147 | |
| 148 } // namespace | |
| 149 | |
| 150 // SingleResponse ::= SEQUENCE { | |
| 151 // certID CertID, | |
| 152 // certStatus CertStatus, | |
| 153 // thisUpdate GeneralizedTime, | |
| 154 // nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, | |
| 155 // singleExtensions [1] EXPLICIT Extensions OPTIONAL | |
| 156 // } | |
| 157 bool ParseOCSPSingleResponse(const der::Input& raw_tlv, | |
| 158 OCSPSingleResponse* out) { | |
| 159 der::Parser outer_parser(raw_tlv); | |
| 160 der::Parser parser; | |
| 161 if (!outer_parser.ReadSequence(&parser)) | |
| 162 return false; | |
| 163 if (outer_parser.HasMore()) | |
| 164 return false; | |
| 165 | |
| 166 if (!parser.ReadRawTLV(&(out->cert_id_tlv))) | |
| 167 return false; | |
| 168 der::Input status_tlv; | |
| 169 if (!parser.ReadRawTLV(&status_tlv)) | |
| 170 return false; | |
| 171 if (!ParseCertStatus(status_tlv, &(out->cert_status))) | |
| 172 return false; | |
| 173 if (!parser.ReadGeneralizedTime(&(out->this_update))) | |
| 174 return false; | |
| 175 | |
| 176 der::Input next_update_input; | |
| 177 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0), | |
| 178 &next_update_input, &(out->has_next_update))) { | |
| 179 return false; | |
| 180 } | |
| 181 if (out->has_next_update) { | |
| 182 der::Parser next_update_parser(next_update_input); | |
| 183 if (!next_update_parser.ReadGeneralizedTime(&(out->next_update))) | |
| 184 return false; | |
| 185 if (next_update_parser.HasMore()) | |
| 186 return false; | |
| 187 } | |
| 188 | |
| 189 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(1), | |
| 190 &(out->extensions), &(out->has_extensions))) { | |
| 191 return false; | |
| 192 } | |
| 193 | |
| 194 return !parser.HasMore(); | |
| 195 } | |
| 196 | |
| 197 namespace { | |
| 198 | |
| 199 // Parses |raw_tlv| to extract a ResponderID (RFC 6960) and stores the | |
| 200 // result in the ResponderID |out|. Returns whether the parsing was successful. | |
| 201 // | |
| 202 // ResponderID ::= CHOICE { | |
| 203 // byName [1] Name, | |
| 204 // byKey [2] KeyHash | |
| 205 // } | |
| 206 bool ParseResponderID(const der::Input& raw_tlv, | |
| 207 OCSPResponseData::ResponderID* out) { | |
| 208 der::Parser parser(raw_tlv); | |
| 209 der::Tag id_tag; | |
| 210 der::Input id_input; | |
| 211 if (!parser.ReadTagAndValue(&id_tag, &id_input)) | |
| 212 return false; | |
| 213 | |
| 214 if (id_tag == der::ContextSpecificConstructed(1)) { | |
| 215 out->type = OCSPResponseData::ResponderType::NAME; | |
| 216 out->name = id_input; | |
| 217 } else if (id_tag == der::ContextSpecificConstructed(2)) { | |
| 218 der::Parser key_parser(id_input); | |
| 219 der::Input responder_key; | |
| 220 if (!key_parser.ReadTag(der::kOctetString, &responder_key)) | |
| 221 return false; | |
| 222 if (key_parser.HasMore()) | |
| 223 return false; | |
| 224 | |
| 225 SHA1HashValue key_hash; | |
| 226 if (responder_key.Length() != sizeof(key_hash.data)) | |
| 227 return false; | |
| 228 memcpy(key_hash.data, responder_key.UnsafeData(), sizeof(key_hash.data)); | |
| 229 out->type = OCSPResponseData::ResponderType::KEY_HASH; | |
| 230 out->key_hash = HashValue(key_hash); | |
| 231 } else { | |
| 232 return false; | |
| 233 } | |
| 234 return !parser.HasMore(); | |
| 235 } | |
| 236 | |
| 237 } // namespace | |
| 238 | |
| 239 // ResponseData ::= SEQUENCE { | |
| 240 // version [0] EXPLICIT Version DEFAULT v1, | |
| 241 // responderID ResponderID, | |
| 242 // producedAt GeneralizedTime, | |
| 243 // responses SEQUENCE OF SingleResponse, | |
| 244 // responseExtensions [1] EXPLICIT Extensions OPTIONAL | |
| 245 // } | |
| 246 bool ParseOCSPResponseData(const der::Input& raw_tlv, OCSPResponseData* out) { | |
| 247 der::Parser outer_parser(raw_tlv); | |
| 248 der::Parser parser; | |
| 249 if (!outer_parser.ReadSequence(&parser)) | |
| 250 return false; | |
| 251 if (outer_parser.HasMore()) | |
| 252 return false; | |
| 253 | |
| 254 der::Input version_input; | |
| 255 bool version_present; | |
| 256 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0), | |
| 257 &version_input, &version_present)) { | |
| 258 return false; | |
| 259 } | |
| 260 | |
| 261 // For compatibilty, we ignore the restriction from X.690 Section 11.5 that | |
| 262 // DEFAULT values should be omitted for values equal to the default value. | |
| 263 // TODO: Add warning about non-strict parsing. | |
| 264 if (version_present) { | |
| 265 der::Parser version_parser(version_input); | |
| 266 if (!version_parser.ReadUint8(&(out->version))) | |
|
eroman
2016/02/23 22:29:03
Where is the version number being checked?
RFC 696
svaldez
2016/02/24 16:44:37
Adding a check. It looks like we don't have any ca
| |
| 267 return false; | |
| 268 if (version_parser.HasMore()) | |
| 269 return false; | |
| 270 } else { | |
| 271 out->version = 0; | |
| 272 } | |
| 273 | |
| 274 der::Input responder_input; | |
| 275 if (!parser.ReadRawTLV(&responder_input)) | |
| 276 return false; | |
| 277 if (!ParseResponderID(responder_input, &(out->responder_id))) | |
| 278 return false; | |
| 279 if (!parser.ReadGeneralizedTime(&(out->produced_at))) | |
| 280 return false; | |
| 281 | |
| 282 der::Parser responses_parser; | |
| 283 if (!parser.ReadSequence(&responses_parser)) | |
| 284 return false; | |
| 285 out->responses.clear(); | |
| 286 while (responses_parser.HasMore()) { | |
| 287 der::Input single_response; | |
| 288 if (!responses_parser.ReadRawTLV(&single_response)) | |
| 289 return false; | |
| 290 out->responses.push_back(single_response); | |
| 291 } | |
| 292 | |
| 293 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(1), | |
| 294 &(out->extensions), &(out->has_extensions))) { | |
| 295 return false; | |
| 296 } | |
| 297 | |
| 298 return !parser.HasMore(); | |
| 299 } | |
| 300 | |
| 301 namespace { | |
| 302 | |
| 303 // Parses |raw_tlv| to extract a BasicOCSPResponse (RFC 6960) and stores the | |
| 304 // result in the OCSPResponse |out|. Returns whether the parsing was | |
| 305 // successful. | |
| 306 // | |
| 307 // BasicOCSPResponse ::= SEQUENCE { | |
| 308 // tbsResponseData ResponseData, | |
| 309 // signatureAlgorithm AlgorithmIdentifier, | |
| 310 // signature BIT STRING, | |
| 311 // certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL | |
| 312 // } | |
| 313 bool ParseBasicOCSPResponse(const der::Input& raw_tlv, OCSPResponse* out) { | |
| 314 der::Parser outer_parser(raw_tlv); | |
| 315 der::Parser parser; | |
| 316 if (!outer_parser.ReadSequence(&parser)) | |
| 317 return false; | |
| 318 if (outer_parser.HasMore()) | |
| 319 return false; | |
| 320 | |
| 321 if (!parser.ReadRawTLV(&(out->data))) | |
| 322 return false; | |
| 323 der::Input sigalg_tlv; | |
| 324 if (!parser.ReadRawTLV(&sigalg_tlv)) | |
| 325 return false; | |
| 326 out->signature_algorithm = SignatureAlgorithm::CreateFromDer(sigalg_tlv); | |
| 327 if (!out->signature_algorithm) | |
| 328 return false; | |
| 329 if (!parser.ReadBitString(&(out->signature))) | |
| 330 return false; | |
| 331 der::Input certs_input; | |
| 332 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &certs_input, | |
| 333 &(out->has_certs))) { | |
| 334 return false; | |
| 335 } | |
| 336 | |
| 337 out->certs.clear(); | |
| 338 if (out->has_certs) { | |
| 339 der::Parser certs_seq_parser(certs_input); | |
| 340 der::Parser certs_parser; | |
| 341 if (!certs_seq_parser.ReadSequence(&certs_parser)) | |
| 342 return false; | |
| 343 if (certs_seq_parser.HasMore()) | |
| 344 return false; | |
| 345 while (certs_parser.HasMore()) { | |
| 346 der::Input cert_tlv; | |
| 347 if (!certs_parser.ReadRawTLV(&cert_tlv)) | |
| 348 return false; | |
| 349 out->certs.push_back(cert_tlv); | |
| 350 } | |
| 351 } | |
| 352 | |
| 353 return !parser.HasMore(); | |
| 354 } | |
| 355 | |
| 356 } // namespace | |
| 357 | |
| 358 // OCSPResponse ::= SEQUENCE { | |
| 359 // responseStatus OCSPResponseStatus, | |
| 360 // responseBytes [0] EXPLICIT ResponseBytes OPTIONAL | |
| 361 // } | |
| 362 // | |
| 363 // ResponseBytes ::= SEQUENCE { | |
| 364 // responseType OBJECT IDENTIFIER, | |
| 365 // response OCTET STRING | |
| 366 // } | |
| 367 bool ParseOCSPResponse(const der::Input& raw_tlv, OCSPResponse* out) { | |
| 368 der::Parser outer_parser(raw_tlv); | |
| 369 der::Parser parser; | |
| 370 if (!outer_parser.ReadSequence(&parser)) | |
| 371 return false; | |
| 372 if (outer_parser.HasMore()) | |
| 373 return false; | |
| 374 | |
| 375 der::Input response_status_input; | |
| 376 uint8_t response_status; | |
| 377 if (!parser.ReadTag(der::kEnumerated, &response_status_input)) | |
| 378 return false; | |
| 379 if (!der::ParseUint8(response_status_input, &response_status)) | |
| 380 return false; | |
| 381 if (response_status > | |
| 382 static_cast<uint8_t>(OCSPResponse::ResponseStatus::LAST)) { | |
| 383 return false; | |
| 384 } | |
| 385 out->status = static_cast<OCSPResponse::ResponseStatus>(response_status); | |
| 386 if (out->status == OCSPResponse::ResponseStatus::UNUSED) | |
| 387 return false; | |
| 388 | |
| 389 if (out->status == OCSPResponse::ResponseStatus::SUCCESSFUL) { | |
| 390 der::Parser outer_bytes_parser; | |
| 391 der::Parser bytes_parser; | |
| 392 if (!parser.ReadConstructed(der::ContextSpecificConstructed(0), | |
| 393 &outer_bytes_parser)) { | |
| 394 return false; | |
| 395 } | |
| 396 if (!outer_bytes_parser.ReadSequence(&bytes_parser)) | |
| 397 return false; | |
| 398 if (outer_bytes_parser.HasMore()) | |
| 399 return false; | |
| 400 | |
| 401 der::Input type_oid; | |
| 402 if (!bytes_parser.ReadTag(der::kOid, &type_oid)) | |
| 403 return false; | |
| 404 if (type_oid != BasicOCSPResponseOid()) | |
| 405 return false; | |
| 406 | |
| 407 // As per RFC 6960 Section 4.2.1, the value of |response| SHALL be the DER | |
| 408 // encoding of BasicOCSPResponse. | |
| 409 der::Input response; | |
| 410 if (!bytes_parser.ReadTag(der::kOctetString, &response)) | |
| 411 return false; | |
| 412 if (!ParseBasicOCSPResponse(response, out)) | |
| 413 return false; | |
| 414 if (bytes_parser.HasMore()) | |
| 415 return false; | |
| 416 } | |
| 417 | |
| 418 return !parser.HasMore(); | |
| 419 } | |
| 420 | |
| 421 namespace { | |
| 422 | |
| 423 // Checks that the |type| hash of |value| is equal to |hash| | |
| 424 bool VerifyHash(HashValueTag type, | |
| 425 const der::Input& hash, | |
| 426 const der::Input& value) { | |
| 427 HashValue target(type); | |
| 428 if (target.size() != hash.Length()) | |
| 429 return false; | |
| 430 memcpy(target.data(), hash.UnsafeData(), target.size()); | |
| 431 | |
| 432 HashValue value_hash(type); | |
| 433 if (type == HASH_VALUE_SHA1) { | |
| 434 base::SHA1HashBytes(value.UnsafeData(), value.Length(), value_hash.data()); | |
| 435 } else if (type == HASH_VALUE_SHA256) { | |
| 436 std::string hash_string = crypto::SHA256HashString(value.AsString()); | |
| 437 memcpy(value_hash.data(), hash_string.data(), value_hash.size()); | |
| 438 } else { | |
| 439 return false; | |
| 440 } | |
| 441 | |
| 442 return target.Equals(value_hash); | |
| 443 } | |
| 444 | |
| 445 // Checks that the input |id_tlv| parses to a valid CertID and matches the | |
| 446 // issuer |issuer| and serial number |serial_number|. | |
| 447 bool CheckCertID(const der::Input& id_tlv, | |
| 448 const ParsedTbsCertificate& issuer, | |
| 449 const der::Input& serial_number) { | |
| 450 OCSPCertID id; | |
| 451 if (!ParseOCSPCertID(id_tlv, &id)) | |
| 452 return false; | |
| 453 | |
| 454 HashValueTag type; | |
| 455 switch (id.hash_algorithm) { | |
| 456 case DigestAlgorithm::Sha1: | |
| 457 type = HASH_VALUE_SHA1; | |
| 458 break; | |
| 459 case DigestAlgorithm::Sha256: | |
| 460 type = HASH_VALUE_SHA256; | |
| 461 break; | |
| 462 case DigestAlgorithm::Sha384: | |
| 463 case DigestAlgorithm::Sha512: | |
| 464 NOTIMPLEMENTED(); | |
| 465 return false; | |
| 466 } | |
| 467 | |
| 468 if (!VerifyHash(type, id.issuer_name_hash, issuer.subject_tlv)) | |
| 469 return false; | |
| 470 | |
| 471 der::Parser outer_parser(issuer.spki_tlv); | |
| 472 der::Parser spki_parser; | |
| 473 der::BitString key_bits; | |
| 474 if (!outer_parser.ReadSequence(&spki_parser)) | |
| 475 return false; | |
| 476 if (outer_parser.HasMore()) | |
| 477 return false; | |
| 478 if (!spki_parser.SkipTag(der::kSequence)) | |
| 479 return false; | |
| 480 if (!spki_parser.ReadBitString(&key_bits)) | |
| 481 return false; | |
| 482 der::Input key_tlv = key_bits.bytes(); | |
| 483 if (!VerifyHash(type, id.issuer_key_hash, key_tlv)) | |
| 484 return false; | |
| 485 | |
| 486 return id.serial_number == serial_number; | |
| 487 } | |
| 488 | |
| 489 } // namespace | |
| 490 | |
| 491 bool GetOCSPCertStatus(const OCSPResponseData& response_data, | |
| 492 const ParsedCertificate& issuer, | |
| 493 const ParsedCertificate& cert, | |
| 494 OCSPCertStatus* out) { | |
| 495 out->status = OCSPCertStatus::Status::UNKNOWN; | |
| 496 | |
| 497 ParsedTbsCertificate tbs_cert; | |
| 498 if (!ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs_cert)) | |
| 499 return false; | |
| 500 ParsedTbsCertificate issuer_tbs_cert; | |
| 501 if (!ParseTbsCertificate(issuer.tbs_certificate_tlv, &issuer_tbs_cert)) | |
| 502 return false; | |
| 503 | |
| 504 for (const auto& response : response_data.responses) { | |
| 505 OCSPSingleResponse single_response; | |
| 506 if (!ParseOCSPSingleResponse(response, &single_response)) | |
| 507 return false; | |
| 508 if (CheckCertID(single_response.cert_id_tlv, issuer_tbs_cert, | |
| 509 tbs_cert.serial_number)) { | |
| 510 *out = single_response.cert_status; | |
| 511 if (single_response.cert_status.status != OCSPCertStatus::Status::GOOD) | |
| 512 return true; | |
| 513 } | |
| 514 } | |
| 515 | |
| 516 return true; | |
| 517 } | |
| 518 | |
| 519 // Verify Code Below (MOVING TO SEPARATE CL) | |
|
eroman
2016/02/23 22:29:03
What is the resolution to this comment?
svaldez
2016/02/24 16:44:37
Will end up removing right before committing, sinc
eroman
2016/02/25 00:15:59
This is easily managed through git.
Create a new b
| |
| 520 | |
| 521 namespace { | |
| 522 | |
| 523 // Checks that the ResponderID |id| matches the certificate |cert|. | |
| 524 bool CheckResponder(const OCSPResponseData::ResponderID& id, | |
| 525 const ParsedTbsCertificate& cert) { | |
| 526 if (id.type == OCSPResponseData::ResponderType::NAME) { | |
| 527 der::Input name_rdn; | |
| 528 der::Input cert_rdn; | |
| 529 if (!der::Parser(id.name).ReadTag(der::kSequence, &name_rdn) || | |
| 530 !der::Parser(cert.subject_tlv).ReadTag(der::kSequence, &cert_rdn)) | |
| 531 return false; | |
| 532 return VerifyNameMatch(name_rdn, cert_rdn); | |
| 533 } else { | |
| 534 der::Parser parser(cert.spki_tlv); | |
| 535 der::Parser spki_parser; | |
| 536 der::BitString key_bits; | |
| 537 if (!parser.ReadSequence(&spki_parser)) | |
| 538 return false; | |
| 539 if (!spki_parser.SkipTag(der::kSequence)) | |
| 540 return false; | |
| 541 if (!spki_parser.ReadBitString(&key_bits)) | |
| 542 return false; | |
| 543 | |
| 544 der::Input key = key_bits.bytes(); | |
| 545 HashValue key_hash(HASH_VALUE_SHA1); | |
| 546 base::SHA1HashBytes(key.UnsafeData(), key.Length(), key_hash.data()); | |
| 547 return key_hash.Equals(id.key_hash); | |
| 548 } | |
| 549 } | |
| 550 | |
| 551 } // namespace | |
| 552 | |
| 553 bool VerifyOCSPResponse(const OCSPResponse& response, | |
| 554 const ParsedCertificate& issuer_cert) { | |
| 555 SimpleSignaturePolicy signature_policy(1024); | |
| 556 | |
| 557 OCSPResponseData response_data; | |
| 558 if (!ParseOCSPResponseData(response.data, &response_data)) | |
| 559 return false; | |
| 560 | |
| 561 ParsedTbsCertificate issuer; | |
| 562 ParsedTbsCertificate responder; | |
| 563 if (!ParseTbsCertificate(issuer_cert.tbs_certificate_tlv, &issuer)) | |
| 564 return false; | |
| 565 | |
| 566 if (CheckResponder(response_data.responder_id, issuer)) { | |
| 567 responder = issuer; | |
| 568 } else { | |
| 569 bool found = false; | |
| 570 for (const auto& responder_cert_tlv : response.certs) { | |
| 571 ParsedCertificate responder_cert; | |
| 572 ParsedTbsCertificate tbs_cert; | |
| 573 if (!ParseCertificate(responder_cert_tlv, &responder_cert)) | |
| 574 return false; | |
| 575 if (!ParseTbsCertificate(responder_cert.tbs_certificate_tlv, &tbs_cert)) | |
| 576 return false; | |
| 577 | |
| 578 if (CheckResponder(response_data.responder_id, tbs_cert)) { | |
| 579 found = true; | |
| 580 responder = tbs_cert; | |
| 581 | |
| 582 scoped_ptr<SignatureAlgorithm> signature_algorithm = | |
| 583 SignatureAlgorithm::CreateFromDer( | |
| 584 responder_cert.signature_algorithm_tlv); | |
| 585 if (!signature_algorithm) | |
| 586 return false; | |
| 587 der::Input issuer_spki = issuer.spki_tlv; | |
| 588 if (!VerifySignedData(*signature_algorithm, | |
| 589 responder_cert.tbs_certificate_tlv, | |
| 590 responder_cert.signature_value, issuer_spki, | |
| 591 &signature_policy)) { | |
| 592 return false; | |
| 593 } | |
| 594 | |
| 595 std::map<der::Input, ParsedExtension> extensions; | |
| 596 std::vector<der::Input> eku; | |
| 597 if (!ParseExtensions(responder.extensions_tlv, &extensions)) | |
| 598 return false; | |
| 599 if (!ParseEKUExtension(extensions[ExtKeyUsageOid()].value, &eku)) | |
| 600 return false; | |
| 601 if (std::find(eku.begin(), eku.end(), OCSPSigning()) == eku.end()) | |
| 602 return false; | |
| 603 break; | |
| 604 } | |
| 605 } | |
| 606 if (!found) | |
| 607 return false; | |
| 608 } | |
| 609 return VerifySignedData(*(response.signature_algorithm), response.data, | |
| 610 response.signature, responder.spki_tlv, | |
| 611 &signature_policy); | |
| 612 } | |
| 613 | |
| 614 } // namespace net | |
| OLD | NEW |