diff --git a/README.markdown b/README.markdown index f41fbe3263fa..9864db2ca5f6 100644 --- a/README.markdown +++ b/README.markdown @@ -25,18 +25,10 @@ minimum" features as needed by ZFS only. Current support is in BETA. Real ciphers are used, but key generation function could do with more work. It is NOT compatible with Solaris pools. - - -Required work: - -* Implement more ciphers besides default. +Currently it is the authentication MAC that appears to differ. * MACs are in use, but compute_mac() is empty, not called? -* Prompt for key (getpassphrase) needs implementing. It is possible - that getpass() will suffice on Linux, as it does not limit input to - 8 chars. - * Key needs to be CK_AES prepared, better than current * All "// FIXME" should be inspected. In particular, known areas @@ -45,38 +37,20 @@ Required work: * Removed KEY methods "https URI" (requires curl) and pkcs11 types. * Undo the POOL VERSION=30, put it back to 28, and make CRYPTO be a - "Named Extension" instead. - - -Current output: - -
-# dd if=/dev/zero of=~/src/pool-image.bin bs=1M count=1024
-
-# zpool create -f mypool ~/src/pool-image.bin
-
-# zfs create -o encryption=on mypool/BOOM
+  "Named Extension" instead. ZFS On Linux currently does not support
+  "feature@" properties.
 
-in key_hdl_to_zc
-in get_assphrase
-Should ask for password here:
-Should ask for password here:
-Key is 'I'M LIZARD QUEEN' and is len 16
-Nov  5 15:47:36 zfsdev kernel: [  324.188602] in CREATE
-Nov  5 15:47:36 zfsdev kernel: [  324.188606]  version OK
-[...]
-Nov  5 15:47:36 zfsdev kernel: [  324.219017] crypto_decrypt IOV (ffff88003a98b200 -> ffff88003a98ba00) curriov 0, iovlen 0x0200
-Nov  5 15:47:36 zfsdev kernel: [  324.219019] crypto_decrypt: done
-Nov  5 15:47:36 zfsdev kernel: [  324.219020] zio_decrypt exit
 
-# mkdir /mypool/BOOM/This.Directory.Is.Hopefully.Encrypted
+Example:
 
-# hexdump -C ../pool-image.bin |less
+# zfs create -o encryption=aes-256-gcm mypool/BOOM
+  Enter passphrase for 'mypool/BOOM':
+  Enter again:
+  kernel: [11266.250594] spl-crypto: Cipher test 'CKM_AES_CCM' -> 'sun-ccm(aes)' successful.
+# zfs list
+  NAME          USED  AVAIL  REFER  MOUNTPOINT
+  mypool        142K   984M    31K  /mypool
+  mypool/BOOM    31K   984M    31K  /mypool/BOOM
 
