#include <crypto.h>
#include <fips.h>
#include "crypto-api.h"
+#include "iov.h"
typedef struct api_cipher_hd_st {
cipher_hd_st ctx_enc;
}
}
-#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:
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(),
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);