diff options
-rw-r--r-- | .travis.yml | 5 | ||||
-rw-r--r-- | cryptography/bindings/openssl/api.py | 13 | ||||
-rw-r--r-- | cryptography/bindings/openssl/evp.py | 1 | ||||
-rw-r--r-- | cryptography/bindings/openssl/nid.py | 44 | ||||
-rw-r--r-- | cryptography/bindings/openssl/pem.py | 44 | ||||
-rw-r--r-- | cryptography/bindings/openssl/pkcs12.py | 34 | ||||
-rw-r--r-- | cryptography/bindings/openssl/x509.py | 187 | ||||
-rw-r--r-- | cryptography/bindings/openssl/x509v3.py | 94 | ||||
-rw-r--r-- | docs/contributing.rst | 17 | ||||
-rw-r--r-- | docs/index.rst | 1 | ||||
-rw-r--r-- | docs/security.rst | 12 | ||||
-rw-r--r-- | tests/primitives/test_block.py | 11 | ||||
-rw-r--r-- | tests/primitives/utils.py | 12 | ||||
-rw-r--r-- | tests/test_utils.py | 14 | ||||
-rw-r--r-- | tests/utils.py | 2 | ||||
-rw-r--r-- | tox.ini | 2 |
16 files changed, 477 insertions, 16 deletions
diff --git a/.travis.yml b/.travis.yml index defcd77b..1c35b397 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,11 @@ env: - TOX_ENV=py32 - TOX_ENV=py33 - TOX_ENV=pypy + - TOX_ENV=py26 CC=clang + - TOX_ENV=py27 CC=clang + - TOX_ENV=py32 CC=clang + - TOX_ENV=py33 CC=clang + - TOX_ENV=pypy CC=clang - TOX_ENV=docs - TOX_ENV=pep8 diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py index cfd4fc47..3c2cf2e2 100644 --- a/cryptography/bindings/openssl/api.py +++ b/cryptography/bindings/openssl/api.py @@ -35,12 +35,17 @@ class API(object): "engine", "err", "evp", + "nid", "opensslv", + "pem", "pkcs7", + "pkcs12", "rand", "rsa", "ssl", - "x509name" + "x509", + "x509name", + "x509v3", ] def __init__(self): @@ -123,7 +128,8 @@ class API(object): return ctx def update_encrypt_context(self, ctx, plaintext): - buf = self.ffi.new("unsigned char[]", len(plaintext)) + block_size = self.lib.EVP_CIPHER_CTX_block_size(ctx) + buf = self.ffi.new("unsigned char[]", len(plaintext) + block_size - 1) outlen = self.ffi.new("int *") res = self.lib.EVP_EncryptUpdate( ctx, buf, outlen, plaintext, len(plaintext) @@ -132,8 +138,7 @@ class API(object): return self.ffi.buffer(buf)[:outlen[0]] def finalize_encrypt_context(self, ctx): - cipher = self.lib.EVP_CIPHER_CTX_cipher(ctx) - block_size = self.lib.EVP_CIPHER_block_size(cipher) + block_size = self.lib.EVP_CIPHER_CTX_block_size(ctx) buf = self.ffi.new("unsigned char[]", block_size) outlen = self.ffi.new("int *") res = self.lib.EVP_EncryptFinal_ex(ctx, buf, outlen) diff --git a/cryptography/bindings/openssl/evp.py b/cryptography/bindings/openssl/evp.py index 2b7b0f4c..20159906 100644 --- a/cryptography/bindings/openssl/evp.py +++ b/cryptography/bindings/openssl/evp.py @@ -76,4 +76,5 @@ int EVP_VerifyFinal(EVP_MD_CTX *, const unsigned char *, unsigned int, MACROS = """ int EVP_PKEY_assign_RSA(EVP_PKEY *, RSA *); int EVP_PKEY_assign_DSA(EVP_PKEY *, DSA *); +int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *); """ diff --git a/cryptography/bindings/openssl/nid.py b/cryptography/bindings/openssl/nid.py new file mode 100644 index 00000000..0f5b0003 --- /dev/null +++ b/cryptography/bindings/openssl/nid.py @@ -0,0 +1,44 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +INCLUDES = "" + +TYPES = """ +static const int NID_undef; +static const int NID_dsa; +static const int NID_dsaWithSHA; +static const int NID_dsaWithSHA1; +static const int NID_md2; +static const int NID_md4; +static const int NID_md5; +static const int NID_mdc2; +static const int NID_ripemd160; +static const int NID_sha; +static const int NID_sha1; +static const int NID_sha256; +static const int NID_sha384; +static const int NID_sha512; +static const int NID_sha224; +static const int NID_sha; +static const int NID_ecdsa_with_SHA1; +static const int NID_ecdsa_with_SHA224; +static const int NID_ecdsa_with_SHA256; +static const int NID_ecdsa_with_SHA384; +static const int NID_ecdsa_with_SHA512; +static const int NID_crl_reason; +static const int NID_pbe_WithSHA1And3_Key_TripleDES_CBC; +""" + +FUNCTIONS = "" + +MACROS = "" diff --git a/cryptography/bindings/openssl/pem.py b/cryptography/bindings/openssl/pem.py new file mode 100644 index 00000000..8c8f736d --- /dev/null +++ b/cryptography/bindings/openssl/pem.py @@ -0,0 +1,44 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +INCLUDES = """ +#include <openssl/pem.h> +""" + +TYPES = """ +typedef int pem_password_cb(char *buf, int size, int rwflag, void *userdata); +""" + +FUNCTIONS = """ +X509 *PEM_read_bio_X509(BIO *, X509 **, pem_password_cb *, void *); +int PEM_write_bio_X509(BIO *, X509 *); + +int PEM_write_bio_PrivateKey(BIO *, EVP_PKEY *, const EVP_CIPHER *, + unsigned char *, int, pem_password_cb *, void *); + +EVP_PKEY *PEM_read_bio_PrivateKey(BIO *, EVP_PKEY **, pem_password_cb *, + void *); + +int PEM_write_bio_X509_REQ(BIO *, X509_REQ *); + +X509_REQ *PEM_read_bio_X509_REQ(BIO *, X509_REQ **, pem_password_cb *, void *); + +X509_CRL *PEM_read_bio_X509_CRL(BIO *, X509_CRL **, pem_password_cb *, void *); + +int PEM_write_bio_X509_CRL(BIO *, X509_CRL *); + +PKCS7 *PEM_read_bio_PKCS7(BIO *, PKCS7 **, pem_password_cb *, void *); +DH *PEM_read_bio_DHparams(BIO *, DH **, pem_password_cb *, void *); +""" + +MACROS = "" diff --git a/cryptography/bindings/openssl/pkcs12.py b/cryptography/bindings/openssl/pkcs12.py new file mode 100644 index 00000000..5c002b93 --- /dev/null +++ b/cryptography/bindings/openssl/pkcs12.py @@ -0,0 +1,34 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +INCLUDES = """ +#include <openssl/pkcs12.h> +""" + +TYPES = """ +typedef ... PKCS12; +""" + +FUNCTIONS = """ +void PKCS12_free(PKCS12 *); + +PKCS12 *d2i_PKCS12_bio(BIO *, PKCS12 **); +int i2d_PKCS12_bio(BIO *, PKCS12 *); +""" + +MACROS = """ +int PKCS12_parse(PKCS12 *, const char *, EVP_PKEY **, X509 **, + struct stack_st_X509 **); +PKCS12 *PKCS12_create(char *, char *, EVP_PKEY *, X509 *, + struct stack_st_X509 *, int, int, int, int, int); +""" diff --git a/cryptography/bindings/openssl/x509.py b/cryptography/bindings/openssl/x509.py new file mode 100644 index 00000000..9a51a6d0 --- /dev/null +++ b/cryptography/bindings/openssl/x509.py @@ -0,0 +1,187 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +INCLUDES = """ +#include <openssl/ssl.h> +""" + +TYPES = """ +typedef struct { + ASN1_OBJECT *algorithm; + ...; +} X509_ALGOR; + +typedef struct { + X509_ALGOR *signature; + ...; +} X509_CINF; + +typedef struct { + ASN1_OBJECT *object; + ASN1_BOOLEAN critical; + ASN1_OCTET_STRING *value; +} X509_EXTENSION; + +typedef ... X509_EXTENSIONS; + +typedef ... X509_REQ; + +typedef ... x509_revoked_st; + +typedef struct { + ASN1_INTEGER *serialNumber; + ASN1_TIME *revocationDate; + X509_EXTENSIONS *extensions; + int sequence; + ...; +} X509_REVOKED; + +typedef struct { + struct x509_revoked_st *revoked; + ...; +} X509_CRL_INFO; + +typedef struct { + X509_CRL_INFO *crl; + ...; +} X509_CRL; + +typedef struct { + X509_CINF *cert_info; + ...; +} X509; + +typedef ... X509_STORE; +typedef ... NETSCAPE_SPKI; +""" + +FUNCTIONS = """ +X509 *X509_new(); +void X509_free(X509 *); +X509 *X509_dup(X509 *); + +int X509_print_ex(BIO *, X509 *, unsigned long, unsigned long); + +int X509_set_version(X509 *, long); + +EVP_PKEY *X509_get_pubkey(X509 *); +int X509_set_pubkey(X509 *, EVP_PKEY *); + +unsigned char *X509_alias_get0(X509 *, int *); +int X509_sign(X509 *, EVP_PKEY *, const EVP_MD *); + +int X509_digest(const X509 *, const EVP_MD *, unsigned char *, unsigned int *); + +ASN1_TIME *X509_gmtime_adj(ASN1_TIME *, long); + +unsigned long X509_subject_name_hash(X509 *); + +X509_NAME *X509_get_subject_name(X509 *); +int X509_set_subject_name(X509 *, X509_NAME *); + +X509_NAME *X509_get_issuer_name(X509 *); +int X509_set_issuer_name(X509 *, X509_NAME *); + +int X509_get_ext_count(X509 *); +int X509_add_ext(X509 *, X509_EXTENSION *, int); +X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *); +X509_EXTENSION *X509_get_ext(X509 *, int); +int X509_EXTENSION_get_critical(X509_EXTENSION *); +ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *); +void X509_EXTENSION_free(X509_EXTENSION *); + +int X509_REQ_set_version(X509_REQ *, long); +X509_REQ *X509_REQ_new(); +void X509_REQ_free(X509_REQ *); +int X509_REQ_set_pubkey(X509_REQ *, EVP_PKEY *); +int X509_REQ_sign(X509_REQ *, EVP_PKEY *, const EVP_MD *); +int X509_REQ_verify(X509_REQ *, EVP_PKEY *); +EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *); +int X509_REQ_add_extensions(X509_REQ *, X509_EXTENSIONS *); +int X509_REQ_print_ex(BIO *, X509_REQ *, unsigned long, unsigned long); + +int X509V3_EXT_print(BIO *, X509_EXTENSION *, unsigned long, int); +ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *); + +X509_REVOKED *X509_REVOKED_new(); +void X509_REVOKED_free(X509_REVOKED *); + +int X509_REVOKED_set_serialNumber(X509_REVOKED *, ASN1_INTEGER *); + +int X509_REVOKED_add1_ext_i2d(X509_REVOKED *, int, void *, int, unsigned long); + +X509_CRL *d2i_X509_CRL_bio(BIO *, X509_CRL **); +X509_CRL *X509_CRL_new(); +void X509_CRL_free(X509_CRL *); +int X509_CRL_add0_revoked(X509_CRL *, X509_REVOKED *); +int i2d_X509_CRL_bio(BIO *, X509_CRL *); +int X509_CRL_print(BIO *, X509_CRL *); +int X509_CRL_set_issuer_name(X509_CRL *, X509_NAME *); +int X509_CRL_sign(X509_CRL *, EVP_PKEY *, const EVP_MD *); + +int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *, EVP_PKEY *); +int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *, EVP_PKEY *, const EVP_MD *); +char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *); +EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *); +int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *, EVP_PKEY *); +NETSCAPE_SPKI *NETSCAPE_SPKI_new(); +void NETSCAPE_SPKI_free(NETSCAPE_SPKI *); + +/* ASN1 serialization */ +int i2d_X509_bio(BIO *, X509 *); +X509 *d2i_X509_bio(BIO *, X509 **); + +int i2d_X509_REQ_bio(BIO *, X509_REQ *); +X509_REQ *d2i_X509_REQ_bio(BIO *, X509_REQ **); + +int i2d_PrivateKey_bio(BIO *, EVP_PKEY *); +EVP_PKEY *d2i_PrivateKey_bio(BIO *, EVP_PKEY **); + +ASN1_INTEGER *X509_get_serialNumber(X509 *); +int X509_set_serialNumber(X509 *, ASN1_INTEGER *); + +/* X509_STORE */ +X509_STORE *X509_STORE_new(); +void X509_STORE_free(X509_STORE *); +int X509_STORE_add_cert(X509_STORE *, X509 *); +""" + +MACROS = """ +long X509_get_version(X509 *); + +ASN1_TIME *X509_get_notBefore(X509 *); +ASN1_TIME *X509_get_notAfter(X509 *); + +long X509_REQ_get_version(X509_REQ *); +X509_NAME *X509_REQ_get_subject_name(X509_REQ *); + +struct stack_st_X509 *sk_X509_new_null(); +void sk_X509_free(struct stack_st_X509 *); +int sk_X509_num(struct stack_st_X509 *); +int sk_X509_push(struct stack_st_X509 *, X509 *); +X509 *sk_X509_value(struct stack_st_X509 *, int); + +X509_EXTENSIONS *sk_X509_EXTENSION_new_null(); +int sk_X509_EXTENSION_num(X509_EXTENSIONS *); +X509_EXTENSION *sk_X509_EXTENSION_value(X509_EXTENSIONS *, int); +int sk_X509_EXTENSION_push(X509_EXTENSIONS *, X509_EXTENSION *); +void sk_X509_EXTENSION_delete(X509_EXTENSIONS *, int); +void sk_X509_EXTENSION_free(X509_EXTENSIONS *); + +int sk_X509_REVOKED_num(struct x509_revoked_st *); +X509_REVOKED *sk_X509_REVOKED_value(struct x509_revoked_st *, int); + +/* These aren't macros these arguments are all const X on openssl > 1.0.x */ +int X509_CRL_set_lastUpdate(X509_CRL *, const ASN1_TIME *); +int X509_CRL_set_nextUpdate(X509_CRL *, const ASN1_TIME *); +""" diff --git a/cryptography/bindings/openssl/x509v3.py b/cryptography/bindings/openssl/x509v3.py new file mode 100644 index 00000000..413bde5f --- /dev/null +++ b/cryptography/bindings/openssl/x509v3.py @@ -0,0 +1,94 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +INCLUDES = """ +#include <openssl/x509v3.h> +""" + +TYPES = """ +typedef struct { + X509 *issuer_cert; + X509 *subject_cert; + ...; +} X509V3_CTX; + +typedef void * (*X509V3_EXT_D2I)(void *, const unsigned char **, long); + +typedef struct { + ASN1_ITEM_EXP *it; + X509V3_EXT_D2I d2i; + ...; +} X509V3_EXT_METHOD; + +static const int GEN_OTHERNAME; +static const int GEN_EMAIL; +static const int GEN_X400; +static const int GEN_DNS; +static const int GEN_URI; +static const int GEN_DIRNAME; +static const int GEN_EDIPARTY; +static const int GEN_IPADD; +static const int GEN_RID; + +typedef struct { + ...; +} OTHERNAME; + +typedef struct { + ...; +} EDIPARTYNAME; + +typedef struct { + int type; + union { + char *ptr; + OTHERNAME *otherName; /* otherName */ + ASN1_IA5STRING *rfc822Name; + ASN1_IA5STRING *dNSName; + ASN1_TYPE *x400Address; + X509_NAME *directoryName; + EDIPARTYNAME *ediPartyName; + ASN1_IA5STRING *uniformResourceIdentifier; + ASN1_OCTET_STRING *iPAddress; + ASN1_OBJECT *registeredID; + + /* Old names */ + ASN1_OCTET_STRING *ip; /* iPAddress */ + X509_NAME *dirn; /* dirn */ + ASN1_IA5STRING *ia5; /* rfc822Name, dNSName, */ + /* uniformResourceIdentifier */ + ASN1_OBJECT *rid; /* registeredID */ + ASN1_TYPE *other; /* x400Address */ + } d; + ...; +} GENERAL_NAME; + +typedef struct stack_st_GENERAL_NAME GENERAL_NAMES; +""" + +FUNCTIONS = """ +void X509V3_set_ctx(X509V3_CTX *, X509 *, X509 *, X509_REQ *, X509_CRL *, int); +X509_EXTENSION *X509V3_EXT_nconf(CONF *, X509V3_CTX *, char *, char *); +int GENERAL_NAME_print(BIO *, GENERAL_NAME *); +""" + +MACROS = """ +void *X509V3_set_ctx_nodb(X509V3_CTX *); +int sk_GENERAL_NAME_num(struct stack_st_GENERAL_NAME *); +int sk_GENERAL_NAME_push(struct stack_st_GENERAL_NAME *, GENERAL_NAME *); +GENERAL_NAME *sk_GENERAL_NAME_value(struct stack_st_GENERAL_NAME *, int); + +/* These aren't macros these functions are all const X on openssl > 1.0.x */ +const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *); +const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int); +""" diff --git a/docs/contributing.rst b/docs/contributing.rst index b125d1af..6a76c705 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -32,11 +32,8 @@ devastating, ``cryptography`` has a strict code review policy: The purpose of these policies is to minimize the chances we merge a change which jeopardizes our users' security. -We do not yet have a formal security contact. To report security issues in -``cryptography`` you should email ``alex.gaynor@gmail.com``, messages may be -encrypted with PGP to key fingerprint -``E27D 4AA0 1651 72CB C5D2 AF2B 125F 5C67 DFE9 4084`` (this public key is -available from most commonly-used keyservers). +If you believe you've identified a security issue in ``cryptography``, please +follow the directions on the :doc:`security page </security>`. Code ---- @@ -65,6 +62,16 @@ Don't name parameters: // Bad long f(long x); +...unless they're inside a struct: + +.. code-block:: c + + struct my_struct { + char *name; + int number; + ...; + }; + Don't include stray ``void`` parameters: .. code-block:: c diff --git a/docs/index.rst b/docs/index.rst index 5cc455f6..a868a5d6 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -34,4 +34,5 @@ Contents primitives/index bindings/index contributing + security community diff --git a/docs/security.rst b/docs/security.rst new file mode 100644 index 00000000..36c8e0f7 --- /dev/null +++ b/docs/security.rst @@ -0,0 +1,12 @@ +Security +======== + +We take the security of ``cryptography`` seriously. If you believe you've +identified a security issue in it, please report it to +``alex.gaynor@gmail.com``. Message may be encrypted with PGP using key +fingerprint ``E27D 4AA0 1651 72CB C5D2 AF2B 125F 5C67 DFE9 4084`` (this public +key is available from most commonly-used keyservers). + +Once you’ve submitted an issue via email, you should receive an acknowledgment +within 48 hours, and depending on the action to be taken, you may receive +further followup emails. diff --git a/tests/primitives/test_block.py b/tests/primitives/test_block.py index f4d3f467..9f5905bf 100644 --- a/tests/primitives/test_block.py +++ b/tests/primitives/test_block.py @@ -63,3 +63,14 @@ class TestBlockCipher(object): with pytest.raises(ValueError): cipher.finalize() + + def test_unaligned_block_encryption(self, api): + cipher = BlockCipher( + ciphers.AES(binascii.unhexlify(b"0" * 32)), + modes.ECB(), + api + ) + ct = cipher.encrypt(b"a" * 15) + assert ct == b"" + ct += cipher.encrypt(b"a" * 65) + assert len(ct) == 80 diff --git a/tests/primitives/utils.py b/tests/primitives/utils.py index 8b32700b..a3759b03 100644 --- a/tests/primitives/utils.py +++ b/tests/primitives/utils.py @@ -43,7 +43,7 @@ def encrypt_test(api, cipher_factory, mode_factory, params, only_if, def generate_hash_test(param_loader, path, file_names, hash_cls, - only_if=lambda api: True, skip_message=None): + only_if=None, skip_message=None): def test_hash(self): for api in _ALL_APIS: for file_name in file_names: @@ -60,7 +60,7 @@ def generate_hash_test(param_loader, path, file_names, hash_cls, def hash_test(api, hash_cls, params, only_if, skip_message): - if not only_if(api): + if only_if is not None and not only_if(api): pytest.skip(skip_message) msg = params[0] md = params[1] @@ -70,7 +70,7 @@ def hash_test(api, hash_cls, params, only_if, skip_message): def generate_base_hash_test(hash_cls, digest_size, block_size, - only_if=lambda api: True, skip_message=None): + only_if=None, skip_message=None): def test_base_hash(self): for api in _ALL_APIS: yield ( @@ -87,7 +87,7 @@ def generate_base_hash_test(hash_cls, digest_size, block_size, def base_hash_test(api, hash_cls, digest_size, block_size, only_if, skip_message): - if not only_if(api): + if only_if is not None and not only_if(api): pytest.skip(skip_message) m = hash_cls(api=api) assert m.digest_size == digest_size @@ -97,7 +97,7 @@ def base_hash_test(api, hash_cls, digest_size, block_size, only_if, assert m._ctx != m_copy._ctx -def generate_long_string_hash_test(hash_factory, md, only_if=lambda api: True, +def generate_long_string_hash_test(hash_factory, md, only_if=None, skip_message=None): def test_long_string_hash(self): for api in _ALL_APIS: @@ -113,7 +113,7 @@ def generate_long_string_hash_test(hash_factory, md, only_if=lambda api: True, def long_string_hash_test(api, hash_factory, md, only_if, skip_message): - if not only_if(api): + if only_if is not None and not only_if(api): pytest.skip(skip_message) m = hash_factory(api) m.update(b"a" * 1000000) diff --git a/tests/test_utils.py b/tests/test_utils.py index a9bb6a87..3fe9e570 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -269,6 +269,20 @@ def test_load_cryptrec_vectors(): ] +def test_load_cryptrec_vectors_invalid(): + vector_data = textwrap.dedent(""" + # Vectors taken from http://info.isl.ntt.co.jp/crypt/eng/camellia/ + # Download is t_camelia.txt + + # Camellia with 128-bit key + + E No.001 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + """).splitlines() + + with pytest.raises(ValueError): + load_cryptrec_vectors(vector_data) + + def test_load_cryptrec_vectors_from_file_encrypt(): test_set = load_cryptrec_vectors_from_file( "Camellia/NTT/camellia-128-ecb.txt" diff --git a/tests/utils.py b/tests/utils.py index 03b780f8..fa7cc68d 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -90,6 +90,8 @@ def load_cryptrec_vectors(vector_data): "plaintext": pt, "ciphertext": ct }) + else: + raise ValueError("Invalid line in file '{}'".format(line)) return cryptrec_list @@ -8,7 +8,7 @@ deps = pretend commands = coverage run --source=cryptography/,tests/ -m pytest - coverage report -m + coverage report -m --fail-under 100 [testenv:docs] deps = sphinx |