rsautl.c revision 296465
1353358Sdim/* rsautl.c */
2353358Sdim/*
3353358Sdim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4353358Sdim * 2000.
5353358Sdim */
6353358Sdim/* ====================================================================
7353358Sdim * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
8353358Sdim *
9353358Sdim * Redistribution and use in source and binary forms, with or without
10353358Sdim * modification, are permitted provided that the following conditions
11353358Sdim * are met:
12276789Sdim *
13276789Sdim * 1. Redistributions of source code must retain the above copyright
14276789Sdim *    notice, this list of conditions and the following disclaimer.
15276789Sdim *
16276789Sdim * 2. Redistributions in binary form must reproduce the above copyright
17353358Sdim *    notice, this list of conditions and the following disclaimer in
18276789Sdim *    the documentation and/or other materials provided with the
19353358Sdim *    distribution.
20276789Sdim *
21353358Sdim * 3. All advertising materials mentioning features or use of this
22353358Sdim *    software must display the following acknowledgment:
23353358Sdim *    "This product includes software developed by the OpenSSL Project
24353358Sdim *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25353358Sdim *
26353358Sdim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27353358Sdim *    endorse or promote products derived from this software without
28353358Sdim *    prior written permission. For written permission, please contact
29353358Sdim *    licensing@OpenSSL.org.
30353358Sdim *
31353358Sdim * 5. Products derived from this software may not be called "OpenSSL"
32353358Sdim *    nor may "OpenSSL" appear in their names without prior written
33353358Sdim *    permission of the OpenSSL Project.
34353358Sdim *
35353358Sdim * 6. Redistributions of any form whatsoever must retain the following
36276789Sdim *    acknowledgment:
37276789Sdim *    "This product includes software developed by the OpenSSL Project
38353358Sdim *    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# ifndef OPENSSL_NO_ENGINE
92    char *engine = NULL;
93# endif
94    char *keyfile = NULL;
95    char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY;
96    int keyform = FORMAT_PEM;
97    char need_priv = 0, badarg = 0, rev = 0;
98    char hexdump = 0, asn1parse = 0;
99    X509 *x;
100    EVP_PKEY *pkey = NULL;
101    RSA *rsa = NULL;
102    unsigned char *rsa_in = NULL, *rsa_out = NULL, pad;
103    char *passargin = NULL, *passin = NULL;
104    int rsa_inlen, rsa_outlen = 0;
105    int keysize;
106
107    int ret = 1;
108
109    argc--;
110    argv++;
111
112    if (!bio_err)
113        bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
114
115    if (!load_config(bio_err, NULL))
116        goto end;
117    ERR_load_crypto_strings();
118    OpenSSL_add_all_algorithms();
119    pad = RSA_PKCS1_PADDING;
120
121    while (argc >= 1) {
122        if (!strcmp(*argv, "-in")) {
123            if (--argc < 1)
124                badarg = 1;
125            else
126                infile = *(++argv);
127        } else if (!strcmp(*argv, "-out")) {
128            if (--argc < 1)
129                badarg = 1;
130            else
131                outfile = *(++argv);
132        } else if (!strcmp(*argv, "-inkey")) {
133            if (--argc < 1)
134                badarg = 1;
135            else
136                keyfile = *(++argv);
137        } else if (!strcmp(*argv, "-passin")) {
138            if (--argc < 1)
139                badarg = 1;
140            else
141                passargin = *(++argv);
142        } else if (strcmp(*argv, "-keyform") == 0) {
143            if (--argc < 1)
144                badarg = 1;
145            else
146                keyform = str2fmt(*(++argv));
147# ifndef OPENSSL_NO_ENGINE
148        } else if (!strcmp(*argv, "-engine")) {
149            if (--argc < 1)
150                badarg = 1;
151            else
152                engine = *(++argv);
153# endif
154        } else if (!strcmp(*argv, "-pubin")) {
155            key_type = KEY_PUBKEY;
156        } else if (!strcmp(*argv, "-certin")) {
157            key_type = KEY_CERT;
158        } else if (!strcmp(*argv, "-asn1parse"))
159            asn1parse = 1;
160        else if (!strcmp(*argv, "-hexdump"))
161            hexdump = 1;
162        else if (!strcmp(*argv, "-raw"))
163            pad = RSA_NO_PADDING;
164        else if (!strcmp(*argv, "-oaep"))
165            pad = RSA_PKCS1_OAEP_PADDING;
166        else if (!strcmp(*argv, "-ssl"))
167            pad = RSA_SSLV23_PADDING;
168        else if (!strcmp(*argv, "-pkcs"))
169            pad = RSA_PKCS1_PADDING;
170        else if (!strcmp(*argv, "-x931"))
171            pad = RSA_X931_PADDING;
172        else if (!strcmp(*argv, "-sign")) {
173            rsa_mode = RSA_SIGN;
174            need_priv = 1;
175        } else if (!strcmp(*argv, "-verify"))
176            rsa_mode = RSA_VERIFY;
177        else if (!strcmp(*argv, "-rev"))
178            rev = 1;
179        else if (!strcmp(*argv, "-encrypt"))
180            rsa_mode = RSA_ENCRYPT;
181        else if (!strcmp(*argv, "-decrypt")) {
182            rsa_mode = RSA_DECRYPT;
183            need_priv = 1;
184        } else
185            badarg = 1;
186        if (badarg) {
187            usage();
188            goto end;
189        }
190        argc--;
191        argv++;
192    }
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# ifndef OPENSSL_NO_ENGINE
199    e = setup_engine(bio_err, engine, 0);
200# endif
201    if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
202        BIO_printf(bio_err, "Error getting password\n");
203        goto end;
204    }
205
206/* FIXME: seed PRNG only if needed */
207    app_RAND_load_file(NULL, bio_err, 0);
208
209    switch (key_type) {
210    case KEY_PRIVKEY:
211        pkey = load_key(bio_err, keyfile, keyform, 0,
212                        passin, e, "Private Key");
213        break;
214
215    case KEY_PUBKEY:
216        pkey = load_pubkey(bio_err, keyfile, keyform, 0,
217                           NULL, e, "Public Key");
218        break;
219
220    case KEY_CERT:
221        x = load_cert(bio_err, keyfile, keyform, NULL, e, "Certificate");
222        if (x) {
223            pkey = X509_get_pubkey(x);
224            X509_free(x);
225        }
226        break;
227    }
228
229    if (!pkey) {
230        return 1;
231    }
232
233    rsa = EVP_PKEY_get1_RSA(pkey);
234    EVP_PKEY_free(pkey);
235
236    if (!rsa) {
237        BIO_printf(bio_err, "Error getting RSA key\n");
238        ERR_print_errors(bio_err);
239        goto end;
240    }
241
242    if (infile) {
243        if (!(in = BIO_new_file(infile, "rb"))) {
244            BIO_printf(bio_err, "Error Reading Input File\n");
245            ERR_print_errors(bio_err);
246            goto end;
247        }
248    } else
249        in = BIO_new_fp(stdin, BIO_NOCLOSE);
250
251    if (outfile) {
252        if (!(out = BIO_new_file(outfile, "wb"))) {
253            BIO_printf(bio_err, "Error Reading Output File\n");
254            ERR_print_errors(bio_err);
255            goto end;
256        }
257    } else {
258        out = BIO_new_fp(stdout, BIO_NOCLOSE);
259# ifdef OPENSSL_SYS_VMS
260        {
261            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
262            out = BIO_push(tmpbio, out);
263        }
264# endif
265    }
266
267    keysize = RSA_size(rsa);
268
269    rsa_in = OPENSSL_malloc(keysize * 2);
270    rsa_out = OPENSSL_malloc(keysize);
271
272    /* Read the input data */
273    rsa_inlen = BIO_read(in, rsa_in, keysize * 2);
274    if (rsa_inlen <= 0) {
275        BIO_printf(bio_err, "Error reading input Data\n");
276        exit(1);
277    }
278    if (rev) {
279        int i;
280        unsigned char ctmp;
281        for (i = 0; i < rsa_inlen / 2; i++) {
282            ctmp = rsa_in[i];
283            rsa_in[i] = rsa_in[rsa_inlen - 1 - i];
284            rsa_in[rsa_inlen - 1 - i] = ctmp;
285        }
286    }
287    switch (rsa_mode) {
288
289    case RSA_VERIFY:
290        rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
291        break;
292
293    case RSA_SIGN:
294        rsa_outlen =
295            RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
296        break;
297
298    case RSA_ENCRYPT:
299        rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
300        break;
301
302    case RSA_DECRYPT:
303        rsa_outlen =
304            RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
305        break;
306
307    }
308
309    if (rsa_outlen <= 0) {
310        BIO_printf(bio_err, "RSA operation error\n");
311        ERR_print_errors(bio_err);
312        goto end;
313    }
314    ret = 0;
315    if (asn1parse) {
316        if (!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) {
317            ERR_print_errors(bio_err);
318        }
319    } else if (hexdump)
320        BIO_dump(out, (char *)rsa_out, rsa_outlen);
321    else
322        BIO_write(out, rsa_out, rsa_outlen);
323 end:
324    RSA_free(rsa);
325    BIO_free(in);
326    BIO_free_all(out);
327    if (rsa_in)
328        OPENSSL_free(rsa_in);
329    if (rsa_out)
330        OPENSSL_free(rsa_out);
331    if (passin)
332        OPENSSL_free(passin);
333    return ret;
334}
335
336static void usage()
337{
338    BIO_printf(bio_err, "Usage: rsautl [options]\n");
339    BIO_printf(bio_err, "-in file        input file\n");
340    BIO_printf(bio_err, "-out file       output file\n");
341    BIO_printf(bio_err, "-inkey file     input key\n");
342    BIO_printf(bio_err, "-keyform arg    private key format - default PEM\n");
343    BIO_printf(bio_err, "-pubin          input is an RSA public\n");
344    BIO_printf(bio_err,
345               "-certin         input is a certificate carrying an RSA public key\n");
346    BIO_printf(bio_err, "-ssl            use SSL v2 padding\n");
347    BIO_printf(bio_err, "-raw            use no padding\n");
348    BIO_printf(bio_err,
349               "-pkcs           use PKCS#1 v1.5 padding (default)\n");
350    BIO_printf(bio_err, "-oaep           use PKCS#1 OAEP\n");
351    BIO_printf(bio_err, "-sign           sign with private key\n");
352    BIO_printf(bio_err, "-verify         verify with public key\n");
353    BIO_printf(bio_err, "-encrypt        encrypt with public key\n");
354    BIO_printf(bio_err, "-decrypt        decrypt with private key\n");
355    BIO_printf(bio_err, "-hexdump        hex dump output\n");
356# ifndef OPENSSL_NO_ENGINE
357    BIO_printf(bio_err,
358               "-engine e       use engine e, possibly a hardware device.\n");
359    BIO_printf(bio_err, "-passin arg    pass phrase source\n");
360# endif
361
362}
363
364#endif
365