diff options
Diffstat (limited to 'cryptography/hazmat/bindings/openssl')
| -rw-r--r-- | cryptography/hazmat/bindings/openssl/backend.py | 43 | 
1 files changed, 42 insertions, 1 deletions
diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py index 9f8ea939..08afa4d6 100644 --- a/cryptography/hazmat/bindings/openssl/backend.py +++ b/cryptography/hazmat/bindings/openssl/backend.py @@ -28,7 +28,7 @@ from cryptography.hazmat.primitives.ciphers.algorithms import (      AES, Blowfish, Camellia, CAST5, TripleDES, ARC4,  )  from cryptography.hazmat.primitives.ciphers.modes import ( -    CBC, CTR, ECB, OFB, CFB +    CBC, CTR, ECB, OFB, CFB, GCM,  ) @@ -186,6 +186,11 @@ class Backend(object):              type(None),              GetCipherByName("rc4")          ) +        self.register_cipher_adapter( +            AES, +            GCM, +            GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}") +        )      def create_symmetric_encryption_ctx(self, cipher, mode):          return _CipherContext(self, cipher, mode, _CipherContext._ENCRYPT) @@ -238,6 +243,9 @@ class _CipherContext(object):      def __init__(self, backend, cipher, mode, operation):          self._backend = backend          self._cipher = cipher +        self._mode = mode +        self._operation = operation +        self._tag = None          ctx = self._backend.lib.EVP_CIPHER_CTX_new()          ctx = self._backend.ffi.gc(ctx, self._backend.lib.EVP_CIPHER_CTX_free) @@ -270,6 +278,20 @@ class _CipherContext(object):              ctx, len(cipher.key)          )          assert res != 0 +        if isinstance(mode, GCM): +            res = self._backend.lib.EVP_CIPHER_CTX_ctrl( +                ctx, self._backend.lib.Cryptography_EVP_CTRL_GCM_SET_IVLEN, +                len(iv_nonce), self._backend.ffi.NULL +            ) +            assert res != 0 +            if operation == self._DECRYPT: +                assert mode.tag is not None +                res = self._backend.lib.EVP_CIPHER_CTX_ctrl( +                    ctx, self._backend.lib.Cryptography_EVP_CTRL_GCM_SET_TAG, +                    len(mode.tag), mode.tag +                ) +                assert res != 0 +          # pass key/iv          res = self._backend.lib.EVP_CipherInit_ex(ctx, self._backend.ffi.NULL,                                                    self._backend.ffi.NULL, @@ -298,10 +320,29 @@ class _CipherContext(object):          if res == 0:              self._backend._handle_error() +        if (isinstance(self._mode, GCM) and +           self._operation == self._ENCRYPT): +            block_byte_size = self._cipher.block_size // 8 +            tag_buf = self._backend.ffi.new("unsigned char[]", block_byte_size) +            res = self._backend.lib.EVP_CIPHER_CTX_ctrl( +                self._ctx, self._backend.lib.Cryptography_EVP_CTRL_GCM_GET_TAG, +                block_byte_size, tag_buf +            ) +            assert res != 0 +            size = self._cipher.block_size +            self._tag = self._backend.ffi.buffer(tag_buf)[:size] +          res = self._backend.lib.EVP_CIPHER_CTX_cleanup(self._ctx)          assert res == 1          return self._backend.ffi.buffer(buf)[:outlen[0]] +    def add_data(self, data): +        outlen = self._backend.ffi.new("int *") +        res = self._backend.lib.EVP_CipherUpdate( +            self._ctx, self._backend.ffi.NULL, outlen, data, len(data) +        ) +        assert res != 0 +  @utils.register_interface(interfaces.HashContext)  class _HashContext(object):  | 
