cryptosoft: Fully support per-operation keys for auth algorithms.

Only pre-allocate auth contexts when a session-wide key is provided or
for sessions without keys.  For sessions with per-operation keys,
always initialize the on-stack context directly rather than
initializing the session context in swcr_authprepare (now removed) and
then copying that session context into the on-stack context.

This approach permits parallel auth operations without needing a
serializing lock.  In addition, the previous code assumed that auth
sessions always provided an initial key unlike cipher sessions which
assume either an initial key or per-op keys.

While here, fix the Blake2 auth transforms to function like other auth
transforms where Setkey is invoked after Init rather than before.

Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D33316
This commit is contained in:
John Baldwin 2021-12-09 11:52:42 -08:00
parent b54d12841e
commit 6113a08b98
2 changed files with 83 additions and 95 deletions

View File

@ -28,8 +28,6 @@ extern int blake2s_ref(uint8_t *out, const void *in, const void *key,
struct blake2b_xform_ctx {
blake2b_state state;
uint8_t key[BLAKE2B_KEYBYTES];
uint16_t klen;
};
CTASSERT(sizeof(union authctx) >= sizeof(struct blake2b_xform_ctx));
@ -39,24 +37,21 @@ blake2b_xform_init(void *vctx)
struct blake2b_xform_ctx *ctx = vctx;
int rc;
if (ctx->klen > 0)
rc = blake2b_init_key_ref(&ctx->state, BLAKE2B_OUTBYTES,
ctx->key, ctx->klen);
else
rc = blake2b_init_ref(&ctx->state, BLAKE2B_OUTBYTES);
rc = blake2b_init_ref(&ctx->state, BLAKE2B_OUTBYTES);
if (rc != 0)
panic("blake2b_init_key: invalid arguments");
panic("blake2b_init: invalid arguments");
}
static void
blake2b_xform_setkey(void *vctx, const uint8_t *key, u_int klen)
{
struct blake2b_xform_ctx *ctx = vctx;
int rc;
if (klen > sizeof(ctx->key))
panic("invalid klen %u", (unsigned)klen);
memcpy(ctx->key, key, klen);
ctx->klen = klen;
rc = blake2b_init_key_ref(&ctx->state, BLAKE2B_OUTBYTES, key,
klen);
if (rc != 0)
panic("blake2b_init_key: invalid arguments");
}
static int
@ -96,8 +91,6 @@ const struct auth_hash auth_hash_blake2b = {
struct blake2s_xform_ctx {
blake2s_state state;
uint8_t key[BLAKE2S_KEYBYTES];
uint16_t klen;
};
CTASSERT(sizeof(union authctx) >= sizeof(struct blake2s_xform_ctx));
@ -107,24 +100,21 @@ blake2s_xform_init(void *vctx)
struct blake2s_xform_ctx *ctx = vctx;
int rc;
if (ctx->klen > 0)
rc = blake2s_init_key_ref(&ctx->state, BLAKE2S_OUTBYTES,
ctx->key, ctx->klen);
else
rc = blake2s_init_ref(&ctx->state, BLAKE2S_OUTBYTES);
rc = blake2s_init_ref(&ctx->state, BLAKE2S_OUTBYTES);
if (rc != 0)
panic("blake2s_init_key: invalid arguments");
panic("blake2s_init: invalid arguments");
}
static void
blake2s_xform_setkey(void *vctx, const uint8_t *key, u_int klen)
{
struct blake2s_xform_ctx *ctx = vctx;
int rc;
if (klen > sizeof(ctx->key))
panic("invalid klen %u", (unsigned)klen);
memcpy(ctx->key, key, klen);
ctx->klen = klen;
rc = blake2s_init_key_ref(&ctx->state, BLAKE2S_OUTBYTES, key,
klen);
if (rc != 0)
panic("blake2s_init_key: invalid arguments");
}
static int

View File

