Skip to contentSkip to conversation

random pt4: Moving and sharing code

PATCH In review Matt Mackall 4 participants 24 messages Jan 21, 2005 – Jan 27, 2005

Subsystems (8)
lore
Share & tools
lore
#5 lore raw

PATCH 5/12 random pt4: Move SHA code to lib/

In reply to Matt Mackall

Move random SHA code to lib/.

lib/Makefile +1 -1
Index: rnd2/lib/Makefile
===================================================================
@@ -5,7 +5,7 @@
 lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
 	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
 	 kobject.o kref.o idr.o div64.o parser.o int_sqrt.o \
-	 bitmap.o extable.o kobject_uevent.o prio_tree.o
+	 bitmap.o extable.o kobject_uevent.o prio_tree.o sha1.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
drivers/char/random.c +5 -116

162 lines not on this page · raw message

include/linux/cryptohash.h new file +10 -0
Index: rnd2/include/linux/cryptohash.h
===================================================================
@@ -0,0 +1,10 @@
+#ifndef __CRYPTOHASH_H
+#define __CRYPTOHASH_H
+
+#define SHA_DIGEST_WORDS 5
+#define SHA_WORKSPACE_WORDS 80
+
+void sha_init(__u32 *buf);
+void sha_transform(__u32 *digest, const char *data, __u32 *W);
+
+#endif
lib/sha1.c new file +102 -0

102 lines not on this page · raw message

#11 lore raw

PATCH 11/12 random pt4: Move syncookies to net/

In reply to Matt Mackall

Move syncookie code off to networking land.

drivers/char/random.c +0 -81
Index: rnd2/drivers/char/random.c
===================================================================
@@ -366,10 +366,6 @@
  * hash; hash collisions will occur no more often than chance.
  */
 
-#ifdef CONFIG_SYN_COOKIES
-static __u32 syncookie_secret[2][16-3+SHA_WORKSPACE_WORDS];
-#endif
-
 /*
  * Static global variables
  */
@@ -901,9 +897,6 @@
 	init_std_data(&input_pool);
 	init_std_data(&blocking_pool);
 	init_std_data(&nonblocking_pool);
-#ifdef CONFIG_SYN_COOKIES
-	get_random_bytes(syncookie_secret, sizeof(syncookie_secret));
-#endif
 	return 0;
 }
 module_init(rand_initialize);
@@ -1578,78 +1571,4 @@
 	return half_md4_transform(hash, keyptr->secret);
 }
 
-#ifdef CONFIG_SYN_COOKIES
-/*
- * Secure SYN cookie computation. This is the algorithm worked out by
- * Dan Bernstein and Eric Schenk.
- *
- * For linux I implement the 1 minute counter by looking at the jiffies clock.
- * The count is passed in as a parameter, so this code doesn't much care.
- */
-
-#define COOKIEBITS 24	/* Upper bits store count */
-#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
-
-static u32 cookie_hash(u32 saddr, u32 daddr, u32 sport, u32 dport,
-		       u32 count, int c)
-{
-	__u32 tmp[16 + 5 + SHA_WORKSPACE_WORDS];
-
-	memcpy(tmp + 3, syncookie_secret[c], sizeof(syncookie_secret[c]));
-	tmp[0] = saddr;
-	tmp[1] = daddr;
-	tmp[2] = (sport << 16) + dport;
-	tmp[3] = count;
-	sha_transform(tmp + 16, tmp);
-
-	return tmp[17];
-}
-
-__u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport,
-		__u16 dport, __u32 sseq, __u32 count, __u32 data)
-{
-	/*
-	 * Compute the secure sequence number.
-	 * The output should be:
-   	 *   HASH(sec1,saddr,sport,daddr,dport,sec1) + sseq + (count * 2^24)
-	 *      + (HASH(sec2,saddr,sport,daddr,dport,count,sec2) % 2^24).
-	 * Where sseq is their sequence number and count increases every
-	 * minute by 1.
-	 * As an extra hack, we add a small "data" value that encodes the
-	 * MSS into the second hash value.
-	 */
-
-	return (cookie_hash(saddr, daddr, sport, dport, 0, 0) +
-		sseq + (count << COOKIEBITS) +
-		((cookie_hash(saddr, daddr, sport, dport, count, 1) + data)
-		 & COOKIEMASK));
-}
-
-/*
- * This retrieves the small "data" value from the syncookie.
- * If the syncookie is bad, the data returned will be out of
- * range.  This must be checked by the caller.
- *
- * The count value used to generate the cookie must be within
- * "maxdiff" if the current (passed-in) "count".  The return value
- * is (__u32)-1 if this test fails.
- */
-__u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, __u16 sport,
-		__u16 dport, __u32 sseq, __u32 count, __u32 maxdiff)
-{
-	__u32 diff;
-
-	/* Strip away the layers from the cookie */
-	cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq;
-
-	/* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */
-	diff = (count - (cookie >> COOKIEBITS)) & ((__u32)-1 >> COOKIEBITS);
-	if (diff >= maxdiff)
-		return (__u32)-1;
-
-	return (cookie -
-		cookie_hash(saddr, daddr, sport, dport, count - diff, 1))
-		& COOKIEMASK;	/* Leaving the data behind */
-}
-#endif
 #endif /* CONFIG_INET */
net/ipv4/syncookies.c +77 -0

88 lines not on this page · raw message

include/linux/random.h +0 -8
Index: rnd2/include/linux/random.h
===================================================================
@@ -55,14 +55,6 @@
 extern u32 secure_tcp_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport);
 extern __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
 					__u16 sport, __u16 dport);
-extern __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr,
-				   __u16 sport, __u16 dport,
-				   __u32 sseq, __u32 count,
-				   __u32 data);
-extern __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr,
-				  __u32 daddr, __u16 sport,
-				  __u16 dport, __u32 sseq,
-				  __u32 count, __u32 maxdiff);
 extern __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
 					  __u16 sport, __u16 dport);
 
#0 lore raw

cover random pt4: Moving and sharing code

This series focuses on moving and sharing code in /drivers/char/random.c. It applies on top of -mm2 which contains my earlier patches.

New bitop:
1 Create new rol32/ror32 bitops 2 Use them throughout the tree

Share SHA code in lib:

3  Kill the SHA1 variants
4  Cleanup SHA1 interface
5  Move SHA1 code to lib/
6  Replace SHA1 with faster version
7  Update cryptolib to use SHA1 from lib

Share halfmd4 hash:
8 Move halfMD4 to lib
9 Kill duplicate halfMD4 in ext3 htree

Move network random bits:
10 Simplify and shrink syncookie code 11 Move syncookies to net/
12 Move other tcp/ip bits to net/

#7 lore raw

PATCH 7/12 random pt4: Update cryptolib to use SHA fro lib

In reply to Matt Mackall

Drop the cryptolib SHA implementation and use the faster and much smaller SHA implementation from lib/. Saves about 5K. This also saves time by doing one memset per update call rather than one per SHA block.

crypto/sha1.c +7 -71
Index: rnd2/crypto/sha1.c
===================================================================
@@ -4,8 +4,7 @@
  * SHA1 Secure Hash Algorithm.
  *
  * Derived from cryptoapi implementation, adapted for in-place
- * scatterlist interface.  Originally based on the public domain
- * implementation written by Steve Reid.
+ * scatterlist interface.
  *
  * Copyright (c) Alan Smithee.
  * Copyright (c) Andrew McDonald <[email protected]>
@@ -13,7 +12,7 @@
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option) 
+ * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
  */
@@ -21,84 +20,19 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/crypto.h>
+#include <linux/cryptohash.h>
 #include <asm/scatterlist.h>
 #include <asm/byteorder.h>
 
 #define SHA1_DIGEST_SIZE	20
 #define SHA1_HMAC_BLOCK_SIZE	64
 
-/* blk0() and blk() perform the initial expand. */
-/* I got the idea of expanding during the round function from SSLeay */
-# define blk0(i) block32[i]
-
-#define blk(i) (block32[i&15] = rol32(block32[(i+13)&15]^block32[(i+8)&15] \
-    ^block32[(i+2)&15]^block32[i&15],1))
-
-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol32(v,5); \
-                        w=rol32(w,30);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol32(v,5); \
-                        w=rol32(w,30);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol32(v,5);w=rol32(w,30);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol32(v,5); \
-                        w=rol32(w,30);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol32(v,5);w=rol32(w,30);
-
 struct sha1_ctx {
         u64 count;
         u32 state[5];
         u8 buffer[64];
 };
 
