aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.rst2
-rw-r--r--docs/development/test-vectors.rst4
-rw-r--r--docs/faq.rst19
-rw-r--r--docs/x509/reference.rst38
-rw-r--r--src/_cffi_src/openssl/engine.py4
-rw-r--r--src/_cffi_src/openssl/err.py8
-rw-r--r--src/_cffi_src/openssl/evp.py30
-rw-r--r--src/_cffi_src/openssl/hmac.py31
-rw-r--r--src/_cffi_src/openssl/ssl.py25
-rw-r--r--src/_cffi_src/openssl/x509.py2
-rw-r--r--src/_cffi_src/openssl/x509_vfy.py6
-rw-r--r--src/cryptography/hazmat/backends/multibackend.py7
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py9
-rw-r--r--src/cryptography/hazmat/backends/openssl/decode_asn1.py15
-rw-r--r--src/cryptography/hazmat/backends/openssl/hashes.py13
-rw-r--r--src/cryptography/hazmat/backends/openssl/hmac.py13
-rw-r--r--src/cryptography/hazmat/bindings/openssl/_conditional.py10
-rw-r--r--src/cryptography/x509/extensions.py8
-rw-r--r--tests/hazmat/backends/test_multibackend.py20
-rw-r--r--tests/hazmat/backends/test_openssl.py21
-rw-r--r--tests/test_x509_ext.py22
-rw-r--r--vectors/cryptography_vectors/x509/e-trust.ru.derbin0 -> 1309 bytes
22 files changed, 255 insertions, 52 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 0bbbcde1..1c11f028 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -14,6 +14,8 @@ Changelog
to :class:`~cryptography.x509.CertificateSigningRequest`.
* Fixed an intermittent ``AssertionError`` when performing an RSA decryption on
an invalid ciphertext, ``ValueError`` is now correctly raised in all cases.
+* Added
+ :meth:`~cryptography.x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier`.
1.2.3 - 2016-03-01
~~~~~~~~~~~~~~~~~~
diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst
index e4618927..73ddb976 100644
--- a/docs/development/test-vectors.rst
+++ b/docs/development/test-vectors.rst
@@ -113,6 +113,9 @@ X.509
* ``department-of-state-root.pem`` - The intermediary CA for the Department of
State, issued by the United States Federal Government's Common Policy CA.
Notably has a ``critical`` policy constraints extensions.
+* ``e-trust.ru.der`` - A certificate from a `Russian CA`_ signed using the GOST
+ cipher and containing numerous unusual encodings such as NUMERICSTRING in
+ the subject DN.
Custom X.509 Vectors
~~~~~~~~~~~~~~~~~~~~
@@ -450,3 +453,4 @@ header format (substituting the correct information):
.. _`root data`: https://hg.mozilla.org/projects/nss/file/25b2922cc564/security/nss/lib/ckfw/builtins/certdata.txt#l2053
.. _`asymmetric/public/PKCS1/dsa.pub.pem`: https://github.com/ruby/ruby/blob/4ccb387f3bc436a08fc6d72c4931994f5de95110/test/openssl/test_pkey_dsa.rb#L53
.. _`Mozilla bug`: https://bugzilla.mozilla.org/show_bug.cgi?id=233586
+.. _`Russian CA`: http://e-trust.gosuslugi.ru/MainCA
diff --git a/docs/faq.rst b/docs/faq.rst
index 363a350f..3456ba97 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -23,5 +23,24 @@ OpenSSL. You're seeing this error because your copy of pip is too old to find
our wheel files. Upgrade your copy of pip with ``pip install -U pip`` and then
try install ``cryptography`` again.
+Starting ``cryptography`` using ``mod_wsgi`` produces an ``InternalError`` during a call in ``_register_osrandom_engine``
+-------------------------------------------------------------------------------------------------------------------------
+
+This happens because ``mod_wsgi`` uses sub-interpreters, which can cause a
+problem during initialization of the OpenSSL backend. To resolve this set the
+`WSGIApplicationGroup`_ to ``%{GLOBAL}`` in the ``mod_wsgi`` configuration.
+
+``cryptography`` raised an ``InternalError`` and I'm not sure what to do?
+-------------------------------------------------------------------------
+
+Frequently ``InternalError`` is raised when there are errors on the OpenSSL
+error stack that were placed there by other libraries that are also using
+OpenSSL. Try removing the other libraries and see if the problem persists.
+If you have no other libraries using OpenSSL in your process, or they do not
+appear to be at fault, it's possible that this is a bug in ``cryptography``.
+Please file an `issue`_ with instructions on how to reproduce it.
+
.. _`NaCl`: https://nacl.cr.yp.to/
.. _`PyNaCl`: https://pynacl.readthedocs.org
+.. _`WSGIApplicationGroup`: https://modwsgi.readthedocs.org/en/develop/configuration-directives/WSGIApplicationGroup.html
+.. _`issue`: https://github.com/pyca/cryptography/issues
diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst
index 67427ddb..399d693a 100644
--- a/docs/x509/reference.rst
+++ b/docs/x509/reference.rst
@@ -1541,6 +1541,13 @@ X.509 Extensions
.. versionadded:: 1.0
+ .. note::
+
+ This method should be used if the issuer certificate does not
+ contain a :class:`~cryptography.x509.SubjectKeyIdentifier`.
+ Otherwise, use
+ :meth:`~cryptography.x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier`.
+
Creates a new AuthorityKeyIdentifier instance using the public key
provided to generate the appropriate digest. This should be the
**issuer's public key**. The resulting object will contain
@@ -1568,6 +1575,37 @@ X.509 Extensions
>>> x509.AuthorityKeyIdentifier.from_issuer_public_key(issuer_cert.public_key())
<AuthorityKeyIdentifier(key_identifier='X\x01\x84$\x1b\xbc+R\x94J=\xa5\x10r\x14Q\xf5\xaf:\xc9', authority_cert_issuer=None, authority_cert_serial_number=None)>
+ .. classmethod:: from_issuer_subject_key_identifier(ski)
+
+ .. versionadded:: 1.3
+
+ .. note::
+ This method should be used if the issuer certificate contains a
+ :class:`~cryptography.x509.SubjectKeyIdentifier`. Otherwise, use
+ :meth:`~cryptography.x509.AuthorityKeyIdentifier.from_issuer_public_key`.
+
+ Creates a new AuthorityKeyIdentifier instance using the
+ SubjectKeyIdentifier from the issuer certificate. The resulting object
+ will contain
+ :attr:`~cryptography.x509.AuthorityKeyIdentifier.key_identifier`, but
+ :attr:`~cryptography.x509.AuthorityKeyIdentifier.authority_cert_issuer`
+ and
+ :attr:`~cryptography.x509.AuthorityKeyIdentifier.authority_cert_serial_number`
+ will be None.
+
+ :param ski: The
+ :class:`~cryptography.x509.SubjectKeyIdentifier` from the issuer
+ certificate.
+
+ .. doctest::
+
+ >>> from cryptography import x509
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> issuer_cert = x509.load_pem_x509_certificate(pem_data, default_backend())
+ >>> ski = issuer_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier)
+ >>> x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(ski)
+ <AuthorityKeyIdentifier(key_identifier='X\x01\x84$\x1b\xbc+R\x94J=\xa5\x10r\x14Q\xf5\xaf:\xc9', authority_cert_issuer=None, authority_cert_serial_number=None)>
+
.. class:: SubjectKeyIdentifier(digest)
.. versionadded:: 0.9
diff --git a/src/_cffi_src/openssl/engine.py b/src/_cffi_src/openssl/engine.py
index 77c97fe5..afdd54e4 100644
--- a/src/_cffi_src/openssl/engine.py
+++ b/src/_cffi_src/openssl/engine.py
@@ -16,12 +16,10 @@ typedef ... RSA_METHOD;
typedef ... DSA_METHOD;
typedef ... DH_METHOD;
typedef struct {
- void (*seed)(const void *, int);
int (*bytes)(unsigned char *, int);
- void (*cleanup)();
- void (*add)(const void *, int, double);
int (*pseudorand)(unsigned char *, int);
int (*status)();
+ ...;
} RAND_METHOD;
typedef int (*ENGINE_GEN_INT_FUNC_PTR)(ENGINE *);
typedef ... *ENGINE_CTRL_FUNC_PTR;
diff --git a/src/_cffi_src/openssl/err.py b/src/_cffi_src/openssl/err.py
index f6e9632d..e31b1808 100644
--- a/src/_cffi_src/openssl/err.py
+++ b/src/_cffi_src/openssl/err.py
@@ -88,7 +88,6 @@ static const int ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM;
static const int ASN1_R_UNKNOWN_OBJECT_TYPE;
static const int ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE;
static const int ASN1_R_UNKNOWN_TAG;
-static const int ASN1_R_UNKOWN_FORMAT;
static const int ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE;
static const int ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM;
static const int ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE;
@@ -121,11 +120,6 @@ static const int EVP_F_EVP_PKEY2PKCS8_BROKEN;
static const int EVP_F_EVP_PKEY_COPY_PARAMETERS;
static const int EVP_F_EVP_PKEY_DECRYPT;
static const int EVP_F_EVP_PKEY_ENCRYPT;
-static const int EVP_F_EVP_PKEY_GET1_DH;
-static const int EVP_F_EVP_PKEY_GET1_DSA;
-static const int EVP_F_EVP_PKEY_GET1_ECDSA;
-static const int EVP_F_EVP_PKEY_GET1_EC_KEY;
-static const int EVP_F_EVP_PKEY_GET1_RSA;
static const int EVP_F_EVP_PKEY_NEW;
static const int EVP_F_EVP_RIJNDAEL;
static const int EVP_F_EVP_SIGNFINAL;
@@ -195,8 +189,6 @@ static const int PEM_F_PEM_READ;
static const int PEM_F_PEM_READ_BIO;
static const int PEM_F_PEM_READ_BIO_PRIVATEKEY;
static const int PEM_F_PEM_READ_PRIVATEKEY;
-static const int PEM_F_PEM_SEALFINAL;
-static const int PEM_F_PEM_SEALINIT;
static const int PEM_F_PEM_SIGNFINAL;
static const int PEM_F_PEM_WRITE;
static const int PEM_F_PEM_WRITE_BIO;
diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py
index d3ec568a..5abc6451 100644
--- a/src/_cffi_src/openssl/evp.py
+++ b/src/_cffi_src/openssl/evp.py
@@ -12,9 +12,7 @@ TYPES = """
typedef ... EVP_CIPHER;
typedef ... EVP_CIPHER_CTX;
typedef ... EVP_MD;
-typedef struct env_md_ctx_st {
- ...;
-} EVP_MD_CTX;
+typedef struct { ...; } EVP_MD_CTX;
typedef ... EVP_PKEY;
typedef ... EVP_PKEY_CTX;
@@ -51,18 +49,15 @@ int EVP_CipherUpdate(EVP_CIPHER_CTX *, unsigned char *, int *,
const unsigned char *, int);
int EVP_CipherFinal_ex(EVP_CIPHER_CTX *, unsigned char *, int *);
int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *);
-void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *);
EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *);
int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *, int);
-EVP_MD_CTX *EVP_MD_CTX_create(void);
int EVP_MD_CTX_copy_ex(EVP_MD_CTX *, const EVP_MD_CTX *);
int EVP_DigestInit_ex(EVP_MD_CTX *, const EVP_MD *, ENGINE *);
int EVP_DigestUpdate(EVP_MD_CTX *, const void *, size_t);
int EVP_DigestFinal_ex(EVP_MD_CTX *, unsigned char *, unsigned int *);
int EVP_MD_CTX_cleanup(EVP_MD_CTX *);
-void EVP_MD_CTX_destroy(EVP_MD_CTX *);
const EVP_MD *EVP_get_digestbyname(const char *);
EVP_PKEY *EVP_PKEY_new(void);
@@ -116,9 +111,18 @@ int EVP_PKEY_cmp(const EVP_PKEY *, const EVP_PKEY *);
EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *);
int Cryptography_EVP_PKEY_id(const EVP_PKEY *);
+
+/* in 1.1.0 _create and _destroy were renamed to _new and _free. The following
+ two functions wrap both the old and new functions so we can call them
+ without worrying about what OpenSSL we're running against. */
+EVP_MD_CTX *Cryptography_EVP_MD_CTX_new(void);
+void Cryptography_EVP_MD_CTX_free(EVP_MD_CTX *);
"""
MACROS = """
+/* became a macro in 1.1.0 */
+void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *);
+
void OpenSSL_add_all_algorithms(void);
int EVP_PKEY_assign_RSA(EVP_PKEY *, RSA *);
int EVP_PKEY_assign_DSA(EVP_PKEY *, DSA *);
@@ -233,4 +237,18 @@ int Cryptography_EVP_PKEY_id(const EVP_PKEY *key) {
return key->type;
#endif
}
+EVP_MD_CTX *Cryptography_EVP_MD_CTX_new(void) {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ return EVP_MD_CTX_create();
+#else
+ return EVP_MD_CTX_new();
+#endif
+}
+void Cryptography_EVP_MD_CTX_free(EVP_MD_CTX *ctx) {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ EVP_MD_CTX_destroy(ctx);
+#else
+ EVP_MD_CTX_free(ctx);
+#endif
+}
"""
diff --git a/src/_cffi_src/openssl/hmac.py b/src/_cffi_src/openssl/hmac.py
index 7178e573..bcc8a861 100644
--- a/src/_cffi_src/openssl/hmac.py
+++ b/src/_cffi_src/openssl/hmac.py
@@ -9,18 +9,17 @@ INCLUDES = """
"""
TYPES = """
-typedef struct { ...; } HMAC_CTX;
+typedef ... HMAC_CTX;
"""
FUNCTIONS = """
-void HMAC_CTX_init(HMAC_CTX *);
-void HMAC_CTX_cleanup(HMAC_CTX *);
-
int Cryptography_HMAC_Init_ex(HMAC_CTX *, const void *, int, const EVP_MD *,
ENGINE *);
int Cryptography_HMAC_Update(HMAC_CTX *, const unsigned char *, size_t);
int Cryptography_HMAC_Final(HMAC_CTX *, unsigned char *, unsigned int *);
int Cryptography_HMAC_CTX_copy(HMAC_CTX *, HMAC_CTX *);
+HMAC_CTX *Cryptography_HMAC_CTX_new(void);
+void Cryptography_HMAC_CTX_free(HMAC_CTX *ctx);
"""
MACROS = """
@@ -80,4 +79,28 @@ int Cryptography_HMAC_CTX_copy(HMAC_CTX *dst_ctx, HMAC_CTX *src_ctx) {
return 0;
#endif
}
+
+HMAC_CTX *Cryptography_HMAC_CTX_new(void) {
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+ return HMAC_CTX_new();
+#else
+ /* This uses OPENSSL_zalloc in 1.1.0, which is malloc + memset */
+ HMAC_CTX *ctx = (HMAC_CTX *)OPENSSL_malloc(sizeof(HMAC_CTX));
+ memset(ctx, 0, sizeof(HMAC_CTX));
+ return ctx;
+#endif
+}
+
+
+
+void Cryptography_HMAC_CTX_free(HMAC_CTX *ctx) {
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+ return HMAC_CTX_free(ctx);
+#else
+ if (ctx != NULL) {
+ HMAC_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+ }
+#endif
+}
"""
diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py
index e97a1d7d..2fc86a31 100644
--- a/src/_cffi_src/openssl/ssl.py
+++ b/src/_cffi_src/openssl/ssl.py
@@ -11,9 +11,8 @@ typedef STACK_OF(SSL_CIPHER) Cryptography_STACK_OF_SSL_CIPHER;
"""
TYPES = """
-/*
- * Internally invented symbols to tell which versions of SSL/TLS are supported.
-*/
+static const long Cryptography_HAS_SSL_ST;
+static const long Cryptography_HAS_TLS_ST;
static const long Cryptography_HAS_SSL2;
static const long Cryptography_HAS_SSL3_METHOD;
static const long Cryptography_HAS_TLSv1_1;
@@ -126,6 +125,8 @@ static const long SSL_MODE_ENABLE_PARTIAL_WRITE;
static const long SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
static const long SSL_MODE_AUTO_RETRY;
static const long SSL3_RANDOM_SIZE;
+static const long TLS_ST_BEFORE;
+static const long TLS_ST_OK;
typedef ... SSL_METHOD;
typedef ... SSL_CTX;
@@ -657,4 +658,22 @@ static const long Cryptography_HAS_SSL_CTX_SET_CLIENT_CERT_ENGINE = 0;
static const long Cryptography_HAS_SSL_CTX_SET_CLIENT_CERT_ENGINE = 1;
#endif
+/* in OpenSSL 1.1.0 the SSL_ST values were renamed to TLS_ST and several were
+ removed */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+static const long Cryptography_HAS_SSL_ST = 1;
+#else
+static const long Cryptography_HAS_SSL_ST = 0;
+static const long SSL_ST_BEFORE = 0;
+static const long SSL_ST_OK = 0;
+static const long SSL_ST_INIT = 0;
+static const long SSL_ST_RENEGOTIATE = 0;
+#endif
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+static const long Cryptography_HAS_TLS_ST = 1;
+#else
+static const long Cryptography_HAS_TLS_ST = 0;
+static const long TLS_ST_BEFORE = 0;
+static const long TLS_ST_OK = 0;
+#endif
"""
diff --git a/src/_cffi_src/openssl/x509.py b/src/_cffi_src/openssl/x509.py
index 4484a8ac..2fe3a1bf 100644
--- a/src/_cffi_src/openssl/x509.py
+++ b/src/_cffi_src/openssl/x509.py
@@ -36,6 +36,8 @@ typedef struct {
...;
} X509_CINF;
+/* TODO: opaque X509_EXTENSION. Cryptography no longer depends on it being
+ non-opaque but pyOpenSSL needs a release where it doesn't depend on this */
typedef struct {
ASN1_OBJECT *object;
ASN1_BOOLEAN critical;
diff --git a/src/_cffi_src/openssl/x509_vfy.py b/src/_cffi_src/openssl/x509_vfy.py
index f8467a76..13287797 100644
--- a/src/_cffi_src/openssl/x509_vfy.py
+++ b/src/_cffi_src/openssl/x509_vfy.py
@@ -173,8 +173,6 @@ int X509_STORE_CTX_get_error(X509_STORE_CTX *);
void X509_STORE_CTX_set_error(X509_STORE_CTX *, int);
int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *);
X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *);
-int X509_STORE_CTX_get_ex_new_index(long, void *, CRYPTO_EX_new *,
- CRYPTO_EX_dup *, CRYPTO_EX_free *);
int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *, int, void *);
void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *, int);
@@ -194,6 +192,10 @@ int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *);
"""
MACROS = """
+/* this CRYPTO_EX_DATA function became a macro in 1.1.0 */
+int X509_STORE_CTX_get_ex_new_index(long, void *, CRYPTO_EX_new *,
+ CRYPTO_EX_dup *, CRYPTO_EX_free *);
+
/* X509_STORE_CTX */
void X509_STORE_CTX_set0_crls(X509_STORE_CTX *,
Cryptography_STACK_OF_X509_CRL *);
diff --git a/src/cryptography/hazmat/backends/multibackend.py b/src/cryptography/hazmat/backends/multibackend.py
index 65f18531..48bc7d08 100644
--- a/src/cryptography/hazmat/backends/multibackend.py
+++ b/src/cryptography/hazmat/backends/multibackend.py
@@ -28,6 +28,13 @@ class MultiBackend(object):
name = "multibackend"
def __init__(self, backends):
+ if len(backends) == 0:
+ raise ValueError(
+ "Multibackend cannot be initialized with no backends. If you "
+ "are seeing this error when trying to use default_backend() "
+ "please try uninstalling and reinstalling cryptography."
+ )
+
self._backends = backends
def _filtered_backends(self, interface):
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index e47f747c..064f9ad6 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -1003,11 +1003,14 @@ class Backend(object):
x509_revoked, serial_number
)
self.openssl_assert(res == 1)
- res = self._lib.ASN1_TIME_set(
- x509_revoked.revocationDate,
+ rev_date = self._lib.ASN1_TIME_set(
+ self._ffi.NULL,
calendar.timegm(builder._revocation_date.timetuple())
)
- self.openssl_assert(res != self._ffi.NULL)
+ self.openssl_assert(rev_date != self._ffi.NULL)
+ rev_date = self._ffi.gc(rev_date, self._lib.ASN1_TIME_free)
+ res = self._lib.X509_REVOKED_set_revocationDate(x509_revoked, rev_date)
+ self.openssl_assert(res == 1)
# add CRL entry extensions
self._create_x509_extensions(
extensions=builder._extensions,
diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py
index 5f828c6b..26f56d12 100644
--- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py
+++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py
@@ -198,7 +198,9 @@ class _X509ExtensionParser(object):
backend.openssl_assert(ext != backend._ffi.NULL)
crit = backend._lib.X509_EXTENSION_get_critical(ext)
critical = crit == 1
- oid = x509.ObjectIdentifier(_obj2txt(backend, ext.object))
+ oid = x509.ObjectIdentifier(
+ _obj2txt(backend, backend._lib.X509_EXTENSION_get_object(ext))
+ )
if oid in seen_oids:
raise x509.DuplicateExtension(
"Duplicate {0} extension found".format(oid), oid
@@ -652,9 +654,10 @@ def _decode_cert_issuer(backend, ext):
"""
data_ptr_ptr = backend._ffi.new("const unsigned char **")
- data_ptr_ptr[0] = ext.value.data
+ value = backend._lib.X509_EXTENSION_get_data(ext)
+ data_ptr_ptr[0] = value.data
gns = backend._lib.d2i_GENERAL_NAMES(
- backend._ffi.NULL, data_ptr_ptr, ext.value.length
+ backend._ffi.NULL, data_ptr_ptr, value.length
)
# Check the result of d2i_GENERAL_NAMES() is valid. Usually this is covered
@@ -706,7 +709,11 @@ def _asn1_string_to_ascii(backend, asn1_string):
def _asn1_string_to_utf8(backend, asn1_string):
buf = backend._ffi.new("unsigned char **")
res = backend._lib.ASN1_STRING_to_UTF8(buf, asn1_string)
- backend.openssl_assert(res >= 0)
+ if res == -1:
+ raise ValueError(
+ "Unsupported ASN1 string type. Type: {0}".format(asn1_string.type)
+ )
+
backend.openssl_assert(buf[0] != backend._ffi.NULL)
buf = backend._ffi.gc(
buf, lambda buffer: backend._lib.OPENSSL_free(buffer[0])
diff --git a/src/cryptography/hazmat/backends/openssl/hashes.py b/src/cryptography/hazmat/backends/openssl/hashes.py
index 02ce5f0d..2c8fce1a 100644
--- a/src/cryptography/hazmat/backends/openssl/hashes.py
+++ b/src/cryptography/hazmat/backends/openssl/hashes.py
@@ -18,9 +18,10 @@ class _HashContext(object):
self._backend = backend
if ctx is None:
- ctx = self._backend._lib.EVP_MD_CTX_create()
- ctx = self._backend._ffi.gc(ctx,
- self._backend._lib.EVP_MD_CTX_destroy)
+ ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new()
+ ctx = self._backend._ffi.gc(
+ ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free
+ )
evp_md = self._backend._lib.EVP_get_digestbyname(
algorithm.name.encode("ascii"))
if evp_md == self._backend._ffi.NULL:
@@ -38,9 +39,9 @@ class _HashContext(object):
algorithm = utils.read_only_property("_algorithm")
def copy(self):
- copied_ctx = self._backend._lib.EVP_MD_CTX_create()
+ copied_ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new()
copied_ctx = self._backend._ffi.gc(
- copied_ctx, self._backend._lib.EVP_MD_CTX_destroy
+ copied_ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free
)
res = self._backend._lib.EVP_MD_CTX_copy_ex(copied_ctx, self._ctx)
self._backend.openssl_assert(res != 0)
@@ -57,6 +58,4 @@ class _HashContext(object):
res = self._backend._lib.EVP_DigestFinal_ex(self._ctx, buf, outlen)
self._backend.openssl_assert(res != 0)
self._backend.openssl_assert(outlen[0] == self.algorithm.digest_size)
- res = self._backend._lib.EVP_MD_CTX_cleanup(self._ctx)
- self._backend.openssl_assert(res == 1)
return self._backend._ffi.buffer(buf)[:outlen[0]]
diff --git a/src/cryptography/hazmat/backends/openssl/hmac.py b/src/cryptography/hazmat/backends/openssl/hmac.py
index dcf2fbaf..ab1ad46f 100644
--- a/src/cryptography/hazmat/backends/openssl/hmac.py
+++ b/src/cryptography/hazmat/backends/openssl/hmac.py
@@ -20,10 +20,10 @@ class _HMACContext(object):
self._backend = backend
if ctx is None:
- ctx = self._backend._ffi.new("HMAC_CTX *")
- self._backend._lib.HMAC_CTX_init(ctx)
+ ctx = self._backend._lib.Cryptography_HMAC_CTX_new()
+ self._backend.openssl_assert(ctx != self._backend._ffi.NULL)
ctx = self._backend._ffi.gc(
- ctx, self._backend._lib.HMAC_CTX_cleanup
+ ctx, self._backend._lib.Cryptography_HMAC_CTX_free
)
evp_md = self._backend._lib.EVP_get_digestbyname(
algorithm.name.encode('ascii'))
@@ -44,10 +44,10 @@ class _HMACContext(object):
algorithm = utils.read_only_property("_algorithm")
def copy(self):
- copied_ctx = self._backend._ffi.new("HMAC_CTX *")
- self._backend._lib.HMAC_CTX_init(copied_ctx)
+ copied_ctx = self._backend._lib.Cryptography_HMAC_CTX_new()
+ self._backend.openssl_assert(copied_ctx != self._backend._ffi.NULL)
copied_ctx = self._backend._ffi.gc(
- copied_ctx, self._backend._lib.HMAC_CTX_cleanup
+ copied_ctx, self._backend._lib.Cryptography_HMAC_CTX_free
)
res = self._backend._lib.Cryptography_HMAC_CTX_copy(
copied_ctx, self._ctx
@@ -72,7 +72,6 @@ class _HMACContext(object):
)
self._backend.openssl_assert(res != 0)
self._backend.openssl_assert(outlen[0] == self.algorithm.digest_size)
- self._backend._lib.HMAC_CTX_cleanup(self._ctx)
return self._backend._ffi.buffer(buf)[:outlen[0]]
def verify(self, signature):
diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py
index f5999312..8b918995 100644
--- a/src/cryptography/hazmat/bindings/openssl/_conditional.py
+++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py
@@ -404,4 +404,14 @@ CONDITIONAL_NAMES = {
"Cryptography_HAS_AES_CTR128_ENCRYPT": [
"AES_ctr128_encrypt",
],
+ "Cryptography_HAS_SSL_ST": [
+ "SSL_ST_BEFORE",
+ "SSL_ST_OK",
+ "SSL_ST_INIT",
+ "SSL_ST_RENEGOTIATE",
+ ],
+ "Cryptography_HAS_TLS_ST": [
+ "TLS_ST_BEFORE",
+ "TLS_ST_OK",
+ ],
}
diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py
index 0aa67212..87d2de1c 100644
--- a/src/cryptography/x509/extensions.py
+++ b/src/cryptography/x509/extensions.py
@@ -191,6 +191,14 @@ class AuthorityKeyIdentifier(object):
authority_cert_serial_number=None
)
+ @classmethod
+ def from_issuer_subject_key_identifier(cls, ski):
+ return cls(
+ key_identifier=ski.value.digest,
+ authority_cert_issuer=None,
+ authority_cert_serial_number=None
+ )
+
def __repr__(self):
return (
"<AuthorityKeyIdentifier(key_identifier={0.key_identifier!r}, "
diff --git a/tests/hazmat/backends/test_multibackend.py b/tests/hazmat/backends/test_multibackend.py
index 74835716..bf54d5ce 100644
--- a/tests/hazmat/backends/test_multibackend.py
+++ b/tests/hazmat/backends/test_multibackend.py
@@ -4,6 +4,8 @@
from __future__ import absolute_import, division, print_function
+import pytest
+
from cryptography import utils
from cryptography.exceptions import (
UnsupportedAlgorithm, _Reasons
@@ -21,6 +23,10 @@ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from ...utils import raises_unsupported_algorithm
+class DummyBackend(object):
+ pass
+
+
@utils.register_interface(CipherBackend)
class DummyCipherBackend(object):
def __init__(self, supported_ciphers):
@@ -226,6 +232,10 @@ class DummyX509Backend(object):
class TestMultiBackend(object):
+ def test_raises_error_with_empty_list(self):
+ with pytest.raises(ValueError):
+ MultiBackend([])
+
def test_ciphers(self):
backend = MultiBackend([
DummyHashBackend([]),
@@ -310,7 +320,7 @@ class TestMultiBackend(object):
backend.load_rsa_public_numbers("public_numbers")
- backend = MultiBackend([])
+ backend = MultiBackend([DummyBackend()])
with raises_unsupported_algorithm(
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
):
@@ -353,7 +363,7 @@ class TestMultiBackend(object):
backend.load_dsa_public_numbers("numbers")
backend.load_dsa_parameter_numbers("numbers")
- backend = MultiBackend([])
+ backend = MultiBackend([DummyBackend()])
with raises_unsupported_algorithm(
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
):
@@ -491,7 +501,7 @@ class TestMultiBackend(object):
backend.load_pem_private_key(b"keydata", None)
backend.load_pem_public_key(b"keydata")
- backend = MultiBackend([])
+ backend = MultiBackend([DummyBackend()])
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION):
backend.load_pem_private_key(b"keydata", None)
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION):
@@ -503,7 +513,7 @@ class TestMultiBackend(object):
backend.load_der_private_key(b"keydata", None)
backend.load_der_public_key(b"keydata")
- backend = MultiBackend([])
+ backend = MultiBackend([DummyBackend()])
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION):
backend.load_der_private_key(b"keydata", None)
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION):
@@ -523,7 +533,7 @@ class TestMultiBackend(object):
backend.create_x509_crl(object(), b"privatekey", hashes.SHA1())
backend.create_x509_revoked_certificate(object())
- backend = MultiBackend([])
+ backend = MultiBackend([DummyBackend()])
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_X509):
backend.load_pem_x509_certificate(b"certdata")
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_X509):
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index 072f8be3..52bee7b3 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -31,6 +31,7 @@ from ..primitives.test_ec import _skip_curve_unsupported
from ...doubles import (
DummyAsymmetricPadding, DummyCipherAlgorithm, DummyHashAlgorithm, DummyMode
)
+from ...test_x509 import _load_cert
from ...utils import load_vectors_from_file, raises_unsupported_algorithm
@@ -656,3 +657,23 @@ class TestRSAPEMSerialization(object):
serialization.PrivateFormat.PKCS8,
serialization.BestAvailableEncryption(password)
)
+
+
+class TestGOSTCertificate(object):
+ @pytest.mark.skipif(
+ backend._lib.OPENSSL_VERSION_NUMBER < 0x1000000f,
+ reason="Requires a newer OpenSSL. Must be >= 1.0.0"
+ )
+ def test_numeric_string_x509_name_entry(self):
+ cert = _load_cert(
+ os.path.join("x509", "e-trust.ru.der"),
+ x509.load_der_x509_certificate,
+ backend
+ )
+ with pytest.raises(ValueError) as exc:
+ cert.subject
+
+ # We assert on the message in this case because if the certificate
+ # fails to load it will also raise a ValueError and this test could
+ # erroneously pass.
+ assert str(exc.value) == "Unsupported ASN1 string type. Type: 18"
diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py
index d85b4bbc..28ddab87 100644
--- a/tests/test_x509_ext.py
+++ b/tests/test_x509_ext.py
@@ -2634,6 +2634,28 @@ class TestAuthorityKeyIdentifierExtension(object):
)
assert ext.value == aki
+ def test_from_issuer_subject_key_identifier(self, backend):
+ issuer_cert = _load_cert(
+ os.path.join("x509", "rapidssl_sha256_ca_g3.pem"),
+ x509.load_pem_x509_certificate,
+ backend
+ )
+ cert = _load_cert(
+ os.path.join("x509", "cryptography.io.pem"),
+ x509.load_pem_x509_certificate,
+ backend
+ )
+ ext = cert.extensions.get_extension_for_oid(
+ ExtensionOID.AUTHORITY_KEY_IDENTIFIER
+ )
+ ski = issuer_cert.extensions.get_extension_for_class(
+ x509.SubjectKeyIdentifier
+ )
+ aki = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
+ ski
+ )
+ assert ext.value == aki
+
class TestNameConstraints(object):
def test_ipaddress_wrong_type(self):
diff --git a/vectors/cryptography_vectors/x509/e-trust.ru.der b/vectors/cryptography_vectors/x509/e-trust.ru.der
new file mode 100644
index 00000000..72b581fe
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/e-trust.ru.der
Binary files differ