Annotation of embedaddon/strongswan/src/libstrongswan/crypto/crypto_tester.c, revision 1.1.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>