Changeset View
Changeset View
Standalone View
Standalone View
sys/opencrypto/cryptosoft.c
Show First 20 Lines • Show All 630 Lines • ▼ Show 20 Lines | |||||
out: | out: | ||||
explicit_bzero(blkbuf, sizeof(blkbuf)); | explicit_bzero(blkbuf, sizeof(blkbuf)); | ||||
explicit_bzero(tag, sizeof(tag)); | explicit_bzero(tag, sizeof(tag)); | ||||
return (error); | return (error); | ||||
} | } | ||||
static void | |||||
build_ccm_b0(const char *nonce, u_int nonce_length, u_int aad_length, | |||||
jhb: It is might be worth exposing some variant of these functions publicly as ccr, aesni, and… | |||||
u_int data_length, u_int tag_length, uint8_t *b0) | |||||
{ | |||||
uint8_t *bp; | |||||
uint8_t flags, L; | |||||
KASSERT(nonce_length >= 7 && nonce_length <= 13, | |||||
("nonce_length must be between 7 and 13 bytes")); | |||||
/* | |||||
* Need to determine the L field value. This is the number of | |||||
* bytes needed to specify the length of the message; the length | |||||
* is whatever is left in the 16 bytes after specifying flags and | |||||
* the nonce. | |||||
*/ | |||||
L = 15 - nonce_length; | |||||
flags = ((aad_length > 0) << 6) + | |||||
(((tag_length - 2) / 2) << 3) + | |||||
L - 1; | |||||
/* | |||||
* Now we need to set up the first block, which has flags, nonce, | |||||
* and the message length. | |||||
*/ | |||||
b0[0] = flags; | |||||
memcpy(b0 + 1, nonce, nonce_length); | |||||
bp = b0 + 1 + nonce_length; | |||||
/* Need to copy L' [aka L-1] bytes of data_length */ | |||||
for (uint8_t *dst = b0 + CCM_CBC_BLOCK_LEN - 1; dst >= bp; dst--) { | |||||
*dst = data_length; | |||||
data_length >>= 8; | |||||
} | |||||
} | |||||
/* NB: OCF only supports AAD lengths < 2^32. */ | |||||
static int | static int | ||||
build_ccm_aad_length(u_int aad_length, uint8_t *blk) | |||||
{ | |||||
if (aad_length < ((1 << 16) - (1 << 8))) { | |||||
be16enc(blk, aad_length); | |||||
return (sizeof(uint16_t)); | |||||
} else { | |||||
blk[0] = 0xff; | |||||
blk[1] = 0xfe; | |||||
be32enc(blk + 2, aad_length); | |||||
return (2 + sizeof(uint32_t)); | |||||
} | |||||
} | |||||
static int | |||||
swcr_ccm_cbc_mac(struct swcr_session *ses, struct cryptop *crp) | swcr_ccm_cbc_mac(struct swcr_session *ses, struct cryptop *crp) | ||||
{ | { | ||||
u_char tag[AES_CBC_MAC_HASH_LEN]; | |||||
u_char iv[AES_BLOCK_LEN]; | u_char iv[AES_BLOCK_LEN]; | ||||
u_char blk[CCM_CBC_BLOCK_LEN]; | |||||
u_char tag[AES_CBC_MAC_HASH_LEN]; | |||||
union authctx ctx; | union authctx ctx; | ||||
const struct crypto_session_params *csp; | const struct crypto_session_params *csp; | ||||
struct swcr_auth *swa; | struct swcr_auth *swa; | ||||
const struct auth_hash *axf; | const struct auth_hash *axf; | ||||
int error, ivlen; | int error, ivlen, len; | ||||
csp = crypto_get_params(crp->crp_session); | csp = crypto_get_params(crp->crp_session); | ||||
swa = &ses->swcr_auth; | swa = &ses->swcr_auth; | ||||
axf = swa->sw_axf; | axf = swa->sw_axf; | ||||
bcopy(swa->sw_ictx, &ctx, axf->ctxsize); | bcopy(swa->sw_ictx, &ctx, axf->ctxsize); | ||||
/* Initialize the IV */ | /* Initialize the IV */ | ||||
ivlen = csp->csp_ivlen; | ivlen = csp->csp_ivlen; | ||||
crypto_read_iv(crp, iv); | crypto_read_iv(crp, iv); | ||||
/* | /* Supply MAC with IV */ | ||||
* AES CCM-CBC-MAC needs to know the length of both the auth | axf->Reinit(&ctx, crp->crp_iv, ivlen); | ||||
* data and payload data before doing the auth computation. | |||||
*/ | |||||
ctx.aes_cbc_mac_ctx.authDataLength = crp->crp_payload_length; | |||||
ctx.aes_cbc_mac_ctx.cryptDataLength = 0; | |||||
axf->Reinit(&ctx, iv, ivlen); | /* Supply MAC with b0. */ | ||||
if (crp->crp_aad != NULL) | build_ccm_b0(crp->crp_iv, ivlen, crp->crp_payload_length, 0, | ||||
error = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length); | swa->sw_mlen, blk); | ||||
else | axf->Update(&ctx, blk, CCM_CBC_BLOCK_LEN); | ||||
error = crypto_apply(crp, crp->crp_payload_start, | |||||
crp->crp_payload_length, axf->Update, &ctx); | |||||
if (error) | |||||
return (error); | |||||
len = build_ccm_aad_length(crp->crp_payload_length, blk); | |||||
axf->Update(&ctx, blk, len); | |||||
crypto_apply(crp, crp->crp_payload_start, crp->crp_payload_length, | |||||
axf->Update, &ctx); | |||||
/* Finalize MAC */ | /* Finalize MAC */ | ||||
axf->Final(tag, &ctx); | axf->Final(tag, &ctx); | ||||
error = 0; | |||||
if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { | if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { | ||||
u_char tag2[AES_CBC_MAC_HASH_LEN]; | u_char tag2[AES_CBC_MAC_HASH_LEN]; | ||||
crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, | crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, | ||||
tag2); | tag2); | ||||
if (timingsafe_bcmp(tag, tag2, swa->sw_mlen) != 0) | if (timingsafe_bcmp(tag, tag2, swa->sw_mlen) != 0) | ||||
error = EBADMSG; | error = EBADMSG; | ||||
explicit_bzero(tag2, sizeof(tag)); | explicit_bzero(tag2, sizeof(tag)); | ||||
} else { | } else { | ||||
/* Inject the authentication data */ | /* Inject the authentication data */ | ||||
crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag); | crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag); | ||||
} | } | ||||
explicit_bzero(tag, sizeof(tag)); | explicit_bzero(tag, sizeof(tag)); | ||||
explicit_bzero(blk, sizeof(blk)); | |||||
explicit_bzero(iv, sizeof(iv)); | explicit_bzero(iv, sizeof(iv)); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
swcr_ccm(struct swcr_session *ses, struct cryptop *crp) | swcr_ccm(struct swcr_session *ses, struct cryptop *crp) | ||||
{ | { | ||||
const struct crypto_session_params *csp; | const struct crypto_session_params *csp; | ||||
Show All 28 Lines | swcr_ccm(struct swcr_session *ses, struct cryptop *crp) | ||||
if (crp->crp_payload_length > ccm_max_payload_length(csp)) | if (crp->crp_payload_length > ccm_max_payload_length(csp)) | ||||
return (EMSGSIZE); | return (EMSGSIZE); | ||||
if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) | if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
ivlen = csp->csp_ivlen; | ivlen = csp->csp_ivlen; | ||||
/* | |||||
* AES CCM-CBC-MAC needs to know the length of both the auth | |||||
* data and payload data before doing the auth computation. | |||||
*/ | |||||
ctx.aes_cbc_mac_ctx.authDataLength = crp->crp_aad_length; | |||||
ctx.aes_cbc_mac_ctx.cryptDataLength = crp->crp_payload_length; | |||||
/* Supply MAC with IV */ | /* Supply MAC with IV */ | ||||
axf->Reinit(&ctx, crp->crp_iv, ivlen); | axf->Reinit(&ctx, crp->crp_iv, ivlen); | ||||
/* Supply MAC with b0. */ | |||||
_Static_assert(sizeof(blkbuf) >= CCM_CBC_BLOCK_LEN, | |||||
"blkbuf too small for b0"); | |||||
build_ccm_b0(crp->crp_iv, ivlen, crp->crp_aad_length, | |||||
crp->crp_payload_length, swa->sw_mlen, blk); | |||||
axf->Update(&ctx, blk, CCM_CBC_BLOCK_LEN); | |||||
/* Supply MAC with AAD */ | /* Supply MAC with AAD */ | ||||
if (crp->crp_aad_length != 0) { | |||||
len = build_ccm_aad_length(crp->crp_aad_length, blk); | |||||
axf->Update(&ctx, blk, len); | |||||
if (crp->crp_aad != NULL) | if (crp->crp_aad != NULL) | ||||
error = axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length); | axf->Update(&ctx, crp->crp_aad, | ||||
crp->crp_aad_length); | |||||
else | else | ||||
error = crypto_apply(crp, crp->crp_aad_start, | crypto_apply(crp, crp->crp_aad_start, | ||||
crp->crp_aad_length, axf->Update, &ctx); | crp->crp_aad_length, axf->Update, &ctx); | ||||
if (error) | |||||
return (error); | /* Pad the AAD (including length field) to a full block. */ | ||||
len = (len + crp->crp_aad_length) % CCM_CBC_BLOCK_LEN; | |||||
if (len != 0) { | |||||
len = CCM_CBC_BLOCK_LEN - len; | |||||
memset(blk, 0, CCM_CBC_BLOCK_LEN); | |||||
axf->Update(&ctx, blk, len); | |||||
} | |||||
} | |||||
if (crp->crp_cipher_key != NULL) | if (crp->crp_cipher_key != NULL) | ||||
exf->setkey(swe->sw_kschedule, crp->crp_cipher_key, | exf->setkey(swe->sw_kschedule, crp->crp_cipher_key, | ||||
crypto_get_params(crp->crp_session)->csp_cipher_klen); | crypto_get_params(crp->crp_session)->csp_cipher_klen); | ||||
exf->reinit(swe->sw_kschedule, crp->crp_iv, ivlen); | exf->reinit(swe->sw_kschedule, crp->crp_iv, ivlen); | ||||
/* Do encryption/decryption with MAC */ | /* Do encryption/decryption with MAC */ | ||||
crypto_cursor_init(&cc_in, &crp->crp_buf); | crypto_cursor_init(&cc_in, &crp->crp_buf); | ||||
▲ Show 20 Lines • Show All 938 Lines • Show Last 20 Lines |
It is might be worth exposing some variant of these functions publicly as ccr, aesni, and safexcel all have their own routines to build b0 and the AAD length words (not counting that ccr duplicates these exact functions again in its software fallback). Public versions could perhaps take the crp as an argument rather than all the broken out fields.