From 4782e51e145180f446f9ee80c071d9dc27a8d508 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 29 Jul 2010 20:42:20 +0000 Subject: [PATCH] Add compat32 shims for opencrypto(4). Reviewed by: bz MFC after: 3 weeks --- sys/opencrypto/cryptodev.c | 273 ++++++++++++++++++++++++++++++++++++- 1 file changed, 266 insertions(+), 7 deletions(-) diff --git a/sys/opencrypto/cryptodev.c b/sys/opencrypto/cryptodev.c index 6ba4425adaab..ddc8e750b603 100644 --- a/sys/opencrypto/cryptodev.c +++ b/sys/opencrypto/cryptodev.c @@ -35,6 +35,8 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_compat.h" + #include #include #include @@ -56,6 +58,201 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef COMPAT_FREEBSD32 +#include +#include + +struct session_op32 { + u_int32_t cipher; + u_int32_t mac; + u_int32_t keylen; + u_int32_t key; + int mackeylen; + u_int32_t mackey; + u_int32_t ses; +}; + +struct session2_op32 { + u_int32_t cipher; + u_int32_t mac; + u_int32_t keylen; + u_int32_t key; + int mackeylen; + u_int32_t mackey; + u_int32_t ses; + int crid; + int pad[4]; +}; + +struct crypt_op32 { + u_int32_t ses; + u_int16_t op; + u_int16_t flags; + u_int len; + u_int32_t src, dst; + u_int32_t mac; + u_int32_t iv; +}; + +struct crparam32 { + u_int32_t crp_p; + u_int crp_nbits; +}; + +struct crypt_kop32 { + u_int crk_op; + u_int crk_status; + u_short crk_iparams; + u_short crk_oparams; + u_int crk_crid; + struct crparam32 crk_param[CRK_MAXPARAM]; +}; + +struct cryptotstat32 { + struct timespec32 acc; + struct timespec32 min; + struct timespec32 max; + u_int32_t count; +}; + +struct cryptostats32 { + u_int32_t cs_ops; + u_int32_t cs_errs; + u_int32_t cs_kops; + u_int32_t cs_kerrs; + u_int32_t cs_intrs; + u_int32_t cs_rets; + u_int32_t cs_blocks; + u_int32_t cs_kblocks; + struct cryptotstat32 cs_invoke; + struct cryptotstat32 cs_done; + struct cryptotstat32 cs_cb; + struct cryptotstat32 cs_finis; +}; + +#define CIOCGSESSION32 _IOWR('c', 101, struct session_op32) +#define CIOCCRYPT32 _IOWR('c', 103, struct crypt_op32) +#define CIOCKEY32 _IOWR('c', 104, struct crypt_kop32) +#define CIOCGSESSION232 _IOWR('c', 106, struct session2_op32) +#define CIOCKEY232 _IOWR('c', 107, struct crypt_kop32) + +static void +session_op_from_32(const struct session_op32 *from, struct session_op *to) +{ + + CP(*from, *to, cipher); + CP(*from, *to, mac); + CP(*from, *to, keylen); + PTRIN_CP(*from, *to, key); + CP(*from, *to, mackeylen); + PTRIN_CP(*from, *to, mackey); + CP(*from, *to, ses); +} + +static void +session2_op_from_32(const struct session2_op32 *from, struct session2_op *to) +{ + + session_op_from_32((const struct session_op32 *)from, + (struct session_op *)to); + CP(*from, *to, crid); +} + +static void +session_op_to_32(const struct session_op *from, struct session_op32 *to) +{ + + CP(*from, *to, cipher); + CP(*from, *to, mac); + CP(*from, *to, keylen); + PTROUT_CP(*from, *to, key); + CP(*from, *to, mackeylen); + PTROUT_CP(*from, *to, mackey); + CP(*from, *to, ses); +} + +static void +session2_op_to_32(const struct session2_op *from, struct session2_op32 *to) +{ + + session_op_to_32((const struct session_op *)from, + (struct session_op32 *)to); + CP(*from, *to, crid); +} + +static void +crypt_op_from_32(const struct crypt_op32 *from, struct crypt_op *to) +{ + + CP(*from, *to, ses); + CP(*from, *to, op); + CP(*from, *to, flags); + CP(*from, *to, len); + PTRIN_CP(*from, *to, src); + PTRIN_CP(*from, *to, dst); + PTRIN_CP(*from, *to, mac); + PTRIN_CP(*from, *to, iv); +} + +static void +crypt_op_to_32(const struct crypt_op *from, struct crypt_op32 *to) +{ + + CP(*from, *to, ses); + CP(*from, *to, op); + CP(*from, *to, flags); + CP(*from, *to, len); + PTROUT_CP(*from, *to, src); + PTROUT_CP(*from, *to, dst); + PTROUT_CP(*from, *to, mac); + PTROUT_CP(*from, *to, iv); +} + +static void +crparam_from_32(const struct crparam32 *from, struct crparam *to) +{ + + PTRIN_CP(*from, *to, crp_p); + CP(*from, *to, crp_nbits); +} + +static void +crparam_to_32(const struct crparam *from, struct crparam32 *to) +{ + + PTROUT_CP(*from, *to, crp_p); + CP(*from, *to, crp_nbits); +} + +static void +crypt_kop_from_32(const struct crypt_kop32 *from, struct crypt_kop *to) +{ + int i; + + CP(*from, *to, crk_op); + CP(*from, *to, crk_status); + CP(*from, *to, crk_iparams); + CP(*from, *to, crk_oparams); + CP(*from, *to, crk_crid); + for (i = 0; i < CRK_MAXPARAM; i++) + crparam_from_32(&from->crk_param[i], &to->crk_param[i]); +} + +static void +crypt_kop_to_32(const struct crypt_kop *from, struct crypt_kop32 *to) +{ + int i; + + CP(*from, *to, crk_op); + CP(*from, *to, crk_status); + CP(*from, *to, crk_iparams); + CP(*from, *to, crk_oparams); + CP(*from, *to, crk_crid); + for (i = 0; i < CRK_MAXPARAM; i++) + crparam_to_32(&from->crk_param[i], &to->crk_param[i]); +} +#endif + struct csession { TAILQ_ENTRY(csession) next; u_int64_t sid; @@ -180,11 +377,27 @@ cryptof_ioctl( u_int64_t sid; u_int32_t ses; int error = 0, crid; +#ifdef COMPAT_FREEBSD32 + struct session2_op sopc; + struct crypt_op copc; + struct crypt_kop kopc; +#endif switch (cmd) { case CIOCGSESSION: case CIOCGSESSION2: - sop = (struct session_op *)data; +#ifdef COMPAT_FREEBSD32 + case CIOCGSESSION32: + case CIOCGSESSION232: + if (cmd == CIOCGSESSION32) { + session_op_from_32(data, (struct session_op *)&sopc); + sop = (struct session_op *)&sopc; + } else if (cmd == CIOCGSESSION232) { + session2_op_from_32(data, &sopc); + sop = (struct session_op *)&sopc; + } else +#endif + sop = (struct session_op *)data; switch (sop->cipher) { case 0: break; @@ -294,7 +507,11 @@ cryptof_ioctl( } /* NB: CIOGSESSION2 has the crid */ - if (cmd == CIOCGSESSION2) { + if (cmd == CIOCGSESSION2 +#ifdef COMPAT_FREEBSD32 + || cmd == CIOCGSESSION232 +#endif + ) { crid = SES2(sop)->crid; error = checkforsoftware(crid); if (error) @@ -315,7 +532,11 @@ cryptof_ioctl( goto bail; } sop->ses = cse->ses; - if (cmd == CIOCGSESSION2) { + if (cmd == CIOCGSESSION2 +#ifdef COMPAT_FREEBSD32 + || cmd == CIOCGSESSION232 +#endif + ) { /* return hardware/driver id */ SES2(sop)->crid = CRYPTO_SESID2HID(cse->sid); } @@ -326,6 +547,15 @@ cryptof_ioctl( if (cria.cri_key) free(cria.cri_key, M_XDATA); } +#ifdef COMPAT_FREEBSD32 + else { + if (cmd == CIOCGSESSION32) + session_op_to_32(sop, data); + else if (cmd == CIOCGSESSION232) + session2_op_to_32((struct session2_op *)sop, + data); + } +#endif break; case CIOCFSESSION: ses = *(u_int32_t *)data; @@ -336,25 +566,54 @@ cryptof_ioctl( error = csefree(cse); break; case CIOCCRYPT: - cop = (struct crypt_op *)data; +#ifdef COMPAT_FREEBSD32 + case CIOCCRYPT32: + if (cmd == CIOCCRYPT32) { + cop = &copc; + crypt_op_from_32(data, cop); + } else +#endif + cop = (struct crypt_op *)data; cse = csefind(fcr, cop->ses); if (cse == NULL) return (EINVAL); error = cryptodev_op(cse, cop, active_cred, td); +#ifdef COMPAT_FREEBSD32 + if (error == 0 && cmd == CIOCCRYPT32) + crypt_op_to_32(cop, data); +#endif break; case CIOCKEY: case CIOCKEY2: +#ifdef COMPAT_FREEBSD32 + case CIOCKEY32: + case CIOCKEY232: +#endif if (!crypto_userasymcrypto) return (EPERM); /* XXX compat? */ - mtx_lock(&Giant); - kop = (struct crypt_kop *)data; - if (cmd == CIOCKEY) { +#ifdef COMPAT_FREEBSD32 + if (cmd == CIOCKEY32 || cmd == CIOCKEY232) { + kop = &kopc; + crypt_kop_from_32(data, kop); + } else +#endif + kop = (struct crypt_kop *)data; + if (cmd == CIOCKEY +#ifdef COMPAT_FREEBSD32 + || cmd == CIOCKEY32 +#endif + ) { /* NB: crypto core enforces s/w driver use */ kop->crk_crid = CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE; } + mtx_lock(&Giant); error = cryptodev_key(kop); mtx_unlock(&Giant); +#ifdef COMPAT_FREEBSD32 + if (cmd == CIOCKEY32 || cmd == CIOCKEY232) + crypt_kop_to_32(kop, data); +#endif break; case CIOCASYMFEAT: if (!crypto_userasymcrypto) {