Home | History | Annotate | Line # | Download | only in apps
rsautl.c revision 1.1.1.1
      1 /* rsautl.c */
      2 /*
      3  * Written by Dr Stephen N Henson (steve (at) openssl.org) for the OpenSSL project
      4  * 2000.
      5  */
      6 /* ====================================================================
      7  * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  *
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  *
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in
     18  *    the documentation and/or other materials provided with the
     19  *    distribution.
     20  *
     21  * 3. All advertising materials mentioning features or use of this
     22  *    software must display the following acknowledgment:
     23  *    "This product includes software developed by the OpenSSL Project
     24  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
     25  *
     26  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     27  *    endorse or promote products derived from this software without
     28  *    prior written permission. For written permission, please contact
     29  *    licensing (at) OpenSSL.org.
     30  *
     31  * 5. Products derived from this software may not be called "OpenSSL"
     32  *    nor may "OpenSSL" appear in their names without prior written
     33  *    permission of the OpenSSL Project.
     34  *
     35  * 6. Redistributions of any form whatsoever must retain the following
     36  *    acknowledgment:
     37  *    "This product includes software developed by the OpenSSL Project
     38  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
     39  *
     40  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     41  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     47  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     51  * OF THE POSSIBILITY OF SUCH DAMAGE.
     52  * ====================================================================
     53  *
     54  * This product includes cryptographic software written by Eric Young
     55  * (eay (at) cryptsoft.com).  This product includes software written by Tim
     56  * Hudson (tjh (at) cryptsoft.com).
     57  *
     58  */
     59 
     60 #include <openssl/opensslconf.h>
     61 #ifndef OPENSSL_NO_RSA
     62 
     63 # include "apps.h"
     64 # include <string.h>
     65 # include <openssl/err.h>
     66 # include <openssl/pem.h>
     67 # include <openssl/rsa.h>
     68 
     69 # define RSA_SIGN        1
     70 # define RSA_VERIFY      2
     71 # define RSA_ENCRYPT     3
     72 # define RSA_DECRYPT     4
     73 
     74 # define KEY_PRIVKEY     1
     75 # define KEY_PUBKEY      2
     76 # define KEY_CERT        3
     77 
     78 static void usage(void);
     79 
     80 # undef PROG
     81 
     82 # define PROG rsautl_main
     83 
     84 int MAIN(int argc, char **);
     85 
     86 int MAIN(int argc, char **argv)
     87 {
     88     ENGINE *e = NULL;
     89     BIO *in = NULL, *out = NULL;
     90     char *infile = NULL, *outfile = NULL;
     91     char *engine = NULL;
     92     char *keyfile = NULL;
     93     char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY;
     94     int keyform = FORMAT_PEM;
     95     char need_priv = 0, badarg = 0, rev = 0;
     96     char hexdump = 0, asn1parse = 0;
     97     X509 *x;
     98     EVP_PKEY *pkey = NULL;
     99     RSA *rsa = NULL;
    100     unsigned char *rsa_in = NULL, *rsa_out = NULL, pad;
    101     char *passargin = NULL, *passin = NULL;
    102     int rsa_inlen, rsa_outlen = 0;
    103     int keysize;
    104 
    105     int ret = 1;
    106 
    107     argc--;
    108     argv++;
    109 
    110     if (!bio_err)
    111         bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
    112 
    113     if (!load_config(bio_err, NULL))
    114         goto end;
    115     ERR_load_crypto_strings();
    116     OpenSSL_add_all_algorithms();
    117     pad = RSA_PKCS1_PADDING;
    118 
    119     while (argc >= 1) {
    120         if (!strcmp(*argv, "-in")) {
    121             if (--argc < 1)
    122                 badarg = 1;
    123             else
    124                 infile = *(++argv);
    125         } else if (!strcmp(*argv, "-out")) {
    126             if (--argc < 1)
    127                 badarg = 1;
    128             else
    129                 outfile = *(++argv);
    130         } else if (!strcmp(*argv, "-inkey")) {
    131             if (--argc < 1)
    132                 badarg = 1;
    133             else
    134                 keyfile = *(++argv);
    135         } else if (!strcmp(*argv, "-passin")) {
    136             if (--argc < 1)
    137                 badarg = 1;
    138             else
    139                 passargin = *(++argv);
    140         } else if (strcmp(*argv, "-keyform") == 0) {
    141             if (--argc < 1)
    142                 badarg = 1;
    143             else
    144                 keyform = str2fmt(*(++argv));
    145 # ifndef OPENSSL_NO_ENGINE
    146         } else if (!strcmp(*argv, "-engine")) {
    147             if (--argc < 1)
    148                 badarg = 1;
    149             else
    150                 engine = *(++argv);
    151 # endif
    152         } else if (!strcmp(*argv, "-pubin")) {
    153             key_type = KEY_PUBKEY;
    154         } else if (!strcmp(*argv, "-certin")) {
    155             key_type = KEY_CERT;
    156         } else if (!strcmp(*argv, "-asn1parse"))
    157             asn1parse = 1;
    158         else if (!strcmp(*argv, "-hexdump"))
    159             hexdump = 1;
    160         else if (!strcmp(*argv, "-raw"))
    161             pad = RSA_NO_PADDING;
    162         else if (!strcmp(*argv, "-oaep"))
    163             pad = RSA_PKCS1_OAEP_PADDING;
    164         else if (!strcmp(*argv, "-ssl"))
    165             pad = RSA_SSLV23_PADDING;
    166         else if (!strcmp(*argv, "-pkcs"))
    167             pad = RSA_PKCS1_PADDING;
    168         else if (!strcmp(*argv, "-x931"))
    169             pad = RSA_X931_PADDING;
    170         else if (!strcmp(*argv, "-sign")) {
    171             rsa_mode = RSA_SIGN;
    172             need_priv = 1;
    173         } else if (!strcmp(*argv, "-verify"))
    174             rsa_mode = RSA_VERIFY;
    175         else if (!strcmp(*argv, "-rev"))
    176             rev = 1;
    177         else if (!strcmp(*argv, "-encrypt"))
    178             rsa_mode = RSA_ENCRYPT;
    179         else if (!strcmp(*argv, "-decrypt")) {
    180             rsa_mode = RSA_DECRYPT;
    181             need_priv = 1;
    182         } else
    183             badarg = 1;
    184         if (badarg) {
    185             usage();
    186             goto end;
    187         }
    188         argc--;
    189         argv++;
    190     }
    191 
    192     if (need_priv && (key_type != KEY_PRIVKEY)) {
    193         BIO_printf(bio_err, "A private key is needed for this operation\n");
    194         goto end;
    195     }
    196     e = setup_engine(bio_err, engine, 0);
    197     if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
    198         BIO_printf(bio_err, "Error getting password\n");
    199         goto end;
    200     }
    201 
    202 /* FIXME: seed PRNG only if needed */
    203     app_RAND_load_file(NULL, bio_err, 0);
    204 
    205     switch (key_type) {
    206     case KEY_PRIVKEY:
    207         pkey = load_key(bio_err, keyfile, keyform, 0,
    208                         passin, e, "Private Key");
    209         break;
    210 
    211     case KEY_PUBKEY:
    212         pkey = load_pubkey(bio_err, keyfile, keyform, 0,
    213                            NULL, e, "Public Key");
    214         break;
    215 
    216     case KEY_CERT:
    217         x = load_cert(bio_err, keyfile, keyform, NULL, e, "Certificate");
    218         if (x) {
    219             pkey = X509_get_pubkey(x);
    220             X509_free(x);
    221         }
    222         break;
    223     }
    224 
    225     if (!pkey) {
    226         return 1;
    227     }
    228 
    229     rsa = EVP_PKEY_get1_RSA(pkey);
    230     EVP_PKEY_free(pkey);
    231 
    232     if (!rsa) {
    233         BIO_printf(bio_err, "Error getting RSA key\n");
    234         ERR_print_errors(bio_err);
    235         goto end;
    236     }
    237 
    238     if (infile) {
    239         if (!(in = BIO_new_file(infile, "rb"))) {
    240             BIO_printf(bio_err, "Error Reading Input File\n");
    241             ERR_print_errors(bio_err);
    242             goto end;
    243         }
    244     } else
    245         in = BIO_new_fp(stdin, BIO_NOCLOSE);
    246 
    247     if (outfile) {
    248         if (!(out = BIO_new_file(outfile, "wb"))) {
    249             BIO_printf(bio_err, "Error Writing Output File\n");
    250             ERR_print_errors(bio_err);
    251             goto end;
    252         }
    253     } else {
    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     keysize = RSA_size(rsa);
    264 
    265     rsa_in = OPENSSL_malloc(keysize * 2);
    266     rsa_out = OPENSSL_malloc(keysize);
    267     if (!rsa_in || !rsa_out) {
    268         BIO_printf(bio_err, "Out of memory\n");
    269         ERR_print_errors(bio_err);
    270         goto end;
    271     }
    272 
    273     /* Read the input data */
    274     rsa_inlen = BIO_read(in, rsa_in, keysize * 2);
    275     if (rsa_inlen < 0) {
    276         BIO_printf(bio_err, "Error reading input Data\n");
    277         exit(1);
    278     }
    279     if (rev) {
    280         int i;
    281         unsigned char ctmp;
    282         for (i = 0; i < rsa_inlen / 2; i++) {
    283             ctmp = rsa_in[i];
    284             rsa_in[i] = rsa_in[rsa_inlen - 1 - i];
    285             rsa_in[rsa_inlen - 1 - i] = ctmp;
    286         }
    287     }
    288     switch (rsa_mode) {
    289 
    290     case RSA_VERIFY:
    291         rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
    292         break;
    293 
    294     case RSA_SIGN:
    295         rsa_outlen =
    296             RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
    297         break;
    298 
    299     case RSA_ENCRYPT:
    300         rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
    301         break;
    302 
    303     case RSA_DECRYPT:
    304         rsa_outlen =
    305             RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
    306         break;
    307 
    308     }
    309 
    310     if (rsa_outlen < 0) {
    311         BIO_printf(bio_err, "RSA operation error\n");
    312         ERR_print_errors(bio_err);
    313         goto end;
    314     }
    315     ret = 0;
    316     if (asn1parse) {
    317         if (!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) {
    318             ERR_print_errors(bio_err);
    319         }
    320     } else if (hexdump)
    321         BIO_dump(out, (char *)rsa_out, rsa_outlen);
    322     else
    323         BIO_write(out, rsa_out, rsa_outlen);
    324  end:
    325     RSA_free(rsa);
    326     release_engine(e);
    327     BIO_free(in);
    328     BIO_free_all(out);
    329     if (rsa_in)
    330         OPENSSL_free(rsa_in);
    331     if (rsa_out)
    332         OPENSSL_free(rsa_out);
    333     if (passin)
    334         OPENSSL_free(passin);
    335     return ret;
    336 }
    337 
    338 static void usage()
    339 {
    340     BIO_printf(bio_err, "Usage: rsautl [options]\n");
    341     BIO_printf(bio_err, "-in file        input file\n");
    342     BIO_printf(bio_err, "-out file       output file\n");
    343     BIO_printf(bio_err, "-inkey file     input key\n");
    344     BIO_printf(bio_err, "-keyform arg    private key format - default PEM\n");
    345     BIO_printf(bio_err, "-pubin          input is an RSA public\n");
    346     BIO_printf(bio_err,
    347                "-certin         input is a certificate carrying an RSA public key\n");
    348     BIO_printf(bio_err, "-ssl            use SSL v2 padding\n");
    349     BIO_printf(bio_err, "-raw            use no padding\n");
    350     BIO_printf(bio_err,
    351                "-pkcs           use PKCS#1 v1.5 padding (default)\n");
    352     BIO_printf(bio_err, "-oaep           use PKCS#1 OAEP\n");
    353     BIO_printf(bio_err, "-sign           sign with private key\n");
    354     BIO_printf(bio_err, "-verify         verify with public key\n");
    355     BIO_printf(bio_err, "-encrypt        encrypt with public key\n");
    356     BIO_printf(bio_err, "-decrypt        decrypt with private key\n");
    357     BIO_printf(bio_err, "-hexdump        hex dump output\n");
    358 # ifndef OPENSSL_NO_ENGINE
    359     BIO_printf(bio_err,
    360                "-engine e       use engine e, possibly a hardware device.\n");
    361     BIO_printf(bio_err, "-passin arg    pass phrase source\n");
    362 # endif
    363 
    364 }
    365 
    366 #else                           /* !OPENSSL_NO_RSA */
    367 
    368 # if PEDANTIC
    369 static void *dummy = &dummy;
    370 # endif
    371 
    372 #endif
    373