[PATCH] Avoid randomness-related udev-induced boot stalls

Michael Shigorin mike at altlinux.org
Sun Nov 8 19:32:53 MSK 2020


Those responsible for breaking udevd even further don't
answer the question: why break what used to work before
"improvements"?

There are many architectures out there, and even those
on x86 aren't really doomed to just trust Intel's hwrng.

No reason to toss haveged here as we need a "show starter"
here, not a service.

So fill the 1024 byte long kernel enthropy pool (512*2 bytes,
$RANDOM is 0..2^16-1) with good enough "seed" while getrandom()
with GRND_INSECURE flag is not widely available yet (Linux 5.6+).

Implemented-by: Andrey Savchenko <bircoph at altlinux.org>
See-also: http://systemd.io/RANDOM_SEEDS
---
 data/etc/rc.d/rc.sysinit | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/data/etc/rc.d/rc.sysinit b/data/etc/rc.d/rc.sysinit
index e95a6fd..30726b8 100755
--- a/data/etc/rc.d/rc.sysinit
+++ b/data/etc/rc.d/rc.sysinit
@@ -31,3 +31,14 @@ if shell_var_is_no "$quiet"; then
 		echo "INITRAMFS: version $VERSION_ID"
 	}
 fi
+
+{
+# Initialize bash random seed using current time nanoseconds
+# to avoid possible kernel pool usage
+RANDOM=$((10#$(date "+%N") % 32768))
+for ((i=0; i<512; i++)); do
+	n=$RANDOM
+	printf "\x$(printf "%x" $((n>>8)))\x$(printf "%x" $((n%256)))"
+done > /dev/random
+unset i n
+} &
-- 
2.25.4


--J5MfuwkIyy7RmF4Q
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="md5_bin.c"

#include <stdint.h>
#include <stdio.h>
#include <string.h>

typedef uint32_t u32;
typedef uint64_t u64;

#define F1(x, y, z)	(z ^ (x & (y ^ z)))
#define F2(x, y, z)	F1(z, x, y)
#define F3(x, y, z)	(x ^ y ^ z)
#define F4(x, y, z)	(y ^ (x | ~z))
#define MD5STEP(f, w, x, y, z, in, s) \
	(w += f(x, y, z) + in, w = (w<<s | w>>(32-s)) + x)

static void md5_transform(u32 *hash, u32 const *in) {
	u32 a, b, c, d;
	a = hash[0]; b = hash[1];
	c = hash[2]; d = hash[3];

	MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
	MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
	MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
	MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
	MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
	MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
	MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
	MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
	MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
	MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
	MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
	MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
	MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
	MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
	MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
	MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);

	MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
	MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
	MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
	MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
	MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
	MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
	MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
	MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
	MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
	MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
	MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
	MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
	MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
	MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
	MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
	MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);

	MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
	MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
	MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
	MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
	MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
	MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
	MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
	MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
	MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
	MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
	MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
	MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
	MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
	MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
	MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
	MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);

	MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
	MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
	MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
	MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
	MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
	MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
	MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
	MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
	MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
	MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
	MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
	MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
	MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
	MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
	MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
	MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);

	hash[0] += a; hash[1] += b;
	hash[2] += c; hash[3] += d;
}

#undef MD5STEP
#undef F4
#undef F3
#undef F2
#undef F1

struct md5_ctx {
	u32 hash[4], block[16];
	u64 byte_count;
};

static void md5_init(struct md5_ctx *ctx) {
	ctx->hash[0] = 0x67452301;
	ctx->hash[1] = 0xefcdab89;
	ctx->hash[2] = 0x98badcfe;
	ctx->hash[3] = 0x10325476;
	ctx->byte_count = 0;
}

static void md5_update(struct md5_ctx *ctx, const char *data, unsigned int len) {
	const u32 avail = 64 - (ctx->byte_count & 0x3f);

	ctx->byte_count += len;
	if (avail > len) {
		memcpy((char*)ctx->block + (64 - avail), data, len);
		return;
	}
	memcpy((char*)ctx->block + (64 - avail), data, avail);
	md5_transform(ctx->hash, ctx->block);
	data += avail; len -= avail;
	while (len >= 64) {
		memcpy(ctx->block, data, 64);
		md5_transform(ctx->hash, ctx->block);
		data += 64; len -= 64;
	}
	memcpy(ctx->block, data, len);
}

static void md5_final(struct md5_ctx *ctx, unsigned char *out) {
	const unsigned int offset = ctx->byte_count & 0x3f;
	char *p = (char*)ctx->block + offset;
	int padding = 56 - (offset + 1);

	*p++ = 0x80;
	if (padding < 0) {
		memset(p, 0, padding + 8);
		md5_transform(ctx->hash, ctx->block);
		p = (char*)ctx->block;
		padding = 56;
	}

	memset(p, 0, padding);
	ctx->block[14] = ctx->byte_count << 3;
	ctx->block[15] = ctx->byte_count >> 29;
	md5_transform(ctx->hash, ctx->block);
	memcpy(out, ctx->hash, 16);
	memset(ctx, 0, sizeof(struct md5_ctx));
}

int main() {
	int a; struct md5_ctx md5; unsigned char hash[16];
	md5_init(&md5);
	while ((a = getchar()) != EOF) { char c = a; md5_update(&md5, &c, 1); }
	md5_final(&md5, hash);
	return fwrite(hash, sizeof(hash), 1, stdout) != 1;
}


--J5MfuwkIyy7RmF4Q--


More information about the Make-initrd mailing list