1*eda14cbcSMatt Macy /* 2*eda14cbcSMatt Macy * CDDL HEADER START 3*eda14cbcSMatt Macy * 4*eda14cbcSMatt Macy * This file and its contents are supplied under the terms of the 5*eda14cbcSMatt Macy * Common Development and Distribution License ("CDDL"), version 1.0. 6*eda14cbcSMatt Macy * You may only use this file in accordance with the terms of version 7*eda14cbcSMatt Macy * 1.0 of the CDDL. 8*eda14cbcSMatt Macy * 9*eda14cbcSMatt Macy * A full copy of the text of the CDDL should have accompanied this 10*eda14cbcSMatt Macy * source. A copy of the CDDL is also available via the Internet at 11*eda14cbcSMatt Macy * http://www.illumos.org/license/CDDL. 12*eda14cbcSMatt Macy * 13*eda14cbcSMatt Macy * CDDL HEADER END 14*eda14cbcSMatt Macy */ 15*eda14cbcSMatt Macy 16*eda14cbcSMatt Macy /* 17*eda14cbcSMatt Macy * Copyright (c) 2017, Datto, Inc. All rights reserved. 18*eda14cbcSMatt Macy * Copyright 2020 Joyent, Inc. 19*eda14cbcSMatt Macy */ 20*eda14cbcSMatt Macy 21*eda14cbcSMatt Macy #include <sys/zfs_context.h> 22*eda14cbcSMatt Macy #include <sys/fs/zfs.h> 23*eda14cbcSMatt Macy #include <sys/dsl_crypt.h> 24*eda14cbcSMatt Macy #include <libintl.h> 25*eda14cbcSMatt Macy #include <termios.h> 26*eda14cbcSMatt Macy #include <signal.h> 27*eda14cbcSMatt Macy #include <errno.h> 28*eda14cbcSMatt Macy #include <openssl/evp.h> 29*eda14cbcSMatt Macy #include <libzfs.h> 30*eda14cbcSMatt Macy #include "libzfs_impl.h" 31*eda14cbcSMatt Macy #include "zfeature_common.h" 32*eda14cbcSMatt Macy 33*eda14cbcSMatt Macy /* 34*eda14cbcSMatt Macy * User keys are used to decrypt the master encryption keys of a dataset. This 35*eda14cbcSMatt Macy * indirection allows a user to change his / her access key without having to 36*eda14cbcSMatt Macy * re-encrypt the entire dataset. User keys can be provided in one of several 37*eda14cbcSMatt Macy * ways. Raw keys are simply given to the kernel as is. Similarly, hex keys 38*eda14cbcSMatt Macy * are converted to binary and passed into the kernel. Password based keys are 39*eda14cbcSMatt Macy * a bit more complicated. Passwords alone do not provide suitable entropy for 40*eda14cbcSMatt Macy * encryption and may be too short or too long to be used. In order to derive 41*eda14cbcSMatt Macy * a more appropriate key we use a PBKDF2 function. This function is designed 42*eda14cbcSMatt Macy * to take a (relatively) long time to calculate in order to discourage 43*eda14cbcSMatt Macy * attackers from guessing from a list of common passwords. PBKDF2 requires 44*eda14cbcSMatt Macy * 2 additional parameters. The first is the number of iterations to run, which 45*eda14cbcSMatt Macy * will ultimately determine how long it takes to derive the resulting key from 46*eda14cbcSMatt Macy * the password. The second parameter is a salt that is randomly generated for 47*eda14cbcSMatt Macy * each dataset. The salt is used to "tweak" PBKDF2 such that a group of 48*eda14cbcSMatt Macy * attackers cannot reasonably generate a table of commonly known passwords to 49*eda14cbcSMatt Macy * their output keys and expect it work for all past and future PBKDF2 users. 50*eda14cbcSMatt Macy * We store the salt as a hidden property of the dataset (although it is 51*eda14cbcSMatt Macy * technically ok if the salt is known to the attacker). 52*eda14cbcSMatt Macy */ 53*eda14cbcSMatt Macy 54*eda14cbcSMatt Macy typedef enum key_locator { 55*eda14cbcSMatt Macy KEY_LOCATOR_NONE, 56*eda14cbcSMatt Macy KEY_LOCATOR_PROMPT, 57*eda14cbcSMatt Macy KEY_LOCATOR_URI 58*eda14cbcSMatt Macy } key_locator_t; 59*eda14cbcSMatt Macy 60*eda14cbcSMatt Macy #define MIN_PASSPHRASE_LEN 8 61*eda14cbcSMatt Macy #define MAX_PASSPHRASE_LEN 512 62*eda14cbcSMatt Macy #define MAX_KEY_PROMPT_ATTEMPTS 3 63*eda14cbcSMatt Macy 64*eda14cbcSMatt Macy static int caught_interrupt; 65*eda14cbcSMatt Macy 66*eda14cbcSMatt Macy static int get_key_material_file(libzfs_handle_t *, const char *, const char *, 67*eda14cbcSMatt Macy zfs_keyformat_t, boolean_t, uint8_t **, size_t *); 68*eda14cbcSMatt Macy 69*eda14cbcSMatt Macy static zfs_uri_handler_t uri_handlers[] = { 70*eda14cbcSMatt Macy { "file", get_key_material_file }, 71*eda14cbcSMatt Macy { NULL, NULL } 72*eda14cbcSMatt Macy }; 73*eda14cbcSMatt Macy 74*eda14cbcSMatt Macy static int 75*eda14cbcSMatt Macy pkcs11_get_urandom(uint8_t *buf, size_t bytes) 76*eda14cbcSMatt Macy { 77*eda14cbcSMatt Macy int rand; 78*eda14cbcSMatt Macy ssize_t bytes_read = 0; 79*eda14cbcSMatt Macy 80*eda14cbcSMatt Macy rand = open("/dev/urandom", O_RDONLY); 81*eda14cbcSMatt Macy 82*eda14cbcSMatt Macy if (rand < 0) 83*eda14cbcSMatt Macy return (rand); 84*eda14cbcSMatt Macy 85*eda14cbcSMatt Macy while (bytes_read < bytes) { 86*eda14cbcSMatt Macy ssize_t rc = read(rand, buf + bytes_read, bytes - bytes_read); 87*eda14cbcSMatt Macy if (rc < 0) 88*eda14cbcSMatt Macy break; 89*eda14cbcSMatt Macy bytes_read += rc; 90*eda14cbcSMatt Macy } 91*eda14cbcSMatt Macy 92*eda14cbcSMatt Macy (void) close(rand); 93*eda14cbcSMatt Macy 94*eda14cbcSMatt Macy return (bytes_read); 95*eda14cbcSMatt Macy } 96*eda14cbcSMatt Macy 97*eda14cbcSMatt Macy static int 98*eda14cbcSMatt Macy zfs_prop_parse_keylocation(libzfs_handle_t *restrict hdl, const char *str, 99*eda14cbcSMatt Macy zfs_keylocation_t *restrict locp, char **restrict schemep) 100*eda14cbcSMatt Macy { 101*eda14cbcSMatt Macy *locp = ZFS_KEYLOCATION_NONE; 102*eda14cbcSMatt Macy *schemep = NULL; 103*eda14cbcSMatt Macy 104*eda14cbcSMatt Macy if (strcmp("prompt", str) == 0) { 105*eda14cbcSMatt Macy *locp = ZFS_KEYLOCATION_PROMPT; 106*eda14cbcSMatt Macy return (0); 107*eda14cbcSMatt Macy } 108*eda14cbcSMatt Macy 109*eda14cbcSMatt Macy regmatch_t pmatch[2]; 110*eda14cbcSMatt Macy 111*eda14cbcSMatt Macy if (regexec(&hdl->libzfs_urire, str, ARRAY_SIZE(pmatch), 112*eda14cbcSMatt Macy pmatch, 0) == 0) { 113*eda14cbcSMatt Macy size_t scheme_len; 114*eda14cbcSMatt Macy 115*eda14cbcSMatt Macy if (pmatch[1].rm_so == -1) { 116*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 117*eda14cbcSMatt Macy "Invalid URI")); 118*eda14cbcSMatt Macy return (EINVAL); 119*eda14cbcSMatt Macy } 120*eda14cbcSMatt Macy 121*eda14cbcSMatt Macy scheme_len = pmatch[1].rm_eo - pmatch[1].rm_so; 122*eda14cbcSMatt Macy 123*eda14cbcSMatt Macy *schemep = calloc(1, scheme_len + 1); 124*eda14cbcSMatt Macy if (*schemep == NULL) { 125*eda14cbcSMatt Macy int ret = errno; 126*eda14cbcSMatt Macy 127*eda14cbcSMatt Macy errno = 0; 128*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 129*eda14cbcSMatt Macy "Invalid URI")); 130*eda14cbcSMatt Macy return (ret); 131*eda14cbcSMatt Macy } 132*eda14cbcSMatt Macy 133*eda14cbcSMatt Macy (void) memcpy(*schemep, str + pmatch[1].rm_so, scheme_len); 134*eda14cbcSMatt Macy *locp = ZFS_KEYLOCATION_URI; 135*eda14cbcSMatt Macy return (0); 136*eda14cbcSMatt Macy } 137*eda14cbcSMatt Macy 138*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Invalid keylocation")); 139*eda14cbcSMatt Macy return (EINVAL); 140*eda14cbcSMatt Macy } 141*eda14cbcSMatt Macy 142*eda14cbcSMatt Macy static int 143*eda14cbcSMatt Macy hex_key_to_raw(char *hex, int hexlen, uint8_t *out) 144*eda14cbcSMatt Macy { 145*eda14cbcSMatt Macy int ret, i; 146*eda14cbcSMatt Macy unsigned int c; 147*eda14cbcSMatt Macy 148*eda14cbcSMatt Macy for (i = 0; i < hexlen; i += 2) { 149*eda14cbcSMatt Macy if (!isxdigit(hex[i]) || !isxdigit(hex[i + 1])) { 150*eda14cbcSMatt Macy ret = EINVAL; 151*eda14cbcSMatt Macy goto error; 152*eda14cbcSMatt Macy } 153*eda14cbcSMatt Macy 154*eda14cbcSMatt Macy ret = sscanf(&hex[i], "%02x", &c); 155*eda14cbcSMatt Macy if (ret != 1) { 156*eda14cbcSMatt Macy ret = EINVAL; 157*eda14cbcSMatt Macy goto error; 158*eda14cbcSMatt Macy } 159*eda14cbcSMatt Macy 160*eda14cbcSMatt Macy out[i / 2] = c; 161*eda14cbcSMatt Macy } 162*eda14cbcSMatt Macy 163*eda14cbcSMatt Macy return (0); 164*eda14cbcSMatt Macy 165*eda14cbcSMatt Macy error: 166*eda14cbcSMatt Macy return (ret); 167*eda14cbcSMatt Macy } 168*eda14cbcSMatt Macy 169*eda14cbcSMatt Macy 170*eda14cbcSMatt Macy static void 171*eda14cbcSMatt Macy catch_signal(int sig) 172*eda14cbcSMatt Macy { 173*eda14cbcSMatt Macy caught_interrupt = sig; 174*eda14cbcSMatt Macy } 175*eda14cbcSMatt Macy 176*eda14cbcSMatt Macy static const char * 177*eda14cbcSMatt Macy get_format_prompt_string(zfs_keyformat_t format) 178*eda14cbcSMatt Macy { 179*eda14cbcSMatt Macy switch (format) { 180*eda14cbcSMatt Macy case ZFS_KEYFORMAT_RAW: 181*eda14cbcSMatt Macy return ("raw key"); 182*eda14cbcSMatt Macy case ZFS_KEYFORMAT_HEX: 183*eda14cbcSMatt Macy return ("hex key"); 184*eda14cbcSMatt Macy case ZFS_KEYFORMAT_PASSPHRASE: 185*eda14cbcSMatt Macy return ("passphrase"); 186*eda14cbcSMatt Macy default: 187*eda14cbcSMatt Macy /* shouldn't happen */ 188*eda14cbcSMatt Macy return (NULL); 189*eda14cbcSMatt Macy } 190*eda14cbcSMatt Macy } 191*eda14cbcSMatt Macy 192*eda14cbcSMatt Macy /* do basic validation of the key material */ 193*eda14cbcSMatt Macy static int 194*eda14cbcSMatt Macy validate_key(libzfs_handle_t *hdl, zfs_keyformat_t keyformat, 195*eda14cbcSMatt Macy const char *key, size_t keylen) 196*eda14cbcSMatt Macy { 197*eda14cbcSMatt Macy switch (keyformat) { 198*eda14cbcSMatt Macy case ZFS_KEYFORMAT_RAW: 199*eda14cbcSMatt Macy /* verify the key length is correct */ 200*eda14cbcSMatt Macy if (keylen < WRAPPING_KEY_LEN) { 201*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 202*eda14cbcSMatt Macy "Raw key too short (expected %u)."), 203*eda14cbcSMatt Macy WRAPPING_KEY_LEN); 204*eda14cbcSMatt Macy return (EINVAL); 205*eda14cbcSMatt Macy } 206*eda14cbcSMatt Macy 207*eda14cbcSMatt Macy if (keylen > WRAPPING_KEY_LEN) { 208*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 209*eda14cbcSMatt Macy "Raw key too long (expected %u)."), 210*eda14cbcSMatt Macy WRAPPING_KEY_LEN); 211*eda14cbcSMatt Macy return (EINVAL); 212*eda14cbcSMatt Macy } 213*eda14cbcSMatt Macy break; 214*eda14cbcSMatt Macy case ZFS_KEYFORMAT_HEX: 215*eda14cbcSMatt Macy /* verify the key length is correct */ 216*eda14cbcSMatt Macy if (keylen < WRAPPING_KEY_LEN * 2) { 217*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 218*eda14cbcSMatt Macy "Hex key too short (expected %u)."), 219*eda14cbcSMatt Macy WRAPPING_KEY_LEN * 2); 220*eda14cbcSMatt Macy return (EINVAL); 221*eda14cbcSMatt Macy } 222*eda14cbcSMatt Macy 223*eda14cbcSMatt Macy if (keylen > WRAPPING_KEY_LEN * 2) { 224*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 225*eda14cbcSMatt Macy "Hex key too long (expected %u)."), 226*eda14cbcSMatt Macy WRAPPING_KEY_LEN * 2); 227*eda14cbcSMatt Macy return (EINVAL); 228*eda14cbcSMatt Macy } 229*eda14cbcSMatt Macy 230*eda14cbcSMatt Macy /* check for invalid hex digits */ 231*eda14cbcSMatt Macy for (size_t i = 0; i < WRAPPING_KEY_LEN * 2; i++) { 232*eda14cbcSMatt Macy if (!isxdigit(key[i])) { 233*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 234*eda14cbcSMatt Macy "Invalid hex character detected.")); 235*eda14cbcSMatt Macy return (EINVAL); 236*eda14cbcSMatt Macy } 237*eda14cbcSMatt Macy } 238*eda14cbcSMatt Macy break; 239*eda14cbcSMatt Macy case ZFS_KEYFORMAT_PASSPHRASE: 240*eda14cbcSMatt Macy /* verify the length is within bounds */ 241*eda14cbcSMatt Macy if (keylen > MAX_PASSPHRASE_LEN) { 242*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 243*eda14cbcSMatt Macy "Passphrase too long (max %u)."), 244*eda14cbcSMatt Macy MAX_PASSPHRASE_LEN); 245*eda14cbcSMatt Macy return (EINVAL); 246*eda14cbcSMatt Macy } 247*eda14cbcSMatt Macy 248*eda14cbcSMatt Macy if (keylen < MIN_PASSPHRASE_LEN) { 249*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 250*eda14cbcSMatt Macy "Passphrase too short (min %u)."), 251*eda14cbcSMatt Macy MIN_PASSPHRASE_LEN); 252*eda14cbcSMatt Macy return (EINVAL); 253*eda14cbcSMatt Macy } 254*eda14cbcSMatt Macy break; 255*eda14cbcSMatt Macy default: 256*eda14cbcSMatt Macy /* can't happen, checked above */ 257*eda14cbcSMatt Macy break; 258*eda14cbcSMatt Macy } 259*eda14cbcSMatt Macy 260*eda14cbcSMatt Macy return (0); 261*eda14cbcSMatt Macy } 262*eda14cbcSMatt Macy 263*eda14cbcSMatt Macy static int 264*eda14cbcSMatt Macy libzfs_getpassphrase(zfs_keyformat_t keyformat, boolean_t is_reenter, 265*eda14cbcSMatt Macy boolean_t new_key, const char *fsname, 266*eda14cbcSMatt Macy char **restrict res, size_t *restrict reslen) 267*eda14cbcSMatt Macy { 268*eda14cbcSMatt Macy FILE *f = stdin; 269*eda14cbcSMatt Macy size_t buflen = 0; 270*eda14cbcSMatt Macy ssize_t bytes; 271*eda14cbcSMatt Macy int ret = 0; 272*eda14cbcSMatt Macy struct termios old_term, new_term; 273*eda14cbcSMatt Macy struct sigaction act, osigint, osigtstp; 274*eda14cbcSMatt Macy 275*eda14cbcSMatt Macy *res = NULL; 276*eda14cbcSMatt Macy *reslen = 0; 277*eda14cbcSMatt Macy 278*eda14cbcSMatt Macy /* 279*eda14cbcSMatt Macy * handle SIGINT and ignore SIGSTP. This is necessary to 280*eda14cbcSMatt Macy * restore the state of the terminal. 281*eda14cbcSMatt Macy */ 282*eda14cbcSMatt Macy caught_interrupt = 0; 283*eda14cbcSMatt Macy act.sa_flags = 0; 284*eda14cbcSMatt Macy (void) sigemptyset(&act.sa_mask); 285*eda14cbcSMatt Macy act.sa_handler = catch_signal; 286*eda14cbcSMatt Macy 287*eda14cbcSMatt Macy (void) sigaction(SIGINT, &act, &osigint); 288*eda14cbcSMatt Macy act.sa_handler = SIG_IGN; 289*eda14cbcSMatt Macy (void) sigaction(SIGTSTP, &act, &osigtstp); 290*eda14cbcSMatt Macy 291*eda14cbcSMatt Macy (void) printf("%s %s%s", 292*eda14cbcSMatt Macy is_reenter ? "Re-enter" : "Enter", 293*eda14cbcSMatt Macy new_key ? "new " : "", 294*eda14cbcSMatt Macy get_format_prompt_string(keyformat)); 295*eda14cbcSMatt Macy if (fsname != NULL) 296*eda14cbcSMatt Macy (void) printf(" for '%s'", fsname); 297*eda14cbcSMatt Macy (void) fputc(':', stdout); 298*eda14cbcSMatt Macy (void) fflush(stdout); 299*eda14cbcSMatt Macy 300*eda14cbcSMatt Macy /* disable the terminal echo for key input */ 301*eda14cbcSMatt Macy (void) tcgetattr(fileno(f), &old_term); 302*eda14cbcSMatt Macy 303*eda14cbcSMatt Macy new_term = old_term; 304*eda14cbcSMatt Macy new_term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); 305*eda14cbcSMatt Macy 306*eda14cbcSMatt Macy ret = tcsetattr(fileno(f), TCSAFLUSH, &new_term); 307*eda14cbcSMatt Macy if (ret != 0) { 308*eda14cbcSMatt Macy ret = errno; 309*eda14cbcSMatt Macy errno = 0; 310*eda14cbcSMatt Macy goto out; 311*eda14cbcSMatt Macy } 312*eda14cbcSMatt Macy 313*eda14cbcSMatt Macy bytes = getline(res, &buflen, f); 314*eda14cbcSMatt Macy if (bytes < 0) { 315*eda14cbcSMatt Macy ret = errno; 316*eda14cbcSMatt Macy errno = 0; 317*eda14cbcSMatt Macy goto out; 318*eda14cbcSMatt Macy } 319*eda14cbcSMatt Macy 320*eda14cbcSMatt Macy /* trim the ending newline if it exists */ 321*eda14cbcSMatt Macy if (bytes > 0 && (*res)[bytes - 1] == '\n') { 322*eda14cbcSMatt Macy (*res)[bytes - 1] = '\0'; 323*eda14cbcSMatt Macy bytes--; 324*eda14cbcSMatt Macy } 325*eda14cbcSMatt Macy 326*eda14cbcSMatt Macy *reslen = bytes; 327*eda14cbcSMatt Macy 328*eda14cbcSMatt Macy out: 329*eda14cbcSMatt Macy /* reset the terminal */ 330*eda14cbcSMatt Macy (void) tcsetattr(fileno(f), TCSAFLUSH, &old_term); 331*eda14cbcSMatt Macy (void) sigaction(SIGINT, &osigint, NULL); 332*eda14cbcSMatt Macy (void) sigaction(SIGTSTP, &osigtstp, NULL); 333*eda14cbcSMatt Macy 334*eda14cbcSMatt Macy /* if we caught a signal, re-throw it now */ 335*eda14cbcSMatt Macy if (caught_interrupt != 0) 336*eda14cbcSMatt Macy (void) kill(getpid(), caught_interrupt); 337*eda14cbcSMatt Macy 338*eda14cbcSMatt Macy /* print the newline that was not echo'd */ 339*eda14cbcSMatt Macy (void) printf("\n"); 340*eda14cbcSMatt Macy 341*eda14cbcSMatt Macy return (ret); 342*eda14cbcSMatt Macy } 343*eda14cbcSMatt Macy 344*eda14cbcSMatt Macy static int 345*eda14cbcSMatt Macy get_key_interactive(libzfs_handle_t *restrict hdl, const char *fsname, 346*eda14cbcSMatt Macy zfs_keyformat_t keyformat, boolean_t confirm_key, boolean_t newkey, 347*eda14cbcSMatt Macy uint8_t **restrict outbuf, size_t *restrict len_out) 348*eda14cbcSMatt Macy { 349*eda14cbcSMatt Macy char *buf = NULL, *buf2 = NULL; 350*eda14cbcSMatt Macy size_t buflen = 0, buf2len = 0; 351*eda14cbcSMatt Macy int ret = 0; 352*eda14cbcSMatt Macy 353*eda14cbcSMatt Macy ASSERT(isatty(fileno(stdin))); 354*eda14cbcSMatt Macy 355*eda14cbcSMatt Macy /* raw keys cannot be entered on the terminal */ 356*eda14cbcSMatt Macy if (keyformat == ZFS_KEYFORMAT_RAW) { 357*eda14cbcSMatt Macy ret = EINVAL; 358*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 359*eda14cbcSMatt Macy "Cannot enter raw keys on the terminal")); 360*eda14cbcSMatt Macy goto out; 361*eda14cbcSMatt Macy } 362*eda14cbcSMatt Macy 363*eda14cbcSMatt Macy /* prompt for the key */ 364*eda14cbcSMatt Macy if ((ret = libzfs_getpassphrase(keyformat, B_FALSE, newkey, fsname, 365*eda14cbcSMatt Macy &buf, &buflen)) != 0) { 366*eda14cbcSMatt Macy free(buf); 367*eda14cbcSMatt Macy buf = NULL; 368*eda14cbcSMatt Macy buflen = 0; 369*eda14cbcSMatt Macy goto out; 370*eda14cbcSMatt Macy } 371*eda14cbcSMatt Macy 372*eda14cbcSMatt Macy if (!confirm_key) 373*eda14cbcSMatt Macy goto out; 374*eda14cbcSMatt Macy 375*eda14cbcSMatt Macy if ((ret = validate_key(hdl, keyformat, buf, buflen)) != 0) { 376*eda14cbcSMatt Macy free(buf); 377*eda14cbcSMatt Macy return (ret); 378*eda14cbcSMatt Macy } 379*eda14cbcSMatt Macy 380*eda14cbcSMatt Macy ret = libzfs_getpassphrase(keyformat, B_TRUE, newkey, fsname, &buf2, 381*eda14cbcSMatt Macy &buf2len); 382*eda14cbcSMatt Macy if (ret != 0) { 383*eda14cbcSMatt Macy free(buf); 384*eda14cbcSMatt Macy free(buf2); 385*eda14cbcSMatt Macy buf = buf2 = NULL; 386*eda14cbcSMatt Macy buflen = buf2len = 0; 387*eda14cbcSMatt Macy goto out; 388*eda14cbcSMatt Macy } 389*eda14cbcSMatt Macy 390*eda14cbcSMatt Macy if (buflen != buf2len || strcmp(buf, buf2) != 0) { 391*eda14cbcSMatt Macy free(buf); 392*eda14cbcSMatt Macy buf = NULL; 393*eda14cbcSMatt Macy buflen = 0; 394*eda14cbcSMatt Macy 395*eda14cbcSMatt Macy ret = EINVAL; 396*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 397*eda14cbcSMatt Macy "Provided keys do not match.")); 398*eda14cbcSMatt Macy } 399*eda14cbcSMatt Macy 400*eda14cbcSMatt Macy free(buf2); 401*eda14cbcSMatt Macy 402*eda14cbcSMatt Macy out: 403*eda14cbcSMatt Macy *outbuf = (uint8_t *)buf; 404*eda14cbcSMatt Macy *len_out = buflen; 405*eda14cbcSMatt Macy return (ret); 406*eda14cbcSMatt Macy } 407*eda14cbcSMatt Macy 408*eda14cbcSMatt Macy static int 409*eda14cbcSMatt Macy get_key_material_raw(FILE *fd, zfs_keyformat_t keyformat, 410*eda14cbcSMatt Macy uint8_t **buf, size_t *len_out) 411*eda14cbcSMatt Macy { 412*eda14cbcSMatt Macy int ret = 0; 413*eda14cbcSMatt Macy size_t buflen = 0; 414*eda14cbcSMatt Macy 415*eda14cbcSMatt Macy *len_out = 0; 416*eda14cbcSMatt Macy 417*eda14cbcSMatt Macy /* read the key material */ 418*eda14cbcSMatt Macy if (keyformat != ZFS_KEYFORMAT_RAW) { 419*eda14cbcSMatt Macy ssize_t bytes; 420*eda14cbcSMatt Macy 421*eda14cbcSMatt Macy bytes = getline((char **)buf, &buflen, fd); 422*eda14cbcSMatt Macy if (bytes < 0) { 423*eda14cbcSMatt Macy ret = errno; 424*eda14cbcSMatt Macy errno = 0; 425*eda14cbcSMatt Macy goto out; 426*eda14cbcSMatt Macy } 427*eda14cbcSMatt Macy 428*eda14cbcSMatt Macy /* trim the ending newline if it exists */ 429*eda14cbcSMatt Macy if (bytes > 0 && (*buf)[bytes - 1] == '\n') { 430*eda14cbcSMatt Macy (*buf)[bytes - 1] = '\0'; 431*eda14cbcSMatt Macy bytes--; 432*eda14cbcSMatt Macy } 433*eda14cbcSMatt Macy 434*eda14cbcSMatt Macy *len_out = bytes; 435*eda14cbcSMatt Macy } else { 436*eda14cbcSMatt Macy size_t n; 437*eda14cbcSMatt Macy 438*eda14cbcSMatt Macy /* 439*eda14cbcSMatt Macy * Raw keys may have newline characters in them and so can't 440*eda14cbcSMatt Macy * use getline(). Here we attempt to read 33 bytes so that we 441*eda14cbcSMatt Macy * can properly check the key length (the file should only have 442*eda14cbcSMatt Macy * 32 bytes). 443*eda14cbcSMatt Macy */ 444*eda14cbcSMatt Macy *buf = malloc((WRAPPING_KEY_LEN + 1) * sizeof (uint8_t)); 445*eda14cbcSMatt Macy if (*buf == NULL) { 446*eda14cbcSMatt Macy ret = ENOMEM; 447*eda14cbcSMatt Macy goto out; 448*eda14cbcSMatt Macy } 449*eda14cbcSMatt Macy 450*eda14cbcSMatt Macy n = fread(*buf, 1, WRAPPING_KEY_LEN + 1, fd); 451*eda14cbcSMatt Macy if (n == 0 || ferror(fd)) { 452*eda14cbcSMatt Macy /* size errors are handled by the calling function */ 453*eda14cbcSMatt Macy free(*buf); 454*eda14cbcSMatt Macy *buf = NULL; 455*eda14cbcSMatt Macy ret = errno; 456*eda14cbcSMatt Macy errno = 0; 457*eda14cbcSMatt Macy goto out; 458*eda14cbcSMatt Macy } 459*eda14cbcSMatt Macy 460*eda14cbcSMatt Macy *len_out = n; 461*eda14cbcSMatt Macy } 462*eda14cbcSMatt Macy out: 463*eda14cbcSMatt Macy return (ret); 464*eda14cbcSMatt Macy } 465*eda14cbcSMatt Macy 466*eda14cbcSMatt Macy static int 467*eda14cbcSMatt Macy get_key_material_file(libzfs_handle_t *hdl, const char *uri, 468*eda14cbcSMatt Macy const char *fsname, zfs_keyformat_t keyformat, boolean_t newkey, 469*eda14cbcSMatt Macy uint8_t **restrict buf, size_t *restrict len_out) 470*eda14cbcSMatt Macy { 471*eda14cbcSMatt Macy FILE *f = NULL; 472*eda14cbcSMatt Macy int ret = 0; 473*eda14cbcSMatt Macy 474*eda14cbcSMatt Macy if (strlen(uri) < 7) 475*eda14cbcSMatt Macy return (EINVAL); 476*eda14cbcSMatt Macy 477*eda14cbcSMatt Macy if ((f = fopen(uri + 7, "r")) == NULL) { 478*eda14cbcSMatt Macy ret = errno; 479*eda14cbcSMatt Macy errno = 0; 480*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 481*eda14cbcSMatt Macy "Failed to open key material file")); 482*eda14cbcSMatt Macy return (ret); 483*eda14cbcSMatt Macy } 484*eda14cbcSMatt Macy 485*eda14cbcSMatt Macy ret = get_key_material_raw(f, keyformat, buf, len_out); 486*eda14cbcSMatt Macy 487*eda14cbcSMatt Macy (void) fclose(f); 488*eda14cbcSMatt Macy 489*eda14cbcSMatt Macy return (ret); 490*eda14cbcSMatt Macy } 491*eda14cbcSMatt Macy 492*eda14cbcSMatt Macy /* 493*eda14cbcSMatt Macy * Attempts to fetch key material, no matter where it might live. The key 494*eda14cbcSMatt Macy * material is allocated and returned in km_out. *can_retry_out will be set 495*eda14cbcSMatt Macy * to B_TRUE if the user is providing the key material interactively, allowing 496*eda14cbcSMatt Macy * for re-entry attempts. 497*eda14cbcSMatt Macy */ 498*eda14cbcSMatt Macy static int 499*eda14cbcSMatt Macy get_key_material(libzfs_handle_t *hdl, boolean_t do_verify, boolean_t newkey, 500*eda14cbcSMatt Macy zfs_keyformat_t keyformat, char *keylocation, const char *fsname, 501*eda14cbcSMatt Macy uint8_t **km_out, size_t *kmlen_out, boolean_t *can_retry_out) 502*eda14cbcSMatt Macy { 503*eda14cbcSMatt Macy int ret; 504*eda14cbcSMatt Macy zfs_keylocation_t keyloc = ZFS_KEYLOCATION_NONE; 505*eda14cbcSMatt Macy uint8_t *km = NULL; 506*eda14cbcSMatt Macy size_t kmlen = 0; 507*eda14cbcSMatt Macy char *uri_scheme = NULL; 508*eda14cbcSMatt Macy zfs_uri_handler_t *handler = NULL; 509*eda14cbcSMatt Macy boolean_t can_retry = B_FALSE; 510*eda14cbcSMatt Macy 511*eda14cbcSMatt Macy /* verify and parse the keylocation */ 512*eda14cbcSMatt Macy ret = zfs_prop_parse_keylocation(hdl, keylocation, &keyloc, 513*eda14cbcSMatt Macy &uri_scheme); 514*eda14cbcSMatt Macy if (ret != 0) 515*eda14cbcSMatt Macy goto error; 516*eda14cbcSMatt Macy 517*eda14cbcSMatt Macy /* open the appropriate file descriptor */ 518*eda14cbcSMatt Macy switch (keyloc) { 519*eda14cbcSMatt Macy case ZFS_KEYLOCATION_PROMPT: 520*eda14cbcSMatt Macy if (isatty(fileno(stdin))) { 521*eda14cbcSMatt Macy can_retry = B_TRUE; 522*eda14cbcSMatt Macy ret = get_key_interactive(hdl, fsname, keyformat, 523*eda14cbcSMatt Macy do_verify, newkey, &km, &kmlen); 524*eda14cbcSMatt Macy } else { 525*eda14cbcSMatt Macy /* fetch the key material into the buffer */ 526*eda14cbcSMatt Macy ret = get_key_material_raw(stdin, keyformat, &km, 527*eda14cbcSMatt Macy &kmlen); 528*eda14cbcSMatt Macy } 529*eda14cbcSMatt Macy 530*eda14cbcSMatt Macy if (ret != 0) 531*eda14cbcSMatt Macy goto error; 532*eda14cbcSMatt Macy 533*eda14cbcSMatt Macy break; 534*eda14cbcSMatt Macy case ZFS_KEYLOCATION_URI: 535*eda14cbcSMatt Macy for (handler = uri_handlers; handler->zuh_scheme != NULL; 536*eda14cbcSMatt Macy handler++) { 537*eda14cbcSMatt Macy if (strcmp(handler->zuh_scheme, uri_scheme) != 0) 538*eda14cbcSMatt Macy continue; 539*eda14cbcSMatt Macy 540*eda14cbcSMatt Macy if ((ret = handler->zuh_handler(hdl, keylocation, 541*eda14cbcSMatt Macy fsname, keyformat, newkey, &km, &kmlen)) != 0) 542*eda14cbcSMatt Macy goto error; 543*eda14cbcSMatt Macy 544*eda14cbcSMatt Macy break; 545*eda14cbcSMatt Macy } 546*eda14cbcSMatt Macy 547*eda14cbcSMatt Macy ret = ENOTSUP; 548*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 549*eda14cbcSMatt Macy "URI scheme is not supported")); 550*eda14cbcSMatt Macy 551*eda14cbcSMatt Macy break; 552*eda14cbcSMatt Macy default: 553*eda14cbcSMatt Macy ret = EINVAL; 554*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 555*eda14cbcSMatt Macy "Invalid keylocation.")); 556*eda14cbcSMatt Macy goto error; 557*eda14cbcSMatt Macy } 558*eda14cbcSMatt Macy 559*eda14cbcSMatt Macy if ((ret = validate_key(hdl, keyformat, (const char *)km, kmlen)) != 0) 560*eda14cbcSMatt Macy goto error; 561*eda14cbcSMatt Macy 562*eda14cbcSMatt Macy *km_out = km; 563*eda14cbcSMatt Macy *kmlen_out = kmlen; 564*eda14cbcSMatt Macy if (can_retry_out != NULL) 565*eda14cbcSMatt Macy *can_retry_out = can_retry; 566*eda14cbcSMatt Macy 567*eda14cbcSMatt Macy free(uri_scheme); 568*eda14cbcSMatt Macy return (0); 569*eda14cbcSMatt Macy 570*eda14cbcSMatt Macy error: 571*eda14cbcSMatt Macy free(km); 572*eda14cbcSMatt Macy 573*eda14cbcSMatt Macy *km_out = NULL; 574*eda14cbcSMatt Macy *kmlen_out = 0; 575*eda14cbcSMatt Macy 576*eda14cbcSMatt Macy if (can_retry_out != NULL) 577*eda14cbcSMatt Macy *can_retry_out = can_retry; 578*eda14cbcSMatt Macy 579*eda14cbcSMatt Macy free(uri_scheme); 580*eda14cbcSMatt Macy return (ret); 581*eda14cbcSMatt Macy } 582*eda14cbcSMatt Macy 583*eda14cbcSMatt Macy static int 584*eda14cbcSMatt Macy derive_key(libzfs_handle_t *hdl, zfs_keyformat_t format, uint64_t iters, 585*eda14cbcSMatt Macy uint8_t *key_material, size_t key_material_len, uint64_t salt, 586*eda14cbcSMatt Macy uint8_t **key_out) 587*eda14cbcSMatt Macy { 588*eda14cbcSMatt Macy int ret; 589*eda14cbcSMatt Macy uint8_t *key; 590*eda14cbcSMatt Macy 591*eda14cbcSMatt Macy *key_out = NULL; 592*eda14cbcSMatt Macy 593*eda14cbcSMatt Macy key = zfs_alloc(hdl, WRAPPING_KEY_LEN); 594*eda14cbcSMatt Macy if (!key) 595*eda14cbcSMatt Macy return (ENOMEM); 596*eda14cbcSMatt Macy 597*eda14cbcSMatt Macy switch (format) { 598*eda14cbcSMatt Macy case ZFS_KEYFORMAT_RAW: 599*eda14cbcSMatt Macy bcopy(key_material, key, WRAPPING_KEY_LEN); 600*eda14cbcSMatt Macy break; 601*eda14cbcSMatt Macy case ZFS_KEYFORMAT_HEX: 602*eda14cbcSMatt Macy ret = hex_key_to_raw((char *)key_material, 603*eda14cbcSMatt Macy WRAPPING_KEY_LEN * 2, key); 604*eda14cbcSMatt Macy if (ret != 0) { 605*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 606*eda14cbcSMatt Macy "Invalid hex key provided.")); 607*eda14cbcSMatt Macy goto error; 608*eda14cbcSMatt Macy } 609*eda14cbcSMatt Macy break; 610*eda14cbcSMatt Macy case ZFS_KEYFORMAT_PASSPHRASE: 611*eda14cbcSMatt Macy salt = LE_64(salt); 612*eda14cbcSMatt Macy 613*eda14cbcSMatt Macy ret = PKCS5_PBKDF2_HMAC_SHA1((char *)key_material, 614*eda14cbcSMatt Macy strlen((char *)key_material), ((uint8_t *)&salt), 615*eda14cbcSMatt Macy sizeof (uint64_t), iters, WRAPPING_KEY_LEN, key); 616*eda14cbcSMatt Macy if (ret != 1) { 617*eda14cbcSMatt Macy ret = EIO; 618*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 619*eda14cbcSMatt Macy "Failed to generate key from passphrase.")); 620*eda14cbcSMatt Macy goto error; 621*eda14cbcSMatt Macy } 622*eda14cbcSMatt Macy break; 623*eda14cbcSMatt Macy default: 624*eda14cbcSMatt Macy ret = EINVAL; 625*eda14cbcSMatt Macy goto error; 626*eda14cbcSMatt Macy } 627*eda14cbcSMatt Macy 628*eda14cbcSMatt Macy *key_out = key; 629*eda14cbcSMatt Macy return (0); 630*eda14cbcSMatt Macy 631*eda14cbcSMatt Macy error: 632*eda14cbcSMatt Macy free(key); 633*eda14cbcSMatt Macy 634*eda14cbcSMatt Macy *key_out = NULL; 635*eda14cbcSMatt Macy return (ret); 636*eda14cbcSMatt Macy } 637*eda14cbcSMatt Macy 638*eda14cbcSMatt Macy static boolean_t 639*eda14cbcSMatt Macy encryption_feature_is_enabled(zpool_handle_t *zph) 640*eda14cbcSMatt Macy { 641*eda14cbcSMatt Macy nvlist_t *features; 642*eda14cbcSMatt Macy uint64_t feat_refcount; 643*eda14cbcSMatt Macy 644*eda14cbcSMatt Macy /* check that features can be enabled */ 645*eda14cbcSMatt Macy if (zpool_get_prop_int(zph, ZPOOL_PROP_VERSION, NULL) 646*eda14cbcSMatt Macy < SPA_VERSION_FEATURES) 647*eda14cbcSMatt Macy return (B_FALSE); 648*eda14cbcSMatt Macy 649*eda14cbcSMatt Macy /* check for crypto feature */ 650*eda14cbcSMatt Macy features = zpool_get_features(zph); 651*eda14cbcSMatt Macy if (!features || nvlist_lookup_uint64(features, 652*eda14cbcSMatt Macy spa_feature_table[SPA_FEATURE_ENCRYPTION].fi_guid, 653*eda14cbcSMatt Macy &feat_refcount) != 0) 654*eda14cbcSMatt Macy return (B_FALSE); 655*eda14cbcSMatt Macy 656*eda14cbcSMatt Macy return (B_TRUE); 657*eda14cbcSMatt Macy } 658*eda14cbcSMatt Macy 659*eda14cbcSMatt Macy static int 660*eda14cbcSMatt Macy populate_create_encryption_params_nvlists(libzfs_handle_t *hdl, 661*eda14cbcSMatt Macy zfs_handle_t *zhp, boolean_t newkey, zfs_keyformat_t keyformat, 662*eda14cbcSMatt Macy char *keylocation, nvlist_t *props, uint8_t **wkeydata, uint_t *wkeylen) 663*eda14cbcSMatt Macy { 664*eda14cbcSMatt Macy int ret; 665*eda14cbcSMatt Macy uint64_t iters = 0, salt = 0; 666*eda14cbcSMatt Macy uint8_t *key_material = NULL; 667*eda14cbcSMatt Macy size_t key_material_len = 0; 668*eda14cbcSMatt Macy uint8_t *key_data = NULL; 669*eda14cbcSMatt Macy const char *fsname = (zhp) ? zfs_get_name(zhp) : NULL; 670*eda14cbcSMatt Macy 671*eda14cbcSMatt Macy /* get key material from keyformat and keylocation */ 672*eda14cbcSMatt Macy ret = get_key_material(hdl, B_TRUE, newkey, keyformat, keylocation, 673*eda14cbcSMatt Macy fsname, &key_material, &key_material_len, NULL); 674*eda14cbcSMatt Macy if (ret != 0) 675*eda14cbcSMatt Macy goto error; 676*eda14cbcSMatt Macy 677*eda14cbcSMatt Macy /* passphrase formats require a salt and pbkdf2 iters property */ 678*eda14cbcSMatt Macy if (keyformat == ZFS_KEYFORMAT_PASSPHRASE) { 679*eda14cbcSMatt Macy /* always generate a new salt */ 680*eda14cbcSMatt Macy ret = pkcs11_get_urandom((uint8_t *)&salt, sizeof (uint64_t)); 681*eda14cbcSMatt Macy if (ret != sizeof (uint64_t)) { 682*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 683*eda14cbcSMatt Macy "Failed to generate salt.")); 684*eda14cbcSMatt Macy goto error; 685*eda14cbcSMatt Macy } 686*eda14cbcSMatt Macy 687*eda14cbcSMatt Macy ret = nvlist_add_uint64(props, 688*eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_PBKDF2_SALT), salt); 689*eda14cbcSMatt Macy if (ret != 0) { 690*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 691*eda14cbcSMatt Macy "Failed to add salt to properties.")); 692*eda14cbcSMatt Macy goto error; 693*eda14cbcSMatt Macy } 694*eda14cbcSMatt Macy 695*eda14cbcSMatt Macy /* 696*eda14cbcSMatt Macy * If not otherwise specified, use the default number of 697*eda14cbcSMatt Macy * pbkdf2 iterations. If specified, we have already checked 698*eda14cbcSMatt Macy * that the given value is greater than MIN_PBKDF2_ITERATIONS 699*eda14cbcSMatt Macy * during zfs_valid_proplist(). 700*eda14cbcSMatt Macy */ 701*eda14cbcSMatt Macy ret = nvlist_lookup_uint64(props, 702*eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), &iters); 703*eda14cbcSMatt Macy if (ret == ENOENT) { 704*eda14cbcSMatt Macy iters = DEFAULT_PBKDF2_ITERATIONS; 705*eda14cbcSMatt Macy ret = nvlist_add_uint64(props, 706*eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), iters); 707*eda14cbcSMatt Macy if (ret != 0) 708*eda14cbcSMatt Macy goto error; 709*eda14cbcSMatt Macy } else if (ret != 0) { 710*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 711*eda14cbcSMatt Macy "Failed to get pbkdf2 iterations.")); 712*eda14cbcSMatt Macy goto error; 713*eda14cbcSMatt Macy } 714*eda14cbcSMatt Macy } else { 715*eda14cbcSMatt Macy /* check that pbkdf2iters was not specified by the user */ 716*eda14cbcSMatt Macy ret = nvlist_lookup_uint64(props, 717*eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), &iters); 718*eda14cbcSMatt Macy if (ret == 0) { 719*eda14cbcSMatt Macy ret = EINVAL; 720*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 721*eda14cbcSMatt Macy "Cannot specify pbkdf2iters with a non-passphrase " 722*eda14cbcSMatt Macy "keyformat.")); 723*eda14cbcSMatt Macy goto error; 724*eda14cbcSMatt Macy } 725*eda14cbcSMatt Macy } 726*eda14cbcSMatt Macy 727*eda14cbcSMatt Macy /* derive a key from the key material */ 728*eda14cbcSMatt Macy ret = derive_key(hdl, keyformat, iters, key_material, key_material_len, 729*eda14cbcSMatt Macy salt, &key_data); 730*eda14cbcSMatt Macy if (ret != 0) 731*eda14cbcSMatt Macy goto error; 732*eda14cbcSMatt Macy 733*eda14cbcSMatt Macy free(key_material); 734*eda14cbcSMatt Macy 735*eda14cbcSMatt Macy *wkeydata = key_data; 736*eda14cbcSMatt Macy *wkeylen = WRAPPING_KEY_LEN; 737*eda14cbcSMatt Macy return (0); 738*eda14cbcSMatt Macy 739*eda14cbcSMatt Macy error: 740*eda14cbcSMatt Macy if (key_material != NULL) 741*eda14cbcSMatt Macy free(key_material); 742*eda14cbcSMatt Macy if (key_data != NULL) 743*eda14cbcSMatt Macy free(key_data); 744*eda14cbcSMatt Macy 745*eda14cbcSMatt Macy *wkeydata = NULL; 746*eda14cbcSMatt Macy *wkeylen = 0; 747*eda14cbcSMatt Macy return (ret); 748*eda14cbcSMatt Macy } 749*eda14cbcSMatt Macy 750*eda14cbcSMatt Macy static boolean_t 751*eda14cbcSMatt Macy proplist_has_encryption_props(nvlist_t *props) 752*eda14cbcSMatt Macy { 753*eda14cbcSMatt Macy int ret; 754*eda14cbcSMatt Macy uint64_t intval; 755*eda14cbcSMatt Macy char *strval; 756*eda14cbcSMatt Macy 757*eda14cbcSMatt Macy ret = nvlist_lookup_uint64(props, 758*eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_ENCRYPTION), &intval); 759*eda14cbcSMatt Macy if (ret == 0 && intval != ZIO_CRYPT_OFF) 760*eda14cbcSMatt Macy return (B_TRUE); 761*eda14cbcSMatt Macy 762*eda14cbcSMatt Macy ret = nvlist_lookup_string(props, 763*eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_KEYLOCATION), &strval); 764*eda14cbcSMatt Macy if (ret == 0 && strcmp(strval, "none") != 0) 765*eda14cbcSMatt Macy return (B_TRUE); 766*eda14cbcSMatt Macy 767*eda14cbcSMatt Macy ret = nvlist_lookup_uint64(props, 768*eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_KEYFORMAT), &intval); 769*eda14cbcSMatt Macy if (ret == 0) 770*eda14cbcSMatt Macy return (B_TRUE); 771*eda14cbcSMatt Macy 772*eda14cbcSMatt Macy ret = nvlist_lookup_uint64(props, 773*eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), &intval); 774*eda14cbcSMatt Macy if (ret == 0) 775*eda14cbcSMatt Macy return (B_TRUE); 776*eda14cbcSMatt Macy 777*eda14cbcSMatt Macy return (B_FALSE); 778*eda14cbcSMatt Macy } 779*eda14cbcSMatt Macy 780*eda14cbcSMatt Macy int 781*eda14cbcSMatt Macy zfs_crypto_get_encryption_root(zfs_handle_t *zhp, boolean_t *is_encroot, 782*eda14cbcSMatt Macy char *buf) 783*eda14cbcSMatt Macy { 784*eda14cbcSMatt Macy int ret; 785*eda14cbcSMatt Macy char prop_encroot[MAXNAMELEN]; 786*eda14cbcSMatt Macy 787*eda14cbcSMatt Macy /* if the dataset isn't encrypted, just return */ 788*eda14cbcSMatt Macy if (zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) == ZIO_CRYPT_OFF) { 789*eda14cbcSMatt Macy *is_encroot = B_FALSE; 790*eda14cbcSMatt Macy if (buf != NULL) 791*eda14cbcSMatt Macy buf[0] = '\0'; 792*eda14cbcSMatt Macy return (0); 793*eda14cbcSMatt Macy } 794*eda14cbcSMatt Macy 795*eda14cbcSMatt Macy ret = zfs_prop_get(zhp, ZFS_PROP_ENCRYPTION_ROOT, prop_encroot, 796*eda14cbcSMatt Macy sizeof (prop_encroot), NULL, NULL, 0, B_TRUE); 797*eda14cbcSMatt Macy if (ret != 0) { 798*eda14cbcSMatt Macy *is_encroot = B_FALSE; 799*eda14cbcSMatt Macy if (buf != NULL) 800*eda14cbcSMatt Macy buf[0] = '\0'; 801*eda14cbcSMatt Macy return (ret); 802*eda14cbcSMatt Macy } 803*eda14cbcSMatt Macy 804*eda14cbcSMatt Macy *is_encroot = strcmp(prop_encroot, zfs_get_name(zhp)) == 0; 805*eda14cbcSMatt Macy if (buf != NULL) 806*eda14cbcSMatt Macy strcpy(buf, prop_encroot); 807*eda14cbcSMatt Macy 808*eda14cbcSMatt Macy return (0); 809*eda14cbcSMatt Macy } 810*eda14cbcSMatt Macy 811*eda14cbcSMatt Macy int 812*eda14cbcSMatt Macy zfs_crypto_create(libzfs_handle_t *hdl, char *parent_name, nvlist_t *props, 813*eda14cbcSMatt Macy nvlist_t *pool_props, boolean_t stdin_available, uint8_t **wkeydata_out, 814*eda14cbcSMatt Macy uint_t *wkeylen_out) 815*eda14cbcSMatt Macy { 816*eda14cbcSMatt Macy int ret; 817*eda14cbcSMatt Macy char errbuf[1024]; 818*eda14cbcSMatt Macy uint64_t crypt = ZIO_CRYPT_INHERIT, pcrypt = ZIO_CRYPT_INHERIT; 819*eda14cbcSMatt Macy uint64_t keyformat = ZFS_KEYFORMAT_NONE; 820*eda14cbcSMatt Macy char *keylocation = NULL; 821*eda14cbcSMatt Macy zfs_handle_t *pzhp = NULL; 822*eda14cbcSMatt Macy uint8_t *wkeydata = NULL; 823*eda14cbcSMatt Macy uint_t wkeylen = 0; 824*eda14cbcSMatt Macy boolean_t local_crypt = B_TRUE; 825*eda14cbcSMatt Macy 826*eda14cbcSMatt Macy (void) snprintf(errbuf, sizeof (errbuf), 827*eda14cbcSMatt Macy dgettext(TEXT_DOMAIN, "Encryption create error")); 828*eda14cbcSMatt Macy 829*eda14cbcSMatt Macy /* lookup crypt from props */ 830*eda14cbcSMatt Macy ret = nvlist_lookup_uint64(props, 831*eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_ENCRYPTION), &crypt); 832*eda14cbcSMatt Macy if (ret != 0) 833*eda14cbcSMatt Macy local_crypt = B_FALSE; 834*eda14cbcSMatt Macy 835*eda14cbcSMatt Macy /* lookup key location and format from props */ 836*eda14cbcSMatt Macy (void) nvlist_lookup_uint64(props, 837*eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_KEYFORMAT), &keyformat); 838*eda14cbcSMatt Macy (void) nvlist_lookup_string(props, 839*eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_KEYLOCATION), &keylocation); 840*eda14cbcSMatt Macy 841*eda14cbcSMatt Macy if (parent_name != NULL) { 842*eda14cbcSMatt Macy /* get a reference to parent dataset */ 843*eda14cbcSMatt Macy pzhp = make_dataset_handle(hdl, parent_name); 844*eda14cbcSMatt Macy if (pzhp == NULL) { 845*eda14cbcSMatt Macy ret = ENOENT; 846*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 847*eda14cbcSMatt Macy "Failed to lookup parent.")); 848*eda14cbcSMatt Macy goto out; 849*eda14cbcSMatt Macy } 850*eda14cbcSMatt Macy 851*eda14cbcSMatt Macy /* Lookup parent's crypt */ 852*eda14cbcSMatt Macy pcrypt = zfs_prop_get_int(pzhp, ZFS_PROP_ENCRYPTION); 853*eda14cbcSMatt Macy 854*eda14cbcSMatt Macy /* Params require the encryption feature */ 855*eda14cbcSMatt Macy if (!encryption_feature_is_enabled(pzhp->zpool_hdl)) { 856*eda14cbcSMatt Macy if (proplist_has_encryption_props(props)) { 857*eda14cbcSMatt Macy ret = EINVAL; 858*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 859*eda14cbcSMatt Macy "Encryption feature not enabled.")); 860*eda14cbcSMatt Macy goto out; 861*eda14cbcSMatt Macy } 862*eda14cbcSMatt Macy 863*eda14cbcSMatt Macy ret = 0; 864*eda14cbcSMatt Macy goto out; 865*eda14cbcSMatt Macy } 866*eda14cbcSMatt Macy } else { 867*eda14cbcSMatt Macy /* 868*eda14cbcSMatt Macy * special case for root dataset where encryption feature 869*eda14cbcSMatt Macy * feature won't be on disk yet 870*eda14cbcSMatt Macy */ 871*eda14cbcSMatt Macy if (!nvlist_exists(pool_props, "feature@encryption")) { 872*eda14cbcSMatt Macy if (proplist_has_encryption_props(props)) { 873*eda14cbcSMatt Macy ret = EINVAL; 874*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 875*eda14cbcSMatt Macy "Encryption feature not enabled.")); 876*eda14cbcSMatt Macy goto out; 877*eda14cbcSMatt Macy } 878*eda14cbcSMatt Macy 879*eda14cbcSMatt Macy ret = 0; 880*eda14cbcSMatt Macy goto out; 881*eda14cbcSMatt Macy } 882*eda14cbcSMatt Macy 883*eda14cbcSMatt Macy pcrypt = ZIO_CRYPT_OFF; 884*eda14cbcSMatt Macy } 885*eda14cbcSMatt Macy 886*eda14cbcSMatt Macy /* Get the inherited encryption property if we don't have it locally */ 887*eda14cbcSMatt Macy if (!local_crypt) 888*eda14cbcSMatt Macy crypt = pcrypt; 889*eda14cbcSMatt Macy 890*eda14cbcSMatt Macy /* 891*eda14cbcSMatt Macy * At this point crypt should be the actual encryption value. If 892*eda14cbcSMatt Macy * encryption is off just verify that no encryption properties have 893*eda14cbcSMatt Macy * been specified and return. 894*eda14cbcSMatt Macy */ 895*eda14cbcSMatt Macy if (crypt == ZIO_CRYPT_OFF) { 896*eda14cbcSMatt Macy if (proplist_has_encryption_props(props)) { 897*eda14cbcSMatt Macy ret = EINVAL; 898*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 899*eda14cbcSMatt Macy "Encryption must be turned on to set encryption " 900*eda14cbcSMatt Macy "properties.")); 901*eda14cbcSMatt Macy goto out; 902*eda14cbcSMatt Macy } 903*eda14cbcSMatt Macy 904*eda14cbcSMatt Macy ret = 0; 905*eda14cbcSMatt Macy goto out; 906*eda14cbcSMatt Macy } 907*eda14cbcSMatt Macy 908*eda14cbcSMatt Macy /* 909*eda14cbcSMatt Macy * If we have a parent crypt it is valid to specify encryption alone. 910*eda14cbcSMatt Macy * This will result in a child that is encrypted with the chosen 911*eda14cbcSMatt Macy * encryption suite that will also inherit the parent's key. If 912*eda14cbcSMatt Macy * the parent is not encrypted we need an encryption suite provided. 913*eda14cbcSMatt Macy */ 914*eda14cbcSMatt Macy if (pcrypt == ZIO_CRYPT_OFF && keylocation == NULL && 915*eda14cbcSMatt Macy keyformat == ZFS_KEYFORMAT_NONE) { 916*eda14cbcSMatt Macy ret = EINVAL; 917*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 918*eda14cbcSMatt Macy "Keyformat required for new encryption root.")); 919*eda14cbcSMatt Macy goto out; 920*eda14cbcSMatt Macy } 921*eda14cbcSMatt Macy 922*eda14cbcSMatt Macy /* 923*eda14cbcSMatt Macy * Specifying a keylocation implies this will be a new encryption root. 924*eda14cbcSMatt Macy * Check that a keyformat is also specified. 925*eda14cbcSMatt Macy */ 926*eda14cbcSMatt Macy if (keylocation != NULL && keyformat == ZFS_KEYFORMAT_NONE) { 927*eda14cbcSMatt Macy ret = EINVAL; 928*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 929*eda14cbcSMatt Macy "Keyformat required for new encryption root.")); 930*eda14cbcSMatt Macy goto out; 931*eda14cbcSMatt Macy } 932*eda14cbcSMatt Macy 933*eda14cbcSMatt Macy /* default to prompt if no keylocation is specified */ 934*eda14cbcSMatt Macy if (keyformat != ZFS_KEYFORMAT_NONE && keylocation == NULL) { 935*eda14cbcSMatt Macy keylocation = "prompt"; 936*eda14cbcSMatt Macy ret = nvlist_add_string(props, 937*eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_KEYLOCATION), keylocation); 938*eda14cbcSMatt Macy if (ret != 0) 939*eda14cbcSMatt Macy goto out; 940*eda14cbcSMatt Macy } 941*eda14cbcSMatt Macy 942*eda14cbcSMatt Macy /* 943*eda14cbcSMatt Macy * If a local key is provided, this dataset will be a new 944*eda14cbcSMatt Macy * encryption root. Populate the encryption params. 945*eda14cbcSMatt Macy */ 946*eda14cbcSMatt Macy if (keylocation != NULL) { 947*eda14cbcSMatt Macy /* 948*eda14cbcSMatt Macy * 'zfs recv -o keylocation=prompt' won't work because stdin 949*eda14cbcSMatt Macy * is being used by the send stream, so we disallow it. 950*eda14cbcSMatt Macy */ 951*eda14cbcSMatt Macy if (!stdin_available && strcmp(keylocation, "prompt") == 0) { 952*eda14cbcSMatt Macy ret = EINVAL; 953*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Cannot use " 954*eda14cbcSMatt Macy "'prompt' keylocation because stdin is in use.")); 955*eda14cbcSMatt Macy goto out; 956*eda14cbcSMatt Macy } 957*eda14cbcSMatt Macy 958*eda14cbcSMatt Macy ret = populate_create_encryption_params_nvlists(hdl, NULL, 959*eda14cbcSMatt Macy B_FALSE, keyformat, keylocation, props, &wkeydata, 960*eda14cbcSMatt Macy &wkeylen); 961*eda14cbcSMatt Macy if (ret != 0) 962*eda14cbcSMatt Macy goto out; 963*eda14cbcSMatt Macy } 964*eda14cbcSMatt Macy 965*eda14cbcSMatt Macy if (pzhp != NULL) 966*eda14cbcSMatt Macy zfs_close(pzhp); 967*eda14cbcSMatt Macy 968*eda14cbcSMatt Macy *wkeydata_out = wkeydata; 969*eda14cbcSMatt Macy *wkeylen_out = wkeylen; 970*eda14cbcSMatt Macy return (0); 971*eda14cbcSMatt Macy 972*eda14cbcSMatt Macy out: 973*eda14cbcSMatt Macy if (pzhp != NULL) 974*eda14cbcSMatt Macy zfs_close(pzhp); 975*eda14cbcSMatt Macy if (wkeydata != NULL) 976*eda14cbcSMatt Macy free(wkeydata); 977*eda14cbcSMatt Macy 978*eda14cbcSMatt Macy *wkeydata_out = NULL; 979*eda14cbcSMatt Macy *wkeylen_out = 0; 980*eda14cbcSMatt Macy return (ret); 981*eda14cbcSMatt Macy } 982*eda14cbcSMatt Macy 983*eda14cbcSMatt Macy int 984*eda14cbcSMatt Macy zfs_crypto_clone_check(libzfs_handle_t *hdl, zfs_handle_t *origin_zhp, 985*eda14cbcSMatt Macy char *parent_name, nvlist_t *props) 986*eda14cbcSMatt Macy { 987*eda14cbcSMatt Macy char errbuf[1024]; 988*eda14cbcSMatt Macy 989*eda14cbcSMatt Macy (void) snprintf(errbuf, sizeof (errbuf), 990*eda14cbcSMatt Macy dgettext(TEXT_DOMAIN, "Encryption clone error")); 991*eda14cbcSMatt Macy 992*eda14cbcSMatt Macy /* 993*eda14cbcSMatt Macy * No encryption properties should be specified. They will all be 994*eda14cbcSMatt Macy * inherited from the origin dataset. 995*eda14cbcSMatt Macy */ 996*eda14cbcSMatt Macy if (nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_KEYFORMAT)) || 997*eda14cbcSMatt Macy nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_KEYLOCATION)) || 998*eda14cbcSMatt Macy nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_ENCRYPTION)) || 999*eda14cbcSMatt Macy nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS))) { 1000*eda14cbcSMatt Macy zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1001*eda14cbcSMatt Macy "Encryption properties must inherit from origin dataset.")); 1002*eda14cbcSMatt Macy return (EINVAL); 1003*eda14cbcSMatt Macy } 1004*eda14cbcSMatt Macy 1005*eda14cbcSMatt Macy return (0); 1006*eda14cbcSMatt Macy } 1007*eda14cbcSMatt Macy 1008*eda14cbcSMatt Macy typedef struct loadkeys_cbdata { 1009*eda14cbcSMatt Macy uint64_t cb_numfailed; 1010*eda14cbcSMatt Macy uint64_t cb_numattempted; 1011*eda14cbcSMatt Macy } loadkey_cbdata_t; 1012*eda14cbcSMatt Macy 1013*eda14cbcSMatt Macy static int 1014*eda14cbcSMatt Macy load_keys_cb(zfs_handle_t *zhp, void *arg) 1015*eda14cbcSMatt Macy { 1016*eda14cbcSMatt Macy int ret; 1017*eda14cbcSMatt Macy boolean_t is_encroot; 1018*eda14cbcSMatt Macy loadkey_cbdata_t *cb = arg; 1019*eda14cbcSMatt Macy uint64_t keystatus = zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS); 1020*eda14cbcSMatt Macy 1021*eda14cbcSMatt Macy /* only attempt to load keys for encryption roots */ 1022*eda14cbcSMatt Macy ret = zfs_crypto_get_encryption_root(zhp, &is_encroot, NULL); 1023*eda14cbcSMatt Macy if (ret != 0 || !is_encroot) 1024*eda14cbcSMatt Macy goto out; 1025*eda14cbcSMatt Macy 1026*eda14cbcSMatt Macy /* don't attempt to load already loaded keys */ 1027*eda14cbcSMatt Macy if (keystatus == ZFS_KEYSTATUS_AVAILABLE) 1028*eda14cbcSMatt Macy goto out; 1029*eda14cbcSMatt Macy 1030*eda14cbcSMatt Macy /* Attempt to load the key. Record status in cb. */ 1031*eda14cbcSMatt Macy cb->cb_numattempted++; 1032*eda14cbcSMatt Macy 1033*eda14cbcSMatt Macy ret = zfs_crypto_load_key(zhp, B_FALSE, NULL); 1034*eda14cbcSMatt Macy if (ret) 1035*eda14cbcSMatt Macy cb->cb_numfailed++; 1036*eda14cbcSMatt Macy 1037*eda14cbcSMatt Macy out: 1038*eda14cbcSMatt Macy (void) zfs_iter_filesystems(zhp, load_keys_cb, cb); 1039*eda14cbcSMatt Macy zfs_close(zhp); 1040*eda14cbcSMatt Macy 1041*eda14cbcSMatt Macy /* always return 0, since this function is best effort */ 1042*eda14cbcSMatt Macy return (0); 1043*eda14cbcSMatt Macy } 1044*eda14cbcSMatt Macy 1045*eda14cbcSMatt Macy /* 1046*eda14cbcSMatt Macy * This function is best effort. It attempts to load all the keys for the given 1047*eda14cbcSMatt Macy * filesystem and all of its children. 1048*eda14cbcSMatt Macy */ 1049*eda14cbcSMatt Macy int 1050*eda14cbcSMatt Macy zfs_crypto_attempt_load_keys(libzfs_handle_t *hdl, char *fsname) 1051*eda14cbcSMatt Macy { 1052*eda14cbcSMatt Macy int ret; 1053*eda14cbcSMatt Macy zfs_handle_t *zhp = NULL; 1054*eda14cbcSMatt Macy loadkey_cbdata_t cb = { 0 }; 1055*eda14cbcSMatt Macy 1056*eda14cbcSMatt Macy zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 1057*eda14cbcSMatt Macy if (zhp == NULL) { 1058*eda14cbcSMatt Macy ret = ENOENT; 1059*eda14cbcSMatt Macy goto error; 1060*eda14cbcSMatt Macy } 1061*eda14cbcSMatt Macy 1062*eda14cbcSMatt Macy ret = load_keys_cb(zfs_handle_dup(zhp), &cb); 1063*eda14cbcSMatt Macy if (ret) 1064*eda14cbcSMatt Macy goto error; 1065*eda14cbcSMatt Macy 1066*eda14cbcSMatt Macy (void) printf(gettext("%llu / %llu keys successfully loaded\n"), 1067*eda14cbcSMatt Macy (u_longlong_t)(cb.cb_numattempted - cb.cb_numfailed), 1068*eda14cbcSMatt Macy (u_longlong_t)cb.cb_numattempted); 1069*eda14cbcSMatt Macy 1070*eda14cbcSMatt Macy if (cb.cb_numfailed != 0) { 1071*eda14cbcSMatt Macy ret = -1; 1072*eda14cbcSMatt Macy goto error; 1073*eda14cbcSMatt Macy } 1074*eda14cbcSMatt Macy 1075*eda14cbcSMatt Macy zfs_close(zhp); 1076*eda14cbcSMatt Macy return (0); 1077*eda14cbcSMatt Macy 1078*eda14cbcSMatt Macy error: 1079*eda14cbcSMatt Macy if (zhp != NULL) 1080*eda14cbcSMatt Macy zfs_close(zhp); 1081*eda14cbcSMatt Macy return (ret); 1082*eda14cbcSMatt Macy } 1083*eda14cbcSMatt Macy 1084*eda14cbcSMatt Macy int 1085*eda14cbcSMatt Macy zfs_crypto_load_key(zfs_handle_t *zhp, boolean_t noop, char *alt_keylocation) 1086*eda14cbcSMatt Macy { 1087*eda14cbcSMatt Macy int ret, attempts = 0; 1088*eda14cbcSMatt Macy char errbuf[1024]; 1089*eda14cbcSMatt Macy uint64_t keystatus, iters = 0, salt = 0; 1090*eda14cbcSMatt Macy uint64_t keyformat = ZFS_KEYFORMAT_NONE; 1091*eda14cbcSMatt Macy char prop_keylocation[MAXNAMELEN]; 1092*eda14cbcSMatt Macy char prop_encroot[MAXNAMELEN]; 1093*eda14cbcSMatt Macy char *keylocation = NULL; 1094*eda14cbcSMatt Macy uint8_t *key_material = NULL, *key_data = NULL; 1095*eda14cbcSMatt Macy size_t key_material_len; 1096*eda14cbcSMatt Macy boolean_t is_encroot, can_retry = B_FALSE, correctible = B_FALSE; 1097*eda14cbcSMatt Macy 1098*eda14cbcSMatt Macy (void) snprintf(errbuf, sizeof (errbuf), 1099*eda14cbcSMatt Macy dgettext(TEXT_DOMAIN, "Key load error")); 1100*eda14cbcSMatt Macy 1101*eda14cbcSMatt Macy /* check that encryption is enabled for the pool */ 1102*eda14cbcSMatt Macy if (!encryption_feature_is_enabled(zhp->zpool_hdl)) { 1103*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1104*eda14cbcSMatt Macy "Encryption feature not enabled.")); 1105*eda14cbcSMatt Macy ret = EINVAL; 1106*eda14cbcSMatt Macy goto error; 1107*eda14cbcSMatt Macy } 1108*eda14cbcSMatt Macy 1109*eda14cbcSMatt Macy /* Fetch the keyformat. Check that the dataset is encrypted. */ 1110*eda14cbcSMatt Macy keyformat = zfs_prop_get_int(zhp, ZFS_PROP_KEYFORMAT); 1111*eda14cbcSMatt Macy if (keyformat == ZFS_KEYFORMAT_NONE) { 1112*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1113*eda14cbcSMatt Macy "'%s' is not encrypted."), zfs_get_name(zhp)); 1114*eda14cbcSMatt Macy ret = EINVAL; 1115*eda14cbcSMatt Macy goto error; 1116*eda14cbcSMatt Macy } 1117*eda14cbcSMatt Macy 1118*eda14cbcSMatt Macy /* 1119*eda14cbcSMatt Macy * Fetch the key location. Check that we are working with an 1120*eda14cbcSMatt Macy * encryption root. 1121*eda14cbcSMatt Macy */ 1122*eda14cbcSMatt Macy ret = zfs_crypto_get_encryption_root(zhp, &is_encroot, prop_encroot); 1123*eda14cbcSMatt Macy if (ret != 0) { 1124*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1125*eda14cbcSMatt Macy "Failed to get encryption root for '%s'."), 1126*eda14cbcSMatt Macy zfs_get_name(zhp)); 1127*eda14cbcSMatt Macy goto error; 1128*eda14cbcSMatt Macy } else if (!is_encroot) { 1129*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1130*eda14cbcSMatt Macy "Keys must be loaded for encryption root of '%s' (%s)."), 1131*eda14cbcSMatt Macy zfs_get_name(zhp), prop_encroot); 1132*eda14cbcSMatt Macy ret = EINVAL; 1133*eda14cbcSMatt Macy goto error; 1134*eda14cbcSMatt Macy } 1135*eda14cbcSMatt Macy 1136*eda14cbcSMatt Macy /* 1137*eda14cbcSMatt Macy * if the caller has elected to override the keylocation property 1138*eda14cbcSMatt Macy * use that instead 1139*eda14cbcSMatt Macy */ 1140*eda14cbcSMatt Macy if (alt_keylocation != NULL) { 1141*eda14cbcSMatt Macy keylocation = alt_keylocation; 1142*eda14cbcSMatt Macy } else { 1143*eda14cbcSMatt Macy ret = zfs_prop_get(zhp, ZFS_PROP_KEYLOCATION, prop_keylocation, 1144*eda14cbcSMatt Macy sizeof (prop_keylocation), NULL, NULL, 0, B_TRUE); 1145*eda14cbcSMatt Macy if (ret != 0) { 1146*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1147*eda14cbcSMatt Macy "Failed to get keylocation for '%s'."), 1148*eda14cbcSMatt Macy zfs_get_name(zhp)); 1149*eda14cbcSMatt Macy goto error; 1150*eda14cbcSMatt Macy } 1151*eda14cbcSMatt Macy 1152*eda14cbcSMatt Macy keylocation = prop_keylocation; 1153*eda14cbcSMatt Macy } 1154*eda14cbcSMatt Macy 1155*eda14cbcSMatt Macy /* check that the key is unloaded unless this is a noop */ 1156*eda14cbcSMatt Macy if (!noop) { 1157*eda14cbcSMatt Macy keystatus = zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS); 1158*eda14cbcSMatt Macy if (keystatus == ZFS_KEYSTATUS_AVAILABLE) { 1159*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1160*eda14cbcSMatt Macy "Key already loaded for '%s'."), zfs_get_name(zhp)); 1161*eda14cbcSMatt Macy ret = EEXIST; 1162*eda14cbcSMatt Macy goto error; 1163*eda14cbcSMatt Macy } 1164*eda14cbcSMatt Macy } 1165*eda14cbcSMatt Macy 1166*eda14cbcSMatt Macy /* passphrase formats require a salt and pbkdf2_iters property */ 1167*eda14cbcSMatt Macy if (keyformat == ZFS_KEYFORMAT_PASSPHRASE) { 1168*eda14cbcSMatt Macy salt = zfs_prop_get_int(zhp, ZFS_PROP_PBKDF2_SALT); 1169*eda14cbcSMatt Macy iters = zfs_prop_get_int(zhp, ZFS_PROP_PBKDF2_ITERS); 1170*eda14cbcSMatt Macy } 1171*eda14cbcSMatt Macy 1172*eda14cbcSMatt Macy try_again: 1173*eda14cbcSMatt Macy /* fetching and deriving the key are correctable errors. set the flag */ 1174*eda14cbcSMatt Macy correctible = B_TRUE; 1175*eda14cbcSMatt Macy 1176*eda14cbcSMatt Macy /* get key material from key format and location */ 1177*eda14cbcSMatt Macy ret = get_key_material(zhp->zfs_hdl, B_FALSE, B_FALSE, keyformat, 1178*eda14cbcSMatt Macy keylocation, zfs_get_name(zhp), &key_material, &key_material_len, 1179*eda14cbcSMatt Macy &can_retry); 1180*eda14cbcSMatt Macy if (ret != 0) 1181*eda14cbcSMatt Macy goto error; 1182*eda14cbcSMatt Macy 1183*eda14cbcSMatt Macy /* derive a key from the key material */ 1184*eda14cbcSMatt Macy ret = derive_key(zhp->zfs_hdl, keyformat, iters, key_material, 1185*eda14cbcSMatt Macy key_material_len, salt, &key_data); 1186*eda14cbcSMatt Macy if (ret != 0) 1187*eda14cbcSMatt Macy goto error; 1188*eda14cbcSMatt Macy 1189*eda14cbcSMatt Macy correctible = B_FALSE; 1190*eda14cbcSMatt Macy 1191*eda14cbcSMatt Macy /* pass the wrapping key and noop flag to the ioctl */ 1192*eda14cbcSMatt Macy ret = lzc_load_key(zhp->zfs_name, noop, key_data, WRAPPING_KEY_LEN); 1193*eda14cbcSMatt Macy if (ret != 0) { 1194*eda14cbcSMatt Macy switch (ret) { 1195*eda14cbcSMatt Macy case EPERM: 1196*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1197*eda14cbcSMatt Macy "Permission denied.")); 1198*eda14cbcSMatt Macy break; 1199*eda14cbcSMatt Macy case EINVAL: 1200*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1201*eda14cbcSMatt Macy "Invalid parameters provided for dataset %s."), 1202*eda14cbcSMatt Macy zfs_get_name(zhp)); 1203*eda14cbcSMatt Macy break; 1204*eda14cbcSMatt Macy case EEXIST: 1205*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1206*eda14cbcSMatt Macy "Key already loaded for '%s'."), zfs_get_name(zhp)); 1207*eda14cbcSMatt Macy break; 1208*eda14cbcSMatt Macy case EBUSY: 1209*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1210*eda14cbcSMatt Macy "'%s' is busy."), zfs_get_name(zhp)); 1211*eda14cbcSMatt Macy break; 1212*eda14cbcSMatt Macy case EACCES: 1213*eda14cbcSMatt Macy correctible = B_TRUE; 1214*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1215*eda14cbcSMatt Macy "Incorrect key provided for '%s'."), 1216*eda14cbcSMatt Macy zfs_get_name(zhp)); 1217*eda14cbcSMatt Macy break; 1218*eda14cbcSMatt Macy } 1219*eda14cbcSMatt Macy goto error; 1220*eda14cbcSMatt Macy } 1221*eda14cbcSMatt Macy 1222*eda14cbcSMatt Macy free(key_material); 1223*eda14cbcSMatt Macy free(key_data); 1224*eda14cbcSMatt Macy 1225*eda14cbcSMatt Macy return (0); 1226*eda14cbcSMatt Macy 1227*eda14cbcSMatt Macy error: 1228*eda14cbcSMatt Macy zfs_error(zhp->zfs_hdl, EZFS_CRYPTOFAILED, errbuf); 1229*eda14cbcSMatt Macy if (key_material != NULL) { 1230*eda14cbcSMatt Macy free(key_material); 1231*eda14cbcSMatt Macy key_material = NULL; 1232*eda14cbcSMatt Macy } 1233*eda14cbcSMatt Macy if (key_data != NULL) { 1234*eda14cbcSMatt Macy free(key_data); 1235*eda14cbcSMatt Macy key_data = NULL; 1236*eda14cbcSMatt Macy } 1237*eda14cbcSMatt Macy 1238*eda14cbcSMatt Macy /* 1239*eda14cbcSMatt Macy * Here we decide if it is ok to allow the user to retry entering their 1240*eda14cbcSMatt Macy * key. The can_retry flag will be set if the user is entering their 1241*eda14cbcSMatt Macy * key from an interactive prompt. The correctable flag will only be 1242*eda14cbcSMatt Macy * set if an error that occurred could be corrected by retrying. Both 1243*eda14cbcSMatt Macy * flags are needed to allow the user to attempt key entry again 1244*eda14cbcSMatt Macy */ 1245*eda14cbcSMatt Macy attempts++; 1246*eda14cbcSMatt Macy if (can_retry && correctible && attempts < MAX_KEY_PROMPT_ATTEMPTS) 1247*eda14cbcSMatt Macy goto try_again; 1248*eda14cbcSMatt Macy 1249*eda14cbcSMatt Macy return (ret); 1250*eda14cbcSMatt Macy } 1251*eda14cbcSMatt Macy 1252*eda14cbcSMatt Macy int 1253*eda14cbcSMatt Macy zfs_crypto_unload_key(zfs_handle_t *zhp) 1254*eda14cbcSMatt Macy { 1255*eda14cbcSMatt Macy int ret; 1256*eda14cbcSMatt Macy char errbuf[1024]; 1257*eda14cbcSMatt Macy char prop_encroot[MAXNAMELEN]; 1258*eda14cbcSMatt Macy uint64_t keystatus, keyformat; 1259*eda14cbcSMatt Macy boolean_t is_encroot; 1260*eda14cbcSMatt Macy 1261*eda14cbcSMatt Macy (void) snprintf(errbuf, sizeof (errbuf), 1262*eda14cbcSMatt Macy dgettext(TEXT_DOMAIN, "Key unload error")); 1263*eda14cbcSMatt Macy 1264*eda14cbcSMatt Macy /* check that encryption is enabled for the pool */ 1265*eda14cbcSMatt Macy if (!encryption_feature_is_enabled(zhp->zpool_hdl)) { 1266*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1267*eda14cbcSMatt Macy "Encryption feature not enabled.")); 1268*eda14cbcSMatt Macy ret = EINVAL; 1269*eda14cbcSMatt Macy goto error; 1270*eda14cbcSMatt Macy } 1271*eda14cbcSMatt Macy 1272*eda14cbcSMatt Macy /* Fetch the keyformat. Check that the dataset is encrypted. */ 1273*eda14cbcSMatt Macy keyformat = zfs_prop_get_int(zhp, ZFS_PROP_KEYFORMAT); 1274*eda14cbcSMatt Macy if (keyformat == ZFS_KEYFORMAT_NONE) { 1275*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1276*eda14cbcSMatt Macy "'%s' is not encrypted."), zfs_get_name(zhp)); 1277*eda14cbcSMatt Macy ret = EINVAL; 1278*eda14cbcSMatt Macy goto error; 1279*eda14cbcSMatt Macy } 1280*eda14cbcSMatt Macy 1281*eda14cbcSMatt Macy /* 1282*eda14cbcSMatt Macy * Fetch the key location. Check that we are working with an 1283*eda14cbcSMatt Macy * encryption root. 1284*eda14cbcSMatt Macy */ 1285*eda14cbcSMatt Macy ret = zfs_crypto_get_encryption_root(zhp, &is_encroot, prop_encroot); 1286*eda14cbcSMatt Macy if (ret != 0) { 1287*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1288*eda14cbcSMatt Macy "Failed to get encryption root for '%s'."), 1289*eda14cbcSMatt Macy zfs_get_name(zhp)); 1290*eda14cbcSMatt Macy goto error; 1291*eda14cbcSMatt Macy } else if (!is_encroot) { 1292*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1293*eda14cbcSMatt Macy "Keys must be unloaded for encryption root of '%s' (%s)."), 1294*eda14cbcSMatt Macy zfs_get_name(zhp), prop_encroot); 1295*eda14cbcSMatt Macy ret = EINVAL; 1296*eda14cbcSMatt Macy goto error; 1297*eda14cbcSMatt Macy } 1298*eda14cbcSMatt Macy 1299*eda14cbcSMatt Macy /* check that the key is loaded */ 1300*eda14cbcSMatt Macy keystatus = zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS); 1301*eda14cbcSMatt Macy if (keystatus == ZFS_KEYSTATUS_UNAVAILABLE) { 1302*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1303*eda14cbcSMatt Macy "Key already unloaded for '%s'."), zfs_get_name(zhp)); 1304*eda14cbcSMatt Macy ret = EACCES; 1305*eda14cbcSMatt Macy goto error; 1306*eda14cbcSMatt Macy } 1307*eda14cbcSMatt Macy 1308*eda14cbcSMatt Macy /* call the ioctl */ 1309*eda14cbcSMatt Macy ret = lzc_unload_key(zhp->zfs_name); 1310*eda14cbcSMatt Macy 1311*eda14cbcSMatt Macy if (ret != 0) { 1312*eda14cbcSMatt Macy switch (ret) { 1313*eda14cbcSMatt Macy case EPERM: 1314*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1315*eda14cbcSMatt Macy "Permission denied.")); 1316*eda14cbcSMatt Macy break; 1317*eda14cbcSMatt Macy case EACCES: 1318*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1319*eda14cbcSMatt Macy "Key already unloaded for '%s'."), 1320*eda14cbcSMatt Macy zfs_get_name(zhp)); 1321*eda14cbcSMatt Macy break; 1322*eda14cbcSMatt Macy case EBUSY: 1323*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1324*eda14cbcSMatt Macy "'%s' is busy."), zfs_get_name(zhp)); 1325*eda14cbcSMatt Macy break; 1326*eda14cbcSMatt Macy } 1327*eda14cbcSMatt Macy zfs_error(zhp->zfs_hdl, EZFS_CRYPTOFAILED, errbuf); 1328*eda14cbcSMatt Macy } 1329*eda14cbcSMatt Macy 1330*eda14cbcSMatt Macy return (ret); 1331*eda14cbcSMatt Macy 1332*eda14cbcSMatt Macy error: 1333*eda14cbcSMatt Macy zfs_error(zhp->zfs_hdl, EZFS_CRYPTOFAILED, errbuf); 1334*eda14cbcSMatt Macy return (ret); 1335*eda14cbcSMatt Macy } 1336*eda14cbcSMatt Macy 1337*eda14cbcSMatt Macy static int 1338*eda14cbcSMatt Macy zfs_crypto_verify_rewrap_nvlist(zfs_handle_t *zhp, nvlist_t *props, 1339*eda14cbcSMatt Macy nvlist_t **props_out, char *errbuf) 1340*eda14cbcSMatt Macy { 1341*eda14cbcSMatt Macy int ret; 1342*eda14cbcSMatt Macy nvpair_t *elem = NULL; 1343*eda14cbcSMatt Macy zfs_prop_t prop; 1344*eda14cbcSMatt Macy nvlist_t *new_props = NULL; 1345*eda14cbcSMatt Macy 1346*eda14cbcSMatt Macy new_props = fnvlist_alloc(); 1347*eda14cbcSMatt Macy 1348*eda14cbcSMatt Macy /* 1349*eda14cbcSMatt Macy * loop through all provided properties, we should only have 1350*eda14cbcSMatt Macy * keyformat, keylocation and pbkdf2iters. The actual validation of 1351*eda14cbcSMatt Macy * values is done by zfs_valid_proplist(). 1352*eda14cbcSMatt Macy */ 1353*eda14cbcSMatt Macy while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { 1354*eda14cbcSMatt Macy const char *propname = nvpair_name(elem); 1355*eda14cbcSMatt Macy prop = zfs_name_to_prop(propname); 1356*eda14cbcSMatt Macy 1357*eda14cbcSMatt Macy switch (prop) { 1358*eda14cbcSMatt Macy case ZFS_PROP_PBKDF2_ITERS: 1359*eda14cbcSMatt Macy case ZFS_PROP_KEYFORMAT: 1360*eda14cbcSMatt Macy case ZFS_PROP_KEYLOCATION: 1361*eda14cbcSMatt Macy break; 1362*eda14cbcSMatt Macy default: 1363*eda14cbcSMatt Macy ret = EINVAL; 1364*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1365*eda14cbcSMatt Macy "Only keyformat, keylocation and pbkdf2iters may " 1366*eda14cbcSMatt Macy "be set with this command.")); 1367*eda14cbcSMatt Macy goto error; 1368*eda14cbcSMatt Macy } 1369*eda14cbcSMatt Macy } 1370*eda14cbcSMatt Macy 1371*eda14cbcSMatt Macy new_props = zfs_valid_proplist(zhp->zfs_hdl, zhp->zfs_type, props, 1372*eda14cbcSMatt Macy zfs_prop_get_int(zhp, ZFS_PROP_ZONED), NULL, zhp->zpool_hdl, 1373*eda14cbcSMatt Macy B_TRUE, errbuf); 1374*eda14cbcSMatt Macy if (new_props == NULL) { 1375*eda14cbcSMatt Macy ret = EINVAL; 1376*eda14cbcSMatt Macy goto error; 1377*eda14cbcSMatt Macy } 1378*eda14cbcSMatt Macy 1379*eda14cbcSMatt Macy *props_out = new_props; 1380*eda14cbcSMatt Macy return (0); 1381*eda14cbcSMatt Macy 1382*eda14cbcSMatt Macy error: 1383*eda14cbcSMatt Macy nvlist_free(new_props); 1384*eda14cbcSMatt Macy *props_out = NULL; 1385*eda14cbcSMatt Macy return (ret); 1386*eda14cbcSMatt Macy } 1387*eda14cbcSMatt Macy 1388*eda14cbcSMatt Macy int 1389*eda14cbcSMatt Macy zfs_crypto_rewrap(zfs_handle_t *zhp, nvlist_t *raw_props, boolean_t inheritkey) 1390*eda14cbcSMatt Macy { 1391*eda14cbcSMatt Macy int ret; 1392*eda14cbcSMatt Macy char errbuf[1024]; 1393*eda14cbcSMatt Macy boolean_t is_encroot; 1394*eda14cbcSMatt Macy nvlist_t *props = NULL; 1395*eda14cbcSMatt Macy uint8_t *wkeydata = NULL; 1396*eda14cbcSMatt Macy uint_t wkeylen = 0; 1397*eda14cbcSMatt Macy dcp_cmd_t cmd = (inheritkey) ? DCP_CMD_INHERIT : DCP_CMD_NEW_KEY; 1398*eda14cbcSMatt Macy uint64_t crypt, pcrypt, keystatus, pkeystatus; 1399*eda14cbcSMatt Macy uint64_t keyformat = ZFS_KEYFORMAT_NONE; 1400*eda14cbcSMatt Macy zfs_handle_t *pzhp = NULL; 1401*eda14cbcSMatt Macy char *keylocation = NULL; 1402*eda14cbcSMatt Macy char origin_name[MAXNAMELEN]; 1403*eda14cbcSMatt Macy char prop_keylocation[MAXNAMELEN]; 1404*eda14cbcSMatt Macy char parent_name[ZFS_MAX_DATASET_NAME_LEN]; 1405*eda14cbcSMatt Macy 1406*eda14cbcSMatt Macy (void) snprintf(errbuf, sizeof (errbuf), 1407*eda14cbcSMatt Macy dgettext(TEXT_DOMAIN, "Key change error")); 1408*eda14cbcSMatt Macy 1409*eda14cbcSMatt Macy /* check that encryption is enabled for the pool */ 1410*eda14cbcSMatt Macy if (!encryption_feature_is_enabled(zhp->zpool_hdl)) { 1411*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1412*eda14cbcSMatt Macy "Encryption feature not enabled.")); 1413*eda14cbcSMatt Macy ret = EINVAL; 1414*eda14cbcSMatt Macy goto error; 1415*eda14cbcSMatt Macy } 1416*eda14cbcSMatt Macy 1417*eda14cbcSMatt Macy /* get crypt from dataset */ 1418*eda14cbcSMatt Macy crypt = zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION); 1419*eda14cbcSMatt Macy if (crypt == ZIO_CRYPT_OFF) { 1420*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1421*eda14cbcSMatt Macy "Dataset not encrypted.")); 1422*eda14cbcSMatt Macy ret = EINVAL; 1423*eda14cbcSMatt Macy goto error; 1424*eda14cbcSMatt Macy } 1425*eda14cbcSMatt Macy 1426*eda14cbcSMatt Macy /* get the encryption root of the dataset */ 1427*eda14cbcSMatt Macy ret = zfs_crypto_get_encryption_root(zhp, &is_encroot, NULL); 1428*eda14cbcSMatt Macy if (ret != 0) { 1429*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1430*eda14cbcSMatt Macy "Failed to get encryption root for '%s'."), 1431*eda14cbcSMatt Macy zfs_get_name(zhp)); 1432*eda14cbcSMatt Macy goto error; 1433*eda14cbcSMatt Macy } 1434*eda14cbcSMatt Macy 1435*eda14cbcSMatt Macy /* Clones use their origin's key and cannot rewrap it */ 1436*eda14cbcSMatt Macy ret = zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin_name, 1437*eda14cbcSMatt Macy sizeof (origin_name), NULL, NULL, 0, B_TRUE); 1438*eda14cbcSMatt Macy if (ret == 0 && strcmp(origin_name, "") != 0) { 1439*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1440*eda14cbcSMatt Macy "Keys cannot be changed on clones.")); 1441*eda14cbcSMatt Macy ret = EINVAL; 1442*eda14cbcSMatt Macy goto error; 1443*eda14cbcSMatt Macy } 1444*eda14cbcSMatt Macy 1445*eda14cbcSMatt Macy /* 1446*eda14cbcSMatt Macy * If the user wants to use the inheritkey variant of this function 1447*eda14cbcSMatt Macy * we don't need to collect any crypto arguments. 1448*eda14cbcSMatt Macy */ 1449*eda14cbcSMatt Macy if (!inheritkey) { 1450*eda14cbcSMatt Macy /* validate the provided properties */ 1451*eda14cbcSMatt Macy ret = zfs_crypto_verify_rewrap_nvlist(zhp, raw_props, &props, 1452*eda14cbcSMatt Macy errbuf); 1453*eda14cbcSMatt Macy if (ret != 0) 1454*eda14cbcSMatt Macy goto error; 1455*eda14cbcSMatt Macy 1456*eda14cbcSMatt Macy /* 1457*eda14cbcSMatt Macy * Load keyformat and keylocation from the nvlist. Fetch from 1458*eda14cbcSMatt Macy * the dataset properties if not specified. 1459*eda14cbcSMatt Macy */ 1460*eda14cbcSMatt Macy (void) nvlist_lookup_uint64(props, 1461*eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_KEYFORMAT), &keyformat); 1462*eda14cbcSMatt Macy (void) nvlist_lookup_string(props, 1463*eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_KEYLOCATION), &keylocation); 1464*eda14cbcSMatt Macy 1465*eda14cbcSMatt Macy if (is_encroot) { 1466*eda14cbcSMatt Macy /* 1467*eda14cbcSMatt Macy * If this is already an encryption root, just keep 1468*eda14cbcSMatt Macy * any properties not set by the user. 1469*eda14cbcSMatt Macy */ 1470*eda14cbcSMatt Macy if (keyformat == ZFS_KEYFORMAT_NONE) { 1471*eda14cbcSMatt Macy keyformat = zfs_prop_get_int(zhp, 1472*eda14cbcSMatt Macy ZFS_PROP_KEYFORMAT); 1473*eda14cbcSMatt Macy ret = nvlist_add_uint64(props, 1474*eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_KEYFORMAT), 1475*eda14cbcSMatt Macy keyformat); 1476*eda14cbcSMatt Macy if (ret != 0) { 1477*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, 1478*eda14cbcSMatt Macy dgettext(TEXT_DOMAIN, "Failed to " 1479*eda14cbcSMatt Macy "get existing keyformat " 1480*eda14cbcSMatt Macy "property.")); 1481*eda14cbcSMatt Macy goto error; 1482*eda14cbcSMatt Macy } 1483*eda14cbcSMatt Macy } 1484*eda14cbcSMatt Macy 1485*eda14cbcSMatt Macy if (keylocation == NULL) { 1486*eda14cbcSMatt Macy ret = zfs_prop_get(zhp, ZFS_PROP_KEYLOCATION, 1487*eda14cbcSMatt Macy prop_keylocation, sizeof (prop_keylocation), 1488*eda14cbcSMatt Macy NULL, NULL, 0, B_TRUE); 1489*eda14cbcSMatt Macy if (ret != 0) { 1490*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, 1491*eda14cbcSMatt Macy dgettext(TEXT_DOMAIN, "Failed to " 1492*eda14cbcSMatt Macy "get existing keylocation " 1493*eda14cbcSMatt Macy "property.")); 1494*eda14cbcSMatt Macy goto error; 1495*eda14cbcSMatt Macy } 1496*eda14cbcSMatt Macy 1497*eda14cbcSMatt Macy keylocation = prop_keylocation; 1498*eda14cbcSMatt Macy } 1499*eda14cbcSMatt Macy } else { 1500*eda14cbcSMatt Macy /* need a new key for non-encryption roots */ 1501*eda14cbcSMatt Macy if (keyformat == ZFS_KEYFORMAT_NONE) { 1502*eda14cbcSMatt Macy ret = EINVAL; 1503*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, 1504*eda14cbcSMatt Macy dgettext(TEXT_DOMAIN, "Keyformat required " 1505*eda14cbcSMatt Macy "for new encryption root.")); 1506*eda14cbcSMatt Macy goto error; 1507*eda14cbcSMatt Macy } 1508*eda14cbcSMatt Macy 1509*eda14cbcSMatt Macy /* default to prompt if no keylocation is specified */ 1510*eda14cbcSMatt Macy if (keylocation == NULL) { 1511*eda14cbcSMatt Macy keylocation = "prompt"; 1512*eda14cbcSMatt Macy ret = nvlist_add_string(props, 1513*eda14cbcSMatt Macy zfs_prop_to_name(ZFS_PROP_KEYLOCATION), 1514*eda14cbcSMatt Macy keylocation); 1515*eda14cbcSMatt Macy if (ret != 0) 1516*eda14cbcSMatt Macy goto error; 1517*eda14cbcSMatt Macy } 1518*eda14cbcSMatt Macy } 1519*eda14cbcSMatt Macy 1520*eda14cbcSMatt Macy /* fetch the new wrapping key and associated properties */ 1521*eda14cbcSMatt Macy ret = populate_create_encryption_params_nvlists(zhp->zfs_hdl, 1522*eda14cbcSMatt Macy zhp, B_TRUE, keyformat, keylocation, props, &wkeydata, 1523*eda14cbcSMatt Macy &wkeylen); 1524*eda14cbcSMatt Macy if (ret != 0) 1525*eda14cbcSMatt Macy goto error; 1526*eda14cbcSMatt Macy } else { 1527*eda14cbcSMatt Macy /* check that zhp is an encryption root */ 1528*eda14cbcSMatt Macy if (!is_encroot) { 1529*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1530*eda14cbcSMatt Macy "Key inheritting can only be performed on " 1531*eda14cbcSMatt Macy "encryption roots.")); 1532*eda14cbcSMatt Macy ret = EINVAL; 1533*eda14cbcSMatt Macy goto error; 1534*eda14cbcSMatt Macy } 1535*eda14cbcSMatt Macy 1536*eda14cbcSMatt Macy /* get the parent's name */ 1537*eda14cbcSMatt Macy ret = zfs_parent_name(zhp, parent_name, sizeof (parent_name)); 1538*eda14cbcSMatt Macy if (ret != 0) { 1539*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1540*eda14cbcSMatt Macy "Root dataset cannot inherit key.")); 1541*eda14cbcSMatt Macy ret = EINVAL; 1542*eda14cbcSMatt Macy goto error; 1543*eda14cbcSMatt Macy } 1544*eda14cbcSMatt Macy 1545*eda14cbcSMatt Macy /* get a handle to the parent */ 1546*eda14cbcSMatt Macy pzhp = make_dataset_handle(zhp->zfs_hdl, parent_name); 1547*eda14cbcSMatt Macy if (pzhp == NULL) { 1548*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1549*eda14cbcSMatt Macy "Failed to lookup parent.")); 1550*eda14cbcSMatt Macy ret = ENOENT; 1551*eda14cbcSMatt Macy goto error; 1552*eda14cbcSMatt Macy } 1553*eda14cbcSMatt Macy 1554*eda14cbcSMatt Macy /* parent must be encrypted */ 1555*eda14cbcSMatt Macy pcrypt = zfs_prop_get_int(pzhp, ZFS_PROP_ENCRYPTION); 1556*eda14cbcSMatt Macy if (pcrypt == ZIO_CRYPT_OFF) { 1557*eda14cbcSMatt Macy zfs_error_aux(pzhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1558*eda14cbcSMatt Macy "Parent must be encrypted.")); 1559*eda14cbcSMatt Macy ret = EINVAL; 1560*eda14cbcSMatt Macy goto error; 1561*eda14cbcSMatt Macy } 1562*eda14cbcSMatt Macy 1563*eda14cbcSMatt Macy /* check that the parent's key is loaded */ 1564*eda14cbcSMatt Macy pkeystatus = zfs_prop_get_int(pzhp, ZFS_PROP_KEYSTATUS); 1565*eda14cbcSMatt Macy if (pkeystatus == ZFS_KEYSTATUS_UNAVAILABLE) { 1566*eda14cbcSMatt Macy zfs_error_aux(pzhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1567*eda14cbcSMatt Macy "Parent key must be loaded.")); 1568*eda14cbcSMatt Macy ret = EACCES; 1569*eda14cbcSMatt Macy goto error; 1570*eda14cbcSMatt Macy } 1571*eda14cbcSMatt Macy } 1572*eda14cbcSMatt Macy 1573*eda14cbcSMatt Macy /* check that the key is loaded */ 1574*eda14cbcSMatt Macy keystatus = zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS); 1575*eda14cbcSMatt Macy if (keystatus == ZFS_KEYSTATUS_UNAVAILABLE) { 1576*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1577*eda14cbcSMatt Macy "Key must be loaded.")); 1578*eda14cbcSMatt Macy ret = EACCES; 1579*eda14cbcSMatt Macy goto error; 1580*eda14cbcSMatt Macy } 1581*eda14cbcSMatt Macy 1582*eda14cbcSMatt Macy /* call the ioctl */ 1583*eda14cbcSMatt Macy ret = lzc_change_key(zhp->zfs_name, cmd, props, wkeydata, wkeylen); 1584*eda14cbcSMatt Macy if (ret != 0) { 1585*eda14cbcSMatt Macy switch (ret) { 1586*eda14cbcSMatt Macy case EPERM: 1587*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1588*eda14cbcSMatt Macy "Permission denied.")); 1589*eda14cbcSMatt Macy break; 1590*eda14cbcSMatt Macy case EINVAL: 1591*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1592*eda14cbcSMatt Macy "Invalid properties for key change.")); 1593*eda14cbcSMatt Macy break; 1594*eda14cbcSMatt Macy case EACCES: 1595*eda14cbcSMatt Macy zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1596*eda14cbcSMatt Macy "Key is not currently loaded.")); 1597*eda14cbcSMatt Macy break; 1598*eda14cbcSMatt Macy } 1599*eda14cbcSMatt Macy zfs_error(zhp->zfs_hdl, EZFS_CRYPTOFAILED, errbuf); 1600*eda14cbcSMatt Macy } 1601*eda14cbcSMatt Macy 1602*eda14cbcSMatt Macy if (pzhp != NULL) 1603*eda14cbcSMatt Macy zfs_close(pzhp); 1604*eda14cbcSMatt Macy if (props != NULL) 1605*eda14cbcSMatt Macy nvlist_free(props); 1606*eda14cbcSMatt Macy if (wkeydata != NULL) 1607*eda14cbcSMatt Macy free(wkeydata); 1608*eda14cbcSMatt Macy 1609*eda14cbcSMatt Macy return (ret); 1610*eda14cbcSMatt Macy 1611*eda14cbcSMatt Macy error: 1612*eda14cbcSMatt Macy if (pzhp != NULL) 1613*eda14cbcSMatt Macy zfs_close(pzhp); 1614*eda14cbcSMatt Macy if (props != NULL) 1615*eda14cbcSMatt Macy nvlist_free(props); 1616*eda14cbcSMatt Macy if (wkeydata != NULL) 1617*eda14cbcSMatt Macy free(wkeydata); 1618*eda14cbcSMatt Macy 1619*eda14cbcSMatt Macy zfs_error(zhp->zfs_hdl, EZFS_CRYPTOFAILED, errbuf); 1620*eda14cbcSMatt Macy return (ret); 1621*eda14cbcSMatt Macy } 1622