diff --git a/scapy/asn1/mib.py b/scapy/asn1/mib.py index 5506c0f99f479292a800ae67467ba4887ce5e184..59dc5b9617e728b881f39d9ddb25f00ad73c07ec 100644 --- a/scapy/asn1/mib.py +++ b/scapy/asn1/mib.py @@ -169,6 +169,12 @@ pkcs1_oids = { "sha224WithRSAEncryption" : "1.2.840.113549.1.1.14" } +####### secsig oiw ####### + +secsig_oids = { + "sha1" : "1.3.14.3.2.26" + } + ####### pkcs9 ####### pkcs9_oids = { @@ -428,7 +434,8 @@ certPkixAd_oids = { "id-ad-caRepository" : "1.3.6.1.5.5.7.48.5", "id-pkix-ocsp-archive-cutoff" : "1.3.6.1.5.5.7.48.6", "id-pkix-ocsp-service-locator" : "1.3.6.1.5.5.7.48.7", - "id-ad-cmc" : "1.3.6.1.5.5.7.48.12" + "id-ad-cmc" : "1.3.6.1.5.5.7.48.12", + "basic-response" : "1.3.6.1.5.5.7.48.1.1" } ####### ansi-x962 ####### @@ -556,6 +563,7 @@ evPolicy_oids = { x509_oids_sets = [ pkcs1_oids, + secsig_oids, pkcs9_oids, attributeType_oids, certificateExtension_oids, diff --git a/scapy/layers/tls/handshake.py b/scapy/layers/tls/handshake.py index 5a6ae985afb229accd7cbafd489becffb542634a..5ee9aaeaa6bc99ff2c58f7082800675041407ac7 100644 --- a/scapy/layers/tls/handshake.py +++ b/scapy/layers/tls/handshake.py @@ -16,12 +16,13 @@ from scapy.error import warning from scapy.fields import * from scapy.packet import Packet, Raw, Padding from scapy.utils import repr_hex +from scapy.layers.x509 import X509_Extensions, OCSP_Response from scapy.layers.tls.cert import Cert, PrivKey, PubKey from scapy.layers.tls.basefields import _tls_version, _TLSVersionField -from scapy.layers.tls.keyexchange import (_tls_named_curves, _TLSServerParamsField, - _TLSSignature, _TLSSignatureField, - _tls_hash_sig, SigAndHashAlgsField, - ServerRSAParams, +from scapy.layers.tls.keyexchange import (_tls_named_curves, _tls_hash_sig, + _TLSSignature, _TLSServerParamsField, + _TLSSignatureField, ServerRSAParams, + SigAndHashAlgsField, SigAndHashAlgsLenField) from scapy.layers.tls.session import (_GenericTLSSessionInheritance, writeConnState, @@ -417,13 +418,15 @@ class ResponderID(Packet): return Padding class OCSPStatusRequest(Packet): + """ + This is the structure defined in RFC 6066, not in RFC 6960! + """ name = "OCSPStatusRequest structure" fields_desc = [ FieldLenField("respidlen", None, length_of="respid"), PacketListField("respid", [], ResponderID, length_from=lambda pkt: pkt.respidlen), FieldLenField("reqextlen", None, length_of="reqext"), - StrLenField("reqext", "", - length_from=lambda pkt: pkt.reqextlen) ] + PacketField("reqext", "", X509_Extensions) ] def guess_payload_class(self, p): return Padding @@ -1365,17 +1368,24 @@ class ThreeBytesLenField(FieldLenField): def getfield(self, pkt, s): return s[3:], self.m2i(pkt, struct.unpack(self.fmt, "\x00"+s[:3])[0]) +_cert_status_cls = { 1: OCSP_Response } + +class _StatusField(PacketField): + def m2i(self, pkt, m): + idtype = pkt.status_type + cls = self.cls + if _cert_status_cls.has_key(idtype): + cls = _cert_status_cls[idtype] + return cls(m) + class TLSCertificateStatus(_TLSHandshake): - """ - XXX No OCSPStatus dissection support. See ASN.1 structures in RFC 6960. - """ name = "TLS Handshake - Certificate Status" fields_desc = [ ByteEnumField("msgtype", 22, _tls_handshake_type), ThreeBytesField("msglen", None), - ByteEnumField("stype", 1, _cert_status_type), - ThreeBytesLenField("resplen", None, length_of="resp"), - StrLenField("resp", "", - length_from=lambda pkt:pkt.resplen) ] + ByteEnumField("status_type", 1, _cert_status_type), + ThreeBytesLenField("responselen", None, + length_of="response"), + _StatusField("response", None, Raw) ] ############################################################################### diff --git a/scapy/layers/x509.py b/scapy/layers/x509.py index ee14bc43d24ced4e00f6551d64bcb1df30e07171..b5b03c9b13724184a1799132c8a6a48dbd0c2cb1 100644 --- a/scapy/layers/x509.py +++ b/scapy/layers/x509.py @@ -16,6 +16,7 @@ from scapy.packet import Packet from scapy.fields import PacketField from scapy.volatile import * + class ASN1P_OID(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_OID("oid", "0") @@ -29,10 +30,10 @@ class ASN1P_PRIVSEQ(ASN1_Packet): # It showcases the private high-tag decoding capacities of scapy. ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( - ASN1F_IA5_STRING("str", ""), - ASN1F_STRING("int", 0), - explicit_tag=0, - flexible_tag=True) + ASN1F_IA5_STRING("str", ""), + ASN1F_STRING("int", 0), + explicit_tag=0, + flexible_tag=True) ####################### @@ -201,7 +202,7 @@ class X509_X400Address(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_field("x400Address", "") -default_directoryName = [ +_default_directoryName = [ X509_RDN(), X509_RDN( rdn=[X509_AttributeTypeAndValue( @@ -215,7 +216,7 @@ default_directoryName = [ class X509_DirectoryName(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER - ASN1_root = ASN1F_SEQUENCE_OF("directoryName", default_directoryName, + ASN1_root = ASN1F_SEQUENCE_OF("directoryName", _default_directoryName, X509_RDN) class X509_EDIPartyName(ASN1_Packet): @@ -303,7 +304,7 @@ class X509_ExtDistributionPointName(ASN1_Packet): ASN1_root = ASN1F_CHOICE("distributionPointName", None, X509_ExtFullName, X509_ExtNameRelativeToCRLIssuer) -reasons_mapping = ["unused", +_reasons_mapping = ["unused", "keyCompromise", "cACompromise", "affiliationChanged", @@ -322,14 +323,14 @@ class X509_ExtDistributionPoint(ASN1_Packet): X509_ExtDistributionPointName, explicit_tag=0xa0)), ASN1F_optional( - ASN1F_FLAGS("reasons", None, reasons_mapping, + ASN1F_FLAGS("reasons", None, _reasons_mapping, implicit_tag=0x81)), ASN1F_optional( ASN1F_SEQUENCE_OF("cRLIssuer", None, X509_GeneralName, implicit_tag=0xa2))) -ku_mapping = ["digitalSignature", +_ku_mapping = ["digitalSignature", "nonRepudiation", "keyEncipherment", "dataEncipherment", @@ -341,7 +342,7 @@ ku_mapping = ["digitalSignature", class X509_ExtKeyUsage(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER - ASN1_root = ASN1F_FLAGS("keyUsage", "101", ku_mapping) + ASN1_root = ASN1F_FLAGS("keyUsage", "101", _ku_mapping) def get_keyUsage(self): return self.ASN1_root.get_flags(self) @@ -380,7 +381,7 @@ class X509_ExtCRLNumber(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_INTEGER("cRLNumber", 0) -cRL_reasons = ["unspecified", +_cRL_reasons = ["unspecified", "keyCompromise", "cACompromise", "affiliationChanged", @@ -394,7 +395,7 @@ cRL_reasons = ["unspecified", class X509_ExtReasonCode(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER - ASN1_root = ASN1F_ENUMERATED("cRLReason", 0, cRL_reasons) + ASN1_root = ASN1F_ENUMERATED("cRLReason", 0, _cRL_reasons) class X509_ExtDeltaCRLIndicator(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER @@ -414,7 +415,7 @@ class X509_ExtIssuingDistributionPoint(ASN1_Packet): implicit_tag=0x82), ASN1F_optional( ASN1F_FLAGS("onlySomeReasons", None, - reasons_mapping, + _reasons_mapping, implicit_tag=0x83)), ASN1F_BOOLEAN("indirectCRL", False, implicit_tag=0x84), @@ -438,7 +439,7 @@ class X509_ExtIssuerAltName(ASN1_Packet): ASN1_root = ASN1F_SEQUENCE_OF("issuerAltName", [], X509_GeneralName) class X509_ExtGeneralSubtree(ASN1_Packet): -# 'minimum' is not optional in RFC 5280, yet it is in some implementations. + # 'minimum' is not optional in RFC 5280, yet it is in some implementations. ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( ASN1F_PACKET("base", X509_GeneralName(), X509_GeneralName), @@ -583,7 +584,7 @@ class X509_ExtDefault(ASN1_Packet): # oid-info.com shows that some extensions share multiple OIDs. # Here we only reproduce those written in RFC5280. -ext_mapping = { +_ext_mapping = { "2.5.29.9" : X509_ExtSubjectDirectoryAttributes, "2.5.29.14" : X509_ExtSubjectKeyIdentifier, "2.5.29.15" : X509_ExtKeyUsage, @@ -614,7 +615,7 @@ ext_mapping = { } class ASN1F_EXT_SEQUENCE(ASN1F_SEQUENCE): -# We use explicit_tag=0x04 with extnValue as STRING encapsulation. + # We use explicit_tag=0x04 with extnValue as STRING encapsulation. def __init__(self, **kargs): seq = [ASN1F_OID("extnID", "2.5.29.19"), ASN1F_optional( @@ -637,8 +638,8 @@ class ASN1F_EXT_SEQUENCE(ASN1F_SEQUENCE): extnID.set_val(pkt, oid) s = critical.dissect(pkt, s) encapsed = X509_ExtDefault - if oid.val in ext_mapping: - encapsed = ext_mapping[oid.val] + if oid.val in _ext_mapping: + encapsed = _ext_mapping[oid.val] self.seq[2].cls = encapsed self.seq[2].cls.ASN1_root.flexible_tag = True # there are too many private extensions not to be flexible here @@ -655,6 +656,13 @@ class X509_Extension(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_EXT_SEQUENCE() +class X509_Extensions(ASN1_Packet): + # we use this in OCSP status requests, in tls/handshake.py + ASN1_codec = ASN1_Codecs.BER + ASN1_root = ASN1F_optional( + ASN1F_SEQUENCE_OF("extensions", + None, X509_Extension)) + ####### Public key wrapper ####### @@ -748,10 +756,10 @@ class RSAPrivateKey_OpenSSL(ASN1_Packet): ECDSAPublicKey, explicit_tag=0xa1))) -class _PacketFieldRaw(PacketField): # We need this hack because ECParameters parsing below must return # a Padding payload, and making the ASN1_Packet class have Padding # instead of Raw payload would break things... +class _PacketFieldRaw(PacketField): def getfield(self, pkt, s): i = self.m2i(pkt, s) remain = "" @@ -773,7 +781,7 @@ class ECDSAPrivateKey_OpenSSL(Packet): ####### TBSCertificate & Certificate ####### -default_issuer = [ +_default_issuer = [ X509_RDN(), X509_RDN( rdn=[X509_AttributeTypeAndValue( @@ -785,7 +793,7 @@ default_issuer = [ value=ASN1_PRINTABLE_STRING("Scapy Default Issuer"))]) ] -default_subject = [ +_default_subject = [ X509_RDN(), X509_RDN( rdn=[X509_AttributeTypeAndValue( @@ -807,7 +815,7 @@ class X509_Validity(ASN1_Packet): ASN1_UTC_TIME(str(ZuluTime(+86400))), ASN1F_UTC_TIME, ASN1F_GENERALIZED_TIME)) -attrName_mapping = [ +_attrName_mapping = [ ("countryName" , "C"), ("stateOrProvinceName" , "ST"), ("localityName" , "L"), @@ -815,7 +823,7 @@ attrName_mapping = [ ("organizationUnitName" , "OU"), ("commonName" , "CN") ] -attrName_specials = [name for name, symbol in attrName_mapping] +_attrName_specials = [name for name, symbol in _attrName_mapping] class X509_TBSCertificate(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER @@ -827,11 +835,11 @@ class X509_TBSCertificate(ASN1_Packet): ASN1F_PACKET("signature", X509_AlgorithmIdentifier(), X509_AlgorithmIdentifier), - ASN1F_SEQUENCE_OF("issuer", default_issuer, X509_RDN), + ASN1F_SEQUENCE_OF("issuer", _default_issuer, X509_RDN), ASN1F_PACKET("validity", X509_Validity(), X509_Validity), - ASN1F_SEQUENCE_OF("subject", default_subject, X509_RDN), + ASN1F_SEQUENCE_OF("subject", _default_subject, X509_RDN), ASN1F_PACKET("subjectPublicKeyInfo", X509_SubjectPublicKeyInfo(), X509_SubjectPublicKeyInfo), @@ -860,12 +868,12 @@ class X509_TBSCertificate(ASN1_Packet): """ name_str = "" attrsDict = self.get_issuer() - for attrType, attrSymbol in attrName_mapping: + for attrType, attrSymbol in _attrName_mapping: if attrType in attrsDict: name_str += "/" + attrSymbol + "=" name_str += attrsDict[attrType] for attrType in sorted(attrsDict): - if attrType not in attrName_specials: + if attrType not in _attrName_specials: name_str += "/" + attrType + "=" name_str += attrsDict[attrType] return name_str @@ -879,12 +887,12 @@ class X509_TBSCertificate(ASN1_Packet): def get_subject_str(self): name_str = "" attrsDict = self.get_subject() - for attrType, attrSymbol in attrName_mapping: + for attrType, attrSymbol in _attrName_mapping: if attrType in attrsDict: name_str += "/" + attrSymbol + "=" name_str += attrsDict[attrType] for attrType in sorted(attrsDict): - if attrType not in attrName_specials: + if attrType not in _attrName_specials: name_str += "/" + attrType + "=" name_str += attrsDict[attrType] return name_str @@ -962,7 +970,7 @@ class X509_TBSCertList(ASN1_Packet): ASN1F_PACKET("signature", X509_AlgorithmIdentifier(), X509_AlgorithmIdentifier), - ASN1F_SEQUENCE_OF("issuer", default_issuer, X509_RDN), + ASN1F_SEQUENCE_OF("issuer", _default_issuer, X509_RDN), ASN1F_UTC_TIME("this_update", str(ZuluTime(-1))), ASN1F_optional( ASN1F_UTC_TIME("next_update", None)), @@ -987,12 +995,12 @@ class X509_TBSCertList(ASN1_Packet): """ name_str = "" attrsDict = self.get_issuer() - for attrType, attrSymbol in attrName_mapping: + for attrType, attrSymbol in _attrName_mapping: if attrType in attrsDict: name_str += "/" + attrSymbol + "=" name_str += attrsDict[attrType] for attrType in sorted(attrsDict): - if attrType not in attrName_specials: + if attrType not in _attrName_specials: name_str += "/" + attrType + "=" name_str += attrsDict[attrType] return name_str @@ -1050,3 +1058,172 @@ class X509_CRL(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_X509_CRL() + +############################# +#### OCSP Status packets #### +############################# +########### based on RFC 6960 + +class OCSP_CertID(ASN1_Packet): + ASN1_codec = ASN1_Codecs.BER + ASN1_root = ASN1F_SEQUENCE( + ASN1F_PACKET("hashAlgorithm", + X509_AlgorithmIdentifier(), + X509_AlgorithmIdentifier), + ASN1F_STRING("issuerNameHash", ""), + ASN1F_STRING("issuerKeyHash", ""), + ASN1F_INTEGER("serialNumber", 0)) + +class OCSP_GoodInfo(ASN1_Packet): + ASN1_codec = ASN1_Codecs.BER + ASN1_root = ASN1F_NULL("info", 0) + +class OCSP_RevokedInfo(ASN1_Packet): + ASN1_codec = ASN1_Codecs.BER + ASN1_root = ASN1F_SEQUENCE( + ASN1F_GENERALIZED_TIME("revocationTime", ""), + ASN1F_optional( + ASN1F_PACKET("revocationReason", None, + X509_ExtReasonCode, + explicit_tag=0x80))) + +class OCSP_UnknownInfo(ASN1_Packet): + ASN1_codec = ASN1_Codecs.BER + ASN1_root = ASN1F_NULL("info", 0) + +class OCSP_CertStatus(ASN1_Packet): + ASN1_codec = ASN1_Codecs.BER + ASN1_root = ASN1F_CHOICE("certStatus", None, + ASN1F_PACKET("good", OCSP_GoodInfo(), + OCSP_GoodInfo, implicit_tag=0x80), + ASN1F_PACKET("revoked", OCSP_RevokedInfo(), + OCSP_RevokedInfo, implicit_tag=0xa1), + ASN1F_PACKET("unknown", OCSP_UnknownInfo(), + OCSP_UnknownInfo, implicit_tag=0x82)) + +class OCSP_SingleResponse(ASN1_Packet): + ASN1_codec = ASN1_Codecs.BER + ASN1_root = ASN1F_SEQUENCE( + ASN1F_PACKET("certID", OCSP_CertID(), OCSP_CertID), + ASN1F_PACKET("certStatus", OCSP_CertStatus(), + OCSP_CertStatus), + ASN1F_GENERALIZED_TIME("thisUpdate", ""), + ASN1F_optional( + ASN1F_GENERALIZED_TIME("nextUpdate", "", + explicit_tag=0xa0)), + ASN1F_optional( + ASN1F_SEQUENCE_OF("singleExtensions", None, + X509_Extension, + explicit_tag=0xa1))) + +class OCSP_ByName(ASN1_Packet): + ASN1_codec = ASN1_Codecs.BER + ASN1_root = ASN1F_SEQUENCE_OF("byName", [], X509_RDN) + +class OCSP_ByKey(ASN1_Packet): + ASN1_codec = ASN1_Codecs.BER + ASN1_root = ASN1F_STRING("byKey", "") + +class OCSP_ResponderID(ASN1_Packet): + ASN1_codec = ASN1_Codecs.BER + ASN1_root = ASN1F_CHOICE("responderID", None, + ASN1F_PACKET("byName", OCSP_ByName(), OCSP_ByName, + explicit_tag=0xa1), + ASN1F_PACKET("byKey", OCSP_ByKey(), OCSP_ByKey, + explicit_tag=0xa2)) + +class OCSP_ResponseData(ASN1_Packet): + ASN1_codec = ASN1_Codecs.BER + ASN1_root = ASN1F_SEQUENCE( + ASN1F_optional( + ASN1F_enum_INTEGER("version", 0, {0: "v1"}, + explicit_tag=0x80)), + ASN1F_PACKET("responderID", OCSP_ResponderID(), + OCSP_ResponderID), + ASN1F_GENERALIZED_TIME("producedAt", + str(GeneralizedTime())), + ASN1F_SEQUENCE_OF("responses", [], OCSP_SingleResponse), + ASN1F_optional( + ASN1F_SEQUENCE_OF("responseExtensions", None, + X509_Extension, + explicit_tag=0xa1))) + +class ASN1F_OCSP_BasicResponseECDSA(ASN1F_SEQUENCE): + def __init__(self, **kargs): + seq = [ASN1F_PACKET("tbsResponseData", + OCSP_ResponseData(), + OCSP_ResponseData), + ASN1F_PACKET("signatureAlgorithm", + X509_AlgorithmIdentifier(), + X509_AlgorithmIdentifier), + ASN1F_BIT_STRING_ENCAPS("signature", + ECDSASignature(), + ECDSASignature), + ASN1F_optional( + ASN1F_SEQUENCE_OF("certs", None, X509_Cert, + explicit_tag=0xa0))] + ASN1F_SEQUENCE.__init__(self, *seq, **kargs) + +class ASN1F_OCSP_BasicResponse(ASN1F_SEQUENCE): + def __init__(self, **kargs): + seq = [ASN1F_PACKET("tbsResponseData", + OCSP_ResponseData(), + OCSP_ResponseData), + ASN1F_PACKET("signatureAlgorithm", + X509_AlgorithmIdentifier(), + X509_AlgorithmIdentifier), + ASN1F_BIT_STRING("signature", + "defaultsignature"*2), + ASN1F_optional( + ASN1F_SEQUENCE_OF("certs", None, X509_Cert, + explicit_tag=0xa0))] + ASN1F_SEQUENCE.__init__(self, *seq, **kargs) + def m2i(self, pkt, x): + c,s = ASN1F_SEQUENCE.m2i(self, pkt, x) + sigtype = pkt.fields["signatureAlgorithm"].algorithm.oidname + if "rsa" in sigtype.lower(): + return c,s + elif "ecdsa" in sigtype.lower(): + return ASN1F_OCSP_BasicResponseECDSA().m2i(pkt, x) + else: + raise Exception("could not parse OCSP basic response") + def dissect(self, pkt, s): + c,x = self.m2i(pkt, s) + return x + def build(self, pkt): + if "signatureAlgorithm" in pkt.fields: + sigtype = pkt.fields['signatureAlgorithm'].algorithm.oidname + else: + sigtype = pkt.default_fields["signatureAlgorithm"].algorithm.oidname + if "rsa" in sigtype.lower(): + return ASN1F_SEQUENCE.build(self, pkt) + elif "ecdsa" in sigtype.lower(): + pkt.default_fields["signatureValue"] = ECDSASignature() + return ASN1F_OCSP_BasicResponseECDSA().build(pkt) + else: + raise Exception("could not build OCSP basic response") + +class OCSP_ResponseBytes(ASN1_Packet): + ASN1_codec = ASN1_Codecs.BER + ASN1_root = ASN1F_SEQUENCE( + ASN1F_OID("responseType", "1.3.6.1.5.5.7.48.1.1"), + ASN1F_OCSP_BasicResponse(explicit_tag=0x04)) + +_responseStatus_mapping = ["successful", + "malformedRequest", + "internalError", + "tryLater", + "notUsed", + "sigRequired", + "unauthorized"] + +class OCSP_Response(ASN1_Packet): + ASN1_codec = ASN1_Codecs.BER + ASN1_root = ASN1F_SEQUENCE( + ASN1F_ENUMERATED("responseStatus", 0, + _responseStatus_mapping), + ASN1F_optional( + ASN1F_PACKET("responseBytes", None, + OCSP_ResponseBytes, + explicit_tag=0xa0))) + diff --git a/test/tls.uts b/test/tls.uts index 32af086dee88685a520f3b42b2171041659175b3..e24d203df6da73108140bac85154cb37fcb5969b 100644 --- a/test/tls.uts +++ b/test/tls.uts @@ -776,9 +776,10 @@ isinstance(t4.payload.payload.payload, NoPayload) + Test TLS CertificateStatus = Reading test session - CertificateStatus -#XXX Fill this once OCSP responses have been implemented assert(isinstance(cert_stat, TLSCertificateStatus)) -cert_stat.resplen == 471 +assert(cert_stat.responselen == 471) +cert_stat.response[0].responseStatus == 0 +# we leave the remaining OCSP tests to x509.uts + Test TLS ServerKeyExchange diff --git a/test/x509.uts b/test/x509.uts index d61e2445dd239b0a6b473c70bb4a03c45ccd688e..1d3b2333d5271a8e59a8361859e71166c534f25d 100644 --- a/test/x509.uts +++ b/test/x509.uts @@ -204,3 +204,42 @@ r = ASN1F_PACKET("otherName", None, X509_OtherName).randval() assert(isinstance(r, X509_OtherName)) str(r.type_id) == '171.184.10.271' + +############ OCSP class ############################################### + += OCSP class : OCSP Response import +s = '0\x82\x01\xd3\n\x01\x00\xa0\x82\x01\xcc0\x82\x01\xc8\x06\t+\x06\x01\x05\x05\x070\x01\x01\x04\x82\x01\xb90\x82\x01\xb50\x81\x9e\xa2\x16\x04\x14Qh\xff\x90\xaf\x02\x07u<\xcc\xd9edb\xa2\x12\xb8Yr;\x18\x0f20160914121000Z0s0q0I0\t\x06\x05+\x0e\x03\x02\x1a\x05\x00\x04\x14\xcf&\xf5\x18\xfa\xc9~\x8f\x8c\xb3B\xe0\x1c/j\x10\x9e\x8e_\n\x04\x14Qh\xff\x90\xaf\x02\x07u<\xcc\xd9edb\xa2\x12\xb8Yr;\x02\x10\x07z]\xc36#\x01\xf9\x89\xfeT\xf7\xf8o>d\x80\x00\x18\x0f20160914121000Z\xa0\x11\x18\x0f20160921112500Z0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00\x90\xef\xf9\x15U\x88\xac@l\xf6n\x04C/\x1a\xf5\xbc[Xi\xd9U\xbe\'\xd3\xb7\xf5\xbb\t\xd8\xb1Tw\x9c2\xac\x7f\x88\xba\x98\xe4\xa13\xf4\xdc\xea\xf3\xacX\xe4,E\xf5\xa9\xc3\xf4B-N\xe0\x89D[\xbe\n\xc2h\x9ar\xfd\'.\xc8,\xed\x83\xc2\xf0\x89_\x8c\xc3\xe7\x8a\xad\xa4\x14\x03\x96\x02\xc4\xa8\xc8\x90\x96%X\x80\x95\x02\x9d_\xc82;m\xe9\x15\x00\xa8\x00\xb9\x01\xe3aN&\xe4\xd5\x8a\xc4w7\x0b\xc3~\xc5\xb1M\x10~T\x9e\x1d\xf6\x06\xf8\x12sTg\x14b_\xe7\xc04\xb4\xa3\xd2\x8f\xe6\xa6\xc4\x01q\x03j\xc8\xd4\xc7\x89\xdde\x99\x1a\xd9\x02\xe7\x17\xd1\xf40P\xef\xf6$\xee\xfad\xf4\xeb\xc8\xf7\x0bRL\x8b\xa5x\xe4R2\xe9\xc2\xfcB\nh\x93\xf7\x0ep4h\xeb\x17\x83\xc8\x88!\xc3W\x94WG\xfe3\x15C0qE&A\x99\xa8}\x1a\xda"\xa9O\xba\x90W_W\xado\x1c\xf0`g7\xbb$\x91o\xec\xdd\xbd\x9e\x8bb\xfc' +response = OCSP_Response(s) + += OCSP class : OCSP Response global checks +assert(response.responseStatus.val == 0) +assert(isinstance(response.responseBytes, OCSP_ResponseBytes)) +responseBytes = response.responseBytes +assert(responseBytes.responseType == ASN1_OID("basic-response")) +assert(responseBytes.signatureAlgorithm.algorithm == ASN1_OID("sha256WithRSAEncryption")) +assert(responseBytes.signatureAlgorithm.parameters == ASN1_NULL(0)) +assert(responseBytes.signature.val_readable[:3] == "\x90\xef\xf9" and responseBytes.signature.val_readable[-3:] == "\x8bb\xfc") +responseBytes.certs is None + += OCSP class : OCSP ResponseData checks +responseData = responseBytes.tbsResponseData +assert(responseData.version is None) +rID = responseData.responderID.responderID +assert(isinstance(rID, OCSP_ByKey)) +assert(rID.byKey.val[:3] == "Qh\xff" and rID.byKey.val[-3:] == "Yr;") +assert(responseData.producedAt == ASN1_GENERALIZED_TIME("20160914121000Z")) +assert(len(responseData.responses) == 1) +responseData.responseExtensions is None + += OCSP class : OCSP SingleResponse checks +singleResponse = responseData.responses[0] +assert(singleResponse.certID.hashAlgorithm.algorithm == ASN1_OID("sha1")) +assert(singleResponse.certID.hashAlgorithm.parameters == ASN1_NULL(0)) +assert(singleResponse.certID.issuerNameHash.val[:3] == "\xcf&\xf5" and singleResponse.certID.issuerNameHash.val[-3:] == "\x8e_\n") +assert(singleResponse.certID.issuerKeyHash.val[:3] == "Qh\xff" and singleResponse.certID.issuerKeyHash.val[-3:] == "Yr;") +assert(singleResponse.certID.serialNumber.val == 0x77a5dc3362301f989fe54f7f86f3e64) +assert(isinstance(singleResponse.certStatus.certStatus, OCSP_GoodInfo)) +assert(singleResponse.thisUpdate == ASN1_GENERALIZED_TIME("20160914121000Z")) +assert(singleResponse.nextUpdate == ASN1_GENERALIZED_TIME("20160921112500Z")) +singleResponse.singleExtensions is None +