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 */
|
size_t cm_param_len; /* mech. parameter len */
|
||||||
} crypto_mechanism_t;
|
} 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 */
|
/* CK_AES_CCM_PARAMS provides parameters to the CKM_AES_CCM mechanism */
|
||||||
typedef struct CK_AES_CCM_PARAMS {
|
typedef struct CK_AES_CCM_PARAMS {
|
||||||
ulong_t ulMACSize;
|
ulong_t ulMACSize;
|
||||||
|
@ -77,13 +71,6 @@ typedef struct CK_AES_GCM_PARAMS {
|
||||||
ulong_t ulTagBits;
|
ulong_t ulTagBits;
|
||||||
} CK_AES_GCM_PARAMS;
|
} 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 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.
|
* 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_HMAC_GENERAL "CKM_SHA512_HMAC_GENERAL"
|
||||||
#define SUN_CKM_SHA512_224 "CKM_SHA512_224"
|
#define SUN_CKM_SHA512_224 "CKM_SHA512_224"
|
||||||
#define SUN_CKM_SHA512_256 "CKM_SHA512_256"
|
#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_CCM "CKM_AES_CCM"
|
||||||
#define SUN_CKM_AES_GCM "CKM_AES_GCM"
|
#define SUN_CKM_AES_GCM "CKM_AES_GCM"
|
||||||
#define SUN_CKM_AES_GMAC "CKM_AES_GMAC"
|
|
||||||
|
|
||||||
/* Data arguments of cryptographic operations */
|
/* Data arguments of cryptographic operations */
|
||||||
|
|
||||||
|
|
|
@ -18,13 +18,10 @@ nodist_libicp_la_SOURCES = \
|
||||||
module/icp/algs/blake3/blake3_impl.c \
|
module/icp/algs/blake3/blake3_impl.c \
|
||||||
module/icp/algs/edonr/edonr.c \
|
module/icp/algs/edonr/edonr.c \
|
||||||
module/icp/algs/modes/modes.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_generic.c \
|
||||||
module/icp/algs/modes/gcm_pclmulqdq.c \
|
module/icp/algs/modes/gcm_pclmulqdq.c \
|
||||||
module/icp/algs/modes/gcm.c \
|
module/icp/algs/modes/gcm.c \
|
||||||
module/icp/algs/modes/ctr.c \
|
|
||||||
module/icp/algs/modes/ccm.c \
|
module/icp/algs/modes/ccm.c \
|
||||||
module/icp/algs/modes/ecb.c \
|
|
||||||
module/icp/algs/sha2/sha2_generic.c \
|
module/icp/algs/sha2/sha2_generic.c \
|
||||||
module/icp/algs/sha2/sha256_impl.c \
|
module/icp/algs/sha2/sha256_impl.c \
|
||||||
module/icp/algs/sha2/sha512_impl.c \
|
module/icp/algs/sha2/sha512_impl.c \
|
||||||
|
|
|
@ -101,10 +101,7 @@ ICP_OBJS := \
|
||||||
algs/blake3/blake3_generic.o \
|
algs/blake3/blake3_generic.o \
|
||||||
algs/blake3/blake3_impl.o \
|
algs/blake3/blake3_impl.o \
|
||||||
algs/edonr/edonr.o \
|
algs/edonr/edonr.o \
|
||||||
algs/modes/cbc.o \
|
|
||||||
algs/modes/ccm.o \
|
algs/modes/ccm.o \
|
||||||
algs/modes/ctr.o \
|
|
||||||
algs/modes/ecb.o \
|
|
||||||
algs/modes/gcm.o \
|
algs/modes/gcm.o \
|
||||||
algs/modes/gcm_generic.o \
|
algs/modes/gcm_generic.o \
|
||||||
algs/modes/modes.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;
|
aes_ctx_t *aes_ctx = ctx;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
if (aes_ctx->ac_flags & CTR_MODE) {
|
if (aes_ctx->ac_flags & CCM_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) {
|
|
||||||
rv = ccm_mode_encrypt_contiguous_blocks(ctx, data, length,
|
rv = ccm_mode_encrypt_contiguous_blocks(ctx, data, length,
|
||||||
out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
|
out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
|
||||||
aes_xor_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,
|
rv = gcm_mode_encrypt_contiguous_blocks(ctx, data, length,
|
||||||
out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
|
out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
|
||||||
aes_xor_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);
|
return (rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,28 +100,15 @@ aes_decrypt_contiguous_blocks(void *ctx, char *data, size_t length,
|
||||||
aes_ctx_t *aes_ctx = ctx;
|
aes_ctx_t *aes_ctx = ctx;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
if (aes_ctx->ac_flags & CTR_MODE) {
|
if (aes_ctx->ac_flags & CCM_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) {
|
|
||||||
rv = ccm_mode_decrypt_contiguous_blocks(ctx, data, length,
|
rv = ccm_mode_decrypt_contiguous_blocks(ctx, data, length,
|
||||||
out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
|
out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
|
||||||
aes_xor_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,
|
rv = gcm_mode_decrypt_contiguous_blocks(ctx, data, length,
|
||||||
out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
|
out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
|
||||||
aes_xor_block);
|
aes_xor_block);
|
||||||
} else if (aes_ctx->ac_flags & CBC_MODE) {
|
} else
|
||||||
rv = cbc_decrypt_contiguous_blocks(ctx, data, length, out,
|
__builtin_unreachable();
|
||||||
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;
|
|
||||||
}
|
|
||||||
return (rv);
|
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 icp_gcm_impl = IMPL_FASTEST;
|
||||||
static uint32_t user_sel_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
|
#ifdef CAN_USE_GCM_ASM
|
||||||
/* Does the architecture we run on support the MOVBE instruction? */
|
/* Does the architecture we run on support the MOVBE instruction? */
|
||||||
boolean_t gcm_avx_can_use_movbe = B_FALSE;
|
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);
|
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.
|
* 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
|
int
|
||||||
gcm_init_ctx_impl(boolean_t gmac_mode, gcm_ctx_t *gcm_ctx, char *param,
|
gcm_init_ctx(gcm_ctx_t *gcm_ctx, char *param,
|
||||||
size_t block_size, int (*encrypt_block)(const void *, const uint8_t *,
|
size_t block_size, int (*encrypt_block)(const void *, const uint8_t *,
|
||||||
uint8_t *), void (*copy_block)(uint8_t *, uint8_t *),
|
uint8_t *), void (*copy_block)(uint8_t *, uint8_t *),
|
||||||
void (*xor_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) {
|
if (param != NULL) {
|
||||||
gcm_param = (CK_AES_GCM_PARAMS *)(void *)param;
|
gcm_param = (CK_AES_GCM_PARAMS *)(void *)param;
|
||||||
|
|
||||||
if (gmac_mode == B_FALSE) {
|
|
||||||
/* GCM mode. */
|
/* GCM mode. */
|
||||||
if ((rv = gcm_validate_args(gcm_param)) != 0) {
|
if ((rv = gcm_validate_args(gcm_param)) != 0) {
|
||||||
return (rv);
|
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;
|
size_t tbits = gcm_param->ulTagBits;
|
||||||
tag_len = CRYPTO_BITS2BYTES(tbits);
|
tag_len = CRYPTO_BITS2BYTES(tbits);
|
||||||
iv_len = gcm_param->ulIvLen;
|
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_tag_len = tag_len;
|
||||||
gcm_ctx->gcm_processed_data_len = 0;
|
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
|
* If this is a GCM context, use the MOVBE and the BSWAP
|
||||||
* variants alternately. GMAC contexts code paths do not
|
* variants alternately.
|
||||||
* use the MOVBE instruction.
|
|
||||||
*/
|
*/
|
||||||
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) {
|
zfs_movbe_available() == B_TRUE) {
|
||||||
(void) atomic_toggle_boolean_nv(
|
(void) atomic_toggle_boolean_nv(
|
||||||
(volatile boolean_t *)&gcm_avx_can_use_movbe);
|
(volatile boolean_t *)&gcm_avx_can_use_movbe);
|
||||||
|
@ -758,18 +717,6 @@ gcm_alloc_ctx(int kmflag)
|
||||||
return (gcm_ctx);
|
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 */
|
/* GCM implementation that contains the fastest methods */
|
||||||
static gcm_impl_ops_t gcm_fastest_impl = {
|
static gcm_impl_ops_t gcm_fastest_impl = {
|
||||||
.name = "fastest"
|
.name = "fastest"
|
||||||
|
|
|
@ -126,20 +126,7 @@ crypto_free_mode_ctx(void *ctx)
|
||||||
{
|
{
|
||||||
common_ctx_t *common_ctx = (common_ctx_t *)ctx;
|
common_ctx_t *common_ctx = (common_ctx_t *)ctx;
|
||||||
|
|
||||||
switch (common_ctx->cc_flags &
|
switch (common_ctx->cc_flags & (CCM_MODE|GCM_MODE)) {
|
||||||
(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;
|
|
||||||
|
|
||||||
case CCM_MODE:
|
case CCM_MODE:
|
||||||
if (((ccm_ctx_t *)ctx)->ccm_pt_buf != NULL)
|
if (((ccm_ctx_t *)ctx)->ccm_pt_buf != NULL)
|
||||||
vmem_free(((ccm_ctx_t *)ctx)->ccm_pt_buf,
|
vmem_free(((ccm_ctx_t *)ctx)->ccm_pt_buf,
|
||||||
|
@ -149,9 +136,12 @@ crypto_free_mode_ctx(void *ctx)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GCM_MODE:
|
case GCM_MODE:
|
||||||
case GMAC_MODE:
|
|
||||||
gcm_clear_ctx((gcm_ctx_t *)ctx);
|
gcm_clear_ctx((gcm_ctx_t *)ctx);
|
||||||
kmem_free(ctx, sizeof (gcm_ctx_t));
|
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
|
#ifdef _AES_IMPL
|
||||||
|
|
||||||
typedef enum aes_mech_type {
|
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_CCM_MECH_INFO_TYPE, /* SUN_CKM_AES_CCM */
|
||||||
AES_GCM_MECH_INFO_TYPE, /* SUN_CKM_AES_GCM */
|
AES_GCM_MECH_INFO_TYPE, /* SUN_CKM_AES_GCM */
|
||||||
AES_GMAC_MECH_INFO_TYPE /* SUN_CKM_AES_GMAC */
|
|
||||||
} aes_mech_type_t;
|
} aes_mech_type_t;
|
||||||
|
|
||||||
#endif /* _AES_IMPL */
|
#endif /* _AES_IMPL */
|
||||||
|
|
|
@ -45,12 +45,8 @@ extern "C" {
|
||||||
extern boolean_t gcm_avx_can_use_movbe;
|
extern boolean_t gcm_avx_can_use_movbe;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ECB_MODE 0x00000002
|
|
||||||
#define CBC_MODE 0x00000004
|
|
||||||
#define CTR_MODE 0x00000008
|
|
||||||
#define CCM_MODE 0x00000010
|
#define CCM_MODE 0x00000010
|
||||||
#define GCM_MODE 0x00000020
|
#define GCM_MODE 0x00000020
|
||||||
#define GMAC_MODE 0x00000040
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cc_keysched: Pointer to key schedule.
|
* 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.
|
* by the caller, or internally, e.g. an init routine.
|
||||||
* If allocated by the latter, then it needs to be freed.
|
* 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 {
|
struct common_ctx {
|
||||||
void *cc_keysched;
|
void *cc_keysched;
|
||||||
|
@ -91,57 +87,6 @@ struct common_ctx {
|
||||||
|
|
||||||
typedef struct common_ctx common_ctx_t;
|
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.
|
* 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_copy_to gcm_common.cc_copy_to
|
||||||
#define gcm_flags gcm_common.cc_flags
|
#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);
|
void gcm_clear_ctx(gcm_ctx_t *ctx);
|
||||||
|
|
||||||
typedef struct aes_ctx {
|
typedef struct aes_ctx {
|
||||||
union {
|
union {
|
||||||
ecb_ctx_t acu_ecb;
|
|
||||||
cbc_ctx_t acu_cbc;
|
|
||||||
ctr_ctx_t acu_ctr;
|
|
||||||
ccm_ctx_t acu_ccm;
|
ccm_ctx_t acu_ccm;
|
||||||
gcm_ctx_t acu_gcm;
|
gcm_ctx_t acu_gcm;
|
||||||
} acu;
|
} acu;
|
||||||
} aes_ctx_t;
|
} aes_ctx_t;
|
||||||
|
|
||||||
#define ac_flags acu.acu_ecb.ecb_common.cc_flags
|
#define ac_flags acu.acu_ccm.ccm_common.cc_flags
|
||||||
#define ac_remainder_len acu.acu_ecb.ecb_common.cc_remainder_len
|
#define ac_remainder_len acu.acu_ccm.ccm_common.cc_remainder_len
|
||||||
#define ac_keysched acu.acu_ecb.ecb_common.cc_keysched
|
#define ac_keysched acu.acu_ccm.ccm_common.cc_keysched
|
||||||
#define ac_keysched_len acu.acu_ecb.ecb_common.cc_keysched_len
|
#define ac_keysched_len acu.acu_ccm.ccm_common.cc_keysched_len
|
||||||
#define ac_iv acu.acu_ecb.ecb_common.cc_iv
|
#define ac_iv acu.acu_ccm.ccm_common.cc_iv
|
||||||
#define ac_lastp acu.acu_ecb.ecb_common.cc_lastp
|
#define ac_lastp acu.acu_ccm.ccm_common.cc_lastp
|
||||||
#define ac_pt_buf acu.acu_ccm.ccm_pt_buf
|
#define ac_pt_buf acu.acu_ccm.ccm_pt_buf
|
||||||
#define ac_mac_len acu.acu_ccm.ccm_mac_len
|
#define ac_mac_len acu.acu_ccm.ccm_mac_len
|
||||||
#define ac_data_len acu.acu_ccm.ccm_data_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_processed_data_len acu.acu_ccm.ccm_processed_data_len
|
||||||
#define ac_tag_len acu.acu_gcm.gcm_tag_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,
|
extern int ccm_mode_encrypt_contiguous_blocks(ccm_ctx_t *, char *, size_t,
|
||||||
crypto_data_t *, size_t,
|
crypto_data_t *, size_t,
|
||||||
int (*encrypt_block)(const void *, const uint8_t *, uint8_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 *),
|
int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
|
||||||
void (*xor_block)(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,
|
extern int ccm_init_ctx(ccm_ctx_t *, char *, int, boolean_t, size_t,
|
||||||
int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
|
int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
|
||||||
void (*xor_block)(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 (*copy_block)(uint8_t *, uint8_t *),
|
||||||
void (*xor_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 *,
|
extern void calculate_ccm_mac(ccm_ctx_t *, uint8_t *,
|
||||||
int (*encrypt_block)(const void *, const uint8_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 *,
|
extern void crypto_get_ptrs(crypto_data_t *, void **, offset_t *,
|
||||||
uint8_t **, size_t *, uint8_t **, size_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 *ccm_alloc_ctx(int);
|
||||||
extern void *gcm_alloc_ctx(int);
|
extern void *gcm_alloc_ctx(int);
|
||||||
extern void *gmac_alloc_ctx(int);
|
|
||||||
extern void crypto_free_mode_ctx(void *);
|
extern void crypto_free_mode_ctx(void *);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -40,18 +40,6 @@
|
||||||
* Mechanism info structure passed to KCF during registration.
|
* Mechanism info structure passed to KCF during registration.
|
||||||
*/
|
*/
|
||||||
static const crypto_mech_info_t aes_mech_info_tab[] = {
|
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 */
|
/* AES_CCM */
|
||||||
{SUN_CKM_AES_CCM, AES_CCM_MECH_INFO_TYPE,
|
{SUN_CKM_AES_CCM, AES_CCM_MECH_INFO_TYPE,
|
||||||
CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
|
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,
|
{SUN_CKM_AES_GCM, AES_GCM_MECH_INFO_TYPE,
|
||||||
CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
|
CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
|
||||||
CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_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 *,
|
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
|
.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 *,
|
static int aes_create_ctx_template(crypto_mechanism_t *, crypto_key_t *,
|
||||||
crypto_spi_ctx_template_t *, size_t *);
|
crypto_spi_ctx_template_t *, size_t *);
|
||||||
static int aes_free_context(crypto_ctx_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 = {
|
static const crypto_ops_t aes_crypto_ops = {
|
||||||
NULL,
|
NULL,
|
||||||
&aes_cipher_ops,
|
&aes_cipher_ops,
|
||||||
&aes_mac_ops,
|
NULL,
|
||||||
&aes_ctx_ops,
|
&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_kcf_provider_handle_t aes_prov_handle = 0;
|
||||||
static crypto_data_t null_crypto_data = { CRYPTO_DATA_RAW };
|
|
||||||
|
|
||||||
int
|
int
|
||||||
aes_mod_init(void)
|
aes_mod_init(void)
|
||||||
|
@ -181,18 +149,6 @@ aes_check_mech_param(crypto_mechanism_t *mechanism, aes_ctx_t **ctx)
|
||||||
int rv = CRYPTO_SUCCESS;
|
int rv = CRYPTO_SUCCESS;
|
||||||
|
|
||||||
switch (mechanism->cm_type) {
|
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:
|
case AES_CCM_MECH_INFO_TYPE:
|
||||||
param_len = sizeof (CK_AES_CCM_PARAMS);
|
param_len = sizeof (CK_AES_CCM_PARAMS);
|
||||||
alloc_fun = ccm_alloc_ctx;
|
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);
|
param_len = sizeof (CK_AES_GCM_PARAMS);
|
||||||
alloc_fun = gcm_alloc_ctx;
|
alloc_fun = gcm_alloc_ctx;
|
||||||
break;
|
break;
|
||||||
case AES_GMAC_MECH_INFO_TYPE:
|
|
||||||
param_len = sizeof (CK_AES_GMAC_PARAMS);
|
|
||||||
alloc_fun = gmac_alloc_ctx;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
rv = CRYPTO_MECHANISM_INVALID;
|
__builtin_unreachable();
|
||||||
return (rv);
|
|
||||||
}
|
}
|
||||||
if (param_required && mechanism->cm_param != NULL &&
|
if (param_required && mechanism->cm_param != NULL &&
|
||||||
mechanism->cm_param_len != param_len) {
|
mechanism->cm_param_len != param_len) {
|
||||||
|
@ -282,22 +233,6 @@ aes_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
|
||||||
return (CRYPTO_SUCCESS);
|
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
|
static int
|
||||||
aes_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
|
aes_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
|
||||||
crypto_data_t *ciphertext)
|
crypto_data_t *ciphertext)
|
||||||
|
@ -310,35 +245,21 @@ aes_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
|
||||||
ASSERT(ctx->cc_provider_private != NULL);
|
ASSERT(ctx->cc_provider_private != NULL);
|
||||||
aes_ctx = ctx->cc_provider_private;
|
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);
|
ASSERT(ciphertext != NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to just return the length needed to store the output.
|
* We need to just return the length needed to store the output.
|
||||||
* We should not destroy the context for the following case.
|
* 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:
|
case CCM_MODE:
|
||||||
length_needed = plaintext->cd_length + aes_ctx->ac_mac_len;
|
length_needed = plaintext->cd_length + aes_ctx->ac_mac_len;
|
||||||
break;
|
break;
|
||||||
case GCM_MODE:
|
case GCM_MODE:
|
||||||
length_needed = plaintext->cd_length + aes_ctx->ac_tag_len;
|
length_needed = plaintext->cd_length + aes_ctx->ac_tag_len;
|
||||||
break;
|
break;
|
||||||
case GMAC_MODE:
|
|
||||||
if (plaintext->cd_length != 0)
|
|
||||||
return (CRYPTO_ARGUMENTS_BAD);
|
|
||||||
|
|
||||||
length_needed = aes_ctx->ac_tag_len;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
length_needed = plaintext->cd_length;
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ciphertext->cd_length < length_needed) {
|
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;
|
||||||
}
|
}
|
||||||
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
|
* gcm_encrypt_final() will compute the MAC and append
|
||||||
* it to existing ciphertext. So, need to adjust the left over
|
* 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);
|
ASSERT(ctx->cc_provider_private != NULL);
|
||||||
aes_ctx = ctx->cc_provider_private;
|
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);
|
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
|
* CCM: plaintext is MAC len smaller than cipher text
|
||||||
* GCM: plaintext is TAG 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:
|
case CCM_MODE:
|
||||||
length_needed = aes_ctx->ac_processed_data_len;
|
length_needed = aes_ctx->ac_processed_data_len;
|
||||||
break;
|
break;
|
||||||
case GCM_MODE:
|
case GCM_MODE:
|
||||||
length_needed = ciphertext->cd_length - aes_ctx->ac_tag_len;
|
length_needed = ciphertext->cd_length - aes_ctx->ac_tag_len;
|
||||||
break;
|
break;
|
||||||
case GMAC_MODE:
|
|
||||||
if (plaintext->cd_length != 0)
|
|
||||||
return (CRYPTO_ARGUMENTS_BAD);
|
|
||||||
|
|
||||||
length_needed = 0;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
length_needed = ciphertext->cd_length;
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plaintext->cd_length < length_needed) {
|
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;
|
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 */
|
/* order of following 2 lines MUST not be reversed */
|
||||||
plaintext->cd_offset = plaintext->cd_length;
|
plaintext->cd_offset = plaintext->cd_length;
|
||||||
plaintext->cd_length = saved_length - 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;
|
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 (ret == CRYPTO_SUCCESS) {
|
||||||
if (plaintext != ciphertext)
|
if (plaintext != ciphertext)
|
||||||
ciphertext->cd_length =
|
ciphertext->cd_length =
|
||||||
|
@ -600,32 +494,13 @@ aes_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
|
||||||
crypto_data_t *plaintext)
|
crypto_data_t *plaintext)
|
||||||
{
|
{
|
||||||
off_t saved_offset;
|
off_t saved_offset;
|
||||||
size_t saved_length, out_len;
|
size_t saved_length;
|
||||||
int ret = CRYPTO_SUCCESS;
|
int ret = CRYPTO_SUCCESS;
|
||||||
aes_ctx_t *aes_ctx;
|
|
||||||
|
|
||||||
ASSERT(ctx->cc_provider_private != NULL);
|
ASSERT(ctx->cc_provider_private != NULL);
|
||||||
aes_ctx = ctx->cc_provider_private;
|
|
||||||
|
|
||||||
ASSERT(plaintext != NULL);
|
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_offset = plaintext->cd_offset;
|
||||||
saved_length = plaintext->cd_length;
|
saved_length = plaintext->cd_length;
|
||||||
|
|
||||||
|
@ -645,19 +520,6 @@ aes_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
|
||||||
ret = CRYPTO_ARGUMENTS_BAD;
|
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 (ret == CRYPTO_SUCCESS) {
|
||||||
if (ciphertext != plaintext)
|
if (ciphertext != plaintext)
|
||||||
plaintext->cd_length =
|
plaintext->cd_length =
|
||||||
|
@ -685,20 +547,13 @@ aes_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data)
|
||||||
return (CRYPTO_ARGUMENTS_BAD);
|
return (CRYPTO_ARGUMENTS_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aes_ctx->ac_flags & CTR_MODE) {
|
if (aes_ctx->ac_flags & CCM_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) {
|
|
||||||
ret = ccm_encrypt_final((ccm_ctx_t *)aes_ctx, data,
|
ret = ccm_encrypt_final((ccm_ctx_t *)aes_ctx, data,
|
||||||
AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
|
AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
|
||||||
if (ret != CRYPTO_SUCCESS) {
|
if (ret != CRYPTO_SUCCESS) {
|
||||||
return (ret);
|
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;
|
size_t saved_offset = data->cd_offset;
|
||||||
|
|
||||||
ret = gcm_encrypt_final((gcm_ctx_t *)aes_ctx, data,
|
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_length = data->cd_offset - saved_offset;
|
||||||
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);
|
(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
|
* This happens if the length of the last ciphertext is
|
||||||
* not a multiple of the AES block length.
|
* not a multiple of the AES block length.
|
||||||
*/
|
*/
|
||||||
if (aes_ctx->ac_remainder_len > 0) {
|
if (aes_ctx->ac_remainder_len > 0)
|
||||||
if ((aes_ctx->ac_flags & CTR_MODE) == 0)
|
|
||||||
return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
|
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) {
|
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) {
|
if (ret != CRYPTO_SUCCESS) {
|
||||||
return (ret);
|
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
|
* This is where all the plaintext is returned, make sure
|
||||||
* the plaintext buffer is big enough
|
* 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);
|
(void) aes_free_context(ctx);
|
||||||
|
|
||||||
return (CRYPTO_SUCCESS);
|
return (CRYPTO_SUCCESS);
|
||||||
|
@ -842,21 +673,6 @@ aes_encrypt_atomic(crypto_mechanism_t *mechanism,
|
||||||
|
|
||||||
ASSERT(ciphertext != NULL);
|
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)
|
if ((ret = aes_check_mech_param(mechanism, NULL)) != CRYPTO_SUCCESS)
|
||||||
return (ret);
|
return (ret);
|
||||||
|
|
||||||
|
@ -869,15 +685,11 @@ aes_encrypt_atomic(crypto_mechanism_t *mechanism,
|
||||||
case AES_CCM_MECH_INFO_TYPE:
|
case AES_CCM_MECH_INFO_TYPE:
|
||||||
length_needed = plaintext->cd_length + aes_ctx.ac_mac_len;
|
length_needed = plaintext->cd_length + aes_ctx.ac_mac_len;
|
||||||
break;
|
break;
|
||||||
case AES_GMAC_MECH_INFO_TYPE:
|
|
||||||
if (plaintext->cd_length != 0)
|
|
||||||
return (CRYPTO_ARGUMENTS_BAD);
|
|
||||||
zfs_fallthrough;
|
|
||||||
case AES_GCM_MECH_INFO_TYPE:
|
case AES_GCM_MECH_INFO_TYPE:
|
||||||
length_needed = plaintext->cd_length + aes_ctx.ac_tag_len;
|
length_needed = plaintext->cd_length + aes_ctx.ac_tag_len;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
length_needed = plaintext->cd_length;
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return size of buffer needed to store output */
|
/* return size of buffer needed to store output */
|
||||||
|
@ -914,21 +726,13 @@ aes_encrypt_atomic(crypto_mechanism_t *mechanism,
|
||||||
if (ret != CRYPTO_SUCCESS)
|
if (ret != CRYPTO_SUCCESS)
|
||||||
goto out;
|
goto out;
|
||||||
ASSERT(aes_ctx.ac_remainder_len == 0);
|
ASSERT(aes_ctx.ac_remainder_len == 0);
|
||||||
} else if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE ||
|
} else if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE) {
|
||||||
mechanism->cm_type == AES_GMAC_MECH_INFO_TYPE) {
|
|
||||||
ret = gcm_encrypt_final((gcm_ctx_t *)&aes_ctx,
|
ret = gcm_encrypt_final((gcm_ctx_t *)&aes_ctx,
|
||||||
ciphertext, AES_BLOCK_LEN, aes_encrypt_block,
|
ciphertext, AES_BLOCK_LEN, aes_encrypt_block,
|
||||||
aes_copy_block, aes_xor_block);
|
aes_copy_block, aes_xor_block);
|
||||||
if (ret != CRYPTO_SUCCESS)
|
if (ret != CRYPTO_SUCCESS)
|
||||||
goto out;
|
goto out;
|
||||||
ASSERT(aes_ctx.ac_remainder_len == 0);
|
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 {
|
} else {
|
||||||
ASSERT(aes_ctx.ac_remainder_len == 0);
|
ASSERT(aes_ctx.ac_remainder_len == 0);
|
||||||
}
|
}
|
||||||
|
@ -947,7 +751,7 @@ out:
|
||||||
memset(aes_ctx.ac_keysched, 0, aes_ctx.ac_keysched_len);
|
memset(aes_ctx.ac_keysched, 0, aes_ctx.ac_keysched_len);
|
||||||
kmem_free(aes_ctx.ac_keysched, 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);
|
gcm_clear_ctx((gcm_ctx_t *)&aes_ctx);
|
||||||
}
|
}
|
||||||
return (ret);
|
return (ret);
|
||||||
|
@ -968,21 +772,6 @@ aes_decrypt_atomic(crypto_mechanism_t *mechanism,
|
||||||
|
|
||||||
ASSERT(plaintext != NULL);
|
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)
|
if ((ret = aes_check_mech_param(mechanism, NULL)) != CRYPTO_SUCCESS)
|
||||||
return (ret);
|
return (ret);
|
||||||
|
|
||||||
|
@ -998,13 +787,8 @@ aes_decrypt_atomic(crypto_mechanism_t *mechanism,
|
||||||
case AES_GCM_MECH_INFO_TYPE:
|
case AES_GCM_MECH_INFO_TYPE:
|
||||||
length_needed = ciphertext->cd_length - aes_ctx.ac_tag_len;
|
length_needed = ciphertext->cd_length - aes_ctx.ac_tag_len;
|
||||||
break;
|
break;
|
||||||
case AES_GMAC_MECH_INFO_TYPE:
|
|
||||||
if (plaintext->cd_length != 0)
|
|
||||||
return (CRYPTO_ARGUMENTS_BAD);
|
|
||||||
length_needed = 0;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
length_needed = ciphertext->cd_length;
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return size of buffer needed to store output */
|
/* return size of buffer needed to store output */
|
||||||
|
@ -1050,8 +834,7 @@ aes_decrypt_atomic(crypto_mechanism_t *mechanism,
|
||||||
} else {
|
} else {
|
||||||
plaintext->cd_length = saved_length;
|
plaintext->cd_length = saved_length;
|
||||||
}
|
}
|
||||||
} else if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE ||
|
} else if (mechanism->cm_type == AES_GCM_MECH_INFO_TYPE) {
|
||||||
mechanism->cm_type == AES_GMAC_MECH_INFO_TYPE) {
|
|
||||||
ret = gcm_decrypt_final((gcm_ctx_t *)&aes_ctx,
|
ret = gcm_decrypt_final((gcm_ctx_t *)&aes_ctx,
|
||||||
plaintext, AES_BLOCK_LEN, aes_encrypt_block,
|
plaintext, AES_BLOCK_LEN, aes_encrypt_block,
|
||||||
aes_xor_block);
|
aes_xor_block);
|
||||||
|
@ -1063,24 +846,8 @@ aes_decrypt_atomic(crypto_mechanism_t *mechanism,
|
||||||
} else {
|
} else {
|
||||||
plaintext->cd_length = saved_length;
|
plaintext->cd_length = saved_length;
|
||||||
}
|
}
|
||||||
} else if (mechanism->cm_type != AES_CTR_MECH_INFO_TYPE) {
|
} else
|
||||||
ASSERT(aes_ctx.ac_remainder_len == 0);
|
__builtin_unreachable();
|
||||||
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 {
|
} else {
|
||||||
plaintext->cd_length = saved_length;
|
plaintext->cd_length = saved_length;
|
||||||
}
|
}
|
||||||
|
@ -1096,7 +863,7 @@ out:
|
||||||
if (aes_ctx.ac_pt_buf != NULL) {
|
if (aes_ctx.ac_pt_buf != NULL) {
|
||||||
vmem_free(aes_ctx.ac_pt_buf, aes_ctx.ac_data_len);
|
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);
|
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;
|
size_t size;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
if (mechanism->cm_type != AES_ECB_MECH_INFO_TYPE &&
|
if (mechanism->cm_type != AES_CCM_MECH_INFO_TYPE &&
|
||||||
mechanism->cm_type != AES_CBC_MECH_INFO_TYPE &&
|
mechanism->cm_type != AES_GCM_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)
|
|
||||||
return (CRYPTO_MECHANISM_INVALID);
|
return (CRYPTO_MECHANISM_INVALID);
|
||||||
|
|
||||||
if ((keysched = aes_alloc_keysched(&size, KM_SLEEP)) == NULL) {
|
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;
|
aes_ctx->ac_keysched = keysched;
|
||||||
|
|
||||||
switch (mechanism->cm_type) {
|
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:
|
case AES_CCM_MECH_INFO_TYPE:
|
||||||
if (mechanism->cm_param == NULL ||
|
if (mechanism->cm_param == NULL ||
|
||||||
mechanism->cm_param_len != sizeof (CK_AES_CCM_PARAMS)) {
|
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_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
|
||||||
aes_xor_block);
|
aes_xor_block);
|
||||||
break;
|
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) {
|
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);
|
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