aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2013-08-09 09:52:43 -0700
committerAlex Gaynor <alex.gaynor@gmail.com>2013-08-09 09:52:43 -0700
commitab4c507fefa52fc3c887b8d0d9786008952a6908 (patch)
treecdd07859176c312704e223caa6f2b099ad0e00ef
parent5de0392f9be95fcd87db096a3176c172f01009da (diff)
downloadcryptography-ab4c507fefa52fc3c887b8d0d9786008952a6908.tar.gz
cryptography-ab4c507fefa52fc3c887b8d0d9786008952a6908.tar.bz2
cryptography-ab4c507fefa52fc3c887b8d0d9786008952a6908.zip
Many TODOs later, we can encrypt a thing
-rw-r--r--cryptography/bindings/openssl/__init__.py2
-rw-r--r--cryptography/bindings/openssl/api.py62
-rw-r--r--cryptography/primitives/block/base.py13
3 files changed, 74 insertions, 3 deletions
diff --git a/cryptography/bindings/openssl/__init__.py b/cryptography/bindings/openssl/__init__.py
index 6c803fbc..103b1db0 100644
--- a/cryptography/bindings/openssl/__init__.py
+++ b/cryptography/bindings/openssl/__init__.py
@@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from cryptography.bindings.openssl import api
+from cryptography.bindings.openssl.api import api
__all__ = ["api"]
diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py
index 3cc6a0e9..ee6e49dd 100644
--- a/cryptography/bindings/openssl/api.py
+++ b/cryptography/bindings/openssl/api.py
@@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from __future__ import absolute_import, division, print_function
+import cffi
class API(object):
@@ -19,5 +19,65 @@ class API(object):
OpenSSL API wrapper.
"""
+ def __init__(self):
+ ffi = cffi.FFI()
+ self._populate_ffi(ffi)
+ self._ffi = ffi
+ self._lib = ffi.verify("""
+ #include <openssl/evp.h>
+ """)
+
+ def _populate_ffi(self, ffi):
+ ffi.cdef("""
+ typedef struct {
+ ...;
+ } EVP_CIPHER_CTX;
+ typedef ... EVP_CIPHER;
+ typedef ... ENGINE;
+
+ const EVP_CIPHER *EVP_get_cipherbyname(const char *);
+ int EVP_EncryptInit_ex(EVP_CIPHER_CTX *, const EVP_CIPHER *,
+ ENGINE *, unsigned char *, unsigned char *);
+ int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *, int);
+ int EVP_EncryptUpdate(EVP_CIPHER_CTX *, unsigned char *, int *,
+ unsigned char *, int);
+ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *, unsigned char *, int *);
+ """)
+
+ def create_block_cipher_context(self, cipher, mode):
+ ctx = self._ffi.new("EVP_CIPHER_CTX *")
+ # TODO: compute real cipher
+ ciphername = b"AES-{}-CBC".format(len(cipher.key) * 8)
+ evp_cipher = self._lib.EVP_get_cipherbyname(ciphername)
+ if evp_cipher == self._ffi.NULL:
+ # TODO: figure out openssl errors
+ raise Exception
+ # TODO: only use the key and initialization_vector as needed
+ res = self._lib.EVP_EncryptInit_ex(ctx, evp_cipher, self._ffi.NULL, cipher.key, mode.initialization_vector)
+ if res == 0:
+ # TODO: figure out openssl errors
+ raise Exception
+ self._lib.EVP_CIPHER_CTX_set_padding(ctx, 0)
+ return ctx
+
+ def update_encrypt_context(self, ctx, plaintext):
+ buf = self._ffi.new("unsigned char[]", len(plaintext))
+ outlen = self._ffi.new("int *")
+ res = self._lib.EVP_EncryptUpdate(ctx, buf, outlen, plaintext, len(plaintext))
+ if res == 0:
+ # TODO: figure out openssl errors
+ raise Exception
+ return self._ffi.buffer(buf)[:outlen[0]]
+
+ def finalize_encrypt_context(self, ctx):
+ # TODO: use real block size
+ buf = self._ffi.new("unsigned char[]", 16)
+ outlen = self._ffi.new("int *")
+ res = self._lib.EVP_EncryptFinal_ex(ctx, buf, outlen)
+ if res == 0:
+ # TODO: figure out openssl errors
+ raise Exception
+ return self._ffi.buffer(buf)[:outlen[0]]
+
api = API()
diff --git a/cryptography/primitives/block/base.py b/cryptography/primitives/block/base.py
index c2cc4327..ed37685d 100644
--- a/cryptography/primitives/block/base.py
+++ b/cryptography/primitives/block/base.py
@@ -1,8 +1,19 @@
+# TODO: which binding is used should be an option somewhere
+from cryptography.bindings.openssl import api
+
+
class BlockCipher(object):
def __init__(self, cipher, mode):
super(BlockCipher, self).__init__()
self.cipher = cipher
self.mode = mode
+ self._ctx = api.create_block_cipher_context(cipher, mode)
+
def encrypt(self, plaintext):
- raise NotImplementedError
+ return api.update_encrypt_context(self._ctx, plaintext)
+
+ def finalize(self):
+ result = api.finalize_encrypt_context(self._ctx)
+ self._ctx = None
+ return result