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 |