diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cryptography/exceptions.py | 1 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/multibackend.py | 25 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/asn1.py | 4 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/ssl.py | 12 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/x509.py | 34 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/x509_vfy.py | 2 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/x509name.py | 2 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/x509v3.py | 21 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/asymmetric/dsa.py | 32 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/asymmetric/ec.py | 26 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/asymmetric/rsa.py | 26 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/asymmetric/utils.py | 46 |
12 files changed, 225 insertions, 6 deletions
diff --git a/src/cryptography/exceptions.py b/src/cryptography/exceptions.py index 4270cb22..b0e1a993 100644 --- a/src/cryptography/exceptions.py +++ b/src/cryptography/exceptions.py @@ -14,6 +14,7 @@ class _Reasons(object): UNSUPPORTED_PUBLIC_KEY_ALGORITHM = object() UNSUPPORTED_ELLIPTIC_CURVE = object() UNSUPPORTED_SERIALIZATION = object() + UNSUPPORTED_X509 = object() class UnsupportedAlgorithm(Exception): diff --git a/src/cryptography/hazmat/backends/multibackend.py b/src/cryptography/hazmat/backends/multibackend.py index fce6c8e1..ffc569f4 100644 --- a/src/cryptography/hazmat/backends/multibackend.py +++ b/src/cryptography/hazmat/backends/multibackend.py @@ -12,7 +12,7 @@ from cryptography.hazmat.backends.interfaces import ( CMACBackend, CipherBackend, DSABackend, EllipticCurveBackend, HMACBackend, HashBackend, PBKDF2HMACBackend, PEMSerializationBackend, PKCS8SerializationBackend, RSABackend, - TraditionalOpenSSLSerializationBackend + TraditionalOpenSSLSerializationBackend, X509Backend ) @@ -27,6 +27,7 @@ from cryptography.hazmat.backends.interfaces import ( @utils.register_interface(DSABackend) @utils.register_interface(EllipticCurveBackend) @utils.register_interface(PEMSerializationBackend) +@utils.register_interface(X509Backend) class MultiBackend(object): name = "multibackend" @@ -347,3 +348,25 @@ class MultiBackend(object): "This backend does not support this key serialization.", _Reasons.UNSUPPORTED_SERIALIZATION ) + + def load_pem_x509_certificate(self, data): + for b in self._filtered_backends( + X509Backend + ): + return b.load_pem_x509_certificate(data) + + raise UnsupportedAlgorithm( + "This backend does not support X.509.", + _Reasons.UNSUPPORTED_X509 + ) + + def load_der_x509_certificate(self, data): + for b in self._filtered_backends( + X509Backend + ): + return b.load_der_x509_certificate(data) + + raise UnsupportedAlgorithm( + "This backend does not support X.509.", + _Reasons.UNSUPPORTED_X509 + ) diff --git a/src/cryptography/hazmat/bindings/openssl/asn1.py b/src/cryptography/hazmat/bindings/openssl/asn1.py index 2681dd9f..a73dc325 100644 --- a/src/cryptography/hazmat/bindings/openssl/asn1.py +++ b/src/cryptography/hazmat/bindings/openssl/asn1.py @@ -57,7 +57,11 @@ typedef ... ASN1_UTCTIME; static const int V_ASN1_GENERALIZEDTIME; +static const int MBSTRING_FLAG; +static const int MBSTRING_ASC; +static const int MBSTRING_BMP; static const int MBSTRING_UTF8; +static const int MBSTRING_UNIV; """ FUNCTIONS = """ diff --git a/src/cryptography/hazmat/bindings/openssl/ssl.py b/src/cryptography/hazmat/bindings/openssl/ssl.py index 1aed28d5..87c1429c 100644 --- a/src/cryptography/hazmat/bindings/openssl/ssl.py +++ b/src/cryptography/hazmat/bindings/openssl/ssl.py @@ -15,7 +15,7 @@ TYPES = """ * Internally invented symbols to tell which versions of SSL/TLS are supported. */ static const long Cryptography_HAS_SSL2; -static const long Cryptography_HAS_SSL3_METHOD; +static const long Cryptography_HAS_SSL3; static const long Cryptography_HAS_TLSv1_1; static const long Cryptography_HAS_TLSv1_2; static const long Cryptography_HAS_SECURE_RENEGOTIATION; @@ -211,6 +211,8 @@ int SSL_CTX_use_certificate_file(SSL_CTX *, const char *, int); int SSL_CTX_use_certificate_chain_file(SSL_CTX *, const char *); int SSL_CTX_use_PrivateKey(SSL_CTX *, EVP_PKEY *); int SSL_CTX_use_PrivateKey_file(SSL_CTX *, const char *, int); +int SSL_CTX_check_private_key(const SSL_CTX *); + void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *); X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *); int SSL_CTX_add_client_CA(SSL_CTX *, X509 *); @@ -385,13 +387,13 @@ SSL_METHOD* (*SSLv2_server_method)(void) = NULL; static const long Cryptography_HAS_SSL2 = 1; #endif -#ifdef OPENSSL_NO_SSL3_METHOD -static const long Cryptography_HAS_SSL3_METHOD = 0; +#ifdef OPENSSL_NO_SSL3 +static const long Cryptography_HAS_SSL3 = 0; SSL_METHOD* (*SSLv3_method)(void) = NULL; SSL_METHOD* (*SSLv3_client_method)(void) = NULL; SSL_METHOD* (*SSLv3_server_method)(void) = NULL; #else -static const long Cryptography_HAS_SSL3_METHOD = 1; +static const long Cryptography_HAS_SSL3 = 1; #endif #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME @@ -564,7 +566,7 @@ CONDITIONAL_NAMES = { "SSLv2_server_method", ], - "Cryptography_HAS_SSL3_METHOD": [ + "Cryptography_HAS_SSL3": [ "SSLv3_method", "SSLv3_client_method", "SSLv3_server_method", diff --git a/src/cryptography/hazmat/bindings/openssl/x509.py b/src/cryptography/hazmat/bindings/openssl/x509.py index 2fdba0f8..a6e1cb63 100644 --- a/src/cryptography/hazmat/bindings/openssl/x509.py +++ b/src/cryptography/hazmat/bindings/openssl/x509.py @@ -70,6 +70,39 @@ typedef struct { } X509; typedef ... NETSCAPE_SPKI; + +static const int X509_FLAG_COMPAT; +static const int X509_FLAG_NO_HEADER; +static const int X509_FLAG_NO_VERSION; +static const int X509_FLAG_NO_SERIAL; +static const int X509_FLAG_NO_SIGNAME; +static const int X509_FLAG_NO_ISSUER; +static const int X509_FLAG_NO_VALIDITY; +static const int X509_FLAG_NO_SUBJECT; +static const int X509_FLAG_NO_PUBKEY; +static const int X509_FLAG_NO_EXTENSIONS; +static const int X509_FLAG_NO_SIGDUMP; +static const int X509_FLAG_NO_AUX; +static const int X509_FLAG_NO_ATTRIBUTES; + +static const int XN_FLAG_SEP_MASK; +static const int XN_FLAG_COMPAT; +static const int XN_FLAG_SEP_COMMA_PLUS; +static const int XN_FLAG_SEP_CPLUS_SPC; +static const int XN_FLAG_SEP_SPLUS_SPC; +static const int XN_FLAG_SEP_MULTILINE; +static const int XN_FLAG_DN_REV; +static const int XN_FLAG_FN_MASK; +static const int XN_FLAG_FN_SN; +static const int XN_FLAG_FN_LN; +static const int XN_FLAG_FN_OID; +static const int XN_FLAG_FN_NONE; +static const int XN_FLAG_SPC_EQ; +static const int XN_FLAG_DUMP_UNKNOWN_FIELDS; +static const int XN_FLAG_FN_ALIGN; +static const int XN_FLAG_RFC2253; +static const int XN_FLAG_ONELINE; +static const int XN_FLAG_MULTILINE; """ FUNCTIONS = """ @@ -140,6 +173,7 @@ int X509_CRL_sign(X509_CRL *, EVP_PKEY *, const EVP_MD *); int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *, EVP_PKEY *); int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *, EVP_PKEY *, const EVP_MD *); char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *); +NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *, int); EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *); int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *, EVP_PKEY *); NETSCAPE_SPKI *NETSCAPE_SPKI_new(void); diff --git a/src/cryptography/hazmat/bindings/openssl/x509_vfy.py b/src/cryptography/hazmat/bindings/openssl/x509_vfy.py index 5b310230..6f05f4d7 100644 --- a/src/cryptography/hazmat/bindings/openssl/x509_vfy.py +++ b/src/cryptography/hazmat/bindings/openssl/x509_vfy.py @@ -131,6 +131,8 @@ int X509_verify_cert(X509_STORE_CTX *); X509_STORE *X509_STORE_new(void); void X509_STORE_free(X509_STORE *); int X509_STORE_add_cert(X509_STORE *, X509 *); +int X509_STORE_load_locations(X509_STORE *, const char *, const char *); +int X509_STORE_set_default_paths(X509_STORE *); /* X509_STORE_CTX */ X509_STORE_CTX *X509_STORE_CTX_new(void); diff --git a/src/cryptography/hazmat/bindings/openssl/x509name.py b/src/cryptography/hazmat/bindings/openssl/x509name.py index 59ce7576..9863c195 100644 --- a/src/cryptography/hazmat/bindings/openssl/x509name.py +++ b/src/cryptography/hazmat/bindings/openssl/x509name.py @@ -27,6 +27,8 @@ ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *); unsigned long X509_NAME_hash(X509_NAME *); int i2d_X509_NAME(X509_NAME *, unsigned char **); +int X509_NAME_add_entry_by_txt(X509_NAME *, const char *, int, + const unsigned char *, int, int, int); int X509_NAME_add_entry_by_NID(X509_NAME *, int, int, unsigned char *, int, int, int); X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *, int); diff --git a/src/cryptography/hazmat/bindings/openssl/x509v3.py b/src/cryptography/hazmat/bindings/openssl/x509v3.py index 364f3fa2..3b007249 100644 --- a/src/cryptography/hazmat/bindings/openssl/x509v3.py +++ b/src/cryptography/hazmat/bindings/openssl/x509v3.py @@ -6,6 +6,19 @@ from __future__ import absolute_import, division, print_function INCLUDES = """ #include <openssl/x509v3.h> + +/* + * This is part of a work-around for the difficulty cffi has in dealing with + * `LHASH_OF(foo)` as the name of a type. We invent a new, simpler name that + * will be an alias for this type and use the alias throughout. This works + * together with another opaque typedef for the same name in the TYPES section. + * Note that the result is an opaque type. + */ +#if OPENSSL_VERSION_NUMBER >= 0x10000000 +typedef LHASH_OF(CONF_VALUE) Cryptography_LHASH_OF_CONF_VALUE; +#else +typedef LHASH Cryptography_LHASH_OF_CONF_VALUE; +#endif """ TYPES = """ @@ -67,9 +80,13 @@ typedef struct { } GENERAL_NAME; typedef struct stack_st_GENERAL_NAME GENERAL_NAMES; + +typedef ... Cryptography_LHASH_OF_CONF_VALUE; """ + FUNCTIONS = """ +int X509V3_EXT_add_alias(int, int); void X509V3_set_ctx(X509V3_CTX *, X509 *, X509 *, X509_REQ *, X509_CRL *, int); X509_EXTENSION *X509V3_EXT_nconf(CONF *, X509V3_CTX *, char *, char *); int GENERAL_NAME_print(BIO *, GENERAL_NAME *); @@ -83,9 +100,13 @@ int sk_GENERAL_NAME_num(struct stack_st_GENERAL_NAME *); int sk_GENERAL_NAME_push(struct stack_st_GENERAL_NAME *, GENERAL_NAME *); GENERAL_NAME *sk_GENERAL_NAME_value(struct stack_st_GENERAL_NAME *, int); +X509_EXTENSION *X509V3_EXT_conf_nid(Cryptography_LHASH_OF_CONF_VALUE *, + X509V3_CTX *, int, char *); + /* These aren't macros these functions are all const X on openssl > 1.0.x */ const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *); const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int); + """ CUSTOMIZATIONS = """ diff --git a/src/cryptography/hazmat/primitives/asymmetric/dsa.py b/src/cryptography/hazmat/primitives/asymmetric/dsa.py index 5d942e04..9b06f3e6 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -59,6 +59,15 @@ class DSAParameterNumbers(object): def parameters(self, backend): return backend.load_dsa_parameter_numbers(self) + def __eq__(self, other): + if not isinstance(other, DSAParameterNumbers): + return NotImplemented + + return self.p == other.p and self.q == other.q and self.g == other.g + + def __ne__(self, other): + return not self == other + class DSAPublicNumbers(object): def __init__(self, y, parameter_numbers): @@ -79,6 +88,18 @@ class DSAPublicNumbers(object): def public_key(self, backend): return backend.load_dsa_public_numbers(self) + def __eq__(self, other): + if not isinstance(other, DSAPublicNumbers): + return NotImplemented + + return ( + self.y == other.y and + self.parameter_numbers == other.parameter_numbers + ) + + def __ne__(self, other): + return not self == other + class DSAPrivateNumbers(object): def __init__(self, x, public_numbers): @@ -97,3 +118,14 @@ class DSAPrivateNumbers(object): def private_key(self, backend): return backend.load_dsa_private_numbers(self) + + def __eq__(self, other): + if not isinstance(other, DSAPrivateNumbers): + return NotImplemented + + return ( + self.x == other.x and self.public_numbers == other.public_numbers + ) + + def __ne__(self, other): + return not self == other diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index d9c41c19..202f1c97 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -161,6 +161,20 @@ class EllipticCurvePublicNumbers(object): x = utils.read_only_property("_x") y = utils.read_only_property("_y") + def __eq__(self, other): + if not isinstance(other, EllipticCurvePublicNumbers): + return NotImplemented + + return ( + self.x == other.x and + self.y == other.y and + self.curve.name == other.curve.name and + self.curve.key_size == other.curve.key_size + ) + + def __ne__(self, other): + return not self == other + class EllipticCurvePrivateNumbers(object): def __init__(self, private_value, public_numbers): @@ -184,3 +198,15 @@ class EllipticCurvePrivateNumbers(object): private_value = utils.read_only_property("_private_value") public_numbers = utils.read_only_property("_public_numbers") + + def __eq__(self, other): + if not isinstance(other, EllipticCurvePrivateNumbers): + return NotImplemented + + return ( + self.private_value == other.private_value and + self.public_numbers == other.public_numbers + ) + + def __ne__(self, other): + return not self == other diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py index 6aeed006..0cc6b22b 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -160,6 +160,23 @@ class RSAPrivateNumbers(object): def private_key(self, backend): return backend.load_rsa_private_numbers(self) + def __eq__(self, other): + if not isinstance(other, RSAPrivateNumbers): + return NotImplemented + + return ( + self.p == other.p and + self.q == other.q and + self.d == other.d and + self.dmp1 == other.dmp1 and + self.dmq1 == other.dmq1 and + self.iqmp == other.iqmp and + self.public_numbers == other.public_numbers + ) + + def __ne__(self, other): + return not self == other + class RSAPublicNumbers(object): def __init__(self, e, n): @@ -180,3 +197,12 @@ class RSAPublicNumbers(object): def __repr__(self): return "<RSAPublicNumbers(e={0}, n={1})>".format(self._e, self._n) + + def __eq__(self, other): + if not isinstance(other, RSAPublicNumbers): + return NotImplemented + + return self.e == other.e and self.n == other.n + + def __ne__(self, other): + return not self == other diff --git a/src/cryptography/hazmat/primitives/asymmetric/utils.py b/src/cryptography/hazmat/primitives/asymmetric/utils.py new file mode 100644 index 00000000..71f4ff8e --- /dev/null +++ b/src/cryptography/hazmat/primitives/asymmetric/utils.py @@ -0,0 +1,46 @@ +# 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. + +from __future__ import absolute_import, division, print_function + +from pyasn1.codec.der import decoder, encoder +from pyasn1.error import PyAsn1Error +from pyasn1.type import namedtype, univ + +import six + + +class _DSSSigValue(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('r', univ.Integer()), + namedtype.NamedType('s', univ.Integer()) + ) + + +def decode_rfc6979_signature(signature): + try: + data, remaining = decoder.decode(signature, asn1Spec=_DSSSigValue()) + except PyAsn1Error: + raise ValueError("Invalid signature data. Unable to decode ASN.1") + + if remaining: + raise ValueError( + "The signature contains bytes after the end of the ASN.1 sequence." + ) + r = int(data.getComponentByName('r')) + s = int(data.getComponentByName('s')) + return (r, s) + + +def encode_rfc6979_signature(r, s): + if ( + not isinstance(r, six.integer_types) or + not isinstance(s, six.integer_types) + ): + raise ValueError("Both r and s must be integers") + + sig = _DSSSigValue() + sig.setComponentByName('r', r) + sig.setComponentByName('s', s) + return encoder.encode(sig) |