Changeset View
Changeset View
Standalone View
Standalone View
sys/opencrypto/cryptosoft.c
Show First 20 Lines • Show All 861 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)); | ||||
explicit_bzero(iv, sizeof(iv)); | explicit_bzero(iv, sizeof(iv)); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | |||||
swcr_chacha20_poly1305(struct swcr_session *ses, struct cryptop *crp) | |||||
{ | |||||
const struct crypto_session_params *csp; | |||||
uint64_t blkbuf[howmany(CHACHA20_NATIVE_BLOCK_LEN, sizeof(uint64_t))]; | |||||
u_char *blk = (u_char *)blkbuf; | |||||
u_char tag[POLY1305_HASH_LEN]; | |||||
struct crypto_buffer_cursor cc_in, cc_out; | |||||
const u_char *inblk; | |||||
u_char *outblk; | |||||
uint64_t *blkp; | |||||
union authctx ctx; | |||||
struct swcr_auth *swa; | |||||
struct swcr_encdec *swe; | |||||
struct auth_hash *axf; | |||||
struct enc_xform *exf; | |||||
int blksz, error, r, resid; | |||||
swa = &ses->swcr_auth; | |||||
axf = swa->sw_axf; | |||||
swe = &ses->swcr_encdec; | |||||
exf = swe->sw_exf; | |||||
blksz = exf->native_blocksize; | |||||
KASSERT(blksz <= sizeof(blkbuf), ("%s: blocksize mismatch", __func__)); | |||||
if ((crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) | |||||
return (EINVAL); | |||||
csp = crypto_get_params(crp->crp_session); | |||||
/* Generate Poly1305 key. */ | |||||
if (crp->crp_cipher_key != NULL) | |||||
axf->Setkey(&ctx, crp->crp_cipher_key, csp->csp_cipher_klen); | |||||
else | |||||
axf->Setkey(&ctx, csp->csp_cipher_key, csp->csp_cipher_klen); | |||||
axf->Reinit(&ctx, crp->crp_iv, csp->csp_ivlen); | |||||
/* Supply MAC with AAD */ | |||||
if (crp->crp_aad != NULL) | |||||
axf->Update(&ctx, crp->crp_aad, crp->crp_aad_length); | |||||
else | |||||
crypto_apply(crp, crp->crp_aad_start, | |||||
crp->crp_aad_length, axf->Update, &ctx); | |||||
if (crp->crp_aad_length % 16 != 0) { | |||||
/* padding1 */ | |||||
memset(blk, 0, 16); | |||||
axf->Update(&ctx, 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); | |||||
/* Do encryption with MAC */ | |||||
crypto_cursor_init(&cc_in, &crp->crp_buf); | |||||
crypto_cursor_advance(&cc_in, crp->crp_payload_start); | |||||
if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { | |||||
crypto_cursor_init(&cc_out, &crp->crp_obuf); | |||||
crypto_cursor_advance(&cc_out, crp->crp_payload_output_start); | |||||
} else | |||||
cc_out = cc_in; | |||||
for (resid = crp->crp_payload_length; resid >= blksz; resid -= blksz) { | |||||
if (crypto_cursor_seglen(&cc_in) < blksz) { | |||||
crypto_cursor_copydata(&cc_in, blksz, blk); | |||||
inblk = blk; | |||||
} else { | |||||
inblk = crypto_cursor_segbase(&cc_in); | |||||
crypto_cursor_advance(&cc_in, blksz); | |||||
} | |||||
if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { | |||||
if (crypto_cursor_seglen(&cc_out) < blksz) | |||||
outblk = blk; | |||||
else | |||||
outblk = crypto_cursor_segbase(&cc_out); | |||||
exf->encrypt(swe->sw_kschedule, inblk, outblk); | |||||
axf->Update(&ctx, outblk, blksz); | |||||
if (outblk == blk) | |||||
crypto_cursor_copyback(&cc_out, blksz, blk); | |||||
else | |||||
crypto_cursor_advance(&cc_out, blksz); | |||||
} else { | |||||
axf->Update(&ctx, inblk, blksz); | |||||
} | |||||
} | |||||
if (resid > 0) { | |||||
crypto_cursor_copydata(&cc_in, resid, blk); | |||||
if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { | |||||
exf->encrypt_last(swe->sw_kschedule, blk, blk, resid); | |||||
crypto_cursor_copyback(&cc_out, resid, blk); | |||||
} | |||||
axf->Update(&ctx, blk, resid); | |||||
if (resid % 16 != 0) { | |||||
/* padding2 */ | |||||
memset(blk, 0, 16); | |||||
axf->Update(&ctx, blk, 16 - resid % 16); | |||||
} | |||||
} | |||||
/* lengths */ | |||||
blkp = (uint64_t *)blk; | |||||
blkp[0] = htole64(crp->crp_aad_length); | |||||
blkp[1] = htole64(crp->crp_payload_length); | |||||
axf->Update(&ctx, blk, sizeof(uint64_t) * 2); | |||||
/* Finalize MAC */ | |||||
axf->Final(tag, &ctx); | |||||
/* Validate tag */ | |||||
error = 0; | |||||
if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { | |||||
u_char tag2[POLY1305_HASH_LEN]; | |||||
crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, tag2); | |||||
r = timingsafe_bcmp(tag, tag2, swa->sw_mlen); | |||||
explicit_bzero(tag2, sizeof(tag2)); | |||||
if (r != 0) { | |||||
error = EBADMSG; | |||||
goto out; | |||||
} | |||||
/* tag matches, decrypt data */ | |||||
crypto_cursor_init(&cc_in, &crp->crp_buf); | |||||
crypto_cursor_advance(&cc_in, crp->crp_payload_start); | |||||
for (resid = crp->crp_payload_length; resid > blksz; | |||||
resid -= blksz) { | |||||
if (crypto_cursor_seglen(&cc_in) < blksz) { | |||||
crypto_cursor_copydata(&cc_in, blksz, blk); | |||||
inblk = blk; | |||||
} else { | |||||
inblk = crypto_cursor_segbase(&cc_in); | |||||
crypto_cursor_advance(&cc_in, blksz); | |||||
} | |||||
if (crypto_cursor_seglen(&cc_out) < blksz) | |||||
outblk = blk; | |||||
else | |||||
outblk = crypto_cursor_segbase(&cc_out); | |||||
exf->decrypt(swe->sw_kschedule, inblk, outblk); | |||||
if (outblk == blk) | |||||
crypto_cursor_copyback(&cc_out, blksz, blk); | |||||
else | |||||
crypto_cursor_advance(&cc_out, blksz); | |||||
} | |||||
if (resid > 0) { | |||||
crypto_cursor_copydata(&cc_in, resid, blk); | |||||
exf->decrypt_last(swe->sw_kschedule, blk, blk, resid); | |||||
crypto_cursor_copyback(&cc_out, resid, blk); | |||||
} | |||||
} else { | |||||
/* Inject the authentication data */ | |||||
crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, tag); | |||||
} | |||||
out: | |||||
explicit_bzero(blkbuf, sizeof(blkbuf)); | |||||
explicit_bzero(tag, sizeof(tag)); | |||||
explicit_bzero(&ctx, sizeof(ctx)); | |||||
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) | ||||
{ | { | ||||
int error; | int error; | ||||
▲ Show 20 Lines • Show All 288 Lines • ▼ Show 20 Lines | swcr_setup_ccm(struct swcr_session *ses, | ||||
if (csp->csp_cipher_key != NULL) | if (csp->csp_cipher_key != NULL) | ||||
axf->Setkey(swa->sw_ictx, csp->csp_cipher_key, | axf->Setkey(swa->sw_ictx, csp->csp_cipher_key, | ||||
csp->csp_cipher_klen); | csp->csp_cipher_klen); | ||||
/* Second, setup the cipher side. */ | /* Second, setup the cipher side. */ | ||||
return (swcr_setup_cipher(ses, csp)); | 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; | |||||
struct auth_hash *axf; | |||||
if (csp->csp_ivlen != CHACHA20_POLY1305_IV_LEN) | |||||
return (EINVAL); | |||||
/* 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) | ||||
{ | { | ||||
struct auth_hash *axf; | 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 71 Lines • ▼ Show 20 Lines | case CSP_MODE_COMPRESS: | ||||
default: | default: | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
break; | break; | ||||
case CSP_MODE_CIPHER: | case CSP_MODE_CIPHER: | ||||
switch (csp->csp_cipher_alg) { | switch (csp->csp_cipher_alg) { | ||||
case CRYPTO_AES_NIST_GCM_16: | case CRYPTO_AES_NIST_GCM_16: | ||||
case CRYPTO_AES_CCM_16: | case CRYPTO_AES_CCM_16: | ||||
case CRYPTO_CHACHA20_POLY1305: | |||||
return (EINVAL); | return (EINVAL); | ||||
default: | default: | ||||
if (!swcr_cipher_supported(csp)) | if (!swcr_cipher_supported(csp)) | ||||
return (EINVAL); | return (EINVAL); | ||||
break; | break; | ||||
} | } | ||||
break; | break; | ||||
case CSP_MODE_DIGEST: | case CSP_MODE_DIGEST: | ||||
if (!swcr_auth_supported(csp)) | if (!swcr_auth_supported(csp)) | ||||
return (EINVAL); | return (EINVAL); | ||||
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: | ||||
case CRYPTO_AES_CCM_16: | case CRYPTO_AES_CCM_16: | ||||
case CRYPTO_CHACHA20_POLY1305: | |||||
break; | break; | ||||
default: | default: | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
break; | break; | ||||
case CSP_MODE_ETA: | case CSP_MODE_ETA: | ||||
/* AEAD algorithms cannot be used for EtA. */ | /* AEAD algorithms cannot be used for EtA. */ | ||||
switch (csp->csp_cipher_alg) { | switch (csp->csp_cipher_alg) { | ||||
case CRYPTO_AES_NIST_GCM_16: | case CRYPTO_AES_NIST_GCM_16: | ||||
case CRYPTO_AES_CCM_16: | case CRYPTO_AES_CCM_16: | ||||
case CRYPTO_CHACHA20_POLY1305: | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
switch (csp->csp_auth_alg) { | switch (csp->csp_auth_alg) { | ||||
case CRYPTO_AES_NIST_GMAC: | case CRYPTO_AES_NIST_GMAC: | ||||
case CRYPTO_AES_CCM_CBC_MAC: | case CRYPTO_AES_CCM_CBC_MAC: | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | #endif | ||||
case CSP_MODE_CIPHER: | case CSP_MODE_CIPHER: | ||||
switch (csp->csp_cipher_alg) { | switch (csp->csp_cipher_alg) { | ||||
case CRYPTO_NULL_CBC: | case CRYPTO_NULL_CBC: | ||||
ses->swcr_process = swcr_null; | ses->swcr_process = swcr_null; | ||||
break; | break; | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
case CRYPTO_AES_NIST_GCM_16: | case CRYPTO_AES_NIST_GCM_16: | ||||
case CRYPTO_AES_CCM_16: | case CRYPTO_AES_CCM_16: | ||||
case CRYPTO_CHACHA20_POLY1305: | |||||
panic("bad cipher algo"); | panic("bad cipher algo"); | ||||
#endif | #endif | ||||
default: | default: | ||||
error = swcr_setup_cipher(ses, csp); | error = swcr_setup_cipher(ses, csp); | ||||
if (error == 0) | if (error == 0) | ||||
ses->swcr_process = swcr_encdec; | ses->swcr_process = swcr_encdec; | ||||
} | } | ||||
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_gcm(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_ccm(ses, csp); | ||||
if (error == 0) | if (error == 0) | ||||
ses->swcr_process = swcr_ccm; | ses->swcr_process = swcr_ccm; | ||||
break; | break; | ||||
case CRYPTO_CHACHA20_POLY1305: | |||||
error = swcr_setup_chacha20_poly1305(ses, csp); | |||||
if (error == 0) | |||||
ses->swcr_process = swcr_chacha20_poly1305; | |||||
break; | |||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
default: | default: | ||||
panic("bad aead algo"); | panic("bad aead algo"); | ||||
#endif | #endif | ||||
} | } | ||||
break; | break; | ||||
case CSP_MODE_ETA: | case CSP_MODE_ETA: | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
switch (csp->csp_cipher_alg) { | switch (csp->csp_cipher_alg) { | ||||
case CRYPTO_AES_NIST_GCM_16: | case CRYPTO_AES_NIST_GCM_16: | ||||
case CRYPTO_AES_CCM_16: | case CRYPTO_AES_CCM_16: | ||||
case CRYPTO_CHACHA20_POLY1305: | |||||
panic("bad eta cipher algo"); | panic("bad eta cipher algo"); | ||||
} | } | ||||
switch (csp->csp_auth_alg) { | switch (csp->csp_auth_alg) { | ||||
case CRYPTO_AES_NIST_GMAC: | case CRYPTO_AES_NIST_GMAC: | ||||
case CRYPTO_AES_CCM_CBC_MAC: | case CRYPTO_AES_CCM_CBC_MAC: | ||||
panic("bad eta auth algo"); | panic("bad eta auth algo"); | ||||
} | } | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 125 Lines • Show Last 20 Lines |