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