Annotation of embedaddon/strongswan/src/libstrongswan/crypto/crypto_tester.c, revision 1.1

1.1     ! misho       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>