cd04a41dfb85a5968531b2ea1c9c2440d05e81d5
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 (!strcmp(*arg
, "-der")) {
147 } else if (!strcmp(*arg
, "-newkey") && arg
[1]) {
148 if (!strncmp(arg
[1], "rsa:", 4)) {
150 keySz
= atoi(arg
[1] + 4);
151 } else if (!strcmp(arg
[1], "ec")) {
154 fprintf(stderr
, "error: invalid algorithm\n");
158 } else if (!strcmp(*arg
, "-days") && arg
[1]) {
159 days
= (unsigned int)atoi(arg
[1]);
161 } else if (!strcmp(*arg
, "-pkeyopt") && arg
[1]) {
162 if (strncmp(arg
[1], "ec_paramgen_curve:", 18)) {
163 fprintf(stderr
, "error: invalid pkey option: %s\n", arg
[1]);
166 if (!strcmp(arg
[1] + 18, "P-256")) {
167 curve
= ECC_SECP256R1
;
168 } else if (!strcmp(arg
[1] + 18, "P-384")) {
169 curve
= ECC_SECP384R1
;
170 } else if (!strcmp(arg
[1] + 18, "P-521")) {
171 curve
= ECC_SECP521R1
;
173 fprintf(stderr
, "error: invalid curve name: %s\n", arg
[1] + 18);
177 } else if (!strcmp(*arg
, "-keyout") && arg
[1]) {
180 } else if (!strcmp(*arg
, "-out") && 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
);
209 #ifdef WOLFSSL_ALT_NAMES
210 if(strlen(val
) + 2 > 256) {
211 fprintf(stderr
, "error: CN is too long: %s\n", val
);
215 newCert
.altNames
[0] = 0x30; //Sequence with one element
216 newCert
.altNames
[1] = strlen(val
) + 2; // Length of entire sequence
217 newCert
.altNames
[2] = 0x82; //8 - String, 2 - DNS Name
218 newCert
.altNames
[3] = strlen(val
); //DNS Name length
219 memcpy(newCert
.altNames
+ 4, val
, strlen(val
)); //DNS Name
220 newCert
.altNamesSz
= strlen(val
) + 4;
223 else if (!strcmp(key
, "EMAIL"))
224 strncpy(newCert
.subject
.email
, val
, CTC_NAME_SIZE
);
226 printf("warning: unknown attribute %s=%s\n", key
, val
);
228 } while (tmp
&& (key
= ++tmp
));
232 newCert
.daysValid
= days
;
234 newCert
.keyUsage
= KEYUSE_DIGITAL_SIG
| KEYUSE_CONTENT_COMMIT
| KEYUSE_KEY_ENCIPHER
;
235 newCert
.extKeyUsage
= EXTKEYUSE_SERVER_AUTH
;
237 gen_key(rng
, &ecKey
, &rsaKey
, type
, keySz
, exp
, curve
);
238 write_key(&ecKey
, &rsaKey
, type
, keySz
, keypath
, pem
);
240 from
= (from
< 1000000000) ? 1000000000 : from
;
241 strftime(fstr
, sizeof(fstr
), "%Y%m%d%H%M%S", gmtime(&from
));
242 to
= from
+ 60 * 60 * 24 * days
;
245 strftime(tstr
, sizeof(tstr
), "%Y%m%d%H%M%S", gmtime(&to
));
248 "Generating selfsigned certificate with subject '%s'"
249 " and validity %s-%s\n",
250 subject
, fstr
, tstr
);
252 if (type
== EC_KEY_TYPE
) {
253 newCert
.sigType
= CTC_SHA256wECDSA
;
254 ret
= wc_MakeCert(&newCert
, derBuf
, sizeof(derBuf
), NULL
, &ecKey
, rng
);
256 newCert
.sigType
= CTC_SHA256wRSA
;
257 ret
= wc_MakeCert(&newCert
, derBuf
, sizeof(derBuf
), &rsaKey
, NULL
, rng
);
260 fprintf(stderr
, "Make Cert failed: %d\n", ret
);
264 if (type
== EC_KEY_TYPE
) {
265 ret
= wc_SignCert(newCert
.bodySz
, newCert
.sigType
, derBuf
, sizeof(derBuf
),
268 ret
= wc_SignCert(newCert
.bodySz
, newCert
.sigType
, derBuf
, sizeof(derBuf
),
272 fprintf(stderr
, "Sign Cert failed: %d\n", ret
);
277 ret
= wc_DerToPem(derBuf
, derSz
, pemBuf
, sizeof(pemBuf
), CERT_TYPE
);
279 fprintf(stderr
, "DER to PEM failed: %d\n", ret
);
284 ret
= write_file(pemBuf
, pemSz
, certpath
);
286 fprintf(stderr
, "Write Cert failed: %d\n", ret
);
290 if (type
== EC_KEY_TYPE
) {
293 wc_FreeRsaKey(&rsaKey
);
298 int dokey(WC_RNG
*rng
, int type
, char **arg
) {
302 int curve
= ECC_SECP256R1
;
303 int keySz
= WOLFSSL_MIN_RSA_BITS
;
304 int exp
= WC_RSA_EXPONENT
;
308 while (*arg
&& **arg
== '-') {
309 if (!strcmp(*arg
, "-out") && arg
[1]) {
312 } else if (!strcmp(*arg
, "-3")) {
314 } else if (!strcmp(*arg
, "-der")) {
320 if (*arg
&& type
== RSA_KEY_TYPE
) {
323 if (!strcmp(*arg
, "P-256")) {
324 curve
= ECC_SECP256R1
;
325 } else if (!strcmp(*arg
, "P-384")) {
326 curve
= ECC_SECP384R1
;
327 } else if (!strcmp(*arg
, "P-521")) {
328 curve
= ECC_SECP521R1
;
330 fprintf(stderr
, "Invalid Curve Name: %s\n", *arg
);
335 ret
= gen_key(rng
, &ecKey
, &rsaKey
, type
, keySz
, exp
, curve
);
339 ret
= write_key(&ecKey
, &rsaKey
, type
, keySz
, path
, pem
);
341 if (type
== EC_KEY_TYPE
) {
344 wc_FreeRsaKey(&rsaKey
);
349 int main(int argc
, char *argv
[]) {
352 ret
= wc_InitRng(&rng
);
354 fprintf(stderr
, "Init Rng failed: %d\n", ret
);
359 if (!strcmp(argv
[1], "eckey"))
360 return dokey(&rng
, EC_KEY_TYPE
, argv
+ 2);
362 if (!strcmp(argv
[1], "rsakey"))
363 return dokey(&rng
, RSA_KEY_TYPE
, argv
+ 2);
365 if (!strcmp(argv
[1], "selfsigned"))
366 return selfsigned(&rng
, argv
+ 2);
369 fprintf(stderr
, "PX5G X.509 Certificate Generator Utilit using WolfSSL\n\n");
370 fprintf(stderr
, "Usage: [eckey|rsakey|selfsigned]\n");