diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 81 | ||||
-rw-r--r-- | src/cryptography/x509/oid.py | 13 |
2 files changed, 61 insertions, 33 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 768559cf..e69554f9 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -40,6 +40,7 @@ from cryptography.hazmat.backends.openssl.x509 import ( _Certificate, _CertificateRevocationList, _CertificateSigningRequest, _DISTPOINT_TYPE_FULLNAME, _DISTPOINT_TYPE_RELATIVENAME ) +from cryptography.hazmat.bindings._openssl import ffi as _ffi from cryptography.hazmat.bindings.openssl import binding from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa @@ -625,6 +626,34 @@ _EXTENSION_ENCODE_HANDLERS = { } +class _PasswordUserdata(object): + def __init__(self, password): + self.password = password + self.called = 0 + self.exception = None + + +def _pem_password_cb(buf, size, writing, userdata_handle): + ud = _ffi.from_handle(userdata_handle) + ud.called += 1 + + if not ud.password: + ud.exception = TypeError( + "Password was not given but private key is encrypted." + ) + return -1 + elif len(ud.password) < size: + pw_buf = _ffi.buffer(buf, size) + pw_buf[:len(ud.password)] = ud.password + return len(ud.password) + else: + ud.exception = ValueError( + "Passwords longer than {0} bytes are not supported " + "by this backend.".format(size - 1) + ) + return 0 + + @utils.register_interface(CipherBackend) @utils.register_interface(CMACBackend) @utils.register_interface(DERSerializationBackend) @@ -1090,37 +1119,22 @@ class Backend(object): Useful for decrypting PKCS8 files and so on. - Returns a tuple of (cdata function pointer, callback function). + Returns a tuple of (cdata function pointer, userdata). """ + # Forward compatibility for new static callbacks: + # _pem_password_cb is not a nested function because closures don't + # work well with static callbacks. Static callbacks are registered + # globally. The backend is passed in as userdata argument. - def pem_password_cb(buf, size, writing, userdata): - pem_password_cb.called += 1 + userdata = _PasswordUserdata(password=password) - if not password: - pem_password_cb.exception = TypeError( - "Password was not given but private key is encrypted." - ) - return 0 - elif len(password) < size: - pw_buf = self._ffi.buffer(buf, size) - pw_buf[:len(password)] = password - return len(password) - else: - pem_password_cb.exception = ValueError( - "Passwords longer than {0} bytes are not supported " - "by this backend.".format(size - 1) - ) - return 0 - - pem_password_cb.called = 0 - pem_password_cb.exception = None - - return ( - self._ffi.callback("int (char *, int, int, void *)", - pem_password_cb), - pem_password_cb + pem_password_cb = self._ffi.callback( + "int (char *, int, int, void *)", + _pem_password_cb, ) + return pem_password_cb, userdata + def _mgf1_hash_supported(self, algorithm): if self._lib.Cryptography_HAS_MGF1_MD: return self.hash_supported(algorithm) @@ -1626,31 +1640,32 @@ class Backend(object): def _load_key(self, openssl_read_func, convert_func, data, password): mem_bio = self._bytes_to_bio(data) - password_callback, password_func = self._pem_password_cb(password) + password_cb, userdata = self._pem_password_cb(password) + userdata_handle = self._ffi.new_handle(userdata) evp_pkey = openssl_read_func( mem_bio.bio, self._ffi.NULL, - password_callback, - self._ffi.NULL + password_cb, + userdata_handle, ) if evp_pkey == self._ffi.NULL: - if password_func.exception is not None: + if userdata.exception is not None: errors = self._consume_errors() self.openssl_assert(errors) - raise password_func.exception + raise userdata.exception else: self._handle_key_loading_error() evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) - if password is not None and password_func.called == 0: + if password is not None and userdata.called == 0: raise TypeError( "Password was given but private key is not encrypted.") assert ( - (password is not None and password_func.called == 1) or + (password is not None and userdata.called == 1) or password is None ) diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py index 27fab86b..7b4df1c9 100644 --- a/src/cryptography/x509/oid.py +++ b/src/cryptography/x509/oid.py @@ -109,6 +109,12 @@ class NameOID(object): PSEUDONYM = ObjectIdentifier("2.5.4.65") DOMAIN_COMPONENT = ObjectIdentifier("0.9.2342.19200300.100.1.25") EMAIL_ADDRESS = ObjectIdentifier("1.2.840.113549.1.9.1") + JURISDICTION_COUNTRY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.3") + JURISDICTION_LOCALITY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.1") + JURISDICTION_STATE_OR_PROVINCE_NAME = ObjectIdentifier( + "1.3.6.1.4.1.311.60.2.1.2" + ) + BUSINESS_CATEGORY = ObjectIdentifier("2.5.4.15") class SignatureAlgorithmOID(object): @@ -180,6 +186,13 @@ _OID_NAMES = { NameOID.PSEUDONYM: "pseudonym", NameOID.DOMAIN_COMPONENT: "domainComponent", NameOID.EMAIL_ADDRESS: "emailAddress", + NameOID.JURISDICTION_COUNTRY_NAME: "jurisdictionCountryName", + NameOID.JURISDICTION_LOCALITY_NAME: "jurisdictionLocalityName", + NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME: ( + "jurisdictionStateOrProvinceName" + ), + NameOID.BUSINESS_CATEGORY: "businessCategory", + SignatureAlgorithmOID.RSA_WITH_MD5: "md5WithRSAEncryption", SignatureAlgorithmOID.RSA_WITH_SHA1: "sha1WithRSAEncryption", SignatureAlgorithmOID.RSA_WITH_SHA224: "sha224WithRSAEncryption", |