Home | History | Annotate | Line # | Download | only in apps
      1 /*
      2  * Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 #include <openssl/opensslconf.h>
     11 
     12 #include "apps.h"
     13 #include "progs.h"
     14 #include <string.h>
     15 #include <openssl/err.h>
     16 #include <openssl/pem.h>
     17 #include <openssl/rsa.h>
     18 
     19 #define RSA_SIGN 1
     20 #define RSA_VERIFY 2
     21 #define RSA_ENCRYPT 3
     22 #define RSA_DECRYPT 4
     23 
     24 #define KEY_PRIVKEY 1
     25 #define KEY_PUBKEY 2
     26 #define KEY_CERT 3
     27 
     28 typedef enum OPTION_choice {
     29     OPT_COMMON,
     30     OPT_ENGINE,
     31     OPT_IN,
     32     OPT_OUT,
     33     OPT_ASN1PARSE,
     34     OPT_HEXDUMP,
     35     OPT_RSA_RAW,
     36     OPT_OAEP,
     37     OPT_PKCS,
     38     OPT_X931,
     39     OPT_SIGN,
     40     OPT_VERIFY,
     41     OPT_REV,
     42     OPT_ENCRYPT,
     43     OPT_DECRYPT,
     44     OPT_PUBIN,
     45     OPT_CERTIN,
     46     OPT_INKEY,
     47     OPT_PASSIN,
     48     OPT_KEYFORM,
     49     OPT_R_ENUM,
     50     OPT_PROV_ENUM
     51 } OPTION_CHOICE;
     52 
     53 const OPTIONS rsautl_options[] = {
     54     OPT_SECTION("General"),
     55     { "help", OPT_HELP, '-', "Display this summary" },
     56     { "sign", OPT_SIGN, '-', "Sign with private key" },
     57     { "verify", OPT_VERIFY, '-', "Verify with public key" },
     58     { "encrypt", OPT_ENCRYPT, '-', "Encrypt with public key" },
     59     { "decrypt", OPT_DECRYPT, '-', "Decrypt with private key" },
     60 #ifndef OPENSSL_NO_ENGINE
     61     { "engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device" },
     62 #endif
     63 
     64     OPT_SECTION("Input"),
     65     { "in", OPT_IN, '<', "Input file" },
     66     { "inkey", OPT_INKEY, 's', "Input key, by default an RSA private key" },
     67     { "keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)" },
     68     { "pubin", OPT_PUBIN, '-', "Input key is an RSA public pkey" },
     69     { "certin", OPT_CERTIN, '-', "Input is a cert carrying an RSA public key" },
     70     { "rev", OPT_REV, '-', "Reverse the order of the input buffer" },
     71     { "passin", OPT_PASSIN, 's', "Input file pass phrase source" },
     72 
     73     OPT_SECTION("Output"),
     74     { "out", OPT_OUT, '>', "Output file" },
     75     { "raw", OPT_RSA_RAW, '-', "Use no padding" },
     76     { "pkcs", OPT_PKCS, '-', "Use PKCS#1 v1.5 padding (default)" },
     77     { "x931", OPT_X931, '-', "Use ANSI X9.31 padding" },
     78     { "oaep", OPT_OAEP, '-', "Use PKCS#1 OAEP" },
     79     { "asn1parse", OPT_ASN1PARSE, '-',
     80         "Run output through asn1parse; useful with -verify" },
     81     { "hexdump", OPT_HEXDUMP, '-', "Hex dump output" },
     82 
     83     OPT_R_OPTIONS,
     84     OPT_PROV_OPTIONS,
     85     { NULL }
     86 };
     87 
     88 int rsautl_main(int argc, char **argv)
     89 {
     90     BIO *in = NULL, *out = NULL;
     91     ENGINE *e = NULL;
     92     EVP_PKEY *pkey = NULL;
     93     EVP_PKEY_CTX *ctx = NULL;
     94     X509 *x;
     95     char *infile = NULL, *outfile = NULL, *keyfile = NULL;
     96     char *passinarg = NULL, *passin = NULL, *prog;
     97     char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY;
     98     unsigned char *rsa_in = NULL, *rsa_out = NULL, pad = RSA_PKCS1_PADDING;
     99     size_t rsa_inlen, rsa_outlen = 0;
    100     int keyformat = FORMAT_UNDEF, keysize, ret = 1, rv;
    101     int hexdump = 0, asn1parse = 0, need_priv = 0, rev = 0;
    102     OPTION_CHOICE o;
    103 
    104     prog = opt_init(argc, argv, rsautl_options);
    105     while ((o = opt_next()) != OPT_EOF) {
    106         switch (o) {
    107         case OPT_EOF:
    108         case OPT_ERR:
    109         opthelp:
    110             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
    111             goto end;
    112         case OPT_HELP:
    113             opt_help(rsautl_options);
    114             ret = 0;
    115             goto end;
    116         case OPT_KEYFORM:
    117             if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat))
    118                 goto opthelp;
    119             break;
    120         case OPT_IN:
    121             infile = opt_arg();
    122             break;
    123         case OPT_OUT:
    124             outfile = opt_arg();
    125             break;
    126         case OPT_ENGINE:
    127             e = setup_engine(opt_arg(), 0);
    128             break;
    129         case OPT_ASN1PARSE:
    130             asn1parse = 1;
    131             break;
    132         case OPT_HEXDUMP:
    133             hexdump = 1;
    134             break;
    135         case OPT_RSA_RAW:
    136             pad = RSA_NO_PADDING;
    137             break;
    138         case OPT_OAEP:
    139             pad = RSA_PKCS1_OAEP_PADDING;
    140             break;
    141         case OPT_PKCS:
    142             pad = RSA_PKCS1_PADDING;
    143             break;
    144         case OPT_X931:
    145             pad = RSA_X931_PADDING;
    146             break;
    147         case OPT_SIGN:
    148             rsa_mode = RSA_SIGN;
    149             need_priv = 1;
    150             break;
    151         case OPT_VERIFY:
    152             rsa_mode = RSA_VERIFY;
    153             break;
    154         case OPT_REV:
    155             rev = 1;
    156             break;
    157         case OPT_ENCRYPT:
    158             rsa_mode = RSA_ENCRYPT;
    159             break;
    160         case OPT_DECRYPT:
    161             rsa_mode = RSA_DECRYPT;
    162             need_priv = 1;
    163             break;
    164         case OPT_PUBIN:
    165             key_type = KEY_PUBKEY;
    166             break;
    167         case OPT_CERTIN:
    168             key_type = KEY_CERT;
    169             break;
    170         case OPT_INKEY:
    171             keyfile = opt_arg();
    172             break;
    173         case OPT_PASSIN:
    174             passinarg = opt_arg();
    175             break;
    176         case OPT_R_CASES:
    177             if (!opt_rand(o))
    178                 goto end;
    179             break;
    180         case OPT_PROV_CASES:
    181             if (!opt_provider(o))
    182                 goto end;
    183             break;
    184         }
    185     }
    186 
    187     /* No extra arguments. */
    188     if (!opt_check_rest_arg(NULL))
    189         goto opthelp;
    190 
    191     if (!app_RAND_load())
    192         goto end;
    193 
    194     if (need_priv && (key_type != KEY_PRIVKEY)) {
    195         BIO_printf(bio_err, "A private key is needed for this operation\n");
    196         goto end;
    197     }
    198 
    199     if (!app_passwd(passinarg, NULL, &passin, NULL)) {
    200         BIO_printf(bio_err, "Error getting password\n");
    201         goto end;
    202     }
    203 
    204     switch (key_type) {
    205     case KEY_PRIVKEY:
    206         pkey = load_key(keyfile, keyformat, 0, passin, e, "private key");
    207         break;
    208 
    209     case KEY_PUBKEY:
    210         pkey = load_pubkey(keyfile, keyformat, 0, NULL, e, "public key");
    211         break;
    212 
    213     case KEY_CERT:
    214         x = load_cert(keyfile, FORMAT_UNDEF, "Certificate");
    215         if (x) {
    216             pkey = X509_get_pubkey(x);
    217             X509_free(x);
    218         }
    219         break;
    220     }
    221 
    222     if (pkey == NULL)
    223         return 1;
    224 
    225     in = bio_open_default(infile, 'r', FORMAT_BINARY);
    226     if (in == NULL)
    227         goto end;
    228     out = bio_open_default(outfile, 'w', FORMAT_BINARY);
    229     if (out == NULL)
    230         goto end;
    231 
    232     keysize = EVP_PKEY_get_size(pkey);
    233 
    234     rsa_in = app_malloc(keysize * 2, "hold rsa key");
    235     rsa_out = app_malloc(keysize, "output rsa key");
    236     rsa_outlen = keysize;
    237 
    238     /* Read the input data */
    239     rv = BIO_read(in, rsa_in, keysize * 2);
    240     if (rv < 0) {
    241         BIO_printf(bio_err, "Error reading input Data\n");
    242         goto end;
    243     }
    244     rsa_inlen = rv;
    245     if (rev) {
    246         size_t i;
    247         unsigned char ctmp;
    248 
    249         for (i = 0; i < rsa_inlen / 2; i++) {
    250             ctmp = rsa_in[i];
    251             rsa_in[i] = rsa_in[rsa_inlen - 1 - i];
    252             rsa_in[rsa_inlen - 1 - i] = ctmp;
    253         }
    254     }
    255 
    256     if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL)
    257         goto end;
    258 
    259     switch (rsa_mode) {
    260     case RSA_VERIFY:
    261         rv = EVP_PKEY_verify_recover_init(ctx) > 0
    262             && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0
    263             && EVP_PKEY_verify_recover(ctx, rsa_out, &rsa_outlen,
    264                    rsa_in, rsa_inlen)
    265                 > 0;
    266         break;
    267     case RSA_SIGN:
    268         rv = EVP_PKEY_sign_init(ctx) > 0
    269             && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0
    270             && EVP_PKEY_sign(ctx, rsa_out, &rsa_outlen, rsa_in, rsa_inlen) > 0;
    271         break;
    272     case RSA_ENCRYPT:
    273         rv = EVP_PKEY_encrypt_init(ctx) > 0
    274             && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0
    275             && EVP_PKEY_encrypt(ctx, rsa_out, &rsa_outlen, rsa_in, rsa_inlen) > 0;
    276         break;
    277     case RSA_DECRYPT:
    278         rv = EVP_PKEY_decrypt_init(ctx) > 0
    279             && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0
    280             && EVP_PKEY_decrypt(ctx, rsa_out, &rsa_outlen, rsa_in, rsa_inlen) > 0;
    281         break;
    282     }
    283 
    284     if (!rv) {
    285         BIO_printf(bio_err, "RSA operation error\n");
    286         ERR_print_errors(bio_err);
    287         goto end;
    288     }
    289     ret = 0;
    290     if (asn1parse) {
    291         if (!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) {
    292             ERR_print_errors(bio_err);
    293         }
    294     } else if (hexdump) {
    295         BIO_dump(out, (char *)rsa_out, rsa_outlen);
    296     } else {
    297         BIO_write(out, rsa_out, rsa_outlen);
    298     }
    299 end:
    300     EVP_PKEY_CTX_free(ctx);
    301     EVP_PKEY_free(pkey);
    302     release_engine(e);
    303     BIO_free(in);
    304     BIO_free_all(out);
    305     OPENSSL_free(rsa_in);
    306     OPENSSL_free(rsa_out);
    307     OPENSSL_free(passin);
    308     return ret;
    309 }
    310