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");