-/* Hash a single 512-bit block. This is the core of the algorithm. */
-static void sha1_transform(u32 *state, const u8 *in)
-{
-	u32 a, b, c, d, e;
-	u32 block32[16];
-
-	/* convert/copy data to workspace */
-	for (a = 0; a < sizeof(block32)/sizeof(u32); a++)
-	  block32[a] = be32_to_cpu (((const u32 *)in)[a]);
-
-	/* Copy context->state[] to working vars */
-	a = state[0];
-	b = state[1];
-	c = state[2];
-	d = state[3];
-	e = state[4];
-
-	/* 4 rounds of 20 operations each. Loop unrolled. */
-	R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
-	R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
-	R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
-	R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
-	R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
-	R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
-	R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
-	R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
-	R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
-	R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
-	R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
-	R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
-	R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
-	R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
-	R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
-	R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
-	R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
-	R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
-	R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
-	R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-	/* Add the working vars back into context.state[] */
-	state[0] += a;
-	state[1] += b;
-	state[2] += c;
-	state[3] += d;
-	state[4] += e;
-	/* Wipe variables */
-	a = b = c = d = e = 0;
-	memset (block32, 0x00, sizeof block32);
-}
-
 static void sha1_init(void *ctx)
 {
 	struct sha1_ctx *sctx = ctx;
@@ -115,19 +49,21 @@
 {
 	struct sha1_ctx *sctx = ctx;
 	unsigned int i, j;
+	u32 temp[SHA_WORKSPACE_WORDS];
 
 	j = (sctx->count >> 3) & 0x3f;
 	sctx->count += len << 3;
 
 	if ((j + len) > 63) {
 		memcpy(&sctx->buffer[j], data, (i = 64-j));
-		sha1_transform(sctx->state, sctx->buffer);
+		sha_transform(sctx->state, sctx->buffer, temp);
 		for ( ; i + 63 < len; i += 64) {
-			sha1_transform(sctx->state, &data[i]);
+			sha_transform(sctx->state, &data[i], temp);
 		}
 		j = 0;
 	}
 	else i = 0;
+	memset(temp, 0, sizeof(temp));
 	memcpy(&sctx->buffer[j], &data[i], len - i);
 }
 
#3 lore raw

PATCH 3/12 random pt4: Kill the SHA variants

In reply to Matt Mackall

Kill the unrolled SHA variants, they're unused and duplicate code in cryptoapi.

drivers/char/random.c +0 -145
Index: rnd2/drivers/char/random.c
===================================================================
@@ -698,9 +698,6 @@
 #define EXTRACT_SIZE 10
 #define HASH_EXTRA_SIZE 80
 
-/* Various size/speed tradeoffs are available.  Choose 0..3. */
-#define SHA_CODE_SIZE 0
-
 /*
  * SHA transform algorithm, taken from code written by Peter Gutmann,
  * and placed in the public domain.
@@ -720,9 +717,6 @@
 #define K3  0x8F1BBCDCL			/* Rounds 40-59: sqrt(5) * 2^30 */
 #define K4  0xCA62C1D6L			/* Rounds 60-79: sqrt(10) * 2^30 */
 
-#define subRound(a, b, c, d, e, f, k, data) \
-    (e += rol32(a, 5) + f(b, c, d) + k + data, b = rol32(b, 30))
-
 static void sha_transform(__u32 digest[85], __u32 const data[16])
 {
 	__u32 A, B, C, D, E;     /* Local vars */
@@ -750,11 +744,6 @@
 	E = digest[ 4 ];
 
 	/* Heavy mangling, in 4 sub-rounds of 20 iterations each. */
-#if SHA_CODE_SIZE == 0
-	/*
-	 * Approximately 50% of the speed of the largest version, but
-	 * takes up 1/16 the space.  Saves about 6k on an i386 kernel.
-	 */
 	for (i = 0; i < 80; i++) {
 		if (i < 40) {
 			if (i < 20)
@@ -770,139 +759,6 @@
 		TEMP += rol32(A, 5) + E + W[i];
 		E = D; D = C; C = rol32(B, 30); B = A; A = TEMP;
 	}
-#elif SHA_CODE_SIZE == 1
-	for (i = 0; i < 20; i++) {
-		TEMP = f1(B, C, D) + K1 + rol32(A, 5) + E + W[i];
-		E = D; D = C; C = rol32(B, 30); B = A; A = TEMP;
-	}
-	for (; i < 40; i++) {
-		TEMP = f2(B, C, D) + K2 + rol32(A, 5) + E + W[i];
-		E = D; D = C; C = rol32(B, 30); B = A; A = TEMP;
-	}
-	for (; i < 60; i++) {
-		TEMP = f3(B, C, D) + K3 + rol32(A, 5) + E + W[i];
-		E = D; D = C; C = rol22(B, 30); B = A; A = TEMP;
-	}
-	for (; i < 80; i++) {
-		TEMP = f4(B, C, D) + K4 + rol32(A, 5) + E + W[i];
-		E = D; D = C; C = rol32(B, 30); B = A; A = TEMP;
-	}
-#elif SHA_CODE_SIZE == 2
-	for (i = 0; i < 20; i += 5) {
-		subRound(A, B, C, D, E, f1, K1, W[i  ]);
-		subRound(E, A, B, C, D, f1, K1, W[i+1]);
-		subRound(D, E, A, B, C, f1, K1, W[i+2]);
-		subRound(C, D, E, A, B, f1, K1, W[i+3]);
-		subRound(B, C, D, E, A, f1, K1, W[i+4]);
-	}
-	for (; i < 40; i += 5) {
-		subRound(A, B, C, D, E, f2, K2, W[i  ]);
-		subRound(E, A, B, C, D, f2, K2, W[i+1]);
-		subRound(D, E, A, B, C, f2, K2, W[i+2]);
-		subRound(C, D, E, A, B, f2, K2, W[i+3]);
-		subRound(B, C, D, E, A, f2, K2, W[i+4]);
-	}
-	for (; i < 60; i += 5) {
-		subRound(A, B, C, D, E, f3, K3, W[i  ]);
-		subRound(E, A, B, C, D, f3, K3, W[i+1]);
-		subRound(D, E, A, B, C, f3, K3, W[i+2]);
-		subRound(C, D, E, A, B, f3, K3, W[i+3]);
-		subRound(B, C, D, E, A, f3, K3, W[i+4]);
-	}
-	for (; i < 80; i += 5) {
-		subRound(A, B, C, D, E, f4, K4, W[i  ]);
-		subRound(E, A, B, C, D, f4, K4, W[i+1]);
-		subRound(D, E, A, B, C, f4, K4, W[i+2]);
-		subRound(C, D, E, A, B, f4, K4, W[i+3]);
-		subRound(B, C, D, E, A, f4, K4, W[i+4]);
-	}
-#elif SHA_CODE_SIZE == 3 /* Really large version */
-	subRound(A, B, C, D, E, f1, K1, W[ 0]);
-	subRound(E, A, B, C, D, f1, K1, W[ 1]);
-	subRound(D, E, A, B, C, f1, K1, W[ 2]);
-	subRound(C, D, E, A, B, f1, K1, W[ 3]);
-	subRound(B, C, D, E, A, f1, K1, W[ 4]);
-	subRound(A, B, C, D, E, f1, K1, W[ 5]);
-	subRound(E, A, B, C, D, f1, K1, W[ 6]);
-	subRound(D, E, A, B, C, f1, K1, W[ 7]);
-	subRound(C, D, E, A, B, f1, K1, W[ 8]);
-	subRound(B, C, D, E, A, f1, K1, W[ 9]);
-	subRound(A, B, C, D, E, f1, K1, W[10]);
-	subRound(E, A, B, C, D, f1, K1, W[11]);
-	subRound(D, E, A, B, C, f1, K1, W[12]);
-	subRound(C, D, E, A, B, f1, K1, W[13]);
-	subRound(B, C, D, E, A, f1, K1, W[14]);
-	subRound(A, B, C, D, E, f1, K1, W[15]);
-	subRound(E, A, B, C, D, f1, K1, W[16]);
-	subRound(D, E, A, B, C, f1, K1, W[17]);
-	subRound(C, D, E, A, B, f1, K1, W[18]);
-	subRound(B, C, D, E, A, f1, K1, W[19]);
-
-	subRound(A, B, C, D, E, f2, K2, W[20]);
-	subRound(E, A, B, C, D, f2, K2, W[21]);
-	subRound(D, E, A, B, C, f2, K2, W[22]);
-	subRound(C, D, E, A, B, f2, K2, W[23]);
-	subRound(B, C, D, E, A, f2, K2, W[24]);
-	subRound(A, B, C, D, E, f2, K2, W[25]);
-	subRound(E, A, B, C, D, f2, K2, W[26]);
-	subRound(D, E, A, B, C, f2, K2, W[27]);
-	subRound(C, D, E, A, B, f2, K2, W[28]);
-	subRound(B, C, D, E, A, f2, K2, W[29]);
-	subRound(A, B, C, D, E, f2, K2, W[30]);
-	subRound(E, A, B, C, D, f2, K2, W[31]);
-	subRound(D, E, A, B, C, f2, K2, W[32]);
-	subRound(C, D, E, A, B, f2, K2, W[33]);
-	subRound(B, C, D, E, A, f2, K2, W[34]);
-	subRound(A, B, C, D, E, f2, K2, W[35]);
-	subRound(E, A, B, C, D, f2, K2, W[36]);
-	subRound(D, E, A, B, C, f2, K2, W[37]);
-	subRound(C, D, E, A, B, f2, K2, W[38]);
-	subRound(B, C, D, E, A, f2, K2, W[39]);
-
-	subRound(A, B, C, D, E, f3, K3, W[40]);
-	subRound(E, A, B, C, D, f3, K3, W[41]);
-	subRound(D, E, A, B, C, f3, K3, W[42]);
-	subRound(C, D, E, A, B, f3, K3, W[43]);
-	subRound(B, C, D, E, A, f3, K3, W[44]);
-	subRound(A, B, C, D, E, f3, K3, W[45]);
-	subRound(E, A, B, C, D, f3, K3, W[46]);
-	subRound(D, E, A, B, C, f3, K3, W[47]);
-	subRound(C, D, E, A, B, f3, K3, W[48]);
-	subRound(B, C, D, E, A, f3, K3, W[49]);
-	subRound(A, B, C, D, E, f3, K3, W[50]);
-	subRound(E, A, B, C, D, f3, K3, W[51]);
-	subRound(D, E, A, B, C, f3, K3, W[52]);
-	subRound(C, D, E, A, B, f3, K3, W[53]);
-	subRound(B, C, D, E, A, f3, K3, W[54]);
-	subRound(A, B, C, D, E, f3, K3, W[55]);
-	subRound(E, A, B, C, D, f3, K3, W[56]);
-	subRound(D, E, A, B, C, f3, K3, W[57]);
-	subRound(C, D, E, A, B, f3, K3, W[58]);
-	subRound(B, C, D, E, A, f3, K3, W[59]);
-
-	subRound(A, B, C, D, E, f4, K4, W[60]);
-	subRound(E, A, B, C, D, f4, K4, W[61]);
-	subRound(D, E, A, B, C, f4, K4, W[62]);
-	subRound(C, D, E, A, B, f4, K4, W[63]);
-	subRound(B, C, D, E, A, f4, K4, W[64]);
-	subRound(A, B, C, D, E, f4, K4, W[65]);
-	subRound(E, A, B, C, D, f4, K4, W[66]);
-	subRound(D, E, A, B, C, f4, K4, W[67]);
-	subRound(C, D, E, A, B, f4, K4, W[68]);
-	subRound(B, C, D, E, A, f4, K4, W[69]);
-	subRound(A, B, C, D, E, f4, K4, W[70]);
-	subRound(E, A, B, C, D, f4, K4, W[71]);
-	subRound(D, E, A, B, C, f4, K4, W[72]);
-	subRound(C, D, E, A, B, f4, K4, W[73]);
-	subRound(B, C, D, E, A, f4, K4, W[74]);
-	subRound(A, B, C, D, E, f4, K4, W[75]);
-	subRound(E, A, B, C, D, f4, K4, W[76]);
-	subRound(D, E, A, B, C, f4, K4, W[77]);
-	subRound(C, D, E, A, B, f4, K4, W[78]);
-	subRound(B, C, D, E, A, f4, K4, W[79]);
-#else
-#error Illegal SHA_CODE_SIZE
-#endif
 
 	/* Build message digest */
 	digest[0] += A;
@@ -923,7 +779,6 @@
 #undef K2
 #undef K3
 #undef K4
-#undef subRound
 
 /*********************************************************************
  *
#12 lore raw

PATCH 12/12 random pt4: Move other tcp/ip bits to net/

In reply to Matt Mackall

Move remaining TCP bits from random.c to networking land.

include/net/tcp.h +8 -0
Index: rnd2/include/net/tcp.h
===================================================================
@@ -2056,4 +2056,12 @@
 
 	return (cwnd != 0);
 }
+
+/* from net/ipv4/random.c */
+
+extern u32 secure_tcp_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport);
+extern __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
+					__u16 sport, __u16 dport);
+extern __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
+					  __u16 sport, __u16 dport);
 #endif	/* _TCP_H */
