rsautl.c revision 312826
1/* rsautl.c */
2/*
3 * Written by Dr Stephen N Henson (steve@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@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@cryptsoft.com).  This product includes software written by Tim
56 * Hudson (tjh@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
78static void usage(void);
79
80# undef PROG
81
82# define PROG rsautl_main
83
84int MAIN(int argc, char **);
85
86int 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
338static 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
369static void *dummy = &dummy;
370# endif
371
372#endif
373