Skip to content

Commit 7e64524

Browse files
committed
Added keygen C tool + vcproj for windows
1 parent 486e633 commit 7e64524

3 files changed

Lines changed: 565 additions & 31 deletions

File tree

tools/keytools/keygen.c

Lines changed: 346 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,346 @@
1+
/* keygen.c
2+
*
3+
* C native key generation tool
4+
*
5+
*
6+
* Copyright (C) 2020 wolfSSL Inc.
7+
*
8+
* This file is part of wolfBoot.
9+
*
10+
* wolfBoot is free software; you can redistribute it and/or modify
11+
* it under the terms of the GNU General Public License as published by
12+
* the Free Software Foundation; either version 2 of the License, or
13+
* (at your option) any later version.
14+
*
15+
* wolfBoot is distributed in the hope that it will be useful,
16+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
* GNU General Public License for more details.
19+
*
20+
* You should have received a copy of the GNU General Public License
21+
* along with this program; if not, write to the Free Software
22+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
23+
*/
24+
25+
/* Option to enable sign tool debugging */
26+
/* Must also define DEBUG_WOLFSSL in user_settings.h */
27+
//#define DEBUG_SIGNTOOL
28+
29+
#include <wolfssl/wolfcrypt/settings.h>
30+
#ifndef NO_RSA
31+
#include <wolfssl/wolfcrypt/rsa.h>
32+
#endif
33+
#ifdef HAVE_ECC
34+
#include <wolfssl/wolfcrypt/ecc.h>
35+
#include <wolfssl/wolfcrypt/asn.h>
36+
37+
#endif
38+
#ifdef HAVE_ED25519
39+
#include <wolfssl/wolfcrypt/ed25519.h>
40+
#endif
41+
42+
#include <wolfssl/wolfcrypt/random.h>
43+
#include <wolfssl/wolfcrypt/error-crypt.h>
44+
#define DEBUG_SIGNTOOL 1
45+
#ifdef DEBUG_SIGNTOOL
46+
#include <wolfssl/wolfcrypt/logging.h>
47+
#endif
48+
49+
#include <stdio.h>
50+
#include <stdlib.h>
51+
#include <string.h>
52+
#include <limits.h>
53+
#include <sys/stat.h>
54+
#include <sys/types.h>
55+
56+
#ifdef _WIN32
57+
#define PATH_MAX 256
58+
#endif
59+
60+
#define KEYGEN_ED25519 0
61+
#define KEYGEN_ECC256 1
62+
#define KEYGEN_RSA2048 2
63+
#define KEYGEN_RSA4096 3
64+
65+
const char Ed25519_pub_key_define[] = "const uint8_t ed25519_pub_key[32] = {";
66+
const char Ecc256_pub_key_define[] = "const uint8_t ecc256_pub_key[64] = {";
67+
const char Rsa_2048_pub_key_define[] = "const uint8_t rsa2048_pub_key[%d] = {";
68+
const char Rsa_4096_pub_key_define[] = "const uint8_t rsa4096_pub_key[%d] = {";
69+
70+
const char Cfile_Banner[] = "/* Public-key file for wolfBoot, automatically generated. Do not edit. */\n" \
71+
"/*\n" \
72+
" * This file has been generated and contains the public key which is\n" \
73+
" * used by wolfBoot to verify the updates.\n" \
74+
" */" \
75+
"\n#include <stdint.h>\n\n";
76+
77+
78+
79+
static void usage(const char *pname) /* implies exit */
80+
{
81+
printf("Usage: %s [--ed25519 | --ecc256 | --rsa2048 | --rsa4096 ] pub_key_file.c\n", pname);
82+
exit(125);
83+
}
84+
85+
static void fwritekey(uint8_t *key, int len, FILE *f)
86+
{
87+
int i;
88+
for (i = 0; i < len; i++)
89+
{
90+
if ((i % 8) == 0) {
91+
if (i != 0)
92+
fprintf(f, ",");
93+
fprintf(f, "\n\t");
94+
}
95+
else {
96+
fprintf(f, ", ");
97+
}
98+
fprintf(f, "0x%02x", key[i]);
99+
}
100+
}
101+
102+
103+
static void keygen_rsa(WC_RNG *rng, char *pubkeyfile, int size)
104+
{
105+
RsaKey k;
106+
uint8_t priv_der[4096], pub_der[2048];
107+
int privlen, publen;
108+
FILE *fpub, *fpriv;
109+
char priv_fname[40];
110+
111+
if (wc_MakeRsaKey(&k, size, 65537, rng) != 0) {
112+
fprintf(stderr, "Unable to create RSA%d key\n", size);
113+
exit(1);
114+
}
115+
privlen = wc_RsaKeyToDer(&k, priv_der, size);
116+
if (privlen <= 0) {
117+
fprintf(stderr, "Unable to export private key to DER\n");
118+
exit(2);
119+
}
120+
publen = wc_RsaKeyToPublicDer(&k, pub_der, size);
121+
if (publen <= 0) {
122+
fprintf(stderr, "Unable to export public key\n");
123+
exit(3);
124+
}
125+
sprintf(priv_fname, "rsa%d.der", size);
126+
fpriv = fopen(priv_fname, "wb");
127+
if (fpriv == NULL) {
128+
fprintf(stderr, "Unable to open file '%s' for writing: %s", priv_fname, strerror(errno));
129+
exit(4);
130+
}
131+
fwrite(priv_der, privlen, 1, fpriv);
132+
fclose(fpriv);
133+
134+
fpub = fopen(pubkeyfile, "w");
135+
if (fpub == NULL) {
136+
fprintf(stderr, "Unable to open file '%s' for writing: %s", pubkeyfile, strerror(errno));
137+
exit(4);
138+
}
139+
fprintf(fpub, "%s", Cfile_Banner);
140+
if (size == 2048)
141+
fprintf(fpub, Rsa_2048_pub_key_define, publen);
142+
else
143+
fprintf(fpub, Rsa_4096_pub_key_define, publen);
144+
145+
fwritekey(pub_der, publen, fpub);
146+
fprintf(fpub, "\n};\n");
147+
fprintf(fpub, "const uint32_t ecc256_pub_key_len = %d;\n", publen);
148+
fclose(fpub);
149+
}
150+
151+
#define ECC256_KEY_SIZE 32
152+
static void keygen_ecc256(WC_RNG *rng, char *pubkfile)
153+
{
154+
ecc_key k;
155+
uint8_t Qx[ECC256_KEY_SIZE], Qy[ECC256_KEY_SIZE], d[ECC256_KEY_SIZE];
156+
uint32_t qxsize = ECC256_KEY_SIZE,
157+
qysize = ECC256_KEY_SIZE,
158+
dsize = ECC256_KEY_SIZE;
159+
uint8_t priv_der[ECC256_KEY_SIZE * 4];
160+
FILE *fpriv, *fpub;
161+
uint32_t outsize = ECC256_KEY_SIZE * 4;
162+
char priv_fname[20] = "";
163+
164+
165+
if (wc_ecc_make_key(rng, ECC256_KEY_SIZE, &k) != 0) {
166+
fprintf(stderr, "Unable to create ecc%d key\n", ECC256_KEY_SIZE << 3);
167+
exit(1);
168+
}
169+
170+
if (wc_ecc_export_private_raw(&k, Qx, &qxsize, Qy, &qysize, d, &dsize) != 0) {
171+
fprintf(stderr, "Unable to export private key to DER\n");
172+
exit(2);
173+
}
174+
175+
if (wc_ecc_export_public_raw(&k, Qx, &qxsize, Qy, &qysize ) != 0) {
176+
fprintf(stderr, "Unable to export public key\n");
177+
exit(3);
178+
}
179+
180+
sprintf(priv_fname, "ecc%d.der", (ECC256_KEY_SIZE << 3));
181+
182+
fpriv = fopen(priv_fname, "wb");
183+
if (fpriv == NULL) {
184+
fprintf(stderr, "Unable to open file '%s' for writing: %s", priv_fname, strerror(errno));
185+
exit(3);
186+
}
187+
188+
fwrite(Qx, qxsize, 1, fpriv);
189+
fwrite(Qy, qysize, 1, fpriv);
190+
fwrite(d, dsize, 1, fpriv);
191+
fclose(fpriv);
192+
fpub = fopen(pubkfile, "w");
193+
if (fpub == NULL) {
194+
fprintf(stderr, "Unable to open file '%s' for writing: %s", pubkfile, strerror(errno));
195+
exit(4);
196+
}
197+
fprintf(fpub, "%s", Cfile_Banner);
198+
fprintf(fpub, "%s", Ecc256_pub_key_define);
199+
fwritekey(Qx, qxsize, fpub);
200+
fprintf(fpub, ",");
201+
fwritekey(Qy, qysize, fpub);
202+
fprintf(fpub, "\n};\n");
203+
fprintf(fpub, "const uint32_t ecc256_pub_key_len = 64;\n");
204+
fclose(fpub);
205+
}
206+
207+
208+
static void keygen_ed25519(WC_RNG *rng, char *pubkfile)
209+
{
210+
ed25519_key k;
211+
uint8_t priv[32], pub[32];
212+
FILE *fpriv, *fpub;
213+
uint32_t outlen = ED25519_KEY_SIZE;
214+
if (wc_ed25519_make_key(rng, ED25519_KEY_SIZE, &k) != 0) {
215+
fprintf(stderr, "Unable to create ed25519 key\n");
216+
exit(1);
217+
}
218+
if (wc_ed25519_export_private_only(&k, priv, &outlen) != 0) {
219+
fprintf(stderr, "Unable to export ed25519 private key\n");
220+
exit(2);
221+
}
222+
if (wc_ed25519_export_public(&k, pub, &outlen) != 0) {
223+
fprintf(stderr, "Unable to export ed25519 public key\n");
224+
exit(2);
225+
}
226+
fpriv = fopen("ed25519.der", "wb");
227+
if (fpriv == NULL) {
228+
fprintf(stderr, "Unable to open file 'ed25519.der' for writing: %s", strerror(errno));
229+
exit(3);
230+
}
231+
fwrite(priv, 32, 1, fpriv);
232+
fclose(fpriv);
233+
fpub = fopen(pubkfile, "w");
234+
if (fpub == NULL) {
235+
fprintf(stderr, "Unable to open file '%s' for writing: %s", pubkfile, strerror(errno));
236+
exit(4);
237+
}
238+
fprintf(fpub, "%s", Cfile_Banner);
239+
fprintf(fpub, "%s", Ed25519_pub_key_define);
240+
fwritekey(pub, 32, fpub);
241+
fprintf(fpub, "\n};\n");
242+
fprintf(fpub, "const uint32_t ed25519_pub_key_len = 32;\n");
243+
fclose(fpub);
244+
}
245+
246+
int main(int argc, char** argv)
247+
{
248+
int ret = 0;
249+
int i;
250+
int force = 0;
251+
int keytype;
252+
const char *kfilename;
253+
char *output_pubkey_file;
254+
WC_RNG rng;
255+
FILE *f;
256+
257+
#ifdef DEBUG_SIGNTOOL
258+
wolfSSL_Debugging_ON();
259+
#endif
260+
261+
/* Check arguments and print usage */
262+
if (argc < 2 || argc > 4)
263+
usage(argv[0]);
264+
265+
for (i = 1; i < argc - 1; i++) {
266+
/* Parse Arguments */
267+
if (strcmp(argv[i], "--ed25519") == 0) {
268+
keytype = KEYGEN_ED25519;
269+
kfilename = strdup("ed25519.der");
270+
}
271+
else if (strcmp(argv[i], "--ecc256") == 0) {
272+
keytype = KEYGEN_ECC256;
273+
kfilename = strdup("ecc256.der");
274+
}
275+
else if (strcmp(argv[i], "--rsa2048") == 0) {
276+
keytype = KEYGEN_RSA2048;
277+
kfilename = strdup("rsa2048.der");
278+
}
279+
else if (strcmp(argv[i], "--rsa4096") == 0) {
280+
keytype = KEYGEN_RSA4096;
281+
kfilename = strdup("rsa4096.der");
282+
}
283+
else if (strcmp(argv[i], "--force") == 0) {
284+
force = 1;
285+
}
286+
else {
287+
fprintf(stderr, "Invalid argument '%s'.", argv[i]);
288+
usage(argv[0]);
289+
}
290+
}
291+
output_pubkey_file = strdup(argv[argc - 1]);
292+
293+
f = fopen(kfilename, "rb");
294+
if (!force && (f != NULL)) {
295+
char reply[40];
296+
fclose(f);
297+
printf("** Warning: key file already exist! Are you sure you want to generate a new key and overwrite the existing key? [Type 'Yes, I am sure!']: ");
298+
fflush(stdout);
299+
gets(reply);
300+
printf("Reply is [%s]\n", reply);
301+
if (strcmp(reply, "Yes, I am sure!") != 0) {
302+
printf("Operation aborted by user.");
303+
exit(5);
304+
}
305+
}
306+
307+
printf("Private key: %s\n", kfilename);
308+
printf("Generated public key C file: %s\n", output_pubkey_file);
309+
printf("Generating key...\n");
310+
fflush(stdout);
311+
wc_InitRng(&rng);
312+
313+
switch (keytype) {
314+
#ifdef HAVE_ED25519
315+
case KEYGEN_ED25519:
316+
{
317+
keygen_ed25519(&rng, output_pubkey_file);
318+
break;
319+
}
320+
#endif
321+
322+
#ifdef HAVE_ECC
323+
case KEYGEN_ECC256:
324+
{
325+
keygen_ecc256(&rng, output_pubkey_file);
326+
break;
327+
}
328+
#endif
329+
330+
#ifndef NO_RSA
331+
case KEYGEN_RSA2048:
332+
{
333+
keygen_rsa(&rng, output_pubkey_file, 2048);
334+
break;
335+
}
336+
case KEYGEN_RSA4096:
337+
{
338+
keygen_rsa(&rng, output_pubkey_file, 4096);
339+
break;
340+
}
341+
#endif
342+
} /* end switch */
343+
344+
printf("Done.\n");
345+
return 0;
346+
}

0 commit comments

Comments
 (0)