|
1 # |
|
2 # Replace arc4random* calls with FIPS compliant implementation in FIPS mode. |
|
3 # |
|
4 # Once libc:arc4random* are FIPS compliant (20816957), this patch will be |
|
5 # dropped. |
|
6 # |
|
7 # This is a temporary patch and is not intented for upstream contribution. |
|
8 # |
|
9 diff -pur old/misc.c new/misc.c |
|
10 --- old/misc.c |
|
11 +++ new/misc.c |
|
12 @@ -1164,3 +1164,87 @@ sock_set_v6only(int s) |
|
13 error("setsockopt IPV6_V6ONLY: %s", strerror(errno)); |
|
14 #endif |
|
15 } |
|
16 + |
|
17 +#ifdef ENABLE_OPENSSL_FIPS |
|
18 +/* cancel arc4random* -> fips_arc4random* defines from misc.h */ |
|
19 +#undef arc4random |
|
20 +#undef arc4random_buf |
|
21 +#undef arc4random_stir |
|
22 +#undef arc4random_uniform |
|
23 + |
|
24 +/* FIPS compliant alternative for arc4random */ |
|
25 +static uint32_t |
|
26 +fips_arc4random_impl() |
|
27 +{ |
|
28 + unsigned int r = 0; |
|
29 + |
|
30 + if (RAND_bytes((unsigned char *)&r, sizeof (r)) <= 0) { |
|
31 + fatal("RAND_bytes() failed. Aborting the process"); |
|
32 + } |
|
33 + |
|
34 + return (r); |
|
35 +} |
|
36 + |
|
37 +uint32_t |
|
38 +fips_arc4random() |
|
39 +{ |
|
40 + if (!ssh_FIPS_mode()) |
|
41 + return arc4random(); |
|
42 + else |
|
43 + return fips_arc4random_impl(); |
|
44 +} |
|
45 + |
|
46 +/* implementation taken from openbsd-compat/arc4random.c */ |
|
47 +void |
|
48 +fips_arc4random_buf(void *_buf, size_t n) |
|
49 +{ |
|
50 + size_t i; |
|
51 + uint32_t r = 0; |
|
52 + char *buf = (char *)_buf; |
|
53 + |
|
54 + if (!ssh_FIPS_mode()) |
|
55 + return arc4random_buf(_buf, n); |
|
56 + |
|
57 + for (i = 0; i < n; i++) { |
|
58 + if (i % 4 == 0) |
|
59 + r = fips_arc4random_impl(); |
|
60 + buf[i] = r & 0xff; |
|
61 + r >>= 8; |
|
62 + } |
|
63 + explicit_bzero(&r, sizeof(r)); |
|
64 +} |
|
65 + |
|
66 +void |
|
67 +fips_arc4random_stir(void) |
|
68 +{ |
|
69 + if (!ssh_FIPS_mode()) |
|
70 + return arc4random_stir(); |
|
71 +} |
|
72 + |
|
73 +/* implementation taken from openbsd-compat/arc4random.c */ |
|
74 +uint32_t |
|
75 +fips_arc4random_uniform(uint32_t upper_bound) |
|
76 +{ |
|
77 + uint32_t r, min; |
|
78 + |
|
79 + if (upper_bound < 2) |
|
80 + return 0; |
|
81 + |
|
82 + /* 2**32 % x == (2**32 - x) % x */ |
|
83 + min = -upper_bound % upper_bound; |
|
84 + |
|
85 + /* |
|
86 + * This could theoretically loop forever but each retry has |
|
87 + * p > 0.5 (worst case, usually far better) of selecting a |
|
88 + * number inside the range we need, so it should rarely need |
|
89 + * to re-roll. |
|
90 + */ |
|
91 + for (;;) { |
|
92 + r = fips_arc4random_impl(); |
|
93 + if (r >= min) |
|
94 + break; |
|
95 + } |
|
96 + |
|
97 + return r % upper_bound; |
|
98 +} |
|
99 +#endif /* ENABLE_OPENSSL_FIPS */ |
|
100 diff -pur old/misc.h new/misc.h |
|
101 --- old/misc.h |
|
102 +++ new/misc.h |
|
103 @@ -140,4 +140,16 @@ char *read_passphrase(const char *, int) |
|
104 int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2))); |
|
105 int read_keyfile_line(FILE *, const char *, char *, size_t, u_long *); |
|
106 |
|
107 +#ifdef ENABLE_OPENSSL_FIPS |
|
108 +/* arc4random* FIPS alternatives */ |
|
109 +uint32_t fips_arc4random(void); |
|
110 +void fips_arc4random_buf(void *, size_t); |
|
111 +void fips_arc4random_stir(void); |
|
112 +uint32_t fips_arc4random_uniform(uint32_t upper_bound); |
|
113 +#define arc4random fips_arc4random |
|
114 +#define arc4random_buf fips_arc4random_buf |
|
115 +#define arc4random_stir fips_arc4random_stir |
|
116 +#define arc4random_uniform fips_arc4random_uniform |
|
117 +#endif /* ENABLE_OPENSSL_FIPS */ |
|
118 + |
|
119 #endif /* _MISC_H */ |