Use new PKCS#12 deserialization code from cryptography 36.0.0 if available (#302)
* Use new PKCS#12 deserialization code from cryptography 36.0.0 if available. * Refactor into smaller functions. * Force complete CI run now since cryptography 36.0.0 is out. ci_completepull/349/head
parent
f832c0a4ac
commit
73bc0f5de7
|
@ -0,0 +1,2 @@
|
||||||
|
bugfixes:
|
||||||
|
- "openssl_pkcs12 - use new PKCS#12 deserialization infrastructure from cryptography 36.0.0 if available (https://github.com/ansible-collections/community.crypto/pull/302)."
|
|
@ -48,6 +48,15 @@ except ImportError:
|
||||||
# Error handled in the calling module.
|
# Error handled in the calling module.
|
||||||
_load_key_and_certificates = None
|
_load_key_and_certificates = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
# This is a separate try/except since this is only present in cryptography 36.0.0 or newer
|
||||||
|
from cryptography.hazmat.primitives.serialization.pkcs12 import (
|
||||||
|
load_pkcs12 as _load_pkcs12,
|
||||||
|
)
|
||||||
|
except ImportError:
|
||||||
|
# Error handled in the calling module.
|
||||||
|
_load_pkcs12 = None
|
||||||
|
|
||||||
from .basic import (
|
from .basic import (
|
||||||
CRYPTOGRAPHY_HAS_ED25519,
|
CRYPTOGRAPHY_HAS_ED25519,
|
||||||
CRYPTOGRAPHY_HAS_ED448,
|
CRYPTOGRAPHY_HAS_ED448,
|
||||||
|
@ -512,23 +521,44 @@ def cryptography_serial_number_of_cert(cert):
|
||||||
def parse_pkcs12(pkcs12_bytes, passphrase=None):
|
def parse_pkcs12(pkcs12_bytes, passphrase=None):
|
||||||
'''Returns a tuple (private_key, certificate, additional_certificates, friendly_name).
|
'''Returns a tuple (private_key, certificate, additional_certificates, friendly_name).
|
||||||
'''
|
'''
|
||||||
if _load_key_and_certificates is None:
|
if _load_pkcs12 is None and _load_key_and_certificates is None:
|
||||||
raise ValueError('load_key_and_certificates() not present in the current cryptography version')
|
raise ValueError('neither load_pkcs12() nor load_key_and_certificates() present in the current cryptography version')
|
||||||
private_key, certificate, additional_certificates = _load_key_and_certificates(
|
|
||||||
pkcs12_bytes, to_bytes(passphrase) if passphrase is not None else None)
|
if passphrase is not None:
|
||||||
|
passphrase = to_bytes(passphrase)
|
||||||
|
|
||||||
|
# Main code for cryptography 36.0.0 and forward
|
||||||
|
if _load_pkcs12 is not None:
|
||||||
|
return _parse_pkcs12_36_0_0(pkcs12_bytes, passphrase)
|
||||||
|
|
||||||
|
if LooseVersion(cryptography.__version__) >= LooseVersion('35.0'):
|
||||||
|
return _parse_pkcs12_35_0_0(pkcs12_bytes, passphrase)
|
||||||
|
|
||||||
|
return _parse_pkcs12_legacy(pkcs12_bytes, passphrase)
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_pkcs12_36_0_0(pkcs12_bytes, passphrase=None):
|
||||||
|
# Requires cryptography 36.0.0 or newer
|
||||||
|
pkcs12 = _load_pkcs12(pkcs12_bytes, passphrase)
|
||||||
|
additional_certificates = [cert.certificate for cert in pkcs12.additional_certs]
|
||||||
|
private_key = pkcs12.key
|
||||||
|
certificate = None
|
||||||
|
friendly_name = None
|
||||||
|
if pkcs12.cert:
|
||||||
|
certificate = pkcs12.cert.certificate
|
||||||
|
friendly_name = pkcs12.cert.friendly_name
|
||||||
|
return private_key, certificate, additional_certificates, friendly_name
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_pkcs12_35_0_0(pkcs12_bytes, passphrase=None):
|
||||||
|
# Backwards compatibility code for cryptography 35.x
|
||||||
|
private_key, certificate, additional_certificates = _load_key_and_certificates(pkcs12_bytes, passphrase)
|
||||||
|
|
||||||
friendly_name = None
|
friendly_name = None
|
||||||
if certificate:
|
if certificate:
|
||||||
# See https://github.com/pyca/cryptography/issues/5760#issuecomment-842687238
|
# See https://github.com/pyca/cryptography/issues/5760#issuecomment-842687238
|
||||||
backend = default_backend()
|
backend = default_backend()
|
||||||
try:
|
|
||||||
# For certain old versions of cryptography, backend is a MultiBackend object,
|
|
||||||
# which has no _lib attribute. In that case, revert to the old approach.
|
|
||||||
backend._lib
|
|
||||||
except AttributeError:
|
|
||||||
backend = certificate._backend
|
|
||||||
|
|
||||||
if LooseVersion(cryptography.__version__) >= LooseVersion('35.0'):
|
|
||||||
# This code basically does what load_key_and_certificates() does, but without error-checking.
|
# This code basically does what load_key_and_certificates() does, but without error-checking.
|
||||||
# Since load_key_and_certificates succeeded, it should not fail.
|
# Since load_key_and_certificates succeeded, it should not fail.
|
||||||
pkcs12 = backend._ffi.gc(
|
pkcs12 = backend._ffi.gc(
|
||||||
|
@ -546,8 +576,18 @@ def parse_pkcs12(pkcs12_bytes, passphrase=None):
|
||||||
maybe_name = backend._lib.X509_alias_get0(certificate_x509_ptr[0], backend._ffi.NULL)
|
maybe_name = backend._lib.X509_alias_get0(certificate_x509_ptr[0], backend._ffi.NULL)
|
||||||
if maybe_name != backend._ffi.NULL:
|
if maybe_name != backend._ffi.NULL:
|
||||||
friendly_name = backend._ffi.string(maybe_name)
|
friendly_name = backend._ffi.string(maybe_name)
|
||||||
else:
|
|
||||||
# cryptography < 35.0.0
|
return private_key, certificate, additional_certificates, friendly_name
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_pkcs12_legacy(pkcs12_bytes, passphrase=None):
|
||||||
|
# Backwards compatibility code for cryptography < 35.0.0
|
||||||
|
private_key, certificate, additional_certificates = _load_key_and_certificates(pkcs12_bytes, passphrase)
|
||||||
|
|
||||||
|
friendly_name = None
|
||||||
|
if certificate:
|
||||||
|
# See https://github.com/pyca/cryptography/issues/5760#issuecomment-842687238
|
||||||
|
backend = certificate._backend
|
||||||
maybe_name = backend._lib.X509_alias_get0(certificate._x509, backend._ffi.NULL)
|
maybe_name = backend._lib.X509_alias_get0(certificate._x509, backend._ffi.NULL)
|
||||||
if maybe_name != backend._ffi.NULL:
|
if maybe_name != backend._ffi.NULL:
|
||||||
friendly_name = backend._ffi.string(maybe_name)
|
friendly_name = backend._ffi.string(maybe_name)
|
||||||
|
|
Loading…
Reference in New Issue