Changeset View
Changeset View
Standalone View
Standalone View
head/sys/opencrypto/cryptodev.c
Show First 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | |||||
#define CIOCGSESSION32 _IOWR('c', 101, struct session_op32) | #define CIOCGSESSION32 _IOWR('c', 101, struct session_op32) | ||||
#define CIOCCRYPT32 _IOWR('c', 103, struct crypt_op32) | #define CIOCCRYPT32 _IOWR('c', 103, struct crypt_op32) | ||||
#define CIOCKEY32 _IOWR('c', 104, struct crypt_kop32) | #define CIOCKEY32 _IOWR('c', 104, struct crypt_kop32) | ||||
#define CIOCGSESSION232 _IOWR('c', 106, struct session2_op32) | #define CIOCGSESSION232 _IOWR('c', 106, struct session2_op32) | ||||
#define CIOCKEY232 _IOWR('c', 107, struct crypt_kop32) | #define CIOCKEY232 _IOWR('c', 107, struct crypt_kop32) | ||||
static void | static void | ||||
session_op_from_32(const struct session_op32 *from, struct session_op *to) | session_op_from_32(const struct session_op32 *from, struct session2_op *to) | ||||
{ | { | ||||
memset(to, 0, sizeof(*to)); | |||||
CP(*from, *to, cipher); | CP(*from, *to, cipher); | ||||
CP(*from, *to, mac); | CP(*from, *to, mac); | ||||
CP(*from, *to, keylen); | CP(*from, *to, keylen); | ||||
PTRIN_CP(*from, *to, key); | PTRIN_CP(*from, *to, key); | ||||
CP(*from, *to, mackeylen); | CP(*from, *to, mackeylen); | ||||
PTRIN_CP(*from, *to, mackey); | PTRIN_CP(*from, *to, mackey); | ||||
CP(*from, *to, ses); | CP(*from, *to, ses); | ||||
to->crid = CRYPTOCAP_F_HARDWARE; | |||||
} | } | ||||
static void | static void | ||||
session2_op_from_32(const struct session2_op32 *from, struct session2_op *to) | session2_op_from_32(const struct session2_op32 *from, struct session2_op *to) | ||||
{ | { | ||||
session_op_from_32((const struct session_op32 *)from, | session_op_from_32((const struct session_op32 *)from, to); | ||||
(struct session_op *)to); | |||||
CP(*from, *to, crid); | CP(*from, *to, crid); | ||||
} | } | ||||
static void | static void | ||||
session_op_to_32(const struct session_op *from, struct session_op32 *to) | session_op_to_32(const struct session2_op *from, struct session_op32 *to) | ||||
{ | { | ||||
CP(*from, *to, cipher); | CP(*from, *to, cipher); | ||||
CP(*from, *to, mac); | CP(*from, *to, mac); | ||||
CP(*from, *to, keylen); | CP(*from, *to, keylen); | ||||
PTROUT_CP(*from, *to, key); | PTROUT_CP(*from, *to, key); | ||||
CP(*from, *to, mackeylen); | CP(*from, *to, mackeylen); | ||||
PTROUT_CP(*from, *to, mackey); | PTROUT_CP(*from, *to, mackey); | ||||
CP(*from, *to, ses); | CP(*from, *to, ses); | ||||
} | } | ||||
static void | static void | ||||
session2_op_to_32(const struct session2_op *from, struct session2_op32 *to) | session2_op_to_32(const struct session2_op *from, struct session2_op32 *to) | ||||
{ | { | ||||
session_op_to_32((const struct session_op *)from, | session_op_to_32(from, (struct session_op32 *)to); | ||||
(struct session_op32 *)to); | |||||
CP(*from, *to, crid); | CP(*from, *to, crid); | ||||
} | } | ||||
static void | static void | ||||
crypt_op_from_32(const struct crypt_op32 *from, struct crypt_op *to) | crypt_op_from_32(const struct crypt_op32 *from, struct crypt_op *to) | ||||
{ | { | ||||
CP(*from, *to, ses); | CP(*from, *to, ses); | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | crypt_kop_to_32(const struct crypt_kop *from, struct crypt_kop32 *to) | ||||
CP(*from, *to, crk_iparams); | CP(*from, *to, crk_iparams); | ||||
CP(*from, *to, crk_oparams); | CP(*from, *to, crk_oparams); | ||||
CP(*from, *to, crk_crid); | CP(*from, *to, crk_crid); | ||||
for (i = 0; i < CRK_MAXPARAM; i++) | for (i = 0; i < CRK_MAXPARAM; i++) | ||||
crparam_to_32(&from->crk_param[i], &to->crk_param[i]); | crparam_to_32(&from->crk_param[i], &to->crk_param[i]); | ||||
} | } | ||||
#endif | #endif | ||||
static void | |||||
session2_op_from_op(const struct session_op *from, struct session2_op *to) | |||||
{ | |||||
memset(to, 0, sizeof(*to)); | |||||
memcpy(to, from, sizeof(*from)); | |||||
to->crid = CRYPTOCAP_F_HARDWARE; | |||||
} | |||||
static void | |||||
session2_op_to_op(const struct session2_op *from, struct session_op *to) | |||||
{ | |||||
memcpy(to, from, sizeof(*to)); | |||||
} | |||||
struct csession { | struct csession { | ||||
TAILQ_ENTRY(csession) next; | TAILQ_ENTRY(csession) next; | ||||
crypto_session_t cses; | crypto_session_t cses; | ||||
volatile u_int refs; | volatile u_int refs; | ||||
u_int32_t ses; | u_int32_t ses; | ||||
struct mtx lock; /* for op submission */ | struct mtx lock; /* for op submission */ | ||||
struct enc_xform *txform; | struct enc_xform *txform; | ||||
▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
cryptof_ioctl( | cryptof_ioctl( | ||||
struct file *fp, | struct file *fp, | ||||
u_long cmd, | u_long cmd, | ||||
void *data, | void *data, | ||||
struct ucred *active_cred, | struct ucred *active_cred, | ||||
struct thread *td) | struct thread *td) | ||||
{ | { | ||||
#define SES2(p) ((struct session2_op *)p) | |||||
struct crypto_session_params csp; | struct crypto_session_params csp; | ||||
struct fcrypt *fcr = fp->f_data; | struct fcrypt *fcr = fp->f_data; | ||||
struct csession *cse; | struct csession *cse; | ||||
struct session_op *sop; | struct session2_op *sop; | ||||
struct crypt_op *cop; | struct crypt_op *cop; | ||||
struct crypt_aead *caead; | struct crypt_aead *caead; | ||||
struct enc_xform *txform = NULL; | struct enc_xform *txform = NULL; | ||||
struct auth_hash *thash = NULL; | struct auth_hash *thash = NULL; | ||||
void *key = NULL; | void *key = NULL; | ||||
void *mackey = NULL; | void *mackey = NULL; | ||||
struct crypt_kop *kop; | struct crypt_kop *kop; | ||||
crypto_session_t cses; | crypto_session_t cses; | ||||
u_int32_t ses; | u_int32_t ses; | ||||
int error = 0, crid; | int error = 0, crid; | ||||
#ifdef COMPAT_FREEBSD32 | union { | ||||
struct session2_op sopc; | struct session2_op sopc; | ||||
#ifdef COMPAT_FREEBSD32 | |||||
struct crypt_op copc; | struct crypt_op copc; | ||||
struct crypt_kop kopc; | struct crypt_kop kopc; | ||||
#endif | #endif | ||||
}; | |||||
#ifdef COMPAT_FREEBSD32 | |||||
u_long cmd32; | |||||
void *data32; | |||||
cmd32 = 0; | |||||
data32 = NULL; | |||||
switch (cmd) { | switch (cmd) { | ||||
case CIOCGSESSION: | |||||
case CIOCGSESSION2: | |||||
#ifdef COMPAT_FREEBSD32 | |||||
case CIOCGSESSION32: | case CIOCGSESSION32: | ||||
cmd32 = cmd; | |||||
data32 = data; | |||||
cmd = CIOCGSESSION; | |||||
data = &sopc; | |||||
session_op_from_32((struct session_op32 *)data32, &sopc); | |||||
break; | |||||
case CIOCGSESSION232: | case CIOCGSESSION232: | ||||
if (cmd == CIOCGSESSION32) { | cmd32 = cmd; | ||||
session_op_from_32(data, (struct session_op *)&sopc); | data32 = data; | ||||
sop = (struct session_op *)&sopc; | cmd = CIOCGSESSION2; | ||||
} else if (cmd == CIOCGSESSION232) { | data = &sopc; | ||||
session2_op_from_32(data, &sopc); | session2_op_from_32((struct session2_op32 *)data32, &sopc); | ||||
sop = (struct session_op *)&sopc; | break; | ||||
} else | case CIOCCRYPT32: | ||||
cmd32 = cmd; | |||||
data32 = data; | |||||
cmd = CIOCCRYPT; | |||||
data = &copc; | |||||
crypt_op_from_32((struct crypt_op32 *)data32, &copc); | |||||
break; | |||||
case CIOCKEY32: | |||||
case CIOCKEY232: | |||||
cmd32 = cmd; | |||||
data32 = data; | |||||
if (cmd == CIOCKEY32) | |||||
cmd = CIOCKEY; | |||||
else | |||||
cmd = CIOCKEY2; | |||||
data = &kopc; | |||||
crypt_kop_from_32((struct crypt_kop32 *)data32, &kopc); | |||||
break; | |||||
} | |||||
#endif | #endif | ||||
sop = (struct session_op *)data; | |||||
switch (cmd) { | |||||
case CIOCGSESSION: | |||||
case CIOCGSESSION2: | |||||
if (cmd == CIOCGSESSION) { | |||||
session2_op_from_op(data, &sopc); | |||||
sop = &sopc; | |||||
} else | |||||
sop = (struct session2_op *)data; | |||||
switch (sop->cipher) { | switch (sop->cipher) { | ||||
case 0: | case 0: | ||||
break; | break; | ||||
case CRYPTO_AES_CBC: | case CRYPTO_AES_CBC: | ||||
txform = &enc_xform_rijndael128; | txform = &enc_xform_rijndael128; | ||||
break; | break; | ||||
case CRYPTO_AES_XTS: | case CRYPTO_AES_XTS: | ||||
txform = &enc_xform_aes_xts; | txform = &enc_xform_aes_xts; | ||||
▲ Show 20 Lines • Show All 246 Lines • ▼ Show 20 Lines | if (thash) { | ||||
} | } | ||||
if (csp.csp_auth_alg == CRYPTO_AES_NIST_GMAC) | if (csp.csp_auth_alg == CRYPTO_AES_NIST_GMAC) | ||||
csp.csp_ivlen = AES_GCM_IV_LEN; | csp.csp_ivlen = AES_GCM_IV_LEN; | ||||
if (csp.csp_auth_alg == CRYPTO_AES_CCM_CBC_MAC) | if (csp.csp_auth_alg == CRYPTO_AES_CCM_CBC_MAC) | ||||
csp.csp_ivlen = AES_CCM_IV_LEN; | csp.csp_ivlen = AES_CCM_IV_LEN; | ||||
} | } | ||||
/* NB: CIOCGSESSION2 has the crid */ | crid = sop->crid; | ||||
if (cmd == CIOCGSESSION2 | |||||
#ifdef COMPAT_FREEBSD32 | |||||
|| cmd == CIOCGSESSION232 | |||||
#endif | |||||
) { | |||||
crid = SES2(sop)->crid; | |||||
error = checkforsoftware(&crid); | error = checkforsoftware(&crid); | ||||
if (error) { | if (error) { | ||||
CRYPTDEB("checkforsoftware"); | CRYPTDEB("checkforsoftware"); | ||||
SDT_PROBE1(opencrypto, dev, ioctl, error, | SDT_PROBE1(opencrypto, dev, ioctl, error, | ||||
__LINE__); | __LINE__); | ||||
goto bail; | goto bail; | ||||
} | } | ||||
} else | |||||
crid = CRYPTOCAP_F_HARDWARE; | |||||
error = crypto_newsession(&cses, &csp, crid); | error = crypto_newsession(&cses, &csp, crid); | ||||
if (error) { | if (error) { | ||||
CRYPTDEB("crypto_newsession"); | CRYPTDEB("crypto_newsession"); | ||||
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); | SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); | ||||
goto bail; | goto bail; | ||||
} | } | ||||
cse = csecreate(fcr, cses, &csp, txform, key, thash, mackey); | cse = csecreate(fcr, cses, &csp, txform, key, thash, mackey); | ||||
if (cse == NULL) { | if (cse == NULL) { | ||||
crypto_freesession(cses); | crypto_freesession(cses); | ||||
error = EINVAL; | error = EINVAL; | ||||
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); | SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); | ||||
CRYPTDEB("csecreate"); | CRYPTDEB("csecreate"); | ||||
goto bail; | goto bail; | ||||
} | } | ||||
sop->ses = cse->ses; | sop->ses = cse->ses; | ||||
if (cmd == CIOCGSESSION2 | |||||
#ifdef COMPAT_FREEBSD32 | |||||
|| cmd == CIOCGSESSION232 | |||||
#endif | |||||
) { | |||||
/* return hardware/driver id */ | /* return hardware/driver id */ | ||||
SES2(sop)->crid = crypto_ses2hid(cse->cses); | sop->crid = crypto_ses2hid(cse->cses); | ||||
} | |||||
bail: | bail: | ||||
if (error) { | if (error) { | ||||
free(key, M_XDATA); | free(key, M_XDATA); | ||||
free(mackey, M_XDATA); | free(mackey, M_XDATA); | ||||
} | } | ||||
#ifdef COMPAT_FREEBSD32 | |||||
else { | if (cmd == CIOCGSESSION && error == 0) | ||||
if (cmd == CIOCGSESSION32) | session2_op_to_op(sop, data); | ||||
session_op_to_32(sop, data); | |||||
else if (cmd == CIOCGSESSION232) | |||||
session2_op_to_32((struct session2_op *)sop, | |||||
data); | |||||
} | |||||
#endif | |||||
break; | break; | ||||
case CIOCFSESSION: | case CIOCFSESSION: | ||||
ses = *(u_int32_t *)data; | ses = *(u_int32_t *)data; | ||||
if (!csedelete(fcr, ses)) { | if (!csedelete(fcr, ses)) { | ||||
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); | SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
break; | break; | ||||
case CIOCCRYPT: | case CIOCCRYPT: | ||||
#ifdef COMPAT_FREEBSD32 | |||||
case CIOCCRYPT32: | |||||
if (cmd == CIOCCRYPT32) { | |||||
cop = &copc; | |||||
crypt_op_from_32(data, cop); | |||||
} else | |||||
#endif | |||||
cop = (struct crypt_op *)data; | cop = (struct crypt_op *)data; | ||||
cse = csefind(fcr, cop->ses); | cse = csefind(fcr, cop->ses); | ||||
if (cse == NULL) { | if (cse == NULL) { | ||||
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); | SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
error = cryptodev_op(cse, cop, active_cred, td); | error = cryptodev_op(cse, cop, active_cred, td); | ||||
csefree(cse); | csefree(cse); | ||||
#ifdef COMPAT_FREEBSD32 | |||||
if (error == 0 && cmd == CIOCCRYPT32) | |||||
crypt_op_to_32(cop, data); | |||||
#endif | |||||
break; | break; | ||||
case CIOCKEY: | case CIOCKEY: | ||||
case CIOCKEY2: | case CIOCKEY2: | ||||
#ifdef COMPAT_FREEBSD32 | |||||
case CIOCKEY32: | |||||
case CIOCKEY232: | |||||
#endif | |||||
if (!crypto_userasymcrypto) { | if (!crypto_userasymcrypto) { | ||||
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); | SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); | ||||
return (EPERM); /* XXX compat? */ | return (EPERM); /* XXX compat? */ | ||||
} | } | ||||
#ifdef COMPAT_FREEBSD32 | |||||
if (cmd == CIOCKEY32 || cmd == CIOCKEY232) { | |||||
kop = &kopc; | |||||
crypt_kop_from_32(data, kop); | |||||
} else | |||||
#endif | |||||
kop = (struct crypt_kop *)data; | kop = (struct crypt_kop *)data; | ||||
if (cmd == CIOCKEY | if (cmd == CIOCKEY) { | ||||
#ifdef COMPAT_FREEBSD32 | |||||
|| cmd == CIOCKEY32 | |||||
#endif | |||||
) { | |||||
/* NB: crypto core enforces s/w driver use */ | /* NB: crypto core enforces s/w driver use */ | ||||
kop->crk_crid = | kop->crk_crid = | ||||
CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE; | CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE; | ||||
} | } | ||||
mtx_lock(&Giant); | mtx_lock(&Giant); | ||||
error = cryptodev_key(kop); | error = cryptodev_key(kop); | ||||
mtx_unlock(&Giant); | mtx_unlock(&Giant); | ||||
#ifdef COMPAT_FREEBSD32 | |||||
if (cmd == CIOCKEY32 || cmd == CIOCKEY232) | |||||
crypt_kop_to_32(kop, data); | |||||
#endif | |||||
break; | break; | ||||
case CIOCASYMFEAT: | case CIOCASYMFEAT: | ||||
if (!crypto_userasymcrypto) { | if (!crypto_userasymcrypto) { | ||||
/* | /* | ||||
* NB: if user asym crypto operations are | * NB: if user asym crypto operations are | ||||
* not permitted return "no algorithms" | * not permitted return "no algorithms" | ||||
* so well-behaved applications will just | * so well-behaved applications will just | ||||
* fallback to doing them in software. | * fallback to doing them in software. | ||||
Show All 19 Lines | case CIOCCRYPTAEAD: | ||||
error = cryptodev_aead(cse, caead, active_cred, td); | error = cryptodev_aead(cse, caead, active_cred, td); | ||||
csefree(cse); | csefree(cse); | ||||
break; | break; | ||||
default: | default: | ||||
error = EINVAL; | error = EINVAL; | ||||
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); | SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); | ||||
break; | break; | ||||
} | } | ||||
#ifdef COMPAT_FREEBSD32 | |||||
switch (cmd32) { | |||||
case CIOCGSESSION32: | |||||
if (error == 0) | |||||
session_op_to_32(data, data32); | |||||
break; | |||||
case CIOCGSESSION232: | |||||
if (error == 0) | |||||
session2_op_to_32(data, data32); | |||||
break; | |||||
case CIOCCRYPT32: | |||||
if (error == 0) | |||||
crypt_op_to_32(data, data32); | |||||
break; | |||||
case CIOCKEY32: | |||||
case CIOCKEY232: | |||||
crypt_kop_to_32(data, data32); | |||||
break; | |||||
} | |||||
#endif | |||||
return (error); | return (error); | ||||
#undef SES2 | |||||
} | } | ||||
static int cryptodev_cb(struct cryptop *); | static int cryptodev_cb(struct cryptop *); | ||||
static struct cryptop_data * | static struct cryptop_data * | ||||
cod_alloc(struct csession *cse, size_t aad_len, size_t len, struct thread *td) | cod_alloc(struct csession *cse, size_t aad_len, size_t len, struct thread *td) | ||||
{ | { | ||||
struct cryptop_data *cod; | struct cryptop_data *cod; | ||||
▲ Show 20 Lines • Show All 792 Lines • Show Last 20 Lines |