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 */