summaryrefslogtreecommitdiff
path: root/usr/src/common
diff options
context:
space:
mode:
authorMatt Barden <matt.barden@nexenta.com>2017-09-04 07:25:59 -0500
committerGordon Ross <gwr@nexenta.com>2017-11-30 19:44:43 -0500
commitcd964fce751ca752af4158842063a9579a2d4331 (patch)
tree968b949de63f645bbbd84739221812eb3093530d /usr/src/common
parent6dfcdabd85f09409c5d2f9fb25a3013384ffaf74 (diff)
downloadillumos-joyent-cd964fce751ca752af4158842063a9579a2d4331.tar.gz
5869 Need AES CMAC support in KCF+PKCS11
Portions contributed by: Jason King <jason.king@joyent.com> Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Dan McDonald <danmcd@joyent.com> Approved by: Gordon Ross <gwr@nexenta.com>
Diffstat (limited to 'usr/src/common')
-rw-r--r--usr/src/common/crypto/aes/aes_impl.h3
-rw-r--r--usr/src/common/crypto/aes/aes_modes.c2
-rw-r--r--usr/src/common/crypto/modes/cbc.c190
-rw-r--r--usr/src/common/crypto/modes/ctr.c24
-rw-r--r--usr/src/common/crypto/modes/modes.c218
-rw-r--r--usr/src/common/crypto/modes/modes.h15
6 files changed, 412 insertions, 40 deletions
diff --git a/usr/src/common/crypto/aes/aes_impl.h b/usr/src/common/crypto/aes/aes_impl.h
index d44e261dda..d73729c03d 100644
--- a/usr/src/common/crypto/aes/aes_impl.h
+++ b/usr/src/common/crypto/aes/aes_impl.h
@@ -159,7 +159,8 @@ typedef enum aes_mech_type {
AES_CTR_MECH_INFO_TYPE, /* SUN_CKM_AES_CTR */
AES_CCM_MECH_INFO_TYPE, /* SUN_CKM_AES_CCM */
AES_GCM_MECH_INFO_TYPE, /* SUN_CKM_AES_GCM */
- AES_GMAC_MECH_INFO_TYPE /* SUN_CKM_AES_GMAC */
+ AES_GMAC_MECH_INFO_TYPE, /* SUN_CKM_AES_GMAC */
+ AES_CMAC_MECH_INFO_TYPE /* SUN_CKM_AES_CMAC */
} aes_mech_type_t;
#endif /* _KERNEL */
diff --git a/usr/src/common/crypto/aes/aes_modes.c b/usr/src/common/crypto/aes/aes_modes.c
index a41f4d9fe4..884bfa934c 100644
--- a/usr/src/common/crypto/aes/aes_modes.c
+++ b/usr/src/common/crypto/aes/aes_modes.c
@@ -93,7 +93,7 @@ aes_encrypt_contiguous_blocks(void *ctx, char *data, size_t length,
out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
aes_xor_block);
#endif
- } else if (aes_ctx->ac_flags & CBC_MODE) {
+ } else if (aes_ctx->ac_flags & (CBC_MODE|CMAC_MODE)) {
rv = cbc_encrypt_contiguous_blocks(ctx,
data, length, out, AES_BLOCK_LEN, aes_encrypt_block,
aes_copy_block, aes_xor_block);
diff --git a/usr/src/common/crypto/modes/cbc.c b/usr/src/common/crypto/modes/cbc.c
index 3fb17ee173..69f43eba61 100644
--- a/usr/src/common/crypto/modes/cbc.c
+++ b/usr/src/common/crypto/modes/cbc.c
@@ -21,6 +21,7 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _KERNEL
@@ -30,10 +31,16 @@
#include <security/cryptoki.h>
#endif
+#include <sys/debug.h>
#include <sys/types.h>
#include <modes/modes.h>
#include <sys/crypto/common.h>
#include <sys/crypto/impl.h>
+#include <aes/aes_impl.h>
+
+/* These are the CMAC Rb constants from NIST SP 800-38B */
+#define CONST_RB_128 0x87
+#define CONST_RB_64 0x1B
/*
* Algorithm independent CBC functions.
@@ -56,7 +63,7 @@ cbc_encrypt_contiguous_blocks(cbc_ctx_t *ctx, char *data, size_t length,
uint8_t *out_data_2;
size_t out_data_1_len;
- if (length + ctx->cbc_remainder_len < block_size) {
+ if (length + ctx->cbc_remainder_len < ctx->max_remain) {
/* accumulate bytes here and return */
bcopy(datap,
(uint8_t *)ctx->cbc_remainder + ctx->cbc_remainder_len,
@@ -97,7 +104,8 @@ cbc_encrypt_contiguous_blocks(cbc_ctx_t *ctx, char *data, size_t length,
ctx->cbc_lastp = blockp;
lastp = blockp;
- if (ctx->cbc_remainder_len > 0) {
+ if ((ctx->cbc_flags & CMAC_MODE) == 0 &&
+ ctx->cbc_remainder_len > 0) {
bcopy(blockp, ctx->cbc_copy_to,
ctx->cbc_remainder_len);
bcopy(blockp + ctx->cbc_remainder_len, datap,
@@ -110,22 +118,31 @@ cbc_encrypt_contiguous_blocks(cbc_ctx_t *ctx, char *data, size_t length,
*/
xor_block(blockp, lastp);
encrypt(ctx->cbc_keysched, lastp, lastp);
- crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
- &out_data_1_len, &out_data_2, block_size);
- /* copy block to where it belongs */
- if (out_data_1_len == block_size) {
- copy_block(lastp, out_data_1);
- } else {
- bcopy(lastp, out_data_1, out_data_1_len);
- if (out_data_2 != NULL) {
- bcopy(lastp + out_data_1_len,
- out_data_2,
- block_size - out_data_1_len);
+ /*
+ * CMAC doesn't output until encrypt_final
+ */
+ if ((ctx->cbc_flags & CMAC_MODE) == 0) {
+ crypto_get_ptrs(out, &iov_or_mp, &offset,
+ &out_data_1, &out_data_1_len,
+ &out_data_2, block_size);
+
+ /* copy block to where it belongs */
+ if (out_data_1_len == block_size) {
+ copy_block(lastp, out_data_1);
+ } else {
+ bcopy(lastp, out_data_1,
+ out_data_1_len);
+ if (out_data_2 != NULL) {
+ bcopy(lastp + out_data_1_len,
+ out_data_2,
+ block_size -
+ out_data_1_len);
+ }
}
+ /* update offset */
+ out->cd_offset += block_size;
}
- /* update offset */
- out->cd_offset += block_size;
}
/* Update pointer to next block of data to be processed. */
@@ -139,7 +156,7 @@ cbc_encrypt_contiguous_blocks(cbc_ctx_t *ctx, char *data, size_t length,
remainder = (size_t)&data[length] - (size_t)datap;
/* Incomplete last block. */
- if (remainder > 0 && remainder < block_size) {
+ if (remainder > 0 && remainder < ctx->max_remain) {
bcopy(datap, ctx->cbc_remainder, remainder);
ctx->cbc_remainder_len = remainder;
ctx->cbc_copy_to = datap;
@@ -299,14 +316,19 @@ cbc_init_ctx(cbc_ctx_t *cbc_ctx, char *param, size_t param_len,
cbc_ctx->cbc_lastp = (uint8_t *)&cbc_ctx->cbc_iv[0];
cbc_ctx->cbc_flags |= CBC_MODE;
+ cbc_ctx->max_remain = block_size;
return (CRYPTO_SUCCESS);
}
/* ARGSUSED */
-void *
-cbc_alloc_ctx(int kmflag)
+static void *
+cbc_cmac_alloc_ctx(int kmflag, uint32_t mode)
{
cbc_ctx_t *cbc_ctx;
+ uint32_t modeval = mode & (CBC_MODE|CMAC_MODE);
+
+ /* Only one of the two modes can be set */
+ VERIFY(modeval == CBC_MODE || modeval == CMAC_MODE);
#ifdef _KERNEL
if ((cbc_ctx = kmem_zalloc(sizeof (cbc_ctx_t), kmflag)) == NULL)
@@ -315,6 +337,136 @@ cbc_alloc_ctx(int kmflag)
#endif
return (NULL);
- cbc_ctx->cbc_flags = CBC_MODE;
+ cbc_ctx->cbc_flags = mode;
return (cbc_ctx);
}
+
+void *
+cbc_alloc_ctx(int kmflag)
+{
+ return (cbc_cmac_alloc_ctx(kmflag, CBC_MODE));
+}
+
+/*
+ * Algorithms for supporting AES-CMAC
+ * NOTE: CMAC is generally just a wrapper for CBC
+ */
+
+void *
+cmac_alloc_ctx(int kmflag)
+{
+ return (cbc_cmac_alloc_ctx(kmflag, CMAC_MODE));
+}
+
+
+/*
+ * Typically max_remain is set to block_size - 1, since we usually
+ * will process the data once we have a full block. However with CMAC,
+ * we must preprocess the final block of data. Since we cannot know
+ * when we've received the final block of data until the _final() method
+ * is called, we must not process the last block of data until we know
+ * it is the last block, or we receive a new block of data. As such,
+ * max_remain for CMAC is block_size + 1.
+ */
+int
+cmac_init_ctx(cbc_ctx_t *cbc_ctx, size_t block_size)
+{
+ /*
+ * CMAC is only approved for block sizes 64 and 128 bits /
+ * 8 and 16 bytes.
+ */
+
+ if (block_size != 16 && block_size != 8)
+ return (CRYPTO_INVALID_CONTEXT);
+
+ /*
+ * For CMAC, cbc_iv is always 0.
+ */
+
+ cbc_ctx->cbc_iv[0] = 0;
+ cbc_ctx->cbc_iv[1] = 0;
+
+ cbc_ctx->cbc_lastp = (uint8_t *)&cbc_ctx->cbc_iv[0];
+ cbc_ctx->cbc_flags |= CMAC_MODE;
+
+ cbc_ctx->max_remain = block_size + 1;
+ return (CRYPTO_SUCCESS);
+}
+
+/*
+ * Left shifts blocks by one and returns the leftmost bit
+ */
+static uint8_t
+cmac_left_shift_block_by1(uint8_t *block, size_t block_size)
+{
+ uint8_t carry = 0, old;
+ size_t i;
+ for (i = block_size; i > 0; i--) {
+ old = carry;
+ carry = (block[i - 1] & 0x80) ? 1 : 0;
+ block[i - 1] = (block[i - 1] << 1) | old;
+ }
+ return (carry);
+}
+
+/*
+ * Generate subkeys to preprocess the last block according to RFC 4493.
+ * Store the final block_size MAC generated in 'out'.
+ */
+int
+cmac_mode_final(cbc_ctx_t *cbc_ctx, crypto_data_t *out,
+ int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
+ void (*xor_block)(uint8_t *, uint8_t *))
+{
+ uint8_t buf[AES_BLOCK_LEN] = {0};
+ uint8_t *M_last = (uint8_t *)cbc_ctx->cbc_remainder;
+ size_t length = cbc_ctx->cbc_remainder_len;
+ size_t block_size = cbc_ctx->max_remain - 1;
+ uint8_t const_rb;
+
+ if (length > block_size)
+ return (CRYPTO_INVALID_CONTEXT);
+
+ if (out->cd_length < block_size)
+ return (CRYPTO_DATA_LEN_RANGE);
+
+ if (block_size == 16)
+ const_rb = CONST_RB_128;
+ else if (block_size == 8)
+ const_rb = CONST_RB_64;
+ else
+ return (CRYPTO_INVALID_CONTEXT);
+
+ /* k_0 = E_k(0) */
+ encrypt_block(cbc_ctx->cbc_keysched, buf, buf);
+
+ if (cmac_left_shift_block_by1(buf, block_size))
+ buf[block_size - 1] ^= const_rb;
+
+ if (length == block_size) {
+ /* Last block complete, so m_n = k_1 + m_n' */
+ xor_block(buf, M_last);
+ xor_block(cbc_ctx->cbc_lastp, M_last);
+ encrypt_block(cbc_ctx->cbc_keysched, M_last, M_last);
+ } else {
+ /* Last block incomplete, so m_n = k_2 + (m_n' | 100...0_bin) */
+ if (cmac_left_shift_block_by1(buf, block_size))
+ buf[block_size - 1] ^= const_rb;
+
+ M_last[length] = 0x80;
+ bzero(M_last + length + 1, block_size - length - 1);
+ xor_block(buf, M_last);
+ xor_block(cbc_ctx->cbc_lastp, M_last);
+ encrypt_block(cbc_ctx->cbc_keysched, M_last, M_last);
+ }
+
+ /*
+ * zero out the sub-key.
+ */
+#ifndef _KERNEL
+ explicit_bzero(&buf, sizeof (buf));
+#else
+ bzero(&buf, sizeof (buf));
+#endif
+ return (crypto_put_output_data(M_last, out, block_size));
+}
diff --git a/usr/src/common/crypto/modes/ctr.c b/usr/src/common/crypto/modes/ctr.c
index e44dc3e642..919ed3ab53 100644
--- a/usr/src/common/crypto/modes/ctr.c
+++ b/usr/src/common/crypto/modes/ctr.c
@@ -169,13 +169,9 @@ ctr_mode_final(ctr_ctx_t *ctx, crypto_data_t *out,
int (*encrypt_block)(const void *, const uint8_t *, uint8_t *))
{
uint8_t *lastp;
- void *iov_or_mp;
- offset_t offset;
- uint8_t *out_data_1;
- uint8_t *out_data_2;
- size_t out_data_1_len;
uint8_t *p;
int i;
+ int rv;
if (out->cd_length < ctx->ctr_remainder_len)
return (CRYPTO_DATA_LEN_RANGE);
@@ -189,23 +185,17 @@ ctr_mode_final(ctr_ctx_t *ctx, crypto_data_t *out,
p[i] ^= lastp[i];
}
- crypto_init_ptrs(out, &iov_or_mp, &offset);
- crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
- &out_data_1_len, &out_data_2, ctx->ctr_remainder_len);
-
- bcopy(p, out_data_1, out_data_1_len);
- if (out_data_2 != NULL) {
- bcopy((uint8_t *)p + out_data_1_len,
- out_data_2, ctx->ctr_remainder_len - out_data_1_len);
+ rv = crypto_put_output_data(p, out, ctx->ctr_remainder_len);
+ if (rv == CRYPTO_SUCCESS) {
+ out->cd_offset += ctx->ctr_remainder_len;
+ ctx->ctr_remainder_len = 0;
}
- out->cd_offset += ctx->ctr_remainder_len;
- ctx->ctr_remainder_len = 0;
- return (CRYPTO_SUCCESS);
+ return (rv);
}
int
ctr_init_ctx(ctr_ctx_t *ctr_ctx, ulong_t count, uint8_t *cb,
-void (*copy_block)(uint8_t *, uint8_t *))
+ void (*copy_block)(uint8_t *, uint8_t *))
{
uint64_t upper_mask = 0;
uint64_t lower_mask = 0;
diff --git a/usr/src/common/crypto/modes/modes.c b/usr/src/common/crypto/modes/modes.c
index 19bf8cc16c..fbf66c0531 100644
--- a/usr/src/common/crypto/modes/modes.c
+++ b/usr/src/common/crypto/modes/modes.c
@@ -21,10 +21,14 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _KERNEL
#include <stdlib.h>
+#include <assert.h>
+#include <strings.h>
#endif
#include <sys/strsun.h>
@@ -170,8 +174,8 @@ crypto_free_mode_ctx(void *ctx)
{
common_ctx_t *common_ctx = (common_ctx_t *)ctx;
- switch (common_ctx->cc_flags &
- (ECB_MODE|CBC_MODE|CTR_MODE|CCM_MODE|GCM_MODE|GMAC_MODE)) {
+ switch (common_ctx->cc_flags & (ECB_MODE|CBC_MODE|CMAC_MODE|CTR_MODE|
+ CCM_MODE|GCM_MODE|GMAC_MODE)) {
case ECB_MODE:
#ifdef _KERNEL
kmem_free(common_ctx, sizeof (ecb_ctx_t));
@@ -181,6 +185,7 @@ crypto_free_mode_ctx(void *ctx)
break;
case CBC_MODE:
+ case CMAC_MODE:
#ifdef _KERNEL
kmem_free(common_ctx, sizeof (cbc_ctx_t));
#else
@@ -225,3 +230,212 @@ crypto_free_mode_ctx(void *ctx)
#endif
}
}
+
+/*
+ * Utility routine to apply the command, 'cmd', to the
+ * data in the uio structure.
+ */
+int
+crypto_uio_data(crypto_data_t *data, uchar_t *buf, int len, cmd_type_t cmd,
+ void *digest_ctx, void (*update)())
+{
+ uio_t *uiop = data->cd_uio;
+ off_t offset = data->cd_offset;
+ size_t length = len;
+ uint_t vec_idx;
+ size_t cur_len;
+ uchar_t *datap;
+
+#ifdef _KERNEL
+ ASSERT3U(data->cd_format, ==, CRYPTO_DATA_UIO);
+#else
+ assert(data->cd_format == CRYPTO_DATA_UIO);
+#endif
+ if (uiop->uio_segflg != UIO_SYSSPACE) {
+ return (CRYPTO_ARGUMENTS_BAD);
+ }
+
+ /*
+ * Jump to the first iovec containing data to be
+ * processed.
+ */
+ for (vec_idx = 0; vec_idx < uiop->uio_iovcnt &&
+ offset >= uiop->uio_iov[vec_idx].iov_len;
+ offset -= uiop->uio_iov[vec_idx++].iov_len)
+ ;
+
+ if (vec_idx == uiop->uio_iovcnt) {
+ /*
+ * The caller specified an offset that is larger than
+ * the total size of the buffers it provided.
+ */
+ return (CRYPTO_DATA_LEN_RANGE);
+ }
+
+ while (vec_idx < uiop->uio_iovcnt && length > 0) {
+ cur_len = MIN(uiop->uio_iov[vec_idx].iov_len -
+ offset, length);
+
+ datap = (uchar_t *)(uiop->uio_iov[vec_idx].iov_base +
+ offset);
+ switch (cmd) {
+ case COPY_FROM_DATA:
+ bcopy(datap, buf, cur_len);
+ buf += cur_len;
+ break;
+ case COPY_TO_DATA:
+ bcopy(buf, datap, cur_len);
+ buf += cur_len;
+ break;
+ case COMPARE_TO_DATA:
+ if (bcmp(datap, buf, cur_len))
+ return (CRYPTO_SIGNATURE_INVALID);
+ buf += cur_len;
+ break;
+ case MD5_DIGEST_DATA:
+ case SHA1_DIGEST_DATA:
+ case SHA2_DIGEST_DATA:
+ case GHASH_DATA:
+ update(digest_ctx, datap, cur_len);
+ break;
+ }
+
+ length -= cur_len;
+ vec_idx++;
+ offset = 0;
+ }
+
+ if (vec_idx == uiop->uio_iovcnt && length > 0) {
+ /*
+ * The end of the specified iovec's was reached but
+ * the length requested could not be processed.
+ */
+ switch (cmd) {
+ case COPY_TO_DATA:
+ data->cd_length = len;
+ return (CRYPTO_BUFFER_TOO_SMALL);
+ default:
+ return (CRYPTO_DATA_LEN_RANGE);
+ }
+ }
+
+ return (CRYPTO_SUCCESS);
+}
+
+/*
+ * Utility routine to apply the command, 'cmd', to the
+ * data in the mblk structure.
+ */
+int
+crypto_mblk_data(crypto_data_t *data, uchar_t *buf, int len, cmd_type_t cmd,
+ void *digest_ctx, void (*update)())
+{
+ off_t offset = data->cd_offset;
+ size_t length = len;
+ mblk_t *mp;
+ size_t cur_len;
+ uchar_t *datap;
+
+#ifdef _KERNEL
+ ASSERT3U(data->cd_format, ==, CRYPTO_DATA_MBLK);
+#else
+ assert(data->cd_format == CRYPTO_DATA_MBLK);
+#endif
+ /*
+ * Jump to the first mblk_t containing data to be processed.
+ */
+ for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp);
+ offset -= MBLKL(mp), mp = mp->b_cont)
+ ;
+ if (mp == NULL) {
+ /*
+ * The caller specified an offset that is larger
+ * than the total size of the buffers it provided.
+ */
+ return (CRYPTO_DATA_LEN_RANGE);
+ }
+
+ /*
+ * Now do the processing on the mblk chain.
+ */
+ while (mp != NULL && length > 0) {
+ cur_len = MIN(MBLKL(mp) - offset, length);
+
+ datap = (uchar_t *)(mp->b_rptr + offset);
+ switch (cmd) {
+ case COPY_FROM_DATA:
+ bcopy(datap, buf, cur_len);
+ buf += cur_len;
+ break;
+ case COPY_TO_DATA:
+ bcopy(buf, datap, cur_len);
+ buf += cur_len;
+ break;
+ case COMPARE_TO_DATA:
+ if (bcmp(datap, buf, cur_len))
+ return (CRYPTO_SIGNATURE_INVALID);
+ buf += cur_len;
+ break;
+ case MD5_DIGEST_DATA:
+ case SHA1_DIGEST_DATA:
+ case SHA2_DIGEST_DATA:
+ case GHASH_DATA:
+ update(digest_ctx, datap, cur_len);
+ break;
+ }
+
+ length -= cur_len;
+ offset = 0;
+ mp = mp->b_cont;
+ }
+
+ if (mp == NULL && length > 0) {
+ /*
+ * The end of the mblk was reached but the length
+ * requested could not be processed.
+ */
+ switch (cmd) {
+ case COPY_TO_DATA:
+ data->cd_length = len;
+ return (CRYPTO_BUFFER_TOO_SMALL);
+ default:
+ return (CRYPTO_DATA_LEN_RANGE);
+ }
+ }
+
+ return (CRYPTO_SUCCESS);
+}
+
+/*
+ * Utility routine to copy a buffer to a crypto_data structure.
+ */
+int
+crypto_put_output_data(uchar_t *buf, crypto_data_t *output, int len)
+{
+ switch (output->cd_format) {
+ case CRYPTO_DATA_RAW:
+ if (MAXOFF_T - output->cd_offset < (off_t)len) {
+ return (CRYPTO_ARGUMENTS_BAD);
+ }
+ if (output->cd_raw.iov_len < len + output->cd_offset) {
+ output->cd_length = len;
+ return (CRYPTO_BUFFER_TOO_SMALL);
+ }
+ bcopy(buf, (uchar_t *)(output->cd_raw.iov_base +
+ output->cd_offset), len);
+ break;
+
+ case CRYPTO_DATA_UIO:
+ return (crypto_uio_data(output, buf, len,
+ COPY_TO_DATA, NULL, NULL));
+
+ case CRYPTO_DATA_MBLK:
+ return (crypto_mblk_data(output, buf, len,
+ COPY_TO_DATA, NULL, NULL));
+
+ default:
+ return (CRYPTO_ARGUMENTS_BAD);
+ }
+
+ return (CRYPTO_SUCCESS);
+}
diff --git a/usr/src/common/crypto/modes/modes.h b/usr/src/common/crypto/modes/modes.h
index 26f3b37b0e..efb3770eea 100644
--- a/usr/src/common/crypto/modes/modes.h
+++ b/usr/src/common/crypto/modes/modes.h
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _COMMON_CRYPTO_MODES_H
@@ -46,6 +48,7 @@ extern "C" {
#define CCM_MODE 0x00000010
#define GCM_MODE 0x00000020
#define GMAC_MODE 0x00000040
+#define CMAC_MODE 0x00000080
/*
* cc_keysched: Pointer to key schedule.
@@ -100,9 +103,13 @@ typedef struct ecb_ctx {
#define ecb_copy_to ecb_common.cc_copy_to
#define ecb_flags ecb_common.cc_flags
+/*
+ * max_remain max bytes in cbc_remainder
+ */
typedef struct cbc_ctx {
struct common_ctx cbc_common;
uint64_t cbc_lastblock[2];
+ size_t max_remain;
} cbc_ctx_t;
#define cbc_keysched cbc_common.cc_keysched
@@ -345,12 +352,18 @@ extern int gcm_decrypt_final(gcm_ctx_t *, crypto_data_t *, size_t,
int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
void (*xor_block)(uint8_t *, uint8_t *));
+extern int cmac_mode_final(cbc_ctx_t *, crypto_data_t *,
+ int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
+ void (*xor_block)(uint8_t *, uint8_t *));
+
extern int ctr_mode_final(ctr_ctx_t *, crypto_data_t *,
int (*encrypt_block)(const void *, const uint8_t *, uint8_t *));
extern int cbc_init_ctx(cbc_ctx_t *, char *, size_t, size_t,
void (*copy_block)(uint8_t *, uint64_t *));
+extern int cmac_init_ctx(cbc_ctx_t *, size_t);
+
extern int ctr_init_ctx(ctr_ctx_t *, ulong_t, uint8_t *,
void (*copy_block)(uint8_t *, uint8_t *));
@@ -379,12 +392,14 @@ extern void crypto_get_ptrs(crypto_data_t *, void **, offset_t *,
extern void *ecb_alloc_ctx(int);
extern void *cbc_alloc_ctx(int);
+extern void *cmac_alloc_ctx(int);
extern void *ctr_alloc_ctx(int);
extern void *ccm_alloc_ctx(int);
extern void *gcm_alloc_ctx(int);
extern void *gmac_alloc_ctx(int);
extern void crypto_free_mode_ctx(void *);
extern void gcm_set_kmflag(gcm_ctx_t *, int);
+extern int crypto_put_output_data(uchar_t *, crypto_data_t *, int);
#ifdef __cplusplus
}