Annotation of embedaddon/strongswan/scripts/aes-test.c, revision 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>