1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright 2021 Google LLC
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * This program provides commands that dump certain types of output from the
6*4882a593Smuzhiyun * fips140 kernel module, as required by the FIPS lab for evaluation purposes.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * While the fips140 kernel module can only be accessed directly by other kernel
9*4882a593Smuzhiyun * code, an easy-to-use userspace utility program was desired for lab testing.
10*4882a593Smuzhiyun * When possible, this program uses AF_ALG to access the crypto algorithms; this
11*4882a593Smuzhiyun * requires that the kernel has AF_ALG enabled. Where AF_ALG isn't sufficient,
12*4882a593Smuzhiyun * a custom device node /dev/fips140 is used instead; this requires that the
13*4882a593Smuzhiyun * fips140 module is loaded and has evaluation testing support compiled in.
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * This program can be compiled and run on an Android device as follows:
16*4882a593Smuzhiyun *
17*4882a593Smuzhiyun * NDK_DIR=$HOME/android-ndk-r23b # adjust directory path as needed
18*4882a593Smuzhiyun * $NDK_DIR/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android31-clang \
19*4882a593Smuzhiyun * fips140_lab_util.c -O2 -Wall -o fips140_lab_util
20*4882a593Smuzhiyun * adb push fips140_lab_util /data/local/tmp/
21*4882a593Smuzhiyun * adb root
22*4882a593Smuzhiyun * adb shell /data/local/tmp/fips140_lab_util
23*4882a593Smuzhiyun */
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #include <errno.h>
26*4882a593Smuzhiyun #include <fcntl.h>
27*4882a593Smuzhiyun #include <getopt.h>
28*4882a593Smuzhiyun #include <limits.h>
29*4882a593Smuzhiyun #include <linux/if_alg.h>
30*4882a593Smuzhiyun #include <stdarg.h>
31*4882a593Smuzhiyun #include <stdbool.h>
32*4882a593Smuzhiyun #include <stdint.h>
33*4882a593Smuzhiyun #include <stdio.h>
34*4882a593Smuzhiyun #include <stdlib.h>
35*4882a593Smuzhiyun #include <string.h>
36*4882a593Smuzhiyun #include <sys/ioctl.h>
37*4882a593Smuzhiyun #include <sys/socket.h>
38*4882a593Smuzhiyun #include <sys/stat.h>
39*4882a593Smuzhiyun #include <sys/sysmacros.h>
40*4882a593Smuzhiyun #include <unistd.h>
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun #include "../../crypto/fips140-eval-testing-uapi.h"
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun /* ---------------------------------------------------------------------------
45*4882a593Smuzhiyun * Utility functions
46*4882a593Smuzhiyun * ---------------------------------------------------------------------------*/
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
49*4882a593Smuzhiyun #define MIN(a, b) ((a) < (b) ? (a) : (b))
50*4882a593Smuzhiyun #define MAX(a, b) ((a) > (b) ? (a) : (b))
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun static void __attribute__((noreturn))
do_die(const char * format,va_list va,int err)53*4882a593Smuzhiyun do_die(const char *format, va_list va, int err)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun fputs("ERROR: ", stderr);
56*4882a593Smuzhiyun vfprintf(stderr, format, va);
57*4882a593Smuzhiyun if (err)
58*4882a593Smuzhiyun fprintf(stderr, ": %s", strerror(err));
59*4882a593Smuzhiyun putc('\n', stderr);
60*4882a593Smuzhiyun exit(1);
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun static void __attribute__((noreturn, format(printf, 1, 2)))
die_errno(const char * format,...)64*4882a593Smuzhiyun die_errno(const char *format, ...)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun va_list va;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun va_start(va, format);
69*4882a593Smuzhiyun do_die(format, va, errno);
70*4882a593Smuzhiyun va_end(va);
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun static void __attribute__((noreturn, format(printf, 1, 2)))
die(const char * format,...)74*4882a593Smuzhiyun die(const char *format, ...)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun va_list va;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun va_start(va, format);
79*4882a593Smuzhiyun do_die(format, va, 0);
80*4882a593Smuzhiyun va_end(va);
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun static void __attribute__((noreturn))
assertion_failed(const char * expr,const char * file,int line)84*4882a593Smuzhiyun assertion_failed(const char *expr, const char *file, int line)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun die("Assertion failed: %s at %s:%d", expr, file, line);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun #define ASSERT(e) ({ if (!(e)) assertion_failed(#e, __FILE__, __LINE__); })
90*4882a593Smuzhiyun
rand_bytes(uint8_t * bytes,size_t count)91*4882a593Smuzhiyun static void rand_bytes(uint8_t *bytes, size_t count)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun size_t i;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun for (i = 0; i < count; i++)
96*4882a593Smuzhiyun bytes[i] = rand();
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
booltostr(bool b)99*4882a593Smuzhiyun static const char *booltostr(bool b)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun return b ? "true" : "false";
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
bytes_to_hex(const uint8_t * bytes,size_t count)104*4882a593Smuzhiyun static const char *bytes_to_hex(const uint8_t *bytes, size_t count)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun static char hex[1025];
107*4882a593Smuzhiyun size_t i;
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun ASSERT(count <= 512);
110*4882a593Smuzhiyun for (i = 0; i < count; i++)
111*4882a593Smuzhiyun sprintf(&hex[2*i], "%02x", bytes[i]);
112*4882a593Smuzhiyun return hex;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
full_write(int fd,const void * buf,size_t count)115*4882a593Smuzhiyun static void full_write(int fd, const void *buf, size_t count)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun while (count) {
118*4882a593Smuzhiyun ssize_t ret = write(fd, buf, count);
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun if (ret < 0)
121*4882a593Smuzhiyun die_errno("write failed");
122*4882a593Smuzhiyun buf += ret;
123*4882a593Smuzhiyun count -= ret;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun enum {
128*4882a593Smuzhiyun OPT_AMOUNT,
129*4882a593Smuzhiyun OPT_ITERATIONS,
130*4882a593Smuzhiyun };
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun static void usage(void);
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun /* ---------------------------------------------------------------------------
135*4882a593Smuzhiyun * /dev/fips140 ioctls
136*4882a593Smuzhiyun * ---------------------------------------------------------------------------*/
137*4882a593Smuzhiyun
get_fips140_device_number(void)138*4882a593Smuzhiyun static int get_fips140_device_number(void)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun FILE *f;
141*4882a593Smuzhiyun char line[128];
142*4882a593Smuzhiyun int number;
143*4882a593Smuzhiyun char name[32];
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun f = fopen("/proc/devices", "r");
146*4882a593Smuzhiyun if (!f)
147*4882a593Smuzhiyun die_errno("Failed to open /proc/devices");
148*4882a593Smuzhiyun while (fgets(line, sizeof(line), f)) {
149*4882a593Smuzhiyun if (sscanf(line, "%d %31s", &number, name) == 2 &&
150*4882a593Smuzhiyun strcmp(name, "fips140") == 0)
151*4882a593Smuzhiyun return number;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun fclose(f);
154*4882a593Smuzhiyun die("fips140 device node is unavailable.\n"
155*4882a593Smuzhiyun "The fips140 device node is only available when the fips140 module is loaded\n"
156*4882a593Smuzhiyun "and has been built with evaluation testing support.");
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
create_fips140_node_if_needed(void)159*4882a593Smuzhiyun static void create_fips140_node_if_needed(void)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun struct stat stbuf;
162*4882a593Smuzhiyun int major;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun if (stat("/dev/fips140", &stbuf) == 0)
165*4882a593Smuzhiyun return;
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun major = get_fips140_device_number();
168*4882a593Smuzhiyun if (mknod("/dev/fips140", S_IFCHR | 0600, makedev(major, 1)) != 0)
169*4882a593Smuzhiyun die_errno("Failed to create fips140 device node");
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun static int fips140_dev_fd = -1;
173*4882a593Smuzhiyun
fips140_ioctl(int cmd,const void * arg)174*4882a593Smuzhiyun static int fips140_ioctl(int cmd, const void *arg)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun if (fips140_dev_fd < 0) {
177*4882a593Smuzhiyun create_fips140_node_if_needed();
178*4882a593Smuzhiyun fips140_dev_fd = open("/dev/fips140", O_RDONLY);
179*4882a593Smuzhiyun if (fips140_dev_fd < 0)
180*4882a593Smuzhiyun die_errno("Failed to open /dev/fips140");
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun return ioctl(fips140_dev_fd, cmd, arg);
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
fips140_is_approved_service(const char * name)185*4882a593Smuzhiyun static bool fips140_is_approved_service(const char *name)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun int ret = fips140_ioctl(FIPS140_IOCTL_IS_APPROVED_SERVICE, name);
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun if (ret < 0)
190*4882a593Smuzhiyun die_errno("FIPS140_IOCTL_IS_APPROVED_SERVICE unexpectedly failed");
191*4882a593Smuzhiyun if (ret == 1)
192*4882a593Smuzhiyun return true;
193*4882a593Smuzhiyun if (ret == 0)
194*4882a593Smuzhiyun return false;
195*4882a593Smuzhiyun die("FIPS140_IOCTL_IS_APPROVED_SERVICE returned unexpected value %d",
196*4882a593Smuzhiyun ret);
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
fips140_module_version(void)199*4882a593Smuzhiyun static const char *fips140_module_version(void)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun static char buf[256];
202*4882a593Smuzhiyun int ret;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun memset(buf, 0, sizeof(buf));
205*4882a593Smuzhiyun ret = fips140_ioctl(FIPS140_IOCTL_MODULE_VERSION, buf);
206*4882a593Smuzhiyun if (ret < 0)
207*4882a593Smuzhiyun die_errno("FIPS140_IOCTL_MODULE_VERSION unexpectedly failed");
208*4882a593Smuzhiyun if (ret != 0)
209*4882a593Smuzhiyun die("FIPS140_IOCTL_MODULE_VERSION returned unexpected value %d",
210*4882a593Smuzhiyun ret);
211*4882a593Smuzhiyun return buf;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun /* ---------------------------------------------------------------------------
215*4882a593Smuzhiyun * AF_ALG utilities
216*4882a593Smuzhiyun * ---------------------------------------------------------------------------*/
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun #define AF_ALG_MAX_RNG_REQUEST_SIZE 128
219*4882a593Smuzhiyun
get_alg_fd(const char * alg_type,const char * alg_name)220*4882a593Smuzhiyun static int get_alg_fd(const char *alg_type, const char *alg_name)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun struct sockaddr_alg addr = {};
223*4882a593Smuzhiyun int alg_fd;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun alg_fd = socket(AF_ALG, SOCK_SEQPACKET, 0);
226*4882a593Smuzhiyun if (alg_fd < 0)
227*4882a593Smuzhiyun die("Failed to create AF_ALG socket.\n"
228*4882a593Smuzhiyun "AF_ALG is only available when it has been enabled in the kernel.\n");
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun strncpy((char *)addr.salg_type, alg_type, sizeof(addr.salg_type) - 1);
231*4882a593Smuzhiyun strncpy((char *)addr.salg_name, alg_name, sizeof(addr.salg_name) - 1);
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun if (bind(alg_fd, (void *)&addr, sizeof(addr)) != 0)
234*4882a593Smuzhiyun die_errno("Failed to bind AF_ALG socket to %s %s",
235*4882a593Smuzhiyun alg_type, alg_name);
236*4882a593Smuzhiyun return alg_fd;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
get_req_fd(int alg_fd,const char * alg_name)239*4882a593Smuzhiyun static int get_req_fd(int alg_fd, const char *alg_name)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun int req_fd = accept(alg_fd, NULL, NULL);
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun if (req_fd < 0)
244*4882a593Smuzhiyun die_errno("Failed to get request file descriptor for %s",
245*4882a593Smuzhiyun alg_name);
246*4882a593Smuzhiyun return req_fd;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun /* ---------------------------------------------------------------------------
250*4882a593Smuzhiyun * dump_jitterentropy command
251*4882a593Smuzhiyun * ---------------------------------------------------------------------------*/
252*4882a593Smuzhiyun
dump_from_jent_fd(int fd,size_t count)253*4882a593Smuzhiyun static void dump_from_jent_fd(int fd, size_t count)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun uint8_t buf[AF_ALG_MAX_RNG_REQUEST_SIZE];
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun while (count) {
258*4882a593Smuzhiyun ssize_t ret;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun memset(buf, 0, sizeof(buf));
261*4882a593Smuzhiyun ret = read(fd, buf, MIN(count, sizeof(buf)));
262*4882a593Smuzhiyun if (ret < 0)
263*4882a593Smuzhiyun die_errno("error reading from jitterentropy_rng");
264*4882a593Smuzhiyun full_write(STDOUT_FILENO, buf, ret);
265*4882a593Smuzhiyun count -= ret;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun
cmd_dump_jitterentropy(int argc,char * argv[])269*4882a593Smuzhiyun static int cmd_dump_jitterentropy(int argc, char *argv[])
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun static const struct option longopts[] = {
272*4882a593Smuzhiyun { "amount", required_argument, NULL, OPT_AMOUNT },
273*4882a593Smuzhiyun { "iterations", required_argument, NULL, OPT_ITERATIONS },
274*4882a593Smuzhiyun { NULL, 0, NULL, 0 },
275*4882a593Smuzhiyun };
276*4882a593Smuzhiyun size_t amount = 128;
277*4882a593Smuzhiyun size_t iterations = 1;
278*4882a593Smuzhiyun size_t i;
279*4882a593Smuzhiyun int c;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun while ((c = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
282*4882a593Smuzhiyun switch (c) {
283*4882a593Smuzhiyun case OPT_AMOUNT:
284*4882a593Smuzhiyun amount = strtoul(optarg, NULL, 0);
285*4882a593Smuzhiyun if (amount <= 0 || amount >= ULONG_MAX)
286*4882a593Smuzhiyun die("invalid argument to --amount");
287*4882a593Smuzhiyun break;
288*4882a593Smuzhiyun case OPT_ITERATIONS:
289*4882a593Smuzhiyun iterations = strtoul(optarg, NULL, 0);
290*4882a593Smuzhiyun if (iterations <= 0 || iterations >= ULONG_MAX)
291*4882a593Smuzhiyun die("invalid argument to --iterations");
292*4882a593Smuzhiyun break;
293*4882a593Smuzhiyun default:
294*4882a593Smuzhiyun usage();
295*4882a593Smuzhiyun return 1;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun for (i = 0; i < iterations; i++) {
300*4882a593Smuzhiyun int alg_fd = get_alg_fd("rng", "jitterentropy_rng");
301*4882a593Smuzhiyun int req_fd = get_req_fd(alg_fd, "jitterentropy_rng");
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun dump_from_jent_fd(req_fd, amount);
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun close(req_fd);
306*4882a593Smuzhiyun close(alg_fd);
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun return 0;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun /* ---------------------------------------------------------------------------
312*4882a593Smuzhiyun * show_invalid_inputs command
313*4882a593Smuzhiyun * ---------------------------------------------------------------------------*/
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun enum direction {
316*4882a593Smuzhiyun UNSPECIFIED,
317*4882a593Smuzhiyun DECRYPT,
318*4882a593Smuzhiyun ENCRYPT,
319*4882a593Smuzhiyun };
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun static const struct invalid_input_test {
322*4882a593Smuzhiyun const char *alg_type;
323*4882a593Smuzhiyun const char *alg_name;
324*4882a593Smuzhiyun const char *key;
325*4882a593Smuzhiyun size_t key_size;
326*4882a593Smuzhiyun const char *msg;
327*4882a593Smuzhiyun size_t msg_size;
328*4882a593Smuzhiyun const char *iv;
329*4882a593Smuzhiyun size_t iv_size;
330*4882a593Smuzhiyun enum direction direction;
331*4882a593Smuzhiyun int setkey_error;
332*4882a593Smuzhiyun int crypt_error;
333*4882a593Smuzhiyun } invalid_input_tests[] = {
334*4882a593Smuzhiyun {
335*4882a593Smuzhiyun .alg_type = "skcipher",
336*4882a593Smuzhiyun .alg_name = "cbc(aes)",
337*4882a593Smuzhiyun .key_size = 16,
338*4882a593Smuzhiyun }, {
339*4882a593Smuzhiyun .alg_type = "skcipher",
340*4882a593Smuzhiyun .alg_name = "cbc(aes)",
341*4882a593Smuzhiyun .key_size = 17,
342*4882a593Smuzhiyun .setkey_error = EINVAL,
343*4882a593Smuzhiyun }, {
344*4882a593Smuzhiyun .alg_type = "skcipher",
345*4882a593Smuzhiyun .alg_name = "cbc(aes)",
346*4882a593Smuzhiyun .key_size = 24,
347*4882a593Smuzhiyun }, {
348*4882a593Smuzhiyun .alg_type = "skcipher",
349*4882a593Smuzhiyun .alg_name = "cbc(aes)",
350*4882a593Smuzhiyun .key_size = 32,
351*4882a593Smuzhiyun }, {
352*4882a593Smuzhiyun .alg_type = "skcipher",
353*4882a593Smuzhiyun .alg_name = "cbc(aes)",
354*4882a593Smuzhiyun .key_size = 33,
355*4882a593Smuzhiyun .setkey_error = EINVAL,
356*4882a593Smuzhiyun }, {
357*4882a593Smuzhiyun .alg_type = "skcipher",
358*4882a593Smuzhiyun .alg_name = "cbc(aes)",
359*4882a593Smuzhiyun .key_size = 16,
360*4882a593Smuzhiyun .msg_size = 1,
361*4882a593Smuzhiyun .direction = DECRYPT,
362*4882a593Smuzhiyun .crypt_error = EINVAL,
363*4882a593Smuzhiyun }, {
364*4882a593Smuzhiyun .alg_type = "skcipher",
365*4882a593Smuzhiyun .alg_name = "cbc(aes)",
366*4882a593Smuzhiyun .key_size = 16,
367*4882a593Smuzhiyun .msg_size = 16,
368*4882a593Smuzhiyun .direction = ENCRYPT,
369*4882a593Smuzhiyun }, {
370*4882a593Smuzhiyun .alg_type = "skcipher",
371*4882a593Smuzhiyun .alg_name = "cbc(aes)",
372*4882a593Smuzhiyun .key_size = 16,
373*4882a593Smuzhiyun .msg_size = 17,
374*4882a593Smuzhiyun .direction = ENCRYPT,
375*4882a593Smuzhiyun .crypt_error = EINVAL,
376*4882a593Smuzhiyun }, {
377*4882a593Smuzhiyun .alg_type = "hash",
378*4882a593Smuzhiyun .alg_name = "cmac(aes)",
379*4882a593Smuzhiyun .key_size = 29,
380*4882a593Smuzhiyun .setkey_error = EINVAL,
381*4882a593Smuzhiyun }, {
382*4882a593Smuzhiyun .alg_type = "skcipher",
383*4882a593Smuzhiyun .alg_name = "xts(aes)",
384*4882a593Smuzhiyun .key_size = 32,
385*4882a593Smuzhiyun }, {
386*4882a593Smuzhiyun .alg_type = "skcipher",
387*4882a593Smuzhiyun .alg_name = "xts(aes)",
388*4882a593Smuzhiyun .key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
389*4882a593Smuzhiyun "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
390*4882a593Smuzhiyun .key_size = 32,
391*4882a593Smuzhiyun .setkey_error = EINVAL,
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun };
394*4882a593Smuzhiyun
describe_crypt_op(const struct invalid_input_test * t)395*4882a593Smuzhiyun static const char *describe_crypt_op(const struct invalid_input_test *t)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun if (t->direction == ENCRYPT)
398*4882a593Smuzhiyun return "encryption";
399*4882a593Smuzhiyun if (t->direction == DECRYPT)
400*4882a593Smuzhiyun return "decryption";
401*4882a593Smuzhiyun if (strcmp(t->alg_type, "hash") == 0)
402*4882a593Smuzhiyun return "hashing";
403*4882a593Smuzhiyun ASSERT(0);
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun
af_alg_setkey(const struct invalid_input_test * t,int alg_fd)406*4882a593Smuzhiyun static bool af_alg_setkey(const struct invalid_input_test *t, int alg_fd)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun const uint8_t *key = (const uint8_t *)t->key;
409*4882a593Smuzhiyun uint8_t _key[t->key_size];
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun if (t->key_size == 0)
412*4882a593Smuzhiyun return true;
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun if (t->key == NULL) {
415*4882a593Smuzhiyun rand_bytes(_key, t->key_size);
416*4882a593Smuzhiyun key = _key;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun if (setsockopt(alg_fd, SOL_ALG, ALG_SET_KEY, key, t->key_size) != 0) {
419*4882a593Smuzhiyun printf("%s: setting %zu-byte key failed with error '%s'\n",
420*4882a593Smuzhiyun t->alg_name, t->key_size, strerror(errno));
421*4882a593Smuzhiyun printf("\tkey was %s\n\n", bytes_to_hex(key, t->key_size));
422*4882a593Smuzhiyun ASSERT(t->setkey_error == errno);
423*4882a593Smuzhiyun return false;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun printf("%s: setting %zu-byte key succeeded\n",
426*4882a593Smuzhiyun t->alg_name, t->key_size);
427*4882a593Smuzhiyun printf("\tkey was %s\n\n", bytes_to_hex(key, t->key_size));
428*4882a593Smuzhiyun ASSERT(t->setkey_error == 0);
429*4882a593Smuzhiyun return true;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun
af_alg_process_msg(const struct invalid_input_test * t,int alg_fd)432*4882a593Smuzhiyun static void af_alg_process_msg(const struct invalid_input_test *t, int alg_fd)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun struct iovec iov;
435*4882a593Smuzhiyun struct msghdr hdr = {
436*4882a593Smuzhiyun .msg_iov = &iov,
437*4882a593Smuzhiyun .msg_iovlen = 1,
438*4882a593Smuzhiyun };
439*4882a593Smuzhiyun const uint8_t *msg = (const uint8_t *)t->msg;
440*4882a593Smuzhiyun uint8_t *_msg = NULL;
441*4882a593Smuzhiyun uint8_t *output = NULL;
442*4882a593Smuzhiyun uint8_t *control = NULL;
443*4882a593Smuzhiyun size_t controllen = 0;
444*4882a593Smuzhiyun struct cmsghdr *cmsg;
445*4882a593Smuzhiyun int req_fd;
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun if (t->msg_size == 0)
448*4882a593Smuzhiyun return;
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun req_fd = get_req_fd(alg_fd, t->alg_name);
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun if (t->msg == NULL) {
453*4882a593Smuzhiyun _msg = malloc(t->msg_size);
454*4882a593Smuzhiyun rand_bytes(_msg, t->msg_size);
455*4882a593Smuzhiyun msg = _msg;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun output = malloc(t->msg_size);
458*4882a593Smuzhiyun iov.iov_base = (void *)msg;
459*4882a593Smuzhiyun iov.iov_len = t->msg_size;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun if (t->direction != UNSPECIFIED)
462*4882a593Smuzhiyun controllen += CMSG_SPACE(sizeof(uint32_t));
463*4882a593Smuzhiyun if (t->iv_size)
464*4882a593Smuzhiyun controllen += CMSG_SPACE(sizeof(struct af_alg_iv) + t->iv_size);
465*4882a593Smuzhiyun control = calloc(1, controllen);
466*4882a593Smuzhiyun hdr.msg_control = control;
467*4882a593Smuzhiyun hdr.msg_controllen = controllen;
468*4882a593Smuzhiyun cmsg = CMSG_FIRSTHDR(&hdr);
469*4882a593Smuzhiyun if (t->direction != UNSPECIFIED) {
470*4882a593Smuzhiyun cmsg->cmsg_level = SOL_ALG;
471*4882a593Smuzhiyun cmsg->cmsg_type = ALG_SET_OP;
472*4882a593Smuzhiyun cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t));
473*4882a593Smuzhiyun *(uint32_t *)CMSG_DATA(cmsg) = t->direction == DECRYPT ?
474*4882a593Smuzhiyun ALG_OP_DECRYPT : ALG_OP_ENCRYPT;
475*4882a593Smuzhiyun cmsg = CMSG_NXTHDR(&hdr, cmsg);
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun if (t->iv_size) {
478*4882a593Smuzhiyun struct af_alg_iv *alg_iv;
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun cmsg->cmsg_level = SOL_ALG;
481*4882a593Smuzhiyun cmsg->cmsg_type = ALG_SET_IV;
482*4882a593Smuzhiyun cmsg->cmsg_len = CMSG_LEN(sizeof(*alg_iv) + t->iv_size);
483*4882a593Smuzhiyun alg_iv = (struct af_alg_iv *)CMSG_DATA(cmsg);
484*4882a593Smuzhiyun alg_iv->ivlen = t->iv_size;
485*4882a593Smuzhiyun memcpy(alg_iv->iv, t->iv, t->iv_size);
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun if (sendmsg(req_fd, &hdr, 0) != t->msg_size)
489*4882a593Smuzhiyun die_errno("sendmsg failed");
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun if (read(req_fd, output, t->msg_size) != t->msg_size) {
492*4882a593Smuzhiyun printf("%s: %s of %zu-byte message failed with error '%s'\n",
493*4882a593Smuzhiyun t->alg_name, describe_crypt_op(t), t->msg_size,
494*4882a593Smuzhiyun strerror(errno));
495*4882a593Smuzhiyun printf("\tmessage was %s\n\n", bytes_to_hex(msg, t->msg_size));
496*4882a593Smuzhiyun ASSERT(t->crypt_error == errno);
497*4882a593Smuzhiyun } else {
498*4882a593Smuzhiyun printf("%s: %s of %zu-byte message succeeded\n",
499*4882a593Smuzhiyun t->alg_name, describe_crypt_op(t), t->msg_size);
500*4882a593Smuzhiyun printf("\tmessage was %s\n\n", bytes_to_hex(msg, t->msg_size));
501*4882a593Smuzhiyun ASSERT(t->crypt_error == 0);
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun free(_msg);
504*4882a593Smuzhiyun free(output);
505*4882a593Smuzhiyun free(control);
506*4882a593Smuzhiyun close(req_fd);
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun
test_invalid_input(const struct invalid_input_test * t)509*4882a593Smuzhiyun static void test_invalid_input(const struct invalid_input_test *t)
510*4882a593Smuzhiyun {
511*4882a593Smuzhiyun int alg_fd = get_alg_fd(t->alg_type, t->alg_name);
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun if (af_alg_setkey(t, alg_fd))
514*4882a593Smuzhiyun af_alg_process_msg(t, alg_fd);
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun close(alg_fd);
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun
cmd_show_invalid_inputs(int argc,char * argv[])519*4882a593Smuzhiyun static int cmd_show_invalid_inputs(int argc, char *argv[])
520*4882a593Smuzhiyun {
521*4882a593Smuzhiyun int i;
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(invalid_input_tests); i++)
524*4882a593Smuzhiyun test_invalid_input(&invalid_input_tests[i]);
525*4882a593Smuzhiyun return 0;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun /* ---------------------------------------------------------------------------
529*4882a593Smuzhiyun * show_module_version command
530*4882a593Smuzhiyun * ---------------------------------------------------------------------------*/
531*4882a593Smuzhiyun
cmd_show_module_version(int argc,char * argv[])532*4882a593Smuzhiyun static int cmd_show_module_version(int argc, char *argv[])
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun printf("fips140_module_version() => \"%s\"\n",
535*4882a593Smuzhiyun fips140_module_version());
536*4882a593Smuzhiyun return 0;
537*4882a593Smuzhiyun }
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun /* ---------------------------------------------------------------------------
540*4882a593Smuzhiyun * show_service_indicators command
541*4882a593Smuzhiyun * ---------------------------------------------------------------------------*/
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun static const char * const default_services_to_show[] = {
544*4882a593Smuzhiyun "aes",
545*4882a593Smuzhiyun "cbc(aes)",
546*4882a593Smuzhiyun "cbcmac(aes)",
547*4882a593Smuzhiyun "cmac(aes)",
548*4882a593Smuzhiyun "ctr(aes)",
549*4882a593Smuzhiyun "cts(cbc(aes))",
550*4882a593Smuzhiyun "ecb(aes)",
551*4882a593Smuzhiyun "essiv(cbc(aes),sha256)",
552*4882a593Smuzhiyun "gcm(aes)",
553*4882a593Smuzhiyun "hmac(sha1)",
554*4882a593Smuzhiyun "hmac(sha224)",
555*4882a593Smuzhiyun "hmac(sha256)",
556*4882a593Smuzhiyun "hmac(sha384)",
557*4882a593Smuzhiyun "hmac(sha512)",
558*4882a593Smuzhiyun "jitterentropy_rng",
559*4882a593Smuzhiyun "sha1",
560*4882a593Smuzhiyun "sha224",
561*4882a593Smuzhiyun "sha256",
562*4882a593Smuzhiyun "sha384",
563*4882a593Smuzhiyun "sha512",
564*4882a593Smuzhiyun "stdrng",
565*4882a593Smuzhiyun "xcbc(aes)",
566*4882a593Smuzhiyun "xts(aes)",
567*4882a593Smuzhiyun };
568*4882a593Smuzhiyun
cmd_show_service_indicators(int argc,char * argv[])569*4882a593Smuzhiyun static int cmd_show_service_indicators(int argc, char *argv[])
570*4882a593Smuzhiyun {
571*4882a593Smuzhiyun const char * const *services = default_services_to_show;
572*4882a593Smuzhiyun int count = ARRAY_SIZE(default_services_to_show);
573*4882a593Smuzhiyun int i;
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun if (argc > 1) {
576*4882a593Smuzhiyun services = (const char **)(argv + 1);
577*4882a593Smuzhiyun count = argc - 1;
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun for (i = 0; i < count; i++) {
580*4882a593Smuzhiyun printf("fips140_is_approved_service(\"%s\") => %s\n",
581*4882a593Smuzhiyun services[i],
582*4882a593Smuzhiyun booltostr(fips140_is_approved_service(services[i])));
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun return 0;
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun /* ---------------------------------------------------------------------------
588*4882a593Smuzhiyun * main()
589*4882a593Smuzhiyun * ---------------------------------------------------------------------------*/
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun static const struct command {
592*4882a593Smuzhiyun const char *name;
593*4882a593Smuzhiyun int (*func)(int argc, char *argv[]);
594*4882a593Smuzhiyun } commands[] = {
595*4882a593Smuzhiyun { "dump_jitterentropy", cmd_dump_jitterentropy },
596*4882a593Smuzhiyun { "show_invalid_inputs", cmd_show_invalid_inputs },
597*4882a593Smuzhiyun { "show_module_version", cmd_show_module_version },
598*4882a593Smuzhiyun { "show_service_indicators", cmd_show_service_indicators },
599*4882a593Smuzhiyun };
600*4882a593Smuzhiyun
usage(void)601*4882a593Smuzhiyun static void usage(void)
602*4882a593Smuzhiyun {
603*4882a593Smuzhiyun fprintf(stderr,
604*4882a593Smuzhiyun "Usage:\n"
605*4882a593Smuzhiyun " fips140_lab_util dump_jitterentropy [OPTION]...\n"
606*4882a593Smuzhiyun " fips140_lab_util show_invalid_inputs\n"
607*4882a593Smuzhiyun " fips140_lab_util show_module_version\n"
608*4882a593Smuzhiyun " fips140_lab_util show_service_indicators [SERVICE]...\n"
609*4882a593Smuzhiyun "\n"
610*4882a593Smuzhiyun "Options for dump_jitterentropy:\n"
611*4882a593Smuzhiyun " --amount=AMOUNT Amount to dump in bytes per iteration (default 128)\n"
612*4882a593Smuzhiyun " --iterations=COUNT Number of start-up iterations (default 1)\n"
613*4882a593Smuzhiyun );
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun
main(int argc,char * argv[])616*4882a593Smuzhiyun int main(int argc, char *argv[])
617*4882a593Smuzhiyun {
618*4882a593Smuzhiyun int i;
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun if (argc < 2) {
621*4882a593Smuzhiyun usage();
622*4882a593Smuzhiyun return 2;
623*4882a593Smuzhiyun }
624*4882a593Smuzhiyun for (i = 1; i < argc; i++) {
625*4882a593Smuzhiyun if (strcmp(argv[i], "--help") == 0) {
626*4882a593Smuzhiyun usage();
627*4882a593Smuzhiyun return 2;
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun }
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(commands); i++) {
632*4882a593Smuzhiyun if (strcmp(commands[i].name, argv[1]) == 0)
633*4882a593Smuzhiyun return commands[i].func(argc - 1, argv + 1);
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun fprintf(stderr, "Unknown command: %s\n\n", argv[1]);
636*4882a593Smuzhiyun usage();
637*4882a593Smuzhiyun return 2;
638*4882a593Smuzhiyun }
639