net/ipv4/Makefile +1 -1
Index: rnd2/net/ipv4/Makefile
===================================================================
@@ -2,7 +2,7 @@
 # Makefile for the Linux TCP/IP (INET) layer.
 #
 
-obj-y     := utils.o route.o inetpeer.o protocol.o \
+obj-y     := utils.o random.o route.o inetpeer.o protocol.o \
 	     ip_input.o ip_fragment.o ip_forward.o ip_options.o \
 	     ip_output.o ip_sockglue.o \
 	     tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o tcp_minisocks.o \
drivers/char/random.c +0 -285

288 lines not on this page · raw message

include/net/ip.h +4 -0
Index: rnd2/include/net/ip.h
===================================================================
@@ -339,4 +339,8 @@
 				  void __user *newval, size_t newlen, 
 				  void **context);
 
+/* from net/ipv4/random.c */
+
+extern __u32 secure_ip_id(__u32 daddr);
+
 #endif	/* _IP_H */
net/ipv4/inetpeer.c +1 -0
Index: rnd2/net/ipv4/inetpeer.c
===================================================================
@@ -21,6 +21,7 @@
 #include <linux/mm.h>
 #include <linux/net.h>
 #include <net/inetpeer.h>
+#include <net/ip.h>
 
 /*
  *  Theory of operations.
net/ipv4/random.c new file +275 -0

275 lines not on this page · raw message

include/linux/random.h +0 -7
Index: rnd2/include/linux/random.h
===================================================================
@@ -51,13 +51,6 @@
 extern void get_random_bytes(void *buf, int nbytes);
 void generate_random_uuid(unsigned char uuid_out[16]);
 
-extern __u32 secure_ip_id(__u32 daddr);
-extern u32 secure_tcp_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport);
-extern __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
-					__u16 sport, __u16 dport);
-extern __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
-					  __u16 sport, __u16 dport);
-
 #ifndef MODULE
 extern struct file_operations random_fops, urandom_fops;
 #endif
#6 lore raw

PATCH 6/12 random pt4: Replace SHA with faster version

In reply to Matt Mackall

A replacement SHA routine that's slightly larger, but over twice as fast. It's also faster and much smaller than the cryptolib version.

             size      speed    buffer size
original:    350B      2.3us     320B
cryptolib:  5776B      1.2us      80B
this code:   466B      1.0us     320B
alternate:  2112B      1.0us      80B
lib/sha1.c +39 -52
Index: rnd/lib/sha1.c
===================================================================
@@ -1,18 +1,16 @@
 /*
- * SHA transform algorithm, taken from code written by Peter Gutmann,
- * and placed in the public domain.
+ * SHA transform algorithm, originally taken from code written by
+ * Peter Gutmann, and placed in the public domain.
  */
 
 #include <linux/kernel.h>
-#include <linux/string.h>
 #include <linux/cryptohash.h>
 
 /* The SHA f()-functions.  */
 
-#define f1(x,y,z)   (z ^ (x & (y ^ z)))		/* Rounds  0-19: x ? y : z */
-#define f2(x,y,z)   (x ^ y ^ z)			/* Rounds 20-39: XOR */
-#define f3(x,y,z)   ((x & y) + (z & (x ^ y)))	/* Rounds 40-59: majority */
-#define f4(x,y,z)   (x ^ y ^ z)			/* Rounds 60-79: XOR */
+#define f1(x,y,z)   (z ^ (x & (y ^ z)))		/* x ? y : z */
+#define f2(x,y,z)   (x ^ y ^ z)			/* XOR */
+#define f3(x,y,z)   ((x & y) + (z & (x ^ y)))	/* majority */
 
 /* The SHA Mysterious Constants */
 
@@ -26,64 +24,53 @@
  *
  * @digest: 160 bit digest to update
  * @data:   512 bits of data to hash
- * @W:      80 words of workspace
+ * @W:      80 words of workspace, caller should clear
  *
  * This function generates a SHA1 digest for a single. Be warned, it
  * does not handle padding and message digest, do not confuse it with
  * the full FIPS 180-1 digest algorithm for variable length messages.
  */
-void sha_transform(__u32 *digest, const char *data, __u32 *W)
+void sha_transform(__u32 *digest, const char *in, __u32 *W)
 {
-	__u32 A, B, C, D, E;
-	__u32 TEMP;
-	int i;
+	__u32 a, b, c, d, e, t, i;
 
-	memset(W, 0, sizeof(W));
 	for (i = 0; i < 16; i++)
-		W[i] = be32_to_cpu(((const __u32 *)data)[i]);
-	/*
-	 * Do the preliminary expansion of 16 to 80 words.  Doing it
-	 * out-of-line line this is faster than doing it in-line on
-	 * register-starved machines like the x86, and not really any
-	 * slower on real processors.
-	 */
-	for (i = 0; i < 64; i++) {
-		TEMP = W[i] ^ W[i+2] ^ W[i+8] ^ W[i+13];
-		W[i+16] = rol32(TEMP, 1);
+		W[i] = be32_to_cpu(((const __u32 *)in)[i]);
+
+	for (i = 0; i < 64; i++)
+		W[i+16] = rol32(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i], 1);
+
+	a = digest[0];
+	b = digest[1];
+	c = digest[2];
+	d = digest[3];
+	e = digest[4];
+
+	for (i = 0; i < 20; i++) {
+		t = f1(b, c, d) + K1 + rol32(a, 5) + e + W[i];
+		e = d; d = c; c = rol32(b, 30); b = a; a = t;
 	}
 
-	/* Set up first buffer and local data buffer */
-	A = digest[ 0 ];
-	B = digest[ 1 ];
-	C = digest[ 2 ];
-	D = digest[ 3 ];
-	E = digest[ 4 ];
-
-	/* Heavy mangling, in 4 sub-rounds of 20 iterations each. */
-	for (i = 0; i < 80; i++) {
-		if (i < 40) {
-			if (i < 20)
-				TEMP = f1(B, C, D) + K1;
-			else
-				TEMP = f2(B, C, D) + K2;
-		} else {
-			if (i < 60)
-				TEMP = f3(B, C, D) + K3;
-			else
-				TEMP = f4(B, C, D) + K4;
-		}
-		TEMP += rol32(A, 5) + E + W[i];
-		E = D; D = C; C = rol32(B, 30); B = A; A = TEMP;
+	for (; i < 40; i ++) {
+		t = f2(b, c, d) + K2 + rol32(a, 5) + e + W[i];
+		e = d; d = c; c = rol32(b, 30); b = a; a = t;
 	}
 
-	/* Build message digest */
-	digest[0] += A;
-	digest[1] += B;
-	digest[2] += C;
-	digest[3] += D;
-	digest[4] += E;
+	for (; i < 60; i ++) {
+		t = f3(b, c, d) + K3 + rol32(a, 5) + e + W[i];
+		e = d; d = c; c = rol32(b, 30); b = a; a = t;
+	}
+
+	for (; i < 80; i ++) {
+		t = f2(b, c, d) + K4 + rol32(a, 5) + e + W[i];
+		e = d; d = c; c = rol32(b, 30); b = a; a = t;
+	}
 
-	/* W is wiped by the caller */
+	digest[0] += a;
+	digest[1] += b;
+	digest[2] += c;
+	digest[3] += d;
+	digest[4] += e;
 }
 
 /*
#8 lore raw

PATCH 8/12 random pt4: Move halfmd4 to lib

In reply to Matt Mackall

Move half-MD4 hash to /lib where we can share it with htree.

drivers/char/random.c +3 -44
Index: rnd2/drivers/char/random.c
===================================================================
@@ -1325,47 +1325,6 @@
 #define K2 013240474631UL
 #define K3 015666365641UL
 
-/*
- * Basic cut-down MD4 transform.  Returns only 32 bits of result.
- */
-static __u32 halfMD4Transform (__u32 const buf[4], __u32 const in[8])
-{
-	__u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
-
-	/* Round 1 */
-	ROUND(F, a, b, c, d, in[0] + K1,  3);
-	ROUND(F, d, a, b, c, in[1] + K1,  7);
-	ROUND(F, c, d, a, b, in[2] + K1, 11);
-	ROUND(F, b, c, d, a, in[3] + K1, 19);
-	ROUND(F, a, b, c, d, in[4] + K1,  3);
-	ROUND(F, d, a, b, c, in[5] + K1,  7);
-	ROUND(F, c, d, a, b, in[6] + K1, 11);
-	ROUND(F, b, c, d, a, in[7] + K1, 19);
-
-	/* Round 2 */
-	ROUND(G, a, b, c, d, in[1] + K2,  3);
-	ROUND(G, d, a, b, c, in[3] + K2,  5);
-	ROUND(G, c, d, a, b, in[5] + K2,  9);
-	ROUND(G, b, c, d, a, in[7] + K2, 13);
-	ROUND(G, a, b, c, d, in[0] + K2,  3);
-	ROUND(G, d, a, b, c, in[2] + K2,  5);
-	ROUND(G, c, d, a, b, in[4] + K2,  9);
-	ROUND(G, b, c, d, a, in[6] + K2, 13);
-
-	/* Round 3 */
-	ROUND(H, a, b, c, d, in[3] + K3,  3);
-	ROUND(H, d, a, b, c, in[7] + K3,  9);
-	ROUND(H, c, d, a, b, in[2] + K3, 11);
-	ROUND(H, b, c, d, a, in[6] + K3, 15);
-	ROUND(H, a, b, c, d, in[1] + K3,  3);
-	ROUND(H, d, a, b, c, in[5] + K3,  9);
-	ROUND(H, c, d, a, b, in[0] + K3, 11);
-	ROUND(H, b, c, d, a, in[4] + K3, 15);
-
-	return buf[1] + b;	/* "most hashed" word */
-	/* Alternative: return sum of all words? */
-}
-
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 
 static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12])
