b937d220ca5e8ea4018d80bcf678b2edd7c3bd93
1 // Copyright 2020 Paul Spooren <mail@aparcar.org>
3 // SPDX-License-Identifier: GPL-2.0-or-later
10 #include <wolfssl/options.h>
11 #include <wolfssl/wolfcrypt/asn.h>
12 #include <wolfssl/wolfcrypt/asn_public.h>
13 #include <wolfssl/wolfcrypt/ecc.h>
14 #include <wolfssl/wolfcrypt/error-crypt.h>
15 #include <wolfssl/wolfcrypt/rsa.h>
16 #include <wolfssl/wolfcrypt/settings.h>
18 #define HEAP_HINT NULL
20 #define WOLFSSL_MIN_RSA_BITS 2048
27 int write_file(byte
*buf
, int bufSz
, char *path
) {
31 file
= fopen(path
, "wb");
33 perror("Error opening file");
39 ret
= (int)fwrite(buf
, 1, bufSz
, file
);
44 /* ret > 0 indicates a successful file write, set to zero for return */
50 int write_key(ecc_key
*ecKey
, RsaKey
*rsaKey
, int type
, int keySz
, char *fName
,
53 byte der
[FOURK_SZ
] = {};
54 byte pem
[FOURK_SZ
] = {};
56 if (type
== EC_KEY_TYPE
) {
57 ret
= wc_EccKeyToDer(ecKey
, der
, sizeof(der
));
59 ret
= wc_RsaKeyToDer(rsaKey
, der
, sizeof(der
));
62 fprintf(stderr
, "Key To DER failed: %d\n", ret
);
67 if (type
== EC_KEY_TYPE
) {
68 ret
= wc_DerToPem(der
, derSz
, pem
, sizeof(pem
), ECC_PRIVATEKEY_TYPE
);
70 ret
= wc_DerToPem(der
, derSz
, pem
, sizeof(pem
), PRIVATEKEY_TYPE
);
73 fprintf(stderr
, "DER to PEM failed: %d\n", ret
);
76 ret
= write_file(pem
, pemSz
, fName
);
78 ret
= write_file(der
, derSz
, fName
);
83 int gen_key(WC_RNG
*rng
, ecc_key
*ecKey
, RsaKey
*rsaKey
, int type
, int keySz
,
84 long exp
, int curve
) {
87 if (type
== EC_KEY_TYPE
) {
88 ret
= wc_ecc_init(ecKey
);
91 ret
= wc_InitRsaKey(rsaKey
, NULL
);
95 fprintf(stderr
, "Key initialization failed: %d\n", ret
);
99 if (type
== EC_KEY_TYPE
) {
100 fprintf(stderr
, "Generating EC private key\n");
101 ret
= wc_ecc_make_key_ex(rng
, 32, ecKey
, curve
);
103 fprintf(stderr
, "Generating RSA private key, %i bit long modulus\n", keySz
);
104 ret
= wc_MakeRsaKey(rsaKey
, keySz
, WC_RSA_EXPONENT
, rng
);
107 fprintf(stderr
, "Key generation failed: %d\n", ret
);
112 int selfsigned(WC_RNG
*rng
, char **arg
) {
117 int keySz
= WOLFSSL_MIN_RSA_BITS
;
118 int type
= EC_KEY_TYPE
;
119 int exp
= WC_RSA_EXPONENT
;
120 int curve
= ECC_SECP256R1
;
121 unsigned int days
= 3653; // 10 years
122 char *keypath
= NULL
, *certpath
= NULL
;
123 char fstr
[20], tstr
[20];
126 #ifdef __USE_TIME_BITS64
127 time_t to
, from
= time(NULL
);
129 unsigned long to
, from
= time(NULL
);
131 byte derBuf
[FOURK_SZ
] = {};
132 byte pemBuf
[FOURK_SZ
] = {};
135 char *key
, *val
, *tmp
;
137 ret
= wc_InitCert(&newCert
);
139 fprintf(stderr
, "Init Cert failed: %d\n", ret
);
144 while (*arg
&& **arg
== '-') {
145 if (!strncmp(*arg
, "-der", 4)) {
147 } else if (!strncmp(*arg
, "-newkey", 6) && arg
[1]) {
148 if (!strncmp(arg
[1], "rsa:", 4)) {
150 keySz
= (unsigned int)atoi(arg
[1] + 4);
151 } else if (!strncmp(arg
[1], "ec", 2)) {
154 fprintf(stderr
, "error: invalid algorithm\n");
158 } else if (!strncmp(*arg
, "-days", 5) && arg
[1]) {
159 days
= (unsigned int)atoi(arg
[1]);
161 } else if (!strncmp(*arg
, "-pkeyopt", 8) && arg
[1]) {
162 if (strncmp(arg
[1], "ec_paramgen_curve:", 18)) {
163 fprintf(stderr
, "error: invalid pkey option: %s\n", arg
[1]);
166 if (!strncmp(arg
[1] + 18, "P-256:", 5)) {
167 curve
= ECC_SECP256R1
;
168 } else if (!strncmp(arg
[1] + 18, "P-384:", 5)) {
169 curve
= ECC_SECP384R1
;
170 } else if (!strncmp(arg
[1] + 18, "P-521:", 5)) {
171 curve
= ECC_SECP521R1
;
173 fprintf(stderr
, "error: invalid curve name: %s\n", arg
[1] + 18);
177 } else if (!strncmp(*arg
, "-keyout", 7) && arg
[1]) {
180 } else if (!strncmp(*arg
, "-out", 4) && arg
[1]) {
183 } else if (!strcmp(*arg
, "-subj") && arg
[1]) {
184 subject
= strdupa(arg
[1]);
187 tmp
= strchr(key
, '/');
191 val
= strchr(key
, '=');
196 if (!strcmp(key
, "C"))
197 strncpy(newCert
.subject
.country
, val
, CTC_NAME_SIZE
);
198 else if (!strcmp(key
, "ST"))
199 strncpy(newCert
.subject
.state
, val
, CTC_NAME_SIZE
);
200 else if (!strcmp(key
, "L"))
201 strncpy(newCert
.subject
.locality
, val
, CTC_NAME_SIZE
);
202 else if (!strcmp(key
, "O"))
203 strncpy(newCert
.subject
.org
, val
, CTC_NAME_SIZE
);
204 else if (!strcmp(key
, "OU"))
205 strncpy(newCert
.subject
.unit
, val
, CTC_NAME_SIZE
);
206 else if (!strcmp(key
, "CN"))
207 strncpy(newCert
.subject
.commonName
, val
, CTC_NAME_SIZE
);
208 else if (!strcmp(key
, "EMAIL"))
209 strncpy(newCert
.subject
.email
, val
, CTC_NAME_SIZE
);
211 printf("warning: unknown attribute %s=%s\n", key
, val
);
213 } while (tmp
&& (key
= ++tmp
));
217 newCert
.daysValid
= days
;
219 gen_key(rng
, &ecKey
, &rsaKey
, type
, keySz
, exp
, curve
);
220 write_key(&ecKey
, &rsaKey
, type
, keySz
, keypath
, pem
);
222 from
= (from
< 1000000000) ? 1000000000 : from
;
223 strftime(fstr
, sizeof(fstr
), "%Y%m%d%H%M%S", gmtime(&from
));
224 to
= from
+ 60 * 60 * 24 * days
;
227 strftime(tstr
, sizeof(tstr
), "%Y%m%d%H%M%S", gmtime(&to
));
230 "Generating selfsigned certificate with subject '%s'"
231 " and validity %s-%s\n",
232 subject
, fstr
, tstr
);
234 if (type
== EC_KEY_TYPE
) {
235 ret
= wc_MakeCert(&newCert
, derBuf
, sizeof(derBuf
), NULL
, &ecKey
, rng
);
237 ret
= wc_MakeCert(&newCert
, derBuf
, sizeof(derBuf
), &rsaKey
, NULL
, rng
);
240 fprintf(stderr
, "Make Cert failed: %d\n", ret
);
244 if (type
== EC_KEY_TYPE
) {
245 newCert
.sigType
= CTC_SHA256wECDSA
;
246 ret
= wc_SignCert(newCert
.bodySz
, newCert
.sigType
, derBuf
, sizeof(derBuf
),
249 newCert
.sigType
= CTC_SHA256wRSA
;
250 ret
= wc_SignCert(newCert
.bodySz
, newCert
.sigType
, derBuf
, sizeof(derBuf
),
254 fprintf(stderr
, "Sign Cert failed: %d\n", ret
);
259 ret
= wc_DerToPem(derBuf
, derSz
, pemBuf
, sizeof(pemBuf
), CERT_TYPE
);
261 fprintf(stderr
, "DER to PEM failed: %d\n", ret
);
266 ret
= write_file(pemBuf
, pemSz
, certpath
);
268 fprintf(stderr
, "Write Cert failed: %d\n", ret
);
272 if (type
== EC_KEY_TYPE
) {
275 wc_FreeRsaKey(&rsaKey
);
280 int dokey(WC_RNG
*rng
, int type
, char **arg
) {
284 int curve
= ECC_SECP256R1
;
285 int keySz
= WOLFSSL_MIN_RSA_BITS
;
286 int exp
= WC_RSA_EXPONENT
;
290 while (*arg
&& **arg
== '-') {
291 if (!strncmp(*arg
, "-out", 4) && arg
[1]) {
294 } else if (!strncmp(*arg
, "-3", 2)) {
296 } else if (!strncmp(*arg
, "-der", 4)) {
302 if (*arg
&& type
== RSA_KEY_TYPE
) {
303 keySz
= (unsigned int)atoi(*arg
);
305 if (!strncmp(*arg
, "P-256", 5)) {
306 curve
= ECC_SECP256R1
;
307 } else if (!strncmp(*arg
, "P-384", 5)) {
308 curve
= ECC_SECP384R1
;
309 } else if (!strncmp(*arg
, "P-521", 5)) {
310 curve
= ECC_SECP521R1
;
312 fprintf(stderr
, "Invalid Curve Name: %s\n", *arg
);
317 ret
= gen_key(rng
, &ecKey
, &rsaKey
, type
, keySz
, exp
, curve
);
321 ret
= write_key(&ecKey
, &rsaKey
, type
, keySz
, path
, pem
);
323 if (type
== EC_KEY_TYPE
) {
326 wc_FreeRsaKey(&rsaKey
);
331 int main(int argc
, char *argv
[]) {
334 ret
= wc_InitRng(&rng
);
336 fprintf(stderr
, "Init Rng failed: %d\n", ret
);
341 if (!strncmp(argv
[1], "eckey", 5))
342 return dokey(&rng
, EC_KEY_TYPE
, argv
+ 2);
344 if (!strncmp(argv
[1], "rsakey", 5))
345 return dokey(&rng
, RSA_KEY_TYPE
, argv
+ 2);
347 if (!strncmp(argv
[1], "selfsigned", 10))
348 return selfsigned(&rng
, argv
+ 2);
351 fprintf(stderr
, "PX5G X.509 Certificate Generator Utilit using WolfSSL\n\n");
352 fprintf(stderr
, "Usage: [eckey|rsakey|selfsigned]\n");