|
1 /* rsautl.c */ |
|
2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) 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 #ifndef OPENSSL_NO_RSA |
|
61 |
|
62 #include "apps.h" |
|
63 #include <string.h> |
|
64 #include <openssl/err.h> |
|
65 #include <openssl/pem.h> |
|
66 #include <openssl/rsa.h> |
|
67 |
|
68 #define RSA_SIGN 1 |
|
69 #define RSA_VERIFY 2 |
|
70 #define RSA_ENCRYPT 3 |
|
71 #define RSA_DECRYPT 4 |
|
72 |
|
73 #define KEY_PRIVKEY 1 |
|
74 #define KEY_PUBKEY 2 |
|
75 #define KEY_CERT 3 |
|
76 |
|
77 static void usage(void); |
|
78 |
|
79 #undef PROG |
|
80 |
|
81 #define PROG rsautl_main |
|
82 |
|
83 |
|
84 int MAIN(int argc, char **); |
|
85 |
|
86 int MAIN(int argc, char **argv) |
|
87 { |
|
88 ENGINE *e = NULL; |
|
89 BIO *in = NULL, *out = NULL; |
|
90 char *infile = NULL, *outfile = NULL; |
|
91 #ifndef OPENSSL_NO_ENGINE |
|
92 char *engine = NULL; |
|
93 #endif |
|
94 char *keyfile = NULL; |
|
95 char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY; |
|
96 int keyform = FORMAT_PEM; |
|
97 char need_priv = 0, badarg = 0, rev = 0; |
|
98 char hexdump = 0, asn1parse = 0; |
|
99 X509 *x; |
|
100 EVP_PKEY *pkey = NULL; |
|
101 RSA *rsa = NULL; |
|
102 unsigned char *rsa_in = NULL, *rsa_out = NULL, pad; |
|
103 char *passargin = NULL, *passin = NULL; |
|
104 int rsa_inlen, rsa_outlen = 0; |
|
105 int keysize; |
|
106 |
|
107 int ret = 1; |
|
108 |
|
109 argc--; |
|
110 argv++; |
|
111 if(!bio_err) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); |
|
112 |
|
113 if (!load_config(bio_err, NULL)) |
|
114 goto end; |
|
115 ERR_load_crypto_strings(); |
|
116 OpenSSL_add_all_algorithms(); |
|
117 pad = RSA_PKCS1_PADDING; |
|
118 |
|
119 while(argc >= 1) |
|
120 { |
|
121 if (!strcmp(*argv,"-in")) { |
|
122 if (--argc < 1) badarg = 1; |
|
123 infile= *(++argv); |
|
124 } else if (!strcmp(*argv,"-out")) { |
|
125 if (--argc < 1) badarg = 1; |
|
126 outfile= *(++argv); |
|
127 } else if(!strcmp(*argv, "-inkey")) { |
|
128 if (--argc < 1) badarg = 1; |
|
129 keyfile = *(++argv); |
|
130 } else if (!strcmp(*argv,"-passin")) { |
|
131 if (--argc < 1) badarg = 1; |
|
132 passargin= *(++argv); |
|
133 } else if (strcmp(*argv,"-keyform") == 0) { |
|
134 if (--argc < 1) badarg = 1; |
|
135 keyform=str2fmt(*(++argv)); |
|
136 #ifndef OPENSSL_NO_ENGINE |
|
137 } else if(!strcmp(*argv, "-engine")) { |
|
138 if (--argc < 1) badarg = 1; |
|
139 engine = *(++argv); |
|
140 #endif |
|
141 } else if(!strcmp(*argv, "-pubin")) { |
|
142 key_type = KEY_PUBKEY; |
|
143 } else if(!strcmp(*argv, "-certin")) { |
|
144 key_type = KEY_CERT; |
|
145 } |
|
146 else if(!strcmp(*argv, "-asn1parse")) asn1parse = 1; |
|
147 else if(!strcmp(*argv, "-hexdump")) hexdump = 1; |
|
148 else if(!strcmp(*argv, "-raw")) pad = RSA_NO_PADDING; |
|
149 else if(!strcmp(*argv, "-oaep")) pad = RSA_PKCS1_OAEP_PADDING; |
|
150 else if(!strcmp(*argv, "-ssl")) pad = RSA_SSLV23_PADDING; |
|
151 else if(!strcmp(*argv, "-pkcs")) pad = RSA_PKCS1_PADDING; |
|
152 else if(!strcmp(*argv, "-x931")) pad = RSA_X931_PADDING; |
|
153 else if(!strcmp(*argv, "-sign")) { |
|
154 rsa_mode = RSA_SIGN; |
|
155 need_priv = 1; |
|
156 } else if(!strcmp(*argv, "-verify")) rsa_mode = RSA_VERIFY; |
|
157 else if(!strcmp(*argv, "-rev")) rev = 1; |
|
158 else if(!strcmp(*argv, "-encrypt")) rsa_mode = RSA_ENCRYPT; |
|
159 else if(!strcmp(*argv, "-decrypt")) { |
|
160 rsa_mode = RSA_DECRYPT; |
|
161 need_priv = 1; |
|
162 } else badarg = 1; |
|
163 if(badarg) { |
|
164 usage(); |
|
165 goto end; |
|
166 } |
|
167 argc--; |
|
168 argv++; |
|
169 } |
|
170 |
|
171 if(need_priv && (key_type != KEY_PRIVKEY)) { |
|
172 BIO_printf(bio_err, "A private key is needed for this operation\n"); |
|
173 goto end; |
|
174 } |
|
175 |
|
176 #ifndef OPENSSL_NO_ENGINE |
|
177 e = setup_engine(bio_err, engine, 0); |
|
178 #endif |
|
179 if(!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { |
|
180 BIO_printf(bio_err, "Error getting password\n"); |
|
181 goto end; |
|
182 } |
|
183 |
|
184 /* FIXME: seed PRNG only if needed */ |
|
185 app_RAND_load_file(NULL, bio_err, 0); |
|
186 |
|
187 switch(key_type) { |
|
188 case KEY_PRIVKEY: |
|
189 pkey = load_key(bio_err, keyfile, keyform, 0, |
|
190 passin, e, "Private Key"); |
|
191 break; |
|
192 |
|
193 case KEY_PUBKEY: |
|
194 pkey = load_pubkey(bio_err, keyfile, keyform, 0, |
|
195 NULL, e, "Public Key"); |
|
196 break; |
|
197 |
|
198 case KEY_CERT: |
|
199 x = load_cert(bio_err, keyfile, keyform, |
|
200 NULL, e, "Certificate"); |
|
201 if(x) { |
|
202 pkey = X509_get_pubkey(x); |
|
203 X509_free(x); |
|
204 } |
|
205 break; |
|
206 } |
|
207 |
|
208 if(!pkey) { |
|
209 return 1; |
|
210 } |
|
211 |
|
212 rsa = EVP_PKEY_get1_RSA(pkey); |
|
213 EVP_PKEY_free(pkey); |
|
214 |
|
215 if(!rsa) { |
|
216 BIO_printf(bio_err, "Error getting RSA key\n"); |
|
217 ERR_print_errors(bio_err); |
|
218 goto end; |
|
219 } |
|
220 |
|
221 |
|
222 if(infile) { |
|
223 if(!(in = BIO_new_file(infile, "rb"))) { |
|
224 BIO_printf(bio_err, "Error Reading Input File\n"); |
|
225 ERR_print_errors(bio_err); |
|
226 goto end; |
|
227 } |
|
228 } |
|
229 else |
|
230 in = BIO_new_fp(stdin, BIO_NOCLOSE); |
|
231 |
|
232 if(outfile) { |
|
233 if(!(out = BIO_new_file(outfile, "wb"))) { |
|
234 BIO_printf(bio_err, "Error Reading Output File\n"); |
|
235 ERR_print_errors(bio_err); |
|
236 goto end; |
|
237 } |
|
238 } else { |
|
239 |
|
240 out = BIO_new_fp(stdout, BIO_NOCLOSE); |
|
241 #ifdef OPENSSL_SYS_VMS |
|
242 { |
|
243 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); |
|
244 out = BIO_push(tmpbio, out); |
|
245 } |
|
246 #endif |
|
247 } |
|
248 |
|
249 keysize = RSA_size(rsa); |
|
250 |
|
251 rsa_in = OPENSSL_malloc(keysize * 2); |
|
252 rsa_out = OPENSSL_malloc(keysize); |
|
253 |
|
254 /* Read the input data */ |
|
255 rsa_inlen = BIO_read(in, rsa_in, keysize * 2); |
|
256 if(rsa_inlen <= 0) { |
|
257 BIO_printf(bio_err, "Error reading input Data\n"); |
|
258 exit(1); |
|
259 } |
|
260 if(rev) { |
|
261 int i; |
|
262 unsigned char ctmp; |
|
263 for(i = 0; i < rsa_inlen/2; i++) { |
|
264 ctmp = rsa_in[i]; |
|
265 rsa_in[i] = rsa_in[rsa_inlen - 1 - i]; |
|
266 rsa_in[rsa_inlen - 1 - i] = ctmp; |
|
267 } |
|
268 } |
|
269 switch(rsa_mode) { |
|
270 |
|
271 case RSA_VERIFY: |
|
272 rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); |
|
273 break; |
|
274 |
|
275 case RSA_SIGN: |
|
276 rsa_outlen = RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); |
|
277 break; |
|
278 |
|
279 case RSA_ENCRYPT: |
|
280 rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); |
|
281 break; |
|
282 |
|
283 case RSA_DECRYPT: |
|
284 rsa_outlen = RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); |
|
285 break; |
|
286 |
|
287 } |
|
288 |
|
289 if(rsa_outlen <= 0) { |
|
290 BIO_printf(bio_err, "RSA operation error\n"); |
|
291 ERR_print_errors(bio_err); |
|
292 goto end; |
|
293 } |
|
294 ret = 0; |
|
295 if(asn1parse) { |
|
296 if(!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) { |
|
297 ERR_print_errors(bio_err); |
|
298 } |
|
299 } else if(hexdump) BIO_dump(out, (char *)rsa_out, rsa_outlen); |
|
300 else BIO_write(out, rsa_out, rsa_outlen); |
|
301 end: |
|
302 RSA_free(rsa); |
|
303 BIO_free(in); |
|
304 BIO_free_all(out); |
|
305 if(rsa_in) OPENSSL_free(rsa_in); |
|
306 if(rsa_out) OPENSSL_free(rsa_out); |
|
307 if(passin) OPENSSL_free(passin); |
|
308 return ret; |
|
309 } |
|
310 |
|
311 static void usage() |
|
312 { |
|
313 BIO_printf(bio_err, "Usage: rsautl [options]\n"); |
|
314 BIO_printf(bio_err, "-in file input file\n"); |
|
315 BIO_printf(bio_err, "-out file output file\n"); |
|
316 BIO_printf(bio_err, "-inkey file input key\n"); |
|
317 BIO_printf(bio_err, "-keyform arg private key format - default PEM\n"); |
|
318 BIO_printf(bio_err, "-pubin input is an RSA public\n"); |
|
319 BIO_printf(bio_err, "-certin input is a certificate carrying an RSA public key\n"); |
|
320 BIO_printf(bio_err, "-ssl use SSL v2 padding\n"); |
|
321 BIO_printf(bio_err, "-raw use no padding\n"); |
|
322 BIO_printf(bio_err, "-pkcs use PKCS#1 v1.5 padding (default)\n"); |
|
323 BIO_printf(bio_err, "-oaep use PKCS#1 OAEP\n"); |
|
324 BIO_printf(bio_err, "-sign sign with private key\n"); |
|
325 BIO_printf(bio_err, "-verify verify with public key\n"); |
|
326 BIO_printf(bio_err, "-encrypt encrypt with public key\n"); |
|
327 BIO_printf(bio_err, "-decrypt decrypt with private key\n"); |
|
328 BIO_printf(bio_err, "-hexdump hex dump output\n"); |
|
329 #ifndef OPENSSL_NO_ENGINE |
|
330 BIO_printf(bio_err, "-engine e use engine e, possibly a hardware device.\n"); |
|
331 BIO_printf (bio_err, "-passin arg pass phrase source\n"); |
|
332 #endif |
|
333 |
|
334 } |
|
335 |
|
336 #endif |