Changeset View
Changeset View
Standalone View
Standalone View
head/sys/opencrypto/cryptosoft.c
Show First 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | swcr_encdec(struct swcr_session *ses, struct cryptop *crp) | ||||
int iovcnt, iovalloc; | int iovcnt, iovalloc; | ||||
int error; | int error; | ||||
bool encrypting; | bool encrypting; | ||||
error = 0; | error = 0; | ||||
sw = &ses->swcr_encdec; | sw = &ses->swcr_encdec; | ||||
exf = sw->sw_exf; | exf = sw->sw_exf; | ||||
blks = exf->blocksize; | |||||
ivlen = exf->ivsize; | ivlen = exf->ivsize; | ||||
if (exf->native_blocksize == 0) { | |||||
/* Check for non-padded data */ | /* Check for non-padded data */ | ||||
if ((crp->crp_payload_length % blks) != 0) | if ((crp->crp_payload_length % exf->blocksize) != 0) | ||||
return EINVAL; | return (EINVAL); | ||||
blks = exf->blocksize; | |||||
} else | |||||
blks = exf->native_blocksize; | |||||
if (exf == &enc_xform_aes_icm && | if (exf == &enc_xform_aes_icm && | ||||
(crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) | (crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
crypto_read_iv(crp, iv); | crypto_read_iv(crp, iv); | ||||
if (crp->crp_cipher_key != NULL) { | if (crp->crp_cipher_key != NULL) { | ||||
csp = crypto_get_params(crp->crp_session); | csp = crypto_get_params(crp->crp_session); | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | swcr_encdec(struct swcr_session *ses, struct cryptop *crp) | ||||
if (ind == -1) { | if (ind == -1) { | ||||
error = EINVAL; | error = EINVAL; | ||||
goto out; | goto out; | ||||
} | } | ||||
i = crp->crp_payload_length; | i = crp->crp_payload_length; | ||||
encrypting = CRYPTO_OP_IS_ENCRYPT(crp->crp_op); | encrypting = CRYPTO_OP_IS_ENCRYPT(crp->crp_op); | ||||
while (i > 0) { | while (i >= blks) { | ||||
/* | /* | ||||
* If there's insufficient data at the end of | * If there's insufficient data at the end of | ||||
* an iovec, we have to do some copying. | * an iovec, we have to do some copying. | ||||
*/ | */ | ||||
if (uio->uio_iov[ind].iov_len < k + blks && | if (uio->uio_iov[ind].iov_len < k + blks && | ||||
uio->uio_iov[ind].iov_len != k) { | uio->uio_iov[ind].iov_len != k) { | ||||
cuio_copydata(uio, count, blks, blk); | cuio_copydata(uio, count, blks, blk); | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | if (uio->uio_iov[ind].iov_len < k + blks && | ||||
i -= blks; | i -= blks; | ||||
/* Could be done... */ | /* Could be done... */ | ||||
if (i == 0) | if (i == 0) | ||||
break; | break; | ||||
} | } | ||||
while (uio->uio_iov[ind].iov_len >= k + blks && i > 0) { | while (uio->uio_iov[ind].iov_len >= k + blks && i >= blks) { | ||||
uint8_t *idat; | uint8_t *idat; | ||||
size_t nb, rem; | |||||
nb = blks; | |||||
rem = MIN((size_t)i, | |||||
uio->uio_iov[ind].iov_len - (size_t)k); | |||||
idat = (uint8_t *)uio->uio_iov[ind].iov_base + k; | idat = (uint8_t *)uio->uio_iov[ind].iov_base + k; | ||||
if (exf->reinit) { | if (exf->reinit) { | ||||
if (encrypting && exf->encrypt_multi == NULL) | if (encrypting) | ||||
exf->encrypt(sw->sw_kschedule, | exf->encrypt(sw->sw_kschedule, | ||||
idat, idat); | idat, idat); | ||||
else if (encrypting) { | else | ||||
nb = rounddown(rem, blks); | |||||
exf->encrypt_multi(sw->sw_kschedule, | |||||
idat, idat, nb); | |||||
} else if (exf->decrypt_multi == NULL) | |||||
exf->decrypt(sw->sw_kschedule, | exf->decrypt(sw->sw_kschedule, | ||||
idat, idat); | idat, idat); | ||||
else { | |||||
nb = rounddown(rem, blks); | |||||
exf->decrypt_multi(sw->sw_kschedule, | |||||
idat, idat, nb); | |||||
} | |||||
} else if (encrypting) { | } else if (encrypting) { | ||||
/* XOR with previous block/IV */ | /* XOR with previous block/IV */ | ||||
for (j = 0; j < blks; j++) | for (j = 0; j < blks; j++) | ||||
idat[j] ^= ivp[j]; | idat[j] ^= ivp[j]; | ||||
exf->encrypt(sw->sw_kschedule, idat, idat); | exf->encrypt(sw->sw_kschedule, idat, idat); | ||||
ivp = idat; | ivp = idat; | ||||
} else { /* decrypt */ | } else { /* decrypt */ | ||||
/* | /* | ||||
* Keep encrypted block to be used | * Keep encrypted block to be used | ||||
* in next block's processing. | * in next block's processing. | ||||
*/ | */ | ||||
nivp = (ivp == iv) ? iv2 : iv; | nivp = (ivp == iv) ? iv2 : iv; | ||||
bcopy(idat, nivp, blks); | bcopy(idat, nivp, blks); | ||||
exf->decrypt(sw->sw_kschedule, idat, idat); | exf->decrypt(sw->sw_kschedule, idat, idat); | ||||
/* XOR with previous block/IV */ | /* XOR with previous block/IV */ | ||||
for (j = 0; j < blks; j++) | for (j = 0; j < blks; j++) | ||||
idat[j] ^= ivp[j]; | idat[j] ^= ivp[j]; | ||||
ivp = nivp; | ivp = nivp; | ||||
} | } | ||||
count += nb; | count += blks; | ||||
k += nb; | k += blks; | ||||
i -= nb; | i -= blks; | ||||
} | } | ||||
/* | /* | ||||
* Advance to the next iov if the end of the current iov | * Advance to the next iov if the end of the current iov | ||||
* is aligned with the end of a cipher block. | * is aligned with the end of a cipher block. | ||||
* Note that the code is equivalent to calling: | * Note that the code is equivalent to calling: | ||||
* ind = cuio_getptr(uio, count, &k); | * ind = cuio_getptr(uio, count, &k); | ||||
*/ | */ | ||||
if (i > 0 && k == uio->uio_iov[ind].iov_len) { | if (i > 0 && k == uio->uio_iov[ind].iov_len) { | ||||
k = 0; | k = 0; | ||||
ind++; | ind++; | ||||
if (ind >= uio->uio_iovcnt) { | if (ind >= uio->uio_iovcnt) { | ||||
error = EINVAL; | error = EINVAL; | ||||
goto out; | goto out; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/* Handle trailing partial block for stream ciphers. */ | |||||
if (i > 0) { | |||||
KASSERT(exf->native_blocksize != 0, | |||||
("%s: partial block of %d bytes for cipher %s", | |||||
__func__, i, exf->name)); | |||||
KASSERT(exf->reinit != NULL, | |||||
("%s: partial block cipher %s without reinit hook", | |||||
__func__, exf->name)); | |||||
KASSERT(i < blks, ("%s: partial block too big", __func__)); | |||||
cuio_copydata(uio, count, i, blk); | |||||
if (encrypting) { | |||||
exf->encrypt_last(sw->sw_kschedule, blk, blk, i); | |||||
} else { | |||||
exf->decrypt_last(sw->sw_kschedule, blk, blk, i); | |||||
} | |||||
cuio_copyback(uio, count, i, blk); | |||||
} | |||||
out: | out: | ||||
if (iovalloc) | if (iovalloc) | ||||
free(iov, M_CRYPTO_DATA); | free(iov, M_CRYPTO_DATA); | ||||
return (error); | return (error); | ||||
} | } | ||||
static void | static void | ||||
▲ Show 20 Lines • Show All 177 Lines • ▼ Show 20 Lines | swcr_gcm(struct swcr_session *ses, struct cryptop *crp) | ||||
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); | ||||
blksz = axf->blocksize; | blksz = axf->blocksize; | ||||
swe = &ses->swcr_encdec; | swe = &ses->swcr_encdec; | ||||
exf = swe->sw_exf; | exf = swe->sw_exf; | ||||
KASSERT(axf->blocksize == exf->native_blocksize, | |||||
("%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); | ||||
/* Initialize the IV */ | /* Initialize the IV */ | ||||
ivlen = AES_GCM_IV_LEN; | ivlen = AES_GCM_IV_LEN; | ||||
bcopy(crp->crp_iv, iv, ivlen); | bcopy(crp->crp_iv, iv, ivlen); | ||||
▲ Show 20 Lines • Show All 137 Lines • ▼ Show 20 Lines | swcr_ccm(struct swcr_session *ses, struct cryptop *crp) | ||||
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); | ||||
blksz = axf->blocksize; | blksz = axf->blocksize; | ||||
swe = &ses->swcr_encdec; | swe = &ses->swcr_encdec; | ||||
exf = swe->sw_exf; | exf = swe->sw_exf; | ||||
KASSERT(axf->blocksize == exf->native_blocksize, | |||||
("%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); | ||||
/* Initialize the IV */ | /* Initialize the IV */ | ||||
ivlen = AES_CCM_IV_LEN; | ivlen = AES_CCM_IV_LEN; | ||||
bcopy(crp->crp_iv, iv, ivlen); | bcopy(crp->crp_iv, iv, ivlen); | ||||
▲ Show 20 Lines • Show All 727 Lines • Show Last 20 Lines |