From 62d0d4513cee45d6c3b9a3c93d3930d15efb9cd8 Mon Sep 17 00:00:00 2001 From: Jorgen Lundman Date: Thu, 21 Feb 2013 10:17:36 +0900 Subject: [PATCH 1/3] When using "raw" it would fail the "invalid all zeros key" test due to tmpkeylen being 0. --- lib/libzfs/libzfs_crypto.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/libzfs/libzfs_crypto.c b/lib/libzfs/libzfs_crypto.c index 5651a8e0ff65..c2866b0de232 100644 --- a/lib/libzfs/libzfs_crypto.c +++ b/lib/libzfs/libzfs_crypto.c @@ -705,6 +705,7 @@ key_hdl_to_zc(libzfs_handle_t *hdl, zfs_handle_t *zhp, char *keysource, free(keydata); return (-1); } + tmpkeydatalen = keydatalen; } else { int tries = 0; From 8500d46e0cb4629f6e5f17fc0726b82391f187cb Mon Sep 17 00:00:00 2001 From: Jorgen Lundman Date: Wed, 24 Apr 2013 12:07:50 +0900 Subject: [PATCH 2/3] "props" is eagerly freed just before they are used. Most likely left behind in error. Fixes https://github.com/zfsrogue/zfs-crypto/issues/19 --- lib/libzfs/libzfs_dataset.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c index 60db43b2a48e..a9d9c37493e4 100644 --- a/lib/libzfs/libzfs_dataset.c +++ b/lib/libzfs/libzfs_dataset.c @@ -3477,8 +3477,6 @@ zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props) nvlist_free(props); return (-1); } - - nvlist_free(props); } (void) strlcpy(zc.zc_name, target, sizeof (zc.zc_name)); From 96a8d19dcf105394c6b16569128838241bd46c0a Mon Sep 17 00:00:00 2001 From: Jorgen Lundman Date: Thu, 25 Apr 2013 09:23:38 +0900 Subject: [PATCH 3/3] Method "-o keysource=passphrase,file://" was missing pkcs11_read_data(), lift that in from OpenSolaris. Reading from file and /dev/random works hopefully fixing https://github.com/zfsrogue/zfs-crypto/issues/20 --- lib/libspl/crypto.c | 115 ++++++++++++++++++++++++++++++++++++- lib/libzfs/libzfs_crypto.c | 3 +- 2 files changed, 115 insertions(+), 3 deletions(-) diff --git a/lib/libspl/crypto.c b/lib/libspl/crypto.c index 6bca41a24096..79a751b13f68 100644 --- a/lib/libspl/crypto.c +++ b/lib/libspl/crypto.c @@ -3,6 +3,9 @@ #include #include #include +#include +#include +#include #include "sha1.h" @@ -138,5 +141,115 @@ int crypto_pass2key(unsigned char *keydata, size_t keydatalen, } +/* OpenSolaris */ - +/* + * Read file into buffer. Used to read raw key data or initialization + * vector data. Buffer must be freed by caller using free(). + * + * If file is a regular file, entire file is read and dlen is set + * to the number of bytes read. Otherwise, dlen should first be set + * to the number of bytes requested and will be reset to actual number + * of bytes returned. + * + * Return 0 on success and errno on error. + */ +int +pkcs11_read_data(char *filename, void **dbuf, size_t *dlen) +{ + int fd = -1; + struct stat statbuf; + boolean_t plain_file; + void *filebuf = NULL; + size_t filesize = 0; + int ret = 0; + + if (filename == NULL || dbuf == NULL || dlen == NULL) + return (-1); + + if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) == -1) { + ret = errno; + goto error; + } + + if (fstat(fd, &statbuf) == -1) { + ret = errno; + goto error; + } + + if (S_ISREG(statbuf.st_mode)) { + /* read the entire regular file */ + filesize = statbuf.st_size; + plain_file = B_TRUE; + } else { + /* read requested bytes from special file */ + filesize = *dlen; + plain_file = B_FALSE; + } + + if (filesize == 0) { + /* + * for decrypt this is an error; for digest this is ok; + * make it ok here but also set dbuf = NULL and dlen = 0 + * to indicate there was no data to read and caller can + * retranslate that to an error if it wishes. + */ + (void) close(fd); + *dbuf = NULL; + *dlen = 0; + return (0); + } + + if ((filebuf = malloc(filesize)) == NULL) { + ret = errno; + goto error; + } + + if (plain_file) { + /* either it got read or it didn't */ + if (read(fd, filebuf, filesize) != filesize) { + ret = errno; + goto error; + } + } else { + /* reading from special file may need some coaxing */ + char *marker = (char *)filebuf; + size_t left = filesize; + ssize_t nread; + + for (/* */; left > 0; marker += nread, left -= nread) { + /* keep reading it's going well */ + nread = read(fd, marker, left); + if (nread > 0 || (nread == 0 && errno == EINTR)) { + errno = 0; + continue; + } + + /* might have to be good enough for caller */ + if (nread == 0 && errno == EAGAIN) + break; + + /* anything else is an error */ + if (errno) { + ret = errno; + goto error; + } + } + /* reset to actual number of bytes read */ + filesize -= left; + } + + (void) close(fd); + *dbuf = filebuf; + *dlen = filesize; + return (0); + +error: + if (filebuf != NULL) { + free(filebuf); + } + if (fd != -1) + (void) close(fd); + + return (ret); +} diff --git a/lib/libzfs/libzfs_crypto.c b/lib/libzfs/libzfs_crypto.c index 064276cba26f..1523d75f8a52 100644 --- a/lib/libzfs/libzfs_crypto.c +++ b/lib/libzfs/libzfs_crypto.c @@ -252,6 +252,7 @@ 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); +int pkcs11_read_data(char *filename, void **dbuf, size_t *dlen); /* @@ -726,7 +727,6 @@ key_hdl_to_zc(libzfs_handle_t *hdl, zfs_handle_t *zhp, char *keysource, * Note that pkcs11_read_data allocates memory with malloc * that we need to free. */ -#if 0 // FIXME keydatalen = keylen; ret = pkcs11_read_data(&(uri[7]), (void **)&keydata, &keydatalen); @@ -736,7 +736,6 @@ key_hdl_to_zc(libzfs_handle_t *hdl, zfs_handle_t *zhp, char *keysource, errno = ret; return (-1); } -#endif break; case KEY_LOCATOR_PKCS11_URI: