16f9291ceSJung-uk Kim /* 2*e71b7053SJung-uk Kim * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. 3ddd58736SKris Kennaway * 4*e71b7053SJung-uk Kim * Licensed under the OpenSSL license (the "License"). You may not use 5*e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 6*e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 7*e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 8ddd58736SKris Kennaway */ 9de7cdddaSKris Kennaway 103b4e3dcbSSimon L. B. Nielsen #include <openssl/opensslconf.h> 11*e71b7053SJung-uk Kim #ifdef OPENSSL_NO_RSA 12*e71b7053SJung-uk Kim NON_EMPTY_TRANSLATION_UNIT 13*e71b7053SJung-uk Kim #else 14de7cdddaSKris Kennaway 15ddd58736SKris Kennaway # include "apps.h" 16*e71b7053SJung-uk Kim # include "progs.h" 17ddd58736SKris Kennaway # include <string.h> 18ddd58736SKris Kennaway # include <openssl/err.h> 19ddd58736SKris Kennaway # include <openssl/pem.h> 203b4e3dcbSSimon L. B. Nielsen # include <openssl/rsa.h> 21ddd58736SKris Kennaway 22ddd58736SKris Kennaway # define RSA_SIGN 1 23ddd58736SKris Kennaway # define RSA_VERIFY 2 24ddd58736SKris Kennaway # define RSA_ENCRYPT 3 25ddd58736SKris Kennaway # define RSA_DECRYPT 4 26ddd58736SKris Kennaway 27ddd58736SKris Kennaway # define KEY_PRIVKEY 1 28ddd58736SKris Kennaway # define KEY_PUBKEY 2 29ddd58736SKris Kennaway # define KEY_CERT 3 30ddd58736SKris Kennaway 31*e71b7053SJung-uk Kim typedef enum OPTION_choice { 32*e71b7053SJung-uk Kim OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, 33*e71b7053SJung-uk Kim OPT_ENGINE, OPT_IN, OPT_OUT, OPT_ASN1PARSE, OPT_HEXDUMP, 34*e71b7053SJung-uk Kim OPT_RAW, OPT_OAEP, OPT_SSL, OPT_PKCS, OPT_X931, 35*e71b7053SJung-uk Kim OPT_SIGN, OPT_VERIFY, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT, 36*e71b7053SJung-uk Kim OPT_PUBIN, OPT_CERTIN, OPT_INKEY, OPT_PASSIN, OPT_KEYFORM, 37*e71b7053SJung-uk Kim OPT_R_ENUM 38*e71b7053SJung-uk Kim } OPTION_CHOICE; 39ddd58736SKris Kennaway 40*e71b7053SJung-uk Kim const OPTIONS rsautl_options[] = { 41*e71b7053SJung-uk Kim {"help", OPT_HELP, '-', "Display this summary"}, 42*e71b7053SJung-uk Kim {"in", OPT_IN, '<', "Input file"}, 43*e71b7053SJung-uk Kim {"out", OPT_OUT, '>', "Output file"}, 44*e71b7053SJung-uk Kim {"inkey", OPT_INKEY, 's', "Input key"}, 45*e71b7053SJung-uk Kim {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"}, 46*e71b7053SJung-uk Kim {"pubin", OPT_PUBIN, '-', "Input is an RSA public"}, 47*e71b7053SJung-uk Kim {"certin", OPT_CERTIN, '-', "Input is a cert carrying an RSA public key"}, 48*e71b7053SJung-uk Kim {"ssl", OPT_SSL, '-', "Use SSL v2 padding"}, 49*e71b7053SJung-uk Kim {"raw", OPT_RAW, '-', "Use no padding"}, 50*e71b7053SJung-uk Kim {"pkcs", OPT_PKCS, '-', "Use PKCS#1 v1.5 padding (default)"}, 51*e71b7053SJung-uk Kim {"oaep", OPT_OAEP, '-', "Use PKCS#1 OAEP"}, 52*e71b7053SJung-uk Kim {"sign", OPT_SIGN, '-', "Sign with private key"}, 53*e71b7053SJung-uk Kim {"verify", OPT_VERIFY, '-', "Verify with public key"}, 54*e71b7053SJung-uk Kim {"asn1parse", OPT_ASN1PARSE, '-', 55*e71b7053SJung-uk Kim "Run output through asn1parse; useful with -verify"}, 56*e71b7053SJung-uk Kim {"hexdump", OPT_HEXDUMP, '-', "Hex dump output"}, 57*e71b7053SJung-uk Kim {"x931", OPT_X931, '-', "Use ANSI X9.31 padding"}, 58*e71b7053SJung-uk Kim {"rev", OPT_REV, '-', "Reverse the order of the input buffer"}, 59*e71b7053SJung-uk Kim {"encrypt", OPT_ENCRYPT, '-', "Encrypt with public key"}, 60*e71b7053SJung-uk Kim {"decrypt", OPT_DECRYPT, '-', "Decrypt with private key"}, 61*e71b7053SJung-uk Kim {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, 62*e71b7053SJung-uk Kim OPT_R_OPTIONS, 63*e71b7053SJung-uk Kim # ifndef OPENSSL_NO_ENGINE 64*e71b7053SJung-uk Kim {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 65*e71b7053SJung-uk Kim # endif 66*e71b7053SJung-uk Kim {NULL} 67*e71b7053SJung-uk Kim }; 68ddd58736SKris Kennaway 69*e71b7053SJung-uk Kim int rsautl_main(int argc, char **argv) 70ddd58736SKris Kennaway { 71ddd58736SKris Kennaway BIO *in = NULL, *out = NULL; 72*e71b7053SJung-uk Kim ENGINE *e = NULL; 73ddd58736SKris Kennaway EVP_PKEY *pkey = NULL; 74ddd58736SKris Kennaway RSA *rsa = NULL; 75*e71b7053SJung-uk Kim X509 *x; 76*e71b7053SJung-uk Kim char *infile = NULL, *outfile = NULL, *keyfile = NULL; 77*e71b7053SJung-uk Kim char *passinarg = NULL, *passin = NULL, *prog; 78*e71b7053SJung-uk Kim char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY; 79*e71b7053SJung-uk Kim unsigned char *rsa_in = NULL, *rsa_out = NULL, pad = RSA_PKCS1_PADDING; 80*e71b7053SJung-uk Kim int rsa_inlen, keyformat = FORMAT_PEM, keysize, ret = 1; 81*e71b7053SJung-uk Kim int rsa_outlen = 0, hexdump = 0, asn1parse = 0, need_priv = 0, rev = 0; 82*e71b7053SJung-uk Kim OPTION_CHOICE o; 83ddd58736SKris Kennaway 84*e71b7053SJung-uk Kim prog = opt_init(argc, argv, rsautl_options); 85*e71b7053SJung-uk Kim while ((o = opt_next()) != OPT_EOF) { 86*e71b7053SJung-uk Kim switch (o) { 87*e71b7053SJung-uk Kim case OPT_EOF: 88*e71b7053SJung-uk Kim case OPT_ERR: 89*e71b7053SJung-uk Kim opthelp: 90*e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 915c87c606SMark Murray goto end; 92*e71b7053SJung-uk Kim case OPT_HELP: 93*e71b7053SJung-uk Kim opt_help(rsautl_options); 94*e71b7053SJung-uk Kim ret = 0; 95*e71b7053SJung-uk Kim goto end; 96*e71b7053SJung-uk Kim case OPT_KEYFORM: 97*e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyformat)) 98*e71b7053SJung-uk Kim goto opthelp; 99*e71b7053SJung-uk Kim break; 100*e71b7053SJung-uk Kim case OPT_IN: 101*e71b7053SJung-uk Kim infile = opt_arg(); 102*e71b7053SJung-uk Kim break; 103*e71b7053SJung-uk Kim case OPT_OUT: 104*e71b7053SJung-uk Kim outfile = opt_arg(); 105*e71b7053SJung-uk Kim break; 106*e71b7053SJung-uk Kim case OPT_ENGINE: 107*e71b7053SJung-uk Kim e = setup_engine(opt_arg(), 0); 108*e71b7053SJung-uk Kim break; 109*e71b7053SJung-uk Kim case OPT_ASN1PARSE: 1106f9291ceSJung-uk Kim asn1parse = 1; 111*e71b7053SJung-uk Kim break; 112*e71b7053SJung-uk Kim case OPT_HEXDUMP: 1136f9291ceSJung-uk Kim hexdump = 1; 114*e71b7053SJung-uk Kim break; 115*e71b7053SJung-uk Kim case OPT_RAW: 1166f9291ceSJung-uk Kim pad = RSA_NO_PADDING; 117*e71b7053SJung-uk Kim break; 118*e71b7053SJung-uk Kim case OPT_OAEP: 1196f9291ceSJung-uk Kim pad = RSA_PKCS1_OAEP_PADDING; 120*e71b7053SJung-uk Kim break; 121*e71b7053SJung-uk Kim case OPT_SSL: 1226f9291ceSJung-uk Kim pad = RSA_SSLV23_PADDING; 123*e71b7053SJung-uk Kim break; 124*e71b7053SJung-uk Kim case OPT_PKCS: 1256f9291ceSJung-uk Kim pad = RSA_PKCS1_PADDING; 126*e71b7053SJung-uk Kim break; 127*e71b7053SJung-uk Kim case OPT_X931: 1286f9291ceSJung-uk Kim pad = RSA_X931_PADDING; 129*e71b7053SJung-uk Kim break; 130*e71b7053SJung-uk Kim case OPT_SIGN: 131ddd58736SKris Kennaway rsa_mode = RSA_SIGN; 132ddd58736SKris Kennaway need_priv = 1; 133*e71b7053SJung-uk Kim break; 134*e71b7053SJung-uk Kim case OPT_VERIFY: 1356f9291ceSJung-uk Kim rsa_mode = RSA_VERIFY; 136*e71b7053SJung-uk Kim break; 137*e71b7053SJung-uk Kim case OPT_REV: 1386f9291ceSJung-uk Kim rev = 1; 139*e71b7053SJung-uk Kim break; 140*e71b7053SJung-uk Kim case OPT_ENCRYPT: 1416f9291ceSJung-uk Kim rsa_mode = RSA_ENCRYPT; 142*e71b7053SJung-uk Kim break; 143*e71b7053SJung-uk Kim case OPT_DECRYPT: 144ddd58736SKris Kennaway rsa_mode = RSA_DECRYPT; 145ddd58736SKris Kennaway need_priv = 1; 146*e71b7053SJung-uk Kim break; 147*e71b7053SJung-uk Kim case OPT_PUBIN: 148*e71b7053SJung-uk Kim key_type = KEY_PUBKEY; 149*e71b7053SJung-uk Kim break; 150*e71b7053SJung-uk Kim case OPT_CERTIN: 151*e71b7053SJung-uk Kim key_type = KEY_CERT; 152*e71b7053SJung-uk Kim break; 153*e71b7053SJung-uk Kim case OPT_INKEY: 154*e71b7053SJung-uk Kim keyfile = opt_arg(); 155*e71b7053SJung-uk Kim break; 156*e71b7053SJung-uk Kim case OPT_PASSIN: 157*e71b7053SJung-uk Kim passinarg = opt_arg(); 158*e71b7053SJung-uk Kim break; 159*e71b7053SJung-uk Kim case OPT_R_CASES: 160*e71b7053SJung-uk Kim if (!opt_rand(o)) 161ddd58736SKris Kennaway goto end; 162*e71b7053SJung-uk Kim break; 163ddd58736SKris Kennaway } 164ddd58736SKris Kennaway } 165*e71b7053SJung-uk Kim argc = opt_num_rest(); 166*e71b7053SJung-uk Kim if (argc != 0) 167*e71b7053SJung-uk Kim goto opthelp; 168ddd58736SKris Kennaway 169ddd58736SKris Kennaway if (need_priv && (key_type != KEY_PRIVKEY)) { 170ddd58736SKris Kennaway BIO_printf(bio_err, "A private key is needed for this operation\n"); 171ddd58736SKris Kennaway goto end; 172ddd58736SKris Kennaway } 173*e71b7053SJung-uk Kim 174*e71b7053SJung-uk Kim if (!app_passwd(passinarg, NULL, &passin, NULL)) { 175ced566fdSJacques Vidrine BIO_printf(bio_err, "Error getting password\n"); 176ced566fdSJacques Vidrine goto end; 177ced566fdSJacques Vidrine } 1785c87c606SMark Murray 179ddd58736SKris Kennaway switch (key_type) { 180ddd58736SKris Kennaway case KEY_PRIVKEY: 181*e71b7053SJung-uk Kim pkey = load_key(keyfile, keyformat, 0, passin, e, "Private Key"); 182ddd58736SKris Kennaway break; 183ddd58736SKris Kennaway 184ddd58736SKris Kennaway case KEY_PUBKEY: 185*e71b7053SJung-uk Kim pkey = load_pubkey(keyfile, keyformat, 0, NULL, e, "Public Key"); 186ddd58736SKris Kennaway break; 187ddd58736SKris Kennaway 188ddd58736SKris Kennaway case KEY_CERT: 189*e71b7053SJung-uk Kim x = load_cert(keyfile, keyformat, "Certificate"); 190ddd58736SKris Kennaway if (x) { 191ddd58736SKris Kennaway pkey = X509_get_pubkey(x); 192ddd58736SKris Kennaway X509_free(x); 193ddd58736SKris Kennaway } 194ddd58736SKris Kennaway break; 195ddd58736SKris Kennaway } 196ddd58736SKris Kennaway 197*e71b7053SJung-uk Kim if (pkey == NULL) 198ddd58736SKris Kennaway return 1; 199ddd58736SKris Kennaway 200ddd58736SKris Kennaway rsa = EVP_PKEY_get1_RSA(pkey); 201ddd58736SKris Kennaway EVP_PKEY_free(pkey); 202ddd58736SKris Kennaway 203*e71b7053SJung-uk Kim if (rsa == NULL) { 204ddd58736SKris Kennaway BIO_printf(bio_err, "Error getting RSA key\n"); 205ddd58736SKris Kennaway ERR_print_errors(bio_err); 206ddd58736SKris Kennaway goto end; 207ddd58736SKris Kennaway } 208ddd58736SKris Kennaway 209*e71b7053SJung-uk Kim in = bio_open_default(infile, 'r', FORMAT_BINARY); 210*e71b7053SJung-uk Kim if (in == NULL) 211ddd58736SKris Kennaway goto end; 212*e71b7053SJung-uk Kim out = bio_open_default(outfile, 'w', FORMAT_BINARY); 213*e71b7053SJung-uk Kim if (out == NULL) 214ddd58736SKris Kennaway goto end; 215ddd58736SKris Kennaway 216ddd58736SKris Kennaway keysize = RSA_size(rsa); 217ddd58736SKris Kennaway 218*e71b7053SJung-uk Kim rsa_in = app_malloc(keysize * 2, "hold rsa key"); 219*e71b7053SJung-uk Kim rsa_out = app_malloc(keysize, "output rsa key"); 220ddd58736SKris Kennaway 221ddd58736SKris Kennaway /* Read the input data */ 222ddd58736SKris Kennaway rsa_inlen = BIO_read(in, rsa_in, keysize * 2); 2234c6a0400SJung-uk Kim if (rsa_inlen < 0) { 224ddd58736SKris Kennaway BIO_printf(bio_err, "Error reading input Data\n"); 225*e71b7053SJung-uk Kim goto end; 226ddd58736SKris Kennaway } 227ddd58736SKris Kennaway if (rev) { 228ddd58736SKris Kennaway int i; 229ddd58736SKris Kennaway unsigned char ctmp; 230ddd58736SKris Kennaway for (i = 0; i < rsa_inlen / 2; i++) { 231ddd58736SKris Kennaway ctmp = rsa_in[i]; 232ddd58736SKris Kennaway rsa_in[i] = rsa_in[rsa_inlen - 1 - i]; 233ddd58736SKris Kennaway rsa_in[rsa_inlen - 1 - i] = ctmp; 234ddd58736SKris Kennaway } 235ddd58736SKris Kennaway } 236ddd58736SKris Kennaway switch (rsa_mode) { 237ddd58736SKris Kennaway 238ddd58736SKris Kennaway case RSA_VERIFY: 239ddd58736SKris Kennaway rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); 240ddd58736SKris Kennaway break; 241ddd58736SKris Kennaway 242ddd58736SKris Kennaway case RSA_SIGN: 2436f9291ceSJung-uk Kim rsa_outlen = 2446f9291ceSJung-uk Kim RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); 245ddd58736SKris Kennaway break; 246ddd58736SKris Kennaway 247ddd58736SKris Kennaway case RSA_ENCRYPT: 248ddd58736SKris Kennaway rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); 249ddd58736SKris Kennaway break; 250ddd58736SKris Kennaway 251ddd58736SKris Kennaway case RSA_DECRYPT: 2526f9291ceSJung-uk Kim rsa_outlen = 2536f9291ceSJung-uk Kim RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); 254ddd58736SKris Kennaway break; 255ddd58736SKris Kennaway } 256ddd58736SKris Kennaway 2574c6a0400SJung-uk Kim if (rsa_outlen < 0) { 258ddd58736SKris Kennaway BIO_printf(bio_err, "RSA operation error\n"); 259ddd58736SKris Kennaway ERR_print_errors(bio_err); 260ddd58736SKris Kennaway goto end; 261ddd58736SKris Kennaway } 262ddd58736SKris Kennaway ret = 0; 263ddd58736SKris Kennaway if (asn1parse) { 264ddd58736SKris Kennaway if (!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) { 265ddd58736SKris Kennaway ERR_print_errors(bio_err); 266ddd58736SKris Kennaway } 267*e71b7053SJung-uk Kim } else if (hexdump) { 2686f9291ceSJung-uk Kim BIO_dump(out, (char *)rsa_out, rsa_outlen); 269*e71b7053SJung-uk Kim } else { 2706f9291ceSJung-uk Kim BIO_write(out, rsa_out, rsa_outlen); 271*e71b7053SJung-uk Kim } 272ddd58736SKris Kennaway end: 273ddd58736SKris Kennaway RSA_free(rsa); 2746cf8931aSJung-uk Kim release_engine(e); 275ddd58736SKris Kennaway BIO_free(in); 276ddd58736SKris Kennaway BIO_free_all(out); 2776f9291ceSJung-uk Kim OPENSSL_free(rsa_in); 2786f9291ceSJung-uk Kim OPENSSL_free(rsa_out); 2796f9291ceSJung-uk Kim OPENSSL_free(passin); 280ddd58736SKris Kennaway return ret; 281ddd58736SKris Kennaway } 282de7cdddaSKris Kennaway #endif 283