PageRenderTime 2063ms CodeModel.GetById 144ms app.highlight 1701ms RepoModel.GetById 143ms app.codeStats 2ms

/security/nss/cmd/fipstest/fipstest.c

https://bitbucket.org/mkato/mozilla-1.9.0-win64
C | 4903 lines | 3797 code | 360 blank | 746 comment | 1445 complexity | ac6666cf55eeec83bda3ea3b4e6ec112 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/* ***** BEGIN LICENSE BLOCK *****
   2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
   3 *
   4 * The contents of this file are subject to the Mozilla Public License Version
   5 * 1.1 (the "License"); you may not use this file except in compliance with
   6 * the License. You may obtain a copy of the License at
   7 * http://www.mozilla.org/MPL/
   8 *
   9 * Software distributed under the License is distributed on an "AS IS" basis,
  10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11 * for the specific language governing rights and limitations under the
  12 * License.
  13 *
  14 * The Original Code is the Netscape security libraries.
  15 *
  16 * The Initial Developer of the Original Code is
  17 * Netscape Communications Corporation.
  18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
  19 * the Initial Developer. All Rights Reserved.
  20 *
  21 * Contributor(s):
  22 *
  23 * Alternatively, the contents of this file may be used under the terms of
  24 * either the GNU General Public License Version 2 or later (the "GPL"), or
  25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  26 * in which case the provisions of the GPL or the LGPL are applicable instead
  27 * of those above. If you wish to allow use of your version of this file only
  28 * under the terms of either the GPL or the LGPL, and not to allow others to
  29 * use your version of this file under the terms of the MPL, indicate your
  30 * decision by deleting the provisions above and replace them with the notice
  31 * and other provisions required by the GPL or the LGPL. If you do not delete
  32 * the provisions above, a recipient may use your version of this file under
  33 * the terms of any one of the MPL, the GPL or the LGPL.
  34 *
  35 * ***** END LICENSE BLOCK ***** */
  36
  37#include <stdio.h>
  38#include <stdlib.h>
  39#include <ctype.h>
  40
  41#include "secitem.h"
  42#include "blapi.h"
  43#include "nss.h"
  44#include "secerr.h"
  45#include "secder.h"
  46#include "secdig.h"
  47#include "keythi.h"
  48#include "ec.h"
  49#include "hasht.h"
  50#include "lowkeyi.h"
  51#include "softoken.h"
  52
  53#if 0
  54#include "../../lib/freebl/mpi/mpi.h"
  55#endif
  56
  57#ifdef NSS_ENABLE_ECC
  58extern SECStatus
  59EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
  60extern SECStatus
  61EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
  62              const ECParams *srcParams);
  63#endif
  64
  65#define ENCRYPT 1
  66#define DECRYPT 0
  67#define BYTE unsigned char
  68#define DEFAULT_RSA_PUBLIC_EXPONENT   0x10001
  69#define RSA_MAX_TEST_MODULUS_BITS     4096
  70#define RSA_MAX_TEST_MODULUS_BYTES    RSA_MAX_TEST_MODULUS_BITS/8
  71#define RSA_MAX_TEST_EXPONENT_BYTES   8
  72#define PQG_TEST_SEED_BYTES           20
  73
  74SECStatus
  75hex_to_byteval(const char *c2, unsigned char *byteval)
  76{
  77    int i;
  78    unsigned char offset;
  79    *byteval = 0;
  80    for (i=0; i<2; i++) {
  81	if (c2[i] >= '0' && c2[i] <= '9') {
  82	    offset = c2[i] - '0';
  83	    *byteval |= offset << 4*(1-i);
  84	} else if (c2[i] >= 'a' && c2[i] <= 'f') {
  85	    offset = c2[i] - 'a';
  86	    *byteval |= (offset + 10) << 4*(1-i);
  87	} else if (c2[i] >= 'A' && c2[i] <= 'F') {
  88	    offset = c2[i] - 'A';
  89	    *byteval |= (offset + 10) << 4*(1-i);
  90	} else {
  91	    return SECFailure;
  92	}
  93    }
  94    return SECSuccess;
  95}
  96
  97SECStatus
  98byteval_to_hex(unsigned char byteval, char *c2, char a)
  99{
 100    int i;
 101    unsigned char offset;
 102    for (i=0; i<2; i++) {
 103	offset = (byteval >> 4*(1-i)) & 0x0f;
 104	if (offset < 10) {
 105	    c2[i] = '0' + offset;
 106	} else {
 107	    c2[i] = a + offset - 10;
 108	}
 109    }
 110    return SECSuccess;
 111}
 112
 113void
 114to_hex_str(char *str, const unsigned char *buf, unsigned int len)
 115{
 116    unsigned int i;
 117    for (i=0; i<len; i++) {
 118	byteval_to_hex(buf[i], &str[2*i], 'a');
 119    }
 120    str[2*len] = '\0';
 121}
 122
 123void
 124to_hex_str_cap(char *str, const unsigned char *buf, unsigned int len)
 125{
 126    unsigned int i;
 127    for (i=0; i<len; i++) {
 128	byteval_to_hex(buf[i], &str[2*i], 'A');
 129    }
 130    str[2*len] = '\0';
 131}
 132
 133/*
 134 * Convert a string of hex digits (str) to an array (buf) of len bytes.
 135 * Return PR_TRUE if the hex string can fit in the byte array.  Return
 136 * PR_FALSE if the hex string is empty or is too long.
 137 */
 138PRBool
 139from_hex_str(unsigned char *buf, unsigned int len, const char *str)
 140{
 141    unsigned int nxdigit;  /* number of hex digits in str */
 142    unsigned int i;  /* index into buf */
 143    unsigned int j;  /* index into str */
 144
 145    /* count the hex digits */
 146    nxdigit = 0;
 147    for (nxdigit = 0; isxdigit(str[nxdigit]); nxdigit++) {
 148	/* empty body */
 149    }
 150    if (nxdigit == 0) {
 151	return PR_FALSE;
 152    }
 153    if (nxdigit > 2*len) {
 154	/*
 155	 * The input hex string is too long, but we allow it if the
 156	 * extra digits are leading 0's.
 157	 */
 158	for (j = 0; j < nxdigit-2*len; j++) {
 159	    if (str[j] != '0') {
 160		return PR_FALSE;
 161	    }
 162	}
 163	/* skip leading 0's */
 164	str += nxdigit-2*len;
 165	nxdigit = 2*len;
 166    }
 167    for (i=0, j=0; i< len; i++) {
 168	if (2*i < 2*len-nxdigit) {
 169	    /* Handle a short input as if we padded it with leading 0's. */
 170	    if (2*i+1 < 2*len-nxdigit) {
 171		buf[i] = 0;
 172	    } else {
 173		char tmp[2];
 174		tmp[0] = '0';
 175		tmp[1] = str[j];
 176		hex_to_byteval(tmp, &buf[i]);
 177		j++;
 178	    }
 179	} else {
 180	    hex_to_byteval(&str[j], &buf[i]);
 181	    j += 2;
 182	}
 183    }
 184    return PR_TRUE;
 185}
 186
 187SECStatus
 188tdea_encrypt_buf(
 189    int mode,
 190    const unsigned char *key, 
 191    const unsigned char *iv,
 192    unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
 193    const unsigned char *input, unsigned int inputlen)
 194{
 195    SECStatus rv = SECFailure;
 196    DESContext *cx;
 197    unsigned char doublecheck[8*20];  /* 1 to 20 blocks */
 198    unsigned int doublechecklen = 0;
 199
 200    cx = DES_CreateContext(key, iv, mode, PR_TRUE);
 201    if (cx == NULL) {
 202        goto loser;
 203    }
 204    rv = DES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
 205    if (rv != SECSuccess) {
 206        goto loser;
 207    }
 208    if (*outputlen != inputlen) {
 209        goto loser;
 210    }
 211    DES_DestroyContext(cx, PR_TRUE);
 212    cx = NULL;
 213
 214    /*
 215     * Doublecheck our result by decrypting the ciphertext and
 216     * compare the output with the input plaintext.
 217     */
 218    cx = DES_CreateContext(key, iv, mode, PR_FALSE);
 219    if (cx == NULL) {
 220        goto loser;
 221    }
 222    rv = DES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
 223                    output, *outputlen);
 224    if (rv != SECSuccess) {
 225        goto loser;
 226    }
 227    if (doublechecklen != *outputlen) {
 228        goto loser;
 229    }
 230    DES_DestroyContext(cx, PR_TRUE);
 231    cx = NULL;
 232    if (memcmp(doublecheck, input, inputlen) != 0) {
 233        goto loser;
 234    }
 235    rv = SECSuccess;
 236
 237loser:
 238    if (cx != NULL) {
 239        DES_DestroyContext(cx, PR_TRUE);
 240    }
 241    return rv;
 242}
 243
 244SECStatus
 245tdea_decrypt_buf(
 246    int mode,
 247    const unsigned char *key, 
 248    const unsigned char *iv,
 249    unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
 250    const unsigned char *input, unsigned int inputlen)
 251{
 252    SECStatus rv = SECFailure;
 253    DESContext *cx;
 254    unsigned char doublecheck[8*20];  /* 1 to 20 blocks */
 255    unsigned int doublechecklen = 0;
 256
 257    cx = DES_CreateContext(key, iv, mode, PR_FALSE);
 258    if (cx == NULL) {
 259        goto loser;
 260    }
 261    rv = DES_Decrypt(cx, output, outputlen, maxoutputlen,
 262                    input, inputlen);
 263    if (rv != SECSuccess) {
 264        goto loser;
 265    }
 266    if (*outputlen != inputlen) {
 267        goto loser;
 268    }
 269    DES_DestroyContext(cx, PR_TRUE);
 270    cx = NULL;
 271
 272    /*
 273     * Doublecheck our result by encrypting the plaintext and
 274     * compare the output with the input ciphertext.
 275     */
 276    cx = DES_CreateContext(key, iv, mode, PR_TRUE);
 277    if (cx == NULL) {
 278        goto loser;
 279    }
 280    rv = DES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
 281        output, *outputlen);
 282    if (rv != SECSuccess) {
 283        goto loser;
 284    }
 285    if (doublechecklen != *outputlen) {
 286        goto loser;
 287    }
 288    DES_DestroyContext(cx, PR_TRUE);
 289    cx = NULL;
 290    if (memcmp(doublecheck, input, inputlen) != 0) {
 291        goto loser;
 292    }
 293    rv = SECSuccess;
 294
 295loser:
 296    if (cx != NULL) {
 297        DES_DestroyContext(cx, PR_TRUE);
 298    }
 299    return rv;
 300}
 301
 302/*
 303 * Perform the TDEA Known Answer Test (KAT) or Multi-block Message
 304 * Test (MMT) in ECB or CBC mode.  The KAT (there are five types)
 305 * and MMT have the same structure: given the key and IV (CBC mode
 306 * only), encrypt the given plaintext or decrypt the given ciphertext.
 307 * So we can handle them the same way.
 308 *
 309 * reqfn is the pathname of the REQUEST file.
 310 *
 311 * The output RESPONSE file is written to stdout.
 312 */
 313void
 314tdea_kat_mmt(char *reqfn)
 315{
 316    char buf[180];      /* holds one line from the input REQUEST file.
 317                         * needs to be large enough to hold the longest
 318                         * line "CIPHERTEXT = <180 hex digits>\n".
 319                         */
 320    FILE *req;       /* input stream from the REQUEST file */
 321    FILE *resp;      /* output stream to the RESPONSE file */
 322    int i, j;
 323    int mode;           /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */
 324    int crypt = DECRYPT;    /* 1 means encrypt, 0 means decrypt */
 325    unsigned char key[24];              /* TDEA 3 key bundle */
 326    unsigned int numKeys = 0;
 327    unsigned char iv[8];		/* for all modes except ECB */
 328    unsigned char plaintext[8*20];     /* 1 to 20 blocks */
 329    unsigned int plaintextlen;
 330    unsigned char ciphertext[8*20];   /* 1 to 20 blocks */  
 331    unsigned int ciphertextlen;
 332    SECStatus rv;
 333
 334    req = fopen(reqfn, "r");
 335    resp = stdout;
 336    while (fgets(buf, sizeof buf, req) != NULL) {
 337        /* a comment or blank line */
 338        if (buf[0] == '#' || buf[0] == '\n') {
 339            fputs(buf, resp);
 340            continue;
 341        }
 342        /* [ENCRYPT] or [DECRYPT] */
 343        if (buf[0] == '[') {
 344            if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
 345                crypt = ENCRYPT;
 346            } else {
 347                crypt = DECRYPT;
 348            }
 349            fputs(buf, resp);
 350            continue;
 351        }
 352        /* NumKeys */
 353        if (strncmp(&buf[0], "NumKeys", 7) == 0) {
 354            i = 7;
 355            while (isspace(buf[i]) || buf[i] == '=') {
 356                i++;
 357            }
 358            numKeys = buf[i];
 359            fputs(buf, resp);
 360            continue;
 361        }
 362        /* "COUNT = x" begins a new data set */
 363        if (strncmp(buf, "COUNT", 5) == 0) {
 364            /* mode defaults to ECB, if dataset has IV mode will be set CBC */
 365            mode = NSS_DES_EDE3;
 366            /* zeroize the variables for the test with this data set */
 367            memset(key, 0, sizeof key);
 368            memset(iv, 0, sizeof iv);
 369            memset(plaintext, 0, sizeof plaintext);
 370            plaintextlen = 0;
 371            memset(ciphertext, 0, sizeof ciphertext);
 372            ciphertextlen = 0;
 373            fputs(buf, resp);
 374            continue;
 375        }
 376        if (numKeys == 0) {
 377            if (strncmp(buf, "KEYs", 4) == 0) {
 378                i = 4;
 379                while (isspace(buf[i]) || buf[i] == '=') {
 380                    i++;
 381                }
 382                for (j=0; isxdigit(buf[i]); i+=2,j++) {
 383                    hex_to_byteval(&buf[i], &key[j]);
 384                    key[j+8] = key[j];
 385                    key[j+16] = key[j];
 386                }
 387                fputs(buf, resp);
 388                continue;
 389            }
 390        } else {
 391            /* KEY1 = ... */
 392            if (strncmp(buf, "KEY1", 4) == 0) {
 393                i = 4;
 394                while (isspace(buf[i]) || buf[i] == '=') {
 395                    i++;
 396                }
 397                for (j=0; isxdigit(buf[i]); i+=2,j++) {
 398                    hex_to_byteval(&buf[i], &key[j]);
 399                }
 400                fputs(buf, resp);
 401                continue;
 402            }
 403            /* KEY2 = ... */
 404            if (strncmp(buf, "KEY2", 4) == 0) {
 405                i = 4;
 406                while (isspace(buf[i]) || buf[i] == '=') {
 407                    i++;
 408                }
 409                for (j=8; isxdigit(buf[i]); i+=2,j++) {
 410                    hex_to_byteval(&buf[i], &key[j]);
 411                }
 412                fputs(buf, resp);
 413                continue;
 414            }
 415            /* KEY3 = ... */
 416            if (strncmp(buf, "KEY3", 4) == 0) {
 417                i = 4;
 418                while (isspace(buf[i]) || buf[i] == '=') {
 419                    i++;
 420                }
 421                for (j=16; isxdigit(buf[i]); i+=2,j++) {
 422                    hex_to_byteval(&buf[i], &key[j]);
 423                }
 424                fputs(buf, resp);
 425                continue;
 426            }
 427        }
 428
 429        /* IV = ... */
 430        if (strncmp(buf, "IV", 2) == 0) {
 431            mode = NSS_DES_EDE3_CBC;
 432            i = 2;
 433            while (isspace(buf[i]) || buf[i] == '=') {
 434                i++;
 435            }
 436            for (j=0; j<sizeof iv; i+=2,j++) {
 437                hex_to_byteval(&buf[i], &iv[j]);
 438            }
 439            fputs(buf, resp);
 440            continue;
 441        }
 442
 443        /* PLAINTEXT = ... */
 444        if (strncmp(buf, "PLAINTEXT", 9) == 0) {
 445            /* sanity check */
 446            if (crypt != ENCRYPT) {
 447                goto loser;
 448            }
 449            i = 9;
 450            while (isspace(buf[i]) || buf[i] == '=') {
 451                i++;
 452            }
 453            for (j=0; isxdigit(buf[i]); i+=2,j++) {
 454                hex_to_byteval(&buf[i], &plaintext[j]);
 455            }
 456            plaintextlen = j;
 457            rv = tdea_encrypt_buf(mode, key,
 458                            (mode == NSS_DES_EDE3) ? NULL : iv,
 459                            ciphertext, &ciphertextlen, sizeof ciphertext,
 460                            plaintext, plaintextlen);
 461            if (rv != SECSuccess) {
 462                goto loser;
 463            }
 464    
 465            fputs(buf, resp);
 466            fputs("CIPHERTEXT = ", resp);
 467            to_hex_str(buf, ciphertext, ciphertextlen);
 468            fputs(buf, resp);
 469            fputc('\n', resp);
 470            continue;
 471        }
 472        /* CIPHERTEXT = ... */
 473        if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
 474            /* sanity check */
 475            if (crypt != DECRYPT) {
 476                goto loser;
 477            }
 478 
 479            i = 10;
 480            while (isspace(buf[i]) || buf[i] == '=') {
 481                i++;
 482            }
 483            for (j=0; isxdigit(buf[i]); i+=2,j++) {
 484                hex_to_byteval(&buf[i], &ciphertext[j]);
 485            }
 486            ciphertextlen = j;
 487 
 488            rv = tdea_decrypt_buf(mode, key,
 489                            (mode == NSS_DES_EDE3) ? NULL : iv,
 490                            plaintext, &plaintextlen, sizeof plaintext,
 491                            ciphertext, ciphertextlen);
 492            if (rv != SECSuccess) {
 493                goto loser;
 494            }
 495 
 496            fputs(buf, resp);
 497            fputs("PLAINTEXT = ", resp);
 498            to_hex_str(buf, plaintext, plaintextlen);
 499            fputs(buf, resp);
 500            fputc('\n', resp);
 501            continue;
 502        }
 503    }
 504
 505loser:
 506    fclose(req);
 507}
 508
 509/*
 510* Set the parity bit for the given byte
 511*/
 512BYTE odd_parity( BYTE in)
 513{
 514    BYTE out = in;
 515    in ^= in >> 4;
 516    in ^= in >> 2;
 517    in ^= in >> 1;
 518    return (BYTE)(out ^ !(in & 1));
 519}
 520
 521/*
 522 * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j] 
 523 * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes.
 524 */
 525void
 526tdea_mct_next_keys(unsigned char *key,
 527    const unsigned char *text_2, const unsigned char *text_1, 
 528    const unsigned char *text, unsigned int numKeys)
 529{
 530    int k;
 531
 532    /* key1[i+1] = key1[i] xor PT/CT[j] */
 533    for (k=0; k<8; k++) {
 534        key[k] ^= text[k];
 535    }
 536    /* key2 */
 537    if (numKeys == 2 || numKeys == 3)  {
 538        /* key2 independent */
 539        for (k=8; k<16; k++) {
 540            /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */
 541            key[k] ^= text_1[k-8];
 542        }
 543    } else {
 544        /* key2 == key 1 */
 545        for (k=8; k<16; k++) {
 546            /* key2[i+1] = KEY2[i] xor PT/CT[j] */
 547            key[k] = key[k-8];
 548        }
 549    }
 550    /* key3 */
 551    if (numKeys == 1 || numKeys == 2) {
 552        /* key3 == key 1 */
 553        for (k=16; k<24; k++) {
 554            /* key3[i+1] = KEY3[i] xor PT/CT[j] */
 555            key[k] = key[k-16];
 556        }
 557    } else {
 558        /* key3 independent */ 
 559        for (k=16; k<24; k++) {
 560            /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */
 561            key[k] ^= text_2[k-16];
 562        }
 563    }
 564    /* set the parity bits */            
 565    for (k=0; k<24; k++) {
 566        key[k] = odd_parity(key[k]);
 567    }
 568}
 569
 570/*
 571 * Perform the Monte Carlo Test
 572 *
 573 * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC
 574 * crypt = ENCRYPT || DECRYPT
 575 * inputtext = plaintext or Cyphertext depending on the value of crypt
 576 * inputlength is expected to be size 8 bytes 
 577 * iv = needs to be set for NSS_DES_EDE3_CBC mode
 578 * resp = is the output response file. 
 579 */
 580 void                                                       
 581tdea_mct_test(int mode, unsigned char* key, unsigned int numKeys, 
 582              unsigned int crypt, unsigned char* inputtext, 
 583              unsigned int inputlength, unsigned char* iv, FILE *resp) { 
 584
 585    int i, j;
 586    unsigned char outputtext_1[8];      /* PT/CT[j-1] */
 587    unsigned char outputtext_2[8];      /* PT/CT[j-2] */
 588    char buf[80];       /* holds one line from the input REQUEST file. */
 589    unsigned int outputlen;
 590    unsigned char outputtext[8];
 591    
 592        
 593    SECStatus rv;
 594
 595    if (mode == NSS_DES_EDE3 && iv != NULL) {
 596        printf("IV must be NULL for NSS_DES_EDE3 mode");
 597        goto loser;
 598    } else if (mode == NSS_DES_EDE3_CBC && iv == NULL) {
 599        printf("IV must not be NULL for NSS_DES_EDE3_CBC mode");
 600        goto loser;
 601    }
 602
 603    /* loop 400 times */
 604    for (i=0; i<400; i++) {
 605        /* if i == 0 CV[0] = IV  not necessary */        
 606        /* record the count and key values and plainText */
 607        sprintf(buf, "COUNT = %d\n", i);
 608        fputs(buf, resp);
 609        /* Output KEY1[i] */
 610        fputs("KEY1 = ", resp);
 611        to_hex_str(buf, key, 8);
 612        fputs(buf, resp);
 613        fputc('\n', resp);
 614        /* Output KEY2[i] */
 615        fputs("KEY2 = ", resp);
 616        to_hex_str(buf, &key[8], 8);
 617        fputs(buf, resp);
 618        fputc('\n', resp);
 619        /* Output KEY3[i] */
 620        fputs("KEY3 = ", resp);
 621        to_hex_str(buf, &key[16], 8);
 622        fputs(buf, resp);
 623        fputc('\n', resp);
 624        if (mode == NSS_DES_EDE3_CBC) {
 625            /* Output CV[i] */
 626            fputs("IV = ", resp);
 627            to_hex_str(buf, iv, 8);
 628            fputs(buf, resp);
 629            fputc('\n', resp);
 630        }
 631        if (crypt == ENCRYPT) {
 632            /* Output PT[0] */
 633            fputs("PLAINTEXT = ", resp);
 634        } else {
 635            /* Output CT[0] */
 636            fputs("CIPHERTEXT = ", resp);
 637        }
 638
 639        to_hex_str(buf, inputtext, inputlength);
 640        fputs(buf, resp);
 641        fputc('\n', resp);
 642
 643        /* loop 10,000 times */
 644        for (j=0; j<10000; j++) {
 645
 646            outputlen = 0;
 647            if (crypt == ENCRYPT) {
 648                /* inputtext == ciphertext outputtext == plaintext*/
 649                rv = tdea_encrypt_buf(mode, key,
 650                            (mode == NSS_DES_EDE3) ? NULL : iv,
 651                            outputtext, &outputlen, 8,
 652                            inputtext, 8);
 653            } else {
 654                /* inputtext == plaintext outputtext == ciphertext */
 655                rv = tdea_decrypt_buf(mode, key,
 656                            (mode == NSS_DES_EDE3) ? NULL : iv,
 657                            outputtext, &outputlen, 8,
 658                            inputtext, 8);
 659            }
 660
 661            if (rv != SECSuccess) {
 662                goto loser;
 663            }
 664            if (outputlen != inputlength) {
 665                goto loser;
 666            }
 667
 668            if (mode == NSS_DES_EDE3_CBC) {
 669                if (crypt == ENCRYPT) {
 670                    if (j == 0) {
 671                        /*P[j+1] = CV[0] */
 672                        memcpy(inputtext, iv, 8);
 673                    } else {
 674                        /* p[j+1] = C[j-1] */
 675                        memcpy(inputtext, outputtext_1, 8);
 676                    }
 677                    /* CV[j+1] = C[j] */
 678                    memcpy(iv, outputtext, 8);
 679                    if (j != 9999) {
 680                        /* save C[j-1] */
 681                        memcpy(outputtext_1, outputtext, 8);
 682                    }
 683                } else { /* DECRYPT */
 684                    /* CV[j+1] = C[j] */
 685                    memcpy(iv, inputtext, 8);
 686                    /* C[j+1] = P[j] */
 687                    memcpy(inputtext, outputtext, 8);
 688                }
 689            } else {
 690                /* ECB mode PT/CT[j+1] = CT/PT[j] */
 691                memcpy(inputtext, outputtext, 8);
 692            }
 693
 694            /* Save PT/CT[j-2] and PT/CT[j-1] */
 695            if (j==9997) memcpy(outputtext_2, outputtext, 8);
 696            if (j==9998) memcpy(outputtext_1, outputtext, 8);
 697            /* done at the end of the for(j) loop */
 698        }
 699
 700
 701        if (crypt == ENCRYPT) {
 702            /* Output CT[j] */
 703            fputs("CIPHERTEXT = ", resp);
 704        } else {
 705            /* Output PT[j] */
 706            fputs("PLAINTEXT = ", resp);
 707        }
 708        to_hex_str(buf, outputtext, 8);
 709        fputs(buf, resp);
 710        fputc('\n', resp);
 711
 712        /* Key[i+1] = Key[i] xor ...  outputtext_2 == PT/CT[j-2] 
 713         *  outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j] 
 714         */
 715        tdea_mct_next_keys(key, outputtext_2, 
 716                           outputtext_1, outputtext, numKeys);
 717
 718        if (mode == NSS_DES_EDE3_CBC) {
 719            /* taken care of in the j=9999 iteration */
 720            if (crypt == ENCRYPT) {
 721                /* P[i] = C[j-1] */
 722                /* CV[i] = C[j] */
 723            } else {
 724                /* taken care of in the j=9999 iteration */
 725                /* CV[i] = C[j] */
 726                /* C[i] = P[j]  */
 727            }
 728        } else {
 729            /* ECB PT/CT[i] = PT/CT[j]  */
 730            memcpy(inputtext, outputtext, 8);
 731        }
 732        /* done at the end of the for(i) loop */
 733        fputc('\n', resp);
 734    }
 735
 736loser:
 737    return;
 738}
 739
 740/*
 741 * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes.
 742 * by gathering the input from the request file, and then 
 743 * calling tdea_mct_test.
 744 *
 745 * reqfn is the pathname of the input REQUEST file.
 746 *
 747 * The output RESPONSE file is written to stdout.
 748 */
 749void
 750tdea_mct(int mode, char *reqfn)
 751{
 752    int i, j;
 753    char buf[80];    /* holds one line from the input REQUEST file. */
 754    FILE *req;       /* input stream from the REQUEST file */
 755    FILE *resp;      /* output stream to the RESPONSE file */
 756    unsigned int crypt = 0;    /* 1 means encrypt, 0 means decrypt */
 757    unsigned char key[24];              /* TDEA 3 key bundle */
 758    unsigned int numKeys = 0;
 759    unsigned char plaintext[8];        /* PT[j] */
 760    unsigned char ciphertext[8];       /* CT[j] */
 761    unsigned char iv[8];
 762
 763    /* zeroize the variables for the test with this data set */
 764    memset(key, 0, sizeof key);
 765    memset(plaintext, 0, sizeof plaintext);
 766    memset(ciphertext, 0, sizeof ciphertext);
 767    memset(iv, 0, sizeof iv);
 768
 769    req = fopen(reqfn, "r");
 770    resp = stdout;
 771    while (fgets(buf, sizeof buf, req) != NULL) {
 772        /* a comment or blank line */
 773        if (buf[0] == '#' || buf[0] == '\n') {
 774            fputs(buf, resp);
 775            continue;
 776        }
 777        /* [ENCRYPT] or [DECRYPT] */
 778        if (buf[0] == '[') {
 779            if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
 780                crypt = ENCRYPT;
 781            } else {
 782                crypt = DECRYPT;
 783           }
 784           fputs(buf, resp);
 785           continue;
 786        }
 787        /* NumKeys */
 788        if (strncmp(&buf[0], "NumKeys", 7) == 0) {
 789            i = 7;
 790            while (isspace(buf[i]) || buf[i] == '=') {
 791                i++;
 792            }
 793            numKeys = atoi(&buf[i]);
 794            continue;
 795        }
 796        /* KEY1 = ... */
 797        if (strncmp(buf, "KEY1", 4) == 0) {
 798            i = 4;
 799            while (isspace(buf[i]) || buf[i] == '=') {
 800                i++;
 801            }
 802            for (j=0; isxdigit(buf[i]); i+=2,j++) {
 803                hex_to_byteval(&buf[i], &key[j]);
 804            }
 805            continue;
 806        }
 807        /* KEY2 = ... */
 808        if (strncmp(buf, "KEY2", 4) == 0) {
 809            i = 4;
 810            while (isspace(buf[i]) || buf[i] == '=') {
 811                i++;
 812            }
 813            for (j=8; isxdigit(buf[i]); i+=2,j++) {
 814                hex_to_byteval(&buf[i], &key[j]);
 815            }
 816            continue;
 817        }
 818        /* KEY3 = ... */
 819        if (strncmp(buf, "KEY3", 4) == 0) {
 820            i = 4;
 821            while (isspace(buf[i]) || buf[i] == '=') {
 822                i++;
 823            }
 824            for (j=16; isxdigit(buf[i]); i+=2,j++) {
 825                hex_to_byteval(&buf[i], &key[j]);
 826            }
 827            continue;
 828        }
 829
 830        /* IV = ... */
 831        if (strncmp(buf, "IV", 2) == 0) {
 832            i = 2;
 833            while (isspace(buf[i]) || buf[i] == '=') {
 834                i++;
 835            }
 836            for (j=0; j<sizeof iv; i+=2,j++) {
 837                hex_to_byteval(&buf[i], &iv[j]);
 838            }
 839            continue;
 840        }
 841
 842       /* PLAINTEXT = ... */
 843       if (strncmp(buf, "PLAINTEXT", 9) == 0) {
 844
 845            /* sanity check */
 846            if (crypt != ENCRYPT) {
 847                goto loser;
 848            }
 849            /* PT[0] = PT */
 850            i = 9;
 851            while (isspace(buf[i]) || buf[i] == '=') {
 852                i++;
 853            }
 854            for (j=0; j<sizeof plaintext; i+=2,j++) {
 855                hex_to_byteval(&buf[i], &plaintext[j]);
 856            }                                     
 857
 858            /* do the Monte Carlo test */
 859            if (mode==NSS_DES_EDE3) {
 860                tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, plaintext, sizeof plaintext, NULL, resp);
 861            } else {
 862                tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, plaintext, sizeof plaintext, iv, resp);
 863            }
 864            continue;
 865        }
 866        /* CIPHERTEXT = ... */
 867        if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
 868            /* sanity check */
 869            if (crypt != DECRYPT) {
 870                goto loser;
 871            }
 872            /* CT[0] = CT */
 873            i = 10;
 874            while (isspace(buf[i]) || buf[i] == '=') {
 875                i++;
 876            }
 877            for (j=0; isxdigit(buf[i]); i+=2,j++) {
 878                hex_to_byteval(&buf[i], &ciphertext[j]);
 879            }
 880            
 881            /* do the Monte Carlo test */
 882            if (mode==NSS_DES_EDE3) {
 883                tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, ciphertext, sizeof ciphertext, NULL, resp); 
 884            } else {
 885                tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, ciphertext, sizeof ciphertext, iv, resp); 
 886            }
 887            continue;
 888        }
 889    }
 890
 891loser:
 892    fclose(req);
 893}
 894
 895
 896SECStatus
 897aes_encrypt_buf(
 898    int mode,
 899    const unsigned char *key, unsigned int keysize,
 900    const unsigned char *iv,
 901    unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
 902    const unsigned char *input, unsigned int inputlen)
 903{
 904    SECStatus rv = SECFailure;
 905    AESContext *cx;
 906    unsigned char doublecheck[10*16];  /* 1 to 10 blocks */
 907    unsigned int doublechecklen = 0;
 908
 909    cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
 910    if (cx == NULL) {
 911	goto loser;
 912    }
 913    rv = AES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
 914    if (rv != SECSuccess) {
 915	goto loser;
 916    }
 917    if (*outputlen != inputlen) {
 918	goto loser;
 919    }
 920    AES_DestroyContext(cx, PR_TRUE);
 921    cx = NULL;
 922
 923    /*
 924     * Doublecheck our result by decrypting the ciphertext and
 925     * compare the output with the input plaintext.
 926     */
 927    cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
 928    if (cx == NULL) {
 929	goto loser;
 930    }
 931    rv = AES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
 932	output, *outputlen);
 933    if (rv != SECSuccess) {
 934	goto loser;
 935    }
 936    if (doublechecklen != *outputlen) {
 937	goto loser;
 938    }
 939    AES_DestroyContext(cx, PR_TRUE);
 940    cx = NULL;
 941    if (memcmp(doublecheck, input, inputlen) != 0) {
 942	goto loser;
 943    }
 944    rv = SECSuccess;
 945
 946loser:
 947    if (cx != NULL) {
 948	AES_DestroyContext(cx, PR_TRUE);
 949    }
 950    return rv;
 951}
 952
 953SECStatus
 954aes_decrypt_buf(
 955    int mode,
 956    const unsigned char *key, unsigned int keysize,
 957    const unsigned char *iv,
 958    unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
 959    const unsigned char *input, unsigned int inputlen)
 960{
 961    SECStatus rv = SECFailure;
 962    AESContext *cx;
 963    unsigned char doublecheck[10*16];  /* 1 to 10 blocks */
 964    unsigned int doublechecklen = 0;
 965
 966    cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
 967    if (cx == NULL) {
 968	goto loser;
 969    }
 970    rv = AES_Decrypt(cx, output, outputlen, maxoutputlen,
 971	input, inputlen);
 972    if (rv != SECSuccess) {
 973	goto loser;
 974    }
 975    if (*outputlen != inputlen) {
 976	goto loser;
 977    }
 978    AES_DestroyContext(cx, PR_TRUE);
 979    cx = NULL;
 980
 981    /*
 982     * Doublecheck our result by encrypting the plaintext and
 983     * compare the output with the input ciphertext.
 984     */
 985    cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
 986    if (cx == NULL) {
 987	goto loser;
 988    }
 989    rv = AES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
 990	output, *outputlen);
 991    if (rv != SECSuccess) {
 992	goto loser;
 993    }
 994    if (doublechecklen != *outputlen) {
 995	goto loser;
 996    }
 997    AES_DestroyContext(cx, PR_TRUE);
 998    cx = NULL;
 999    if (memcmp(doublecheck, input, inputlen) != 0) {
1000	goto loser;
1001    }
1002    rv = SECSuccess;
1003
1004loser:
1005    if (cx != NULL) {
1006	AES_DestroyContext(cx, PR_TRUE);
1007    }
1008    return rv;
1009}
1010
1011/*
1012 * Perform the AES Known Answer Test (KAT) or Multi-block Message
1013 * Test (MMT) in ECB or CBC mode.  The KAT (there are four types)
1014 * and MMT have the same structure: given the key and IV (CBC mode
1015 * only), encrypt the given plaintext or decrypt the given ciphertext.
1016 * So we can handle them the same way.
1017 *
1018 * reqfn is the pathname of the REQUEST file.
1019 *
1020 * The output RESPONSE file is written to stdout.
1021 */
1022void
1023aes_kat_mmt(char *reqfn)
1024{
1025    char buf[512];      /* holds one line from the input REQUEST file.
1026                         * needs to be large enough to hold the longest
1027                         * line "CIPHERTEXT = <320 hex digits>\n".
1028                         */
1029    FILE *aesreq;       /* input stream from the REQUEST file */
1030    FILE *aesresp;      /* output stream to the RESPONSE file */
1031    int i, j;
1032    int mode;           /* NSS_AES (ECB) or NSS_AES_CBC */
1033    int encrypt = 0;    /* 1 means encrypt, 0 means decrypt */
1034    unsigned char key[32];              /* 128, 192, or 256 bits */
1035    unsigned int keysize;
1036    unsigned char iv[16];		/* for all modes except ECB */
1037    unsigned char plaintext[10*16];     /* 1 to 10 blocks */
1038    unsigned int plaintextlen;
1039    unsigned char ciphertext[10*16];    /* 1 to 10 blocks */
1040    unsigned int ciphertextlen;
1041    SECStatus rv;
1042
1043    aesreq = fopen(reqfn, "r");
1044    aesresp = stdout;
1045    while (fgets(buf, sizeof buf, aesreq) != NULL) {
1046	/* a comment or blank line */
1047	if (buf[0] == '#' || buf[0] == '\n') {
1048	    fputs(buf, aesresp);
1049	    continue;
1050	}
1051	/* [ENCRYPT] or [DECRYPT] */
1052	if (buf[0] == '[') {
1053	    if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1054		encrypt = 1;
1055	    } else {
1056		encrypt = 0;
1057	    }
1058	    fputs(buf, aesresp);
1059	    continue;
1060	}
1061	/* "COUNT = x" begins a new data set */
1062	if (strncmp(buf, "COUNT", 5) == 0) {
1063	    mode = NSS_AES;
1064	    /* zeroize the variables for the test with this data set */
1065	    memset(key, 0, sizeof key);
1066	    keysize = 0;
1067	    memset(iv, 0, sizeof iv);
1068	    memset(plaintext, 0, sizeof plaintext);
1069	    plaintextlen = 0;
1070	    memset(ciphertext, 0, sizeof ciphertext);
1071	    ciphertextlen = 0;
1072	    fputs(buf, aesresp);
1073	    continue;
1074	}
1075	/* KEY = ... */
1076	if (strncmp(buf, "KEY", 3) == 0) {
1077	    i = 3;
1078	    while (isspace(buf[i]) || buf[i] == '=') {
1079		i++;
1080	    }
1081	    for (j=0; isxdigit(buf[i]); i+=2,j++) {
1082		hex_to_byteval(&buf[i], &key[j]);
1083	    }
1084	    keysize = j;
1085	    fputs(buf, aesresp);
1086	    continue;
1087	}
1088	/* IV = ... */
1089	if (strncmp(buf, "IV", 2) == 0) {
1090	    mode = NSS_AES_CBC;
1091	    i = 2;
1092	    while (isspace(buf[i]) || buf[i] == '=') {
1093		i++;
1094	    }
1095	    for (j=0; j<sizeof iv; i+=2,j++) {
1096		hex_to_byteval(&buf[i], &iv[j]);
1097	    }
1098	    fputs(buf, aesresp);
1099	    continue;
1100	}
1101	/* PLAINTEXT = ... */
1102	if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1103	    /* sanity check */
1104	    if (!encrypt) {
1105		goto loser;
1106	    }
1107
1108	    i = 9;
1109	    while (isspace(buf[i]) || buf[i] == '=') {
1110		i++;
1111	    }
1112	    for (j=0; isxdigit(buf[i]); i+=2,j++) {
1113		hex_to_byteval(&buf[i], &plaintext[j]);
1114	    }
1115	    plaintextlen = j;
1116
1117	    rv = aes_encrypt_buf(mode, key, keysize,
1118		(mode == NSS_AES) ? NULL : iv,
1119		ciphertext, &ciphertextlen, sizeof ciphertext,
1120		plaintext, plaintextlen);
1121	    if (rv != SECSuccess) {
1122		goto loser;
1123	    }
1124
1125	    fputs(buf, aesresp);
1126	    fputs("CIPHERTEXT = ", aesresp);
1127	    to_hex_str(buf, ciphertext, ciphertextlen);
1128	    fputs(buf, aesresp);
1129	    fputc('\n', aesresp);
1130	    continue;
1131	}
1132	/* CIPHERTEXT = ... */
1133	if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1134	    /* sanity check */
1135	    if (encrypt) {
1136		goto loser;
1137	    }
1138
1139	    i = 10;
1140	    while (isspace(buf[i]) || buf[i] == '=') {
1141		i++;
1142	    }
1143	    for (j=0; isxdigit(buf[i]); i+=2,j++) {
1144		hex_to_byteval(&buf[i], &ciphertext[j]);
1145	    }
1146	    ciphertextlen = j;
1147
1148	    rv = aes_decrypt_buf(mode, key, keysize,
1149		(mode == NSS_AES) ? NULL : iv,
1150		plaintext, &plaintextlen, sizeof plaintext,
1151		ciphertext, ciphertextlen);
1152	    if (rv != SECSuccess) {
1153		goto loser;
1154	    }
1155
1156	    fputs(buf, aesresp);
1157	    fputs("PLAINTEXT = ", aesresp);
1158	    to_hex_str(buf, plaintext, plaintextlen);
1159	    fputs(buf, aesresp);
1160	    fputc('\n', aesresp);
1161	    continue;
1162	}
1163    }
1164loser:
1165    fclose(aesreq);
1166}
1167
1168/*
1169 * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo
1170 * Test (MCT) in ECB and CBC modes.
1171 */
1172void
1173aes_mct_next_key(unsigned char *key, unsigned int keysize,
1174    const unsigned char *ciphertext_1, const unsigned char *ciphertext)
1175{
1176    int k;
1177
1178    switch (keysize) {
1179    case 16:  /* 128-bit key */
1180	/* Key[i+1] = Key[i] xor CT[j] */
1181	for (k=0; k<16; k++) {
1182	    key[k] ^= ciphertext[k];
1183	}
1184	break;
1185    case 24:  /* 192-bit key */
1186	/*
1187	 * Key[i+1] = Key[i] xor (last 64-bits of
1188	 *            CT[j-1] || CT[j])
1189	 */
1190	for (k=0; k<8; k++) {
1191	    key[k] ^= ciphertext_1[k+8];
1192	}
1193	for (k=8; k<24; k++) {
1194	    key[k] ^= ciphertext[k-8];
1195	}
1196	break;
1197    case 32:  /* 256-bit key */
1198	/* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */
1199	for (k=0; k<16; k++) {
1200	    key[k] ^= ciphertext_1[k];
1201	}
1202	for (k=16; k<32; k++) {
1203	    key[k] ^= ciphertext[k-16];
1204	}
1205	break;
1206    }
1207}
1208
1209/*
1210 * Perform the AES Monte Carlo Test (MCT) in ECB mode.  MCT exercises
1211 * our AES code in streaming mode because the plaintext or ciphertext
1212 * is generated block by block as we go, so we can't collect all the
1213 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1214 * one shot.
1215 *
1216 * reqfn is the pathname of the input REQUEST file.
1217 *
1218 * The output RESPONSE file is written to stdout.
1219 */
1220void
1221aes_ecb_mct(char *reqfn)
1222{
1223    char buf[80];       /* holds one line from the input REQUEST file.
1224                         * needs to be large enough to hold the longest
1225                         * line "KEY = <64 hex digits>\n".
1226                         */
1227    FILE *aesreq;       /* input stream from the REQUEST file */
1228    FILE *aesresp;      /* output stream to the RESPONSE file */
1229    int i, j;
1230    int encrypt = 0;    /* 1 means encrypt, 0 means decrypt */
1231    unsigned char key[32];              /* 128, 192, or 256 bits */
1232    unsigned int keysize;
1233    unsigned char plaintext[16];        /* PT[j] */
1234    unsigned char plaintext_1[16];      /* PT[j-1] */
1235    unsigned char ciphertext[16];       /* CT[j] */
1236    unsigned char ciphertext_1[16];     /* CT[j-1] */
1237    unsigned char doublecheck[16];
1238    unsigned int outputlen;
1239    AESContext *cx = NULL;	/* the operation being tested */
1240    AESContext *cx2 = NULL;     /* the inverse operation done in parallel
1241                                 * to doublecheck our result.
1242                                 */
1243    SECStatus rv;
1244
1245    aesreq = fopen(reqfn, "r");
1246    aesresp = stdout;
1247    while (fgets(buf, sizeof buf, aesreq) != NULL) {
1248	/* a comment or blank line */
1249	if (buf[0] == '#' || buf[0] == '\n') {
1250	    fputs(buf, aesresp);
1251	    continue;
1252	}
1253	/* [ENCRYPT] or [DECRYPT] */
1254	if (buf[0] == '[') {
1255	    if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1256		encrypt = 1;
1257	    } else {
1258		encrypt = 0;
1259	    }
1260	    fputs(buf, aesresp);
1261	    continue;
1262	}
1263	/* "COUNT = x" begins a new data set */
1264	if (strncmp(buf, "COUNT", 5) == 0) {
1265	    /* zeroize the variables for the test with this data set */
1266	    memset(key, 0, sizeof key);
1267	    keysize = 0;
1268	    memset(plaintext, 0, sizeof plaintext);
1269	    memset(ciphertext, 0, sizeof ciphertext);
1270	    continue;
1271	}
1272	/* KEY = ... */
1273	if (strncmp(buf, "KEY", 3) == 0) {
1274	    /* Key[0] = Key */
1275	    i = 3;
1276	    while (isspace(buf[i]) || buf[i] == '=') {
1277		i++;
1278	    }
1279	    for (j=0; isxdigit(buf[i]); i+=2,j++) {
1280		hex_to_byteval(&buf[i], &key[j]);
1281	    }
1282	    keysize = j;
1283	    continue;
1284	}
1285	/* PLAINTEXT = ... */
1286	if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1287	    /* sanity check */
1288	    if (!encrypt) {
1289		goto loser;
1290	    }
1291	    /* PT[0] = PT */
1292	    i = 9;
1293	    while (isspace(buf[i]) || buf[i] == '=') {
1294		i++;
1295	    }
1296	    for (j=0; j<sizeof plaintext; i+=2,j++) {
1297		hex_to_byteval(&buf[i], &plaintext[j]);
1298	    }
1299
1300	    for (i=0; i<100; i++) {
1301		sprintf(buf, "COUNT = %d\n", i);
1302	        fputs(buf, aesresp);
1303		/* Output Key[i] */
1304		fputs("KEY = ", aesresp);
1305		to_hex_str(buf, key, keysize);
1306		fputs(buf, aesresp);
1307		fputc('\n', aesresp);
1308		/* Output PT[0] */
1309		fputs("PLAINTEXT = ", aesresp);
1310		to_hex_str(buf, plaintext, sizeof plaintext);
1311		fputs(buf, aesresp);
1312		fputc('\n', aesresp);
1313
1314		cx = AES_CreateContext(key, NULL, NSS_AES,
1315		    PR_TRUE, keysize, 16);
1316		if (cx == NULL) {
1317		    goto loser;
1318		}
1319		/*
1320		 * doublecheck our result by decrypting the result
1321		 * and comparing the output with the plaintext.
1322		 */
1323		cx2 = AES_CreateContext(key, NULL, NSS_AES,
1324		    PR_FALSE, keysize, 16);
1325		if (cx2 == NULL) {
1326		    goto loser;
1327		}
1328		for (j=0; j<1000; j++) {
1329		    /* Save CT[j-1] */
1330		    memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
1331
1332		    /* CT[j] = AES(Key[i], PT[j]) */
1333		    outputlen = 0;
1334		    rv = AES_Encrypt(cx,
1335			ciphertext, &outputlen, sizeof ciphertext,
1336			plaintext, sizeof plaintext);
1337		    if (rv != SECSuccess) {
1338			goto loser;
1339		    }
1340		    if (outputlen != sizeof plaintext) {
1341			goto loser;
1342		    }
1343
1344		    /* doublecheck our result */
1345		    outputlen = 0;
1346		    rv = AES_Decrypt(cx2,
1347			doublecheck, &outputlen, sizeof doublecheck,
1348			ciphertext, sizeof ciphertext);
1349		    if (rv != SECSuccess) {
1350			goto loser;
1351		    }
1352		    if (outputlen != sizeof ciphertext) {
1353			goto loser;
1354		    }
1355		    if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
1356			goto loser;
1357		    }
1358
1359		    /* PT[j+1] = CT[j] */
1360		    memcpy(plaintext, ciphertext, sizeof plaintext);
1361		}
1362		AES_DestroyContext(cx, PR_TRUE);
1363		cx = NULL;
1364		AES_DestroyContext(cx2, PR_TRUE);
1365		cx2 = NULL;
1366
1367		/* Output CT[j] */
1368		fputs("CIPHERTEXT = ", aesresp);
1369		to_hex_str(buf, ciphertext, sizeof ciphertext);
1370		fputs(buf, aesresp);
1371		fputc('\n', aesresp);
1372
1373		/* Key[i+1] = Key[i] xor ... */
1374		aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
1375		/* PT[0] = CT[j] */
1376		/* done at the end of the for(j) loop */
1377
1378		fputc('\n', aesresp);
1379	    }
1380
1381	    continue;
1382	}
1383	/* CIPHERTEXT = ... */
1384	if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1385	    /* sanity check */
1386	    if (encrypt) {
1387		goto loser;
1388	    }
1389	    /* CT[0] = CT */
1390	    i = 10;
1391	    while (isspace(buf[i]) || buf[i] == '=') {
1392		i++;
1393	    }
1394	    for (j=0; isxdigit(buf[i]); i+=2,j++) {
1395		hex_to_byteval(&buf[i], &ciphertext[j]);
1396	    }
1397
1398	    for (i=0; i<100; i++) {
1399		sprintf(buf, "COUNT = %d\n", i);
1400	        fputs(buf, aesresp);
1401		/* Output Key[i] */
1402		fputs("KEY = ", aesresp);
1403		to_hex_str(buf, key, keysize);
1404		fputs(buf, aesresp);
1405		fputc('\n', aesresp);
1406		/* Output CT[0] */
1407		fputs("CIPHERTEXT = ", aesresp);
1408		to_hex_str(buf, ciphertext, sizeof ciphertext);
1409		fputs(buf, aesresp);
1410		fputc('\n', aesresp);
1411
1412		cx = AES_CreateContext(key, NULL, NSS_AES,
1413		    PR_FALSE, keysize, 16);
1414		if (cx == NULL) {
1415		    goto loser;
1416		}
1417		/*
1418		 * doublecheck our result by encrypting the result
1419		 * and comparing the output with the ciphertext.
1420		 */
1421		cx2 = AES_CreateContext(key, NULL, NSS_AES,
1422		    PR_TRUE, keysize, 16);
1423		if (cx2 == NULL) {
1424		    goto loser;
1425		}
1426		for (j=0; j<1000; j++) {
1427		    /* Save PT[j-1] */
1428		    memcpy(plaintext_1, plaintext, sizeof plaintext);
1429
1430		    /* PT[j] = AES(Key[i], CT[j]) */
1431		    outputlen = 0;
1432		    rv = AES_Decrypt(cx,
1433			plaintext, &outputlen, sizeof plaintext,
1434			ciphertext, sizeof ciphertext);
1435		    if (rv != SECSuccess) {
1436			goto loser;
1437		    }
1438		    if (outputlen != sizeof ciphertext) {
1439			goto loser;
1440		    }
1441
1442		    /* doublecheck our result */
1443		    outputlen = 0;
1444		    rv = AES_Encrypt(cx2,
1445			doublecheck, &outputlen, sizeof doublecheck,
1446			plaintext, sizeof plaintext);
1447		    if (rv != SECSuccess) {
1448			goto loser;
1449		    }
1450		    if (outputlen != sizeof plaintext) {
1451			goto loser;
1452		    }
1453		    if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
1454			goto loser;
1455		    }
1456
1457		    /* CT[j+1] = PT[j] */
1458		    memcpy(ciphertext, plaintext, sizeof ciphertext);
1459		}
1460		AES_DestroyContext(cx, PR_TRUE);
1461		cx = NULL;
1462		AES_DestroyContext(cx2, PR_TRUE);
1463		cx2 = NULL;
1464
1465		/* Output PT[j] */
1466		fputs("PLAINTEXT = ", aesresp);
1467		to_hex_str(buf, plaintext, sizeof plaintext);
1468		fputs(buf, aesresp);
1469		fputc('\n', aesresp);
1470
1471		/* Key[i+1] = Key[i] xor ... */
1472		aes_mct_next_key(key, keysize, plaintext_1, plaintext);
1473		/* CT[0] = PT[j] */
1474		/* done at the end of the for(j) loop */
1475
1476		fputc('\n', aesresp);
1477	    }
1478
1479	    continue;
1480	}
1481    }
1482loser:
1483    if (cx != NULL) {
1484	AES_DestroyContext(cx, PR_TRUE);
1485    }
1486    if (cx2 != NULL) {
1487	AES_DestroyContext(cx2, PR_TRUE);
1488    }
1489    fclose(aesreq);
1490}
1491
1492/*
1493 * Perform the AES Monte Carlo Test (MCT) in CBC mode.  MCT exercises
1494 * our AES code in streaming mode because the plaintext or ciphertext
1495 * is generated block by block as we go, so we can't collect all the
1496 * plaintext or ciphertext in one buffer and encrypt or decrypt it in
1497 * one shot.
1498 *
1499 * reqfn is the pathname of the input REQUEST file.
1500 *
1501 * The output RESPONSE file is written to stdout.
1502 */
1503void
1504aes_cbc_mct(char *reqfn)
1505{
1506    char buf[80];       /* holds one line from the input REQUEST file.
1507                         * needs to be large enough to hold the longest
1508                         * line "KEY = <64 hex digits>\n".
1509                         */
1510    FILE *aesreq;       /* input stream from the REQUEST file */
1511    FILE *aesresp;      /* output stream to the RESPONSE file */
1512    int i, j;
1513    int encrypt = 0;    /* 1 means encrypt, 0 means decrypt */
1514    unsigned char key[32];              /* 128, 192, or 256 bits */
1515    unsigned int keysize;
1516    unsigned char iv[16];
1517    unsigned char plaintext[16];        /* PT[j] */
1518    unsigned char plaintext_1[16];      /* PT[j-1] */
1519    unsigned char ciphertext[16];       /* CT[j] */
1520    unsigned char ciphertext_1[16];     /* CT[j-1] */
1521    unsigned char doublecheck[16];
1522    unsigned int outputlen;
1523    AESContext *cx = NULL;	/* the operation being tested */
1524    AESContext *cx2 = NULL;     /* the inverse operation done in parallel
1525                                 * to doublecheck our result.
1526                                 */
1527    SECStatus rv;
1528
1529    aesreq = fopen(reqfn, "r");
1530    aesresp = stdout;
1531    while (fgets(buf, sizeof buf, aesreq) != NULL) {
1532	/* a comment or blank line */
1533	if (buf[0] == '#' || buf[0] == '\n') {
1534	    fputs(buf, aesresp);
1535	    continue;
1536	}
1537	/* [ENCRYPT] or [DECRYPT] */
1538	if (buf[0] == '[') {
1539	    if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
1540		encrypt = 1;
1541	    } else {
1542		encrypt = 0;
1543	    }
1544	    fputs(buf, aesresp);
1545	    continue;
1546	}
1547	/* "COUNT = x" begins a new data set */
1548	if (strncmp(buf, "COUNT", 5) == 0) {
1549	    /* zeroize the variables for the test with this data set */
1550	    memset(key, 0, sizeof key);
1551	    keysize = 0;
1552	    memset(iv, 0, sizeof iv);
1553	    memset(plaintext, 0, sizeof plaintext);
1554	    memset(ciphertext, 0, sizeof ciphertext);
1555	    continue;
1556	}
1557	/* KEY = ... */
1558	if (strncmp(buf, "KEY", 3) == 0) {
1559	    /* Key[0] = Key */
1560	    i = 3;
1561	    while (isspace(buf[i]) || buf[i] == '=') {
1562		i++;
1563	    }
1564	    for (j=0; isxdigit(buf[i]); i+=2,j++) {
1565		hex_to_byteval(&buf[i], &key[j]);
1566	    }
1567	    keysize = j;
1568	    continue;
1569	}
1570	/* IV = ... */
1571	if (strncmp(buf, "IV", 2) == 0) {
1572	    /* IV[0] = IV */
1573	    i = 2;
1574	    while (isspace(buf[i]) || buf[i] == '=') {
1575		i++;
1576	    }
1577	    for (j=0; j<sizeof iv; i+=2,j++) {
1578		hex_to_byteval(&buf[i], &iv[j]);
1579	    }
1580	    continue;
1581	}
1582	/* PLAINTEXT = ... */
1583	if (strncmp(buf, "PLAINTEXT", 9) == 0) {
1584	    /* sanity check */
1585	    if (!encrypt) {
1586		goto loser;
1587	    }
1588	    /* PT[0] = PT */
1589	    i = 9;
1590	    while (isspace(buf[i]) || buf[i] == '=') {
1591		i++;
1592	    }
1593	    for (j=0; j<sizeof plaintext; i+=2,j++) {
1594		hex_to_byteval(&buf[i], &plaintext[j]);
1595	    }
1596
1597	    for (i=0; i<100; i++) {
1598		sprintf(buf, "COUNT = %d\n", i);
1599	        fputs(buf, aesresp);
1600		/* Output Key[i] */
1601		fputs("KEY = ", aesresp);
1602		to_hex_str(buf, key, keysize);
1603		fputs(buf, aesresp);
1604		fputc('\n', aesresp);
1605		/* Output IV[i] */
1606		fputs("IV = ", aesresp);
1607		to_hex_str(buf, iv, sizeof iv);
1608		fputs(buf, aesresp);
1609		fputc('\n', aesresp);
1610		/* Output PT[0] */
1611		fputs("PLAINTEXT = ", aesresp);
1612		to_hex_str(buf, plaintext, sizeof plaintext);
1613		fputs(buf, aesresp);
1614		fputc('\n', aesresp);
1615
1616		cx = AES_CreateContext(key, iv, NSS_AES_CBC,
1617		    PR_TRUE, keysize, 16);
1618		if (cx == NULL) {
1619		    goto loser;
1620		}
1621		/*
1622		 * doublecheck our result by decrypting the result
1623		 * and comparing the output with the plaintext.
1624		 */
1625		cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
1626		    PR_FALSE, keysize, 16);
1627		if (cx2 == NULL) {
1628		    goto loser;
1629		}
1630		/* CT[-1] = IV[i] */
1631		memcpy(ciphertext, iv, sizeof ciphertext);
1632		for (j=0; j<1000; j++) {
1633		    /* Save CT[j-1] */
1634		    memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
1635		    /*
1636		     * If ( j=0 )
1637		     *      CT[j] = AES(Key[i], IV[i], PT[j])
1638		     *      PT[j+1] = IV[i] (= CT[j-1])
1639		     * Else
1640		     *      CT[j] = AES(Key[i], PT[j])
1641		     *      PT[j+1] = CT[j-1]
1642		     */
1643		    outputlen = 0;
1644		    rv = AES_Encrypt(cx,
1645			ciphertext, &outputlen, sizeof ciphertext,
1646			plaintext, sizeof plaintext);
1647		    if (rv != SECSuccess) {
1648			goto loser;
1649		    }
1650		    if (outputlen != sizeof plaintext) {
1651			goto loser;
1652		    }
1653
1654		    /* doublecheck our result */
1655		    outputlen = 0;
1656		    rv = AES_Decrypt(cx2,
1657			doublecheck, &outputlen, sizeof doublecheck,
1658			ciphertext, sizeof ciphertext);
1659		    if (rv != SECSuccess) {
1660			goto loser;
1661		    }
1662		    if (outputlen != sizeof ciphertext) {
1663			goto loser;
1664		    }
1665		    if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
1666			goto loser;
1667		    }
1668
1669		    memcpy(plaintext, ciphertext_1, sizeof plaintext);
1670		}
1671		AES_DestroyContext(cx, PR_TRUE);
1672		cx = NULL;
1673		AES_DestroyContext(cx2, PR_TRUE);
1674		cx2 = NULL;
1675
1676		/* Output CT[j] */
1677		fputs("CIPHERTEXT = ", aesresp);
1678		to_hex_str(buf, ciphertext, sizeof ciphertext);
1679		fputs(buf, aesresp);
1680		fputc('\n', aesresp);
1681
1682		/* Key[i+1] = Key[i] xor ... */
1683		aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
1684		/* IV[i+1] = CT[j] */
1685		memcpy(iv, ciphertext, sizeof iv);
1686		/* PT[0] = CT[j-1] */
1687		/* done at the end of the for(j) loop */
1688
1689		fputc('\n', aesresp);
1690	    }
1691
1692	    continue;
1693	}
1694	/* CIPHERTEXT = ... */
1695	if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
1696	    /* sanity check */
1697	    if (encrypt) {
1698		goto loser;
1699	    }
1700	    /* CT[0] = CT */
1701	    i = 10;
1702	    while (isspace(buf[i]) || buf[i] == '=') {
1703		i++;
1704	    }
1705	    for (j=0; isxdigit(buf[i]); i+=2,j++) {
1706		hex_to_byteval(&buf[i], &ciphertext[j]);
1707	    }
1708
1709	    for (i=0; i<100; i++) {
1710		sprintf(buf, "COUNT = %d\n", i);
1711	        fputs(buf, aesresp);
1712		/* Output Key[i] */
1713		fputs("KEY = ", aesresp);
1714		to_hex_str(buf, key, keysize);
1715		fputs(buf, aesresp);
1716		fputc('\n', aesresp);
1717		/* Output IV[i] */
1718		fputs("IV = ", aesresp);
1719		to_hex_str(buf, iv, sizeof iv);
1720		fputs(buf, aesresp);
1721		fputc('\n', aesresp);
1722		/* Output CT[0] */
1723		fputs("CIPHERTEXT = ", aesresp);
1724		to_hex_str(buf, ciphertext, sizeof ciphertext);
1725		fputs(buf, aesresp);
1726		fputc('\n', aesresp);
1727
1728		cx = AES_CreateContext(key, iv, NSS_AES_CBC,
1729		    PR_FALSE, keysize, 16);
1730		if (cx == NULL) {
1731		    goto loser;
1732		}
1733		/*
1734		 * doublecheck our result by encrypting the result
1735		 * and comparing the output with the ciphertext.
1736		 */
1737		cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
1738		    PR_TRUE, keysize, 16);
1739		if (cx2 == NULL) {
1740		    goto loser;
1741		}
1742		/* PT[-1] = IV[i] */
1743		memcpy(plaintext, iv, sizeof plaintext);
1744		for (j=0; j<1000; j++) {
1745		    /* Save PT[j-1] */
1746		    memcpy(plaintext_1, plaintext, sizeof plaintext);
1747		    /*
1748		     * If ( j=0 )
1749		     *      PT[j] = AES(Key[i], IV[i], CT[j])
1750		     *      CT[j+1] = IV[i] (= PT[j-1])
1751		     * Else
1752		     *      PT[j] = AES(Key[i], CT[j])
1753		     *      CT[j+1] = PT[j-1]
1754		     */
1755		    outputlen = 0;
1756		    rv = AES_Decrypt(cx,
1757			plaintext, &outputlen, sizeof plaintext,
1758			ciphertext, sizeof ciphertext);
1759		    if (rv != SECSuccess) {
1760			goto loser;
1761		    }
1762		    if (outputlen != sizeof ciphertext) {
1763			goto loser;
1764		    }
1765
1766		    /* doublecheck our result */
1767		    outputlen = 0;
1768		    rv = AES_Encrypt(cx2,
1769			doublecheck, &outputlen, sizeof doublecheck,
1770			plaintext, sizeof plaintext);
1771		    if (rv != SECSuccess) {
1772			goto loser;
1773		    }
1774		    if (outputlen != sizeof plaintext) {
1775			goto loser;
1776		    }
1777		    if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
1778			goto loser;
1779		    }
1780
1781		    memcpy(ciphertext, plaintext_1, sizeof ciphertext);
1782		}
1783		AES_DestroyContext(cx, PR_TRUE);
1784		cx = NULL;
1785		AES_DestroyContext(cx2, PR_TRUE);
1786		cx2 = NULL;
1787
1788		/* Output PT[j] */
1789		fputs("

Large files files are truncated, but you can click here to view the full file