]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
crypto-api: use giovec_t iterator interface for aead_encryptv
authorDaiki Ueno <dueno@redhat.com>
Thu, 1 Aug 2019 16:13:38 +0000 (18:13 +0200)
committerDaiki Ueno <dueno@redhat.com>
Fri, 9 Aug 2019 06:47:06 +0000 (08:47 +0200)
This replaces the macros AUTH_UPDATE and ENCRYPT used in
gnutls_aead_cipher_encryptv() with the iov_iter interface.

Signed-off-by: Daiki Ueno <dueno@redhat.com>
lib/crypto-api.c

index 8af3f3b7dc193faeb94e11c1223e7ae8308c0aaf..70107fed0a5ef85e4bfb6b6a6ffd9b0329c7607a 100644 (file)
@@ -31,6 +31,7 @@
 #include <crypto.h>
 #include <fips.h>
 #include "crypto-api.h"
+#include "iov.h"
 
 typedef struct api_cipher_hd_st {
        cipher_hd_st ctx_enc;
@@ -916,98 +917,6 @@ static int copy_iov(struct iov_store_st *dst, const giovec_t *iov, int iovcnt)
        }
 }
 
-#define AUTH_UPDATE_FINAL(ctx) do { \
-       if (index) { \
-               ret = _gnutls_cipher_auth(ctx, cache, index); \
-               if (unlikely(ret < 0)) \
-                       return gnutls_assert_val(ret); \
-       } \
-       } while(0)
-
-#define AUTH_UPDATE(ctx, data, length) do { \
-       if (index) { \
-               ssize_t left = blocksize - index; \
-               if (length < left) { \
-                       memcpy(cache+index, data, \
-                              length); \
-                       index += length; \
-                       goto __update_done; \
-               } else { \
-                       memcpy(cache+index, data, left); \
-                       ret = _gnutls_cipher_auth(ctx, cache, blocksize); \
-                       if (unlikely(ret < 0)) \
-                               return gnutls_assert_val(ret); \
-                       data += left; \
-                       length -= left; \
-               } \
-       } \
-       if (length >= blocksize) { \
-               ssize_t to_proc = (length/blocksize)*blocksize; \
-               ret = _gnutls_cipher_auth(ctx, data, to_proc); \
-               if (unlikely(ret < 0)) \
-                       return gnutls_assert_val(ret); \
-               data += to_proc; \
-               length -= to_proc; \
-       } \
-       if (length) \
-               memcpy(cache, data, length); \
-       index = length; \
- __update_done: \
-       ; \
-       } while(0)
-
-#define ENCRYPT_FINAL(ctx, dst, dst_size) do { \
-       if (index) { \
-               if (unlikely(dst_size < (ssize_t)index)) \
-                       return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); \
-               ret = _gnutls_cipher_encrypt2(ctx, cache, index, dst, dst_size); \
-               if (unlikely(ret < 0)) \
-                       return gnutls_assert_val(ret); \
-               dst += index; \
-               dst_size -= index; \
-       } \
-       } while(0)
-
-#define ENCRYPT(ctx, data, length, dst, dst_size) do { \
-       if (index) { \
-               ssize_t left = blocksize - index; \
-               if (length < left) { \
-                       memcpy(cache+index, data, \
-                              length); \
-                       index += length; \
-                       goto __encrypt_done; \
-               } else { \
-                       if (unlikely(dst_size < blocksize)) \
-                               return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); \
-                       memcpy(cache+index, data, left); \
-                       ret = _gnutls_cipher_encrypt2(ctx, cache, blocksize, dst, dst_size); \
-                       if (unlikely(ret < 0)) \
-                               return gnutls_assert_val(ret); \
-                       data += left; \
-                       length -= left; \
-                       dst += blocksize; \
-                       dst_size -= blocksize; \
-               } \
-       } \
-       if (length >= blocksize) { \
-               ssize_t to_proc = (length/blocksize)*blocksize; \
-               if (unlikely(dst_size < to_proc)) \
-                       return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); \
-               ret = _gnutls_cipher_encrypt2(ctx, data, to_proc, dst, dst_size); \
-               if (unlikely(ret < 0)) \
-                       return gnutls_assert_val(ret); \
-               data += to_proc; \
-               length -= to_proc; \
-               dst += to_proc; \
-               dst_size -= to_proc; \
-       } \
-       if (length) \
-               memcpy(cache, data, length); \
-       index = length; \
- __encrypt_done: \
-       ; \
-       } while(0)
-
 
 /**
  * gnutls_aead_cipher_encryptv:
@@ -1039,14 +948,13 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
                            void *ctext, size_t *ctext_len)
 {
        api_aead_cipher_hd_st *h = handle;
-       int ret;
+       ssize_t ret;
        uint8_t *dst;
-       ssize_t dst_size, total = 0, len;
+       ssize_t dst_size, total = 0;
        uint8_t *p;
-       unsigned i;
-       uint8_t cache[MAX_CIPHER_BLOCK_SIZE];
-       unsigned index;
        ssize_t blocksize = handle->ctx_enc.e->blocksize;
+       struct iov_iter_st iter;
+       size_t blocks;
 
        /* Limitation: this function provides an optimization under the internally registered
         * AEAD ciphers. When an AEAD cipher is used registered with gnutls_crypto_register_aead_cipher(),
@@ -1088,25 +996,64 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
        if (unlikely(ret < 0))
                return gnutls_assert_val(ret);
 
-       index = 0;
-       for (i = 0; i < (unsigned)auth_iovcnt; i++) {
-               p = auth_iov[i].iov_base;
-               len = auth_iov[i].iov_len;
-               AUTH_UPDATE(&handle->ctx_enc, p, len);
+       ret = _gnutls_iov_iter_init(&iter, auth_iov, auth_iovcnt, blocksize);
+       if (unlikely(ret < 0))
+               return gnutls_assert_val(ret);
+       while (1) {
+               ret = _gnutls_iov_iter_next(&iter, &p);
+               if (unlikely(ret < 0))
+                       return gnutls_assert_val(ret);
+               if (ret == 0)
+                       break;
+               blocks = ret;
+               ret = _gnutls_cipher_auth(&handle->ctx_enc, p,
+                                         blocksize * blocks);
+               if (unlikely(ret < 0))
+                       return gnutls_assert_val(ret);
+       }
+       if (iter.block_offset > 0) {
+               ret = _gnutls_cipher_auth(&handle->ctx_enc,
+                                         iter.block, iter.block_offset);
+               if (unlikely(ret < 0))
+                       return gnutls_assert_val(ret);
        }
-       AUTH_UPDATE_FINAL(&handle->ctx_enc);
 
        dst = ctext;
        dst_size = *ctext_len;
 
-       index = 0;
-       for (i = 0; i < (unsigned)iovcnt; i++) {
-               p = iov[i].iov_base;
-               len = iov[i].iov_len;
-               ENCRYPT(&handle->ctx_enc, p, len, dst, dst_size);
-               total += iov[i].iov_len;
+       ret = _gnutls_iov_iter_init(&iter, iov, iovcnt, blocksize);
+       if (unlikely(ret < 0))
+               return gnutls_assert_val(ret);
+       while (1) {
+               ret = _gnutls_iov_iter_next(&iter, &p);
+               if (unlikely(ret < 0))
+                       return gnutls_assert_val(ret);
+               if (ret == 0)
+                       break;
+               blocks = ret;
+               if (unlikely((size_t) dst_size < blocksize * blocks))
+                       return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+               ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p,
+                                             blocksize * blocks,
+                                             dst, dst_size);
+               if (unlikely(ret < 0))
+                       return gnutls_assert_val(ret);
+               DECR_LEN(dst_size, blocksize * blocks);
+               dst += blocksize * blocks;
+               total += blocksize * blocks;
+       }
+       if (iter.block_offset > 0) {
+               if (unlikely((size_t) dst_size < iter.block_offset))
+                       return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+               ret = _gnutls_cipher_encrypt2(&handle->ctx_enc,
+                                             iter.block, iter.block_offset,
+                                             dst, dst_size);
+               if (unlikely(ret < 0))
+                       return gnutls_assert_val(ret);
+               DECR_LEN(dst_size, iter.block_offset);
+               dst += iter.block_offset;
+               total += iter.block_offset;
        }
-       ENCRYPT_FINAL(&handle->ctx_enc, dst, dst_size);
 
        if ((size_t)dst_size < tag_size)
                return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);