aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cryptography/exceptions.py1
-rw-r--r--src/cryptography/hazmat/backends/multibackend.py25
-rw-r--r--src/cryptography/hazmat/bindings/openssl/asn1.py4
-rw-r--r--src/cryptography/hazmat/bindings/openssl/ssl.py12
-rw-r--r--src/cryptography/hazmat/bindings/openssl/x509.py34
-rw-r--r--src/cryptography/hazmat/bindings/openssl/x509_vfy.py2
-rw-r--r--src/cryptography/hazmat/bindings/openssl/x509name.py2
-rw-r--r--src/cryptography/hazmat/bindings/openssl/x509v3.py21
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/dsa.py32
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/ec.py26
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/rsa.py26
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/utils.py46
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)