aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.rst8
-rw-r--r--docs/development/test-vectors.rst4
-rw-r--r--docs/faq.rst28
-rw-r--r--docs/x509/reference.rst38
-rw-r--r--docs/x509/tutorial.rst68
-rw-r--r--src/_cffi_src/build_openssl.py17
-rw-r--r--src/_cffi_src/openssl/aes.py11
-rw-r--r--src/_cffi_src/openssl/asn1.py10
-rw-r--r--src/_cffi_src/openssl/bio.py3
-rw-r--r--src/_cffi_src/openssl/conf.py24
-rw-r--r--src/_cffi_src/openssl/crypto.py41
-rw-r--r--src/_cffi_src/openssl/dh.py1
-rw-r--r--src/_cffi_src/openssl/ec.py22
-rw-r--r--src/_cffi_src/openssl/ecdh.py14
-rw-r--r--src/_cffi_src/openssl/ecdsa.py21
-rw-r--r--src/_cffi_src/openssl/engine.py35
-rw-r--r--src/_cffi_src/openssl/err.py10
-rw-r--r--src/_cffi_src/openssl/evp.py37
-rw-r--r--src/_cffi_src/openssl/hmac.py31
-rw-r--r--src/_cffi_src/openssl/rand.py3
-rw-r--r--src/_cffi_src/openssl/ssl.py134
-rw-r--r--src/_cffi_src/openssl/x509.py94
-rw-r--r--src/_cffi_src/openssl/x509_vfy.py6
-rw-r--r--src/_cffi_src/openssl/x509name.py12
-rw-r--r--src/_cffi_src/openssl/x509v3.py1
-rw-r--r--src/cryptography/hazmat/backends/multibackend.py7
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py81
-rw-r--r--src/cryptography/hazmat/backends/openssl/decode_asn1.py15
-rw-r--r--src/cryptography/hazmat/backends/openssl/encode_asn1.py139
-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/backends/openssl/x509.py61
-rw-r--r--src/cryptography/hazmat/bindings/openssl/_conditional.py25
-rw-r--r--src/cryptography/hazmat/bindings/openssl/binding.py27
-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/hazmat/bindings/test_openssl.py28
-rw-r--r--tests/test_x509.py81
-rw-r--r--tests/test_x509_ext.py22
-rw-r--r--vectors/cryptography_vectors/x509/e-trust.ru.derbin0 -> 1309 bytes
41 files changed, 888 insertions, 346 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 0bbbcde1..aad8d934 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -8,12 +8,16 @@ Changelog
* Deprecated support for OpenSSL 0.9.8. Support will be removed in
``cryptography`` 1.4.
-* Added support for the :class:`~cryptography.x509.PolicyConstraints` X.509
- extension.
+* Added support for the :class:`~cryptography.x509.PolicyConstraints`
+ X.509 extension including both parsing and generation using
+ :class:`~cryptography.x509.CertificateBuilder` and
+ :class:`~cryptography.x509.CertificateSigningRequestBuilder`.
* Added :attr:`~cryptography.x509.CertificateSigningRequest.is_signature_valid`
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 e09f0a0c..cc44492f 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
~~~~~~~~~~~~~~~~~~~~
@@ -452,3 +455,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 10c8656b..3456ba97 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -14,5 +14,33 @@ to NaCl.
If you prefer NaCl's design, we highly recommend `PyNaCl`_.
+Compiling ``cryptography`` on OS X produces a ``fatal error: 'openssl/aes.h' file not found`` error
+---------------------------------------------------------------------------------------------------
+
+This happens because OS X 10.11 no longer includes a copy of OpenSSL.
+``cryptography`` now provides wheels which include a statically linked copy of
+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/docs/x509/tutorial.rst b/docs/x509/tutorial.rst
index 7252e43a..6941372f 100644
--- a/docs/x509/tutorial.rst
+++ b/docs/x509/tutorial.rst
@@ -82,3 +82,71 @@ a few details:
... f.write(csr.public_bytes(serialization.Encoding.PEM))
Now we can give our CSR to a CA, who will give a certificate to us in return.
+
+Creating a self-signed certificate
+----------------------------------
+
+While most of the time you want a certificate that has been *signed* by someone
+else (i.e. a certificate authority), so that trust is established, sometimes
+you want to create a self-signed certificate. Self-signed certificates are not
+issued by a certificate authority, but instead they are signed by the private
+key corresponding to the public key they embed.
+
+This means that other people don't trust these certificates, but it also means
+they can be issued very easily. In general the only use case for a self-signed
+certificate is local testing, where you don't need anyone else to trust your
+certificate.
+
+Like generating a CSR, we start with creating a new private key:
+
+.. code-block:: pycon
+
+ >>> # Generate our key
+ >>> key = rsa.generate_private_key(
+ ... public_exponent=65537,
+ ... key_size=2048,
+ ... backend=default_backend()
+ ... )
+ >>> # Write our key to disk for safe keeping
+ >>> with open("path/to/store/key.pem", "wb") as f:
+ ... f.write(key.private_bytes(
+ ... encoding=serialization.Encoding.PEM,
+ ... format=serialization.PrivateFormat.TraditionalOpenSSL,
+ ... encryption_algorithm=serialization.BestAvailableEncryption(b"passphrase"),
+ ... ))
+
+Then we generate the certificate itself:
+
+.. code-block:: pycon
+
+ >>> # Various details about who we are. For a self-signed certificate the
+ >>> # subject and issuer are always the same.
+ >>> subject = issuer = x509.Name([
+ ... x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+ ... x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"CA"),
+ ... x509.NameAttribute(NameOID.LOCALITY_NAME, u"San Francisco"),
+ ... x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"My Company"),
+ ... x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
+ ... ])
+ >>> cert = x509.CertificateBuilder().subject_name(
+ ... subject
+ ... ).issuer_name(
+ ... issuer
+ ... ).public_key(
+ ... private_key.public_key()
+ ... ).not_valid_before(
+ ... datetime.datetime.utcnow()
+ ... ).not_valid_after(
+ ... # Our certificate will be valid for 10 days
+ ... datetime.datetime.utcnow() + datetime.timedelta(days=10)
+ ... ).add_extension(
+ ... x509.SubjectAlternativeName([x509.DNSName(u"localhost")]),
+ ... critical=False,
+ ... # Sign our certificate with our private key
+ ... ).sign(private_key, hashes.SHA256(), default_backend())
+ >>> # Write our certificate out to disk.
+ >>> with open("path/to/certificate.pem", "wb") as f:
+ ... f.write(cert.public_bytes(serialization.Encoding.PEM))
+
+And now we have a private key and certificate that can be used for local
+testing.
diff --git a/src/_cffi_src/build_openssl.py b/src/_cffi_src/build_openssl.py
index ba6e17b3..2ff28d75 100644
--- a/src/_cffi_src/build_openssl.py
+++ b/src/_cffi_src/build_openssl.py
@@ -42,21 +42,6 @@ _PRE_INCLUDE = """
#if defined(OPENSSL_SYS_WINDOWS)
#include <windows.h>
#endif
-#ifdef __APPLE__
-#include <AvailabilityMacros.h>
-#define __ORIG_DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER \
- DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#endif
-"""
-
-_POST_INCLUDE = """
-#ifdef __APPLE__
-#undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER \
- __ORIG_DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#endif
"""
@@ -70,7 +55,6 @@ ffi = build_ffi_for_binding(
"bio",
"cmac",
"cms",
- "conf",
"crypto",
"dh",
"dsa",
@@ -98,7 +82,6 @@ ffi = build_ffi_for_binding(
"callbacks",
],
pre_include=_PRE_INCLUDE,
- post_include=_POST_INCLUDE,
libraries=_get_openssl_libraries(sys.platform),
extra_link_args=extra_link_args(compiler_type()),
)
diff --git a/src/_cffi_src/openssl/aes.py b/src/_cffi_src/openssl/aes.py
index 8a5d0471..438431b5 100644
--- a/src/_cffi_src/openssl/aes.py
+++ b/src/_cffi_src/openssl/aes.py
@@ -10,6 +10,7 @@ INCLUDES = """
TYPES = """
static const int Cryptography_HAS_AES_WRAP;
+static const int Cryptography_HAS_AES_CTR128_ENCRYPT;
struct aes_key_st {
...;
@@ -50,5 +51,13 @@ int (*AES_wrap_key)(AES_KEY *, const unsigned char *, unsigned char *,
int (*AES_unwrap_key)(AES_KEY *, const unsigned char *, unsigned char *,
const unsigned char *, unsigned int) = NULL;
#endif
-
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+static const int Cryptography_HAS_AES_CTR128_ENCRYPT = 0;
+void (*AES_ctr128_encrypt)(const unsigned char *, unsigned char *,
+ const size_t, const AES_KEY *,
+ unsigned char[], unsigned char[],
+ unsigned int *) = NULL;
+#else
+static const int Cryptography_HAS_AES_CTR128_ENCRYPT = 1;
+#endif
"""
diff --git a/src/_cffi_src/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py
index 30bd2451..084eec2c 100644
--- a/src/_cffi_src/openssl/asn1.py
+++ b/src/_cffi_src/openssl/asn1.py
@@ -24,6 +24,7 @@ struct asn1_string_st {
typedef struct asn1_string_st ASN1_OCTET_STRING;
typedef struct asn1_string_st ASN1_IA5STRING;
typedef struct asn1_string_st ASN1_BIT_STRING;
+typedef struct asn1_string_st ASN1_TIME;
typedef ... ASN1_OBJECT;
typedef struct asn1_string_st ASN1_STRING;
typedef struct asn1_string_st ASN1_UTF8STRING;
@@ -33,9 +34,6 @@ typedef ... ASN1_ENUMERATED;
typedef ... ASN1_ITEM;
typedef ... ASN1_VALUE;
-typedef struct {
- ...;
-} ASN1_TIME;
typedef ... ASN1_ITEM_EXP;
typedef ... ASN1_UTCTIME;
@@ -155,4 +153,10 @@ ASN1_TYPE *d2i_ASN1_TYPE(ASN1_TYPE **, const unsigned char **, long);
"""
CUSTOMIZATIONS = """
+/* This macro is removed in 1.1.0. We re-add it if required to support
+ pyOpenSSL versions older than whatever resolves
+ https://github.com/pyca/pyopenssl/issues/431 */
+#if !defined(M_ASN1_TIME_dup)
+#define M_ASN1_TIME_dup(a) (ASN1_TIME *)ASN1_STRING_dup((const ASN1_STRING *)a)
+#endif
"""
diff --git a/src/_cffi_src/openssl/bio.py b/src/_cffi_src/openssl/bio.py
index 6439e63a..df9b1b48 100644
--- a/src/_cffi_src/openssl/bio.py
+++ b/src/_cffi_src/openssl/bio.py
@@ -68,8 +68,6 @@ static const int BIO_CTRL_WPENDING;
static const int BIO_C_FILE_SEEK;
static const int BIO_C_FILE_TELL;
static const int BIO_TYPE_NONE;
-static const int BIO_TYPE_PROXY_CLIENT;
-static const int BIO_TYPE_PROXY_SERVER;
static const int BIO_TYPE_NBIO_TEST;
static const int BIO_TYPE_BER;
static const int BIO_TYPE_BIO;
@@ -113,7 +111,6 @@ long BIO_callback_ctrl(
int,
void (*)(struct bio_st *, int, const char *, int, long, long)
);
-char *BIO_ptr_ctrl(BIO *, int, long);
long BIO_int_ctrl(BIO *, int, long, int);
size_t BIO_ctrl_pending(BIO *);
size_t BIO_ctrl_wpending(BIO *);
diff --git a/src/_cffi_src/openssl/conf.py b/src/_cffi_src/openssl/conf.py
deleted file mode 100644
index c89ae5ca..00000000
--- a/src/_cffi_src/openssl/conf.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# 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
-
-INCLUDES = """
-#include <openssl/conf.h>
-"""
-
-TYPES = """
-typedef ... CONF;
-"""
-
-FUNCTIONS = """
-void OPENSSL_config(const char *);
-void OPENSSL_no_config(void);
-"""
-
-MACROS = """
-"""
-
-CUSTOMIZATIONS = """
-"""
diff --git a/src/_cffi_src/openssl/crypto.py b/src/_cffi_src/openssl/crypto.py
index 3c045410..9357815b 100644
--- a/src/_cffi_src/openssl/crypto.py
+++ b/src/_cffi_src/openssl/crypto.py
@@ -16,6 +16,11 @@ static const int SSLEAY_CFLAGS;
static const int SSLEAY_PLATFORM;
static const int SSLEAY_DIR;
static const int SSLEAY_BUILT_ON;
+static const int OPENSSL_VERSION;
+static const int OPENSSL_CFLAGS;
+static const int OPENSSL_BUILT_ON;
+static const int OPENSSL_PLATFORM;
+static const int OPENSSL_DIR;
static const int CRYPTO_MEM_CHECK_ON;
static const int CRYPTO_MEM_CHECK_OFF;
static const int CRYPTO_MEM_CHECK_ENABLE;
@@ -28,9 +33,6 @@ static const int CRYPTO_LOCK_SSL;
"""
FUNCTIONS = """
-unsigned long SSLeay(void);
-const char *SSLeay_version(int);
-
void CRYPTO_free(void *);
int CRYPTO_mem_ctrl(int);
int CRYPTO_is_mem_check_on(void);
@@ -38,8 +40,6 @@ void CRYPTO_mem_leaks(struct bio_st *);
void CRYPTO_cleanup_all_ex_data(void);
int CRYPTO_num_locks(void);
void CRYPTO_set_locking_callback(void(*)(int, int, const char *, int));
-void CRYPTO_set_id_callback(unsigned long (*)(void));
-unsigned long (*CRYPTO_get_id_callback(void))(void);
void (*CRYPTO_get_locking_callback(void))(int, int, const char *, int);
void CRYPTO_lock(int, int, const char *, int);
@@ -47,9 +47,38 @@ void OPENSSL_free(void *);
"""
MACROS = """
+/* SSLeay was removed in 1.1.0 */
+unsigned long SSLeay(void);
+const char *SSLeay_version(int);
+/* these functions were added to replace the SSLeay functions in 1.1.0 */
+unsigned long OpenSSL_version_num(void);
+const char *OpenSSL_version(int);
+
void CRYPTO_add(int *, int, int);
-void CRYPTO_malloc_init(void);
"""
CUSTOMIZATIONS = """
+/* In 1.1.0 SSLeay has finally been retired. We bidirectionally define the
+ values so you can use either one. This is so we can use the new function
+ names no matter what OpenSSL we're running on, but users on older pyOpenSSL
+ releases won't see issues if they're running OpenSSL 1.1.0 */
+#if !defined(SSLEAY_VERSION)
+# define SSLeay OpenSSL_version_num
+# define SSLeay_version OpenSSL_version
+# define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER
+# define SSLEAY_VERSION OPENSSL_VERSION
+# define SSLEAY_CFLAGS OPENSSL_CFLAGS
+# define SSLEAY_BUILT_ON OPENSSL_BUILT_ON
+# define SSLEAY_PLATFORM OPENSSL_PLATFORM
+# define SSLEAY_DIR OPENSSL_DIR
+#endif
+#if !defined(OPENSSL_VERSION)
+# define OpenSSL_version_num SSLeay
+# define OpenSSL_version SSLeay_version
+# define OPENSSL_VERSION SSLEAY_VERSION
+# define OPENSSL_CFLAGS SSLEAY_CFLAGS
+# define OPENSSL_BUILT_ON SSLEAY_BUILT_ON
+# define OPENSSL_PLATFORM SSLEAY_PLATFORM
+# define OPENSSL_DIR SSLEAY_DIR
+#endif
"""
diff --git a/src/_cffi_src/openssl/dh.py b/src/_cffi_src/openssl/dh.py
index 8df66f8b..8055d0c8 100644
--- a/src/_cffi_src/openssl/dh.py
+++ b/src/_cffi_src/openssl/dh.py
@@ -29,7 +29,6 @@ FUNCTIONS = """
DH *DH_new(void);
void DH_free(DH *);
int DH_size(const DH *);
-DH *DH_generate_parameters(int, int, void (*)(int, int, void *), void *);
int DH_check(const DH *, int *);
int DH_check_pub_key(const DH *, const BIGNUM *, int *);
int DH_generate_key(DH *);
diff --git a/src/_cffi_src/openssl/ec.py b/src/_cffi_src/openssl/ec.py
index f5cbf968..91603096 100644
--- a/src/_cffi_src/openssl/ec.py
+++ b/src/_cffi_src/openssl/ec.py
@@ -76,8 +76,8 @@ int EC_KEY_get_flags(const EC_KEY *);
void EC_KEY_set_flags(EC_KEY *, int);
void EC_KEY_clear_flags(EC_KEY *, int);
EC_KEY *EC_KEY_new_by_curve_name(int);
-EC_KEY *EC_KEY_copy(EC_KEY *, const EC_KEY *);
-EC_KEY *EC_KEY_dup(const EC_KEY *);
+EC_KEY *EC_KEY_copy(EC_KEY *, EC_KEY *);
+EC_KEY *EC_KEY_dup(EC_KEY *);
int EC_KEY_up_ref(EC_KEY *);
const EC_GROUP *EC_KEY_get0_group(const EC_KEY *);
int EC_GROUP_get_order(const EC_GROUP *, BIGNUM *, BN_CTX *);
@@ -90,19 +90,6 @@ unsigned int EC_KEY_get_enc_flags(const EC_KEY *);
void EC_KEY_set_enc_flags(EC_KEY *eckey, unsigned int);
point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *);
void EC_KEY_set_conv_form(EC_KEY *, point_conversion_form_t);
-void *EC_KEY_get_key_method_data(
- EC_KEY *,
- void *(*)(void *),
- void (*)(void *),
- void (*)(void *)
-);
-void EC_KEY_insert_key_method_data(
- EC_KEY *,
- void *,
- void *(*)(void *),
- void (*)(void *),
- void (*)(void *)
-);
void EC_KEY_set_asn1_flag(EC_KEY *, int);
int EC_KEY_precompute_mult(EC_KEY *, BN_CTX *);
int EC_KEY_generate_key(EC_KEY *);
@@ -237,11 +224,6 @@ unsigned int (*EC_KEY_get_enc_flags)(const EC_KEY *) = NULL;
void (*EC_KEY_set_enc_flags)(EC_KEY *eckey, unsigned int) = NULL;
point_conversion_form_t (*EC_KEY_get_conv_form)(const EC_KEY *) = NULL;
void (*EC_KEY_set_conv_form)(EC_KEY *, point_conversion_form_t) = NULL;
-void *(*EC_KEY_get_key_method_data)(
- EC_KEY *, void *(*)(void *), void (*)(void *), void (*)(void *)) = NULL;
-void (*EC_KEY_insert_key_method_data)(
- EC_KEY *, void *,
- void *(*)(void *), void (*)(void *), void (*)(void *)) = NULL;
void (*EC_KEY_set_asn1_flag)(EC_KEY *, int) = NULL;
int (*EC_KEY_precompute_mult)(EC_KEY *, BN_CTX *) = NULL;
int (*EC_KEY_generate_key)(EC_KEY *) = NULL;
diff --git a/src/_cffi_src/openssl/ecdh.py b/src/_cffi_src/openssl/ecdh.py
index 3116c3b6..099f53cb 100644
--- a/src/_cffi_src/openssl/ecdh.py
+++ b/src/_cffi_src/openssl/ecdh.py
@@ -20,13 +20,6 @@ FUNCTIONS = """
MACROS = """
int ECDH_compute_key(void *, size_t, const EC_POINT *, EC_KEY *,
void *(*)(const void *, size_t, void *, size_t *));
-
-int ECDH_get_ex_new_index(long, void *, CRYPTO_EX_new *, CRYPTO_EX_dup *,
- CRYPTO_EX_free *);
-
-int ECDH_set_ex_data(EC_KEY *, int, void *);
-
-void *ECDH_get_ex_data(EC_KEY *, int);
"""
CUSTOMIZATIONS = """
@@ -37,13 +30,6 @@ int (*ECDH_compute_key)(void *, size_t, const EC_POINT *, EC_KEY *,
void *(*)(const void *, size_t, void *,
size_t *)) = NULL;
-int (*ECDH_get_ex_new_index)(long, void *, CRYPTO_EX_new *, CRYPTO_EX_dup *,
- CRYPTO_EX_free *) = NULL;
-
-int (*ECDH_set_ex_data)(EC_KEY *, int, void *) = NULL;
-
-void *(*ECDH_get_ex_data)(EC_KEY *, int) = NULL;
-
#else
static const long Cryptography_HAS_ECDH = 1;
#endif
diff --git a/src/_cffi_src/openssl/ecdsa.py b/src/_cffi_src/openssl/ecdsa.py
index f231864b..f3e9fba0 100644
--- a/src/_cffi_src/openssl/ecdsa.py
+++ b/src/_cffi_src/openssl/ecdsa.py
@@ -13,10 +13,7 @@ INCLUDES = """
TYPES = """
static const int Cryptography_HAS_ECDSA;
-typedef struct {
- BIGNUM *r;
- BIGNUM *s;
-} ECDSA_SIG;
+typedef ... ECDSA_SIG;
typedef ... CRYPTO_EX_new;
typedef ... CRYPTO_EX_dup;
@@ -44,14 +41,6 @@ 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();
-void ECDSA_set_default_method(const ECDSA_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 *);
-int ECDSA_set_ex_data(EC_KEY *, int, void *);
-void *ECDSA_get_ex_data(EC_KEY *, int);
"""
CUSTOMIZATIONS = """
@@ -83,14 +72,6 @@ int (*ECDSA_verify)(int, const unsigned char *, int, const unsigned char *,
int, EC_KEY *) = NULL;
int (*ECDSA_size)(const EC_KEY *) = NULL;
-const ECDSA_METHOD* (*ECDSA_OpenSSL)() = NULL;
-void (*ECDSA_set_default_method)(const ECDSA_METHOD *) = NULL;
-const ECDSA_METHOD* (*ECDSA_get_default_method)() = NULL;
-int (*ECDSA_set_method)(EC_KEY *, const ECDSA_METHOD *) = NULL;
-int (*ECDSA_get_ex_new_index)(long, void *, CRYPTO_EX_new *,
- CRYPTO_EX_dup *, CRYPTO_EX_free *) = NULL;
-int (*ECDSA_set_ex_data)(EC_KEY *, int, void *) = NULL;
-void* (*ECDSA_get_ex_data)(EC_KEY *, int) = NULL;
#else
static const long Cryptography_HAS_ECDSA = 1;
#endif
diff --git a/src/_cffi_src/openssl/engine.py b/src/_cffi_src/openssl/engine.py
index 60c6f3e2..afdd54e4 100644
--- a/src/_cffi_src/openssl/engine.py
+++ b/src/_cffi_src/openssl/engine.py
@@ -14,18 +14,13 @@ static const long Cryptography_HAS_ENGINE_CRYPTODEV;
typedef ... ENGINE;
typedef ... RSA_METHOD;
typedef ... DSA_METHOD;
-typedef ... ECDH_METHOD;
-typedef ... ECDSA_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 ... STORE_METHOD;
typedef int (*ENGINE_GEN_INT_FUNC_PTR)(ENGINE *);
typedef ... *ENGINE_CTRL_FUNC_PTR;
typedef ... *ENGINE_LOAD_KEY_PTR;
@@ -37,11 +32,8 @@ typedef ... UI_METHOD;
static const unsigned int ENGINE_METHOD_RSA;
static const unsigned int ENGINE_METHOD_DSA;
static const unsigned int ENGINE_METHOD_RAND;
-static const unsigned int ENGINE_METHOD_ECDH;
-static const unsigned int ENGINE_METHOD_ECDSA;
static const unsigned int ENGINE_METHOD_CIPHERS;
static const unsigned int ENGINE_METHOD_DIGESTS;
-static const unsigned int ENGINE_METHOD_STORE;
static const unsigned int ENGINE_METHOD_ALL;
static const unsigned int ENGINE_METHOD_NONE;
@@ -58,22 +50,16 @@ int ENGINE_remove(ENGINE *);
ENGINE *ENGINE_by_id(const char *);
int ENGINE_init(ENGINE *);
int ENGINE_finish(ENGINE *);
-void ENGINE_load_openssl(void);
-void ENGINE_load_dynamic(void);
void ENGINE_load_builtin_engines(void);
void ENGINE_cleanup(void);
ENGINE *ENGINE_get_default_RSA(void);
ENGINE *ENGINE_get_default_DSA(void);
-ENGINE *ENGINE_get_default_ECDH(void);
-ENGINE *ENGINE_get_default_ECDSA(void);
ENGINE *ENGINE_get_default_DH(void);
ENGINE *ENGINE_get_default_RAND(void);
ENGINE *ENGINE_get_cipher_engine(int);
ENGINE *ENGINE_get_digest_engine(int);
int ENGINE_set_default_RSA(ENGINE *);
int ENGINE_set_default_DSA(ENGINE *);
-int ENGINE_set_default_ECDH(ENGINE *);
-int ENGINE_set_default_ECDSA(ENGINE *);
int ENGINE_set_default_DH(ENGINE *);
int ENGINE_set_default_RAND(ENGINE *);
int ENGINE_set_default_ciphers(ENGINE *);
@@ -88,21 +74,12 @@ void ENGINE_register_all_RSA(void);
int ENGINE_register_DSA(ENGINE *);
void ENGINE_unregister_DSA(ENGINE *);
void ENGINE_register_all_DSA(void);
-int ENGINE_register_ECDH(ENGINE *);
-void ENGINE_unregister_ECDH(ENGINE *);
-void ENGINE_register_all_ECDH(void);
-int ENGINE_register_ECDSA(ENGINE *);
-void ENGINE_unregister_ECDSA(ENGINE *);
-void ENGINE_register_all_ECDSA(void);
int ENGINE_register_DH(ENGINE *);
void ENGINE_unregister_DH(ENGINE *);
void ENGINE_register_all_DH(void);
int ENGINE_register_RAND(ENGINE *);
void ENGINE_unregister_RAND(ENGINE *);
void ENGINE_register_all_RAND(void);
-int ENGINE_register_STORE(ENGINE *);
-void ENGINE_unregister_STORE(ENGINE *);
-void ENGINE_register_all_STORE(void);
int ENGINE_register_ciphers(ENGINE *);
void ENGINE_unregister_ciphers(ENGINE *);
void ENGINE_register_all_ciphers(void);
@@ -123,11 +100,8 @@ int ENGINE_set_id(ENGINE *, const char *);
int ENGINE_set_name(ENGINE *, const char *);
int ENGINE_set_RSA(ENGINE *, const RSA_METHOD *);
int ENGINE_set_DSA(ENGINE *, const DSA_METHOD *);
-int ENGINE_set_ECDH(ENGINE *, const ECDH_METHOD *);
-int ENGINE_set_ECDSA(ENGINE *, const ECDSA_METHOD *);
int ENGINE_set_DH(ENGINE *, const DH_METHOD *);
int ENGINE_set_RAND(ENGINE *, const RAND_METHOD *);
-int ENGINE_set_STORE(ENGINE *, const STORE_METHOD *);
int ENGINE_set_destroy_function(ENGINE *, ENGINE_GEN_INT_FUNC_PTR);
int ENGINE_set_init_function(ENGINE *, ENGINE_GEN_INT_FUNC_PTR);
int ENGINE_set_finish_function(ENGINE *, ENGINE_GEN_INT_FUNC_PTR);
@@ -142,11 +116,8 @@ const char *ENGINE_get_id(const ENGINE *);
const char *ENGINE_get_name(const ENGINE *);
const RSA_METHOD *ENGINE_get_RSA(const ENGINE *);
const DSA_METHOD *ENGINE_get_DSA(const ENGINE *);
-const ECDH_METHOD *ENGINE_get_ECDH(const ENGINE *);
-const ECDSA_METHOD *ENGINE_get_ECDSA(const ENGINE *);
const DH_METHOD *ENGINE_get_DH(const ENGINE *);
const RAND_METHOD *ENGINE_get_RAND(const ENGINE *);
-const STORE_METHOD *ENGINE_get_STORE(const ENGINE *);
const EVP_CIPHER *ENGINE_get_cipher(ENGINE *, int);
const EVP_MD *ENGINE_get_digest(ENGINE *, int);
@@ -158,6 +129,10 @@ void ENGINE_add_conf_module(void);
"""
MACROS = """
+/* these became macros in 1.1.0 */
+void ENGINE_load_openssl(void);
+void ENGINE_load_dynamic(void);
+
void ENGINE_load_cryptodev(void);
"""
diff --git a/src/_cffi_src/openssl/err.py b/src/_cffi_src/openssl/err.py
index 4ba90662..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;
@@ -236,8 +228,6 @@ static const int RSA_F_RSA_SIGN;
"""
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 *);
void ERR_error_string_n(unsigned long, char *, size_t);
diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py
index 1d37b814..5abc6451 100644
--- a/src/_cffi_src/openssl/evp.py
+++ b/src/_cffi_src/openssl/evp.py
@@ -10,16 +10,9 @@ INCLUDES = """
TYPES = """
typedef ... EVP_CIPHER;
-typedef struct {
- const EVP_CIPHER *cipher;
- ENGINE *engine;
- int encrypt;
- ...;
-} EVP_CIPHER_CTX;
+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;
@@ -56,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);
@@ -121,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 *);
@@ -238,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/rand.py b/src/_cffi_src/openssl/rand.py
index 91e1a396..0a94d705 100644
--- a/src/_cffi_src/openssl/rand.py
+++ b/src/_cffi_src/openssl/rand.py
@@ -22,7 +22,6 @@ int RAND_load_file(const char *, long);
int RAND_write_file(const char *);
void RAND_cleanup(void);
int RAND_bytes(unsigned char *, int);
-int RAND_pseudo_bytes(unsigned char *, int);
"""
MACROS = """
@@ -32,7 +31,7 @@ int RAND_query_egd_bytes(const char *, unsigned char *, int);
"""
CUSTOMIZATIONS = """
-#if defined(LIBRESSL_VERSION_NUMBER)
+#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER >= 0x10100000L
static const long Cryptography_HAS_EGD = 0;
int (*RAND_egd)(const char *) = NULL;
int (*RAND_egd_bytes)(const char *, int) = NULL;
diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py
index 98b396da..75b0f130 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;
@@ -162,9 +163,6 @@ typedef ... COMP_METHOD;
"""
FUNCTIONS = """
-void SSL_load_error_strings(void);
-int SSL_library_init(void);
-
/* SSL */
const char *SSL_state_string_long(const SSL *);
SSL_SESSION *SSL_get1_session(SSL *);
@@ -253,20 +251,25 @@ char *SSL_CIPHER_get_version(const SSL_CIPHER *);
size_t SSL_get_finished(const SSL *, void *, size_t);
size_t SSL_get_peer_finished(const SSL *, void *, size_t);
+Cryptography_STACK_OF_X509_NAME *SSL_load_client_CA_file(const char *);
+"""
-/* CRYPTO_EX_DATA */
+MACROS = """
+/* These became macros in 1.1.0 */
+int SSL_library_init(void);
+void SSL_load_error_strings(void);
+
+/* these CRYPTO_EX_DATA functions became macros in 1.1.0 */
int SSL_get_ex_new_index(long, void *, CRYPTO_EX_new *, CRYPTO_EX_dup *,
CRYPTO_EX_free *);
int SSL_set_ex_data(SSL *, int, void *);
-
int SSL_CTX_get_ex_new_index(long, void *, CRYPTO_EX_new *, CRYPTO_EX_dup *,
CRYPTO_EX_free *);
int SSL_CTX_set_ex_data(SSL_CTX *, int, void *);
-Cryptography_STACK_OF_X509_NAME *SSL_load_client_CA_file(const char *);
-"""
+SSL_SESSION *SSL_get_session(const SSL *);
+const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *, unsigned int *);
-MACROS = """
/* not a macro, but older OpenSSLs don't pass the args as const */
char *SSL_CIPHER_description(const SSL_CIPHER *, char *, int);
int SSL_SESSION_print(BIO *, const SSL_SESSION *);
@@ -372,8 +375,6 @@ 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 *);
-
/* NPN APIs were introduced in OpenSSL 1.0.1. To continue to support earlier
* versions some special handling of these is necessary.
*/
@@ -398,7 +399,7 @@ void SSL_get0_next_proto_negotiated(const SSL *,
const unsigned char **, unsigned *);
int sk_SSL_CIPHER_num(Cryptography_STACK_OF_SSL_CIPHER *);
-SSL_CIPHER *sk_SSL_CIPHER_value(Cryptography_STACK_OF_SSL_CIPHER *, int);
+const 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.
@@ -422,9 +423,91 @@ long SSL_get_server_tmp_key(SSL *, EVP_PKEY **);
*/
void SSL_CTX_set_cert_cb(SSL_CTX *, int (*)(SSL *, void *), void *);
void SSL_set_cert_cb(SSL *, int (*)(SSL *, void *), void *);
+
+/* Added in 1.0.2 */
+const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *);
+/* Added in 1.0.1 */
+int SSL_SESSION_set1_id_context(SSL_SESSION *, const unsigned char *,
+ unsigned int);
+/* Added in 1.1.0 for the great opaquing of structs */
+size_t SSL_SESSION_get_master_key(const SSL_SESSION *, unsigned char *,
+ size_t);
+size_t SSL_get_client_random(const SSL *, unsigned char *, size_t);
+size_t SSL_get_server_random(const SSL *, unsigned char *, size_t);
"""
CUSTOMIZATIONS = """
+/* Added in 1.0.1 but we need it in all versions now due to the great
+ opaquing. */
+#if OPENSSL_VERSION_NUMBER < 0x1000100fL
+/* from ssl.h */
+#define SSL_F_SSL_SESSION_SET1_ID_CONTEXT 312
+#define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG 273
+/* from ssl/ssl_sess.c */
+int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx,
+ unsigned int sid_ctx_len)
+{
+ if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
+ SSLerr(SSL_F_SSL_SESSION_SET1_ID_CONTEXT,
+ SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
+ return 0;
+ }
+ s->sid_ctx_length = sid_ctx_len;
+ memcpy(s->sid_ctx, sid_ctx, sid_ctx_len);
+
+ return 1;
+}
+#endif
+/* Added in 1.0.2 but we need it in all versions now due to the great
+ opaquing. */
+#if OPENSSL_VERSION_NUMBER < 0x10002001L || defined(LIBRESSL_VERSION_NUMBER)
+/* from ssl/ssl_lib.c */
+const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *ctx) {
+ return ctx->method;
+}
+#endif
+/* Added in 1.1.0 in the great opaquing, but we need to define it for older
+ OpenSSLs. Such is our burden. */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+/* from ssl/ssl_lib.c */
+size_t SSL_get_client_random(const SSL *ssl, unsigned char *out, size_t outlen)
+{
+ if (outlen == 0)
+ return sizeof(ssl->s3->client_random);
+ if (outlen > sizeof(ssl->s3->client_random))
+ outlen = sizeof(ssl->s3->client_random);
+ memcpy(out, ssl->s3->client_random, outlen);
+ return outlen;
+}
+/* Added in 1.1.0 as well */
+/* from ssl/ssl_lib.c */
+size_t SSL_get_server_random(const SSL *ssl, unsigned char *out, size_t outlen)
+{
+ if (outlen == 0)
+ return sizeof(ssl->s3->server_random);
+ if (outlen > sizeof(ssl->s3->server_random))
+ outlen = sizeof(ssl->s3->server_random);
+ memcpy(out, ssl->s3->server_random, outlen);
+ return outlen;
+}
+/* Added in 1.1.0 as well */
+/* from ssl/ssl_lib.c */
+size_t SSL_SESSION_get_master_key(const SSL_SESSION *session,
+ unsigned char *out, size_t outlen)
+{
+ if (session->master_key_length < 0) {
+ /* Should never happen */
+ return 0;
+ }
+ if (outlen == 0)
+ return session->master_key_length;
+ if (outlen > (size_t)session->master_key_length)
+ outlen = session->master_key_length;
+ memcpy(out, session->master_key, outlen);
+ return outlen;
+}
+#endif
+
/** Secure renegotiation is supported in OpenSSL >= 0.9.8m
* But some Linux distributions have back ported some features.
*/
@@ -565,11 +648,6 @@ static const long Cryptography_HAS_NETBSD_D1_METH = 1;
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) {
- return ctx->method;
-}
-
/* Because OPENSSL defines macros that claim lack of support for things, rather
* than macros that claim support for things, we need to do a version check in
* addition to a definition check. NPN was added in 1.0.1: for any version
@@ -655,4 +733,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 c5eb600a..b0ff9844 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;
@@ -152,12 +154,6 @@ X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *);
X509_EXTENSION *X509_get_ext(X509 *, int);
int X509_get_ext_by_NID(X509 *, int, int);
-/* CRYPTO_EX_DATA */
-int X509_get_ex_new_index(long, void *, CRYPTO_EX_new *, CRYPTO_EX_dup *,
- CRYPTO_EX_free *);
-int X509_set_ex_data(X509 *, int, void *);
-void *X509_get_ex_data(X509 *, int);
-
int X509_EXTENSION_get_critical(X509_EXTENSION *);
ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *);
void X509_EXTENSION_free(X509_EXTENSION *);
@@ -270,12 +266,22 @@ void PKCS8_PRIV_KEY_INFO_free(PKCS8_PRIV_KEY_INFO *);
"""
MACROS = """
+/* these CRYPTO_EX_DATA functions became macros in 1.1.0 */
+int X509_get_ex_new_index(long, void *, CRYPTO_EX_new *, CRYPTO_EX_dup *,
+ CRYPTO_EX_free *);
+int X509_set_ex_data(X509 *, int, void *);
+void *X509_get_ex_data(X509 *, int);
+
X509_REVOKED *Cryptography_X509_REVOKED_dup(X509_REVOKED *);
int i2d_X509_CINF(X509_CINF *, unsigned char **);
int i2d_X509_CRL_INFO(X509_CRL_INFO *, unsigned char **);
int i2d_X509_REQ_INFO(X509_REQ_INFO *, unsigned char **);
+/* new in 1.0.2 */
+int i2d_re_X509_tbs(X509 *, unsigned char **);
+void X509_get0_signature(ASN1_BIT_STRING **, X509_ALGOR **, X509 *);
+
long X509_get_version(X509 *);
ASN1_TIME *X509_get_notBefore(X509 *);
@@ -347,9 +353,46 @@ ASN1_OBJECT *sk_ASN1_OBJECT_value(Cryptography_STACK_OF_ASN1_OBJECT *, int);
void sk_ASN1_OBJECT_free(Cryptography_STACK_OF_ASN1_OBJECT *);
Cryptography_STACK_OF_ASN1_OBJECT *sk_ASN1_OBJECT_new_null(void);
int sk_ASN1_OBJECT_push(Cryptography_STACK_OF_ASN1_OBJECT *, ASN1_OBJECT *);
+
+/* these functions were added in 1.1.0 */
+ASN1_INTEGER *X509_REVOKED_get0_serialNumber(X509_REVOKED *);
+ASN1_TIME *X509_REVOKED_get0_revocationDate(X509_REVOKED *);
+void X509_CRL_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg,
+ X509_CRL *crl);
+int i2d_re_X509_REQ_tbs(X509_REQ *, unsigned char **);
+int i2d_re_X509_CRL_tbs(X509_CRL *, unsigned char **);
+void X509_REQ_get0_signature(ASN1_BIT_STRING **, X509_ALGOR **, X509_REQ *);
"""
CUSTOMIZATIONS = """
+/* Added in 1.0.2 beta but we need it in all versions now due to the great
+ opaquing. */
+#if OPENSSL_VERSION_NUMBER < 0x10002001L || defined(LIBRESSL_VERSION_NUMBER)
+/* from x509/x_x509.c version 1.0.2 */
+void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg,
+ const X509 *x)
+{
+ if (psig)
+ *psig = x->signature;
+ if (palg)
+ *palg = x->sig_alg;
+}
+#endif
+/* Added in 1.0.2 but we need it in all versions now due to the great
+ opaquing. */
+#if OPENSSL_VERSION_NUMBER < 0x10002003L || defined(LIBRESSL_VERSION_NUMBER)
+/* from x509/x_x509.c */
+int i2d_re_X509_tbs(X509 *x, unsigned char **pp)
+{
+ /* in 1.0.2+ this function also sets x->cert_info->enc.modified = 1
+ but older OpenSSLs don't have the enc ASN1_ENCODING member in the
+ X509 struct. Setting modified to 1 marks the encoding
+ (x->cert_info->enc.enc) as invalid, but since the entire struct isn't
+ present we don't care. */
+ return i2d_X509_CINF(x->cert_info, pp);
+}
+#endif
+
/* OpenSSL 0.9.8e does not have this definition. */
#if OPENSSL_VERSION_NUMBER <= 0x0090805fL
typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS;
@@ -375,4 +418,43 @@ X509_REVOKED *Cryptography_X509_REVOKED_dup(X509_REVOKED *rev) {
return ASN1_item_dup(ASN1_ITEM_rptr(X509_REVOKED), rev);
}
+/* Added in 1.1.0 but we need it in all versions now due to the great
+ opaquing. */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+/* from x509/x509_req.c */
+void X509_REQ_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg,
+ X509_REQ *req)
+{
+ if (psig != NULL)
+ *psig = req->signature;
+ if (palg != NULL)
+ *palg = req->sig_alg;
+}
+int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp)
+{
+ req->req_info->enc.modified = 1;
+ return i2d_X509_REQ_INFO(req->req_info, pp);
+}
+int i2d_re_X509_CRL_tbs(X509_CRL *crl, unsigned char **pp) {
+ crl->crl->enc.modified = 1;
+ return i2d_X509_CRL_INFO(crl->crl, pp);
+}
+
+void X509_CRL_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg,
+ X509_CRL *crl)
+{
+ if (psig != NULL)
+ *psig = crl->signature;
+ if (palg != NULL)
+ *palg = crl->sig_alg;
+}
+ASN1_TIME *X509_REVOKED_get0_revocationDate(X509_REVOKED *x)
+{
+ return x->revocationDate;
+}
+ASN1_INTEGER *X509_REVOKED_get0_serialNumber(X509_REVOKED *x)
+{
+ return x->serialNumber;
+}
+#endif
"""
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/_cffi_src/openssl/x509name.py b/src/_cffi_src/openssl/x509name.py
index 7b833d61..86d50bbd 100644
--- a/src/_cffi_src/openssl/x509name.py
+++ b/src/_cffi_src/openssl/x509name.py
@@ -16,10 +16,7 @@ typedef STACK_OF(X509_NAME_ENTRY) Cryptography_STACK_OF_X509_NAME_ENTRY;
TYPES = """
typedef ... Cryptography_STACK_OF_X509_NAME_ENTRY;
-typedef struct {
- Cryptography_STACK_OF_X509_NAME_ENTRY *entries;
- ...;
-} X509_NAME;
+typedef ... X509_NAME;
typedef ... X509_NAME_ENTRY;
typedef ... Cryptography_STACK_OF_X509_NAME;
"""
@@ -47,6 +44,10 @@ int X509_NAME_get_index_by_NID(X509_NAME *, int, int);
int X509_NAME_cmp(const X509_NAME *, const X509_NAME *);
char *X509_NAME_oneline(X509_NAME *, char *, int);
X509_NAME *X509_NAME_dup(X509_NAME *);
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **,
+ ASN1_OBJECT *, int,
+ const unsigned char *, int);
+int X509_NAME_add_entry(X509_NAME *, X509_NAME_ENTRY *, int, int);
"""
MACROS = """
@@ -56,6 +57,9 @@ int sk_X509_NAME_push(Cryptography_STACK_OF_X509_NAME *, X509_NAME *);
X509_NAME *sk_X509_NAME_value(Cryptography_STACK_OF_X509_NAME *, int);
void sk_X509_NAME_free(Cryptography_STACK_OF_X509_NAME *);
int sk_X509_NAME_ENTRY_num(Cryptography_STACK_OF_X509_NAME_ENTRY *);
+Cryptography_STACK_OF_X509_NAME_ENTRY *sk_X509_NAME_ENTRY_new_null(void);
+int sk_X509_NAME_ENTRY_push(Cryptography_STACK_OF_X509_NAME_ENTRY *,
+ X509_NAME_ENTRY *);
X509_NAME_ENTRY *sk_X509_NAME_ENTRY_value(
Cryptography_STACK_OF_X509_NAME_ENTRY *, int);
Cryptography_STACK_OF_X509_NAME_ENTRY *sk_X509_NAME_ENTRY_dup(
diff --git a/src/_cffi_src/openssl/x509v3.py b/src/_cffi_src/openssl/x509v3.py
index 3612f1c2..d4a93f26 100644
--- a/src/_cffi_src/openssl/x509v3.py
+++ b/src/_cffi_src/openssl/x509v3.py
@@ -34,6 +34,7 @@ typedef ... Cryptography_STACK_OF_POLICYINFO;
typedef ... Cryptography_STACK_OF_ASN1_INTEGER;
typedef ... Cryptography_STACK_OF_GENERAL_SUBTREE;
typedef ... EXTENDED_KEY_USAGE;
+typedef ... CONF;
typedef struct {
X509 *issuer_cert;
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 4a8fda99..5ce2489c 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -31,8 +31,7 @@ from cryptography.hazmat.backends.openssl.ec import (
from cryptography.hazmat.backends.openssl.encode_asn1 import (
_CRL_ENTRY_EXTENSION_ENCODE_HANDLERS,
_CRL_EXTENSION_ENCODE_HANDLERS, _EXTENSION_ENCODE_HANDLERS,
- _encode_asn1_int_gc, _encode_asn1_str_gc, _encode_name_gc,
- _txt2obj_gc,
+ _encode_asn1_int_gc, _encode_asn1_str_gc, _encode_name_gc, _txt2obj_gc,
)
from cryptography.hazmat.backends.openssl.hashes import _HashContext
from cryptography.hazmat.backends.openssl.hmac import _HMACContext
@@ -179,7 +178,7 @@ class Backend(object):
Example: OpenSSL 1.0.1e 11 Feb 2013
"""
return self._ffi.string(
- self._lib.SSLeay_version(self._lib.SSLEAY_VERSION)
+ self._lib.OpenSSL_version(self._lib.OPENSSL_VERSION)
).decode("ascii")
def create_hmac_ctx(self, key, algorithm):
@@ -968,6 +967,31 @@ class Backend(object):
def _create_x509_extensions(self, extensions, handlers, x509_obj,
add_func, gc):
for i, extension in enumerate(extensions):
+ x509_extension = self._create_x509_extension(
+ handlers, extension
+ )
+ self.openssl_assert(x509_extension != self._ffi.NULL)
+
+ if gc:
+ x509_extension = self._ffi.gc(
+ x509_extension, self._lib.X509_EXTENSION_free
+ )
+ res = add_func(x509_obj, x509_extension, i)
+ self.openssl_assert(res >= 1)
+
+ def _create_x509_extension(self, handlers, extension):
+ if isinstance(extension.value, x509.UnrecognizedExtension):
+ obj = _txt2obj_gc(self, extension.oid.dotted_string)
+ value = _encode_asn1_str_gc(
+ self, extension.value.value, len(extension.value.value)
+ )
+ return self._lib.X509_EXTENSION_create_by_OBJ(
+ self._ffi.NULL,
+ obj,
+ 1 if extension.critical else 0,
+ value
+ )
+ else:
try:
encode = handlers[extension.oid]
except KeyError:
@@ -975,21 +999,37 @@ class Backend(object):
'Extension not supported: {0}'.format(extension.oid)
)
- pp, r = encode(self, extension.value)
- obj = _txt2obj_gc(self, extension.oid.dotted_string)
- x509_extension = self._lib.X509_EXTENSION_create_by_OBJ(
- self._ffi.NULL,
- obj,
- 1 if extension.critical else 0,
- _encode_asn1_str_gc(self, pp[0], r)
+ ext_struct = encode(self, extension.value)
+ nid = self._lib.OBJ_txt2nid(
+ extension.oid.dotted_string.encode("ascii")
)
- self.openssl_assert(x509_extension != self._ffi.NULL)
- if gc:
- x509_extension = self._ffi.gc(
- x509_extension, self._lib.X509_EXTENSION_free
+ backend.openssl_assert(nid != self._lib.NID_undef)
+ x509_extension = self._lib.X509V3_EXT_i2d(
+ nid, 1 if extension.critical else 0, ext_struct
+ )
+ if (
+ x509_extension == self._ffi.NULL and
+ extension.oid == x509.OID_CERTIFICATE_ISSUER
+ ):
+ # This path exists to support OpenSSL 0.9.8, which does not
+ # know how to encode a CERTIFICATE_ISSUER for CRLs. Once we
+ # drop 0.9.8 support we can remove this.
+ self._consume_errors()
+ pp = backend._ffi.new("unsigned char **")
+ r = self._lib.i2d_GENERAL_NAMES(ext_struct, pp)
+ backend.openssl_assert(r > 0)
+ pp = backend._ffi.gc(
+ pp,
+ lambda pointer: backend._lib.OPENSSL_free(pointer[0])
)
- res = add_func(x509_obj, x509_extension, i)
- self.openssl_assert(res >= 1)
+ obj = _txt2obj_gc(self, extension.oid.dotted_string)
+ return self._lib.X509_EXTENSION_create_by_OBJ(
+ self._ffi.NULL,
+ obj,
+ 1 if extension.critical else 0,
+ _encode_asn1_str_gc(self, pp[0], r)
+ )
+ return x509_extension
def create_x509_revoked_certificate(self, builder):
if not isinstance(builder, x509.RevokedCertificateBuilder):
@@ -1003,11 +1043,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/encode_asn1.py b/src/cryptography/hazmat/backends/openssl/encode_asn1.py
index 8cdf4c4b..b0e2e73e 100644
--- a/src/cryptography/hazmat/backends/openssl/encode_asn1.py
+++ b/src/cryptography/hazmat/backends/openssl/encode_asn1.py
@@ -74,21 +74,8 @@ def _encode_asn1_str_gc(backend, data, length):
return s
-def _encode_extension_to_der(backend, i2d_func, value):
- pp = backend._ffi.new("unsigned char **")
- r = i2d_func(value, pp)
- backend.openssl_assert(r > 0)
- pp = backend._ffi.gc(
- pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0])
- )
- return pp, r
-
-
def _encode_inhibit_any_policy(backend, inhibit_any_policy):
- asn1int = _encode_asn1_int_gc(backend, inhibit_any_policy.skip_certs)
- return _encode_extension_to_der(
- backend, backend._lib.i2d_ASN1_INTEGER, asn1int
- )
+ return _encode_asn1_int_gc(backend, inhibit_any_policy.skip_certs)
def _encode_name(backend, attributes):
@@ -97,17 +84,8 @@ def _encode_name(backend, attributes):
"""
subject = backend._lib.X509_NAME_new()
for attribute in attributes:
- value = attribute.value.encode('utf8')
- obj = _txt2obj_gc(backend, attribute.oid.dotted_string)
- if attribute.oid == NameOID.COUNTRY_NAME:
- # Per RFC5280 Appendix A.1 countryName should be encoded as
- # PrintableString, not UTF8String
- type = backend._lib.MBSTRING_ASC
- else:
- type = backend._lib.MBSTRING_UTF8
- res = backend._lib.X509_NAME_add_entry_by_OBJ(
- subject, obj, type, value, -1, -1, 0,
- )
+ name_entry = _encode_name_entry(backend, attribute)
+ res = backend._lib.X509_NAME_add_entry(subject, name_entry, -1, 0)
backend.openssl_assert(res == 1)
return subject
@@ -118,11 +96,35 @@ def _encode_name_gc(backend, attributes):
return subject
-def _encode_crl_number(backend, crl_number):
- asn1int = _encode_asn1_int_gc(backend, crl_number.crl_number)
- return _encode_extension_to_der(
- backend, backend._lib.i2d_ASN1_INTEGER, asn1int
+def _encode_sk_name_entry(backend, attributes):
+ """
+ The sk_X50_NAME_ENTRY created will not be gc'd.
+ """
+ stack = backend._lib.sk_X509_NAME_ENTRY_new_null()
+ for attribute in attributes:
+ name_entry = _encode_name_entry(backend, attribute)
+ res = backend._lib.sk_X509_NAME_ENTRY_push(stack, name_entry)
+ backend.openssl_assert(res == 1)
+ return stack
+
+
+def _encode_name_entry(backend, attribute):
+ value = attribute.value.encode('utf8')
+ obj = _txt2obj_gc(backend, attribute.oid.dotted_string)
+ if attribute.oid == NameOID.COUNTRY_NAME:
+ # Per RFC5280 Appendix A.1 countryName should be encoded as
+ # PrintableString, not UTF8String
+ type = backend._lib.MBSTRING_ASC
+ else:
+ type = backend._lib.MBSTRING_UTF8
+ name_entry = backend._lib.X509_NAME_ENTRY_create_by_OBJ(
+ backend._ffi.NULL, obj, type, value, -1
)
+ return name_entry
+
+
+def _encode_crl_number(backend, crl_number):
+ return _encode_asn1_int_gc(backend, crl_number.crl_number)
def _encode_crl_reason(backend, crl_reason):
@@ -134,9 +136,7 @@ def _encode_crl_reason(backend, crl_reason):
)
backend.openssl_assert(res == 1)
- return _encode_extension_to_der(
- backend, backend._lib.i2d_ASN1_ENUMERATED, asn1enum
- )
+ return asn1enum
def _encode_invalidity_date(backend, invalidity_date):
@@ -148,9 +148,7 @@ def _encode_invalidity_date(backend, invalidity_date):
backend.openssl_assert(time != backend._ffi.NULL)
time = backend._ffi.gc(time, backend._lib.ASN1_GENERALIZEDTIME_free)
- return _encode_extension_to_der(
- backend, backend._lib.i2d_ASN1_GENERALIZEDTIME, time
- )
+ return time
def _encode_certificate_policies(backend, certificate_policies):
@@ -200,9 +198,7 @@ def _encode_certificate_policies(backend, certificate_policies):
pi.qualifiers = pqis
- return _encode_extension_to_der(
- backend, backend._lib.i2d_CERTIFICATEPOLICIES, cp
- )
+ return cp
def _encode_notice_reference(backend, notice):
@@ -243,10 +239,10 @@ def _txt2obj_gc(backend, name):
def _encode_ocsp_nocheck(backend, ext):
"""
- The OCSP No Check extension is defined as a null ASN.1 value. Rather than
- calling OpenSSL we can return a Python bytestring value in a list.
+ The OCSP No Check extension is defined as a null ASN.1 value embedded in
+ an ASN.1 string.
"""
- return [b"\x05\x00"], 2
+ return _encode_asn1_str_gc(backend, b"\x05\x00", 2)
def _encode_key_usage(backend, key_usage):
@@ -278,9 +274,7 @@ def _encode_key_usage(backend, key_usage):
res = set_bit(ku, 8, 0)
backend.openssl_assert(res == 1)
- return _encode_extension_to_der(
- backend, backend._lib.i2d_ASN1_BIT_STRING, ku
- )
+ return ku
def _encode_authority_key_identifier(backend, authority_keyid):
@@ -304,9 +298,7 @@ def _encode_authority_key_identifier(backend, authority_keyid):
backend, authority_keyid.authority_cert_serial_number
)
- return _encode_extension_to_der(
- backend, backend._lib.i2d_AUTHORITY_KEYID, akid
- )
+ return akid
def _encode_basic_constraints(backend, basic_constraints):
@@ -320,9 +312,7 @@ def _encode_basic_constraints(backend, basic_constraints):
backend, basic_constraints.path_length
)
- return _encode_extension_to_der(
- backend, backend._lib.i2d_BASIC_CONSTRAINTS, constraints
- )
+ return constraints
def _encode_authority_information_access(backend, authority_info_access):
@@ -342,9 +332,7 @@ def _encode_authority_information_access(backend, authority_info_access):
res = backend._lib.sk_ACCESS_DESCRIPTION_push(aia, ad)
backend.openssl_assert(res >= 1)
- return _encode_extension_to_der(
- backend, backend._lib.i2d_AUTHORITY_INFO_ACCESS, aia
- )
+ return aia
def _encode_general_names(backend, names):
@@ -363,16 +351,11 @@ def _encode_alt_name(backend, san):
general_names = backend._ffi.gc(
general_names, backend._lib.GENERAL_NAMES_free
)
- return _encode_extension_to_der(
- backend, backend._lib.i2d_GENERAL_NAMES, general_names
- )
+ return general_names
def _encode_subject_key_identifier(backend, ski):
- asn1_str = _encode_asn1_str_gc(backend, ski.digest, len(ski.digest))
- return _encode_extension_to_der(
- backend, backend._lib.i2d_ASN1_OCTET_STRING, asn1_str
- )
+ return _encode_asn1_str_gc(backend, ski.digest, len(ski.digest))
def _encode_general_name(backend, name):
@@ -470,10 +453,7 @@ def _encode_extended_key_usage(backend, extended_key_usage):
res = backend._lib.sk_ASN1_OBJECT_push(eku, obj)
backend.openssl_assert(res >= 1)
- eku_ptr = backend._ffi.cast("EXTENDED_KEY_USAGE *", eku)
- return _encode_extension_to_der(
- backend, backend._lib.i2d_EXTENDED_KEY_USAGE, eku_ptr
- )
+ return eku
_CRLREASONFLAGS = {
@@ -516,8 +496,7 @@ def _encode_crl_distribution_points(backend, crl_distribution_points):
dpn = backend._lib.DIST_POINT_NAME_new()
backend.openssl_assert(dpn != backend._ffi.NULL)
dpn.type = _DISTPOINT_TYPE_RELATIVENAME
- name = _encode_name_gc(backend, point.relative_name)
- relativename = backend._lib.sk_X509_NAME_ENTRY_dup(name.entries)
+ relativename = _encode_sk_name_entry(backend, point.relative_name)
backend.openssl_assert(relativename != backend._ffi.NULL)
dpn.name.relativename = relativename
dp.distpoint = dpn
@@ -528,14 +507,12 @@ def _encode_crl_distribution_points(backend, crl_distribution_points):
res = backend._lib.sk_DIST_POINT_push(cdp, dp)
backend.openssl_assert(res >= 1)
- return _encode_extension_to_der(
- backend, backend._lib.i2d_CRL_DIST_POINTS, cdp
- )
+ return cdp
def _encode_name_constraints(backend, name_constraints):
nc = backend._lib.NAME_CONSTRAINTS_new()
- assert nc != backend._ffi.NULL
+ backend.openssl_assert(nc != backend._ffi.NULL)
nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free)
permitted = _encode_general_subtree(
backend, name_constraints.permitted_subtrees
@@ -546,9 +523,24 @@ def _encode_name_constraints(backend, name_constraints):
)
nc.excludedSubtrees = excluded
- return _encode_extension_to_der(
- backend, backend._lib.Cryptography_i2d_NAME_CONSTRAINTS, nc
- )
+ return nc
+
+
+def _encode_policy_constraints(backend, policy_constraints):
+ pc = backend._lib.POLICY_CONSTRAINTS_new()
+ backend.openssl_assert(pc != backend._ffi.NULL)
+ pc = backend._ffi.gc(pc, backend._lib.POLICY_CONSTRAINTS_free)
+ if policy_constraints.require_explicit_policy is not None:
+ pc.requireExplicitPolicy = _encode_asn1_int(
+ backend, policy_constraints.require_explicit_policy
+ )
+
+ if policy_constraints.inhibit_policy_mapping is not None:
+ pc.inhibitPolicyMapping = _encode_asn1_int(
+ backend, policy_constraints.inhibit_policy_mapping
+ )
+
+ return pc
def _encode_general_subtree(backend, subtrees):
@@ -581,6 +573,7 @@ _EXTENSION_ENCODE_HANDLERS = {
ExtensionOID.INHIBIT_ANY_POLICY: _encode_inhibit_any_policy,
ExtensionOID.OCSP_NO_CHECK: _encode_ocsp_nocheck,
ExtensionOID.NAME_CONSTRAINTS: _encode_name_constraints,
+ ExtensionOID.POLICY_CONSTRAINTS: _encode_policy_constraints,
}
_CRL_EXTENSION_ENCODE_HANDLERS = {
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/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index c71f8d92..71a2fb78 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -97,7 +97,12 @@ class _Certificate(object):
@property
def signature_hash_algorithm(self):
- oid = _obj2txt(self._backend, self._x509.sig_alg.algorithm)
+ alg = self._backend._ffi.new("X509_ALGOR **")
+ self._backend._lib.X509_get0_signature(
+ self._backend._ffi.NULL, alg, self._x509
+ )
+ self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL)
+ oid = _obj2txt(self._backend, alg[0].algorithm)
try:
return x509._SIG_OIDS_TO_HASH[oid]
except KeyError:
@@ -111,13 +116,17 @@ class _Certificate(object):
@property
def signature(self):
- return _asn1_string_to_bytes(self._backend, self._x509.signature)
+ sig = self._backend._ffi.new("ASN1_BIT_STRING **")
+ self._backend._lib.X509_get0_signature(
+ sig, self._backend._ffi.NULL, self._x509
+ )
+ self._backend.openssl_assert(sig[0] != self._backend._ffi.NULL)
+ return _asn1_string_to_bytes(self._backend, sig[0])
@property
def tbs_certificate_bytes(self):
pp = self._backend._ffi.new("unsigned char **")
- # the X509_CINF struct holds the tbsCertificate data
- res = self._backend._lib.i2d_X509_CINF(self._x509.cert_info, pp)
+ res = self._backend._lib.i2d_re_X509_tbs(self._x509, pp)
self._backend.openssl_assert(res > 0)
pp = self._backend._ffi.gc(
pp, lambda pointer: self._backend._lib.OPENSSL_free(pointer[0])
@@ -153,14 +162,20 @@ class _RevokedCertificate(object):
@property
def serial_number(self):
- asn1_int = self._x509_revoked.serialNumber
+ asn1_int = self._backend._lib.X509_REVOKED_get0_serialNumber(
+ self._x509_revoked
+ )
self._backend.openssl_assert(asn1_int != self._backend._ffi.NULL)
return _asn1_integer_to_int(self._backend, asn1_int)
@property
def revocation_date(self):
return _parse_asn1_time(
- self._backend, self._x509_revoked.revocationDate)
+ self._backend,
+ self._backend._lib.X509_REVOKED_get0_revocationDate(
+ self._x509_revoked
+ )
+ )
@property
def extensions(self):
@@ -198,7 +213,12 @@ class _CertificateRevocationList(object):
@property
def signature_hash_algorithm(self):
- oid = _obj2txt(self._backend, self._x509_crl.sig_alg.algorithm)
+ alg = self._backend._ffi.new("X509_ALGOR **")
+ self._backend._lib.X509_CRL_get0_signature(
+ self._backend._ffi.NULL, alg, self._x509_crl
+ )
+ self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL)
+ oid = _obj2txt(self._backend, alg[0].algorithm)
try:
return x509._SIG_OIDS_TO_HASH[oid]
except KeyError:
@@ -226,13 +246,17 @@ class _CertificateRevocationList(object):
@property
def signature(self):
- return _asn1_string_to_bytes(self._backend, self._x509_crl.signature)
+ sig = self._backend._ffi.new("ASN1_BIT_STRING **")
+ self._backend._lib.X509_CRL_get0_signature(
+ sig, self._backend._ffi.NULL, self._x509_crl
+ )
+ self._backend.openssl_assert(sig[0] != self._backend._ffi.NULL)
+ return _asn1_string_to_bytes(self._backend, sig[0])
@property
def tbs_certlist_bytes(self):
pp = self._backend._ffi.new("unsigned char **")
- # the X509_CRL_INFO struct holds the tbsCertList data
- res = self._backend._lib.i2d_X509_CRL_INFO(self._x509_crl.crl, pp)
+ res = self._backend._lib.i2d_re_X509_CRL_tbs(self._x509_crl, pp)
self._backend.openssl_assert(res > 0)
pp = self._backend._ffi.gc(
pp, lambda pointer: self._backend._lib.OPENSSL_free(pointer[0])
@@ -321,7 +345,12 @@ class _CertificateSigningRequest(object):
@property
def signature_hash_algorithm(self):
- oid = _obj2txt(self._backend, self._x509_req.sig_alg.algorithm)
+ alg = self._backend._ffi.new("X509_ALGOR **")
+ self._backend._lib.X509_REQ_get0_signature(
+ self._backend._ffi.NULL, alg, self._x509_req
+ )
+ self._backend.openssl_assert(alg[0] != self._backend._ffi.NULL)
+ oid = _obj2txt(self._backend, alg[0].algorithm)
try:
return x509._SIG_OIDS_TO_HASH[oid]
except KeyError:
@@ -351,8 +380,7 @@ class _CertificateSigningRequest(object):
@property
def tbs_certrequest_bytes(self):
pp = self._backend._ffi.new("unsigned char **")
- # the X509_REQ_INFO struct holds the CertificateRequestInfo data
- res = self._backend._lib.i2d_X509_REQ_INFO(self._x509_req.req_info, pp)
+ res = self._backend._lib.i2d_re_X509_REQ_tbs(self._x509_req, pp)
self._backend.openssl_assert(res > 0)
pp = self._backend._ffi.gc(
pp, lambda pointer: self._backend._lib.OPENSSL_free(pointer[0])
@@ -361,7 +389,12 @@ class _CertificateSigningRequest(object):
@property
def signature(self):
- return _asn1_string_to_bytes(self._backend, self._x509_req.signature)
+ sig = self._backend._ffi.new("ASN1_BIT_STRING **")
+ self._backend._lib.X509_REQ_get0_signature(
+ sig, self._backend._ffi.NULL, self._x509_req
+ )
+ self._backend.openssl_assert(sig[0] != self._backend._ffi.NULL)
+ return _asn1_string_to_bytes(self._backend, sig[0])
@property
def is_signature_valid(self):
diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py
index 206c2915..148534da 100644
--- a/src/cryptography/hazmat/bindings/openssl/_conditional.py
+++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py
@@ -86,8 +86,6 @@ CONDITIONAL_NAMES = {
"EC_KEY_get_enc_flags",
"EC_KEY_set_enc_flags",
"EC_KEY_set_conv_form",
- "EC_KEY_get_key_method_data",
- "EC_KEY_insert_key_method_data",
"EC_KEY_set_asn1_flag",
"EC_KEY_precompute_mult",
"EC_KEY_generate_key",
@@ -168,9 +166,6 @@ CONDITIONAL_NAMES = {
],
"Cryptography_HAS_ECDH": [
"ECDH_compute_key",
- "ECDH_get_ex_new_index",
- "ECDH_set_ex_data",
- "ECDH_get_ex_data",
],
"Cryptography_HAS_ECDSA": [
"ECDSA_SIG_new",
@@ -185,13 +180,6 @@ CONDITIONAL_NAMES = {
"ECDSA_sign_ex",
"ECDSA_verify",
"ECDSA_size",
- "ECDSA_OpenSSL",
- "ECDSA_set_default_method",
- "ECDSA_get_default_method",
- "ECDSA_set_method",
- "ECDSA_get_ex_new_index",
- "ECDSA_set_ex_data",
- "ECDSA_get_ex_data",
],
"Cryptography_HAS_ENGINE_CRYPTODEV": [
"ENGINE_load_cryptodev"
@@ -411,4 +399,17 @@ CONDITIONAL_NAMES = {
"SSL_CTX_set_cert_cb",
"SSL_set_cert_cb",
],
+ "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/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py
index b2215de3..5d7466f9 100644
--- a/src/cryptography/hazmat/bindings/openssl/binding.py
+++ b/src/cryptography/hazmat/bindings/openssl/binding.py
@@ -17,6 +17,9 @@ from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES
_OpenSSLError = collections.namedtuple("_OpenSSLError",
["code", "lib", "func", "reason"])
+_OpenSSLErrorWithText = collections.namedtuple(
+ "_OpenSSLErrorWithText", ["code", "lib", "func", "reason", "reason_text"]
+)
def _consume_errors(lib):
@@ -31,17 +34,33 @@ def _consume_errors(lib):
err_reason = lib.ERR_GET_REASON(code)
errors.append(_OpenSSLError(code, err_lib, err_func, err_reason))
+
return errors
def _openssl_assert(lib, ok):
if not ok:
errors = _consume_errors(lib)
+ errors_with_text = []
+ for err in errors:
+ err_text_reason = ffi.string(
+ lib.ERR_error_string(err.code, ffi.NULL)
+ )
+ errors_with_text.append(
+ _OpenSSLErrorWithText(
+ err.code, err.lib, err.func, err.reason, err_text_reason
+ )
+ )
+
raise InternalError(
- "Unknown OpenSSL error. Please file an issue at https://github.com"
- "/pyca/cryptography/issues with information on how to reproduce "
- "this. ({0!r})".format(errors),
- errors
+ "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
)
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/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py
index 76a9218b..457799d3 100644
--- a/tests/hazmat/bindings/test_openssl.py
+++ b/tests/hazmat/bindings/test_openssl.py
@@ -6,7 +6,10 @@ from __future__ import absolute_import, division, print_function
import pytest
-from cryptography.hazmat.bindings.openssl.binding import Binding
+from cryptography.exceptions import InternalError
+from cryptography.hazmat.bindings.openssl.binding import (
+ Binding, _OpenSSLErrorWithText, _openssl_assert
+)
class TestOpenSSL(object):
@@ -149,3 +152,26 @@ class TestOpenSSL(object):
else:
with pytest.raises(AttributeError):
b.lib.CMAC_Init
+
+ def test_openssl_assert_error_on_stack(self):
+ b = Binding()
+ b.lib.ERR_put_error(
+ b.lib.ERR_LIB_EVP,
+ b.lib.EVP_F_EVP_ENCRYPTFINAL_EX,
+ b.lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH,
+ b"",
+ -1
+ )
+ with pytest.raises(InternalError) as exc_info:
+ _openssl_assert(b.lib, False)
+
+ assert exc_info.value.err_code == [_OpenSSLErrorWithText(
+ code=101183626,
+ lib=b.lib.ERR_LIB_EVP,
+ func=b.lib.EVP_F_EVP_ENCRYPTFINAL_EX,
+ reason=b.lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH,
+ reason_text=(
+ b'error:0607F08A:digital envelope routines:EVP_EncryptFinal_'
+ b'ex:data not multiple of block length'
+ )
+ )]
diff --git a/tests/test_x509.py b/tests/test_x509.py
index c042169c..aaeefae9 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -2225,6 +2225,54 @@ class TestCertificateBuilder(object):
)
assert ext.value == x509.InhibitAnyPolicy(3)
+ @pytest.mark.parametrize(
+ "pc",
+ [
+ x509.PolicyConstraints(
+ require_explicit_policy=None,
+ inhibit_policy_mapping=1
+ ),
+ x509.PolicyConstraints(
+ require_explicit_policy=3,
+ inhibit_policy_mapping=1
+ ),
+ x509.PolicyConstraints(
+ require_explicit_policy=0,
+ inhibit_policy_mapping=None
+ ),
+ ]
+ )
+ @pytest.mark.requires_backend_interface(interface=RSABackend)
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_policy_constraints(self, backend, pc):
+ issuer_private_key = RSA_KEY_2048.private_key(backend)
+ subject_private_key = RSA_KEY_2048.private_key(backend)
+
+ not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
+ not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
+
+ cert = x509.CertificateBuilder().subject_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
+ ).issuer_name(
+ x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
+ ).not_valid_before(
+ not_valid_before
+ ).not_valid_after(
+ not_valid_after
+ ).public_key(
+ subject_private_key.public_key()
+ ).serial_number(
+ 123
+ ).add_extension(
+ pc, critical=False
+ ).sign(issuer_private_key, hashes.SHA256(), backend)
+
+ ext = cert.extensions.get_extension_for_class(
+ x509.PolicyConstraints
+ )
+ assert ext.critical is False
+ assert ext.value == pc
+
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_name_constraints(self, backend):
@@ -2334,6 +2382,39 @@ class TestCertificateBuilder(object):
)
assert basic_constraints.value.path_length is None
+ @pytest.mark.parametrize(
+ "unrecognized", [
+ x509.UnrecognizedExtension(
+ x509.ObjectIdentifier("1.2.3.4.5"),
+ b"abcdef",
+ )
+ ]
+ )
+ @pytest.mark.requires_backend_interface(interface=RSABackend)
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_unrecognized_extension(self, backend, unrecognized):
+ private_key = RSA_KEY_2048.private_key(backend)
+
+ cert = x509.CertificateBuilder().subject_name(
+ x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US')])
+ ).issuer_name(
+ x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US')])
+ ).not_valid_before(
+ datetime.datetime(2002, 1, 1, 12, 1)
+ ).not_valid_after(
+ datetime.datetime(2030, 12, 31, 8, 30)
+ ).public_key(
+ private_key.public_key()
+ ).serial_number(
+ 123
+ ).add_extension(
+ unrecognized, critical=False
+ ).sign(private_key, hashes.SHA256(), backend)
+
+ ext = cert.extensions.get_extension_for_oid(unrecognized.oid)
+
+ assert ext.value == unrecognized
+
@pytest.mark.requires_backend_interface(interface=X509Backend)
class TestCertificateSigningRequestBuilder(object):
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