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 } 405