Update LibreSSL from version 2.4.4 => 2.9.1
[dragonfly.git] / crypto / libressl / apps / openssl / rsautl.c
1 /* $OpenBSD: rsautl.c,v 1.17 2019/02/04 11:21:05 tb Exp $ */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project 2000.
4  */
5 /* ====================================================================
6  * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #include <openssl/opensslconf.h>
60
61 #include <string.h>
62
63 #include "apps.h"
64
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
78 struct {
79         int asn1parse;
80         int hexdump;
81         char *infile;
82         char *keyfile;
83         int keyform;
84         int key_type;
85         char *outfile;
86         int pad;
87         char *passargin;
88         int rev;
89         int rsa_mode;
90 } rsautl_config;
91
92 struct option rsautl_options[] = {
93         {
94                 .name = "asn1parse",
95                 .desc = "ASN.1 parse the output data",
96                 .type = OPTION_FLAG,
97                 .opt.flag = &rsautl_config.asn1parse,
98         },
99         {
100                 .name = "certin",
101                 .desc = "Input is a certificate containing an RSA public key",
102                 .type = OPTION_VALUE,
103                 .value = KEY_CERT,
104                 .opt.value = &rsautl_config.key_type,
105         },
106         {
107                 .name = "decrypt",
108                 .desc = "Decrypt the input data using RSA private key",
109                 .type = OPTION_VALUE,
110                 .value = RSA_DECRYPT,
111                 .opt.value = &rsautl_config.rsa_mode,
112         },
113         {
114                 .name = "encrypt",
115                 .desc = "Encrypt the input data using RSA public key",
116                 .type = OPTION_VALUE,
117                 .value = RSA_ENCRYPT,
118                 .opt.value = &rsautl_config.rsa_mode,
119         },
120         {
121                 .name = "hexdump",
122                 .desc = "Hex dump the output data",
123                 .type = OPTION_FLAG,
124                 .opt.flag = &rsautl_config.hexdump,
125         },
126         {
127                 .name = "in",
128                 .argname = "file",
129                 .desc = "Input file (default stdin)",
130                 .type = OPTION_ARG,
131                 .opt.arg = &rsautl_config.infile,
132         },
133         {
134                 .name = "inkey",
135                 .argname = "file",
136                 .desc = "Input key file",
137                 .type = OPTION_ARG,
138                 .opt.arg = &rsautl_config.keyfile,
139         },
140         {
141                 .name = "keyform",
142                 .argname = "fmt",
143                 .desc = "Input key format (DER, TXT or PEM (default))",
144                 .type = OPTION_ARG_FORMAT,
145                 .opt.value = &rsautl_config.keyform,
146         },
147         {
148                 .name = "oaep",
149                 .desc = "Use PKCS#1 OAEP padding",
150                 .type = OPTION_VALUE,
151                 .value = RSA_PKCS1_OAEP_PADDING,
152                 .opt.value = &rsautl_config.pad,
153         },
154         {
155                 .name = "out",
156                 .argname = "file",
157                 .desc = "Output file (default stdout)",
158                 .type = OPTION_ARG,
159                 .opt.arg = &rsautl_config.outfile,
160         },
161         {
162                 .name = "passin",
163                 .argname = "arg",
164                 .desc = "Key password source",
165                 .type = OPTION_ARG,
166                 .opt.arg = &rsautl_config.passargin,
167         },
168         {
169                 .name = "pkcs",
170                 .desc = "Use PKCS#1 v1.5 padding (default)",
171                 .type = OPTION_VALUE,
172                 .value = RSA_PKCS1_PADDING,
173                 .opt.value = &rsautl_config.pad,
174         },
175         {
176                 .name = "pubin",
177                 .desc = "Input is an RSA public key",
178                 .type = OPTION_VALUE,
179                 .value = KEY_PUBKEY,
180                 .opt.value = &rsautl_config.key_type,
181         },
182         {
183                 .name = "raw",
184                 .desc = "Use no padding",
185                 .type = OPTION_VALUE,
186                 .value = RSA_NO_PADDING,
187                 .opt.value = &rsautl_config.pad,
188         },
189         {
190                 .name = "rev",
191                 .desc = "Reverse the input data",
192                 .type = OPTION_FLAG,
193                 .opt.flag = &rsautl_config.rev,
194         },
195         {
196                 .name = "sign",
197                 .desc = "Sign the input data using RSA private key",
198                 .type = OPTION_VALUE,
199                 .value = RSA_SIGN,
200                 .opt.value = &rsautl_config.rsa_mode,
201         },
202         {
203                 .name = "verify",
204                 .desc = "Verify the input data using RSA public key",
205                 .type = OPTION_VALUE,
206                 .value = RSA_VERIFY,
207                 .opt.value = &rsautl_config.rsa_mode,
208         },
209         {
210                 .name = "x931",
211                 .desc = "Use ANSI X9.31 padding",
212                 .type = OPTION_VALUE,
213                 .value = RSA_X931_PADDING,
214                 .opt.value = &rsautl_config.pad,
215         },
216
217         {NULL},
218 };
219
220 static void
221 rsautl_usage()
222 {
223         fprintf(stderr,
224             "usage: rsautl [-asn1parse] [-certin] [-decrypt] [-encrypt] "
225             "[-hexdump]\n"
226             "    [-in file] [-inkey file] [-keyform der | pem]\n"
227             "    [-oaep | -pkcs | -raw | -x931] [-out file] [-passin arg]\n"
228             "    [-pubin] [-rev] [-sign] [-verify]\n\n");
229
230         options_usage(rsautl_options);
231 }
232
233 int
234 rsautl_main(int argc, char **argv)
235 {
236         BIO *in = NULL, *out = NULL;
237         X509 *x;
238         EVP_PKEY *pkey = NULL;
239         RSA *rsa = NULL;
240         unsigned char *rsa_in = NULL, *rsa_out = NULL;
241         char *passin = NULL;
242         int rsa_inlen, rsa_outlen = 0;
243         int need_priv = 0;
244         int keysize;
245         int ret = 1;
246
247         if (single_execution) {
248                 if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
249                         perror("pledge");
250                         exit(1);
251                 }
252         }
253
254         memset(&rsautl_config, 0, sizeof(rsautl_config));
255         rsautl_config.keyform = FORMAT_PEM;
256         rsautl_config.key_type = KEY_PRIVKEY;
257         rsautl_config.pad = RSA_PKCS1_PADDING;
258         rsautl_config.rsa_mode = RSA_VERIFY;
259
260         if (options_parse(argc, argv, rsautl_options, NULL, NULL) != 0) {
261                 rsautl_usage();
262                 return (1);
263         }
264
265         if (rsautl_config.rsa_mode == RSA_SIGN ||
266             rsautl_config.rsa_mode == RSA_DECRYPT)
267                 need_priv = 1;
268
269         if (need_priv && rsautl_config.key_type != KEY_PRIVKEY) {
270                 BIO_printf(bio_err, "A private key is needed for this operation\n");
271                 goto end;
272         }
273         if (!app_passwd(bio_err, rsautl_config.passargin, NULL, &passin, NULL)) {
274                 BIO_printf(bio_err, "Error getting password\n");
275                 goto end;
276         }
277
278         switch (rsautl_config.key_type) {
279         case KEY_PRIVKEY:
280                 pkey = load_key(bio_err, rsautl_config.keyfile,
281                     rsautl_config.keyform, 0, passin, "Private Key");
282                 break;
283
284         case KEY_PUBKEY:
285                 pkey = load_pubkey(bio_err, rsautl_config.keyfile,
286                     rsautl_config.keyform, 0, NULL, "Public Key");
287                 break;
288
289         case KEY_CERT:
290                 x = load_cert(bio_err, rsautl_config.keyfile,
291                     rsautl_config.keyform, NULL, "Certificate");
292                 if (x) {
293                         pkey = X509_get_pubkey(x);
294                         X509_free(x);
295                 }
296                 break;
297         }
298
299         if (!pkey)
300                 goto end;
301
302         rsa = EVP_PKEY_get1_RSA(pkey);
303         EVP_PKEY_free(pkey);
304
305         if (!rsa) {
306                 BIO_printf(bio_err, "Error getting RSA key\n");
307                 ERR_print_errors(bio_err);
308                 goto end;
309         }
310         if (rsautl_config.infile) {
311                 if (!(in = BIO_new_file(rsautl_config.infile, "rb"))) {
312                         BIO_printf(bio_err, "Error Reading Input File\n");
313                         ERR_print_errors(bio_err);
314                         goto end;
315                 }
316         } else
317                 in = BIO_new_fp(stdin, BIO_NOCLOSE);
318
319         if (rsautl_config.outfile) {
320                 if (!(out = BIO_new_file(rsautl_config.outfile, "wb"))) {
321                         BIO_printf(bio_err, "Error Reading Output File\n");
322                         ERR_print_errors(bio_err);
323                         goto end;
324                 }
325         } else {
326                 out = BIO_new_fp(stdout, BIO_NOCLOSE);
327         }
328
329         keysize = RSA_size(rsa);
330
331         rsa_in = reallocarray(NULL, keysize, 2);
332         if (rsa_in == NULL) {
333                 BIO_printf(bio_err, "Error allocating memory for input data\n");
334                 exit(1);
335         }
336         rsa_out = malloc(keysize);
337         if (rsa_out == NULL) {
338                 BIO_printf(bio_err, "Error allocating memory for output data\n");
339                 exit(1);
340         }
341
342         /* Read the input data */
343         rsa_inlen = BIO_read(in, rsa_in, keysize * 2);
344         if (rsa_inlen <= 0) {
345                 BIO_printf(bio_err, "Error reading input Data\n");
346                 exit(1);
347         }
348         if (rsautl_config.rev) {
349                 int i;
350                 unsigned char ctmp;
351                 for (i = 0; i < rsa_inlen / 2; i++) {
352                         ctmp = rsa_in[i];
353                         rsa_in[i] = rsa_in[rsa_inlen - 1 - i];
354                         rsa_in[rsa_inlen - 1 - i] = ctmp;
355                 }
356         }
357
358         switch (rsautl_config.rsa_mode) {
359         case RSA_VERIFY:
360                 rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out,
361                     rsa, rsautl_config.pad);
362                 break;
363
364         case RSA_SIGN:
365                 rsa_outlen = RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out,
366                     rsa, rsautl_config.pad);
367                 break;
368
369         case RSA_ENCRYPT:
370                 rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out,
371                     rsa, rsautl_config.pad);
372                 break;
373
374         case RSA_DECRYPT:
375                 rsa_outlen = RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out,
376                     rsa, rsautl_config.pad);
377                 break;
378         }
379
380         if (rsa_outlen <= 0) {
381                 BIO_printf(bio_err, "RSA operation error\n");
382                 ERR_print_errors(bio_err);
383                 goto end;
384         }
385         ret = 0;
386         if (rsautl_config.asn1parse) {
387                 if (!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) {
388                         ERR_print_errors(bio_err);
389                 }
390         } else if (rsautl_config.hexdump)
391                 BIO_dump(out, (char *) rsa_out, rsa_outlen);
392         else
393                 BIO_write(out, rsa_out, rsa_outlen);
394
395  end:
396         RSA_free(rsa);
397         BIO_free(in);
398         BIO_free_all(out);
399         free(rsa_in);
400         free(rsa_out);
401         free(passin);
402
403         return ret;
404 }