svn commit: r304321 - in head/sys: boot/efi/boot1 boot/efi/loader boot/i386/boot2 boot/i386/gptboot boot/i386/gptzfsboot boot/i386/zfsboot boot/userboot/ficl boot/userboot/userboot boot/userboot/zf...

Toomas Soome tsoome at FreeBSD.org
Thu Aug 18 00:37:10 UTC 2016


Author: tsoome
Date: Thu Aug 18 00:37:07 2016
New Revision: 304321
URL: https://svnweb.freebsd.org/changeset/base/304321

Log:
  Add SHA512, skein, large blocks support for loader zfs.
  
  Updated sha512 from illumos.
  Using skein from freebsd crypto tree.
  Since loader itself is using 64MB memory for heap, updated zfsboot to
  use same, and this also allows to support zfs large blocks.
  
  Note, adding additional features does increate zfsboot code, therefore
  this update does increase zfsboot code to 128k, also I have ported gptldr.S
  update to zfsldr.S to support 64k+ code.
  
  With this update, boot1.efi has almost reached the current limit of the size
  set for it, so one of the future patches for boot1.efi will need to
  increase the limit.
  
  Currently known missing zfs features in boot loader are edonr and gzip support.
  
  Reviewed by:	delphij, imp
  Approved by:	imp (mentor)
  Obtained from:	sha256.c update and skein_zfs.c stub from illumos.
  Differential Revision:	https://reviews.freebsd.org/D7418

Added:
  head/sys/cddl/boot/zfs/skein_zfs.c   (contents, props changed)
Modified:
  head/sys/boot/efi/boot1/Makefile
  head/sys/boot/efi/loader/Makefile
  head/sys/boot/i386/boot2/Makefile
  head/sys/boot/i386/gptboot/Makefile
  head/sys/boot/i386/gptboot/gptldr.S
  head/sys/boot/i386/gptzfsboot/Makefile
  head/sys/boot/i386/zfsboot/Makefile
  head/sys/boot/i386/zfsboot/zfsboot.c
  head/sys/boot/i386/zfsboot/zfsldr.S
  head/sys/boot/userboot/ficl/Makefile
  head/sys/boot/userboot/userboot/Makefile
  head/sys/boot/userboot/zfs/Makefile
  head/sys/boot/zfs/Makefile
  head/sys/boot/zfs/zfsimpl.c
  head/sys/cddl/boot/zfs/fletcher.c
  head/sys/cddl/boot/zfs/sha256.c
  head/sys/cddl/boot/zfs/zfsimpl.h
  head/sys/cddl/boot/zfs/zfssubr.c

Modified: head/sys/boot/efi/boot1/Makefile
==============================================================================
--- head/sys/boot/efi/boot1/Makefile	Wed Aug 17 22:13:39 2016	(r304320)
+++ head/sys/boot/efi/boot1/Makefile	Thu Aug 18 00:37:07 2016	(r304321)
@@ -19,12 +19,16 @@ CWARNFLAGS.zfs_module.c += -Wno-missing-
 CWARNFLAGS.zfs_module.c += -Wno-sign-compare
 CWARNFLAGS.zfs_module.c += -Wno-unused-parameter
 CWARNFLAGS.zfs_module.c += -Wno-unused-function
+CWARNFLAGS.skein.c += -Wno-cast-align
+CWARNFLAGS.skein.c += -Wno-missing-variable-declarations
 .endif
 
 # architecture-specific loader code
 SRCS=	boot1.c self_reloc.c start.S ufs_module.c
 .if ${MK_ZFS} != "no"
 SRCS+=		zfs_module.c
+SRCS+=		skein.c skein_block.c
+.PATH:		${.CURDIR}/../../../crypto/skein
 .endif
 
 CFLAGS+=	-I.
@@ -40,6 +44,7 @@ CFLAGS+=	-DEFI_DEBUG
 .if ${MK_ZFS} != "no"
 CFLAGS+=	-I${.CURDIR}/../../zfs/
 CFLAGS+=	-I${.CURDIR}/../../../cddl/boot/zfs/
+CFLAGS+=	-I${.CURDIR}/../../../crypto/skein
 CFLAGS+=	-DEFI_ZFS_BOOT
 .endif
 

Modified: head/sys/boot/efi/loader/Makefile
==============================================================================
--- head/sys/boot/efi/loader/Makefile	Wed Aug 17 22:13:39 2016	(r304320)
+++ head/sys/boot/efi/loader/Makefile	Thu Aug 18 00:37:07 2016	(r304321)
@@ -24,6 +24,8 @@ SRCS=	autoload.c \
 .if ${MK_ZFS} != "no"
 SRCS+=		zfs.c
 .PATH:		${.CURDIR}/../../zfs
+SRCS+=		skein.c skein_block.c
+.PATH:		${.CURDIR}/../../../crypto/skein
 
 # Disable warnings that are currently incompatible with the zfs boot code
 CWARNFLAGS.zfs.c+=	-Wno-sign-compare
@@ -53,6 +55,7 @@ CFLAGS+=	-I${.CURDIR}/../../i386/libi386
 .if ${MK_ZFS} != "no"
 CFLAGS+=	-I${.CURDIR}/../../zfs
 CFLAGS+=	-I${.CURDIR}/../../../cddl/boot/zfs
