components/openssh/patches/036-fipsrandom.patch
author Jan Parcel <jan.parcel@oracle.com>
Mon, 01 Feb 2016 06:53:50 -0800
changeset 5376 4615bc2f4a50
parent 5310 a06a01eef195
permissions -rw-r--r--
22631538 Patch comment incorrect/outdated for patch 039-sshd_config_5_defaults.patch

#
# Replace arc4random* calls with FIPS compliant implementation in FIPS mode.
#
# Once libc:arc4random* are FIPS compliant (20816957), this patch will be
# dropped.
#
# This is a temporary patch and is not intented for upstream contribution.
#
diff -pur old/misc.c new/misc.c
--- old/misc.c
+++ new/misc.c
@@ -1164,3 +1164,87 @@ sock_set_v6only(int s)
 		error("setsockopt IPV6_V6ONLY: %s", strerror(errno));
 #endif
 }
+
+#ifdef ENABLE_OPENSSL_FIPS
+/* cancel arc4random* -> fips_arc4random* defines from misc.h */
+#undef	arc4random
+#undef	arc4random_buf
+#undef	arc4random_stir
+#undef	arc4random_uniform
+
+/* FIPS compliant alternative for arc4random */
+static uint32_t
+fips_arc4random_impl()
+{
+	unsigned int r = 0;
+
+	if (RAND_bytes((unsigned char *)&r, sizeof (r)) <= 0) {
+		fatal("RAND_bytes() failed. Aborting the process");
+	}
+
+	return (r);
+}
+
+uint32_t
+fips_arc4random()
+{
+	if (!ssh_FIPS_mode())
+		return arc4random();
+	else
+		return fips_arc4random_impl();
+}
+
+/* implementation taken from openbsd-compat/arc4random.c */
+void
+fips_arc4random_buf(void *_buf, size_t n)
+{
+	size_t i;
+	uint32_t r = 0;
+	char *buf = (char *)_buf;
+
+	if (!ssh_FIPS_mode())
+		return arc4random_buf(_buf, n);
+
+	for (i = 0; i < n; i++) {
+		if (i % 4 == 0)
+			r = fips_arc4random_impl();
+		buf[i] = r & 0xff;
+		r >>= 8;
+	}
+	explicit_bzero(&r, sizeof(r));
+}
+
+void
+fips_arc4random_stir(void)
+{
+	if (!ssh_FIPS_mode())
+		return arc4random_stir();
+}
+
+/* implementation taken from openbsd-compat/arc4random.c */
+uint32_t
+fips_arc4random_uniform(uint32_t upper_bound)
+{
+	uint32_t r, min;
+
+	if (upper_bound < 2)
+		return 0;
+
+	/* 2**32 % x == (2**32 - x) % x */
+	min = -upper_bound % upper_bound;
+
+	/*
+	 * This could theoretically loop forever but each retry has
+	 * p > 0.5 (worst case, usually far better) of selecting a
+	 * number inside the range we need, so it should rarely need
+	 * to re-roll.
+	 */
+	for (;;) {
+		r = fips_arc4random_impl();
+		if (r >= min)
+			break;
+	}
+
+	return r % upper_bound;
+}
+#endif /* ENABLE_OPENSSL_FIPS */
diff -pur old/misc.h new/misc.h
--- old/misc.h
+++ new/misc.h
@@ -140,4 +140,16 @@ char	*read_passphrase(const char *, int)
 int	 ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
 int	 read_keyfile_line(FILE *, const char *, char *, size_t, u_long *);
 
+#ifdef ENABLE_OPENSSL_FIPS
+/* arc4random* FIPS alternatives */
+uint32_t fips_arc4random(void);
+void	 fips_arc4random_buf(void *, size_t);
+void	 fips_arc4random_stir(void);
+uint32_t fips_arc4random_uniform(uint32_t upper_bound);
+#define	arc4random fips_arc4random
+#define	arc4random_buf fips_arc4random_buf
+#define	arc4random_stir fips_arc4random_stir
+#define	arc4random_uniform fips_arc4random_uniform
+#endif /* ENABLE_OPENSSL_FIPS */
+
 #endif /* _MISC_H */