-0041b440  07 00 00 00 00 00 00 40  00 00 00 00 00 00 74 48  |.......@......tH|
-0041b450  49 53 2e 64 49 52 45 43  54 4f 52 59 2e 69 53 2e  |IS.dIRECTORY.iS.|
-0041b460  68 4f 50 45 46 55 4c 4c  59 2e 65 4e 43 52 59 50  |hOPEFULLY.eNCRYP|
-0041b470  54 45 44 00 00 00 00 00  00 00 00 00 00 00 00 00  |TED.............|
-
zfs/rogue diff --git a/lib/libspl/crypto.c b/lib/libspl/crypto.c index 8bb4e7147383..ad6c526d6213 100644 --- a/lib/libspl/crypto.c +++ b/lib/libspl/crypto.c @@ -37,7 +37,9 @@ int crypto_pass2key(unsigned char *keydata, size_t keydatalen, unsigned char iv[16] = { 0 }; unsigned char statickey[16] = { 0 }; +#ifdef VERBOSE printf("In crypto_pass2key: keylen %ld\n", keydatalen); +#endif // This needs fixing, we use at-most 16 chars of the password. memcpy(statickey, keydata, keydatalen < sizeof(statickey) ? keydatalen : @@ -45,7 +47,9 @@ int crypto_pass2key(unsigned char *keydata, size_t keydatalen, if (aes_setkey_enc(&aes, statickey, sizeof(statickey) * 8)) goto out; +#ifdef VERBOSE printf("Key set ok\n"); +#endif // Sun uses ITERATIONS=1000 // "i" is 4 byte integer of iterations @@ -76,11 +80,12 @@ int crypto_pass2key(unsigned char *keydata, size_t keydatalen, if (i < iterations) goto out; +#ifdef VERBOSE printf("Done with keygen: %ld\n", desired_keylen); for (i = 0; i < desired_keylen; i++) printf("0x%02x ", buffer[i]); printf("\n"); - +#endif if (out_keydata) { *out_keydata = buffer; diff --git a/lib/libzfs/libzfs_crypto.c b/lib/libzfs/libzfs_crypto.c index 93b64292ecb8..5cb59ddd74a7 100644 --- a/lib/libzfs/libzfs_crypto.c +++ b/lib/libzfs/libzfs_crypto.c @@ -245,6 +245,15 @@ zfs_can_prompt_if_needed(char *keysource) } +/* + * Move this to a header file + */ +int crypto_pass2key(unsigned char *keydata, size_t keydatalen, + void *salt, size_t saltlen, + size_t desired_keylen, + void **out_keydata, size_t *out_keylen); + + /* * Linux does not have the same limitation that Solaris has, of limiting * getpass() to only 8 chars. Linux limit is 128 chars. @@ -257,6 +266,82 @@ static char *getpassphrase(const char *prompt) return getpass(prompt); } +/* + * This could possibly go somewhere more appropriate + */ +/* + * This function takes a char[] and length of hexadecimal values and + * returns a malloc'ed byte array with the length of that new byte array. + * The caller needs to provide a pointer to where this new malloc'ed byte array + * will be passed back; as well as, a pointer for the length of the new + * byte array. + * + * The caller is responsible for freeing the malloc'ed array when done + * + * The return code is 0 if successful, otherwise the errno value is returned. + */ +int +hexstr_to_bytes(char *hexstr, size_t hexlen, uchar_t **bytes, size_t *blen) +{ + int i, ret = 0; + unsigned char ch; + uchar_t *b = NULL; + + *bytes = NULL; + *blen = 0; + + if (hexstr == NULL || (hexlen % 2 == 1)) + return (EINVAL); + + if (hexstr[0] == '0' && ((hexstr[1] == 'x') || (hexstr[1] == 'X'))) { + hexstr += 2; + hexlen -= 2; + } + + *blen = (hexlen / 2); + + b = malloc(*blen); + if (b == NULL) { + *blen = 0; + return (errno); + } + + for (i = 0; i < hexlen; i++) { + ch = (unsigned char) *hexstr; + + if (!isxdigit(ch)) { + ret = EINVAL; + goto out; + } + + hexstr++; + + if ((ch >= '0') && (ch <= '9')) + ch -= '0'; + else if ((ch >= 'A') && (ch <= 'F')) + ch = ch - 'A' + 10; + else if ((ch >= 'a') && (ch <= 'f')) + ch = ch - 'a' + 10; + + if (i & 1) + b[i/2] |= ch; + else + b[i/2] = (ch << 4); + } + + out: + if (b != NULL && ret != 0) { + free(b); + *blen = 0; + } else + *bytes = b; + + return (ret); +} + + + + static int get_passphrase(libzfs_handle_t *hdl, char **passphrase, @@ -268,8 +353,6 @@ get_passphrase(libzfs_handle_t *hdl, char **passphrase, int min_psize = 8; char dsname[MAXNAMELEN]; - fprintf(stderr, "in get_assphrase\r\n"); - zfs_cmd_target_dsname(zc, cmd, dsname, sizeof (dsname)); if (format == KEY_FORMAT_HEX) { min_psize = 2 * @@ -578,8 +661,6 @@ key_hdl_to_zc(libzfs_handle_t *hdl, zfs_handle_t *zhp, char *keysource, uint64_t salt; //struct cb_arg_curl cb_curl = { 0 }; - fprintf(stderr, "in key_hdl_to_zc\r\n"); - zc->zc_crypto.zic_clone_newkey = hdl->libzfs_crypt.zc_clone_newkey; if (!keysource_prop_parser(keysource, &format, &locator, &uri)) { @@ -760,10 +841,8 @@ key_hdl_to_zc(libzfs_handle_t *hdl, zfs_handle_t *zhp, char *keysource, * so to avoid a memory leak we use a tmpkeydata buffer * and bcopy it. */ -#if 0 // FIXME ret = hexstr_to_bytes(keydata, keydatalen, (uchar_t **)&tmpkeydata, &tmpkeydatalen); -#endif if (ret) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, @@ -818,9 +897,6 @@ key_hdl_to_zc(libzfs_handle_t *hdl, zfs_handle_t *zhp, char *keysource, } } - fprintf(stderr, "Key is '%s' and is len %u\r\n", - keydata, keydatalen); - // FIXME //tmpkeydata = strdup(keydata); //tmpkeydatalen = keydatalen; @@ -859,7 +935,7 @@ key_hdl_to_zc(libzfs_handle_t *hdl, zfs_handle_t *zhp, char *keysource, } #endif - crypto_pass2key(keydata, keydatalen, + crypto_pass2key((unsigned char *)keydata, keydatalen, (void *)&salt, sizeof(salt), keylen, (void **)&tmpkeydata, &tmpkeydatalen); @@ -915,8 +991,6 @@ zfs_key_load(zfs_handle_t *zhp, boolean_t mount, boolean_t share, zfs_cmd_t zc = { {0 }}; char errbuf[1024]; - fprintf(stderr, "zfs_key_load\r\n"); - (void) strlcpy(zc.zc_name, zfs_get_name(zhp), sizeof (zc.zc_name)); (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c index 996d0a8c499e..e647942d95ab 100644 --- a/lib/libzfs/libzfs_dataset.c +++ b/lib/libzfs/libzfs_dataset.c @@ -1237,6 +1237,14 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl, if (intval == ZIO_CRYPT_OFF) break; + if (type == ZFS_TYPE_VOLUME) { + zfs_error_aux(hdl, + dgettext(TEXT_DOMAIN, "encryption " + "is currently not supported on volumes")); + (void) zfs_error(hdl, + EZFS_PROPREADONLY, errbuf); + goto error; + } /* * Since encryption is on, we must make sure the user * did not specify a checksum so we can set it to diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c index af1c6685dd8a..564cccc1a348 100644 --- a/lib/libzfs/libzfs_mount.c +++ b/lib/libzfs/libzfs_mount.c @@ -412,11 +412,8 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags) * Don't need to check ZFS_PROP_ENCRYPTION because encrypted * datasets have keystatus of ZFS_CRYPT_KEY_NONE. */ - fprintf(stderr, "zfs_mount: mount, keystatus is %d\r\n", - zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS)); if (zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS) == ZFS_CRYPT_KEY_UNAVAILABLE) { - fprintf(stderr, "loading KEY\r\n"); (void )zfs_key_load(zhp, B_FALSE, B_FALSE, B_FALSE); } diff --git a/module/zfs/dmu_objset.c b/module/zfs/dmu_objset.c index 6f1789db8965..841c1aa80038 100644 --- a/module/zfs/dmu_objset.c +++ b/module/zfs/dmu_objset.c @@ -837,10 +837,6 @@ dmu_objset_create(const char *name, dmu_objset_type_t type, uint64_t flags, ASSERT(strchr(name, '@') == NULL); err = dsl_dir_open(name, FTAG, &pdd, &tail); -#if _KERNEL - printk("called dsl_dir_open %d\n", err); -#endif - if (err) return (err); diff --git a/module/zfs/sha256.c b/module/zfs/sha256.c index 9825823b2395..db306c195216 100644 --- a/module/zfs/sha256.c +++ b/module/zfs/sha256.c @@ -135,7 +135,13 @@ zio_checksum_SHAMAC(const void *buf, uint64_t size, zio_cksum_t *zcp) { zio_cksum_t tmp; - // FIXME, disabling checksum until ciphers implemented + // It is unknown if this function is correct, wrt to Solaris +#if _KERNEL +#ifdef ZFS_CRYPTO_VERBOSE + printk("SHAMAC called.\n"); +#endif +#endif + #if 1 zio_checksum_SHA256(buf, size, &tmp); #else diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index 59bacce876ab..1812ad586a75 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -184,17 +184,11 @@ zfs_earlier_version(const char *name, int version) if (spa_open(name, &spa, FTAG) == 0) { if (spa_version(spa) < version) { -#if _KERNEL - printk(" earlier version %d < %d\n", spa_version(spa), version); -#endif spa_close(spa, FTAG); return (1); } spa_close(spa, FTAG); } -#if _KERNEL - printk(" version OK\n"); -#endif return (0); } @@ -209,17 +203,10 @@ zpl_earlier_version(const char *name, int version) objset_t *os; boolean_t rc = B_TRUE; -#if _KERNEL - printk(" XXXX zpl_earlier_version %d\n", version); -#endif - if (dmu_objset_hold(name, FTAG, &os) == 0) { uint64_t zplversion; if (dmu_objset_type(os) != DMU_OST_ZFS) { -#if _KERNEL - printk(" zpl_earlier_version NOT FS!\n"); -#endif dmu_objset_rele(os, FTAG); return (B_TRUE); } @@ -227,10 +214,6 @@ zpl_earlier_version(const char *name, int version) if (zfs_get_zplprop(os, ZFS_PROP_VERSION, &zplversion) == 0) rc = zplversion < version; dmu_objset_rele(os, FTAG); -#if _KERNEL - printk(" XXXX zpl_earlier_version %d < %d\n", - (int)zplversion, (int)version); -#endif } return (rc); } @@ -2314,9 +2297,6 @@ zfs_set_prop_nvlist(const char *dsname, zprop_source_t source, nvlist_t *nvl, nvlist_t *errors; nvlist_t *retrynvl; -#if _KERNEL - printk("set_prop enter\n"); -#endif VERIFY(nvlist_alloc(&genericnvl, NV_UNIQUE_NAME, KM_SLEEP) == 0); VERIFY(nvlist_alloc(&errors, NV_UNIQUE_NAME, KM_SLEEP) == 0); VERIFY(nvlist_alloc(&retrynvl, NV_UNIQUE_NAME, KM_SLEEP) == 0); @@ -2328,9 +2308,6 @@ zfs_set_prop_nvlist(const char *dsname, zprop_source_t source, nvlist_t *nvl, zfs_prop_t prop = zfs_name_to_prop(propname); int err = 0; -#if _KERNEL - printk("set_prop playing with '%s'\n", propname); -#endif /* decode the property value */ propval = pair; if (nvpair_type(pair) == DATA_TYPE_NVLIST) { @@ -2383,17 +2360,10 @@ zfs_set_prop_nvlist(const char *dsname, zprop_source_t source, nvlist_t *nvl, } } -#if _KERNEL - printk(" so far %d\n", err); -#endif - /* Validate permissions */ if (err == 0) err = zfs_check_settable(dsname, pair, CRED()); -#if _KERNEL - printk(" so far2 %d\n", err); -#endif if (err == 0) { err = zfs_prop_set_special(dsname, source, pair); if (err == -1) { @@ -2421,10 +2391,6 @@ zfs_set_prop_nvlist(const char *dsname, zprop_source_t source, nvlist_t *nvl, goto retry; } -#if _KERNEL - printk("set_prop notempty test\n"); -#endif - if (!nvlist_empty(genericnvl) && dsl_props_set(dsname, source, genericnvl) != 0) { /* @@ -2460,12 +2426,6 @@ zfs_set_prop_nvlist(const char *dsname, zprop_source_t source, nvlist_t *nvl, VERIFY(nvlist_add_int32(errors, propname, err) == 0); -#if _KERNEL - printk("set_prop failed on '%s' %d\n", - propname, err); -#endif - - } } } @@ -2484,12 +2444,6 @@ zfs_set_prop_nvlist(const char *dsname, zprop_source_t source, nvlist_t *nvl, else *errlist = errors; -#if _KERNEL - printk("set_prop returning with %d\n", - rv); -#endif - - return (rv); } @@ -2899,9 +2853,6 @@ zfs_fill_zplprops_impl(objset_t *os, uint64_t zplver, int error; ASSERT(zplprops != NULL); -#if _KERNEL - printk("zfs_fill_zplprops_impl enter\n"); -#endif /* @@ -2972,16 +2923,6 @@ zfs_fill_zplprops_impl(objset_t *os, uint64_t zplver, if (is_ci) *is_ci = (sense == ZFS_CASE_INSENSITIVE); -#if _KERNEL - { - uint64_t zplversion = 999; - - zfs_get_zplprop(os, ZFS_PROP_VERSION, &zplversion); - - printk("zfs_fill_zplprops_impl exit, ZFS version %llu\n", - zplversion); - } -#endif return (0); } @@ -3019,15 +2960,8 @@ zfs_fill_zplprops(const char *dataset, nvlist_t *createprops, if ((error = dmu_objset_hold(parentname, FTAG, &os)) != 0) return (error); -#if _KERNEL - printk("fill calling zplprops\n"); -#endif - error = zfs_fill_zplprops_impl(os, zplver, fuids_ok, sa_ok, createprops, zplprops, is_ci); -#if _KERNEL - printk("fill exit %d\n",error); -#endif dmu_objset_rele(os, FTAG); return (error); @@ -3156,14 +3090,7 @@ zfs_ioc_create(zfs_cmd_t *zc) zct.zct_zplprops = NULL; zct.zct_props = nvprops; -#if _KERNEL - printk("in CREATE\n"); -#endif - if ((error = zfs_get_crypto_ctx(zc, &dcc)) != 0) { -#if _KERNEL - printk("get_crypto_ctsx failed\n"); -#endif return (error); } @@ -3250,11 +3177,6 @@ zfs_ioc_create(zfs_cmd_t *zc) error = dmu_objset_create(zc->zc_name, type, is_insensitive ? DS_FLAG_CI_DATASET : 0, &dcc, cbfunc, &zct); -#if _KERNEL - printk("called dmu_objset_create %d\n", error); - zpl_earlier_version(zc->zc_name, 5); -#endif - nvlist_free(zct.zct_zplprops); } @@ -3264,9 +3186,7 @@ zfs_ioc_create(zfs_cmd_t *zc) if (error == 0) { error = zfs_set_prop_nvlist(zc->zc_name, ZPROP_SRC_LOCAL, nvprops, NULL); -#if _KERNEL - printk("zfs_set_prop_nvlist said %d\n", error); -#endif + error = 0; if (error != 0) @@ -3274,11 +3194,6 @@ zfs_ioc_create(zfs_cmd_t *zc) } nvlist_free(nvprops); -#if _KERNEL - printk("zfs_create returning with %d\n", error); - zpl_earlier_version(zc->zc_name, 5); -#endif - return (error); } @@ -3591,10 +3506,6 @@ zfs_check_settable(const char *dsname, nvpair_t *pair, cred_t *cr) uint64_t intval; int err; -#if _KERNEL - printk("check_settable('%s') %d\n", propname, prop); -#endif - if (prop == ZPROP_INVAL) { if (zfs_prop_user(propname)) { if ((err = zfs_secpolicy_write_perms(dsname, @@ -3692,25 +3603,14 @@ zfs_check_settable(const char *dsname, nvpair_t *pair, cred_t *cr) break; case ZFS_PROP_ENCRYPTION: -#if _KERNEL - printk(" encryption baby\n"); -#endif - if (zfs_earlier_version(dsname, SPA_VERSION_CRYPTO)) return (ENOTSUP); -#if _KERNEL - printk(" pool version check OK\n"); -#endif + if (zpl_earlier_version(dsname, ZPL_VERSION_SA)) return (ENOTSUP); -#if _KERNEL - printk(" zpl version check OK\n"); -#endif + if (zfs_is_bootfs(dsname) && !BOOTFS_CRYPT_VALID(intval)) return (ERANGE); -#if _KERNEL - printk(" encryption OK\n", err); -#endif break; @@ -3732,9 +3632,6 @@ zfs_check_settable(const char *dsname, nvpair_t *pair, cred_t *cr) break; } -#if _KERNEL - printk(" check leaving for secpolicy\n", err); -#endif return (zfs_secpolicy_setprop(dsname, prop, pair, CRED())); } diff --git a/module/zfs/zfs_vfsops.c b/module/zfs/zfs_vfsops.c index 289e0e9be9f8..2742aec5e426 100644 --- a/module/zfs/zfs_vfsops.c +++ b/module/zfs/zfs_vfsops.c @@ -1496,11 +1496,6 @@ zfs_set_version(zfs_sb_t *zsb, uint64_t newvers) error = zap_update(os, MASTER_NODE_OBJ, ZPL_VERSION_STR, 8, 1, &newvers, tx); -#if _KERNEL - printk("vfsops setting zfs_version zap_update %d\n", error); -#endif - - if (error) { dmu_tx_commit(tx); return (error); @@ -1558,10 +1553,6 @@ zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value) if (os != NULL) error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value); -#if _KERNEL - printk(" get_zplprop zap_lookup '%s' %d\n", pname, error); -#endif - if (error == ENOENT) { /* No value set, use the default value */ switch (prop) {