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