Back to index

lightning-sunbird  0.9+nobinonly
fipstest.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include <ctype.h>
00040 
00041 #include "secitem.h"
00042 #include "blapi.h"
00043 #include "nss.h"
00044 #include "secerr.h"
00045 #include "secder.h"
00046 #include "secdig.h"
00047 #include "keythi.h"
00048 #include "ec.h"
00049 #include "hasht.h"
00050 #include "lowkeyi.h"
00051 #include "softoken.h"
00052 #include "pqgutil.h"
00053 
00054 #if 0
00055 #include "../../lib/freebl/mpi/mpi.h"
00056 #endif
00057 
00058 #ifdef NSS_ENABLE_ECC
00059 extern SECStatus
00060 EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
00061 extern SECStatus
00062 EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
00063               const ECParams *srcParams);
00064 #endif
00065 
00066 #define ENCRYPT 1
00067 #define DECRYPT 0
00068 #define BYTE unsigned char
00069 #define DEFAULT_RSA_PUBLIC_EXPONENT   0x10001
00070 #define RSA_MAX_TEST_MODULUS_BITS     4096
00071 #define RSA_MAX_TEST_MODULUS_BYTES    RSA_MAX_TEST_MODULUS_BITS/8
00072 #define RSA_MAX_TEST_EXPONENT_BYTES   8
00073 #define PQG_TEST_SEED_BYTES           20
00074 
00075 SECStatus
00076 hex_from_2char(const char *c2, unsigned char *byteval)
00077 {
00078     int i;
00079     unsigned char offset;
00080     *byteval = 0;
00081     for (i=0; i<2; i++) {
00082        if (c2[i] >= '0' && c2[i] <= '9') {
00083            offset = c2[i] - '0';
00084            *byteval |= offset << 4*(1-i);
00085        } else if (c2[i] >= 'a' && c2[i] <= 'f') {
00086            offset = c2[i] - 'a';
00087            *byteval |= (offset + 10) << 4*(1-i);
00088        } else if (c2[i] >= 'A' && c2[i] <= 'F') {
00089            offset = c2[i] - 'A';
00090            *byteval |= (offset + 10) << 4*(1-i);
00091        } else {
00092            return SECFailure;
00093        }
00094     }
00095     return SECSuccess;
00096 }
00097 
00098 SECStatus
00099 char2_from_hex(unsigned char byteval, char *c2, char a)
00100 {
00101     int i;
00102     unsigned char offset;
00103     for (i=0; i<2; i++) {
00104        offset = (byteval >> 4*(1-i)) & 0x0f;
00105        if (offset < 10) {
00106            c2[i] = '0' + offset;
00107        } else {
00108            c2[i] = a + offset - 10;
00109        }
00110     }
00111     return SECSuccess;
00112 }
00113 
00114 void
00115 to_hex_str(char *str, const unsigned char *buf, unsigned int len)
00116 {
00117     unsigned int i;
00118     for (i=0; i<len; i++) {
00119        char2_from_hex(buf[i], &str[2*i], 'a');
00120     }
00121     str[2*len] = '\0';
00122 }
00123 
00124 void
00125 to_hex_str_cap(char *str, const unsigned char *buf, unsigned int len)
00126 {
00127     unsigned int i;
00128     for (i=0; i<len; i++) {
00129        char2_from_hex(buf[i], &str[2*i], 'A');
00130     }
00131     str[2*len] = '\0';
00132 }
00133 
00134 /*
00135  * Convert a string of hex digits (str) to an array (buf) of len bytes.
00136  * Return PR_TRUE if the hex string can fit in the byte array.  Return
00137  * PR_FALSE if the hex string is empty or is too long.
00138  */
00139 PRBool
00140 from_hex_str(unsigned char *buf, unsigned int len, const char *str)
00141 {
00142     unsigned int nxdigit;  /* number of hex digits in str */
00143     unsigned int i;  /* index into buf */
00144     unsigned int j;  /* index into str */
00145 
00146     /* count the hex digits */
00147     nxdigit = 0;
00148     for (nxdigit = 0; isxdigit(str[nxdigit]); nxdigit++) {
00149        /* empty body */
00150     }
00151     if (nxdigit == 0) {
00152        return PR_FALSE;
00153     }
00154     if (nxdigit > 2*len) {
00155        /*
00156         * The input hex string is too long, but we allow it if the
00157         * extra digits are leading 0's.
00158         */
00159        for (j = 0; j < nxdigit-2*len; j++) {
00160            if (str[j] != '0') {
00161               return PR_FALSE;
00162            }
00163        }
00164        /* skip leading 0's */
00165        str += nxdigit-2*len;
00166        nxdigit = 2*len;
00167     }
00168     for (i=0, j=0; i< len; i++) {
00169        if (2*i < 2*len-nxdigit) {
00170            /* Handle a short input as if we padded it with leading 0's. */
00171            if (2*i+1 < 2*len-nxdigit) {
00172               buf[i] = 0;
00173            } else {
00174               char tmp[2];
00175               tmp[0] = '0';
00176               tmp[1] = str[j];
00177               hex_from_2char(tmp, &buf[i]);
00178               j++;
00179            }
00180        } else {
00181            hex_from_2char(&str[j], &buf[i]);
00182            j += 2;
00183        }
00184     }
00185     return PR_TRUE;
00186 }
00187 
00188 SECStatus
00189 tdea_encrypt_buf(
00190     int mode,
00191     const unsigned char *key, 
00192     const unsigned char *iv,
00193     unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
00194     const unsigned char *input, unsigned int inputlen)
00195 {
00196     SECStatus rv = SECFailure;
00197     DESContext *cx;
00198     unsigned char doublecheck[8*20];  /* 1 to 20 blocks */
00199     unsigned int doublechecklen = 0;
00200 
00201     cx = DES_CreateContext(key, iv, mode, PR_TRUE);
00202     if (cx == NULL) {
00203         goto loser;
00204     }
00205     rv = DES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
00206     if (rv != SECSuccess) {
00207         goto loser;
00208     }
00209     if (*outputlen != inputlen) {
00210         goto loser;
00211     }
00212     DES_DestroyContext(cx, PR_TRUE);
00213     cx = NULL;
00214 
00215     /*
00216      * Doublecheck our result by decrypting the ciphertext and
00217      * compare the output with the input plaintext.
00218      */
00219     cx = DES_CreateContext(key, iv, mode, PR_FALSE);
00220     if (cx == NULL) {
00221         goto loser;
00222     }
00223     rv = DES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
00224                     output, *outputlen);
00225     if (rv != SECSuccess) {
00226         goto loser;
00227     }
00228     if (doublechecklen != *outputlen) {
00229         goto loser;
00230     }
00231     DES_DestroyContext(cx, PR_TRUE);
00232     cx = NULL;
00233     if (memcmp(doublecheck, input, inputlen) != 0) {
00234         goto loser;
00235     }
00236     rv = SECSuccess;
00237 
00238 loser:
00239     if (cx != NULL) {
00240         DES_DestroyContext(cx, PR_TRUE);
00241     }
00242     return rv;
00243 }
00244 
00245 SECStatus
00246 tdea_decrypt_buf(
00247     int mode,
00248     const unsigned char *key, 
00249     const unsigned char *iv,
00250     unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
00251     const unsigned char *input, unsigned int inputlen)
00252 {
00253     SECStatus rv = SECFailure;
00254     DESContext *cx;
00255     unsigned char doublecheck[8*20];  /* 1 to 20 blocks */
00256     unsigned int doublechecklen = 0;
00257 
00258     cx = DES_CreateContext(key, iv, mode, PR_FALSE);
00259     if (cx == NULL) {
00260         goto loser;
00261     }
00262     rv = DES_Decrypt(cx, output, outputlen, maxoutputlen,
00263                     input, inputlen);
00264     if (rv != SECSuccess) {
00265         goto loser;
00266     }
00267     if (*outputlen != inputlen) {
00268         goto loser;
00269     }
00270     DES_DestroyContext(cx, PR_TRUE);
00271     cx = NULL;
00272 
00273     /*
00274      * Doublecheck our result by encrypting the plaintext and
00275      * compare the output with the input ciphertext.
00276      */
00277     cx = DES_CreateContext(key, iv, mode, PR_TRUE);
00278     if (cx == NULL) {
00279         goto loser;
00280     }
00281     rv = DES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
00282         output, *outputlen);
00283     if (rv != SECSuccess) {
00284         goto loser;
00285     }
00286     if (doublechecklen != *outputlen) {
00287         goto loser;
00288     }
00289     DES_DestroyContext(cx, PR_TRUE);
00290     cx = NULL;
00291     if (memcmp(doublecheck, input, inputlen) != 0) {
00292         goto loser;
00293     }
00294     rv = SECSuccess;
00295 
00296 loser:
00297     if (cx != NULL) {
00298         DES_DestroyContext(cx, PR_TRUE);
00299     }
00300     return rv;
00301 }
00302 
00303 /*
00304  * Perform the TDEA Known Answer Test (KAT) or Multi-block Message
00305  * Test (MMT) in ECB or CBC mode.  The KAT (there are five types)
00306  * and MMT have the same structure: given the key and IV (CBC mode
00307  * only), encrypt the given plaintext or decrypt the given ciphertext.
00308  * So we can handle them the same way.
00309  *
00310  * reqfn is the pathname of the REQUEST file.
00311  *
00312  * The output RESPONSE file is written to stdout.
00313  */
00314 void
00315 tdea_kat_mmt(char *reqfn)
00316 {
00317     char buf[180];      /* holds one line from the input REQUEST file.
00318                          * needs to be large enough to hold the longest
00319                          * line "CIPHERTEXT = <180 hex digits>\n".
00320                          */
00321     FILE *req;       /* input stream from the REQUEST file */
00322     FILE *resp;      /* output stream to the RESPONSE file */
00323     int i, j;
00324     int mode;           /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */
00325     int crypt = DECRYPT;    /* 1 means encrypt, 0 means decrypt */
00326     unsigned char key[24];              /* TDEA 3 key bundle */
00327     unsigned int numKeys = 0;
00328     unsigned char iv[8];           /* for all modes except ECB */
00329     unsigned char plaintext[8*20];     /* 1 to 20 blocks */
00330     unsigned int plaintextlen;
00331     unsigned char ciphertext[8*20];   /* 1 to 20 blocks */  
00332     unsigned int ciphertextlen;
00333     SECStatus rv;
00334 
00335     req = fopen(reqfn, "r");
00336     resp = stdout;
00337     while (fgets(buf, sizeof buf, req) != NULL) {
00338         /* a comment or blank line */
00339         if (buf[0] == '#' || buf[0] == '\n') {
00340             fputs(buf, resp);
00341             continue;
00342         }
00343         /* [ENCRYPT] or [DECRYPT] */
00344         if (buf[0] == '[') {
00345             if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
00346                 crypt = ENCRYPT;
00347             } else {
00348                 crypt = DECRYPT;
00349             }
00350             fputs(buf, resp);
00351             continue;
00352         }
00353         /* NumKeys */
00354         if (strncmp(&buf[0], "NumKeys", 7) == 0) {
00355             i = 7;
00356             while (isspace(buf[i]) || buf[i] == '=') {
00357                 i++;
00358             }
00359             numKeys = buf[i];
00360             fputs(buf, resp);
00361             continue;
00362         }
00363         /* "COUNT = x" begins a new data set */
00364         if (strncmp(buf, "COUNT", 5) == 0) {
00365             /* mode defaults to ECB, if dataset has IV mode will be set CBC */
00366             mode = NSS_DES_EDE3;
00367             /* zeroize the variables for the test with this data set */
00368             memset(key, 0, sizeof key);
00369             memset(iv, 0, sizeof iv);
00370             memset(plaintext, 0, sizeof plaintext);
00371             plaintextlen = 0;
00372             memset(ciphertext, 0, sizeof ciphertext);
00373             ciphertextlen = 0;
00374             fputs(buf, resp);
00375             continue;
00376         }
00377         if (numKeys == 0) {
00378             if (strncmp(buf, "KEYs", 4) == 0) {
00379                 i = 4;
00380                 while (isspace(buf[i]) || buf[i] == '=') {
00381                     i++;
00382                 }
00383                 for (j=0; isxdigit(buf[i]); i+=2,j++) {
00384                     hex_from_2char(&buf[i], &key[j]);
00385                     key[j+8] = key[j];
00386                     key[j+16] = key[j];
00387                 }
00388                 fputs(buf, resp);
00389                 continue;
00390             }
00391         } else {
00392             /* KEY1 = ... */
00393             if (strncmp(buf, "KEY1", 4) == 0) {
00394                 i = 4;
00395                 while (isspace(buf[i]) || buf[i] == '=') {
00396                     i++;
00397                 }
00398                 for (j=0; isxdigit(buf[i]); i+=2,j++) {
00399                     hex_from_2char(&buf[i], &key[j]);
00400                 }
00401                 fputs(buf, resp);
00402                 continue;
00403             }
00404             /* KEY2 = ... */
00405             if (strncmp(buf, "KEY2", 4) == 0) {
00406                 i = 4;
00407                 while (isspace(buf[i]) || buf[i] == '=') {
00408                     i++;
00409                 }
00410                 for (j=8; isxdigit(buf[i]); i+=2,j++) {
00411                     hex_from_2char(&buf[i], &key[j]);
00412                 }
00413                 fputs(buf, resp);
00414                 continue;
00415             }
00416             /* KEY3 = ... */
00417             if (strncmp(buf, "KEY3", 4) == 0) {
00418                 i = 4;
00419                 while (isspace(buf[i]) || buf[i] == '=') {
00420                     i++;
00421                 }
00422                 for (j=16; isxdigit(buf[i]); i+=2,j++) {
00423                     hex_from_2char(&buf[i], &key[j]);
00424                 }
00425                 fputs(buf, resp);
00426                 continue;
00427             }
00428         }
00429 
00430         /* IV = ... */
00431         if (strncmp(buf, "IV", 2) == 0) {
00432             mode = NSS_DES_EDE3_CBC;
00433             i = 2;
00434             while (isspace(buf[i]) || buf[i] == '=') {
00435                 i++;
00436             }
00437             for (j=0; j<sizeof iv; i+=2,j++) {
00438                 hex_from_2char(&buf[i], &iv[j]);
00439             }
00440             fputs(buf, resp);
00441             continue;
00442         }
00443 
00444         /* PLAINTEXT = ... */
00445         if (strncmp(buf, "PLAINTEXT", 9) == 0) {
00446             /* sanity check */
00447             if (crypt != ENCRYPT) {
00448                 goto loser;
00449             }
00450             i = 9;
00451             while (isspace(buf[i]) || buf[i] == '=') {
00452                 i++;
00453             }
00454             for (j=0; isxdigit(buf[i]); i+=2,j++) {
00455                 hex_from_2char(&buf[i], &plaintext[j]);
00456             }
00457             plaintextlen = j;
00458             rv = tdea_encrypt_buf(mode, key,
00459                             (mode == NSS_DES_EDE3) ? NULL : iv,
00460                             ciphertext, &ciphertextlen, sizeof ciphertext,
00461                             plaintext, plaintextlen);
00462             if (rv != SECSuccess) {
00463                 goto loser;
00464             }
00465     
00466             fputs(buf, resp);
00467             fputs("CIPHERTEXT = ", resp);
00468             to_hex_str(buf, ciphertext, ciphertextlen);
00469             fputs(buf, resp);
00470             fputc('\n', resp);
00471             continue;
00472         }
00473         /* CIPHERTEXT = ... */
00474         if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
00475             /* sanity check */
00476             if (crypt != DECRYPT) {
00477                 goto loser;
00478             }
00479  
00480             i = 10;
00481             while (isspace(buf[i]) || buf[i] == '=') {
00482                 i++;
00483             }
00484             for (j=0; isxdigit(buf[i]); i+=2,j++) {
00485                 hex_from_2char(&buf[i], &ciphertext[j]);
00486             }
00487             ciphertextlen = j;
00488  
00489             rv = tdea_decrypt_buf(mode, key,
00490                             (mode == NSS_DES_EDE3) ? NULL : iv,
00491                             plaintext, &plaintextlen, sizeof plaintext,
00492                             ciphertext, ciphertextlen);
00493             if (rv != SECSuccess) {
00494                 goto loser;
00495             }
00496  
00497             fputs(buf, resp);
00498             fputs("PLAINTEXT = ", resp);
00499             to_hex_str(buf, plaintext, plaintextlen);
00500             fputs(buf, resp);
00501             fputc('\n', resp);
00502             continue;
00503         }
00504     }
00505 
00506 loser:
00507     fclose(req);
00508 }
00509 
00510 /*
00511 * Set the parity bit for the given byte
00512 */
00513 BYTE odd_parity( BYTE in)
00514 {
00515     BYTE out = in;
00516     in ^= in >> 4;
00517     in ^= in >> 2;
00518     in ^= in >> 1;
00519     return (BYTE)(out ^ !(in & 1));
00520 }
00521 
00522 /*
00523  * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j] 
00524  * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes.
00525  */
00526 void
00527 tdea_mct_next_keys(unsigned char *key,
00528     const unsigned char *text_2, const unsigned char *text_1, 
00529     const unsigned char *text, unsigned int numKeys)
00530 {
00531     int k;
00532 
00533     /* key1[i+1] = key1[i] xor PT/CT[j] */
00534     for (k=0; k<8; k++) {
00535         key[k] ^= text[k];
00536     }
00537     /* key2 */
00538     if (numKeys == 2 || numKeys == 3)  {
00539         /* key2 independent */
00540         for (k=8; k<16; k++) {
00541             /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */
00542             key[k] ^= text_1[k-8];
00543         }
00544     } else {
00545         /* key2 == key 1 */
00546         for (k=8; k<16; k++) {
00547             /* key2[i+1] = KEY2[i] xor PT/CT[j] */
00548             key[k] = key[k-8];
00549         }
00550     }
00551     /* key3 */
00552     if (numKeys == 1 || numKeys == 2) {
00553         /* key3 == key 1 */
00554         for (k=16; k<24; k++) {
00555             /* key3[i+1] = KEY3[i] xor PT/CT[j] */
00556             key[k] = key[k-16];
00557         }
00558     } else {
00559         /* key3 independent */ 
00560         for (k=16; k<24; k++) {
00561             /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */
00562             key[k] ^= text_2[k-16];
00563         }
00564     }
00565     /* set the parity bits */            
00566     for (k=0; k<24; k++) {
00567         key[k] = odd_parity(key[k]);
00568     }
00569 }
00570 
00571 /*
00572  * Perform the Monte Carlo Test
00573  *
00574  * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC
00575  * crypt = ENCRYPT || DECRYPT
00576  * inputtext = plaintext or Cyphertext depending on the value of crypt
00577  * inputlength is expected to be size 8 bytes 
00578  * iv = needs to be set for NSS_DES_EDE3_CBC mode
00579  * resp = is the output response file. 
00580  */
00581  void                                                       
00582 tdea_mct_test(int mode, unsigned char* key, unsigned int numKeys, 
00583               unsigned int crypt, unsigned char* inputtext, 
00584               unsigned int inputlength, unsigned char* iv, FILE *resp) { 
00585 
00586     int i, j;
00587     unsigned char outputtext_1[8];      /* PT/CT[j-1] */
00588     unsigned char outputtext_2[8];      /* PT/CT[j-2] */
00589     char buf[80];       /* holds one line from the input REQUEST file. */
00590     unsigned int outputlen;
00591     unsigned char outputtext[8];
00592     
00593         
00594     SECStatus rv;
00595 
00596     if (mode == NSS_DES_EDE3 && iv != NULL) {
00597         printf("IV must be NULL for NSS_DES_EDE3 mode");
00598         goto loser;
00599     } else if (mode == NSS_DES_EDE3_CBC && iv == NULL) {
00600         printf("IV must not be NULL for NSS_DES_EDE3_CBC mode");
00601         goto loser;
00602     }
00603 
00604     /* loop 400 times */
00605     for (i=0; i<400; i++) {
00606         /* if i == 0 CV[0] = IV  not necessary */        
00607         /* record the count and key values and plainText */
00608         sprintf(buf, "COUNT = %d\n", i);
00609         fputs(buf, resp);
00610         /* Output KEY1[i] */
00611         fputs("KEY1 = ", resp);
00612         to_hex_str(buf, key, 8);
00613         fputs(buf, resp);
00614         fputc('\n', resp);
00615         /* Output KEY2[i] */
00616         fputs("KEY2 = ", resp);
00617         to_hex_str(buf, &key[8], 8);
00618         fputs(buf, resp);
00619         fputc('\n', resp);
00620         /* Output KEY3[i] */
00621         fputs("KEY3 = ", resp);
00622         to_hex_str(buf, &key[16], 8);
00623         fputs(buf, resp);
00624         fputc('\n', resp);
00625         if (mode == NSS_DES_EDE3_CBC) {
00626             /* Output CV[i] */
00627             fputs("IV = ", resp);
00628             to_hex_str(buf, iv, 8);
00629             fputs(buf, resp);
00630             fputc('\n', resp);
00631         }
00632         if (crypt == ENCRYPT) {
00633             /* Output PT[0] */
00634             fputs("PLAINTEXT = ", resp);
00635         } else {
00636             /* Output CT[0] */
00637             fputs("CIPHERTEXT = ", resp);
00638         }
00639 
00640         to_hex_str(buf, inputtext, inputlength);
00641         fputs(buf, resp);
00642         fputc('\n', resp);
00643 
00644         /* loop 10,000 times */
00645         for (j=0; j<10000; j++) {
00646 
00647             outputlen = 0;
00648             if (crypt == ENCRYPT) {
00649                 /* inputtext == ciphertext outputtext == plaintext*/
00650                 rv = tdea_encrypt_buf(mode, key,
00651                             (mode == NSS_DES_EDE3) ? NULL : iv,
00652                             outputtext, &outputlen, 8,
00653                             inputtext, 8);
00654             } else {
00655                 /* inputtext == plaintext outputtext == ciphertext */
00656                 rv = tdea_decrypt_buf(mode, key,
00657                             (mode == NSS_DES_EDE3) ? NULL : iv,
00658                             outputtext, &outputlen, 8,
00659                             inputtext, 8);
00660             }
00661 
00662             if (rv != SECSuccess) {
00663                 goto loser;
00664             }
00665             if (outputlen != inputlength) {
00666                 goto loser;
00667             }
00668 
00669             if (mode == NSS_DES_EDE3_CBC) {
00670                 if (crypt == ENCRYPT) {
00671                     if (j == 0) {
00672                         /*P[j+1] = CV[0] */
00673                         memcpy(inputtext, iv, 8);
00674                     } else {
00675                         /* p[j+1] = C[j-1] */
00676                         memcpy(inputtext, outputtext_1, 8);
00677                     }
00678                     /* CV[j+1] = C[j] */
00679                     memcpy(iv, outputtext, 8);
00680                     if (j != 9999) {
00681                         /* save C[j-1] */
00682                         memcpy(outputtext_1, outputtext, 8);
00683                     }
00684                 } else { /* DECRYPT */
00685                     /* CV[j+1] = C[j] */
00686                     memcpy(iv, inputtext, 8);
00687                     /* C[j+1] = P[j] */
00688                     memcpy(inputtext, outputtext, 8);
00689                 }
00690             } else {
00691                 /* ECB mode PT/CT[j+1] = CT/PT[j] */
00692                 memcpy(inputtext, outputtext, 8);
00693             }
00694 
00695             /* Save PT/CT[j-2] and PT/CT[j-1] */
00696             if (j==9997) memcpy(outputtext_2, outputtext, 8);
00697             if (j==9998) memcpy(outputtext_1, outputtext, 8);
00698             /* done at the end of the for(j) loop */
00699         }
00700 
00701 
00702         if (crypt == ENCRYPT) {
00703             /* Output CT[j] */
00704             fputs("CIPHERTEXT = ", resp);
00705         } else {
00706             /* Output PT[j] */
00707             fputs("PLAINTEXT = ", resp);
00708         }
00709         to_hex_str(buf, outputtext, 8);
00710         fputs(buf, resp);
00711         fputc('\n', resp);
00712 
00713         /* Key[i+1] = Key[i] xor ...  outputtext_2 == PT/CT[j-2] 
00714          *  outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j] 
00715          */
00716         tdea_mct_next_keys(key, outputtext_2, 
00717                            outputtext_1, outputtext, numKeys);
00718 
00719         if (mode == NSS_DES_EDE3_CBC) {
00720             /* taken care of in the j=9999 iteration */
00721             if (crypt == ENCRYPT) {
00722                 /* P[i] = C[j-1] */
00723                 /* CV[i] = C[j] */
00724             } else {
00725                 /* taken care of in the j=9999 iteration */
00726                 /* CV[i] = C[j] */
00727                 /* C[i] = P[j]  */
00728             }
00729         } else {
00730             /* ECB PT/CT[i] = PT/CT[j]  */
00731             memcpy(inputtext, outputtext, 8);
00732         }
00733         /* done at the end of the for(i) loop */
00734         fputc('\n', resp);
00735     }
00736 
00737 loser:
00738     return;
00739 }
00740 
00741 /*
00742  * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes.
00743  * by gathering the input from the request file, and then 
00744  * calling tdea_mct_test.
00745  *
00746  * reqfn is the pathname of the input REQUEST file.
00747  *
00748  * The output RESPONSE file is written to stdout.
00749  */
00750 void
00751 tdea_mct(int mode, char *reqfn)
00752 {
00753     int i, j;
00754     char buf[80];    /* holds one line from the input REQUEST file. */
00755     FILE *req;       /* input stream from the REQUEST file */
00756     FILE *resp;      /* output stream to the RESPONSE file */
00757     unsigned int crypt = 0;    /* 1 means encrypt, 0 means decrypt */
00758     unsigned char key[24];              /* TDEA 3 key bundle */
00759     unsigned int numKeys = 0;
00760     unsigned char plaintext[8];        /* PT[j] */
00761     unsigned char ciphertext[8];       /* CT[j] */
00762     unsigned char iv[8];
00763 
00764     /* zeroize the variables for the test with this data set */
00765     memset(key, 0, sizeof key);
00766     memset(plaintext, 0, sizeof plaintext);
00767     memset(ciphertext, 0, sizeof ciphertext);
00768     memset(iv, 0, sizeof iv);
00769 
00770     req = fopen(reqfn, "r");
00771     resp = stdout;
00772     while (fgets(buf, sizeof buf, req) != NULL) {
00773         /* a comment or blank line */
00774         if (buf[0] == '#' || buf[0] == '\n') {
00775             fputs(buf, resp);
00776             continue;
00777         }
00778         /* [ENCRYPT] or [DECRYPT] */
00779         if (buf[0] == '[') {
00780             if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
00781                 crypt = ENCRYPT;
00782             } else {
00783                 crypt = DECRYPT;
00784            }
00785            fputs(buf, resp);
00786            continue;
00787         }
00788         /* NumKeys */
00789         if (strncmp(&buf[0], "NumKeys", 7) == 0) {
00790             i = 7;
00791             while (isspace(buf[i]) || buf[i] == '=') {
00792                 i++;
00793             }
00794             numKeys = atoi(&buf[i]);
00795             continue;
00796         }
00797         /* KEY1 = ... */
00798         if (strncmp(buf, "KEY1", 4) == 0) {
00799             i = 4;
00800             while (isspace(buf[i]) || buf[i] == '=') {
00801                 i++;
00802             }
00803             for (j=0; isxdigit(buf[i]); i+=2,j++) {
00804                 hex_from_2char(&buf[i], &key[j]);
00805             }
00806             continue;
00807         }
00808         /* KEY2 = ... */
00809         if (strncmp(buf, "KEY2", 4) == 0) {
00810             i = 4;
00811             while (isspace(buf[i]) || buf[i] == '=') {
00812                 i++;
00813             }
00814             for (j=8; isxdigit(buf[i]); i+=2,j++) {
00815                 hex_from_2char(&buf[i], &key[j]);
00816             }
00817             continue;
00818         }
00819         /* KEY3 = ... */
00820         if (strncmp(buf, "KEY3", 4) == 0) {
00821             i = 4;
00822             while (isspace(buf[i]) || buf[i] == '=') {
00823                 i++;
00824             }
00825             for (j=16; isxdigit(buf[i]); i+=2,j++) {
00826                 hex_from_2char(&buf[i], &key[j]);
00827             }
00828             continue;
00829         }
00830 
00831         /* IV = ... */
00832         if (strncmp(buf, "IV", 2) == 0) {
00833             i = 2;
00834             while (isspace(buf[i]) || buf[i] == '=') {
00835                 i++;
00836             }
00837             for (j=0; j<sizeof iv; i+=2,j++) {
00838                 hex_from_2char(&buf[i], &iv[j]);
00839             }
00840             continue;
00841         }
00842 
00843        /* PLAINTEXT = ... */
00844        if (strncmp(buf, "PLAINTEXT", 9) == 0) {
00845 
00846             /* sanity check */
00847             if (crypt != ENCRYPT) {
00848                 goto loser;
00849             }
00850             /* PT[0] = PT */
00851             i = 9;
00852             while (isspace(buf[i]) || buf[i] == '=') {
00853                 i++;
00854             }
00855             for (j=0; j<sizeof plaintext; i+=2,j++) {
00856                 hex_from_2char(&buf[i], &plaintext[j]);
00857             }                                     
00858 
00859             /* do the Monte Carlo test */
00860             if (mode==NSS_DES_EDE3) {
00861                 tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, plaintext, sizeof plaintext, NULL, resp);
00862             } else {
00863                 tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, plaintext, sizeof plaintext, iv, resp);
00864             }
00865             continue;
00866         }
00867         /* CIPHERTEXT = ... */
00868         if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
00869             /* sanity check */
00870             if (crypt != DECRYPT) {
00871                 goto loser;
00872             }
00873             /* CT[0] = CT */
00874             i = 10;
00875             while (isspace(buf[i]) || buf[i] == '=') {
00876                 i++;
00877             }
00878             for (j=0; isxdigit(buf[i]); i+=2,j++) {
00879                 hex_from_2char(&buf[i], &ciphertext[j]);
00880             }
00881             
00882             /* do the Monte Carlo test */
00883             if (mode==NSS_DES_EDE3) {
00884                 tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, ciphertext, sizeof ciphertext, NULL, resp); 
00885             } else {
00886                 tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, ciphertext, sizeof ciphertext, iv, resp); 
00887             }
00888             continue;
00889         }
00890     }
00891 
00892 loser:
00893     fclose(req);
00894 }
00895 
00896 
00897 SECStatus
00898 aes_encrypt_buf(
00899     int mode,
00900     const unsigned char *key, unsigned int keysize,
00901     const unsigned char *iv,
00902     unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
00903     const unsigned char *input, unsigned int inputlen)
00904 {
00905     SECStatus rv = SECFailure;
00906     AESContext *cx;
00907     unsigned char doublecheck[10*16];  /* 1 to 10 blocks */
00908     unsigned int doublechecklen = 0;
00909 
00910     cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
00911     if (cx == NULL) {
00912        goto loser;
00913     }
00914     rv = AES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
00915     if (rv != SECSuccess) {
00916        goto loser;
00917     }
00918     if (*outputlen != inputlen) {
00919        goto loser;
00920     }
00921     AES_DestroyContext(cx, PR_TRUE);
00922     cx = NULL;
00923 
00924     /*
00925      * Doublecheck our result by decrypting the ciphertext and
00926      * compare the output with the input plaintext.
00927      */
00928     cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
00929     if (cx == NULL) {
00930        goto loser;
00931     }
00932     rv = AES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
00933        output, *outputlen);
00934     if (rv != SECSuccess) {
00935        goto loser;
00936     }
00937     if (doublechecklen != *outputlen) {
00938        goto loser;
00939     }
00940     AES_DestroyContext(cx, PR_TRUE);
00941     cx = NULL;
00942     if (memcmp(doublecheck, input, inputlen) != 0) {
00943        goto loser;
00944     }
00945     rv = SECSuccess;
00946 
00947 loser:
00948     if (cx != NULL) {
00949        AES_DestroyContext(cx, PR_TRUE);
00950     }
00951     return rv;
00952 }
00953 
00954 SECStatus
00955 aes_decrypt_buf(
00956     int mode,
00957     const unsigned char *key, unsigned int keysize,
00958     const unsigned char *iv,
00959     unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
00960     const unsigned char *input, unsigned int inputlen)
00961 {
00962     SECStatus rv = SECFailure;
00963     AESContext *cx;
00964     unsigned char doublecheck[10*16];  /* 1 to 10 blocks */
00965     unsigned int doublechecklen = 0;
00966 
00967     cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16);
00968     if (cx == NULL) {
00969        goto loser;
00970     }
00971     rv = AES_Decrypt(cx, output, outputlen, maxoutputlen,
00972        input, inputlen);
00973     if (rv != SECSuccess) {
00974        goto loser;
00975     }
00976     if (*outputlen != inputlen) {
00977        goto loser;
00978     }
00979     AES_DestroyContext(cx, PR_TRUE);
00980     cx = NULL;
00981 
00982     /*
00983      * Doublecheck our result by encrypting the plaintext and
00984      * compare the output with the input ciphertext.
00985      */
00986     cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16);
00987     if (cx == NULL) {
00988        goto loser;
00989     }
00990     rv = AES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
00991        output, *outputlen);
00992     if (rv != SECSuccess) {
00993        goto loser;
00994     }
00995     if (doublechecklen != *outputlen) {
00996        goto loser;
00997     }
00998     AES_DestroyContext(cx, PR_TRUE);
00999     cx = NULL;
01000     if (memcmp(doublecheck, input, inputlen) != 0) {
01001        goto loser;
01002     }
01003     rv = SECSuccess;
01004 
01005 loser:
01006     if (cx != NULL) {
01007        AES_DestroyContext(cx, PR_TRUE);
01008     }
01009     return rv;
01010 }
01011 
01012 /*
01013  * Perform the AES Known Answer Test (KAT) or Multi-block Message
01014  * Test (MMT) in ECB or CBC mode.  The KAT (there are four types)
01015  * and MMT have the same structure: given the key and IV (CBC mode
01016  * only), encrypt the given plaintext or decrypt the given ciphertext.
01017  * So we can handle them the same way.
01018  *
01019  * reqfn is the pathname of the REQUEST file.
01020  *
01021  * The output RESPONSE file is written to stdout.
01022  */
01023 void
01024 aes_kat_mmt(char *reqfn)
01025 {
01026     char buf[512];      /* holds one line from the input REQUEST file.
01027                          * needs to be large enough to hold the longest
01028                          * line "CIPHERTEXT = <320 hex digits>\n".
01029                          */
01030     FILE *aesreq;       /* input stream from the REQUEST file */
01031     FILE *aesresp;      /* output stream to the RESPONSE file */
01032     int i, j;
01033     int mode;           /* NSS_AES (ECB) or NSS_AES_CBC */
01034     int encrypt = 0;    /* 1 means encrypt, 0 means decrypt */
01035     unsigned char key[32];              /* 128, 192, or 256 bits */
01036     unsigned int keysize;
01037     unsigned char iv[16];          /* for all modes except ECB */
01038     unsigned char plaintext[10*16];     /* 1 to 10 blocks */
01039     unsigned int plaintextlen;
01040     unsigned char ciphertext[10*16];    /* 1 to 10 blocks */
01041     unsigned int ciphertextlen;
01042     SECStatus rv;
01043 
01044     aesreq = fopen(reqfn, "r");
01045     aesresp = stdout;
01046     while (fgets(buf, sizeof buf, aesreq) != NULL) {
01047        /* a comment or blank line */
01048        if (buf[0] == '#' || buf[0] == '\n') {
01049            fputs(buf, aesresp);
01050            continue;
01051        }
01052        /* [ENCRYPT] or [DECRYPT] */
01053        if (buf[0] == '[') {
01054            if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
01055               encrypt = 1;
01056            } else {
01057               encrypt = 0;
01058            }
01059            fputs(buf, aesresp);
01060            continue;
01061        }
01062        /* "COUNT = x" begins a new data set */
01063        if (strncmp(buf, "COUNT", 5) == 0) {
01064            mode = NSS_AES;
01065            /* zeroize the variables for the test with this data set */
01066            memset(key, 0, sizeof key);
01067            keysize = 0;
01068            memset(iv, 0, sizeof iv);
01069            memset(plaintext, 0, sizeof plaintext);
01070            plaintextlen = 0;
01071            memset(ciphertext, 0, sizeof ciphertext);
01072            ciphertextlen = 0;
01073            fputs(buf, aesresp);
01074            continue;
01075        }
01076        /* KEY = ... */
01077        if (strncmp(buf, "KEY", 3) == 0) {
01078            i = 3;
01079            while (isspace(buf[i]) || buf[i] == '=') {
01080               i++;
01081            }
01082            for (j=0; isxdigit(buf[i]); i+=2,j++) {
01083               hex_from_2char(&buf[i], &key[j]);
01084            }
01085            keysize = j;
01086            fputs(buf, aesresp);
01087            continue;
01088        }
01089        /* IV = ... */
01090        if (strncmp(buf, "IV", 2) == 0) {
01091            mode = NSS_AES_CBC;
01092            i = 2;
01093            while (isspace(buf[i]) || buf[i] == '=') {
01094               i++;
01095            }
01096            for (j=0; j<sizeof iv; i+=2,j++) {
01097               hex_from_2char(&buf[i], &iv[j]);
01098            }
01099            fputs(buf, aesresp);
01100            continue;
01101        }
01102        /* PLAINTEXT = ... */
01103        if (strncmp(buf, "PLAINTEXT", 9) == 0) {
01104            /* sanity check */
01105            if (!encrypt) {
01106               goto loser;
01107            }
01108 
01109            i = 9;
01110            while (isspace(buf[i]) || buf[i] == '=') {
01111               i++;
01112            }
01113            for (j=0; isxdigit(buf[i]); i+=2,j++) {
01114               hex_from_2char(&buf[i], &plaintext[j]);
01115            }
01116            plaintextlen = j;
01117 
01118            rv = aes_encrypt_buf(mode, key, keysize,
01119               (mode == NSS_AES) ? NULL : iv,
01120               ciphertext, &ciphertextlen, sizeof ciphertext,
01121               plaintext, plaintextlen);
01122            if (rv != SECSuccess) {
01123               goto loser;
01124            }
01125 
01126            fputs(buf, aesresp);
01127            fputs("CIPHERTEXT = ", aesresp);
01128            to_hex_str(buf, ciphertext, ciphertextlen);
01129            fputs(buf, aesresp);
01130            fputc('\n', aesresp);
01131            continue;
01132        }
01133        /* CIPHERTEXT = ... */
01134        if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
01135            /* sanity check */
01136            if (encrypt) {
01137               goto loser;
01138            }
01139 
01140            i = 10;
01141            while (isspace(buf[i]) || buf[i] == '=') {
01142               i++;
01143            }
01144            for (j=0; isxdigit(buf[i]); i+=2,j++) {
01145               hex_from_2char(&buf[i], &ciphertext[j]);
01146            }
01147            ciphertextlen = j;
01148 
01149            rv = aes_decrypt_buf(mode, key, keysize,
01150               (mode == NSS_AES) ? NULL : iv,
01151               plaintext, &plaintextlen, sizeof plaintext,
01152               ciphertext, ciphertextlen);
01153            if (rv != SECSuccess) {
01154               goto loser;
01155            }
01156 
01157            fputs(buf, aesresp);
01158            fputs("PLAINTEXT = ", aesresp);
01159            to_hex_str(buf, plaintext, plaintextlen);
01160            fputs(buf, aesresp);
01161            fputc('\n', aesresp);
01162            continue;
01163        }
01164     }
01165 loser:
01166     fclose(aesreq);
01167 }
01168 
01169 /*
01170  * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo
01171  * Test (MCT) in ECB and CBC modes.
01172  */
01173 void
01174 aes_mct_next_key(unsigned char *key, unsigned int keysize,
01175     const unsigned char *ciphertext_1, const unsigned char *ciphertext)
01176 {
01177     int k;
01178 
01179     switch (keysize) {
01180     case 16:  /* 128-bit key */
01181        /* Key[i+1] = Key[i] xor CT[j] */
01182        for (k=0; k<16; k++) {
01183            key[k] ^= ciphertext[k];
01184        }
01185        break;
01186     case 24:  /* 192-bit key */
01187        /*
01188         * Key[i+1] = Key[i] xor (last 64-bits of
01189         *            CT[j-1] || CT[j])
01190         */
01191        for (k=0; k<8; k++) {
01192            key[k] ^= ciphertext_1[k+8];
01193        }
01194        for (k=8; k<24; k++) {
01195            key[k] ^= ciphertext[k-8];
01196        }
01197        break;
01198     case 32:  /* 256-bit key */
01199        /* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */
01200        for (k=0; k<16; k++) {
01201            key[k] ^= ciphertext_1[k];
01202        }
01203        for (k=16; k<32; k++) {
01204            key[k] ^= ciphertext[k-16];
01205        }
01206        break;
01207     }
01208 }
01209 
01210 /*
01211  * Perform the AES Monte Carlo Test (MCT) in ECB mode.  MCT exercises
01212  * our AES code in streaming mode because the plaintext or ciphertext
01213  * is generated block by block as we go, so we can't collect all the
01214  * plaintext or ciphertext in one buffer and encrypt or decrypt it in
01215  * one shot.
01216  *
01217  * reqfn is the pathname of the input REQUEST file.
01218  *
01219  * The output RESPONSE file is written to stdout.
01220  */
01221 void
01222 aes_ecb_mct(char *reqfn)
01223 {
01224     char buf[80];       /* holds one line from the input REQUEST file.
01225                          * needs to be large enough to hold the longest
01226                          * line "KEY = <64 hex digits>\n".
01227                          */
01228     FILE *aesreq;       /* input stream from the REQUEST file */
01229     FILE *aesresp;      /* output stream to the RESPONSE file */
01230     int i, j;
01231     int encrypt = 0;    /* 1 means encrypt, 0 means decrypt */
01232     unsigned char key[32];              /* 128, 192, or 256 bits */
01233     unsigned int keysize;
01234     unsigned char plaintext[16];        /* PT[j] */
01235     unsigned char plaintext_1[16];      /* PT[j-1] */
01236     unsigned char ciphertext[16];       /* CT[j] */
01237     unsigned char ciphertext_1[16];     /* CT[j-1] */
01238     unsigned char doublecheck[16];
01239     unsigned int outputlen;
01240     AESContext *cx = NULL;  /* the operation being tested */
01241     AESContext *cx2 = NULL;     /* the inverse operation done in parallel
01242                                  * to doublecheck our result.
01243                                  */
01244     SECStatus rv;
01245 
01246     aesreq = fopen(reqfn, "r");
01247     aesresp = stdout;
01248     while (fgets(buf, sizeof buf, aesreq) != NULL) {
01249        /* a comment or blank line */
01250        if (buf[0] == '#' || buf[0] == '\n') {
01251            fputs(buf, aesresp);
01252            continue;
01253        }
01254        /* [ENCRYPT] or [DECRYPT] */
01255        if (buf[0] == '[') {
01256            if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
01257               encrypt = 1;
01258            } else {
01259               encrypt = 0;
01260            }
01261            fputs(buf, aesresp);
01262            continue;
01263        }
01264        /* "COUNT = x" begins a new data set */
01265        if (strncmp(buf, "COUNT", 5) == 0) {
01266            /* zeroize the variables for the test with this data set */
01267            memset(key, 0, sizeof key);
01268            keysize = 0;
01269            memset(plaintext, 0, sizeof plaintext);
01270            memset(ciphertext, 0, sizeof ciphertext);
01271            continue;
01272        }
01273        /* KEY = ... */
01274        if (strncmp(buf, "KEY", 3) == 0) {
01275            /* Key[0] = Key */
01276            i = 3;
01277            while (isspace(buf[i]) || buf[i] == '=') {
01278               i++;
01279            }
01280            for (j=0; isxdigit(buf[i]); i+=2,j++) {
01281               hex_from_2char(&buf[i], &key[j]);
01282            }
01283            keysize = j;
01284            continue;
01285        }
01286        /* PLAINTEXT = ... */
01287        if (strncmp(buf, "PLAINTEXT", 9) == 0) {
01288            /* sanity check */
01289            if (!encrypt) {
01290               goto loser;
01291            }
01292            /* PT[0] = PT */
01293            i = 9;
01294            while (isspace(buf[i]) || buf[i] == '=') {
01295               i++;
01296            }
01297            for (j=0; j<sizeof plaintext; i+=2,j++) {
01298               hex_from_2char(&buf[i], &plaintext[j]);
01299            }
01300 
01301            for (i=0; i<100; i++) {
01302               sprintf(buf, "COUNT = %d\n", i);
01303                fputs(buf, aesresp);
01304               /* Output Key[i] */
01305               fputs("KEY = ", aesresp);
01306               to_hex_str(buf, key, keysize);
01307               fputs(buf, aesresp);
01308               fputc('\n', aesresp);
01309               /* Output PT[0] */
01310               fputs("PLAINTEXT = ", aesresp);
01311               to_hex_str(buf, plaintext, sizeof plaintext);
01312               fputs(buf, aesresp);
01313               fputc('\n', aesresp);
01314 
01315               cx = AES_CreateContext(key, NULL, NSS_AES,
01316                   PR_TRUE, keysize, 16);
01317               if (cx == NULL) {
01318                   goto loser;
01319               }
01320               /*
01321                * doublecheck our result by decrypting the result
01322                * and comparing the output with the plaintext.
01323                */
01324               cx2 = AES_CreateContext(key, NULL, NSS_AES,
01325                   PR_FALSE, keysize, 16);
01326               if (cx2 == NULL) {
01327                   goto loser;
01328               }
01329               for (j=0; j<1000; j++) {
01330                   /* Save CT[j-1] */
01331                   memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
01332 
01333                   /* CT[j] = AES(Key[i], PT[j]) */
01334                   outputlen = 0;
01335                   rv = AES_Encrypt(cx,
01336                      ciphertext, &outputlen, sizeof ciphertext,
01337                      plaintext, sizeof plaintext);
01338                   if (rv != SECSuccess) {
01339                      goto loser;
01340                   }
01341                   if (outputlen != sizeof plaintext) {
01342                      goto loser;
01343                   }
01344 
01345                   /* doublecheck our result */
01346                   outputlen = 0;
01347                   rv = AES_Decrypt(cx2,
01348                      doublecheck, &outputlen, sizeof doublecheck,
01349                      ciphertext, sizeof ciphertext);
01350                   if (rv != SECSuccess) {
01351                      goto loser;
01352                   }
01353                   if (outputlen != sizeof ciphertext) {
01354                      goto loser;
01355                   }
01356                   if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
01357                      goto loser;
01358                   }
01359 
01360                   /* PT[j+1] = CT[j] */
01361                   memcpy(plaintext, ciphertext, sizeof plaintext);
01362               }
01363               AES_DestroyContext(cx, PR_TRUE);
01364               cx = NULL;
01365               AES_DestroyContext(cx2, PR_TRUE);
01366               cx2 = NULL;
01367 
01368               /* Output CT[j] */
01369               fputs("CIPHERTEXT = ", aesresp);
01370               to_hex_str(buf, ciphertext, sizeof ciphertext);
01371               fputs(buf, aesresp);
01372               fputc('\n', aesresp);
01373 
01374               /* Key[i+1] = Key[i] xor ... */
01375               aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
01376               /* PT[0] = CT[j] */
01377               /* done at the end of the for(j) loop */
01378 
01379               fputc('\n', aesresp);
01380            }
01381 
01382            continue;
01383        }
01384        /* CIPHERTEXT = ... */
01385        if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
01386            /* sanity check */
01387            if (encrypt) {
01388               goto loser;
01389            }
01390            /* CT[0] = CT */
01391            i = 10;
01392            while (isspace(buf[i]) || buf[i] == '=') {
01393               i++;
01394            }
01395            for (j=0; isxdigit(buf[i]); i+=2,j++) {
01396               hex_from_2char(&buf[i], &ciphertext[j]);
01397            }
01398 
01399            for (i=0; i<100; i++) {
01400               sprintf(buf, "COUNT = %d\n", i);
01401                fputs(buf, aesresp);
01402               /* Output Key[i] */
01403               fputs("KEY = ", aesresp);
01404               to_hex_str(buf, key, keysize);
01405               fputs(buf, aesresp);
01406               fputc('\n', aesresp);
01407               /* Output CT[0] */
01408               fputs("CIPHERTEXT = ", aesresp);
01409               to_hex_str(buf, ciphertext, sizeof ciphertext);
01410               fputs(buf, aesresp);
01411               fputc('\n', aesresp);
01412 
01413               cx = AES_CreateContext(key, NULL, NSS_AES,
01414                   PR_FALSE, keysize, 16);
01415               if (cx == NULL) {
01416                   goto loser;
01417               }
01418               /*
01419                * doublecheck our result by encrypting the result
01420                * and comparing the output with the ciphertext.
01421                */
01422               cx2 = AES_CreateContext(key, NULL, NSS_AES,
01423                   PR_TRUE, keysize, 16);
01424               if (cx2 == NULL) {
01425                   goto loser;
01426               }
01427               for (j=0; j<1000; j++) {
01428                   /* Save PT[j-1] */
01429                   memcpy(plaintext_1, plaintext, sizeof plaintext);
01430 
01431                   /* PT[j] = AES(Key[i], CT[j]) */
01432                   outputlen = 0;
01433                   rv = AES_Decrypt(cx,
01434                      plaintext, &outputlen, sizeof plaintext,
01435                      ciphertext, sizeof ciphertext);
01436                   if (rv != SECSuccess) {
01437                      goto loser;
01438                   }
01439                   if (outputlen != sizeof ciphertext) {
01440                      goto loser;
01441                   }
01442 
01443                   /* doublecheck our result */
01444                   outputlen = 0;
01445                   rv = AES_Encrypt(cx2,
01446                      doublecheck, &outputlen, sizeof doublecheck,
01447                      plaintext, sizeof plaintext);
01448                   if (rv != SECSuccess) {
01449                      goto loser;
01450                   }
01451                   if (outputlen != sizeof plaintext) {
01452                      goto loser;
01453                   }
01454                   if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
01455                      goto loser;
01456                   }
01457 
01458                   /* CT[j+1] = PT[j] */
01459                   memcpy(ciphertext, plaintext, sizeof ciphertext);
01460               }
01461               AES_DestroyContext(cx, PR_TRUE);
01462               cx = NULL;
01463               AES_DestroyContext(cx2, PR_TRUE);
01464               cx2 = NULL;
01465 
01466               /* Output PT[j] */
01467               fputs("PLAINTEXT = ", aesresp);
01468               to_hex_str(buf, plaintext, sizeof plaintext);
01469               fputs(buf, aesresp);
01470               fputc('\n', aesresp);
01471 
01472               /* Key[i+1] = Key[i] xor ... */
01473               aes_mct_next_key(key, keysize, plaintext_1, plaintext);
01474               /* CT[0] = PT[j] */
01475               /* done at the end of the for(j) loop */
01476 
01477               fputc('\n', aesresp);
01478            }
01479 
01480            continue;
01481        }
01482     }
01483 loser:
01484     if (cx != NULL) {
01485        AES_DestroyContext(cx, PR_TRUE);
01486     }
01487     if (cx2 != NULL) {
01488        AES_DestroyContext(cx2, PR_TRUE);
01489     }
01490     fclose(aesreq);
01491 }
01492 
01493 /*
01494  * Perform the AES Monte Carlo Test (MCT) in CBC mode.  MCT exercises
01495  * our AES code in streaming mode because the plaintext or ciphertext
01496  * is generated block by block as we go, so we can't collect all the
01497  * plaintext or ciphertext in one buffer and encrypt or decrypt it in
01498  * one shot.
01499  *
01500  * reqfn is the pathname of the input REQUEST file.
01501  *
01502  * The output RESPONSE file is written to stdout.
01503  */
01504 void
01505 aes_cbc_mct(char *reqfn)
01506 {
01507     char buf[80];       /* holds one line from the input REQUEST file.
01508                          * needs to be large enough to hold the longest
01509                          * line "KEY = <64 hex digits>\n".
01510                          */
01511     FILE *aesreq;       /* input stream from the REQUEST file */
01512     FILE *aesresp;      /* output stream to the RESPONSE file */
01513     int i, j;
01514     int encrypt = 0;    /* 1 means encrypt, 0 means decrypt */
01515     unsigned char key[32];              /* 128, 192, or 256 bits */
01516     unsigned int keysize;
01517     unsigned char iv[16];
01518     unsigned char plaintext[16];        /* PT[j] */
01519     unsigned char plaintext_1[16];      /* PT[j-1] */
01520     unsigned char ciphertext[16];       /* CT[j] */
01521     unsigned char ciphertext_1[16];     /* CT[j-1] */
01522     unsigned char doublecheck[16];
01523     unsigned int outputlen;
01524     AESContext *cx = NULL;  /* the operation being tested */
01525     AESContext *cx2 = NULL;     /* the inverse operation done in parallel
01526                                  * to doublecheck our result.
01527                                  */
01528     SECStatus rv;
01529 
01530     aesreq = fopen(reqfn, "r");
01531     aesresp = stdout;
01532     while (fgets(buf, sizeof buf, aesreq) != NULL) {
01533        /* a comment or blank line */
01534        if (buf[0] == '#' || buf[0] == '\n') {
01535            fputs(buf, aesresp);
01536            continue;
01537        }
01538        /* [ENCRYPT] or [DECRYPT] */
01539        if (buf[0] == '[') {
01540            if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
01541               encrypt = 1;
01542            } else {
01543               encrypt = 0;
01544            }
01545            fputs(buf, aesresp);
01546            continue;
01547        }
01548        /* "COUNT = x" begins a new data set */
01549        if (strncmp(buf, "COUNT", 5) == 0) {
01550            /* zeroize the variables for the test with this data set */
01551            memset(key, 0, sizeof key);
01552            keysize = 0;
01553            memset(iv, 0, sizeof iv);
01554            memset(plaintext, 0, sizeof plaintext);
01555            memset(ciphertext, 0, sizeof ciphertext);
01556            continue;
01557        }
01558        /* KEY = ... */
01559        if (strncmp(buf, "KEY", 3) == 0) {
01560            /* Key[0] = Key */
01561            i = 3;
01562            while (isspace(buf[i]) || buf[i] == '=') {
01563               i++;
01564            }
01565            for (j=0; isxdigit(buf[i]); i+=2,j++) {
01566               hex_from_2char(&buf[i], &key[j]);
01567            }
01568            keysize = j;
01569            continue;
01570        }
01571        /* IV = ... */
01572        if (strncmp(buf, "IV", 2) == 0) {
01573            /* IV[0] = IV */
01574            i = 2;
01575            while (isspace(buf[i]) || buf[i] == '=') {
01576               i++;
01577            }
01578            for (j=0; j<sizeof iv; i+=2,j++) {
01579               hex_from_2char(&buf[i], &iv[j]);
01580            }
01581            continue;
01582        }
01583        /* PLAINTEXT = ... */
01584        if (strncmp(buf, "PLAINTEXT", 9) == 0) {
01585            /* sanity check */
01586            if (!encrypt) {
01587               goto loser;
01588            }
01589            /* PT[0] = PT */
01590            i = 9;
01591            while (isspace(buf[i]) || buf[i] == '=') {
01592               i++;
01593            }
01594            for (j=0; j<sizeof plaintext; i+=2,j++) {
01595               hex_from_2char(&buf[i], &plaintext[j]);
01596            }
01597 
01598            for (i=0; i<100; i++) {
01599               sprintf(buf, "COUNT = %d\n", i);
01600                fputs(buf, aesresp);
01601               /* Output Key[i] */
01602               fputs("KEY = ", aesresp);
01603               to_hex_str(buf, key, keysize);
01604               fputs(buf, aesresp);
01605               fputc('\n', aesresp);
01606               /* Output IV[i] */
01607               fputs("IV = ", aesresp);
01608               to_hex_str(buf, iv, sizeof iv);
01609               fputs(buf, aesresp);
01610               fputc('\n', aesresp);
01611               /* Output PT[0] */
01612               fputs("PLAINTEXT = ", aesresp);
01613               to_hex_str(buf, plaintext, sizeof plaintext);
01614               fputs(buf, aesresp);
01615               fputc('\n', aesresp);
01616 
01617               cx = AES_CreateContext(key, iv, NSS_AES_CBC,
01618                   PR_TRUE, keysize, 16);
01619               if (cx == NULL) {
01620                   goto loser;
01621               }
01622               /*
01623                * doublecheck our result by decrypting the result
01624                * and comparing the output with the plaintext.
01625                */
01626               cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
01627                   PR_FALSE, keysize, 16);
01628               if (cx2 == NULL) {
01629                   goto loser;
01630               }
01631               /* CT[-1] = IV[i] */
01632               memcpy(ciphertext, iv, sizeof ciphertext);
01633               for (j=0; j<1000; j++) {
01634                   /* Save CT[j-1] */
01635                   memcpy(ciphertext_1, ciphertext, sizeof ciphertext);
01636                   /*
01637                    * If ( j=0 )
01638                    *      CT[j] = AES(Key[i], IV[i], PT[j])
01639                    *      PT[j+1] = IV[i] (= CT[j-1])
01640                    * Else
01641                    *      CT[j] = AES(Key[i], PT[j])
01642                    *      PT[j+1] = CT[j-1]
01643                    */
01644                   outputlen = 0;
01645                   rv = AES_Encrypt(cx,
01646                      ciphertext, &outputlen, sizeof ciphertext,
01647                      plaintext, sizeof plaintext);
01648                   if (rv != SECSuccess) {
01649                      goto loser;
01650                   }
01651                   if (outputlen != sizeof plaintext) {
01652                      goto loser;
01653                   }
01654 
01655                   /* doublecheck our result */
01656                   outputlen = 0;
01657                   rv = AES_Decrypt(cx2,
01658                      doublecheck, &outputlen, sizeof doublecheck,
01659                      ciphertext, sizeof ciphertext);
01660                   if (rv != SECSuccess) {
01661                      goto loser;
01662                   }
01663                   if (outputlen != sizeof ciphertext) {
01664                      goto loser;
01665                   }
01666                   if (memcmp(doublecheck, plaintext, sizeof plaintext)) {
01667                      goto loser;
01668                   }
01669 
01670                   memcpy(plaintext, ciphertext_1, sizeof plaintext);
01671               }
01672               AES_DestroyContext(cx, PR_TRUE);
01673               cx = NULL;
01674               AES_DestroyContext(cx2, PR_TRUE);
01675               cx2 = NULL;
01676 
01677               /* Output CT[j] */
01678               fputs("CIPHERTEXT = ", aesresp);
01679               to_hex_str(buf, ciphertext, sizeof ciphertext);
01680               fputs(buf, aesresp);
01681               fputc('\n', aesresp);
01682 
01683               /* Key[i+1] = Key[i] xor ... */
01684               aes_mct_next_key(key, keysize, ciphertext_1, ciphertext);
01685               /* IV[i+1] = CT[j] */
01686               memcpy(iv, ciphertext, sizeof iv);
01687               /* PT[0] = CT[j-1] */
01688               /* done at the end of the for(j) loop */
01689 
01690               fputc('\n', aesresp);
01691            }
01692 
01693            continue;
01694        }
01695        /* CIPHERTEXT = ... */
01696        if (strncmp(buf, "CIPHERTEXT", 10) == 0) {
01697            /* sanity check */
01698            if (encrypt) {
01699               goto loser;
01700            }
01701            /* CT[0] = CT */
01702            i = 10;
01703            while (isspace(buf[i]) || buf[i] == '=') {
01704               i++;
01705            }
01706            for (j=0; isxdigit(buf[i]); i+=2,j++) {
01707               hex_from_2char(&buf[i], &ciphertext[j]);
01708            }
01709 
01710            for (i=0; i<100; i++) {
01711               sprintf(buf, "COUNT = %d\n", i);
01712                fputs(buf, aesresp);
01713               /* Output Key[i] */
01714               fputs("KEY = ", aesresp);
01715               to_hex_str(buf, key, keysize);
01716               fputs(buf, aesresp);
01717               fputc('\n', aesresp);
01718               /* Output IV[i] */
01719               fputs("IV = ", aesresp);
01720               to_hex_str(buf, iv, sizeof iv);
01721               fputs(buf, aesresp);
01722               fputc('\n', aesresp);
01723               /* Output CT[0] */
01724               fputs("CIPHERTEXT = ", aesresp);
01725               to_hex_str(buf, ciphertext, sizeof ciphertext);
01726               fputs(buf, aesresp);
01727               fputc('\n', aesresp);
01728 
01729               cx = AES_CreateContext(key, iv, NSS_AES_CBC,
01730                   PR_FALSE, keysize, 16);
01731               if (cx == NULL) {
01732                   goto loser;
01733               }
01734               /*
01735                * doublecheck our result by encrypting the result
01736                * and comparing the output with the ciphertext.
01737                */
01738               cx2 = AES_CreateContext(key, iv, NSS_AES_CBC,
01739                   PR_TRUE, keysize, 16);
01740               if (cx2 == NULL) {
01741                   goto loser;
01742               }
01743               /* PT[-1] = IV[i] */
01744               memcpy(plaintext, iv, sizeof plaintext);
01745               for (j=0; j<1000; j++) {
01746                   /* Save PT[j-1] */
01747                   memcpy(plaintext_1, plaintext, sizeof plaintext);
01748                   /*
01749                    * If ( j=0 )
01750                    *      PT[j] = AES(Key[i], IV[i], CT[j])
01751                    *      CT[j+1] = IV[i] (= PT[j-1])
01752                    * Else
01753                    *      PT[j] = AES(Key[i], CT[j])
01754                    *      CT[j+1] = PT[j-1]
01755                    */
01756                   outputlen = 0;
01757                   rv = AES_Decrypt(cx,
01758                      plaintext, &outputlen, sizeof plaintext,
01759                      ciphertext, sizeof ciphertext);
01760                   if (rv != SECSuccess) {
01761                      goto loser;
01762                   }
01763                   if (outputlen != sizeof ciphertext) {
01764                      goto loser;
01765                   }
01766 
01767                   /* doublecheck our result */
01768                   outputlen = 0;
01769                   rv = AES_Encrypt(cx2,
01770                      doublecheck, &outputlen, sizeof doublecheck,
01771                      plaintext, sizeof plaintext);
01772                   if (rv != SECSuccess) {
01773                      goto loser;
01774                   }
01775                   if (outputlen != sizeof plaintext) {
01776                      goto loser;
01777                   }
01778                   if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) {
01779                      goto loser;
01780                   }
01781 
01782                   memcpy(ciphertext, plaintext_1, sizeof ciphertext);
01783               }
01784               AES_DestroyContext(cx, PR_TRUE);
01785               cx = NULL;
01786               AES_DestroyContext(cx2, PR_TRUE);
01787               cx2 = NULL;
01788 
01789               /* Output PT[j] */
01790               fputs("PLAINTEXT = ", aesresp);
01791               to_hex_str(buf, plaintext, sizeof plaintext);
01792               fputs(buf, aesresp);
01793               fputc('\n', aesresp);
01794 
01795               /* Key[i+1] = Key[i] xor ... */
01796               aes_mct_next_key(key, keysize, plaintext_1, plaintext);
01797               /* IV[i+1] = PT[j] */
01798               memcpy(iv, plaintext, sizeof iv);
01799               /* CT[0] = PT[j-1] */
01800               /* done at the end of the for(j) loop */
01801 
01802               fputc('\n', aesresp);
01803            }
01804 
01805            continue;
01806        }
01807     }
01808 loser:
01809     if (cx != NULL) {
01810        AES_DestroyContext(cx, PR_TRUE);
01811     }
01812     if (cx2 != NULL) {
01813        AES_DestroyContext(cx2, PR_TRUE);
01814     }
01815     fclose(aesreq);
01816 }
01817 
01818 void write_compact_string(FILE *out, unsigned char *hash, unsigned int len)
01819 {
01820     unsigned int i;
01821     int j, count = 0, last = -1, z = 0;
01822     long start = ftell(out);
01823     for (i=0; i<len; i++) {
01824        for (j=7; j>=0; j--) {
01825            if (last < 0) {
01826               last = (hash[i] & (1 << j)) ? 1 : 0;
01827               fprintf(out, "%d ", last);
01828               count = 1;
01829            } else if (hash[i] & (1 << j)) {
01830               if (last) {
01831                   count++; 
01832               } else { 
01833                   last = 0;
01834                   fprintf(out, "%d ", count);
01835                   count = 1;
01836                   z++;
01837               }
01838            } else {
01839               if (!last) {
01840                   count++; 
01841               } else { 
01842                   last = 1;
01843                   fprintf(out, "%d ", count);
01844                   count = 1;
01845                   z++;
01846               }
01847            }
01848        }
01849     }
01850     fprintf(out, "^\n");
01851     fseek(out, start, SEEK_SET);
01852     fprintf(out, "%d ", z);
01853     fseek(out, 0, SEEK_END);
01854 }
01855 
01856 int get_next_line(FILE *req, char *key, char *val, FILE *rsp)
01857 {
01858     int ignore = 0;
01859     char *writeto = key;
01860     int w = 0;
01861     int c;
01862     while ((c = fgetc(req)) != EOF) {
01863        if (ignore) {
01864            fprintf(rsp, "%c", c);
01865            if (c == '\n') return ignore;
01866        } else if (c == '\n') {
01867            break;
01868        } else if (c == '#') {
01869            ignore = 1;
01870            fprintf(rsp, "%c", c);
01871        } else if (c == '=') {
01872            writeto[w] = '\0';
01873            w = 0;
01874            writeto = val;
01875        } else if (c == ' ' || c == '[' || c == ']') {
01876            continue;
01877        } else {
01878            writeto[w++] = c;
01879        }
01880     }
01881     writeto[w] = '\0';
01882     return (c == EOF) ? -1 : ignore;
01883 }
01884 
01885 #ifdef NSS_ENABLE_ECC
01886 typedef struct curveNameTagPairStr {
01887     char *curveName;
01888     SECOidTag curveOidTag;
01889 } CurveNameTagPair;
01890 
01891 #define DEFAULT_CURVE_OID_TAG  SEC_OID_SECG_EC_SECP192R1
01892 /* #define DEFAULT_CURVE_OID_TAG  SEC_OID_SECG_EC_SECP160R1 */
01893 
01894 static CurveNameTagPair nameTagPair[] =
01895 { 
01896   { "sect163k1", SEC_OID_SECG_EC_SECT163K1},
01897   { "nistk163", SEC_OID_SECG_EC_SECT163K1},
01898   { "sect163r1", SEC_OID_SECG_EC_SECT163R1},
01899   { "sect163r2", SEC_OID_SECG_EC_SECT163R2},
01900   { "nistb163", SEC_OID_SECG_EC_SECT163R2},
01901   { "sect193r1", SEC_OID_SECG_EC_SECT193R1},
01902   { "sect193r2", SEC_OID_SECG_EC_SECT193R2},
01903   { "sect233k1", SEC_OID_SECG_EC_SECT233K1},
01904   { "nistk233", SEC_OID_SECG_EC_SECT233K1},
01905   { "sect233r1", SEC_OID_SECG_EC_SECT233R1},
01906   { "nistb233", SEC_OID_SECG_EC_SECT233R1},
01907   { "sect239k1", SEC_OID_SECG_EC_SECT239K1},
01908   { "sect283k1", SEC_OID_SECG_EC_SECT283K1},
01909   { "nistk283", SEC_OID_SECG_EC_SECT283K1},
01910   { "sect283r1", SEC_OID_SECG_EC_SECT283R1},
01911   { "nistb283", SEC_OID_SECG_EC_SECT283R1},
01912   { "sect409k1", SEC_OID_SECG_EC_SECT409K1},
01913   { "nistk409", SEC_OID_SECG_EC_SECT409K1},
01914   { "sect409r1", SEC_OID_SECG_EC_SECT409R1},
01915   { "nistb409", SEC_OID_SECG_EC_SECT409R1},
01916   { "sect571k1", SEC_OID_SECG_EC_SECT571K1},
01917   { "nistk571", SEC_OID_SECG_EC_SECT571K1},
01918   { "sect571r1", SEC_OID_SECG_EC_SECT571R1},
01919   { "nistb571", SEC_OID_SECG_EC_SECT571R1},
01920   { "secp160k1", SEC_OID_SECG_EC_SECP160K1},
01921   { "secp160r1", SEC_OID_SECG_EC_SECP160R1},
01922   { "secp160r2", SEC_OID_SECG_EC_SECP160R2},
01923   { "secp192k1", SEC_OID_SECG_EC_SECP192K1},
01924   { "secp192r1", SEC_OID_SECG_EC_SECP192R1},
01925   { "nistp192", SEC_OID_SECG_EC_SECP192R1},
01926   { "secp224k1", SEC_OID_SECG_EC_SECP224K1},
01927   { "secp224r1", SEC_OID_SECG_EC_SECP224R1},
01928   { "nistp224", SEC_OID_SECG_EC_SECP224R1},
01929   { "secp256k1", SEC_OID_SECG_EC_SECP256K1},
01930   { "secp256r1", SEC_OID_SECG_EC_SECP256R1},
01931   { "nistp256", SEC_OID_SECG_EC_SECP256R1},
01932   { "secp384r1", SEC_OID_SECG_EC_SECP384R1},
01933   { "nistp384", SEC_OID_SECG_EC_SECP384R1},
01934   { "secp521r1", SEC_OID_SECG_EC_SECP521R1},
01935   { "nistp521", SEC_OID_SECG_EC_SECP521R1},
01936 
01937   { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
01938   { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
01939   { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
01940   { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
01941   { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
01942   { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
01943 
01944   { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
01945   { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
01946   { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
01947   { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
01948   { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
01949   { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
01950   { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
01951   { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
01952   { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
01953   { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
01954   { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
01955   { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
01956   { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
01957   { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
01958   { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
01959   { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
01960   { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
01961   { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
01962   { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
01963   { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
01964 
01965   { "secp112r1", SEC_OID_SECG_EC_SECP112R1},
01966   { "secp112r2", SEC_OID_SECG_EC_SECP112R2},
01967   { "secp128r1", SEC_OID_SECG_EC_SECP128R1},
01968   { "secp128r2", SEC_OID_SECG_EC_SECP128R2},
01969 
01970   { "sect113r1", SEC_OID_SECG_EC_SECT113R1},
01971   { "sect113r2", SEC_OID_SECG_EC_SECT113R2},
01972   { "sect131r1", SEC_OID_SECG_EC_SECT131R1},
01973   { "sect131r2", SEC_OID_SECG_EC_SECT131R2},
01974 };
01975 
01976 static SECKEYECParams * 
01977 getECParams(const char *curve)
01978 {
01979     SECKEYECParams *ecparams;
01980     SECOidData *oidData = NULL;
01981     SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
01982     int i, numCurves;
01983 
01984     if (curve != NULL) {
01985         numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair);
01986        for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); 
01987             i++) {
01988            if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
01989                curveOidTag = nameTagPair[i].curveOidTag;
01990        }
01991     }
01992 
01993     /* Return NULL if curve name is not recognized */
01994     if ((curveOidTag == SEC_OID_UNKNOWN) || 
01995        (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
01996         fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
01997        return NULL;
01998     }
01999 
02000     ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
02001 
02002     /* 
02003      * ecparams->data needs to contain the ASN encoding of an object ID (OID)
02004      * representing the named curve. The actual OID is in 
02005      * oidData->oid.data so we simply prepend 0x06 and OID length
02006      */
02007     ecparams->data[0] = SEC_ASN1_OBJECT_ID;
02008     ecparams->data[1] = oidData->oid.len;
02009     memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
02010 
02011     return ecparams;
02012 }
02013 
02014 /*
02015  * Perform the ECDSA Key Pair Generation Test.
02016  *
02017  * reqfn is the pathname of the REQUEST file.
02018  *
02019  * The output RESPONSE file is written to stdout.
02020  */
02021 void
02022 ecdsa_keypair_test(char *reqfn)
02023 {
02024     char buf[256];      /* holds one line from the input REQUEST file
02025                          * or to the output RESPONSE file.
02026                          * needs to be large enough to hold the longest
02027                          * line "Qx = <144 hex digits>\n".
02028                          */
02029     FILE *ecdsareq;     /* input stream from the REQUEST file */
02030     FILE *ecdsaresp;    /* output stream to the RESPONSE file */
02031     char curve[16];     /* "nistxddd" */
02032     ECParams *ecparams;
02033     int N;
02034     int i;
02035     unsigned int len;
02036 
02037     ecdsareq = fopen(reqfn, "r");
02038     ecdsaresp = stdout;
02039     strcpy(curve, "nist");
02040     while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
02041        /* a comment or blank line */
02042        if (buf[0] == '#' || buf[0] == '\n') {
02043            fputs(buf, ecdsaresp);
02044            continue;
02045        }
02046        /* [X-ddd] */
02047        if (buf[0] == '[') {
02048            const char *src;
02049            char *dst;
02050            SECKEYECParams *encodedparams;
02051 
02052            src = &buf[1];
02053            dst = &curve[4];
02054            *dst++ = tolower(*src);
02055            src += 2;  /* skip the hyphen */
02056            *dst++ = *src++;
02057            *dst++ = *src++;
02058            *dst++ = *src++;
02059            *dst = '\0';
02060            encodedparams = getECParams(curve);
02061            if (encodedparams == NULL) {
02062               goto loser;
02063            }
02064            if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
02065               goto loser;
02066            }
02067            SECITEM_FreeItem(encodedparams, PR_TRUE);
02068            fputs(buf, ecdsaresp);
02069            continue;
02070        }
02071        /* N = x */
02072        if (buf[0] == 'N') {
02073            if (sscanf(buf, "N = %d", &N) != 1) {
02074               goto loser;
02075            }
02076            for (i = 0; i < N; i++) {
02077               ECPrivateKey *ecpriv;
02078 
02079               if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
02080                   goto loser;
02081               }
02082               fputs("d = ", ecdsaresp);
02083               to_hex_str(buf, ecpriv->privateValue.data,
02084                         ecpriv->privateValue.len);
02085               fputs(buf, ecdsaresp);
02086               fputc('\n', ecdsaresp);
02087               if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue)
02088                   != SECSuccess) {
02089                   goto loser;
02090               }
02091               len = ecpriv->publicValue.len;
02092               if (len%2 == 0) {
02093                   goto loser;
02094               }
02095               len = (len-1)/2;
02096               if (ecpriv->publicValue.data[0]
02097                   != EC_POINT_FORM_UNCOMPRESSED) {
02098                   goto loser;
02099               }
02100               fputs("Qx = ", ecdsaresp);
02101               to_hex_str(buf, &ecpriv->publicValue.data[1], len);
02102               fputs(buf, ecdsaresp);
02103               fputc('\n', ecdsaresp);
02104               fputs("Qy = ", ecdsaresp);
02105               to_hex_str(buf, &ecpriv->publicValue.data[1+len], len);
02106               fputs(buf, ecdsaresp);
02107               fputc('\n', ecdsaresp);
02108               fputc('\n', ecdsaresp);
02109               PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
02110            }
02111            PORT_FreeArena(ecparams->arena, PR_FALSE);
02112            continue;
02113        }
02114     }
02115 loser:
02116     fclose(ecdsareq);
02117 }
02118 
02119 /*
02120  * Perform the ECDSA Public Key Validation Test.
02121  *
02122  * reqfn is the pathname of the REQUEST file.
02123  *
02124  * The output RESPONSE file is written to stdout.
02125  */
02126 void
02127 ecdsa_pkv_test(char *reqfn)
02128 {
02129     char buf[256];      /* holds one line from the input REQUEST file.
02130                          * needs to be large enough to hold the longest
02131                          * line "Qx = <144 hex digits>\n".
02132                          */
02133     FILE *ecdsareq;     /* input stream from the REQUEST file */
02134     FILE *ecdsaresp;    /* output stream to the RESPONSE file */
02135     char curve[16];     /* "nistxddd" */
02136     ECParams *ecparams = NULL;
02137     SECItem pubkey;
02138     unsigned int i;
02139     unsigned int len;
02140     PRBool keyvalid = PR_TRUE;
02141 
02142     ecdsareq = fopen(reqfn, "r");
02143     ecdsaresp = stdout;
02144     strcpy(curve, "nist");
02145     pubkey.data = NULL;
02146     while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
02147        /* a comment or blank line */
02148        if (buf[0] == '#' || buf[0] == '\n') {
02149            fputs(buf, ecdsaresp);
02150            continue;
02151        }
02152        /* [X-ddd] */
02153        if (buf[0] == '[') {
02154            const char *src;
02155            char *dst;
02156            SECKEYECParams *encodedparams;
02157 
02158            src = &buf[1];
02159            dst = &curve[4];
02160            *dst++ = tolower(*src);
02161            src += 2;  /* skip the hyphen */
02162            *dst++ = *src++;
02163            *dst++ = *src++;
02164            *dst++ = *src++;
02165            *dst = '\0';
02166            if (ecparams != NULL) {
02167               PORT_FreeArena(ecparams->arena, PR_FALSE);
02168               ecparams = NULL;
02169            }
02170            encodedparams = getECParams(curve);
02171            if (encodedparams == NULL) {
02172               goto loser;
02173            }
02174            if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
02175               goto loser;
02176            }
02177            SECITEM_FreeItem(encodedparams, PR_TRUE);
02178            len = (ecparams->fieldID.size + 7) >> 3;
02179            if (pubkey.data != NULL) {
02180               PORT_Free(pubkey.data);
02181               pubkey.data = NULL;
02182            }
02183            SECITEM_AllocItem(NULL, &pubkey, 2*len+1);
02184            if (pubkey.data == NULL) {
02185               goto loser;
02186            }
02187            pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
02188            fputs(buf, ecdsaresp);
02189            continue;
02190        }
02191        /* Qx = ... */
02192        if (strncmp(buf, "Qx", 2) == 0) {
02193            fputs(buf, ecdsaresp);
02194            i = 2;
02195            while (isspace(buf[i]) || buf[i] == '=') {
02196               i++;
02197            }
02198            keyvalid = from_hex_str(&pubkey.data[1], len, &buf[i]);
02199            continue;
02200        }
02201        /* Qy = ... */
02202        if (strncmp(buf, "Qy", 2) == 0) {
02203            fputs(buf, ecdsaresp);
02204            if (!keyvalid) {
02205               fputs("Result = F\n", ecdsaresp);
02206               continue;
02207            }
02208            i = 2;
02209            while (isspace(buf[i]) || buf[i] == '=') {
02210               i++;
02211            }
02212            keyvalid = from_hex_str(&pubkey.data[1+len], len, &buf[i]);
02213            if (!keyvalid) {
02214               fputs("Result = F\n", ecdsaresp);
02215               continue;
02216            }
02217            if (EC_ValidatePublicKey(ecparams, &pubkey) == SECSuccess) {
02218               fputs("Result = P\n", ecdsaresp);
02219            } else if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
02220               fputs("Result = F\n", ecdsaresp);
02221            } else {
02222               goto loser;
02223            }
02224            continue;
02225        }
02226     }
02227 loser:
02228     if (ecparams != NULL) {
02229        PORT_FreeArena(ecparams->arena, PR_FALSE);
02230     }
02231     if (pubkey.data != NULL) {
02232        PORT_Free(pubkey.data);
02233     }
02234     fclose(ecdsareq);
02235 }
02236 
02237 /*
02238  * Perform the ECDSA Signature Generation Test.
02239  *
02240  * reqfn is the pathname of the REQUEST file.
02241  *
02242  * The output RESPONSE file is written to stdout.
02243  */
02244 void
02245 ecdsa_siggen_test(char *reqfn)
02246 {
02247     char buf[1024];     /* holds one line from the input REQUEST file
02248                          * or to the output RESPONSE file.
02249                          * needs to be large enough to hold the longest
02250                          * line "Msg = <256 hex digits>\n".
02251                          */
02252     FILE *ecdsareq;     /* input stream from the REQUEST file */
02253     FILE *ecdsaresp;    /* output stream to the RESPONSE file */
02254     char curve[16];     /* "nistxddd" */
02255     ECParams *ecparams = NULL;
02256     int i, j;
02257     unsigned int len;
02258     unsigned char msg[512];  /* message to be signed (<= 128 bytes) */
02259     unsigned int msglen;
02260     unsigned char sha1[20];  /* SHA-1 hash (160 bits) */
02261     unsigned char sig[2*MAX_ECKEY_LEN];
02262     SECItem signature, digest;
02263 
02264     ecdsareq = fopen(reqfn, "r");
02265     ecdsaresp = stdout;
02266     strcpy(curve, "nist");
02267     while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
02268        /* a comment or blank line */
02269        if (buf[0] == '#' || buf[0] == '\n') {
02270            fputs(buf, ecdsaresp);
02271            continue;
02272        }
02273        /* [X-ddd] */
02274        if (buf[0] == '[') {
02275            const char *src;
02276            char *dst;
02277            SECKEYECParams *encodedparams;
02278 
02279            src = &buf[1];
02280            dst = &curve[4];
02281            *dst++ = tolower(*src);
02282            src += 2;  /* skip the hyphen */
02283            *dst++ = *src++;
02284            *dst++ = *src++;
02285            *dst++ = *src++;
02286            *dst = '\0';
02287            if (ecparams != NULL) {
02288               PORT_FreeArena(ecparams->arena, PR_FALSE);
02289               ecparams = NULL;
02290            }
02291            encodedparams = getECParams(curve);
02292            if (encodedparams == NULL) {
02293               goto loser;
02294            }
02295            if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
02296               goto loser;
02297            }
02298            SECITEM_FreeItem(encodedparams, PR_TRUE);
02299            fputs(buf, ecdsaresp);
02300            continue;
02301        }
02302        /* Msg = ... */
02303        if (strncmp(buf, "Msg", 3) == 0) {
02304            ECPrivateKey *ecpriv;
02305 
02306            i = 3;
02307            while (isspace(buf[i]) || buf[i] == '=') {
02308               i++;
02309            }
02310            for (j=0; isxdigit(buf[i]); i+=2,j++) {
02311               hex_from_2char(&buf[i], &msg[j]);
02312            }
02313            msglen = j;
02314            if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) {
02315               goto loser;
02316            }
02317            fputs(buf, ecdsaresp);
02318 
02319            if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
02320               goto loser;
02321            }
02322            if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue)
02323               != SECSuccess) {
02324               goto loser;
02325            }
02326            len = ecpriv->publicValue.len;
02327            if (len%2 == 0) {
02328               goto loser;
02329            }
02330            len = (len-1)/2;
02331            if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
02332               goto loser;
02333            }
02334            fputs("Qx = ", ecdsaresp);
02335            to_hex_str(buf, &ecpriv->publicValue.data[1], len);
02336            fputs(buf, ecdsaresp);
02337            fputc('\n', ecdsaresp);
02338            fputs("Qy = ", ecdsaresp);
02339            to_hex_str(buf, &ecpriv->publicValue.data[1+len], len);
02340            fputs(buf, ecdsaresp);
02341            fputc('\n', ecdsaresp);
02342 
02343            digest.type = siBuffer;
02344            digest.data = sha1;
02345            digest.len = sizeof sha1;
02346            signature.type = siBuffer;
02347            signature.data = sig;
02348            signature.len = sizeof sig;
02349            if (ECDSA_SignDigest(ecpriv, &signature, &digest) != SECSuccess) {
02350               goto loser;
02351            }
02352            len = signature.len;
02353            if (len%2 != 0) {
02354               goto loser;
02355            }
02356            len = len/2;
02357            fputs("R = ", ecdsaresp);
02358            to_hex_str(buf, &signature.data[0], len);
02359            fputs(buf, ecdsaresp);
02360            fputc('\n', ecdsaresp);
02361            fputs("S = ", ecdsaresp);
02362            to_hex_str(buf, &signature.data[len], len);
02363            fputs(buf, ecdsaresp);
02364            fputc('\n', ecdsaresp);
02365 
02366            PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
02367            continue;
02368        }
02369     }
02370 loser:
02371     if (ecparams != NULL) {
02372        PORT_FreeArena(ecparams->arena, PR_FALSE);
02373     }
02374     fclose(ecdsareq);
02375 }
02376 
02377 /*
02378  * Perform the ECDSA Signature Verification Test.
02379  *
02380  * reqfn is the pathname of the REQUEST file.
02381  *
02382  * The output RESPONSE file is written to stdout.
02383  */
02384 void
02385 ecdsa_sigver_test(char *reqfn)
02386 {
02387     char buf[1024];     /* holds one line from the input REQUEST file.
02388                          * needs to be large enough to hold the longest
02389                          * line "Msg = <256 hex digits>\n".
02390                          */
02391     FILE *ecdsareq;     /* input stream from the REQUEST file */
02392     FILE *ecdsaresp;    /* output stream to the RESPONSE file */
02393     char curve[16];     /* "nistxddd" */
02394     ECPublicKey ecpub;
02395     unsigned int i, j;
02396     unsigned int flen;  /* length in bytes of the field size */
02397     unsigned int olen;  /* length in bytes of the base point order */
02398     unsigned char msg[512];  /* message that was signed (<= 128 bytes) */
02399     unsigned int msglen;
02400     unsigned char sha1[20];  /* SHA-1 hash (160 bits) */
02401     unsigned char sig[2*MAX_ECKEY_LEN];
02402     SECItem signature, digest;
02403     PRBool keyvalid = PR_TRUE;
02404     PRBool sigvalid = PR_TRUE;
02405 
02406     ecdsareq = fopen(reqfn, "r");
02407     ecdsaresp = stdout;
02408     ecpub.ecParams.arena = NULL;
02409     strcpy(curve, "nist");
02410     while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
02411        /* a comment or blank line */
02412        if (buf[0] == '#' || buf[0] == '\n') {
02413            fputs(buf, ecdsaresp);
02414            continue;
02415        }
02416        /* [X-ddd] */
02417        if (buf[0] == '[') {
02418            const char *src;
02419            char *dst;
02420            SECKEYECParams *encodedparams;
02421            ECParams *ecparams;
02422 
02423            src = &buf[1];
02424            dst = &curve[4];
02425            *dst++ = tolower(*src);
02426            src += 2;  /* skip the hyphen */
02427            *dst++ = *src++;
02428            *dst++ = *src++;
02429            *dst++ = *src++;
02430            *dst = '\0';
02431            encodedparams = getECParams(curve);
02432            if (encodedparams == NULL) {
02433               goto loser;
02434            }
02435            if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
02436               goto loser;
02437            }
02438            SECITEM_FreeItem(encodedparams, PR_TRUE);
02439            if (ecpub.ecParams.arena != NULL) {
02440               PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
02441            }
02442            ecpub.ecParams.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
02443            if (ecpub.ecParams.arena == NULL) {
02444               goto loser;
02445            }
02446            if (EC_CopyParams(ecpub.ecParams.arena, &ecpub.ecParams, ecparams)
02447               != SECSuccess) {
02448               goto loser;
02449            }
02450            PORT_FreeArena(ecparams->arena, PR_FALSE);
02451            flen = (ecpub.ecParams.fieldID.size + 7) >> 3;
02452            olen = ecpub.ecParams.order.len;
02453            if (2*olen > sizeof sig) {
02454               goto loser;
02455            }
02456            ecpub.publicValue.type = siBuffer;
02457            ecpub.publicValue.data = NULL;
02458            ecpub.publicValue.len = 0;
02459            SECITEM_AllocItem(ecpub.ecParams.arena,
02460                            &ecpub.publicValue, 2*flen+1);
02461            if (ecpub.publicValue.data == NULL) {
02462               goto loser;
02463            }
02464            ecpub.publicValue.data[0] = EC_POINT_FORM_UNCOMPRESSED;
02465            fputs(buf, ecdsaresp);
02466            continue;
02467        }
02468        /* Msg = ... */
02469        if (strncmp(buf, "Msg", 3) == 0) {
02470            i = 3;
02471            while (isspace(buf[i]) || buf[i] == '=') {
02472               i++;
02473            }
02474            for (j=0; isxdigit(buf[i]); i+=2,j++) {
02475               hex_from_2char(&buf[i], &msg[j]);
02476            }
02477            msglen = j;
02478            if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) {
02479               goto loser;
02480            }
02481            fputs(buf, ecdsaresp);
02482 
02483            digest.type = siBuffer;
02484            digest.data = sha1;
02485            digest.len = sizeof sha1;
02486 
02487            continue;
02488        }
02489        /* Qx = ... */
02490        if (strncmp(buf, "Qx", 2) == 0) {
02491            fputs(buf, ecdsaresp);
02492            i = 2;
02493            while (isspace(buf[i]) || buf[i] == '=') {
02494               i++;
02495            }
02496            keyvalid = from_hex_str(&ecpub.publicValue.data[1], flen,
02497                                 &buf[i]);
02498            continue;
02499        }
02500        /* Qy = ... */
02501        if (strncmp(buf, "Qy", 2) == 0) {
02502            fputs(buf, ecdsaresp);
02503            if (!keyvalid) {
02504               continue;
02505            }
02506            i = 2;
02507            while (isspace(buf[i]) || buf[i] == '=') {
02508               i++;
02509            }
02510            keyvalid = from_hex_str(&ecpub.publicValue.data[1+flen], flen,
02511                                 &buf[i]);
02512            if (!keyvalid) {
02513               continue;
02514            }
02515            if (EC_ValidatePublicKey(&ecpub.ecParams, &ecpub.publicValue)
02516               != SECSuccess) {
02517               if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
02518                   keyvalid = PR_FALSE;
02519               } else {
02520                   goto loser;
02521               }
02522            }
02523            continue;
02524        }
02525        /* R = ... */
02526        if (buf[0] == 'R') {
02527            fputs(buf, ecdsaresp);
02528            i = 1;
02529            while (isspace(buf[i]) || buf[i] == '=') {
02530               i++;
02531            }
02532            sigvalid = from_hex_str(sig, olen, &buf[i]);
02533            continue;
02534        }
02535        /* S = ... */
02536        if (buf[0] == 'S') {
02537            fputs(buf, ecdsaresp);
02538            i = 1;
02539            while (isspace(buf[i]) || buf[i] == '=') {
02540               i++;
02541            }
02542            if (sigvalid) {
02543               sigvalid = from_hex_str(&sig[olen], olen, &buf[i]);
02544            }
02545            signature.type = siBuffer;
02546            signature.data = sig;
02547            signature.len = 2*olen;
02548 
02549            if (!keyvalid || !sigvalid) {
02550               fputs("Result = F\n", ecdsaresp);
02551            } else if (ECDSA_VerifyDigest(&ecpub, &signature, &digest)
02552               == SECSuccess) {
02553               fputs("Result = P\n", ecdsaresp);
02554            } else {
02555               fputs("Result = F\n", ecdsaresp);
02556            }
02557            continue;
02558        }
02559     }
02560 loser:
02561     if (ecpub.ecParams.arena != NULL) {
02562        PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
02563     }
02564     fclose(ecdsareq);
02565 }
02566 #endif /* NSS_ENABLE_ECC */
02567 
02568 /*
02569  * Perform the RNG Variable Seed Test (VST) for the RNG algorithm
02570  * "DSA - Generation of X", used both as specified and as a generic
02571  * purpose RNG.  The presence of "Q = ..." in the REQUEST file
02572  * indicates we are using the algorithm as specified.
02573  *
02574  * reqfn is the pathname of the REQUEST file.
02575  *
02576  * The output RESPONSE file is written to stdout.
02577  */
02578 void
02579 rng_vst(char *reqfn)
02580 {
02581     char buf[256];      /* holds one line from the input REQUEST file.
02582                          * needs to be large enough to hold the longest
02583                          * line "XSeed = <128 hex digits>\n".
02584                          */
02585     FILE *rngreq;       /* input stream from the REQUEST file */
02586     FILE *rngresp;      /* output stream to the RESPONSE file */
02587     unsigned int i, j;
02588     unsigned char Q[DSA_SUBPRIME_LEN];
02589     PRBool hasQ = PR_FALSE;
02590     unsigned int b;  /* 160 <= b <= 512, b is a multiple of 8 */
02591     unsigned char XKey[512/8];
02592     unsigned char XSeed[512/8];
02593     unsigned char GENX[2*SHA1_LENGTH];
02594     unsigned char DSAX[DSA_SUBPRIME_LEN];
02595     SECStatus rv;
02596 
02597     rngreq = fopen(reqfn, "r");
02598     rngresp = stdout;
02599     while (fgets(buf, sizeof buf, rngreq) != NULL) {
02600        /* a comment or blank line */
02601        if (buf[0] == '#' || buf[0] == '\n') {
02602            fputs(buf, rngresp);
02603            continue;
02604        }
02605        /* [Xchange - SHA1] */
02606        if (buf[0] == '[') {
02607            fputs(buf, rngresp);
02608            continue;
02609        }
02610        /* Q = ... */
02611        if (buf[0] == 'Q') {
02612            i = 1;
02613            while (isspace(buf[i]) || buf[i] == '=') {
02614               i++;
02615            }
02616            for (j=0; j<sizeof Q; i+=2,j++) {
02617               hex_from_2char(&buf[i], &Q[j]);
02618            }
02619            fputs(buf, rngresp);
02620            hasQ = PR_TRUE;
02621            continue;
02622        }
02623        /* "COUNT = x" begins a new data set */
02624        if (strncmp(buf, "COUNT", 5) == 0) {
02625            /* zeroize the variables for the test with this data set */
02626            b = 0;
02627            memset(XKey, 0, sizeof XKey);
02628            memset(XSeed, 0, sizeof XSeed);
02629            fputs(buf, rngresp);
02630            continue;
02631        }
02632        /* b = ... */
02633        if (buf[0] == 'b') {
02634            i = 1;
02635            while (isspace(buf[i]) || buf[i] == '=') {
02636               i++;
02637            }
02638            b = atoi(&buf[i]);
02639            if (b < 160 || b > 512 || b%8 != 0) {
02640               goto loser;
02641            }
02642            fputs(buf, rngresp);
02643            continue;
02644        }
02645        /* XKey = ... */
02646        if (strncmp(buf, "XKey", 4) == 0) {
02647            i = 4;
02648            while (isspace(buf[i]) || buf[i] == '=') {
02649               i++;
02650            }
02651            for (j=0; j<b/8; i+=2,j++) {
02652               hex_from_2char(&buf[i], &XKey[j]);
02653            }
02654            fputs(buf, rngresp);
02655            continue;
02656        }
02657        /* XSeed = ... */
02658        if (strncmp(buf, "XSeed", 5) == 0) {
02659            i = 5;
02660            while (isspace(buf[i]) || buf[i] == '=') {
02661               i++;
02662            }
02663            for (j=0; j<b/8; i+=2,j++) {
02664               hex_from_2char(&buf[i], &XSeed[j]);
02665            }
02666            fputs(buf, rngresp);
02667 
02668            rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
02669            if (rv != SECSuccess) {
02670               goto loser;
02671            }
02672            fputs("X = ", rngresp);
02673            if (hasQ) {
02674               rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
02675               if (rv != SECSuccess) {
02676                   goto loser;
02677               }
02678               to_hex_str(buf, DSAX, sizeof DSAX);
02679            } else {
02680               to_hex_str(buf, GENX, sizeof GENX);
02681            }
02682            fputs(buf, rngresp);
02683            fputc('\n', rngresp);
02684            continue;
02685        }
02686     }
02687 loser:
02688     fclose(rngreq);
02689 }
02690 
02691 /*
02692  * Perform the RNG Monte Carlo Test (MCT) for the RNG algorithm
02693  * "DSA - Generation of X", used both as specified and as a generic
02694  * purpose RNG.  The presence of "Q = ..." in the REQUEST file
02695  * indicates we are using the algorithm as specified.
02696  *
02697  * reqfn is the pathname of the REQUEST file.
02698  *
02699  * The output RESPONSE file is written to stdout.
02700  */
02701 void
02702 rng_mct(char *reqfn)
02703 {
02704     char buf[256];      /* holds one line from the input REQUEST file.
02705                          * needs to be large enough to hold the longest
02706                          * line "XSeed = <128 hex digits>\n".
02707                          */
02708     FILE *rngreq;       /* input stream from the REQUEST file */
02709     FILE *rngresp;      /* output stream to the RESPONSE file */
02710     unsigned int i, j;
02711     unsigned char Q[DSA_SUBPRIME_LEN];
02712     PRBool hasQ = PR_FALSE;
02713     unsigned int b;  /* 160 <= b <= 512, b is a multiple of 8 */
02714     unsigned char XKey[512/8];
02715     unsigned char XSeed[512/8];
02716     unsigned char GENX[2*SHA1_LENGTH];
02717     unsigned char DSAX[DSA_SUBPRIME_LEN];
02718     SECStatus rv;
02719 
02720     rngreq = fopen(reqfn, "r");
02721     rngresp = stdout;
02722     while (fgets(buf, sizeof buf, rngreq) != NULL) {
02723        /* a comment or blank line */
02724        if (buf[0] == '#' || buf[0] == '\n') {
02725            fputs(buf, rngresp);
02726            continue;
02727        }
02728        /* [Xchange - SHA1] */
02729        if (buf[0] == '[') {
02730            fputs(buf, rngresp);
02731            continue;
02732        }
02733        /* Q = ... */
02734        if (buf[0] == 'Q') {
02735            i = 1;
02736            while (isspace(buf[i]) || buf[i] == '=') {
02737               i++;
02738            }
02739            for (j=0; j<sizeof Q; i+=2,j++) {
02740               hex_from_2char(&buf[i], &Q[j]);
02741            }
02742            fputs(buf, rngresp);
02743            hasQ = PR_TRUE;
02744            continue;
02745        }
02746        /* "COUNT = x" begins a new data set */
02747        if (strncmp(buf, "COUNT", 5) == 0) {
02748            /* zeroize the variables for the test with this data set */
02749            b = 0;
02750            memset(XKey, 0, sizeof XKey);
02751            memset(XSeed, 0, sizeof XSeed);
02752            fputs(buf, rngresp);
02753            continue;
02754        }
02755        /* b = ... */
02756        if (buf[0] == 'b') {
02757            i = 1;
02758            while (isspace(buf[i]) || buf[i] == '=') {
02759               i++;
02760            }
02761            b = atoi(&buf[i]);
02762            if (b < 160 || b > 512 || b%8 != 0) {
02763               goto loser;
02764            }
02765            fputs(buf, rngresp);
02766            continue;
02767        }
02768        /* XKey = ... */
02769        if (strncmp(buf, "XKey", 4) == 0) {
02770            i = 4;
02771            while (isspace(buf[i]) || buf[i] == '=') {
02772               i++;
02773            }
02774            for (j=0; j<b/8; i+=2,j++) {
02775               hex_from_2char(&buf[i], &XKey[j]);
02776            }
02777            fputs(buf, rngresp);
02778            continue;
02779        }
02780        /* XSeed = ... */
02781        if (strncmp(buf, "XSeed", 5) == 0) {
02782            unsigned int k;
02783            i = 5;
02784            while (isspace(buf[i]) || buf[i] == '=') {
02785               i++;
02786            }
02787            for (j=0; j<b/8; i+=2,j++) {
02788               hex_from_2char(&buf[i], &XSeed[j]);
02789            }
02790            fputs(buf, rngresp);
02791 
02792            for (k = 0; k < 10000; k++) {
02793               rv = FIPS186Change_GenerateX(XKey, XSeed, GENX);
02794               if (rv != SECSuccess) {
02795                   goto loser;
02796               }
02797            }
02798            fputs("X = ", rngresp);
02799            if (hasQ) {
02800               rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX);
02801               if (rv != SECSuccess) {
02802                   goto loser;
02803               }
02804               to_hex_str(buf, DSAX, sizeof DSAX);
02805            } else {
02806               to_hex_str(buf, GENX, sizeof GENX);
02807            }
02808            fputs(buf, rngresp);
02809            fputc('\n', rngresp);
02810            continue;
02811        }
02812     }
02813 loser:
02814     fclose(rngreq);
02815 }
02816 
02817 /*
02818  * Calculate the SHA Message Digest 
02819  *
02820  * MD = Message digest 
02821  * MDLen = length of Message Digest and SHA_Type
02822  * msg = message to digest 
02823  * msgLen = length of message to digest
02824  */
02825 SECStatus sha_calcMD(unsigned char *MD, unsigned int MDLen, unsigned char *msg, unsigned int msgLen) 
02826 {    
02827     SECStatus   sha_status = SECFailure;
02828 
02829     if (MDLen == SHA1_LENGTH) {
02830         sha_status = SHA1_HashBuf(MD, msg, msgLen);
02831     } else if (MDLen == SHA256_LENGTH) {
02832         sha_status = SHA256_HashBuf(MD, msg, msgLen);
02833     } else if (MDLen == SHA384_LENGTH) {
02834         sha_status = SHA384_HashBuf(MD, msg, msgLen);
02835     } else if (MDLen == SHA512_LENGTH) {
02836         sha_status = SHA512_HashBuf(MD, msg, msgLen);
02837     }
02838 
02839     return sha_status;
02840 }
02841 
02842 /*
02843  * Perform the SHA Monte Carlo Test
02844  *
02845  * MDLen = length of Message Digest and SHA_Type
02846  * seed = input seed value
02847  * resp = is the output response file. 
02848  */
02849 SECStatus sha_mct_test(unsigned int MDLen, unsigned char *seed, FILE *resp) 
02850 {
02851     int i, j;
02852     unsigned int msgLen = MDLen*3;
02853     unsigned char MD_i3[HASH_LENGTH_MAX];  /* MD[i-3] */
02854     unsigned char MD_i2[HASH_LENGTH_MAX];  /* MD[i-2] */
02855     unsigned char MD_i1[HASH_LENGTH_MAX];  /* MD[i-1] */
02856     unsigned char MD_i[HASH_LENGTH_MAX];   /* MD[i] */
02857     unsigned char msg[HASH_LENGTH_MAX*3];
02858     char buf[HASH_LENGTH_MAX*2 + 1];  /* MAX buf MD_i as a hex string */
02859 
02860     for (j=0; j<100; j++) {
02861         /* MD_0 = MD_1 = MD_2 = seed */
02862         memcpy(MD_i3, seed, MDLen);
02863         memcpy(MD_i2, seed, MDLen);
02864         memcpy(MD_i1, seed, MDLen);
02865 
02866         for (i=3; i < 1003; i++) {
02867             /* Mi = MD[i-3] || MD [i-2] || MD [i-1] */
02868             memcpy(msg, MD_i3, MDLen);
02869             memcpy(&msg[MDLen], MD_i2, MDLen);
02870             memcpy(&msg[MDLen*2], MD_i1,MDLen); 
02871 
02872             /* MDi = SHA(Msg) */
02873             if (sha_calcMD(MD_i, MDLen,   
02874                            msg, msgLen) != SECSuccess) {
02875                 return SECFailure;
02876             }
02877 
02878             /* save MD[i-3] MD[i-2]  MD[i-1] */
02879             memcpy(MD_i3, MD_i2, MDLen);
02880             memcpy(MD_i2, MD_i1, MDLen);
02881             memcpy(MD_i1, MD_i, MDLen);
02882 
02883         }
02884 
02885         /* seed = MD_i */
02886         memcpy(seed, MD_i, MDLen);
02887 
02888         sprintf(buf, "COUNT = %d\n", j);
02889         fputs(buf, resp);
02890 
02891         /* output MD_i */
02892         fputs("MD = ", resp);
02893         to_hex_str(buf, MD_i, MDLen);
02894         fputs(buf, resp);
02895         fputc('\n', resp);
02896     }
02897 
02898     return SECSuccess;
02899 }
02900 
02901 /*
02902  * Perform the SHA Tests.
02903  *
02904  * reqfn is the pathname of the input REQUEST file.
02905  *
02906  * The output RESPONSE file is written to stdout.
02907  */
02908 void sha_test(char *reqfn) 
02909 {
02910     unsigned int i, j;
02911     unsigned int MDlen;   /* the length of the Message Digest in Bytes  */
02912     unsigned int msgLen;  /* the length of the input Message in Bytes */
02913     unsigned char *msg = NULL; /* holds the message to digest.*/
02914     size_t bufSize = 25608; /*MAX buffer size */
02915     char *buf = NULL;      /* holds one line from the input REQUEST file.*/
02916     unsigned char seed[HASH_LENGTH_MAX];   /* max size of seed 64 bytes */
02917     unsigned char MD[HASH_LENGTH_MAX];     /* message digest */
02918 
02919     FILE *req;       /* input stream from the REQUEST file */
02920     FILE *resp;      /* output stream to the RESPONSE file */
02921 
02922     buf = PORT_ZAlloc(bufSize);
02923     if (buf == NULL) {
02924         goto loser;
02925     }      
02926 
02927     /* zeroize the variables for the test with this data set */
02928     memset(seed, 0, sizeof seed);
02929 
02930     req = fopen(reqfn, "r");
02931     resp = stdout;
02932     while (fgets(buf, bufSize, req) != NULL) {
02933 
02934         /* a comment or blank line */
02935         if (buf[0] == '#' || buf[0] == '\n') {
02936             fputs(buf, resp);
02937             continue;
02938         }
02939         /* [L = Length of the Message Digest and sha_type */
02940         if (buf[0] == '[') {
02941             if (strncmp(&buf[1], "L ", 1) == 0) {
02942                 i = 2;
02943                 while (isspace(buf[i]) || buf[i] == '=') {
02944                     i++;
02945                 }
02946                 MDlen = atoi(&buf[i]);
02947                 fputs(buf, resp);
02948                 continue;
02949             }
02950         }
02951         /* Len = Length of the Input Message Length  ... */
02952         if (strncmp(buf, "Len", 3) == 0) {
02953             i = 3;
02954             while (isspace(buf[i]) || buf[i] == '=') {
02955                 i++;
02956             }
02957             if (msg) {
02958                 PORT_ZFree(msg,msgLen);
02959                 msg = NULL;
02960             }
02961             msgLen = atoi(&buf[i]); /* in bits */
02962             msgLen = msgLen/8; /* convert to bytes */
02963             fputs(buf, resp);
02964             msg = PORT_ZAlloc(msgLen);
02965             if (msg == NULL && msgLen != 0) {
02966                 goto loser;
02967             } 
02968             continue;
02969         }
02970         /* MSG = ... */
02971         if (strncmp(buf, "Msg", 3) == 0) {
02972             i = 3;
02973             while (isspace(buf[i]) || buf[i] == '=') {
02974                 i++;
02975             }
02976             for (j=0; j< msgLen; i+=2,j++) {
02977                 hex_from_2char(&buf[i], &msg[j]);
02978             }
02979            fputs(buf, resp);
02980            /* calculate the Message Digest */ 
02981            memset(MD, 0, sizeof MD);
02982            if (sha_calcMD(MD, MDlen,   
02983                           msg, msgLen) != SECSuccess) {
02984                goto loser;
02985            }
02986 
02987            fputs("MD = ", resp);
02988            to_hex_str(buf, MD, MDlen);
02989            fputs(buf, resp);
02990            fputc('\n', resp);
02991 
02992            continue;
02993         }
02994         /* Seed = ... */
02995         if (strncmp(buf, "Seed", 4) == 0) {
02996             i = 4;
02997             while (isspace(buf[i]) || buf[i] == '=') {
02998                 i++;
02999             }
03000             for (j=0; j<sizeof seed; i+=2,j++) {
03001                 hex_from_2char(&buf[i], &seed[j]);
03002             }                                     
03003 
03004             fputs(buf, resp);
03005             fputc('\n', resp);
03006 
03007             /* do the Monte Carlo test */
03008             if (sha_mct_test(MDlen, seed, resp) != SECSuccess) {
03009                 goto loser; 
03010             }
03011 
03012             continue;
03013         }
03014     }
03015 loser:
03016     fclose(req);
03017     if (buf) {
03018         PORT_ZFree(buf, bufSize);
03019     }
03020     if (msg) {
03021         PORT_ZFree(msg, msgLen);
03022     }
03023 }
03024 
03025 /****************************************************/
03026 /* HMAC SHA-X calc                                  */
03027 /* hmac_computed - the computed HMAC                */
03028 /* hmac_length - the length of the computed HMAC    */
03029 /* secret_key - secret key to HMAC                  */
03030 /* secret_key_length - length of secret key,        */
03031 /* message - message to HMAC                        */
03032 /* message_length - length ofthe message            */
03033 /****************************************************/
03034 static SECStatus
03035 hmac_calc(unsigned char *hmac_computed,
03036           const unsigned int hmac_length,
03037           const unsigned char *secret_key,
03038           const unsigned int secret_key_length,
03039           const unsigned char *message,
03040           const unsigned int message_length,
03041           const HASH_HashType hashAlg )
03042 {
03043     SECStatus hmac_status = SECFailure;
03044     HMACContext *cx = NULL;
03045     SECHashObject *hashObj = NULL;
03046     unsigned int bytes_hashed = 0;
03047 
03048     hashObj = (SECHashObject *) HASH_GetRawHashObject(hashAlg);
03049  
03050     if (!hashObj) 
03051         return( SECFailure );
03052 
03053     cx = HMAC_Create(hashObj, secret_key, 
03054                      secret_key_length, 
03055                      PR_TRUE);  /* PR_TRUE for in FIPS mode */
03056 
03057     if (cx == NULL) 
03058         return( SECFailure );
03059 
03060     HMAC_Begin(cx);
03061     HMAC_Update(cx, message, message_length);
03062     hmac_status = HMAC_Finish(cx, hmac_computed, &bytes_hashed, 
03063                               hmac_length);
03064 
03065     HMAC_Destroy(cx, PR_TRUE);
03066 
03067     return( hmac_status );
03068 }
03069 
03070 /*
03071  * Perform the HMAC Tests.
03072  *
03073  * reqfn is the pathname of the input REQUEST file.
03074  *
03075  * The output RESPONSE file is written to stdout.
03076  */
03077 void hmac_test(char *reqfn) 
03078 {
03079     unsigned int i, j;
03080     size_t bufSize =      288;    /* MAX buffer size */
03081     char *buf = NULL;  /* holds one line from the input REQUEST file.*/
03082     unsigned int keyLen;          /* Key Length */  
03083     unsigned char key[140];       /* key MAX size = 140 */
03084     unsigned int msgLen = 128;    /* the length of the input  */
03085                                   /*  Message is always 128 Bytes */
03086     unsigned char *msg = NULL;    /* holds the message to digest.*/
03087     unsigned int HMACLen;         /* the length of the HMAC Bytes  */
03088     unsigned char HMAC[HASH_LENGTH_MAX];  /* computed HMAC */
03089     HASH_HashType hash_alg;       /* HMAC type */
03090 
03091     FILE *req;       /* input stream from the REQUEST file */
03092     FILE *resp;      /* output stream to the RESPONSE file */
03093 
03094     buf = PORT_ZAlloc(bufSize);
03095     if (buf == NULL) {
03096         goto loser;
03097     }      
03098     msg = PORT_ZAlloc(msgLen);
03099     memset(msg, 0, msgLen);
03100     if (msg == NULL) {
03101         goto loser;
03102     } 
03103 
03104     req = fopen(reqfn, "r");
03105     resp = stdout;
03106     while (fgets(buf, bufSize, req) != NULL) {
03107 
03108         /* a comment or blank line */
03109         if (buf[0] == '#' || buf[0] == '\n') {
03110             fputs(buf, resp);
03111             continue;
03112         }
03113         /* [L = Length of the MAC and HASH_type */
03114         if (buf[0] == '[') {
03115             if (strncmp(&buf[1], "L ", 1) == 0) {
03116                 i = 2;
03117                 while (isspace(buf[i]) || buf[i] == '=') {
03118                     i++;
03119                 }
03120                 /* HMACLen will get reused for Tlen */
03121                 HMACLen = atoi(&buf[i]);
03122                 /* set the HASH algorithm for HMAC */
03123                 if (HMACLen == SHA1_LENGTH) {
03124                     hash_alg = HASH_AlgSHA1;
03125                 } else if (HMACLen == SHA256_LENGTH) {
03126                     hash_alg = HASH_AlgSHA256;
03127                 } else if (HMACLen == SHA384_LENGTH) {
03128                     hash_alg = HASH_AlgSHA384;
03129                 } else if (HMACLen == SHA512_LENGTH) {
03130                     hash_alg = HASH_AlgSHA512;
03131                 } else {
03132                     goto loser;
03133                 }
03134                 fputs(buf, resp);
03135                 continue;
03136             }
03137         }
03138         /* Count = test iteration number*/
03139         if (strncmp(buf, "Count ", 5) == 0) {    
03140             /* count can just be put into resp file */
03141             fputs(buf, resp);
03142             /* zeroize the variables for the test with this data set */
03143             keyLen = 0; 
03144             HMACLen = 0;
03145             memset(key, 0, sizeof key);     
03146             memset(msg, 0, sizeof msg);  
03147             memset(HMAC, 0, sizeof HMAC);
03148             continue;
03149         }
03150         /* KLen = Length of the Input Secret Key ... */
03151         if (strncmp(buf, "Klen", 4) == 0) {
03152             i = 4;
03153             while (isspace(buf[i]) || buf[i] == '=') {
03154                 i++;
03155             }
03156             keyLen = atoi(&buf[i]); /* in bytes */
03157             fputs(buf, resp);
03158             continue;
03159         }
03160         /* key = the secret key for the key to MAC */
03161         if (strncmp(buf, "Key", 3) == 0) {
03162             i = 3;
03163             while (isspace(buf[i]) || buf[i] == '=') {
03164                 i++;
03165             }
03166             for (j=0; j< keyLen; i+=2,j++) {
03167                 hex_from_2char(&buf[i], &key[j]);
03168             }
03169            fputs(buf, resp);
03170         }
03171         /* TLen = Length of the calculated HMAC */
03172         if (strncmp(buf, "Tlen", 4) == 0) {
03173             i = 4;
03174             while (isspace(buf[i]) || buf[i] == '=') {
03175                 i++;
03176             }
03177             HMACLen = atoi(&buf[i]); /* in bytes */
03178             fputs(buf, resp);
03179             continue;
03180         }
03181         /* MSG = to HMAC always 128 bytes for these tests */
03182         if (strncmp(buf, "Msg", 3) == 0) {
03183             i = 3;
03184             while (isspace(buf[i]) || buf[i] == '=') {
03185                 i++;
03186             }
03187             for (j=0; j< msgLen; i+=2,j++) {
03188                 hex_from_2char(&buf[i], &msg[j]);
03189             }
03190            fputs(buf, resp);
03191            /* calculate the HMAC and output */ 
03192            if (hmac_calc(HMAC, HMACLen, key, keyLen,   
03193                          msg, msgLen, hash_alg) != SECSuccess) {
03194                goto loser;
03195            }
03196            fputs("MAC = ", resp);
03197            to_hex_str(buf, HMAC, HMACLen);
03198            fputs(buf, resp);
03199            fputc('\n', resp);
03200            continue;
03201         }
03202     }
03203 loser:
03204     fclose(req);
03205     if (buf) {
03206         PORT_ZFree(buf, bufSize);
03207     }
03208     if (msg) {
03209         PORT_ZFree(msg, msgLen);
03210     }
03211 }
03212 
03213 /*
03214  * Perform the DSA Key Pair Generation Test.
03215  *
03216  * reqfn is the pathname of the REQUEST file.
03217  *
03218  * The output RESPONSE file is written to stdout.
03219  */
03220 void
03221 dsa_keypair_test(char *reqfn)
03222 {
03223     char buf[260];       /* holds one line from the input REQUEST file
03224                          * or to the output RESPONSE file.
03225                          * 257 to hold (128 public key (x2 for HEX) + 1'\n'
03226                          */
03227     FILE *dsareq;     /* input stream from the REQUEST file */
03228     FILE *dsaresp;    /* output stream to the RESPONSE file */
03229     int N;            /* number of time to generate key pair */
03230     int modulus;
03231     int i;
03232     PQGParams *pqg = NULL;
03233     PQGVerify *vfy = NULL;
03234     int keySizeIndex;   /* index for valid key sizes */
03235 
03236     dsareq = fopen(reqfn, "r");
03237     dsaresp = stdout;
03238     while (fgets(buf, sizeof buf, dsareq) != NULL) {
03239         /* a comment or blank line */
03240         if (buf[0] == '#' || buf[0] == '\n') {
03241             fputs(buf, dsaresp);
03242             continue;
03243         }
03244 
03245         /* [Mod = x] */
03246         if (buf[0] == '[') {
03247             if(pqg!=NULL) {
03248                 PQG_DestroyParams(pqg);
03249                 pqg = NULL;
03250             }
03251             if(vfy!=NULL) {
03252                 PQG_DestroyVerify(vfy);
03253                 vfy = NULL;
03254             }
03255 
03256             if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
03257                 goto loser;
03258             }
03259             fputs(buf, dsaresp);
03260             fputc('\n', dsaresp);
03261 
03262             /*****************************************************************
03263              * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
03264              * that points to a valid key size.
03265              */
03266             keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
03267             if(keySizeIndex == -1 || modulus<512 || modulus>1024) {
03268                fprintf(dsaresp,
03269                     "DSA key size must be a multiple of 64 between 512 "
03270                     "and 1024, inclusive");
03271                 goto loser;
03272             }
03273 
03274             /* Generate the parameters P, Q, and G */
03275             if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
03276                 &pqg, &vfy) != SECSuccess) {
03277                 fprintf(dsaresp, "ERROR: Unable to generate PQG parameters");
03278                 goto loser;
03279             }
03280 
03281             /* output P, Q, and G */
03282             to_hex_str(buf, pqg->prime.data, pqg->prime.len);
03283             fprintf(dsaresp, "P = %s\n", buf);
03284             to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
03285             fprintf(dsaresp, "Q = %s\n", buf);
03286             to_hex_str(buf, pqg->base.data, pqg->base.len);
03287             fprintf(dsaresp, "G = %s\n\n", buf);
03288             continue;
03289         }
03290         /* N = ...*/
03291         if (buf[0] == 'N') {
03292 
03293             if (sscanf(buf, "N = %d", &N) != 1) {
03294                 goto loser;
03295             }
03296             /* Generate a DSA key, and output the key pair for N times */
03297             for (i = 0; i < N; i++) {
03298                 DSAPrivateKey *dsakey = NULL;
03299                 if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
03300                     fprintf(dsaresp, "ERROR: Unable to generate DSA key");
03301                     goto loser;
03302                 }
03303                 to_hex_str(buf, dsakey->privateValue.data,
03304                            dsakey->privateValue.len);
03305                 fprintf(dsaresp, "X = %s\n", buf);
03306                 to_hex_str(buf, dsakey->publicValue.data,
03307                            dsakey->publicValue.len);
03308                 fprintf(dsaresp, "Y = %s\n\n", buf);
03309                 PORT_FreeArena(dsakey->params.arena, PR_TRUE);
03310                 dsakey = NULL;
03311             }
03312             continue;
03313         }
03314 
03315     }
03316 loser:
03317     fclose(dsareq);
03318 }
03319 
03320 /*
03321  * Perform the DSA Domain Parameter Validation Test.
03322  *
03323  * reqfn is the pathname of the REQUEST file.
03324  *
03325  * The output RESPONSE file is written to stdout.
03326  */
03327 void
03328 dsa_pqgver_test(char *reqfn)
03329 {
03330     char buf[263];      /* holds one line from the input REQUEST file
03331                          * or to the output RESPONSE file.
03332                          * 260 to hold (128 public key (x2 for HEX) + P = ...
03333                          */
03334     FILE *dsareq;     /* input stream from the REQUEST file */
03335     FILE *dsaresp;    /* output stream to the RESPONSE file */
03336     int modulus; 
03337     unsigned int i, j;
03338     PQGParams pqg;
03339     PQGVerify vfy;
03340     unsigned int pghSize;        /* size for p, g, and h */
03341 
03342     dsareq = fopen(reqfn, "r");
03343     dsaresp = stdout;
03344     memset(&pqg, 0, sizeof(pqg));
03345     memset(&vfy, 0, sizeof(vfy));
03346 
03347     while (fgets(buf, sizeof buf, dsareq) != NULL) {
03348         /* a comment or blank line */
03349         if (buf[0] == '#' || buf[0] == '\n') {
03350             fputs(buf, dsaresp);
03351             continue;
03352         }
03353 
03354         /* [Mod = x] */
03355         if (buf[0] == '[') {
03356 
03357             if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
03358                 goto loser;
03359             }
03360 
03361             if (pqg.prime.data) { /* P */
03362                 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
03363             }
03364             if (pqg.subPrime.data) { /* Q */
03365                 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
03366             }
03367             if (pqg.base.data) {    /* G */
03368                 SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
03369             }
03370             if (vfy.seed.data) {   /* seed */
03371                 SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
03372             }
03373             if (vfy.h.data) {     /* H */
03374                 SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
03375             }
03376 
03377             fputs(buf, dsaresp);
03378 
03379             /*calculate the size of p, g, and h then allocate items  */
03380             pghSize = modulus/8;
03381             SECITEM_AllocItem(NULL, &pqg.prime, pghSize);
03382             SECITEM_AllocItem(NULL, &pqg.base, pghSize);
03383             SECITEM_AllocItem(NULL, &vfy.h, pghSize);
03384             pqg.prime.len = pqg.base.len = vfy.h.len = pghSize;
03385             /* seed and q are always 20 bytes */
03386             SECITEM_AllocItem(NULL, &vfy.seed, 20);
03387             SECITEM_AllocItem(NULL, &pqg.subPrime, 20);
03388             vfy.seed.len = pqg.subPrime.len = 20;
03389             vfy.counter = 0;
03390 
03391             continue;
03392         }
03393         /* P = ... */
03394         if (buf[0] == 'P') {
03395             i = 1;
03396             while (isspace(buf[i]) || buf[i] == '=') {
03397                 i++;
03398             }
03399             for (j=0; j< pqg.prime.len; i+=2,j++) {
03400                 hex_from_2char(&buf[i], &pqg.prime.data[j]);
03401             }
03402 
03403             fputs(buf, dsaresp);
03404             continue;
03405         }
03406 
03407         /* Q = ... */
03408         if (buf[0] == 'Q') {
03409             i = 1;
03410             while (isspace(buf[i]) || buf[i] == '=') {
03411                 i++;
03412             }
03413             for (j=0; j< pqg.subPrime.len; i+=2,j++) {
03414                 hex_from_2char(&buf[i], &pqg.subPrime.data[j]);
03415             }
03416 
03417             fputs(buf, dsaresp);
03418             continue;
03419         }
03420 
03421         /* G = ... */
03422         if (buf[0] == 'G') {
03423             i = 1;
03424             while (isspace(buf[i]) || buf[i] == '=') {
03425                 i++;
03426             }
03427             for (j=0; j< pqg.base.len; i+=2,j++) {
03428                 hex_from_2char(&buf[i], &pqg.base.data[j]);
03429             }
03430 
03431             fputs(buf, dsaresp);
03432             continue;
03433         }
03434 
03435         /* Seed = ... */
03436         if (strncmp(buf, "Seed", 4) == 0) {
03437             i = 4;
03438             while (isspace(buf[i]) || buf[i] == '=') {
03439                 i++;
03440             }
03441             for (j=0; j< vfy.seed.len; i+=2,j++) {
03442                 hex_from_2char(&buf[i], &vfy.seed.data[j]);
03443             }
03444 
03445             fputs(buf, dsaresp);
03446             continue;
03447         }
03448 
03449         /* c = ... */
03450         if (buf[0] == 'c') {
03451 
03452             if (sscanf(buf, "c = %u", &vfy.counter) != 1) {
03453                 goto loser;
03454             }
03455 
03456             fputs(buf, dsaresp);
03457             continue;
03458         }
03459 
03460         /* H = ... */
03461         if (buf[0] == 'H') {
03462             SECStatus rv, result = SECFailure;
03463 
03464             i = 1;
03465             while (isspace(buf[i]) || buf[i] == '=') {
03466                 i++;
03467             }
03468             for (j=0; j< vfy.h.len; i+=2,j++) {
03469                 hex_from_2char(&buf[i], &vfy.h.data[j]);
03470             }
03471             fputs(buf, dsaresp);
03472 
03473             /* Verify the Parameters */
03474             rv = PQG_VerifyParams(&pqg, &vfy, &result);
03475             if (rv != SECSuccess) {
03476                 goto loser;
03477             }
03478             if (result == SECSuccess) {
03479                 fprintf(dsaresp, "Result = P\n");
03480             } else {
03481                 fprintf(dsaresp, "Result = F\n");
03482             }
03483             continue;
03484         }
03485     }
03486 loser:
03487     fclose(dsareq);
03488     if (pqg.prime.data) { /* P */
03489         SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
03490     }
03491     if (pqg.subPrime.data) { /* Q */
03492         SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
03493     }
03494     if (pqg.base.data) {    /* G */
03495         SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
03496     }
03497     if (vfy.seed.data) {   /* seed */
03498         SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
03499     }
03500     if (vfy.h.data) {     /* H */
03501         SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
03502     }
03503 
03504 }
03505 
03506 /*
03507  * Perform the DSA Public Key Validation Test.
03508  *
03509  * reqfn is the pathname of the REQUEST file.
03510  *
03511  * The output RESPONSE file is written to stdout.
03512  */
03513 void
03514 dsa_pqggen_test(char *reqfn)
03515 {
03516     char buf[263];      /* holds one line from the input REQUEST file
03517                          * or to the output RESPONSE file.
03518                          * 263 to hold seed = (128 public key (x2 for HEX)
03519                          */
03520     FILE *dsareq;     /* input stream from the REQUEST file */
03521     FILE *dsaresp;    /* output stream to the RESPONSE file */
03522     int N;            /* number of times to generate parameters */
03523     int modulus; 
03524     int i;
03525     unsigned int j;
03526     PQGParams *pqg = NULL;
03527     PQGVerify *vfy = NULL;
03528     unsigned int keySizeIndex;
03529 
03530     dsareq = fopen(reqfn, "r");
03531     dsaresp = stdout;
03532     while (fgets(buf, sizeof buf, dsareq) != NULL) {
03533         /* a comment or blank line */
03534         if (buf[0] == '#' || buf[0] == '\n') {
03535             fputs(buf, dsaresp);
03536             continue;
03537         }
03538 
03539         /* [Mod = ... ] */
03540         if (buf[0] == '[') {
03541 
03542             if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
03543                 goto loser;
03544             }
03545 
03546             fputs(buf, dsaresp);
03547             fputc('\n', dsaresp);
03548 
03549             /****************************************************************
03550              * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
03551              * that points to a valid key size.
03552              */
03553             keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
03554             if(keySizeIndex == -1 || modulus<512 || modulus>1024) {
03555                fprintf(dsaresp,
03556                     "DSA key size must be a multiple of 64 between 512 "
03557                     "and 1024, inclusive");
03558                 goto loser;
03559             }
03560 
03561             continue;
03562         }
03563         /* N = ... */
03564         if (buf[0] == 'N') {
03565 
03566             if (sscanf(buf, "N = %d", &N) != 1) {
03567                 goto loser;
03568             }
03569             for (i = 0; i < N; i++) {
03570                 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
03571                     &pqg, &vfy) != SECSuccess) {
03572                     fprintf(dsaresp,
03573                             "ERROR: Unable to generate PQG parameters");
03574                     goto loser;
03575                 }
03576                 to_hex_str(buf, pqg->prime.data, pqg->prime.len);
03577                 fprintf(dsaresp, "P = %s\n", buf);
03578                 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
03579                 fprintf(dsaresp, "Q = %s\n", buf);
03580                 to_hex_str(buf, pqg->base.data, pqg->base.len);
03581                 fprintf(dsaresp, "G = %s\n", buf);
03582                 to_hex_str(buf, vfy->seed.data, vfy->seed.len);
03583                 fprintf(dsaresp, "Seed = %s\n", buf);
03584                 fprintf(dsaresp, "c = %d\n", vfy->counter);
03585                 to_hex_str(buf, vfy->h.data, vfy->h.len);
03586                 fputs("H = ", dsaresp);
03587                 for (j=vfy->h.len; j<pqg->prime.len; j++) {
03588                     fprintf(dsaresp, "00");
03589                 }
03590                 fprintf(dsaresp, "%s\n", buf);
03591                 fputc('\n', dsaresp);
03592                 if(pqg!=NULL) {
03593                     PQG_DestroyParams(pqg);
03594                     pqg = NULL;
03595                 }
03596                 if(vfy!=NULL) {
03597                     PQG_DestroyVerify(vfy);
03598                     vfy = NULL;
03599                 }
03600             }
03601 
03602             continue;
03603         }
03604 
03605     }
03606 loser:
03607     fclose(dsareq);
03608     if(pqg!=NULL) {
03609         PQG_DestroyParams(pqg);
03610     }
03611     if(vfy!=NULL) {
03612         PQG_DestroyVerify(vfy);
03613     }
03614 }
03615 
03616 /*
03617  * Perform the DSA Signature Generation Test.
03618  *
03619  * reqfn is the pathname of the REQUEST file.
03620  *
03621  * The output RESPONSE file is written to stdout.
03622  */
03623 void
03624 dsa_siggen_test(char *reqfn)
03625 {
03626     char buf[263];       /* holds one line from the input REQUEST file
03627                          * or to the output RESPONSE file.
03628                          * max for Msg = ....
03629                          */
03630     FILE *dsareq;     /* input stream from the REQUEST file */
03631     FILE *dsaresp;    /* output stream to the RESPONSE file */
03632     int modulus;          
03633     int i, j;
03634     PQGParams *pqg = NULL;
03635     PQGVerify *vfy = NULL;
03636     DSAPrivateKey *dsakey = NULL;
03637     int keySizeIndex;     /* index for valid key sizes */
03638     unsigned char sha1[20];  /* SHA-1 hash (160 bits) */
03639     unsigned char sig[DSA_SIGNATURE_LEN];
03640     SECItem digest, signature;
03641 
03642     dsareq = fopen(reqfn, "r");
03643     dsaresp = stdout;
03644 
03645     while (fgets(buf, sizeof buf, dsareq) != NULL) {
03646         /* a comment or blank line */
03647         if (buf[0] == '#' || buf[0] == '\n') {
03648             fputs(buf, dsaresp);
03649             continue;
03650         }
03651 
03652         /* [Mod = x] */
03653         if (buf[0] == '[') {
03654             if(pqg!=NULL) {
03655                 PQG_DestroyParams(pqg);
03656                 pqg = NULL;
03657             }
03658             if(vfy!=NULL) {
03659                 PQG_DestroyVerify(vfy);
03660                 vfy = NULL;
03661             }
03662             if (dsakey != NULL) {
03663                     PORT_FreeArena(dsakey->params.arena, PR_TRUE);
03664                     dsakey = NULL;
03665             }
03666 
03667             if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
03668                 goto loser;
03669             }
03670             fputs(buf, dsaresp);
03671             fputc('\n', dsaresp);
03672 
03673             /****************************************************************
03674             * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
03675             * that points to a valid key size.
03676             */
03677             keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
03678             if(keySizeIndex == -1 || modulus<512 || modulus>1024) {
03679                 fprintf(dsaresp,
03680                     "DSA key size must be a multiple of 64 between 512 "
03681                     "and 1024, inclusive");
03682                 goto loser;
03683             }
03684 
03685             /* Generate PQG and output PQG */
03686             if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
03687                 &pqg, &vfy) != SECSuccess) {
03688                 fprintf(dsaresp, "ERROR: Unable to generate PQG parameters");
03689                 goto loser;
03690             }
03691             to_hex_str(buf, pqg->prime.data, pqg->prime.len);
03692             fprintf(dsaresp, "P = %s\n", buf);
03693             to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
03694             fprintf(dsaresp, "Q = %s\n", buf);
03695             to_hex_str(buf, pqg->base.data, pqg->base.len);
03696             fprintf(dsaresp, "G = %s\n", buf);
03697 
03698             /* create DSA Key */
03699             if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
03700                 fprintf(dsaresp, "ERROR: Unable to generate DSA key");
03701                 goto loser;
03702             }
03703             continue;
03704         }
03705 
03706         /* Msg = ... */
03707         if (strncmp(buf, "Msg", 3) == 0) {
03708             unsigned char msg[128]; /* MAX msg 128 */
03709             unsigned int len = 0;
03710 
03711             memset(sha1, 0, sizeof sha1);
03712             memset(sig,  0, sizeof sig);
03713 
03714             i = 3;
03715             while (isspace(buf[i]) || buf[i] == '=') {
03716                 i++;
03717             }
03718             for (j=0; isxdigit(buf[i]); i+=2,j++) {
03719                 hex_from_2char(&buf[i], &msg[j]);
03720             }
03721             if (SHA1_HashBuf(sha1, msg, j) != SECSuccess) {
03722                  fprintf(dsaresp, "ERROR: Unable to generate SHA1 digest");
03723                  goto loser;
03724             }
03725 
03726             digest.type = siBuffer;
03727             digest.data = sha1;
03728             digest.len = sizeof sha1;
03729             signature.type = siBuffer;
03730             signature.data = sig;
03731             signature.len = sizeof sig;
03732 
03733             if (DSA_SignDigest(dsakey, &signature, &digest) != SECSuccess) {
03734                 fprintf(dsaresp, "ERROR: Unable to generate DSA signature");
03735                 goto loser;
03736             }
03737             len = signature.len;
03738             if (len%2 != 0) {
03739                 goto loser;
03740             }
03741             len = len/2;
03742 
03743             /* output the orginal Msg, and generated Y, R, and S */
03744             fputs(buf, dsaresp);
03745             fputc('\n', dsaresp);
03746             to_hex_str(buf, dsakey->publicValue.data,
03747                        dsakey->publicValue.len);
03748             fprintf(dsaresp, "Y = %s\n", buf);
03749             to_hex_str(buf, &signature.data[0], len);
03750             fprintf(dsaresp, "R = %s\n", buf);
03751             to_hex_str(buf, &signature.data[len], len);
03752             fprintf(dsaresp, "S = %s\n", buf);
03753             continue;
03754         }
03755 
03756     }
03757 loser:
03758     fclose(dsareq);
03759     if(pqg != NULL) {
03760         PQG_DestroyParams(pqg);
03761         pqg = NULL;
03762     }
03763     if(vfy != NULL) {
03764         PQG_DestroyVerify(vfy);
03765         vfy = NULL;
03766     }
03767     if (dsaKey) {
03768         PORT_FreeArena(dsakey->params.arena, PR_TRUE);
03769         dsakey = NULL;
03770     }
03771 }
03772 
03773  /*
03774  * Perform the DSA Signature Verification Test.
03775  *
03776  * reqfn is the pathname of the REQUEST file.
03777  *
03778  * The output RESPONSE file is written to stdout.
03779  */
03780 void
03781 dsa_sigver_test(char *reqfn)
03782 {
03783     char buf[263];       /* holds one line from the input REQUEST file
03784                          * or to the output RESPONSE file.
03785                          * max for Msg = ....
03786                          */
03787     FILE *dsareq;     /* input stream from the REQUEST file */
03788     FILE *dsaresp;    /* output stream to the RESPONSE file */
03789     int modulus;  
03790     unsigned int i, j;
03791     SECItem digest, signature;
03792     DSAPublicKey pubkey;
03793     unsigned int pgySize;        /* size for p, g, and y */
03794     unsigned char sha1[20];  /* SHA-1 hash (160 bits) */
03795     unsigned char sig[DSA_SIGNATURE_LEN];
03796 
03797     dsareq = fopen(reqfn, "r");
03798     dsaresp = stdout;
03799     memset(&pubkey, 0, sizeof(pubkey));
03800 
03801     while (fgets(buf, sizeof buf, dsareq) != NULL) {
03802         /* a comment or blank line */
03803         if (buf[0] == '#' || buf[0] == '\n') {
03804             fputs(buf, dsaresp);
03805             continue;
03806         }
03807 
03808         /* [Mod = x] */
03809         if (buf[0] == '[') {
03810 
03811             if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
03812                 goto loser;
03813             }
03814 
03815             if (pubkey.params.prime.data) { /* P */
03816                 SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
03817             }
03818             if (pubkey.params.subPrime.data) { /* Q */
03819                 SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
03820             }
03821             if (pubkey.params.base.data) {    /* G */
03822                 SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
03823             }
03824             if (pubkey.publicValue.data) {    /* Y */
03825                 SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
03826             }
03827             fputs(buf, dsaresp);
03828 
03829             /* calculate the size of p, g, and y then allocate items */
03830             pgySize = modulus/8;
03831             SECITEM_AllocItem(NULL, &pubkey.params.prime, pgySize);
03832             SECITEM_AllocItem(NULL, &pubkey.params.base, pgySize);
03833             SECITEM_AllocItem(NULL, &pubkey.publicValue, pgySize);
03834             pubkey.params.prime.len = pubkey.params.base.len = pgySize;
03835             pubkey.publicValue.len = pgySize;
03836 
03837             /* q always 20 bytes */
03838             SECITEM_AllocItem(NULL, &pubkey.params.subPrime, 20);
03839             pubkey.params.subPrime.len = 20;
03840 
03841             continue;
03842         }
03843         /* P = ... */
03844         if (buf[0] == 'P') {
03845             i = 1;
03846             while (isspace(buf[i]) || buf[i] == '=') {
03847                 i++;
03848             }
03849             memset(pubkey.params.prime.data, 0, pubkey.params.prime.len);
03850             for (j=0; j< pubkey.params.prime.len; i+=2,j++) {
03851                 hex_from_2char(&buf[i], &pubkey.params.prime.data[j]);
03852             }
03853 
03854             fputs(buf, dsaresp);
03855             continue;
03856         }
03857 
03858         /* Q = ... */
03859         if (buf[0] == 'Q') {
03860             i = 1;
03861             while (isspace(buf[i]) || buf[i] == '=') {
03862                 i++;
03863             }
03864             memset(pubkey.params.subPrime.data, 0, pubkey.params.subPrime.len);
03865             for (j=0; j< pubkey.params.subPrime.len; i+=2,j++) {
03866                 hex_from_2char(&buf[i], &pubkey.params.subPrime.data[j]);
03867             }
03868 
03869             fputs(buf, dsaresp);
03870             continue;
03871         }
03872 
03873         /* G = ... */
03874         if (buf[0] == 'G') {
03875             i = 1;
03876             while (isspace(buf[i]) || buf[i] == '=') {
03877                 i++;
03878             }
03879             memset(pubkey.params.base.data, 0, pubkey.params.base.len);
03880             for (j=0; j< pubkey.params.base.len; i+=2,j++) {
03881                 hex_from_2char(&buf[i], &pubkey.params.base.data[j]);
03882             }
03883 
03884             fputs(buf, dsaresp);
03885             continue;
03886         }
03887 
03888         /* Msg = ... */
03889         if (strncmp(buf, "Msg", 3) == 0) {
03890             unsigned char msg[128]; /* MAX msg 128 */
03891             memset(sha1, 0, sizeof sha1);
03892 
03893             i = 3;
03894             while (isspace(buf[i]) || buf[i] == '=') {
03895                 i++;
03896             }
03897             for (j=0; isxdigit(buf[i]); i+=2,j++) {
03898                 hex_from_2char(&buf[i], &msg[j]);
03899             }
03900             if (SHA1_HashBuf(sha1, msg, j) != SECSuccess) {
03901                 fprintf(dsaresp, "ERROR: Unable to generate SHA1 digest");
03902                 goto loser;
03903             }
03904 
03905             fputs(buf, dsaresp);
03906             continue;
03907         }
03908 
03909         /* Y = ... */
03910         if (buf[0] == 'Y') {
03911             i = 1;
03912             while (isspace(buf[i]) || buf[i] == '=') {
03913                 i++;
03914             }
03915             memset(pubkey.publicValue.data, 0, pubkey.params.subPrime.len);
03916             for (j=0; j< pubkey.publicValue.len; i+=2,j++) {
03917                 hex_from_2char(&buf[i], &pubkey.publicValue.data[j]);
03918             }
03919 
03920             fputs(buf, dsaresp);
03921             continue;
03922         }
03923 
03924         /* R = ... */
03925         if (buf[0] == 'R') {
03926             memset(sig,  0, sizeof sig);
03927             i = 1;
03928             while (isspace(buf[i]) || buf[i] == '=') {
03929                 i++;
03930             }
03931             for (j=0; j< DSA_SUBPRIME_LEN; i+=2,j++) {
03932                 hex_from_2char(&buf[i], &sig[j]);
03933             }
03934 
03935             fputs(buf, dsaresp);
03936             continue;
03937         }
03938 
03939         /* S = ... */
03940         if (buf[0] == 'S') {
03941             i = 1;
03942             while (isspace(buf[i]) || buf[i] == '=') {
03943                 i++;
03944             }
03945             for (j=DSA_SUBPRIME_LEN; j< DSA_SIGNATURE_LEN; i+=2,j++) {
03946                 hex_from_2char(&buf[i], &sig[j]);
03947             }
03948             fputs(buf, dsaresp);
03949 
03950             digest.type = siBuffer;
03951             digest.data = sha1;
03952             digest.len = sizeof sha1;
03953             signature.type = siBuffer;
03954             signature.data = sig;
03955             signature.len = sizeof sig;
03956 
03957             if (DSA_VerifyDigest(&pubkey, &signature, &digest) == SECSuccess) {
03958                 fprintf(dsaresp, "Result = P\n");
03959             } else {
03960                 fprintf(dsaresp, "Result = F\n");
03961             }
03962             continue;
03963         }
03964     }
03965 loser:
03966     fclose(dsareq);
03967     if (pubkey.params.prime.data) { /* P */
03968         SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
03969     }
03970     if (pubkey.params.subPrime.data) { /* Q */
03971         SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
03972     }
03973     if (pubkey.params.base.data) {    /* G */
03974         SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
03975     }
03976     if (pubkey.publicValue.data) {    /* Y */
03977         SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
03978     }
03979 }
03980 
03981 /*
03982  * Perform the RSA Signature Generation Test.
03983  *
03984  * reqfn is the pathname of the REQUEST file.
03985  *
03986  * The output RESPONSE file is written to stdout.
03987  */
03988 void
03989 rsa_siggen_test(char *reqfn)
03990 {
03991     char buf[2*RSA_MAX_TEST_MODULUS_BYTES+1];
03992                         /* buf holds one line from the input REQUEST file
03993                          * or to the output RESPONSE file.
03994                          * 2x for HEX output + 1 for \n
03995                          */
03996     FILE *rsareq;     /* input stream from the REQUEST file */
03997     FILE *rsaresp;    /* output stream to the RESPONSE file */
03998     int i, j;
03999     unsigned char  sha[HASH_LENGTH_MAX];    /* SHA digest */
04000     unsigned int   shaLength = 0;           /* length of SHA */
04001     HASH_HashType  shaAlg = HASH_AlgNULL;   /* type of SHA Alg */
04002     SECOidTag      shaOid = SEC_OID_UNKNOWN;
04003     int modulus;                                /* the Modulus size */
04004     int  publicExponent  = DEFAULT_RSA_PUBLIC_EXPONENT;
04005     SECItem pe = {0, 0, 0 };
04006     unsigned char pubEx[4];
04007     int peCount = 0;
04008 
04009     RSAPrivateKey  *rsaBlapiPrivKey = NULL;   /* holds RSA private and
04010                                               * public keys */
04011     RSAPublicKey   *rsaBlapiPublicKey = NULL; /* hold RSA public key */
04012 
04013     rsareq = fopen(reqfn, "r");
04014     rsaresp = stdout;
04015 
04016     /* calculate the exponent */
04017     for (i=0; i < 4; i++) {
04018         if (peCount || (publicExponent &
04019                 ((unsigned long)0xff000000L >> (i*8)))) {
04020             pubEx[peCount] =
04021                 (unsigned char)((publicExponent >> (3-i)*8) & 0xff);
04022             peCount++;
04023         }
04024     }
04025     pe.len = peCount;
04026     pe.data = &pubEx[0];
04027     pe.type = siBuffer;
04028 
04029     while (fgets(buf, sizeof buf, rsareq) != NULL) {
04030         /* a comment or blank line */
04031         if (buf[0] == '#' || buf[0] == '\n') {
04032             fputs(buf, rsaresp);
04033             continue;
04034         }
04035 
04036         /* [mod = ...] */
04037         if (buf[0] == '[') {
04038 
04039             if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
04040                 goto loser;
04041             }
04042             if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
04043                 fprintf(rsaresp,"ERROR: modulus greater than test maximum\n");
04044                 goto loser;
04045             }
04046 
04047             fputs(buf, rsaresp);
04048 
04049             if (rsaBlapiPrivKey != NULL) {
04050                 PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
04051                 rsaBlapiPrivKey = NULL;
04052                 rsaBlapiPublicKey = NULL;
04053             }
04054 
04055             rsaBlapiPrivKey = RSA_NewKey(modulus, &pe);
04056             if (rsaBlapiPrivKey == NULL) {
04057                 fprintf(rsaresp, "Error unable to create RSA key\n");
04058                 goto loser;
04059             }
04060 
04061             to_hex_str(buf, rsaBlapiPrivKey->modulus.data,
04062                        rsaBlapiPrivKey->modulus.len);
04063             fprintf(rsaresp, "\nn = %s\n\n", buf);
04064             to_hex_str(buf, rsaBlapiPrivKey->publicExponent.data,
04065                        rsaBlapiPrivKey->publicExponent.len);
04066             fprintf(rsaresp, "e = %s\n", buf);
04067             /* convert private key to public key.  Memory
04068              * is freed with private key's arena  */
04069             rsaBlapiPublicKey = (RSAPublicKey *)PORT_ArenaAlloc(
04070                                                   rsaBlapiPrivKey->arena,
04071                                                   sizeof(RSAPublicKey));
04072 
04073             rsaBlapiPublicKey->modulus.len = rsaBlapiPrivKey->modulus.len;
04074             rsaBlapiPublicKey->modulus.data = rsaBlapiPrivKey->modulus.data;
04075             rsaBlapiPublicKey->publicExponent.len =
04076                 rsaBlapiPrivKey->publicExponent.len;
04077             rsaBlapiPublicKey->publicExponent.data =
04078                 rsaBlapiPrivKey->publicExponent.data;
04079             continue;
04080         }
04081 
04082         /* SHAAlg = ... */
04083         if (strncmp(buf, "SHAAlg", 6) == 0) {
04084            i = 6;
04085            while (isspace(buf[i]) || buf[i] == '=') {
04086                i++;
04087            }
04088            /* set the SHA Algorithm */
04089            if (strncmp(&buf[i], "SHA1", 4) == 0) {
04090                 shaAlg = HASH_AlgSHA1;
04091            } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
04092                 shaAlg = HASH_AlgSHA256;
04093            } else if (strncmp(&buf[i], "SHA384", 6)== 0) {
04094                shaAlg = HASH_AlgSHA384;
04095            } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
04096                shaAlg = HASH_AlgSHA512;
04097            } else {
04098                fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
04099                goto loser;
04100            }
04101            fputs(buf, rsaresp);
04102            continue;
04103 
04104         }
04105         /* Msg = ... */
04106         if (strncmp(buf, "Msg", 3) == 0) {
04107 
04108             unsigned char msg[128]; /* MAX msg 128 */
04109             unsigned int rsa_bytes_signed;
04110             unsigned char rsa_computed_signature[RSA_MAX_TEST_MODULUS_BYTES];
04111             SECStatus       rv = SECFailure;
04112             NSSLOWKEYPublicKey  * rsa_public_key;
04113             NSSLOWKEYPrivateKey * rsa_private_key;
04114             NSSLOWKEYPrivateKey   low_RSA_private_key = { NULL,
04115                                                 NSSLOWKEYRSAKey, };
04116             NSSLOWKEYPublicKey    low_RSA_public_key = { NULL,
04117                                                 NSSLOWKEYRSAKey, };
04118 
04119             low_RSA_private_key.u.rsa = *rsaBlapiPrivKey;
04120             low_RSA_public_key.u.rsa = *rsaBlapiPublicKey;
04121 
04122             rsa_private_key = &low_RSA_private_key;
04123             rsa_public_key = &low_RSA_public_key;
04124 
04125             memset(sha, 0, sizeof sha);
04126             memset(msg, 0, sizeof msg);
04127             rsa_bytes_signed = 0;
04128             memset(rsa_computed_signature, 0, sizeof rsa_computed_signature);
04129 
04130             i = 3;
04131             while (isspace(buf[i]) || buf[i] == '=') {
04132                 i++;
04133             }
04134             for (j=0; isxdigit(buf[i]) && j < sizeof(msg); i+=2,j++) {
04135                 hex_from_2char(&buf[i], &msg[j]);
04136             }
04137 
04138             if (shaAlg == HASH_AlgSHA1) {
04139                 if (SHA1_HashBuf(sha, msg, j) != SECSuccess) {
04140                      fprintf(rsaresp, "ERROR: Unable to generate SHA1");
04141                      goto loser;
04142                 }
04143                 shaLength = SHA1_LENGTH;
04144                 shaOid = SEC_OID_SHA1;
04145             } else if (shaAlg == HASH_AlgSHA256) {
04146                 if (SHA256_HashBuf(sha, msg, j) != SECSuccess) {
04147                      fprintf(rsaresp, "ERROR: Unable to generate SHA256");
04148                      goto loser;
04149                 }
04150                 shaLength = SHA256_LENGTH;
04151                 shaOid = SEC_OID_SHA256;
04152             } else if (shaAlg == HASH_AlgSHA384) {
04153                 if (SHA384_HashBuf(sha, msg, j) != SECSuccess) {
04154                      fprintf(rsaresp, "ERROR: Unable to generate SHA384");
04155                      goto loser;
04156                 }
04157                 shaLength = SHA384_LENGTH;
04158                 shaOid = SEC_OID_SHA384;
04159             } else if (shaAlg == HASH_AlgSHA512) {
04160                 if (SHA512_HashBuf(sha, msg, j) != SECSuccess) {
04161                      fprintf(rsaresp, "ERROR: Unable to generate SHA512");
04162                      goto loser;
04163                 }
04164                 shaLength = SHA512_LENGTH;
04165                 shaOid = SEC_OID_SHA512;
04166             } else {
04167                 fprintf(rsaresp, "ERROR: SHAAlg not defined.");
04168                 goto loser;
04169             }
04170 
04171             /* Perform RSA signature with the RSA private key. */
04172             rv = RSA_HashSign( shaOid,
04173                                rsa_private_key,
04174                                rsa_computed_signature,
04175                                &rsa_bytes_signed,
04176                                nsslowkey_PrivateModulusLen(rsa_private_key),
04177                                sha,
04178                                shaLength);
04179 
04180             if( rv != SECSuccess ) {
04181                  fprintf(rsaresp, "ERROR: RSA_HashSign failed");
04182                  goto loser;
04183             }
04184 
04185             /* Output the signature */
04186             fputs(buf, rsaresp);
04187             to_hex_str(buf, rsa_computed_signature, rsa_bytes_signed);
04188             fprintf(rsaresp, "S = %s\n", buf);
04189 
04190             /* Perform RSA verification with the RSA public key. */
04191             rv = RSA_HashCheckSign( shaOid,
04192                                     rsa_public_key,
04193                                     rsa_computed_signature,
04194                                     rsa_bytes_signed,
04195                                     sha,
04196                                     shaLength);
04197             if( rv != SECSuccess ) {
04198                  fprintf(rsaresp, "ERROR: RSA_HashCheckSign failed");
04199                  goto loser;
04200             }
04201             continue;
04202         }
04203     }
04204 loser:
04205     fclose(rsareq);
04206 
04207     if (rsaBlapiPrivKey != NULL) {
04208         /* frees private and public key */
04209         PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
04210         rsaBlapiPrivKey = NULL;
04211         rsaBlapiPublicKey = NULL;
04212     }
04213 
04214 }
04215 /*
04216  * Perform the RSA Signature Verification Test.
04217  *
04218  * reqfn is the pathname of the REQUEST file.
04219  *
04220  * The output RESPONSE file is written to stdout.
04221  */
04222 void
04223 rsa_sigver_test(char *reqfn)
04224 {
04225     char buf[2*RSA_MAX_TEST_MODULUS_BYTES+7];
04226                         /* buf holds one line from the input REQUEST file
04227                          * or to the output RESPONSE file.
04228                          * s = 2x for HEX output + 1 for \n
04229                          */
04230     FILE *rsareq;     /* input stream from the REQUEST file */
04231     FILE *rsaresp;    /* output stream to the RESPONSE file */
04232     int i, j;
04233     unsigned char   sha[HASH_LENGTH_MAX];   /* SHA digest */
04234     unsigned int    shaLength = 0;              /* actual length of the digest */
04235     HASH_HashType   shaAlg = HASH_AlgNULL;
04236     SECOidTag       shaOid = SEC_OID_UNKNOWN;
04237     int modulus = 0;                            /* the Modulus size */
04238     unsigned char   signature[513];    /* largest signature size + '\n' */
04239     unsigned int    signatureLength = 0;   /* actual length of the signature */
04240     PRBool keyvalid = PR_TRUE;
04241 
04242     RSAPublicKey   rsaBlapiPublicKey; /* hold RSA public key */
04243 
04244     rsareq = fopen(reqfn, "r");
04245     rsaresp = stdout;
04246     memset(&rsaBlapiPublicKey, 0, sizeof(RSAPublicKey));
04247 
04248     while (fgets(buf, sizeof buf, rsareq) != NULL) {
04249         /* a comment or blank line */
04250         if (buf[0] == '#' || buf[0] == '\n') {
04251             fputs(buf, rsaresp);
04252             continue;
04253         }
04254 
04255         /* [Mod = ...] */
04256         if (buf[0] == '[') {
04257             unsigned int flen;  /* length in bytes of the field size */
04258 
04259             if (rsaBlapiPublicKey.modulus.data) { /* n */
04260                 SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
04261             }
04262             if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
04263                 goto loser;
04264             }
04265 
04266             if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
04267                 fprintf(rsaresp,"ERROR: modulus greater than test maximum\n");
04268                 goto loser;
04269             }
04270 
04271             fputs(buf, rsaresp);
04272 
04273             signatureLength = flen = modulus/8;
04274 
04275             SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.modulus, flen);
04276             if (rsaBlapiPublicKey.modulus.data == NULL) {
04277                 goto loser;
04278             }
04279             continue;
04280         }
04281 
04282         /* n = ... modulus */
04283         if (buf[0] == 'n') {
04284             i = 1;
04285             while (isspace(buf[i]) || buf[i] == '=') {
04286                 i++;
04287             }
04288             keyvalid = from_hex_str(&rsaBlapiPublicKey.modulus.data[0],
04289                                     rsaBlapiPublicKey.modulus.len,
04290                                     &buf[i]);
04291 
04292             if (!keyvalid) {
04293                 fprintf(rsaresp, "ERROR: rsa_sigver n not valid.\n");
04294                                  goto loser;
04295             }
04296             fputs(buf, rsaresp);
04297             continue;
04298         }
04299 
04300         /* SHAAlg = ... */
04301         if (strncmp(buf, "SHAAlg", 6) == 0) {
04302            i = 6;
04303            while (isspace(buf[i]) || buf[i] == '=') {
04304                i++;
04305            }
04306            /* set the SHA Algorithm */
04307            if (strncmp(&buf[i], "SHA1", 4) == 0) {
04308                 shaAlg = HASH_AlgSHA1;
04309            } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
04310                 shaAlg = HASH_AlgSHA256;
04311            } else if (strncmp(&buf[i], "SHA384", 6) == 0) {
04312                shaAlg = HASH_AlgSHA384;
04313            } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
04314                shaAlg = HASH_AlgSHA512;
04315            } else {
04316                fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
04317                goto loser;
04318            }
04319            fputs(buf, rsaresp);
04320            continue;
04321         }
04322 
04323         /* e = ... public Key */
04324         if (buf[0] == 'e') {
04325             unsigned char data[RSA_MAX_TEST_EXPONENT_BYTES];
04326             unsigned char t;
04327 
04328             memset(data, 0, sizeof data);
04329 
04330             if (rsaBlapiPublicKey.publicExponent.data) { /* e */
04331                 SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
04332             }
04333 
04334             i = 1;
04335             while (isspace(buf[i]) || buf[i] == '=') {
04336                 i++;
04337             }
04338             /* skip leading zero's */
04339             while (isxdigit(buf[i])) {
04340                 hex_from_2char(&buf[i], &t);
04341                 if (t == 0) {
04342                     i+=2;
04343                 } else break;
04344             }
04345         
04346             /* get the exponent */
04347             for (j=0; isxdigit(buf[i]) && j < sizeof data; i+=2,j++) {
04348                 hex_from_2char(&buf[i], &data[j]);
04349             }
04350 
04351             if (j == 0) { j = 1; }  /* to handle 1 byte length exponents */
04352 
04353             SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.publicExponent,  j);
04354             if (rsaBlapiPublicKey.publicExponent.data == NULL) {
04355                 goto loser;
04356             }
04357 
04358             for (i=0; i < j; i++) {
04359                 rsaBlapiPublicKey.publicExponent.data[i] = data[i];
04360             }
04361 
04362             fputs(buf, rsaresp);
04363             continue;
04364         }
04365 
04366         /* Msg = ... */
04367         if (strncmp(buf, "Msg", 3) == 0) {
04368             unsigned char msg[128]; /* MAX msg 128 */
04369 
04370             memset(sha, 0, sizeof sha);
04371             memset(msg, 0, sizeof msg);
04372 
04373             i = 3;
04374             while (isspace(buf[i]) || buf[i] == '=') {
04375                 i++;
04376             }
04377 
04378             for (j=0; isxdigit(buf[i]) && j < sizeof msg; i+=2,j++) {
04379                 hex_from_2char(&buf[i], &msg[j]);
04380             }
04381 
04382             if (shaAlg == HASH_AlgSHA1) {
04383                 if (SHA1_HashBuf(sha, msg, j) != SECSuccess) {
04384                      fprintf(rsaresp, "ERROR: Unable to generate SHA1");
04385                      goto loser;
04386                 }
04387                 shaLength = SHA1_LENGTH;
04388                 shaOid = SEC_OID_SHA1;
04389             } else if (shaAlg == HASH_AlgSHA256) {
04390                 if (SHA256_HashBuf(sha, msg, j) != SECSuccess) {
04391                      fprintf(rsaresp, "ERROR: Unable to generate SHA256");
04392                      goto loser;
04393                 }
04394                 shaLength = SHA256_LENGTH;
04395                 shaOid = SEC_OID_SHA256;
04396             } else if (shaAlg == HASH_AlgSHA384) {
04397                 if (SHA384_HashBuf(sha, msg, j) != SECSuccess) {
04398                      fprintf(rsaresp, "ERROR: Unable to generate SHA384");
04399                      goto loser;
04400                 }
04401                 shaLength = SHA384_LENGTH;
04402                 shaOid = SEC_OID_SHA384;
04403             } else if (shaAlg == HASH_AlgSHA512) {
04404                 if (SHA512_HashBuf(sha, msg, j) != SECSuccess) {
04405                      fprintf(rsaresp, "ERROR: Unable to generate SHA512");
04406                      goto loser;
04407                 }
04408                 shaLength = SHA512_LENGTH;
04409                 shaOid = SEC_OID_SHA512;
04410             } else {
04411                 fprintf(rsaresp, "ERROR: SHAAlg not defined.");
04412                 goto loser;
04413             }
04414 
04415             fputs(buf, rsaresp);
04416             continue;
04417 
04418         }
04419 
04420         /* S = ... */
04421         if (buf[0] == 'S') {
04422             SECStatus rv = SECFailure;
04423             NSSLOWKEYPublicKey  * rsa_public_key;
04424             NSSLOWKEYPublicKey    low_RSA_public_key = { NULL,
04425                                                   NSSLOWKEYRSAKey, };
04426 
04427             /* convert to a low RSA public key */
04428             low_RSA_public_key.u.rsa = rsaBlapiPublicKey;
04429             rsa_public_key = &low_RSA_public_key;
04430 
04431             memset(signature, 0, sizeof(signature));
04432             i = 1;
04433             while (isspace(buf[i]) || buf[i] == '=') {
04434                 i++;
04435             }
04436 
04437             for (j=0; isxdigit(buf[i]) && j < sizeof signature; i+=2,j++) {
04438                 hex_from_2char(&buf[i], &signature[j]);
04439             }
04440 
04441             signatureLength = j;
04442             fputs(buf, rsaresp);
04443 
04444             /* Perform RSA verification with the RSA public key. */
04445             rv = RSA_HashCheckSign( shaOid,
04446                                     rsa_public_key,
04447                                     signature,
04448                                     signatureLength,
04449                                     sha,
04450                                     shaLength);
04451             if( rv == SECSuccess ) {
04452                 fputs("Result = P\n", rsaresp);
04453             } else {
04454                 fputs("Result = F\n", rsaresp);
04455             }
04456             continue;
04457         }
04458     }
04459 loser:
04460     fclose(rsareq);
04461     if (rsaBlapiPublicKey.modulus.data) { /* n */
04462         SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
04463     }
04464     if (rsaBlapiPublicKey.publicExponent.data) { /* e */
04465         SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
04466     }
04467 }
04468 
04469 int main(int argc, char **argv)
04470 {
04471     if (argc < 2) exit (-1);
04472     NSS_NoDB_Init(NULL);
04473     /*************/
04474     /*   TDEA    */
04475     /*************/
04476     if (strcmp(argv[1], "tdea") == 0) {
04477         /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
04478         if (strcmp(argv[2], "kat") == 0) {
04479             /* Known Answer Test (KAT) */
04480             tdea_kat_mmt(argv[4]);     
04481         } else if (strcmp(argv[2], "mmt") == 0) {
04482             /* Multi-block Message Test (MMT) */
04483                 tdea_kat_mmt(argv[4]);
04484         } else if (strcmp(argv[2], "mct") == 0) {
04485                 /* Monte Carlo Test (MCT) */
04486                 if (strcmp(argv[3], "ecb") == 0) {
04487                     /* ECB mode */
04488                     tdea_mct(NSS_DES_EDE3, argv[4]); 
04489                 } else if (strcmp(argv[3], "cbc") == 0) {
04490                     /* CBC mode */
04491                     tdea_mct(NSS_DES_EDE3_CBC, argv[4]);
04492                 }
04493         }
04494     /*************/
04495     /*   AES     */
04496     /*************/
04497     } else if (strcmp(argv[1], "aes") == 0) {
04498        /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
04499        if (       strcmp(argv[2], "kat") == 0) {
04500            /* Known Answer Test (KAT) */
04501            aes_kat_mmt(argv[4]);
04502        } else if (strcmp(argv[2], "mmt") == 0) {
04503            /* Multi-block Message Test (MMT) */
04504            aes_kat_mmt(argv[4]);
04505        } else if (strcmp(argv[2], "mct") == 0) {
04506            /* Monte Carlo Test (MCT) */
04507            if (       strcmp(argv[3], "ecb") == 0) {
04508               /* ECB mode */
04509               aes_ecb_mct(argv[4]);
04510            } else if (strcmp(argv[3], "cbc") == 0) {
04511               /* CBC mode */
04512               aes_cbc_mct(argv[4]);
04513            }
04514        }
04515     /*************/
04516     /*   SHA     */
04517     /*************/
04518     } else if (strcmp(argv[1], "sha") == 0) {
04519         sha_test(argv[2]);
04520     /*************/
04521     /*   RSA     */
04522     /*************/
04523     } else if (strcmp(argv[1], "rsa") == 0) {
04524         /* argv[2]=siggen|sigver */
04525         /* argv[3]=<test name>.req */
04526         if (strcmp(argv[2], "siggen") == 0) {
04527             /* Signature Generation Test */
04528             rsa_siggen_test(argv[3]);
04529         } else if (strcmp(argv[2], "sigver") == 0) {
04530             /* Signature Verification Test */
04531             rsa_sigver_test(argv[3]);
04532         }
04533     /*************/
04534     /*   HMAC    */
04535     /*************/
04536     } else if (strcmp(argv[1], "hmac") == 0) {
04537         hmac_test(argv[2]);
04538     /*************/
04539     /*   DSA     */
04540     /*************/
04541     } else if (strcmp(argv[1], "dsa") == 0) {
04542         /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */
04543         /* argv[3]=<test name>.req */
04544         if (strcmp(argv[2], "keypair") == 0) {
04545             /* Key Pair Generation Test */
04546             dsa_keypair_test(argv[3]);
04547         } else if (strcmp(argv[2], "pqggen") == 0) {
04548         /* Domain Parameter Generation Test */
04549             dsa_pqggen_test(argv[3]);
04550         } else if (strcmp(argv[2], "pqgver") == 0) {
04551                 /* Domain Parameter Validation Test */
04552             dsa_pqgver_test(argv[3]);
04553         } else if (strcmp(argv[2], "siggen") == 0) {
04554             /* Signature Generation Test */
04555             dsa_siggen_test(argv[3]);
04556         } else if (strcmp(argv[2], "sigver") == 0) {
04557             /* Signature Verification Test */
04558             dsa_sigver_test(argv[3]);
04559         }
04560 #ifdef NSS_ENABLE_ECC
04561     /*************/
04562     /*   ECDSA   */
04563     /*************/
04564     } else if (strcmp(argv[1], "ecdsa") == 0) {
04565        /* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */
04566        if (       strcmp(argv[2], "keypair") == 0) {
04567            /* Key Pair Generation Test */
04568            ecdsa_keypair_test(argv[3]);
04569        } else if (strcmp(argv[2], "pkv") == 0) {
04570            /* Public Key Validation Test */
04571            ecdsa_pkv_test(argv[3]);
04572        } else if (strcmp(argv[2], "siggen") == 0) {
04573            /* Signature Generation Test */
04574            ecdsa_siggen_test(argv[3]);
04575        } else if (strcmp(argv[2], "sigver") == 0) {
04576            /* Signature Verification Test */
04577            ecdsa_sigver_test(argv[3]);
04578        }
04579 #endif /* NSS_ENABLE_ECC */
04580     /*************/
04581     /*   RNG     */
04582     /*************/
04583     } else if (strcmp(argv[1], "rng") == 0) {
04584        /* argv[2]=vst|mct argv[3]=<test name>.req */
04585        if (       strcmp(argv[2], "vst") == 0) {
04586            /* Variable Seed Test */
04587            rng_vst(argv[3]);
04588        } else if (strcmp(argv[2], "mct") == 0) {
04589            /* Monte Carlo Test */
04590            rng_mct(argv[3]);
04591        }
04592     }
04593     return 0;
04594 }