OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
pkeyutl.c
Go to the documentation of this file.
1 /* Written by Dr Stephen N Henson ([email protected]) 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
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  * ([email protected]). This product includes software written by Tim
54  * Hudson ([email protected]).
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;
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  {
146  "Error initializing context\n");
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  {
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");
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  {
260  "Error Opening Input File\n");
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");
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");
361  goto end;
362  }
363  ret = 0;
364  if(asn1parse)
365  {
366  if(!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
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 public 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 original 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 device.\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 
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  {
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  }