Print this page
5072963 Need an optimized AES implementation for amd64
6699938 CCM max payload computation is off by one
*** 21,31 ****
/*
* 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"
#include <sys/sysmacros.h>
#include <sys/systm.h>
#include <sys/crypto/common.h>
--- 21,31 ----
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
! #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,58 ****
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 .
*/
static void
aes_init_ptrs(crypto_data_t *out, void **iov_or_mp, offset_t *current_offset)
{
offset_t offset;
--- 48,58 ----
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.
*/
static void
aes_init_ptrs(crypto_data_t *out, void **iov_or_mp, offset_t *current_offset)
{
offset_t offset;
*** 251,262 ****
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))) {
/* LINTED: pointer alignment */
*(uint32_t *)&blockp[0] ^=
/* LINTED: pointer alignment */
*(uint32_t *)&lastp[0];
/* LINTED: pointer alignment */
--- 251,261 ----
if (ctx->ac_flags & AES_CBC_MODE) {
/*
* XOR the previous cipher block or IV with the
* current clear block. Check for alignment.
*/
! 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,306 ****
--- 291,321 ----
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,472 ****
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))) {
/* LINTED: pointer alignment */
*(uint32_t *)blockp ^= *(uint32_t *)lastp;
/* LINTED: pointer alignment */
*(uint32_t *)&blockp[4] ^=
/* LINTED: pointer alignment */
--- 476,486 ----
if (ctx->ac_flags & AES_CBC_MODE) {
/*
* XOR the previous cipher block or IV with the
* currently decrypted block. Check for alignment.
*/
! 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,500 ****
--- 504,524 ----
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,703 ****
* 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))) {
/* LINTED: pointer alignment */
*(uint32_t *)&mac_buf[0] ^=
/* LINTED: pointer alignment */
*(uint32_t *)&blockp[0];
/* LINTED: pointer alignment */
--- 716,726 ----
* do CBC MAC
*
* XOR the previous cipher block current clear block.
* mac_buf always contain previous cipher block.
*/
! 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,769 ****
/*
* 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))) {
/* LINTED: pointer alignment */
*(uint32_t *)&blockp[0] ^=
/* LINTED: pointer alignment */
*(uint32_t *)&lastp[0];
/* LINTED: pointer alignment */
--- 781,791 ----
/*
* XOR the previous cipher block or IV with the
* current clear block. Check for alignment.
*/
! 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,812 ****
--- 820,850 ----
} 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,877 ****
/* 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))) {
/* 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 */
--- 904,914 ----
/* The IV for CBC MAC for AES CCM mode is always zero */
bzero(iv, AES_BLOCK_LEN);
ivp = (uint8_t *)iv;
! 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,914 ****
/* 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))) {
/* 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,950 ----
/* 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_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,951 ****
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))) {
/* 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 */
--- 976,986 ----
processed += AES_BLOCK_LEN;
remainder -= AES_BLOCK_LEN;
}
/* xor with previous buffer */
! 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,1043 ****
/* 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))) {
/* 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 */
--- 1067,1077 ----
/* copy remainder to temporary buffer */
bcopy(ctx->ac_remainder, macp, ctx->ac_remainder_len);
/* calculate the CBC MAC */
! 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,1168 ****
size_t macSize, nonceSize;
uint8_t q;
uint64_t maxValue;
/*
! * Check the length of the MAC. Only valid length
* 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 */
nonceSize = ccm_param->ulNonceSize;
if ((nonceSize < 7) || (nonceSize > 13)) {
return (CRYPTO_MECHANISM_PARAM_INVALID);
}
q = (uint8_t)((15 - nonceSize) & 0xFF);
/*
* If it is decrypt, need to make sure size of ciphertext is at least
--- 1179,1203 ----
size_t macSize, nonceSize;
uint8_t q;
uint64_t maxValue;
/*
! * 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 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,1185 ****
/*
* 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);
} else {
maxValue = ULONG_MAX;
}
if (ccm_param->ulDataSize > maxValue) {
--- 1210,1220 ----
/*
* 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)) - 1;
} else {
maxValue = ULONG_MAX;
}
if (ccm_param->ulDataSize > maxValue) {
*** 1190,1200 ****
return (0);
}
/*
* Format the first block used in CBC-MAC (B0) and the initial counter
! * block based on formating 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
*
--- 1225,1235 ----
return (0);
}
/*
* Format the first block used in CBC-MAC (B0) and the initial counter
! * 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,1227 ****
#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 */
if (authDataSize > 0) {
have_adata = 1;
}
b0[0] = (have_adata << 6) | (((t - 2) / 2) << 3) | (q - 1);
--- 1252,1262 ----
#endif /* _LITTLE_ENDIAN */
q = (uint8_t)((15 - nonceSize) & 0xFF);
t = (uint8_t)((aes_ctx->ac_ccm_mac_len) & 0xFF);
! /* Construct the first octet of b0 */
if (authDataSize > 0) {
have_adata = 1;
}
b0[0] = (have_adata << 6) | (((t - 2) / 2) << 3) | (q - 1);
*** 1270,1280 ****
/*
* 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
* counter block will be used for the counter value.
*/
cb[15] = 0x01;
/* EXPORT DELETE END */
--- 1305,1315 ----
/*
* 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 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,1534 ****
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))) {
/* 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 */
--- 1558,1568 ----
counter &= ctx->ac_counter_mask;
ctx->ac_cb[1] =
(ctx->ac_cb[1] & ~(ctx->ac_counter_mask)) | counter;
/* XOR with the ciphertext */
! 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,1551 ****
}
/* 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))) {
/* LINTED: pointer alignment */
*(uint32_t *)&resultp[0] = *(uint32_t *)blockp;
/* LINTED: pointer alignment */
*(uint32_t *)&resultp[4] = *(uint32_t *)&blockp[4];
/* LINTED: pointer alignment */
--- 1574,1584 ----
}
/* Copy the plaintext to the "holding buffer" */
resultp = (uint8_t *)ctx->ac_ccm_pt_buf +
ctx->ac_ccm_processed_data_len;
! 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,1638 ****
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))) {
/* LINTED: pointer alignment */
*(uint32_t *)&macp[0] = *(uint32_t *)pt;
/* LINTED: pointer alignment */
*(uint32_t *)&macp[4] = *(uint32_t *)&pt[4];
/* LINTED: pointer alignment */
--- 1660,1670 ----
if (mac_remain < AES_BLOCK_LEN) {
bzero(tmp, AES_BLOCK_LEN);
bcopy(pt, tmp, mac_remain);
mac_remain = 0;
} else {
! 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,1656 ****
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))) {
/* 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 */
--- 1677,1687 ----
mac_remain -= AES_BLOCK_LEN;
pt += AES_BLOCK_LEN;
}
/* calculate the CBC MAC */
! 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 */