]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/os/freebsd/zfs/crypto_os.c
freebsd: remove __FBSDID macro use
[mirror_zfs.git] / module / os / freebsd / zfs / crypto_os.c
index fbf998416234e90e6c6e8071e9aeb0429b1ff23d..ed8d2407613e2a5acfff90d35bdfdcd978968470 100644 (file)
@@ -27,9 +27,6 @@
  * Portions of this file are derived from sys/geom/eli/g_eli_hmac.c
  */
 
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
 #include <sys/types.h>
 #include <sys/errno.h>
 
@@ -39,8 +36,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/sysctl.h>
 #include <opencrypto/cryptodev.h>
 #include <opencrypto/xform.h>
-#else
-#include <strings.h>
 #endif
 
 #include <sys/zio_crypt.h>
@@ -69,11 +64,11 @@ crypto_mac_init(struct hmac_ctx *ctx, const crypto_key_t *c_key)
        /*
         * This code is based on the similar code in geom/eli/g_eli_hmac.c
         */
-       explicit_bzero(key, sizeof (key));
+       memset(key, 0, sizeof (key));
        if (c_key->ck_length  == 0)
                /* do nothing */;
        else if (cl_bytes <= SHA512_HMAC_BLOCK_SIZE)
-               bcopy(c_key->ck_data, key, cl_bytes);
+               memcpy(key, c_key->ck_data, cl_bytes);
        else {
                /*
                 * If key is longer than 128 bytes reset it to
@@ -89,16 +84,16 @@ crypto_mac_init(struct hmac_ctx *ctx, const crypto_key_t *c_key)
                k_ipad[i] = key[i] ^ 0x36;
                k_opad[i] = key[i] ^ 0x5c;
        }
-       explicit_bzero(key, sizeof (key));
+       memset(key, 0, sizeof (key));
 
        /* Start inner SHA512. */
        SHA512_Init(&ctx->innerctx);
        SHA512_Update(&ctx->innerctx, k_ipad, sizeof (k_ipad));
-       explicit_bzero(k_ipad, sizeof (k_ipad));
+       memset(k_ipad, 0, sizeof (k_ipad));
        /* Start outer SHA512. */
        SHA512_Init(&ctx->outerctx);
        SHA512_Update(&ctx->outerctx, k_opad, sizeof (k_opad));
-       explicit_bzero(k_opad, sizeof (k_opad));
+       memset(k_opad, 0, sizeof (k_opad));
 }
 
 void
@@ -119,12 +114,12 @@ crypto_mac_final(struct hmac_ctx *ctx, void *md, size_t mdsize)
        SHA512_Update(&ctx->outerctx, digest, sizeof (digest));
        SHA512_Final(digest, &ctx->outerctx);
 
-       explicit_bzero(ctx, sizeof (*ctx));
+       memset(ctx, 0, sizeof (*ctx));
        /* mdsize == 0 means "Give me the whole hash!" */
        if (mdsize == 0)
                mdsize = SHA512_DIGEST_LENGTH;
-       bcopy(digest, md, mdsize);
-       explicit_bzero(digest, sizeof (digest));
+       memcpy(md, digest, mdsize);
+       memset(digest, 0, sizeof (digest));
 }
 
 void
@@ -151,33 +146,52 @@ freebsd_zfs_crypt_done(struct cryptop *crp)
        return (0);
 }
 
+static int
+freebsd_zfs_crypt_done_sync(struct cryptop *crp)
+{
+
+       return (0);
+}
+
 void
 freebsd_crypt_freesession(freebsd_crypt_session_t *sess)
 {
        mtx_destroy(&sess->fs_lock);
        crypto_freesession(sess->fs_sid);
-       explicit_bzero(sess, sizeof (*sess));
+       memset(sess, 0, sizeof (*sess));
 }
 
 static int
