diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/bio.py | 6 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/cms.py | 61 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/ecdsa.py | 8 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/err.py | 8 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/ssl.py | 24 | ||||
-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 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/serialization.py | 77 | ||||
-rw-r--r-- | src/cryptography/utils.py | 7 |
11 files changed, 296 insertions, 25 deletions
diff --git a/src/cryptography/hazmat/bindings/openssl/bio.py b/src/cryptography/hazmat/bindings/openssl/bio.py index 854b2bc6..6cc1bcb2 100644 --- a/src/cryptography/hazmat/bindings/openssl/bio.py +++ b/src/cryptography/hazmat/bindings/openssl/bio.py @@ -17,7 +17,7 @@ struct bio_method_st { int (*bwrite)(BIO *, const char *, int); int (*bread)(BIO *, char *, int); int (*bputs)(BIO *, const char *); - int (*bgets)(BIO *, char*, int); + int (*bgets)(BIO *, char *, int); long (*ctrl)(BIO *, int, long, void *); int (*create)(BIO *); int (*destroy)(BIO *); @@ -27,7 +27,7 @@ struct bio_method_st { typedef struct bio_method_st BIO_METHOD; struct bio_st { BIO_METHOD *method; - long (*callback)(struct bio_st*, int, const char*, int, long, long); + long (*callback)(struct bio_st *, int, const char *, int, long, long); char *cb_arg; int init; int shutdown; @@ -89,7 +89,7 @@ static const int BIO_TYPE_FILTER; """ FUNCTIONS = """ -BIO* BIO_new(BIO_METHOD *); +BIO *BIO_new(BIO_METHOD *); int BIO_set(BIO *, BIO_METHOD *); int BIO_free(BIO *); void BIO_vfree(BIO *); diff --git a/src/cryptography/hazmat/bindings/openssl/cms.py b/src/cryptography/hazmat/bindings/openssl/cms.py index 7cbedf44..a43df5d9 100644 --- a/src/cryptography/hazmat/bindings/openssl/cms.py +++ b/src/cryptography/hazmat/bindings/openssl/cms.py @@ -25,6 +25,27 @@ typedef ... CMS_RevocationInfoChoice; typedef ... CMS_RecipientInfo; typedef ... CMS_ReceiptRequest; typedef ... CMS_Receipt; + +static const int CMS_TEXT; +static const int CMS_NOCERTS; +static const int CMS_NO_CONTENT_VERIFY; +static const int CMS_NO_ATTR_VERIFY; +static const int CMS_NOSIGS; +static const int CMS_NOINTERN; +static const int CMS_NO_SIGNER_CERT_VERIFY; +static const int CMS_NOVERIFY; +static const int CMS_DETACHED; +static const int CMS_BINARY; +static const int CMS_NOATTR; +static const int CMS_NOSMIMECAP; +static const int CMS_NOOLDMIMETYPE; +static const int CMS_CRLFEOL; +static const int CMS_STREAM; +static const int CMS_NOCRL; +static const int CMS_PARTIAL; +static const int CMS_REUSE_DIGEST; +static const int CMS_USE_KEYID; +static const int CMS_DEBUG_DECRYPT; """ FUNCTIONS = """ @@ -59,6 +80,26 @@ typedef void CMS_RevocationInfoChoice; typedef void CMS_RecipientInfo; typedef void CMS_ReceiptRequest; typedef void CMS_Receipt; +const long CMS_TEXT = 0; +const long CMS_NOCERTS = 0; +const long CMS_NO_CONTENT_VERIFY = 0; +const long CMS_NO_ATTR_VERIFY = 0; +const long CMS_NOSIGS = 0; +const long CMS_NOINTERN = 0; +const long CMS_NO_SIGNER_CERT_VERIFY = 0; +const long CMS_NOVERIFY = 0; +const long CMS_DETACHED = 0; +const long CMS_BINARY = 0; +const long CMS_NOATTR = 0; +const long CMS_NOSMIMECAP = 0; +const long CMS_NOOLDMIMETYPE = 0; +const long CMS_CRLFEOL = 0; +const long CMS_STREAM = 0; +const long CMS_NOCRL = 0; +const long CMS_PARTIAL = 0; +const long CMS_REUSE_DIGEST = 0; +const long CMS_USE_KEYID = 0; +const long CMS_DEBUG_DECRYPT = 0; BIO *(*BIO_new_CMS)(BIO *, CMS_ContentInfo *) = NULL; int (*i2d_CMS_bio_stream)(BIO *, CMS_ContentInfo *, BIO *, int) = NULL; int (*PEM_write_bio_CMS_stream)(BIO *, CMS_ContentInfo *, BIO *, int) = NULL; @@ -87,5 +128,25 @@ CONDITIONAL_NAMES = { "CMS_encrypt", "CMS_decrypt", "CMS_add1_signer", + "CMS_TEXT", + "CMS_NOCERTS", + "CMS_NO_CONTENT_VERIFY", + "CMS_NO_ATTR_VERIFY", + "CMS_NOSIGS", + "CMS_NOINTERN", + "CMS_NO_SIGNER_CERT_VERIFY", + "CMS_NOVERIFY", + "CMS_DETACHED", + "CMS_BINARY", + "CMS_NOATTR", + "CMS_NOSMIMECAP", + "CMS_NOOLDMIMETYPE", + "CMS_CRLFEOL", + "CMS_STREAM", + "CMS_NOCRL", + "CMS_PARTIAL", + "CMS_REUSE_DIGEST", + "CMS_USE_KEYID", + "CMS_DEBUG_DECRYPT", ] } diff --git a/src/cryptography/hazmat/bindings/openssl/ecdsa.py b/src/cryptography/hazmat/bindings/openssl/ecdsa.py index 30866d11..db21025c 100644 --- a/src/cryptography/hazmat/bindings/openssl/ecdsa.py +++ b/src/cryptography/hazmat/bindings/openssl/ecdsa.py @@ -34,7 +34,7 @@ ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **s, const unsigned char **, long); ECDSA_SIG *ECDSA_do_sign(const unsigned char *, int, EC_KEY *); ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *, int, const BIGNUM *, const BIGNUM *, EC_KEY *); -int ECDSA_do_verify(const unsigned char *, int, const ECDSA_SIG *, EC_KEY*); +int ECDSA_do_verify(const unsigned char *, int, const ECDSA_SIG *, EC_KEY *); int ECDSA_sign_setup(EC_KEY *, BN_CTX *, BIGNUM **, BIGNUM **); int ECDSA_sign(int, const unsigned char *, int, unsigned char *, unsigned int *, EC_KEY *); @@ -44,9 +44,9 @@ int ECDSA_verify(int, const unsigned char *, int, const unsigned char *, int, EC_KEY *); int ECDSA_size(const EC_KEY *); -const ECDSA_METHOD* ECDSA_OpenSSL(); +const ECDSA_METHOD *ECDSA_OpenSSL(); void ECDSA_set_default_method(const ECDSA_METHOD *); -const ECDSA_METHOD* ECDSA_get_default_method(); +const ECDSA_METHOD *ECDSA_get_default_method(); int ECDSA_get_ex_new_index(long, void *, CRYPTO_EX_new *, CRYPTO_EX_dup *, CRYPTO_EX_free *); int ECDSA_set_method(EC_KEY *, const ECDSA_METHOD *); @@ -72,7 +72,7 @@ ECDSA_SIG* (*ECDSA_do_sign)(const unsigned char *, int, EC_KEY *eckey) = NULL; ECDSA_SIG* (*ECDSA_do_sign_ex)(const unsigned char *, int, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL; int (*ECDSA_do_verify)(const unsigned char *, int, const ECDSA_SIG *, - EC_KEY*) = NULL; + EC_KEY *) = NULL; int (*ECDSA_sign_setup)(EC_KEY *, BN_CTX *, BIGNUM **, BIGNUM **) = NULL; int (*ECDSA_sign)(int, const unsigned char *, int, unsigned char *, unsigned int *, EC_KEY *) = NULL; diff --git a/src/cryptography/hazmat/bindings/openssl/err.py b/src/cryptography/hazmat/bindings/openssl/err.py index 1d43acd7..ec393c1b 100644 --- a/src/cryptography/hazmat/bindings/openssl/err.py +++ b/src/cryptography/hazmat/bindings/openssl/err.py @@ -231,11 +231,11 @@ FUNCTIONS = """ void ERR_load_crypto_strings(void); void ERR_load_SSL_strings(void); void ERR_free_strings(void); -char* ERR_error_string(unsigned long, char *); +char *ERR_error_string(unsigned long, char *); void ERR_error_string_n(unsigned long, char *, size_t); -const char* ERR_lib_error_string(unsigned long); -const char* ERR_func_error_string(unsigned long); -const char* ERR_reason_error_string(unsigned long); +const char *ERR_lib_error_string(unsigned long); +const char *ERR_func_error_string(unsigned long); +const char *ERR_reason_error_string(unsigned long); void ERR_print_errors(BIO *); void ERR_print_errors_fp(FILE *); unsigned long ERR_get_error(void); diff --git a/src/cryptography/hazmat/bindings/openssl/ssl.py b/src/cryptography/hazmat/bindings/openssl/ssl.py index 1aed28d5..9a48f586 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 *); @@ -320,7 +322,7 @@ void (*SSL_CTX_get_info_callback(SSL_CTX *))(const SSL *, int, int); RHEL/CentOS 5 this can be moved back to FUNCTIONS. */ SSL_CTX *SSL_set_SSL_CTX(SSL *, SSL_CTX *); -const SSL_METHOD* Cryptography_SSL_CTX_get_method(const SSL_CTX*); +const SSL_METHOD *Cryptography_SSL_CTX_get_method(const SSL_CTX *); /* NPN APIs were introduced in OpenSSL 1.0.1. To continue to support earlier * versions some special handling of these is necessary. @@ -351,8 +353,8 @@ SSL_CIPHER *sk_SSL_CIPHER_value(Cryptography_STACK_OF_SSL_CIPHER *, int); /* ALPN APIs were introduced in OpenSSL 1.0.2. To continue to support earlier * versions some special handling of these is necessary. */ -int SSL_CTX_set_alpn_protos(SSL_CTX *, const unsigned char*, unsigned); -int SSL_set_alpn_protos(SSL *, const unsigned char*, unsigned); +int SSL_CTX_set_alpn_protos(SSL_CTX *, const unsigned char *, unsigned); +int SSL_set_alpn_protos(SSL *, const unsigned char *, unsigned); void SSL_CTX_set_alpn_select_cb(SSL_CTX *, int (*) (SSL *, const unsigned char **, @@ -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 @@ -485,7 +487,7 @@ static const long Cryptography_HAS_NETBSD_D1_METH = 1; #endif /* Workaround for #794 caused by cffi const** bug. */ -const SSL_METHOD* Cryptography_SSL_CTX_get_method(const SSL_CTX* ctx) { +const SSL_METHOD *Cryptography_SSL_CTX_get_method(const SSL_CTX *ctx) { return ctx->method; } @@ -523,9 +525,9 @@ static const long Cryptography_HAS_NEXTPROTONEG = 1; /* ALPN was added in OpenSSL 1.0.2. */ #if OPENSSL_VERSION_NUMBER < 0x10002001L int (*SSL_CTX_set_alpn_protos)(SSL_CTX *, - const unsigned char*, + const unsigned char *, unsigned) = NULL; -int (*SSL_set_alpn_protos)(SSL *, const unsigned char*, unsigned) = NULL; +int (*SSL_set_alpn_protos)(SSL *, const unsigned char *, unsigned) = NULL; void (*SSL_CTX_set_alpn_select_cb)(SSL_CTX *, int (*) (SSL *, const unsigned char **, @@ -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/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) diff --git a/src/cryptography/hazmat/primitives/serialization.py b/src/cryptography/hazmat/primitives/serialization.py index b9cf5967..0dbbc85c 100644 --- a/src/cryptography/hazmat/primitives/serialization.py +++ b/src/cryptography/hazmat/primitives/serialization.py @@ -4,9 +4,13 @@ from __future__ import absolute_import, division, print_function +import base64 +import struct import warnings from cryptography import utils +from cryptography.exceptions import UnsupportedAlgorithm +from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers def load_pem_traditional_openssl_private_key(data, password, backend): @@ -39,3 +43,76 @@ def load_pem_private_key(data, password, backend): def load_pem_public_key(data, backend): return backend.load_pem_public_key(data) + + +def load_ssh_public_key(data, backend): + key_parts = data.split(b' ') + + if len(key_parts) != 2 and len(key_parts) != 3: + raise ValueError( + 'Key is not in the proper format or contains extra data.') + + key_type = key_parts[0] + key_body = key_parts[1] + + if not key_type.startswith(b'ssh-'): + raise ValueError('SSH-formatted keys must begin with \'ssh-\'.') + + if not key_type.startswith(b'ssh-rsa'): + raise UnsupportedAlgorithm('Only RSA keys are currently supported.') + + return _load_ssh_rsa_public_key(key_body, backend) + + +def _load_ssh_rsa_public_key(key_body, backend): + data = base64.b64decode(key_body) + + key_type, rest = _read_next_string(data) + e, rest = _read_next_mpint(rest) + n, rest = _read_next_mpint(rest) + + if key_type != b'ssh-rsa': + raise ValueError( + 'Key header and key body contain different key type values.') + + if rest: + raise ValueError('Key body contains extra bytes.') + + return backend.load_rsa_public_numbers(RSAPublicNumbers(e, n)) + + +def _read_next_string(data): + """Retrieves the next RFC 4251 string value from the data.""" + str_len, = struct.unpack('>I', data[:4]) + return data[4:4 + str_len], data[4 + str_len:] + + +def _read_next_mpint(data): + """ + Reads the next mpint from the data. + + Currently, all mpints are interpreted as unsigned. + """ + mpint_data, rest = _read_next_string(data) + + return _int_from_bytes(mpint_data, byteorder='big', signed=False), rest + + +if hasattr(int, "from_bytes"): + _int_from_bytes = int.from_bytes +else: + def _int_from_bytes(data, byteorder, signed=False): + assert byteorder == 'big' + assert not signed + + if len(data) % 4 != 0: + data = (b'\x00' * (4 - (len(data) % 4))) + data + + result = 0 + + while len(data) > 0: + digit, = struct.unpack('>I', data[:4]) + result = (result << 32) + digit + data = data[4:] + + return result diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index 63464dfa..78f73464 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -48,8 +48,9 @@ def verify_interface(iface, klass): ) -def bit_length(x): - if sys.version_info >= (2, 7): +if sys.version_info >= (2, 7): + def bit_length(x): return x.bit_length() - else: +else: + def bit_length(x): return len(bin(x)) - (2 + (x <= 0)) |