roken: getuserinfo WIN32 fix username string termination
[heimdal.git] / lib / hcrypto / test_rsa.c
blob54b7a66c5ba1397e5cad30a109cb49069a148c1b
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 #include <config.h>
35 #include <roken.h>
36 #include <getarg.h>
38 #include <engine.h>
39 #include <evp.h>
45 static int version_flag;
46 static int help_flag;
47 static int time_keygen;
48 static char *time_key;
49 static int key_blinding = 1;
50 static char *rsa_key;
51 static char *id_flag;
52 static int loops = 1;
54 static struct getargs args[] = {
55 { "loops", 0, arg_integer, &loops,
56 "number of loops", "loops" },
57 { "id", 0, arg_string, &id_flag,
58 "selects the engine id", "engine-id" },
59 { "time-keygen", 0, arg_flag, &time_keygen,
60 "time rsa generation", NULL },
61 { "time-key", 0, arg_string, &time_key,
62 "rsa key file", NULL },
63 { "key-blinding", 0, arg_negative_flag, &key_blinding,
64 "key blinding", NULL },
65 { "key", 0, arg_string, &rsa_key,
66 "rsa key file", NULL },
67 { "version", 0, arg_flag, &version_flag,
68 "print version", NULL },
69 { "help", 0, arg_flag, &help_flag,
70 NULL, NULL }
77 static void
78 check_rsa(const unsigned char *in, size_t len, RSA *rsa, int padding)
80 unsigned char *res, *res2;
81 unsigned int len2;
82 int keylen;
84 res = malloc(RSA_size(rsa));
85 if (res == NULL)
86 errx(1, "res: ENOMEM");
88 res2 = malloc(RSA_size(rsa));
89 if (res2 == NULL)
90 errx(1, "res2: ENOMEM");
92 /* signing */
94 keylen = RSA_private_encrypt(len, in, res, rsa, padding);
95 if (keylen <= 0)
96 errx(1, "failed to private encrypt: %d %d", (int)len, (int)keylen);
98 if (keylen > RSA_size(rsa))
99 errx(1, "keylen > RSA_size(rsa)");
101 keylen = RSA_public_decrypt(keylen, res, res2, rsa, padding);
102 if (keylen <= 0)
103 errx(1, "failed to public decrypt: %d", (int)keylen);
105 if (keylen != len)
106 errx(1, "output buffer not same length: %d", (int)keylen);
108 if (memcmp(res2, in, len) != 0)
109 errx(1, "string not the same after decryption");
111 /* encryption */
113 keylen = RSA_public_encrypt(len, in, res, rsa, padding);
114 if (keylen <= 0)
115 errx(1, "failed to public encrypt: %d", (int)keylen);
117 if (keylen > RSA_size(rsa))
118 errx(1, "keylen > RSA_size(rsa)");
120 keylen = RSA_private_decrypt(keylen, res, res2, rsa, padding);
121 if (keylen <= 0)
122 errx(1, "failed to private decrypt: %d", (int)keylen);
124 if (keylen != len)
125 errx(1, "output buffer not same length: %d", (int)keylen);
127 if (memcmp(res2, in, len) != 0)
128 errx(1, "string not the same after decryption");
130 len2 = keylen;
132 if (RSA_sign(NID_sha1, in, len, res, &len2, rsa) != 1)
133 errx(1, "RSA_sign failed");
135 if (RSA_verify(NID_sha1, in, len, res, len2, rsa) != 1)
136 errx(1, "RSA_verify failed");
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 *keyfile)
151 unsigned char buf[1024 * 4];
152 const unsigned char *p;
153 size_t size;
154 RSA *rsa;
155 FILE *f;
157 f = fopen(keyfile, "rb");
158 if (f == NULL)
159 err(1, "could not open file %s", keyfile);
160 rk_cloexec_file(f);
162 size = fread(buf, 1, sizeof(buf), f);
163 fclose(f);
164 if (size == 0)
165 err(1, "failed to read file %s", keyfile);
166 if (size == sizeof(buf))
167 err(1, "key too long in file %s!", keyfile);
169 p = buf;
170 rsa = d2i_RSAPrivateKey(NULL, &p, size);
171 if (rsa == NULL)
172 err(1, "failed to parse key in file %s", keyfile);
174 RSA_set_method(rsa, ENGINE_get_RSA(engine));
176 if (!key_blinding)
177 rsa->flags |= RSA_FLAG_NO_BLINDING;
179 return rsa;
186 static void
187 usage (int ret)
189 arg_printusage (args,
190 sizeof(args)/sizeof(*args),
191 NULL,
192 "filename.so");
193 exit (ret);
197 main(int argc, char **argv)
199 ENGINE *engine = NULL;
200 int i, j, idx = 0;
201 RSA *rsa;
203 setprogname(argv[0]);
205 if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &idx))
206 usage(1);
208 if (help_flag)
209 usage(0);
211 if(version_flag){
212 print_version(NULL);
213 exit(0);
216 argc -= idx;
217 argv += idx;
219 OpenSSL_add_all_algorithms();
220 #ifdef OPENSSL
221 ENGINE_load_openssl();
222 #endif
223 ENGINE_load_builtin_engines();
225 if (argc == 0) {
226 engine = ENGINE_by_id("builtin");
227 } else {
228 engine = ENGINE_by_id(argv[0]);
229 if (engine == NULL)
230 engine = ENGINE_by_dso(argv[0], id_flag);
232 if (engine == NULL)
233 errx(1, "ENGINE_by_dso failed");
235 if (ENGINE_get_RSA(engine) == NULL)
236 return 77;
238 printf("rsa %s\n", ENGINE_get_RSA(engine)->name);
240 if (RAND_status() != 1)
241 errx(77, "no functional random device, refusing to run tests");
243 if (time_keygen) {
244 struct timeval tv1, tv2;
245 BIGNUM *e;
247 rsa = RSA_new_method(engine);
248 if (!key_blinding)
249 rsa->flags |= RSA_FLAG_NO_BLINDING;
251 e = BN_new();
252 BN_set_word(e, 0x10001);
254 printf("running keygen with %d loops\n", loops);
256 gettimeofday(&tv1, NULL);
258 for (i = 0; i < loops; i++) {
259 rsa = RSA_new_method(engine);
260 if (RSA_generate_key_ex(rsa, 1024, e, NULL) != 1)
261 errx(1, "RSA_generate_key_ex");
262 RSA_free(rsa);
265 gettimeofday(&tv2, NULL);
266 timevalsub(&tv2, &tv1);
268 printf("time %lu.%06lu\n",
269 (unsigned long)tv2.tv_sec,
270 (unsigned long)tv2.tv_usec);
272 BN_free(e);
273 ENGINE_finish(engine);
275 return 0;
278 if (time_key) {
279 const int size = 20;
280 struct timeval tv1, tv2;
281 unsigned char *p;
283 if (strcmp(time_key, "generate") == 0) {
284 BIGNUM *e;
286 rsa = RSA_new_method(engine);
287 if (!key_blinding)
288 rsa->flags |= RSA_FLAG_NO_BLINDING;
290 e = BN_new();
291 BN_set_word(e, 0x10001);
293 if (RSA_generate_key_ex(rsa, 1024, e, NULL) != 1)
294 errx(1, "RSA_generate_key_ex");
295 } else {
296 rsa = read_key(engine, time_key);
299 p = emalloc(loops * size);
301 RAND_bytes(p, loops * size);
303 gettimeofday(&tv1, NULL);
304 for (i = 0; i < loops; i++)
305 check_rsa(p + (i * size), size, rsa, RSA_PKCS1_PADDING);
306 gettimeofday(&tv2, NULL);
308 timevalsub(&tv2, &tv1);
310 printf("time %lu.%06lu\n",
311 (unsigned long)tv2.tv_sec,
312 (unsigned long)tv2.tv_usec);
314 RSA_free(rsa);
315 ENGINE_finish(engine);
317 return 0;
320 if (rsa_key) {
321 rsa = read_key(engine, rsa_key);
324 * Assuming that you use the RSA key in the distribution, this
325 * test will generate a signature have a starting zero and thus
326 * will generate a checksum that is 127 byte instead of the
327 * checksum that is 128 byte (like the key).
330 const unsigned char sha1[20] = {
331 0x6d, 0x33, 0xf9, 0x40, 0x75, 0x5b, 0x4e, 0xc5, 0x90, 0x35,
332 0x48, 0xab, 0x75, 0x02, 0x09, 0x76, 0x9a, 0xb4, 0x7d, 0x6b
335 check_rsa(sha1, sizeof(sha1), rsa, RSA_PKCS1_PADDING);
338 for (i = 0; i < 128; i++) {
339 unsigned char sha1[20];
341 RAND_bytes(sha1, sizeof(sha1));
342 check_rsa(sha1, sizeof(sha1), rsa, RSA_PKCS1_PADDING);
344 for (i = 0; i < 128; i++) {
345 unsigned char des3[21];
347 RAND_bytes(des3, sizeof(des3));
348 check_rsa(des3, sizeof(des3), rsa, RSA_PKCS1_PADDING);
350 for (i = 0; i < 128; i++) {
351 unsigned char aes[32];
353 RAND_bytes(aes, sizeof(aes));
354 check_rsa(aes, sizeof(aes), rsa, RSA_PKCS1_PADDING);
357 RSA_free(rsa);
360 for (i = 0; i < loops; i++) {
361 BN_GENCB cb;
362 BIGNUM *e;
363 unsigned int n;
365 rsa = RSA_new_method(engine);
366 if (!key_blinding)
367 rsa->flags |= RSA_FLAG_NO_BLINDING;
369 e = BN_new();
370 BN_set_word(e, 0x10001);
372 BN_GENCB_set(&cb, cb_func, NULL);
374 RAND_bytes(&n, sizeof(n));
375 n &= 0x1ff;
376 n += 1024;
378 if (RSA_generate_key_ex(rsa, n, e, &cb) != 1)
379 errx(1, "RSA_generate_key_ex");
381 BN_free(e);
383 for (j = 0; j < 8; j++) {
384 unsigned char sha1[20];
385 RAND_bytes(sha1, sizeof(sha1));
386 check_rsa(sha1, sizeof(sha1), rsa, RSA_PKCS1_PADDING);
389 RSA_free(rsa);
392 ENGINE_finish(engine);
394 return 0;