Print this page
5072963 Need an optimized AES implementation for amd64
6699938 CCM max payload computation is off by one
@@ -21,11 +21,11 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "@(#)aes_cbc_crypt.c 1.9 08/05/09 SMI"
+#pragma ident "@(#)aes_cbc_crypt.c 1.10 08/06/13 SMI"
#include <sys/sysmacros.h>
#include <sys/systm.h>
#include <sys/crypto/common.h>
@@ -48,11 +48,11 @@
aes_ccm_decrypt_contiguous_blocks(aes_ctx_t *ctx, char *data, size_t length,
crypto_data_t *out);
/*
* Initialize by setting iov_or_mp to point to the current iovec or mp,
- * and by setting current_offset to an offset within the current iovec or mp .
+ * and by setting current_offset to an offset within the current iovec or mp.
*/
static void
aes_init_ptrs(crypto_data_t *out, void **iov_or_mp, offset_t *current_offset)
{
offset_t offset;
@@ -251,12 +251,11 @@
if (ctx->ac_flags & AES_CBC_MODE) {
/*
* XOR the previous cipher block or IV with the
* current clear block. Check for alignment.
*/
- if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) &&
- IS_P2ALIGNED(lastp, sizeof (uint32_t))) {
+ if (IS_P2ALIGNED2(blockp, lastp, sizeof (uint32_t))) {
/* LINTED: pointer alignment */
*(uint32_t *)&blockp[0] ^=
/* LINTED: pointer alignment */
*(uint32_t *)&lastp[0];
/* LINTED: pointer alignment */
@@ -292,15 +291,31 @@
aes_encrypt_block(ctx->ac_keysched, blockp, lastp);
aes_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
&out_data_1_len, &out_data_2, AES_BLOCK_LEN);
/* copy block to where it belongs */
+ if ((out_data_1_len == AES_BLOCK_LEN) &&
+ (IS_P2ALIGNED2(lastp, out_data_1,
+ sizeof (uint32_t)))) {
+ /* LINTED: pointer alignment */
+ uint32_t *d = (uint32_t *)out_data_1;
+ /* LINTED: pointer alignment */
+ d[0] = *(uint32_t *)lastp;
+ /* LINTED: pointer alignment */
+ d[1] = *(uint32_t *)&lastp[4];
+ /* LINTED: pointer alignment */
+ d[2] = *(uint32_t *)&lastp[8];
+ /* LINTED: pointer alignment */
+ d[3] = *(uint32_t *)&lastp[12];
+ } else {
bcopy(lastp, out_data_1, out_data_1_len);
+ }
if (out_data_2 != NULL) {
bcopy(lastp + out_data_1_len, out_data_2,
AES_BLOCK_LEN - out_data_1_len);
}
+
/* update offset */
out->cd_offset += AES_BLOCK_LEN;
}
/* Update pointer to next block of data to be processed. */
@@ -461,12 +476,11 @@
if (ctx->ac_flags & AES_CBC_MODE) {
/*
* XOR the previous cipher block or IV with the
* currently decrypted block. Check for alignment.
*/
- if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) &&
- IS_P2ALIGNED(lastp, sizeof (uint32_t))) {
+ if (IS_P2ALIGNED2(blockp, lastp, sizeof (uint32_t))) {
/* LINTED: pointer alignment */
*(uint32_t *)blockp ^= *(uint32_t *)lastp;
/* LINTED: pointer alignment */
*(uint32_t *)&blockp[4] ^=
/* LINTED: pointer alignment */
@@ -490,11 +504,21 @@
if (out != NULL) {
aes_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
&out_data_1_len, &out_data_2, AES_BLOCK_LEN);
/* copy temporary block to where it belongs */
+ if ((out_data_1_len == AES_BLOCK_LEN) &&
+ (IS_P2ALIGNED(out_data_1, sizeof (uint32_t)))) {
+ /* LINTED: pointer alignment */
+ uint32_t *d = (uint32_t *)out_data_1;
+ d[0] = tmp[0];
+ d[1] = tmp[1];
+ d[2] = tmp[2];
+ d[3] = tmp[3];
+ } else {
bcopy(&tmp, out_data_1, out_data_1_len);
+ }
if (out_data_2 != NULL) {
bcopy((uint8_t *)&tmp + out_data_1_len,
out_data_2, AES_BLOCK_LEN - out_data_1_len);
}
@@ -692,12 +716,11 @@
* do CBC MAC
*
* XOR the previous cipher block current clear block.
* mac_buf always contain previous cipher block.
*/
- if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) &&
- IS_P2ALIGNED(mac_buf, sizeof (uint32_t))) {
+ if (IS_P2ALIGNED2(blockp, mac_buf, sizeof (uint32_t))) {
/* LINTED: pointer alignment */
*(uint32_t *)&mac_buf[0] ^=
/* LINTED: pointer alignment */
*(uint32_t *)&blockp[0];
/* LINTED: pointer alignment */
@@ -758,12 +781,11 @@
/*
* XOR the previous cipher block or IV with the
* current clear block. Check for alignment.
*/
- if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) &&
- IS_P2ALIGNED(lastp, sizeof (uint32_t))) {
+ if (IS_P2ALIGNED2(blockp, lastp, sizeof (uint32_t))) {
/* LINTED: pointer alignment */
*(uint32_t *)&blockp[0] ^=
/* LINTED: pointer alignment */
*(uint32_t *)&lastp[0];
/* LINTED: pointer alignment */
@@ -798,15 +820,31 @@
} else {
aes_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
&out_data_1_len, &out_data_2, AES_BLOCK_LEN);
/* copy block to where it belongs */
+ if ((out_data_1_len == AES_BLOCK_LEN) &&
+ (IS_P2ALIGNED2(lastp, out_data_1,
+ sizeof (uint32_t)))) {
+ /* LINTED: pointer alignment */
+ uint32_t *d = (uint32_t *)out_data_1;
+ /* LINTED: pointer alignment */
+ d[0] = *(uint32_t *)lastp;
+ /* LINTED: pointer alignment */
+ d[1] = *(uint32_t *)&lastp[4];
+ /* LINTED: pointer alignment */
+ d[2] = *(uint32_t *)&lastp[8];
+ /* LINTED: pointer alignment */
+ d[3] = *(uint32_t *)&lastp[12];
+ } else {
bcopy(lastp, out_data_1, out_data_1_len);
+ }
if (out_data_2 != NULL) {
bcopy(lastp + out_data_1_len, out_data_2,
AES_BLOCK_LEN - out_data_1_len);
}
+
/* update offset */
out->cd_offset += AES_BLOCK_LEN;
}
/* Update pointer to next block of data to be processed. */
@@ -866,12 +904,11 @@
/* The IV for CBC MAC for AES CCM mode is always zero */
bzero(iv, AES_BLOCK_LEN);
ivp = (uint8_t *)iv;
- if (IS_P2ALIGNED(ivp, sizeof (uint32_t)) &&
- IS_P2ALIGNED(mac_buf, sizeof (uint32_t))) {
+ if (IS_P2ALIGNED2(ivp, mac_buf, sizeof (uint32_t))) {
/* LINTED: pointer alignment */
*(uint32_t *)&mac_buf[0] ^= *(uint32_t *)&ivp[0];
/* LINTED: pointer alignment */
*(uint32_t *)&mac_buf[4] ^= *(uint32_t *)&ivp[4];
/* LINTED: pointer alignment */
@@ -903,12 +940,11 @@
/* in case auth_data is very small */
processed = auth_data_len;
}
bcopy(auth_data, authp+encoded_a_len, processed);
/* xor with previous buffer */
- if (IS_P2ALIGNED(authp, sizeof (uint32_t)) &&
- IS_P2ALIGNED(mac_buf, sizeof (uint32_t))) {
+ if (IS_P2ALIGNED2(authp, mac_buf, sizeof (uint32_t))) {
/* LINTED: pointer alignment */
*(uint32_t *)&mac_buf[0] ^= *(uint32_t *)&authp[0];
/* LINTED: pointer alignment */
*(uint32_t *)&mac_buf[4] ^= *(uint32_t *)&authp[4];
/* LINTED: pointer alignment */
@@ -940,12 +976,11 @@
processed += AES_BLOCK_LEN;
remainder -= AES_BLOCK_LEN;
}
/* xor with previous buffer */
- if (IS_P2ALIGNED(datap, sizeof (uint32_t)) &&
- IS_P2ALIGNED(mac_buf, sizeof (uint32_t))) {
+ if (IS_P2ALIGNED2(datap, mac_buf, sizeof (uint32_t))) {
/* LINTED: pointer alignment */
*(uint32_t *)&mac_buf[0] ^= *(uint32_t *)&datap[0];
/* LINTED: pointer alignment */
*(uint32_t *)&mac_buf[4] ^= *(uint32_t *)&datap[4];
/* LINTED: pointer alignment */
@@ -1032,12 +1067,11 @@
/* copy remainder to temporary buffer */
bcopy(ctx->ac_remainder, macp, ctx->ac_remainder_len);
/* calculate the CBC MAC */
- if (IS_P2ALIGNED(macp, sizeof (uint32_t)) &&
- IS_P2ALIGNED(mac_buf, sizeof (uint32_t))) {
+ if (IS_P2ALIGNED2(macp, mac_buf, sizeof (uint32_t))) {
/* LINTED: pointer alignment */
*(uint32_t *)&mac_buf[0] ^= *(uint32_t *)&macp[0];
/* LINTED: pointer alignment */
*(uint32_t *)&mac_buf[4] ^= *(uint32_t *)&macp[4];
/* LINTED: pointer alignment */
@@ -1145,24 +1179,25 @@
size_t macSize, nonceSize;
uint8_t q;
uint64_t maxValue;
/*
- * Check the length of the MAC. Only valid length
+ * Check the byte length of the MAC. The only valid
* lengths for the MAC are: 4, 6, 8, 10, 12, 14, 16
*/
macSize = ccm_param->ulMACSize;
if ((macSize < 4) || (macSize > 16) || ((macSize % 2) != 0)) {
return (CRYPTO_MECHANISM_PARAM_INVALID);
}
- /* Check the nonce value. Valid values are 7, 8, 9, 10, 11, 12, 13 */
+ /* Check the nonce length. Valid values are 7, 8, 9, 10, 11, 12, 13 */
nonceSize = ccm_param->ulNonceSize;
if ((nonceSize < 7) || (nonceSize > 13)) {
return (CRYPTO_MECHANISM_PARAM_INVALID);
}
+ /* q is the length of the field storing the length, in bytes */
q = (uint8_t)((15 - nonceSize) & 0xFF);
/*
* If it is decrypt, need to make sure size of ciphertext is at least
@@ -1175,11 +1210,11 @@
/*
* Check to make sure the length of the payload is within the
* range of values allowed by q
*/
if (q < 8) {
- maxValue = 1ULL << (q * 8);
+ maxValue = (1ULL << (q * 8)) - 1;
} else {
maxValue = ULONG_MAX;
}
if (ccm_param->ulDataSize > maxValue) {
@@ -1190,11 +1225,11 @@
return (0);
}
/*
* Format the first block used in CBC-MAC (B0) and the initial counter
- * block based on formating functions and counter generation functions
+ * block based on formatting functions and counter generation functions
* specified in RFC 3610 and NIST publication 800-38C, appendix A
*
* b0 is the first block used in CBC-MAC
* cb0 is the first counter block
*
@@ -1217,11 +1252,11 @@
#endif /* _LITTLE_ENDIAN */
q = (uint8_t)((15 - nonceSize) & 0xFF);
t = (uint8_t)((aes_ctx->ac_ccm_mac_len) & 0xFF);
- /* Construct the first octect of b0 */
+ /* Construct the first octet of b0 */
if (authDataSize > 0) {
have_adata = 1;
}
b0[0] = (have_adata << 6) | (((t - 2) / 2) << 3) | (q - 1);
@@ -1270,11 +1305,11 @@
/*
* During calculation, we start using counter block 1, we will
* set it up right here.
* We can just set the last byte to have the value 1, because
- * even with the bigest nonce of 13, the last byte of the
+ * even with the biggest nonce of 13, the last byte of the
* counter block will be used for the counter value.
*/
cb[15] = 0x01;
/* EXPORT DELETE END */
@@ -1523,12 +1558,11 @@
counter &= ctx->ac_counter_mask;
ctx->ac_cb[1] =
(ctx->ac_cb[1] & ~(ctx->ac_counter_mask)) | counter;
/* XOR with the ciphertext */
- if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) &&
- IS_P2ALIGNED(cbp, sizeof (uint32_t))) {
+ if (IS_P2ALIGNED2(blockp, cbp, sizeof (uint32_t))) {
/* LINTED: pointer alignment */
*(uint32_t *)&blockp[0] ^= *(uint32_t *)&cbp[0];
/* LINTED: pointer alignment */
*(uint32_t *)&blockp[4] ^= *(uint32_t *)&cbp[4];
/* LINTED: pointer alignment */
@@ -1540,12 +1574,11 @@
}
/* Copy the plaintext to the "holding buffer" */
resultp = (uint8_t *)ctx->ac_ccm_pt_buf +
ctx->ac_ccm_processed_data_len;
- if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) &&
- IS_P2ALIGNED(resultp, sizeof (uint32_t))) {
+ if (IS_P2ALIGNED2(blockp, resultp, sizeof (uint32_t))) {
/* LINTED: pointer alignment */
*(uint32_t *)&resultp[0] = *(uint32_t *)blockp;
/* LINTED: pointer alignment */
*(uint32_t *)&resultp[4] = *(uint32_t *)&blockp[4];
/* LINTED: pointer alignment */
@@ -1627,12 +1660,11 @@
if (mac_remain < AES_BLOCK_LEN) {
bzero(tmp, AES_BLOCK_LEN);
bcopy(pt, tmp, mac_remain);
mac_remain = 0;
} else {
- if (IS_P2ALIGNED(pt, sizeof (uint32_t)) &&
- IS_P2ALIGNED(macp, sizeof (uint32_t))) {
+ if (IS_P2ALIGNED2(pt, macp, sizeof (uint32_t))) {
/* LINTED: pointer alignment */
*(uint32_t *)&macp[0] = *(uint32_t *)pt;
/* LINTED: pointer alignment */
*(uint32_t *)&macp[4] = *(uint32_t *)&pt[4];
/* LINTED: pointer alignment */
@@ -1645,12 +1677,11 @@
mac_remain -= AES_BLOCK_LEN;
pt += AES_BLOCK_LEN;
}
/* calculate the CBC MAC */
- if (IS_P2ALIGNED(macp, sizeof (uint32_t)) &&
- IS_P2ALIGNED(mac_buf, sizeof (uint32_t))) {
+ if (IS_P2ALIGNED2(macp, mac_buf, sizeof (uint32_t))) {
/* LINTED: pointer alignment */
*(uint32_t *)&mac_buf[0] ^= *(uint32_t *)&macp[0];
/* LINTED: pointer alignment */
*(uint32_t *)&mac_buf[4] ^= *(uint32_t *)&macp[4];
/* LINTED: pointer alignment */