From 69e0652b1a48815c7d61fed8b625264419ac2796 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 18 Oct 2013 17:28:39 -0500 Subject: hash vector loader and tests --- tests/test_utils.py | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++- tests/utils.py | 35 ++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 28e7407b..b56e106e 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -11,11 +11,14 @@ # See the License for the specific language governing permissions and # limitations under the License. +import pytest + import textwrap from .utils import (load_nist_vectors, load_nist_vectors_from_file, load_cryptrec_vectors, load_cryptrec_vectors_from_file, - load_openssl_vectors, load_openssl_vectors_from_file) + load_openssl_vectors, load_openssl_vectors_from_file, load_hash_vectors, + load_hash_vectors_from_file) def test_load_nist_vectors_encrypt(): @@ -360,3 +363,55 @@ def test_load_openssl_vectors_from_file(): "ciphertext": b"D776379BE0E50825E681DA1A4C980E8E", }, ] + + +def test_load_hash_vectors(): + vector_data = textwrap.dedent(""" + + # http://tools.ietf.org/html/rfc1321 + + Len = 0 + Msg = 00 + MD = d41d8cd98f00b204e9800998ecf8427e + + Len = 8 + Msg = 61 + MD = 0cc175b9c0f1b6a831c399e269772661 + + Len = 24 + Msg = 616263 + MD = 900150983cd24fb0d6963f7d28e17f72 + + Len = 112 + Msg = 6d65737361676520646967657374 + MD = f96b697d7cb7938d525a2f31aaf161d0 + """).splitlines() + assert load_hash_vectors(vector_data) == [ + ('', 'd41d8cd98f00b204e9800998ecf8427e'), + ('61', '0cc175b9c0f1b6a831c399e269772661'), + ('616263', '900150983cd24fb0d6963f7d28e17f72'), + ('6d65737361676520646967657374', 'f96b697d7cb7938d525a2f31aaf161d0'), + ] + + +def test_load_hash_vectors_bad_data(): + vector_data = textwrap.dedent(""" + # http://tools.ietf.org/html/rfc1321 + + Len = 0 + Msg = 00 + UNKNOWN=Hello World + """).splitlines() + with pytest.raises(ValueError): + load_hash_vectors(vector_data) + + +def test_load_hash_vectors_from_file(): + test_list = load_hash_vectors_from_file("RFC/MD5/rfc-1321.txt") + assert len(test_list) == 7 + assert test_list[:4] == [ + ('', 'd41d8cd98f00b204e9800998ecf8427e'), + ('61', '0cc175b9c0f1b6a831c399e269772661'), + ('616263', '900150983cd24fb0d6963f7d28e17f72'), + ('6d65737361676520646967657374', 'f96b697d7cb7938d525a2f31aaf161d0'), + ] diff --git a/tests/utils.py b/tests/utils.py index 6b1cfd79..cf255334 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -119,3 +119,38 @@ def load_openssl_vectors(vector_data): "ciphertext": vector[4].encode("ascii"), }) return vectors + + +def load_hash_vectors(vector_data): + vectors = [] + + for line in vector_data: + line = line.strip() + + if not line or line.startswith("#"): + continue + + if line.startswith("Len"): + length = int(line.split(" = ")[1]) + elif line.startswith("Msg"): + """ + In the NIST vectors they have chosen to represent an empty + string as hex 00, which is of course not actually an empty + string. So we parse the provided length and catch this edge case. + """ + msg = line.split(" = ")[1].encode("ascii") if length > 0 else b"" + elif line.startswith("MD"): + md = line.split(" = ")[1] + # after MD is found the Msg+MD tuple is complete + vectors.append((msg, md)) + else: + raise ValueError("Unknown line in hash vector") + return vectors + + +def load_hash_vectors_from_file(filename): + base = os.path.join( + os.path.dirname(__file__), "primitives", "vectors" + ) + with open(os.path.join(base, filename), "r") as vector_file: + return load_hash_vectors(vector_file) -- cgit v1.2.3 From 79c16e9ef8d0454c64310ccd5faa7fd7dca26313 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 18 Oct 2013 17:44:36 -0500 Subject: alphabetical import order and quote consistency... --- tests/test_utils.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index b56e106e..e68f6a7f 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -11,10 +11,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -import pytest - import textwrap +import pytest + from .utils import (load_nist_vectors, load_nist_vectors_from_file, load_cryptrec_vectors, load_cryptrec_vectors_from_file, load_openssl_vectors, load_openssl_vectors_from_file, load_hash_vectors, @@ -387,10 +387,10 @@ def test_load_hash_vectors(): MD = f96b697d7cb7938d525a2f31aaf161d0 """).splitlines() assert load_hash_vectors(vector_data) == [ - ('', 'd41d8cd98f00b204e9800998ecf8427e'), - ('61', '0cc175b9c0f1b6a831c399e269772661'), - ('616263', '900150983cd24fb0d6963f7d28e17f72'), - ('6d65737361676520646967657374', 'f96b697d7cb7938d525a2f31aaf161d0'), + (b"", "d41d8cd98f00b204e9800998ecf8427e"), + (b"61", "0cc175b9c0f1b6a831c399e269772661"), + (b"616263", "900150983cd24fb0d6963f7d28e17f72"), + (b"6d65737361676520646967657374", "f96b697d7cb7938d525a2f31aaf161d0"), ] @@ -410,8 +410,8 @@ def test_load_hash_vectors_from_file(): test_list = load_hash_vectors_from_file("RFC/MD5/rfc-1321.txt") assert len(test_list) == 7 assert test_list[:4] == [ - ('', 'd41d8cd98f00b204e9800998ecf8427e'), - ('61', '0cc175b9c0f1b6a831c399e269772661'), - ('616263', '900150983cd24fb0d6963f7d28e17f72'), - ('6d65737361676520646967657374', 'f96b697d7cb7938d525a2f31aaf161d0'), + (b"", "d41d8cd98f00b204e9800998ecf8427e"), + (b"61", "0cc175b9c0f1b6a831c399e269772661"), + (b"616263", "900150983cd24fb0d6963f7d28e17f72"), + (b"6d65737361676520646967657374", "f96b697d7cb7938d525a2f31aaf161d0"), ] -- cgit v1.2.3 From 87cd0db396e157b3fb160b8b6fd770e2c661ace2 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 18 Oct 2013 18:01:26 -0500 Subject: update loader and test to handle lines with brackets --- tests/test_utils.py | 1 + tests/utils.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index e68f6a7f..a9bb6a87 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -369,6 +369,7 @@ def test_load_hash_vectors(): vector_data = textwrap.dedent(""" # http://tools.ietf.org/html/rfc1321 + [irrelevant] Len = 0 Msg = 00 diff --git a/tests/utils.py b/tests/utils.py index cf255334..03b780f8 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -127,7 +127,7 @@ def load_hash_vectors(vector_data): for line in vector_data: line = line.strip() - if not line or line.startswith("#"): + if not line or line.startswith("#") or line.startswith("["): continue if line.startswith("Len"): -- cgit v1.2.3 From bde6fb52129909cf319157dba95d65fb557d5013 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 18 Oct 2013 18:08:49 -0500 Subject: Hash Saga Part 3 - API changes + SHA1 support + tests --- cryptography/bindings/openssl/api.py | 30 +++++++++++++++++++ cryptography/primitives/hashes.py | 48 ++++++++++++++++++++++++++++++ tests/primitives/test_hash_vectors.py | 35 ++++++++++++++++++++++ tests/primitives/test_hashes.py | 28 ++++++++++++++++++ tests/primitives/test_utils.py | 24 ++++++++++++++- tests/primitives/utils.py | 55 +++++++++++++++++++++++++++++++++++ 6 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 cryptography/primitives/hashes.py create mode 100644 tests/primitives/test_hash_vectors.py create mode 100644 tests/primitives/test_hashes.py diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py index 79ec5eea..548a9e66 100644 --- a/cryptography/bindings/openssl/api.py +++ b/cryptography/bindings/openssl/api.py @@ -139,5 +139,35 @@ class API(object): assert res != 0 return self.ffi.buffer(buf)[:outlen[0]] + def supports_hash(self, hashname): + return (self.ffi.NULL != + self.lib.EVP_get_digestbyname(hashname.encode("ascii"))) + + def create_hash_context(self, hashobject): + ctx = self.lib.EVP_MD_CTX_create() + ctx = self.ffi.gc(ctx, self.lib.EVP_MD_CTX_destroy) + evp_md = self.lib.EVP_get_digestbyname(hashobject.name.encode("ascii")) + assert evp_md != self.ffi.NULL + res = self.lib.EVP_DigestInit_ex(ctx, evp_md, self.ffi.NULL) + assert res != 0 + return ctx + + def update_hash_context(self, ctx, data): + res = self.lib.EVP_DigestUpdate(ctx, data, len(data)) + assert res != 0 + + def finalize_hash_context(self, ctx, digest_size): + buf = self.ffi.new("unsigned char[]", digest_size) + res = self.lib.EVP_DigestFinal_ex(ctx, buf, self.ffi.NULL) + assert res != 0 + return self.ffi.buffer(buf)[:digest_size] + + def copy_hash_context(self, ctx): + copied_ctx = self.lib.EVP_MD_CTX_create() + copied_ctx = self.ffi.gc(copied_ctx, self.lib.EVP_MD_CTX_destroy) + res = self.lib.EVP_MD_CTX_copy_ex(copied_ctx, ctx) + assert res != 0 + return copied_ctx + api = API() diff --git a/cryptography/primitives/hashes.py b/cryptography/primitives/hashes.py new file mode 100644 index 00000000..d74287f9 --- /dev/null +++ b/cryptography/primitives/hashes.py @@ -0,0 +1,48 @@ +# 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. + +from __future__ import absolute_import, division, print_function + +import binascii + +from cryptography.bindings import _default_api + + +class BaseHash(object): + def __init__(self, api=None, ctx=None): + if api is None: + api = _default_api + self._api = api + self._ctx = self._api.create_hash_context(self) if ctx is None else ctx + + def update(self, string): + self._api.update_hash_context(self._ctx, string) + + def copy(self): + return self.__class__(ctx=self._copy_ctx()) + + def digest(self): + return self._api.finalize_hash_context(self._copy_ctx(), + self.digest_size) + + def hexdigest(self): + return binascii.hexlify(self.digest()).decode("ascii") + + def _copy_ctx(self): + return self._api.copy_hash_context(self._ctx) + + +class SHA1(BaseHash): + name = "sha1" + digest_size = 20 + block_size = 64 diff --git a/tests/primitives/test_hash_vectors.py b/tests/primitives/test_hash_vectors.py new file mode 100644 index 00000000..4b71ad70 --- /dev/null +++ b/tests/primitives/test_hash_vectors.py @@ -0,0 +1,35 @@ +# 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. + +from __future__ import absolute_import, division, print_function + +import os + +from cryptography.primitives import hashes + +from .utils import generate_hash_test +from ..utils import load_hash_vectors_from_file + + +class TestSHA1(object): + test_SHA1 = generate_hash_test( + load_hash_vectors_from_file, + os.path.join("NIST", "SHABYTE"), + [ + "SHA1LongMsg.rsp", + "SHA1ShortMsg.rsp", + ], + lambda api: hashes.SHA1(api=api), + only_if=lambda api: api.supports_hash("sha1"), + skip_message="Does not support SHA1", + ) diff --git a/tests/primitives/test_hashes.py b/tests/primitives/test_hashes.py new file mode 100644 index 00000000..3419b14d --- /dev/null +++ b/tests/primitives/test_hashes.py @@ -0,0 +1,28 @@ +# 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. + +from __future__ import absolute_import, division, print_function + +from cryptography.primitives import hashes + +from .utils import generate_base_hash_test + + +class TestSHA1(object): + test_SHA1 = generate_base_hash_test( + lambda api: hashes.SHA1(api=api), + digest_size=20, + block_size=64, + only_if=lambda api: api.supports_hash("sha1"), + skip_message="Does not support SHA1", + ) diff --git a/tests/primitives/test_utils.py b/tests/primitives/test_utils.py index 4666ece7..43ec8a71 100644 --- a/tests/primitives/test_utils.py +++ b/tests/primitives/test_utils.py @@ -1,6 +1,6 @@ import pytest -from .utils import encrypt_test +from .utils import encrypt_test, hash_test, base_hash_test class TestEncryptTest(object): @@ -12,3 +12,25 @@ class TestEncryptTest(object): skip_message="message!" ) assert exc_info.value.args[0] == "message!" + + +class TestHashTest(object): + def test_skips_if_only_if_returns_false(self): + with pytest.raises(pytest.skip.Exception) as exc_info: + hash_test( + None, None, None, + only_if=lambda api: False, + skip_message="message!" + ) + assert exc_info.value.args[0] == "message!" + + +class TestBaseHashTest(object): + def test_skips_if_only_if_returns_false(self): + with pytest.raises(pytest.skip.Exception) as exc_info: + base_hash_test( + None, None, None, None, + only_if=lambda api: False, + skip_message="message!" + ) + assert exc_info.value.args[0] == "message!" diff --git a/tests/primitives/utils.py b/tests/primitives/utils.py index 3cf08c28..f301199c 100644 --- a/tests/primitives/utils.py +++ b/tests/primitives/utils.py @@ -40,3 +40,58 @@ def encrypt_test(api, cipher_factory, mode_factory, params, only_if, actual_ciphertext = cipher.encrypt(binascii.unhexlify(plaintext)) actual_ciphertext += cipher.finalize() assert actual_ciphertext == binascii.unhexlify(ciphertext) + + +def generate_hash_test(param_loader, path, file_names, hash_factory, + only_if=lambda api: True, skip_message=None): + def test_hash(self): + for api in _ALL_APIS: + for file_name in file_names: + for params in param_loader(os.path.join(path, file_name)): + yield ( + hash_test, + api, + hash_factory, + params, + only_if, + skip_message + ) + return test_hash + + +def hash_test(api, hash_factory, params, only_if, skip_message): + if not only_if(api): + pytest.skip(skip_message) + msg = params[0] + md = params[1] + m = hash_factory(api) + m.update(binascii.unhexlify(msg)) + assert m.hexdigest() == md.replace(" ", "").lower() + + +def generate_base_hash_test(hash_factory, digest_size, block_size, + only_if=lambda api: True, skip_message=None): + def test_base_hash(self): + for api in _ALL_APIS: + yield ( + base_hash_test, + api, + hash_factory, + digest_size, + block_size, + only_if, + skip_message, + ) + return test_base_hash + + +def base_hash_test(api, hash_factory, digest_size, block_size, only_if, + skip_message): + if not only_if(api): + pytest.skip(skip_message) + m = hash_factory(api=api) + assert m.digest_size == digest_size + assert m.block_size == block_size + m_copy = m.copy() + assert m != m_copy + assert m._ctx != m_copy._ctx -- cgit v1.2.3 From 66021687ccf03cb1c45e4ddefe5f6b0e737e45a8 Mon Sep 17 00:00:00 2001 From: cyli Date: Fri, 18 Oct 2013 16:33:50 -0700 Subject: Add bindings for x509name --- cryptography/bindings/openssl/api.py | 1 + cryptography/bindings/openssl/x509name.py | 46 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 cryptography/bindings/openssl/x509name.py diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py index 2a6d38e6..ad913783 100644 --- a/cryptography/bindings/openssl/api.py +++ b/cryptography/bindings/openssl/api.py @@ -39,6 +39,7 @@ class API(object): "rand", "rsa", "ssl", + "x509name" ] def __init__(self): diff --git a/cryptography/bindings/openssl/x509name.py b/cryptography/bindings/openssl/x509name.py new file mode 100644 index 00000000..919c84b3 --- /dev/null +++ b/cryptography/bindings/openssl/x509name.py @@ -0,0 +1,46 @@ +# 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 +""" + +TYPES = """ +typedef ... X509_NAME; +typedef ... X509_NAME_ENTRY; +""" + +FUNCTIONS = """ +int X509_NAME_entry_count(X509_NAME *); +X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *, int); +ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *); +ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *); +unsigned long X509_NAME_hash(X509_NAME *); + +int i2d_X509_NAME(X509_NAME *, unsigned char **); +int X509_NAME_add_entry_by_NID(X509_NAME *, int, int, unsigned char *, + int, int, int); +X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *, int); +void X509_NAME_ENTRY_free(X509_NAME_ENTRY *); +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 *); +void X509_NAME_free(X509_NAME *); + +struct stack_st_X509_NAME *sk_X509_NAME_new_null(); +int sk_X509_NAME_num(struct stack_st_X509_NAME *); +int sk_X509_NAME_push(struct stack_st_X509_NAME *, X509_NAME *); +X509_NAME *sk_X509_NAME_value(struct stack_st_X509_NAME *, int); +void sk_X509_NAME_free(struct stack_st_X509_NAME *); +""" -- cgit v1.2.3 From c0c9fe714088beef3adbc82f67eb0a558cf73ff7 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 18 Oct 2013 17:40:49 -0700 Subject: Added bindings for pkcs7. Refs #77 --- cryptography/bindings/openssl/api.py | 1 + cryptography/bindings/openssl/pkcs7.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 cryptography/bindings/openssl/pkcs7.py diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py index 2a6d38e6..2ad6c054 100644 --- a/cryptography/bindings/openssl/api.py +++ b/cryptography/bindings/openssl/api.py @@ -36,6 +36,7 @@ class API(object): "err", "evp", "opensslv", + "pkcs7", "rand", "rsa", "ssl", diff --git a/cryptography/bindings/openssl/pkcs7.py b/cryptography/bindings/openssl/pkcs7.py new file mode 100644 index 00000000..752bfa00 --- /dev/null +++ b/cryptography/bindings/openssl/pkcs7.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 +""" + +TYPES = """ +typedef struct { + ASN1_OBJECT *type; + ...; +} PKCS7; +""" + +FUNCTIONS = """ +void PKCS7_free(PKCS7 *); +""" + +MACROS = """ +int PKCS7_type_is_signed(PKCS7 *); +int PKCS7_type_is_enveloped(PKCS7 *); +int PKCS7_type_is_signedAndEnveloped(PKCS7 *); +int PKCS7_type_is_data(PKCS7 *); +""" -- cgit v1.2.3 From bb069c2fee6460185ee435ea848d80bab2ccec6c Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 18 Oct 2013 19:51:01 -0500 Subject: remove unneeded lambdas from tests --- tests/primitives/test_hash_vectors.py | 2 +- tests/primitives/test_hashes.py | 2 +- tests/primitives/utils.py | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/primitives/test_hash_vectors.py b/tests/primitives/test_hash_vectors.py index 4b71ad70..8198b086 100644 --- a/tests/primitives/test_hash_vectors.py +++ b/tests/primitives/test_hash_vectors.py @@ -29,7 +29,7 @@ class TestSHA1(object): "SHA1LongMsg.rsp", "SHA1ShortMsg.rsp", ], - lambda api: hashes.SHA1(api=api), + hashes.SHA1, only_if=lambda api: api.supports_hash("sha1"), skip_message="Does not support SHA1", ) diff --git a/tests/primitives/test_hashes.py b/tests/primitives/test_hashes.py index 3419b14d..1bc2e9e9 100644 --- a/tests/primitives/test_hashes.py +++ b/tests/primitives/test_hashes.py @@ -20,7 +20,7 @@ from .utils import generate_base_hash_test class TestSHA1(object): test_SHA1 = generate_base_hash_test( - lambda api: hashes.SHA1(api=api), + hashes.SHA1, digest_size=20, block_size=64, only_if=lambda api: api.supports_hash("sha1"), diff --git a/tests/primitives/utils.py b/tests/primitives/utils.py index f301199c..0d4c0eb3 100644 --- a/tests/primitives/utils.py +++ b/tests/primitives/utils.py @@ -42,7 +42,7 @@ def encrypt_test(api, cipher_factory, mode_factory, params, only_if, assert actual_ciphertext == binascii.unhexlify(ciphertext) -def generate_hash_test(param_loader, path, file_names, hash_factory, +def generate_hash_test(param_loader, path, file_names, hash_cls, only_if=lambda api: True, skip_message=None): def test_hash(self): for api in _ALL_APIS: @@ -51,7 +51,7 @@ def generate_hash_test(param_loader, path, file_names, hash_factory, yield ( hash_test, api, - hash_factory, + hash_cls, params, only_if, skip_message @@ -59,24 +59,24 @@ def generate_hash_test(param_loader, path, file_names, hash_factory, return test_hash -def hash_test(api, hash_factory, params, only_if, skip_message): +def hash_test(api, hash_cls, params, only_if, skip_message): if not only_if(api): pytest.skip(skip_message) msg = params[0] md = params[1] - m = hash_factory(api) + m = hash_cls(api=api) m.update(binascii.unhexlify(msg)) assert m.hexdigest() == md.replace(" ", "").lower() -def generate_base_hash_test(hash_factory, digest_size, block_size, +def generate_base_hash_test(hash_cls, digest_size, block_size, only_if=lambda api: True, skip_message=None): def test_base_hash(self): for api in _ALL_APIS: yield ( base_hash_test, api, - hash_factory, + hash_cls, digest_size, block_size, only_if, @@ -85,11 +85,11 @@ def generate_base_hash_test(hash_factory, digest_size, block_size, return test_base_hash -def base_hash_test(api, hash_factory, digest_size, block_size, only_if, +def base_hash_test(api, hash_cls, digest_size, block_size, only_if, skip_message): if not only_if(api): pytest.skip(skip_message) - m = hash_factory(api=api) + m = hash_cls(api=api) assert m.digest_size == digest_size assert m.block_size == block_size m_copy = m.copy() -- cgit v1.2.3 From ba3b471e4b0f56e65acdb9d5daf64eb726d9c371 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 18 Oct 2013 20:53:04 -0500 Subject: change api.supports_hash to take a hash class rather than a str * This change means hash class names will be byte strings and we no longer need to encode to ascii on hashobject.name in create_hash_context --- cryptography/bindings/openssl/api.py | 6 +++--- cryptography/primitives/hashes.py | 2 +- tests/primitives/test_hash_vectors.py | 2 +- tests/primitives/test_hashes.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py index 548a9e66..84458367 100644 --- a/cryptography/bindings/openssl/api.py +++ b/cryptography/bindings/openssl/api.py @@ -139,14 +139,14 @@ class API(object): assert res != 0 return self.ffi.buffer(buf)[:outlen[0]] - def supports_hash(self, hashname): + def supports_hash(self, hash_cls): return (self.ffi.NULL != - self.lib.EVP_get_digestbyname(hashname.encode("ascii"))) + self.lib.EVP_get_digestbyname(hash_cls.name)) def create_hash_context(self, hashobject): ctx = self.lib.EVP_MD_CTX_create() ctx = self.ffi.gc(ctx, self.lib.EVP_MD_CTX_destroy) - evp_md = self.lib.EVP_get_digestbyname(hashobject.name.encode("ascii")) + evp_md = self.lib.EVP_get_digestbyname(hashobject.name) assert evp_md != self.ffi.NULL res = self.lib.EVP_DigestInit_ex(ctx, evp_md, self.ffi.NULL) assert res != 0 diff --git a/cryptography/primitives/hashes.py b/cryptography/primitives/hashes.py index d74287f9..f5cf135a 100644 --- a/cryptography/primitives/hashes.py +++ b/cryptography/primitives/hashes.py @@ -43,6 +43,6 @@ class BaseHash(object): class SHA1(BaseHash): - name = "sha1" + name = b"sha1" digest_size = 20 block_size = 64 diff --git a/tests/primitives/test_hash_vectors.py b/tests/primitives/test_hash_vectors.py index 8198b086..9a925e27 100644 --- a/tests/primitives/test_hash_vectors.py +++ b/tests/primitives/test_hash_vectors.py @@ -30,6 +30,6 @@ class TestSHA1(object): "SHA1ShortMsg.rsp", ], hashes.SHA1, - only_if=lambda api: api.supports_hash("sha1"), + only_if=lambda api: api.supports_hash(hashes.SHA1), skip_message="Does not support SHA1", ) diff --git a/tests/primitives/test_hashes.py b/tests/primitives/test_hashes.py index 1bc2e9e9..4ad5c89a 100644 --- a/tests/primitives/test_hashes.py +++ b/tests/primitives/test_hashes.py @@ -23,6 +23,6 @@ class TestSHA1(object): hashes.SHA1, digest_size=20, block_size=64, - only_if=lambda api: api.supports_hash("sha1"), + only_if=lambda api: api.supports_hash(hashes.SHA1), skip_message="Does not support SHA1", ) -- cgit v1.2.3 From 3b7730cf90c6a5114391d2d5a2ccc1cdb448da9e Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 18 Oct 2013 20:59:25 -0500 Subject: change name to str --- cryptography/bindings/openssl/api.py | 4 ++-- cryptography/primitives/hashes.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py index 84458367..cf3389d2 100644 --- a/cryptography/bindings/openssl/api.py +++ b/cryptography/bindings/openssl/api.py @@ -141,12 +141,12 @@ class API(object): def supports_hash(self, hash_cls): return (self.ffi.NULL != - self.lib.EVP_get_digestbyname(hash_cls.name)) + self.lib.EVP_get_digestbyname(hash_cls.name.encode("ascii"))) def create_hash_context(self, hashobject): ctx = self.lib.EVP_MD_CTX_create() ctx = self.ffi.gc(ctx, self.lib.EVP_MD_CTX_destroy) - evp_md = self.lib.EVP_get_digestbyname(hashobject.name) + evp_md = self.lib.EVP_get_digestbyname(hashobject.name.encode("ascii")) assert evp_md != self.ffi.NULL res = self.lib.EVP_DigestInit_ex(ctx, evp_md, self.ffi.NULL) assert res != 0 diff --git a/cryptography/primitives/hashes.py b/cryptography/primitives/hashes.py index f5cf135a..d74287f9 100644 --- a/cryptography/primitives/hashes.py +++ b/cryptography/primitives/hashes.py @@ -43,6 +43,6 @@ class BaseHash(object): class SHA1(BaseHash): - name = b"sha1" + name = "sha1" digest_size = 20 block_size = 64 -- cgit v1.2.3 From fc1c8314a7aed4838755f00c0ece1c6197de1f86 Mon Sep 17 00:00:00 2001 From: cyli Date: Fri, 18 Oct 2013 19:04:16 -0700 Subject: Move some things from functions to macros --- cryptography/bindings/openssl/x509name.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cryptography/bindings/openssl/x509name.py b/cryptography/bindings/openssl/x509name.py index 919c84b3..bd7abe2d 100644 --- a/cryptography/bindings/openssl/x509name.py +++ b/cryptography/bindings/openssl/x509name.py @@ -37,7 +37,9 @@ 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 *); void X509_NAME_free(X509_NAME *); +""" +MACROS = """ struct stack_st_X509_NAME *sk_X509_NAME_new_null(); int sk_X509_NAME_num(struct stack_st_X509_NAME *); int sk_X509_NAME_push(struct stack_st_X509_NAME *, X509_NAME *); -- cgit v1.2.3 From 7e5697c6f597ac6b0550ae3dbcc19482d10f3efe Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 18 Oct 2013 21:07:36 -0500 Subject: SHA-2 family support --- cryptography/primitives/hashes.py | 24 +++++++++++++++ tests/primitives/test_hash_vectors.py | 56 +++++++++++++++++++++++++++++++++++ tests/primitives/test_hashes.py | 40 +++++++++++++++++++++++++ 3 files changed, 120 insertions(+) diff --git a/cryptography/primitives/hashes.py b/cryptography/primitives/hashes.py index d74287f9..d004c45c 100644 --- a/cryptography/primitives/hashes.py +++ b/cryptography/primitives/hashes.py @@ -46,3 +46,27 @@ class SHA1(BaseHash): name = "sha1" digest_size = 20 block_size = 64 + + +class SHA224(BaseHash): + name = "sha224" + digest_size = 28 + block_size = 64 + + +class SHA256(BaseHash): + name = "sha256" + digest_size = 32 + block_size = 64 + + +class SHA384(BaseHash): + name = "sha384" + digest_size = 48 + block_size = 128 + + +class SHA512(BaseHash): + name = "sha512" + digest_size = 64 + block_size = 128 diff --git a/tests/primitives/test_hash_vectors.py b/tests/primitives/test_hash_vectors.py index 9a925e27..d0fe46d1 100644 --- a/tests/primitives/test_hash_vectors.py +++ b/tests/primitives/test_hash_vectors.py @@ -33,3 +33,59 @@ class TestSHA1(object): only_if=lambda api: api.supports_hash(hashes.SHA1), skip_message="Does not support SHA1", ) + + +class TestSHA224(object): + test_SHA224 = generate_hash_test( + load_hash_vectors_from_file, + os.path.join("NIST", "SHABYTE"), + [ + "SHA224LongMsg.rsp", + "SHA224ShortMsg.rsp", + ], + hashes.SHA224, + only_if=lambda api: api.supports_hash(hashes.SHA224), + skip_message="Does not support SHA224", + ) + + +class TestSHA256(object): + test_SHA256 = generate_hash_test( + load_hash_vectors_from_file, + os.path.join("NIST", "SHABYTE"), + [ + "SHA256LongMsg.rsp", + "SHA256ShortMsg.rsp", + ], + hashes.SHA256, + only_if=lambda api: api.supports_hash(hashes.SHA256), + skip_message="Does not support SHA256", + ) + + +class TestSHA384(object): + test_SHA384 = generate_hash_test( + load_hash_vectors_from_file, + os.path.join("NIST", "SHABYTE"), + [ + "SHA384LongMsg.rsp", + "SHA384ShortMsg.rsp", + ], + hashes.SHA384, + only_if=lambda api: api.supports_hash(hashes.SHA384), + skip_message="Does not support SHA384", + ) + + +class TestSHA512(object): + test_SHA512 = generate_hash_test( + load_hash_vectors_from_file, + os.path.join("NIST", "SHABYTE"), + [ + "SHA512LongMsg.rsp", + "SHA512ShortMsg.rsp", + ], + hashes.SHA512, + only_if=lambda api: api.supports_hash(hashes.SHA512), + skip_message="Does not support SHA512", + ) diff --git a/tests/primitives/test_hashes.py b/tests/primitives/test_hashes.py index 4ad5c89a..2f2dd1c7 100644 --- a/tests/primitives/test_hashes.py +++ b/tests/primitives/test_hashes.py @@ -26,3 +26,43 @@ class TestSHA1(object): only_if=lambda api: api.supports_hash(hashes.SHA1), skip_message="Does not support SHA1", ) + + +class TestSHA224(object): + test_SHA224 = generate_base_hash_test( + hashes.SHA224, + digest_size=28, + block_size=64, + only_if=lambda api: api.supports_hash(hashes.SHA224), + skip_message="Does not support SHA224", + ) + + +class TestSHA256(object): + test_SHA256 = generate_base_hash_test( + hashes.SHA256, + digest_size=32, + block_size=64, + only_if=lambda api: api.supports_hash(hashes.SHA256), + skip_message="Does not support SHA256", + ) + + +class TestSHA384(object): + test_SHA384 = generate_base_hash_test( + hashes.SHA384, + digest_size=48, + block_size=128, + only_if=lambda api: api.supports_hash(hashes.SHA384), + skip_message="Does not support SHA384", + ) + + +class TestSHA512(object): + test_SHA512 = generate_base_hash_test( + hashes.SHA512, + digest_size=64, + block_size=128, + only_if=lambda api: api.supports_hash(hashes.SHA512), + skip_message="Does not support SHA512", + ) -- cgit v1.2.3 From c179407406f0ef5c2b7b5b6316521408ba3803b3 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 18 Oct 2013 21:42:57 -0500 Subject: ripemd160 support + long string hash test * Note that the long string hash test for RIPEMD160 adds a vector in the test. You can verify this vector (for b"a" * 1000000) on the RIPE homepage: http://homes.esat.kuleuven.be/~bosselae/ripemd160.html --- cryptography/primitives/hashes.py | 6 ++++++ tests/primitives/test_hash_vectors.py | 22 +++++++++++++++++++++- tests/primitives/test_hashes.py | 10 ++++++++++ tests/primitives/test_utils.py | 14 +++++++++++++- tests/primitives/utils.py | 23 +++++++++++++++++++++++ 5 files changed, 73 insertions(+), 2 deletions(-) diff --git a/cryptography/primitives/hashes.py b/cryptography/primitives/hashes.py index d004c45c..affca564 100644 --- a/cryptography/primitives/hashes.py +++ b/cryptography/primitives/hashes.py @@ -70,3 +70,9 @@ class SHA512(BaseHash): name = "sha512" digest_size = 64 block_size = 128 + + +class RIPEMD160(BaseHash): + name = "ripemd160" + digest_size = 20 + block_size = 64 diff --git a/tests/primitives/test_hash_vectors.py b/tests/primitives/test_hash_vectors.py index d0fe46d1..51c4b85d 100644 --- a/tests/primitives/test_hash_vectors.py +++ b/tests/primitives/test_hash_vectors.py @@ -17,7 +17,7 @@ import os from cryptography.primitives import hashes -from .utils import generate_hash_test +from .utils import generate_hash_test, generate_long_string_hash_test from ..utils import load_hash_vectors_from_file @@ -89,3 +89,23 @@ class TestSHA512(object): only_if=lambda api: api.supports_hash(hashes.SHA512), skip_message="Does not support SHA512", ) + + +class TestRIPEMD160(object): + test_RIPEMD160 = generate_hash_test( + load_hash_vectors_from_file, + os.path.join("ISO", "ripemd160"), + [ + "ripevectors.txt", + ], + hashes.RIPEMD160, + only_if=lambda api: api.supports_hash(hashes.RIPEMD160), + skip_message="Does not support RIPEMD160", + ) + + test_RIPEMD160_long_string = generate_long_string_hash_test( + hashes.RIPEMD160, + "52783243c1697bdbe16d37f97f68f08325dc1528", + only_if=lambda api: api.supports_hash(hashes.RIPEMD160), + skip_message="Does not support RIPEMD160", + ) diff --git a/tests/primitives/test_hashes.py b/tests/primitives/test_hashes.py index 2f2dd1c7..bfb45037 100644 --- a/tests/primitives/test_hashes.py +++ b/tests/primitives/test_hashes.py @@ -66,3 +66,13 @@ class TestSHA512(object): only_if=lambda api: api.supports_hash(hashes.SHA512), skip_message="Does not support SHA512", ) + + +class TestRIPEMD160(object): + test_RIPEMD160 = generate_base_hash_test( + hashes.RIPEMD160, + digest_size=20, + block_size=64, + only_if=lambda api: api.supports_hash(hashes.RIPEMD160), + skip_message="Does not support RIPEMD160", + ) diff --git a/tests/primitives/test_utils.py b/tests/primitives/test_utils.py index 43ec8a71..9888309e 100644 --- a/tests/primitives/test_utils.py +++ b/tests/primitives/test_utils.py @@ -1,6 +1,7 @@ import pytest -from .utils import encrypt_test, hash_test, base_hash_test +from .utils import (base_hash_test, encrypt_test, hash_test, + long_string_hash_test) class TestEncryptTest(object): @@ -34,3 +35,14 @@ class TestBaseHashTest(object): skip_message="message!" ) assert exc_info.value.args[0] == "message!" + + +class TestLongHashTest(object): + def test_skips_if_only_if_returns_false(self): + with pytest.raises(pytest.skip.Exception) as exc_info: + long_string_hash_test( + None, None, None, + only_if=lambda api: False, + skip_message="message!" + ) + assert exc_info.value.args[0] == "message!" diff --git a/tests/primitives/utils.py b/tests/primitives/utils.py index 0d4c0eb3..8b32700b 100644 --- a/tests/primitives/utils.py +++ b/tests/primitives/utils.py @@ -95,3 +95,26 @@ def base_hash_test(api, hash_cls, digest_size, block_size, only_if, m_copy = m.copy() assert m != m_copy assert m._ctx != m_copy._ctx + + +def generate_long_string_hash_test(hash_factory, md, only_if=lambda api: True, + skip_message=None): + def test_long_string_hash(self): + for api in _ALL_APIS: + yield( + long_string_hash_test, + api, + hash_factory, + md, + only_if, + skip_message + ) + return test_long_string_hash + + +def long_string_hash_test(api, hash_factory, md, only_if, skip_message): + if not only_if(api): + pytest.skip(skip_message) + m = hash_factory(api) + m.update(b"a" * 1000000) + assert m.hexdigest() == md.lower() -- cgit v1.2.3 From e89657dd0152762a17d8e8b4042fe9b24043927f Mon Sep 17 00:00:00 2001 From: cyli Date: Fri, 18 Oct 2013 15:44:24 -0700 Subject: Add x509 bindings --- cryptography/bindings/openssl/api.py | 3 +- cryptography/bindings/openssl/x509.py | 181 ++++++++++++++++++++++++++++++++++ 2 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 cryptography/bindings/openssl/x509.py diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py index cfd4fc47..31549131 100644 --- a/cryptography/bindings/openssl/api.py +++ b/cryptography/bindings/openssl/api.py @@ -40,7 +40,8 @@ class API(object): "rand", "rsa", "ssl", - "x509name" + "x509name", + "x509" ] def __init__(self): diff --git a/cryptography/bindings/openssl/x509.py b/cryptography/bindings/openssl/x509.py new file mode 100644 index 00000000..0a60dab0 --- /dev/null +++ b/cryptography/bindings/openssl/x509.py @@ -0,0 +1,181 @@ +# 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 +""" + +TYPES = """ +typedef int time_t; + +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 x, long); +long X509_get_version(X509 *); + +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); +ASN1_TIME *X509_get_notBefore(X509 *); +ASN1_TIME *X509_get_notAfter(X509 *); + +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); +long X509_REQ_get_version(X509_REQ *); +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 *); +X509_NAME *X509_REQ_get_subject_name(X509_REQ *); +int X509_REQ_add_extensions(X509_REQ *, X509_EXTENSIONS *); +int X509_REQ_print_ex(BIO *, X509_REQ *, unsigned long, unsigned long); + +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 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 sk_X509_REVOKED_num(struct x509_revoked_st *); +X509_REVOKED *sk_X509_REVOKED_value(struct x509_revoked_st *, int); +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_lastUpdate(X509_CRL *, const ASN1_TIME *); +int X509_CRL_set_nextUpdate(X509_CRL *, const ASN1_TIME *); +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 *); +""" -- cgit v1.2.3 From 86c65644171af71bc70d09a8f0d070aad9550520 Mon Sep 17 00:00:00 2001 From: cyli Date: Fri, 18 Oct 2013 19:16:41 -0700 Subject: Do not redefine time_t, since asn1 already defines it. --- cryptography/bindings/openssl/x509.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/cryptography/bindings/openssl/x509.py b/cryptography/bindings/openssl/x509.py index 0a60dab0..f88d0f75 100644 --- a/cryptography/bindings/openssl/x509.py +++ b/cryptography/bindings/openssl/x509.py @@ -16,8 +16,6 @@ INCLUDES = """ """ TYPES = """ -typedef int time_t; - typedef struct { ASN1_OBJECT *algorithm; ...; -- cgit v1.2.3 From 80b95ed3bf918ec4e8a4601dad8da837b39b896f Mon Sep 17 00:00:00 2001 From: cyli Date: Fri, 18 Oct 2013 20:37:29 -0700 Subject: Move macros to macros, and some functions that have changed between versions to macros --- cryptography/bindings/openssl/x509.py | 51 ++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/cryptography/bindings/openssl/x509.py b/cryptography/bindings/openssl/x509.py index f88d0f75..fc0922fb 100644 --- a/cryptography/bindings/openssl/x509.py +++ b/cryptography/bindings/openssl/x509.py @@ -72,8 +72,7 @@ X509 *X509_dup(X509 *); int X509_print_ex(BIO *, X509 *, unsigned long, unsigned long); -int X509_set_version(X509 x, long); -long X509_get_version(X509 *); +int X509_set_version(X509 *, long); EVP_PKEY *X509_get_pubkey(X509 *); int X509_set_pubkey(X509 *, EVP_PKEY *); @@ -84,8 +83,6 @@ 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); -ASN1_TIME *X509_get_notBefore(X509 *); -ASN1_TIME *X509_get_notAfter(X509 *); unsigned long X509_subject_name_hash(X509 *); @@ -104,29 +101,16 @@ ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *); void X509_EXTENSION_free(X509_EXTENSION *); int X509_REQ_set_version(X509_REQ *, long); -long X509_REQ_get_version(X509_REQ *); 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 *); -X509_NAME *X509_REQ_get_subject_name(X509_REQ *); int X509_REQ_add_extensions(X509_REQ *, X509_EXTENSIONS *); int X509_REQ_print_ex(BIO *, X509_REQ *, unsigned long, unsigned long); -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 X509V3_EXT_print(BIO *, X509_EXTENSION *, unsigned long, int); ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *); @@ -134,8 +118,6 @@ ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *); X509_REVOKED *X509_REVOKED_new(); void X509_REVOKED_free(X509_REVOKED *); -int sk_X509_REVOKED_num(struct x509_revoked_st *); -X509_REVOKED *sk_X509_REVOKED_value(struct x509_revoked_st *, int); int X509_REVOKED_set_serialNumber(X509_REVOKED *, ASN1_INTEGER *); int X509_REVOKED_add1_ext_i2d(X509_REVOKED *, int, void *, int, unsigned long); @@ -146,8 +128,6 @@ 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_lastUpdate(X509_CRL *, const ASN1_TIME *); -int X509_CRL_set_nextUpdate(X509_CRL *, const ASN1_TIME *); int X509_CRL_set_issuer_name(X509_CRL *, X509_NAME *); int X509_CRL_sign(X509_CRL *, EVP_PKEY *, const EVP_MD *); @@ -177,3 +157,32 @@ 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); + +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 *); +""" -- cgit v1.2.3 From 01451eb9900c309884a7873b47ca17249dcf6a83 Mon Sep 17 00:00:00 2001 From: cyli Date: Fri, 18 Oct 2013 21:21:28 -0700 Subject: One more macro with a confusing error --- cryptography/bindings/openssl/x509.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cryptography/bindings/openssl/x509.py b/cryptography/bindings/openssl/x509.py index fc0922fb..9a51a6d0 100644 --- a/cryptography/bindings/openssl/x509.py +++ b/cryptography/bindings/openssl/x509.py @@ -110,8 +110,6 @@ 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); -X509_EXTENSIONS *sk_X509_EXTENSION_new_null(); - int X509V3_EXT_print(BIO *, X509_EXTENSION *, unsigned long, int); ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *); @@ -173,6 +171,7 @@ 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 *); -- cgit v1.2.3