Ejemplo n.º 1
0
class ECCurve(ASN1_Packet):
    ASN1_codec = ASN1_Codecs.BER
    ASN1_root = ASN1F_SEQUENCE(
        ASN1F_STRING("a", ""),
        ASN1F_STRING("b", ""),
        ASN1F_optional(
            ASN1F_BIT_STRING("seed", None)))
Ejemplo n.º 2
0
 def __init__(self, **kargs):
     seq = [
         ASN1F_PACKET("signatureAlgorithm", X509_AlgorithmIdentifier(),
                      X509_AlgorithmIdentifier),
         ASN1F_BIT_STRING("subjectPublicKey", None)
     ]
     ASN1F_SEQUENCE.__init__(self, *seq, **kargs)
Ejemplo n.º 3
0
 def __init__(self, **kargs):
     seq = [
         ASN1F_PACKET("tbsCertList", X509_TBSCertList(), X509_TBSCertList),
         ASN1F_PACKET("signatureAlgorithm", X509_AlgorithmIdentifier(),
                      X509_AlgorithmIdentifier),
         ASN1F_BIT_STRING("signatureValue", "defaultsignature" * 2)
     ]
     ASN1F_SEQUENCE.__init__(self, *seq, **kargs)
Ejemplo n.º 4
0
 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)
Ejemplo n.º 5
0
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", ""),
    )
Ejemplo n.º 6
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
Ejemplo n.º 7
0
class X509_ExtNetscapeCertType(ASN1_Packet):
    ASN1_codec = ASN1_Codecs.BER
    ASN1_root = ASN1F_BIT_STRING("netscapeCertType", "")
Ejemplo n.º 8
0
class ECDSAPublicKey(ASN1_Packet):
    ASN1_codec = ASN1_Codecs.BER
    ASN1_root = ASN1F_BIT_STRING("ecPoint", "")
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
class SAPCredv2_Cred(ASN1_Packet):
    """SAP Credv2 Credential without LPS definition"""
    ASN1_codec = ASN1_Codecs.BER
    ASN1_root = ASN1F_SEQUENCE(
        ASN1F_IA5_STRING("cert_name", None),
        ASN1F_IA5_STRING("unknown1", None),
        ASN1F_IA5_STRING("pse_path", None),
        ASN1F_IA5_STRING("unknown2", None),
        ASN1F_BIT_STRING("cipher", None),
    )

    @property
    def common_name(self):
        return self.cert_name.val

    @property
    def pse_file_path(self):
        return self.pse_path.val

    @property
    def lps_type(self):
        return None

    @property
    def lps_type_str(self):
        return "OFF"

    @property
    def cipher_format_version(self):
        cipher = self.cipher.val_readable
        if len(cipher) >= 36 and ord(cipher[0]) in [0, 1]:
            return ord(cipher[0])
        return 0

    @property
    def cipher_algorithm(self):
        if self.cipher_format_version == 1:
            return ord(self.cipher.val_readable[1])
        return 0

    def decrypt(self, username):
        """Decrypt a credential given a particular username. Tries to identify the credential
        format and choose the decryption method to use.

        :param username: Username to use when decrypting
        :type username: string

        :return: decrypted object
        :rtype: SAPCredv2_Cred_Plain
        """

        if self.cipher_format_version == 1:
            return self.decrypt_with_header(username)
        else:
            return self.decrypt_simple(username)

    def decrypt_simple(self, username):
        """Decrypt a credential using the simple approach. It only handles 3DES.
        Tries to parse the decrypted object into a plain credential object type. If it fails,
        probably due to an invalid username use to decrypt it, raises an exception.

        :param username: Username to use when decrypting
        :type username: string

        :return: decrypted object
        :rtype: SAPCredv2_Cred_Plain
        """

        blob = self.cipher.val_readable

        # Construct the key using the key format and the username
        key = (cred_key_fmt % username)[:24]
        # Set empty IV
        iv = "\x00" * 8

        # Decrypt the cipher text with the derived key and IV
        decryptor = Cipher(algorithms.TripleDES(key),
                           modes.CBC(iv),
                           backend=default_backend()).decryptor()
        plain = decryptor.update(blob) + decryptor.finalize()

        return SAPCredv2_Cred_Plain(plain)

    def decrypt_with_header(self, username):
        """Decrypt a credential file using the header. It handles 3DES and AES256 algorithms.
        Tries to parse the decrypted object into a plain credential object type. If it fails,
        probably due to an invalid username use to decrypt it, raises an exception.

        :param username: Username to use when decrypting
        :type username: string

        :return: decrypted object
        :rtype: SAPCredv2_Cred_Plain

        :raise SAPCredv2_Decryption_Error: if there's an error decrypting the object
        """

        blob = self.cipher.val_readable
        header = SAPCredv2_Cred_Cipher(blob)

        # Validate supported version
        if header.version != 1:
            raise SAPCredv2_Decryption_Error("Version not supported")

        # Validate and select proper algorithm
        if header.algorithm == CIPHER_ALGORITHM_3DES:
            algorithm = algorithms.TripleDES
        elif header.algorithm == CIPHER_ALGORITHM_AES256:
            algorithm = algorithms.AES
        else:
            raise SAPCredv2_Decryption_Error("Algorithm not supported")

        def xor(string, start):
            """XOR a given string using a fixed key and a starting number."""
            key = 0x15a4e35
            x = start
            y = ""
            for c in string:
                x *= key
                x += 1
                y += chr(ord(c) ^ (x & 0xff))
            return y

        def derive_key(key, header, salt, username):
            """Derive a key using SAP's algorithm. The key is derived using SHA256 and xor from an
            initial key, a header, salt and username.
            """
            digest = Hash(SHA256(), backend=default_backend())
            digest.update(key)
            digest.update(header)
            digest.update(salt)
            digest.update(xor(username, ord(salt[0])))
            digest.update("" * 0x20)
            hashed = digest.finalize()
            derived_key = xor(hashed, ord(salt[1]))
            return derived_key

        # Derive the key using SAP's algorithm
        key = derive_key(cred_key_fmt, blob[0:4], header.salt, username)

        # Decrypt the cipher text with the derived key and IV
        decryptor = Cipher(algorithm(key),
                           modes.CBC(header.iv),
                           backend=default_backend()).decryptor()
        plain = decryptor.update(header.cipher_text) + decryptor.finalize()

        # Perform a final xor over the decrypted content with a fixed key
        plain = xor(plain, 0x64FB914E)

        return SAPCredv2_Cred_Plain(plain)