Example #1
0
def return_ocsp_request_object(cert, issuer, algo, nonce=True):
    cert_details = ocsp.CertId({
        'issuer_name_hash':
        getattr(cert.issuer, algo),
        'issuer_key_hash':
        getattr(issuer.public_key, algo),
        'hash_algorithm':
        algos.DigestAlgorithm({'algorithm': algo}),
        'serial_number':
        cert.serial_number,
    })

    request_obj = ocsp.Request({
        'req_cert': cert_details,
    })

    tbs_request_obj = ocsp.TBSRequest(
        {'request_list': ocsp.Requests([request_obj])})

    if nonce:
        nonce_extension = ocsp.TBSRequestExtension({
            'extn_id':
            'nonce',
            'critical':
            True,
            'extn_value':
            core.OctetString(os.urandom(16)),
        })
        tbs_request_obj['request_extensions']: ocsp.TBSRequestExtensions(
            [nonce_extension])

    ocsp_request_obj = ocsp.OCSPRequest({
        'tbs_request': tbs_request_obj,
    })

    return ocsp_request_obj
Example #2
0
def fetch(cert,
          issuer,
          hash_algo='sha1',
          nonce=True,
          user_agent=None,
          timeout=10):
    """
    Fetches an OCSP response for a certificate

    :param cert:
        An asn1cyrpto.x509.Certificate object to get an OCSP reponse for

    :param issuer:
        An asn1crypto.x509.Certificate object that is the issuer of cert

    :param hash_algo:
        A unicode string of "sha1" or "sha256"

    :param nonce:
        A boolean - if the nonce extension should be used to prevent replay
        attacks

    :param user_agent:
        The HTTP user agent to use when requesting the OCSP response. If None,
        a default is used in the format "certvalidation 1.0.0".

    :param timeout:
        The number of seconds after which an HTTP request should timeout

    :raises:
        urllib.error.URLError/urllib2.URLError - when a URL/HTTP error occurs
        socket.error - when a socket error occurs

    :return:
        An asn1crypto.ocsp.OCSPResponse object
    """

    if not isinstance(cert, x509.Certificate):
        raise TypeError(
            'cert must be an instance of asn1crypto.x509.Certificate, not %s' %
            type_name(cert))

    if not isinstance(issuer, x509.Certificate):
        raise TypeError(
            'issuer must be an instance of asn1crypto.x509.Certificate, not %s'
            % type_name(issuer))

    if hash_algo not in set(['sha1', 'sha256']):
        raise ValueError('hash_algo must be one of "sha1", "sha256", not %s' %
                         repr(hash_algo))

    if not isinstance(nonce, bool):
        raise TypeError('nonce must be a bool, not %s' % type_name(nonce))

    if user_agent is None:
        user_agent = 'certvalidator %s' % __version__
    elif not isinstance(user_agent, str_cls):
        raise TypeError('user_agent must be a unicode string, not %s' %
                        type_name(user_agent))

    cert_id = ocsp.CertId({
        'hash_algorithm':
        algos.DigestAlgorithm({'algorithm': hash_algo}),
        'issuer_name_hash':
        getattr(cert.issuer, hash_algo),
        'issuer_key_hash':
        getattr(issuer.public_key, hash_algo),
        'serial_number':
        cert.serial_number,
    })

    request = ocsp.Request({
        'req_cert': cert_id,
    })
    tbs_request = ocsp.TBSRequest({
        'request_list': ocsp.Requests([request]),
    })

    if nonce:
        nonce_extension = ocsp.TBSRequestExtension({
            'extn_id':
            'nonce',
            'critical':
            False,
            'extn_value':
            core.OctetString(core.OctetString(os.urandom(16)).dump())
        })
        tbs_request['request_extensions'] = ocsp.TBSRequestExtensions(
            [nonce_extension])

    ocsp_request = ocsp.OCSPRequest({
        'tbs_request': tbs_request,
    })

    last_e = None
    for ocsp_url in cert.ocsp_urls:
        try:
            request = Request(ocsp_url)
            request.add_header('Accept', 'application/ocsp-response')
            request.add_header('Content-Type', 'application/ocsp-request')
            request.add_header('User-Agent', user_agent)
            response = urlopen(request, ocsp_request.dump(), timeout)
            ocsp_response = ocsp.OCSPResponse.load(response.read())
            request_nonce = ocsp_request.nonce_value
            if ocsp_response['response_status'].native == 'unauthorized':
                raise errors.OCSPNoMatchesError(
                    'Unable to verify OCSP response since the responder returned unauthorized'
                )
            response_nonce = ocsp_response.nonce_value
            if request_nonce and response_nonce and request_nonce.native != response_nonce.native:
                raise errors.OCSPValidationError(
                    'Unable to verify OCSP response since the request and response nonces do not match'
                )
            return ocsp_response

        except (URLError) as e:
            last_e = e

    raise last_e
