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