168651Skris/* rsautl.c */
2296465Sdelphij/*
3296465Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4296465Sdelphij * 2000.
568651Skris */
668651Skris/* ====================================================================
768651Skris * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
868651Skris *
968651Skris * Redistribution and use in source and binary forms, with or without
1068651Skris * modification, are permitted provided that the following conditions
1168651Skris * are met:
1268651Skris *
1368651Skris * 1. Redistributions of source code must retain the above copyright
14296465Sdelphij *    notice, this list of conditions and the following disclaimer.
1568651Skris *
1668651Skris * 2. Redistributions in binary form must reproduce the above copyright
1768651Skris *    notice, this list of conditions and the following disclaimer in
1868651Skris *    the documentation and/or other materials provided with the
1968651Skris *    distribution.
2068651Skris *
2168651Skris * 3. All advertising materials mentioning features or use of this
2268651Skris *    software must display the following acknowledgment:
2368651Skris *    "This product includes software developed by the OpenSSL Project
2468651Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2568651Skris *
2668651Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2768651Skris *    endorse or promote products derived from this software without
2868651Skris *    prior written permission. For written permission, please contact
2968651Skris *    licensing@OpenSSL.org.
3068651Skris *
3168651Skris * 5. Products derived from this software may not be called "OpenSSL"
3268651Skris *    nor may "OpenSSL" appear in their names without prior written
3368651Skris *    permission of the OpenSSL Project.
3468651Skris *
3568651Skris * 6. Redistributions of any form whatsoever must retain the following
3668651Skris *    acknowledgment:
3768651Skris *    "This product includes software developed by the OpenSSL Project
3868651Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3968651Skris *
4068651Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4168651Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4268651Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4368651Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4468651Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4568651Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4668651Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4768651Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4868651Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4968651Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5068651Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5168651Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
5268651Skris * ====================================================================
5368651Skris *
5468651Skris * This product includes cryptographic software written by Eric Young
5568651Skris * (eay@cryptsoft.com).  This product includes software written by Tim
5668651Skris * Hudson (tjh@cryptsoft.com).
5768651Skris *
5868651Skris */
5972613Skris
60160814Ssimon#include <openssl/opensslconf.h>
61109998Smarkm#ifndef OPENSSL_NO_RSA
6272613Skris
63296465Sdelphij# include "apps.h"
64296465Sdelphij# include <string.h>
65296465Sdelphij# include <openssl/err.h>
66296465Sdelphij# include <openssl/pem.h>
67296465Sdelphij# include <openssl/rsa.h>
6868651Skris
69296465Sdelphij# define RSA_SIGN        1
70296465Sdelphij# define RSA_VERIFY      2
71296465Sdelphij# define RSA_ENCRYPT     3
72296465Sdelphij# define RSA_DECRYPT     4
7368651Skris
74296465Sdelphij# define KEY_PRIVKEY     1
75296465Sdelphij# define KEY_PUBKEY      2
76296465Sdelphij# define KEY_CERT        3
7768651Skris
7868651Skrisstatic void usage(void);
7968651Skris
80296465Sdelphij# undef PROG
8168651Skris
82296465Sdelphij# define PROG rsautl_main
8368651Skris
8468651Skrisint MAIN(int argc, char **);
8568651Skris
8668651Skrisint MAIN(int argc, char **argv)
8768651Skris{
88296465Sdelphij    ENGINE *e = NULL;
89296465Sdelphij    BIO *in = NULL, *out = NULL;
90296465Sdelphij    char *infile = NULL, *outfile = NULL;
91296465Sdelphij# ifndef OPENSSL_NO_ENGINE
92296465Sdelphij    char *engine = NULL;
93296465Sdelphij# endif
94296465Sdelphij    char *keyfile = NULL;
95296465Sdelphij    char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY;
96296465Sdelphij    int keyform = FORMAT_PEM;
97296465Sdelphij    char need_priv = 0, badarg = 0, rev = 0;
98296465Sdelphij    char hexdump = 0, asn1parse = 0;
99296465Sdelphij    X509 *x;
100296465Sdelphij    EVP_PKEY *pkey = NULL;
101296465Sdelphij    RSA *rsa = NULL;
102296465Sdelphij    unsigned char *rsa_in = NULL, *rsa_out = NULL, pad;
103296465Sdelphij    char *passargin = NULL, *passin = NULL;
104296465Sdelphij    int rsa_inlen, rsa_outlen = 0;
105296465Sdelphij    int keysize;
10668651Skris
107296465Sdelphij    int ret = 1;
10868651Skris
109296465Sdelphij    argc--;
110296465Sdelphij    argv++;
11168651Skris
112296465Sdelphij    if (!bio_err)
113296465Sdelphij        bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
114109998Smarkm
115296465Sdelphij    if (!load_config(bio_err, NULL))
116296465Sdelphij        goto end;
117296465Sdelphij    ERR_load_crypto_strings();
118296465Sdelphij    OpenSSL_add_all_algorithms();
119296465Sdelphij    pad = RSA_PKCS1_PADDING;
12068651Skris
121296465Sdelphij    while (argc >= 1) {
122296465Sdelphij        if (!strcmp(*argv, "-in")) {
123296465Sdelphij            if (--argc < 1)
124296465Sdelphij                badarg = 1;
125296465Sdelphij            else
126296465Sdelphij                infile = *(++argv);
127296465Sdelphij        } else if (!strcmp(*argv, "-out")) {
128296465Sdelphij            if (--argc < 1)
129296465Sdelphij                badarg = 1;
130296465Sdelphij            else
131296465Sdelphij                outfile = *(++argv);
132296465Sdelphij        } else if (!strcmp(*argv, "-inkey")) {
133296465Sdelphij            if (--argc < 1)
134296465Sdelphij                badarg = 1;
135296465Sdelphij            else
136296465Sdelphij                keyfile = *(++argv);
137296465Sdelphij        } else if (!strcmp(*argv, "-passin")) {
138296465Sdelphij            if (--argc < 1)
139296465Sdelphij                badarg = 1;
140296465Sdelphij            else
141296465Sdelphij                passargin = *(++argv);
142296465Sdelphij        } else if (strcmp(*argv, "-keyform") == 0) {
143296465Sdelphij            if (--argc < 1)
144296465Sdelphij                badarg = 1;
145296465Sdelphij            else
146296465Sdelphij                keyform = str2fmt(*(++argv));
147296465Sdelphij# ifndef OPENSSL_NO_ENGINE
148296465Sdelphij        } else if (!strcmp(*argv, "-engine")) {
149296465Sdelphij            if (--argc < 1)
150296465Sdelphij                badarg = 1;
151296465Sdelphij            else
152296465Sdelphij                engine = *(++argv);
153296465Sdelphij# endif
154296465Sdelphij        } else if (!strcmp(*argv, "-pubin")) {
155296465Sdelphij            key_type = KEY_PUBKEY;
156296465Sdelphij        } else if (!strcmp(*argv, "-certin")) {
157296465Sdelphij            key_type = KEY_CERT;
158296465Sdelphij        } else if (!strcmp(*argv, "-asn1parse"))
159296465Sdelphij            asn1parse = 1;
160296465Sdelphij        else if (!strcmp(*argv, "-hexdump"))
161296465Sdelphij            hexdump = 1;
162296465Sdelphij        else if (!strcmp(*argv, "-raw"))
163296465Sdelphij            pad = RSA_NO_PADDING;
164296465Sdelphij        else if (!strcmp(*argv, "-oaep"))
165296465Sdelphij            pad = RSA_PKCS1_OAEP_PADDING;
166296465Sdelphij        else if (!strcmp(*argv, "-ssl"))
167296465Sdelphij            pad = RSA_SSLV23_PADDING;
168296465Sdelphij        else if (!strcmp(*argv, "-pkcs"))
169296465Sdelphij            pad = RSA_PKCS1_PADDING;
170296465Sdelphij        else if (!strcmp(*argv, "-x931"))
171296465Sdelphij            pad = RSA_X931_PADDING;
172296465Sdelphij        else if (!strcmp(*argv, "-sign")) {
173296465Sdelphij            rsa_mode = RSA_SIGN;
174296465Sdelphij            need_priv = 1;
175296465Sdelphij        } else if (!strcmp(*argv, "-verify"))
176296465Sdelphij            rsa_mode = RSA_VERIFY;
177296465Sdelphij        else if (!strcmp(*argv, "-rev"))
178296465Sdelphij            rev = 1;
179296465Sdelphij        else if (!strcmp(*argv, "-encrypt"))
180296465Sdelphij            rsa_mode = RSA_ENCRYPT;
181296465Sdelphij        else if (!strcmp(*argv, "-decrypt")) {
182296465Sdelphij            rsa_mode = RSA_DECRYPT;
183296465Sdelphij            need_priv = 1;
184296465Sdelphij        } else
185296465Sdelphij            badarg = 1;
186296465Sdelphij        if (badarg) {
187296465Sdelphij            usage();
188296465Sdelphij            goto end;
189296465Sdelphij        }
190296465Sdelphij        argc--;
191296465Sdelphij        argv++;
192296465Sdelphij    }
19368651Skris
194296465Sdelphij    if (need_priv && (key_type != KEY_PRIVKEY)) {
195296465Sdelphij        BIO_printf(bio_err, "A private key is needed for this operation\n");
196296465Sdelphij        goto end;
197296465Sdelphij    }
198296465Sdelphij# ifndef OPENSSL_NO_ENGINE
199296465Sdelphij    e = setup_engine(bio_err, engine, 0);
200296465Sdelphij# endif
201296465Sdelphij    if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
202296465Sdelphij        BIO_printf(bio_err, "Error getting password\n");
203296465Sdelphij        goto end;
204296465Sdelphij    }
205109998Smarkm
20668651Skris/* FIXME: seed PRNG only if needed */
207296465Sdelphij    app_RAND_load_file(NULL, bio_err, 0);
20868651Skris
209296465Sdelphij    switch (key_type) {
210296465Sdelphij    case KEY_PRIVKEY:
211296465Sdelphij        pkey = load_key(bio_err, keyfile, keyform, 0,
212296465Sdelphij                        passin, e, "Private Key");
213296465Sdelphij        break;
21468651Skris
215296465Sdelphij    case KEY_PUBKEY:
216296465Sdelphij        pkey = load_pubkey(bio_err, keyfile, keyform, 0,
217296465Sdelphij                           NULL, e, "Public Key");
218296465Sdelphij        break;
21968651Skris
220296465Sdelphij    case KEY_CERT:
221296465Sdelphij        x = load_cert(bio_err, keyfile, keyform, NULL, e, "Certificate");
222296465Sdelphij        if (x) {
223296465Sdelphij            pkey = X509_get_pubkey(x);
224296465Sdelphij            X509_free(x);
225296465Sdelphij        }
226296465Sdelphij        break;
227296465Sdelphij    }
22868651Skris
229296465Sdelphij    if (!pkey) {
230296465Sdelphij        return 1;
231296465Sdelphij    }
23268651Skris
233296465Sdelphij    rsa = EVP_PKEY_get1_RSA(pkey);
234296465Sdelphij    EVP_PKEY_free(pkey);
23568651Skris
236296465Sdelphij    if (!rsa) {
237296465Sdelphij        BIO_printf(bio_err, "Error getting RSA key\n");
238296465Sdelphij        ERR_print_errors(bio_err);
239296465Sdelphij        goto end;
240296465Sdelphij    }
24168651Skris
242296465Sdelphij    if (infile) {
243296465Sdelphij        if (!(in = BIO_new_file(infile, "rb"))) {
244296465Sdelphij            BIO_printf(bio_err, "Error Reading Input File\n");
245296465Sdelphij            ERR_print_errors(bio_err);
246296465Sdelphij            goto end;
247296465Sdelphij        }
248296465Sdelphij    } else
249296465Sdelphij        in = BIO_new_fp(stdin, BIO_NOCLOSE);
25068651Skris
251296465Sdelphij    if (outfile) {
252296465Sdelphij        if (!(out = BIO_new_file(outfile, "wb"))) {
253296465Sdelphij            BIO_printf(bio_err, "Error Reading Output File\n");
254296465Sdelphij            ERR_print_errors(bio_err);
255296465Sdelphij            goto end;
256296465Sdelphij        }
257296465Sdelphij    } else {
258296465Sdelphij        out = BIO_new_fp(stdout, BIO_NOCLOSE);
259296465Sdelphij# ifdef OPENSSL_SYS_VMS
260296465Sdelphij        {
261296465Sdelphij            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
262296465Sdelphij            out = BIO_push(tmpbio, out);
263296465Sdelphij        }
264296465Sdelphij# endif
265296465Sdelphij    }
26668651Skris
267296465Sdelphij    keysize = RSA_size(rsa);
26868651Skris
269296465Sdelphij    rsa_in = OPENSSL_malloc(keysize * 2);
270296465Sdelphij    rsa_out = OPENSSL_malloc(keysize);
27168651Skris
272296465Sdelphij    /* Read the input data */
273296465Sdelphij    rsa_inlen = BIO_read(in, rsa_in, keysize * 2);
274296465Sdelphij    if (rsa_inlen <= 0) {
275296465Sdelphij        BIO_printf(bio_err, "Error reading input Data\n");
276296465Sdelphij        exit(1);
277296465Sdelphij    }
278296465Sdelphij    if (rev) {
279296465Sdelphij        int i;
280296465Sdelphij        unsigned char ctmp;
281296465Sdelphij        for (i = 0; i < rsa_inlen / 2; i++) {
282296465Sdelphij            ctmp = rsa_in[i];
283296465Sdelphij            rsa_in[i] = rsa_in[rsa_inlen - 1 - i];
284296465Sdelphij            rsa_in[rsa_inlen - 1 - i] = ctmp;
285296465Sdelphij        }
286296465Sdelphij    }
287296465Sdelphij    switch (rsa_mode) {
28868651Skris
289296465Sdelphij    case RSA_VERIFY:
290296465Sdelphij        rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
291296465Sdelphij        break;
29268651Skris
293296465Sdelphij    case RSA_SIGN:
294296465Sdelphij        rsa_outlen =
295296465Sdelphij            RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
296296465Sdelphij        break;
29768651Skris
298296465Sdelphij    case RSA_ENCRYPT:
299296465Sdelphij        rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
300296465Sdelphij        break;
30168651Skris
302296465Sdelphij    case RSA_DECRYPT:
303296465Sdelphij        rsa_outlen =
304296465Sdelphij            RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
305296465Sdelphij        break;
30668651Skris
307296465Sdelphij    }
30868651Skris
309296465Sdelphij    if (rsa_outlen <= 0) {
310296465Sdelphij        BIO_printf(bio_err, "RSA operation error\n");
311296465Sdelphij        ERR_print_errors(bio_err);
312296465Sdelphij        goto end;
313296465Sdelphij    }
314296465Sdelphij    ret = 0;
315296465Sdelphij    if (asn1parse) {
316296465Sdelphij        if (!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) {
317296465Sdelphij            ERR_print_errors(bio_err);
318296465Sdelphij        }
319296465Sdelphij    } else if (hexdump)
320296465Sdelphij        BIO_dump(out, (char *)rsa_out, rsa_outlen);
321296465Sdelphij    else
322296465Sdelphij        BIO_write(out, rsa_out, rsa_outlen);
323296465Sdelphij end:
324296465Sdelphij    RSA_free(rsa);
325296465Sdelphij    BIO_free(in);
326296465Sdelphij    BIO_free_all(out);
327296465Sdelphij    if (rsa_in)
328296465Sdelphij        OPENSSL_free(rsa_in);
329296465Sdelphij    if (rsa_out)
330296465Sdelphij        OPENSSL_free(rsa_out);
331296465Sdelphij    if (passin)
332296465Sdelphij        OPENSSL_free(passin);
333296465Sdelphij    return ret;
33468651Skris}
33568651Skris
33668651Skrisstatic void usage()
33768651Skris{
338296465Sdelphij    BIO_printf(bio_err, "Usage: rsautl [options]\n");
339296465Sdelphij    BIO_printf(bio_err, "-in file        input file\n");
340296465Sdelphij    BIO_printf(bio_err, "-out file       output file\n");
341296465Sdelphij    BIO_printf(bio_err, "-inkey file     input key\n");
342296465Sdelphij    BIO_printf(bio_err, "-keyform arg    private key format - default PEM\n");
343296465Sdelphij    BIO_printf(bio_err, "-pubin          input is an RSA public\n");
344296465Sdelphij    BIO_printf(bio_err,
345296465Sdelphij               "-certin         input is a certificate carrying an RSA public key\n");
346296465Sdelphij    BIO_printf(bio_err, "-ssl            use SSL v2 padding\n");
347296465Sdelphij    BIO_printf(bio_err, "-raw            use no padding\n");
348296465Sdelphij    BIO_printf(bio_err,
349296465Sdelphij               "-pkcs           use PKCS#1 v1.5 padding (default)\n");
350296465Sdelphij    BIO_printf(bio_err, "-oaep           use PKCS#1 OAEP\n");
351296465Sdelphij    BIO_printf(bio_err, "-sign           sign with private key\n");
352296465Sdelphij    BIO_printf(bio_err, "-verify         verify with public key\n");
353296465Sdelphij    BIO_printf(bio_err, "-encrypt        encrypt with public key\n");
354296465Sdelphij    BIO_printf(bio_err, "-decrypt        decrypt with private key\n");
355296465Sdelphij    BIO_printf(bio_err, "-hexdump        hex dump output\n");
356296465Sdelphij# ifndef OPENSSL_NO_ENGINE
357296465Sdelphij    BIO_printf(bio_err,
358296465Sdelphij               "-engine e       use engine e, possibly a hardware device.\n");
359296465Sdelphij    BIO_printf(bio_err, "-passin arg    pass phrase source\n");
360296465Sdelphij# endif
361109998Smarkm
36268651Skris}
36368651Skris
36472613Skris#endif
365