16f9291ceSJung-uk Kim /* 2*b077aed3SPierre Pronchery * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. 3ddd58736SKris Kennaway * 4*b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use 5e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 6e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 7e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 8ddd58736SKris Kennaway */ 9de7cdddaSKris Kennaway 103b4e3dcbSSimon L. B. Nielsen #include <openssl/opensslconf.h> 11*b077aed3SPierre Pronchery 12ddd58736SKris Kennaway #include "apps.h" 13e71b7053SJung-uk Kim #include "progs.h" 14ddd58736SKris Kennaway #include <string.h> 15ddd58736SKris Kennaway #include <openssl/err.h> 16ddd58736SKris Kennaway #include <openssl/pem.h> 173b4e3dcbSSimon L. B. Nielsen #include <openssl/rsa.h> 18ddd58736SKris Kennaway 19ddd58736SKris Kennaway #define RSA_SIGN 1 20ddd58736SKris Kennaway #define RSA_VERIFY 2 21ddd58736SKris Kennaway #define RSA_ENCRYPT 3 22ddd58736SKris Kennaway #define RSA_DECRYPT 4 23ddd58736SKris Kennaway 24ddd58736SKris Kennaway #define KEY_PRIVKEY 1 25ddd58736SKris Kennaway #define KEY_PUBKEY 2 26ddd58736SKris Kennaway #define KEY_CERT 3 27ddd58736SKris Kennaway 28e71b7053SJung-uk Kim typedef enum OPTION_choice { 29*b077aed3SPierre Pronchery OPT_COMMON, 30e71b7053SJung-uk Kim OPT_ENGINE, OPT_IN, OPT_OUT, OPT_ASN1PARSE, OPT_HEXDUMP, 31*b077aed3SPierre Pronchery OPT_RSA_RAW, OPT_OAEP, OPT_PKCS, OPT_X931, 32e71b7053SJung-uk Kim OPT_SIGN, OPT_VERIFY, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT, 33e71b7053SJung-uk Kim OPT_PUBIN, OPT_CERTIN, OPT_INKEY, OPT_PASSIN, OPT_KEYFORM, 34*b077aed3SPierre Pronchery OPT_R_ENUM, OPT_PROV_ENUM 35e71b7053SJung-uk Kim } OPTION_CHOICE; 36ddd58736SKris Kennaway 37e71b7053SJung-uk Kim const OPTIONS rsautl_options[] = { 38*b077aed3SPierre Pronchery OPT_SECTION("General"), 39e71b7053SJung-uk Kim {"help", OPT_HELP, '-', "Display this summary"}, 40e71b7053SJung-uk Kim {"sign", OPT_SIGN, '-', "Sign with private key"}, 41e71b7053SJung-uk Kim {"verify", OPT_VERIFY, '-', "Verify with public key"}, 42e71b7053SJung-uk Kim {"encrypt", OPT_ENCRYPT, '-', "Encrypt with public key"}, 43e71b7053SJung-uk Kim {"decrypt", OPT_DECRYPT, '-', "Decrypt with private key"}, 44e71b7053SJung-uk Kim #ifndef OPENSSL_NO_ENGINE 45e71b7053SJung-uk Kim {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 46e71b7053SJung-uk Kim #endif 47*b077aed3SPierre Pronchery 48*b077aed3SPierre Pronchery OPT_SECTION("Input"), 49*b077aed3SPierre Pronchery {"in", OPT_IN, '<', "Input file"}, 50*b077aed3SPierre Pronchery {"inkey", OPT_INKEY, 's', "Input key"}, 51*b077aed3SPierre Pronchery {"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"}, 52*b077aed3SPierre Pronchery {"pubin", OPT_PUBIN, '-', "Input is an RSA public"}, 53*b077aed3SPierre Pronchery {"certin", OPT_CERTIN, '-', "Input is a cert carrying an RSA public key"}, 54*b077aed3SPierre Pronchery {"rev", OPT_REV, '-', "Reverse the order of the input buffer"}, 55*b077aed3SPierre Pronchery {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, 56*b077aed3SPierre Pronchery 57*b077aed3SPierre Pronchery OPT_SECTION("Output"), 58*b077aed3SPierre Pronchery {"out", OPT_OUT, '>', "Output file"}, 59*b077aed3SPierre Pronchery {"raw", OPT_RSA_RAW, '-', "Use no padding"}, 60*b077aed3SPierre Pronchery {"pkcs", OPT_PKCS, '-', "Use PKCS#1 v1.5 padding (default)"}, 61*b077aed3SPierre Pronchery {"x931", OPT_X931, '-', "Use ANSI X9.31 padding"}, 62*b077aed3SPierre Pronchery {"oaep", OPT_OAEP, '-', "Use PKCS#1 OAEP"}, 63*b077aed3SPierre Pronchery {"asn1parse", OPT_ASN1PARSE, '-', 64*b077aed3SPierre Pronchery "Run output through asn1parse; useful with -verify"}, 65*b077aed3SPierre Pronchery {"hexdump", OPT_HEXDUMP, '-', "Hex dump output"}, 66*b077aed3SPierre Pronchery 67*b077aed3SPierre Pronchery OPT_R_OPTIONS, 68*b077aed3SPierre Pronchery OPT_PROV_OPTIONS, 69e71b7053SJung-uk Kim {NULL} 70e71b7053SJung-uk Kim }; 71ddd58736SKris Kennaway 72e71b7053SJung-uk Kim int rsautl_main(int argc, char **argv) 73ddd58736SKris Kennaway { 74ddd58736SKris Kennaway BIO *in = NULL, *out = NULL; 75e71b7053SJung-uk Kim ENGINE *e = NULL; 76ddd58736SKris Kennaway EVP_PKEY *pkey = NULL; 77*b077aed3SPierre Pronchery EVP_PKEY_CTX *ctx = NULL; 78e71b7053SJung-uk Kim X509 *x; 79e71b7053SJung-uk Kim char *infile = NULL, *outfile = NULL, *keyfile = NULL; 80e71b7053SJung-uk Kim char *passinarg = NULL, *passin = NULL, *prog; 81e71b7053SJung-uk Kim char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY; 82e71b7053SJung-uk Kim unsigned char *rsa_in = NULL, *rsa_out = NULL, pad = RSA_PKCS1_PADDING; 83*b077aed3SPierre Pronchery size_t rsa_inlen, rsa_outlen = 0; 84*b077aed3SPierre Pronchery int keyformat = FORMAT_UNDEF, keysize, ret = 1, rv; 85*b077aed3SPierre Pronchery int hexdump = 0, asn1parse = 0, need_priv = 0, rev = 0; 86e71b7053SJung-uk Kim OPTION_CHOICE o; 87ddd58736SKris Kennaway 88e71b7053SJung-uk Kim prog = opt_init(argc, argv, rsautl_options); 89e71b7053SJung-uk Kim while ((o = opt_next()) != OPT_EOF) { 90e71b7053SJung-uk Kim switch (o) { 91e71b7053SJung-uk Kim case OPT_EOF: 92e71b7053SJung-uk Kim case OPT_ERR: 93e71b7053SJung-uk Kim opthelp: 94e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 955c87c606SMark Murray goto end; 96e71b7053SJung-uk Kim case OPT_HELP: 97e71b7053SJung-uk Kim opt_help(rsautl_options); 98e71b7053SJung-uk Kim ret = 0; 99e71b7053SJung-uk Kim goto end; 100e71b7053SJung-uk Kim case OPT_KEYFORM: 101*b077aed3SPierre Pronchery if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat)) 102e71b7053SJung-uk Kim goto opthelp; 103e71b7053SJung-uk Kim break; 104e71b7053SJung-uk Kim case OPT_IN: 105e71b7053SJung-uk Kim infile = opt_arg(); 106e71b7053SJung-uk Kim break; 107e71b7053SJung-uk Kim case OPT_OUT: 108e71b7053SJung-uk Kim outfile = opt_arg(); 109e71b7053SJung-uk Kim break; 110e71b7053SJung-uk Kim case OPT_ENGINE: 111e71b7053SJung-uk Kim e = setup_engine(opt_arg(), 0); 112e71b7053SJung-uk Kim break; 113e71b7053SJung-uk Kim case OPT_ASN1PARSE: 1146f9291ceSJung-uk Kim asn1parse = 1; 115e71b7053SJung-uk Kim break; 116e71b7053SJung-uk Kim case OPT_HEXDUMP: 1176f9291ceSJung-uk Kim hexdump = 1; 118e71b7053SJung-uk Kim break; 119*b077aed3SPierre Pronchery case OPT_RSA_RAW: 1206f9291ceSJung-uk Kim pad = RSA_NO_PADDING; 121e71b7053SJung-uk Kim break; 122e71b7053SJung-uk Kim case OPT_OAEP: 1236f9291ceSJung-uk Kim pad = RSA_PKCS1_OAEP_PADDING; 124e71b7053SJung-uk Kim break; 125e71b7053SJung-uk Kim case OPT_PKCS: 1266f9291ceSJung-uk Kim pad = RSA_PKCS1_PADDING; 127e71b7053SJung-uk Kim break; 128e71b7053SJung-uk Kim case OPT_X931: 1296f9291ceSJung-uk Kim pad = RSA_X931_PADDING; 130e71b7053SJung-uk Kim break; 131e71b7053SJung-uk Kim case OPT_SIGN: 132ddd58736SKris Kennaway rsa_mode = RSA_SIGN; 133ddd58736SKris Kennaway need_priv = 1; 134e71b7053SJung-uk Kim break; 135e71b7053SJung-uk Kim case OPT_VERIFY: 1366f9291ceSJung-uk Kim rsa_mode = RSA_VERIFY; 137e71b7053SJung-uk Kim break; 138e71b7053SJung-uk Kim case OPT_REV: 1396f9291ceSJung-uk Kim rev = 1; 140e71b7053SJung-uk Kim break; 141e71b7053SJung-uk Kim case OPT_ENCRYPT: 1426f9291ceSJung-uk Kim rsa_mode = RSA_ENCRYPT; 143e71b7053SJung-uk Kim break; 144e71b7053SJung-uk Kim case OPT_DECRYPT: 145ddd58736SKris Kennaway rsa_mode = RSA_DECRYPT; 146ddd58736SKris Kennaway need_priv = 1; 147e71b7053SJung-uk Kim break; 148e71b7053SJung-uk Kim case OPT_PUBIN: 149e71b7053SJung-uk Kim key_type = KEY_PUBKEY; 150e71b7053SJung-uk Kim break; 151e71b7053SJung-uk Kim case OPT_CERTIN: 152e71b7053SJung-uk Kim key_type = KEY_CERT; 153e71b7053SJung-uk Kim break; 154e71b7053SJung-uk Kim case OPT_INKEY: 155e71b7053SJung-uk Kim keyfile = opt_arg(); 156e71b7053SJung-uk Kim break; 157e71b7053SJung-uk Kim case OPT_PASSIN: 158e71b7053SJung-uk Kim passinarg = opt_arg(); 159e71b7053SJung-uk Kim break; 160e71b7053SJung-uk Kim case OPT_R_CASES: 161e71b7053SJung-uk Kim if (!opt_rand(o)) 162ddd58736SKris Kennaway goto end; 163e71b7053SJung-uk Kim break; 164*b077aed3SPierre Pronchery case OPT_PROV_CASES: 165*b077aed3SPierre Pronchery if (!opt_provider(o)) 166*b077aed3SPierre Pronchery goto end; 167*b077aed3SPierre Pronchery break; 168ddd58736SKris Kennaway } 169ddd58736SKris Kennaway } 170*b077aed3SPierre Pronchery 171*b077aed3SPierre Pronchery /* No extra arguments. */ 172e71b7053SJung-uk Kim argc = opt_num_rest(); 173e71b7053SJung-uk Kim if (argc != 0) 174e71b7053SJung-uk Kim goto opthelp; 175ddd58736SKris Kennaway 176*b077aed3SPierre Pronchery if (!app_RAND_load()) 177*b077aed3SPierre Pronchery goto end; 178*b077aed3SPierre Pronchery 179ddd58736SKris Kennaway if (need_priv && (key_type != KEY_PRIVKEY)) { 180ddd58736SKris Kennaway BIO_printf(bio_err, "A private key is needed for this operation\n"); 181ddd58736SKris Kennaway goto end; 182ddd58736SKris Kennaway } 183e71b7053SJung-uk Kim 184e71b7053SJung-uk Kim if (!app_passwd(passinarg, NULL, &passin, NULL)) { 185ced566fdSJacques Vidrine BIO_printf(bio_err, "Error getting password\n"); 186ced566fdSJacques Vidrine goto end; 187ced566fdSJacques Vidrine } 1885c87c606SMark Murray 189ddd58736SKris Kennaway switch (key_type) { 190ddd58736SKris Kennaway case KEY_PRIVKEY: 191*b077aed3SPierre Pronchery pkey = load_key(keyfile, keyformat, 0, passin, e, "private key"); 192ddd58736SKris Kennaway break; 193ddd58736SKris Kennaway 194ddd58736SKris Kennaway case KEY_PUBKEY: 195*b077aed3SPierre Pronchery pkey = load_pubkey(keyfile, keyformat, 0, NULL, e, "public key"); 196ddd58736SKris Kennaway break; 197ddd58736SKris Kennaway 198ddd58736SKris Kennaway case KEY_CERT: 199*b077aed3SPierre Pronchery x = load_cert(keyfile, FORMAT_UNDEF, "Certificate"); 200ddd58736SKris Kennaway if (x) { 201ddd58736SKris Kennaway pkey = X509_get_pubkey(x); 202ddd58736SKris Kennaway X509_free(x); 203ddd58736SKris Kennaway } 204ddd58736SKris Kennaway break; 205ddd58736SKris Kennaway } 206ddd58736SKris Kennaway 207e71b7053SJung-uk Kim if (pkey == NULL) 208ddd58736SKris Kennaway return 1; 209ddd58736SKris Kennaway 210e71b7053SJung-uk Kim in = bio_open_default(infile, 'r', FORMAT_BINARY); 211e71b7053SJung-uk Kim if (in == NULL) 212ddd58736SKris Kennaway goto end; 213e71b7053SJung-uk Kim out = bio_open_default(outfile, 'w', FORMAT_BINARY); 214e71b7053SJung-uk Kim if (out == NULL) 215ddd58736SKris Kennaway goto end; 216ddd58736SKris Kennaway 217*b077aed3SPierre Pronchery keysize = EVP_PKEY_get_size(pkey); 218ddd58736SKris Kennaway 219e71b7053SJung-uk Kim rsa_in = app_malloc(keysize * 2, "hold rsa key"); 220e71b7053SJung-uk Kim rsa_out = app_malloc(keysize, "output rsa key"); 221*b077aed3SPierre Pronchery rsa_outlen = keysize; 222ddd58736SKris Kennaway 223ddd58736SKris Kennaway /* Read the input data */ 224*b077aed3SPierre Pronchery rv = BIO_read(in, rsa_in, keysize * 2); 225*b077aed3SPierre Pronchery if (rv < 0) { 226ddd58736SKris Kennaway BIO_printf(bio_err, "Error reading input Data\n"); 227e71b7053SJung-uk Kim goto end; 228ddd58736SKris Kennaway } 229*b077aed3SPierre Pronchery rsa_inlen = rv; 230ddd58736SKris Kennaway if (rev) { 231*b077aed3SPierre Pronchery size_t i; 232ddd58736SKris Kennaway unsigned char ctmp; 233*b077aed3SPierre Pronchery 234ddd58736SKris Kennaway for (i = 0; i < rsa_inlen / 2; i++) { 235ddd58736SKris Kennaway ctmp = rsa_in[i]; 236ddd58736SKris Kennaway rsa_in[i] = rsa_in[rsa_inlen - 1 - i]; 237ddd58736SKris Kennaway rsa_in[rsa_inlen - 1 - i] = ctmp; 238ddd58736SKris Kennaway } 239ddd58736SKris Kennaway } 240*b077aed3SPierre Pronchery 241*b077aed3SPierre Pronchery if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL) 242*b077aed3SPierre Pronchery goto end; 243*b077aed3SPierre Pronchery 244ddd58736SKris Kennaway switch (rsa_mode) { 245ddd58736SKris Kennaway case RSA_VERIFY: 246*b077aed3SPierre Pronchery rv = EVP_PKEY_verify_recover_init(ctx) > 0 247*b077aed3SPierre Pronchery && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0 248*b077aed3SPierre Pronchery && EVP_PKEY_verify_recover(ctx, rsa_out, &rsa_outlen, 249*b077aed3SPierre Pronchery rsa_in, rsa_inlen) > 0; 250ddd58736SKris Kennaway break; 251ddd58736SKris Kennaway case RSA_SIGN: 252*b077aed3SPierre Pronchery rv = EVP_PKEY_sign_init(ctx) > 0 253*b077aed3SPierre Pronchery && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0 254*b077aed3SPierre Pronchery && EVP_PKEY_sign(ctx, rsa_out, &rsa_outlen, rsa_in, rsa_inlen) > 0; 255ddd58736SKris Kennaway break; 256ddd58736SKris Kennaway case RSA_ENCRYPT: 257*b077aed3SPierre Pronchery rv = EVP_PKEY_encrypt_init(ctx) > 0 258*b077aed3SPierre Pronchery && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0 259*b077aed3SPierre Pronchery && EVP_PKEY_encrypt(ctx, rsa_out, &rsa_outlen, rsa_in, rsa_inlen) > 0; 260ddd58736SKris Kennaway break; 261ddd58736SKris Kennaway case RSA_DECRYPT: 262*b077aed3SPierre Pronchery rv = EVP_PKEY_decrypt_init(ctx) > 0 263*b077aed3SPierre Pronchery && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0 264*b077aed3SPierre Pronchery && EVP_PKEY_decrypt(ctx, rsa_out, &rsa_outlen, rsa_in, rsa_inlen) > 0; 265ddd58736SKris Kennaway break; 266ddd58736SKris Kennaway } 267ddd58736SKris Kennaway 268*b077aed3SPierre Pronchery if (!rv) { 269ddd58736SKris Kennaway BIO_printf(bio_err, "RSA operation error\n"); 270ddd58736SKris Kennaway ERR_print_errors(bio_err); 271ddd58736SKris Kennaway goto end; 272ddd58736SKris Kennaway } 273ddd58736SKris Kennaway ret = 0; 274ddd58736SKris Kennaway if (asn1parse) { 275ddd58736SKris Kennaway if (!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) { 276ddd58736SKris Kennaway ERR_print_errors(bio_err); 277ddd58736SKris Kennaway } 278e71b7053SJung-uk Kim } else if (hexdump) { 2796f9291ceSJung-uk Kim BIO_dump(out, (char *)rsa_out, rsa_outlen); 280e71b7053SJung-uk Kim } else { 2816f9291ceSJung-uk Kim BIO_write(out, rsa_out, rsa_outlen); 282e71b7053SJung-uk Kim } 283ddd58736SKris Kennaway end: 284*b077aed3SPierre Pronchery EVP_PKEY_CTX_free(ctx); 285*b077aed3SPierre Pronchery EVP_PKEY_free(pkey); 2866cf8931aSJung-uk Kim release_engine(e); 287ddd58736SKris Kennaway BIO_free(in); 288ddd58736SKris Kennaway BIO_free_all(out); 2896f9291ceSJung-uk Kim OPENSSL_free(rsa_in); 2906f9291ceSJung-uk Kim OPENSSL_free(rsa_out); 2916f9291ceSJung-uk Kim OPENSSL_free(passin); 292ddd58736SKris Kennaway return ret; 293ddd58736SKris Kennaway } 294