second commit

This commit is contained in:
Александр Геннадьевич Сальный
2022-10-15 21:01:12 +03:00
commit 7caeeaaff5
1329 changed files with 489315 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.

View File

@@ -0,0 +1,367 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
import typing
def cryptography_has_ec2m() -> typing.List[str]:
return [
"EC_POINT_get_affine_coordinates_GF2m",
]
def cryptography_has_ssl3_method() -> typing.List[str]:
return [
"SSLv3_method",
"SSLv3_client_method",
"SSLv3_server_method",
]
def cryptography_has_110_verification_params() -> typing.List[str]:
return ["X509_CHECK_FLAG_NEVER_CHECK_SUBJECT"]
def cryptography_has_set_cert_cb() -> typing.List[str]:
return [
"SSL_CTX_set_cert_cb",
"SSL_set_cert_cb",
]
def cryptography_has_ssl_st() -> typing.List[str]:
return [
"SSL_ST_BEFORE",
"SSL_ST_OK",
"SSL_ST_INIT",
"SSL_ST_RENEGOTIATE",
]
def cryptography_has_tls_st() -> typing.List[str]:
return [
"TLS_ST_BEFORE",
"TLS_ST_OK",
]
def cryptography_has_scrypt() -> typing.List[str]:
return [
"EVP_PBE_scrypt",
]
def cryptography_has_evp_pkey_dhx() -> typing.List[str]:
return [
"EVP_PKEY_DHX",
]
def cryptography_has_mem_functions() -> typing.List[str]:
return [
"Cryptography_CRYPTO_set_mem_functions",
]
def cryptography_has_x509_store_ctx_get_issuer() -> typing.List[str]:
return [
"X509_STORE_get_get_issuer",
"X509_STORE_set_get_issuer",
]
def cryptography_has_ed448() -> typing.List[str]:
return [
"EVP_PKEY_ED448",
"NID_ED448",
]
def cryptography_has_ed25519() -> typing.List[str]:
return [
"NID_ED25519",
"EVP_PKEY_ED25519",
]
def cryptography_has_poly1305() -> typing.List[str]:
return [
"NID_poly1305",
"EVP_PKEY_POLY1305",
]
def cryptography_has_oneshot_evp_digest_sign_verify() -> typing.List[str]:
return [
"EVP_DigestSign",
"EVP_DigestVerify",
]
def cryptography_has_evp_digestfinal_xof() -> typing.List[str]:
return [
"EVP_DigestFinalXOF",
]
def cryptography_has_evp_pkey_get_set_tls_encodedpoint() -> typing.List[str]:
return [
"EVP_PKEY_get1_tls_encodedpoint",
"EVP_PKEY_set1_tls_encodedpoint",
]
def cryptography_has_fips() -> typing.List[str]:
return [
"FIPS_mode_set",
"FIPS_mode",
]
def cryptography_has_psk() -> typing.List[str]:
return [
"SSL_CTX_use_psk_identity_hint",
"SSL_CTX_set_psk_server_callback",
"SSL_CTX_set_psk_client_callback",
]
def cryptography_has_psk_tlsv13() -> typing.List[str]:
return [
"SSL_CTX_set_psk_find_session_callback",
"SSL_CTX_set_psk_use_session_callback",
"Cryptography_SSL_SESSION_new",
"SSL_CIPHER_find",
"SSL_SESSION_set1_master_key",
"SSL_SESSION_set_cipher",
"SSL_SESSION_set_protocol_version",
]
def cryptography_has_custom_ext() -> typing.List[str]:
return [
"SSL_CTX_add_client_custom_ext",
"SSL_CTX_add_server_custom_ext",
"SSL_extension_supported",
]
def cryptography_has_openssl_cleanup() -> typing.List[str]:
return [
"OPENSSL_cleanup",
]
def cryptography_has_tlsv13() -> typing.List[str]:
return [
"TLS1_3_VERSION",
"SSL_OP_NO_TLSv1_3",
]
def cryptography_has_tlsv13_functions() -> typing.List[str]:
return [
"SSL_VERIFY_POST_HANDSHAKE",
"SSL_CTX_set_ciphersuites",
"SSL_verify_client_post_handshake",
"SSL_CTX_set_post_handshake_auth",
"SSL_set_post_handshake_auth",
"SSL_SESSION_get_max_early_data",
"SSL_write_early_data",
"SSL_read_early_data",
"SSL_CTX_set_max_early_data",
]
def cryptography_has_keylog() -> typing.List[str]:
return [
"SSL_CTX_set_keylog_callback",
"SSL_CTX_get_keylog_callback",
]
def cryptography_has_raw_key() -> typing.List[str]:
return [
"EVP_PKEY_new_raw_private_key",
"EVP_PKEY_new_raw_public_key",
"EVP_PKEY_get_raw_private_key",
"EVP_PKEY_get_raw_public_key",
]
def cryptography_has_engine() -> typing.List[str]:
return [
"ENGINE_by_id",
"ENGINE_init",
"ENGINE_finish",
"ENGINE_get_default_RAND",
"ENGINE_set_default_RAND",
"ENGINE_unregister_RAND",
"ENGINE_ctrl_cmd",
"ENGINE_free",
"ENGINE_get_name",
"Cryptography_add_osrandom_engine",
"ENGINE_ctrl_cmd_string",
"ENGINE_load_builtin_engines",
"ENGINE_load_private_key",
"ENGINE_load_public_key",
"SSL_CTX_set_client_cert_engine",
]
def cryptography_has_verified_chain() -> typing.List[str]:
return [
"SSL_get0_verified_chain",
]
def cryptography_has_srtp() -> typing.List[str]:
return [
"SSL_CTX_set_tlsext_use_srtp",
"SSL_set_tlsext_use_srtp",
"SSL_get_selected_srtp_profile",
]
def cryptography_has_get_proto_version() -> typing.List[str]:
return [
"SSL_CTX_get_min_proto_version",
"SSL_CTX_get_max_proto_version",
"SSL_get_min_proto_version",
"SSL_get_max_proto_version",
]
def cryptography_has_providers() -> typing.List[str]:
return [
"OSSL_PROVIDER_load",
"OSSL_PROVIDER_unload",
"ERR_LIB_PROV",
"PROV_R_WRONG_FINAL_BLOCK_LENGTH",
"PROV_R_BAD_DECRYPT",
]
def cryptography_has_op_no_renegotiation() -> typing.List[str]:
return [
"SSL_OP_NO_RENEGOTIATION",
]
def cryptography_has_dtls_get_data_mtu() -> typing.List[str]:
return [
"DTLS_get_data_mtu",
]
def cryptography_has_300_fips() -> typing.List[str]:
return [
"EVP_default_properties_is_fips_enabled",
"EVP_default_properties_enable_fips",
]
def cryptography_has_ssl_cookie() -> typing.List[str]:
return [
"SSL_OP_COOKIE_EXCHANGE",
"DTLSv1_listen",
"SSL_CTX_set_cookie_generate_cb",
"SSL_CTX_set_cookie_verify_cb",
]
def cryptography_has_pkcs7_funcs() -> typing.List[str]:
return [
"SMIME_write_PKCS7",
"PEM_write_bio_PKCS7_stream",
"PKCS7_sign_add_signer",
"PKCS7_final",
"PKCS7_verify",
"SMIME_read_PKCS7",
"PKCS7_get0_signers",
]
def cryptography_has_bn_flags() -> typing.List[str]:
return [
"BN_FLG_CONSTTIME",
"BN_set_flags",
"BN_prime_checks_for_size",
]
def cryptography_has_evp_pkey_dh() -> typing.List[str]:
return [
"EVP_PKEY_set1_DH",
]
def cryptography_has_300_evp_cipher() -> typing.List[str]:
return ["EVP_CIPHER_fetch", "EVP_CIPHER_free"]
def cryptography_has_unexpected_eof_while_reading() -> typing.List[str]:
return ["SSL_R_UNEXPECTED_EOF_WHILE_READING"]
# This is a mapping of
# {condition: function-returning-names-dependent-on-that-condition} so we can
# loop over them and delete unsupported names at runtime. It will be removed
# when cffi supports #if in cdef. We use functions instead of just a dict of
# lists so we can use coverage to measure which are used.
CONDITIONAL_NAMES = {
"Cryptography_HAS_EC2M": cryptography_has_ec2m,
"Cryptography_HAS_SSL3_METHOD": cryptography_has_ssl3_method,
"Cryptography_HAS_110_VERIFICATION_PARAMS": (
cryptography_has_110_verification_params
),
"Cryptography_HAS_SET_CERT_CB": cryptography_has_set_cert_cb,
"Cryptography_HAS_SSL_ST": cryptography_has_ssl_st,
"Cryptography_HAS_TLS_ST": cryptography_has_tls_st,
"Cryptography_HAS_SCRYPT": cryptography_has_scrypt,
"Cryptography_HAS_EVP_PKEY_DHX": cryptography_has_evp_pkey_dhx,
"Cryptography_HAS_MEM_FUNCTIONS": cryptography_has_mem_functions,
"Cryptography_HAS_X509_STORE_CTX_GET_ISSUER": (
cryptography_has_x509_store_ctx_get_issuer
),
"Cryptography_HAS_ED448": cryptography_has_ed448,
"Cryptography_HAS_ED25519": cryptography_has_ed25519,
"Cryptography_HAS_POLY1305": cryptography_has_poly1305,
"Cryptography_HAS_ONESHOT_EVP_DIGEST_SIGN_VERIFY": (
cryptography_has_oneshot_evp_digest_sign_verify
),
"Cryptography_HAS_EVP_PKEY_get_set_tls_encodedpoint": (
cryptography_has_evp_pkey_get_set_tls_encodedpoint
),
"Cryptography_HAS_FIPS": cryptography_has_fips,
"Cryptography_HAS_PSK": cryptography_has_psk,
"Cryptography_HAS_PSK_TLSv1_3": cryptography_has_psk_tlsv13,
"Cryptography_HAS_CUSTOM_EXT": cryptography_has_custom_ext,
"Cryptography_HAS_OPENSSL_CLEANUP": cryptography_has_openssl_cleanup,
"Cryptography_HAS_TLSv1_3": cryptography_has_tlsv13,
"Cryptography_HAS_TLSv1_3_FUNCTIONS": cryptography_has_tlsv13_functions,
"Cryptography_HAS_KEYLOG": cryptography_has_keylog,
"Cryptography_HAS_RAW_KEY": cryptography_has_raw_key,
"Cryptography_HAS_EVP_DIGESTFINAL_XOF": (
cryptography_has_evp_digestfinal_xof
),
"Cryptography_HAS_ENGINE": cryptography_has_engine,
"Cryptography_HAS_VERIFIED_CHAIN": cryptography_has_verified_chain,
"Cryptography_HAS_SRTP": cryptography_has_srtp,
"Cryptography_HAS_GET_PROTO_VERSION": cryptography_has_get_proto_version,
"Cryptography_HAS_PROVIDERS": cryptography_has_providers,
"Cryptography_HAS_OP_NO_RENEGOTIATION": (
cryptography_has_op_no_renegotiation
),
"Cryptography_HAS_DTLS_GET_DATA_MTU": cryptography_has_dtls_get_data_mtu,
"Cryptography_HAS_300_FIPS": cryptography_has_300_fips,
"Cryptography_HAS_SSL_COOKIE": cryptography_has_ssl_cookie,
"Cryptography_HAS_PKCS7_FUNCS": cryptography_has_pkcs7_funcs,
"Cryptography_HAS_BN_FLAGS": cryptography_has_bn_flags,
"Cryptography_HAS_EVP_PKEY_DH": cryptography_has_evp_pkey_dh,
"Cryptography_HAS_300_EVP_CIPHER": cryptography_has_300_evp_cipher,
"Cryptography_HAS_UNEXPECTED_EOF_WHILE_READING": (
cryptography_has_unexpected_eof_while_reading
),
}

