shithub: mc

Download patch

ref: 9855b5ed494d2a6759747b6cc22e6d43b35a8fd4
parent: 7b625e88ac4f7d8bb5805efa498b29640f36eb80
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Feb 18 17:47:04 EST 2018

Add hmac implementation.

--- a/lib/crypto/bld.sub
+++ b/lib/crypto/bld.sub
@@ -2,11 +2,15 @@
 
 lib crypto =
 	# hashes
+	hash.myr
 	md5.myr
 	sha1.myr
 	sha256.myr
 	sha512.myr
 	sha3.myr
+
+	# hmac
+	hmac.myr
 
 	# ciphers
 	chacha20.myr
--- /dev/null
+++ b/lib/crypto/hash.myr
@@ -1,0 +1,12 @@
+use std
+
+pkg crypto =
+	trait hash @a =
+		Blocksz	: std.size
+		Hashsz	: std.size
+
+		hinit	: (h : @a# -> void)
+		hadd	: (h : @a#, msg : byte[:] -> void)
+		hfin	: (h : @a#, dst : byte[:] -> void)
+	;;
+;;
--- /dev/null
+++ b/lib/crypto/hmac.myr
@@ -1,0 +1,75 @@
+use std
+
+use "sha256"
+use "hash"
+
+pkg crypto =
+	type hmac(@h) :: hash @h = struct
+		inner	: @h
+		outer	: @h
+	;;
+
+	const hmacsha256 	: (key : byte[:], msg : byte[:] -> byte[32])
+	const hmacsha224 	: (key : byte[:], msg : byte[:] -> byte[28])
+	generic hmacinit	: (hmac : hmac(@h)#, key : byte[:] -> void)
+	generic hmacadd		: (hmac : hmac(@h)#, msg : byte[:] -> void)
+	generic hmacfin		: (hmac : hmac(@h)#, dst : byte[:] -> void)
+;;
+
+const hmacsha256 = {key, msg
+	var hmac : hmac(sha256)
+	var r : byte[32]
+
+	hmacinit(&hmac, key)
+	hmacadd(&hmac, msg)
+	hmacfin(&hmac, r[:])
+	-> r
+}
+
+const hmacsha224 = {key, msg
+	var hmac : hmac(sha224)
+	var r : byte[28]
+
+	hmacinit(&hmac, key)
+	hmacadd(&hmac, msg)
+	hmacfin(&hmac, r[:])
+	-> r
+}
+
+
+generic hmacinit = {hmac : hmac(@h)#, key :: hash @h
+	/* for now, max block size is 128 bytes */
+	var k : byte[128], ik : byte[128], ok : byte[128]
+	var hashsz, blksz
+
+	hashsz = impl(Hashsz, @h)
+	blksz = impl(Blocksz, @h)
+	std.slfill(k[:blksz], 0)
+	if key.len > blksz
+		/* abuse the inner hasher a bit */
+		hinit(&hmac.inner)
+		hadd(&hmac.inner, key)
+		hfin(&hmac.inner, k[:hashsz])
+	else
+		std.slcp(k[:key.len], key)
+	;;
+	for var i = 0; i < blksz; i++
+		ik[i] = k[i] ^ 0x36
+		ok[i] = k[i] ^ 0x5c
+	;;
+	hinit(&hmac.inner)
+	hinit(&hmac.outer)
+	hadd(&hmac.inner, ik[:blksz])
+	hadd(&hmac.outer, ok[:blksz])
+}
+
+
+generic hmacadd = {hmac, msg
+	hadd(&hmac.inner, msg)
+}
+
+generic hmacfin = {hmac : hmac(@h)#, dst :: hash @h
+	hfin(&hmac.inner, dst)
+	hadd(&hmac.outer, dst)
+	hfin(&hmac.outer, dst)
+}
--- a/lib/crypto/md5.myr
+++ b/lib/crypto/md5.myr
@@ -1,8 +1,12 @@
 use std
+use "hash"
 
 pkg crypto =
 	type md5
 
+	impl hash md5
+
+	/* legacy/convenience */
 	const md5	: (data : byte[:] -> byte[16])
 	const md5init	: (st : md5# -> void)
 	const md5add	: (st : md5#, data : byte[:] -> void)
@@ -28,76 +32,93 @@
 }
 
 const md5init = {st
-	st.a = 0x67452301
-	st.b = 0xefcdab89
-	st.c = 0x98badcfe
-	st.d = 0x10325476
-        st.msglen = 0
+	hinit(st)
 }
 
-const md5add = {st, data
-	var n, ntail
-
-        ntail = st.msglen % 64
-	st.msglen += data.len
-	if ntail > 0
-		n = std.min(64 - ntail, data.len)
-		std.slcp(st.tail[ntail:ntail + n], data[:n])
-		data = data[n:]
-		if n + ntail < 64
-			-> void
-		;;
-		step(st, st.tail[:])
-	;;
-	while data.len >= 64
-		step(st, data[:64])
-		data = data[64:]
-	;;
-	std.slcp(st.tail[:data.len], data)
+const md5add = {st, msg
+	hadd(st, msg)
 }
 
 const md5fin = {st
 	var r : byte[16]
-        var ntail
+	hfin(st, r[:])
+	-> r
+}
 
-        /* append first padding block */
-        ntail = st.msglen % 64
-        st.tail[ntail++] = 0x80
-	std.slfill(st.tail[ntail:], 0)
-	if 64 - ntail < 8
-		step(st, st.tail[:])
-        	std.slfill(st.tail[:], 0)
-	;;
+impl hash md5 =
+	Blocksz = 64
+	Hashsz = 16
 
-        /* append size block */
-	st.tail[56] = ((st.msglen * 8) >> 0	: byte)
-	st.tail[57] = ((st.msglen * 8) >> 8	: byte)
-	st.tail[58] = ((st.msglen * 8) >> 16	: byte)
-	st.tail[59] = ((st.msglen * 8) >> 24	: byte)
-	st.tail[60] = ((st.msglen * 8) >> 32	: byte)
-	st.tail[61] = ((st.msglen * 8) >> 40	: byte)
-	st.tail[62] = ((st.msglen * 8) >> 48	: byte)
-	st.tail[63] = ((st.msglen * 8) >> 56	: byte)
-        step(st, st.tail[:])
+	hinit = {st
+		st.a = 0x67452301
+		st.b = 0xefcdab89
+		st.c = 0x98badcfe
+		st.d = 0x10325476
+		st.msglen = 0
+	}
 
-	r[0] = (st.a >> 0	: byte)
-	r[1] = (st.a >> 8	: byte)
-	r[2] = (st.a >> 16	: byte)
-	r[3] = (st.a >> 24	: byte)
-	r[4] = (st.b >> 0	: byte)
-	r[5] = (st.b >> 8	: byte)
-	r[6] = (st.b >> 16	: byte)
-	r[7] = (st.b >> 24	: byte)
-	r[8] = (st.c >> 0	: byte)
-	r[9] = (st.c >> 8	: byte)
-	r[10] = (st.c >> 16	: byte)
-	r[11] = (st.c >> 24	: byte)
-	r[12] = (st.d >> 0	: byte)
-	r[13] = (st.d >> 8	: byte)
-	r[14] = (st.d >> 16	: byte)
-	r[15] = (st.d >> 24	: byte)
-	-> r
-}
+	hadd = {st, data
+		var n, ntail
+
+		ntail = st.msglen % 64
+		st.msglen += data.len
+		if ntail > 0
+			n = std.min(64 - ntail, data.len)
+			std.slcp(st.tail[ntail:ntail + n], data[:n])
+			data = data[n:]
+			if n + ntail < 64
+				-> void
+			;;
+			step(st, st.tail[:])
+		;;
+		while data.len >= 64
+			step(st, data[:64])
+			data = data[64:]
+		;;
+		std.slcp(st.tail[:data.len], data)
+	}
+
+	hfin = {st, r
+		var ntail
+
+		/* append first padding block */
+		ntail = st.msglen % 64
+		st.tail[ntail++] = 0x80
+		std.slfill(st.tail[ntail:], 0)
+		if 64 - ntail < 8
+			step(st, st.tail[:])
+			std.slfill(st.tail[:], 0)
+		;;
+
+		/* append size block */
+		st.tail[56] = ((st.msglen * 8) >> 0	: byte)
+		st.tail[57] = ((st.msglen * 8) >> 8	: byte)
+		st.tail[58] = ((st.msglen * 8) >> 16	: byte)
+		st.tail[59] = ((st.msglen * 8) >> 24	: byte)
+		st.tail[60] = ((st.msglen * 8) >> 32	: byte)
+		st.tail[61] = ((st.msglen * 8) >> 40	: byte)
+		st.tail[62] = ((st.msglen * 8) >> 48	: byte)
+		st.tail[63] = ((st.msglen * 8) >> 56	: byte)
+		step(st, st.tail[:])
+
+		r[0] = (st.a >> 0	: byte)
+		r[1] = (st.a >> 8	: byte)
+		r[2] = (st.a >> 16	: byte)
+		r[3] = (st.a >> 24	: byte)
+		r[4] = (st.b >> 0	: byte)
+		r[5] = (st.b >> 8	: byte)
+		r[6] = (st.b >> 16	: byte)
+		r[7] = (st.b >> 24	: byte)
+		r[8] = (st.c >> 0	: byte)
+		r[9] = (st.c >> 8	: byte)
+		r[10] = (st.c >> 16	: byte)
+		r[11] = (st.c >> 24	: byte)
+		r[12] = (st.d >> 0	: byte)
+		r[13] = (st.d >> 8	: byte)
+		r[14] = (st.d >> 16	: byte)
+		r[15] = (st.d >> 24	: byte)
+	}
+;;
 
 const step = {st, blk
 	var a, b, c, d
--- a/lib/crypto/rand.myr
+++ b/lib/crypto/rand.myr
@@ -2,7 +2,6 @@
 use thread
 
 use "entropy"
-use "sha256"
 use "chacha20"
 
 pkg crypto =
--- a/lib/crypto/sha1.myr
+++ b/lib/crypto/sha1.myr
@@ -1,8 +1,12 @@
 use std
+use "hash"
 
 pkg crypto =
 	type sha1
 
+	impl hash sha1
+
+	/* legacy/convenience */
 	const sha1	: (data : byte[:] -> byte[20])
 	const sha1init	: (st : sha1# -> void)
 	const sha1add	: (st : sha1#, data : byte[:] -> void)
@@ -28,84 +32,101 @@
 }
 
 const sha1init = {st
-        st.a = 0x67452301
-        st.b = 0xefcdab89
-        st.c = 0x98badcfe
-        st.d = 0x10325476
-        st.e = 0xc3d2e1f0
-        st.msglen = 0
+	hinit(st)
 }
 
-const sha1add = {st, data
-	var n, ntail
+const sha1add = {st, msg
+	hadd(st, msg)
+}
 
-        ntail = st.msglen % 64
-	st.msglen += data.len
-	if ntail > 0
-		n = std.min(64 - ntail, data.len)
-		std.slcp(st.tail[ntail:ntail + n], data[:n])
-		data = data[n:]
-		if n + ntail < 64
-			-> void
+const sha1fin = {st
+	var r : byte[20]
+	hfin(st, r[:])
+	-> r
+}
+
+impl hash sha1 =
+	Blocksz = 64
+	Hashsz = 20
+
+	hinit = {st
+		st.a = 0x67452301
+		st.b = 0xefcdab89
+		st.c = 0x98badcfe
+		st.d = 0x10325476
+		st.e = 0xc3d2e1f0
+		st.msglen = 0
+	}
+
+	hadd = {st, data
+		var n, ntail
+
+		ntail = st.msglen % 64
+		st.msglen += data.len
+		if ntail > 0
+			n = std.min(64 - ntail, data.len)
+			std.slcp(st.tail[ntail:ntail + n], data[:n])
+			data = data[n:]
+			if n + ntail < 64
+				-> void
+			;;
+			step(st, st.tail[:])
 		;;
-		step(st, st.tail[:])
-        ;;
 
-	while data.len >= 64
-		step(st, data[:64])
-		data = data[64:]
-        ;;
+		while data.len >= 64
+			step(st, data[:64])
+			data = data[64:]
+		;;
 
-	std.slcp(st.tail[:data.len], data)
-}
+		std.slcp(st.tail[:data.len], data)
+	}
 
-const sha1fin = {st
-	var r : byte[20]
-        var ntail
+	hfin = {st, r
+		var ntail
 
-        /* append first padding block */
-        ntail = st.msglen % 64
-        st.tail[ntail++] = 0x80
-	std.slfill(st.tail[ntail:], 0)
-	if 64 - ntail < 8
-		step(st, st.tail[:])
-        	std.slfill(st.tail[:], 0)
-        ;;
+		/* append first padding block */
+		ntail = st.msglen % 64
+		st.tail[ntail++] = 0x80
+		std.slfill(st.tail[ntail:], 0)
+		if 64 - ntail < 8
+			step(st, st.tail[:])
+			std.slfill(st.tail[:], 0)
+		;;
 
 
-        /* append size block */
-	st.tail[56] = ((st.msglen * 8) >> 56	: byte)
-	st.tail[57] = ((st.msglen * 8) >> 48	: byte)
-	st.tail[58] = ((st.msglen * 8) >> 40	: byte)
-	st.tail[59] = ((st.msglen * 8) >> 32	: byte)
-	st.tail[60] = ((st.msglen * 8) >> 24	: byte)
-	st.tail[61] = ((st.msglen * 8) >> 16	: byte)
-	st.tail[62] = ((st.msglen * 8) >> 8	: byte)
-	st.tail[63] = ((st.msglen * 8) >> 0	: byte)
-        step(st, st.tail[:])
+		/* append size block */
+		st.tail[56] = ((st.msglen * 8) >> 56	: byte)
+		st.tail[57] = ((st.msglen * 8) >> 48	: byte)
+		st.tail[58] = ((st.msglen * 8) >> 40	: byte)
+		st.tail[59] = ((st.msglen * 8) >> 32	: byte)
+		st.tail[60] = ((st.msglen * 8) >> 24	: byte)
+		st.tail[61] = ((st.msglen * 8) >> 16	: byte)
+		st.tail[62] = ((st.msglen * 8) >> 8	: byte)
+		st.tail[63] = ((st.msglen * 8) >> 0	: byte)
+		step(st, st.tail[:])
 
-	r[0]  = (st.a >> 24	: byte)
-	r[1]  = (st.a >> 16	: byte)
-	r[2]  = (st.a >> 8	: byte)
-	r[3]  = (st.a >> 0	: byte)
-	r[4]  = (st.b >> 24	: byte)
-	r[5]  = (st.b >> 16	: byte)
-	r[6]  = (st.b >> 8	: byte)
-	r[7]  = (st.b >> 0	: byte)
-	r[8]  = (st.c >> 24	: byte)
-	r[9]  = (st.c >> 16	: byte)
-	r[10] = (st.c >> 8	: byte)
-	r[11] = (st.c >> 0	: byte)
-	r[12] = (st.d >> 16	: byte)
-	r[13] = (st.d >> 24	: byte)
-	r[14] = (st.d >> 8	: byte)
-	r[15] = (st.d >> 0	: byte)
-	r[16] = (st.e >> 16	: byte)
-	r[17] = (st.e >> 24	: byte)
-	r[18] = (st.e >> 8	: byte)
-	r[19] = (st.e >> 0	: byte)
-	-> r
-}
+		r[0]  = (st.a >> 24	: byte)
+		r[1]  = (st.a >> 16	: byte)
+		r[2]  = (st.a >> 8	: byte)
+		r[3]  = (st.a >> 0	: byte)
+		r[4]  = (st.b >> 24	: byte)
+		r[5]  = (st.b >> 16	: byte)
+		r[6]  = (st.b >> 8	: byte)
+		r[7]  = (st.b >> 0	: byte)
+		r[8]  = (st.c >> 24	: byte)
+		r[9]  = (st.c >> 16	: byte)
+		r[10] = (st.c >> 8	: byte)
+		r[11] = (st.c >> 0	: byte)
+		r[12] = (st.d >> 16	: byte)
+		r[13] = (st.d >> 24	: byte)
+		r[14] = (st.d >> 8	: byte)
+		r[15] = (st.d >> 0	: byte)
+		r[16] = (st.e >> 16	: byte)
+		r[17] = (st.e >> 24	: byte)
+		r[18] = (st.e >> 8	: byte)
+		r[19] = (st.e >> 0	: byte)
+	}
+;;
 
 const K0 = 0x5a827999
 const K1 = 0x6ed9eba1
--- a/lib/crypto/sha256.myr
+++ b/lib/crypto/sha256.myr
@@ -1,9 +1,14 @@
 use std
+use "hash"
 
 pkg crypto =
 	type sha256
 	type sha224
 
+	impl hash sha256
+	impl hash sha224
+
+	/* for convenience/legacy */
 	const sha256	: (data : byte[:] -> byte[32])
 	const sha256init	: (st : sha256# -> void)
 	const sha256add	: (st : sha256#, data : byte[:] -> void)
@@ -22,71 +27,41 @@
 ;;
 
 const sha256 = {data
-	var st
+	var st : sha256, r : byte[32]
 
-	sha256init(&st)
-	sha256add(&st, data)
-	-> sha256fin(&st)
+	hinit(&st)
+	hadd(&st, data)
+	hfin(&st, r[:])
+	-> r
 }
 
 const sha256init = {st
-	st.x[0] = 0x6A09E667
-	st.x[1] = 0xBB67AE85
-	st.x[2] = 0x3C6EF372
-	st.x[3] = 0xA54FF53A
-	st.x[4] = 0x510e527f
-	st.x[5] = 0x9b05688c
-	st.x[6] = 0x1f83d9ab
-	st.x[7] = 0x5be0cd19
-	st.msglen = 0
+	hinit(st)
 }
 
 const sha256add = {st, data
-	var n, ntail
-
-	ntail = st.msglen % 64
-	st.msglen += data.len
-	if ntail > 0
-		n = std.min(64 - ntail, data.len)
-		std.slcp(st.tail[ntail:ntail + n], data[:n])
-		data = data[n:]
-		if n + ntail < 64
-			-> void
-		;;
-		step(st.x[:], st.tail[:])
-	;;
-
-	while data.len >= 64
-		step(st.x[:], data[:64])
-		data = data[64:]
-	;;
-
-	ntail = st.msglen % 64
-	std.slcp(st.tail[:ntail], data)
+	hadd(st, data)
 }
 
 const sha256fin = {st
 	var r : byte[32]
+	hfin(st, r[:])
+	-> r
+}
 
-	tail(st.x[:], st.msglen, st.tail[:])
+const sha224init = {st
+	hinit(st)
+}
+const sha224add = {st, data
+	hadd(st, data)
+}
 
-	pack(r[0:4], st.x[0])
-	pack(r[4:8], st.x[1])
-	pack(r[8:12], st.x[2])
-	pack(r[12:16], st.x[3])
-	pack(r[16:20], st.x[4])
-	pack(r[20:24], st.x[5])
-	pack(r[24:28], st.x[6])
-	pack(r[28:32], st.x[7])
+const sha224fin = {st
+	var r : byte[28]
+	hfin(st, r[:])
 	-> r
 }
 
-type sha224 = struct
-	x : uint32[8]
-	tail : byte[64]
-	msglen : uint64
-;;
-
 const sha224 = {data
 	var st
 
@@ -95,56 +70,119 @@
 	-> sha224fin(&st)
 }
 
-const sha224init = {st
-	st.x[0] = 0xc1059ed8
-	st.x[1] = 0x367cd507
-	st.x[2] = 0x3070dd17
-	st.x[3] = 0xf70e5939
-	st.x[4] = 0xffc00b31
-	st.x[5] = 0x68581511
-	st.x[6] = 0x64f98fa7
-	st.x[7] = 0xbefa4fa4
-	st.msglen = 0
-}
 
-const sha224add = {st, data
-	var n, ntail
+impl hash sha256 =
+	Blocksz = 64
+	Hashsz = 32
 
-	ntail = st.msglen % 64
-	st.msglen += data.len
-	if ntail > 0
-		n = std.min(64 - ntail, data.len)
-		std.slcp(st.tail[ntail:ntail + n], data[:n])
-		data = data[n:]
-		if n + ntail < 64
-			-> void
+	hinit = {st
+		st.x[0] = 0x6a09e667
+		st.x[1] = 0xbb67ae85
+		st.x[2] = 0x3c6ef372
+		st.x[3] = 0xa54ff53a
+		st.x[4] = 0x510e527f
+		st.x[5] = 0x9b05688c
+		st.x[6] = 0x1f83d9ab
+		st.x[7] = 0x5be0cd19
+		st.msglen = 0
+	}
+
+	hadd = {st, data
+		var n, ntail
+
+		ntail = st.msglen % 64
+		st.msglen += data.len
+		if ntail > 0
+			n = std.min(64 - ntail, data.len)
+			std.slcp(st.tail[ntail:ntail + n], data[:n])
+			data = data[n:]
+			if n + ntail < 64
+				-> void
+			;;
+			step(st.x[:], st.tail[:])
 		;;
-		step(st.x[:], st.tail[:])
-	;;
 
-	while data.len >= 64
-		step(st.x[:], data[:64])
-		data = data[64:]
-	;;
+		while data.len >= 64
+			step(st.x[:], data[:64])
+			data = data[64:]
+		;;
 
-	ntail = st.msglen % 64
-	std.slcp(st.tail[:ntail], data)
-}
+		ntail = st.msglen % 64
+		std.slcp(st.tail[:ntail], data)
+	}
 
-const sha224fin = {st
-	var r : byte[28]
+	hfin = {st, r
+		tail(st.x[:], st.msglen, st.tail[:])
 
-	tail(st.x[:], st.msglen, st.tail[:])
+		pack(r[0:4], st.x[0])
+		pack(r[4:8], st.x[1])
+		pack(r[8:12], st.x[2])
+		pack(r[12:16], st.x[3])
+		pack(r[16:20], st.x[4])
+		pack(r[20:24], st.x[5])
+		pack(r[24:28], st.x[6])
+		pack(r[28:32], st.x[7])
+	}
+;;
 
-	pack(r[0:4], st.x[0])
-	pack(r[4:8], st.x[1])
-	pack(r[8:12], st.x[2])
-	pack(r[12:16], st.x[3])
-	pack(r[16:20], st.x[4])
-	pack(r[20:24], st.x[5])
-	pack(r[24:28], st.x[6])
-	-> r
-}
+type sha224 = struct
+	x : uint32[8]
+	tail : byte[64]
+	msglen : uint64
+;;
+
+impl hash sha224 =
+	Blocksz = 64
+	Hashsz = 28
+
+	hinit = {st
+		st.x[0] = 0xc1059ed8
+		st.x[1] = 0x367cd507
+		st.x[2] = 0x3070dd17
+		st.x[3] = 0xf70e5939
+		st.x[4] = 0xffc00b31
+		st.x[5] = 0x68581511
+		st.x[6] = 0x64f98fa7
+		st.x[7] = 0xbefa4fa4
+		st.msglen = 0
+	}
+
+	hadd = {st, data
+		var n, ntail
+
+		ntail = st.msglen % 64
+		st.msglen += data.len
+		if ntail > 0
+			n = std.min(64 - ntail, data.len)
+			std.slcp(st.tail[ntail:ntail + n], data[:n])
+			data = data[n:]
+			if n + ntail < 64
+				-> void
+			;;
+			step(st.x[:], st.tail[:])
+		;;
+
+		while data.len >= 64
+			step(st.x[:], data[:64])
+			data = data[64:]
+		;;
+
+		ntail = st.msglen % 64
+		std.slcp(st.tail[:ntail], data)
+	}
+
+	hfin = {st, r
+		tail(st.x[:], st.msglen, st.tail[:])
+
+		pack(r[0:4], st.x[0])
+		pack(r[4:8], st.x[1])
+		pack(r[8:12], st.x[2])
+		pack(r[12:16], st.x[3])
+		pack(r[16:20], st.x[4])
+		pack(r[20:24], st.x[5])
+		pack(r[24:28], st.x[6])
+	}
+;;
 
 
 const tail = {x, msglen, tail
--- a/lib/crypto/sha512.myr
+++ b/lib/crypto/sha512.myr
@@ -1,9 +1,14 @@
 use std
+use "hash"
 
 pkg crypto =
 	type sha512
 	type sha384
 
+	impl hash sha512
+	impl hash sha384
+
+	/* for convenience/legacy */
 	const sha512	: (data : byte[:] -> byte[64])
 	const sha512init	: (st : sha512# -> void)
 	const sha512add	: (st : sha512#, data : byte[:] -> void)
@@ -29,122 +34,156 @@
 ;;
 
 const sha512 = {data
-	var st
+	var st : sha512 
+	var r : byte[64]
 
-	sha512init(&st)
-	sha512add(&st, data)
-	-> sha512fin(&st)
+	hinit(&st)
+	hadd(&st, data)
+	hfin(&st, r[:])
+	-> r
 }
 
 const sha512init = {st
-	st.x[0] = 0x6a09e667f3bcc908ul
-	st.x[1] = 0xbb67ae8584caa73bul
-	st.x[2] = 0x3c6ef372fe94f82bul
-	st.x[3] = 0xa54ff53a5f1d36f1ul
-	st.x[4] = 0x510e527fade682d1ul
-	st.x[5] = 0x9b05688c2b3e6c1ful
-	st.x[6] = 0x1f83d9abfb41bd6bul
-	st.x[7] = 0x5be0cd19137e2179ul
-	st.msglen = 0
+	hinit(st)
 }
-
-const sha512add = {st, data
-	var n, ntail
-
-	ntail = st.msglen % 128
-	st.msglen += data.len
-	if ntail > 0
-		n = std.min(128 - ntail, data.len)
-		std.slcp(st.tail[ntail:ntail+n], data[:n])
-		data = data[n:]
-		if n + ntail < 128
-			-> void
-		;;
-		step(st.x[:], st.tail[:])
-	;;
-
-	while data.len >= 128
-		step(st.x[:], data[:128])
-		data = data[128:]
-	;;
-
-	ntail = st.msglen % 128
-	std.slcp(st.tail[:ntail], data)
+const sha512add = {st, msg
+	hadd(st, msg)
 }
-
 const sha512fin = {st
 	var r : byte[64]
-
-	tail(st.x[:], st.msglen, st.tail[:])
-
-	pack(r[ 0: 8],	st.x[0])
-	pack(r[ 8:16],	st.x[1])
-	pack(r[16:24],	st.x[2])
-	pack(r[24:32],	st.x[3])
-	pack(r[32:40],	st.x[4])
-	pack(r[40:48],	st.x[5])
-	pack(r[48:56],	st.x[6])
-	pack(r[56:64],	st.x[7])
+	hfin(st, r[:])
 	-> r
 }
 
 const sha384 = {data
-	var st
+	var st : sha384
+	var r : byte[48]
 
-	sha384init(&st)
-	sha384add(&st, data)
-	-> sha384fin(&st)
+	hinit(&st)
+	hadd(&st, data)
+	hfin(&st, r[:])
+	-> r
 }
 
 const sha384init = {st
-	st.x[0] = 0xCBBB9D5DC1059ED8ul
-	st.x[1] = 0x629A292A367CD507ul
-	st.x[2] = 0x9159015A3070DD17ul
-	st.x[3] = 0x152FECD8F70E5939ul
-	st.x[4] = 0x67332667FFC00B31ul
-	st.x[5] = 0x8EB44A8768581511ul
-	st.x[6] = 0xDB0C2E0D64F98FA7ul
-	st.x[7] = 0x47B5481DBEFA4FA4ul
-	st.msglen = 0
+	hinit(st)
 }
 
-const sha384add = {st, data
-	var n, ntail
+const sha384add = {st, msg
+	hadd(st, msg)
+}
 
-	ntail = st.msglen % 128
-	st.msglen += data.len
-	if ntail > 0
-		n = std.min(128 - ntail, data.len)
-		std.slcp(st.tail[ntail:ntail+n], data[:n])
-		data = data[n:]
-		if n + ntail < 128
-			-> void
+const sha384fin = {st
+	var r : byte[48]
+	hfin(st, r[:])
+	-> r
+}
+
+impl hash sha512 =
+	Blocksz = 128
+	Hashsz = 64
+
+	hinit = {st
+		st.x[0] = 0x6a09e667f3bcc908ul
+		st.x[1] = 0xbb67ae8584caa73bul
+		st.x[2] = 0x3c6ef372fe94f82bul
+		st.x[3] = 0xa54ff53a5f1d36f1ul
+		st.x[4] = 0x510e527fade682d1ul
+		st.x[5] = 0x9b05688c2b3e6c1ful
+		st.x[6] = 0x1f83d9abfb41bd6bul
+		st.x[7] = 0x5be0cd19137e2179ul
+		st.msglen = 0
+	}
+
+	hadd = {st, data
+		var n, ntail
+
+		ntail = st.msglen % 128
+		st.msglen += data.len
+		if ntail > 0
+			n = std.min(128 - ntail, data.len)
+			std.slcp(st.tail[ntail:ntail+n], data[:n])
+			data = data[n:]
+			if n + ntail < 128
+				-> void
+			;;
+			step(st.x[:], st.tail[:])
 		;;
-		step(st.x[:], st.tail[:])
-	;;
 
-	while data.len >= 128
-		step(st.x[:], data[:128])
-		data = data[128:]
-	;;
+		while data.len >= 128
+			step(st.x[:], data[:128])
+			data = data[128:]
+		;;
 
-	ntail = st.msglen % 128
-	std.slcp(st.tail[:ntail], data)
-}
+		ntail = st.msglen % 128
+		std.slcp(st.tail[:ntail], data)
+	}
 
-const sha384fin = {st
-	var r : byte[48]
+	hfin = {st, r
+		tail(st.x[:], st.msglen, st.tail[:])
 
-	tail(st.x[:], st.msglen, st.tail[:])
+		pack(r[ 0: 8],	st.x[0])
+		pack(r[ 8:16],	st.x[1])
+		pack(r[16:24],	st.x[2])
+		pack(r[24:32],	st.x[3])
+		pack(r[32:40],	st.x[4])
+		pack(r[40:48],	st.x[5])
+		pack(r[48:56],	st.x[6])
+		pack(r[56:64],	st.x[7])
+	}
+;;
 
-	pack(r[ 0: 8],	st.x[0])
-	pack(r[ 8:16],	st.x[1])
-	pack(r[16:24],	st.x[2])
-	pack(r[24:32],	st.x[3])
-	pack(r[32:40],	st.x[4])
-	pack(r[40:48],	st.x[5])
-	-> r
-}
+impl hash sha384 =
+	Blocksz = 128
+	Hashsz = 48
+
+	hinit = {st
+		st.x[0] = 0xCBBB9D5DC1059ED8ul
+		st.x[1] = 0x629A292A367CD507ul
+		st.x[2] = 0x9159015A3070DD17ul
+		st.x[3] = 0x152FECD8F70E5939ul
+		st.x[4] = 0x67332667FFC00B31ul
+		st.x[5] = 0x8EB44A8768581511ul
+		st.x[6] = 0xDB0C2E0D64F98FA7ul
+		st.x[7] = 0x47B5481DBEFA4FA4ul
+		st.msglen = 0
+	}
+
+	hadd = {st, data
+		var n, ntail
+
+		ntail = st.msglen % 128
+		st.msglen += data.len
+		if ntail > 0
+			n = std.min(128 - ntail, data.len)
+			std.slcp(st.tail[ntail:ntail+n], data[:n])
+			data = data[n:]
+			if n + ntail < 128
+				-> void
+			;;
+			step(st.x[:], st.tail[:])
+		;;
+
+		while data.len >= 128
+			step(st.x[:], data[:128])
+			data = data[128:]
+		;;
+
+		ntail = st.msglen % 128
+		std.slcp(st.tail[:ntail], data)
+	}
+
+	hfin = {st, r
+		tail(st.x[:], st.msglen, st.tail[:])
+
+		pack(r[ 0: 8],	st.x[0])
+		pack(r[ 8:16],	st.x[1])
+		pack(r[16:24],	st.x[2])
+		pack(r[24:32],	st.x[3])
+		pack(r[32:40],	st.x[4])
+		pack(r[40:48],	st.x[5])
+	}
+;;
 
 
 const tail = {x, msglen, tail
--- a/lib/std/sjlj.myr
+++ /dev/null
@@ -1,8 +1,0 @@
-pkg std =
-	type jmpbuf = struct
-		regs	: uint64[8]
-	;;
-
-	extern const setjmp	: (jb : jmpbuf# -> bool)
-	extern const longjmp	: (jb : jmpbuf# -> void)
-;;