src/OpenSSL/crypto.py
def load_pkcs12(buffer, passphrase=None):
    """
    Load pkcs12 data from the string *buffer*. If the pkcs12 structure is
    encrypted, a *passphrase* must be included.  The MAC is always
    checked and thus required.

    See also the man page for the C function :py:func:`PKCS12_parse`.

    :param buffer: The buffer the certificate is stored in
    :param passphrase: (Optional) The password to decrypt the PKCS12 lump
    :returns: The PKCS12 object
    """
    passphrase = _text_to_bytes_and_warn("passphrase", passphrase)

    if isinstance(buffer, _text_type):
        buffer = buffer.encode("ascii")

    bio = _new_mem_buf(buffer)

    # Use null passphrase if passphrase is None or empty string. With PKCS#12
    # password based encryption no password and a zero length password are two
    # different things, but OpenSSL implementation will try both to figure out
    # which one works.
    if not passphrase:
        passphrase = _ffi.NULL

    p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
    if p12 == _ffi.NULL:
        _raise_current_error()
    p12 = _ffi.gc(p12, _lib.PKCS12_free)

    pkey = _ffi.new("EVP_PKEY**")
    cert = _ffi.new("X509**")
    cacerts = _ffi.new("Cryptography_STACK_OF_X509**")

    parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
    if not parse_result:
        _raise_current_error()

    cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)

    # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
    # queue for no particular reason.  This error isn't interesting to anyone
    # outside this function.  It's not even interesting to us.  Get rid of it.
    try:
        _raise_current_error()
    except Error:
        pass

    if pkey[0] == _ffi.NULL:
        pykey = None
    else:
        pykey = PKey.__new__(PKey)
        pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)

    if cert[0] == _ffi.NULL:
        pycert = None
        friendlyname = None
    else:
        pycert = X509._from_raw_x509_ptr(cert[0])

        friendlyname_length = _ffi.new("int*")
        friendlyname_buffer = _lib.X509_alias_get0(
            cert[0], friendlyname_length
        )
        friendlyname = _ffi.buffer(
            friendlyname_buffer, friendlyname_length[0]
        )[:]
        if friendlyname_buffer == _ffi.NULL:
            friendlyname = None

    pycacerts = []
    for i in range(_lib.sk_X509_num(cacerts)):
        x509 = _lib.sk_X509_value(cacerts, i)
        pycacert = X509._from_raw_x509_ptr(x509)
        pycacerts.append(pycacert)
    if not pycacerts:
        pycacerts = None

    pkcs12 = PKCS12.__new__(PKCS12)
    pkcs12._pkey = pykey
    pkcs12._cert = pycert
    pkcs12._cacerts = pycacerts
    pkcs12._friendlyname = friendlyname
    return pkcs12
def load_pkcs12(buffer, passphrase=None):
    """
    Load pkcs12 data from the string *buffer*. If the pkcs12 structure is
    encrypted, a *passphrase* must be included.  The MAC is always
    checked and thus required.

    See also the man page for the C function :py:func:`PKCS12_parse`.

    :param buffer: The buffer the certificate is stored in
    :param passphrase: (Optional) The password to decrypt the PKCS12 lump
    :returns: The PKCS12 object
    """
    passphrase = _text_to_bytes_and_warn("passphrase", passphrase)

    if isinstance(buffer, _text_type):
        buffer = buffer.encode("ascii")

    bio = _new_mem_buf(buffer)

    # Use null passphrase if passphrase is None or empty string. With PKCS#12
    # password based encryption no password and a zero length password are two
    # different things, but OpenSSL implementation will try both to figure out
    # which one works.
    if not passphrase:
        passphrase = _ffi.NULL

    p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
    if p12 == _ffi.NULL:
        _raise_current_error()
    p12 = _ffi.gc(p12, _lib.PKCS12_free)

    pkey = _ffi.new("EVP_PKEY**")
    cert = _ffi.new("X509**")
    cacerts = _ffi.new("Cryptography_STACK_OF_X509**")

    parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
    if not parse_result:
        _raise_current_error()

    cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)

    # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
    # queue for no particular reason.  This error isn't interesting to anyone
    # outside this function.  It's not even interesting to us.  Get rid of it.
    try:
        _raise_current_error()
    except Error:
        pass

    if pkey[0] == _ffi.NULL:
        pykey = None
    else:
        pykey = PKey.__new__(PKey)
        pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)

    if cert[0] == _ffi.NULL:
        pycert = None
        friendlyname = None
    else:
        pycert = X509._from_raw_x509_ptr(cert[0])

        friendlyname_length = _ffi.new("int*")
        friendlyname_buffer = _lib.X509_alias_get0(
            cert[0], friendlyname_length
        )
        friendlyname = _ffi.buffer(
            friendlyname_buffer, friendlyname_length[0]
        )[:]
        if friendlyname_buffer == _ffi.NULL:
            friendlyname = None

    pycacerts = []
    for i in range(_lib.sk_X509_num(cacerts)):
        x509 = _lib.sk_X509_value(cacerts, i)
        pycacert = X509._from_raw_x509_ptr(x509)
        pycacerts.append(pycacert)
    if not pycacerts:
        pycacerts = None

    pkcs12 = PKCS12.__new__(PKCS12)
    pkcs12._pkey = pykey
    pkcs12._cert = pycert
    pkcs12._cacerts = pycacerts
    pkcs12._friendlyname = friendlyname
    return pkcs12
Load pkcs12 data from the string *buffer*. If the pkcs12 structure is
    encrypted, a *passphrase* must be included.  The MAC is always
    checked and thus required.

    See also the man page for the C function :py:func:`PKCS12_parse`.

    :param buffer: The buffer the certificate is stored in
    :param passphrase: (Optional) The password to decrypt the PKCS12 lump
    :returns: The PKCS12 object