Annotation of embedaddon/strongswan/scripts/aes-test.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2013 Tobias Brunner
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include <stdio.h>
                     17: #include <stdlib.h>
                     18: #include <string.h>
                     19: #include <unistd.h>
                     20: #include <getopt.h>
                     21: #include <errno.h>
                     22: 
                     23: #include <library.h>
                     24: 
                     25: /** plugins to load */
                     26: #undef PLUGINS
                     27: #define PLUGINS "openssl"
                     28: 
                     29: /**
                     30:  * Context
                     31:  */
                     32: static struct {
                     33:        /** input file */
                     34:        FILE *in;
                     35:        /** output file */
                     36:        FILE *out;
                     37:        /** whether to use GCM or CBC */
                     38:        bool use_gcm;
                     39:        /** whether to run the Monte Carlo Test */
                     40:        bool use_mct;
                     41:        /** whether to test encryption or decryption */
                     42:        bool decrypt;
                     43:        /** IV length in bits in case of GCM */
                     44:        int ivlen;
                     45:        /** ICV length in bits in case of GCM */
                     46:        int icvlen;
                     47: } ctx;
                     48: 
                     49: /**
                     50:  * Types of parameters of a test vector
                     51:  */
                     52: typedef enum {
                     53:        PARAM_UNKNOWN,
                     54:        PARAM_COUNT,
                     55:        PARAM_KEY,
                     56:        PARAM_IV,
                     57:        PARAM_PLAINTEXT,
                     58:        PARAM_CIPHERTEXT,
                     59:        PARAM_AAD,
                     60:        PARAM_ICV,
                     61: } param_t;
                     62: 
                     63: static param_t parse_parameter(char *param)
                     64: {
                     65:        if (strcaseeq(param, "COUNT"))
                     66:        {
                     67:                return PARAM_COUNT;
                     68:        }
                     69:        if (strcaseeq(param, "KEY"))
                     70:        {
                     71:                return PARAM_KEY;
                     72:        }
                     73:        if (strcaseeq(param, "IV"))
                     74:        {
                     75:                return PARAM_IV;
                     76:        }
                     77:        if (strcaseeq(param, "PLAINTEXT") ||
                     78:                strcaseeq(param, "PT"))
                     79:        {
                     80:                return PARAM_PLAINTEXT;
                     81:        }
                     82:        if (strcaseeq(param, "CIPHERTEXT") ||
                     83:                strcaseeq(param, "CT"))
                     84:        {
                     85:                return PARAM_CIPHERTEXT;
                     86:        }
                     87:        if (strcaseeq(param, "AAD"))
                     88:        {
                     89:                return PARAM_AAD;
                     90:        }
                     91:        if (strcaseeq(param, "TAG"))
                     92:        {
                     93:                return PARAM_ICV;
                     94:        }
                     95:        return PARAM_UNKNOWN;
                     96: }
                     97: 
                     98: /**
                     99:  * Test vector
                    100:  */
                    101: typedef struct {
                    102:        /** encryption/decryption key */
                    103:        chunk_t key;
                    104:        /** initialization vector */
                    105:        chunk_t iv;
                    106:        /** plain text */
                    107:        chunk_t plain;
                    108:        /** cipher text */
                    109:        chunk_t cipher;
                    110:        /** associated data */
                    111:        chunk_t aad;
                    112:        /** ICV/tag */
                    113:        chunk_t icv;
                    114:        /** whether the IV was provided */
                    115:        bool external_iv;
                    116:        /** whether the decryption/verification in GCM mode was successful */
                    117:        bool success;
                    118: } test_vector_t;
                    119: 
                    120: static void test_vector_free(test_vector_t *test)
                    121: {
                    122:        chunk_free(&test->key);
                    123:        chunk_free(&test->iv);
                    124:        chunk_free(&test->plain);
                    125:        chunk_free(&test->cipher);
                    126:        chunk_free(&test->aad);
                    127:        chunk_free(&test->icv);
                    128: }
                    129: 
                    130: static void print_result(test_vector_t *test)
                    131: {
                    132:        if (ctx.use_gcm)
                    133:        {
                    134:                if (ctx.decrypt)
                    135:                {
                    136:                        if (test->success)
                    137:                        {
                    138:                                fprintf(ctx.out, "PT = %+B\n", &test->plain);
                    139:                        }
                    140:                        else
                    141:                        {
                    142:                                fprintf(ctx.out, "FAIL\n");
                    143:                        }
                    144:                        return;
                    145:                }
                    146:                if (!test->external_iv)
                    147:                {
                    148:                        fprintf(ctx.out, "IV = %+B\n", &test->iv);
                    149:                }
                    150:                fprintf(ctx.out, "CT = %+B\n", &test->cipher);
                    151:                fprintf(ctx.out, "Tag = %+B\n", &test->icv);
                    152:        }
                    153:        else
                    154:        {
                    155:                fprintf(ctx.out, "%s = %+B\n", ctx.decrypt ? "PLAINTEXT" : "CIPHERTEXT",
                    156:                                ctx.decrypt ? &test->plain : &test->cipher);
                    157:        }
                    158: }
                    159: 
                    160: static bool get_next_test_vector(test_vector_t *test)
                    161: {
                    162:        param_t param = PARAM_UNKNOWN;
                    163:        char line[512];
                    164: 
                    165:        memset(test, 0, sizeof(test_vector_t));
                    166: 
                    167:        while (fgets(line, sizeof(line), ctx.in))
                    168:        {
                    169:                enumerator_t *enumerator;
                    170:                chunk_t value = chunk_empty;
                    171:                char *token;
                    172:                int i;
                    173: 
                    174:                switch (line[0])
                    175:                {
                    176:                        case '\n':
                    177:                        case '\r':
                    178:                        case '#':
                    179:                        case '\0':
                    180:                                /* copy comments, empty lines etc. directly to the output */
                    181:                                if (param != PARAM_UNKNOWN)
                    182:                                {       /* seems we got a complete test vector */
                    183:                                        return TRUE;
                    184:                                }
                    185:                                fputs(line, ctx.out);
                    186:                                continue;
                    187:                        case '[':
                    188:                                /* control directives */
                    189:                                fputs(line, ctx.out);
                    190:                                if (strpfx(line, "[ENCRYPT]"))
                    191:                                {
                    192:                                        ctx.decrypt = FALSE;
                    193:                                }
                    194:                                else if (strpfx(line, "[DECRYPT]"))
                    195:                                {
                    196:                                        ctx.decrypt = TRUE;
                    197:                                }
                    198:                                else if (strcasepfx(line, "[IVlen = "))
                    199:                                {
                    200:                                        ctx.ivlen = atoi(line + strlen("[IVlen = "));
                    201:                                }
                    202:                                else if (strcasepfx(line, "[Taglen = "))
                    203:                                {
                    204:                                        ctx.icvlen = atoi(line + strlen("[Taglen = "));
                    205:                                }
                    206:                                continue;
                    207:                        default:
                    208:                                /* we assume the rest of the lines are PARAM = VALUE pairs*/
                    209:                                fputs(line, ctx.out);
                    210:                                break;
                    211:                }
                    212: 
                    213:                i = 0;
                    214:                enumerator = enumerator_create_token(line, "=", " \n\r");
                    215:                while (enumerator->enumerate(enumerator, &token))
                    216:                {
                    217:                        switch (i++)
                    218:                        {
                    219:                                case 0: /* PARAM */
                    220:                                        param = parse_parameter(token);
                    221:                                        continue;
                    222:                                case 1: /* VALUE */
                    223:                                        if (param != PARAM_UNKNOWN && param != PARAM_COUNT)
                    224:                                        {
                    225:                                                value = chunk_from_hex(chunk_from_str(token), NULL);
                    226:                                        }
                    227:                                        else
                    228:                                        {
                    229:                                                value = chunk_empty;
                    230:                                        }
                    231:                                        continue;
                    232:                                default:
                    233:                                        break;
                    234:                        }
                    235:                        break;
                    236:                }
                    237:                enumerator->destroy(enumerator);
                    238:                if (i < 2)
                    239:                {
                    240:                        value = chunk_empty;
                    241:                }
                    242:                switch (param)
                    243:                {
                    244:                        case PARAM_KEY:
                    245:                                test->key = value;
                    246:                                break;
                    247:                        case PARAM_IV:
                    248:                                test->iv = value;
                    249:                                test->external_iv = TRUE;
                    250:                                break;
                    251:                        case PARAM_PLAINTEXT:
                    252:                                test->plain = value;
                    253:                                break;
                    254:                        case PARAM_CIPHERTEXT:
                    255:                                test->cipher = value;
                    256:                                break;
                    257:                        case PARAM_AAD:
                    258:                                test->aad = value;
                    259:                                break;
                    260:                        case PARAM_ICV:
                    261:                                test->icv = value;
                    262:                                break;
                    263:                        default:
                    264:                                chunk_free(&value);
                    265:                                break;
                    266:                }
                    267:        }
                    268:        if (param != PARAM_UNKNOWN)
                    269:        {       /* could be that the file ended with a complete test vector */
                    270:                return TRUE;
                    271:        }
                    272:        return FALSE;
                    273: }
                    274: 
                    275: static bool verify_test_vector(test_vector_t *test)
                    276: {
                    277:        if (ctx.use_gcm)
                    278:        {
                    279:                if (ctx.decrypt)
                    280:                {
                    281:                        return test->key.ptr && test->iv.ptr && test->cipher.ptr &&
                    282:                                   test->icv.ptr;
                    283:                }
                    284:                return test->key.ptr && test->plain.ptr;
                    285:        }
                    286:        if (ctx.decrypt)
                    287:        {
                    288:                return test->key.ptr && test->iv.ptr && test->cipher.ptr;
                    289:        }
                    290:        return test->key.ptr && test->iv.ptr && test->plain.ptr;
                    291: }
                    292: 
                    293: static bool do_test_gcm(test_vector_t *test)
                    294: {
                    295:        encryption_algorithm_t alg;
                    296:        chunk_t key, iv;
                    297:        aead_t *aead;
                    298:        size_t saltlen, ivlen;
                    299: 
                    300:        switch (ctx.icvlen / 8)
                    301:        {
                    302:                case 8:
                    303:                        alg = ENCR_AES_GCM_ICV8;
                    304:                        break;
                    305:                case 12:
                    306:                        alg = ENCR_AES_GCM_ICV12;
                    307:                        break;
                    308:                case 16:
                    309:                        alg = ENCR_AES_GCM_ICV16;
                    310:                        break;
                    311:                default:
                    312:                        DBG1(DBG_APP, "unsupported ICV length: %d", ctx.icvlen);
                    313:                        return FALSE;
                    314:        }
                    315: 
                    316:        aead = lib->crypto->create_aead(lib->crypto, alg, test->key.len, 4);
                    317:        if (!aead)
                    318:        {
                    319:                DBG1(DBG_APP, "algorithm %N or key length (%d bits) not supported",
                    320:                         encryption_algorithm_names, alg, test->key.len * 8);
                    321:                return FALSE;
                    322:        }
                    323:        /* our API is quite RFC 4106 specific, that is, part of the IV is provided
                    324:         * at the end of the key. */
                    325:        saltlen = aead->get_key_size(aead) - test->key.len;
                    326:        ivlen = aead->get_iv_size(aead);
                    327:        if (ctx.ivlen / 8 != saltlen + ivlen)
                    328:        {
                    329:                DBG1(DBG_APP, "unsupported IV length: %d", ctx.ivlen);
                    330:                aead->destroy(aead);
                    331:                return FALSE;
                    332:        }
                    333:        if (!test->external_iv)
                    334:        {
                    335:                rng_t *rng;
                    336: 
                    337:                /* the IV consists of saltlen random bytes (usually additional keymat)
                    338:                 * followed by a counter, zero here */
                    339:                test->iv = chunk_alloc(saltlen + ivlen);
                    340:                memset(test->iv.ptr, 0, test->iv.len);
                    341:                rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
                    342:                if (!rng || !rng->get_bytes(rng, saltlen, test->iv.ptr))
                    343:                {
                    344:                        DBG1(DBG_APP, "failed to generate IV");
                    345:                        DESTROY_IF(rng);
                    346:                        aead->destroy(aead);
                    347:                        return FALSE;
                    348:                }
                    349:                rng->destroy(rng);
                    350:        }
                    351:        key = chunk_alloca(test->key.len + saltlen);
                    352:        memcpy(key.ptr, test->key.ptr, test->key.len);
                    353:        memcpy(key.ptr + test->key.len, test->iv.ptr, saltlen);
                    354:        iv = chunk_alloca(ivlen);
                    355:        memcpy(iv.ptr, test->iv.ptr + saltlen, iv.len);
                    356:        if (!aead->set_key(aead, key))
                    357:        {
                    358:                DBG1(DBG_APP, "failed to set key");
                    359:                aead->destroy(aead);
                    360:                return FALSE;
                    361:        }
                    362:        if (ctx.decrypt)
                    363:        {
                    364:                /* the ICV is expected to follow the cipher text */
                    365:                chunk_t cipher = chunk_cata("cc", test->cipher, test->icv);
                    366:                /* store if the verification of the ICV verification is successful */
                    367:                test->success = aead->decrypt(aead, cipher, test->aad, iv,
                    368:                                                                          &test->plain);
                    369:        }
                    370:        else
                    371:        {
                    372:                if (!aead->encrypt(aead, test->plain, test->aad, iv, &test->cipher))
                    373:                {
                    374:                        DBG1(DBG_APP, "encryption failed");
                    375:                        aead->destroy(aead);
                    376:                        return FALSE;
                    377:                }
                    378:                /* copy ICV from the end of the cipher text */
                    379:                test->icv = chunk_alloc(ctx.icvlen / 8);
                    380:                test->cipher.len -= test->icv.len;
                    381:                memcpy(test->icv.ptr, test->cipher.ptr + test->cipher.len,
                    382:                           test->icv.len);
                    383:        }
                    384:        aead->destroy(aead);
                    385:        return TRUE;
                    386: }
                    387: 
                    388: static bool do_crypt(crypter_t *crypter, test_vector_t *test)
                    389: {
                    390:        if (ctx.decrypt)
                    391:        {
                    392:                if (!crypter->decrypt(crypter, test->cipher, test->iv, &test->plain))
                    393:                {
                    394:                        DBG1(DBG_APP, "decryption failed");
                    395:                        return FALSE;
                    396:                }
                    397:        }
                    398:        else
                    399:        {
                    400:                if (!crypter->encrypt(crypter, test->plain, test->iv, &test->cipher))
                    401:                {
                    402:                        DBG1(DBG_APP, "encryption failed");
                    403:                        return FALSE;
                    404:                }
                    405:        }
                    406:        return TRUE;
                    407: }
                    408: 
                    409: static bool do_test_cbc(test_vector_t *test)
                    410: {
                    411:        crypter_t *crypter;
                    412: 
                    413:        crypter = lib->crypto->create_crypter(lib->crypto, ENCR_AES_CBC,
                    414:                                                                                  test->key.len);
                    415:        if (!crypter)
                    416:        {
                    417:                DBG1(DBG_APP, "algorithm %N or key length (%d bits) not supported",
                    418:                         encryption_algorithm_names, ENCR_AES_CBC, test->key.len * 8);
                    419:                return FALSE;
                    420:        }
                    421:        if (!crypter->set_key(crypter, test->key))
                    422:        {
                    423:                DBG1(DBG_APP, "failed to set key");
                    424:                crypter->destroy(crypter);
                    425:                return FALSE;
                    426:        }
                    427:        if (!do_crypt(crypter, test))
                    428:        {
                    429:                crypter->destroy(crypter);
                    430:                return FALSE;
                    431:        }
                    432:        crypter->destroy(crypter);
                    433:        return TRUE;
                    434: }
                    435: 
                    436: static bool do_test_mct(test_vector_t *test)
                    437: {
                    438:        crypter_t *crypter;
                    439:        chunk_t prev, *input, *output;
                    440:        int i, j;
                    441: 
                    442:        crypter = lib->crypto->create_crypter(lib->crypto, ENCR_AES_CBC,
                    443:                                                                                  test->key.len);
                    444:        if (!crypter)
                    445:        {
                    446:                DBG1(DBG_APP, "algorithm %N or key length (%d bits) not supported",
                    447:                         encryption_algorithm_names, ENCR_AES_CBC, test->key.len * 8);
                    448:                return FALSE;
                    449:        }
                    450:        input = ctx.decrypt ? &test->cipher : &test->plain;
                    451:        output = ctx.decrypt ? &test->plain : &test->cipher;
                    452:        if (crypter->get_block_size(crypter) != input->len)
                    453:        {
                    454:                DBG1(DBG_APP, "MCT only works for input with a length of one block");
                    455:                crypter->destroy(crypter);
                    456:                return FALSE;
                    457:        }
                    458:        prev = chunk_alloca(input->len);
                    459:        /* assume initial IV as previous output */
                    460:        *output = chunk_clone(test->iv);
                    461:        for (i = 0; i < 100; i++)
                    462:        {
                    463:                if (i > 0)
                    464:                {       /* we copied the original lines already */
                    465:                        fprintf(ctx.out, "COUNT = %d\n", i);
                    466:                        fprintf(ctx.out, "KEY = %+B\n", &test->key);
                    467:                        fprintf(ctx.out, "IV = %+B\n", &test->iv);
                    468:                        fprintf(ctx.out, "%s = %+B\n",
                    469:                                        ctx.decrypt ? "CIPHERTEXT" : "PLAINTEXT", input);
                    470:                }
                    471:                if (!crypter->set_key(crypter, test->key))
                    472:                {
                    473:                        DBG1(DBG_APP, "failed to set key");
                    474:                        return FALSE;
                    475:                }
                    476:                for (j = 0; j < 1000; j++)
                    477:                {
                    478:                        /* store previous output as it is used as input after next */
                    479:                        memcpy(prev.ptr, output->ptr, prev.len);
                    480:                        chunk_free(output);
                    481:                        if (!do_crypt(crypter, test))
                    482:                        {
                    483:                                crypter->destroy(crypter);
                    484:                                return FALSE;
                    485:                        }
                    486:                        /* prepare the next IV (our API does not allow incremental calls) */
                    487:                        if (ctx.decrypt)
                    488:                        {
                    489:                                memcpy(test->iv.ptr, input->ptr, test->iv.len);
                    490:                        }
                    491:                        else
                    492:                        {
                    493:                                memcpy(test->iv.ptr, output->ptr, test->iv.len);
                    494:                        }
                    495:                        /* the previous output is the next input */
                    496:                        memcpy(input->ptr, prev.ptr, input->len);
                    497:                }
                    498:                fprintf(ctx.out, "%s = %+B\n\n",
                    499:                                ctx.decrypt ? "PLAINTEXT" : "CIPHERTEXT", output);
                    500:                /* derive key for next round */
                    501:                switch (test->key.len)
                    502:                {
                    503:                        case 16:
                    504:                                memxor(test->key.ptr, output->ptr, output->len);
                    505:                                break;
                    506:                        case 24:
                    507:                                memxor(test->key.ptr, prev.ptr + 8, 8);
                    508:                                memxor(test->key.ptr + 8, output->ptr, output->len);
                    509:                                break;
                    510:                        case 32:
                    511:                                memxor(test->key.ptr, prev.ptr, prev.len);
                    512:                                memxor(test->key.ptr + prev.len, output->ptr, output->len);
                    513:                                break;
                    514:                }
                    515:                /* the current output is used as IV for the next round */
                    516:                memcpy(test->iv.ptr, output->ptr, test->iv.len);
                    517:        }
                    518:        crypter->destroy(crypter);
                    519:        /* we return FALSE as we print the output ourselves */
                    520:        return FALSE;
                    521: }
                    522: 
                    523: static bool do_test(test_vector_t *test)
                    524: {
                    525:        if (ctx.use_gcm)
                    526:        {
                    527:                return do_test_gcm(test);
                    528:        }
                    529:        if (ctx.use_mct)
                    530:        {
                    531:                return do_test_mct(test);
                    532:        }
                    533:        return do_test_cbc(test);
                    534: }
                    535: 
                    536: static void usage(FILE *out, char *name)
                    537: {
                    538:        fprintf(out, "Test AES implementation according to the AES Algorithm Validation Suite (AESAVS)\n");
                    539:        fprintf(out, "and the GCM Validation System (GCMVS)\n\n");
                    540:        fprintf(out, "%s [OPTIONS]\n\n", name);
                    541:        fprintf(out, "Options:\n");
                    542:        fprintf(out, "  -h, --help          print this help.\n");
                    543:        fprintf(out, "  -d, --debug=LEVEL   set debug level (default 1).\n");
                    544:        fprintf(out, "  -m, --mode=MODE     mode to test, either CBC or GCM (default CBC).\n");
                    545:        fprintf(out, "  -t, --mct           run Monte Carlo Test (MCT), only for CBC.\n");
                    546:        fprintf(out, "  -x, --decrypt       test decryption (not needed for CBC as files contain control directives).\n");
                    547:        fprintf(out, "  -i, --in=FILE       request file (default STDIN).\n");
                    548:        fprintf(out, "  -o, --out=FILE      response file (default STDOUT).\n");
                    549:        fprintf(out, "\n");
                    550: }
                    551: 
                    552: int main(int argc, char *argv[])
                    553: {
                    554:        test_vector_t test;
                    555: 
                    556:        ctx.in = stdin;
                    557:        ctx.out = stdout;
                    558: 
                    559:        library_init(NULL, "aes-test");
                    560:        atexit(library_deinit);
                    561: 
                    562:        while (true)
                    563:        {
                    564:                struct option long_opts[] = {
                    565:                        {"help",                no_argument,            NULL,   'h' },
                    566:                        {"debug",               required_argument,      NULL,   'd' },
                    567:                        {"mode",                required_argument,      NULL,   'm' },
                    568:                        {"mct",                 no_argument,            NULL,   't' },
                    569:                        {"decrypt",             no_argument,            NULL,   'x' },
                    570:                        {"in",                  required_argument,      NULL,   'i' },
                    571:                        {"out",                 required_argument,      NULL,   'o' },
                    572:                        {0,0,0,0 },
                    573:                };
                    574:                switch (getopt_long(argc, argv, "hd:m:txi:o:", long_opts, NULL))
                    575:                {
                    576:                        case EOF:
                    577:                                break;
                    578:                        case 'h':
                    579:                                usage(stdout, argv[0]);
                    580:                                return 0;
                    581:                        case 'd':
                    582:                                dbg_default_set_level(atoi(optarg));
                    583:                                continue;
                    584:                        case 'm':
                    585:                                if (strcaseeq(optarg, "GCM"))
                    586:                                {
                    587:                                        ctx.use_gcm = TRUE;
                    588:                                }
                    589:                                else if (!strcaseeq(optarg, "CBC"))
                    590:                                {
                    591:                                        usage(stderr, argv[0]);
                    592:                                        return 1;
                    593:                                }
                    594:                                continue;
                    595:                        case 't':
                    596:                                ctx.use_mct = TRUE;
                    597:                                continue;
                    598:                        case 'x':
                    599:                                ctx.decrypt = TRUE;
                    600:                                continue;
                    601:                        case 'i':
                    602:                                ctx.in = fopen(optarg, "r");
                    603:                                if (!ctx.in)
                    604:                                {
                    605:                                        fprintf(stderr, "failed to open '%s': %s\n", optarg,
                    606:                                                        strerror(errno));
                    607:                                        usage(stderr, argv[0]);
                    608:                                        return 1;
                    609:                                }
                    610:                                continue;
                    611:                        case 'o':
                    612:                                ctx.out = fopen(optarg, "w");
                    613:                                if (!ctx.out)
                    614:                                {
                    615:                                        fprintf(stderr, "failed to open '%s': %s\n", optarg,
                    616:                                                        strerror(errno));
                    617:                                        usage(stderr, argv[0]);
                    618:                                        return 1;
                    619:                                }
                    620:                                continue;
                    621:                        default:
                    622:                                usage(stderr, argv[0]);
                    623:                                return 1;
                    624:                }
                    625:                break;
                    626:        }
                    627:        /* TODO: maybe make plugins configurable */
                    628:        lib->plugins->load(lib->plugins, PLUGINS);
                    629:        lib->plugins->status(lib->plugins, LEVEL_CTRL);
                    630: 
                    631:        while (get_next_test_vector(&test))
                    632:        {
                    633:                if (verify_test_vector(&test))
                    634:                {
                    635:                        if (do_test(&test))
                    636:                        {
                    637:                                print_result(&test);
                    638:                        }
                    639:                }
                    640:                else
                    641:                {
                    642:                        DBG1(DBG_APP, "test vector with missing data encountered");
                    643:                }
                    644:                fprintf(ctx.out, "\n");
                    645:                test_vector_free(&test);
                    646:        }
                    647: 
                    648:        if (ctx.in != stdin)
                    649:        {
                    650:                fclose(ctx.in);
                    651:        }
                    652:        if (ctx.out != stdout)
                    653:        {
                    654:                fclose(ctx.out);
                    655:        }
                    656:        return 0;
                    657: }

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