rsautl.c 10.1 KB
Newer Older
1 2 3
/*
 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
 * 2000.
4 5 6 7 8 9 10 11 12
 */
/* ====================================================================
 * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
 *
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    licensing@OpenSSL.org.
 *
 * 5. Products derived from this software may not be called "OpenSSL"
 *    nor may "OpenSSL" appear in their names without prior written
 *    permission of the OpenSSL Project.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
 *
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This product includes cryptographic software written by Eric Young
 * (eay@cryptsoft.com).  This product includes software written by Tim
 * Hudson (tjh@cryptsoft.com).
 *
 */
B
Bodo Möller 已提交
58

N
make  
Nils Larsch 已提交
59
#include <openssl/opensslconf.h>
60
#ifndef OPENSSL_NO_RSA
B
Bodo Möller 已提交
61

62 63 64 65 66
# include "apps.h"
# include <string.h>
# include <openssl/err.h>
# include <openssl/pem.h>
# include <openssl/rsa.h>
67

68 69 70 71
# define RSA_SIGN        1
# define RSA_VERIFY      2
# define RSA_ENCRYPT     3
# define RSA_DECRYPT     4
72

73 74 75
# define KEY_PRIVKEY     1
# define KEY_PUBKEY      2
# define KEY_CERT        3
76

77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
typedef enum OPTION_choice {
    OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
    OPT_ENGINE, OPT_IN, OPT_OUT, OPT_ASN1PARSE, OPT_HEXDUMP,
    OPT_RAW, OPT_OAEP, OPT_SSL, OPT_PKCS, OPT_X931,
    OPT_SIGN, OPT_VERIFY, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT,
    OPT_PUBIN, OPT_CERTIN, OPT_INKEY, OPT_PASSIN, OPT_KEYFORM
} OPTION_CHOICE;