@@ -1550,7 +1509,7 @@
 	hash[2]=(sport << 16) + dport;
 	hash[3]=keyptr->secret[11];
 
-	seq = halfMD4Transform(hash, keyptr->secret) & HASH_MASK;
+	seq = half_md4_transform(hash, keyptr->secret) & HASH_MASK;
 	seq += keyptr->count;
 	/*
 	 *	As close as possible to RFC 793, which
@@ -1591,7 +1550,7 @@
 	hash[2] = keyptr->secret[10];
 	hash[3] = keyptr->secret[11];
 
-	return halfMD4Transform(hash, keyptr->secret);
+	return half_md4_transform(hash, keyptr->secret);
 }
 
 /* Generate secure starting point for ephemeral TCP port search */
@@ -1609,7 +1568,7 @@
 	hash[2] = dport ^ keyptr->secret[10];
 	hash[3] = keyptr->secret[11];
 
-	return halfMD4Transform(hash, keyptr->secret);
+	return half_md4_transform(hash, keyptr->secret);
 }
 
 #ifdef CONFIG_SYN_COOKIES
lib/halfmd4.c new file +61 -0

61 lines not on this page · raw message

lib/Makefile +2 -1
Index: rnd2/lib/Makefile
===================================================================
@@ -5,7 +5,8 @@
 lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
 	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
 	 kobject.o kref.o idr.o div64.o parser.o int_sqrt.o \
-	 bitmap.o extable.o kobject_uevent.o prio_tree.o sha1.o
+	 bitmap.o extable.o kobject_uevent.o prio_tree.o \
+	 sha1.o halfmd4.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
include/linux/cryptohash.h +2 -0
Index: rnd2/include/linux/cryptohash.h
===================================================================
@@ -7,4 +7,6 @@
 void sha_init(__u32 *buf);
 void sha_transform(__u32 *digest, const char *data, __u32 *W);
 
+__u32 half_md4_transform(__u32 const buf[4], __u32 const in[8]);
+
 #endif
#10 lore raw

PATCH 10/12 random pt4: Simplify and shrink syncookie code

In reply to Matt Mackall

Simplify syncookie initialization
Refactor syncookie code with separate hash function

drivers/char/random.c +30 -48
Index: rnd2/drivers/char/random.c
===================================================================
@@ -366,6 +366,10 @@
  * hash; hash collisions will occur no more often than chance.
  */
 
+#ifdef CONFIG_SYN_COOKIES
+static __u32 syncookie_secret[2][16-3+SHA_WORKSPACE_WORDS];
+#endif
+
 /*
  * Static global variables
  */
@@ -897,6 +901,9 @@
 	init_std_data(&input_pool);
 	init_std_data(&blocking_pool);
 	init_std_data(&nonblocking_pool);
+#ifdef CONFIG_SYN_COOKIES
+	get_random_bytes(syncookie_secret, sizeof(syncookie_secret));
+#endif
 	return 0;
 }
 module_init(rand_initialize);
@@ -1583,23 +1590,24 @@
 #define COOKIEBITS 24	/* Upper bits store count */
 #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
 
-static int syncookie_init;
-static __u32 syncookie_secret[2][16-3+SHA_DIGEST_WORDS];
-
-__u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport,
-		__u16 dport, __u32 sseq, __u32 count, __u32 data)
+static u32 cookie_hash(u32 saddr, u32 daddr, u32 sport, u32 dport,
+		       u32 count, int c)
 {
 	__u32 tmp[16 + 5 + SHA_WORKSPACE_WORDS];
-	__u32 seq;
 
-	/*
-	 * Pick two random secrets the first time we need a cookie.
-	 */
-	if (syncookie_init == 0) {
-		get_random_bytes(syncookie_secret, sizeof(syncookie_secret));
-		syncookie_init = 1;
-	}
+	memcpy(tmp + 3, syncookie_secret[c], sizeof(syncookie_secret[c]));
+	tmp[0] = saddr;
+	tmp[1] = daddr;
+	tmp[2] = (sport << 16) + dport;
+	tmp[3] = count;
+	sha_transform(tmp + 16, tmp);
 
+	return tmp[17];
+}
+
+__u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport,
+		__u16 dport, __u32 sseq, __u32 count, __u32 data)
+{
 	/*
 	 * Compute the secure sequence number.
 	 * The output should be:
@@ -1611,22 +1619,10 @@
 	 * MSS into the second hash value.
 	 */
 
-	memcpy(tmp + 3, syncookie_secret[0], sizeof(syncookie_secret[0]));
-	tmp[0]=saddr;
-	tmp[1]=daddr;
-	tmp[2]=(sport << 16) + dport;
-	sha_transform(tmp+16, (__u8 *)tmp, tmp + 16 + 5);
-	seq = tmp[17] + sseq + (count << COOKIEBITS);
-
-	memcpy(tmp + 3, syncookie_secret[1], sizeof(syncookie_secret[1]));
-	tmp[0]=saddr;
-	tmp[1]=daddr;
-	tmp[2]=(sport << 16) + dport;
-	tmp[3] = count;	/* minute counter */
-	sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5);
-
-	/* Add in the second hash and the data */
-	return seq + ((tmp[17] + data) & COOKIEMASK);
+	return (cookie_hash(saddr, daddr, sport, dport, 0, 0) +
+		sseq + (count << COOKIEBITS) +
+		((cookie_hash(saddr, daddr, sport, dport, count, 1) + data)
+		 & COOKIEMASK));
 }
 
 /*
@@ -1641,33 +1637,19 @@
 __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, __u16 sport,
 		__u16 dport, __u32 sseq, __u32 count, __u32 maxdiff)
 {
-	__u32 tmp[16 + 5 + SHA_WORKSPACE_WORDS];
 	__u32 diff;
 
-	if (syncookie_init == 0)
-		return (__u32)-1; /* Well, duh! */
-
 	/* Strip away the layers from the cookie */
-	memcpy(tmp + 3, syncookie_secret[0], sizeof(syncookie_secret[0]));
-	tmp[0]=saddr;
-	tmp[1]=daddr;
-	tmp[2]=(sport << 16) + dport;
-	sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5);
-	cookie -= tmp[17] + sseq;
-	/* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */
+	cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq;
 
+	/* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */
 	diff = (count - (cookie >> COOKIEBITS)) & ((__u32)-1 >> COOKIEBITS);
 	if (diff >= maxdiff)
 		return (__u32)-1;
 
-	memcpy(tmp+3, syncookie_secret[1], sizeof(syncookie_secret[1]));
-	tmp[0] = saddr;
-	tmp[1] = daddr;
-	tmp[2] = (sport << 16) + dport;
-	tmp[3] = count - diff;	/* minute counter */
-	sha_transform(tmp + 16, tmp);
-
-	return (cookie - tmp[17]) & COOKIEMASK;	/* Leaving the data behind */
+	return (cookie -
+		cookie_hash(saddr, daddr, sport, dport, count - diff, 1))
+		& COOKIEMASK;	/* Leaving the data behind */
 }
 #endif
 #endif /* CONFIG_INET */
#2 lore raw

PATCH 2/12 random pt4: Use them throughout the tree

In reply to Matt Mackall

Move users of private rotl/rotr functions to rol32/ror32. Crypto bits verified with tcrypt.

crypto/michael_mic.c +3 -15
Index: rnd2/crypto/michael_mic.c
===================================================================
@@ -24,18 +24,6 @@
 };
 
 
-static inline u32 rotl(u32 val, int bits)
-{
-	return (val << bits) | (val >> (32 - bits));
-}
-
-
-static inline u32 rotr(u32 val, int bits)
-{
-	return (val >> bits) | (val << (32 - bits));
-}
-
-
 static inline u32 xswap(u32 val)
 {
 	return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8);
@@ -44,13 +32,13 @@
 
 #define michael_block(l, r)	\
 do {				\
-	r ^= rotl(l, 17);	\
+	r ^= rol32(l, 17);	\
 	l += r;			\
 	r ^= xswap(l);		\
 	l += r;			\
-	r ^= rotl(l, 3);	\
+	r ^= rol32(l, 3);	\
 	l += r;			\
-	r ^= rotr(l, 2);	\
+	r ^= ror32(l, 2);	\
 	l += r;			\
 } while (0)
 
fs/ncpfs/ncpsign_kernel.c +1 -2
Index: rnd2/fs/ncpfs/ncpsign_kernel.c
===================================================================
@@ -11,10 +11,9 @@
 
 #include <linux/string.h>
 #include <linux/ncp.h>
+#include <linux/bitops.h>
 #include "ncpsign_kernel.h"
 
