@@ -355,6 +355,29 @@ def extract_revoked_status(self, single_response):
355355 def _convert_generalized_time_to_datetime (self , gentime ):
356356 return datetime .strptime (str (gentime ), '%Y%m%d%H%M%SZ' )
357357
358+ def check_cert_time_validity (self , cur_time , tbs_certificate ):
359+ cert_validity = tbs_certificate .getComponentByName ('validity' )
360+ cert_not_after = cert_validity .getComponentByName ('notAfter' )
361+ val_end = cert_not_after .getComponentByName ('utcTime' ).asDateTime
362+ cert_not_before = cert_validity .getComponentByName ('notBefore' )
363+ val_start = cert_not_before .getComponentByName ('utcTime' ).asDateTime
364+
365+ if cur_time > val_end or cur_time < val_start :
366+ debug_msg = "Certificate attached to OCSP Response is invalid. " \
367+ "OCSP response current time - {0} certificate not " \
368+ "before time - {1} certificate not after time - {2}. " . \
369+ format (cur_time , val_start , val_end )
370+ return False , debug_msg
371+ else :
372+ return True , None
373+
374+ """
375+ is_valid_time - checks various components of the OCSP Response
376+ for expiry.
377+ :param cert_id - certificate id corresponding to OCSP Response
378+ :param ocsp_response
379+ :return True/False depending on time validity within the response
380+ """
358381 def is_valid_time (self , cert_id , ocsp_response ):
359382 res = der_decoder .decode (ocsp_response , OCSPResponse ())[0 ]
360383
@@ -370,6 +393,35 @@ def is_valid_time(self, cert_id, ocsp_response):
370393 response_bytes .getComponentByName ('response' ),
371394 BasicOCSPResponse ())[0 ]
372395
396+ attached_certs = basic_ocsp_response .getComponentByName ('certs' )
397+ if self ._has_certs_in_ocsp_response (attached_certs ):
398+ logger .debug ("Certificate is attached in Basic OCSP Response" )
399+ cert_der = der_encoder .encode (attached_certs [0 ])
400+ cert_openssl = load_certificate (FILETYPE_ASN1 , cert_der )
401+ ocsp_cert = self ._convert_openssl_to_pyasn1_certificate (
402+ cert_openssl )
403+
404+ cur_time = datetime .utcnow ().replace (tzinfo = pytz .utc )
405+ tbs_certificate = ocsp_cert .getComponentByName ('tbsCertificate' )
406+
407+ """
408+ Note:
409+ We purposefully do not verify certificate signature here.
410+ The OCSP Response is extracted from the OCSP Response Cache
411+ which is expected to have OCSP Responses with verified
412+ attached signature. Moreover this OCSP Response is eventually
413+ going to be processed by the driver before being consumed by
414+ the driver.
415+ This step ensures that the OCSP Response cache does not have
416+ any invalid entries.
417+ """
418+
419+ cert_valid , debug_msg = self .check_cert_time_validity (cur_time ,
420+ tbs_certificate )
421+ if not cert_valid :
422+ logger .debug (debug_msg )
423+ return False
424+
373425 tbs_response_data = basic_ocsp_response .getComponentByName (
374426 'tbsResponseData' )
375427 single_response = tbs_response_data .getComponentByName ('responses' )[0 ]
@@ -413,27 +465,25 @@ def process_ocsp_response(self, issuer, cert_id, ocsp_response):
413465
414466 cur_time = datetime .utcnow ().replace (tzinfo = pytz .utc )
415467 tbs_certificate = ocsp_cert .getComponentByName ('tbsCertificate' )
416- cert_validity = tbs_certificate .getComponentByName ('validity' )
417- cert_not_after = cert_validity .getComponentByName ('notAfter' )
418- cert_not_after_utc = cert_not_after .getComponentByName ('utcTime' ).asDateTime
419- cert_not_before = cert_validity .getComponentByName ('notBefore' )
420- cert_not_before_utc = cert_not_before .getComponentByName ('utcTime' ).asDateTime
421-
422- if cur_time > cert_not_after_utc or cur_time < cert_not_before_utc :
423- debug_msg = "Certificate attached to OCSP Response is invalid. " \
424- "OCSP response current time - {0} certificate not " \
425- "before time - {1} certificate not after time - {2}. " .\
426- format (cur_time , cert_not_before_utc , cert_not_after_utc )
427- raise RevocationCheckError (
428- msg = debug_msg ,
429- errno = ER_INVALID_OCSP_RESPONSE_CODE
430- )
468+
469+ """
470+ Signature verification should happen before any kind of
471+ validation
472+ """
431473
432474 self .verify_signature (
433475 ocsp_cert .getComponentByName ('signatureAlgorithm' ),
434476 ocsp_cert .getComponentByName ('signatureValue' ),
435477 issuer ,
436478 ocsp_cert .getComponentByName ('tbsCertificate' ))
479+
480+ cert_valid , debug_msg = self .check_cert_time_validity (cur_time ,
481+ tbs_certificate )
482+ if not cert_valid :
483+ raise RevocationCheckError (
484+ msg = debug_msg ,
485+ errno = ER_INVALID_OCSP_RESPONSE_CODE
486+ )
437487 else :
438488 logger .debug ("Certificate is NOT attached in Basic OCSP Response. "
439489 "Using issuer's certificate" )
0 commit comments