+CFLAGS+=	-I${.CURDIR}/../../../crypto/skein
 CFLAGS+=	-DEFI_ZFS_BOOT
 .endif
 CFLAGS+=	-DNO_PCI -DEFI

Modified: head/sys/boot/i386/boot2/Makefile
==============================================================================
--- head/sys/boot/i386/boot2/Makefile	Wed Aug 17 22:13:39 2016	(r304320)
+++ head/sys/boot/i386/boot2/Makefile	Thu Aug 18 00:37:07 2016	(r304321)
@@ -33,7 +33,7 @@ CFLAGS=	-fomit-frame-pointer \
 	-DSIOSPD=${BOOT_COMCONSOLE_SPEED} \
 	-I${.CURDIR}/../../common \
 	-I${.CURDIR}/../btx/lib -I. \
-	-Wall -Waggregate-return -Wbad-function-cast -Wcast-align \
+	-Wall -Waggregate-return -Wbad-function-cast -Wno-cast-align \
 	-Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
 	-Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings \
 	-Winline

Modified: head/sys/boot/i386/gptboot/Makefile
==============================================================================
--- head/sys/boot/i386/gptboot/Makefile	Wed Aug 17 22:13:39 2016	(r304320)
+++ head/sys/boot/i386/gptboot/Makefile	Thu Aug 18 00:37:07 2016	(r304321)
@@ -32,10 +32,10 @@ CFLAGS=	-DBOOTPROG=\"gptboot\" \
 	-I${.CURDIR}/../btx/lib -I. \
 	-I${.CURDIR}/../boot2 \
 	-I${.CURDIR}/../../.. \
-	-Wall -Waggregate-return -Wbad-function-cast -Wcast-align \
+	-Wall -Waggregate-return -Wbad-function-cast -Wno-cast-align \
 	-Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
 	-Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings \
-	-Winline
+	-Winline -Wno-pointer-sign
 
 CFLAGS.gcc+=	--param max-inline-insns-single=100
 

Modified: head/sys/boot/i386/gptboot/gptldr.S
==============================================================================
--- head/sys/boot/i386/gptboot/gptldr.S	Wed Aug 17 22:13:39 2016	(r304320)
+++ head/sys/boot/i386/gptboot/gptldr.S	Thu Aug 18 00:37:07 2016	(r304321)
@@ -45,7 +45,7 @@
 /* Misc. Constants */
 		.set SIZ_PAG,0x1000		# Page size
 		.set SIZ_SEC,0x200		# Sector size
-		.set COPY_BLKS,0x4		# Number of blocks
+		.set COPY_BLKS,0x8		# Number of blocks
 						# to copy for boot2
 		.set COPY_BLK_SZ,0x8000		# Copy in 32k blocks; must be
 						# a multiple of 16 bytes

Modified: head/sys/boot/i386/gptzfsboot/Makefile
==============================================================================
--- head/sys/boot/i386/gptzfsboot/Makefile	Wed Aug 17 22:13:39 2016	(r304320)
+++ head/sys/boot/i386/gptzfsboot/Makefile	Thu Aug 18 00:37:07 2016	(r304321)
@@ -2,7 +2,7 @@
 
 .PATH:		${.CURDIR}/../boot2 ${.CURDIR}/../gptboot \
 		${.CURDIR}/../zfsboot ${.CURDIR}/../common \
-		${.CURDIR}/../../common
+		${.CURDIR}/../../common ${.CURDIR}/../../../crypto/skein
 
 FILES=		gptzfsboot
 MAN=		gptzfsboot.8
@@ -27,13 +27,14 @@ CFLAGS=	-DBOOTPROG=\"gptzfsboot\" \
 	-I${.CURDIR}/../common \
 	-I${.CURDIR}/../../zfs \
 	-I${.CURDIR}/../../../cddl/boot/zfs \
+	-I${.CURDIR}/../../../crypto/skein \
 	-I${.CURDIR}/../btx/lib -I. \
 	-I${.CURDIR}/../boot2 \
 	-I${.CURDIR}/../../.. \
-	-Wall -Waggregate-return -Wbad-function-cast -Wcast-align \
+	-Wall -Waggregate-return -Wbad-function-cast -Wno-cast-align \
 	-Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
 	-Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings \
-	-Winline
+	-Winline -Wno-tentative-definition-incomplete-type -Wno-pointer-sign
 
 .if !defined(LOADER_NO_GELI_SUPPORT)
 CFLAGS+=	-DLOADER_GELI_SUPPORT
@@ -67,12 +68,13 @@ gptldr.out: gptldr.o
 	${LD} ${LD_FLAGS} -e start -Ttext ${ORG1} -o ${.TARGET} gptldr.o
 
 CLEANFILES+=	gptzfsboot.bin gptzfsboot.out zfsboot.o sio.o cons.o \
-		drv.o gpt.o util.o ${OPENCRYPTO_XTS}
+		drv.o gpt.o util.o skein.o skein_block.o ${OPENCRYPTO_XTS}
 
 gptzfsboot.bin: gptzfsboot.out
 	${OBJCOPY} -S -O binary gptzfsboot.out ${.TARGET}
 
