Initial version
diff --git a/asn1crypto/ocsp.py b/asn1crypto/ocsp.py
new file mode 100644
index 0000000..69f9abf
--- /dev/null
+++ b/asn1crypto/ocsp.py
@@ -0,0 +1,307 @@
+# coding: utf-8
+from __future__ import unicode_literals
+from __future__ import absolute_import
+
+from .algos import DigestAlgorithm, SignedDigestAlgorithm
+from .core import (
+    Boolean,
+    Choice,
+    Enumerated,
+    GeneralizedTime,
+    IA5String,
+    Integer,
+    Null,
+    ObjectIdentifier,
+    OctetBitString,
+    OctetString,
+    Sequence,
+    SequenceOf,
+)
+from .crl import AuthorityInfoAccessSyntax, CRLReason
+from .keys import PublicKeyAlgorithm
+from .x509 import Certificate, GeneralName, GeneralNames, Name
+
+
+
+# The structures in this file are taken from https://tools.ietf.org/html/rfc6960
+
+
+class ResponseType(ObjectIdentifier):
+    _map = {
+        '1.3.6.1.5.5.7.48.1.1': 'basic_ocsp_response',
+    }
+
+
+class AcceptableResponses(SequenceOf):
+    _child_spec = ResponseType
+
+
+class ServiceLocator(Sequence):
+    _fields = [
+        ('issuer', Name),
+        ('locator', AuthorityInfoAccessSyntax),
+    ]
+
+
+class PreferredSignatureAlgorithm(Sequence):
+    _fields = [
+        ('sig_identifier', SignedDigestAlgorithm),
+        ('cert_identifier', PublicKeyAlgorithm, {'optional': True}),
+    ]
+
+
+class PreferredSignatureAlgorithms(SequenceOf):
+    _child_spec = PreferredSignatureAlgorithm
+
+
+class RequestExtensionId(ObjectIdentifier):
+    _map = {
+        '1.3.6.1.5.5.7.48.1.7': 'ocsp_service_locator',
+    }
+
+
+class RequestExtension(Sequence):
+    _fields = [
+        ('extn_id', RequestExtensionId),
+        ('critical', Boolean, {'default': False}),
+        ('extn_value', OctetString),
+    ]
+
+    _oid_pair = ('extn_id', 'extn_value')
+    _oid_specs = {
+        'ocsp_service_locator': ServiceLocator,
+    }
+
+
+class RequestExtensions(SequenceOf):
+    _child_spec = RequestExtension
+
+
+class TBSRequestExtensionId(ObjectIdentifier):
+    _map = {
+        '1.3.6.1.5.5.7.48.1.2': 'ocsp_noonce',
+        '1.3.6.1.5.5.7.48.1.4': 'ocsp_response',
+        '1.3.6.1.5.5.7.48.1.8': 'ocsp_preferred_signature_algorithms',
+    }
+
+
+class TBSRequestExtension(Sequence):
+    _fields = [
+        ('extn_id', TBSRequestExtensionId),
+        ('critical', Boolean, {'default': False}),
+        ('extn_value', OctetString),
+    ]
+
+    _oid_pair = ('extn_id', 'extn_value')
+    _oid_specs = {
+        'ocsp_noonce': OctetString,
+        'ocsp_response': AcceptableResponses,
+        'ocsp_preferred_signature_algorithms': PreferredSignatureAlgorithms,
+    }
+
+
+class TBSRequestExtensions(SequenceOf):
+    _child_spec = TBSRequestExtension
+
+
+class ResponseDataExtensionId(ObjectIdentifier):
+    _map = {
+        '1.3.6.1.5.5.7.48.1.2': 'ocsp_noonce',
+        '1.3.6.1.5.5.7.48.1.9': 'ocsp_extended_revoke',
+    }
+
+
+class ResponseDataExtension(Sequence):
+    _fields = [
+        ('extn_id', ResponseDataExtensionId),
+        ('critical', Boolean, {'default': False}),
+        ('extn_value', OctetString),
+    ]
+
+    _oid_pair = ('extn_id', 'extn_value')
+    _oid_specs = {
+        'ocsp_noonce': OctetString,
+        'ocsp_extended_revoke': Null,
+    }
+
+
+class ResponseDataExtensions(SequenceOf):
+    _child_spec = ResponseDataExtension
+
+
+class CrlId(Sequence):
+    _fields = [
+        ('crl_url', IA5String, {'tag_type': 'explicit', 'tag': 0, 'optional': True}),
+        ('crl_num', Integer, {'tag_type': 'explicit', 'tag': 1, 'optional': True}),
+        ('crl_time', GeneralizedTime, {'tag_type': 'explicit', 'tag': 2, 'optional': True}),
+    ]
+
+
+class SingleResponseExtensionId(ObjectIdentifier):
+    _map = {
+        '1.3.6.1.5.5.7.48.1.3': 'ocsp_crl',
+        '1.3.6.1.5.5.7.48.1.6': 'ocsp_archive_cutoff',
+        # These are CRLEntryExtension values from https://tools.ietf.org/html/rfc5280
+        '2.5.29.21': 'crl_reason',
+        '2.5.29.24': 'invalidity_date',
+        '2.5.29.29': 'certificate_issuer',
+    }
+
+
+class SingleResponseExtension(Sequence):
+    _fields = [
+        ('extn_id', SingleResponseExtensionId),
+        ('critical', Boolean, {'default': False}),
+        ('extn_value', OctetString),
+    ]
+
+    _oid_pair = ('extn_id', 'extn_value')
+    _oid_specs = {
+        'ocsp_crl': CrlId,
+        'ocsp_archive_cutoff': GeneralizedTime,
+        'crl_reason': CRLReason,
+        'invalidity_date': GeneralizedTime,
+        'certificate_issuer': GeneralNames,
+    }
+
+
+class SingleResponseExtensions(SequenceOf):
+    _child_spec = SingleResponseExtension
+
+
+class Version(Integer):
+    _map = {
+        0: 'v1'
+    }
+
+class CertId(Sequence):
+    _fields = [
+        ('hash_algorithm', DigestAlgorithm),
+        ('issuer_name_hash', OctetString),
+        ('issuer_key_hash', OctetString),
+        ('serial_number', Integer),
+    ]
+
+
+class Request(Sequence):
+    _fields = [
+        ('req_cert', CertId),
+        ('single_request_extensions', RequestExtensions, {'tag_type': 'explicit', 'tag': 0, 'optional': True}),
+    ]
+
+
+class Requests(SequenceOf):
+    _child_spec = Request
+
+
+class TBSRequest(Sequence):
+    _fields = [
+        ('version', Version, {'tag_type': 'explicit', 'tag': 0, 'default': 'v1'}),
+        ('requestor_name', GeneralName, {'tag_type': 'explicit', 'tag': 1, 'optional': True}),
+        ('request_list', Requests),
+        ('request_extensions', TBSRequestExtensions, {'tag_type': 'explicit', 'tag': 2, 'optional': True}),
+    ]
+
+
+class Certificates(SequenceOf):
+    _child_spec = Certificate
+
+
+class Signature(Sequence):
+    _fields = [
+        ('signature_algorithm', SignedDigestAlgorithm),
+        ('signature', OctetBitString),
+        ('certs', Certificates, {'tag_type': 'explicit', 'tag': 0, 'optional': True}),
+    ]
+
+
+class OCSPRequest(Sequence):
+    _fields = [
+        ('tbs_request', TBSRequest),
+        ('optional_signature', Signature, {'tag_type': 'explicit', 'tag': 0, 'optional': True}),
+    ]
+
+
+class OCSPResponseStatus(Enumerated):
+    _map = {
+        0: 'successful',
+        1: 'malformed_request',
+        2: 'internal_error',
+        3: 'try_later',
+        5: 'sign_required',
+        6: 'unauthoried',
+    }
+
+
+class ResponderId(Choice):
+    _alternatives = [
+        ('by_name', Name, {'tag_type': 'explicit', 'tag': 1}),
+        ('by_key', OctetString, {'tag_type': 'explicit', 'tag': 2}),
+    ]
+
+
+class RevokedInfo(Sequence):
+    _fields = [
+        ('revocation_time', GeneralizedTime),
+        ('revocation_reason', CRLReason, {'tag_type': 'explicit', 'tag': 0, 'optional': True}),
+    ]
+
+
+class CertStatus(Choice):
+    _alternatives = [
+        ('good', Null, {'tag_type': 'implicit', 'tag': 0}),
+        ('revoked', RevokedInfo, {'tag_type': 'implicit', 'tag': 1}),
+        ('unknown', Null, {'tag_type': 'implicit', 'tag': 2}),
+    ]
+
+
+class SingleResponse(Sequence):
+    _fields = [
+        ('cert_id', CertId),
+        ('cert_status', CertStatus),
+        ('this_update', GeneralizedTime),
+        ('next_update', GeneralizedTime, {'tag_type': 'explicit', 'tag': 0, 'optional': True}),
+        ('single_extensions', SingleResponseExtensions, {'tag_type': 'explicit', 'tag': 1, 'optional': True}),
+    ]
+
+
+class Responses(SequenceOf):
+    _child_spec = SingleResponse
+
+
+class ResponseData(Sequence):
+    _fields = [
+        ('version', Version, {'tag_type': 'explicit', 'tag': 0, 'default': 'v1'}),
+        ('responder_id', ResponderId),
+        ('produced_at', GeneralizedTime),
+        ('responses', Responses),
+        ('response_extensions', ResponseDataExtensions, {'tag_type': 'explicit', 'tag': 1, 'optional': True}),
+    ]
+
+
+class BasicOCSPResponse(Sequence):
+    _fields = [
+        ('tbs_response_data', ResponseData),
+        ('signature_algorithm', SignedDigestAlgorithm),
+        ('signature', OctetBitString),
+        ('certs', Certificates, {'tag_type': 'explicit', 'tag': 0, 'optional': True}),
+    ]
+
+
+class ResponseBytes(Sequence):
+    _fields = [
+        ('response_type', ResponseType),
+        ('response', OctetString),
+    ]
+
+    _oid_pair = ('response_type', 'response')
+    _oid_specs = {
+        'basic_ocsp_response': BasicOCSPResponse,
+    }
+
+
+class OCSPResponse(Sequence):
+    _fields = [
+        ('response_status', OCSPResponseStatus),
+        ('response_bytes', ResponseBytes, {'tag_type': 'explicit', 'tag': 0, 'optional': True}),
+    ]