1 /* $NetBSD: test_rsa.c,v 1.1.1.2 2014/04/24 12:45:30 pettai Exp $ */ 2 3 /* 4 * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * 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 the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <config.h> 37 38 #include <stdio.h> 39 40 #include <krb5/roken.h> 41 #include <krb5/getarg.h> 42 43 #include <engine.h> 44 #include <evp.h> 45 46 /* 47 * 48 */ 49 50 static int version_flag; 51 static int help_flag; 52 static int time_keygen; 53 static char *time_key; 54 static int key_blinding = 1; 55 static char *rsa_key; 56 static char *id_flag; 57 static int loops = 1; 58 59 static struct getargs args[] = { 60 { "loops", 0, arg_integer, &loops, 61 "number of loops", "loops" }, 62 { "id", 0, arg_string, &id_flag, 63 "selects the engine id", "engine-id" }, 64 { "time-keygen", 0, arg_flag, &time_keygen, 65 "time rsa generation", NULL }, 66 { "time-key", 0, arg_string, &time_key, 67 "rsa key file", NULL }, 68 { "key-blinding", 0, arg_negative_flag, &key_blinding, 69 "key blinding", NULL }, 70 { "key", 0, arg_string, &rsa_key, 71 "rsa key file", NULL }, 72 { "version", 0, arg_flag, &version_flag, 73 "print version", NULL }, 74 { "help", 0, arg_flag, &help_flag, 75 NULL, NULL } 76 }; 77 78 /* 79 * 80 */ 81 82 static void 83 check_rsa(const unsigned char *in, size_t len, RSA *rsa, int padding) 84 { 85 unsigned char *res, *res2; 86 unsigned int len2; 87 int keylen; 88 89 res = malloc(RSA_size(rsa)); 90 if (res == NULL) 91 errx(1, "res: ENOMEM"); 92 93 res2 = malloc(RSA_size(rsa)); 94 if (res2 == NULL) 95 errx(1, "res2: ENOMEM"); 96 97 /* signing */ 98 99 keylen = RSA_private_encrypt(len, in, res, rsa, padding); 100 if (keylen <= 0) 101 errx(1, "failed to private encrypt: %d %d", (int)len, (int)keylen); 102 103 if (keylen > RSA_size(rsa)) 104 errx(1, "keylen > RSA_size(rsa)"); 105 106 keylen = RSA_public_decrypt(keylen, res, res2, rsa, padding); 107 if (keylen <= 0) 108 errx(1, "failed to public decrypt: %d", (int)keylen); 109 110 if (keylen != len) 111 errx(1, "output buffer not same length: %d", (int)keylen); 112 113 if (memcmp(res2, in, len) != 0) 114 errx(1, "string not the same after decryption"); 115 116 /* encryption */ 117 118 keylen = RSA_public_encrypt(len, in, res, rsa, padding); 119 if (keylen <= 0) 120 errx(1, "failed to public encrypt: %d", (int)keylen); 121 122 if (keylen > RSA_size(rsa)) 123 errx(1, "keylen > RSA_size(rsa)"); 124 125 keylen = RSA_private_decrypt(keylen, res, res2, rsa, padding); 126 if (keylen <= 0) 127 errx(1, "failed to private decrypt: %d", (int)keylen); 128 129 if (keylen != len) 130 errx(1, "output buffer not same length: %d", (int)keylen); 131 132 if (memcmp(res2, in, len) != 0) 133 errx(1, "string not the same after decryption"); 134 135 len2 = keylen; 136 137 if (RSA_sign(NID_sha1, in, len, res, &len2, rsa) != 1) 138 errx(1, "RSA_sign failed"); 139 140 if (RSA_verify(NID_sha1, in, len, res, len2, rsa) != 1) 141 errx(1, "RSA_verify failed"); 142 143 free(res); 144 free(res2); 145 } 146 147 static int 148 cb_func(int a, int b, BN_GENCB *c) 149 { 150 return 1; 151 } 152 153 static RSA * 154 read_key(ENGINE *engine, const char *rsa_key) 155 { 156 unsigned char buf[1024 * 4]; 157 const unsigned char *p; 158 size_t size; 159 RSA *rsa; 160 FILE *f; 161 162 f = fopen(rsa_key, "rb"); 163 if (f == NULL) 164 err(1, "could not open file %s", rsa_key); 165 rk_cloexec_file(f); 166 167 size = fread(buf, 1, sizeof(buf), f); 168 fclose(f); 169 if (size == 0) 170 err(1, "failed to read file %s", rsa_key); 171 if (size == sizeof(buf)) 172 err(1, "key too long in file %s!", rsa_key); 173 174 p = buf; 175 rsa = d2i_RSAPrivateKey(NULL, &p, size); 176 if (rsa == NULL) 177 err(1, "failed to parse key in file %s", rsa_key); 178 179 RSA_set_method(rsa, ENGINE_get_RSA(engine)); 180 181 if (!key_blinding) 182 rsa->flags |= RSA_FLAG_NO_BLINDING; 183 184 return rsa; 185 } 186 187 /* 188 * 189 */ 190 191 static void 192 usage (int ret) 193 { 194 arg_printusage (args, 195 sizeof(args)/sizeof(*args), 196 NULL, 197 "filename.so"); 198 exit (ret); 199 } 200 201 int 202 main(int argc, char **argv) 203 { 204 ENGINE *engine = NULL; 205 int i, j, idx = 0; 206 RSA *rsa; 207 208 setprogname(argv[0]); 209 210 if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &idx)) 211 usage(1); 212 213 if (help_flag) 214 usage(0); 215 216 if(version_flag){ 217 print_version(NULL); 218 exit(0); 219 } 220 221 argc -= idx; 222 argv += idx; 223 224 OpenSSL_add_all_algorithms(); 225 #ifdef OPENSSL 226 ENGINE_load_openssl(); 227 #endif 228 ENGINE_load_builtin_engines(); 229 230 if (argc == 0) { 231 engine = ENGINE_by_id("builtin"); 232 } else { 233 engine = ENGINE_by_id(argv[0]); 234 if (engine == NULL) 235 engine = ENGINE_by_dso(argv[0], id_flag); 236 } 237 if (engine == NULL) 238 errx(1, "ENGINE_by_dso failed"); 239 240 if (ENGINE_get_RSA(engine) == NULL) 241 return 77; 242 243 printf("rsa %s\n", ENGINE_get_RSA(engine)->name); 244 245 if (RAND_status() != 1) 246 errx(77, "no functional random device, refusing to run tests"); 247 248 if (time_keygen) { 249 struct timeval tv1, tv2; 250 BIGNUM *e; 251 252 rsa = RSA_new_method(engine); 253 if (!key_blinding) 254 rsa->flags |= RSA_FLAG_NO_BLINDING; 255 256 e = BN_new(); 257 BN_set_word(e, 0x10001); 258 259 printf("running keygen with %d loops\n", loops); 260 261 gettimeofday(&tv1, NULL); 262 263 for (i = 0; i < loops; i++) { 264 rsa = RSA_new_method(engine); 265 if (RSA_generate_key_ex(rsa, 1024, e, NULL) != 1) 266 errx(1, "RSA_generate_key_ex"); 267 RSA_free(rsa); 268 } 269 270 gettimeofday(&tv2, NULL); 271 timevalsub(&tv2, &tv1); 272 273 printf("time %lu.%06lu\n", 274 (unsigned long)tv2.tv_sec, 275 (unsigned long)tv2.tv_usec); 276 277 BN_free(e); 278 ENGINE_finish(engine); 279 280 return 0; 281 } 282 283 if (time_key) { 284 const int size = 20; 285 struct timeval tv1, tv2; 286 unsigned char *p; 287 288 if (strcmp(time_key, "generate") == 0) { 289 BIGNUM *e; 290 291 rsa = RSA_new_method(engine); 292 if (!key_blinding) 293 rsa->flags |= RSA_FLAG_NO_BLINDING; 294 295 e = BN_new(); 296 BN_set_word(e, 0x10001); 297 298 if (RSA_generate_key_ex(rsa, 1024, e, NULL) != 1) 299 errx(1, "RSA_generate_key_ex"); 300 } else { 301 rsa = read_key(engine, time_key); 302 } 303 304 p = emalloc(loops * size); 305 306 RAND_bytes(p, loops * size); 307 308 gettimeofday(&tv1, NULL); 309 for (i = 0; i < loops; i++) 310 check_rsa(p + (i * size), size, rsa, RSA_PKCS1_PADDING); 311 gettimeofday(&tv2, NULL); 312 313 timevalsub(&tv2, &tv1); 314 315 printf("time %lu.%06lu\n", 316 (unsigned long)tv2.tv_sec, 317 (unsigned long)tv2.tv_usec); 318 319 RSA_free(rsa); 320 ENGINE_finish(engine); 321 322 return 0; 323 } 324 325 if (rsa_key) { 326 rsa = read_key(engine, rsa_key); 327 328 /* 329 * Assuming that you use the RSA key in the distribution, this 330 * test will generate a signature have a starting zero and thus 331 * will generate a checksum that is 127 byte instead of the 332 * checksum that is 128 byte (like the key). 333 */ 334 { 335 const unsigned char sha1[20] = { 336 0x6d, 0x33, 0xf9, 0x40, 0x75, 0x5b, 0x4e, 0xc5, 0x90, 0x35, 337 0x48, 0xab, 0x75, 0x02, 0x09, 0x76, 0x9a, 0xb4, 0x7d, 0x6b 338 }; 339 340 check_rsa(sha1, sizeof(sha1), rsa, RSA_PKCS1_PADDING); 341 } 342 343 for (i = 0; i < 128; i++) { 344 unsigned char sha1[20]; 345 346 RAND_bytes(sha1, sizeof(sha1)); 347 check_rsa(sha1, sizeof(sha1), rsa, RSA_PKCS1_PADDING); 348 } 349 for (i = 0; i < 128; i++) { 350 unsigned char des3[21]; 351 352 RAND_bytes(des3, sizeof(des3)); 353 check_rsa(des3, sizeof(des3), rsa, RSA_PKCS1_PADDING); 354 } 355 for (i = 0; i < 128; i++) { 356 unsigned char aes[32]; 357 358 RAND_bytes(aes, sizeof(aes)); 359 check_rsa(aes, sizeof(aes), rsa, RSA_PKCS1_PADDING); 360 } 361 362 RSA_free(rsa); 363 } 364 365 for (i = 0; i < loops; i++) { 366 BN_GENCB cb; 367 BIGNUM *e; 368 unsigned int n; 369 370 rsa = RSA_new_method(engine); 371 if (!key_blinding) 372 rsa->flags |= RSA_FLAG_NO_BLINDING; 373 374 e = BN_new(); 375 BN_set_word(e, 0x10001); 376 377 BN_GENCB_set(&cb, cb_func, NULL); 378 379 RAND_bytes(&n, sizeof(n)); 380 n &= 0x1ff; 381 n += 1024; 382 383 if (RSA_generate_key_ex(rsa, n, e, &cb) != 1) 384 errx(1, "RSA_generate_key_ex"); 385 386 BN_free(e); 387 388 for (j = 0; j < 8; j++) { 389 unsigned char sha1[20]; 390 RAND_bytes(sha1, sizeof(sha1)); 391 check_rsa(sha1, sizeof(sha1), rsa, RSA_PKCS1_PADDING); 392 } 393 394 RSA_free(rsa); 395 } 396 397 ENGINE_finish(engine); 398 399 return 0; 400 } 401