-zfs_crypto_dispatch(freebsd_crypt_session_t *session,  struct cryptop *crp)
+zfs_crypto_dispatch(freebsd_crypt_session_t *session, struct cryptop *crp)
 {
        int error;
 
        crp->crp_opaque = session;
-       crp->crp_callback = freebsd_zfs_crypt_done;
        for (;;) {
+#if __FreeBSD_version < 1400004
+               boolean_t async = ((crypto_ses2caps(crp->crp_session) &
+                   CRYPTOCAP_F_SYNC) == 0);
+#else
+               boolean_t async = !CRYPTO_SESS_SYNC(crp->crp_session);
+#endif
+               crp->crp_callback = async ? freebsd_zfs_crypt_done :
+                   freebsd_zfs_crypt_done_sync;
                error = crypto_dispatch(crp);
-               if (error)
-                       break;
-               mtx_lock(&session->fs_lock);
-               while (session->fs_done == false)
-                       msleep(crp, &session->fs_lock, PRIBIO,
-                           "zfs_crypto", hz/5);
-               mtx_unlock(&session->fs_lock);
-
-               if (crp->crp_etype != EAGAIN) {
+               if (error == 0) {
+                       if (async) {
+                               mtx_lock(&session->fs_lock);
+                               while (session->fs_done == false) {
+                                       msleep(crp, &session->fs_lock, 0,
+                                           "zfs_crypto", 0);
+                               }
+                               mtx_unlock(&session->fs_lock);
+                       }
                        error = crp->crp_etype;
+               }
+
+               if (error == ENOMEM) {
+                       pause("zcrnomem", 1);
+               } else if (error != EAGAIN) {
                        break;
                }
                crp->crp_etype = 0;
@@ -196,7 +210,7 @@ zfs_crypto_dispatch(freebsd_crypt_session_t *session,       struct cryptop *crp)
 static void
 freebsd_crypt_uio_debug_log(boolean_t encrypt,
     freebsd_crypt_session_t *input_sessionp,
-    struct zio_crypt_info *c_info,
+    const struct zio_crypt_info *c_info,
     zfs_uio_t *data_uio,
     crypto_key_t *key,
     uint8_t *ivbuf,
@@ -208,12 +222,12 @@ freebsd_crypt_uio_debug_log(boolean_t encrypt,
        uint8_t *p = NULL;
        size_t total = 0;
 
-       printf("%s(%s, %p, { %s, %d, %d, %s }, %p, { %d, %p, %u }, "
+       printf("%s(%s, %p, { %s, %d, %d, %s }, %p, { %p, %u }, "
            "%p, %u, %u)\n",
            __FUNCTION__, encrypt ? "encrypt" : "decrypt", input_sessionp,
            c_info->ci_algname, c_info->ci_crypt_type,
            (unsigned int)c_info->ci_keylen, c_info->ci_name,
-           data_uio, key->ck_format, key->ck_data,
+           data_uio, key->ck_data,
            (unsigned int)key->ck_length,
            ivbuf, (unsigned int)datalen, (unsigned int)auth_len);
        printf("\tkey = { ");
@@ -239,17 +253,17 @@ freebsd_crypt_uio_debug_log(boolean_t encrypt,
 #if __FreeBSD_version >= 1300087
 int
 freebsd_crypt_newsession(freebsd_crypt_session_t *sessp,
-    struct zio_crypt_info *c_info, crypto_key_t *key)
+    const struct zio_crypt_info *c_info, crypto_key_t *key)
 {
-       struct crypto_session_params csp;
+       struct crypto_session_params csp = {0};
        int error = 0;
 
 #ifdef FCRYPTO_DEBUG
-       printf("%s(%p, { %s, %d, %d, %s }, { %d, %p, %u })\n",
+       printf("%s(%p, { %s, %d, %d, %s }, { %p, %u })\n",
            __FUNCTION__, sessp,
            c_info->ci_algname, c_info->ci_crypt_type,
            (unsigned int)c_info->ci_keylen, c_info->ci_name,
-           key->ck_format, key->ck_data, (unsigned int)key->ck_length);
+           key->ck_data, (unsigned int)key->ck_length);
        printf("\tkey = { ");
        for (int i = 0; i < key->ck_length / 8; i++) {
                uint8_t *b = (uint8_t *)key->ck_data;
@@ -257,7 +271,6 @@ freebsd_crypt_newsession(freebsd_crypt_session_t *sessp,
        }
        printf("}\n");
 #endif
-       bzero(&csp, sizeof (csp));
        csp.csp_mode = CSP_MODE_AEAD;
        csp.csp_cipher_key = key->ck_data;
        csp.csp_cipher_klen = key->ck_length / 8;
@@ -293,8 +306,19 @@ freebsd_crypt_newsession(freebsd_crypt_session_t *sessp,
                error = ENOTSUP;
                goto bad;
        }
-       error = crypto_newsession(&sessp->fs_sid, &csp,
-           CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE);
+
+       /*
+        * Disable the use of hardware drivers on FreeBSD 13 and later since
+        * common crypto offload drivers impose constraints on AES-GCM AAD
+        * lengths that make them unusable for ZFS, and we currently do not have
+        * a mechanism to fall back to a software driver for requests not
+        * handled by a hardware driver.
+        *
+        * On 12 we continue to permit the use of hardware drivers since
+        * CPU-accelerated drivers such as aesni(4) register themselves as
+        * hardware drivers.
+        */
+       error = crypto_newsession(&sessp->fs_sid, &csp, CRYPTOCAP_F_SOFTWARE);
        mtx_init(&sessp->fs_lock, "FreeBSD Cryptographic Session Lock",
            NULL, MTX_DEF);
        crypt_sessions++;
@@ -309,7 +333,7 @@ bad:
 int
 freebsd_crypt_uio(boolean_t encrypt,
     freebsd_crypt_session_t *input_sessionp,
-    struct zio_crypt_info *c_info,
+    const struct zio_crypt_info *c_info,
     zfs_uio_t *data_uio,
     crypto_key_t *key,
     uint8_t *ivbuf,
@@ -351,7 +375,7 @@ freebsd_crypt_uio(boolean_t encrypt,
        crp->crp_payload_length = datalen;
        crp->crp_digest_start = auth_len + datalen;
 
-       bcopy(ivbuf, crp->crp_iv, ZIO_DATA_IV_LEN);
+       memcpy(crp->crp_iv, ivbuf, ZIO_DATA_IV_LEN);
        error = zfs_crypto_dispatch(session, crp);
        crypto_freereq(crp);
 out:
@@ -369,20 +393,20 @@ out:
 #else
 int
 freebsd_crypt_newsession(freebsd_crypt_session_t *sessp,
-    struct zio_crypt_info *c_info, crypto_key_t *key)
+    const struct zio_crypt_info *c_info, crypto_key_t *key)
 {
-       struct cryptoini cria, crie, *crip;
+       struct cryptoini cria = {0}, crie = {0}, *crip;
        struct enc_xform *xform;
        struct auth_hash *xauth;
        int error = 0;
        crypto_session_t sid;
 
 #ifdef FCRYPTO_DEBUG
-       printf("%s(%p, { %s, %d, %d, %s }, { %d, %p, %u })\n",
+       printf("%s(%p, { %s, %d, %d, %s }, { %p, %u })\n",
            __FUNCTION__, sessp,
            c_info->ci_algname, c_info->ci_crypt_type,
            (unsigned int)c_info->ci_keylen, c_info->ci_name,
-           key->ck_format, key->ck_data, (unsigned int)key->ck_length);
+           key->ck_data, (unsigned int)key->ck_length);
        printf("\tkey = { ");
        for (int i = 0; i < key->ck_length / 8; i++) {
                uint8_t *b = (uint8_t *)key->ck_data;
@@ -439,9 +463,6 @@ freebsd_crypt_newsession(freebsd_crypt_session_t *sessp,
            xauth->name, xauth->keysize);
 #endif
 
-       bzero(&crie, sizeof (crie));
-       bzero(&cria, sizeof (cria));
-
        crie.cri_alg = xform->type;
        crie.cri_key = key->ck_data;
        crie.cri_klen = key->ck_length;
@@ -453,7 +474,7 @@ freebsd_crypt_newsession(freebsd_crypt_session_t *sessp,
        cria.cri_next = &crie;
        crie.cri_next = NULL;
        crip = &cria;
-       // Everything else is bzero'd
+       // Everything else is zero-initialised
 
        error = crypto_newsession(&sid, crip,
            CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE);
@@ -479,7 +500,7 @@ bad:
 int
 freebsd_crypt_uio(boolean_t encrypt,
     freebsd_crypt_session_t *input_sessionp,
-    struct zio_crypt_info *c_info,
+    const struct zio_crypt_info *c_info,
     zfs_uio_t *data_uio,
     crypto_key_t *key,
     uint8_t *ivbuf,
@@ -582,7 +603,7 @@ freebsd_crypt_uio(boolean_t encrypt,
        enc_desc->crd_inject = auth_len;
        enc_desc->crd_alg = xform->type;
        enc_desc->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
-       bcopy(ivbuf, enc_desc->crd_iv, ZIO_DATA_IV_LEN);
+       memcpy(enc_desc->crd_iv, ivbuf, ZIO_DATA_IV_LEN);
        enc_desc->crd_next = NULL;
 
 #ifdef FCRYPTO_DEBUG