Skip to content

Commit

Permalink
Merge pull request openzfs#4 from lundman/master
Browse files Browse the repository at this point in the history
Crypto cleanup
  • Loading branch information
zfsrogue committed Nov 19, 2012
2 parents 6f2e742 + 78be8b7 commit f172117
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 174 deletions.
50 changes: 12 additions & 38 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:

<pre>
# 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.............|
</pre>

zfs/rogue
7 changes: 6 additions & 1 deletion lib/libspl/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,19 @@ 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 :
sizeof(statickey));

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
Expand Down Expand Up @@ -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;
Expand Down
98 changes: 86 additions & 12 deletions lib/libzfs/libzfs_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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,
Expand All @@ -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 *
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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,
Expand Down
8 changes: 8 additions & 0 deletions lib/libzfs/libzfs_dataset.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 0 additions & 3 deletions lib/libzfs/libzfs_mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
4 changes: 0 additions & 4 deletions module/zfs/dmu_objset.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
8 changes: 7 additions & 1 deletion module/zfs/sha256.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit f172117

Please sign in to comment.