rsautl.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /* rsautl.c */
  2. /*
  3. * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
  4. * 2000.
  5. */
  6. /* ====================================================================
  7. * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. *
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. *
  16. * 2. Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in
  18. * the documentation and/or other materials provided with the
  19. * distribution.
  20. *
  21. * 3. All advertising materials mentioning features or use of this
  22. * software must display the following acknowledgment:
  23. * "This product includes software developed by the OpenSSL Project
  24. * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  25. *
  26. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  27. * endorse or promote products derived from this software without
  28. * prior written permission. For written permission, please contact
  29. * licensing@OpenSSL.org.
  30. *
  31. * 5. Products derived from this software may not be called "OpenSSL"
  32. * nor may "OpenSSL" appear in their names without prior written
  33. * permission of the OpenSSL Project.
  34. *
  35. * 6. Redistributions of any form whatsoever must retain the following
  36. * acknowledgment:
  37. * "This product includes software developed by the OpenSSL Project
  38. * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  39. *
  40. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  41. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  42. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  43. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  44. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  45. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  46. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  47. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  48. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  49. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  50. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  51. * OF THE POSSIBILITY OF SUCH DAMAGE.
  52. * ====================================================================
  53. *
  54. * This product includes cryptographic software written by Eric Young
  55. * (eay@cryptsoft.com). This product includes software written by Tim
  56. * Hudson (tjh@cryptsoft.com).
  57. *
  58. */
  59. #include <openssl/opensslconf.h>
  60. #ifndef OPENSSL_NO_RSA
  61. # include "apps.h"
  62. # include <string.h>
  63. # include <openssl/err.h>
  64. # include <openssl/pem.h>
  65. # include <openssl/rsa.h>
  66. # define RSA_SIGN 1
  67. # define RSA_VERIFY 2
  68. # define RSA_ENCRYPT 3
  69. # define RSA_DECRYPT 4
  70. # define KEY_PRIVKEY 1
  71. # define KEY_PUBKEY 2
  72. # define KEY_CERT 3
  73. static void usage(void);
  74. # undef PROG
  75. # define PROG rsautl_main
  76. int MAIN(int argc, char **);
  77. int MAIN(int argc, char **argv)
  78. {
  79. ENGINE *e = NULL;
  80. BIO *in = NULL, *out = NULL;
  81. char *infile = NULL, *outfile = NULL;
  82. # ifndef OPENSSL_NO_ENGINE
  83. char *engine = NULL;
  84. # endif
  85. char *keyfile = NULL;
  86. char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY;
  87. int keyform = FORMAT_PEM;
  88. char need_priv = 0, badarg = 0, rev = 0;
  89. char hexdump = 0, asn1parse = 0;
  90. X509 *x;
  91. EVP_PKEY *pkey = NULL;
  92. RSA *rsa = NULL;
  93. unsigned char *rsa_in = NULL, *rsa_out = NULL, pad;
  94. char *passargin = NULL, *passin = NULL;
  95. int rsa_inlen, rsa_outlen = 0;
  96. int keysize;
  97. int ret = 1;
  98. argc--;
  99. argv++;
  100. if (!bio_err)
  101. bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
  102. if (!load_config(bio_err, NULL))
  103. goto end;
  104. ERR_load_crypto_strings();
  105. OpenSSL_add_all_algorithms();
  106. pad = RSA_PKCS1_PADDING;
  107. while (argc >= 1) {
  108. if (!strcmp(*argv, "-in")) {
  109. if (--argc < 1)
  110. badarg = 1;
  111. else
  112. infile = *(++argv);
  113. } else if (!strcmp(*argv, "-out")) {
  114. if (--argc < 1)
  115. badarg = 1;
  116. else
  117. outfile = *(++argv);
  118. } else if (!strcmp(*argv, "-inkey")) {
  119. if (--argc < 1)
  120. badarg = 1;
  121. else
  122. keyfile = *(++argv);
  123. } else if (!strcmp(*argv, "-passin")) {
  124. if (--argc < 1)
  125. badarg = 1;
  126. else
  127. passargin = *(++argv);
  128. } else if (strcmp(*argv, "-keyform") == 0) {
  129. if (--argc < 1)
  130. badarg = 1;
  131. else
  132. keyform = str2fmt(*(++argv));
  133. # ifndef OPENSSL_NO_ENGINE
  134. } else if (!strcmp(*argv, "-engine")) {
  135. if (--argc < 1)
  136. badarg = 1;
  137. else
  138. engine = *(++argv);
  139. # endif
  140. } else if (!strcmp(*argv, "-pubin")) {
  141. key_type = KEY_PUBKEY;
  142. } else if (!strcmp(*argv, "-certin")) {
  143. key_type = KEY_CERT;
  144. } else if (!strcmp(*argv, "-asn1parse"))
  145. asn1parse = 1;
  146. else if (!strcmp(*argv, "-hexdump"))
  147. hexdump = 1;
  148. else if (!strcmp(*argv, "-raw"))
  149. pad = RSA_NO_PADDING;
  150. else if (!strcmp(*argv, "-oaep"))
  151. pad = RSA_PKCS1_OAEP_PADDING;
  152. else if (!strcmp(*argv, "-ssl"))
  153. pad = RSA_SSLV23_PADDING;
  154. else if (!strcmp(*argv, "-pkcs"))
  155. pad = RSA_PKCS1_PADDING;
  156. else if (!strcmp(*argv, "-x931"))
  157. pad = RSA_X931_PADDING;
  158. else if (!strcmp(*argv, "-sign")) {
  159. rsa_mode = RSA_SIGN;
  160. need_priv = 1;
  161. } else if (!strcmp(*argv, "-verify"))
  162. rsa_mode = RSA_VERIFY;
  163. else if (!strcmp(*argv, "-rev"))
  164. rev = 1;
  165. else if (!strcmp(*argv, "-encrypt"))
  166. rsa_mode = RSA_ENCRYPT;
  167. else if (!strcmp(*argv, "-decrypt")) {
  168. rsa_mode = RSA_DECRYPT;
  169. need_priv = 1;
  170. } else
  171. badarg = 1;
  172. if (badarg) {
  173. usage();
  174. goto end;
  175. }
  176. argc--;
  177. argv++;
  178. }
  179. if (need_priv && (key_type != KEY_PRIVKEY)) {
  180. BIO_printf(bio_err, "A private key is needed for this operation\n");
  181. goto end;
  182. }
  183. # ifndef OPENSSL_NO_ENGINE
  184. e = setup_engine(bio_err, engine, 0);
  185. # endif
  186. if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
  187. BIO_printf(bio_err, "Error getting password\n");
  188. goto end;
  189. }
  190. /* FIXME: seed PRNG only if needed */
  191. app_RAND_load_file(NULL, bio_err, 0);
  192. switch (key_type) {
  193. case KEY_PRIVKEY:
  194. pkey = load_key(bio_err, keyfile, keyform, 0,
  195. passin, e, "Private Key");
  196. break;
  197. case KEY_PUBKEY:
  198. pkey = load_pubkey(bio_err, keyfile, keyform, 0,
  199. NULL, e, "Public Key");
  200. break;
  201. case KEY_CERT:
  202. x = load_cert(bio_err, keyfile, keyform, NULL, e, "Certificate");
  203. if (x) {
  204. pkey = X509_get_pubkey(x);
  205. X509_free(x);
  206. }
  207. break;
  208. }
  209. if (!pkey) {
  210. return 1;
  211. }
  212. rsa = EVP_PKEY_get1_RSA(pkey);
  213. EVP_PKEY_free(pkey);
  214. if (!rsa) {
  215. BIO_printf(bio_err, "Error getting RSA key\n");
  216. ERR_print_errors(bio_err);
  217. goto end;
  218. }
  219. if (infile) {
  220. if (!(in = BIO_new_file(infile, "rb"))) {
  221. BIO_printf(bio_err, "Error Reading Input File\n");
  222. ERR_print_errors(bio_err);
  223. goto end;
  224. }
  225. } else
  226. in = BIO_new_fp(stdin, BIO_NOCLOSE);
  227. if (outfile) {
  228. if (!(out = BIO_new_file(outfile, "wb"))) {
  229. BIO_printf(bio_err, "Error Reading Output File\n");
  230. ERR_print_errors(bio_err);
  231. goto end;
  232. }
  233. } else {
  234. out = BIO_new_fp(stdout, BIO_NOCLOSE);
  235. # ifdef OPENSSL_SYS_VMS
  236. {
  237. BIO *tmpbio = BIO_new(BIO_f_linebuffer());
  238. out = BIO_push(tmpbio, out);
  239. }
  240. # endif
  241. }
  242. keysize = RSA_size(rsa);
  243. rsa_in = OPENSSL_malloc(keysize * 2);
  244. rsa_out = OPENSSL_malloc(keysize);
  245. /* Read the input data */
  246. rsa_inlen = BIO_read(in, rsa_in, keysize * 2);
  247. if (rsa_inlen <= 0) {
  248. BIO_printf(bio_err, "Error reading input Data\n");
  249. exit(1);
  250. }
  251. if (rev) {
  252. int i;
  253. unsigned char ctmp;
  254. for (i = 0; i < rsa_inlen / 2; i++) {
  255. ctmp = rsa_in[i];
  256. rsa_in[i] = rsa_in[rsa_inlen - 1 - i];
  257. rsa_in[rsa_inlen - 1 - i] = ctmp;
  258. }
  259. }
  260. switch (rsa_mode) {
  261. case RSA_VERIFY:
  262. rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
  263. break;
  264. case RSA_SIGN:
  265. rsa_outlen =
  266. RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
  267. break;
  268. case RSA_ENCRYPT:
  269. rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
  270. break;
  271. case RSA_DECRYPT:
  272. rsa_outlen =
  273. RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
  274. break;
  275. }
  276. if (rsa_outlen <= 0) {
  277. BIO_printf(bio_err, "RSA operation error\n");
  278. ERR_print_errors(bio_err);
  279. goto end;
  280. }
  281. ret = 0;
  282. if (asn1parse) {
  283. if (!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) {
  284. ERR_print_errors(bio_err);
  285. }
  286. } else if (hexdump)
  287. BIO_dump(out, (char *)rsa_out, rsa_outlen);
  288. else
  289. BIO_write(out, rsa_out, rsa_outlen);
  290. end:
  291. RSA_free(rsa);
  292. BIO_free(in);
  293. BIO_free_all(out);
  294. if (rsa_in)
  295. OPENSSL_free(rsa_in);
  296. if (rsa_out)
  297. OPENSSL_free(rsa_out);
  298. if (passin)
  299. OPENSSL_free(passin);
  300. return ret;
  301. }
  302. static void usage()
  303. {
  304. BIO_printf(bio_err, "Usage: rsautl [options]\n");
  305. BIO_printf(bio_err, "-in file input file\n");
  306. BIO_printf(bio_err, "-out file output file\n");
  307. BIO_printf(bio_err, "-inkey file input key\n");
  308. BIO_printf(bio_err, "-keyform arg private key format - default PEM\n");
  309. BIO_printf(bio_err, "-pubin input is an RSA public\n");
  310. BIO_printf(bio_err,
  311. "-certin input is a certificate carrying an RSA public key\n");
  312. BIO_printf(bio_err, "-ssl use SSL v2 padding\n");
  313. BIO_printf(bio_err, "-raw use no padding\n");
  314. BIO_printf(bio_err,
  315. "-pkcs use PKCS#1 v1.5 padding (default)\n");
  316. BIO_printf(bio_err, "-oaep use PKCS#1 OAEP\n");
  317. BIO_printf(bio_err, "-sign sign with private key\n");
  318. BIO_printf(bio_err, "-verify verify with public key\n");
  319. BIO_printf(bio_err, "-encrypt encrypt with public key\n");
  320. BIO_printf(bio_err, "-decrypt decrypt with private key\n");
  321. BIO_printf(bio_err, "-hexdump hex dump output\n");
  322. # ifndef OPENSSL_NO_ENGINE
  323. BIO_printf(bio_err,
  324. "-engine e use engine e, possibly a hardware device.\n");
  325. BIO_printf(bio_err, "-passin arg pass phrase source\n");
  326. # endif
  327. }
  328. #endif