class X509_ExtGeneralSubtree(ASN1_Packet): # '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), ASN1F_optional(ASN1F_INTEGER("minimum", None, implicit_tag=0x80)), ASN1F_optional(ASN1F_INTEGER("maximum", None, implicit_tag=0x81)))
class X509_ExtPolicyConstraints(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( ASN1F_optional( ASN1F_INTEGER("requireExplicitPolicy", None, implicit_tag=0x80)), ASN1F_optional( ASN1F_INTEGER("inhibitPolicyMapping", None, implicit_tag=0x81)))
class SNMPtrapv2(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SNMP_PDU_TRAPv2(ASN1F_INTEGER("id", 0), ASN1F_enum_INTEGER("error", 0, SNMP_error), # noqa: E501 ASN1F_INTEGER("error_index", 0), ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind) # noqa: E501 )
class SNMPbulk(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SNMP_PDU_BULK(ASN1F_INTEGER("id", 0), ASN1F_INTEGER("non_repeaters", 0), ASN1F_INTEGER("max_repetitions", 0), ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind) # noqa: E501 )
class ECSpecifiedDomain(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( ASN1F_enum_INTEGER("version", 1, {1: "ecpVer1"}), ASN1F_PACKET("fieldID", ECFieldID(), ECFieldID), ASN1F_PACKET("curve", ECCurve(), ECCurve), ASN1F_STRING("base", ""), ASN1F_INTEGER("order", 0), ASN1F_optional(ASN1F_INTEGER("cofactor", None)))
class X509_RevokedCertificate(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( ASN1F_INTEGER("serialNumber", 1), ASN1F_UTC_TIME("revocationDate", str(ZuluTime(+86400))), ASN1F_optional( ASN1F_SEQUENCE_OF("crlEntryExtensions", None, X509_Extension)))
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 PKCS12_PBE1_Parameters(ASN1_Packet): """PKCS12 PBE1 Parameters""" ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( ASN1F_STRING("salt", ""), ASN1F_INTEGER("iterations", 2048), )
class X509_ExtBasicConstraints(ASN1_Packet): # The cA field should not be optional, but some certs omit it for False. ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( ASN1F_optional( ASN1F_BOOLEAN("cA", False)), ASN1F_optional( ASN1F_INTEGER("pathLenConstraint", None)))
class RSAPrivateKey(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( ASN1F_enum_INTEGER("version", 0, ["two-prime", "multi"]), ASN1F_INTEGER("modulus", 10), ASN1F_INTEGER("publicExponent", 3), ASN1F_INTEGER("privateExponent", 3), ASN1F_INTEGER("prime1", 2), ASN1F_INTEGER("prime2", 5), ASN1F_INTEGER("exponent1", 0), ASN1F_INTEGER("exponent2", 3), ASN1F_INTEGER("coefficient", 1), ASN1F_optional( ASN1F_SEQUENCE_OF("otherPrimeInfos", None, RSAOtherPrimeInfo)))
class SNMPtrapv1(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SNMP_PDU_TRAPv1(ASN1F_OID("enterprise", "1.3"), ASN1F_IPADDRESS("agent_addr", "0.0.0.0"), ASN1F_enum_INTEGER("generic_trap", 0, SNMP_trap_types), # noqa: E501 ASN1F_INTEGER("specific_trap", 0), ASN1F_TIME_TICKS("time_stamp", IntAutoTime()), # noqa: E501 ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind) # noqa: E501 )
class SAPPSE_Cont(ASN1_Packet): """SAP PSEv2 Content definition""" ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( ASN1F_PACKET("algorithm_identifier", PKCS5_Algorithm_Identifier(), PKCS5_Algorithm_Identifier), ASN1F_GENERALIZED_TIME("timestamp", None), ASN1F_INTEGER("unknown1", 1), ASN1F_SET_OF("pse_obj", SAPPSE_Obj(), SAPPSE_Obj), )
class SAPPSEv4_Enc_Cont(ASN1_Packet): """SAP PSEv4 Encrypted content definition""" ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_PSE_v4_ENC_CONT_SEQUENCE( ASN1F_INTEGER("unknown", 1), ASN1F_PACKET("algorithm_identifier", PKCS5_Algorithm_Identifier(), PKCS5_Algorithm_Identifier), ASN1F_STRING("cipher_text", ""), ASN1F_STRING("encrypted_pin", ""), )
class LDAP_SearchRequest(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( LDAPDN("baseObject", ""), ASN1F_ENUMERATED("scope", 0, { 0: "baseObject", 1: "singleLevel", 2: "wholeSubtree" }), ASN1F_ENUMERATED( "derefAliases", 0, { 0: "neverDerefAliases", 1: "derefInSearching", 2: "derefFindingBaseObj", 3: "derefAlways" }), ASN1F_INTEGER("sizeLimit", 0), ASN1F_INTEGER("timeLimit", 0), ASN1F_BOOLEAN("attrsOnly", False), ASN1F_PACKET("filter", LDAP_Filter(), LDAP_Filter), ASN1F_SEQUENCE_OF("attributes", [], LDAP_SearchRequestAttribute))
class SAPPSE_Root_Key(ASN1_Packet): """SAP PSEv2 Root Key definition""" ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( ASN1F_enum_INTEGER("version", 0x0, ["v0"], explicit_tag=0xa0), ASN1F_INTEGER("serial_number", 0), ASN1F_PACKET("public_key", X509_SubjectPublicKeyInfo(), X509_SubjectPublicKeyInfo), ASN1F_PACKET("validity", X509_Validity(), X509_Validity, explicit_tag=0xa1), ASN1F_PACKET("sign_alg_id", X509_AlgorithmIdentifier(), X509_AlgorithmIdentifier, explicit_tag=0xa2), ASN1F_BIT_STRING("sign_bit_string", ""), )
class SAPPSE_Obj_PKList(ASN1_Packet): """SAP PSEv2 PKList, EKList, PCAList Object definition""" ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( ASN1F_enum_INTEGER("version", 0x0, ["v0"], explicit_tag=0xa0), ASN1F_INTEGER("serial_number", 0), ASN1F_PACKET("signature", X509_AlgorithmIdentifier(), X509_AlgorithmIdentifier), ASN1F_PACKET("issuer", X509_DirectoryName(), X509_DirectoryName), ASN1F_PACKET("validity", X509_Validity(), X509_Validity), ASN1F_PACKET("partner", X509_DirectoryName(), X509_DirectoryName), ASN1F_PACKET("verification_key", X509_SubjectPublicKeyInfo(), X509_SubjectPublicKeyInfo), )
class X509_ExtAuthorityKeyIdentifier(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( ASN1F_optional( ASN1F_STRING("keyIdentifier", b"\xff" * 20, implicit_tag=0x80)), ASN1F_optional( ASN1F_SEQUENCE_OF("authorityCertIssuer", None, X509_GeneralName, implicit_tag=0xa1)), ASN1F_optional( ASN1F_INTEGER("authorityCertSerialNumber", None, implicit_tag=0x82)))
class LDAP_BindRequest(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( ASN1F_INTEGER("version", 2), LDAPDN("bind_name", ""), ASN1F_CHOICE( "authentication", None, ASN1F_LDAP_Authentication_simple, ASN1F_LDAP_Authentication_krbv42LDAP, ASN1F_LDAP_Authentication_krbv42DSA, ASN1F_PACKET("sasl", LDAP_SaslCredentials(), LDAP_SaslCredentials, implicit_tag=0xa3), ))
class LDAP(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( ASN1F_INTEGER("messageID", 0), ASN1F_CHOICE( "protocolOp", LDAP_SearchRequest(), ASN1F_PACKET("bindRequest", LDAP_BindRequest(), LDAP_BindRequest, implicit_tag=0x60), ASN1F_PACKET("bindResponse", LDAP_BindResponse(), LDAP_BindResponse, implicit_tag=0x61), ASN1F_PACKET("unbindRequest", LDAP_UnbindRequest(), LDAP_UnbindRequest, implicit_tag=0x42), ASN1F_PACKET("searchRequest", LDAP_SearchRequest(), LDAP_SearchRequest, implicit_tag=0x63), ASN1F_PACKET("searchResponse", LDAP_SearchResponseEntry(), LDAP_SearchResponseEntry, implicit_tag=0x64), ASN1F_PACKET("searchResponse", LDAP_SearchResponseResultCode(), LDAP_SearchResponseResultCode, implicit_tag=0x65), ASN1F_PACKET("abandonRequest", LDAP_AbandonRequest(), LDAP_AbandonRequest, implicit_tag=0x70)), # LDAP v3 only ASN1F_optional( ASN1F_SEQUENCE_OF("Controls", [], LDAP_Control, implicit_tag=0x0))) def mysummary(self): return (self.protocolOp.__class__.__name__.replace("_", " "), [LDAP])
class RSAOtherPrimeInfo(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE(ASN1F_INTEGER("prime", 0), ASN1F_INTEGER("exponent", 0), ASN1F_INTEGER("coefficient", 0))
class RSAPublicKey(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE(ASN1F_INTEGER("modulus", 10), ASN1F_INTEGER("publicExponent", 3))
class X509_ExtInhibitAnyPolicy(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_INTEGER("skipCerts", 0)
class X509_ExtDeltaCRLIndicator(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_INTEGER("deltaCRLIndicator", 0)
class X509_ExtCRLNumber(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_INTEGER("cRLNumber", 0)
class X509_TBSCertificate(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( ASN1F_optional( ASN1F_enum_INTEGER("version", 0x2, ["v1", "v2", "v3"], explicit_tag=0xa0)), ASN1F_INTEGER("serialNumber", 1), ASN1F_PACKET("signature", X509_AlgorithmIdentifier(), X509_AlgorithmIdentifier), ASN1F_SEQUENCE_OF("issuer", _default_issuer, X509_RDN), ASN1F_PACKET("validity", X509_Validity(), X509_Validity), ASN1F_SEQUENCE_OF("subject", _default_subject, X509_RDN), ASN1F_PACKET("subjectPublicKeyInfo", X509_SubjectPublicKeyInfo(), X509_SubjectPublicKeyInfo), ASN1F_optional( ASN1F_BIT_STRING("issuerUniqueID", None, implicit_tag=0x81)), ASN1F_optional( ASN1F_BIT_STRING("subjectUniqueID", None, implicit_tag=0x82)), ASN1F_optional( ASN1F_SEQUENCE_OF("extensions", [X509_Extension()], X509_Extension, explicit_tag=0xa3))) def get_issuer(self): attrs = self.issuer attrsDict = {} for attr in attrs: # we assume there is only one name in each rdn ASN1_SET attrsDict[attr.rdn[0].type.oidname] = plain_str( attr.rdn[0].value.val) # noqa: E501 return attrsDict def get_issuer_str(self): """ Returns a one-line string containing every type/value in a rather specific order. sorted() built-in ensures unicity. """ name_str = "" attrsDict = self.get_issuer() 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: name_str += "/" + attrType + "=" name_str += attrsDict[attrType] return name_str def get_subject(self): attrs = self.subject attrsDict = {} for attr in attrs: # we assume there is only one name in each rdn ASN1_SET attrsDict[attr.rdn[0].type.oidname] = plain_str( attr.rdn[0].value.val) # noqa: E501 return attrsDict def get_subject_str(self): name_str = "" attrsDict = self.get_subject() 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: name_str += "/" + attrType + "=" name_str += attrsDict[attrType] return name_str
class ECDSASignature(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE(ASN1F_INTEGER("r", 0), ASN1F_INTEGER("s", 0))
class SAPPSEFile(ASN1_Packet): """SAP PSE definition""" ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( ASN1F_INTEGER("version", 2), ASN1F_CHOICE( "enc_cont", SAPPSEv2_Enc_Cont(), SAPPSEv2_Enc_Cont, SAPPSEv4_Enc_Cont, )) def decrypt(self, pin): """Decrypts a PSE file given a provided PIN. Calls the respective decryption function based on the PSE version. """ if self.version == 2: return self.decrypt_non_lps(pin) elif self.version == 256: return self.decrypt_lps(pin) else: raise ValueError("Unsupported or invalid PSE version") def decrypt_lps(self, pin): """Decrypts an LPS encrypted PSE file given a provided PIN. :param pin: :type pin: string :return: decrypted object :rtype: SAPPSE_Cont :raise ValueError: if the provided PIN doesn't match with the one used for encryption :raise NotImplementedError: if the algorithm specified is not supported :raise Exception: if the algorithm specified is not valid """ # Decrypt the encryption key using the LPS method cipher = SAP_LPS_Cipher(self.enc_cont.encrypted_pin.val) log_pse.debug("Obtained LPS cipher object (version={}, lps={})".format( cipher.version, cipher.lps_type)) key = cipher.decrypt() # Choose the proper algorithms and values according to the algorithm ID if self.enc_cont.algorithm_identifier.alg_id == NIST_ALGORITHM_AES_256_CBC: salt = self.enc_cont.algorithm_identifier.parameters.salt.val algorithm = algorithms.AES mode = modes.CBC key, iv = key[:32], key[32:] else: raise Exception("Invalid PBE algorithm") # Decrypt the cipher text with the derived key and IV decryptor = Cipher(algorithm(key), mode(iv), backend=default_backend()).decryptor() plain = decryptor.update( self.enc_cont.cipher_text.val) + decryptor.finalize() return plain def decrypt_non_lps(self, pin): """Decrypts a non-LPS encrypted PSE file given a provided PIN. Implements PKCS12 PBE1 based encryption for v2 PSE files. :param pin: :type pin: string :return: decrypted object :rtype: SAPPSE_Cont :raise ValueError: if the provided PIN doesn't match with the one used for encryption :raise NotImplementedError: if the algorithm specified is not supported :raise Exception: if the algorithm specified is not valid """ cipher_text = self.enc_cont.cipher_text.val # Choose the proper algorithms and values according to the algorithm ID if self.enc_cont.algorithm_identifier.alg_id == PKCS12_ALGORITHM_PBE1_SHA_3DES_CBC: salt = self.enc_cont.algorithm_identifier.parameters.salt.val iterations = self.enc_cont.algorithm_identifier.parameters.iterations.val hash_algorithm = SHA1 enc_algorithm = algorithms.TripleDES enc_mode = modes.CBC iv = None pbes_cls = PKCS12_PBES1 elif self.enc_cont.algorithm_identifier.alg_id == PKCS5_ALGORITHM_PBES2: raise NotImplementedError("PBE algorithm not implemented") else: raise Exception("Invalid PBE algorithm") # Build the PBE class pbes = pbes_cls(salt, iterations, iv, pin, hash_algorithm, enc_algorithm, enc_mode, default_backend()) # On version 2, we can check that the PIN was valid before decrypting the whole # cipher text if self.version == 2: encrypted_pin = pbes.encrypt(pin) if encrypted_pin != self.enc_cont.encrypted_pin.val: raise ValueError("Invalid PIN supplied") # Decrypt and parse the cipher text plain_text = pbes.decrypt(cipher_text) return plain_text
class SAPCredv2_Cred_LPS(ASN1_Packet): """SAP Credv2 Credential with LPS definition""" ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE( ASN1F_INTEGER("version", 2), ASN1F_SEQUENCE( ASN1F_SET( ASN1F_SEQUENCE(ASN1F_OID("oid", "2.5.4.3"), ASN1F_PRINTABLE_STRING("value", None)))), ASN1F_UTF8_STRING("pse_path", None), ASN1F_BIT_STRING("cipher", None), ) @property def common_name(self): return self.value.val @property def pse_file_path(self): return self.pse_path.val @property def lps_type(self): return ord(self.cipher.val_readable[1]) @property def lps_type_str(self): if self.lps_type in SAP_LPS_Cipher.lps_types: lps = SAP_LPS_Cipher.lps_types[self.lps_type] else: lps = "OFF" return lps @property def cipher_format_version(self): return ord(self.cipher.val_readable[0]) @property def cipher_algorithm(self): if self.version == 2: return CIPHER_ALGORITHM_AES256 else: return CIPHER_ALGORITHM_3DES def decrypt(self, username=None): """Decrypt a credential file using LPS. :param username: Username to use when decrypting. Not used but kept to match signature :type username: string :return: decrypted object :rtype: SAPCredv2_Cred_Plain """ cipher = SAP_LPS_Cipher(self.cipher.val_readable) log_cred.debug( "Obtained LPS cipher object (version={}, lps={})".format( cipher.version, cipher.lps_type)) plain = cipher.decrypt() # Get the pin from the raw data plain_size = ord(plain[0]) pin = plain[plain_size + 1:] # Create a plain credential container plain_cred = SAPCredv2_Cred_Plain() plain_cred.pin = ASN1_IA5_STRING(pin) return plain_cred
class ECFieldID(ASN1_Packet): # No characteristic-two-field support for now. ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_SEQUENCE(ASN1F_OID("fieldType", "prime-field"), ASN1F_INTEGER("prime", 0))
class ASN1P_INTEGER(ASN1_Packet): ASN1_codec = ASN1_Codecs.BER ASN1_root = ASN1F_INTEGER("number", 0)