* 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>
#include <sys/sysctl.h>
#include <opencrypto/cryptodev.h>
#include <opencrypto/xform.h>
-#else
-#include <strings.h>
#endif
#include <sys/zio_crypt.h>
/*
* 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
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
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
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;
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,
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 = { ");
#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;
}
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;
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++;
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,
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:
#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;
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;
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);
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,
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