@ -65,6 +65,7 @@ struct swcr_auth {
void *sw_octx;
const struct auth_hash *sw_axf;
uint16_t sw_mlen;
bool sw_hmac;
};
struct swcr_encdec {
@ -283,33 +284,6 @@ swcr_encdec(struct swcr_session *ses, struct cryptop *crp)
return (0);
}
static void
swcr_authprepare(const struct auth_hash *axf, struct swcr_auth *sw,
const uint8_t *key, int klen)
{
switch (axf->type) {
case CRYPTO_SHA1_HMAC:
case CRYPTO_SHA2_224_HMAC:
case CRYPTO_SHA2_256_HMAC:
case CRYPTO_SHA2_384_HMAC:
case CRYPTO_SHA2_512_HMAC:
case CRYPTO_NULL_HMAC:
case CRYPTO_RIPEMD160_HMAC:
hmac_init_ipad(axf, key, klen, sw->sw_ictx);
hmac_init_opad(axf, key, klen, sw->sw_octx);
break;
case CRYPTO_POLY1305:
case CRYPTO_BLAKE2B:
case CRYPTO_BLAKE2S:
axf->Setkey(sw->sw_ictx, key, klen);
axf->Init(sw->sw_ictx);
break;
default:
panic("%s: algorithm %d doesn't use keys", __func__, axf->type);
}
}
/*
* Compute or verify hash.
*/
@ -318,7 +292,7 @@ swcr_authcompute(struct swcr_session *ses, struct cryptop *crp)
{
u_char aalg[HASH_MAX_LEN];
const struct crypto_session_params *csp;
struct swcr_auth *sw;
const struct swcr_auth *sw;
const struct auth_hash *axf;
union authctx ctx;
int err;
@ -329,11 +303,16 @@ swcr_authcompute(struct swcr_session *ses, struct cryptop *crp)
csp = crypto_get_params(crp->crp_session);
if (crp->crp_auth_key != NULL) {
swcr_authprepare(axf, sw, crp->crp_auth_key,
csp->csp_auth_klen);
}
bcopy(sw->sw_ictx, &ctx, axf->ctxsize);
if (sw->sw_hmac) {
hmac_init_ipad(axf, crp->crp_auth_key,
csp->csp_auth_klen, &ctx);
} else {
axf->Init(&ctx);
axf->Setkey(&ctx, crp->crp_auth_key,
csp->csp_auth_klen);
}
} else
memcpy(&ctx, sw->sw_ictx, axf->ctxsize);
if (crp->crp_aad != NULL)
err = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length);
@ -358,8 +337,12 @@ swcr_authcompute(struct swcr_session *ses, struct cryptop *crp)
axf->Update(&ctx, crp->crp_esn, 4);
axf->Final(aalg, &ctx);
if (sw->sw_octx != NULL) {
bcopy(sw->sw_octx, &ctx, axf->ctxsize);
if (sw->sw_hmac) {
if (crp->crp_auth_key != NULL)
hmac_init_opad(axf, crp->crp_auth_key,
csp->csp_auth_klen, &ctx);
else
memcpy(&ctx, sw->sw_octx, axf->ctxsize);
axf->Update(&ctx, aalg, axf->hashsize);
axf->Final(aalg, &ctx);
}
@ -394,7 +377,7 @@ swcr_gmac(struct swcr_session *ses, struct cryptop *crp)
struct crypto_buffer_cursor cc;
const u_char *inblk;
union authctx ctx;
struct swcr_auth *swa;
const struct swcr_auth *swa;
const struct auth_hash *axf;
uint32_t *blkp;
size_t len;
@ -402,12 +385,17 @@ swcr_gmac(struct swcr_session *ses, struct cryptop *crp)
swa = &ses->swcr_auth;
axf = swa->sw_axf;
bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
blksz = GMAC_BLOCK_LEN;
KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch",
__func__));
if (crp->crp_auth_key != NULL) {
axf->Init(&ctx);
axf->Setkey(&ctx, crp->crp_auth_key,
crypto_get_params(crp->crp_session)->csp_auth_klen);
} else
memcpy(&ctx, swa->sw_ictx, axf->ctxsize);
/* Initialize the IV */
ivlen = AES_GCM_IV_LEN;
crypto_read_iv(crp, iv);
@ -694,7 +682,7 @@ swcr_ccm_cbc_mac(struct swcr_session *ses, struct cryptop *crp)
u_char tag[AES_CBC_MAC_HASH_LEN];
union authctx ctx;
const struct crypto_session_params *csp;
struct swcr_auth *swa;
const struct swcr_auth *swa;
const struct auth_hash *axf;
int error, ivlen, len;
@ -702,7 +690,11 @@ swcr_ccm_cbc_mac(struct swcr_session *ses, struct cryptop *crp)
swa = &ses->swcr_auth;
axf = swa->sw_axf;
bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
if (crp->crp_auth_key != NULL) {
axf->Init(&ctx);
axf->Setkey(&ctx, crp->crp_auth_key, csp->csp_auth_klen);
} else
memcpy(&ctx, swa->sw_ictx, axf->ctxsize);
/* Initialize the IV */
ivlen = csp->csp_ivlen;
@ -1218,9 +1210,12 @@ swcr_setup_auth(struct swcr_session *ses,
swa->sw_mlen = axf->hashsize;
else
swa->sw_mlen = csp->csp_auth_mlen;
swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT);
if (swa->sw_ictx == NULL)
return (ENOBUFS);
if (csp->csp_auth_klen == 0 || csp->csp_auth_key != NULL) {
swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
M_NOWAIT);
if (swa->sw_ictx == NULL)
return (ENOBUFS);
}
switch (csp->csp_auth_alg) {
case CRYPTO_SHA1_HMAC:
@ -1230,18 +1225,17 @@ swcr_setup_auth(struct swcr_session *ses,
case CRYPTO_SHA2_512_HMAC:
case CRYPTO_NULL_HMAC:
case CRYPTO_RIPEMD160_HMAC:
swa->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
M_NOWAIT);
if (swa->sw_octx == NULL)
return (ENOBUFS);
swa->sw_hmac = true;
if (csp->csp_auth_key != NULL) {
swcr_authprepare(axf, swa, csp->csp_auth_key,
csp->csp_auth_klen);
swa->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
M_NOWAIT);
if (swa->sw_octx == NULL)
return (ENOBUFS);
hmac_init_ipad(axf, csp->csp_auth_key,
csp->csp_auth_klen, swa->sw_ictx);
hmac_init_opad(axf, csp->csp_auth_key,
csp->csp_auth_klen, swa->sw_octx);
}
if (csp->csp_mode == CSP_MODE_DIGEST)
ses->swcr_process = swcr_authcompute;
break;
case CRYPTO_SHA1:
case CRYPTO_SHA2_224:
@ -1249,37 +1243,41 @@ swcr_setup_auth(struct swcr_session *ses,
case CRYPTO_SHA2_384:
case CRYPTO_SHA2_512:
axf->Init(swa->sw_ictx);
if (csp->csp_mode == CSP_MODE_DIGEST)
ses->swcr_process = swcr_authcompute;
break;
case CRYPTO_AES_NIST_GMAC:
axf->Init(swa->sw_ictx);
axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
csp->csp_auth_klen);
if (csp->csp_mode == CSP_MODE_DIGEST)
ses->swcr_process = swcr_gmac;
break;
case CRYPTO_AES_CCM_CBC_MAC:
case CRYPTO_POLY1305:
if (csp->csp_auth_key != NULL) {
axf->Init(swa->sw_ictx);
axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
csp->csp_auth_klen);
}
break;
case CRYPTO_BLAKE2B:
case CRYPTO_BLAKE2S:
/*
* Blake2b and Blake2s support an optional key but do
* not require one.
*/
if (csp->csp_auth_klen == 0 || csp->csp_auth_key != NULL)
if (csp->csp_auth_klen == 0)
axf->Init(swa->sw_ictx);
else if (csp->csp_auth_key != NULL)
axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
csp->csp_auth_klen);
axf->Init(swa->sw_ictx);
if (csp->csp_mode == CSP_MODE_DIGEST)
ses->swcr_process = swcr_authcompute;
break;
case CRYPTO_AES_CCM_CBC_MAC:
axf->Init(swa->sw_ictx);
axf->Setkey(swa->sw_ictx, csp->csp_auth_key,
csp->csp_auth_klen);
if (csp->csp_mode == CSP_MODE_DIGEST)
}
if (csp->csp_mode == CSP_MODE_DIGEST) {
switch (csp->csp_auth_alg) {
case CRYPTO_AES_NIST_GMAC:
ses->swcr_process = swcr_gmac;
break;
case CRYPTO_AES_CCM_CBC_MAC:
ses->swcr_process = swcr_ccm_cbc_mac;
break;
break;
default:
ses->swcr_process = swcr_authcompute;
}
}
return (0);