View File

@@ -0,0 +1,230 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
import threading
import types
import typing
import warnings
import cryptography
from cryptography import utils
from cryptography.exceptions import InternalError
from cryptography.hazmat.bindings._openssl import ffi, lib
from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES
_OpenSSLErrorWithText = typing.NamedTuple(
"_OpenSSLErrorWithText",
[("code", int), ("lib", int), ("reason", int), ("reason_text", bytes)],
)
class _OpenSSLError:
def __init__(self, code: int, lib: int, reason: int):
self._code = code
self._lib = lib
self._reason = reason
def _lib_reason_match(self, lib: int, reason: int) -> bool:
return lib == self.lib and reason == self.reason
@property
def code(self) -> int:
return self._code
@property
def lib(self) -> int:
return self._lib
@property
def reason(self) -> int:
return self._reason
def _consume_errors(lib) -> typing.List[_OpenSSLError]:
errors = []
while True:
code: int = lib.ERR_get_error()
if code == 0:
break
err_lib: int = lib.ERR_GET_LIB(code)
err_reason: int = lib.ERR_GET_REASON(code)
errors.append(_OpenSSLError(code, err_lib, err_reason))
return errors
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_with_text(lib):
return _errors_with_text(_consume_errors(lib))
def _openssl_assert(
lib, ok: bool, errors: typing.Optional[typing.List[_OpenSSLError]] = None
) -> None:
if not ok:
if errors is None:
errors = _consume_errors(lib)
errors_with_text = _errors_with_text(errors)
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 build_conditional_library(lib, conditional_names):
conditional_lib = types.ModuleType("lib")
conditional_lib._original_lib = lib # type: ignore[attr-defined]
excluded_names = set()
for condition, names_cb in conditional_names.items():
if not getattr(lib, condition):
excluded_names.update(names_cb())
for attr in dir(lib):
if attr not in excluded_names:
setattr(conditional_lib, attr, getattr(lib, attr))
return conditional_lib
class Binding:
"""
OpenSSL API wrapper.
"""
lib: typing.ClassVar = None
ffi = ffi
_lib_loaded = False
_init_lock = threading.Lock()
_legacy_provider: typing.Any = None
_default_provider: typing.Any = None
def __init__(self):
self._ensure_ffi_initialized()
def _enable_fips(self) -> None:
# This function enables FIPS mode for OpenSSL 3.0.0 on installs that
# have the FIPS provider installed properly.
_openssl_assert(self.lib, self.lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER)
self._base_provider = self.lib.OSSL_PROVIDER_load(
self.ffi.NULL, b"base"
)
_openssl_assert(self.lib, self._base_provider != self.ffi.NULL)
self.lib._fips_provider = self.lib.OSSL_PROVIDER_load(
self.ffi.NULL, b"fips"
)
_openssl_assert(self.lib, self.lib._fips_provider != self.ffi.NULL)
res = self.lib.EVP_default_properties_enable_fips(self.ffi.NULL, 1)
_openssl_assert(self.lib, res == 1)
@classmethod
def _register_osrandom_engine(cls):
# Clear any errors extant in the queue before we start. In many
# scenarios other things may be interacting with OpenSSL in the same
# process space and it has proven untenable to assume that they will
# reliably clear the error queue. Once we clear it here we will
# error on any subsequent unexpected item in the stack.
cls.lib.ERR_clear_error()
if cls.lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE:
result = cls.lib.Cryptography_add_osrandom_engine()
_openssl_assert(cls.lib, result in (1, 2))
@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()
# As of OpenSSL 3.0.0 we must register a legacy cipher provider
# to get RC2 (needed for junk asymmetric private key
# serialization), RC4, Blowfish, IDEA, SEED, etc. These things
# are ugly legacy, but we aren't going to get rid of them
# any time soon.
if cls.lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER:
cls._legacy_provider = cls.lib.OSSL_PROVIDER_load(
cls.ffi.NULL, b"legacy"
)
_openssl_assert(
cls.lib, cls._legacy_provider != cls.ffi.NULL
)
cls._default_provider = cls.lib.OSSL_PROVIDER_load(
cls.ffi.NULL, b"default"
)
_openssl_assert(
cls.lib, cls._default_provider != cls.ffi.NULL
)
@classmethod
def init_static_locks(cls):
cls._ensure_ffi_initialized()
def _verify_openssl_version(lib):
if (
lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111
and not lib.CRYPTOGRAPHY_IS_LIBRESSL
and not lib.CRYPTOGRAPHY_IS_BORINGSSL
):
warnings.warn(
"OpenSSL version 1.1.0 is no longer supported by the OpenSSL "
"project, please upgrade. The next release of cryptography will "
"be the last to support compiling with OpenSSL 1.1.0.",
utils.DeprecatedIn37,
)
def _verify_package_version(version):
# Occasionally we run into situations where the version of the Python
# package does not match the version of the shared object that is loaded.
# This may occur in environments where multiple versions of cryptography
# are installed and available in the python path. To avoid errors cropping
# up later this code checks that the currently imported package and the
# shared object that were loaded have the same version and raise an
# ImportError if they do not
so_package_version = ffi.string(lib.CRYPTOGRAPHY_PACKAGE_VERSION)
if version.encode("ascii") != so_package_version:
raise ImportError(
"The version of cryptography does not match the loaded "
"shared object. This can happen if you have multiple copies of "
"cryptography installed in your Python path. Please try creating "
"a new virtual environment to resolve this issue. "
"Loaded python version: {}, shared object version: {}".format(
version, so_package_version
)
)
_verify_package_version(cryptography.__version__)
Binding.init_static_locks()
_verify_openssl_version(Binding.lib)