82b59a805c596f76f0bf97af56ca7b40c71375e8
[openssl.git] / apps / pkeyutl.c
1 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) 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, char *engine);
78
79 int MAIN(int argc, char **);
80
81 int MAIN(int argc, char **argv)
82 {
83         BIO *in = NULL, *out = NULL;
84         char *infile = NULL, *outfile = NULL, *sigfile = NULL;
85         char *engine = NULL;
86         int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
87         int keyform = FORMAT_PEM;
88         char badarg = 0, rev = 0;
89         char hexdump = 0, asn1parse = 0;
90         EVP_PKEY_CTX *ctx = NULL;
91         char *passargin = NULL;
92         int keysize = -1;
93
94         unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
95         int buf_inlen, buf_outlen, siglen = -1;
96
97         int ret = 1, rv = -1;
98
99         argc--;
100         argv++;
101
102         if(!bio_err) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
103
104         if (!load_config(bio_err, NULL))
105                 goto end;
106         ERR_load_crypto_strings();
107         OpenSSL_add_all_algorithms();
108         
109         while(argc >= 1)
110                 {
111                 if (!strcmp(*argv,"-in"))
112                         {
113                         if (--argc < 1) badarg = 1;
114                         infile= *(++argv);
115                         }
116                 else if (!strcmp(*argv,"-out"))
117                         {
118                         if (--argc < 1) badarg = 1;
119                         outfile= *(++argv);
120                         }
121                 else if (!strcmp(*argv,"-sigfile"))
122                         {
123                         if (--argc < 1) badarg = 1;
124                         sigfile= *(++argv);
125                         }
126                 else if(!strcmp(*argv, "-inkey"))
127                         {
128                         if (--argc < 1)
129                                 badarg = 1;
130                         else
131                                 {
132                                 ctx = init_ctx(&keysize,
133                                                 *(++argv), keyform, key_type,
134                                                 passargin, pkey_op, engine);
135                                 if (!ctx)
136                                         {
137                                         BIO_puts(bio_err,
138                                                 "Error initializing context\n");
139                                         ERR_print_errors(bio_err);
140                                         badarg = 1;
141                                         }
142                                 }
143                         }
144                 else if (!strcmp(*argv,"-passin"))
145                         {
146                         if (--argc < 1) badarg = 1;
147                         passargin= *(++argv);
148                         }
149                 else if (strcmp(*argv,"-keyform") == 0)
150                         {
151                         if (--argc < 1) badarg = 1;
152                         keyform=str2fmt(*(++argv));
153                         }
154 #ifndef OPENSSL_NO_ENGINE
155                 else if(!strcmp(*argv, "-engine"))
156                         {
157                         if (--argc < 1)
158                                 badarg = 1;
159                         else
160                                 engine = *(++argv);
161                         }
162 #endif
163                 else if(!strcmp(*argv, "-pubin"))
164                         key_type = KEY_PUBKEY;
165                 else if(!strcmp(*argv, "-certin"))
166                         key_type = KEY_CERT;
167                 else if(!strcmp(*argv, "-asn1parse"))
168                         asn1parse = 1;
169                 else if(!strcmp(*argv, "-hexdump"))
170                         hexdump = 1;
171                 else if(!strcmp(*argv, "-sign"))
172                         pkey_op = EVP_PKEY_OP_SIGN;
173                 else if(!strcmp(*argv, "-verify"))
174                         pkey_op = EVP_PKEY_OP_VERIFY;
175                 else if(!strcmp(*argv, "-verifyrecover"))
176                         pkey_op = EVP_PKEY_OP_VERIFYRECOVER;
177                 else if(!strcmp(*argv, "-rev"))
178                         rev = 1;
179                 else if(!strcmp(*argv, "-encrypt"))
180                         pkey_op = EVP_PKEY_OP_ENCRYPT;
181                 else if(!strcmp(*argv, "-decrypt"))
182                         pkey_op = EVP_PKEY_OP_DECRYPT;
183                 else if (strcmp(*argv,"-param") == 0)
184                         {
185                         if (--argc < 1)
186                                 badarg = 1;
187                         if (!ctx)
188                                 {
189                                 BIO_puts(bio_err,
190                                         "-param command before -inkey\n");
191                                 badarg = 1;
192                                 }
193                         else if (pkey_ctrl_string(ctx, *(++argv)) <= 0)
194                                 {
195                                 BIO_puts(bio_err, "parameter setting error\n");
196                                 ERR_print_errors(bio_err);
197                                 goto end;
198                                 }
199                         }
200                 else badarg = 1;
201                 if(badarg)
202                         {
203                         usage();
204                         goto end;
205                         }
206                 argc--;
207                 argv++;
208                 }
209
210         if (!ctx)
211                 {
212                 usage();
213                 goto end;
214                 }
215
216         if (sigfile && (pkey_op != EVP_PKEY_OP_VERIFY))
217                 {
218                 BIO_puts(bio_err, "Signature file specified for non verify\n");
219                 goto end;
220                 }
221
222         if (!sigfile && (pkey_op == EVP_PKEY_OP_VERIFY))
223                 {
224                 BIO_puts(bio_err, "No signature file specified for verify\n");
225                 goto end;
226                 }
227
228 /* FIXME: seed PRNG only if needed */
229         app_RAND_load_file(NULL, bio_err, 0);
230
231         if(infile)
232                 {
233                 if(!(in = BIO_new_file(infile, "rb")))
234                         {
235                         BIO_printf(bio_err, "Error Reading Input File\n");
236                         ERR_print_errors(bio_err);      
237                         goto end;
238                         }
239                 }
240         else
241                 in = BIO_new_fp(stdin, BIO_NOCLOSE);
242
243         if(outfile)
244                 {
245                 if(!(out = BIO_new_file(outfile, "wb")))
246                         {
247                         BIO_printf(bio_err, "Error Creating Output File\n");
248                         ERR_print_errors(bio_err);      
249                         goto end;
250                         }
251                 }
252         else
253                 {
254                 out = BIO_new_fp(stdout, BIO_NOCLOSE);
255 #ifdef OPENSSL_SYS_VMS
256                 {
257                     BIO *tmpbio = BIO_new(BIO_f_linebuffer());
258                     out = BIO_push(tmpbio, out);
259                 }
260 #endif
261         }
262
263         if (sigfile)
264                 {
265                 BIO *sigbio = BIO_new_file(sigfile, "rb");
266                 if (!sigbio)
267                         {
268                         BIO_printf(bio_err, "Can't open signature file %s\n",
269                                                                 sigfile);
270                         goto end;
271                         }
272                 siglen = bio_to_mem(&sig, keysize * 10, sigbio);
273                 BIO_free(sigbio);
274                 if (siglen <= 0)
275                         {
276                         BIO_printf(bio_err, "Error reading signature data\n");
277                         goto end;
278                         }
279                 }
280         
281         buf_out = OPENSSL_malloc(keysize);
282
283         /* Read the input data */
284         buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
285         if(buf_inlen <= 0)
286                 {
287                 BIO_printf(bio_err, "Error reading input Data\n");
288                 exit(1);
289                 }
290         if(rev)
291                 {
292                 int i;
293                 unsigned char ctmp;
294                 for(i = 0; i < buf_inlen/2; i++)
295                         {
296                         ctmp = buf_in[i];
297                         buf_in[i] = buf_in[buf_inlen - 1 - i];
298                         buf_in[buf_inlen - 1 - i] = ctmp;
299                         }
300                 }
301         switch(pkey_op)
302                 {
303                 case EVP_PKEY_OP_VERIFYRECOVER:
304                 rv  = EVP_PKEY_verify_recover(ctx, buf_out, &buf_outlen,
305                                                         buf_in, buf_inlen);
306                 break;
307
308                 case EVP_PKEY_OP_SIGN:
309                 rv  = EVP_PKEY_sign(ctx, buf_out, &buf_outlen,
310                                                         buf_in, buf_inlen);
311                 break;
312
313                 case EVP_PKEY_OP_ENCRYPT:
314                 rv  = EVP_PKEY_encrypt(ctx, buf_out, &buf_outlen,
315                                                         buf_in, buf_inlen);
316                 break;
317
318                 case EVP_PKEY_OP_DECRYPT:
319                 rv  = EVP_PKEY_decrypt(ctx, buf_out, &buf_outlen,
320                                                         buf_in, buf_inlen);
321                 break; 
322
323                 case EVP_PKEY_OP_VERIFY:
324                 rv  = EVP_PKEY_verify(ctx, sig, siglen, buf_in, buf_inlen);
325                 if (rv == 0)
326                         BIO_puts(out, "Signature Verification Failure\n");
327                 else if (rv == 1)
328                         BIO_puts(out, "Signature Verified Successfully\n");
329                 if (rv >= 0)
330                         goto end;
331                 break; 
332
333                 }
334
335         if(rv <= 0)
336                 {
337                 BIO_printf(bio_err, "Public Key operation error\n");
338                 ERR_print_errors(bio_err);
339                 goto end;
340                 }
341         ret = 0;
342         if(asn1parse)
343                 {
344                 if(!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
345                         ERR_print_errors(bio_err);
346                 }
347         else if(hexdump)
348                 BIO_dump(out, (char *)buf_out, buf_outlen);
349         else
350                 BIO_write(out, buf_out, buf_outlen);
351
352         end:
353         if (ctx)
354                 EVP_PKEY_CTX_free(ctx);
355         BIO_free(in);
356         BIO_free_all(out);
357         if (buf_in)
358                 OPENSSL_free(buf_in);
359         if (buf_out)
360                 OPENSSL_free(buf_out);
361         if (sig)
362                 OPENSSL_free(sig);
363         return ret;
364 }
365
366 static void usage()
367 {
368         BIO_printf(bio_err, "Usage: pkeyutl [options]\n");
369         BIO_printf(bio_err, "-in file        input file\n");
370         BIO_printf(bio_err, "-out file       output file\n");
371         BIO_printf(bio_err, "-inkey file     input key\n");
372         BIO_printf(bio_err, "-keyform arg    private key format - default PEM\n");
373         BIO_printf(bio_err, "-pubin          input is an RSA public\n");
374         BIO_printf(bio_err, "-certin         input is a certificate carrying an RSA public key\n");
375         BIO_printf(bio_err, "-ctrl X:Y       control parameters\n");
376         BIO_printf(bio_err, "-sign           sign with private key\n");
377         BIO_printf(bio_err, "-verify         verify with public key\n");
378         BIO_printf(bio_err, "-encrypt        encrypt with public key\n");
379         BIO_printf(bio_err, "-decrypt        decrypt with private key\n");
380         BIO_printf(bio_err, "-hexdump        hex dump output\n");
381 #ifndef OPENSSL_NO_ENGINE
382         BIO_printf(bio_err, "-engine e       use engine e, possibly a hardware device.\n");
383         BIO_printf(bio_err, "-passin arg     pass phrase source\n");
384 #endif
385
386 }
387
388 static EVP_PKEY_CTX *init_ctx(int *pkeysize,
389                                 char *keyfile, int keyform, int key_type,
390                                 char *passargin, int pkey_op, char *engine)
391         {
392         ENGINE *e = NULL;
393         EVP_PKEY *pkey = NULL;
394         EVP_PKEY_CTX *ctx = NULL;
395         char *passin = NULL;
396         int rv = -1;
397         X509 *x;
398         if(((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT))
399                 && (key_type != KEY_PRIVKEY))
400                 {
401                 BIO_printf(bio_err, "A private key is needed for this operation\n");
402                 goto end;
403                 }
404         if(!app_passwd(bio_err, passargin, NULL, &passin, NULL))
405                 {
406                 BIO_printf(bio_err, "Error getting password\n");
407                 goto end;
408                 }
409         switch(key_type)
410                 {
411                 case KEY_PRIVKEY:
412                 pkey = load_key(bio_err, keyfile, keyform, 0,
413                         passin, e, "Private Key");
414                 break;
415
416                 case KEY_PUBKEY:
417                 pkey = load_pubkey(bio_err, keyfile, keyform, 0,
418                         NULL, e, "Public Key");
419                 break;
420
421                 case KEY_CERT:
422                 x = load_cert(bio_err, keyfile, keyform,
423                         NULL, e, "Certificate");
424                 if(x)
425                         {
426                         pkey = X509_get_pubkey(x);
427                         X509_free(x);
428                         }
429                 break;
430
431                 }
432
433         *pkeysize = EVP_PKEY_size(pkey);
434
435         if (!pkey)
436                 goto end;
437
438         ctx = EVP_PKEY_CTX_new(pkey);
439
440         EVP_PKEY_free(pkey);
441
442         if (!ctx)
443                 goto end;
444
445         switch(pkey_op)
446                 {
447                 case EVP_PKEY_OP_SIGN:
448                 rv = EVP_PKEY_sign_init(ctx);
449                 break;
450
451                 case EVP_PKEY_OP_VERIFY:
452                 rv = EVP_PKEY_verify_init(ctx);
453                 break;
454
455                 case EVP_PKEY_OP_VERIFYRECOVER:
456                 rv = EVP_PKEY_verify_recover_init(ctx);
457                 break;
458
459                 case EVP_PKEY_OP_ENCRYPT:
460                 rv = EVP_PKEY_encrypt_init(ctx);
461                 break;
462
463                 case EVP_PKEY_OP_DECRYPT:
464                 rv = EVP_PKEY_decrypt_init(ctx);
465                 break;
466                 }
467
468         if (rv <= 0)
469                 {
470                 EVP_PKEY_CTX_free(ctx);
471                 ctx = NULL;
472                 }
473
474         end:
475
476         if (passin)
477                 OPENSSL_free(passin);
478
479         return ctx;
480
481
482         }
483