File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / crypto / crypto_tester.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 09:46:44 2020 UTC (4 years, 2 months ago) by misho
Branches: strongswan, MAIN
CVS tags: v5_9_2p0, v5_8_4p7, HEAD
Strongswan

    1: /*
    2:  * Copyright (C) 2009-2010 Martin Willi
    3:  * Copyright (C) 2016-2019 Andreas Steffen
    4:  * HSR Hochschule fuer Technik Rapperswil
    5:  * Copyright (C) 2010 revosec AG
    6:  *
    7:  * This program is free software; you can redistribute it and/or modify it
    8:  * under the terms of the GNU General Public License as published by the
    9:  * Free Software Foundation; either version 2 of the License, or (at your
   10:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
   11:  *
   12:  * This program is distributed in the hope that it will be useful, but
   13:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   14:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   15:  * for more details.
   16:  */
   17: 
   18: #ifdef HAVE_DLADDR
   19: # define _GNU_SOURCE
   20: # include <dlfcn.h>
   21: #endif
   22: #include <time.h>
   23: 
   24: #include "crypto_tester.h"
   25: 
   26: #include <utils/debug.h>
   27: #include <collections/linked_list.h>
   28: #include <crypto/rngs/rng_tester.h>
   29: 
   30: typedef struct private_crypto_tester_t private_crypto_tester_t;
   31: 
   32: /**
   33:  * Private data of an crypto_tester_t object.
   34:  */
   35: struct private_crypto_tester_t {
   36: 
   37: 	/**
   38: 	 * Public crypto_tester_t interface.
   39: 	 */
   40: 	crypto_tester_t public;
   41: 
   42: 	/**
   43: 	 * List of crypter test vectors
   44: 	 */
   45: 	linked_list_t *crypter;
   46: 
   47: 	/**
   48: 	 * List of aead test vectors
   49: 	 */
   50: 	linked_list_t *aead;
   51: 
   52: 	/**
   53: 	 * List of signer test vectors
   54: 	 */
   55: 	linked_list_t *signer;
   56: 
   57: 	/**
   58: 	 * List of hasher test vectors
   59: 	 */
   60: 	linked_list_t *hasher;
   61: 
   62: 	/**
   63: 	 * List of PRF test vectors
   64: 	 */
   65: 	linked_list_t *prf;
   66: 
   67: 	/**
   68: 	 * List of XOF test vectors
   69: 	 */
   70: 	linked_list_t *xof;
   71: 
   72: 	/**
   73: 	 * List of DRBG test vectors
   74: 	 */
   75: 	linked_list_t *drbg;
   76: 
   77: 	/**
   78: 	 * List of RNG test vectors
   79: 	 */
   80: 	linked_list_t *rng;
   81: 
   82: 	/**
   83: 	 * List of Diffie-Hellman test vectors
   84: 	 */
   85: 	linked_list_t *dh;
   86: 
   87: 	/**
   88: 	 * Is a test vector required to pass a test?
   89: 	 */
   90: 	bool required;
   91: 
   92: 	/**
   93: 	 * should we run RNG_TRUE tests? Enough entropy?
   94: 	 */
   95: 	bool rng_true;
   96: 
   97: 	/**
   98: 	 * time we test each algorithm
   99: 	 */
  100: 	int bench_time;
  101: 
  102: 	/**
  103: 	 * size of buffer we use for benchmarking
  104: 	 */
  105: 	int bench_size;
  106: };
  107: 
  108: /**
  109:  * Get the name of a test vector, if available
  110:  */
  111: static const char* get_name(void *sym)
  112: {
  113: #ifdef HAVE_DLADDR
  114: 	Dl_info dli;
  115: 
  116: 	if (dladdr(sym, &dli))
  117: 	{
  118: 		return dli.dli_sname;
  119: 	}
  120: #endif
  121: 	return "unknown";
  122: }
  123: 
  124: #if defined(CLOCK_THREAD_CPUTIME_ID) && defined(HAVE_CLOCK_GETTIME)
  125: 
  126: /**
  127:  * Start a benchmark timer
  128:  */
  129: static void start_timing(struct timespec *start)
  130: {
  131: 	clock_gettime(CLOCK_THREAD_CPUTIME_ID, start);
  132: }
  133: 
  134: /**
  135:  * End a benchmark timer, return ms
  136:  */
  137: static u_int end_timing(struct timespec *start)
  138: {
  139: 	struct timespec end;
  140: 
  141: 	clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end);
  142: 	return (end.tv_nsec - start->tv_nsec) / 1000000 +
  143: 			(end.tv_sec - start->tv_sec) * 1000;
  144: }
  145: 
  146: #else /* CLOCK_THREAD_CPUTIME_ID */
  147: 
  148: /* Make benchmarking a no-op if CLOCK_THREAD_CPUTIME_ID is not available */
  149: #define start_timing(start) ((start)->tv_sec = 0, (start)->tv_nsec = 0)
  150: #define end_timing(...) (this->bench_time)
  151: 
  152: #endif /* CLOCK_THREAD_CPUTIME_ID */
  153: 
  154: /**
  155:  * Benchmark a crypter
  156:  */
  157: static u_int bench_crypter(private_crypto_tester_t *this,
  158: 	encryption_algorithm_t alg, crypter_constructor_t create, size_t key_size)
  159: {
  160: 	crypter_t *crypter;
  161: 
  162: 	crypter = create(alg, key_size);
  163: 	if (crypter)
  164: 	{
  165: 		char iv[crypter->get_iv_size(crypter)];
  166: 		char key[crypter->get_key_size(crypter)];
  167: 		chunk_t buf;
  168: 		struct timespec start;
  169: 		u_int runs;
  170: 
  171: 		memset(iv, 0x56, sizeof(iv));
  172: 		memset(key, 0x12, sizeof(key));
  173: 		if (!crypter->set_key(crypter, chunk_from_thing(key)))
  174: 		{
  175: 			return 0;
  176: 		}
  177: 
  178: 		buf = chunk_alloc(this->bench_size);
  179: 		memset(buf.ptr, 0x34, buf.len);
  180: 
  181: 		runs = 0;
  182: 		start_timing(&start);
  183: 		while (end_timing(&start) < this->bench_time)
  184: 		{
  185: 			if (crypter->encrypt(crypter, buf, chunk_from_thing(iv), NULL))
  186: 			{
  187: 				runs++;
  188: 			}
  189: 			if (crypter->decrypt(crypter, buf, chunk_from_thing(iv), NULL))
  190: 			{
  191: 				runs++;
  192: 			}
  193: 		}
  194: 		free(buf.ptr);
  195: 		crypter->destroy(crypter);
  196: 
  197: 		return runs;
  198: 	}
  199: 	return 0;
  200: }
  201: 
  202: METHOD(crypto_tester_t, test_crypter, bool,
  203: 	private_crypto_tester_t *this, encryption_algorithm_t alg, size_t key_size,
  204: 	crypter_constructor_t create, u_int *speed, const char *plugin_name)
  205: {
  206: 	enumerator_t *enumerator;
  207: 	crypter_test_vector_t *vector;
  208: 	bool failed = FALSE;
  209: 	u_int tested = 0;
  210: 
  211: 	enumerator = this->crypter->create_enumerator(this->crypter);
  212: 	while (enumerator->enumerate(enumerator, &vector))
  213: 	{
  214: 		crypter_t *crypter;
  215: 		chunk_t key, iv, plain = chunk_empty, cipher = chunk_empty;
  216: 
  217: 		if (vector->alg != alg)
  218: 		{
  219: 			continue;
  220: 		}
  221: 		if (key_size && key_size != vector->key_size)
  222: 		{	/* test only vectors with a specific key size, if key size given */
  223: 			continue;
  224: 		}
  225: 
  226: 		crypter = create(alg, vector->key_size);
  227: 		if (!crypter)
  228: 		{	/* key size not supported */
  229: 			continue;
  230: 		}
  231: 		tested++;
  232: 		failed = TRUE;
  233: 
  234: 		key = chunk_create(vector->key, crypter->get_key_size(crypter));
  235: 		if (!crypter->set_key(crypter, key))
  236: 		{
  237: 			goto failure;
  238: 		}
  239: 		iv = chunk_create(vector->iv, crypter->get_iv_size(crypter));
  240: 
  241: 		/* allocated encryption */
  242: 		plain = chunk_create(vector->plain, vector->len);
  243: 		if (!crypter->encrypt(crypter, plain, iv, &cipher))
  244: 		{
  245: 			goto failure;
  246: 		}
  247: 		if (!memeq(vector->cipher, cipher.ptr, cipher.len))
  248: 		{
  249: 			goto failure;
  250: 		}
  251: 		/* inline decryption */
  252: 		if (!crypter->decrypt(crypter, cipher, iv, NULL))
  253: 		{
  254: 			goto failure;
  255: 		}
  256: 		if (!memeq(vector->plain, cipher.ptr, cipher.len))
  257: 		{
  258: 			goto failure;
  259: 		}
  260: 		/* allocated decryption */
  261: 		if (!crypter->decrypt(crypter,
  262: 						chunk_create(vector->cipher, vector->len), iv, &plain))
  263: 		{
  264: 			goto failure;
  265: 		}
  266: 		if (!memeq(vector->plain, plain.ptr, plain.len))
  267: 		{
  268: 			goto failure;
  269: 		}
  270: 		/* inline encryption */
  271: 		if (!crypter->encrypt(crypter, plain, iv, NULL))
  272: 		{
  273: 			goto failure;
  274: 		}
  275: 		if (!memeq(vector->cipher, plain.ptr, plain.len))
  276: 		{
  277: 			goto failure;
  278: 		}
  279: 
  280: 		failed = FALSE;
  281: failure:
  282: 		crypter->destroy(crypter);
  283: 		chunk_free(&cipher);
  284: 		if (plain.ptr != vector->plain)
  285: 		{
  286: 			chunk_free(&plain);
  287: 		}
  288: 		if (failed)
  289: 		{
  290: 			DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
  291: 				 encryption_algorithm_names, alg, plugin_name, get_name(vector));
  292: 			break;
  293: 		}
  294: 	}
  295: 	enumerator->destroy(enumerator);
  296: 	if (!tested)
  297: 	{
  298: 		if (failed)
  299: 		{
  300: 			DBG1(DBG_LIB,"disable %N[%s]: %zd byte key size not supported",
  301: 				 encryption_algorithm_names, alg, plugin_name, key_size);
  302: 			return FALSE;
  303: 		}
  304: 		else
  305: 		{
  306: 			DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
  307: 				 this->required ? "disabled" : "enabled ",
  308: 				 encryption_algorithm_names, alg, plugin_name);
  309: 			return !this->required;
  310: 		}
  311: 	}
  312: 	if (!failed)
  313: 	{
  314: 		if (speed)
  315: 		{
  316: 			*speed = bench_crypter(this, alg, create, key_size);
  317: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points "
  318: 				 "(%zd bit key)", encryption_algorithm_names, alg,
  319: 				 plugin_name, tested, *speed, key_size * 8);
  320: 		}
  321: 		else
  322: 		{
  323: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
  324: 				 encryption_algorithm_names, alg, plugin_name, tested);
  325: 		}
  326: 	}
  327: 	return !failed;
  328: }
  329: 
  330: /**
  331:  * Benchmark an aead transform
  332:  */
  333: static u_int bench_aead(private_crypto_tester_t *this,
  334: 	encryption_algorithm_t alg, aead_constructor_t create, size_t key_size)
  335: {
  336: 	aead_t *aead;
  337: 
  338: 	aead = create(alg, key_size, 0);
  339: 	if (aead)
  340: 	{
  341: 		char iv[aead->get_iv_size(aead)];
  342: 		char key[aead->get_key_size(aead)];
  343: 		char assoc[4];
  344: 		chunk_t buf;
  345: 		struct timespec start;
  346: 		u_int runs;
  347: 		size_t icv;
  348: 
  349: 		memset(iv, 0x56, sizeof(iv));
  350: 		memset(key, 0x12, sizeof(key));
  351: 		memset(assoc, 0x78, sizeof(assoc));
  352: 		if (!aead->set_key(aead, chunk_from_thing(key)))
  353: 		{
  354: 			return 0;
  355: 		}
  356: 		icv = aead->get_icv_size(aead);
  357: 
  358: 		buf = chunk_alloc(this->bench_size + icv);
  359: 		memset(buf.ptr, 0x34, buf.len);
  360: 		buf.len -= icv;
  361: 
  362: 		runs = 0;
  363: 		start_timing(&start);
  364: 		while (end_timing(&start) < this->bench_time)
  365: 		{
  366: 			if (aead->encrypt(aead, buf, chunk_from_thing(assoc),
  367: 						chunk_from_thing(iv), NULL))
  368: 			{
  369: 				runs += 2;
  370: 			}
  371: 			if (aead->decrypt(aead, chunk_create(buf.ptr, buf.len + icv),
  372: 						chunk_from_thing(assoc), chunk_from_thing(iv), NULL))
  373: 			{
  374: 				runs += 2;
  375: 			}
  376: 		}
  377: 		free(buf.ptr);
  378: 		aead->destroy(aead);
  379: 
  380: 		return runs;
  381: 	}
  382: 	return 0;
  383: }
  384: 
  385: METHOD(crypto_tester_t, test_aead, bool,
  386: 	private_crypto_tester_t *this, encryption_algorithm_t alg, size_t key_size,
  387: 	size_t salt_size, aead_constructor_t create,
  388: 	u_int *speed, const char *plugin_name)
  389: {
  390: 	enumerator_t *enumerator;
  391: 	aead_test_vector_t *vector;
  392: 	bool failed = FALSE;
  393: 	u_int tested = 0;
  394: 
  395: 	enumerator = this->aead->create_enumerator(this->aead);
  396: 	while (enumerator->enumerate(enumerator, &vector))
  397: 	{
  398: 		aead_t *aead;
  399: 		chunk_t key, iv, assoc, plain = chunk_empty, cipher = chunk_empty;
  400: 		size_t icv;
  401: 
  402: 		if (vector->alg != alg)
  403: 		{
  404: 			continue;
  405: 		}
  406: 		if (key_size && key_size != vector->key_size)
  407: 		{	/* test only vectors with a specific key size, if key size given */
  408: 			continue;
  409: 		}
  410: 		if (salt_size && salt_size != vector->salt_size)
  411: 		{
  412: 			continue;
  413: 		}
  414: 
  415: 		tested++;
  416: 		failed = TRUE;
  417: 		aead = create(alg, vector->key_size, vector->salt_size);
  418: 		if (!aead)
  419: 		{
  420: 			DBG1(DBG_LIB, "%N[%s]: %u bit key size not supported",
  421: 				 encryption_algorithm_names, alg, plugin_name,
  422: 				 BITS_PER_BYTE * vector->key_size);
  423: 			continue;
  424: 		}
  425: 
  426: 		key = chunk_create(vector->key, aead->get_key_size(aead));
  427: 		if (!aead->set_key(aead, key))
  428: 		{
  429: 			goto failure;
  430: 		}
  431: 		iv = chunk_create(vector->iv, aead->get_iv_size(aead));
  432: 		assoc = chunk_create(vector->adata, vector->alen);
  433: 		icv = aead->get_icv_size(aead);
  434: 
  435: 		/* allocated encryption */
  436: 		plain = chunk_create(vector->plain, vector->len);
  437: 		if (!aead->encrypt(aead, plain, assoc, iv, &cipher))
  438: 		{
  439: 			goto failure;
  440: 		}
  441: 		if (!memeq(vector->cipher, cipher.ptr, cipher.len))
  442: 		{
  443: 			goto failure;
  444: 		}
  445: 		/* inline decryption */
  446: 		if (!aead->decrypt(aead, cipher, assoc, iv, NULL))
  447: 		{
  448: 			goto failure;
  449: 		}
  450: 		if (!memeq(vector->plain, cipher.ptr, cipher.len - icv))
  451: 		{
  452: 			goto failure;
  453: 		}
  454: 		/* allocated decryption */
  455: 		if (!aead->decrypt(aead, chunk_create(vector->cipher, vector->len + icv),
  456: 						   assoc, iv, &plain))
  457: 		{
  458: 			goto failure;
  459: 		}
  460: 		if (!memeq(vector->plain, plain.ptr, plain.len))
  461: 		{
  462: 			goto failure;
  463: 		}
  464: 		plain.ptr = realloc(plain.ptr, plain.len + icv);
  465: 		/* inline encryption */
  466: 		if (!aead->encrypt(aead, plain, assoc, iv, NULL))
  467: 		{
  468: 			goto failure;
  469: 		}
  470: 		if (!memeq(vector->cipher, plain.ptr, plain.len + icv))
  471: 		{
  472: 			goto failure;
  473: 		}
  474: 
  475: 		failed = FALSE;
  476: failure:
  477: 		aead->destroy(aead);
  478: 		chunk_free(&cipher);
  479: 		if (plain.ptr != vector->plain)
  480: 		{
  481: 			chunk_free(&plain);
  482: 		}
  483: 		if (failed)
  484: 		{
  485: 			DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
  486: 				 encryption_algorithm_names, alg, plugin_name, get_name(vector));
  487: 			break;
  488: 		}
  489: 	}
  490: 	enumerator->destroy(enumerator);
  491: 	if (!tested)
  492: 	{
  493: 		if (failed)
  494: 		{
  495: 			DBG1(DBG_LIB,"disable %N[%s]: %zd byte key size not supported",
  496: 				 encryption_algorithm_names, alg, plugin_name, key_size);
  497: 			return FALSE;
  498: 		}
  499: 		else
  500: 		{
  501: 			DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
  502: 				 this->required ? "disabled" : "enabled ",
  503: 				 encryption_algorithm_names, alg, plugin_name);
  504: 			return !this->required;
  505: 		}
  506: 	}
  507: 	if (!failed)
  508: 	{
  509: 		if (speed)
  510: 		{
  511: 			*speed = bench_aead(this, alg, create, key_size);
  512: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points "
  513: 				 "(%zd bit key)", encryption_algorithm_names, alg,
  514: 				 plugin_name, tested, *speed, key_size * 8);
  515: 		}
  516: 		else
  517: 		{
  518: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
  519: 				 encryption_algorithm_names, alg, plugin_name, tested);
  520: 		}
  521: 	}
  522: 	return !failed;
  523: }
  524: 
  525: /**
  526:  * Benchmark a signer
  527:  */
  528: static u_int bench_signer(private_crypto_tester_t *this,
  529: 	integrity_algorithm_t alg, signer_constructor_t create)
  530: {
  531: 	signer_t *signer;
  532: 
  533: 	signer = create(alg);
  534: 	if (signer)
  535: 	{
  536: 		char key[signer->get_key_size(signer)];
  537: 		char mac[signer->get_block_size(signer)];
  538: 		chunk_t buf;
  539: 		struct timespec start;
  540: 		u_int runs;
  541: 
  542: 		memset(key, 0x12, sizeof(key));
  543: 		if (!signer->set_key(signer, chunk_from_thing(key)))
  544: 		{
  545: 			return 0;
  546: 		}
  547: 
  548: 		buf = chunk_alloc(this->bench_size);
  549: 		memset(buf.ptr, 0x34, buf.len);
  550: 
  551: 		runs = 0;
  552: 		start_timing(&start);
  553: 		while (end_timing(&start) < this->bench_time)
  554: 		{
  555: 			if (signer->get_signature(signer, buf, mac))
  556: 			{
  557: 				runs++;
  558: 			}
  559: 			if (signer->verify_signature(signer, buf, chunk_from_thing(mac)))
  560: 			{
  561: 				runs++;
  562: 			}
  563: 		}
  564: 		free(buf.ptr);
  565: 		signer->destroy(signer);
  566: 
  567: 		return runs;
  568: 	}
  569: 	return 0;
  570: }
  571: 
  572: METHOD(crypto_tester_t, test_signer, bool,
  573: 	private_crypto_tester_t *this, integrity_algorithm_t alg,
  574: 	signer_constructor_t create, u_int *speed, const char *plugin_name)
  575: {
  576: 	enumerator_t *enumerator;
  577: 	signer_test_vector_t *vector;
  578: 	bool failed = FALSE;
  579: 	u_int tested = 0;
  580: 
  581: 	enumerator = this->signer->create_enumerator(this->signer);
  582: 	while (enumerator->enumerate(enumerator, &vector))
  583: 	{
  584: 		signer_t *signer;
  585: 		chunk_t key, data, mac = chunk_empty;
  586: 
  587: 		if (vector->alg != alg)
  588: 		{
  589: 			continue;
  590: 		}
  591: 
  592: 		tested++;
  593: 		failed = TRUE;
  594: 		signer = create(alg);
  595: 		if (!signer)
  596: 		{
  597: 			DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
  598: 				 integrity_algorithm_names, alg, plugin_name);
  599: 			break;
  600: 		}
  601: 
  602: 		data = chunk_create(vector->data, vector->len);
  603: 		key = chunk_create(vector->key, signer->get_key_size(signer));
  604: 		if (!signer->set_key(signer, key))
  605: 		{
  606: 			goto failure;
  607: 		}
  608: 		/* do partial append mode and check if key gets set correctly */
  609: 		if (!signer->get_signature(signer, data, NULL))
  610: 		{
  611: 			goto failure;
  612: 		}
  613: 		if (!signer->set_key(signer, key))
  614: 		{
  615: 			goto failure;
  616: 		}
  617: 		/* allocated signature */
  618: 		if (!signer->allocate_signature(signer, data, &mac))
  619: 		{
  620: 			goto failure;
  621: 		}
  622: 		if (mac.len != signer->get_block_size(signer))
  623: 		{
  624: 			goto failure;
  625: 		}
  626: 		if (!memeq(vector->mac, mac.ptr, mac.len))
  627: 		{
  628: 			goto failure;
  629: 		}
  630: 		/* signature to existing buffer */
  631: 		memset(mac.ptr, 0, mac.len);
  632: 		if (!signer->get_signature(signer, data, mac.ptr))
  633: 		{
  634: 			goto failure;
  635: 		}
  636: 		if (!memeq(vector->mac, mac.ptr, mac.len))
  637: 		{
  638: 			goto failure;
  639: 		}
  640: 		/* signature verification, good case */
  641: 		if (!signer->verify_signature(signer, data, mac))
  642: 		{
  643: 			goto failure;
  644: 		}
  645: 		/* signature verification, bad case */
  646: 		*(mac.ptr + mac.len - 1) += 1;
  647: 		if (signer->verify_signature(signer, data, mac))
  648: 		{
  649: 			goto failure;
  650: 		}
  651: 		/* signature to existing buffer, using append mode */
  652: 		if (data.len > 2)
  653: 		{
  654: 			if (!signer->allocate_signature(signer,
  655: 											chunk_create(data.ptr, 1), NULL))
  656: 			{
  657: 				goto failure;
  658: 			}
  659: 			if (!signer->get_signature(signer,
  660: 									   chunk_create(data.ptr + 1, 1), NULL))
  661: 			{
  662: 				goto failure;
  663: 			}
  664: 			if (!signer->verify_signature(signer, chunk_skip(data, 2),
  665: 										  chunk_create(vector->mac, mac.len)))
  666: 			{
  667: 				goto failure;
  668: 			}
  669: 		}
  670: 
  671: 		failed = FALSE;
  672: failure:
  673: 		signer->destroy(signer);
  674: 		chunk_free(&mac);
  675: 		if (failed)
  676: 		{
  677: 			DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
  678: 				 integrity_algorithm_names, alg, plugin_name, get_name(vector));
  679: 			break;
  680: 		}
  681: 	}
  682: 	enumerator->destroy(enumerator);
  683: 	if (!tested)
  684: 	{
  685: 		DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
  686: 			 this->required ? "disabled" : "enabled ",
  687: 			 integrity_algorithm_names, alg, plugin_name);
  688: 		return !this->required;
  689: 	}
  690: 	if (!failed)
  691: 	{
  692: 		if (speed)
  693: 		{
  694: 			*speed = bench_signer(this, alg, create);
  695: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
  696: 				 integrity_algorithm_names, alg, plugin_name, tested, *speed);
  697: 		}
  698: 		else
  699: 		{
  700: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
  701: 				 integrity_algorithm_names, alg, plugin_name, tested);
  702: 		}
  703: 	}
  704: 	return !failed;
  705: }
  706: 
  707: /**
  708:  * Benchmark a hasher
  709:  */
  710: static u_int bench_hasher(private_crypto_tester_t *this,
  711: 	hash_algorithm_t alg, hasher_constructor_t create)
  712: {
  713: 	hasher_t *hasher;
  714: 
  715: 	hasher = create(alg);
  716: 	if (hasher)
  717: 	{
  718: 		char hash[hasher->get_hash_size(hasher)];
  719: 		chunk_t buf;
  720: 		struct timespec start;
  721: 		u_int runs;
  722: 
  723: 		buf = chunk_alloc(this->bench_size);
  724: 		memset(buf.ptr, 0x34, buf.len);
  725: 
  726: 		runs = 0;
  727: 		start_timing(&start);
  728: 		while (end_timing(&start) < this->bench_time)
  729: 		{
  730: 			if (hasher->get_hash(hasher, buf, hash))
  731: 			{
  732: 				runs++;
  733: 			}
  734: 		}
  735: 		free(buf.ptr);
  736: 		hasher->destroy(hasher);
  737: 
  738: 		return runs;
  739: 	}
  740: 	return 0;
  741: }
  742: 
  743: METHOD(crypto_tester_t, test_hasher, bool,
  744: 	private_crypto_tester_t *this, hash_algorithm_t alg,
  745: 	hasher_constructor_t create, u_int *speed, const char *plugin_name)
  746: {
  747: 	enumerator_t *enumerator;
  748: 	hasher_test_vector_t *vector;
  749: 	bool failed = FALSE;
  750: 	u_int tested = 0;
  751: 
  752: 	enumerator = this->hasher->create_enumerator(this->hasher);
  753: 	while (enumerator->enumerate(enumerator, &vector))
  754: 	{
  755: 		hasher_t *hasher;
  756: 		chunk_t data, hash;
  757: 
  758: 		if (vector->alg != alg)
  759: 		{
  760: 			continue;
  761: 		}
  762: 
  763: 		tested++;
  764: 		failed = TRUE;
  765: 		hasher = create(alg);
  766: 		if (!hasher)
  767: 		{
  768: 			DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
  769: 				 hash_algorithm_names, alg, plugin_name);
  770: 			break;
  771: 		}
  772: 
  773: 		/* allocated hash */
  774: 		data = chunk_create(vector->data, vector->len);
  775: 		if (!hasher->allocate_hash(hasher, data, &hash))
  776: 		{
  777: 			goto failure;
  778: 		}
  779: 		if (hash.len != hasher->get_hash_size(hasher))
  780: 		{
  781: 			goto failure;
  782: 		}
  783: 		if (!memeq(vector->hash, hash.ptr, hash.len))
  784: 		{
  785: 			goto failure;
  786: 		}
  787: 		/* hash to existing buffer, with a reset */
  788: 		memset(hash.ptr, 0, hash.len);
  789: 		if (!hasher->get_hash(hasher, data, NULL))
  790: 		{
  791: 			goto failure;
  792: 		}
  793: 		if (!hasher->reset(hasher))
  794: 		{
  795: 			goto failure;
  796: 		}
  797: 		if (!hasher->get_hash(hasher, data, hash.ptr))
  798: 		{
  799: 			goto failure;
  800: 		}
  801: 		if (!memeq(vector->hash, hash.ptr, hash.len))
  802: 		{
  803: 			goto failure;
  804: 		}
  805: 		/* hasher to existing buffer, using append mode */
  806: 		if (data.len > 2)
  807: 		{
  808: 			memset(hash.ptr, 0, hash.len);
  809: 			if (!hasher->allocate_hash(hasher, chunk_create(data.ptr, 1), NULL))
  810: 			{
  811: 				goto failure;
  812: 			}
  813: 			if (!hasher->get_hash(hasher, chunk_create(data.ptr + 1, 1), NULL))
  814: 			{
  815: 				goto failure;
  816: 			}
  817: 			if (!hasher->get_hash(hasher, chunk_skip(data, 2), hash.ptr))
  818: 			{
  819: 				goto failure;
  820: 			}
  821: 			if (!memeq(vector->hash, hash.ptr, hash.len))
  822: 			{
  823: 				goto failure;
  824: 			}
  825: 		}
  826: 
  827: 		failed = FALSE;
  828: failure:
  829: 		hasher->destroy(hasher);
  830: 		chunk_free(&hash);
  831: 		if (failed)
  832: 		{
  833: 			DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
  834: 				 hash_algorithm_names, alg, plugin_name, get_name(vector));
  835: 			break;
  836: 		}
  837: 	}
  838: 	enumerator->destroy(enumerator);
  839: 	if (!tested)
  840: 	{
  841: 		DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
  842: 			 this->required ? "disabled" : "enabled ",
  843: 			 hash_algorithm_names, alg, plugin_name);
  844: 		return !this->required;
  845: 	}
  846: 	if (!failed)
  847: 	{
  848: 		if (speed)
  849: 		{
  850: 			*speed = bench_hasher(this, alg, create);
  851: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
  852: 				 hash_algorithm_names, alg, plugin_name, tested, *speed);
  853: 		}
  854: 		else
  855: 		{
  856: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
  857: 				 hash_algorithm_names, alg, plugin_name, tested);
  858: 		}
  859: 	}
  860: 	return !failed;
  861: }
  862: 
  863: /**
  864:  * Benchmark a PRF
  865:  */
  866: static u_int bench_prf(private_crypto_tester_t *this,
  867: 					   pseudo_random_function_t alg, prf_constructor_t create)
  868: {
  869: 	prf_t *prf;
  870: 
  871: 	prf = create(alg);
  872: 	if (prf)
  873: 	{
  874: 		char bytes[prf->get_block_size(prf)], key[prf->get_block_size(prf)];
  875: 		chunk_t buf;
  876: 		struct timespec start;
  877: 		u_int runs;
  878: 
  879: 		memset(key, 0x56, prf->get_block_size(prf));
  880: 		if (!prf->set_key(prf, chunk_create(key, prf->get_block_size(prf))))
  881: 		{
  882: 			prf->destroy(prf);
  883: 			return 0;
  884: 		}
  885: 
  886: 		buf = chunk_alloc(this->bench_size);
  887: 		memset(buf.ptr, 0x34, buf.len);
  888: 
  889: 		runs = 0;
  890: 		start_timing(&start);
  891: 		while (end_timing(&start) < this->bench_time)
  892: 		{
  893: 			if (prf->get_bytes(prf, buf, bytes))
  894: 			{
  895: 				runs++;
  896: 			}
  897: 		}
  898: 		free(buf.ptr);
  899: 		prf->destroy(prf);
  900: 
  901: 		return runs;
  902: 	}
  903: 	return 0;
  904: }
  905: 
  906: METHOD(crypto_tester_t, test_prf, bool,
  907: 	private_crypto_tester_t *this, pseudo_random_function_t alg,
  908: 	prf_constructor_t create, u_int *speed, const char *plugin_name)
  909: {
  910: 	enumerator_t *enumerator;
  911: 	prf_test_vector_t *vector;
  912: 	bool failed = FALSE;
  913: 	u_int tested = 0;
  914: 
  915: 	enumerator = this->prf->create_enumerator(this->prf);
  916: 	while (enumerator->enumerate(enumerator, &vector))
  917: 	{
  918: 		prf_t *prf;
  919: 		chunk_t key, seed, out = chunk_empty;
  920: 
  921: 		if (vector->alg != alg)
  922: 		{
  923: 			continue;
  924: 		}
  925: 
  926: 		tested++;
  927: 		failed = TRUE;
  928: 		prf = create(alg);
  929: 		if (!prf)
  930: 		{
  931: 			DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
  932: 				 pseudo_random_function_names, alg, plugin_name);
  933: 			break;
  934: 		}
  935: 
  936: 		seed = chunk_create(vector->seed, vector->len);
  937: 		key = chunk_create(vector->key, vector->key_size);
  938: 		if (!prf->set_key(prf, key))
  939: 		{
  940: 			goto failure;
  941: 		}
  942: 		if (alg != PRF_FIPS_SHA1_160)
  943: 		{
  944: 			/* do partial append mode and check if key gets set correctly */
  945: 			if (!prf->get_bytes(prf, seed, NULL))
  946: 			{
  947: 				goto failure;
  948: 			}
  949: 			if (!prf->set_key(prf, key))
  950: 			{
  951: 				goto failure;
  952: 			}
  953: 		}
  954: 		/* allocated bytes */
  955: 		if (!prf->allocate_bytes(prf, seed, &out))
  956: 		{
  957: 			goto failure;
  958: 		}
  959: 		if (out.len != prf->get_block_size(prf))
  960: 		{
  961: 			goto failure;
  962: 		}
  963: 		if (!memeq(vector->out, out.ptr, out.len))
  964: 		{
  965: 			goto failure;
  966: 		}
  967: 		/* bytes to existing buffer */
  968: 		memset(out.ptr, 0, out.len);
  969: 		if (vector->stateful)
  970: 		{
  971: 			if (!prf->set_key(prf, key))
  972: 			{
  973: 				goto failure;
  974: 			}
  975: 		}
  976: 		if (!prf->get_bytes(prf, seed, out.ptr))
  977: 		{
  978: 			goto failure;
  979: 		}
  980: 		if (!memeq(vector->out, out.ptr, out.len))
  981: 		{
  982: 			goto failure;
  983: 		}
  984: 		/* bytes to existing buffer, using append mode */
  985: 		if (alg != PRF_FIPS_SHA1_160 && seed.len > 2)
  986: 		{
  987: 			memset(out.ptr, 0, out.len);
  988: 			if (vector->stateful)
  989: 			{
  990: 				if (!prf->set_key(prf, key))
  991: 				{
  992: 					goto failure;
  993: 				}
  994: 			}
  995: 			if (!prf->allocate_bytes(prf, chunk_create(seed.ptr, 1), NULL))
  996: 			{
  997: 				goto failure;
  998: 			}
  999: 			if (!prf->get_bytes(prf, chunk_create(seed.ptr + 1, 1), NULL))
 1000: 			{
 1001: 				goto failure;
 1002: 			}
 1003: 			if (!prf->get_bytes(prf, chunk_skip(seed, 2), out.ptr))
 1004: 			{
 1005: 				goto failure;
 1006: 			}
 1007: 			if (!memeq(vector->out, out.ptr, out.len))
 1008: 			{
 1009: 				goto failure;
 1010: 			}
 1011: 		}
 1012: 
 1013: 		failed = FALSE;
 1014: failure:
 1015: 		prf->destroy(prf);
 1016: 		chunk_free(&out);
 1017: 		if (failed)
 1018: 		{
 1019: 			DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
 1020: 				 pseudo_random_function_names, alg, plugin_name, get_name(vector));
 1021: 			break;
 1022: 		}
 1023: 	}
 1024: 	enumerator->destroy(enumerator);
 1025: 	if (!tested)
 1026: 	{
 1027: 		DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
 1028: 			 this->required ? "disabled" : "enabled ",
 1029: 			 pseudo_random_function_names, alg, plugin_name);
 1030: 		return !this->required;
 1031: 	}
 1032: 	if (!failed)
 1033: 	{
 1034: 		if (speed)
 1035: 		{
 1036: 			*speed = bench_prf(this, alg, create);
 1037: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
 1038: 				 pseudo_random_function_names, alg, plugin_name, tested, *speed);
 1039: 		}
 1040: 		else
 1041: 		{
 1042: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
 1043: 				 pseudo_random_function_names, alg, plugin_name, tested);
 1044: 		}
 1045: 	}
 1046: 	return !failed;
 1047: }
 1048: 
 1049: /**
 1050:  * Benchmark an XOF
 1051:  */
 1052: static u_int bench_xof(private_crypto_tester_t *this,
 1053: 					   ext_out_function_t alg, xof_constructor_t create)
 1054: {
 1055: 	xof_t *xof;
 1056: 
 1057: 	xof = create(alg);
 1058: 	if (xof)
 1059: 	{
 1060: 		char seed[xof->get_seed_size(xof)];
 1061: 		char bytes[xof->get_block_size(xof)];
 1062: 		struct timespec start;
 1063: 		u_int runs;
 1064: 
 1065: 		memset(seed, 0x56, xof->get_seed_size(xof));
 1066: 		if (!xof->set_seed(xof, chunk_create(seed, xof->get_seed_size(xof))))
 1067: 		{
 1068: 			xof->destroy(xof);
 1069: 			return 0;
 1070: 		}
 1071: 
 1072: 		runs = 0;
 1073: 		start_timing(&start);
 1074: 		while (end_timing(&start) < this->bench_time)
 1075: 		{
 1076: 			if (xof->get_bytes(xof, xof->get_block_size(xof), bytes))
 1077: 			{
 1078: 				runs++;
 1079: 			}
 1080: 		}
 1081: 		xof->destroy(xof);
 1082: 
 1083: 		return runs;
 1084: 	}
 1085: 	return 0;
 1086: }
 1087: 
 1088: METHOD(crypto_tester_t, test_xof, bool,
 1089: 	private_crypto_tester_t *this, ext_out_function_t alg,
 1090: 	xof_constructor_t create, u_int *speed, const char *plugin_name)
 1091: {
 1092: 	enumerator_t *enumerator;
 1093: 	xof_test_vector_t *vector;
 1094: 	bool failed = FALSE;
 1095: 	u_int tested = 0;
 1096: 
 1097: 	enumerator = this->xof->create_enumerator(this->xof);
 1098: 	while (enumerator->enumerate(enumerator, &vector))
 1099: 	{
 1100: 		xof_t *xof;
 1101: 		chunk_t seed, out = chunk_empty;
 1102: 
 1103: 		if (vector->alg != alg)
 1104: 		{
 1105: 			continue;
 1106: 		}
 1107: 
 1108: 		tested++;
 1109: 		failed = TRUE;
 1110: 		xof = create(alg);
 1111: 		if (!xof)
 1112: 		{
 1113: 			DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
 1114: 				 ext_out_function_names, alg, plugin_name);
 1115: 			break;
 1116: 		}
 1117: 
 1118: 		seed = chunk_create(vector->seed, vector->len);
 1119: 		if (!xof->set_seed(xof, seed))
 1120: 		{
 1121: 			goto failure;
 1122: 		}
 1123: 		/* allocated bytes */
 1124: 		if (!xof->allocate_bytes(xof, vector->out_len, &out))
 1125: 		{
 1126: 			goto failure;
 1127: 		}
 1128: 		if (out.len != vector->out_len)
 1129: 		{
 1130: 			goto failure;
 1131: 		}
 1132: 		if (!memeq(vector->out, out.ptr, out.len))
 1133: 		{
 1134: 			goto failure;
 1135: 		}
 1136: 		/* bytes to existing buffer */
 1137: 		memset(out.ptr, 0, out.len);
 1138: 		if (!xof->set_seed(xof, seed))
 1139: 		{
 1140: 			goto failure;
 1141: 		}
 1142: 		if (!xof->get_bytes(xof, vector->out_len, out.ptr))
 1143: 		{
 1144: 			goto failure;
 1145: 		}
 1146: 		if (!memeq(vector->out, out.ptr, vector->out_len))
 1147: 		{
 1148: 			goto failure;
 1149: 		}
 1150: 		/* bytes to existing buffer, using append mode */
 1151: 		/* TODO */
 1152: 
 1153: 		failed = FALSE;
 1154: failure:
 1155: 		xof->destroy(xof);
 1156: 		chunk_free(&out);
 1157: 		if (failed)
 1158: 		{
 1159: 			DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
 1160: 				 ext_out_function_names, alg, plugin_name, get_name(vector));
 1161: 			break;
 1162: 		}
 1163: 	}
 1164: 	enumerator->destroy(enumerator);
 1165: 	if (!tested)
 1166: 	{
 1167: 		DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
 1168: 			 this->required ? "disabled" : "enabled ",
 1169: 			 ext_out_function_names, alg, plugin_name);
 1170: 		return !this->required;
 1171: 	}
 1172: 	if (!failed)
 1173: 	{
 1174: 		if (speed)
 1175: 		{
 1176: 			*speed = bench_xof(this, alg, create);
 1177: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
 1178: 				 ext_out_function_names, alg, plugin_name, tested, *speed);
 1179: 		}
 1180: 		else
 1181: 		{
 1182: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
 1183: 				 ext_out_function_names, alg, plugin_name, tested);
 1184: 		}
 1185: 	}
 1186: 	return !failed;
 1187: }
 1188: 
 1189: /**
 1190:  * Benchmark a DRBG
 1191:  */
 1192: static u_int bench_drbg(private_crypto_tester_t *this,
 1193: 						drbg_type_t type, drbg_constructor_t create)
 1194: {
 1195: 	drbg_t *drbg;
 1196: 	rng_t *entropy;
 1197: 	uint32_t strength = 128;
 1198: 	chunk_t seed = chunk_alloca(48);
 1199: 
 1200: 	memset(seed.ptr, 0x81, seed.len);
 1201: 	entropy = rng_tester_create(seed);
 1202: 
 1203: 	drbg = create(type, strength, entropy, chunk_empty);
 1204: 	if (drbg)
 1205: 	{
 1206: 		struct timespec start;
 1207: 		u_int runs = 0;
 1208: 		size_t out_len = 128;
 1209: 		char out_buf[out_len];
 1210: 
 1211: 		start_timing(&start);
 1212: 		while (end_timing(&start) < this->bench_time)
 1213: 		{
 1214: 			if (drbg->generate(drbg, out_len, out_buf))
 1215: 			{
 1216: 				runs++;
 1217: 			}
 1218: 		}
 1219: 		drbg->destroy(drbg);
 1220: 
 1221: 		return runs;
 1222: 	}
 1223: 	return 0;
 1224: }
 1225: 
 1226: METHOD(crypto_tester_t, test_drbg, bool,
 1227: 	private_crypto_tester_t *this, drbg_type_t type,
 1228: 	drbg_constructor_t create, u_int *speed, const char *plugin_name)
 1229: {
 1230: 	enumerator_t *enumerator;
 1231: 	drbg_test_vector_t *vector;
 1232: 	bool failed = FALSE;
 1233: 	u_int tested = 0;
 1234: 
 1235: 	enumerator = this->drbg->create_enumerator(this->drbg);
 1236: 	while (enumerator->enumerate(enumerator, &vector))
 1237: 	{
 1238: 		drbg_t *drbg;
 1239: 		rng_t *entropy;
 1240: 		chunk_t out = chunk_empty;
 1241: 
 1242: 		if (vector->type != type)
 1243: 		{
 1244: 			continue;
 1245: 		}
 1246: 		tested++;
 1247: 		failed = TRUE;
 1248: 
 1249: 		entropy = rng_tester_create(vector->entropy);
 1250: 		out = chunk_alloc(vector->out.len);
 1251: 
 1252: 		drbg = create(type, vector->strength, entropy,
 1253: 					  vector->personalization_str);
 1254: 		if (!drbg)
 1255: 		{
 1256: 			DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
 1257: 				 drbg_type_names, type, plugin_name);
 1258: 			entropy->destroy(entropy);
 1259: 			chunk_free(&out);
 1260: 			break;
 1261: 		}
 1262: 		if (!drbg->reseed(drbg))
 1263: 		{
 1264: 			goto failure;
 1265: 		}
 1266: 		if (!drbg->generate(drbg, out.len, out.ptr))
 1267: 		{
 1268: 			goto failure;
 1269: 		}
 1270: 		if (!drbg->generate(drbg, out.len, out.ptr))
 1271: 		{
 1272: 			goto failure;
 1273: 		}
 1274: 		if (!chunk_equals(out, vector->out))
 1275: 		{
 1276: 			goto failure;
 1277: 		}
 1278: 		failed = FALSE;
 1279: 
 1280: failure:
 1281: 		drbg->destroy(drbg);
 1282: 		chunk_free(&out);
 1283: 		if (failed)
 1284: 		{
 1285: 			DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
 1286: 				 drbg_type_names, type, plugin_name, get_name(vector));
 1287: 			break;
 1288: 		}
 1289: 	}
 1290: 	enumerator->destroy(enumerator);
 1291: 	if (!tested)
 1292: 	{
 1293: 		DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
 1294: 			 this->required ? "disabled" : "enabled ",
 1295: 			 drbg_type_names, type, plugin_name);
 1296: 		return !this->required;
 1297: 	}
 1298: 	if (!failed)
 1299: 	{
 1300: 		if (speed)
 1301: 		{
 1302: 			*speed = bench_drbg(this, type, create);
 1303: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
 1304: 				 drbg_type_names, type, plugin_name, tested, *speed);
 1305: 		}
 1306: 		else
 1307: 		{
 1308: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
 1309: 				 drbg_type_names, type, plugin_name, tested);
 1310: 		}
 1311: 	}
 1312: 	return !failed;
 1313: }
 1314: 
 1315: /**
 1316:  * Benchmark a RNG
 1317:  */
 1318: static u_int bench_rng(private_crypto_tester_t *this,
 1319: 					   rng_quality_t quality, rng_constructor_t create)
 1320: {
 1321: 	rng_t *rng;
 1322: 
 1323: 	rng = create(quality);
 1324: 	if (rng)
 1325: 	{
 1326: 		struct timespec start;
 1327: 		chunk_t buf;
 1328: 		u_int runs;
 1329: 
 1330: 		runs = 0;
 1331: 		buf = chunk_alloc(this->bench_size);
 1332: 		start_timing(&start);
 1333: 		while (end_timing(&start) < this->bench_time)
 1334: 		{
 1335: 			if (!rng->get_bytes(rng, buf.len, buf.ptr))
 1336: 			{
 1337: 				runs = 0;
 1338: 				break;
 1339: 			}
 1340: 			runs++;
 1341: 		}
 1342: 		free(buf.ptr);
 1343: 		rng->destroy(rng);
 1344: 
 1345: 		return runs;
 1346: 	}
 1347: 	return 0;
 1348: }
 1349: 
 1350: METHOD(crypto_tester_t, test_rng, bool,
 1351: 	private_crypto_tester_t *this, rng_quality_t quality,
 1352: 	rng_constructor_t create, u_int *speed, const char *plugin_name)
 1353: {
 1354: 	enumerator_t *enumerator;
 1355: 	rng_test_vector_t *vector;
 1356: 	bool failed = FALSE;
 1357: 	u_int tested = 0;
 1358: 
 1359: 	if (!this->rng_true && quality == RNG_TRUE)
 1360: 	{
 1361: 		DBG1(DBG_LIB, "enabled  %N[%s]: skipping test (disabled by config)",
 1362: 			 rng_quality_names, quality, plugin_name);
 1363: 		return TRUE;
 1364: 	}
 1365: 
 1366: 	enumerator = this->rng->create_enumerator(this->rng);
 1367: 	while (enumerator->enumerate(enumerator, &vector))
 1368: 	{
 1369: 		chunk_t data = chunk_empty;
 1370: 		rng_t *rng;
 1371: 
 1372: 		if (vector->quality != quality)
 1373: 		{
 1374: 			continue;
 1375: 		}
 1376: 
 1377: 		tested++;
 1378: 		failed = TRUE;
 1379: 		rng = create(quality);
 1380: 		if (!rng)
 1381: 		{
 1382: 			DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
 1383: 				 rng_quality_names, quality, plugin_name);
 1384: 			break;
 1385: 		}
 1386: 
 1387: 		/* allocated bytes */
 1388: 		if (!rng->allocate_bytes(rng, vector->len, &data) ||
 1389: 			data.len != vector->len ||
 1390: 			!vector->test(vector->user, data))
 1391: 		{
 1392: 			goto failure;
 1393: 		}
 1394: 		/* write bytes into existing buffer */
 1395: 		memset(data.ptr, 0, data.len);
 1396: 		if (!rng->get_bytes(rng, vector->len, data.ptr))
 1397: 		{
 1398: 			goto failure;
 1399: 		}
 1400: 		if (!vector->test(vector->user, data))
 1401: 		{
 1402: 			goto failure;
 1403: 		}
 1404: 
 1405: 		failed = FALSE;
 1406: failure:
 1407: 		rng->destroy(rng);
 1408: 		chunk_free(&data);
 1409: 		if (failed)
 1410: 		{
 1411: 			DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
 1412: 				 rng_quality_names, quality, plugin_name, get_name(vector));
 1413: 			break;
 1414: 		}
 1415: 	}
 1416: 	enumerator->destroy(enumerator);
 1417: 	if (!tested)
 1418: 	{
 1419: 		DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
 1420: 			 this->required ? ", disabled" : "enabled ",
 1421: 			 rng_quality_names, quality, plugin_name);
 1422: 		return !this->required;
 1423: 	}
 1424: 	if (!failed)
 1425: 	{
 1426: 		if (speed)
 1427: 		{
 1428: 			*speed = bench_rng(this, quality, create);
 1429: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
 1430: 				 rng_quality_names, quality, plugin_name, tested, *speed);
 1431: 		}
 1432: 		else
 1433: 		{
 1434: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
 1435: 				 rng_quality_names, quality, plugin_name, tested);
 1436: 		}
 1437: 	}
 1438: 	return !failed;
 1439: }
 1440: 
 1441: /**
 1442:  * Benchmark a DH backend
 1443:  */
 1444: static u_int bench_dh(private_crypto_tester_t *this,
 1445: 					  diffie_hellman_group_t group, dh_constructor_t create)
 1446: {
 1447: 	chunk_t pub = chunk_empty, shared = chunk_empty;
 1448: 	diffie_hellman_t *dh;
 1449: 	struct timespec start;
 1450: 	u_int runs;
 1451: 
 1452: 	runs = 0;
 1453: 	start_timing(&start);
 1454: 	while (end_timing(&start) < this->bench_time)
 1455: 	{
 1456: 		dh = create(group);
 1457: 		if (!dh)
 1458: 		{
 1459: 			return 0;
 1460: 		}
 1461: 		if (dh->get_my_public_value(dh, &pub) &&
 1462: 			dh->set_other_public_value(dh, pub) &&
 1463: 			dh->get_shared_secret(dh, &shared))
 1464: 		{
 1465: 			runs++;
 1466: 		}
 1467: 		chunk_free(&pub);
 1468: 		chunk_free(&shared);
 1469: 		dh->destroy(dh);
 1470: 	}
 1471: 	return runs;
 1472: }
 1473: 
 1474: METHOD(crypto_tester_t, test_dh, bool,
 1475: 	private_crypto_tester_t *this, diffie_hellman_group_t group,
 1476: 	dh_constructor_t create, u_int *speed, const char *plugin_name)
 1477: {
 1478: 	enumerator_t *enumerator;
 1479: 	dh_test_vector_t *v;
 1480: 	bool failed = FALSE;
 1481: 	u_int tested = 0;
 1482: 
 1483: 	enumerator = this->dh->create_enumerator(this->dh);
 1484: 	while (enumerator->enumerate(enumerator, &v))
 1485: 	{
 1486: 		diffie_hellman_t *a, *b;
 1487: 		chunk_t apub, bpub, asec, bsec;
 1488: 
 1489: 		if (v->group != group)
 1490: 		{
 1491: 			continue;
 1492: 		}
 1493: 
 1494: 		a = create(group);
 1495: 		b = create(group);
 1496: 		if (!a || !b)
 1497: 		{
 1498: 			DESTROY_IF(a);
 1499: 			DESTROY_IF(b);
 1500: 			failed = TRUE;
 1501: 			tested++;
 1502: 			DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
 1503: 				 diffie_hellman_group_names, group, plugin_name);
 1504: 			break;
 1505: 		}
 1506: 
 1507: 		if (!a->set_private_value || !b->set_private_value)
 1508: 		{	/* does not support testing */
 1509: 			a->destroy(a);
 1510: 			b->destroy(b);
 1511: 			continue;
 1512: 		}
 1513: 		failed = TRUE;
 1514: 		tested++;
 1515: 
 1516: 		apub = bpub = asec = bsec = chunk_empty;
 1517: 
 1518: 		if (!a->set_private_value(a, chunk_create(v->priv_a, v->priv_len)) ||
 1519: 			!b->set_private_value(b, chunk_create(v->priv_b, v->priv_len)))
 1520: 		{
 1521: 			goto failure;
 1522: 		}
 1523: 		if (!a->get_my_public_value(a, &apub) ||
 1524: 			!chunk_equals(apub, chunk_create(v->pub_a, v->pub_len)))
 1525: 		{
 1526: 			goto failure;
 1527: 		}
 1528: 		if (!b->get_my_public_value(b, &bpub) ||
 1529: 			!chunk_equals(bpub, chunk_create(v->pub_b, v->pub_len)))
 1530: 		{
 1531: 			goto failure;
 1532: 		}
 1533: 		if (!a->set_other_public_value(a, bpub) ||
 1534: 			!b->set_other_public_value(b, apub))
 1535: 		{
 1536: 			goto failure;
 1537: 		}
 1538: 		if (!a->get_shared_secret(a, &asec) ||
 1539: 			!chunk_equals(asec, chunk_create(v->shared, v->shared_len)))
 1540: 		{
 1541: 			goto failure;
 1542: 		}
 1543: 		if (!b->get_shared_secret(b, &bsec) ||
 1544: 			!chunk_equals(bsec, chunk_create(v->shared, v->shared_len)))
 1545: 		{
 1546: 			goto failure;
 1547: 		}
 1548: 
 1549: 		failed = FALSE;
 1550: failure:
 1551: 		a->destroy(a);
 1552: 		b->destroy(b);
 1553: 		chunk_free(&apub);
 1554: 		chunk_free(&bpub);
 1555: 		chunk_free(&asec);
 1556: 		chunk_free(&bsec);
 1557: 		if (failed)
 1558: 		{
 1559: 			DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
 1560: 				 diffie_hellman_group_names, group, plugin_name, get_name(v));
 1561: 			break;
 1562: 		}
 1563: 	}
 1564: 	enumerator->destroy(enumerator);
 1565: 	if (!tested)
 1566: 	{
 1567: 		DBG1(DBG_LIB, "%s %N[%s]: no test vectors found / untestable",
 1568: 			 this->required ? "disabled" : "enabled ",
 1569: 			 diffie_hellman_group_names, group, plugin_name);
 1570: 		return !this->required;
 1571: 	}
 1572: 	if (!failed)
 1573: 	{
 1574: 		if (speed)
 1575: 		{
 1576: 			*speed = bench_dh(this, group, create);
 1577: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
 1578: 				 diffie_hellman_group_names, group, plugin_name, tested, *speed);
 1579: 		}
 1580: 		else
 1581: 		{
 1582: 			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
 1583: 				 diffie_hellman_group_names, group, plugin_name, tested);
 1584: 		}
 1585: 	}
 1586: 	return !failed;
 1587: }
 1588: 
 1589: METHOD(crypto_tester_t, add_crypter_vector, void,
 1590: 	private_crypto_tester_t *this, crypter_test_vector_t *vector)
 1591: {
 1592: 	this->crypter->insert_last(this->crypter, vector);
 1593: }
 1594: 
 1595: METHOD(crypto_tester_t, add_aead_vector, void,
 1596: 	private_crypto_tester_t *this, aead_test_vector_t *vector)
 1597: {
 1598: 	this->aead->insert_last(this->aead, vector);
 1599: }
 1600: 
 1601: METHOD(crypto_tester_t, add_signer_vector, void,
 1602: 	private_crypto_tester_t *this, signer_test_vector_t *vector)
 1603: {
 1604: 	this->signer->insert_last(this->signer, vector);
 1605: }
 1606: 
 1607: METHOD(crypto_tester_t, add_hasher_vector, void,
 1608: 	private_crypto_tester_t *this, hasher_test_vector_t *vector)
 1609: {
 1610: 	this->hasher->insert_last(this->hasher, vector);
 1611: }
 1612: 
 1613: METHOD(crypto_tester_t, add_prf_vector, void,
 1614: 	private_crypto_tester_t *this, prf_test_vector_t *vector)
 1615: {
 1616: 	this->prf->insert_last(this->prf, vector);
 1617: }
 1618: 
 1619: METHOD(crypto_tester_t, add_xof_vector, void,
 1620: 	private_crypto_tester_t *this, xof_test_vector_t *vector)
 1621: {
 1622: 	this->xof->insert_last(this->xof, vector);
 1623: }
 1624: 
 1625: METHOD(crypto_tester_t, add_drbg_vector, void,
 1626: 	private_crypto_tester_t *this, drbg_test_vector_t *vector)
 1627: {
 1628: 	this->drbg->insert_last(this->drbg, vector);
 1629: }
 1630: 
 1631: METHOD(crypto_tester_t, add_rng_vector, void,
 1632: 	private_crypto_tester_t *this, rng_test_vector_t *vector)
 1633: {
 1634: 	this->rng->insert_last(this->rng, vector);
 1635: }
 1636: 
 1637: METHOD(crypto_tester_t, add_dh_vector, void,
 1638: 	private_crypto_tester_t *this, dh_test_vector_t *vector)
 1639: {
 1640: 	this->dh->insert_last(this->dh, vector);
 1641: }
 1642: 
 1643: METHOD(crypto_tester_t, destroy, void,
 1644: 	private_crypto_tester_t *this)
 1645: {
 1646: 	this->crypter->destroy(this->crypter);
 1647: 	this->aead->destroy(this->aead);
 1648: 	this->signer->destroy(this->signer);
 1649: 	this->hasher->destroy(this->hasher);
 1650: 	this->prf->destroy(this->prf);
 1651: 	this->xof->destroy(this->xof);
 1652: 	this->drbg->destroy(this->drbg);
 1653: 	this->rng->destroy(this->rng);
 1654: 	this->dh->destroy(this->dh);
 1655: 	free(this);
 1656: }
 1657: 
 1658: /**
 1659:  * See header
 1660:  */
 1661: crypto_tester_t *crypto_tester_create()
 1662: {
 1663: 	private_crypto_tester_t *this;
 1664: 
 1665: 	INIT(this,
 1666: 		.public = {
 1667: 			.test_crypter = _test_crypter,
 1668: 			.test_aead = _test_aead,
 1669: 			.test_signer = _test_signer,
 1670: 			.test_hasher = _test_hasher,
 1671: 			.test_prf = _test_prf,
 1672: 			.test_xof = _test_xof,
 1673: 			.test_drbg = _test_drbg,
 1674: 			.test_rng = _test_rng,
 1675: 			.test_dh = _test_dh,
 1676: 			.add_crypter_vector = _add_crypter_vector,
 1677: 			.add_aead_vector = _add_aead_vector,
 1678: 			.add_signer_vector = _add_signer_vector,
 1679: 			.add_hasher_vector = _add_hasher_vector,
 1680: 			.add_prf_vector = _add_prf_vector,
 1681: 			.add_xof_vector = _add_xof_vector,
 1682: 			.add_drbg_vector = _add_drbg_vector,
 1683: 			.add_rng_vector = _add_rng_vector,
 1684: 			.add_dh_vector = _add_dh_vector,
 1685: 			.destroy = _destroy,
 1686: 		},
 1687: 		.crypter = linked_list_create(),
 1688: 		.aead = linked_list_create(),
 1689: 		.signer = linked_list_create(),
 1690: 		.hasher = linked_list_create(),
 1691: 		.prf = linked_list_create(),
 1692: 		.xof = linked_list_create(),
 1693: 		.drbg = linked_list_create(),
 1694: 		.rng = linked_list_create(),
 1695: 		.dh = linked_list_create(),
 1696: 
 1697: 		.required = lib->settings->get_bool(lib->settings,
 1698: 								"%s.crypto_test.required", FALSE, lib->ns),
 1699: 		.rng_true = lib->settings->get_bool(lib->settings,
 1700: 								"%s.crypto_test.rng_true", FALSE, lib->ns),
 1701: 		.bench_time = lib->settings->get_int(lib->settings,
 1702: 								"%s.crypto_test.bench_time", 50, lib->ns),
 1703: 		.bench_size = lib->settings->get_int(lib->settings,
 1704: 								"%s.crypto_test.bench_size", 1024, lib->ns),
 1705: 	);
 1706: 
 1707: 	/* enforce a block size of 16, should be fine for all algorithms */
 1708: 	this->bench_size = this->bench_size / 16 * 16;
 1709: 
 1710: 	return &this->public;
 1711: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>