-#define rol32(i,c) (((((i)&0xffffffff)<<c)&0xffffffff)| \
-                    (((i)&0xffffffff)>>(32-c)))
 /* i386: 32-bit, little endian, handles mis-alignment */
 #ifdef __i386__
 #define GET_LE32(p) (*(int *)(p))
crypto/cast5.c +3 -6
Index: rnd2/crypto/cast5.c
===================================================================
@@ -567,14 +567,11 @@
 	0xeaee6801, 0x8db2a283, 0xea8bf59e
 };
 
-
-#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) )
-
-#define F1(D,m,r)  (  (I = ((m) + (D))), (I=rol((r),I)),   \
+#define F1(D,m,r)  (  (I = ((m) + (D))), (I=rol32(I,(r))),   \
     (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) )
-#define F2(D,m,r)  (  (I = ((m) ^ (D))), (I=rol((r),I)),   \
+#define F2(D,m,r)  (  (I = ((m) ^ (D))), (I=rol32(I,(r))),   \
     (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) )
-#define F3(D,m,r)  (  (I = ((m) - (D))), (I=rol((r),I)),   \
+#define F3(D,m,r)  (  (I = ((m) - (D))), (I=rol32(I,(r))),   \
     (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) )
 
 
crypto/aes.c +18 -35

104 lines not on this page · raw message

crypto/cast6.c +3 -5
Index: rnd2/crypto/cast6.c
===================================================================
@@ -33,13 +33,11 @@
 	u8 Kr[12][4];
 };
 
-#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) )
-
-#define F1(D,r,m)  (  (I = ((m) + (D))), (I=rol((r),I)),   \
+#define F1(D,r,m)  (  (I = ((m) + (D))), (I=rol32(I,(r))),   \
     (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) )
-#define F2(D,r,m)  (  (I = ((m) ^ (D))), (I=rol((r),I)),   \
+#define F2(D,r,m)  (  (I = ((m) ^ (D))), (I=rol32(I,(r))),   \
     (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) )
-#define F3(D,r,m)  (  (I = ((m) - (D))), (I=rol((r),I)),   \
+#define F3(D,r,m)  (  (I = ((m) - (D))), (I=rol32(I,(r))),   \
     (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) )
 
 static const u32 s1[256] = {
fs/xfs/xfs_da_btree.c +9 -11
Index: rnd2/fs/xfs/xfs_da_btree.c
===================================================================
@@ -1627,40 +1627,38 @@
 {
 	xfs_dahash_t hash;
 
-#define	ROTL(x,y)	(((x) << (y)) | ((x) >> (32 - (y))))
 #ifdef SLOWVERSION
 	/*
 	 * This is the old one-byte-at-a-time version.
 	 */
-	for (hash = 0; namelen > 0; namelen--) {
-		hash = *name++ ^ ROTL(hash, 7);
-	}
+	for (hash = 0; namelen > 0; namelen--)
+		hash = *name++ ^ rol32(hash, 7);
+
 	return(hash);
 #else
 	/*
 	 * Do four characters at a time as long as we can.
 	 */
-	for (hash = 0; namelen >= 4; namelen -= 4, name += 4) {
+	for (hash = 0; namelen >= 4; namelen -= 4, name += 4)
 		hash = (name[0] << 21) ^ (name[1] << 14) ^ (name[2] << 7) ^
-		       (name[3] << 0) ^ ROTL(hash, 7 * 4);
-	}
+		       (name[3] << 0) ^ rol32(hash, 7 * 4);
+
 	/*
 	 * Now do the rest of the characters.
 	 */
 	switch (namelen) {
 	case 3:
 		return (name[0] << 14) ^ (name[1] << 7) ^ (name[2] << 0) ^
-		       ROTL(hash, 7 * 3);
+		       rol32(hash, 7 * 3);
 	case 2:
-		return (name[0] << 7) ^ (name[1] << 0) ^ ROTL(hash, 7 * 2);
+		return (name[0] << 7) ^ (name[1] << 0) ^ rol32(hash, 7 * 2);
 	case 1:
-		return (name[0] << 0) ^ ROTL(hash, 7 * 1);
+		return (name[0] << 0) ^ rol32(hash, 7 * 1);
 	case 0:
 		return hash;
 	}
 	/* NOTREACHED */
 #endif
-#undef ROTL
 	return 0; /* keep gcc happy */
 }
 
crypto/serpent.c +11 -13
Index: rnd2/crypto/serpent.c
===================================================================
@@ -31,11 +31,9 @@
 #define SERPENT_BLOCK_SIZE		 16
 
 #define PHI 0x9e3779b9UL
-#define ROL(x,r) ((x) = ((x) << (r)) | ((x) >> (32-(r))))
-#define ROR(x,r) ((x) = ((x) >> (r)) | ((x) << (32-(r))))
 
 #define keyiter(a,b,c,d,i,j) \
-        b ^= d; b ^= c; b ^= a; b ^= PHI ^ i; ROL(b,11); k[j] = b;
+        b ^= d; b ^= c; b ^= a; b ^= PHI ^ i; b = rol32(b,11); k[j] = b;
 
 #define loadkeys(x0,x1,x2,x3,i) \
 	x0=k[i]; x1=k[i+1]; x2=k[i+2]; x3=k[i+3];
@@ -48,24 +46,24 @@
 	x1 ^= k[4*(i)+1];        x0 ^= k[4*(i)+0];
 
 #define LK(x0,x1,x2,x3,x4,i)				\
-					ROL(x0,13);	\
-	ROL(x2,3);	x1 ^= x0;	x4  = x0 << 3;	\
+					x0=rol32(x0,13);\
+	x2=rol32(x2,3);	x1 ^= x0;	x4  = x0 << 3;	\
 	x3 ^= x2;	x1 ^= x2;			\
-	ROL(x1,1);	x3 ^= x4;			\
-	ROL(x3,7);	x4  = x1;			\
+	x1=rol32(x1,1);	x3 ^= x4;			\
+	x3=rol32(x3,7);	x4  = x1;			\
 	x0 ^= x1;	x4 <<= 7;	x2 ^= x3;	\
 	x0 ^= x3;	x2 ^= x4;	x3 ^= k[4*i+3];	\
-	x1 ^= k[4*i+1];	ROL(x0,5);	ROL(x2,22);	\
+	x1 ^= k[4*i+1];	x0=rol32(x0,5);	x2=rol32(x2,22);\
 	x0 ^= k[4*i+0];	x2 ^= k[4*i+2];
 
 #define KL(x0,x1,x2,x3,x4,i)				\
 	x0 ^= k[4*i+0];	x1 ^= k[4*i+1];	x2 ^= k[4*i+2];	\
-	x3 ^= k[4*i+3];	ROR(x0,5);	ROR(x2,22);	\
+	x3 ^= k[4*i+3];	x0=ror32(x0,5);	x2=ror32(x2,22);\
 	x4 =  x1;	x2 ^= x3;	x0 ^= x3;	\
-	x4 <<= 7;	x0 ^= x1;	ROR(x1,1);	\
-	x2 ^= x4;	ROR(x3,7);	x4 = x0 << 3;	\
-	x1 ^= x0;	x3 ^= x4;	ROR(x0,13);	\
-	x1 ^= x2;	x3 ^= x2;	ROR(x2,3);
+	x4 <<= 7;	x0 ^= x1;	x1=ror32(x1,1);	\
+	x2 ^= x4;	x3=ror32(x3,7);	x4 = x0 << 3;	\
+	x1 ^= x0;	x3 ^= x4;	x0=ror32(x0,13);\
+	x1 ^= x2;	x3 ^= x2;	x2=ror32(x2,3);
 
 #define S0(x0,x1,x2,x3,x4)				\
 					x4  = x3;	\
crypto/sha1.c +9 -14
Index: rnd2/crypto/sha1.c
===================================================================
@@ -27,27 +27,22 @@
 #define SHA1_DIGEST_SIZE	20
 #define SHA1_HMAC_BLOCK_SIZE	64
 
-static inline u32 rol(u32 value, u32 bits)
-{
-	return (((value) << (bits)) | ((value) >> (32 - (bits))));
-}
-
 /* blk0() and blk() perform the initial expand. */
 /* I got the idea of expanding during the round function from SSLeay */
 # define blk0(i) block32[i]
 
-#define blk(i) (block32[i&15] = rol(block32[(i+13)&15]^block32[(i+8)&15] \
+#define blk(i) (block32[i&15] = rol32(block32[(i+13)&15]^block32[(i+8)&15] \
     ^block32[(i+2)&15]^block32[i&15],1))
 
 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5); \
