summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2017-12-01 12:46:20 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2017-12-01 12:46:20 +0000
commit3f77d0944006d98d130349a35d3bf65399df67b6 (patch)
treef8fd50737ec835829e925262e94d5a46782df75b /usr/src
parent319ffd7b00d357d8bcc5a3ab337a6a870bf0faa6 (diff)
parentcd964fce751ca752af4158842063a9579a2d4331 (diff)
downloadillumos-joyent-3f77d0944006d98d130349a35d3bf65399df67b6.tar.gz
[illumos-gate merge]
commit cd964fce751ca752af4158842063a9579a2d4331 5869 Need AES CMAC support in KCF+PKCS11 commit 6dfcdabd85f09409c5d2f9fb25a3013384ffaf74 8800 loader: use the same option list for dhcp discovery and request commit dfbc6f2daa6bb8fc06fad985ead27d5db30eab3a 8799 loader: Always issue the pxe request commit 494a2e4857c10ebf74b8a5652d96466bd9e02f2c 8865 nightly shouldn't depend on specific /usr/bin/egrep behavior
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/boot/lib/libstand/bootp.c68
-rw-r--r--usr/src/boot/lib/libstand/bootp.h8
-rw-r--r--usr/src/boot/lib/libstand/net.h8
-rw-r--r--usr/src/boot/sys/boot/common/dev_net.c2
-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
-rw-r--r--usr/src/lib/pkcs11/libsoftcrypto/common/mapfile-vers4
-rw-r--r--usr/src/lib/pkcs11/pkcs11_kernel/Makefile.com3
-rw-r--r--usr/src/lib/pkcs11/pkcs11_softtoken/common/softAESCrypt.c252
-rw-r--r--usr/src/lib/pkcs11/pkcs11_softtoken/common/softCrypt.h24
-rw-r--r--usr/src/lib/pkcs11/pkcs11_softtoken/common/softEncryptUtil.c90
-rw-r--r--usr/src/lib/pkcs11/pkcs11_softtoken/common/softSignUtil.c67
-rw-r--r--usr/src/lib/pkcs11/pkcs11_softtoken/common/softSlotToken.c6
-rw-r--r--usr/src/lib/pkcs11/pkcs11_softtoken/common/softVerifyUtil.c67
-rw-r--r--usr/src/pkg/manifests/system-test-cryptotest.mf52
-rw-r--r--usr/src/test/Makefile2
-rw-r--r--usr/src/test/crypto-tests/Makefile20
-rw-r--r--usr/src/test/crypto-tests/cmd/Makefile20
-rw-r--r--usr/src/test/crypto-tests/cmd/kcf/Makefile38
-rw-r--r--usr/src/test/crypto-tests/cmd/kcf/cleanup.ksh18
-rw-r--r--usr/src/test/crypto-tests/cmd/kcf/setup.ksh18
-rw-r--r--usr/src/test/crypto-tests/cmd/scripts/Makefile38
-rw-r--r--usr/src/test/crypto-tests/cmd/scripts/cryptotest.ksh49
-rw-r--r--usr/src/test/crypto-tests/doc/Makefile36
-rw-r--r--usr/src/test/crypto-tests/doc/README60
-rw-r--r--usr/src/test/crypto-tests/runfiles/Makefile40
-rw-r--r--usr/src/test/crypto-tests/runfiles/default.run32
-rw-r--r--usr/src/test/crypto-tests/tests/Makefile20
-rw-r--r--usr/src/test/crypto-tests/tests/common/Makefile33
-rw-r--r--usr/src/test/crypto-tests/tests/common/cryptotest.h102
-rw-r--r--usr/src/test/crypto-tests/tests/common/cryptotest_kcf.c378
-rw-r--r--usr/src/test/crypto-tests/tests/common/cryptotest_pkcs.c401
-rw-r--r--usr/src/test/crypto-tests/tests/common/testfuncs.c268
-rw-r--r--usr/src/test/crypto-tests/tests/modes/Makefile21
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/Makefile21
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/Makefile.subdirs82
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/cbc/Makefile20
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/cbc/aes_cbc.c69
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/cbc/aes_cbc.h173
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/ccm/Makefile20
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/ccm/aes_ccm.c120
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/ccm/aes_ccm.h481
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/cmac/Makefile20
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/cmac/aes_cmac.c51
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/cmac/aes_cmac.h72
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/ctr/Makefile20
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/ctr/aes_ctr.c85
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/ctr/aes_ctr.h289
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/ecb/Makefile20
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/ecb/aes_ecb.c60
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/ecb/aes_ecb.h110
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/gcm/Makefile20
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/gcm/aes_gcm.c87
-rw-r--r--usr/src/test/crypto-tests/tests/modes/aes/gcm/aes_gcm.h737
-rw-r--r--usr/src/tools/scripts/nightly.sh1
-rw-r--r--usr/src/uts/common/crypto/core/kcf_cryptoadm.c12
-rw-r--r--usr/src/uts/common/crypto/core/kcf_mech_tabs.c6
-rw-r--r--usr/src/uts/common/crypto/core/kcf_prov_lib.c198
-rw-r--r--usr/src/uts/common/crypto/io/aes.c177
-rw-r--r--usr/src/uts/common/crypto/io/crypto.c210
-rw-r--r--usr/src/uts/common/crypto/io/dprov.c16
-rw-r--r--usr/src/uts/common/sys/crypto/common.h1
-rw-r--r--usr/src/uts/common/sys/crypto/impl.h1
-rw-r--r--usr/src/uts/common/sys/crypto/ioctl.h11
-rw-r--r--usr/src/uts/common/sys/crypto/spi.h4
69 files changed, 5502 insertions, 389 deletions
diff --git a/usr/src/boot/lib/libstand/bootp.c b/usr/src/boot/lib/libstand/bootp.c
index 2dac122970..3e706da761 100644
--- a/usr/src/boot/lib/libstand/bootp.c
+++ b/usr/src/boot/lib/libstand/bootp.c
@@ -88,9 +88,38 @@ struct in_addr dhcp_serverip;
struct bootp *bootp_response;
size_t bootp_response_size;
+static void
+bootp_fill_request(unsigned char *bp_vend)
+{
+ /*
+ * We are booting from PXE, we want to send the string
+ * 'PXEClient' to the DHCP server so you have the option of
+ * only responding to PXE aware dhcp requests.
+ */
+ bp_vend[0] = TAG_CLASSID;
+ bp_vend[1] = 9;
+ bcopy("PXEClient", &bp_vend[2], 9);
+ bp_vend[11] = TAG_USER_CLASS;
+ /* len of each user class + number of user class */
+ bp_vend[12] = 8;
+ /* len of the first user class */
+ bp_vend[13] = 7;
+ bcopy("illumos", &bp_vend[14], 7);
+ bp_vend[21] = TAG_PARAM_REQ;
+ bp_vend[22] = 7;
+ bp_vend[23] = TAG_SUBNET_MASK;
+ bp_vend[24] = TAG_GATEWAY;
+ bp_vend[25] = TAG_HOSTNAME;
+ bp_vend[26] = TAG_SWAPSERVER;
+ bp_vend[27] = TAG_ROOTPATH;
+ bp_vend[28] = TAG_INTF_MTU;
+ bp_vend[29] = TAG_SERVERID;
+ bp_vend[30] = TAG_END;
+}
+
/* Fetch required bootp infomation */
void
-bootp(int sock, int flag)
+bootp(int sock)
{
void *pkt;
struct iodesc *d;
@@ -131,34 +160,7 @@ bootp(int sock, int flag)
bp->bp_vend[4] = TAG_DHCP_MSGTYPE;
bp->bp_vend[5] = 1;
bp->bp_vend[6] = DHCPDISCOVER;
-
- /*
- * If we are booting from PXE, we want to send the string
- * 'PXEClient' to the DHCP server so you have the option of
- * only responding to PXE aware dhcp requests.
- */
- if (flag & BOOTP_PXE) {
- bp->bp_vend[7] = TAG_CLASSID;
- bp->bp_vend[8] = 9;
- bcopy("PXEClient", &bp->bp_vend[9], 9);
- bp->bp_vend[18] = TAG_USER_CLASS;
- /* len of each user class + number of user class */
- bp->bp_vend[19] = 8;
- /* len of the first user class */
- bp->bp_vend[20] = 7;
- bcopy("illumos", &bp->bp_vend[21], 7);
- bp->bp_vend[28] = TAG_PARAM_REQ;
- bp->bp_vend[29] = 7;
- bp->bp_vend[30] = TAG_ROOTPATH;
- bp->bp_vend[31] = TAG_HOSTNAME;
- bp->bp_vend[32] = TAG_SWAPSERVER;
- bp->bp_vend[33] = TAG_GATEWAY;
- bp->bp_vend[34] = TAG_SUBNET_MASK;
- bp->bp_vend[35] = TAG_INTF_MTU;
- bp->bp_vend[36] = TAG_SERVERID;
- bp->bp_vend[37] = TAG_END;
- } else
- bp->bp_vend[7] = TAG_END;
+ bootp_fill_request(&bp->bp_vend[7]);
#else
bp->bp_vend[4] = TAG_END;
#endif
@@ -194,13 +196,7 @@ bootp(int sock, int flag)
bp->bp_vend[20] = 4;
leasetime = htonl(300);
bcopy(&leasetime, &bp->bp_vend[21], 4);
- if (flag & BOOTP_PXE) {
- bp->bp_vend[25] = TAG_CLASSID;
- bp->bp_vend[26] = 9;
- bcopy("PXEClient", &bp->bp_vend[27], 9);
- bp->bp_vend[36] = TAG_END;
- } else
- bp->bp_vend[25] = TAG_END;
+ bootp_fill_request(&bp->bp_vend[25]);
expected_dhcpmsgtype = DHCPACK;
diff --git a/usr/src/boot/lib/libstand/bootp.h b/usr/src/boot/lib/libstand/bootp.h
index c1aa218231..db68995fd1 100644
--- a/usr/src/boot/lib/libstand/bootp.h
+++ b/usr/src/boot/lib/libstand/bootp.h
@@ -1,5 +1,3 @@
-/* $NetBSD: bootp.h,v 1.4 1997/09/06 13:55:57 drochner Exp $ */
-
/*
* Bootstrap Protocol (BOOTP). RFC951 and RFC1048.
*
@@ -124,12 +122,6 @@ struct bootp {
#endif
/*
- * bootp flags
- */
-#define BOOTP_NONE 0x0000 /* No flags */
-#define BOOTP_PXE 0x0001 /* Booting from PXE. */
-
-/*
* "vendor" data permitted for CMU bootp clients.
*/
diff --git a/usr/src/boot/lib/libstand/net.h b/usr/src/boot/lib/libstand/net.h
index 14b84f0590..87228f5592 100644
--- a/usr/src/boot/lib/libstand/net.h
+++ b/usr/src/boot/lib/libstand/net.h
@@ -1,5 +1,3 @@
-/* $NetBSD: net.h,v 1.10 1995/10/20 00:46:30 cgd Exp $ */
-
/*
* Copyright (c) 1993 Adam Glass
* Copyright (c) 1992 Regents of the University of California.
@@ -17,7 +15,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
@@ -32,8 +30,6 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD$
*/
#ifndef _STAND_NET_H
@@ -120,7 +116,7 @@ ssize_t sendrecv(struct iodesc *,
void **, void **);
/* bootp/DHCP */
-void bootp(int, int);
+void bootp(int);
/* Utilities: */
char *ether_sprintf(u_char *);
diff --git a/usr/src/boot/sys/boot/common/dev_net.c b/usr/src/boot/sys/boot/common/dev_net.c
index 24e3d9291b..dfa7eb1f99 100644
--- a/usr/src/boot/sys/boot/common/dev_net.c
+++ b/usr/src/boot/sys/boot/common/dev_net.c
@@ -280,7 +280,7 @@ net_getparams(int sock)
d->myip = myip;
}
if (rc < 0)
- bootp(sock, BOOTP_NONE);
+ bootp(sock);
}
if (myip.s_addr != 0)
goto exit;
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
}
diff --git a/usr/src/lib/pkcs11/libsoftcrypto/common/mapfile-vers b/usr/src/lib/pkcs11/libsoftcrypto/common/mapfile-vers
index 293319c719..377db64fa5 100644
--- a/usr/src/lib/pkcs11/libsoftcrypto/common/mapfile-vers
+++ b/usr/src/lib/pkcs11/libsoftcrypto/common/mapfile-vers
@@ -49,6 +49,7 @@ SYMBOL_VERSION SUNWprivate {
aes_encrypt_block;
aes_encrypt_contiguous_blocks;
aes_init_keysched;
+ aes_xor_block;
arcfour_crypt;
arcfour_key_init;
big_One;
@@ -76,6 +77,9 @@ SYMBOL_VERSION SUNWprivate {
blowfish_encrypt_contiguous_blocks;
blowfish_init_keysched;
bytestring2bignum;
+ cbc_alloc_ctx;
+ cmac_init_ctx;
+ cmac_mode_final;
ctr_mode_final;
ctr_init_ctx;
des3_crunch_block;
diff --git a/usr/src/lib/pkcs11/pkcs11_kernel/Makefile.com b/usr/src/lib/pkcs11/pkcs11_kernel/Makefile.com
index d71ccc01aa..e44f6cfec0 100644
--- a/usr/src/lib/pkcs11/pkcs11_kernel/Makefile.com
+++ b/usr/src/lib/pkcs11/pkcs11_kernel/Makefile.com
@@ -59,12 +59,13 @@ ARCFOURDIR= $(SRC)/common/crypto/arcfour
BLOWFISHDIR= $(SRC)/common/crypto/blowfish
DESDIR= $(SRC)/common/crypto/des
ECCDIR= $(SRC)/common/crypto/ecc
+CRYPTDIR= $(SRC)/common/crypto
ST_DIR= $(SRC)/lib/pkcs11/pkcs11_softtoken/common
lint \
pics/kernelAttributeUtil.o := \
CPPFLAGS += -I$(AESDIR) -I$(BLOWFISHDIR) -I$(ARCFOURDIR) -I$(DESDIR) \
- -I$(ECCDIR)
+ -I$(ECCDIR) -I$(CRYPTDIR)
pics/kernelKeys.o := \
CPPFLAGS += -I$(ECCDIR)
pics/kernelSoftCommon.o := \
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softAESCrypt.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softAESCrypt.c
index 7f2810033b..bc8edcdc4c 100644
--- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softAESCrypt.c
+++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softAESCrypt.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#include <pthread.h>
@@ -29,10 +30,11 @@
#include <strings.h>
#include <sys/types.h>
#include <security/cryptoki.h>
+#include <aes_impl.h>
#include "softSession.h"
#include "softObject.h"
#include "softCrypt.h"
-#include <aes_impl.h>
+#include "softOps.h"
/*
* Allocate context for the active encryption or decryption operation, and
@@ -179,7 +181,8 @@ soft_aes_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
* AES allows any input length for C_Encrypt function with the
* mechanism CKM_AES_CBC_PAD and for C_EncryptUpdate function.
*/
- if ((!update) && (mechanism != CKM_AES_CBC_PAD)) {
+ if ((!update) && (mechanism != CKM_AES_CBC_PAD) &&
+ (mechanism != CKM_AES_CMAC)) {
if ((ulDataLen % AES_BLOCK_LEN) != 0) {
rv = CKR_DATA_LEN_RANGE;
goto cleanup;
@@ -201,6 +204,8 @@ soft_aes_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
*/
out_len = AES_BLOCK_LEN *
(ulDataLen / AES_BLOCK_LEN + 1);
+ } else if (mechanism == CKM_AES_CMAC) {
+ out_len = AES_BLOCK_LEN;
} else {
/*
* For non-padding mode, the output length will
@@ -247,6 +252,24 @@ soft_aes_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
* encryption until when more data comes in next
* C_EncryptUpdate or when C_EncryptFinal is called.
*/
+ out_buf = pEncrypted;
+
+ /*
+ * We prefer to let the underlying implementation of CMAC handle
+ * the storing of extra bytes, and no data is output until
+ * *_final, so skip that part of the following validation.
+ */
+ if (mechanism == CKM_AES_CMAC) {
+ if (pEncrypted == NULL) {
+ *pulEncryptedLen = ulDataLen;
+ return (CKR_OK);
+ }
+
+ remain = 0;
+ in_buf = pData;
+ goto do_encryption;
+ }
+
if ((total_len < AES_BLOCK_LEN) ||
((mechanism == CKM_AES_CBC_PAD) &&
(total_len == AES_BLOCK_LEN))) {
@@ -304,7 +327,6 @@ soft_aes_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
} else {
in_buf = pData;
}
- out_buf = pEncrypted;
}
do_encryption:
@@ -344,6 +366,9 @@ do_encryption:
break;
}
+ case CKM_AES_CMAC:
+ out_len = ulDataLen;
+ /*FALLTHRU*/
case CKM_AES_CBC:
case CKM_AES_CBC_PAD:
{
@@ -397,6 +422,13 @@ do_encryption:
(char *)tmpblock, AES_BLOCK_LEN, &out);
out_len += AES_BLOCK_LEN;
+ } else if (mechanism == CKM_AES_CMAC) {
+ out.cd_length = AES_BLOCK_LEN;
+ out.cd_raw.iov_base = (char *)out_buf;
+ out.cd_raw.iov_len = AES_BLOCK_LEN;
+
+ rc = cmac_mode_final(soft_aes_ctx->aes_cbc, &out,
+ aes_encrypt_block, aes_xor_block);
}
if (rc == 0) {
@@ -435,6 +467,13 @@ encrypt_failed:
if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len > 0)
rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
aes_encrypt_block);
+
+ /*
+ * Even though success means we've encrypted all of the input,
+ * we should still behave like the other functions and return
+ * the encrypted length in pulEncryptedLen
+ */
+ *pulEncryptedLen = ulDataLen;
}
} /* end switch */
@@ -790,6 +829,14 @@ decrypt_failed:
if (rc == CRYPTO_DATA_LEN_RANGE)
rc = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
}
+
+ /*
+ * Even though success means we've decrypted all of the input,
+ * we should still behave like the other functions and return
+ * the decrypted length in pulDataLen
+ */
+ *pulDataLen = ulEncryptedLen;
+
}
} /* end switch */
@@ -838,6 +885,26 @@ aes_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec)
cbc_ctx->cbc_lastp = (uint8_t *)cbc_ctx->cbc_iv;
cbc_ctx->cbc_flags |= CBC_MODE;
+ cbc_ctx->max_remain = AES_BLOCK_LEN;
+
+ return (cbc_ctx);
+}
+
+void *
+aes_cmac_ctx_init(void *key_sched, size_t size)
+{
+
+ cbc_ctx_t *cbc_ctx;
+
+ if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
+ return (NULL);
+
+ cbc_ctx->cbc_keysched = key_sched;
+ cbc_ctx->cbc_keysched_len = size;
+
+ cbc_ctx->cbc_lastp = (uint8_t *)cbc_ctx->cbc_iv;
+ cbc_ctx->cbc_flags |= CMAC_MODE;
+ cbc_ctx->max_remain = AES_BLOCK_LEN + 1;
return (cbc_ctx);
}
@@ -869,3 +936,182 @@ aes_ctr_ctx_init(void *key_sched, size_t size, uint8_t *param)
return (ctr_ctx);
}
+
+/*
+ * Allocate and initialize AES contexts for both signing and encrypting,
+ * saving both context pointers in the session struct. For general-length AES
+ * MAC, check the length in the parameter to see if it is in the right range.
+ */
+CK_RV
+soft_aes_sign_verify_init_common(soft_session_t *session_p,
+ CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, boolean_t sign_op)
+{
+ soft_aes_ctx_t *soft_aes_ctx;
+ CK_MECHANISM encrypt_mech;
+ CK_RV rv;
+
+ if (key_p->key_type != CKK_AES) {
+ return (CKR_KEY_TYPE_INCONSISTENT);
+ }
+
+ /* allocate memory for the sign/verify context */
+ soft_aes_ctx = malloc(sizeof (soft_aes_ctx_t));
+ if (soft_aes_ctx == NULL) {
+ return (CKR_HOST_MEMORY);
+ }
+
+ /* initialization vector is zero for AES CMAC */
+ bzero(soft_aes_ctx->ivec, AES_BLOCK_LEN);
+
+ switch (pMechanism->mechanism) {
+
+ case CKM_AES_CMAC_GENERAL:
+
+ if (pMechanism->ulParameterLen !=
+ sizeof (CK_MAC_GENERAL_PARAMS)) {
+ free(soft_aes_ctx);
+ return (CKR_MECHANISM_PARAM_INVALID);
+ }
+
+ if (*(CK_MAC_GENERAL_PARAMS *)pMechanism->pParameter >
+ AES_BLOCK_LEN) {
+ free(soft_aes_ctx);
+ return (CKR_MECHANISM_PARAM_INVALID);
+ }
+
+ soft_aes_ctx->mac_len = *((CK_MAC_GENERAL_PARAMS_PTR)
+ pMechanism->pParameter);
+
+ /*FALLTHRU*/
+ case CKM_AES_CMAC:
+
+ /*
+ * For non-general AES MAC, output is always block size
+ */
+ if (pMechanism->mechanism == CKM_AES_CMAC) {
+ soft_aes_ctx->mac_len = AES_BLOCK_LEN;
+ }
+
+ /* allocate a context for AES encryption */
+ encrypt_mech.mechanism = CKM_AES_CMAC;
+ encrypt_mech.pParameter = (void *)soft_aes_ctx->ivec;
+ encrypt_mech.ulParameterLen = AES_BLOCK_LEN;
+ rv = soft_encrypt_init_internal(session_p, &encrypt_mech,
+ key_p);
+ if (rv != CKR_OK) {
+ free(soft_aes_ctx);
+ return (rv);
+ }
+
+ (void) pthread_mutex_lock(&session_p->session_mutex);
+
+ if (sign_op) {
+ session_p->sign.context = soft_aes_ctx;
+ session_p->sign.mech.mechanism = pMechanism->mechanism;
+ } else {
+ session_p->verify.context = soft_aes_ctx;
+ session_p->verify.mech.mechanism =
+ pMechanism->mechanism;
+ }
+
+ (void) pthread_mutex_unlock(&session_p->session_mutex);
+
+ break;
+ }
+ return (CKR_OK);
+}
+
+/*
+ * Called by soft_sign(), soft_sign_final(), soft_verify() or
+ * soft_verify_final().
+ */
+CK_RV
+soft_aes_sign_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, CK_ULONG_PTR pulSignedLen,
+ boolean_t sign_op, boolean_t Final)
+{
+ soft_aes_ctx_t *soft_aes_ctx_sign_verify;
+ CK_RV rv;
+ CK_BYTE *pEncrypted = NULL;
+ CK_ULONG ulEncryptedLen = AES_BLOCK_LEN;
+ CK_BYTE last_block[AES_BLOCK_LEN];
+
+ if (sign_op) {
+ soft_aes_ctx_sign_verify =
+ (soft_aes_ctx_t *)session_p->sign.context;
+
+ if (soft_aes_ctx_sign_verify->mac_len == 0) {
+ *pulSignedLen = 0;
+ goto clean_exit;
+ }
+
+ /* Application asks for the length of the output buffer. */
+ if (pSigned == NULL) {
+ *pulSignedLen = soft_aes_ctx_sign_verify->mac_len;
+ return (CKR_OK);
+ }
+
+ /* Is the application-supplied buffer large enough? */
+ if (*pulSignedLen < soft_aes_ctx_sign_verify->mac_len) {
+ *pulSignedLen = soft_aes_ctx_sign_verify->mac_len;
+ return (CKR_BUFFER_TOO_SMALL);
+ }
+ } else {
+ soft_aes_ctx_sign_verify =
+ (soft_aes_ctx_t *)session_p->verify.context;
+ }
+
+ if (Final) {
+ rv = soft_encrypt_final(session_p, last_block,
+ &ulEncryptedLen);
+ } else {
+ rv = soft_encrypt(session_p, pData, ulDataLen,
+ last_block, &ulEncryptedLen);
+ }
+
+ if (rv == CKR_OK) {
+ *pulSignedLen = soft_aes_ctx_sign_verify->mac_len;
+
+ /* the leftmost mac_len bytes of last_block is our MAC */
+ (void) memcpy(pSigned, last_block, *pulSignedLen);
+ }
+
+clean_exit:
+
+ (void) pthread_mutex_lock(&session_p->session_mutex);
+
+ /* soft_encrypt_common() has freed the encrypt context */
+ if (sign_op) {
+ free(session_p->sign.context);
+ session_p->sign.context = NULL;
+ } else {
+ free(session_p->verify.context);
+ session_p->verify.context = NULL;
+ }
+ session_p->encrypt.flags = 0;
+
+ (void) pthread_mutex_unlock(&session_p->session_mutex);
+
+ if (pEncrypted) {
+ free(pEncrypted);
+ }
+
+ return (rv);
+}
+
+/*
+ * Called by soft_sign_update()
+ */
+CK_RV
+soft_aes_mac_sign_verify_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen)
+{
+ CK_BYTE buf[AES_BLOCK_LEN];
+ CK_ULONG ulEncryptedLen = AES_BLOCK_LEN;
+ CK_RV rv;
+
+ rv = soft_encrypt_update(session_p, pPart, ulPartLen,
+ buf, &ulEncryptedLen);
+
+ return (rv);
+}
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softCrypt.h b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softCrypt.h
index d4c58bc9d3..eb9f69e74b 100644
--- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softCrypt.h
+++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softCrypt.h
@@ -59,6 +59,7 @@ typedef struct soft_aes_ctx {
uint8_t data[AES_BLOCK_LEN]; /* for use by update */
size_t remain_len; /* for use by update */
void *aes_cbc; /* to be used by CBC mode */
+ size_t mac_len;
} soft_aes_ctx_t;
typedef struct soft_blowfish_ctx {
@@ -84,15 +85,14 @@ CK_RV soft_des_encrypt_common(soft_session_t *, CK_BYTE_PTR, CK_ULONG,
CK_RV soft_des_decrypt_common(soft_session_t *, CK_BYTE_PTR, CK_ULONG,
CK_BYTE_PTR, CK_ULONG_PTR, boolean_t);
-CK_RV soft_des_sign_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData,
- CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, CK_ULONG_PTR pulSignedLen,
- boolean_t sign_op, boolean_t Final);
+CK_RV soft_des_sign_verify_common(soft_session_t *, CK_BYTE_PTR,
+ CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR,
+ boolean_t, boolean_t);
-CK_RV soft_des_sign_verify_init_common(soft_session_t *session_p,
- CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, boolean_t sign_op);
+CK_RV soft_des_sign_verify_init_common(soft_session_t *, CK_MECHANISM_PTR,
+ soft_object_t *, boolean_t);
-CK_RV soft_des_mac_sign_verify_update(soft_session_t *session_p,
- CK_BYTE_PTR pPart, CK_ULONG ulPartLen);
+CK_RV soft_des_mac_sign_verify_update(soft_session_t *, CK_BYTE_PTR, CK_ULONG);
void soft_add_pkcs7_padding(CK_BYTE *, int, CK_ULONG);
@@ -105,6 +105,7 @@ CK_RV soft_arcfour_crypt(crypto_active_op_t *, CK_BYTE_PTR, CK_ULONG,
CK_BYTE_PTR, CK_ULONG_PTR);
void *aes_cbc_ctx_init(void *, size_t, uint8_t *);
+void *aes_cmac_ctx_init(void *, size_t);
void *aes_ctr_ctx_init(void *, size_t, uint8_t *);
CK_RV soft_aes_crypt_init_common(soft_session_t *, CK_MECHANISM_PTR,
@@ -116,6 +117,15 @@ CK_RV soft_aes_encrypt_common(soft_session_t *, CK_BYTE_PTR, CK_ULONG,
CK_RV soft_aes_decrypt_common(soft_session_t *, CK_BYTE_PTR, CK_ULONG,
CK_BYTE_PTR, CK_ULONG_PTR, boolean_t);
+CK_RV soft_aes_sign_verify_common(soft_session_t *, CK_BYTE_PTR,
+ CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR,
+ boolean_t, boolean_t);
+
+CK_RV soft_aes_sign_verify_init_common(soft_session_t *, CK_MECHANISM_PTR,
+ soft_object_t *, boolean_t);
+
+CK_RV soft_aes_mac_sign_verify_update(soft_session_t *, CK_BYTE_PTR, CK_ULONG);
+
void *blowfish_cbc_ctx_init(void *, size_t, uint8_t *);
CK_RV soft_blowfish_crypt_init_common(soft_session_t *, CK_MECHANISM_PTR,
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softEncryptUtil.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softEncryptUtil.c
index 39e863065e..aebacaa868 100644
--- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softEncryptUtil.c
+++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softEncryptUtil.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
#include <pthread.h>
@@ -48,14 +49,14 @@ soft_add_pkcs7_padding(CK_BYTE *buf, int block_size, CK_ULONG data_len)
/*
* Perform encrypt init operation internally for the support of
- * CKM_DES_MAC and CKM_DES_MAC_GENERAL
+ * CKM_AES and CKM_DES MAC operations.
*
* This function is called with the session being held, and without
* its mutex taken.
*/
CK_RV
soft_encrypt_init_internal(soft_session_t *session_p, CK_MECHANISM_PTR
- pMechanism, soft_object_t *key_p)
+ pMechanism, soft_object_t *key_p)
{
CK_RV rv;
@@ -197,6 +198,12 @@ cbc_common:
case CKM_AES_CBC:
case CKM_AES_CBC_PAD:
+ if ((pMechanism->pParameter == NULL) ||
+ (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
+ return (CKR_MECHANISM_PARAM_INVALID);
+ }
+ /* FALLTHRU */
+ case CKM_AES_CMAC:
{
soft_aes_ctx_t *soft_aes_ctx;
@@ -204,10 +211,6 @@ cbc_common:
return (CKR_KEY_TYPE_INCONSISTENT);
}
- if ((pMechanism->pParameter == NULL) ||
- (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
- return (CKR_MECHANISM_PARAM_INVALID);
- }
rv = soft_aes_crypt_init_common(session_p, pMechanism,
key_p, B_TRUE);
@@ -219,14 +222,22 @@ cbc_common:
soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
/* Copy Initialization Vector (IV) into the context. */
- (void) memcpy(soft_aes_ctx->ivec, pMechanism->pParameter,
- AES_BLOCK_LEN);
-
- /* Allocate a context for AES cipher-block chaining. */
- soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
- soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
- soft_aes_ctx->ivec);
-
+ if (pMechanism->mechanism == CKM_AES_CMAC) {
+ (void) bzero(soft_aes_ctx->ivec, AES_BLOCK_LEN);
+ /* Allocate a context for AES cipher-block chaining. */
+ soft_aes_ctx->aes_cbc = (void *)aes_cmac_ctx_init(
+ soft_aes_ctx->key_sched,
+ soft_aes_ctx->keysched_len);
+ } else {
+ (void) memcpy(soft_aes_ctx->ivec,
+ pMechanism->pParameter,
+ AES_BLOCK_LEN);
+ /* Allocate a context for AES cipher-block chaining. */
+ soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
+ soft_aes_ctx->key_sched,
+ soft_aes_ctx->keysched_len,
+ soft_aes_ctx->ivec);
+ }
if (soft_aes_ctx->aes_cbc == NULL) {
bzero(soft_aes_ctx->key_sched,
soft_aes_ctx->keysched_len);
@@ -404,6 +415,7 @@ soft_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
}
/* FALLTHROUGH */
+ case CKM_AES_CMAC:
case CKM_AES_CBC_PAD:
return (soft_aes_encrypt_common(session_p, pData,
@@ -488,8 +500,8 @@ soft_encrypt(soft_session_t *session_p, CK_BYTE_PTR pData,
*/
CK_RV
soft_encrypt_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
- CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
- CK_ULONG_PTR pulEncryptedPartLen)
+ CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG_PTR pulEncryptedPartLen)
{
CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
@@ -505,6 +517,7 @@ soft_encrypt_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
case CKM_AES_ECB:
case CKM_AES_CBC:
case CKM_AES_CBC_PAD:
+ case CKM_AES_CMAC:
case CKM_AES_CTR:
case CKM_BLOWFISH_CBC:
case CKM_RC4:
@@ -538,7 +551,7 @@ soft_encrypt_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
*/
CK_RV
soft_encrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastEncryptedPart,
- CK_ULONG_PTR pulLastEncryptedPartLen)
+ CK_ULONG_PTR pulLastEncryptedPartLen)
{
CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
@@ -717,6 +730,46 @@ soft_encrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastEncryptedPart,
break;
}
+ case CKM_AES_CMAC:
+ {
+ soft_aes_ctx_t *soft_aes_ctx;
+ soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
+
+ if (pLastEncryptedPart == NULL) {
+ /*
+ * Application asks for the length of the output
+ * buffer to hold the ciphertext.
+ */
+ *pulLastEncryptedPartLen = AES_BLOCK_LEN;
+ goto clean1;
+ } else {
+ crypto_data_t out;
+
+ out.cd_format = CRYPTO_DATA_RAW;
+ out.cd_offset = 0;
+ out.cd_length = AES_BLOCK_LEN;
+ out.cd_raw.iov_base = (char *)pLastEncryptedPart;
+ out.cd_raw.iov_len = AES_BLOCK_LEN;
+
+ rc = cmac_mode_final(soft_aes_ctx->aes_cbc, &out,
+ aes_encrypt_block, aes_xor_block);
+
+ if (rc == 0) {
+ *pulLastEncryptedPartLen = AES_BLOCK_LEN;
+ } else {
+ *pulLastEncryptedPartLen = 0;
+ rv = CKR_FUNCTION_FAILED;
+ }
+
+ /* Cleanup memory space. */
+ free(soft_aes_ctx->aes_cbc);
+ bzero(soft_aes_ctx->key_sched,
+ soft_aes_ctx->keysched_len);
+ free(soft_aes_ctx->key_sched);
+ }
+
+ break;
+ }
case CKM_AES_CBC:
case CKM_AES_ECB:
{
@@ -840,7 +893,7 @@ clean1:
*/
void
soft_crypt_cleanup(soft_session_t *session_p, boolean_t encrypt,
- boolean_t lock_held)
+ boolean_t lock_held)
{
crypto_active_op_t *active_op;
@@ -881,6 +934,7 @@ soft_crypt_cleanup(soft_session_t *session_p, boolean_t encrypt,
case CKM_AES_CBC_PAD:
case CKM_AES_CBC:
+ case CKM_AES_CMAC:
case CKM_AES_ECB:
{
soft_aes_ctx_t *soft_aes_ctx =
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSignUtil.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSignUtil.c
index 586dd76fdc..f8824df2dd 100644
--- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSignUtil.c
+++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSignUtil.c
@@ -21,10 +21,9 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
@@ -103,6 +102,12 @@ soft_sign_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
return (soft_des_sign_verify_init_common(session_p, pMechanism,
key_p, B_TRUE));
+ case CKM_AES_CMAC_GENERAL:
+ case CKM_AES_CMAC:
+
+ return (soft_aes_sign_verify_init_common(session_p, pMechanism,
+ key_p, B_TRUE));
+
default:
return (CKR_MECHANISM_INVALID);
}
@@ -187,6 +192,27 @@ soft_sign(soft_session_t *session_p, CK_BYTE_PTR pData,
return (rv);
}
+ case CKM_AES_CMAC_GENERAL:
+ case CKM_AES_CMAC:
+ {
+ CK_BYTE signature[AES_BLOCK_LEN];
+
+ if (pSignature != NULL) {
+ /* Pass local buffer to avoid overflow. */
+ rv = soft_aes_sign_verify_common(session_p, pData,
+ ulDataLen, signature, pulSignatureLen, B_TRUE,
+ B_FALSE);
+ } else {
+ /* Pass NULL, let callee handle it. */
+ rv = soft_aes_sign_verify_common(session_p, pData,
+ ulDataLen, NULL, pulSignatureLen, B_TRUE, B_FALSE);
+ }
+
+ if ((rv == CKR_OK) && (pSignature != NULL))
+ (void) memcpy(pSignature, signature, *pulSignatureLen);
+
+ return (rv);
+ }
case CKM_RSA_X_509:
case CKM_RSA_PKCS:
@@ -271,6 +297,12 @@ soft_sign_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
return (soft_des_mac_sign_verify_update(session_p, pPart,
ulPartLen));
+ case CKM_AES_CMAC_GENERAL:
+ case CKM_AES_CMAC:
+
+ return (soft_aes_mac_sign_verify_update(session_p, pPart,
+ ulPartLen));
+
case CKM_MD5_RSA_PKCS:
case CKM_SHA1_RSA_PKCS:
case CKM_SHA256_RSA_PKCS:
@@ -367,6 +399,26 @@ soft_sign_final(soft_session_t *session_p, CK_BYTE_PTR pSignature,
return (rv);
}
+ case CKM_AES_CMAC_GENERAL:
+ case CKM_AES_CMAC:
+ {
+ CK_BYTE signature[AES_BLOCK_LEN]; /* use the maximum size */
+
+ if (pSignature != NULL) {
+ /* Pass local buffer to avoid overflow. */
+ rv = soft_aes_sign_verify_common(session_p, NULL, 0,
+ signature, pulSignatureLen, B_TRUE, B_TRUE);
+ } else {
+ /* Pass NULL, let callee handle it. */
+ rv = soft_aes_sign_verify_common(session_p, NULL, 0,
+ NULL, pulSignatureLen, B_TRUE, B_TRUE);
+ }
+
+ if ((rv == CKR_OK) && (pSignature != NULL))
+ (void) memcpy(pSignature, signature, *pulSignatureLen);
+
+ return (rv);
+ }
case CKM_MD5_RSA_PKCS:
case CKM_SHA1_RSA_PKCS:
case CKM_SHA256_RSA_PKCS:
@@ -524,6 +576,17 @@ soft_sign_verify_cleanup(soft_session_t *session_p, boolean_t sign,
bzero(active_op->context, sizeof (soft_des_ctx_t));
break;
+ case CKM_AES_CMAC_GENERAL:
+ case CKM_AES_CMAC:
+ if (session_p->encrypt.context != NULL) {
+ free(session_p->encrypt.context);
+ session_p->encrypt.context = NULL;
+ session_p->encrypt.flags = 0;
+ }
+ if (active_op->context != NULL)
+ bzero(active_op->context, sizeof (soft_aes_ctx_t));
+ break;
+
}
if (active_op->context != NULL) {
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSlotToken.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSlotToken.c
index a18633094d..602b72486e 100644
--- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSlotToken.c
+++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSlotToken.c
@@ -55,6 +55,8 @@ static CK_MECHANISM_TYPE soft_mechanisms[] = {
CKM_AES_CBC,
CKM_AES_CBC_PAD,
CKM_AES_CTR,
+ CKM_AES_CMAC_GENERAL,
+ CKM_AES_CMAC,
CKM_AES_ECB,
CKM_AES_KEY_GEN,
CKM_BLOWFISH_CBC,
@@ -160,6 +162,10 @@ static CK_MECHANISM_INFO soft_mechanism_info[] = {
CKF_ENCRYPT|CKF_DECRYPT|
CKF_WRAP|CKF_UNWRAP}, /* CKM_AES_CTR */
{AES_MINBYTES, AES_MAXBYTES,
+ CKF_SIGN|CKF_VERIFY}, /* CKM_AES_CMAC_GENERAL */
+ {AES_MINBYTES, AES_MAXBYTES,
+ CKF_SIGN|CKF_VERIFY}, /* CKM_AES_CMAC */
+ {AES_MINBYTES, AES_MAXBYTES,
CKF_ENCRYPT|CKF_DECRYPT|
CKF_WRAP|CKF_UNWRAP}, /* CKM_AES_ECB */
{AES_MINBYTES, AES_MAXBYTES,
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softVerifyUtil.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softVerifyUtil.c
index dde02d2cf7..85c1e64398 100644
--- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softVerifyUtil.c
+++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softVerifyUtil.c
@@ -21,10 +21,9 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdlib.h>
#include <string.h>
#include <strings.h>
@@ -104,6 +103,12 @@ soft_verify_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
return (soft_des_sign_verify_init_common(session_p, pMechanism,
key_p, B_FALSE));
+ case CKM_AES_CMAC_GENERAL:
+ case CKM_AES_CMAC:
+
+ return (soft_aes_sign_verify_init_common(session_p, pMechanism,
+ key_p, B_FALSE));
+
default:
return (CKR_MECHANISM_INVALID);
}
@@ -198,6 +203,32 @@ soft_verify(soft_session_t *session_p, CK_BYTE_PTR pData,
return (rv);
}
+ case CKM_AES_CMAC_GENERAL:
+ case CKM_AES_CMAC:
+ {
+ CK_ULONG len;
+ CK_BYTE signature[AES_BLOCK_LEN];
+ soft_aes_ctx_t *aes_ctx;
+
+ aes_ctx = (soft_aes_ctx_t *)session_p->verify.context;
+ len = aes_ctx->mac_len;
+
+ /* Pass local buffer to avoid overflow. */
+ rv = soft_aes_sign_verify_common(session_p, pData,
+ ulDataLen, signature, &len, B_FALSE, B_FALSE);
+
+ if (rv == CKR_OK) {
+ if (len != ulSignatureLen) {
+ rv = CKR_SIGNATURE_LEN_RANGE;
+ }
+
+ if (memcmp(signature, pSignature, len) != 0) {
+ rv = CKR_SIGNATURE_INVALID;
+ }
+ }
+
+ return (rv);
+ }
case CKM_RSA_X_509:
case CKM_RSA_PKCS:
@@ -282,6 +313,12 @@ soft_verify_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
return (soft_des_mac_sign_verify_update(session_p, pPart,
ulPartLen));
+ case CKM_AES_CMAC_GENERAL:
+ case CKM_AES_CMAC:
+
+ return (soft_aes_mac_sign_verify_update(session_p, pPart,
+ ulPartLen));
+
case CKM_MD5_RSA_PKCS:
case CKM_SHA1_RSA_PKCS:
case CKM_SHA256_RSA_PKCS:
@@ -389,6 +426,32 @@ soft_verify_final(soft_session_t *session_p, CK_BYTE_PTR pSignature,
return (rv);
}
+ case CKM_AES_CMAC_GENERAL:
+ case CKM_AES_CMAC:
+ {
+ CK_ULONG len;
+ CK_BYTE signature[AES_BLOCK_LEN];
+ soft_aes_ctx_t *aes_ctx;
+
+ aes_ctx = (soft_aes_ctx_t *)session_p->verify.context;
+ len = aes_ctx->mac_len;
+
+ /* Pass local buffer to avoid overflow. */
+ rv = soft_aes_sign_verify_common(session_p, NULL, 0,
+ signature, &len, B_FALSE, B_TRUE);
+
+ if (rv == CKR_OK) {
+ if (len != ulSignatureLen) {
+ rv = CKR_SIGNATURE_LEN_RANGE;
+ }
+
+ if (memcmp(signature, pSignature, len) != 0) {
+ rv = CKR_SIGNATURE_INVALID;
+ }
+ }
+
+ return (rv);
+ }
case CKM_MD5_RSA_PKCS:
case CKM_SHA1_RSA_PKCS:
case CKM_SHA256_RSA_PKCS:
diff --git a/usr/src/pkg/manifests/system-test-cryptotest.mf b/usr/src/pkg/manifests/system-test-cryptotest.mf
new file mode 100644
index 0000000000..db54e93b90
--- /dev/null
+++ b/usr/src/pkg/manifests/system-test-cryptotest.mf
@@ -0,0 +1,52 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+set name=pkg.fmri value=pkg:/system/test/cryptotest@$(PKGVERS)
+set name=pkg.description value="Miscellaneous KCF/PKCS Unit Tests"
+set name=pkg.summary value="KCF/PKCS Unit Test Suite"
+set name=info.classification \
+ value=org.opensolaris.category.2008:Development/System
+set name=variant.arch value=$(ARCH)
+dir path=opt/crypto-tests
+dir path=opt/crypto-tests/bin
+dir path=opt/crypto-tests/runfiles
+dir path=opt/crypto-tests/tests
+dir path=opt/crypto-tests/tests/kcf
+dir path=opt/crypto-tests/tests/kcf/aes
+dir path=opt/crypto-tests/tests/pkcs
+dir path=opt/crypto-tests/tests/pkcs/aes
+file path=opt/crypto-tests/README mode=0444
+file path=opt/crypto-tests/bin/cryptotest mode=0555
+file path=opt/crypto-tests/runfiles/default.run mode=0444
+file path=opt/crypto-tests/tests/kcf/aes/aes_cbc mode=0555
+file path=opt/crypto-tests/tests/kcf/aes/aes_ccm mode=0555
+file path=opt/crypto-tests/tests/kcf/aes/aes_cmac mode=0555
+file path=opt/crypto-tests/tests/kcf/aes/aes_ctr mode=0555
+file path=opt/crypto-tests/tests/kcf/aes/aes_ecb mode=0555
+file path=opt/crypto-tests/tests/kcf/aes/aes_gcm mode=0555
+file path=opt/crypto-tests/tests/kcf/aes/cleanup mode=0555
+file path=opt/crypto-tests/tests/kcf/aes/setup mode=0555
+file path=opt/crypto-tests/tests/pkcs/aes/aes_cbc mode=0555
+file path=opt/crypto-tests/tests/pkcs/aes/aes_ccm mode=0555
+file path=opt/crypto-tests/tests/pkcs/aes/aes_cmac mode=0555
+file path=opt/crypto-tests/tests/pkcs/aes/aes_ctr mode=0555
+file path=opt/crypto-tests/tests/pkcs/aes/aes_ecb mode=0555
+file path=opt/crypto-tests/tests/pkcs/aes/aes_gcm mode=0555
+license cr_Sun license=cr_Sun
+license lic_CDDL license=lic_CDDL
+depend fmri=driver/crypto/dprov type=require
+depend fmri=system/test/testrunner type=require
diff --git a/usr/src/test/Makefile b/usr/src/test/Makefile
index 304163b79f..fdc5abc683 100644
--- a/usr/src/test/Makefile
+++ b/usr/src/test/Makefile
@@ -16,6 +16,6 @@
.PARALLEL: $(SUBDIRS)
-SUBDIRS = libc-tests os-tests test-runner util-tests zfs-tests
+SUBDIRS = libc-tests crypto-tests os-tests test-runner util-tests zfs-tests
include Makefile.com
diff --git a/usr/src/test/crypto-tests/Makefile b/usr/src/test/crypto-tests/Makefile
new file mode 100644
index 0000000000..6669972e13
--- /dev/null
+++ b/usr/src/test/crypto-tests/Makefile
@@ -0,0 +1,20 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+.PARALLEL: $(SUBDIRS)
+
+SUBDIRS = cmd doc runfiles tests
+
+include $(SRC)/test/Makefile.com
diff --git a/usr/src/test/crypto-tests/cmd/Makefile b/usr/src/test/crypto-tests/cmd/Makefile
new file mode 100644
index 0000000000..02bea22f72
--- /dev/null
+++ b/usr/src/test/crypto-tests/cmd/Makefile
@@ -0,0 +1,20 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+.PARALLEL: $(SUBDIRS)
+
+SUBDIRS = kcf scripts
+
+include $(SRC)/test/Makefile.com
diff --git a/usr/src/test/crypto-tests/cmd/kcf/Makefile b/usr/src/test/crypto-tests/cmd/kcf/Makefile
new file mode 100644
index 0000000000..fd2d8f2746
--- /dev/null
+++ b/usr/src/test/crypto-tests/cmd/kcf/Makefile
@@ -0,0 +1,38 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+include $(SRC)/Makefile.master
+include $(SRC)/test/Makefile.com
+
+ROOTOPTPKG = $(ROOT)/opt/crypto-tests
+ROOTBIN = $(ROOTOPTPKG)/tests/kcf/aes
+
+PROGS = cleanup setup
+
+CMDS = $(PROGS:%=$(ROOTBIN)/%)
+$(CMDS) := FILEMODE = 0555
+
+all lint clean clobber:
+
+install: $(CMDS)
+
+$(CMDS): $(ROOTBIN)
+
+$(ROOTBIN):
+ $(INS.dir)
+
+$(ROOTBIN)/%: %.ksh
+ $(INS.rename)
diff --git a/usr/src/test/crypto-tests/cmd/kcf/cleanup.ksh b/usr/src/test/crypto-tests/cmd/kcf/cleanup.ksh
new file mode 100644
index 0000000000..26bed45978
--- /dev/null
+++ b/usr/src/test/crypto-tests/cmd/kcf/cleanup.ksh
@@ -0,0 +1,18 @@
+#!/usr/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+rem_drv dprov \ No newline at end of file
diff --git a/usr/src/test/crypto-tests/cmd/kcf/setup.ksh b/usr/src/test/crypto-tests/cmd/kcf/setup.ksh
new file mode 100644
index 0000000000..ef8e66dae6
--- /dev/null
+++ b/usr/src/test/crypto-tests/cmd/kcf/setup.ksh
@@ -0,0 +1,18 @@
+#!/usr/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+add_drv dprov \ No newline at end of file
diff --git a/usr/src/test/crypto-tests/cmd/scripts/Makefile b/usr/src/test/crypto-tests/cmd/scripts/Makefile
new file mode 100644
index 0000000000..587b5303e1
--- /dev/null
+++ b/usr/src/test/crypto-tests/cmd/scripts/Makefile
@@ -0,0 +1,38 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+include $(SRC)/Makefile.master
+include $(SRC)/test/Makefile.com
+
+ROOTOPTPKG = $(ROOT)/opt/crypto-tests
+ROOTBIN = $(ROOTOPTPKG)/bin
+
+PROGS = cryptotest
+
+CMDS = $(PROGS:%=$(ROOTBIN)/%)
+$(CMDS) := FILEMODE = 0555
+
+all lint clean clobber:
+
+install: $(CMDS)
+
+$(CMDS): $(ROOTBIN)
+
+$(ROOTBIN):
+ $(INS.dir)
+
+$(ROOTBIN)/%: %.ksh
+ $(INS.rename)
diff --git a/usr/src/test/crypto-tests/cmd/scripts/cryptotest.ksh b/usr/src/test/crypto-tests/cmd/scripts/cryptotest.ksh
new file mode 100644
index 0000000000..313cf1e0dc
--- /dev/null
+++ b/usr/src/test/crypto-tests/cmd/scripts/cryptotest.ksh
@@ -0,0 +1,49 @@
+#!/usr/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+export CRYPTO_TESTS="/opt/crypto-tests"
+runner="/opt/test-runner/bin/run"
+
+function fail
+{
+ echo $1
+ exit ${2:-1}
+}
+
+function find_runfile
+{
+ typeset distro=default
+
+ [[ -n $distro ]] && echo $CRYPTO_TESTS/runfiles/$distro.run
+}
+
+while getopts c: c; do
+ case $c in
+ 'c')
+ runfile=$OPTARG
+ [[ -f $runfile ]] || fail "Cannot read file: $runfile"
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+
+[[ -z $runfile ]] && runfile=$(find_runfile)
+[[ -z $runfile ]] && fail "Couldn't determine distro"
+
+$runner -c $runfile
+
+exit $?
diff --git a/usr/src/test/crypto-tests/doc/Makefile b/usr/src/test/crypto-tests/doc/Makefile
new file mode 100644
index 0000000000..cf4f0beb39
--- /dev/null
+++ b/usr/src/test/crypto-tests/doc/Makefile
@@ -0,0 +1,36 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+include $(SRC)/Makefile.master
+
+READMES = README
+
+ROOTOPTPKG = $(ROOT)/opt/crypto-tests
+
+FILES = $(READMES:%=$(ROOTOPTPKG)/%)
+$(FILES) := FILEMODE = 0444
+
+all: $(READMES)
+
+install: $(ROOTOPTPKG) $(FILES)
+
+clean lint clobber:
+
+$(ROOTOPTPKG):
+ $(INS.dir)
+
+$(ROOTOPTPKG)/%: %
+ $(INS.file)
diff --git a/usr/src/test/crypto-tests/doc/README b/usr/src/test/crypto-tests/doc/README
new file mode 100644
index 0000000000..0c848ac735
--- /dev/null
+++ b/usr/src/test/crypto-tests/doc/README
@@ -0,0 +1,60 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+KCF/PKCS Unit Test Suite README
+
+1. Building and installing the KCF/PKCS Unit Test Suite
+2. Running the KCF/PKCS Unit Test Suite
+3. Test results
+
+--------------------------------------------------------------------------------
+
+1. Building and installing the KCF/PKCS Unit Test Suite
+
+The KCF/PKCS Unit Test Suite runs under the testrunner framework (which can be
+installed as pkg:/system/test/testrunner). To build both the KCF/PKCS Unit Test Suite
+and the testrunner without running a full nightly:
+
+ build_machine$ bldenv [-d] <your_env_file>
+ build_machine$ cd $SRC/test
+ build_machine$ dmake install
+ build_machine$ cd $SRC/pkg
+ build_machine$ dmake install
+
+Then set the publisher on the test machine to point to your repository and
+install the KCF/PKCS Unit Test Suite.
+
+ test_machine# pkg install pkg:/system/test/cryptotest
+
+Note, the framework will be installed automatically, as the KCF/PKCS Unit Test Suite
+depends on it.
+
+2. Running the KCF/PKCS Unit Test Suite
+
+The pre-requisites for running the KCF/PKCS Unit Test Suite are:
+ - A non-root user with the ability to sudo(1M) to root without a
+ password or the root user must run the test.
+
+Once the pre-requisites are satisfied, simply run the cryptotest script:
+
+ test_machine$ /opt/crypto-tests/bin/cryptotest
+
+3. Test results
+
+While the KCF/PKCS Unit Test Suite is running, one informational line is printed at
+the end of each test, and a results summary is printed at the end of the run.
+The results summary includes the location of the complete logs, which is of the
+form /var/tmp/test_results/<ISO 8601 date>.
diff --git a/usr/src/test/crypto-tests/runfiles/Makefile b/usr/src/test/crypto-tests/runfiles/Makefile
new file mode 100644
index 0000000000..2c6db60352
--- /dev/null
+++ b/usr/src/test/crypto-tests/runfiles/Makefile
@@ -0,0 +1,40 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+include $(SRC)/Makefile.master
+
+SRCS = default.run
+
+ROOTOPTPKG = $(ROOT)/opt/crypto-tests
+RUNFILES = $(ROOTOPTPKG)/runfiles
+
+CMDS = $(SRCS:%=$(RUNFILES)/%)
+$(CMDS) := FILEMODE = 0444
+
+all: $(SRCS)
+
+install: $(CMDS)
+
+clean lint clobber:
+
+$(CMDS): $(RUNFILES) $(SRCS)
+
+$(RUNFILES):
+ $(INS.dir)
+
+$(RUNFILES)/%: %
+ $(INS.file)
diff --git a/usr/src/test/crypto-tests/runfiles/default.run b/usr/src/test/crypto-tests/runfiles/default.run
new file mode 100644
index 0000000000..ecd77fe085
--- /dev/null
+++ b/usr/src/test/crypto-tests/runfiles/default.run
@@ -0,0 +1,32 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+[DEFAULT]
+pre =
+verbose = False
+quiet = False
+timeout = 60
+post =
+outputdir = /var/tmp/test_results
+
+[/opt/crypto-tests/tests/pkcs/aes]
+tests = ['aes_cbc', 'aes_ccm', 'aes_cmac', 'aes_ctr', 'aes_ecb', 'aes_gcm']
+
+[/opt/crypto-tests/tests/kcf/aes]
+pre = setup
+user = root
+tests = ['aes_cbc', 'aes_ccm', 'aes_cmac', 'aes_ctr', 'aes_ecb', 'aes_gcm']
+post = cleanup \ No newline at end of file
diff --git a/usr/src/test/crypto-tests/tests/Makefile b/usr/src/test/crypto-tests/tests/Makefile
new file mode 100644
index 0000000000..abd151c0a5
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/Makefile
@@ -0,0 +1,20 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+SUBDIRS = modes common
+
+modes: common
+
+include $(SRC)/test/Makefile.com
diff --git a/usr/src/test/crypto-tests/tests/common/Makefile b/usr/src/test/crypto-tests/tests/common/Makefile
new file mode 100644
index 0000000000..3dae390d40
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/common/Makefile
@@ -0,0 +1,33 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/test/Makefile.com
+
+OBJS = testfuncs.o cryptotest_pkcs.o cryptotest_kcf.o
+SRCS = $(OBJS:%.o=%.c)
+
+CPPFLAGS += -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I$(SRC)/common/crypto/
+
+all install: $(OBJS)
+
+%.o: %.c
+ $(COMPILE.c) -o $@ $<
+
+lint:
+
+clobber clean:
+ -$(RM) $(OBJS)
diff --git a/usr/src/test/crypto-tests/tests/common/cryptotest.h b/usr/src/test/crypto-tests/tests/common/cryptotest.h
new file mode 100644
index 0000000000..32b53f0730
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/common/cryptotest.h
@@ -0,0 +1,102 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _CRYPTOTEST_H
+#define _CRYPTOTEST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/crypto/ioctl.h>
+
+#define CTEST_INIT_FAILED (-1)
+#define CTEST_NAME_RESOLVE_FAILED (-2)
+#define CTEST_MECH_NO_PROVIDER (-3)
+
+typedef struct cryptotest {
+ uint8_t *in;
+ uint8_t *out;
+ uint8_t *key;
+ void *param;
+
+ size_t inlen;
+ size_t outlen;
+ size_t keylen;
+ size_t plen;
+
+ char *mechname;
+ size_t updatelen;
+} cryptotest_t;
+
+typedef int (*testfunc_t)(cryptotest_t *);
+
+typedef struct test_fg {
+ testfunc_t single;
+ testfunc_t update;
+} test_fg_t;
+
+#define CRYPTO_INVALID_SESSION ((size_t)-1)
+typedef struct crypto_op crypto_op_t;
+
+int run_test(cryptotest_t *args, uint8_t *cmp, size_t cmplen, test_fg_t *funcs);
+
+/* utils */
+crypto_op_t *cryptotest_init(cryptotest_t *args, crypto_func_group_t fg);
+int cryptotest_close(crypto_op_t *op);
+int get_mech_info(crypto_op_t *op);
+int get_hsession_by_mech(crypto_op_t *op);
+
+/* CRYPTO_MAC */
+int mac_init(crypto_op_t *op);
+int mac_single(crypto_op_t *op);
+int mac_update(crypto_op_t *op, int offset);
+int mac_final(crypto_op_t *op);
+
+/* CRYPTO_ENCRYPT */
+int encrypt_init(crypto_op_t *op);
+int encrypt_single(crypto_op_t *op);
+int encrypt_update(crypto_op_t *op, int offset, size_t *encrlen);
+int encrypt_final(crypto_op_t *op, size_t encrlen);
+
+/* CRYPTO_DECRYPT */
+int decrypt_init(crypto_op_t *op);
+int decrypt_single(crypto_op_t *op);
+int decrypt_update(crypto_op_t *op, int offset, size_t *encrlen);
+int decrypt_final(crypto_op_t *op, size_t encrlen);
+
+/* wrappers */
+int test_mac_single(cryptotest_t *args);
+int test_mac(cryptotest_t *args);
+
+int test_encrypt_single(cryptotest_t *args);
+int test_encrypt(cryptotest_t *args);
+
+int test_decrypt_single(cryptotest_t *args);
+int test_decrypt(cryptotest_t *args);
+
+extern test_fg_t cryptotest_decr_fg;
+extern test_fg_t cryptotest_encr_fg;
+extern test_fg_t cryptotest_mac_fg;
+
+#define MAC_FG (&cryptotest_mac_fg)
+#define ENCR_FG (&cryptotest_encr_fg)
+#define DECR_FG (&cryptotest_decr_fg)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CRYPTOTEST_H */
diff --git a/usr/src/test/crypto-tests/tests/common/cryptotest_kcf.c b/usr/src/test/crypto-tests/tests/common/cryptotest_kcf.c
new file mode 100644
index 0000000000..260821dcac
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/common/cryptotest_kcf.c
@@ -0,0 +1,378 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <fcntl.h>
+#include <strings.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cryptotest.h"
+
+struct crypto_op {
+ char *in;
+ char *out;
+ char *key;
+ char *param;
+
+ size_t inlen;
+ size_t outlen;
+ size_t keylen;
+ size_t paramlen;
+ size_t updatelen;
+
+ char *mechname;
+
+ /* internal */
+ crypto_mech_type_t mech;
+ crypto_session_id_t hsession;
+ crypto_func_group_t fg;
+};
+
+static int fd;
+static const char CRYPTO_DEVICE[] = "/dev/crypto";
+
+int
+kcf_do_ioctl(int opcode, uint_t *arg, char *opstr)
+{
+ int ret;
+
+ while ((ret = ioctl(fd, opcode, arg)) < 0) {
+ if (errno != EINTR)
+ break;
+ }
+
+ if (ret < 0 || *arg != CRYPTO_SUCCESS)
+ (void) fprintf(stderr, "%s: Error = %d %d 0x%02x\n",
+ (opstr == NULL) ? "ioctl" : opstr,
+ ret, errno, *arg);
+
+ if (ret < 0)
+ return (errno);
+
+ return (*arg);
+}
+
+crypto_op_t *
+cryptotest_init(cryptotest_t *arg, crypto_func_group_t fg)
+{
+ crypto_op_t *op = malloc(sizeof (*op));
+
+ if (op == NULL)
+ return (NULL);
+
+ while ((fd = open(CRYPTO_DEVICE, O_RDWR)) < 0) {
+ if (errno != EINTR)
+ return (NULL);
+ }
+
+ op->in = (char *)arg->in;
+ op->out = (char *)arg->out;
+ op->key = (char *)arg->key;
+ op->param = (char *)arg->param;
+
+ op->inlen = arg->inlen;
+ op->outlen = arg->outlen;
+ op->keylen = arg->keylen * 8; /* kcf uses keylen in bits */
+ op->paramlen = arg->plen;
+ op->updatelen = arg->updatelen;
+
+ op->mechname = arg->mechname;
+
+ op->hsession = CRYPTO_INVALID_SESSION;
+ op->fg = fg;
+
+ if (op->out == NULL)
+ op->outlen = op->inlen;
+ return (op);
+}
+
+int
+cryptotest_close_session(crypto_session_id_t session)
+{
+ crypto_close_session_t cs;
+
+ cs.cs_session = session;
+ return (kcf_do_ioctl(CRYPTO_CLOSE_SESSION, (uint_t *)&cs, "session"));
+}
+
+int
+cryptotest_close(crypto_op_t *op)
+{
+ if (op->hsession != CRYPTO_INVALID_SESSION)
+ (void) cryptotest_close_session(op->hsession);
+ free(op);
+ if (fd >= 0)
+ return (close(fd));
+ return (0);
+}
+
+int
+get_mech_info(crypto_op_t *op)
+{
+ crypto_get_mechanism_number_t get_number;
+
+ bzero(&get_number, sizeof (get_number));
+
+ get_number.pn_mechanism_string = op->mechname;
+ get_number.pn_mechanism_len = strlen(op->mechname) + 1;
+
+ if (kcf_do_ioctl(CRYPTO_GET_MECHANISM_NUMBER,
+ (uint_t *)&get_number, "get_mech_info") != CRYPTO_SUCCESS) {
+ (void) fprintf(stderr, "failed to resolve mechanism name %s\n",
+ op->mechname);
+ (void) cryptotest_close(op);
+ return (CTEST_NAME_RESOLVE_FAILED);
+ }
+ op->mech = get_number.pn_internal_number;
+ return (CRYPTO_SUCCESS);
+}
+
+int
+get_hsession_by_mech(crypto_op_t *op)
+{
+ crypto_by_mech_t mech;
+ int rv;
+
+ mech.mech_keylen = op->keylen;
+ mech.mech_type = op->mech;
+ mech.mech_fg = op->fg;
+
+ rv = kcf_do_ioctl(CRYPTO_GET_PROVIDER_BY_MECH, (uint_t *)&mech,
+ "get_hsession_by_mech");
+
+ if (rv != 0 || mech.rv != CRYPTO_SUCCESS) {
+ (void) fprintf(stderr,
+ "could not find provider for mechanism %llu\n",
+ mech.mech_type);
+ (void) cryptotest_close(op);
+ return (CTEST_MECH_NO_PROVIDER);
+ }
+
+ op->hsession = mech.session_id;
+
+ return (CRYPTO_SUCCESS);
+}
+
+/*
+ * CRYPTO_MAC_* functions
+ */
+int
+mac_init(crypto_op_t *op)
+{
+ crypto_mac_init_t init;
+
+ bzero((void *)&init, sizeof (init));
+
+ init.mi_session = op->hsession;
+
+ init.mi_key.ck_data = op->key;
+ init.mi_key.ck_format = CRYPTO_KEY_RAW; /* must be this */
+ init.mi_key.ck_length = op->keylen;
+
+ init.mi_mech.cm_type = op->mech;
+ init.mi_mech.cm_param = NULL;
+ init.mi_mech.cm_param_len = 0;
+
+ return (kcf_do_ioctl(CRYPTO_MAC_INIT, (uint_t *)&init, "init"));
+}
+
+int
+mac_single(crypto_op_t *op)
+{
+ crypto_mac_t mac;
+
+ bzero(&mac, sizeof (mac));
+ mac.cm_session = op->hsession;
+ mac.cm_datalen = op->inlen;
+ mac.cm_databuf = op->in;
+ mac.cm_maclen = op->outlen;
+ mac.cm_macbuf = op->out;
+
+ return (kcf_do_ioctl(CRYPTO_MAC, (uint_t *)&mac, "single"));
+}
+
+int
+mac_update(crypto_op_t *op, int offset)
+{
+ crypto_mac_update_t update;
+
+ bzero((void *)&update, sizeof (update));
+
+ update.mu_session = op->hsession;
+ update.mu_databuf = op->in + offset;
+ update.mu_datalen = op->updatelen;
+
+ return (kcf_do_ioctl(CRYPTO_MAC_UPDATE, (uint_t *)&update, "update"));
+}
+
+int
+mac_final(crypto_op_t *op)
+{
+ crypto_mac_final_t final;
+
+ bzero((void *)&final, sizeof (final));
+
+ final.mf_session = op->hsession;
+ final.mf_maclen = op->outlen;
+ final.mf_macbuf = op->out;
+
+ return (kcf_do_ioctl(CRYPTO_MAC_FINAL, (uint_t *)&final, "final"));
+}
+
+
+/*
+ * CRYPTO_ENCRYPT_* functions
+ */
+
+int
+encrypt_init(crypto_op_t *op)
+{
+ crypto_encrypt_init_t init;
+
+ bzero((void *)&init, sizeof (init));
+
+ init.ei_session = op->hsession;
+
+ init.ei_key.ck_data = op->key;
+ init.ei_key.ck_format = CRYPTO_KEY_RAW; /* must be this */
+ init.ei_key.ck_length = op->keylen;
+
+ init.ei_mech.cm_type = op->mech;
+ init.ei_mech.cm_param = op->param;
+ init.ei_mech.cm_param_len = op->paramlen;
+
+ return (kcf_do_ioctl(CRYPTO_ENCRYPT_INIT, (uint_t *)&init, "init"));
+}
+
+int
+encrypt_single(crypto_op_t *op)
+{
+ crypto_encrypt_t encrypt;
+
+ bzero(&encrypt, sizeof (encrypt));
+ encrypt.ce_session = op->hsession;
+ encrypt.ce_datalen = op->inlen;
+ encrypt.ce_databuf = op->in;
+ encrypt.ce_encrlen = op->outlen;
+ encrypt.ce_encrbuf = op->out;
+
+ return (kcf_do_ioctl(CRYPTO_ENCRYPT, (uint_t *)&encrypt, "single"));
+}
+
+int
+encrypt_update(crypto_op_t *op, int offset, size_t *encrlen)
+{
+ crypto_encrypt_update_t update;
+ int ret;
+ bzero((void *)&update, sizeof (update));
+
+ update.eu_session = op->hsession;
+ update.eu_databuf = op->in + offset;
+ update.eu_datalen = op->updatelen;
+ update.eu_encrlen = op->outlen - *encrlen;
+ update.eu_encrbuf = op->out + *encrlen;
+
+ ret = kcf_do_ioctl(CRYPTO_ENCRYPT_UPDATE, (uint_t *)&update, "update");
+ *encrlen += update.eu_encrlen;
+ return (ret);
+}
+
+int
+encrypt_final(crypto_op_t *op, size_t encrlen)
+{
+ crypto_encrypt_final_t final;
+
+ bzero((void *)&final, sizeof (final));
+
+ final.ef_session = op->hsession;
+ final.ef_encrlen = op->outlen - encrlen;
+ final.ef_encrbuf = op->out + encrlen;
+
+ return (kcf_do_ioctl(CRYPTO_ENCRYPT_FINAL, (uint_t *)&final, "final"));
+}
+
+/*
+ * CRYPTO_DECRYPT_* functions
+ */
+
+int
+decrypt_init(crypto_op_t *op)
+{
+ crypto_decrypt_init_t init;
+
+ bzero((void *)&init, sizeof (init));
+
+ init.di_session = op->hsession;
+
+ init.di_key.ck_data = op->key;
+ init.di_key.ck_format = CRYPTO_KEY_RAW; /* must be this */
+ init.di_key.ck_length = op->keylen;
+
+ init.di_mech.cm_type = op->mech;
+ init.di_mech.cm_param = op->param;
+ init.di_mech.cm_param_len = op->paramlen;
+
+ return (kcf_do_ioctl(CRYPTO_DECRYPT_INIT, (uint_t *)&init, "init"));
+}
+
+int
+decrypt_single(crypto_op_t *op)
+{
+ crypto_decrypt_t decrypt;
+
+ bzero(&decrypt, sizeof (decrypt));
+ decrypt.cd_session = op->hsession;
+ decrypt.cd_datalen = op->outlen;
+ decrypt.cd_databuf = op->out;
+ decrypt.cd_encrlen = op->inlen;
+ decrypt.cd_encrbuf = op->in;
+
+ return (kcf_do_ioctl(CRYPTO_DECRYPT, (uint_t *)&decrypt, "single"));
+}
+
+int
+decrypt_update(crypto_op_t *op, int offset, size_t *encrlen)
+{
+ crypto_decrypt_update_t update;
+ int ret;
+
+ bzero((void *)&update, sizeof (update));
+
+ update.du_session = op->hsession;
+ update.du_databuf = op->out + *encrlen;
+ update.du_datalen = op->outlen - *encrlen;
+ update.du_encrlen = op->updatelen;
+ update.du_encrbuf = op->in + offset;
+
+ ret = kcf_do_ioctl(CRYPTO_DECRYPT_UPDATE, (uint_t *)&update, "update");
+ *encrlen += update.du_datalen;
+ return (ret);
+}
+
+int
+decrypt_final(crypto_op_t *op, size_t encrlen)
+{
+ crypto_decrypt_final_t final;
+
+ bzero((void *)&final, sizeof (final));
+
+ final.df_session = op->hsession;
+ final.df_datalen = op->outlen - encrlen;
+ final.df_databuf = op->out + encrlen;
+
+ return (kcf_do_ioctl(CRYPTO_DECRYPT_FINAL, (uint_t *)&final, "final"));
+}
diff --git a/usr/src/test/crypto-tests/tests/common/cryptotest_pkcs.c b/usr/src/test/crypto-tests/tests/common/cryptotest_pkcs.c
new file mode 100644
index 0000000000..4a98a2aafc
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/common/cryptotest_pkcs.c
@@ -0,0 +1,401 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <stdio.h>
+#include <cryptoutil.h>
+
+#include "cryptotest.h"
+
+struct crypto_op {
+ CK_BYTE_PTR in;
+ CK_BYTE_PTR out;
+ CK_BYTE_PTR key;
+ CK_BYTE_PTR param;
+
+ size_t inlen;
+ size_t outlen;
+ size_t keylen;
+ size_t paramlen;
+ size_t updatelen;
+
+ char *mechname;
+
+ /* internal */
+ CK_MECHANISM_TYPE mech;
+ CK_OBJECT_HANDLE keyt;
+ CK_SESSION_HANDLE hsession;
+ size_t fg;
+};
+
+static void
+cryptotest_error(char *name, CK_RV rv)
+{
+ (void) fprintf(stderr, "%s: Error = 0x%.8lX '%s'\n",
+ name, rv, pkcs11_strerror(rv));
+}
+
+crypto_op_t *
+cryptotest_init(cryptotest_t *arg, size_t fg)
+{
+ crypto_op_t *op = malloc(sizeof (*op));
+
+ op->in = (CK_BYTE_PTR)arg->in;
+ op->out = (CK_BYTE_PTR)arg->out;
+ op->key = (CK_BYTE_PTR)arg->key;
+ op->param = (CK_BYTE_PTR)arg->param;
+
+ op->inlen = arg->inlen;
+ op->outlen = arg->outlen;
+ op->keylen = arg->keylen;
+ op->paramlen = arg->plen;
+ op->updatelen = arg->updatelen;
+
+ op->mechname = arg->mechname;
+
+ op->hsession = CRYPTO_INVALID_SESSION;
+ op->fg = fg;
+
+ if (op->out == NULL)
+ op->outlen = op->inlen;
+ return (op);
+}
+
+int
+cryptotest_close_session(CK_SESSION_HANDLE hsession)
+{
+ CK_RV rv;
+ rv = C_CloseSession(hsession);
+ if (rv != CKR_OK)
+ cryptotest_error("cryptotest_close_session", rv);
+
+ return (rv);
+}
+
+int
+cryptotest_close(crypto_op_t *op)
+{
+ (void) C_DestroyObject(op->hsession, op->keyt);
+ if (op->hsession != CRYPTO_INVALID_SESSION)
+ (void) cryptotest_close_session(op->hsession);
+ free(op);
+ return (C_Finalize(NULL));
+}
+
+int
+get_mech_info(crypto_op_t *op)
+{
+ CK_RV rv;
+ rv = pkcs11_str2mech(op->mechname, &op->mech);
+ if (rv != CKR_OK) {
+ cryptotest_error("get_mech_info", rv);
+ (void) fprintf(stderr, "failed to resolve mechanism name %s\n",
+ op->mechname);
+ (void) cryptotest_close(op);
+ return (CTEST_NAME_RESOLVE_FAILED);
+ }
+ return (rv);
+}
+
+
+int
+get_hsession_by_mech(crypto_op_t *op)
+{
+ CK_RV rv;
+ rv = SUNW_C_GetMechSession(op->mech, &op->hsession);
+ if (rv != CKR_OK) {
+ cryptotest_error("get_hsession_by_mech", rv);
+ (void) fprintf(stderr,
+ "could not find provider for mechanism %lu\n",
+ op->mech);
+ (void) cryptotest_close(op);
+ return (CTEST_MECH_NO_PROVIDER);
+ }
+ return (rv);
+}
+
+/*
+ * SIGN_* functions
+ */
+int
+sign_init(crypto_op_t *op)
+{
+ CK_MECHANISM mech;
+ CK_RV rv;
+
+ mech.mechanism = op->mech;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+
+ rv = SUNW_C_KeyToObject(op->hsession, op->mech,
+ op->key, op->keylen, &op->keyt);
+
+ if (rv != CKR_OK)
+ cryptotest_error("SUNW_C_KeyToObject", rv);
+
+ rv = C_SignInit(op->hsession, &mech, op->keyt);
+
+ if (rv != CKR_OK)
+ cryptotest_error("C_SignInit", rv);
+
+ return (rv);
+}
+
+int
+sign_single(crypto_op_t *op)
+{
+ CK_RV rv;
+
+ rv = C_Sign(op->hsession, op->in, op->inlen,
+ op->out, (CK_ULONG_PTR)&op->outlen);
+ if (rv != CKR_OK)
+ cryptotest_error("C_Sign", rv);
+ return (rv);
+}
+
+int
+sign_update(crypto_op_t *op, int offset)
+{
+ CK_RV rv;
+ rv = C_SignUpdate(op->hsession, op->in + offset, op->updatelen);
+ if (rv != CKR_OK)
+ cryptotest_error("C_SignUpdate", rv);
+
+ return (rv);
+}
+
+int
+sign_final(crypto_op_t *op)
+{
+ CK_RV rv;
+ rv = C_SignFinal(op->hsession, op->out, (CK_ULONG_PTR)&op->outlen);
+ if (rv != CKR_OK)
+ cryptotest_error("C_SignFinal", rv);
+ return (rv);
+}
+
+/*
+ * MAC_* functions
+ */
+int
+mac_init(crypto_op_t *op)
+{
+ return (sign_init(op));
+}
+
+int
+mac_single(crypto_op_t *op)
+{
+ return (sign_single(op));
+}
+
+int
+mac_update(crypto_op_t *op, int offset)
+{
+ return (sign_update(op, offset));
+}
+
+int
+mac_final(crypto_op_t *op)
+{
+ return (sign_final(op));
+}
+
+/*
+ * VERIFY_* functions
+ */
+int
+verify_init(crypto_op_t *op)
+{
+ CK_MECHANISM mech;
+ CK_RV rv;
+
+ mech.mechanism = op->mech;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+
+ rv = SUNW_C_KeyToObject(op->hsession, op->mech,
+ op->key, op->keylen, &op->keyt);
+
+ if (rv != CKR_OK)
+ cryptotest_error("SUNW_C_KeyToObject", rv);
+
+ rv = C_VerifyInit(op->hsession, &mech, op->keyt);
+
+ if (rv != CKR_OK)
+ cryptotest_error("C_VerifyInit", rv);
+
+ return (rv);
+}
+
+int
+verify_single(crypto_op_t *op)
+{
+ CK_RV rv;
+
+ rv = C_Verify(op->hsession, op->in, op->inlen, op->out, op->outlen);
+ if (rv != CKR_OK && rv != CKR_SIGNATURE_INVALID &&
+ rv != CKR_SIGNATURE_LEN_RANGE)
+ cryptotest_error("C_Verify", rv);
+ return (rv);
+}
+
+int
+verify_update(crypto_op_t *op, int offset)
+{
+ CK_RV rv;
+ rv = C_VerifyUpdate(op->hsession, op->in + offset, op->updatelen);
+ if (rv != CKR_OK)
+ cryptotest_error("C_VerifyUpdate", rv);
+ return (rv);
+}
+
+int
+verify_final(crypto_op_t *op)
+{
+ CK_RV rv;
+ rv = C_VerifyFinal(op->hsession, op->out, op->outlen);
+ if (rv != CKR_OK && rv != CKR_SIGNATURE_INVALID &&
+ rv != CKR_SIGNATURE_LEN_RANGE)
+ cryptotest_error("C_VerifyFinal", rv);
+ return (rv);
+}
+
+/*
+ * ENCRYPT_* functions
+ */
+int
+encrypt_init(crypto_op_t *op)
+{
+ CK_MECHANISM mech;
+ CK_RV rv;
+
+ mech.mechanism = op->mech;
+ mech.pParameter = op->param;
+ mech.ulParameterLen = op->paramlen;
+
+ rv = SUNW_C_KeyToObject(op->hsession, op->mech,
+ op->key, op->keylen, &op->keyt);
+
+ if (rv != CKR_OK)
+ cryptotest_error("SUNW_C_KeyToObject", rv);
+
+ rv = C_EncryptInit(op->hsession, &mech, op->keyt);
+
+ if (rv != CKR_OK)
+ cryptotest_error("C_EncryptInit", rv);
+
+ return (rv);
+}
+
+int
+encrypt_single(crypto_op_t *op)
+{
+ CK_RV rv;
+
+ rv = C_Encrypt(op->hsession, op->in, op->inlen,
+ op->out, (CK_ULONG_PTR)&op->outlen);
+ if (rv != CKR_OK)
+ cryptotest_error("C_Encrypt", rv);
+ return (rv);
+}
+
+int
+encrypt_update(crypto_op_t *op, int offset, size_t *encrlen)
+{
+ CK_RV rv;
+ CK_ULONG outlen = op->outlen - *encrlen;
+ rv = C_EncryptUpdate(op->hsession, op->in + offset, op->updatelen,
+ op->out + *encrlen, &outlen);
+ if (rv != CKR_OK)
+ cryptotest_error("C_EncryptUpdate", rv);
+
+ *encrlen += outlen;
+ return (rv);
+}
+
+int
+encrypt_final(crypto_op_t *op, size_t encrlen)
+{
+ CK_RV rv;
+ CK_ULONG outlen = op->outlen - encrlen;
+ rv = C_EncryptFinal(op->hsession, op->out + encrlen, &outlen);
+ if (rv != CKR_OK)
+ cryptotest_error("C_EncryptFinal", rv);
+ return (rv);
+}
+
+/*
+ * DECRYPT_* functions
+ */
+int
+decrypt_init(crypto_op_t *op)
+{
+ CK_MECHANISM mech;
+ CK_RV rv;
+
+ mech.mechanism = op->mech;
+ mech.pParameter = op->param;
+ mech.ulParameterLen = op->paramlen;
+
+ rv = SUNW_C_KeyToObject(op->hsession, op->mech,
+ op->key, op->keylen, &op->keyt);
+
+ if (rv != CKR_OK)
+ cryptotest_error("SUNW_C_KeyToObject", rv);
+
+ rv = C_DecryptInit(op->hsession, &mech, op->keyt);
+
+ if (rv != CKR_OK)
+ cryptotest_error("C_DecryptInit", rv);
+
+ return (rv);
+}
+
+int
+decrypt_single(crypto_op_t *op)
+{
+ CK_RV rv;
+
+ rv = C_Decrypt(op->hsession, op->in, op->inlen,
+ op->out, (CK_ULONG_PTR)&op->outlen);
+ if (rv != CKR_OK)
+ cryptotest_error("C_Decrypt", rv);
+ return (rv);
+}
+
+int
+decrypt_update(crypto_op_t *op, int offset, size_t *encrlen)
+{
+ CK_RV rv;
+ CK_ULONG outlen = op->outlen - *encrlen;
+ rv = C_DecryptUpdate(op->hsession, op->in + offset, op->updatelen,
+ op->out + *encrlen, &outlen);
+ if (rv != CKR_OK)
+ cryptotest_error("C_DecryptUpdate", rv);
+
+ *encrlen += outlen;
+ return (rv);
+}
+
+int
+decrypt_final(crypto_op_t *op, size_t encrlen)
+{
+ CK_RV rv;
+ CK_ULONG outlen = op->outlen - encrlen;
+ rv = C_DecryptFinal(op->hsession, op->out + encrlen, &outlen);
+ if (rv != CKR_OK)
+ cryptotest_error("C_DecryptFinal", rv);
+ return (rv);
+}
diff --git a/usr/src/test/crypto-tests/tests/common/testfuncs.c b/usr/src/test/crypto-tests/tests/common/testfuncs.c
new file mode 100644
index 0000000000..f4aacce111
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/common/testfuncs.c
@@ -0,0 +1,268 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#define __EXTENSIONS__
+#include <strings.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "cryptotest.h"
+
+
+
+test_fg_t cryptotest_decr_fg = {test_decrypt_single, test_decrypt};
+test_fg_t cryptotest_encr_fg = {test_encrypt_single, test_encrypt};
+test_fg_t cryptotest_mac_fg = {test_mac_single, test_mac};
+
+/*
+ * Utils
+ */
+
+void
+printbuf(uint8_t *buf, char *name, size_t size)
+{
+ size_t i;
+
+ flockfile(stderr);
+ (void) fprintf(stderr, "%s%s", name, (size > 0) ? " " : "");
+ for (i = 0; i < size; i++)
+ (void) fprintf(stderr, "%02x", buf[i]);
+ (void) fputc('\n', stderr);
+ funlockfile(stderr);
+}
+
+int
+bufcmp(uint8_t *auth, uint8_t *cmp, size_t size)
+{
+ if (memcmp(cmp, auth, size) != 0) {
+ (void) fprintf(stderr, "mismatched result\n\n");
+ printbuf(cmp, "calc", size);
+ printbuf(auth, "orig", size);
+ return (1);
+ } else {
+ (void) fprintf(stderr, "result matches\n\n");
+ return (0);
+ }
+}
+
+/*
+ * Wrapper functions
+ */
+
+int
+run_test(cryptotest_t *args, uint8_t *cmp, size_t cmplen,
+ test_fg_t *funcs)
+{
+ int ret, errs = 0;
+ static int i = 0;
+
+ (void) fprintf(stderr, "%s: run %d\n", args->mechname, ++i);
+ bzero(args->out, args->outlen);
+ ret = funcs->update(args);
+ if (ret > 0) {
+ (void) fprintf(stderr, "failure %x\n", ret);
+ errs += 1;
+ } else if (ret < 0) {
+ (void) fprintf(stderr, "fatal error %d\n", ret);
+ exit(1);
+ } else
+ errs += bufcmp(cmp, args->out, cmplen);
+
+ bzero(args->out, args->outlen);
+ ret = funcs->single(args);
+ if (ret > 0) {
+ (void) fprintf(stderr, "failure %x\n", ret);
+ errs += 1;
+ } else if (ret < 0) {
+ (void) fprintf(stderr, "fatal error %d\n", ret);
+ exit(2);
+ } else
+ errs += bufcmp(cmp, args->out, cmplen);
+
+ return (errs);
+}
+
+static int
+test_mac_common(cryptotest_t *args, boolean_t AIO)
+{
+ int ret, i;
+ crypto_op_t *crypto_op;
+
+ if (args->in == NULL || args->key == NULL)
+ return (CRYPTO_FAILED);
+
+ if ((crypto_op = cryptotest_init(args, CRYPTO_FG_MAC)) == NULL) {
+ (void) fprintf(stderr, "Error occured during initialization\n");
+ (void) cryptotest_close(NULL);
+ return (CTEST_INIT_FAILED);
+ }
+
+ if ((ret = get_mech_info(crypto_op)) != CRYPTO_SUCCESS)
+ goto out;
+
+ if ((ret = get_hsession_by_mech(crypto_op)) != CRYPTO_SUCCESS)
+ goto out;
+
+ if ((ret = mac_init(crypto_op)) != CRYPTO_SUCCESS)
+ goto out;
+
+ if (AIO) {
+ if ((ret = mac_single(crypto_op)) != CRYPTO_SUCCESS)
+ goto out;
+ } else {
+ for (i = 0; i < args->inlen; i += args->updatelen) {
+
+ if ((ret = mac_update(crypto_op, i)) != CRYPTO_SUCCESS)
+ goto out;
+ }
+
+ if ((ret = mac_final(crypto_op)) != CRYPTO_SUCCESS)
+ goto out;
+
+ }
+
+out:
+ (void) cryptotest_close(crypto_op);
+ return (ret);
+}
+
+int
+test_mac_single(cryptotest_t *args)
+{
+ return (test_mac_common(args, B_TRUE));
+}
+
+int
+test_mac(cryptotest_t *args)
+{
+ return (test_mac_common(args, B_FALSE));
+}
+
+static int
+test_encrypt_common(cryptotest_t *args, boolean_t AIO)
+{
+ int ret, i;
+ size_t encrlen = 0;
+ crypto_op_t *crypto_op;
+
+ if (args->key == NULL)
+ return (CRYPTO_FAILED);
+
+ if ((crypto_op = cryptotest_init(args, CRYPTO_FG_ENCRYPT)) == NULL) {
+ (void) fprintf(stderr, "Error occured during initialization\n");
+ (void) cryptotest_close(NULL);
+ return (CTEST_INIT_FAILED);
+ }
+
+ if ((ret = get_mech_info(crypto_op)) != CRYPTO_SUCCESS)
+ goto out;
+
+ if ((ret = get_hsession_by_mech(crypto_op)) != CRYPTO_SUCCESS)
+ goto out;
+
+ if ((ret = encrypt_init(crypto_op)) != CRYPTO_SUCCESS)
+ goto out;
+
+ if (AIO) {
+ if ((ret = encrypt_single(crypto_op)) != CRYPTO_SUCCESS)
+ goto out;
+ } else {
+ for (i = 0; i < args->inlen; i += args->updatelen) {
+
+ if ((ret = encrypt_update(crypto_op, i,
+ &encrlen)) != CRYPTO_SUCCESS)
+ goto out;
+ }
+
+ if ((ret = encrypt_final(crypto_op, encrlen)) != CRYPTO_SUCCESS)
+ goto out;
+
+ }
+
+out:
+ (void) cryptotest_close(crypto_op);
+ return (ret);
+}
+
+int
+test_encrypt_single(cryptotest_t *args)
+{
+ return (test_encrypt_common(args, B_TRUE));
+}
+
+
+int
+test_encrypt(cryptotest_t *args)
+{
+ return (test_encrypt_common(args, B_FALSE));
+}
+
+static int
+test_decrypt_common(cryptotest_t *args, boolean_t AIO)
+{
+ int ret, i;
+ size_t encrlen = 0;
+ crypto_op_t *crypto_op;
+
+ if (args->key == NULL)
+ return (CRYPTO_FAILED);
+
+ if ((crypto_op = cryptotest_init(args, CRYPTO_FG_DECRYPT)) == NULL) {
+ (void) fprintf(stderr, "Error occured during initialization\n");
+ (void) cryptotest_close(NULL);
+ return (CTEST_INIT_FAILED);
+ }
+
+ if ((ret = get_mech_info(crypto_op)) != CRYPTO_SUCCESS)
+ goto out;
+
+ if ((ret = get_hsession_by_mech(crypto_op)) != CRYPTO_SUCCESS)
+ goto out;
+
+ if ((ret = decrypt_init(crypto_op)) != CRYPTO_SUCCESS)
+ goto out;
+
+ if (AIO) {
+ if ((ret = decrypt_single(crypto_op)) != CRYPTO_SUCCESS)
+ goto out;
+ } else {
+ for (i = 0; i < args->inlen; i += args->updatelen) {
+
+ if ((ret = decrypt_update(crypto_op, i,
+ &encrlen)) != CRYPTO_SUCCESS)
+ goto out;
+ }
+
+ if ((ret = decrypt_final(crypto_op, encrlen)) != CRYPTO_SUCCESS)
+ goto out;
+
+ }
+
+out:
+ (void) cryptotest_close(crypto_op);
+ return (ret);
+}
+
+int
+test_decrypt_single(cryptotest_t *args)
+{
+ return (test_decrypt_common(args, B_TRUE));
+}
+
+
+int
+test_decrypt(cryptotest_t *args)
+{
+ return (test_decrypt_common(args, B_FALSE));
+}
diff --git a/usr/src/test/crypto-tests/tests/modes/Makefile b/usr/src/test/crypto-tests/tests/modes/Makefile
new file mode 100644
index 0000000000..c8dc4e360b
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/Makefile
@@ -0,0 +1,21 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+.PARALLEL: $(SUBDIRS)
+
+SUBDIRS = aes
+
+include $(SRC)/test/Makefile.com
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/Makefile b/usr/src/test/crypto-tests/tests/modes/aes/Makefile
new file mode 100644
index 0000000000..a58f77eb94
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/Makefile
@@ -0,0 +1,21 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+.PARALLEL: $(SUBDIRS)
+
+SUBDIRS = cbc ccm cmac ctr ecb gcm
+
+include $(SRC)/test/Makefile.com
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/Makefile.subdirs b/usr/src/test/crypto-tests/tests/modes/aes/Makefile.subdirs
new file mode 100644
index 0000000000..d0dc303420
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/Makefile.subdirs
@@ -0,0 +1,82 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+include $(SRC)/test/Makefile.com
+
+CRYPTO = pkcs kcf
+PROGS = $(CRYPTO:%=$(PROG)_%)
+ROOTOPTPKG = $(ROOT)/opt/crypto-tests
+TESTROOT = $(ROOTOPTPKG)/tests/#$(SUFFIX)/aes
+TESTDIR = $(CRYPTO:%=$(TESTROOT)/%/aes)
+
+COMMONDIR = ../../../common
+OBJS_COMMON = testfuncs.o
+OBJS_COMDIR = $(OBJS_COMMON:%=$(COMMONDIR)/%)
+OBJS_LOCAL = $(PROG:%=%.o)
+OBJS = $(OBJS_LOCAL) $(OBJS_COMDIR)
+OBJS_PKCS = $(OBJS_LOCAL) $(OBJS_COMDIR) $(COMMONDIR)/cryptotest_pkcs.o
+OBJS_KCF = $(OBJS_LOCAL) $(OBJS_COMDIR) $(COMMONDIR)/cryptotest_kcf.o
+SRCS = $(OBJS:%.o=%.c)
+PKCSLIBS = -lpkcs11 -lcryptoutil
+
+C99MODE = -xc99=%all
+
+CMDS = $(TESTDIR:%=%/$(PROG))
+$(CMDS) := FILEMODE = 0555
+
+LINTFLAGS += -xerroff=E_NAME_USED_NOT_DEF2
+LINTFLAGS += -xerroff=E_NAME_DEF_NOT_USED2
+
+CPPFLAGS += -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I$(COMMONDIR) -I$(SRC)/common/crypto/
+
+all: $(PROGS)
+
+$(PROG)_kcf: $(OBJS_KCF)
+ $(LINK.c) $(OBJS_KCF) -o $@ $(LDLIBS)
+ $(POST_PROCESS)
+
+$(PROG)_pkcs: $(OBJS_PKCS)
+ $(LINK.c) $(OBJS_PKCS) -o $@ $(LDLIBS) $(PKCSLIBS)
+ $(POST_PROCESS)
+
+
+$(COMMONDIR)/%.o:
+
+%.o: %.c
+ $(COMPILE.c) -o $@ $<
+
+install: all $(CMDS)
+
+lint: $(CRYPTO:%=lint_%)
+
+lint_pkcs:
+ $(LINT.c) $(OBJS_PKCS:%.o=%.c) $(LDLIBS) $(PKCSLIBS)
+
+lint_kcf:
+ $(LINT.c) $(OBJS_KCF:%.o=%.c) $(LDLIBS)
+clobber: clean
+ -$(RM) $(PROGS)
+
+clean:
+ -$(RM) $(OBJS_LOCAL)
+
+$(CMDS): $(TESTDIR) $(PROGS)
+
+$(TESTDIR):
+ $(INS.dir)
+
+$(TESTROOT)/%/aes/$(PROG): $(PROG)_%
+ $(INS.rename)
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/cbc/Makefile b/usr/src/test/crypto-tests/tests/modes/aes/cbc/Makefile
new file mode 100644
index 0000000000..e74dc104bd
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/cbc/Makefile
@@ -0,0 +1,20 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+PROG = aes_cbc
+
+include $(SRC)/cmd/Makefile.cmd
+include ../Makefile.subdirs
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/cbc/aes_cbc.c b/usr/src/test/crypto-tests/tests/modes/aes/cbc/aes_cbc.c
new file mode 100644
index 0000000000..446f3f27ab
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/cbc/aes_cbc.c
@@ -0,0 +1,69 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <aes/aes_impl.h>
+#include <stdio.h>
+
+#include "cryptotest.h"
+#include "aes_cbc.h"
+
+int
+main(void)
+{
+ int errs = 0;
+ int i;
+ uint8_t N[1024];
+ cryptotest_t args;
+
+ args.out = N;
+
+ args.outlen = sizeof (N);
+ args.plen = AES_BLOCK_LEN;
+
+ args.mechname = SUN_CKM_AES_CBC;
+ args.updatelen = 1;
+
+
+ for (i = 0; i < sizeof (RES) / sizeof (RES[0]); i++) {
+ args.in = DATA[i];
+ args.key = KEY[i];
+ args.param = IV[i];
+
+ args.inlen = DATALEN[i];
+ args.keylen = KEYLEN[i];
+
+ errs += run_test(&args, RES[i], RESLEN[i], ENCR_FG);
+ (void) fprintf(stderr, "----------\n");
+ }
+
+ (void) fprintf(stderr, "\t\t\t=== decrypt ===\n----------\n\n");
+
+ for (i = 0; i < sizeof (RES) / sizeof (RES[0]); i++) {
+ args.in = RES[i];
+ args.key = KEY[i];
+ args.param = IV[i];
+
+ args.inlen = RESLEN[i];
+ args.keylen = KEYLEN[i];
+
+ errs += run_test(&args, DATA[i], DATALEN[i], DECR_FG);
+ (void) fprintf(stderr, "----------\n");
+ }
+
+ if (errs != 0)
+ (void) fprintf(stderr, "%d tests failed\n", errs);
+
+ return (errs);
+}
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/cbc/aes_cbc.h b/usr/src/test/crypto-tests/tests/modes/aes/cbc/aes_cbc.h
new file mode 100644
index 0000000000..8a4dea540c
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/cbc/aes_cbc.h
@@ -0,0 +1,173 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _AES_CBC_H
+#define _AES_CBC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Test vectors
+ * RFC3602 section 4
+ */
+
+static uint8_t CBC1_KEY[16] = {
+ 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
+ 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06,
+};
+static uint8_t CBC1_IV[16] = {
+ 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
+ 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41,
+};
+static uint8_t CBC1_DATA[] = {
+ 'S', 'i', 'n', 'g', 'l', 'e', ' ', 'b',
+ 'l', 'o', 'c', 'k', ' ', 'm', 's', 'g',
+};
+static uint8_t CBC1_RES[] = {
+ 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8,
+ 0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a,
+};
+
+static uint8_t CBC2_KEY[] = {
+ 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
+ 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a,
+};
+static uint8_t CBC2_IV[] = {
+ 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
+ 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58,
+};
+static uint8_t CBC2_DATA[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
+};
+static uint8_t CBC2_RES[] = {
+ 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a,
+ 0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a,
+
+ 0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9,
+ 0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1,
+};
+
+static uint8_t CBC3_KEY[] = {
+ 0x6c, 0x3e, 0xa0, 0x47, 0x76, 0x30, 0xce, 0x21,
+ 0xa2, 0xce, 0x33, 0x4a, 0xa7, 0x46, 0xc2, 0xcd,
+};
+static uint8_t CBC3_IV[] = {
+ 0xc7, 0x82, 0xdc, 0x4c, 0x09, 0x8c, 0x66, 0xcb,
+ 0xd9, 0xcd, 0x27, 0xd8, 0x25, 0x68, 0x2c, 0x81,
+};
+static uint8_t CBC3_DATA[] = {
+ 'T', 'h', 'i', 's', ' ', 'i', 's', ' ',
+ 'a', ' ', '4', '8', '-', 'b', 'y', 't',
+
+ 'e', ' ', 'm', 'e', 's', 's', 'a', 'g',
+ 'e', ' ', '(', 'e', 'x', 'a', 'c', 't',
+
+ 'l', 'y', ' ', '3', ' ', 'A', 'E', 'S',
+ ' ', 'b', 'l', 'o', 'c', 'k', 's', ')',
+};
+
+static uint8_t CBC3_RES[] = {
+ 0xd0, 0xa0, 0x2b, 0x38, 0x36, 0x45, 0x17, 0x53,
+ 0xd4, 0x93, 0x66, 0x5d, 0x33, 0xf0, 0xe8, 0x86,
+
+ 0x2d, 0xea, 0x54, 0xcd, 0xb2, 0x93, 0xab, 0xc7,
+ 0x50, 0x69, 0x39, 0x27, 0x67, 0x72, 0xf8, 0xd5,
+
+ 0x02, 0x1c, 0x19, 0x21, 0x6b, 0xad, 0x52, 0x5c,
+ 0x85, 0x79, 0x69, 0x5d, 0x83, 0xba, 0x26, 0x84,
+};
+
+static uint8_t CBC4_KEY[] = {
+ 0x56, 0xe4, 0x7a, 0x38, 0xc5, 0x59, 0x89, 0x74,
+ 0xbc, 0x46, 0x90, 0x3d, 0xba, 0x29, 0x03, 0x49,
+};
+static uint8_t CBC4_IV[] = {
+ 0x8c, 0xe8, 0x2e, 0xef, 0xbe, 0xa0, 0xda, 0x3c,
+ 0x44, 0x69, 0x9e, 0xd7, 0xdb, 0x51, 0xb7, 0xd9,
+};
+static uint8_t CBC4_DATA[] = {
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+};
+static uint8_t CBC4_RES[] = {
+ 0xc3, 0x0e, 0x32, 0xff, 0xed, 0xc0, 0x77, 0x4e,
+ 0x6a, 0xff, 0x6a, 0xf0, 0x86, 0x9f, 0x71, 0xaa,
+
+ 0x0f, 0x3a, 0xf0, 0x7a, 0x9a, 0x31, 0xa9, 0xc6,
+ 0x84, 0xdb, 0x20, 0x7e, 0xb0, 0xef, 0x8e, 0x4e,
+
+ 0x35, 0x90, 0x7a, 0xa6, 0x32, 0xc3, 0xff, 0xdf,
+ 0x86, 0x8b, 0xb7, 0xb2, 0x9d, 0x3d, 0x46, 0xad,
+
+ 0x83, 0xce, 0x9f, 0x9a, 0x10, 0x2e, 0xe9, 0x9d,
+ 0x49, 0xa5, 0x3e, 0x87, 0xf4, 0xc3, 0xda, 0x55,
+};
+
+uint8_t *DATA[] = {
+ CBC1_DATA, CBC2_DATA, CBC3_DATA, CBC4_DATA
+};
+
+size_t DATALEN[] = {
+ sizeof (CBC1_DATA), sizeof (CBC2_DATA),
+ sizeof (CBC3_DATA), sizeof (CBC4_DATA),
+};
+
+uint8_t *KEY[] = {
+ CBC1_KEY, CBC2_KEY, CBC3_KEY, CBC4_KEY
+};
+
+size_t KEYLEN[] = {
+ sizeof (CBC1_KEY), sizeof (CBC2_KEY),
+ sizeof (CBC3_KEY), sizeof (CBC4_KEY),
+};
+
+uint8_t *IV[] = {
+ CBC1_IV, CBC2_IV, CBC3_IV, CBC4_IV
+};
+
+size_t IVLEN[] = {
+ sizeof (CBC1_IV), sizeof (CBC2_IV),
+ sizeof (CBC3_IV), sizeof (CBC4_IV),
+};
+
+uint8_t *RES[] = {
+ CBC1_RES, CBC2_RES, CBC3_RES, CBC4_RES
+};
+
+size_t RESLEN[] = {
+ sizeof (CBC1_RES), sizeof (CBC2_RES),
+ sizeof (CBC3_RES), sizeof (CBC4_RES),
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AES_CBC_H */
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/ccm/Makefile b/usr/src/test/crypto-tests/tests/modes/aes/ccm/Makefile
new file mode 100644
index 0000000000..28ec598193
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/ccm/Makefile
@@ -0,0 +1,20 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+PROG = aes_ccm
+
+include $(SRC)/cmd/Makefile.cmd
+include ../Makefile.subdirs
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/ccm/aes_ccm.c b/usr/src/test/crypto-tests/tests/modes/aes/ccm/aes_ccm.c
new file mode 100644
index 0000000000..a01129547e
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/ccm/aes_ccm.c
@@ -0,0 +1,120 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <strings.h>
+#include <stdio.h>
+
+#include "cryptotest.h"
+#include "aes_ccm.h"
+
+int
+main(void)
+{
+ int errs = 0;
+ int i;
+ uint8_t N[1024];
+ CK_AES_CCM_PARAMS param;
+ cryptotest_t args;
+
+ bzero(&param, sizeof (param));
+
+ args.out = N;
+ args.param = &param;
+
+ args.outlen = sizeof (N);
+ args.plen = sizeof (param);
+
+ args.mechname = SUN_CKM_AES_CCM;
+ args.updatelen = 1;
+
+ param.authData = CCM_DATA1;
+ args.key = CCM_KEY1;
+ args.keylen = sizeof (CCM_KEY1);
+ for (i = 0; i < 12; i++) {
+ param.ulMACSize = MACLEN[i];
+ param.ulNonceSize = NONCELEN[i];
+ param.ulAuthDataSize = AUTHLEN[i];
+ param.ulDataSize = DATALEN[i] - AUTHLEN[i];
+ param.nonce = NONCE[i];
+
+ args.in = CCM_DATA1 + AUTHLEN[i];
+ args.inlen = DATALEN[i] - AUTHLEN[i];
+
+ errs += run_test(&args, RES[i] + AUTHLEN[i],
+ RESLEN[i] - AUTHLEN[i], ENCR_FG);
+ (void) fprintf(stderr, "----------\n");
+ }
+
+ args.key = CCM_KEY2;
+ args.keylen = sizeof (CCM_KEY2);
+ for (i = 12; i < 24; i++) {
+ param.ulMACSize = MACLEN[i];
+ param.ulNonceSize = NONCELEN[i];
+ param.ulAuthDataSize = AUTHLEN[i];
+ param.ulDataSize = DATALEN[i] - AUTHLEN[i];
+ param.nonce = NONCE[i];
+ param.authData = DATA_2[i-12];
+
+ args.in = DATA_2[i-12] + AUTHLEN[i];
+ args.inlen = DATALEN[i] - AUTHLEN[i];
+
+ errs += run_test(&args, RES[i] + AUTHLEN[i],
+ RESLEN[i] - AUTHLEN[i], ENCR_FG);
+ (void) fprintf(stderr, "----------\n");
+ }
+
+ (void) fprintf(stderr, "\t\t\t=== decrypt ===\n----------\n\n");
+
+ param.authData = CCM_DATA1;
+ args.key = CCM_KEY1;
+ args.keylen = sizeof (CCM_KEY1);
+ for (i = 0; i < 12; i++) {
+ param.ulMACSize = MACLEN[i];
+ param.ulNonceSize = NONCELEN[i];
+ param.ulAuthDataSize = AUTHLEN[i];
+ param.ulDataSize = RESLEN[i] - AUTHLEN[i];
+ param.nonce = NONCE[i];
+
+ args.in = RES[i] + AUTHLEN[i];
+ args.inlen = RESLEN[i] - AUTHLEN[i];
+
+ errs += run_test(&args, CCM_DATA1 + AUTHLEN[i],
+ DATALEN[i] - AUTHLEN[i], DECR_FG);
+ (void) fprintf(stderr, "----------\n");
+ }
+
+ args.key = CCM_KEY2;
+ args.keylen = sizeof (CCM_KEY2);
+ for (i = 12; i < 24; i++) {
+ param.ulMACSize = MACLEN[i];
+ param.ulNonceSize = NONCELEN[i];
+ param.ulAuthDataSize = AUTHLEN[i];
+ param.ulDataSize = RESLEN[i] - AUTHLEN[i];
+ param.nonce = NONCE[i];
+ param.authData = DATA_2[i-12];
+
+ args.in = RES[i] + AUTHLEN[i];
+ args.inlen = RESLEN[i] - AUTHLEN[i];
+
+ errs += run_test(&args, DATA_2[i-12] + AUTHLEN[i],
+ DATALEN[i] - AUTHLEN[i], ENCR_FG);
+ (void) fprintf(stderr, "----------\n");
+ }
+
+ if (errs != 0)
+ (void) fprintf(stderr, "%d tests failed\n", errs);
+
+ return (errs);
+}
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/ccm/aes_ccm.h b/usr/src/test/crypto-tests/tests/modes/aes/ccm/aes_ccm.h
new file mode 100644
index 0000000000..c23ecffe4b
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/ccm/aes_ccm.h
@@ -0,0 +1,481 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _AES_CCM_H
+#define _AES_CCM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Test vectors
+ * RFC3610 section 4
+ */
+
+/*
+ * 1st half
+ */
+static uint8_t CCM_KEY1[16] = {
+ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
+};
+
+/* nonces */
+static uint8_t CCM1_N[] = {
+ 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0,
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5,
+};
+static uint8_t CCM2_N[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01, 0xA0,
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5,
+};
+static uint8_t CCM3_N[] = {
+ 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x02, 0xA0,
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5,
+};
+static uint8_t CCM4_N[] = {
+ 0x00, 0x00, 0x00, 0x06, 0x05, 0x04, 0x03, 0xA0,
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5,
+};
+static uint8_t CCM5_N[] = {
+ 0x00, 0x00, 0x00, 0x07, 0x06, 0x05, 0x04, 0xA0,
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5,
+};
+static uint8_t CCM6_N[] = {
+ 0x00, 0x00, 0x00, 0x08, 0x07, 0x06, 0x05, 0xA0,
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5,
+};
+static uint8_t CCM7_N[] = {
+ 0x00, 0x00, 0x00, 0x09, 0x08, 0x07, 0x06, 0xA0,
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5,
+};
+static uint8_t CCM8_N[] = {
+ 0x00, 0x00, 0x00, 0x0A, 0x09, 0x08, 0x07, 0xA0,
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5,
+};
+static uint8_t CCM9_N[] = {
+ 0x00, 0x00, 0x00, 0x0B, 0x0A, 0x09, 0x08, 0xA0,
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5,
+};
+static uint8_t CCM10_N[] = {
+ 0x00, 0x00, 0x00, 0x0C, 0x0B, 0x0A, 0x09, 0xA0,
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5,
+};
+static uint8_t CCM11_N[] = {
+ 0x00, 0x00, 0x00, 0x0D, 0x0C, 0x0B, 0x0A, 0xA0,
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5,
+};
+static uint8_t CCM12_N[] = {
+ 0x00, 0x00, 0x00, 0x0E, 0x0D, 0x0C, 0x0B, 0xA0,
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5,
+};
+
+/* vector data is a subset of this */
+static uint8_t CCM_DATA1[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20,
+};
+
+/* results */
+static uint8_t CCM1_RES[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x58, 0x8C, 0x97, 0x9A, 0x61, 0xC6, 0x63, 0xD2,
+ 0xF0, 0x66, 0xD0, 0xC2, 0xC0, 0xF9, 0x89, 0x80,
+ 0x6D, 0x5F, 0x6B, 0x61, 0xDA, 0xC3, 0x84, 0x17,
+ 0xE8, 0xD1, 0x2C, 0xFD, 0xF9, 0x26, 0xE0,
+};
+static uint8_t CCM2_RES[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x72, 0xC9, 0x1A, 0x36, 0xE1, 0x35, 0xF8, 0xCF,
+ 0x29, 0x1C, 0xA8, 0x94, 0x08, 0x5C, 0x87, 0xE3,
+ 0xCC, 0x15, 0xC4, 0x39, 0xC9, 0xE4, 0x3A, 0x3B,
+ 0xA0, 0x91, 0xD5, 0x6E, 0x10, 0x40, 0x09, 0x16,
+};
+static uint8_t CCM3_RES[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x51, 0xB1, 0xE5, 0xF4, 0x4A, 0x19, 0x7D, 0x1D,
+ 0xA4, 0x6B, 0x0F, 0x8E, 0x2D, 0x28, 0x2A, 0xE8,
+ 0x71, 0xE8, 0x38, 0xBB, 0x64, 0xDA, 0x85, 0x96,
+ 0x57, 0x4A, 0xDA, 0xA7, 0x6F, 0xBD, 0x9F, 0xB0,
+ 0xC5,
+};
+static uint8_t CCM4_RES[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0xA2, 0x8C, 0x68, 0x65,
+ 0x93, 0x9A, 0x9A, 0x79, 0xFA, 0xAA, 0x5C, 0x4C,
+ 0x2A, 0x9D, 0x4A, 0x91, 0xCD, 0xAC, 0x8C, 0x96,
+ 0xC8, 0x61, 0xB9, 0xC9, 0xE6, 0x1E, 0xF1,
+};
+static uint8_t CCM5_RES[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0xDC, 0xF1, 0xFB, 0x7B,
+ 0x5D, 0x9E, 0x23, 0xFB, 0x9D, 0x4E, 0x13, 0x12,
+ 0x53, 0x65, 0x8A, 0xD8, 0x6E, 0xBD, 0xCA, 0x3E,
+ 0x51, 0xE8, 0x3F, 0x07, 0x7D, 0x9C, 0x2D, 0x93,
+};
+static uint8_t CCM6_RES[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x6F, 0xC1, 0xB0, 0x11,
+ 0xF0, 0x06, 0x56, 0x8B, 0x51, 0x71, 0xA4, 0x2D,
+ 0x95, 0x3D, 0x46, 0x9B, 0x25, 0x70, 0xA4, 0xBD,
+ 0x87, 0x40, 0x5A, 0x04, 0x43, 0xAC, 0x91, 0xCB,
+ 0x94,
+};
+static uint8_t CCM7_RES[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x01, 0x35, 0xD1, 0xB2, 0xC9, 0x5F, 0x41, 0xD5,
+ 0xD1, 0xD4, 0xFE, 0xC1, 0x85, 0xD1, 0x66, 0xB8,
+ 0x09, 0x4E, 0x99, 0x9D, 0xFE, 0xD9, 0x6C, 0x04,
+ 0x8C, 0x56, 0x60, 0x2C, 0x97, 0xAC, 0xBB, 0x74,
+ 0x90,
+};
+static uint8_t CCM8_RES[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x7B, 0x75, 0x39, 0x9A, 0xC0, 0x83, 0x1D, 0xD2,
+ 0xF0, 0xBB, 0xD7, 0x58, 0x79, 0xA2, 0xFD, 0x8F,
+ 0x6C, 0xAE, 0x6B, 0x6C, 0xD9, 0xB7, 0xDB, 0x24,
+ 0xC1, 0x7B, 0x44, 0x33, 0xF4, 0x34, 0x96, 0x3F,
+ 0x34, 0xB4,
+};
+static uint8_t CCM9_RES[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x82, 0x53, 0x1A, 0x60, 0xCC, 0x24, 0x94, 0x5A,
+ 0x4B, 0x82, 0x79, 0x18, 0x1A, 0xB5, 0xC8, 0x4D,
+ 0xF2, 0x1C, 0xE7, 0xF9, 0xB7, 0x3F, 0x42, 0xE1,
+ 0x97, 0xEA, 0x9C, 0x07, 0xE5, 0x6B, 0x5E, 0xB1,
+ 0x7E, 0x5F, 0x4E,
+};
+static uint8_t CCM10_RES[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x07, 0x34, 0x25, 0x94,
+ 0x15, 0x77, 0x85, 0x15, 0x2B, 0x07, 0x40, 0x98,
+ 0x33, 0x0A, 0xBB, 0x14, 0x1B, 0x94, 0x7B, 0x56,
+ 0x6A, 0xA9, 0x40, 0x6B, 0x4D, 0x99, 0x99, 0x88,
+ 0xDD,
+};
+static uint8_t CCM11_RES[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x67, 0x6B, 0xB2, 0x03,
+ 0x80, 0xB0, 0xE3, 0x01, 0xE8, 0xAB, 0x79, 0x59,
+ 0x0A, 0x39, 0x6D, 0xA7, 0x8B, 0x83, 0x49, 0x34,
+ 0xF5, 0x3A, 0xA2, 0xE9, 0x10, 0x7A, 0x8B, 0x6C,
+ 0x02, 0x2C,
+};
+static uint8_t CCM12_RES[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0xC0, 0xFF, 0xA0, 0xD6,
+ 0xF0, 0x5B, 0xDB, 0x67, 0xF2, 0x4D, 0x43, 0xA4,
+ 0x33, 0x8D, 0x2A, 0xA4, 0xBE, 0xD7, 0xB2, 0x0E,
+ 0x43, 0xCD, 0x1A, 0xA3, 0x16, 0x62, 0xE7, 0xAD,
+ 0x65, 0xD6, 0xDB,
+};
+
+
+/*
+ * 2nd half
+ */
+static uint8_t CCM_KEY2[16] = {
+ 0xD7, 0x82, 0x8D, 0x13, 0xB2, 0xB0, 0xBD, 0xC3,
+ 0x25, 0xA7, 0x62, 0x36, 0xDF, 0x93, 0xCC, 0x6B,
+};
+
+/* nonces */
+static uint8_t CCM13_N[] = {
+ 0x00, 0x41, 0x2B, 0x4E, 0xA9, 0xCD, 0xBE, 0x3C,
+ 0x96, 0x96, 0x76, 0x6C, 0xFA,
+};
+static uint8_t CCM14_N[] = {
+ 0x00, 0x33, 0x56, 0x8E, 0xF7, 0xB2, 0x63, 0x3C,
+ 0x96, 0x96, 0x76, 0x6C, 0xFA,
+};
+static uint8_t CCM15_N[] = {
+ 0x00, 0x10, 0x3F, 0xE4, 0x13, 0x36, 0x71, 0x3C,
+ 0x96, 0x96, 0x76, 0x6C, 0xFA,
+};
+static uint8_t CCM16_N[] = {
+ 0x00, 0x76, 0x4C, 0x63, 0xB8, 0x05, 0x8E, 0x3C,
+ 0x96, 0x96, 0x76, 0x6C, 0xFA,
+};
+static uint8_t CCM17_N[] = {
+ 0x00, 0xF8, 0xB6, 0x78, 0x09, 0x4E, 0x3B, 0x3C,
+ 0x96, 0x96, 0x76, 0x6C, 0xFA,
+};
+static uint8_t CCM18_N[] = {
+ 0x00, 0xD5, 0x60, 0x91, 0x2D, 0x3F, 0x70, 0x3C,
+ 0x96, 0x96, 0x76, 0x6C, 0xFA,
+};
+static uint8_t CCM19_N[] = {
+ 0x00, 0x42, 0xFF, 0xF8, 0xF1, 0x95, 0x1C, 0x3C,
+ 0x96, 0x96, 0x76, 0x6C, 0xFA,
+};
+static uint8_t CCM20_N[] = {
+ 0x00, 0x92, 0x0F, 0x40, 0xE5, 0x6C, 0xDC, 0x3C,
+ 0x96, 0x96, 0x76, 0x6C, 0xFA,
+};
+static uint8_t CCM21_N[] = {
+ 0x00, 0x27, 0xCA, 0x0C, 0x71, 0x20, 0xBC, 0x3C,
+ 0x96, 0x96, 0x76, 0x6C, 0xFA,
+};
+static uint8_t CCM22_N[] = {
+ 0x00, 0x5B, 0x8C, 0xCB, 0xCD, 0x9A, 0xF8, 0x3C,
+ 0x96, 0x96, 0x76, 0x6C, 0xFA,
+};
+static uint8_t CCM23_N[] = {
+ 0x00, 0x3E, 0xBE, 0x94, 0x04, 0x4B, 0x9A, 0x3C,
+ 0x96, 0x96, 0x76, 0x6C, 0xFA,
+};
+static uint8_t CCM24_N[] = {
+ 0x00, 0x8D, 0x49, 0x3B, 0x30, 0xAE, 0x8B, 0x3C,
+ 0x96, 0x96, 0x76, 0x6C, 0xFA,
+};
+
+/* data */
+static uint8_t CCM13_DATA[] = {
+ 0x0B, 0xE1, 0xA8, 0x8B, 0xAC, 0xE0, 0x18, 0xB1,
+ 0x08, 0xE8, 0xCF, 0x97, 0xD8, 0x20, 0xEA, 0x25,
+ 0x84, 0x60, 0xE9, 0x6A, 0xD9, 0xCF, 0x52, 0x89,
+ 0x05, 0x4D, 0x89, 0x5C, 0xEA, 0xC4, 0x7C,
+};
+static uint8_t CCM14_DATA[] = {
+ 0x63, 0x01, 0x8F, 0x76, 0xDC, 0x8A, 0x1B, 0xCB,
+ 0x90, 0x20, 0xEA, 0x6F, 0x91, 0xBD, 0xD8, 0x5A,
+ 0xFA, 0x00, 0x39, 0xBA, 0x4B, 0xAF, 0xF9, 0xBF,
+ 0xB7, 0x9C, 0x70, 0x28, 0x94, 0x9C, 0xD0, 0xEC,
+};
+static uint8_t CCM15_DATA[] = {
+ 0xAA, 0x6C, 0xFA, 0x36, 0xCA, 0xE8, 0x6B, 0x40,
+ 0xB9, 0x16, 0xE0, 0xEA, 0xCC, 0x1C, 0x00, 0xD7,
+ 0xDC, 0xEC, 0x68, 0xEC, 0x0B, 0x3B, 0xBB, 0x1A,
+ 0x02, 0xDE, 0x8A, 0x2D, 0x1A, 0xA3, 0x46, 0x13,
+ 0x2E,
+};
+static uint8_t CCM16_DATA[] = {
+ 0xD0, 0xD0, 0x73, 0x5C, 0x53, 0x1E, 0x1B, 0xEC,
+ 0xF0, 0x49, 0xC2, 0x44, 0x12, 0xDA, 0xAC, 0x56,
+ 0x30, 0xEF, 0xA5, 0x39, 0x6F, 0x77, 0x0C, 0xE1,
+ 0xA6, 0x6B, 0x21, 0xF7, 0xB2, 0x10, 0x1C,
+};
+static uint8_t CCM17_DATA[] = {
+ 0x77, 0xB6, 0x0F, 0x01, 0x1C, 0x03, 0xE1, 0x52,
+ 0x58, 0x99, 0xBC, 0xAE, 0xE8, 0x8B, 0x6A, 0x46,
+ 0xC7, 0x8D, 0x63, 0xE5, 0x2E, 0xB8, 0xC5, 0x46,
+ 0xEF, 0xB5, 0xDE, 0x6F, 0x75, 0xE9, 0xCC, 0x0D,
+};
+static uint8_t CCM18_DATA[] = {
+ 0xCD, 0x90, 0x44, 0xD2, 0xB7, 0x1F, 0xDB, 0x81,
+ 0x20, 0xEA, 0x60, 0xC0, 0x64, 0x35, 0xAC, 0xBA,
+ 0xFB, 0x11, 0xA8, 0x2E, 0x2F, 0x07, 0x1D, 0x7C,
+ 0xA4, 0xA5, 0xEB, 0xD9, 0x3A, 0x80, 0x3B, 0xA8,
+ 0x7F,
+};
+static uint8_t CCM19_DATA[] = {
+ 0xD8, 0x5B, 0xC7, 0xE6, 0x9F, 0x94, 0x4F, 0xB8,
+ 0x8A, 0x19, 0xB9, 0x50, 0xBC, 0xF7, 0x1A, 0x01,
+ 0x8E, 0x5E, 0x67, 0x01, 0xC9, 0x17, 0x87, 0x65,
+ 0x98, 0x09, 0xD6, 0x7D, 0xBE, 0xDD, 0x18,
+};
+static uint8_t CCM20_DATA[] = {
+ 0x74, 0xA0, 0xEB, 0xC9, 0x06, 0x9F, 0x5B, 0x37,
+ 0x17, 0x61, 0x43, 0x3C, 0x37, 0xC5, 0xA3, 0x5F,
+ 0xC1, 0xF3, 0x9F, 0x40, 0x63, 0x02, 0xEB, 0x90,
+ 0x7C, 0x61, 0x63, 0xBE, 0x38, 0xC9, 0x84, 0x37,
+};
+static uint8_t CCM21_DATA[] = {
+ 0x44, 0xA3, 0xAA, 0x3A, 0xAE, 0x64, 0x75, 0xCA,
+ 0xA4, 0x34, 0xA8, 0xE5, 0x85, 0x00, 0xC6, 0xE4,
+ 0x15, 0x30, 0x53, 0x88, 0x62, 0xD6, 0x86, 0xEA,
+ 0x9E, 0x81, 0x30, 0x1B, 0x5A, 0xE4, 0x22, 0x6B,
+ 0xFA,
+};
+static uint8_t CCM22_DATA[] = {
+ 0xEC, 0x46, 0xBB, 0x63, 0xB0, 0x25, 0x20, 0xC3,
+ 0x3C, 0x49, 0xFD, 0x70, 0xB9, 0x6B, 0x49, 0xE2,
+ 0x1D, 0x62, 0x17, 0x41, 0x63, 0x28, 0x75, 0xDB,
+ 0x7F, 0x6C, 0x92, 0x43, 0xD2, 0xD7, 0xC2,
+};
+static uint8_t CCM23_DATA[] = {
+ 0x47, 0xA6, 0x5A, 0xC7, 0x8B, 0x3D, 0x59, 0x42,
+ 0x27, 0xE8, 0x5E, 0x71, 0xE2, 0xFC, 0xFB, 0xB8,
+ 0x80, 0x44, 0x2C, 0x73, 0x1B, 0xF9, 0x51, 0x67,
+ 0xC8, 0xFF, 0xD7, 0x89, 0x5E, 0x33, 0x70, 0x76,
+};
+static uint8_t CCM24_DATA[] = {
+ 0x6E, 0x37, 0xA6, 0xEF, 0x54, 0x6D, 0x95, 0x5D,
+ 0x34, 0xAB, 0x60, 0x59, 0xAB, 0xF2, 0x1C, 0x0B,
+ 0x02, 0xFE, 0xB8, 0x8F, 0x85, 0x6D, 0xF4, 0xA3,
+ 0x73, 0x81, 0xBC, 0xE3, 0xCC, 0x12, 0x85, 0x17,
+ 0xD4,
+};
+
+/* results */
+
+static uint8_t CCM13_RES[] = {
+ 0x0B, 0xE1, 0xA8, 0x8B, 0xAC, 0xE0, 0x18, 0xB1,
+ 0x4C, 0xB9, 0x7F, 0x86, 0xA2, 0xA4, 0x68, 0x9A,
+ 0x87, 0x79, 0x47, 0xAB, 0x80, 0x91, 0xEF, 0x53,
+ 0x86, 0xA6, 0xFF, 0xBD, 0xD0, 0x80, 0xF8, 0xE7,
+ 0x8C, 0xF7, 0xCB, 0x0C, 0xDD, 0xD7, 0xB3,
+};
+static uint8_t CCM14_RES[] = {
+ 0x63, 0x01, 0x8F, 0x76, 0xDC, 0x8A, 0x1B, 0xCB,
+ 0x4C, 0xCB, 0x1E, 0x7C, 0xA9, 0x81, 0xBE, 0xFA,
+ 0xA0, 0x72, 0x6C, 0x55, 0xD3, 0x78, 0x06, 0x12,
+ 0x98, 0xC8, 0x5C, 0x92, 0x81, 0x4A, 0xBC, 0x33,
+ 0xC5, 0x2E, 0xE8, 0x1D, 0x7D, 0x77, 0xC0, 0x8A,
+};
+static uint8_t CCM15_RES[] = {
+ 0xAA, 0x6C, 0xFA, 0x36, 0xCA, 0xE8, 0x6B, 0x40,
+ 0xB1, 0xD2, 0x3A, 0x22, 0x20, 0xDD, 0xC0, 0xAC,
+ 0x90, 0x0D, 0x9A, 0xA0, 0x3C, 0x61, 0xFC, 0xF4,
+ 0xA5, 0x59, 0xA4, 0x41, 0x77, 0x67, 0x08, 0x97,
+ 0x08, 0xA7, 0x76, 0x79, 0x6E, 0xDB, 0x72, 0x35,
+ 0x06,
+};
+static uint8_t CCM16_RES[] = {
+ 0xD0, 0xD0, 0x73, 0x5C, 0x53, 0x1E, 0x1B, 0xEC,
+ 0xF0, 0x49, 0xC2, 0x44, 0x14, 0xD2, 0x53, 0xC3,
+ 0x96, 0x7B, 0x70, 0x60, 0x9B, 0x7C, 0xBB, 0x7C,
+ 0x49, 0x91, 0x60, 0x28, 0x32, 0x45, 0x26, 0x9A,
+ 0x6F, 0x49, 0x97, 0x5B, 0xCA, 0xDE, 0xAF,
+};
+static uint8_t CCM17_RES[] = {
+ 0x77, 0xB6, 0x0F, 0x01, 0x1C, 0x03, 0xE1, 0x52,
+ 0x58, 0x99, 0xBC, 0xAE, 0x55, 0x45, 0xFF, 0x1A,
+ 0x08, 0x5E, 0xE2, 0xEF, 0xBF, 0x52, 0xB2, 0xE0,
+ 0x4B, 0xEE, 0x1E, 0x23, 0x36, 0xC7, 0x3E, 0x3F,
+ 0x76, 0x2C, 0x0C, 0x77, 0x44, 0xFE, 0x7E, 0x3C,
+};
+static uint8_t CCM18_RES[] = {
+ 0xCD, 0x90, 0x44, 0xD2, 0xB7, 0x1F, 0xDB, 0x81,
+ 0x20, 0xEA, 0x60, 0xC0, 0x00, 0x97, 0x69, 0xEC,
+ 0xAB, 0xDF, 0x48, 0x62, 0x55, 0x94, 0xC5, 0x92,
+ 0x51, 0xE6, 0x03, 0x57, 0x22, 0x67, 0x5E, 0x04,
+ 0xC8, 0x47, 0x09, 0x9E, 0x5A, 0xE0, 0x70, 0x45,
+ 0x51,
+};
+static uint8_t CCM19_RES[] = {
+ 0xD8, 0x5B, 0xC7, 0xE6, 0x9F, 0x94, 0x4F, 0xB8,
+ 0xBC, 0x21, 0x8D, 0xAA, 0x94, 0x74, 0x27, 0xB6,
+ 0xDB, 0x38, 0x6A, 0x99, 0xAC, 0x1A, 0xEF, 0x23,
+ 0xAD, 0xE0, 0xB5, 0x29, 0x39, 0xCB, 0x6A, 0x63,
+ 0x7C, 0xF9, 0xBE, 0xC2, 0x40, 0x88, 0x97, 0xC6,
+ 0xBA,
+};
+static uint8_t CCM20_RES[] = {
+ 0x74, 0xA0, 0xEB, 0xC9, 0x06, 0x9F, 0x5B, 0x37,
+ 0x58, 0x10, 0xE6, 0xFD, 0x25, 0x87, 0x40, 0x22,
+ 0xE8, 0x03, 0x61, 0xA4, 0x78, 0xE3, 0xE9, 0xCF,
+ 0x48, 0x4A, 0xB0, 0x4F, 0x44, 0x7E, 0xFF, 0xF6,
+ 0xF0, 0xA4, 0x77, 0xCC, 0x2F, 0xC9, 0xBF, 0x54,
+ 0x89, 0x44,
+};
+static uint8_t CCM21_RES[] = {
+ 0x44, 0xA3, 0xAA, 0x3A, 0xAE, 0x64, 0x75, 0xCA,
+ 0xF2, 0xBE, 0xED, 0x7B, 0xC5, 0x09, 0x8E, 0x83,
+ 0xFE, 0xB5, 0xB3, 0x16, 0x08, 0xF8, 0xE2, 0x9C,
+ 0x38, 0x81, 0x9A, 0x89, 0xC8, 0xE7, 0x76, 0xF1,
+ 0x54, 0x4D, 0x41, 0x51, 0xA4, 0xED, 0x3A, 0x8B,
+ 0x87, 0xB9, 0xCE,
+};
+static uint8_t CCM22_RES[] = {
+ 0xEC, 0x46, 0xBB, 0x63, 0xB0, 0x25, 0x20, 0xC3,
+ 0x3C, 0x49, 0xFD, 0x70, 0x31, 0xD7, 0x50, 0xA0,
+ 0x9D, 0xA3, 0xED, 0x7F, 0xDD, 0xD4, 0x9A, 0x20,
+ 0x32, 0xAA, 0xBF, 0x17, 0xEC, 0x8E, 0xBF, 0x7D,
+ 0x22, 0xC8, 0x08, 0x8C, 0x66, 0x6B, 0xE5, 0xC1,
+ 0x97,
+};
+static uint8_t CCM23_RES[] = {
+ 0x47, 0xA6, 0x5A, 0xC7, 0x8B, 0x3D, 0x59, 0x42,
+ 0x27, 0xE8, 0x5E, 0x71, 0xE8, 0x82, 0xF1, 0xDB,
+ 0xD3, 0x8C, 0xE3, 0xED, 0xA7, 0xC2, 0x3F, 0x04,
+ 0xDD, 0x65, 0x07, 0x1E, 0xB4, 0x13, 0x42, 0xAC,
+ 0xDF, 0x7E, 0x00, 0xDC, 0xCE, 0xC7, 0xAE, 0x52,
+ 0x98, 0x7D,
+};
+static uint8_t CCM24_RES[] = {
+ 0x6E, 0x37, 0xA6, 0xEF, 0x54, 0x6D, 0x95, 0x5D,
+ 0x34, 0xAB, 0x60, 0x59, 0xF3, 0x29, 0x05, 0xB8,
+ 0x8A, 0x64, 0x1B, 0x04, 0xB9, 0xC9, 0xFF, 0xB5,
+ 0x8C, 0xC3, 0x90, 0x90, 0x0F, 0x3D, 0xA1, 0x2A,
+ 0xB1, 0x6D, 0xCE, 0x9E, 0x82, 0xEF, 0xA1, 0x6D,
+ 0xA6, 0x20, 0x59,
+};
+
+uint8_t *DATA_2[] = {
+ CCM13_DATA, CCM14_DATA, CCM15_DATA, CCM16_DATA, CCM17_DATA, CCM18_DATA,
+ CCM19_DATA, CCM20_DATA, CCM21_DATA, CCM22_DATA, CCM23_DATA, CCM24_DATA,
+};
+
+size_t DATALEN[] = {
+ 31, 32, 33, 31, 32, 33, 31, 32, 33, 31, 32, 33,
+ sizeof (CCM13_DATA), sizeof (CCM14_DATA), sizeof (CCM15_DATA),
+ sizeof (CCM16_DATA), sizeof (CCM17_DATA), sizeof (CCM18_DATA),
+ sizeof (CCM19_DATA), sizeof (CCM20_DATA), sizeof (CCM21_DATA),
+ sizeof (CCM22_DATA), sizeof (CCM23_DATA), sizeof (CCM24_DATA),
+};
+
+uint8_t *RES[] = {
+ CCM1_RES, CCM2_RES, CCM3_RES, CCM4_RES, CCM5_RES, CCM6_RES,
+ CCM7_RES, CCM8_RES, CCM9_RES, CCM10_RES, CCM11_RES, CCM12_RES,
+ CCM13_RES, CCM14_RES, CCM15_RES, CCM16_RES, CCM17_RES, CCM18_RES,
+ CCM19_RES, CCM20_RES, CCM21_RES, CCM22_RES, CCM23_RES, CCM24_RES,
+};
+
+size_t RESLEN[] = {
+ sizeof (CCM1_RES), sizeof (CCM2_RES), sizeof (CCM3_RES),
+ sizeof (CCM4_RES), sizeof (CCM5_RES), sizeof (CCM6_RES),
+ sizeof (CCM7_RES), sizeof (CCM8_RES), sizeof (CCM9_RES),
+ sizeof (CCM10_RES), sizeof (CCM11_RES), sizeof (CCM12_RES),
+ sizeof (CCM13_RES), sizeof (CCM14_RES), sizeof (CCM15_RES),
+ sizeof (CCM16_RES), sizeof (CCM17_RES), sizeof (CCM18_RES),
+ sizeof (CCM19_RES), sizeof (CCM20_RES), sizeof (CCM21_RES),
+ sizeof (CCM22_RES), sizeof (CCM23_RES), sizeof (CCM24_RES),
+};
+
+uint8_t *NONCE[] = {
+ CCM1_N, CCM2_N, CCM3_N, CCM4_N, CCM5_N, CCM6_N, CCM7_N, CCM8_N,
+ CCM9_N, CCM10_N, CCM11_N, CCM12_N, CCM13_N, CCM14_N, CCM15_N, CCM16_N,
+ CCM17_N, CCM18_N, CCM19_N, CCM20_N, CCM21_N, CCM22_N, CCM23_N, CCM24_N,
+};
+
+size_t NONCELEN[] = {
+ sizeof (CCM1_N), sizeof (CCM2_N), sizeof (CCM3_N), sizeof (CCM4_N),
+ sizeof (CCM5_N), sizeof (CCM6_N), sizeof (CCM7_N), sizeof (CCM8_N),
+ sizeof (CCM9_N), sizeof (CCM10_N), sizeof (CCM11_N), sizeof (CCM12_N),
+ sizeof (CCM13_N), sizeof (CCM14_N), sizeof (CCM15_N), sizeof (CCM16_N),
+ sizeof (CCM17_N), sizeof (CCM18_N), sizeof (CCM19_N), sizeof (CCM20_N),
+ sizeof (CCM21_N), sizeof (CCM22_N), sizeof (CCM23_N), sizeof (CCM24_N),
+};
+
+size_t AUTHLEN[] = {
+ 8, 8, 8, 12, 12, 12, 8, 8, 8, 12, 12, 12,
+ 8, 8, 8, 12, 12, 12, 8, 8, 8, 12, 12, 12,
+};
+
+size_t MACLEN[] = {
+ 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10,
+ 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AES_CCM_H */
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/cmac/Makefile b/usr/src/test/crypto-tests/tests/modes/aes/cmac/Makefile
new file mode 100644
index 0000000000..c4e63db251
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/cmac/Makefile
@@ -0,0 +1,20 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+PROG = aes_cmac
+
+include $(SRC)/cmd/Makefile.cmd
+include ../Makefile.subdirs
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/cmac/aes_cmac.c b/usr/src/test/crypto-tests/tests/modes/aes/cmac/aes_cmac.c
new file mode 100644
index 0000000000..a6e5936a80
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/cmac/aes_cmac.c
@@ -0,0 +1,51 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <aes/aes_impl.h>
+#include <stdio.h>
+
+#include "cryptotest.h"
+#include "aes_cmac.h"
+
+int
+main(void)
+{
+ int errs = 0;
+ int i;
+ uint8_t N[AES_BLOCK_LEN];
+ cryptotest_t args;
+
+ args.in = M;
+ args.out = N;
+ args.key = keytest;
+ args.param = NULL;
+
+ args.outlen = sizeof (N);
+ args.keylen = sizeof (keytest);
+ args.plen = 0;
+
+ args.mechname = SUN_CKM_AES_CMAC;
+ args.updatelen = 1;
+
+ for (i = 0; i < sizeof (RES) / sizeof (RES[0]); i++) {
+ args.inlen = DATALEN[i];
+ errs += run_test(&args, RES[i], AES_BLOCK_LEN, MAC_FG);
+ (void) fprintf(stderr, "----------\n");
+ }
+ if (errs != 0)
+ (void) fprintf(stderr, "%d tests failed\n", errs);
+
+ return (errs);
+}
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/cmac/aes_cmac.h b/usr/src/test/crypto-tests/tests/modes/aes/cmac/aes_cmac.h
new file mode 100644
index 0000000000..7f6c9b0fad
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/cmac/aes_cmac.h
@@ -0,0 +1,72 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _AES_CMAC_H
+#define _AES_CMAC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Test Vectors
+ * RFC4493
+ */
+static uint8_t CMAC_0[AES_BLOCK_LEN] = {
+ 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
+ 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
+};
+static uint8_t CMAC_16[AES_BLOCK_LEN] = {
+ 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
+ 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
+};
+static uint8_t CMAC_40[AES_BLOCK_LEN] = {
+ 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
+ 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
+};
+static uint8_t CMAC_64[AES_BLOCK_LEN] = {
+ 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
+ 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
+};
+
+uint8_t M[64] = {
+ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+ 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+ 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
+};
+
+uint8_t keytest[16] = {
+ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+};
+
+uint8_t *RES[] = {
+ CMAC_0, CMAC_16, CMAC_40, CMAC_64
+};
+
+size_t DATALEN[] = {
+ 0, 16, 40, 64
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AES_CMAC_H */
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/ctr/Makefile b/usr/src/test/crypto-tests/tests/modes/aes/ctr/Makefile
new file mode 100644
index 0000000000..a1a1d35425
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/ctr/Makefile
@@ -0,0 +1,20 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+PROG = aes_ctr
+
+include $(SRC)/cmd/Makefile.cmd
+include ../Makefile.subdirs
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/ctr/aes_ctr.c b/usr/src/test/crypto-tests/tests/modes/aes/ctr/aes_ctr.c
new file mode 100644
index 0000000000..c747485b8b
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/ctr/aes_ctr.c
@@ -0,0 +1,85 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <strings.h>
+#include <stdio.h>
+/* used for CK_*_PARAMS */
+#include <security/cryptoki.h>
+
+#include "cryptotest.h"
+#include "aes_ctr.h"
+
+int
+main(void)
+{
+ int errs = 0;
+ int i;
+ uint8_t N[1024];
+ CK_AES_CTR_PARAMS param;
+ cryptotest_t args;
+ size_t cblen = sizeof (CTR_CB0);
+
+ bzero(&param, sizeof (param));
+ param.ulCounterBits = 128 - cblen*8;
+ param.cb[15] = 0x01;
+
+ args.out = N;
+ args.param = &param;
+
+ args.outlen = sizeof (N);
+ args.plen = sizeof (param);
+
+ /*
+ * CTR is a stream cipher, and it runs ctr_mode_final every time
+ * it has a remainder, so the result is different
+ * if len == 0 mod block_size vs len != 0 mod block_size
+ */
+
+ args.mechname = SUN_CKM_AES_CTR;
+ args.updatelen = 16;
+
+ for (i = 0; i < sizeof (DATA) / sizeof (DATA[0]); i++) {
+ bcopy(CB[i], param.cb, cblen);
+
+ args.in = DATA[i];
+ args.key = KEY[i];
+
+ args.inlen = DATALEN[i];
+ args.keylen = KEYLEN[i];
+
+ errs += run_test(&args, RES[i], RESLEN[i], ENCR_FG);
+ (void) fprintf(stderr, "----------\n");
+ }
+
+ (void) fprintf(stderr, "\t\t\t=== decrypt ===\n----------\n\n");
+
+ for (i = 0; i < sizeof (DATA) / sizeof (DATA[0]); i++) {
+ bcopy(CB[i], param.cb, cblen);
+
+ args.in = RES[i];
+ args.key = KEY[i];
+
+ args.inlen = RESLEN[i];
+ args.keylen = KEYLEN[i];
+
+ errs += run_test(&args, DATA[i], DATALEN[i], ENCR_FG);
+ (void) fprintf(stderr, "----------\n");
+ }
+
+ if (errs != 0)
+ (void) fprintf(stderr, "%d tests failed\n", errs);
+
+ return (errs);
+}
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/ctr/aes_ctr.h b/usr/src/test/crypto-tests/tests/modes/aes/ctr/aes_ctr.h
new file mode 100644
index 0000000000..369ebc56fb
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/ctr/aes_ctr.h
@@ -0,0 +1,289 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _AES_CTR_H
+#define _AES_CTR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Test vectors
+ * RFC3686 section 6
+ */
+
+uint8_t CTR_KEY0[] = {
+ 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
+ 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E,
+};
+
+uint8_t CTR_CB0[] = {
+ 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+uint8_t CTR_DATA0[] = {
+ 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+ 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67,
+};
+
+uint8_t CTR_RES0[] = {
+ 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79,
+ 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8,
+};
+
+uint8_t CTR_KEY1[] = {
+ 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
+ 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63,
+};
+
+uint8_t CTR_CB1[] = {
+ 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
+ 0xDA, 0x48, 0xD9, 0x0B,
+};
+
+uint8_t CTR_DATA1[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+};
+
+uint8_t CTR_RES1[] = {
+ 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9,
+ 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88,
+ 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8,
+ 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28,
+};
+
+uint8_t CTR_KEY2[] = {
+ 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
+ 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC,
+};
+
+uint8_t CTR_CB2[] = {
+ 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
+ 0x4A, 0x17, 0x86, 0xF0,
+};
+
+uint8_t CTR_DATA2[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23,
+};
+
+uint8_t CTR_RES2[] = {
+ 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9,
+ 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7,
+ 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36,
+ 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53,
+ 0x25, 0xB2, 0x07, 0x2F,
+};
+
+uint8_t CTR_KEY3[] = {
+ 0x16, 0xAF, 0x5B, 0x14, 0x5F, 0xC9, 0xF5, 0x79,
+ 0xC1, 0x75, 0xF9, 0x3E, 0x3B, 0xFB, 0x0E, 0xED,
+ 0x86, 0x3D, 0x06, 0xCC, 0xFD, 0xB7, 0x85, 0x15,
+};
+
+uint8_t CTR_CB3[] = {
+ 0x00, 0x00, 0x00, 0x48, 0x36, 0x73, 0x3C, 0x14,
+ 0x7D, 0x6D, 0x93, 0xCB,
+};
+
+uint8_t CTR_DATA3[] = {
+ 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+ 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67,
+};
+
+uint8_t CTR_RES3[] = {
+ 0x4B, 0x55, 0x38, 0x4F, 0xE2, 0x59, 0xC9, 0xC8,
+ 0x4E, 0x79, 0x35, 0xA0, 0x03, 0xCB, 0xE9, 0x28,
+};
+
+uint8_t CTR_KEY4[] = {
+ 0x7C, 0x5C, 0xB2, 0x40, 0x1B, 0x3D, 0xC3, 0x3C,
+ 0x19, 0xE7, 0x34, 0x08, 0x19, 0xE0, 0xF6, 0x9C,
+ 0x67, 0x8C, 0x3D, 0xB8, 0xE6, 0xF6, 0xA9, 0x1A,
+};
+
+uint8_t CTR_CB4[] = {
+ 0x00, 0x96, 0xB0, 0x3B, 0x02, 0x0C, 0x6E, 0xAD,
+ 0xC2, 0xCB, 0x50, 0x0D,
+};
+
+uint8_t CTR_DATA4[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+};
+
+uint8_t CTR_RES4[] = {
+ 0x45, 0x32, 0x43, 0xFC, 0x60, 0x9B, 0x23, 0x32,
+ 0x7E, 0xDF, 0xAA, 0xFA, 0x71, 0x31, 0xCD, 0x9F,
+ 0x84, 0x90, 0x70, 0x1C, 0x5A, 0xD4, 0xA7, 0x9C,
+ 0xFC, 0x1F, 0xE0, 0xFF, 0x42, 0xF4, 0xFB, 0x00,
+};
+
+uint8_t CTR_KEY5[] = {
+ 0x02, 0xBF, 0x39, 0x1E, 0xE8, 0xEC, 0xB1, 0x59,
+ 0xB9, 0x59, 0x61, 0x7B, 0x09, 0x65, 0x27, 0x9B,
+ 0xF5, 0x9B, 0x60, 0xA7, 0x86, 0xD3, 0xE0, 0xFE,
+};
+
+uint8_t CTR_CB5[] = {
+ 0x00, 0x07, 0xBD, 0xFD, 0x5C, 0xBD, 0x60, 0x27,
+ 0x8D, 0xCC, 0x09, 0x12,
+};
+
+uint8_t CTR_DATA5[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23,
+};
+
+uint8_t CTR_RES5[] = {
+ 0x96, 0x89, 0x3F, 0xC5, 0x5E, 0x5C, 0x72, 0x2F,
+ 0x54, 0x0B, 0x7D, 0xD1, 0xDD, 0xF7, 0xE7, 0x58,
+ 0xD2, 0x88, 0xBC, 0x95, 0xC6, 0x91, 0x65, 0x88,
+ 0x45, 0x36, 0xC8, 0x11, 0x66, 0x2F, 0x21, 0x88,
+ 0xAB, 0xEE, 0x09, 0x35,
+};
+
+uint8_t CTR_KEY6[] = {
+ 0x77, 0x6B, 0xEF, 0xF2, 0x85, 0x1D, 0xB0, 0x6F,
+ 0x4C, 0x8A, 0x05, 0x42, 0xC8, 0x69, 0x6F, 0x6C,
+ 0x6A, 0x81, 0xAF, 0x1E, 0xEC, 0x96, 0xB4, 0xD3,
+ 0x7F, 0xC1, 0xD6, 0x89, 0xE6, 0xC1, 0xC1, 0x04,
+};
+
+uint8_t CTR_CB6[] = {
+ 0x00, 0x00, 0x00, 0x60, 0xDB, 0x56, 0x72, 0xC9,
+ 0x7A, 0xA8, 0xF0, 0xB2,
+};
+
+uint8_t CTR_DATA6[] = {
+ 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+ 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67,
+};
+
+uint8_t CTR_RES6[] = {
+ 0x14, 0x5A, 0xD0, 0x1D, 0xBF, 0x82, 0x4E, 0xC7,
+ 0x56, 0x08, 0x63, 0xDC, 0x71, 0xE3, 0xE0, 0xC0,
+};
+
+uint8_t CTR_KEY7[] = {
+ 0xF6, 0xD6, 0x6D, 0x6B, 0xD5, 0x2D, 0x59, 0xBB,
+ 0x07, 0x96, 0x36, 0x58, 0x79, 0xEF, 0xF8, 0x86,
+ 0xC6, 0x6D, 0xD5, 0x1A, 0x5B, 0x6A, 0x99, 0x74,
+ 0x4B, 0x50, 0x59, 0x0C, 0x87, 0xA2, 0x38, 0x84,
+};
+
+uint8_t CTR_CB7[] = {
+ 0x00, 0xFA, 0xAC, 0x24, 0xC1, 0x58, 0x5E, 0xF1,
+ 0x5A, 0x43, 0xD8, 0x75,
+};
+
+uint8_t CTR_DATA7[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+};
+
+uint8_t CTR_RES7[] = {
+ 0xF0, 0x5E, 0x23, 0x1B, 0x38, 0x94, 0x61, 0x2C,
+ 0x49, 0xEE, 0x00, 0x0B, 0x80, 0x4E, 0xB2, 0xA9,
+ 0xB8, 0x30, 0x6B, 0x50, 0x8F, 0x83, 0x9D, 0x6A,
+ 0x55, 0x30, 0x83, 0x1D, 0x93, 0x44, 0xAF, 0x1C,
+};
+
+uint8_t CTR_KEY8[] = {
+ 0xFF, 0x7A, 0x61, 0x7C, 0xE6, 0x91, 0x48, 0xE4,
+ 0xF1, 0x72, 0x6E, 0x2F, 0x43, 0x58, 0x1D, 0xE2,
+ 0xAA, 0x62, 0xD9, 0xF8, 0x05, 0x53, 0x2E, 0xDF,
+ 0xF1, 0xEE, 0xD6, 0x87, 0xFB, 0x54, 0x15, 0x3D,
+};
+
+uint8_t CTR_CB8[] = {
+ 0x00, 0x1C, 0xC5, 0xB7, 0x51, 0xA5, 0x1D, 0x70,
+ 0xA1, 0xC1, 0x11, 0x48,
+};
+
+uint8_t CTR_DATA8[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23,
+};
+
+uint8_t CTR_RES8[] = {
+ 0xEB, 0x6C, 0x52, 0x82, 0x1D, 0x0B, 0xBB, 0xF7,
+ 0xCE, 0x75, 0x94, 0x46, 0x2A, 0xCA, 0x4F, 0xAA,
+ 0xB4, 0x07, 0xDF, 0x86, 0x65, 0x69, 0xFD, 0x07,
+ 0xF4, 0x8C, 0xC0, 0xB5, 0x83, 0xD6, 0x07, 0x1F,
+ 0x1E, 0xC0, 0xE6, 0xB8,
+};
+
+uint8_t *DATA[] = {
+ CTR_DATA0, CTR_DATA1, CTR_DATA2, CTR_DATA3, CTR_DATA4,
+ CTR_DATA5, CTR_DATA6, CTR_DATA7, CTR_DATA8,
+};
+
+size_t DATALEN[] = {
+ sizeof (CTR_DATA0), sizeof (CTR_DATA1), sizeof (CTR_DATA2),
+ sizeof (CTR_DATA3), sizeof (CTR_DATA4), sizeof (CTR_DATA5),
+ sizeof (CTR_DATA6), sizeof (CTR_DATA7), sizeof (CTR_DATA8),
+};
+
+uint8_t *RES[] = {
+ CTR_RES0, CTR_RES1, CTR_RES2, CTR_RES3, CTR_RES4,
+ CTR_RES5, CTR_RES6, CTR_RES7, CTR_RES8,
+};
+
+size_t RESLEN[] = {
+ sizeof (CTR_RES0), sizeof (CTR_RES1), sizeof (CTR_RES2),
+ sizeof (CTR_RES3), sizeof (CTR_RES4), sizeof (CTR_RES5),
+ sizeof (CTR_RES6), sizeof (CTR_RES7), sizeof (CTR_RES8),
+};
+
+uint8_t *KEY[] = {
+ CTR_KEY0, CTR_KEY1, CTR_KEY2, CTR_KEY3, CTR_KEY4,
+ CTR_KEY5, CTR_KEY6, CTR_KEY7, CTR_KEY8,
+};
+
+size_t KEYLEN[] = {
+ sizeof (CTR_KEY0), sizeof (CTR_KEY1), sizeof (CTR_KEY2),
+ sizeof (CTR_KEY3), sizeof (CTR_KEY4), sizeof (CTR_KEY5),
+ sizeof (CTR_KEY6), sizeof (CTR_KEY7), sizeof (CTR_KEY8),
+};
+
+uint8_t *CB[] = {
+ CTR_CB0, CTR_CB1, CTR_CB2, CTR_CB3, CTR_CB4,
+ CTR_CB5, CTR_CB6, CTR_CB7, CTR_CB8,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AES_CTR_H */
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/ecb/Makefile b/usr/src/test/crypto-tests/tests/modes/aes/ecb/Makefile
new file mode 100644
index 0000000000..00adfa3b43
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/ecb/Makefile
@@ -0,0 +1,20 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+PROG = aes_ecb
+
+include $(SRC)/cmd/Makefile.cmd
+include ../Makefile.subdirs
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/ecb/aes_ecb.c b/usr/src/test/crypto-tests/tests/modes/aes/ecb/aes_ecb.c
new file mode 100644
index 0000000000..1768349f9b
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/ecb/aes_ecb.c
@@ -0,0 +1,60 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <stdio.h>
+#include "cryptotest.h"
+#include "aes_ecb.h"
+
+int
+main(void)
+{
+ int errs = 0;
+ int i;
+ uint8_t N[1024];
+ cryptotest_t args;
+
+ args.in = ECB_DATA;
+ args.out = N;
+ args.param = NULL;
+
+ args.inlen = sizeof (ECB_DATA);
+ args.outlen = sizeof (N);
+ args.plen = 0;
+
+ args.mechname = SUN_CKM_AES_ECB;
+ args.updatelen = 1;
+
+ for (i = 0; i < sizeof (RES) / sizeof (RES[0]); i++) {
+ args.key = KEY[i];
+ args.keylen = KEYLEN[i];
+ errs += run_test(&args, RES[i], RESLEN[i], ENCR_FG);
+ (void) fprintf(stderr, "----------\n");
+ }
+
+ (void) fprintf(stderr, "\t\t\t=== decrypt ===\n----------\n\n");
+
+ for (i = 0; i < sizeof (RES) / sizeof (RES[0]); i++) {
+ args.key = KEY[i];
+ args.in = RES[i];
+ args.keylen = KEYLEN[i];
+ args.inlen = RESLEN[i];
+ errs += run_test(&args, ECB_DATA, sizeof (ECB_DATA), DECR_FG);
+ (void) fprintf(stderr, "----------\n");
+ }
+ if (errs != 0)
+ (void) fprintf(stderr, "%d tests failed\n", errs);
+
+ return (errs);
+}
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/ecb/aes_ecb.h b/usr/src/test/crypto-tests/tests/modes/aes/ecb/aes_ecb.h
new file mode 100644
index 0000000000..4c8181c936
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/ecb/aes_ecb.h
@@ -0,0 +1,110 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _AES_ECB_H
+#define _AES_ECB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Test vectors
+ * NIST SP-800-38A Appendix F
+ */
+
+uint8_t ECB_KEY0[] = {
+ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
+};
+
+uint8_t ECB_DATA[] = {
+ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+ 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+ 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
+};
+
+uint8_t ECB_RES0[] = {
+ 0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60,
+ 0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97,
+ 0xf5, 0xd3, 0xd5, 0x85, 0x03, 0xb9, 0x69, 0x9d,
+ 0xe7, 0x85, 0x89, 0x5a, 0x96, 0xfd, 0xba, 0xaf,
+ 0x43, 0xb1, 0xcd, 0x7f, 0x59, 0x8e, 0xce, 0x23,
+ 0x88, 0x1b, 0x00, 0xe3, 0xed, 0x03, 0x06, 0x88,
+ 0x7b, 0x0c, 0x78, 0x5e, 0x27, 0xe8, 0xad, 0x3f,
+ 0x82, 0x23, 0x20, 0x71, 0x04, 0x72, 0x5d, 0xd4,
+};
+
+uint8_t ECB_KEY1[] = {
+ 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
+ 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
+ 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b,
+};
+
+uint8_t ECB_RES1[] = {
+ 0xbd, 0x33, 0x4f, 0x1d, 0x6e, 0x45, 0xf2, 0x5f,
+ 0xf7, 0x12, 0xa2, 0x14, 0x57, 0x1f, 0xa5, 0xcc,
+ 0x97, 0x41, 0x04, 0x84, 0x6d, 0x0a, 0xd3, 0xad,
+ 0x77, 0x34, 0xec, 0xb3, 0xec, 0xee, 0x4e, 0xef,
+ 0xef, 0x7a, 0xfd, 0x22, 0x70, 0xe2, 0xe6, 0x0a,
+ 0xdc, 0xe0, 0xba, 0x2f, 0xac, 0xe6, 0x44, 0x4e,
+ 0x9a, 0x4b, 0x41, 0xba, 0x73, 0x8d, 0x6c, 0x72,
+ 0xfb, 0x16, 0x69, 0x16, 0x03, 0xc1, 0x8e, 0x0e,
+};
+
+uint8_t ECB_KEY2[] = {
+ 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
+ 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+ 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+ 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4,
+};
+
+uint8_t ECB_RES2[] = {
+ 0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c,
+ 0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8,
+ 0x59, 0x1c, 0xcb, 0x10, 0xd4, 0x10, 0xed, 0x26,
+ 0xdc, 0x5b, 0xa7, 0x4a, 0x31, 0x36, 0x28, 0x70,
+ 0xb6, 0xed, 0x21, 0xb9, 0x9c, 0xa6, 0xf4, 0xf9,
+ 0xf1, 0x53, 0xe7, 0xb1, 0xbe, 0xaf, 0xed, 0x1d,
+ 0x23, 0x30, 0x4b, 0x7a, 0x39, 0xf9, 0xf3, 0xff,
+ 0x06, 0x7d, 0x8d, 0x8f, 0x9e, 0x24, 0xec, 0xc7,
+};
+
+uint8_t *RES[] = {
+ ECB_RES0, ECB_RES1, ECB_RES2,
+};
+
+size_t RESLEN[] = {
+ sizeof (ECB_RES0), sizeof (ECB_RES1), sizeof (ECB_RES2),
+};
+
+uint8_t *KEY[] = {
+ ECB_KEY0, ECB_KEY1, ECB_KEY2,
+};
+
+size_t KEYLEN[] = {
+ sizeof (ECB_KEY0), sizeof (ECB_KEY1), sizeof (ECB_KEY2),
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AES_ECB_H */
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/gcm/Makefile b/usr/src/test/crypto-tests/tests/modes/aes/gcm/Makefile
new file mode 100644
index 0000000000..c480cf13f9
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/gcm/Makefile
@@ -0,0 +1,20 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+PROG = aes_gcm
+
+include $(SRC)/cmd/Makefile.cmd
+include ../Makefile.subdirs
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/gcm/aes_gcm.c b/usr/src/test/crypto-tests/tests/modes/aes/gcm/aes_gcm.c
new file mode 100644
index 0000000000..764cbba385
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/gcm/aes_gcm.c
@@ -0,0 +1,87 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <strings.h>
+#include <stdio.h>
+#include "cryptotest.h"
+#include "aes_gcm.h"
+
+const size_t GCM_SPEC_TAG_LEN = 16;
+int
+main(void)
+{
+ int errs = 0;
+ int i;
+ uint8_t N[1024];
+ size_t taglen = GCM_SPEC_TAG_LEN;
+
+ CK_AES_GCM_PARAMS param;
+ cryptotest_t args;
+
+ bzero(&param, sizeof (param));
+ param.ulTagBits = taglen*8;
+
+ args.out = N;
+ args.param = &param;
+
+ args.outlen = sizeof (N);
+ args.plen = sizeof (param);
+
+ args.mechname = SUN_CKM_AES_GCM;
+ args.updatelen = 1;
+
+ for (i = 0; i < sizeof (DATA) / sizeof (DATA[0]); i++) {
+ args.in = DATA[i];
+ args.key = KEY[i];
+
+ args.inlen = DATALEN[i];
+ args.keylen = KEYLEN[i];
+
+ param.pIv = IV[i];
+ param.ulIvLen = IVLEN[i];
+ param.ulIvBits = IVLEN[i]*8;
+ param.pAAD = AUTH[i];
+ param.ulAADLen = AUTHLEN[i];
+
+
+ errs += run_test(&args, RES[i], RESLEN[i], ENCR_FG);
+ (void) fprintf(stderr, "----------\n");
+ }
+
+ (void) fprintf(stderr, "\t\t\t=== decrypt ===\n----------\n\n");
+
+ for (i = 0; i < sizeof (DATA) / sizeof (DATA[0]); i++) {
+ args.in = RES[i];
+ args.key = KEY[i];
+
+ args.inlen = RESLEN[i];
+ args.keylen = KEYLEN[i];
+
+ param.pIv = IV[i];
+ param.ulIvLen = IVLEN[i];
+ param.ulIvBits = IVLEN[i]*8;
+ param.pAAD = AUTH[i];
+ param.ulAADLen = AUTHLEN[i];
+
+
+ errs += run_test(&args, DATA[i], DATALEN[i], DECR_FG);
+ (void) fprintf(stderr, "----------\n");
+ }
+
+ if (errs != 0)
+ (void) fprintf(stderr, "%d tests failed\n", errs);
+
+ return (errs);
+}
diff --git a/usr/src/test/crypto-tests/tests/modes/aes/gcm/aes_gcm.h b/usr/src/test/crypto-tests/tests/modes/aes/gcm/aes_gcm.h
new file mode 100644
index 0000000000..4537c64e21
--- /dev/null
+++ b/usr/src/test/crypto-tests/tests/modes/aes/gcm/aes_gcm.h
@@ -0,0 +1,737 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _AES_GCM_H
+#define _AES_GCM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Test vectors
+ * NIST, "The Galois/Counter Mode of Operation (GCM)", Appendix B
+ * http://csrc.nist.gov/groups/ST/toolkit/
+ * BCM/documents/proposedmodes/gcm/gcm-spec.pdf
+ */
+
+uint8_t GCM_KEY0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+#define GCM_DATA0 NULL
+
+#define GCM_AUTH0 NULL
+
+uint8_t GCM_IV0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+uint8_t GCM_RES0[] = {
+ 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
+ 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a,
+};
+
+uint8_t GCM_KEY1[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+uint8_t GCM_DATA1[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+#define GCM_AUTH1 NULL
+
+uint8_t GCM_IV1[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+uint8_t GCM_RES1[] = {
+ 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
+ 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78,
+ 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
+ 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf,
+};
+
+uint8_t GCM_KEY2[] = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+};
+
+uint8_t GCM_DATA2[] = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+};
+
+#define GCM_AUTH2 NULL
+
+uint8_t GCM_IV2[] = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88,
+};
+
+uint8_t GCM_RES2[] = {
+ 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85,
+ 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
+ 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4,
+};
+
+uint8_t GCM_KEY3[] = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+};
+
+uint8_t GCM_DATA3[] = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39,
+};
+
+uint8_t GCM_AUTH3[] = {
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2,
+};
+
+uint8_t GCM_IV3[] = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88,
+};
+
+uint8_t GCM_RES3[] = {
+ 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91, 0x5b, 0xc9, 0x4f, 0xbc,
+ 0x32, 0x21, 0xa5, 0xdb, 0x94, 0xfa, 0xe9, 0x5a,
+ 0xe7, 0x12, 0x1a, 0x47,
+};
+
+uint8_t GCM_KEY4[] = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+};
+
+uint8_t GCM_DATA4[] = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39,
+};
+
+uint8_t GCM_AUTH4[] = {
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2,
+};
+
+uint8_t GCM_IV4[] = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+};
+
+uint8_t GCM_RES4[] = {
+ 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
+ 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
+ 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
+ 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
+ 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
+ 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
+ 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
+ 0xc2, 0x3f, 0x45, 0x98, 0x36, 0x12, 0xd2, 0xe7,
+ 0x9e, 0x3b, 0x07, 0x85, 0x56, 0x1b, 0xe1, 0x4a,
+ 0xac, 0xa2, 0xfc, 0xcb,
+};
+
+uint8_t GCM_KEY5[] = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+};
+
+uint8_t GCM_DATA5[] = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39,
+};
+
+uint8_t GCM_AUTH5[] = {
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2,
+};
+
+uint8_t GCM_IV5[] = {
+ 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
+ 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
+ 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
+ 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
+ 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
+ 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
+ 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
+ 0xa6, 0x37, 0xb3, 0x9b,
+};
+
+uint8_t GCM_RES5[] = {
+ 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
+ 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
+ 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
+ 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
+ 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
+ 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
+ 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
+ 0x4c, 0x34, 0xae, 0xe5, 0x61, 0x9c, 0xc5, 0xae,
+ 0xff, 0xfe, 0x0b, 0xfa, 0x46, 0x2a, 0xf4, 0x3c,
+ 0x16, 0x99, 0xd0, 0x50,
+};
+
+uint8_t GCM_KEY6[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+#define GCM_DATA6 NULL
+
+#define GCM_AUTH6 NULL
+
+uint8_t GCM_IV6[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+uint8_t GCM_RES6[] = {
+ 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
+ 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35,
+};
+
+uint8_t GCM_KEY7[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+uint8_t GCM_DATA7[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+#define GCM_AUTH7 NULL
+
+uint8_t GCM_IV7[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+uint8_t GCM_RES7[] = {
+ 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
+ 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00,
+ 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
+ 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb,
+};
+
+uint8_t GCM_KEY8[] = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+};
+
+uint8_t GCM_DATA8[] = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+};
+
+#define GCM_AUTH8 NULL
+
+uint8_t GCM_IV8[] = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88,
+};
+
+uint8_t GCM_RES8[] = {
+ 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+ 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+ 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+ 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+ 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+ 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+ 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+ 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56,
+ 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
+ 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14,
+};
+
+uint8_t GCM_KEY9[] = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+};
+
+uint8_t GCM_DATA9[] = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39,
+};
+
+uint8_t GCM_AUTH9[] = {
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2,
+};
+
+uint8_t GCM_IV9[] = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88,
+};
+
+uint8_t GCM_RES9[] = {
+ 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+ 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+ 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+ 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+ 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+ 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+ 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+ 0xcc, 0xda, 0x27, 0x10, 0x25, 0x19, 0x49, 0x8e,
+ 0x80, 0xf1, 0x47, 0x8f, 0x37, 0xba, 0x55, 0xbd,
+ 0x6d, 0x27, 0x61, 0x8c,
+};
+
+uint8_t GCM_KEY10[] = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+};
+
+uint8_t GCM_DATA10[] = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39,
+};
+
+uint8_t GCM_AUTH10[] = {
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2,
+};
+
+uint8_t GCM_IV10[] = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+};
+
+uint8_t GCM_RES10[] = {
+ 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
+ 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
+ 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
+ 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
+ 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
+ 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
+ 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
+ 0xa0, 0xf0, 0x62, 0xf7, 0x65, 0xdc, 0xc5, 0x7f,
+ 0xcf, 0x62, 0x3a, 0x24, 0x09, 0x4f, 0xcc, 0xa4,
+ 0x0d, 0x35, 0x33, 0xf8,
+};
+
+uint8_t GCM_KEY11[] = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+};
+
+uint8_t GCM_DATA11[] = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39,
+};
+
+uint8_t GCM_AUTH11[] = {
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2,
+};
+
+uint8_t GCM_IV11[] = {
+ 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
+ 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
+ 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
+ 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
+ 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
+ 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
+ 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
+ 0xa6, 0x37, 0xb3, 0x9b,
+};
+
+uint8_t GCM_RES11[] = {
+ 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
+ 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
+ 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
+ 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
+ 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
+ 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
+ 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
+ 0xe9, 0xb7, 0x37, 0x3b, 0xdc, 0xf5, 0x66, 0xff,
+ 0x29, 0x1c, 0x25, 0xbb, 0xb8, 0x56, 0x8f, 0xc3,
+ 0xd3, 0x76, 0xa6, 0xd9,
+};
+
+uint8_t GCM_KEY12[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+#define GCM_DATA12 NULL
+
+#define GCM_AUTH12 NULL
+
+uint8_t GCM_IV12[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+uint8_t GCM_RES12[] = {
+ 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
+ 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b,
+};
+
+uint8_t GCM_KEY13[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+uint8_t GCM_DATA13[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+#define GCM_AUTH13 NULL
+
+uint8_t GCM_IV13[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+uint8_t GCM_RES13[] = {
+ 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
+ 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18,
+ 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
+ 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19,
+};
+
+uint8_t GCM_KEY14[] = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+};
+
+uint8_t GCM_DATA14[] = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+};
+
+#define GCM_AUTH14 NULL
+
+uint8_t GCM_IV14[] = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88,
+};
+
+uint8_t GCM_RES14[] = {
+ 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+ 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+ 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+ 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+ 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+ 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+ 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+ 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad,
+ 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
+ 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c,
+};
+
+uint8_t GCM_KEY15[] = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+};
+
+uint8_t GCM_DATA15[] = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39,
+};
+
+uint8_t GCM_AUTH15[] = {
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2,
+};
+
+uint8_t GCM_IV15[] = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88,
+};
+
+uint8_t GCM_RES15[] = {
+ 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+ 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+ 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+ 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+ 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+ 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+ 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+ 0xbc, 0xc9, 0xf6, 0x62, 0x76, 0xfc, 0x6e, 0xce,
+ 0x0f, 0x4e, 0x17, 0x68, 0xcd, 0xdf, 0x88, 0x53,
+ 0xbb, 0x2d, 0x55, 0x1b,
+};
+
+uint8_t GCM_KEY16[] = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+};
+
+uint8_t GCM_DATA16[] = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39,
+};
+
+uint8_t GCM_AUTH16[] = {
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2,
+};
+
+uint8_t GCM_IV16[] = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+};
+
+uint8_t GCM_RES16[] = {
+ 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
+ 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
+ 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
+ 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
+ 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
+ 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
+ 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
+ 0xf4, 0x7c, 0x9b, 0x1f, 0x3a, 0x33, 0x7d, 0xbf,
+ 0x46, 0xa7, 0x92, 0xc4, 0x5e, 0x45, 0x49, 0x13,
+ 0xfe, 0x2e, 0xa8, 0xf2,
+};
+
+uint8_t GCM_KEY17[] = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+};
+
+uint8_t GCM_DATA17[] = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39,
+};
+
+uint8_t GCM_AUTH17[] = {
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2,
+};
+
+uint8_t GCM_IV17[] = {
+ 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
+ 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
+ 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
+ 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
+ 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
+ 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
+ 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
+ 0xa6, 0x37, 0xb3, 0x9b,
+};
+
+uint8_t GCM_RES17[] = {
+ 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
+ 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
+ 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
+ 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
+ 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
+ 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
+ 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
+ 0x44, 0xae, 0x7e, 0x3f, 0xa4, 0x4a, 0x82, 0x66,
+ 0xee, 0x1c, 0x8e, 0xb0, 0xc8, 0xb5, 0xd4, 0xcf,
+ 0x5a, 0xe9, 0xf1, 0x9a,
+};
+
+
+uint8_t *DATA[] = {
+ GCM_DATA0, GCM_DATA1, GCM_DATA2, GCM_DATA3, GCM_DATA4, GCM_DATA5,
+ GCM_DATA6, GCM_DATA7, GCM_DATA8, GCM_DATA9, GCM_DATA10, GCM_DATA11,
+ GCM_DATA12, GCM_DATA13, GCM_DATA14, GCM_DATA15, GCM_DATA16, GCM_DATA17,
+};
+
+size_t DATALEN[] = {
+ 0, sizeof (GCM_DATA1), sizeof (GCM_DATA2), sizeof (GCM_DATA3),
+ sizeof (GCM_DATA4), sizeof (GCM_DATA5), 0, sizeof (GCM_DATA7),
+ sizeof (GCM_DATA8), sizeof (GCM_DATA9), sizeof (GCM_DATA10),
+ sizeof (GCM_DATA11), 0, sizeof (GCM_DATA13), sizeof (GCM_DATA14),
+ sizeof (GCM_DATA15), sizeof (GCM_DATA16),
+ sizeof (GCM_DATA17),
+};
+
+uint8_t *RES[] = {
+ GCM_RES0, GCM_RES1, GCM_RES2, GCM_RES3, GCM_RES4, GCM_RES5,
+ GCM_RES6, GCM_RES7, GCM_RES8, GCM_RES9, GCM_RES10, GCM_RES11,
+ GCM_RES12, GCM_RES13, GCM_RES14, GCM_RES15, GCM_RES16, GCM_RES17,
+};
+
+size_t RESLEN[] = {
+ sizeof (GCM_RES0), sizeof (GCM_RES1), sizeof (GCM_RES2),
+ sizeof (GCM_RES3), sizeof (GCM_RES4), sizeof (GCM_RES5),
+ sizeof (GCM_RES6), sizeof (GCM_RES7), sizeof (GCM_RES8),
+ sizeof (GCM_RES9), sizeof (GCM_RES10), sizeof (GCM_RES11),
+ sizeof (GCM_RES12), sizeof (GCM_RES13), sizeof (GCM_RES14),
+ sizeof (GCM_RES15), sizeof (GCM_RES16), sizeof (GCM_RES17),
+};
+
+uint8_t *IV[] = {
+ GCM_IV0, GCM_IV1, GCM_IV2, GCM_IV3, GCM_IV4, GCM_IV5,
+ GCM_IV6, GCM_IV7, GCM_IV8, GCM_IV9, GCM_IV10, GCM_IV11,
+ GCM_IV12, GCM_IV13, GCM_IV14, GCM_IV15, GCM_IV16, GCM_IV17,
+};
+
+size_t IVLEN[] = {
+ sizeof (GCM_IV0), sizeof (GCM_IV1), sizeof (GCM_IV2),
+ sizeof (GCM_IV3), sizeof (GCM_IV4), sizeof (GCM_IV5),
+ sizeof (GCM_IV6), sizeof (GCM_IV7), sizeof (GCM_IV8),
+ sizeof (GCM_IV9), sizeof (GCM_IV10), sizeof (GCM_IV11),
+ sizeof (GCM_IV12), sizeof (GCM_IV13), sizeof (GCM_IV14),
+ sizeof (GCM_IV15), sizeof (GCM_IV16), sizeof (GCM_IV17),
+};
+
+uint8_t *AUTH[] = {
+ GCM_AUTH0, GCM_AUTH1, GCM_AUTH2, GCM_AUTH3, GCM_AUTH4, GCM_AUTH5,
+ GCM_AUTH6, GCM_AUTH7, GCM_AUTH8, GCM_AUTH9, GCM_AUTH10, GCM_AUTH11,
+ GCM_AUTH12, GCM_AUTH13, GCM_AUTH14, GCM_AUTH15, GCM_AUTH16, GCM_AUTH17,
+};
+
+size_t AUTHLEN[] = {
+ 0, 0, 0, sizeof (GCM_AUTH3), sizeof (GCM_AUTH4), sizeof (GCM_AUTH5),
+ 0, 0, 0, sizeof (GCM_AUTH9), sizeof (GCM_AUTH10), sizeof (GCM_AUTH11),
+ 0, 0, 0, sizeof (GCM_AUTH15), sizeof (GCM_AUTH16), sizeof (GCM_AUTH17),
+};
+
+uint8_t *KEY[] = {
+ GCM_KEY0, GCM_KEY1, GCM_KEY2, GCM_KEY3, GCM_KEY4, GCM_KEY5,
+ GCM_KEY6, GCM_KEY7, GCM_KEY8, GCM_KEY9, GCM_KEY10, GCM_KEY11,
+ GCM_KEY12, GCM_KEY13, GCM_KEY14, GCM_KEY15, GCM_KEY16, GCM_KEY17,
+};
+
+size_t KEYLEN[] = {
+ sizeof (GCM_KEY0), sizeof (GCM_KEY1), sizeof (GCM_KEY2),
+ sizeof (GCM_KEY3), sizeof (GCM_KEY4), sizeof (GCM_KEY5),
+ sizeof (GCM_KEY6), sizeof (GCM_KEY7), sizeof (GCM_KEY8),
+ sizeof (GCM_KEY9), sizeof (GCM_KEY10), sizeof (GCM_KEY11),
+ sizeof (GCM_KEY12), sizeof (GCM_KEY13), sizeof (GCM_KEY14),
+ sizeof (GCM_KEY15), sizeof (GCM_KEY16), sizeof (GCM_KEY17),
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AES_GCM_H */
diff --git a/usr/src/tools/scripts/nightly.sh b/usr/src/tools/scripts/nightly.sh
index 391ced5de6..7efa53e1f7 100644
--- a/usr/src/tools/scripts/nightly.sh
+++ b/usr/src/tools/scripts/nightly.sh
@@ -260,7 +260,6 @@ function build {
| egrep -v 'chars, width' \
| egrep -v "symbol (\`|')timezone' has differing types:" \
| egrep -v 'PSTAMP' \
- | egrep -v '|%WHOANDWHERE%|' \
| egrep -v '^Manifying' \
| egrep -v 'Ignoring unknown host' \
| egrep -v 'Processing method:' \
diff --git a/usr/src/uts/common/crypto/core/kcf_cryptoadm.c b/usr/src/uts/common/crypto/core/kcf_cryptoadm.c
index 518b0bc722..54e7c533ad 100644
--- a/usr/src/uts/common/crypto/core/kcf_cryptoadm.c
+++ b/usr/src/uts/common/crypto/core/kcf_cryptoadm.c
@@ -73,9 +73,11 @@ static void kcf_soft_config_dump(char *message);
* (excluding final NUL-character string element).
*/
static int
-count_mechanisms(crypto_mech_name_t mechs[]) {
+count_mechanisms(crypto_mech_name_t mechs[])
+{
int count;
- for (count = 0; mechs[count][0] != '\0'; ++count);
+ for (count = 0; mechs[count][0] != '\0'; ++count)
+ ;
return (count);
}
@@ -100,7 +102,7 @@ kcf_soft_config_init(void)
* # /etc/crypto/kcf.conf
* des:supportedlist=CKM_DES_CBC,CKM_DES_ECB,CKM_DES3_CBC,CKM_DES3_ECB
* aes:supportedlist=CKM_AES_ECB,CKM_AES_CBC,CKM_AES_CTR,CKM_AES_CCM,\
- * CKM_AES_GCM,CKM_AES_GMAC
+ * CKM_AES_GCM,CKM_AES_GMAC,CKM_AES_CMAC
* arcfour:supportedlist=CKM_RC4
* blowfish:supportedlist=CKM_BLOWFISH_ECB,CKM_BLOWFISH_CBC
* ecc:supportedlist=CKM_EC_KEY_PAIR_GEN,CKM_ECDH1_DERIVE,CKM_ECDSA,\
@@ -134,7 +136,7 @@ kcf_soft_config_init(void)
"CKM_DES_CBC", "CKM_DES_ECB", "CKM_DES3_CBC", "CKM_DES3_ECB", ""};
static crypto_mech_name_t aes_mechs[] = {
"CKM_AES_ECB", "CKM_AES_CBC", "CKM_AES_CTR", "CKM_AES_CCM",
- "CKM_AES_GCM", "CKM_AES_GMAC", ""};
+ "CKM_AES_GCM", "CKM_AES_GMAC", "CKM_AES_CMAC", ""};
static crypto_mech_name_t arcfour_mechs[] = {
"CKM_RC4", ""};
static crypto_mech_name_t blowfish_mechs[] = {
@@ -250,7 +252,7 @@ kcf_soft_config_dump(char *message)
*/
static void
filter_providers(uint_t count, kcf_provider_desc_t **provider_array,
- char *skip_providers, int *mech_counts, int *new_count)
+ char *skip_providers, int *mech_counts, int *new_count)
{
int i, j;
kcf_provider_desc_t *prov1, *prov2;
diff --git a/usr/src/uts/common/crypto/core/kcf_mech_tabs.c b/usr/src/uts/common/crypto/core/kcf_mech_tabs.c
index 099f73a291..6d81267d50 100644
--- a/usr/src/uts/common/crypto/core/kcf_mech_tabs.c
+++ b/usr/src/uts/common/crypto/core/kcf_mech_tabs.c
@@ -224,7 +224,7 @@ kcf_init_mech_tabs()
kcf_cipher_mechs_tab[8].me_threshold = kcf_rc4_threshold;
- /* 5 HMACs */
+ /* 6 HMACs */
(void) strncpy(kcf_mac_mechs_tab[0].me_name, SUN_CKM_MD5_HMAC,
CRYPTO_MAX_MECH_NAME);
kcf_mac_mechs_tab[0].me_threshold = kcf_md5_threshold;
@@ -245,6 +245,10 @@ kcf_init_mech_tabs()
CRYPTO_MAX_MECH_NAME);
kcf_mac_mechs_tab[4].me_threshold = kcf_sha1_threshold;
+ (void) strncpy(kcf_mac_mechs_tab[5].me_name, SUN_CKM_AES_CMAC,
+ CRYPTO_MAX_MECH_NAME);
+ kcf_mac_mechs_tab[5].me_threshold = kcf_sha1_threshold;
+
/* 1 random number generation pseudo mechanism */
(void) strncpy(kcf_misc_mechs_tab[0].me_name, SUN_RANDOM,
CRYPTO_MAX_MECH_NAME);
diff --git a/usr/src/uts/common/crypto/core/kcf_prov_lib.c b/usr/src/uts/common/crypto/core/kcf_prov_lib.c
index 59f7ea1e70..65322bfb3c 100644
--- a/usr/src/uts/common/crypto/core/kcf_prov_lib.c
+++ b/usr/src/uts/common/crypto/core/kcf_prov_lib.c
@@ -35,204 +35,6 @@
#include <sys/crypto/impl.h>
/*
- * 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;
-
- ASSERT(data->cd_format == CRYPTO_DATA_UIO);
- 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;
-
- ASSERT(data->cd_format == CRYPTO_DATA_MBLK);
- /*
- * 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 (output->cd_raw.iov_len < len) {
- 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);
-}
-
-/*
* Utility routine to get data from a crypto_data structure.
*
* '*dptr' contains a pointer to a buffer on return. 'buf'
diff --git a/usr/src/uts/common/crypto/io/aes.c b/usr/src/uts/common/crypto/io/aes.c
index 6a30f0b7bc..a008927cbb 100644
--- a/usr/src/uts/common/crypto/io/aes.c
+++ b/usr/src/uts/common/crypto/io/aes.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -70,6 +71,11 @@ static crypto_mech_info_t aes_mech_info_tab[] = {
CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
AES_MIN_KEY_BYTES, AES_MAX_KEY_BYTES, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
+ /* AES_CMAC */
+ {SUN_CKM_AES_CMAC, AES_CMAC_MECH_INFO_TYPE,
+ CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
+ CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
+ AES_MIN_KEY_BYTES, AES_MAX_KEY_BYTES, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
/* AES_CTR */
{SUN_CKM_AES_CTR, AES_CTR_MECH_INFO_TYPE,
CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
@@ -148,6 +154,14 @@ static crypto_cipher_ops_t aes_cipher_ops = {
aes_decrypt_atomic
};
+static int aes_mac_init(crypto_ctx_t *, crypto_mechanism_t *,
+ crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
+static int aes_mac(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
+ crypto_req_handle_t);
+static int aes_mac_update(crypto_ctx_t *, crypto_data_t *,
+ crypto_req_handle_t);
+static int aes_mac_final(crypto_ctx_t *, crypto_data_t *,
+ crypto_req_handle_t);
static int aes_mac_atomic(crypto_provider_handle_t, crypto_session_id_t,
crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
crypto_spi_ctx_template_t, crypto_req_handle_t);
@@ -156,10 +170,10 @@ static int aes_mac_verify_atomic(crypto_provider_handle_t, crypto_session_id_t,
crypto_spi_ctx_template_t, crypto_req_handle_t);
static crypto_mac_ops_t aes_mac_ops = {
- NULL,
- NULL,
- NULL,
- NULL,
+ aes_mac_init,
+ aes_mac,
+ aes_mac_update,
+ aes_mac_final,
aes_mac_atomic,
aes_mac_verify_atomic
};
@@ -264,6 +278,10 @@ aes_check_mech_param(crypto_mechanism_t *mechanism, aes_ctx_t **ctx, int kmflag)
param_len = AES_BLOCK_LEN;
alloc_fun = cbc_alloc_ctx;
break;
+ case AES_CMAC_MECH_INFO_TYPE:
+ param_required = B_FALSE;
+ alloc_fun = cmac_alloc_ctx;
+ break;
case AES_CTR_MECH_INFO_TYPE:
param_len = sizeof (CK_AES_CTR_PARAMS);
alloc_fun = ctr_alloc_ctx;
@@ -336,14 +354,16 @@ aes_provider_status(crypto_provider_handle_t provider, uint_t *status)
static int
aes_encrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
crypto_key_t *key, crypto_spi_ctx_template_t template,
- crypto_req_handle_t req) {
+ crypto_req_handle_t req)
+{
return (aes_common_init(ctx, mechanism, key, template, req, B_TRUE));
}
static int
aes_decrypt_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
crypto_key_t *key, crypto_spi_ctx_template_t template,
- crypto_req_handle_t req) {
+ crypto_req_handle_t req)
+{
return (aes_common_init(ctx, mechanism, key, template, req, B_FALSE));
}
@@ -417,8 +437,9 @@ aes_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
* For block ciphers, plaintext must be a multiple of AES block size.
* This test is only valid for ciphers whose blocksize is a power of 2.
*/
- if (((aes_ctx->ac_flags & (CTR_MODE|CCM_MODE|GCM_MODE|GMAC_MODE))
- == 0) && (plaintext->cd_length & (AES_BLOCK_LEN - 1)) != 0)
+ if (((aes_ctx->ac_flags & (CMAC_MODE|CTR_MODE|CCM_MODE|
+ GCM_MODE|GMAC_MODE)) == 0) &&
+ (plaintext->cd_length & (AES_BLOCK_LEN - 1)) != 0)
return (CRYPTO_DATA_LEN_RANGE);
AES_ARG_INPLACE(plaintext, ciphertext);
@@ -427,13 +448,16 @@ aes_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
* We need to just return the length needed to store the output.
* We should not destroy the context for the following case.
*/
- switch (aes_ctx->ac_flags & (CCM_MODE|GCM_MODE|GMAC_MODE)) {
+ switch (aes_ctx->ac_flags & (CMAC_MODE|CCM_MODE|GCM_MODE|GMAC_MODE)) {
case CCM_MODE:
length_needed = plaintext->cd_length + aes_ctx->ac_mac_len;
break;
case GCM_MODE:
length_needed = plaintext->cd_length + aes_ctx->ac_tag_len;
break;
+ case CMAC_MODE:
+ length_needed = AES_BLOCK_LEN;
+ break;
case GMAC_MODE:
if (plaintext->cd_length != 0)
return (CRYPTO_ARGUMENTS_BAD);
@@ -507,6 +531,12 @@ aes_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
ciphertext->cd_offset - saved_offset;
}
ciphertext->cd_offset = saved_offset;
+ } else if (aes_ctx->ac_flags & CMAC_MODE) {
+ /* cmac_update doesn't store data */
+ ciphertext->cd_length = saved_length;
+ ret = cmac_mode_final((cbc_ctx_t *)aes_ctx, ciphertext,
+ aes_encrypt_block, aes_xor_block);
+ aes_ctx->ac_remainder_len = 0;
}
ASSERT(aes_ctx->ac_remainder_len == 0);
@@ -650,8 +680,12 @@ aes_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
out_len += plaintext->cd_length;
out_len &= ~(AES_BLOCK_LEN - 1);
- /* return length needed to store the output */
- if (ciphertext->cd_length < out_len) {
+ /*
+ * return length needed to store the output.
+ * CMAC stores its output in a local buffer until *_final.
+ */
+ if ((aes_ctx->ac_flags & CMAC_MODE) == 0 &&
+ ciphertext->cd_length < out_len) {
ciphertext->cd_length = out_len;
return (CRYPTO_BUFFER_TOO_SMALL);
}
@@ -833,6 +867,12 @@ aes_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
}
data->cd_length = data->cd_offset - saved_offset;
data->cd_offset = saved_offset;
+ } else if (aes_ctx->ac_flags & CMAC_MODE) {
+ ret = cmac_mode_final((cbc_ctx_t *)aes_ctx, data,
+ aes_encrypt_block, aes_xor_block);
+ if (ret != CRYPTO_SUCCESS)
+ return (ret);
+ data->cd_length = AES_BLOCK_LEN;
} else {
/*
* There must be no unprocessed plaintext.
@@ -970,7 +1010,7 @@ aes_encrypt_atomic(crypto_provider_handle_t provider,
AES_ARG_INPLACE(plaintext, ciphertext);
/*
- * CTR, CCM, GCM, and GMAC modes do not require that plaintext
+ * CTR, CCM, CMAC, GCM, and GMAC modes do not require that plaintext
* be a multiple of AES block size.
*/
switch (mechanism->cm_type) {
@@ -978,6 +1018,7 @@ aes_encrypt_atomic(crypto_provider_handle_t provider,
case AES_CCM_MECH_INFO_TYPE:
case AES_GCM_MECH_INFO_TYPE:
case AES_GMAC_MECH_INFO_TYPE:
+ case AES_CMAC_MECH_INFO_TYPE:
break;
default:
if ((plaintext->cd_length & (AES_BLOCK_LEN - 1)) != 0)
@@ -1005,6 +1046,9 @@ aes_encrypt_atomic(crypto_provider_handle_t provider,
case AES_GCM_MECH_INFO_TYPE:
length_needed = plaintext->cd_length + aes_ctx.ac_tag_len;
break;
+ case AES_CMAC_MECH_INFO_TYPE:
+ length_needed = AES_BLOCK_LEN;
+ break;
default:
length_needed = plaintext->cd_length;
}
@@ -1062,6 +1106,12 @@ aes_encrypt_atomic(crypto_provider_handle_t provider,
if (ret != CRYPTO_SUCCESS)
goto out;
}
+ } else if (mechanism->cm_type == AES_CMAC_MECH_INFO_TYPE) {
+ ret = cmac_mode_final((cbc_ctx_t *)&aes_ctx,
+ ciphertext, aes_encrypt_block,
+ aes_xor_block);
+ if (ret != CRYPTO_SUCCESS)
+ goto out;
} else {
ASSERT(aes_ctx.ac_remainder_len == 0);
}
@@ -1262,6 +1312,7 @@ aes_create_ctx_template(crypto_provider_handle_t provider,
if (mechanism->cm_type != AES_ECB_MECH_INFO_TYPE &&
mechanism->cm_type != AES_CBC_MECH_INFO_TYPE &&
+ mechanism->cm_type != AES_CMAC_MECH_INFO_TYPE &&
mechanism->cm_type != AES_CTR_MECH_INFO_TYPE &&
mechanism->cm_type != AES_CCM_MECH_INFO_TYPE &&
mechanism->cm_type != AES_GCM_MECH_INFO_TYPE &&
@@ -1343,6 +1394,9 @@ aes_common_init_ctx(aes_ctx_t *aes_ctx, crypto_spi_ctx_template_t *template,
rv = cbc_init_ctx((cbc_ctx_t *)aes_ctx, mechanism->cm_param,
mechanism->cm_param_len, AES_BLOCK_LEN, aes_copy_block64);
break;
+ case AES_CMAC_MECH_INFO_TYPE:
+ rv = cmac_init_ctx((cbc_ctx_t *)aes_ctx, AES_BLOCK_LEN);
+ break;
case AES_CTR_MECH_INFO_TYPE: {
CK_AES_CTR_PARAMS *pp;
@@ -1428,6 +1482,44 @@ process_gmac_mech(crypto_mechanism_t *mech, crypto_data_t *data,
}
static int
+aes_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
+ crypto_key_t *key, crypto_spi_ctx_template_t template,
+ crypto_req_handle_t req)
+{
+ return (aes_encrypt_init(ctx, mechanism,
+ key, template, req));
+}
+
+static int
+aes_mac(crypto_ctx_t *ctx, crypto_data_t *plaintext, crypto_data_t *ciphertext,
+ crypto_req_handle_t req)
+{
+ return (aes_encrypt(ctx, plaintext, ciphertext, req));
+}
+
+static int
+aes_mac_update(crypto_ctx_t *ctx, crypto_data_t *data,
+ crypto_req_handle_t req)
+{
+ crypto_data_t out;
+ uint8_t block[AES_BLOCK_LEN];
+ out.cd_format = CRYPTO_DATA_RAW;
+ out.cd_offset = 0;
+ out.cd_length = sizeof (block);
+ out.cd_miscdata = NULL;
+ out.cd_raw.iov_base = (void *)block;
+ out.cd_raw.iov_len = sizeof (block);
+
+ return (aes_encrypt_update(ctx, data, &out, req));
+}
+
+static int
+aes_mac_final(crypto_ctx_t *ctx, crypto_data_t *mac, crypto_req_handle_t req)
+{
+ return (aes_encrypt_final(ctx, mac, req));
+}
+
+static int
aes_mac_atomic(crypto_provider_handle_t provider,
crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
@@ -1437,16 +1529,21 @@ aes_mac_atomic(crypto_provider_handle_t provider,
crypto_mechanism_t gcm_mech;
int rv;
- if ((rv = process_gmac_mech(mechanism, data, &gcm_params))
- != CRYPTO_SUCCESS)
- return (rv);
+ if (mechanism->cm_type == AES_GMAC_MECH_INFO_TYPE) {
+ if ((rv = process_gmac_mech(mechanism, data, &gcm_params))
+ != CRYPTO_SUCCESS)
+ return (rv);
- gcm_mech.cm_type = AES_GCM_MECH_INFO_TYPE;
- gcm_mech.cm_param_len = sizeof (CK_AES_GCM_PARAMS);
- gcm_mech.cm_param = (char *)&gcm_params;
+ gcm_mech.cm_type = AES_GCM_MECH_INFO_TYPE;
+ gcm_mech.cm_param_len = sizeof (CK_AES_GCM_PARAMS);
+ gcm_mech.cm_param = (char *)&gcm_params;
- return (aes_encrypt_atomic(provider, session_id, &gcm_mech,
- key, &null_crypto_data, mac, template, req));
+ return (aes_encrypt_atomic(provider, session_id, &gcm_mech,
+ key, &null_crypto_data, mac, template, req));
+ }
+ /* CMAC */
+ return (aes_encrypt_atomic(provider, session_id, mechanism,
+ key, data, mac, template, req));
}
static int
@@ -1457,16 +1554,42 @@ aes_mac_verify_atomic(crypto_provider_handle_t provider,
{
CK_AES_GCM_PARAMS gcm_params;
crypto_mechanism_t gcm_mech;
+ crypto_data_t data_mac;
+ char buf[AES_BLOCK_LEN];
int rv;
- if ((rv = process_gmac_mech(mechanism, data, &gcm_params))
- != CRYPTO_SUCCESS)
+ if (mechanism->cm_type == AES_GMAC_MECH_INFO_TYPE) {
+ if ((rv = process_gmac_mech(mechanism, data, &gcm_params))
+ != CRYPTO_SUCCESS)
+ return (rv);
+
+ gcm_mech.cm_type = AES_GCM_MECH_INFO_TYPE;
+ gcm_mech.cm_param_len = sizeof (CK_AES_GCM_PARAMS);
+ gcm_mech.cm_param = (char *)&gcm_params;
+
+ return (aes_decrypt_atomic(provider, session_id, &gcm_mech,
+ key, mac, &null_crypto_data, template, req));
+ }
+
+ /* CMAC */
+
+ data_mac.cd_format = CRYPTO_DATA_RAW;
+ data_mac.cd_offset = 0;
+ data_mac.cd_length = AES_BLOCK_LEN;
+ data_mac.cd_miscdata = NULL;
+ data_mac.cd_raw.iov_base = (void *) buf;
+ data_mac.cd_raw.iov_len = AES_BLOCK_LEN;
+
+ rv = aes_encrypt_atomic(provider, session_id, &gcm_mech,
+ key, data, &data_mac, template, req);
+
+ if (rv != CRYPTO_SUCCESS)
return (rv);
- gcm_mech.cm_type = AES_GCM_MECH_INFO_TYPE;
- gcm_mech.cm_param_len = sizeof (CK_AES_GCM_PARAMS);
- gcm_mech.cm_param = (char *)&gcm_params;
+ /* should use get_input_data for mac? */
+ if (bcmp(buf, mac->cd_raw.iov_base + mac->cd_offset,
+ AES_BLOCK_LEN) != 0)
+ return (CRYPTO_INVALID_MAC);
- return (aes_decrypt_atomic(provider, session_id, &gcm_mech,
- key, mac, &null_crypto_data, template, req));
+ return (CRYPTO_SUCCESS);
}
diff --git a/usr/src/uts/common/crypto/io/crypto.c b/usr/src/uts/common/crypto/io/crypto.c
index 31947ae130..812c624d66 100644
--- a/usr/src/uts/common/crypto/io/crypto.c
+++ b/usr/src/uts/common/crypto/io/crypto.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
@@ -112,6 +113,12 @@ static int crypto_free_find_ctx(crypto_session_data_t *);
static int crypto_get_provider_list(crypto_minor_t *, uint_t *,
crypto_provider_entry_t **, boolean_t);
+static int crypto_create_provider_session(crypto_minor_t *,
+ kcf_provider_desc_t *, crypto_session_id_t, crypto_provider_session_t **,
+ kcf_provider_desc_t *);
+static int crypto_create_session_ptr(crypto_minor_t *, kcf_provider_desc_t *,
+ crypto_provider_session_t *, crypto_session_id_t *);
+
/* number of minor numbers to allocate at a time */
#define CRYPTO_MINOR_CHUNK 16
@@ -221,6 +228,10 @@ static kcf_lock_withpad_t *crypto_locks;
crypto_cancel_ctx((sp)->sd_verify_recover_ctx); \
(sp)->sd_verify_recover_ctx = NULL; \
} \
+ if ((sp)->sd_mac_ctx != NULL) { \
+ crypto_cancel_ctx((sp)->sd_mac_ctx); \
+ (sp)->sd_mac_ctx = NULL; \
+ } \
}
#define CRYPTO_DECREMENT_RCTL(val) if ((val) != 0) { \
@@ -1700,7 +1711,7 @@ crypto_get_provider_session(crypto_minor_t *cm,
{
kcf_provider_desc_t *pd, *real_provider;
kcf_req_params_t params;
- crypto_provider_session_t *ps, *new_ps;
+ crypto_provider_session_t *ps;
crypto_session_id_t provider_session_id = 0;
int rv;
@@ -1746,9 +1757,6 @@ again:
}
}
- /* allocate crypto_provider_session structure */
- new_ps = kmem_zalloc(sizeof (crypto_provider_session_t), KM_SLEEP);
-
/*
* Check if someone opened a session to the provider
* while we dropped the lock.
@@ -1757,7 +1765,6 @@ again:
for (ps = cm->cm_provider_session; ps != NULL; ps = ps->ps_next) {
if (ps->ps_provider == pd) {
mutex_exit(&cm->cm_lock);
- kmem_free(new_ps, sizeof (crypto_provider_session_t));
if (real_provider != NULL) {
KCF_WRAP_SESSION_OPS_PARAMS(&params,
KCF_OP_SESSION_CLOSE, NULL,
@@ -1773,18 +1780,32 @@ again:
}
}
+ return (crypto_create_provider_session(cm, pd, provider_session_id,
+ output_ps, real_provider));
+}
+
+static int
+crypto_create_provider_session(crypto_minor_t *cm, kcf_provider_desc_t *pd,
+ crypto_session_id_t sid, crypto_provider_session_t **out_ps,
+ kcf_provider_desc_t *real)
+{
+ crypto_provider_session_t *ps;
+
+ /* allocate crypto_provider_session structure */
+ ps = kmem_zalloc(sizeof (crypto_provider_session_t), KM_SLEEP);
+
/* increment refcnt and attach to crypto_minor structure */
- new_ps->ps_session = provider_session_id;
- new_ps->ps_refcnt = 1;
+ ps->ps_session = sid;
+ ps->ps_refcnt = 1;
KCF_PROV_REFHOLD(pd);
- new_ps->ps_provider = pd;
- if (real_provider != NULL) {
- new_ps->ps_real_provider = real_provider;
+ ps->ps_provider = pd;
+ if (real != NULL) {
+ ps->ps_real_provider = real;
}
- new_ps->ps_next = cm->cm_provider_session;
- cm->cm_provider_session = new_ps;
+ ps->ps_next = cm->cm_provider_session;
+ cm->cm_provider_session = ps;
- *output_ps = new_ps;
+ *out_ps = ps;
return (CRYPTO_SUCCESS);
}
@@ -1880,7 +1901,7 @@ grow_session_table(crypto_minor_t *cm)
}
/*
- * Find unused entry in session table and return it's index.
+ * Find unused entry in session table and return its index.
* Initialize session table entry.
*/
/* ARGSUSED */
@@ -1888,11 +1909,7 @@ static int
crypto_open_session(dev_t dev, uint_t flags, crypto_session_id_t *session_index,
crypto_provider_id_t provider_id)
{
- crypto_session_data_t **session_table;
- crypto_session_data_t *sp;
crypto_minor_t *cm;
- uint_t session_table_count;
- uint_t i;
int rv;
crypto_provider_session_t *ps;
kcf_provider_desc_t *provider;
@@ -1928,6 +1945,25 @@ crypto_open_session(dev_t dev, uint_t flags, crypto_session_id_t *session_index,
}
provider = cm->cm_provider_array[provider_id];
+ rv = crypto_create_session_ptr(cm, provider, ps, session_index);
+ mutex_exit(&cm->cm_lock);
+ crypto_release_minor(cm);
+ return (rv);
+
+}
+
+static int
+crypto_create_session_ptr(crypto_minor_t *cm, kcf_provider_desc_t *provider,
+ crypto_provider_session_t *ps, crypto_session_id_t *session_index)
+{
+ crypto_session_data_t **session_table;
+ crypto_session_data_t *sp;
+ uint_t session_table_count;
+ uint_t i;
+ int rv;
+
+ ASSERT(MUTEX_HELD(&cm->cm_lock));
+
again:
session_table_count = cm->cm_session_table_count;
session_table = cm->cm_session_table;
@@ -1941,8 +1977,6 @@ again:
if (i == session_table_count || session_table_count == 0) {
if ((rv = grow_session_table(cm)) != CRYPTO_SUCCESS) {
crypto_release_provider_session(cm, ps);
- mutex_exit(&cm->cm_lock);
- crypto_release_minor(cm);
return (rv);
}
goto again;
@@ -1956,6 +1990,7 @@ again:
sp->sd_decr_ctx = NULL;
sp->sd_sign_ctx = NULL;
sp->sd_verify_ctx = NULL;
+ sp->sd_mac_ctx = NULL;
sp->sd_sign_recover_ctx = NULL;
sp->sd_verify_recover_ctx = NULL;
mutex_init(&sp->sd_lock, NULL, MUTEX_DRIVER, NULL);
@@ -1973,9 +2008,8 @@ again:
}
cm->cm_session_table[i] = sp;
- mutex_exit(&cm->cm_lock);
- crypto_release_minor(cm);
- *session_index = i;
+ if (session_index != NULL)
+ *session_index = i;
return (CRYPTO_SUCCESS);
}
@@ -3123,7 +3157,7 @@ common_final(dev_t dev, caddr_t arg, int mode,
ASSERT(final == crypto_encrypt_final ||
final == crypto_decrypt_final || final == crypto_sign_final ||
- final == crypto_digest_final);
+ final == crypto_digest_final || final == crypto_mac_final);
if (final == crypto_encrypt_final) {
ctxpp = &sp->sd_encr_ctx;
@@ -3131,6 +3165,8 @@ common_final(dev_t dev, caddr_t arg, int mode,
ctxpp = &sp->sd_decr_ctx;
} else if (final == crypto_sign_final) {
ctxpp = &sp->sd_sign_ctx;
+ } else if (final == crypto_mac_final) {
+ ctxpp = &sp->sd_mac_ctx;
} else {
ctxpp = &sp->sd_digest_ctx;
}
@@ -3420,6 +3456,35 @@ digest(dev_t dev, caddr_t arg, int mode, int *rval)
return (common_digest(dev, arg, mode, crypto_digest_single));
}
+static int
+mac_init(dev_t dev, caddr_t arg, int mode, int *rval)
+{
+ _NOTE(ARGUNUSED(rval))
+ return (sign_verify_init(dev, arg, mode, crypto_mac_init_prov));
+}
+
+static int
+mac_update(dev_t dev, caddr_t arg, int mode, int *rval)
+{
+ _NOTE(ARGUNUSED(rval))
+ return (sign_verify_update(dev, arg, mode, crypto_mac_update));
+}
+
+static int
+mac_final(dev_t dev, caddr_t arg, int mode, int *rval)
+{
+ _NOTE(ARGUNUSED(rval))
+ return (common_final(dev, arg, mode, crypto_mac_final));
+}
+
+/* ARGSUSED */
+static int
+mac(dev_t dev, caddr_t arg, int mode, int *rval)
+{
+ _NOTE(ARGUNUSED(rval))
+ return (common_digest(dev, arg, mode, crypto_mac_single));
+}
+
/*
* ASSUMPTION: crypto_digest, crypto_sign, crypto_sign_recover,
* and crypto_verify_recover are identical except for field names.
@@ -3456,6 +3521,8 @@ common_digest(dev_t dev, caddr_t arg, int mode,
data.cd_raw.iov_base = NULL;
digest.cd_raw.iov_base = NULL;
+ data.cd_miscdata = NULL;
+ digest.cd_miscdata = NULL;
datalen = STRUCT_FGET(crypto_digest, cd_datalen);
digestlen = STRUCT_FGET(crypto_digest, cd_digestlen);
@@ -3503,7 +3570,8 @@ common_digest(dev_t dev, caddr_t arg, int mode,
ASSERT(single == crypto_digest_single ||
single == crypto_sign_single ||
single == crypto_verify_recover_single ||
- single == crypto_sign_recover_single);
+ single == crypto_sign_recover_single ||
+ single == crypto_mac_single);
if (single == crypto_digest_single) {
ctxpp = &sp->sd_digest_ctx;
@@ -3511,6 +3579,8 @@ common_digest(dev_t dev, caddr_t arg, int mode,
ctxpp = &sp->sd_sign_ctx;
} else if (single == crypto_verify_recover_single) {
ctxpp = &sp->sd_verify_recover_ctx;
+ } else if (single == crypto_mac_single) {
+ ctxpp = &sp->sd_mac_ctx;
} else {
ctxpp = &sp->sd_sign_recover_ctx;
}
@@ -3897,7 +3967,8 @@ sign_verify_init(dev_t dev, caddr_t arg, int mode,
ASSERT(init == crypto_sign_init_prov ||
init == crypto_verify_init_prov ||
init == crypto_sign_recover_init_prov ||
- init == crypto_verify_recover_init_prov);
+ init == crypto_verify_recover_init_prov ||
+ init == crypto_mac_init_prov);
if (init == crypto_sign_init_prov) {
fg = CRYPTO_FG_SIGN;
@@ -3908,6 +3979,9 @@ sign_verify_init(dev_t dev, caddr_t arg, int mode,
} else if (init == crypto_sign_recover_init_prov) {
fg = CRYPTO_FG_SIGN_RECOVER;
ctxpp = &sp->sd_sign_recover_ctx;
+ } else if (init == crypto_mac_init_prov) {
+ fg = CRYPTO_FG_MAC;
+ ctxpp = &sp->sd_mac_ctx;
} else {
fg = CRYPTO_FG_VERIFY_RECOVER;
ctxpp = &sp->sd_verify_recover_ctx;
@@ -4134,6 +4208,7 @@ sign_verify_update(dev_t dev, caddr_t arg, int mode,
}
data.cd_raw.iov_base = NULL;
+ data.cd_miscdata = NULL;
datalen = STRUCT_FGET(sign_update, su_datalen);
if (datalen > crypto_max_buffer_len) {
@@ -4163,8 +4238,16 @@ sign_verify_update(dev_t dev, caddr_t arg, int mode,
goto release_minor;
}
- ctxpp = (update == crypto_sign_update) ?
- &sp->sd_sign_ctx : &sp->sd_verify_ctx;
+ ASSERT(update == crypto_sign_update ||
+ update == crypto_verify_update ||
+ update == crypto_mac_update);
+
+ if (update == crypto_sign_update)
+ ctxpp = &sp->sd_sign_ctx;
+ else if (update == crypto_verify_update)
+ ctxpp = &sp->sd_verify_ctx;
+ else
+ ctxpp = &sp->sd_mac_ctx;
rv = (update)(*ctxpp, &data, NULL);
if (rv != CRYPTO_SUCCESS)
@@ -6550,6 +6633,62 @@ out:
return (error);
}
+static int
+get_provider_by_mech(dev_t dev, caddr_t arg, int mode, int *rval)
+{
+ _NOTE(ARGUNUSED(mode, rval))
+ kcf_mech_entry_t *me;
+ kcf_provider_desc_t *pd;
+ crypto_key_t key;
+ crypto_by_mech_t mech;
+ crypto_provider_session_t *ps;
+ crypto_minor_t *cm;
+ int rv, error;
+
+ if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
+ cmn_err(CE_WARN, "get_provider_by_mech: failed holding minor");
+ return (ENXIO);
+ }
+
+ bzero(&key, sizeof (key));
+ key.ck_format = CRYPTO_KEY_RAW;
+
+ if (copyin(arg, &mech, sizeof (mech)) != 0) {
+ crypto_release_minor(cm);
+ return (EFAULT);
+ }
+
+ key.ck_length = mech.mech_keylen;
+ /* pd is returned held */
+ if ((pd = kcf_get_mech_provider(mech.mech_type, &key, &me, &error,
+ NULL, mech.mech_fg, 0)) == NULL) {
+ rv = error;
+ goto release_minor;
+ }
+
+ /* don't want to allow direct access to software providers */
+ if (pd->pd_prov_type == CRYPTO_SW_PROVIDER) {
+ rv = CRYPTO_MECHANISM_INVALID;
+ KCF_PROV_REFRELE(pd);
+ cmn_err(CE_WARN, "software mech_type given");
+ goto release_minor;
+ }
+
+ mutex_enter(&cm->cm_lock);
+ if ((rv = crypto_create_provider_session(cm, pd, pd->pd_sid, &ps, NULL))
+ == CRYPTO_SUCCESS)
+ rv = crypto_create_session_ptr(cm, pd, ps, &mech.session_id);
+
+ mutex_exit(&cm->cm_lock);
+release_minor:
+ crypto_release_minor(cm);
+ mech.rv = rv;
+ if (copyout(&mech, arg, sizeof (mech)) != 0)
+ return (EFAULT);
+
+ return (rv);
+}
+
/* ARGSUSED */
static int
crypto_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c,
@@ -6573,6 +6712,9 @@ crypto_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c,
case CRYPTO_GET_PROVIDER_LIST:
return (get_provider_list(dev, ARG, mode, rval));
+ case CRYPTO_GET_PROVIDER_BY_MECH:
+ return (get_provider_by_mech(dev, ARG, mode, rval));
+
case CRYPTO_GET_PROVIDER_INFO:
return (get_provider_info(dev, ARG, mode, rval));
@@ -6663,6 +6805,18 @@ crypto_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c,
case CRYPTO_VERIFY_RECOVER:
return (verify_recover(dev, ARG, mode, rval));
+ case CRYPTO_MAC_INIT:
+ return (mac_init(dev, ARG, mode, rval));
+
+ case CRYPTO_MAC:
+ return (mac(dev, ARG, mode, rval));
+
+ case CRYPTO_MAC_UPDATE:
+ return (mac_update(dev, ARG, mode, rval));
+
+ case CRYPTO_MAC_FINAL:
+ return (mac_final(dev, ARG, mode, rval));
+
case CRYPTO_SET_PIN:
return (set_pin(dev, ARG, mode, rval));
diff --git a/usr/src/uts/common/crypto/io/dprov.c b/usr/src/uts/common/crypto/io/dprov.c
index 6259c8396d..de0a9b20e9 100644
--- a/usr/src/uts/common/crypto/io/dprov.c
+++ b/usr/src/uts/common/crypto/io/dprov.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -228,6 +229,7 @@ typedef enum dprov_mech_type {
BLOWFISH_CBC_MECH_INFO_TYPE, /* SUN_CKM_BLOWFISH_CBC */
BLOWFISH_ECB_MECH_INFO_TYPE, /* SUN_CKM_BLOWFISH_ECB */
AES_CBC_MECH_INFO_TYPE, /* SUN_CKM_AES_CBC */
+ AES_CMAC_MECH_INFO_TYPE, /* SUN_CKM_AES_CMAC */
AES_ECB_MECH_INFO_TYPE, /* SUN_CKM_AES_ECB */
AES_CTR_MECH_INFO_TYPE, /* SUN_CKM_AES_CTR */
AES_CCM_MECH_INFO_TYPE, /* SUN_CKM_AES_CCM */
@@ -476,6 +478,14 @@ static crypto_mech_info_t dprov_mech_info_tab[] = {
CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
CRYPTO_FG_MAC_DECRYPT_ATOMIC,
AES_MIN_KEY_LEN, AES_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
+ /* AES-CMAC */
+ {SUN_CKM_AES_CMAC, AES_CMAC_MECH_INFO_TYPE,
+ CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_MAC |
+ CRYPTO_FG_ENCRYPT_ATOMIC | CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
+ CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC |
+ CRYPTO_FG_SIGN | CRYPTO_FG_SIGN_ATOMIC |
+ CRYPTO_FG_VERIFY | CRYPTO_FG_VERIFY_ATOMIC,
+ AES_MIN_KEY_LEN, AES_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BYTES},
/* AES-ECB */
{SUN_CKM_AES_ECB, AES_ECB_MECH_INFO_TYPE,
CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | CRYPTO_FG_ENCRYPT_MAC |
@@ -2110,7 +2120,8 @@ dprov_valid_mac_mech(crypto_mech_type_t mech_type)
mech_type == SHA384_HMAC_GEN_MECH_INFO_TYPE ||
mech_type == SHA512_HMAC_MECH_INFO_TYPE ||
mech_type == SHA512_HMAC_GEN_MECH_INFO_TYPE ||
- mech_type == AES_GMAC_MECH_INFO_TYPE);
+ mech_type == AES_GMAC_MECH_INFO_TYPE ||
+ mech_type == AES_CMAC_MECH_INFO_TYPE);
}
static int
@@ -2302,6 +2313,7 @@ dprov_valid_cipher_mech(crypto_mech_type_t mech_type)
mech_type == BLOWFISH_CBC_MECH_INFO_TYPE ||
mech_type == BLOWFISH_ECB_MECH_INFO_TYPE ||
mech_type == AES_CBC_MECH_INFO_TYPE ||
+ mech_type == AES_CMAC_MECH_INFO_TYPE ||
mech_type == AES_ECB_MECH_INFO_TYPE ||
mech_type == AES_CTR_MECH_INFO_TYPE ||
mech_type == AES_CCM_MECH_INFO_TYPE ||
@@ -9498,7 +9510,7 @@ dprov_object_is_token(dprov_object_t *object)
*/
static int
dprov_get_object_attr_scalar_common(dprov_object_t *object, uint64_t attr_type,
- void *value, size_t value_len)
+ void *value, size_t value_len)
{
int attr_idx;
size_t oa_value_len;
diff --git a/usr/src/uts/common/sys/crypto/common.h b/usr/src/uts/common/sys/crypto/common.h
index 22e8e7c13f..c20ff8239b 100644
--- a/usr/src/uts/common/sys/crypto/common.h
+++ b/usr/src/uts/common/sys/crypto/common.h
@@ -206,6 +206,7 @@ typedef uint32_t crypto_keysize_unit_t;
#define SUN_CKM_BLOWFISH_CBC "CKM_BLOWFISH_CBC"
#define SUN_CKM_BLOWFISH_ECB "CKM_BLOWFISH_ECB"
#define SUN_CKM_AES_CBC "CKM_AES_CBC"
+#define SUN_CKM_AES_CMAC "CKM_AES_CMAC"
#define SUN_CKM_AES_ECB "CKM_AES_ECB"
#define SUN_CKM_AES_CTR "CKM_AES_CTR"
#define SUN_CKM_AES_CCM "CKM_AES_CCM"
diff --git a/usr/src/uts/common/sys/crypto/impl.h b/usr/src/uts/common/sys/crypto/impl.h
index aaeae3409c..7d9c959ecd 100644
--- a/usr/src/uts/common/sys/crypto/impl.h
+++ b/usr/src/uts/common/sys/crypto/impl.h
@@ -510,6 +510,7 @@ typedef struct crypto_session_data {
crypto_ctx_t *sd_digest_ctx;
crypto_ctx_t *sd_encr_ctx;
crypto_ctx_t *sd_decr_ctx;
+ crypto_ctx_t *sd_mac_ctx;
crypto_ctx_t *sd_sign_ctx;
crypto_ctx_t *sd_verify_ctx;
crypto_ctx_t *sd_sign_recover_ctx;
diff --git a/usr/src/uts/common/sys/crypto/ioctl.h b/usr/src/uts/common/sys/crypto/ioctl.h
index 32dddf4394..b7b511768b 100644
--- a/usr/src/uts/common/sys/crypto/ioctl.h
+++ b/usr/src/uts/common/sys/crypto/ioctl.h
@@ -1483,6 +1483,17 @@ typedef struct crypto_get_all_mechanism_info32 {
#define CRYPTO_GET_MECHANISM_LIST CRYPTO(140)
#define CRYPTO_GET_ALL_MECHANISM_INFO CRYPTO(141)
+#define CRYPTO_GET_PROVIDER_BY_MECH CRYPTO(142)
+
+typedef struct crypto_by_mech {
+ int rv;
+ int res;
+ crypto_mech_type_t mech_type;
+ uint_t mech_keylen;
+ crypto_func_group_t mech_fg;
+ crypto_session_id_t session_id;
+} crypto_by_mech_t;
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/common/sys/crypto/spi.h b/usr/src/uts/common/sys/crypto/spi.h
index 47741d2876..42294e8dde 100644
--- a/usr/src/uts/common/sys/crypto/spi.h
+++ b/usr/src/uts/common/sys/crypto/spi.h
@@ -588,6 +588,8 @@ typedef union crypto_provider_dev {
dev_info_t *pd_hw; /* for CRYPTO_HW_PROVIDER */
} crypto_provider_dev_t;
+#endif /* _KERNEL */
+
/*
* The mechanism info structure crypto_mech_info_t contains a function group
* bit mask cm_func_group_mask. This field, of type crypto_func_group_t,
@@ -597,8 +599,6 @@ typedef union crypto_provider_dev {
typedef uint32_t crypto_func_group_t;
-#endif /* _KERNEL */
-
#define CRYPTO_FG_ENCRYPT 0x00000001 /* encrypt_init() */
#define CRYPTO_FG_DECRYPT 0x00000002 /* decrypt_init() */
#define CRYPTO_FG_DIGEST 0x00000004 /* digest_init() */