tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

fipstest.c (309987B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <ctype.h>
      8 
      9 #include "secitem.h"
     10 #include "blapi.h"
     11 #include "nssutil.h"
     12 #include "secerr.h"
     13 #include "secder.h"
     14 #include "secdig.h"
     15 #include "secoid.h"
     16 #include "ec.h"
     17 #include "hasht.h"
     18 #include "lowkeyi.h"
     19 #include "softoken.h"
     20 #include "pkcs11t.h"
     21 #define __PASTE(x, y) x##y
     22 #undef CK_PKCS11_FUNCTION_INFO
     23 #undef CK_NEED_ARG_LIST
     24 #define CK_EXTERN extern
     25 #define CK_PKCS11_FUNCTION_INFO(func) \
     26    CK_RV __PASTE(NS, func)
     27 #define CK_NEED_ARG_LIST 1
     28 #include "pkcs11f.h"
     29 #undef CK_PKCS11_FUNCTION_INFO
     30 #undef CK_NEED_ARG_LIST
     31 #undef __PASTE
     32 #define SSL3_RANDOM_LENGTH 32
     33 
     34 #if 0
     35 #include "../../lib/freebl/mpi/mpi.h"
     36 #endif
     37 #define MATCH_OPENSSL 1
     38 /*#define MATCH_NIST 1 */
     39 #ifdef MATCH_NIST
     40 #define VERBOSE_REASON 1
     41 #endif
     42 
     43 extern SECStatus
     44 EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
     45 extern SECStatus
     46 EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
     47              const ECParams *srcParams);
     48 
     49 #define ENCRYPT 1
     50 #define DECRYPT 0
     51 #define BYTE unsigned char
     52 #define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001
     53 #define RSA_MAX_TEST_MODULUS_BITS 4096
     54 #define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS / 8
     55 #define RSA_MAX_TEST_EXPONENT_BYTES 8
     56 #define PQG_TEST_SEED_BYTES 20
     57 
     58 SECStatus
     59 hex_to_byteval(const char *c2, unsigned char *byteval)
     60 {
     61    int i;
     62    unsigned char offset;
     63    *byteval = 0;
     64    for (i = 0; i < 2; i++) {
     65        if (c2[i] >= '0' && c2[i] <= '9') {
     66            offset = c2[i] - '0';
     67            *byteval |= offset << 4 * (1 - i);
     68        } else if (c2[i] >= 'a' && c2[i] <= 'f') {
     69            offset = c2[i] - 'a';
     70            *byteval |= (offset + 10) << 4 * (1 - i);
     71        } else if (c2[i] >= 'A' && c2[i] <= 'F') {
     72            offset = c2[i] - 'A';
     73            *byteval |= (offset + 10) << 4 * (1 - i);
     74        } else {
     75            return SECFailure;
     76        }
     77    }
     78    return SECSuccess;
     79 }
     80 
     81 SECStatus
     82 byteval_to_hex(unsigned char byteval, char *c2, char a)
     83 {
     84    int i;
     85    unsigned char offset;
     86    for (i = 0; i < 2; i++) {
     87        offset = (byteval >> 4 * (1 - i)) & 0x0f;
     88        if (offset < 10) {
     89            c2[i] = '0' + offset;
     90        } else {
     91            c2[i] = a + offset - 10;
     92        }
     93    }
     94    return SECSuccess;
     95 }
     96 
     97 void
     98 to_hex_str(char *str, const unsigned char *buf, unsigned int len)
     99 {
    100    unsigned int i;
    101    for (i = 0; i < len; i++) {
    102        byteval_to_hex(buf[i], &str[2 * i], 'a');
    103    }
    104    str[2 * len] = '\0';
    105 }
    106 
    107 void
    108 to_hex_str_cap(char *str, const unsigned char *buf, unsigned int len)
    109 {
    110    unsigned int i;
    111    for (i = 0; i < len; i++) {
    112        byteval_to_hex(buf[i], &str[2 * i], 'A');
    113    }
    114    str[2 * len] = '\0';
    115 }
    116 
    117 /*
    118 * Convert a string of hex digits (str) to an array (buf) of len bytes.
    119 * Return PR_TRUE if the hex string can fit in the byte array.  Return
    120 * PR_FALSE if the hex string is empty or is too long.
    121 */
    122 PRBool
    123 from_hex_str(unsigned char *buf, unsigned int len, const char *str)
    124 {
    125    unsigned int nxdigit; /* number of hex digits in str */
    126    unsigned int i;       /* index into buf */
    127    unsigned int j;       /* index into str */
    128 
    129    /* count the hex digits */
    130    nxdigit = 0;
    131    for (nxdigit = 0; isxdigit((unsigned char)str[nxdigit]); nxdigit++) {
    132        /* empty body */
    133    }
    134    if (nxdigit == 0) {
    135        return PR_FALSE;
    136    }
    137    if (nxdigit > 2 * len) {
    138        /*
    139         * The input hex string is too long, but we allow it if the
    140         * extra digits are leading 0's.
    141         */
    142        for (j = 0; j < nxdigit - 2 * len; j++) {
    143            if (str[j] != '0') {
    144                return PR_FALSE;
    145            }
    146        }
    147        /* skip leading 0's */
    148        str += nxdigit - 2 * len;
    149        nxdigit = 2 * len;
    150    }
    151    for (i = 0, j = 0; i < len; i++) {
    152        if (2 * i < 2 * len - nxdigit) {
    153            /* Handle a short input as if we padded it with leading 0's. */
    154            if (2 * i + 1 < 2 * len - nxdigit) {
    155                buf[i] = 0;
    156            } else {
    157                char tmp[2];
    158                tmp[0] = '0';
    159                tmp[1] = str[j];
    160                hex_to_byteval(tmp, &buf[i]);
    161                j++;
    162            }
    163        } else {
    164            hex_to_byteval(&str[j], &buf[i]);
    165            j += 2;
    166        }
    167    }
    168    return PR_TRUE;
    169 }
    170 
    171 SECStatus
    172 tdea_encrypt_buf(
    173    int mode,
    174    const unsigned char *key,
    175    const unsigned char *iv,
    176    unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
    177    const unsigned char *input, unsigned int inputlen)
    178 {
    179    SECStatus rv = SECFailure;
    180    DESContext *cx;
    181    unsigned char doublecheck[8 * 20]; /* 1 to 20 blocks */
    182    unsigned int doublechecklen = 0;
    183 
    184    cx = DES_CreateContext(key, iv, mode, PR_TRUE);
    185    if (cx == NULL) {
    186        goto loser;
    187    }
    188    rv = DES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
    189    if (rv != SECSuccess) {
    190        goto loser;
    191    }
    192    if (*outputlen != inputlen) {
    193        goto loser;
    194    }
    195    DES_DestroyContext(cx, PR_TRUE);
    196    cx = NULL;
    197 
    198    /*
    199     * Doublecheck our result by decrypting the ciphertext and
    200     * compare the output with the input plaintext.
    201     */
    202    cx = DES_CreateContext(key, iv, mode, PR_FALSE);
    203    if (cx == NULL) {
    204        goto loser;
    205    }
    206    rv = DES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
    207                     output, *outputlen);
    208    if (rv != SECSuccess) {
    209        goto loser;
    210    }
    211    if (doublechecklen != *outputlen) {
    212        goto loser;
    213    }
    214    DES_DestroyContext(cx, PR_TRUE);
    215    cx = NULL;
    216    if (memcmp(doublecheck, input, inputlen) != 0) {
    217        goto loser;
    218    }
    219    rv = SECSuccess;
    220 
    221 loser:
    222    if (cx != NULL) {
    223        DES_DestroyContext(cx, PR_TRUE);
    224    }
    225    return rv;
    226 }
    227 
    228 SECStatus
    229 tdea_decrypt_buf(
    230    int mode,
    231    const unsigned char *key,
    232    const unsigned char *iv,
    233    unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
    234    const unsigned char *input, unsigned int inputlen)
    235 {
    236    SECStatus rv = SECFailure;
    237    DESContext *cx;
    238    unsigned char doublecheck[8 * 20]; /* 1 to 20 blocks */
    239    unsigned int doublechecklen = 0;
    240 
    241    cx = DES_CreateContext(key, iv, mode, PR_FALSE);
    242    if (cx == NULL) {
    243        goto loser;
    244    }
    245    rv = DES_Decrypt(cx, output, outputlen, maxoutputlen,
    246                     input, inputlen);
    247    if (rv != SECSuccess) {
    248        goto loser;
    249    }
    250    if (*outputlen != inputlen) {
    251        goto loser;
    252    }
    253    DES_DestroyContext(cx, PR_TRUE);
    254    cx = NULL;
    255 
    256    /*
    257     * Doublecheck our result by encrypting the plaintext and
    258     * compare the output with the input ciphertext.
    259     */
    260    cx = DES_CreateContext(key, iv, mode, PR_TRUE);
    261    if (cx == NULL) {
    262        goto loser;
    263    }
    264    rv = DES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
    265                     output, *outputlen);
    266    if (rv != SECSuccess) {
    267        goto loser;
    268    }
    269    if (doublechecklen != *outputlen) {
    270        goto loser;
    271    }
    272    DES_DestroyContext(cx, PR_TRUE);
    273    cx = NULL;
    274    if (memcmp(doublecheck, input, inputlen) != 0) {
    275        goto loser;
    276    }
    277    rv = SECSuccess;
    278 
    279 loser:
    280    if (cx != NULL) {
    281        DES_DestroyContext(cx, PR_TRUE);
    282    }
    283    return rv;
    284 }
    285 
    286 /*
    287 * Perform the TDEA Known Answer Test (KAT) or Multi-block Message
    288 * Test (MMT) in ECB or CBC mode.  The KAT (there are five types)
    289 * and MMT have the same structure: given the key and IV (CBC mode
    290 * only), encrypt the given plaintext or decrypt the given ciphertext.
    291 * So we can handle them the same way.
    292 *
    293 * reqfn is the pathname of the REQUEST file.
    294 *
    295 * The output RESPONSE file is written to stdout.
    296 */
    297 void
    298 tdea_kat_mmt(char *reqfn)
    299 {
    300    char buf[180]; /* holds one line from the input REQUEST file.
    301                    * needs to be large enough to hold the longest
    302                    * line "CIPHERTEXT = <180 hex digits>\n".
    303                    */
    304    FILE *req;     /* input stream from the REQUEST file */
    305    FILE *resp;    /* output stream to the RESPONSE file */
    306    int i, j;
    307    int mode = NSS_DES_EDE3; /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */
    308    int crypt = DECRYPT;     /* 1 means encrypt, 0 means decrypt */
    309    unsigned char key[24];   /* TDEA 3 key bundle */
    310    unsigned int numKeys = 0;
    311    unsigned char iv[8];             /* for all modes except ECB */
    312    unsigned char plaintext[8 * 20]; /* 1 to 20 blocks */
    313    unsigned int plaintextlen;
    314    unsigned char ciphertext[8 * 20]; /* 1 to 20 blocks */
    315    unsigned int ciphertextlen;
    316    SECStatus rv;
    317 
    318    req = fopen(reqfn, "r");
    319    resp = stdout;
    320    while (fgets(buf, sizeof buf, req) != NULL) {
    321        /* a comment or blank line */
    322        if (buf[0] == '#' || buf[0] == '\n') {
    323            fputs(buf, resp);
    324            continue;
    325        }
    326        /* [ENCRYPT] or [DECRYPT] */
    327        if (buf[0] == '[') {
    328            if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
    329                crypt = ENCRYPT;
    330            } else {
    331                crypt = DECRYPT;
    332            }
    333            fputs(buf, resp);
    334            continue;
    335        }
    336        /* NumKeys */
    337        if (strncmp(&buf[0], "NumKeys", 7) == 0) {
    338            i = 7;
    339            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
    340                i++;
    341            }
    342            numKeys = buf[i];
    343            fputs(buf, resp);
    344            continue;
    345        }
    346        /* "COUNT = x" begins a new data set */
    347        if (strncmp(buf, "COUNT", 5) == 0) {
    348            /* mode defaults to ECB, if dataset has IV mode will be set CBC */
    349            mode = NSS_DES_EDE3;
    350            /* zeroize the variables for the test with this data set */
    351            memset(key, 0, sizeof key);
    352            memset(iv, 0, sizeof iv);
    353            memset(plaintext, 0, sizeof plaintext);
    354            plaintextlen = 0;
    355            memset(ciphertext, 0, sizeof ciphertext);
    356            ciphertextlen = 0;
    357            fputs(buf, resp);
    358            continue;
    359        }
    360        if (numKeys == 0) {
    361            if (strncmp(buf, "KEYs", 4) == 0) {
    362                i = 4;
    363                while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
    364                    i++;
    365                }
    366                for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
    367                    hex_to_byteval(&buf[i], &key[j]);
    368                    key[j + 8] = key[j];
    369                    key[j + 16] = key[j];
    370                }
    371                fputs(buf, resp);
    372                continue;
    373            }
    374        } else {
    375            /* KEY1 = ... */
    376            if (strncmp(buf, "KEY1", 4) == 0) {
    377                i = 4;
    378                while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
    379                    i++;
    380                }
    381                for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
    382                    hex_to_byteval(&buf[i], &key[j]);
    383                }
    384                fputs(buf, resp);
    385                continue;
    386            }
    387            /* KEY2 = ... */
    388            if (strncmp(buf, "KEY2", 4) == 0) {
    389                i = 4;
    390                while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
    391                    i++;
    392                }
    393                for (j = 8; isxdigit((unsigned char)buf[i]); i += 2, j++) {
    394                    hex_to_byteval(&buf[i], &key[j]);
    395                }
    396                fputs(buf, resp);
    397                continue;
    398            }
    399            /* KEY3 = ... */
    400            if (strncmp(buf, "KEY3", 4) == 0) {
    401                i = 4;
    402                while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
    403                    i++;
    404                }
    405                for (j = 16; isxdigit((unsigned char)buf[i]); i += 2, j++) {
    406                    hex_to_byteval(&buf[i], &key[j]);
    407                }
    408                fputs(buf, resp);
    409                continue;
    410            }
    411        }
    412 
    413        /* IV = ... */
    414        if (strncmp(buf, "IV", 2) == 0) {
    415            mode = NSS_DES_EDE3_CBC;
    416            i = 2;
    417            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
    418                i++;
    419            }
    420            for (j = 0; j < sizeof iv; i += 2, j++) {
    421                hex_to_byteval(&buf[i], &iv[j]);
    422            }
    423            fputs(buf, resp);
    424            continue;
    425        }
    426 
    427        /* PLAINTEXT = ... */
    428        if (strncmp(buf, "PLAINTEXT", 9) == 0) {
    429            /* sanity check */
    430            if (crypt != ENCRYPT) {
    431                goto loser;
    432            }
    433            i = 9;
    434            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
    435                i++;
    436            }
    437            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
    438                hex_to_byteval(&buf[i], &plaintext[j]);
    439            }
    440            plaintextlen = j;
    441            rv = tdea_encrypt_buf(mode, key,
    442                                  (mode == NSS_DES_EDE3) ? NULL : iv,
    443                                  ciphertext, &ciphertextlen, sizeof ciphertext,
    444                                  plaintext, plaintextlen);
    445            if (rv != SECSuccess) {
    446                goto loser;
    447            }
    448 
    449            fputs(buf, resp);
    450            fputs("CIPHERTEXT = ", resp);
    451            to_hex_str(buf, ciphertext, ciphertextlen);
    452            fputs(buf, resp);
    453            fputc('\n', resp);
    454            continue;
    455        }
    456        /* CIPHERTEXT = ... */
    457        if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
    458            /* sanity check */
    459            if (crypt != DECRYPT) {
    460                goto loser;
    461            }
    462 
    463            i = 10;
    464            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
    465                i++;
    466            }
    467            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
    468                hex_to_byteval(&buf[i], &ciphertext[j]);
    469            }
    470            ciphertextlen = j;
    471 
    472            rv = tdea_decrypt_buf(mode, key,
    473                                  (mode == NSS_DES_EDE3) ? NULL : iv,
    474                                  plaintext, &plaintextlen, sizeof plaintext,
    475                                  ciphertext, ciphertextlen);
    476            if (rv != SECSuccess) {
    477                goto loser;
    478            }
    479 
    480            fputs(buf, resp);
    481            fputs("PLAINTEXT = ", resp);
    482            to_hex_str(buf, plaintext, plaintextlen);
    483            fputs(buf, resp);
    484            fputc('\n', resp);
    485            continue;
    486        }
    487    }
    488 
    489 loser:
    490    fclose(req);
    491 }
    492 
    493 /*
    494 * Set the parity bit for the given byte
    495 */
    496 BYTE
    497 odd_parity(BYTE in)
    498 {
    499    BYTE out = in;
    500    in ^= in >> 4;
    501    in ^= in >> 2;
    502    in ^= in >> 1;
    503    return (BYTE)(out ^ !(in & 1));
    504 }
    505 
    506 /*
    507 * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j]
    508 * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes.
    509 */
    510 void
    511 tdea_mct_next_keys(unsigned char *key,
    512                   const unsigned char *text_2, const unsigned char *text_1,
    513                   const unsigned char *text, unsigned int numKeys)
    514 {
    515    int k;
    516 
    517    /* key1[i+1] = key1[i] xor PT/CT[j] */
    518    for (k = 0; k < 8; k++) {
    519        key[k] ^= text[k];
    520    }
    521    /* key2 */
    522    if (numKeys == 2 || numKeys == 3) {
    523        /* key2 independent */
    524        for (k = 8; k < 16; k++) {
    525            /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */
    526            key[k] ^= text_1[k - 8];
    527        }
    528    } else {
    529        /* key2 == key 1 */
    530        for (k = 8; k < 16; k++) {
    531            /* key2[i+1] = KEY2[i] xor PT/CT[j] */
    532            key[k] = key[k - 8];
    533        }
    534    }
    535    /* key3 */
    536    if (numKeys == 1 || numKeys == 2) {
    537        /* key3 == key 1 */
    538        for (k = 16; k < 24; k++) {
    539            /* key3[i+1] = KEY3[i] xor PT/CT[j] */
    540            key[k] = key[k - 16];
    541        }
    542    } else {
    543        /* key3 independent */
    544        for (k = 16; k < 24; k++) {
    545            /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */
    546            key[k] ^= text_2[k - 16];
    547        }
    548    }
    549    /* set the parity bits */
    550    for (k = 0; k < 24; k++) {
    551        key[k] = odd_parity(key[k]);
    552    }
    553 }
    554 
    555 /*
    556 * Perform the Monte Carlo Test
    557 *
    558 * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC
    559 * crypt = ENCRYPT || DECRYPT
    560 * inputtext = plaintext or Cyphertext depending on the value of crypt
    561 * inputlength is expected to be size 8 bytes
    562 * iv = needs to be set for NSS_DES_EDE3_CBC mode
    563 * resp = is the output response file.
    564 */
    565 void
    566 tdea_mct_test(int mode, unsigned char *key, unsigned int numKeys,
    567              unsigned int crypt, unsigned char *inputtext,
    568              unsigned int inputlength, unsigned char *iv, FILE *resp)
    569 {
    570 
    571    int i, j;
    572    unsigned char outputtext_1[8]; /* PT/CT[j-1] */
    573    unsigned char outputtext_2[8]; /* PT/CT[j-2] */
    574    char buf[80];                  /* holds one line from the input REQUEST file. */
    575    unsigned int outputlen;
    576    unsigned char outputtext[8];
    577 
    578    SECStatus rv;
    579 
    580    if (mode == NSS_DES_EDE3 && iv != NULL) {
    581        printf("IV must be NULL for NSS_DES_EDE3 mode");
    582        goto loser;
    583    } else if (mode == NSS_DES_EDE3_CBC && iv == NULL) {
    584        printf("IV must not be NULL for NSS_DES_EDE3_CBC mode");
    585        goto loser;
    586    }
    587 
    588    /* loop 400 times */
    589    for (i = 0; i < 400; i++) {
    590        /* if i == 0 CV[0] = IV  not necessary */
    591        /* record the count and key values and plainText */
    592        snprintf(buf, sizeof(buf), "COUNT = %d\n", i);
    593        fputs(buf, resp);
    594        /* Output KEY1[i] */
    595        fputs("KEY1 = ", resp);
    596        to_hex_str(buf, key, 8);
    597        fputs(buf, resp);
    598        fputc('\n', resp);
    599        /* Output KEY2[i] */
    600        fputs("KEY2 = ", resp);
    601        to_hex_str(buf, &key[8], 8);
    602        fputs(buf, resp);
    603        fputc('\n', resp);
    604        /* Output KEY3[i] */
    605        fputs("KEY3 = ", resp);
    606        to_hex_str(buf, &key[16], 8);
    607        fputs(buf, resp);
    608        fputc('\n', resp);
    609        if (mode == NSS_DES_EDE3_CBC) {
    610            /* Output CV[i] */
    611            fputs("IV = ", resp);
    612            to_hex_str(buf, iv, 8);
    613            fputs(buf, resp);
    614            fputc('\n', resp);
    615        }
    616        if (crypt == ENCRYPT) {
    617            /* Output PT[0] */
    618            fputs("PLAINTEXT = ", resp);
    619        } else {
    620            /* Output CT[0] */
    621            fputs("CIPHERTEXT = ", resp);
    622        }
    623 
    624        to_hex_str(buf, inputtext, inputlength);
    625        fputs(buf, resp);
    626        fputc('\n', resp);
    627 
    628        /* loop 10,000 times */
    629        for (j = 0; j < 10000; j++) {
    630 
    631            outputlen = 0;
    632            if (crypt == ENCRYPT) {
    633                /* inputtext == ciphertext outputtext == plaintext*/
    634                rv = tdea_encrypt_buf(mode, key,
    635                                      (mode ==
    636                                       NSS_DES_EDE3)
    637                                          ? NULL
    638                                          : iv,
    639                                      outputtext, &outputlen, 8,
    640                                      inputtext, 8);
    641            } else {
    642                /* inputtext == plaintext outputtext == ciphertext */
    643                rv = tdea_decrypt_buf(mode, key,
    644                                      (mode ==
    645                                       NSS_DES_EDE3)
    646                                          ? NULL
    647                                          : iv,
    648                                      outputtext, &outputlen, 8,
    649                                      inputtext, 8);
    650            }
    651 
    652            if (rv != SECSuccess) {
    653                goto loser;
    654            }
    655            if (outputlen != inputlength) {
    656                goto loser;
    657            }
    658 
    659            if (mode == NSS_DES_EDE3_CBC) {
    660                if (crypt == ENCRYPT) {
    661                    if (j == 0) {
    662                        /*P[j+1] = CV[0] */
    663                        memcpy(inputtext, iv, 8);
    664                    } else {
    665                        /* p[j+1] = C[j-1] */
    666                        memcpy(inputtext, outputtext_1, 8);
    667                    }
    668                    /* CV[j+1] = C[j] */
    669                    memcpy(iv, outputtext, 8);
    670                    if (j != 9999) {
    671                        /* save C[j-1] */
    672                        memcpy(outputtext_1, outputtext, 8);
    673                    }
    674                } else { /* DECRYPT */
    675                    /* CV[j+1] = C[j] */
    676                    memcpy(iv, inputtext, 8);
    677                    /* C[j+1] = P[j] */
    678                    memcpy(inputtext, outputtext, 8);
    679                }
    680            } else {
    681                /* ECB mode PT/CT[j+1] = CT/PT[j] */
    682                memcpy(inputtext, outputtext, 8);
    683            }
    684 
    685            /* Save PT/CT[j-2] and PT/CT[j-1] */
    686            if (j == 9997)
    687                memcpy(outputtext_2, outputtext, 8);
    688            if (j == 9998)
    689                memcpy(outputtext_1, outputtext, 8);
    690            /* done at the end of the for(j) loop */
    691        }
    692 
    693        if (crypt == ENCRYPT) {
    694            /* Output CT[j] */
    695            fputs("CIPHERTEXT = ", resp);
    696        } else {
    697            /* Output PT[j] */
    698            fputs("PLAINTEXT = ", resp);
    699        }
    700        to_hex_str(buf, outputtext, 8);
    701        fputs(buf, resp);
    702        fputc('\n', resp);
    703 
    704        /* Key[i+1] = Key[i] xor ...  outputtext_2 == PT/CT[j-2]
    705         *  outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j]
    706         */
    707        tdea_mct_next_keys(key, outputtext_2,
    708                           outputtext_1, outputtext, numKeys);
    709 
    710        if (mode == NSS_DES_EDE3_CBC) {
    711            /* taken care of in the j=9999 iteration */
    712            if (crypt == ENCRYPT) {
    713                /* P[i] = C[j-1] */
    714                /* CV[i] = C[j] */
    715            } else {
    716                /* taken care of in the j=9999 iteration */
    717                /* CV[i] = C[j] */
    718                /* C[i] = P[j]  */
    719            }
    720        } else {
    721            /* ECB PT/CT[i] = PT/CT[j]  */
    722            memcpy(inputtext, outputtext, 8);
    723        }
    724        /* done at the end of the for(i) loop */
    725        fputc('\n', resp);
    726    }
    727 
    728 loser:
    729    return;
    730 }
    731 
    732 /*
    733 * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes.
    734 * by gathering the input from the request file, and then
    735 * calling tdea_mct_test.
    736 *
    737 * reqfn is the pathname of the input REQUEST file.
    738 *
    739 * The output RESPONSE file is written to stdout.
    740 */
    741 void
    742 tdea_mct(int mode, char *reqfn)
    743 {
    744    int i, j;
    745    char buf[80];           /* holds one line from the input REQUEST file. */
    746    FILE *req;              /* input stream from the REQUEST file */
    747    FILE *resp;             /* output stream to the RESPONSE file */
    748    unsigned int crypt = 0; /* 1 means encrypt, 0 means decrypt */
    749    unsigned char key[24];  /* TDEA 3 key bundle */
    750    unsigned int numKeys = 0;
    751    unsigned char plaintext[8];  /* PT[j] */
    752    unsigned char ciphertext[8]; /* CT[j] */
    753    unsigned char iv[8];
    754 
    755    /* zeroize the variables for the test with this data set */
    756    memset(key, 0, sizeof key);
    757    memset(plaintext, 0, sizeof plaintext);
    758    memset(ciphertext, 0, sizeof ciphertext);
    759    memset(iv, 0, sizeof iv);
    760 
    761    req = fopen(reqfn, "r");
    762    resp = stdout;
    763    while (fgets(buf, sizeof buf, req) != NULL) {
    764        /* a comment or blank line */
    765        if (buf[0] == '#' || buf[0] == '\n') {
    766            fputs(buf, resp);
    767            continue;
    768        }
    769        /* [ENCRYPT] or [DECRYPT] */
    770        if (buf[0] == '[') {
    771            if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
    772                crypt = ENCRYPT;
    773            } else {
    774                crypt = DECRYPT;
    775            }
    776            fputs(buf, resp);
    777            continue;
    778        }
    779        /* NumKeys */
    780        if (strncmp(&buf[0], "NumKeys", 7) == 0) {
    781            i = 7;
    782            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
    783                i++;
    784            }
    785            numKeys = atoi(&buf[i]);
    786            continue;
    787        }
    788        /* KEY1 = ... */
    789        if (strncmp(buf, "KEY1", 4) == 0) {
    790            i = 4;
    791            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
    792                i++;
    793            }
    794            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
    795                hex_to_byteval(&buf[i], &key[j]);
    796            }
    797            continue;
    798        }
    799        /* KEY2 = ... */
    800        if (strncmp(buf, "KEY2", 4) == 0) {
    801            i = 4;
    802            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
    803                i++;
    804            }
    805            for (j = 8; isxdigit((unsigned char)buf[i]); i += 2, j++) {
    806                hex_to_byteval(&buf[i], &key[j]);
    807            }
    808            continue;
    809        }
    810        /* KEY3 = ... */
    811        if (strncmp(buf, "KEY3", 4) == 0) {
    812            i = 4;
    813            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
    814                i++;
    815            }
    816            for (j = 16; isxdigit((unsigned char)buf[i]); i += 2, j++) {
    817                hex_to_byteval(&buf[i], &key[j]);
    818            }
    819            continue;
    820        }
    821 
    822        /* IV = ... */
    823        if (strncmp(buf, "IV", 2) == 0) {
    824            i = 2;
    825            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
    826                i++;
    827            }
    828            for (j = 0; j < sizeof iv; i += 2, j++) {
    829                hex_to_byteval(&buf[i], &iv[j]);
    830            }
    831            continue;
    832        }
    833 
    834        /* PLAINTEXT = ... */
    835        if (strncmp(buf, "PLAINTEXT", 9) == 0) {
    836 
    837            /* sanity check */
    838            if (crypt != ENCRYPT) {
    839                goto loser;
    840            }
    841            /* PT[0] = PT */
    842            i = 9;
    843            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
    844                i++;
    845            }
    846            for (j = 0; j < sizeof plaintext; i += 2, j++) {
    847                hex_to_byteval(&buf[i], &plaintext[j]);
    848            }
    849 
    850            /* do the Monte Carlo test */
    851            if (mode == NSS_DES_EDE3) {
    852                tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, plaintext, sizeof plaintext, NULL, resp);
    853            } else {
    854                tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, plaintext, sizeof plaintext, iv, resp);
    855            }
    856            continue;
    857        }
    858        /* CIPHERTEXT = ... */
    859        if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
    860            /* sanity check */
    861            if (crypt != DECRYPT) {
    862                goto loser;
    863            }
    864            /* CT[0] = CT */
    865            i = 10;
    866            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
    867                i++;
    868            }
    869            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
    870                hex_to_byteval(&buf[i], &ciphertext[j]);
    871            }
    872 
    873            /* do the Monte Carlo test */
    874            if (mode == NSS_DES_EDE3) {
    875                tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, ciphertext, sizeof ciphertext, NULL, resp);
    876            } else {
    877                tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, ciphertext, sizeof ciphertext, iv, resp);
    878            }
    879            continue;
    880        }
    881    }
    882 
    883 loser:
    884    fclose(req);
    885 }
    886 
    887 SECStatus
    888 aes_encrypt_buf(
    889    int mode,
    890    const unsigned char *key, unsigned int keysize,
    891    const unsigned char *iv,
    892    unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
    893    const unsigned char *input, unsigned int inputlen)
    894 {
    895    SECStatus rv = SECFailure;
    896    AESContext *cx;
    897    unsigned char doublecheck[10 * 16]; /* 1 to 10 blocks */
    898    unsigned int doublechecklen = 0;
    899 
    900    cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
    901    if (cx == NULL) {
    902        goto loser;
    903    }
    904    rv = AES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
    905    if (rv != SECSuccess) {
    906        goto loser;
    907    }
    908    if (*outputlen != inputlen) {
    909        goto loser;
    910    }
    911    AES_DestroyContext(cx, PR_TRUE);
    912    cx = NULL;
    913 
    914    /*
    915     * Doublecheck our result by decrypting the ciphertext and
    916     * compare the output with the input plaintext.
    917     */
    918    cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
    919    if (cx == NULL) {
    920        goto loser;
    921    }
    922    rv = AES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
    923                     output, *outputlen);
    924    if (rv != SECSuccess) {
    925        goto loser;
    926    }
    927    if (doublechecklen != *outputlen) {
    928        goto loser;
    929    }
    930    AES_DestroyContext(cx, PR_TRUE);
    931    cx = NULL;
    932    if (memcmp(doublecheck, input, inputlen) != 0) {
    933        goto loser;
    934    }
    935    rv = SECSuccess;
    936 
    937 loser:
    938    if (cx != NULL) {
    939        AES_DestroyContext(cx, PR_TRUE);
    940    }
    941    return rv;
    942 }
    943 
    944 SECStatus
    945 aes_decrypt_buf(
    946    int mode,
    947    const unsigned char *key, unsigned int keysize,
    948    const unsigned char *iv,
    949    unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
    950    const unsigned char *input, unsigned int inputlen)
    951 {
    952    SECStatus rv = SECFailure;
    953    AESContext *cx;
    954    unsigned char doublecheck[10 * 16]; /* 1 to 10 blocks */
    955    unsigned int doublechecklen = 0;
    956 
    957    cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
    958    if (cx == NULL) {
    959        goto loser;
    960    }
    961    rv = AES_Decrypt(cx, output, outputlen, maxoutputlen,
    962                     input, inputlen);
    963    if (rv != SECSuccess) {
    964        goto loser;
    965    }
    966    if (*outputlen != inputlen) {
    967        goto loser;
    968    }
    969    AES_DestroyContext(cx, PR_TRUE);
    970    cx = NULL;
    971 
    972    /*
    973     * Doublecheck our result by encrypting the plaintext and
    974     * compare the output with the input ciphertext.
    975     */
    976    cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
    977    if (cx == NULL) {
    978        goto loser;
    979    }
    980    rv = AES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
    981                     output, *outputlen);
    982    if (rv != SECSuccess) {
    983        goto loser;
    984    }
    985    if (doublechecklen != *outputlen) {
    986        goto loser;
    987    }
    988    AES_DestroyContext(cx, PR_TRUE);
    989    cx = NULL;
    990    if (memcmp(doublecheck, input, inputlen) != 0) {
    991        goto loser;
    992    }
    993    rv = SECSuccess;
    994 
    995 loser:
    996    if (cx != NULL) {
    997        AES_DestroyContext(cx, PR_TRUE);
    998    }
    999    return rv;
   1000 }
   1001 /*
   1002 * Perform the AES GCM tests.
   1003 *
   1004 * reqfn is the pathname of the REQUEST file.
   1005 *
   1006 * The output RESPONSE file is written to stdout.
   1007 */
   1008 void
   1009 aes_gcm(char *reqfn, int encrypt)
   1010 {
   1011    char buf[512]; /* holds one line from the input REQUEST file.
   1012                    * needs to be large enough to hold the longest
   1013                    * line "CIPHERTEXT = <320 hex digits>\n".
   1014                    */
   1015    FILE *aesreq;  /* input stream from the REQUEST file */
   1016    FILE *aesresp; /* output stream to the RESPONSE file */
   1017    int i, j;
   1018    unsigned char key[32]; /* 128, 192, or 256 bits */
   1019    unsigned int keysize = 0;
   1020    unsigned char iv[128];            /* handle large gcm IV's */
   1021    unsigned char plaintext[10 * 16]; /* 1 to 10 blocks */
   1022    unsigned int plaintextlen;
   1023    unsigned char ciphertext[11 * 16]; /* 1 to 10 blocks + tag */
   1024    unsigned int ciphertextlen;
   1025    unsigned char aad[11 * 16]; /* 1 to 10 blocks + tag */
   1026    unsigned int aadlen = 0;
   1027    unsigned int tagbits;
   1028    unsigned int taglen = 0;
   1029    unsigned int ivlen;
   1030    CK_NSS_GCM_PARAMS params;
   1031    SECStatus rv;
   1032 
   1033    aesreq = fopen(reqfn, "r");
   1034    aesresp = stdout;
   1035    while (fgets(buf, sizeof buf, aesreq) != NULL) {
   1036        /* a comment or blank line */
   1037        if (buf[0] == '#' || buf[0] == '\n') {
   1038            fputs(buf, aesresp);
   1039            continue;
   1040        }
   1041        /* [ENCRYPT] or [DECRYPT] */
   1042        if (buf[0] == '[') {
   1043            if (strncmp(buf, "[Taglen", 7) == 0) {
   1044                if (sscanf(buf, "[Taglen = %d]", &tagbits) != 1) {
   1045                    goto loser;
   1046                }
   1047                taglen = tagbits / 8;
   1048            }
   1049            if (strncmp(buf, "[IVlen", 6) == 0) {
   1050                if (sscanf(buf, "[IVlen = %d]", &ivlen) != 1) {
   1051                    goto loser;
   1052                }
   1053                ivlen = ivlen / 8;
   1054            }
   1055            fputs(buf, aesresp);
   1056            continue;
   1057        }
   1058        /* "COUNT = x" begins a new data set */
   1059        if (strncmp(buf, "Count", 5) == 0) {
   1060            /* zeroize the variables for the test with this data set */
   1061            memset(key, 0, sizeof key);
   1062            keysize = 0;
   1063            memset(iv, 0, sizeof iv);
   1064            memset(plaintext, 0, sizeof plaintext);
   1065            plaintextlen = 0;
   1066            memset(ciphertext, 0, sizeof ciphertext);
   1067            ciphertextlen = 0;
   1068            fputs(buf, aesresp);
   1069            continue;
   1070        }
   1071        /* KEY = ... */
   1072        if (strncmp(buf, "Key", 3) == 0) {
   1073            i = 3;
   1074            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1075                i++;
   1076            }
   1077            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   1078                hex_to_byteval(&buf[i], &key[j]);
   1079            }
   1080            keysize = j;
   1081            fputs(buf, aesresp);
   1082            continue;
   1083        }
   1084        /* IV = ... */
   1085        if (strncmp(buf, "IV", 2) == 0) {
   1086            i = 2;
   1087            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1088                i++;
   1089            }
   1090            for (j = 0; j < sizeof iv; i += 2, j++) {
   1091                hex_to_byteval(&buf[i], &iv[j]);
   1092            }
   1093            fputs(buf, aesresp);
   1094            continue;
   1095        }
   1096        /* PLAINTEXT = ... */
   1097        if (strncmp(buf, "PT", 2) == 0) {
   1098            /* sanity check */
   1099            if (!encrypt) {
   1100                goto loser;
   1101            }
   1102 
   1103            i = 2;
   1104            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1105                i++;
   1106            }
   1107            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   1108                hex_to_byteval(&buf[i], &plaintext[j]);
   1109            }
   1110            plaintextlen = j;
   1111            fputs(buf, aesresp);
   1112            continue;
   1113        }
   1114        /* CIPHERTEXT = ... */
   1115        if (strncmp(buf, "CT", 2) == 0) {
   1116            /* sanity check */
   1117            if (encrypt) {
   1118                goto loser;
   1119            }
   1120 
   1121            i = 2;
   1122            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1123                i++;
   1124            }
   1125            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   1126                hex_to_byteval(&buf[i], &ciphertext[j]);
   1127            }
   1128            ciphertextlen = j;
   1129            fputs(buf, aesresp);
   1130            continue;
   1131        }
   1132        if (strncmp(buf, "AAD", 3) == 0) {
   1133            i = 3;
   1134            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1135                i++;
   1136            }
   1137            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   1138                hex_to_byteval(&buf[i], &aad[j]);
   1139            }
   1140            aadlen = j;
   1141            fputs(buf, aesresp);
   1142            if (encrypt) {
   1143                if (encrypt == 2) {
   1144                    rv = RNG_GenerateGlobalRandomBytes(iv, ivlen);
   1145                    if (rv != SECSuccess) {
   1146                        goto loser;
   1147                    }
   1148                }
   1149                params.pIv = iv;
   1150                params.ulIvLen = ivlen;
   1151                params.pAAD = aad;
   1152                params.ulAADLen = aadlen;
   1153                params.ulTagBits = tagbits;
   1154                rv = aes_encrypt_buf(NSS_AES_GCM, key, keysize,
   1155                                     (unsigned char *)&params,
   1156                                     ciphertext, &ciphertextlen, sizeof ciphertext,
   1157                                     plaintext, plaintextlen);
   1158                if (rv != SECSuccess) {
   1159                    goto loser;
   1160                }
   1161 
   1162                if (encrypt == 2) {
   1163                    fputs("IV = ", aesresp);
   1164                    to_hex_str(buf, iv, ivlen);
   1165                    fputs(buf, aesresp);
   1166                    fputc('\n', aesresp);
   1167                }
   1168                fputs("CT = ", aesresp);
   1169                j = ciphertextlen - taglen;
   1170                to_hex_str(buf, ciphertext, j);
   1171                fputs(buf, aesresp);
   1172                fputs("\nTag = ", aesresp);
   1173                to_hex_str(buf, ciphertext + j, taglen);
   1174                fputs(buf, aesresp);
   1175                fputc('\n', aesresp);
   1176            }
   1177            continue;
   1178        }
   1179        if (strncmp(buf, "Tag", 3) == 0) {
   1180            /* sanity check */
   1181            if (encrypt) {
   1182                goto loser;
   1183            }
   1184 
   1185            i = 3;
   1186            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1187                i++;
   1188            }
   1189            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   1190                hex_to_byteval(&buf[i], &ciphertext[j + ciphertextlen]);
   1191            }
   1192            ciphertextlen += j;
   1193            params.pIv = iv;
   1194            params.ulIvLen = ivlen;
   1195            params.pAAD = aad;
   1196            params.ulAADLen = aadlen;
   1197            params.ulTagBits = tagbits;
   1198            rv = aes_decrypt_buf(NSS_AES_GCM, key, keysize,
   1199                                 (unsigned char *)&params,
   1200                                 plaintext, &plaintextlen, sizeof plaintext,
   1201                                 ciphertext, ciphertextlen);
   1202            fputs(buf, aesresp);
   1203            if (rv != SECSuccess) {
   1204                fprintf(aesresp, "FAIL\n");
   1205            } else {
   1206                fputs("PT = ", aesresp);
   1207                to_hex_str(buf, plaintext, plaintextlen);
   1208                fputs(buf, aesresp);
   1209                fputc('\n', aesresp);
   1210            }
   1211            continue;
   1212        }
   1213    }
   1214 loser:
   1215    fclose(aesreq);
   1216 }
   1217 
   1218 /*
   1219 * Perform the AES Known Answer Test (KAT) or Multi-block Message
   1220 * Test (MMT) in ECB or CBC mode.  The KAT (there are four types)
   1221 * and MMT have the same structure: given the key and IV (CBC mode
   1222 * only), encrypt the given plaintext or decrypt the given ciphertext.
   1223 * So we can handle them the same way.
   1224 *
   1225 * reqfn is the pathname of the REQUEST file.
   1226 *
   1227 * The output RESPONSE file is written to stdout.
   1228 */
   1229 void
   1230 aes_kat_mmt(char *reqfn)
   1231 {
   1232    char buf[512]; /* holds one line from the input REQUEST file.
   1233                    * needs to be large enough to hold the longest
   1234                    * line "CIPHERTEXT = <320 hex digits>\n".
   1235                    */
   1236    FILE *aesreq;  /* input stream from the REQUEST file */
   1237    FILE *aesresp; /* output stream to the RESPONSE file */
   1238    int i, j;
   1239    int mode = NSS_AES;    /* NSS_AES (ECB) or NSS_AES_CBC */
   1240    int encrypt = 0;       /* 1 means encrypt, 0 means decrypt */
   1241    unsigned char key[32]; /* 128, 192, or 256 bits */
   1242    unsigned int keysize = 0;
   1243    unsigned char iv[16];             /* for all modes except ECB */
   1244    unsigned char plaintext[10 * 16]; /* 1 to 10 blocks */
   1245    unsigned int plaintextlen;
   1246    unsigned char ciphertext[10 * 16]; /* 1 to 10 blocks */
   1247    unsigned int ciphertextlen;
   1248    SECStatus rv;
   1249 
   1250    aesreq = fopen(reqfn, "r");
   1251    aesresp = stdout;
   1252    while (fgets(buf, sizeof buf, aesreq) != NULL) {
   1253        /* a comment or blank line */
   1254        if (buf[0] == '#' || buf[0] == '\n') {
   1255            fputs(buf, aesresp);
   1256            continue;
   1257        }
   1258        /* [ENCRYPT] or [DECRYPT] */
   1259        if (buf[0] == '[') {
   1260            if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
   1261                encrypt = 1;
   1262            } else {
   1263                encrypt = 0;
   1264            }
   1265            fputs(buf, aesresp);
   1266            continue;
   1267        }
   1268        /* "COUNT = x" begins a new data set */
   1269        if (strncmp(buf, "COUNT", 5) == 0) {
   1270            mode = NSS_AES;
   1271            /* zeroize the variables for the test with this data set */
   1272            memset(key, 0, sizeof key);
   1273            keysize = 0;
   1274            memset(iv, 0, sizeof iv);
   1275            memset(plaintext, 0, sizeof plaintext);
   1276            plaintextlen = 0;
   1277            memset(ciphertext, 0, sizeof ciphertext);
   1278            ciphertextlen = 0;
   1279            fputs(buf, aesresp);
   1280            continue;
   1281        }
   1282        /* KEY = ... */
   1283        if (strncmp(buf, "KEY", 3) == 0) {
   1284            i = 3;
   1285            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1286                i++;
   1287            }
   1288            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   1289                hex_to_byteval(&buf[i], &key[j]);
   1290            }
   1291            keysize = j;
   1292            fputs(buf, aesresp);
   1293            continue;
   1294        }
   1295        /* IV = ... */
   1296        if (strncmp(buf, "IV", 2) == 0) {
   1297            mode = NSS_AES_CBC;
   1298            i = 2;
   1299            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1300                i++;
   1301            }
   1302            for (j = 0; j < sizeof iv; i += 2, j++) {
   1303                hex_to_byteval(&buf[i], &iv[j]);
   1304            }
   1305            fputs(buf, aesresp);
   1306            continue;
   1307        }
   1308        /* PLAINTEXT = ... */
   1309        if (strncmp(buf, "PLAINTEXT", 9) == 0) {
   1310            /* sanity check */
   1311            if (!encrypt) {
   1312                goto loser;
   1313            }
   1314 
   1315            i = 9;
   1316            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1317                i++;
   1318            }
   1319            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   1320                hex_to_byteval(&buf[i], &plaintext[j]);
   1321            }
   1322            plaintextlen = j;
   1323 
   1324            rv = aes_encrypt_buf(mode, key, keysize,
   1325                                 (mode ==
   1326                                  NSS_AES)
   1327                                     ? NULL
   1328                                     : iv,
   1329                                 ciphertext, &ciphertextlen, sizeof ciphertext,
   1330                                 plaintext, plaintextlen);
   1331            if (rv != SECSuccess) {
   1332                goto loser;
   1333            }
   1334 
   1335            fputs(buf, aesresp);
   1336            fputs("CIPHERTEXT = ", aesresp);
   1337            to_hex_str(buf, ciphertext, ciphertextlen);
   1338            fputs(buf, aesresp);
   1339            fputc('\n', aesresp);
   1340            continue;
   1341        }
   1342        /* CIPHERTEXT = ... */
   1343        if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
   1344            /* sanity check */
   1345            if (encrypt) {
   1346                goto loser;
   1347            }
   1348 
   1349            i = 10;
   1350            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1351                i++;
   1352            }
   1353            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   1354                hex_to_byteval(&buf[i], &ciphertext[j]);
   1355            }
   1356            ciphertextlen = j;
   1357 
   1358            rv = aes_decrypt_buf(mode, key, keysize,
   1359                                 (mode ==
   1360                                  NSS_AES)
   1361                                     ? NULL
   1362                                     : iv,
   1363                                 plaintext, &plaintextlen, sizeof plaintext,
   1364                                 ciphertext, ciphertextlen);
   1365            if (rv != SECSuccess) {
   1366                goto loser;
   1367            }
   1368 
   1369            fputs(buf, aesresp);
   1370            fputs("PLAINTEXT = ", aesresp);
   1371            to_hex_str(buf, plaintext, plaintextlen);
   1372            fputs(buf, aesresp);
   1373            fputc('\n', aesresp);
   1374            continue;
   1375        }
   1376    }
   1377 loser:
   1378    fclose(aesreq);
   1379 }
   1380 
   1381 /*
   1382 * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo
   1383 * Test (MCT) in ECB and CBC modes.
   1384 */
   1385 void
   1386 aes_mct_next_key(unsigned char *key, unsigned int keysize,
   1387                 const unsigned char *ciphertext_1, const unsigned char *ciphertext)
   1388 {
   1389    int k;
   1390 
   1391    switch (keysize) {
   1392        case 16: /* 128-bit key */
   1393            /* Key[i+1] = Key[i] xor CT[j] */
   1394            for (k = 0; k < 16; k++) {
   1395                key[k] ^= ciphertext[k];
   1396            }
   1397            break;
   1398        case 24: /* 192-bit key */
   1399            /*
   1400             * Key[i+1] = Key[i] xor (last 64-bits of
   1401             *            CT[j-1] || CT[j])
   1402             */
   1403            for (k = 0; k < 8; k++) {
   1404                key[k] ^= ciphertext_1[k + 8];
   1405            }
   1406            for (k = 8; k < 24; k++) {
   1407                key[k] ^= ciphertext[k - 8];
   1408            }
   1409            break;
   1410        case 32: /* 256-bit key */
   1411            /* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */
   1412            for (k = 0; k < 16; k++) {
   1413                key[k] ^= ciphertext_1[k];
   1414            }
   1415            for (k = 16; k < 32; k++) {
   1416                key[k] ^= ciphertext[k - 16];
   1417            }
   1418            break;
   1419    }
   1420 }
   1421 
   1422 /*
   1423 * Perform the AES Monte Carlo Test (MCT) in ECB mode.  MCT exercises
   1424 * our AES code in streaming mode because the plaintext or ciphertext
   1425 * is generated block by block as we go, so we can't collect all the
   1426 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
   1427 * one shot.
   1428 *
   1429 * reqfn is the pathname of the input REQUEST file.
   1430 *
   1431 * The output RESPONSE file is written to stdout.
   1432 */
   1433 void
   1434 aes_ecb_mct(char *reqfn)
   1435 {
   1436    char buf[80];  /* holds one line from the input REQUEST file.
   1437                    * needs to be large enough to hold the longest
   1438                    * line "KEY = <64 hex digits>\n".
   1439                    */
   1440    FILE *aesreq;  /* input stream from the REQUEST file */
   1441    FILE *aesresp; /* output stream to the RESPONSE file */
   1442    int i, j;
   1443    int encrypt = 0;       /* 1 means encrypt, 0 means decrypt */
   1444    unsigned char key[32]; /* 128, 192, or 256 bits */
   1445    unsigned int keysize = 0;
   1446    unsigned char plaintext[16];    /* PT[j] */
   1447    unsigned char plaintext_1[16];  /* PT[j-1] */
   1448    unsigned char ciphertext[16];   /* CT[j] */
   1449    unsigned char ciphertext_1[16]; /* CT[j-1] */
   1450    unsigned char doublecheck[16];
   1451    unsigned int outputlen;
   1452    AESContext *cx = NULL;  /* the operation being tested */
   1453    AESContext *cx2 = NULL; /* the inverse operation done in parallel
   1454                             * to doublecheck our result.
   1455                             */
   1456    SECStatus rv;
   1457 
   1458    aesreq = fopen(reqfn, "r");
   1459    aesresp = stdout;
   1460    while (fgets(buf, sizeof buf, aesreq) != NULL) {
   1461        /* a comment or blank line */
   1462        if (buf[0] == '#' || buf[0] == '\n') {
   1463            fputs(buf, aesresp);
   1464            continue;
   1465        }
   1466        /* [ENCRYPT] or [DECRYPT] */
   1467        if (buf[0] == '[') {
   1468            if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
   1469                encrypt = 1;
   1470            } else {
   1471                encrypt = 0;
   1472            }
   1473            fputs(buf, aesresp);
   1474            continue;
   1475        }
   1476        /* "COUNT = x" begins a new data set */
   1477        if (strncmp(buf, "COUNT", 5) == 0) {
   1478            /* zeroize the variables for the test with this data set */
   1479            memset(key, 0, sizeof key);
   1480            keysize = 0;
   1481            memset(plaintext, 0, sizeof plaintext);
   1482            memset(ciphertext, 0, sizeof ciphertext);
   1483            continue;
   1484        }
   1485        /* KEY = ... */
   1486        if (strncmp(buf, "KEY", 3) == 0) {
   1487            /* Key[0] = Key */
   1488            i = 3;
   1489            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1490                i++;
   1491            }
   1492            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   1493                hex_to_byteval(&buf[i], &key[j]);
   1494            }
   1495            keysize = j;
   1496            continue;
   1497        }
   1498        /* PLAINTEXT = ... */
   1499        if (strncmp(buf, "PLAINTEXT", 9) == 0) {
   1500            /* sanity check */
   1501            if (!encrypt) {
   1502                goto loser;
   1503            }
   1504            /* PT[0] = PT */
   1505            i = 9;
   1506            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1507                i++;
   1508            }
   1509            for (j = 0; j < sizeof plaintext; i += 2, j++) {
   1510                hex_to_byteval(&buf[i], &plaintext[j]);
   1511            }
   1512 
   1513            for (i = 0; i < 100; i++) {
   1514                snprintf(buf, sizeof(buf), "COUNT = %d\n", i);
   1515                fputs(buf, aesresp);
   1516                /* Output Key[i] */
   1517                fputs("KEY = ", aesresp);
   1518                to_hex_str(buf, key, keysize);
   1519                fputs(buf, aesresp);
   1520                fputc('\n', aesresp);
   1521                /* Output PT[0] */
   1522                fputs("PLAINTEXT = ", aesresp);
   1523                to_hex_str(buf, plaintext, sizeof plaintext);
   1524                fputs(buf, aesresp);
   1525                fputc('\n', aesresp);
   1526 
   1527                cx = AES_CreateContext(key, NULL, NSS_AES,
   1528                                       PR_TRUE, keysize, 16);
   1529                if (cx == NULL) {
   1530                    goto loser;
   1531                }
   1532                /*
   1533                 * doublecheck our result by decrypting the result
   1534                 * and comparing the output with the plaintext.
   1535                 */
   1536                cx2 = AES_CreateContext(key, NULL, NSS_AES,
   1537                                        PR_FALSE, keysize, 16);
   1538                if (cx2 == NULL) {
   1539                    goto loser;
   1540                }
   1541                for (j = 0; j < 1000; j++) {
   1542                    /* Save CT[j-1] */
   1543                    memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
   1544 
   1545                    /* CT[j] = AES(Key[i], PT[j]) */
   1546                    outputlen = 0;
   1547                    rv = AES_Encrypt(cx,
   1548                                     ciphertext, &outputlen, sizeof ciphertext,
   1549                                     plaintext, sizeof plaintext);
   1550                    if (rv != SECSuccess) {
   1551                        goto loser;
   1552                    }
   1553                    if (outputlen != sizeof plaintext) {
   1554                        goto loser;
   1555                    }
   1556 
   1557                    /* doublecheck our result */
   1558                    outputlen = 0;
   1559                    rv = AES_Decrypt(cx2,
   1560                                     doublecheck, &outputlen, sizeof doublecheck,
   1561                                     ciphertext, sizeof ciphertext);
   1562                    if (rv != SECSuccess) {
   1563                        goto loser;
   1564                    }
   1565                    if (outputlen != sizeof ciphertext) {
   1566                        goto loser;
   1567                    }
   1568                    if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
   1569                        goto loser;
   1570                    }
   1571 
   1572                    /* PT[j+1] = CT[j] */
   1573                    memcpy(plaintext, ciphertext, sizeof plaintext);
   1574                }
   1575                AES_DestroyContext(cx, PR_TRUE);
   1576                cx = NULL;
   1577                AES_DestroyContext(cx2, PR_TRUE);
   1578                cx2 = NULL;
   1579 
   1580                /* Output CT[j] */
   1581                fputs("CIPHERTEXT = ", aesresp);
   1582                to_hex_str(buf, ciphertext, sizeof ciphertext);
   1583                fputs(buf, aesresp);
   1584                fputc('\n', aesresp);
   1585 
   1586                /* Key[i+1] = Key[i] xor ... */
   1587                aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
   1588                /* PT[0] = CT[j] */
   1589                /* done at the end of the for(j) loop */
   1590 
   1591                fputc('\n', aesresp);
   1592            }
   1593 
   1594            continue;
   1595        }
   1596        /* CIPHERTEXT = ... */
   1597        if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
   1598            /* sanity check */
   1599            if (encrypt) {
   1600                goto loser;
   1601            }
   1602            /* CT[0] = CT */
   1603            i = 10;
   1604            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1605                i++;
   1606            }
   1607            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   1608                hex_to_byteval(&buf[i], &ciphertext[j]);
   1609            }
   1610 
   1611            for (i = 0; i < 100; i++) {
   1612                snprintf(buf, sizeof(buf), "COUNT = %d\n", i);
   1613                fputs(buf, aesresp);
   1614                /* Output Key[i] */
   1615                fputs("KEY = ", aesresp);
   1616                to_hex_str(buf, key, keysize);
   1617                fputs(buf, aesresp);
   1618                fputc('\n', aesresp);
   1619                /* Output CT[0] */
   1620                fputs("CIPHERTEXT = ", aesresp);
   1621                to_hex_str(buf, ciphertext, sizeof ciphertext);
   1622                fputs(buf, aesresp);
   1623                fputc('\n', aesresp);
   1624 
   1625                cx = AES_CreateContext(key, NULL, NSS_AES,
   1626                                       PR_FALSE, keysize, 16);
   1627                if (cx == NULL) {
   1628                    goto loser;
   1629                }
   1630                /*
   1631                 * doublecheck our result by encrypting the result
   1632                 * and comparing the output with the ciphertext.
   1633                 */
   1634                cx2 = AES_CreateContext(key, NULL, NSS_AES,
   1635                                        PR_TRUE, keysize, 16);
   1636                if (cx2 == NULL) {
   1637                    goto loser;
   1638                }
   1639                for (j = 0; j < 1000; j++) {
   1640                    /* Save PT[j-1] */
   1641                    memcpy(plaintext_1, plaintext, sizeof plaintext);
   1642 
   1643                    /* PT[j] = AES(Key[i], CT[j]) */
   1644                    outputlen = 0;
   1645                    rv = AES_Decrypt(cx,
   1646                                     plaintext, &outputlen, sizeof plaintext,
   1647                                     ciphertext, sizeof ciphertext);
   1648                    if (rv != SECSuccess) {
   1649                        goto loser;
   1650                    }
   1651                    if (outputlen != sizeof ciphertext) {
   1652                        goto loser;
   1653                    }
   1654 
   1655                    /* doublecheck our result */
   1656                    outputlen = 0;
   1657                    rv = AES_Encrypt(cx2,
   1658                                     doublecheck, &outputlen, sizeof doublecheck,
   1659                                     plaintext, sizeof plaintext);
   1660                    if (rv != SECSuccess) {
   1661                        goto loser;
   1662                    }
   1663                    if (outputlen != sizeof plaintext) {
   1664                        goto loser;
   1665                    }
   1666                    if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
   1667                        goto loser;
   1668                    }
   1669 
   1670                    /* CT[j+1] = PT[j] */
   1671                    memcpy(ciphertext, plaintext, sizeof ciphertext);
   1672                }
   1673                AES_DestroyContext(cx, PR_TRUE);
   1674                cx = NULL;
   1675                AES_DestroyContext(cx2, PR_TRUE);
   1676                cx2 = NULL;
   1677 
   1678                /* Output PT[j] */
   1679                fputs("PLAINTEXT = ", aesresp);
   1680                to_hex_str(buf, plaintext, sizeof plaintext);
   1681                fputs(buf, aesresp);
   1682                fputc('\n', aesresp);
   1683 
   1684                /* Key[i+1] = Key[i] xor ... */
   1685                aes_mct_next_key(key, keysize, plaintext_1, plaintext);
   1686                /* CT[0] = PT[j] */
   1687                /* done at the end of the for(j) loop */
   1688 
   1689                fputc('\n', aesresp);
   1690            }
   1691 
   1692            continue;
   1693        }
   1694    }
   1695 loser:
   1696    if (cx != NULL) {
   1697        AES_DestroyContext(cx, PR_TRUE);
   1698    }
   1699    if (cx2 != NULL) {
   1700        AES_DestroyContext(cx2, PR_TRUE);
   1701    }
   1702    fclose(aesreq);
   1703 }
   1704 
   1705 /*
   1706 * Perform the AES Monte Carlo Test (MCT) in CBC mode.  MCT exercises
   1707 * our AES code in streaming mode because the plaintext or ciphertext
   1708 * is generated block by block as we go, so we can't collect all the
   1709 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
   1710 * one shot.
   1711 *
   1712 * reqfn is the pathname of the input REQUEST file.
   1713 *
   1714 * The output RESPONSE file is written to stdout.
   1715 */
   1716 void
   1717 aes_cbc_mct(char *reqfn)
   1718 {
   1719    char buf[80];  /* holds one line from the input REQUEST file.
   1720                    * needs to be large enough to hold the longest
   1721                    * line "KEY = <64 hex digits>\n".
   1722                    */
   1723    FILE *aesreq;  /* input stream from the REQUEST file */
   1724    FILE *aesresp; /* output stream to the RESPONSE file */
   1725    int i, j;
   1726    int encrypt = 0;       /* 1 means encrypt, 0 means decrypt */
   1727    unsigned char key[32]; /* 128, 192, or 256 bits */
   1728    unsigned int keysize = 0;
   1729    unsigned char iv[16];
   1730    unsigned char plaintext[16];    /* PT[j] */
   1731    unsigned char plaintext_1[16];  /* PT[j-1] */
   1732    unsigned char ciphertext[16];   /* CT[j] */
   1733    unsigned char ciphertext_1[16]; /* CT[j-1] */
   1734    unsigned char doublecheck[16];
   1735    unsigned int outputlen;
   1736    AESContext *cx = NULL;  /* the operation being tested */
   1737    AESContext *cx2 = NULL; /* the inverse operation done in parallel
   1738                             * to doublecheck our result.
   1739                             */
   1740    SECStatus rv;
   1741 
   1742    aesreq = fopen(reqfn, "r");
   1743    aesresp = stdout;
   1744    while (fgets(buf, sizeof buf, aesreq) != NULL) {
   1745        /* a comment or blank line */
   1746        if (buf[0] == '#' || buf[0] == '\n') {
   1747            fputs(buf, aesresp);
   1748            continue;
   1749        }
   1750        /* [ENCRYPT] or [DECRYPT] */
   1751        if (buf[0] == '[') {
   1752            if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
   1753                encrypt = 1;
   1754            } else {
   1755                encrypt = 0;
   1756            }
   1757            fputs(buf, aesresp);
   1758            continue;
   1759        }
   1760        /* "COUNT = x" begins a new data set */
   1761        if (strncmp(buf, "COUNT", 5) == 0) {
   1762            /* zeroize the variables for the test with this data set */
   1763            memset(key, 0, sizeof key);
   1764            keysize = 0;
   1765            memset(iv, 0, sizeof iv);
   1766            memset(plaintext, 0, sizeof plaintext);
   1767            memset(ciphertext, 0, sizeof ciphertext);
   1768            continue;
   1769        }
   1770        /* KEY = ... */
   1771        if (strncmp(buf, "KEY", 3) == 0) {
   1772            /* Key[0] = Key */
   1773            i = 3;
   1774            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1775                i++;
   1776            }
   1777            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   1778                hex_to_byteval(&buf[i], &key[j]);
   1779            }
   1780            keysize = j;
   1781            continue;
   1782        }
   1783        /* IV = ... */
   1784        if (strncmp(buf, "IV", 2) == 0) {
   1785            /* IV[0] = IV */
   1786            i = 2;
   1787            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1788                i++;
   1789            }
   1790            for (j = 0; j < sizeof iv; i += 2, j++) {
   1791                hex_to_byteval(&buf[i], &iv[j]);
   1792            }
   1793            continue;
   1794        }
   1795        /* PLAINTEXT = ... */
   1796        if (strncmp(buf, "PLAINTEXT", 9) == 0) {
   1797            /* sanity check */
   1798            if (!encrypt) {
   1799                goto loser;
   1800            }
   1801            /* PT[0] = PT */
   1802            i = 9;
   1803            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1804                i++;
   1805            }
   1806            for (j = 0; j < sizeof plaintext; i += 2, j++) {
   1807                hex_to_byteval(&buf[i], &plaintext[j]);
   1808            }
   1809 
   1810            for (i = 0; i < 100; i++) {
   1811                snprintf(buf, sizeof(buf), "COUNT = %d\n", i);
   1812                fputs(buf, aesresp);
   1813                /* Output Key[i] */
   1814                fputs("KEY = ", aesresp);
   1815                to_hex_str(buf, key, keysize);
   1816                fputs(buf, aesresp);
   1817                fputc('\n', aesresp);
   1818                /* Output IV[i] */
   1819                fputs("IV = ", aesresp);
   1820                to_hex_str(buf, iv, sizeof iv);
   1821                fputs(buf, aesresp);
   1822                fputc('\n', aesresp);
   1823                /* Output PT[0] */
   1824                fputs("PLAINTEXT = ", aesresp);
   1825                to_hex_str(buf, plaintext, sizeof plaintext);
   1826                fputs(buf, aesresp);
   1827                fputc('\n', aesresp);
   1828 
   1829                cx = AES_CreateContext(key, iv, NSS_AES_CBC,
   1830                                       PR_TRUE, keysize, 16);
   1831                if (cx == NULL) {
   1832                    goto loser;
   1833                }
   1834                /*
   1835                 * doublecheck our result by decrypting the result
   1836                 * and comparing the output with the plaintext.
   1837                 */
   1838                cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
   1839                                        PR_FALSE, keysize, 16);
   1840                if (cx2 == NULL) {
   1841                    goto loser;
   1842                }
   1843                /* CT[-1] = IV[i] */
   1844                memcpy(ciphertext, iv, sizeof ciphertext);
   1845                for (j = 0; j < 1000; j++) {
   1846                    /* Save CT[j-1] */
   1847                    memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
   1848                    /*
   1849                     * If ( j=0 )
   1850                     *      CT[j] = AES(Key[i], IV[i], PT[j])
   1851                     *      PT[j+1] = IV[i] (= CT[j-1])
   1852                     * Else
   1853                     *      CT[j] = AES(Key[i], PT[j])
   1854                     *      PT[j+1] = CT[j-1]
   1855                     */
   1856                    outputlen = 0;
   1857                    rv = AES_Encrypt(cx,
   1858                                     ciphertext, &outputlen, sizeof ciphertext,
   1859                                     plaintext, sizeof plaintext);
   1860                    if (rv != SECSuccess) {
   1861                        goto loser;
   1862                    }
   1863                    if (outputlen != sizeof plaintext) {
   1864                        goto loser;
   1865                    }
   1866 
   1867                    /* doublecheck our result */
   1868                    outputlen = 0;
   1869                    rv = AES_Decrypt(cx2,
   1870                                     doublecheck, &outputlen, sizeof doublecheck,
   1871                                     ciphertext, sizeof ciphertext);
   1872                    if (rv != SECSuccess) {
   1873                        goto loser;
   1874                    }
   1875                    if (outputlen != sizeof ciphertext) {
   1876                        goto loser;
   1877                    }
   1878                    if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
   1879                        goto loser;
   1880                    }
   1881 
   1882                    memcpy(plaintext, ciphertext_1, sizeof plaintext);
   1883                }
   1884                AES_DestroyContext(cx, PR_TRUE);
   1885                cx = NULL;
   1886                AES_DestroyContext(cx2, PR_TRUE);
   1887                cx2 = NULL;
   1888 
   1889                /* Output CT[j] */
   1890                fputs("CIPHERTEXT = ", aesresp);
   1891                to_hex_str(buf, ciphertext, sizeof ciphertext);
   1892                fputs(buf, aesresp);
   1893                fputc('\n', aesresp);
   1894 
   1895                /* Key[i+1] = Key[i] xor ... */
   1896                aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
   1897                /* IV[i+1] = CT[j] */
   1898                memcpy(iv, ciphertext, sizeof iv);
   1899                /* PT[0] = CT[j-1] */
   1900                /* done at the end of the for(j) loop */
   1901 
   1902                fputc('\n', aesresp);
   1903            }
   1904 
   1905            continue;
   1906        }
   1907        /* CIPHERTEXT = ... */
   1908        if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
   1909            /* sanity check */
   1910            if (encrypt) {
   1911                goto loser;
   1912            }
   1913            /* CT[0] = CT */
   1914            i = 10;
   1915            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   1916                i++;
   1917            }
   1918            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   1919                hex_to_byteval(&buf[i], &ciphertext[j]);
   1920            }
   1921 
   1922            for (i = 0; i < 100; i++) {
   1923                snprintf(buf, sizeof(buf), "COUNT = %d\n", i);
   1924                fputs(buf, aesresp);
   1925                /* Output Key[i] */
   1926                fputs("KEY = ", aesresp);
   1927                to_hex_str(buf, key, keysize);
   1928                fputs(buf, aesresp);
   1929                fputc('\n', aesresp);
   1930                /* Output IV[i] */
   1931                fputs("IV = ", aesresp);
   1932                to_hex_str(buf, iv, sizeof iv);
   1933                fputs(buf, aesresp);
   1934                fputc('\n', aesresp);
   1935                /* Output CT[0] */
   1936                fputs("CIPHERTEXT = ", aesresp);
   1937                to_hex_str(buf, ciphertext, sizeof ciphertext);
   1938                fputs(buf, aesresp);
   1939                fputc('\n', aesresp);
   1940 
   1941                cx = AES_CreateContext(key, iv, NSS_AES_CBC,
   1942                                       PR_FALSE, keysize, 16);
   1943                if (cx == NULL) {
   1944                    goto loser;
   1945                }
   1946                /*
   1947                 * doublecheck our result by encrypting the result
   1948                 * and comparing the output with the ciphertext.
   1949                 */
   1950                cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
   1951                                        PR_TRUE, keysize, 16);
   1952                if (cx2 == NULL) {
   1953                    goto loser;
   1954                }
   1955                /* PT[-1] = IV[i] */
   1956                memcpy(plaintext, iv, sizeof plaintext);
   1957                for (j = 0; j < 1000; j++) {
   1958                    /* Save PT[j-1] */
   1959                    memcpy(plaintext_1, plaintext, sizeof plaintext);
   1960                    /*
   1961                     * If ( j=0 )
   1962                     *      PT[j] = AES(Key[i], IV[i], CT[j])
   1963                     *      CT[j+1] = IV[i] (= PT[j-1])
   1964                     * Else
   1965                     *      PT[j] = AES(Key[i], CT[j])
   1966                     *      CT[j+1] = PT[j-1]
   1967                     */
   1968                    outputlen = 0;
   1969                    rv = AES_Decrypt(cx,
   1970                                     plaintext, &outputlen, sizeof plaintext,
   1971                                     ciphertext, sizeof ciphertext);
   1972                    if (rv != SECSuccess) {
   1973                        goto loser;
   1974                    }
   1975                    if (outputlen != sizeof ciphertext) {
   1976                        goto loser;
   1977                    }
   1978 
   1979                    /* doublecheck our result */
   1980                    outputlen = 0;
   1981                    rv = AES_Encrypt(cx2,
   1982                                     doublecheck, &outputlen, sizeof doublecheck,
   1983                                     plaintext, sizeof plaintext);
   1984                    if (rv != SECSuccess) {
   1985                        goto loser;
   1986                    }
   1987                    if (outputlen != sizeof plaintext) {
   1988                        goto loser;
   1989                    }
   1990                    if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
   1991                        goto loser;
   1992                    }
   1993 
   1994                    memcpy(ciphertext, plaintext_1, sizeof ciphertext);
   1995                }
   1996                AES_DestroyContext(cx, PR_TRUE);
   1997                cx = NULL;
   1998                AES_DestroyContext(cx2, PR_TRUE);
   1999                cx2 = NULL;
   2000 
   2001                /* Output PT[j] */
   2002                fputs("PLAINTEXT = ", aesresp);
   2003                to_hex_str(buf, plaintext, sizeof plaintext);
   2004                fputs(buf, aesresp);
   2005                fputc('\n', aesresp);
   2006 
   2007                /* Key[i+1] = Key[i] xor ... */
   2008                aes_mct_next_key(key, keysize, plaintext_1, plaintext);
   2009                /* IV[i+1] = PT[j] */
   2010                memcpy(iv, plaintext, sizeof iv);
   2011                /* CT[0] = PT[j-1] */
   2012                /* done at the end of the for(j) loop */
   2013 
   2014                fputc('\n', aesresp);
   2015            }
   2016 
   2017            continue;
   2018        }
   2019    }
   2020 loser:
   2021    if (cx != NULL) {
   2022        AES_DestroyContext(cx, PR_TRUE);
   2023    }
   2024    if (cx2 != NULL) {
   2025        AES_DestroyContext(cx2, PR_TRUE);
   2026    }
   2027    fclose(aesreq);
   2028 }
   2029 
   2030 void
   2031 write_compact_string(FILE *out, unsigned char *hash, unsigned int len)
   2032 {
   2033    unsigned int i;
   2034    int j, count = 0, last = -1, z = 0;
   2035    long start = ftell(out);
   2036    for (i = 0; i < len; i++) {
   2037        for (j = 7; j >= 0; j--) {
   2038            if (last < 0) {
   2039                last = (hash[i] & (1 << j)) ? 1 : 0;
   2040                fprintf(out, "%d ", last);
   2041                count = 1;
   2042            } else if (hash[i] & (1 << j)) {
   2043                if (last) {
   2044                    count++;
   2045                } else {
   2046                    last = 0;
   2047                    fprintf(out, "%d ", count);
   2048                    count = 1;
   2049                    z++;
   2050                }
   2051            } else {
   2052                if (!last) {
   2053                    count++;
   2054                } else {
   2055                    last = 1;
   2056                    fprintf(out, "%d ", count);
   2057                    count = 1;
   2058                    z++;
   2059                }
   2060            }
   2061        }
   2062    }
   2063    fprintf(out, "^\n");
   2064    fseek(out, start, SEEK_SET);
   2065    fprintf(out, "%d ", z);
   2066    fseek(out, 0, SEEK_END);
   2067 }
   2068 
   2069 int
   2070 get_next_line(FILE *req, char *key, char *val, FILE *rsp)
   2071 {
   2072    int ignore = 0;
   2073    char *writeto = key;
   2074    int w = 0;
   2075    int c;
   2076    while ((c = fgetc(req)) != EOF) {
   2077        if (ignore) {
   2078            fprintf(rsp, "%c", c);
   2079            if (c == '\n')
   2080                return ignore;
   2081        } else if (c == '\n') {
   2082            break;
   2083        } else if (c == '#') {
   2084            ignore = 1;
   2085            fprintf(rsp, "%c", c);
   2086        } else if (c == '=') {
   2087            writeto[w] = '\0';
   2088            w = 0;
   2089            writeto = val;
   2090        } else if (c == ' ' || c == '[' || c == ']') {
   2091            continue;
   2092        } else {
   2093            writeto[w++] = c;
   2094        }
   2095    }
   2096    writeto[w] = '\0';
   2097    return (c == EOF) ? -1 : ignore;
   2098 }
   2099 
   2100 typedef struct curveNameTagPairStr {
   2101    char *curveName;
   2102    SECOidTag curveOidTag;
   2103 } CurveNameTagPair;
   2104 
   2105 #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1
   2106 /* #define DEFAULT_CURVE_OID_TAG  SEC_OID_SECG_EC_SECP160R1 */
   2107 
   2108 static CurveNameTagPair nameTagPair[] = {
   2109    { "sect163k1", SEC_OID_SECG_EC_SECT163K1 },
   2110    { "nistk163", SEC_OID_SECG_EC_SECT163K1 },
   2111    { "sect163r1", SEC_OID_SECG_EC_SECT163R1 },
   2112    { "sect163r2", SEC_OID_SECG_EC_SECT163R2 },
   2113    { "nistb163", SEC_OID_SECG_EC_SECT163R2 },
   2114    { "sect193r1", SEC_OID_SECG_EC_SECT193R1 },
   2115    { "sect193r2", SEC_OID_SECG_EC_SECT193R2 },
   2116    { "sect233k1", SEC_OID_SECG_EC_SECT233K1 },
   2117    { "nistk233", SEC_OID_SECG_EC_SECT233K1 },
   2118    { "sect233r1", SEC_OID_SECG_EC_SECT233R1 },
   2119    { "nistb233", SEC_OID_SECG_EC_SECT233R1 },
   2120    { "sect239k1", SEC_OID_SECG_EC_SECT239K1 },
   2121    { "sect283k1", SEC_OID_SECG_EC_SECT283K1 },
   2122    { "nistk283", SEC_OID_SECG_EC_SECT283K1 },
   2123    { "sect283r1", SEC_OID_SECG_EC_SECT283R1 },
   2124    { "nistb283", SEC_OID_SECG_EC_SECT283R1 },
   2125    { "sect409k1", SEC_OID_SECG_EC_SECT409K1 },
   2126    { "nistk409", SEC_OID_SECG_EC_SECT409K1 },
   2127    { "sect409r1", SEC_OID_SECG_EC_SECT409R1 },
   2128    { "nistb409", SEC_OID_SECG_EC_SECT409R1 },
   2129    { "sect571k1", SEC_OID_SECG_EC_SECT571K1 },
   2130    { "nistk571", SEC_OID_SECG_EC_SECT571K1 },
   2131    { "sect571r1", SEC_OID_SECG_EC_SECT571R1 },
   2132    { "nistb571", SEC_OID_SECG_EC_SECT571R1 },
   2133    { "secp160k1", SEC_OID_SECG_EC_SECP160K1 },
   2134    { "secp160r1", SEC_OID_SECG_EC_SECP160R1 },
   2135    { "secp160r2", SEC_OID_SECG_EC_SECP160R2 },
   2136    { "secp192k1", SEC_OID_SECG_EC_SECP192K1 },
   2137    { "secp192r1", SEC_OID_SECG_EC_SECP192R1 },
   2138    { "nistp192", SEC_OID_SECG_EC_SECP192R1 },
   2139    { "secp224k1", SEC_OID_SECG_EC_SECP224K1 },
   2140    { "secp224r1", SEC_OID_SECG_EC_SECP224R1 },
   2141    { "nistp224", SEC_OID_SECG_EC_SECP224R1 },
   2142    { "secp256k1", SEC_OID_SECG_EC_SECP256K1 },
   2143    { "secp256r1", SEC_OID_SECG_EC_SECP256R1 },
   2144    { "nistp256", SEC_OID_SECG_EC_SECP256R1 },
   2145    { "secp384r1", SEC_OID_SECG_EC_SECP384R1 },
   2146    { "nistp384", SEC_OID_SECG_EC_SECP384R1 },
   2147    { "secp521r1", SEC_OID_SECG_EC_SECP521R1 },
   2148    { "nistp521", SEC_OID_SECG_EC_SECP521R1 },
   2149 
   2150    { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
   2151    { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
   2152    { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
   2153    { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
   2154    { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
   2155    { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
   2156 
   2157    { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
   2158    { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
   2159    { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
   2160    { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
   2161    { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
   2162    { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
   2163    { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
   2164    { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
   2165    { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
   2166    { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
   2167    { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
   2168    { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
   2169    { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
   2170    { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
   2171    { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
   2172    { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
   2173    { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
   2174    { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
   2175    { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
   2176    { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
   2177 
   2178    { "secp112r1", SEC_OID_SECG_EC_SECP112R1 },
   2179    { "secp112r2", SEC_OID_SECG_EC_SECP112R2 },
   2180    { "secp128r1", SEC_OID_SECG_EC_SECP128R1 },
   2181    { "secp128r2", SEC_OID_SECG_EC_SECP128R2 },
   2182 
   2183    { "sect113r1", SEC_OID_SECG_EC_SECT113R1 },
   2184    { "sect113r2", SEC_OID_SECG_EC_SECT113R2 },
   2185    { "sect131r1", SEC_OID_SECG_EC_SECT131R1 },
   2186    { "sect131r2", SEC_OID_SECG_EC_SECT131R2 },
   2187 };
   2188 
   2189 static SECItem *
   2190 getECParams(const char *curve)
   2191 {
   2192    SECItem *ecparams;
   2193    SECOidData *oidData = NULL;
   2194    SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
   2195    int i, numCurves;
   2196 
   2197    if (curve != NULL) {
   2198        numCurves = sizeof(nameTagPair) / sizeof(CurveNameTagPair);
   2199        for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN));
   2200             i++) {
   2201            if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
   2202                curveOidTag = nameTagPair[i].curveOidTag;
   2203        }
   2204    }
   2205 
   2206    /* Return NULL if curve name is not recognized */
   2207    if ((curveOidTag == SEC_OID_UNKNOWN) ||
   2208        (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
   2209        fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
   2210        return NULL;
   2211    }
   2212 
   2213    ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
   2214 
   2215    /*
   2216     * ecparams->data needs to contain the ASN encoding of an object ID (OID)
   2217     * representing the named curve. The actual OID is in
   2218     * oidData->oid.data so we simply prepend 0x06 and OID length
   2219     */
   2220    ecparams->data[0] = SEC_ASN1_OBJECT_ID;
   2221    ecparams->data[1] = oidData->oid.len;
   2222    memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
   2223 
   2224    return ecparams;
   2225 }
   2226 
   2227 /*
   2228 * HASH_ functions are available to full NSS apps and internally inside
   2229 * freebl, but not exported to users of freebl. Create short stubs to
   2230 * replace the functionality for fipstest.
   2231 */
   2232 SECStatus
   2233 fips_hashBuf(HASH_HashType type, unsigned char *hashBuf,
   2234             unsigned char *msg, int len)
   2235 {
   2236    SECStatus rv = SECFailure;
   2237 
   2238    switch (type) {
   2239        case HASH_AlgSHA1:
   2240            rv = SHA1_HashBuf(hashBuf, msg, len);
   2241            break;
   2242        case HASH_AlgSHA224:
   2243            rv = SHA224_HashBuf(hashBuf, msg, len);
   2244            break;
   2245        case HASH_AlgSHA256:
   2246            rv = SHA256_HashBuf(hashBuf, msg, len);
   2247            break;
   2248        case HASH_AlgSHA384:
   2249            rv = SHA384_HashBuf(hashBuf, msg, len);
   2250            break;
   2251        case HASH_AlgSHA512:
   2252            rv = SHA512_HashBuf(hashBuf, msg, len);
   2253            break;
   2254        default:
   2255            break;
   2256    }
   2257    return rv;
   2258 }
   2259 
   2260 int
   2261 fips_hashLen(HASH_HashType type)
   2262 {
   2263    int len = 0;
   2264 
   2265    switch (type) {
   2266        case HASH_AlgSHA1:
   2267            len = SHA1_LENGTH;
   2268            break;
   2269        case HASH_AlgSHA224:
   2270            len = SHA224_LENGTH;
   2271            break;
   2272        case HASH_AlgSHA256:
   2273            len = SHA256_LENGTH;
   2274            break;
   2275        case HASH_AlgSHA384:
   2276            len = SHA384_LENGTH;
   2277            break;
   2278        case HASH_AlgSHA512:
   2279            len = SHA512_LENGTH;
   2280            break;
   2281        default:
   2282            break;
   2283    }
   2284    return len;
   2285 }
   2286 
   2287 SECOidTag
   2288 fips_hashOid(HASH_HashType type)
   2289 {
   2290    SECOidTag oid = SEC_OID_UNKNOWN;
   2291 
   2292    switch (type) {
   2293        case HASH_AlgSHA1:
   2294            oid = SEC_OID_SHA1;
   2295            break;
   2296        case HASH_AlgSHA224:
   2297            oid = SEC_OID_SHA224;
   2298            break;
   2299        case HASH_AlgSHA256:
   2300            oid = SEC_OID_SHA256;
   2301            break;
   2302        case HASH_AlgSHA384:
   2303            oid = SEC_OID_SHA384;
   2304            break;
   2305        case HASH_AlgSHA512:
   2306            oid = SEC_OID_SHA512;
   2307            break;
   2308        default:
   2309            break;
   2310    }
   2311    return oid;
   2312 }
   2313 
   2314 HASH_HashType
   2315 sha_get_hashType(int hashbits)
   2316 {
   2317    HASH_HashType hashType = HASH_AlgNULL;
   2318 
   2319    switch (hashbits) {
   2320        case 1:
   2321        case (SHA1_LENGTH * PR_BITS_PER_BYTE):
   2322            hashType = HASH_AlgSHA1;
   2323            break;
   2324        case (SHA224_LENGTH * PR_BITS_PER_BYTE):
   2325            hashType = HASH_AlgSHA224;
   2326            break;
   2327        case (SHA256_LENGTH * PR_BITS_PER_BYTE):
   2328            hashType = HASH_AlgSHA256;
   2329            break;
   2330        case (SHA384_LENGTH * PR_BITS_PER_BYTE):
   2331            hashType = HASH_AlgSHA384;
   2332            break;
   2333        case (SHA512_LENGTH * PR_BITS_PER_BYTE):
   2334            hashType = HASH_AlgSHA512;
   2335            break;
   2336        default:
   2337            break;
   2338    }
   2339    return hashType;
   2340 }
   2341 
   2342 HASH_HashType
   2343 hash_string_to_hashType(const char *src)
   2344 {
   2345    HASH_HashType shaAlg = HASH_AlgNULL;
   2346    if (strncmp(src, "SHA-1", 5) == 0) {
   2347        shaAlg = HASH_AlgSHA1;
   2348    } else if (strncmp(src, "SHA-224", 7) == 0) {
   2349        shaAlg = HASH_AlgSHA224;
   2350    } else if (strncmp(src, "SHA-256", 7) == 0) {
   2351        shaAlg = HASH_AlgSHA256;
   2352    } else if (strncmp(src, "SHA-384", 7) == 0) {
   2353        shaAlg = HASH_AlgSHA384;
   2354    } else if (strncmp(src, "SHA-512", 7) == 0) {
   2355        shaAlg = HASH_AlgSHA512;
   2356    } else if (strncmp(src, "SHA1", 4) == 0) {
   2357        shaAlg = HASH_AlgSHA1;
   2358    } else if (strncmp(src, "SHA224", 6) == 0) {
   2359        shaAlg = HASH_AlgSHA224;
   2360    } else if (strncmp(src, "SHA256", 6) == 0) {
   2361        shaAlg = HASH_AlgSHA256;
   2362    } else if (strncmp(src, "SHA384", 6) == 0) {
   2363        shaAlg = HASH_AlgSHA384;
   2364    } else if (strncmp(src, "SHA512", 6) == 0) {
   2365        shaAlg = HASH_AlgSHA512;
   2366    }
   2367    return shaAlg;
   2368 }
   2369 
   2370 /*
   2371 * Perform the ECDSA Key Pair Generation Test.
   2372 *
   2373 * reqfn is the pathname of the REQUEST file.
   2374 *
   2375 * The output RESPONSE file is written to stdout.
   2376 */
   2377 void
   2378 ecdsa_keypair_test(char *reqfn)
   2379 {
   2380    char buf[256];   /* holds one line from the input REQUEST file
   2381                      * or to the output RESPONSE file.
   2382                      * needs to be large enough to hold the longest
   2383                      * line "Qx = <144 hex digits>\n".
   2384                      */
   2385    FILE *ecdsareq;  /* input stream from the REQUEST file */
   2386    FILE *ecdsaresp; /* output stream to the RESPONSE file */
   2387    char curve[16];  /* "nistxddd" */
   2388    ECParams *ecparams = NULL;
   2389    int N;
   2390    int i;
   2391    unsigned int len;
   2392 
   2393    ecdsareq = fopen(reqfn, "r");
   2394    ecdsaresp = stdout;
   2395    strcpy(curve, "nist");
   2396    while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
   2397        /* a comment or blank line */
   2398        if (buf[0] == '#' || buf[0] == '\n') {
   2399            fputs(buf, ecdsaresp);
   2400            continue;
   2401        }
   2402        /* [X-ddd] */
   2403        if (buf[0] == '[') {
   2404            const char *src;
   2405            char *dst;
   2406            SECItem *encodedparams;
   2407 
   2408            if (buf[1] == 'B') {
   2409                fputs(buf, ecdsaresp);
   2410                continue;
   2411            }
   2412            if (ecparams) {
   2413                PORT_FreeArena(ecparams->arena, PR_FALSE);
   2414                ecparams = NULL;
   2415            }
   2416 
   2417            src = &buf[1];
   2418            dst = &curve[4];
   2419            *dst++ = tolower((unsigned char)*src);
   2420            src += 2; /* skip the hyphen */
   2421            *dst++ = *src++;
   2422            *dst++ = *src++;
   2423            *dst++ = *src++;
   2424            *dst = '\0';
   2425            encodedparams = getECParams(curve);
   2426            if (encodedparams == NULL) {
   2427                fprintf(stderr, "Unknown curve %s.", curve);
   2428                goto loser;
   2429            }
   2430            if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
   2431                fprintf(stderr, "Curve %s not supported.\n", curve);
   2432                goto loser;
   2433            }
   2434            SECITEM_FreeItem(encodedparams, PR_TRUE);
   2435            fputs(buf, ecdsaresp);
   2436            continue;
   2437        }
   2438        /* N = x */
   2439        if (buf[0] == 'N') {
   2440            if (sscanf(buf, "N = %d", &N) != 1) {
   2441                goto loser;
   2442            }
   2443            for (i = 0; i < N; i++) {
   2444                ECPrivateKey *ecpriv;
   2445 
   2446                if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
   2447                    goto loser;
   2448                }
   2449                fputs("d = ", ecdsaresp);
   2450                to_hex_str(buf, ecpriv->privateValue.data,
   2451                           ecpriv->privateValue.len);
   2452                fputs(buf, ecdsaresp);
   2453                fputc('\n', ecdsaresp);
   2454                if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue) !=
   2455                    SECSuccess) {
   2456                    goto loser;
   2457                }
   2458                len = ecpriv->publicValue.len;
   2459                if (len % 2 == 0) {
   2460                    goto loser;
   2461                }
   2462                len = (len - 1) / 2;
   2463                if (ecpriv->publicValue.data[0] !=
   2464                    EC_POINT_FORM_UNCOMPRESSED) {
   2465                    goto loser;
   2466                }
   2467                fputs("Qx = ", ecdsaresp);
   2468                to_hex_str(buf, &ecpriv->publicValue.data[1], len);
   2469                fputs(buf, ecdsaresp);
   2470                fputc('\n', ecdsaresp);
   2471                fputs("Qy = ", ecdsaresp);
   2472                to_hex_str(buf, &ecpriv->publicValue.data[1 + len], len);
   2473                fputs(buf, ecdsaresp);
   2474                fputc('\n', ecdsaresp);
   2475                fputc('\n', ecdsaresp);
   2476                PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
   2477            }
   2478            continue;
   2479        }
   2480    }
   2481 loser:
   2482    if (ecparams) {
   2483        PORT_FreeArena(ecparams->arena, PR_FALSE);
   2484        ecparams = NULL;
   2485    }
   2486    fclose(ecdsareq);
   2487 }
   2488 
   2489 /*
   2490 * Perform the ECDSA Public Key Validation Test.
   2491 *
   2492 * reqfn is the pathname of the REQUEST file.
   2493 *
   2494 * The output RESPONSE file is written to stdout.
   2495 */
   2496 void
   2497 ecdsa_pkv_test(char *reqfn)
   2498 {
   2499    char buf[256];   /* holds one line from the input REQUEST file.
   2500                      * needs to be large enough to hold the longest
   2501                      * line "Qx = <144 hex digits>\n".
   2502                      */
   2503    FILE *ecdsareq;  /* input stream from the REQUEST file */
   2504    FILE *ecdsaresp; /* output stream to the RESPONSE file */
   2505    char curve[16];  /* "nistxddd" */
   2506    ECParams *ecparams = NULL;
   2507    SECItem pubkey;
   2508    unsigned int i;
   2509    unsigned int len = 0;
   2510    PRBool keyvalid = PR_TRUE;
   2511 
   2512    ecdsareq = fopen(reqfn, "r");
   2513    ecdsaresp = stdout;
   2514    strcpy(curve, "nist");
   2515    pubkey.data = NULL;
   2516    while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
   2517        /* a comment or blank line */
   2518        if (buf[0] == '#' || buf[0] == '\n') {
   2519            fputs(buf, ecdsaresp);
   2520            continue;
   2521        }
   2522        /* [X-ddd] */
   2523        if (buf[0] == '[') {
   2524            const char *src;
   2525            char *dst;
   2526            SECItem *encodedparams;
   2527 
   2528            src = &buf[1];
   2529            dst = &curve[4];
   2530            *dst++ = tolower((unsigned char)*src);
   2531            src += 2; /* skip the hyphen */
   2532            *dst++ = *src++;
   2533            *dst++ = *src++;
   2534            *dst++ = *src++;
   2535            *dst = '\0';
   2536            if (ecparams != NULL) {
   2537                PORT_FreeArena(ecparams->arena, PR_FALSE);
   2538                ecparams = NULL;
   2539            }
   2540            encodedparams = getECParams(curve);
   2541            if (encodedparams == NULL) {
   2542                fprintf(stderr, "Unknown curve %s.", curve);
   2543                goto loser;
   2544            }
   2545            if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
   2546                fprintf(stderr, "Curve %s not supported.\n", curve);
   2547                goto loser;
   2548            }
   2549            SECITEM_FreeItem(encodedparams, PR_TRUE);
   2550            len = (ecparams->fieldID.size + 7) >> 3;
   2551            if (pubkey.data != NULL) {
   2552                PORT_Free(pubkey.data);
   2553                pubkey.data = NULL;
   2554            }
   2555            SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(ecparams));
   2556            if (pubkey.data == NULL) {
   2557                goto loser;
   2558            }
   2559            pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
   2560            fputs(buf, ecdsaresp);
   2561            continue;
   2562        }
   2563        /* Qx = ... */
   2564        if (strncmp(buf, "Qx", 2) == 0) {
   2565            fputs(buf, ecdsaresp);
   2566            i = 2;
   2567            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   2568                i++;
   2569            }
   2570            keyvalid = from_hex_str(&pubkey.data[1], len, &buf[i]);
   2571            continue;
   2572        }
   2573        /* Qy = ... */
   2574        if (strncmp(buf, "Qy", 2) == 0) {
   2575            fputs(buf, ecdsaresp);
   2576            if (!keyvalid) {
   2577                fputs("Result = F\n", ecdsaresp);
   2578                continue;
   2579            }
   2580            i = 2;
   2581            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   2582                i++;
   2583            }
   2584            keyvalid = from_hex_str(&pubkey.data[1 + len], len, &buf[i]);
   2585            if (!keyvalid) {
   2586                fputs("Result = F\n", ecdsaresp);
   2587                continue;
   2588            }
   2589            if (EC_ValidatePublicKey(ecparams, &pubkey) == SECSuccess) {
   2590                fputs("Result = P\n", ecdsaresp);
   2591            } else if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
   2592                fputs("Result = F\n", ecdsaresp);
   2593            } else {
   2594                goto loser;
   2595            }
   2596            continue;
   2597        }
   2598    }
   2599 loser:
   2600    if (ecparams != NULL) {
   2601        PORT_FreeArena(ecparams->arena, PR_FALSE);
   2602    }
   2603    if (pubkey.data != NULL) {
   2604        PORT_Free(pubkey.data);
   2605    }
   2606    fclose(ecdsareq);
   2607 }
   2608 
   2609 /*
   2610 * Perform the ECDSA Signature Generation Test.
   2611 *
   2612 * reqfn is the pathname of the REQUEST file.
   2613 *
   2614 * The output RESPONSE file is written to stdout.
   2615 */
   2616 void
   2617 ecdsa_siggen_test(char *reqfn)
   2618 {
   2619    char buf[1024];  /* holds one line from the input REQUEST file
   2620                      * or to the output RESPONSE file.
   2621                      * needs to be large enough to hold the longest
   2622                      * line "Msg = <256 hex digits>\n".
   2623                      */
   2624    FILE *ecdsareq;  /* input stream from the REQUEST file */
   2625    FILE *ecdsaresp; /* output stream to the RESPONSE file */
   2626    char curve[16];  /* "nistxddd" */
   2627    ECParams *ecparams = NULL;
   2628    int i, j;
   2629    unsigned int len;
   2630    unsigned char msg[512]; /* message to be signed (<= 128 bytes) */
   2631    unsigned int msglen;
   2632    unsigned char sha[HASH_LENGTH_MAX];  /* SHA digest */
   2633    unsigned int shaLength = 0;          /* length of SHA */
   2634    HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
   2635    unsigned char sig[2 * MAX_ECKEY_LEN];
   2636    SECItem signature, digest;
   2637 
   2638    ecdsareq = fopen(reqfn, "r");
   2639    ecdsaresp = stdout;
   2640    strcpy(curve, "nist");
   2641    while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
   2642        /* a comment or blank line */
   2643        if (buf[0] == '#' || buf[0] == '\n') {
   2644            fputs(buf, ecdsaresp);
   2645            continue;
   2646        }
   2647        /* [X-ddd] */
   2648        if (buf[0] == '[') {
   2649            const char *src;
   2650            char *dst;
   2651            SECItem *encodedparams;
   2652 
   2653            src = &buf[1];
   2654            dst = &curve[4];
   2655            *dst++ = tolower((unsigned char)*src);
   2656            src += 2; /* skip the hyphen */
   2657            *dst++ = *src++;
   2658            *dst++ = *src++;
   2659            *dst++ = *src++;
   2660            *dst = '\0';
   2661            src++; /* skip the comma */
   2662            /* set the SHA Algorithm */
   2663            shaAlg = hash_string_to_hashType(src);
   2664            if (shaAlg == HASH_AlgNULL) {
   2665                fprintf(ecdsaresp, "ERROR: Unable to find SHAAlg type");
   2666                goto loser;
   2667            }
   2668            if (ecparams != NULL) {
   2669                PORT_FreeArena(ecparams->arena, PR_FALSE);
   2670                ecparams = NULL;
   2671            }
   2672            encodedparams = getECParams(curve);
   2673            if (encodedparams == NULL) {
   2674                fprintf(stderr, "Unknown curve %s.", curve);
   2675                goto loser;
   2676            }
   2677            if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
   2678                fprintf(stderr, "Curve %s not supported.\n", curve);
   2679                goto loser;
   2680            }
   2681            SECITEM_FreeItem(encodedparams, PR_TRUE);
   2682            fputs(buf, ecdsaresp);
   2683            continue;
   2684        }
   2685        /* Msg = ... */
   2686        if (strncmp(buf, "Msg", 3) == 0) {
   2687            ECPrivateKey *ecpriv;
   2688 
   2689            i = 3;
   2690            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   2691                i++;
   2692            }
   2693            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   2694                hex_to_byteval(&buf[i], &msg[j]);
   2695            }
   2696            msglen = j;
   2697            shaLength = fips_hashLen(shaAlg);
   2698            if (fips_hashBuf(shaAlg, sha, msg, msglen) != SECSuccess) {
   2699                if (shaLength == 0) {
   2700                    fprintf(ecdsaresp, "ERROR: SHAAlg not defined.");
   2701                }
   2702                fprintf(ecdsaresp, "ERROR: Unable to generate SHA%x",
   2703                        shaLength == 160 ? 1 : shaLength);
   2704                goto loser;
   2705            }
   2706            fputs(buf, ecdsaresp);
   2707 
   2708            if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
   2709                goto loser;
   2710            }
   2711            if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue) !=
   2712                SECSuccess) {
   2713                goto loser;
   2714            }
   2715            len = ecpriv->publicValue.len;
   2716            if (len % 2 == 0) {
   2717                goto loser;
   2718            }
   2719            len = (len - 1) / 2;
   2720            if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
   2721                goto loser;
   2722            }
   2723            fputs("Qx = ", ecdsaresp);
   2724            to_hex_str(buf, &ecpriv->publicValue.data[1], len);
   2725            fputs(buf, ecdsaresp);
   2726            fputc('\n', ecdsaresp);
   2727            fputs("Qy = ", ecdsaresp);
   2728            to_hex_str(buf, &ecpriv->publicValue.data[1 + len], len);
   2729            fputs(buf, ecdsaresp);
   2730            fputc('\n', ecdsaresp);
   2731 
   2732            digest.type = siBuffer;
   2733            digest.data = sha;
   2734            digest.len = shaLength;
   2735            signature.type = siBuffer;
   2736            signature.data = sig;
   2737            signature.len = sizeof sig;
   2738            if (ECDSA_SignDigest(ecpriv, &signature, &digest) != SECSuccess) {
   2739                goto loser;
   2740            }
   2741            len = signature.len;
   2742            if (len % 2 != 0) {
   2743                goto loser;
   2744            }
   2745            len = len / 2;
   2746            fputs("R = ", ecdsaresp);
   2747            to_hex_str(buf, &signature.data[0], len);
   2748            fputs(buf, ecdsaresp);
   2749            fputc('\n', ecdsaresp);
   2750            fputs("S = ", ecdsaresp);
   2751            to_hex_str(buf, &signature.data[len], len);
   2752            fputs(buf, ecdsaresp);
   2753            fputc('\n', ecdsaresp);
   2754 
   2755            PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
   2756            continue;
   2757        }
   2758    }
   2759 loser:
   2760    if (ecparams != NULL) {
   2761        PORT_FreeArena(ecparams->arena, PR_FALSE);
   2762    }
   2763    fclose(ecdsareq);
   2764 }
   2765 
   2766 /*
   2767 * Perform the ECDSA Signature Verification Test.
   2768 *
   2769 * reqfn is the pathname of the REQUEST file.
   2770 *
   2771 * The output RESPONSE file is written to stdout.
   2772 */
   2773 void
   2774 ecdsa_sigver_test(char *reqfn)
   2775 {
   2776    char buf[1024];  /* holds one line from the input REQUEST file.
   2777                      * needs to be large enough to hold the longest
   2778                      * line "Msg = <256 hex digits>\n".
   2779                      */
   2780    FILE *ecdsareq;  /* input stream from the REQUEST file */
   2781    FILE *ecdsaresp; /* output stream to the RESPONSE file */
   2782    char curve[16];  /* "nistxddd" */
   2783    ECPublicKey ecpub;
   2784    unsigned int i, j;
   2785    unsigned int flen = 0;  /* length in bytes of the field size */
   2786    unsigned int olen = 0;  /* length in bytes of the base point order */
   2787    unsigned char msg[512]; /* message that was signed (<= 128 bytes) */
   2788    unsigned int msglen = 0;
   2789    unsigned char sha[HASH_LENGTH_MAX];  /* SHA digest */
   2790    unsigned int shaLength = 0;          /* length of SHA */
   2791    HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
   2792    unsigned char sig[2 * MAX_ECKEY_LEN];
   2793    SECItem signature, digest;
   2794    PRBool keyvalid = PR_TRUE;
   2795    PRBool sigvalid = PR_TRUE;
   2796 
   2797    ecdsareq = fopen(reqfn, "r");
   2798    ecdsaresp = stdout;
   2799    ecpub.ecParams.arena = NULL;
   2800    strcpy(curve, "nist");
   2801    while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
   2802        /* a comment or blank line */
   2803        if (buf[0] == '#' || buf[0] == '\n') {
   2804            fputs(buf, ecdsaresp);
   2805            continue;
   2806        }
   2807        /* [X-ddd] */
   2808        if (buf[0] == '[') {
   2809            const char *src;
   2810            char *dst;
   2811            SECItem *encodedparams;
   2812            ECParams *ecparams;
   2813 
   2814            src = &buf[1];
   2815            dst = &curve[4];
   2816            *dst++ = tolower((unsigned char)*src);
   2817            src += 2; /* skip the hyphen */
   2818            *dst++ = *src++;
   2819            *dst++ = *src++;
   2820            *dst++ = *src++;
   2821            *dst = '\0';
   2822            src++; /* skip the comma */
   2823            /* set the SHA Algorithm */
   2824            shaAlg = hash_string_to_hashType(src);
   2825            if (shaAlg == HASH_AlgNULL) {
   2826                fprintf(ecdsaresp, "ERROR: Unable to find SHAAlg type");
   2827                goto loser;
   2828            }
   2829            encodedparams = getECParams(curve);
   2830            if (encodedparams == NULL) {
   2831                fprintf(stderr, "Unknown curve %s.", curve);
   2832                goto loser;
   2833            }
   2834            if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
   2835                fprintf(stderr, "Curve %s not supported.\n", curve);
   2836                goto loser;
   2837            }
   2838            SECITEM_FreeItem(encodedparams, PR_TRUE);
   2839            if (ecpub.ecParams.arena != NULL) {
   2840                PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
   2841            }
   2842            ecpub.ecParams.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   2843            if (ecpub.ecParams.arena == NULL) {
   2844                goto loser;
   2845            }
   2846            if (EC_CopyParams(ecpub.ecParams.arena, &ecpub.ecParams, ecparams) !=
   2847                SECSuccess) {
   2848                goto loser;
   2849            }
   2850            PORT_FreeArena(ecparams->arena, PR_FALSE);
   2851            flen = (ecpub.ecParams.fieldID.size + 7) >> 3;
   2852            olen = ecpub.ecParams.order.len;
   2853            if (2 * olen > sizeof sig) {
   2854                goto loser;
   2855            }
   2856            ecpub.publicValue.type = siBuffer;
   2857            ecpub.publicValue.data = NULL;
   2858            ecpub.publicValue.len = 0;
   2859            SECITEM_AllocItem(ecpub.ecParams.arena,
   2860                              &ecpub.publicValue, 2 * flen + 1);
   2861            if (ecpub.publicValue.data == NULL) {
   2862                goto loser;
   2863            }
   2864            ecpub.publicValue.data[0] = EC_POINT_FORM_UNCOMPRESSED;
   2865            fputs(buf, ecdsaresp);
   2866            continue;
   2867        }
   2868        /* Msg = ... */
   2869        if (strncmp(buf, "Msg", 3) == 0) {
   2870            i = 3;
   2871            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   2872                i++;
   2873            }
   2874            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   2875                hex_to_byteval(&buf[i], &msg[j]);
   2876            }
   2877            msglen = j;
   2878            shaLength = fips_hashLen(shaAlg);
   2879            if (fips_hashBuf(shaAlg, sha, msg, msglen) != SECSuccess) {
   2880                if (shaLength == 0) {
   2881                    fprintf(ecdsaresp, "ERROR: SHAAlg not defined.");
   2882                }
   2883                fprintf(ecdsaresp, "ERROR: Unable to generate SHA%x",
   2884                        shaLength == 160 ? 1 : shaLength);
   2885                goto loser;
   2886            }
   2887            fputs(buf, ecdsaresp);
   2888 
   2889            digest.type = siBuffer;
   2890            digest.data = sha;
   2891            digest.len = shaLength;
   2892 
   2893            continue;
   2894        }
   2895        /* Qx = ... */
   2896        if (strncmp(buf, "Qx", 2) == 0) {
   2897            fputs(buf, ecdsaresp);
   2898            i = 2;
   2899            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   2900                i++;
   2901            }
   2902            keyvalid = from_hex_str(&ecpub.publicValue.data[1], flen,
   2903                                    &buf[i]);
   2904            continue;
   2905        }
   2906        /* Qy = ... */
   2907        if (strncmp(buf, "Qy", 2) == 0) {
   2908            fputs(buf, ecdsaresp);
   2909            if (!keyvalid) {
   2910                continue;
   2911            }
   2912            i = 2;
   2913            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   2914                i++;
   2915            }
   2916            keyvalid = from_hex_str(&ecpub.publicValue.data[1 + flen], flen,
   2917                                    &buf[i]);
   2918            if (!keyvalid) {
   2919                continue;
   2920            }
   2921            if (EC_ValidatePublicKey(&ecpub.ecParams, &ecpub.publicValue) !=
   2922                SECSuccess) {
   2923                if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
   2924                    keyvalid = PR_FALSE;
   2925                } else {
   2926                    goto loser;
   2927                }
   2928            }
   2929            continue;
   2930        }
   2931        /* R = ... */
   2932        if (buf[0] == 'R') {
   2933            fputs(buf, ecdsaresp);
   2934            i = 1;
   2935            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   2936                i++;
   2937            }
   2938            sigvalid = from_hex_str(sig, olen, &buf[i]);
   2939            continue;
   2940        }
   2941        /* S = ... */
   2942        if (buf[0] == 'S') {
   2943            fputs(buf, ecdsaresp);
   2944            i = 1;
   2945            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   2946                i++;
   2947            }
   2948            if (sigvalid) {
   2949                sigvalid = from_hex_str(&sig[olen], olen, &buf[i]);
   2950            }
   2951            signature.type = siBuffer;
   2952            signature.data = sig;
   2953            signature.len = 2 * olen;
   2954 
   2955            if (!keyvalid || !sigvalid) {
   2956                fputs("Result = F\n", ecdsaresp);
   2957            } else if (ECDSA_VerifyDigest(&ecpub, &signature, &digest) ==
   2958                       SECSuccess) {
   2959                fputs("Result = P\n", ecdsaresp);
   2960            } else {
   2961                fputs("Result = F\n", ecdsaresp);
   2962            }
   2963            continue;
   2964        }
   2965    }
   2966 loser:
   2967    if (ecpub.ecParams.arena != NULL) {
   2968        PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
   2969    }
   2970    fclose(ecdsareq);
   2971 }
   2972 
   2973 /*
   2974 * Perform the ECDH Functional Test.
   2975 *
   2976 * reqfn is the pathname of the REQUEST file.
   2977 *
   2978 * The output RESPONSE file is written to stdout.
   2979 */
   2980 #define MAX_ECC_PARAMS 256
   2981 void
   2982 ecdh_functional(char *reqfn, PRBool response)
   2983 {
   2984    char buf[256];  /* holds one line from the input REQUEST file.
   2985                     * needs to be large enough to hold the longest
   2986                     * line "Qx = <144 hex digits>\n".
   2987                     */
   2988    FILE *ecdhreq;  /* input stream from the REQUEST file */
   2989    FILE *ecdhresp; /* output stream to the RESPONSE file */
   2990    char curve[16]; /* "nistxddd" */
   2991    unsigned char hashBuf[HASH_LENGTH_MAX];
   2992    ECParams *ecparams[MAX_ECC_PARAMS] = { NULL };
   2993    ECPrivateKey *ecpriv = NULL;
   2994    ECParams *current_ecparams = NULL;
   2995    SECItem pubkey;
   2996    SECItem ZZ;
   2997    unsigned int i;
   2998    unsigned int len = 0;
   2999    unsigned int uit_len = 0;
   3000    int current_curve = -1;
   3001    HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
   3002 
   3003    ecdhreq = fopen(reqfn, "r");
   3004    ecdhresp = stdout;
   3005    strcpy(curve, "nist");
   3006    pubkey.data = NULL;
   3007    while (fgets(buf, sizeof buf, ecdhreq) != NULL) {
   3008        /* a comment or blank line */
   3009        if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
   3010            fputs(buf, ecdhresp);
   3011            continue;
   3012        }
   3013        if (buf[0] == '[') {
   3014            /* [Ex] */
   3015            if (buf[1] == 'E' && buf[3] == ']') {
   3016                current_curve = buf[2] - 'A';
   3017                fputs(buf, ecdhresp);
   3018                continue;
   3019            }
   3020            /* [Curve selected: x-nnn */
   3021            if (strncmp(buf, "[Curve ", 7) == 0) {
   3022                const char *src;
   3023                char *dst;
   3024                SECItem *encodedparams;
   3025 
   3026                if ((current_curve < 0) || (current_curve > MAX_ECC_PARAMS)) {
   3027                    fprintf(stderr, "No curve type defined\n");
   3028                    goto loser;
   3029                }
   3030 
   3031                src = &buf[1];
   3032                /* skip passed the colon */
   3033                while (*src && *src != ':')
   3034                    src++;
   3035                if (*src != ':') {
   3036                    fprintf(stderr,
   3037                            "No colon in curve selected statement\n%s", buf);
   3038                    goto loser;
   3039                }
   3040                src++;
   3041                /* skip to the first non-space */
   3042                while (*src && *src == ' ')
   3043                    src++;
   3044                dst = &curve[4];
   3045                *dst++ = tolower((unsigned char)*src);
   3046                src += 2; /* skip the hyphen */
   3047                *dst++ = *src++;
   3048                *dst++ = *src++;
   3049                *dst++ = *src++;
   3050                *dst = '\0';
   3051                if (ecparams[current_curve] != NULL) {
   3052                    PORT_FreeArena(ecparams[current_curve]->arena, PR_FALSE);
   3053                    ecparams[current_curve] = NULL;
   3054                }
   3055                encodedparams = getECParams(curve);
   3056                if (encodedparams == NULL) {
   3057                    fprintf(stderr, "Unknown curve %s.", curve);
   3058                    goto loser;
   3059                }
   3060                if (EC_DecodeParams(encodedparams, &ecparams[current_curve]) != SECSuccess) {
   3061                    fprintf(stderr, "Curve %s not supported.\n", curve);
   3062                    goto loser;
   3063                }
   3064                SECITEM_FreeItem(encodedparams, PR_TRUE);
   3065                fputs(buf, ecdhresp);
   3066                continue;
   3067            }
   3068            /* [Ex - SHAxxx] */
   3069            if (buf[1] == 'E' && buf[3] == ' ') {
   3070                const char *src;
   3071                current_curve = buf[2] - 'A';
   3072                if ((current_curve < 0) || (current_curve > 256)) {
   3073                    fprintf(stderr, "bad curve type defined (%c)\n", buf[2]);
   3074                    goto loser;
   3075                }
   3076                current_ecparams = ecparams[current_curve];
   3077                if (current_ecparams == NULL) {
   3078                    fprintf(stderr, "no curve defined for type %c defined\n",
   3079                            buf[2]);
   3080                    goto loser;
   3081                }
   3082                /* skip passed the colon */
   3083                src = &buf[1];
   3084                while (*src && *src != '-')
   3085                    src++;
   3086                if (*src != '-') {
   3087                    fprintf(stderr,
   3088                            "No data in curve selected statement\n%s", buf);
   3089                    goto loser;
   3090                }
   3091                src++;
   3092                /* skip to the first non-space */
   3093                while (*src && *src == ' ')
   3094                    src++;
   3095                hash = hash_string_to_hashType(src);
   3096                if (hash == HASH_AlgNULL) {
   3097                    fprintf(ecdhresp, "ERROR: Unable to find SHAAlg type");
   3098                    goto loser;
   3099                }
   3100                fputs(buf, ecdhresp);
   3101                continue;
   3102            }
   3103            fputs(buf, ecdhresp);
   3104            continue;
   3105        }
   3106        /* COUNT = ... */
   3107        if (strncmp(buf, "COUNT", 5) == 0) {
   3108            fputs(buf, ecdhresp);
   3109            if (current_ecparams == NULL) {
   3110                fprintf(stderr, "no curve defined for type %c defined\n",
   3111                        buf[2]);
   3112                goto loser;
   3113            }
   3114            len = (current_ecparams->fieldID.size + 7) >> 3;
   3115            if (pubkey.data != NULL) {
   3116                PORT_Free(pubkey.data);
   3117                pubkey.data = NULL;
   3118            }
   3119            SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(current_ecparams));
   3120            if (pubkey.data == NULL) {
   3121                goto loser;
   3122            }
   3123            pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
   3124            continue;
   3125        }
   3126        /* QeCAVSx = ... */
   3127        if (strncmp(buf, "QeCAVSx", 7) == 0) {
   3128            fputs(buf, ecdhresp);
   3129            i = 7;
   3130            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   3131                i++;
   3132            }
   3133            from_hex_str(&pubkey.data[1], len, &buf[i]);
   3134            continue;
   3135        }
   3136        /* QeCAVSy = ... */
   3137        if (strncmp(buf, "QeCAVSy", 7) == 0) {
   3138            fputs(buf, ecdhresp);
   3139            i = 7;
   3140            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   3141                i++;
   3142            }
   3143            from_hex_str(&pubkey.data[1 + len], len, &buf[i]);
   3144            if (current_ecparams == NULL) {
   3145                fprintf(stderr, "no curve defined\n");
   3146                goto loser;
   3147            }
   3148            /* validate CAVS public key */
   3149            if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) {
   3150                fprintf(stderr, "BAD key detected\n");
   3151                goto loser;
   3152            }
   3153 
   3154            /* generate ECC key pair */
   3155            if (EC_NewKey(current_ecparams, &ecpriv) != SECSuccess) {
   3156                fprintf(stderr, "Failed to generate new key\n");
   3157                goto loser;
   3158            }
   3159            /* validate UIT generated public key */
   3160            if (EC_ValidatePublicKey(current_ecparams, &ecpriv->publicValue) !=
   3161                SECSuccess) {
   3162                fprintf(stderr, "generate key did not validate\n");
   3163                goto loser;
   3164            }
   3165            /* output UIT public key */
   3166            uit_len = ecpriv->publicValue.len;
   3167            if (uit_len % 2 == 0) {
   3168                fprintf(stderr, "generate key had invalid public value len\n");
   3169                goto loser;
   3170            }
   3171            uit_len = (uit_len - 1) / 2;
   3172            if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
   3173                fprintf(stderr, "generate key was compressed\n");
   3174                goto loser;
   3175            }
   3176            fputs("deIUT = ", ecdhresp);
   3177            to_hex_str(buf, ecpriv->privateValue.data, ecpriv->privateValue.len);
   3178            fputs(buf, ecdhresp);
   3179            fputc('\n', ecdhresp);
   3180            fputs("QeIUTx = ", ecdhresp);
   3181            to_hex_str(buf, &ecpriv->publicValue.data[1], uit_len);
   3182            fputs(buf, ecdhresp);
   3183            fputc('\n', ecdhresp);
   3184            fputs("QeIUTy = ", ecdhresp);
   3185            to_hex_str(buf, &ecpriv->publicValue.data[1 + uit_len], uit_len);
   3186            fputs(buf, ecdhresp);
   3187            fputc('\n', ecdhresp);
   3188            /* ECDH */
   3189            if (ECDH_Derive(&pubkey, current_ecparams, &ecpriv->privateValue,
   3190                            PR_FALSE, &ZZ) != SECSuccess) {
   3191                fprintf(stderr, "Derive failed\n");
   3192                goto loser;
   3193            }
   3194            /* output hash of ZZ */
   3195            if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
   3196                fprintf(stderr, "hash of derived key failed\n");
   3197                goto loser;
   3198            }
   3199            SECITEM_FreeItem(&ZZ, PR_FALSE);
   3200            fputs("HashZZ = ", ecdhresp);
   3201            to_hex_str(buf, hashBuf, fips_hashLen(hash));
   3202            fputs(buf, ecdhresp);
   3203            fputc('\n', ecdhresp);
   3204            fputc('\n', ecdhresp);
   3205            PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
   3206            ecpriv = NULL;
   3207            continue;
   3208        }
   3209    }
   3210 loser:
   3211    if (ecpriv != NULL) {
   3212        PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
   3213    }
   3214    for (i = 0; i < MAX_ECC_PARAMS; i++) {
   3215        if (ecparams[i] != NULL) {
   3216            PORT_FreeArena(ecparams[i]->arena, PR_FALSE);
   3217            ecparams[i] = NULL;
   3218        }
   3219    }
   3220    if (pubkey.data != NULL) {
   3221        PORT_Free(pubkey.data);
   3222    }
   3223    fclose(ecdhreq);
   3224 }
   3225 
   3226 /*
   3227 * Perform the ECDH Validity Test.
   3228 *
   3229 * reqfn is the pathname of the REQUEST file.
   3230 *
   3231 * The output RESPONSE file is written to stdout.
   3232 */
   3233 void
   3234 ecdh_verify(char *reqfn, PRBool response)
   3235 {
   3236    char buf[256];  /* holds one line from the input REQUEST file.
   3237                     * needs to be large enough to hold the longest
   3238                     * line "Qx = <144 hex digits>\n".
   3239                     */
   3240    FILE *ecdhreq;  /* input stream from the REQUEST file */
   3241    FILE *ecdhresp; /* output stream to the RESPONSE file */
   3242    char curve[16]; /* "nistxddd" */
   3243    unsigned char hashBuf[HASH_LENGTH_MAX];
   3244    unsigned char cavsHashBuf[HASH_LENGTH_MAX];
   3245    unsigned char private_data[MAX_ECKEY_LEN];
   3246    ECParams *ecparams[MAX_ECC_PARAMS] = { NULL };
   3247    ECParams *current_ecparams = NULL;
   3248    SECItem pubkey;
   3249    SECItem ZZ;
   3250    SECItem private_value;
   3251    unsigned int i;
   3252    unsigned int len = 0;
   3253    int current_curve = -1;
   3254    HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
   3255 
   3256    ecdhreq = fopen(reqfn, "r");
   3257    ecdhresp = stdout;
   3258    strcpy(curve, "nist");
   3259    pubkey.data = NULL;
   3260    while (fgets(buf, sizeof buf, ecdhreq) != NULL) {
   3261        /* a comment or blank line */
   3262        if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
   3263            fputs(buf, ecdhresp);
   3264            continue;
   3265        }
   3266        if (buf[0] == '[') {
   3267            /* [Ex] */
   3268            if (buf[1] == 'E' && buf[3] == ']') {
   3269                current_curve = buf[2] - 'A';
   3270                fputs(buf, ecdhresp);
   3271                continue;
   3272            }
   3273            /* [Curve selected: x-nnn */
   3274            if (strncmp(buf, "[Curve ", 7) == 0) {
   3275                const char *src;
   3276                char *dst;
   3277                SECItem *encodedparams;
   3278 
   3279                if ((current_curve < 0) || (current_curve > MAX_ECC_PARAMS)) {
   3280                    fprintf(stderr, "No curve type defined\n");
   3281                    goto loser;
   3282                }
   3283 
   3284                src = &buf[1];
   3285                /* skip passed the colon */
   3286                while (*src && *src != ':')
   3287                    src++;
   3288                if (*src != ':') {
   3289                    fprintf(stderr,
   3290                            "No colon in curve selected statement\n%s", buf);
   3291                    goto loser;
   3292                }
   3293                src++;
   3294                /* skip to the first non-space */
   3295                while (*src && *src == ' ')
   3296                    src++;
   3297                dst = &curve[4];
   3298                *dst++ = tolower((unsigned char)*src);
   3299                src += 2; /* skip the hyphen */
   3300                *dst++ = *src++;
   3301                *dst++ = *src++;
   3302                *dst++ = *src++;
   3303                *dst = '\0';
   3304                if (ecparams[current_curve] != NULL) {
   3305                    PORT_FreeArena(ecparams[current_curve]->arena, PR_FALSE);
   3306                    ecparams[current_curve] = NULL;
   3307                }
   3308                encodedparams = getECParams(curve);
   3309                if (encodedparams == NULL) {
   3310                    fprintf(stderr, "Unknown curve %s.\n", curve);
   3311                    goto loser;
   3312                }
   3313                if (EC_DecodeParams(encodedparams, &ecparams[current_curve]) != SECSuccess) {
   3314                    fprintf(stderr, "Curve %s not supported.\n", curve);
   3315                    goto loser;
   3316                }
   3317                SECITEM_FreeItem(encodedparams, PR_TRUE);
   3318                fputs(buf, ecdhresp);
   3319                continue;
   3320            }
   3321            /* [Ex - SHAxxx] */
   3322            if (buf[1] == 'E' && buf[3] == ' ') {
   3323                const char *src;
   3324                current_curve = buf[2] - 'A';
   3325                if ((current_curve < 0) || (current_curve > 256)) {
   3326                    fprintf(stderr, "bad curve type defined (%c)\n", buf[2]);
   3327                    goto loser;
   3328                }
   3329                current_ecparams = ecparams[current_curve];
   3330                if (current_ecparams == NULL) {
   3331                    fprintf(stderr, "no curve defined for type %c defined\n",
   3332                            buf[2]);
   3333                    goto loser;
   3334                }
   3335                /* skip passed the colon */
   3336                src = &buf[1];
   3337                while (*src && *src != '-')
   3338                    src++;
   3339                if (*src != '-') {
   3340                    fprintf(stderr,
   3341                            "No data in curve selected statement\n%s", buf);
   3342                    goto loser;
   3343                }
   3344                src++;
   3345                /* skip to the first non-space */
   3346                while (*src && *src == ' ')
   3347                    src++;
   3348                hash = hash_string_to_hashType(src);
   3349                if (hash == HASH_AlgNULL) {
   3350                    fprintf(ecdhresp, "ERROR: Unable to find SHAAlg type");
   3351                    goto loser;
   3352                }
   3353                fputs(buf, ecdhresp);
   3354                continue;
   3355            }
   3356            fputs(buf, ecdhresp);
   3357            continue;
   3358        }
   3359        /* COUNT = ... */
   3360        if (strncmp(buf, "COUNT", 5) == 0) {
   3361            fputs(buf, ecdhresp);
   3362            if (current_ecparams == NULL) {
   3363                fprintf(stderr, "no curve defined for type %c defined\n",
   3364                        buf[2]);
   3365                goto loser;
   3366            }
   3367            len = (current_ecparams->fieldID.size + 7) >> 3;
   3368            if (pubkey.data != NULL) {
   3369                PORT_Free(pubkey.data);
   3370                pubkey.data = NULL;
   3371            }
   3372            SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(current_ecparams));
   3373            if (pubkey.data == NULL) {
   3374                goto loser;
   3375            }
   3376            pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
   3377            continue;
   3378        }
   3379        /* QeCAVSx = ... */
   3380        if (strncmp(buf, "QeCAVSx", 7) == 0) {
   3381            fputs(buf, ecdhresp);
   3382            i = 7;
   3383            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   3384                i++;
   3385            }
   3386            from_hex_str(&pubkey.data[1], len, &buf[i]);
   3387            continue;
   3388        }
   3389        /* QeCAVSy = ... */
   3390        if (strncmp(buf, "QeCAVSy", 7) == 0) {
   3391            fputs(buf, ecdhresp);
   3392            i = 7;
   3393            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   3394                i++;
   3395            }
   3396            from_hex_str(&pubkey.data[1 + len], len, &buf[i]);
   3397            continue;
   3398        }
   3399        if (strncmp(buf, "deIUT", 5) == 0) {
   3400            fputs(buf, ecdhresp);
   3401            i = 5;
   3402            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   3403                i++;
   3404            }
   3405            from_hex_str(private_data, len, &buf[i]);
   3406            private_value.data = private_data;
   3407            private_value.len = len;
   3408            continue;
   3409        }
   3410        if (strncmp(buf, "QeIUTx", 6) == 0) {
   3411            fputs(buf, ecdhresp);
   3412            continue;
   3413        }
   3414        if (strncmp(buf, "QeIUTy", 6) == 0) {
   3415            fputs(buf, ecdhresp);
   3416            continue;
   3417        }
   3418        if ((strncmp(buf, "CAVSHashZZ", 10) == 0) ||
   3419            (strncmp(buf, "HashZZ", 6) == 0)) {
   3420            fputs(buf, ecdhresp);
   3421            i = (buf[0] == 'C') ? 10 : 6;
   3422            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   3423                i++;
   3424            }
   3425            from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]);
   3426            if (current_ecparams == NULL) {
   3427                fprintf(stderr, "no curve defined for type defined\n");
   3428                goto loser;
   3429            }
   3430            /* validate CAVS public key */
   3431            if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) {
   3432 #ifdef VERBOSE_REASON
   3433                fprintf(ecdhresp, "Result = F # key didn't validate\n");
   3434 #else
   3435                fprintf(ecdhresp, "Result = F\n");
   3436 #endif
   3437                continue;
   3438            }
   3439 
   3440            /* ECDH */
   3441            if (ECDH_Derive(&pubkey, current_ecparams, &private_value,
   3442                            PR_FALSE, &ZZ) != SECSuccess) {
   3443 #ifdef VERBOSE_REASON
   3444                fprintf(ecdhresp, "Result = F # derive failure\n");
   3445 #else
   3446                fprintf(ecdhresp, "Result = F\n");
   3447 #endif
   3448                continue;
   3449            }
   3450 /* output  ZZ */
   3451 #ifndef MATCH_OPENSSL
   3452            fputs("Z = ", ecdhresp);
   3453            to_hex_str(buf, ZZ.data, ZZ.len);
   3454            fputs(buf, ecdhresp);
   3455            fputc('\n', ecdhresp);
   3456 #endif
   3457 
   3458            if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
   3459                fprintf(stderr, "hash of derived key failed\n");
   3460                goto loser;
   3461            }
   3462            SECITEM_FreeItem(&ZZ, PR_FALSE);
   3463 #ifndef MATCH_NIST
   3464            fputs("IUTHashZZ = ", ecdhresp);
   3465            to_hex_str(buf, hashBuf, fips_hashLen(hash));
   3466            fputs(buf, ecdhresp);
   3467            fputc('\n', ecdhresp);
   3468 #endif
   3469            if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) {
   3470 #ifdef VERBOSE_REASON
   3471                fprintf(ecdhresp, "Result = F # hash doesn't match\n");
   3472 #else
   3473                fprintf(ecdhresp, "Result = F\n");
   3474 #endif
   3475            } else {
   3476                fprintf(ecdhresp, "Result = P\n");
   3477            }
   3478 #ifndef MATCH_OPENSSL
   3479            fputc('\n', ecdhresp);
   3480 #endif
   3481            continue;
   3482        }
   3483    }
   3484 loser:
   3485    for (i = 0; i < MAX_ECC_PARAMS; i++) {
   3486        if (ecparams[i] != NULL) {
   3487            PORT_FreeArena(ecparams[i]->arena, PR_FALSE);
   3488            ecparams[i] = NULL;
   3489        }
   3490    }
   3491    if (pubkey.data != NULL) {
   3492        PORT_Free(pubkey.data);
   3493    }
   3494    fclose(ecdhreq);
   3495 }
   3496 
   3497 /*
   3498 * Perform the DH Functional Test.
   3499 *
   3500 * reqfn is the pathname of the REQUEST file.
   3501 *
   3502 * The output RESPONSE file is written to stdout.
   3503 */
   3504 #define MAX_ECC_PARAMS 256
   3505 void
   3506 dh_functional(char *reqfn, PRBool response)
   3507 {
   3508    char buf[1024]; /* holds one line from the input REQUEST file.
   3509                     * needs to be large enough to hold the longest
   3510                     * line "YephCAVS = <512 hex digits>\n".
   3511                     */
   3512    FILE *dhreq;    /* input stream from the REQUEST file */
   3513    FILE *dhresp;   /* output stream to the RESPONSE file */
   3514    unsigned char hashBuf[HASH_LENGTH_MAX];
   3515    DSAPrivateKey *dsapriv = NULL;
   3516    PQGParams pqg = { 0 };
   3517    unsigned char pubkeydata[DSA_MAX_P_BITS / 8];
   3518    SECItem pubkey;
   3519    SECItem ZZ;
   3520    unsigned int i, j;
   3521    unsigned int pgySize;
   3522    HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
   3523 
   3524    dhreq = fopen(reqfn, "r");
   3525    dhresp = stdout;
   3526    while (fgets(buf, sizeof buf, dhreq) != NULL) {
   3527        /* a comment or blank line */
   3528        if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
   3529            fputs(buf, dhresp);
   3530            continue;
   3531        }
   3532        if (buf[0] == '[') {
   3533            /* [Fx - SHAxxx] */
   3534            if (buf[1] == 'F' && buf[3] == ' ') {
   3535                const char *src;
   3536                /* skip passed the colon */
   3537                src = &buf[1];
   3538                while (*src && *src != '-')
   3539                    src++;
   3540                if (*src != '-') {
   3541                    fprintf(stderr, "No hash specified\n%s", buf);
   3542                    goto loser;
   3543                }
   3544                src++;
   3545                /* skip to the first non-space */
   3546                while (*src && *src == ' ')
   3547                    src++;
   3548                hash = hash_string_to_hashType(src);
   3549                if (hash == HASH_AlgNULL) {
   3550                    fprintf(dhresp, "ERROR: Unable to find SHAAlg type");
   3551                    goto loser;
   3552                }
   3553                /* clear the PQG parameters */
   3554                if (pqg.prime.data) { /* P */
   3555                    SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
   3556                }
   3557                if (pqg.subPrime.data) { /* Q */
   3558                    SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
   3559                }
   3560                if (pqg.base.data) { /* G */
   3561                    SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
   3562                }
   3563                pgySize = DSA_MAX_P_BITS / 8; /* change if more key sizes are supported in CAVS */
   3564                SECITEM_AllocItem(NULL, &pqg.prime, pgySize);
   3565                SECITEM_AllocItem(NULL, &pqg.base, pgySize);
   3566                pqg.prime.len = pqg.base.len = pgySize;
   3567 
   3568                /* set q to the max allows */
   3569                SECITEM_AllocItem(NULL, &pqg.subPrime, DSA_MAX_Q_BITS / 8);
   3570                pqg.subPrime.len = DSA_MAX_Q_BITS / 8;
   3571                fputs(buf, dhresp);
   3572                continue;
   3573            }
   3574            fputs(buf, dhresp);
   3575            continue;
   3576        }
   3577        if (buf[0] == 'P') {
   3578            i = 1;
   3579            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   3580                i++;
   3581            }
   3582            for (j = 0; j < pqg.prime.len; i += 2, j++) {
   3583                if (!isxdigit((unsigned char)buf[i])) {
   3584                    pqg.prime.len = j;
   3585                    break;
   3586                }
   3587                hex_to_byteval(&buf[i], &pqg.prime.data[j]);
   3588            }
   3589 
   3590            fputs(buf, dhresp);
   3591            continue;
   3592        }
   3593 
   3594        /* Q = ... */
   3595        if (buf[0] == 'Q') {
   3596            i = 1;
   3597            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   3598                i++;
   3599            }
   3600            for (j = 0; j < pqg.subPrime.len; i += 2, j++) {
   3601                if (!isxdigit((unsigned char)buf[i])) {
   3602                    pqg.subPrime.len = j;
   3603                    break;
   3604                }
   3605                hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
   3606            }
   3607 
   3608            fputs(buf, dhresp);
   3609            continue;
   3610        }
   3611 
   3612        /* G = ... */
   3613        if (buf[0] == 'G') {
   3614            i = 1;
   3615            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   3616                i++;
   3617            }
   3618            for (j = 0; j < pqg.base.len; i += 2, j++) {
   3619                if (!isxdigit((unsigned char)buf[i])) {
   3620                    pqg.base.len = j;
   3621                    break;
   3622                }
   3623                hex_to_byteval(&buf[i], &pqg.base.data[j]);
   3624            }
   3625 
   3626            fputs(buf, dhresp);
   3627            continue;
   3628        }
   3629 
   3630        /* COUNT = ... */
   3631        if (strncmp(buf, "COUNT", 5) == 0) {
   3632            fputs(buf, dhresp);
   3633            continue;
   3634        }
   3635 
   3636        /* YephemCAVS = ... */
   3637        if (strncmp(buf, "YephemCAVS", 10) == 0) {
   3638            fputs(buf, dhresp);
   3639            i = 10;
   3640            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   3641                i++;
   3642            }
   3643            from_hex_str(pubkeydata, pqg.prime.len, &buf[i]);
   3644            pubkey.data = pubkeydata;
   3645            pubkey.len = pqg.prime.len;
   3646 
   3647            /* generate FCC key pair, nist uses pqg rather then pg,
   3648             * so use DSA to generate the key */
   3649            if (DSA_NewKey(&pqg, &dsapriv) != SECSuccess) {
   3650                fprintf(stderr, "Failed to generate new key\n");
   3651                goto loser;
   3652            }
   3653            fputs("XephemIUT = ", dhresp);
   3654            to_hex_str(buf, dsapriv->privateValue.data, dsapriv->privateValue.len);
   3655            fputs(buf, dhresp);
   3656            fputc('\n', dhresp);
   3657            fputs("YephemIUT = ", dhresp);
   3658            to_hex_str(buf, dsapriv->publicValue.data, dsapriv->publicValue.len);
   3659            fputs(buf, dhresp);
   3660            fputc('\n', dhresp);
   3661            /* DH */
   3662            if (DH_Derive(&pubkey, &pqg.prime, &dsapriv->privateValue,
   3663                          &ZZ, pqg.prime.len) != SECSuccess) {
   3664                fprintf(stderr, "Derive failed\n");
   3665                goto loser;
   3666            }
   3667            /* output hash of ZZ */
   3668            if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
   3669                fprintf(stderr, "hash of derived key failed\n");
   3670                goto loser;
   3671            }
   3672            SECITEM_FreeItem(&ZZ, PR_FALSE);
   3673            fputs("HashZZ = ", dhresp);
   3674            to_hex_str(buf, hashBuf, fips_hashLen(hash));
   3675            fputs(buf, dhresp);
   3676            fputc('\n', dhresp);
   3677            fputc('\n', dhresp);
   3678            PORT_FreeArena(dsapriv->params.arena, PR_TRUE);
   3679            dsapriv = NULL;
   3680            continue;
   3681        }
   3682    }
   3683 loser:
   3684    if (dsapriv != NULL) {
   3685        PORT_FreeArena(dsapriv->params.arena, PR_TRUE);
   3686    }
   3687    fclose(dhreq);
   3688 }
   3689 
   3690 /*
   3691 * Perform the DH Validity Test.
   3692 *
   3693 * reqfn is the pathname of the REQUEST file.
   3694 *
   3695 * The output RESPONSE file is written to stdout.
   3696 */
   3697 void
   3698 dh_verify(char *reqfn, PRBool response)
   3699 {
   3700    char buf[1024]; /* holds one line from the input REQUEST file.
   3701                     * needs to be large enough to hold the longest
   3702                     * line "YephCAVS = <512 hex digits>\n".
   3703                     */
   3704    FILE *dhreq;    /* input stream from the REQUEST file */
   3705    FILE *dhresp;   /* output stream to the RESPONSE file */
   3706    unsigned char hashBuf[HASH_LENGTH_MAX];
   3707    unsigned char cavsHashBuf[HASH_LENGTH_MAX];
   3708    PQGParams pqg = { 0 };
   3709    unsigned char pubkeydata[DSA_MAX_P_BITS / 8];
   3710    unsigned char privkeydata[DSA_MAX_P_BITS / 8];
   3711    SECItem pubkey;
   3712    SECItem privkey;
   3713    SECItem ZZ;
   3714    unsigned int i, j;
   3715    unsigned int pgySize;
   3716    HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
   3717 
   3718    dhreq = fopen(reqfn, "r");
   3719    dhresp = stdout;
   3720    while (fgets(buf, sizeof buf, dhreq) != NULL) {
   3721        /* a comment or blank line */
   3722        if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
   3723            fputs(buf, dhresp);
   3724            continue;
   3725        }
   3726        if (buf[0] == '[') {
   3727            /* [Fx - SHAxxx] */
   3728            if (buf[1] == 'F' && buf[3] == ' ') {
   3729                const char *src;
   3730                /* skip passed the colon */
   3731                src = &buf[1];
   3732                while (*src && *src != '-')
   3733                    src++;
   3734                if (*src != '-') {
   3735                    fprintf(stderr, "No hash specified\n%s", buf);
   3736                    goto loser;
   3737                }
   3738                src++;
   3739                /* skip to the first non-space */
   3740                while (*src && *src == ' ')
   3741                    src++;
   3742                hash = hash_string_to_hashType(src);
   3743                if (hash == HASH_AlgNULL) {
   3744                    fprintf(dhresp, "ERROR: Unable to find SHAAlg type");
   3745                    goto loser;
   3746                }
   3747                /* clear the PQG parameters */
   3748                if (pqg.prime.data) { /* P */
   3749                    SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
   3750                }
   3751                if (pqg.subPrime.data) { /* Q */
   3752                    SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
   3753                }
   3754                if (pqg.base.data) { /* G */
   3755                    SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
   3756                }
   3757                pgySize = DSA_MAX_P_BITS / 8; /* change if more key sizes are supported in CAVS */
   3758                SECITEM_AllocItem(NULL, &pqg.prime, pgySize);
   3759                SECITEM_AllocItem(NULL, &pqg.base, pgySize);
   3760                pqg.prime.len = pqg.base.len = pgySize;
   3761 
   3762                /* set q to the max allows */
   3763                SECITEM_AllocItem(NULL, &pqg.subPrime, DSA_MAX_Q_BITS / 8);
   3764                pqg.subPrime.len = DSA_MAX_Q_BITS / 8;
   3765                fputs(buf, dhresp);
   3766                continue;
   3767            }
   3768            fputs(buf, dhresp);
   3769            continue;
   3770        }
   3771        if (buf[0] == 'P') {
   3772            i = 1;
   3773            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   3774                i++;
   3775            }
   3776            for (j = 0; j < pqg.prime.len; i += 2, j++) {
   3777                if (!isxdigit((unsigned char)buf[i])) {
   3778                    pqg.prime.len = j;
   3779                    break;
   3780                }
   3781                hex_to_byteval(&buf[i], &pqg.prime.data[j]);
   3782            }
   3783 
   3784            fputs(buf, dhresp);
   3785            continue;
   3786        }
   3787 
   3788        /* Q = ... */
   3789        if (buf[0] == 'Q') {
   3790            i = 1;
   3791            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   3792                i++;
   3793            }
   3794            for (j = 0; j < pqg.subPrime.len; i += 2, j++) {
   3795                if (!isxdigit((unsigned char)buf[i])) {
   3796                    pqg.subPrime.len = j;
   3797                    break;
   3798                }
   3799                hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
   3800            }
   3801 
   3802            fputs(buf, dhresp);
   3803            continue;
   3804        }
   3805 
   3806        /* G = ... */
   3807        if (buf[0] == 'G') {
   3808            i = 1;
   3809            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   3810                i++;
   3811            }
   3812            for (j = 0; j < pqg.base.len; i += 2, j++) {
   3813                if (!isxdigit((unsigned char)buf[i])) {
   3814                    pqg.base.len = j;
   3815                    break;
   3816                }
   3817                hex_to_byteval(&buf[i], &pqg.base.data[j]);
   3818            }
   3819 
   3820            fputs(buf, dhresp);
   3821            continue;
   3822        }
   3823 
   3824        /* COUNT = ... */
   3825        if (strncmp(buf, "COUNT", 5) == 0) {
   3826            fputs(buf, dhresp);
   3827            continue;
   3828        }
   3829 
   3830        /* YephemCAVS = ... */
   3831        if (strncmp(buf, "YephemCAVS", 10) == 0) {
   3832            fputs(buf, dhresp);
   3833            i = 10;
   3834            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   3835                i++;
   3836            }
   3837            from_hex_str(pubkeydata, pqg.prime.len, &buf[i]);
   3838            pubkey.data = pubkeydata;
   3839            pubkey.len = pqg.prime.len;
   3840            continue;
   3841        }
   3842        /* XephemUIT = ... */
   3843        if (strncmp(buf, "XephemIUT", 9) == 0) {
   3844            fputs(buf, dhresp);
   3845            i = 9;
   3846            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   3847                i++;
   3848            }
   3849            from_hex_str(privkeydata, pqg.subPrime.len, &buf[i]);
   3850            privkey.data = privkeydata;
   3851            privkey.len = pqg.subPrime.len;
   3852            continue;
   3853        }
   3854        /* YephemUIT = ... */
   3855        if (strncmp(buf, "YephemIUT", 9) == 0) {
   3856            fputs(buf, dhresp);
   3857            continue;
   3858        }
   3859        /* CAVSHashZZ = ... */
   3860        if ((strncmp(buf, "CAVSHashZZ", 10) == 0) ||
   3861            (strncmp(buf, "HashZZ", 6) == 0)) {
   3862            fputs(buf, dhresp);
   3863            i = buf[0] == 'C' ? 10 : 6;
   3864            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   3865                i++;
   3866            }
   3867            from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]);
   3868            /* do the DH operation*/
   3869            if (DH_Derive(&pubkey, &pqg.prime, &privkey,
   3870                          &ZZ, pqg.prime.len) != SECSuccess) {
   3871                fprintf(stderr, "Derive failed\n");
   3872                goto loser;
   3873            }
   3874 /* output  ZZ */
   3875 #ifndef MATCH_OPENSSL
   3876            fputs("Z = ", dhresp);
   3877            to_hex_str(buf, ZZ.data, ZZ.len);
   3878            fputs(buf, dhresp);
   3879            fputc('\n', dhresp);
   3880 #endif
   3881            if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
   3882                fprintf(stderr, "hash of derived key failed\n");
   3883                goto loser;
   3884            }
   3885            SECITEM_FreeItem(&ZZ, PR_FALSE);
   3886 #ifndef MATCH_NIST
   3887            fputs("IUTHashZZ = ", dhresp);
   3888            to_hex_str(buf, hashBuf, fips_hashLen(hash));
   3889            fputs(buf, dhresp);
   3890            fputc('\n', dhresp);
   3891 #endif
   3892            if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) {
   3893                fprintf(dhresp, "Result = F\n");
   3894            } else {
   3895                fprintf(dhresp, "Result = P\n");
   3896            }
   3897 #ifndef MATCH_OPENSSL
   3898            fputc('\n', dhresp);
   3899 #endif
   3900            continue;
   3901        }
   3902    }
   3903 loser:
   3904    fclose(dhreq);
   3905 }
   3906 
   3907 PRBool
   3908 isblankline(char *b)
   3909 {
   3910    while (isspace((unsigned char)*b))
   3911        b++;
   3912    if ((*b == '\n') || (*b == 0)) {
   3913        return PR_TRUE;
   3914    }
   3915    return PR_FALSE;
   3916 }
   3917 
   3918 static int debug = 0;
   3919 
   3920 /*
   3921 * Perform the Hash_DRBG (CAVS) for the RNG algorithm
   3922 *
   3923 * reqfn is the pathname of the REQUEST file.
   3924 *
   3925 * The output RESPONSE file is written to stdout.
   3926 */
   3927 void
   3928 drbg(char *reqfn)
   3929 {
   3930    char buf[2000]; /* test case has some very long lines, returned bits
   3931                     * as high as 800 bytes (6400 bits). That 1600 byte
   3932                     * plus a tag */
   3933    char buf2[2000];
   3934    FILE *rngreq;  /* input stream from the REQUEST file */
   3935    FILE *rngresp; /* output stream to the RESPONSE file */
   3936 
   3937    unsigned int i, j;
   3938 #ifdef HANDLE_PREDICTION_RESISTANCE
   3939    PRBool predictionResistance = PR_FALSE;
   3940 #endif
   3941    unsigned char *nonce = NULL;
   3942    int nonceLen = 0;
   3943    unsigned char *personalizationString = NULL;
   3944    int personalizationStringLen = 0;
   3945    unsigned char *additionalInput = NULL;
   3946    int additionalInputLen = 0;
   3947    unsigned char *entropyInput = NULL;
   3948    int entropyInputLen = 0;
   3949    unsigned char *predictedreturn_bytes = NULL;
   3950    unsigned char *return_bytes = NULL;
   3951    int return_bytes_len = 0;
   3952    enum { NONE,
   3953           INSTANTIATE,
   3954           GENERATE,
   3955           RESEED,
   3956           RESULT } command =
   3957        NONE;
   3958    PRBool genResult = PR_FALSE;
   3959    SECStatus rv;
   3960 
   3961    rngreq = fopen(reqfn, "r");
   3962    rngresp = stdout;
   3963    while (fgets(buf, sizeof buf, rngreq) != NULL) {
   3964        switch (command) {
   3965            case INSTANTIATE:
   3966                if (debug) {
   3967                    fputs("# PRNGTEST_Instantiate(", rngresp);
   3968                    to_hex_str(buf2, entropyInput, entropyInputLen);
   3969                    fputs(buf2, rngresp);
   3970                    fprintf(rngresp, ",%d,", entropyInputLen);
   3971                    to_hex_str(buf2, nonce, nonceLen);
   3972                    fputs(buf2, rngresp);
   3973                    fprintf(rngresp, ",%d,", nonceLen);
   3974                    to_hex_str(buf2, personalizationString,
   3975                               personalizationStringLen);
   3976                    fputs(buf2, rngresp);
   3977                    fprintf(rngresp, ",%d)\n", personalizationStringLen);
   3978                }
   3979                rv = PRNGTEST_Instantiate(entropyInput, entropyInputLen,
   3980                                          nonce, nonceLen,
   3981                                          personalizationString,
   3982                                          personalizationStringLen);
   3983                if (rv != SECSuccess) {
   3984                    goto loser;
   3985                }
   3986                break;
   3987 
   3988            case GENERATE:
   3989            case RESULT:
   3990                memset(return_bytes, 0, return_bytes_len);
   3991                if (debug) {
   3992                    fputs("# PRNGTEST_Generate(returnbytes", rngresp);
   3993                    fprintf(rngresp, ",%d,", return_bytes_len);
   3994                    to_hex_str(buf2, additionalInput, additionalInputLen);
   3995                    fputs(buf2, rngresp);
   3996                    fprintf(rngresp, ",%d)\n", additionalInputLen);
   3997                }
   3998                rv = PRNGTEST_Generate((PRUint8 *)return_bytes,
   3999                                       return_bytes_len,
   4000                                       (PRUint8 *)additionalInput,
   4001                                       additionalInputLen);
   4002                if (rv != SECSuccess) {
   4003                    goto loser;
   4004                }
   4005 
   4006                if (command == RESULT) {
   4007                    fputs("ReturnedBits = ", rngresp);
   4008                    to_hex_str(buf2, return_bytes, return_bytes_len);
   4009                    fputs(buf2, rngresp);
   4010                    fputc('\n', rngresp);
   4011                    if (debug) {
   4012                        fputs("# PRNGTEST_Uninstantiate()\n", rngresp);
   4013                    }
   4014                    rv = PRNGTEST_Uninstantiate();
   4015                    if (rv != SECSuccess) {
   4016                        goto loser;
   4017                    }
   4018                } else if (debug) {
   4019                    fputs("#ReturnedBits = ", rngresp);
   4020                    to_hex_str(buf2, return_bytes, return_bytes_len);
   4021                    fputs(buf2, rngresp);
   4022                    fputc('\n', rngresp);
   4023                }
   4024 
   4025                memset(additionalInput, 0, additionalInputLen);
   4026                break;
   4027 
   4028            case RESEED:
   4029                if (entropyInput || additionalInput) {
   4030                    if (debug) {
   4031                        fputs("# PRNGTEST_Reseed(", rngresp);
   4032                        fprintf(rngresp, ",%d,", return_bytes_len);
   4033                        to_hex_str(buf2, entropyInput, entropyInputLen);
   4034                        fputs(buf2, rngresp);
   4035                        fprintf(rngresp, ",%d,", entropyInputLen);
   4036                        to_hex_str(buf2, additionalInput, additionalInputLen);
   4037                        fputs(buf2, rngresp);
   4038                        fprintf(rngresp, ",%d)\n", additionalInputLen);
   4039                    }
   4040                    rv = PRNGTEST_Reseed(entropyInput, entropyInputLen,
   4041                                         additionalInput, additionalInputLen);
   4042                    if (rv != SECSuccess) {
   4043                        goto loser;
   4044                    }
   4045                }
   4046                memset(entropyInput, 0, entropyInputLen);
   4047                memset(additionalInput, 0, additionalInputLen);
   4048                break;
   4049            case NONE:
   4050                break;
   4051        }
   4052        command = NONE;
   4053 
   4054        /* a comment or blank line */
   4055        if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
   4056            fputs(buf, rngresp);
   4057            continue;
   4058        }
   4059 
   4060        /* [Hash - SHA256] */
   4061        if (strncmp(buf, "[SHA-256]", 9) == 0) {
   4062            fputs(buf, rngresp);
   4063            continue;
   4064        }
   4065 
   4066        if (strncmp(buf, "[PredictionResistance", 21) == 0) {
   4067 #ifdef HANDLE_PREDICTION_RESISTANCE
   4068            i = 21;
   4069            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4070                i++;
   4071            }
   4072            if (strncmp(buf, "False", 5) == 0) {
   4073                predictionResistance = PR_FALSE;
   4074            } else {
   4075                predictionResistance = PR_TRUE;
   4076            }
   4077 #endif
   4078 
   4079            fputs(buf, rngresp);
   4080            continue;
   4081        }
   4082 
   4083        if (strncmp(buf, "[ReturnedBitsLen", 16) == 0) {
   4084            if (return_bytes) {
   4085                PORT_ZFree(return_bytes, return_bytes_len);
   4086                return_bytes = NULL;
   4087            }
   4088            if (predictedreturn_bytes) {
   4089                PORT_ZFree(predictedreturn_bytes, return_bytes_len);
   4090                predictedreturn_bytes = NULL;
   4091            }
   4092            return_bytes_len = 0;
   4093            if (sscanf(buf, "[ReturnedBitsLen = %d]", &return_bytes_len) != 1) {
   4094                goto loser;
   4095            }
   4096            return_bytes_len = return_bytes_len / 8;
   4097            if (return_bytes_len > 0) {
   4098                return_bytes = PORT_Alloc(return_bytes_len);
   4099                predictedreturn_bytes = PORT_Alloc(return_bytes_len);
   4100            }
   4101            fputs(buf, rngresp);
   4102            continue;
   4103        }
   4104 
   4105        if (strncmp(buf, "[EntropyInputLen", 16) == 0) {
   4106            if (entropyInput) {
   4107                PORT_ZFree(entropyInput, entropyInputLen);
   4108                entropyInput = NULL;
   4109                entropyInputLen = 0;
   4110            }
   4111            if (sscanf(buf, "[EntropyInputLen = %d]", &entropyInputLen) != 1) {
   4112                goto loser;
   4113            }
   4114            entropyInputLen = entropyInputLen / 8;
   4115            if (entropyInputLen > 0) {
   4116                entropyInput = PORT_Alloc(entropyInputLen);
   4117            }
   4118            fputs(buf, rngresp);
   4119            continue;
   4120        }
   4121 
   4122        if (strncmp(buf, "[NonceLen", 9) == 0) {
   4123            if (nonce) {
   4124                PORT_ZFree(nonce, nonceLen);
   4125                nonce = NULL;
   4126                nonceLen = 0;
   4127            }
   4128 
   4129            if (sscanf(buf, "[NonceLen = %d]", &nonceLen) != 1) {
   4130                goto loser;
   4131            }
   4132            nonceLen = nonceLen / 8;
   4133            if (nonceLen > 0) {
   4134                nonce = PORT_Alloc(nonceLen);
   4135            }
   4136            fputs(buf, rngresp);
   4137            continue;
   4138        }
   4139 
   4140        if (strncmp(buf, "[PersonalizationStringLen", 16) == 0) {
   4141            if (personalizationString) {
   4142                PORT_ZFree(personalizationString, personalizationStringLen);
   4143                personalizationString = NULL;
   4144                personalizationStringLen = 0;
   4145            }
   4146 
   4147            if (sscanf(buf, "[PersonalizationStringLen = %d]", &personalizationStringLen) != 1) {
   4148                goto loser;
   4149            }
   4150            personalizationStringLen = personalizationStringLen / 8;
   4151            if (personalizationStringLen > 0) {
   4152                personalizationString = PORT_Alloc(personalizationStringLen);
   4153            }
   4154            fputs(buf, rngresp);
   4155 
   4156            continue;
   4157        }
   4158 
   4159        if (strncmp(buf, "[AdditionalInputLen", 16) == 0) {
   4160            if (additionalInput) {
   4161                PORT_ZFree(additionalInput, additionalInputLen);
   4162                additionalInput = NULL;
   4163                additionalInputLen = 0;
   4164            }
   4165 
   4166            if (sscanf(buf, "[AdditionalInputLen = %d]", &additionalInputLen) != 1) {
   4167                goto loser;
   4168            }
   4169            additionalInputLen = additionalInputLen / 8;
   4170            if (additionalInputLen > 0) {
   4171                additionalInput = PORT_Alloc(additionalInputLen);
   4172            }
   4173            fputs(buf, rngresp);
   4174            continue;
   4175        }
   4176 
   4177        if (strncmp(buf, "COUNT", 5) == 0) {
   4178            /* zeroize the variables for the test with this data set */
   4179            if (entropyInput) {
   4180                memset(entropyInput, 0, entropyInputLen);
   4181            }
   4182            if (nonce) {
   4183                memset(nonce, 0, nonceLen);
   4184            }
   4185            if (personalizationString) {
   4186                memset(personalizationString, 0, personalizationStringLen);
   4187            }
   4188            if (additionalInput) {
   4189                memset(additionalInput, 0, additionalInputLen);
   4190            }
   4191            genResult = PR_FALSE;
   4192 
   4193            fputs(buf, rngresp);
   4194            continue;
   4195        }
   4196 
   4197        /* EntropyInputReseed = ... */
   4198        if (strncmp(buf, "EntropyInputReseed", 18) == 0) {
   4199            if (entropyInput) {
   4200                memset(entropyInput, 0, entropyInputLen);
   4201                i = 18;
   4202                while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4203                    i++;
   4204                }
   4205 
   4206                for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { /*j<entropyInputLen*/
   4207                    hex_to_byteval(&buf[i], &entropyInput[j]);
   4208                }
   4209            }
   4210            fputs(buf, rngresp);
   4211            continue;
   4212        }
   4213 
   4214        /* AttionalInputReseed  = ... */
   4215        if (strncmp(buf, "AdditionalInputReseed", 21) == 0) {
   4216            if (additionalInput) {
   4217                memset(additionalInput, 0, additionalInputLen);
   4218                i = 21;
   4219                while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4220                    i++;
   4221                }
   4222                for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { /*j<additionalInputLen*/
   4223                    hex_to_byteval(&buf[i], &additionalInput[j]);
   4224                }
   4225            }
   4226            command = RESEED;
   4227            fputs(buf, rngresp);
   4228            continue;
   4229        }
   4230 
   4231        /* Entropy input = ... */
   4232        if (strncmp(buf, "EntropyInput", 12) == 0) {
   4233            i = 12;
   4234            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4235                i++;
   4236            }
   4237            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { /*j<entropyInputLen*/
   4238                hex_to_byteval(&buf[i], &entropyInput[j]);
   4239            }
   4240            fputs(buf, rngresp);
   4241            continue;
   4242        }
   4243 
   4244        /* nouce = ... */
   4245        if (strncmp(buf, "Nonce", 5) == 0) {
   4246            i = 5;
   4247            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4248                i++;
   4249            }
   4250            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { /*j<nonceLen*/
   4251                hex_to_byteval(&buf[i], &nonce[j]);
   4252            }
   4253            fputs(buf, rngresp);
   4254            continue;
   4255        }
   4256 
   4257        /* Personalization string = ... */
   4258        if (strncmp(buf, "PersonalizationString", 21) == 0) {
   4259            if (personalizationString) {
   4260                i = 21;
   4261                while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4262                    i++;
   4263                }
   4264                for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { /*j<personalizationStringLen*/
   4265                    hex_to_byteval(&buf[i], &personalizationString[j]);
   4266                }
   4267            }
   4268            fputs(buf, rngresp);
   4269            command = INSTANTIATE;
   4270            continue;
   4271        }
   4272 
   4273        /* Additional input = ... */
   4274        if (strncmp(buf, "AdditionalInput", 15) == 0) {
   4275            if (additionalInput) {
   4276                i = 15;
   4277                while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4278                    i++;
   4279                }
   4280                for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { /*j<additionalInputLen*/
   4281                    hex_to_byteval(&buf[i], &additionalInput[j]);
   4282                }
   4283            }
   4284            if (genResult) {
   4285                command = RESULT;
   4286            } else {
   4287                command = GENERATE;
   4288                genResult = PR_TRUE; /* next time generate result */
   4289            }
   4290            fputs(buf, rngresp);
   4291            continue;
   4292        }
   4293 
   4294        /* Returned bits = ... */
   4295        if (strncmp(buf, "ReturnedBits", 12) == 0) {
   4296            i = 12;
   4297            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4298                i++;
   4299            }
   4300            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { /*j<additionalInputLen*/
   4301                hex_to_byteval(&buf[i], &predictedreturn_bytes[j]);
   4302            }
   4303 
   4304            if (memcmp(return_bytes,
   4305                       predictedreturn_bytes, return_bytes_len) != 0) {
   4306                if (debug) {
   4307                    fprintf(rngresp, "# Generate failed:\n");
   4308                    fputs("#   predicted=", rngresp);
   4309                    to_hex_str(buf, predictedreturn_bytes,
   4310                               return_bytes_len);
   4311                    fputs(buf, rngresp);
   4312                    fputs("\n#   actual  = ", rngresp);
   4313                    fputs(buf2, rngresp);
   4314                    fputc('\n', rngresp);
   4315 
   4316                } else {
   4317                    fprintf(stderr, "Generate failed:\n");
   4318                    fputs("   predicted=", stderr);
   4319                    to_hex_str(buf, predictedreturn_bytes,
   4320                               return_bytes_len);
   4321                    fputs(buf, stderr);
   4322                    fputs("\n   actual  = ", stderr);
   4323                    fputs(buf2, stderr);
   4324                    fputc('\n', stderr);
   4325                }
   4326            }
   4327            memset(predictedreturn_bytes, 0, return_bytes_len);
   4328 
   4329            continue;
   4330        }
   4331    }
   4332 loser:
   4333    if (predictedreturn_bytes) {
   4334        PORT_Free(predictedreturn_bytes);
   4335    }
   4336    if (return_bytes) {
   4337        PORT_Free(return_bytes);
   4338    }
   4339    if (additionalInput) {
   4340        PORT_Free(additionalInput);
   4341    }
   4342    if (personalizationString) {
   4343        PORT_Free(personalizationString);
   4344    }
   4345    if (nonce) {
   4346        PORT_Free(nonce);
   4347    }
   4348    if (entropyInput) {
   4349        PORT_Free(entropyInput);
   4350    }
   4351    fclose(rngreq);
   4352 }
   4353 
   4354 /*
   4355 * Perform the RNG Variable Seed Test (VST) for the RNG algorithm
   4356 * "DSA - Generation of X", used both as specified and as a generic
   4357 * purpose RNG.  The presence of "Q = ..." in the REQUEST file
   4358 * indicates we are using the algorithm as specified.
   4359 *
   4360 * reqfn is the pathname of the REQUEST file.
   4361 *
   4362 * The output RESPONSE file is written to stdout.
   4363 */
   4364 void
   4365 rng_vst(char *reqfn)
   4366 {
   4367    char buf[256]; /* holds one line from the input REQUEST file.
   4368                    * needs to be large enough to hold the longest
   4369                    * line "XSeed = <128 hex digits>\n".
   4370                    */
   4371    FILE *rngreq;  /* input stream from the REQUEST file */
   4372    FILE *rngresp; /* output stream to the RESPONSE file */
   4373    unsigned int i, j;
   4374    unsigned char Q[DSA1_SUBPRIME_LEN];
   4375    PRBool hasQ = PR_FALSE;
   4376    unsigned int b = 0; /* 160 <= b <= 512, b is a multiple of 8 */
   4377    unsigned char XKey[512 / 8];
   4378    unsigned char XSeed[512 / 8];
   4379    unsigned char GENX[DSA1_SIGNATURE_LEN];
   4380    unsigned char DSAX[DSA1_SUBPRIME_LEN];
   4381    SECStatus rv;
   4382 
   4383    rngreq = fopen(reqfn, "r");
   4384    rngresp = stdout;
   4385    while (fgets(buf, sizeof buf, rngreq) != NULL) {
   4386        /* a comment or blank line */
   4387        if (buf[0] == '#' || buf[0] == '\n') {
   4388            fputs(buf, rngresp);
   4389            continue;
   4390        }
   4391        /* [Xchange - SHA1] */
   4392        if (buf[0] == '[') {
   4393            fputs(buf, rngresp);
   4394            continue;
   4395        }
   4396        /* Q = ... */
   4397        if (buf[0] == 'Q') {
   4398            i = 1;
   4399            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4400                i++;
   4401            }
   4402            for (j = 0; j < sizeof Q; i += 2, j++) {
   4403                hex_to_byteval(&buf[i], &Q[j]);
   4404            }
   4405            fputs(buf, rngresp);
   4406            hasQ = PR_TRUE;
   4407            continue;
   4408        }
   4409        /* "COUNT = x" begins a new data set */
   4410        if (strncmp(buf, "COUNT", 5) == 0) {
   4411            /* zeroize the variables for the test with this data set */
   4412            b = 0;
   4413            memset(XKey, 0, sizeof XKey);
   4414            memset(XSeed, 0, sizeof XSeed);
   4415            fputs(buf, rngresp);
   4416            continue;
   4417        }
   4418        /* b = ... */
   4419        if (buf[0] == 'b') {
   4420            i = 1;
   4421            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4422                i++;
   4423            }
   4424            b = atoi(&buf[i]);
   4425            if (b < 160 || b > 512 || b % 8 != 0) {
   4426                goto loser;
   4427            }
   4428            fputs(buf, rngresp);
   4429            continue;
   4430        }
   4431        /* XKey = ... */
   4432        if (strncmp(buf, "XKey", 4) == 0) {
   4433            i = 4;
   4434            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4435                i++;
   4436            }
   4437            for (j = 0; j < b / 8; i += 2, j++) {
   4438                hex_to_byteval(&buf[i], &XKey[j]);
   4439            }
   4440            fputs(buf, rngresp);
   4441            continue;
   4442        }
   4443        /* XSeed = ... */
   4444        if (strncmp(buf, "XSeed", 5) == 0) {
   4445            i = 5;
   4446            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4447                i++;
   4448            }
   4449            for (j = 0; j < b / 8; i += 2, j++) {
   4450                hex_to_byteval(&buf[i], &XSeed[j]);
   4451            }
   4452            fputs(buf, rngresp);
   4453 
   4454            rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
   4455            if (rv != SECSuccess) {
   4456                goto loser;
   4457            }
   4458            fputs("X = ", rngresp);
   4459            if (hasQ) {
   4460                rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
   4461                if (rv != SECSuccess) {
   4462                    goto loser;
   4463                }
   4464                to_hex_str(buf, DSAX, sizeof DSAX);
   4465            } else {
   4466                to_hex_str(buf, GENX, sizeof GENX);
   4467            }
   4468            fputs(buf, rngresp);
   4469            fputc('\n', rngresp);
   4470            continue;
   4471        }
   4472    }
   4473 loser:
   4474    fclose(rngreq);
   4475 }
   4476 
   4477 /*
   4478 * Perform the RNG Monte Carlo Test (MCT) for the RNG algorithm
   4479 * "DSA - Generation of X", used both as specified and as a generic
   4480 * purpose RNG.  The presence of "Q = ..." in the REQUEST file
   4481 * indicates we are using the algorithm as specified.
   4482 *
   4483 * reqfn is the pathname of the REQUEST file.
   4484 *
   4485 * The output RESPONSE file is written to stdout.
   4486 */
   4487 void
   4488 rng_mct(char *reqfn)
   4489 {
   4490    char buf[256]; /* holds one line from the input REQUEST file.
   4491                    * needs to be large enough to hold the longest
   4492                    * line "XSeed = <128 hex digits>\n".
   4493                    */
   4494    FILE *rngreq;  /* input stream from the REQUEST file */
   4495    FILE *rngresp; /* output stream to the RESPONSE file */
   4496    unsigned int i, j;
   4497    unsigned char Q[DSA1_SUBPRIME_LEN];
   4498    PRBool hasQ = PR_FALSE;
   4499    unsigned int b = 0; /* 160 <= b <= 512, b is a multiple of 8 */
   4500    unsigned char XKey[512 / 8];
   4501    unsigned char XSeed[512 / 8];
   4502    unsigned char GENX[2 * SHA1_LENGTH];
   4503    unsigned char DSAX[DSA1_SUBPRIME_LEN];
   4504    SECStatus rv;
   4505 
   4506    rngreq = fopen(reqfn, "r");
   4507    rngresp = stdout;
   4508    while (fgets(buf, sizeof buf, rngreq) != NULL) {
   4509        /* a comment or blank line */
   4510        if (buf[0] == '#' || buf[0] == '\n') {
   4511            fputs(buf, rngresp);
   4512            continue;
   4513        }
   4514        /* [Xchange - SHA1] */
   4515        if (buf[0] == '[') {
   4516            fputs(buf, rngresp);
   4517            continue;
   4518        }
   4519        /* Q = ... */
   4520        if (buf[0] == 'Q') {
   4521            i = 1;
   4522            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4523                i++;
   4524            }
   4525            for (j = 0; j < sizeof Q; i += 2, j++) {
   4526                hex_to_byteval(&buf[i], &Q[j]);
   4527            }
   4528            fputs(buf, rngresp);
   4529            hasQ = PR_TRUE;
   4530            continue;
   4531        }
   4532        /* "COUNT = x" begins a new data set */
   4533        if (strncmp(buf, "COUNT", 5) == 0) {
   4534            /* zeroize the variables for the test with this data set */
   4535            b = 0;
   4536            memset(XKey, 0, sizeof XKey);
   4537            memset(XSeed, 0, sizeof XSeed);
   4538            fputs(buf, rngresp);
   4539            continue;
   4540        }
   4541        /* b = ... */
   4542        if (buf[0] == 'b') {
   4543            i = 1;
   4544            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4545                i++;
   4546            }
   4547            b = atoi(&buf[i]);
   4548            if (b < 160 || b > 512 || b % 8 != 0) {
   4549                goto loser;
   4550            }
   4551            fputs(buf, rngresp);
   4552            continue;
   4553        }
   4554        /* XKey = ... */
   4555        if (strncmp(buf, "XKey", 4) == 0) {
   4556            i = 4;
   4557            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4558                i++;
   4559            }
   4560            for (j = 0; j < b / 8; i += 2, j++) {
   4561                hex_to_byteval(&buf[i], &XKey[j]);
   4562            }
   4563            fputs(buf, rngresp);
   4564            continue;
   4565        }
   4566        /* XSeed = ... */
   4567        if (strncmp(buf, "XSeed", 5) == 0) {
   4568            unsigned int k;
   4569            i = 5;
   4570            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4571                i++;
   4572            }
   4573            for (j = 0; j < b / 8; i += 2, j++) {
   4574                hex_to_byteval(&buf[i], &XSeed[j]);
   4575            }
   4576            fputs(buf, rngresp);
   4577 
   4578            for (k = 0; k < 10000; k++) {
   4579                rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
   4580                if (rv != SECSuccess) {
   4581                    goto loser;
   4582                }
   4583            }
   4584            fputs("X = ", rngresp);
   4585            if (hasQ) {
   4586                rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
   4587                if (rv != SECSuccess) {
   4588                    goto loser;
   4589                }
   4590                to_hex_str(buf, DSAX, sizeof DSAX);
   4591            } else {
   4592                to_hex_str(buf, GENX, sizeof GENX);
   4593            }
   4594            fputs(buf, rngresp);
   4595            fputc('\n', rngresp);
   4596            continue;
   4597        }
   4598    }
   4599 loser:
   4600    fclose(rngreq);
   4601 }
   4602 
   4603 /*
   4604 * Calculate the SHA Message Digest
   4605 *
   4606 * MD = Message digest
   4607 * MDLen = length of Message Digest and SHA_Type
   4608 * msg = message to digest
   4609 * msgLen = length of message to digest
   4610 */
   4611 SECStatus
   4612 sha_calcMD(unsigned char *MD, unsigned int MDLen, unsigned char *msg, unsigned int msgLen)
   4613 {
   4614    HASH_HashType hashType = sha_get_hashType(MDLen * PR_BITS_PER_BYTE);
   4615 
   4616    return fips_hashBuf(hashType, MD, msg, msgLen);
   4617 }
   4618 
   4619 /*
   4620 * Perform the SHA Monte Carlo Test
   4621 *
   4622 * MDLen = length of Message Digest and SHA_Type
   4623 * seed = input seed value
   4624 * resp = is the output response file.
   4625 */
   4626 SECStatus
   4627 sha_mct_test(unsigned int MDLen, unsigned char *seed, FILE *resp)
   4628 {
   4629    int i, j;
   4630    unsigned int msgLen = MDLen * 3;
   4631    unsigned char MD_i3[HASH_LENGTH_MAX]; /* MD[i-3] */
   4632    unsigned char MD_i2[HASH_LENGTH_MAX]; /* MD[i-2] */
   4633    unsigned char MD_i1[HASH_LENGTH_MAX]; /* MD[i-1] */
   4634    unsigned char MD_i[HASH_LENGTH_MAX];  /* MD[i] */
   4635    unsigned char msg[HASH_LENGTH_MAX * 3];
   4636    char buf[HASH_LENGTH_MAX * 2 + 1]; /* MAX buf MD_i as a hex string */
   4637 
   4638    for (j = 0; j < 100; j++) {
   4639        /* MD_0 = MD_1 = MD_2 = seed */
   4640        memcpy(MD_i3, seed, MDLen);
   4641        memcpy(MD_i2, seed, MDLen);
   4642        memcpy(MD_i1, seed, MDLen);
   4643 
   4644        for (i = 3; i < 1003; i++) {
   4645            /* Mi = MD[i-3] || MD [i-2] || MD [i-1] */
   4646            memcpy(msg, MD_i3, MDLen);
   4647            memcpy(&msg[MDLen], MD_i2, MDLen);
   4648            memcpy(&msg[MDLen * 2], MD_i1, MDLen);
   4649 
   4650            /* MDi = SHA(Msg) */
   4651            if (sha_calcMD(MD_i, MDLen,
   4652                           msg, msgLen) != SECSuccess) {
   4653                return SECFailure;
   4654            }
   4655 
   4656            /* save MD[i-3] MD[i-2]  MD[i-1] */
   4657            memcpy(MD_i3, MD_i2, MDLen);
   4658            memcpy(MD_i2, MD_i1, MDLen);
   4659            memcpy(MD_i1, MD_i, MDLen);
   4660        }
   4661 
   4662        /* seed = MD_i */
   4663        memcpy(seed, MD_i, MDLen);
   4664 
   4665        snprintf(buf, sizeof(buf), "COUNT = %d\n", j);
   4666        fputs(buf, resp);
   4667 
   4668        /* output MD_i */
   4669        fputs("MD = ", resp);
   4670        to_hex_str(buf, MD_i, MDLen);
   4671        fputs(buf, resp);
   4672        fputc('\n', resp);
   4673    }
   4674 
   4675    return SECSuccess;
   4676 }
   4677 
   4678 /*
   4679 * Perform the SHA Tests.
   4680 *
   4681 * reqfn is the pathname of the input REQUEST file.
   4682 *
   4683 * The output RESPONSE file is written to stdout.
   4684 */
   4685 void
   4686 sha_test(char *reqfn)
   4687 {
   4688    unsigned int i, j;
   4689    unsigned int MDlen = 0;              /* the length of the Message Digest in Bytes  */
   4690    unsigned int msgLen = 0;             /* the length of the input Message in Bytes */
   4691    unsigned char *msg = NULL;           /* holds the message to digest.*/
   4692    size_t bufSize = 256 * 128;          /*MAX buffer size */
   4693    char *buf = NULL;                    /* holds one line from the input REQUEST file.*/
   4694    unsigned char seed[HASH_LENGTH_MAX]; /* max size of seed 64 bytes */
   4695    unsigned char MD[HASH_LENGTH_MAX];   /* message digest */
   4696 
   4697    FILE *req = NULL; /* input stream from the REQUEST file */
   4698    FILE *resp;       /* output stream to the RESPONSE file */
   4699 
   4700    buf = PORT_ZAlloc(bufSize);
   4701    if (buf == NULL) {
   4702        goto loser;
   4703    }
   4704 
   4705    /* zeroize the variables for the test with this data set */
   4706    memset(seed, 0, sizeof seed);
   4707 
   4708    req = fopen(reqfn, "r");
   4709    resp = stdout;
   4710    while (fgets(buf, bufSize, req) != NULL) {
   4711 
   4712        /* a comment or blank line */
   4713        if (buf[0] == '#' || buf[0] == '\n') {
   4714            fputs(buf, resp);
   4715            continue;
   4716        }
   4717        /* [L = Length of the Message Digest and sha_type */
   4718        if (buf[0] == '[') {
   4719            if (strncmp(&buf[1], "L ", 1) == 0) {
   4720                i = 2;
   4721                while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4722                    i++;
   4723                }
   4724                MDlen = atoi(&buf[i]);
   4725                fputs(buf, resp);
   4726                continue;
   4727            }
   4728        }
   4729        /* Len = Length of the Input Message Length  ... */
   4730        if (strncmp(buf, "Len", 3) == 0) {
   4731            i = 3;
   4732            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4733                i++;
   4734            }
   4735            if (msg) {
   4736                PORT_ZFree(msg, msgLen);
   4737                msg = NULL;
   4738            }
   4739            msgLen = atoi(&buf[i]); /* in bits */
   4740            if (msgLen % 8 != 0) {
   4741                fprintf(stderr, "SHA tests are incorrectly configured for "
   4742                                "BIT oriented implementations\n");
   4743                goto loser;
   4744            }
   4745            msgLen = msgLen / 8; /* convert to bytes */
   4746            fputs(buf, resp);
   4747            msg = PORT_ZAlloc(msgLen);
   4748            if (msg == NULL && msgLen != 0) {
   4749                goto loser;
   4750            }
   4751            continue;
   4752        }
   4753        /* MSG = ... */
   4754        if (strncmp(buf, "Msg", 3) == 0) {
   4755            i = 3;
   4756            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4757                i++;
   4758            }
   4759            for (j = 0; j < msgLen; i += 2, j++) {
   4760                hex_to_byteval(&buf[i], &msg[j]);
   4761            }
   4762            fputs(buf, resp);
   4763            /* calculate the Message Digest */
   4764            memset(MD, 0, sizeof MD);
   4765            if (sha_calcMD(MD, MDlen,
   4766                           msg, msgLen) != SECSuccess) {
   4767                goto loser;
   4768            }
   4769 
   4770            fputs("MD = ", resp);
   4771            to_hex_str(buf, MD, MDlen);
   4772            fputs(buf, resp);
   4773            fputc('\n', resp);
   4774 
   4775            continue;
   4776        }
   4777        /* Seed = ... */
   4778        if (strncmp(buf, "Seed", 4) == 0) {
   4779            i = 4;
   4780            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4781                i++;
   4782            }
   4783            for (j = 0; j < sizeof seed; i += 2, j++) {
   4784                hex_to_byteval(&buf[i], &seed[j]);
   4785            }
   4786 
   4787            fputs(buf, resp);
   4788            fputc('\n', resp);
   4789 
   4790            /* do the Monte Carlo test */
   4791            if (sha_mct_test(MDlen, seed, resp) != SECSuccess) {
   4792                goto loser;
   4793            }
   4794 
   4795            continue;
   4796        }
   4797    }
   4798 loser:
   4799    if (req) {
   4800        fclose(req);
   4801    }
   4802    if (buf) {
   4803        PORT_ZFree(buf, bufSize);
   4804    }
   4805    if (msg) {
   4806        PORT_ZFree(msg, msgLen);
   4807    }
   4808 }
   4809 
   4810 /****************************************************/
   4811 /* HMAC SHA-X calc                                  */
   4812 /* hmac_computed - the computed HMAC                */
   4813 /* hmac_length - the length of the computed HMAC    */
   4814 /* secret_key - secret key to HMAC                  */
   4815 /* secret_key_length - length of secret key,        */
   4816 /* message - message to HMAC                        */
   4817 /* message_length - length ofthe message            */
   4818 /****************************************************/
   4819 static SECStatus
   4820 hmac_calc(unsigned char *hmac_computed,
   4821          const unsigned int hmac_length,
   4822          const unsigned char *secret_key,
   4823          const unsigned int secret_key_length,
   4824          const unsigned char *message,
   4825          const unsigned int message_length,
   4826          const HASH_HashType hashAlg)
   4827 {
   4828    SECStatus hmac_status = SECFailure;
   4829    HMACContext *cx = NULL;
   4830    SECHashObject *hashObj = NULL;
   4831    unsigned int bytes_hashed = 0;
   4832 
   4833    hashObj = (SECHashObject *)HASH_GetRawHashObject(hashAlg);
   4834 
   4835    if (!hashObj)
   4836        return (SECFailure);
   4837 
   4838    cx = HMAC_Create(hashObj, secret_key,
   4839                     secret_key_length,
   4840                     PR_TRUE); /* PR_TRUE for in FIPS mode */
   4841 
   4842    if (cx == NULL)
   4843        return (SECFailure);
   4844 
   4845    HMAC_Begin(cx);
   4846    HMAC_Update(cx, message, message_length);
   4847    hmac_status = HMAC_Finish(cx, hmac_computed, &bytes_hashed,
   4848                              hmac_length);
   4849 
   4850    HMAC_Destroy(cx, PR_TRUE);
   4851 
   4852    return (hmac_status);
   4853 }
   4854 
   4855 /*
   4856 * Perform the HMAC Tests.
   4857 *
   4858 * reqfn is the pathname of the input REQUEST file.
   4859 *
   4860 * The output RESPONSE file is written to stdout.
   4861 */
   4862 void
   4863 hmac_test(char *reqfn)
   4864 {
   4865    unsigned int i, j;
   4866    size_t bufSize = 400;                        /* MAX buffer size */
   4867    char *buf = NULL;                            /* holds one line from the input REQUEST file.*/
   4868    unsigned int keyLen = 0;                     /* Key Length */
   4869    unsigned char key[200];                      /* key MAX size = 184 */
   4870    unsigned int msgLen = 128;                   /* the length of the input  */
   4871                                                 /*  Message is always 128 Bytes */
   4872    unsigned char *msg = NULL;                   /* holds the message to digest.*/
   4873    unsigned int HMACLen = 0;                    /* the length of the HMAC Bytes  */
   4874    unsigned int TLen = 0;                       /* the length of the requested */
   4875                                                 /* truncated HMAC Bytes */
   4876    unsigned char HMAC[HASH_LENGTH_MAX];         /* computed HMAC */
   4877    unsigned char expectedHMAC[HASH_LENGTH_MAX]; /* for .fax files that have */
   4878                                                 /* supplied known answer */
   4879    HASH_HashType hash_alg = HASH_AlgNULL;       /* HMAC type */
   4880 
   4881    FILE *req = NULL; /* input stream from the REQUEST file */
   4882    FILE *resp;       /* output stream to the RESPONSE file */
   4883 
   4884    buf = PORT_ZAlloc(bufSize);
   4885    if (buf == NULL) {
   4886        goto loser;
   4887    }
   4888    msg = PORT_ZAlloc(msgLen);
   4889    if (msg == NULL) {
   4890        goto loser;
   4891    }
   4892 
   4893    req = fopen(reqfn, "r");
   4894    resp = stdout;
   4895    while (fgets(buf, bufSize, req) != NULL) {
   4896        if (strncmp(buf, "Mac", 3) == 0) {
   4897            i = 3;
   4898            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4899                i++;
   4900            }
   4901            memset(expectedHMAC, 0, HASH_LENGTH_MAX);
   4902            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   4903                hex_to_byteval(&buf[i], &expectedHMAC[j]);
   4904            }
   4905            if (memcmp(HMAC, expectedHMAC, TLen) != 0) {
   4906                fprintf(stderr, "Generate failed:\n");
   4907                fputs("   expected=", stderr);
   4908                to_hex_str(buf, expectedHMAC,
   4909                           TLen);
   4910                fputs(buf, stderr);
   4911                fputs("\n   generated=", stderr);
   4912                to_hex_str(buf, HMAC,
   4913                           TLen);
   4914                fputs(buf, stderr);
   4915                fputc('\n', stderr);
   4916            }
   4917        }
   4918 
   4919        /* a comment or blank line */
   4920        if (buf[0] == '#' || buf[0] == '\n') {
   4921            fputs(buf, resp);
   4922            continue;
   4923        }
   4924        /* [L = Length of the MAC and HASH_type */
   4925        if (buf[0] == '[') {
   4926            if (strncmp(&buf[1], "L ", 1) == 0) {
   4927                i = 2;
   4928                while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4929                    i++;
   4930                }
   4931                /* HMACLen will get reused for Tlen */
   4932                HMACLen = atoi(&buf[i]);
   4933                hash_alg = sha_get_hashType(HMACLen * PR_BITS_PER_BYTE);
   4934                if (hash_alg == HASH_AlgNULL) {
   4935                    goto loser;
   4936                }
   4937                fputs(buf, resp);
   4938                continue;
   4939            }
   4940        }
   4941        /* Count = test iteration number*/
   4942        if (strncmp(buf, "Count ", 5) == 0) {
   4943            /* count can just be put into resp file */
   4944            fputs(buf, resp);
   4945            /* zeroize the variables for the test with this data set */
   4946            keyLen = 0;
   4947            TLen = 0;
   4948            memset(key, 0, sizeof key);
   4949            memset(msg, 0, msgLen);
   4950            memset(HMAC, 0, sizeof HMAC);
   4951            continue;
   4952        }
   4953        /* KLen = Length of the Input Secret Key ... */
   4954        if (strncmp(buf, "Klen", 4) == 0) {
   4955            i = 4;
   4956            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4957                i++;
   4958            }
   4959            keyLen = atoi(&buf[i]); /* in bytes */
   4960            fputs(buf, resp);
   4961            continue;
   4962        }
   4963        /* key = the secret key for the key to MAC */
   4964        if (strncmp(buf, "Key", 3) == 0) {
   4965            i = 3;
   4966            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4967                i++;
   4968            }
   4969            for (j = 0; j < keyLen; i += 2, j++) {
   4970                hex_to_byteval(&buf[i], &key[j]);
   4971            }
   4972            fputs(buf, resp);
   4973        }
   4974        /* TLen = Length of the calculated HMAC */
   4975        if (strncmp(buf, "Tlen", 4) == 0) {
   4976            i = 4;
   4977            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4978                i++;
   4979            }
   4980            TLen = atoi(&buf[i]); /* in bytes */
   4981            fputs(buf, resp);
   4982            continue;
   4983        }
   4984        /* MSG = to HMAC always 128 bytes for these tests */
   4985        if (strncmp(buf, "Msg", 3) == 0) {
   4986            i = 3;
   4987            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   4988                i++;
   4989            }
   4990            for (j = 0; j < msgLen; i += 2, j++) {
   4991                hex_to_byteval(&buf[i], &msg[j]);
   4992            }
   4993            fputs(buf, resp);
   4994            /* calculate the HMAC and output */
   4995            if (hmac_calc(HMAC, HMACLen, key, keyLen,
   4996                          msg, msgLen, hash_alg) != SECSuccess) {
   4997                goto loser;
   4998            }
   4999            fputs("Mac = ", resp);
   5000            to_hex_str(buf, HMAC, TLen);
   5001            fputs(buf, resp);
   5002            fputc('\n', resp);
   5003            continue;
   5004        }
   5005    }
   5006 loser:
   5007    if (req) {
   5008        fclose(req);
   5009    }
   5010    if (buf) {
   5011        PORT_ZFree(buf, bufSize);
   5012    }
   5013    if (msg) {
   5014        PORT_ZFree(msg, msgLen);
   5015    }
   5016 }
   5017 
   5018 /*
   5019 * Perform the DSA Key Pair Generation Test.
   5020 *
   5021 * reqfn is the pathname of the REQUEST file.
   5022 *
   5023 * The output RESPONSE file is written to stdout.
   5024 */
   5025 void
   5026 dsa_keypair_test(char *reqfn)
   5027 {
   5028    char buf[800]; /* holds one line from the input REQUEST file
   5029                    * or to the output RESPONSE file.
   5030                    * 800 to hold (384 public key (x2 for HEX) + 1'\n'
   5031                    */
   5032    FILE *dsareq;  /* input stream from the REQUEST file */
   5033    FILE *dsaresp; /* output stream to the RESPONSE file */
   5034    int count;
   5035    int N;
   5036    int L;
   5037    int i;
   5038    PQGParams *pqg = NULL;
   5039    PQGVerify *vfy = NULL;
   5040    PRBool use_dsa1 = PR_FALSE;
   5041    int keySizeIndex; /* index for valid key sizes */
   5042 
   5043    dsareq = fopen(reqfn, "r");
   5044    dsaresp = stdout;
   5045    while (fgets(buf, sizeof buf, dsareq) != NULL) {
   5046        /* a comment or blank line */
   5047        if (buf[0] == '#' || buf[0] == '\n') {
   5048            fputs(buf, dsaresp);
   5049            continue;
   5050        }
   5051 
   5052        /* [Mod = x] */
   5053        if (buf[0] == '[') {
   5054            if (pqg != NULL) {
   5055                PQG_DestroyParams(pqg);
   5056                pqg = NULL;
   5057            }
   5058            if (vfy != NULL) {
   5059                PQG_DestroyVerify(vfy);
   5060                vfy = NULL;
   5061            }
   5062 
   5063            if (sscanf(buf, "[mod = L=%d, N=%d]", &L, &N) != 2) {
   5064                use_dsa1 = PR_TRUE;
   5065                if (sscanf(buf, "[mod = %d]", &L) != 1) {
   5066                    goto loser;
   5067                }
   5068            }
   5069            fputs(buf, dsaresp);
   5070            fputc('\n', dsaresp);
   5071 
   5072            if (use_dsa1) {
   5073                /*************************************************************
   5074                 * PQG_ParamGenSeedLen doesn't take a key size, it takes an
   5075                 * index that points to a valid key size.
   5076                 */
   5077                keySizeIndex = PQG_PBITS_TO_INDEX(L);
   5078                if (keySizeIndex == -1 || L < 512 || L > 1024) {
   5079                    fprintf(dsaresp,
   5080                            "DSA key size must be a multiple of 64 between 512 "
   5081                            "and 1024, inclusive");
   5082                    goto loser;
   5083                }
   5084 
   5085                /* Generate the parameters P, Q, and G */
   5086                if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
   5087                                        &pqg, &vfy) !=
   5088                    SECSuccess) {
   5089                    fprintf(dsaresp,
   5090                            "ERROR: Unable to generate PQG parameters");
   5091                    goto loser;
   5092                }
   5093            } else {
   5094                if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) {
   5095                    fprintf(dsaresp,
   5096                            "ERROR: Unable to generate PQG parameters");
   5097                    goto loser;
   5098                }
   5099            }
   5100 
   5101            /* output P, Q, and G */
   5102            to_hex_str(buf, pqg->prime.data, pqg->prime.len);
   5103            fprintf(dsaresp, "P = %s\n", buf);
   5104            to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
   5105            fprintf(dsaresp, "Q = %s\n", buf);
   5106            to_hex_str(buf, pqg->base.data, pqg->base.len);
   5107            fprintf(dsaresp, "G = %s\n\n", buf);
   5108            continue;
   5109        }
   5110        /* N = ...*/
   5111        if (buf[0] == 'N') {
   5112 
   5113            if (sscanf(buf, "N = %d", &count) != 1) {
   5114                goto loser;
   5115            }
   5116            /* Generate a DSA key, and output the key pair for N times */
   5117            for (i = 0; i < count; i++) {
   5118                DSAPrivateKey *dsakey = NULL;
   5119                if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
   5120                    fprintf(dsaresp, "ERROR: Unable to generate DSA key");
   5121                    goto loser;
   5122                }
   5123                to_hex_str(buf, dsakey->privateValue.data,
   5124                           dsakey->privateValue.len);
   5125                fprintf(dsaresp, "X = %s\n", buf);
   5126                to_hex_str(buf, dsakey->publicValue.data,
   5127                           dsakey->publicValue.len);
   5128                fprintf(dsaresp, "Y = %s\n\n", buf);
   5129                PORT_FreeArena(dsakey->params.arena, PR_TRUE);
   5130                dsakey = NULL;
   5131            }
   5132            continue;
   5133        }
   5134    }
   5135 loser:
   5136    fclose(dsareq);
   5137 }
   5138 
   5139 /*
   5140 * pqg generation type
   5141 */
   5142 typedef enum {
   5143    FIPS186_1, /* Generate/Verify P,Q & G  according to FIPS 186-1 */
   5144    A_1_2_1,   /* Generate Provable P & Q */
   5145    A_1_1_3,   /* Verify Probable P & Q */
   5146    A_1_2_2,   /* Verify Provable P & Q */
   5147    A_2_1,     /* Generate Unverifiable G */
   5148    A_2_2,     /* Assure Unverifiable G */
   5149    A_2_3,     /* Generate Verifiable G */
   5150    A_2_4      /* Verify Verifiable G */
   5151 } dsa_pqg_type;
   5152 
   5153 /*
   5154 * Perform the DSA Domain Parameter Validation Test.
   5155 *
   5156 * reqfn is the pathname of the REQUEST file.
   5157 *
   5158 * The output RESPONSE file is written to stdout.
   5159 */
   5160 void
   5161 dsa_pqgver_test(char *reqfn)
   5162 {
   5163    char buf[800]; /* holds one line from the input REQUEST file
   5164                    * or to the output RESPONSE file.
   5165                    * 800 to hold (384 public key (x2 for HEX) + P = ...
   5166                    */
   5167    FILE *dsareq;  /* input stream from the REQUEST file */
   5168    FILE *dsaresp; /* output stream to the RESPONSE file */
   5169    int N;
   5170    int L;
   5171    unsigned int i, j;
   5172    PQGParams pqg;
   5173    PQGVerify vfy;
   5174    unsigned int pghSize = 0; /* size for p, g, and h */
   5175    dsa_pqg_type type = FIPS186_1;
   5176 
   5177    dsareq = fopen(reqfn, "r");
   5178    dsaresp = stdout;
   5179    memset(&pqg, 0, sizeof(pqg));
   5180    memset(&vfy, 0, sizeof(vfy));
   5181 
   5182    while (fgets(buf, sizeof buf, dsareq) != NULL) {
   5183        /* a comment or blank line */
   5184        if (buf[0] == '#' || buf[0] == '\n') {
   5185            fputs(buf, dsaresp);
   5186            continue;
   5187        }
   5188 
   5189        /* [A.xxxxx ] */
   5190        if (buf[0] == '[' && buf[1] == 'A') {
   5191 
   5192            if (strncmp(&buf[1], "A.1.1.3", 7) == 0) {
   5193                type = A_1_1_3;
   5194            } else if (strncmp(&buf[1], "A.2.2", 5) == 0) {
   5195                type = A_2_2;
   5196            } else if (strncmp(&buf[1], "A.2.4", 5) == 0) {
   5197                type = A_2_4;
   5198            } else if (strncmp(&buf[1], "A.1.2.2", 7) == 0) {
   5199                type = A_1_2_2;
   5200                /* validate our output from PQGGEN */
   5201            } else if (strncmp(&buf[1], "A.1.1.2", 7) == 0) {
   5202                type = A_2_4; /* validate PQ and G together */
   5203            } else {
   5204                fprintf(stderr, "Unknown dsa ver test %s\n", &buf[1]);
   5205                exit(1);
   5206            }
   5207 
   5208            fputs(buf, dsaresp);
   5209            continue;
   5210        }
   5211 
   5212        /* [Mod = x] */
   5213        if (buf[0] == '[') {
   5214 
   5215            if (type == FIPS186_1) {
   5216                N = 160;
   5217                if (sscanf(buf, "[mod = %d]", &L) != 1) {
   5218                    goto loser;
   5219                }
   5220            } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) {
   5221                goto loser;
   5222            }
   5223 
   5224            if (pqg.prime.data) { /* P */
   5225                SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
   5226            }
   5227            if (pqg.subPrime.data) { /* Q */
   5228                SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
   5229            }
   5230            if (pqg.base.data) { /* G */
   5231                SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
   5232            }
   5233            if (vfy.seed.data) { /* seed */
   5234                SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
   5235            }
   5236            if (vfy.h.data) { /* H */
   5237                SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
   5238            }
   5239 
   5240            fputs(buf, dsaresp);
   5241 
   5242            /*calculate the size of p, g, and h then allocate items  */
   5243            pghSize = L / 8;
   5244 
   5245            pqg.base.data = vfy.h.data = NULL;
   5246            vfy.seed.len = pqg.base.len = vfy.h.len = 0;
   5247            SECITEM_AllocItem(NULL, &pqg.prime, pghSize);
   5248            SECITEM_AllocItem(NULL, &vfy.seed, pghSize * 3);
   5249            if (type == A_2_2) {
   5250                SECITEM_AllocItem(NULL, &vfy.h, pghSize);
   5251                vfy.h.len = pghSize;
   5252            } else if (type == A_2_4) {
   5253                SECITEM_AllocItem(NULL, &vfy.h, 1);
   5254                vfy.h.len = 1;
   5255            }
   5256            pqg.prime.len = pghSize;
   5257            /* q is always N bits */
   5258            SECITEM_AllocItem(NULL, &pqg.subPrime, N / 8);
   5259            pqg.subPrime.len = N / 8;
   5260            vfy.counter = -1;
   5261 
   5262            continue;
   5263        }
   5264        /* P = ... */
   5265        if (buf[0] == 'P') {
   5266            i = 1;
   5267            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   5268                i++;
   5269            }
   5270            for (j = 0; j < pqg.prime.len; i += 2, j++) {
   5271                hex_to_byteval(&buf[i], &pqg.prime.data[j]);
   5272            }
   5273 
   5274            fputs(buf, dsaresp);
   5275            continue;
   5276        }
   5277 
   5278        /* Q = ... */
   5279        if (buf[0] == 'Q') {
   5280            i = 1;
   5281            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   5282                i++;
   5283            }
   5284            for (j = 0; j < pqg.subPrime.len; i += 2, j++) {
   5285                hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
   5286            }
   5287 
   5288            fputs(buf, dsaresp);
   5289            continue;
   5290        }
   5291 
   5292        /* G = ... */
   5293        if (buf[0] == 'G') {
   5294            i = 1;
   5295            if (pqg.base.data) {
   5296                SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
   5297            }
   5298            SECITEM_AllocItem(NULL, &pqg.base, pghSize);
   5299            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   5300                i++;
   5301            }
   5302            for (j = 0; j < pqg.base.len; i += 2, j++) {
   5303                hex_to_byteval(&buf[i], &pqg.base.data[j]);
   5304            }
   5305 
   5306            fputs(buf, dsaresp);
   5307            continue;
   5308        }
   5309 
   5310        /* Seed = ...  or domain_parameter_seed = ... */
   5311        if (strncmp(buf, "Seed", 4) == 0) {
   5312            i = 4;
   5313        } else if (strncmp(buf, "domain_parameter_seed", 21) == 0) {
   5314            i = 21;
   5315        } else if (strncmp(buf, "firstseed", 9) == 0) {
   5316            i = 9;
   5317        } else {
   5318            i = 0;
   5319        }
   5320        if (i) {
   5321            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   5322                i++;
   5323            }
   5324            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   5325                hex_to_byteval(&buf[i], &vfy.seed.data[j]);
   5326            }
   5327            vfy.seed.len = j;
   5328 
   5329            fputs(buf, dsaresp);
   5330            if (type == A_2_4) {
   5331                SECStatus result;
   5332 
   5333                /* Verify the Parameters */
   5334                SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
   5335                if (rv != SECSuccess) {
   5336                    goto loser;
   5337                }
   5338                if (result == SECSuccess) {
   5339                    fprintf(dsaresp, "Result = P\n");
   5340                } else {
   5341                    fprintf(dsaresp, "Result = F\n");
   5342                }
   5343            }
   5344            continue;
   5345        }
   5346        if ((strncmp(buf, "pseed", 5) == 0) ||
   5347            (strncmp(buf, "qseed", 5) == 0)) {
   5348            i = 5;
   5349            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   5350                i++;
   5351            }
   5352            for (j = vfy.seed.len; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   5353                hex_to_byteval(&buf[i], &vfy.seed.data[j]);
   5354            }
   5355            vfy.seed.len = j;
   5356            fputs(buf, dsaresp);
   5357 
   5358            continue;
   5359        }
   5360        if (strncmp(buf, "index", 4) == 0) {
   5361            i = 5;
   5362            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   5363                i++;
   5364            }
   5365            hex_to_byteval(&buf[i], &vfy.h.data[0]);
   5366            vfy.h.len = 1;
   5367            fputs(buf, dsaresp);
   5368        }
   5369 
   5370        /* c = ...  or counter=*/
   5371        if (buf[0] == 'c') {
   5372            if (strncmp(buf, "counter", 7) == 0) {
   5373                if (sscanf(buf, "counter = %u", &vfy.counter) != 1) {
   5374                    goto loser;
   5375                }
   5376            } else {
   5377                if (sscanf(buf, "c = %u", &vfy.counter) != 1) {
   5378                    goto loser;
   5379                }
   5380            }
   5381 
   5382            fputs(buf, dsaresp);
   5383            if (type == A_1_1_3) {
   5384                SECStatus result;
   5385                /* only verify P and Q, we have everything now. do it */
   5386                SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
   5387                if (rv != SECSuccess) {
   5388                    goto loser;
   5389                }
   5390                if (result == SECSuccess) {
   5391                    fprintf(dsaresp, "Result = P\n");
   5392                } else {
   5393                    fprintf(dsaresp, "Result = F\n");
   5394                }
   5395                fprintf(dsaresp, "\n");
   5396            }
   5397            continue;
   5398        }
   5399        if (strncmp(buf, "pgen_counter", 12) == 0) {
   5400            if (sscanf(buf, "pgen_counter = %u", &vfy.counter) != 1) {
   5401                goto loser;
   5402            }
   5403            fputs(buf, dsaresp);
   5404            continue;
   5405        }
   5406        if (strncmp(buf, "qgen_counter", 12) == 0) {
   5407            fputs(buf, dsaresp);
   5408            if (type == A_1_2_2) {
   5409                SECStatus result;
   5410                /* only verify P and Q, we have everything now. do it */
   5411                SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
   5412                if (rv != SECSuccess) {
   5413                    goto loser;
   5414                }
   5415                if (result == SECSuccess) {
   5416                    fprintf(dsaresp, "Result = P\n");
   5417                } else {
   5418                    fprintf(dsaresp, "Result = F\n");
   5419                }
   5420                fprintf(dsaresp, "\n");
   5421            }
   5422            continue;
   5423        }
   5424        /* H = ... */
   5425        if (buf[0] == 'H') {
   5426            SECStatus rv, result = SECFailure;
   5427 
   5428            i = 1;
   5429            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   5430                i++;
   5431            }
   5432            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   5433                hex_to_byteval(&buf[i], &vfy.h.data[j]);
   5434            }
   5435            vfy.h.len = j;
   5436            fputs(buf, dsaresp);
   5437 
   5438            /* this should be a byte value. Remove the leading zeros. If
   5439             * it doesn't reduce to a byte, PQG_VerifyParams will catch it
   5440            if (type == A_2_2) {
   5441                data_save = vfy.h.data;
   5442                while(vfy.h.data[0] && (vfy.h.len > 1)) {
   5443                        vfy.h.data++;
   5444                        vfy.h.len--;
   5445                }
   5446            } */
   5447 
   5448            /* Verify the Parameters */
   5449            rv = PQG_VerifyParams(&pqg, &vfy, &result);
   5450            if (rv != SECSuccess) {
   5451                goto loser;
   5452            }
   5453            if (result == SECSuccess) {
   5454                fprintf(dsaresp, "Result = P\n");
   5455            } else {
   5456                fprintf(dsaresp, "Result = F\n");
   5457            }
   5458            fprintf(dsaresp, "\n");
   5459            continue;
   5460        }
   5461    }
   5462 loser:
   5463    fclose(dsareq);
   5464    if (pqg.prime.data) { /* P */
   5465        SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
   5466    }
   5467    if (pqg.subPrime.data) { /* Q */
   5468        SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
   5469    }
   5470    if (pqg.base.data) { /* G */
   5471        SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
   5472    }
   5473    if (vfy.seed.data) { /* seed */
   5474        SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
   5475    }
   5476    if (vfy.h.data) { /* H */
   5477        SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
   5478    }
   5479 }
   5480 
   5481 /*
   5482 * Perform the DSA Public Key Validation Test.
   5483 *
   5484 * reqfn is the pathname of the REQUEST file.
   5485 *
   5486 * The output RESPONSE file is written to stdout.
   5487 */
   5488 void
   5489 dsa_pqggen_test(char *reqfn)
   5490 {
   5491    char buf[800]; /* holds one line from the input REQUEST file
   5492                    * or to the output RESPONSE file.
   5493                    * 800 to hold seed = (384 public key (x2 for HEX)
   5494                    */
   5495    FILE *dsareq;  /* input stream from the REQUEST file */
   5496    FILE *dsaresp; /* output stream to the RESPONSE file */
   5497    int count;     /* number of times to generate parameters */
   5498    int N;
   5499    int L;
   5500    int i;
   5501    unsigned int j;
   5502    int output_g = 1;
   5503    PQGParams *pqg = NULL;
   5504    PQGVerify *vfy = NULL;
   5505    unsigned int keySizeIndex = 0;
   5506    dsa_pqg_type type = FIPS186_1;
   5507 
   5508    dsareq = fopen(reqfn, "r");
   5509    dsaresp = stdout;
   5510    while (fgets(buf, sizeof buf, dsareq) != NULL) {
   5511        /* a comment or blank line */
   5512        if (buf[0] == '#' || buf[0] == '\n') {
   5513            fputs(buf, dsaresp);
   5514            continue;
   5515        }
   5516 
   5517        /* [A.xxxxx ] */
   5518        if (buf[0] == '[' && buf[1] == 'A') {
   5519            if (strncmp(&buf[1], "A.1.1.2", 7) == 0) {
   5520                fprintf(stderr, "NSS does Generate Probablistic Primes\n");
   5521                exit(1);
   5522            } else if (strncmp(&buf[1], "A.2.1", 5) == 0) {
   5523                type = A_1_2_1;
   5524                output_g = 1;
   5525                exit(1);
   5526            } else if (strncmp(&buf[1], "A.2.3", 5) == 0) {
   5527                fprintf(stderr, "NSS only Generates G with P&Q\n");
   5528                exit(1);
   5529            } else if (strncmp(&buf[1], "A.1.2.1", 7) == 0) {
   5530                type = A_1_2_1;
   5531                output_g = 0;
   5532            } else {
   5533                fprintf(stderr, "Unknown dsa pqggen test %s\n", &buf[1]);
   5534                exit(1);
   5535            }
   5536            fputs(buf, dsaresp);
   5537            continue;
   5538        }
   5539 
   5540        /* [Mod = ... ] */
   5541        if (buf[0] == '[') {
   5542 
   5543            if (type == FIPS186_1) {
   5544                N = 160;
   5545                if (sscanf(buf, "[mod = %d]", &L) != 1) {
   5546                    goto loser;
   5547                }
   5548            } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) {
   5549                goto loser;
   5550            }
   5551 
   5552            fputs(buf, dsaresp);
   5553            fputc('\n', dsaresp);
   5554 
   5555            if (type == FIPS186_1) {
   5556                /************************************************************
   5557                 * PQG_ParamGenSeedLen doesn't take a key size, it takes an
   5558                 * index that points to a valid key size.
   5559                 */
   5560                keySizeIndex = PQG_PBITS_TO_INDEX(L);
   5561                if (keySizeIndex == -1 || L < 512 || L > 1024) {
   5562                    fprintf(dsaresp,
   5563                            "DSA key size must be a multiple of 64 between 512 "
   5564                            "and 1024, inclusive");
   5565                    goto loser;
   5566                }
   5567            }
   5568            continue;
   5569        }
   5570        /* N = ... */
   5571        if (buf[0] == 'N') {
   5572            if (strncmp(buf, "Num", 3) == 0) {
   5573                if (sscanf(buf, "Num = %d", &count) != 1) {
   5574                    goto loser;
   5575                }
   5576            } else if (sscanf(buf, "N = %d", &count) != 1) {
   5577                goto loser;
   5578            }
   5579            for (i = 0; i < count; i++) {
   5580                SECStatus rv;
   5581 
   5582                if (type == FIPS186_1) {
   5583                    rv = PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
   5584                                             &pqg, &vfy);
   5585                } else {
   5586                    rv = PQG_ParamGenV2(L, N, N, &pqg, &vfy);
   5587                }
   5588                if (rv != SECSuccess) {
   5589                    fprintf(dsaresp,
   5590                            "ERROR: Unable to generate PQG parameters");
   5591                    goto loser;
   5592                }
   5593                to_hex_str(buf, pqg->prime.data, pqg->prime.len);
   5594                fprintf(dsaresp, "P = %s\n", buf);
   5595                to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
   5596                fprintf(dsaresp, "Q = %s\n", buf);
   5597                if (output_g) {
   5598                    to_hex_str(buf, pqg->base.data, pqg->base.len);
   5599                    fprintf(dsaresp, "G = %s\n", buf);
   5600                }
   5601                if (type == FIPS186_1) {
   5602                    to_hex_str(buf, vfy->seed.data, vfy->seed.len);
   5603                    fprintf(dsaresp, "Seed = %s\n", buf);
   5604                    fprintf(dsaresp, "c = %d\n", vfy->counter);
   5605                    to_hex_str(buf, vfy->h.data, vfy->h.len);
   5606                    fputs("H = ", dsaresp);
   5607                    for (j = vfy->h.len; j < pqg->prime.len; j++) {
   5608                        fprintf(dsaresp, "00");
   5609                    }
   5610                    fprintf(dsaresp, "%s\n", buf);
   5611                } else {
   5612                    unsigned int seedlen = vfy->seed.len / 2;
   5613                    unsigned int pgen_counter = vfy->counter >> 16;
   5614                    unsigned int qgen_counter = vfy->counter & 0xffff;
   5615                    /*fprintf(dsaresp, "index = %02x\n", vfy->h.data[0]); */
   5616                    to_hex_str(buf, vfy->seed.data, seedlen);
   5617                    fprintf(dsaresp, "pseed = %s\n", buf);
   5618                    to_hex_str(buf, vfy->seed.data + seedlen, seedlen);
   5619                    fprintf(dsaresp, "qseed = %s\n", buf);
   5620                    fprintf(dsaresp, "pgen_counter = %d\n", pgen_counter);
   5621                    fprintf(dsaresp, "qgen_counter = %d\n", qgen_counter);
   5622                    if (output_g) {
   5623                        to_hex_str(buf, vfy->seed.data, vfy->seed.len);
   5624                        fprintf(dsaresp, "domain_parameter_seed = %s\n", buf);
   5625                        fprintf(dsaresp, "index = %02x\n", vfy->h.data[0]);
   5626                    }
   5627                }
   5628                fputc('\n', dsaresp);
   5629                if (pqg != NULL) {
   5630                    PQG_DestroyParams(pqg);
   5631                    pqg = NULL;
   5632                }
   5633                if (vfy != NULL) {
   5634                    PQG_DestroyVerify(vfy);
   5635                    vfy = NULL;
   5636                }
   5637            }
   5638 
   5639            continue;
   5640        }
   5641    }
   5642 loser:
   5643    fclose(dsareq);
   5644    if (pqg != NULL) {
   5645        PQG_DestroyParams(pqg);
   5646    }
   5647    if (vfy != NULL) {
   5648        PQG_DestroyVerify(vfy);
   5649    }
   5650 }
   5651 
   5652 /*
   5653 * Perform the DSA Signature Generation Test.
   5654 *
   5655 * reqfn is the pathname of the REQUEST file.
   5656 *
   5657 * The output RESPONSE file is written to stdout.
   5658 */
   5659 void
   5660 dsa_siggen_test(char *reqfn)
   5661 {
   5662    char buf[800]; /* holds one line from the input REQUEST file
   5663                    * or to the output RESPONSE file.
   5664                    * max for Msg = ....
   5665                    */
   5666    FILE *dsareq;  /* input stream from the REQUEST file */
   5667    FILE *dsaresp; /* output stream to the RESPONSE file */
   5668    int modulus;
   5669    int L;
   5670    int N;
   5671    int i, j;
   5672    PRBool use_dsa1 = PR_FALSE;
   5673    PQGParams *pqg = NULL;
   5674    PQGVerify *vfy = NULL;
   5675    DSAPrivateKey *dsakey = NULL;
   5676    int keySizeIndex;                       /* index for valid key sizes */
   5677    unsigned char hashBuf[HASH_LENGTH_MAX]; /* SHA-x hash (160-512 bits) */
   5678    unsigned char sig[DSA_MAX_SIGNATURE_LEN];
   5679    SECItem digest, signature;
   5680    HASH_HashType hashType = HASH_AlgNULL;
   5681    int hashNum = 0;
   5682 
   5683    dsareq = fopen(reqfn, "r");
   5684    dsaresp = stdout;
   5685 
   5686    while (fgets(buf, sizeof buf, dsareq) != NULL) {
   5687        /* a comment or blank line */
   5688        if (buf[0] == '#' || buf[0] == '\n') {
   5689            fputs(buf, dsaresp);
   5690            continue;
   5691        }
   5692 
   5693        /* [Mod = x] */
   5694        if (buf[0] == '[') {
   5695            if (pqg != NULL) {
   5696                PQG_DestroyParams(pqg);
   5697                pqg = NULL;
   5698            }
   5699            if (vfy != NULL) {
   5700                PQG_DestroyVerify(vfy);
   5701                vfy = NULL;
   5702            }
   5703            if (dsakey != NULL) {
   5704                PORT_FreeArena(dsakey->params.arena, PR_TRUE);
   5705                dsakey = NULL;
   5706            }
   5707 
   5708            if (sscanf(buf, "[mod = L=%d,  N=%d, SHA-%d]", &L, &N,
   5709                       &hashNum) != 3) {
   5710                use_dsa1 = PR_TRUE;
   5711                hashNum = 1;
   5712                if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
   5713                    goto loser;
   5714                }
   5715            }
   5716            fputs(buf, dsaresp);
   5717            fputc('\n', dsaresp);
   5718 
   5719            /****************************************************************
   5720             * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
   5721             * that points to a valid key size.
   5722             */
   5723            if (use_dsa1) {
   5724                keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
   5725                if (keySizeIndex == -1 || modulus < 512 || modulus > 1024) {
   5726                    fprintf(dsaresp,
   5727                            "DSA key size must be a multiple of 64 between 512 "
   5728                            "and 1024, inclusive");
   5729                    goto loser;
   5730                }
   5731                /* Generate PQG and output PQG */
   5732                if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
   5733                                        &pqg, &vfy) !=
   5734                    SECSuccess) {
   5735                    fprintf(dsaresp,
   5736                            "ERROR: Unable to generate PQG parameters");
   5737                    goto loser;
   5738                }
   5739            } else {
   5740                if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) {
   5741                    fprintf(dsaresp,
   5742                            "ERROR: Unable to generate PQG parameters");
   5743                    goto loser;
   5744                }
   5745            }
   5746            to_hex_str(buf, pqg->prime.data, pqg->prime.len);
   5747            fprintf(dsaresp, "P = %s\n", buf);
   5748            to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
   5749            fprintf(dsaresp, "Q = %s\n", buf);
   5750            to_hex_str(buf, pqg->base.data, pqg->base.len);
   5751            fprintf(dsaresp, "G = %s\n", buf);
   5752 
   5753            /* create DSA Key */
   5754            if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
   5755                fprintf(dsaresp, "ERROR: Unable to generate DSA key");
   5756                goto loser;
   5757            }
   5758 
   5759            hashType = sha_get_hashType(hashNum);
   5760            if (hashType == HASH_AlgNULL) {
   5761                fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)", hashNum);
   5762                goto loser;
   5763            }
   5764            continue;
   5765        }
   5766 
   5767        /* Msg = ... */
   5768        if (strncmp(buf, "Msg", 3) == 0) {
   5769            unsigned char msg[128]; /* MAX msg 128 */
   5770            unsigned int len = 0;
   5771 
   5772            if (hashType == HASH_AlgNULL) {
   5773                fprintf(dsaresp, "ERROR: Hash Alg not set");
   5774                goto loser;
   5775            }
   5776 
   5777            memset(hashBuf, 0, sizeof hashBuf);
   5778            memset(sig, 0, sizeof sig);
   5779 
   5780            i = 3;
   5781            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   5782                i++;
   5783            }
   5784            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   5785                hex_to_byteval(&buf[i], &msg[j]);
   5786            }
   5787            if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) {
   5788                fprintf(dsaresp, "ERROR: Unable to generate SHA% digest",
   5789                        hashNum);
   5790                goto loser;
   5791            }
   5792 
   5793            digest.type = siBuffer;
   5794            digest.data = hashBuf;
   5795            digest.len = fips_hashLen(hashType);
   5796            signature.type = siBuffer;
   5797            signature.data = sig;
   5798            signature.len = sizeof sig;
   5799 
   5800            if (DSA_SignDigest(dsakey, &signature, &digest) != SECSuccess) {
   5801                fprintf(dsaresp, "ERROR: Unable to generate DSA signature");
   5802                goto loser;
   5803            }
   5804            len = signature.len;
   5805            if (len % 2 != 0) {
   5806                goto loser;
   5807            }
   5808            len = len / 2;
   5809 
   5810            /* output the orginal Msg, and generated Y, R, and S */
   5811            fputs(buf, dsaresp);
   5812            to_hex_str(buf, dsakey->publicValue.data,
   5813                       dsakey->publicValue.len);
   5814            fprintf(dsaresp, "Y = %s\n", buf);
   5815            to_hex_str(buf, &signature.data[0], len);
   5816            fprintf(dsaresp, "R = %s\n", buf);
   5817            to_hex_str(buf, &signature.data[len], len);
   5818            fprintf(dsaresp, "S = %s\n", buf);
   5819            fputc('\n', dsaresp);
   5820            continue;
   5821        }
   5822    }
   5823 loser:
   5824    fclose(dsareq);
   5825    if (pqg != NULL) {
   5826        PQG_DestroyParams(pqg);
   5827        pqg = NULL;
   5828    }
   5829    if (vfy != NULL) {
   5830        PQG_DestroyVerify(vfy);
   5831        vfy = NULL;
   5832    }
   5833    if (dsakey) {
   5834        PORT_FreeArena(dsakey->params.arena, PR_TRUE);
   5835        dsakey = NULL;
   5836    }
   5837 }
   5838 
   5839 /*
   5840 * Perform the DSA Signature Verification Test.
   5841 *
   5842 * reqfn is the pathname of the REQUEST file.
   5843 *
   5844 * The output RESPONSE file is written to stdout.
   5845 */
   5846 void
   5847 dsa_sigver_test(char *reqfn)
   5848 {
   5849    char buf[800]; /* holds one line from the input REQUEST file
   5850                    * or to the output RESPONSE file.
   5851                    * max for Msg = ....
   5852                    */
   5853    FILE *dsareq;  /* input stream from the REQUEST file */
   5854    FILE *dsaresp; /* output stream to the RESPONSE file */
   5855    int L;
   5856    int N;
   5857    unsigned int i, j;
   5858    SECItem digest, signature;
   5859    DSAPublicKey pubkey;
   5860    unsigned int pgySize;                   /* size for p, g, and y */
   5861    unsigned char hashBuf[HASH_LENGTH_MAX]; /* SHA-x hash (160-512 bits) */
   5862    unsigned char sig[DSA_MAX_SIGNATURE_LEN];
   5863    HASH_HashType hashType = HASH_AlgNULL;
   5864    int hashNum = 0;
   5865 
   5866    dsareq = fopen(reqfn, "r");
   5867    dsaresp = stdout;
   5868    memset(&pubkey, 0, sizeof(pubkey));
   5869 
   5870    while (fgets(buf, sizeof buf, dsareq) != NULL) {
   5871        /* a comment or blank line */
   5872        if (buf[0] == '#' || buf[0] == '\n') {
   5873            fputs(buf, dsaresp);
   5874            continue;
   5875        }
   5876 
   5877        /* [Mod = x] */
   5878        if (buf[0] == '[') {
   5879 
   5880            if (sscanf(buf, "[mod = L=%d,  N=%d, SHA-%d]", &L, &N,
   5881                       &hashNum) != 3) {
   5882                N = 160;
   5883                hashNum = 1;
   5884                if (sscanf(buf, "[mod = %d]", &L) != 1) {
   5885                    goto loser;
   5886                }
   5887            }
   5888 
   5889            if (pubkey.params.prime.data) { /* P */
   5890                SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
   5891            }
   5892            if (pubkey.params.subPrime.data) { /* Q */
   5893                SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
   5894            }
   5895            if (pubkey.params.base.data) { /* G */
   5896                SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
   5897            }
   5898            if (pubkey.publicValue.data) { /* Y */
   5899                SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
   5900            }
   5901            fputs(buf, dsaresp);
   5902 
   5903            /* calculate the size of p, g, and y then allocate items */
   5904            pgySize = L / 8;
   5905            SECITEM_AllocItem(NULL, &pubkey.params.prime, pgySize);
   5906            SECITEM_AllocItem(NULL, &pubkey.params.base, pgySize);
   5907            SECITEM_AllocItem(NULL, &pubkey.publicValue, pgySize);
   5908            pubkey.params.prime.len = pubkey.params.base.len = pgySize;
   5909            pubkey.publicValue.len = pgySize;
   5910 
   5911            /* q always N/8 bytes */
   5912            SECITEM_AllocItem(NULL, &pubkey.params.subPrime, N / 8);
   5913            pubkey.params.subPrime.len = N / 8;
   5914 
   5915            hashType = sha_get_hashType(hashNum);
   5916            if (hashType == HASH_AlgNULL) {
   5917                fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)", hashNum);
   5918                goto loser;
   5919            }
   5920 
   5921            continue;
   5922        }
   5923        /* P = ... */
   5924        if (buf[0] == 'P') {
   5925            i = 1;
   5926            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   5927                i++;
   5928            }
   5929            memset(pubkey.params.prime.data, 0, pubkey.params.prime.len);
   5930            for (j = 0; j < pubkey.params.prime.len; i += 2, j++) {
   5931                hex_to_byteval(&buf[i], &pubkey.params.prime.data[j]);
   5932            }
   5933 
   5934            fputs(buf, dsaresp);
   5935            continue;
   5936        }
   5937 
   5938        /* Q = ... */
   5939        if (buf[0] == 'Q') {
   5940            i = 1;
   5941            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   5942                i++;
   5943            }
   5944            memset(pubkey.params.subPrime.data, 0, pubkey.params.subPrime.len);
   5945            for (j = 0; j < pubkey.params.subPrime.len; i += 2, j++) {
   5946                hex_to_byteval(&buf[i], &pubkey.params.subPrime.data[j]);
   5947            }
   5948 
   5949            fputs(buf, dsaresp);
   5950            continue;
   5951        }
   5952 
   5953        /* G = ... */
   5954        if (buf[0] == 'G') {
   5955            i = 1;
   5956            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   5957                i++;
   5958            }
   5959            memset(pubkey.params.base.data, 0, pubkey.params.base.len);
   5960            for (j = 0; j < pubkey.params.base.len; i += 2, j++) {
   5961                hex_to_byteval(&buf[i], &pubkey.params.base.data[j]);
   5962            }
   5963 
   5964            fputs(buf, dsaresp);
   5965            continue;
   5966        }
   5967 
   5968        /* Msg = ... */
   5969        if (strncmp(buf, "Msg", 3) == 0) {
   5970            unsigned char msg[128]; /* MAX msg 128 */
   5971            memset(hashBuf, 0, sizeof hashBuf);
   5972 
   5973            if (hashType == HASH_AlgNULL) {
   5974                fprintf(dsaresp, "ERROR: Hash Alg not set");
   5975                goto loser;
   5976            }
   5977 
   5978            i = 3;
   5979            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   5980                i++;
   5981            }
   5982            for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) {
   5983                hex_to_byteval(&buf[i], &msg[j]);
   5984            }
   5985            if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) {
   5986                fprintf(dsaresp, "ERROR: Unable to generate SHA-%d digest",
   5987                        hashNum);
   5988                goto loser;
   5989            }
   5990 
   5991            fputs(buf, dsaresp);
   5992            continue;
   5993        }
   5994 
   5995        /* Y = ... */
   5996        if (buf[0] == 'Y') {
   5997            i = 1;
   5998            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   5999                i++;
   6000            }
   6001            memset(pubkey.publicValue.data, 0, pubkey.params.subPrime.len);
   6002            for (j = 0; j < pubkey.publicValue.len; i += 2, j++) {
   6003                hex_to_byteval(&buf[i], &pubkey.publicValue.data[j]);
   6004            }
   6005 
   6006            fputs(buf, dsaresp);
   6007            continue;
   6008        }
   6009 
   6010        /* R = ... */
   6011        if (buf[0] == 'R') {
   6012            memset(sig, 0, sizeof sig);
   6013            i = 1;
   6014            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   6015                i++;
   6016            }
   6017            for (j = 0; j < pubkey.params.subPrime.len; i += 2, j++) {
   6018                hex_to_byteval(&buf[i], &sig[j]);
   6019            }
   6020 
   6021            fputs(buf, dsaresp);
   6022            continue;
   6023        }
   6024 
   6025        /* S = ... */
   6026        if (buf[0] == 'S') {
   6027            if (hashType == HASH_AlgNULL) {
   6028                fprintf(dsaresp, "ERROR: Hash Alg not set");
   6029                goto loser;
   6030            }
   6031 
   6032            i = 1;
   6033            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   6034                i++;
   6035            }
   6036            for (j = pubkey.params.subPrime.len;
   6037                 j < pubkey.params.subPrime.len * 2; i += 2, j++) {
   6038                hex_to_byteval(&buf[i], &sig[j]);
   6039            }
   6040            fputs(buf, dsaresp);
   6041 
   6042            digest.type = siBuffer;
   6043            digest.data = hashBuf;
   6044            digest.len = fips_hashLen(hashType);
   6045            signature.type = siBuffer;
   6046            signature.data = sig;
   6047            signature.len = pubkey.params.subPrime.len * 2;
   6048 
   6049            if (DSA_VerifyDigest(&pubkey, &signature, &digest) == SECSuccess) {
   6050                fprintf(dsaresp, "Result = P\n");
   6051            } else {
   6052                fprintf(dsaresp, "Result = F\n");
   6053            }
   6054            fprintf(dsaresp, "\n");
   6055            continue;
   6056        }
   6057    }
   6058 loser:
   6059    fclose(dsareq);
   6060    if (pubkey.params.prime.data) { /* P */
   6061        SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
   6062    }
   6063    if (pubkey.params.subPrime.data) { /* Q */
   6064        SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
   6065    }
   6066    if (pubkey.params.base.data) { /* G */
   6067        SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
   6068    }
   6069    if (pubkey.publicValue.data) { /* Y */
   6070        SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
   6071    }
   6072 }
   6073 
   6074 static void
   6075 pad(unsigned char *buf, int pad_len, unsigned char *src, int src_len)
   6076 {
   6077    int offset = 0;
   6078    /* this shouldn't happen, fail right away rather than produce bad output */
   6079    if (pad_len < src_len) {
   6080        fprintf(stderr, "data bigger than expected! %d > %d\n", src_len, pad_len);
   6081        exit(1);
   6082    }
   6083 
   6084    offset = pad_len - src_len;
   6085    memset(buf, 0, offset);
   6086    memcpy(buf + offset, src, src_len);
   6087    return;
   6088 }
   6089 
   6090 /*
   6091 * Perform the DSA Key Pair Generation Test.
   6092 *
   6093 * reqfn is the pathname of the REQUEST file.
   6094 *
   6095 * The output RESPONSE file is written to stdout.
   6096 */
   6097 void
   6098 rsa_keypair_test(char *reqfn)
   6099 {
   6100    char buf[800];           /* holds one line from the input REQUEST file
   6101                              * or to the output RESPONSE file.
   6102                              * 800 to hold (384 public key (x2 for HEX) + 1'\n'
   6103                              */
   6104    unsigned char buf2[400]; /* can't need more then 1/2 buf length */
   6105    FILE *rsareq;            /* input stream from the REQUEST file */
   6106    FILE *rsaresp;           /* output stream to the RESPONSE file */
   6107    int count;
   6108    int i;
   6109    int keySize = 1; /* key size in bits*/
   6110    int len = 0;     /* key size in bytes */
   6111    int len2 = 0;    /* key size in bytes/2 (prime size) */
   6112    SECItem e;
   6113    unsigned char default_e[] = { 0x1, 0x0, 0x1 };
   6114 
   6115    e.data = default_e;
   6116    e.len = sizeof(default_e);
   6117 
   6118    rsareq = fopen(reqfn, "r");
   6119    rsaresp = stdout;
   6120    while (fgets(buf, sizeof buf, rsareq) != NULL) {
   6121        /* a comment or blank line */
   6122        if (buf[0] == '#' || buf[0] == '\n') {
   6123            fputs(buf, rsaresp);
   6124            continue;
   6125        }
   6126 
   6127        /* [Mod = x] */
   6128        if (buf[0] == '[') {
   6129            if (buf[1] == 'm') {
   6130                if (sscanf(buf, "[mod = %d]", &keySize) != 1) {
   6131                    goto loser;
   6132                }
   6133                len = keySize / 8;
   6134                len2 = keySize / 16;
   6135            }
   6136            fputs(buf, rsaresp);
   6137            continue;
   6138        }
   6139        /* N = ...*/
   6140        if (buf[0] == 'N') {
   6141 
   6142            if (sscanf(buf, "N = %d", &count) != 1) {
   6143                goto loser;
   6144            }
   6145 
   6146            /* Generate a DSA key, and output the key pair for N times */
   6147            for (i = 0; i < count; i++) {
   6148                RSAPrivateKey *rsakey = NULL;
   6149                if ((rsakey = RSA_NewKey(keySize, &e)) == NULL) {
   6150                    fprintf(rsaresp, "ERROR: Unable to generate RSA key");
   6151                    goto loser;
   6152                }
   6153                pad(buf2, len, rsakey->publicExponent.data,
   6154                    rsakey->publicExponent.len);
   6155                to_hex_str(buf, buf2, len);
   6156                fprintf(rsaresp, "e = %s\n", buf);
   6157                pad(buf2, len2, rsakey->prime1.data,
   6158                    rsakey->prime1.len);
   6159                to_hex_str(buf, buf2, len2);
   6160                fprintf(rsaresp, "p = %s\n", buf);
   6161                pad(buf2, len2, rsakey->prime2.data,
   6162                    rsakey->prime2.len);
   6163                to_hex_str(buf, buf2, len2);
   6164                fprintf(rsaresp, "q = %s\n", buf);
   6165                pad(buf2, len, rsakey->modulus.data,
   6166                    rsakey->modulus.len);
   6167                to_hex_str(buf, buf2, len);
   6168                fprintf(rsaresp, "n = %s\n", buf);
   6169                pad(buf2, len, rsakey->privateExponent.data,
   6170                    rsakey->privateExponent.len);
   6171                to_hex_str(buf, buf2, len);
   6172                fprintf(rsaresp, "d = %s\n", buf);
   6173                fprintf(rsaresp, "\n");
   6174                PORT_FreeArena(rsakey->arena, PR_TRUE);
   6175                rsakey = NULL;
   6176            }
   6177            continue;
   6178        }
   6179    }
   6180 loser:
   6181    fclose(rsareq);
   6182 }
   6183 
   6184 /*
   6185 * Perform the RSA Signature Generation Test.
   6186 *
   6187 * reqfn is the pathname of the REQUEST file.
   6188 *
   6189 * The output RESPONSE file is written to stdout.
   6190 */
   6191 void
   6192 rsa_siggen_test(char *reqfn)
   6193 {
   6194    char buf[2 * RSA_MAX_TEST_MODULUS_BYTES + 1];
   6195    /* buf holds one line from the input REQUEST file
   6196     * or to the output RESPONSE file.
   6197     * 2x for HEX output + 1 for \n
   6198     */
   6199    FILE *rsareq;  /* input stream from the REQUEST file */
   6200    FILE *rsaresp; /* output stream to the RESPONSE file */
   6201    int i, j;
   6202    unsigned char sha[HASH_LENGTH_MAX];  /* SHA digest */
   6203    unsigned int shaLength = 0;          /* length of SHA */
   6204    HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
   6205    SECOidTag shaOid = SEC_OID_UNKNOWN;
   6206    int modulus; /* the Modulus size */
   6207    int publicExponent = DEFAULT_RSA_PUBLIC_EXPONENT;
   6208    SECItem pe = { 0, 0, 0 };
   6209    unsigned char pubEx[4];
   6210    int peCount = 0;
   6211 
   6212    RSAPrivateKey *rsaBlapiPrivKey = NULL;  /* holds RSA private and
   6213                                             * public keys */
   6214    RSAPublicKey *rsaBlapiPublicKey = NULL; /* hold RSA public key */
   6215 
   6216    rsareq = fopen(reqfn, "r");
   6217    rsaresp = stdout;
   6218 
   6219    /* calculate the exponent */
   6220    for (i = 0; i < 4; i++) {
   6221        if (peCount || (publicExponent &
   6222                        ((unsigned long)0xff000000L >> (i *
   6223                                                        8)))) {
   6224            pubEx[peCount] =
   6225                (unsigned char)((publicExponent >> (3 - i) * 8) & 0xff);
   6226            peCount++;
   6227        }
   6228    }
   6229    pe.len = peCount;
   6230    pe.data = &pubEx[0];
   6231    pe.type = siBuffer;
   6232 
   6233    while (fgets(buf, sizeof buf, rsareq) != NULL) {
   6234        /* a comment or blank line */
   6235        if (buf[0] == '#' || buf[0] == '\n') {
   6236            fputs(buf, rsaresp);
   6237            continue;
   6238        }
   6239 
   6240        /* [mod = ...] */
   6241        if (buf[0] == '[') {
   6242 
   6243            if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
   6244                goto loser;
   6245            }
   6246            if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
   6247                fprintf(rsaresp, "ERROR: modulus greater than test maximum\n");
   6248                goto loser;
   6249            }
   6250 
   6251            fputs(buf, rsaresp);
   6252 
   6253            if (rsaBlapiPrivKey != NULL) {
   6254                PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
   6255                rsaBlapiPrivKey = NULL;
   6256                rsaBlapiPublicKey = NULL;
   6257            }
   6258 
   6259            rsaBlapiPrivKey = RSA_NewKey(modulus, &pe);
   6260            if (rsaBlapiPrivKey == NULL) {
   6261                fprintf(rsaresp, "Error unable to create RSA key\n");
   6262                goto loser;
   6263            }
   6264 
   6265            to_hex_str(buf, rsaBlapiPrivKey->modulus.data,
   6266                       rsaBlapiPrivKey->modulus.len);
   6267            fprintf(rsaresp, "\nn = %s\n\n", buf);
   6268            to_hex_str(buf, rsaBlapiPrivKey->publicExponent.data,
   6269                       rsaBlapiPrivKey->publicExponent.len);
   6270            fprintf(rsaresp, "e = %s\n", buf);
   6271            /* convert private key to public key.  Memory
   6272             * is freed with private key's arena  */
   6273            rsaBlapiPublicKey = (RSAPublicKey *)PORT_ArenaAlloc(
   6274                rsaBlapiPrivKey->arena,
   6275                sizeof(RSAPublicKey));
   6276 
   6277            rsaBlapiPublicKey->modulus.len = rsaBlapiPrivKey->modulus.len;
   6278            rsaBlapiPublicKey->modulus.data = rsaBlapiPrivKey->modulus.data;
   6279            rsaBlapiPublicKey->publicExponent.len =
   6280                rsaBlapiPrivKey->publicExponent.len;
   6281            rsaBlapiPublicKey->publicExponent.data =
   6282                rsaBlapiPrivKey->publicExponent.data;
   6283            continue;
   6284        }
   6285 
   6286        /* SHAAlg = ... */
   6287        if (strncmp(buf, "SHAAlg", 6) == 0) {
   6288            i = 6;
   6289            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   6290                i++;
   6291            }
   6292            /* set the SHA Algorithm */
   6293            shaAlg = hash_string_to_hashType(&buf[i]);
   6294            if (shaAlg == HASH_AlgNULL) {
   6295                fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
   6296                goto loser;
   6297            }
   6298            fputs(buf, rsaresp);
   6299            continue;
   6300        }
   6301        /* Msg = ... */
   6302        if (strncmp(buf, "Msg", 3) == 0) {
   6303 
   6304            unsigned char msg[128]; /* MAX msg 128 */
   6305            unsigned int rsa_bytes_signed;
   6306            unsigned char rsa_computed_signature[RSA_MAX_TEST_MODULUS_BYTES];
   6307            SECStatus rv = SECFailure;
   6308            NSSLOWKEYPublicKey *rsa_public_key;
   6309            NSSLOWKEYPrivateKey *rsa_private_key;
   6310            NSSLOWKEYPrivateKey low_RSA_private_key = { NULL,
   6311                                                        NSSLOWKEYRSAKey };
   6312            NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
   6313                                                      NSSLOWKEYRSAKey };
   6314 
   6315            low_RSA_private_key.u.rsa = *rsaBlapiPrivKey;
   6316            low_RSA_public_key.u.rsa = *rsaBlapiPublicKey;
   6317 
   6318            rsa_private_key = &low_RSA_private_key;
   6319            rsa_public_key = &low_RSA_public_key;
   6320 
   6321            memset(sha, 0, sizeof sha);
   6322            memset(msg, 0, sizeof msg);
   6323            rsa_bytes_signed = 0;
   6324            memset(rsa_computed_signature, 0, sizeof rsa_computed_signature);
   6325 
   6326            i = 3;
   6327            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   6328                i++;
   6329            }
   6330            for (j = 0; isxdigit((unsigned char)buf[i]) && j < sizeof(msg); i += 2, j++) {
   6331                hex_to_byteval(&buf[i], &msg[j]);
   6332            }
   6333            shaLength = fips_hashLen(shaAlg);
   6334            if (fips_hashBuf(shaAlg, sha, msg, j) != SECSuccess) {
   6335                if (shaLength == 0) {
   6336                    fprintf(rsaresp, "ERROR: SHAAlg not defined.");
   6337                }
   6338                fprintf(rsaresp, "ERROR: Unable to generate SHA%x",
   6339                        shaLength == 160 ? 1 : shaLength);
   6340                goto loser;
   6341            }
   6342            shaOid = fips_hashOid(shaAlg);
   6343 
   6344            /* Perform RSA signature with the RSA private key. */
   6345            rv = RSA_HashSign(shaOid,
   6346                              rsa_private_key,
   6347                              rsa_computed_signature,
   6348                              &rsa_bytes_signed,
   6349                              nsslowkey_PrivateModulusLen(rsa_private_key),
   6350                              sha,
   6351                              shaLength);
   6352 
   6353            if (rv != SECSuccess) {
   6354                fprintf(rsaresp, "ERROR: RSA_HashSign failed");
   6355                goto loser;
   6356            }
   6357 
   6358            /* Output the signature */
   6359            fputs(buf, rsaresp);
   6360            to_hex_str(buf, rsa_computed_signature, rsa_bytes_signed);
   6361            fprintf(rsaresp, "S = %s\n", buf);
   6362 
   6363            /* Perform RSA verification with the RSA public key. */
   6364            rv = RSA_HashCheckSign(shaOid,
   6365                                   rsa_public_key,
   6366                                   rsa_computed_signature,
   6367                                   rsa_bytes_signed,
   6368                                   sha,
   6369                                   shaLength);
   6370            if (rv != SECSuccess) {
   6371                fprintf(rsaresp, "ERROR: RSA_HashCheckSign failed");
   6372                goto loser;
   6373            }
   6374            continue;
   6375        }
   6376    }
   6377 loser:
   6378    fclose(rsareq);
   6379 
   6380    if (rsaBlapiPrivKey != NULL) {
   6381        /* frees private and public key */
   6382        PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
   6383        rsaBlapiPrivKey = NULL;
   6384        rsaBlapiPublicKey = NULL;
   6385    }
   6386 }
   6387 /*
   6388 * Perform the RSA Signature Verification Test.
   6389 *
   6390 * reqfn is the pathname of the REQUEST file.
   6391 *
   6392 * The output RESPONSE file is written to stdout.
   6393 */
   6394 void
   6395 rsa_sigver_test(char *reqfn)
   6396 {
   6397    char buf[2 * RSA_MAX_TEST_MODULUS_BYTES + 7];
   6398    /* buf holds one line from the input REQUEST file
   6399     * or to the output RESPONSE file.
   6400     * s = 2x for HEX output + 1 for \n
   6401     */
   6402    FILE *rsareq;  /* input stream from the REQUEST file */
   6403    FILE *rsaresp; /* output stream to the RESPONSE file */
   6404    int i, j;
   6405    unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
   6406    unsigned int shaLength = 0;         /* actual length of the digest */
   6407    HASH_HashType shaAlg = HASH_AlgNULL;
   6408    SECOidTag shaOid = SEC_OID_UNKNOWN;
   6409    int modulus = 0;                  /* the Modulus size */
   6410    unsigned char signature[513];     /* largest signature size + '\n' */
   6411    unsigned int signatureLength = 0; /* actual length of the signature */
   6412    PRBool keyvalid = PR_TRUE;
   6413 
   6414    RSAPublicKey rsaBlapiPublicKey; /* hold RSA public key */
   6415 
   6416    rsareq = fopen(reqfn, "r");
   6417    rsaresp = stdout;
   6418    memset(&rsaBlapiPublicKey, 0, sizeof(RSAPublicKey));
   6419 
   6420    while (fgets(buf, sizeof buf, rsareq) != NULL) {
   6421        /* a comment or blank line */
   6422        if (buf[0] == '#' || buf[0] == '\n') {
   6423            fputs(buf, rsaresp);
   6424            continue;
   6425        }
   6426 
   6427        /* [Mod = ...] */
   6428        if (buf[0] == '[') {
   6429            unsigned int flen; /* length in bytes of the field size */
   6430 
   6431            if (rsaBlapiPublicKey.modulus.data) { /* n */
   6432                SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
   6433            }
   6434            if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
   6435                goto loser;
   6436            }
   6437 
   6438            if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
   6439                fprintf(rsaresp, "ERROR: modulus greater than test maximum\n");
   6440                goto loser;
   6441            }
   6442 
   6443            fputs(buf, rsaresp);
   6444 
   6445            signatureLength = flen = modulus / 8;
   6446 
   6447            SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.modulus, flen);
   6448            if (rsaBlapiPublicKey.modulus.data == NULL) {
   6449                goto loser;
   6450            }
   6451            continue;
   6452        }
   6453 
   6454        /* n = ... modulus */
   6455        if (buf[0] == 'n') {
   6456            i = 1;
   6457            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   6458                i++;
   6459            }
   6460            keyvalid = from_hex_str(&rsaBlapiPublicKey.modulus.data[0],
   6461                                    rsaBlapiPublicKey.modulus.len,
   6462                                    &buf[i]);
   6463 
   6464            if (!keyvalid) {
   6465                fprintf(rsaresp, "ERROR: rsa_sigver n not valid.\n");
   6466                goto loser;
   6467            }
   6468            fputs(buf, rsaresp);
   6469            continue;
   6470        }
   6471 
   6472        /* SHAAlg = ... */
   6473        if (strncmp(buf, "SHAAlg", 6) == 0) {
   6474            i = 6;
   6475            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   6476                i++;
   6477            }
   6478            /* set the SHA Algorithm */
   6479            shaAlg = hash_string_to_hashType(&buf[i]);
   6480            if (shaAlg == HASH_AlgNULL) {
   6481                fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
   6482                goto loser;
   6483            }
   6484            fputs(buf, rsaresp);
   6485            continue;
   6486        }
   6487 
   6488        /* e = ... public Key */
   6489        if (buf[0] == 'e') {
   6490            unsigned char data[RSA_MAX_TEST_EXPONENT_BYTES];
   6491            unsigned char t;
   6492 
   6493            memset(data, 0, sizeof data);
   6494 
   6495            if (rsaBlapiPublicKey.publicExponent.data) { /* e */
   6496                SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
   6497            }
   6498 
   6499            i = 1;
   6500            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   6501                i++;
   6502            }
   6503            /* skip leading zero's */
   6504            while (isxdigit((unsigned char)buf[i])) {
   6505                hex_to_byteval(&buf[i], &t);
   6506                if (t == 0) {
   6507                    i += 2;
   6508                } else
   6509                    break;
   6510            }
   6511 
   6512            /* get the exponent */
   6513            for (j = 0; isxdigit((unsigned char)buf[i]) && j < sizeof data; i += 2, j++) {
   6514                hex_to_byteval(&buf[i], &data[j]);
   6515            }
   6516 
   6517            if (j == 0) {
   6518                j = 1;
   6519            } /* to handle 1 byte length exponents */
   6520 
   6521            SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.publicExponent, j);
   6522            if (rsaBlapiPublicKey.publicExponent.data == NULL) {
   6523                goto loser;
   6524            }
   6525 
   6526            for (i = 0; i < j; i++) {
   6527                rsaBlapiPublicKey.publicExponent.data[i] = data[i];
   6528            }
   6529 
   6530            fputs(buf, rsaresp);
   6531            continue;
   6532        }
   6533 
   6534        /* Msg = ... */
   6535        if (strncmp(buf, "Msg", 3) == 0) {
   6536            unsigned char msg[128]; /* MAX msg 128 */
   6537 
   6538            memset(sha, 0, sizeof sha);
   6539            memset(msg, 0, sizeof msg);
   6540 
   6541            i = 3;
   6542            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   6543                i++;
   6544            }
   6545 
   6546            for (j = 0; isxdigit((unsigned char)buf[i]) && j < sizeof msg; i += 2, j++) {
   6547                hex_to_byteval(&buf[i], &msg[j]);
   6548            }
   6549 
   6550            shaLength = fips_hashLen(shaAlg);
   6551            if (fips_hashBuf(shaAlg, sha, msg, j) != SECSuccess) {
   6552                if (shaLength == 0) {
   6553                    fprintf(rsaresp, "ERROR: SHAAlg not defined.");
   6554                }
   6555                fprintf(rsaresp, "ERROR: Unable to generate SHA%x",
   6556                        shaLength == 160 ? 1 : shaLength);
   6557                goto loser;
   6558            }
   6559 
   6560            fputs(buf, rsaresp);
   6561            continue;
   6562        }
   6563 
   6564        /* S = ... */
   6565        if (buf[0] == 'S') {
   6566            SECStatus rv = SECFailure;
   6567            NSSLOWKEYPublicKey *rsa_public_key;
   6568            NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
   6569                                                      NSSLOWKEYRSAKey };
   6570 
   6571            /* convert to a low RSA public key */
   6572            low_RSA_public_key.u.rsa = rsaBlapiPublicKey;
   6573            rsa_public_key = &low_RSA_public_key;
   6574 
   6575            memset(signature, 0, sizeof(signature));
   6576            i = 1;
   6577            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   6578                i++;
   6579            }
   6580 
   6581            for (j = 0; isxdigit((unsigned char)buf[i]) && j < sizeof signature; i += 2, j++) {
   6582                hex_to_byteval(&buf[i], &signature[j]);
   6583            }
   6584 
   6585            signatureLength = j;
   6586            fputs(buf, rsaresp);
   6587 
   6588            shaOid = fips_hashOid(shaAlg);
   6589 
   6590            /* Perform RSA verification with the RSA public key. */
   6591            rv = RSA_HashCheckSign(shaOid,
   6592                                   rsa_public_key,
   6593                                   signature,
   6594                                   signatureLength,
   6595                                   sha,
   6596                                   shaLength);
   6597            if (rv == SECSuccess) {
   6598                fputs("Result = P\n", rsaresp);
   6599            } else {
   6600                fputs("Result = F\n", rsaresp);
   6601            }
   6602            continue;
   6603        }
   6604    }
   6605 loser:
   6606    fclose(rsareq);
   6607    if (rsaBlapiPublicKey.modulus.data) { /* n */
   6608        SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
   6609    }
   6610    if (rsaBlapiPublicKey.publicExponent.data) { /* e */
   6611        SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
   6612    }
   6613 }
   6614 
   6615 void
   6616 tls(char *reqfn)
   6617 {
   6618    char buf[256]; /* holds one line from the input REQUEST file.
   6619                    * needs to be large enough to hold the longest
   6620                    * line "XSeed = <128 hex digits>\n".
   6621                    */
   6622    unsigned char *pms = NULL;
   6623    int pms_len;
   6624    unsigned char *master_secret = NULL;
   6625    unsigned char *key_block = NULL;
   6626    int key_block_len;
   6627    unsigned char serverHello_random[SSL3_RANDOM_LENGTH];
   6628    unsigned char clientHello_random[SSL3_RANDOM_LENGTH];
   6629    unsigned char server_random[SSL3_RANDOM_LENGTH];
   6630    unsigned char client_random[SSL3_RANDOM_LENGTH];
   6631    FILE *tlsreq = NULL; /* input stream from the REQUEST file */
   6632    FILE *tlsresp;       /* output stream to the RESPONSE file */
   6633    unsigned int i, j;
   6634    CK_SLOT_ID slotList[10];
   6635    CK_SLOT_ID slotID;
   6636    CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
   6637    CK_ULONG count;
   6638    static const CK_C_INITIALIZE_ARGS pk11args = {
   6639        NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
   6640        (void *)"flags=readOnly,noCertDB,noModDB", NULL
   6641    };
   6642    static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY;
   6643    static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
   6644    static CK_BBOOL ck_true = CK_TRUE;
   6645    static CK_ULONG one = 1;
   6646    CK_ATTRIBUTE create_template[] = {
   6647        { CKA_VALUE, NULL, 0 },
   6648        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
   6649        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
   6650        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
   6651    };
   6652    CK_ULONG create_template_count =
   6653        sizeof(create_template) / sizeof(create_template[0]);
   6654    CK_ATTRIBUTE derive_template[] = {
   6655        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
   6656        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
   6657        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
   6658        { CKA_VALUE_LEN, &one, sizeof(one) },
   6659    };
   6660    CK_ULONG derive_template_count =
   6661        sizeof(derive_template) / sizeof(derive_template[0]);
   6662    CK_ATTRIBUTE master_template = { CKA_VALUE, NULL, 0 };
   6663    CK_ATTRIBUTE kb1_template = { CKA_VALUE, NULL, 0 };
   6664    CK_ATTRIBUTE kb2_template = { CKA_VALUE, NULL, 0 };
   6665 
   6666    CK_MECHANISM master_mech = { CKM_TLS_MASTER_KEY_DERIVE, NULL, 0 };
   6667    CK_MECHANISM key_block_mech = { CKM_TLS_KEY_AND_MAC_DERIVE, NULL, 0 };
   6668    CK_TLS12_MASTER_KEY_DERIVE_PARAMS master_params;
   6669    CK_TLS12_KEY_MAT_PARAMS key_block_params;
   6670    CK_SSL3_KEY_MAT_OUT key_material;
   6671    CK_RV crv;
   6672 
   6673    /* set up PKCS #11 parameters */
   6674    master_params.prfHashMechanism = CKM_SHA256;
   6675    master_params.pVersion = NULL;
   6676    master_params.RandomInfo.pClientRandom = clientHello_random;
   6677    master_params.RandomInfo.ulClientRandomLen = sizeof(clientHello_random);
   6678    master_params.RandomInfo.pServerRandom = serverHello_random;
   6679    master_params.RandomInfo.ulServerRandomLen = sizeof(serverHello_random);
   6680    master_mech.pParameter = (void *)&master_params;
   6681    master_mech.ulParameterLen = sizeof(master_params);
   6682    key_block_params.prfHashMechanism = CKM_SHA256;
   6683    key_block_params.ulMacSizeInBits = 0;
   6684    key_block_params.ulKeySizeInBits = 0;
   6685    key_block_params.ulIVSizeInBits = 0;
   6686    key_block_params.bIsExport = PR_FALSE; /* ignored anyway for TLS mech */
   6687    key_block_params.RandomInfo.pClientRandom = client_random;
   6688    key_block_params.RandomInfo.ulClientRandomLen = sizeof(client_random);
   6689    key_block_params.RandomInfo.pServerRandom = server_random;
   6690    key_block_params.RandomInfo.ulServerRandomLen = sizeof(server_random);
   6691    key_block_params.pReturnedKeyMaterial = &key_material;
   6692    key_block_mech.pParameter = (void *)&key_block_params;
   6693    key_block_mech.ulParameterLen = sizeof(key_block_params);
   6694 
   6695    crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
   6696    if (crv != CKR_OK) {
   6697        fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
   6698        goto loser;
   6699    }
   6700    count = slotListCount;
   6701    crv = NSC_GetSlotList(PR_TRUE, slotList, &count);
   6702    if (crv != CKR_OK) {
   6703        fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
   6704        goto loser;
   6705    }
   6706    if ((count > slotListCount) || count < 1) {
   6707        fprintf(stderr,
   6708                "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
   6709                (int)count, (int)slotListCount);
   6710        goto loser;
   6711    }
   6712    slotID = slotList[0];
   6713    tlsreq = fopen(reqfn, "r");
   6714    tlsresp = stdout;
   6715    while (fgets(buf, sizeof buf, tlsreq) != NULL) {
   6716        /* a comment or blank line */
   6717        if (buf[0] == '#' || buf[0] == '\n') {
   6718            fputs(buf, tlsresp);
   6719            continue;
   6720        }
   6721        /* [Xchange - SHA1] */
   6722        if (buf[0] == '[') {
   6723            if (strncmp(buf, "[TLS", 4) == 0) {
   6724                if (buf[7] == '0') {
   6725                    /* CK_SSL3_MASTER_KEY_DERIVE_PARAMS is a subset of
   6726                     * CK_TLS12_MASTER_KEY_DERIVE_PARAMS and
   6727                     * CK_SSL3_KEY_MAT_PARAMS is a subset of
   6728                     * CK_TLS12_KEY_MAT_PARAMS. The latter params have
   6729                     * an extra prfHashMechanism field at the end. */
   6730                    master_mech.mechanism = CKM_TLS_MASTER_KEY_DERIVE;
   6731                    key_block_mech.mechanism = CKM_TLS_KEY_AND_MAC_DERIVE;
   6732                    master_mech.ulParameterLen = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS);
   6733                    key_block_mech.ulParameterLen = sizeof(CK_SSL3_KEY_MAT_PARAMS);
   6734                } else if (buf[7] == '2') {
   6735                    if (strncmp(&buf[10], "SHA-1", 5) == 0) {
   6736                        master_params.prfHashMechanism = CKM_SHA_1;
   6737                        key_block_params.prfHashMechanism = CKM_SHA_1;
   6738                    } else if (strncmp(&buf[10], "SHA-224", 7) == 0) {
   6739                        master_params.prfHashMechanism = CKM_SHA224;
   6740                        key_block_params.prfHashMechanism = CKM_SHA224;
   6741                    } else if (strncmp(&buf[10], "SHA-256", 7) == 0) {
   6742                        master_params.prfHashMechanism = CKM_SHA256;
   6743                        key_block_params.prfHashMechanism = CKM_SHA256;
   6744                    } else if (strncmp(&buf[10], "SHA-384", 7) == 0) {
   6745                        master_params.prfHashMechanism = CKM_SHA384;
   6746                        key_block_params.prfHashMechanism = CKM_SHA384;
   6747                    } else if (strncmp(&buf[10], "SHA-512", 7) == 0) {
   6748                        master_params.prfHashMechanism = CKM_SHA512;
   6749                        key_block_params.prfHashMechanism = CKM_SHA512;
   6750                    } else {
   6751                        fprintf(tlsresp, "ERROR: Unable to find prf Hash type");
   6752                        goto loser;
   6753                    }
   6754                    master_mech.mechanism = CKM_TLS12_MASTER_KEY_DERIVE;
   6755                    key_block_mech.mechanism = CKM_TLS12_KEY_AND_MAC_DERIVE;
   6756                    master_mech.ulParameterLen = sizeof(master_params);
   6757                    key_block_mech.ulParameterLen = sizeof(key_block_params);
   6758                } else {
   6759                    fprintf(stderr, "Unknown TLS type %x\n",
   6760                            (unsigned int)buf[0]);
   6761                    goto loser;
   6762                }
   6763            }
   6764            if (strncmp(buf, "[pre-master", 11) == 0) {
   6765                if (sscanf(buf, "[pre-master secret length = %d]",
   6766                           &pms_len) != 1) {
   6767                    goto loser;
   6768                }
   6769                pms_len = pms_len / 8;
   6770                pms = malloc(pms_len);
   6771                master_secret = malloc(pms_len);
   6772                create_template[0].pValue = pms;
   6773                create_template[0].ulValueLen = pms_len;
   6774                master_template.pValue = master_secret;
   6775                master_template.ulValueLen = pms_len;
   6776            }
   6777            if (strncmp(buf, "[key", 4) == 0) {
   6778                if (sscanf(buf, "[key block length = %d]", &key_block_len) != 1) {
   6779                    goto loser;
   6780                }
   6781                key_block_params.ulKeySizeInBits = 8;
   6782                key_block_params.ulIVSizeInBits = key_block_len / 2 - 8;
   6783                key_block_len = key_block_len / 8;
   6784                key_block = malloc(key_block_len);
   6785                kb1_template.pValue = &key_block[0];
   6786                kb1_template.ulValueLen = 1;
   6787                kb2_template.pValue = &key_block[1];
   6788                kb2_template.ulValueLen = 1;
   6789                key_material.pIVClient = &key_block[2];
   6790                key_material.pIVServer = &key_block[2 + key_block_len / 2 - 1];
   6791            }
   6792            fputs(buf, tlsresp);
   6793            continue;
   6794        }
   6795        /* "COUNT = x" begins a new data set */
   6796        if (strncmp(buf, "COUNT", 5) == 0) {
   6797            /* zeroize the variables for the test with this data set */
   6798            memset(pms, 0, pms_len);
   6799            memset(master_secret, 0, pms_len);
   6800            memset(key_block, 0, key_block_len);
   6801            fputs(buf, tlsresp);
   6802            continue;
   6803        }
   6804        /* pre_master_secret = ... */
   6805        if (strncmp(buf, "pre_master_secret", 17) == 0) {
   6806            i = 17;
   6807            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   6808                i++;
   6809            }
   6810            for (j = 0; j < pms_len; i += 2, j++) {
   6811                hex_to_byteval(&buf[i], &pms[j]);
   6812            }
   6813            fputs(buf, tlsresp);
   6814            continue;
   6815        }
   6816        /* serverHello_random = ... */
   6817        if (strncmp(buf, "serverHello_random", 18) == 0) {
   6818            i = 18;
   6819            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   6820                i++;
   6821            }
   6822            for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) {
   6823                hex_to_byteval(&buf[i], &serverHello_random[j]);
   6824            }
   6825            fputs(buf, tlsresp);
   6826            continue;
   6827        }
   6828        /* clientHello_random = ... */
   6829        if (strncmp(buf, "clientHello_random", 18) == 0) {
   6830            i = 18;
   6831            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   6832                i++;
   6833            }
   6834            for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) {
   6835                hex_to_byteval(&buf[i], &clientHello_random[j]);
   6836            }
   6837            fputs(buf, tlsresp);
   6838            continue;
   6839        }
   6840        /* server_random = ... */
   6841        if (strncmp(buf, "server_random", 13) == 0) {
   6842            i = 13;
   6843            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   6844                i++;
   6845            }
   6846            for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) {
   6847                hex_to_byteval(&buf[i], &server_random[j]);
   6848            }
   6849            fputs(buf, tlsresp);
   6850            continue;
   6851        }
   6852        /* client_random = ... */
   6853        if (strncmp(buf, "client_random", 13) == 0) {
   6854            CK_SESSION_HANDLE session;
   6855            CK_OBJECT_HANDLE pms_handle;
   6856            CK_OBJECT_HANDLE master_handle;
   6857            CK_OBJECT_HANDLE fake_handle;
   6858            i = 13;
   6859            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   6860                i++;
   6861            }
   6862            for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) {
   6863                hex_to_byteval(&buf[i], &client_random[j]);
   6864            }
   6865            fputs(buf, tlsresp);
   6866            crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
   6867            if (crv != CKR_OK) {
   6868                fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n",
   6869                        (unsigned int)crv);
   6870                goto loser;
   6871            }
   6872            crv = NSC_CreateObject(session, create_template,
   6873                                   create_template_count, &pms_handle);
   6874            if (crv != CKR_OK) {
   6875                fprintf(stderr, "NSC_CreateObject failed crv=0x%x\n",
   6876                        (unsigned int)crv);
   6877                goto loser;
   6878            }
   6879            crv = NSC_DeriveKey(session, &master_mech, pms_handle,
   6880                                derive_template, derive_template_count - 1,
   6881                                &master_handle);
   6882            if (crv != CKR_OK) {
   6883                fprintf(stderr, "NSC_DeriveKey(master) failed crv=0x%x\n",
   6884                        (unsigned int)crv);
   6885                goto loser;
   6886            }
   6887            crv = NSC_GetAttributeValue(session, master_handle,
   6888                                        &master_template, 1);
   6889            if (crv != CKR_OK) {
   6890                fprintf(stderr, "NSC_GetAttribute failed crv=0x%x\n",
   6891                        (unsigned int)crv);
   6892                goto loser;
   6893            }
   6894            fputs("master_secret = ", tlsresp);
   6895            to_hex_str(buf, master_secret, pms_len);
   6896            fputs(buf, tlsresp);
   6897            fputc('\n', tlsresp);
   6898            crv = NSC_DeriveKey(session, &key_block_mech, master_handle,
   6899                                derive_template, derive_template_count, &fake_handle);
   6900            if (crv != CKR_OK) {
   6901                fprintf(stderr,
   6902                        "NSC_DeriveKey(keyblock) failed crv=0x%x\n",
   6903                        (unsigned int)crv);
   6904                goto loser;
   6905            }
   6906            crv = NSC_GetAttributeValue(session, key_material.hClientKey,
   6907                                        &kb1_template, 1);
   6908            if (crv != CKR_OK) {
   6909                fprintf(stderr, "NSC_GetAttribute failed crv=0x%x\n",
   6910                        (unsigned int)crv);
   6911                goto loser;
   6912            }
   6913            crv = NSC_GetAttributeValue(session, key_material.hServerKey,
   6914                                        &kb2_template, 1);
   6915            if (crv != CKR_OK) {
   6916                fprintf(stderr, "NSC_GetAttribute failed crv=0x%x\n",
   6917                        (unsigned int)crv);
   6918                goto loser;
   6919            }
   6920            fputs("key_block = ", tlsresp);
   6921            to_hex_str(buf, key_block, key_block_len);
   6922            fputs(buf, tlsresp);
   6923            fputc('\n', tlsresp);
   6924            crv = NSC_CloseSession(session);
   6925            continue;
   6926        }
   6927    }
   6928 loser:
   6929    NSC_Finalize(NULL);
   6930    if (pms)
   6931        free(pms);
   6932    if (master_secret)
   6933        free(master_secret);
   6934    if (key_block)
   6935        free(key_block);
   6936    if (tlsreq)
   6937        fclose(tlsreq);
   6938 }
   6939 
   6940 void
   6941 ikev1(char *reqfn)
   6942 {
   6943    char buf[4096]; /* holds one line from the input REQUEST file.
   6944                     * needs to be large enough to hold the longest
   6945                     * line "g^xy = <2048 hex digits>\n".
   6946                     */
   6947    unsigned char *gxy = NULL;
   6948    int gxy_len;
   6949    unsigned char *Ni = NULL;
   6950    int Ni_len;
   6951    unsigned char *Nr = NULL;
   6952    int Nr_len;
   6953    unsigned char CKYi[8];
   6954    int CKYi_len;
   6955    unsigned char CKYr[8];
   6956    int CKYr_len;
   6957    unsigned int i, j;
   6958    FILE *ikereq = NULL; /* input stream from the REQUEST file */
   6959    FILE *ikeresp;       /* output stream to the RESPONSE file */
   6960 
   6961    CK_SLOT_ID slotList[10];
   6962    CK_SLOT_ID slotID;
   6963    CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
   6964    CK_ULONG count;
   6965    static const CK_C_INITIALIZE_ARGS pk11args = {
   6966        NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
   6967        (void *)"flags=readOnly,noCertDB,noModDB", NULL
   6968    };
   6969    static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY;
   6970    static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
   6971    static CK_BBOOL ck_true = CK_TRUE;
   6972    static CK_ULONG keyLen = 1;
   6973    CK_ATTRIBUTE gxy_template[] = {
   6974        { CKA_VALUE, NULL, 0 }, /* must be first */
   6975        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
   6976        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
   6977        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
   6978    };
   6979    CK_ULONG gxy_template_count =
   6980        sizeof(gxy_template) / sizeof(gxy_template[0]);
   6981    CK_ATTRIBUTE derive_template[] = {
   6982        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
   6983        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
   6984        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
   6985        { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) }, /* must be last */
   6986    };
   6987    CK_ULONG derive_template_count =
   6988        sizeof(derive_template) / sizeof(derive_template[0]);
   6989    CK_ATTRIBUTE skeyid_template = { CKA_VALUE, NULL, 0 };
   6990    CK_ATTRIBUTE skeyid_d_template = { CKA_VALUE, NULL, 0 };
   6991    CK_ATTRIBUTE skeyid_a_template = { CKA_VALUE, NULL, 0 };
   6992    CK_ATTRIBUTE skeyid_e_template = { CKA_VALUE, NULL, 0 };
   6993    unsigned char skeyid_secret[HASH_LENGTH_MAX];
   6994    unsigned char skeyid_d_secret[HASH_LENGTH_MAX];
   6995    unsigned char skeyid_a_secret[HASH_LENGTH_MAX];
   6996    unsigned char skeyid_e_secret[HASH_LENGTH_MAX];
   6997 
   6998    CK_MECHANISM ike_mech = { CKM_IKE_PRF_DERIVE, NULL, 0 };
   6999    CK_MECHANISM ike1_mech = { CKM_IKE1_PRF_DERIVE, NULL, 0 };
   7000    CK_IKE_PRF_DERIVE_PARAMS ike_prf;
   7001    CK_IKE1_PRF_DERIVE_PARAMS ike1_prf;
   7002    CK_RV crv;
   7003 
   7004    /* set up PKCS #11 parameters */
   7005    ike_prf.bDataAsKey = PR_TRUE;
   7006    ike_prf.bRekey = PR_FALSE;
   7007    ike_prf.hNewKey = CK_INVALID_HANDLE;
   7008    CKYi_len = sizeof(CKYi);
   7009    CKYr_len = sizeof(CKYr);
   7010    ike1_prf.pCKYi = CKYi;
   7011    ike1_prf.ulCKYiLen = CKYi_len;
   7012    ike1_prf.pCKYr = CKYr;
   7013    ike1_prf.ulCKYrLen = CKYr_len;
   7014    ike_mech.pParameter = &ike_prf;
   7015    ike_mech.ulParameterLen = sizeof(ike_prf);
   7016    ike1_mech.pParameter = &ike1_prf;
   7017    ike1_mech.ulParameterLen = sizeof(ike1_prf);
   7018    skeyid_template.pValue = skeyid_secret;
   7019    skeyid_template.ulValueLen = HASH_LENGTH_MAX;
   7020    skeyid_d_template.pValue = skeyid_d_secret;
   7021    skeyid_d_template.ulValueLen = HASH_LENGTH_MAX;
   7022    skeyid_a_template.pValue = skeyid_a_secret;
   7023    skeyid_a_template.ulValueLen = HASH_LENGTH_MAX;
   7024    skeyid_e_template.pValue = skeyid_e_secret;
   7025    skeyid_e_template.ulValueLen = HASH_LENGTH_MAX;
   7026 
   7027    crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
   7028    if (crv != CKR_OK) {
   7029        fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
   7030        goto loser;
   7031    }
   7032    count = slotListCount;
   7033    crv = NSC_GetSlotList(PR_TRUE, slotList, &count);
   7034    if (crv != CKR_OK) {
   7035        fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
   7036        goto loser;
   7037    }
   7038    if ((count > slotListCount) || count < 1) {
   7039        fprintf(stderr,
   7040                "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
   7041                (int)count, (int)slotListCount);
   7042        goto loser;
   7043    }
   7044    slotID = slotList[0];
   7045    ikereq = fopen(reqfn, "r");
   7046    ikeresp = stdout;
   7047    while (fgets(buf, sizeof buf, ikereq) != NULL) {
   7048        /* a comment or blank line */
   7049        if (buf[0] == '#' || buf[0] == '\n') {
   7050            fputs(buf, ikeresp);
   7051            continue;
   7052        }
   7053        /* [.....] */
   7054        if (buf[0] == '[') {
   7055            if (strncmp(buf, "[SHA-1]", 7) == 0) {
   7056                ike_prf.prfMechanism = CKM_SHA_1_HMAC;
   7057                ike1_prf.prfMechanism = CKM_SHA_1_HMAC;
   7058            }
   7059            if (strncmp(buf, "[SHA-224]", 9) == 0) {
   7060                ike_prf.prfMechanism = CKM_SHA224_HMAC;
   7061                ike1_prf.prfMechanism = CKM_SHA224_HMAC;
   7062            }
   7063            if (strncmp(buf, "[SHA-256]", 9) == 0) {
   7064                ike_prf.prfMechanism = CKM_SHA256_HMAC;
   7065                ike1_prf.prfMechanism = CKM_SHA256_HMAC;
   7066            }
   7067            if (strncmp(buf, "[SHA-384]", 9) == 0) {
   7068                ike_prf.prfMechanism = CKM_SHA384_HMAC;
   7069                ike1_prf.prfMechanism = CKM_SHA384_HMAC;
   7070            }
   7071            if (strncmp(buf, "[SHA-512]", 9) == 0) {
   7072                ike_prf.prfMechanism = CKM_SHA512_HMAC;
   7073                ike1_prf.prfMechanism = CKM_SHA512_HMAC;
   7074            }
   7075            if (strncmp(buf, "[AES-XCBC", 9) == 0) {
   7076                ike_prf.prfMechanism = CKM_AES_XCBC_MAC;
   7077                ike1_prf.prfMechanism = CKM_AES_XCBC_MAC;
   7078            }
   7079            if (strncmp(buf, "[g^xy", 5) == 0) {
   7080                if (sscanf(buf, "[g^xy length = %d]",
   7081                           &gxy_len) != 1) {
   7082                    goto loser;
   7083                }
   7084                gxy_len = gxy_len / 8;
   7085                if (gxy)
   7086                    free(gxy);
   7087                gxy = malloc(gxy_len);
   7088                gxy_template[0].pValue = gxy;
   7089                gxy_template[0].ulValueLen = gxy_len;
   7090            }
   7091            if (strncmp(buf, "[Ni", 3) == 0) {
   7092                if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) {
   7093                    goto loser;
   7094                }
   7095                Ni_len = Ni_len / 8;
   7096                if (Ni)
   7097                    free(Ni);
   7098                Ni = malloc(Ni_len);
   7099                ike_prf.pNi = Ni;
   7100                ike_prf.ulNiLen = Ni_len;
   7101            }
   7102            if (strncmp(buf, "[Nr", 3) == 0) {
   7103                if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) {
   7104                    goto loser;
   7105                }
   7106                Nr_len = Nr_len / 8;
   7107                if (Nr)
   7108                    free(Nr);
   7109                Nr = malloc(Nr_len);
   7110                ike_prf.pNr = Nr;
   7111                ike_prf.ulNrLen = Nr_len;
   7112            }
   7113            fputs(buf, ikeresp);
   7114            continue;
   7115        }
   7116        /* "COUNT = x" begins a new data set */
   7117        if (strncmp(buf, "COUNT", 5) == 0) {
   7118            /* zeroize the variables for the test with this data set */
   7119            memset(gxy, 0, gxy_len);
   7120            memset(Ni, 0, Ni_len);
   7121            memset(Nr, 0, Nr_len);
   7122            memset(CKYi, 0, CKYi_len);
   7123            memset(CKYr, 0, CKYr_len);
   7124            fputs(buf, ikeresp);
   7125            continue;
   7126        }
   7127        /* Ni = ... */
   7128        if (strncmp(buf, "Ni", 2) == 0) {
   7129            i = 2;
   7130            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   7131                i++;
   7132            }
   7133            for (j = 0; j < Ni_len; i += 2, j++) {
   7134                hex_to_byteval(&buf[i], &Ni[j]);
   7135            }
   7136            fputs(buf, ikeresp);
   7137            continue;
   7138        }
   7139        /* Nr = ... */
   7140        if (strncmp(buf, "Nr", 2) == 0) {
   7141            i = 2;
   7142            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   7143                i++;
   7144            }
   7145            for (j = 0; j < Nr_len; i += 2, j++) {
   7146                hex_to_byteval(&buf[i], &Nr[j]);
   7147            }
   7148            fputs(buf, ikeresp);
   7149            continue;
   7150        }
   7151        /* CKYi = ... */
   7152        if (strncmp(buf, "CKY_I", 5) == 0) {
   7153            i = 5;
   7154            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   7155                i++;
   7156            }
   7157            for (j = 0; j < CKYi_len; i += 2, j++) {
   7158                hex_to_byteval(&buf[i], &CKYi[j]);
   7159            }
   7160            fputs(buf, ikeresp);
   7161            continue;
   7162        }
   7163        /* CKYr = ... */
   7164        if (strncmp(buf, "CKY_R", 5) == 0) {
   7165            i = 5;
   7166            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   7167                i++;
   7168            }
   7169            for (j = 0; j < CKYr_len; i += 2, j++) {
   7170                hex_to_byteval(&buf[i], &CKYr[j]);
   7171            }
   7172            fputs(buf, ikeresp);
   7173            continue;
   7174        }
   7175        /* g^xy = ... */
   7176        if (strncmp(buf, "g^xy", 4) == 0) {
   7177            CK_SESSION_HANDLE session;
   7178            CK_OBJECT_HANDLE gxy_handle;
   7179            CK_OBJECT_HANDLE skeyid_handle;
   7180            CK_OBJECT_HANDLE skeyid_d_handle;
   7181            CK_OBJECT_HANDLE skeyid_a_handle;
   7182            CK_OBJECT_HANDLE skeyid_e_handle;
   7183            i = 4;
   7184            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   7185                i++;
   7186            }
   7187            for (j = 0; j < gxy_len; i += 2, j++) {
   7188                hex_to_byteval(&buf[i], &gxy[j]);
   7189            }
   7190            fputs(buf, ikeresp);
   7191            crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
   7192            if (crv != CKR_OK) {
   7193                fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n",
   7194                        (unsigned int)crv);
   7195                goto loser;
   7196            }
   7197            crv = NSC_CreateObject(session, gxy_template,
   7198                                   gxy_template_count, &gxy_handle);
   7199            if (crv != CKR_OK) {
   7200                fprintf(stderr, "NSC_CreateObject failed crv=0x%x\n",
   7201                        (unsigned int)crv);
   7202                goto loser;
   7203            }
   7204            /* get the skeyid key */
   7205            crv = NSC_DeriveKey(session, &ike_mech, gxy_handle,
   7206                                derive_template, derive_template_count - 1,
   7207                                &skeyid_handle);
   7208            if (crv != CKR_OK) {
   7209                fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n",
   7210                        (unsigned int)crv);
   7211                goto loser;
   7212            }
   7213            skeyid_template.ulValueLen = HASH_LENGTH_MAX;
   7214            crv = NSC_GetAttributeValue(session, skeyid_handle,
   7215                                        &skeyid_template, 1);
   7216            if (crv != CKR_OK) {
   7217                fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
   7218                        (unsigned int)crv);
   7219                goto loser;
   7220            }
   7221            /* use the length of the skeyid to set the target length of all the
   7222             * other keys */
   7223            keyLen = skeyid_template.ulValueLen;
   7224            ike1_prf.hKeygxy = gxy_handle;
   7225            ike1_prf.bHasPrevKey = PR_FALSE;
   7226            ike1_prf.keyNumber = 0;
   7227            crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
   7228                                derive_template, derive_template_count,
   7229                                &skeyid_d_handle);
   7230            if (crv != CKR_OK) {
   7231                fprintf(stderr, "NSC_DeriveKey(skeyid_d) failed crv=0x%x\n",
   7232                        (unsigned int)crv);
   7233                goto loser;
   7234            }
   7235 
   7236            ike1_prf.hKeygxy = gxy_handle;
   7237            ike1_prf.bHasPrevKey = CK_TRUE;
   7238            ike1_prf.hPrevKey = skeyid_d_handle;
   7239            ike1_prf.keyNumber = 1;
   7240            crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
   7241                                derive_template, derive_template_count,
   7242                                &skeyid_a_handle);
   7243            if (crv != CKR_OK) {
   7244                fprintf(stderr, "NSC_DeriveKey(skeyid_a) failed crv=0x%x\n",
   7245                        (unsigned int)crv);
   7246                goto loser;
   7247            }
   7248            ike1_prf.hKeygxy = gxy_handle;
   7249            ike1_prf.bHasPrevKey = CK_TRUE;
   7250            ike1_prf.hPrevKey = skeyid_a_handle;
   7251            ike1_prf.keyNumber = 2;
   7252            crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
   7253                                derive_template, derive_template_count,
   7254                                &skeyid_e_handle);
   7255            if (crv != CKR_OK) {
   7256                fprintf(stderr, "NSC_DeriveKey(skeyid_e) failed crv=0x%x\n",
   7257                        (unsigned int)crv);
   7258                goto loser;
   7259            }
   7260            fputs("SKEYID = ", ikeresp);
   7261            to_hex_str(buf, skeyid_secret, keyLen);
   7262            fputs(buf, ikeresp);
   7263            fputc('\n', ikeresp);
   7264 
   7265            skeyid_d_template.ulValueLen = keyLen;
   7266            crv = NSC_GetAttributeValue(session, skeyid_d_handle,
   7267                                        &skeyid_d_template, 1);
   7268            if (crv != CKR_OK) {
   7269                fprintf(stderr, "NSC_GetAttribute(skeyid_d) failed crv=0x%x\n",
   7270                        (unsigned int)crv);
   7271                goto loser;
   7272            }
   7273            fputs("SKEYID_d = ", ikeresp);
   7274            to_hex_str(buf, skeyid_d_secret, skeyid_d_template.ulValueLen);
   7275            fputs(buf, ikeresp);
   7276            fputc('\n', ikeresp);
   7277 
   7278            skeyid_a_template.ulValueLen = keyLen;
   7279            crv = NSC_GetAttributeValue(session, skeyid_a_handle,
   7280                                        &skeyid_a_template, 1);
   7281            if (crv != CKR_OK) {
   7282                fprintf(stderr, "NSC_GetAttribute(skeyid_a) failed crv=0x%x\n",
   7283                        (unsigned int)crv);
   7284                goto loser;
   7285            }
   7286            fputs("SKEYID_a = ", ikeresp);
   7287            to_hex_str(buf, skeyid_a_secret, skeyid_a_template.ulValueLen);
   7288            fputs(buf, ikeresp);
   7289            fputc('\n', ikeresp);
   7290 
   7291            skeyid_e_template.ulValueLen = keyLen;
   7292            crv = NSC_GetAttributeValue(session, skeyid_e_handle,
   7293                                        &skeyid_e_template, 1);
   7294            if (crv != CKR_OK) {
   7295                fprintf(stderr, "NSC_GetAttribute(skeyid_e) failed crv=0x%x\n",
   7296                        (unsigned int)crv);
   7297                goto loser;
   7298            }
   7299            fputs("SKEYID_e = ", ikeresp);
   7300            to_hex_str(buf, skeyid_e_secret, skeyid_e_template.ulValueLen);
   7301            fputs(buf, ikeresp);
   7302            fputc('\n', ikeresp);
   7303 
   7304            crv = NSC_CloseSession(session);
   7305            continue;
   7306        }
   7307    }
   7308 loser:
   7309    NSC_Finalize(NULL);
   7310    if (gxy)
   7311        free(gxy);
   7312    if (Ni)
   7313        free(Ni);
   7314    if (Nr)
   7315        free(Nr);
   7316    if (ikereq)
   7317        fclose(ikereq);
   7318 }
   7319 
   7320 void
   7321 ikev1_psk(char *reqfn)
   7322 {
   7323    char buf[4096]; /* holds one line from the input REQUEST file.
   7324                     * needs to be large enough to hold the longest
   7325                     * line "g^xy = <2048 hex digits>\n".
   7326                     */
   7327    unsigned char *gxy = NULL;
   7328    int gxy_len;
   7329    unsigned char *Ni = NULL;
   7330    int Ni_len;
   7331    unsigned char *Nr = NULL;
   7332    int Nr_len;
   7333    unsigned char CKYi[8];
   7334    int CKYi_len;
   7335    unsigned char CKYr[8];
   7336    int CKYr_len;
   7337    unsigned char *psk = NULL;
   7338    int psk_len;
   7339    unsigned int i, j;
   7340    FILE *ikereq = NULL; /* input stream from the REQUEST file */
   7341    FILE *ikeresp;       /* output stream to the RESPONSE file */
   7342 
   7343    CK_SLOT_ID slotList[10];
   7344    CK_SLOT_ID slotID;
   7345    CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
   7346    CK_ULONG count;
   7347    static const CK_C_INITIALIZE_ARGS pk11args = {
   7348        NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
   7349        (void *)"flags=readOnly,noCertDB,noModDB", NULL
   7350    };
   7351    static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY;
   7352    static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
   7353    static CK_BBOOL ck_true = CK_TRUE;
   7354    static CK_ULONG keyLen = 1;
   7355    CK_ATTRIBUTE gxy_template[] = {
   7356        { CKA_VALUE, NULL, 0 }, /* must be first */
   7357        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
   7358        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
   7359        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
   7360    };
   7361    CK_ULONG gxy_template_count =
   7362        sizeof(gxy_template) / sizeof(gxy_template[0]);
   7363    CK_ATTRIBUTE psk_template[] = {
   7364        { CKA_VALUE, NULL, 0 }, /* must be first */
   7365        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
   7366        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
   7367        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
   7368    };
   7369    CK_ULONG psk_template_count =
   7370        sizeof(psk_template) / sizeof(psk_template[0]);
   7371    CK_ATTRIBUTE derive_template[] = {
   7372        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
   7373        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
   7374        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
   7375        { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) }, /* must be last */
   7376    };
   7377    CK_ULONG derive_template_count =
   7378        sizeof(derive_template) / sizeof(derive_template[0]);
   7379    CK_ATTRIBUTE skeyid_template = { CKA_VALUE, NULL, 0 };
   7380    CK_ATTRIBUTE skeyid_d_template = { CKA_VALUE, NULL, 0 };
   7381    CK_ATTRIBUTE skeyid_a_template = { CKA_VALUE, NULL, 0 };
   7382    CK_ATTRIBUTE skeyid_e_template = { CKA_VALUE, NULL, 0 };
   7383    unsigned char skeyid_secret[HASH_LENGTH_MAX];
   7384    unsigned char skeyid_d_secret[HASH_LENGTH_MAX];
   7385    unsigned char skeyid_a_secret[HASH_LENGTH_MAX];
   7386    unsigned char skeyid_e_secret[HASH_LENGTH_MAX];
   7387 
   7388    CK_MECHANISM ike_mech = { CKM_IKE_PRF_DERIVE, NULL, 0 };
   7389    CK_MECHANISM ike1_mech = { CKM_IKE1_PRF_DERIVE, NULL, 0 };
   7390    CK_IKE_PRF_DERIVE_PARAMS ike_prf;
   7391    CK_IKE1_PRF_DERIVE_PARAMS ike1_prf;
   7392    CK_RV crv;
   7393 
   7394    /* set up PKCS #11 parameters */
   7395    ike_prf.bDataAsKey = PR_FALSE;
   7396    ike_prf.bRekey = PR_FALSE;
   7397    ike_prf.hNewKey = CK_INVALID_HANDLE;
   7398    CKYi_len = 8;
   7399    CKYr_len = 8;
   7400    ike1_prf.pCKYi = CKYi;
   7401    ike1_prf.ulCKYiLen = CKYi_len;
   7402    ike1_prf.pCKYr = CKYr;
   7403    ike1_prf.ulCKYrLen = CKYr_len;
   7404    ike_mech.pParameter = &ike_prf;
   7405    ike_mech.ulParameterLen = sizeof(ike_prf);
   7406    ike1_mech.pParameter = &ike1_prf;
   7407    ike1_mech.ulParameterLen = sizeof(ike1_prf);
   7408    skeyid_template.pValue = skeyid_secret;
   7409    skeyid_template.ulValueLen = HASH_LENGTH_MAX;
   7410    skeyid_d_template.pValue = skeyid_d_secret;
   7411    skeyid_d_template.ulValueLen = HASH_LENGTH_MAX;
   7412    skeyid_a_template.pValue = skeyid_a_secret;
   7413    skeyid_a_template.ulValueLen = HASH_LENGTH_MAX;
   7414    skeyid_e_template.pValue = skeyid_e_secret;
   7415    skeyid_e_template.ulValueLen = HASH_LENGTH_MAX;
   7416 
   7417    crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
   7418    if (crv != CKR_OK) {
   7419        fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
   7420        goto loser;
   7421    }
   7422    count = slotListCount;
   7423    crv = NSC_GetSlotList(PR_TRUE, slotList, &count);
   7424    if (crv != CKR_OK) {
   7425        fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
   7426        goto loser;
   7427    }
   7428    if ((count > slotListCount) || count < 1) {
   7429        fprintf(stderr,
   7430                "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
   7431                (int)count, (int)slotListCount);
   7432        goto loser;
   7433    }
   7434    slotID = slotList[0];
   7435    ikereq = fopen(reqfn, "r");
   7436    ikeresp = stdout;
   7437    while (fgets(buf, sizeof buf, ikereq) != NULL) {
   7438        /* a comment or blank line */
   7439        if (buf[0] == '#' || buf[0] == '\n') {
   7440            fputs(buf, ikeresp);
   7441            continue;
   7442        }
   7443        /* [.....] */
   7444        if (buf[0] == '[') {
   7445            if (strncmp(buf, "[SHA-1]", 7) == 0) {
   7446                ike_prf.prfMechanism = CKM_SHA_1_HMAC;
   7447                ike1_prf.prfMechanism = CKM_SHA_1_HMAC;
   7448            }
   7449            if (strncmp(buf, "[SHA-224]", 9) == 0) {
   7450                ike_prf.prfMechanism = CKM_SHA224_HMAC;
   7451                ike1_prf.prfMechanism = CKM_SHA224_HMAC;
   7452            }
   7453            if (strncmp(buf, "[SHA-256]", 9) == 0) {
   7454                ike_prf.prfMechanism = CKM_SHA256_HMAC;
   7455                ike1_prf.prfMechanism = CKM_SHA256_HMAC;
   7456            }
   7457            if (strncmp(buf, "[SHA-384]", 9) == 0) {
   7458                ike_prf.prfMechanism = CKM_SHA384_HMAC;
   7459                ike1_prf.prfMechanism = CKM_SHA384_HMAC;
   7460            }
   7461            if (strncmp(buf, "[SHA-512]", 9) == 0) {
   7462                ike_prf.prfMechanism = CKM_SHA512_HMAC;
   7463                ike1_prf.prfMechanism = CKM_SHA512_HMAC;
   7464            }
   7465            if (strncmp(buf, "[AES-XCBC", 9) == 0) {
   7466                ike_prf.prfMechanism = CKM_AES_XCBC_MAC;
   7467                ike1_prf.prfMechanism = CKM_AES_XCBC_MAC;
   7468            }
   7469            if (strncmp(buf, "[g^xy", 5) == 0) {
   7470                if (sscanf(buf, "[g^xy length = %d]",
   7471                           &gxy_len) != 1) {
   7472                    goto loser;
   7473                }
   7474                gxy_len = gxy_len / 8;
   7475                if (gxy)
   7476                    free(gxy);
   7477                gxy = malloc(gxy_len);
   7478                gxy_template[0].pValue = gxy;
   7479                gxy_template[0].ulValueLen = gxy_len;
   7480            }
   7481            if (strncmp(buf, "[pre-shared-key", 15) == 0) {
   7482                if (sscanf(buf, "[pre-shared-key length = %d]",
   7483                           &psk_len) != 1) {
   7484                    goto loser;
   7485                }
   7486                psk_len = psk_len / 8;
   7487                if (psk)
   7488                    free(psk);
   7489                psk = malloc(psk_len);
   7490                psk_template[0].pValue = psk;
   7491                psk_template[0].ulValueLen = psk_len;
   7492            }
   7493            if (strncmp(buf, "[Ni", 3) == 0) {
   7494                if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) {
   7495                    goto loser;
   7496                }
   7497                Ni_len = Ni_len / 8;
   7498                if (Ni)
   7499                    free(Ni);
   7500                Ni = malloc(Ni_len);
   7501                ike_prf.pNi = Ni;
   7502                ike_prf.ulNiLen = Ni_len;
   7503            }
   7504            if (strncmp(buf, "[Nr", 3) == 0) {
   7505                if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) {
   7506                    goto loser;
   7507                }
   7508                Nr_len = Nr_len / 8;
   7509                if (Nr)
   7510                    free(Nr);
   7511                Nr = malloc(Nr_len);
   7512                ike_prf.pNr = Nr;
   7513                ike_prf.ulNrLen = Nr_len;
   7514            }
   7515            fputs(buf, ikeresp);
   7516            continue;
   7517        }
   7518        /* "COUNT = x" begins a new data set */
   7519        if (strncmp(buf, "COUNT", 5) == 0) {
   7520            /* zeroize the variables for the test with this data set */
   7521            memset(gxy, 0, gxy_len);
   7522            memset(Ni, 0, Ni_len);
   7523            memset(Nr, 0, Nr_len);
   7524            memset(CKYi, 0, CKYi_len);
   7525            memset(CKYr, 0, CKYr_len);
   7526            fputs(buf, ikeresp);
   7527            continue;
   7528        }
   7529        /* Ni = ... */
   7530        if (strncmp(buf, "Ni", 2) == 0) {
   7531            i = 2;
   7532            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   7533                i++;
   7534            }
   7535            for (j = 0; j < Ni_len; i += 2, j++) {
   7536                hex_to_byteval(&buf[i], &Ni[j]);
   7537            }
   7538            fputs(buf, ikeresp);
   7539            continue;
   7540        }
   7541        /* Nr = ... */
   7542        if (strncmp(buf, "Nr", 2) == 0) {
   7543            i = 2;
   7544            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   7545                i++;
   7546            }
   7547            for (j = 0; j < Nr_len; i += 2, j++) {
   7548                hex_to_byteval(&buf[i], &Nr[j]);
   7549            }
   7550            fputs(buf, ikeresp);
   7551            continue;
   7552        }
   7553        /* CKYi = ... */
   7554        if (strncmp(buf, "CKY_I", 5) == 0) {
   7555            i = 5;
   7556            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   7557                i++;
   7558            }
   7559            for (j = 0; j < CKYi_len; i += 2, j++) {
   7560                hex_to_byteval(&buf[i], &CKYi[j]);
   7561            }
   7562            fputs(buf, ikeresp);
   7563            continue;
   7564        }
   7565        /* CKYr = ... */
   7566        if (strncmp(buf, "CKY_R", 5) == 0) {
   7567            i = 5;
   7568            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   7569                i++;
   7570            }
   7571            for (j = 0; j < CKYr_len; i += 2, j++) {
   7572                hex_to_byteval(&buf[i], &CKYr[j]);
   7573            }
   7574            fputs(buf, ikeresp);
   7575            continue;
   7576        }
   7577        /* g^xy = ... */
   7578        if (strncmp(buf, "g^xy", 4) == 0) {
   7579            i = 4;
   7580            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   7581                i++;
   7582            }
   7583            for (j = 0; j < gxy_len; i += 2, j++) {
   7584                hex_to_byteval(&buf[i], &gxy[j]);
   7585            }
   7586            fputs(buf, ikeresp);
   7587            continue;
   7588        }
   7589        /* pre-shared-key = ... */
   7590        if (strncmp(buf, "pre-shared-key", 14) == 0) {
   7591            CK_SESSION_HANDLE session;
   7592            CK_OBJECT_HANDLE gxy_handle;
   7593            CK_OBJECT_HANDLE psk_handle;
   7594            CK_OBJECT_HANDLE skeyid_handle;
   7595            CK_OBJECT_HANDLE skeyid_d_handle;
   7596            CK_OBJECT_HANDLE skeyid_a_handle;
   7597            CK_OBJECT_HANDLE skeyid_e_handle;
   7598            i = 14;
   7599            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   7600                i++;
   7601            }
   7602            for (j = 0; j < psk_len; i += 2, j++) {
   7603                hex_to_byteval(&buf[i], &psk[j]);
   7604            }
   7605            fputs(buf, ikeresp);
   7606            crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
   7607            if (crv != CKR_OK) {
   7608                fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n",
   7609                        (unsigned int)crv);
   7610                goto loser;
   7611            }
   7612            crv = NSC_CreateObject(session, psk_template,
   7613                                   psk_template_count, &psk_handle);
   7614            if (crv != CKR_OK) {
   7615                fprintf(stderr, "NSC_CreateObject(psk) failed crv=0x%x\n",
   7616                        (unsigned int)crv);
   7617                goto loser;
   7618            }
   7619            crv = NSC_CreateObject(session, gxy_template,
   7620                                   gxy_template_count, &gxy_handle);
   7621            if (crv != CKR_OK) {
   7622                fprintf(stderr, "NSC_CreateObject(gxy) failed crv=0x%x\n",
   7623                        (unsigned int)crv);
   7624                goto loser;
   7625            }
   7626            /* get the skeyid key */
   7627            crv = NSC_DeriveKey(session, &ike_mech, psk_handle,
   7628                                derive_template, derive_template_count - 1,
   7629                                &skeyid_handle);
   7630            if (crv != CKR_OK) {
   7631                fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n",
   7632                        (unsigned int)crv);
   7633                goto loser;
   7634            }
   7635            skeyid_template.ulValueLen = HASH_LENGTH_MAX;
   7636            crv = NSC_GetAttributeValue(session, skeyid_handle,
   7637                                        &skeyid_template, 1);
   7638            if (crv != CKR_OK) {
   7639                fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
   7640                        (unsigned int)crv);
   7641                goto loser;
   7642            }
   7643            /* use the length of the skeyid to set the target length of all the
   7644             * other keys */
   7645            keyLen = skeyid_template.ulValueLen;
   7646            ike1_prf.hKeygxy = gxy_handle;
   7647            ike1_prf.bHasPrevKey = PR_FALSE;
   7648            ike1_prf.keyNumber = 0;
   7649            crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
   7650                                derive_template, derive_template_count,
   7651                                &skeyid_d_handle);
   7652            if (crv != CKR_OK) {
   7653                fprintf(stderr, "NSC_DeriveKey(skeyid_d) failed crv=0x%x\n",
   7654                        (unsigned int)crv);
   7655                goto loser;
   7656            }
   7657 
   7658            ike1_prf.hKeygxy = gxy_handle;
   7659            ike1_prf.bHasPrevKey = CK_TRUE;
   7660            ike1_prf.hPrevKey = skeyid_d_handle;
   7661            ike1_prf.keyNumber = 1;
   7662            crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
   7663                                derive_template, derive_template_count,
   7664                                &skeyid_a_handle);
   7665            if (crv != CKR_OK) {
   7666                fprintf(stderr, "NSC_DeriveKey(skeyid_a) failed crv=0x%x\n",
   7667                        (unsigned int)crv);
   7668                goto loser;
   7669            }
   7670            ike1_prf.hKeygxy = gxy_handle;
   7671            ike1_prf.bHasPrevKey = CK_TRUE;
   7672            ike1_prf.hPrevKey = skeyid_a_handle;
   7673            ike1_prf.keyNumber = 2;
   7674            crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
   7675                                derive_template, derive_template_count,
   7676                                &skeyid_e_handle);
   7677            if (crv != CKR_OK) {
   7678                fprintf(stderr, "NSC_DeriveKey(skeyid_e) failed crv=0x%x\n",
   7679                        (unsigned int)crv);
   7680                goto loser;
   7681            }
   7682            fputs("SKEYID = ", ikeresp);
   7683            to_hex_str(buf, skeyid_secret, keyLen);
   7684            fputs(buf, ikeresp);
   7685            fputc('\n', ikeresp);
   7686 
   7687            skeyid_d_template.ulValueLen = keyLen;
   7688            crv = NSC_GetAttributeValue(session, skeyid_d_handle,
   7689                                        &skeyid_d_template, 1);
   7690            if (crv != CKR_OK) {
   7691                fprintf(stderr, "NSC_GetAttribute(skeyid_d) failed crv=0x%x\n",
   7692                        (unsigned int)crv);
   7693                goto loser;
   7694            }
   7695            fputs("SKEYID_d = ", ikeresp);
   7696            to_hex_str(buf, skeyid_d_secret, skeyid_d_template.ulValueLen);
   7697            fputs(buf, ikeresp);
   7698            fputc('\n', ikeresp);
   7699 
   7700            skeyid_a_template.ulValueLen = keyLen;
   7701            crv = NSC_GetAttributeValue(session, skeyid_a_handle,
   7702                                        &skeyid_a_template, 1);
   7703            if (crv != CKR_OK) {
   7704                fprintf(stderr, "NSC_GetAttribute(skeyid_a) failed crv=0x%x\n",
   7705                        (unsigned int)crv);
   7706                goto loser;
   7707            }
   7708            fputs("SKEYID_a = ", ikeresp);
   7709            to_hex_str(buf, skeyid_a_secret, skeyid_a_template.ulValueLen);
   7710            fputs(buf, ikeresp);
   7711            fputc('\n', ikeresp);
   7712 
   7713            skeyid_e_template.ulValueLen = keyLen;
   7714            crv = NSC_GetAttributeValue(session, skeyid_e_handle,
   7715                                        &skeyid_e_template, 1);
   7716            if (crv != CKR_OK) {
   7717                fprintf(stderr, "NSC_GetAttribute(skeyid_e) failed crv=0x%x\n",
   7718                        (unsigned int)crv);
   7719                goto loser;
   7720            }
   7721            fputs("SKEYID_e = ", ikeresp);
   7722            to_hex_str(buf, skeyid_e_secret, skeyid_e_template.ulValueLen);
   7723            fputs(buf, ikeresp);
   7724            fputc('\n', ikeresp);
   7725 
   7726            crv = NSC_CloseSession(session);
   7727            continue;
   7728        }
   7729    }
   7730 loser:
   7731    NSC_Finalize(NULL);
   7732    if (psk)
   7733        free(psk);
   7734    if (gxy)
   7735        free(gxy);
   7736    if (Ni)
   7737        free(Ni);
   7738    if (Nr)
   7739        free(Nr);
   7740    if (ikereq)
   7741        fclose(ikereq);
   7742 }
   7743 
   7744 void
   7745 ikev2(char *reqfn)
   7746 {
   7747    char buf[4096]; /* holds one line from the input REQUEST file.
   7748                     * needs to be large enough to hold the longest
   7749                     * line "g^xy = <2048 hex digits>\n".
   7750                     */
   7751    unsigned char *gir = NULL;
   7752    unsigned char *gir_new = NULL;
   7753    int gir_len;
   7754    unsigned char *Ni = NULL;
   7755    int Ni_len;
   7756    unsigned char *Nr = NULL;
   7757    int Nr_len;
   7758    unsigned char *SPIi = NULL;
   7759    int SPIi_len = 8;
   7760    unsigned char *SPIr = NULL;
   7761    int SPIr_len = 8;
   7762    unsigned char *DKM = NULL;
   7763    int DKM_len;
   7764    unsigned char *DKM_child = NULL;
   7765    int DKM_child_len;
   7766    unsigned char *seed_data = NULL;
   7767    int seed_data_len = 0;
   7768    unsigned int i, j;
   7769    FILE *ikereq = NULL; /* input stream from the REQUEST file */
   7770    FILE *ikeresp;       /* output stream to the RESPONSE file */
   7771 
   7772    CK_SLOT_ID slotList[10];
   7773    CK_SLOT_ID slotID;
   7774    CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
   7775    CK_ULONG count;
   7776    static const CK_C_INITIALIZE_ARGS pk11args = {
   7777        NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
   7778        (void *)"flags=readOnly,noCertDB,noModDB", NULL
   7779    };
   7780    static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY;
   7781    static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
   7782    static CK_BBOOL ck_true = CK_TRUE;
   7783    static CK_ULONG keyLen = 1;
   7784    CK_ATTRIBUTE gir_template[] = {
   7785        { CKA_VALUE, NULL, 0 },
   7786        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
   7787        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
   7788        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
   7789    };
   7790    CK_ULONG gir_template_count =
   7791        sizeof(gir_template) / sizeof(gir_template[0]);
   7792    CK_ATTRIBUTE gir_new_template[] = {
   7793        { CKA_VALUE, NULL, 0 },
   7794        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
   7795        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
   7796        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
   7797    };
   7798    CK_ULONG gir_new_template_count =
   7799        sizeof(gir_new_template) / sizeof(gir_new_template[0]);
   7800    CK_ATTRIBUTE derive_template[] = {
   7801        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
   7802        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
   7803        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
   7804        { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) },
   7805    };
   7806    CK_ULONG derive_template_count =
   7807        sizeof(derive_template) / sizeof(derive_template[0]);
   7808    CK_ATTRIBUTE skeyseed_template = { CKA_VALUE, NULL, 0 };
   7809    CK_ATTRIBUTE dkm_template = { CKA_VALUE, NULL, 0 };
   7810    CK_ATTRIBUTE dkm_child_template = { CKA_VALUE, NULL, 0 };
   7811    unsigned char skeyseed_secret[HASH_LENGTH_MAX];
   7812 
   7813    CK_MECHANISM ike_mech = { CKM_IKE_PRF_DERIVE, NULL, 0 };
   7814    CK_MECHANISM ike2_mech = { CKM_IKE2_PRF_PLUS_DERIVE, NULL, 0 };
   7815    CK_MECHANISM subset_mech = { CKM_EXTRACT_KEY_FROM_KEY, NULL, 0 };
   7816    CK_IKE_PRF_DERIVE_PARAMS ike_prf;
   7817    CK_IKE2_PRF_PLUS_DERIVE_PARAMS ike2_prf;
   7818    CK_EXTRACT_PARAMS subset_params;
   7819    CK_RV crv;
   7820 
   7821    /* set up PKCS #11 parameters */
   7822    ike_mech.pParameter = &ike_prf;
   7823    ike_mech.ulParameterLen = sizeof(ike_prf);
   7824    ike2_mech.pParameter = &ike2_prf;
   7825    ike2_mech.ulParameterLen = sizeof(ike2_prf);
   7826    subset_mech.pParameter = &subset_params;
   7827    subset_mech.ulParameterLen = sizeof(subset_params);
   7828    subset_params = 0;
   7829    skeyseed_template.pValue = skeyseed_secret;
   7830    skeyseed_template.ulValueLen = HASH_LENGTH_MAX;
   7831 
   7832    crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
   7833    if (crv != CKR_OK) {
   7834        fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
   7835        goto loser;
   7836    }
   7837    count = slotListCount;
   7838    crv = NSC_GetSlotList(PR_TRUE, slotList, &count);
   7839    if (crv != CKR_OK) {
   7840        fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
   7841        goto loser;
   7842    }
   7843    if ((count > slotListCount) || count < 1) {
   7844        fprintf(stderr,
   7845                "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
   7846                (int)count, (int)slotListCount);
   7847        goto loser;
   7848    }
   7849    slotID = slotList[0];
   7850    ikereq = fopen(reqfn, "r");
   7851    ikeresp = stdout;
   7852    while (fgets(buf, sizeof buf, ikereq) != NULL) {
   7853        /* a comment or blank line */
   7854        if (buf[0] == '#' || buf[0] == '\n') {
   7855            fputs(buf, ikeresp);
   7856            continue;
   7857        }
   7858        /* [.....] */
   7859        if (buf[0] == '[') {
   7860            if (strncmp(buf, "[SHA-1]", 7) == 0) {
   7861                ike_prf.prfMechanism = CKM_SHA_1_HMAC;
   7862                ike2_prf.prfMechanism = CKM_SHA_1_HMAC;
   7863            }
   7864            if (strncmp(buf, "[SHA-224]", 9) == 0) {
   7865                ike_prf.prfMechanism = CKM_SHA224_HMAC;
   7866                ike2_prf.prfMechanism = CKM_SHA224_HMAC;
   7867            }
   7868            if (strncmp(buf, "[SHA-256]", 9) == 0) {
   7869                ike_prf.prfMechanism = CKM_SHA256_HMAC;
   7870                ike2_prf.prfMechanism = CKM_SHA256_HMAC;
   7871            }
   7872            if (strncmp(buf, "[SHA-384]", 9) == 0) {
   7873                ike_prf.prfMechanism = CKM_SHA384_HMAC;
   7874                ike2_prf.prfMechanism = CKM_SHA384_HMAC;
   7875            }
   7876            if (strncmp(buf, "[SHA-512]", 9) == 0) {
   7877                ike_prf.prfMechanism = CKM_SHA512_HMAC;
   7878                ike2_prf.prfMechanism = CKM_SHA512_HMAC;
   7879            }
   7880            if (strncmp(buf, "[AES-XCBC", 9) == 0) {
   7881                ike_prf.prfMechanism = CKM_AES_XCBC_MAC;
   7882                ike2_prf.prfMechanism = CKM_AES_XCBC_MAC;
   7883            }
   7884            if (strncmp(buf, "[g^ir", 5) == 0) {
   7885                if (sscanf(buf, "[g^ir length = %d]",
   7886                           &gir_len) != 1) {
   7887                    goto loser;
   7888                }
   7889                gir_len = gir_len / 8;
   7890                if (gir)
   7891                    free(gir);
   7892                if (gir_new)
   7893                    free(gir_new);
   7894                gir = malloc(gir_len);
   7895                gir_new = malloc(gir_len);
   7896                gir_template[0].pValue = gir;
   7897                gir_template[0].ulValueLen = gir_len;
   7898                gir_new_template[0].pValue = gir_new;
   7899                gir_new_template[0].ulValueLen = gir_len;
   7900            }
   7901            if (strncmp(buf, "[Ni", 3) == 0) {
   7902                if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) {
   7903                    goto loser;
   7904                }
   7905                Ni_len = Ni_len / 8;
   7906            }
   7907            if (strncmp(buf, "[Nr", 3) == 0) {
   7908                if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) {
   7909                    goto loser;
   7910                }
   7911                Nr_len = Nr_len / 8;
   7912            }
   7913            if (strncmp(buf, "[DKM", 4) == 0) {
   7914                if (sscanf(buf, "[DKM length = %d]",
   7915                           &DKM_len) != 1) {
   7916                    goto loser;
   7917                }
   7918                DKM_len = DKM_len / 8;
   7919                if (DKM)
   7920                    free(DKM);
   7921                DKM = malloc(DKM_len);
   7922                dkm_template.pValue = DKM;
   7923                dkm_template.ulValueLen = DKM_len;
   7924            }
   7925            if (strncmp(buf, "[Child SA DKM", 13) == 0) {
   7926                if (sscanf(buf, "[Child SA DKM length = %d]",
   7927                           &DKM_child_len) != 1) {
   7928                    goto loser;
   7929                }
   7930                DKM_child_len = DKM_child_len / 8;
   7931                if (DKM_child)
   7932                    free(DKM_child);
   7933                DKM_child = malloc(DKM_child_len);
   7934                dkm_child_template.pValue = DKM_child;
   7935                dkm_child_template.ulValueLen = DKM_child_len;
   7936            }
   7937            fputs(buf, ikeresp);
   7938            continue;
   7939        }
   7940        /* "COUNT = x" begins a new data set */
   7941        if (strncmp(buf, "COUNT", 5) == 0) {
   7942            /* zeroize the variables for the test with this data set */
   7943            int new_seed_len = Ni_len + Nr_len + SPIi_len + SPIr_len;
   7944            if (seed_data_len != new_seed_len) {
   7945                if (seed_data)
   7946                    free(seed_data);
   7947                seed_data_len = new_seed_len;
   7948                seed_data = malloc(seed_data_len);
   7949                Ni = seed_data;
   7950                Nr = &seed_data[Ni_len];
   7951                SPIi = &seed_data[Ni_len + Nr_len];
   7952                SPIr = &seed_data[new_seed_len - SPIr_len];
   7953                ike_prf.pNi = Ni;
   7954                ike_prf.ulNiLen = Ni_len;
   7955                ike_prf.pNr = Nr;
   7956                ike_prf.ulNrLen = Nr_len;
   7957                ike2_prf.pSeedData = seed_data;
   7958            }
   7959            memset(gir, 0, gir_len);
   7960            memset(gir_new, 0, gir_len);
   7961            memset(seed_data, 0, seed_data_len);
   7962            fputs(buf, ikeresp);
   7963            continue;
   7964        }
   7965        /* Ni = ... */
   7966        if (strncmp(buf, "Ni", 2) == 0) {
   7967            i = 2;
   7968            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   7969                i++;
   7970            }
   7971            for (j = 0; j < Ni_len; i += 2, j++) {
   7972                hex_to_byteval(&buf[i], &Ni[j]);
   7973            }
   7974            fputs(buf, ikeresp);
   7975            continue;
   7976        }
   7977        /* Nr = ... */
   7978        if (strncmp(buf, "Nr", 2) == 0) {
   7979            i = 2;
   7980            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   7981                i++;
   7982            }
   7983            for (j = 0; j < Nr_len; i += 2, j++) {
   7984                hex_to_byteval(&buf[i], &Nr[j]);
   7985            }
   7986            fputs(buf, ikeresp);
   7987            continue;
   7988        }
   7989        /* g^ir (new) = ... */
   7990        if (strncmp(buf, "g^ir (new)", 10) == 0) {
   7991            i = 10;
   7992            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   7993                i++;
   7994            }
   7995            for (j = 0; j < gir_len; i += 2, j++) {
   7996                hex_to_byteval(&buf[i], &gir_new[j]);
   7997            }
   7998            fputs(buf, ikeresp);
   7999            continue;
   8000        }
   8001        /* g^ir = ... */
   8002        if (strncmp(buf, "g^ir", 4) == 0) {
   8003            i = 4;
   8004            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   8005                i++;
   8006            }
   8007            for (j = 0; j < gir_len; i += 2, j++) {
   8008                hex_to_byteval(&buf[i], &gir[j]);
   8009            }
   8010            fputs(buf, ikeresp);
   8011            continue;
   8012        }
   8013        /* SPIi = ... */
   8014        if (strncmp(buf, "SPIi", 4) == 0) {
   8015            i = 4;
   8016            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   8017                i++;
   8018            }
   8019            for (j = 0; j < SPIi_len; i += 2, j++) {
   8020                hex_to_byteval(&buf[i], &SPIi[j]);
   8021            }
   8022            fputs(buf, ikeresp);
   8023            continue;
   8024        }
   8025        /* SPIr = ... */
   8026        if (strncmp(buf, "SPIr", 4) == 0) {
   8027            CK_SESSION_HANDLE session;
   8028            CK_OBJECT_HANDLE gir_handle;
   8029            CK_OBJECT_HANDLE gir_new_handle;
   8030            CK_OBJECT_HANDLE skeyseed_handle;
   8031            CK_OBJECT_HANDLE sk_d_handle;
   8032            CK_OBJECT_HANDLE skeyseed_new_handle;
   8033            CK_OBJECT_HANDLE dkm_handle;
   8034            CK_OBJECT_HANDLE dkm_child_handle;
   8035            i = 4;
   8036            while (isspace((unsigned char)buf[i]) || buf[i] == '=') {
   8037                i++;
   8038            }
   8039            for (j = 0; j < SPIr_len; i += 2, j++) {
   8040                hex_to_byteval(&buf[i], &SPIr[j]);
   8041            }
   8042            fputs(buf, ikeresp);
   8043            crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
   8044            if (crv != CKR_OK) {
   8045                fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n",
   8046                        (unsigned int)crv);
   8047                goto loser;
   8048            }
   8049            crv = NSC_CreateObject(session, gir_template,
   8050                                   gir_template_count, &gir_handle);
   8051            if (crv != CKR_OK) {
   8052                fprintf(stderr, "NSC_CreateObject (g^ir) failed crv=0x%x\n",
   8053                        (unsigned int)crv);
   8054                goto loser;
   8055            }
   8056            crv = NSC_CreateObject(session, gir_new_template,
   8057                                   gir_new_template_count, &gir_new_handle);
   8058            if (crv != CKR_OK) {
   8059                fprintf(stderr, "NSC_CreateObject (g^ir new) failed crv=0x%x\n",
   8060                        (unsigned int)crv);
   8061                goto loser;
   8062            }
   8063            /* get the SKEYSEED key */
   8064            ike_prf.bDataAsKey = CK_TRUE;
   8065            ike_prf.bRekey = CK_FALSE;
   8066            ike_prf.hNewKey = CK_INVALID_HANDLE;
   8067            crv = NSC_DeriveKey(session, &ike_mech, gir_handle,
   8068                                derive_template, derive_template_count - 1,
   8069                                &skeyseed_handle);
   8070            if (crv != CKR_OK) {
   8071                fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n",
   8072                        (unsigned int)crv);
   8073                goto loser;
   8074            }
   8075            skeyseed_template.ulValueLen = HASH_LENGTH_MAX;
   8076            crv = NSC_GetAttributeValue(session, skeyseed_handle,
   8077                                        &skeyseed_template, 1);
   8078            if (crv != CKR_OK) {
   8079                fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
   8080                        (unsigned int)crv);
   8081                goto loser;
   8082            }
   8083            fputs("SKEYSEED = ", ikeresp);
   8084            to_hex_str(buf, skeyseed_secret, skeyseed_template.ulValueLen);
   8085            fputs(buf, ikeresp);
   8086            fputc('\n', ikeresp);
   8087 
   8088            /* get DKM */
   8089            keyLen = DKM_len;
   8090            ike2_prf.bHasSeedKey = CK_FALSE;
   8091            ike2_prf.hSeedKey = CK_INVALID_HANDLE;
   8092            ike2_prf.ulSeedDataLen = seed_data_len;
   8093            crv = NSC_DeriveKey(session, &ike2_mech, skeyseed_handle,
   8094                                derive_template, derive_template_count,
   8095                                &dkm_handle);
   8096            if (crv != CKR_OK) {
   8097                fprintf(stderr, "NSC_DeriveKey(DKM) failed crv=0x%x\n",
   8098                        (unsigned int)crv);
   8099                goto loser;
   8100            }
   8101            crv = NSC_GetAttributeValue(session, dkm_handle,
   8102                                        &dkm_template, 1);
   8103            if (crv != CKR_OK) {
   8104                fprintf(stderr, "NSC_GetAttribute(DKM) failed crv=0x%x\n",
   8105                        (unsigned int)crv);
   8106                goto loser;
   8107            }
   8108            fputs("DKM = ", ikeresp);
   8109            to_hex_str(buf, DKM, DKM_len);
   8110            fputs(buf, ikeresp);
   8111            fputc('\n', ikeresp);
   8112 
   8113            /* get the sk_d from the DKM */
   8114            keyLen = skeyseed_template.ulValueLen;
   8115            crv = NSC_DeriveKey(session, &subset_mech, dkm_handle,
   8116                                derive_template, derive_template_count,
   8117                                &sk_d_handle);
   8118            if (crv != CKR_OK) {
   8119                fprintf(stderr, "NSC_DeriveKey(sk_d) failed crv=0x%x\n",
   8120                        (unsigned int)crv);
   8121                goto loser;
   8122            }
   8123 
   8124            /* get DKM child */
   8125            keyLen = DKM_child_len;
   8126            ike2_prf.bHasSeedKey = CK_FALSE;
   8127            ike2_prf.hSeedKey = CK_INVALID_HANDLE;
   8128            ike2_prf.ulSeedDataLen = Ni_len + Nr_len;
   8129            crv = NSC_DeriveKey(session, &ike2_mech, sk_d_handle,
   8130                                derive_template, derive_template_count,
   8131                                &dkm_child_handle);
   8132            if (crv != CKR_OK) {
   8133                fprintf(stderr, "NSC_DeriveKey(DKM Child SA) failed crv=0x%x\n",
   8134                        (unsigned int)crv);
   8135                goto loser;
   8136            }
   8137            crv = NSC_GetAttributeValue(session, dkm_child_handle,
   8138                                        &dkm_child_template, 1);
   8139            if (crv != CKR_OK) {
   8140                fprintf(stderr, "NSC_GetAttribute(DKM Child SA) failed crv=0x%x\n",
   8141                        (unsigned int)crv);
   8142                goto loser;
   8143            }
   8144            fputs("DKM(Child SA) = ", ikeresp);
   8145            to_hex_str(buf, DKM_child, DKM_child_len);
   8146            fputs(buf, ikeresp);
   8147            fputc('\n', ikeresp);
   8148 
   8149            /* get DKM child D-H*/
   8150            keyLen = DKM_child_len;
   8151            ike2_prf.bHasSeedKey = CK_TRUE;
   8152            ike2_prf.hSeedKey = gir_new_handle;
   8153            ike2_prf.ulSeedDataLen = Ni_len + Nr_len;
   8154            crv = NSC_DeriveKey(session, &ike2_mech, sk_d_handle,
   8155                                derive_template, derive_template_count,
   8156                                &dkm_child_handle);
   8157            if (crv != CKR_OK) {
   8158                fprintf(stderr, "NSC_DeriveKey(DKM Child SA D-H) failed crv=0x%x\n",
   8159                        (unsigned int)crv);
   8160                goto loser;
   8161            }
   8162            crv = NSC_GetAttributeValue(session, dkm_child_handle,
   8163                                        &dkm_child_template, 1);
   8164            if (crv != CKR_OK) {
   8165                fprintf(stderr, "NSC_GetAttribute(DKM Child SA D-H) failed crv=0x%x\n",
   8166                        (unsigned int)crv);
   8167                goto loser;
   8168            }
   8169            fputs("DKM(Child SA D-H) = ", ikeresp);
   8170            to_hex_str(buf, DKM_child, DKM_child_len);
   8171            fputs(buf, ikeresp);
   8172            fputc('\n', ikeresp);
   8173 
   8174            /* get SKEYSEED(rekey) */
   8175            ike_prf.bDataAsKey = CK_FALSE;
   8176            ike_prf.bRekey = CK_TRUE;
   8177            ike_prf.hNewKey = gir_new_handle;
   8178            crv = NSC_DeriveKey(session, &ike_mech, sk_d_handle,
   8179                                derive_template, derive_template_count - 1,
   8180                                &skeyseed_new_handle);
   8181            if (crv != CKR_OK) {
   8182                fprintf(stderr, "NSC_DeriveKey(skeyid rekey) failed crv=0x%x\n",
   8183                        (unsigned int)crv);
   8184                goto loser;
   8185            }
   8186            skeyseed_template.ulValueLen = HASH_LENGTH_MAX;
   8187            crv = NSC_GetAttributeValue(session, skeyseed_new_handle,
   8188                                        &skeyseed_template, 1);
   8189            if (crv != CKR_OK) {
   8190                fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
   8191                        (unsigned int)crv);
   8192                goto loser;
   8193            }
   8194            fputs("SKEYSEED(rekey) = ", ikeresp);
   8195            to_hex_str(buf, skeyseed_secret, skeyseed_template.ulValueLen);
   8196            fputs(buf, ikeresp);
   8197            fputc('\n', ikeresp);
   8198 
   8199            crv = NSC_CloseSession(session);
   8200            continue;
   8201        }
   8202    }
   8203 loser:
   8204    NSC_Finalize(NULL);
   8205    if (gir)
   8206        free(gir);
   8207    if (gir_new)
   8208        free(gir_new);
   8209    if (seed_data)
   8210        free(seed_data);
   8211    if (DKM)
   8212        free(DKM);
   8213    if (DKM_child)
   8214        free(DKM_child);
   8215    if (ikereq)
   8216        fclose(ikereq);
   8217 }
   8218 
   8219 void
   8220 kbkdf(char *path)
   8221 {
   8222    /* == Parser data == */
   8223    char buf[610]; /* holds one line from the input REQUEST file. Needs to
   8224                    * be large enough to hold the longest line:
   8225                    * "KO = <600 hex digits>\n". */
   8226    CK_ULONG L;
   8227    unsigned char KI[64];
   8228    unsigned int KI_len = 64;
   8229    unsigned char KO[300];
   8230    unsigned int KO_len = 300;
   8231    /* This is used only with feedback mode. */
   8232    unsigned char IV[64];
   8233    unsigned int IV_len = 64;
   8234    /* These are only used in counter mode with counter location as
   8235     * MIDDLE_FIXED. */
   8236    unsigned char BeforeFixedInputData[50];
   8237    unsigned int BeforeFixedInputData_len = 50;
   8238    unsigned char AfterFixedInputData[10];
   8239    unsigned int AfterFixedInputData_len = 10;
   8240    /* These are used with every KDF type. */
   8241    unsigned char FixedInputData[60];
   8242    unsigned int FixedInputData_len = 60;
   8243 
   8244    /* Counter locations:
   8245     *
   8246     * 0: not used
   8247     * 1: beginning
   8248     * 2: middle
   8249     * 3: end */
   8250    int ctr_location = 0;
   8251    CK_ULONG counter_bitlen = 0;
   8252 
   8253    size_t buf_offset;
   8254    size_t offset;
   8255 
   8256    FILE *kbkdf_req = NULL;
   8257    FILE *kbkdf_resp = NULL;
   8258 
   8259    /* == PKCS#11 data == */
   8260    CK_RV crv;
   8261 
   8262    CK_SLOT_ID slotList[10];
   8263    CK_SLOT_ID slotID;
   8264    CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
   8265    CK_ULONG slotCount = 0;
   8266 
   8267    CK_MECHANISM kdf = { 0 };
   8268 
   8269    CK_MECHANISM_TYPE prf_mech = 0;
   8270    CK_BBOOL ck_true = CK_TRUE;
   8271 
   8272    /* We never need more than 3 data parameters. */
   8273    CK_PRF_DATA_PARAM dataParams[3];
   8274    CK_ULONG dataParams_len = 3;
   8275 
   8276    CK_SP800_108_COUNTER_FORMAT iterator = { CK_FALSE, 0 };
   8277 
   8278    CK_SP800_108_KDF_PARAMS kdfParams = { 0 };
   8279    CK_SP800_108_FEEDBACK_KDF_PARAMS feedbackParams = { 0 };
   8280 
   8281    CK_OBJECT_CLASS ck_secret_key = CKO_SECRET_KEY;
   8282    CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
   8283 
   8284    CK_ATTRIBUTE prf_template[] = {
   8285        { CKA_VALUE, &KI, sizeof(KI) },
   8286        { CKA_CLASS, &ck_secret_key, sizeof(ck_secret_key) },
   8287        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
   8288        { CKA_DERIVE, &ck_true, sizeof(ck_true) }
   8289    };
   8290    CK_ULONG prf_template_count = sizeof(prf_template) / sizeof(prf_template[0]);
   8291 
   8292    CK_ATTRIBUTE derive_template[] = {
   8293        { CKA_CLASS, &ck_secret_key, sizeof(ck_secret_key) },
   8294        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
   8295        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
   8296        { CKA_VALUE_LEN, &L, sizeof(L) }
   8297    };
   8298    CK_ULONG derive_template_count = sizeof(derive_template) / sizeof(derive_template[0]);
   8299 
   8300    CK_ATTRIBUTE output_key = { CKA_VALUE, KO, KO_len };
   8301 
   8302    const CK_C_INITIALIZE_ARGS pk11args = {
   8303        NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
   8304        (void *)"flags=readOnly,noCertDB,noModDB", NULL
   8305    };
   8306 
   8307    /* == Start up PKCS#11 == */
   8308    crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
   8309    if (crv != CKR_OK) {
   8310        fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
   8311        goto done;
   8312    }
   8313 
   8314    slotCount = slotListCount;
   8315    crv = NSC_GetSlotList(PR_TRUE, slotList, &slotCount);
   8316    if (crv != CKR_OK) {
   8317        fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
   8318        goto done;
   8319    }
   8320    if ((slotCount > slotListCount) || slotCount < 1) {
   8321        fprintf(stderr,
   8322                "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
   8323                (int)slotCount, (int)slotListCount);
   8324        goto done;
   8325    }
   8326    slotID = slotList[0];
   8327 
   8328    /* == Start parsing the file == */
   8329    kbkdf_req = fopen(path, "r");
   8330    kbkdf_resp = stdout;
   8331 
   8332    while (fgets(buf, sizeof buf, kbkdf_req) != NULL) {
   8333        /* If we have a comment, check if it tells us the type of KDF to use.
   8334         * This differs per-file, so we have to parse it. */
   8335        if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
   8336            if (strncmp(buf, "# KDF Mode Supported: Counter Mode", 34) == 0) {
   8337                kdf.mechanism = CKM_SP800_108_COUNTER_KDF;
   8338            }
   8339            if (strncmp(buf, "# KDF Mode Supported: Feedback Mode", 35) == 0) {
   8340                kdf.mechanism = CKM_SP800_108_FEEDBACK_KDF;
   8341            }
   8342            if (strncmp(buf, "# KDF Mode Supported: DblPipeline Mode", 38) == 0) {
   8343                kdf.mechanism = CKM_SP800_108_DOUBLE_PIPELINE_KDF;
   8344            }
   8345 
   8346            fputs(buf, kbkdf_resp);
   8347            continue;
   8348        }
   8349 
   8350        /* [....] - context directive */
   8351        if (buf[0] == '[') {
   8352            /* PRF begins each new section. */
   8353            if (strncmp(buf, "[PRF=CMAC_AES128]", 17) == 0) {
   8354                prf_mech = CKM_AES_CMAC;
   8355                KI_len = 16;
   8356            } else if (strncmp(buf, "[PRF=CMAC_AES192]", 17) == 0) {
   8357                prf_mech = CKM_AES_CMAC;
   8358                KI_len = 24;
   8359            } else if (strncmp(buf, "[PRF=CMAC_AES256]", 17) == 0) {
   8360                prf_mech = CKM_AES_CMAC;
   8361                KI_len = 32;
   8362            } else if (strncmp(buf, "[PRF=HMAC_SHA1]", 15) == 0) {
   8363                prf_mech = CKM_SHA_1_HMAC;
   8364                KI_len = 20;
   8365            } else if (strncmp(buf, "[PRF=HMAC_SHA224]", 17) == 0) {
   8366                prf_mech = CKM_SHA224_HMAC;
   8367                KI_len = 28;
   8368            } else if (strncmp(buf, "[PRF=HMAC_SHA256]", 17) == 0) {
   8369                prf_mech = CKM_SHA256_HMAC;
   8370                KI_len = 32;
   8371            } else if (strncmp(buf, "[PRF=HMAC_SHA384]", 17) == 0) {
   8372                prf_mech = CKM_SHA384_HMAC;
   8373                KI_len = 48;
   8374            } else if (strncmp(buf, "[PRF=HMAC_SHA512]", 17) == 0) {
   8375                prf_mech = CKM_SHA512_HMAC;
   8376                KI_len = 64;
   8377            } else if (strncmp(buf, "[PRF=", 5) == 0) {
   8378                fprintf(stderr, "Invalid or unsupported PRF mechanism: %s\n", buf);
   8379                goto done;
   8380            }
   8381 
   8382            /* Then comes counter, if present. */
   8383            if (strncmp(buf, "[CTRLOCATION=BEFORE_FIXED]", 26) == 0 ||
   8384                strncmp(buf, "[CTRLOCATION=BEFORE_ITER]", 24) == 0) {
   8385                ctr_location = 1;
   8386            }
   8387            if (strncmp(buf, "[CTRLOCATION=MIDDLE_FIXED]", 26) == 0 ||
   8388                strncmp(buf, "[CTRLOCATION=AFTER_ITER]", 24) == 0) {
   8389                ctr_location = 2;
   8390            }
   8391            if (strncmp(buf, "[CTRLOCATION=AFTER_FIXED]", 25) == 0) {
   8392                ctr_location = 3;
   8393            }
   8394 
   8395            /* If counter is present, then we need to know its size. */
   8396            if (strncmp(buf, "[RLEN=", 6) == 0) {
   8397                if (sscanf(buf, "[RLEN=%lu_BITS]", &counter_bitlen) != 1) {
   8398                    goto done;
   8399                }
   8400            }
   8401 
   8402            fputs(buf, kbkdf_resp);
   8403            continue;
   8404        }
   8405 
   8406        /* Each test contains a counter, an output length L, an input key KI,
   8407         * maybe an initialization vector IV, one of a couple of fixed data
   8408         * buffers, and finally the output key KO. */
   8409 
   8410        /* First comes COUNT. */
   8411        if (strncmp(buf, "COUNT=", 6) == 0) {
   8412            /* Clear all out data fields on each test. */
   8413            memset(KI, 0, sizeof KI);
   8414            memset(KO, 0, sizeof KO);
   8415            memset(IV, 0, sizeof IV);
   8416            memset(BeforeFixedInputData, 0, sizeof BeforeFixedInputData);
   8417            memset(AfterFixedInputData, 0, sizeof AfterFixedInputData);
   8418            memset(FixedInputData, 0, sizeof FixedInputData);
   8419 
   8420            /* Then reset lengths except KI: it was determined by PRF
   8421             * selection above. */
   8422            KO_len = 0;
   8423            IV_len = 0;
   8424            BeforeFixedInputData_len = 0;
   8425            AfterFixedInputData_len = 0;
   8426            FixedInputData_len = 0;
   8427 
   8428            fputs(buf, kbkdf_resp);
   8429            continue;
   8430        }
   8431 
   8432        /* Then comes L. */
   8433        if (strncmp(buf, "L = ", 4) == 0) {
   8434            if (sscanf(buf, "L = %lu", &L) != 1) {
   8435                goto done;
   8436            }
   8437 
   8438            if ((L % 8) != 0) {
   8439                fprintf(stderr, "Assumption that L was length in bits incorrect: %lu - %s", L, buf);
   8440                fprintf(stderr, "Note that NSS only supports byte-aligned outputs and not bit-aligned outputs.\n");
   8441                goto done;
   8442            }
   8443 
   8444            L = L / 8;
   8445 
   8446            fputs(buf, kbkdf_resp);
   8447            continue;
   8448        }
   8449 
   8450        /* Then comes KI. */
   8451        if (strncmp(buf, "KI = ", 5) == 0) {
   8452            buf_offset = 5;
   8453 
   8454            for (offset = 0; offset < KI_len; offset++, buf_offset += 2) {
   8455                hex_to_byteval(buf + buf_offset, KI + offset);
   8456            }
   8457 
   8458            fputs(buf, kbkdf_resp);
   8459            continue;
   8460        }
   8461 
   8462        /* Then comes IVlen and IV, if present. */
   8463        if (strncmp(buf, "IVlen = ", 8) == 0) {
   8464            if (sscanf(buf, "IVlen = %u", &IV_len) != 1) {
   8465                goto done;
   8466            }
   8467 
   8468            if ((IV_len % 8) != 0) {
   8469                fprintf(stderr, "Assumption that IV_len was length in bits incorrect: %u - %s. ", IV_len, buf);
   8470                fprintf(stderr, "Note that NSS only supports byte-aligned inputs and not bit-aligned inputs.\n");
   8471                goto done;
   8472            }
   8473 
   8474            /* Need the IV length in bytes, not bits. */
   8475            IV_len = IV_len / 8;
   8476 
   8477            fputs(buf, kbkdf_resp);
   8478            continue;
   8479        }
   8480        if (strncmp(buf, "IV = ", 5) == 0) {
   8481            buf_offset = 5;
   8482 
   8483            for (offset = 0; offset < IV_len; offset++, buf_offset += 2) {
   8484                hex_to_byteval(buf + buf_offset, IV + offset);
   8485            }
   8486 
   8487            fputs(buf, kbkdf_resp);
   8488            continue;
   8489        }
   8490 
   8491        /* We might have DataBeforeCtr and DataAfterCtr if present. */
   8492        if (strncmp(buf, "DataBeforeCtrLen = ", 19) == 0) {
   8493            if (sscanf(buf, "DataBeforeCtrLen = %u", &BeforeFixedInputData_len) != 1) {
   8494                goto done;
   8495            }
   8496 
   8497            fputs(buf, kbkdf_resp);
   8498            continue;
   8499        }
   8500        if (strncmp(buf, "DataBeforeCtrData = ", 20) == 0) {
   8501            buf_offset = 20;
   8502 
   8503            for (offset = 0; offset < BeforeFixedInputData_len; offset++, buf_offset += 2) {
   8504                hex_to_byteval(buf + buf_offset, BeforeFixedInputData + offset);
   8505            }
   8506 
   8507            fputs(buf, kbkdf_resp);
   8508            continue;
   8509        }
   8510        if (strncmp(buf, "DataAfterCtrLen = ", 18) == 0) {
   8511            if (sscanf(buf, "DataAfterCtrLen = %u", &AfterFixedInputData_len) != 1) {
   8512                goto done;
   8513            }
   8514 
   8515            fputs(buf, kbkdf_resp);
   8516            continue;
   8517        }
   8518        if (strncmp(buf, "DataAfterCtrData = ", 19) == 0) {
   8519            buf_offset = 19;
   8520 
   8521            for (offset = 0; offset < AfterFixedInputData_len; offset++, buf_offset += 2) {
   8522                hex_to_byteval(buf + buf_offset, AfterFixedInputData + offset);
   8523            }
   8524 
   8525            fputs(buf, kbkdf_resp);
   8526            continue;
   8527        }
   8528 
   8529        /* Otherwise, we might have FixedInputData, if present. */
   8530        if (strncmp(buf, "FixedInputDataByteLen = ", 24) == 0) {
   8531            if (sscanf(buf, "FixedInputDataByteLen = %u", &FixedInputData_len) != 1) {
   8532                goto done;
   8533            }
   8534 
   8535            fputs(buf, kbkdf_resp);
   8536            continue;
   8537        }
   8538        if (strncmp(buf, "FixedInputData = ", 17) == 0) {
   8539            buf_offset = 17;
   8540 
   8541            for (offset = 0; offset < FixedInputData_len; offset++, buf_offset += 2) {
   8542                hex_to_byteval(buf + buf_offset, FixedInputData + offset);
   8543            }
   8544 
   8545            fputs(buf, kbkdf_resp);
   8546            continue;
   8547        }
   8548 
   8549        /* Finally, run the KBKDF calculation when KO is passed. */
   8550        if (strncmp(buf, "KO = ", 5) == 0) {
   8551            CK_SESSION_HANDLE session;
   8552            CK_OBJECT_HANDLE prf_key;
   8553            CK_OBJECT_HANDLE derived_key;
   8554 
   8555            /* Open the session. */
   8556            crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
   8557            if (crv != CKR_OK) {
   8558                fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n", (unsigned int)crv);
   8559                goto done;
   8560            }
   8561 
   8562            /* Create the PRF key object. */
   8563            prf_template[0].ulValueLen = KI_len;
   8564            crv = NSC_CreateObject(session, prf_template, prf_template_count, &prf_key);
   8565            if (crv != CKR_OK) {
   8566                fprintf(stderr, "NSC_CreateObject (prf_key) failed crv=0x%x\n", (unsigned int)crv);
   8567                goto done;
   8568            }
   8569 
   8570            /* Set up the KDF parameters. */
   8571            if (kdf.mechanism == CKM_SP800_108_COUNTER_KDF) {
   8572                /* Counter operates in one of three ways: counter before fixed
   8573                 * input data, counter between fixed input data, and counter
   8574                 * after fixed input data. In all cases, we have an iterator.
   8575                 */
   8576                iterator.ulWidthInBits = counter_bitlen;
   8577 
   8578                if (ctr_location == 0 || ctr_location > 3) {
   8579                    fprintf(stderr, "Expected ctr_location != 0 for Counter Mode KDF but got 0.\n");
   8580                    goto done;
   8581                } else if (ctr_location == 1) {
   8582                    /* Counter before */
   8583                    dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE;
   8584                    dataParams[0].pValue = &iterator;
   8585                    dataParams[0].ulValueLen = sizeof(iterator);
   8586 
   8587                    dataParams[1].type = CK_SP800_108_BYTE_ARRAY;
   8588                    dataParams[1].pValue = FixedInputData;
   8589                    dataParams[1].ulValueLen = FixedInputData_len;
   8590 
   8591                    dataParams_len = 2;
   8592                } else if (ctr_location == 2) {
   8593                    /* Counter between */
   8594                    dataParams[0].type = CK_SP800_108_BYTE_ARRAY;
   8595                    dataParams[0].pValue = BeforeFixedInputData;
   8596                    dataParams[0].ulValueLen = BeforeFixedInputData_len;
   8597 
   8598                    dataParams[1].type = CK_SP800_108_ITERATION_VARIABLE;
   8599                    dataParams[1].pValue = &iterator;
   8600                    dataParams[1].ulValueLen = sizeof(iterator);
   8601 
   8602                    dataParams[2].type = CK_SP800_108_BYTE_ARRAY;
   8603                    dataParams[2].pValue = AfterFixedInputData;
   8604                    dataParams[2].ulValueLen = AfterFixedInputData_len;
   8605 
   8606                    dataParams_len = 3;
   8607                } else {
   8608                    /* Counter after */
   8609                    dataParams[0].type = CK_SP800_108_BYTE_ARRAY;
   8610                    dataParams[0].pValue = FixedInputData;
   8611                    dataParams[0].ulValueLen = FixedInputData_len;
   8612 
   8613                    dataParams[1].type = CK_SP800_108_ITERATION_VARIABLE;
   8614                    dataParams[1].pValue = &iterator;
   8615                    dataParams[1].ulValueLen = sizeof(iterator);
   8616 
   8617                    dataParams_len = 2;
   8618                }
   8619            } else if (kdf.mechanism == CKM_SP800_108_FEEDBACK_KDF || kdf.mechanism == CKM_SP800_108_DOUBLE_PIPELINE_KDF) {
   8620                /* When counter_bitlen != 0, we have an optional counter. */
   8621                if (counter_bitlen != 0) {
   8622                    iterator.ulWidthInBits = counter_bitlen;
   8623 
   8624                    if (ctr_location == 0 || ctr_location > 3) {
   8625                        fprintf(stderr, "Expected ctr_location != 0 for Counter Mode KDF but got 0.\n");
   8626                        goto done;
   8627                    } else if (ctr_location == 1) {
   8628                        /* Counter before */
   8629                        dataParams[0].type = CK_SP800_108_OPTIONAL_COUNTER;
   8630                        dataParams[0].pValue = &iterator;
   8631                        dataParams[0].ulValueLen = sizeof(iterator);
   8632 
   8633                        dataParams[1].type = CK_SP800_108_ITERATION_VARIABLE;
   8634                        dataParams[1].pValue = NULL;
   8635                        dataParams[1].ulValueLen = 0;
   8636 
   8637                        dataParams[2].type = CK_SP800_108_BYTE_ARRAY;
   8638                        dataParams[2].pValue = FixedInputData;
   8639                        dataParams[2].ulValueLen = FixedInputData_len;
   8640 
   8641                        dataParams_len = 3;
   8642                    } else if (ctr_location == 2) {
   8643                        /* Counter between */
   8644                        dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE;
   8645                        dataParams[0].pValue = NULL;
   8646                        dataParams[0].ulValueLen = 0;
   8647 
   8648                        dataParams[1].type = CK_SP800_108_OPTIONAL_COUNTER;
   8649                        dataParams[1].pValue = &iterator;
   8650                        dataParams[1].ulValueLen = sizeof(iterator);
   8651 
   8652                        dataParams[2].type = CK_SP800_108_BYTE_ARRAY;
   8653                        dataParams[2].pValue = FixedInputData;
   8654                        dataParams[2].ulValueLen = FixedInputData_len;
   8655 
   8656                        dataParams_len = 3;
   8657                    } else {
   8658                        /* Counter after */
   8659                        dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE;
   8660                        dataParams[0].pValue = NULL;
   8661                        dataParams[0].ulValueLen = 0;
   8662 
   8663                        dataParams[1].type = CK_SP800_108_BYTE_ARRAY;
   8664                        dataParams[1].pValue = FixedInputData;
   8665                        dataParams[1].ulValueLen = FixedInputData_len;
   8666 
   8667                        dataParams[2].type = CK_SP800_108_OPTIONAL_COUNTER;
   8668                        dataParams[2].pValue = &iterator;
   8669                        dataParams[2].ulValueLen = sizeof(iterator);
   8670 
   8671                        dataParams_len = 3;
   8672                    }
   8673                } else {
   8674                    dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE;
   8675                    dataParams[0].pValue = NULL;
   8676                    dataParams[0].ulValueLen = 0;
   8677 
   8678                    dataParams[1].type = CK_SP800_108_BYTE_ARRAY;
   8679                    dataParams[1].pValue = FixedInputData;
   8680                    dataParams[1].ulValueLen = FixedInputData_len;
   8681 
   8682                    dataParams_len = 2;
   8683                }
   8684            }
   8685 
   8686            if (kdf.mechanism != CKM_SP800_108_FEEDBACK_KDF) {
   8687                kdfParams.prfType = prf_mech;
   8688                kdfParams.ulNumberOfDataParams = dataParams_len;
   8689                kdfParams.pDataParams = dataParams;
   8690 
   8691                kdf.pParameter = &kdfParams;
   8692                kdf.ulParameterLen = sizeof(kdfParams);
   8693            } else {
   8694                feedbackParams.prfType = prf_mech;
   8695                feedbackParams.ulNumberOfDataParams = dataParams_len;
   8696                feedbackParams.pDataParams = dataParams;
   8697                feedbackParams.ulIVLen = IV_len;
   8698                if (IV_len == 0) {
   8699                    feedbackParams.pIV = NULL;
   8700                } else {
   8701                    feedbackParams.pIV = IV;
   8702                }
   8703 
   8704                kdf.pParameter = &feedbackParams;
   8705                kdf.ulParameterLen = sizeof(feedbackParams);
   8706            }
   8707 
   8708            crv = NSC_DeriveKey(session, &kdf, prf_key, derive_template, derive_template_count, &derived_key);
   8709            if (crv != CKR_OK) {
   8710                fprintf(stderr, "NSC_DeriveKey(derived_key) failed crv=0x%x\n", (unsigned int)crv);
   8711                goto done;
   8712            }
   8713 
   8714            crv = NSC_GetAttributeValue(session, derived_key, &output_key, 1);
   8715            if (crv != CKR_OK) {
   8716                fprintf(stderr, "NSC_GetAttribute(derived_value) failed crv=0x%x\n", (unsigned int)crv);
   8717                goto done;
   8718            }
   8719 
   8720            fputs("KO = ", kbkdf_resp);
   8721            to_hex_str(buf, KO, output_key.ulValueLen);
   8722            fputs(buf, kbkdf_resp);
   8723            fputs("\r\n", kbkdf_resp);
   8724 
   8725            continue;
   8726        }
   8727    }
   8728 
   8729 done:
   8730    if (kbkdf_req != NULL) {
   8731        fclose(kbkdf_req);
   8732    }
   8733    if (kbkdf_resp != stdout && kbkdf_resp != NULL) {
   8734        fclose(kbkdf_resp);
   8735    }
   8736 
   8737    return;
   8738 }
   8739 
   8740 int
   8741 main(int argc, char **argv)
   8742 {
   8743    if (argc < 2)
   8744        exit(-1);
   8745 
   8746    RNG_RNGInit();
   8747    SECOID_Init();
   8748 
   8749    /*************/
   8750    /*   TDEA    */
   8751    /*************/
   8752    if (strcmp(argv[1], "tdea") == 0) {
   8753        /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
   8754        if (strcmp(argv[2], "kat") == 0) {
   8755            /* Known Answer Test (KAT) */
   8756            tdea_kat_mmt(argv[4]);
   8757        } else if (strcmp(argv[2], "mmt") == 0) {
   8758            /* Multi-block Message Test (MMT) */
   8759            tdea_kat_mmt(argv[4]);
   8760        } else if (strcmp(argv[2], "mct") == 0) {
   8761            /* Monte Carlo Test (MCT) */
   8762            if (strcmp(argv[3], "ecb") == 0) {
   8763                /* ECB mode */
   8764                tdea_mct(NSS_DES_EDE3, argv[4]);
   8765            } else if (strcmp(argv[3], "cbc") == 0) {
   8766                /* CBC mode */
   8767                tdea_mct(NSS_DES_EDE3_CBC, argv[4]);
   8768            }
   8769        }
   8770        /*************/
   8771        /*   AES     */
   8772        /*************/
   8773    } else if (strcmp(argv[1], "aes") == 0) {
   8774        /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
   8775        if (strcmp(argv[2], "kat") == 0) {
   8776            /* Known Answer Test (KAT) */
   8777            aes_kat_mmt(argv[4]);
   8778        } else if (strcmp(argv[2], "mmt") == 0) {
   8779            /* Multi-block Message Test (MMT) */
   8780            aes_kat_mmt(argv[4]);
   8781        } else if (strcmp(argv[2], "gcm") == 0) {
   8782            if (strcmp(argv[3], "decrypt") == 0) {
   8783                aes_gcm(argv[4], 0);
   8784            } else if (strcmp(argv[3], "encrypt_extiv") == 0) {
   8785                aes_gcm(argv[4], 1);
   8786            } else if (strcmp(argv[3], "encrypt_intiv") == 0) {
   8787                aes_gcm(argv[4], 2);
   8788            }
   8789        } else if (strcmp(argv[2], "mct") == 0) {
   8790            /* Monte Carlo Test (MCT) */
   8791            if (strcmp(argv[3], "ecb") == 0) {
   8792                /* ECB mode */
   8793                aes_ecb_mct(argv[4]);
   8794            } else if (strcmp(argv[3], "cbc") == 0) {
   8795                /* CBC mode */
   8796                aes_cbc_mct(argv[4]);
   8797            }
   8798        }
   8799        /*************/
   8800        /*   SHA     */
   8801        /*************/
   8802    } else if (strcmp(argv[1], "sha") == 0) {
   8803        sha_test(argv[2]);
   8804        /*************/
   8805        /*   RSA     */
   8806        /*************/
   8807    } else if (strcmp(argv[1], "rsa") == 0) {
   8808        /* argv[2]=siggen|sigver */
   8809        /* argv[3]=<test name>.req */
   8810        if (strcmp(argv[2], "siggen") == 0) {
   8811            /* Signature Generation Test */
   8812            rsa_siggen_test(argv[3]);
   8813        } else if (strcmp(argv[2], "sigver") == 0) {
   8814            /* Signature Verification Test */
   8815            rsa_sigver_test(argv[3]);
   8816        } else if (strcmp(argv[2], "keypair") == 0) {
   8817            /* Key Pair Generation Test */
   8818            rsa_keypair_test(argv[3]);
   8819        }
   8820        /*************/
   8821        /*   HMAC    */
   8822        /*************/
   8823    } else if (strcmp(argv[1], "hmac") == 0) {
   8824        hmac_test(argv[2]);
   8825        /*************/
   8826        /*   DSA     */
   8827        /*************/
   8828    } else if (strcmp(argv[1], "dsa") == 0) {
   8829        /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */
   8830        /* argv[3]=<test name>.req */
   8831        if (strcmp(argv[2], "keypair") == 0) {
   8832            /* Key Pair Generation Test */
   8833            dsa_keypair_test(argv[3]);
   8834        } else if (strcmp(argv[2], "pqggen") == 0) {
   8835            /* Domain Parameter Generation Test */
   8836            dsa_pqggen_test(argv[3]);
   8837        } else if (strcmp(argv[2], "pqgver") == 0) {
   8838            /* Domain Parameter Validation Test */
   8839            dsa_pqgver_test(argv[3]);
   8840        } else if (strcmp(argv[2], "siggen") == 0) {
   8841            /* Signature Generation Test */
   8842            dsa_siggen_test(argv[3]);
   8843        } else if (strcmp(argv[2], "sigver") == 0) {
   8844            /* Signature Verification Test */
   8845            dsa_sigver_test(argv[3]);
   8846        }
   8847        /*************/
   8848        /*   ECDSA   */
   8849        /*************/
   8850    } else if (strcmp(argv[1], "ecdsa") == 0) {
   8851        /* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */
   8852        if (strcmp(argv[2], "keypair") == 0) {
   8853            /* Key Pair Generation Test */
   8854            ecdsa_keypair_test(argv[3]);
   8855        } else if (strcmp(argv[2], "pkv") == 0) {
   8856            /* Public Key Validation Test */
   8857            ecdsa_pkv_test(argv[3]);
   8858        } else if (strcmp(argv[2], "siggen") == 0) {
   8859            /* Signature Generation Test */
   8860            ecdsa_siggen_test(argv[3]);
   8861        } else if (strcmp(argv[2], "sigver") == 0) {
   8862            /* Signature Verification Test */
   8863            ecdsa_sigver_test(argv[3]);
   8864        }
   8865        /*************/
   8866        /*   ECDH   */
   8867        /*************/
   8868    } else if (strcmp(argv[1], "ecdh") == 0) {
   8869        /* argv[2]={init|resp}-{func|verify} argv[3]=<test name>.req */
   8870        if (strcmp(argv[2], "init-func") == 0) {
   8871            ecdh_functional(argv[3], 0);
   8872        } else if (strcmp(argv[2], "resp-func") == 0) {
   8873            ecdh_functional(argv[3], 1);
   8874        } else if (strcmp(argv[2], "init-verify") == 0) {
   8875            ecdh_verify(argv[3], 0);
   8876        } else if (strcmp(argv[2], "resp-verify") == 0) {
   8877            ecdh_verify(argv[3], 1);
   8878        }
   8879        /*************/
   8880        /*   DH   */
   8881        /*************/
   8882    } else if (strcmp(argv[1], "dh") == 0) {
   8883        /* argv[2]={init|resp}-{func|verify} argv[3]=<test name>.req */
   8884        if (strcmp(argv[2], "init-func") == 0) {
   8885            dh_functional(argv[3], 0);
   8886        } else if (strcmp(argv[2], "resp-func") == 0) {
   8887            dh_functional(argv[3], 1);
   8888        } else if (strcmp(argv[2], "init-verify") == 0) {
   8889            dh_verify(argv[3], 0);
   8890        } else if (strcmp(argv[2], "resp-verify") == 0) {
   8891            dh_verify(argv[3], 1);
   8892        }
   8893        /*************/
   8894        /*   RNG     */
   8895        /*************/
   8896    } else if (strcmp(argv[1], "rng") == 0) {
   8897        /* argv[2]=vst|mct argv[3]=<test name>.req */
   8898        if (strcmp(argv[2], "vst") == 0) {
   8899            /* Variable Seed Test */
   8900            rng_vst(argv[3]);
   8901        } else if (strcmp(argv[2], "mct") == 0) {
   8902            /* Monte Carlo Test */
   8903            rng_mct(argv[3]);
   8904        }
   8905    } else if (strcmp(argv[1], "drbg") == 0) {
   8906        /* Variable Seed Test */
   8907        drbg(argv[2]);
   8908    } else if (strcmp(argv[1], "ddrbg") == 0) {
   8909        debug = 1;
   8910        drbg(argv[2]);
   8911    } else if (strcmp(argv[1], "tls") == 0) {
   8912        tls(argv[2]);
   8913    } else if (strcmp(argv[1], "ikev1") == 0) {
   8914        ikev1(argv[2]);
   8915    } else if (strcmp(argv[1], "ikev1-psk") == 0) {
   8916        ikev1_psk(argv[2]);
   8917    } else if (strcmp(argv[1], "ikev2") == 0) {
   8918        ikev2(argv[2]);
   8919    } else if (strcmp(argv[1], "kbkdf") == 0) {
   8920        kbkdf(argv[2]);
   8921    }
   8922    return 0;
   8923 }