OPTIONS rsautl_options[] = {
    {"help", OPT_HELP, '-', "Display this summary"},
    {"in", OPT_IN, '<', "Input file"},
    {"out", OPT_OUT, '>', "Output file"},
    {"inkey", OPT_INKEY, '<', "Input key"},
    {"keyform", OPT_KEYFORM, 'F', "Private key format - default PEM"},
    {"pubin", OPT_PUBIN, '-', "Input is an RSA public"},
    {"certin", OPT_CERTIN, '-', "Input is a cert carrying an RSA public key"},
    {"ssl", OPT_SSL, '-', "Use SSL v2 padding"},
    {"raw", OPT_RAW, '-', "Use no padding"},
    {"pkcs", OPT_PKCS, '-', "Use PKCS#1 v1.5 padding (default)"},
    {"oaep", OPT_OAEP, '-', "Use PKCS#1 OAEP"},
    {"sign", OPT_SIGN, '-', "Sign with private key"},
    {"verify", OPT_VERIFY, '-', "Verify with public key"},
    {"asn1parse", OPT_ASN1PARSE, '-'},
    {"hexdump", OPT_HEXDUMP, '-', "Hex dump output"},
    {"x931", OPT_X931, '-', "Use ANSI X9.31 padding"},
    {"rev", OPT_REV, '-'},
    {"encrypt", OPT_ENCRYPT, '-', "Encrypt with public key"},
    {"decrypt", OPT_DECRYPT, '-', "Decrypt with private key"},
    {"passin", OPT_PASSIN, 's', "Pass phrase source"},
# ifndef OPENSSL_NO_ENGINE
    {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
# endif
    {NULL}
};
111

112
int rsautl_main(int argc, char **argv)
113
{
114
    BIO *in = NULL, *out = NULL;
115
    ENGINE *e = NULL;
116 117
    EVP_PKEY *pkey = NULL;
    RSA *rsa = NULL;
118
    X509 *x;
R
Rich Salz 已提交
119
    char *infile = NULL, *outfile = NULL, *keyfile = NULL;
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
    char *passinarg = NULL, *passin = NULL, *prog;
    char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY;
    unsigned char *rsa_in = NULL, *rsa_out = NULL, pad = RSA_PKCS1_PADDING;
    int rsa_inlen, keyformat = FORMAT_PEM, keysize, ret = 1;
    int rsa_outlen = 0, hexdump = 0, asn1parse = 0, need_priv = 0, rev = 0;
    OPTION_CHOICE o;

    prog = opt_init(argc, argv, rsautl_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(rsautl_options);
            ret = 0;
            goto end;
        case OPT_KEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_ENGINE:
R
Rich Salz 已提交
150
            e = setup_engine(opt_arg(), 0);
151 152
            break;
        case OPT_ASN1PARSE:
153
            asn1parse = 1;
154 155
            break;
        case OPT_HEXDUMP:
156
            hexdump = 1;
157 158
            break;
        case OPT_RAW:
159
            pad = RSA_NO_PADDING;
160 161
            break;
        case OPT_OAEP:
162
            pad = RSA_PKCS1_OAEP_PADDING;
163 164
            break;
        case OPT_SSL:
165
            pad = RSA_SSLV23_PADDING;
166 167
            break;
        case OPT_PKCS:
168
            pad = RSA_PKCS1_PADDING;
169 170
            break;
        case OPT_X931:
171
            pad = RSA_X931_PADDING;
172 173
            break;
        case OPT_SIGN:
174 175
            rsa_mode = RSA_SIGN;
            need_priv = 1;
176 177
            break;
        case OPT_VERIFY:
178
            rsa_mode = RSA_VERIFY;
179 180
            break;
        case OPT_REV:
181
            rev = 1;
182 183
            break;
        case OPT_ENCRYPT:
184
            rsa_mode = RSA_ENCRYPT;
185 186
            break;
        case OPT_DECRYPT:
187 188
            rsa_mode = RSA_DECRYPT;
            need_priv = 1;
189 190 191 192 193 194 195 196 197 198 199 200 201
            break;
        case OPT_PUBIN:
            key_type = KEY_PUBKEY;
            break;
        case OPT_CERTIN:
            key_type = KEY_CERT;
            break;
        case OPT_INKEY:
            keyfile = opt_arg();
            break;
        case OPT_PASSIN:
            passinarg = opt_arg();
            break;
202 203
        }
    }
204 205
    argc = opt_num_rest();
    argv = opt_rest();
206 207 208 209 210

    if (need_priv && (key_type != KEY_PRIVKEY)) {
        BIO_printf(bio_err, "A private key is needed for this operation\n");
        goto end;
    }
R
Rich Salz 已提交
211

212
    if (!app_passwd(passinarg, NULL, &passin, NULL)) {
213 214 215
        BIO_printf(bio_err, "Error getting password\n");
        goto end;
    }
216

R
Richard Levitte 已提交
217 218 219
    if (!app_load_modules(NULL))
        goto end;

B
Bodo Möller 已提交
220
/* FIXME: seed PRNG only if needed */
221
    app_RAND_load_file(NULL, 0);
222 223 224

    switch (key_type) {
    case KEY_PRIVKEY:
225
        pkey = load_key(keyfile, keyformat, 0, passin, e, "Private Key");
226 227 228
        break;

    case KEY_PUBKEY:
229
        pkey = load_pubkey(keyfile, keyformat, 0, NULL, e, "Public Key");
230 231 232
        break;

    case KEY_CERT:
233
        x = load_cert(keyfile, keyformat, NULL, e, "Certificate");
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
        if (x) {
            pkey = X509_get_pubkey(x);
            X509_free(x);
        }
        break;
    }

    if (!pkey) {
        return 1;
    }

    rsa = EVP_PKEY_get1_RSA(pkey);
    EVP_PKEY_free(pkey);

    if (!rsa) {
        BIO_printf(bio_err, "Error getting RSA key\n");
        ERR_print_errors(bio_err);
        goto end;
    }

254 255 256 257 258 259
    in = bio_open_default(infile, "rb");
    if (in == NULL)
        goto end;
    out = bio_open_default(outfile, "wb");
    if (out == NULL)
        goto end;
260 261 262

    keysize = RSA_size(rsa);

R
Rich Salz 已提交
263 264
    rsa_in = app_malloc(keysize * 2, "hold rsa key");
    rsa_out = app_malloc(keysize, "output rsa key");
265 266 267 268 269

    /* Read the input data */
    rsa_inlen = BIO_read(in, rsa_in, keysize * 2);
    if (rsa_inlen <= 0) {
        BIO_printf(bio_err, "Error reading input Data\n");
270
        goto end;
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
    }
    if (rev) {
        int i;
        unsigned char ctmp;
        for (i = 0; i < rsa_inlen / 2; i++) {
            ctmp = rsa_in[i];
            rsa_in[i] = rsa_in[rsa_inlen - 1 - i];
            rsa_in[rsa_inlen - 1 - i] = ctmp;
        }
    }
    switch (rsa_mode) {

    case RSA_VERIFY:
        rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
        break;

    case RSA_SIGN:
        rsa_outlen =
            RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
        break;

    case RSA_ENCRYPT:
        rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
        break;

    case RSA_DECRYPT:
        rsa_outlen =
            RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
        break;

    }

    if (rsa_outlen <= 0) {
        BIO_printf(bio_err, "RSA operation error\n");
        ERR_print_errors(bio_err);
        goto end;
    }
    ret = 0;
    if (asn1parse) {
        if (!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) {
            ERR_print_errors(bio_err);
        }
    } else if (hexdump)
        BIO_dump(out, (char *)rsa_out, rsa_outlen);
    else
        BIO_write(out, rsa_out, rsa_outlen);
 end:
    RSA_free(rsa);
    BIO_free(in);
    BIO_free_all(out);
R
Rich Salz 已提交
321 322 323
    OPENSSL_free(rsa_in);
    OPENSSL_free(rsa_out);
    OPENSSL_free(passin);
324
    return ret;
325 326
}

327
#else                           /* !OPENSSL_NO_RSA */
D
Dr. Stephen Henson 已提交
328 329

# if PEDANTIC
330
static void *dummy = &dummy;
D
Dr. Stephen Henson 已提交
331 332
# endif

B
Bodo Möller 已提交
333
#endif