mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-26 03:09:34 +03:00
icp: brutally remove unused AES modes
Still retaining the struture, for now. Sponsored-by: Klara, Inc. Sponsored-by: Wasabi Technology, Inc. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Rob Norris <rob.norris@klarasystems.com> Closes #16209
This commit is contained in:
parent
4185179190
commit
57249bcddc
@ -51,12 +51,6 @@ typedef struct crypto_mechanism {
|
||||
size_t cm_param_len; /* mech. parameter len */
|
||||
} crypto_mechanism_t;
|
||||
|
||||
/* CK_AES_CTR_PARAMS provides parameters to the CKM_AES_CTR mechanism */
|
||||
typedef struct CK_AES_CTR_PARAMS {
|
||||
ulong_t ulCounterBits;
|
||||
uint8_t cb[16];
|
||||
} CK_AES_CTR_PARAMS;
|
||||
|
||||
/* CK_AES_CCM_PARAMS provides parameters to the CKM_AES_CCM mechanism */
|
||||
typedef struct CK_AES_CCM_PARAMS {
|
||||
ulong_t ulMACSize;
|
||||
@ -77,13 +71,6 @@ typedef struct CK_AES_GCM_PARAMS {
|
||||
ulong_t ulTagBits;
|
||||
} CK_AES_GCM_PARAMS;
|
||||
|
||||
/* CK_AES_GMAC_PARAMS provides parameters to the CKM_AES_GMAC mechanism */
|
||||
typedef struct CK_AES_GMAC_PARAMS {
|
||||
uchar_t *pIv;
|
||||
uchar_t *pAAD;
|
||||
ulong_t ulAADLen;
|
||||
} CK_AES_GMAC_PARAMS;
|
||||
|
||||
/*
|
||||
* The measurement unit bit flag for a mechanism's minimum or maximum key size.
|
||||
* The unit are mechanism dependent. It can be in bits or in bytes.
|
||||
@ -103,12 +90,8 @@ typedef uint32_t crypto_keysize_unit_t;
|
||||
#define SUN_CKM_SHA512_HMAC_GENERAL "CKM_SHA512_HMAC_GENERAL"
|
||||
#define SUN_CKM_SHA512_224 "CKM_SHA512_224"
|
||||
#define SUN_CKM_SHA512_256 "CKM_SHA512_256"
|
||||
#define SUN_CKM_AES_CBC "CKM_AES_CBC"
|
||||
#define SUN_CKM_AES_ECB "CKM_AES_ECB"
|
||||
#define SUN_CKM_AES_CTR "CKM_AES_CTR"
|
||||
#define SUN_CKM_AES_CCM "CKM_AES_CCM"
|
||||
#define SUN_CKM_AES_GCM "CKM_AES_GCM"
|
||||
#define SUN_CKM_AES_GMAC "CKM_AES_GMAC"
|
||||
|
||||
/* Data arguments of cryptographic operations */
|
||||
|
||||
|
@ -18,13 +18,10 @@ nodist_libicp_la_SOURCES = \
|
||||
module/icp/algs/blake3/blake3_impl.c \
|
||||
module/icp/algs/edonr/edonr.c \
|
||||
module/icp/algs/modes/modes.c \
|
||||
module/icp/algs/modes/cbc.c \
|
||||
module/icp/algs/modes/gcm_generic.c \
|
||||
module/icp/algs/modes/gcm_pclmulqdq.c \
|
||||
module/icp/algs/modes/gcm.c \
|
||||
module/icp/algs/modes/ctr.c \
|
||||
module/icp/algs/modes/ccm.c \
|
||||
module/icp/algs/modes/ecb.c \
|
||||
module/icp/algs/sha2/sha2_generic.c \
|
||||
module/icp/algs/sha2/sha256_impl.c \
|
||||
module/icp/algs/sha2/sha512_impl.c \
|
||||
|
@ -101,10 +101,7 @@ ICP_OBJS := \
|
||||
algs/blake3/blake3_generic.o \
|
||||
algs/blake3/blake3_impl.o \
|
||||
algs/edonr/edonr.o \
|
||||
algs/modes/cbc.o \
|
||||
algs/modes/ccm.o \
|
||||
algs/modes/ctr.o \
|
||||
algs/modes/ecb.o \
|
||||
algs/modes/gcm.o \
|
||||
algs/modes/gcm_generic.o \
|
||||
algs/modes/modes.o \
|
||||
|
@ -75,25 +75,17 @@ aes_encrypt_contiguous_blocks(void *ctx, char *data, size_t length,
|
||||
aes_ctx_t *aes_ctx = ctx;
|
||||
int rv;
|
||||
|
||||
if (aes_ctx->ac_flags & CTR_MODE) {
|
||||
rv = ctr_mode_contiguous_blocks(ctx, data, length, out,
|
||||
AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
|
||||
} else if (aes_ctx->ac_flags & CCM_MODE) {
|
||||
if (aes_ctx->ac_flags & CCM_MODE) {
|
||||
rv = ccm_mode_encrypt_contiguous_blocks(ctx, data, length,
|
||||
out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
|
||||
aes_xor_block);
|
||||
} else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) {
|
||||
} else if (aes_ctx->ac_flags & GCM_MODE) {
|
||||
rv = gcm_mode_encrypt_contiguous_blocks(ctx, data, length,
|
||||
out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
|
||||
aes_xor_block);
|
||||
} else if (aes_ctx->ac_flags & CBC_MODE) {
|
||||
rv = cbc_encrypt_contiguous_blocks(ctx,
|
||||
data, length, out, AES_BLOCK_LEN, aes_encrypt_block,
|
||||
aes_copy_block, aes_xor_block);
|
||||
} else {
|
||||
rv = ecb_cipher_contiguous_blocks(ctx, data, length, out,
|
||||
AES_BLOCK_LEN, aes_encrypt_block);
|
||||
}
|
||||
else
|
||||
__builtin_unreachable();
|
||||
return (rv);
|
||||
}
|
||||
|
||||
@ -108,28 +100,15 @@ aes_decrypt_contiguous_blocks(void *ctx, char *data, size_t length,
|
||||
aes_ctx_t *aes_ctx = ctx;
|
||||
int rv;
|
||||
|
||||
if (aes_ctx->ac_flags & CTR_MODE) {
|
||||
rv = ctr_mode_contiguous_blocks(ctx, data, length, out,
|
||||
AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
|
||||
if (rv == CRYPTO_DATA_LEN_RANGE)
|
||||
rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
|
||||
} else if (aes_ctx->ac_flags & CCM_MODE) {
|
||||
if (aes_ctx->ac_flags & CCM_MODE) {
|
||||
rv = ccm_mode_decrypt_contiguous_blocks(ctx, data, length,
|
||||
out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
|
||||
aes_xor_block);
|
||||
} else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) {
|
||||
} else if (aes_ctx->ac_flags & GCM_MODE) {
|
||||
rv = gcm_mode_decrypt_contiguous_blocks(ctx, data, length,
|
||||
out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
|
||||
aes_xor_block);
|
||||
} else if (aes_ctx->ac_flags & CBC_MODE) {
|
||||
rv = cbc_decrypt_contiguous_blocks(ctx, data, length, out,
|
||||
AES_BLOCK_LEN, aes_decrypt_block, aes_copy_block,
|
||||
aes_xor_block);
|
||||
} else {
|
||||
rv = ecb_cipher_contiguous_blocks(ctx, data, length, out,
|
||||
AES_BLOCK_LEN, aes_decrypt_block);
|
||||
if (rv == CRYPTO_DATA_LEN_RANGE)
|
||||
rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
|
||||
}
|
||||
} else
|
||||
__builtin_unreachable();
|
||||
return (rv);
|
||||
}
|
||||
|
@ -1,264 +0,0 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or https://opensource.org/licenses/CDDL-1.0.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#include <sys/zfs_context.h>
|
||||
#include <modes/modes.h>
|
||||
#include <sys/crypto/common.h>
|
||||
#include <sys/crypto/impl.h>
|
||||
|
||||
/*
|
||||
* Algorithm independent CBC functions.
|
||||
*/
|
||||
int
|
||||
cbc_encrypt_contiguous_blocks(cbc_ctx_t *ctx, char *data, size_t length,
|
||||
crypto_data_t *out, size_t block_size,
|
||||
int (*encrypt)(const void *, const uint8_t *, uint8_t *),
|
||||
void (*copy_block)(uint8_t *, uint8_t *),
|
||||
void (*xor_block)(uint8_t *, uint8_t *))
|
||||
{
|
||||
size_t remainder = length;
|
||||
size_t need = 0;
|
||||
uint8_t *datap = (uint8_t *)data;
|
||||
uint8_t *blockp;
|
||||
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;
|
||||
|
||||
if (length + ctx->cbc_remainder_len < block_size) {
|
||||
/* accumulate bytes here and return */
|
||||
memcpy((uint8_t *)ctx->cbc_remainder + ctx->cbc_remainder_len,
|
||||
datap,
|
||||
length);
|
||||
ctx->cbc_remainder_len += length;
|
||||
ctx->cbc_copy_to = datap;
|
||||
return (CRYPTO_SUCCESS);
|
||||
}
|
||||
|
||||
lastp = (uint8_t *)ctx->cbc_iv;
|
||||
crypto_init_ptrs(out, &iov_or_mp, &offset);
|
||||
|
||||
do {
|
||||
/* Unprocessed data from last call. */
|
||||
if (ctx->cbc_remainder_len > 0) {
|
||||
need = block_size - ctx->cbc_remainder_len;
|
||||
|
||||
if (need > remainder)
|
||||
return (CRYPTO_DATA_LEN_RANGE);
|
||||
|
||||
memcpy(&((uint8_t *)ctx->cbc_remainder)
|
||||
[ctx->cbc_remainder_len], datap, need);
|
||||
|
||||
blockp = (uint8_t *)ctx->cbc_remainder;
|
||||
} else {
|
||||
blockp = datap;
|
||||
}
|
||||
|
||||
/*
|
||||
* XOR the previous cipher block or IV with the
|
||||
* current clear block.
|
||||
*/
|
||||
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 {
|
||||
memcpy(out_data_1, lastp, out_data_1_len);
|
||||
if (out_data_2 != NULL) {
|
||||
memcpy(out_data_2,
|
||||
lastp + out_data_1_len,
|
||||
block_size - out_data_1_len);
|
||||
}
|
||||
}
|
||||
/* update offset */
|
||||
out->cd_offset += block_size;
|
||||
|
||||
/* Update pointer to next block of data to be processed. */
|
||||
if (ctx->cbc_remainder_len != 0) {
|
||||
datap += need;
|
||||
ctx->cbc_remainder_len = 0;
|
||||
} else {
|
||||
datap += block_size;
|
||||
}
|
||||
|
||||
remainder = (size_t)&data[length] - (size_t)datap;
|
||||
|
||||
/* Incomplete last block. */
|
||||
if (remainder > 0 && remainder < block_size) {
|
||||
memcpy(ctx->cbc_remainder, datap, remainder);
|
||||
ctx->cbc_remainder_len = remainder;
|
||||
ctx->cbc_copy_to = datap;
|
||||
goto out;
|
||||
}
|
||||
ctx->cbc_copy_to = NULL;
|
||||
|
||||
} while (remainder > 0);
|
||||
|
||||
out:
|
||||
/*
|
||||
* Save the last encrypted block in the context.
|
||||
*/
|
||||
if (ctx->cbc_lastp != NULL) {
|
||||
copy_block((uint8_t *)ctx->cbc_lastp, (uint8_t *)ctx->cbc_iv);
|
||||
ctx->cbc_lastp = (uint8_t *)ctx->cbc_iv;
|
||||
}
|
||||
|
||||
return (CRYPTO_SUCCESS);
|
||||
}
|
||||
|
||||
#define OTHER(a, ctx) \
|
||||
(((a) == (ctx)->cbc_lastblock) ? (ctx)->cbc_iv : (ctx)->cbc_lastblock)
|
||||
|
||||
int
|
||||
cbc_decrypt_contiguous_blocks(cbc_ctx_t *ctx, char *data, size_t length,
|
||||
crypto_data_t *out, size_t block_size,
|
||||
int (*decrypt)(const void *, const uint8_t *, uint8_t *),
|
||||
void (*copy_block)(uint8_t *, uint8_t *),
|
||||
void (*xor_block)(uint8_t *, uint8_t *))
|
||||
{
|
||||
size_t remainder = length;
|
||||
size_t need = 0;
|
||||
uint8_t *datap = (uint8_t *)data;
|
||||
uint8_t *blockp;
|
||||
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;
|
||||
|
||||
if (length + ctx->cbc_remainder_len < block_size) {
|
||||
/* accumulate bytes here and return */
|
||||
memcpy((uint8_t *)ctx->cbc_remainder + ctx->cbc_remainder_len,
|
||||
datap,
|
||||
length);
|
||||
ctx->cbc_remainder_len += length;
|
||||
ctx->cbc_copy_to = datap;
|
||||
return (CRYPTO_SUCCESS);
|
||||
}
|
||||
|
||||
lastp = ctx->cbc_lastp;
|
||||
crypto_init_ptrs(out, &iov_or_mp, &offset);
|
||||
|
||||
do {
|
||||
/* Unprocessed data from last call. */
|
||||
if (ctx->cbc_remainder_len > 0) {
|
||||
need = block_size - ctx->cbc_remainder_len;
|
||||
|
||||
if (need > remainder)
|
||||
return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
|
||||
|
||||
memcpy(&((uint8_t *)ctx->cbc_remainder)
|
||||
[ctx->cbc_remainder_len], datap, need);
|
||||
|
||||
blockp = (uint8_t *)ctx->cbc_remainder;
|
||||
} else {
|
||||
blockp = datap;
|
||||
}
|
||||
|
||||
/* LINTED: pointer alignment */
|
||||
copy_block(blockp, (uint8_t *)OTHER((uint64_t *)lastp, ctx));
|
||||
|
||||
decrypt(ctx->cbc_keysched, blockp,
|
||||
(uint8_t *)ctx->cbc_remainder);
|
||||
blockp = (uint8_t *)ctx->cbc_remainder;
|
||||
|
||||
/*
|
||||
* XOR the previous cipher block or IV with the
|
||||
* currently decrypted block.
|
||||
*/
|
||||
xor_block(lastp, blockp);
|
||||
|
||||
/* LINTED: pointer alignment */
|
||||
lastp = (uint8_t *)OTHER((uint64_t *)lastp, ctx);
|
||||
|
||||
crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
|
||||
&out_data_1_len, &out_data_2, block_size);
|
||||
|
||||
memcpy(out_data_1, blockp, out_data_1_len);
|
||||
if (out_data_2 != NULL) {
|
||||
memcpy(out_data_2, blockp + out_data_1_len,
|
||||
block_size - out_data_1_len);
|
||||
}
|
||||
|
||||
/* update offset */
|
||||
out->cd_offset += block_size;
|
||||
|
||||
/* Update pointer to next block of data to be processed. */
|
||||
if (ctx->cbc_remainder_len != 0) {
|
||||
datap += need;
|
||||
ctx->cbc_remainder_len = 0;
|
||||
} else {
|
||||
datap += block_size;
|
||||
}
|
||||
|
||||
remainder = (size_t)&data[length] - (size_t)datap;
|
||||
|
||||
/* Incomplete last block. */
|
||||
if (remainder > 0 && remainder < block_size) {
|
||||
memcpy(ctx->cbc_remainder, datap, remainder);
|
||||
ctx->cbc_remainder_len = remainder;
|
||||
ctx->cbc_lastp = lastp;
|
||||
ctx->cbc_copy_to = datap;
|
||||
return (CRYPTO_SUCCESS);
|
||||
}
|
||||
ctx->cbc_copy_to = NULL;
|
||||
|
||||
} while (remainder > 0);
|
||||
|
||||
ctx->cbc_lastp = lastp;
|
||||
return (CRYPTO_SUCCESS);
|
||||
}
|
||||
|
||||
int
|
||||
cbc_init_ctx(cbc_ctx_t *cbc_ctx, char *param, size_t param_len,
|
||||
size_t block_size, void (*copy_block)(uint8_t *, uint64_t *))
|
||||
{
|
||||
/* Copy IV into context. */
|
||||
ASSERT3P(param, !=, NULL);
|
||||
ASSERT3U(param_len, ==, block_size);
|
||||
|
||||
copy_block((uchar_t *)param, cbc_ctx->cbc_iv);
|
||||
|
||||
return (CRYPTO_SUCCESS);
|
||||
}
|
||||
|
||||
void *
|
||||
cbc_alloc_ctx(int kmflag)
|
||||
{
|
||||
cbc_ctx_t *cbc_ctx;
|
||||
|
||||
if ((cbc_ctx = kmem_zalloc(sizeof (cbc_ctx_t), kmflag)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
cbc_ctx->cbc_flags = CBC_MODE;
|
||||
return (cbc_ctx);
|
||||
}
|
@ -1,227 +0,0 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or https://opensource.org/licenses/CDDL-1.0.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#include <sys/zfs_context.h>
|
||||
#include <modes/modes.h>
|
||||
#include <sys/crypto/common.h>
|
||||
#include <sys/crypto/impl.h>
|
||||
#include <sys/byteorder.h>
|
||||
|
||||
/*
|
||||
* Encrypt and decrypt multiple blocks of data in counter mode.
|
||||
*/
|
||||
int
|
||||
ctr_mode_contiguous_blocks(ctr_ctx_t *ctx, char *data, size_t length,
|
||||
crypto_data_t *out, size_t block_size,
|
||||
int (*cipher)(const void *ks, const uint8_t *pt, uint8_t *ct),
|
||||
void (*xor_block)(uint8_t *, uint8_t *))
|
||||
{
|
||||
size_t remainder = length;
|
||||
size_t need = 0;
|
||||
uint8_t *datap = (uint8_t *)data;
|
||||
uint8_t *blockp;
|
||||
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;
|
||||
uint64_t lower_counter, upper_counter;
|
||||
|
||||
if (length + ctx->ctr_remainder_len < block_size) {
|
||||
/* accumulate bytes here and return */
|
||||
memcpy((uint8_t *)ctx->ctr_remainder + ctx->ctr_remainder_len,
|
||||
datap,
|
||||
length);
|
||||
ctx->ctr_remainder_len += length;
|
||||
ctx->ctr_copy_to = datap;
|
||||
return (CRYPTO_SUCCESS);
|
||||
}
|
||||
|
||||
crypto_init_ptrs(out, &iov_or_mp, &offset);
|
||||
|
||||
do {
|
||||
/* Unprocessed data from last call. */
|
||||
if (ctx->ctr_remainder_len > 0) {
|
||||
need = block_size - ctx->ctr_remainder_len;
|
||||
|
||||
if (need > remainder)
|
||||
return (CRYPTO_DATA_LEN_RANGE);
|
||||
|
||||
memcpy(&((uint8_t *)ctx->ctr_remainder)
|
||||
[ctx->ctr_remainder_len], datap, need);
|
||||
|
||||
blockp = (uint8_t *)ctx->ctr_remainder;
|
||||
} else {
|
||||
blockp = datap;
|
||||
}
|
||||
|
||||
/* ctr_cb is the counter block */
|
||||
cipher(ctx->ctr_keysched, (uint8_t *)ctx->ctr_cb,
|
||||
(uint8_t *)ctx->ctr_tmp);
|
||||
|
||||
lastp = (uint8_t *)ctx->ctr_tmp;
|
||||
|
||||
/*
|
||||
* Increment Counter.
|
||||
*/
|
||||
lower_counter = ntohll(ctx->ctr_cb[1] & ctx->ctr_lower_mask);
|
||||
lower_counter = htonll(lower_counter + 1);
|
||||
lower_counter &= ctx->ctr_lower_mask;
|
||||
ctx->ctr_cb[1] = (ctx->ctr_cb[1] & ~(ctx->ctr_lower_mask)) |
|
||||
lower_counter;
|
||||
|
||||
/* wrap around */
|
||||
if (lower_counter == 0) {
|
||||
upper_counter =
|
||||
ntohll(ctx->ctr_cb[0] & ctx->ctr_upper_mask);
|
||||
upper_counter = htonll(upper_counter + 1);
|
||||
upper_counter &= ctx->ctr_upper_mask;
|
||||
ctx->ctr_cb[0] =
|
||||
(ctx->ctr_cb[0] & ~(ctx->ctr_upper_mask)) |
|
||||
upper_counter;
|
||||
}
|
||||
|
||||
/*
|
||||
* XOR encrypted counter block with the current clear block.
|
||||
*/
|
||||
xor_block(blockp, 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 */
|
||||
memcpy(out_data_1, lastp, out_data_1_len);
|
||||
if (out_data_2 != NULL) {
|
||||
memcpy(out_data_2, lastp + out_data_1_len,
|
||||
block_size - out_data_1_len);
|
||||
}
|
||||
/* update offset */
|
||||
out->cd_offset += block_size;
|
||||
|
||||
/* Update pointer to next block of data to be processed. */
|
||||
if (ctx->ctr_remainder_len != 0) {
|
||||
datap += need;
|
||||
ctx->ctr_remainder_len = 0;
|
||||
} else {
|
||||
datap += block_size;
|
||||
}
|
||||
|
||||
remainder = (size_t)&data[length] - (size_t)datap;
|
||||
|
||||
/* Incomplete last block. */
|
||||
if (remainder > 0 && remainder < block_size) {
|
||||
memcpy(ctx->ctr_remainder, datap, remainder);
|
||||
ctx->ctr_remainder_len = remainder;
|
||||
ctx->ctr_copy_to = datap;
|
||||
goto out;
|
||||
}
|
||||
ctx->ctr_copy_to = NULL;
|
||||
|
||||
} while (remainder > 0);
|
||||
|
||||
out:
|
||||
return (CRYPTO_SUCCESS);
|
||||
}
|
||||
|
||||
int
|
||||
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;
|
||||
|
||||
if (out->cd_length < ctx->ctr_remainder_len)
|
||||
return (CRYPTO_DATA_LEN_RANGE);
|
||||
|
||||
encrypt_block(ctx->ctr_keysched, (uint8_t *)ctx->ctr_cb,
|
||||
(uint8_t *)ctx->ctr_tmp);
|
||||
|
||||
lastp = (uint8_t *)ctx->ctr_tmp;
|
||||
p = (uint8_t *)ctx->ctr_remainder;
|
||||
for (i = 0; i < ctx->ctr_remainder_len; i++) {
|
||||
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);
|
||||
|
||||
memcpy(out_data_1, p, out_data_1_len);
|
||||
if (out_data_2 != NULL) {
|
||||
memcpy(out_data_2,
|
||||
(uint8_t *)p + out_data_1_len,
|
||||
ctx->ctr_remainder_len - out_data_1_len);
|
||||
}
|
||||
out->cd_offset += ctx->ctr_remainder_len;
|
||||
ctx->ctr_remainder_len = 0;
|
||||
return (CRYPTO_SUCCESS);
|
||||
}
|
||||
|
||||
int
|
||||
ctr_init_ctx(ctr_ctx_t *ctr_ctx, ulong_t count, uint8_t *cb,
|
||||
void (*copy_block)(uint8_t *, uint8_t *))
|
||||
{
|
||||
uint64_t upper_mask = 0;
|
||||
uint64_t lower_mask = 0;
|
||||
|
||||
if (count == 0 || count > 128) {
|
||||
return (CRYPTO_MECHANISM_PARAM_INVALID);
|
||||
}
|
||||
/* upper 64 bits of the mask */
|
||||
if (count >= 64) {
|
||||
count -= 64;
|
||||
upper_mask = (count == 64) ? UINT64_MAX : (1ULL << count) - 1;
|
||||
lower_mask = UINT64_MAX;
|
||||
} else {
|
||||
/* now the lower 63 bits */
|
||||
lower_mask = (1ULL << count) - 1;
|
||||
}
|
||||
ctr_ctx->ctr_lower_mask = htonll(lower_mask);
|
||||
ctr_ctx->ctr_upper_mask = htonll(upper_mask);
|
||||
|
||||
copy_block(cb, (uchar_t *)ctr_ctx->ctr_cb);
|
||||
ctr_ctx->ctr_lastp = (uint8_t *)&ctr_ctx->ctr_cb[0];
|
||||
ctr_ctx->ctr_flags |= CTR_MODE;
|
||||
return (CRYPTO_SUCCESS);
|
||||
}
|
||||
|
||||
void *
|
||||
ctr_alloc_ctx(int kmflag)
|
||||
{
|
||||
ctr_ctx_t *ctr_ctx;
|
||||
|
||||
if ((ctr_ctx = kmem_zalloc(sizeof (ctr_ctx_t), kmflag)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
ctr_ctx->ctr_flags = CTR_MODE;
|
||||
return (ctr_ctx);
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or https://opensource.org/licenses/CDDL-1.0.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#include <sys/zfs_context.h>
|
||||
#include <modes/modes.h>
|
||||
#include <sys/crypto/common.h>
|
||||
#include <sys/crypto/impl.h>
|
||||
|
||||
/*
|
||||
* Algorithm independent ECB functions.
|
||||
*/
|
||||
int
|
||||
ecb_cipher_contiguous_blocks(ecb_ctx_t *ctx, char *data, size_t length,
|
||||
crypto_data_t *out, size_t block_size,
|
||||
int (*cipher)(const void *ks, const uint8_t *pt, uint8_t *ct))
|
||||
{
|
||||
size_t remainder = length;
|
||||
size_t need = 0;
|
||||
uint8_t *datap = (uint8_t *)data;
|
||||
uint8_t *blockp;
|
||||
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;
|
||||
|
||||
if (length + ctx->ecb_remainder_len < block_size) {
|
||||
/* accumulate bytes here and return */
|
||||
memcpy((uint8_t *)ctx->ecb_remainder + ctx->ecb_remainder_len,
|
||||
datap,
|
||||
length);
|
||||
ctx->ecb_remainder_len += length;
|
||||
ctx->ecb_copy_to = datap;
|
||||
return (CRYPTO_SUCCESS);
|
||||
}
|
||||
|
||||
lastp = (uint8_t *)ctx->ecb_iv;
|
||||
crypto_init_ptrs(out, &iov_or_mp, &offset);
|
||||
|
||||
do {
|
||||
/* Unprocessed data from last call. */
|
||||
if (ctx->ecb_remainder_len > 0) {
|
||||
need = block_size - ctx->ecb_remainder_len;
|
||||
|
||||
if (need > remainder)
|
||||
return (CRYPTO_DATA_LEN_RANGE);
|
||||
|
||||
memcpy(&((uint8_t *)ctx->ecb_remainder)
|
||||
[ctx->ecb_remainder_len], datap, need);
|
||||
|
||||
blockp = (uint8_t *)ctx->ecb_remainder;
|
||||
} else {
|
||||
blockp = datap;
|
||||
}
|
||||
|
||||
cipher(ctx->ecb_keysched, blockp, 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 */
|
||||
memcpy(out_data_1, lastp, out_data_1_len);
|
||||
if (out_data_2 != NULL) {
|
||||
memcpy(out_data_2, lastp + out_data_1_len,
|
||||
block_size - out_data_1_len);
|
||||
}
|
||||
/* update offset */
|
||||
out->cd_offset += block_size;
|
||||
|
||||
/* Update pointer to next block of data to be processed. */
|
||||
if (ctx->ecb_remainder_len != 0) {
|
||||
datap += need;
|
||||
ctx->ecb_remainder_len = 0;
|
||||
} else {
|
||||
datap += block_size;
|
||||
}
|
||||
|
||||
remainder = (size_t)&data[length] - (size_t)datap;
|
||||
|
||||
/* Incomplete last block. */
|
||||
if (remainder > 0 && remainder < block_size) {
|
||||
memcpy(ctx->ecb_remainder, datap, remainder);
|
||||
ctx->ecb_remainder_len = remainder;
|
||||
ctx->ecb_copy_to = datap;
|
||||
goto out;
|
||||
}
|
||||
ctx->ecb_copy_to = NULL;
|
||||
|
||||
} while (remainder > 0);
|
||||
|
||||
out:
|
||||
return (CRYPTO_SUCCESS);
|
||||
}
|
||||
|
||||
void *
|
||||
ecb_alloc_ctx(int kmflag)
|
||||
{
|
||||
ecb_ctx_t *ecb_ctx;
|
||||
|
||||
if ((ecb_ctx = kmem_zalloc(sizeof (ecb_ctx_t), kmflag)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
ecb_ctx->ecb_flags = ECB_MODE;
|
||||
return (ecb_ctx);
|
||||
}
|
@ -50,11 +50,6 @@
|
||||
static uint32_t icp_gcm_impl = IMPL_FASTEST;
|
||||
static uint32_t user_sel_impl = IMPL_FASTEST;
|
||||
|
||||
static inline int gcm_init_ctx_impl(boolean_t, gcm_ctx_t *, char *, size_t,
|
||||
int (*)(const void *, const uint8_t *, uint8_t *),
|
||||
void (*)(uint8_t *, uint8_t *),
|
||||
void (*)(uint8_t *, uint8_t *));
|
||||
|
||||
#ifdef CAN_USE_GCM_ASM
|
||||
/* Does the architecture we run on support the MOVBE instruction? */
|
||||
boolean_t gcm_avx_can_use_movbe = B_FALSE;
|
||||
@ -590,40 +585,11 @@ gcm_init(gcm_ctx_t *ctx, const uint8_t *iv, size_t iv_len,
|
||||
return (CRYPTO_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* The following function is called at encrypt or decrypt init time
|
||||
* for AES GCM mode.
|
||||
*/
|
||||
int
|
||||
gcm_init_ctx(gcm_ctx_t *gcm_ctx, char *param, size_t block_size,
|
||||
int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
|
||||
void (*copy_block)(uint8_t *, uint8_t *),
|
||||
void (*xor_block)(uint8_t *, uint8_t *))
|
||||
{
|
||||
return (gcm_init_ctx_impl(B_FALSE, gcm_ctx, param, block_size,
|
||||
encrypt_block, copy_block, xor_block));
|
||||
}
|
||||
|
||||
/*
|
||||
* The following function is called at encrypt or decrypt init time
|
||||
* for AES GMAC mode.
|
||||
*/
|
||||
int
|
||||
gmac_init_ctx(gcm_ctx_t *gcm_ctx, char *param, size_t block_size,
|
||||
int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
|
||||
void (*copy_block)(uint8_t *, uint8_t *),
|
||||
void (*xor_block)(uint8_t *, uint8_t *))
|
||||
{
|
||||
return (gcm_init_ctx_impl(B_TRUE, gcm_ctx, param, block_size,
|
||||
encrypt_block, copy_block, xor_block));
|
||||
}
|
||||
|
||||
/*
|
||||
* Init the GCM context struct. Handle the cycle and avx implementations here.
|
||||
* Initialization of a GMAC context differs slightly from a GCM context.
|
||||
*/
|
||||
static inline int
|
||||
gcm_init_ctx_impl(boolean_t gmac_mode, gcm_ctx_t *gcm_ctx, char *param,
|
||||
int
|
||||
gcm_init_ctx(gcm_ctx_t *gcm_ctx, char *param,
|
||||
size_t block_size, int (*encrypt_block)(const void *, const uint8_t *,
|
||||
uint8_t *), void (*copy_block)(uint8_t *, uint8_t *),
|
||||
void (*xor_block)(uint8_t *, uint8_t *))
|
||||
@ -635,7 +601,6 @@ gcm_init_ctx_impl(boolean_t gmac_mode, gcm_ctx_t *gcm_ctx, char *param,
|
||||
if (param != NULL) {
|
||||
gcm_param = (CK_AES_GCM_PARAMS *)(void *)param;
|
||||
|
||||
if (gmac_mode == B_FALSE) {
|
||||
/* GCM mode. */
|
||||
if ((rv = gcm_validate_args(gcm_param)) != 0) {
|
||||
return (rv);
|
||||
@ -645,12 +610,7 @@ gcm_init_ctx_impl(boolean_t gmac_mode, gcm_ctx_t *gcm_ctx, char *param,
|
||||
size_t tbits = gcm_param->ulTagBits;
|
||||
tag_len = CRYPTO_BITS2BYTES(tbits);
|
||||
iv_len = gcm_param->ulIvLen;
|
||||
} else {
|
||||
/* GMAC mode. */
|
||||
gcm_ctx->gcm_flags |= GMAC_MODE;
|
||||
tag_len = CRYPTO_BITS2BYTES(AES_GMAC_TAG_BITS);
|
||||
iv_len = AES_GMAC_IV_LEN;
|
||||
}
|
||||
|
||||
gcm_ctx->gcm_tag_len = tag_len;
|
||||
gcm_ctx->gcm_processed_data_len = 0;
|
||||
|
||||
@ -684,10 +644,9 @@ gcm_init_ctx_impl(boolean_t gmac_mode, gcm_ctx_t *gcm_ctx, char *param,
|
||||
}
|
||||
/*
|
||||
* If this is a GCM context, use the MOVBE and the BSWAP
|
||||
* variants alternately. GMAC contexts code paths do not
|
||||
* use the MOVBE instruction.
|
||||
* variants alternately.
|
||||
*/
|
||||
if (gcm_ctx->gcm_use_avx == B_TRUE && gmac_mode == B_FALSE &&
|
||||
if (gcm_ctx->gcm_use_avx == B_TRUE &&
|
||||
zfs_movbe_available() == B_TRUE) {
|
||||
(void) atomic_toggle_boolean_nv(
|
||||
(volatile boolean_t *)&gcm_avx_can_use_movbe);
|
||||
@ -758,18 +717,6 @@ gcm_alloc_ctx(int kmflag)
|
||||
return (gcm_ctx);
|
||||
}
|
||||
|
||||
void *
|
||||
gmac_alloc_ctx(int kmflag)
|
||||
{
|
||||
gcm_ctx_t *gcm_ctx;
|
||||
|
||||
if ((gcm_ctx = kmem_zalloc(sizeof (gcm_ctx_t), kmflag)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
gcm_ctx->gcm_flags = GMAC_MODE;
|
||||
return (gcm_ctx);
|
||||
}
|
||||
|
||||
/* GCM implementation that contains the fastest methods */
|
||||
static gcm_impl_ops_t gcm_fastest_impl = {
|
||||
.name = "fastest"
|
||||
|
@ -126,20 +126,7 @@ 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)) {
|
||||
case ECB_MODE:
|
||||
kmem_free(common_ctx, sizeof (ecb_ctx_t));
|
||||
break;
|
||||
|
||||
case CBC_MODE:
|
||||
kmem_free(common_ctx, sizeof (cbc_ctx_t));
|
||||
break;
|
||||
|
||||
case CTR_MODE:
|
||||
kmem_free(common_ctx, sizeof (ctr_ctx_t));
|
||||
break;
|
||||
|
||||
switch (common_ctx->cc_flags & (CCM_MODE|GCM_MODE)) {
|
||||
case CCM_MODE:
|
||||
if (((ccm_ctx_t *)ctx)->ccm_pt_buf != NULL)
|
||||
vmem_free(((ccm_ctx_t *)ctx)->ccm_pt_buf,
|
||||
@ -149,9 +136,12 @@ crypto_free_mode_ctx(void *ctx)
|
||||
break;
|
||||
|
||||
case GCM_MODE:
|
||||
case GMAC_MODE:
|
||||
gcm_clear_ctx((gcm_ctx_t *)ctx);
|
||||
kmem_free(ctx, sizeof (gcm_ctx_t));
|
||||
break;
|
||||
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,13 +149,8 @@ extern int aes_decrypt_contiguous_blocks(void *ctx, char *data, size_t length,
|
||||
#ifdef _AES_IMPL
|
||||
|
||||
typedef enum aes_mech_type {
|
||||
AES_ECB_MECH_INFO_TYPE, /* SUN_CKM_AES_ECB */
|
||||
AES_CBC_MECH_INFO_TYPE, /* SUN_CKM_AES_CBC */
|
||||
AES_CBC_PAD_MECH_INFO_TYPE, /* SUN_CKM_AES_CBC_PAD */
|
||||
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_mech_type_t;
|
||||
|
||||
#endif /* _AES_IMPL */
|
||||
|
@ -45,12 +45,8 @@ extern "C" {
|
||||
extern boolean_t gcm_avx_can_use_movbe;
|
||||
#endif
|
||||
|
||||
#define ECB_MODE 0x00000002
|
||||
#define CBC_MODE 0x00000004
|
||||
#define CTR_MODE 0x00000008
|
||||
#define CCM_MODE 0x00000010
|
||||
#define GCM_MODE 0x00000020
|
||||
#define GMAC_MODE 0x00000040
|
||||
|
||||
/*
|
||||
* cc_keysched: Pointer to key schedule.
|
||||
@ -76,7 +72,7 @@ extern boolean_t gcm_avx_can_use_movbe;
|
||||
* by the caller, or internally, e.g. an init routine.
|
||||
* If allocated by the latter, then it needs to be freed.
|
||||
*
|
||||
* ECB_MODE, CBC_MODE, CTR_MODE, or CCM_MODE
|
||||
* CCM_MODE
|
||||
*/
|
||||
struct common_ctx {
|
||||
void *cc_keysched;
|
||||
@ -91,57 +87,6 @@ struct common_ctx {
|
||||
|
||||
typedef struct common_ctx common_ctx_t;
|
||||
|
||||
typedef struct ecb_ctx {
|
||||
struct common_ctx ecb_common;
|
||||
uint64_t ecb_lastblock[2];
|
||||
} ecb_ctx_t;
|
||||
|
||||
#define ecb_keysched ecb_common.cc_keysched
|
||||
#define ecb_keysched_len ecb_common.cc_keysched_len
|
||||
#define ecb_iv ecb_common.cc_iv
|
||||
#define ecb_remainder ecb_common.cc_remainder
|
||||
#define ecb_remainder_len ecb_common.cc_remainder_len
|
||||
#define ecb_lastp ecb_common.cc_lastp
|
||||
#define ecb_copy_to ecb_common.cc_copy_to
|
||||
#define ecb_flags ecb_common.cc_flags
|
||||
|
||||
typedef struct cbc_ctx {
|
||||
struct common_ctx cbc_common;
|
||||
uint64_t cbc_lastblock[2];
|
||||
} cbc_ctx_t;
|
||||
|
||||
#define cbc_keysched cbc_common.cc_keysched
|
||||
#define cbc_keysched_len cbc_common.cc_keysched_len
|
||||
#define cbc_iv cbc_common.cc_iv
|
||||
#define cbc_remainder cbc_common.cc_remainder
|
||||
#define cbc_remainder_len cbc_common.cc_remainder_len
|
||||
#define cbc_lastp cbc_common.cc_lastp
|
||||
#define cbc_copy_to cbc_common.cc_copy_to
|
||||
#define cbc_flags cbc_common.cc_flags
|
||||
|
||||
/*
|
||||
* ctr_lower_mask Bit-mask for lower 8 bytes of counter block.
|
||||
* ctr_upper_mask Bit-mask for upper 8 bytes of counter block.
|
||||
*/
|
||||
typedef struct ctr_ctx {
|
||||
struct common_ctx ctr_common;
|
||||
uint64_t ctr_lower_mask;
|
||||
uint64_t ctr_upper_mask;
|
||||
uint32_t ctr_tmp[4];
|
||||
} ctr_ctx_t;
|
||||
|
||||
/*
|
||||
* ctr_cb Counter block.
|
||||
*/
|
||||
#define ctr_keysched ctr_common.cc_keysched
|
||||
#define ctr_keysched_len ctr_common.cc_keysched_len
|
||||
#define ctr_cb ctr_common.cc_iv
|
||||
#define ctr_remainder ctr_common.cc_remainder
|
||||
#define ctr_remainder_len ctr_common.cc_remainder_len
|
||||
#define ctr_lastp ctr_common.cc_lastp
|
||||
#define ctr_copy_to ctr_common.cc_copy_to
|
||||
#define ctr_flags ctr_common.cc_flags
|
||||
|
||||
/*
|
||||
*
|
||||
* ccm_mac_len: Stores length of the MAC in CCM mode.
|
||||
@ -241,27 +186,21 @@ typedef struct gcm_ctx {
|
||||
#define gcm_copy_to gcm_common.cc_copy_to
|
||||
#define gcm_flags gcm_common.cc_flags
|
||||
|
||||
#define AES_GMAC_IV_LEN 12
|
||||
#define AES_GMAC_TAG_BITS 128
|
||||
|
||||
void gcm_clear_ctx(gcm_ctx_t *ctx);
|
||||
|
||||
typedef struct aes_ctx {
|
||||
union {
|
||||
ecb_ctx_t acu_ecb;
|
||||
cbc_ctx_t acu_cbc;
|
||||
ctr_ctx_t acu_ctr;
|
||||
ccm_ctx_t acu_ccm;
|
||||
gcm_ctx_t acu_gcm;
|
||||
} acu;
|
||||
} aes_ctx_t;
|
||||
|
||||
#define ac_flags acu.acu_ecb.ecb_common.cc_flags
|
||||
#define ac_remainder_len acu.acu_ecb.ecb_common.cc_remainder_len
|
||||
#define ac_keysched acu.acu_ecb.ecb_common.cc_keysched
|
||||
#define ac_keysched_len acu.acu_ecb.ecb_common.cc_keysched_len
|
||||
#define ac_iv acu.acu_ecb.ecb_common.cc_iv
|
||||
#define ac_lastp acu.acu_ecb.ecb_common.cc_lastp
|
||||
#define ac_flags acu.acu_ccm.ccm_common.cc_flags
|
||||
#define ac_remainder_len acu.acu_ccm.ccm_common.cc_remainder_len
|
||||
#define ac_keysched acu.acu_ccm.ccm_common.cc_keysched
|
||||
#define ac_keysched_len acu.acu_ccm.ccm_common.cc_keysched_len
|
||||
#define ac_iv acu.acu_ccm.ccm_common.cc_iv
|
||||
#define ac_lastp acu.acu_ccm.ccm_common.cc_lastp
|
||||
#define ac_pt_buf acu.acu_ccm.ccm_pt_buf
|
||||
#define ac_mac_len acu.acu_ccm.ccm_mac_len
|
||||
#define ac_data_len acu.acu_ccm.ccm_data_len
|
||||
@ -269,27 +208,6 @@ typedef struct aes_ctx {
|
||||
#define ac_processed_data_len acu.acu_ccm.ccm_processed_data_len
|
||||
#define ac_tag_len acu.acu_gcm.gcm_tag_len
|
||||
|
||||
extern int ecb_cipher_contiguous_blocks(ecb_ctx_t *, char *, size_t,
|
||||
crypto_data_t *, size_t, int (*cipher)(const void *, const uint8_t *,
|
||||
uint8_t *));
|
||||
|
||||
extern int cbc_encrypt_contiguous_blocks(cbc_ctx_t *, char *, size_t,
|
||||
crypto_data_t *, size_t,
|
||||
int (*encrypt)(const void *, const uint8_t *, uint8_t *),
|
||||
void (*copy_block)(uint8_t *, uint8_t *),
|
||||
void (*xor_block)(uint8_t *, uint8_t *));
|
||||
|
||||
extern int cbc_decrypt_contiguous_blocks(cbc_ctx_t *, char *, size_t,
|
||||
crypto_data_t *, size_t,
|
||||
int (*decrypt)(const void *, const uint8_t *, uint8_t *),
|
||||
void (*copy_block)(uint8_t *, uint8_t *),
|
||||
void (*xor_block)(uint8_t *, uint8_t *));
|
||||
|
||||
extern int ctr_mode_contiguous_blocks(ctr_ctx_t *, char *, size_t,
|
||||
crypto_data_t *, size_t,
|
||||
int (*cipher)(const void *, const uint8_t *, uint8_t *),
|
||||
void (*xor_block)(uint8_t *, uint8_t *));
|
||||
|
||||
extern int ccm_mode_encrypt_contiguous_blocks(ccm_ctx_t *, char *, size_t,
|
||||
crypto_data_t *, size_t,
|
||||
int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
|
||||
@ -332,15 +250,6 @@ 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 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 ctr_init_ctx(ctr_ctx_t *, ulong_t, uint8_t *,
|
||||
void (*copy_block)(uint8_t *, uint8_t *));
|
||||
|
||||
extern int ccm_init_ctx(ccm_ctx_t *, char *, int, boolean_t, size_t,
|
||||
int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
|
||||
void (*xor_block)(uint8_t *, uint8_t *));
|
||||
@ -350,11 +259,6 @@ extern int gcm_init_ctx(gcm_ctx_t *, char *, size_t,
|
||||
void (*copy_block)(uint8_t *, uint8_t *),
|
||||
void (*xor_block)(uint8_t *, uint8_t *));
|
||||
|
||||
extern int gmac_init_ctx(gcm_ctx_t *, char *, size_t,
|
||||
int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
|
||||
void (*copy_block)(uint8_t *, uint8_t *),
|
||||
void (*xor_block)(uint8_t *, uint8_t *));
|
||||
|
||||
extern void calculate_ccm_mac(ccm_ctx_t *, uint8_t *,
|
||||
int (*encrypt_block)(const void *, const uint8_t *, uint8_t *));
|
||||
|
||||
@ -364,12 +268,8 @@ extern void crypto_init_ptrs(crypto_data_t *, void **, offset_t *);
|
||||
extern void crypto_get_ptrs(crypto_data_t *, void **, offset_t *,
|
||||
uint8_t **, size_t *, uint8_t **, size_t);
|
||||
|
||||
extern void *ecb_alloc_ctx(int);
|
||||
extern void *cbc_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 *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -40,18 +40,6 @@
|
||||
* Mechanism info structure passed to KCF during registration.
|
||||
*/
|
||||
static const crypto_mech_info_t aes_mech_info_tab[] = {
|
||||
/* AES_ECB */
|
||||
{SUN_CKM_AES_ECB, AES_ECB_MECH_INFO_TYPE,
|
||||
CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
|
||||
CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC},
|
||||
/* AES_CBC */
|
||||
{SUN_CKM_AES_CBC, AES_CBC_MECH_INFO_TYPE,
|
||||
CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
|
||||
CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC},
|
||||
/* AES_CTR */
|
||||
{SUN_CKM_AES_CTR, AES_CTR_MECH_INFO_TYPE,
|
||||
CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
|
||||
CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC},
|
||||
/* AES_CCM */
|
||||
{SUN_CKM_AES_CCM, AES_CCM_MECH_INFO_TYPE,
|
||||
CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
|
||||
@ -60,11 +48,6 @@ static const crypto_mech_info_t aes_mech_info_tab[] = {
|
||||
{SUN_CKM_AES_GCM, AES_GCM_MECH_INFO_TYPE,
|
||||
CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
|
||||
CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC},
|
||||
/* AES_GMAC */
|
||||
{SUN_CKM_AES_GMAC, AES_GMAC_MECH_INFO_TYPE,
|
||||
CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
|
||||
CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC |
|
||||
CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC},
|
||||
};
|
||||
|
||||
static int aes_encrypt_init(crypto_ctx_t *, crypto_mechanism_t *,
|
||||
@ -103,20 +86,6 @@ static const crypto_cipher_ops_t aes_cipher_ops = {
|
||||
.decrypt_atomic = aes_decrypt_atomic
|
||||
};
|
||||
|
||||
static int aes_mac_atomic(crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
|
||||
crypto_data_t *, crypto_spi_ctx_template_t);
|
||||
static int aes_mac_verify_atomic(crypto_mechanism_t *, crypto_key_t *,
|
||||
crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t);
|
||||
|
||||
static const crypto_mac_ops_t aes_mac_ops = {
|
||||
.mac_init = NULL,
|
||||
.mac = NULL,
|
||||
.mac_update = NULL,
|
||||
.mac_final = NULL,
|
||||
.mac_atomic = aes_mac_atomic,
|
||||
.mac_verify_atomic = aes_mac_verify_atomic
|
||||
};
|
||||
|
||||
static int aes_create_ctx_template(crypto_mechanism_t *, crypto_key_t *,
|
||||
crypto_spi_ctx_template_t *, size_t *);
|
||||
static int aes_free_context(crypto_ctx_t *);
|
||||
@ -129,7 +98,7 @@ static const crypto_ctx_ops_t aes_ctx_ops = {
|
||||
static const crypto_ops_t aes_crypto_ops = {
|
||||
NULL,
|
||||
&aes_cipher_ops,
|
||||
&aes_mac_ops,
|
||||
NULL,
|
||||
&aes_ctx_ops,
|
||||
};
|
||||
|
||||
@ -141,7 +110,6 @@ static const crypto_provider_info_t aes_prov_info = {
|
||||
};
|
||||
|
||||
static crypto_kcf_provider_handle_t aes_prov_handle = 0;
|
||||
static crypto_data_t null_crypto_data = { CRYPTO_DATA_RAW };
|
||||
|
||||
int
|
||||
aes_mod_init(void)
|
||||
@ -181,18 +149,6 @@ aes_check_mech_param(crypto_mechanism_t *mechanism, aes_ctx_t **ctx)
|
||||
int rv = CRYPTO_SUCCESS;
|
||||
|
||||
switch (mechanism->cm_type) {
|
||||
case AES_ECB_MECH_INFO_TYPE:
|
||||
param_required = B_FALSE;
|
||||
alloc_fun = ecb_alloc_ctx;
|
||||
break;
|
||||
case AES_CBC_MECH_INFO_TYPE:
|
||||
param_len = AES_BLOCK_LEN;
|
||||
alloc_fun = cbc_alloc_ctx;
|
||||
break;
|
||||
case AES_CTR_MECH_INFO_TYPE:
|
||||
param_len = sizeof (CK_AES_CTR_PARAMS);
|
||||
alloc_fun = ctr_alloc_ctx;
|
||||
break;
|
||||
case AES_CCM_MECH_INFO_TYPE:
|
||||
param_len = sizeof (CK_AES_CCM_PARAMS);
|
||||
alloc_fun = ccm_alloc_ctx;
|
||||
@ -201,13 +157,8 @@ aes_check_mech_param(crypto_mechanism_t *mechanism, aes_ctx_t **ctx)
|
||||
param_len = sizeof (CK_AES_GCM_PARAMS);
|
||||
alloc_fun = gcm_alloc_ctx;
|
||||
break;
|
||||
case AES_GMAC_MECH_INFO_TYPE:
|
||||
param_len = sizeof (CK_AES_GMAC_PARAMS);
|
||||
alloc_fun = gmac_alloc_ctx;
|
||||
break;
|
||||
default:
|
||||
rv = CRYPTO_MECHANISM_INVALID;
|
||||
return (rv);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
if (param_required && mechanism->cm_param != NULL &&
|
||||
mechanism->cm_param_len != param_len) {
|
||||
@ -282,22 +233,6 @@ aes_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
|
||||
return (CRYPTO_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
aes_copy_block64(uint8_t *in, uint64_t *out)
|
||||
{
|
||||
if (IS_P2ALIGNED(in, sizeof (uint64_t))) {
|
||||
/* LINTED: pointer alignment */
|
||||
out[0] = *(uint64_t *)&in[0];
|
||||
/* LINTED: pointer alignment */
|
||||
out[1] = *(uint64_t *)&in[8];
|
||||
} else {
|
||||
uint8_t *iv8 = (uint8_t *)&out[0];
|
||||
|
||||
AES_COPY_BLOCK(in, iv8);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
aes_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
|
||||
crypto_data_t *ciphertext)
|
||||
@ -310,35 +245,21 @@ aes_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
|
||||
ASSERT(ctx->cc_provider_private != NULL);
|
||||
aes_ctx = ctx->cc_provider_private;
|
||||
|
||||
/*
|
||||
* 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)
|
||||
return (CRYPTO_DATA_LEN_RANGE);
|
||||
|
||||
ASSERT(ciphertext != NULL);
|
||||
|
||||
/*
|
||||
* 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 & (CCM_MODE|GCM_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 GMAC_MODE:
|
||||
if (plaintext->cd_length != 0)
|
||||
return (CRYPTO_ARGUMENTS_BAD);
|
||||
|
||||
length_needed = aes_ctx->ac_tag_len;
|
||||
break;
|
||||
default:
|
||||
length_needed = plaintext->cd_length;
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
if (ciphertext->cd_length < length_needed) {
|
||||
@ -382,7 +303,7 @@ 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 & (GCM_MODE|GMAC_MODE)) {
|
||||
} else if (aes_ctx->ac_flags & GCM_MODE) {
|
||||
/*
|
||||
* gcm_encrypt_final() will compute the MAC and append
|
||||
* it to existing ciphertext. So, need to adjust the left over
|
||||
@ -426,15 +347,6 @@ aes_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
|
||||
ASSERT(ctx->cc_provider_private != NULL);
|
||||
aes_ctx = ctx->cc_provider_private;
|
||||
|
||||
/*
|
||||
* 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) && (ciphertext->cd_length & (AES_BLOCK_LEN - 1)) != 0) {
|
||||
return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
|
||||
}
|
||||
|
||||
ASSERT(plaintext != NULL);
|
||||
|
||||
/*
|
||||
@ -443,23 +355,16 @@ aes_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
|
||||
*
|
||||
* CCM: plaintext is MAC len smaller than cipher text
|
||||
* GCM: plaintext is TAG len smaller than cipher text
|
||||
* GMAC: plaintext length must be zero
|
||||
*/
|
||||
switch (aes_ctx->ac_flags & (CCM_MODE|GCM_MODE|GMAC_MODE)) {
|
||||
switch (aes_ctx->ac_flags & (CCM_MODE|GCM_MODE)) {
|
||||
case CCM_MODE:
|
||||
length_needed = aes_ctx->ac_processed_data_len;
|
||||
break;
|
||||
case GCM_MODE:
|
||||
length_needed = ciphertext->cd_length - aes_ctx->ac_tag_len;
|
||||
break;
|
||||
case GMAC_MODE:
|
||||
if (plaintext->cd_length != 0)
|
||||
return (CRYPTO_ARGUMENTS_BAD);
|
||||
|
||||
length_needed = 0;
|
||||
break;
|
||||
default:
|
||||
length_needed = ciphertext->cd_length;
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
if (plaintext->cd_length < length_needed) {
|
||||
@ -499,7 +404,7 @@ aes_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
|
||||
}
|
||||
|
||||
plaintext->cd_offset = saved_offset;
|
||||
} else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) {
|
||||
} else if (aes_ctx->ac_flags & GCM_MODE) {
|
||||
/* order of following 2 lines MUST not be reversed */
|
||||
plaintext->cd_offset = plaintext->cd_length;
|
||||
plaintext->cd_length = saved_length - plaintext->cd_length;
|
||||
@ -571,17 +476,6 @@ aes_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
|
||||
ret = CRYPTO_ARGUMENTS_BAD;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since AES counter mode is a stream cipher, we call
|
||||
* ctr_mode_final() to pick up any remaining bytes.
|
||||
* It is an internal function that does not destroy
|
||||
* the context like *normal* final routines.
|
||||
*/
|
||||
if ((aes_ctx->ac_flags & CTR_MODE) && (aes_ctx->ac_remainder_len > 0)) {
|
||||
ret = ctr_mode_final((ctr_ctx_t *)aes_ctx,
|
||||
ciphertext, aes_encrypt_block);
|
||||
}
|
||||
|
||||
if (ret == CRYPTO_SUCCESS) {
|
||||
if (plaintext != ciphertext)
|
||||
ciphertext->cd_length =
|
||||
@ -600,32 +494,13 @@ aes_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
|
||||
crypto_data_t *plaintext)
|
||||
{
|
||||
off_t saved_offset;
|
||||
size_t saved_length, out_len;
|
||||
size_t saved_length;
|
||||
int ret = CRYPTO_SUCCESS;
|
||||
aes_ctx_t *aes_ctx;
|
||||
|
||||
ASSERT(ctx->cc_provider_private != NULL);
|
||||
aes_ctx = ctx->cc_provider_private;
|
||||
|
||||
ASSERT(plaintext != NULL);
|
||||
|
||||
/*
|
||||
* Compute number of bytes that will hold the plaintext.
|
||||
* This is not necessary for CCM, GCM, and GMAC since these
|
||||
* mechanisms never return plaintext for update operations.
|
||||
*/
|
||||
if ((aes_ctx->ac_flags & (CCM_MODE|GCM_MODE|GMAC_MODE)) == 0) {
|
||||
out_len = aes_ctx->ac_remainder_len;
|
||||
out_len += ciphertext->cd_length;
|
||||
out_len &= ~(AES_BLOCK_LEN - 1);
|
||||
|
||||
/* return length needed to store the output */
|
||||
if (plaintext->cd_length < out_len) {
|
||||
plaintext->cd_length = out_len;
|
||||
return (CRYPTO_BUFFER_TOO_SMALL);
|
||||
}
|
||||
}
|
||||
|
||||
saved_offset = plaintext->cd_offset;
|
||||
saved_length = plaintext->cd_length;
|
||||
|
||||
@ -645,19 +520,6 @@ aes_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
|
||||
ret = CRYPTO_ARGUMENTS_BAD;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since AES counter mode is a stream cipher, we call
|
||||
* ctr_mode_final() to pick up any remaining bytes.
|
||||
* It is an internal function that does not destroy
|
||||
* the context like *normal* final routines.
|
||||
*/
|
||||
if ((aes_ctx->ac_flags & CTR_MODE) && (aes_ctx->ac_remainder_len > 0)) {
|
||||
ret = ctr_mode_final((ctr_ctx_t *)aes_ctx, plaintext,
|
||||
aes_encrypt_block);
|
||||
if (ret == CRYPTO_DATA_LEN_RANGE)
|
||||
ret = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
|
||||
}
|
||||
|
||||
if (ret == CRYPTO_SUCCESS) {
|
||||
if (ciphertext != plaintext)
|
||||
plaintext->cd_length =
|
||||
@ -685,20 +547,13 @@ aes_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data)
|
||||
return (CRYPTO_ARGUMENTS_BAD);
|
||||
}
|
||||
|
||||
if (aes_ctx->ac_flags & CTR_MODE) {
|
||||
if (aes_ctx->ac_remainder_len > 0) {
|
||||
ret = ctr_mode_final((ctr_ctx_t *)aes_ctx, data,
|
||||
aes_encrypt_block);
|
||||
if (ret != CRYPTO_SUCCESS)
|
||||
return (ret);
|
||||
}
|
||||
} else if (aes_ctx->ac_flags & CCM_MODE) {
|
||||
if (aes_ctx->ac_flags & CCM_MODE) {
|
||||
ret = ccm_encrypt_final((ccm_ctx_t *)aes_ctx, data,
|
||||
AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
|
||||
if (ret != CRYPTO_SUCCESS) {
|
||||
return (ret);
|
||||
}
|
||||
} else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) {
|
||||
} else if (aes_ctx->ac_flags & GCM_MODE) {
|
||||
size_t saved_offset = data->cd_offset;
|
||||
|
||||
ret = gcm_encrypt_final((gcm_ctx_t *)aes_ctx, data,
|
||||
@ -709,16 +564,6 @@ 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 {
|
||||
/*
|
||||
* There must be no unprocessed plaintext.
|
||||
* This happens if the length of the last data is
|
||||
* not a multiple of the AES block length.
|
||||
*/
|
||||
if (aes_ctx->ac_remainder_len > 0) {
|
||||
return (CRYPTO_DATA_LEN_RANGE);
|
||||
}
|
||||
data->cd_length = 0;
|
||||
}
|
||||
|
||||
(void) aes_free_context(ctx);
|
||||
@ -747,18 +592,8 @@ aes_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data)
|
||||
* This happens if the length of the last ciphertext is
|
||||
* not a multiple of the AES block length.
|
||||
*/
|
||||
if (aes_ctx->ac_remainder_len > 0) {
|
||||
if ((aes_ctx->ac_flags & CTR_MODE) == 0)
|
||||
if (aes_ctx->ac_remainder_len > 0)
|
||||
return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
|
||||
else {
|
||||
ret = ctr_mode_final((ctr_ctx_t *)aes_ctx, data,
|
||||
aes_encrypt_block);
|
||||
if (ret == CRYPTO_DATA_LEN_RANGE)
|
||||
ret = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
|
||||
if (ret != CRYPTO_SUCCESS)
|
||||
return (ret);
|
||||
}
|
||||
}
|
||||
|
||||
if (aes_ctx->ac_flags & CCM_MODE) {
|
||||
/*
|
||||
@ -788,7 +623,7 @@ aes_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data)
|
||||
if (ret != CRYPTO_SUCCESS) {
|
||||
return (ret);
|
||||
}
|
||||
} else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) {
|
||||
} else if (aes_ctx->ac_flags & GCM_MODE) {
|
||||
/*
|
||||
* This is where all the plaintext is returned, make sure
|
||||
* the plaintext buffer is big enough
|
||||
@ -818,10 +653,6 @@ aes_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data)
|
||||
}
|
||||
|
||||
|
||||
if ((aes_ctx->ac_flags & (CTR_MODE|CCM_MODE|GCM_MODE|GMAC_MODE)) == 0) {
|
||||
data->cd_length = 0;
|
||||
}
|
||||
|
||||
(void) aes_free_context(ctx);
|
||||
|
||||
return (CRYPTO_SUCCESS);
|
||||
@ -842,21 +673,6 @@ aes_encrypt_atomic(crypto_mechanism_t *mechanism,
|
||||
|
||||
ASSERT(ciphertext != NULL);
|
||||
|
||||
/*
|
||||
* CTR, CCM, GCM, and GMAC modes do not require that plaintext
|
||||
* be a multiple of AES block size.
|
||||
*/
|
||||
switch (mechanism->cm_type) {
|
||||
case AES_CTR_MECH_INFO_TYPE:
|
||||
case AES_CCM_MECH_INFO_TYPE:
|
||||
case AES_GCM_MECH_INFO_TYPE:
|
||||
case AES_GMAC_MECH_INFO_TYPE:
|
||||
break;
|
||||
default:
|
||||
if ((plaintext->cd_length & (AES_BLOCK_LEN - 1)) != 0)
|
||||
return (CRYPTO_DATA_LEN_RANGE);
|
||||
}
|
||||
|
||||
if ((ret = aes_check_mech_param(mechanism, NULL)) != CRYPTO_SUCCESS)
|
||||
return (ret);
|
||||
|
||||
@ -869,15 +685,11 @@ aes_encrypt_atomic(crypto_mechanism_t *mechanism,
|
||||
case AES_CCM_MECH_INFO_TYPE:
|
||||
length_needed = plaintext->cd_length + aes_ctx.ac_mac_len;
|
||||
break;
|
||||
case AES_GMAC_MECH_INFO_TYPE:
|
||||
if (plaintext->cd_length != 0)
|
||||
return (CRYPTO_ARGUMENTS_BAD);
|
||||
zfs_fallthrough;
|
||||
case AES_GCM_MECH_INFO_TYPE:
|
||||
length_needed = plaintext->cd_length + aes_ctx.ac_tag_len;
|
||||
break;
|
||||
default:
|
||||
length_needed = plaintext->cd_length;
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
/* return size of buffer needed to store output */
|
||||
@ -914,21 +726,13 @@ aes_encrypt_atomic(crypto_mechanism_t *mechanism,
|
||||
if (ret != CRYPTO_SUCCESS)
|
||||
goto out;
|
||||
ASSERT(aes_ctx.ac_remainder_len == 0);
|
||||
} else if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE ||
|
||||
mechanism->cm_type == AES_GMAC_MECH_INFO_TYPE) {
|
||||
} else if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE) {
|
||||
ret = gcm_encrypt_final((gcm_ctx_t *)&aes_ctx,
|
||||
ciphertext, AES_BLOCK_LEN, aes_encrypt_block,
|
||||
aes_copy_block, aes_xor_block);
|
||||
if (ret != CRYPTO_SUCCESS)
|
||||
goto out;
|
||||
ASSERT(aes_ctx.ac_remainder_len == 0);
|
||||
} else if (mechanism->cm_type == AES_CTR_MECH_INFO_TYPE) {
|
||||
if (aes_ctx.ac_remainder_len > 0) {
|
||||
ret = ctr_mode_final((ctr_ctx_t *)&aes_ctx,
|
||||
ciphertext, aes_encrypt_block);
|
||||
if (ret != CRYPTO_SUCCESS)
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
ASSERT(aes_ctx.ac_remainder_len == 0);
|
||||
}
|
||||
@ -947,7 +751,7 @@ out:
|
||||
memset(aes_ctx.ac_keysched, 0, aes_ctx.ac_keysched_len);
|
||||
kmem_free(aes_ctx.ac_keysched, aes_ctx.ac_keysched_len);
|
||||
}
|
||||
if (aes_ctx.ac_flags & (GCM_MODE|GMAC_MODE)) {
|
||||
if (aes_ctx.ac_flags & GCM_MODE) {
|
||||
gcm_clear_ctx((gcm_ctx_t *)&aes_ctx);
|
||||
}
|
||||
return (ret);
|
||||
@ -968,21 +772,6 @@ aes_decrypt_atomic(crypto_mechanism_t *mechanism,
|
||||
|
||||
ASSERT(plaintext != NULL);
|
||||
|
||||
/*
|
||||
* CCM, GCM, CTR, and GMAC modes do not require that ciphertext
|
||||
* be a multiple of AES block size.
|
||||
*/
|
||||
switch (mechanism->cm_type) {
|
||||
case AES_CTR_MECH_INFO_TYPE:
|
||||
case AES_CCM_MECH_INFO_TYPE:
|
||||
case AES_GCM_MECH_INFO_TYPE:
|
||||
case AES_GMAC_MECH_INFO_TYPE:
|
||||
break;
|
||||
default:
|
||||
if ((ciphertext->cd_length & (AES_BLOCK_LEN - 1)) != 0)
|
||||
return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
|
||||
}
|
||||
|
||||
if ((ret = aes_check_mech_param(mechanism, NULL)) != CRYPTO_SUCCESS)
|
||||
return (ret);
|
||||
|
||||
@ -998,13 +787,8 @@ aes_decrypt_atomic(crypto_mechanism_t *mechanism,
|
||||
case AES_GCM_MECH_INFO_TYPE:
|
||||
length_needed = ciphertext->cd_length - aes_ctx.ac_tag_len;
|
||||
break;
|
||||
case AES_GMAC_MECH_INFO_TYPE:
|
||||
if (plaintext->cd_length != 0)
|
||||
return (CRYPTO_ARGUMENTS_BAD);
|
||||
length_needed = 0;
|
||||
break;
|
||||
default:
|
||||
length_needed = ciphertext->cd_length;
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
/* return size of buffer needed to store output */
|
||||
@ -1050,8 +834,7 @@ aes_decrypt_atomic(crypto_mechanism_t *mechanism,
|
||||
} else {
|
||||
plaintext->cd_length = saved_length;
|
||||
}
|
||||
} else if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE ||
|
||||
mechanism->cm_type == AES_GMAC_MECH_INFO_TYPE) {
|
||||
} else if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE) {
|
||||
ret = gcm_decrypt_final((gcm_ctx_t *)&aes_ctx,
|
||||
plaintext, AES_BLOCK_LEN, aes_encrypt_block,
|
||||
aes_xor_block);
|
||||
@ -1063,24 +846,8 @@ aes_decrypt_atomic(crypto_mechanism_t *mechanism,
|
||||
} else {
|
||||
plaintext->cd_length = saved_length;
|
||||
}
|
||||
} else if (mechanism->cm_type != AES_CTR_MECH_INFO_TYPE) {
|
||||
ASSERT(aes_ctx.ac_remainder_len == 0);
|
||||
if (ciphertext != plaintext)
|
||||
plaintext->cd_length =
|
||||
plaintext->cd_offset - saved_offset;
|
||||
} else {
|
||||
if (aes_ctx.ac_remainder_len > 0) {
|
||||
ret = ctr_mode_final((ctr_ctx_t *)&aes_ctx,
|
||||
plaintext, aes_encrypt_block);
|
||||
if (ret == CRYPTO_DATA_LEN_RANGE)
|
||||
ret = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
|
||||
if (ret != CRYPTO_SUCCESS)
|
||||
goto out;
|
||||
}
|
||||
if (ciphertext != plaintext)
|
||||
plaintext->cd_length =
|
||||
plaintext->cd_offset - saved_offset;
|
||||
}
|
||||
} else
|
||||
__builtin_unreachable();
|
||||
} else {
|
||||
plaintext->cd_length = saved_length;
|
||||
}
|
||||
@ -1096,7 +863,7 @@ out:
|
||||
if (aes_ctx.ac_pt_buf != NULL) {
|
||||
vmem_free(aes_ctx.ac_pt_buf, aes_ctx.ac_data_len);
|
||||
}
|
||||
} else if (aes_ctx.ac_flags & (GCM_MODE|GMAC_MODE)) {
|
||||
} else if (aes_ctx.ac_flags & GCM_MODE) {
|
||||
gcm_clear_ctx((gcm_ctx_t *)&aes_ctx);
|
||||
}
|
||||
|
||||
@ -1114,12 +881,8 @@ aes_create_ctx_template(crypto_mechanism_t *mechanism, crypto_key_t *key,
|
||||
size_t size;
|
||||
int rv;
|
||||
|
||||
if (mechanism->cm_type != AES_ECB_MECH_INFO_TYPE &&
|
||||
mechanism->cm_type != AES_CBC_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 &&
|
||||
mechanism->cm_type != AES_GMAC_MECH_INFO_TYPE)
|
||||
if (mechanism->cm_type != AES_CCM_MECH_INFO_TYPE &&
|
||||
mechanism->cm_type != AES_GCM_MECH_INFO_TYPE)
|
||||
return (CRYPTO_MECHANISM_INVALID);
|
||||
|
||||
if ((keysched = aes_alloc_keysched(&size, KM_SLEEP)) == NULL) {
|
||||
@ -1193,22 +956,6 @@ aes_common_init_ctx(aes_ctx_t *aes_ctx, crypto_spi_ctx_template_t *template,
|
||||
aes_ctx->ac_keysched = keysched;
|
||||
|
||||
switch (mechanism->cm_type) {
|
||||
case AES_CBC_MECH_INFO_TYPE:
|
||||
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_CTR_MECH_INFO_TYPE: {
|
||||
CK_AES_CTR_PARAMS *pp;
|
||||
|
||||
if (mechanism->cm_param == NULL ||
|
||||
mechanism->cm_param_len != sizeof (CK_AES_CTR_PARAMS)) {
|
||||
return (CRYPTO_MECHANISM_PARAM_INVALID);
|
||||
}
|
||||
pp = (CK_AES_CTR_PARAMS *)(void *)mechanism->cm_param;
|
||||
rv = ctr_init_ctx((ctr_ctx_t *)aes_ctx, pp->ulCounterBits,
|
||||
pp->cb, aes_copy_block);
|
||||
break;
|
||||
}
|
||||
case AES_CCM_MECH_INFO_TYPE:
|
||||
if (mechanism->cm_param == NULL ||
|
||||
mechanism->cm_param_len != sizeof (CK_AES_CCM_PARAMS)) {
|
||||
@ -1227,17 +974,6 @@ aes_common_init_ctx(aes_ctx_t *aes_ctx, crypto_spi_ctx_template_t *template,
|
||||
AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
|
||||
aes_xor_block);
|
||||
break;
|
||||
case AES_GMAC_MECH_INFO_TYPE:
|
||||
if (mechanism->cm_param == NULL ||
|
||||
mechanism->cm_param_len != sizeof (CK_AES_GMAC_PARAMS)) {
|
||||
return (CRYPTO_MECHANISM_PARAM_INVALID);
|
||||
}
|
||||
rv = gmac_init_ctx((gcm_ctx_t *)aes_ctx, mechanism->cm_param,
|
||||
AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
|
||||
aes_xor_block);
|
||||
break;
|
||||
case AES_ECB_MECH_INFO_TYPE:
|
||||
aes_ctx->ac_flags |= ECB_MODE;
|
||||
}
|
||||
|
||||
if (rv != CRYPTO_SUCCESS) {
|
||||
@ -1249,75 +985,3 @@ aes_common_init_ctx(aes_ctx_t *aes_ctx, crypto_spi_ctx_template_t *template,
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static int
|
||||
process_gmac_mech(crypto_mechanism_t *mech, crypto_data_t *data,
|
||||
CK_AES_GCM_PARAMS *gcm_params)
|
||||
{
|
||||
/* LINTED: pointer alignment */
|
||||
CK_AES_GMAC_PARAMS *params = (CK_AES_GMAC_PARAMS *)mech->cm_param;
|
||||
|
||||
if (mech->cm_type != AES_GMAC_MECH_INFO_TYPE)
|
||||
return (CRYPTO_MECHANISM_INVALID);
|
||||
|
||||
if (mech->cm_param_len != sizeof (CK_AES_GMAC_PARAMS))
|
||||
return (CRYPTO_MECHANISM_PARAM_INVALID);
|
||||
|
||||
if (params->pIv == NULL)
|
||||
return (CRYPTO_MECHANISM_PARAM_INVALID);
|
||||
|
||||
gcm_params->pIv = params->pIv;
|
||||
gcm_params->ulIvLen = AES_GMAC_IV_LEN;
|
||||
gcm_params->ulTagBits = AES_GMAC_TAG_BITS;
|
||||
|
||||
if (data == NULL)
|
||||
return (CRYPTO_SUCCESS);
|
||||
|
||||
if (data->cd_format != CRYPTO_DATA_RAW)
|
||||
return (CRYPTO_ARGUMENTS_BAD);
|
||||
|
||||
gcm_params->pAAD = (uchar_t *)data->cd_raw.iov_base;
|
||||
gcm_params->ulAADLen = data->cd_length;
|
||||
return (CRYPTO_SUCCESS);
|
||||
}
|
||||
|
||||
static int
|
||||
aes_mac_atomic(crypto_mechanism_t *mechanism,
|
||||
crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
|
||||
crypto_spi_ctx_template_t template)
|
||||
{
|
||||
CK_AES_GCM_PARAMS gcm_params;
|
||||
crypto_mechanism_t gcm_mech;
|
||||
int rv;
|
||||
|
||||
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_encrypt_atomic(&gcm_mech,
|
||||
key, &null_crypto_data, mac, template));
|
||||
}
|
||||
|
||||
static int
|
||||
aes_mac_verify_atomic(crypto_mechanism_t *mechanism, crypto_key_t *key,
|
||||
crypto_data_t *data, crypto_data_t *mac, crypto_spi_ctx_template_t template)
|
||||
{
|
||||
CK_AES_GCM_PARAMS gcm_params;
|
||||
crypto_mechanism_t gcm_mech;
|
||||
int rv;
|
||||
|
||||
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(&gcm_mech,
|
||||
key, mac, &null_crypto_data, template));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user