x
[heimdal.git] / lib / hcrypto / test_rsa.c
blob49a78ccf39840944023b2ce01f9d1d397b66d6ea
1 /*
2 * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
38 #ifdef RCSID
39 RCSID("$Id$");
40 #endif
42 #include <stdio.h>
44 #include <roken.h>
45 #include <getarg.h>
47 #include <engine.h>
48 #include <evp.h>
54 static int version_flag;
55 static int help_flag;
56 static int time_keygen;
57 static char *time_key;
58 static int key_blinding = 1;
59 static char *rsa_key;
60 static char *id_flag;
61 static int loops = 1;
63 static struct getargs args[] = {
64 { "loops", 0, arg_integer, &loops,
65 "number of loops", "loops" },
66 { "id", 0, arg_string, &id_flag,
67 "selects the engine id", "engine-id" },
68 { "time-keygen", 0, arg_flag, &time_keygen,
69 "time rsa generation", NULL },
70 { "time-key", 0, arg_string, &time_key,
71 "rsa key file", NULL },
72 { "key-blinding", 0, arg_negative_flag, &key_blinding,
73 "key blinding", NULL },
74 { "key", 0, arg_string, &rsa_key,
75 "rsa key file", NULL },
76 { "version", 0, arg_flag, &version_flag,
77 "print version", NULL },
78 { "help", 0, arg_flag, &help_flag,
79 NULL, NULL }
86 static void
87 check_rsa(const unsigned char *in, size_t len, RSA *rsa, int padding)
89 unsigned char *res, *res2;
90 int keylen;
92 res = malloc(RSA_size(rsa));
93 if (res == NULL)
94 errx(1, "res: ENOMEM");
96 res2 = malloc(RSA_size(rsa));
97 if (res2 == NULL)
98 errx(1, "res2: ENOMEM");
100 /* signing */
102 keylen = RSA_private_encrypt(len, in, res, rsa, padding);
103 if (keylen <= 0)
104 errx(1, "failed to private encrypt: %d %d", (int)len, (int)keylen);
106 if (keylen > RSA_size(rsa))
107 errx(1, "keylen > RSA_size(rsa)");
109 keylen = RSA_public_decrypt(keylen, res, res2, rsa, padding);
110 if (keylen <= 0)
111 errx(1, "failed to public decrypt: %d", (int)keylen);
113 if (keylen != len)
114 errx(1, "output buffer not same length: %d", (int)keylen);
116 if (memcmp(res2, in, len) != 0)
117 errx(1, "string not the same after decryption");
119 /* encryption */
121 keylen = RSA_public_encrypt(len, in, res, rsa, padding);
122 if (keylen <= 0)
123 errx(1, "failed to public encrypt: %d", (int)keylen);
125 if (keylen > RSA_size(rsa))
126 errx(1, "keylen > RSA_size(rsa)");
128 keylen = RSA_private_decrypt(keylen, res, res2, rsa, padding);
129 if (keylen <= 0)
130 errx(1, "failed to private decrypt: %d", (int)keylen);
132 if (keylen != len)
133 errx(1, "output buffer not same length: %d", (int)keylen);
135 if (memcmp(res2, in, len) != 0)
136 errx(1, "string not the same after decryption");
138 free(res);
139 free(res2);
142 static int
143 cb_func(int a, int b, BN_GENCB *c)
145 return 1;
148 static RSA *
149 read_key(ENGINE *engine, const char *rsa_key)
151 unsigned char buf[1024 * 4];
152 const unsigned char *p;
153 size_t size;
154 RSA *rsa;
155 FILE *f;
157 f = fopen(rsa_key, "r");
158 if (f == NULL)
159 err(1, "could not open file %s", rsa_key);
161 size = fread(buf, 1, sizeof(buf), f);
162 fclose(f);
163 if (size == 0)
164 err(1, "failed to read file %s", rsa_key);
165 if (size == sizeof(buf))
166 err(1, "key too long in file %s!", rsa_key);
168 p = buf;
169 rsa = d2i_RSAPrivateKey(NULL, &p, size);
170 if (rsa == NULL)
171 err(1, "failed to parse key in file %s", rsa_key);
173 RSA_set_method(rsa, ENGINE_get_RSA(engine));
175 if (!key_blinding)
176 rsa->flags |= RSA_FLAG_NO_BLINDING;
178 return rsa;
185 static void
186 usage (int ret)
188 arg_printusage (args,
189 sizeof(args)/sizeof(*args),
190 NULL,
191 "filename.so");
192 exit (ret);
196 main(int argc, char **argv)
198 ENGINE *engine = NULL;
199 int i, j, idx = 0;
200 RSA *rsa;
202 setprogname(argv[0]);
204 if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &idx))
205 usage(1);
207 if (help_flag)
208 usage(0);
210 if(version_flag){
211 print_version(NULL);
212 exit(0);
215 argc -= idx;
216 argv += idx;
218 OpenSSL_add_all_algorithms();
220 if (argc == 0) {
221 OpenSSL_add_all_algorithms();
222 ENGINE_load_builtin_engines();
223 engine = ENGINE_by_id("builtin");
224 } else {
225 engine = ENGINE_by_dso(argv[0], id_flag);
227 if (engine == NULL)
228 errx(1, "ENGINE_by_dso failed");
230 if (ENGINE_get_RSA(engine) == NULL)
231 return 77;
233 printf("rsa %s\n", ENGINE_get_RSA(engine)->name);
235 if (RAND_status() != 1)
236 errx(77, "no functional random device, refusing to run tests");
238 if (time_keygen) {
239 struct timeval tv1, tv2;
240 const int num = 10;
241 BIGNUM *e;
243 rsa = RSA_new_method(engine);
244 if (!key_blinding)
245 rsa->flags |= RSA_FLAG_NO_BLINDING;
247 e = BN_new();
248 BN_set_word(e, 0x10001);
250 gettimeofday(&tv1, NULL);
252 for (i = 0; i < num; i++) {
253 rsa = RSA_new_method(engine);
254 if (RSA_generate_key_ex(rsa, 1024, e, NULL) != 1)
255 errx(1, "RSA_generate_key_ex");
256 RSA_free(rsa);
259 gettimeofday(&tv2, NULL);
260 timevalsub(&tv2, &tv1);
262 printf("time %lu.%06lu\n",
263 (unsigned long)tv2.tv_sec,
264 (unsigned long)tv2.tv_usec);
266 BN_free(e);
267 ENGINE_finish(engine);
269 return 0;
272 if (time_key) {
273 const int size = 20;
274 const int num = 128;
275 struct timeval tv1, tv2;
276 unsigned char *p;
278 rsa = read_key(engine, time_key);
280 p = emalloc(num * size);
282 RAND_bytes(p, num * size);
284 gettimeofday(&tv1, NULL);
285 for (i = 0; i < num; i++)
286 check_rsa(p + (i * size), size, rsa, RSA_PKCS1_PADDING);
287 gettimeofday(&tv2, NULL);
289 timevalsub(&tv2, &tv1);
291 printf("time %lu.%06lu\n",
292 (unsigned long)tv2.tv_sec,
293 (unsigned long)tv2.tv_usec);
295 RSA_free(rsa);
296 ENGINE_finish(engine);
298 return 0;
301 if (rsa_key) {
302 rsa = read_key(engine, rsa_key);
305 * Assuming that you use the RSA key in the distribution, this
306 * test will generate a signature have a starting zero and thus
307 * will generate a checksum that is 127 byte instead of the
308 * checksum that is 128 byte (like the key).
311 const unsigned char sha1[20] = {
312 0x6d, 0x33, 0xf9, 0x40, 0x75, 0x5b, 0x4e, 0xc5, 0x90, 0x35,
313 0x48, 0xab, 0x75, 0x02, 0x09, 0x76, 0x9a, 0xb4, 0x7d, 0x6b
316 check_rsa(sha1, sizeof(sha1), rsa, RSA_PKCS1_PADDING);
319 for (i = 0; i < 128; i++) {
320 unsigned char sha1[20];
322 RAND_bytes(sha1, sizeof(sha1));
323 check_rsa(sha1, sizeof(sha1), rsa, RSA_PKCS1_PADDING);
325 for (i = 0; i < 128; i++) {
326 unsigned char des3[21];
328 RAND_bytes(des3, sizeof(des3));
329 check_rsa(des3, sizeof(des3), rsa, RSA_PKCS1_PADDING);
331 for (i = 0; i < 128; i++) {
332 unsigned char aes[32];
334 RAND_bytes(aes, sizeof(aes));
335 check_rsa(aes, sizeof(aes), rsa, RSA_PKCS1_PADDING);
338 RSA_free(rsa);
341 for (i = 0; i < loops; i++) {
342 BN_GENCB cb;
343 BIGNUM *e;
344 unsigned int n;
346 rsa = RSA_new_method(engine);
347 if (!key_blinding)
348 rsa->flags |= RSA_FLAG_NO_BLINDING;
350 e = BN_new();
351 BN_set_word(e, 0x10001);
353 BN_GENCB_set(&cb, cb_func, NULL);
355 RAND_bytes(&n, sizeof(n));
356 n &= 0x1ff;
357 n += 1024;
359 if (RSA_generate_key_ex(rsa, n, e, &cb) != 1)
360 errx(1, "RSA_generate_key_ex");
362 BN_free(e);
364 for (j = 0; j < 8; j++) {
365 unsigned char sha1[20];
366 RAND_bytes(sha1, sizeof(sha1));
367 check_rsa(sha1, sizeof(sha1), rsa, RSA_PKCS1_PADDING);
370 RSA_free(rsa);
373 ENGINE_finish(engine);
375 return 0;