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