diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c index ec5d1acacf85..ec7bcf9daa3f 100644 --- a/cmd/zdb/zdb.c +++ b/cmd/zdb/zdb.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -3033,7 +3034,8 @@ static char *key_material = NULL; static boolean_t zdb_derive_key(dsl_dir_t *dd, uint8_t *key_out) { - uint64_t keyformat, salt, iters; + uint64_t keyformat, salt, iters, key_kdf; + uint64_t argon2_t_cost, argon2_m_cost, argon2_parallelism, argon2_version; int i; unsigned char c; @@ -3055,16 +3057,47 @@ zdb_derive_key(dsl_dir_t *dd, uint8_t *key_out) case ZFS_KEYFORMAT_PASSPHRASE: VERIFY0(zap_lookup(dd->dd_pool->dp_meta_objset, - dd->dd_crypto_obj, zfs_prop_to_name(ZFS_PROP_PBKDF2_SALT), - sizeof (uint64_t), 1, &salt)); - VERIFY0(zap_lookup(dd->dd_pool->dp_meta_objset, - dd->dd_crypto_obj, zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), - sizeof (uint64_t), 1, &iters)); - - if (PKCS5_PBKDF2_HMAC_SHA1(key_material, strlen(key_material), - ((uint8_t *)&salt), sizeof (uint64_t), iters, - WRAPPING_KEY_LEN, key_out) != 1) - return (B_FALSE); + dd->dd_crypto_obj, zfs_prop_to_name(ZFS_PROP_KEY_KDF), + sizeof (uint64_t), 1, &key_kdf)); + if (key_kdf == ZFS_KEY_KDF_PBKDF2 || key_kdf == ZFS_KEY_KDF_NONE) { + VERIFY0(zap_lookup(dd->dd_pool->dp_meta_objset, + dd->dd_crypto_obj, zfs_prop_to_name(ZFS_PROP_PBKDF2_SALT), + sizeof (uint64_t), 1, &salt)); + VERIFY0(zap_lookup(dd->dd_pool->dp_meta_objset, + dd->dd_crypto_obj, zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), + sizeof (uint64_t), 1, &iters)); + + if (PKCS5_PBKDF2_HMAC_SHA1(key_material, strlen(key_material), + ((uint8_t *)&salt), sizeof (uint64_t), iters, + WRAPPING_KEY_LEN, key_out) != 1) + return (B_FALSE); + } else if (key_kdf == ZFS_KEY_KDF_ARGON2ID) { + VERIFY0(zap_lookup(dd->dd_pool->dp_meta_objset, + dd->dd_crypto_obj, zfs_prop_to_name(ZFS_PROP_ARGON2_T_COST), + sizeof (uint64_t), 1, &argon2_t_cost)); + VERIFY0(zap_lookup(dd->dd_pool->dp_meta_objset, + dd->dd_crypto_obj, zfs_prop_to_name(ZFS_PROP_ARGON2_M_COST), + sizeof (uint64_t), 1, &argon2_m_cost)); + VERIFY0(zap_lookup(dd->dd_pool->dp_meta_objset, + dd->dd_crypto_obj, zfs_prop_to_name(ZFS_PROP_ARGON2_PARALLELISM), + sizeof (uint64_t), 1, &argon2_parallelism)); + VERIFY0(zap_lookup(dd->dd_pool->dp_meta_objset, + dd->dd_crypto_obj, zfs_prop_to_name(ZFS_PROP_ARGON2_VERSION), + sizeof (uint64_t), 1, &argon2_version)); + + if (argon2_hash(argon2_t_cost, argon2_m_cost, + argon2_parallelism, key_material, + strlen((char *)key_material), &salt, sizeof (uint64_t), + key_out, WRAPPING_KEY_LEN, NULL, + 0, Argon2_id, + argon2_version) + != ARGON2_OK) + return (B_FALSE); + } else { + fatal("no support for kdf %u\n", + (unsigned int) key_kdf); + return (B_TRUE); + } break; diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index e28f1d04f350..611850014797 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -413,7 +413,7 @@ get_usage(zfs_help_t idx) "<-a | filesystem|volume>\n")); case HELP_CHANGE_KEY: return (gettext("\tchange-key [-l] [-o keyformat=]\n" - "\t [-o keylocation=] [-o pbkdf2iters=]\n" + "\t [-o keylocation=] [-o pbkdf2iters=] [-o keykdf=] [-o argon2_t_cost=] [-o argon2_m_cost=] [-o argon2_parallelism=]\n" "\t \n" "\tchange-key -i [-l] \n")); case HELP_VERSION: diff --git a/cmd/ztest.c b/cmd/ztest.c index b6b99bfff6db..99996daf3c0a 100644 --- a/cmd/ztest.c +++ b/cmd/ztest.c @@ -4206,6 +4206,8 @@ ztest_dataset_create(char *dsname) zfs_prop_to_name(ZFS_PROP_KEYFORMAT), ZFS_KEYFORMAT_RAW); fnvlist_add_string(props, zfs_prop_to_name(ZFS_PROP_KEYLOCATION), "prompt"); + fnvlist_add_uint64(props, + zfs_prop_to_name(ZFS_PROP_KEY_KDF), ZFS_KEY_KDF_PBKDF2); fnvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_PBKDF2_SALT), 0ULL); fnvlist_add_uint64(props, diff --git a/config/user-libcrypto.m4 b/config/user-libcrypto.m4 index 7293e1b0b42c..2bea4bbd4e9c 100644 --- a/config/user-libcrypto.m4 +++ b/config/user-libcrypto.m4 @@ -2,7 +2,18 @@ dnl # dnl # Check for libcrypto. Used for userspace password derivation via PBKDF2. dnl # AC_DEFUN([ZFS_AC_CONFIG_USER_LIBCRYPTO], [ - ZFS_AC_FIND_SYSTEM_LIBRARY(LIBCRYPTO, [libcrypto], [openssl/evp.h], [], [crypto], [PKCS5_PBKDF2_HMAC_SHA1], [], [ - AC_MSG_FAILURE([ - *** evp.h missing, libssl-devel package required])]) +# ZFS_AC_FIND_SYSTEM_LIBRARY(LIBCRYPTO, [libcrypto], [openssl/evp.h], [], [crypto], [PKCS5_PBKDF2_HMAC_SHA1], [], [ +# AC_MSG_FAILURE([ +# *** evp.h missing, libssl-devel package required])]) + +ZFS_AC_FIND_SYSTEM_LIBRARY(LIBCRYPTO_SSL, [libcrypto], [openssl/evp.h], [], [crypto], [PKCS5_PBKDF2_HMAC_SHA1], [], [ + AC_MSG_FAILURE([*** evp.h missing, libssl-devel package required])]) +ZFS_AC_FIND_SYSTEM_LIBRARY(LIBCRYPTO_ARGON2, [libargon2], [argon2.h], [], [argon2], [argon2id_hash_raw], [], [ + AC_MSG_FAILURE([*** libargon2-dev package required])]) + +LIBCRYPTO_CFLAGS="$LIBCRYPTO_SSL_CFLAGS $LIBCRYPTO_ARGON2_CFLAGS" +LIBCRYPTO_LIBS="$LIBCRYPTO_SSL_LIBS $LIBCRYPTO_ARGON2_LIBS" +AC_SUBST(LIBCRYPTO_CFLAGS, []) +AC_SUBST(LIBCRYPTO_LIBS, []) ]) + diff --git a/contrib/pam_zfs_key/pam_zfs_key.c b/contrib/pam_zfs_key/pam_zfs_key.c index 27c7d63781c5..030fc2a66249 100644 --- a/contrib/pam_zfs_key/pam_zfs_key.c +++ b/contrib/pam_zfs_key/pam_zfs_key.c @@ -346,6 +346,15 @@ change_key(pam_handle_t *pamh, const char *ds_name, zfs_close(ds); return (-1); } + if (nvlist_add_uint64(nvlist, + zfs_prop_to_name(ZFS_PROP_KEY_KDF), + ZFS_KEY_KDF_PBKDF2)) { + pam_syslog(pamh, LOG_ERR, "nvlist_add failed for key_kdf"); + pw_free(key); + nvlist_free(nvlist); + zfs_close(ds); + return (-1); + } if (nvlist_add_uint64(nvlist, zfs_prop_to_name(ZFS_PROP_KEYFORMAT), ZFS_KEYFORMAT_PASSPHRASE)) { diff --git a/include/sys/dsl_crypt.h b/include/sys/dsl_crypt.h index 72716e296c9e..14a550c3cd06 100644 --- a/include/sys/dsl_crypt.h +++ b/include/sys/dsl_crypt.h @@ -49,6 +49,9 @@ typedef struct dsl_wrapping_key { /* link on spa_keystore_t:sk_wkeys */ avl_node_t wk_avl_link; + /* key kdf algorithm */ + uint64_t wk_key_kdf; + /* keyformat property enum */ zfs_keyformat_t wk_keyformat; @@ -58,6 +61,18 @@ typedef struct dsl_wrapping_key { /* the pbkdf2 iterations, if the keyformat is of type passphrase */ uint64_t wk_iters; + /* key kdf algorithm */ + uint64_t wk_argon2_t_cost; + + /* key kdf algorithm */ + uint64_t wk_argon2_m_cost; + + /* key kdf algorithm */ + uint64_t wk_argon2_parallelism; + + /* key kdf algorithm */ + uint64_t wk_argon2_version; + /* actual wrapping key */ crypto_key_t wk_key; diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h index 0734ff12280e..95291486ded3 100644 --- a/include/sys/fs/zfs.h +++ b/include/sys/fs/zfs.h @@ -191,6 +191,11 @@ typedef enum { ZFS_PROP_REDACTED, ZFS_PROP_REDACT_SNAPS, ZFS_PROP_SNAPSHOTS_CHANGED, + ZFS_PROP_KEY_KDF, + ZFS_PROP_ARGON2_T_COST, + ZFS_PROP_ARGON2_M_COST, + ZFS_PROP_ARGON2_PARALLELISM, + ZFS_PROP_ARGON2_VERSION, ZFS_NUM_PROPS } zfs_prop_t; @@ -543,9 +548,20 @@ typedef enum zfs_key_location { ZFS_KEYLOCATION_LOCATIONS } zfs_keylocation_t; +typedef enum zfs_key_kdf { + ZFS_KEY_KDF_NONE = 0, + ZFS_KEY_KDF_PBKDF2, + ZFS_KEY_KDF_ARGON2ID, +} zfs_key_kdf_t; + #define DEFAULT_PBKDF2_ITERATIONS 350000 #define MIN_PBKDF2_ITERATIONS 100000 +#define DEFAULT_ARGON2_T_COST 4 +#define DEFAULT_ARGON2_M_COST (1<<19) +#define DEFAULT_ARGON2_PARALLELISM 4 +#define DEFAULT_ARGON2_VERSION ARGON2_VERSION_13 + /* * On-disk version number. */ diff --git a/lib/libzfs/libzfs.abi b/lib/libzfs/libzfs.abi index 732863dcffc7..e399c11c1462 100644 --- a/lib/libzfs/libzfs.abi +++ b/lib/libzfs/libzfs.abi @@ -1862,7 +1862,12 @@ - + + + + + + diff --git a/lib/libzfs/libzfs_crypto.c b/lib/libzfs/libzfs_crypto.c index 8f2a50d55e87..7f2dc0ef266c 100644 --- a/lib/libzfs/libzfs_crypto.c +++ b/lib/libzfs/libzfs_crypto.c @@ -26,6 +26,7 @@ #include #include #include +#include #if LIBFETCH_DYNAMIC #include #endif @@ -775,7 +776,8 @@ get_key_material(libzfs_handle_t *hdl, boolean_t do_verify, boolean_t newkey, static int derive_key(libzfs_handle_t *hdl, zfs_keyformat_t format, uint64_t iters, uint8_t *key_material, uint64_t salt, - uint8_t **key_out) + zfs_key_kdf_t key_kdf, uint64_t argon2_t_cost, uint64_t argon2_m_cost, + uint64_t argon2_parallelism, uint64_t argon2_version, uint8_t **key_out) { int ret; uint8_t *key; @@ -799,11 +801,27 @@ derive_key(libzfs_handle_t *hdl, zfs_keyformat_t format, uint64_t iters, break; case ZFS_KEYFORMAT_PASSPHRASE: salt = LE_64(salt); + ret = 0; - ret = PKCS5_PBKDF2_HMAC_SHA1((char *)key_material, - strlen((char *)key_material), ((uint8_t *)&salt), - sizeof (uint64_t), iters, WRAPPING_KEY_LEN, key); - if (ret != 1) { + if (key_kdf == ZFS_KEY_KDF_PBKDF2) { + ret = PKCS5_PBKDF2_HMAC_SHA1((char *)key_material, + strlen((char *)key_material), ((uint8_t *)&salt), + sizeof (uint64_t), iters, WRAPPING_KEY_LEN, key) != 1; + } else if (key_kdf == ZFS_KEY_KDF_ARGON2ID) { + ret = argon2_hash(argon2_t_cost, argon2_m_cost, + argon2_parallelism, key_material, + strlen((char *)key_material), &salt, sizeof (uint64_t), + key, WRAPPING_KEY_LEN, NULL, + 0, Argon2_id, + argon2_version) + != ARGON2_OK; + } else { + ret = EINVAL; + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "KDF not supported")); + goto error; + } + if (ret) { ret = EIO; zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Failed to generate key from passphrase.")); @@ -846,14 +864,39 @@ encryption_feature_is_enabled(zpool_handle_t *zph) return (B_TRUE); } +static int +check_and_add_encryption_param_to_nvlist(libzfs_handle_t *hdl, + nvlist_t *props, zfs_prop_t prop, uint64_t *value, uint64_t default_value, + const char *error_msg) +{ + int ret; + ret = nvlist_lookup_uint64(props, + zfs_prop_to_name(prop), value); + if (ret == ENOENT) { + *value = default_value; + ret = nvlist_add_uint64(props, + zfs_prop_to_name(prop), *value); + if (ret != 0) + return (ret); + } else if (ret != 0) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + error_msg)); + return (ret); + } + return (0); +} + static int populate_create_encryption_params_nvlists(libzfs_handle_t *hdl, zfs_handle_t *zhp, boolean_t newkey, zfs_keyformat_t keyformat, - const char *keylocation, nvlist_t *props, uint8_t **wkeydata, + const char *keylocation, zfs_key_kdf_t key_kdf, + nvlist_t *props, uint8_t **wkeydata, uint_t *wkeylen) { int ret; uint64_t iters = 0, salt = 0; + uint64_t argon2_t_cost = 0, argon2_m_cost = 0, argon2_parallelism = 0; + uint64_t argon2_version = 0; uint8_t *key_material = NULL; size_t key_material_len = 0; uint8_t *key_data = NULL; @@ -883,24 +926,34 @@ populate_create_encryption_params_nvlists(libzfs_handle_t *hdl, goto error; } - /* - * If not otherwise specified, use the default number of - * pbkdf2 iterations. If specified, we have already checked - * that the given value is greater than MIN_PBKDF2_ITERATIONS - * during zfs_valid_proplist(). - */ - ret = nvlist_lookup_uint64(props, - zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), &iters); - if (ret == ENOENT) { - iters = DEFAULT_PBKDF2_ITERATIONS; - ret = nvlist_add_uint64(props, - zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), iters); - if (ret != 0) + if (key_kdf == ZFS_KEY_KDF_PBKDF2) { + /* + * If not otherwise specified, use the default number of + * pbkdf2 iterations. If specified, we have already checked + * that the given value is greater than MIN_PBKDF2_ITERATIONS + * during zfs_valid_proplist(). + */ + if (check_and_add_encryption_param_to_nvlist(hdl, props, + ZFS_PROP_PBKDF2_ITERS, &iters, DEFAULT_PBKDF2_ITERATIONS, + "Failed to get argon2_t_cost")) + goto error; + } else if (key_kdf == ZFS_KEY_KDF_ARGON2ID) { + if (check_and_add_encryption_param_to_nvlist(hdl, props, + ZFS_PROP_ARGON2_T_COST, &argon2_t_cost, DEFAULT_ARGON2_T_COST, + "Failed to get argon2_t_cost")) + goto error; + if (check_and_add_encryption_param_to_nvlist(hdl, props, + ZFS_PROP_ARGON2_M_COST, &argon2_m_cost, DEFAULT_ARGON2_M_COST, + "Failed to get argon2_m_cost")) + goto error; + if (check_and_add_encryption_param_to_nvlist(hdl, props, + ZFS_PROP_ARGON2_PARALLELISM, &argon2_parallelism, DEFAULT_ARGON2_PARALLELISM, + "Failed to get argon2_parallelism")) + goto error; + if (check_and_add_encryption_param_to_nvlist(hdl, props, + ZFS_PROP_ARGON2_VERSION, &argon2_version, DEFAULT_ARGON2_VERSION, + "Failed to get argon2_version")) goto error; - } else if (ret != 0) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "Failed to get pbkdf2 iterations.")); - goto error; } } else { /* check that pbkdf2iters was not specified by the user */ @@ -916,7 +969,9 @@ populate_create_encryption_params_nvlists(libzfs_handle_t *hdl, } /* derive a key from the key material */ - ret = derive_key(hdl, keyformat, iters, key_material, salt, &key_data); + ret = derive_key(hdl, keyformat, iters, key_material, salt, + key_kdf, argon2_t_cost, argon2_m_cost, argon2_parallelism, argon2_version, + &key_data); if (ret != 0) goto error; @@ -964,6 +1019,31 @@ proplist_has_encryption_props(nvlist_t *props) if (ret == 0) return (B_TRUE); + ret = nvlist_lookup_uint64(props, + zfs_prop_to_name(ZFS_PROP_KEY_KDF), &intval); + if (ret == 0 && intval != ZFS_KEY_KDF_NONE) + return (B_TRUE); + + ret = nvlist_lookup_uint64(props, + zfs_prop_to_name(ZFS_PROP_ARGON2_T_COST), &intval); + if (ret == 0) + return (B_TRUE); + + ret = nvlist_lookup_uint64(props, + zfs_prop_to_name(ZFS_PROP_ARGON2_M_COST), &intval); + if (ret == 0) + return (B_TRUE); + + ret = nvlist_lookup_uint64(props, + zfs_prop_to_name(ZFS_PROP_ARGON2_PARALLELISM), &intval); + if (ret == 0) + return (B_TRUE); + + ret = nvlist_lookup_uint64(props, + zfs_prop_to_name(ZFS_PROP_ARGON2_VERSION), &intval); + if (ret == 0) + return (B_TRUE); + return (B_FALSE); } @@ -1007,6 +1087,7 @@ zfs_crypto_create(libzfs_handle_t *hdl, char *parent_name, nvlist_t *props, char errbuf[ERRBUFLEN]; uint64_t crypt = ZIO_CRYPT_INHERIT, pcrypt = ZIO_CRYPT_INHERIT; uint64_t keyformat = ZFS_KEYFORMAT_NONE; + uint64_t key_kdf = ZFS_KEY_KDF_NONE; const char *keylocation = NULL; zfs_handle_t *pzhp = NULL; uint8_t *wkeydata = NULL; @@ -1027,6 +1108,8 @@ zfs_crypto_create(libzfs_handle_t *hdl, char *parent_name, nvlist_t *props, zfs_prop_to_name(ZFS_PROP_KEYFORMAT), &keyformat); (void) nvlist_lookup_string(props, zfs_prop_to_name(ZFS_PROP_KEYLOCATION), &keylocation); + (void) nvlist_lookup_uint64(props, + zfs_prop_to_name(ZFS_PROP_KEY_KDF), &key_kdf); if (parent_name != NULL) { /* get a reference to parent dataset */ @@ -1129,6 +1212,15 @@ zfs_crypto_create(libzfs_handle_t *hdl, char *parent_name, nvlist_t *props, goto out; } + if (key_kdf == ZFS_KEY_KDF_NONE) { + /* default kdf is set to PBKDF2 if no KDF is specified */ + key_kdf = ZFS_KEY_KDF_PBKDF2; + ret = nvlist_add_uint64(props, + zfs_prop_to_name(ZFS_PROP_KEY_KDF), key_kdf); + if (ret != 0) + goto out; + } + /* * If a local key is provided, this dataset will be a new * encryption root. Populate the encryption params. @@ -1146,7 +1238,7 @@ zfs_crypto_create(libzfs_handle_t *hdl, char *parent_name, nvlist_t *props, } ret = populate_create_encryption_params_nvlists(hdl, NULL, - B_TRUE, keyformat, keylocation, props, &wkeydata, + B_TRUE, keyformat, keylocation, key_kdf, props, &wkeydata, &wkeylen); if (ret != 0) goto out; @@ -1186,6 +1278,11 @@ zfs_crypto_clone_check(libzfs_handle_t *hdl, zfs_handle_t *origin_zhp, */ if (nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_KEYFORMAT)) || nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_KEYLOCATION)) || + nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_KEY_KDF)) || + nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_ARGON2_T_COST)) || + nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_ARGON2_M_COST)) || + nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_ARGON2_PARALLELISM)) || + nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_ARGON2_VERSION)) || nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_ENCRYPTION)) || nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS))) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, @@ -1280,6 +1377,8 @@ zfs_crypto_load_key(zfs_handle_t *zhp, boolean_t noop, char errbuf[ERRBUFLEN]; uint64_t keystatus, iters = 0, salt = 0; uint64_t keyformat = ZFS_KEYFORMAT_NONE; + zfs_key_kdf_t key_kdf = ZFS_KEY_KDF_NONE; + uint64_t argon2_t_cost = 0, argon2_m_cost = 0, argon2_parallelism = 0, argon2_version = 0; char prop_keylocation[MAXNAMELEN]; char prop_encroot[MAXNAMELEN]; const char *keylocation = NULL; @@ -1358,7 +1457,24 @@ zfs_crypto_load_key(zfs_handle_t *zhp, boolean_t noop, /* passphrase formats require a salt and pbkdf2_iters property */ if (keyformat == ZFS_KEYFORMAT_PASSPHRASE) { salt = zfs_prop_get_int(zhp, ZFS_PROP_PBKDF2_SALT); - iters = zfs_prop_get_int(zhp, ZFS_PROP_PBKDF2_ITERS); + key_kdf = zfs_prop_get_int(zhp, ZFS_PROP_KEY_KDF); + /* + * the old kdf is PBKDF2 if no upgrade is performed the dataset is encrypted + * but no kdf is set, the iters are not loaded correctly. + */ + if (key_kdf == ZFS_KEY_KDF_PBKDF2 || key_kdf == ZFS_KEY_KDF_NONE) { + key_kdf = ZFS_KEY_KDF_PBKDF2; + iters = zfs_prop_get_int(zhp, ZFS_PROP_PBKDF2_ITERS); + } else if (key_kdf == ZFS_KEY_KDF_ARGON2ID) { + argon2_t_cost = zfs_prop_get_int(zhp, ZFS_PROP_ARGON2_T_COST); + argon2_m_cost = zfs_prop_get_int(zhp, ZFS_PROP_ARGON2_M_COST); + argon2_parallelism = zfs_prop_get_int(zhp, ZFS_PROP_ARGON2_PARALLELISM); + argon2_version = zfs_prop_get_int(zhp, ZFS_PROP_ARGON2_VERSION); + } else { + zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, + "No KDF fits.")); + goto error; + } } try_again: @@ -1374,6 +1490,7 @@ zfs_crypto_load_key(zfs_handle_t *zhp, boolean_t noop, /* derive a key from the key material */ ret = derive_key(zhp->zfs_hdl, keyformat, iters, key_material, salt, + key_kdf, argon2_t_cost, argon2_m_cost, argon2_parallelism, argon2_version, &key_data); if (ret != 0) goto error; @@ -1555,11 +1672,15 @@ zfs_crypto_verify_rewrap_nvlist(zfs_handle_t *zhp, nvlist_t *props, case ZFS_PROP_PBKDF2_ITERS: case ZFS_PROP_KEYFORMAT: case ZFS_PROP_KEYLOCATION: + case ZFS_PROP_KEY_KDF: + case ZFS_PROP_ARGON2_T_COST: + case ZFS_PROP_ARGON2_M_COST: + case ZFS_PROP_ARGON2_PARALLELISM: break; default: ret = EINVAL; zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, - "Only keyformat, keylocation and pbkdf2iters may " + "Only keyformat, keylocation and pbkdf2iters, keykdf, argon2_t_cost, argon2_m_cost, argon2_parallelism may " "be set with this command.")); goto error; } @@ -1594,6 +1715,7 @@ zfs_crypto_rewrap(zfs_handle_t *zhp, nvlist_t *raw_props, boolean_t inheritkey) dcp_cmd_t cmd = (inheritkey) ? DCP_CMD_INHERIT : DCP_CMD_NEW_KEY; uint64_t crypt, pcrypt, keystatus, pkeystatus; uint64_t keyformat = ZFS_KEYFORMAT_NONE; + uint64_t key_kdf = ZFS_KEY_KDF_NONE; zfs_handle_t *pzhp = NULL; const char *keylocation = NULL; char origin_name[MAXNAMELEN]; @@ -1658,8 +1780,20 @@ zfs_crypto_rewrap(zfs_handle_t *zhp, nvlist_t *raw_props, boolean_t inheritkey) zfs_prop_to_name(ZFS_PROP_KEYFORMAT), &keyformat); (void) nvlist_lookup_string(props, zfs_prop_to_name(ZFS_PROP_KEYLOCATION), &keylocation); + (void) nvlist_lookup_uint64(props, + zfs_prop_to_name(ZFS_PROP_KEY_KDF), &key_kdf); + + if (key_kdf == ZFS_KEY_KDF_NONE) { + /* default kdf is set to PBKDF2 if no KDF is specified */ + key_kdf = ZFS_KEY_KDF_PBKDF2; + ret = nvlist_add_uint64(props, + zfs_prop_to_name(ZFS_PROP_KEY_KDF), key_kdf); + if (ret != 0) + goto error; + } if (is_encroot) { + // TODO keep existing settings if root is enc /* * If this is already an encryption root, just keep * any properties not set by the user. @@ -1716,7 +1850,7 @@ zfs_crypto_rewrap(zfs_handle_t *zhp, nvlist_t *raw_props, boolean_t inheritkey) /* fetch the new wrapping key and associated properties */ ret = populate_create_encryption_params_nvlists(zhp->zfs_hdl, - zhp, B_TRUE, keyformat, keylocation, props, &wkeydata, + zhp, B_TRUE, keyformat, keylocation, key_kdf, props, &wkeydata, &wkeylen); if (ret != 0) goto error; diff --git a/module/zcommon/zfs_prop.c b/module/zcommon/zfs_prop.c index 3db6fd13f4ae..174d4762fa8a 100644 --- a/module/zcommon/zfs_prop.c +++ b/module/zcommon/zfs_prop.c @@ -226,6 +226,13 @@ zfs_prop_init(void) { NULL } }; + static const zprop_index_t key_kdf_table[] = { + { "none", ZFS_KEY_KDF_NONE }, + { "PBKDF2", ZFS_KEY_KDF_PBKDF2 }, + { "Argon2id", ZFS_KEY_KDF_ARGON2ID }, + { NULL } + }; + static const zprop_index_t keyformat_table[] = { { "none", ZFS_KEYFORMAT_NONE }, { "raw", ZFS_KEYFORMAT_RAW }, @@ -533,6 +540,11 @@ zfs_prop_init(void) ZFS_CASE_SENSITIVE, PROP_ONETIME, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "sensitive | insensitive | mixed", "CASE", case_table, sfeatures); + zprop_register_index(ZFS_PROP_KEY_KDF, "keykdf", + ZFS_KEY_KDF_NONE, PROP_ONETIME_DEFAULT, + ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, + "none | PBKDF2 | Argon2id", "KEYKDF", key_kdf_table, + sfeatures); zprop_register_index(ZFS_PROP_KEYFORMAT, "keyformat", ZFS_KEYFORMAT_NONE, PROP_ONETIME_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, @@ -655,6 +667,15 @@ zfs_prop_init(void) zprop_register_number(ZFS_PROP_PBKDF2_ITERS, "pbkdf2iters", 0, PROP_ONETIME_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "", "PBKDF2ITERS", B_TRUE, sfeatures); + zprop_register_number(ZFS_PROP_ARGON2_T_COST, "argon2_t_cost", + 0, PROP_ONETIME_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, + "", "ARGON2TCOST", B_TRUE, sfeatures); + zprop_register_number(ZFS_PROP_ARGON2_M_COST, "argon2_m_cost", + 0, PROP_ONETIME_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, + "", "ARGON2MCOST", B_TRUE, sfeatures); + zprop_register_number(ZFS_PROP_ARGON2_PARALLELISM, "argon2_parallelism", + 0, PROP_ONETIME_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, + "", "ARGON2PARALLELISM", B_TRUE, sfeatures); zprop_register_number(ZFS_PROP_OBJSETID, "objsetid", 0, PROP_READONLY, ZFS_TYPE_DATASET, "", "OBJSETID", B_TRUE, sfeatures); @@ -722,6 +743,10 @@ zfs_prop_init(void) PROP_TYPE_NUMBER, PROP_ONETIME_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "PBKDF2SALT", B_FALSE, sfeatures); + zprop_register_hidden(ZFS_PROP_ARGON2_VERSION, "argon2_version", + PROP_TYPE_NUMBER, PROP_ONETIME_DEFAULT, + ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "ARGON2VERISON", B_FALSE, + sfeatures); zprop_register_hidden(ZFS_PROP_KEY_GUID, "keyguid", PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_DATASET, "KEYGUID", B_TRUE, sfeatures); zprop_register_hidden(ZFS_PROP_REDACTED, "redacted", PROP_TYPE_NUMBER, @@ -958,7 +983,8 @@ zfs_prop_encryption_key_param(zfs_prop_t prop) * changed at will without needing the master keys. */ return (prop == ZFS_PROP_PBKDF2_SALT || prop == ZFS_PROP_PBKDF2_ITERS || - prop == ZFS_PROP_KEYFORMAT); + prop == ZFS_PROP_KEYFORMAT || prop == ZFS_PROP_KEY_KDF || prop == ZFS_PROP_ARGON2_T_COST || + prop == ZFS_PROP_ARGON2_M_COST || prop == ZFS_PROP_ARGON2_PARALLELISM || prop == ZFS_PROP_ARGON2_VERSION); } /* diff --git a/module/zfs/dsl_crypt.c b/module/zfs/dsl_crypt.c index 5e6e4e3d6c39..2bcde94d345d 100644 --- a/module/zfs/dsl_crypt.c +++ b/module/zfs/dsl_crypt.c @@ -108,8 +108,10 @@ dsl_wrapping_key_free(dsl_wrapping_key_t *wkey) } static void -dsl_wrapping_key_create(uint8_t *wkeydata, zfs_keyformat_t keyformat, - uint64_t salt, uint64_t iters, dsl_wrapping_key_t **wkey_out) +dsl_wrapping_key_create(uint8_t *wkeydata, zfs_keyformat_t keyformat, zfs_key_kdf_t key_kdf, + uint64_t salt, uint64_t iters, + uint64_t argon2_t_cost, uint64_t argon2_m_cost, uint64_t argon2_parallelism, uint64_t argon2_version, + dsl_wrapping_key_t **wkey_out) { dsl_wrapping_key_t *wkey; @@ -125,6 +127,11 @@ dsl_wrapping_key_create(uint8_t *wkeydata, zfs_keyformat_t keyformat, /* initialize the rest of the struct */ zfs_refcount_create(&wkey->wk_refcnt); wkey->wk_keyformat = keyformat; + wkey->wk_key_kdf = key_kdf; + wkey->wk_argon2_t_cost = argon2_t_cost; + wkey->wk_argon2_m_cost = argon2_m_cost; + wkey->wk_argon2_parallelism = argon2_parallelism; + wkey->wk_argon2_version = argon2_version; wkey->wk_salt = salt; wkey->wk_iters = iters; @@ -139,6 +146,8 @@ dsl_crypto_params_create_nvlist(dcp_cmd_t cmd, nvlist_t *props, uint64_t crypt = ZIO_CRYPT_INHERIT; uint64_t keyformat = ZFS_KEYFORMAT_NONE; uint64_t salt = 0, iters = 0; + uint64_t key_kdf = ZFS_KEY_KDF_NONE; + uint64_t argon2_t_cost = 0, argon2_m_cost = 0, argon2_parallelism = 0, argon2_version = 0; dsl_crypto_params_t *dcp = NULL; dsl_wrapping_key_t *wkey = NULL; uint8_t *wkeydata = NULL; @@ -156,10 +165,20 @@ dsl_crypto_params_create_nvlist(dcp_cmd_t cmd, nvlist_t *props, zfs_prop_to_name(ZFS_PROP_KEYFORMAT), &keyformat); (void) nvlist_lookup_string(props, zfs_prop_to_name(ZFS_PROP_KEYLOCATION), &keylocation); + (void) nvlist_lookup_uint64(props, + zfs_prop_to_name(ZFS_PROP_KEY_KDF), &key_kdf); (void) nvlist_lookup_uint64(props, zfs_prop_to_name(ZFS_PROP_PBKDF2_SALT), &salt); (void) nvlist_lookup_uint64(props, zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), &iters); + (void) nvlist_lookup_uint64(props, + zfs_prop_to_name(ZFS_PROP_ARGON2_T_COST), &argon2_t_cost); + (void) nvlist_lookup_uint64(props, + zfs_prop_to_name(ZFS_PROP_ARGON2_M_COST), &argon2_m_cost); + (void) nvlist_lookup_uint64(props, + zfs_prop_to_name(ZFS_PROP_ARGON2_PARALLELISM), &argon2_parallelism); + (void) nvlist_lookup_uint64(props, + zfs_prop_to_name(ZFS_PROP_ARGON2_VERSION), &argon2_version); dcp->cp_crypt = crypt; } @@ -214,8 +233,10 @@ dsl_crypto_params_create_nvlist(dcp_cmd_t cmd, nvlist_t *props, /* create the wrapping key from the raw data */ if (wkeydata != NULL) { /* create the wrapping key with the verified parameters */ - dsl_wrapping_key_create(wkeydata, keyformat, salt, - iters, &wkey); + dsl_wrapping_key_create(wkeydata, keyformat, key_kdf, salt, + iters, + argon2_t_cost, argon2_m_cost, argon2_parallelism, argon2_version, + &wkey); dcp->cp_wkey = wkey; } @@ -226,8 +247,12 @@ dsl_crypto_params_create_nvlist(dcp_cmd_t cmd, nvlist_t *props, (void) nvlist_remove_all(props, zfs_prop_to_name(ZFS_PROP_ENCRYPTION)); (void) nvlist_remove_all(props, zfs_prop_to_name(ZFS_PROP_KEYFORMAT)); (void) nvlist_remove_all(props, zfs_prop_to_name(ZFS_PROP_PBKDF2_SALT)); - (void) nvlist_remove_all(props, - zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS)); + (void) nvlist_remove_all(props, zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS)); + (void) nvlist_remove_all(props, zfs_prop_to_name(ZFS_PROP_KEY_KDF)); + (void) nvlist_remove_all(props, zfs_prop_to_name(ZFS_PROP_ARGON2_T_COST)); + (void) nvlist_remove_all(props, zfs_prop_to_name(ZFS_PROP_ARGON2_M_COST)); + (void) nvlist_remove_all(props, zfs_prop_to_name(ZFS_PROP_ARGON2_PARALLELISM)); + (void) nvlist_remove_all(props, zfs_prop_to_name(ZFS_PROP_ARGON2_VERSION)); *dcp_out = dcp; @@ -743,6 +768,8 @@ spa_keystore_load_wkey(const char *dsname, dsl_crypto_params_t *dcp, dsl_wrapping_key_t *wkey = dcp->cp_wkey; dsl_pool_t *dp = NULL; uint64_t rddobj, keyformat, salt, iters; + uint64_t key_kdf, argon2_t_cost, argon2_m_cost, argon2_parallelism; + uint64_t argon2_version; /* * We don't validate the wrapping key's keyformat, salt, or iters @@ -802,9 +829,37 @@ spa_keystore_load_wkey(const char *dsname, dsl_crypto_params_t *dcp, if (ret != 0) goto error; + ret = zap_lookup(dp->dp_meta_objset, dd->dd_crypto_obj, + zfs_prop_to_name(ZFS_PROP_KEY_KDF), 8, 1, &key_kdf); + if (ret != 0) + goto error; + + ret = zap_lookup(dp->dp_meta_objset, dd->dd_crypto_obj, + zfs_prop_to_name(ZFS_PROP_ARGON2_T_COST), 8, 1, &argon2_t_cost); + if (ret != 0) + goto error; + + ret = zap_lookup(dp->dp_meta_objset, dd->dd_crypto_obj, + zfs_prop_to_name(ZFS_PROP_ARGON2_M_COST), 8, 1, &argon2_m_cost); + if (ret != 0) + goto error; + + ret = zap_lookup(dp->dp_meta_objset, dd->dd_crypto_obj, + zfs_prop_to_name(ZFS_PROP_ARGON2_PARALLELISM), 8, 1, &argon2_parallelism); + if (ret != 0) + goto error; + + ret = zap_lookup(dp->dp_meta_objset, dd->dd_crypto_obj, + zfs_prop_to_name(ZFS_PROP_ARGON2_VERSION), 8, 1, &argon2_version); + if (ret != 0) + goto error; + ASSERT3U(keyformat, <, ZFS_KEYFORMAT_FORMATS); ASSERT3U(keyformat, !=, ZFS_KEYFORMAT_NONE); - IMPLY(keyformat == ZFS_KEYFORMAT_PASSPHRASE, iters != 0); + /* should only run if kdf is PBKDF2 */ + IMPLY((keyformat == ZFS_KEYFORMAT_PASSPHRASE + && (key_kdf == ZFS_KEY_KDF_PBKDF2 || key_kdf == ZFS_KEY_KDF_NONE)), + iters != 0); IMPLY(keyformat == ZFS_KEYFORMAT_PASSPHRASE, salt != 0); IMPLY(keyformat != ZFS_KEYFORMAT_PASSPHRASE, iters == 0); IMPLY(keyformat != ZFS_KEYFORMAT_PASSPHRASE, salt == 0); @@ -812,6 +867,11 @@ spa_keystore_load_wkey(const char *dsname, dsl_crypto_params_t *dcp, wkey->wk_keyformat = keyformat; wkey->wk_salt = salt; wkey->wk_iters = iters; + wkey->wk_key_kdf = key_kdf; + wkey->wk_argon2_t_cost = argon2_t_cost; + wkey->wk_argon2_m_cost = argon2_m_cost; + wkey->wk_argon2_parallelism = argon2_parallelism; + wkey->wk_argon2_version = argon2_version; /* * At this point we have verified the wkey and confirmed that it can @@ -1170,7 +1230,10 @@ static void dsl_crypto_key_sync_impl(objset_t *mos, uint64_t dckobj, uint64_t crypt, uint64_t root_ddobj, uint64_t guid, uint8_t *iv, uint8_t *mac, uint8_t *keydata, uint8_t *hmac_keydata, uint64_t keyformat, - uint64_t salt, uint64_t iters, dmu_tx_t *tx) + uint64_t salt, uint64_t iters, + uint64_t key_kdf, + uint64_t argon2_t_cost, uint64_t argon2_m_cost, uint64_t argon2_parallelism, uint64_t argon2_version, + dmu_tx_t *tx) { VERIFY0(zap_update(mos, dckobj, DSL_CRYPTO_KEY_CRYPTO_SUITE, 8, 1, &crypt, tx)); @@ -1192,6 +1255,17 @@ dsl_crypto_key_sync_impl(objset_t *mos, uint64_t dckobj, uint64_t crypt, 8, 1, &salt, tx)); VERIFY0(zap_update(mos, dckobj, zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), 8, 1, &iters, tx)); + VERIFY0(zap_update(mos, dckobj, zfs_prop_to_name(ZFS_PROP_KEY_KDF), + 8, 1, &key_kdf, tx)); + VERIFY0(zap_update(mos, dckobj, zfs_prop_to_name(ZFS_PROP_ARGON2_T_COST), + 8, 1, &argon2_t_cost, tx)); + VERIFY0(zap_update(mos, dckobj, zfs_prop_to_name(ZFS_PROP_ARGON2_M_COST), + 8, 1, &argon2_m_cost, tx)); + VERIFY0(zap_update(mos, dckobj, zfs_prop_to_name(ZFS_PROP_ARGON2_PARALLELISM), + 8, 1, &argon2_parallelism, tx)); + VERIFY0(zap_update(mos, dckobj, zfs_prop_to_name(ZFS_PROP_ARGON2_VERSION), + 8, 1, &argon2_version, tx)); + } static void @@ -1215,6 +1289,8 @@ dsl_crypto_key_sync(dsl_crypto_key_t *dck, dmu_tx_t *tx) dsl_crypto_key_sync_impl(tx->tx_pool->dp_meta_objset, dck->dck_obj, key->zk_crypt, wkey->wk_ddobj, key->zk_guid, iv, mac, keydata, hmac_keydata, wkey->wk_keyformat, wkey->wk_salt, wkey->wk_iters, + wkey->wk_key_kdf, + wkey->wk_argon2_t_cost, wkey->wk_argon2_m_cost, wkey->wk_argon2_parallelism, wkey->wk_argon2_version, tx); } @@ -1368,8 +1444,10 @@ spa_keystore_change_key_check(void *arg, dmu_tx_t *tx) /* passphrases require pbkdf2 salt and iters */ if (dcp->cp_wkey->wk_keyformat == ZFS_KEYFORMAT_PASSPHRASE) { - if (dcp->cp_wkey->wk_salt == 0 || - dcp->cp_wkey->wk_iters < MIN_PBKDF2_ITERATIONS) { + if ((dcp->cp_wkey->wk_key_kdf == ZFS_KEY_KDF_NONE || + dcp->cp_wkey->wk_key_kdf == ZFS_KEY_KDF_PBKDF2) && + (dcp->cp_wkey->wk_salt == 0 || + dcp->cp_wkey->wk_iters < MIN_PBKDF2_ITERATIONS)) { ret = SET_ERROR(EINVAL); goto error; } @@ -1541,6 +1619,7 @@ spa_keystore_change_key_sync(void *arg, dmu_tx_t *tx) keylocation, tx); } + VERIFY0(dsl_dir_get_encryption_root_ddobj(ds->ds_dir, &rddobj)); new_rddobj = ds->ds_dir->dd_object; } else { @@ -1854,8 +1933,10 @@ dmu_objset_create_crypt_check(dsl_dir_t *parentdd, dsl_crypto_params_t *dcp, break; case ZFS_KEYFORMAT_PASSPHRASE: /* requires pbkdf2 iters and salt */ - if (dcp->cp_wkey->wk_salt == 0 || - dcp->cp_wkey->wk_iters < MIN_PBKDF2_ITERATIONS) + if ((dcp->cp_wkey->wk_key_kdf == ZFS_KEY_KDF_NONE || + dcp->cp_wkey->wk_key_kdf == ZFS_KEY_KDF_PBKDF2) && + (dcp->cp_wkey->wk_salt == 0 || + dcp->cp_wkey->wk_iters < MIN_PBKDF2_ITERATIONS)) return (SET_ERROR(EINVAL)); break; case ZFS_KEYFORMAT_NONE: @@ -2236,7 +2317,8 @@ dsl_crypto_recv_raw_key_sync(dsl_dataset_t *ds, nvlist_t *nvl, dmu_tx_t *tx) uint_t len; uint64_t rddobj, one = 1; uint8_t *keydata, *hmac_keydata, *iv, *mac; - uint64_t crypt, key_guid, keyformat, iters, salt; + uint64_t crypt, key_guid, keyformat, iters, salt, key_kdf; + uint64_t argon2_t_cost, argon2_m_cost, argon2_parallelism, argon2_version; uint64_t version = ZIO_CRYPT_KEY_CURRENT_VERSION; const char *keylocation = "prompt"; @@ -2247,8 +2329,18 @@ dsl_crypto_recv_raw_key_sync(dsl_dataset_t *ds, nvlist_t *nvl, dmu_tx_t *tx) zfs_prop_to_name(ZFS_PROP_KEYFORMAT)); iters = fnvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS)); + key_kdf = fnvlist_lookup_uint64(nvl, + zfs_prop_to_name(ZFS_PROP_KEY_KDF)); salt = fnvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_PBKDF2_SALT)); + argon2_t_cost = fnvlist_lookup_uint64(nvl, + zfs_prop_to_name(ZFS_PROP_ARGON2_T_COST)); + argon2_m_cost = fnvlist_lookup_uint64(nvl, + zfs_prop_to_name(ZFS_PROP_ARGON2_M_COST)); + argon2_parallelism = fnvlist_lookup_uint64(nvl, + zfs_prop_to_name(ZFS_PROP_ARGON2_PARALLELISM)); + argon2_version = fnvlist_lookup_uint64(nvl, + zfs_prop_to_name(ZFS_PROP_ARGON2_VERSION)); VERIFY0(nvlist_lookup_uint8_array(nvl, DSL_CRYPTO_KEY_MASTER_KEY, &keydata, &len)); VERIFY0(nvlist_lookup_uint8_array(nvl, DSL_CRYPTO_KEY_HMAC_KEY, @@ -2298,7 +2390,9 @@ dsl_crypto_recv_raw_key_sync(dsl_dataset_t *ds, nvlist_t *nvl, dmu_tx_t *tx) /* sync the key data to the ZAP object on disk */ dsl_crypto_key_sync_impl(mos, dd->dd_crypto_obj, crypt, rddobj, key_guid, iv, mac, keydata, hmac_keydata, keyformat, salt, - iters, tx); + iters, key_kdf, + argon2_t_cost, argon2_m_cost, argon2_parallelism, argon2_version, + tx); } static int @@ -2391,8 +2485,9 @@ dsl_crypto_populate_key_nvlist(objset_t *os, uint64_t from_ivset_guid, dsl_dir_t *rdd = NULL; dsl_pool_t *dp = ds->ds_dir->dd_pool; objset_t *mos = dp->dp_meta_objset; - uint64_t crypt = 0, key_guid = 0, format = 0; + uint64_t crypt = 0, key_guid = 0, format = 0, key_kdf = 0; uint64_t iters = 0, salt = 0, version = 0; + uint64_t argon2_t_cost = 0, argon2_m_cost = 0, argon2_parallelism = 0, argon2_version = 0; uint64_t to_ivset_guid = 0; uint8_t raw_keydata[MASTER_KEY_MAX_LEN]; uint8_t raw_hmac_keydata[SHA512_HMAC_KEYLEN]; @@ -2484,6 +2579,31 @@ dsl_crypto_populate_key_nvlist(objset_t *os, uint64_t from_ivset_guid, zfs_prop_to_name(ZFS_PROP_PBKDF2_SALT), 8, 1, &salt); if (ret != 0) goto error_unlock; + + ret = zap_lookup(dp->dp_meta_objset, rdd->dd_crypto_obj, + zfs_prop_to_name(ZFS_PROP_KEY_KDF), 8, 1, &key_kdf); + if (ret != 0) + goto error_unlock; + + ret = zap_lookup(dp->dp_meta_objset, rdd->dd_crypto_obj, + zfs_prop_to_name(ZFS_PROP_ARGON2_T_COST), 8, 1, &argon2_t_cost); + if (ret != 0) + goto error_unlock; + + ret = zap_lookup(dp->dp_meta_objset, rdd->dd_crypto_obj, + zfs_prop_to_name(ZFS_PROP_ARGON2_M_COST), 8, 1, &argon2_m_cost); + if (ret != 0) + goto error_unlock; + + ret = zap_lookup(dp->dp_meta_objset, rdd->dd_crypto_obj, + zfs_prop_to_name(ZFS_PROP_ARGON2_PARALLELISM), 8, 1, &argon2_parallelism); + if (ret != 0) + goto error_unlock; + + ret = zap_lookup(dp->dp_meta_objset, rdd->dd_crypto_obj, + zfs_prop_to_name(ZFS_PROP_ARGON2_VERSION), 8, 1, &argon2_version); + if (ret != 0) + goto error_unlock; } dsl_dir_rele(rdd, FTAG); @@ -2504,7 +2624,12 @@ dsl_crypto_populate_key_nvlist(objset_t *os, uint64_t from_ivset_guid, os->os_phys->os_portable_mac, ZIO_OBJSET_MAC_LEN)); fnvlist_add_uint64(nvl, zfs_prop_to_name(ZFS_PROP_KEYFORMAT), format); fnvlist_add_uint64(nvl, zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), iters); + fnvlist_add_uint64(nvl, zfs_prop_to_name(ZFS_PROP_KEY_KDF), key_kdf); fnvlist_add_uint64(nvl, zfs_prop_to_name(ZFS_PROP_PBKDF2_SALT), salt); + fnvlist_add_uint64(nvl, zfs_prop_to_name(ZFS_PROP_ARGON2_T_COST), argon2_t_cost); + fnvlist_add_uint64(nvl, zfs_prop_to_name(ZFS_PROP_ARGON2_M_COST), argon2_m_cost); + fnvlist_add_uint64(nvl, zfs_prop_to_name(ZFS_PROP_ARGON2_PARALLELISM), argon2_parallelism); + fnvlist_add_uint64(nvl, zfs_prop_to_name(ZFS_PROP_ARGON2_VERSION), argon2_version); fnvlist_add_uint64(nvl, "mdn_checksum", mdn->dn_checksum); fnvlist_add_uint64(nvl, "mdn_compress", mdn->dn_compress); fnvlist_add_uint64(nvl, "mdn_nlevels", mdn->dn_nlevels); @@ -2616,6 +2741,26 @@ dsl_dataset_crypt_stats(dsl_dataset_t *ds, nvlist_t *nv) zfs_prop_to_name(ZFS_PROP_KEYFORMAT), 8, 1, &intval) == 0) { dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_KEYFORMAT, intval); } + if (zap_lookup(dd->dd_pool->dp_meta_objset, dd->dd_crypto_obj, + zfs_prop_to_name(ZFS_PROP_KEY_KDF), 8, 1, &intval) == 0) { + dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_KEY_KDF, intval); + } + if (zap_lookup(dd->dd_pool->dp_meta_objset, dd->dd_crypto_obj, + zfs_prop_to_name(ZFS_PROP_ARGON2_T_COST), 8, 1, &intval) == 0) { + dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_ARGON2_T_COST, intval); + } + if (zap_lookup(dd->dd_pool->dp_meta_objset, dd->dd_crypto_obj, + zfs_prop_to_name(ZFS_PROP_ARGON2_M_COST), 8, 1, &intval) == 0) { + dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_ARGON2_M_COST, intval); + } + if (zap_lookup(dd->dd_pool->dp_meta_objset, dd->dd_crypto_obj, + zfs_prop_to_name(ZFS_PROP_ARGON2_PARALLELISM), 8, 1, &intval) == 0) { + dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_ARGON2_PARALLELISM, intval); + } + if (zap_lookup(dd->dd_pool->dp_meta_objset, dd->dd_crypto_obj, + zfs_prop_to_name(ZFS_PROP_ARGON2_VERSION), 8, 1, &intval) == 0) { + dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_ARGON2_VERSION, intval); + } if (zap_lookup(dd->dd_pool->dp_meta_objset, dd->dd_crypto_obj, zfs_prop_to_name(ZFS_PROP_PBKDF2_SALT), 8, 1, &intval) == 0) { dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_PBKDF2_SALT, intval); diff --git a/module/zfs/zcp_get.c b/module/zfs/zcp_get.c index 6fd45151d92a..25d9af71ae88 100644 --- a/module/zfs/zcp_get.c +++ b/module/zfs/zcp_get.c @@ -378,13 +378,16 @@ get_special_prop(lua_State *state, dsl_dataset_t *ds, const char *dsname, } case ZFS_PROP_KEYSTATUS: + case ZFS_PROP_KEY_KDF: case ZFS_PROP_KEYFORMAT: { /* provide defaults in case no crypto obj exists */ setpoint[0] = '\0'; if (zfs_prop == ZFS_PROP_KEYSTATUS) numval = ZFS_KEYSTATUS_NONE; - else + else if (zfs_prop == ZFS_PROP_KEYFORMAT) numval = ZFS_KEYFORMAT_NONE; + else if (zfs_prop == ZFS_PROP_KEY_KDF) + numval = ZFS_KEY_KDF_NONE; nvlist_t *nvl, *propval; nvl = fnvlist_alloc();