blob: c150d7d00b512c25a0bf076b6503b4d28146b42f [file] [log] [blame]
developer67cb0a82023-12-25 23:36:27 +08001--- a/Makefile.am
2+++ b/Makefile.am
developerd042eba2023-11-14 14:23:39 +08003@@ -193,6 +193,16 @@ EXTRA_bin_kcapi_rng_DEPENDENCIES = libto
4
5 SCAN_FILES += $(bin_kcapi_rng_SOURCES)
6 man_MANS += apps/kcapi-rng.1
7+
8+bin_PROGRAMS += bin/kcapi-drbg
9+
10+bin_kcapi_drbg_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/lib/
11+bin_kcapi_drbg_LDFLAGS = $(COMMON_LDFLAGS)
12+bin_kcapi_drbg_LDADD = libkcapi.la
13+bin_kcapi_drbg_SOURCES = apps/kcapi-drbg.c apps/app-internal.c
14+EXTRA_bin_kcapi_rng_DEPENDENCIES = libtool
15+
16+SCAN_FILES += $(bin_kcapi_drbg_SOURCES)
17 endif
18
19 if ENABLE_KCAPI_ENCAPP
20--- /dev/null
developer67cb0a82023-12-25 23:36:27 +080021+++ b/apps/kcapi-drbg.c
developerd042eba2023-11-14 14:23:39 +080022@@ -0,0 +1,273 @@
23+// SPDX-License-Identifier: BSD-2-Clause
24+/*
25+ * Copyright (C) 2023, MediaTek Inc. All rights reserved.
26+ */
27+
28+#define _GNU_SOURCE
29+#include <unistd.h>
30+#include <sys/syscall.h>
31+#include <errno.h>
32+#include <limits.h>
33+#include <stdint.h>
34+#include <sys/types.h>
35+#include <sys/stat.h>
36+#include <fcntl.h>
37+#include <stdio.h>
38+#include <stdlib.h>
39+#include <string.h>
40+#include <getopt.h>
41+
42+#include <kcapi.h>
43+
44+#include "app-internal.h"
45+
46+/* For efficiency reasons, this should be identical to algif_rng.c:MAXSIZE. */
47+#define KCAPI_RNG_BUFSIZE 2048
48+
49+static struct kcapi_handle *rng = NULL;
50+static char *rng_name = NULL;
51+static bool hexout = false;
52+static unsigned char* entropy = NULL;
53+static unsigned char* nonce = NULL;
54+static unsigned char* per = NULL;
55+static unsigned char* additional_1 = NULL;
56+static unsigned char* additional_2 = NULL;
57+static uint32_t entropy_len = 0;
58+static uint32_t nonce_len = 0;
59+static uint32_t per_len = 0;
60+static uint32_t add1_len = 0;
61+static uint32_t add2_len = 0;
62+
63+
64+
65+static unsigned char* hextobin(char* hexstr, uint32_t *ret_len) {
66+ uint32_t len = strlen(hexstr);
67+ size_t i = 0;
68+ char *pos = hexstr;
69+ unsigned char *ret = (unsigned char*) malloc((len + 1) / 2);
70+
71+ for (i = 0; i < (len + 1) / 2; i++) {
72+ if(i == 0 && (len % 2) == 1) {
73+ sscanf(pos, "%1hhx", &ret[i]);
74+ pos += 1;
75+ } else {
76+ sscanf(pos, "%2hhx", &ret[i]);
77+ pos += 2;
78+ }
79+ }
80+ *ret_len = (len + 1) / 2;
81+
82+ return ret;
83+}
84+
85+static void uninit() {
86+ memset(entropy, 0, entropy_len);
87+ memset(nonce, 0, nonce_len);
88+ memset(per, 0, per_len);
89+ memset(additional_1, 0, add1_len);
90+ memset(additional_2, 0, add2_len);
91+ if(entropy)
92+ free(entropy);
93+ if(nonce)
94+ free(nonce);
95+ if(per)
96+ free(per);
97+}
98+
99+static void usage(void)
100+{
101+ fprintf(stderr, "\nKernel Crypto API DRBG\n");
102+ fprintf(stderr, "Usage:\n");
103+ fprintf(stderr, "\t-b --bytes <BYTES>\tNumber of bytes to generate (required option)\n");
104+ fprintf(stderr, "\t-r --rng name <RNGNAME>\tDRNG name as advertised in /proc/crypto(require option))\n");
105+ fprintf(stderr, "\t-e --entropy <RNGNAME>\tDRBG entropy(require option))\n");
106+ fprintf(stderr, "\t-n --nonce <RNGNAME>\tDRBG nonce(require option))\n");
107+ fprintf(stderr, "\t-p --personaliztion string <RNGNAME>\tDRBG personaliztion string(require option))\n");
108+ fprintf(stderr, "\t --hex\t\tThe random number is returned in hexadecimal\n");
109+ fprintf(stderr, "\t\t\t\tnotation\n");
110+ fprintf(stderr, "\t-h --help\t\tThis help information\n");
111+
112+ uninit();
113+ exit(1);
114+}
115+
116+static int parse_opts(int argc, char *argv[], size_t *outlen)
117+{
118+ int c = 0;
119+ size_t bytes = 0;
120+
121+ while (1) {
122+ int opt_index = 0;
123+ static struct option opts[] = {
124+ {"entropy", required_argument, 0, 'e'},
125+ {"nonce", required_argument, 0, 'n'},
126+ {"bytes", required_argument, 0, 'b'},
127+ {"rng_name", required_argument, 0, 'r'},
128+ {"personal_strng ", required_argument, 0, 'p'},
129+ {"help", no_argument, 0, 'h'},
130+ {"hex", no_argument, 0, 0},
131+ {"additionalinput1 ", required_argument, 0, 'a'},
132+ {"additionalinput2 ", required_argument, 0, 'c'},
133+ {0, 0, 0, 0}
134+ };
135+ c = getopt_long(argc, argv, "e:n:b:r:p:ha:c:", opts, &opt_index);
136+ if (-1 == c)
137+ break;
138+ switch (c) {
139+ case 0:
140+ switch (opt_index) {
141+ case 0:
142+ entropy = hextobin(optarg, &entropy_len);
143+ break;
144+ case 1:
145+ nonce = hextobin(optarg, &nonce_len);
146+ break;
147+ case 2:
148+ bytes = strtoul(optarg, NULL, 10);
149+ if (bytes == ULONG_MAX) {
150+ usage();
151+ return -EINVAL;
152+ }
153+ break;
154+ case 3:
155+ rng_name = optarg;
156+ break;
157+ case 4:
158+ per = hextobin(optarg, &per_len);
159+ break;
160+ case 5:
161+ usage();
162+ break;
163+ case 6:
164+ hexout = true;
165+ break;
166+ case 7:
167+ additional_1 = hextobin(optarg, &add1_len);
168+ break;
169+ case 8:
170+ additional_2 = hextobin(optarg, &add2_len);
171+ break;
172+ default:
173+ usage();
174+ }
175+ break;
176+ case 'e':
177+ entropy = hextobin(optarg, &entropy_len);
178+ break;
179+ case 'n':
180+ nonce = hextobin(optarg, &nonce_len);
181+ break;
182+ case 'b':
183+ bytes = strtoul(optarg, NULL, 10);
184+ if (bytes == ULONG_MAX) {
185+ usage();
186+ return -EINVAL;
187+ }
188+ break;
189+ case 'r':
190+ rng_name = optarg;
191+ break;
192+ case 'p':
193+ per = hextobin(optarg, &per_len);
194+ break;
195+ case 'a':
196+ additional_1 = hextobin(optarg, &add1_len);
197+ break;
198+ case 'c':
199+ additional_2 = hextobin(optarg, &add2_len);
200+ break;
201+ default:
202+ usage();
203+ }
204+ }
205+ if (!bytes || !nonce || !entropy || !rng_name)
206+ usage();
207+
208+ *outlen = (size_t)bytes;
209+ return 0;
210+}
211+
212+int main(int argc, char *argv[])
213+{
214+ ssize_t ret = 0;
215+ uint8_t buf[KCAPI_RNG_BUFSIZE] __aligned(KCAPI_APP_ALIGN);
216+ uint8_t *seedbuf = buf;
217+ uint32_t seedsize = 0;
218+ size_t outlen = 0;
219+ unsigned char *ent = NULL;
220+ int count = 2;
221+
222+ ret = parse_opts(argc, argv, &outlen);
223+ if (ret)
224+ return (int)ret;
225+
226+ ret = kcapi_rng_init(&rng, rng_name, 0);
227+ if (ret)
228+ return (int)ret;
229+
230+ seedsize = kcapi_rng_seedsize(rng);
231+
232+ ent = (unsigned char*)malloc(entropy_len + nonce_len + per_len);
233+ memset(ent, 0, entropy_len + nonce_len + per_len);
234+ memcpy(ent, entropy, entropy_len);
235+ memcpy(ent + entropy_len, nonce, nonce_len);
236+ memcpy(ent + entropy_len + nonce_len, per, per_len);
237+
238+ kcapi_rng_setentropy(rng, ent, entropy_len + nonce_len + per_len);
239+
240+ ret = kcapi_rng_seed(rng, seedbuf, seedsize);
241+ if (ret)
242+ goto out;
243+
244+ while(count --) {
245+ size_t len = outlen;
246+ while (len) {
247+ size_t todo = (len < KCAPI_RNG_BUFSIZE) ?
248+ len : KCAPI_RNG_BUFSIZE;
249+
250+ if(count == 1 && additional_1) {
251+ kcapi_rng_setaddtl(rng, additional_1, add1_len);
252+ } else if(count == 0 && additional_2 ){
253+ kcapi_rng_setaddtl(rng, additional_2, add2_len);
254+ }
255+
256+ ret = kcapi_rng_generate(rng, buf, todo);
257+ if (ret < 0)
258+ goto out;
259+
260+ if ((uint32_t)ret == 0) {
261+ ret = -EFAULT;
262+ goto out;
263+ }
264+
265+ if(count == 0) {
266+ if (hexout) {
267+ char hexbuf[2 * KCAPI_RNG_BUFSIZE];
268+
269+ bin2hex(buf, (size_t)ret, hexbuf, sizeof(hexbuf), 0);
270+ fwrite(hexbuf, 2 * (size_t)ret, 1, stdout);
271+ } else {
272+ fwrite(buf, (size_t)ret, 1, stdout);
273+ }
274+ }
275+ len -= (size_t)ret;
276+ }
277+ }
278+
279+ ret = 0;
280+out:
281+ if (rng)
282+ kcapi_rng_destroy(rng);
283+ kcapi_memset_secure(buf, 0, sizeof(buf));
284+
285+ if (seedbuf && (seedbuf != buf)) {
286+ kcapi_memset_secure(seedbuf, 0, seedsize);
287+ free(seedbuf);
288+ }
289+
290+ uninit();
291+ if(!ent)
292+ free(ent);
293+
294+ return (int)ret;
295+}