Changeset View
Changeset View
Standalone View
Standalone View
sys/opencrypto/cryptosoft.c
Show First 20 Lines • Show All 460 Lines • ▼ Show 20 Lines | |||||
swcr_gcm(struct swcr_session *ses, struct cryptop *crp) | swcr_gcm(struct swcr_session *ses, struct cryptop *crp) | ||||
{ | { | ||||
uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))]; | uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))]; | ||||
u_char *blk = (u_char *)blkbuf; | u_char *blk = (u_char *)blkbuf; | ||||
u_char tag[GMAC_DIGEST_LEN]; | u_char tag[GMAC_DIGEST_LEN]; | ||||
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; | ||||
union authctx ctx; | |||||
struct swcr_auth *swa; | struct swcr_auth *swa; | ||||
struct swcr_encdec *swe; | struct swcr_encdec *swe; | ||||
const struct auth_hash *axf; | |||||
const struct enc_xform *exf; | const struct enc_xform *exf; | ||||
uint32_t *blkp; | uint32_t *blkp; | ||||
size_t len; | size_t len; | ||||
int blksz, error, ivlen, r, resid; | int blksz, error, ivlen, r, resid; | ||||
swa = &ses->swcr_auth; | 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__)); | |||||
swe = &ses->swcr_encdec; | swe = &ses->swcr_encdec; | ||||
exf = swe->sw_exf; | exf = swe->sw_exf; | ||||
KASSERT(axf->blocksize == exf->native_blocksize, | blksz = GMAC_BLOCK_LEN; | ||||
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; | ||||
/* Supply MAC with IV */ | /* Supply cipher with nonce. */ | ||||
axf->Reinit(&ctx, crp->crp_iv, ivlen); | if (crp->crp_cipher_key != NULL) | ||||
exf->setkey(swe->sw_kschedule, crp->crp_cipher_key, | |||||
crypto_get_params(crp->crp_session)->csp_cipher_klen); | |||||
exf->reinit(swe->sw_kschedule, 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); | len = rounddown(crp->crp_aad_length, blksz); | ||||
if (len != 0) | if (len != 0) | ||||
axf->Update(&ctx, crp->crp_aad, len); | exf->update(swe->sw_kschedule, crp->crp_aad, len); | ||||
if (crp->crp_aad_length != len) { | if (crp->crp_aad_length != len) { | ||||
memset(blk, 0, blksz); | memset(blk, 0, blksz); | ||||
memcpy(blk, (char *)crp->crp_aad + len, | memcpy(blk, (char *)crp->crp_aad + len, | ||||
crp->crp_aad_length - len); | crp->crp_aad_length - len); | ||||
axf->Update(&ctx, blk, blksz); | exf->update(swe->sw_kschedule, 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 -= len) { | ||||
inblk = crypto_cursor_segment(&cc_in, &len); | inblk = crypto_cursor_segment(&cc_in, &len); | ||||
if (len >= blksz) { | if (len >= blksz) { | ||||
len = rounddown(MIN(len, resid), blksz); | len = rounddown(MIN(len, resid), blksz); | ||||
crypto_cursor_advance(&cc_in, len); | crypto_cursor_advance(&cc_in, len); | ||||
} else { | } else { | ||||
len = blksz; | len = blksz; | ||||
crypto_cursor_copydata(&cc_in, len, blk); | crypto_cursor_copydata(&cc_in, len, blk); | ||||
inblk = blk; | inblk = blk; | ||||
} | } | ||||
axf->Update(&ctx, inblk, len); | exf->update(swe->sw_kschedule, inblk, len); | ||||
} | } | ||||
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); | ||||
axf->Update(&ctx, blk, blksz); | exf->update(swe->sw_kschedule, blk, blksz); | ||||
} | } | ||||
} | } | ||||
if (crp->crp_cipher_key != NULL) | |||||
exf->setkey(swe->sw_kschedule, crp->crp_cipher_key, | |||||
crypto_get_params(crp->crp_session)->csp_cipher_klen); | |||||
exf->reinit(swe->sw_kschedule, crp->crp_iv, ivlen); | |||||
/* 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); | ||||
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) { | for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) { | ||||
inblk = crypto_cursor_segment(&cc_in, &len); | inblk = crypto_cursor_segment(&cc_in, &len); | ||||
if (len < blksz) { | if (len < blksz) { | ||||
crypto_cursor_copydata(&cc_in, blksz, blk); | crypto_cursor_copydata(&cc_in, blksz, blk); | ||||
inblk = blk; | inblk = blk; | ||||
} else { | } else { | ||||
crypto_cursor_advance(&cc_in, 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); | outblk = crypto_cursor_segment(&cc_out, &len); | ||||
if (len < blksz) | if (len < blksz) | ||||
outblk = blk; | outblk = blk; | ||||
exf->encrypt(swe->sw_kschedule, inblk, outblk); | exf->encrypt(swe->sw_kschedule, inblk, outblk); | ||||
axf->Update(&ctx, outblk, blksz); | exf->update(swe->sw_kschedule, outblk, blksz); | ||||
if (outblk == blk) | if (outblk == blk) | ||||
crypto_cursor_copyback(&cc_out, blksz, blk); | crypto_cursor_copyback(&cc_out, blksz, blk); | ||||
else | else | ||||
crypto_cursor_advance(&cc_out, blksz); | crypto_cursor_advance(&cc_out, blksz); | ||||
} else { | } else { | ||||
axf->Update(&ctx, inblk, blksz); | exf->update(swe->sw_kschedule, inblk, blksz); | ||||
} | } | ||||
} | } | ||||
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(swe->sw_kschedule, blk, blk, resid); | exf->encrypt_last(swe->sw_kschedule, blk, blk, resid); | ||||
crypto_cursor_copyback(&cc_out, resid, blk); | crypto_cursor_copyback(&cc_out, resid, blk); | ||||
} | } | ||||
axf->Update(&ctx, blk, resid); | exf->update(swe->sw_kschedule, blk, resid); | ||||
} | } | ||||
/* length block */ | /* length block */ | ||||
memset(blk, 0, blksz); | memset(blk, 0, blksz); | ||||
blkp = (uint32_t *)blk + 1; | blkp = (uint32_t *)blk + 1; | ||||
*blkp = htobe32(crp->crp_aad_length * 8); | *blkp = htobe32(crp->crp_aad_length * 8); | ||||
blkp = (uint32_t *)blk + 3; | blkp = (uint32_t *)blk + 3; | ||||
*blkp = htobe32(crp->crp_payload_length * 8); | *blkp = htobe32(crp->crp_payload_length * 8); | ||||
axf->Update(&ctx, blk, blksz); | exf->update(swe->sw_kschedule, blk, blksz); | ||||
/* Finalize MAC */ | /* Finalize MAC */ | ||||
axf->Final(tag, &ctx); | exf->final(tag, swe->sw_kschedule); | ||||
/* Validate tag */ | /* Validate tag */ | ||||
error = 0; | error = 0; | ||||
if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { | if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { | ||||
u_char tag2[GMAC_DIGEST_LEN]; | u_char tag2[GMAC_DIGEST_LEN]; | ||||
crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2); | crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2); | ||||
▲ Show 20 Lines • Show All 156 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
const struct crypto_session_params *csp; | const struct crypto_session_params *csp; | ||||
uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))]; | uint32_t blkbuf[howmany(AES_BLOCK_LEN, sizeof(uint32_t))]; | ||||
u_char *blk = (u_char *)blkbuf; | u_char *blk = (u_char *)blkbuf; | ||||
u_char tag[AES_CBC_MAC_HASH_LEN]; | u_char tag[AES_CBC_MAC_HASH_LEN]; | ||||
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; | ||||
union authctx ctx; | |||||
struct swcr_auth *swa; | struct swcr_auth *swa; | ||||
struct swcr_encdec *swe; | struct swcr_encdec *swe; | ||||
const struct auth_hash *axf; | |||||
const struct enc_xform *exf; | const struct enc_xform *exf; | ||||
size_t len; | size_t len; | ||||
int blksz, error, ivlen, r, resid; | int blksz, error, ivlen, r, resid; | ||||
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; | |||||
bcopy(swa->sw_ictx, &ctx, axf->ctxsize); | |||||
blksz = AES_BLOCK_LEN; | |||||
KASSERT(axf->blocksize == blksz, ("%s: axf block size mismatch", | |||||
__func__)); | |||||
swe = &ses->swcr_encdec; | swe = &ses->swcr_encdec; | ||||
exf = swe->sw_exf; | exf = swe->sw_exf; | ||||
KASSERT(axf->blocksize == exf->native_blocksize, | blksz = AES_BLOCK_LEN; | ||||
KASSERT(blksz == exf->native_blocksize, | |||||
("%s: blocksize mismatch", __func__)); | ("%s: blocksize mismatch", __func__)); | ||||
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; | ||||
/* Supply MAC with IV */ | if (crp->crp_cipher_key != NULL) | ||||
axf->Reinit(&ctx, crp->crp_iv, ivlen); | exf->setkey(swe->sw_kschedule, crp->crp_cipher_key, | ||||
crypto_get_params(crp->crp_session)->csp_cipher_klen); | |||||
exf->reinit(swe->sw_kschedule, crp->crp_iv, ivlen); | |||||
/* Supply MAC with b0. */ | /* Supply MAC with b0. */ | ||||
_Static_assert(sizeof(blkbuf) >= CCM_CBC_BLOCK_LEN, | _Static_assert(sizeof(blkbuf) >= CCM_CBC_BLOCK_LEN, | ||||
"blkbuf too small for b0"); | "blkbuf too small for b0"); | ||||
build_ccm_b0(crp->crp_iv, ivlen, crp->crp_aad_length, | build_ccm_b0(crp->crp_iv, ivlen, crp->crp_aad_length, | ||||
crp->crp_payload_length, swa->sw_mlen, blk); | crp->crp_payload_length, swa->sw_mlen, blk); | ||||
axf->Update(&ctx, blk, CCM_CBC_BLOCK_LEN); | exf->update(swe->sw_kschedule, blk, CCM_CBC_BLOCK_LEN); | ||||
/* Supply MAC with AAD */ | /* Supply MAC with AAD */ | ||||
if (crp->crp_aad_length != 0) { | if (crp->crp_aad_length != 0) { | ||||
len = build_ccm_aad_length(crp->crp_aad_length, blk); | len = build_ccm_aad_length(crp->crp_aad_length, blk); | ||||
axf->Update(&ctx, blk, len); | exf->update(swe->sw_kschedule, blk, len); | ||||
if (crp->crp_aad != NULL) | if (crp->crp_aad != NULL) | ||||
axf->Update(&ctx, crp->crp_aad, | exf->update(swe->sw_kschedule, crp->crp_aad, | ||||
crp->crp_aad_length); | crp->crp_aad_length); | ||||
else | else | ||||
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, exf->update, | ||||
swe->sw_kschedule); | |||||
/* Pad the AAD (including length field) to a full block. */ | /* Pad the AAD (including length field) to a full block. */ | ||||
len = (len + crp->crp_aad_length) % CCM_CBC_BLOCK_LEN; | len = (len + crp->crp_aad_length) % CCM_CBC_BLOCK_LEN; | ||||
if (len != 0) { | if (len != 0) { | ||||
len = CCM_CBC_BLOCK_LEN - len; | len = CCM_CBC_BLOCK_LEN - len; | ||||
memset(blk, 0, CCM_CBC_BLOCK_LEN); | memset(blk, 0, CCM_CBC_BLOCK_LEN); | ||||
axf->Update(&ctx, blk, len); | exf->update(swe->sw_kschedule, blk, len); | ||||
} | } | ||||
} | } | ||||
if (crp->crp_cipher_key != NULL) | |||||
exf->setkey(swe->sw_kschedule, crp->crp_cipher_key, | |||||
crypto_get_params(crp->crp_session)->csp_cipher_klen); | |||||
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); | ||||
crypto_cursor_advance(&cc_in, crp->crp_payload_start); | crypto_cursor_advance(&cc_in, crp->crp_payload_start); | ||||
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) { | for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) { | ||||
inblk = crypto_cursor_segment(&cc_in, &len); | inblk = crypto_cursor_segment(&cc_in, &len); | ||||
if (len < blksz) { | if (len < blksz) { | ||||
crypto_cursor_copydata(&cc_in, blksz, blk); | crypto_cursor_copydata(&cc_in, blksz, blk); | ||||
inblk = blk; | inblk = blk; | ||||
} else | } else | ||||
crypto_cursor_advance(&cc_in, 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); | outblk = crypto_cursor_segment(&cc_out, &len); | ||||
if (len < blksz) | if (len < blksz) | ||||
outblk = blk; | outblk = blk; | ||||
axf->Update(&ctx, inblk, blksz); | exf->update(swe->sw_kschedule, inblk, blksz); | ||||
exf->encrypt(swe->sw_kschedule, inblk, outblk); | exf->encrypt(swe->sw_kschedule, inblk, outblk); | ||||
if (outblk == blk) | if (outblk == blk) | ||||
crypto_cursor_copyback(&cc_out, blksz, blk); | crypto_cursor_copyback(&cc_out, blksz, blk); | ||||
else | else | ||||
crypto_cursor_advance(&cc_out, blksz); | crypto_cursor_advance(&cc_out, blksz); | ||||
} else { | } else { | ||||
/* | /* | ||||
* One of the problems with CCM+CBC is that | * One of the problems with CCM+CBC is that | ||||
* the authentication is done on the | * the authentication is done on the | ||||
* unencrypted data. As a result, we have to | * unencrypted data. As a result, we have to | ||||
* decrypt the data twice: once to generate | * decrypt the data twice: once to generate | ||||
* the tag and a second time after the tag is | * the tag and a second time after the tag is | ||||
* verified. | * verified. | ||||
*/ | */ | ||||
exf->decrypt(swe->sw_kschedule, inblk, blk); | exf->decrypt(swe->sw_kschedule, inblk, blk); | ||||
axf->Update(&ctx, blk, blksz); | exf->update(swe->sw_kschedule, blk, blksz); | ||||
} | } | ||||
} | } | ||||
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)) { | ||||
axf->Update(&ctx, blk, resid); | exf->update(swe->sw_kschedule, blk, resid); | ||||
exf->encrypt_last(swe->sw_kschedule, blk, blk, resid); | exf->encrypt_last(swe->sw_kschedule, blk, blk, resid); | ||||
crypto_cursor_copyback(&cc_out, resid, blk); | crypto_cursor_copyback(&cc_out, resid, blk); | ||||
} else { | } else { | ||||
exf->decrypt_last(swe->sw_kschedule, blk, blk, resid); | exf->decrypt_last(swe->sw_kschedule, blk, blk, resid); | ||||
axf->Update(&ctx, blk, resid); | exf->update(swe->sw_kschedule, blk, resid); | ||||
} | } | ||||
} | } | ||||
/* Finalize MAC */ | /* Finalize MAC */ | ||||
axf->Final(tag, &ctx); | exf->final(tag, swe->sw_kschedule); | ||||
/* Validate tag */ | /* Validate tag */ | ||||
error = 0; | error = 0; | ||||
if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { | if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { | ||||
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); | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | swcr_chacha20_poly1305(struct swcr_session *ses, struct cryptop *crp) | ||||
const struct crypto_session_params *csp; | const struct crypto_session_params *csp; | ||||
uint64_t blkbuf[howmany(CHACHA20_NATIVE_BLOCK_LEN, sizeof(uint64_t))]; | uint64_t blkbuf[howmany(CHACHA20_NATIVE_BLOCK_LEN, sizeof(uint64_t))]; | ||||
u_char *blk = (u_char *)blkbuf; | u_char *blk = (u_char *)blkbuf; | ||||
u_char tag[POLY1305_HASH_LEN]; | u_char tag[POLY1305_HASH_LEN]; | ||||
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; | ||||
uint64_t *blkp; | uint64_t *blkp; | ||||
union authctx ctx; | |||||
struct swcr_auth *swa; | struct swcr_auth *swa; | ||||
struct swcr_encdec *swe; | struct swcr_encdec *swe; | ||||
const struct auth_hash *axf; | |||||
const struct enc_xform *exf; | const struct enc_xform *exf; | ||||
size_t len; | size_t len; | ||||
int blksz, error, r, resid; | int blksz, error, r, resid; | ||||
swa = &ses->swcr_auth; | swa = &ses->swcr_auth; | ||||
axf = swa->sw_axf; | |||||
swe = &ses->swcr_encdec; | swe = &ses->swcr_encdec; | ||||
exf = swe->sw_exf; | exf = swe->sw_exf; | ||||
blksz = exf->native_blocksize; | blksz = exf->native_blocksize; | ||||
KASSERT(blksz <= sizeof(blkbuf), ("%s: blocksize mismatch", __func__)); | KASSERT(blksz <= sizeof(blkbuf), ("%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); | ||||
csp = crypto_get_params(crp->crp_session); | csp = crypto_get_params(crp->crp_session); | ||||
/* Generate Poly1305 key. */ | |||||
if (crp->crp_cipher_key != NULL) | if (crp->crp_cipher_key != NULL) | ||||
axf->Setkey(&ctx, crp->crp_cipher_key, csp->csp_cipher_klen); | exf->setkey(swe->sw_kschedule, crp->crp_cipher_key, | ||||
else | csp->csp_cipher_klen); | ||||
axf->Setkey(&ctx, csp->csp_cipher_key, csp->csp_cipher_klen); | exf->reinit(swe->sw_kschedule, crp->crp_iv, csp->csp_ivlen); | ||||
axf->Reinit(&ctx, crp->crp_iv, csp->csp_ivlen); | |||||
/* Supply MAC with AAD */ | /* Supply MAC with AAD */ | ||||
if (crp->crp_aad != NULL) | if (crp->crp_aad != NULL) | ||||
axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length); | exf->update(swe->sw_kschedule, crp->crp_aad, | ||||
crp->crp_aad_length); | |||||
else | else | ||||
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, exf->update, swe->sw_kschedule); | ||||
if (crp->crp_aad_length % 16 != 0) { | if (crp->crp_aad_length % 16 != 0) { | ||||
/* padding1 */ | /* padding1 */ | ||||
memset(blk, 0, 16); | memset(blk, 0, 16); | ||||
axf->Update(&ctx, blk, 16 - crp->crp_aad_length % 16); | exf->update(swe->sw_kschedule, blk, | ||||
16 - crp->crp_aad_length % 16); | |||||
} | } | ||||
if (crp->crp_cipher_key != NULL) | |||||
exf->setkey(swe->sw_kschedule, crp->crp_cipher_key, | |||||
csp->csp_cipher_klen); | |||||
exf->reinit(swe->sw_kschedule, crp->crp_iv, csp->csp_ivlen); | |||||
/* 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); | ||||
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) { | for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) { | ||||
inblk = crypto_cursor_segment(&cc_in, &len); | inblk = crypto_cursor_segment(&cc_in, &len); | ||||
if (len < blksz) { | if (len < blksz) { | ||||
crypto_cursor_copydata(&cc_in, blksz, blk); | crypto_cursor_copydata(&cc_in, blksz, blk); | ||||
inblk = blk; | inblk = blk; | ||||
} else | } else | ||||
crypto_cursor_advance(&cc_in, 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); | outblk = crypto_cursor_segment(&cc_out, &len); | ||||
if (len < blksz) | if (len < blksz) | ||||
outblk = blk; | outblk = blk; | ||||
exf->encrypt(swe->sw_kschedule, inblk, outblk); | exf->encrypt(swe->sw_kschedule, inblk, outblk); | ||||
axf->Update(&ctx, outblk, blksz); | exf->update(swe->sw_kschedule, outblk, blksz); | ||||
if (outblk == blk) | if (outblk == blk) | ||||
crypto_cursor_copyback(&cc_out, blksz, blk); | crypto_cursor_copyback(&cc_out, blksz, blk); | ||||
else | else | ||||
crypto_cursor_advance(&cc_out, blksz); | crypto_cursor_advance(&cc_out, blksz); | ||||
} else { | } else { | ||||
axf->Update(&ctx, inblk, blksz); | exf->update(swe->sw_kschedule, inblk, blksz); | ||||
} | } | ||||
} | } | ||||
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(swe->sw_kschedule, blk, blk, resid); | exf->encrypt_last(swe->sw_kschedule, blk, blk, resid); | ||||
crypto_cursor_copyback(&cc_out, resid, blk); | crypto_cursor_copyback(&cc_out, resid, blk); | ||||
} | } | ||||
axf->Update(&ctx, blk, resid); | exf->update(swe->sw_kschedule, blk, resid); | ||||
if (resid % 16 != 0) { | if (resid % 16 != 0) { | ||||
/* padding2 */ | /* padding2 */ | ||||
memset(blk, 0, 16); | memset(blk, 0, 16); | ||||
axf->Update(&ctx, blk, 16 - resid % 16); | exf->update(swe->sw_kschedule, blk, 16 - resid % 16); | ||||
} | } | ||||
} | } | ||||
/* lengths */ | /* lengths */ | ||||
blkp = (uint64_t *)blk; | blkp = (uint64_t *)blk; | ||||
blkp[0] = htole64(crp->crp_aad_length); | blkp[0] = htole64(crp->crp_aad_length); | ||||
blkp[1] = htole64(crp->crp_payload_length); | blkp[1] = htole64(crp->crp_payload_length); | ||||
axf->Update(&ctx, blk, sizeof(uint64_t) * 2); | exf->update(swe->sw_kschedule, blk, sizeof(uint64_t) * 2); | ||||
/* Finalize MAC */ | /* Finalize MAC */ | ||||
axf->Final(tag, &ctx); | exf->final(tag, swe->sw_kschedule); | ||||
/* Validate tag */ | /* Validate tag */ | ||||
error = 0; | error = 0; | ||||
if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { | if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { | ||||
u_char tag2[POLY1305_HASH_LEN]; | u_char tag2[POLY1305_HASH_LEN]; | ||||
crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2); | crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2); | ||||
Show All 32 Lines | swcr_chacha20_poly1305(struct swcr_session *ses, struct cryptop *crp) | ||||
} 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); | ||||
} | } | ||||
out: | out: | ||||
explicit_bzero(blkbuf, sizeof(blkbuf)); | explicit_bzero(blkbuf, sizeof(blkbuf)); | ||||
explicit_bzero(tag, sizeof(tag)); | explicit_bzero(tag, sizeof(tag)); | ||||
explicit_bzero(&ctx, sizeof(ctx)); | |||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Apply a cipher and a digest to perform EtA. | * Apply a cipher and a digest to perform EtA. | ||||
*/ | */ | ||||
static int | static int | ||||
swcr_eta(struct swcr_session *ses, struct cryptop *crp) | swcr_eta(struct swcr_session *ses, struct cryptop *crp) | ||||
▲ Show 20 Lines • Show All 204 Lines • ▼ Show 20 Lines | if (csp->csp_mode == CSP_MODE_DIGEST) | ||||
ses->swcr_process = swcr_ccm_cbc_mac; | ses->swcr_process = swcr_ccm_cbc_mac; | ||||
break; | break; | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
swcr_setup_gcm(struct swcr_session *ses, | swcr_setup_aead(struct swcr_session *ses, | ||||
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; | int error; | ||||
/* First, setup the auth side. */ | error = swcr_setup_cipher(ses, csp); | ||||
swa = &ses->swcr_auth; | if (error) | ||||
switch (csp->csp_cipher_klen * 8) { | return (error); | ||||
case 128: | |||||
axf = &auth_hash_nist_gmac_aes_128; | |||||
break; | |||||
case 192: | |||||
axf = &auth_hash_nist_gmac_aes_192; | |||||
break; | |||||
case 256: | |||||
axf = &auth_hash_nist_gmac_aes_256; | |||||
break; | |||||
default: | |||||
return (EINVAL); | |||||
} | |||||
swa->sw_axf = axf; | |||||
if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize) | |||||
return (EINVAL); | |||||
if (csp->csp_auth_mlen == 0) | |||||
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); | |||||
axf->Init(swa->sw_ictx); | |||||
if (csp->csp_cipher_key != NULL) | |||||
axf->Setkey(swa->sw_ictx, csp->csp_cipher_key, | |||||
csp->csp_cipher_klen); | |||||
/* Second, setup the cipher side. */ | |||||
return (swcr_setup_cipher(ses, csp)); | |||||
} | |||||
static int | |||||
swcr_setup_ccm(struct swcr_session *ses, | |||||
const struct crypto_session_params *csp) | |||||
{ | |||||
struct swcr_auth *swa; | |||||
const struct auth_hash *axf; | |||||
/* First, setup the auth side. */ | |||||
swa = &ses->swcr_auth; | swa = &ses->swcr_auth; | ||||
switch (csp->csp_cipher_klen * 8) { | |||||
case 128: | |||||
axf = &auth_hash_ccm_cbc_mac_128; | |||||
break; | |||||
case 192: | |||||
axf = &auth_hash_ccm_cbc_mac_192; | |||||
break; | |||||
case 256: | |||||
axf = &auth_hash_ccm_cbc_mac_256; | |||||
break; | |||||
default: | |||||
return (EINVAL); | |||||
} | |||||
swa->sw_axf = axf; | |||||
if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize) | |||||
return (EINVAL); | |||||
if (csp->csp_auth_mlen == 0) | if (csp->csp_auth_mlen == 0) | ||||
swa->sw_mlen = axf->hashsize; | swa->sw_mlen = ses->swcr_encdec.sw_exf->macsize; | ||||
else | else | ||||
swa->sw_mlen = csp->csp_auth_mlen; | swa->sw_mlen = csp->csp_auth_mlen; | ||||
swa->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT); | return (0); | ||||
if (swa->sw_ictx == NULL) | |||||
return (ENOBUFS); | |||||
axf->Init(swa->sw_ictx); | |||||
if (csp->csp_cipher_key != NULL) | |||||
axf->Setkey(swa->sw_ictx, csp->csp_cipher_key, | |||||
csp->csp_cipher_klen); | |||||
/* Second, setup the cipher side. */ | |||||
return (swcr_setup_cipher(ses, csp)); | |||||
} | } | ||||
static int | |||||
swcr_setup_chacha20_poly1305(struct swcr_session *ses, | |||||
const struct crypto_session_params *csp) | |||||
{ | |||||
struct swcr_auth *swa; | |||||
const struct auth_hash *axf; | |||||
/* First, setup the auth side. */ | |||||
swa = &ses->swcr_auth; | |||||
axf = &auth_hash_chacha20_poly1305; | |||||
swa->sw_axf = axf; | |||||
if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize) | |||||
return (EINVAL); | |||||
if (csp->csp_auth_mlen == 0) | |||||
swa->sw_mlen = axf->hashsize; | |||||
else | |||||
swa->sw_mlen = csp->csp_auth_mlen; | |||||
/* The auth state is regenerated for each nonce. */ | |||||
/* Second, setup the cipher side. */ | |||||
return (swcr_setup_cipher(ses, csp)); | |||||
} | |||||
static bool | static bool | ||||
swcr_auth_supported(const struct crypto_session_params *csp) | swcr_auth_supported(const struct crypto_session_params *csp) | ||||
{ | { | ||||
const struct auth_hash *axf; | const struct auth_hash *axf; | ||||
axf = crypto_auth_hash(csp); | axf = crypto_auth_hash(csp); | ||||
if (axf == NULL) | if (axf == NULL) | ||||
return (false); | return (false); | ||||
▲ Show 20 Lines • Show All 177 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
break; | break; | ||||
case CSP_MODE_DIGEST: | case CSP_MODE_DIGEST: | ||||
error = swcr_setup_auth(ses, csp); | error = swcr_setup_auth(ses, csp); | ||||
break; | break; | ||||
case CSP_MODE_AEAD: | case CSP_MODE_AEAD: | ||||
switch (csp->csp_cipher_alg) { | switch (csp->csp_cipher_alg) { | ||||
case CRYPTO_AES_NIST_GCM_16: | case CRYPTO_AES_NIST_GCM_16: | ||||
error = swcr_setup_gcm(ses, csp); | error = swcr_setup_aead(ses, csp); | ||||
if (error == 0) | if (error == 0) | ||||
ses->swcr_process = swcr_gcm; | ses->swcr_process = swcr_gcm; | ||||
break; | break; | ||||
case CRYPTO_AES_CCM_16: | case CRYPTO_AES_CCM_16: | ||||
error = swcr_setup_ccm(ses, csp); | error = swcr_setup_aead(ses, csp); | ||||
if (error == 0) | if (error == 0) | ||||
ses->swcr_process = swcr_ccm; | ses->swcr_process = swcr_ccm; | ||||
break; | break; | ||||
case CRYPTO_CHACHA20_POLY1305: | case CRYPTO_CHACHA20_POLY1305: | ||||
error = swcr_setup_chacha20_poly1305(ses, csp); | error = swcr_setup_aead(ses, csp); | ||||
if (error == 0) | if (error == 0) | ||||
ses->swcr_process = swcr_chacha20_poly1305; | ses->swcr_process = swcr_chacha20_poly1305; | ||||
break; | break; | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
default: | default: | ||||
panic("bad aead algo"); | panic("bad aead algo"); | ||||
#endif | #endif | ||||
} | } | ||||
▲ Show 20 Lines • Show All 141 Lines • Show Last 20 Lines |