security/nss/cmd/fipstest/fipstest.c

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     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/. */
     5 #include <stdio.h>
     6 #include <stdlib.h>
     7 #include <ctype.h>
     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"
    21 #if 0
    22 #include "../../lib/freebl/mpi/mpi.h"
    23 #endif
    25 #ifndef NSS_DISABLE_ECC
    26 extern SECStatus
    27 EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
    28 extern SECStatus
    29 EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
    30               const ECParams *srcParams);
    31 #endif
    33 #define ENCRYPT 1
    34 #define DECRYPT 0
    35 #define BYTE unsigned char
    36 #define DEFAULT_RSA_PUBLIC_EXPONENT   0x10001
    37 #define RSA_MAX_TEST_MODULUS_BITS     4096
    38 #define RSA_MAX_TEST_MODULUS_BYTES    RSA_MAX_TEST_MODULUS_BITS/8
    39 #define RSA_MAX_TEST_EXPONENT_BYTES   8
    40 #define PQG_TEST_SEED_BYTES           20
    42 SECStatus
    43 hex_to_byteval(const char *c2, unsigned char *byteval)
    44 {
    45     int i;
    46     unsigned char offset;
    47     *byteval = 0;
    48     for (i=0; i<2; i++) {
    49 	if (c2[i] >= '0' && c2[i] <= '9') {
    50 	    offset = c2[i] - '0';
    51 	    *byteval |= offset << 4*(1-i);
    52 	} else if (c2[i] >= 'a' && c2[i] <= 'f') {
    53 	    offset = c2[i] - 'a';
    54 	    *byteval |= (offset + 10) << 4*(1-i);
    55 	} else if (c2[i] >= 'A' && c2[i] <= 'F') {
    56 	    offset = c2[i] - 'A';
    57 	    *byteval |= (offset + 10) << 4*(1-i);
    58 	} else {
    59 	    return SECFailure;
    60 	}
    61     }
    62     return SECSuccess;
    63 }
    65 SECStatus
    66 byteval_to_hex(unsigned char byteval, char *c2, char a)
    67 {
    68     int i;
    69     unsigned char offset;
    70     for (i=0; i<2; i++) {
    71 	offset = (byteval >> 4*(1-i)) & 0x0f;
    72 	if (offset < 10) {
    73 	    c2[i] = '0' + offset;
    74 	} else {
    75 	    c2[i] = a + offset - 10;
    76 	}
    77     }
    78     return SECSuccess;
    79 }
    81 void
    82 to_hex_str(char *str, const unsigned char *buf, unsigned int len)
    83 {
    84     unsigned int i;
    85     for (i=0; i<len; i++) {
    86 	byteval_to_hex(buf[i], &str[2*i], 'a');
    87     }
    88     str[2*len] = '\0';
    89 }
    91 void
    92 to_hex_str_cap(char *str, const unsigned char *buf, unsigned int len)
    93 {
    94     unsigned int i;
    95     for (i=0; i<len; i++) {
    96 	byteval_to_hex(buf[i], &str[2*i], 'A');
    97     }
    98     str[2*len] = '\0';
    99 }
   101 /*
   102  * Convert a string of hex digits (str) to an array (buf) of len bytes.
   103  * Return PR_TRUE if the hex string can fit in the byte array.  Return
   104  * PR_FALSE if the hex string is empty or is too long.
   105  */
   106 PRBool
   107 from_hex_str(unsigned char *buf, unsigned int len, const char *str)
   108 {
   109     unsigned int nxdigit;  /* number of hex digits in str */
   110     unsigned int i;  /* index into buf */
   111     unsigned int j;  /* index into str */
   113     /* count the hex digits */
   114     nxdigit = 0;
   115     for (nxdigit = 0; isxdigit(str[nxdigit]); nxdigit++) {
   116 	/* empty body */
   117     }
   118     if (nxdigit == 0) {
   119 	return PR_FALSE;
   120     }
   121     if (nxdigit > 2*len) {
   122 	/*
   123 	 * The input hex string is too long, but we allow it if the
   124 	 * extra digits are leading 0's.
   125 	 */
   126 	for (j = 0; j < nxdigit-2*len; j++) {
   127 	    if (str[j] != '0') {
   128 		return PR_FALSE;
   129 	    }
   130 	}
   131 	/* skip leading 0's */
   132 	str += nxdigit-2*len;
   133 	nxdigit = 2*len;
   134     }
   135     for (i=0, j=0; i< len; i++) {
   136 	if (2*i < 2*len-nxdigit) {
   137 	    /* Handle a short input as if we padded it with leading 0's. */
   138 	    if (2*i+1 < 2*len-nxdigit) {
   139 		buf[i] = 0;
   140 	    } else {
   141 		char tmp[2];
   142 		tmp[0] = '0';
   143 		tmp[1] = str[j];
   144 		hex_to_byteval(tmp, &buf[i]);
   145 		j++;
   146 	    }
   147 	} else {
   148 	    hex_to_byteval(&str[j], &buf[i]);
   149 	    j += 2;
   150 	}
   151     }
   152     return PR_TRUE;
   153 }
   155 SECStatus
   156 tdea_encrypt_buf(
   157     int mode,
   158     const unsigned char *key, 
   159     const unsigned char *iv,
   160     unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
   161     const unsigned char *input, unsigned int inputlen)
   162 {
   163     SECStatus rv = SECFailure;
   164     DESContext *cx;
   165     unsigned char doublecheck[8*20];  /* 1 to 20 blocks */
   166     unsigned int doublechecklen = 0;
   168     cx = DES_CreateContext(key, iv, mode, PR_TRUE);
   169     if (cx == NULL) {
   170         goto loser;
   171     }
   172     rv = DES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
   173     if (rv != SECSuccess) {
   174         goto loser;
   175     }
   176     if (*outputlen != inputlen) {
   177         goto loser;
   178     }
   179     DES_DestroyContext(cx, PR_TRUE);
   180     cx = NULL;
   182     /*
   183      * Doublecheck our result by decrypting the ciphertext and
   184      * compare the output with the input plaintext.
   185      */
   186     cx = DES_CreateContext(key, iv, mode, PR_FALSE);
   187     if (cx == NULL) {
   188         goto loser;
   189     }
   190     rv = DES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
   191                     output, *outputlen);
   192     if (rv != SECSuccess) {
   193         goto loser;
   194     }
   195     if (doublechecklen != *outputlen) {
   196         goto loser;
   197     }
   198     DES_DestroyContext(cx, PR_TRUE);
   199     cx = NULL;
   200     if (memcmp(doublecheck, input, inputlen) != 0) {
   201         goto loser;
   202     }
   203     rv = SECSuccess;
   205 loser:
   206     if (cx != NULL) {
   207         DES_DestroyContext(cx, PR_TRUE);
   208     }
   209     return rv;
   210 }
   212 SECStatus
   213 tdea_decrypt_buf(
   214     int mode,
   215     const unsigned char *key, 
   216     const unsigned char *iv,
   217     unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
   218     const unsigned char *input, unsigned int inputlen)
   219 {
   220     SECStatus rv = SECFailure;
   221     DESContext *cx;
   222     unsigned char doublecheck[8*20];  /* 1 to 20 blocks */
   223     unsigned int doublechecklen = 0;
   225     cx = DES_CreateContext(key, iv, mode, PR_FALSE);
   226     if (cx == NULL) {
   227         goto loser;
   228     }
   229     rv = DES_Decrypt(cx, output, outputlen, maxoutputlen,
   230                     input, inputlen);
   231     if (rv != SECSuccess) {
   232         goto loser;
   233     }
   234     if (*outputlen != inputlen) {
   235         goto loser;
   236     }
   237     DES_DestroyContext(cx, PR_TRUE);
   238     cx = NULL;
   240     /*
   241      * Doublecheck our result by encrypting the plaintext and
   242      * compare the output with the input ciphertext.
   243      */
   244     cx = DES_CreateContext(key, iv, mode, PR_TRUE);
   245     if (cx == NULL) {
   246         goto loser;
   247     }
   248     rv = DES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
   249         output, *outputlen);
   250     if (rv != SECSuccess) {
   251         goto loser;
   252     }
   253     if (doublechecklen != *outputlen) {
   254         goto loser;
   255     }
   256     DES_DestroyContext(cx, PR_TRUE);
   257     cx = NULL;
   258     if (memcmp(doublecheck, input, inputlen) != 0) {
   259         goto loser;
   260     }
   261     rv = SECSuccess;
   263 loser:
   264     if (cx != NULL) {
   265         DES_DestroyContext(cx, PR_TRUE);
   266     }
   267     return rv;
   268 }
   270 /*
   271  * Perform the TDEA Known Answer Test (KAT) or Multi-block Message
   272  * Test (MMT) in ECB or CBC mode.  The KAT (there are five types)
   273  * and MMT have the same structure: given the key and IV (CBC mode
   274  * only), encrypt the given plaintext or decrypt the given ciphertext.
   275  * So we can handle them the same way.
   276  *
   277  * reqfn is the pathname of the REQUEST file.
   278  *
   279  * The output RESPONSE file is written to stdout.
   280  */
   281 void
   282 tdea_kat_mmt(char *reqfn)
   283 {
   284     char buf[180];      /* holds one line from the input REQUEST file.
   285                          * needs to be large enough to hold the longest
   286                          * line "CIPHERTEXT = <180 hex digits>\n".
   287                          */
   288     FILE *req;       /* input stream from the REQUEST file */
   289     FILE *resp;      /* output stream to the RESPONSE file */
   290     int i, j;
   291     int mode;           /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */
   292     int crypt = DECRYPT;    /* 1 means encrypt, 0 means decrypt */
   293     unsigned char key[24];              /* TDEA 3 key bundle */
   294     unsigned int numKeys = 0;
   295     unsigned char iv[8];		/* for all modes except ECB */
   296     unsigned char plaintext[8*20];     /* 1 to 20 blocks */
   297     unsigned int plaintextlen;
   298     unsigned char ciphertext[8*20];   /* 1 to 20 blocks */  
   299     unsigned int ciphertextlen;
   300     SECStatus rv;
   302     req = fopen(reqfn, "r");
   303     resp = stdout;
   304     while (fgets(buf, sizeof buf, req) != NULL) {
   305         /* a comment or blank line */
   306         if (buf[0] == '#' || buf[0] == '\n') {
   307             fputs(buf, resp);
   308             continue;
   309         }
   310         /* [ENCRYPT] or [DECRYPT] */
   311         if (buf[0] == '[') {
   312             if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
   313                 crypt = ENCRYPT;
   314             } else {
   315                 crypt = DECRYPT;
   316             }
   317             fputs(buf, resp);
   318             continue;
   319         }
   320         /* NumKeys */
   321         if (strncmp(&buf[0], "NumKeys", 7) == 0) {
   322             i = 7;
   323             while (isspace(buf[i]) || buf[i] == '=') {
   324                 i++;
   325             }
   326             numKeys = buf[i];
   327             fputs(buf, resp);
   328             continue;
   329         }
   330         /* "COUNT = x" begins a new data set */
   331         if (strncmp(buf, "COUNT", 5) == 0) {
   332             /* mode defaults to ECB, if dataset has IV mode will be set CBC */
   333             mode = NSS_DES_EDE3;
   334             /* zeroize the variables for the test with this data set */
   335             memset(key, 0, sizeof key);
   336             memset(iv, 0, sizeof iv);
   337             memset(plaintext, 0, sizeof plaintext);
   338             plaintextlen = 0;
   339             memset(ciphertext, 0, sizeof ciphertext);
   340             ciphertextlen = 0;
   341             fputs(buf, resp);
   342             continue;
   343         }
   344         if (numKeys == 0) {
   345             if (strncmp(buf, "KEYs", 4) == 0) {
   346                 i = 4;
   347                 while (isspace(buf[i]) || buf[i] == '=') {
   348                     i++;
   349                 }
   350                 for (j=0; isxdigit(buf[i]); i+=2,j++) {
   351                     hex_to_byteval(&buf[i], &key[j]);
   352                     key[j+8] = key[j];
   353                     key[j+16] = key[j];
   354                 }
   355                 fputs(buf, resp);
   356                 continue;
   357             }
   358         } else {
   359             /* KEY1 = ... */
   360             if (strncmp(buf, "KEY1", 4) == 0) {
   361                 i = 4;
   362                 while (isspace(buf[i]) || buf[i] == '=') {
   363                     i++;
   364                 }
   365                 for (j=0; isxdigit(buf[i]); i+=2,j++) {
   366                     hex_to_byteval(&buf[i], &key[j]);
   367                 }
   368                 fputs(buf, resp);
   369                 continue;
   370             }
   371             /* KEY2 = ... */
   372             if (strncmp(buf, "KEY2", 4) == 0) {
   373                 i = 4;
   374                 while (isspace(buf[i]) || buf[i] == '=') {
   375                     i++;
   376                 }
   377                 for (j=8; isxdigit(buf[i]); i+=2,j++) {
   378                     hex_to_byteval(&buf[i], &key[j]);
   379                 }
   380                 fputs(buf, resp);
   381                 continue;
   382             }
   383             /* KEY3 = ... */
   384             if (strncmp(buf, "KEY3", 4) == 0) {
   385                 i = 4;
   386                 while (isspace(buf[i]) || buf[i] == '=') {
   387                     i++;
   388                 }
   389                 for (j=16; isxdigit(buf[i]); i+=2,j++) {
   390                     hex_to_byteval(&buf[i], &key[j]);
   391                 }
   392                 fputs(buf, resp);
   393                 continue;
   394             }
   395         }
   397         /* IV = ... */
   398         if (strncmp(buf, "IV", 2) == 0) {
   399             mode = NSS_DES_EDE3_CBC;
   400             i = 2;
   401             while (isspace(buf[i]) || buf[i] == '=') {
   402                 i++;
   403             }
   404             for (j=0; j<sizeof iv; i+=2,j++) {
   405                 hex_to_byteval(&buf[i], &iv[j]);
   406             }
   407             fputs(buf, resp);
   408             continue;
   409         }
   411         /* PLAINTEXT = ... */
   412         if (strncmp(buf, "PLAINTEXT", 9) == 0) {
   413             /* sanity check */
   414             if (crypt != ENCRYPT) {
   415                 goto loser;
   416             }
   417             i = 9;
   418             while (isspace(buf[i]) || buf[i] == '=') {
   419                 i++;
   420             }
   421             for (j=0; isxdigit(buf[i]); i+=2,j++) {
   422                 hex_to_byteval(&buf[i], &plaintext[j]);
   423             }
   424             plaintextlen = j;
   425             rv = tdea_encrypt_buf(mode, key,
   426                             (mode == NSS_DES_EDE3) ? NULL : iv,
   427                             ciphertext, &ciphertextlen, sizeof ciphertext,
   428                             plaintext, plaintextlen);
   429             if (rv != SECSuccess) {
   430                 goto loser;
   431             }
   433             fputs(buf, resp);
   434             fputs("CIPHERTEXT = ", resp);
   435             to_hex_str(buf, ciphertext, ciphertextlen);
   436             fputs(buf, resp);
   437             fputc('\n', resp);
   438             continue;
   439         }
   440         /* CIPHERTEXT = ... */
   441         if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
   442             /* sanity check */
   443             if (crypt != DECRYPT) {
   444                 goto loser;
   445             }
   447             i = 10;
   448             while (isspace(buf[i]) || buf[i] == '=') {
   449                 i++;
   450             }
   451             for (j=0; isxdigit(buf[i]); i+=2,j++) {
   452                 hex_to_byteval(&buf[i], &ciphertext[j]);
   453             }
   454             ciphertextlen = j;
   456             rv = tdea_decrypt_buf(mode, key,
   457                             (mode == NSS_DES_EDE3) ? NULL : iv,
   458                             plaintext, &plaintextlen, sizeof plaintext,
   459                             ciphertext, ciphertextlen);
   460             if (rv != SECSuccess) {
   461                 goto loser;
   462             }
   464             fputs(buf, resp);
   465             fputs("PLAINTEXT = ", resp);
   466             to_hex_str(buf, plaintext, plaintextlen);
   467             fputs(buf, resp);
   468             fputc('\n', resp);
   469             continue;
   470         }
   471     }
   473 loser:
   474     fclose(req);
   475 }
   477 /*
   478 * Set the parity bit for the given byte
   479 */
   480 BYTE odd_parity( BYTE in)
   481 {
   482     BYTE out = in;
   483     in ^= in >> 4;
   484     in ^= in >> 2;
   485     in ^= in >> 1;
   486     return (BYTE)(out ^ !(in & 1));
   487 }
   489 /*
   490  * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j] 
   491  * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes.
   492  */
   493 void
   494 tdea_mct_next_keys(unsigned char *key,
   495     const unsigned char *text_2, const unsigned char *text_1, 
   496     const unsigned char *text, unsigned int numKeys)
   497 {
   498     int k;
   500     /* key1[i+1] = key1[i] xor PT/CT[j] */
   501     for (k=0; k<8; k++) {
   502         key[k] ^= text[k];
   503     }
   504     /* key2 */
   505     if (numKeys == 2 || numKeys == 3)  {
   506         /* key2 independent */
   507         for (k=8; k<16; k++) {
   508             /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */
   509             key[k] ^= text_1[k-8];
   510         }
   511     } else {
   512         /* key2 == key 1 */
   513         for (k=8; k<16; k++) {
   514             /* key2[i+1] = KEY2[i] xor PT/CT[j] */
   515             key[k] = key[k-8];
   516         }
   517     }
   518     /* key3 */
   519     if (numKeys == 1 || numKeys == 2) {
   520         /* key3 == key 1 */
   521         for (k=16; k<24; k++) {
   522             /* key3[i+1] = KEY3[i] xor PT/CT[j] */
   523             key[k] = key[k-16];
   524         }
   525     } else {
   526         /* key3 independent */ 
   527         for (k=16; k<24; k++) {
   528             /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */
   529             key[k] ^= text_2[k-16];
   530         }
   531     }
   532     /* set the parity bits */            
   533     for (k=0; k<24; k++) {
   534         key[k] = odd_parity(key[k]);
   535     }
   536 }
   538 /*
   539  * Perform the Monte Carlo Test
   540  *
   541  * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC
   542  * crypt = ENCRYPT || DECRYPT
   543  * inputtext = plaintext or Cyphertext depending on the value of crypt
   544  * inputlength is expected to be size 8 bytes 
   545  * iv = needs to be set for NSS_DES_EDE3_CBC mode
   546  * resp = is the output response file. 
   547  */
   548  void                                                       
   549 tdea_mct_test(int mode, unsigned char* key, unsigned int numKeys, 
   550               unsigned int crypt, unsigned char* inputtext, 
   551               unsigned int inputlength, unsigned char* iv, FILE *resp) { 
   553     int i, j;
   554     unsigned char outputtext_1[8];      /* PT/CT[j-1] */
   555     unsigned char outputtext_2[8];      /* PT/CT[j-2] */
   556     char buf[80];       /* holds one line from the input REQUEST file. */
   557     unsigned int outputlen;
   558     unsigned char outputtext[8];
   561     SECStatus rv;
   563     if (mode == NSS_DES_EDE3 && iv != NULL) {
   564         printf("IV must be NULL for NSS_DES_EDE3 mode");
   565         goto loser;
   566     } else if (mode == NSS_DES_EDE3_CBC && iv == NULL) {
   567         printf("IV must not be NULL for NSS_DES_EDE3_CBC mode");
   568         goto loser;
   569     }
   571     /* loop 400 times */
   572     for (i=0; i<400; i++) {
   573         /* if i == 0 CV[0] = IV  not necessary */        
   574         /* record the count and key values and plainText */
   575         sprintf(buf, "COUNT = %d\n", i);
   576         fputs(buf, resp);
   577         /* Output KEY1[i] */
   578         fputs("KEY1 = ", resp);
   579         to_hex_str(buf, key, 8);
   580         fputs(buf, resp);
   581         fputc('\n', resp);
   582         /* Output KEY2[i] */
   583         fputs("KEY2 = ", resp);
   584         to_hex_str(buf, &key[8], 8);
   585         fputs(buf, resp);
   586         fputc('\n', resp);
   587         /* Output KEY3[i] */
   588         fputs("KEY3 = ", resp);
   589         to_hex_str(buf, &key[16], 8);
   590         fputs(buf, resp);
   591         fputc('\n', resp);
   592         if (mode == NSS_DES_EDE3_CBC) {
   593             /* Output CV[i] */
   594             fputs("IV = ", resp);
   595             to_hex_str(buf, iv, 8);
   596             fputs(buf, resp);
   597             fputc('\n', resp);
   598         }
   599         if (crypt == ENCRYPT) {
   600             /* Output PT[0] */
   601             fputs("PLAINTEXT = ", resp);
   602         } else {
   603             /* Output CT[0] */
   604             fputs("CIPHERTEXT = ", resp);
   605         }
   607         to_hex_str(buf, inputtext, inputlength);
   608         fputs(buf, resp);
   609         fputc('\n', resp);
   611         /* loop 10,000 times */
   612         for (j=0; j<10000; j++) {
   614             outputlen = 0;
   615             if (crypt == ENCRYPT) {
   616                 /* inputtext == ciphertext outputtext == plaintext*/
   617                 rv = tdea_encrypt_buf(mode, key,
   618                             (mode == NSS_DES_EDE3) ? NULL : iv,
   619                             outputtext, &outputlen, 8,
   620                             inputtext, 8);
   621             } else {
   622                 /* inputtext == plaintext outputtext == ciphertext */
   623                 rv = tdea_decrypt_buf(mode, key,
   624                             (mode == NSS_DES_EDE3) ? NULL : iv,
   625                             outputtext, &outputlen, 8,
   626                             inputtext, 8);
   627             }
   629             if (rv != SECSuccess) {
   630                 goto loser;
   631             }
   632             if (outputlen != inputlength) {
   633                 goto loser;
   634             }
   636             if (mode == NSS_DES_EDE3_CBC) {
   637                 if (crypt == ENCRYPT) {
   638                     if (j == 0) {
   639                         /*P[j+1] = CV[0] */
   640                         memcpy(inputtext, iv, 8);
   641                     } else {
   642                         /* p[j+1] = C[j-1] */
   643                         memcpy(inputtext, outputtext_1, 8);
   644                     }
   645                     /* CV[j+1] = C[j] */
   646                     memcpy(iv, outputtext, 8);
   647                     if (j != 9999) {
   648                         /* save C[j-1] */
   649                         memcpy(outputtext_1, outputtext, 8);
   650                     }
   651                 } else { /* DECRYPT */
   652                     /* CV[j+1] = C[j] */
   653                     memcpy(iv, inputtext, 8);
   654                     /* C[j+1] = P[j] */
   655                     memcpy(inputtext, outputtext, 8);
   656                 }
   657             } else {
   658                 /* ECB mode PT/CT[j+1] = CT/PT[j] */
   659                 memcpy(inputtext, outputtext, 8);
   660             }
   662             /* Save PT/CT[j-2] and PT/CT[j-1] */
   663             if (j==9997) memcpy(outputtext_2, outputtext, 8);
   664             if (j==9998) memcpy(outputtext_1, outputtext, 8);
   665             /* done at the end of the for(j) loop */
   666         }
   669         if (crypt == ENCRYPT) {
   670             /* Output CT[j] */
   671             fputs("CIPHERTEXT = ", resp);
   672         } else {
   673             /* Output PT[j] */
   674             fputs("PLAINTEXT = ", resp);
   675         }
   676         to_hex_str(buf, outputtext, 8);
   677         fputs(buf, resp);
   678         fputc('\n', resp);
   680         /* Key[i+1] = Key[i] xor ...  outputtext_2 == PT/CT[j-2] 
   681          *  outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j] 
   682          */
   683         tdea_mct_next_keys(key, outputtext_2, 
   684                            outputtext_1, outputtext, numKeys);
   686         if (mode == NSS_DES_EDE3_CBC) {
   687             /* taken care of in the j=9999 iteration */
   688             if (crypt == ENCRYPT) {
   689                 /* P[i] = C[j-1] */
   690                 /* CV[i] = C[j] */
   691             } else {
   692                 /* taken care of in the j=9999 iteration */
   693                 /* CV[i] = C[j] */
   694                 /* C[i] = P[j]  */
   695             }
   696         } else {
   697             /* ECB PT/CT[i] = PT/CT[j]  */
   698             memcpy(inputtext, outputtext, 8);
   699         }
   700         /* done at the end of the for(i) loop */
   701         fputc('\n', resp);
   702     }
   704 loser:
   705     return;
   706 }
   708 /*
   709  * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes.
   710  * by gathering the input from the request file, and then 
   711  * calling tdea_mct_test.
   712  *
   713  * reqfn is the pathname of the input REQUEST file.
   714  *
   715  * The output RESPONSE file is written to stdout.
   716  */
   717 void
   718 tdea_mct(int mode, char *reqfn)
   719 {
   720     int i, j;
   721     char buf[80];    /* holds one line from the input REQUEST file. */
   722     FILE *req;       /* input stream from the REQUEST file */
   723     FILE *resp;      /* output stream to the RESPONSE file */
   724     unsigned int crypt = 0;    /* 1 means encrypt, 0 means decrypt */
   725     unsigned char key[24];              /* TDEA 3 key bundle */
   726     unsigned int numKeys = 0;
   727     unsigned char plaintext[8];        /* PT[j] */
   728     unsigned char ciphertext[8];       /* CT[j] */
   729     unsigned char iv[8];
   731     /* zeroize the variables for the test with this data set */
   732     memset(key, 0, sizeof key);
   733     memset(plaintext, 0, sizeof plaintext);
   734     memset(ciphertext, 0, sizeof ciphertext);
   735     memset(iv, 0, sizeof iv);
   737     req = fopen(reqfn, "r");
   738     resp = stdout;
   739     while (fgets(buf, sizeof buf, req) != NULL) {
   740         /* a comment or blank line */
   741         if (buf[0] == '#' || buf[0] == '\n') {
   742             fputs(buf, resp);
   743             continue;
   744         }
   745         /* [ENCRYPT] or [DECRYPT] */
   746         if (buf[0] == '[') {
   747             if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
   748                 crypt = ENCRYPT;
   749             } else {
   750                 crypt = DECRYPT;
   751            }
   752            fputs(buf, resp);
   753            continue;
   754         }
   755         /* NumKeys */
   756         if (strncmp(&buf[0], "NumKeys", 7) == 0) {
   757             i = 7;
   758             while (isspace(buf[i]) || buf[i] == '=') {
   759                 i++;
   760             }
   761             numKeys = atoi(&buf[i]);
   762             continue;
   763         }
   764         /* KEY1 = ... */
   765         if (strncmp(buf, "KEY1", 4) == 0) {
   766             i = 4;
   767             while (isspace(buf[i]) || buf[i] == '=') {
   768                 i++;
   769             }
   770             for (j=0; isxdigit(buf[i]); i+=2,j++) {
   771                 hex_to_byteval(&buf[i], &key[j]);
   772             }
   773             continue;
   774         }
   775         /* KEY2 = ... */
   776         if (strncmp(buf, "KEY2", 4) == 0) {
   777             i = 4;
   778             while (isspace(buf[i]) || buf[i] == '=') {
   779                 i++;
   780             }
   781             for (j=8; isxdigit(buf[i]); i+=2,j++) {
   782                 hex_to_byteval(&buf[i], &key[j]);
   783             }
   784             continue;
   785         }
   786         /* KEY3 = ... */
   787         if (strncmp(buf, "KEY3", 4) == 0) {
   788             i = 4;
   789             while (isspace(buf[i]) || buf[i] == '=') {
   790                 i++;
   791             }
   792             for (j=16; isxdigit(buf[i]); i+=2,j++) {
   793                 hex_to_byteval(&buf[i], &key[j]);
   794             }
   795             continue;
   796         }
   798         /* IV = ... */
   799         if (strncmp(buf, "IV", 2) == 0) {
   800             i = 2;
   801             while (isspace(buf[i]) || buf[i] == '=') {
   802                 i++;
   803             }
   804             for (j=0; j<sizeof iv; i+=2,j++) {
   805                 hex_to_byteval(&buf[i], &iv[j]);
   806             }
   807             continue;
   808         }
   810        /* PLAINTEXT = ... */
   811        if (strncmp(buf, "PLAINTEXT", 9) == 0) {
   813             /* sanity check */
   814             if (crypt != ENCRYPT) {
   815                 goto loser;
   816             }
   817             /* PT[0] = PT */
   818             i = 9;
   819             while (isspace(buf[i]) || buf[i] == '=') {
   820                 i++;
   821             }
   822             for (j=0; j<sizeof plaintext; i+=2,j++) {
   823                 hex_to_byteval(&buf[i], &plaintext[j]);
   824             }                                     
   826             /* do the Monte Carlo test */
   827             if (mode==NSS_DES_EDE3) {
   828                 tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, plaintext, sizeof plaintext, NULL, resp);
   829             } else {
   830                 tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, plaintext, sizeof plaintext, iv, resp);
   831             }
   832             continue;
   833         }
   834         /* CIPHERTEXT = ... */
   835         if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
   836             /* sanity check */
   837             if (crypt != DECRYPT) {
   838                 goto loser;
   839             }
   840             /* CT[0] = CT */
   841             i = 10;
   842             while (isspace(buf[i]) || buf[i] == '=') {
   843                 i++;
   844             }
   845             for (j=0; isxdigit(buf[i]); i+=2,j++) {
   846                 hex_to_byteval(&buf[i], &ciphertext[j]);
   847             }
   849             /* do the Monte Carlo test */
   850             if (mode==NSS_DES_EDE3) {
   851                 tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, ciphertext, sizeof ciphertext, NULL, resp); 
   852             } else {
   853                 tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, ciphertext, sizeof ciphertext, iv, resp); 
   854             }
   855             continue;
   856         }
   857     }
   859 loser:
   860     fclose(req);
   861 }
   864 SECStatus
   865 aes_encrypt_buf(
   866     int mode,
   867     const unsigned char *key, unsigned int keysize,
   868     const unsigned char *iv,
   869     unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
   870     const unsigned char *input, unsigned int inputlen)
   871 {
   872     SECStatus rv = SECFailure;
   873     AESContext *cx;
   874     unsigned char doublecheck[10*16];  /* 1 to 10 blocks */
   875     unsigned int doublechecklen = 0;
   877     cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
   878     if (cx == NULL) {
   879 	goto loser;
   880     }
   881     rv = AES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
   882     if (rv != SECSuccess) {
   883 	goto loser;
   884     }
   885     if (*outputlen != inputlen) {
   886 	goto loser;
   887     }
   888     AES_DestroyContext(cx, PR_TRUE);
   889     cx = NULL;
   891     /*
   892      * Doublecheck our result by decrypting the ciphertext and
   893      * compare the output with the input plaintext.
   894      */
   895     cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
   896     if (cx == NULL) {
   897 	goto loser;
   898     }
   899     rv = AES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
   900 	output, *outputlen);
   901     if (rv != SECSuccess) {
   902 	goto loser;
   903     }
   904     if (doublechecklen != *outputlen) {
   905 	goto loser;
   906     }
   907     AES_DestroyContext(cx, PR_TRUE);
   908     cx = NULL;
   909     if (memcmp(doublecheck, input, inputlen) != 0) {
   910 	goto loser;
   911     }
   912     rv = SECSuccess;
   914 loser:
   915     if (cx != NULL) {
   916 	AES_DestroyContext(cx, PR_TRUE);
   917     }
   918     return rv;
   919 }
   921 SECStatus
   922 aes_decrypt_buf(
   923     int mode,
   924     const unsigned char *key, unsigned int keysize,
   925     const unsigned char *iv,
   926     unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
   927     const unsigned char *input, unsigned int inputlen)
   928 {
   929     SECStatus rv = SECFailure;
   930     AESContext *cx;
   931     unsigned char doublecheck[10*16];  /* 1 to 10 blocks */
   932     unsigned int doublechecklen = 0;
   934     cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
   935     if (cx == NULL) {
   936 	goto loser;
   937     }
   938     rv = AES_Decrypt(cx, output, outputlen, maxoutputlen,
   939 	input, inputlen);
   940     if (rv != SECSuccess) {
   941 	goto loser;
   942     }
   943     if (*outputlen != inputlen) {
   944 	goto loser;
   945     }
   946     AES_DestroyContext(cx, PR_TRUE);
   947     cx = NULL;
   949     /*
   950      * Doublecheck our result by encrypting the plaintext and
   951      * compare the output with the input ciphertext.
   952      */
   953     cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
   954     if (cx == NULL) {
   955 	goto loser;
   956     }
   957     rv = AES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
   958 	output, *outputlen);
   959     if (rv != SECSuccess) {
   960 	goto loser;
   961     }
   962     if (doublechecklen != *outputlen) {
   963 	goto loser;
   964     }
   965     AES_DestroyContext(cx, PR_TRUE);
   966     cx = NULL;
   967     if (memcmp(doublecheck, input, inputlen) != 0) {
   968 	goto loser;
   969     }
   970     rv = SECSuccess;
   972 loser:
   973     if (cx != NULL) {
   974 	AES_DestroyContext(cx, PR_TRUE);
   975     }
   976     return rv;
   977 }
   979 /*
   980  * Perform the AES Known Answer Test (KAT) or Multi-block Message
   981  * Test (MMT) in ECB or CBC mode.  The KAT (there are four types)
   982  * and MMT have the same structure: given the key and IV (CBC mode
   983  * only), encrypt the given plaintext or decrypt the given ciphertext.
   984  * So we can handle them the same way.
   985  *
   986  * reqfn is the pathname of the REQUEST file.
   987  *
   988  * The output RESPONSE file is written to stdout.
   989  */
   990 void
   991 aes_kat_mmt(char *reqfn)
   992 {
   993     char buf[512];      /* holds one line from the input REQUEST file.
   994                          * needs to be large enough to hold the longest
   995                          * line "CIPHERTEXT = <320 hex digits>\n".
   996                          */
   997     FILE *aesreq;       /* input stream from the REQUEST file */
   998     FILE *aesresp;      /* output stream to the RESPONSE file */
   999     int i, j;
  1000     int mode;           /* NSS_AES (ECB) or NSS_AES_CBC */
  1001     int encrypt = 0;    /* 1 means encrypt, 0 means decrypt */
  1002     unsigned char key[32];              /* 128, 192, or 256 bits */
  1003     unsigned int keysize;
  1004     unsigned char iv[16];		/* for all modes except ECB */
  1005     unsigned char plaintext[10*16];     /* 1 to 10 blocks */
  1006     unsigned int plaintextlen;
  1007     unsigned char ciphertext[10*16];    /* 1 to 10 blocks */
  1008     unsigned int ciphertextlen;
  1009     SECStatus rv;
  1011     aesreq = fopen(reqfn, "r");
  1012     aesresp = stdout;
  1013     while (fgets(buf, sizeof buf, aesreq) != NULL) {
  1014 	/* a comment or blank line */
  1015 	if (buf[0] == '#' || buf[0] == '\n') {
  1016 	    fputs(buf, aesresp);
  1017 	    continue;
  1019 	/* [ENCRYPT] or [DECRYPT] */
  1020 	if (buf[0] == '[') {
  1021 	    if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
  1022 		encrypt = 1;
  1023 	    } else {
  1024 		encrypt = 0;
  1026 	    fputs(buf, aesresp);
  1027 	    continue;
  1029 	/* "COUNT = x" begins a new data set */
  1030 	if (strncmp(buf, "COUNT", 5) == 0) {
  1031 	    mode = NSS_AES;
  1032 	    /* zeroize the variables for the test with this data set */
  1033 	    memset(key, 0, sizeof key);
  1034 	    keysize = 0;
  1035 	    memset(iv, 0, sizeof iv);
  1036 	    memset(plaintext, 0, sizeof plaintext);
  1037 	    plaintextlen = 0;
  1038 	    memset(ciphertext, 0, sizeof ciphertext);
  1039 	    ciphertextlen = 0;
  1040 	    fputs(buf, aesresp);
  1041 	    continue;
  1043 	/* KEY = ... */
  1044 	if (strncmp(buf, "KEY", 3) == 0) {
  1045 	    i = 3;
  1046 	    while (isspace(buf[i]) || buf[i] == '=') {
  1047 		i++;
  1049 	    for (j=0; isxdigit(buf[i]); i+=2,j++) {
  1050 		hex_to_byteval(&buf[i], &key[j]);
  1052 	    keysize = j;
  1053 	    fputs(buf, aesresp);
  1054 	    continue;
  1056 	/* IV = ... */
  1057 	if (strncmp(buf, "IV", 2) == 0) {
  1058 	    mode = NSS_AES_CBC;
  1059 	    i = 2;
  1060 	    while (isspace(buf[i]) || buf[i] == '=') {
  1061 		i++;
  1063 	    for (j=0; j<sizeof iv; i+=2,j++) {
  1064 		hex_to_byteval(&buf[i], &iv[j]);
  1066 	    fputs(buf, aesresp);
  1067 	    continue;
  1069 	/* PLAINTEXT = ... */
  1070 	if (strncmp(buf, "PLAINTEXT", 9) == 0) {
  1071 	    /* sanity check */
  1072 	    if (!encrypt) {
  1073 		goto loser;
  1076 	    i = 9;
  1077 	    while (isspace(buf[i]) || buf[i] == '=') {
  1078 		i++;
  1080 	    for (j=0; isxdigit(buf[i]); i+=2,j++) {
  1081 		hex_to_byteval(&buf[i], &plaintext[j]);
  1083 	    plaintextlen = j;
  1085 	    rv = aes_encrypt_buf(mode, key, keysize,
  1086 		(mode == NSS_AES) ? NULL : iv,
  1087 		ciphertext, &ciphertextlen, sizeof ciphertext,
  1088 		plaintext, plaintextlen);
  1089 	    if (rv != SECSuccess) {
  1090 		goto loser;
  1093 	    fputs(buf, aesresp);
  1094 	    fputs("CIPHERTEXT = ", aesresp);
  1095 	    to_hex_str(buf, ciphertext, ciphertextlen);
  1096 	    fputs(buf, aesresp);
  1097 	    fputc('\n', aesresp);
  1098 	    continue;
  1100 	/* CIPHERTEXT = ... */
  1101 	if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
  1102 	    /* sanity check */
  1103 	    if (encrypt) {
  1104 		goto loser;
  1107 	    i = 10;
  1108 	    while (isspace(buf[i]) || buf[i] == '=') {
  1109 		i++;
  1111 	    for (j=0; isxdigit(buf[i]); i+=2,j++) {
  1112 		hex_to_byteval(&buf[i], &ciphertext[j]);
  1114 	    ciphertextlen = j;
  1116 	    rv = aes_decrypt_buf(mode, key, keysize,
  1117 		(mode == NSS_AES) ? NULL : iv,
  1118 		plaintext, &plaintextlen, sizeof plaintext,
  1119 		ciphertext, ciphertextlen);
  1120 	    if (rv != SECSuccess) {
  1121 		goto loser;
  1124 	    fputs(buf, aesresp);
  1125 	    fputs("PLAINTEXT = ", aesresp);
  1126 	    to_hex_str(buf, plaintext, plaintextlen);
  1127 	    fputs(buf, aesresp);
  1128 	    fputc('\n', aesresp);
  1129 	    continue;
  1132 loser:
  1133     fclose(aesreq);
  1136 /*
  1137  * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo
  1138  * Test (MCT) in ECB and CBC modes.
  1139  */
  1140 void
  1141 aes_mct_next_key(unsigned char *key, unsigned int keysize,
  1142     const unsigned char *ciphertext_1, const unsigned char *ciphertext)
  1144     int k;
  1146     switch (keysize) {
  1147     case 16:  /* 128-bit key */
  1148 	/* Key[i+1] = Key[i] xor CT[j] */
  1149 	for (k=0; k<16; k++) {
  1150 	    key[k] ^= ciphertext[k];
  1152 	break;
  1153     case 24:  /* 192-bit key */
  1154 	/*
  1155 	 * Key[i+1] = Key[i] xor (last 64-bits of
  1156 	 *            CT[j-1] || CT[j])
  1157 	 */
  1158 	for (k=0; k<8; k++) {
  1159 	    key[k] ^= ciphertext_1[k+8];
  1161 	for (k=8; k<24; k++) {
  1162 	    key[k] ^= ciphertext[k-8];
  1164 	break;
  1165     case 32:  /* 256-bit key */
  1166 	/* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */
  1167 	for (k=0; k<16; k++) {
  1168 	    key[k] ^= ciphertext_1[k];
  1170 	for (k=16; k<32; k++) {
  1171 	    key[k] ^= ciphertext[k-16];
  1173 	break;
  1177 /*
  1178  * Perform the AES Monte Carlo Test (MCT) in ECB mode.  MCT exercises
  1179  * our AES code in streaming mode because the plaintext or ciphertext
  1180  * is generated block by block as we go, so we can't collect all the
  1181  * plaintext or ciphertext in one buffer and encrypt or decrypt it in
  1182  * one shot.
  1184  * reqfn is the pathname of the input REQUEST file.
  1186  * The output RESPONSE file is written to stdout.
  1187  */
  1188 void
  1189 aes_ecb_mct(char *reqfn)
  1191     char buf[80];       /* holds one line from the input REQUEST file.
  1192                          * needs to be large enough to hold the longest
  1193                          * line "KEY = <64 hex digits>\n".
  1194                          */
  1195     FILE *aesreq;       /* input stream from the REQUEST file */
  1196     FILE *aesresp;      /* output stream to the RESPONSE file */
  1197     int i, j;
  1198     int encrypt = 0;    /* 1 means encrypt, 0 means decrypt */
  1199     unsigned char key[32];              /* 128, 192, or 256 bits */
  1200     unsigned int keysize;
  1201     unsigned char plaintext[16];        /* PT[j] */
  1202     unsigned char plaintext_1[16];      /* PT[j-1] */
  1203     unsigned char ciphertext[16];       /* CT[j] */
  1204     unsigned char ciphertext_1[16];     /* CT[j-1] */
  1205     unsigned char doublecheck[16];
  1206     unsigned int outputlen;
  1207     AESContext *cx = NULL;	/* the operation being tested */
  1208     AESContext *cx2 = NULL;     /* the inverse operation done in parallel
  1209                                  * to doublecheck our result.
  1210                                  */
  1211     SECStatus rv;
  1213     aesreq = fopen(reqfn, "r");
  1214     aesresp = stdout;
  1215     while (fgets(buf, sizeof buf, aesreq) != NULL) {
  1216 	/* a comment or blank line */
  1217 	if (buf[0] == '#' || buf[0] == '\n') {
  1218 	    fputs(buf, aesresp);
  1219 	    continue;
  1221 	/* [ENCRYPT] or [DECRYPT] */
  1222 	if (buf[0] == '[') {
  1223 	    if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
  1224 		encrypt = 1;
  1225 	    } else {
  1226 		encrypt = 0;
  1228 	    fputs(buf, aesresp);
  1229 	    continue;
  1231 	/* "COUNT = x" begins a new data set */
  1232 	if (strncmp(buf, "COUNT", 5) == 0) {
  1233 	    /* zeroize the variables for the test with this data set */
  1234 	    memset(key, 0, sizeof key);
  1235 	    keysize = 0;
  1236 	    memset(plaintext, 0, sizeof plaintext);
  1237 	    memset(ciphertext, 0, sizeof ciphertext);
  1238 	    continue;
  1240 	/* KEY = ... */
  1241 	if (strncmp(buf, "KEY", 3) == 0) {
  1242 	    /* Key[0] = Key */
  1243 	    i = 3;
  1244 	    while (isspace(buf[i]) || buf[i] == '=') {
  1245 		i++;
  1247 	    for (j=0; isxdigit(buf[i]); i+=2,j++) {
  1248 		hex_to_byteval(&buf[i], &key[j]);
  1250 	    keysize = j;
  1251 	    continue;
  1253 	/* PLAINTEXT = ... */
  1254 	if (strncmp(buf, "PLAINTEXT", 9) == 0) {
  1255 	    /* sanity check */
  1256 	    if (!encrypt) {
  1257 		goto loser;
  1259 	    /* PT[0] = PT */
  1260 	    i = 9;
  1261 	    while (isspace(buf[i]) || buf[i] == '=') {
  1262 		i++;
  1264 	    for (j=0; j<sizeof plaintext; i+=2,j++) {
  1265 		hex_to_byteval(&buf[i], &plaintext[j]);
  1268 	    for (i=0; i<100; i++) {
  1269 		sprintf(buf, "COUNT = %d\n", i);
  1270 	        fputs(buf, aesresp);
  1271 		/* Output Key[i] */
  1272 		fputs("KEY = ", aesresp);
  1273 		to_hex_str(buf, key, keysize);
  1274 		fputs(buf, aesresp);
  1275 		fputc('\n', aesresp);
  1276 		/* Output PT[0] */
  1277 		fputs("PLAINTEXT = ", aesresp);
  1278 		to_hex_str(buf, plaintext, sizeof plaintext);
  1279 		fputs(buf, aesresp);
  1280 		fputc('\n', aesresp);
  1282 		cx = AES_CreateContext(key, NULL, NSS_AES,
  1283 		    PR_TRUE, keysize, 16);
  1284 		if (cx == NULL) {
  1285 		    goto loser;
  1287 		/*
  1288 		 * doublecheck our result by decrypting the result
  1289 		 * and comparing the output with the plaintext.
  1290 		 */
  1291 		cx2 = AES_CreateContext(key, NULL, NSS_AES,
  1292 		    PR_FALSE, keysize, 16);
  1293 		if (cx2 == NULL) {
  1294 		    goto loser;
  1296 		for (j=0; j<1000; j++) {
  1297 		    /* Save CT[j-1] */
  1298 		    memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
  1300 		    /* CT[j] = AES(Key[i], PT[j]) */
  1301 		    outputlen = 0;
  1302 		    rv = AES_Encrypt(cx,
  1303 			ciphertext, &outputlen, sizeof ciphertext,
  1304 			plaintext, sizeof plaintext);
  1305 		    if (rv != SECSuccess) {
  1306 			goto loser;
  1308 		    if (outputlen != sizeof plaintext) {
  1309 			goto loser;
  1312 		    /* doublecheck our result */
  1313 		    outputlen = 0;
  1314 		    rv = AES_Decrypt(cx2,
  1315 			doublecheck, &outputlen, sizeof doublecheck,
  1316 			ciphertext, sizeof ciphertext);
  1317 		    if (rv != SECSuccess) {
  1318 			goto loser;
  1320 		    if (outputlen != sizeof ciphertext) {
  1321 			goto loser;
  1323 		    if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
  1324 			goto loser;
  1327 		    /* PT[j+1] = CT[j] */
  1328 		    memcpy(plaintext, ciphertext, sizeof plaintext);
  1330 		AES_DestroyContext(cx, PR_TRUE);
  1331 		cx = NULL;
  1332 		AES_DestroyContext(cx2, PR_TRUE);
  1333 		cx2 = NULL;
  1335 		/* Output CT[j] */
  1336 		fputs("CIPHERTEXT = ", aesresp);
  1337 		to_hex_str(buf, ciphertext, sizeof ciphertext);
  1338 		fputs(buf, aesresp);
  1339 		fputc('\n', aesresp);
  1341 		/* Key[i+1] = Key[i] xor ... */
  1342 		aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
  1343 		/* PT[0] = CT[j] */
  1344 		/* done at the end of the for(j) loop */
  1346 		fputc('\n', aesresp);
  1349 	    continue;
  1351 	/* CIPHERTEXT = ... */
  1352 	if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
  1353 	    /* sanity check */
  1354 	    if (encrypt) {
  1355 		goto loser;
  1357 	    /* CT[0] = CT */
  1358 	    i = 10;
  1359 	    while (isspace(buf[i]) || buf[i] == '=') {
  1360 		i++;
  1362 	    for (j=0; isxdigit(buf[i]); i+=2,j++) {
  1363 		hex_to_byteval(&buf[i], &ciphertext[j]);
  1366 	    for (i=0; i<100; i++) {
  1367 		sprintf(buf, "COUNT = %d\n", i);
  1368 	        fputs(buf, aesresp);
  1369 		/* Output Key[i] */
  1370 		fputs("KEY = ", aesresp);
  1371 		to_hex_str(buf, key, keysize);
  1372 		fputs(buf, aesresp);
  1373 		fputc('\n', aesresp);
  1374 		/* Output CT[0] */
  1375 		fputs("CIPHERTEXT = ", aesresp);
  1376 		to_hex_str(buf, ciphertext, sizeof ciphertext);
  1377 		fputs(buf, aesresp);
  1378 		fputc('\n', aesresp);
  1380 		cx = AES_CreateContext(key, NULL, NSS_AES,
  1381 		    PR_FALSE, keysize, 16);
  1382 		if (cx == NULL) {
  1383 		    goto loser;
  1385 		/*
  1386 		 * doublecheck our result by encrypting the result
  1387 		 * and comparing the output with the ciphertext.
  1388 		 */
  1389 		cx2 = AES_CreateContext(key, NULL, NSS_AES,
  1390 		    PR_TRUE, keysize, 16);
  1391 		if (cx2 == NULL) {
  1392 		    goto loser;
  1394 		for (j=0; j<1000; j++) {
  1395 		    /* Save PT[j-1] */
  1396 		    memcpy(plaintext_1, plaintext, sizeof plaintext);
  1398 		    /* PT[j] = AES(Key[i], CT[j]) */
  1399 		    outputlen = 0;
  1400 		    rv = AES_Decrypt(cx,
  1401 			plaintext, &outputlen, sizeof plaintext,
  1402 			ciphertext, sizeof ciphertext);
  1403 		    if (rv != SECSuccess) {
  1404 			goto loser;
  1406 		    if (outputlen != sizeof ciphertext) {
  1407 			goto loser;
  1410 		    /* doublecheck our result */
  1411 		    outputlen = 0;
  1412 		    rv = AES_Encrypt(cx2,
  1413 			doublecheck, &outputlen, sizeof doublecheck,
  1414 			plaintext, sizeof plaintext);
  1415 		    if (rv != SECSuccess) {
  1416 			goto loser;
  1418 		    if (outputlen != sizeof plaintext) {
  1419 			goto loser;
  1421 		    if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
  1422 			goto loser;
  1425 		    /* CT[j+1] = PT[j] */
  1426 		    memcpy(ciphertext, plaintext, sizeof ciphertext);
  1428 		AES_DestroyContext(cx, PR_TRUE);
  1429 		cx = NULL;
  1430 		AES_DestroyContext(cx2, PR_TRUE);
  1431 		cx2 = NULL;
  1433 		/* Output PT[j] */
  1434 		fputs("PLAINTEXT = ", aesresp);
  1435 		to_hex_str(buf, plaintext, sizeof plaintext);
  1436 		fputs(buf, aesresp);
  1437 		fputc('\n', aesresp);
  1439 		/* Key[i+1] = Key[i] xor ... */
  1440 		aes_mct_next_key(key, keysize, plaintext_1, plaintext);
  1441 		/* CT[0] = PT[j] */
  1442 		/* done at the end of the for(j) loop */
  1444 		fputc('\n', aesresp);
  1447 	    continue;
  1450 loser:
  1451     if (cx != NULL) {
  1452 	AES_DestroyContext(cx, PR_TRUE);
  1454     if (cx2 != NULL) {
  1455 	AES_DestroyContext(cx2, PR_TRUE);
  1457     fclose(aesreq);
  1460 /*
  1461  * Perform the AES Monte Carlo Test (MCT) in CBC mode.  MCT exercises
  1462  * our AES code in streaming mode because the plaintext or ciphertext
  1463  * is generated block by block as we go, so we can't collect all the
  1464  * plaintext or ciphertext in one buffer and encrypt or decrypt it in
  1465  * one shot.
  1467  * reqfn is the pathname of the input REQUEST file.
  1469  * The output RESPONSE file is written to stdout.
  1470  */
  1471 void
  1472 aes_cbc_mct(char *reqfn)
  1474     char buf[80];       /* holds one line from the input REQUEST file.
  1475                          * needs to be large enough to hold the longest
  1476                          * line "KEY = <64 hex digits>\n".
  1477                          */
  1478     FILE *aesreq;       /* input stream from the REQUEST file */
  1479     FILE *aesresp;      /* output stream to the RESPONSE file */
  1480     int i, j;
  1481     int encrypt = 0;    /* 1 means encrypt, 0 means decrypt */
  1482     unsigned char key[32];              /* 128, 192, or 256 bits */
  1483     unsigned int keysize;
  1484     unsigned char iv[16];
  1485     unsigned char plaintext[16];        /* PT[j] */
  1486     unsigned char plaintext_1[16];      /* PT[j-1] */
  1487     unsigned char ciphertext[16];       /* CT[j] */
  1488     unsigned char ciphertext_1[16];     /* CT[j-1] */
  1489     unsigned char doublecheck[16];
  1490     unsigned int outputlen;
  1491     AESContext *cx = NULL;	/* the operation being tested */
  1492     AESContext *cx2 = NULL;     /* the inverse operation done in parallel
  1493                                  * to doublecheck our result.
  1494                                  */
  1495     SECStatus rv;
  1497     aesreq = fopen(reqfn, "r");
  1498     aesresp = stdout;
  1499     while (fgets(buf, sizeof buf, aesreq) != NULL) {
  1500 	/* a comment or blank line */
  1501 	if (buf[0] == '#' || buf[0] == '\n') {
  1502 	    fputs(buf, aesresp);
  1503 	    continue;
  1505 	/* [ENCRYPT] or [DECRYPT] */
  1506 	if (buf[0] == '[') {
  1507 	    if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
  1508 		encrypt = 1;
  1509 	    } else {
  1510 		encrypt = 0;
  1512 	    fputs(buf, aesresp);
  1513 	    continue;
  1515 	/* "COUNT = x" begins a new data set */
  1516 	if (strncmp(buf, "COUNT", 5) == 0) {
  1517 	    /* zeroize the variables for the test with this data set */
  1518 	    memset(key, 0, sizeof key);
  1519 	    keysize = 0;
  1520 	    memset(iv, 0, sizeof iv);
  1521 	    memset(plaintext, 0, sizeof plaintext);
  1522 	    memset(ciphertext, 0, sizeof ciphertext);
  1523 	    continue;
  1525 	/* KEY = ... */
  1526 	if (strncmp(buf, "KEY", 3) == 0) {
  1527 	    /* Key[0] = Key */
  1528 	    i = 3;
  1529 	    while (isspace(buf[i]) || buf[i] == '=') {
  1530 		i++;
  1532 	    for (j=0; isxdigit(buf[i]); i+=2,j++) {
  1533 		hex_to_byteval(&buf[i], &key[j]);
  1535 	    keysize = j;
  1536 	    continue;
  1538 	/* IV = ... */
  1539 	if (strncmp(buf, "IV", 2) == 0) {
  1540 	    /* IV[0] = IV */
  1541 	    i = 2;
  1542 	    while (isspace(buf[i]) || buf[i] == '=') {
  1543 		i++;
  1545 	    for (j=0; j<sizeof iv; i+=2,j++) {
  1546 		hex_to_byteval(&buf[i], &iv[j]);
  1548 	    continue;
  1550 	/* PLAINTEXT = ... */
  1551 	if (strncmp(buf, "PLAINTEXT", 9) == 0) {
  1552 	    /* sanity check */
  1553 	    if (!encrypt) {
  1554 		goto loser;
  1556 	    /* PT[0] = PT */
  1557 	    i = 9;
  1558 	    while (isspace(buf[i]) || buf[i] == '=') {
  1559 		i++;
  1561 	    for (j=0; j<sizeof plaintext; i+=2,j++) {
  1562 		hex_to_byteval(&buf[i], &plaintext[j]);
  1565 	    for (i=0; i<100; i++) {
  1566 		sprintf(buf, "COUNT = %d\n", i);
  1567 	        fputs(buf, aesresp);
  1568 		/* Output Key[i] */
  1569 		fputs("KEY = ", aesresp);
  1570 		to_hex_str(buf, key, keysize);
  1571 		fputs(buf, aesresp);
  1572 		fputc('\n', aesresp);
  1573 		/* Output IV[i] */
  1574 		fputs("IV = ", aesresp);
  1575 		to_hex_str(buf, iv, sizeof iv);
  1576 		fputs(buf, aesresp);
  1577 		fputc('\n', aesresp);
  1578 		/* Output PT[0] */
  1579 		fputs("PLAINTEXT = ", aesresp);
  1580 		to_hex_str(buf, plaintext, sizeof plaintext);
  1581 		fputs(buf, aesresp);
  1582 		fputc('\n', aesresp);
  1584 		cx = AES_CreateContext(key, iv, NSS_AES_CBC,
  1585 		    PR_TRUE, keysize, 16);
  1586 		if (cx == NULL) {
  1587 		    goto loser;
  1589 		/*
  1590 		 * doublecheck our result by decrypting the result
  1591 		 * and comparing the output with the plaintext.
  1592 		 */
  1593 		cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
  1594 		    PR_FALSE, keysize, 16);
  1595 		if (cx2 == NULL) {
  1596 		    goto loser;
  1598 		/* CT[-1] = IV[i] */
  1599 		memcpy(ciphertext, iv, sizeof ciphertext);
  1600 		for (j=0; j<1000; j++) {
  1601 		    /* Save CT[j-1] */
  1602 		    memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
  1603 		    /*
  1604 		     * If ( j=0 )
  1605 		     *      CT[j] = AES(Key[i], IV[i], PT[j])
  1606 		     *      PT[j+1] = IV[i] (= CT[j-1])
  1607 		     * Else
  1608 		     *      CT[j] = AES(Key[i], PT[j])
  1609 		     *      PT[j+1] = CT[j-1]
  1610 		     */
  1611 		    outputlen = 0;
  1612 		    rv = AES_Encrypt(cx,
  1613 			ciphertext, &outputlen, sizeof ciphertext,
  1614 			plaintext, sizeof plaintext);
  1615 		    if (rv != SECSuccess) {
  1616 			goto loser;
  1618 		    if (outputlen != sizeof plaintext) {
  1619 			goto loser;
  1622 		    /* doublecheck our result */
  1623 		    outputlen = 0;
  1624 		    rv = AES_Decrypt(cx2,
  1625 			doublecheck, &outputlen, sizeof doublecheck,
  1626 			ciphertext, sizeof ciphertext);
  1627 		    if (rv != SECSuccess) {
  1628 			goto loser;
  1630 		    if (outputlen != sizeof ciphertext) {
  1631 			goto loser;
  1633 		    if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
  1634 			goto loser;
  1637 		    memcpy(plaintext, ciphertext_1, sizeof plaintext);
  1639 		AES_DestroyContext(cx, PR_TRUE);
  1640 		cx = NULL;
  1641 		AES_DestroyContext(cx2, PR_TRUE);
  1642 		cx2 = NULL;
  1644 		/* Output CT[j] */
  1645 		fputs("CIPHERTEXT = ", aesresp);
  1646 		to_hex_str(buf, ciphertext, sizeof ciphertext);
  1647 		fputs(buf, aesresp);
  1648 		fputc('\n', aesresp);
  1650 		/* Key[i+1] = Key[i] xor ... */
  1651 		aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
  1652 		/* IV[i+1] = CT[j] */
  1653 		memcpy(iv, ciphertext, sizeof iv);
  1654 		/* PT[0] = CT[j-1] */
  1655 		/* done at the end of the for(j) loop */
  1657 		fputc('\n', aesresp);
  1660 	    continue;
  1662 	/* CIPHERTEXT = ... */
  1663 	if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
  1664 	    /* sanity check */
  1665 	    if (encrypt) {
  1666 		goto loser;
  1668 	    /* CT[0] = CT */
  1669 	    i = 10;
  1670 	    while (isspace(buf[i]) || buf[i] == '=') {
  1671 		i++;
  1673 	    for (j=0; isxdigit(buf[i]); i+=2,j++) {
  1674 		hex_to_byteval(&buf[i], &ciphertext[j]);
  1677 	    for (i=0; i<100; i++) {
  1678 		sprintf(buf, "COUNT = %d\n", i);
  1679 	        fputs(buf, aesresp);
  1680 		/* Output Key[i] */
  1681 		fputs("KEY = ", aesresp);
  1682 		to_hex_str(buf, key, keysize);
  1683 		fputs(buf, aesresp);
  1684 		fputc('\n', aesresp);
  1685 		/* Output IV[i] */
  1686 		fputs("IV = ", aesresp);
  1687 		to_hex_str(buf, iv, sizeof iv);
  1688 		fputs(buf, aesresp);
  1689 		fputc('\n', aesresp);
  1690 		/* Output CT[0] */
  1691 		fputs("CIPHERTEXT = ", aesresp);
  1692 		to_hex_str(buf, ciphertext, sizeof ciphertext);
  1693 		fputs(buf, aesresp);
  1694 		fputc('\n', aesresp);
  1696 		cx = AES_CreateContext(key, iv, NSS_AES_CBC,
  1697 		    PR_FALSE, keysize, 16);
  1698 		if (cx == NULL) {
  1699 		    goto loser;
  1701 		/*
  1702 		 * doublecheck our result by encrypting the result
  1703 		 * and comparing the output with the ciphertext.
  1704 		 */
  1705 		cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
  1706 		    PR_TRUE, keysize, 16);
  1707 		if (cx2 == NULL) {
  1708 		    goto loser;
  1710 		/* PT[-1] = IV[i] */
  1711 		memcpy(plaintext, iv, sizeof plaintext);
  1712 		for (j=0; j<1000; j++) {
  1713 		    /* Save PT[j-1] */
  1714 		    memcpy(plaintext_1, plaintext, sizeof plaintext);
  1715 		    /*
  1716 		     * If ( j=0 )
  1717 		     *      PT[j] = AES(Key[i], IV[i], CT[j])
  1718 		     *      CT[j+1] = IV[i] (= PT[j-1])
  1719 		     * Else
  1720 		     *      PT[j] = AES(Key[i], CT[j])
  1721 		     *      CT[j+1] = PT[j-1]
  1722 		     */
  1723 		    outputlen = 0;
  1724 		    rv = AES_Decrypt(cx,
  1725 			plaintext, &outputlen, sizeof plaintext,
  1726 			ciphertext, sizeof ciphertext);
  1727 		    if (rv != SECSuccess) {
  1728 			goto loser;
  1730 		    if (outputlen != sizeof ciphertext) {
  1731 			goto loser;
  1734 		    /* doublecheck our result */
  1735 		    outputlen = 0;
  1736 		    rv = AES_Encrypt(cx2,
  1737 			doublecheck, &outputlen, sizeof doublecheck,
  1738 			plaintext, sizeof plaintext);
  1739 		    if (rv != SECSuccess) {
  1740 			goto loser;
  1742 		    if (outputlen != sizeof plaintext) {
  1743 			goto loser;
  1745 		    if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
  1746 			goto loser;
  1749 		    memcpy(ciphertext, plaintext_1, sizeof ciphertext);
  1751 		AES_DestroyContext(cx, PR_TRUE);
  1752 		cx = NULL;
  1753 		AES_DestroyContext(cx2, PR_TRUE);
  1754 		cx2 = NULL;
  1756 		/* Output PT[j] */
  1757 		fputs("PLAINTEXT = ", aesresp);
  1758 		to_hex_str(buf, plaintext, sizeof plaintext);
  1759 		fputs(buf, aesresp);
  1760 		fputc('\n', aesresp);
  1762 		/* Key[i+1] = Key[i] xor ... */
  1763 		aes_mct_next_key(key, keysize, plaintext_1, plaintext);
  1764 		/* IV[i+1] = PT[j] */
  1765 		memcpy(iv, plaintext, sizeof iv);
  1766 		/* CT[0] = PT[j-1] */
  1767 		/* done at the end of the for(j) loop */
  1769 		fputc('\n', aesresp);
  1772 	    continue;
  1775 loser:
  1776     if (cx != NULL) {
  1777 	AES_DestroyContext(cx, PR_TRUE);
  1779     if (cx2 != NULL) {
  1780 	AES_DestroyContext(cx2, PR_TRUE);
  1782     fclose(aesreq);
  1785 void write_compact_string(FILE *out, unsigned char *hash, unsigned int len)
  1787     unsigned int i;
  1788     int j, count = 0, last = -1, z = 0;
  1789     long start = ftell(out);
  1790     for (i=0; i<len; i++) {
  1791 	for (j=7; j>=0; j--) {
  1792 	    if (last < 0) {
  1793 		last = (hash[i] & (1 << j)) ? 1 : 0;
  1794 		fprintf(out, "%d ", last);
  1795 		count = 1;
  1796 	    } else if (hash[i] & (1 << j)) {
  1797 		if (last) {
  1798 		    count++; 
  1799 		} else { 
  1800 		    last = 0;
  1801 		    fprintf(out, "%d ", count);
  1802 		    count = 1;
  1803 		    z++;
  1805 	    } else {
  1806 		if (!last) {
  1807 		    count++; 
  1808 		} else { 
  1809 		    last = 1;
  1810 		    fprintf(out, "%d ", count);
  1811 		    count = 1;
  1812 		    z++;
  1817     fprintf(out, "^\n");
  1818     fseek(out, start, SEEK_SET);
  1819     fprintf(out, "%d ", z);
  1820     fseek(out, 0, SEEK_END);
  1823 int get_next_line(FILE *req, char *key, char *val, FILE *rsp)
  1825     int ignore = 0;
  1826     char *writeto = key;
  1827     int w = 0;
  1828     int c;
  1829     while ((c = fgetc(req)) != EOF) {
  1830 	if (ignore) {
  1831 	    fprintf(rsp, "%c", c);
  1832 	    if (c == '\n') return ignore;
  1833 	} else if (c == '\n') {
  1834 	    break;
  1835 	} else if (c == '#') {
  1836 	    ignore = 1;
  1837 	    fprintf(rsp, "%c", c);
  1838 	} else if (c == '=') {
  1839 	    writeto[w] = '\0';
  1840 	    w = 0;
  1841 	    writeto = val;
  1842 	} else if (c == ' ' || c == '[' || c == ']') {
  1843 	    continue;
  1844 	} else {
  1845 	    writeto[w++] = c;
  1848     writeto[w] = '\0';
  1849     return (c == EOF) ? -1 : ignore;
  1852 #ifndef NSS_DISABLE_ECC
  1853 typedef struct curveNameTagPairStr {
  1854     char *curveName;
  1855     SECOidTag curveOidTag;
  1856 } CurveNameTagPair;
  1858 #define DEFAULT_CURVE_OID_TAG  SEC_OID_SECG_EC_SECP192R1
  1859 /* #define DEFAULT_CURVE_OID_TAG  SEC_OID_SECG_EC_SECP160R1 */
  1861 static CurveNameTagPair nameTagPair[] =
  1863   { "sect163k1", SEC_OID_SECG_EC_SECT163K1},
  1864   { "nistk163", SEC_OID_SECG_EC_SECT163K1},
  1865   { "sect163r1", SEC_OID_SECG_EC_SECT163R1},
  1866   { "sect163r2", SEC_OID_SECG_EC_SECT163R2},
  1867   { "nistb163", SEC_OID_SECG_EC_SECT163R2},
  1868   { "sect193r1", SEC_OID_SECG_EC_SECT193R1},
  1869   { "sect193r2", SEC_OID_SECG_EC_SECT193R2},
  1870   { "sect233k1", SEC_OID_SECG_EC_SECT233K1},
  1871   { "nistk233", SEC_OID_SECG_EC_SECT233K1},
  1872   { "sect233r1", SEC_OID_SECG_EC_SECT233R1},
  1873   { "nistb233", SEC_OID_SECG_EC_SECT233R1},
  1874   { "sect239k1", SEC_OID_SECG_EC_SECT239K1},
  1875   { "sect283k1", SEC_OID_SECG_EC_SECT283K1},
  1876   { "nistk283", SEC_OID_SECG_EC_SECT283K1},
  1877   { "sect283r1", SEC_OID_SECG_EC_SECT283R1},
  1878   { "nistb283", SEC_OID_SECG_EC_SECT283R1},
  1879   { "sect409k1", SEC_OID_SECG_EC_SECT409K1},
  1880   { "nistk409", SEC_OID_SECG_EC_SECT409K1},
  1881   { "sect409r1", SEC_OID_SECG_EC_SECT409R1},
  1882   { "nistb409", SEC_OID_SECG_EC_SECT409R1},
  1883   { "sect571k1", SEC_OID_SECG_EC_SECT571K1},
  1884   { "nistk571", SEC_OID_SECG_EC_SECT571K1},
  1885   { "sect571r1", SEC_OID_SECG_EC_SECT571R1},
  1886   { "nistb571", SEC_OID_SECG_EC_SECT571R1},
  1887   { "secp160k1", SEC_OID_SECG_EC_SECP160K1},
  1888   { "secp160r1", SEC_OID_SECG_EC_SECP160R1},
  1889   { "secp160r2", SEC_OID_SECG_EC_SECP160R2},
  1890   { "secp192k1", SEC_OID_SECG_EC_SECP192K1},
  1891   { "secp192r1", SEC_OID_SECG_EC_SECP192R1},
  1892   { "nistp192", SEC_OID_SECG_EC_SECP192R1},
  1893   { "secp224k1", SEC_OID_SECG_EC_SECP224K1},
  1894   { "secp224r1", SEC_OID_SECG_EC_SECP224R1},
  1895   { "nistp224", SEC_OID_SECG_EC_SECP224R1},
  1896   { "secp256k1", SEC_OID_SECG_EC_SECP256K1},
  1897   { "secp256r1", SEC_OID_SECG_EC_SECP256R1},
  1898   { "nistp256", SEC_OID_SECG_EC_SECP256R1},
  1899   { "secp384r1", SEC_OID_SECG_EC_SECP384R1},
  1900   { "nistp384", SEC_OID_SECG_EC_SECP384R1},
  1901   { "secp521r1", SEC_OID_SECG_EC_SECP521R1},
  1902   { "nistp521", SEC_OID_SECG_EC_SECP521R1},
  1904   { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
  1905   { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
  1906   { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
  1907   { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
  1908   { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
  1909   { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
  1911   { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
  1912   { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
  1913   { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
  1914   { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
  1915   { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
  1916   { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
  1917   { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
  1918   { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
  1919   { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
  1920   { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
  1921   { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
  1922   { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
  1923   { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
  1924   { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
  1925   { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
  1926   { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
  1927   { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
  1928   { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
  1929   { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
  1930   { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
  1932   { "secp112r1", SEC_OID_SECG_EC_SECP112R1},
  1933   { "secp112r2", SEC_OID_SECG_EC_SECP112R2},
  1934   { "secp128r1", SEC_OID_SECG_EC_SECP128R1},
  1935   { "secp128r2", SEC_OID_SECG_EC_SECP128R2},
  1937   { "sect113r1", SEC_OID_SECG_EC_SECT113R1},
  1938   { "sect113r2", SEC_OID_SECG_EC_SECT113R2},
  1939   { "sect131r1", SEC_OID_SECG_EC_SECT131R1},
  1940   { "sect131r2", SEC_OID_SECG_EC_SECT131R2},
  1941 };
  1943 static SECItem * 
  1944 getECParams(const char *curve)
  1946     SECItem *ecparams;
  1947     SECOidData *oidData = NULL;
  1948     SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
  1949     int i, numCurves;
  1951     if (curve != NULL) {
  1952         numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair);
  1953 	for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); 
  1954 	     i++) {
  1955 	    if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
  1956 	        curveOidTag = nameTagPair[i].curveOidTag;
  1960     /* Return NULL if curve name is not recognized */
  1961     if ((curveOidTag == SEC_OID_UNKNOWN) || 
  1962 	(oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
  1963         fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
  1964 	return NULL;
  1967     ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
  1969     /* 
  1970      * ecparams->data needs to contain the ASN encoding of an object ID (OID)
  1971      * representing the named curve. The actual OID is in 
  1972      * oidData->oid.data so we simply prepend 0x06 and OID length
  1973      */
  1974     ecparams->data[0] = SEC_ASN1_OBJECT_ID;
  1975     ecparams->data[1] = oidData->oid.len;
  1976     memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
  1978     return ecparams;
  1981 /*
  1982  * Perform the ECDSA Key Pair Generation Test.
  1984  * reqfn is the pathname of the REQUEST file.
  1986  * The output RESPONSE file is written to stdout.
  1987  */
  1988 void
  1989 ecdsa_keypair_test(char *reqfn)
  1991     char buf[256];      /* holds one line from the input REQUEST file
  1992                          * or to the output RESPONSE file.
  1993                          * needs to be large enough to hold the longest
  1994                          * line "Qx = <144 hex digits>\n".
  1995                          */
  1996     FILE *ecdsareq;     /* input stream from the REQUEST file */
  1997     FILE *ecdsaresp;    /* output stream to the RESPONSE file */
  1998     char curve[16];     /* "nistxddd" */
  1999     ECParams *ecparams;
  2000     int N;
  2001     int i;
  2002     unsigned int len;
  2004     ecdsareq = fopen(reqfn, "r");
  2005     ecdsaresp = stdout;
  2006     strcpy(curve, "nist");
  2007     while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
  2008 	/* a comment or blank line */
  2009 	if (buf[0] == '#' || buf[0] == '\n') {
  2010 	    fputs(buf, ecdsaresp);
  2011 	    continue;
  2013 	/* [X-ddd] */
  2014 	if (buf[0] == '[') {
  2015 	    const char *src;
  2016 	    char *dst;
  2017 	    SECItem *encodedparams;
  2019 	    src = &buf[1];
  2020 	    dst = &curve[4];
  2021 	    *dst++ = tolower(*src);
  2022 	    src += 2;  /* skip the hyphen */
  2023 	    *dst++ = *src++;
  2024 	    *dst++ = *src++;
  2025 	    *dst++ = *src++;
  2026 	    *dst = '\0';
  2027 	    encodedparams = getECParams(curve);
  2028 	    if (encodedparams == NULL) {
  2029 		goto loser;
  2031 	    if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
  2032 		goto loser;
  2034 	    SECITEM_FreeItem(encodedparams, PR_TRUE);
  2035 	    fputs(buf, ecdsaresp);
  2036 	    continue;
  2038 	/* N = x */
  2039 	if (buf[0] == 'N') {
  2040 	    if (sscanf(buf, "N = %d", &N) != 1) {
  2041 		goto loser;
  2043 	    for (i = 0; i < N; i++) {
  2044 		ECPrivateKey *ecpriv;
  2046 		if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
  2047 		    goto loser;
  2049 		fputs("d = ", ecdsaresp);
  2050 		to_hex_str(buf, ecpriv->privateValue.data,
  2051 			   ecpriv->privateValue.len);
  2052 		fputs(buf, ecdsaresp);
  2053 		fputc('\n', ecdsaresp);
  2054 		if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue)
  2055 		    != SECSuccess) {
  2056 		    goto loser;
  2058 		len = ecpriv->publicValue.len;
  2059 		if (len%2 == 0) {
  2060 		    goto loser;
  2062 		len = (len-1)/2;
  2063 		if (ecpriv->publicValue.data[0]
  2064 		    != EC_POINT_FORM_UNCOMPRESSED) {
  2065 		    goto loser;
  2067 		fputs("Qx = ", ecdsaresp);
  2068 		to_hex_str(buf, &ecpriv->publicValue.data[1], len);
  2069 		fputs(buf, ecdsaresp);
  2070 		fputc('\n', ecdsaresp);
  2071 		fputs("Qy = ", ecdsaresp);
  2072 		to_hex_str(buf, &ecpriv->publicValue.data[1+len], len);
  2073 		fputs(buf, ecdsaresp);
  2074 		fputc('\n', ecdsaresp);
  2075 		fputc('\n', ecdsaresp);
  2076 		PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
  2078 	    PORT_FreeArena(ecparams->arena, PR_FALSE);
  2079 	    continue;
  2082 loser:
  2083     fclose(ecdsareq);
  2086 /*
  2087  * Perform the ECDSA Public Key Validation Test.
  2089  * reqfn is the pathname of the REQUEST file.
  2091  * The output RESPONSE file is written to stdout.
  2092  */
  2093 void
  2094 ecdsa_pkv_test(char *reqfn)
  2096     char buf[256];      /* holds one line from the input REQUEST file.
  2097                          * needs to be large enough to hold the longest
  2098                          * line "Qx = <144 hex digits>\n".
  2099                          */
  2100     FILE *ecdsareq;     /* input stream from the REQUEST file */
  2101     FILE *ecdsaresp;    /* output stream to the RESPONSE file */
  2102     char curve[16];     /* "nistxddd" */
  2103     ECParams *ecparams = NULL;
  2104     SECItem pubkey;
  2105     unsigned int i;
  2106     unsigned int len;
  2107     PRBool keyvalid = PR_TRUE;
  2109     ecdsareq = fopen(reqfn, "r");
  2110     ecdsaresp = stdout;
  2111     strcpy(curve, "nist");
  2112     pubkey.data = NULL;
  2113     while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
  2114 	/* a comment or blank line */
  2115 	if (buf[0] == '#' || buf[0] == '\n') {
  2116 	    fputs(buf, ecdsaresp);
  2117 	    continue;
  2119 	/* [X-ddd] */
  2120 	if (buf[0] == '[') {
  2121 	    const char *src;
  2122 	    char *dst;
  2123 	    SECItem *encodedparams;
  2125 	    src = &buf[1];
  2126 	    dst = &curve[4];
  2127 	    *dst++ = tolower(*src);
  2128 	    src += 2;  /* skip the hyphen */
  2129 	    *dst++ = *src++;
  2130 	    *dst++ = *src++;
  2131 	    *dst++ = *src++;
  2132 	    *dst = '\0';
  2133 	    if (ecparams != NULL) {
  2134 		PORT_FreeArena(ecparams->arena, PR_FALSE);
  2135 		ecparams = NULL;
  2137 	    encodedparams = getECParams(curve);
  2138 	    if (encodedparams == NULL) {
  2139 		goto loser;
  2141 	    if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
  2142 		goto loser;
  2144 	    SECITEM_FreeItem(encodedparams, PR_TRUE);
  2145 	    len = (ecparams->fieldID.size + 7) >> 3;
  2146 	    if (pubkey.data != NULL) {
  2147 		PORT_Free(pubkey.data);
  2148 		pubkey.data = NULL;
  2150 	    SECITEM_AllocItem(NULL, &pubkey, 2*len+1);
  2151 	    if (pubkey.data == NULL) {
  2152 		goto loser;
  2154 	    pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
  2155 	    fputs(buf, ecdsaresp);
  2156 	    continue;
  2158 	/* Qx = ... */
  2159 	if (strncmp(buf, "Qx", 2) == 0) {
  2160 	    fputs(buf, ecdsaresp);
  2161 	    i = 2;
  2162 	    while (isspace(buf[i]) || buf[i] == '=') {
  2163 		i++;
  2165 	    keyvalid = from_hex_str(&pubkey.data[1], len, &buf[i]);
  2166 	    continue;
  2168 	/* Qy = ... */
  2169 	if (strncmp(buf, "Qy", 2) == 0) {
  2170 	    fputs(buf, ecdsaresp);
  2171 	    if (!keyvalid) {
  2172 		fputs("Result = F\n", ecdsaresp);
  2173 		continue;
  2175 	    i = 2;
  2176 	    while (isspace(buf[i]) || buf[i] == '=') {
  2177 		i++;
  2179 	    keyvalid = from_hex_str(&pubkey.data[1+len], len, &buf[i]);
  2180 	    if (!keyvalid) {
  2181 		fputs("Result = F\n", ecdsaresp);
  2182 		continue;
  2184 	    if (EC_ValidatePublicKey(ecparams, &pubkey) == SECSuccess) {
  2185 		fputs("Result = P\n", ecdsaresp);
  2186 	    } else if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
  2187 		fputs("Result = F\n", ecdsaresp);
  2188 	    } else {
  2189 		goto loser;
  2191 	    continue;
  2194 loser:
  2195     if (ecparams != NULL) {
  2196 	PORT_FreeArena(ecparams->arena, PR_FALSE);
  2198     if (pubkey.data != NULL) {
  2199 	PORT_Free(pubkey.data);
  2201     fclose(ecdsareq);
  2204 /*
  2205  * Perform the ECDSA Signature Generation Test.
  2207  * reqfn is the pathname of the REQUEST file.
  2209  * The output RESPONSE file is written to stdout.
  2210  */
  2211 void
  2212 ecdsa_siggen_test(char *reqfn)
  2214     char buf[1024];     /* holds one line from the input REQUEST file
  2215                          * or to the output RESPONSE file.
  2216                          * needs to be large enough to hold the longest
  2217                          * line "Msg = <256 hex digits>\n".
  2218                          */
  2219     FILE *ecdsareq;     /* input stream from the REQUEST file */
  2220     FILE *ecdsaresp;    /* output stream to the RESPONSE file */
  2221     char curve[16];     /* "nistxddd" */
  2222     ECParams *ecparams = NULL;
  2223     int i, j;
  2224     unsigned int len;
  2225     unsigned char msg[512];  /* message to be signed (<= 128 bytes) */
  2226     unsigned int msglen;
  2227     unsigned char sha1[20];  /* SHA-1 hash (160 bits) */
  2228     unsigned char sig[2*MAX_ECKEY_LEN];
  2229     SECItem signature, digest;
  2231     ecdsareq = fopen(reqfn, "r");
  2232     ecdsaresp = stdout;
  2233     strcpy(curve, "nist");
  2234     while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
  2235 	/* a comment or blank line */
  2236 	if (buf[0] == '#' || buf[0] == '\n') {
  2237 	    fputs(buf, ecdsaresp);
  2238 	    continue;
  2240 	/* [X-ddd] */
  2241 	if (buf[0] == '[') {
  2242 	    const char *src;
  2243 	    char *dst;
  2244 	    SECItem *encodedparams;
  2246 	    src = &buf[1];
  2247 	    dst = &curve[4];
  2248 	    *dst++ = tolower(*src);
  2249 	    src += 2;  /* skip the hyphen */
  2250 	    *dst++ = *src++;
  2251 	    *dst++ = *src++;
  2252 	    *dst++ = *src++;
  2253 	    *dst = '\0';
  2254 	    if (ecparams != NULL) {
  2255 		PORT_FreeArena(ecparams->arena, PR_FALSE);
  2256 		ecparams = NULL;
  2258 	    encodedparams = getECParams(curve);
  2259 	    if (encodedparams == NULL) {
  2260 		goto loser;
  2262 	    if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
  2263 		goto loser;
  2265 	    SECITEM_FreeItem(encodedparams, PR_TRUE);
  2266 	    fputs(buf, ecdsaresp);
  2267 	    continue;
  2269 	/* Msg = ... */
  2270 	if (strncmp(buf, "Msg", 3) == 0) {
  2271 	    ECPrivateKey *ecpriv;
  2273 	    i = 3;
  2274 	    while (isspace(buf[i]) || buf[i] == '=') {
  2275 		i++;
  2277 	    for (j=0; isxdigit(buf[i]); i+=2,j++) {
  2278 		hex_to_byteval(&buf[i], &msg[j]);
  2280 	    msglen = j;
  2281 	    if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) {
  2282 		goto loser;
  2284 	    fputs(buf, ecdsaresp);
  2286 	    if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
  2287 		goto loser;
  2289 	    if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue)
  2290 		!= SECSuccess) {
  2291 		goto loser;
  2293 	    len = ecpriv->publicValue.len;
  2294 	    if (len%2 == 0) {
  2295 		goto loser;
  2297 	    len = (len-1)/2;
  2298 	    if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
  2299 		goto loser;
  2301 	    fputs("Qx = ", ecdsaresp);
  2302 	    to_hex_str(buf, &ecpriv->publicValue.data[1], len);
  2303 	    fputs(buf, ecdsaresp);
  2304 	    fputc('\n', ecdsaresp);
  2305 	    fputs("Qy = ", ecdsaresp);
  2306 	    to_hex_str(buf, &ecpriv->publicValue.data[1+len], len);
  2307 	    fputs(buf, ecdsaresp);
  2308 	    fputc('\n', ecdsaresp);
  2310 	    digest.type = siBuffer;
  2311 	    digest.data = sha1;
  2312 	    digest.len = sizeof sha1;
  2313 	    signature.type = siBuffer;
  2314 	    signature.data = sig;
  2315 	    signature.len = sizeof sig;
  2316 	    if (ECDSA_SignDigest(ecpriv, &signature, &digest) != SECSuccess) {
  2317 		goto loser;
  2319 	    len = signature.len;
  2320 	    if (len%2 != 0) {
  2321 		goto loser;
  2323 	    len = len/2;
  2324 	    fputs("R = ", ecdsaresp);
  2325 	    to_hex_str(buf, &signature.data[0], len);
  2326 	    fputs(buf, ecdsaresp);
  2327 	    fputc('\n', ecdsaresp);
  2328 	    fputs("S = ", ecdsaresp);
  2329 	    to_hex_str(buf, &signature.data[len], len);
  2330 	    fputs(buf, ecdsaresp);
  2331 	    fputc('\n', ecdsaresp);
  2333 	    PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
  2334 	    continue;
  2337 loser:
  2338     if (ecparams != NULL) {
  2339 	PORT_FreeArena(ecparams->arena, PR_FALSE);
  2341     fclose(ecdsareq);
  2344 /*
  2345  * Perform the ECDSA Signature Verification Test.
  2347  * reqfn is the pathname of the REQUEST file.
  2349  * The output RESPONSE file is written to stdout.
  2350  */
  2351 void
  2352 ecdsa_sigver_test(char *reqfn)
  2354     char buf[1024];     /* holds one line from the input REQUEST file.
  2355                          * needs to be large enough to hold the longest
  2356                          * line "Msg = <256 hex digits>\n".
  2357                          */
  2358     FILE *ecdsareq;     /* input stream from the REQUEST file */
  2359     FILE *ecdsaresp;    /* output stream to the RESPONSE file */
  2360     char curve[16];     /* "nistxddd" */
  2361     ECPublicKey ecpub;
  2362     unsigned int i, j;
  2363     unsigned int flen;  /* length in bytes of the field size */
  2364     unsigned int olen;  /* length in bytes of the base point order */
  2365     unsigned char msg[512];  /* message that was signed (<= 128 bytes) */
  2366     unsigned int msglen;
  2367     unsigned char sha1[20];  /* SHA-1 hash (160 bits) */
  2368     unsigned char sig[2*MAX_ECKEY_LEN];
  2369     SECItem signature, digest;
  2370     PRBool keyvalid = PR_TRUE;
  2371     PRBool sigvalid = PR_TRUE;
  2373     ecdsareq = fopen(reqfn, "r");
  2374     ecdsaresp = stdout;
  2375     ecpub.ecParams.arena = NULL;
  2376     strcpy(curve, "nist");
  2377     while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
  2378 	/* a comment or blank line */
  2379 	if (buf[0] == '#' || buf[0] == '\n') {
  2380 	    fputs(buf, ecdsaresp);
  2381 	    continue;
  2383 	/* [X-ddd] */
  2384 	if (buf[0] == '[') {
  2385 	    const char *src;
  2386 	    char *dst;
  2387 	    SECItem *encodedparams;
  2388 	    ECParams *ecparams;
  2390 	    src = &buf[1];
  2391 	    dst = &curve[4];
  2392 	    *dst++ = tolower(*src);
  2393 	    src += 2;  /* skip the hyphen */
  2394 	    *dst++ = *src++;
  2395 	    *dst++ = *src++;
  2396 	    *dst++ = *src++;
  2397 	    *dst = '\0';
  2398 	    encodedparams = getECParams(curve);
  2399 	    if (encodedparams == NULL) {
  2400 		goto loser;
  2402 	    if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
  2403 		goto loser;
  2405 	    SECITEM_FreeItem(encodedparams, PR_TRUE);
  2406 	    if (ecpub.ecParams.arena != NULL) {
  2407 		PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
  2409 	    ecpub.ecParams.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  2410 	    if (ecpub.ecParams.arena == NULL) {
  2411 		goto loser;
  2413 	    if (EC_CopyParams(ecpub.ecParams.arena, &ecpub.ecParams, ecparams)
  2414 		!= SECSuccess) {
  2415 		goto loser;
  2417 	    PORT_FreeArena(ecparams->arena, PR_FALSE);
  2418 	    flen = (ecpub.ecParams.fieldID.size + 7) >> 3;
  2419 	    olen = ecpub.ecParams.order.len;
  2420 	    if (2*olen > sizeof sig) {
  2421 		goto loser;
  2423 	    ecpub.publicValue.type = siBuffer;
  2424 	    ecpub.publicValue.data = NULL;
  2425 	    ecpub.publicValue.len = 0;
  2426 	    SECITEM_AllocItem(ecpub.ecParams.arena,
  2427 			      &ecpub.publicValue, 2*flen+1);
  2428 	    if (ecpub.publicValue.data == NULL) {
  2429 		goto loser;
  2431 	    ecpub.publicValue.data[0] = EC_POINT_FORM_UNCOMPRESSED;
  2432 	    fputs(buf, ecdsaresp);
  2433 	    continue;
  2435 	/* Msg = ... */
  2436 	if (strncmp(buf, "Msg", 3) == 0) {
  2437 	    i = 3;
  2438 	    while (isspace(buf[i]) || buf[i] == '=') {
  2439 		i++;
  2441 	    for (j=0; isxdigit(buf[i]); i+=2,j++) {
  2442 		hex_to_byteval(&buf[i], &msg[j]);
  2444 	    msglen = j;
  2445 	    if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) {
  2446 		goto loser;
  2448 	    fputs(buf, ecdsaresp);
  2450 	    digest.type = siBuffer;
  2451 	    digest.data = sha1;
  2452 	    digest.len = sizeof sha1;
  2454 	    continue;
  2456 	/* Qx = ... */
  2457 	if (strncmp(buf, "Qx", 2) == 0) {
  2458 	    fputs(buf, ecdsaresp);
  2459 	    i = 2;
  2460 	    while (isspace(buf[i]) || buf[i] == '=') {
  2461 		i++;
  2463 	    keyvalid = from_hex_str(&ecpub.publicValue.data[1], flen,
  2464 				    &buf[i]);
  2465 	    continue;
  2467 	/* Qy = ... */
  2468 	if (strncmp(buf, "Qy", 2) == 0) {
  2469 	    fputs(buf, ecdsaresp);
  2470 	    if (!keyvalid) {
  2471 		continue;
  2473 	    i = 2;
  2474 	    while (isspace(buf[i]) || buf[i] == '=') {
  2475 		i++;
  2477 	    keyvalid = from_hex_str(&ecpub.publicValue.data[1+flen], flen,
  2478 				    &buf[i]);
  2479 	    if (!keyvalid) {
  2480 		continue;
  2482 	    if (EC_ValidatePublicKey(&ecpub.ecParams, &ecpub.publicValue)
  2483 		!= SECSuccess) {
  2484 		if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
  2485 		    keyvalid = PR_FALSE;
  2486 		} else {
  2487 		    goto loser;
  2490 	    continue;
  2492 	/* R = ... */
  2493 	if (buf[0] == 'R') {
  2494 	    fputs(buf, ecdsaresp);
  2495 	    i = 1;
  2496 	    while (isspace(buf[i]) || buf[i] == '=') {
  2497 		i++;
  2499 	    sigvalid = from_hex_str(sig, olen, &buf[i]);
  2500 	    continue;
  2502 	/* S = ... */
  2503 	if (buf[0] == 'S') {
  2504 	    fputs(buf, ecdsaresp);
  2505 	    i = 1;
  2506 	    while (isspace(buf[i]) || buf[i] == '=') {
  2507 		i++;
  2509 	    if (sigvalid) {
  2510 		sigvalid = from_hex_str(&sig[olen], olen, &buf[i]);
  2512 	    signature.type = siBuffer;
  2513 	    signature.data = sig;
  2514 	    signature.len = 2*olen;
  2516 	    if (!keyvalid || !sigvalid) {
  2517 		fputs("Result = F\n", ecdsaresp);
  2518 	    } else if (ECDSA_VerifyDigest(&ecpub, &signature, &digest)
  2519 		== SECSuccess) {
  2520 		fputs("Result = P\n", ecdsaresp);
  2521 	    } else {
  2522 		fputs("Result = F\n", ecdsaresp);
  2524 	    continue;
  2527 loser:
  2528     if (ecpub.ecParams.arena != NULL) {
  2529 	PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
  2531     fclose(ecdsareq);
  2533 #endif /* NSS_DISABLE_ECC */
  2536 /*
  2537  * Read a value from the test and allocate the result.
  2538  */
  2539 static unsigned char *
  2540 alloc_value(char *buf, int *len)
  2542     unsigned char * value;
  2543     int i, count;
  2545     if (strncmp(buf, "<None>", 6) == 0) {
  2546 	*len = 0;
  2547 	return NULL;
  2550     /* find the length of the number */
  2551     for (count = 0; isxdigit(buf[count]); count++);
  2552     *len = count/2;
  2554     if (*len == 0) {
  2555 	return NULL;
  2558     value = PORT_Alloc(*len);
  2559     if (!value) {
  2560 	*len = 0;
  2561 	return NULL;
  2564     for (i=0; i<*len; buf+=2 , i++) {
  2565 	hex_to_byteval(buf, &value[i]);
  2569     return value;
  2572 PRBool
  2573 isblankline(char *b)
  2575    while (isspace(*b)) b++;
  2576    if ((*b == '\n') || (*b == 0)) {
  2577 	return PR_TRUE;
  2579    return PR_FALSE;
  2582 static int debug = 0;
  2584 /*
  2585  * Perform the Hash_DRBG (CAVS) for the RNG algorithm
  2587  * reqfn is the pathname of the REQUEST file.
  2589  * The output RESPONSE file is written to stdout.
  2590  */
  2591 void
  2592 drbg(char *reqfn)
  2594     char buf[2000];   /* test case has some very long lines, returned bits
  2595      * as high as 800 bytes (6400 bits). That 1600 byte
  2596      * plus a tag */
  2597     char buf2[2000]; 
  2598     FILE *rngreq;       /* input stream from the REQUEST file */
  2599     FILE *rngresp;      /* output stream to the RESPONSE file */
  2601     unsigned int i, j;
  2602     PRBool predictionResistance = PR_FALSE;
  2603     unsigned char *nonce =  NULL;
  2604     int nonceLen = 0;
  2605     unsigned char *personalizationString =  NULL;
  2606     int personalizationStringLen = 0;
  2607     unsigned char *additionalInput =  NULL;
  2608     int additionalInputLen = 0;
  2609     unsigned char *entropyInput = NULL;
  2610     int entropyInputLen = 0;
  2611     unsigned char predictedreturn_bytes[SHA256_LENGTH];
  2612     unsigned char return_bytes[SHA256_LENGTH];
  2613     int return_bytes_len = SHA256_LENGTH;
  2614     enum { NONE, INSTANTIATE, GENERATE, RESEED, RESULT } command =
  2615     NONE;
  2616     PRBool genResult = PR_FALSE;
  2617     SECStatus rv;
  2619     rngreq = fopen(reqfn, "r");
  2620     rngresp = stdout;
  2621     while (fgets(buf, sizeof buf, rngreq) != NULL) {
  2622        switch (command) {
  2623             case INSTANTIATE:
  2624 		if (debug) {
  2625 		    fputs("# PRNGTEST_Instantiate(",rngresp);
  2626 		    to_hex_str(buf2,entropyInput, entropyInputLen);
  2627 		    fputs(buf2,rngresp);
  2628 		    fprintf(rngresp,",%d,",entropyInputLen);
  2629 		    to_hex_str(buf2,nonce, nonceLen);
  2630 		    fputs(buf2,rngresp);
  2631 		    fprintf(rngresp,",%d,",nonceLen);
  2632 		    to_hex_str(buf2,personalizationString, 
  2633 					personalizationStringLen);
  2634 		    fputs(buf2,rngresp);
  2635 		    fprintf(rngresp,",%d)\n", personalizationStringLen);
  2637                 rv = PRNGTEST_Instantiate(entropyInput, entropyInputLen,
  2638                                           nonce, nonceLen,
  2639                                           personalizationString, 
  2640 				          personalizationStringLen);
  2641                 if (rv != SECSuccess) {
  2642                     goto loser;
  2644                 break;
  2646             case GENERATE:
  2647             case RESULT:
  2648                 memset(return_bytes, 0, return_bytes_len);
  2649 		if (debug) {
  2650 		    fputs("# PRNGTEST_Generate(returnbytes",rngresp);
  2651 		    fprintf(rngresp,",%d,", return_bytes_len);
  2652 		    to_hex_str(buf2,additionalInput, additionalInputLen);
  2653 		    fputs(buf2,rngresp);
  2654 		    fprintf(rngresp,",%d)\n",additionalInputLen);
  2656                 rv = PRNGTEST_Generate((PRUint8 *) return_bytes, 
  2657 					return_bytes_len,
  2658                                        (PRUint8 *) additionalInput, 
  2659 					additionalInputLen);
  2660                 if (rv != SECSuccess) {
  2661                     goto loser;
  2664                 if (command == RESULT) {
  2665                     fputs("ReturnedBits = ", rngresp);
  2666                     to_hex_str(buf2, return_bytes, return_bytes_len);
  2667                     fputs(buf2, rngresp);
  2668                     fputc('\n', rngresp);
  2669 		    if (debug) {
  2670 			fputs("# PRNGTEST_Uninstantiate()\n",rngresp);
  2672                     rv = PRNGTEST_Uninstantiate();
  2673                     if (rv != SECSuccess) {
  2674                         goto loser;
  2676                 } else if (debug) {
  2677                     fputs("#ReturnedBits = ", rngresp);
  2678                     to_hex_str(buf2, return_bytes, return_bytes_len);
  2679                     fputs(buf2, rngresp);
  2680                     fputc('\n', rngresp);
  2683                 memset(additionalInput, 0, additionalInputLen);
  2684                 break;
  2686             case RESEED:
  2687                 if (entropyInput || additionalInput) {
  2688 		    if (debug) {
  2689 			fputs("# PRNGTEST_Reseed(",rngresp);
  2690 			fprintf(rngresp,",%d,", return_bytes_len);
  2691 			to_hex_str(buf2,entropyInput, entropyInputLen);
  2692 			fputs(buf2,rngresp);
  2693 			fprintf(rngresp,",%d,", entropyInputLen);
  2694 			to_hex_str(buf2,additionalInput, additionalInputLen);
  2695 			fputs(buf2,rngresp);
  2696 			fprintf(rngresp,",%d)\n",additionalInputLen);
  2698                     rv = PRNGTEST_Reseed(entropyInput, entropyInputLen,
  2699                                              additionalInput, additionalInputLen);
  2700                     if (rv != SECSuccess) {
  2701                         goto loser;
  2704                 memset(entropyInput, 0, entropyInputLen);
  2705                 memset(additionalInput, 0, additionalInputLen);
  2706                 break;
  2707             case NONE:
  2708                 break;
  2711         command = NONE;
  2713         /* a comment or blank line */
  2714         if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r' ) {
  2715             fputs(buf, rngresp);
  2716             continue;
  2719         /* [Hash - SHA256] */
  2720         if (strncmp(buf, "[SHA-256]", 9) == 0) {
  2721             fputs(buf, rngresp);
  2722             continue;
  2725         if (strncmp(buf, "[PredictionResistance", 21)  == 0) {
  2726             i = 21;
  2727             while (isspace(buf[i]) || buf[i] == '=') {
  2728                 i++;
  2730             if (strncmp(buf, "False", 5) == 0) {
  2731                 predictionResistance = PR_FALSE;
  2732             } else {
  2733                 predictionResistance = PR_TRUE;
  2736             fputs(buf, rngresp);
  2737             continue;
  2740         if (strncmp(buf, "[EntropyInputLen", 16)  == 0) {
  2741             if (entropyInput) {
  2742                 PORT_ZFree(entropyInput, entropyInputLen);
  2743                 entropyInput = NULL;
  2744                 entropyInputLen = 0;
  2746             if (sscanf(buf, "[EntropyInputLen = %d]", &entropyInputLen) != 1) {
  2747                 goto loser;
  2749 	    entropyInputLen = entropyInputLen/8;
  2750             if (entropyInputLen > 0) {
  2751                 entropyInput = PORT_Alloc(entropyInputLen);
  2753             fputs(buf, rngresp);
  2754             continue;
  2757         if (strncmp(buf, "[NonceLen", 9)  == 0) {
  2758             if (nonce) {
  2759                 PORT_ZFree(nonce, nonceLen);
  2760                 nonce = NULL;
  2761                 nonceLen = 0;
  2764             if (sscanf(buf, "[NonceLen = %d]", &nonceLen) != 1) {
  2765                 goto loser;
  2767 	    nonceLen = nonceLen/8;
  2768             if (nonceLen > 0) {
  2769                 nonce = PORT_Alloc(nonceLen);
  2771             fputs(buf, rngresp);
  2772             continue;
  2775         if (strncmp(buf, "[PersonalizationStringLen", 16)  == 0) {
  2776             if (personalizationString) {
  2777                 PORT_ZFree(personalizationString, personalizationStringLen);
  2778                 personalizationString = NULL;
  2779                 personalizationStringLen = 0;
  2782             if (sscanf(buf, "[PersonalizationStringLen = %d]", &personalizationStringLen) != 1) {
  2783                 goto loser;
  2785 	    personalizationStringLen = personalizationStringLen / 8;
  2786             if (personalizationStringLen > 0) {
  2787                 personalizationString = PORT_Alloc(personalizationStringLen);
  2789             fputs(buf, rngresp);
  2791             continue;
  2794         if (strncmp(buf, "[AdditionalInputLen", 16)  == 0) {
  2795             if (additionalInput) {
  2796                 PORT_ZFree(additionalInput, additionalInputLen);
  2797                 additionalInput = NULL;
  2798                 additionalInputLen = 0;
  2801             if (sscanf(buf, "[AdditionalInputLen = %d]", &additionalInputLen) != 1) {
  2802                 goto loser;
  2804 	    additionalInputLen = additionalInputLen/8;
  2805             if (additionalInputLen > 0) {
  2806                 additionalInput = PORT_Alloc(additionalInputLen);
  2808             fputs(buf, rngresp);
  2809             continue;
  2812         if (strncmp(buf, "COUNT", 5) == 0) {
  2813             /* zeroize the variables for the test with this data set */
  2814             if (entropyInput) {
  2815                 memset(entropyInput, 0, entropyInputLen);
  2817             if (nonce) {
  2818                 memset(nonce, 0, nonceLen);        
  2820             if (personalizationString) {
  2821                 memset(personalizationString, 0, personalizationStringLen);
  2823             if (additionalInput) {
  2824                 memset(additionalInput, 0, additionalInputLen);
  2826             genResult = PR_FALSE;
  2828             fputs(buf, rngresp);
  2829             continue;
  2832         /* EntropyInputReseed = ... */
  2833         if (strncmp(buf, "EntropyInputReseed", 18) == 0) {
  2834             if (entropyInput) {
  2835                 memset(entropyInput, 0, entropyInputLen);
  2836                 i = 18;
  2837                 while (isspace(buf[i]) || buf[i] == '=') {
  2838                     i++;
  2841                 for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<entropyInputLen*/
  2842                     hex_to_byteval(&buf[i], &entropyInput[j]);
  2845             fputs(buf, rngresp);
  2846             continue;
  2849         /* AttionalInputReseed  = ... */
  2850         if (strncmp(buf, "AdditionalInputReseed", 21) == 0) {
  2851             if (additionalInput) {
  2852                 memset(additionalInput, 0, additionalInputLen);
  2853                 i = 21;
  2854                 while (isspace(buf[i]) || buf[i] == '=') {
  2855                     i++;
  2857                 for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<additionalInputLen*/
  2858                     hex_to_byteval(&buf[i], &additionalInput[j]);
  2861             command = RESEED;
  2862             fputs(buf, rngresp);
  2863             continue;
  2866         /* Entropy input = ... */
  2867         if (strncmp(buf, "EntropyInput", 12) == 0) {
  2868             i = 12;
  2869             while (isspace(buf[i]) || buf[i] == '=') {
  2870                 i++;
  2872             for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<entropyInputLen*/
  2873                 hex_to_byteval(&buf[i], &entropyInput[j]);
  2875             fputs(buf, rngresp);
  2876             continue;
  2879         /* nouce = ... */
  2880         if (strncmp(buf, "Nonce", 5) == 0) {
  2881             i = 5;
  2882             while (isspace(buf[i]) || buf[i] == '=') {
  2883                 i++;
  2885             for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<nonceLen*/
  2886                 hex_to_byteval(&buf[i], &nonce[j]);
  2888             fputs(buf, rngresp);
  2889             continue;
  2892         /* Personalization string = ... */
  2893         if (strncmp(buf, "PersonalizationString", 21) == 0) {
  2894             if (personalizationString) {
  2895                 i = 21;
  2896                 while (isspace(buf[i]) || buf[i] == '=') {
  2897                     i++;
  2899                 for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<personalizationStringLen*/
  2900                     hex_to_byteval(&buf[i], &personalizationString[j]);
  2903             fputs(buf, rngresp);
  2904             command = INSTANTIATE;
  2905             continue;
  2908         /* Additional input = ... */
  2909         if (strncmp(buf, "AdditionalInput", 15) == 0) {
  2910             if (additionalInput) {
  2911                 i = 15;
  2912                 while (isspace(buf[i]) || buf[i] == '=') {
  2913                     i++;
  2915                 for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<additionalInputLen*/
  2916                     hex_to_byteval(&buf[i], &additionalInput[j]);
  2919             if (genResult) {
  2920                 command = RESULT;
  2921             } else {
  2922                 command = GENERATE;
  2923                 genResult = PR_TRUE; /* next time generate result */
  2925             fputs(buf, rngresp);
  2926             continue;
  2929         /* Returned bits = ... */
  2930         if (strncmp(buf, "ReturnedBits", 12) == 0) {
  2931             i = 12;
  2932             while (isspace(buf[i]) || buf[i] == '=') {
  2933                 i++;
  2935             for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j<additionalInputLen*/
  2936                 hex_to_byteval(&buf[i], &predictedreturn_bytes[j]);
  2939             if (memcmp(return_bytes, 
  2940                        predictedreturn_bytes, return_bytes_len) != 0) {
  2941 		if (debug) {
  2942                 fprintf(rngresp, "# Generate failed:\n");
  2943                 fputs(  "#   predicted=", rngresp);
  2944                 to_hex_str(buf, predictedreturn_bytes, 
  2945                            return_bytes_len);
  2946                 fputs(buf, rngresp);
  2947                 fputs("\n#   actual  = ", rngresp);
  2948                 fputs(buf2, rngresp);
  2949                 fputc('\n', rngresp);
  2951 		} else {
  2952                 fprintf(stderr, "Generate failed:\n");
  2953                 fputs(  "   predicted=", stderr);
  2954                 to_hex_str(buf, predictedreturn_bytes, 
  2955                            return_bytes_len);
  2956                 fputs(buf, stderr);
  2957                 fputs("\n   actual  = ", stderr);
  2958                 fputs(buf2, stderr);
  2959                 fputc('\n', stderr);
  2962             memset(predictedreturn_bytes, 0 , sizeof predictedreturn_bytes);
  2964             continue;
  2967 loser:
  2968     fclose(rngreq);
  2971 /*
  2972  * Perform the RNG Variable Seed Test (VST) for the RNG algorithm
  2973  * "DSA - Generation of X", used both as specified and as a generic
  2974  * purpose RNG.  The presence of "Q = ..." in the REQUEST file
  2975  * indicates we are using the algorithm as specified.
  2977  * reqfn is the pathname of the REQUEST file.
  2979  * The output RESPONSE file is written to stdout.
  2980  */
  2981 void
  2982 rng_vst(char *reqfn)
  2984     char buf[256];      /* holds one line from the input REQUEST file.
  2985                          * needs to be large enough to hold the longest
  2986                          * line "XSeed = <128 hex digits>\n".
  2987                          */
  2988     FILE *rngreq;       /* input stream from the REQUEST file */
  2989     FILE *rngresp;      /* output stream to the RESPONSE file */
  2990     unsigned int i, j;
  2991     unsigned char Q[DSA1_SUBPRIME_LEN];
  2992     PRBool hasQ = PR_FALSE;
  2993     unsigned int b;  /* 160 <= b <= 512, b is a multiple of 8 */
  2994     unsigned char XKey[512/8];
  2995     unsigned char XSeed[512/8];
  2996     unsigned char GENX[DSA1_SIGNATURE_LEN];
  2997     unsigned char DSAX[DSA1_SUBPRIME_LEN];
  2998     SECStatus rv;
  3000     rngreq = fopen(reqfn, "r");
  3001     rngresp = stdout;
  3002     while (fgets(buf, sizeof buf, rngreq) != NULL) {
  3003 	/* a comment or blank line */
  3004 	if (buf[0] == '#' || buf[0] == '\n') {
  3005 	    fputs(buf, rngresp);
  3006 	    continue;
  3008 	/* [Xchange - SHA1] */
  3009 	if (buf[0] == '[') {
  3010 	    fputs(buf, rngresp);
  3011 	    continue;
  3013 	/* Q = ... */
  3014 	if (buf[0] == 'Q') {
  3015 	    i = 1;
  3016 	    while (isspace(buf[i]) || buf[i] == '=') {
  3017 		i++;
  3019 	    for (j=0; j<sizeof Q; i+=2,j++) {
  3020 		hex_to_byteval(&buf[i], &Q[j]);
  3022 	    fputs(buf, rngresp);
  3023 	    hasQ = PR_TRUE;
  3024 	    continue;
  3026 	/* "COUNT = x" begins a new data set */
  3027 	if (strncmp(buf, "COUNT", 5) == 0) {
  3028 	    /* zeroize the variables for the test with this data set */
  3029 	    b = 0;
  3030 	    memset(XKey, 0, sizeof XKey);
  3031 	    memset(XSeed, 0, sizeof XSeed);
  3032 	    fputs(buf, rngresp);
  3033 	    continue;
  3035 	/* b = ... */
  3036 	if (buf[0] == 'b') {
  3037 	    i = 1;
  3038 	    while (isspace(buf[i]) || buf[i] == '=') {
  3039 		i++;
  3041 	    b = atoi(&buf[i]);
  3042 	    if (b < 160 || b > 512 || b%8 != 0) {
  3043 		goto loser;
  3045 	    fputs(buf, rngresp);
  3046 	    continue;
  3048 	/* XKey = ... */
  3049 	if (strncmp(buf, "XKey", 4) == 0) {
  3050 	    i = 4;
  3051 	    while (isspace(buf[i]) || buf[i] == '=') {
  3052 		i++;
  3054 	    for (j=0; j<b/8; i+=2,j++) {
  3055 		hex_to_byteval(&buf[i], &XKey[j]);
  3057 	    fputs(buf, rngresp);
  3058 	    continue;
  3060 	/* XSeed = ... */
  3061 	if (strncmp(buf, "XSeed", 5) == 0) {
  3062 	    i = 5;
  3063 	    while (isspace(buf[i]) || buf[i] == '=') {
  3064 		i++;
  3066 	    for (j=0; j<b/8; i+=2,j++) {
  3067 		hex_to_byteval(&buf[i], &XSeed[j]);
  3069 	    fputs(buf, rngresp);
  3071 	    rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
  3072 	    if (rv != SECSuccess) {
  3073 		goto loser;
  3075 	    fputs("X = ", rngresp);
  3076 	    if (hasQ) {
  3077 		rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
  3078 		if (rv != SECSuccess) {
  3079 		    goto loser;
  3081 		to_hex_str(buf, DSAX, sizeof DSAX);
  3082 	    } else {
  3083 		to_hex_str(buf, GENX, sizeof GENX);
  3085 	    fputs(buf, rngresp);
  3086 	    fputc('\n', rngresp);
  3087 	    continue;
  3090 loser:
  3091     fclose(rngreq);
  3094 /*
  3095  * Perform the RNG Monte Carlo Test (MCT) for the RNG algorithm
  3096  * "DSA - Generation of X", used both as specified and as a generic
  3097  * purpose RNG.  The presence of "Q = ..." in the REQUEST file
  3098  * indicates we are using the algorithm as specified.
  3100  * reqfn is the pathname of the REQUEST file.
  3102  * The output RESPONSE file is written to stdout.
  3103  */
  3104 void
  3105 rng_mct(char *reqfn)
  3107     char buf[256];      /* holds one line from the input REQUEST file.
  3108                          * needs to be large enough to hold the longest
  3109                          * line "XSeed = <128 hex digits>\n".
  3110                          */
  3111     FILE *rngreq;       /* input stream from the REQUEST file */
  3112     FILE *rngresp;      /* output stream to the RESPONSE file */
  3113     unsigned int i, j;
  3114     unsigned char Q[DSA1_SUBPRIME_LEN];
  3115     PRBool hasQ = PR_FALSE;
  3116     unsigned int b;  /* 160 <= b <= 512, b is a multiple of 8 */
  3117     unsigned char XKey[512/8];
  3118     unsigned char XSeed[512/8];
  3119     unsigned char GENX[2*SHA1_LENGTH];
  3120     unsigned char DSAX[DSA1_SUBPRIME_LEN];
  3121     SECStatus rv;
  3123     rngreq = fopen(reqfn, "r");
  3124     rngresp = stdout;
  3125     while (fgets(buf, sizeof buf, rngreq) != NULL) {
  3126 	/* a comment or blank line */
  3127 	if (buf[0] == '#' || buf[0] == '\n') {
  3128 	    fputs(buf, rngresp);
  3129 	    continue;
  3131 	/* [Xchange - SHA1] */
  3132 	if (buf[0] == '[') {
  3133 	    fputs(buf, rngresp);
  3134 	    continue;
  3136 	/* Q = ... */
  3137 	if (buf[0] == 'Q') {
  3138 	    i = 1;
  3139 	    while (isspace(buf[i]) || buf[i] == '=') {
  3140 		i++;
  3142 	    for (j=0; j<sizeof Q; i+=2,j++) {
  3143 		hex_to_byteval(&buf[i], &Q[j]);
  3145 	    fputs(buf, rngresp);
  3146 	    hasQ = PR_TRUE;
  3147 	    continue;
  3149 	/* "COUNT = x" begins a new data set */
  3150 	if (strncmp(buf, "COUNT", 5) == 0) {
  3151 	    /* zeroize the variables for the test with this data set */
  3152 	    b = 0;
  3153 	    memset(XKey, 0, sizeof XKey);
  3154 	    memset(XSeed, 0, sizeof XSeed);
  3155 	    fputs(buf, rngresp);
  3156 	    continue;
  3158 	/* b = ... */
  3159 	if (buf[0] == 'b') {
  3160 	    i = 1;
  3161 	    while (isspace(buf[i]) || buf[i] == '=') {
  3162 		i++;
  3164 	    b = atoi(&buf[i]);
  3165 	    if (b < 160 || b > 512 || b%8 != 0) {
  3166 		goto loser;
  3168 	    fputs(buf, rngresp);
  3169 	    continue;
  3171 	/* XKey = ... */
  3172 	if (strncmp(buf, "XKey", 4) == 0) {
  3173 	    i = 4;
  3174 	    while (isspace(buf[i]) || buf[i] == '=') {
  3175 		i++;
  3177 	    for (j=0; j<b/8; i+=2,j++) {
  3178 		hex_to_byteval(&buf[i], &XKey[j]);
  3180 	    fputs(buf, rngresp);
  3181 	    continue;
  3183 	/* XSeed = ... */
  3184 	if (strncmp(buf, "XSeed", 5) == 0) {
  3185 	    unsigned int k;
  3186 	    i = 5;
  3187 	    while (isspace(buf[i]) || buf[i] == '=') {
  3188 		i++;
  3190 	    for (j=0; j<b/8; i+=2,j++) {
  3191 		hex_to_byteval(&buf[i], &XSeed[j]);
  3193 	    fputs(buf, rngresp);
  3195 	    for (k = 0; k < 10000; k++) {
  3196 		rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
  3197 		if (rv != SECSuccess) {
  3198 		    goto loser;
  3201 	    fputs("X = ", rngresp);
  3202 	    if (hasQ) {
  3203 		rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
  3204 		if (rv != SECSuccess) {
  3205 		    goto loser;
  3207 		to_hex_str(buf, DSAX, sizeof DSAX);
  3208 	    } else {
  3209 		to_hex_str(buf, GENX, sizeof GENX);
  3211 	    fputs(buf, rngresp);
  3212 	    fputc('\n', rngresp);
  3213 	    continue;
  3216 loser:
  3217     fclose(rngreq);
  3220 /*
  3221  * HASH_ functions are available to full NSS apps and internally inside
  3222  * freebl, but not exported to users of freebl. Create short stubs to
  3223  * replace the functionality for fipstest.
  3224  */
  3225 SECStatus
  3226 fips_hashBuf(HASH_HashType type, unsigned char *hashBuf, 
  3227 					unsigned char *msg, int len)
  3229     SECStatus rv = SECFailure;
  3231     switch (type) {
  3232     case HASH_AlgSHA1:
  3233 	rv = SHA1_HashBuf(hashBuf, msg, len);
  3234 	break;
  3235     case HASH_AlgSHA224:
  3236 	rv = SHA224_HashBuf(hashBuf, msg, len);
  3237 	break;
  3238     case HASH_AlgSHA256:
  3239 	rv = SHA256_HashBuf(hashBuf, msg, len);
  3240 	break;
  3241     case HASH_AlgSHA384:
  3242 	rv = SHA384_HashBuf(hashBuf, msg, len);
  3243 	break;
  3244     case HASH_AlgSHA512:
  3245 	rv = SHA512_HashBuf(hashBuf, msg, len);
  3246 	break;
  3247     default:
  3248 	break;
  3250     return rv;
  3253 int
  3254 fips_hashLen(HASH_HashType type)
  3256     int len = 0;
  3258     switch (type) {
  3259     case HASH_AlgSHA1:
  3260 	len = SHA1_LENGTH;
  3261 	break;
  3262     case HASH_AlgSHA224:
  3263 	len = SHA224_LENGTH;
  3264 	break;
  3265     case HASH_AlgSHA256:
  3266 	len = SHA256_LENGTH;
  3267 	break;
  3268     case HASH_AlgSHA384:
  3269 	len = SHA384_LENGTH;
  3270 	break;
  3271     case HASH_AlgSHA512:
  3272 	len = SHA512_LENGTH;
  3273 	break;
  3274     default:
  3275 	break;
  3277     return len;
  3280 SECOidTag
  3281 fips_hashOid(HASH_HashType type)
  3283     SECOidTag oid = SEC_OID_UNKNOWN;
  3285     switch (type) {
  3286     case HASH_AlgSHA1:
  3287 	oid = SEC_OID_SHA1;
  3288 	break;
  3289     case HASH_AlgSHA224:
  3290 	oid = SEC_OID_SHA224;
  3291 	break;
  3292     case HASH_AlgSHA256:
  3293 	oid = SEC_OID_SHA256;
  3294 	break;
  3295     case HASH_AlgSHA384:
  3296 	oid = SEC_OID_SHA384;
  3297 	break;
  3298     case HASH_AlgSHA512:
  3299 	oid = SEC_OID_SHA512;
  3300 	break;
  3301     default:
  3302 	break;
  3304     return oid;
  3307 HASH_HashType
  3308 sha_get_hashType(int hashbits)
  3310     HASH_HashType hashType = HASH_AlgNULL;
  3312     switch (hashbits) {
  3313     case 1:
  3314     case (SHA1_LENGTH*PR_BITS_PER_BYTE):
  3315 	hashType = HASH_AlgSHA1;
  3316 	break;
  3317     case (SHA224_LENGTH*PR_BITS_PER_BYTE):
  3318 	hashType = HASH_AlgSHA224;
  3319 	break;
  3320     case (SHA256_LENGTH*PR_BITS_PER_BYTE):
  3321 	hashType = HASH_AlgSHA256;
  3322 	break;
  3323     case (SHA384_LENGTH*PR_BITS_PER_BYTE):
  3324 	hashType = HASH_AlgSHA384;
  3325 	break;
  3326     case (SHA512_LENGTH*PR_BITS_PER_BYTE):
  3327 	hashType = HASH_AlgSHA512;
  3328 	break;
  3329     default:
  3330 	break;
  3332     return hashType;
  3335 /*
  3336  * Calculate the SHA Message Digest 
  3338  * MD = Message digest 
  3339  * MDLen = length of Message Digest and SHA_Type
  3340  * msg = message to digest 
  3341  * msgLen = length of message to digest
  3342  */
  3343 SECStatus sha_calcMD(unsigned char *MD, unsigned int MDLen, unsigned char *msg, unsigned int msgLen) 
  3345     HASH_HashType  hashType = sha_get_hashType(MDLen*PR_BITS_PER_BYTE);
  3347     return fips_hashBuf(hashType, MD, msg, msgLen);
  3350 /*
  3351  * Perform the SHA Monte Carlo Test
  3353  * MDLen = length of Message Digest and SHA_Type
  3354  * seed = input seed value
  3355  * resp = is the output response file. 
  3356  */
  3357 SECStatus sha_mct_test(unsigned int MDLen, unsigned char *seed, FILE *resp) 
  3359     int i, j;
  3360     unsigned int msgLen = MDLen*3;
  3361     unsigned char MD_i3[HASH_LENGTH_MAX];  /* MD[i-3] */
  3362     unsigned char MD_i2[HASH_LENGTH_MAX];  /* MD[i-2] */
  3363     unsigned char MD_i1[HASH_LENGTH_MAX];  /* MD[i-1] */
  3364     unsigned char MD_i[HASH_LENGTH_MAX];   /* MD[i] */
  3365     unsigned char msg[HASH_LENGTH_MAX*3];
  3366     char buf[HASH_LENGTH_MAX*2 + 1];  /* MAX buf MD_i as a hex string */
  3368     for (j=0; j<100; j++) {
  3369         /* MD_0 = MD_1 = MD_2 = seed */
  3370         memcpy(MD_i3, seed, MDLen);
  3371         memcpy(MD_i2, seed, MDLen);
  3372         memcpy(MD_i1, seed, MDLen);
  3374         for (i=3; i < 1003; i++) {
  3375             /* Mi = MD[i-3] || MD [i-2] || MD [i-1] */
  3376             memcpy(msg, MD_i3, MDLen);
  3377             memcpy(&msg[MDLen], MD_i2, MDLen);
  3378             memcpy(&msg[MDLen*2], MD_i1,MDLen); 
  3380             /* MDi = SHA(Msg) */
  3381             if (sha_calcMD(MD_i, MDLen,   
  3382                            msg, msgLen) != SECSuccess) {
  3383                 return SECFailure;
  3386             /* save MD[i-3] MD[i-2]  MD[i-1] */
  3387             memcpy(MD_i3, MD_i2, MDLen);
  3388             memcpy(MD_i2, MD_i1, MDLen);
  3389             memcpy(MD_i1, MD_i, MDLen);
  3393         /* seed = MD_i */
  3394         memcpy(seed, MD_i, MDLen);
  3396         sprintf(buf, "COUNT = %d\n", j);
  3397         fputs(buf, resp);
  3399         /* output MD_i */
  3400         fputs("MD = ", resp);
  3401         to_hex_str(buf, MD_i, MDLen);
  3402         fputs(buf, resp);
  3403         fputc('\n', resp);
  3406     return SECSuccess;
  3409 /*
  3410  * Perform the SHA Tests.
  3412  * reqfn is the pathname of the input REQUEST file.
  3414  * The output RESPONSE file is written to stdout.
  3415  */
  3416 void sha_test(char *reqfn) 
  3418     unsigned int i, j;
  3419     unsigned int MDlen;   /* the length of the Message Digest in Bytes  */
  3420     unsigned int msgLen;  /* the length of the input Message in Bytes */
  3421     unsigned char *msg = NULL; /* holds the message to digest.*/
  3422     size_t bufSize = 25608; /*MAX buffer size */
  3423     char *buf = NULL;      /* holds one line from the input REQUEST file.*/
  3424     unsigned char seed[HASH_LENGTH_MAX];   /* max size of seed 64 bytes */
  3425     unsigned char MD[HASH_LENGTH_MAX];     /* message digest */
  3427     FILE *req = NULL;  /* input stream from the REQUEST file */
  3428     FILE *resp;        /* output stream to the RESPONSE file */
  3430     buf = PORT_ZAlloc(bufSize);
  3431     if (buf == NULL) {
  3432         goto loser;
  3435     /* zeroize the variables for the test with this data set */
  3436     memset(seed, 0, sizeof seed);
  3438     req = fopen(reqfn, "r");
  3439     resp = stdout;
  3440     while (fgets(buf, bufSize, req) != NULL) {
  3442         /* a comment or blank line */
  3443         if (buf[0] == '#' || buf[0] == '\n') {
  3444             fputs(buf, resp);
  3445             continue;
  3447         /* [L = Length of the Message Digest and sha_type */
  3448         if (buf[0] == '[') {
  3449             if (strncmp(&buf[1], "L ", 1) == 0) {
  3450                 i = 2;
  3451                 while (isspace(buf[i]) || buf[i] == '=') {
  3452                     i++;
  3454                 MDlen = atoi(&buf[i]);
  3455                 fputs(buf, resp);
  3456                 continue;
  3459         /* Len = Length of the Input Message Length  ... */
  3460         if (strncmp(buf, "Len", 3) == 0) {
  3461             i = 3;
  3462             while (isspace(buf[i]) || buf[i] == '=') {
  3463                 i++;
  3465             if (msg) {
  3466                 PORT_ZFree(msg,msgLen);
  3467                 msg = NULL;
  3469             msgLen = atoi(&buf[i]); /* in bits */
  3470             if (msgLen%8 != 0) {
  3471                 fprintf(stderr, "SHA tests are incorrectly configured for "
  3472                     "BIT oriented implementations\n");
  3473                 goto loser;
  3475             msgLen = msgLen/8; /* convert to bytes */
  3476             fputs(buf, resp);
  3477             msg = PORT_ZAlloc(msgLen);
  3478             if (msg == NULL && msgLen != 0) {
  3479                 goto loser;
  3481             continue;
  3483         /* MSG = ... */
  3484         if (strncmp(buf, "Msg", 3) == 0) {
  3485             i = 3;
  3486             while (isspace(buf[i]) || buf[i] == '=') {
  3487                 i++;
  3489             for (j=0; j< msgLen; i+=2,j++) {
  3490                 hex_to_byteval(&buf[i], &msg[j]);
  3492            fputs(buf, resp);
  3493            /* calculate the Message Digest */ 
  3494            memset(MD, 0, sizeof MD);
  3495            if (sha_calcMD(MD, MDlen,   
  3496                           msg, msgLen) != SECSuccess) {
  3497                goto loser;
  3500            fputs("MD = ", resp);
  3501            to_hex_str(buf, MD, MDlen);
  3502            fputs(buf, resp);
  3503            fputc('\n', resp);
  3505            continue;
  3507         /* Seed = ... */
  3508         if (strncmp(buf, "Seed", 4) == 0) {
  3509             i = 4;
  3510             while (isspace(buf[i]) || buf[i] == '=') {
  3511                 i++;
  3513             for (j=0; j<sizeof seed; i+=2,j++) {
  3514                 hex_to_byteval(&buf[i], &seed[j]);
  3517             fputs(buf, resp);
  3518             fputc('\n', resp);
  3520             /* do the Monte Carlo test */
  3521             if (sha_mct_test(MDlen, seed, resp) != SECSuccess) {
  3522                 goto loser; 
  3525             continue;
  3528 loser:
  3529     if (req) {
  3530         fclose(req);
  3532     if (buf) {
  3533         PORT_ZFree(buf, bufSize);
  3535     if (msg) {
  3536         PORT_ZFree(msg, msgLen);
  3540 /****************************************************/
  3541 /* HMAC SHA-X calc                                  */
  3542 /* hmac_computed - the computed HMAC                */
  3543 /* hmac_length - the length of the computed HMAC    */
  3544 /* secret_key - secret key to HMAC                  */
  3545 /* secret_key_length - length of secret key,        */
  3546 /* message - message to HMAC                        */
  3547 /* message_length - length ofthe message            */
  3548 /****************************************************/
  3549 static SECStatus
  3550 hmac_calc(unsigned char *hmac_computed,
  3551           const unsigned int hmac_length,
  3552           const unsigned char *secret_key,
  3553           const unsigned int secret_key_length,
  3554           const unsigned char *message,
  3555           const unsigned int message_length,
  3556           const HASH_HashType hashAlg )
  3558     SECStatus hmac_status = SECFailure;
  3559     HMACContext *cx = NULL;
  3560     SECHashObject *hashObj = NULL;
  3561     unsigned int bytes_hashed = 0;
  3563     hashObj = (SECHashObject *) HASH_GetRawHashObject(hashAlg);
  3565     if (!hashObj) 
  3566         return( SECFailure );
  3568     cx = HMAC_Create(hashObj, secret_key, 
  3569                      secret_key_length, 
  3570                      PR_TRUE);  /* PR_TRUE for in FIPS mode */
  3572     if (cx == NULL) 
  3573         return( SECFailure );
  3575     HMAC_Begin(cx);
  3576     HMAC_Update(cx, message, message_length);
  3577     hmac_status = HMAC_Finish(cx, hmac_computed, &bytes_hashed, 
  3578                               hmac_length);
  3580     HMAC_Destroy(cx, PR_TRUE);
  3582     return( hmac_status );
  3585 /*
  3586  * Perform the HMAC Tests.
  3588  * reqfn is the pathname of the input REQUEST file.
  3590  * The output RESPONSE file is written to stdout.
  3591  */
  3592 void hmac_test(char *reqfn) 
  3594     unsigned int i, j;
  3595     size_t bufSize =      400;    /* MAX buffer size */
  3596     char *buf = NULL;  /* holds one line from the input REQUEST file.*/
  3597     unsigned int keyLen;          /* Key Length */  
  3598     unsigned char key[200];       /* key MAX size = 184 */
  3599     unsigned int msgLen = 128;    /* the length of the input  */
  3600                                   /*  Message is always 128 Bytes */
  3601     unsigned char *msg = NULL;    /* holds the message to digest.*/
  3602     unsigned int HMACLen;         /* the length of the HMAC Bytes  */
  3603     unsigned int TLen;            /* the length of the requested */
  3604                                   /* truncated HMAC Bytes */
  3605     unsigned char HMAC[HASH_LENGTH_MAX];  /* computed HMAC */
  3606     unsigned char expectedHMAC[HASH_LENGTH_MAX]; /* for .fax files that have */ 
  3607                                                  /* supplied known answer */
  3608     HASH_HashType hash_alg;       /* HMAC type */
  3611     FILE *req = NULL;  /* input stream from the REQUEST file */
  3612     FILE *resp;        /* output stream to the RESPONSE file */
  3614     buf = PORT_ZAlloc(bufSize);
  3615     if (buf == NULL) {
  3616         goto loser;
  3618     msg = PORT_ZAlloc(msgLen);
  3619     if (msg == NULL) {
  3620         goto loser;
  3623     req = fopen(reqfn, "r");
  3624     resp = stdout;
  3625     while (fgets(buf, bufSize, req) != NULL) {
  3626         if (strncmp(buf, "Mac", 3) == 0) {
  3627             i = 3;
  3628             while (isspace(buf[i]) || buf[i] == '=') {
  3629                 i++;
  3631             memset(expectedHMAC, 0, HASH_LENGTH_MAX);
  3632             for (j=0; isxdigit(buf[i]); i+=2,j++) { 
  3633                 hex_to_byteval(&buf[i], &expectedHMAC[j]);
  3635             if (memcmp(HMAC, expectedHMAC, TLen) != 0) {
  3636                 fprintf(stderr, "Generate failed:\n");
  3637                 fputs(  "   expected=", stderr);
  3638                 to_hex_str(buf, expectedHMAC, 
  3639                            TLen);
  3640                 fputs(buf, stderr);
  3641                 fputs("\n   generated=", stderr);
  3642                 to_hex_str(buf, HMAC, 
  3643                            TLen);
  3644                 fputs(buf, stderr);
  3645                 fputc('\n', stderr);
  3649         /* a comment or blank line */
  3650         if (buf[0] == '#' || buf[0] == '\n') {
  3651             fputs(buf, resp);
  3652             continue;
  3654         /* [L = Length of the MAC and HASH_type */
  3655         if (buf[0] == '[') {
  3656             if (strncmp(&buf[1], "L ", 1) == 0) {
  3657                 i = 2;
  3658                 while (isspace(buf[i]) || buf[i] == '=') {
  3659                     i++;
  3661                 /* HMACLen will get reused for Tlen */
  3662                 HMACLen = atoi(&buf[i]);
  3663 		hash_alg = sha_get_hashType(HMACLen*PR_BITS_PER_BYTE);
  3664 		if (hash_alg == HASH_AlgNULL) {
  3665 		    goto loser;
  3667                 fputs(buf, resp);
  3668                 continue;
  3671         /* Count = test iteration number*/
  3672         if (strncmp(buf, "Count ", 5) == 0) {    
  3673             /* count can just be put into resp file */
  3674             fputs(buf, resp);
  3675             /* zeroize the variables for the test with this data set */
  3676             keyLen = 0; 
  3677             TLen = 0;
  3678             memset(key, 0, sizeof key);     
  3679             memset(msg, 0, msgLen);
  3680             memset(HMAC, 0, sizeof HMAC);
  3681             continue;
  3683         /* KLen = Length of the Input Secret Key ... */
  3684         if (strncmp(buf, "Klen", 4) == 0) {
  3685             i = 4;
  3686             while (isspace(buf[i]) || buf[i] == '=') {
  3687                 i++;
  3689             keyLen = atoi(&buf[i]); /* in bytes */
  3690             fputs(buf, resp);
  3691             continue;
  3693         /* key = the secret key for the key to MAC */
  3694         if (strncmp(buf, "Key", 3) == 0) {
  3695             i = 3;
  3696             while (isspace(buf[i]) || buf[i] == '=') {
  3697                 i++;
  3699             for (j=0; j< keyLen; i+=2,j++) {
  3700                 hex_to_byteval(&buf[i], &key[j]);
  3702            fputs(buf, resp);
  3704         /* TLen = Length of the calculated HMAC */
  3705         if (strncmp(buf, "Tlen", 4) == 0) {
  3706             i = 4;
  3707             while (isspace(buf[i]) || buf[i] == '=') {
  3708                 i++;
  3710             TLen = atoi(&buf[i]); /* in bytes */
  3711             fputs(buf, resp);
  3712             continue;
  3714         /* MSG = to HMAC always 128 bytes for these tests */
  3715         if (strncmp(buf, "Msg", 3) == 0) {
  3716             i = 3;
  3717             while (isspace(buf[i]) || buf[i] == '=') {
  3718                 i++;
  3720             for (j=0; j< msgLen; i+=2,j++) {
  3721                 hex_to_byteval(&buf[i], &msg[j]);
  3723            fputs(buf, resp);
  3724            /* calculate the HMAC and output */ 
  3725            if (hmac_calc(HMAC, HMACLen, key, keyLen,   
  3726                          msg, msgLen, hash_alg) != SECSuccess) {
  3727                goto loser;
  3729            fputs("MAC = ", resp);
  3730            to_hex_str(buf, HMAC, TLen);
  3731            fputs(buf, resp);
  3732            fputc('\n', resp);
  3733            continue;
  3736 loser:
  3737     if (req) {
  3738         fclose(req);
  3740     if (buf) {
  3741         PORT_ZFree(buf, bufSize);
  3743     if (msg) {
  3744         PORT_ZFree(msg, msgLen);
  3748 /*
  3749  * Perform the DSA Key Pair Generation Test.
  3751  * reqfn is the pathname of the REQUEST file.
  3753  * The output RESPONSE file is written to stdout.
  3754  */
  3755 void
  3756 dsa_keypair_test(char *reqfn)
  3758     char buf[800];       /* holds one line from the input REQUEST file
  3759                          * or to the output RESPONSE file.
  3760                          * 800 to hold (384 public key (x2 for HEX) + 1'\n'
  3761                          */
  3762     FILE *dsareq;     /* input stream from the REQUEST file */
  3763     FILE *dsaresp;    /* output stream to the RESPONSE file */
  3764     int count;
  3765     int N;
  3766     int L;
  3767     int i;
  3768     PQGParams *pqg = NULL;
  3769     PQGVerify *vfy = NULL;
  3770     PRBool use_dsa1 = PR_FALSE;
  3771     int keySizeIndex;   /* index for valid key sizes */
  3773     dsareq = fopen(reqfn, "r");
  3774     dsaresp = stdout;
  3775     while (fgets(buf, sizeof buf, dsareq) != NULL) {
  3776         /* a comment or blank line */
  3777         if (buf[0] == '#' || buf[0] == '\n') {
  3778             fputs(buf, dsaresp);
  3779             continue;
  3782         /* [Mod = x] */
  3783         if (buf[0] == '[') {
  3784             if(pqg!=NULL) {
  3785                 PQG_DestroyParams(pqg);
  3786                 pqg = NULL;
  3788             if(vfy!=NULL) {
  3789                 PQG_DestroyVerify(vfy);
  3790                 vfy = NULL;
  3793             if (sscanf(buf, "[mod = L=%d, N=%d]", &L, &N) != 2) {
  3794 		use_dsa1 = PR_TRUE;
  3795                 if (sscanf(buf, "[mod = %d]", &L) != 1) {
  3796                     goto loser;
  3799             fputs(buf, dsaresp);
  3800             fputc('\n', dsaresp);
  3802 	    if (use_dsa1) {
  3803                 /*************************************************************
  3804                  * PQG_ParamGenSeedLen doesn't take a key size, it takes an 
  3805 		 * index that points to a valid key size.
  3806                  */
  3807                 keySizeIndex = PQG_PBITS_TO_INDEX(L);
  3808                 if(keySizeIndex == -1 || L<512 || L>1024) {
  3809                    fprintf(dsaresp,
  3810                         "DSA key size must be a multiple of 64 between 512 "
  3811                         "and 1024, inclusive");
  3812                     goto loser;
  3815                 /* Generate the parameters P, Q, and G */
  3816                 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
  3817                     &pqg, &vfy) != SECSuccess) {
  3818                     fprintf(dsaresp, 
  3819 				"ERROR: Unable to generate PQG parameters");
  3820                     goto loser;
  3822 	    } else {
  3823                 if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) {
  3824                     fprintf(dsaresp, 
  3825 				"ERROR: Unable to generate PQG parameters");
  3826                     goto loser;
  3830             /* output P, Q, and G */
  3831             to_hex_str(buf, pqg->prime.data, pqg->prime.len);
  3832             fprintf(dsaresp, "P = %s\n", buf);
  3833             to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
  3834             fprintf(dsaresp, "Q = %s\n", buf);
  3835             to_hex_str(buf, pqg->base.data, pqg->base.len);
  3836             fprintf(dsaresp, "G = %s\n\n", buf);
  3837             continue;
  3839         /* N = ...*/
  3840         if (buf[0] == 'N') {
  3842             if (sscanf(buf, "N = %d", &count) != 1) {
  3843                 goto loser;
  3845             /* Generate a DSA key, and output the key pair for N times */
  3846             for (i = 0; i < count; i++) {
  3847                 DSAPrivateKey *dsakey = NULL;
  3848                 if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
  3849                     fprintf(dsaresp, "ERROR: Unable to generate DSA key");
  3850                     goto loser;
  3852                 to_hex_str(buf, dsakey->privateValue.data,
  3853                            dsakey->privateValue.len);
  3854                 fprintf(dsaresp, "X = %s\n", buf);
  3855                 to_hex_str(buf, dsakey->publicValue.data,
  3856                            dsakey->publicValue.len);
  3857                 fprintf(dsaresp, "Y = %s\n\n", buf);
  3858                 PORT_FreeArena(dsakey->params.arena, PR_TRUE);
  3859                 dsakey = NULL;
  3861             continue;
  3865 loser:
  3866     fclose(dsareq);
  3869 /*
  3870  * pqg generation type
  3871  */
  3872 typedef enum {
  3873     FIPS186_1,/* Generate/Verify P,Q & G  according to FIPS 186-1 */
  3874     A_1_1_2, /* Generate Probable P & Q */
  3875     A_1_1_3, /* Verify Probable P & Q */
  3876     A_1_2_2, /* Verify Provable P & Q */
  3877     A_2_1,   /* Generate Unverifiable G */
  3878     A_2_2,   /* Assure Unverifiable G */
  3879     A_2_3,   /* Generate Verifiable G */
  3880     A_2_4    /* Verify Verifiable G */
  3881 } dsa_pqg_type;
  3883 /*
  3884  * Perform the DSA Domain Parameter Validation Test.
  3886  * reqfn is the pathname of the REQUEST file.
  3888  * The output RESPONSE file is written to stdout.
  3889  */
  3890 void
  3891 dsa_pqgver_test(char *reqfn)
  3893     char buf[800];      /* holds one line from the input REQUEST file
  3894                          * or to the output RESPONSE file.
  3895                          * 800 to hold (384 public key (x2 for HEX) + P = ...
  3896                          */
  3897     FILE *dsareq;     /* input stream from the REQUEST file */
  3898     FILE *dsaresp;    /* output stream to the RESPONSE file */
  3899     int N;
  3900     int L;
  3901     unsigned int i, j;
  3902     PQGParams pqg;
  3903     PQGVerify vfy;
  3904     unsigned int pghSize;        /* size for p, g, and h */
  3905     dsa_pqg_type type = FIPS186_1;
  3907     dsareq = fopen(reqfn, "r");
  3908     dsaresp = stdout;
  3909     memset(&pqg, 0, sizeof(pqg));
  3910     memset(&vfy, 0, sizeof(vfy));
  3912     while (fgets(buf, sizeof buf, dsareq) != NULL) {
  3913         /* a comment or blank line */
  3914         if (buf[0] == '#' || buf[0] == '\n') {
  3915             fputs(buf, dsaresp);
  3916             continue;
  3919         /* [A.xxxxx ] */
  3920         if (buf[0] == '['  && buf[1] == 'A') {
  3922 	    if (strncmp(&buf[1],"A.1.1.3",7) == 0) {
  3923 		type = A_1_1_3;
  3924 	    } else if (strncmp(&buf[1],"A.2.2",5) == 0) {
  3925 		type = A_2_2;
  3926 	    } else if (strncmp(&buf[1],"A.2.4",5) == 0) {
  3927 		type = A_2_4;
  3928 	    } else if (strncmp(&buf[1],"A.1.2.2",7) == 0) {
  3929 		type = A_1_2_2;
  3930 	    /* validate our output from PQGGEN */
  3931 	    } else if (strncmp(&buf[1],"A.1.1.2",7) == 0) {
  3932 		type = A_2_4; /* validate PQ and G together */
  3933 	    } else {
  3934 		fprintf(stderr, "Unknown dsa ver test %s\n", &buf[1]);
  3935 		exit(1);
  3938             fputs(buf, dsaresp);
  3939             continue;
  3943         /* [Mod = x] */
  3944         if (buf[0] == '[') {
  3946 	    if (type == FIPS186_1) {
  3947                 N=160;
  3948                 if (sscanf(buf, "[mod = %d]", &L) != 1) {
  3949                     goto loser;
  3951 	    } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) {
  3952 		goto loser;
  3955             if (pqg.prime.data) { /* P */
  3956                 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
  3958             if (pqg.subPrime.data) { /* Q */
  3959                 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
  3961             if (pqg.base.data) {    /* G */
  3962                 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
  3964             if (vfy.seed.data) {   /* seed */
  3965                 SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
  3967             if (vfy.h.data) {     /* H */
  3968                 SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
  3971             fputs(buf, dsaresp);
  3973             /*calculate the size of p, g, and h then allocate items  */
  3974             pghSize = L/8;
  3976 	    pqg.base.data = vfy.h.data = NULL;
  3977 	    vfy.seed.len = pqg.base.len = vfy.h.len = 0;
  3978             SECITEM_AllocItem(NULL, &pqg.prime, pghSize);
  3979             SECITEM_AllocItem(NULL, &vfy.seed, pghSize*3);
  3980 	    if (type == A_2_2) {
  3981 		SECITEM_AllocItem(NULL, &vfy.h, pghSize);
  3982 	    	vfy.h.len = pghSize;
  3983 	    } else if (type == A_2_4) {
  3984 		SECITEM_AllocItem(NULL, &vfy.h, 1);
  3985 	    	vfy.h.len = 1;
  3987             pqg.prime.len = pghSize;
  3988             /* q is always N bits */
  3989             SECITEM_AllocItem(NULL, &pqg.subPrime, N/8);
  3990             pqg.subPrime.len = N/8;
  3991             vfy.counter = -1;
  3993             continue;
  3995         /* P = ... */
  3996         if (buf[0] == 'P') {
  3997             i = 1;
  3998             while (isspace(buf[i]) || buf[i] == '=') {
  3999                 i++;
  4001             for (j=0; j< pqg.prime.len; i+=2,j++) {
  4002                 hex_to_byteval(&buf[i], &pqg.prime.data[j]);
  4005             fputs(buf, dsaresp);
  4006             continue;
  4009         /* Q = ... */
  4010         if (buf[0] == 'Q') {
  4011             i = 1;
  4012             while (isspace(buf[i]) || buf[i] == '=') {
  4013                 i++;
  4015             for (j=0; j< pqg.subPrime.len; i+=2,j++) {
  4016                 hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
  4019             fputs(buf, dsaresp);
  4020             continue;
  4023         /* G = ... */
  4024         if (buf[0] == 'G') {
  4025             i = 1;
  4026             if (pqg.base.data) {
  4027                 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
  4029             SECITEM_AllocItem(NULL, &pqg.base, pghSize);
  4030             while (isspace(buf[i]) || buf[i] == '=') {
  4031                 i++;
  4033             for (j=0; j< pqg.base.len; i+=2,j++) {
  4034                 hex_to_byteval(&buf[i], &pqg.base.data[j]);
  4037             fputs(buf, dsaresp);
  4038             continue;
  4041         /* Seed = ...  or domain_parameter_seed = ... */
  4042         if (strncmp(buf, "Seed", 4) == 0) {
  4043             i = 4;
  4044         } else if (strncmp(buf, "domain_parameter_seed", 21) == 0) {
  4045 	    i = 21;
  4046 	} else if (strncmp(buf,"firstseed",9) == 0) {
  4047 	    i = 9;
  4048 	} else {
  4049 	    i = 0;
  4051 	if (i) {
  4052             while (isspace(buf[i]) || buf[i] == '=') {
  4053                 i++;
  4055             for (j=0; isxdigit(buf[i]); i+=2,j++) {
  4056                 hex_to_byteval(&buf[i], &vfy.seed.data[j]);
  4058 	    vfy.seed.len = j;
  4060             fputs(buf, dsaresp);
  4061 	    if (type == A_2_4) {
  4062 		SECStatus result;
  4064                 /* Verify the Parameters */
  4065                 SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
  4066                 if (rv != SECSuccess) {
  4067                     goto loser;
  4069                 if (result == SECSuccess) {
  4070                     fprintf(dsaresp, "Result = P\n");
  4071                 } else {
  4072                     fprintf(dsaresp, "Result = F\n");
  4075             continue;
  4077 	if ((strncmp(buf,"pseed",5) == 0) ||
  4078 	    (strncmp(buf,"qseed",5) == 0))
  4080 	    i = 5;
  4081             while (isspace(buf[i]) || buf[i] == '=') {
  4082                 i++;
  4084             for (j=vfy.seed.len; isxdigit(buf[i]); i+=2,j++) {
  4085                 hex_to_byteval(&buf[i], &vfy.seed.data[j]);
  4087 	    vfy.seed.len = j;
  4088             fputs(buf, dsaresp);
  4090             continue;
  4092         if (strncmp(buf, "index", 4) == 0) {
  4093 	    i=5;
  4094             while (isspace(buf[i]) || buf[i] == '=') {
  4095                 i++;
  4097 	    hex_to_byteval(&buf[i], &vfy.h.data[0]);
  4098 	    vfy.h.len = 1;
  4099             fputs(buf, dsaresp);
  4102         /* c = ...  or counter=*/
  4103         if (buf[0] == 'c')  {
  4104 	    if (strncmp(buf,"counter", 7) == 0) {
  4105                 if (sscanf(buf, "counter = %u", &vfy.counter) != 1) {
  4106                     goto loser;
  4108 	    } else {
  4109                 if (sscanf(buf, "c = %u", &vfy.counter) != 1) {
  4110                     goto loser;
  4114             fputs(buf, dsaresp);
  4115             if (type == A_1_1_3) {
  4116 		SECStatus result;
  4117                 /* only verify P and Q, we have everything now. do it */
  4118                 SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
  4119                 if (rv != SECSuccess) {
  4120                     goto loser;
  4122                 if (result == SECSuccess) {
  4123                     fprintf(dsaresp, "Result = P\n");
  4124                 } else {
  4125                     fprintf(dsaresp, "Result = F\n");
  4127                 fprintf(dsaresp, "\n");
  4129             continue;
  4131 	if (strncmp(buf,"pgen_counter", 12) == 0) {
  4132             if (sscanf(buf, "pgen_counter = %u", &vfy.counter) != 1) {
  4133                 goto loser;
  4135             fputs(buf, dsaresp);
  4136 	    continue;
  4138 	if (strncmp(buf,"qgen_counter", 12) == 0) {
  4139             fputs(buf, dsaresp);
  4140             if (type == A_1_2_2) {
  4141 		SECStatus result;
  4142                 /* only verify P and Q, we have everything now. do it */
  4143                 SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
  4144                 if (rv != SECSuccess) {
  4145                     goto loser;
  4147                 if (result == SECSuccess) {
  4148                     fprintf(dsaresp, "Result = P\n");
  4149                 } else {
  4150                     fprintf(dsaresp, "Result = F\n");
  4152                 fprintf(dsaresp, "\n");
  4154 	    continue;
  4156         /* H = ... */
  4157         if (buf[0] == 'H') {
  4158             SECStatus rv, result = SECFailure;
  4160             i = 1;
  4161             while (isspace(buf[i]) || buf[i] == '=') {
  4162                 i++;
  4164             for (j=0; isxdigit(buf[i]); i+=2,j++) {
  4165                 hex_to_byteval(&buf[i], &vfy.h.data[j]);
  4167 	    vfy.h.len = j;
  4168             fputs(buf, dsaresp);
  4170 	    /* this should be a byte value. Remove the leading zeros. If
  4171 	     * it doesn't reduce to a byte, PQG_VerifyParams will catch it 
  4172 	    if (type == A_2_2) {
  4173 		data_save = vfy.h.data;
  4174 		while(vfy.h.data[0] && (vfy.h.len > 1)) {
  4175 			vfy.h.data++;
  4176 			vfy.h.len--;
  4178 	    } */
  4180             /* Verify the Parameters */
  4181             rv = PQG_VerifyParams(&pqg, &vfy, &result);
  4182             if (rv != SECSuccess) {
  4183                 goto loser;
  4185             if (result == SECSuccess) {
  4186                 fprintf(dsaresp, "Result = P\n");
  4187             } else {
  4188                 fprintf(dsaresp, "Result = F\n");
  4190             fprintf(dsaresp, "\n");
  4191             continue;
  4194 loser:
  4195     fclose(dsareq);
  4196     if (pqg.prime.data) { /* P */
  4197         SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
  4199     if (pqg.subPrime.data) { /* Q */
  4200         SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
  4202     if (pqg.base.data) {    /* G */
  4203         SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
  4205     if (vfy.seed.data) {   /* seed */
  4206         SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
  4208     if (vfy.h.data) {     /* H */
  4209         SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
  4214 /*
  4215  * Perform the DSA Public Key Validation Test.
  4217  * reqfn is the pathname of the REQUEST file.
  4219  * The output RESPONSE file is written to stdout.
  4220  */
  4221 void
  4222 dsa_pqggen_test(char *reqfn)
  4224     char buf[800];      /* holds one line from the input REQUEST file
  4225                          * or to the output RESPONSE file.
  4226                          * 800 to hold seed = (384 public key (x2 for HEX)
  4227                          */
  4228     FILE *dsareq;     /* input stream from the REQUEST file */
  4229     FILE *dsaresp;    /* output stream to the RESPONSE file */
  4230     int count;            /* number of times to generate parameters */
  4231     int N;
  4232     int L;
  4233     int i;
  4234     unsigned int j;
  4235     PQGParams *pqg = NULL;
  4236     PQGVerify *vfy = NULL;
  4237     unsigned int keySizeIndex;
  4238     dsa_pqg_type type = FIPS186_1;
  4240     dsareq = fopen(reqfn, "r");
  4241     dsaresp = stdout;
  4242     while (fgets(buf, sizeof buf, dsareq) != NULL) {
  4243         /* a comment or blank line */
  4244         if (buf[0] == '#' || buf[0] == '\n') {
  4245             fputs(buf, dsaresp);
  4246             continue;
  4249         /* [A.xxxxx ] */
  4250         if (buf[0] == '['  && buf[1] == 'A') {
  4251 	    if (strncmp(&buf[1],"A.1.1.2",7) == 0) {
  4252 		type = A_1_1_2;
  4253 	    } else if (strncmp(&buf[1],"A.2.1",5) == 0) {
  4254 		fprintf(stderr, "NSS only Generates G with P&Q\n");
  4255 		exit(1);
  4256 	    } else if (strncmp(&buf[1],"A.2.3",5) == 0) {
  4257 		fprintf(stderr, "NSS only Generates G with P&Q\n");
  4258 		exit(1);
  4259 	    } else if (strncmp(&buf[1],"A.1.2.1",7) == 0) {
  4260 		fprintf(stderr, "NSS does not support Shawe-Taylor Primes\n");
  4261 		exit(1);
  4262 	    } else {
  4263 		fprintf(stderr, "Unknown dsa ver test %s\n", &buf[1]);
  4264 		exit(1);
  4266             fputs(buf, dsaresp);
  4267             continue;
  4270         /* [Mod = ... ] */
  4271         if (buf[0] == '[') {
  4273 	    if (type == FIPS186_1) {
  4274                 N=160;
  4275                 if (sscanf(buf, "[mod = %d]", &L) != 1) {
  4276                     goto loser;
  4278 	    } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) {
  4279 		goto loser;
  4282             fputs(buf, dsaresp);
  4283             fputc('\n', dsaresp);
  4285 	    if (type == FIPS186_1) {
  4286                 /************************************************************
  4287                  * PQG_ParamGenSeedLen doesn't take a key size, it takes an
  4288                  * index that points to a valid key size.
  4289                  */
  4290                 keySizeIndex = PQG_PBITS_TO_INDEX(L);
  4291                 if(keySizeIndex == -1 || L<512 || L>1024) {
  4292                    fprintf(dsaresp,
  4293                         "DSA key size must be a multiple of 64 between 512 "
  4294                         "and 1024, inclusive");
  4295                     goto loser;
  4298             continue;
  4300         /* N = ... */
  4301         if (buf[0] == 'N') {
  4302             if (sscanf(buf, "N = %d", &count) != 1) {
  4303                 goto loser;
  4305             for (i = 0; i < count; i++) {
  4306                 SECStatus rv;
  4308                 if (type == FIPS186_1) {
  4309                     rv = PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
  4310                          &pqg, &vfy);
  4311                 } else {
  4312                     rv = PQG_ParamGenV2(L, N, N, &pqg, &vfy);
  4314                 if (rv != SECSuccess) {
  4315                     fprintf(dsaresp,
  4316                             "ERROR: Unable to generate PQG parameters");
  4317                     goto loser;
  4319                 to_hex_str(buf, pqg->prime.data, pqg->prime.len);
  4320                 fprintf(dsaresp, "P = %s\n", buf);
  4321                 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
  4322                 fprintf(dsaresp, "Q = %s\n", buf);
  4323                 to_hex_str(buf, pqg->base.data, pqg->base.len);
  4324                 fprintf(dsaresp, "G = %s\n", buf);
  4325 		if (type == FIPS186_1) {
  4326                     to_hex_str(buf, vfy->seed.data, vfy->seed.len);
  4327                     fprintf(dsaresp, "Seed = %s\n", buf);
  4328                     fprintf(dsaresp, "c = %d\n", vfy->counter);
  4329                     to_hex_str(buf, vfy->h.data, vfy->h.len);
  4330                     fputs("H = ", dsaresp);
  4331                     for (j=vfy->h.len; j< pqg->prime.len; j++) {
  4332                 	fprintf(dsaresp, "00");
  4334                     fprintf(dsaresp, "%s\n", buf);
  4335 		} else {
  4336                     fprintf(dsaresp, "counter = %d\n", vfy->counter);
  4337 		    fprintf(dsaresp, "index = %02x\n", vfy->h.data[0]);
  4338                     to_hex_str(buf, vfy->seed.data, vfy->seed.len);
  4339                     fprintf(dsaresp, "domain_parameter_seed = %s\n", buf);
  4341                 fputc('\n', dsaresp);
  4342                 if(pqg!=NULL) {
  4343                     PQG_DestroyParams(pqg);
  4344                     pqg = NULL;
  4346                 if(vfy!=NULL) {
  4347                     PQG_DestroyVerify(vfy);
  4348                     vfy = NULL;
  4352             continue;
  4356 loser:
  4357     fclose(dsareq);
  4358     if(pqg!=NULL) {
  4359         PQG_DestroyParams(pqg);
  4361     if(vfy!=NULL) {
  4362         PQG_DestroyVerify(vfy);
  4367 /*
  4368  * Perform the DSA Signature Generation Test.
  4370  * reqfn is the pathname of the REQUEST file.
  4372  * The output RESPONSE file is written to stdout.
  4373  */
  4374 void
  4375 dsa_siggen_test(char *reqfn)
  4377     char buf[800];      /* holds one line from the input REQUEST file
  4378                          * or to the output RESPONSE file.
  4379                          * max for Msg = ....
  4380                          */
  4381     FILE *dsareq;     /* input stream from the REQUEST file */
  4382     FILE *dsaresp;    /* output stream to the RESPONSE file */
  4383     int modulus;
  4384     int L;
  4385     int N;
  4386     int i, j;
  4387     PRBool use_dsa1 = PR_FALSE;
  4388     PQGParams *pqg = NULL;
  4389     PQGVerify *vfy = NULL;
  4390     DSAPrivateKey *dsakey = NULL;
  4391     int keySizeIndex;     /* index for valid key sizes */
  4392     unsigned char hashBuf[HASH_LENGTH_MAX];  /* SHA-x hash (160-512 bits) */
  4393     unsigned char sig[DSA_MAX_SIGNATURE_LEN];
  4394     SECItem digest, signature;
  4395     HASH_HashType hashType = HASH_AlgNULL;
  4396     int hashNum = 0;
  4398     dsareq = fopen(reqfn, "r");
  4399     dsaresp = stdout;
  4401     while (fgets(buf, sizeof buf, dsareq) != NULL) {
  4402         /* a comment or blank line */
  4403         if (buf[0] == '#' || buf[0] == '\n') {
  4404             fputs(buf, dsaresp);
  4405             continue;
  4408         /* [Mod = x] */
  4409         if (buf[0] == '[') {
  4410             if(pqg!=NULL) {
  4411                 PQG_DestroyParams(pqg);
  4412                 pqg = NULL;
  4414             if(vfy!=NULL) {
  4415                 PQG_DestroyVerify(vfy);
  4416                 vfy = NULL;
  4418             if (dsakey != NULL) {
  4419                     PORT_FreeArena(dsakey->params.arena, PR_TRUE);
  4420                     dsakey = NULL;
  4423             if (sscanf(buf, "[mod = L=%d,  N=%d, SHA-%d]", &L, & N,
  4424                 &hashNum) != 3) {
  4425                 use_dsa1 = PR_TRUE;
  4426 		hashNum = 1;
  4427                 if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
  4428                     goto loser;
  4431             fputs(buf, dsaresp);
  4432             fputc('\n', dsaresp);
  4434             /****************************************************************
  4435             * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
  4436             * that points to a valid key size.
  4437             */
  4438             if (use_dsa1) {
  4439                 keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
  4440                 if(keySizeIndex == -1 || modulus<512 || modulus>1024) {
  4441                     fprintf(dsaresp,
  4442                         "DSA key size must be a multiple of 64 between 512 "
  4443                         "and 1024, inclusive");
  4444                     goto loser;
  4446                 /* Generate PQG and output PQG */
  4447                 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
  4448                     &pqg, &vfy) != SECSuccess) {
  4449                     fprintf(dsaresp, 
  4450                             "ERROR: Unable to generate PQG parameters");
  4451                     goto loser;
  4453             } else {
  4454                 if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) {
  4455                     fprintf(dsaresp, 
  4456                             "ERROR: Unable to generate PQG parameters");
  4457                     goto loser;
  4460             to_hex_str(buf, pqg->prime.data, pqg->prime.len);
  4461             fprintf(dsaresp, "P = %s\n", buf);
  4462             to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
  4463             fprintf(dsaresp, "Q = %s\n", buf);
  4464             to_hex_str(buf, pqg->base.data, pqg->base.len);
  4465             fprintf(dsaresp, "G = %s\n", buf);
  4467             /* create DSA Key */
  4468             if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
  4469                 fprintf(dsaresp, "ERROR: Unable to generate DSA key");
  4470                 goto loser;
  4473 	    hashType = sha_get_hashType(hashNum);
  4474 	    if (hashType == HASH_AlgNULL) {
  4475 		fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)",hashNum);
  4476 		goto loser;
  4478             continue;
  4481         /* Msg = ... */
  4482         if (strncmp(buf, "Msg", 3) == 0) {
  4483             unsigned char msg[128]; /* MAX msg 128 */
  4484             unsigned int len = 0;
  4486 	    if (hashType == HASH_AlgNULL) {
  4487 		fprintf(dsaresp, "ERROR: Hash Alg not set");
  4488 		goto loser;
  4491             memset(hashBuf, 0, sizeof hashBuf);
  4492             memset(sig,  0, sizeof sig);
  4494             i = 3;
  4495             while (isspace(buf[i]) || buf[i] == '=') {
  4496                 i++;
  4498             for (j=0; isxdigit(buf[i]); i+=2,j++) {
  4499                 hex_to_byteval(&buf[i], &msg[j]);
  4501             if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) {
  4502                  fprintf(dsaresp, "ERROR: Unable to generate SHA% digest", 
  4503 			 hashNum);
  4504                  goto loser;
  4508             digest.type = siBuffer;
  4509             digest.data = hashBuf;
  4510             digest.len = fips_hashLen(hashType);
  4511             signature.type = siBuffer;
  4512             signature.data = sig;
  4513             signature.len = sizeof sig;
  4515             if (DSA_SignDigest(dsakey, &signature, &digest) != SECSuccess) {
  4516                 fprintf(dsaresp, "ERROR: Unable to generate DSA signature");
  4517                 goto loser;
  4519             len = signature.len;
  4520             if (len%2 != 0) {
  4521                 goto loser;
  4523             len = len/2;
  4525             /* output the orginal Msg, and generated Y, R, and S */
  4526             fputs(buf, dsaresp);
  4527             to_hex_str(buf, dsakey->publicValue.data,
  4528                        dsakey->publicValue.len);
  4529             fprintf(dsaresp, "Y = %s\n", buf);
  4530             to_hex_str(buf, &signature.data[0], len);
  4531             fprintf(dsaresp, "R = %s\n", buf);
  4532             to_hex_str(buf, &signature.data[len], len);
  4533             fprintf(dsaresp, "S = %s\n", buf);
  4534             fputc('\n', dsaresp);
  4535             continue;
  4539 loser:
  4540     fclose(dsareq);
  4541     if(pqg != NULL) {
  4542         PQG_DestroyParams(pqg);
  4543         pqg = NULL;
  4545     if(vfy != NULL) {
  4546         PQG_DestroyVerify(vfy);
  4547         vfy = NULL;
  4549     if (dsakey) {
  4550         PORT_FreeArena(dsakey->params.arena, PR_TRUE);
  4551         dsakey = NULL;
  4555  /*
  4556  * Perform the DSA Signature Verification Test.
  4558  * reqfn is the pathname of the REQUEST file.
  4560  * The output RESPONSE file is written to stdout.
  4561  */
  4562 void
  4563 dsa_sigver_test(char *reqfn)
  4565     char buf[800];       /* holds one line from the input REQUEST file
  4566                          * or to the output RESPONSE file.
  4567                          * max for Msg = ....
  4568                          */
  4569     FILE *dsareq;     /* input stream from the REQUEST file */
  4570     FILE *dsaresp;    /* output stream to the RESPONSE file */
  4571     int L;
  4572     int N;
  4573     unsigned int i, j;
  4574     SECItem digest, signature;
  4575     DSAPublicKey pubkey;
  4576     unsigned int pgySize;        /* size for p, g, and y */
  4577     unsigned char hashBuf[HASH_LENGTH_MAX];  /* SHA-x hash (160-512 bits) */
  4578     unsigned char sig[DSA_MAX_SIGNATURE_LEN];
  4579     HASH_HashType hashType = HASH_AlgNULL;
  4580     int hashNum = 0;
  4582     dsareq = fopen(reqfn, "r");
  4583     dsaresp = stdout;
  4584     memset(&pubkey, 0, sizeof(pubkey));
  4586     while (fgets(buf, sizeof buf, dsareq) != NULL) {
  4587         /* a comment or blank line */
  4588         if (buf[0] == '#' || buf[0] == '\n') {
  4589             fputs(buf, dsaresp);
  4590             continue;
  4593         /* [Mod = x] */
  4594         if (buf[0] == '[') {
  4596             if (sscanf(buf, "[mod = L=%d,  N=%d, SHA-%d]", &L, & N,
  4597                 &hashNum) != 3) {
  4598 		N=160;
  4599 		hashNum = 1;
  4600                 if (sscanf(buf, "[mod = %d]", &L) != 1) {
  4601                     goto loser;
  4605             if (pubkey.params.prime.data) { /* P */
  4606                 SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
  4608             if (pubkey.params.subPrime.data) { /* Q */
  4609                 SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
  4611             if (pubkey.params.base.data) {    /* G */
  4612                 SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
  4614             if (pubkey.publicValue.data) {    /* Y */
  4615                 SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
  4617             fputs(buf, dsaresp);
  4619             /* calculate the size of p, g, and y then allocate items */
  4620             pgySize = L/8;
  4621             SECITEM_AllocItem(NULL, &pubkey.params.prime, pgySize);
  4622             SECITEM_AllocItem(NULL, &pubkey.params.base, pgySize);
  4623             SECITEM_AllocItem(NULL, &pubkey.publicValue, pgySize);
  4624             pubkey.params.prime.len = pubkey.params.base.len = pgySize;
  4625             pubkey.publicValue.len = pgySize;
  4627             /* q always N/8 bytes */
  4628             SECITEM_AllocItem(NULL, &pubkey.params.subPrime, N/8);
  4629             pubkey.params.subPrime.len = N/8;
  4631 	    hashType = sha_get_hashType(hashNum);
  4632 	    if (hashType == HASH_AlgNULL) {
  4633 		fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)",hashNum);
  4634 		goto loser;
  4637             continue;
  4639         /* P = ... */
  4640         if (buf[0] == 'P') {
  4641             i = 1;
  4642             while (isspace(buf[i]) || buf[i] == '=') {
  4643                 i++;
  4645             memset(pubkey.params.prime.data, 0, pubkey.params.prime.len);
  4646             for (j=0; j< pubkey.params.prime.len; i+=2,j++) {
  4647                 hex_to_byteval(&buf[i], &pubkey.params.prime.data[j]);
  4650             fputs(buf, dsaresp);
  4651             continue;
  4654         /* Q = ... */
  4655         if (buf[0] == 'Q') {
  4656             i = 1;
  4657             while (isspace(buf[i]) || buf[i] == '=') {
  4658                 i++;
  4660             memset(pubkey.params.subPrime.data, 0, pubkey.params.subPrime.len);
  4661             for (j=0; j< pubkey.params.subPrime.len; i+=2,j++) {
  4662                 hex_to_byteval(&buf[i], &pubkey.params.subPrime.data[j]);
  4665             fputs(buf, dsaresp);
  4666             continue;
  4669         /* G = ... */
  4670         if (buf[0] == 'G') {
  4671             i = 1;
  4672             while (isspace(buf[i]) || buf[i] == '=') {
  4673                 i++;
  4675             memset(pubkey.params.base.data, 0, pubkey.params.base.len);
  4676             for (j=0; j< pubkey.params.base.len; i+=2,j++) {
  4677                 hex_to_byteval(&buf[i], &pubkey.params.base.data[j]);
  4680             fputs(buf, dsaresp);
  4681             continue;
  4684         /* Msg = ... */
  4685         if (strncmp(buf, "Msg", 3) == 0) {
  4686             unsigned char msg[128]; /* MAX msg 128 */
  4687             memset(hashBuf, 0, sizeof hashBuf);
  4689 	    if (hashType == HASH_AlgNULL) {
  4690 		fprintf(dsaresp, "ERROR: Hash Alg not set");
  4691 		goto loser;
  4694             i = 3;
  4695             while (isspace(buf[i]) || buf[i] == '=') {
  4696                 i++;
  4698             for (j=0; isxdigit(buf[i]); i+=2,j++) {
  4699                 hex_to_byteval(&buf[i], &msg[j]);
  4701             if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) {
  4702                 fprintf(dsaresp, "ERROR: Unable to generate SHA-%d digest",
  4703 								hashNum);
  4704                 goto loser;
  4707             fputs(buf, dsaresp);
  4708             continue;
  4711         /* Y = ... */
  4712         if (buf[0] == 'Y') {
  4713             i = 1;
  4714             while (isspace(buf[i]) || buf[i] == '=') {
  4715                 i++;
  4717             memset(pubkey.publicValue.data, 0, pubkey.params.subPrime.len);
  4718             for (j=0; j< pubkey.publicValue.len; i+=2,j++) {
  4719                 hex_to_byteval(&buf[i], &pubkey.publicValue.data[j]);
  4722             fputs(buf, dsaresp);
  4723             continue;
  4726         /* R = ... */
  4727         if (buf[0] == 'R') {
  4728             memset(sig,  0, sizeof sig);
  4729             i = 1;
  4730             while (isspace(buf[i]) || buf[i] == '=') {
  4731                 i++;
  4733             for (j=0; j< pubkey.params.subPrime.len; i+=2,j++) {
  4734                 hex_to_byteval(&buf[i], &sig[j]);
  4737             fputs(buf, dsaresp);
  4738             continue;
  4741         /* S = ... */
  4742         if (buf[0] == 'S') {
  4743 	    if (hashType == HASH_AlgNULL) {
  4744 		fprintf(dsaresp, "ERROR: Hash Alg not set");
  4745 		goto loser;
  4748             i = 1;
  4749             while (isspace(buf[i]) || buf[i] == '=') {
  4750                 i++;
  4752             for (j=pubkey.params.subPrime.len; 
  4753 				j< pubkey.params.subPrime.len*2; i+=2,j++) {
  4754                 hex_to_byteval(&buf[i], &sig[j]);
  4756             fputs(buf, dsaresp);
  4758             digest.type = siBuffer;
  4759             digest.data = hashBuf;
  4760             digest.len = fips_hashLen(hashType);
  4761             signature.type = siBuffer;
  4762             signature.data = sig;
  4763             signature.len = pubkey.params.subPrime.len*2;
  4765             if (DSA_VerifyDigest(&pubkey, &signature, &digest) == SECSuccess) {
  4766                 fprintf(dsaresp, "Result = P\n");
  4767             } else {
  4768                 fprintf(dsaresp, "Result = F\n");
  4770 	    fprintf(dsaresp, "\n");
  4771             continue;
  4774 loser:
  4775     fclose(dsareq);
  4776     if (pubkey.params.prime.data) { /* P */
  4777         SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
  4779     if (pubkey.params.subPrime.data) { /* Q */
  4780         SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
  4782     if (pubkey.params.base.data) {    /* G */
  4783         SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
  4785     if (pubkey.publicValue.data) {    /* Y */
  4786         SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
  4790 /*
  4791  * Perform the RSA Signature Generation Test.
  4793  * reqfn is the pathname of the REQUEST file.
  4795  * The output RESPONSE file is written to stdout.
  4796  */
  4797 void
  4798 rsa_siggen_test(char *reqfn)
  4800     char buf[2*RSA_MAX_TEST_MODULUS_BYTES+1];
  4801                         /* buf holds one line from the input REQUEST file
  4802                          * or to the output RESPONSE file.
  4803                          * 2x for HEX output + 1 for \n
  4804                          */
  4805     FILE *rsareq;     /* input stream from the REQUEST file */
  4806     FILE *rsaresp;    /* output stream to the RESPONSE file */
  4807     int i, j;
  4808     unsigned char  sha[HASH_LENGTH_MAX];    /* SHA digest */
  4809     unsigned int   shaLength = 0;           /* length of SHA */
  4810     HASH_HashType  shaAlg = HASH_AlgNULL;   /* type of SHA Alg */
  4811     SECOidTag      shaOid = SEC_OID_UNKNOWN;
  4812     int modulus;                                /* the Modulus size */
  4813     int  publicExponent  = DEFAULT_RSA_PUBLIC_EXPONENT;
  4814     SECItem pe = {0, 0, 0 };
  4815     unsigned char pubEx[4];
  4816     int peCount = 0;
  4818     RSAPrivateKey  *rsaBlapiPrivKey = NULL;   /* holds RSA private and
  4819                                               * public keys */
  4820     RSAPublicKey   *rsaBlapiPublicKey = NULL; /* hold RSA public key */
  4822     rsareq = fopen(reqfn, "r");
  4823     rsaresp = stdout;
  4825     /* calculate the exponent */
  4826     for (i=0; i < 4; i++) {
  4827         if (peCount || (publicExponent &
  4828                 ((unsigned long)0xff000000L >> (i*8)))) {
  4829             pubEx[peCount] =
  4830                 (unsigned char)((publicExponent >> (3-i)*8) & 0xff);
  4831             peCount++;
  4834     pe.len = peCount;
  4835     pe.data = &pubEx[0];
  4836     pe.type = siBuffer;
  4838     while (fgets(buf, sizeof buf, rsareq) != NULL) {
  4839         /* a comment or blank line */
  4840         if (buf[0] == '#' || buf[0] == '\n') {
  4841             fputs(buf, rsaresp);
  4842             continue;
  4845         /* [mod = ...] */
  4846         if (buf[0] == '[') {
  4848             if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
  4849                 goto loser;
  4851             if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
  4852                 fprintf(rsaresp,"ERROR: modulus greater than test maximum\n");
  4853                 goto loser;
  4856             fputs(buf, rsaresp);
  4858             if (rsaBlapiPrivKey != NULL) {
  4859                 PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
  4860                 rsaBlapiPrivKey = NULL;
  4861                 rsaBlapiPublicKey = NULL;
  4864             rsaBlapiPrivKey = RSA_NewKey(modulus, &pe);
  4865             if (rsaBlapiPrivKey == NULL) {
  4866                 fprintf(rsaresp, "Error unable to create RSA key\n");
  4867                 goto loser;
  4870             to_hex_str(buf, rsaBlapiPrivKey->modulus.data,
  4871                        rsaBlapiPrivKey->modulus.len);
  4872             fprintf(rsaresp, "\nn = %s\n\n", buf);
  4873             to_hex_str(buf, rsaBlapiPrivKey->publicExponent.data,
  4874                        rsaBlapiPrivKey->publicExponent.len);
  4875             fprintf(rsaresp, "e = %s\n", buf);
  4876             /* convert private key to public key.  Memory
  4877              * is freed with private key's arena  */
  4878             rsaBlapiPublicKey = (RSAPublicKey *)PORT_ArenaAlloc(
  4879                                                   rsaBlapiPrivKey->arena,
  4880                                                   sizeof(RSAPublicKey));
  4882             rsaBlapiPublicKey->modulus.len = rsaBlapiPrivKey->modulus.len;
  4883             rsaBlapiPublicKey->modulus.data = rsaBlapiPrivKey->modulus.data;
  4884             rsaBlapiPublicKey->publicExponent.len =
  4885                 rsaBlapiPrivKey->publicExponent.len;
  4886             rsaBlapiPublicKey->publicExponent.data =
  4887                 rsaBlapiPrivKey->publicExponent.data;
  4888             continue;
  4891         /* SHAAlg = ... */
  4892         if (strncmp(buf, "SHAAlg", 6) == 0) {
  4893            i = 6;
  4894            while (isspace(buf[i]) || buf[i] == '=') {
  4895                i++;
  4897            /* set the SHA Algorithm */
  4898            if (strncmp(&buf[i], "SHA1", 4) == 0) {
  4899                 shaAlg = HASH_AlgSHA1;
  4900            } else if (strncmp(&buf[i], "SHA224", 6) == 0) {
  4901                 shaAlg = HASH_AlgSHA224;
  4902            } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
  4903                 shaAlg = HASH_AlgSHA256;
  4904            } else if (strncmp(&buf[i], "SHA384", 6)== 0) {
  4905                shaAlg = HASH_AlgSHA384;
  4906            } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
  4907                shaAlg = HASH_AlgSHA512;
  4908            } else {
  4909                fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
  4910                goto loser;
  4912            fputs(buf, rsaresp);
  4913            continue;
  4916         /* Msg = ... */
  4917         if (strncmp(buf, "Msg", 3) == 0) {
  4919             unsigned char msg[128]; /* MAX msg 128 */
  4920             unsigned int rsa_bytes_signed;
  4921             unsigned char rsa_computed_signature[RSA_MAX_TEST_MODULUS_BYTES];
  4922             SECStatus       rv = SECFailure;
  4923             NSSLOWKEYPublicKey  * rsa_public_key;
  4924             NSSLOWKEYPrivateKey * rsa_private_key;
  4925             NSSLOWKEYPrivateKey   low_RSA_private_key = { NULL,
  4926                                                 NSSLOWKEYRSAKey, };
  4927             NSSLOWKEYPublicKey    low_RSA_public_key = { NULL,
  4928                                                 NSSLOWKEYRSAKey, };
  4930             low_RSA_private_key.u.rsa = *rsaBlapiPrivKey;
  4931             low_RSA_public_key.u.rsa = *rsaBlapiPublicKey;
  4933             rsa_private_key = &low_RSA_private_key;
  4934             rsa_public_key = &low_RSA_public_key;
  4936             memset(sha, 0, sizeof sha);
  4937             memset(msg, 0, sizeof msg);
  4938             rsa_bytes_signed = 0;
  4939             memset(rsa_computed_signature, 0, sizeof rsa_computed_signature);
  4941             i = 3;
  4942             while (isspace(buf[i]) || buf[i] == '=') {
  4943                 i++;
  4945             for (j=0; isxdigit(buf[i]) && j < sizeof(msg); i+=2,j++) {
  4946                 hex_to_byteval(&buf[i], &msg[j]);
  4948 	    shaLength = fips_hashLen(shaAlg);
  4949 	    if (fips_hashBuf(shaAlg,sha,msg,j) != SECSuccess) {
  4950 		if (shaLength == 0) {
  4951             	    fprintf(rsaresp, "ERROR: SHAAlg not defined.");
  4953                 fprintf(rsaresp, "ERROR: Unable to generate SHA%x",
  4954 			shaLength == 160 ? 1 : shaLength);
  4955                 goto loser;
  4957 	    shaOid = fips_hashOid(shaAlg);
  4959             /* Perform RSA signature with the RSA private key. */
  4960             rv = RSA_HashSign( shaOid,
  4961                                rsa_private_key,
  4962                                rsa_computed_signature,
  4963                                &rsa_bytes_signed,
  4964                                nsslowkey_PrivateModulusLen(rsa_private_key),
  4965                                sha,
  4966                                shaLength);
  4968             if( rv != SECSuccess ) {
  4969                  fprintf(rsaresp, "ERROR: RSA_HashSign failed");
  4970                  goto loser;
  4973             /* Output the signature */
  4974             fputs(buf, rsaresp);
  4975             to_hex_str(buf, rsa_computed_signature, rsa_bytes_signed);
  4976             fprintf(rsaresp, "S = %s\n", buf);
  4978             /* Perform RSA verification with the RSA public key. */
  4979             rv = RSA_HashCheckSign( shaOid,
  4980                                     rsa_public_key,
  4981                                     rsa_computed_signature,
  4982                                     rsa_bytes_signed,
  4983                                     sha,
  4984                                     shaLength);
  4985             if( rv != SECSuccess ) {
  4986                  fprintf(rsaresp, "ERROR: RSA_HashCheckSign failed");
  4987                  goto loser;
  4989             continue;
  4992 loser:
  4993     fclose(rsareq);
  4995     if (rsaBlapiPrivKey != NULL) {
  4996         /* frees private and public key */
  4997         PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
  4998         rsaBlapiPrivKey = NULL;
  4999         rsaBlapiPublicKey = NULL;
  5003 /*
  5004  * Perform the RSA Signature Verification Test.
  5006  * reqfn is the pathname of the REQUEST file.
  5008  * The output RESPONSE file is written to stdout.
  5009  */
  5010 void
  5011 rsa_sigver_test(char *reqfn)
  5013     char buf[2*RSA_MAX_TEST_MODULUS_BYTES+7];
  5014                         /* buf holds one line from the input REQUEST file
  5015                          * or to the output RESPONSE file.
  5016                          * s = 2x for HEX output + 1 for \n
  5017                          */
  5018     FILE *rsareq;     /* input stream from the REQUEST file */
  5019     FILE *rsaresp;    /* output stream to the RESPONSE file */
  5020     int i, j;
  5021     unsigned char   sha[HASH_LENGTH_MAX];   /* SHA digest */
  5022     unsigned int    shaLength = 0;              /* actual length of the digest */
  5023     HASH_HashType   shaAlg = HASH_AlgNULL;
  5024     SECOidTag       shaOid = SEC_OID_UNKNOWN;
  5025     int modulus = 0;                            /* the Modulus size */
  5026     unsigned char   signature[513];    /* largest signature size + '\n' */
  5027     unsigned int    signatureLength = 0;   /* actual length of the signature */
  5028     PRBool keyvalid = PR_TRUE;
  5030     RSAPublicKey   rsaBlapiPublicKey; /* hold RSA public key */
  5032     rsareq = fopen(reqfn, "r");
  5033     rsaresp = stdout;
  5034     memset(&rsaBlapiPublicKey, 0, sizeof(RSAPublicKey));
  5036     while (fgets(buf, sizeof buf, rsareq) != NULL) {
  5037         /* a comment or blank line */
  5038         if (buf[0] == '#' || buf[0] == '\n') {
  5039             fputs(buf, rsaresp);
  5040             continue;
  5043         /* [Mod = ...] */
  5044         if (buf[0] == '[') {
  5045             unsigned int flen;  /* length in bytes of the field size */
  5047             if (rsaBlapiPublicKey.modulus.data) { /* n */
  5048                 SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
  5050             if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
  5051                 goto loser;
  5054             if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
  5055                 fprintf(rsaresp,"ERROR: modulus greater than test maximum\n");
  5056                 goto loser;
  5059             fputs(buf, rsaresp);
  5061             signatureLength = flen = modulus/8;
  5063             SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.modulus, flen);
  5064             if (rsaBlapiPublicKey.modulus.data == NULL) {
  5065                 goto loser;
  5067             continue;
  5070         /* n = ... modulus */
  5071         if (buf[0] == 'n') {
  5072             i = 1;
  5073             while (isspace(buf[i]) || buf[i] == '=') {
  5074                 i++;
  5076             keyvalid = from_hex_str(&rsaBlapiPublicKey.modulus.data[0],
  5077                                     rsaBlapiPublicKey.modulus.len,
  5078                                     &buf[i]);
  5080             if (!keyvalid) {
  5081                 fprintf(rsaresp, "ERROR: rsa_sigver n not valid.\n");
  5082                                  goto loser;
  5084             fputs(buf, rsaresp);
  5085             continue;
  5088         /* SHAAlg = ... */
  5089         if (strncmp(buf, "SHAAlg", 6) == 0) {
  5090            i = 6;
  5091            while (isspace(buf[i]) || buf[i] == '=') {
  5092                i++;
  5094            /* set the SHA Algorithm */
  5095            if (strncmp(&buf[i], "SHA1", 4) == 0) {
  5096                 shaAlg = HASH_AlgSHA1;
  5097            } else if (strncmp(&buf[i], "SHA224", 6) == 0) {
  5098                 shaAlg = HASH_AlgSHA224;
  5099            } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
  5100                 shaAlg = HASH_AlgSHA256;
  5101            } else if (strncmp(&buf[i], "SHA384", 6) == 0) {
  5102                shaAlg = HASH_AlgSHA384;
  5103            } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
  5104                shaAlg = HASH_AlgSHA512;
  5105            } else {
  5106                fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
  5107                goto loser;
  5109            fputs(buf, rsaresp);
  5110            continue;
  5113         /* e = ... public Key */
  5114         if (buf[0] == 'e') {
  5115             unsigned char data[RSA_MAX_TEST_EXPONENT_BYTES];
  5116             unsigned char t;
  5118             memset(data, 0, sizeof data);
  5120             if (rsaBlapiPublicKey.publicExponent.data) { /* e */
  5121                 SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
  5124             i = 1;
  5125             while (isspace(buf[i]) || buf[i] == '=') {
  5126                 i++;
  5128             /* skip leading zero's */
  5129             while (isxdigit(buf[i])) {
  5130                 hex_to_byteval(&buf[i], &t);
  5131                 if (t == 0) {
  5132                     i+=2;
  5133                 } else break;
  5136             /* get the exponent */
  5137             for (j=0; isxdigit(buf[i]) && j < sizeof data; i+=2,j++) {
  5138                 hex_to_byteval(&buf[i], &data[j]);
  5141             if (j == 0) { j = 1; }  /* to handle 1 byte length exponents */
  5143             SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.publicExponent,  j);
  5144             if (rsaBlapiPublicKey.publicExponent.data == NULL) {
  5145                 goto loser;
  5148             for (i=0; i < j; i++) {
  5149                 rsaBlapiPublicKey.publicExponent.data[i] = data[i];
  5152             fputs(buf, rsaresp);
  5153             continue;
  5156         /* Msg = ... */
  5157         if (strncmp(buf, "Msg", 3) == 0) {
  5158             unsigned char msg[128]; /* MAX msg 128 */
  5160             memset(sha, 0, sizeof sha);
  5161             memset(msg, 0, sizeof msg);
  5163             i = 3;
  5164             while (isspace(buf[i]) || buf[i] == '=') {
  5165                 i++;
  5168             for (j=0; isxdigit(buf[i]) && j < sizeof msg; i+=2,j++) {
  5169                 hex_to_byteval(&buf[i], &msg[j]);
  5172 	    shaLength = fips_hashLen(shaAlg);
  5173 	    if (fips_hashBuf(shaAlg,sha,msg,j) != SECSuccess) {
  5174 		if (shaLength == 0) {
  5175             	    fprintf(rsaresp, "ERROR: SHAAlg not defined.");
  5177                 fprintf(rsaresp, "ERROR: Unable to generate SHA%x",
  5178 			shaLength == 160 ? 1 : shaLength);
  5179                 goto loser;
  5182             fputs(buf, rsaresp);
  5183             continue;
  5187         /* S = ... */
  5188         if (buf[0] == 'S') {
  5189             SECStatus rv = SECFailure;
  5190             NSSLOWKEYPublicKey  * rsa_public_key;
  5191             NSSLOWKEYPublicKey    low_RSA_public_key = { NULL,
  5192                                                   NSSLOWKEYRSAKey, };
  5194             /* convert to a low RSA public key */
  5195             low_RSA_public_key.u.rsa = rsaBlapiPublicKey;
  5196             rsa_public_key = &low_RSA_public_key;
  5198             memset(signature, 0, sizeof(signature));
  5199             i = 1;
  5200             while (isspace(buf[i]) || buf[i] == '=') {
  5201                 i++;
  5204             for (j=0; isxdigit(buf[i]) && j < sizeof signature; i+=2,j++) {
  5205                 hex_to_byteval(&buf[i], &signature[j]);
  5208             signatureLength = j;
  5209             fputs(buf, rsaresp);
  5211             /* Perform RSA verification with the RSA public key. */
  5212             rv = RSA_HashCheckSign( shaOid,
  5213                                     rsa_public_key,
  5214                                     signature,
  5215                                     signatureLength,
  5216                                     sha,
  5217                                     shaLength);
  5218             if( rv == SECSuccess ) {
  5219                 fputs("Result = P\n", rsaresp);
  5220             } else {
  5221                 fputs("Result = F\n", rsaresp);
  5223             continue;
  5226 loser:
  5227     fclose(rsareq);
  5228     if (rsaBlapiPublicKey.modulus.data) { /* n */
  5229         SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
  5231     if (rsaBlapiPublicKey.publicExponent.data) { /* e */
  5232         SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
  5236 int main(int argc, char **argv)
  5238     if (argc < 2) exit (-1);
  5240     RNG_RNGInit();
  5241     SECOID_Init();
  5243     /*************/
  5244     /*   TDEA    */
  5245     /*************/
  5246     if (strcmp(argv[1], "tdea") == 0) {
  5247         /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
  5248         if (strcmp(argv[2], "kat") == 0) {
  5249             /* Known Answer Test (KAT) */
  5250             tdea_kat_mmt(argv[4]);     
  5251         } else if (strcmp(argv[2], "mmt") == 0) {
  5252             /* Multi-block Message Test (MMT) */
  5253                 tdea_kat_mmt(argv[4]);
  5254         } else if (strcmp(argv[2], "mct") == 0) {
  5255                 /* Monte Carlo Test (MCT) */
  5256                 if (strcmp(argv[3], "ecb") == 0) {
  5257                     /* ECB mode */
  5258                     tdea_mct(NSS_DES_EDE3, argv[4]); 
  5259                 } else if (strcmp(argv[3], "cbc") == 0) {
  5260                     /* CBC mode */
  5261                     tdea_mct(NSS_DES_EDE3_CBC, argv[4]);
  5264     /*************/
  5265     /*   AES     */
  5266     /*************/
  5267     } else if (strcmp(argv[1], "aes") == 0) {
  5268 	/* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
  5269 	if (       strcmp(argv[2], "kat") == 0) {
  5270 	    /* Known Answer Test (KAT) */
  5271 	    aes_kat_mmt(argv[4]);
  5272 	} else if (strcmp(argv[2], "mmt") == 0) {
  5273 	    /* Multi-block Message Test (MMT) */
  5274 	    aes_kat_mmt(argv[4]);
  5275 	} else if (strcmp(argv[2], "mct") == 0) {
  5276 	    /* Monte Carlo Test (MCT) */
  5277 	    if (       strcmp(argv[3], "ecb") == 0) {
  5278 		/* ECB mode */
  5279 		aes_ecb_mct(argv[4]);
  5280 	    } else if (strcmp(argv[3], "cbc") == 0) {
  5281 		/* CBC mode */
  5282 		aes_cbc_mct(argv[4]);
  5285     /*************/
  5286     /*   SHA     */
  5287     /*************/
  5288     } else if (strcmp(argv[1], "sha") == 0) {
  5289         sha_test(argv[2]);
  5290     /*************/
  5291     /*   RSA     */
  5292     /*************/
  5293     } else if (strcmp(argv[1], "rsa") == 0) {
  5294         /* argv[2]=siggen|sigver */
  5295         /* argv[3]=<test name>.req */
  5296         if (strcmp(argv[2], "siggen") == 0) {
  5297             /* Signature Generation Test */
  5298             rsa_siggen_test(argv[3]);
  5299         } else if (strcmp(argv[2], "sigver") == 0) {
  5300             /* Signature Verification Test */
  5301             rsa_sigver_test(argv[3]);
  5303     /*************/
  5304     /*   HMAC    */
  5305     /*************/
  5306     } else if (strcmp(argv[1], "hmac") == 0) {
  5307         hmac_test(argv[2]);
  5308     /*************/
  5309     /*   DSA     */
  5310     /*************/
  5311     } else if (strcmp(argv[1], "dsa") == 0) {
  5312         /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */
  5313         /* argv[3]=<test name>.req */
  5314         if (strcmp(argv[2], "keypair") == 0) {
  5315             /* Key Pair Generation Test */
  5316             dsa_keypair_test(argv[3]);
  5317         } else if (strcmp(argv[2], "pqggen") == 0) {
  5318         /* Domain Parameter Generation Test */
  5319             dsa_pqggen_test(argv[3]);
  5320         } else if (strcmp(argv[2], "pqgver") == 0) {
  5321                 /* Domain Parameter Validation Test */
  5322             dsa_pqgver_test(argv[3]);
  5323         } else if (strcmp(argv[2], "siggen") == 0) {
  5324             /* Signature Generation Test */
  5325             dsa_siggen_test(argv[3]);
  5326         } else if (strcmp(argv[2], "sigver") == 0) {
  5327             /* Signature Verification Test */
  5328             dsa_sigver_test(argv[3]);
  5330 #ifndef NSS_DISABLE_ECC
  5331     /*************/
  5332     /*   ECDSA   */
  5333     /*************/
  5334     } else if (strcmp(argv[1], "ecdsa") == 0) {
  5335 	/* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */
  5336 	if (       strcmp(argv[2], "keypair") == 0) {
  5337 	    /* Key Pair Generation Test */
  5338 	    ecdsa_keypair_test(argv[3]);
  5339 	} else if (strcmp(argv[2], "pkv") == 0) {
  5340 	    /* Public Key Validation Test */
  5341 	    ecdsa_pkv_test(argv[3]);
  5342 	} else if (strcmp(argv[2], "siggen") == 0) {
  5343 	    /* Signature Generation Test */
  5344 	    ecdsa_siggen_test(argv[3]);
  5345 	} else if (strcmp(argv[2], "sigver") == 0) {
  5346 	    /* Signature Verification Test */
  5347 	    ecdsa_sigver_test(argv[3]);
  5349 #endif /* NSS_DISABLE_ECC */
  5350     /*************/
  5351     /*   RNG     */
  5352     /*************/
  5353     } else if (strcmp(argv[1], "rng") == 0) {
  5354 	/* argv[2]=vst|mct argv[3]=<test name>.req */
  5355 	if (       strcmp(argv[2], "vst") == 0) {
  5356 	    /* Variable Seed Test */
  5357 	    rng_vst(argv[3]);
  5358 	} else if (strcmp(argv[2], "mct") == 0) {
  5359 	    /* Monte Carlo Test */
  5360 	    rng_mct(argv[3]);
  5362     } else if (strcmp(argv[1], "drbg") == 0) {
  5363 	/* Variable Seed Test */
  5364 	drbg(argv[2]);
  5365     } else if (strcmp(argv[1], "ddrbg") == 0) {
  5366 	debug = 1;
  5367 	drbg(argv[2]);
  5369     return 0;

mercurial