-                        w=rol(w,30);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5); \
-                        w=rol(w,30);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5); \
-                        w=rol(w,30);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol32(v,5); \
+                        w=rol32(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol32(v,5); \
+                        w=rol32(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol32(v,5);w=rol32(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol32(v,5); \
+                        w=rol32(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol32(v,5);w=rol32(w,30);
 
 struct sha1_ctx {
         u64 count;
crypto/sha256.c +4 -9
Index: rnd2/crypto/sha256.c
===================================================================
@@ -42,15 +42,10 @@
 	return (x & y) | (z & (x | y));
 }
 
-static inline u32 RORu32(u32 x, u32 y)
-{
-	return (x >> y) | (x << (32 - y));
-}
-
-#define e0(x)       (RORu32(x, 2) ^ RORu32(x,13) ^ RORu32(x,22))
-#define e1(x)       (RORu32(x, 6) ^ RORu32(x,11) ^ RORu32(x,25))
-#define s0(x)       (RORu32(x, 7) ^ RORu32(x,18) ^ (x >> 3))
-#define s1(x)       (RORu32(x,17) ^ RORu32(x,19) ^ (x >> 10))
+#define e0(x)       (ror32(x, 2) ^ ror32(x,13) ^ ror32(x,22))
+#define e1(x)       (ror32(x, 6) ^ ror32(x,11) ^ ror32(x,25))
+#define s0(x)       (ror32(x, 7) ^ ror32(x,18) ^ (x >> 3))
+#define s1(x)       (ror32(x,17) ^ ror32(x,19) ^ (x >> 10))
 
 #define H0         0x6a09e667
 #define H1         0xbb67ae85
#1 lore raw

PATCH 1/12 random pt4: Create new rol32/ror32 bitops

In reply to Matt Mackall

Add rol32 and ror32 bitops to bitops.h

drivers/char/random.c +0 -5
Index: rnd2/drivers/char/random.c
===================================================================
@@ -374,11 +374,6 @@
 static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
 static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
 
-static inline __u32 rol32(__u32 word, int shift)
-{
-	return (word << shift) | (word >> (32 - shift));
-}
-
 #if 0
 static int debug = 0;
 module_param(debug, bool, 0644);
include/linux/bitops.h +22 -0
Index: rnd2/include/linux/bitops.h
===================================================================
@@ -134,4 +134,26 @@
 	return sizeof(w) == 4 ? generic_hweight32(w) : generic_hweight64(w);
 }
 
+/*
+ * rol32 - rotate a 32-bit value left
+ *
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u32 rol32(__u32 word, int shift)
+{
+	return (word << shift) | (word >> (32 - shift));
+}
+
+/*
+ * ror32 - rotate a 32-bit value right
+ *
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u32 ror32(__u32 word, int shift)
+{
+	return (word >> shift) | (word << (32 - shift));
+}
+
 #endif
#4 lore raw

PATCH 4/12 random pt4: Cleanup SHA interface

In reply to Matt Mackall

Clean up SHA hash function for moving to lib/
Do proper endian conversion
Provide sha_init function
Add kerneldoc

drivers/char/random.c +36 -40
Index: rnd2/drivers/char/random.c
===================================================================
@@ -671,29 +671,6 @@
 
 EXPORT_SYMBOL(add_disk_randomness);
 
-/******************************************************************
- *
- * Hash function definition
- *
- *******************************************************************/
-
-/*
- * This chunk of code defines a function
- * void sha_transform(__u32 digest[HASH_BUFFER_SIZE + HASH_EXTRA_SIZE],
- * 		__u32 const data[16])
- *
- * The function hashes the input data to produce a digest in the first
- * HASH_BUFFER_SIZE words of the digest[] array, and uses HASH_EXTRA_SIZE
- * more words for internal purposes.  (This buffer is exported so the
- * caller can wipe it once rather than this code doing it each call,
- * and tacking it onto the end of the digest[] array is the quick and
- * dirty way of doing it.)
- *
- * For /dev/random purposes, the length of the data being hashed is
- * fixed in length, so appending a bit count in the usual way is not
- * cryptographically necessary.
- */
-
 #define HASH_BUFFER_SIZE 5
 #define EXTRACT_SIZE 10
 #define HASH_EXTRA_SIZE 80
@@ -717,20 +694,32 @@
 #define K3  0x8F1BBCDCL			/* Rounds 40-59: sqrt(5) * 2^30 */
 #define K4  0xCA62C1D6L			/* Rounds 60-79: sqrt(10) * 2^30 */
 
-static void sha_transform(__u32 digest[85], __u32 const data[16])
+/*
+ * sha_transform: single block SHA1 transform
+ *
+ * @digest: 160 bit digest to update
+ * @data:   512 bytes of data to hash
+ * @W:      80 words of workspace
+ *
+ * This function generates a SHA1 digest for a single. Be warned, it
+ * does not handle padding and message digest, do not confuse it with
+ * the full FIPS 180-1 digest algorithm for variable length messages.
+ */
+static void sha_transform(__u32 digest[5], const char *data, __u32 W[80])
 {
-	__u32 A, B, C, D, E;     /* Local vars */
+	__u32 A, B, C, D, E;
 	__u32 TEMP;
 	int i;
-#define W (digest + HASH_BUFFER_SIZE)	/* Expanded data array */
 
+	memset(W, 0, sizeof(W));
+	for (i = 0; i < 16; i++)
+		W[i] = be32_to_cpu(((const __u32 *)data)[i]);
 	/*
 	 * Do the preliminary expansion of 16 to 80 words.  Doing it
 	 * out-of-line line this is faster than doing it in-line on
 	 * register-starved machines like the x86, and not really any
 	 * slower on real processors.
 	 */
-	memcpy(W, data, 16*sizeof(__u32));
 	for (i = 0; i < 64; i++) {
 		TEMP = W[i] ^ W[i+2] ^ W[i+8] ^ W[i+13];
 		W[i+16] = rol32(TEMP, 1);
@@ -768,7 +757,6 @@
 	digest[4] += E;
 
 	/* W is wiped by the caller */
-#undef W
 }
 
 #undef f1
@@ -780,6 +768,20 @@
 #undef K3
 #undef K4
 
+/*
+ * sha_init: initialize the vectors for a SHA1 digest
+ *
+ * @buf: vector to initialize
+ */
+static void sha_init(__u32 *buf)
+{
+	buf[0] = 0x67452301;
+	buf[1] = 0xefcdab89;
+	buf[2] = 0x98badcfe;
+	buf[3] = 0x10325476;
+	buf[4] = 0xc3d2e1f0;
+}
+
 /*********************************************************************
  *
  * Entropy extraction routines
@@ -870,13 +872,7 @@
 	int i, x;
 	__u32 data[16], buf[85];
 
-	/* Hash the pool to get the output */
-	buf[0] = 0x67452301;
-	buf[1] = 0xefcdab89;
-	buf[2] = 0x98badcfe;
-	buf[3] = 0x10325476;
-	buf[4] = 0xc3d2e1f0;
-
+	sha_init(buf);
 	/*
 	 * As we hash the pool, we mix intermediate values of
 	 * the hash back into the pool.  This eliminates
@@ -886,7 +882,7 @@
 	 * function can be inverted.
 	 */
 	for (i = 0, x = 0; i < r->poolinfo->poolwords; i += 16, x+=2) {
-		sha_transform(buf, r->pool+i);
+		sha_transform(buf, (__u8 *)r->pool+i, buf + 5);
 		add_entropy_words(r, &buf[x % 5], 1);
 	}
 
@@ -896,7 +892,7 @@
 	 * final time.
 	 */
 	__add_entropy_words(r, &buf[x % 5], 1, data);
-	sha_transform(buf, data);
+	sha_transform(buf, (__u8 *)data, buf + 5);
 
 	/*
 	 * In case the hash function has some recognizable
@@ -1771,7 +1767,7 @@
 	tmp[0]=saddr;
 	tmp[1]=daddr;
 	tmp[2]=(sport << 16) + dport;
-	sha_transform(tmp+16, tmp);
+	sha_transform(tmp+16, (__u8 *)tmp, tmp + 16 + 5);
 	seq = tmp[17] + sseq + (count << COOKIEBITS);
 
 	memcpy(tmp + 3, syncookie_secret[1], sizeof(syncookie_secret[1]));
@@ -1779,7 +1775,7 @@
 	tmp[1]=daddr;
 	tmp[2]=(sport << 16) + dport;
 	tmp[3] = count;	/* minute counter */
-	sha_transform(tmp + 16, tmp);
+	sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5);
 
 	/* Add in the second hash and the data */
 	return seq + ((tmp[17] + data) & COOKIEMASK);
@@ -1808,7 +1804,7 @@
 	tmp[0]=saddr;
 	tmp[1]=daddr;
 	tmp[2]=(sport << 16) + dport;
-	sha_transform(tmp + 16, tmp);
+	sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5);
 	cookie -= tmp[17] + sseq;
 	/* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */
 
#9 lore raw

PATCH 9/12 random pt4: Kill duplicate halfmd4 in ext3 htree

In reply to Matt Mackall

Replace duplicate halfMD4 code with call to lib/

fs/ext3/hash.c +2 -68
Index: rnd/fs/ext3/hash.c
===================================================================
@@ -13,6 +13,7 @@
 #include <linux/jbd.h>
 #include <linux/sched.h>
 #include <linux/ext3_fs.h>
+#include <linux/cryptohash.h>
 
 #define DELTA 0x9E3779B9
 
@@ -33,73 +34,6 @@
 	buf[1] += b1;
 }
 
-/* F, G and H are basic MD4 functions: selection, majority, parity */
-#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-
-/*
- * The generic round function.  The application is so specific that
- * we don't bother protecting all the arguments with parens, as is generally
- * good macro practice, in favor of extra legibility.
- * Rotation is separate from addition to prevent recomputation
- */
-#define ROUND(f, a, b, c, d, x, s)	\
-	(a += f(b, c, d) + x, a = (a << s) | (a >> (32-s)))
-#define K1 0
-#define K2 013240474631UL
-#define K3 015666365641UL
-
-/*
- * Basic cut-down MD4 transform.  Returns only 32 bits of result.
- */
-static void halfMD4Transform (__u32 buf[4], __u32 const in[])
-{
-	__u32	a = buf[0], b = buf[1], c = buf[2], d = buf[3];
-
-	/* Round 1 */
-	ROUND(F, a, b, c, d, in[0] + K1,  3);
-	ROUND(F, d, a, b, c, in[1] + K1,  7);
-	ROUND(F, c, d, a, b, in[2] + K1, 11);
-	ROUND(F, b, c, d, a, in[3] + K1, 19);
-	ROUND(F, a, b, c, d, in[4] + K1,  3);
-	ROUND(F, d, a, b, c, in[5] + K1,  7);
-	ROUND(F, c, d, a, b, in[6] + K1, 11);
-	ROUND(F, b, c, d, a, in[7] + K1, 19);
-
-	/* Round 2 */
-	ROUND(G, a, b, c, d, in[1] + K2,  3);
-	ROUND(G, d, a, b, c, in[3] + K2,  5);
-	ROUND(G, c, d, a, b, in[5] + K2,  9);
-	ROUND(G, b, c, d, a, in[7] + K2, 13);
-	ROUND(G, a, b, c, d, in[0] + K2,  3);
-	ROUND(G, d, a, b, c, in[2] + K2,  5);
-	ROUND(G, c, d, a, b, in[4] + K2,  9);
-	ROUND(G, b, c, d, a, in[6] + K2, 13);
-
-	/* Round 3 */
-	ROUND(H, a, b, c, d, in[3] + K3,  3);
-	ROUND(H, d, a, b, c, in[7] + K3,  9);
-	ROUND(H, c, d, a, b, in[2] + K3, 11);
-	ROUND(H, b, c, d, a, in[6] + K3, 15);
-	ROUND(H, a, b, c, d, in[1] + K3,  3);
-	ROUND(H, d, a, b, c, in[5] + K3,  9);
-	ROUND(H, c, d, a, b, in[0] + K3, 11);
-	ROUND(H, b, c, d, a, in[4] + K3, 15);
-
-	buf[0] += a;
-	buf[1] += b;
-	buf[2] += c;
-	buf[3] += d;
-}
-
-#undef ROUND
-#undef F
-#undef G
-#undef H
-#undef K1
-#undef K2
-#undef K3
 
 /* The old legacy hash */
 static __u32 dx_hack_hash (const char *name, int len)
@@ -187,7 +121,7 @@
 		p = name;
 		while (len > 0) {
 			str2hashbuf(p, len, in, 8);
-			halfMD4Transform(buf, in);
+			half_md4_transform(buf, in);
 			len -= 32;
 			p += 32;
 		}
include/linux/cryptohash.h +1 -1
Index: rnd/include/linux/cryptohash.h
===================================================================
@@ -7,6 +7,6 @@
 void sha_init(__u32 *buf);
 void sha_transform(__u32 *digest, const char *data, __u32 *W);
 
-__u32 half_md4_transform(__u32 const buf[4], __u32 const in[8]);
+__u32 half_md4_transform(__u32 buf[4], __u32 const in[8]);
 
 #endif
lib/halfmd4.c +7 -3
Index: rnd/lib/halfmd4.c
===================================================================
@@ -21,7 +21,7 @@
 /*
  * Basic cut-down MD4 transform.  Returns only 32 bits of result.
  */
-__u32 half_md4_transform(__u32 const buf[4], __u32 const in[8])
+__u32 half_md4_transform(__u32 buf[4], __u32 const in[8])
 {
 	__u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
 
@@ -55,7 +55,11 @@
 	ROUND(H, c, d, a, b, in[0] + K3, 11);
 	ROUND(H, b, c, d, a, in[4] + K3, 15);
 
-	return buf[1] + b;	/* "most hashed" word */
-	/* Alternative: return sum of all words? */
+	buf[0] += a;
+	buf[1] += b;
+	buf[2] += c;
+	buf[3] += d;
+
+	return buf[1]; /* "most hashed" word */
 }
 
#21 lore raw

Re: [PATCH 4/12] random pt4: Cleanup SHA interface

In reply to Matt Mackall
Quoted 56 lines · Matt Mackall

Clean up SHA hash function for moving to lib/
Do proper endian conversion
Provide sha_init function
Add kerneldoc

Index: rnd2/drivers/char/random.c
===================================================================

drivers/char/random.c +10 -24
@@ -671,29 +671,6 @@
 
 EXPORT_SYMBOL(add_disk_randomness);
 
-/******************************************************************
- *
- * Hash function definition
- *
- *******************************************************************/
-
-/*
- * This chunk of code defines a function
- * void sha_transform(__u32 digest[HASH_BUFFER_SIZE + HASH_EXTRA_SIZE],
- * 		__u32 const data[16])
- *
- * The function hashes the input data to produce a digest in the first
- * HASH_BUFFER_SIZE words of the digest[] array, and uses HASH_EXTRA_SIZE
- * more words for internal purposes.  (This buffer is exported so the
- * caller can wipe it once rather than this code doing it each call,
- * and tacking it onto the end of the digest[] array is the quick and
- * dirty way of doing it.)
- *
- * For /dev/random purposes, the length of the data being hashed is
- * fixed in length, so appending a bit count in the usual way is not
- * cryptographically necessary.
- */
-
 #define HASH_BUFFER_SIZE 5
 #define EXTRACT_SIZE 10
 #define HASH_EXTRA_SIZE 80
@@ -717,20 +694,32 @@
 #define K3  0x8F1BBCDCL			/* Rounds 40-59: sqrt(5) * 2^30 */
 #define K4  0xCA62C1D6L			/* Rounds 60-79: sqrt(10) * 2^30 */
 
-static void sha_transform(__u32 digest[85], __u32 const data[16])
+/*
+ * sha_transform: single block SHA1 transform
+ *
+ * @digest: 160 bit digest to update
+ * @data:   512 bytes of data to hash
+ * @W:      80 words of workspace
+ *
+ * This function generates a SHA1 digest for a single. Be warned, it
+ * does not handle padding and message digest, do not confuse it with
+ * the full FIPS 180-1 digest algorithm for variable length messages.

drivers/char/random.c line 714

Quoted 10 lines
drivers/char/random.c +4 -2
+ */
+static void sha_transform(__u32 digest[5], const char *data, __u32 W[80])
 {
-	__u32 A, B, C, D, E;     /* Local vars */
+	__u32 A, B, C, D, E;
 	__u32 TEMP;
 	int i;
-#define W (digest + HASH_BUFFER_SIZE)	/* Expanded data array */
 
+	memset(W, 0, sizeof(W));

Hmm..... Parameter decays into pointer, sizeof(W) != 80*4. See:

# cat tt.c
#include <stdio.h>
void f(char w[80]) {
    printf("%d\n", sizeof(w));
}
int main() {
    f(0);
    return 0;
}
# gcc tt.c; ./a.out
4
# gcc --version
gcc (GCC) 3.4.3

In light of this, if your sha1 passed regression tests, I conclude that we don't need that memset at all.

Quoted 108 lines
drivers/char/random.c +22 -15
+	for (i = 0; i < 16; i++)
+		W[i] = be32_to_cpu(((const __u32 *)data)[i]);
 	/*
 	 * Do the preliminary expansion of 16 to 80 words.  Doing it
 	 * out-of-line line this is faster than doing it in-line on
 	 * register-starved machines like the x86, and not really any
 	 * slower on real processors.
 	 */
-	memcpy(W, data, 16*sizeof(__u32));
 	for (i = 0; i < 64; i++) {
 		TEMP = W[i] ^ W[i+2] ^ W[i+8] ^ W[i+13];
 		W[i+16] = rol32(TEMP, 1);
@@ -768,7 +757,6 @@
 	digest[4] += E;
 
 	/* W is wiped by the caller */
-#undef W
 }
 
 #undef f1
@@ -780,6 +768,20 @@
 #undef K3
 #undef K4
 
+/*
+ * sha_init: initialize the vectors for a SHA1 digest
+ *
+ * @buf: vector to initialize
+ */
+static void sha_init(__u32 *buf)
+{
+	buf[0] = 0x67452301;
+	buf[1] = 0xefcdab89;
+	buf[2] = 0x98badcfe;
+	buf[3] = 0x10325476;
+	buf[4] = 0xc3d2e1f0;
+}
+
 /*********************************************************************
  *
  * Entropy extraction routines
@@ -870,13 +872,7 @@
 	int i, x;
 	__u32 data[16], buf[85];
 
-	/* Hash the pool to get the output */
-	buf[0] = 0x67452301;
-	buf[1] = 0xefcdab89;
-	buf[2] = 0x98badcfe;
-	buf[3] = 0x10325476;
-	buf[4] = 0xc3d2e1f0;
-
+	sha_init(buf);
 	/*
 	 * As we hash the pool, we mix intermediate values of
 	 * the hash back into the pool.  This eliminates
@@ -886,7 +882,7 @@
 	 * function can be inverted.
 	 */
 	for (i = 0, x = 0; i < r->poolinfo->poolwords; i += 16, x+=2) {
-		sha_transform(buf, r->pool+i);
+		sha_transform(buf, (__u8 *)r->pool+i, buf + 5);
 		add_entropy_words(r, &buf[x % 5], 1);
 	}
 
@@ -896,7 +892,7 @@
 	 * final time.
 	 */
 	__add_entropy_words(r, &buf[x % 5], 1, data);
-	sha_transform(buf, data);
+	sha_transform(buf, (__u8 *)data, buf + 5);
 
 	/*
 	 * In case the hash function has some recognizable
@@ -1771,7 +1767,7 @@
 	tmp[0]=saddr;
 	tmp[1]=daddr;
 	tmp[2]=(sport << 16) + dport;
-	sha_transform(tmp+16, tmp);
+	sha_transform(tmp+16, (__u8 *)tmp, tmp + 16 + 5);
 	seq = tmp[17] + sseq + (count << COOKIEBITS);
 
 	memcpy(tmp + 3, syncookie_secret[1], sizeof(syncookie_secret[1]));
@@ -1779,7 +1775,7 @@
 	tmp[1]=daddr;
 	tmp[2]=(sport << 16) + dport;
 	tmp[3] = count;	/* minute counter */
-	sha_transform(tmp + 16, tmp);
+	sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5);
 
 	/* Add in the second hash and the data */
 	return seq + ((tmp[17] + data) & COOKIEMASK);
@@ -1808,7 +1804,7 @@
 	tmp[0]=saddr;
 	tmp[1]=daddr;
 	tmp[2]=(sport << 16) + dport;
-	sha_transform(tmp + 16, tmp);
+	sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5);
 	cookie -= tmp[17] + sseq;
 	/* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */
 
