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 */