OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * px5g - Embedded x509 key and certificate generator based on PolarSSL |
||
3 | * |
||
4 | * Copyright (C) 2009 Steven Barth <steven@midlink.org> |
||
5 | * Copyright (C) 2014 Felix Fietkau <nbd@nbd.name> |
||
6 | * |
||
7 | * This library is free software; you can redistribute it and/or |
||
8 | * modify it under the terms of the GNU Lesser General Public |
||
9 | * License, version 2.1 as published by the Free Software Foundation. |
||
10 | * |
||
11 | * This library is distributed in the hope that it will be useful, |
||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
14 | * Lesser General Public License for more details. |
||
15 | * |
||
16 | * You should have received a copy of the GNU Lesser General Public |
||
17 | * License along with this library; if not, write to the Free Software |
||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
||
19 | * MA 02110-1301 USA |
||
20 | */ |
||
21 | |||
22 | #include <sys/types.h> |
||
23 | |||
24 | #include <stdio.h> |
||
25 | #include <stdlib.h> |
||
26 | #include <string.h> |
||
27 | #include <time.h> |
||
28 | #include <limits.h> |
||
29 | #include <unistd.h> |
||
30 | #include <fcntl.h> |
||
31 | #include <stdbool.h> |
||
32 | |||
33 | #include <mbedtls/bignum.h> |
||
34 | #include <mbedtls/x509_crt.h> |
||
35 | #include <mbedtls/rsa.h> |
||
36 | #include <mbedtls/pk.h> |
||
37 | |||
38 | #define PX5G_VERSION "0.2" |
||
39 | #define PX5G_COPY "Copyright (c) 2009 Steven Barth <steven@midlink.org>" |
||
40 | #define PX5G_LICENSE "Licensed under the GNU Lesser General Public License v2.1" |
||
41 | |||
42 | static int urandom_fd; |
||
43 | static char buf[16384]; |
||
44 | |||
45 | static int _urandom(void *ctx, unsigned char *out, size_t len) |
||
46 | { |
||
47 | read(urandom_fd, out, len); |
||
48 | return 0; |
||
49 | } |
||
50 | |||
51 | static void write_file(const char *path, int len, bool pem) |
||
52 | { |
||
53 | FILE *f = stdout; |
||
54 | const char *buf_start = buf; |
||
55 | |||
56 | if (!pem) |
||
57 | buf_start += sizeof(buf) - len; |
||
58 | |||
59 | if (!len) { |
||
60 | fprintf(stderr, "No data to write\n"); |
||
61 | exit(1); |
||
62 | } |
||
63 | |||
64 | if (!f) { |
||
65 | fprintf(stderr, "error: I/O error\n"); |
||
66 | exit(1); |
||
67 | } |
||
68 | |||
69 | if (path) |
||
70 | f = fopen(path, "w"); |
||
71 | |||
72 | fwrite(buf_start, 1, len, f); |
||
73 | fclose(f); |
||
74 | } |
||
75 | |||
76 | static void write_key(mbedtls_pk_context *key, const char *path, bool pem) |
||
77 | { |
||
78 | int len = 0; |
||
79 | |||
80 | if (pem) { |
||
81 | if (mbedtls_pk_write_key_pem(key, (void *) buf, sizeof(buf)) == 0) |
||
82 | len = strlen(buf); |
||
83 | } else { |
||
84 | len = mbedtls_pk_write_key_der(key, (void *) buf, sizeof(buf)); |
||
85 | if (len < 0) |
||
86 | len = 0; |
||
87 | } |
||
88 | |||
89 | write_file(path, len, pem); |
||
90 | } |
||
91 | |||
92 | static void gen_key(mbedtls_pk_context *key, int ksize, int exp, bool pem) |
||
93 | { |
||
94 | mbedtls_pk_init(key); |
||
95 | fprintf(stderr, "Generating RSA private key, %i bit long modulus\n", ksize); |
||
96 | mbedtls_pk_setup(key, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)); |
||
97 | if (mbedtls_rsa_gen_key(mbedtls_pk_rsa(*key), _urandom, NULL, ksize, exp)) { |
||
98 | fprintf(stderr, "error: key generation failed\n"); |
||
99 | exit(1); |
||
100 | } |
||
101 | } |
||
102 | |||
103 | int rsakey(char **arg) |
||
104 | { |
||
105 | mbedtls_pk_context key; |
||
106 | unsigned int ksize = 512; |
||
107 | int exp = 65537; |
||
108 | char *path = NULL; |
||
109 | bool pem = true; |
||
110 | |||
111 | while (*arg && **arg == '-') { |
||
112 | if (!strcmp(*arg, "-out") && arg[1]) { |
||
113 | path = arg[1]; |
||
114 | arg++; |
||
115 | } else if (!strcmp(*arg, "-3")) { |
||
116 | exp = 3; |
||
117 | } else if (!strcmp(*arg, "-der")) { |
||
118 | pem = false; |
||
119 | } |
||
120 | arg++; |
||
121 | } |
||
122 | |||
123 | if (*arg) |
||
124 | ksize = (unsigned int)atoi(*arg); |
||
125 | |||
126 | gen_key(&key, ksize, exp, pem); |
||
127 | write_key(&key, path, pem); |
||
128 | |||
129 | mbedtls_pk_free(&key); |
||
130 | |||
131 | return 0; |
||
132 | } |
||
133 | |||
134 | int selfsigned(char **arg) |
||
135 | { |
||
136 | mbedtls_pk_context key; |
||
137 | mbedtls_x509write_cert cert; |
||
138 | mbedtls_mpi serial; |
||
139 | |||
140 | char *subject = ""; |
||
141 | unsigned int ksize = 512; |
||
142 | int exp = 65537; |
||
143 | unsigned int days = 30; |
||
144 | char *keypath = NULL, *certpath = NULL; |
||
145 | bool pem = true; |
||
146 | time_t from = time(NULL), to; |
||
147 | char fstr[20], tstr[20], sstr[17]; |
||
148 | int len; |
||
149 | |||
150 | while (*arg && **arg == '-') { |
||
151 | if (!strcmp(*arg, "-der")) { |
||
152 | pem = false; |
||
153 | } else if (!strcmp(*arg, "-newkey") && arg[1]) { |
||
154 | if (strncmp(arg[1], "rsa:", 4)) { |
||
155 | fprintf(stderr, "error: invalid algorithm"); |
||
156 | return 1; |
||
157 | } |
||
158 | ksize = (unsigned int)atoi(arg[1] + 4); |
||
159 | arg++; |
||
160 | } else if (!strcmp(*arg, "-days") && arg[1]) { |
||
161 | days = (unsigned int)atoi(arg[1]); |
||
162 | arg++; |
||
163 | } else if (!strcmp(*arg, "-keyout") && arg[1]) { |
||
164 | keypath = arg[1]; |
||
165 | arg++; |
||
166 | } else if (!strcmp(*arg, "-out") && arg[1]) { |
||
167 | certpath = arg[1]; |
||
168 | arg++; |
||
169 | } else if (!strcmp(*arg, "-subj") && arg[1]) { |
||
170 | if (arg[1][0] != '/' || strchr(arg[1], ';')) { |
||
171 | fprintf(stderr, "error: invalid subject"); |
||
172 | return 1; |
||
173 | } |
||
174 | subject = calloc(strlen(arg[1]) + 1, 1); |
||
175 | char *oldc = arg[1] + 1, *newc = subject, *delim; |
||
176 | do { |
||
177 | delim = strchr(oldc, '='); |
||
178 | if (!delim) { |
||
179 | fprintf(stderr, "error: invalid subject"); |
||
180 | return 1; |
||
181 | } |
||
182 | memcpy(newc, oldc, delim - oldc + 1); |
||
183 | newc += delim - oldc + 1; |
||
184 | oldc = delim + 1; |
||
185 | |||
186 | delim = strchr(oldc, '/'); |
||
187 | if (!delim) { |
||
188 | delim = arg[1] + strlen(arg[1]); |
||
189 | } |
||
190 | memcpy(newc, oldc, delim - oldc); |
||
191 | newc += delim - oldc; |
||
192 | *newc++ = ','; |
||
193 | oldc = delim + 1; |
||
194 | } while(*delim); |
||
195 | arg++; |
||
196 | } |
||
197 | arg++; |
||
198 | } |
||
199 | |||
200 | gen_key(&key, ksize, exp, pem); |
||
201 | |||
202 | if (keypath) |
||
203 | write_key(&key, keypath, pem); |
||
204 | |||
205 | from = (from < 1000000000) ? 1000000000 : from; |
||
206 | strftime(fstr, sizeof(fstr), "%Y%m%d%H%M%S", gmtime(&from)); |
||
207 | to = from + 60 * 60 * 24 * days; |
||
208 | if (to < from) |
||
209 | to = INT_MAX; |
||
210 | strftime(tstr, sizeof(tstr), "%Y%m%d%H%M%S", gmtime(&to)); |
||
211 | |||
212 | fprintf(stderr, "Generating selfsigned certificate with subject '%s'" |
||
213 | " and validity %s-%s\n", subject, fstr, tstr); |
||
214 | |||
215 | mbedtls_x509write_crt_init(&cert); |
||
216 | mbedtls_x509write_crt_set_md_alg(&cert, MBEDTLS_MD_SHA256); |
||
217 | mbedtls_x509write_crt_set_issuer_key(&cert, &key); |
||
218 | mbedtls_x509write_crt_set_subject_key(&cert, &key); |
||
219 | mbedtls_x509write_crt_set_subject_name(&cert, subject); |
||
220 | mbedtls_x509write_crt_set_issuer_name(&cert, subject); |
||
221 | mbedtls_x509write_crt_set_validity(&cert, fstr, tstr); |
||
222 | mbedtls_x509write_crt_set_basic_constraints(&cert, 0, -1); |
||
223 | mbedtls_x509write_crt_set_subject_key_identifier(&cert); |
||
224 | mbedtls_x509write_crt_set_authority_key_identifier(&cert); |
||
225 | |||
226 | _urandom(NULL, buf, 8); |
||
227 | for (len = 0; len < 8; len++) |
||
228 | sprintf(sstr + len*2, "%02x", (unsigned char) buf[len]); |
||
229 | |||
230 | mbedtls_mpi_init(&serial); |
||
231 | mbedtls_mpi_read_string(&serial, 16, sstr); |
||
232 | mbedtls_x509write_crt_set_serial(&cert, &serial); |
||
233 | |||
234 | if (pem) { |
||
235 | if (mbedtls_x509write_crt_pem(&cert, (void *) buf, sizeof(buf), _urandom, NULL) < 0) { |
||
236 | fprintf(stderr, "Failed to generate certificate\n"); |
||
237 | return 1; |
||
238 | } |
||
239 | |||
240 | len = strlen(buf); |
||
241 | } else { |
||
242 | len = mbedtls_x509write_crt_der(&cert, (void *) buf, sizeof(buf), _urandom, NULL); |
||
243 | if (len < 0) { |
||
244 | fprintf(stderr, "Failed to generate certificate: %d\n", len); |
||
245 | return 1; |
||
246 | } |
||
247 | } |
||
248 | write_file(certpath, len, pem); |
||
249 | |||
250 | mbedtls_x509write_crt_free(&cert); |
||
251 | mbedtls_mpi_free(&serial); |
||
252 | mbedtls_pk_free(&key); |
||
253 | |||
254 | return 0; |
||
255 | } |
||
256 | |||
257 | int main(int argc, char *argv[]) |
||
258 | { |
||
259 | urandom_fd = open("/dev/urandom", O_RDONLY); |
||
260 | |||
261 | if (!argv[1]) { |
||
262 | //Usage |
||
263 | } else if (!strcmp(argv[1], "rsakey")) { |
||
264 | return rsakey(argv+2); |
||
265 | } else if (!strcmp(argv[1], "selfsigned")) { |
||
266 | return selfsigned(argv+2); |
||
267 | } |
||
268 | |||
269 | fprintf(stderr, |
||
270 | "PX5G X.509 Certificate Generator Utility v" PX5G_VERSION "\n" PX5G_COPY |
||
271 | "\nbased on PolarSSL by Christophe Devine and Paul Bakker\n\n"); |
||
272 | fprintf(stderr, "Usage: %s [rsakey|selfsigned]\n", *argv); |
||
273 | return 1; |
||
274 | } |