-

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

#22 lore raw

Re: [PATCH 4/12] random pt4: Cleanup SHA interface

Quoted 9 lines · Denis Vlasenko
Quoted 8 lines · Matt Mackall
drivers/char/random.c +2 -2
+static void sha_transform(__u32 digest[5], const char *data, __u32 W[80])
 {
-	__u32 A, B, C, D, E;     /* Local vars */
+	__u32 A, B, C, D, E;
 	__u32 TEMP;
 	int i;
-#define W (digest + HASH_BUFFER_SIZE)	/* Expanded data array */
Quoted 3 lines

drivers/char/random.c line 714

Quoted 1 line
drivers/char/random.c +1 -0
+	memset(W, 0, sizeof(W));

Hmm..... Parameter decays into pointer, sizeof(W) != 80*4. See:

Good spotting.

Quoted 2 lines

In light of this, if your sha1 passed regression tests, I conclude that we don't need that memset at all.

Indeed, I noticed it was superfluous when I was benchmarking it. The entire function is replaced a couple patches later.

Signature · 1 line
Mathematics is the supreme nostalgia of our time.
#23 lore raw

Re: [PATCH 1/12] random pt4: Create new rol32/ror32 bitops

In reply to Matt Mackall
Quoted 19 lines · Matt Mackall
include/linux/bitops.h +13 -0
@@ -134,4 +134,26 @@
 	return sizeof(w) == 4 ? generic_hweight32(w) : generic_hweight64(w);
 }
 
