Changeset View
Changeset View
Standalone View
Standalone View
sys/opencrypto/cryptosoft.c
Show First 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | |||||
#include <sys/kobj.h> | #include <sys/kobj.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include "cryptodev_if.h" | #include "cryptodev_if.h" | ||||
struct swcr_auth { | struct swcr_auth { | ||||
void *sw_ictx; | void *sw_ictx; | ||||
void *sw_octx; | void *sw_octx; | ||||
struct auth_hash *sw_axf; | const struct auth_hash *sw_axf; | ||||
uint16_t sw_mlen; | uint16_t sw_mlen; | ||||
}; | }; | ||||
struct swcr_encdec { | struct swcr_encdec { | ||||
void *sw_kschedule; | void *sw_kschedule; | ||||
struct enc_xform *sw_exf; | const struct enc_xform *sw_exf; | ||||
}; | }; | ||||
struct swcr_compdec { | struct swcr_compdec { | ||||
struct comp_algo *sw_cxf; | const struct comp_algo *sw_cxf; | ||||
}; | }; | ||||
struct swcr_session { | struct swcr_session { | ||||
struct mtx swcr_lock; | struct mtx swcr_lock; | ||||
int (*swcr_process)(struct swcr_session *, struct cryptop *); | int (*swcr_process)(struct swcr_session *, struct cryptop *); | ||||
struct swcr_auth swcr_auth; | struct swcr_auth swcr_auth; | ||||
struct swcr_encdec swcr_encdec; | struct swcr_encdec swcr_encdec; | ||||
Show All 16 Lines | |||||
* Apply a symmetric encryption/decryption algorithm. | * Apply a symmetric encryption/decryption algorithm. | ||||
*/ | */ | ||||
static int | static int | ||||
swcr_encdec(struct swcr_session *ses, struct cryptop *crp) | swcr_encdec(struct swcr_session *ses, struct cryptop *crp) | ||||
{ | { | ||||
unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN]; | unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN]; | ||||
unsigned char *ivp, *nivp, iv2[EALG_MAX_BLOCK_LEN]; | unsigned char *ivp, *nivp, iv2[EALG_MAX_BLOCK_LEN]; | ||||
const struct crypto_session_params *csp; | const struct crypto_session_params *csp; | ||||
const struct enc_xform *exf; | |||||
struct swcr_encdec *sw; | struct swcr_encdec *sw; | ||||
struct enc_xform *exf; | |||||
size_t inlen, outlen; | size_t inlen, outlen; | ||||
int i, blks, ivlen, resid; | int i, blks, ivlen, resid; | ||||
struct crypto_buffer_cursor cc_in, cc_out; | struct crypto_buffer_cursor cc_in, cc_out; | ||||
const unsigned char *inblk; | const unsigned char *inblk; | ||||
unsigned char *outblk; | unsigned char *outblk; | ||||
int error; | int error; | ||||
bool encrypting; | bool encrypting; | ||||
▲ Show 20 Lines • Show All 157 Lines • ▼ Show 20 Lines | swcr_encdec(struct swcr_session *ses, struct cryptop *crp) | ||||
explicit_bzero(blk, sizeof(blk)); | explicit_bzero(blk, sizeof(blk)); | ||||
explicit_bzero(iv, sizeof(iv)); | explicit_bzero(iv, sizeof(iv)); | ||||
explicit_bzero(iv2, sizeof(iv2)); | explicit_bzero(iv2, sizeof(iv2)); | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
swcr_authprepare(struct auth_hash *axf, struct swcr_auth *sw, | swcr_authprepare(const struct auth_hash *axf, struct swcr_auth *sw, | ||||
const uint8_t *key, int klen) | const uint8_t *key, int klen) | ||||
{ | { | ||||
switch (axf->type) { | switch (axf->type) { | ||||
case CRYPTO_SHA1_HMAC: | case CRYPTO_SHA1_HMAC: | ||||
case CRYPTO_SHA2_224_HMAC: | case CRYPTO_SHA2_224_HMAC: | ||||
case CRYPTO_SHA2_256_HMAC: | case CRYPTO_SHA2_256_HMAC: | ||||
case CRYPTO_SHA2_384_HMAC: | case CRYPTO_SHA2_384_HMAC: | ||||
Show All 18 Lines | |||||
* Compute or verify hash. | * Compute or verify hash. | ||||
*/ | */ | ||||
static int | static int | ||||
swcr_authcompute(struct swcr_session *ses, struct cryptop *crp) | swcr_authcompute(struct swcr_session *ses, struct cryptop *crp) | ||||
{ | { | ||||
u_char aalg[HASH_MAX_LEN]; | u_char aalg[HASH_MAX_LEN]; | ||||
const struct crypto_session_params *csp; | const struct crypto_session_params *csp; | ||||
struct swcr_auth *sw; | struct swcr_auth *sw; | ||||
struct auth_hash *axf; | const struct auth_hash *axf; | ||||
union authctx ctx; | union authctx ctx; | ||||
int err; | int err; | ||||
sw = &ses->swcr_auth; | sw = &ses->swcr_auth; | ||||
axf = sw->sw_axf; | axf = sw->sw_axf; | ||||
csp = crypto_get_params(crp->crp_session); | csp = crypto_get_params(crp->crp_session); | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | swcr_gmac(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]; | ||||
u_char iv[AES_BLOCK_LEN]; | u_char iv[AES_BLOCK_LEN]; | ||||
struct crypto_buffer_cursor cc; | struct crypto_buffer_cursor cc; | ||||
const u_char *inblk; | const u_char *inblk; | ||||
union authctx ctx; | union authctx ctx; | ||||
struct swcr_auth *swa; | struct swcr_auth *swa; | ||||
struct auth_hash *axf; | const struct auth_hash *axf; | ||||
uint32_t *blkp; | uint32_t *blkp; | ||||
size_t len; | size_t len; | ||||
int blksz, error, ivlen, resid; | int blksz, error, ivlen, resid; | ||||
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); | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | swcr_gcm(struct swcr_session *ses, struct cryptop *crp) | ||||
u_char tag[GMAC_DIGEST_LEN]; | u_char tag[GMAC_DIGEST_LEN]; | ||||
u_char iv[AES_BLOCK_LEN]; | u_char iv[AES_BLOCK_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; | union authctx ctx; | ||||
struct swcr_auth *swa; | struct swcr_auth *swa; | ||||
struct swcr_encdec *swe; | struct swcr_encdec *swe; | ||||
struct auth_hash *axf; | const struct auth_hash *axf; | ||||
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; | axf = swa->sw_axf; | ||||
bcopy(swa->sw_ictx, &ctx, axf->ctxsize); | bcopy(swa->sw_ictx, &ctx, axf->ctxsize); | ||||
▲ Show 20 Lines • Show All 159 Lines • ▼ Show 20 Lines | |||||
static int | 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 tag[AES_CBC_MAC_HASH_LEN]; | ||||
u_char iv[AES_BLOCK_LEN]; | u_char iv[AES_BLOCK_LEN]; | ||||
union authctx ctx; | union authctx ctx; | ||||
struct swcr_auth *swa; | struct swcr_auth *swa; | ||||
struct auth_hash *axf; | const struct auth_hash *axf; | ||||
int error, ivlen; | int error, ivlen; | ||||
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 */ | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | swcr_ccm(struct swcr_session *ses, struct cryptop *crp) | ||||
u_char tag[AES_CBC_MAC_HASH_LEN]; | u_char tag[AES_CBC_MAC_HASH_LEN]; | ||||
u_char iv[AES_BLOCK_LEN]; | u_char iv[AES_BLOCK_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; | union authctx ctx; | ||||
struct swcr_auth *swa; | struct swcr_auth *swa; | ||||
struct swcr_encdec *swe; | struct swcr_encdec *swe; | ||||
struct auth_hash *axf; | const struct auth_hash *axf; | ||||
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; | ||||
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 = AES_BLOCK_LEN; | blksz = AES_BLOCK_LEN; | ||||
▲ Show 20 Lines • Show All 151 Lines • ▼ Show 20 Lines | swcr_chacha20_poly1305(struct swcr_session *ses, struct cryptop *crp) | ||||
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; | union authctx ctx; | ||||
struct swcr_auth *swa; | struct swcr_auth *swa; | ||||
struct swcr_encdec *swe; | struct swcr_encdec *swe; | ||||
struct auth_hash *axf; | const struct auth_hash *axf; | ||||
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; | axf = swa->sw_axf; | ||||
swe = &ses->swcr_encdec; | swe = &ses->swcr_encdec; | ||||
exf = swe->sw_exf; | exf = swe->sw_exf; | ||||
▲ Show 20 Lines • Show All 153 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* Apply a compression/decompression algorithm | * Apply a compression/decompression algorithm | ||||
*/ | */ | ||||
static int | static int | ||||
swcr_compdec(struct swcr_session *ses, struct cryptop *crp) | swcr_compdec(struct swcr_session *ses, struct cryptop *crp) | ||||
{ | { | ||||
const struct comp_algo *cxf; | |||||
uint8_t *data, *out; | uint8_t *data, *out; | ||||
struct comp_algo *cxf; | |||||
int adj; | int adj; | ||||
uint32_t result; | uint32_t result; | ||||
cxf = ses->swcr_compdec.sw_cxf; | cxf = ses->swcr_compdec.sw_cxf; | ||||
/* We must handle the whole buffer of data in one time | /* We must handle the whole buffer of data in one time | ||||
* then if there is not all the data in the mbuf, we must | * then if there is not all the data in the mbuf, we must | ||||
* copy in a buffer. | * copy in a buffer. | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | swcr_compdec(struct swcr_session *ses, struct cryptop *crp) | ||||
return 0; | return 0; | ||||
} | } | ||||
static int | static int | ||||
swcr_setup_cipher(struct swcr_session *ses, | swcr_setup_cipher(struct swcr_session *ses, | ||||
const struct crypto_session_params *csp) | const struct crypto_session_params *csp) | ||||
{ | { | ||||
struct swcr_encdec *swe; | struct swcr_encdec *swe; | ||||
struct enc_xform *txf; | const struct enc_xform *txf; | ||||
int error; | int error; | ||||
swe = &ses->swcr_encdec; | swe = &ses->swcr_encdec; | ||||
txf = crypto_cipher(csp); | txf = crypto_cipher(csp); | ||||
MPASS(txf->ivsize == csp->csp_ivlen); | MPASS(txf->ivsize == csp->csp_ivlen); | ||||
if (txf->ctxsize != 0) { | if (txf->ctxsize != 0) { | ||||
swe->sw_kschedule = malloc(txf->ctxsize, M_CRYPTO_DATA, | swe->sw_kschedule = malloc(txf->ctxsize, M_CRYPTO_DATA, | ||||
M_NOWAIT); | M_NOWAIT); | ||||
Show All 10 Lines | swcr_setup_cipher(struct swcr_session *ses, | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
swcr_setup_auth(struct swcr_session *ses, | swcr_setup_auth(struct swcr_session *ses, | ||||
const struct crypto_session_params *csp) | const struct crypto_session_params *csp) | ||||
{ | { | ||||
struct swcr_auth *swa; | struct swcr_auth *swa; | ||||
struct auth_hash *axf; | const struct auth_hash *axf; | ||||
swa = &ses->swcr_auth; | swa = &ses->swcr_auth; | ||||
axf = crypto_auth_hash(csp); | axf = crypto_auth_hash(csp); | ||||
swa->sw_axf = axf; | swa->sw_axf = axf; | ||||
if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize) | if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (csp->csp_auth_mlen == 0) | if (csp->csp_auth_mlen == 0) | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | swcr_setup_auth(struct swcr_session *ses, | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
swcr_setup_gcm(struct swcr_session *ses, | swcr_setup_gcm(struct swcr_session *ses, | ||||
const struct crypto_session_params *csp) | const struct crypto_session_params *csp) | ||||
{ | { | ||||
struct swcr_auth *swa; | struct swcr_auth *swa; | ||||
struct auth_hash *axf; | const struct auth_hash *axf; | ||||
if (csp->csp_ivlen != AES_GCM_IV_LEN) | if (csp->csp_ivlen != AES_GCM_IV_LEN) | ||||
return (EINVAL); | return (EINVAL); | ||||
/* First, setup the auth side. */ | /* First, setup the auth side. */ | ||||
swa = &ses->swcr_auth; | swa = &ses->swcr_auth; | ||||
switch (csp->csp_cipher_klen * 8) { | switch (csp->csp_cipher_klen * 8) { | ||||
case 128: | case 128: | ||||
Show All 27 Lines | swcr_setup_gcm(struct swcr_session *ses, | ||||
return (swcr_setup_cipher(ses, csp)); | return (swcr_setup_cipher(ses, csp)); | ||||
} | } | ||||
static int | static int | ||||
swcr_setup_ccm(struct swcr_session *ses, | swcr_setup_ccm(struct swcr_session *ses, | ||||
const struct crypto_session_params *csp) | const struct crypto_session_params *csp) | ||||
{ | { | ||||
struct swcr_auth *swa; | struct swcr_auth *swa; | ||||
struct auth_hash *axf; | const struct auth_hash *axf; | ||||
if (csp->csp_ivlen != AES_CCM_IV_LEN) | if (csp->csp_ivlen != AES_CCM_IV_LEN) | ||||
return (EINVAL); | return (EINVAL); | ||||
/* First, setup the auth side. */ | /* First, setup the auth side. */ | ||||
swa = &ses->swcr_auth; | swa = &ses->swcr_auth; | ||||
switch (csp->csp_cipher_klen * 8) { | switch (csp->csp_cipher_klen * 8) { | ||||
case 128: | case 128: | ||||
Show All 27 Lines | swcr_setup_ccm(struct swcr_session *ses, | ||||
return (swcr_setup_cipher(ses, csp)); | return (swcr_setup_cipher(ses, csp)); | ||||
} | } | ||||
static int | static int | ||||
swcr_setup_chacha20_poly1305(struct swcr_session *ses, | swcr_setup_chacha20_poly1305(struct swcr_session *ses, | ||||
const struct crypto_session_params *csp) | const struct crypto_session_params *csp) | ||||
{ | { | ||||
struct swcr_auth *swa; | struct swcr_auth *swa; | ||||
struct auth_hash *axf; | const struct auth_hash *axf; | ||||
if (csp->csp_ivlen != CHACHA20_POLY1305_IV_LEN) | if (csp->csp_ivlen != CHACHA20_POLY1305_IV_LEN) | ||||
return (EINVAL); | return (EINVAL); | ||||
/* First, setup the auth side. */ | /* First, setup the auth side. */ | ||||
swa = &ses->swcr_auth; | swa = &ses->swcr_auth; | ||||
axf = &auth_hash_chacha20_poly1305; | axf = &auth_hash_chacha20_poly1305; | ||||
swa->sw_axf = axf; | swa->sw_axf = axf; | ||||
if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize) | if (csp->csp_auth_mlen < 0 || csp->csp_auth_mlen > axf->hashsize) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (csp->csp_auth_mlen == 0) | if (csp->csp_auth_mlen == 0) | ||||
swa->sw_mlen = axf->hashsize; | swa->sw_mlen = axf->hashsize; | ||||
else | else | ||||
swa->sw_mlen = csp->csp_auth_mlen; | swa->sw_mlen = csp->csp_auth_mlen; | ||||
/* The auth state is regenerated for each nonce. */ | /* The auth state is regenerated for each nonce. */ | ||||
/* Second, setup the cipher side. */ | /* Second, setup the cipher side. */ | ||||
return (swcr_setup_cipher(ses, csp)); | 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; | 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); | ||||
switch (csp->csp_auth_alg) { | switch (csp->csp_auth_alg) { | ||||
case CRYPTO_SHA1_HMAC: | case CRYPTO_SHA1_HMAC: | ||||
case CRYPTO_SHA2_224_HMAC: | case CRYPTO_SHA2_224_HMAC: | ||||
case CRYPTO_SHA2_256_HMAC: | case CRYPTO_SHA2_256_HMAC: | ||||
Show All 36 Lines | case CRYPTO_AES_CCM_CBC_MAC: | ||||
break; | break; | ||||
} | } | ||||
return (true); | return (true); | ||||
} | } | ||||
static bool | static bool | ||||
swcr_cipher_supported(const struct crypto_session_params *csp) | swcr_cipher_supported(const struct crypto_session_params *csp) | ||||
{ | { | ||||
struct enc_xform *txf; | const struct enc_xform *txf; | ||||
txf = crypto_cipher(csp); | txf = crypto_cipher(csp); | ||||
if (txf == NULL) | if (txf == NULL) | ||||
return (false); | return (false); | ||||
if (csp->csp_cipher_alg != CRYPTO_NULL_CBC && | if (csp->csp_cipher_alg != CRYPTO_NULL_CBC && | ||||
txf->ivsize != csp->csp_ivlen) | txf->ivsize != csp->csp_ivlen) | ||||
return (false); | return (false); | ||||
return (true); | return (true); | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static int | static int | ||||
swcr_newsession(device_t dev, crypto_session_t cses, | swcr_newsession(device_t dev, crypto_session_t cses, | ||||
const struct crypto_session_params *csp) | const struct crypto_session_params *csp) | ||||
{ | { | ||||
struct swcr_session *ses; | struct swcr_session *ses; | ||||
struct swcr_encdec *swe; | struct swcr_encdec *swe; | ||||
struct swcr_auth *swa; | struct swcr_auth *swa; | ||||
struct comp_algo *cxf; | const struct comp_algo *cxf; | ||||
int error; | int error; | ||||
ses = crypto_get_driver_session(cses); | ses = crypto_get_driver_session(cses); | ||||
mtx_init(&ses->swcr_lock, "swcr session lock", NULL, MTX_DEF); | mtx_init(&ses->swcr_lock, "swcr session lock", NULL, MTX_DEF); | ||||
error = 0; | error = 0; | ||||
swe = &ses->swcr_encdec; | swe = &ses->swcr_encdec; | ||||
swa = &ses->swcr_auth; | swa = &ses->swcr_auth; | ||||
▲ Show 20 Lines • Show All 197 Lines • Show Last 20 Lines |