def _openssl_assert(lib, ok): if not ok: errors = _consume_errors(lib) errors_with_text = [] for err in errors: buf = ffi.new("char[]", 256) lib.ERR_error_string_n(err.code, buf, len(buf)) err_text_reason = ffi.string(buf) errors_with_text.append( _OpenSSLErrorWithText( err.code, err.lib, err.func, err.reason, err_text_reason ) ) raise InternalError( "Unknown OpenSSL error. This error is commonly encountered when " "another library is not cleaning up the OpenSSL error stack. If " "you are using cryptography with another library that uses " "OpenSSL try disabling it before reporting a bug. Otherwise " "please file an issue at https://github.com/pyca/cryptography/" "issues with information on how to reproduce " "this. ({0!r})".format(errors_with_text), errors_with_text )
def _openssl_assert(lib, ok): if not ok: errors = _consume_errors(lib) errors_with_text = [] for err in errors: buf = ffi.new("char[]", 256) lib.ERR_error_string_n(err.code, buf, len(buf)) err_text_reason = ffi.string(buf) errors_with_text.append( _OpenSSLErrorWithText( err.code, err.lib, err.func, err.reason, err_text_reason ) ) raise InternalError( "Unknown OpenSSL error. This error is commonly encountered when " "another library is not cleaning up the OpenSSL error stack. If " "you are using cryptography with another library that uses " "OpenSSL try disabling it before reporting a bug. Otherwise " "please file an issue at https://github.com/pyca/cryptography/" "issues with information on how to reproduce " "this. ({0!r})".format(errors_with_text), errors_with_text )
def _errors_with_text(errors): errors_with_text = [] for err in errors: buf = ffi.new("char[]", 256) lib.ERR_error_string_n(err.code, buf, len(buf)) err_text_reason = ffi.string(buf) errors_with_text.append( _OpenSSLErrorWithText(err.code, err.lib, err.func, err.reason, err_text_reason)) return errors_with_text
def _errors_with_text( errors: typing.List[_OpenSSLError], ) -> typing.List[_OpenSSLErrorWithText]: errors_with_text = [] for err in errors: buf = ffi.new("char[]", 256) lib.ERR_error_string_n(err.code, buf, len(buf)) err_text_reason: bytes = ffi.string(buf) errors_with_text.append( _OpenSSLErrorWithText(err.code, err.lib, err.reason, err_text_reason)) return errors_with_text
def _consume_errors(lib): if not ok: errors = _consume_errors(lib) errors_with_text = [] for err in errors: buf = ffi.new("char[]", 256) lib.ERR_error_string_n(err.code, buf, len(buf)) err_text_reason = ffi.string(buf) err_text_reason = ffi.string(buf) errors_with_text.append( _OpenSSLErrorWithText(err.code, err.lib, err.func, err.reason, err_text_reason)) raise InternalError( "xxx" "xxx" "this. ({0!r})".format(errors_with_text), errors_with_text)
class Binding(object): """ OpenSSL API wrapper. """ lib = None ffi = ffi _lib_loaded = False _locks = None _lock_cb_handle = None _init_lock = threading.Lock() _lock_init_lock = threading.Lock() _osrandom_engine_id = ffi.new("const char[]", b"osrandom") _osrandom_engine_name = ffi.new("const char[]", b"osrandom_engine") _osrandom_method = ffi.new( "RAND_METHOD *", dict(bytes=_osrandom_rand_bytes, pseudorand=_osrandom_rand_bytes, status=_osrandom_rand_status)) def __init__(self): self._ensure_ffi_initialized() @classmethod def _register_osrandom_engine(cls): _openssl_assert(cls.lib, cls.lib.ERR_peek_error() == 0) engine = cls.lib.ENGINE_new() _openssl_assert(cls.lib, engine != cls.ffi.NULL) try: result = cls.lib.ENGINE_set_id(engine, cls._osrandom_engine_id) _openssl_assert(cls.lib, result == 1) result = cls.lib.ENGINE_set_name(engine, cls._osrandom_engine_name) _openssl_assert(cls.lib, result == 1) result = cls.lib.ENGINE_set_RAND(engine, cls._osrandom_method) _openssl_assert(cls.lib, result == 1) result = cls.lib.ENGINE_add(engine) if result != 1: errors = _consume_errors(cls.lib) _openssl_assert( cls.lib, errors[0].reason == cls.lib.ENGINE_R_CONFLICTING_ENGINE_ID) finally: result = cls.lib.ENGINE_free(engine) _openssl_assert(cls.lib, result == 1) @classmethod def _ensure_ffi_initialized(cls): with cls._init_lock: if not cls._lib_loaded: cls.lib = build_conditional_library(lib, CONDITIONAL_NAMES) cls._lib_loaded = True # initialize the SSL library cls.lib.SSL_library_init() # adds all ciphers/digests for EVP cls.lib.OpenSSL_add_all_algorithms() # loads error strings for libcrypto and libssl functions cls.lib.SSL_load_error_strings() cls._register_osrandom_engine() @classmethod def init_static_locks(cls): with cls._lock_init_lock: cls._ensure_ffi_initialized() if not cls._lock_cb_handle: cls._lock_cb_handle = cls.ffi.callback( "void(int, int, const char *, int)", cls._lock_cb) # Use Python's implementation if available, importing _ssl triggers # the setup for this. __import__("_ssl") if cls.lib.CRYPTO_get_locking_callback() != cls.ffi.NULL: return # If nothing else has setup a locking callback already, we set up # our own num_locks = cls.lib.CRYPTO_num_locks() cls._locks = [threading.Lock() for n in range(num_locks)] cls.lib.CRYPTO_set_locking_callback(cls._lock_cb_handle) @classmethod def _lock_cb(cls, mode, n, file, line): lock = cls._locks[n] if mode & cls.lib.CRYPTO_LOCK: lock.acquire() elif mode & cls.lib.CRYPTO_UNLOCK: lock.release() else: raise RuntimeError( "Unknown lock mode {0}: lock={1}, file={2}, line={3}.".format( mode, n, file, line))
class Binding(object): """ OpenSSL API wrapper. """ lib = None ffi = ffi _lib_loaded = False _locks = None _lock_cb_handle = None _init_lock = threading.Lock() _lock_init_lock = threading.Lock() _osrandom_engine_id = ffi.new("const char[]", b"osrandom") _osrandom_engine_name = ffi.new("const char[]", b"osrandom_engine") _osrandom_method = ffi.new( "RAND_METHOD *", dict(bytes=_osrandom_rand_bytes, pseudorand=_osrandom_rand_bytes, status=_osrandom_rand_status)) def __init__(self): self._ensure_ffi_initialized() @classmethod def _register_osrandom_engine(cls): assert cls.lib.ERR_peek_error() == 0 looked_up_engine = cls.lib.ENGINE_by_id(cls._osrandom_engine_id) if looked_up_engine != ffi.NULL: raise RuntimeError("osrandom engine already registered") cls.lib.ERR_clear_error() engine = cls.lib.ENGINE_new() assert engine != cls.ffi.NULL try: result = cls.lib.ENGINE_set_id(engine, cls._osrandom_engine_id) assert result == 1 result = cls.lib.ENGINE_set_name(engine, cls._osrandom_engine_name) assert result == 1 result = cls.lib.ENGINE_set_RAND(engine, cls._osrandom_method) assert result == 1 result = cls.lib.ENGINE_add(engine) assert result == 1 finally: result = cls.lib.ENGINE_free(engine) assert result == 1 @classmethod def _ensure_ffi_initialized(cls): with cls._init_lock: if not cls._lib_loaded: cls.lib = build_conditional_library(lib, CONDITIONAL_NAMES) cls._lib_loaded = True cls._register_osrandom_engine() @classmethod def init_static_locks(cls): with cls._lock_init_lock: cls._ensure_ffi_initialized() if not cls._lock_cb_handle: cls._lock_cb_handle = cls.ffi.callback( "void(int, int, const char *, int)", cls._lock_cb) # Use Python's implementation if available, importing _ssl triggers # the setup for this. __import__("_ssl") if cls.lib.CRYPTO_get_locking_callback() != cls.ffi.NULL: return # If nothing else has setup a locking callback already, we set up # our own num_locks = cls.lib.CRYPTO_num_locks() cls._locks = [threading.Lock() for n in range(num_locks)] cls.lib.CRYPTO_set_locking_callback(cls._lock_cb_handle) @classmethod def _lock_cb(cls, mode, n, file, line): lock = cls._locks[n] if mode & cls.lib.CRYPTO_LOCK: lock.acquire() elif mode & cls.lib.CRYPTO_UNLOCK: lock.release() else: raise RuntimeError( "Unknown lock mode {0}: lock={1}, file={2}, line={3}.".format( mode, n, file, line))
class Binding(object): """ OpenSSL API wrapper. """ lib = None ffi = ffi _lib_loaded = False _init_lock = threading.Lock() _lock_init_lock = threading.Lock() _osrandom_engine_id = ffi.new("const char[]", b"osrandom") _osrandom_engine_name = ffi.new("const char[]", b"osrandom_engine") _osrandom_method = ffi.new( "RAND_METHOD *", dict(bytes=_osrandom_rand_bytes, pseudorand=_osrandom_rand_bytes, status=_osrandom_rand_status)) def __init__(self): self._ensure_ffi_initialized() @classmethod def _register_osrandom_engine(cls): _openssl_assert(cls.lib, cls.lib.ERR_peek_error() == 0) engine = cls.lib.ENGINE_new() _openssl_assert(cls.lib, engine != cls.ffi.NULL) try: result = cls.lib.ENGINE_set_id(engine, cls._osrandom_engine_id) _openssl_assert(cls.lib, result == 1) result = cls.lib.ENGINE_set_name(engine, cls._osrandom_engine_name) _openssl_assert(cls.lib, result == 1) result = cls.lib.ENGINE_set_RAND(engine, cls._osrandom_method) _openssl_assert(cls.lib, result == 1) result = cls.lib.ENGINE_add(engine) if result != 1: errors = _consume_errors(cls.lib) _openssl_assert( cls.lib, errors[0].reason == cls.lib.ENGINE_R_CONFLICTING_ENGINE_ID) finally: result = cls.lib.ENGINE_free(engine) _openssl_assert(cls.lib, result == 1) @classmethod def _ensure_ffi_initialized(cls): with cls._init_lock: if not cls._lib_loaded: cls.lib = build_conditional_library(lib, CONDITIONAL_NAMES) cls._lib_loaded = True # initialize the SSL library cls.lib.SSL_library_init() # adds all ciphers/digests for EVP cls.lib.OpenSSL_add_all_algorithms() # loads error strings for libcrypto and libssl functions cls.lib.SSL_load_error_strings() cls._register_osrandom_engine() @classmethod def init_static_locks(cls): with cls._lock_init_lock: cls._ensure_ffi_initialized() # Use Python's implementation if available, importing _ssl triggers # the setup for this. __import__("_ssl") if cls.lib.CRYPTO_get_locking_callback() != cls.ffi.NULL: return # If nothing else has setup a locking callback already, we set up # our own res = lib._setup_ssl_threads() _openssl_assert(cls.lib, res == 1)