+/*
+ * rol32 - rotate a 32-bit value left
+ *
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u32 rol32(__u32 word, int shift)
+{
+	return (word << shift) | (word >> (32 - shift));
+}
+
+/*
+ * ror32 - rotate a 32-bit value right

include/linux/bitops.h line 159

Quoted 10 lines
include/linux/bitops.h +9 -0
+ *
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u32 ror32(__u32 word, int shift)
+{
+	return (word >> shift) | (word << (32 - shift));
+}
+
 #endif

gcc generates surprisingly good assembly for this, I coudn't beat it for 32bit rotations. Cool!

So you are absolutely right here with not trying
to asm optimize it.

OTOH 64bit gcc rol is worse.
--
vda

#16 lore raw

Re: [PATCH 6/12] random pt4: Replace SHA with faster version

In reply to Denis Vlasenko
Quoted 5 lines · Denis Vlasenko
Quoted 2 lines · Matt Mackall

- * @W: 80 words of workspace
+ * @W: 80 words of workspace, caller should clear

Why?

Are you asking why should the caller clear or why should it be cleared at all?

For the first question, having the caller do the clear avoids redundant clears on repeated calls.

For the second question, forward security. If an attacker breaks into the box shortly after a secret is generated, he may be able to recover the secret from such state.

Signature · 1 line
Mathematics is the supreme nostalgia of our time.
#15 lore raw

Re: [PATCH 6/12] random pt4: Replace SHA with faster version

In reply to Matt Mackall
Quoted 2 lines · Matt Mackall

- * @W: 80 words of workspace
+ * @W: 80 words of workspace, caller should clear

Why?

Quoted 19 lines

*
* This function generates a SHA1 digest for a single. Be warned, it
* does not handle padding and message digest, do not confuse it with
* the full FIPS 180-1 digest algorithm for variable length messages. */

lib/sha1.c +2 -9
-void sha_transform(__u32 *digest, const char *data, __u32 *W)
+void sha_transform(__u32 *digest, const char *in, __u32 *W)
 {
-	__u32 A, B, C, D, E;
-	__u32 TEMP;
-	int i;
+	__u32 a, b, c, d, e, t, i;
 
-	memset(W, 0, sizeof(W));
 	for (i = 0; i < 16; i++)
-		W[i] = be32_to_cpu(((const __u32 *)data)[i]);
-	/*
-	 * Do the preliminary expansion of 16 to 80 words.  Doing it
-	 * out-of-line line this is faster than doing it in-line on

lib/sha1.c line 41

Quoted 10 lines
lib/sha1.c +4 -6
-	 * register-starved machines like the x86, and not really any
-	 * slower on real processors.
-	 */
-	for (i = 0; i < 64; i++) {
-		TEMP = W[i] ^ W[i+2] ^ W[i+8] ^ W[i+13];
-		W[i+16] = rol32(TEMP, 1);
+		W[i] = be32_to_cpu(((const __u32 *)in)[i]);
+
+	for (i = 0; i < 64; i++)
+		W[i+16] = rol32(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i], 1);

--
vda

#17 lore raw

Re: [PATCH 6/12] random pt4: Replace SHA with faster version

In reply to Matt Mackall
Quoted 7 lines · Matt Mackall
Quoted 5 lines · Denis Vlasenko
Quoted 2 lines · Matt Mackall

- * @W: 80 words of workspace
+ * @W: 80 words of workspace, caller should clear

Why?

Quoted 8 lines

Are you asking why should the caller clear or why should it be cleared at all?

For the first question, having the caller do the clear avoids redundant clears on repeated calls.

For the second question, forward security. If an attacker breaks into the box shortly after a secret is generated, he may be able to recover the secret from such state.

Whoops. I understood a comment as 'caller should clear prior to use' and this seems to be untrue (code overwrites entire W[80] vector without using prior contents).

Now I think that you most probably meant 'caller should clear AFTER use'. If so, comment should be amended.
--
vda

#18 lore raw

PATCH 1/1 SHA1 clarify kerneldoc

Quoted 17 lines · Denis Vlasenko
Quoted 7 lines · Matt Mackall
Quoted 5 lines · Denis Vlasenko
Quoted 2 lines · Matt Mackall

- * @W: 80 words of workspace
+ * @W: 80 words of workspace, caller should clear

Why?

Quoted 8 lines

Are you asking why should the caller clear or why should it be cleared at all?

For the first question, having the caller do the clear avoids redundant clears on repeated calls.

For the second question, forward security. If an attacker breaks into the box shortly after a secret is generated, he may be able to recover the secret from such state.

Quoted 6 lines

Whoops. I understood a comment as 'caller should clear prior to use' and this seems to be untrue (code overwrites entire W[80] vector without using prior contents).

Now I think that you most probably meant 'caller should clear AFTER use'. If so, comment should be amended.

Indeed.

lib/sha1.c +5 -1
Index: rc2mm1/lib/sha1.c
===================================================================
@@ -25,11 +25,15 @@
  *
  * @digest: 160 bit digest to update
  * @data:   512 bits of data to hash
- * @W:      80 words of workspace, caller should clear
+ * @W:      80 words of workspace (see note)
  *
  * This function generates a SHA1 digest for a single. Be warned, it
  * does not handle padding and message digest, do not confuse it with
  * the full FIPS 180-1 digest algorithm for variable length messages.
+ *
+ * Note: If the hash is security sensitive, the caller should be sure
+ * to clear the workspace. This is left to the caller to avoid
+ * unnecessary clears between chained hashing operations.
  */
 void sha_transform(__u32 *digest, const char *in, __u32 *W)
 {
Signature · 1 line
Mathematics is the supreme nostalgia of our time.
#14 lore raw

Re: [PATCH 7/12] random pt4: Update cryptolib to use SHA fro lib

Quoted 5 lines · Lee Revell
Quoted 2 lines · Matt Mackall

* Copyright (c) Alan Smithee.
* Copyright (c) Andrew McDonald <[email protected]>

Alan Smithee?

Aka anonymous contributor.

Signature · 1 line
Mathematics is the supreme nostalgia of our time.
#19 lore raw

Re: [PATCH] SHA1 clarify kerneldoc

In reply to Matt Mackall
Quoted 37 lines · Matt Mackall
Quoted 20 lines · Denis Vlasenko
Quoted 9 lines · Matt Mackall
Quoted 6 lines · Denis Vlasenko
Quoted 2 lines · Matt Mackall

- * @W: 80 words of workspace
+ * @W: 80 words of workspace, caller should clear

Why?

Quoted 8 lines

Are you asking why should the caller clear or why should it be cleared at all?

For the first question, having the caller do the clear avoids redundant clears on repeated calls.

For the second question, forward security. If an attacker breaks into the box shortly after a secret is generated, he may be able to recover the secret from such state.

Quoted 6 lines

Whoops. I understood a comment as 'caller should clear prior to use' and this seems to be untrue (code overwrites entire W[80] vector without using prior contents).

Now I think that you most probably meant 'caller should clear AFTER use'. If so, comment should be amended.

Indeed.

Index: rc2mm1/lib/sha1.c
===================================================================

lib/sha1.c line 30

Quoted 7 lines
lib/sha1.c +1 -1
@@ -25,11 +25,15 @@
  *
  * @digest: 160 bit digest to update
  * @data:   512 bits of data to hash
- * @W:      80 words of workspace, caller should clear
+ * @W:      80 words of workspace (see note)
  *
  * This function generates a SHA1 digest for a single. Be warned, it
                                                  ^^^^^^

Is this a term I don't know, "single" as a noun, or should "512 bit block" follow, as it does in crypto/sha1 from rc1-bk1 which is what I have handy?

Quoted 11 lines
lib/sha1.c +4 -0
  * does not handle padding and message digest, do not confuse it with
  * the full FIPS 180-1 digest algorithm for variable length messages.
+ *
+ * Note: If the hash is security sensitive, the caller should be sure
+ * to clear the workspace. This is left to the caller to avoid
+ * unnecessary clears between chained hashing operations.
  */
 void sha_transform(__u32 *digest, const char *in, __u32 *W)
 {
Signature · 3 lines
   -bill davidsen ([email protected])
"The secret to procrastination is to put things off until the
 last possible moment - but no longer"  -me
#20 lore raw

Re: [PATCH] SHA1 clarify kerneldoc

Quoted 6 lines · Bill Davidsen
Quoted 2 lines

*
* This function generates a SHA1 digest for a single. Be warned, it

                                                  ^^^^^^

Is this a term I don't know, "single" as a noun, or should "512 bit block" follow, as it does in crypto/sha1 from rc1-bk1 which is what I have handy?

That'll teach me to add comments.

lib/sha1.c +4 -3
Index: rc2mm1/lib/sha1.c
===================================================================
@@ -27,9 +27,10 @@
  * @data:   512 bits of data to hash
  * @W:      80 words of workspace (see note)
  *
- * This function generates a SHA1 digest for a single. Be warned, it
- * does not handle padding and message digest, do not confuse it with
- * the full FIPS 180-1 digest algorithm for variable length messages.
+ * This function generates a SHA1 digest for a single 512-bit block.
+ * Be warned, it does not handle padding and message digest, do not
+ * confuse it with the full FIPS 180-1 digest algorithm for variable
+ * length messages.
  *
  * Note: If the hash is security sensitive, the caller should be sure
  * to clear the workspace. This is left to the caller to avoid
Signature · 1 line
Mathematics is the supreme nostalgia of our time.