-gptzfsboot.out: ${BTXCRT} zfsboot.o sio.o gpt.o drv.o cons.o util.o ${OPENCRYPTO_XTS}
+gptzfsboot.out: ${BTXCRT} zfsboot.o sio.o gpt.o drv.o cons.o util.o \
+	skein.o skein_block.o ${OPENCRYPTO_XTS}
 	${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBSTAND} ${LIBGELIBOOT}
 
 zfsboot.o: ${.CURDIR}/../../zfs/zfsimpl.c

Modified: head/sys/boot/i386/zfsboot/Makefile
==============================================================================
--- head/sys/boot/i386/zfsboot/Makefile	Wed Aug 17 22:13:39 2016	(r304320)
+++ head/sys/boot/i386/zfsboot/Makefile	Thu Aug 18 00:37:07 2016	(r304321)
@@ -1,6 +1,7 @@
 # $FreeBSD$
 
-.PATH:		${.CURDIR}/../boot2 ${.CURDIR}/../common ${.CURDIR}/../../common
+.PATH:		${.CURDIR}/../boot2 ${.CURDIR}/../common \
+		${.CURDIR}/../../common ${.CURDIR}/../../../crypto/skein
 
 FILES=		zfsboot
 MAN=		zfsboot.8
@@ -25,9 +26,10 @@ CFLAGS=	-DBOOTPROG=\"zfsboot\" \
 	-I${.CURDIR}/../common \
 	-I${.CURDIR}/../../zfs \
 	-I${.CURDIR}/../../../cddl/boot/zfs \
+	-I${.CURDIR}/../../../crypto/skein \
 	-I${.CURDIR}/../btx/lib -I. \
 	-I${.CURDIR}/../boot2 \
-	-Wall -Waggregate-return -Wbad-function-cast -Wcast-align \
+	-Wall -Waggregate-return -Wbad-function-cast -Wno-cast-align \
 	-Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
 	-Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings \
 	-Winline
@@ -55,12 +57,13 @@ zfsldr.out: zfsldr.o
 	${LD} ${LD_FLAGS} -e start -Ttext ${ORG1} -o ${.TARGET} zfsldr.o
 
 CLEANFILES+=	zfsboot2 zfsboot.ld zfsboot.ldr zfsboot.bin zfsboot.out \
-		zfsboot.o zfsboot.s zfsboot.s.tmp sio.o cons.o drv.o util.o
+		zfsboot.o zfsboot.s zfsboot.s.tmp sio.o cons.o drv.o util.o \
+		skein.o skein_block.o
 
-# We currently allow 65536 bytes for zfsboot - in practice it could be
+# We currently allow 128k bytes for zfsboot - in practice it could be
 # any size up to 3.5Mb but keeping it fixed size simplifies zfsldr.
 # 
-BOOT2SIZE=	65536
+BOOT2SIZE=	131072
 
 zfsboot2: zfsboot.ld
 	@set -- `ls -l zfsboot.ld`; x=$$((${BOOT2SIZE}-$$5)); \
@@ -77,7 +80,7 @@ zfsboot.ldr:
 zfsboot.bin: zfsboot.out
 	${OBJCOPY} -S -O binary zfsboot.out ${.TARGET}
 
-zfsboot.out: ${BTXCRT} zfsboot.o sio.o drv.o cons.o util.o
+zfsboot.out: ${BTXCRT} zfsboot.o sio.o drv.o cons.o util.o skein.o skein_block.o
 	${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBSTAND}
 
 SRCS=	zfsboot.c

Modified: head/sys/boot/i386/zfsboot/zfsboot.c
==============================================================================
--- head/sys/boot/i386/zfsboot/zfsboot.c	Wed Aug 17 22:13:39 2016	(r304320)
+++ head/sys/boot/i386/zfsboot/zfsboot.c	Thu Aug 18 00:37:07 2016	(r304321)
@@ -105,7 +105,7 @@ static struct bios_smap smap;
 /*
  * The minimum amount of memory to reserve in bios_extmem for the heap.
  */
-#define	HEAP_MIN		(3 * 1024 * 1024)
+#define	HEAP_MIN		(64 * 1024 * 1024)
 
 static char *heap_next;
 static char *heap_end;

Modified: head/sys/boot/i386/zfsboot/zfsldr.S
==============================================================================
--- head/sys/boot/i386/zfsboot/zfsldr.S	Wed Aug 17 22:13:39 2016	(r304320)
+++ head/sys/boot/i386/zfsboot/zfsldr.S	Thu Aug 18 00:37:07 2016	(r304321)
@@ -32,8 +32,11 @@
 /* Misc. Constants */
 		.set SIZ_PAG,0x1000		# Page size
 		.set SIZ_SEC,0x200		# Sector size
-
-		.set NSECT,0x80
+		.set COPY_BLKS,0x8		# Number of blocks
+						# to copy for boot2
+		.set COPY_BLK_SZ,0x8000		# Copy in 32k blocks; must be
+						# a multiple of 16 bytes
+		.set NSECT,(COPY_BLK_SZ / SIZ_SEC * COPY_BLKS)
 		.globl start
 		.code16
 
