Changeset View
Standalone View
sys/opencrypto/cryptosoft.c
Show First 20 Lines • Show All 405 Lines • ▼ Show 20 Lines | struct { | ||||||||
uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))]; | uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))]; | ||||||||
u_char tag[GMAC_DIGEST_LEN]; | u_char tag[GMAC_DIGEST_LEN]; | ||||||||
u_char tag2[GMAC_DIGEST_LEN]; | u_char tag2[GMAC_DIGEST_LEN]; | ||||||||
} s; | } s; | ||||||||
u_char *blk = (u_char *)s.blkbuf; | u_char *blk = (u_char *)s.blkbuf; | ||||||||
struct crypto_buffer_cursor cc_in, cc_out; | struct crypto_buffer_cursor cc_in, cc_out; | ||||||||
const u_char *inblk; | const u_char *inblk; | ||||||||
u_char *outblk; | u_char *outblk; | ||||||||
size_t inlen, outlen, todo; | |||||||||
const struct swcr_auth *swa; | const struct swcr_auth *swa; | ||||||||
const struct swcr_encdec *swe; | const struct swcr_encdec *swe; | ||||||||
const struct enc_xform *exf; | const struct enc_xform *exf; | ||||||||
void *ctx; | void *ctx; | ||||||||
uint32_t *blkp; | uint32_t *blkp; | ||||||||
size_t len; | |||||||||
int blksz, error, ivlen, r, resid; | int blksz, error, ivlen, r, resid; | ||||||||
swa = &ses->swcr_auth; | swa = &ses->swcr_auth; | ||||||||
swe = &ses->swcr_encdec; | swe = &ses->swcr_encdec; | ||||||||
exf = swe->sw_exf; | exf = swe->sw_exf; | ||||||||
blksz = GMAC_BLOCK_LEN; | blksz = GMAC_BLOCK_LEN; | ||||||||
KASSERT(blksz == exf->native_blocksize, | KASSERT(blksz == exf->native_blocksize, | ||||||||
("%s: blocksize mismatch", __func__)); | ("%s: blocksize mismatch", __func__)); | ||||||||
if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) | if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) | ||||||||
return (EINVAL); | return (EINVAL); | ||||||||
ivlen = AES_GCM_IV_LEN; | ivlen = AES_GCM_IV_LEN; | ||||||||
ctx = __builtin_alloca(exf->ctxsize); | ctx = __builtin_alloca(exf->ctxsize); | ||||||||
if (crp->crp_cipher_key != NULL) | if (crp->crp_cipher_key != NULL) | ||||||||
exf->setkey(ctx, crp->crp_cipher_key, | exf->setkey(ctx, crp->crp_cipher_key, | ||||||||
crypto_get_params(crp->crp_session)->csp_cipher_klen); | crypto_get_params(crp->crp_session)->csp_cipher_klen); | ||||||||
else | else | ||||||||
memcpy(ctx, swe->sw_ctx, exf->ctxsize); | memcpy(ctx, swe->sw_ctx, exf->ctxsize); | ||||||||
exf->reinit(ctx, crp->crp_iv, ivlen); | exf->reinit(ctx, crp->crp_iv, ivlen); | ||||||||
/* Supply MAC with AAD */ | /* Supply MAC with AAD */ | ||||||||
if (crp->crp_aad != NULL) { | if (crp->crp_aad != NULL) { | ||||||||
len = rounddown(crp->crp_aad_length, blksz); | inlen = rounddown2(crp->crp_aad_length, blksz); | ||||||||
if (len != 0) | if (inlen != 0) | ||||||||
exf->update(ctx, crp->crp_aad, len); | exf->update(ctx, crp->crp_aad, inlen); | ||||||||
if (crp->crp_aad_length != len) { | if (crp->crp_aad_length != inlen) { | ||||||||
markjUnsubmitted Done Inline Actions
markj: | |||||||||
memset(blk, 0, blksz); | memset(blk, 0, blksz); | ||||||||
memcpy(blk, (char *)crp->crp_aad + len, | memcpy(blk, (char *)crp->crp_aad + inlen, | ||||||||
crp->crp_aad_length - len); | crp->crp_aad_length - inlen); | ||||||||
exf->update(ctx, blk, blksz); | exf->update(ctx, blk, blksz); | ||||||||
} | } | ||||||||
} else { | } else { | ||||||||
crypto_cursor_init(&cc_in, &crp->crp_buf); | crypto_cursor_init(&cc_in, &crp->crp_buf); | ||||||||
crypto_cursor_advance(&cc_in, crp->crp_aad_start); | crypto_cursor_advance(&cc_in, crp->crp_aad_start); | ||||||||
for (resid = crp->crp_aad_length; resid >= blksz; | for (resid = crp->crp_aad_length; resid >= blksz; | ||||||||
resid -= len) { | resid -= inlen) { | ||||||||
inblk = crypto_cursor_segment(&cc_in, &len); | inblk = crypto_cursor_segment(&cc_in, &inlen); | ||||||||
if (len >= blksz) { | if (inlen >= blksz) { | ||||||||
len = rounddown(MIN(len, resid), blksz); | inlen = rounddown2(MIN(inlen, resid), blksz); | ||||||||
Done Inline Actions
markj: | |||||||||
crypto_cursor_advance(&cc_in, len); | crypto_cursor_advance(&cc_in, inlen); | ||||||||
} else { | } else { | ||||||||
len = blksz; | inlen = blksz; | ||||||||
crypto_cursor_copydata(&cc_in, len, blk); | crypto_cursor_copydata(&cc_in, inlen, blk); | ||||||||
inblk = blk; | inblk = blk; | ||||||||
} | } | ||||||||
exf->update(ctx, inblk, len); | exf->update(ctx, inblk, inlen); | ||||||||
} | } | ||||||||
if (resid > 0) { | if (resid > 0) { | ||||||||
memset(blk, 0, blksz); | memset(blk, 0, blksz); | ||||||||
crypto_cursor_copydata(&cc_in, resid, blk); | crypto_cursor_copydata(&cc_in, resid, blk); | ||||||||
exf->update(ctx, blk, blksz); | exf->update(ctx, blk, blksz); | ||||||||
} | } | ||||||||
} | } | ||||||||
/* Do encryption with MAC */ | /* Do encryption with MAC */ | ||||||||
crypto_cursor_init(&cc_in, &crp->crp_buf); | crypto_cursor_init(&cc_in, &crp->crp_buf); | ||||||||
crypto_cursor_advance(&cc_in, crp->crp_payload_start); | crypto_cursor_advance(&cc_in, crp->crp_payload_start); | ||||||||
inblk = crypto_cursor_segment(&cc_in, &inlen); | |||||||||
if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { | if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { | ||||||||
crypto_cursor_init(&cc_out, &crp->crp_obuf); | crypto_cursor_init(&cc_out, &crp->crp_obuf); | ||||||||
crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); | crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); | ||||||||
} else | } else | ||||||||
cc_out = cc_in; | cc_out = cc_in; | ||||||||
for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) { | outblk = crypto_cursor_segment(&cc_out, &outlen); | ||||||||
inblk = crypto_cursor_segment(&cc_in, &len); | |||||||||
if (len < blksz) { | for (resid = crp->crp_payload_length; resid >= blksz; resid -= todo) { | ||||||||
if (inlen < blksz) { | |||||||||
Not Done Inline ActionsCouldn't this be a for-loop as well? for (resid = crp->crp_payload_length; resid >= blksz; resid -= todo) markj: Couldn't this be a for-loop as well? `for (resid = crp->crp_payload_length; resid >= blksz… | |||||||||
Done Inline ActionsI did this more to match swcr_encdec(), but I could make it a for loop. I think I want all of them to be the same though, so I might go back and adjust swcr_encdec() then. jhb: I did this more to match swcr_encdec(), but I could make it a for loop. I think I want all of… | |||||||||
crypto_cursor_copydata(&cc_in, blksz, blk); | crypto_cursor_copydata(&cc_in, blksz, blk); | ||||||||
inblk = blk; | inblk = blk; | ||||||||
} else { | inlen = blksz; | ||||||||
crypto_cursor_advance(&cc_in, blksz); | |||||||||
} | } | ||||||||
if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { | if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { | ||||||||
outblk = crypto_cursor_segment(&cc_out, &len); | if (outlen < blksz) { | ||||||||
if (len < blksz) | |||||||||
outblk = blk; | outblk = blk; | ||||||||
exf->encrypt(ctx, inblk, outblk); | outlen = blksz; | ||||||||
exf->update(ctx, outblk, blksz); | } | ||||||||
if (outblk == blk) | |||||||||
todo = rounddown2(MIN(resid, MIN(inlen, outlen)), | |||||||||
blksz); | |||||||||
exf->encrypt_multi(ctx, inblk, outblk, todo); | |||||||||
exf->update(ctx, outblk, todo); | |||||||||
if (outblk == blk) { | |||||||||
crypto_cursor_copyback(&cc_out, blksz, blk); | crypto_cursor_copyback(&cc_out, blksz, blk); | ||||||||
else | outblk = crypto_cursor_segment(&cc_out, &outlen); | ||||||||
crypto_cursor_advance(&cc_out, blksz); | |||||||||
} else { | } else { | ||||||||
exf->update(ctx, inblk, blksz); | crypto_cursor_advance(&cc_out, todo); | ||||||||
outlen -= todo; | |||||||||
outblk += todo; | |||||||||
if (outlen == 0) | |||||||||
outblk = crypto_cursor_segment(&cc_out, | |||||||||
&outlen); | |||||||||
} | } | ||||||||
} else { | |||||||||
todo = rounddown2(MIN(resid, inlen), blksz); | |||||||||
exf->update(ctx, inblk, todo); | |||||||||
} | } | ||||||||
if (inblk == blk) { | |||||||||
inblk = crypto_cursor_segment(&cc_in, &inlen); | |||||||||
} else { | |||||||||
crypto_cursor_advance(&cc_in, todo); | |||||||||
inlen -= todo; | |||||||||
inblk += todo; | |||||||||
if (inlen == 0) | |||||||||
inblk = crypto_cursor_segment(&cc_in, &inlen); | |||||||||
} | |||||||||
} | |||||||||
if (resid > 0) { | if (resid > 0) { | ||||||||
crypto_cursor_copydata(&cc_in, resid, blk); | crypto_cursor_copydata(&cc_in, resid, blk); | ||||||||
if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { | if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { | ||||||||
exf->encrypt_last(ctx, blk, blk, resid); | exf->encrypt_last(ctx, blk, blk, resid); | ||||||||
Not Done Inline ActionsSuppose todo == inlen, so the current input segment is a multiple of the block size. Then, on the next iteration we'll bounce the first block of the next segment through blk, even though that's not necessarily required. I don't think there's a correctness problem there, just seems suboptimal. markj: Suppose `todo == inlen`, so the current input segment is a multiple of the block size. Then, on… | |||||||||
Done Inline ActionsI think in the chacha20_poly1305 case I noticed this and fixed it. Part of the problem is that the GCM update routine wants blocks except for the last update. I think though I could handle this case by just checking for 'inlen == todo' here. jhb: I think in the chacha20_poly1305 case I noticed this and fixed it. Part of the problem is that… | |||||||||
Done Inline ActionsActually, this suboptimal behavior is present even in swcr_encdec(), so I will have to go back and fix them all. jhb: Actually, this suboptimal behavior is present even in swcr_encdec(), so I will have to go back… | |||||||||
crypto_cursor_copyback(&cc_out, resid, blk); | crypto_cursor_copyback(&cc_out, resid, blk); | ||||||||
} | } | ||||||||
exf->update(ctx, blk, resid); | exf->update(ctx, blk, resid); | ||||||||
} | } | ||||||||
/* length block */ | /* length block */ | ||||||||
memset(blk, 0, blksz); | memset(blk, 0, blksz); | ||||||||
blkp = (uint32_t *)blk + 1; | blkp = (uint32_t *)blk + 1; | ||||||||
Show All 14 Lines | if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { | ||||||||
if (r != 0) { | if (r != 0) { | ||||||||
error = EBADMSG; | error = EBADMSG; | ||||||||
goto out; | goto out; | ||||||||
} | } | ||||||||
/* tag matches, decrypt data */ | /* tag matches, decrypt data */ | ||||||||
crypto_cursor_init(&cc_in, &crp->crp_buf); | crypto_cursor_init(&cc_in, &crp->crp_buf); | ||||||||
crypto_cursor_advance(&cc_in, crp->crp_payload_start); | crypto_cursor_advance(&cc_in, crp->crp_payload_start); | ||||||||
inblk = crypto_cursor_segment(&cc_in, &inlen); | |||||||||
for (resid = crp->crp_payload_length; resid > blksz; | for (resid = crp->crp_payload_length; resid > blksz; | ||||||||
resid -= blksz) { | resid -= todo) { | ||||||||
inblk = crypto_cursor_segment(&cc_in, &len); | if (inlen < blksz) { | ||||||||
if (len < blksz) { | |||||||||
crypto_cursor_copydata(&cc_in, blksz, blk); | crypto_cursor_copydata(&cc_in, blksz, blk); | ||||||||
inblk = blk; | inblk = blk; | ||||||||
Not Done Inline ActionsAgain, seems like this should be a for-loop. markj: Again, seems like this should be a for-loop. | |||||||||
} else | inlen = blksz; | ||||||||
crypto_cursor_advance(&cc_in, blksz); | } | ||||||||
outblk = crypto_cursor_segment(&cc_out, &len); | if (outlen < blksz) { | ||||||||
if (len < blksz) | |||||||||
outblk = blk; | outblk = blk; | ||||||||
exf->decrypt(ctx, inblk, outblk); | outlen = blksz; | ||||||||
if (outblk == blk) | } | ||||||||
todo = rounddown2(MIN(resid, MIN(inlen, outlen)), | |||||||||
blksz); | |||||||||
exf->decrypt_multi(ctx, inblk, outblk, todo); | |||||||||
if (inblk == blk) { | |||||||||
inblk = crypto_cursor_segment(&cc_in, &inlen); | |||||||||
} else { | |||||||||
crypto_cursor_advance(&cc_in, todo); | |||||||||
inlen -= todo; | |||||||||
inblk += todo; | |||||||||
if (inlen == 0) | |||||||||
inblk = crypto_cursor_segment(&cc_in, | |||||||||
&inlen); | |||||||||
} | |||||||||
if (outblk == blk) { | |||||||||
crypto_cursor_copyback(&cc_out, blksz, blk); | crypto_cursor_copyback(&cc_out, blksz, blk); | ||||||||
else | outblk = crypto_cursor_segment(&cc_out, | ||||||||
crypto_cursor_advance(&cc_out, blksz); | &outlen); | ||||||||
} else { | |||||||||
crypto_cursor_advance(&cc_out, todo); | |||||||||
outlen -= todo; | |||||||||
outblk += todo; | |||||||||
Not Done Inline ActionsSame comment about not reloading the segment if outlen == 0 after subtracting todo. markj: Same comment about not reloading the segment if `outlen == 0` after subtracting `todo`. | |||||||||
if (outlen == 0) | |||||||||
outblk = crypto_cursor_segment(&cc_out, | |||||||||
&outlen); | |||||||||
} | |||||||||
} | } | ||||||||
if (resid > 0) { | if (resid > 0) { | ||||||||
crypto_cursor_copydata(&cc_in, resid, blk); | crypto_cursor_copydata(&cc_in, resid, blk); | ||||||||
exf->decrypt_last(ctx, blk, blk, resid); | exf->decrypt_last(ctx, blk, blk, resid); | ||||||||
crypto_cursor_copyback(&cc_out, resid, blk); | crypto_cursor_copyback(&cc_out, resid, blk); | ||||||||
} | } | ||||||||
} else { | } else { | ||||||||
/* Inject the authentication data */ | /* Inject the authentication data */ | ||||||||
▲ Show 20 Lines • Show All 1,044 Lines • Show Last 20 Lines |