buildworld: Add support to skip toolchain if requested.
[dragonfly.git] / sbin / hammer2 / cmd_rsa.c
CommitLineData
62efe6ec
MD
1/*
2 * Copyright (c) 2011-2012 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@dragonflybsd.org>
6 * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * 3. Neither the name of The DragonFly Project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific, prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#include "hammer2.h"
37
0c3a8cd0
MD
38#include <openssl/rsa.h> /* public/private key functions */
39#include <openssl/pem.h> /* public/private key file load */
40#include <openssl/err.h>
41
62efe6ec
MD
42/*
43 * Should be run as root. Creates /etc/hammer2/rsa.{pub,prv} using
44 * an openssl command.
45 */
46int
47cmd_rsainit(const char *dir_path)
48{
49 struct stat st;
50 int ecode;
51 char *str1;
52 char *str2;
53 char *cmd;
54 mode_t old_umask;
55
56 /*
57 * Create the directory if necessary
58 */
59 if (stat(dir_path, &st) < 0) {
60 str1 = strdup(dir_path);
61 str2 = str1 - 1;
62
63 while ((str2 = strchr(str2 + 1, '/')) != NULL) {
64 *str2 = 0;
65 mkdir(str1, 0755);
66 *str2 = '/';
67 }
68 mkdir(str1, 0700);
69 free(str1);
70 }
71 asprintf(&str1, "%s/rsa.prv", dir_path);
72 asprintf(&str2, "%s/rsa.pub", dir_path);
73
ce48a6c5 74 old_umask = umask(077);
62efe6ec 75 if (stat(str1, &st) < 0) {
62efe6ec 76 asprintf(&cmd, "openssl genrsa -out %s 2048", str1);
62efe6ec
MD
77 ecode = system(cmd);
78 free(cmd);
79 chmod(str1, 0400);
80 if (ecode) {
81 fprintf(stderr,
82 "hammer2 rsainit: private key gen failed\n");
83 free(str2);
84 free(str1);
ce48a6c5 85 umask(old_umask);
62efe6ec
MD
86 return 1;
87 }
88 printf("hammer2 rsainit: created %s\n", str1);
89 remove(str2);
90 } else {
91 printf("hammer2 rsainit: Using existing private key in %s\n",
92 str1);
93 }
94 if (stat(str2, &st) < 0) {
95 asprintf(&cmd, "openssl rsa -in %s -out %s -pubout",
96 str1, str2);
97 ecode = system(cmd);
98 free(cmd);
99 if (ecode) {
100 fprintf(stderr,
101 "hammer2 rsainit: public key gen failed\n");
102 free(str2);
103 free(str1);
ce48a6c5 104 umask(old_umask);
62efe6ec
MD
105 return 1;
106 }
107 printf("hammer2 rsainit: created %s\n", str2);
108 } else {
109 printf("hammer2 rsainit: both keys already exist\n");
110 }
ce48a6c5 111 umask(old_umask);
62efe6ec
MD
112 free(str2);
113 free(str1);
114
115 return 0;
116}
117
118int
119cmd_rsaenc(const char **keyfiles, int nkeys)
120{
121 RSA **keys = calloc(nkeys, sizeof(RSA *));
122 int *ispub = calloc(nkeys, sizeof(int));
123 int ecode = 0;
124 int blksize = 0;
125 int i;
126 int off;
127 int n;
128 unsigned char *data_in;
129 unsigned char *data_out;
130
131 for (i = 0; i < nkeys; ++i) {
132 FILE *fp;
133 const char *sfx;
134
135 sfx = strrchr(keyfiles[i], '.');
136 if (sfx && strcmp(sfx, ".pub") == 0) {
137 fp = fopen(keyfiles[i], "r");
138 if (fp == NULL) {
139 fprintf(stderr, "hammer2 rsaenc: unable to "
140 "open %s\n", keyfiles[i]);
141 ecode = 1;
142 goto done;
143 }
144 keys[i] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
145 ispub[i] = 1;
146 fclose(fp);
147 if (keys[i] == NULL) {
148 fprintf(stderr, "hammer2 rsaenc: unable to "
149 "parse public key from %s\n",
150 keyfiles[i]);
151 ecode = 1;
152 goto done;
153 }
154 } else if (sfx && strcmp(sfx, ".prv") == 0) {
155 fp = fopen(keyfiles[i], "r");
156 if (fp == NULL) {
157 fprintf(stderr, "hammer2 rsaenc: unable to "
158 "open %s\n", keyfiles[i]);
159 ecode = 1;
160 goto done;
161 }
162 keys[i] = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
163 fclose(fp);
164 if (keys[i] == NULL) {
165 fprintf(stderr, "hammer2 rsaenc: unable to "
166 "parse private key from %s\n",
167 keyfiles[i]);
168 ecode = 1;
169 goto done;
170 }
171 } else {
172 fprintf(stderr, "hammer2: rsaenc: key files must end "
173 "in .pub or .prv\n");
174 ecode = 1;
175 goto done;
176 }
177 if (i == 0)
178 blksize = RSA_size(keys[i]);
179 else
180 assert(blksize == RSA_size(keys[i]));
181 }
182 fprintf(stderr, "blksize %d\n", blksize);
183
184 /*
185 *
186 */
187 data_in = malloc(blksize);
188 data_out = malloc(blksize);
189 off = 0;
190 while ((n = read(0, data_in + off, blksize - off)) > 0) {
191 off += n;
192 if (off == blksize) {
193 for (i = 0; i < nkeys; ++i) {
194 if (ispub[i])
195 RSA_public_encrypt(blksize,
196 data_in, data_out,
197 keys[i],
198 RSA_NO_PADDING);
199 else
200 RSA_private_encrypt(blksize,
201 data_in, data_out,
202 keys[i],
203 RSA_NO_PADDING);
204 if (i + 1 != nkeys)
205 bcopy(data_out, data_in, blksize);
206 }
207 if (write(1, data_out, blksize) != blksize) {
208 perror("write");
209 ecode = 1;
210 break;
211 }
212 off = 0;
213 }
214 }
215 if (off && ecode == 0) {
216 if (off < blksize)
217 bzero(data_in + off, blksize - off);
218 for (i = 0; i < nkeys; ++i) {
219 if (ispub[i])
220 RSA_public_encrypt(blksize,
221 data_in, data_out,
222 keys[i],
223 RSA_NO_PADDING);
224 else
225 RSA_private_encrypt(blksize,
226 data_in, data_out,
227 keys[i],
228 RSA_NO_PADDING);
229 if (i + 1 != nkeys)
230 bcopy(data_out, data_in, blksize);
231 }
232 if (write(1, data_out, blksize) != blksize) {
233 perror("write");
234 ecode = 1;
235 }
236 }
237 if (n < 0) {
238 perror("read");
239 ecode = 1;
240 }
241 free(data_out);
242 free(data_in);
243done:
244 for (i = 0; i < nkeys; ++i) {
245 if (keys[i])
246 RSA_free(keys[i]);
247 }
248 free(keys);
249 free(ispub);
250 return (ecode);
251}
252
253int
254cmd_rsadec(const char **keyfiles, int nkeys)
255{
256 RSA **keys = calloc(nkeys, sizeof(RSA *));
257 int *ispub = calloc(nkeys, sizeof(int));
258 int ecode = 0;
259 int blksize = 0;
260 int i;
261 int off;
262 int n;
263 unsigned char *data_in;
264 unsigned char *data_out;
265
266 for (i = 0; i < nkeys; ++i) {
267 FILE *fp;
268 const char *sfx;
269
270 sfx = strrchr(keyfiles[i], '.');
271 if (sfx && strcmp(sfx, ".pub") == 0) {
272 fp = fopen(keyfiles[i], "r");
273 if (fp == NULL) {
274 fprintf(stderr, "hammer2 rsaenc: unable to "
275 "open %s\n", keyfiles[i]);
276 ecode = 1;
277 goto done;
278 }
279 keys[i] = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
280 ispub[i] = 1;
281 fclose(fp);
282 if (keys[i] == NULL) {
283 fprintf(stderr, "hammer2 rsaenc: unable to "
284 "parse public key from %s\n",
285 keyfiles[i]);
286 ecode = 1;
287 goto done;
288 }
289 } else if (sfx && strcmp(sfx, ".prv") == 0) {
290 fp = fopen(keyfiles[i], "r");
291 if (fp == NULL) {
292 fprintf(stderr, "hammer2 rsaenc: unable to "
293 "open %s\n", keyfiles[i]);
294 ecode = 1;
295 goto done;
296 }
297 keys[i] = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
298 fclose(fp);
299 if (keys[i] == NULL) {
300 fprintf(stderr, "hammer2 rsaenc: unable to "
301 "parse private key from %s\n",
302 keyfiles[i]);
303 ecode = 1;
304 goto done;
305 }
306 } else {
307 fprintf(stderr, "hammer2: rsaenc: key files must end "
308 "in .pub or .prv\n");
309 ecode = 1;
310 goto done;
311 }
312 if (i == 0)
313 blksize = RSA_size(keys[i]);
314 else
315 assert(blksize == RSA_size(keys[i]));
316 }
317
318 /*
319 *
320 */
321 data_in = malloc(blksize);
322 data_out = malloc(blksize);
323 off = 0;
324 while ((n = read(0, data_in + off, blksize - off)) > 0) {
325 off += n;
326 if (off == blksize) {
327 for (i = 0; i < nkeys; ++i) {
328 if (ispub[i])
329 RSA_public_decrypt(blksize,
330 data_in, data_out,
331 keys[i],
332 RSA_NO_PADDING);
333 else
334 RSA_private_decrypt(blksize,
335 data_in, data_out,
336 keys[i],
337 RSA_NO_PADDING);
338 if (i + 1 != nkeys)
339 bcopy(data_out, data_in, blksize);
340 }
341 if (write(1, data_out, blksize) != blksize) {
342 perror("write");
343 ecode = 1;
344 break;
345 }
346 off = 0;
347 }
348 }
349 if (off) {
350 if (off < blksize)
351 bzero(data_in + off, blksize - off);
352 for (i = 0; i < nkeys; ++i) {
353 if (ispub[i])
354 RSA_public_decrypt(blksize,
355 data_in, data_out,
356 keys[i],
357 RSA_NO_PADDING);
358 else
359 RSA_private_decrypt(blksize,
360 data_in, data_out,
361 keys[i],
362 RSA_NO_PADDING);
363 if (i + 1 != nkeys)
364 bcopy(data_out, data_in, blksize);
365 }
366 if (write(1, data_out, blksize) != blksize) {
367 perror("write");
368 ecode = 1;
369 }
370 }
371 if (n < 0) {
372 perror("read");
373 ecode = 1;
374 }
375 free(data_out);
376 free(data_in);
377done:
378 for (i = 0; i < nkeys; ++i) {
379 if (keys[i])
380 RSA_free(keys[i]);
381 }
382 free(keys);
383 free(ispub);
384 return (ecode);
385}