Many TODOs later, we can encrypt a thing
diff --git a/cryptography/bindings/openssl/__init__.py b/cryptography/bindings/openssl/__init__.py
index 6c803fb..103b1db 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 3cc6a0e..ee6e49d 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 @@
     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 c2cc432..ed37685 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