Extends afalg functionality to another AES cipher.
GCM, will enable TLS to use hardware crypto accelerator
through AF_ALG socket. Support keysize 128,192 ans 256.
Signed-off-by: Atul Gupta <atul.gu...@chelsio.com>
---
engines/e_afalg.c | 568 --
engines/e_afalg.h | 28 ++-
engines/e_afalg_err.h | 2 +
3 files changed, 578 insertions(+), 20 deletions(-)
diff --git a/engines/e_afalg.c b/engines/e_afalg.c
index 49b0173..b2de6bb 100644
--- a/engines/e_afalg.c
+++ b/engines/e_afalg.c
@@ -80,13 +80,18 @@ static int afalg_destroy(ENGINE *e);
static int afalg_init(ENGINE *e);
static int afalg_finish(ENGINE *e);
const EVP_CIPHER *afalg_aes_cbc(int nid);
-static cbc_handles *get_cipher_handle(int nid);
+const EVP_CIPHER *afalg_aes_gcm(int nid);
+static aes_handles *get_cipher_handle(int nid);
static int afalg_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
const int **nids, int nid);
static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
static int afalg_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl);
+static int afalg_gcm_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc);
+static int afalg_do_gcm(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl);
static int afalg_cipher_cleanup(EVP_CIPHER_CTX *ctx);
static int afalg_chk_platform(void);
@@ -98,11 +103,17 @@ static int afalg_cipher_nids[] = {
NID_aes_128_cbc,
NID_aes_192_cbc,
NID_aes_256_cbc,
+NID_aes_128_gcm,
+NID_aes_192_gcm,
+NID_aes_256_gcm,
};
-static cbc_handles cbc_handle[] = {{AES_KEY_SIZE_128, NULL},
-{AES_KEY_SIZE_192, NULL},
-{AES_KEY_SIZE_256, NULL}};
+static aes_handles cipher_handle[] = {{AES_KEY_SIZE_128, NULL},
+ {AES_KEY_SIZE_192, NULL},
+ {AES_KEY_SIZE_256, NULL},
+ {AES_KEY_SIZE_128, NULL},
+ {AES_KEY_SIZE_192, NULL},
+ {AES_KEY_SIZE_256, NULL}};
static ossl_inline int io_setup(unsigned n, aio_context_t *ctx)
{
@@ -324,6 +335,129 @@ int afalg_fin_cipher_aio(afalg_aio *aio, int sfd,
unsigned char *buf,
return 1;
}
+int afalg_fin_gcm_aio(EVP_CIPHER_CTX *ctx, int sfd, unsigned char *buf,
+ size_t len)
+{
+afalg_gcm_ctx *gctx;
+afalg_ctx *actx;
+afalg_aio *aio;
+int retry = 0;
+unsigned int done = 0;
+struct iocb *cb;
+struct timespec timeout;
+struct io_event events[MAX_INFLIGHTS];
+struct iovec iov[2];
+u_int64_t eval = 0;
+int r;
+
+timeout.tv_sec = 0;
+timeout.tv_nsec = 0;
+gctx = (afalg_gcm_ctx *) EVP_CIPHER_CTX_get_cipher_data(ctx);
+actx = (afalg_ctx *)>ctx;
+aio = >aio;
+
+/* if efd has not been initialised yet do it here */
+if (aio->mode == MODE_UNINIT) {
+r = afalg_setup_async_event_notification(aio);
+if (r == 0)
+return 0;
+}
+
+cb = &(aio->cbt[0 % MAX_INFLIGHTS]);
+memset(cb, '\0', sizeof(*cb));
+
+/* iov that describes input data */
+iov[0].iov_base = (void *)EVP_CIPHER_CTX_buf_noconst(ctx);
+iov[0].iov_len = gctx->aad_len;
+iov[1].iov_base = (unsigned char *)buf;
+iov[1].iov_len = len;
+
+cb->aio_fildes = sfd;
+cb->aio_lio_opcode = IOCB_CMD_PREADV;
+/*
+ * The pointer has to be converted to unsigned value first to avoid
+ * sign extension on cast to 64 bit value in 32-bit builds
+ */
+cb->aio_buf = (size_t)iov;
+cb->aio_offset = 0;
+cb->aio_data = 0;
+cb->aio_nbytes = 2;
+cb->aio_flags = IOCB_FLAG_RESFD;
+cb->aio_resfd = aio->efd;
+
+/*
+ * Perform AIO read on AFALG socket, this in turn performs an async
+ * crypto operation in kernel space
+ */
+r = io_read(aio->aio_ctx, 1, );
+if (r < 0) {
+ALG_PWARN("%s: io_read failed : ", __func__);
+return 0;
+}
+
+do {
+/* While AIO read is being performed pause job */
+ASYNC_pause_job();
+
+/* Check for completion of AIO read */
+r = read(aio->efd, , sizeof(eval));
+if (r < 0) {
+if (errno == EAGAIN || errno == EWOULDBLOCK)
+continue;
+ALG_PERR("%s: read failed for event fd : ", __func__);
+return 0;
+} else if (r == 0 || eval <= 0) {
+ALG_WARN("%s: eventfd read %d bytes, eval = %lu\n", __func__, r,
+ eval);
+}
+if (eval > 0) {
+
+