@@ -88,12 +91,12 @@ main.3: 	add $0x10,%si	 		# Next entry
 /*
  * Ok, we have a slice and drive in %dx now, so use that to locate and
  * load boot2.  %si references the start of the slice we are looking
- * for, so go ahead and load up the 128 sectors starting at sector 1024
- * (i.e. after the two vdev labels).  We don't have do anything fancy
- * here to allow for an extra copy of boot1 and a partition table
- * (compare to this section of the UFS bootstrap) so we just load it
- * all at 0x9000. The first part of boot2 is BTX, which wants to run
- * at 0x9000. The boot2.bin binary starts right after the end of BTX,
+ * for, so go ahead and load up the COPY_BLKS*COPY_BLK_SZ/SIZ_SEC sectors
+ * starting at sector 1024 (i.e. after the two vdev labels).  We don't
+ * have do anything fancy here to allow for an extra copy of boot1 and
+ * a partition table (compare to this section of the UFS bootstrap) so we
+ * just load it all at 0x9000. The first part of boot2 is BTX, which wants
+ * to run at 0x9000. The boot2.bin binary starts right after the end of BTX,
  * so we have to figure out where the start of it is and then move the
  * binary to 0xc000.  Normally, BTX clients start at MEM_USR, or 0xa000,
  * but when we use btxld to create zfsboot2, we use an entry point of
@@ -116,23 +119,37 @@ main.6:		pushal				# Save params
 		incl %eax			# Advance to
 		add $SIZ_SEC,%ebx		#  next sector
 		loop main.6			# If not last, read another
-		mov MEM_BTX+0xa,%bx		# Get BTX length
-		mov $NSECT*SIZ_SEC-1,%di	# Size of load area (less one)
-		mov %di,%si			# End of load area, 0x9000 rel
-		sub %bx,%di			# End of client, 0xc000 rel
-		mov %di,%cx			# Size of
-		inc %cx				#  client
-		mov $(MEM_BTX)>>4,%dx		# Segment
-		mov %dx,%ds			#   addressing 0x9000
-		mov $(MEM_USR+2*SIZ_PAG)>>4,%dx	# Segment
-		mov %dx,%es			#   addressing 0xc000
-		std				# Move with decrement
-		rep				# Relocate
-		movsb				#  client
+
+		mov $MEM_BTX,%bx		# BTX
+		mov 0xa(%bx),%si		# Get BTX length and set
+		add %bx,%si			#  %si to start of boot2
+		dec %si				# Set %ds:%si to point at the
+		mov %si,%ax			# last byte we want to copy
+		shr $4,%ax			# from boot2, with %si made as
+		add $(COPY_BLKS*COPY_BLK_SZ/16),%ax	# small as possible.
+		and $0xf,%si			#
+		mov %ax,%ds			#
+		mov $(MEM_USR+2*SIZ_PAG)/16,%ax # Set %es:(-1) to point at
+		add $(COPY_BLKS*COPY_BLK_SZ/16),%ax	# the last byte we
+		mov %ax,%es			# want to copy boot2 into.
+		mov $COPY_BLKS,%bx		# Copy COPY_BLKS 32k blocks
+copyloop:
+		add $COPY_BLK_SZ,%si		# Adjust %ds:%si to point at
+		mov %ds,%ax			# the end of the next 32k to
+		sub $COPY_BLK_SZ/16,%ax		# copy from boot2
+		mov %ax,%ds
+		mov $COPY_BLK_SZ-1,%di		# Adjust %es:%di to point at
+		mov %es,%ax			# the end of the next 32k into
+		sub $COPY_BLK_SZ/16,%ax		# which we want boot2 copied
+		mov %ax,%es
+		mov $COPY_BLK_SZ,%cx		# Copy 32k
+		std
+		rep movsb
+		dec %bx
+		jnz copyloop
+		mov %cx,%ds			# Reset %ds and %es
+		mov %cx,%es
 		cld				# Back to increment
-		xor %dx,%dx			# Back
-		mov %ds,%dx			#  to zero
-		mov %dx,%es			#  segment
 
 /*
  * Enable A20 so we can access memory above 1 meg.

Modified: head/sys/boot/userboot/ficl/Makefile
==============================================================================
--- head/sys/boot/userboot/ficl/Makefile	Wed Aug 17 22:13:39 2016	(r304320)
+++ head/sys/boot/userboot/ficl/Makefile	Thu Aug 18 00:37:07 2016	(r304321)
@@ -10,6 +10,9 @@ BASE_SRCS=	dict.c ficl.c fileaccess.c fl
 
 SRCS=		${BASE_SRCS} sysdep.c softcore.c
 CLEANFILES=	softcore.c testmain testmain.o
+
+CWARNFLAGS.loader.c.c += -Wno-implicit-function-declaration
+
 .if HAVE_PNP
 CFLAGS+=	-DHAVE_PNP
 .endif

Modified: head/sys/boot/userboot/userboot/Makefile
==============================================================================
--- head/sys/boot/userboot/userboot/Makefile	Wed Aug 17 22:13:39 2016	(r304320)
+++ head/sys/boot/userboot/userboot/Makefile	Thu Aug 18 00:37:07 2016	(r304321)
@@ -35,6 +35,8 @@ CFLAGS+=	-I${.CURDIR}/../../..
 CFLAGS+=	-I${.CURDIR}/../../../../lib/libstand
 CFLAGS+=	-ffreestanding -I.
 
+CWARNFLAGS.main.c += -Wno-implicit-function-declaration
+
 LDFLAGS+=	-nostdlib -Wl,-Bsymbolic
 
 NEWVERSWHAT=	"User boot" ${MACHINE_CPUARCH}

Modified: head/sys/boot/userboot/zfs/Makefile
==============================================================================
--- head/sys/boot/userboot/zfs/Makefile	Wed Aug 17 22:13:39 2016	(r304320)
+++ head/sys/boot/userboot/zfs/Makefile	Thu Aug 18 00:37:07 2016	(r304321)
@@ -2,15 +2,16 @@
 
 S=		${.CURDIR}/../../zfs
 
-.PATH:		${S}
+.PATH:		${S} ${.CURDIR}/../../../crypto/skein
 LIB=		zfsboot
 INTERNALLIB=
 
-SRCS+=		zfs.c
+SRCS+=		zfs.c skein.c skein_block.c
 
 CFLAGS+=	-I${.CURDIR}/../../common -I${.CURDIR}/../../.. -I.
 CFLAGS+=	-I${.CURDIR}/../../../../lib/libstand
 CFLAGS+=	-I${.CURDIR}/../../../cddl/boot/zfs
+CFLAGS+=	-I${.CURDIR}/../../../crypto/skein
 
 CFLAGS+=	-ffreestanding -fPIC
 CFLAGS+=	-Wformat -Wall

Modified: head/sys/boot/zfs/Makefile
==============================================================================
--- head/sys/boot/zfs/Makefile	Wed Aug 17 22:13:39 2016	(r304320)
+++ head/sys/boot/zfs/Makefile	Thu Aug 18 00:37:07 2016	(r304321)
@@ -5,10 +5,14 @@ INTERNALLIB=
 
 SRCS+=		zfs.c
 
+SRCS+=		skein.c skein_block.c
+.PATH:		${.CURDIR}/../../crypto/skein
+
 CFLAGS+=	-DBOOTPROG=\"zfsloader\"
 CFLAGS+=	-I${.CURDIR}/../common -I${.CURDIR}/../.. -I.
 CFLAGS+=	-I${.CURDIR}/../../../lib/libstand
 CFLAGS+=	-I${.CURDIR}/../../cddl/boot/zfs
+CFLAGS+=	-I${.CURDIR}/../../crypto/skein
 
 .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
 CFLAGS+=	-march=i386

Modified: head/sys/boot/zfs/zfsimpl.c
==============================================================================
--- head/sys/boot/zfs/zfsimpl.c	Wed Aug 17 22:13:39 2016	(r304320)
+++ head/sys/boot/zfs/zfsimpl.c	Thu Aug 18 00:37:07 2016	(r304321)
@@ -58,6 +58,8 @@ static const char *features_for_read[] =
 	"com.delphix:extensible_dataset",
 	"com.delphix:embedded_data",
 	"org.open-zfs:large_blocks",
+	"org.illumos:sha512",
+	"org.illumos:skein",
 	NULL
 };
 
@@ -78,6 +80,9 @@ static char *zfs_temp_buf, *zfs_temp_end
 static int zio_read(const spa_t *spa, const blkptr_t *bp, void *buf);
 static int zfs_get_root(const spa_t *spa, uint64_t *objid);
 static int zfs_rlookup(const spa_t *spa, uint64_t objnum, char *result);
+static int zap_lookup(const spa_t *spa, const dnode_phys_t *dnode,
+    const char *name, uint64_t integer_size, uint64_t num_integers,
+    void *value);
 
 static void
 zfs_init(void)
@@ -420,7 +425,7 @@ vdev_read_phys(vdev_t *vdev, const blkpt
 	rc = vdev->v_phys_read(vdev, vdev->v_read_priv, offset, buf, psize);
 	if (rc)
 		return (rc);
-	if (bp && zio_checksum_verify(bp, buf))
+	if (bp && zio_checksum_verify(vdev->spa, bp, buf))
 		return (EIO);
 
 	return (0);
@@ -1074,6 +1079,7 @@ vdev_probe(vdev_phys_read_t *read, void 
 	}
 	zfs_free(upbuf, VDEV_UBERBLOCK_SIZE(vdev));
 
+	vdev->spa = spa;
 	if (spap)
 		*spap = spa;
 	return (0);
@@ -1122,7 +1128,7 @@ zio_read_gang(const spa_t *spa, const bl
 		pbuf += BP_GET_PSIZE(gbp);
 	}
 
-	if (zio_checksum_verify(bp, buf))
+	if (zio_checksum_verify(spa, bp, buf))
 		return (EIO);
 	return (0);
 }
@@ -1224,7 +1230,8 @@ dnode_read(const spa_t *spa, const dnode
 	int i, rc;
 
 	if (bsize > SPA_MAXBLOCKSIZE) {
-		printf("ZFS: I/O error - blocks larger than 128K are not supported\n");
+		printf("ZFS: I/O error - blocks larger than %llu are not "
+		    "supported\n", SPA_MAXBLOCKSIZE);
 		return (EIO);
 	}
 
@@ -1364,12 +1371,73 @@ fzap_leaf_value(const zap_leaf_t *zl, co
 	return value;
 }
 
+static void
+stv(int len, void *addr, uint64_t value)
+{
+	switch (len) {
+	case 1:
+		*(uint8_t *)addr = value;
+		return;
+	case 2:
+		*(uint16_t *)addr = value;
+		return;
+	case 4:
+		*(uint32_t *)addr = value;
+		return;
+	case 8:
+		*(uint64_t *)addr = value;
+		return;
+	}
+}
+
+/*
+ * Extract a array from a zap leaf entry.
+ */
+static void
+fzap_leaf_array(const zap_leaf_t *zl, const zap_leaf_chunk_t *zc,
+    uint64_t integer_size, uint64_t num_integers, void *buf)
+{
+	uint64_t array_int_len = zc->l_entry.le_value_intlen;
+	uint64_t value = 0;
+	uint64_t *u64 = buf;
+	char *p = buf;
+	int len = MIN(zc->l_entry.le_value_numints, num_integers);
+	int chunk = zc->l_entry.le_value_chunk;
+	int byten = 0;
+
+	if (integer_size == 8 && len == 1) {
+		*u64 = fzap_leaf_value(zl, zc);
+		return;
+	}
+
+	while (len > 0) {
+		struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(zl, chunk).l_array;
+		int i;
+
+		ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(zl));
+		for (i = 0; i < ZAP_LEAF_ARRAY_BYTES && len > 0; i++) {
+			value = (value << 8) | la->la_array[i];
+			byten++;
+			if (byten == array_int_len) {
+				stv(integer_size, p, value);
+				byten = 0;
+				len--;
+				if (len == 0)
+					return;
+				p += integer_size;
+			}
+		}
+		chunk = la->la_next;
+	}
+}
+
 /*
  * Lookup a value in a fatzap directory. Assumes that the zap scratch
  * buffer contains the directory header.
  */
 static int
