Author: jhb
Date: Wed Aug 26 21:17:18 2020
New Revision: 364838
URL: https://svnweb.freebsd.org/changeset/base/364838

Log:
  Simplify compat shims for /dev/crypto.
  
  - Make session handling always use the CIOGSESSION2 structure.
    CIOGSESSION requests use a thunk similar to COMPAT_FREEBSD32 session
    requests.  This permits the ioctl handler to use the 'crid' field
    unconditionally.
  
  - Move COMPAT_FREEBSD32 handling out of the main ioctl handler body
    and instead do conversions in/out of thunk structures in dedicated
    blocks at the start and end of the ioctl function.
  
  Reviewed by:  markj (earlier version)
  Sponsored by: Netflix
  Differential Revision:        https://reviews.freebsd.org/D26178

Modified:
  head/sys/opencrypto/cryptodev.c

Modified: head/sys/opencrypto/cryptodev.c
==============================================================================
--- head/sys/opencrypto/cryptodev.c     Wed Aug 26 21:13:36 2020        
(r364837)
+++ head/sys/opencrypto/cryptodev.c     Wed Aug 26 21:17:18 2020        
(r364838)
@@ -124,9 +124,10 @@ struct crypt_kop32 {
 #define        CIOCKEY232      _IOWR('c', 107, struct crypt_kop32)
 
 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, mac);
        CP(*from, *to, keylen);
@@ -134,19 +135,19 @@ session_op_from_32(const struct session_op32 *from, st
        CP(*from, *to, mackeylen);
        PTRIN_CP(*from, *to, mackey);
        CP(*from, *to, ses);
+       to->crid = CRYPTOCAP_F_HARDWARE;
 }
 
 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);
+       session_op_from_32((const struct session_op32 *)from, to);
        CP(*from, *to, crid);
 }
 
 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);
@@ -162,8 +163,7 @@ 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);
+       session_op_to_32(from, (struct session_op32 *)to);
        CP(*from, *to, crid);
 }
 
@@ -240,6 +240,22 @@ crypt_kop_to_32(const struct crypt_kop *from, struct c
 }
 #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 {
        TAILQ_ENTRY(csession) next;
        crypto_session_t cses;
@@ -354,11 +370,10 @@ cryptof_ioctl(
        struct ucred *active_cred,
        struct thread *td)
 {
-#define        SES2(p) ((struct session2_op *)p)
        struct crypto_session_params csp;
        struct fcrypt *fcr = fp->f_data;
        struct csession *cse;
-       struct session_op *sop;
+       struct session2_op *sop;
        struct crypt_op *cop;
        struct crypt_aead *caead;
        struct enc_xform *txform = NULL;
@@ -369,27 +384,64 @@ cryptof_ioctl(
        crypto_session_t cses;
        u_int32_t ses;
        int error = 0, crid;
+       union {
+               struct session2_op sopc;
 #ifdef COMPAT_FREEBSD32
-       struct session2_op sopc;
-       struct crypt_op copc;
-       struct crypt_kop kopc;
+               struct crypt_op copc;
+               struct crypt_kop kopc;
 #endif
+       };
+#ifdef COMPAT_FREEBSD32
+       u_long cmd32;
+       void *data32;
 
+       cmd32 = 0;
+       data32 = NULL;
        switch (cmd) {
-       case CIOCGSESSION:
-       case CIOCGSESSION2:
-#ifdef COMPAT_FREEBSD32
        case CIOCGSESSION32:
+               cmd32 = cmd;
+               data32 = data;
+               cmd = CIOCGSESSION;
+               data = &sopc;
+               session_op_from_32((struct session_op32 *)data32, &sopc);
+               break;
        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
+               cmd32 = cmd;
+               data32 = data;
+               cmd = CIOCGSESSION2;
+               data = &sopc;
+               session2_op_from_32((struct session2_op32 *)data32, &sopc);
+               break;
+       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
-                       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) {
                case 0:
                        break;
@@ -652,22 +704,14 @@ cryptof_ioctl(
                                csp.csp_ivlen = AES_CCM_IV_LEN;
                }
 
-               /* NB: CIOCGSESSION2 has the crid */
-               if (cmd == CIOCGSESSION2
-#ifdef COMPAT_FREEBSD32
-                   || cmd == CIOCGSESSION232
-#endif
-                       ) {
-                       crid = SES2(sop)->crid;
-                       error = checkforsoftware(&crid);
-                       if (error) {
-                               CRYPTDEB("checkforsoftware");
-                               SDT_PROBE1(opencrypto, dev, ioctl, error,
-                                   __LINE__);
-                               goto bail;
-                       }
-               } else
-                       crid = CRYPTOCAP_F_HARDWARE;
+               crid = sop->crid;
+               error = checkforsoftware(&crid);
+               if (error) {
+                       CRYPTDEB("checkforsoftware");
+                       SDT_PROBE1(opencrypto, dev, ioctl, error,
+                           __LINE__);
+                       goto bail;
+               }
                error = crypto_newsession(&cses, &csp, crid);
                if (error) {
                        CRYPTDEB("crypto_newsession");
@@ -685,28 +729,17 @@ cryptof_ioctl(
                        goto bail;
                }
                sop->ses = cse->ses;
-               if (cmd == CIOCGSESSION2
-#ifdef COMPAT_FREEBSD32
-                   || cmd == CIOCGSESSION232
-#endif
-                   ) {
-                       /* return hardware/driver id */
-                       SES2(sop)->crid = crypto_ses2hid(cse->cses);
-               }
+
+               /* return hardware/driver id */
+               sop->crid = crypto_ses2hid(cse->cses);
 bail:
                if (error) {
                        free(key, M_XDATA);
                        free(mackey, 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
+
+               if (cmd == CIOCGSESSION && error == 0)
+                       session2_op_to_op(sop, data);
                break;
        case CIOCFSESSION:
                ses = *(u_int32_t *)data;
@@ -716,14 +749,7 @@ bail:
                }
                break;
        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);
                if (cse == NULL) {
                        SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
@@ -731,33 +757,15 @@ bail:
                }
                error = cryptodev_op(cse, cop, active_cred, td);
                csefree(cse);
-#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) {
                        SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
                        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;
-               if (cmd == CIOCKEY
-#ifdef COMPAT_FREEBSD32
-                   || cmd == CIOCKEY32
-#endif
-                   ) {
+               kop = (struct crypt_kop *)data;
+               if (cmd == CIOCKEY) {
                        /* NB: crypto core enforces s/w driver use */
                        kop->crk_crid =
                            CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
@@ -765,10 +773,6 @@ bail:
                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) {
@@ -804,8 +808,28 @@ bail:
                SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
                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);
-#undef SES2
 }
 
 static int cryptodev_cb(struct cryptop *);
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to