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