Example #3
0
    def set_extension(self, name, value):
        """
        Sets the value for an extension using a fully constructed
        asn1crypto.core.Asn1Value object. Normally this should not be needed,
        and the convenience attributes should be sufficient.

        See the definition of asn1crypto.ocsp.TBSRequestExtension and
        asn1crypto.ocsp.RequestExtension to determine the appropriate object
        type for a given extension. Extensions are marked as critical when RFC
        6960 indicates so.

        :param name:
            A unicode string of an extension id name from
            asn1crypto.ocsp.TBSRequestExtensionId or
            asn1crypto.ocsp.RequestExtensionId. If the extension is not one
            defined in those classes, this must be an instance of one of the
            classes instead of a unicode string.

        :param value:
            A value object per the specs defined by
            asn1crypto.ocsp.TBSRequestExtension or
            asn1crypto.ocsp.RequestExtension
        """

        if isinstance(name, str_cls):
            request_extension_oids = set(
                ['service_locator', '1.3.6.1.5.5.7.48.1.7'])
            tbs_request_extension_oids = set([
                'nonce', 'acceptable_responses',
                'preferred_signature_algorithms', '1.3.6.1.5.5.7.48.1.2',
                '1.3.6.1.5.5.7.48.1.4', '1.3.6.1.5.5.7.48.1.8'
            ])

            if name in request_extension_oids:
                name = ocsp.RequestExtensionId(name)

            elif name in tbs_request_extension_oids:
                name = ocsp.TBSRequestExtensionId(name)

            else:
                raise ValueError(
                    _pretty_message(
                        '''
                    name must be a unicode string from
                    asn1crypto.ocsp.TBSRequestExtensionId or
                    asn1crypto.ocsp.RequestExtensionId, not %s
                    ''', repr(name)))

        if isinstance(name, ocsp.RequestExtensionId):
            extension = ocsp.RequestExtension({'extn_id': name})

        elif isinstance(name, ocsp.TBSRequestExtensionId):
            extension = ocsp.TBSRequestExtension({'extn_id': name})

        else:
            raise TypeError(
                _pretty_message(
                    '''
                name must be a unicode string or an instance of
                asn1crypto.ocsp.TBSRequestExtensionId or
                asn1crypto.ocsp.RequestExtensionId, not %s
                ''', _type_name(name)))

        # We use native here to convert OIDs to meaningful names
        name = extension['extn_id'].native
        spec = extension.spec('extn_value')

        if not isinstance(value, spec) and value is not None:
            raise TypeError(
                _pretty_message(
                    '''
                value must be an instance of %s, not %s
                ''', _type_name(spec), _type_name(value)))

        if isinstance(extension, ocsp.TBSRequestExtension):
            extn_dict = self._tbs_request_extensions
        else:
            extn_dict = self._request_extensions

        if value is None:
            if name in extn_dict:
                del extn_dict[name]
        else:
            extn_dict[name] = value
Example #4
0
    def set_extension(self, name, value):

        if isinstance(name, str_cls):
            request_extension_oids = set(
                ['service_locator', '1.3.6.1.5.5.7.48.1.7'])
            tbs_request_extension_oids = set([
                'nonce', 'acceptable_responses',
                'preferred_signature_algorithms', '1.3.6.1.5.5.7.48.1.2',
                '1.3.6.1.5.5.7.48.1.4', '1.3.6.1.5.5.7.48.1.8'
            ])

            if name in request_extension_oids:
                name = ocsp.RequestExtensionId(name)

            elif name in tbs_request_extension_oids:
                name = ocsp.TBSRequestExtensionId(name)

            else:
                raise ValueError(
                    _pretty_message(
                        '''
                    name must be a unicode string from
                    asn1crypto.ocsp.TBSRequestExtensionId or
                    asn1crypto.ocsp.RequestExtensionId, not %s
                    ''', repr(name)))

        if isinstance(name, ocsp.RequestExtensionId):
            extension = ocsp.RequestExtension({'extn_id': name})

        elif isinstance(name, ocsp.TBSRequestExtensionId):
            extension = ocsp.TBSRequestExtension({'extn_id': name})

        else:
            raise TypeError(
                _pretty_message(
                    '''
                name must be a unicode string or an instance of
                asn1crypto.ocsp.TBSRequestExtensionId or
                asn1crypto.ocsp.RequestExtensionId, not %s
                ''', _type_name(name)))

        name = extension['extn_id'].native
        spec = extension.spec('extn_value')

        if not isinstance(value, spec) and value is not None:
            raise TypeError(
                _pretty_message(
                    '''
                value must be an instance of %s, not %s
                ''', _type_name(spec), _type_name(value)))

        if isinstance(extension, ocsp.TBSRequestExtension):
            extn_dict = self._tbs_request_extensions
        else:
            extn_dict = self._request_extensions

        if value is None:
            if name in extn_dict:
                del extn_dict[name]
        else:
            extn_dict[name] = value