OLD | NEW |
| (Empty) |
1 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | |
2 * project 2006. | |
3 */ | |
4 /* ==================================================================== | |
5 * Copyright (c) 2006 The OpenSSL Project. All rights reserved. | |
6 * | |
7 * Redistribution and use in source and binary forms, with or without | |
8 * modification, are permitted provided that the following conditions | |
9 * are met: | |
10 * | |
11 * 1. Redistributions of source code must retain the above copyright | |
12 * notice, this list of conditions and the following disclaimer. | |
13 * | |
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 * | |
19 * 3. All advertising materials mentioning features or use of this | |
20 * software must display the following acknowledgment: | |
21 * "This product includes software developed by the OpenSSL Project | |
22 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |
23 * | |
24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
25 * endorse or promote products derived from this software without | |
26 * prior written permission. For written permission, please contact | |
27 * licensing@OpenSSL.org. | |
28 * | |
29 * 5. Products derived from this software may not be called "OpenSSL" | |
30 * nor may "OpenSSL" appear in their names without prior written | |
31 * permission of the OpenSSL Project. | |
32 * | |
33 * 6. Redistributions of any form whatsoever must retain the following | |
34 * acknowledgment: | |
35 * "This product includes software developed by the OpenSSL Project | |
36 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |
37 * | |
38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
49 * OF THE POSSIBILITY OF SUCH DAMAGE. | |
50 * ==================================================================== | |
51 * | |
52 * This product includes cryptographic software written by Eric Young | |
53 * (eay@cryptsoft.com). This product includes software written by Tim | |
54 * Hudson (tjh@cryptsoft.com). | |
55 * | |
56 */ | |
57 | |
58 | |
59 #include "apps.h" | |
60 #include <string.h> | |
61 #include <openssl/err.h> | |
62 #include <openssl/pem.h> | |
63 #include <openssl/evp.h> | |
64 | |
65 #define KEY_PRIVKEY 1 | |
66 #define KEY_PUBKEY 2 | |
67 #define KEY_CERT 3 | |
68 | |
69 static void usage(void); | |
70 | |
71 #undef PROG | |
72 | |
73 #define PROG pkeyutl_main | |
74 | |
75 static EVP_PKEY_CTX *init_ctx(int *pkeysize, | |
76 char *keyfile, int keyform, int key_type, | |
77 char *passargin, int pkey_op, ENGINE *e); | |
78 | |
79 static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform, | |
80 const char *file); | |
81 | |
82 static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, | |
83 unsigned char *out, size_t *poutlen, | |
84 unsigned char *in, size_t inlen); | |
85 | |
86 int MAIN(int argc, char **); | |
87 | |
88 int MAIN(int argc, char **argv) | |
89 { | |
90 BIO *in = NULL, *out = NULL; | |
91 char *infile = NULL, *outfile = NULL, *sigfile = NULL; | |
92 ENGINE *e = NULL; | |
93 int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY; | |
94 int keyform = FORMAT_PEM, peerform = FORMAT_PEM; | |
95 char badarg = 0, rev = 0; | |
96 char hexdump = 0, asn1parse = 0; | |
97 EVP_PKEY_CTX *ctx = NULL; | |
98 char *passargin = NULL; | |
99 int keysize = -1; | |
100 | |
101 unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; | |
102 size_t buf_outlen; | |
103 int buf_inlen = 0, siglen = -1; | |
104 | |
105 int ret = 1, rv = -1; | |
106 | |
107 argc--; | |
108 argv++; | |
109 | |
110 if(!bio_err) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); | |
111 | |
112 if (!load_config(bio_err, NULL)) | |
113 goto end; | |
114 ERR_load_crypto_strings(); | |
115 OpenSSL_add_all_algorithms(); | |
116 | |
117 while(argc >= 1) | |
118 { | |
119 if (!strcmp(*argv,"-in")) | |
120 { | |
121 if (--argc < 1) badarg = 1; | |
122 else infile= *(++argv); | |
123 } | |
124 else if (!strcmp(*argv,"-out")) | |
125 { | |
126 if (--argc < 1) badarg = 1; | |
127 else outfile= *(++argv); | |
128 } | |
129 else if (!strcmp(*argv,"-sigfile")) | |
130 { | |
131 if (--argc < 1) badarg = 1; | |
132 else sigfile= *(++argv); | |
133 } | |
134 else if(!strcmp(*argv, "-inkey")) | |
135 { | |
136 if (--argc < 1) | |
137 badarg = 1; | |
138 else | |
139 { | |
140 ctx = init_ctx(&keysize, | |
141 *(++argv), keyform, key_type, | |
142 passargin, pkey_op, e); | |
143 if (!ctx) | |
144 { | |
145 BIO_puts(bio_err, | |
146 "Error initializing context\n"); | |
147 ERR_print_errors(bio_err); | |
148 badarg = 1; | |
149 } | |
150 } | |
151 } | |
152 else if (!strcmp(*argv,"-peerkey")) | |
153 { | |
154 if (--argc < 1) | |
155 badarg = 1; | |
156 else if (!setup_peer(bio_err, ctx, peerform, *(++argv))) | |
157 badarg = 1; | |
158 } | |
159 else if (!strcmp(*argv,"-passin")) | |
160 { | |
161 if (--argc < 1) badarg = 1; | |
162 else passargin= *(++argv); | |
163 } | |
164 else if (strcmp(*argv,"-peerform") == 0) | |
165 { | |
166 if (--argc < 1) badarg = 1; | |
167 else peerform=str2fmt(*(++argv)); | |
168 } | |
169 else if (strcmp(*argv,"-keyform") == 0) | |
170 { | |
171 if (--argc < 1) badarg = 1; | |
172 else keyform=str2fmt(*(++argv)); | |
173 } | |
174 #ifndef OPENSSL_NO_ENGINE | |
175 else if(!strcmp(*argv, "-engine")) | |
176 { | |
177 if (--argc < 1) | |
178 badarg = 1; | |
179 else | |
180 e = setup_engine(bio_err, *(++argv), 0); | |
181 } | |
182 #endif | |
183 else if(!strcmp(*argv, "-pubin")) | |
184 key_type = KEY_PUBKEY; | |
185 else if(!strcmp(*argv, "-certin")) | |
186 key_type = KEY_CERT; | |
187 else if(!strcmp(*argv, "-asn1parse")) | |
188 asn1parse = 1; | |
189 else if(!strcmp(*argv, "-hexdump")) | |
190 hexdump = 1; | |
191 else if(!strcmp(*argv, "-sign")) | |
192 pkey_op = EVP_PKEY_OP_SIGN; | |
193 else if(!strcmp(*argv, "-verify")) | |
194 pkey_op = EVP_PKEY_OP_VERIFY; | |
195 else if(!strcmp(*argv, "-verifyrecover")) | |
196 pkey_op = EVP_PKEY_OP_VERIFYRECOVER; | |
197 else if(!strcmp(*argv, "-rev")) | |
198 rev = 1; | |
199 else if(!strcmp(*argv, "-encrypt")) | |
200 pkey_op = EVP_PKEY_OP_ENCRYPT; | |
201 else if(!strcmp(*argv, "-decrypt")) | |
202 pkey_op = EVP_PKEY_OP_DECRYPT; | |
203 else if(!strcmp(*argv, "-derive")) | |
204 pkey_op = EVP_PKEY_OP_DERIVE; | |
205 else if (strcmp(*argv,"-pkeyopt") == 0) | |
206 { | |
207 if (--argc < 1) | |
208 badarg = 1; | |
209 else if (!ctx) | |
210 { | |
211 BIO_puts(bio_err, | |
212 "-pkeyopt command before -inkey\n"); | |
213 badarg = 1; | |
214 } | |
215 else if (pkey_ctrl_string(ctx, *(++argv)) <= 0) | |
216 { | |
217 BIO_puts(bio_err, "parameter setting error\n"); | |
218 ERR_print_errors(bio_err); | |
219 goto end; | |
220 } | |
221 } | |
222 else badarg = 1; | |
223 if(badarg) | |
224 { | |
225 usage(); | |
226 goto end; | |
227 } | |
228 argc--; | |
229 argv++; | |
230 } | |
231 | |
232 if (!ctx) | |
233 { | |
234 usage(); | |
235 goto end; | |
236 } | |
237 | |
238 if (sigfile && (pkey_op != EVP_PKEY_OP_VERIFY)) | |
239 { | |
240 BIO_puts(bio_err, "Signature file specified for non verify\n"); | |
241 goto end; | |
242 } | |
243 | |
244 if (!sigfile && (pkey_op == EVP_PKEY_OP_VERIFY)) | |
245 { | |
246 BIO_puts(bio_err, "No signature file specified for verify\n"); | |
247 goto end; | |
248 } | |
249 | |
250 /* FIXME: seed PRNG only if needed */ | |
251 app_RAND_load_file(NULL, bio_err, 0); | |
252 | |
253 if (pkey_op != EVP_PKEY_OP_DERIVE) | |
254 { | |
255 if(infile) | |
256 { | |
257 if(!(in = BIO_new_file(infile, "rb"))) | |
258 { | |
259 BIO_puts(bio_err, | |
260 "Error Opening Input File\n"); | |
261 ERR_print_errors(bio_err); | |
262 goto end; | |
263 } | |
264 } | |
265 else | |
266 in = BIO_new_fp(stdin, BIO_NOCLOSE); | |
267 } | |
268 | |
269 if(outfile) | |
270 { | |
271 if(!(out = BIO_new_file(outfile, "wb"))) | |
272 { | |
273 BIO_printf(bio_err, "Error Creating Output File\n"); | |
274 ERR_print_errors(bio_err); | |
275 goto end; | |
276 } | |
277 } | |
278 else | |
279 { | |
280 out = BIO_new_fp(stdout, BIO_NOCLOSE); | |
281 #ifdef OPENSSL_SYS_VMS | |
282 { | |
283 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); | |
284 out = BIO_push(tmpbio, out); | |
285 } | |
286 #endif | |
287 } | |
288 | |
289 if (sigfile) | |
290 { | |
291 BIO *sigbio = BIO_new_file(sigfile, "rb"); | |
292 if (!sigbio) | |
293 { | |
294 BIO_printf(bio_err, "Can't open signature file %s\n", | |
295 sigfile); | |
296 goto end; | |
297 } | |
298 siglen = bio_to_mem(&sig, keysize * 10, sigbio); | |
299 BIO_free(sigbio); | |
300 if (siglen <= 0) | |
301 { | |
302 BIO_printf(bio_err, "Error reading signature data\n"); | |
303 goto end; | |
304 } | |
305 } | |
306 | |
307 if (in) | |
308 { | |
309 /* Read the input data */ | |
310 buf_inlen = bio_to_mem(&buf_in, keysize * 10, in); | |
311 if(buf_inlen <= 0) | |
312 { | |
313 BIO_printf(bio_err, "Error reading input Data\n"); | |
314 exit(1); | |
315 } | |
316 if(rev) | |
317 { | |
318 size_t i; | |
319 unsigned char ctmp; | |
320 size_t l = (size_t)buf_inlen; | |
321 for(i = 0; i < l/2; i++) | |
322 { | |
323 ctmp = buf_in[i]; | |
324 buf_in[i] = buf_in[l - 1 - i]; | |
325 buf_in[l - 1 - i] = ctmp; | |
326 } | |
327 } | |
328 } | |
329 | |
330 if(pkey_op == EVP_PKEY_OP_VERIFY) | |
331 { | |
332 rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen, | |
333 buf_in, (size_t)buf_inlen); | |
334 if (rv == 0) | |
335 BIO_puts(out, "Signature Verification Failure\n"); | |
336 else if (rv == 1) | |
337 BIO_puts(out, "Signature Verified Successfully\n"); | |
338 if (rv >= 0) | |
339 goto end; | |
340 } | |
341 else | |
342 { | |
343 rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, | |
344 buf_in, (size_t)buf_inlen); | |
345 if (rv > 0) | |
346 { | |
347 buf_out = OPENSSL_malloc(buf_outlen); | |
348 if (!buf_out) | |
349 rv = -1; | |
350 else | |
351 rv = do_keyop(ctx, pkey_op, | |
352 buf_out, (size_t *)&buf_outlen, | |
353 buf_in, (size_t)buf_inlen); | |
354 } | |
355 } | |
356 | |
357 if(rv <= 0) | |
358 { | |
359 BIO_printf(bio_err, "Public Key operation error\n"); | |
360 ERR_print_errors(bio_err); | |
361 goto end; | |
362 } | |
363 ret = 0; | |
364 if(asn1parse) | |
365 { | |
366 if(!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1)) | |
367 ERR_print_errors(bio_err); | |
368 } | |
369 else if(hexdump) | |
370 BIO_dump(out, (char *)buf_out, buf_outlen); | |
371 else | |
372 BIO_write(out, buf_out, buf_outlen); | |
373 | |
374 end: | |
375 if (ctx) | |
376 EVP_PKEY_CTX_free(ctx); | |
377 BIO_free(in); | |
378 BIO_free_all(out); | |
379 if (buf_in) | |
380 OPENSSL_free(buf_in); | |
381 if (buf_out) | |
382 OPENSSL_free(buf_out); | |
383 if (sig) | |
384 OPENSSL_free(sig); | |
385 return ret; | |
386 } | |
387 | |
388 static void usage() | |
389 { | |
390 BIO_printf(bio_err, "Usage: pkeyutl [options]\n"); | |
391 BIO_printf(bio_err, "-in file input file\n"); | |
392 BIO_printf(bio_err, "-out file output file\n"); | |
393 BIO_printf(bio_err, "-sigfile file signature file (verify operation only
)\n"); | |
394 BIO_printf(bio_err, "-inkey file input key\n"); | |
395 BIO_printf(bio_err, "-keyform arg private key format - default PEM\n"
); | |
396 BIO_printf(bio_err, "-pubin input is a public key\n"); | |
397 BIO_printf(bio_err, "-certin input is a certificate carrying a p
ublic key\n"); | |
398 BIO_printf(bio_err, "-pkeyopt X:Y public key options\n"); | |
399 BIO_printf(bio_err, "-sign sign with private key\n"); | |
400 BIO_printf(bio_err, "-verify verify with public key\n"); | |
401 BIO_printf(bio_err, "-verifyrecover verify with public key, recover ori
ginal data\n"); | |
402 BIO_printf(bio_err, "-encrypt encrypt with public key\n"); | |
403 BIO_printf(bio_err, "-decrypt decrypt with private key\n"); | |
404 BIO_printf(bio_err, "-derive derive shared secret\n"); | |
405 BIO_printf(bio_err, "-hexdump hex dump output\n"); | |
406 #ifndef OPENSSL_NO_ENGINE | |
407 BIO_printf(bio_err, "-engine e use engine e, possibly a hardware d
evice.\n"); | |
408 #endif | |
409 BIO_printf(bio_err, "-passin arg pass phrase source\n"); | |
410 | |
411 } | |
412 | |
413 static EVP_PKEY_CTX *init_ctx(int *pkeysize, | |
414 char *keyfile, int keyform, int key_type, | |
415 char *passargin, int pkey_op, ENGINE *e) | |
416 { | |
417 EVP_PKEY *pkey = NULL; | |
418 EVP_PKEY_CTX *ctx = NULL; | |
419 char *passin = NULL; | |
420 int rv = -1; | |
421 X509 *x; | |
422 if(((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) | |
423 || (pkey_op == EVP_PKEY_OP_DERIVE)) | |
424 && (key_type != KEY_PRIVKEY)) | |
425 { | |
426 BIO_printf(bio_err, "A private key is needed for this operation\
n"); | |
427 goto end; | |
428 } | |
429 if(!app_passwd(bio_err, passargin, NULL, &passin, NULL)) | |
430 { | |
431 BIO_printf(bio_err, "Error getting password\n"); | |
432 goto end; | |
433 } | |
434 switch(key_type) | |
435 { | |
436 case KEY_PRIVKEY: | |
437 pkey = load_key(bio_err, keyfile, keyform, 0, | |
438 passin, e, "Private Key"); | |
439 break; | |
440 | |
441 case KEY_PUBKEY: | |
442 pkey = load_pubkey(bio_err, keyfile, keyform, 0, | |
443 NULL, e, "Public Key"); | |
444 break; | |
445 | |
446 case KEY_CERT: | |
447 x = load_cert(bio_err, keyfile, keyform, | |
448 NULL, e, "Certificate"); | |
449 if(x) | |
450 { | |
451 pkey = X509_get_pubkey(x); | |
452 X509_free(x); | |
453 } | |
454 break; | |
455 | |
456 } | |
457 | |
458 *pkeysize = EVP_PKEY_size(pkey); | |
459 | |
460 if (!pkey) | |
461 goto end; | |
462 | |
463 ctx = EVP_PKEY_CTX_new(pkey, e); | |
464 | |
465 EVP_PKEY_free(pkey); | |
466 | |
467 if (!ctx) | |
468 goto end; | |
469 | |
470 switch(pkey_op) | |
471 { | |
472 case EVP_PKEY_OP_SIGN: | |
473 rv = EVP_PKEY_sign_init(ctx); | |
474 break; | |
475 | |
476 case EVP_PKEY_OP_VERIFY: | |
477 rv = EVP_PKEY_verify_init(ctx); | |
478 break; | |
479 | |
480 case EVP_PKEY_OP_VERIFYRECOVER: | |
481 rv = EVP_PKEY_verify_recover_init(ctx); | |
482 break; | |
483 | |
484 case EVP_PKEY_OP_ENCRYPT: | |
485 rv = EVP_PKEY_encrypt_init(ctx); | |
486 break; | |
487 | |
488 case EVP_PKEY_OP_DECRYPT: | |
489 rv = EVP_PKEY_decrypt_init(ctx); | |
490 break; | |
491 | |
492 case EVP_PKEY_OP_DERIVE: | |
493 rv = EVP_PKEY_derive_init(ctx); | |
494 break; | |
495 } | |
496 | |
497 if (rv <= 0) | |
498 { | |
499 EVP_PKEY_CTX_free(ctx); | |
500 ctx = NULL; | |
501 } | |
502 | |
503 end: | |
504 | |
505 if (passin) | |
506 OPENSSL_free(passin); | |
507 | |
508 return ctx; | |
509 | |
510 | |
511 } | |
512 | |
513 static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform, | |
514 const char *file) | |
515 { | |
516 EVP_PKEY *peer = NULL; | |
517 int ret; | |
518 if (!ctx) | |
519 { | |
520 BIO_puts(err, "-peerkey command before -inkey\n"); | |
521 return 0; | |
522 } | |
523 | |
524 peer = load_pubkey(bio_err, file, peerform, 0, NULL, NULL, "Peer Key"); | |
525 | |
526 if (!peer) | |
527 { | |
528 BIO_printf(bio_err, "Error reading peer key %s\n", file); | |
529 ERR_print_errors(err); | |
530 return 0; | |
531 } | |
532 | |
533 ret = EVP_PKEY_derive_set_peer(ctx, peer); | |
534 | |
535 EVP_PKEY_free(peer); | |
536 if (ret <= 0) | |
537 ERR_print_errors(err); | |
538 return ret; | |
539 } | |
540 | |
541 static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, | |
542 unsigned char *out, size_t *poutlen, | |
543 unsigned char *in, size_t inlen) | |
544 { | |
545 int rv = 0; | |
546 switch(pkey_op) | |
547 { | |
548 case EVP_PKEY_OP_VERIFYRECOVER: | |
549 rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen); | |
550 break; | |
551 | |
552 case EVP_PKEY_OP_SIGN: | |
553 rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen); | |
554 break; | |
555 | |
556 case EVP_PKEY_OP_ENCRYPT: | |
557 rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen); | |
558 break; | |
559 | |
560 case EVP_PKEY_OP_DECRYPT: | |
561 rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen); | |
562 break; | |
563 | |
564 case EVP_PKEY_OP_DERIVE: | |
565 rv = EVP_PKEY_derive(ctx, out, poutlen); | |
566 break; | |
567 | |
568 } | |
569 return rv; | |
570 } | |
OLD | NEW |