-fzap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name, uint64_t *value)
+fzap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name,
+    uint64_t integer_size, uint64_t num_integers, void *value)
 {
 	int bsize = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
 	zap_phys_t zh = *(zap_phys_t *) zap_scratch;
@@ -1436,9 +1504,10 @@ fzap_lookup(const spa_t *spa, const dnod
 		zc = &ZAP_LEAF_CHUNK(&zl, zc->l_entry.le_next);
 	}
 	if (fzap_name_equal(&zl, zc, name)) {
-		if (zc->l_entry.le_value_intlen * zc->l_entry.le_value_numints > 8)
+		if (zc->l_entry.le_value_intlen * zc->l_entry.le_value_numints >
+		    integer_size * num_integers)
 			return (E2BIG);
-		*value = fzap_leaf_value(&zl, zc);
+		fzap_leaf_array(&zl, zc, integer_size, num_integers, value);
 		return (0);
 	}
 
@@ -1449,7 +1518,8 @@ fzap_lookup(const spa_t *spa, const dnod
  * Lookup a name in a zap object and return its value as a uint64_t.
  */
 static int
-zap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name, uint64_t *value)
+zap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name,
+    uint64_t integer_size, uint64_t num_integers, void *value)
 {
 	int rc;
 	uint64_t zap_type;
@@ -1462,8 +1532,10 @@ zap_lookup(const spa_t *spa, const dnode
 	zap_type = *(uint64_t *) zap_scratch;
 	if (zap_type == ZBT_MICRO)
 		return mzap_lookup(dnode, name, value);
-	else if (zap_type == ZBT_HEADER)
-		return fzap_lookup(spa, dnode, name, value);
+	else if (zap_type == ZBT_HEADER) {
+		return fzap_lookup(spa, dnode, name, integer_size,
+		    num_integers, value);
+	}
 	printf("ZFS: invalid zap_type=%d\n", (int)zap_type);
 	return (EIO);
 }
@@ -1802,7 +1874,8 @@ zfs_lookup_dataset(const spa_t *spa, con
 
 	if (objset_get_dnode(spa, &spa->spa_mos, DMU_POOL_DIRECTORY_OBJECT, &dir))
 		return (EIO);
-	if (zap_lookup(spa, &dir, DMU_POOL_ROOT_DATASET, &dir_obj))
+	if (zap_lookup(spa, &dir, DMU_POOL_ROOT_DATASET, sizeof (dir_obj),
+	    1, &dir_obj))
 		return (EIO);
 
 	p = name;
@@ -1832,7 +1905,8 @@ zfs_lookup_dataset(const spa_t *spa, con
 			return (EIO);
 
 		/* Actual loop condition #2. */
-		if (zap_lookup(spa, &child_dir_zap, element, &dir_obj) != 0)
+		if (zap_lookup(spa, &child_dir_zap, element, sizeof (dir_obj),
+		    1, &dir_obj) != 0)
 			return (ENOENT);
 	}
 
@@ -1962,9 +2036,9 @@ zfs_get_root(const spa_t *spa, uint64_t 
 	/*
 	 * Lookup the pool_props and see if we can find a bootfs.
 	 */
-	if (zap_lookup(spa, &dir, DMU_POOL_PROPS, &props) == 0
+	if (zap_lookup(spa, &dir, DMU_POOL_PROPS, sizeof (props), 1, &props) == 0
 	     && objset_get_dnode(spa, &spa->spa_mos, props, &propdir) == 0
-	     && zap_lookup(spa, &propdir, "bootfs", &bootfs) == 0
+	     && zap_lookup(spa, &propdir, "bootfs", sizeof (bootfs), 1, &bootfs) == 0
 	     && bootfs != 0)
 	{
 		*objid = bootfs;
@@ -1973,7 +2047,7 @@ zfs_get_root(const spa_t *spa, uint64_t 
 	/*
 	 * Lookup the root dataset directory
 	 */
-	if (zap_lookup(spa, &dir, DMU_POOL_ROOT_DATASET, &root)
+	if (zap_lookup(spa, &dir, DMU_POOL_ROOT_DATASET, sizeof (root), 1, &root)
 	    || objset_get_dnode(spa, &spa->spa_mos, root, &dir)) {
 		printf("ZFS: can't find root dsl_dir\n");
 		return (EIO);
@@ -2047,7 +2121,8 @@ check_mos_features(const spa_t *spa)
 	if ((rc = objset_get_dnode(spa, &spa->spa_mos, DMU_OT_OBJECT_DIRECTORY,
 	    &dir)) != 0)
 		return (rc);
-	if ((rc = zap_lookup(spa, &dir, DMU_POOL_FEATURES_FOR_READ, &objnum)) != 0)
+	if ((rc = zap_lookup(spa, &dir, DMU_POOL_FEATURES_FOR_READ,
+	    sizeof (objnum), 1, &objnum)) != 0)
 		return (rc);
 
 	if ((rc = objset_get_dnode(spa, &spa->spa_mos, objnum, &dir)) != 0)
@@ -2072,6 +2147,7 @@ check_mos_features(const spa_t *spa)
 static int
 zfs_spa_init(spa_t *spa)
 {
+	dnode_phys_t dir;
 	int rc;
 
 	if (zio_read(spa, &spa->spa_uberblock.ub_rootbp, &spa->spa_mos)) {
@@ -2083,6 +2159,17 @@ zfs_spa_init(spa_t *spa)
 		return (EIO);
 	}
 
+	if (objset_get_dnode(spa, &spa->spa_mos, DMU_POOL_DIRECTORY_OBJECT,
+	    &dir)) {
+		printf("ZFS: failed to read pool %s directory object\n",
+		    spa->spa_name);
+		return (EIO);
+	}
+	/* this is allowed to fail, older pools do not have salt */
+	rc = zap_lookup(spa, &dir, DMU_POOL_CHECKSUM_SALT, 1,
+	    sizeof (spa->spa_cksum_salt.zcs_bytes),
+	    spa->spa_cksum_salt.zcs_bytes);
+
 	rc = check_mos_features(spa);
 	if (rc != 0) {
 		printf("ZFS: pool %s is not supported\n", spa->spa_name);
@@ -2173,7 +2260,7 @@ zfs_lookup(const struct zfsmount *mount,
 	if (rc)
 		return (rc);
 
-	rc = zap_lookup(spa, &dn, ZFS_ROOT_OBJ, &rootnum);
+	rc = zap_lookup(spa, &dn, ZFS_ROOT_OBJ, sizeof (rootnum), 1, &rootnum);
 	if (rc)
 		return (rc);
 
@@ -2205,7 +2292,7 @@ zfs_lookup(const struct zfsmount *mount,
 			return (ENOTDIR);
 
 		parentnum = objnum;
-		rc = zap_lookup(spa, &dn, element, &objnum);
+		rc = zap_lookup(spa, &dn, element, sizeof (objnum), 1, &objnum);
 		if (rc)
 			return (rc);
 		objnum = ZFS_DIRENT_OBJ(objnum);

Modified: head/sys/cddl/boot/zfs/fletcher.c
==============================================================================
--- head/sys/cddl/boot/zfs/fletcher.c	Wed Aug 17 22:13:39 2016	(r304320)
+++ head/sys/cddl/boot/zfs/fletcher.c	Thu Aug 18 00:37:07 2016	(r304321)
@@ -23,10 +23,9 @@
  * Use is subject to license terms.
  */
 
-/*#pragma ident	"%Z%%M%	%I%	%E% SMI"*/
-
 static 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 __unused, zio_cksum_t *zcp)
 {
 	const uint64_t *ip = buf;
 	const uint64_t *ipend = ip + (size / sizeof (uint64_t));
@@ -43,7 +42,8 @@ fletcher_2_native(const void *buf, uint6
 }
 
 static 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 __unused, zio_cksum_t *zcp)
 {
 	const uint64_t *ip = buf;
 	const uint64_t *ipend = ip + (size / sizeof (uint64_t));
@@ -60,7 +60,8 @@ fletcher_2_byteswap(const void *buf, uin
 }
 
 static 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 __unused, zio_cksum_t *zcp)
 {
 	const uint32_t *ip = buf;
 	const uint32_t *ipend = ip + (size / sizeof (uint32_t));
@@ -77,7 +78,8 @@ fletcher_4_native(const void *buf, uint6
 }
 
 static 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 __unused, zio_cksum_t *zcp)
 {
 	const uint32_t *ip = buf;
 	const uint32_t *ipend = ip + (size / sizeof (uint32_t));

Modified: head/sys/cddl/boot/zfs/sha256.c
==============================================================================
--- head/sys/cddl/boot/zfs/sha256.c	Wed Aug 17 22:13:39 2016	(r304320)
+++ head/sys/cddl/boot/zfs/sha256.c	Thu Aug 18 00:37:07 2016	(r304321)
@@ -23,19 +23,21 @@
  * Copyright 2005 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.
+ * Copyright 2015 Toomas Soome <tsoome at me.com>
+ */
 
 /*
- * 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)))
@@ -44,12 +46,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,
@@ -69,46 +80,134 @@ 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;
 }
 
 static void
-zio_checksum_SHA256(const void *buf, uint64_t size, zio_cksum_t *zcp)
+SHA512Transform(uint64_t *H, const uint8_t *cp)
+{
+	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) |
+		    ((uint64_t)cp[4] << 24) | ((uint64_t)cp[5] << 16) |
+		    ((uint64_t)cp[6] << 8) | (uint64_t)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)
 {
-	uint32_t H[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
-	    0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
 	uint8_t pad[128];
-	int padsize = size & 63;
-	int i;
+	unsigned padsize = size & 63;
+	unsigned i, k;
 
+	/* process all blocks up to the last one */
 	for (i = 0; i < size - padsize; i += 64)
 		SHA256Transform(H, (uint8_t *)buf + i);
 
-	for (i = 0; i < padsize; i++)
-		pad[i] = ((uint8_t *)buf)[i];
+	/* process the last block and padding */
+	for (k = 0; k < padsize; k++)
+		pad[k] = ((uint8_t *)buf)[k+i];
 
 	for (pad[padsize++] = 0x80; (padsize & 63) != 56; padsize++)
 		pad[padsize] = 0;
@@ -125,3 +224,102 @@ zio_checksum_SHA256(const void *buf, uin
 	    (uint64_t)H[4] << 32 | H[5],
 	    (uint64_t)H[6] << 32 | H[7]);
 }
+
+/*
+ * encode 64bit data in big-endian format.
+ */
+static void
+Encode64(uint8_t *output, uint64_t *input, size_t len)
+{
+	size_t i, j;
+	for (i = 0, j = 0; j < len; i++, j += 8) {
+		output[j]	= (input[i] >> 56) & 0xff;
+		output[j + 1]	= (input[i] >> 48) & 0xff;
+		output[j + 2]	= (input[i] >> 40) & 0xff;
+		output[j + 3]	= (input[i] >> 32) & 0xff;
+		output[j + 4]	= (input[i] >> 24) & 0xff;
+		output[j + 5]	= (input[i] >> 16) & 0xff;
+		output[j + 6]	= (input[i] >>  8) & 0xff;
+		output[j + 7]	= input[i] & 0xff;
+	}
+}
+
+/*
+ * 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)
+{
+	uint64_t	c64[2];
+	uint8_t		pad[256];
+	unsigned	padsize = size & 127;
+	unsigned	i, k;
+
+	/* 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 (k = 0; k < padsize; k++)
+		pad[k] = ((uint8_t *)buf)[k+i];
+
+	if (padsize < 112) {
+		for (pad[padsize++] = 0x80; padsize < 112; padsize++)
+			pad[padsize] = 0;
+	} else {
+		for (pad[padsize++] = 0x80; padsize < 240; padsize++)
+			pad[padsize] = 0;
+	}
+
+	c64[0] = 0;
+	c64[1] = size << 3;
+	Encode64(pad+padsize, c64, sizeof (c64));
+	padsize += sizeof (c64);
+
+	for (i = 0; i < padsize; i += 128)
+		SHA512Transform(H, pad + i);
+
+	/* truncate the output to the first 256 bits which fit into 'zcp' */
+	Encode64((uint8_t *)zcp, H, sizeof (uint64_t) * 4);
+}
+
+static void
+zio_checksum_SHA256(const void *buf, uint64_t size,
+    const void *ctx_template __unused, 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);
+}
+
+static void
+zio_checksum_SHA512_native(const void *buf, uint64_t size,
+    const void *ctx_template __unused, 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);
+}
+
+static 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]);
+}

Added: head/sys/cddl/boot/zfs/skein_zfs.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/cddl/boot/zfs/skein_zfs.c	Thu Aug 18 00:37:07 2016	(r304321)
@@ -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
+ *
+ * $FreeBSD$
+ */
+/*
+ * Copyright 2013 Saso Kiselkov.  All rights reserved.
+ */
+#include <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*/
+static 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));
+}
+

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list