2 * px5g - Embedded x509 key and certificate generator based on PolarSSL
4 * Copyright (C) 2009 Steven Barth <steven@midlink.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License, version 2.1 as published by the Free Software Foundation.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
28 #include "polarssl/bignum.h"
29 #include "polarssl/x509.h"
30 #include "polarssl/rsa.h"
32 #define PX5G_VERSION "0.1"
33 #define PX5G_COPY "Copyright (c) 2009 Steven Barth <steven@midlink.org>"
34 #define PX5G_LICENSE "Licensed under the GNU Lesser General Public License v2.1"
36 static int urandom_fd
;
38 static int _urandom(void *ctx
)
41 read(urandom_fd
, &ret
, sizeof(ret
));
46 int rsakey(char **arg
) {
49 unsigned int ksize
= 512;
52 int flag
= X509_OUTPUT_PEM
;
54 while (*arg
&& **arg
== '-') {
55 if (!strcmp(*arg
, "-out") && arg
[1]) {
58 } else if (!strcmp(*arg
, "-3")) {
60 } else if (!strcmp(*arg
, "-der")) {
61 flag
= X509_OUTPUT_DER
;
67 ksize
= (unsigned int)atoi(*arg
);
70 rsa_init(&rsa
, RSA_PKCS_V15
, 0, _urandom
, NULL
);
72 fprintf(stderr
, "Generating RSA private key, %i bit long modulus\n", ksize
);
73 if (rsa_gen_key(&rsa
, ksize
, exp
)) {
74 fprintf(stderr
, "error: key generation failed\n");
78 if (x509write_keyfile(&rsa
, path
, flag
)) {
79 fprintf(stderr
, "error: I/O error\n");
87 int selfsigned(char **arg
) {
92 unsigned int ksize
= 512;
94 unsigned int days
= 30;
95 char *keypath
= NULL
, *certpath
= NULL
;
96 int flag
= X509_OUTPUT_PEM
;
97 time_t from
= time(NULL
), to
;
98 char fstr
[20], tstr
[20];
100 while (*arg
&& **arg
== '-') {
101 if (!strcmp(*arg
, "-der")) {
102 flag
= X509_OUTPUT_DER
;
103 } else if (!strcmp(*arg
, "-newkey") && arg
[1]) {
104 if (strncmp(arg
[1], "rsa:", 4)) {
105 fprintf(stderr
, "error: invalid algorithm");
108 ksize
= (unsigned int)atoi(arg
[1] + 4);
110 } else if (!strcmp(*arg
, "-days") && arg
[1]) {
111 days
= (unsigned int)atoi(arg
[1]);
113 } else if (!strcmp(*arg
, "-keyout") && arg
[1]) {
116 } else if (!strcmp(*arg
, "-out") && arg
[1]) {
119 } else if (!strcmp(*arg
, "-subj") && arg
[1]) {
120 if (arg
[1][0] != '/' || strchr(arg
[1], ';')) {
121 fprintf(stderr
, "error: invalid subject");
124 subject
= calloc(strlen(arg
[1]) + 1, 1);
125 char *oldc
= arg
[1] + 1, *newc
= subject
, *delim
;
127 delim
= strchr(oldc
, '=');
129 fprintf(stderr
, "error: invalid subject");
132 memcpy(newc
, oldc
, delim
- oldc
+ 1);
133 newc
+= delim
- oldc
+ 1;
136 delim
= strchr(oldc
, '/');
138 delim
= arg
[1] + strlen(arg
[1]);
140 memcpy(newc
, oldc
, delim
- oldc
);
141 newc
+= delim
- oldc
;
150 rsa_init(&rsa
, RSA_PKCS_V15
, 0, _urandom
, NULL
);
151 x509write_init_node(&node
);
152 fprintf(stderr
, "Generating RSA private key, %i bit long modulus\n", ksize
);
153 if (rsa_gen_key(&rsa
, ksize
, exp
)) {
154 fprintf(stderr
, "error: key generation failed\n");
159 if (x509write_keyfile(&rsa
, keypath
, flag
)) {
160 fprintf(stderr
, "error: I/O error\n");
165 from
= (from
< 1000000000) ? 1000000000 : from
;
166 strftime(fstr
, sizeof(fstr
), "%F %H:%M:%S", gmtime(&from
));
167 to
= from
+ 60 * 60 * 24 * days
;
170 strftime(tstr
, sizeof(tstr
), "%F %H:%M:%S", gmtime(&to
));
173 x509write_init_raw(&cert
);
174 x509write_add_pubkey(&cert
, &rsa
);
175 x509write_add_subject(&cert
, (unsigned char*)subject
);
176 x509write_add_validity(&cert
, (unsigned char*)fstr
, (unsigned char*)tstr
);
177 fprintf(stderr
, "Generating selfsigned certificate with subject '%s'"
178 " and validity %s-%s\n", subject
, fstr
, tstr
);
179 if (x509write_create_selfsign(&cert
, &rsa
)) {
180 fprintf(stderr
, "error: certificate generation failed\n");
183 if (x509write_crtfile(&cert
, (unsigned char*)certpath
, flag
)) {
184 fprintf(stderr
, "error: I/O error\n");
188 x509write_free_raw(&cert
);
193 int main(int argc
, char *argv
[]) {
194 urandom_fd
= open("/dev/urandom", O_RDONLY
);
195 if (urandom_fd
< 0) {
196 perror("open(/dev/urandom)");
202 } else if (!strcmp(argv
[1], "rsakey")) {
203 return rsakey(argv
+2);
204 } else if (!strcmp(argv
[1], "selfsigned")) {
205 return selfsigned(argv
+2);
209 "PX5G X.509 Certificate Generator Utility v" PX5G_VERSION
"\n" PX5G_COPY
210 "\nbased on PolarSSL by Christophe Devine and Paul Bakker\n\n");
211 fprintf(stderr
, "Usage: %s [rsakey|selfsigned]\n", *argv
);