diff options
Diffstat (limited to 'usr/src')
114 files changed, 8042 insertions, 363 deletions
diff --git a/usr/src/cmd/boot/bootadm/bootadm.c b/usr/src/cmd/boot/bootadm/bootadm.c index dfafc5f87f..2d3a3ff8d2 100644 --- a/usr/src/cmd/boot/bootadm/bootadm.c +++ b/usr/src/cmd/boot/bootadm/bootadm.c @@ -83,6 +83,7 @@ #include <sys/efi_partition.h> #include <regex.h> #include <locale.h> +#include <sys/mkdev.h> #include "message.h" #include "bootadm.h" @@ -96,7 +97,8 @@ /* Primary subcmds */ typedef enum { BAM_MENU = 3, - BAM_ARCHIVE + BAM_ARCHIVE, + BAM_INSTALL } subcmd_t; typedef enum { @@ -233,12 +235,14 @@ static int bam_purge = 0; static char *bam_subcmd; static char *bam_opt; static char **bam_argv; +static char *bam_pool; static int bam_argc; static int bam_check; static int bam_saved_check; static int bam_smf_check; static int bam_lock_fd = -1; static int bam_zfs; +static int bam_mbr; static char rootbuf[PATH_MAX] = "/"; static int bam_update_all; static int bam_alt_platform; @@ -249,6 +253,7 @@ static char *bam_home_env = NULL; static void parse_args_internal(int, char *[]); static void parse_args(int, char *argv[]); static error_t bam_menu(char *, char *, int, char *[]); +static error_t bam_install(char *, char *); static error_t bam_archive(char *, char *); static void bam_lock(void); @@ -269,6 +274,7 @@ static error_t delete_all_entries(menu_t *, char *, char *); static error_t update_entry(menu_t *mp, char *menu_root, char *opt); static error_t update_temp(menu_t *mp, char *dummy, char *opt); +static error_t install_bootloader(void); static error_t update_archive(char *, char *); static error_t list_archive(char *, char *); static error_t update_all(char *, char *); @@ -318,6 +324,12 @@ static subcmd_defn_t arch_subcmds[] = { NULL, 0, NULL, 0 /* must be last */ }; +/* Install related sub commands */ +static subcmd_defn_t inst_subcmds[] = { + "install_bootloader", OPT_ABSENT, install_bootloader, 0, /* PUB */ + NULL, 0, NULL, 0 /* must be last */ +}; + enum dircache_copy_opt { FILE32 = 0, FILE64, @@ -446,6 +458,13 @@ usage(void) "\t%s update-archive [-vn] [-R altroot [-p platform]]\n", prog); (void) fprintf(stderr, "\t%s list-archive [-R altroot [-p platform]]\n", prog); +#if defined(_OPB) + (void) fprintf(stderr, + "\t%s install-bootloader [-fv] [-R altroot] [-P pool]\n", prog); +#else + (void) fprintf(stderr, + "\t%s install-bootloader [-Mfv] [-R altroot] [-P pool]\n", prog); +#endif #if !defined(_OPB) /* x86 only */ (void) fprintf(stderr, "\t%s set-menu [-R altroot] key=value\n", prog); @@ -540,6 +559,9 @@ main(int argc, char *argv[]) case BAM_ARCHIVE: ret = bam_archive(bam_subcmd, bam_opt); break; + case BAM_INSTALL: + ret = bam_install(bam_subcmd, bam_opt); + break; default: usage(); bam_exit(1); @@ -559,6 +581,7 @@ main(int argc, char *argv[]) * set-menu -- -m set_option * list-menu -- -m list_entry * update-menu -- -m update_entry + * install-bootloader -- -i install_bootloader */ static struct cmd_map { char *bam_cmdname; @@ -570,6 +593,7 @@ static struct cmd_map { { "set-menu", BAM_MENU, "set_option"}, { "list-menu", BAM_MENU, "list_entry"}, { "update-menu", BAM_MENU, "update_entry"}, + { "install-bootloader", BAM_INSTALL, "install_bootloader"}, { NULL, 0, NULL} }; @@ -611,6 +635,7 @@ parse_args(int argc, char *argv[]) * -a update -- update-archive * -a list -- list-archive * -a update-all -- (reboot to sync all mnted OS archive) + * -i install_bootloader -- install-bootloader * -m update_entry -- update-menu * -m list_entry -- list-menu * -m update_temp -- (reboot -- [boot-args]) @@ -630,12 +655,17 @@ parse_args_internal(int argc, char *argv[]) int c, error; extern char *optarg; extern int optind, opterr; +#if defined(_OPB) + const char *optstring = "a:d:fi:m:no:veFCR:p:P:XZ"; +#else + const char *optstring = "a:d:fi:m:no:veFCMR:p:P:XZ"; +#endif /* Suppress error message from getopt */ opterr = 0; error = 0; - while ((c = getopt(argc, argv, "a:d:fm:no:veFCR:p:XZ")) != -1) { + while ((c = getopt(argc, argv, optstring)) != -1) { switch (c) { case 'a': if (bam_cmd) { @@ -658,6 +688,14 @@ parse_args_internal(int argc, char *argv[]) case 'F': bam_purge = 1; break; + case 'i': + if (bam_cmd) { + error = 1; + bam_error(MULT_CMDS, c); + } + bam_cmd = BAM_INSTALL; + bam_subcmd = optarg; + break; case 'm': if (bam_cmd) { error = 1; @@ -666,6 +704,11 @@ parse_args_internal(int argc, char *argv[]) bam_cmd = BAM_MENU; bam_subcmd = optarg; break; +#if !defined(_OPB) + case 'M': + bam_mbr = 1; + break; +#endif case 'n': bam_check = 1; /* @@ -693,6 +736,13 @@ parse_args_internal(int argc, char *argv[]) case 'C': bam_smf_check = 1; break; + case 'P': + if (bam_pool != NULL) { + error = 1; + bam_error(DUP_OPT, c); + } + bam_pool = optarg; + break; case 'R': if (bam_root) { error = 1; @@ -772,6 +822,14 @@ parse_args_internal(int argc, char *argv[]) } /* + * mbr and pool are options for install_bootloader + */ + if (bam_cmd != BAM_INSTALL && (bam_mbr || bam_pool != NULL)) { + usage(); + bam_exit(0); + } + + /* * -n implies verbose mode */ if (bam_check) @@ -981,6 +1039,241 @@ list_setting(menu_t *mp, char *which, char *setting) } static error_t +install_bootloader(void) +{ + nvlist_t *nvl; + uint16_t flags = 0; + int found = 0; + struct extmnttab mnt; + struct stat statbuf = {0}; + be_node_list_t *be_nodes, *node; + FILE *fp; + char *root_ds = NULL; + int ret; + + if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { + bam_error(_("out of memory\n")); + return (BAM_ERROR); + } + + /* + * if bam_alt_root is set, the stage files are used from alt root. + * if pool is set, the target devices are pool devices, stage files + * are read from pool bootfs unless alt root is set. + * + * use arguments as targets, stage files are from alt or current root + * if no arguments and no pool, install on current boot pool. + */ + + if (bam_alt_root) { + if (stat(bam_root, &statbuf) != 0) { + bam_error(STAT_FAIL, bam_root, strerror(errno)); + ret = BAM_ERROR; + goto done; + } + if ((fp = fopen(MNTTAB, "r")) == NULL) { + bam_error(OPEN_FAIL, MNTTAB, strerror(errno)); + ret = BAM_ERROR; + goto done; + } + resetmnttab(fp); + while (getextmntent(fp, &mnt, sizeof (mnt)) == 0) { + if (mnt.mnt_major == major(statbuf.st_dev) && + mnt.mnt_minor == minor(statbuf.st_dev)) { + found = 1; + root_ds = strdup(mnt.mnt_special); + break; + } + } + (void) fclose(fp); + + if (found == 0) { + bam_error(NOT_IN_MNTTAB, bam_root); + ret = BAM_ERROR; + goto done; + } + if (root_ds == NULL) { + bam_error(_("out of memory\n")); + ret = BAM_ERROR; + goto done; + } + + if (be_list(NULL, &be_nodes) != BE_SUCCESS) { + bam_error(_("No BE's found\n")); + ret = BAM_ERROR; + goto done; + } + for (node = be_nodes; node != NULL; node = node->be_next_node) + if (strcmp(root_ds, node->be_root_ds) == 0) + break; + + if (node == NULL) + bam_error(_("BE (%s) does not exist\n"), root_ds); + + free(root_ds); + root_ds = NULL; + if (node == NULL) { + be_free_list(be_nodes); + ret = BAM_ERROR; + goto done; + } + ret = nvlist_add_string(nvl, BE_ATTR_ORIG_BE_NAME, + node->be_node_name); + ret |= nvlist_add_string(nvl, BE_ATTR_ORIG_BE_ROOT, + node->be_root_ds); + be_free_list(be_nodes); + if (ret) { + ret = BAM_ERROR; + goto done; + } + } + + if (bam_force) + flags |= BE_INSTALLBOOT_FLAG_FORCE; + if (bam_mbr) + flags |= BE_INSTALLBOOT_FLAG_MBR; + if (bam_verbose) + flags |= BE_INSTALLBOOT_FLAG_VERBOSE; + + if (nvlist_add_uint16(nvl, BE_ATTR_INSTALL_FLAGS, flags) != 0) { + bam_error(_("out of memory\n")); + goto done; + } + + /* + * if altroot was set, we got be name and be root, only need + * to set pool name as target. + * if no altroot, need to find be name and root from pool. + */ + if (bam_pool != NULL) { + ret = nvlist_add_string(nvl, BE_ATTR_ORIG_BE_POOL, bam_pool); + if (ret) { + ret = BAM_ERROR; + goto done; + } + if (found) { + ret = be_installboot(nvl); + if (ret) + ret = BAM_ERROR; + goto done; + } + } + + if (be_list(NULL, &be_nodes) != BE_SUCCESS) { + bam_error(_("No BE's found\n")); + ret = BAM_ERROR; + goto done; + } + + if (bam_pool != NULL) { + /* + * find active be_node in bam_pool + */ + for (node = be_nodes; node != NULL; node = node->be_next_node) { + if (strcmp(bam_pool, node->be_rpool) != 0) + continue; + if (node->be_active_on_boot) + break; + } + if (node == NULL) { + bam_error(_("No active BE in %s\n"), bam_pool); + be_free_list(be_nodes); + ret = BAM_ERROR; + goto done; + } + ret = nvlist_add_string(nvl, BE_ATTR_ORIG_BE_NAME, + node->be_node_name); + ret |= nvlist_add_string(nvl, BE_ATTR_ORIG_BE_ROOT, + node->be_root_ds); + be_free_list(be_nodes); + if (ret) { + ret = BAM_ERROR; + goto done; + } + ret = be_installboot(nvl); + if (ret) + ret = BAM_ERROR; + goto done; + } + + /* + * get dataset for "/" and fill up the args. + */ + if ((fp = fopen(MNTTAB, "r")) == NULL) { + bam_error(OPEN_FAIL, MNTTAB, strerror(errno)); + ret = BAM_ERROR; + be_free_list(be_nodes); + goto done; + } + resetmnttab(fp); + found = 0; + while (getextmntent(fp, &mnt, sizeof (mnt)) == 0) { + if (strcmp(mnt.mnt_mountp, "/") == 0) { + found = 1; + root_ds = strdup(mnt.mnt_special); + break; + } + } + (void) fclose(fp); + + if (found == 0) { + bam_error(NOT_IN_MNTTAB, "/"); + ret = BAM_ERROR; + be_free_list(be_nodes); + goto done; + } + if (root_ds == NULL) { + bam_error(_("out of memory\n")); + ret = BAM_ERROR; + be_free_list(be_nodes); + goto done; + } + + for (node = be_nodes; node != NULL; node = node->be_next_node) { + if (strcmp(root_ds, node->be_root_ds) == 0) + break; + } + + if (node == NULL) { + bam_error(_("No such BE: %s\n"), root_ds); + free(root_ds); + be_free_list(be_nodes); + ret = BAM_ERROR; + goto done; + } + free(root_ds); + + ret = nvlist_add_string(nvl, BE_ATTR_ORIG_BE_NAME, node->be_node_name); + ret |= nvlist_add_string(nvl, BE_ATTR_ORIG_BE_ROOT, node->be_root_ds); + ret |= nvlist_add_string(nvl, BE_ATTR_ORIG_BE_POOL, node->be_rpool); + be_free_list(be_nodes); + + if (ret) + ret = BAM_ERROR; + else + ret = be_installboot(nvl) ? BAM_ERROR : 0; +done: + nvlist_free(nvl); + + return (ret); +} + +static error_t +bam_install(char *subcmd, char *opt) +{ + error_t (*f)(void); + + /* + * Check arguments + */ + if (check_subcmd_and_options(subcmd, opt, inst_subcmds, &f) == + BAM_ERROR) + return (BAM_ERROR); + + return (f()); +} + +static error_t bam_menu(char *subcmd, char *opt, int largc, char *largv[]) { error_t ret; diff --git a/usr/src/cmd/cron/at.c b/usr/src/cmd/cron/at.c index 37fe880ee2..68769c2f8a 100644 --- a/usr/src/cmd/cron/at.c +++ b/usr/src/cmd/cron/at.c @@ -101,6 +101,7 @@ static int not_this_project(char *); static char *mkjobname(time_t); static time_t parse_time(char *); static time_t gtime(struct tm *); +static void escapestr(const char *); void atabort(char *)__NORETURN; void yyerror(void); extern int yyparse(void); @@ -546,6 +547,23 @@ struct tm *tptr; } /* + * Escape a string to be used inside the job shell script. + */ +static void +escapestr(const char *str) +{ + char c; + (void) putchar('\''); + while ((c = *str++) != '\0') { + if (c != '\'') + (void) putchar(c); + else + (void) fputs("'\\''", stdout); /* ' -> '\'' */ + } + (void) putchar('\''); +} + +/* * make job file from proto + stdin */ static void @@ -633,12 +651,12 @@ copy(char *jobfile, FILE *inputfile, int when) } for (ep = environ; *ep; ep++) { - if (strchr(*ep, '\'') != NULL) - continue; if ((val = strchr(*ep, '=')) == NULL) continue; *val++ = '\0'; - printf("export %s; %s='%s'\n", *ep, *ep, val); + (void) printf("export %s; %s=", *ep, *ep); + escapestr(val); + (void) putchar('\n'); *--val = '='; } if ((pfp = fopen(pname1, "r")) == NULL && @@ -678,7 +696,7 @@ copy(char *jobfile, FILE *inputfile, int when) if (seteuid(effeusr) < 0) { atabort(CANTCHUID); } - printf("%s", dirbuf); + escapestr(dirbuf); break; case 'm': printf("%o", um); diff --git a/usr/src/cmd/prtdiag/i386/smbios.c b/usr/src/cmd/prtdiag/i386/smbios.c index 4bdbfe36be..a7ba98d562 100644 --- a/usr/src/cmd/prtdiag/i386/smbios.c +++ b/usr/src/cmd/prtdiag/i386/smbios.c @@ -287,8 +287,8 @@ do_slots(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg) * 0xff. Therefore if we find any of them set there, we just * ignore it for now. */ - if (s.smbl_sg != 0xff || s.smbl_bus != 0xff || - s.smbl_df != 0xff || arg != NULL) + if (s.smbl_sg != 0xff && s.smbl_bus != 0xff && + s.smbl_df != 0xff && arg != NULL) do_slot_mapping(&s, arg); (void) printf(gettext("\n")); diff --git a/usr/src/common/crypto/edonr/edonr.c b/usr/src/common/crypto/edonr/edonr.c new file mode 100644 index 0000000000..afc4361e26 --- /dev/null +++ b/usr/src/common/crypto/edonr/edonr.c @@ -0,0 +1,729 @@ +/* + * IDI,NTNU + * + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Copyright (C) 2009, 2010, Jorn Amundsen <jorn.amundsen@ntnu.no> + * Tweaked Edon-R implementation for SUPERCOP, based on NIST API. + * + * $Id: edonr.c 517 2013-02-17 20:34:39Z joern $ + */ +/* + * Portions copyright (c) 2013, Saso Kiselkov, All rights reserved + */ + +/* determine where we can get bcopy/bzero declarations */ +#ifdef _KERNEL +#include <sys/systm.h> +#else +#include <strings.h> +#endif +#include <sys/edonr.h> +#include <sys/debug.h> + +/* big endian support, provides no-op's if run on little endian hosts */ +#include "edonr_byteorder.h" + +#define hashState224(x) ((x)->pipe->p256) +#define hashState256(x) ((x)->pipe->p256) +#define hashState384(x) ((x)->pipe->p512) +#define hashState512(x) ((x)->pipe->p512) + +/* shift and rotate shortcuts */ +#define shl(x, n) ((x) << n) +#define shr(x, n) ((x) >> n) + +#define rotl32(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) +#define rotr32(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) + +#define rotl64(x, n) (((x) << (n)) | ((x) >> (64 - (n)))) +#define rotr64(x, n) (((x) >> (n)) | ((x) << (64 - (n)))) + +#if !defined(__C99_RESTRICT) +#define restrict /* restrict */ +#endif + +#define EDONR_VALID_HASHBITLEN(x) \ + ((x) == 512 || (x) == 384 || (x) == 256 || (x) == 224) + +/* EdonR224 initial double chaining pipe */ +static const uint32_t i224p2[16] = { + 0x00010203ul, 0x04050607ul, 0x08090a0bul, 0x0c0d0e0ful, + 0x10111213ul, 0x14151617ul, 0x18191a1bul, 0x1c1d1e1ful, + 0x20212223ul, 0x24252627ul, 0x28292a2bul, 0x2c2d2e2ful, + 0x30313233ul, 0x34353637ul, 0x38393a3bul, 0x3c3d3e3ful, +}; + +/* EdonR256 initial double chaining pipe */ +static const uint32_t i256p2[16] = { + 0x40414243ul, 0x44454647ul, 0x48494a4bul, 0x4c4d4e4ful, + 0x50515253ul, 0x54555657ul, 0x58595a5bul, 0x5c5d5e5ful, + 0x60616263ul, 0x64656667ul, 0x68696a6bul, 0x6c6d6e6ful, + 0x70717273ul, 0x74757677ul, 0x78797a7bul, 0x7c7d7e7ful, +}; + +/* EdonR384 initial double chaining pipe */ +static const uint64_t i384p2[16] = { + 0x0001020304050607ull, 0x08090a0b0c0d0e0full, + 0x1011121314151617ull, 0x18191a1b1c1d1e1full, + 0x2021222324252627ull, 0x28292a2b2c2d2e2full, + 0x3031323334353637ull, 0x38393a3b3c3d3e3full, + 0x4041424344454647ull, 0x48494a4b4c4d4e4full, + 0x5051525354555657ull, 0x58595a5b5c5d5e5full, + 0x6061626364656667ull, 0x68696a6b6c6d6e6full, + 0x7071727374757677ull, 0x78797a7b7c7d7e7full +}; + +/* EdonR512 initial double chaining pipe */ +static const uint64_t i512p2[16] = { + 0x8081828384858687ull, 0x88898a8b8c8d8e8full, + 0x9091929394959697ull, 0x98999a9b9c9d9e9full, + 0xa0a1a2a3a4a5a6a7ull, 0xa8a9aaabacadaeafull, + 0xb0b1b2b3b4b5b6b7ull, 0xb8b9babbbcbdbebfull, + 0xc0c1c2c3c4c5c6c7ull, 0xc8c9cacbcccdcecfull, + 0xd0d1d2d3d4d5d6d7ull, 0xd8d9dadbdcdddedfull, + 0xe0e1e2e3e4e5e6e7ull, 0xe8e9eaebecedeeefull, + 0xf0f1f2f3f4f5f6f7ull, 0xf8f9fafbfcfdfeffull +}; + +/* + * First Latin Square + * 0 7 1 3 2 4 6 5 + * 4 1 7 6 3 0 5 2 + * 7 0 4 2 5 3 1 6 + * 1 4 0 5 6 2 7 3 + * 2 3 6 7 1 5 0 4 + * 5 2 3 1 7 6 4 0 + * 3 6 5 0 4 7 2 1 + * 6 5 2 4 0 1 3 7 + */ +#define LS1_256(c, x0, x1, x2, x3, x4, x5, x6, x7) \ +{ \ + uint32_t x04, x17, x23, x56, x07, x26; \ + x04 = x0+x4, x17 = x1+x7, x07 = x04+x17; \ + s0 = c + x07 + x2; \ + s1 = rotl32(x07 + x3, 4); \ + s2 = rotl32(x07 + x6, 8); \ + x23 = x2 + x3; \ + s5 = rotl32(x04 + x23 + x5, 22); \ + x56 = x5 + x6; \ + s6 = rotl32(x17 + x56 + x0, 24); \ + x26 = x23+x56; \ + s3 = rotl32(x26 + x7, 13); \ + s4 = rotl32(x26 + x1, 17); \ + s7 = rotl32(x26 + x4, 29); \ +} + +#define LS1_512(c, x0, x1, x2, x3, x4, x5, x6, x7) \ +{ \ + uint64_t x04, x17, x23, x56, x07, x26; \ + x04 = x0+x4, x17 = x1+x7, x07 = x04+x17; \ + s0 = c + x07 + x2; \ + s1 = rotl64(x07 + x3, 5); \ + s2 = rotl64(x07 + x6, 15); \ + x23 = x2 + x3; \ + s5 = rotl64(x04 + x23 + x5, 40); \ + x56 = x5 + x6; \ + s6 = rotl64(x17 + x56 + x0, 50); \ + x26 = x23+x56; \ + s3 = rotl64(x26 + x7, 22); \ + s4 = rotl64(x26 + x1, 31); \ + s7 = rotl64(x26 + x4, 59); \ +} + +/* + * Second Orthogonal Latin Square + * 0 4 2 3 1 6 5 7 + * 7 6 3 2 5 4 1 0 + * 5 3 1 6 0 2 7 4 + * 1 0 5 4 3 7 2 6 + * 2 1 0 7 4 5 6 3 + * 3 5 7 0 6 1 4 2 + * 4 7 6 1 2 0 3 5 + * 6 2 4 5 7 3 0 1 + */ +#define LS2_256(c, y0, y1, y2, y3, y4, y5, y6, y7) \ +{ \ + uint32_t y01, y25, y34, y67, y04, y05, y27, y37; \ + y01 = y0+y1, y25 = y2+y5, y05 = y01+y25; \ + t0 = ~c + y05 + y7; \ + t2 = rotl32(y05 + y3, 9); \ + y34 = y3+y4, y04 = y01+y34; \ + t1 = rotl32(y04 + y6, 5); \ + t4 = rotl32(y04 + y5, 15); \ + y67 = y6+y7, y37 = y34+y67; \ + t3 = rotl32(y37 + y2, 11); \ + t7 = rotl32(y37 + y0, 27); \ + y27 = y25+y67; \ + t5 = rotl32(y27 + y4, 20); \ + t6 = rotl32(y27 + y1, 25); \ +} + +#define LS2_512(c, y0, y1, y2, y3, y4, y5, y6, y7) \ +{ \ + uint64_t y01, y25, y34, y67, y04, y05, y27, y37; \ + y01 = y0+y1, y25 = y2+y5, y05 = y01+y25; \ + t0 = ~c + y05 + y7; \ + t2 = rotl64(y05 + y3, 19); \ + y34 = y3+y4, y04 = y01+y34; \ + t1 = rotl64(y04 + y6, 10); \ + t4 = rotl64(y04 + y5, 36); \ + y67 = y6+y7, y37 = y34+y67; \ + t3 = rotl64(y37 + y2, 29); \ + t7 = rotl64(y37 + y0, 55); \ + y27 = y25+y67; \ + t5 = rotl64(y27 + y4, 44); \ + t6 = rotl64(y27 + y1, 48); \ +} + +#define quasi_exform256(r0, r1, r2, r3, r4, r5, r6, r7) \ +{ \ + uint32_t s04, s17, s23, s56, t01, t25, t34, t67; \ + s04 = s0 ^ s4, t01 = t0 ^ t1; \ + r0 = (s04 ^ s1) + (t01 ^ t5); \ + t67 = t6 ^ t7; \ + r1 = (s04 ^ s7) + (t2 ^ t67); \ + s23 = s2 ^ s3; \ + r7 = (s23 ^ s5) + (t4 ^ t67); \ + t34 = t3 ^ t4; \ + r3 = (s23 ^ s4) + (t0 ^ t34); \ + s56 = s5 ^ s6; \ + r5 = (s3 ^ s56) + (t34 ^ t6); \ + t25 = t2 ^ t5; \ + r6 = (s2 ^ s56) + (t25 ^ t7); \ + s17 = s1 ^ s7; \ + r4 = (s0 ^ s17) + (t1 ^ t25); \ + r2 = (s17 ^ s6) + (t01 ^ t3); \ +} + +#define quasi_exform512(r0, r1, r2, r3, r4, r5, r6, r7) \ +{ \ + uint64_t s04, s17, s23, s56, t01, t25, t34, t67; \ + s04 = s0 ^ s4, t01 = t0 ^ t1; \ + r0 = (s04 ^ s1) + (t01 ^ t5); \ + t67 = t6 ^ t7; \ + r1 = (s04 ^ s7) + (t2 ^ t67); \ + s23 = s2 ^ s3; \ + r7 = (s23 ^ s5) + (t4 ^ t67); \ + t34 = t3 ^ t4; \ + r3 = (s23 ^ s4) + (t0 ^ t34); \ + s56 = s5 ^ s6; \ + r5 = (s3 ^ s56) + (t34 ^ t6); \ + t25 = t2 ^ t5; \ + r6 = (s2 ^ s56) + (t25 ^ t7); \ + s17 = s1 ^ s7; \ + r4 = (s0 ^ s17) + (t1 ^ t25); \ + r2 = (s17 ^ s6) + (t01 ^ t3); \ +} + +static size_t +Q256(size_t bitlen, const uint32_t *data, uint32_t *restrict p) +{ + size_t bl; + + for (bl = bitlen; bl >= EdonR256_BLOCK_BITSIZE; + bl -= EdonR256_BLOCK_BITSIZE, data += 16) { + uint32_t s0, s1, s2, s3, s4, s5, s6, s7, t0, t1, t2, t3, t4, + t5, t6, t7; + uint32_t p0, p1, p2, p3, p4, p5, p6, p7, q0, q1, q2, q3, q4, + q5, q6, q7; + const uint32_t defix = 0xaaaaaaaa; +#if defined(MACHINE_IS_BIG_ENDIAN) + uint32_t swp0, swp1, swp2, swp3, swp4, swp5, swp6, swp7, swp8, + swp9, swp10, swp11, swp12, swp13, swp14, swp15; +#define d(j) swp ## j +#define s32(j) ld_swap32((uint32_t *)data + j, swp ## j) +#else +#define d(j) data[j] +#endif + + /* First row of quasigroup e-transformations */ +#if defined(MACHINE_IS_BIG_ENDIAN) + s32(8); + s32(9); + s32(10); + s32(11); + s32(12); + s32(13); + s32(14); + s32(15); +#endif + LS1_256(defix, d(15), d(14), d(13), d(12), d(11), d(10), d(9), + d(8)); +#if defined(MACHINE_IS_BIG_ENDIAN) + s32(0); + s32(1); + s32(2); + s32(3); + s32(4); + s32(5); + s32(6); + s32(7); +#undef s32 +#endif + LS2_256(defix, d(0), d(1), d(2), d(3), d(4), d(5), d(6), d(7)); + quasi_exform256(p0, p1, p2, p3, p4, p5, p6, p7); + + LS1_256(defix, p0, p1, p2, p3, p4, p5, p6, p7); + LS2_256(defix, d(8), d(9), d(10), d(11), d(12), d(13), d(14), + d(15)); + quasi_exform256(q0, q1, q2, q3, q4, q5, q6, q7); + + /* Second row of quasigroup e-transformations */ + LS1_256(defix, p[8], p[9], p[10], p[11], p[12], p[13], p[14], + p[15]); + LS2_256(defix, p0, p1, p2, p3, p4, p5, p6, p7); + quasi_exform256(p0, p1, p2, p3, p4, p5, p6, p7); + + LS1_256(defix, p0, p1, p2, p3, p4, p5, p6, p7); + LS2_256(defix, q0, q1, q2, q3, q4, q5, q6, q7); + quasi_exform256(q0, q1, q2, q3, q4, q5, q6, q7); + + /* Third row of quasigroup e-transformations */ + LS1_256(defix, p0, p1, p2, p3, p4, p5, p6, p7); + LS2_256(defix, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + quasi_exform256(p0, p1, p2, p3, p4, p5, p6, p7); + + LS1_256(defix, q0, q1, q2, q3, q4, q5, q6, q7); + LS2_256(defix, p0, p1, p2, p3, p4, p5, p6, p7); + quasi_exform256(q0, q1, q2, q3, q4, q5, q6, q7); + + /* Fourth row of quasigroup e-transformations */ + LS1_256(defix, d(7), d(6), d(5), d(4), d(3), d(2), d(1), d(0)); + LS2_256(defix, p0, p1, p2, p3, p4, p5, p6, p7); + quasi_exform256(p0, p1, p2, p3, p4, p5, p6, p7); + + LS1_256(defix, p0, p1, p2, p3, p4, p5, p6, p7); + LS2_256(defix, q0, q1, q2, q3, q4, q5, q6, q7); + quasi_exform256(q0, q1, q2, q3, q4, q5, q6, q7); + + /* Edon-R tweak on the original SHA-3 Edon-R submission. */ + p[0] ^= d(8) ^ p0; + p[1] ^= d(9) ^ p1; + p[2] ^= d(10) ^ p2; + p[3] ^= d(11) ^ p3; + p[4] ^= d(12) ^ p4; + p[5] ^= d(13) ^ p5; + p[6] ^= d(14) ^ p6; + p[7] ^= d(15) ^ p7; + p[8] ^= d(0) ^ q0; + p[9] ^= d(1) ^ q1; + p[10] ^= d(2) ^ q2; + p[11] ^= d(3) ^ q3; + p[12] ^= d(4) ^ q4; + p[13] ^= d(5) ^ q5; + p[14] ^= d(6) ^ q6; + p[15] ^= d(7) ^ q7; + } + +#undef d + return (bitlen - bl); +} + +#if defined(__IBMC__) && defined(_AIX) && defined(__64BIT__) +static inline size_t +#else +static size_t +#endif +Q512(size_t bitlen, const uint64_t *data, uint64_t *restrict p) +{ + size_t bl; + + for (bl = bitlen; bl >= EdonR512_BLOCK_BITSIZE; + bl -= EdonR512_BLOCK_BITSIZE, data += 16) { + uint64_t s0, s1, s2, s3, s4, s5, s6, s7, t0, t1, t2, t3, t4, + t5, t6, t7; + uint64_t p0, p1, p2, p3, p4, p5, p6, p7, q0, q1, q2, q3, q4, + q5, q6, q7; + const uint64_t defix = 0xaaaaaaaaaaaaaaaaull; +#if defined(MACHINE_IS_BIG_ENDIAN) + uint64_t swp0, swp1, swp2, swp3, swp4, swp5, swp6, swp7, swp8, + swp9, swp10, swp11, swp12, swp13, swp14, swp15; +#define d(j) swp##j +#define s64(j) ld_swap64((uint64_t *)data+j, swp##j) +#else +#define d(j) data[j] +#endif + + /* First row of quasigroup e-transformations */ +#if defined(MACHINE_IS_BIG_ENDIAN) + s64(8); + s64(9); + s64(10); + s64(11); + s64(12); + s64(13); + s64(14); + s64(15); +#endif + LS1_512(defix, d(15), d(14), d(13), d(12), d(11), d(10), d(9), + d(8)); +#if defined(MACHINE_IS_BIG_ENDIAN) + s64(0); + s64(1); + s64(2); + s64(3); + s64(4); + s64(5); + s64(6); + s64(7); +#undef s64 +#endif + LS2_512(defix, d(0), d(1), d(2), d(3), d(4), d(5), d(6), d(7)); + quasi_exform512(p0, p1, p2, p3, p4, p5, p6, p7); + + LS1_512(defix, p0, p1, p2, p3, p4, p5, p6, p7); + LS2_512(defix, d(8), d(9), d(10), d(11), d(12), d(13), d(14), + d(15)); + quasi_exform512(q0, q1, q2, q3, q4, q5, q6, q7); + + /* Second row of quasigroup e-transformations */ + LS1_512(defix, p[8], p[9], p[10], p[11], p[12], p[13], p[14], + p[15]); + LS2_512(defix, p0, p1, p2, p3, p4, p5, p6, p7); + quasi_exform512(p0, p1, p2, p3, p4, p5, p6, p7); + + LS1_512(defix, p0, p1, p2, p3, p4, p5, p6, p7); + LS2_512(defix, q0, q1, q2, q3, q4, q5, q6, q7); + quasi_exform512(q0, q1, q2, q3, q4, q5, q6, q7); + + /* Third row of quasigroup e-transformations */ + LS1_512(defix, p0, p1, p2, p3, p4, p5, p6, p7); + LS2_512(defix, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + quasi_exform512(p0, p1, p2, p3, p4, p5, p6, p7); + + LS1_512(defix, q0, q1, q2, q3, q4, q5, q6, q7); + LS2_512(defix, p0, p1, p2, p3, p4, p5, p6, p7); + quasi_exform512(q0, q1, q2, q3, q4, q5, q6, q7); + + /* Fourth row of quasigroup e-transformations */ + LS1_512(defix, d(7), d(6), d(5), d(4), d(3), d(2), d(1), d(0)); + LS2_512(defix, p0, p1, p2, p3, p4, p5, p6, p7); + quasi_exform512(p0, p1, p2, p3, p4, p5, p6, p7); + + LS1_512(defix, p0, p1, p2, p3, p4, p5, p6, p7); + LS2_512(defix, q0, q1, q2, q3, q4, q5, q6, q7); + quasi_exform512(q0, q1, q2, q3, q4, q5, q6, q7); + + /* Edon-R tweak on the original SHA-3 Edon-R submission. */ + p[0] ^= d(8) ^ p0; + p[1] ^= d(9) ^ p1; + p[2] ^= d(10) ^ p2; + p[3] ^= d(11) ^ p3; + p[4] ^= d(12) ^ p4; + p[5] ^= d(13) ^ p5; + p[6] ^= d(14) ^ p6; + p[7] ^= d(15) ^ p7; + p[8] ^= d(0) ^ q0; + p[9] ^= d(1) ^ q1; + p[10] ^= d(2) ^ q2; + p[11] ^= d(3) ^ q3; + p[12] ^= d(4) ^ q4; + p[13] ^= d(5) ^ q5; + p[14] ^= d(6) ^ q6; + p[15] ^= d(7) ^ q7; + } + +#undef d + return (bitlen - bl); +} + +void +EdonRInit(EdonRState *state, size_t hashbitlen) +{ + ASSERT(EDONR_VALID_HASHBITLEN(hashbitlen)); + switch (hashbitlen) { + case 224: + state->hashbitlen = 224; + state->bits_processed = 0; + state->unprocessed_bits = 0; + bcopy(i224p2, hashState224(state)->DoublePipe, + 16 * sizeof (uint32_t)); + break; + + case 256: + state->hashbitlen = 256; + state->bits_processed = 0; + state->unprocessed_bits = 0; + bcopy(i256p2, hashState256(state)->DoublePipe, + 16 * sizeof (uint32_t)); + break; + + case 384: + state->hashbitlen = 384; + state->bits_processed = 0; + state->unprocessed_bits = 0; + bcopy(i384p2, hashState384(state)->DoublePipe, + 16 * sizeof (uint64_t)); + break; + + case 512: + state->hashbitlen = 512; + state->bits_processed = 0; + state->unprocessed_bits = 0; + bcopy(i512p2, hashState224(state)->DoublePipe, + 16 * sizeof (uint64_t)); + break; + } +} + + +void +EdonRUpdate(EdonRState *state, const uint8_t *data, size_t databitlen) +{ + uint32_t *data32; + uint64_t *data64; + + size_t bits_processed; + + ASSERT(EDONR_VALID_HASHBITLEN(state->hashbitlen)); + switch (state->hashbitlen) { + case 224: + case 256: + if (state->unprocessed_bits > 0) { + /* LastBytes = databitlen / 8 */ + int LastBytes = (int)databitlen >> 3; + + ASSERT(state->unprocessed_bits + databitlen <= + EdonR256_BLOCK_SIZE * 8); + + bcopy(data, hashState256(state)->LastPart + + (state->unprocessed_bits >> 3), LastBytes); + state->unprocessed_bits += (int)databitlen; + databitlen = state->unprocessed_bits; + /* LINTED E_BAD_PTR_CAST_ALIGN */ + data32 = (uint32_t *)hashState256(state)->LastPart; + } else + /* LINTED E_BAD_PTR_CAST_ALIGN */ + data32 = (uint32_t *)data; + + bits_processed = Q256(databitlen, data32, + hashState256(state)->DoublePipe); + state->bits_processed += bits_processed; + databitlen -= bits_processed; + state->unprocessed_bits = (int)databitlen; + if (databitlen > 0) { + /* LastBytes = Ceil(databitlen / 8) */ + int LastBytes = + ((~(((-(int)databitlen) >> 3) & 0x01ff)) + + 1) & 0x01ff; + + data32 += bits_processed >> 5; /* byte size update */ + bcopy(data32, hashState256(state)->LastPart, LastBytes); + } + break; + + case 384: + case 512: + if (state->unprocessed_bits > 0) { + /* LastBytes = databitlen / 8 */ + int LastBytes = (int)databitlen >> 3; + + ASSERT(state->unprocessed_bits + databitlen <= + EdonR512_BLOCK_SIZE * 8); + + bcopy(data, hashState512(state)->LastPart + + (state->unprocessed_bits >> 3), LastBytes); + state->unprocessed_bits += (int)databitlen; + databitlen = state->unprocessed_bits; + /* LINTED E_BAD_PTR_CAST_ALIGN */ + data64 = (uint64_t *)hashState512(state)->LastPart; + } else + /* LINTED E_BAD_PTR_CAST_ALIGN */ + data64 = (uint64_t *)data; + + bits_processed = Q512(databitlen, data64, + hashState512(state)->DoublePipe); + state->bits_processed += bits_processed; + databitlen -= bits_processed; + state->unprocessed_bits = (int)databitlen; + if (databitlen > 0) { + /* LastBytes = Ceil(databitlen / 8) */ + int LastBytes = + ((~(((-(int)databitlen) >> 3) & 0x03ff)) + + 1) & 0x03ff; + + data64 += bits_processed >> 6; /* byte size update */ + bcopy(data64, hashState512(state)->LastPart, LastBytes); + } + break; + } +} + +void +EdonRFinal(EdonRState *state, uint8_t *hashval) +{ + uint32_t *data32; + uint64_t *data64, num_bits; + + size_t databitlen; + int LastByte, PadOnePosition; + + num_bits = state->bits_processed + state->unprocessed_bits; + ASSERT(EDONR_VALID_HASHBITLEN(state->hashbitlen)); + switch (state->hashbitlen) { + case 224: + case 256: + LastByte = (int)state->unprocessed_bits >> 3; + PadOnePosition = 7 - (state->unprocessed_bits & 0x07); + hashState256(state)->LastPart[LastByte] = + (hashState256(state)->LastPart[LastByte] + & (0xff << (PadOnePosition + 1))) ^ + (0x01 << PadOnePosition); + /* LINTED E_BAD_PTR_CAST_ALIGN */ + data64 = (uint64_t *)hashState256(state)->LastPart; + + if (state->unprocessed_bits < 448) { + (void) memset((hashState256(state)->LastPart) + + LastByte + 1, 0x00, + EdonR256_BLOCK_SIZE - LastByte - 9); + databitlen = EdonR256_BLOCK_SIZE * 8; +#if defined(MACHINE_IS_BIG_ENDIAN) + st_swap64(num_bits, data64 + 7); +#else + data64[7] = num_bits; +#endif + } else { + (void) memset((hashState256(state)->LastPart) + + LastByte + 1, 0x00, + EdonR256_BLOCK_SIZE * 2 - LastByte - 9); + databitlen = EdonR256_BLOCK_SIZE * 16; +#if defined(MACHINE_IS_BIG_ENDIAN) + st_swap64(num_bits, data64 + 15); +#else + data64[15] = num_bits; +#endif + } + + /* LINTED E_BAD_PTR_CAST_ALIGN */ + data32 = (uint32_t *)hashState256(state)->LastPart; + state->bits_processed += Q256(databitlen, data32, + hashState256(state)->DoublePipe); + break; + + case 384: + case 512: + LastByte = (int)state->unprocessed_bits >> 3; + PadOnePosition = 7 - (state->unprocessed_bits & 0x07); + hashState512(state)->LastPart[LastByte] = + (hashState512(state)->LastPart[LastByte] + & (0xff << (PadOnePosition + 1))) ^ + (0x01 << PadOnePosition); + /* LINTED E_BAD_PTR_CAST_ALIGN */ + data64 = (uint64_t *)hashState512(state)->LastPart; + + if (state->unprocessed_bits < 960) { + (void) memset((hashState512(state)->LastPart) + + LastByte + 1, 0x00, + EdonR512_BLOCK_SIZE - LastByte - 9); + databitlen = EdonR512_BLOCK_SIZE * 8; +#if defined(MACHINE_IS_BIG_ENDIAN) + st_swap64(num_bits, data64 + 15); +#else + data64[15] = num_bits; +#endif + } else { + (void) memset((hashState512(state)->LastPart) + + LastByte + 1, 0x00, + EdonR512_BLOCK_SIZE * 2 - LastByte - 9); + databitlen = EdonR512_BLOCK_SIZE * 16; +#if defined(MACHINE_IS_BIG_ENDIAN) + st_swap64(num_bits, data64 + 31); +#else + data64[31] = num_bits; +#endif + } + + state->bits_processed += Q512(databitlen, data64, + hashState512(state)->DoublePipe); + break; + } + + switch (state->hashbitlen) { + case 224: { +#if defined(MACHINE_IS_BIG_ENDIAN) + uint32_t *d32 = (uint32_t *)hashval; + uint32_t *s32 = hashState224(state)->DoublePipe + 9; + int j; + + for (j = 0; j < EdonR224_DIGEST_SIZE >> 2; j++) + st_swap32(s32[j], d32 + j); +#else + bcopy(hashState256(state)->DoublePipe + 9, hashval, + EdonR224_DIGEST_SIZE); +#endif + break; + } + case 256: { +#if defined(MACHINE_IS_BIG_ENDIAN) + uint32_t *d32 = (uint32_t *)hashval; + uint32_t *s32 = hashState224(state)->DoublePipe + 8; + int j; + + for (j = 0; j < EdonR256_DIGEST_SIZE >> 2; j++) + st_swap32(s32[j], d32 + j); +#else + bcopy(hashState256(state)->DoublePipe + 8, hashval, + EdonR256_DIGEST_SIZE); +#endif + break; + } + case 384: { +#if defined(MACHINE_IS_BIG_ENDIAN) + uint64_t *d64 = (uint64_t *)hashval; + uint64_t *s64 = hashState384(state)->DoublePipe + 10; + int j; + + for (j = 0; j < EdonR384_DIGEST_SIZE >> 3; j++) + st_swap64(s64[j], d64 + j); +#else + bcopy(hashState384(state)->DoublePipe + 10, hashval, + EdonR384_DIGEST_SIZE); +#endif + break; + } + case 512: { +#if defined(MACHINE_IS_BIG_ENDIAN) + uint64_t *d64 = (uint64_t *)hashval; + uint64_t *s64 = hashState512(state)->DoublePipe + 8; + int j; + + for (j = 0; j < EdonR512_DIGEST_SIZE >> 3; j++) + st_swap64(s64[j], d64 + j); +#else + bcopy(hashState512(state)->DoublePipe + 8, hashval, + EdonR512_DIGEST_SIZE); +#endif + break; + } + } +} + + +void +EdonRHash(size_t hashbitlen, const uint8_t *data, size_t databitlen, + uint8_t *hashval) +{ + EdonRState state; + + EdonRInit(&state, hashbitlen); + EdonRUpdate(&state, data, databitlen); + EdonRFinal(&state, hashval); +} diff --git a/usr/src/common/crypto/edonr/edonr_byteorder.h b/usr/src/common/crypto/edonr/edonr_byteorder.h new file mode 100644 index 0000000000..9fdf2b3de4 --- /dev/null +++ b/usr/src/common/crypto/edonr/edonr_byteorder.h @@ -0,0 +1,219 @@ +/* + * IDI,NTNU + * + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Copyright (C) 2009, 2010, Jorn Amundsen <jorn.amundsen@ntnu.no> + * + * C header file to determine compile machine byte order. Take care when cross + * compiling. + * + * $Id: byteorder.h 517 2013-02-17 20:34:39Z joern $ + */ +/* + * Portions copyright (c) 2013, Saso Kiselkov, All rights reserved + */ + +#ifndef _CRYPTO_EDONR_BYTEORDER_H +#define _CRYPTO_EDONR_BYTEORDER_H + +#if defined(__linux) +#include <endian.h> +#else +#include <sys/param.h> +#endif + +#if defined(__BYTE_ORDER) +#if (__BYTE_ORDER == __BIG_ENDIAN) +#define MACHINE_IS_BIG_ENDIAN +#elif (__BYTE_ORDER == __LITTLE_ENDIAN) +#define MACHINE_IS_LITTLE_ENDIAN +#endif +#elif defined(BYTE_ORDER) +#if (BYTE_ORDER == BIG_ENDIAN) +#define MACHINE_IS_BIG_ENDIAN +#elif (BYTE_ORDER == LITTLE_ENDIAN) +#define MACHINE_IS_LITTLE_ENDIAN +#endif +#endif /* __BYTE_ORDER || BYTE_ORDER */ + +#if !defined(MACHINE_IS_BIG_ENDIAN) && !defined(MACHINE_IS_LITTLE_ENDIAN) +#if defined(_BIG_ENDIAN) || defined(_MIPSEB) +#define MACHINE_IS_BIG_ENDIAN +#endif +#if defined(_LITTLE_ENDIAN) || defined(_MIPSEL) +#define MACHINE_IS_LITTLE_ENDIAN +#endif +#endif /* !MACHINE_IS_BIG_ENDIAN && !MACHINE_IS_LITTLE_ENDIAN */ + +#if !defined(MACHINE_IS_BIG_ENDIAN) && !defined(MACHINE_IS_LITTLE_ENDIAN) +#error unknown machine byte sex +#endif + +#define BYTEORDER_INCLUDED + +#if defined(MACHINE_IS_BIG_ENDIAN) +/* + * Byte swapping macros for big endian architectures and compilers, + * add as appropriate for other architectures and/or compilers. + * + * ld_swap64(src,dst) : uint64_t dst = *(src) + * st_swap64(src,dst) : *(dst) = uint64_t src + */ + +#if defined(__PPC__) || defined(_ARCH_PPC) + +#if defined(__64BIT__) +#if defined(_ARCH_PWR7) +#define aix_ld_swap64(s64, d64)\ + __asm__("ldbrx %0,0,%1" : "=r"(d64) : "r"(s64)) +#define aix_st_swap64(s64, d64)\ + __asm__ volatile("stdbrx %1,0,%0" : : "r"(d64), "r"(s64)) +#else +#define aix_ld_swap64(s64, d64) \ +{ \ + uint64_t *s4, h; \ + \ + __asm__("addi %0,%3,4;lwbrx %1,0,%3;lwbrx %2,0,%0;rldimi %1,%2,32,0"\ + : "+r"(s4), "=r"(d64), "=r"(h) : "b"(s64)); \ +} + +#define aix_st_swap64(s64, d64) \ +{ \ + uint64_t *s4, h; \ + h = (s64) >> 32; \ + __asm__ volatile("addi %0,%3,4;stwbrx %1,0,%3;stwbrx %2,0,%0" \ + : "+r"(s4) : "r"(s64), "r"(h), "b"(d64)); \ +} +#endif /* 64BIT && PWR7 */ +#else +#define aix_ld_swap64(s64, d64) \ +{ \ + uint32_t *s4, h, l; \ + __asm__("addi %0,%3,4;lwbrx %1,0,%3;lwbrx %2,0,%0" \ + : "+r"(s4), "=r"(l), "=r"(h) : "b"(s64)); \ + d64 = ((uint64_t)h<<32) | l; \ +} + +#define aix_st_swap64(s64, d64) \ +{ \ + uint32_t *s4, h, l; \ + l = (s64) & 0xfffffffful, h = (s64) >> 32; \ + __asm__ volatile("addi %0,%3,4;stwbrx %1,0,%3;stwbrx %2,0,%0" \ + : "+r"(s4) : "r"(l), "r"(h), "b"(d64)); \ +} +#endif /* __64BIT__ */ +#define aix_ld_swap32(s32, d32)\ + __asm__("lwbrx %0,0,%1" : "=r"(d32) : "r"(s32)) +#define aix_st_swap32(s32, d32)\ + __asm__ volatile("stwbrx %1,0,%0" : : "r"(d32), "r"(s32)) +#define ld_swap32(s, d) aix_ld_swap32(s, d) +#define st_swap32(s, d) aix_st_swap32(s, d) +#define ld_swap64(s, d) aix_ld_swap64(s, d) +#define st_swap64(s, d) aix_st_swap64(s, d) +#endif /* __PPC__ || _ARCH_PPC */ + +#if defined(__sparc) +#if !defined(__arch64__) && !defined(__sparcv8) && defined(__sparcv9) +#define __arch64__ +#endif +#if defined(__GNUC__) || (defined(__SUNPRO_C) && __SUNPRO_C > 0x590) +/* need Sun Studio C 5.10 and above for GNU inline assembly */ +#if defined(__arch64__) +#define sparc_ld_swap64(s64, d64) \ + __asm__("ldxa [%1]0x88,%0" : "=r"(d64) : "r"(s64)) +#define sparc_st_swap64(s64, d64) \ + __asm__ volatile("stxa %0,[%1]0x88" : : "r"(s64), "r"(d64)) +#define st_swap64(s, d) sparc_st_swap64(s, d) +#else +#define sparc_ld_swap64(s64, d64) \ +{ \ + uint32_t *s4, h, l; \ + __asm__("add %3,4,%0\n\tlda [%3]0x88,%1\n\tlda [%0]0x88,%2" \ + : "+r"(s4), "=r"(l), "=r"(h) : "r"(s64)); \ + d64 = ((uint64_t)h<<32) | l; \ +} +#define sparc_st_swap64(s64, d64) \ +{ \ + uint32_t *s4, h, l; \ + l = (s64) & 0xfffffffful, h = (s64) >> 32; \ + __asm__ volatile("add %3,4,%0\n\tsta %1,[%3]0x88\n\tsta %2,[%0]0x88"\ + : "+r"(s4) : "r"(l), "r"(h), "r"(d64)); \ +} +#endif /* sparc64 */ +#define sparc_ld_swap32(s32, d32)\ + __asm__("lda [%1]0x88,%0" : "=r"(d32) : "r"(s32)) +#define sparc_st_swap32(s32, d32)\ + __asm__ volatile("sta %0,[%1]0x88" : : "r"(s32), "r"(d32)) +#define ld_swap32(s, d) sparc_ld_swap32(s, d) +#define st_swap32(s, d) sparc_st_swap32(s, d) +#define ld_swap64(s, d) sparc_ld_swap64(s, d) +#define st_swap64(s, d) sparc_st_swap64(s, d) +#endif /* GCC || Sun Studio C > 5.9 */ +#endif /* sparc */ + +/* GCC fallback */ +#if ((__GNUC__ >= 4) || defined(__PGIC__)) && !defined(ld_swap32) +#define ld_swap32(s, d) (d = __builtin_bswap32(*(s))) +#define st_swap32(s, d) (*(d) = __builtin_bswap32(s)) +#endif /* GCC4/PGIC && !swap32 */ +#if ((__GNUC__ >= 4) || defined(__PGIC__)) && !defined(ld_swap64) +#define ld_swap64(s, d) (d = __builtin_bswap64(*(s))) +#define st_swap64(s, d) (*(d) = __builtin_bswap64(s)) +#endif /* GCC4/PGIC && !swap64 */ + +/* generic fallback */ +#if !defined(ld_swap32) +#define ld_swap32(s, d) \ + (d = (*(s) >> 24) | (*(s) >> 8 & 0xff00) | \ + (*(s) << 8 & 0xff0000) | (*(s) << 24)) +#define st_swap32(s, d) \ + (*(d) = ((s) >> 24) | ((s) >> 8 & 0xff00) | \ + ((s) << 8 & 0xff0000) | ((s) << 24)) +#endif +#if !defined(ld_swap64) +#define ld_swap64(s, d) \ + (d = (*(s) >> 56) | (*(s) >> 40 & 0xff00) | \ + (*(s) >> 24 & 0xff0000) | (*(s) >> 8 & 0xff000000) | \ + (*(s) & 0xff000000) << 8 | (*(s) & 0xff0000) << 24 | \ + (*(s) & 0xff00) << 40 | *(s) << 56) +#define st_swap64(s, d) \ + (*(d) = ((s) >> 56) | ((s) >> 40 & 0xff00) | \ + ((s) >> 24 & 0xff0000) | ((s) >> 8 & 0xff000000) | \ + ((s) & 0xff000000) << 8 | ((s) & 0xff0000) << 24 | \ + ((s) & 0xff00) << 40 | (s) << 56) +#endif + +#endif /* MACHINE_IS_BIG_ENDIAN */ + + +#if defined(MACHINE_IS_LITTLE_ENDIAN) +/* replace swaps with simple assignments on little endian systems */ +#undef ld_swap32 +#undef st_swap32 +#define ld_swap32(s, d) (d = *(s)) +#define st_swap32(s, d) (*(d) = s) +#undef ld_swap64 +#undef st_swap64 +#define ld_swap64(s, d) (d = *(s)) +#define st_swap64(s, d) (*(d) = s) +#endif /* MACHINE_IS_LITTLE_ENDIAN */ + +#endif /* _CRYPTO_EDONR_BYTEORDER_H */ diff --git a/usr/src/common/crypto/sha2/sha2.c b/usr/src/common/crypto/sha2/sha2.c index 1a2603ccf0..56ac1ffcd9 100644 --- a/usr/src/common/crypto/sha2/sha2.c +++ b/usr/src/common/crypto/sha2/sha2.c @@ -2,6 +2,9 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2013 Saso Kiselkov. All rights reserved. + */ /* * The basic framework for this code came from the reference @@ -715,6 +718,26 @@ SHA2Init(uint64_t mech, SHA2_CTX *ctx) ctx->state.s64[6] = 0x1f83d9abfb41bd6bULL; ctx->state.s64[7] = 0x5be0cd19137e2179ULL; break; + case SHA512_224_MECH_INFO_TYPE: + ctx->state.s64[0] = 0x8C3D37C819544DA2ULL; + ctx->state.s64[1] = 0x73E1996689DCD4D6ULL; + ctx->state.s64[2] = 0x1DFAB7AE32FF9C82ULL; + ctx->state.s64[3] = 0x679DD514582F9FCFULL; + ctx->state.s64[4] = 0x0F6D2B697BD44DA8ULL; + ctx->state.s64[5] = 0x77E36F7304C48942ULL; + ctx->state.s64[6] = 0x3F9D85A86A1D36C8ULL; + ctx->state.s64[7] = 0x1112E6AD91D692A1ULL; + break; + case SHA512_256_MECH_INFO_TYPE: + ctx->state.s64[0] = 0x22312194FC2BF72CULL; + ctx->state.s64[1] = 0x9F555FA3C84C64C2ULL; + ctx->state.s64[2] = 0x2393B86B6F53B151ULL; + ctx->state.s64[3] = 0x963877195940EABDULL; + ctx->state.s64[4] = 0x96283EE2A88EFFE3ULL; + ctx->state.s64[5] = 0xBE5E1E2553863992ULL; + ctx->state.s64[6] = 0x2B0199FC2C85B8AAULL; + ctx->state.s64[7] = 0x0EB72DDC81C52CA2ULL; + break; #ifdef _KERNEL default: cmn_err(CE_PANIC, @@ -901,7 +924,6 @@ SHA2Final(void *digest, SHA2_CTX *ctx) SHA2Update(ctx, PADDING, ((index < 56) ? 56 : 120) - index); SHA2Update(ctx, bitcount_be, sizeof (bitcount_be)); Encode(digest, ctx->state.s32, sizeof (ctx->state.s32)); - } else { index = (ctx->count.c64[1] >> 3) & 0x7f; Encode64(bitcount_be64, ctx->count.c64, @@ -912,9 +934,25 @@ SHA2Final(void *digest, SHA2_CTX *ctx) ctx->state.s64[6] = ctx->state.s64[7] = 0; Encode64(digest, ctx->state.s64, sizeof (uint64_t) * 6); - } else + } else if (algotype == SHA512_224_MECH_INFO_TYPE) { + uint8_t last[sizeof (uint64_t)]; + /* + * Since SHA-512/224 doesn't align well to 64-bit + * boundaries, we must do the encoding in three steps: + * 1) encode the three 64-bit words that fit neatly + * 2) encode the last 64-bit word to a temp buffer + * 3) chop out the lower 32-bits from the temp buffer + * and append them to the digest + */ + Encode64(digest, ctx->state.s64, sizeof (uint64_t) * 3); + Encode64(last, &ctx->state.s64[3], sizeof (uint64_t)); + bcopy(last, (uint8_t *)digest + 24, 4); + } else if (algotype == SHA512_256_MECH_INFO_TYPE) { + Encode64(digest, ctx->state.s64, sizeof (uint64_t) * 4); + } else { Encode64(digest, ctx->state.s64, sizeof (ctx->state.s64)); + } } /* zeroize sensitive information */ diff --git a/usr/src/common/crypto/skein/THIRDPARTYLICENSE b/usr/src/common/crypto/skein/THIRDPARTYLICENSE new file mode 100644 index 0000000000..b7434fd178 --- /dev/null +++ b/usr/src/common/crypto/skein/THIRDPARTYLICENSE @@ -0,0 +1,3 @@ +Implementation of the Skein hash function. +Source code author: Doug Whiting, 2008. +This algorithm and source code is released to the public domain. diff --git a/usr/src/common/crypto/skein/THIRDPARTYLICENSE.descrip b/usr/src/common/crypto/skein/THIRDPARTYLICENSE.descrip new file mode 100644 index 0000000000..0ae89cfdf5 --- /dev/null +++ b/usr/src/common/crypto/skein/THIRDPARTYLICENSE.descrip @@ -0,0 +1 @@ +LICENSE TERMS OF SKEIN HASH ALGORITHM IMPLEMENTATION diff --git a/usr/src/common/crypto/skein/skein.c b/usr/src/common/crypto/skein/skein.c new file mode 100644 index 0000000000..00421fdf66 --- /dev/null +++ b/usr/src/common/crypto/skein/skein.c @@ -0,0 +1,914 @@ +/* + * Implementation of the Skein hash function. + * Source code author: Doug Whiting, 2008. + * This algorithm and source code is released to the public domain. + */ +/* Copyright 2013 Doug Whiting. This code is released to the public domain. */ + +#define SKEIN_PORT_CODE /* instantiate any code in skein_port.h */ + +#include <sys/types.h> +#include <sys/note.h> +#include <sys/skein.h> /* get the Skein API definitions */ +#include "skein_impl.h" /* get internal definitions */ + +/* External function to process blkCnt (nonzero) full block(s) of data. */ +void Skein_256_Process_Block(Skein_256_Ctxt_t *ctx, const uint8_t *blkPtr, + size_t blkCnt, size_t byteCntAdd); +void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx, const uint8_t *blkPtr, + size_t blkCnt, size_t byteCntAdd); +void Skein1024_Process_Block(Skein1024_Ctxt_t *ctx, const uint8_t *blkPtr, + size_t blkCnt, size_t byteCntAdd); + +/* 256-bit Skein */ +/* init the context for a straight hashing operation */ +int +Skein_256_Init(Skein_256_Ctxt_t *ctx, size_t hashBitLen) +{ + union { + uint8_t b[SKEIN_256_STATE_BYTES]; + uint64_t w[SKEIN_256_STATE_WORDS]; + } cfg; /* config block */ + + Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN); + ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ + + switch (hashBitLen) { /* use pre-computed values, where available */ +#ifndef SKEIN_NO_PRECOMP + case 256: + bcopy(SKEIN_256_IV_256, ctx->X, sizeof (ctx->X)); + break; + case 224: + bcopy(SKEIN_256_IV_224, ctx->X, sizeof (ctx->X)); + break; + case 160: + bcopy(SKEIN_256_IV_160, ctx->X, sizeof (ctx->X)); + break; + case 128: + bcopy(SKEIN_256_IV_128, ctx->X, sizeof (ctx->X)); + break; +#endif + default: + /* here if there is no precomputed IV value available */ + /* + * build/process the config block, type == CONFIG (could be + * precomputed) + */ + /* set tweaks: T0=0; T1=CFG | FINAL */ + Skein_Start_New_Type(ctx, CFG_FINAL); + + /* set the schema, version */ + cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); + /* hash result length in bits */ + cfg.w[1] = Skein_Swap64(hashBitLen); + cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL); + /* zero pad config block */ + bzero(&cfg.w[3], sizeof (cfg) - 3 * sizeof (cfg.w[0])); + + /* compute the initial chaining values from config block */ + /* zero the chaining variables */ + bzero(ctx->X, sizeof (ctx->X)); + Skein_256_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN); + break; + } + /* + * The chaining vars ctx->X are now initialized for the given + * hashBitLen. + * Set up to process the data message portion of the hash (default) + */ + Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */ + + return (SKEIN_SUCCESS); +} + +/* init the context for a MAC and/or tree hash operation */ +/* + * [identical to Skein_256_Init() when keyBytes == 0 && + * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] + */ +int +Skein_256_InitExt(Skein_256_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo, + const uint8_t *key, size_t keyBytes) +{ + union { + uint8_t b[SKEIN_256_STATE_BYTES]; + uint64_t w[SKEIN_256_STATE_WORDS]; + } cfg; /* config block */ + + Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN); + Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL); + + /* compute the initial chaining values ctx->X[], based on key */ + if (keyBytes == 0) { /* is there a key? */ + /* no key: use all zeroes as key for config block */ + bzero(ctx->X, sizeof (ctx->X)); + } else { /* here to pre-process a key */ + + Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X)); + /* do a mini-Init right here */ + /* set output hash bit count = state size */ + ctx->h.hashBitLen = 8 * sizeof (ctx->X); + /* set tweaks: T0 = 0; T1 = KEY type */ + Skein_Start_New_Type(ctx, KEY); + /* zero the initial chaining variables */ + bzero(ctx->X, sizeof (ctx->X)); + /* hash the key */ + (void) Skein_256_Update(ctx, key, keyBytes); + /* put result into cfg.b[] */ + (void) Skein_256_Final_Pad(ctx, cfg.b); + /* copy over into ctx->X[] */ + bcopy(cfg.b, ctx->X, sizeof (cfg.b)); +#if SKEIN_NEED_SWAP + { + uint_t i; + /* convert key bytes to context words */ + for (i = 0; i < SKEIN_256_STATE_WORDS; i++) + ctx->X[i] = Skein_Swap64(ctx->X[i]); + } +#endif + } + /* + * build/process the config block, type == CONFIG (could be + * precomputed for each key) + */ + ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ + Skein_Start_New_Type(ctx, CFG_FINAL); + + bzero(&cfg.w, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */ + cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); + cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ + /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */ + cfg.w[2] = Skein_Swap64(treeInfo); + + Skein_Show_Key(256, &ctx->h, key, keyBytes); + + /* compute the initial chaining values from config block */ + Skein_256_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN); + + /* The chaining vars ctx->X are now initialized */ + /* Set up to process the data message portion of the hash (default) */ + ctx->h.bCnt = 0; /* buffer b[] starts out empty */ + Skein_Start_New_Type(ctx, MSG); + + return (SKEIN_SUCCESS); +} + +/* process the input bytes */ +int +Skein_256_Update(Skein_256_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt) +{ + size_t n; + + /* catch uninitialized context */ + Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL); + + /* process full blocks, if any */ + if (msgByteCnt + ctx->h.bCnt > SKEIN_256_BLOCK_BYTES) { + /* finish up any buffered message data */ + if (ctx->h.bCnt) { + /* # bytes free in buffer b[] */ + n = SKEIN_256_BLOCK_BYTES - ctx->h.bCnt; + if (n) { + /* check on our logic here */ + Skein_assert(n < msgByteCnt); + bcopy(msg, &ctx->b[ctx->h.bCnt], n); + msgByteCnt -= n; + msg += n; + ctx->h.bCnt += n; + } + Skein_assert(ctx->h.bCnt == SKEIN_256_BLOCK_BYTES); + Skein_256_Process_Block(ctx, ctx->b, 1, + SKEIN_256_BLOCK_BYTES); + ctx->h.bCnt = 0; + } + /* + * now process any remaining full blocks, directly from input + * message data + */ + if (msgByteCnt > SKEIN_256_BLOCK_BYTES) { + /* number of full blocks to process */ + n = (msgByteCnt - 1) / SKEIN_256_BLOCK_BYTES; + Skein_256_Process_Block(ctx, msg, n, + SKEIN_256_BLOCK_BYTES); + msgByteCnt -= n * SKEIN_256_BLOCK_BYTES; + msg += n * SKEIN_256_BLOCK_BYTES; + } + Skein_assert(ctx->h.bCnt == 0); + } + + /* copy any remaining source message data bytes into b[] */ + if (msgByteCnt) { + Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES); + bcopy(msg, &ctx->b[ctx->h.bCnt], msgByteCnt); + ctx->h.bCnt += msgByteCnt; + } + + return (SKEIN_SUCCESS); +} + +/* finalize the hash computation and output the result */ +int +Skein_256_Final(Skein_256_Ctxt_t *ctx, uint8_t *hashVal) +{ + size_t i, n, byteCnt; + uint64_t X[SKEIN_256_STATE_WORDS]; + + /* catch uninitialized context */ + Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL); + + ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ + /* zero pad b[] if necessary */ + if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES) + bzero(&ctx->b[ctx->h.bCnt], + SKEIN_256_BLOCK_BYTES - ctx->h.bCnt); + + /* process the final block */ + Skein_256_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt); + + /* now output the result */ + /* total number of output bytes */ + byteCnt = (ctx->h.hashBitLen + 7) >> 3; + + /* run Threefish in "counter mode" to generate output */ + /* zero out b[], so it can hold the counter */ + bzero(ctx->b, sizeof (ctx->b)); + /* keep a local copy of counter mode "key" */ + bcopy(ctx->X, X, sizeof (X)); + for (i = 0; i * SKEIN_256_BLOCK_BYTES < byteCnt; i++) { + /* build the counter block */ + uint64_t tmp = Skein_Swap64((uint64_t)i); + bcopy(&tmp, ctx->b, sizeof (tmp)); + Skein_Start_New_Type(ctx, OUT_FINAL); + /* run "counter mode" */ + Skein_256_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t)); + /* number of output bytes left to go */ + n = byteCnt - i * SKEIN_256_BLOCK_BYTES; + if (n >= SKEIN_256_BLOCK_BYTES) + n = SKEIN_256_BLOCK_BYTES; + Skein_Put64_LSB_First(hashVal + i * SKEIN_256_BLOCK_BYTES, + ctx->X, n); /* "output" the ctr mode bytes */ + Skein_Show_Final(256, &ctx->h, n, + hashVal + i * SKEIN_256_BLOCK_BYTES); + /* restore the counter mode key for next time */ + bcopy(X, ctx->X, sizeof (X)); + } + return (SKEIN_SUCCESS); +} + +/* 512-bit Skein */ + +/* init the context for a straight hashing operation */ +int +Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen) +{ + union { + uint8_t b[SKEIN_512_STATE_BYTES]; + uint64_t w[SKEIN_512_STATE_WORDS]; + } cfg; /* config block */ + + Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN); + ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ + + switch (hashBitLen) { /* use pre-computed values, where available */ +#ifndef SKEIN_NO_PRECOMP + case 512: + bcopy(SKEIN_512_IV_512, ctx->X, sizeof (ctx->X)); + break; + case 384: + bcopy(SKEIN_512_IV_384, ctx->X, sizeof (ctx->X)); + break; + case 256: + bcopy(SKEIN_512_IV_256, ctx->X, sizeof (ctx->X)); + break; + case 224: + bcopy(SKEIN_512_IV_224, ctx->X, sizeof (ctx->X)); + break; +#endif + default: + /* + * here if there is no precomputed IV value available + * build/process the config block, type == CONFIG (could be + * precomputed) + */ + /* set tweaks: T0=0; T1=CFG | FINAL */ + Skein_Start_New_Type(ctx, CFG_FINAL); + + /* set the schema, version */ + cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); + /* hash result length in bits */ + cfg.w[1] = Skein_Swap64(hashBitLen); + cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL); + /* zero pad config block */ + bzero(&cfg.w[3], sizeof (cfg) - 3 * sizeof (cfg.w[0])); + + /* compute the initial chaining values from config block */ + /* zero the chaining variables */ + bzero(ctx->X, sizeof (ctx->X)); + Skein_512_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN); + break; + } + + /* + * The chaining vars ctx->X are now initialized for the given + * hashBitLen. Set up to process the data message portion of the + * hash (default) + */ + Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */ + + return (SKEIN_SUCCESS); +} + +/* init the context for a MAC and/or tree hash operation */ +/* + * [identical to Skein_512_Init() when keyBytes == 0 && + * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] + */ +int +Skein_512_InitExt(Skein_512_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo, + const uint8_t *key, size_t keyBytes) +{ + union { + uint8_t b[SKEIN_512_STATE_BYTES]; + uint64_t w[SKEIN_512_STATE_WORDS]; + } cfg; /* config block */ + + Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN); + Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL); + + /* compute the initial chaining values ctx->X[], based on key */ + if (keyBytes == 0) { /* is there a key? */ + /* no key: use all zeroes as key for config block */ + bzero(ctx->X, sizeof (ctx->X)); + } else { /* here to pre-process a key */ + + Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X)); + /* do a mini-Init right here */ + /* set output hash bit count = state size */ + ctx->h.hashBitLen = 8 * sizeof (ctx->X); + /* set tweaks: T0 = 0; T1 = KEY type */ + Skein_Start_New_Type(ctx, KEY); + /* zero the initial chaining variables */ + bzero(ctx->X, sizeof (ctx->X)); + (void) Skein_512_Update(ctx, key, keyBytes); /* hash the key */ + /* put result into cfg.b[] */ + (void) Skein_512_Final_Pad(ctx, cfg.b); + /* copy over into ctx->X[] */ + bcopy(cfg.b, ctx->X, sizeof (cfg.b)); +#if SKEIN_NEED_SWAP + { + uint_t i; + /* convert key bytes to context words */ + for (i = 0; i < SKEIN_512_STATE_WORDS; i++) + ctx->X[i] = Skein_Swap64(ctx->X[i]); + } +#endif + } + /* + * build/process the config block, type == CONFIG (could be + * precomputed for each key) + */ + ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ + Skein_Start_New_Type(ctx, CFG_FINAL); + + bzero(&cfg.w, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */ + cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); + cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ + /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */ + cfg.w[2] = Skein_Swap64(treeInfo); + + Skein_Show_Key(512, &ctx->h, key, keyBytes); + + /* compute the initial chaining values from config block */ + Skein_512_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN); + + /* The chaining vars ctx->X are now initialized */ + /* Set up to process the data message portion of the hash (default) */ + ctx->h.bCnt = 0; /* buffer b[] starts out empty */ + Skein_Start_New_Type(ctx, MSG); + + return (SKEIN_SUCCESS); +} + +/* process the input bytes */ +int +Skein_512_Update(Skein_512_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt) +{ + size_t n; + + /* catch uninitialized context */ + Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL); + + /* process full blocks, if any */ + if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES) { + /* finish up any buffered message data */ + if (ctx->h.bCnt) { + /* # bytes free in buffer b[] */ + n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt; + if (n) { + /* check on our logic here */ + Skein_assert(n < msgByteCnt); + bcopy(msg, &ctx->b[ctx->h.bCnt], n); + msgByteCnt -= n; + msg += n; + ctx->h.bCnt += n; + } + Skein_assert(ctx->h.bCnt == SKEIN_512_BLOCK_BYTES); + Skein_512_Process_Block(ctx, ctx->b, 1, + SKEIN_512_BLOCK_BYTES); + ctx->h.bCnt = 0; + } + /* + * now process any remaining full blocks, directly from input + * message data + */ + if (msgByteCnt > SKEIN_512_BLOCK_BYTES) { + /* number of full blocks to process */ + n = (msgByteCnt - 1) / SKEIN_512_BLOCK_BYTES; + Skein_512_Process_Block(ctx, msg, n, + SKEIN_512_BLOCK_BYTES); + msgByteCnt -= n * SKEIN_512_BLOCK_BYTES; + msg += n * SKEIN_512_BLOCK_BYTES; + } + Skein_assert(ctx->h.bCnt == 0); + } + + /* copy any remaining source message data bytes into b[] */ + if (msgByteCnt) { + Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES); + bcopy(msg, &ctx->b[ctx->h.bCnt], msgByteCnt); + ctx->h.bCnt += msgByteCnt; + } + + return (SKEIN_SUCCESS); +} + +/* finalize the hash computation and output the result */ +int +Skein_512_Final(Skein_512_Ctxt_t *ctx, uint8_t *hashVal) +{ + size_t i, n, byteCnt; + uint64_t X[SKEIN_512_STATE_WORDS]; + + /* catch uninitialized context */ + Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL); + + ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ + /* zero pad b[] if necessary */ + if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES) + bzero(&ctx->b[ctx->h.bCnt], + SKEIN_512_BLOCK_BYTES - ctx->h.bCnt); + + /* process the final block */ + Skein_512_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt); + + /* now output the result */ + /* total number of output bytes */ + byteCnt = (ctx->h.hashBitLen + 7) >> 3; + + /* run Threefish in "counter mode" to generate output */ + /* zero out b[], so it can hold the counter */ + bzero(ctx->b, sizeof (ctx->b)); + /* keep a local copy of counter mode "key" */ + bcopy(ctx->X, X, sizeof (X)); + for (i = 0; i * SKEIN_512_BLOCK_BYTES < byteCnt; i++) { + /* build the counter block */ + uint64_t tmp = Skein_Swap64((uint64_t)i); + bcopy(&tmp, ctx->b, sizeof (tmp)); + Skein_Start_New_Type(ctx, OUT_FINAL); + /* run "counter mode" */ + Skein_512_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t)); + /* number of output bytes left to go */ + n = byteCnt - i * SKEIN_512_BLOCK_BYTES; + if (n >= SKEIN_512_BLOCK_BYTES) + n = SKEIN_512_BLOCK_BYTES; + Skein_Put64_LSB_First(hashVal + i * SKEIN_512_BLOCK_BYTES, + ctx->X, n); /* "output" the ctr mode bytes */ + Skein_Show_Final(512, &ctx->h, n, + hashVal + i * SKEIN_512_BLOCK_BYTES); + /* restore the counter mode key for next time */ + bcopy(X, ctx->X, sizeof (X)); + } + return (SKEIN_SUCCESS); +} + +/* 1024-bit Skein */ + +/* init the context for a straight hashing operation */ +int +Skein1024_Init(Skein1024_Ctxt_t *ctx, size_t hashBitLen) +{ + union { + uint8_t b[SKEIN1024_STATE_BYTES]; + uint64_t w[SKEIN1024_STATE_WORDS]; + } cfg; /* config block */ + + Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN); + ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ + + switch (hashBitLen) { /* use pre-computed values, where available */ +#ifndef SKEIN_NO_PRECOMP + case 512: + bcopy(SKEIN1024_IV_512, ctx->X, sizeof (ctx->X)); + break; + case 384: + bcopy(SKEIN1024_IV_384, ctx->X, sizeof (ctx->X)); + break; + case 1024: + bcopy(SKEIN1024_IV_1024, ctx->X, sizeof (ctx->X)); + break; +#endif + default: + /* here if there is no precomputed IV value available */ + /* + * build/process the config block, type == CONFIG (could be + * precomputed) + */ + /* set tweaks: T0=0; T1=CFG | FINAL */ + Skein_Start_New_Type(ctx, CFG_FINAL); + + /* set the schema, version */ + cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); + /* hash result length in bits */ + cfg.w[1] = Skein_Swap64(hashBitLen); + cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL); + /* zero pad config block */ + bzero(&cfg.w[3], sizeof (cfg) - 3 * sizeof (cfg.w[0])); + + /* compute the initial chaining values from config block */ + /* zero the chaining variables */ + bzero(ctx->X, sizeof (ctx->X)); + Skein1024_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN); + break; + } + + /* + * The chaining vars ctx->X are now initialized for the given + * hashBitLen. Set up to process the data message portion of the hash + * (default) + */ + Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */ + + return (SKEIN_SUCCESS); +} + +/* init the context for a MAC and/or tree hash operation */ +/* + * [identical to Skein1024_Init() when keyBytes == 0 && + * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] + */ +int +Skein1024_InitExt(Skein1024_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo, + const uint8_t *key, size_t keyBytes) +{ + union { + uint8_t b[SKEIN1024_STATE_BYTES]; + uint64_t w[SKEIN1024_STATE_WORDS]; + } cfg; /* config block */ + + Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN); + Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL); + + /* compute the initial chaining values ctx->X[], based on key */ + if (keyBytes == 0) { /* is there a key? */ + /* no key: use all zeroes as key for config block */ + bzero(ctx->X, sizeof (ctx->X)); + } else { /* here to pre-process a key */ + Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X)); + /* do a mini-Init right here */ + /* set output hash bit count = state size */ + ctx->h.hashBitLen = 8 * sizeof (ctx->X); + /* set tweaks: T0 = 0; T1 = KEY type */ + Skein_Start_New_Type(ctx, KEY); + /* zero the initial chaining variables */ + bzero(ctx->X, sizeof (ctx->X)); + (void) Skein1024_Update(ctx, key, keyBytes); /* hash the key */ + /* put result into cfg.b[] */ + (void) Skein1024_Final_Pad(ctx, cfg.b); + /* copy over into ctx->X[] */ + bcopy(cfg.b, ctx->X, sizeof (cfg.b)); +#if SKEIN_NEED_SWAP + { + uint_t i; + /* convert key bytes to context words */ + for (i = 0; i < SKEIN1024_STATE_WORDS; i++) + ctx->X[i] = Skein_Swap64(ctx->X[i]); + } +#endif + } + /* + * build/process the config block, type == CONFIG (could be + * precomputed for each key) + */ + ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ + Skein_Start_New_Type(ctx, CFG_FINAL); + + bzero(&cfg.w, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */ + cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); + /* hash result length in bits */ + cfg.w[1] = Skein_Swap64(hashBitLen); + /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */ + cfg.w[2] = Skein_Swap64(treeInfo); + + Skein_Show_Key(1024, &ctx->h, key, keyBytes); + + /* compute the initial chaining values from config block */ + Skein1024_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN); + + /* The chaining vars ctx->X are now initialized */ + /* Set up to process the data message portion of the hash (default) */ + ctx->h.bCnt = 0; /* buffer b[] starts out empty */ + Skein_Start_New_Type(ctx, MSG); + + return (SKEIN_SUCCESS); +} + +/* process the input bytes */ +int +Skein1024_Update(Skein1024_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt) +{ + size_t n; + + /* catch uninitialized context */ + Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL); + + /* process full blocks, if any */ + if (msgByteCnt + ctx->h.bCnt > SKEIN1024_BLOCK_BYTES) { + /* finish up any buffered message data */ + if (ctx->h.bCnt) { + /* # bytes free in buffer b[] */ + n = SKEIN1024_BLOCK_BYTES - ctx->h.bCnt; + if (n) { + /* check on our logic here */ + Skein_assert(n < msgByteCnt); + bcopy(msg, &ctx->b[ctx->h.bCnt], n); + msgByteCnt -= n; + msg += n; + ctx->h.bCnt += n; + } + Skein_assert(ctx->h.bCnt == SKEIN1024_BLOCK_BYTES); + Skein1024_Process_Block(ctx, ctx->b, 1, + SKEIN1024_BLOCK_BYTES); + ctx->h.bCnt = 0; + } + /* + * now process any remaining full blocks, directly from + * input message data + */ + if (msgByteCnt > SKEIN1024_BLOCK_BYTES) { + /* number of full blocks to process */ + n = (msgByteCnt - 1) / SKEIN1024_BLOCK_BYTES; + Skein1024_Process_Block(ctx, msg, n, + SKEIN1024_BLOCK_BYTES); + msgByteCnt -= n * SKEIN1024_BLOCK_BYTES; + msg += n * SKEIN1024_BLOCK_BYTES; + } + Skein_assert(ctx->h.bCnt == 0); + } + + /* copy any remaining source message data bytes into b[] */ + if (msgByteCnt) { + Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES); + bcopy(msg, &ctx->b[ctx->h.bCnt], msgByteCnt); + ctx->h.bCnt += msgByteCnt; + } + + return (SKEIN_SUCCESS); +} + +/* finalize the hash computation and output the result */ +int +Skein1024_Final(Skein1024_Ctxt_t *ctx, uint8_t *hashVal) +{ + size_t i, n, byteCnt; + uint64_t X[SKEIN1024_STATE_WORDS]; + + /* catch uninitialized context */ + Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL); + + ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ + /* zero pad b[] if necessary */ + if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES) + bzero(&ctx->b[ctx->h.bCnt], + SKEIN1024_BLOCK_BYTES - ctx->h.bCnt); + + /* process the final block */ + Skein1024_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt); + + /* now output the result */ + /* total number of output bytes */ + byteCnt = (ctx->h.hashBitLen + 7) >> 3; + + /* run Threefish in "counter mode" to generate output */ + /* zero out b[], so it can hold the counter */ + bzero(ctx->b, sizeof (ctx->b)); + /* keep a local copy of counter mode "key" */ + bcopy(ctx->X, X, sizeof (X)); + for (i = 0; i * SKEIN1024_BLOCK_BYTES < byteCnt; i++) { + /* build the counter block */ + uint64_t tmp = Skein_Swap64((uint64_t)i); + bcopy(&tmp, ctx->b, sizeof (tmp)); + Skein_Start_New_Type(ctx, OUT_FINAL); + /* run "counter mode" */ + Skein1024_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t)); + /* number of output bytes left to go */ + n = byteCnt - i * SKEIN1024_BLOCK_BYTES; + if (n >= SKEIN1024_BLOCK_BYTES) + n = SKEIN1024_BLOCK_BYTES; + Skein_Put64_LSB_First(hashVal + i * SKEIN1024_BLOCK_BYTES, + ctx->X, n); /* "output" the ctr mode bytes */ + Skein_Show_Final(1024, &ctx->h, n, + hashVal + i * SKEIN1024_BLOCK_BYTES); + /* restore the counter mode key for next time */ + bcopy(X, ctx->X, sizeof (X)); + } + return (SKEIN_SUCCESS); +} + +/* Functions to support MAC/tree hashing */ +/* (this code is identical for Optimized and Reference versions) */ + +/* finalize the hash computation and output the block, no OUTPUT stage */ +int +Skein_256_Final_Pad(Skein_256_Ctxt_t *ctx, uint8_t *hashVal) +{ + /* catch uninitialized context */ + Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL); + + ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ + /* zero pad b[] if necessary */ + if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES) + bzero(&ctx->b[ctx->h.bCnt], + SKEIN_256_BLOCK_BYTES - ctx->h.bCnt); + /* process the final block */ + Skein_256_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt); + + /* "output" the state bytes */ + Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN_256_BLOCK_BYTES); + + return (SKEIN_SUCCESS); +} + +/* finalize the hash computation and output the block, no OUTPUT stage */ +int +Skein_512_Final_Pad(Skein_512_Ctxt_t *ctx, uint8_t *hashVal) +{ + /* catch uninitialized context */ + Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL); + + ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ + /* zero pad b[] if necessary */ + if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES) + bzero(&ctx->b[ctx->h.bCnt], + SKEIN_512_BLOCK_BYTES - ctx->h.bCnt); + /* process the final block */ + Skein_512_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt); + + /* "output" the state bytes */ + Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN_512_BLOCK_BYTES); + + return (SKEIN_SUCCESS); +} + +/* finalize the hash computation and output the block, no OUTPUT stage */ +int +Skein1024_Final_Pad(Skein1024_Ctxt_t *ctx, uint8_t *hashVal) +{ + /* catch uninitialized context */ + Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL); + + /* tag as the final block */ + ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; + /* zero pad b[] if necessary */ + if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES) + bzero(&ctx->b[ctx->h.bCnt], + SKEIN1024_BLOCK_BYTES - ctx->h.bCnt); + /* process the final block */ + Skein1024_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt); + + /* "output" the state bytes */ + Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN1024_BLOCK_BYTES); + + return (SKEIN_SUCCESS); +} + +#if SKEIN_TREE_HASH +/* just do the OUTPUT stage */ +int +Skein_256_Output(Skein_256_Ctxt_t *ctx, uint8_t *hashVal) +{ + size_t i, n, byteCnt; + uint64_t X[SKEIN_256_STATE_WORDS]; + + /* catch uninitialized context */ + Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL); + + /* now output the result */ + /* total number of output bytes */ + byteCnt = (ctx->h.hashBitLen + 7) >> 3; + + /* run Threefish in "counter mode" to generate output */ + /* zero out b[], so it can hold the counter */ + bzero(ctx->b, sizeof (ctx->b)); + /* keep a local copy of counter mode "key" */ + bcopy(ctx->X, X, sizeof (X)); + for (i = 0; i * SKEIN_256_BLOCK_BYTES < byteCnt; i++) { + /* build the counter block */ + uint64_t tmp = Skein_Swap64((uint64_t)i); + bcopy(&tmp, ctx->b, sizeof (tmp)); + Skein_Start_New_Type(ctx, OUT_FINAL); + /* run "counter mode" */ + Skein_256_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t)); + /* number of output bytes left to go */ + n = byteCnt - i * SKEIN_256_BLOCK_BYTES; + if (n >= SKEIN_256_BLOCK_BYTES) + n = SKEIN_256_BLOCK_BYTES; + Skein_Put64_LSB_First(hashVal + i * SKEIN_256_BLOCK_BYTES, + ctx->X, n); /* "output" the ctr mode bytes */ + Skein_Show_Final(256, &ctx->h, n, + hashVal + i * SKEIN_256_BLOCK_BYTES); + /* restore the counter mode key for next time */ + bcopy(X, ctx->X, sizeof (X)); + } + return (SKEIN_SUCCESS); +} + +/* just do the OUTPUT stage */ +int +Skein_512_Output(Skein_512_Ctxt_t *ctx, uint8_t *hashVal) +{ + size_t i, n, byteCnt; + uint64_t X[SKEIN_512_STATE_WORDS]; + + /* catch uninitialized context */ + Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL); + + /* now output the result */ + /* total number of output bytes */ + byteCnt = (ctx->h.hashBitLen + 7) >> 3; + + /* run Threefish in "counter mode" to generate output */ + /* zero out b[], so it can hold the counter */ + bzero(ctx->b, sizeof (ctx->b)); + /* keep a local copy of counter mode "key" */ + bcopy(ctx->X, X, sizeof (X)); + for (i = 0; i * SKEIN_512_BLOCK_BYTES < byteCnt; i++) { + /* build the counter block */ + uint64_t tmp = Skein_Swap64((uint64_t)i); + bcopy(&tmp, ctx->b, sizeof (tmp)); + Skein_Start_New_Type(ctx, OUT_FINAL); + /* run "counter mode" */ + Skein_512_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t)); + /* number of output bytes left to go */ + n = byteCnt - i * SKEIN_512_BLOCK_BYTES; + if (n >= SKEIN_512_BLOCK_BYTES) + n = SKEIN_512_BLOCK_BYTES; + Skein_Put64_LSB_First(hashVal + i * SKEIN_512_BLOCK_BYTES, + ctx->X, n); /* "output" the ctr mode bytes */ + Skein_Show_Final(256, &ctx->h, n, + hashVal + i * SKEIN_512_BLOCK_BYTES); + /* restore the counter mode key for next time */ + bcopy(X, ctx->X, sizeof (X)); + } + return (SKEIN_SUCCESS); +} + +/* just do the OUTPUT stage */ +int +Skein1024_Output(Skein1024_Ctxt_t *ctx, uint8_t *hashVal) +{ + size_t i, n, byteCnt; + uint64_t X[SKEIN1024_STATE_WORDS]; + + /* catch uninitialized context */ + Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL); + + /* now output the result */ + /* total number of output bytes */ + byteCnt = (ctx->h.hashBitLen + 7) >> 3; + + /* run Threefish in "counter mode" to generate output */ + /* zero out b[], so it can hold the counter */ + bzero(ctx->b, sizeof (ctx->b)); + /* keep a local copy of counter mode "key" */ + bcopy(ctx->X, X, sizeof (X)); + for (i = 0; i * SKEIN1024_BLOCK_BYTES < byteCnt; i++) { + /* build the counter block */ + uint64_t tmp = Skein_Swap64((uint64_t)i); + bcopy(&tmp, ctx->b, sizeof (tmp)); + Skein_Start_New_Type(ctx, OUT_FINAL); + /* run "counter mode" */ + Skein1024_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t)); + /* number of output bytes left to go */ + n = byteCnt - i * SKEIN1024_BLOCK_BYTES; + if (n >= SKEIN1024_BLOCK_BYTES) + n = SKEIN1024_BLOCK_BYTES; + Skein_Put64_LSB_First(hashVal + i * SKEIN1024_BLOCK_BYTES, + ctx->X, n); /* "output" the ctr mode bytes */ + Skein_Show_Final(256, &ctx->h, n, + hashVal + i * SKEIN1024_BLOCK_BYTES); + /* restore the counter mode key for next time */ + bcopy(X, ctx->X, sizeof (X)); + } + return (SKEIN_SUCCESS); +} +#endif diff --git a/usr/src/common/crypto/skein/skein_block.c b/usr/src/common/crypto/skein/skein_block.c new file mode 100644 index 0000000000..2dead09b7b --- /dev/null +++ b/usr/src/common/crypto/skein/skein_block.c @@ -0,0 +1,767 @@ +/* + * Implementation of the Skein block functions. + * Source code author: Doug Whiting, 2008. + * This algorithm and source code is released to the public domain. + * Compile-time switches: + * SKEIN_USE_ASM -- set bits (256/512/1024) to select which + * versions use ASM code for block processing + * [default: use C for all block sizes] + */ +/* Copyright 2013 Doug Whiting. This code is released to the public domain. */ + +#include <sys/skein.h> +#include "skein_impl.h" + +#ifndef SKEIN_USE_ASM +#define SKEIN_USE_ASM (0) /* default is all C code (no ASM) */ +#endif + +#ifndef SKEIN_LOOP +#define SKEIN_LOOP 001 /* default: unroll 256 and 512, but not 1024 */ +#endif + +/* some useful definitions for code here */ +#define BLK_BITS (WCNT*64) +#define KW_TWK_BASE (0) +#define KW_KEY_BASE (3) +#define ks (kw + KW_KEY_BASE) +#define ts (kw + KW_TWK_BASE) + +/* no debugging in Illumos version */ +#define DebugSaveTweak(ctx) + +/* Skein_256 */ +#if !(SKEIN_USE_ASM & 256) +void +Skein_256_Process_Block(Skein_256_Ctxt_t *ctx, const uint8_t *blkPtr, + size_t blkCnt, size_t byteCntAdd) +{ /* do it in C */ + enum { + WCNT = SKEIN_256_STATE_WORDS + }; +#undef RCNT +#define RCNT (SKEIN_256_ROUNDS_TOTAL / 8) + +#ifdef SKEIN_LOOP /* configure how much to unroll the loop */ +#define SKEIN_UNROLL_256 (((SKEIN_LOOP) / 100) % 10) +#else +#define SKEIN_UNROLL_256 (0) +#endif + +#if SKEIN_UNROLL_256 +#if (RCNT % SKEIN_UNROLL_256) +#error "Invalid SKEIN_UNROLL_256" /* sanity check on unroll count */ +#endif + size_t r; + /* key schedule words : chaining vars + tweak + "rotation" */ + uint64_t kw[WCNT + 4 + RCNT * 2]; +#else + uint64_t kw[WCNT + 4]; /* key schedule words : chaining vars + tweak */ +#endif + /* local copy of context vars, for speed */ + uint64_t X0, X1, X2, X3; + uint64_t w[WCNT]; /* local copy of input block */ +#ifdef SKEIN_DEBUG + /* use for debugging (help compiler put Xn in registers) */ + const uint64_t *Xptr[4]; + Xptr[0] = &X0; + Xptr[1] = &X1; + Xptr[2] = &X2; + Xptr[3] = &X3; +#endif + Skein_assert(blkCnt != 0); /* never call with blkCnt == 0! */ + ts[0] = ctx->h.T[0]; + ts[1] = ctx->h.T[1]; + do { + /* + * this implementation only supports 2**64 input bytes + * (no carry out here) + */ + ts[0] += byteCntAdd; /* update processed length */ + + /* precompute the key schedule for this block */ + ks[0] = ctx->X[0]; + ks[1] = ctx->X[1]; + ks[2] = ctx->X[2]; + ks[3] = ctx->X[3]; + ks[4] = ks[0] ^ ks[1] ^ ks[2] ^ ks[3] ^ SKEIN_KS_PARITY; + + ts[2] = ts[0] ^ ts[1]; + + /* get input block in little-endian format */ + Skein_Get64_LSB_First(w, blkPtr, WCNT); + DebugSaveTweak(ctx); + Skein_Show_Block(BLK_BITS, &ctx->h, ctx->X, blkPtr, w, ks, ts); + + X0 = w[0] + ks[0]; /* do the first full key injection */ + X1 = w[1] + ks[1] + ts[0]; + X2 = w[2] + ks[2] + ts[1]; + X3 = w[3] + ks[3]; + + Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INITIAL, + Xptr); /* show starting state values */ + + blkPtr += SKEIN_256_BLOCK_BYTES; + + /* run the rounds */ + +#define Round256(p0, p1, p2, p3, ROT, rNum) \ + X##p0 += X##p1; X##p1 = RotL_64(X##p1, ROT##_0); X##p1 ^= X##p0; \ + X##p2 += X##p3; X##p3 = RotL_64(X##p3, ROT##_1); X##p3 ^= X##p2; \ + +#if SKEIN_UNROLL_256 == 0 +#define R256(p0, p1, p2, p3, ROT, rNum) /* fully unrolled */ \ + Round256(p0, p1, p2, p3, ROT, rNum) \ + Skein_Show_R_Ptr(BLK_BITS, &ctx->h, rNum, Xptr); + +#define I256(R) \ + X0 += ks[((R) + 1) % 5]; /* inject the key schedule value */ \ + X1 += ks[((R) + 2) % 5] + ts[((R) + 1) % 3]; \ + X2 += ks[((R) + 3) % 5] + ts[((R) + 2) % 3]; \ + X3 += ks[((R) + 4) % 5] + (R) + 1; \ + Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, Xptr); +#else /* looping version */ +#define R256(p0, p1, p2, p3, ROT, rNum) \ + Round256(p0, p1, p2, p3, ROT, rNum) \ + Skein_Show_R_Ptr(BLK_BITS, &ctx->h, 4 * (r - 1) + rNum, Xptr); + +#define I256(R) \ + X0 += ks[r + (R) + 0]; /* inject the key schedule value */ \ + X1 += ks[r + (R) + 1] + ts[r + (R) + 0]; \ + X2 += ks[r + (R) + 2] + ts[r + (R) + 1]; \ + X3 += ks[r + (R) + 3] + r + (R); \ + ks[r + (R) + 4] = ks[r + (R) - 1]; /* rotate key schedule */ \ + ts[r + (R) + 2] = ts[r + (R) - 1]; \ + Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, Xptr); + + /* loop thru it */ + for (r = 1; r < 2 * RCNT; r += 2 * SKEIN_UNROLL_256) +#endif + { +#define R256_8_rounds(R) \ + R256(0, 1, 2, 3, R_256_0, 8 * (R) + 1); \ + R256(0, 3, 2, 1, R_256_1, 8 * (R) + 2); \ + R256(0, 1, 2, 3, R_256_2, 8 * (R) + 3); \ + R256(0, 3, 2, 1, R_256_3, 8 * (R) + 4); \ + I256(2 * (R)); \ + R256(0, 1, 2, 3, R_256_4, 8 * (R) + 5); \ + R256(0, 3, 2, 1, R_256_5, 8 * (R) + 6); \ + R256(0, 1, 2, 3, R_256_6, 8 * (R) + 7); \ + R256(0, 3, 2, 1, R_256_7, 8 * (R) + 8); \ + I256(2 * (R) + 1); + + R256_8_rounds(0); + +#define R256_Unroll_R(NN) \ + ((SKEIN_UNROLL_256 == 0 && SKEIN_256_ROUNDS_TOTAL / 8 > (NN)) || \ + (SKEIN_UNROLL_256 > (NN))) + +#if R256_Unroll_R(1) + R256_8_rounds(1); +#endif +#if R256_Unroll_R(2) + R256_8_rounds(2); +#endif +#if R256_Unroll_R(3) + R256_8_rounds(3); +#endif +#if R256_Unroll_R(4) + R256_8_rounds(4); +#endif +#if R256_Unroll_R(5) + R256_8_rounds(5); +#endif +#if R256_Unroll_R(6) + R256_8_rounds(6); +#endif +#if R256_Unroll_R(7) + R256_8_rounds(7); +#endif +#if R256_Unroll_R(8) + R256_8_rounds(8); +#endif +#if R256_Unroll_R(9) + R256_8_rounds(9); +#endif +#if R256_Unroll_R(10) + R256_8_rounds(10); +#endif +#if R256_Unroll_R(11) + R256_8_rounds(11); +#endif +#if R256_Unroll_R(12) + R256_8_rounds(12); +#endif +#if R256_Unroll_R(13) + R256_8_rounds(13); +#endif +#if R256_Unroll_R(14) + R256_8_rounds(14); +#endif +#if (SKEIN_UNROLL_256 > 14) +#error "need more unrolling in Skein_256_Process_Block" +#endif + } + /* + * do the final "feedforward" xor, update context chaining vars + */ + ctx->X[0] = X0 ^ w[0]; + ctx->X[1] = X1 ^ w[1]; + ctx->X[2] = X2 ^ w[2]; + ctx->X[3] = X3 ^ w[3]; + + Skein_Show_Round(BLK_BITS, &ctx->h, SKEIN_RND_FEED_FWD, ctx->X); + + ts[1] &= ~SKEIN_T1_FLAG_FIRST; + } + while (--blkCnt); + ctx->h.T[0] = ts[0]; + ctx->h.T[1] = ts[1]; +} + +#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF) +size_t +Skein_256_Process_Block_CodeSize(void) +{ + return ((uint8_t *)Skein_256_Process_Block_CodeSize) - + ((uint8_t *)Skein_256_Process_Block); +} + +uint_t +Skein_256_Unroll_Cnt(void) +{ + return (SKEIN_UNROLL_256); +} +#endif +#endif + +/* Skein_512 */ +#if !(SKEIN_USE_ASM & 512) +void +Skein_512_Process_Block(Skein_512_Ctxt_t *ctx, const uint8_t *blkPtr, + size_t blkCnt, size_t byteCntAdd) +{ /* do it in C */ + enum { + WCNT = SKEIN_512_STATE_WORDS + }; +#undef RCNT +#define RCNT (SKEIN_512_ROUNDS_TOTAL / 8) + +#ifdef SKEIN_LOOP /* configure how much to unroll the loop */ +#define SKEIN_UNROLL_512 (((SKEIN_LOOP) / 10) % 10) +#else +#define SKEIN_UNROLL_512 (0) +#endif + +#if SKEIN_UNROLL_512 +#if (RCNT % SKEIN_UNROLL_512) +#error "Invalid SKEIN_UNROLL_512" /* sanity check on unroll count */ +#endif + size_t r; + /* key schedule words : chaining vars + tweak + "rotation" */ + uint64_t kw[WCNT + 4 + RCNT * 2]; +#else + uint64_t kw[WCNT + 4]; /* key schedule words : chaining vars + tweak */ +#endif + /* local copy of vars, for speed */ + uint64_t X0, X1, X2, X3, X4, X5, X6, X7; + uint64_t w[WCNT]; /* local copy of input block */ +#ifdef SKEIN_DEBUG + /* use for debugging (help compiler put Xn in registers) */ + const uint64_t *Xptr[8]; + Xptr[0] = &X0; + Xptr[1] = &X1; + Xptr[2] = &X2; + Xptr[3] = &X3; + Xptr[4] = &X4; + Xptr[5] = &X5; + Xptr[6] = &X6; + Xptr[7] = &X7; +#endif + + Skein_assert(blkCnt != 0); /* never call with blkCnt == 0! */ + ts[0] = ctx->h.T[0]; + ts[1] = ctx->h.T[1]; + do { + /* + * this implementation only supports 2**64 input bytes + * (no carry out here) + */ + ts[0] += byteCntAdd; /* update processed length */ + + /* precompute the key schedule for this block */ + ks[0] = ctx->X[0]; + ks[1] = ctx->X[1]; + ks[2] = ctx->X[2]; + ks[3] = ctx->X[3]; + ks[4] = ctx->X[4]; + ks[5] = ctx->X[5]; + ks[6] = ctx->X[6]; + ks[7] = ctx->X[7]; + ks[8] = ks[0] ^ ks[1] ^ ks[2] ^ ks[3] ^ + ks[4] ^ ks[5] ^ ks[6] ^ ks[7] ^ SKEIN_KS_PARITY; + + ts[2] = ts[0] ^ ts[1]; + + /* get input block in little-endian format */ + Skein_Get64_LSB_First(w, blkPtr, WCNT); + DebugSaveTweak(ctx); + Skein_Show_Block(BLK_BITS, &ctx->h, ctx->X, blkPtr, w, ks, ts); + + X0 = w[0] + ks[0]; /* do the first full key injection */ + X1 = w[1] + ks[1]; + X2 = w[2] + ks[2]; + X3 = w[3] + ks[3]; + X4 = w[4] + ks[4]; + X5 = w[5] + ks[5] + ts[0]; + X6 = w[6] + ks[6] + ts[1]; + X7 = w[7] + ks[7]; + + blkPtr += SKEIN_512_BLOCK_BYTES; + + Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INITIAL, + Xptr); + /* run the rounds */ +#define Round512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, rNum) \ + X##p0 += X##p1; X##p1 = RotL_64(X##p1, ROT##_0); X##p1 ^= X##p0;\ + X##p2 += X##p3; X##p3 = RotL_64(X##p3, ROT##_1); X##p3 ^= X##p2;\ + X##p4 += X##p5; X##p5 = RotL_64(X##p5, ROT##_2); X##p5 ^= X##p4;\ + X##p6 += X##p7; X##p7 = RotL_64(X##p7, ROT##_3); X##p7 ^= X##p6; + +#if SKEIN_UNROLL_512 == 0 +#define R512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, rNum) /* unrolled */ \ + Round512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, rNum) \ + Skein_Show_R_Ptr(BLK_BITS, &ctx->h, rNum, Xptr); + +#define I512(R) \ + X0 += ks[((R) + 1) % 9]; /* inject the key schedule value */\ + X1 += ks[((R) + 2) % 9]; \ + X2 += ks[((R) + 3) % 9]; \ + X3 += ks[((R) + 4) % 9]; \ + X4 += ks[((R) + 5) % 9]; \ + X5 += ks[((R) + 6) % 9] + ts[((R) + 1) % 3]; \ + X6 += ks[((R) + 7) % 9] + ts[((R) + 2) % 3]; \ + X7 += ks[((R) + 8) % 9] + (R) + 1; \ + Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, Xptr); +#else /* looping version */ +#define R512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, rNum) \ + Round512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, rNum) \ + Skein_Show_R_Ptr(BLK_BITS, &ctx->h, 4 * (r - 1) + rNum, Xptr); + +#define I512(R) \ + X0 += ks[r + (R) + 0]; /* inject the key schedule value */ \ + X1 += ks[r + (R) + 1]; \ + X2 += ks[r + (R) + 2]; \ + X3 += ks[r + (R) + 3]; \ + X4 += ks[r + (R) + 4]; \ + X5 += ks[r + (R) + 5] + ts[r + (R) + 0]; \ + X6 += ks[r + (R) + 6] + ts[r + (R) + 1]; \ + X7 += ks[r + (R) + 7] + r + (R); \ + ks[r + (R)+8] = ks[r + (R) - 1]; /* rotate key schedule */\ + ts[r + (R)+2] = ts[r + (R) - 1]; \ + Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, Xptr); + + /* loop thru it */ + for (r = 1; r < 2 * RCNT; r += 2 * SKEIN_UNROLL_512) +#endif /* end of looped code definitions */ + { +#define R512_8_rounds(R) /* do 8 full rounds */ \ + R512(0, 1, 2, 3, 4, 5, 6, 7, R_512_0, 8 * (R) + 1); \ + R512(2, 1, 4, 7, 6, 5, 0, 3, R_512_1, 8 * (R) + 2); \ + R512(4, 1, 6, 3, 0, 5, 2, 7, R_512_2, 8 * (R) + 3); \ + R512(6, 1, 0, 7, 2, 5, 4, 3, R_512_3, 8 * (R) + 4); \ + I512(2 * (R)); \ + R512(0, 1, 2, 3, 4, 5, 6, 7, R_512_4, 8 * (R) + 5); \ + R512(2, 1, 4, 7, 6, 5, 0, 3, R_512_5, 8 * (R) + 6); \ + R512(4, 1, 6, 3, 0, 5, 2, 7, R_512_6, 8 * (R) + 7); \ + R512(6, 1, 0, 7, 2, 5, 4, 3, R_512_7, 8 * (R) + 8); \ + I512(2*(R) + 1); /* and key injection */ + + R512_8_rounds(0); + +#define R512_Unroll_R(NN) \ + ((SKEIN_UNROLL_512 == 0 && SKEIN_512_ROUNDS_TOTAL / 8 > (NN)) || \ + (SKEIN_UNROLL_512 > (NN))) + +#if R512_Unroll_R(1) + R512_8_rounds(1); +#endif +#if R512_Unroll_R(2) + R512_8_rounds(2); +#endif +#if R512_Unroll_R(3) + R512_8_rounds(3); +#endif +#if R512_Unroll_R(4) + R512_8_rounds(4); +#endif +#if R512_Unroll_R(5) + R512_8_rounds(5); +#endif +#if R512_Unroll_R(6) + R512_8_rounds(6); +#endif +#if R512_Unroll_R(7) + R512_8_rounds(7); +#endif +#if R512_Unroll_R(8) + R512_8_rounds(8); +#endif +#if R512_Unroll_R(9) + R512_8_rounds(9); +#endif +#if R512_Unroll_R(10) + R512_8_rounds(10); +#endif +#if R512_Unroll_R(11) + R512_8_rounds(11); +#endif +#if R512_Unroll_R(12) + R512_8_rounds(12); +#endif +#if R512_Unroll_R(13) + R512_8_rounds(13); +#endif +#if R512_Unroll_R(14) + R512_8_rounds(14); +#endif +#if (SKEIN_UNROLL_512 > 14) +#error "need more unrolling in Skein_512_Process_Block" +#endif + } + + /* + * do the final "feedforward" xor, update context chaining vars + */ + ctx->X[0] = X0 ^ w[0]; + ctx->X[1] = X1 ^ w[1]; + ctx->X[2] = X2 ^ w[2]; + ctx->X[3] = X3 ^ w[3]; + ctx->X[4] = X4 ^ w[4]; + ctx->X[5] = X5 ^ w[5]; + ctx->X[6] = X6 ^ w[6]; + ctx->X[7] = X7 ^ w[7]; + Skein_Show_Round(BLK_BITS, &ctx->h, SKEIN_RND_FEED_FWD, ctx->X); + + ts[1] &= ~SKEIN_T1_FLAG_FIRST; + } + while (--blkCnt); + ctx->h.T[0] = ts[0]; + ctx->h.T[1] = ts[1]; +} + +#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF) +size_t +Skein_512_Process_Block_CodeSize(void) +{ + return ((uint8_t *)Skein_512_Process_Block_CodeSize) - + ((uint8_t *)Skein_512_Process_Block); +} + +uint_t +Skein_512_Unroll_Cnt(void) +{ + return (SKEIN_UNROLL_512); +} +#endif +#endif + +/* Skein1024 */ +#if !(SKEIN_USE_ASM & 1024) +void +Skein1024_Process_Block(Skein1024_Ctxt_t *ctx, const uint8_t *blkPtr, + size_t blkCnt, size_t byteCntAdd) +{ + /* do it in C, always looping (unrolled is bigger AND slower!) */ + enum { + WCNT = SKEIN1024_STATE_WORDS + }; +#undef RCNT +#define RCNT (SKEIN1024_ROUNDS_TOTAL/8) + +#ifdef SKEIN_LOOP /* configure how much to unroll the loop */ +#define SKEIN_UNROLL_1024 ((SKEIN_LOOP)%10) +#else +#define SKEIN_UNROLL_1024 (0) +#endif + +#if (SKEIN_UNROLL_1024 != 0) +#if (RCNT % SKEIN_UNROLL_1024) +#error "Invalid SKEIN_UNROLL_1024" /* sanity check on unroll count */ +#endif + size_t r; + /* key schedule words : chaining vars + tweak + "rotation" */ + uint64_t kw[WCNT + 4 + RCNT * 2]; +#else + uint64_t kw[WCNT + 4]; /* key schedule words : chaining vars + tweak */ +#endif + + /* local copy of vars, for speed */ + uint64_t X00, X01, X02, X03, X04, X05, X06, X07, X08, X09, X10, X11, + X12, X13, X14, X15; + uint64_t w[WCNT]; /* local copy of input block */ +#ifdef SKEIN_DEBUG + /* use for debugging (help compiler put Xn in registers) */ + const uint64_t *Xptr[16]; + Xptr[0] = &X00; + Xptr[1] = &X01; + Xptr[2] = &X02; + Xptr[3] = &X03; + Xptr[4] = &X04; + Xptr[5] = &X05; + Xptr[6] = &X06; + Xptr[7] = &X07; + Xptr[8] = &X08; + Xptr[9] = &X09; + Xptr[10] = &X10; + Xptr[11] = &X11; + Xptr[12] = &X12; + Xptr[13] = &X13; + Xptr[14] = &X14; + Xptr[15] = &X15; +#endif + + Skein_assert(blkCnt != 0); /* never call with blkCnt == 0! */ + ts[0] = ctx->h.T[0]; + ts[1] = ctx->h.T[1]; + do { + /* + * this implementation only supports 2**64 input bytes + * (no carry out here) + */ + ts[0] += byteCntAdd; /* update processed length */ + + /* precompute the key schedule for this block */ + ks[0] = ctx->X[0]; + ks[1] = ctx->X[1]; + ks[2] = ctx->X[2]; + ks[3] = ctx->X[3]; + ks[4] = ctx->X[4]; + ks[5] = ctx->X[5]; + ks[6] = ctx->X[6]; + ks[7] = ctx->X[7]; + ks[8] = ctx->X[8]; + ks[9] = ctx->X[9]; + ks[10] = ctx->X[10]; + ks[11] = ctx->X[11]; + ks[12] = ctx->X[12]; + ks[13] = ctx->X[13]; + ks[14] = ctx->X[14]; + ks[15] = ctx->X[15]; + ks[16] = ks[0] ^ ks[1] ^ ks[2] ^ ks[3] ^ + ks[4] ^ ks[5] ^ ks[6] ^ ks[7] ^ + ks[8] ^ ks[9] ^ ks[10] ^ ks[11] ^ + ks[12] ^ ks[13] ^ ks[14] ^ ks[15] ^ SKEIN_KS_PARITY; + + ts[2] = ts[0] ^ ts[1]; + + /* get input block in little-endian format */ + Skein_Get64_LSB_First(w, blkPtr, WCNT); + DebugSaveTweak(ctx); + Skein_Show_Block(BLK_BITS, &ctx->h, ctx->X, blkPtr, w, ks, ts); + + X00 = w[0] + ks[0]; /* do the first full key injection */ + X01 = w[1] + ks[1]; + X02 = w[2] + ks[2]; + X03 = w[3] + ks[3]; + X04 = w[4] + ks[4]; + X05 = w[5] + ks[5]; + X06 = w[6] + ks[6]; + X07 = w[7] + ks[7]; + X08 = w[8] + ks[8]; + X09 = w[9] + ks[9]; + X10 = w[10] + ks[10]; + X11 = w[11] + ks[11]; + X12 = w[12] + ks[12]; + X13 = w[13] + ks[13] + ts[0]; + X14 = w[14] + ks[14] + ts[1]; + X15 = w[15] + ks[15]; + + Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INITIAL, + Xptr); + +#define Round1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, \ + pD, pE, pF, ROT, rNum) \ + X##p0 += X##p1; X##p1 = RotL_64(X##p1, ROT##_0); X##p1 ^= X##p0;\ + X##p2 += X##p3; X##p3 = RotL_64(X##p3, ROT##_1); X##p3 ^= X##p2;\ + X##p4 += X##p5; X##p5 = RotL_64(X##p5, ROT##_2); X##p5 ^= X##p4;\ + X##p6 += X##p7; X##p7 = RotL_64(X##p7, ROT##_3); X##p7 ^= X##p6;\ + X##p8 += X##p9; X##p9 = RotL_64(X##p9, ROT##_4); X##p9 ^= X##p8;\ + X##pA += X##pB; X##pB = RotL_64(X##pB, ROT##_5); X##pB ^= X##pA;\ + X##pC += X##pD; X##pD = RotL_64(X##pD, ROT##_6); X##pD ^= X##pC;\ + X##pE += X##pF; X##pF = RotL_64(X##pF, ROT##_7); X##pF ^= X##pE; + +#if SKEIN_UNROLL_1024 == 0 +#define R1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, \ + pE, pF, ROT, rn) \ + Round1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, \ + pD, pE, pF, ROT, rn) \ + Skein_Show_R_Ptr(BLK_BITS, &ctx->h, rn, Xptr); + +#define I1024(R) \ + X00 += ks[((R) + 1) % 17]; /* inject the key schedule value */\ + X01 += ks[((R) + 2) % 17]; \ + X02 += ks[((R) + 3) % 17]; \ + X03 += ks[((R) + 4) % 17]; \ + X04 += ks[((R) + 5) % 17]; \ + X05 += ks[((R) + 6) % 17]; \ + X06 += ks[((R) + 7) % 17]; \ + X07 += ks[((R) + 8) % 17]; \ + X08 += ks[((R) + 9) % 17]; \ + X09 += ks[((R) + 10) % 17]; \ + X10 += ks[((R) + 11) % 17]; \ + X11 += ks[((R) + 12) % 17]; \ + X12 += ks[((R) + 13) % 17]; \ + X13 += ks[((R) + 14) % 17] + ts[((R) + 1) % 3]; \ + X14 += ks[((R) + 15) % 17] + ts[((R) + 2) % 3]; \ + X15 += ks[((R) + 16) % 17] + (R) +1; \ + Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, Xptr); +#else /* looping version */ +#define R1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, \ + pE, pF, ROT, rn) \ + Round1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, \ + pD, pE, pF, ROT, rn) \ + Skein_Show_R_Ptr(BLK_BITS, &ctx->h, 4 * (r - 1) + rn, Xptr); + +#define I1024(R) \ + X00 += ks[r + (R) + 0]; /* inject the key schedule value */ \ + X01 += ks[r + (R) + 1]; \ + X02 += ks[r + (R) + 2]; \ + X03 += ks[r + (R) + 3]; \ + X04 += ks[r + (R) + 4]; \ + X05 += ks[r + (R) + 5]; \ + X06 += ks[r + (R) + 6]; \ + X07 += ks[r + (R) + 7]; \ + X08 += ks[r + (R) + 8]; \ + X09 += ks[r + (R) + 9]; \ + X10 += ks[r + (R) + 10]; \ + X11 += ks[r + (R) + 11]; \ + X12 += ks[r + (R) + 12]; \ + X13 += ks[r + (R) + 13] + ts[r + (R) + 0]; \ + X14 += ks[r + (R) + 14] + ts[r + (R) + 1]; \ + X15 += ks[r + (R) + 15] + r + (R); \ + ks[r + (R) + 16] = ks[r + (R) - 1]; /* rotate key schedule */\ + ts[r + (R) + 2] = ts[r + (R) - 1]; \ + Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, Xptr); + + /* loop thru it */ + for (r = 1; r <= 2 * RCNT; r += 2 * SKEIN_UNROLL_1024) +#endif + { +#define R1024_8_rounds(R) /* do 8 full rounds */ \ + R1024(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, \ + 14, 15, R1024_0, 8 * (R) + 1); \ + R1024(00, 09, 02, 13, 06, 11, 04, 15, 10, 07, 12, 03, 14, 05, \ + 08, 01, R1024_1, 8 * (R) + 2); \ + R1024(00, 07, 02, 05, 04, 03, 06, 01, 12, 15, 14, 13, 08, 11, \ + 10, 09, R1024_2, 8 * (R) + 3); \ + R1024(00, 15, 02, 11, 06, 13, 04, 09, 14, 01, 08, 05, 10, 03, \ + 12, 07, R1024_3, 8 * (R) + 4); \ + I1024(2 * (R)); \ + R1024(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, \ + 14, 15, R1024_4, 8 * (R) + 5); \ + R1024(00, 09, 02, 13, 06, 11, 04, 15, 10, 07, 12, 03, 14, 05, \ + 08, 01, R1024_5, 8 * (R) + 6); \ + R1024(00, 07, 02, 05, 04, 03, 06, 01, 12, 15, 14, 13, 08, 11, \ + 10, 09, R1024_6, 8 * (R) + 7); \ + R1024(00, 15, 02, 11, 06, 13, 04, 09, 14, 01, 08, 05, 10, 03, \ + 12, 07, R1024_7, 8 * (R) + 8); \ + I1024(2 * (R) + 1); + + R1024_8_rounds(0); + +#define R1024_Unroll_R(NN) \ + ((SKEIN_UNROLL_1024 == 0 && SKEIN1024_ROUNDS_TOTAL/8 > (NN)) || \ + (SKEIN_UNROLL_1024 > (NN))) + +#if R1024_Unroll_R(1) + R1024_8_rounds(1); +#endif +#if R1024_Unroll_R(2) + R1024_8_rounds(2); +#endif +#if R1024_Unroll_R(3) + R1024_8_rounds(3); +#endif +#if R1024_Unroll_R(4) + R1024_8_rounds(4); +#endif +#if R1024_Unroll_R(5) + R1024_8_rounds(5); +#endif +#if R1024_Unroll_R(6) + R1024_8_rounds(6); +#endif +#if R1024_Unroll_R(7) + R1024_8_rounds(7); +#endif +#if R1024_Unroll_R(8) + R1024_8_rounds(8); +#endif +#if R1024_Unroll_R(9) + R1024_8_rounds(9); +#endif +#if R1024_Unroll_R(10) + R1024_8_rounds(10); +#endif +#if R1024_Unroll_R(11) + R1024_8_rounds(11); +#endif +#if R1024_Unroll_R(12) + R1024_8_rounds(12); +#endif +#if R1024_Unroll_R(13) + R1024_8_rounds(13); +#endif +#if R1024_Unroll_R(14) + R1024_8_rounds(14); +#endif +#if (SKEIN_UNROLL_1024 > 14) +#error "need more unrolling in Skein_1024_Process_Block" +#endif + } + /* + * do the final "feedforward" xor, update context chaining vars + */ + + ctx->X[0] = X00 ^ w[0]; + ctx->X[1] = X01 ^ w[1]; + ctx->X[2] = X02 ^ w[2]; + ctx->X[3] = X03 ^ w[3]; + ctx->X[4] = X04 ^ w[4]; + ctx->X[5] = X05 ^ w[5]; + ctx->X[6] = X06 ^ w[6]; + ctx->X[7] = X07 ^ w[7]; + ctx->X[8] = X08 ^ w[8]; + ctx->X[9] = X09 ^ w[9]; + ctx->X[10] = X10 ^ w[10]; + ctx->X[11] = X11 ^ w[11]; + ctx->X[12] = X12 ^ w[12]; + ctx->X[13] = X13 ^ w[13]; + ctx->X[14] = X14 ^ w[14]; + ctx->X[15] = X15 ^ w[15]; + + Skein_Show_Round(BLK_BITS, &ctx->h, SKEIN_RND_FEED_FWD, ctx->X); + + ts[1] &= ~SKEIN_T1_FLAG_FIRST; + blkPtr += SKEIN1024_BLOCK_BYTES; + } while (--blkCnt); + ctx->h.T[0] = ts[0]; + ctx->h.T[1] = ts[1]; +} + +#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF) +size_t +Skein1024_Process_Block_CodeSize(void) +{ + return ((uint8_t *)Skein1024_Process_Block_CodeSize) - + ((uint8_t *)Skein1024_Process_Block); +} + +uint_t +Skein1024_Unroll_Cnt(void) +{ + return (SKEIN_UNROLL_1024); +} +#endif +#endif diff --git a/usr/src/common/crypto/skein/skein_impl.h b/usr/src/common/crypto/skein/skein_impl.h new file mode 100644 index 0000000000..e83a06971b --- /dev/null +++ b/usr/src/common/crypto/skein/skein_impl.h @@ -0,0 +1,289 @@ +/* + * Internal definitions for Skein hashing. + * Source code author: Doug Whiting, 2008. + * This algorithm and source code is released to the public domain. + * + * The following compile-time switches may be defined to control some + * tradeoffs between speed, code size, error checking, and security. + * + * The "default" note explains what happens when the switch is not defined. + * + * SKEIN_DEBUG -- make callouts from inside Skein code + * to examine/display intermediate values. + * [default: no callouts (no overhead)] + * + * SKEIN_ERR_CHECK -- how error checking is handled inside Skein + * code. If not defined, most error checking + * is disabled (for performance). Otherwise, + * the switch value is interpreted as: + * 0: use assert() to flag errors + * 1: return SKEIN_FAIL to flag errors + */ +/* Copyright 2013 Doug Whiting. This code is released to the public domain. */ + +#ifndef _SKEIN_IMPL_H_ +#define _SKEIN_IMPL_H_ + +#include <sys/skein.h> +#include "skein_impl.h" +#include "skein_port.h" + +/* determine where we can get bcopy/bzero declarations */ +#ifdef _KERNEL +#include <sys/systm.h> +#else +#include <strings.h> +#endif + +/* + * "Internal" Skein definitions + * -- not needed for sequential hashing API, but will be + * helpful for other uses of Skein (e.g., tree hash mode). + * -- included here so that they can be shared between + * reference and optimized code. + */ + +/* tweak word T[1]: bit field starting positions */ +/* offset 64 because it's the second word */ +#define SKEIN_T1_BIT(BIT) ((BIT) - 64) + +/* bits 112..118: level in hash tree */ +#define SKEIN_T1_POS_TREE_LVL SKEIN_T1_BIT(112) +/* bit 119: partial final input byte */ +#define SKEIN_T1_POS_BIT_PAD SKEIN_T1_BIT(119) +/* bits 120..125: type field */ +#define SKEIN_T1_POS_BLK_TYPE SKEIN_T1_BIT(120) +/* bits 126: first block flag */ +#define SKEIN_T1_POS_FIRST SKEIN_T1_BIT(126) +/* bit 127: final block flag */ +#define SKEIN_T1_POS_FINAL SKEIN_T1_BIT(127) + +/* tweak word T[1]: flag bit definition(s) */ +#define SKEIN_T1_FLAG_FIRST (((uint64_t)1) << SKEIN_T1_POS_FIRST) +#define SKEIN_T1_FLAG_FINAL (((uint64_t)1) << SKEIN_T1_POS_FINAL) +#define SKEIN_T1_FLAG_BIT_PAD (((uint64_t)1) << SKEIN_T1_POS_BIT_PAD) + +/* tweak word T[1]: tree level bit field mask */ +#define SKEIN_T1_TREE_LVL_MASK (((uint64_t)0x7F) << SKEIN_T1_POS_TREE_LVL) +#define SKEIN_T1_TREE_LEVEL(n) (((uint64_t)(n)) << SKEIN_T1_POS_TREE_LVL) + +/* tweak word T[1]: block type field */ +#define SKEIN_BLK_TYPE_KEY (0) /* key, for MAC and KDF */ +#define SKEIN_BLK_TYPE_CFG (4) /* configuration block */ +#define SKEIN_BLK_TYPE_PERS (8) /* personalization string */ +#define SKEIN_BLK_TYPE_PK (12) /* public key (for signature hashing) */ +#define SKEIN_BLK_TYPE_KDF (16) /* key identifier for KDF */ +#define SKEIN_BLK_TYPE_NONCE (20) /* nonce for PRNG */ +#define SKEIN_BLK_TYPE_MSG (48) /* message processing */ +#define SKEIN_BLK_TYPE_OUT (63) /* output stage */ +#define SKEIN_BLK_TYPE_MASK (63) /* bit field mask */ + +#define SKEIN_T1_BLK_TYPE(T) \ + (((uint64_t)(SKEIN_BLK_TYPE_##T)) << SKEIN_T1_POS_BLK_TYPE) +/* key, for MAC and KDF */ +#define SKEIN_T1_BLK_TYPE_KEY SKEIN_T1_BLK_TYPE(KEY) +/* configuration block */ +#define SKEIN_T1_BLK_TYPE_CFG SKEIN_T1_BLK_TYPE(CFG) +/* personalization string */ +#define SKEIN_T1_BLK_TYPE_PERS SKEIN_T1_BLK_TYPE(PERS) +/* public key (for digital signature hashing) */ +#define SKEIN_T1_BLK_TYPE_PK SKEIN_T1_BLK_TYPE(PK) +/* key identifier for KDF */ +#define SKEIN_T1_BLK_TYPE_KDF SKEIN_T1_BLK_TYPE(KDF) +/* nonce for PRNG */ +#define SKEIN_T1_BLK_TYPE_NONCE SKEIN_T1_BLK_TYPE(NONCE) +/* message processing */ +#define SKEIN_T1_BLK_TYPE_MSG SKEIN_T1_BLK_TYPE(MSG) +/* output stage */ +#define SKEIN_T1_BLK_TYPE_OUT SKEIN_T1_BLK_TYPE(OUT) +/* field bit mask */ +#define SKEIN_T1_BLK_TYPE_MASK SKEIN_T1_BLK_TYPE(MASK) + +#define SKEIN_T1_BLK_TYPE_CFG_FINAL \ + (SKEIN_T1_BLK_TYPE_CFG | SKEIN_T1_FLAG_FINAL) +#define SKEIN_T1_BLK_TYPE_OUT_FINAL \ + (SKEIN_T1_BLK_TYPE_OUT | SKEIN_T1_FLAG_FINAL) + +#define SKEIN_VERSION (1) + +#ifndef SKEIN_ID_STRING_LE /* allow compile-time personalization */ +#define SKEIN_ID_STRING_LE (0x33414853) /* "SHA3" (little-endian) */ +#endif + +#define SKEIN_MK_64(hi32, lo32) ((lo32) + (((uint64_t)(hi32)) << 32)) +#define SKEIN_SCHEMA_VER SKEIN_MK_64(SKEIN_VERSION, SKEIN_ID_STRING_LE) +#define SKEIN_KS_PARITY SKEIN_MK_64(0x1BD11BDA, 0xA9FC1A22) + +#define SKEIN_CFG_STR_LEN (4*8) + +/* bit field definitions in config block treeInfo word */ +#define SKEIN_CFG_TREE_LEAF_SIZE_POS (0) +#define SKEIN_CFG_TREE_NODE_SIZE_POS (8) +#define SKEIN_CFG_TREE_MAX_LEVEL_POS (16) + +#define SKEIN_CFG_TREE_LEAF_SIZE_MSK \ + (((uint64_t)0xFF) << SKEIN_CFG_TREE_LEAF_SIZE_POS) +#define SKEIN_CFG_TREE_NODE_SIZE_MSK \ + (((uint64_t)0xFF) << SKEIN_CFG_TREE_NODE_SIZE_POS) +#define SKEIN_CFG_TREE_MAX_LEVEL_MSK \ + (((uint64_t)0xFF) << SKEIN_CFG_TREE_MAX_LEVEL_POS) + +#define SKEIN_CFG_TREE_INFO(leaf, node, maxLvl) \ + ((((uint64_t)(leaf)) << SKEIN_CFG_TREE_LEAF_SIZE_POS) | \ + (((uint64_t)(node)) << SKEIN_CFG_TREE_NODE_SIZE_POS) | \ + (((uint64_t)(maxLvl)) << SKEIN_CFG_TREE_MAX_LEVEL_POS)) + +/* use as treeInfo in InitExt() call for sequential processing */ +#define SKEIN_CFG_TREE_INFO_SEQUENTIAL SKEIN_CFG_TREE_INFO(0, 0, 0) + +/* + * Skein macros for getting/setting tweak words, etc. + * These are useful for partial input bytes, hash tree init/update, etc. + */ +#define Skein_Get_Tweak(ctxPtr, TWK_NUM) ((ctxPtr)->h.T[TWK_NUM]) +#define Skein_Set_Tweak(ctxPtr, TWK_NUM, tVal) \ + do { \ + (ctxPtr)->h.T[TWK_NUM] = (tVal); \ + _NOTE(CONSTCOND) \ + } while (0) + +#define Skein_Get_T0(ctxPtr) Skein_Get_Tweak(ctxPtr, 0) +#define Skein_Get_T1(ctxPtr) Skein_Get_Tweak(ctxPtr, 1) +#define Skein_Set_T0(ctxPtr, T0) Skein_Set_Tweak(ctxPtr, 0, T0) +#define Skein_Set_T1(ctxPtr, T1) Skein_Set_Tweak(ctxPtr, 1, T1) + +/* set both tweak words at once */ +#define Skein_Set_T0_T1(ctxPtr, T0, T1) \ + do { \ + Skein_Set_T0(ctxPtr, (T0)); \ + Skein_Set_T1(ctxPtr, (T1)); \ + _NOTE(CONSTCOND) \ + } while (0) + +#define Skein_Set_Type(ctxPtr, BLK_TYPE) \ + Skein_Set_T1(ctxPtr, SKEIN_T1_BLK_TYPE_##BLK_TYPE) + +/* + * set up for starting with a new type: h.T[0]=0; h.T[1] = NEW_TYPE; h.bCnt=0; + */ +#define Skein_Start_New_Type(ctxPtr, BLK_TYPE) \ + do { \ + Skein_Set_T0_T1(ctxPtr, 0, SKEIN_T1_FLAG_FIRST | \ + SKEIN_T1_BLK_TYPE_ ## BLK_TYPE); \ + (ctxPtr)->h.bCnt = 0; \ + _NOTE(CONSTCOND) \ + } while (0) + +#define Skein_Clear_First_Flag(hdr) \ + do { \ + (hdr).T[1] &= ~SKEIN_T1_FLAG_FIRST; \ + _NOTE(CONSTCOND) \ + } while (0) +#define Skein_Set_Bit_Pad_Flag(hdr) \ + do { \ + (hdr).T[1] |= SKEIN_T1_FLAG_BIT_PAD; \ + _NOTE(CONSTCOND) \ + } while (0) + +#define Skein_Set_Tree_Level(hdr, height) \ + do { \ + (hdr).T[1] |= SKEIN_T1_TREE_LEVEL(height); \ + _NOTE(CONSTCOND) \ + } while (0) + +/* + * "Internal" Skein definitions for debugging and error checking + * Note: in Illumos we always disable debugging features. + */ +#define Skein_Show_Block(bits, ctx, X, blkPtr, wPtr, ksEvenPtr, ksOddPtr) +#define Skein_Show_Round(bits, ctx, r, X) +#define Skein_Show_R_Ptr(bits, ctx, r, X_ptr) +#define Skein_Show_Final(bits, ctx, cnt, outPtr) +#define Skein_Show_Key(bits, ctx, key, keyBytes) + +/* run-time checks (e.g., bad params, uninitialized context)? */ +#ifndef SKEIN_ERR_CHECK +/* default: ignore all Asserts, for performance */ +#define Skein_Assert(x, retCode) +#define Skein_assert(x) +#elif defined(SKEIN_ASSERT) +#include <sys/debug.h> +#define Skein_Assert(x, retCode) ASSERT(x) +#define Skein_assert(x) ASSERT(x) +#else +#include <sys/debug.h> +/* caller error */ +#define Skein_Assert(x, retCode) \ + do { \ + if (!(x)) \ + return (retCode); \ + _NOTE(CONSTCOND) \ + } while (0) +/* internal error */ +#define Skein_assert(x) ASSERT(x) +#endif + +/* + * Skein block function constants (shared across Ref and Opt code) + */ +enum { + /* Skein_256 round rotation constants */ + R_256_0_0 = 14, R_256_0_1 = 16, + R_256_1_0 = 52, R_256_1_1 = 57, + R_256_2_0 = 23, R_256_2_1 = 40, + R_256_3_0 = 5, R_256_3_1 = 37, + R_256_4_0 = 25, R_256_4_1 = 33, + R_256_5_0 = 46, R_256_5_1 = 12, + R_256_6_0 = 58, R_256_6_1 = 22, + R_256_7_0 = 32, R_256_7_1 = 32, + + /* Skein_512 round rotation constants */ + R_512_0_0 = 46, R_512_0_1 = 36, R_512_0_2 = 19, R_512_0_3 = 37, + R_512_1_0 = 33, R_512_1_1 = 27, R_512_1_2 = 14, R_512_1_3 = 42, + R_512_2_0 = 17, R_512_2_1 = 49, R_512_2_2 = 36, R_512_2_3 = 39, + R_512_3_0 = 44, R_512_3_1 = 9, R_512_3_2 = 54, R_512_3_3 = 56, + R_512_4_0 = 39, R_512_4_1 = 30, R_512_4_2 = 34, R_512_4_3 = 24, + R_512_5_0 = 13, R_512_5_1 = 50, R_512_5_2 = 10, R_512_5_3 = 17, + R_512_6_0 = 25, R_512_6_1 = 29, R_512_6_2 = 39, R_512_6_3 = 43, + R_512_7_0 = 8, R_512_7_1 = 35, R_512_7_2 = 56, R_512_7_3 = 22, + + /* Skein1024 round rotation constants */ + R1024_0_0 = 24, R1024_0_1 = 13, R1024_0_2 = 8, R1024_0_3 = + 47, R1024_0_4 = 8, R1024_0_5 = 17, R1024_0_6 = 22, R1024_0_7 = 37, + R1024_1_0 = 38, R1024_1_1 = 19, R1024_1_2 = 10, R1024_1_3 = + 55, R1024_1_4 = 49, R1024_1_5 = 18, R1024_1_6 = 23, R1024_1_7 = 52, + R1024_2_0 = 33, R1024_2_1 = 4, R1024_2_2 = 51, R1024_2_3 = + 13, R1024_2_4 = 34, R1024_2_5 = 41, R1024_2_6 = 59, R1024_2_7 = 17, + R1024_3_0 = 5, R1024_3_1 = 20, R1024_3_2 = 48, R1024_3_3 = + 41, R1024_3_4 = 47, R1024_3_5 = 28, R1024_3_6 = 16, R1024_3_7 = 25, + R1024_4_0 = 41, R1024_4_1 = 9, R1024_4_2 = 37, R1024_4_3 = + 31, R1024_4_4 = 12, R1024_4_5 = 47, R1024_4_6 = 44, R1024_4_7 = 30, + R1024_5_0 = 16, R1024_5_1 = 34, R1024_5_2 = 56, R1024_5_3 = + 51, R1024_5_4 = 4, R1024_5_5 = 53, R1024_5_6 = 42, R1024_5_7 = 41, + R1024_6_0 = 31, R1024_6_1 = 44, R1024_6_2 = 47, R1024_6_3 = + 46, R1024_6_4 = 19, R1024_6_5 = 42, R1024_6_6 = 44, R1024_6_7 = 25, + R1024_7_0 = 9, R1024_7_1 = 48, R1024_7_2 = 35, R1024_7_3 = + 52, R1024_7_4 = 23, R1024_7_5 = 31, R1024_7_6 = 37, R1024_7_7 = 20 +}; + +/* number of rounds for the different block sizes */ +#define SKEIN_256_ROUNDS_TOTAL (72) +#define SKEIN_512_ROUNDS_TOTAL (72) +#define SKEIN1024_ROUNDS_TOTAL (80) + + +extern const uint64_t SKEIN_256_IV_128[]; +extern const uint64_t SKEIN_256_IV_160[]; +extern const uint64_t SKEIN_256_IV_224[]; +extern const uint64_t SKEIN_256_IV_256[]; +extern const uint64_t SKEIN_512_IV_128[]; +extern const uint64_t SKEIN_512_IV_160[]; +extern const uint64_t SKEIN_512_IV_224[]; +extern const uint64_t SKEIN_512_IV_256[]; +extern const uint64_t SKEIN_512_IV_384[]; +extern const uint64_t SKEIN_512_IV_512[]; +extern const uint64_t SKEIN1024_IV_384[]; +extern const uint64_t SKEIN1024_IV_512[]; +extern const uint64_t SKEIN1024_IV_1024[]; + +#endif /* _SKEIN_IMPL_H_ */ diff --git a/usr/src/common/crypto/skein/skein_iv.c b/usr/src/common/crypto/skein/skein_iv.c new file mode 100644 index 0000000000..140d38f765 --- /dev/null +++ b/usr/src/common/crypto/skein/skein_iv.c @@ -0,0 +1,185 @@ +/* + * Pre-computed Skein IVs + * + * NOTE: these values are not "magic" constants, but + * are generated using the Threefish block function. + * They are pre-computed here only for speed; i.e., to + * avoid the need for a Threefish call during Init(). + * + * The IV for any fixed hash length may be pre-computed. + * Only the most common values are included here. + */ +/* Copyright 2013 Doug Whiting. This code is released to the public domain. */ +/* + * Illumos implementation note: these constants are for Skein v1.3 as per: + * http://www.skein-hash.info/sites/default/files/skein1.3.pdf + */ + +#include <sys/skein.h> /* get Skein macros and types */ +#include "skein_impl.h" /* get internal definitions */ + +#define MK_64 SKEIN_MK_64 + +/* blkSize = 256 bits. hashSize = 128 bits */ +const uint64_t SKEIN_256_IV_128[] = { + MK_64(0xE1111906, 0x964D7260), + MK_64(0x883DAAA7, 0x7C8D811C), + MK_64(0x10080DF4, 0x91960F7A), + MK_64(0xCCF7DDE5, 0xB45BC1C2) +}; + +/* blkSize = 256 bits. hashSize = 160 bits */ +const uint64_t SKEIN_256_IV_160[] = { + MK_64(0x14202314, 0x72825E98), + MK_64(0x2AC4E9A2, 0x5A77E590), + MK_64(0xD47A5856, 0x8838D63E), + MK_64(0x2DD2E496, 0x8586AB7D) +}; + +/* blkSize = 256 bits. hashSize = 224 bits */ +const uint64_t SKEIN_256_IV_224[] = { + MK_64(0xC6098A8C, 0x9AE5EA0B), + MK_64(0x876D5686, 0x08C5191C), + MK_64(0x99CB88D7, 0xD7F53884), + MK_64(0x384BDDB1, 0xAEDDB5DE) +}; + +/* blkSize = 256 bits. hashSize = 256 bits */ +const uint64_t SKEIN_256_IV_256[] = { + MK_64(0xFC9DA860, 0xD048B449), + MK_64(0x2FCA6647, 0x9FA7D833), + MK_64(0xB33BC389, 0x6656840F), + MK_64(0x6A54E920, 0xFDE8DA69) +}; + +/* blkSize = 512 bits. hashSize = 128 bits */ +const uint64_t SKEIN_512_IV_128[] = { + MK_64(0xA8BC7BF3, 0x6FBF9F52), + MK_64(0x1E9872CE, 0xBD1AF0AA), + MK_64(0x309B1790, 0xB32190D3), + MK_64(0xBCFBB854, 0x3F94805C), + MK_64(0x0DA61BCD, 0x6E31B11B), + MK_64(0x1A18EBEA, 0xD46A32E3), + MK_64(0xA2CC5B18, 0xCE84AA82), + MK_64(0x6982AB28, 0x9D46982D) +}; + +/* blkSize = 512 bits. hashSize = 160 bits */ +const uint64_t SKEIN_512_IV_160[] = { + MK_64(0x28B81A2A, 0xE013BD91), + MK_64(0xC2F11668, 0xB5BDF78F), + MK_64(0x1760D8F3, 0xF6A56F12), + MK_64(0x4FB74758, 0x8239904F), + MK_64(0x21EDE07F, 0x7EAF5056), + MK_64(0xD908922E, 0x63ED70B8), + MK_64(0xB8EC76FF, 0xECCB52FA), + MK_64(0x01A47BB8, 0xA3F27A6E) +}; + +/* blkSize = 512 bits. hashSize = 224 bits */ +const uint64_t SKEIN_512_IV_224[] = { + MK_64(0xCCD06162, 0x48677224), + MK_64(0xCBA65CF3, 0xA92339EF), + MK_64(0x8CCD69D6, 0x52FF4B64), + MK_64(0x398AED7B, 0x3AB890B4), + MK_64(0x0F59D1B1, 0x457D2BD0), + MK_64(0x6776FE65, 0x75D4EB3D), + MK_64(0x99FBC70E, 0x997413E9), + MK_64(0x9E2CFCCF, 0xE1C41EF7) +}; + +/* blkSize = 512 bits. hashSize = 256 bits */ +const uint64_t SKEIN_512_IV_256[] = { + MK_64(0xCCD044A1, 0x2FDB3E13), + MK_64(0xE8359030, 0x1A79A9EB), + MK_64(0x55AEA061, 0x4F816E6F), + MK_64(0x2A2767A4, 0xAE9B94DB), + MK_64(0xEC06025E, 0x74DD7683), + MK_64(0xE7A436CD, 0xC4746251), + MK_64(0xC36FBAF9, 0x393AD185), + MK_64(0x3EEDBA18, 0x33EDFC13) +}; + +/* blkSize = 512 bits. hashSize = 384 bits */ +const uint64_t SKEIN_512_IV_384[] = { + MK_64(0xA3F6C6BF, 0x3A75EF5F), + MK_64(0xB0FEF9CC, 0xFD84FAA4), + MK_64(0x9D77DD66, 0x3D770CFE), + MK_64(0xD798CBF3, 0xB468FDDA), + MK_64(0x1BC4A666, 0x8A0E4465), + MK_64(0x7ED7D434, 0xE5807407), + MK_64(0x548FC1AC, 0xD4EC44D6), + MK_64(0x266E1754, 0x6AA18FF8) +}; + +/* blkSize = 512 bits. hashSize = 512 bits */ +const uint64_t SKEIN_512_IV_512[] = { + MK_64(0x4903ADFF, 0x749C51CE), + MK_64(0x0D95DE39, 0x9746DF03), + MK_64(0x8FD19341, 0x27C79BCE), + MK_64(0x9A255629, 0xFF352CB1), + MK_64(0x5DB62599, 0xDF6CA7B0), + MK_64(0xEABE394C, 0xA9D5C3F4), + MK_64(0x991112C7, 0x1A75B523), + MK_64(0xAE18A40B, 0x660FCC33) +}; + +/* blkSize = 1024 bits. hashSize = 384 bits */ +const uint64_t SKEIN1024_IV_384[] = { + MK_64(0x5102B6B8, 0xC1894A35), + MK_64(0xFEEBC9E3, 0xFE8AF11A), + MK_64(0x0C807F06, 0xE32BED71), + MK_64(0x60C13A52, 0xB41A91F6), + MK_64(0x9716D35D, 0xD4917C38), + MK_64(0xE780DF12, 0x6FD31D3A), + MK_64(0x797846B6, 0xC898303A), + MK_64(0xB172C2A8, 0xB3572A3B), + MK_64(0xC9BC8203, 0xA6104A6C), + MK_64(0x65909338, 0xD75624F4), + MK_64(0x94BCC568, 0x4B3F81A0), + MK_64(0x3EBBF51E, 0x10ECFD46), + MK_64(0x2DF50F0B, 0xEEB08542), + MK_64(0x3B5A6530, 0x0DBC6516), + MK_64(0x484B9CD2, 0x167BBCE1), + MK_64(0x2D136947, 0xD4CBAFEA) +}; + +/* blkSize = 1024 bits. hashSize = 512 bits */ +const uint64_t SKEIN1024_IV_512[] = { + MK_64(0xCAEC0E5D, 0x7C1B1B18), + MK_64(0xA01B0E04, 0x5F03E802), + MK_64(0x33840451, 0xED912885), + MK_64(0x374AFB04, 0xEAEC2E1C), + MK_64(0xDF25A0E2, 0x813581F7), + MK_64(0xE4004093, 0x8B12F9D2), + MK_64(0xA662D539, 0xC2ED39B6), + MK_64(0xFA8B85CF, 0x45D8C75A), + MK_64(0x8316ED8E, 0x29EDE796), + MK_64(0x053289C0, 0x2E9F91B8), + MK_64(0xC3F8EF1D, 0x6D518B73), + MK_64(0xBDCEC3C4, 0xD5EF332E), + MK_64(0x549A7E52, 0x22974487), + MK_64(0x67070872, 0x5B749816), + MK_64(0xB9CD28FB, 0xF0581BD1), + MK_64(0x0E2940B8, 0x15804974) +}; + +/* blkSize = 1024 bits. hashSize = 1024 bits */ +const uint64_t SKEIN1024_IV_1024[] = { + MK_64(0xD593DA07, 0x41E72355), + MK_64(0x15B5E511, 0xAC73E00C), + MK_64(0x5180E5AE, 0xBAF2C4F0), + MK_64(0x03BD41D3, 0xFCBCAFAF), + MK_64(0x1CAEC6FD, 0x1983A898), + MK_64(0x6E510B8B, 0xCDD0589F), + MK_64(0x77E2BDFD, 0xC6394ADA), + MK_64(0xC11E1DB5, 0x24DCB0A3), + MK_64(0xD6D14AF9, 0xC6329AB5), + MK_64(0x6A9B0BFC, 0x6EB67E0D), + MK_64(0x9243C60D, 0xCCFF1332), + MK_64(0x1A1F1DDE, 0x743F02D4), + MK_64(0x0996753C, 0x10ED0BB8), + MK_64(0x6572DD22, 0xF2B4969A), + MK_64(0x61FD3062, 0xD00A579A), + MK_64(0x1DE0536E, 0x8682E539) +}; diff --git a/usr/src/common/crypto/skein/skein_port.h b/usr/src/common/crypto/skein/skein_port.h new file mode 100644 index 0000000000..1b02252369 --- /dev/null +++ b/usr/src/common/crypto/skein/skein_port.h @@ -0,0 +1,128 @@ +/* + * Platform-specific definitions for Skein hash function. + * + * Source code author: Doug Whiting, 2008. + * + * This algorithm and source code is released to the public domain. + * + * Many thanks to Brian Gladman for his portable header files. + * + * To port Skein to an "unsupported" platform, change the definitions + * in this file appropriately. + */ +/* Copyright 2013 Doug Whiting. This code is released to the public domain. */ + +#ifndef _SKEIN_PORT_H_ +#define _SKEIN_PORT_H_ + +#include <sys/types.h> /* get integer type definitions */ +#include <sys/systm.h> /* for bcopy() */ + +#ifndef RotL_64 +#define RotL_64(x, N) (((x) << (N)) | ((x) >> (64 - (N)))) +#endif + +/* + * Skein is "natively" little-endian (unlike SHA-xxx), for optimal + * performance on x86 CPUs. The Skein code requires the following + * definitions for dealing with endianness: + * + * SKEIN_NEED_SWAP: 0 for little-endian, 1 for big-endian + * Skein_Put64_LSB_First + * Skein_Get64_LSB_First + * Skein_Swap64 + * + * If SKEIN_NEED_SWAP is defined at compile time, it is used here + * along with the portable versions of Put64/Get64/Swap64, which + * are slow in general. + * + * Otherwise, an "auto-detect" of endianness is attempted below. + * If the default handling doesn't work well, the user may insert + * platform-specific code instead (e.g., for big-endian CPUs). + * + */ +#ifndef SKEIN_NEED_SWAP /* compile-time "override" for endianness? */ + +#include <sys/isa_defs.h> /* get endianness selection */ + +#define PLATFORM_MUST_ALIGN _ALIGNMENT_REQUIRED +#if defined(_BIG_ENDIAN) +/* here for big-endian CPUs */ +#define SKEIN_NEED_SWAP (1) +#else +/* here for x86 and x86-64 CPUs (and other detected little-endian CPUs) */ +#define SKEIN_NEED_SWAP (0) +#if PLATFORM_MUST_ALIGN == 0 /* ok to use "fast" versions? */ +#define Skein_Put64_LSB_First(dst08, src64, bCnt) bcopy(src64, dst08, bCnt) +#define Skein_Get64_LSB_First(dst64, src08, wCnt) \ + bcopy(src08, dst64, 8 * (wCnt)) +#endif +#endif + +#endif /* ifndef SKEIN_NEED_SWAP */ + +/* + * Provide any definitions still needed. + */ +#ifndef Skein_Swap64 /* swap for big-endian, nop for little-endian */ +#if SKEIN_NEED_SWAP +#define Skein_Swap64(w64) \ + (((((uint64_t)(w64)) & 0xFF) << 56) | \ + (((((uint64_t)(w64)) >> 8) & 0xFF) << 48) | \ + (((((uint64_t)(w64)) >> 16) & 0xFF) << 40) | \ + (((((uint64_t)(w64)) >> 24) & 0xFF) << 32) | \ + (((((uint64_t)(w64)) >> 32) & 0xFF) << 24) | \ + (((((uint64_t)(w64)) >> 40) & 0xFF) << 16) | \ + (((((uint64_t)(w64)) >> 48) & 0xFF) << 8) | \ + (((((uint64_t)(w64)) >> 56) & 0xFF))) +#else +#define Skein_Swap64(w64) (w64) +#endif +#endif /* ifndef Skein_Swap64 */ + +#ifndef Skein_Put64_LSB_First +void +Skein_Put64_LSB_First(uint8_t *dst, const uint64_t *src, size_t bCnt) +#ifdef SKEIN_PORT_CODE /* instantiate the function code here? */ +{ + /* + * this version is fully portable (big-endian or little-endian), + * but slow + */ + size_t n; + + for (n = 0; n < bCnt; n++) + dst[n] = (uint8_t)(src[n >> 3] >> (8 * (n & 7))); +} +#else +; /* output only the function prototype */ +#endif +#endif /* ifndef Skein_Put64_LSB_First */ + +#ifndef Skein_Get64_LSB_First +void +Skein_Get64_LSB_First(uint64_t *dst, const uint8_t *src, size_t wCnt) +#ifdef SKEIN_PORT_CODE /* instantiate the function code here? */ +{ + /* + * this version is fully portable (big-endian or little-endian), + * but slow + */ + size_t n; + + for (n = 0; n < 8 * wCnt; n += 8) + dst[n / 8] = (((uint64_t)src[n])) + + (((uint64_t)src[n + 1]) << 8) + + (((uint64_t)src[n + 2]) << 16) + + (((uint64_t)src[n + 3]) << 24) + + (((uint64_t)src[n + 4]) << 32) + + (((uint64_t)src[n + 5]) << 40) + + (((uint64_t)src[n + 6]) << 48) + + (((uint64_t)src[n + 7]) << 56); +} +#else +; /* output only the function prototype */ +#endif +#endif /* ifndef Skein_Get64_LSB_First */ + +#endif /* _SKEIN_PORT_H_ */ diff --git a/usr/src/common/zfs/zfeature_common.c b/usr/src/common/zfs/zfeature_common.c index 025c227e67..f75894b44d 100644 --- a/usr/src/common/zfs/zfeature_common.c +++ b/usr/src/common/zfs/zfeature_common.c @@ -231,4 +231,17 @@ zpool_feature_init(void) "org.open-zfs:large_blocks", "large_blocks", "Support for blocks larger than 128KB.", ZFEATURE_FLAG_PER_DATASET, large_blocks_deps); + + zfeature_register(SPA_FEATURE_SHA512, + "org.illumos:sha512", "sha512", + "SHA-512/256 hash algorithm.", + ZFEATURE_FLAG_PER_DATASET, NULL); + zfeature_register(SPA_FEATURE_SKEIN, + "org.illumos:skein", "skein", + "Skein hash algorithm.", + ZFEATURE_FLAG_PER_DATASET, NULL); + zfeature_register(SPA_FEATURE_EDONR, + "org.illumos:edonr", "edonr", + "Edon-R hash algorithm.", + ZFEATURE_FLAG_PER_DATASET, NULL); } diff --git a/usr/src/common/zfs/zfeature_common.h b/usr/src/common/zfs/zfeature_common.h index 794290bfe0..6b229aebc4 100644 --- a/usr/src/common/zfs/zfeature_common.h +++ b/usr/src/common/zfs/zfeature_common.h @@ -52,6 +52,9 @@ typedef enum spa_feature { SPA_FEATURE_BOOKMARKS, SPA_FEATURE_FS_SS_LIMIT, SPA_FEATURE_LARGE_BLOCKS, + SPA_FEATURE_SHA512, + SPA_FEATURE_SKEIN, + SPA_FEATURE_EDONR, SPA_FEATURES } spa_feature_t; diff --git a/usr/src/common/zfs/zfs_fletcher.c b/usr/src/common/zfs/zfs_fletcher.c index fa43ce6bdb..a58fa14b7c 100644 --- a/usr/src/common/zfs/zfs_fletcher.c +++ b/usr/src/common/zfs/zfs_fletcher.c @@ -22,6 +22,9 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2013 Saso Kiselkov. All rights reserved. + */ /* * Fletcher Checksums @@ -131,8 +134,10 @@ #include <sys/zio.h> #include <sys/spa.h> +/*ARGSUSED*/ void -fletcher_2_native(const void *buf, uint64_t size, zio_cksum_t *zcp) +fletcher_2_native(const void *buf, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp) { const uint64_t *ip = buf; const uint64_t *ipend = ip + (size / sizeof (uint64_t)); @@ -148,8 +153,10 @@ fletcher_2_native(const void *buf, uint64_t size, zio_cksum_t *zcp) ZIO_SET_CHECKSUM(zcp, a0, a1, b0, b1); } +/*ARGSUSED*/ void -fletcher_2_byteswap(const void *buf, uint64_t size, zio_cksum_t *zcp) +fletcher_2_byteswap(const void *buf, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp) { const uint64_t *ip = buf; const uint64_t *ipend = ip + (size / sizeof (uint64_t)); @@ -165,8 +172,10 @@ fletcher_2_byteswap(const void *buf, uint64_t size, zio_cksum_t *zcp) ZIO_SET_CHECKSUM(zcp, a0, a1, b0, b1); } +/*ARGSUSED*/ void -fletcher_4_native(const void *buf, uint64_t size, zio_cksum_t *zcp) +fletcher_4_native(const void *buf, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp) { const uint32_t *ip = buf; const uint32_t *ipend = ip + (size / sizeof (uint32_t)); @@ -182,8 +191,10 @@ fletcher_4_native(const void *buf, uint64_t size, zio_cksum_t *zcp) ZIO_SET_CHECKSUM(zcp, a, b, c, d); } +/*ARGSUSED*/ void -fletcher_4_byteswap(const void *buf, uint64_t size, zio_cksum_t *zcp) +fletcher_4_byteswap(const void *buf, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp) { const uint32_t *ip = buf; const uint32_t *ipend = ip + (size / sizeof (uint32_t)); diff --git a/usr/src/common/zfs/zfs_fletcher.h b/usr/src/common/zfs/zfs_fletcher.h index b49df0cf4f..a920cc816d 100644 --- a/usr/src/common/zfs/zfs_fletcher.h +++ b/usr/src/common/zfs/zfs_fletcher.h @@ -22,6 +22,9 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2013 Saso Kiselkov. All rights reserved. + */ #ifndef _ZFS_FLETCHER_H #define _ZFS_FLETCHER_H @@ -37,14 +40,12 @@ extern "C" { * fletcher checksum functions */ -void fletcher_2_native(const void *, uint64_t, zio_cksum_t *); -void fletcher_2_byteswap(const void *, uint64_t, zio_cksum_t *); -void fletcher_4_native(const void *, uint64_t, zio_cksum_t *); -void fletcher_4_byteswap(const void *, uint64_t, zio_cksum_t *); -void fletcher_4_incremental_native(const void *, uint64_t, - zio_cksum_t *); -void fletcher_4_incremental_byteswap(const void *, uint64_t, - zio_cksum_t *); +void fletcher_2_native(const void *, uint64_t, const void *, zio_cksum_t *); +void fletcher_2_byteswap(const void *, uint64_t, const void *, zio_cksum_t *); +void fletcher_4_native(const void *, uint64_t, const void *, zio_cksum_t *); +void fletcher_4_byteswap(const void *, uint64_t, const void *, zio_cksum_t *); +void fletcher_4_incremental_native(const void *, uint64_t, zio_cksum_t *); +void fletcher_4_incremental_byteswap(const void *, uint64_t, zio_cksum_t *); #ifdef __cplusplus } diff --git a/usr/src/common/zfs/zfs_prop.c b/usr/src/common/zfs/zfs_prop.c index 54aaa027dd..5c5af72ff2 100644 --- a/usr/src/common/zfs/zfs_prop.c +++ b/usr/src/common/zfs/zfs_prop.c @@ -71,6 +71,9 @@ zfs_prop_init(void) { "fletcher4", ZIO_CHECKSUM_FLETCHER_4 }, { "sha256", ZIO_CHECKSUM_SHA256 }, { "noparity", ZIO_CHECKSUM_NOPARITY }, + { "sha512", ZIO_CHECKSUM_SHA512 }, + { "skein", ZIO_CHECKSUM_SKEIN }, + { "edonr", ZIO_CHECKSUM_EDONR }, { NULL } }; @@ -81,6 +84,14 @@ zfs_prop_init(void) { "sha256", ZIO_CHECKSUM_SHA256 }, { "sha256,verify", ZIO_CHECKSUM_SHA256 | ZIO_CHECKSUM_VERIFY }, + { "sha512", ZIO_CHECKSUM_SHA512 }, + { "sha512,verify", + ZIO_CHECKSUM_SHA512 | ZIO_CHECKSUM_VERIFY }, + { "skein", ZIO_CHECKSUM_SKEIN }, + { "skein,verify", + ZIO_CHECKSUM_SKEIN | ZIO_CHECKSUM_VERIFY }, + { "edonr,verify", + ZIO_CHECKSUM_EDONR | ZIO_CHECKSUM_VERIFY }, { NULL } }; @@ -217,12 +228,12 @@ zfs_prop_init(void) zprop_register_index(ZFS_PROP_CHECKSUM, "checksum", ZIO_CHECKSUM_DEFAULT, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - "on | off | fletcher2 | fletcher4 | sha256", "CHECKSUM", - checksum_table); + "on | off | fletcher2 | fletcher4 | sha256 | sha512 | " + "skein | edonr", "CHECKSUM", checksum_table); zprop_register_index(ZFS_PROP_DEDUP, "dedup", ZIO_CHECKSUM_OFF, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - "on | off | verify | sha256[,verify]", "DEDUP", - dedup_table); + "on | off | verify | sha256[,verify], sha512[,verify], " + "skein[,verify], edonr,verify", "DEDUP", dedup_table); zprop_register_index(ZFS_PROP_COMPRESSION, "compression", ZIO_COMPRESS_DEFAULT, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, diff --git a/usr/src/grub/capability b/usr/src/grub/capability index 111cd61ccb..12d0ea054a 100644 --- a/usr/src/grub/capability +++ b/usr/src/grub/capability @@ -20,6 +20,7 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2013 by Delphix. All rights reserved. +# Copyright 2013 Saso Kiselkov. All rights reserved. # # This file defines the current capabilities of GRUB over and above that # supported by the standard distribution diff --git a/usr/src/grub/grub-0.97/stage2/fsys_zfs.c b/usr/src/grub/grub-0.97/stage2/fsys_zfs.c index 91b4bcec6f..019fbc76c6 100644 --- a/usr/src/grub/grub-0.97/stage2/fsys_zfs.c +++ b/usr/src/grub/grub-0.97/stage2/fsys_zfs.c @@ -145,12 +145,14 @@ zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = { {{fletcher_4_native, fletcher_4_byteswap}, 1, 0, "fletcher4"}, {{zio_checksum_SHA256, zio_checksum_SHA256}, 1, 0, "SHA256"}, {{NULL, NULL}, 0, 0, "zilog2"}, + {{zio_checksum_off, zio_checksum_off}, 0, 0, "noparity"}, + {{zio_checksum_SHA512, NULL}, 0, 0, "SHA512"} }; /* * zio_checksum_verify: Provides support for checksum verification. * - * Fletcher2, Fletcher4, and SHA256 are supported. + * Fletcher2, Fletcher4, SHA-256 and SHA-512/256 are supported. * * Return: * -1 = Failure @@ -1049,6 +1051,7 @@ static const char *spa_feature_names[] = { "com.delphix:extensible_dataset", "com.delphix:embedded_data", "org.open-zfs:large_blocks", + "org.illumos:sha512", NULL }; diff --git a/usr/src/grub/grub-0.97/stage2/fsys_zfs.h b/usr/src/grub/grub-0.97/stage2/fsys_zfs.h index 2f77a5b6a7..debf98c80e 100644 --- a/usr/src/grub/grub-0.97/stage2/fsys_zfs.h +++ b/usr/src/grub/grub-0.97/stage2/fsys_zfs.h @@ -213,6 +213,7 @@ extern void fletcher_2_byteswap(const void *, uint64_t, zio_cksum_t *); extern void fletcher_4_native(const void *, uint64_t, zio_cksum_t *); extern void fletcher_4_byteswap(const void *, uint64_t, zio_cksum_t *); extern void zio_checksum_SHA256(const void *, uint64_t, zio_cksum_t *); +extern void zio_checksum_SHA512(const void *, uint64_t, zio_cksum_t *); extern int lzjb_decompress(void *, void *, size_t, size_t); extern int lz4_decompress(void *, void *, size_t, size_t); diff --git a/usr/src/grub/grub-0.97/stage2/zfs-include/zio.h b/usr/src/grub/grub-0.97/stage2/zfs-include/zio.h index 3b893f451e..434a2f2ef7 100644 --- a/usr/src/grub/grub-0.97/stage2/zfs-include/zio.h +++ b/usr/src/grub/grub-0.97/stage2/zfs-include/zio.h @@ -67,6 +67,10 @@ enum zio_checksum { ZIO_CHECKSUM_FLETCHER_4, ZIO_CHECKSUM_SHA256, ZIO_CHECKSUM_ZILOG2, + ZIO_CHECKSUM_NOPARITY, + ZIO_CHECKSUM_SHA512, + ZIO_CHECKSUM_SKEIN, + ZIO_CHECKSUM_EDONR, ZIO_CHECKSUM_FUNCTIONS }; diff --git a/usr/src/grub/grub-0.97/stage2/zfs_sha256.c b/usr/src/grub/grub-0.97/stage2/zfs_sha256.c index 393eaee05b..402af22196 100644 --- a/usr/src/grub/grub-0.97/stage2/zfs_sha256.c +++ b/usr/src/grub/grub-0.97/stage2/zfs_sha256.c @@ -20,21 +20,22 @@ * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright 2013 Saso Kiselkov. All rights reserved. + */ #include "fsys_zfs.h" /* - * SHA-256 checksum, as specified in FIPS 180-2, available at: + * SHA-256 and SHA-512/256 hashes, as specified in FIPS 180-4, available at: * http://csrc.nist.gov/cryptval * - * This is a very compact implementation of SHA-256. + * This is a very compact implementation of SHA-256 and SHA-512/256. * It is designed to be simple and portable, not to be fast. */ /* - * The literal definitions according to FIPS180-2 would be: + * The literal definitions according to FIPS180-4 would be: * * Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z))) * Maj(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) @@ -43,12 +44,21 @@ */ #define Ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define Maj(x, y, z) (((x) & (y)) ^ ((z) & ((x) ^ (y)))) -#define Rot32(x, s) (((x) >> s) | ((x) << (32 - s))) -#define SIGMA0(x) (Rot32(x, 2) ^ Rot32(x, 13) ^ Rot32(x, 22)) -#define SIGMA1(x) (Rot32(x, 6) ^ Rot32(x, 11) ^ Rot32(x, 25)) -#define sigma0(x) (Rot32(x, 7) ^ Rot32(x, 18) ^ ((x) >> 3)) -#define sigma1(x) (Rot32(x, 17) ^ Rot32(x, 19) ^ ((x) >> 10)) +#define ROTR(x, n) (((x) >> (n)) | ((x) << ((sizeof (x) * NBBY)-(n)))) + +/* SHA-224/256 operations */ +#define BIGSIGMA0_256(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define BIGSIGMA1_256(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define SIGMA0_256(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ ((x) >> 3)) +#define SIGMA1_256(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ ((x) >> 10)) +/* SHA-384/512 operations */ +#define BIGSIGMA0_512(x) (ROTR((x), 28) ^ ROTR((x), 34) ^ ROTR((x), 39)) +#define BIGSIGMA1_512(x) (ROTR((x), 14) ^ ROTR((x), 18) ^ ROTR((x), 41)) +#define SIGMA0_512(x) (ROTR((x), 1) ^ ROTR((x), 8) ^ ((x) >> 7)) +#define SIGMA1_512(x) (ROTR((x), 19) ^ ROTR((x), 61) ^ ((x) >> 6)) + +/* SHA-256 round constants */ static const uint32_t SHA256_K[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, @@ -68,44 +78,131 @@ static const uint32_t SHA256_K[64] = { 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; +/* SHA-512 round constants */ +static const uint64_t SHA512_K[80] = { + 0x428A2F98D728AE22ULL, 0x7137449123EF65CDULL, + 0xB5C0FBCFEC4D3B2FULL, 0xE9B5DBA58189DBBCULL, + 0x3956C25BF348B538ULL, 0x59F111F1B605D019ULL, + 0x923F82A4AF194F9BULL, 0xAB1C5ED5DA6D8118ULL, + 0xD807AA98A3030242ULL, 0x12835B0145706FBEULL, + 0x243185BE4EE4B28CULL, 0x550C7DC3D5FFB4E2ULL, + 0x72BE5D74F27B896FULL, 0x80DEB1FE3B1696B1ULL, + 0x9BDC06A725C71235ULL, 0xC19BF174CF692694ULL, + 0xE49B69C19EF14AD2ULL, 0xEFBE4786384F25E3ULL, + 0x0FC19DC68B8CD5B5ULL, 0x240CA1CC77AC9C65ULL, + 0x2DE92C6F592B0275ULL, 0x4A7484AA6EA6E483ULL, + 0x5CB0A9DCBD41FBD4ULL, 0x76F988DA831153B5ULL, + 0x983E5152EE66DFABULL, 0xA831C66D2DB43210ULL, + 0xB00327C898FB213FULL, 0xBF597FC7BEEF0EE4ULL, + 0xC6E00BF33DA88FC2ULL, 0xD5A79147930AA725ULL, + 0x06CA6351E003826FULL, 0x142929670A0E6E70ULL, + 0x27B70A8546D22FFCULL, 0x2E1B21385C26C926ULL, + 0x4D2C6DFC5AC42AEDULL, 0x53380D139D95B3DFULL, + 0x650A73548BAF63DEULL, 0x766A0ABB3C77B2A8ULL, + 0x81C2C92E47EDAEE6ULL, 0x92722C851482353BULL, + 0xA2BFE8A14CF10364ULL, 0xA81A664BBC423001ULL, + 0xC24B8B70D0F89791ULL, 0xC76C51A30654BE30ULL, + 0xD192E819D6EF5218ULL, 0xD69906245565A910ULL, + 0xF40E35855771202AULL, 0x106AA07032BBD1B8ULL, + 0x19A4C116B8D2D0C8ULL, 0x1E376C085141AB53ULL, + 0x2748774CDF8EEB99ULL, 0x34B0BCB5E19B48A8ULL, + 0x391C0CB3C5C95A63ULL, 0x4ED8AA4AE3418ACBULL, + 0x5B9CCA4F7763E373ULL, 0x682E6FF3D6B2B8A3ULL, + 0x748F82EE5DEFB2FCULL, 0x78A5636F43172F60ULL, + 0x84C87814A1F0AB72ULL, 0x8CC702081A6439ECULL, + 0x90BEFFFA23631E28ULL, 0xA4506CEBDE82BDE9ULL, + 0xBEF9A3F7B2C67915ULL, 0xC67178F2E372532BULL, + 0xCA273ECEEA26619CULL, 0xD186B8C721C0C207ULL, + 0xEADA7DD6CDE0EB1EULL, 0xF57D4F7FEE6ED178ULL, + 0x06F067AA72176FBAULL, 0x0A637DC5A2C898A6ULL, + 0x113F9804BEF90DAEULL, 0x1B710B35131C471BULL, + 0x28DB77F523047D84ULL, 0x32CAAB7B40C72493ULL, + 0x3C9EBE0A15C9BEBCULL, 0x431D67C49C100D4CULL, + 0x4CC5D4BECB3E42B6ULL, 0x597F299CFC657E2AULL, + 0x5FCB6FAB3AD6FAECULL, 0x6C44198C4A475817ULL +}; + static void SHA256Transform(uint32_t *H, const uint8_t *cp) { uint32_t a, b, c, d, e, f, g, h, t, T1, T2, W[64]; - for (t = 0; t < 16; t++, cp += 4) + /* copy chunk into the first 16 words of the message schedule */ + for (t = 0; t < 16; t++, cp += sizeof (uint32_t)) W[t] = (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | cp[3]; + /* extend the first 16 words into the remaining 48 words */ for (t = 16; t < 64; t++) - W[t] = sigma1(W[t - 2]) + W[t - 7] + - sigma0(W[t - 15]) + W[t - 16]; + W[t] = SIGMA1_256(W[t - 2]) + W[t - 7] + + SIGMA0_256(W[t - 15]) + W[t - 16]; + /* init working variables to the current hash value */ a = H[0]; b = H[1]; c = H[2]; d = H[3]; e = H[4]; f = H[5]; g = H[6]; h = H[7]; + /* iterate the compression function for all rounds of the hash */ for (t = 0; t < 64; t++) { - T1 = h + SIGMA1(e) + Ch(e, f, g) + SHA256_K[t] + W[t]; - T2 = SIGMA0(a) + Maj(a, b, c); + T1 = h + BIGSIGMA1_256(e) + Ch(e, f, g) + SHA256_K[t] + W[t]; + T2 = BIGSIGMA0_256(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; } + /* add the compressed chunk to the current hash value */ H[0] += a; H[1] += b; H[2] += c; H[3] += d; H[4] += e; H[5] += f; H[6] += g; H[7] += h; } -void -zio_checksum_SHA256(const void *buf, uint64_t size, zio_cksum_t *zcp) +static void +SHA512Transform(uint64_t *H, const uint8_t *cp) { - uint32_t H[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; - uint8_t pad[128]; - int padsize = size & 63; - int i; + uint64_t a, b, c, d, e, f, g, h, t, T1, T2, W[80]; + + /* copy chunk into the first 16 words of the message schedule */ + for (t = 0; t < 16; t++, cp += sizeof (uint64_t)) + W[t] = ((uint64_t)cp[0] << 56) | ((uint64_t)cp[1] << 48) | + ((uint64_t)cp[2] << 40) | ((uint64_t)cp[3] << 32) | + (cp[4] << 24) | (cp[5] << 16) | (cp[6] << 8) | cp[7]; + /* extend the first 16 words into the remaining 64 words */ + for (t = 16; t < 80; t++) + W[t] = SIGMA1_512(W[t - 2]) + W[t - 7] + + SIGMA0_512(W[t - 15]) + W[t - 16]; + + /* init working variables to the current hash value */ + a = H[0]; b = H[1]; c = H[2]; d = H[3]; + e = H[4]; f = H[5]; g = H[6]; h = H[7]; + + /* iterate the compression function for all rounds of the hash */ + for (t = 0; t < 80; t++) { + T1 = h + BIGSIGMA1_512(e) + Ch(e, f, g) + SHA512_K[t] + W[t]; + T2 = BIGSIGMA0_512(a) + Maj(a, b, c); + h = g; g = f; f = e; e = d + T1; + d = c; c = b; b = a; a = T1 + T2; + } + + /* add the compressed chunk to the current hash value */ + H[0] += a; H[1] += b; H[2] += c; H[3] += d; + H[4] += e; H[5] += f; H[6] += g; H[7] += h; +} + +/* + * Implements the SHA-224 and SHA-256 hash algos - to select between them + * pass the appropriate initial values of 'H' and truncate the last 32 bits + * in case of SHA-224. + */ +static void +SHA256(uint32_t *H, const void *buf, uint64_t size, zio_cksum_t *zcp) +{ + uint8_t pad[128]; + unsigned padsize = size & 63; + unsigned i; + + /* process all blocks up to the last one */ for (i = 0; i < size - padsize; i += 64) SHA256Transform(H, (uint8_t *)buf + i); + /* process the last block and padding */ for (i = 0; i < padsize; i++) pad[i] = ((uint8_t *)buf)[i]; @@ -124,3 +221,60 @@ zio_checksum_SHA256(const void *buf, uint64_t size, zio_cksum_t *zcp) (uint64_t)H[4] << 32 | H[5], (uint64_t)H[6] << 32 | H[7]); } + +/* + * Implements the SHA-384, SHA-512 and SHA-512/t hash algos - to select + * between them pass the appropriate initial values for 'H'. The output + * of this function is truncated to the first 256 bits that fit into 'zcp'. + */ +static void +SHA512(uint64_t *H, const void *buf, uint64_t size, zio_cksum_t *zcp) +{ + uint8_t pad[256]; + unsigned padsize = size & 127; + unsigned i; + + /* process all blocks up to the last one */ + for (i = 0; i < size - padsize; i += 128) + SHA512Transform(H, (uint8_t *)buf + i); + + /* process the last block and padding */ + for (i = 0; i < padsize; i++) + pad[i] = ((uint8_t *)buf)[i]; + + for (pad[padsize++] = 0x80; (padsize & 127) != 120; padsize++) + pad[padsize] = 0; + + for (i = 0; i < 8; i++) + pad[padsize++] = (size << 3) >> (120 - 8 * i); + + for (i = 0; i < padsize; i += 128) + SHA512Transform(H, pad + i); + + /* truncate the output to the first 256 bits which fit into 'zcp' */ + ZIO_SET_CHECKSUM(zcp, H[0], H[1], H[2], H[3]); +} + +void +zio_checksum_SHA256(const void *buf, uint64_t size, zio_cksum_t *zcp) +{ + /* SHA-256 as per FIPS 180-4. */ + uint32_t H[] = { + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 + }; + SHA256(H, buf, size, zcp); +} + +void +zio_checksum_SHA512(const void *buf, uint64_t size, zio_cksum_t *zcp) +{ + /* SHA-512/256 as per FIPS 180-4. */ + uint64_t H[] = { + 0x22312194FC2BF72CULL, 0x9F555FA3C84C64C2ULL, + 0x2393B86B6F53B151ULL, 0x963877195940EABDULL, + 0x96283EE2A88EFFE3ULL, 0xBE5E1E2553863992ULL, + 0x2B0199FC2C85B8AAULL, 0x0EB72DDC81C52CA2ULL + }; + SHA512(H, buf, size, zcp); +} diff --git a/usr/src/lib/libbe/common/be_activate.c b/usr/src/lib/libbe/common/be_activate.c index 985a585094..6eda8eebba 100644 --- a/usr/src/lib/libbe/common/be_activate.c +++ b/usr/src/lib/libbe/common/be_activate.c @@ -55,8 +55,8 @@ static int set_bootfs(char *boot_rpool, char *be_root_ds); static int set_canmount(be_node_list_t *, char *); static boolean_t be_do_install_mbr(char *, nvlist_t *); static int be_do_installboot_helper(zpool_handle_t *, nvlist_t *, char *, - char *); -static int be_do_installboot(be_transaction_data_t *); + char *, uint16_t); +static int be_do_installboot(be_transaction_data_t *, uint16_t); static int be_get_grub_vers(be_transaction_data_t *, char **, char **); static int get_ver_from_capfile(char *, char **); static int be_promote_zone_ds(char *, char *); @@ -119,6 +119,82 @@ be_activate(nvlist_t *be_attrs) return (ret); } +/* + * Function: be_installboot + * Description: Calls be_do_installboot to install/update bootloader on + * pool passed in through be_attrs. The primary consumer is + * bootadm command to avoid duplication of the code. + * Parameters: + * be_attrs - pointer to nvlist_t of attributes being passed in. + * The following attribute values are used: + * + * BE_ATTR_ORIG_BE_NAME *required + * BE_ATTR_ORIG_BE_POOL *required + * BE_ATTR_ORIG_BE_ROOT *required + * BE_ATTR_INSTALL_FLAGS optional + * + * Return: + * BE_SUCCESS - Success + * be_errno_t - Failure + * Scope: + * Public + */ +int +be_installboot(nvlist_t *be_attrs) +{ + int ret = BE_SUCCESS; + uint16_t flags = 0; + uint16_t verbose; + be_transaction_data_t bt = { 0 }; + + /* Get flags */ + if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, + BE_ATTR_INSTALL_FLAGS, DATA_TYPE_UINT16, &flags, NULL) != 0) { + be_print_err(gettext("be_installboot: failed to lookup " + "BE_ATTR_INSTALL_FLAGS attribute\n")); + return (BE_ERR_INVAL); + } + + /* Set verbose early, so we get all messages */ + verbose = flags & BE_INSTALLBOOT_FLAG_VERBOSE; + if (verbose == BE_INSTALLBOOT_FLAG_VERBOSE) + libbe_print_errors(B_TRUE); + + ret = nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_NAME, + &bt.obe_name); + if (ret != 0) { + be_print_err(gettext("be_installboot: failed to " + "lookup BE_ATTR_ORIG_BE_NAME attribute\n")); + return (BE_ERR_INVAL); + } + + ret = nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_POOL, + &bt.obe_zpool); + if (ret != 0) { + be_print_err(gettext("be_installboot: failed to " + "lookup BE_ATTR_ORIG_BE_POOL attribute\n")); + return (BE_ERR_INVAL); + } + + ret = nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_ROOT, + &bt.obe_root_ds); + if (ret != 0) { + be_print_err(gettext("be_installboot: failed to " + "lookup BE_ATTR_ORIG_BE_ROOT attribute\n")); + return (BE_ERR_INVAL); + } + + /* Initialize libzfs handle */ + if (!be_zfs_init()) + return (BE_ERR_INIT); + + ret = be_do_installboot(&bt, flags); + + be_zfs_fini(); + + return (ret); +} + /* ******************************************************************** */ /* Semi Private Functions */ /* ******************************************************************** */ @@ -175,7 +251,8 @@ _be_activate(char *be_name) cb.obe_root_ds = strdup(root_ds); if (getzoneid() == GLOBAL_ZONEID) { - if ((ret = be_do_installboot(&cb)) != BE_SUCCESS) + ret = be_do_installboot(&cb, BE_INSTALLBOOT_FLAG_NULL); + if (ret != BE_SUCCESS) return (ret); if (!be_has_menu_entry(root_ds, cb.obe_zpool, &entry)) { @@ -794,14 +871,16 @@ be_do_install_mbr(char *diskname, nvlist_t *child) static int be_do_installboot_helper(zpool_handle_t *zphp, nvlist_t *child, char *stage1, - char *stage2) + char *stage2, uint16_t flags) { char install_cmd[MAXPATHLEN]; char be_run_cmd_errbuf[BUFSIZ]; + char be_run_cmd_outbuf[BUFSIZ]; char diskname[MAXPATHLEN]; char *vname; char *path, *dsk_ptr; char *flag = ""; + int ret; if (nvlist_lookup_string(child, ZPOOL_CONFIG_PATH, &path) != 0) { be_print_err(gettext("be_do_installboot: " @@ -836,31 +915,60 @@ be_do_installboot_helper(zpool_handle_t *zphp, nvlist_t *child, char *stage1, } if (be_is_isa("i386")) { - if (be_do_install_mbr(diskname, child)) - flag = "-m -f"; + uint16_t force = flags & BE_INSTALLBOOT_FLAG_FORCE; + uint16_t mbr = flags & BE_INSTALLBOOT_FLAG_MBR; + + if (force == BE_INSTALLBOOT_FLAG_FORCE) { + if (mbr == BE_INSTALLBOOT_FLAG_MBR || + be_do_install_mbr(diskname, child)) + flag = "-F -m -f"; + else + flag = "-F"; + } else { + if (mbr == BE_INSTALLBOOT_FLAG_MBR || + be_do_install_mbr(diskname, child)) + flag = "-m -f"; + } + (void) snprintf(install_cmd, sizeof (install_cmd), "%s %s %s %s %s", BE_INSTALL_GRUB, flag, stage1, stage2, diskname); } else { - flag = "-F zfs"; + if ((flags & BE_INSTALLBOOT_FLAG_FORCE) == + BE_INSTALLBOOT_FLAG_FORCE) + flag = "-f -F zfs"; + else + flag = "-F zfs"; + (void) snprintf(install_cmd, sizeof (install_cmd), "%s %s %s %s", BE_INSTALL_BOOT, flag, stage2, diskname); } - if (be_run_cmd(install_cmd, be_run_cmd_errbuf, BUFSIZ, NULL, 0) - != BE_SUCCESS) { + *be_run_cmd_outbuf = '\0'; + *be_run_cmd_errbuf = '\0'; + + ret = be_run_cmd(install_cmd, be_run_cmd_errbuf, BUFSIZ, + be_run_cmd_outbuf, BUFSIZ); + + if (ret != BE_SUCCESS) { be_print_err(gettext("be_do_installboot: install " "failed for device %s.\n"), vname); - /* Assume localized cmd err output. */ - be_print_err(gettext(" Command: \"%s\"\n"), - install_cmd); + ret = BE_ERR_BOOTFILE_INST; + } + + be_print_err(gettext(" Command: \"%s\"\n"), install_cmd); + if (be_run_cmd_outbuf[0] != 0) { + be_print_err(gettext(" Output:\n")); + be_print_err("%s", be_run_cmd_outbuf); + } + + if (be_run_cmd_errbuf[0] != 0) { + be_print_err(gettext(" Errors:\n")); be_print_err("%s", be_run_cmd_errbuf); - free(vname); - return (BE_ERR_BOOTFILE_INST); } free(vname); - return (BE_SUCCESS); + return (ret); } /* @@ -1069,6 +1177,7 @@ be_is_install_needed(be_transaction_data_t *bt, boolean_t *update) * * Parameters: * bt - The transaction data for the BE we're activating. + * flags - flags for bootloader install * Return: * BE_SUCCESS - Success * be_errno_t - Failure @@ -1077,7 +1186,7 @@ be_is_install_needed(be_transaction_data_t *bt, boolean_t *update) * Private */ static int -be_do_installboot(be_transaction_data_t *bt) +be_do_installboot(be_transaction_data_t *bt, uint16_t flags) { zpool_handle_t *zphp = NULL; zfs_handle_t *zhp = NULL; @@ -1096,9 +1205,11 @@ be_do_installboot(be_transaction_data_t *bt) * version implementation like grub. Embedded versioning is * checked by actual installer. */ - ret = be_is_install_needed(bt, &update); - if (ret != BE_SUCCESS || update == B_FALSE) - return (ret); + if ((flags & BE_INSTALLBOOT_FLAG_FORCE) != BE_INSTALLBOOT_FLAG_FORCE) { + ret = be_is_install_needed(bt, &update); + if (ret != BE_SUCCESS || update == B_FALSE) + return (ret); + } if ((zhp = zfs_open(g_zfs, bt->obe_root_ds, ZFS_TYPE_FILESYSTEM)) == NULL) { @@ -1205,7 +1316,7 @@ be_do_installboot(be_transaction_data_t *bt) for (i = 0; i < nchildren; i++) { ret = be_do_installboot_helper(zphp, nvchild[i], - stage1, stage2); + stage1, stage2, flags); if (ret != BE_SUCCESS) goto done; } @@ -1213,7 +1324,7 @@ be_do_installboot(be_transaction_data_t *bt) free(vname); ret = be_do_installboot_helper(zphp, child[c], stage1, - stage2); + stage2, flags); if (ret != BE_SUCCESS) goto done; } diff --git a/usr/src/lib/libbe/common/libbe.h b/usr/src/lib/libbe/common/libbe.h index c5662893a2..994bc881ac 100644 --- a/usr/src/lib/libbe/common/libbe.h +++ b/usr/src/lib/libbe/common/libbe.h @@ -42,6 +42,7 @@ extern "C" { #define BE_ATTR_ORIG_BE_NAME "orig_be_name" #define BE_ATTR_ORIG_BE_POOL "orig_be_pool" +#define BE_ATTR_ORIG_BE_ROOT "orig_be_root" #define BE_ATTR_SNAP_NAME "snap_name" #define BE_ATTR_NEW_BE_NAME "new_be_name" @@ -59,6 +60,7 @@ extern "C" { #define BE_ATTR_MOUNT_FLAGS "mount_flags" #define BE_ATTR_UNMOUNT_FLAGS "unmount_flags" #define BE_ATTR_DESTROY_FLAGS "destroy_flags" +#define BE_ATTR_INSTALL_FLAGS "install_flags" #define BE_ATTR_ROOT_DS "root_ds" #define BE_ATTR_UUID_STR "uuid_str" @@ -205,6 +207,12 @@ typedef struct be_node_list { #define BE_DESTROY_FLAG_SNAPSHOTS 0x00000001 #define BE_DESTROY_FLAG_FORCE_UNMOUNT 0x00000002 +/* Flags for installboot */ +#define BE_INSTALLBOOT_FLAG_NULL 0x00000000 +#define BE_INSTALLBOOT_FLAG_MBR 0x00000001 +#define BE_INSTALLBOOT_FLAG_FORCE 0x00000002 +#define BE_INSTALLBOOT_FLAG_VERBOSE 0x00000004 + /* sort rules for be_sort() */ typedef enum { BE_SORT_UNSPECIFIED = -1, @@ -244,6 +252,11 @@ char *be_err_to_str(int); int be_sort(be_node_list_t **, int); /* + * Installboot support + */ +int be_installboot(nvlist_t *); + +/* * Library functions */ void libbe_print_errors(boolean_t); diff --git a/usr/src/lib/libbe/common/mapfile-vers b/usr/src/lib/libbe/common/mapfile-vers index 0e57583dab..0602bd7de3 100644 --- a/usr/src/lib/libbe/common/mapfile-vers +++ b/usr/src/lib/libbe/common/mapfile-vers @@ -49,6 +49,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { be_err_to_str; be_free_list; be_init; + be_installboot; be_list; be_mount; be_rename; diff --git a/usr/src/lib/libmd/Makefile b/usr/src/lib/libmd/Makefile index ddd89d7382..137586aef6 100644 --- a/usr/src/lib/libmd/Makefile +++ b/usr/src/lib/libmd/Makefile @@ -21,6 +21,7 @@ # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2013 Saso Kiselkov. All rights reserved. # include $(SRC)/lib/Makefile.lib @@ -29,7 +30,7 @@ $(SPARC_BLD)CAPDIR = capabilities SUBDIRS= $(MACH) $(BUILD64) $(MACH64) -HDRS = md4.h md5.h sha1.h sha2.h +HDRS = md4.h md5.h sha1.h sha2.h skein.h HDRDIR = common all := TARGET= all diff --git a/usr/src/lib/libmd/Makefile.com b/usr/src/lib/libmd/Makefile.com index af8cac390b..9d2458f918 100644 --- a/usr/src/lib/libmd/Makefile.com +++ b/usr/src/lib/libmd/Makefile.com @@ -21,13 +21,18 @@ # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2013 Saso Kiselkov. All rights reserved. # LIBS = $(DYNLIB) $(LINTLIB) -SRCS = $(COMDIR)/md4/md4.c \ +SRCS = $(COMDIR)/edonr/edonr.c \ + $(COMDIR)/md4/md4.c \ $(COMDIR)/md5/md5.c \ $(COMDIR)/sha1/sha1.c \ - $(COMDIR)/sha2/sha2.c + $(COMDIR)/sha2/sha2.c \ + $(COMDIR)/skein/skein.c \ + $(COMDIR)/skein/skein_block.c \ + $(COMDIR)/skein/skein_iv.c COMDIR = $(SRC)/common/crypto SRCDIR = ../common diff --git a/usr/src/lib/libmd/Makefile.targ b/usr/src/lib/libmd/Makefile.targ index 58ec7b30e5..fadc3d71ad 100644 --- a/usr/src/lib/libmd/Makefile.targ +++ b/usr/src/lib/libmd/Makefile.targ @@ -21,10 +21,15 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2013 Saso Kiselkov. All rights reserved. # COMDIR = $(SRC)/common/crypto +pics/%.o: $(COMDIR)/edonr/%.c + $(COMPILE.c) -I$(COMDIR)/edonr -o $@ $< + $(POST_PROCESS_O) + pics/%.o: $(COMDIR)/md4/%.c $(COMPILE.c) -I$(COMDIR)/md4 -o $@ $< $(POST_PROCESS_O) @@ -46,4 +51,8 @@ pics/%.o: $(COMDIR)/sha2/%.c $(COMPILE.c) -I$(COMDIR)/sha2 -o $@ $< $(POST_PROCESS_O) +pics/%.o: $(COMDIR)/skein/%.c + $(COMPILE.c) -I$(COMDIR)/skein -o $@ $< + $(POST_PROCESS_O) + include $(SRC)/lib/Makefile.targ diff --git a/usr/src/lib/libmd/amd64/Makefile b/usr/src/lib/libmd/amd64/Makefile index 3872749fbb..8ac0b15a30 100644 --- a/usr/src/lib/libmd/amd64/Makefile +++ b/usr/src/lib/libmd/amd64/Makefile @@ -20,12 +20,14 @@ # # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2013 Saso Kiselkov. All rights reserved. # LIBRARY = libmd.a VERS = .1 -OBJECTS = md4.o md5.o sha1.o sha2.o +OBJECTS = edonr.o md4.o md5.o sha1.o sha2.o \ + skein.o skein_block.o skein_iv.o include $(SRC)/lib/Makefile.lib include $(SRC)/lib/Makefile.rootfs diff --git a/usr/src/lib/libmd/common/mapfile-vers b/usr/src/lib/libmd/common/mapfile-vers index a70144e833..f0b225235b 100644 --- a/usr/src/lib/libmd/common/mapfile-vers +++ b/usr/src/lib/libmd/common/mapfile-vers @@ -20,6 +20,7 @@ # # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2013 Saso Kiselkov. All rights reserved. # # @@ -50,6 +51,31 @@ $mapfile_version 2 # ELF section. As a result, ld will put the two main symbols in. # +SYMBOL_VERSION ILLUMOS_0.1 { + global: + Skein1024_Final; + Skein1024_Final_Pad; + Skein1024_Init; + Skein1024_InitExt; + Skein1024_Output; + Skein1024_Update; + Skein_256_Final; + Skein_256_Final_Pad; + Skein_256_Init; + Skein_256_InitExt; + Skein_256_Output; + Skein_256_Update; + Skein_512_Final; + Skein_512_Final_Pad; + Skein_512_Init; + Skein_512_InitExt; + Skein_512_Output; + Skein_512_Update; + EdonRFinal; + EdonRHash; + EdonRInit; + EdonRUpdate; +} SUNW_1.1; SYMBOL_VERSION SUNW_1.1 { global: diff --git a/usr/src/lib/libmd/common/skein.h b/usr/src/lib/libmd/common/skein.h new file mode 100644 index 0000000000..f341b96776 --- /dev/null +++ b/usr/src/lib/libmd/common/skein.h @@ -0,0 +1,31 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2013 Saso Kiselkov. All rights reserved. + */ + +#ifndef _SKEIN_H +#define _SKEIN_H + +#include <sys/skein.h> + +#endif /* _SKEIN_H */ diff --git a/usr/src/lib/libmd/i386/Makefile b/usr/src/lib/libmd/i386/Makefile index 3e6fe00e17..d7827814d6 100644 --- a/usr/src/lib/libmd/i386/Makefile +++ b/usr/src/lib/libmd/i386/Makefile @@ -21,12 +21,14 @@ # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2013 Saso Kiselkov. All rights reserved. # LIBRARY = libmd.a VERS = .1 -OBJECTS = md4.o md5.o sha1.o sha2.o +OBJECTS = edonr.o md4.o md5.o sha1.o sha2.o \ + skein.o skein_block.o skein_iv.o include $(SRC)/lib/Makefile.lib include $(SRC)/lib/Makefile.rootfs diff --git a/usr/src/lib/libmd/inc.flg b/usr/src/lib/libmd/inc.flg index 2652430b84..05c340cfd3 100644 --- a/usr/src/lib/libmd/inc.flg +++ b/usr/src/lib/libmd/inc.flg @@ -23,9 +23,11 @@ # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" +# Copyright 2013 Saso Kiselkov. All rights reserved. +find_files "s.*" usr/src/common/crypto/edonr find_files "s.*" usr/src/common/crypto/md4 find_files "s.*" usr/src/common/crypto/md5 find_files "s.*" usr/src/common/crypto/sha1 find_files "s.*" usr/src/common/crypto/sha2 +find_files "s.*" usr/src/common/crypto/skein diff --git a/usr/src/lib/libmd/sparc/Makefile b/usr/src/lib/libmd/sparc/Makefile index 5f491cc9af..8260480325 100644 --- a/usr/src/lib/libmd/sparc/Makefile +++ b/usr/src/lib/libmd/sparc/Makefile @@ -20,12 +20,14 @@ # # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2013 Saso Kiselkov. All rights reserved. # LIBRARY = libmd.a VERS = .1 -OBJECTS = md4.o md5.o sha1.o sha2.o +OBJECTS = edonr.o md4.o md5.o sha1.o sha2.o \ + skein.o skein_block.o skein_iv.o include $(SRC)/lib/Makefile.lib include $(SRC)/lib/Makefile.rootfs diff --git a/usr/src/lib/libmd/sparcv9/Makefile b/usr/src/lib/libmd/sparcv9/Makefile index 5dd3f2eac3..a57dcf95f8 100644 --- a/usr/src/lib/libmd/sparcv9/Makefile +++ b/usr/src/lib/libmd/sparcv9/Makefile @@ -20,12 +20,14 @@ # # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2013 Saso Kiselkov. All rights reserved. # LIBRARY = libmd.a VERS = .1 -OBJECTS = md4.o md5.o sha1.o sha2.o +OBJECTS = edonr.o md4.o md5.o sha1.o sha2.o \ + skein.o skein_block.o skein_iv.o include $(SRC)/lib/Makefile.lib include $(SRC)/lib/Makefile.rootfs diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c index f240b6494f..633850d316 100644 --- a/usr/src/lib/libzfs/common/libzfs_dataset.c +++ b/usr/src/lib/libzfs/common/libzfs_dataset.c @@ -1468,6 +1468,12 @@ zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err, "property setting is not allowed on " "bootable datasets")); (void) zfs_error(hdl, EZFS_NOTSUP, errbuf); + } else if (prop == ZFS_PROP_CHECKSUM || + prop == ZFS_PROP_DEDUP) { + (void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "property setting is not allowed on " + "root pools")); + (void) zfs_error(hdl, EZFS_NOTSUP, errbuf); } else { (void) zfs_standard_error(hdl, err, errbuf); } diff --git a/usr/src/man/man1m/bootadm.1m b/usr/src/man/man1m/bootadm.1m index db51b33f58..a227e23232 100644 --- a/usr/src/man/man1m/bootadm.1m +++ b/usr/src/man/man1m/bootadm.1m @@ -3,7 +3,8 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH BOOTADM 1M "Apr 25, 2008" +.\" Copyright (c) 2015 Toomas Soome <tsoome@me.com> +.TH BOOTADM 1M "Jul 26, 2015" .SH NAME bootadm \- manage bootability of GRUB-enabled operating system .SH SYNOPSIS @@ -19,6 +20,11 @@ bootadm \- manage bootability of GRUB-enabled operating system .LP .nf +\fB/sbin/bootadm\fR install-bootloader [\fB-Mfv\fR] [\fB-R\fR \fIaltroot\fR] [\fB-P\fR \fIpool\fR] +.fi + +.LP +.nf x86 only .fi @@ -33,7 +39,6 @@ bootadm \- manage bootability of GRUB-enabled operating system .fi .SH DESCRIPTION -.sp .LP The \fBbootadm\fR command manages the boot archive and, with x86 boot environments, the GRUB (GRand Unified Bootloader) menu. The @@ -43,6 +48,18 @@ as a preventative measure or as part of a recovery procedure. The default boot entry in the GRUB menu. .sp .LP +The \fBinstall-bootloader\fR subcommand installs the system boot loader on a +ZFS pool. If ZFS pool was not specified with the \fB-P\fR option, then the boot +loader is installed on the ZFS pool that the system booted from. If the +system did not boot from a ZFS pool (for example, it booted an installer via PXE +or CD-ROM) then the \fB-P\fR option is required. +.sp +This subcommand can be used to install, update, and repair the boot loader on a +ZFS pool intended for booting. When disks in the ZFS pool used for booting the +system have been replaced, one should run \fBbootadm install-bootloader\fR to +ensure that all disks in that pool have the system boot loader installed. +.sp +.LP The \fBlist-menu\fR subcommand displays the location of the GRUB menu and the current GRUB menu entries. While the typical location of the GRUB menu is \fB/boot/grub/menu.lst\fR, depending on the install method used the active GRUB @@ -59,7 +76,6 @@ The \fBbootadm\fR command determines dynamically the options supported by the image to be managed, so that \fBbootadm\fR invoked on one platform can be used to manage diskless clients of a different platform type. .SH SUBCOMMANDS -.sp .LP The \fBbootadm\fR command has the following subcommands: .sp @@ -87,6 +103,40 @@ both SPARC and x86 platforms. .sp .ne 2 .na +\fB\fBinstall-bootloader\fR\fR +.ad +.sp .6 +.RS 4n +Applies platform specific method to install the system boot loader to the disks +that are part of the selected ZFS pool (either specified with \fB-P\fR or +the default). +.sp +On SPARC, the boot loader is installed in the boot area of the disk partition +used by the ZFS pool. +.sp +On x86, disks are formatted using either \fBMBR Partitioning\fR (Master Boot +Record) or using \fBGPT Partitioning\fR (GUID Partition Tables). The first +sector on the disk that is used by the \fBBIOS\fR to find a boot loader +is referred to as the \fBMBR\fR (Master Boot Record) and is always used +regardless of the partition scheme. +.sp +On x86, disks in a ZFS pool may be a combination of either type of partitioning +scheme. If an entire disk was added to a ZFS pool (e.g. c0t0d0), then it was +formatted with \fBGPT\fR partitioning and the fact is recorded. The +\fBinstall-bootloader\fR subcommand will always update the system boot loader on +the disks. However, unless the entire disk was given a ZFS pool or the \fB-M\fR +option is specified, the \fBMBR\fR of the disk will not updated, as the system +cannot guarantee that the \fBMBR\fR belongs to it. If, for example, the system +was being dual booted, a different initial boot loader may be installed there. +.sp +When \fBGRUB\fR is being used as the system boot loader (currently on x86), to +reinstall the boot loader on some or all of the disks, the \fB-f\fR option must +be passed to the \fBinstall-bootloader\fR subcommand. +.RE + +.sp +.ne 2 +.na \fB\fBset-menu\fR\fR .ad .sp .6 @@ -109,17 +159,17 @@ title of each entry. Applies to x86 platforms only. .RE .SH OPTIONS -.sp .LP The \fBbootadm\fR command has the following options: .sp .ne 2 .na -\fB\fB-v\fR\fR +\fB\fB-f\fR\fR .ad .sp .6 .RS 4n -In an \fBupdate-archive\fR operation, stale files are displayed on stderr. +In an \fBinstall-bootloader\fR operation, override boot loader versioning +constraints. .RE .sp @@ -150,11 +200,55 @@ than the server. Platform must be one of \fBi86pc\fR, \fBsun4u\fR, or .sp .ne 2 .na +\fB\fB-v\fR\fR +.ad +.sp .6 +.RS 4n +In an \fBupdate-archive\fR operation, stale files are displayed on stderr. +.sp +In an \fBinstall-bootloader\fR operation, display any output from tasks +performed. +.RE + +.sp +.ne 2 +.na +\fB\fB-M\fR\fR +.ad +.sp .6 +.RS 4n +On x86 systems, in an \fBinstall-bootloader\fR operation, additionally installs +the system boot loader to the \fBMBR\fR (master boot record). For more +information, see the discussion of \fBinstall-bootloader\fR in the +\fBSUBCOMMANDS\fR section. +.sp +This option is not supported on non-x86 systems, and it is an error to specify +it. +.RE + +.sp +.ne 2 +.na +\fB-P\fR\ \fIpool\fR +.ad +.sp .6 +.RS 4n +In an \fBinstall-bootloader\fR operation, the boot loader is installed on +the disks in the ZFS pool \fIpool\fR. If the \fB-P\fR option is not specified, +then the boot loader is installed on the ZFS pool that the system booted from. +If the system did not boot from a ZFS pool then the \fB-P\fR option is required. +.RE + +.sp +.ne 2 +.na \fB\fB-R\fR\ \fIaltroot\fR\fR .ad .sp .6 .RS 4n -Operation is applied to an alternate root path. +Operation is applied to an alternate root path. In an \fBinstall-bootloader\fR +operation, the boot loader is still installed on the specified pool; however, +the boot loader itself will come from the alternate root. .LP Note - .sp @@ -307,7 +401,6 @@ mounted. To access the GRUB menu, mount the device and access the GRUB menu at \fB\fI<mountpoint>\fR/boot/grub/menu.lst\fR. .SH EXIT STATUS -.sp .LP The following exit values are returned: .sp @@ -331,7 +424,6 @@ The command exited due to an error. .RE .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -347,9 +439,9 @@ Interface Stability Committed .TE .SH SEE ALSO -.sp .LP -\fBboot\fR(1M), \fBinstallgrub\fR(1M), \fBattributes\fR(5) +\fBboot\fR(1M), \fBbeadm\fR(1M), \fBinstallgrub\fR(1M), \fBinstallboot\fR(1M), +\fBattributes\fR(5) .sp .LP Consult the GRUB home page, under: diff --git a/usr/src/man/man1m/zfs.1m b/usr/src/man/man1m/zfs.1m index 6ccfa39f86..b027027558 100644 --- a/usr/src/man/man1m/zfs.1m +++ b/usr/src/man/man1m/zfs.1m @@ -908,7 +908,8 @@ command. This property is not inherited. .It Xo .Sy checksum Ns = Ns Sy on Ns | Ns Sy off Ns | Ns Sy fletcher2 Ns | Ns -.Sy fletcher4 Ns | Ns Sy sha256 Ns | Ns Sy noparity +.Sy fletcher4 Ns | Ns Sy sha256 Ns | Ns Sy noparity Ns | Ns +.Sy sha512 Ns | Ns Sy skein Ns | Ns Sy edonr .Xc Controls the checksum used to verify data integrity. The default value is .Sy on , @@ -927,6 +928,16 @@ should not be used by any other dataset. Disabling checksums is .Sy NOT a recommended practice. .Pp +The +.Sy sha512 , +.Sy skein , +and +.Sy edonr +checksum algorithms require enabling the appropriate features on the +pool. Please see +.Xr zpool-features 5 +for more information on these algorithms. +.Pp Changing this property affects only newly-written data. .It Xo .Sy compression Ns = Ns Sy on Ns | Ns Sy off Ns | Ns Sy gzip Ns | Ns diff --git a/usr/src/man/man5/zpool-features.5 b/usr/src/man/man5/zpool-features.5 index fbefb37b80..a80fc3479e 100644 --- a/usr/src/man/man5/zpool-features.5 +++ b/usr/src/man/man5/zpool-features.5 @@ -1,5 +1,5 @@ '\" te -.\" Copyright (c) 2013 by Delphix. All rights reserved. +.\" Copyright (c) 2012, 2015 by Delphix. All rights reserved. .\" Copyright (c) 2013 by Saso Kiselkov. All rights reserved. .\" Copyright (c) 2014, Joyent, Inc. All rights reserved. .\" The contents of this file are subject to the terms of the Common Development @@ -444,5 +444,114 @@ set larger than 128KB, and will return to being \fBenabled\fR once all filesystems that have ever had their recordsize larger than 128KB are destroyed. .RE +.sp +.ne 2 +.na +\fB\fBsha512\fR\fR +.ad +.RS 4n +.TS +l l . +GUID org.illumos:sha512 +READ\-ONLY COMPATIBLE no +DEPENDENCIES none +.TE + +This feature enables the use of the SHA-512/256 truncated hash algorithm +(FIPS 180-4) for checksum and dedup. The native 64-bit arithmetic of +SHA-512 provides an approximate 50% performance boost over SHA-256 on +64-bit hardware and is thus a good minimum-change replacement candidate +for systems where hash performance is important, but these systems +cannot for whatever reason utilize the faster \fBskein\fR and +\fBedonr\fR algorithms. + +When the \fBsha512\fR feature is set to \fBenabled\fR, the administrator +can turn on the \fBsha512\fR checksum on any dataset using the +\fBzfs set checksum=sha512\fR(1M) command. This feature becomes +\fBactive\fR once a \fBchecksum\fR property has been set to \fBsha512\fR, +and will return to being \fBenabled\fR once all filesystems that have +ever had their checksum set to \fBsha512\fR are destroyed. + +Booting off of pools utilizing SHA-512/256 is supported (provided that +the updated GRUB stage2 module is installed). + +.RE + +.sp +.ne 2 +.na +\fB\fBskein\fR\fR +.ad +.RS 4n +.TS +l l . +GUID org.illumos:skein +READ\-ONLY COMPATIBLE no +DEPENDENCIES none +.TE + +This feature enables the use of the Skein hash algorithm for checksum +and dedup. Skein is a high-performance secure hash algorithm that was a +finalist in the NIST SHA-3 competition. It provides a very high security +margin and high performance on 64-bit hardware (80% faster than +SHA-256). This implementation also utilizes the new salted checksumming +functionality in ZFS, which means that the checksum is pre-seeded with a +secret 256-bit random key (stored on the pool) before being fed the data +block to be checksummed. Thus the produced checksums are unique to a +given pool, preventing hash collision attacks on systems with dedup. + +When the \fBskein\fR feature is set to \fBenabled\fR, the administrator +can turn on the \fBskein\fR checksum on any dataset using the +\fBzfs set checksum=skein\fR(1M) command. This feature becomes +\fBactive\fR once a \fBchecksum\fR property has been set to \fBskein\fR, +and will return to being \fBenabled\fR once all filesystems that have +ever had their checksum set to \fBskein\fR are destroyed. + +Booting off of pools using \fBskein\fR is \fBNOT\fR supported +-- any attempt to enable \fBskein\fR on a root pool will fail with an +error. + +.RE + +.sp +.ne 2 +.na +\fB\fBedonr\fR\fR +.ad +.RS 4n +.TS +l l . +GUID org.illumos:edonr +READ\-ONLY COMPATIBLE no +DEPENDENCIES none +.TE + +This feature enables the use of the Edon-R hash algorithm for checksum, +including for nopwrite (if compression is also enabled, an overwrite of +a block whose checksum matches the data being written will be ignored). +In an abundance of caution, Edon-R can not be used with dedup +(without verification). + +Edon-R is a very high-performance hash algorithm that was part +of the NIST SHA-3 competition. It provides extremely high hash +performance (over 350% faster than SHA-256), but was not selected +because of its unsuitability as a general purpose secure hash algorithm. +This implementation utilizes the new salted checksumming functionality +in ZFS, which means that the checksum is pre-seeded with a secret +256-bit random key (stored on the pool) before being fed the data block +to be checksummed. Thus the produced checksums are unique to a given +pool. + +When the \fBedonr\fR feature is set to \fBenabled\fR, the administrator +can turn on the \fBedonr\fR checksum on any dataset using the +\fBzfs set checksum=edonr\fR(1M) command. This feature becomes +\fBactive\fR once a \fBchecksum\fR property has been set to \fBedonr\fR, +and will return to being \fBenabled\fR once all filesystems that have +ever had their checksum set to \fBedonr\fR are destroyed. + +Booting off of pools using \fBedonr\fR is \fBNOT\fR supported +-- any attempt to enable \fBedonr\fR on a root pool will fail with an +error. + .SH "SEE ALSO" \fBzpool\fR(1M) diff --git a/usr/src/pkg/manifests/system-header.mf b/usr/src/pkg/manifests/system-header.mf index 18d7611554..c095e30963 100644 --- a/usr/src/pkg/manifests/system-header.mf +++ b/usr/src/pkg/manifests/system-header.mf @@ -24,6 +24,7 @@ # Copyright (c) 2012 by Delphix. All rights reserved. # Copyright 2012 Nexenta Systems, Inc. All rights reserved. # Copyright 2014 Garrett D'Amore <garrett@damore.org> +# Copyright 2013 Saso Kiselkov. All rights reserved. # set name=pkg.fmri value=pkg:/system/header@$(PKGVERS) @@ -766,6 +767,7 @@ file path=usr/include/sharefs/sharetab.h file path=usr/include/siginfo.h file path=usr/include/signal.h file path=usr/include/sip.h +file path=usr/include/skein.h file path=usr/include/smbios.h file path=usr/include/spawn.h $(i386_ONLY)file path=usr/include/stack_unwind.h @@ -943,6 +945,7 @@ file path=usr/include/sys/ecppio.h file path=usr/include/sys/ecppreg.h file path=usr/include/sys/ecppsys.h file path=usr/include/sys/ecppvar.h +file path=usr/include/sys/edonr.h file path=usr/include/sys/efi_partition.h file path=usr/include/sys/elf.h file path=usr/include/sys/elf_386.h @@ -1428,6 +1431,7 @@ file path=usr/include/sys/shm_impl.h file path=usr/include/sys/sid.h file path=usr/include/sys/siginfo.h file path=usr/include/sys/signal.h +file path=usr/include/sys/skein.h file path=usr/include/sys/sleepq.h file path=usr/include/sys/smbios.h file path=usr/include/sys/smbios_impl.h diff --git a/usr/src/pkg/manifests/system-kernel.mf b/usr/src/pkg/manifests/system-kernel.mf index 4832229cb2..507d6355b6 100644 --- a/usr/src/pkg/manifests/system-kernel.mf +++ b/usr/src/pkg/manifests/system-kernel.mf @@ -21,6 +21,7 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2013 Saso Kiselkov. All rights reserved. # # @@ -305,22 +306,26 @@ file path=kernel/crypto/$(ARCH64)/arcfour group=sys mode=0755 file path=kernel/crypto/$(ARCH64)/blowfish group=sys mode=0755 file path=kernel/crypto/$(ARCH64)/des group=sys mode=0755 file path=kernel/crypto/$(ARCH64)/ecc group=sys mode=0755 +file path=kernel/crypto/$(ARCH64)/edonr group=sys mode=0755 file path=kernel/crypto/$(ARCH64)/md4 group=sys mode=0755 file path=kernel/crypto/$(ARCH64)/md5 group=sys mode=0755 file path=kernel/crypto/$(ARCH64)/rsa group=sys mode=0755 file path=kernel/crypto/$(ARCH64)/sha1 group=sys mode=0755 file path=kernel/crypto/$(ARCH64)/sha2 group=sys mode=0755 +file path=kernel/crypto/$(ARCH64)/skein group=sys mode=0755 file path=kernel/crypto/$(ARCH64)/swrand group=sys mode=0755 $(i386_ONLY)file path=kernel/crypto/aes group=sys mode=0755 $(i386_ONLY)file path=kernel/crypto/arcfour group=sys mode=0755 $(i386_ONLY)file path=kernel/crypto/blowfish group=sys mode=0755 $(i386_ONLY)file path=kernel/crypto/des group=sys mode=0755 $(i386_ONLY)file path=kernel/crypto/ecc group=sys mode=0755 +$(i386_ONLY)file path=kernel/crypto/edonr group=sys mode=0755 $(i386_ONLY)file path=kernel/crypto/md4 group=sys mode=0755 $(i386_ONLY)file path=kernel/crypto/md5 group=sys mode=0755 $(i386_ONLY)file path=kernel/crypto/rsa group=sys mode=0755 $(i386_ONLY)file path=kernel/crypto/sha1 group=sys mode=0755 $(i386_ONLY)file path=kernel/crypto/sha2 group=sys mode=0755 +$(i386_ONLY)file path=kernel/crypto/skein group=sys mode=0755 $(i386_ONLY)file path=kernel/crypto/swrand group=sys mode=0755 $(sparc_ONLY)file path=kernel/dacf/$(ARCH64)/consconfig_dacf group=sys \ mode=0755 @@ -822,15 +827,21 @@ $(sparc_ONLY)file path=usr/share/man/man7d/dad.7d $(i386_ONLY)file path=usr/share/man/man7d/smbios.7d # Sadly vuid mouse support is in different packages on different platforms # While kstat(7D) is in SUNWcs, the structures are general +hardlink path=kernel/misc/$(ARCH64)/edonr \ + target=../../../kernel/crypto/$(ARCH64)/edonr hardlink path=kernel/misc/$(ARCH64)/md5 \ target=../../../kernel/crypto/$(ARCH64)/md5 hardlink path=kernel/misc/$(ARCH64)/sha1 \ target=../../../kernel/crypto/$(ARCH64)/sha1 hardlink path=kernel/misc/$(ARCH64)/sha2 \ target=../../../kernel/crypto/$(ARCH64)/sha2 +hardlink path=kernel/misc/$(ARCH64)/skein \ + target=../../../kernel/crypto/$(ARCH64)/skein +$(i386_ONLY)hardlink path=kernel/misc/edonr target=../../kernel/crypto/edonr $(i386_ONLY)hardlink path=kernel/misc/md5 target=../../kernel/crypto/md5 $(i386_ONLY)hardlink path=kernel/misc/sha1 target=../../kernel/crypto/sha1 $(i386_ONLY)hardlink path=kernel/misc/sha2 target=../../kernel/crypto/sha2 +$(i386_ONLY)hardlink path=kernel/misc/skein target=../../kernel/crypto/skein hardlink path=kernel/socketmod/$(ARCH64)/icmp \ target=../../../kernel/drv/$(ARCH64)/icmp hardlink path=kernel/socketmod/$(ARCH64)/rts \ diff --git a/usr/src/pkg/manifests/system-test-zfstest.mf b/usr/src/pkg/manifests/system-test-zfstest.mf index dab3f35c90..f9818c15e4 100644 --- a/usr/src/pkg/manifests/system-test-zfstest.mf +++ b/usr/src/pkg/manifests/system-test-zfstest.mf @@ -35,6 +35,7 @@ dir path=opt/zfs-tests/tests/functional/atime dir path=opt/zfs-tests/tests/functional/bootfs dir path=opt/zfs-tests/tests/functional/cache dir path=opt/zfs-tests/tests/functional/cachefile +dir path=opt/zfs-tests/tests/functional/checksum dir path=opt/zfs-tests/tests/functional/clean_mirror dir path=opt/zfs-tests/tests/functional/cli_root dir path=opt/zfs-tests/tests/functional/cli_root/zdb @@ -328,6 +329,33 @@ file path=opt/zfs-tests/tests/functional/cachefile/cachefile_001_pos mode=0555 file path=opt/zfs-tests/tests/functional/cachefile/cachefile_002_pos mode=0555 file path=opt/zfs-tests/tests/functional/cachefile/cachefile_003_pos mode=0555 file path=opt/zfs-tests/tests/functional/cachefile/cachefile_004_pos mode=0555 +$(i386_ONLY)file path=opt/zfs-tests/tests/functional/checksum/edonr_test.amd64 \ + mode=0555 +$(i386_ONLY)file path=opt/zfs-tests/tests/functional/checksum/edonr_test.i386 \ + mode=0555 +$(sparc_ONLY)file \ + path=opt/zfs-tests/tests/functional/checksum/edonr_test.sparc mode=0555 +$(sparc_ONLY)file \ + path=opt/zfs-tests/tests/functional/checksum/edonr_test.sparcv9 mode=0555 +file path=opt/zfs-tests/tests/functional/checksum/run_edonr_test mode=0555 +file path=opt/zfs-tests/tests/functional/checksum/run_sha2_test mode=0555 +file path=opt/zfs-tests/tests/functional/checksum/run_skein_test mode=0555 +$(i386_ONLY)file path=opt/zfs-tests/tests/functional/checksum/sha2_test.amd64 \ + mode=0555 +$(i386_ONLY)file path=opt/zfs-tests/tests/functional/checksum/sha2_test.i386 \ + mode=0555 +$(sparc_ONLY)file path=opt/zfs-tests/tests/functional/checksum/sha2_test.sparc \ + mode=0555 +$(sparc_ONLY)file \ + path=opt/zfs-tests/tests/functional/checksum/sha2_test.sparcv9 mode=0555 +$(i386_ONLY)file path=opt/zfs-tests/tests/functional/checksum/skein_test.amd64 \ + mode=0555 +$(i386_ONLY)file path=opt/zfs-tests/tests/functional/checksum/skein_test.i386 \ + mode=0555 +$(sparc_ONLY)file \ + path=opt/zfs-tests/tests/functional/checksum/skein_test.sparc mode=0555 +$(sparc_ONLY)file \ + path=opt/zfs-tests/tests/functional/checksum/skein_test.sparcv9 mode=0555 file path=opt/zfs-tests/tests/functional/clean_mirror/clean_mirror_001_pos \ mode=0555 file path=opt/zfs-tests/tests/functional/clean_mirror/clean_mirror_002_pos \ diff --git a/usr/src/test/zfs-tests/include/libtest.shlib b/usr/src/test/zfs-tests/include/libtest.shlib index 7c25516d51..96aa5c1189 100644 --- a/usr/src/test/zfs-tests/include/libtest.shlib +++ b/usr/src/test/zfs-tests/include/libtest.shlib @@ -2576,6 +2576,11 @@ function is_mp (($($PSRINFO | $WC -l) > 1)) } +function get_cpu_freq +{ + $PSRINFO -v 0 | $AWK '/processor operates at/ {print $6}' +} + # Run the given command as the user provided. function user_run { diff --git a/usr/src/test/zfs-tests/runfiles/delphix.run b/usr/src/test/zfs-tests/runfiles/delphix.run index c98ed9f888..0ab2739792 100644 --- a/usr/src/test/zfs-tests/runfiles/delphix.run +++ b/usr/src/test/zfs-tests/runfiles/delphix.run @@ -72,6 +72,11 @@ tests = ['cachefile_001_pos', 'cachefile_002_pos', 'cachefile_003_pos', pre = post = +[/opt/zfs-tests/tests/functional/checksum] +tests = ['run_edonr_test', 'run_sha2_test', 'run_skein_test'] +pre = +post = + [/opt/zfs-tests/tests/functional/clean_mirror] tests = [ 'clean_mirror_001_pos', 'clean_mirror_002_pos', 'clean_mirror_003_pos', 'clean_mirror_004_pos'] diff --git a/usr/src/test/zfs-tests/runfiles/omnios.run b/usr/src/test/zfs-tests/runfiles/omnios.run index 8908515500..f19c83f10d 100644 --- a/usr/src/test/zfs-tests/runfiles/omnios.run +++ b/usr/src/test/zfs-tests/runfiles/omnios.run @@ -10,7 +10,7 @@ # # -# Copyright (c) 2013 by Delphix. All rights reserved. +# Copyright (c) 2013, 2015 by Delphix. All rights reserved. # [DEFAULT] @@ -72,6 +72,11 @@ tests = ['cachefile_001_pos', 'cachefile_002_pos', 'cachefile_003_pos', pre = post = +[/opt/zfs-tests/tests/functional/checksum] +tests = ['run_edonr_test', 'run_sha2_test', 'run_skein_test'] +pre = +post = + [/opt/zfs-tests/tests/functional/clean_mirror] tests = [ 'clean_mirror_001_pos', 'clean_mirror_002_pos', 'clean_mirror_003_pos', 'clean_mirror_004_pos'] diff --git a/usr/src/test/zfs-tests/runfiles/openindiana.run b/usr/src/test/zfs-tests/runfiles/openindiana.run index 8908515500..f525b7297e 100644 --- a/usr/src/test/zfs-tests/runfiles/openindiana.run +++ b/usr/src/test/zfs-tests/runfiles/openindiana.run @@ -10,7 +10,7 @@ # # -# Copyright (c) 2013 by Delphix. All rights reserved. +# Copyright (c) 2012, 2015 by Delphix. All rights reserved. # [DEFAULT] @@ -72,6 +72,11 @@ tests = ['cachefile_001_pos', 'cachefile_002_pos', 'cachefile_003_pos', pre = post = +[/opt/zfs-tests/tests/functional/checksum] +tests = ['run_edonr_test', 'run_sha2_test', 'run_skein_test'] +pre = +post = + [/opt/zfs-tests/tests/functional/clean_mirror] tests = [ 'clean_mirror_001_pos', 'clean_mirror_002_pos', 'clean_mirror_003_pos', 'clean_mirror_004_pos'] diff --git a/usr/src/test/zfs-tests/tests/functional/Makefile b/usr/src/test/zfs-tests/tests/functional/Makefile index 65838aba43..c3561926fd 100644 --- a/usr/src/test/zfs-tests/tests/functional/Makefile +++ b/usr/src/test/zfs-tests/tests/functional/Makefile @@ -11,7 +11,7 @@ # # -# Copyright (c) 2013, 2014 by Delphix. All rights reserved. +# Copyright (c) 2013, 2015 by Delphix. All rights reserved. # .PARALLEL: $(SUBDIRS) @@ -21,6 +21,7 @@ SUBDIRS = acl \ bootfs \ cache \ cachefile \ + checksum \ clean_mirror \ cli_root \ cli_user \ diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/Makefile b/usr/src/test/zfs-tests/tests/functional/checksum/Makefile new file mode 100644 index 0000000000..8182cab0b9 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/Makefile @@ -0,0 +1,49 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +.PARALLEL: $(SUBDIRS) + +include $(SRC)/Makefile.master + +ROOTOPTPKG = $(ROOT)/opt/zfs-tests +TESTDIR = $(ROOTOPTPKG)/tests/functional/checksum + +SCRIPTS = run_edonr_test \ + run_sha2_test \ + run_skein_test + +CMDS = $(SCRIPTS:%=$(TESTDIR)/%) +$(CMDS) := FILEMODE = 0555 + +all lint clean clobber: + +install: $(CMDS) + +$(CMDS): $(TESTDIR) + +$(TESTDIR): + $(INS.dir) + +$(TESTDIR)/%: % + $(INS.file) + +$(TESTDIR)/%: %.ksh + $(INS.rename) + +SUBDIRS = edonr \ + sha2 \ + skein + +include $(SRC)/test/Makefile.com diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/Makefile.subdirs b/usr/src/test/zfs-tests/tests/functional/checksum/Makefile.subdirs new file mode 100644 index 0000000000..9064aabbdb --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/Makefile.subdirs @@ -0,0 +1,57 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +include $(SRC)/cmd/Makefile.cmd + +ROOTOPTPKG = $(ROOT)/opt/zfs-tests +TESTDIR = $(ROOTOPTPKG)/tests/functional/checksum + +OBJS = $(PROG:%=%.o) +SRCS = $(OBJS:%.o=../%.c) + +CMD32 = $(PROG:%=$(TESTDIR)/%.$(MACH)) +CMD64 = $(PROG:%=$(TESTDIR)/%.$(MACH64)) +CMDS = $(CMD32) $(CMD64) +$(CMDS) := FILEMODE = 0555 + +C99MODE = -xc99=%all +CFLAGS = -I $(SRC)/uts/common -D_KERNEL +LDLIBS += -lmd +LINTFLAGS += -u +LINTFLAGS64 += -u + +all: $(PROG) $(TESTDIR) + +lint: lint_SRCS + +clobber: clean + +clean: + $(RM) $(PROG) + +include $(SRC)/cmd/Makefile.targ + +$(TESTDIR): + $(INS.dir) + +$(TESTDIR)/%.$(MACH): % + $(INS.rename) + +$(TESTDIR)/%.$(MACH64): % + $(INS.rename) + +%: ../%.c + $(LINK.c) -o $@ $< $(LDLIBS) + $(POST_PROCESS) diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/edonr/Makefile b/usr/src/test/zfs-tests/tests/functional/checksum/edonr/Makefile new file mode 100644 index 0000000000..e81deeab71 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/edonr/Makefile @@ -0,0 +1,29 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +include $(SRC)/Makefile.master +include $(SRC)/test/Makefile.com + +SUBDIRS = $(MACH) +$(BUILD64) SUBDIRS += $(MACH64) + +all: $(SUBDIRS) + +clean clobber lint: $(SUBDIRS) + +install: $(SUBDIRS) + +$(SUBDIRS): + @cd $@; pwd; $(MAKE) $(TARGET) diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/edonr/amd64/Makefile b/usr/src/test/zfs-tests/tests/functional/checksum/edonr/amd64/Makefile new file mode 100644 index 0000000000..9e72bca9b9 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/edonr/amd64/Makefile @@ -0,0 +1,20 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +PROG=edonr_test +include ../../Makefile.subdirs +include $(SRC)/cmd/Makefile.cmd.64 + +install: all $(CMD64) diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/edonr/edonr_test.c b/usr/src/test/zfs-tests/tests/functional/checksum/edonr/edonr_test.c new file mode 100644 index 0000000000..eb13930f12 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/edonr/edonr_test.c @@ -0,0 +1,217 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2013 Saso Kiselkov. All rights reserved. + */ + +/* + * This is just to keep the compiler happy about sys/time.h not declaring + * gettimeofday due to -D_KERNEL (we can do this since we're actually + * running in userspace, but we need -D_KERNEL for the remaining Edon-R code). + */ +#ifdef _KERNEL +#undef _KERNEL +#endif + +#include <sys/edonr.h> +#include <stdlib.h> +#include <strings.h> +#include <stdio.h> +#include <sys/time.h> +#include <note.h> + +/* + * Test messages from: + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf + */ +const char *test_msg0 = "abc"; +const char *test_msg1 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmn" + "lmnomnopnopq"; +const char *test_msg2 = "abcdefghbcdefghicdefghijdefghijkefghijklfghi" + "jklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; + +/* + * Test digests computed by hand. There's no formal standard or spec for edonr. + */ +const uint8_t edonr_224_test_digests[][28] = { + { + /* for test_msg0 */ + 0x56, 0x63, 0xc4, 0x93, 0x95, 0x20, 0xfa, 0xf6, + 0x12, 0x31, 0x65, 0xa4, 0x66, 0xf2, 0x56, 0x01, + 0x95, 0x2e, 0xa9, 0xe4, 0x24, 0xdd, 0xc9, 0x6b, + 0xef, 0xd0, 0x40, 0x94 + }, + { + /* for test_msg1 */ + 0xd0, 0x13, 0xe4, 0x87, 0x4d, 0x06, 0x8d, 0xca, + 0x4e, 0x14, 0xb9, 0x37, 0x2f, 0xce, 0x12, 0x20, + 0x60, 0xf8, 0x5c, 0x0a, 0xfd, 0x7a, 0x7d, 0x97, + 0x88, 0x2b, 0x05, 0x75 + } + /* no test vector for test_msg2 */ +}; + +const uint8_t edonr_256_test_digests[][32] = { + { + /* for test_msg0 */ + 0x54, 0xd7, 0x8b, 0x13, 0xc7, 0x4e, 0xda, 0x5a, + 0xed, 0xc2, 0x71, 0xcc, 0x88, 0x1f, 0xb2, 0x2f, + 0x83, 0x99, 0xaf, 0xd3, 0x04, 0x0b, 0x6a, 0x39, + 0x2d, 0x73, 0x94, 0x05, 0x50, 0x8d, 0xd8, 0x51 + }, + { + /* for test_msg1 */ + 0x49, 0x2d, 0x0b, 0x19, 0xab, 0x1e, 0xde, 0x3a, + 0xea, 0x9b, 0xf2, 0x39, 0x3a, 0xb1, 0x21, 0xde, + 0x21, 0xf6, 0x80, 0x1f, 0xad, 0xbe, 0x8b, 0x07, + 0xc7, 0xfb, 0xe6, 0x99, 0x0e, 0x4d, 0x73, 0x63 + } + /* no test vectorfor test_msg2 */ +}; + +const uint8_t edonr_384_test_digests[][48] = { + { + /* for test_msg0 */ + 0x0e, 0x7c, 0xd7, 0x85, 0x78, 0x77, 0xe0, 0x89, + 0x5b, 0x1c, 0xdf, 0x49, 0xf4, 0x1d, 0x20, 0x9c, + 0x72, 0x7d, 0x2e, 0x57, 0x9b, 0x9b, 0x9a, 0xdc, + 0x60, 0x27, 0x97, 0x82, 0xb9, 0x90, 0x72, 0xec, + 0x7e, 0xce, 0xd3, 0x16, 0x5f, 0x47, 0x75, 0x48, + 0xfa, 0x60, 0x72, 0x7e, 0x01, 0xc7, 0x7c, 0xc6 + }, + { + /* no test vector for test_msg1 */ + NULL + }, + { + /* for test_msg2 */ + 0xe2, 0x34, 0xa1, 0x02, 0x83, 0x76, 0xae, 0xe6, + 0x82, 0xd9, 0x38, 0x32, 0x0e, 0x00, 0x78, 0xd2, + 0x34, 0xdb, 0xb9, 0xbd, 0xf0, 0x08, 0xa8, 0x0f, + 0x63, 0x1c, 0x3d, 0x4a, 0xfd, 0x0a, 0xe9, 0x59, + 0xdc, 0xd4, 0xce, 0xcd, 0x8d, 0x67, 0x6c, 0xea, + 0xbb, 0x1a, 0x32, 0xed, 0x5c, 0x6b, 0xf1, 0x7f + } +}; + +const uint8_t edonr_512_test_digests[][64] = { + { + /* for test_msg0 */ + 0x1b, 0x14, 0xdb, 0x15, 0x5f, 0x1d, 0x40, 0x65, + 0x94, 0xb8, 0xce, 0xf7, 0x0a, 0x43, 0x62, 0xec, + 0x6b, 0x5d, 0xe6, 0xa5, 0xda, 0xf5, 0x0e, 0xc9, + 0x99, 0xe9, 0x87, 0xc1, 0x9d, 0x30, 0x49, 0xe2, + 0xde, 0x59, 0x77, 0xbb, 0x05, 0xb1, 0xbb, 0x22, + 0x00, 0x50, 0xa1, 0xea, 0x5b, 0x46, 0xa9, 0xf1, + 0x74, 0x0a, 0xca, 0xfb, 0xf6, 0xb4, 0x50, 0x32, + 0xad, 0xc9, 0x0c, 0x62, 0x83, 0x72, 0xc2, 0x2b + }, + { + /* no test vector for test_msg1 */ + NULL + }, + { + /* for test_msg2 */ + 0x53, 0x51, 0x07, 0x0d, 0xc5, 0x1c, 0x3b, 0x2b, + 0xac, 0xa5, 0xa6, 0x0d, 0x02, 0x52, 0xcc, 0xb4, + 0xe4, 0x92, 0x1a, 0x96, 0xfe, 0x5a, 0x69, 0xe7, + 0x6d, 0xad, 0x48, 0xfd, 0x21, 0xa0, 0x84, 0x5a, + 0xd5, 0x7f, 0x88, 0x0b, 0x3e, 0x4a, 0x90, 0x7b, + 0xc5, 0x03, 0x15, 0x18, 0x42, 0xbb, 0x94, 0x9e, + 0x1c, 0xba, 0x74, 0x39, 0xa6, 0x40, 0x9a, 0x34, + 0xb8, 0x43, 0x6c, 0xb4, 0x69, 0x21, 0x58, 0x3c + } +}; + +int +main(int argc, char *argv[]) +{ + boolean_t failed = B_FALSE; + uint64_t cpu_mhz = 0; + + if (argc == 2) + cpu_mhz = atoi(argv[1]); + +#define EDONR_ALGO_TEST(_m, mode, testdigest) \ + do { \ + EdonRState ctx; \ + uint8_t digest[mode / 8]; \ + EdonRInit(&ctx, mode); \ + EdonRUpdate(&ctx, (const uint8_t *) _m, strlen(_m) * 8);\ + EdonRFinal(&ctx, digest); \ + (void) printf("Edon-R-%-6sMessage: " #_m \ + "\tResult: ", #mode); \ + if (bcmp(digest, testdigest, mode / 8) == 0) { \ + (void) printf("OK\n"); \ + } else { \ + (void) printf("FAILED!\n"); \ + failed = B_TRUE; \ + } \ + NOTE(CONSTCOND) \ + } while (0) + +#define EDONR_PERF_TEST(mode) \ + do { \ + EdonRState ctx; \ + uint8_t digest[mode / 8]; \ + uint8_t block[131072]; \ + uint64_t delta; \ + double cpb = 0; \ + int i; \ + struct timeval start, end; \ + bzero(block, sizeof (block)); \ + (void) gettimeofday(&start, NULL); \ + EdonRInit(&ctx, mode); \ + for (i = 0; i < 8192; i++) \ + EdonRUpdate(&ctx, block, sizeof (block) * 8); \ + EdonRFinal(&ctx, digest); \ + (void) gettimeofday(&end, NULL); \ + delta = (end.tv_sec * 1000000llu + end.tv_usec) - \ + (start.tv_sec * 1000000llu + start.tv_usec); \ + if (cpu_mhz != 0) { \ + cpb = (cpu_mhz * 1e6 * ((double)delta / \ + 1000000)) / (8192 * 128 * 1024); \ + } \ + (void) printf("Edon-R-%-6s%llu us (%.02f CPB)\n", #mode,\ + (u_longlong_t)delta, cpb); \ + NOTE(CONSTCOND) \ + } while (0) + + (void) printf("Running algorithm correctness tests:\n"); + EDONR_ALGO_TEST(test_msg0, 224, edonr_224_test_digests[0]); + EDONR_ALGO_TEST(test_msg1, 224, edonr_224_test_digests[1]); + EDONR_ALGO_TEST(test_msg0, 256, edonr_256_test_digests[0]); + EDONR_ALGO_TEST(test_msg1, 256, edonr_256_test_digests[1]); + EDONR_ALGO_TEST(test_msg0, 384, edonr_384_test_digests[0]); + EDONR_ALGO_TEST(test_msg2, 384, edonr_384_test_digests[2]); + EDONR_ALGO_TEST(test_msg0, 512, edonr_512_test_digests[0]); + EDONR_ALGO_TEST(test_msg2, 512, edonr_512_test_digests[2]); + if (failed) + return (1); + + (void) printf("Running performance tests (hashing 1024 MiB of " + "data):\n"); + EDONR_PERF_TEST(256); + EDONR_PERF_TEST(512); + + return (0); +} diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/edonr/i386/Makefile b/usr/src/test/zfs-tests/tests/functional/checksum/edonr/i386/Makefile new file mode 100644 index 0000000000..9b3ee25a05 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/edonr/i386/Makefile @@ -0,0 +1,19 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +PROG=edonr_test +include ../../Makefile.subdirs + +install: all $(CMD32) diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/edonr/sparc/Makefile b/usr/src/test/zfs-tests/tests/functional/checksum/edonr/sparc/Makefile new file mode 100644 index 0000000000..9b3ee25a05 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/edonr/sparc/Makefile @@ -0,0 +1,19 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +PROG=edonr_test +include ../../Makefile.subdirs + +install: all $(CMD32) diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/edonr/sparcv9/Makefile b/usr/src/test/zfs-tests/tests/functional/checksum/edonr/sparcv9/Makefile new file mode 100644 index 0000000000..9e72bca9b9 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/edonr/sparcv9/Makefile @@ -0,0 +1,20 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +PROG=edonr_test +include ../../Makefile.subdirs +include $(SRC)/cmd/Makefile.cmd.64 + +install: all $(CMD64) diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/run_edonr_test.ksh b/usr/src/test/zfs-tests/tests/functional/checksum/run_edonr_test.ksh new file mode 100644 index 0000000000..54ea27158e --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/run_edonr_test.ksh @@ -0,0 +1,32 @@ +#!/usr/bin/ksh + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# Run the tests for the EdonR hash algorithm. +# + +log_assert "Run the tests for the EdonR hash algorithm." + +freq=$(get_cpu_freq) +for isa in $($ISAINFO); do + log_must $STF_SUITE/tests/functional/checksum/edonr_test.$isa $freq +done + +log_pass "EdonR tests passed." diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/run_sha2_test.ksh b/usr/src/test/zfs-tests/tests/functional/checksum/run_sha2_test.ksh new file mode 100644 index 0000000000..7ebe897010 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/run_sha2_test.ksh @@ -0,0 +1,32 @@ +#!/usr/bin/ksh + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# Run the tests for the SHA-2 hash algorithm. +# + +log_assert "Run the tests for the SHA-2 hash algorithm." + +freq=$(get_cpu_freq) +for isa in $($ISAINFO); do + log_must $STF_SUITE/tests/functional/checksum/sha2_test.$isa $freq +done + +log_pass "SHA-2 tests passed." diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/run_skein_test.ksh b/usr/src/test/zfs-tests/tests/functional/checksum/run_skein_test.ksh new file mode 100644 index 0000000000..4ca9e1a60a --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/run_skein_test.ksh @@ -0,0 +1,32 @@ +#!/usr/bin/ksh + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# Run the tests for the Skein hash algorithm. +# + +log_assert "Run the tests for the Skein hash algorithm." + +freq=$(get_cpu_freq) +for isa in $($ISAINFO); do + log_must $STF_SUITE/tests/functional/checksum/skein_test.$isa $freq +done + +log_pass "Skein tests passed." diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/sha2/Makefile b/usr/src/test/zfs-tests/tests/functional/checksum/sha2/Makefile new file mode 100644 index 0000000000..e81deeab71 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/sha2/Makefile @@ -0,0 +1,29 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +include $(SRC)/Makefile.master +include $(SRC)/test/Makefile.com + +SUBDIRS = $(MACH) +$(BUILD64) SUBDIRS += $(MACH64) + +all: $(SUBDIRS) + +clean clobber lint: $(SUBDIRS) + +install: $(SUBDIRS) + +$(SUBDIRS): + @cd $@; pwd; $(MAKE) $(TARGET) diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/sha2/amd64/Makefile b/usr/src/test/zfs-tests/tests/functional/checksum/sha2/amd64/Makefile new file mode 100644 index 0000000000..ee81ed97d7 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/sha2/amd64/Makefile @@ -0,0 +1,20 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +PROG=sha2_test +include ../../Makefile.subdirs +include $(SRC)/cmd/Makefile.cmd.64 + +install: all $(CMD64) diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/sha2/i386/Makefile b/usr/src/test/zfs-tests/tests/functional/checksum/sha2/i386/Makefile new file mode 100644 index 0000000000..41b7f0741a --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/sha2/i386/Makefile @@ -0,0 +1,19 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +PROG=sha2_test +include ../../Makefile.subdirs + +install: all $(CMD32) diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/sha2/sha2_test.c b/usr/src/test/zfs-tests/tests/functional/checksum/sha2/sha2_test.c new file mode 100644 index 0000000000..59992e3732 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/sha2/sha2_test.c @@ -0,0 +1,262 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2013 Saso Kiselkov. All rights reserved. + */ + +/* + * This is just to keep the compiler happy about sys/time.h not declaring + * gettimeofday due to -D_KERNEL (we can do this since we're actually + * running in userspace, but we need -D_KERNEL for the remaining SHA2 code). + */ +#ifdef _KERNEL +#undef _KERNEL +#endif + +#include <sys/varargs.h> +#include <stdlib.h> +#include <strings.h> +#include <stdio.h> +#include <sys/time.h> +#define _SHA2_IMPL +#include <sys/sha2.h> +#include <note.h> + +/* + * Test messages from: + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf + */ + +const char *test_msg0 = "abc"; +const char *test_msg1 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmn" + "lmnomnopnopq"; +const char *test_msg2 = "abcdefghbcdefghicdefghijdefghijkefghijklfghi" + "jklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; + +/* + * Test digests from: + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf + */ +const uint8_t sha256_test_digests[][32] = { + { + /* for test_msg0 */ + 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD + }, + { + /* for test_msg1 */ + 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, + 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, + 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, + 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 + } + /* no test vector for test_msg2 */ +}; + +const uint8_t sha384_test_digests[][48] = { + { + /* for test_msg0 */ + 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, + 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, + 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, + 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, + 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, + 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 + }, + { + /* no test vector for test_msg1 */ + NULL + }, + { + /* for test_msg2 */ + 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, + 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, + 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, + 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, + 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, + 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 + } +}; + +const uint8_t sha512_test_digests[][64] = { + { + /* for test_msg0 */ + 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, + 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, + 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, + 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, + 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, + 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, + 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, + 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F + }, + { + /* no test vector for test_msg1 */ + NULL + }, + { + /* for test_msg2 */ + 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, + 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, + 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, + 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, + 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, + 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, + 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, + 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 + } +}; + +const uint8_t sha512_224_test_digests[][28] = { + { + /* for test_msg0 */ + 0x46, 0x34, 0x27, 0x0F, 0x70, 0x7B, 0x6A, 0x54, + 0xDA, 0xAE, 0x75, 0x30, 0x46, 0x08, 0x42, 0xE2, + 0x0E, 0x37, 0xED, 0x26, 0x5C, 0xEE, 0xE9, 0xA4, + 0x3E, 0x89, 0x24, 0xAA + }, + { + /* no test vector for test_msg1 */ + NULL + }, + { + /* for test_msg2 */ + 0x23, 0xFE, 0xC5, 0xBB, 0x94, 0xD6, 0x0B, 0x23, + 0x30, 0x81, 0x92, 0x64, 0x0B, 0x0C, 0x45, 0x33, + 0x35, 0xD6, 0x64, 0x73, 0x4F, 0xE4, 0x0E, 0x72, + 0x68, 0x67, 0x4A, 0xF9 + } +}; + +const uint8_t sha512_256_test_digests[][32] = { + { + /* for test_msg0 */ + 0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9, + 0x9B, 0x2E, 0x29, 0xB7, 0x6B, 0x4C, 0x7D, 0xAB, + 0xE4, 0xC2, 0xD0, 0xC6, 0x34, 0xFC, 0x6D, 0x46, + 0xE0, 0xE2, 0xF1, 0x31, 0x07, 0xE7, 0xAF, 0x23 + }, + { + /* no test vector for test_msg1 */ + NULL + }, + { + /* for test_msg2 */ + 0x39, 0x28, 0xE1, 0x84, 0xFB, 0x86, 0x90, 0xF8, + 0x40, 0xDA, 0x39, 0x88, 0x12, 0x1D, 0x31, 0xBE, + 0x65, 0xCB, 0x9D, 0x3E, 0xF8, 0x3E, 0xE6, 0x14, + 0x6F, 0xEA, 0xC8, 0x61, 0xE1, 0x9B, 0x56, 0x3A + } +}; + +/* + * Local reimplementation of cmn_err, since it's used in sha2.c. + */ +/*ARGSUSED*/ +void +cmn_err(int level, char *format, ...) +{ + va_list ap; + va_start(ap, format); + /* LINTED: E_SEC_PRINTF_VAR_FMT */ + (void) vfprintf(stderr, format, ap); + va_end(ap); +} + +int +main(int argc, char *argv[]) +{ + boolean_t failed = B_FALSE; + uint64_t cpu_mhz = 0; + + if (argc == 2) + cpu_mhz = atoi(argv[1]); + +#define SHA2_ALGO_TEST(_m, mode, diglen, testdigest) \ + do { \ + SHA2_CTX ctx; \ + uint8_t digest[diglen / 8]; \ + SHA2Init(SHA ## mode ## _MECH_INFO_TYPE, &ctx); \ + SHA2Update(&ctx, _m, strlen(_m)); \ + SHA2Final(digest, &ctx); \ + (void) printf("SHA%-9sMessage: " #_m \ + "\tResult: ", #mode); \ + if (bcmp(digest, testdigest, diglen / 8) == 0) { \ + (void) printf("OK\n"); \ + } else { \ + (void) printf("FAILED!\n"); \ + failed = B_TRUE; \ + } \ + NOTE(CONSTCOND) \ + } while (0) + +#define SHA2_PERF_TEST(mode, diglen) \ + do { \ + SHA2_CTX ctx; \ + uint8_t digest[diglen / 8]; \ + uint8_t block[131072]; \ + uint64_t delta; \ + double cpb = 0; \ + int i; \ + struct timeval start, end; \ + bzero(block, sizeof (block)); \ + (void) gettimeofday(&start, NULL); \ + SHA2Init(SHA ## mode ## _MECH_INFO_TYPE, &ctx); \ + for (i = 0; i < 8192; i++) \ + SHA2Update(&ctx, block, sizeof (block)); \ + SHA2Final(digest, &ctx); \ + (void) gettimeofday(&end, NULL); \ + delta = (end.tv_sec * 1000000llu + end.tv_usec) - \ + (start.tv_sec * 1000000llu + start.tv_usec); \ + if (cpu_mhz != 0) { \ + cpb = (cpu_mhz * 1e6 * ((double)delta / \ + 1000000)) / (8192 * 128 * 1024); \ + } \ + (void) printf("SHA%-9s%llu us (%.02f CPB)\n", #mode, \ + (u_longlong_t)delta, cpb); \ + NOTE(CONSTCOND) \ + } while (0) + + (void) printf("Running algorithm correctness tests:\n"); + SHA2_ALGO_TEST(test_msg0, 256, 256, sha256_test_digests[0]); + SHA2_ALGO_TEST(test_msg1, 256, 256, sha256_test_digests[1]); + SHA2_ALGO_TEST(test_msg0, 384, 384, sha384_test_digests[0]); + SHA2_ALGO_TEST(test_msg2, 384, 384, sha384_test_digests[2]); + SHA2_ALGO_TEST(test_msg0, 512, 512, sha512_test_digests[0]); + SHA2_ALGO_TEST(test_msg2, 512, 512, sha512_test_digests[2]); + SHA2_ALGO_TEST(test_msg0, 512_224, 224, sha512_224_test_digests[0]); + SHA2_ALGO_TEST(test_msg2, 512_224, 224, sha512_224_test_digests[2]); + SHA2_ALGO_TEST(test_msg0, 512_256, 256, sha512_256_test_digests[0]); + SHA2_ALGO_TEST(test_msg2, 512_256, 256, sha512_256_test_digests[2]); + + if (failed) + return (1); + + (void) printf("Running performance tests (hashing 1024 MiB of " + "data):\n"); + SHA2_PERF_TEST(256, 256); + SHA2_PERF_TEST(512, 512); + + return (0); +} diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/sha2/sparc/Makefile b/usr/src/test/zfs-tests/tests/functional/checksum/sha2/sparc/Makefile new file mode 100644 index 0000000000..41b7f0741a --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/sha2/sparc/Makefile @@ -0,0 +1,19 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +PROG=sha2_test +include ../../Makefile.subdirs + +install: all $(CMD32) diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/sha2/sparcv9/Makefile b/usr/src/test/zfs-tests/tests/functional/checksum/sha2/sparcv9/Makefile new file mode 100644 index 0000000000..ee81ed97d7 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/sha2/sparcv9/Makefile @@ -0,0 +1,20 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +PROG=sha2_test +include ../../Makefile.subdirs +include $(SRC)/cmd/Makefile.cmd.64 + +install: all $(CMD64) diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/skein/Makefile b/usr/src/test/zfs-tests/tests/functional/checksum/skein/Makefile new file mode 100644 index 0000000000..e81deeab71 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/skein/Makefile @@ -0,0 +1,29 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +include $(SRC)/Makefile.master +include $(SRC)/test/Makefile.com + +SUBDIRS = $(MACH) +$(BUILD64) SUBDIRS += $(MACH64) + +all: $(SUBDIRS) + +clean clobber lint: $(SUBDIRS) + +install: $(SUBDIRS) + +$(SUBDIRS): + @cd $@; pwd; $(MAKE) $(TARGET) diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/skein/amd64/Makefile b/usr/src/test/zfs-tests/tests/functional/checksum/skein/amd64/Makefile new file mode 100644 index 0000000000..c2f6093e72 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/skein/amd64/Makefile @@ -0,0 +1,20 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +PROG=skein_test +include ../../Makefile.subdirs +include $(SRC)/cmd/Makefile.cmd.64 + +install: all $(CMD64) diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/skein/i386/Makefile b/usr/src/test/zfs-tests/tests/functional/checksum/skein/i386/Makefile new file mode 100644 index 0000000000..220481ca11 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/skein/i386/Makefile @@ -0,0 +1,19 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +PROG=skein_test +include ../../Makefile.subdirs + +install: all $(CMD32) diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/skein/skein_test.c b/usr/src/test/zfs-tests/tests/functional/checksum/skein/skein_test.c new file mode 100644 index 0000000000..ed57fec125 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/skein/skein_test.c @@ -0,0 +1,339 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2013 Saso Kiselkov. All rights reserved. + */ + +/* + * This is just to keep the compiler happy about sys/time.h not declaring + * gettimeofday due to -D_KERNEL (we can do this since we're actually + * running in userspace, but we need -D_KERNEL for the remaining Skein code). + */ +#ifdef _KERNEL +#undef _KERNEL +#endif + +#include <sys/skein.h> +#include <stdlib.h> +#include <strings.h> +#include <stdio.h> +#include <sys/time.h> +#include <note.h> + +/* + * Skein test suite using values from the Skein V1.3 specification found at: + * http://www.skein-hash.info/sites/default/files/skein1.3.pdf + */ + +/* + * Test messages from the Skein spec, Appendix C. + */ +const uint8_t test_msg0[] = { + 0xFF +}; + +const uint8_t test_msg1[] = { + 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, + 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0, + 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8, + 0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0 +}; + +const uint8_t test_msg2[] = { + 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, + 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0, + 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8, + 0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0, + 0xDF, 0xDE, 0xDD, 0xDC, 0xDB, 0xDA, 0xD9, 0xD8, + 0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xD0, + 0xCF, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8, + 0xC7, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xC0 +}; + +const uint8_t test_msg3[] = { + 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, + 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0, + 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8, + 0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0, + 0xDF, 0xDE, 0xDD, 0xDC, 0xDB, 0xDA, 0xD9, 0xD8, + 0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xD0, + 0xCF, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8, + 0xC7, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xC0, + 0xBF, 0xBE, 0xBD, 0xBC, 0xBB, 0xBA, 0xB9, 0xB8, + 0xB7, 0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1, 0xB0, + 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, + 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, + 0x9F, 0x9E, 0x9D, 0x9C, 0x9B, 0x9A, 0x99, 0x98, + 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, + 0x8F, 0x8E, 0x8D, 0x8C, 0x8B, 0x8A, 0x89, 0x88, + 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80 +}; + +const uint8_t test_msg4[] = { + 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, + 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0, + 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8, + 0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0, + 0xDF, 0xDE, 0xDD, 0xDC, 0xDB, 0xDA, 0xD9, 0xD8, + 0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xD0, + 0xCF, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8, + 0xC7, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xC0, + 0xBF, 0xBE, 0xBD, 0xBC, 0xBB, 0xBA, 0xB9, 0xB8, + 0xB7, 0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1, 0xB0, + 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, + 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, + 0x9F, 0x9E, 0x9D, 0x9C, 0x9B, 0x9A, 0x99, 0x98, + 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, + 0x8F, 0x8E, 0x8D, 0x8C, 0x8B, 0x8A, 0x89, 0x88, + 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, + 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, + 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, + 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, 0x68, + 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60, + 0x5F, 0x5E, 0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58, + 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, + 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48, + 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, + 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, + 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, + 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28, + 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, + 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, + 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, + 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 +}; + +/* + * Test digests from the Skein spec, Appendix C. + */ +const uint8_t skein_256_test_digests[][32] = { + { + /* for test_msg0 */ + 0x0B, 0x98, 0xDC, 0xD1, 0x98, 0xEA, 0x0E, 0x50, + 0xA7, 0xA2, 0x44, 0xC4, 0x44, 0xE2, 0x5C, 0x23, + 0xDA, 0x30, 0xC1, 0x0F, 0xC9, 0xA1, 0xF2, 0x70, + 0xA6, 0x63, 0x7F, 0x1F, 0x34, 0xE6, 0x7E, 0xD2 + }, + { + /* for test_msg1 */ + 0x8D, 0x0F, 0xA4, 0xEF, 0x77, 0x7F, 0xD7, 0x59, + 0xDF, 0xD4, 0x04, 0x4E, 0x6F, 0x6A, 0x5A, 0xC3, + 0xC7, 0x74, 0xAE, 0xC9, 0x43, 0xDC, 0xFC, 0x07, + 0x92, 0x7B, 0x72, 0x3B, 0x5D, 0xBF, 0x40, 0x8B + }, + { + /* for test_msg2 */ + 0xDF, 0x28, 0xE9, 0x16, 0x63, 0x0D, 0x0B, 0x44, + 0xC4, 0xA8, 0x49, 0xDC, 0x9A, 0x02, 0xF0, 0x7A, + 0x07, 0xCB, 0x30, 0xF7, 0x32, 0x31, 0x82, 0x56, + 0xB1, 0x5D, 0x86, 0x5A, 0xC4, 0xAE, 0x16, 0x2F + } + /* no test digests for test_msg3 and test_msg4 */ +}; + +const uint8_t skein_512_test_digests[][64] = { + { + /* for test_msg0 */ + 0x71, 0xB7, 0xBC, 0xE6, 0xFE, 0x64, 0x52, 0x22, + 0x7B, 0x9C, 0xED, 0x60, 0x14, 0x24, 0x9E, 0x5B, + 0xF9, 0xA9, 0x75, 0x4C, 0x3A, 0xD6, 0x18, 0xCC, + 0xC4, 0xE0, 0xAA, 0xE1, 0x6B, 0x31, 0x6C, 0xC8, + 0xCA, 0x69, 0x8D, 0x86, 0x43, 0x07, 0xED, 0x3E, + 0x80, 0xB6, 0xEF, 0x15, 0x70, 0x81, 0x2A, 0xC5, + 0x27, 0x2D, 0xC4, 0x09, 0xB5, 0xA0, 0x12, 0xDF, + 0x2A, 0x57, 0x91, 0x02, 0xF3, 0x40, 0x61, 0x7A + }, + { + /* no test vector for test_msg1 */ + NULL + }, + { + /* for test_msg2 */ + 0x45, 0x86, 0x3B, 0xA3, 0xBE, 0x0C, 0x4D, 0xFC, + 0x27, 0xE7, 0x5D, 0x35, 0x84, 0x96, 0xF4, 0xAC, + 0x9A, 0x73, 0x6A, 0x50, 0x5D, 0x93, 0x13, 0xB4, + 0x2B, 0x2F, 0x5E, 0xAD, 0xA7, 0x9F, 0xC1, 0x7F, + 0x63, 0x86, 0x1E, 0x94, 0x7A, 0xFB, 0x1D, 0x05, + 0x6A, 0xA1, 0x99, 0x57, 0x5A, 0xD3, 0xF8, 0xC9, + 0xA3, 0xCC, 0x17, 0x80, 0xB5, 0xE5, 0xFA, 0x4C, + 0xAE, 0x05, 0x0E, 0x98, 0x98, 0x76, 0x62, 0x5B + }, + { + /* for test_msg3 */ + 0x91, 0xCC, 0xA5, 0x10, 0xC2, 0x63, 0xC4, 0xDD, + 0xD0, 0x10, 0x53, 0x0A, 0x33, 0x07, 0x33, 0x09, + 0x62, 0x86, 0x31, 0xF3, 0x08, 0x74, 0x7E, 0x1B, + 0xCB, 0xAA, 0x90, 0xE4, 0x51, 0xCA, 0xB9, 0x2E, + 0x51, 0x88, 0x08, 0x7A, 0xF4, 0x18, 0x87, 0x73, + 0xA3, 0x32, 0x30, 0x3E, 0x66, 0x67, 0xA7, 0xA2, + 0x10, 0x85, 0x6F, 0x74, 0x21, 0x39, 0x00, 0x00, + 0x71, 0xF4, 0x8E, 0x8B, 0xA2, 0xA5, 0xAD, 0xB7 + } + /* no test digests for test_msg4 */ +}; + +const uint8_t skein_1024_test_digests[][128] = { + { + /* for test_msg0 */ + 0xE6, 0x2C, 0x05, 0x80, 0x2E, 0xA0, 0x15, 0x24, + 0x07, 0xCD, 0xD8, 0x78, 0x7F, 0xDA, 0x9E, 0x35, + 0x70, 0x3D, 0xE8, 0x62, 0xA4, 0xFB, 0xC1, 0x19, + 0xCF, 0xF8, 0x59, 0x0A, 0xFE, 0x79, 0x25, 0x0B, + 0xCC, 0xC8, 0xB3, 0xFA, 0xF1, 0xBD, 0x24, 0x22, + 0xAB, 0x5C, 0x0D, 0x26, 0x3F, 0xB2, 0xF8, 0xAF, + 0xB3, 0xF7, 0x96, 0xF0, 0x48, 0x00, 0x03, 0x81, + 0x53, 0x1B, 0x6F, 0x00, 0xD8, 0x51, 0x61, 0xBC, + 0x0F, 0xFF, 0x4B, 0xEF, 0x24, 0x86, 0xB1, 0xEB, + 0xCD, 0x37, 0x73, 0xFA, 0xBF, 0x50, 0xAD, 0x4A, + 0xD5, 0x63, 0x9A, 0xF9, 0x04, 0x0E, 0x3F, 0x29, + 0xC6, 0xC9, 0x31, 0x30, 0x1B, 0xF7, 0x98, 0x32, + 0xE9, 0xDA, 0x09, 0x85, 0x7E, 0x83, 0x1E, 0x82, + 0xEF, 0x8B, 0x46, 0x91, 0xC2, 0x35, 0x65, 0x65, + 0x15, 0xD4, 0x37, 0xD2, 0xBD, 0xA3, 0x3B, 0xCE, + 0xC0, 0x01, 0xC6, 0x7F, 0xFD, 0xE1, 0x5B, 0xA8 + }, + { + /* no test vector for test_msg1 */ + NULL + }, + { + /* no test vector for test_msg2 */ + NULL + }, + { + /* for test_msg3 */ + 0x1F, 0x3E, 0x02, 0xC4, 0x6F, 0xB8, 0x0A, 0x3F, + 0xCD, 0x2D, 0xFB, 0xBC, 0x7C, 0x17, 0x38, 0x00, + 0xB4, 0x0C, 0x60, 0xC2, 0x35, 0x4A, 0xF5, 0x51, + 0x18, 0x9E, 0xBF, 0x43, 0x3C, 0x3D, 0x85, 0xF9, + 0xFF, 0x18, 0x03, 0xE6, 0xD9, 0x20, 0x49, 0x31, + 0x79, 0xED, 0x7A, 0xE7, 0xFC, 0xE6, 0x9C, 0x35, + 0x81, 0xA5, 0xA2, 0xF8, 0x2D, 0x3E, 0x0C, 0x7A, + 0x29, 0x55, 0x74, 0xD0, 0xCD, 0x7D, 0x21, 0x7C, + 0x48, 0x4D, 0x2F, 0x63, 0x13, 0xD5, 0x9A, 0x77, + 0x18, 0xEA, 0xD0, 0x7D, 0x07, 0x29, 0xC2, 0x48, + 0x51, 0xD7, 0xE7, 0xD2, 0x49, 0x1B, 0x90, 0x2D, + 0x48, 0x91, 0x94, 0xE6, 0xB7, 0xD3, 0x69, 0xDB, + 0x0A, 0xB7, 0xAA, 0x10, 0x6F, 0x0E, 0xE0, 0xA3, + 0x9A, 0x42, 0xEF, 0xC5, 0x4F, 0x18, 0xD9, 0x37, + 0x76, 0x08, 0x09, 0x85, 0xF9, 0x07, 0x57, 0x4F, + 0x99, 0x5E, 0xC6, 0xA3, 0x71, 0x53, 0xA5, 0x78 + }, + { + /* for test_msg4 */ + 0x84, 0x2A, 0x53, 0xC9, 0x9C, 0x12, 0xB0, 0xCF, + 0x80, 0xCF, 0x69, 0x49, 0x1B, 0xE5, 0xE2, 0xF7, + 0x51, 0x5D, 0xE8, 0x73, 0x3B, 0x6E, 0xA9, 0x42, + 0x2D, 0xFD, 0x67, 0x66, 0x65, 0xB5, 0xFA, 0x42, + 0xFF, 0xB3, 0xA9, 0xC4, 0x8C, 0x21, 0x77, 0x77, + 0x95, 0x08, 0x48, 0xCE, 0xCD, 0xB4, 0x8F, 0x64, + 0x0F, 0x81, 0xFB, 0x92, 0xBE, 0xF6, 0xF8, 0x8F, + 0x7A, 0x85, 0xC1, 0xF7, 0xCD, 0x14, 0x46, 0xC9, + 0x16, 0x1C, 0x0A, 0xFE, 0x8F, 0x25, 0xAE, 0x44, + 0x4F, 0x40, 0xD3, 0x68, 0x00, 0x81, 0xC3, 0x5A, + 0xA4, 0x3F, 0x64, 0x0F, 0xD5, 0xFA, 0x3C, 0x3C, + 0x03, 0x0B, 0xCC, 0x06, 0xAB, 0xAC, 0x01, 0xD0, + 0x98, 0xBC, 0xC9, 0x84, 0xEB, 0xD8, 0x32, 0x27, + 0x12, 0x92, 0x1E, 0x00, 0xB1, 0xBA, 0x07, 0xD6, + 0xD0, 0x1F, 0x26, 0x90, 0x70, 0x50, 0x25, 0x5E, + 0xF2, 0xC8, 0xE2, 0x4F, 0x71, 0x6C, 0x52, 0xA5 + } +}; + +int +main(int argc, char *argv[]) +{ + boolean_t failed = B_FALSE; + uint64_t cpu_mhz = 0; + + if (argc == 2) + cpu_mhz = atoi(argv[1]); + +#define SKEIN_ALGO_TEST(_m, mode, diglen, testdigest) \ + do { \ + Skein ## mode ## _Ctxt_t ctx; \ + uint8_t digest[diglen / 8]; \ + (void) Skein ## mode ## _Init(&ctx, diglen); \ + (void) Skein ## mode ## _Update(&ctx, _m, sizeof (_m)); \ + (void) Skein ## mode ## _Final(&ctx, digest); \ + (void) printf("Skein" #mode "/" #diglen \ + "\tMessage: " #_m "\tResult: "); \ + if (bcmp(digest, testdigest, diglen / 8) == 0) { \ + (void) printf("OK\n"); \ + } else { \ + (void) printf("FAILED!\n"); \ + failed = B_TRUE; \ + } \ + NOTE(CONSTCOND) \ + } while (0) + +#define SKEIN_PERF_TEST(mode, diglen) \ + do { \ + Skein ## mode ## _Ctxt_t ctx; \ + uint8_t digest[diglen / 8]; \ + uint8_t block[131072]; \ + uint64_t delta; \ + double cpb = 0; \ + int i; \ + struct timeval start, end; \ + bzero(block, sizeof (block)); \ + (void) gettimeofday(&start, NULL); \ + (void) Skein ## mode ## _Init(&ctx, diglen); \ + for (i = 0; i < 8192; i++) { \ + (void) Skein ## mode ## _Update(&ctx, block, \ + sizeof (block)); \ + } \ + (void) Skein ## mode ## _Final(&ctx, digest); \ + (void) gettimeofday(&end, NULL); \ + delta = (end.tv_sec * 1000000llu + end.tv_usec) - \ + (start.tv_sec * 1000000llu + start.tv_usec); \ + if (cpu_mhz != 0) { \ + cpb = (cpu_mhz * 1e6 * ((double)delta / \ + 1000000)) / (8192 * 128 * 1024); \ + } \ + (void) printf("Skein" #mode "/" #diglen "\t%llu us " \ + "(%.02f CPB)\n", (u_longlong_t)delta, cpb); \ + NOTE(CONSTCOND) \ + } while (0) + + (void) printf("Running algorithm correctness tests:\n"); + SKEIN_ALGO_TEST(test_msg0, _256, 256, skein_256_test_digests[0]); + SKEIN_ALGO_TEST(test_msg1, _256, 256, skein_256_test_digests[1]); + SKEIN_ALGO_TEST(test_msg2, _256, 256, skein_256_test_digests[2]); + SKEIN_ALGO_TEST(test_msg0, _512, 512, skein_512_test_digests[0]); + SKEIN_ALGO_TEST(test_msg2, _512, 512, skein_512_test_digests[2]); + SKEIN_ALGO_TEST(test_msg3, _512, 512, skein_512_test_digests[3]); + SKEIN_ALGO_TEST(test_msg0, 1024, 1024, skein_1024_test_digests[0]); + SKEIN_ALGO_TEST(test_msg3, 1024, 1024, skein_1024_test_digests[3]); + SKEIN_ALGO_TEST(test_msg4, 1024, 1024, skein_1024_test_digests[4]); + if (failed) + return (1); + + (void) printf("Running performance tests (hashing 1024 MiB of " + "data):\n"); + SKEIN_PERF_TEST(_256, 256); + SKEIN_PERF_TEST(_512, 512); + SKEIN_PERF_TEST(1024, 1024); + + return (0); +} diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/skein/sparc/Makefile b/usr/src/test/zfs-tests/tests/functional/checksum/skein/sparc/Makefile new file mode 100644 index 0000000000..220481ca11 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/skein/sparc/Makefile @@ -0,0 +1,19 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +PROG=skein_test +include ../../Makefile.subdirs + +install: all $(CMD32) diff --git a/usr/src/test/zfs-tests/tests/functional/checksum/skein/sparcv9/Makefile b/usr/src/test/zfs-tests/tests/functional/checksum/skein/sparcv9/Makefile new file mode 100644 index 0000000000..c2f6093e72 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/checksum/skein/sparcv9/Makefile @@ -0,0 +1,20 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Delphix. All rights reserved. +# + +PROG=skein_test +include ../../Makefile.subdirs +include $(SRC)/cmd/Makefile.cmd.64 + +install: all $(CMD64) diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files index 3555a86b48..16b5390bf3 100644 --- a/usr/src/uts/common/Makefile.files +++ b/usr/src/uts/common/Makefile.files @@ -519,6 +519,10 @@ SHA1_OBJS += sha1.o sha1_mod.o SHA2_OBJS += sha2.o sha2_mod.o +SKEIN_OBJS += skein.o skein_block.o skein_iv.o skein_mod.o + +EDONR_OBJS += edonr.o edonr_mod.o + IPGPC_OBJS += classifierddi.o classifier.o filters.o trie.o table.o \ ba_table.o @@ -1403,6 +1407,8 @@ ZFS_COMMON_OBJS += \ rrwlock.o \ sa.o \ sha256.o \ + edonr_zfs.o \ + skein_zfs.o \ spa.o \ spa_config.o \ spa_errlog.o \ diff --git a/usr/src/uts/common/Makefile.rules b/usr/src/uts/common/Makefile.rules index 4bf1113182..ca25352d65 100644 --- a/usr/src/uts/common/Makefile.rules +++ b/usr/src/uts/common/Makefile.rules @@ -24,6 +24,7 @@ # Copyright 2013 Garrett D'Amore <garrett@damore.org> # Copyright 2015 Nexenta Systems, Inc. All rights reserved. # Copyright 2015 Joyent, Inc. +# Copyright 2013 Saso Kiselkov. All rights reserved. # # @@ -1610,6 +1611,10 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/common/rpc/sec_gss/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) +$(OBJS_DIR)/%.o: $(COMMONBASE)/crypto/edonr/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + $(OBJS_DIR)/%.o: $(COMMONBASE)/crypto/sha1/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) @@ -1618,6 +1623,10 @@ $(OBJS_DIR)/%.o: $(COMMONBASE)/crypto/sha2/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) +$(OBJS_DIR)/%.o: $(COMMONBASE)/crypto/skein/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + $(OBJS_DIR)/%.o: $(UTSBASE)/common/syscall/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) @@ -2790,12 +2799,18 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/common/rpc/sec/%.c $(LINTS_DIR)/%.ln: $(UTSBASE)/common/rpc/sec_gss/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) +$(LINTS_DIR)/%.ln: $(COMMONBASE)/crypto/edonr/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + $(LINTS_DIR)/%.ln: $(COMMONBASE)/crypto/sha1/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) $(LINTS_DIR)/%.ln: $(COMMONBASE)/crypto/sha2/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) +$(LINTS_DIR)/%.ln: $(COMMONBASE)/crypto/skein/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + $(LINTS_DIR)/%.ln: $(UTSBASE)/common/syscall/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) diff --git a/usr/src/uts/common/crypto/io/edonr_mod.c b/usr/src/uts/common/crypto/io/edonr_mod.c new file mode 100644 index 0000000000..d17bbe9900 --- /dev/null +++ b/usr/src/uts/common/crypto/io/edonr_mod.c @@ -0,0 +1,63 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2013 Saso Kiselkov. All rights reserved. + */ + +#include <sys/modctl.h> +#include <sys/crypto/common.h> +#include <sys/crypto/spi.h> +#include <sys/sysmacros.h> +#include <sys/systm.h> +#include <sys/edonr.h> + +/* + * Unlike sha2 or skein, we won't expose edonr via the Kernel Cryptographic + * Framework (KCF), because Edon-R is *NOT* suitable for general-purpose + * cryptographic use. Users of Edon-R must interface directly to this module. + */ + +static struct modlmisc modlmisc = { + &mod_miscops, + "Edon-R Message-Digest Algorithm" +}; + +static struct modlinkage modlinkage = { + MODREV_1, &modlmisc, NULL +}; + +int +_init(void) +{ + int error; + + if ((error = mod_install(&modlinkage)) != 0) + return (error); + + return (0); +} + +int +_info(struct modinfo *modinfop) +{ + return (mod_info(&modlinkage, modinfop)); +} diff --git a/usr/src/uts/common/crypto/io/skein_mod.c b/usr/src/uts/common/crypto/io/skein_mod.c new file mode 100644 index 0000000000..49ad9cb0c7 --- /dev/null +++ b/usr/src/uts/common/crypto/io/skein_mod.c @@ -0,0 +1,832 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2013 Saso Kiselkov. All rights reserved. + */ + +#include <sys/modctl.h> +#include <sys/crypto/common.h> +#include <sys/crypto/spi.h> +#include <sys/strsun.h> +#include <sys/sysmacros.h> +#include <sys/systm.h> +#define SKEIN_MODULE_IMPL +#include <sys/skein.h> + +/* + * Like the sha2 module, we create the skein module with two modlinkages: + * - modlmisc to allow direct calls to Skein_* API functions. + * - modlcrypto to integrate well into the Kernel Crypto Framework (KCF). + */ +static struct modlmisc modlmisc = { + &mod_miscops, + "Skein Message-Digest Algorithm" +}; + +static struct modlcrypto modlcrypto = { + &mod_cryptoops, + "Skein Kernel SW Provider" +}; + +static struct modlinkage modlinkage = { + MODREV_1, &modlmisc, &modlcrypto, NULL +}; + +static crypto_mech_info_t skein_mech_info_tab[] = { + {CKM_SKEIN_256, SKEIN_256_MECH_INFO_TYPE, + CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, + 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS}, + {CKM_SKEIN_256_MAC, SKEIN_256_MAC_MECH_INFO_TYPE, + CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 1, INT_MAX, + CRYPTO_KEYSIZE_UNIT_IN_BYTES}, + {CKM_SKEIN_512, SKEIN_512_MECH_INFO_TYPE, + CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, + 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS}, + {CKM_SKEIN_512_MAC, SKEIN_512_MAC_MECH_INFO_TYPE, + CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 1, INT_MAX, + CRYPTO_KEYSIZE_UNIT_IN_BYTES}, + {CKM_SKEIN1024, SKEIN1024_MECH_INFO_TYPE, + CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, + 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS}, + {CKM_SKEIN1024_MAC, SKEIN1024_MAC_MECH_INFO_TYPE, + CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 1, INT_MAX, + CRYPTO_KEYSIZE_UNIT_IN_BYTES} +}; + +static void skein_provider_status(crypto_provider_handle_t, uint_t *); + +static crypto_control_ops_t skein_control_ops = { + skein_provider_status +}; + +static int skein_digest_init(crypto_ctx_t *, crypto_mechanism_t *, + crypto_req_handle_t); +static int skein_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, + crypto_req_handle_t); +static int skein_update(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t); +static int skein_final(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t); +static int skein_digest_atomic(crypto_provider_handle_t, crypto_session_id_t, + crypto_mechanism_t *, crypto_data_t *, crypto_data_t *, + crypto_req_handle_t); + +static crypto_digest_ops_t skein_digest_ops = { + skein_digest_init, + skein_digest, + skein_update, + NULL, + skein_final, + skein_digest_atomic +}; + +static int skein_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *, + crypto_spi_ctx_template_t, crypto_req_handle_t); +static int skein_mac_atomic(crypto_provider_handle_t, crypto_session_id_t, + crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *, + crypto_spi_ctx_template_t, crypto_req_handle_t); + +static crypto_mac_ops_t skein_mac_ops = { + skein_mac_init, + NULL, + skein_update, /* using regular digest update is OK here */ + skein_final, /* using regular digest final is OK here */ + skein_mac_atomic, + NULL +}; + +static int skein_create_ctx_template(crypto_provider_handle_t, + crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *, + size_t *, crypto_req_handle_t); +static int skein_free_context(crypto_ctx_t *); + +static crypto_ctx_ops_t skein_ctx_ops = { + skein_create_ctx_template, + skein_free_context +}; + +static crypto_ops_t skein_crypto_ops = { + &skein_control_ops, + &skein_digest_ops, + NULL, + &skein_mac_ops, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &skein_ctx_ops, + NULL, + NULL, + NULL +}; + +static crypto_provider_info_t skein_prov_info = { + CRYPTO_SPI_VERSION_4, + "Skein Software Provider", + CRYPTO_SW_PROVIDER, + {&modlinkage}, + NULL, + &skein_crypto_ops, + sizeof (skein_mech_info_tab) / sizeof (crypto_mech_info_t), + skein_mech_info_tab +}; + +static crypto_kcf_provider_handle_t skein_prov_handle = NULL; + +typedef struct skein_ctx { + skein_mech_type_t sc_mech_type; + size_t sc_digest_bitlen; + union { + Skein_256_Ctxt_t sc_256; + Skein_512_Ctxt_t sc_512; + Skein1024_Ctxt_t sc_1024; + } sc_u; +} skein_ctx_t; +#define SKEIN_CTX(_ctx_) ((skein_ctx_t *)((_ctx_)->cc_provider_private)) +#define SKEIN_CTX_LVALUE(_ctx_) (_ctx_)->cc_provider_private +#define SKEIN_OP(_skein_ctx, _op, ...) \ + do { \ + skein_ctx_t *sc = (_skein_ctx); \ + switch (sc->sc_mech_type) { \ + case SKEIN_256_MECH_INFO_TYPE: \ + case SKEIN_256_MAC_MECH_INFO_TYPE: \ + (void) Skein_256_ ## _op(&sc->sc_u.sc_256, \ + __VA_ARGS__); \ + break; \ + case SKEIN_512_MECH_INFO_TYPE: \ + case SKEIN_512_MAC_MECH_INFO_TYPE: \ + (void) Skein_512_ ## _op(&sc->sc_u.sc_512, \ + __VA_ARGS__); \ + break; \ + case SKEIN1024_MECH_INFO_TYPE: \ + case SKEIN1024_MAC_MECH_INFO_TYPE: \ + (void) Skein1024_ ## _op(&sc->sc_u.sc_1024, \ + __VA_ARGS__); \ + break; \ + } \ + _NOTE(CONSTCOND) \ + } while (0) + +static int +skein_get_digest_bitlen(const crypto_mechanism_t *mechanism, size_t *result) +{ + if (mechanism->cm_param != NULL) { + /*LINTED(E_BAD_PTR_CAST_ALIGN)*/ + skein_param_t *param = (skein_param_t *)mechanism->cm_param; + + if (mechanism->cm_param_len != sizeof (*param) || + param->sp_digest_bitlen == 0) { + return (CRYPTO_MECHANISM_PARAM_INVALID); + } + *result = param->sp_digest_bitlen; + } else { + switch (mechanism->cm_type) { + case SKEIN_256_MECH_INFO_TYPE: + *result = 256; + break; + case SKEIN_512_MECH_INFO_TYPE: + *result = 512; + break; + case SKEIN1024_MECH_INFO_TYPE: + *result = 1024; + break; + default: + return (CRYPTO_MECHANISM_INVALID); + } + } + return (CRYPTO_SUCCESS); +} + +int +_init(void) +{ + int error; + + if ((error = mod_install(&modlinkage)) != 0) + return (error); + + /* + * Try to register with KCF - failure shouldn't unload us, since we + * still may want to continue providing misc/skein functionality. + */ + (void) crypto_register_provider(&skein_prov_info, &skein_prov_handle); + + return (0); +} + +int +_info(struct modinfo *modinfop) +{ + return (mod_info(&modlinkage, modinfop)); +} + +/* + * KCF software provider control entry points. + */ +/* ARGSUSED */ +static void +skein_provider_status(crypto_provider_handle_t provider, uint_t *status) +{ + *status = CRYPTO_PROVIDER_READY; +} + +/* + * General Skein hashing helper functions. + */ + +/* + * Performs an Update on a context with uio input data. + */ +static int +skein_digest_update_uio(skein_ctx_t *ctx, const crypto_data_t *data) +{ + off_t offset = data->cd_offset; + size_t length = data->cd_length; + uint_t vec_idx; + size_t cur_len; + const uio_t *uio = data->cd_uio; + + /* we support only kernel buffer */ + if (uio->uio_segflg != UIO_SYSSPACE) + return (CRYPTO_ARGUMENTS_BAD); + + /* + * Jump to the first iovec containing data to be + * digested. + */ + for (vec_idx = 0; vec_idx < uio->uio_iovcnt && + offset >= uio->uio_iov[vec_idx].iov_len; + offset -= uio->uio_iov[vec_idx++].iov_len) + ; + if (vec_idx == uio->uio_iovcnt) { + /* + * The caller specified an offset that is larger than the + * total size of the buffers it provided. + */ + return (CRYPTO_DATA_LEN_RANGE); + } + + /* + * Now do the digesting on the iovecs. + */ + while (vec_idx < uio->uio_iovcnt && length > 0) { + cur_len = MIN(uio->uio_iov[vec_idx].iov_len - offset, length); + SKEIN_OP(ctx, Update, (uint8_t *)uio->uio_iov[vec_idx].iov_base + + offset, cur_len); + length -= cur_len; + vec_idx++; + offset = 0; + } + + if (vec_idx == uio->uio_iovcnt && length > 0) { + /* + * The end of the specified iovec's was reached but + * the length requested could not be processed, i.e. + * The caller requested to digest more data than it provided. + */ + return (CRYPTO_DATA_LEN_RANGE); + } + + return (CRYPTO_SUCCESS); +} + +/* + * Performs a Final on a context and writes to a uio digest output. + */ +static int +skein_digest_final_uio(skein_ctx_t *ctx, crypto_data_t *digest, + crypto_req_handle_t req) +{ + off_t offset = digest->cd_offset; + uint_t vec_idx; + uio_t *uio = digest->cd_uio; + + /* we support only kernel buffer */ + if (uio->uio_segflg != UIO_SYSSPACE) + return (CRYPTO_ARGUMENTS_BAD); + + /* + * Jump to the first iovec containing ptr to the digest to be returned. + */ + for (vec_idx = 0; offset >= uio->uio_iov[vec_idx].iov_len && + vec_idx < uio->uio_iovcnt; + offset -= uio->uio_iov[vec_idx++].iov_len) + ; + if (vec_idx == uio->uio_iovcnt) { + /* + * The caller specified an offset that is larger than the + * total size of the buffers it provided. + */ + return (CRYPTO_DATA_LEN_RANGE); + } + if (offset + CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen) <= + uio->uio_iov[vec_idx].iov_len) { + /* The computed digest will fit in the current iovec. */ + SKEIN_OP(ctx, Final, + (uchar_t *)uio->uio_iov[vec_idx].iov_base + offset); + } else { + uint8_t *digest_tmp; + off_t scratch_offset = 0; + size_t length = CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen); + size_t cur_len; + + digest_tmp = kmem_alloc(CRYPTO_BITS2BYTES( + ctx->sc_digest_bitlen), crypto_kmflag(req)); + if (digest_tmp == NULL) + return (CRYPTO_HOST_MEMORY); + SKEIN_OP(ctx, Final, digest_tmp); + while (vec_idx < uio->uio_iovcnt && length > 0) { + cur_len = MIN(uio->uio_iov[vec_idx].iov_len - offset, + length); + bcopy(digest_tmp + scratch_offset, + uio->uio_iov[vec_idx].iov_base + offset, cur_len); + + length -= cur_len; + vec_idx++; + scratch_offset += cur_len; + offset = 0; + } + kmem_free(digest_tmp, CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen)); + + if (vec_idx == uio->uio_iovcnt && length > 0) { + /* + * The end of the specified iovec's was reached but + * the length requested could not be processed, i.e. + * The caller requested to digest more data than it + * provided. + */ + return (CRYPTO_DATA_LEN_RANGE); + } + } + + return (CRYPTO_SUCCESS); +} + +/* + * Performs an Update on a context with mblk input data. + */ +static int +skein_digest_update_mblk(skein_ctx_t *ctx, crypto_data_t *data) +{ + off_t offset = data->cd_offset; + size_t length = data->cd_length; + mblk_t *mp; + size_t cur_len; + + /* Jump to the first mblk_t containing data to be digested. */ + for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp); + offset -= MBLKL(mp), mp = mp->b_cont) + ; + if (mp == NULL) { + /* + * The caller specified an offset that is larger than the + * total size of the buffers it provided. + */ + return (CRYPTO_DATA_LEN_RANGE); + } + + /* Now do the digesting on the mblk chain. */ + while (mp != NULL && length > 0) { + cur_len = MIN(MBLKL(mp) - offset, length); + SKEIN_OP(ctx, Update, mp->b_rptr + offset, cur_len); + length -= cur_len; + offset = 0; + mp = mp->b_cont; + } + + if (mp == NULL && length > 0) { + /* + * The end of the mblk was reached but the length requested + * could not be processed, i.e. The caller requested + * to digest more data than it provided. + */ + return (CRYPTO_DATA_LEN_RANGE); + } + + return (CRYPTO_SUCCESS); +} + +/* + * Performs a Final on a context and writes to an mblk digest output. + */ +static int +skein_digest_final_mblk(skein_ctx_t *ctx, crypto_data_t *digest, + crypto_req_handle_t req) +{ + off_t offset = digest->cd_offset; + mblk_t *mp; + + /* Jump to the first mblk_t that will be used to store the digest. */ + for (mp = digest->cd_mp; mp != NULL && offset >= MBLKL(mp); + offset -= MBLKL(mp), mp = mp->b_cont) + ; + if (mp == NULL) { + /* caller specified offset is too large */ + return (CRYPTO_DATA_LEN_RANGE); + } + + if (offset + CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen) <= MBLKL(mp)) { + /* The digest will fit in the current mblk. */ + SKEIN_OP(ctx, Final, mp->b_rptr + offset); + } else { + /* Split the digest up between the individual buffers. */ + uint8_t *digest_tmp; + off_t scratch_offset = 0; + size_t length = CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen); + size_t cur_len; + + digest_tmp = kmem_alloc(CRYPTO_BITS2BYTES( + ctx->sc_digest_bitlen), crypto_kmflag(req)); + if (digest_tmp == NULL) + return (CRYPTO_HOST_MEMORY); + SKEIN_OP(ctx, Final, digest_tmp); + while (mp != NULL && length > 0) { + cur_len = MIN(MBLKL(mp) - offset, length); + bcopy(digest_tmp + scratch_offset, + mp->b_rptr + offset, cur_len); + length -= cur_len; + mp = mp->b_cont; + scratch_offset += cur_len; + offset = 0; + } + kmem_free(digest_tmp, CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen)); + if (mp == NULL && length > 0) { + /* digest too long to fit in the mblk buffers */ + return (CRYPTO_DATA_LEN_RANGE); + } + } + + return (CRYPTO_SUCCESS); +} + +/* + * KCF software provider digest entry points. + */ + +/* + * Initializes a skein digest context to the configuration in `mechanism'. + * The mechanism cm_type must be one of SKEIN_*_MECH_INFO_TYPE. The cm_param + * field may contain a skein_param_t structure indicating the length of the + * digest the algorithm should produce. Otherwise the default output lengths + * are applied (32 bytes for Skein-256, 64 bytes for Skein-512 and 128 bytes + * for Skein-1024). + */ +static int +skein_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, + crypto_req_handle_t req) +{ + int error = CRYPTO_SUCCESS; + + if (!VALID_SKEIN_DIGEST_MECH(mechanism->cm_type)) + return (CRYPTO_MECHANISM_INVALID); + + SKEIN_CTX_LVALUE(ctx) = kmem_alloc(sizeof (*SKEIN_CTX(ctx)), + crypto_kmflag(req)); + if (SKEIN_CTX(ctx) == NULL) + return (CRYPTO_HOST_MEMORY); + + SKEIN_CTX(ctx)->sc_mech_type = mechanism->cm_type; + error = skein_get_digest_bitlen(mechanism, + &SKEIN_CTX(ctx)->sc_digest_bitlen); + if (error != CRYPTO_SUCCESS) + goto errout; + SKEIN_OP(SKEIN_CTX(ctx), Init, SKEIN_CTX(ctx)->sc_digest_bitlen); + + return (CRYPTO_SUCCESS); +errout: + bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); + kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); + SKEIN_CTX_LVALUE(ctx) = NULL; + return (error); +} + +/* + * Executes a skein_update and skein_digest on a pre-initialized crypto + * context in a single step. See the documentation to these functions to + * see what to pass here. + */ +static int +skein_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest, + crypto_req_handle_t req) +{ + int error = CRYPTO_SUCCESS; + + ASSERT(SKEIN_CTX(ctx) != NULL); + + if (digest->cd_length < + CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen)) { + digest->cd_length = + CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen); + return (CRYPTO_BUFFER_TOO_SMALL); + } + + error = skein_update(ctx, data, req); + if (error != CRYPTO_SUCCESS) { + bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); + kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); + SKEIN_CTX_LVALUE(ctx) = NULL; + digest->cd_length = 0; + return (error); + } + error = skein_final(ctx, digest, req); + + return (error); +} + +/* + * Performs a skein Update with the input message in `data' (successive calls + * can push more data). This is used both for digest and MAC operation. + * Supported input data formats are raw, uio and mblk. + */ +/*ARGSUSED*/ +static int +skein_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req) +{ + int error = CRYPTO_SUCCESS; + + ASSERT(SKEIN_CTX(ctx) != NULL); + + switch (data->cd_format) { + case CRYPTO_DATA_RAW: + SKEIN_OP(SKEIN_CTX(ctx), Update, + (uint8_t *)data->cd_raw.iov_base + data->cd_offset, + data->cd_length); + break; + case CRYPTO_DATA_UIO: + error = skein_digest_update_uio(SKEIN_CTX(ctx), data); + break; + case CRYPTO_DATA_MBLK: + error = skein_digest_update_mblk(SKEIN_CTX(ctx), data); + break; + default: + error = CRYPTO_ARGUMENTS_BAD; + } + + return (error); +} + +/* + * Performs a skein Final, writing the output to `digest'. This is used both + * for digest and MAC operation. + * Supported output digest formats are raw, uio and mblk. + */ +/*ARGSUSED*/ +static int +skein_final(crypto_ctx_t *ctx, crypto_data_t *digest, crypto_req_handle_t req) +{ + int error = CRYPTO_SUCCESS; + + ASSERT(SKEIN_CTX(ctx) != NULL); + + if (digest->cd_length < + CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen)) { + digest->cd_length = + CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen); + return (CRYPTO_BUFFER_TOO_SMALL); + } + + switch (digest->cd_format) { + case CRYPTO_DATA_RAW: + SKEIN_OP(SKEIN_CTX(ctx), Final, + (uint8_t *)digest->cd_raw.iov_base + digest->cd_offset); + break; + case CRYPTO_DATA_UIO: + error = skein_digest_final_uio(SKEIN_CTX(ctx), digest, req); + break; + case CRYPTO_DATA_MBLK: + error = skein_digest_final_mblk(SKEIN_CTX(ctx), digest, req); + break; + default: + error = CRYPTO_ARGUMENTS_BAD; + } + + if (error == CRYPTO_SUCCESS) + digest->cd_length = + CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen); + else + digest->cd_length = 0; + + bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); + kmem_free(SKEIN_CTX(ctx), sizeof (*(SKEIN_CTX(ctx)))); + SKEIN_CTX_LVALUE(ctx) = NULL; + + return (error); +} + +/* + * Performs a full skein digest computation in a single call, configuring the + * algorithm according to `mechanism', reading the input to be digested from + * `data' and writing the output to `digest'. + * Supported input/output formats are raw, uio and mblk. + */ +/*ARGSUSED*/ +static int +skein_digest_atomic(crypto_provider_handle_t provider, + crypto_session_id_t session_id, crypto_mechanism_t *mechanism, + crypto_data_t *data, crypto_data_t *digest, crypto_req_handle_t req) +{ + int error; + skein_ctx_t skein_ctx; + crypto_ctx_t ctx; + SKEIN_CTX_LVALUE(&ctx) = &skein_ctx; + + /* Init */ + if (!VALID_SKEIN_DIGEST_MECH(mechanism->cm_type)) + return (CRYPTO_MECHANISM_INVALID); + skein_ctx.sc_mech_type = mechanism->cm_type; + error = skein_get_digest_bitlen(mechanism, &skein_ctx.sc_digest_bitlen); + if (error != CRYPTO_SUCCESS) + goto out; + SKEIN_OP(&skein_ctx, Init, skein_ctx.sc_digest_bitlen); + + if ((error = skein_update(&ctx, data, digest)) != CRYPTO_SUCCESS) + goto out; + if ((error = skein_final(&ctx, data, digest)) != CRYPTO_SUCCESS) + goto out; + +out: + if (error == CRYPTO_SUCCESS) + digest->cd_length = + CRYPTO_BITS2BYTES(skein_ctx.sc_digest_bitlen); + else + digest->cd_length = 0; + bzero(&skein_ctx, sizeof (skein_ctx)); + + return (error); +} + +/* + * Helper function that builds a Skein MAC context from the provided + * mechanism and key. + */ +static int +skein_mac_ctx_build(skein_ctx_t *ctx, crypto_mechanism_t *mechanism, + crypto_key_t *key) +{ + int error; + + if (!VALID_SKEIN_MAC_MECH(mechanism->cm_type)) + return (CRYPTO_MECHANISM_INVALID); + if (key->ck_format != CRYPTO_KEY_RAW) + return (CRYPTO_ARGUMENTS_BAD); + ctx->sc_mech_type = mechanism->cm_type; + error = skein_get_digest_bitlen(mechanism, &ctx->sc_digest_bitlen); + if (error != CRYPTO_SUCCESS) + return (error); + SKEIN_OP(ctx, InitExt, ctx->sc_digest_bitlen, 0, key->ck_data, + CRYPTO_BITS2BYTES(key->ck_length)); + + return (CRYPTO_SUCCESS); +} + +/* + * KCF software provide mac entry points. + */ +/* + * Initializes a skein MAC context. You may pass a ctx_template, in which + * case the template will be reused to make initialization more efficient. + * Otherwise a new context will be constructed. The mechanism cm_type must + * be one of SKEIN_*_MAC_MECH_INFO_TYPE. Same as in skein_digest_init, you + * may pass a skein_param_t in cm_param to configure the length of the + * digest. The key must be in raw format. + */ +static int +skein_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, + crypto_key_t *key, crypto_spi_ctx_template_t ctx_template, + crypto_req_handle_t req) +{ + int error; + + SKEIN_CTX_LVALUE(ctx) = kmem_alloc(sizeof (*SKEIN_CTX(ctx)), + crypto_kmflag(req)); + if (SKEIN_CTX(ctx) == NULL) + return (CRYPTO_HOST_MEMORY); + + if (ctx_template != NULL) { + bcopy(ctx_template, SKEIN_CTX(ctx), + sizeof (*SKEIN_CTX(ctx))); + } else { + error = skein_mac_ctx_build(SKEIN_CTX(ctx), mechanism, key); + if (error != CRYPTO_SUCCESS) + goto errout; + } + + return (CRYPTO_SUCCESS); +errout: + bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); + kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); + return (error); +} + +/* + * The MAC update and final calls are reused from the regular digest code. + */ + +/*ARGSUSED*/ +/* + * Same as skein_digest_atomic, performs an atomic Skein MAC operation in + * one step. All the same properties apply to the arguments of this + * function as to those of the partial operations above. + */ +static int +skein_mac_atomic(crypto_provider_handle_t provider, + crypto_session_id_t session_id, crypto_mechanism_t *mechanism, + crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac, + crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) +{ + /* faux crypto context just for skein_digest_{update,final} */ + int error; + crypto_ctx_t ctx; + skein_ctx_t skein_ctx; + SKEIN_CTX_LVALUE(&ctx) = &skein_ctx; + + if (ctx_template != NULL) { + bcopy(ctx_template, &skein_ctx, sizeof (skein_ctx)); + } else { + error = skein_mac_ctx_build(&skein_ctx, mechanism, key); + if (error != CRYPTO_SUCCESS) + goto errout; + } + + if ((error = skein_update(&ctx, data, req)) != CRYPTO_SUCCESS) + goto errout; + if ((error = skein_final(&ctx, mac, req)) != CRYPTO_SUCCESS) + goto errout; + + return (CRYPTO_SUCCESS); +errout: + bzero(&skein_ctx, sizeof (skein_ctx)); + return (error); +} + +/* + * KCF software provider context management entry points. + */ + +/* + * Constructs a context template for the Skein MAC algorithm. The same + * properties apply to the arguments of this function as to those of + * skein_mac_init. + */ +/*ARGSUSED*/ +static int +skein_create_ctx_template(crypto_provider_handle_t provider, + crypto_mechanism_t *mechanism, crypto_key_t *key, + crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size, + crypto_req_handle_t req) +{ + int error; + skein_ctx_t *ctx_tmpl; + + ctx_tmpl = kmem_alloc(sizeof (*ctx_tmpl), crypto_kmflag(req)); + if (ctx_tmpl == NULL) + return (CRYPTO_HOST_MEMORY); + error = skein_mac_ctx_build(ctx_tmpl, mechanism, key); + if (error != CRYPTO_SUCCESS) + goto errout; + *ctx_template = ctx_tmpl; + *ctx_template_size = sizeof (*ctx_tmpl); + + return (CRYPTO_SUCCESS); +errout: + bzero(ctx_tmpl, sizeof (*ctx_tmpl)); + kmem_free(ctx_tmpl, sizeof (*ctx_tmpl)); + return (error); +} + +/* + * Frees a skein context in a parent crypto context. + */ +static int +skein_free_context(crypto_ctx_t *ctx) +{ + if (SKEIN_CTX(ctx) != NULL) { + bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); + kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); + SKEIN_CTX_LVALUE(ctx) = NULL; + } + + return (CRYPTO_SUCCESS); +} diff --git a/usr/src/uts/common/fs/zfs/arc.c b/usr/src/uts/common/fs/zfs/arc.c index b7bf5ad40a..81835f1291 100644 --- a/usr/src/uts/common/fs/zfs/arc.c +++ b/usr/src/uts/common/fs/zfs/arc.c @@ -1373,7 +1373,7 @@ arc_cksum_verify(arc_buf_t *buf) mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock); return; } - fletcher_2_native(buf->b_data, buf->b_hdr->b_size, &zc); + fletcher_2_native(buf->b_data, buf->b_hdr->b_size, NULL, &zc); if (!ZIO_CHECKSUM_EQUAL(*buf->b_hdr->b_freeze_cksum, zc)) panic("buffer modified while frozen!"); mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock); @@ -1386,7 +1386,7 @@ arc_cksum_equal(arc_buf_t *buf) int equal; mutex_enter(&buf->b_hdr->b_l1hdr.b_freeze_lock); - fletcher_2_native(buf->b_data, buf->b_hdr->b_size, &zc); + fletcher_2_native(buf->b_data, buf->b_hdr->b_size, NULL, &zc); equal = ZIO_CHECKSUM_EQUAL(*buf->b_hdr->b_freeze_cksum, zc); mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock); @@ -1406,7 +1406,7 @@ arc_cksum_compute(arc_buf_t *buf, boolean_t force) } buf->b_hdr->b_freeze_cksum = kmem_alloc(sizeof (zio_cksum_t), KM_SLEEP); fletcher_2_native(buf->b_data, buf->b_hdr->b_size, - buf->b_hdr->b_freeze_cksum); + NULL, buf->b_hdr->b_freeze_cksum); mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock); arc_buf_watch(buf); } diff --git a/usr/src/uts/common/fs/zfs/ddt.c b/usr/src/uts/common/fs/zfs/ddt.c index 7d93896572..9955f89e77 100644 --- a/usr/src/uts/common/fs/zfs/ddt.c +++ b/usr/src/uts/common/fs/zfs/ddt.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2014 by Delphix. All rights reserved. + * Copyright (c) 2012, 2015 by Delphix. All rights reserved. */ #include <sys/zfs_context.h> @@ -59,7 +59,8 @@ ddt_object_create(ddt_t *ddt, enum ddt_type type, enum ddt_class class, spa_t *spa = ddt->ddt_spa; objset_t *os = ddt->ddt_os; uint64_t *objectp = &ddt->ddt_object[type][class]; - boolean_t prehash = zio_checksum_table[ddt->ddt_checksum].ci_dedup; + boolean_t prehash = zio_checksum_table[ddt->ddt_checksum].ci_flags & + ZCHECKSUM_FLAG_DEDUP; char name[DDT_NAMELEN]; ddt_object_name(ddt, type, class, name); diff --git a/usr/src/uts/common/fs/zfs/dmu.c b/usr/src/uts/common/fs/zfs/dmu.c index e6239306ae..c4ac897a71 100644 --- a/usr/src/uts/common/fs/zfs/dmu.c +++ b/usr/src/uts/common/fs/zfs/dmu.c @@ -1424,7 +1424,8 @@ dmu_sync_done(zio_t *zio, arc_buf_t *buf, void *varg) ASSERT(BP_EQUAL(bp, bp_orig)); ASSERT(zio->io_prop.zp_compress != ZIO_COMPRESS_OFF); - ASSERT(zio_checksum_table[chksum].ci_dedup); + ASSERT(zio_checksum_table[chksum].ci_flags & + ZCHECKSUM_FLAG_NOPWRITE); } dr->dt.dl.dr_overridden_by = *zio->io_bp; dr->dt.dl.dr_override_state = DR_OVERRIDDEN; @@ -1769,8 +1770,10 @@ dmu_write_policy(objset_t *os, dnode_t *dn, int level, int wp, zio_prop_t *zp) * as well. Otherwise, the metadata checksum defaults * to fletcher4. */ - if (zio_checksum_table[checksum].ci_correctable < 1 || - zio_checksum_table[checksum].ci_eck) + if (!(zio_checksum_table[checksum].ci_flags & + ZCHECKSUM_FLAG_METADATA) || + (zio_checksum_table[checksum].ci_flags & + ZCHECKSUM_FLAG_EMBEDDED)) checksum = ZIO_CHECKSUM_FLETCHER_4; if (os->os_redundant_metadata == ZFS_REDUNDANT_METADATA_ALL || @@ -1809,16 +1812,19 @@ dmu_write_policy(objset_t *os, dnode_t *dn, int level, int wp, zio_prop_t *zp) */ if (dedup_checksum != ZIO_CHECKSUM_OFF) { dedup = (wp & WP_DMU_SYNC) ? B_FALSE : B_TRUE; - if (!zio_checksum_table[checksum].ci_dedup) + if (!(zio_checksum_table[checksum].ci_flags & + ZCHECKSUM_FLAG_DEDUP)) dedup_verify = B_TRUE; } /* - * Enable nopwrite if we have a cryptographically secure - * checksum that has no known collisions (i.e. SHA-256) - * and compression is enabled. We don't enable nopwrite if - * dedup is enabled as the two features are mutually exclusive. + * Enable nopwrite if we have secure enough checksum + * algorithm (see comment in zio_nop_write) and + * compression is enabled. We don't enable nopwrite if + * dedup is enabled as the two features are mutually + * exclusive. */ - nopwrite = (!dedup && zio_checksum_table[checksum].ci_dedup && + nopwrite = (!dedup && (zio_checksum_table[checksum].ci_flags & + ZCHECKSUM_FLAG_NOPWRITE) && compress != ZIO_COMPRESS_OFF && zfs_nopwrite_enabled); } diff --git a/usr/src/uts/common/fs/zfs/dmu_objset.c b/usr/src/uts/common/fs/zfs/dmu_objset.c index 9ad18f0d11..f84ff378c9 100644 --- a/usr/src/uts/common/fs/zfs/dmu_objset.c +++ b/usr/src/uts/common/fs/zfs/dmu_objset.c @@ -680,40 +680,8 @@ dmu_objset_evict(objset_t *os) for (int t = 0; t < TXG_SIZE; t++) ASSERT(!dmu_objset_is_dirty(os, t)); - if (ds) { - if (!ds->ds_is_snapshot) { - VERIFY0(dsl_prop_unregister(ds, - zfs_prop_to_name(ZFS_PROP_CHECKSUM), - checksum_changed_cb, os)); - VERIFY0(dsl_prop_unregister(ds, - zfs_prop_to_name(ZFS_PROP_COMPRESSION), - compression_changed_cb, os)); - VERIFY0(dsl_prop_unregister(ds, - zfs_prop_to_name(ZFS_PROP_COPIES), - copies_changed_cb, os)); - VERIFY0(dsl_prop_unregister(ds, - zfs_prop_to_name(ZFS_PROP_DEDUP), - dedup_changed_cb, os)); - VERIFY0(dsl_prop_unregister(ds, - zfs_prop_to_name(ZFS_PROP_LOGBIAS), - logbias_changed_cb, os)); - VERIFY0(dsl_prop_unregister(ds, - zfs_prop_to_name(ZFS_PROP_SYNC), - sync_changed_cb, os)); - VERIFY0(dsl_prop_unregister(ds, - zfs_prop_to_name(ZFS_PROP_REDUNDANT_METADATA), - redundant_metadata_changed_cb, os)); - VERIFY0(dsl_prop_unregister(ds, - zfs_prop_to_name(ZFS_PROP_RECORDSIZE), - recordsize_changed_cb, os)); - } - VERIFY0(dsl_prop_unregister(ds, - zfs_prop_to_name(ZFS_PROP_PRIMARYCACHE), - primary_cache_changed_cb, os)); - VERIFY0(dsl_prop_unregister(ds, - zfs_prop_to_name(ZFS_PROP_SECONDARYCACHE), - secondary_cache_changed_cb, os)); - } + if (ds) + dsl_prop_unregister_all(ds, os); if (os->os_sa) sa_tear_down(os); diff --git a/usr/src/uts/common/fs/zfs/dmu_send.c b/usr/src/uts/common/fs/zfs/dmu_send.c index eeb77f4b1e..1323d5225a 100644 --- a/usr/src/uts/common/fs/zfs/dmu_send.c +++ b/usr/src/uts/common/fs/zfs/dmu_send.c @@ -268,7 +268,8 @@ dump_write(dmu_sendarg_t *dsp, dmu_object_type_t type, drrw->drr_checksumtype = ZIO_CHECKSUM_OFF; } else { drrw->drr_checksumtype = BP_GET_CHECKSUM(bp); - if (zio_checksum_table[drrw->drr_checksumtype].ci_dedup) + if (zio_checksum_table[drrw->drr_checksumtype].ci_flags & + ZCHECKSUM_FLAG_DEDUP) drrw->drr_checksumflags |= DRR_CHECKSUM_DEDUP; DDK_SET_LSIZE(&drrw->drr_key, BP_GET_LSIZE(bp)); DDK_SET_PSIZE(&drrw->drr_key, BP_GET_PSIZE(bp)); diff --git a/usr/src/uts/common/fs/zfs/dsl_dataset.c b/usr/src/uts/common/fs/zfs/dsl_dataset.c index 7f63cd97bc..8f9e26bc16 100644 --- a/usr/src/uts/common/fs/zfs/dsl_dataset.c +++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c @@ -50,6 +50,8 @@ #include <sys/dsl_destroy.h> #include <sys/dsl_userhold.h> #include <sys/dsl_bookmark.h> +#include <sys/dmu_send.h> +#include <sys/zio_checksum.h> /* * The SPA supports block sizes up to 16MB. However, very large blocks @@ -124,10 +126,16 @@ dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx) dsl_dataset_phys(ds)->ds_compressed_bytes += compressed; dsl_dataset_phys(ds)->ds_uncompressed_bytes += uncompressed; dsl_dataset_phys(ds)->ds_unique_bytes += used; + if (BP_GET_LSIZE(bp) > SPA_OLD_MAXBLOCKSIZE) { ds->ds_feature_activation_needed[SPA_FEATURE_LARGE_BLOCKS] = B_TRUE; } + + spa_feature_t f = zio_checksum_to_feature(BP_GET_CHECKSUM(bp)); + if (f != SPA_FEATURE_NONE) + ds->ds_feature_activation_needed[f] = B_TRUE; + mutex_exit(&ds->ds_lock); dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD, delta, compressed, uncompressed, tx); @@ -282,6 +290,7 @@ dsl_dataset_evict(void *dbu) ASSERT(!list_link_active(&ds->ds_synced_link)); + list_destroy(&ds->ds_prop_cbs); mutex_destroy(&ds->ds_lock); mutex_destroy(&ds->ds_opening_lock); mutex_destroy(&ds->ds_sendstream_lock); @@ -424,6 +433,9 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag, list_create(&ds->ds_sendstreams, sizeof (dmu_sendarg_t), offsetof(dmu_sendarg_t, dsa_link)); + list_create(&ds->ds_prop_cbs, sizeof (dsl_prop_cb_record_t), + offsetof(dsl_prop_cb_record_t, cbr_ds_node)); + if (doi.doi_type == DMU_OTN_ZAP_METADATA) { for (spa_feature_t f = 0; f < SPA_FEATURES; f++) { if (!(spa_feature_table[f].fi_flags & diff --git a/usr/src/uts/common/fs/zfs/dsl_dir.c b/usr/src/uts/common/fs/zfs/dsl_dir.c index 1222b8933a..ca7d8b9bee 100644 --- a/usr/src/uts/common/fs/zfs/dsl_dir.c +++ b/usr/src/uts/common/fs/zfs/dsl_dir.c @@ -148,11 +148,7 @@ dsl_dir_evict(void *dbu) spa_async_close(dd->dd_pool->dp_spa, dd); - /* - * The props callback list should have been cleaned up by - * objset_evict(). - */ - list_destroy(&dd->dd_prop_cbs); + dsl_prop_fini(dd); mutex_destroy(&dd->dd_lock); kmem_free(dd, sizeof (dsl_dir_t)); } @@ -187,9 +183,7 @@ dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj, dd->dd_dbuf = dbuf; dd->dd_pool = dp; mutex_init(&dd->dd_lock, NULL, MUTEX_DEFAULT, NULL); - - list_create(&dd->dd_prop_cbs, sizeof (dsl_prop_cb_record_t), - offsetof(dsl_prop_cb_record_t, cbr_node)); + dsl_prop_init(dd); dsl_dir_snap_cmtime_update(dd); @@ -247,6 +241,7 @@ dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj, if (winner != NULL) { if (dd->dd_parent) dsl_dir_rele(dd->dd_parent, dd); + dsl_prop_fini(dd); mutex_destroy(&dd->dd_lock); kmem_free(dd, sizeof (dsl_dir_t)); dd = winner; @@ -274,6 +269,7 @@ dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj, errout: if (dd->dd_parent) dsl_dir_rele(dd->dd_parent, dd); + dsl_prop_fini(dd); mutex_destroy(&dd->dd_lock); kmem_free(dd, sizeof (dsl_dir_t)); dmu_buf_rele(dbuf, tag); diff --git a/usr/src/uts/common/fs/zfs/dsl_prop.c b/usr/src/uts/common/fs/zfs/dsl_prop.c index 09eec21604..353de42d1e 100644 --- a/usr/src/uts/common/fs/zfs/dsl_prop.c +++ b/usr/src/uts/common/fs/zfs/dsl_prop.c @@ -216,6 +216,58 @@ dsl_prop_get_ds(dsl_dataset_t *ds, const char *propname, intsz, numints, buf, setpoint, ds->ds_is_snapshot)); } +static dsl_prop_record_t * +dsl_prop_record_find(dsl_dir_t *dd, const char *propname) +{ + dsl_prop_record_t *pr = NULL; + + ASSERT(MUTEX_HELD(&dd->dd_lock)); + + for (pr = list_head(&dd->dd_props); + pr != NULL; pr = list_next(&dd->dd_props, pr)) { + if (strcmp(pr->pr_propname, propname) == 0) + break; + } + + return (pr); +} + +static dsl_prop_record_t * +dsl_prop_record_create(dsl_dir_t *dd, const char *propname) +{ + dsl_prop_record_t *pr; + + ASSERT(MUTEX_HELD(&dd->dd_lock)); + + pr = kmem_alloc(sizeof (dsl_prop_record_t), KM_SLEEP); + pr->pr_propname = spa_strdup(propname); + list_create(&pr->pr_cbs, sizeof (dsl_prop_cb_record_t), + offsetof(dsl_prop_cb_record_t, cbr_pr_node)); + list_insert_head(&dd->dd_props, pr); + + return (pr); +} + +void +dsl_prop_init(dsl_dir_t *dd) +{ + list_create(&dd->dd_props, sizeof (dsl_prop_record_t), + offsetof(dsl_prop_record_t, pr_node)); +} + +void +dsl_prop_fini(dsl_dir_t *dd) +{ + dsl_prop_record_t *pr; + + while ((pr = list_remove_head(&dd->dd_props)) != NULL) { + list_destroy(&pr->pr_cbs); + strfree((char *)pr->pr_propname); + kmem_free(pr, sizeof (dsl_prop_record_t)); + } + list_destroy(&dd->dd_props); +} + /* * Register interest in the named property. We'll call the callback * once to notify it of the current property value, and again each time @@ -230,6 +282,7 @@ dsl_prop_register(dsl_dataset_t *ds, const char *propname, dsl_dir_t *dd = ds->ds_dir; dsl_pool_t *dp = dd->dd_pool; uint64_t value; + dsl_prop_record_t *pr; dsl_prop_cb_record_t *cbr; int err; @@ -241,12 +294,16 @@ dsl_prop_register(dsl_dataset_t *ds, const char *propname, cbr = kmem_alloc(sizeof (dsl_prop_cb_record_t), KM_SLEEP); cbr->cbr_ds = ds; - cbr->cbr_propname = kmem_alloc(strlen(propname)+1, KM_SLEEP); - (void) strcpy((char *)cbr->cbr_propname, propname); cbr->cbr_func = callback; cbr->cbr_arg = cbarg; + mutex_enter(&dd->dd_lock); - list_insert_head(&dd->dd_prop_cbs, cbr); + pr = dsl_prop_record_find(dd, propname); + if (pr == NULL) + pr = dsl_prop_record_create(dd, propname); + cbr->cbr_pr = pr; + list_insert_head(&pr->pr_cbs, cbr); + list_insert_head(&ds->ds_prop_cbs, cbr); mutex_exit(&dd->dd_lock); cbr->cbr_func(cbr->cbr_arg, value); @@ -377,56 +434,34 @@ dsl_prop_predict(dsl_dir_t *dd, const char *propname, } /* - * Unregister this callback. Return 0 on success, ENOENT if ddname is - * invalid, or ENOMSG if no matching callback registered. + * Unregister all callbacks that are registered with the + * given callback argument. */ -int -dsl_prop_unregister(dsl_dataset_t *ds, const char *propname, - dsl_prop_changed_cb_t *callback, void *cbarg) +void +dsl_prop_unregister_all(dsl_dataset_t *ds, void *cbarg) { + dsl_prop_cb_record_t *cbr, *next_cbr; + dsl_dir_t *dd = ds->ds_dir; - dsl_prop_cb_record_t *cbr; mutex_enter(&dd->dd_lock); - for (cbr = list_head(&dd->dd_prop_cbs); - cbr; cbr = list_next(&dd->dd_prop_cbs, cbr)) { - if (cbr->cbr_ds == ds && - cbr->cbr_func == callback && - cbr->cbr_arg == cbarg && - strcmp(cbr->cbr_propname, propname) == 0) - break; - } - - if (cbr == NULL) { - mutex_exit(&dd->dd_lock); - return (SET_ERROR(ENOMSG)); + next_cbr = list_head(&ds->ds_prop_cbs); + while (next_cbr != NULL) { + cbr = next_cbr; + next_cbr = list_next(&ds->ds_prop_cbs, cbr); + if (cbr->cbr_arg == cbarg) { + list_remove(&ds->ds_prop_cbs, cbr); + list_remove(&cbr->cbr_pr->pr_cbs, cbr); + kmem_free(cbr, sizeof (dsl_prop_cb_record_t)); + } } - - list_remove(&dd->dd_prop_cbs, cbr); mutex_exit(&dd->dd_lock); - kmem_free((void*)cbr->cbr_propname, strlen(cbr->cbr_propname)+1); - kmem_free(cbr, sizeof (dsl_prop_cb_record_t)); - - return (0); } boolean_t dsl_prop_hascb(dsl_dataset_t *ds) { - dsl_dir_t *dd = ds->ds_dir; - boolean_t rv = B_FALSE; - dsl_prop_cb_record_t *cbr; - - mutex_enter(&dd->dd_lock); - for (cbr = list_head(&dd->dd_prop_cbs); cbr; - cbr = list_next(&dd->dd_prop_cbs, cbr)) { - if (cbr->cbr_ds == ds) { - rv = B_TRUE; - break; - } - } - mutex_exit(&dd->dd_lock); - return (rv); + return (!list_is_empty(&ds->ds_prop_cbs)); } /* ARGSUSED */ @@ -434,38 +469,50 @@ static int dsl_prop_notify_all_cb(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg) { dsl_dir_t *dd = ds->ds_dir; + dsl_prop_record_t *pr; dsl_prop_cb_record_t *cbr; mutex_enter(&dd->dd_lock); - for (cbr = list_head(&dd->dd_prop_cbs); cbr; - cbr = list_next(&dd->dd_prop_cbs, cbr)) { - uint64_t value; + for (pr = list_head(&dd->dd_props); + pr; pr = list_next(&dd->dd_props, pr)) { + for (cbr = list_head(&pr->pr_cbs); cbr; + cbr = list_next(&pr->pr_cbs, cbr)) { + uint64_t value; - /* - * Callback entries do not have holds on their datasets - * so that datasets with registered callbacks are still - * eligible for eviction. Unlike operations on callbacks - * for a single dataset, we are performing a recursive - * descent of related datasets and the calling context - * for this iteration only has a dataset hold on the root. - * Without a hold, the callback's pointer to the dataset - * could be invalidated by eviction at any time. - * - * Use dsl_dataset_try_add_ref() to verify that the - * dataset has not begun eviction processing and to - * prevent eviction from occurring for the duration - * of the callback. If the hold attempt fails, this - * object is already being evicted and the callback can - * be safely ignored. - */ - if (!dsl_dataset_try_add_ref(dp, cbr->cbr_ds, FTAG)) - continue; + /* + * Callback entries do not have holds on their + * datasets so that datasets with registered + * callbacks are still eligible for eviction. + * Unlike operations to update properties on a + * single dataset, we are performing a recursive + * descent of related head datasets. The caller + * of this function only has a dataset hold on + * the passed in head dataset, not the snapshots + * associated with this dataset. Without a hold, + * the dataset pointer within callback records + * for snapshots can be invalidated by eviction + * at any time. + * + * Use dsl_dataset_try_add_ref() to verify + * that the dataset for a snapshot has not + * begun eviction processing and to prevent + * eviction from occurring for the duration of + * the callback. If the hold attempt fails, + * this object is already being evicted and the + * callback can be safely ignored. + */ + if (ds != cbr->cbr_ds && + !dsl_dataset_try_add_ref(dp, cbr->cbr_ds, FTAG)) + continue; - if (dsl_prop_get_ds(cbr->cbr_ds, cbr->cbr_propname, - sizeof (value), 1, &value, NULL) == 0) - cbr->cbr_func(cbr->cbr_arg, value); + if (dsl_prop_get_ds(cbr->cbr_ds, + cbr->cbr_pr->pr_propname, sizeof (value), 1, + &value, NULL) == 0) + cbr->cbr_func(cbr->cbr_arg, value); - dsl_dataset_rele(cbr->cbr_ds, FTAG); + if (ds != cbr->cbr_ds) + dsl_dataset_rele(cbr->cbr_ds, FTAG); + } } mutex_exit(&dd->dd_lock); @@ -490,6 +537,7 @@ dsl_prop_changed_notify(dsl_pool_t *dp, uint64_t ddobj, const char *propname, uint64_t value, int first) { dsl_dir_t *dd; + dsl_prop_record_t *pr; dsl_prop_cb_record_t *cbr; objset_t *mos = dp->dp_meta_objset; zap_cursor_t zc; @@ -516,30 +564,33 @@ dsl_prop_changed_notify(dsl_pool_t *dp, uint64_t ddobj, } mutex_enter(&dd->dd_lock); - for (cbr = list_head(&dd->dd_prop_cbs); cbr; - cbr = list_next(&dd->dd_prop_cbs, cbr)) { - uint64_t propobj; + pr = dsl_prop_record_find(dd, propname); + if (pr != NULL) { + for (cbr = list_head(&pr->pr_cbs); cbr; + cbr = list_next(&pr->pr_cbs, cbr)) { + uint64_t propobj; - /* - * cbr->cbf_ds may be invalidated due to eviction, - * requiring the use of dsl_dataset_try_add_ref(). - * See comment block in dsl_prop_notify_all_cb() - * for details. - */ - if (strcmp(cbr->cbr_propname, propname) != 0 || - !dsl_dataset_try_add_ref(dp, cbr->cbr_ds, FTAG)) - continue; + /* + * cbr->cbr_ds may be invalidated due to eviction, + * requiring the use of dsl_dataset_try_add_ref(). + * See comment block in dsl_prop_notify_all_cb() + * for details. + */ + if (!dsl_dataset_try_add_ref(dp, cbr->cbr_ds, FTAG)) + continue; - propobj = dsl_dataset_phys(cbr->cbr_ds)->ds_props_obj; + propobj = dsl_dataset_phys(cbr->cbr_ds)->ds_props_obj; - /* - * If the property is not set on this ds, then it is - * inherited here; call the callback. - */ - if (propobj == 0 || zap_contains(mos, propobj, propname) != 0) - cbr->cbr_func(cbr->cbr_arg, value); + /* + * If the property is not set on this ds, then it is + * inherited here; call the callback. + */ + if (propobj == 0 || + zap_contains(mos, propobj, propname) != 0) + cbr->cbr_func(cbr->cbr_arg, value); - dsl_dataset_rele(cbr->cbr_ds, FTAG); + dsl_dataset_rele(cbr->cbr_ds, FTAG); + } } mutex_exit(&dd->dd_lock); @@ -679,10 +730,10 @@ dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname, * ds here. */ mutex_enter(&ds->ds_dir->dd_lock); - for (cbr = list_head(&ds->ds_dir->dd_prop_cbs); cbr; - cbr = list_next(&ds->ds_dir->dd_prop_cbs, cbr)) { - if (cbr->cbr_ds == ds && - strcmp(cbr->cbr_propname, propname) == 0) + for (cbr = list_head(&ds->ds_prop_cbs); cbr; + cbr = list_next(&ds->ds_prop_cbs, cbr)) { + if (strcmp(cbr->cbr_pr->pr_propname, + propname) == 0) cbr->cbr_func(cbr->cbr_arg, intval); } mutex_exit(&ds->ds_dir->dd_lock); diff --git a/usr/src/uts/common/fs/zfs/edonr_zfs.c b/usr/src/uts/common/fs/zfs/edonr_zfs.c new file mode 100644 index 0000000000..93f1221fd5 --- /dev/null +++ b/usr/src/uts/common/fs/zfs/edonr_zfs.c @@ -0,0 +1,102 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2013 Saso Kiselkov. All rights reserved. + * Use is subject to license terms. + */ +#include <sys/zfs_context.h> +#include <sys/zio.h> +#include <sys/edonr.h> + +#define EDONR_MODE 512 +#define EDONR_BLOCK_SIZE EdonR512_BLOCK_SIZE + +/* + * Native zio_checksum interface for the Edon-R hash function. + */ +/*ARGSUSED*/ +void +zio_checksum_edonr_native(const void *buf, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp) +{ + uint8_t digest[EDONR_MODE / 8]; + EdonRState ctx; + + ASSERT(ctx_template != NULL); + bcopy(ctx_template, &ctx, sizeof (ctx)); + EdonRUpdate(&ctx, buf, size * 8); + EdonRFinal(&ctx, digest); + bcopy(digest, zcp->zc_word, sizeof (zcp->zc_word)); +} + +/* + * Byteswapped zio_checksum interface for the Edon-R hash function. + */ +void +zio_checksum_edonr_byteswap(const void *buf, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp) +{ + zio_cksum_t tmp; + + zio_checksum_edonr_native(buf, size, ctx_template, &tmp); + zcp->zc_word[0] = BSWAP_64(zcp->zc_word[0]); + zcp->zc_word[1] = BSWAP_64(zcp->zc_word[1]); + zcp->zc_word[2] = BSWAP_64(zcp->zc_word[2]); + zcp->zc_word[3] = BSWAP_64(zcp->zc_word[3]); +} + +void * +zio_checksum_edonr_tmpl_init(const zio_cksum_salt_t *salt) +{ + EdonRState *ctx; + uint8_t salt_block[EDONR_BLOCK_SIZE]; + + /* + * Edon-R needs all but the last hash invocation to be on full-size + * blocks, but the salt is too small. Rather than simply padding it + * with zeros, we expand the salt into a new salt block of proper + * size by double-hashing it (the new salt block will be composed of + * H(salt) || H(H(salt))). + */ + CTASSERT(EDONR_BLOCK_SIZE == 2 * (EDONR_MODE / 8)); + EdonRHash(EDONR_MODE, salt->zcs_bytes, sizeof (salt->zcs_bytes) * 8, + salt_block); + EdonRHash(EDONR_MODE, salt_block, EDONR_MODE, salt_block + + EDONR_MODE / 8); + + /* + * Feed the new salt block into the hash function - this will serve + * as our MAC key. + */ + ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP); + EdonRInit(ctx, EDONR_MODE); + EdonRUpdate(ctx, salt_block, sizeof (salt_block) * 8); + return (ctx); +} + +void +zio_checksum_edonr_tmpl_free(void *ctx_template) +{ + EdonRState *ctx = ctx_template; + + bzero(ctx, sizeof (*ctx)); + kmem_free(ctx, sizeof (*ctx)); +} diff --git a/usr/src/uts/common/fs/zfs/sha256.c b/usr/src/uts/common/fs/zfs/sha256.c index f515be6bb3..81a7f6b1c2 100644 --- a/usr/src/uts/common/fs/zfs/sha256.c +++ b/usr/src/uts/common/fs/zfs/sha256.c @@ -22,12 +22,17 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2013 Saso Kiselkov. All rights reserved. + */ #include <sys/zfs_context.h> #include <sys/zio.h> #include <sys/sha2.h> +/*ARGSUSED*/ void -zio_checksum_SHA256(const void *buf, uint64_t size, zio_cksum_t *zcp) +zio_checksum_SHA256(const void *buf, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp) { SHA2_CTX ctx; zio_cksum_t tmp; @@ -48,3 +53,29 @@ zio_checksum_SHA256(const void *buf, uint64_t size, zio_cksum_t *zcp) zcp->zc_word[2] = BE_64(tmp.zc_word[2]); zcp->zc_word[3] = BE_64(tmp.zc_word[3]); } + +/*ARGSUSED*/ +void +zio_checksum_SHA512_native(const void *buf, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp) +{ + SHA2_CTX ctx; + + SHA2Init(SHA512_256, &ctx); + SHA2Update(&ctx, buf, size); + SHA2Final(zcp, &ctx); +} + +/*ARGSUSED*/ +void +zio_checksum_SHA512_byteswap(const void *buf, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp) +{ + zio_cksum_t tmp; + + zio_checksum_SHA512_native(buf, size, ctx_template, &tmp); + zcp->zc_word[0] = BSWAP_64(tmp.zc_word[0]); + zcp->zc_word[1] = BSWAP_64(tmp.zc_word[1]); + zcp->zc_word[2] = BSWAP_64(tmp.zc_word[2]); + zcp->zc_word[3] = BSWAP_64(tmp.zc_word[3]); +} diff --git a/usr/src/uts/common/fs/zfs/skein_zfs.c b/usr/src/uts/common/fs/zfs/skein_zfs.c new file mode 100644 index 0000000000..6592340396 --- /dev/null +++ b/usr/src/uts/common/fs/zfs/skein_zfs.c @@ -0,0 +1,91 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2013 Saso Kiselkov. All rights reserved. + */ +#include <sys/zfs_context.h> +#include <sys/zio.h> +#include <sys/skein.h> + +/* + * Computes a native 256-bit skein MAC checksum. Please note that this + * function requires the presence of a ctx_template that should be allocated + * using zio_checksum_skein_tmpl_init. + */ +/*ARGSUSED*/ +void +zio_checksum_skein_native(const void *buf, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp) +{ + Skein_512_Ctxt_t ctx; + + ASSERT(ctx_template != NULL); + bcopy(ctx_template, &ctx, sizeof (ctx)); + (void) Skein_512_Update(&ctx, buf, size); + (void) Skein_512_Final(&ctx, (uint8_t *)zcp); + bzero(&ctx, sizeof (ctx)); +} + +/* + * Byteswapped version of zio_checksum_skein_native. This just invokes + * the native checksum function and byteswaps the resulting checksum (since + * skein is internally endian-insensitive). + */ +void +zio_checksum_skein_byteswap(const void *buf, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp) +{ + zio_cksum_t tmp; + + zio_checksum_skein_native(buf, size, ctx_template, &tmp); + zcp->zc_word[0] = BSWAP_64(tmp.zc_word[0]); + zcp->zc_word[1] = BSWAP_64(tmp.zc_word[1]); + zcp->zc_word[2] = BSWAP_64(tmp.zc_word[2]); + zcp->zc_word[3] = BSWAP_64(tmp.zc_word[3]); +} + +/* + * Allocates a skein MAC template suitable for using in skein MAC checksum + * computations and returns a pointer to it. + */ +void * +zio_checksum_skein_tmpl_init(const zio_cksum_salt_t *salt) +{ + Skein_512_Ctxt_t *ctx; + + ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP); + (void) Skein_512_InitExt(ctx, sizeof (zio_cksum_t) * 8, 0, + salt->zcs_bytes, sizeof (salt->zcs_bytes)); + return (ctx); +} + +/* + * Frees a skein context template previously allocated using + * zio_checksum_skein_tmpl_init. + */ +void +zio_checksum_skein_tmpl_free(void *ctx_template) +{ + Skein_512_Ctxt_t *ctx = ctx_template; + + bzero(ctx, sizeof (*ctx)); + kmem_free(ctx, sizeof (*ctx)); +} diff --git a/usr/src/uts/common/fs/zfs/spa.c b/usr/src/uts/common/fs/zfs/spa.c index 537c0945d1..95a6b0fae7 100644 --- a/usr/src/uts/common/fs/zfs/spa.c +++ b/usr/src/uts/common/fs/zfs/spa.c @@ -24,6 +24,7 @@ * Copyright (c) 2011, 2014 by Delphix. All rights reserved. * Copyright (c) 2015, Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. + * Copyright 2013 Saso Kiselkov. All rights reserved. */ /* @@ -2512,6 +2513,19 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config, return (spa_load(spa, state, SPA_IMPORT_EXISTING, B_TRUE)); } + /* Grab the secret checksum salt from the MOS. */ + error = zap_lookup(spa->spa_meta_objset, DMU_POOL_DIRECTORY_OBJECT, + DMU_POOL_CHECKSUM_SALT, 1, + sizeof (spa->spa_cksum_salt.zcs_bytes), + spa->spa_cksum_salt.zcs_bytes); + if (error == ENOENT) { + /* Generate a new salt for subsequent use */ + (void) random_get_pseudo_bytes(spa->spa_cksum_salt.zcs_bytes, + sizeof (spa->spa_cksum_salt.zcs_bytes)); + } else if (error != 0) { + return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO)); + } + if (spa_dir_prop(spa, DMU_POOL_SYNC_BPOBJ, &obj) != 0) return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, EIO)); error = bpobj_open(&spa->spa_deferred_bpobj, spa->spa_meta_objset, obj); @@ -3665,6 +3679,12 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props, spa_history_create_obj(spa, tx); /* + * Generate some random noise for salted checksums to operate on. + */ + (void) random_get_pseudo_bytes(spa->spa_cksum_salt.zcs_bytes, + sizeof (spa->spa_cksum_salt.zcs_bytes)); + + /* * Set pool properties. */ spa->spa_bootfs = zpool_prop_default_numeric(ZPOOL_PROP_BOOTFS); @@ -6215,6 +6235,20 @@ spa_sync_upgrades(spa_t *spa, dmu_tx_t *tx) if (lz4_en && !lz4_ac) spa_feature_incr(spa, SPA_FEATURE_LZ4_COMPRESS, tx); } + + /* + * If we haven't written the salt, do so now. Note that the + * feature may not be activated yet, but that's fine since + * the presence of this ZAP entry is backwards compatible. + */ + if (zap_contains(spa->spa_meta_objset, DMU_POOL_DIRECTORY_OBJECT, + DMU_POOL_CHECKSUM_SALT) == ENOENT) { + VERIFY0(zap_add(spa->spa_meta_objset, + DMU_POOL_DIRECTORY_OBJECT, DMU_POOL_CHECKSUM_SALT, 1, + sizeof (spa->spa_cksum_salt.zcs_bytes), + spa->spa_cksum_salt.zcs_bytes, tx)); + } + rrw_exit(&dp->dp_config_rwlock, FTAG); } diff --git a/usr/src/uts/common/fs/zfs/spa_misc.c b/usr/src/uts/common/fs/zfs/spa_misc.c index c5af055a86..9148a03433 100644 --- a/usr/src/uts/common/fs/zfs/spa_misc.c +++ b/usr/src/uts/common/fs/zfs/spa_misc.c @@ -23,6 +23,7 @@ * Copyright (c) 2011, 2015 by Delphix. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. + * Copyright 2013 Saso Kiselkov. All rights reserved. */ #include <sys/zfs_context.h> @@ -50,7 +51,7 @@ #include <sys/arc.h> #include <sys/ddt.h> #include "zfs_prop.h" -#include "zfeature_common.h" +#include <sys/zfeature.h> /* * SPA locking @@ -556,6 +557,7 @@ spa_add(const char *name, nvlist_t *config, const char *altroot) mutex_init(&spa->spa_history_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&spa->spa_proc_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&spa->spa_props_lock, NULL, MUTEX_DEFAULT, NULL); + mutex_init(&spa->spa_cksum_tmpls_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&spa->spa_scrub_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&spa->spa_suspend_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&spa->spa_vdev_top_lock, NULL, MUTEX_DEFAULT, NULL); @@ -716,6 +718,8 @@ spa_remove(spa_t *spa) for (int t = 0; t < TXG_SIZE; t++) bplist_destroy(&spa->spa_free_bplist[t]); + zio_checksum_templates_free(spa); + cv_destroy(&spa->spa_async_cv); cv_destroy(&spa->spa_evicting_os_cv); cv_destroy(&spa->spa_proc_cv); @@ -729,6 +733,7 @@ spa_remove(spa_t *spa) mutex_destroy(&spa->spa_history_lock); mutex_destroy(&spa->spa_proc_lock); mutex_destroy(&spa->spa_props_lock); + mutex_destroy(&spa->spa_cksum_tmpls_lock); mutex_destroy(&spa->spa_scrub_lock); mutex_destroy(&spa->spa_suspend_lock); mutex_destroy(&spa->spa_vdev_top_lock); diff --git a/usr/src/uts/common/fs/zfs/sys/dmu.h b/usr/src/uts/common/fs/zfs/sys/dmu.h index 149cb112f9..c10806989d 100644 --- a/usr/src/uts/common/fs/zfs/sys/dmu.h +++ b/usr/src/uts/common/fs/zfs/sys/dmu.h @@ -27,6 +27,7 @@ * Copyright 2013 DEY Storage Systems, Inc. * Copyright 2014 HybridCluster. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. + * Copyright 2013 Saso Kiselkov. All rights reserved. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -318,6 +319,7 @@ typedef struct dmu_buf { #define DMU_POOL_FREE_BPOBJ "free_bpobj" #define DMU_POOL_BPTREE_OBJ "bptree_obj" #define DMU_POOL_EMPTY_BPOBJ "empty_bpobj" +#define DMU_POOL_CHECKSUM_SALT "org.illumos:checksum_salt" /* * Allocate an object from this objset. The range of object numbers diff --git a/usr/src/uts/common/fs/zfs/sys/dsl_dataset.h b/usr/src/uts/common/fs/zfs/sys/dsl_dataset.h index 001bff566a..c9cd5890aa 100644 --- a/usr/src/uts/common/fs/zfs/sys/dsl_dataset.h +++ b/usr/src/uts/common/fs/zfs/sys/dsl_dataset.h @@ -184,6 +184,9 @@ typedef struct dsl_dataset { kmutex_t ds_sendstream_lock; list_t ds_sendstreams; + /* Protected by our dsl_dir's dd_lock */ + list_t ds_prop_cbs; + /* * For ZFEATURE_FLAG_PER_DATASET features, set if this dataset * uses this feature. diff --git a/usr/src/uts/common/fs/zfs/sys/dsl_dir.h b/usr/src/uts/common/fs/zfs/sys/dsl_dir.h index f50014d95a..93fb73f37e 100644 --- a/usr/src/uts/common/fs/zfs/sys/dsl_dir.h +++ b/usr/src/uts/common/fs/zfs/sys/dsl_dir.h @@ -102,7 +102,7 @@ struct dsl_dir { /* Protected by dd_lock */ kmutex_t dd_lock; - list_t dd_prop_cbs; /* list of dsl_prop_cb_record_t's */ + list_t dd_props; /* list of dsl_prop_record_t's */ timestruc_t dd_snap_cmtime; /* last time snapshot namespace changed */ uint64_t dd_origin_txg; diff --git a/usr/src/uts/common/fs/zfs/sys/dsl_prop.h b/usr/src/uts/common/fs/zfs/sys/dsl_prop.h index 5fe18d6a7c..21e6f4674b 100644 --- a/usr/src/uts/common/fs/zfs/sys/dsl_prop.h +++ b/usr/src/uts/common/fs/zfs/sys/dsl_prop.h @@ -41,10 +41,17 @@ struct dsl_dir; /* The callback func may not call into the DMU or DSL! */ typedef void (dsl_prop_changed_cb_t)(void *arg, uint64_t newval); +typedef struct dsl_prop_record { + list_node_t pr_node; /* link on dd_props */ + const char *pr_propname; + list_t pr_cbs; +} dsl_prop_record_t; + typedef struct dsl_prop_cb_record { - list_node_t cbr_node; /* link on dd_prop_cbs */ + list_node_t cbr_pr_node; /* link on pr_cbs */ + list_node_t cbr_ds_node; /* link on ds_prop_cbs */ + dsl_prop_record_t *cbr_pr; struct dsl_dataset *cbr_ds; - const char *cbr_propname; dsl_prop_changed_cb_t *cbr_func; void *cbr_arg; } dsl_prop_cb_record_t; @@ -54,10 +61,11 @@ typedef struct dsl_props_arg { zprop_source_t pa_source; } dsl_props_arg_t; +void dsl_prop_init(dsl_dir_t *dd); +void dsl_prop_fini(dsl_dir_t *dd); int dsl_prop_register(struct dsl_dataset *ds, const char *propname, dsl_prop_changed_cb_t *callback, void *cbarg); -int dsl_prop_unregister(struct dsl_dataset *ds, const char *propname, - dsl_prop_changed_cb_t *callback, void *cbarg); +void dsl_prop_unregister_all(struct dsl_dataset *ds, void *cbarg); void dsl_prop_notify_all(struct dsl_dir *dd); boolean_t dsl_prop_hascb(struct dsl_dataset *ds); diff --git a/usr/src/uts/common/fs/zfs/sys/spa.h b/usr/src/uts/common/fs/zfs/sys/spa.h index 2c4887b6ca..7ac7839033 100644 --- a/usr/src/uts/common/fs/zfs/sys/spa.h +++ b/usr/src/uts/common/fs/zfs/sys/spa.h @@ -23,6 +23,7 @@ * Copyright (c) 2011, 2014 by Delphix. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. + * Copyright 2013 Saso Kiselkov. All rights reserved. */ #ifndef _SYS_SPA_H @@ -147,6 +148,14 @@ typedef struct zio_cksum { } zio_cksum_t; /* + * Some checksums/hashes need a 256-bit initialization salt. This salt is kept + * secret and is suitable for use in MAC algorithms as the key. + */ +typedef struct zio_cksum_salt { + uint8_t zcs_bytes[32]; +} zio_cksum_salt_t; + +/* * Each block is described by its DVAs, time of birth, checksum, etc. * The word-by-word, bit-by-bit layout of the blkptr is as follows: * diff --git a/usr/src/uts/common/fs/zfs/sys/spa_impl.h b/usr/src/uts/common/fs/zfs/sys/spa_impl.h index 56e6adb713..4418001982 100644 --- a/usr/src/uts/common/fs/zfs/sys/spa_impl.h +++ b/usr/src/uts/common/fs/zfs/sys/spa_impl.h @@ -23,6 +23,7 @@ * Copyright (c) 2011, 2015 by Delphix. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. + * Copyright 2013 Saso Kiselkov. All rights reserved. */ #ifndef _SYS_SPA_IMPL_H @@ -165,6 +166,10 @@ struct spa { uint64_t spa_syncing_txg; /* txg currently syncing */ bpobj_t spa_deferred_bpobj; /* deferred-free bplist */ bplist_t spa_free_bplist[TXG_SIZE]; /* bplist of stuff to free */ + zio_cksum_salt_t spa_cksum_salt; /* secret salt for cksum */ + /* checksum context templates */ + kmutex_t spa_cksum_tmpls_lock; + void *spa_cksum_tmpls[ZIO_CHECKSUM_FUNCTIONS]; uberblock_t spa_ubsync; /* last synced uberblock */ uberblock_t spa_uberblock; /* current uberblock */ boolean_t spa_extreme_rewind; /* rewind past deferred frees */ diff --git a/usr/src/uts/common/fs/zfs/sys/zio.h b/usr/src/uts/common/fs/zfs/sys/zio.h index fff6897bf6..b32f1492e6 100644 --- a/usr/src/uts/common/fs/zfs/sys/zio.h +++ b/usr/src/uts/common/fs/zfs/sys/zio.h @@ -82,6 +82,9 @@ enum zio_checksum { ZIO_CHECKSUM_SHA256, ZIO_CHECKSUM_ZILOG2, ZIO_CHECKSUM_NOPARITY, + ZIO_CHECKSUM_SHA512, + ZIO_CHECKSUM_SKEIN, + ZIO_CHECKSUM_EDONR, ZIO_CHECKSUM_FUNCTIONS }; diff --git a/usr/src/uts/common/fs/zfs/sys/zio_checksum.h b/usr/src/uts/common/fs/zfs/sys/zio_checksum.h index 0c293ab20e..572b29d3cb 100644 --- a/usr/src/uts/common/fs/zfs/sys/zio_checksum.h +++ b/usr/src/uts/common/fs/zfs/sys/zio_checksum.h @@ -20,13 +20,15 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014 by Delphix. All rights reserved. + * Copyright (c) 2014, 2015 by Delphix. All rights reserved. + * Copyright Saso Kiselkov 2013, All rights reserved. */ #ifndef _SYS_ZIO_CHECKSUM_H #define _SYS_ZIO_CHECKSUM_H #include <sys/zio.h> +#include <zfeature_common.h> #ifdef __cplusplus extern "C" { @@ -35,17 +37,34 @@ extern "C" { /* * Signature for checksum functions. */ -typedef void zio_checksum_func_t(const void *, uint64_t, zio_cksum_t *); +typedef void zio_checksum_t(const void *data, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp); +typedef void *zio_checksum_tmpl_init_t(const zio_cksum_salt_t *salt); +typedef void zio_checksum_tmpl_free_t(void *ctx_template); + +typedef enum zio_checksum_flags { + /* Strong enough for metadata? */ + ZCHECKSUM_FLAG_METADATA = (1 << 1), + /* ZIO embedded checksum */ + ZCHECKSUM_FLAG_EMBEDDED = (1 << 2), + /* Strong enough for dedup (without verification)? */ + ZCHECKSUM_FLAG_DEDUP = (1 << 3), + /* Uses salt value */ + ZCHECKSUM_FLAG_SALTED = (1 << 4), + /* Strong enough for nopwrite? */ + ZCHECKSUM_FLAG_NOPWRITE = (1 << 5) +} zio_checksum_flags_t; /* * Information about each checksum function. */ typedef struct zio_checksum_info { - zio_checksum_func_t *ci_func[2]; /* checksum function per byteorder */ - int ci_correctable; /* number of correctable bits */ - int ci_eck; /* uses zio embedded checksum? */ - boolean_t ci_dedup; /* strong enough for dedup? */ - char *ci_name; /* descriptive name */ + /* checksum function for each byteorder */ + zio_checksum_t *ci_func[2]; + zio_checksum_tmpl_init_t *ci_tmpl_init; + zio_checksum_tmpl_free_t *ci_tmpl_free; + zio_checksum_flags_t ci_flags; + char *ci_name; /* descriptive name */ } zio_checksum_info_t; typedef struct zio_bad_cksum { @@ -62,12 +81,28 @@ extern zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS]; /* * Checksum routines. */ -extern zio_checksum_func_t zio_checksum_SHA256; +extern zio_checksum_t zio_checksum_SHA256; +extern zio_checksum_t zio_checksum_SHA512_native; +extern zio_checksum_t zio_checksum_SHA512_byteswap; + +/* Skein */ +extern zio_checksum_t zio_checksum_skein_native; +extern zio_checksum_t zio_checksum_skein_byteswap; +extern zio_checksum_tmpl_init_t zio_checksum_skein_tmpl_init; +extern zio_checksum_tmpl_free_t zio_checksum_skein_tmpl_free; + +/* Edon-R */ +extern zio_checksum_t zio_checksum_edonr_native; +extern zio_checksum_t zio_checksum_edonr_byteswap; +extern zio_checksum_tmpl_init_t zio_checksum_edonr_tmpl_init; +extern zio_checksum_tmpl_free_t zio_checksum_edonr_tmpl_free; extern void zio_checksum_compute(zio_t *zio, enum zio_checksum checksum, void *data, uint64_t size); extern int zio_checksum_error(zio_t *zio, zio_bad_cksum_t *out); extern enum zio_checksum spa_dedup_checksum(spa_t *spa); +extern void zio_checksum_templates_free(spa_t *spa); +extern spa_feature_t zio_checksum_to_feature(enum zio_checksum cksum); #ifdef __cplusplus } diff --git a/usr/src/uts/common/fs/zfs/zfs_ioctl.c b/usr/src/uts/common/fs/zfs/zfs_ioctl.c index 2cd123d8b7..21097f94ae 100644 --- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c +++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c @@ -180,6 +180,7 @@ #include <sys/dsl_bookmark.h> #include <sys/dsl_userhold.h> #include <sys/zfeature.h> +#include <sys/zio_checksum.h> #include "zfs_namecheck.h" #include "zfs_prop.h" @@ -3855,11 +3856,6 @@ zfs_check_settable(const char *dsname, nvpair_t *pair, cred_t *cr) return (SET_ERROR(ENOTSUP)); break; - case ZFS_PROP_DEDUP: - if (zfs_earlier_version(dsname, SPA_VERSION_DEDUP)) - return (SET_ERROR(ENOTSUP)); - break; - case ZFS_PROP_RECORDSIZE: /* Record sizes above 128k need the feature to be enabled */ if (nvpair_value_uint64(pair, &intval) == 0 && @@ -3910,6 +3906,45 @@ zfs_check_settable(const char *dsname, nvpair_t *pair, cred_t *cr) return (SET_ERROR(ENOTSUP)); } break; + + case ZFS_PROP_CHECKSUM: + case ZFS_PROP_DEDUP: + { + spa_feature_t feature; + spa_t *spa; + + /* dedup feature version checks */ + if (prop == ZFS_PROP_DEDUP && + zfs_earlier_version(dsname, SPA_VERSION_DEDUP)) + return (SET_ERROR(ENOTSUP)); + + if (nvpair_value_uint64(pair, &intval) != 0) + return (SET_ERROR(EINVAL)); + + /* check prop value is enabled in features */ + feature = zio_checksum_to_feature(intval); + if (feature == SPA_FEATURE_NONE) + break; + + if ((err = spa_open(dsname, &spa, FTAG)) != 0) + return (err); + /* + * Salted checksums are not supported on root pools. + */ + if (spa_bootfs(spa) != 0 && + intval < ZIO_CHECKSUM_FUNCTIONS && + (zio_checksum_table[intval].ci_flags & + ZCHECKSUM_FLAG_SALTED)) { + spa_close(spa, FTAG); + return (SET_ERROR(ERANGE)); + } + if (!spa_feature_is_enabled(spa, feature)) { + spa_close(spa, FTAG); + return (SET_ERROR(ENOTSUP)); + } + spa_close(spa, FTAG); + break; + } } return (zfs_secpolicy_setprop(dsname, prop, pair, CRED())); diff --git a/usr/src/uts/common/fs/zfs/zfs_vfsops.c b/usr/src/uts/common/fs/zfs/zfs_vfsops.c index 0ebc173fed..daa8289502 100644 --- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c +++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c @@ -562,33 +562,7 @@ zfs_register_callbacks(vfs_t *vfsp) return (0); unregister: - /* - * We may attempt to unregister some callbacks that are not - * registered, but this is OK; it will simply return ENOMSG, - * which we will ignore. - */ - (void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_ATIME), - atime_changed_cb, zfsvfs); - (void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_XATTR), - xattr_changed_cb, zfsvfs); - (void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_RECORDSIZE), - blksz_changed_cb, zfsvfs); - (void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_READONLY), - readonly_changed_cb, zfsvfs); - (void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_DEVICES), - devices_changed_cb, zfsvfs); - (void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_SETUID), - setuid_changed_cb, zfsvfs); - (void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_EXEC), - exec_changed_cb, zfsvfs); - (void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_SNAPDIR), - snapdir_changed_cb, zfsvfs); - (void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_ACLMODE), - acl_mode_changed_cb, zfsvfs); - (void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_ACLINHERIT), - acl_inherit_changed_cb, zfsvfs); - (void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_VSCAN), - vscan_changed_cb, zfsvfs); + dsl_prop_unregister_all(ds, zfsvfs); return (error); } @@ -1250,46 +1224,9 @@ void zfs_unregister_callbacks(zfsvfs_t *zfsvfs) { objset_t *os = zfsvfs->z_os; - struct dsl_dataset *ds; - - /* - * Unregister properties. - */ - if (!dmu_objset_is_snapshot(os)) { - ds = dmu_objset_ds(os); - VERIFY(dsl_prop_unregister(ds, "atime", atime_changed_cb, - zfsvfs) == 0); - - VERIFY(dsl_prop_unregister(ds, "xattr", xattr_changed_cb, - zfsvfs) == 0); - - VERIFY(dsl_prop_unregister(ds, "recordsize", blksz_changed_cb, - zfsvfs) == 0); - VERIFY(dsl_prop_unregister(ds, "readonly", readonly_changed_cb, - zfsvfs) == 0); - - VERIFY(dsl_prop_unregister(ds, "devices", devices_changed_cb, - zfsvfs) == 0); - - VERIFY(dsl_prop_unregister(ds, "setuid", setuid_changed_cb, - zfsvfs) == 0); - - VERIFY(dsl_prop_unregister(ds, "exec", exec_changed_cb, - zfsvfs) == 0); - - VERIFY(dsl_prop_unregister(ds, "snapdir", snapdir_changed_cb, - zfsvfs) == 0); - - VERIFY(dsl_prop_unregister(ds, "aclmode", acl_mode_changed_cb, - zfsvfs) == 0); - - VERIFY(dsl_prop_unregister(ds, "aclinherit", - acl_inherit_changed_cb, zfsvfs) == 0); - - VERIFY(dsl_prop_unregister(ds, "vscan", - vscan_changed_cb, zfsvfs) == 0); - } + if (!dmu_objset_is_snapshot(os)) + dsl_prop_unregister_all(dmu_objset_ds(os), zfsvfs); } /* diff --git a/usr/src/uts/common/fs/zfs/zio.c b/usr/src/uts/common/fs/zfs/zio.c index 059ffea0e5..df534001df 100644 --- a/usr/src/uts/common/fs/zfs/zio.c +++ b/usr/src/uts/common/fs/zfs/zio.c @@ -934,7 +934,7 @@ zio_write_phys(zio_t *pio, vdev_t *vd, uint64_t offset, uint64_t size, zio->io_prop.zp_checksum = checksum; - if (zio_checksum_table[checksum].ci_eck) { + if (zio_checksum_table[checksum].ci_flags & ZCHECKSUM_FLAG_EMBEDDED) { /* * zec checksums are necessarily destructive -- they modify * the end of the write buffer to hold the verifier/checksum. @@ -1130,8 +1130,8 @@ zio_write_bp_init(zio_t *zio) if (BP_IS_HOLE(bp) || !zp->zp_dedup) return (ZIO_PIPELINE_CONTINUE); - ASSERT(zio_checksum_table[zp->zp_checksum].ci_dedup || - zp->zp_dedup_verify); + ASSERT((zio_checksum_table[zp->zp_checksum].ci_flags & + ZCHECKSUM_FLAG_DEDUP) || zp->zp_dedup_verify); if (BP_GET_CHECKSUM(bp) == zp->zp_checksum) { BP_SET_DEDUP(bp, 1); @@ -1986,12 +1986,22 @@ zio_write_gang_block(zio_t *pio) } /* - * The zio_nop_write stage in the pipeline determines if allocating - * a new bp is necessary. By leveraging a cryptographically secure checksum, - * such as SHA256, we can compare the checksums of the new data and the old - * to determine if allocating a new block is required. The nopwrite - * feature can handle writes in either syncing or open context (i.e. zil - * writes) and as a result is mutually exclusive with dedup. + * The zio_nop_write stage in the pipeline determines if allocating a + * new bp is necessary. The nopwrite feature can handle writes in + * either syncing or open context (i.e. zil writes) and as a result is + * mutually exclusive with dedup. + * + * By leveraging a cryptographically secure checksum, such as SHA256, we + * can compare the checksums of the new data and the old to determine if + * allocating a new block is required. Note that our requirements for + * cryptographic strength are fairly weak: there can't be any accidental + * hash collisions, but we don't need to be secure against intentional + * (malicious) collisions. To trigger a nopwrite, you have to be able + * to write the file to begin with, and triggering an incorrect (hash + * collision) nopwrite is no worse than simply writing to the file. + * That said, there are no known attacks against the checksum algorithms + * used for nopwrite, assuming that the salt and the checksums + * themselves remain secret. */ static int zio_nop_write(zio_t *zio) @@ -2014,7 +2024,8 @@ zio_nop_write(zio_t *zio) * allocate a new bp. */ if (BP_IS_HOLE(bp_orig) || - !zio_checksum_table[BP_GET_CHECKSUM(bp)].ci_dedup || + !(zio_checksum_table[BP_GET_CHECKSUM(bp)].ci_flags & + ZCHECKSUM_FLAG_NOPWRITE) || BP_GET_CHECKSUM(bp) != BP_GET_CHECKSUM(bp_orig) || BP_GET_COMPRESS(bp) != BP_GET_COMPRESS(bp_orig) || BP_GET_DEDUP(bp) != BP_GET_DEDUP(bp_orig) || @@ -2026,7 +2037,8 @@ zio_nop_write(zio_t *zio) * avoid allocating a new bp and issuing any I/O. */ if (ZIO_CHECKSUM_EQUAL(bp->blk_cksum, bp_orig->blk_cksum)) { - ASSERT(zio_checksum_table[zp->zp_checksum].ci_dedup); + ASSERT(zio_checksum_table[zp->zp_checksum].ci_flags & + ZCHECKSUM_FLAG_NOPWRITE); ASSERT3U(BP_GET_PSIZE(bp), ==, BP_GET_PSIZE(bp_orig)); ASSERT3U(BP_GET_LSIZE(bp), ==, BP_GET_LSIZE(bp_orig)); ASSERT(zp->zp_compress != ZIO_COMPRESS_OFF); @@ -2307,7 +2319,8 @@ zio_ddt_write(zio_t *zio) * we can't resolve it, so just convert to an ordinary write. * (And automatically e-mail a paper to Nature?) */ - if (!zio_checksum_table[zp->zp_checksum].ci_dedup) { + if (!(zio_checksum_table[zp->zp_checksum].ci_flags & + ZCHECKSUM_FLAG_DEDUP)) { zp->zp_checksum = spa_dedup_checksum(spa); zio_pop_transforms(zio); zio->io_stage = ZIO_STAGE_OPEN; diff --git a/usr/src/uts/common/fs/zfs/zio_checksum.c b/usr/src/uts/common/fs/zfs/zio_checksum.c index d1c60c3ffa..b471ad9047 100644 --- a/usr/src/uts/common/fs/zfs/zio_checksum.c +++ b/usr/src/uts/common/fs/zfs/zio_checksum.c @@ -22,10 +22,12 @@ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright 2013 Saso Kiselkov. All rights reserved. */ #include <sys/zfs_context.h> #include <sys/spa.h> +#include <sys/spa_impl.h> #include <sys/zio.h> #include <sys/zio_checksum.h> #include <sys/zil.h> @@ -59,29 +61,95 @@ * checksum function of the appropriate strength. When reading a block, * we compare the expected checksum against the actual checksum, which we * compute via the checksum function specified by BP_GET_CHECKSUM(bp). + * + * SALTED CHECKSUMS + * + * To enable the use of less secure hash algorithms with dedup, we + * introduce the notion of salted checksums (MACs, really). A salted + * checksum is fed both a random 256-bit value (the salt) and the data + * to be checksummed. This salt is kept secret (stored on the pool, but + * never shown to the user). Thus even if an attacker knew of collision + * weaknesses in the hash algorithm, they won't be able to mount a known + * plaintext attack on the DDT, since the actual hash value cannot be + * known ahead of time. How the salt is used is algorithm-specific + * (some might simply prefix it to the data block, others might need to + * utilize a full-blown HMAC). On disk the salt is stored in a ZAP + * object in the MOS (DMU_POOL_CHECKSUM_SALT). + * + * CONTEXT TEMPLATES + * + * Some hashing algorithms need to perform a substantial amount of + * initialization work (e.g. salted checksums above may need to pre-hash + * the salt) before being able to process data. Performing this + * redundant work for each block would be wasteful, so we instead allow + * a checksum algorithm to do the work once (the first time it's used) + * and then keep this pre-initialized context as a template inside the + * spa_t (spa_cksum_tmpls). If the zio_checksum_info_t contains + * non-NULL ci_tmpl_init and ci_tmpl_free callbacks, they are used to + * construct and destruct the pre-initialized checksum context. The + * pre-initialized context is then reused during each checksum + * invocation and passed to the checksum function. */ /*ARGSUSED*/ static void -zio_checksum_off(const void *buf, uint64_t size, zio_cksum_t *zcp) +zio_checksum_off(const void *buf, uint64_t size, + const void *ctx_template, zio_cksum_t *zcp) { ZIO_SET_CHECKSUM(zcp, 0, 0, 0, 0); } zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = { - {{NULL, NULL}, 0, 0, 0, "inherit"}, - {{NULL, NULL}, 0, 0, 0, "on"}, - {{zio_checksum_off, zio_checksum_off}, 0, 0, 0, "off"}, - {{zio_checksum_SHA256, zio_checksum_SHA256}, 1, 1, 0, "label"}, - {{zio_checksum_SHA256, zio_checksum_SHA256}, 1, 1, 0, "gang_header"}, - {{fletcher_2_native, fletcher_2_byteswap}, 0, 1, 0, "zilog"}, - {{fletcher_2_native, fletcher_2_byteswap}, 0, 0, 0, "fletcher2"}, - {{fletcher_4_native, fletcher_4_byteswap}, 1, 0, 0, "fletcher4"}, - {{zio_checksum_SHA256, zio_checksum_SHA256}, 1, 0, 1, "sha256"}, - {{fletcher_4_native, fletcher_4_byteswap}, 0, 1, 0, "zilog2"}, - {{zio_checksum_off, zio_checksum_off}, 0, 0, 0, "noparity"}, + {{NULL, NULL}, NULL, NULL, 0, "inherit"}, + {{NULL, NULL}, NULL, NULL, 0, "on"}, + {{zio_checksum_off, zio_checksum_off}, + NULL, NULL, 0, "off"}, + {{zio_checksum_SHA256, zio_checksum_SHA256}, + NULL, NULL, ZCHECKSUM_FLAG_METADATA | ZCHECKSUM_FLAG_EMBEDDED, + "label"}, + {{zio_checksum_SHA256, zio_checksum_SHA256}, + NULL, NULL, ZCHECKSUM_FLAG_METADATA | ZCHECKSUM_FLAG_EMBEDDED, + "gang_header"}, + {{fletcher_2_native, fletcher_2_byteswap}, + NULL, NULL, ZCHECKSUM_FLAG_EMBEDDED, "zilog"}, + {{fletcher_2_native, fletcher_2_byteswap}, + NULL, NULL, 0, "fletcher2"}, + {{fletcher_4_native, fletcher_4_byteswap}, + NULL, NULL, ZCHECKSUM_FLAG_METADATA, "fletcher4"}, + {{zio_checksum_SHA256, zio_checksum_SHA256}, + NULL, NULL, ZCHECKSUM_FLAG_METADATA | ZCHECKSUM_FLAG_DEDUP | + ZCHECKSUM_FLAG_NOPWRITE, "sha256"}, + {{fletcher_4_native, fletcher_4_byteswap}, + NULL, NULL, ZCHECKSUM_FLAG_EMBEDDED, "zilog2"}, + {{zio_checksum_off, zio_checksum_off}, + NULL, NULL, 0, "noparity"}, + {{zio_checksum_SHA512_native, zio_checksum_SHA512_byteswap}, + NULL, NULL, ZCHECKSUM_FLAG_METADATA | ZCHECKSUM_FLAG_DEDUP | + ZCHECKSUM_FLAG_NOPWRITE, "sha512"}, + {{zio_checksum_skein_native, zio_checksum_skein_byteswap}, + zio_checksum_skein_tmpl_init, zio_checksum_skein_tmpl_free, + ZCHECKSUM_FLAG_METADATA | ZCHECKSUM_FLAG_DEDUP | + ZCHECKSUM_FLAG_SALTED | ZCHECKSUM_FLAG_NOPWRITE, "skein"}, + {{zio_checksum_edonr_native, zio_checksum_edonr_byteswap}, + zio_checksum_edonr_tmpl_init, zio_checksum_edonr_tmpl_free, + ZCHECKSUM_FLAG_METADATA | ZCHECKSUM_FLAG_SALTED | + ZCHECKSUM_FLAG_NOPWRITE, "edonr"}, }; +spa_feature_t +zio_checksum_to_feature(enum zio_checksum cksum) +{ + switch (cksum) { + case ZIO_CHECKSUM_SHA512: + return (SPA_FEATURE_SHA512); + case ZIO_CHECKSUM_SKEIN: + return (SPA_FEATURE_SKEIN); + case ZIO_CHECKSUM_EDONR: + return (SPA_FEATURE_EDONR); + } + return (SPA_FEATURE_NONE); +} + enum zio_checksum zio_checksum_select(enum zio_checksum child, enum zio_checksum parent) { @@ -115,7 +183,8 @@ zio_checksum_dedup_select(spa_t *spa, enum zio_checksum child, if (child == (ZIO_CHECKSUM_ON | ZIO_CHECKSUM_VERIFY)) return (spa_dedup_checksum(spa) | ZIO_CHECKSUM_VERIFY); - ASSERT(zio_checksum_table[child & ZIO_CHECKSUM_MASK].ci_dedup || + ASSERT((zio_checksum_table[child & ZIO_CHECKSUM_MASK].ci_flags & + ZCHECKSUM_FLAG_DEDUP) || (child & ZIO_CHECKSUM_VERIFY) || child == ZIO_CHECKSUM_OFF); return (child); @@ -148,6 +217,30 @@ zio_checksum_label_verifier(zio_cksum_t *zcp, uint64_t offset) } /* + * Calls the template init function of a checksum which supports context + * templates and installs the template into the spa_t. + */ +static void +zio_checksum_template_init(enum zio_checksum checksum, spa_t *spa) +{ + zio_checksum_info_t *ci = &zio_checksum_table[checksum]; + + if (ci->ci_tmpl_init == NULL) + return; + if (spa->spa_cksum_tmpls[checksum] != NULL) + return; + + VERIFY(ci->ci_tmpl_free != NULL); + mutex_enter(&spa->spa_cksum_tmpls_lock); + if (spa->spa_cksum_tmpls[checksum] == NULL) { + spa->spa_cksum_tmpls[checksum] = + ci->ci_tmpl_init(&spa->spa_cksum_salt); + VERIFY(spa->spa_cksum_tmpls[checksum] != NULL); + } + mutex_exit(&spa->spa_cksum_tmpls_lock); +} + +/* * Generate the checksum. */ void @@ -158,11 +251,14 @@ zio_checksum_compute(zio_t *zio, enum zio_checksum checksum, uint64_t offset = zio->io_offset; zio_checksum_info_t *ci = &zio_checksum_table[checksum]; zio_cksum_t cksum; + spa_t *spa = zio->io_spa; ASSERT((uint_t)checksum < ZIO_CHECKSUM_FUNCTIONS); ASSERT(ci->ci_func[0] != NULL); - if (ci->ci_eck) { + zio_checksum_template_init(checksum, spa); + + if (ci->ci_flags & ZCHECKSUM_FLAG_EMBEDDED) { zio_eck_t *eck; if (checksum == ZIO_CHECKSUM_ZILOG2) { @@ -181,10 +277,12 @@ zio_checksum_compute(zio_t *zio, enum zio_checksum checksum, else bp->blk_cksum = eck->zec_cksum; eck->zec_magic = ZEC_MAGIC; - ci->ci_func[0](data, size, &cksum); + ci->ci_func[0](data, size, spa->spa_cksum_tmpls[checksum], + &cksum); eck->zec_cksum = cksum; } else { - ci->ci_func[0](data, size, &bp->blk_cksum); + ci->ci_func[0](data, size, spa->spa_cksum_tmpls[checksum], + &bp->blk_cksum); } } @@ -202,11 +300,14 @@ zio_checksum_error(zio_t *zio, zio_bad_cksum_t *info) void *data = zio->io_data; zio_checksum_info_t *ci = &zio_checksum_table[checksum]; zio_cksum_t actual_cksum, expected_cksum, verifier; + spa_t *spa = zio->io_spa; if (checksum >= ZIO_CHECKSUM_FUNCTIONS || ci->ci_func[0] == NULL) return (SET_ERROR(EINVAL)); - if (ci->ci_eck) { + zio_checksum_template_init(checksum, spa); + + if (ci->ci_flags & ZCHECKSUM_FLAG_EMBEDDED) { zio_eck_t *eck; if (checksum == ZIO_CHECKSUM_ZILOG2) { @@ -243,7 +344,8 @@ zio_checksum_error(zio_t *zio, zio_bad_cksum_t *info) expected_cksum = eck->zec_cksum; eck->zec_cksum = verifier; - ci->ci_func[byteswap](data, size, &actual_cksum); + ci->ci_func[byteswap](data, size, + spa->spa_cksum_tmpls[checksum], &actual_cksum); eck->zec_cksum = expected_cksum; if (byteswap) @@ -253,7 +355,8 @@ zio_checksum_error(zio_t *zio, zio_bad_cksum_t *info) ASSERT(!BP_IS_GANG(bp)); byteswap = BP_SHOULD_BYTESWAP(bp); expected_cksum = bp->blk_cksum; - ci->ci_func[byteswap](data, size, &actual_cksum); + ci->ci_func[byteswap](data, size, + spa->spa_cksum_tmpls[checksum], &actual_cksum); } info->zbc_expected = expected_cksum; @@ -275,3 +378,23 @@ zio_checksum_error(zio_t *zio, zio_bad_cksum_t *info) return (0); } + +/* + * Called by a spa_t that's about to be deallocated. This steps through + * all of the checksum context templates and deallocates any that were + * initialized using the algorithm-specific template init function. + */ +void +zio_checksum_templates_free(spa_t *spa) +{ + for (enum zio_checksum checksum = 0; + checksum < ZIO_CHECKSUM_FUNCTIONS; checksum++) { + if (spa->spa_cksum_tmpls[checksum] != NULL) { + zio_checksum_info_t *ci = &zio_checksum_table[checksum]; + + VERIFY(ci->ci_tmpl_free != NULL); + ci->ci_tmpl_free(spa->spa_cksum_tmpls[checksum]); + spa->spa_cksum_tmpls[checksum] = NULL; + } + } +} diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile index b646989821..c81a9f1a92 100644 --- a/usr/src/uts/common/sys/Makefile +++ b/usr/src/uts/common/sys/Makefile @@ -23,6 +23,7 @@ # Copyright 2013, Joyent, Inc. All rights reserved. # Copyright 2013 Garrett D'Amore <garrett@damore.org> # Copyright 2015, Joyent, Inc. All rights reserved. +# Copyright 2013 Saso Kiselkov. All rights reserved. # include $(SRC)/uts/Makefile.uts @@ -202,6 +203,7 @@ CHKHDRS= \ ecppio.h \ ecppreg.h \ ecppvar.h \ + edonr.h \ efi_partition.h \ elf.h \ elf_386.h \ @@ -513,6 +515,7 @@ CHKHDRS= \ siginfo.h \ signal.h \ signalfd.h \ + skein.h \ sleepq.h \ smbios.h \ smbios_impl.h \ diff --git a/usr/src/uts/common/sys/crypto/common.h b/usr/src/uts/common/sys/crypto/common.h index 8fc7b05de6..68283c390a 100644 --- a/usr/src/uts/common/sys/crypto/common.h +++ b/usr/src/uts/common/sys/crypto/common.h @@ -21,6 +21,9 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. */ +/* + * Copyright 2013 Saso Kiselkov. All rights reserved. + */ #ifndef _SYS_CRYPTO_COMMON_H #define _SYS_CRYPTO_COMMON_H @@ -194,6 +197,8 @@ typedef uint32_t crypto_keysize_unit_t; #define SUN_CKM_SHA512 "CKM_SHA512" #define SUN_CKM_SHA512_HMAC "CKM_SHA512_HMAC" #define SUN_CKM_SHA512_HMAC_GENERAL "CKM_SHA512_HMAC_GENERAL" +#define SUN_CKM_SHA512_224 "CKM_SHA512_224" +#define SUN_CKM_SHA512_256 "CKM_SHA512_256" #define SUN_CKM_DES_CBC "CKM_DES_CBC" #define SUN_CKM_DES3_CBC "CKM_DES3_CBC" #define SUN_CKM_DES_ECB "CKM_DES_ECB" diff --git a/usr/src/uts/common/sys/debug.h b/usr/src/uts/common/sys/debug.h index 27b84beb88..8efc8956b6 100644 --- a/usr/src/uts/common/sys/debug.h +++ b/usr/src/uts/common/sys/debug.h @@ -27,6 +27,7 @@ /* * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright 2013 Saso Kiselkov. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -124,6 +125,14 @@ _NOTE(CONSTCOND) } while (0) #define ASSERT0(x) ((void)0) #endif +/* + * Compile-time assertion. The condition 'x' must be constant. + */ +#define CTASSERT(x) _CTASSERT(x, __LINE__) +#define _CTASSERT(x, y) __CTASSERT(x, y) +#define __CTASSERT(x, y) \ + typedef char __compile_time_assertion__ ## y [(x) ? 1 : -1] + #ifdef _KERNEL extern void abort_sequence_enter(char *); diff --git a/usr/src/uts/common/sys/edonr.h b/usr/src/uts/common/sys/edonr.h new file mode 100644 index 0000000000..e65118dc1f --- /dev/null +++ b/usr/src/uts/common/sys/edonr.h @@ -0,0 +1,93 @@ +/* + * IDI,NTNU + * + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Copyright (C) 2009, 2010, Jorn Amundsen <jorn.amundsen@ntnu.no> + * + * Tweaked Edon-R implementation for SUPERCOP, based on NIST API. + * + * $Id: edonr.h 517 2013-02-17 20:34:39Z joern $ + */ +/* + * Portions copyright (c) 2013, Saso Kiselkov, All rights reserved + */ + +#ifndef _SYS_EDONR_H_ +#define _SYS_EDONR_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> + +/* + * EdonR allows to call EdonRUpdate() consecutively only if the total length + * of stored unprocessed data and the new supplied data is less than or equal + * to the BLOCK_SIZE on which the compression functions operates. + * Otherwise an assertion failure is invoked. + */ + +/* Specific algorithm definitions */ +#define EdonR224_DIGEST_SIZE 28 +#define EdonR224_BLOCK_SIZE 64 +#define EdonR256_DIGEST_SIZE 32 +#define EdonR256_BLOCK_SIZE 64 +#define EdonR384_DIGEST_SIZE 48 +#define EdonR384_BLOCK_SIZE 128 +#define EdonR512_DIGEST_SIZE 64 +#define EdonR512_BLOCK_SIZE 128 + +#define EdonR256_BLOCK_BITSIZE 512 +#define EdonR512_BLOCK_BITSIZE 1024 + +typedef struct { + uint32_t DoublePipe[16]; + uint8_t LastPart[EdonR256_BLOCK_SIZE * 2]; +} EdonRData256; +typedef struct { + uint64_t DoublePipe[16]; + uint8_t LastPart[EdonR512_BLOCK_SIZE * 2]; +} EdonRData512; + +typedef struct { + size_t hashbitlen; + + /* + algorithm specific parameters */ + int unprocessed_bits; + uint64_t bits_processed; + union { + EdonRData256 p256[1]; + EdonRData512 p512[1]; + } pipe[1]; +} EdonRState; + +void EdonRInit(EdonRState *state, size_t hashbitlen); +void EdonRUpdate(EdonRState *state, const uint8_t *data, size_t databitlen); +void EdonRFinal(EdonRState *state, uint8_t *hashval); +void EdonRHash(size_t hashbitlen, const uint8_t *data, size_t databitlen, + uint8_t *hashval); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_EDONR_H_ */ diff --git a/usr/src/uts/common/sys/sha2.h b/usr/src/uts/common/sys/sha2.h index ad46dd683a..4dd966b6ca 100644 --- a/usr/src/uts/common/sys/sha2.h +++ b/usr/src/uts/common/sys/sha2.h @@ -22,6 +22,7 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* Copyright 2013 Saso Kiselkov. All rights reserved. */ #ifndef _SYS_SHA2_H #define _SYS_SHA2_H @@ -39,6 +40,10 @@ extern "C" { #define SHA384_DIGEST_LENGTH 48 /* SHA384 digest length in bytes */ #define SHA512_DIGEST_LENGTH 64 /* SHA512 digest length in bytes */ +/* Truncated versions of SHA-512 according to FIPS-180-4, section 5.3.6 */ +#define SHA512_224_DIGEST_LENGTH 28 /* SHA512/224 digest length */ +#define SHA512_256_DIGEST_LENGTH 32 /* SHA512/256 digest length */ + #define SHA256_HMAC_BLOCK_SIZE 64 /* SHA256-HMAC block size */ #define SHA512_HMAC_BLOCK_SIZE 128 /* SHA512-HMAC block size */ @@ -51,6 +56,8 @@ extern "C" { #define SHA512 6 #define SHA512_HMAC 7 #define SHA512_HMAC_GEN 8 +#define SHA512_224 9 +#define SHA512_256 10 /* * SHA2 context. @@ -130,7 +137,9 @@ typedef enum sha2_mech_type { SHA384_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA384_HMAC_GENERAL */ SHA512_MECH_INFO_TYPE, /* SUN_CKM_SHA512 */ SHA512_HMAC_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC */ - SHA512_HMAC_GEN_MECH_INFO_TYPE /* SUN_CKM_SHA512_HMAC_GENERAL */ + SHA512_HMAC_GEN_MECH_INFO_TYPE, /* SUN_CKM_SHA512_HMAC_GENERAL */ + SHA512_224_MECH_INFO_TYPE, /* SUN_CKM_SHA512_224 */ + SHA512_256_MECH_INFO_TYPE /* SUN_CKM_SHA512_256 */ } sha2_mech_type_t; #endif /* _SHA2_IMPL */ diff --git a/usr/src/uts/common/sys/skein.h b/usr/src/uts/common/sys/skein.h new file mode 100644 index 0000000000..423e1dc34e --- /dev/null +++ b/usr/src/uts/common/sys/skein.h @@ -0,0 +1,178 @@ +/* + * Interface declarations for Skein hashing. + * Source code author: Doug Whiting, 2008. + * This algorithm and source code is released to the public domain. + * + * The following compile-time switches may be defined to control some + * tradeoffs between speed, code size, error checking, and security. + * + * The "default" note explains what happens when the switch is not defined. + * + * SKEIN_DEBUG -- make callouts from inside Skein code + * to examine/display intermediate values. + * [default: no callouts (no overhead)] + * + * SKEIN_ERR_CHECK -- how error checking is handled inside Skein + * code. If not defined, most error checking + * is disabled (for performance). Otherwise, + * the switch value is interpreted as: + * 0: use assert() to flag errors + * 1: return SKEIN_FAIL to flag errors + */ +/* Copyright 2013 Doug Whiting. This code is released to the public domain. */ +#ifndef _SYS_SKEIN_H_ +#define _SYS_SKEIN_H_ + +#include <sys/types.h> /* get size_t definition */ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + SKEIN_SUCCESS = 0, /* return codes from Skein calls */ + SKEIN_FAIL = 1, + SKEIN_BAD_HASHLEN = 2 +}; + +#define SKEIN_MODIFIER_WORDS (2) /* number of modifier (tweak) words */ + +#define SKEIN_256_STATE_WORDS (4) +#define SKEIN_512_STATE_WORDS (8) +#define SKEIN1024_STATE_WORDS (16) +#define SKEIN_MAX_STATE_WORDS (16) + +#define SKEIN_256_STATE_BYTES (8 * SKEIN_256_STATE_WORDS) +#define SKEIN_512_STATE_BYTES (8 * SKEIN_512_STATE_WORDS) +#define SKEIN1024_STATE_BYTES (8 * SKEIN1024_STATE_WORDS) + +#define SKEIN_256_STATE_BITS (64 * SKEIN_256_STATE_WORDS) +#define SKEIN_512_STATE_BITS (64 * SKEIN_512_STATE_WORDS) +#define SKEIN1024_STATE_BITS (64 * SKEIN1024_STATE_WORDS) + +#define SKEIN_256_BLOCK_BYTES (8 * SKEIN_256_STATE_WORDS) +#define SKEIN_512_BLOCK_BYTES (8 * SKEIN_512_STATE_WORDS) +#define SKEIN1024_BLOCK_BYTES (8 * SKEIN1024_STATE_WORDS) + +typedef struct { + size_t hashBitLen; /* size of hash result, in bits */ + size_t bCnt; /* current byte count in buffer b[] */ + /* tweak words: T[0]=byte cnt, T[1]=flags */ + uint64_t T[SKEIN_MODIFIER_WORDS]; +} Skein_Ctxt_Hdr_t; + +typedef struct { /* 256-bit Skein hash context structure */ + Skein_Ctxt_Hdr_t h; /* common header context variables */ + uint64_t X[SKEIN_256_STATE_WORDS]; /* chaining variables */ + /* partial block buffer (8-byte aligned) */ + uint8_t b[SKEIN_256_BLOCK_BYTES]; +} Skein_256_Ctxt_t; + +typedef struct { /* 512-bit Skein hash context structure */ + Skein_Ctxt_Hdr_t h; /* common header context variables */ + uint64_t X[SKEIN_512_STATE_WORDS]; /* chaining variables */ + /* partial block buffer (8-byte aligned) */ + uint8_t b[SKEIN_512_BLOCK_BYTES]; +} Skein_512_Ctxt_t; + +typedef struct { /* 1024-bit Skein hash context structure */ + Skein_Ctxt_Hdr_t h; /* common header context variables */ + uint64_t X[SKEIN1024_STATE_WORDS]; /* chaining variables */ + /* partial block buffer (8-byte aligned) */ + uint8_t b[SKEIN1024_BLOCK_BYTES]; +} Skein1024_Ctxt_t; + +/* Skein APIs for (incremental) "straight hashing" */ +int Skein_256_Init(Skein_256_Ctxt_t *ctx, size_t hashBitLen); +int Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen); +int Skein1024_Init(Skein1024_Ctxt_t *ctx, size_t hashBitLen); + +int Skein_256_Update(Skein_256_Ctxt_t *ctx, const uint8_t *msg, + size_t msgByteCnt); +int Skein_512_Update(Skein_512_Ctxt_t *ctx, const uint8_t *msg, + size_t msgByteCnt); +int Skein1024_Update(Skein1024_Ctxt_t *ctx, const uint8_t *msg, + size_t msgByteCnt); + +int Skein_256_Final(Skein_256_Ctxt_t *ctx, uint8_t *hashVal); +int Skein_512_Final(Skein_512_Ctxt_t *ctx, uint8_t *hashVal); +int Skein1024_Final(Skein1024_Ctxt_t *ctx, uint8_t *hashVal); + +/* + * Skein APIs for "extended" initialization: MAC keys, tree hashing. + * After an InitExt() call, just use Update/Final calls as with Init(). + * + * Notes: Same parameters as _Init() calls, plus treeInfo/key/keyBytes. + * When keyBytes == 0 and treeInfo == SKEIN_SEQUENTIAL, + * the results of InitExt() are identical to calling Init(). + * The function Init() may be called once to "precompute" the IV for + * a given hashBitLen value, then by saving a copy of the context + * the IV computation may be avoided in later calls. + * Similarly, the function InitExt() may be called once per MAC key + * to precompute the MAC IV, then a copy of the context saved and + * reused for each new MAC computation. + */ +int Skein_256_InitExt(Skein_256_Ctxt_t *ctx, size_t hashBitLen, + uint64_t treeInfo, const uint8_t *key, size_t keyBytes); +int Skein_512_InitExt(Skein_512_Ctxt_t *ctx, size_t hashBitLen, + uint64_t treeInfo, const uint8_t *key, size_t keyBytes); +int Skein1024_InitExt(Skein1024_Ctxt_t *ctx, size_t hashBitLen, + uint64_t treeInfo, const uint8_t *key, size_t keyBytes); + +/* + * Skein APIs for MAC and tree hash: + * Final_Pad: pad, do final block, but no OUTPUT type + * Output: do just the output stage + */ +int Skein_256_Final_Pad(Skein_256_Ctxt_t *ctx, uint8_t *hashVal); +int Skein_512_Final_Pad(Skein_512_Ctxt_t *ctx, uint8_t *hashVal); +int Skein1024_Final_Pad(Skein1024_Ctxt_t *ctx, uint8_t *hashVal); + +#ifndef SKEIN_TREE_HASH +#define SKEIN_TREE_HASH (1) +#endif +#if SKEIN_TREE_HASH +int Skein_256_Output(Skein_256_Ctxt_t *ctx, uint8_t *hashVal); +int Skein_512_Output(Skein_512_Ctxt_t *ctx, uint8_t *hashVal); +int Skein1024_Output(Skein1024_Ctxt_t *ctx, uint8_t *hashVal); +#endif + +/* + * When you initialize a Skein KCF hashing method you can pass this param + * structure in cm_param to fine-tune the algorithm's defaults. + */ +typedef struct skein_param { + size_t sp_digest_bitlen; /* length of digest in bits */ +} skein_param_t; + +/* Module definitions */ +#ifdef SKEIN_MODULE_IMPL +#define CKM_SKEIN_256 "CKM_SKEIN_256" +#define CKM_SKEIN_512 "CKM_SKEIN_512" +#define CKM_SKEIN1024 "CKM_SKEIN1024" +#define CKM_SKEIN_256_MAC "CKM_SKEIN_256_MAC" +#define CKM_SKEIN_512_MAC "CKM_SKEIN_512_MAC" +#define CKM_SKEIN1024_MAC "CKM_SKEIN1024_MAC" + +typedef enum skein_mech_type { + SKEIN_256_MECH_INFO_TYPE, + SKEIN_512_MECH_INFO_TYPE, + SKEIN1024_MECH_INFO_TYPE, + SKEIN_256_MAC_MECH_INFO_TYPE, + SKEIN_512_MAC_MECH_INFO_TYPE, + SKEIN1024_MAC_MECH_INFO_TYPE +} skein_mech_type_t; + +#define VALID_SKEIN_DIGEST_MECH(__mech) \ + ((int)(__mech) >= SKEIN_256_MECH_INFO_TYPE && \ + (__mech) <= SKEIN1024_MECH_INFO_TYPE) +#define VALID_SKEIN_MAC_MECH(__mech) \ + ((int)(__mech) >= SKEIN_256_MAC_MECH_INFO_TYPE && \ + (__mech) <= SKEIN1024_MAC_MECH_INFO_TYPE) +#endif /* SKEIN_MODULE_IMPL */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_SKEIN_H_ */ diff --git a/usr/src/uts/intel/Makefile.intel b/usr/src/uts/intel/Makefile.intel index 740f0a74a5..e136ec025d 100644 --- a/usr/src/uts/intel/Makefile.intel +++ b/usr/src/uts/intel/Makefile.intel @@ -674,11 +674,13 @@ CRYPTO_KMODS += arcfour CRYPTO_KMODS += blowfish CRYPTO_KMODS += des CRYPTO_KMODS += ecc +CRYPTO_KMODS += edonr CRYPTO_KMODS += md4 CRYPTO_KMODS += md5 CRYPTO_KMODS += rsa CRYPTO_KMODS += sha1 CRYPTO_KMODS += sha2 +CRYPTO_KMODS += skein CRYPTO_KMODS += swrand # diff --git a/usr/src/uts/intel/edonr/Makefile b/usr/src/uts/intel/edonr/Makefile new file mode 100644 index 0000000000..90c1ad761e --- /dev/null +++ b/usr/src/uts/intel/edonr/Makefile @@ -0,0 +1,92 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2013 Saso Kiselkov. All rights reserved. +# +# +# This makefile drives the production of the edonr kernel module. +# +# intel architecture dependent +# + +# +# Path to the base of the uts directory tree (usually /usr/src/uts). +# +UTSBASE = ../.. +COMDIR = $(COMMONBASE)/crypto + +# +# Define the module and object file sets. +# +MODULE = edonr +OBJECTS = $(EDONR_OBJS:%=$(OBJS_DIR)/%) +LINTS = $(EDONR_OBJS:%.o=$(LINTS_DIR)/%.ln) +ROOTMODULE = $(ROOT_CRYPTO_DIR)/$(MODULE) +ROOTLINK = $(ROOT_MISC_DIR)/$(MODULE) + +# +# Include common rules. +# +include $(UTSBASE)/intel/Makefile.intel + +# +# Define targets +# +ALL_TARGET = $(BINARY) +LINT_TARGET = $(MODULE).lint +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK) + +# +# Linkage dependencies +# +LDFLAGS += -dy -Nmisc/kcf + +CFLAGS += -I$(COMDIR) +LINTFLAGS += -I$(COMDIR) + +# +# Default build targets. +# +.KEEP_STATE: + +def: $(DEF_DEPS) + +all: $(ALL_DEPS) + +clean: $(CLEAN_DEPS) + +clobber: $(CLOBBER_DEPS) + +lint: $(LINT_DEPS) + +modlintlib: $(MODLINTLIB_DEPS) + +clean.lint: $(CLEAN_LINT_DEPS) + +install: $(INSTALL_DEPS) + +$(ROOTLINK): $(ROOT_MISC_DIR) $(ROOTMODULE) + -$(RM) $@; ln $(ROOTMODULE) $@ + +# +# Include common targets. +# +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/intel/skein/Makefile b/usr/src/uts/intel/skein/Makefile new file mode 100644 index 0000000000..1028a97b80 --- /dev/null +++ b/usr/src/uts/intel/skein/Makefile @@ -0,0 +1,92 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2013 Saso Kiselkov. All rights reserved. +# +# +# This makefile drives the production of the skein crypto kernel module. +# +# intel architecture dependent +# + +# +# Path to the base of the uts directory tree (usually /usr/src/uts). +# +UTSBASE = ../.. +COMDIR = $(COMMONBASE)/crypto + +# +# Define the module and object file sets. +# +MODULE = skein +OBJECTS = $(SKEIN_OBJS:%=$(OBJS_DIR)/%) +LINTS = $(SKEIN_OBJS:%.o=$(LINTS_DIR)/%.ln) +ROOTMODULE = $(ROOT_CRYPTO_DIR)/$(MODULE) +ROOTLINK = $(ROOT_MISC_DIR)/$(MODULE) + +# +# Include common rules. +# +include $(UTSBASE)/intel/Makefile.intel + +# +# Define targets +# +ALL_TARGET = $(BINARY) +LINT_TARGET = $(MODULE).lint +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK) + +# +# Linkage dependencies +# +LDFLAGS += -dy -Nmisc/kcf + +CFLAGS += -I$(COMDIR) +LINTFLAGS += -I$(COMDIR) + +# +# Default build targets. +# +.KEEP_STATE: + +def: $(DEF_DEPS) + +all: $(ALL_DEPS) + +clean: $(CLEAN_DEPS) + +clobber: $(CLOBBER_DEPS) + +lint: $(LINT_DEPS) + +modlintlib: $(MODLINTLIB_DEPS) + +clean.lint: $(CLEAN_LINT_DEPS) + +install: $(INSTALL_DEPS) + +$(ROOTLINK): $(ROOT_MISC_DIR) $(ROOTMODULE) + -$(RM) $@; ln $(ROOTMODULE) $@ + +# +# Include common targets. +# +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/intel/zfs/Makefile b/usr/src/uts/intel/zfs/Makefile index be0f82115c..ea5e947b76 100644 --- a/usr/src/uts/intel/zfs/Makefile +++ b/usr/src/uts/intel/zfs/Makefile @@ -24,6 +24,9 @@ # # This makefile drives the production of the zfs file system # kernel module. +# +# Copyright 2013 Saso Kiselkov. All rights reserved. +# # # Path to the base of the uts directory tree (usually /usr/src/uts). @@ -58,7 +61,8 @@ INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK) $(ROOT_CONFFILE) # Overrides and depends_on # MODSTUBS_DIR = $(OBJS_DIR) -LDFLAGS += -dy -Nfs/specfs -Ncrypto/swrand -Nmisc/idmap -Nmisc/sha2 +LDFLAGS += -dy -Nfs/specfs -Ncrypto/swrand -Nmisc/idmap -Nmisc/sha2 \ + -Nmisc/skein -Nmisc/edonr INC_PATH += -I$(UTSBASE)/common/fs/zfs INC_PATH += -I$(SRC)/common diff --git a/usr/src/uts/sparc/Makefile.sparc b/usr/src/uts/sparc/Makefile.sparc index e8458de8e3..a5f22cdace 100644 --- a/usr/src/uts/sparc/Makefile.sparc +++ b/usr/src/uts/sparc/Makefile.sparc @@ -434,12 +434,14 @@ CRYPTO_KMODS += aes CRYPTO_KMODS += arcfour CRYPTO_KMODS += blowfish CRYPTO_KMODS += des +CRYPTO_KMODS += ecc +CRYPTO_KMODS += edonr CRYPTO_KMODS += md4 CRYPTO_KMODS += md5 -CRYPTO_KMODS += ecc CRYPTO_KMODS += rsa CRYPTO_KMODS += sha1 CRYPTO_KMODS += sha2 +CRYPTO_KMODS += skein CRYPTO_KMODS += swrand # diff --git a/usr/src/uts/sparc/edonr/Makefile b/usr/src/uts/sparc/edonr/Makefile new file mode 100644 index 0000000000..b0c6eb0f8c --- /dev/null +++ b/usr/src/uts/sparc/edonr/Makefile @@ -0,0 +1,92 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2013 Saso Kiselkov. All rights reserved. +# +# +# This makefile drives the production of the edonr kernel module. +# +# sparc architecture dependent +# + +# +# Path to the base of the uts directory tree (usually /usr/src/uts). +# +UTSBASE = ../.. +COMDIR = $(COMMONBASE)/crypto + +# +# Define the module and object file sets. +# +MODULE = edonr +OBJECTS = $(EDONR_OBJS:%=$(OBJS_DIR)/%) +LINTS = $(EDONR_OBJS:%.o=$(LINTS_DIR)/%.ln) +ROOTMODULE = $(ROOT_CRYPTO_DIR)/$(MODULE) +ROOTLINK = $(ROOT_MISC_DIR)/$(MODULE) + +# +# Include common rules. +# +include $(UTSBASE)/sparc/Makefile.sparc + +# +# Define targets +# +ALL_TARGET = $(BINARY) +LINT_TARGET = $(MODULE).lint +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK) + +# +# Linkage dependencies +# +LDFLAGS += -dy -Nmisc/kcf + +CFLAGS += -I$(COMDIR) +LINTFLAGS += -I$(COMDIR) + +# +# Default build targets. +# +.KEEP_STATE: + +def: $(DEF_DEPS) + +all: $(ALL_DEPS) + +clean: $(CLEAN_DEPS) + +clobber: $(CLOBBER_DEPS) + +lint: $(LINT_DEPS) + +modlintlib: $(MODLINTLIB_DEPS) + +clean.lint: $(CLEAN_LINT_DEPS) + +install: $(INSTALL_DEPS) + +$(ROOTLINK): $(ROOT_MISC_DIR) $(ROOTMODULE) + -$(RM) $@; ln $(ROOTMODULE) $@ + +# +# Include common targets. +# +include $(UTSBASE)/sparc/Makefile.targ diff --git a/usr/src/uts/sparc/skein/Makefile b/usr/src/uts/sparc/skein/Makefile new file mode 100644 index 0000000000..6f1b4ecfab --- /dev/null +++ b/usr/src/uts/sparc/skein/Makefile @@ -0,0 +1,92 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2013 Saso Kiselkov. All rights reserved. +# +# +# This makefile drives the production of the skein crypto kernel module. +# +# sparc architecture dependent +# + +# +# Path to the base of the uts directory tree (usually /usr/src/uts). +# +UTSBASE = ../.. +COMDIR = $(COMMONBASE)/crypto + +# +# Define the module and object file sets. +# +MODULE = skein +OBJECTS = $(SKEIN_OBJS:%=$(OBJS_DIR)/%) +LINTS = $(SKEIN_OBJS:%.o=$(LINTS_DIR)/%.ln) +ROOTMODULE = $(ROOT_CRYPTO_DIR)/$(MODULE) +ROOTLINK = $(ROOT_MISC_DIR)/$(MODULE) + +# +# Include common rules. +# +include $(UTSBASE)/sparc/Makefile.sparc + +# +# Define targets +# +ALL_TARGET = $(BINARY) +LINT_TARGET = $(MODULE).lint +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK) + +# +# Linkage dependencies +# +LDFLAGS += -dy -Nmisc/kcf + +CFLAGS += -I$(COMDIR) +LINTFLAGS += -I$(COMDIR) + +# +# Default build targets. +# +.KEEP_STATE: + +def: $(DEF_DEPS) + +all: $(ALL_DEPS) + +clean: $(CLEAN_DEPS) + +clobber: $(CLOBBER_DEPS) + +lint: $(LINT_DEPS) + +modlintlib: $(MODLINTLIB_DEPS) + +clean.lint: $(CLEAN_LINT_DEPS) + +install: $(INSTALL_DEPS) + +$(ROOTLINK): $(ROOT_MISC_DIR) $(ROOTMODULE) + -$(RM) $@; ln $(ROOTMODULE) $@ + +# +# Include common targets. +# +include $(UTSBASE)/sparc/Makefile.targ diff --git a/usr/src/uts/sparc/zfs/Makefile b/usr/src/uts/sparc/zfs/Makefile index b891e4fae1..8d6d25df5e 100644 --- a/usr/src/uts/sparc/zfs/Makefile +++ b/usr/src/uts/sparc/zfs/Makefile @@ -24,6 +24,9 @@ # # This makefile drives the production of the zfs file system # kernel module. +# +# Copyright 2013 Saso Kiselkov. All rights reserved. +# # # Path to the base of the uts directory tree (usually /usr/src/uts). @@ -62,7 +65,7 @@ INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK) $(ROOT_CONFFILE) # MODSTUBS_DIR = $(OBJS_DIR) LDFLAGS += -dy -Nfs/specfs -Ncrypto/swrand -Nmisc/idmap \ - -Nsched/SDC -Nmisc/sha2 + -Nsched/SDC -Nmisc/sha2 -Nmisc/skein -Nmisc/edonr INC_PATH += -I$(UTSBASE)/common/fs/zfs INC_PATH += -I$(SRC)/common |