Back to index

lightning-sunbird  0.9+nobinonly
blapitest.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  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 
00041 #include "blapi.h"
00042 #include "secrng.h"
00043 #include "prmem.h"
00044 #include "prprf.h"
00045 #include "prtime.h"
00046 #include "prsystem.h"
00047 #include "plstr.h"
00048 #include "nssb64.h"
00049 #include "secutil.h"
00050 #include "plgetopt.h"
00051 #include "softoken.h"
00052 #include "nspr.h"
00053 #include "nss.h"
00054 
00055 #ifdef NSS_ENABLE_ECC
00056 #include "ecl-curve.h"
00057 SECStatus EC_DecodeParams(const SECItem *encodedParams, 
00058        ECParams **ecparams);
00059 SECStatus EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
00060              const ECParams *srcParams);
00061 SECStatus secoid_Init(void);
00062 #endif
00063 
00064 /* Temporary - add debugging ouput on windows for RSA to track QA failure */
00065 #ifdef _WIN32
00066 #define TRACK_BLTEST_BUG
00067     char __bltDBG[] = "BLTEST DEBUG";
00068 #endif
00069 
00070 char *progName;
00071 char *testdir = NULL;
00072 
00073 #define BLTEST_DEFAULT_CHUNKSIZE 4096
00074 
00075 #define WORDSIZE sizeof(unsigned long)
00076 
00077 #define CHECKERROR(rv, ln) \
00078     if (rv) { \
00079        PRErrorCode prerror = PR_GetError(); \
00080        PR_fprintf(PR_STDERR, "%s: ERR %d (%s) at line %d.\n", progName, \
00081                    prerror, SECU_Strerror(prerror), ln); \
00082        exit(-1); \
00083     }
00084 
00085 /* Macros for performance timing. */
00086 #define TIMESTART() \
00087     time1 = PR_IntervalNow();
00088 
00089 #define TIMEFINISH(time, reps) \
00090     time2 = (PRIntervalTime)(PR_IntervalNow() - time1); \
00091     time1 = PR_IntervalToMilliseconds(time2); \
00092     time = ((double)(time1))/reps;
00093 
00094 #define TIMEMARK(seconds) \
00095     time1 = PR_SecondsToInterval(seconds); \
00096     { \
00097         PRInt64 tmp, L100; \
00098         LL_I2L(L100, 100); \
00099         if (time2 == 0) { \
00100             time2 = 1; \
00101         } \
00102         LL_DIV(tmp, time1, time2); \
00103         if (tmp < 10) { \
00104             if (tmp == 0) { \
00105                 opsBetweenChecks = 1; \
00106             } else { \
00107                 LL_L2I(opsBetweenChecks, tmp); \
00108             } \
00109         } else { \
00110             opsBetweenChecks = 10; \
00111         } \
00112     } \
00113     time2 = time1; \
00114     time1 = PR_IntervalNow();
00115 
00116 #define TIMETOFINISH() \
00117     PR_IntervalNow() - time1 >= time2
00118 
00119 static void Usage()
00120 {
00121 #define PRINTUSAGE(subject, option, predicate) \
00122     fprintf(stderr, "%10s %s\t%s\n", subject, option, predicate);
00123     fprintf(stderr, "\n");
00124     PRINTUSAGE(progName, "[-DEHSV]", "List available cipher modes"); /* XXX */
00125     fprintf(stderr, "\n");
00126     PRINTUSAGE(progName, "-E -m mode ", "Encrypt a buffer");
00127     PRINTUSAGE("",   "", "[-i plaintext] [-o ciphertext] [-k key] [-v iv]");
00128     PRINTUSAGE("",   "", "[-b bufsize] [-g keysize] [-e exp] [-r rounds]");
00129     PRINTUSAGE("",   "", "[-w wordsize] [-p repetitions | -5 time_interval]");
00130     PRINTUSAGE("",   "", "[-4 th_num]");
00131     PRINTUSAGE("",   "-m", "cipher mode to use");
00132     PRINTUSAGE("",   "-i", "file which contains input buffer");
00133     PRINTUSAGE("",   "-o", "file for output buffer");
00134     PRINTUSAGE("",   "-k", "file which contains key");
00135     PRINTUSAGE("",   "-v", "file which contains initialization vector");
00136     PRINTUSAGE("",   "-b", "size of input buffer");
00137     PRINTUSAGE("",   "-g", "key size (in bytes)");
00138     PRINTUSAGE("",   "-p", "do performance test");
00139     PRINTUSAGE("",   "-4", "run test in multithread mode. th_num number of parallel threads");
00140     PRINTUSAGE("",   "-5", "run test for specified time interval(in seconds)");
00141     PRINTUSAGE("(rsa)", "-e", "rsa public exponent");
00142     PRINTUSAGE("(rc5)", "-r", "number of rounds");
00143     PRINTUSAGE("(rc5)", "-w", "wordsize (32 or 64)");
00144     fprintf(stderr, "\n");
00145     PRINTUSAGE(progName, "-D -m mode", "Decrypt a buffer");
00146     PRINTUSAGE("",   "", "[-i plaintext] [-o ciphertext] [-k key] [-v iv]");
00147     PRINTUSAGE("",   "", "[-p repetitions | -5 time_interval] [-4 th_num]");
00148     PRINTUSAGE("",   "-m", "cipher mode to use");
00149     PRINTUSAGE("",   "-i", "file which contains input buffer");
00150     PRINTUSAGE("",   "-o", "file for output buffer");
00151     PRINTUSAGE("",   "-k", "file which contains key");
00152     PRINTUSAGE("",   "-v", "file which contains initialization vector");
00153     PRINTUSAGE("",   "-p", "do performance test");
00154     PRINTUSAGE("",   "-4", "run test in multithread mode. th_num number of parallel threads");
00155     PRINTUSAGE("",   "-5", "run test for specified time interval(in seconds)");
00156     fprintf(stderr, "\n");
00157     PRINTUSAGE(progName, "-H -m mode", "Hash a buffer");
00158     PRINTUSAGE("",   "", "[-i plaintext] [-o hash]");
00159     PRINTUSAGE("",   "", "[-b bufsize]");
00160     PRINTUSAGE("",   "", "[-p repetitions | -5 time_interval] [-4 th_num]");
00161     PRINTUSAGE("",   "-m", "cipher mode to use");
00162     PRINTUSAGE("",   "-i", "file which contains input buffer");
00163     PRINTUSAGE("",   "-o", "file for hash");
00164     PRINTUSAGE("",   "-b", "size of input buffer");
00165     PRINTUSAGE("",   "-p", "do performance test");
00166     PRINTUSAGE("",   "-4", "run test in multithread mode. th_num number of parallel threads");
00167     PRINTUSAGE("",   "-5", "run test for specified time interval(in seconds)");
00168     fprintf(stderr, "\n");
00169     PRINTUSAGE(progName, "-S -m mode", "Sign a buffer");
00170     PRINTUSAGE("",   "", "[-i plaintext] [-o signature] [-k key]");
00171     PRINTUSAGE("",   "", "[-b bufsize]");
00172 #ifdef NSS_ENABLE_ECC
00173     PRINTUSAGE("",   "", "[-n curvename]");
00174 #endif
00175     PRINTUSAGE("",   "", "[-p repetitions | -5 time_interval] [-4 th_num]");
00176     PRINTUSAGE("",   "-m", "cipher mode to use");
00177     PRINTUSAGE("",   "-i", "file which contains input buffer");
00178     PRINTUSAGE("",   "-o", "file for signature");
00179     PRINTUSAGE("",   "-k", "file which contains key");
00180 #ifdef NSS_ENABLE_ECC
00181     PRINTUSAGE("",   "-n", "name of curve for EC key generation; one of:");
00182     PRINTUSAGE("",  "",   "  sect163k1, nistk163, sect163r1, sect163r2,");
00183     PRINTUSAGE("",  "",   "  nistb163, sect193r1, sect193r2, sect233k1, nistk233,");
00184     PRINTUSAGE("",  "",   "  sect233r1, nistb233, sect239k1, sect283k1, nistk283,");
00185     PRINTUSAGE("",  "",   "  sect283r1, nistb283, sect409k1, nistk409, sect409r1,");
00186     PRINTUSAGE("",  "",   "  nistb409, sect571k1, nistk571, sect571r1, nistb571,");
00187     PRINTUSAGE("",  "",   "  secp160k1, secp160r1, secp160r2, secp192k1, secp192r1,");
00188     PRINTUSAGE("",  "",   "  nistp192, secp224k1, secp224r1, nistp224, secp256k1,");
00189     PRINTUSAGE("",  "",   "  secp256r1, nistp256, secp384r1, nistp384, secp521r1,");
00190     PRINTUSAGE("",  "",   "  nistp521, prime192v1, prime192v2, prime192v3,");
00191     PRINTUSAGE("",  "",   "  prime239v1, prime239v2, prime239v3, c2pnb163v1,");
00192     PRINTUSAGE("",  "",   "  c2pnb163v2, c2pnb163v3, c2pnb176v1, c2tnb191v1,");
00193     PRINTUSAGE("",  "",   "  c2tnb191v2, c2tnb191v3, c2onb191v4, c2onb191v5,");
00194     PRINTUSAGE("",  "",   "  c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3,");
00195     PRINTUSAGE("",  "",   "  c2onb239v4, c2onb239v5, c2pnb272w1, c2pnb304w1,");
00196     PRINTUSAGE("",  "",   "  c2tnb359w1, c2pnb368w1, c2tnb431r1, secp112r1,");
00197     PRINTUSAGE("",  "",   "  secp112r2, secp128r1, secp128r2, sect113r1, sect113r2,");
00198     PRINTUSAGE("",  "",   "  sect131r1, sect131r2");
00199 #endif
00200     PRINTUSAGE("",   "-p", "do performance test");
00201     PRINTUSAGE("",   "-4", "run test in multithread mode. th_num number of parallel threads");
00202     PRINTUSAGE("",   "-5", "run test for specified time interval(in seconds)");
00203     fprintf(stderr, "\n");
00204     PRINTUSAGE(progName, "-V -m mode", "Verify a signed buffer");
00205     PRINTUSAGE("",   "", "[-i plaintext] [-s signature] [-k key]");
00206     PRINTUSAGE("",   "", "[-p repetitions | -5 time_interval] [-4 th_num]");
00207     PRINTUSAGE("",   "-m", "cipher mode to use");
00208     PRINTUSAGE("",   "-i", "file which contains input buffer");
00209     PRINTUSAGE("",   "-s", "file which contains signature of input buffer");
00210     PRINTUSAGE("",   "-k", "file which contains key");
00211     PRINTUSAGE("",   "-p", "do performance test");
00212     PRINTUSAGE("",   "-4", "run test in multithread mode. th_num number of parallel threads");
00213     PRINTUSAGE("",   "-5", "run test for specified time interval(in seconds)");
00214     fprintf(stderr, "\n");
00215     PRINTUSAGE(progName, "-N -m mode -b bufsize", 
00216                                             "Create a nonce plaintext and key");
00217     PRINTUSAGE("",      "", "[-g keysize] [-u cxreps]");
00218     PRINTUSAGE("",   "-g", "key size (in bytes)");
00219     PRINTUSAGE("",      "-u", "number of repetitions of context creation");
00220     fprintf(stderr, "\n");
00221     PRINTUSAGE(progName, "-F", "Run the FIPS self-test");
00222     fprintf(stderr, "\n");
00223     PRINTUSAGE(progName, "-T [-m mode1,mode2...]", "Run the BLAPI self-test");
00224     fprintf(stderr, "\n");
00225     exit(1);
00226 }
00227 
00228 /*  Helper functions for ascii<-->binary conversion/reading/writing */
00229 
00230 /* XXX argh */
00231 struct item_with_arena {
00232     SECItem   *item;
00233     PRArenaPool *arena;
00234 };
00235 
00236 static PRInt32
00237 get_binary(void *arg, const unsigned char *ibuf, PRInt32 size)
00238 {
00239     struct item_with_arena *it = arg;
00240     SECItem *binary = it->item;
00241     SECItem *tmp;
00242     int index;
00243     if (binary->data == NULL) {
00244        tmp = SECITEM_AllocItem(it->arena, NULL, size);
00245        binary->data = tmp->data;
00246        binary->len = tmp->len;
00247        index = 0;
00248     } else {
00249        SECITEM_ReallocItem(NULL, binary, binary->len, binary->len + size);
00250        index = binary->len;
00251     }
00252     PORT_Memcpy(&binary->data[index], ibuf, size);
00253     return binary->len;
00254 }
00255 
00256 static SECStatus
00257 atob(SECItem *ascii, SECItem *binary, PRArenaPool *arena)
00258 {
00259     SECStatus status;
00260     NSSBase64Decoder *cx;
00261     struct item_with_arena it;
00262     int len;
00263     binary->data = NULL;
00264     binary->len = 0;
00265     it.item = binary;
00266     it.arena = arena;
00267     len = (strcmp(&ascii->data[ascii->len-2],"\r\n")) ? 
00268            ascii->len : ascii->len-2;
00269     cx = NSSBase64Decoder_Create(get_binary, &it);
00270     status = NSSBase64Decoder_Update(cx, (const char *)ascii->data, len);
00271     status = NSSBase64Decoder_Destroy(cx, PR_FALSE);
00272     return status;
00273 }
00274 
00275 static PRInt32
00276 output_ascii(void *arg, const char *obuf, PRInt32 size)
00277 {
00278     PRFileDesc *outfile = arg;
00279     PRInt32 nb = PR_Write(outfile, obuf, size);
00280     if (nb != size) {
00281        PORT_SetError(SEC_ERROR_IO);
00282        return -1;
00283     }
00284     return nb;
00285 }
00286 
00287 static SECStatus
00288 btoa_file(SECItem *binary, PRFileDesc *outfile)
00289 {
00290     SECStatus status;
00291     NSSBase64Encoder *cx;
00292     SECItem ascii;
00293     ascii.data = NULL;
00294     ascii.len = 0;
00295     if (binary->len == 0)
00296        return SECSuccess;
00297     cx = NSSBase64Encoder_Create(output_ascii, outfile);
00298     status = NSSBase64Encoder_Update(cx, binary->data, binary->len);
00299     status = NSSBase64Encoder_Destroy(cx, PR_FALSE);
00300     status = PR_Write(outfile, "\r\n", 2);
00301     return status;
00302 }
00303 
00304 SECStatus
00305 hex_from_2char(unsigned char *c2, unsigned char *byteval)
00306 {
00307     int i;
00308     unsigned char offset;
00309     *byteval = 0;
00310     for (i=0; i<2; i++) {
00311        if (c2[i] >= '0' && c2[i] <= '9') {
00312            offset = c2[i] - '0';
00313            *byteval |= offset << 4*(1-i);
00314        } else if (c2[i] >= 'a' && c2[i] <= 'f') {
00315            offset = c2[i] - 'a';
00316            *byteval |= (offset + 10) << 4*(1-i);
00317        } else if (c2[i] >= 'A' && c2[i] <= 'F') {
00318            offset = c2[i] - 'A';
00319            *byteval |= (offset + 10) << 4*(1-i);
00320        } else {
00321            return SECFailure;
00322        }
00323     }
00324     return SECSuccess;
00325 }
00326 
00327 SECStatus
00328 char2_from_hex(unsigned char byteval, unsigned char *c2)
00329 {
00330     int i;
00331     unsigned char offset;
00332     for (i=0; i<2; i++) {
00333        offset = (byteval >> 4*(1-i)) & 0x0f;
00334        if (offset < 10) {
00335            c2[i] = '0' + offset;
00336        } else {
00337            c2[i] = 'A' + offset - 10;
00338        }
00339     }
00340     return SECSuccess;
00341 }
00342 
00343 void
00344 serialize_key(SECItem *it, int ni, PRFileDesc *file)
00345 {
00346     unsigned char len[4];
00347     int i;
00348     SECStatus status;
00349     NSSBase64Encoder *cx;
00350     SECItem ascii;
00351     ascii.data = NULL;
00352     ascii.len = 0;
00353     cx = NSSBase64Encoder_Create(output_ascii, file);
00354     for (i=0; i<ni; i++, it++) {
00355        len[0] = (it->len >> 24) & 0xff;
00356        len[1] = (it->len >> 16) & 0xff;
00357        len[2] = (it->len >>  8) & 0xff;
00358        len[3] = (it->len     & 0xff);
00359        status = NSSBase64Encoder_Update(cx, len, 4);
00360        status = NSSBase64Encoder_Update(cx, it->data, it->len);
00361     }
00362     status = NSSBase64Encoder_Destroy(cx, PR_FALSE);
00363     status = PR_Write(file, "\r\n", 2);
00364 }
00365 
00366 void
00367 key_from_filedata(PRArenaPool *arena, SECItem *it, int ns, int ni, SECItem *filedata)
00368 {
00369     int fpos = 0;
00370     int i, len;
00371     unsigned char *buf = filedata->data;
00372     for (i=0; i<ni; i++) {
00373        len  = (buf[fpos++] & 0xff) << 24;
00374        len |= (buf[fpos++] & 0xff) << 16;
00375        len |= (buf[fpos++] & 0xff) <<  8;
00376        len |= (buf[fpos++] & 0xff);
00377        if (ns <= i) {
00378            if (len > 0) {
00379               it->len = len;
00380               it->data = PORT_ArenaAlloc(arena, it->len);
00381               PORT_Memcpy(it->data, &buf[fpos], it->len);
00382            } else {
00383               it->len = 0;
00384               it->data = NULL;
00385            }
00386            it++;
00387        }
00388        fpos += len;
00389     }
00390 }
00391 
00392 static RSAPrivateKey *
00393 rsakey_from_filedata(SECItem *filedata)
00394 {
00395     RSAPrivateKey *key;
00396     PRArenaPool *arena;
00397     arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
00398     key = (RSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(RSAPrivateKey));
00399     key->arena = arena;
00400     key_from_filedata(arena, &key->version, 0, 9, filedata);
00401     return key;
00402 }
00403 
00404 static PQGParams *
00405 pqg_from_filedata(SECItem *filedata)
00406 {
00407     PQGParams *pqg;
00408     PRArenaPool *arena;
00409     arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
00410     pqg = (PQGParams *)PORT_ArenaZAlloc(arena, sizeof(PQGParams));
00411     pqg->arena = arena;
00412     key_from_filedata(arena, &pqg->prime, 0, 3, filedata);
00413     return pqg;
00414 }
00415 
00416 static DSAPrivateKey *
00417 dsakey_from_filedata(SECItem *filedata)
00418 {
00419     DSAPrivateKey *key;
00420     PRArenaPool *arena;
00421     arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
00422     key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey));
00423     key->params.arena = arena;
00424     key_from_filedata(arena, &key->params.prime, 0, 5, filedata);
00425     return key;
00426 }
00427 
00428 #ifdef NSS_ENABLE_ECC
00429 static ECPrivateKey *
00430 eckey_from_filedata(SECItem *filedata)
00431 {
00432     ECPrivateKey *key;
00433     PRArenaPool *arena;
00434     SECStatus rv;
00435     ECParams *tmpECParams = NULL;
00436     arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
00437     key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey));
00438     /* read and convert params */
00439     key->ecParams.arena = arena;
00440     key_from_filedata(arena, &key->ecParams.DEREncoding, 0, 1, filedata);
00441     rv = secoid_Init();
00442     CHECKERROR(rv, __LINE__);
00443     rv = EC_DecodeParams(&key->ecParams.DEREncoding, &tmpECParams);
00444     CHECKERROR(rv, __LINE__);
00445     rv = EC_CopyParams(key->ecParams.arena, &key->ecParams, tmpECParams);
00446     CHECKERROR(rv, __LINE__);
00447     rv = SECOID_Shutdown();
00448     CHECKERROR(rv, __LINE__);
00449     PORT_FreeArena(tmpECParams->arena, PR_TRUE);
00450     /* read key */
00451     key_from_filedata(arena, &key->publicValue, 1, 3, filedata);
00452     return key;
00453 }
00454 
00455 typedef struct curveNameTagPairStr {
00456     char *curveName;
00457     SECOidTag curveOidTag;
00458 } CurveNameTagPair;
00459 
00460 #define DEFAULT_CURVE_OID_TAG  SEC_OID_SECG_EC_SECP192R1
00461 /* #define DEFAULT_CURVE_OID_TAG  SEC_OID_SECG_EC_SECP160R1 */
00462 
00463 static CurveNameTagPair nameTagPair[] =
00464 { 
00465   { "sect163k1", SEC_OID_SECG_EC_SECT163K1},
00466   { "nistk163", SEC_OID_SECG_EC_SECT163K1},
00467   { "sect163r1", SEC_OID_SECG_EC_SECT163R1},
00468   { "sect163r2", SEC_OID_SECG_EC_SECT163R2},
00469   { "nistb163", SEC_OID_SECG_EC_SECT163R2},
00470   { "sect193r1", SEC_OID_SECG_EC_SECT193R1},
00471   { "sect193r2", SEC_OID_SECG_EC_SECT193R2},
00472   { "sect233k1", SEC_OID_SECG_EC_SECT233K1},
00473   { "nistk233", SEC_OID_SECG_EC_SECT233K1},
00474   { "sect233r1", SEC_OID_SECG_EC_SECT233R1},
00475   { "nistb233", SEC_OID_SECG_EC_SECT233R1},
00476   { "sect239k1", SEC_OID_SECG_EC_SECT239K1},
00477   { "sect283k1", SEC_OID_SECG_EC_SECT283K1},
00478   { "nistk283", SEC_OID_SECG_EC_SECT283K1},
00479   { "sect283r1", SEC_OID_SECG_EC_SECT283R1},
00480   { "nistb283", SEC_OID_SECG_EC_SECT283R1},
00481   { "sect409k1", SEC_OID_SECG_EC_SECT409K1},
00482   { "nistk409", SEC_OID_SECG_EC_SECT409K1},
00483   { "sect409r1", SEC_OID_SECG_EC_SECT409R1},
00484   { "nistb409", SEC_OID_SECG_EC_SECT409R1},
00485   { "sect571k1", SEC_OID_SECG_EC_SECT571K1},
00486   { "nistk571", SEC_OID_SECG_EC_SECT571K1},
00487   { "sect571r1", SEC_OID_SECG_EC_SECT571R1},
00488   { "nistb571", SEC_OID_SECG_EC_SECT571R1},
00489   { "secp160k1", SEC_OID_SECG_EC_SECP160K1},
00490   { "secp160r1", SEC_OID_SECG_EC_SECP160R1},
00491   { "secp160r2", SEC_OID_SECG_EC_SECP160R2},
00492   { "secp192k1", SEC_OID_SECG_EC_SECP192K1},
00493   { "secp192r1", SEC_OID_SECG_EC_SECP192R1},
00494   { "nistp192", SEC_OID_SECG_EC_SECP192R1},
00495   { "secp224k1", SEC_OID_SECG_EC_SECP224K1},
00496   { "secp224r1", SEC_OID_SECG_EC_SECP224R1},
00497   { "nistp224", SEC_OID_SECG_EC_SECP224R1},
00498   { "secp256k1", SEC_OID_SECG_EC_SECP256K1},
00499   { "secp256r1", SEC_OID_SECG_EC_SECP256R1},
00500   { "nistp256", SEC_OID_SECG_EC_SECP256R1},
00501   { "secp384r1", SEC_OID_SECG_EC_SECP384R1},
00502   { "nistp384", SEC_OID_SECG_EC_SECP384R1},
00503   { "secp521r1", SEC_OID_SECG_EC_SECP521R1},
00504   { "nistp521", SEC_OID_SECG_EC_SECP521R1},
00505 
00506   { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
00507   { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
00508   { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
00509   { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
00510   { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
00511   { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
00512 
00513   { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
00514   { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
00515   { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
00516   { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
00517   { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
00518   { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
00519   { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
00520   { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
00521   { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
00522   { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
00523   { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
00524   { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
00525   { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
00526   { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
00527   { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
00528   { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
00529   { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
00530   { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
00531   { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
00532   { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
00533 
00534   { "secp112r1", SEC_OID_SECG_EC_SECP112R1},
00535   { "secp112r2", SEC_OID_SECG_EC_SECP112R2},
00536   { "secp128r1", SEC_OID_SECG_EC_SECP128R1},
00537   { "secp128r2", SEC_OID_SECG_EC_SECP128R2},
00538 
00539   { "sect113r1", SEC_OID_SECG_EC_SECT113R1},
00540   { "sect113r2", SEC_OID_SECG_EC_SECT113R2},
00541   { "sect131r1", SEC_OID_SECG_EC_SECT131R1},
00542   { "sect131r2", SEC_OID_SECG_EC_SECT131R2},
00543 };
00544 
00545 static SECKEYECParams * 
00546 getECParams(char *curve)
00547 {
00548     SECKEYECParams *ecparams;
00549     SECOidData *oidData = NULL;
00550     SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
00551     int i, numCurves;
00552 
00553     if (curve != NULL) {
00554         numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair);
00555        for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); 
00556             i++) {
00557            if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
00558                curveOidTag = nameTagPair[i].curveOidTag;
00559        }
00560     }
00561 
00562     /* Return NULL if curve name is not recognized */
00563     if ((curveOidTag == SEC_OID_UNKNOWN) || 
00564        (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
00565         fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
00566        return NULL;
00567     }
00568 
00569     ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
00570 
00571     /* 
00572      * ecparams->data needs to contain the ASN encoding of an object ID (OID)
00573      * representing the named curve. The actual OID is in 
00574      * oidData->oid.data so we simply prepend 0x06 and OID length
00575      */
00576     ecparams->data[0] = SEC_ASN1_OBJECT_ID;
00577     ecparams->data[1] = oidData->oid.len;
00578     memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
00579 
00580     return ecparams;
00581 }
00582 #endif /* NSS_ENABLE_ECC */
00583 
00584 static void
00585 dump_pqg(PQGParams *pqg)
00586 {
00587     SECU_PrintInteger(stdout, &pqg->prime, "PRIME:", 0);
00588     SECU_PrintInteger(stdout, &pqg->subPrime, "SUBPRIME:", 0);
00589     SECU_PrintInteger(stdout, &pqg->base, "BASE:", 0);
00590 }
00591 
00592 static void
00593 dump_dsakey(DSAPrivateKey *key)
00594 {
00595     dump_pqg(&key->params);
00596     SECU_PrintInteger(stdout, &key->publicValue, "PUBLIC VALUE:", 0);
00597     SECU_PrintInteger(stdout, &key->privateValue, "PRIVATE VALUE:", 0);
00598 }
00599 
00600 #ifdef NSS_ENABLE_ECC
00601 static void
00602 dump_ecp(ECParams *ecp)
00603 {
00604     /* TODO other fields */
00605     SECU_PrintInteger(stdout, &ecp->base, "BASE POINT:", 0);
00606 }
00607 
00608 static void
00609 dump_eckey(ECPrivateKey *key)
00610 {
00611     dump_ecp(&key->ecParams);
00612     SECU_PrintInteger(stdout, &key->publicValue, "PUBLIC VALUE:", 0);
00613     SECU_PrintInteger(stdout, &key->privateValue, "PRIVATE VALUE:", 0);
00614 }
00615 #endif
00616 
00617 static void
00618 dump_rsakey(RSAPrivateKey *key)
00619 {
00620     SECU_PrintInteger(stdout, &key->version, "VERSION:", 0);
00621     SECU_PrintInteger(stdout, &key->modulus, "MODULUS:", 0);
00622     SECU_PrintInteger(stdout, &key->publicExponent, "PUBLIC EXP:", 0);
00623     SECU_PrintInteger(stdout, &key->privateExponent, "PRIVATE EXP:", 0);
00624     SECU_PrintInteger(stdout, &key->prime1, "CRT PRIME 1:", 0);
00625     SECU_PrintInteger(stdout, &key->prime2, "CRT PRIME 2:", 0);
00626     SECU_PrintInteger(stdout, &key->exponent1, "CRT EXP 1:", 0);
00627     SECU_PrintInteger(stdout, &key->exponent2, "CRT EXP 2:", 0);
00628     SECU_PrintInteger(stdout, &key->coefficient, "CRT COEFFICIENT:", 0);
00629 }
00630 
00631 typedef enum {
00632     bltestBase64Encoded,       /* Base64 encoded ASCII */
00633     bltestBinary,           /* straight binary */
00634     bltestHexSpaceDelim,       /* 0x12 0x34 0xab 0xCD ... */
00635     bltestHexStream         /* 1234abCD ... */
00636 } bltestIOMode;
00637 
00638 typedef struct
00639 {
00640     SECItem      buf;
00641     SECItem      pBuf;
00642     bltestIOMode   mode;
00643     PRFileDesc*         file;
00644 } bltestIO;
00645 
00646 typedef SECStatus (* bltestSymmCipherFn)(void *cx,
00647                                     unsigned char *output,
00648                                     unsigned int *outputLen,
00649                                     unsigned int maxOutputLen,
00650                                     const unsigned char *input,
00651                                     unsigned int inputLen);
00652 
00653 typedef SECStatus (* bltestPubKeyCipherFn)(void *key,
00654                                       SECItem *output,
00655                                       const SECItem *input);
00656 
00657 typedef SECStatus (* bltestHashCipherFn)(unsigned char *dest,
00658                                     const unsigned char *src,
00659                                     uint32 src_length);
00660 
00661 typedef enum {
00662     bltestINVALID = -1,
00663     bltestDES_ECB,     /* Symmetric Key Ciphers */
00664     bltestDES_CBC,     /* .                  */
00665     bltestDES_EDE_ECB,        /* .                  */
00666     bltestDES_EDE_CBC,        /* .                  */
00667     bltestRC2_ECB,     /* .                  */
00668     bltestRC2_CBC,     /* .                  */
00669     bltestRC4,                /* .                  */
00670     bltestRC5_ECB,     /* .                  */
00671     bltestRC5_CBC,     /* .                  */
00672     bltestAES_ECB,        /* .                     */
00673     bltestAES_CBC,        /* .                     */
00674     bltestRSA,                /* Public Key Ciphers        */
00675 #ifdef NSS_ENABLE_ECC
00676     bltestECDSA,       /* . (Public Key Sig.)   */
00677 #endif
00678     bltestDSA,                /* .                     */
00679     bltestMD2,                /* Hash algorithms    */
00680     bltestMD5,                /* .                  */
00681     bltestSHA1,           /* .                      */
00682     bltestSHA256,         /* .                      */
00683     bltestSHA384,         /* .                      */
00684     bltestSHA512,         /* .                      */
00685     NUMMODES
00686 } bltestCipherMode;
00687 
00688 static char *mode_strings[] =
00689 {
00690     "des_ecb",
00691     "des_cbc",
00692     "des3_ecb",
00693     "des3_cbc",
00694     "rc2_ecb",
00695     "rc2_cbc",
00696     "rc4",
00697     "rc5_ecb",
00698     "rc5_cbc",
00699     "aes_ecb",
00700     "aes_cbc",
00701     "rsa",
00702 #ifdef NSS_ENABLE_ECC
00703     "ecdsa",
00704 #endif
00705     /*"pqg",*/
00706     "dsa",
00707     "md2",
00708     "md5",
00709     "sha1",
00710     "sha256",
00711     "sha384",
00712     "sha512",
00713 };
00714 
00715 typedef struct
00716 {
00717     bltestIO key;
00718     bltestIO iv;
00719 } bltestSymmKeyParams;
00720 
00721 typedef struct
00722 {
00723     bltestIO key;
00724     bltestIO iv;
00725     int            rounds;
00726     int            wordsize;
00727 } bltestRC5Params;
00728 
00729 typedef struct
00730 {
00731     bltestIO key;
00732     int            keysizeInBits;
00733     RSAPrivateKey *rsakey;
00734 } bltestRSAParams;
00735 
00736 typedef struct
00737 {
00738     bltestIO   key;
00739     bltestIO   pqgdata;
00740     unsigned int j;
00741     bltestIO   keyseed;
00742     bltestIO   sigseed;
00743     bltestIO   sig; /* if doing verify, have additional input */
00744     PQGParams *pqg;
00745     DSAPrivateKey *dsakey;
00746 } bltestDSAParams;
00747 
00748 #ifdef NSS_ENABLE_ECC
00749 typedef struct
00750 {
00751     bltestIO   key;
00752     char      *curveName;
00753     bltestIO   sigseed;
00754     bltestIO   sig; /* if doing verify, have additional input */
00755     ECPrivateKey *eckey;
00756 } bltestECDSAParams;
00757 #endif
00758 
00759 typedef struct
00760 {
00761     bltestIO   key; /* unused */
00762     PRBool     restart;
00763 } bltestHashParams;
00764 
00765 typedef union
00766 {
00767     bltestIO         key;
00768     bltestSymmKeyParams sk;
00769     bltestRC5Params  rc5;
00770     bltestRSAParams  rsa;
00771     bltestDSAParams  dsa;
00772 #ifdef NSS_ENABLE_ECC
00773     bltestECDSAParams       ecdsa;
00774 #endif
00775     bltestHashParams hash;
00776 } bltestParams;
00777 
00778 typedef struct bltestCipherInfoStr bltestCipherInfo;
00779 
00780 struct  bltestCipherInfoStr {
00781     PRArenaPool *arena;
00782     /* link to next in multithreaded test */
00783     bltestCipherInfo *next;
00784     PRThread         *cipherThread;
00785 
00786     /* MonteCarlo test flag*/
00787     PRBool mCarlo;
00788     /* cipher context */
00789     void *cx;
00790     /* I/O streams */
00791     bltestIO input;
00792     bltestIO output;
00793     /* Cipher-specific parameters */
00794     bltestParams params;
00795     /* Cipher mode */
00796     bltestCipherMode  mode;
00797     /* Cipher function (encrypt/decrypt/sign/verify/hash) */
00798     union {
00799        bltestSymmCipherFn   symmkeyCipher;
00800        bltestPubKeyCipherFn pubkeyCipher;
00801        bltestHashCipherFn   hashCipher;
00802     } cipher;
00803     /* performance testing */
00804     int   repetitionsToPerfom;
00805     int   seconds;
00806     int         repetitions;
00807     int   cxreps;
00808     double cxtime;
00809     double optime;
00810 };
00811 
00812 PRBool
00813 is_symmkeyCipher(bltestCipherMode mode)
00814 {
00815     /* change as needed! */
00816     if (mode >= bltestDES_ECB && mode <= bltestAES_CBC)
00817        return PR_TRUE;
00818     return PR_FALSE;
00819 }
00820 
00821 PRBool
00822 is_pubkeyCipher(bltestCipherMode mode)
00823 {
00824     /* change as needed! */
00825     if (mode >= bltestRSA && mode <= bltestDSA)
00826        return PR_TRUE;
00827     return PR_FALSE;
00828 }
00829 
00830 PRBool
00831 is_hashCipher(bltestCipherMode mode)
00832 {
00833     /* change as needed! */
00834     if (mode >= bltestMD2 && mode <= bltestSHA512)
00835        return PR_TRUE;
00836     return PR_FALSE;
00837 }
00838 
00839 PRBool
00840 is_sigCipher(bltestCipherMode mode)
00841 {
00842     /* change as needed! */
00843 #ifdef NSS_ENABLE_ECC
00844     if (mode >= bltestECDSA && mode <= bltestDSA)
00845 #else
00846     if (mode >= bltestDSA && mode <= bltestDSA)
00847 #endif
00848        return PR_TRUE;
00849     return PR_FALSE;
00850 }
00851 
00852 PRBool
00853 cipher_requires_IV(bltestCipherMode mode)
00854 {
00855     /* change as needed! */
00856     if (mode == bltestDES_CBC || mode == bltestDES_EDE_CBC ||
00857        mode == bltestRC2_CBC || mode == bltestRC5_CBC     ||
00858         mode == bltestAES_CBC)
00859        return PR_TRUE;
00860     return PR_FALSE;
00861 }
00862 
00863 SECStatus finishIO(bltestIO *output, PRFileDesc *file);
00864 
00865 SECStatus
00866 setupIO(PRArenaPool *arena, bltestIO *input, PRFileDesc *file,
00867        char *str, int numBytes)
00868 {
00869     SECStatus rv = SECSuccess;
00870     SECItem fileData;
00871     SECItem *in;
00872     unsigned char *tok;
00873     unsigned int i, j;
00874 
00875     if (file && (numBytes == 0 || file == PR_STDIN)) {
00876        /* grabbing data from a file */
00877        rv = SECU_FileToItem(&fileData, file);
00878        if (rv != SECSuccess) {
00879            PR_Close(file);
00880            return SECFailure;
00881        }
00882        in = &fileData;
00883     } else if (str) {
00884        /* grabbing data from command line */
00885        fileData.data = str;
00886        fileData.len = PL_strlen(str);
00887        in = &fileData;
00888     } else if (file) {
00889        /* create nonce */
00890        SECITEM_AllocItem(arena, &input->buf, numBytes);
00891        RNG_GenerateGlobalRandomBytes(input->buf.data, numBytes);
00892        return finishIO(input, file);
00893     } else {
00894        return SECFailure;
00895     }
00896 
00897     switch (input->mode) {
00898     case bltestBase64Encoded:
00899        rv = atob(in, &input->buf, arena);
00900        break;
00901     case bltestBinary:
00902        if (in->data[in->len-1] == '\n') --in->len;
00903        if (in->data[in->len-1] == '\r') --in->len;
00904        SECITEM_CopyItem(arena, &input->buf, in);
00905        break;
00906     case bltestHexSpaceDelim:
00907        SECITEM_AllocItem(arena, &input->buf, in->len/5);
00908        for (i=0, j=0; i<in->len; i+=5, j++) {
00909            tok = &in->data[i];
00910            if (tok[0] != '0' || tok[1] != 'x' || tok[4] != ' ')
00911               /* bad hex token */
00912               break;
00913 
00914            rv = hex_from_2char(&tok[2], input->buf.data + j);
00915            if (rv)
00916               break;
00917        }
00918        break;
00919     case bltestHexStream:
00920        SECITEM_AllocItem(arena, &input->buf, in->len/2);
00921        for (i=0, j=0; i<in->len; i+=2, j++) {
00922            tok = &in->data[i];
00923            rv = hex_from_2char(tok, input->buf.data + j);
00924            if (rv)
00925               break;
00926        }
00927        break;
00928     }
00929 
00930     if (file)
00931        SECITEM_FreeItem(&fileData, PR_FALSE);
00932     return rv;
00933 }
00934 
00935 SECStatus
00936 finishIO(bltestIO *output, PRFileDesc *file)
00937 {
00938     SECStatus rv = SECSuccess;
00939     PRInt32 nb;
00940     unsigned char byteval;
00941     SECItem *it;
00942     char hexstr[5];
00943     unsigned int i;
00944     if (output->pBuf.len > 0) {
00945        it = &output->pBuf;
00946     } else {
00947        it = &output->buf;
00948     }
00949     switch (output->mode) {
00950     case bltestBase64Encoded:
00951        rv = btoa_file(it, file);
00952        break;
00953     case bltestBinary:
00954        nb = PR_Write(file, it->data, it->len);
00955        rv = (nb == (PRInt32)it->len) ? SECSuccess : SECFailure;
00956        break;
00957     case bltestHexSpaceDelim:
00958        hexstr[0] = '0';
00959        hexstr[1] = 'x';
00960        hexstr[4] = ' ';
00961        for (i=0; i<it->len; i++) {
00962            byteval = it->data[i];
00963            rv = char2_from_hex(byteval, hexstr + 2);
00964            nb = PR_Write(file, hexstr, 5);
00965            if (rv)
00966               break;
00967        }
00968        PR_Write(file, "\n", 1);
00969        break;
00970     case bltestHexStream:
00971        for (i=0; i<it->len; i++) {
00972            byteval = it->data[i];
00973            rv = char2_from_hex(byteval, hexstr);
00974            if (rv)
00975               break;
00976            nb = PR_Write(file, hexstr, 2);
00977        }
00978        PR_Write(file, "\n", 1);
00979        break;
00980     }
00981     return rv;
00982 }
00983 
00984 void
00985 bltestCopyIO(PRArenaPool *arena, bltestIO *dest, bltestIO *src)
00986 {
00987     SECITEM_CopyItem(arena, &dest->buf, &src->buf);
00988     if (src->pBuf.len > 0) {
00989        dest->pBuf.len = src->pBuf.len;
00990        dest->pBuf.data = dest->buf.data + (src->pBuf.data - src->buf.data);
00991     }
00992     dest->mode = src->mode;
00993     dest->file = src->file;
00994 }
00995 
00996 void
00997 misalignBuffer(PRArenaPool *arena, bltestIO *io, int off)
00998 {
00999     ptrdiff_t offset = (ptrdiff_t)io->buf.data % WORDSIZE;
01000     int length = io->buf.len;
01001     if (offset != off) {
01002        SECITEM_ReallocItem(arena, &io->buf, length, length + 2*WORDSIZE);
01003        io->buf.len = length + 2*WORDSIZE; /* why doesn't realloc do this? */
01004        /* offset may have changed? */
01005        offset = (ptrdiff_t)io->buf.data % WORDSIZE;
01006        if (offset != off) {
01007            memmove(io->buf.data + off, io->buf.data, length);
01008            io->pBuf.data = io->buf.data + off;
01009            io->pBuf.len = length;
01010        } else {
01011            io->pBuf.data = io->buf.data;
01012            io->pBuf.len = length;
01013        }
01014     } else {
01015        io->pBuf.data = io->buf.data;
01016        io->pBuf.len = length;
01017     }
01018 }
01019 
01020 SECStatus
01021 des_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
01022             unsigned int maxOutputLen, const unsigned char *input,
01023             unsigned int inputLen)
01024 {
01025     return DES_Encrypt((DESContext *)cx, output, outputLen, maxOutputLen,
01026                        input, inputLen);
01027 }
01028 
01029 SECStatus
01030 des_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
01031             unsigned int maxOutputLen, const unsigned char *input,
01032             unsigned int inputLen)
01033 {
01034     return DES_Decrypt((DESContext *)cx, output, outputLen, maxOutputLen,
01035                        input, inputLen);
01036 }
01037 
01038 SECStatus
01039 rc2_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
01040             unsigned int maxOutputLen, const unsigned char *input,
01041             unsigned int inputLen)
01042 {
01043     return RC2_Encrypt((RC2Context *)cx, output, outputLen, maxOutputLen,
01044                        input, inputLen);
01045 }
01046 
01047 SECStatus
01048 rc2_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
01049             unsigned int maxOutputLen, const unsigned char *input,
01050             unsigned int inputLen)
01051 {
01052     return RC2_Decrypt((RC2Context *)cx, output, outputLen, maxOutputLen,
01053                        input, inputLen);
01054 }
01055 
01056 SECStatus
01057 rc4_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
01058             unsigned int maxOutputLen, const unsigned char *input,
01059             unsigned int inputLen)
01060 {
01061     return RC4_Encrypt((RC4Context *)cx, output, outputLen, maxOutputLen,
01062                        input, inputLen);
01063 }
01064 
01065 SECStatus
01066 rc4_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
01067             unsigned int maxOutputLen, const unsigned char *input,
01068             unsigned int inputLen)
01069 {
01070     return RC4_Decrypt((RC4Context *)cx, output, outputLen, maxOutputLen,
01071                        input, inputLen);
01072 }
01073 
01074 SECStatus
01075 aes_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
01076             unsigned int maxOutputLen, const unsigned char *input,
01077             unsigned int inputLen)
01078 {
01079     return AES_Encrypt((AESContext *)cx, output, outputLen, maxOutputLen,
01080                        input, inputLen);
01081 }
01082 
01083 SECStatus
01084 aes_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
01085             unsigned int maxOutputLen, const unsigned char *input,
01086             unsigned int inputLen)
01087 {
01088     return AES_Decrypt((AESContext *)cx, output, outputLen, maxOutputLen,
01089                        input, inputLen);
01090 }
01091 
01092 SECStatus
01093 rsa_PublicKeyOp(void *key, SECItem *output, const SECItem *input)
01094 {
01095     return RSA_PublicKeyOp((RSAPublicKey *)key, output->data, input->data);
01096 }
01097 
01098 SECStatus
01099 rsa_PrivateKeyOp(void *key, SECItem *output, const SECItem *input)
01100 {
01101     return RSA_PrivateKeyOp((RSAPrivateKey *)key, output->data, input->data);
01102 }
01103 
01104 SECStatus
01105 dsa_signDigest(void *key, SECItem *output, const SECItem *input)
01106 {
01107     return DSA_SignDigest((DSAPrivateKey *)key, output, input);
01108 }
01109 
01110 SECStatus
01111 dsa_verifyDigest(void *key, SECItem *output, const SECItem *input)
01112 {
01113     return DSA_VerifyDigest((DSAPublicKey *)key, output, input);
01114 }
01115 
01116 #ifdef NSS_ENABLE_ECC
01117 SECStatus
01118 ecdsa_signDigest(void *key, SECItem *output, const SECItem *input)
01119 {
01120     return ECDSA_SignDigest((ECPrivateKey *)key, output, input);
01121 }
01122 
01123 SECStatus
01124 ecdsa_verifyDigest(void *key, SECItem *output, const SECItem *input)
01125 {
01126     return ECDSA_VerifyDigest((ECPublicKey *)key, output, input);
01127 }
01128 #endif
01129 
01130 SECStatus
01131 bltest_des_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
01132 {
01133     PRIntervalTime time1, time2;
01134     bltestSymmKeyParams *desp = &cipherInfo->params.sk;
01135     int minorMode;
01136     int i;
01137     switch (cipherInfo->mode) {
01138     case bltestDES_ECB:         minorMode = NSS_DES;      break;
01139     case bltestDES_CBC:         minorMode = NSS_DES_CBC;         break;
01140     case bltestDES_EDE_ECB: minorMode = NSS_DES_EDE3;     break;
01141     case bltestDES_EDE_CBC: minorMode = NSS_DES_EDE3_CBC; break;
01142     default:
01143        return SECFailure;
01144     }
01145     cipherInfo->cx = (void*)DES_CreateContext(desp->key.buf.data,
01146                                          desp->iv.buf.data,
01147                                          minorMode, encrypt);
01148     if (cipherInfo->cxreps > 0) {
01149        DESContext **dummycx;
01150        dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(DESContext *));
01151        TIMESTART();
01152        for (i=0; i<cipherInfo->cxreps; i++) {
01153            dummycx[i] = (void*)DES_CreateContext(desp->key.buf.data,
01154                                              desp->iv.buf.data,
01155                                              minorMode, encrypt);
01156        }
01157        TIMEFINISH(cipherInfo->cxtime, 1.0);
01158        for (i=0; i<cipherInfo->cxreps; i++) {
01159            DES_DestroyContext(dummycx[i], PR_TRUE);
01160        }
01161        PORT_Free(dummycx);
01162     }
01163     if (encrypt)
01164        cipherInfo->cipher.symmkeyCipher = des_Encrypt;
01165     else
01166        cipherInfo->cipher.symmkeyCipher = des_Decrypt;
01167     return SECSuccess;
01168 }
01169 
01170 SECStatus
01171 bltest_rc2_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
01172 {
01173     PRIntervalTime time1, time2;
01174     bltestSymmKeyParams *rc2p = &cipherInfo->params.sk;
01175     int minorMode;
01176     int i;
01177     switch (cipherInfo->mode) {
01178     case bltestRC2_ECB: minorMode = NSS_RC2;      break;
01179     case bltestRC2_CBC: minorMode = NSS_RC2_CBC; break;
01180     default:
01181        return SECFailure;
01182     }
01183     cipherInfo->cx = (void*)RC2_CreateContext(rc2p->key.buf.data,
01184                                          rc2p->key.buf.len,
01185                                          rc2p->iv.buf.data,
01186                                          minorMode,
01187                                          rc2p->key.buf.len);
01188     if (cipherInfo->cxreps > 0) {
01189        RC2Context **dummycx;
01190        dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(RC2Context *));
01191        TIMESTART();
01192        for (i=0; i<cipherInfo->cxreps; i++) {
01193            dummycx[i] = (void*)RC2_CreateContext(rc2p->key.buf.data,
01194                                                  rc2p->key.buf.len,
01195                                                  rc2p->iv.buf.data,
01196                                                  minorMode,
01197                                                  rc2p->key.buf.len);
01198        }
01199        TIMEFINISH(cipherInfo->cxtime, 1.0);
01200        for (i=0; i<cipherInfo->cxreps; i++) {
01201            RC2_DestroyContext(dummycx[i], PR_TRUE);
01202        }
01203        PORT_Free(dummycx);
01204     }
01205     if (encrypt)
01206        cipherInfo->cipher.symmkeyCipher = rc2_Encrypt;
01207     else
01208        cipherInfo->cipher.symmkeyCipher = rc2_Decrypt;
01209     return SECSuccess;
01210 }
01211 
01212 SECStatus
01213 bltest_rc4_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
01214 {
01215     PRIntervalTime time1, time2;
01216     int i;
01217     bltestSymmKeyParams *rc4p = &cipherInfo->params.sk;
01218     cipherInfo->cx = (void*)RC4_CreateContext(rc4p->key.buf.data,
01219                                          rc4p->key.buf.len);
01220     if (cipherInfo->cxreps > 0) {
01221        RC4Context **dummycx;
01222        dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(RC4Context *));
01223        TIMESTART();
01224        for (i=0; i<cipherInfo->cxreps; i++) {
01225            dummycx[i] = (void*)RC4_CreateContext(rc4p->key.buf.data,
01226                                                  rc4p->key.buf.len);
01227        }
01228        TIMEFINISH(cipherInfo->cxtime, 1.0);
01229        for (i=0; i<cipherInfo->cxreps; i++) {
01230            RC4_DestroyContext(dummycx[i], PR_TRUE);
01231        }
01232        PORT_Free(dummycx);
01233     }
01234     if (encrypt)
01235        cipherInfo->cipher.symmkeyCipher = rc4_Encrypt;
01236     else
01237        cipherInfo->cipher.symmkeyCipher = rc4_Decrypt;
01238     return SECSuccess;
01239 }
01240 
01241 SECStatus
01242 bltest_rc5_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
01243 {
01244 #if NSS_SOFTOKEN_DOES_RC5
01245     PRIntervalTime time1, time2;
01246     bltestRC5Params *rc5p = &cipherInfo->params.rc5;
01247     int minorMode;
01248     switch (cipherInfo->mode) {
01249     case bltestRC5_ECB: minorMode = NSS_RC5;      break;
01250     case bltestRC5_CBC: minorMode = NSS_RC5_CBC; break;
01251     default:
01252        return SECFailure;
01253     }
01254     TIMESTART();
01255     cipherInfo->cx = (void*)RC5_CreateContext(&rc5p->key.buf,
01256                                          rc5p->rounds, rc5p->wordsize,
01257                                          rc5p->iv.buf.data, minorMode);
01258     TIMEFINISH(cipherInfo->cxtime, 1.0);
01259     if (encrypt)
01260        cipherInfo->cipher.symmkeyCipher = RC5_Encrypt;
01261     else
01262        cipherInfo->cipher.symmkeyCipher = RC5_Decrypt;
01263     return SECSuccess;
01264 #else
01265     return SECFailure;
01266 #endif
01267 }
01268 
01269 SECStatus
01270 bltest_aes_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
01271 {
01272     bltestSymmKeyParams *aesp = &cipherInfo->params.sk;
01273     int minorMode;
01274     int i;
01275     int keylen   = aesp->key.buf.len;
01276     int blocklen = AES_BLOCK_SIZE; 
01277     PRIntervalTime time1, time2;
01278 
01279     switch (cipherInfo->mode) {
01280     case bltestAES_ECB:         minorMode = NSS_AES;      break;
01281     case bltestAES_CBC:         minorMode = NSS_AES_CBC;         break;
01282     default:
01283        return SECFailure;
01284     }
01285     cipherInfo->cx = (void*)AES_CreateContext(aesp->key.buf.data,
01286                                          aesp->iv.buf.data,
01287                                          minorMode, encrypt, 
01288                                               keylen, blocklen);
01289     if (cipherInfo->cxreps > 0) {
01290        AESContext **dummycx;
01291        dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(AESContext *));
01292        TIMESTART();
01293        for (i=0; i<cipherInfo->cxreps; i++) {
01294            dummycx[i] = (void*)AES_CreateContext(aesp->key.buf.data,
01295                                              aesp->iv.buf.data,
01296                                              minorMode, encrypt,
01297                                                  keylen, blocklen);
01298        }
01299        TIMEFINISH(cipherInfo->cxtime, 1.0);
01300        for (i=0; i<cipherInfo->cxreps; i++) {
01301            AES_DestroyContext(dummycx[i], PR_TRUE);
01302        }
01303        PORT_Free(dummycx);
01304     }
01305     if (encrypt)
01306        cipherInfo->cipher.symmkeyCipher = aes_Encrypt;
01307     else
01308        cipherInfo->cipher.symmkeyCipher = aes_Decrypt;
01309     return SECSuccess;
01310 }
01311 
01312 SECStatus
01313 bltest_rsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
01314 {
01315     int i;
01316     RSAPrivateKey **dummyKey;
01317     PRIntervalTime time1, time2;
01318     bltestRSAParams *rsap = &cipherInfo->params.rsa;
01319     /* RSA key gen was done during parameter setup */
01320     cipherInfo->cx = cipherInfo->params.rsa.rsakey;
01321     /* For performance testing */
01322     if (cipherInfo->cxreps > 0) {
01323        /* Create space for n private key objects */
01324        dummyKey = (RSAPrivateKey **)PORT_Alloc(cipherInfo->cxreps *
01325                                           sizeof(RSAPrivateKey *));
01326        /* Time n keygens, storing in the array */
01327        TIMESTART();
01328        for (i=0; i<cipherInfo->cxreps; i++)
01329            dummyKey[i] = RSA_NewKey(rsap->keysizeInBits, 
01330                                     &rsap->rsakey->publicExponent);
01331        TIMEFINISH(cipherInfo->cxtime, cipherInfo->cxreps);
01332        /* Free the n key objects */
01333        for (i=0; i<cipherInfo->cxreps; i++)
01334            PORT_FreeArena(dummyKey[i]->arena, PR_TRUE);
01335        PORT_Free(dummyKey);
01336     }
01337     if (encrypt) {
01338        /* Have to convert private key to public key.  Memory
01339         * is freed with private key's arena  */
01340        RSAPublicKey *pubkey;
01341        RSAPrivateKey *key = (RSAPrivateKey *)cipherInfo->cx;
01342        pubkey = (RSAPublicKey *)PORT_ArenaAlloc(key->arena,
01343                                            sizeof(RSAPublicKey));
01344        pubkey->modulus.len = key->modulus.len;
01345        pubkey->modulus.data = key->modulus.data;
01346        pubkey->publicExponent.len = key->publicExponent.len;
01347        pubkey->publicExponent.data = key->publicExponent.data;
01348        cipherInfo->cx = (void *)pubkey;
01349        cipherInfo->cipher.pubkeyCipher = rsa_PublicKeyOp;
01350     } else {
01351        cipherInfo->cipher.pubkeyCipher = rsa_PrivateKeyOp;
01352     }
01353     return SECSuccess;
01354 }
01355 
01356 SECStatus
01357 bltest_pqg_init(bltestDSAParams *dsap)
01358 {
01359     SECStatus rv, res;
01360     PQGVerify *vfy = NULL;
01361     rv = PQG_ParamGen(dsap->j, &dsap->pqg, &vfy);
01362     CHECKERROR(rv, __LINE__);
01363     rv = PQG_VerifyParams(dsap->pqg, vfy, &res);
01364     CHECKERROR(res, __LINE__);
01365     CHECKERROR(rv, __LINE__);
01366     return rv;
01367 }
01368 
01369 SECStatus
01370 bltest_dsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
01371 {
01372     int i;
01373     DSAPrivateKey **dummyKey;
01374     PQGParams *dummypqg;
01375     PRIntervalTime time1, time2;
01376     bltestDSAParams *dsap = &cipherInfo->params.dsa;
01377     PQGVerify *ignore = NULL;
01378     /* DSA key gen was done during parameter setup */
01379     cipherInfo->cx = cipherInfo->params.dsa.dsakey;
01380     /* For performance testing */
01381     if (cipherInfo->cxreps > 0) {
01382        /* Create space for n private key objects */
01383        dummyKey = (DSAPrivateKey **)PORT_ZAlloc(cipherInfo->cxreps *
01384                                                 sizeof(DSAPrivateKey *));
01385        /* Time n keygens, storing in the array */
01386        TIMESTART();
01387        for (i=0; i<cipherInfo->cxreps; i++) {
01388            dummypqg = NULL;
01389            PQG_ParamGen(dsap->j, &dummypqg, &ignore);
01390            DSA_NewKey(dummypqg, &dummyKey[i]);
01391        }
01392        TIMEFINISH(cipherInfo->cxtime, cipherInfo->cxreps);
01393        /* Free the n key objects */
01394        for (i=0; i<cipherInfo->cxreps; i++)
01395            PORT_FreeArena(dummyKey[i]->params.arena, PR_TRUE);
01396        PORT_Free(dummyKey);
01397     }
01398     if (!dsap->pqg && dsap->pqgdata.buf.len > 0) {
01399        dsap->pqg = pqg_from_filedata(&dsap->pqgdata.buf);
01400     }
01401     if (!cipherInfo->cx && dsap->key.buf.len > 0) {
01402        cipherInfo->cx = dsakey_from_filedata(&dsap->key.buf);
01403     }
01404     if (encrypt) {
01405        cipherInfo->cipher.pubkeyCipher = dsa_signDigest;
01406     } else {
01407        /* Have to convert private key to public key.  Memory
01408         * is freed with private key's arena  */
01409        DSAPublicKey *pubkey;
01410        DSAPrivateKey *key = (DSAPrivateKey *)cipherInfo->cx;
01411        pubkey = (DSAPublicKey *)PORT_ArenaZAlloc(key->params.arena,
01412                                             sizeof(DSAPublicKey));
01413        pubkey->params.prime.len = key->params.prime.len;
01414        pubkey->params.prime.data = key->params.prime.data;
01415        pubkey->params.subPrime.len = key->params.subPrime.len;
01416        pubkey->params.subPrime.data = key->params.subPrime.data;
01417        pubkey->params.base.len = key->params.base.len;
01418        pubkey->params.base.data = key->params.base.data;
01419        pubkey->publicValue.len = key->publicValue.len;
01420        pubkey->publicValue.data = key->publicValue.data;
01421        cipherInfo->cipher.pubkeyCipher = dsa_verifyDigest;
01422     }
01423     return SECSuccess;
01424 }
01425 
01426 #ifdef NSS_ENABLE_ECC
01427 SECStatus
01428 bltest_ecdsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
01429 {
01430     int i;
01431     ECPrivateKey **dummyKey;
01432     PRIntervalTime time1, time2;
01433     bltestECDSAParams *ecdsap = &cipherInfo->params.ecdsa;
01434     /* ECDSA key gen was done during parameter setup */
01435     cipherInfo->cx = cipherInfo->params.ecdsa.eckey;
01436     /* For performance testing */
01437     if (cipherInfo->cxreps > 0) {
01438        /* Create space for n private key objects */
01439        dummyKey = (ECPrivateKey **)PORT_ZAlloc(cipherInfo->cxreps *
01440                                                 sizeof(ECPrivateKey *));
01441        /* Time n keygens, storing in the array */
01442        TIMESTART();
01443        for (i=0; i<cipherInfo->cxreps; i++) {
01444            EC_NewKey(&ecdsap->eckey->ecParams, &dummyKey[i]);
01445        }
01446        TIMEFINISH(cipherInfo->cxtime, cipherInfo->cxreps);
01447        /* Free the n key objects */
01448        for (i=0; i<cipherInfo->cxreps; i++)
01449            PORT_FreeArena(dummyKey[i]->ecParams.arena, PR_TRUE);
01450        PORT_Free(dummyKey);
01451     }
01452     if (!cipherInfo->cx && ecdsap->key.buf.len > 0) {
01453        cipherInfo->cx = eckey_from_filedata(&ecdsap->key.buf);
01454     }
01455     if (encrypt) {
01456        cipherInfo->cipher.pubkeyCipher = ecdsa_signDigest;
01457     } else {
01458        /* Have to convert private key to public key.  Memory
01459         * is freed with private key's arena  */
01460        ECPublicKey *pubkey;
01461        ECPrivateKey *key = (ECPrivateKey *)cipherInfo->cx;
01462        pubkey = (ECPublicKey *)PORT_ArenaZAlloc(key->ecParams.arena,
01463                                             sizeof(ECPublicKey));
01464        pubkey->ecParams.type = key->ecParams.type;
01465        pubkey->ecParams.fieldID.size = key->ecParams.fieldID.size;
01466        pubkey->ecParams.fieldID.type = key->ecParams.fieldID.type;
01467        pubkey->ecParams.fieldID.u.prime.len = key->ecParams.fieldID.u.prime.len;
01468        pubkey->ecParams.fieldID.u.prime.data = key->ecParams.fieldID.u.prime.data;
01469        pubkey->ecParams.fieldID.k1 = key->ecParams.fieldID.k1;
01470        pubkey->ecParams.fieldID.k2 = key->ecParams.fieldID.k2;
01471        pubkey->ecParams.fieldID.k3 = key->ecParams.fieldID.k3;
01472        pubkey->ecParams.curve.a.len = key->ecParams.curve.a.len;
01473        pubkey->ecParams.curve.a.data = key->ecParams.curve.a.data;
01474        pubkey->ecParams.curve.b.len = key->ecParams.curve.b.len;
01475        pubkey->ecParams.curve.b.data = key->ecParams.curve.b.data;
01476        pubkey->ecParams.curve.seed.len = key->ecParams.curve.seed.len;
01477        pubkey->ecParams.curve.seed.data = key->ecParams.curve.seed.data;
01478        pubkey->ecParams.base.len = key->ecParams.base.len;
01479        pubkey->ecParams.base.data = key->ecParams.base.data;
01480        pubkey->ecParams.order.len = key->ecParams.order.len;
01481        pubkey->ecParams.order.data = key->ecParams.order.data;
01482        pubkey->ecParams.cofactor = key->ecParams.cofactor;
01483        pubkey->ecParams.DEREncoding.len = key->ecParams.DEREncoding.len;
01484        pubkey->ecParams.DEREncoding.data = key->ecParams.DEREncoding.data;
01485        pubkey->ecParams.name= key->ecParams.name;
01486        pubkey->publicValue.len = key->publicValue.len;
01487        pubkey->publicValue.data = key->publicValue.data;
01488        cipherInfo->cipher.pubkeyCipher = ecdsa_verifyDigest;
01489     }
01490     return SECSuccess;
01491 }
01492 #endif
01493 
01494 /* XXX unfortunately, this is not defined in blapi.h */
01495 SECStatus
01496 md2_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length)
01497 {
01498     unsigned int len;
01499     MD2Context *cx = MD2_NewContext();
01500     if (cx == NULL) return SECFailure;
01501     MD2_Begin(cx);
01502     MD2_Update(cx, src, src_length);
01503     MD2_End(cx, dest, &len, MD2_LENGTH);
01504     MD2_DestroyContext(cx, PR_TRUE);
01505     return SECSuccess;
01506 }
01507 
01508 SECStatus
01509 md2_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
01510 {
01511     MD2Context *cx, *cx_cpy;
01512     unsigned char *cxbytes;
01513     unsigned int len;
01514     unsigned int i, quarter;
01515     SECStatus rv = SECSuccess;
01516     cx = MD2_NewContext();
01517     MD2_Begin(cx);
01518     /* divide message by 4, restarting 3 times */
01519     quarter = (src_length + 3)/ 4;
01520     for (i=0; i < 4 && src_length > 0; i++) {
01521        MD2_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
01522        len = MD2_FlattenSize(cx);
01523        cxbytes = PORT_Alloc(len);
01524        MD2_Flatten(cx, cxbytes);
01525        cx_cpy = MD2_Resurrect(cxbytes, NULL);
01526        if (!cx_cpy) {
01527            PR_fprintf(PR_STDERR, "%s: MD2_Resurrect failed!\n", progName);
01528            goto finish;
01529        }
01530        rv = PORT_Memcmp(cx, cx_cpy, len);
01531        if (rv) {
01532            MD2_DestroyContext(cx_cpy, PR_TRUE);
01533            PR_fprintf(PR_STDERR, "%s: MD2_restart failed!\n", progName);
01534            goto finish;
01535        }
01536        MD2_DestroyContext(cx_cpy, PR_TRUE);
01537        PORT_Free(cxbytes);
01538        src_length -= quarter;
01539     }
01540     MD2_End(cx, dest, &len, MD2_LENGTH);
01541 finish:
01542     MD2_DestroyContext(cx, PR_TRUE);
01543     return rv;
01544 }
01545 
01546 SECStatus
01547 md5_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
01548 {
01549     SECStatus rv = SECSuccess;
01550     MD5Context *cx, *cx_cpy;
01551     unsigned char *cxbytes;
01552     unsigned int len;
01553     unsigned int i, quarter;
01554     cx = MD5_NewContext();
01555     MD5_Begin(cx);
01556     /* divide message by 4, restarting 3 times */
01557     quarter = (src_length + 3)/ 4;
01558     for (i=0; i < 4 && src_length > 0; i++) {
01559        MD5_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
01560        len = MD5_FlattenSize(cx);
01561        cxbytes = PORT_Alloc(len);
01562        MD5_Flatten(cx, cxbytes);
01563        cx_cpy = MD5_Resurrect(cxbytes, NULL);
01564        if (!cx_cpy) {
01565            PR_fprintf(PR_STDERR, "%s: MD5_Resurrect failed!\n", progName);
01566            rv = SECFailure;
01567            goto finish;
01568        }
01569        rv = PORT_Memcmp(cx, cx_cpy, len);
01570        if (rv) {
01571            MD5_DestroyContext(cx_cpy, PR_TRUE);
01572            PR_fprintf(PR_STDERR, "%s: MD5_restart failed!\n", progName);
01573            goto finish;
01574        }
01575        MD5_DestroyContext(cx_cpy, PR_TRUE);
01576        PORT_Free(cxbytes);
01577        src_length -= quarter;
01578     }
01579     MD5_End(cx, dest, &len, MD5_LENGTH);
01580 finish:
01581     MD5_DestroyContext(cx, PR_TRUE);
01582     return rv;
01583 }
01584 
01585 SECStatus
01586 sha1_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
01587 {
01588     SECStatus rv = SECSuccess;
01589     SHA1Context *cx, *cx_cpy;
01590     unsigned char *cxbytes;
01591     unsigned int len;
01592     unsigned int i, quarter;
01593     cx = SHA1_NewContext();
01594     SHA1_Begin(cx);
01595     /* divide message by 4, restarting 3 times */
01596     quarter = (src_length + 3)/ 4;
01597     for (i=0; i < 4 && src_length > 0; i++) {
01598        SHA1_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
01599        len = SHA1_FlattenSize(cx);
01600        cxbytes = PORT_Alloc(len);
01601        SHA1_Flatten(cx, cxbytes);
01602        cx_cpy = SHA1_Resurrect(cxbytes, NULL);
01603        if (!cx_cpy) {
01604            PR_fprintf(PR_STDERR, "%s: SHA1_Resurrect failed!\n", progName);
01605            rv = SECFailure;
01606            goto finish;
01607        }
01608        rv = PORT_Memcmp(cx, cx_cpy, len);
01609        if (rv) {
01610            SHA1_DestroyContext(cx_cpy, PR_TRUE);
01611            PR_fprintf(PR_STDERR, "%s: SHA1_restart failed!\n", progName);
01612            goto finish;
01613        }
01614        SHA1_DestroyContext(cx_cpy, PR_TRUE);
01615        PORT_Free(cxbytes);
01616        src_length -= quarter;
01617     }
01618     SHA1_End(cx, dest, &len, MD5_LENGTH);
01619 finish:
01620     SHA1_DestroyContext(cx, PR_TRUE);
01621     return rv;
01622 }
01623 
01624 SECStatus
01625 SHA256_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
01626 {
01627     SECStatus rv = SECSuccess;
01628     SHA256Context *cx, *cx_cpy;
01629     unsigned char *cxbytes;
01630     unsigned int len;
01631     unsigned int i, quarter;
01632     cx = SHA256_NewContext();
01633     SHA256_Begin(cx);
01634     /* divide message by 4, restarting 3 times */
01635     quarter = (src_length + 3)/ 4;
01636     for (i=0; i < 4 && src_length > 0; i++) {
01637        SHA256_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
01638        len = SHA256_FlattenSize(cx);
01639        cxbytes = PORT_Alloc(len);
01640        SHA256_Flatten(cx, cxbytes);
01641        cx_cpy = SHA256_Resurrect(cxbytes, NULL);
01642        if (!cx_cpy) {
01643            PR_fprintf(PR_STDERR, "%s: SHA256_Resurrect failed!\n", progName);
01644            rv = SECFailure;
01645            goto finish;
01646        }
01647        rv = PORT_Memcmp(cx, cx_cpy, len);
01648        if (rv) {
01649            SHA256_DestroyContext(cx_cpy, PR_TRUE);
01650            PR_fprintf(PR_STDERR, "%s: SHA256_restart failed!\n", progName);
01651            goto finish;
01652        }
01653        SHA256_DestroyContext(cx_cpy, PR_TRUE);
01654        PORT_Free(cxbytes);
01655        src_length -= quarter;
01656     }
01657     SHA256_End(cx, dest, &len, MD5_LENGTH);
01658 finish:
01659     SHA256_DestroyContext(cx, PR_TRUE);
01660     return rv;
01661 }
01662 
01663 SECStatus
01664 SHA384_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
01665 {
01666     SECStatus rv = SECSuccess;
01667     SHA384Context *cx, *cx_cpy;
01668     unsigned char *cxbytes;
01669     unsigned int len;
01670     unsigned int i, quarter;
01671     cx = SHA384_NewContext();
01672     SHA384_Begin(cx);
01673     /* divide message by 4, restarting 3 times */
01674     quarter = (src_length + 3)/ 4;
01675     for (i=0; i < 4 && src_length > 0; i++) {
01676        SHA384_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
01677        len = SHA384_FlattenSize(cx);
01678        cxbytes = PORT_Alloc(len);
01679        SHA384_Flatten(cx, cxbytes);
01680        cx_cpy = SHA384_Resurrect(cxbytes, NULL);
01681        if (!cx_cpy) {
01682            PR_fprintf(PR_STDERR, "%s: SHA384_Resurrect failed!\n", progName);
01683            rv = SECFailure;
01684            goto finish;
01685        }
01686        rv = PORT_Memcmp(cx, cx_cpy, len);
01687        if (rv) {
01688            SHA384_DestroyContext(cx_cpy, PR_TRUE);
01689            PR_fprintf(PR_STDERR, "%s: SHA384_restart failed!\n", progName);
01690            goto finish;
01691        }
01692        SHA384_DestroyContext(cx_cpy, PR_TRUE);
01693        PORT_Free(cxbytes);
01694        src_length -= quarter;
01695     }
01696     SHA384_End(cx, dest, &len, MD5_LENGTH);
01697 finish:
01698     SHA384_DestroyContext(cx, PR_TRUE);
01699     return rv;
01700 }
01701 
01702 SECStatus
01703 SHA512_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
01704 {
01705     SECStatus rv = SECSuccess;
01706     SHA512Context *cx, *cx_cpy;
01707     unsigned char *cxbytes;
01708     unsigned int len;
01709     unsigned int i, quarter;
01710     cx = SHA512_NewContext();
01711     SHA512_Begin(cx);
01712     /* divide message by 4, restarting 3 times */
01713     quarter = (src_length + 3)/ 4;
01714     for (i=0; i < 4 && src_length > 0; i++) {
01715        SHA512_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
01716        len = SHA512_FlattenSize(cx);
01717        cxbytes = PORT_Alloc(len);
01718        SHA512_Flatten(cx, cxbytes);
01719        cx_cpy = SHA512_Resurrect(cxbytes, NULL);
01720        if (!cx_cpy) {
01721            PR_fprintf(PR_STDERR, "%s: SHA512_Resurrect failed!\n", progName);
01722            rv = SECFailure;
01723            goto finish;
01724        }
01725        rv = PORT_Memcmp(cx, cx_cpy, len);
01726        if (rv) {
01727            SHA512_DestroyContext(cx_cpy, PR_TRUE);
01728            PR_fprintf(PR_STDERR, "%s: SHA512_restart failed!\n", progName);
01729            goto finish;
01730        }
01731        SHA512_DestroyContext(cx_cpy, PR_TRUE);
01732        PORT_Free(cxbytes);
01733        src_length -= quarter;
01734     }
01735     SHA512_End(cx, dest, &len, MD5_LENGTH);
01736 finish:
01737     SHA512_DestroyContext(cx, PR_TRUE);
01738     return rv;
01739 }
01740 
01741 SECStatus
01742 pubkeyInitKey(bltestCipherInfo *cipherInfo, PRFileDesc *file,
01743 #ifdef NSS_ENABLE_ECC
01744              int keysize, int exponent, char *curveName)
01745 #else
01746              int keysize, int exponent)
01747 #endif
01748 {
01749     int i;
01750     SECStatus rv = SECSuccess;
01751     bltestRSAParams *rsap;
01752     bltestDSAParams *dsap;
01753 #ifdef NSS_ENABLE_ECC
01754     bltestECDSAParams *ecdsap;
01755     SECItem *tmpECParamsDER;
01756     ECParams *tmpECParams = NULL;
01757     SECItem ecSerialize[3];
01758 #endif
01759     switch (cipherInfo->mode) {
01760     case bltestRSA:
01761        rsap = &cipherInfo->params.rsa;
01762        if (keysize > 0) {
01763            SECItem expitem = { 0, 0, 0 };
01764            SECITEM_AllocItem(cipherInfo->arena, &expitem, sizeof(int));
01765            for (i = 1; i <= sizeof(int); i++)
01766               expitem.data[i-1] = exponent >> (8*(sizeof(int) - i));
01767            rsap->rsakey = RSA_NewKey(keysize * 8, &expitem);
01768            serialize_key(&rsap->rsakey->version, 9, file);
01769            rsap->keysizeInBits = keysize * 8;
01770        } else {
01771            setupIO(cipherInfo->arena, &cipherInfo->params.key, file, NULL, 0);
01772            rsap->rsakey = rsakey_from_filedata(&cipherInfo->params.key.buf);
01773            rsap->keysizeInBits = rsap->rsakey->modulus.len * 8;
01774        }
01775        break;
01776     case bltestDSA:
01777        dsap = &cipherInfo->params.dsa;
01778        if (keysize > 0) {
01779            dsap->j = PQG_PBITS_TO_INDEX(8*keysize);
01780            if (!dsap->pqg)
01781               bltest_pqg_init(dsap);
01782            rv = DSA_NewKey(dsap->pqg, &dsap->dsakey);
01783            CHECKERROR(rv, __LINE__);
01784            serialize_key(&dsap->dsakey->params.prime, 5, file);
01785        } else {
01786            setupIO(cipherInfo->arena, &cipherInfo->params.key, file, NULL, 0);
01787            dsap->dsakey = dsakey_from_filedata(&cipherInfo->params.key.buf);
01788            dsap->j = PQG_PBITS_TO_INDEX(8*dsap->dsakey->params.prime.len);
01789        }
01790        break;
01791 #ifdef NSS_ENABLE_ECC
01792     case bltestECDSA:
01793        ecdsap = &cipherInfo->params.ecdsa;
01794        if (curveName != NULL) {
01795            tmpECParamsDER = getECParams(curveName);
01796            rv = secoid_Init();
01797            CHECKERROR(rv, __LINE__);
01798            rv = EC_DecodeParams(tmpECParamsDER, &tmpECParams) == SECFailure;
01799            CHECKERROR(rv, __LINE__);
01800            rv = EC_NewKey(tmpECParams, &ecdsap->eckey);
01801            CHECKERROR(rv, __LINE__);
01802            ecSerialize[0].type = tmpECParamsDER->type;
01803            ecSerialize[0].data = tmpECParamsDER->data;
01804            ecSerialize[0].len  = tmpECParamsDER->len;
01805            ecSerialize[1].type = ecdsap->eckey->publicValue.type;
01806            ecSerialize[1].data = ecdsap->eckey->publicValue.data;
01807            ecSerialize[1].len  = ecdsap->eckey->publicValue.len;
01808            ecSerialize[2].type = ecdsap->eckey->privateValue.type;
01809            ecSerialize[2].data = ecdsap->eckey->privateValue.data;
01810            ecSerialize[2].len  = ecdsap->eckey->privateValue.len;
01811            serialize_key(&(ecSerialize[0]), 3, file);
01812            free(tmpECParamsDER);
01813            PORT_FreeArena(tmpECParams->arena, PR_TRUE);
01814            rv = SECOID_Shutdown();
01815            CHECKERROR(rv, __LINE__);
01816        } else {
01817            setupIO(cipherInfo->arena, &cipherInfo->params.key, file, NULL, 0);
01818            ecdsap->eckey = eckey_from_filedata(&cipherInfo->params.key.buf);
01819        }
01820        break;
01821 #endif
01822     default:
01823        return SECFailure;
01824     }
01825     return SECSuccess;
01826 }
01827 
01828 SECStatus
01829 cipherInit(bltestCipherInfo *cipherInfo, PRBool encrypt)
01830 {
01831     PRBool restart;
01832     switch (cipherInfo->mode) {
01833     case bltestDES_ECB:
01834     case bltestDES_CBC:
01835     case bltestDES_EDE_ECB:
01836     case bltestDES_EDE_CBC:
01837        SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
01838                        cipherInfo->input.pBuf.len);
01839        return bltest_des_init(cipherInfo, encrypt);
01840        break;
01841     case bltestRC2_ECB:
01842     case bltestRC2_CBC:
01843        SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
01844                        cipherInfo->input.pBuf.len);
01845        return bltest_rc2_init(cipherInfo, encrypt);
01846        break;
01847     case bltestRC4:
01848        SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
01849                        cipherInfo->input.pBuf.len);
01850        return bltest_rc4_init(cipherInfo, encrypt);
01851        break;
01852     case bltestRC5_ECB:
01853     case bltestRC5_CBC:
01854 #if NSS_SOFTOKEN_DOES_RC5
01855        SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
01856                        cipherInfo->input.pBuf.len);
01857 #endif
01858        return bltest_rc5_init(cipherInfo, encrypt);
01859        break;
01860     case bltestAES_ECB:
01861     case bltestAES_CBC:
01862        SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
01863                        cipherInfo->input.pBuf.len);
01864        return bltest_aes_init(cipherInfo, encrypt);
01865        break;
01866     case bltestRSA:
01867        SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
01868                        cipherInfo->input.pBuf.len);
01869        return bltest_rsa_init(cipherInfo, encrypt);
01870        break;
01871     case bltestDSA:
01872        SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
01873                        DSA_SIGNATURE_LEN);
01874        return bltest_dsa_init(cipherInfo, encrypt);
01875        break;
01876 #ifdef NSS_ENABLE_ECC
01877     case bltestECDSA:
01878        SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
01879                        2 * MAX_ECKEY_LEN);
01880        return bltest_ecdsa_init(cipherInfo, encrypt);
01881        break;
01882 #endif
01883     case bltestMD2:
01884        restart = cipherInfo->params.hash.restart;
01885        SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
01886                        MD2_LENGTH);
01887        cipherInfo->cipher.hashCipher = (restart) ? md2_restart : md2_HashBuf;
01888        return SECSuccess;
01889        break;
01890     case bltestMD5:
01891        restart = cipherInfo->params.hash.restart;
01892        SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
01893                        MD5_LENGTH);
01894        cipherInfo->cipher.hashCipher = (restart) ? md5_restart : MD5_HashBuf;
01895        return SECSuccess;
01896        break;
01897     case bltestSHA1:
01898        restart = cipherInfo->params.hash.restart;
01899        SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
01900                        SHA1_LENGTH);
01901        cipherInfo->cipher.hashCipher = (restart) ? sha1_restart : SHA1_HashBuf;
01902        return SECSuccess;
01903        break;
01904     case bltestSHA256:
01905        restart = cipherInfo->params.hash.restart;
01906        SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
01907                        SHA256_LENGTH);
01908        cipherInfo->cipher.hashCipher = (restart) ? SHA256_restart 
01909                                                  : SHA256_HashBuf;
01910        return SECSuccess;
01911        break;
01912     case bltestSHA384:
01913        restart = cipherInfo->params.hash.restart;
01914        SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
01915                        SHA384_LENGTH);
01916        cipherInfo->cipher.hashCipher = (restart) ? SHA384_restart 
01917                                                  : SHA384_HashBuf;
01918        return SECSuccess;
01919        break;
01920     case bltestSHA512:
01921        restart = cipherInfo->params.hash.restart;
01922        SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
01923                        SHA512_LENGTH);
01924        cipherInfo->cipher.hashCipher = (restart) ? SHA512_restart 
01925                                                  : SHA512_HashBuf;
01926        return SECSuccess;
01927        break;
01928     default:
01929        return SECFailure;
01930     }
01931     return SECSuccess;
01932 }
01933 
01934 SECStatus
01935 dsaOp(bltestCipherInfo *cipherInfo)
01936 {
01937     PRIntervalTime time1, time2;
01938     SECStatus rv = SECSuccess;
01939     int i;
01940     int maxLen = cipherInfo->output.pBuf.len;
01941     SECItem dummyOut = { 0, 0, 0 };
01942     SECITEM_AllocItem(NULL, &dummyOut, maxLen);
01943     if (cipherInfo->cipher.pubkeyCipher == dsa_signDigest) {
01944        if (cipherInfo->params.dsa.sigseed.buf.len > 0) {
01945             bltestDSAParams *dsa = &cipherInfo->params.dsa;
01946             DSAPrivateKey *key = (DSAPrivateKey *)cipherInfo->cx;
01947 
01948             TIMESTART();
01949             rv = DSA_SignDigestWithSeed(key,
01950                                         &cipherInfo->output.pBuf,
01951                                         &cipherInfo->input.pBuf,
01952                                         dsa->sigseed.buf.data);
01953             TIMEFINISH(cipherInfo->optime, 1.0);
01954             CHECKERROR(rv, __LINE__);
01955             cipherInfo->repetitions = 0;
01956             if (cipherInfo->repetitionsToPerfom != 0) {
01957                 TIMESTART();
01958                 for (i=0; i<cipherInfo->repetitionsToPerfom;
01959                      i++, cipherInfo->repetitions++) {
01960                     rv = DSA_SignDigestWithSeed(key, &dummyOut,
01961                                                 &cipherInfo->input.pBuf,
01962                                                 dsa->sigseed.buf.data);
01963                     CHECKERROR(rv, __LINE__);
01964                 }
01965             } else {
01966                 int opsBetweenChecks = 0;
01967                 TIMEMARK(cipherInfo->seconds);
01968                 while (! (TIMETOFINISH())) {
01969                     int j = 0;
01970                     for (;j < opsBetweenChecks;j++) {
01971                         rv = DSA_SignDigestWithSeed(key, &dummyOut,
01972                                                     &cipherInfo->input.pBuf,
01973                                                     dsa->sigseed.buf.data);
01974                         CHECKERROR(rv, __LINE__);
01975                     }
01976                     cipherInfo->repetitions += j;
01977                 }
01978             }
01979             TIMEFINISH(cipherInfo->optime, 1.0);
01980         } else {
01981             TIMESTART();
01982             rv = DSA_SignDigest((DSAPrivateKey *)cipherInfo->cx,
01983                                 &cipherInfo->output.pBuf,
01984                                 &cipherInfo->input.pBuf);
01985             TIMEFINISH(cipherInfo->optime, 1.0);
01986             CHECKERROR(rv, __LINE__);
01987             cipherInfo->repetitions = 0;
01988             if (cipherInfo->repetitionsToPerfom != 0) {
01989                 TIMESTART();
01990                 for (i=0; i<cipherInfo->repetitionsToPerfom;
01991                      i++, cipherInfo->repetitions++) {
01992                     rv = DSA_SignDigest((DSAPrivateKey *)cipherInfo->cx,
01993                                         &dummyOut,
01994                                         &cipherInfo->input.pBuf);
01995                     CHECKERROR(rv, __LINE__);
01996                 }
01997             } else {
01998                 int opsBetweenChecks = 0;
01999                 TIMEMARK(cipherInfo->seconds);
02000                 while (! (TIMETOFINISH())) {
02001                     int j = 0;
02002                     for (;j < opsBetweenChecks;j++) {
02003                         rv = DSA_SignDigest((DSAPrivateKey *)cipherInfo->cx,
02004                                             &dummyOut,
02005                                             &cipherInfo->input.pBuf);
02006                         CHECKERROR(rv, __LINE__);
02007                     }
02008                     cipherInfo->repetitions += j;
02009                 }
02010             }
02011             TIMEFINISH(cipherInfo->optime, 1.0);
02012         }
02013         bltestCopyIO(cipherInfo->arena, &cipherInfo->params.dsa.sig, 
02014                      &cipherInfo->output);
02015     } else {
02016         TIMESTART();
02017         rv = DSA_VerifyDigest((DSAPublicKey *)cipherInfo->cx,
02018                               &cipherInfo->params.dsa.sig.buf,
02019                               &cipherInfo->input.pBuf);
02020         TIMEFINISH(cipherInfo->optime, 1.0);
02021         CHECKERROR(rv, __LINE__);
02022         cipherInfo->repetitions = 0;
02023         if (cipherInfo->repetitionsToPerfom != 0) {
02024             TIMESTART();
02025             for (i=0; i<cipherInfo->repetitionsToPerfom;
02026                  i++, cipherInfo->repetitions++) {
02027                 rv = DSA_VerifyDigest((DSAPublicKey *)cipherInfo->cx,
02028                                       &cipherInfo->params.dsa.sig.buf,
02029                                       &cipherInfo->input.pBuf);
02030                 CHECKERROR(rv, __LINE__);
02031             }
02032         } else {
02033             int opsBetweenChecks = 0;
02034             TIMEMARK(cipherInfo->seconds);
02035             while (! (TIMETOFINISH())) {
02036                 int j = 0;
02037                 for (;j < opsBetweenChecks;j++) {
02038                     rv = DSA_VerifyDigest((DSAPublicKey *)cipherInfo->cx,
02039                                           &cipherInfo->params.dsa.sig.buf,
02040                                           &cipherInfo->input.pBuf);
02041                     CHECKERROR(rv, __LINE__);
02042                 }
02043                 cipherInfo->repetitions += j;
02044             }
02045         }
02046         TIMEFINISH(cipherInfo->optime, 1.0);
02047     }
02048     SECITEM_FreeItem(&dummyOut, PR_FALSE);
02049     return rv;
02050 }
02051 
02052 #ifdef NSS_ENABLE_ECC
02053 SECStatus
02054 ecdsaOp(bltestCipherInfo *cipherInfo)
02055 {
02056     PRIntervalTime time1, time2;
02057     SECStatus rv = SECSuccess;
02058     int i;
02059     int maxLen = cipherInfo->output.pBuf.len;
02060     SECItem dummyOut = { 0, 0, 0 };
02061     SECITEM_AllocItem(NULL, &dummyOut, maxLen);
02062     if (cipherInfo->cipher.pubkeyCipher == ecdsa_signDigest) {
02063         if (cipherInfo->params.ecdsa.sigseed.buf.len > 0) {
02064             ECPrivateKey *key = (ECPrivateKey *)cipherInfo->cx;
02065             bltestECDSAParams *ecdsa = &cipherInfo->params.ecdsa;
02066 
02067             TIMESTART();
02068             rv = ECDSA_SignDigestWithSeed(key,
02069                                           &cipherInfo->output.pBuf,
02070                                           &cipherInfo->input.pBuf,
02071                                           ecdsa->sigseed.buf.data,
02072                                           ecdsa->sigseed.buf.len);
02073             TIMEFINISH(cipherInfo->optime, 1.0);
02074             CHECKERROR(rv, __LINE__);
02075             cipherInfo->repetitions = 0;
02076             if (cipherInfo->repetitionsToPerfom != 0) {
02077                 TIMESTART();
02078                 for (i=0; i<cipherInfo->repetitionsToPerfom;
02079                      i++, cipherInfo->repetitions++) {
02080                     rv = ECDSA_SignDigestWithSeed(key, &dummyOut,
02081                                                   &cipherInfo->input.pBuf,
02082                                                   ecdsa->sigseed.buf.data,
02083                                                   ecdsa->sigseed.buf.len);
02084                     CHECKERROR(rv, __LINE__);
02085                 }
02086             } else {
02087                 int opsBetweenChecks = 0;
02088                 TIMEMARK(cipherInfo->seconds);
02089                 while (! (TIMETOFINISH())) {
02090                     int j = 0;
02091                     for (;j < opsBetweenChecks;j++) {
02092                         rv = ECDSA_SignDigestWithSeed(key, &dummyOut,
02093                                                       &cipherInfo->input.pBuf,
02094                                                       ecdsa->sigseed.buf.data,
02095                                                       ecdsa->sigseed.buf.len);
02096                         CHECKERROR(rv, __LINE__);
02097                     }
02098                     cipherInfo->repetitions += j;
02099                 }
02100             }
02101             TIMEFINISH(cipherInfo->optime, 1.0);
02102         } else {
02103             TIMESTART();
02104             rv = ECDSA_SignDigest((ECPrivateKey *)cipherInfo->cx,
02105                                   &cipherInfo->output.pBuf,
02106                                   &cipherInfo->input.pBuf);
02107             TIMEFINISH(cipherInfo->optime, 1.0);
02108             CHECKERROR(rv, __LINE__);
02109             cipherInfo->repetitions = 0;
02110             if (cipherInfo->repetitionsToPerfom != 0) {
02111                 TIMESTART();
02112                 for (i=0; i<cipherInfo->repetitionsToPerfom;
02113                      i++, cipherInfo->repetitions++) {
02114                     rv = ECDSA_SignDigest((ECPrivateKey *)cipherInfo->cx,
02115                                           &dummyOut,
02116                                           &cipherInfo->input.pBuf);
02117                     CHECKERROR(rv, __LINE__);
02118                 }
02119             } else {
02120                 int opsBetweenChecks = 0;
02121                 TIMEMARK(cipherInfo->seconds);
02122                 while (! (TIMETOFINISH())) {
02123                     int j = 0;
02124                     for (;j < opsBetweenChecks;j++) {
02125                         rv = ECDSA_SignDigest((ECPrivateKey *)cipherInfo->cx,
02126                                               &dummyOut,
02127                                               &cipherInfo->input.pBuf);
02128                         CHECKERROR(rv, __LINE__);
02129                     }
02130                     cipherInfo->repetitions += j;
02131                 }
02132             }
02133             TIMEFINISH(cipherInfo->optime, 1.0);
02134         }
02135         bltestCopyIO(cipherInfo->arena, &cipherInfo->params.ecdsa.sig, 
02136                      &cipherInfo->output);
02137     } else {
02138         TIMESTART();
02139         rv = ECDSA_VerifyDigest((ECPublicKey *)cipherInfo->cx,
02140                                 &cipherInfo->params.ecdsa.sig.buf,
02141                                 &cipherInfo->input.pBuf);
02142         TIMEFINISH(cipherInfo->optime, 1.0);
02143         CHECKERROR(rv, __LINE__);
02144         cipherInfo->repetitions = 0;
02145         if (cipherInfo->repetitionsToPerfom != 0) {
02146             TIMESTART();
02147             for (i=0; i<cipherInfo->repetitionsToPerfom;
02148                  i++, cipherInfo->repetitions++) {
02149                 rv = ECDSA_VerifyDigest((ECPublicKey *)cipherInfo->cx,
02150                                         &cipherInfo->params.ecdsa.sig.buf,
02151                                         &cipherInfo->input.pBuf);
02152                 CHECKERROR(rv, __LINE__);
02153             }
02154         } else {
02155             int opsBetweenChecks = 0;
02156             TIMEMARK(cipherInfo->seconds);
02157             while (! (TIMETOFINISH())) {
02158                 int j = 0;
02159                 for (;j < opsBetweenChecks;j++) {
02160                     rv = ECDSA_VerifyDigest((ECPublicKey *)cipherInfo->cx,
02161                                             &cipherInfo->params.ecdsa.sig.buf,
02162                                             &cipherInfo->input.pBuf);
02163                     CHECKERROR(rv, __LINE__);
02164                 }
02165                 cipherInfo->repetitions += j;
02166             }
02167         }
02168         TIMEFINISH(cipherInfo->optime, 1.0);
02169     }
02170     SECITEM_FreeItem(&dummyOut, PR_FALSE);
02171     return rv;
02172 }
02173 #endif
02174 
02175 SECStatus
02176 cipherDoOp(bltestCipherInfo *cipherInfo)
02177 {
02178     PRIntervalTime time1, time2;
02179     SECStatus rv = SECSuccess;
02180     int i, len;
02181     int maxLen = cipherInfo->output.pBuf.len;
02182     unsigned char *dummyOut;
02183     if (cipherInfo->mode == bltestDSA)
02184        return dsaOp(cipherInfo);
02185 #ifdef NSS_ENABLE_ECC
02186     else if (cipherInfo->mode == bltestECDSA)
02187        return ecdsaOp(cipherInfo);
02188 #endif
02189     dummyOut = PORT_Alloc(maxLen);
02190     if (is_symmkeyCipher(cipherInfo->mode)) {
02191         TIMESTART();
02192         rv = (*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx,
02193                                                  cipherInfo->output.pBuf.data,
02194                                                  &len, maxLen,
02195                                                  cipherInfo->input.pBuf.data,
02196                                                  cipherInfo->input.pBuf.len);
02197         TIMEFINISH(cipherInfo->optime, 1.0);
02198         CHECKERROR(rv, __LINE__);
02199         cipherInfo->repetitions = 0;
02200         if (cipherInfo->repetitionsToPerfom != 0) {
02201             TIMESTART();
02202             for (i=0; i<cipherInfo->repetitionsToPerfom; i++,
02203                      cipherInfo->repetitions++) {
02204                 (*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx, dummyOut,
02205                                                     &len, maxLen,
02206                                                     cipherInfo->input.pBuf.data,
02207                                                     cipherInfo->input.pBuf.len);
02208                 
02209                 CHECKERROR(rv, __LINE__);
02210             }
02211         } else {
02212             int opsBetweenChecks = 0;
02213             bltestIO *input = &cipherInfo->input;
02214             TIMEMARK(cipherInfo->seconds);
02215             while (! (TIMETOFINISH())) {
02216                 int j = 0;
02217                 for (;j < opsBetweenChecks;j++) {
02218                     (*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx,
02219                                                         dummyOut,
02220                                                         &len, maxLen,
02221                                                         input->pBuf.data,
02222                                                         input->pBuf.len);
02223                 }
02224                 cipherInfo->repetitions += j;
02225             }
02226         }
02227         TIMEFINISH(cipherInfo->optime, 1.0);
02228     } else if (is_pubkeyCipher(cipherInfo->mode)) {
02229         TIMESTART();
02230         rv = (*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx,
02231                                                 &cipherInfo->output.pBuf,
02232                                                 &cipherInfo->input.pBuf);
02233         TIMEFINISH(cipherInfo->optime, 1.0);
02234         CHECKERROR(rv, __LINE__);
02235         cipherInfo->repetitions = 0;
02236         if (cipherInfo->repetitionsToPerfom != 0) {
02237             TIMESTART();
02238             for (i=0; i<cipherInfo->repetitionsToPerfom;
02239                  i++, cipherInfo->repetitions++) {
02240                 SECItem dummy;
02241                 dummy.data = dummyOut;
02242                 dummy.len = maxLen;
02243                 (*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx, &dummy, 
02244                                                    &cipherInfo->input.pBuf);
02245                 CHECKERROR(rv, __LINE__);
02246             }
02247         } else {
02248             int opsBetweenChecks = 0;
02249             TIMEMARK(cipherInfo->seconds);
02250             while (! (TIMETOFINISH())) {
02251                 int j = 0;
02252                 for (;j < opsBetweenChecks;j++) {
02253                     SECItem dummy;
02254                     dummy.data = dummyOut;
02255                     dummy.len = maxLen;
02256                     (*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx, &dummy,
02257                                                        &cipherInfo->input.pBuf);
02258                     CHECKERROR(rv, __LINE__);
02259                 }
02260                 cipherInfo->repetitions += j;
02261             }
02262         }
02263         TIMEFINISH(cipherInfo->optime, 1.0);
02264     } else if (is_hashCipher(cipherInfo->mode)) {
02265         TIMESTART();
02266         rv = (*cipherInfo->cipher.hashCipher)(cipherInfo->output.pBuf.data,
02267                                               cipherInfo->input.pBuf.data,
02268                                               cipherInfo->input.pBuf.len);
02269         TIMEFINISH(cipherInfo->optime, 1.0);
02270         CHECKERROR(rv, __LINE__);
02271         cipherInfo->repetitions = 0;
02272         if (cipherInfo->repetitionsToPerfom != 0) {
02273             TIMESTART();
02274             for (i=0; i<cipherInfo->repetitionsToPerfom;
02275                  i++, cipherInfo->repetitions++) {
02276                 (*cipherInfo->cipher.hashCipher)(dummyOut,
02277                                                  cipherInfo->input.pBuf.data,
02278                                                  cipherInfo->input.pBuf.len);
02279                 CHECKERROR(rv, __LINE__);
02280             }
02281         } else {
02282             int opsBetweenChecks = 0;
02283             TIMEMARK(cipherInfo->seconds);
02284             while (! (TIMETOFINISH())) {
02285                 int j = 0;
02286                 for (;j < opsBetweenChecks;j++) {
02287                     bltestIO *input = &cipherInfo->input;
02288                     (*cipherInfo->cipher.hashCipher)(dummyOut,
02289                                                      input->pBuf.data,
02290                                                      input->pBuf.len);
02291                     CHECKERROR(rv, __LINE__);
02292                 }
02293                 cipherInfo->repetitions += j;
02294             }
02295         }
02296         TIMEFINISH(cipherInfo->optime, 1.0);
02297     }
02298     PORT_Free(dummyOut);
02299     return rv;
02300 }
02301 
02302 SECStatus
02303 cipherFinish(bltestCipherInfo *cipherInfo)
02304 {
02305     switch (cipherInfo->mode) {
02306     case bltestDES_ECB:
02307     case bltestDES_CBC:
02308     case bltestDES_EDE_ECB:
02309     case bltestDES_EDE_CBC:
02310        DES_DestroyContext((DESContext *)cipherInfo->cx, PR_TRUE);
02311        break;
02312     case bltestAES_ECB:
02313     case bltestAES_CBC:
02314        AES_DestroyContext((AESContext *)cipherInfo->cx, PR_TRUE);
02315        break;
02316     case bltestRC2_ECB:
02317     case bltestRC2_CBC:
02318        RC2_DestroyContext((RC2Context *)cipherInfo->cx, PR_TRUE);
02319        break;
02320     case bltestRC4:
02321        RC4_DestroyContext((RC4Context *)cipherInfo->cx, PR_TRUE);
02322        break;
02323 #if NSS_SOFTOKEN_DOES_RC5
02324     case bltestRC5_ECB:
02325     case bltestRC5_CBC:
02326        RC5_DestroyContext((RC5Context *)cipherInfo->cx, PR_TRUE);
02327        break;
02328 #endif
02329     case bltestRSA: /* keys are alloc'ed within cipherInfo's arena, */
02330     case bltestDSA: /* will be freed with it. */
02331 #ifdef NSS_ENABLE_ECC
02332     case bltestECDSA:
02333 #endif
02334     case bltestMD2: /* hash contexts are ephemeral */
02335     case bltestMD5:
02336     case bltestSHA1:
02337     case bltestSHA256:
02338     case bltestSHA384:
02339     case bltestSHA512:
02340        return SECSuccess;
02341        break;
02342     default:
02343        return SECFailure;
02344     }
02345     return SECSuccess;
02346 }
02347 
02348 void
02349 print_exponent(SECItem *exp)
02350 {
02351     int i;
02352     int e = 0;
02353     if (exp->len <= 4) {
02354        for (i=exp->len; i >=0; --i) e |= exp->data[exp->len-i] << 8*(i-1);
02355        fprintf(stdout, "%12d", e);
02356     } else {
02357        e = 8*exp->len;
02358        fprintf(stdout, "~2**%-8d", e);
02359     }
02360 }
02361 
02362 static void
02363 splitToReportUnit(PRInt64 res, int *resArr, int *del, int size)
02364 {
02365     PRInt64 remaining = res, tmp = 0;
02366     PRInt64 Ldel;
02367     int i = -1;
02368 
02369     while (remaining > 0 && ++i < size) {
02370         LL_I2L(Ldel, del[i]);
02371         LL_MOD(tmp, remaining, Ldel);
02372         LL_L2I(resArr[i], tmp);
02373         LL_DIV(remaining, remaining, Ldel);
02374     }
02375 }
02376 
02377 static char*
02378 getHighUnitBytes(PRInt64 res)
02379 {
02380     int spl[] = {0, 0, 0, 0};
02381     int del[] = {1024, 1024, 1024, 1024};
02382     char *marks[] = {"b", "Kb", "Mb", "Gb"};
02383     int i = 3;
02384 
02385     splitToReportUnit(res, spl, del, 4);
02386 
02387     for (;i>0;i--) {
02388         if (spl[i] != 0) {
02389             break;
02390         }
02391     }
02392 
02393     return PR_smprintf("%d%s", spl[i], marks[i]);
02394 }
02395 
02396 
02397 static void
02398 printPR_smpString(const char *sformat, char *reportStr,
02399                   const char *nformat, PRInt64 rNum)
02400 {
02401     if (reportStr) {
02402         fprintf(stdout, sformat, reportStr);
02403         PR_smprintf_free(reportStr);
02404     } else {
02405         int prnRes;
02406         LL_L2I(prnRes, rNum);
02407         fprintf(stdout, nformat, rNum);
02408     }
02409 }
02410 
02411 static char*
02412 getHighUnitOps(PRInt64 res)
02413 {
02414     int spl[] = {0, 0, 0, 0};
02415     int del[] = {1000, 1000, 1000, 1000};
02416     char *marks[] = {"", "T", "M", "B"};
02417     int i = 3;
02418 
02419     splitToReportUnit(res, spl, del, 4);
02420 
02421     for (;i>0;i--) {
02422         if (spl[i] != 0) {
02423             break;
02424         }
02425     }
02426 
02427     return PR_smprintf("%d%s", spl[i], marks[i]);
02428 }
02429 
02430 void
02431 dump_performance_info(bltestCipherInfo *infoList, double totalTimeInt,
02432                       PRBool encrypt, PRBool cxonly)
02433 {
02434     bltestCipherInfo *info = infoList;
02435     
02436     PRInt64 totalIn = 0;
02437     PRBool td = PR_TRUE;
02438 
02439     int   repetitions = 0;
02440     int   cxreps = 0;
02441     double cxtime = 0;
02442     double optime = 0;
02443     while (info != NULL) {
02444         repetitions += info->repetitions;
02445         cxreps += info->cxreps;
02446         cxtime += info->cxtime;
02447         optime += info->optime;
02448         totalIn += info->input.buf.len * info->repetitions;
02449         
02450         info = info->next;
02451     }
02452     info = infoList;
02453 
02454     fprintf(stdout, "#%9s", "mode");
02455     fprintf(stdout, "%12s", "in");
02456 print_td:
02457     switch (info->mode) {
02458       case bltestDES_ECB:
02459       case bltestDES_CBC:
02460       case bltestDES_EDE_ECB:
02461       case bltestDES_EDE_CBC:
02462       case bltestAES_ECB:
02463       case bltestAES_CBC:
02464       case bltestRC2_ECB:
02465       case bltestRC2_CBC:
02466       case bltestRC4:
02467           if (td)
02468               fprintf(stdout, "%8s", "symmkey");
02469           else
02470               fprintf(stdout, "%8d", 8*info->params.sk.key.buf.len);
02471           break;
02472 #if NSS_SOFTOKEN_DOES_RC5
02473       case bltestRC5_ECB:
02474       case bltestRC5_CBC:
02475           if (info->params.sk.key.buf.len > 0)
02476               printf("symmetric key(bytes)=%d,", info->params.sk.key.buf.len);
02477           if (info->rounds > 0)
02478               printf("rounds=%d,", info->params.rc5.rounds);
02479           if (info->wordsize > 0)
02480               printf("wordsize(bytes)=%d,", info->params.rc5.wordsize);
02481           break;
02482 #endif
02483       case bltestRSA:
02484           if (td) {
02485               fprintf(stdout, "%8s", "rsa_mod");
02486               fprintf(stdout, "%12s", "rsa_pe");
02487           } else {
02488               fprintf(stdout, "%8d", info->params.rsa.keysizeInBits);
02489               print_exponent(&info->params.rsa.rsakey->publicExponent);
02490           }
02491           break;
02492       case bltestDSA:
02493           if (td)
02494               fprintf(stdout, "%8s", "pqg_mod");
02495           else
02496               fprintf(stdout, "%8d", PQG_INDEX_TO_PBITS(info->params.dsa.j));
02497           break;
02498 #ifdef NSS_ENABLE_ECC
02499       case bltestECDSA:
02500           if (td)
02501               fprintf(stdout, "%12s", "ec_curve");
02502           else {
02503              ECCurveName curveName = info->params.ecdsa.eckey->ecParams.name;
02504               fprintf(stdout, "%12s",
02505                       ecCurve_map[curveName]? ecCurve_map[curveName]->text:
02506                                          "Unsupported curve");
02507          }
02508           break;
02509 #endif
02510       case bltestMD2:
02511       case bltestMD5:
02512       case bltestSHA1:
02513       case bltestSHA256:
02514       case bltestSHA384:
02515       case bltestSHA512:
02516       default:
02517           break;
02518     }
02519     if (!td) {
02520         PRInt64 totalThroughPut;
02521 
02522         printPR_smpString("%8s", getHighUnitOps(repetitions),
02523                           "%8d", repetitions);
02524 
02525         printPR_smpString("%8s", getHighUnitOps(cxreps), "%8d", cxreps);
02526 
02527         fprintf(stdout, "%12.3f", cxtime);
02528         fprintf(stdout, "%12.3f", optime);
02529         fprintf(stdout, "%12.03f", totalTimeInt / 1000);
02530 
02531         totalThroughPut = (PRInt64)(totalIn / totalTimeInt * 1000);
02532         printPR_smpString("%12s", getHighUnitBytes(totalThroughPut),
02533                           "%12d", totalThroughPut);
02534 
02535         fprintf(stdout, "\n");
02536         return;
02537     }
02538     
02539     fprintf(stdout, "%8s", "opreps");
02540     fprintf(stdout, "%8s", "cxreps");
02541     fprintf(stdout, "%12s", "context");
02542     fprintf(stdout, "%12s", "op");
02543     fprintf(stdout, "%12s", "time(sec)");
02544     fprintf(stdout, "%12s", "thrgput");
02545     fprintf(stdout, "\n");
02546     fprintf(stdout, "%8s", mode_strings[info->mode]);
02547     fprintf(stdout, "_%c", (cxonly) ? 'c' : (encrypt) ? 'e' : 'd');
02548     printPR_smpString("%12s", getHighUnitBytes(totalIn), "%12d", totalIn);
02549     
02550     td = !td;
02551     goto print_td;
02552 }
02553 
02554 void
02555 printmodes()
02556 {
02557     bltestCipherMode mode;
02558     int nummodes = sizeof(mode_strings) / sizeof(char *);
02559     fprintf(stderr, "%s: Available modes (specify with -m):\n", progName);
02560     for (mode=0; mode<nummodes; mode++)
02561        fprintf(stderr, "%s\n", mode_strings[mode]);
02562 }
02563 
02564 bltestCipherMode
02565 get_mode(const char *modestring)
02566 {
02567     bltestCipherMode mode;
02568     int nummodes = sizeof(mode_strings) / sizeof(char *);
02569     for (mode=0; mode<nummodes; mode++)
02570        if (PL_strcmp(modestring, mode_strings[mode]) == 0)
02571            return mode;
02572     fprintf(stderr, "%s: invalid mode: %s\n", progName, modestring);
02573     return bltestINVALID;
02574 }
02575 
02576 void
02577 load_file_data(PRArenaPool *arena, bltestIO *data,
02578               char *fn, bltestIOMode ioMode)
02579 {
02580     PRFileDesc *file;
02581     data->mode = ioMode;
02582     data->file = NULL; /* don't use -- not saving anything */
02583     data->pBuf.data = NULL;
02584     data->pBuf.len = 0;
02585     file = PR_Open(fn, PR_RDONLY, 00660);
02586     if (file)
02587        setupIO(arena, data, file, NULL, 0);
02588 }
02589 
02590 void
02591 get_params(PRArenaPool *arena, bltestParams *params, 
02592           bltestCipherMode mode, int j)
02593 {
02594     char filename[256];
02595     char *modestr = mode_strings[mode];
02596 #if NSS_SOFTOKEN_DOES_RC5
02597     FILE *file;
02598     char *mark, *param, *val;
02599     int index = 0;
02600 #endif
02601     switch (mode) {
02602     case bltestDES_CBC:
02603     case bltestDES_EDE_CBC:
02604     case bltestRC2_CBC:
02605     case bltestAES_CBC:
02606        sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "iv", j);
02607        load_file_data(arena, &params->sk.iv, filename, bltestBinary);
02608     case bltestDES_ECB:
02609     case bltestDES_EDE_ECB:
02610     case bltestRC2_ECB:
02611     case bltestRC4:
02612     case bltestAES_ECB:
02613        sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
02614        load_file_data(arena, &params->sk.key, filename, bltestBinary);
02615        break;
02616 #if NSS_SOFTOKEN_DOES_RC5
02617     case bltestRC5_ECB:
02618     case bltestRC5_CBC:
02619        sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "iv", j);
02620        load_file_data(arena, &params->sk.iv, filename, bltestBinary);
02621        sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
02622        load_file_data(arena, &params->sk.key, filename, bltestBinary);
02623            sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr,
02624                            "params", j);
02625        file = fopen(filename, "r");
02626        if (!file) return;
02627        param = malloc(100);
02628        len = fread(param, 1, 100, file);
02629        while (index < len) {
02630            mark = PL_strchr(param, '=');
02631            *mark = '\0';
02632            val = mark + 1;
02633            mark = PL_strchr(val, '\n');
02634            *mark = '\0';
02635            if (PL_strcmp(param, "rounds") == 0) {
02636               params->rc5.rounds = atoi(val);
02637            } else if (PL_strcmp(param, "wordsize") == 0) {
02638               params->rc5.wordsize = atoi(val);
02639            }
02640            index += PL_strlen(param) + PL_strlen(val) + 2;
02641            param = mark + 1;
02642        }
02643        break;
02644 #endif
02645     case bltestRSA:
02646        sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
02647        load_file_data(arena, &params->rsa.key, filename, bltestBase64Encoded);
02648        params->rsa.rsakey = rsakey_from_filedata(&params->key.buf);
02649        break;
02650     case bltestDSA:
02651        sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
02652        load_file_data(arena, &params->dsa.key, filename, bltestBase64Encoded);
02653        params->dsa.dsakey = dsakey_from_filedata(&params->key.buf);
02654        sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "pqg", j);
02655        load_file_data(arena, &params->dsa.pqgdata, filename,
02656                      bltestBase64Encoded);
02657        params->dsa.pqg = pqg_from_filedata(&params->dsa.pqgdata.buf);
02658        sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "keyseed", j);
02659        load_file_data(arena, &params->dsa.keyseed, filename, 
02660                       bltestBase64Encoded);
02661        sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "sigseed", j);
02662        load_file_data(arena, &params->dsa.sigseed, filename, 
02663                       bltestBase64Encoded);
02664        sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "ciphertext",j);
02665        load_file_data(arena, &params->dsa.sig, filename, bltestBase64Encoded);
02666        break;
02667 #ifdef NSS_ENABLE_ECC
02668     case bltestECDSA:
02669        sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
02670        load_file_data(arena, &params->ecdsa.key, filename, bltestBase64Encoded);
02671        params->ecdsa.eckey = eckey_from_filedata(&params->key.buf);
02672        sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "sigseed", j);
02673        load_file_data(arena, &params->ecdsa.sigseed, filename, 
02674                       bltestBase64Encoded);
02675        sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "ciphertext",j);
02676        load_file_data(arena, &params->ecdsa.sig, filename, bltestBase64Encoded);
02677        break;
02678 #endif
02679     case bltestMD2:
02680     case bltestMD5:
02681     case bltestSHA1:
02682     case bltestSHA256:
02683     case bltestSHA384:
02684     case bltestSHA512:
02685        /*params->hash.restart = PR_TRUE;*/
02686        params->hash.restart = PR_FALSE;
02687        break;
02688     default:
02689        break;
02690     }
02691 }
02692 
02693 SECStatus
02694 verify_self_test(bltestIO *result, bltestIO *cmp, bltestCipherMode mode,
02695                PRBool forward, SECStatus sigstatus)
02696 {
02697     int res;
02698     char *modestr = mode_strings[mode];
02699     res = SECITEM_CompareItem(&result->pBuf, &cmp->buf);
02700     if (is_sigCipher(mode)) {
02701        if (forward) {
02702            if (res == 0) {
02703               printf("Signature self-test for %s passed.\n", modestr);
02704            } else {
02705               printf("Signature self-test for %s failed!\n", modestr);
02706            }
02707        } else {
02708            if (sigstatus == SECSuccess) {
02709               printf("Verification self-test for %s passed.\n", modestr);
02710            } else {
02711               printf("Verification self-test for %s failed!\n", modestr);
02712            }
02713        }
02714        return sigstatus;
02715     } else if (is_hashCipher(mode)) {
02716        if (res == 0) {
02717            printf("Hash self-test for %s passed.\n", modestr);
02718        } else {
02719            printf("Hash self-test for %s failed!\n", modestr);
02720        }
02721     } else {
02722        if (forward) {
02723            if (res == 0) {
02724               printf("Encryption self-test for %s passed.\n", modestr);
02725            } else {
02726               printf("Encryption self-test for %s failed!\n", modestr);
02727            }
02728        } else {
02729            if (res == 0) {
02730               printf("Decryption self-test for %s passed.\n", modestr);
02731            } else {
02732               printf("Decryption self-test for %s failed!\n", modestr);
02733            }
02734        }
02735     }
02736     return (res != 0);
02737 }
02738 
02739 static SECStatus
02740 blapi_selftest(bltestCipherMode *modes, int numModes, int inoff, int outoff,
02741                PRBool encrypt, PRBool decrypt)
02742 {
02743     bltestCipherInfo cipherInfo;
02744     bltestIO pt, ct;
02745     bltestCipherMode mode;
02746     bltestParams *params;
02747     int i, j, nummodes, numtests;
02748     char *modestr;
02749     char filename[256];
02750     PRFileDesc *file;
02751     PRArenaPool *arena;
02752     SECItem item;
02753     PRBool finished;
02754     SECStatus rv = SECSuccess, srv;
02755 
02756     PORT_Memset(&cipherInfo, 0, sizeof(cipherInfo));
02757     arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
02758     cipherInfo.arena = arena;
02759 
02760     finished = PR_FALSE;
02761     nummodes = (numModes == 0) ? NUMMODES : numModes;
02762     for (i=0; i < nummodes && !finished; i++) {
02763        if (i == bltestRC5_ECB || i == bltestRC5_CBC) continue;
02764        if (numModes > 0)
02765            mode = modes[i];
02766        else
02767            mode = i;
02768        if (mode == bltestINVALID) {
02769            fprintf(stderr, "%s: Skipping invalid mode.\n",progName);
02770            continue;
02771        }
02772        modestr = mode_strings[mode];
02773        cipherInfo.mode = mode;
02774        params = &cipherInfo.params;
02775 #ifdef TRACK_BLTEST_BUG
02776        if (mode == bltestRSA) {
02777            fprintf(stderr, "[%s] Self-Testing RSA\n", __bltDBG);
02778        }
02779 #endif
02780        /* get the number of tests in the directory */
02781        sprintf(filename, "%s/tests/%s/%s", testdir, modestr, "numtests");
02782        file = PR_Open(filename, PR_RDONLY, 00660);
02783        if (!file) {
02784            fprintf(stderr, "%s: File %s does not exist.\n", progName,filename);
02785            return SECFailure;
02786        }
02787        rv = SECU_FileToItem(&item, file);
02788 #ifdef TRACK_BLTEST_BUG
02789        if (mode == bltestRSA) {
02790            fprintf(stderr, "[%s] Loaded data from %s\n", __bltDBG, filename);
02791        }
02792 #endif
02793        PR_Close(file);
02794        /* loop over the tests in the directory */
02795        numtests = 0;
02796        for (j=0; j<item.len; j++) {
02797            if (!isdigit(item.data[j])) {
02798               break;
02799            }
02800            numtests *= 10;
02801            numtests += (int) (item.data[j] - '0');
02802        }
02803        for (j=0; j<numtests; j++) {
02804 #ifdef TRACK_BLTEST_BUG
02805            if (mode == bltestRSA) {
02806               fprintf(stderr, "[%s] Executing self-test #%d\n", __bltDBG, j);
02807            }
02808 #endif
02809            sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr,
02810                            "plaintext", j);
02811            load_file_data(arena, &pt, filename, 
02812 #ifdef NSS_ENABLE_ECC
02813                           ((mode == bltestDSA) || (mode == bltestECDSA))
02814 #else
02815                           (mode == bltestDSA)
02816 #endif
02817                           ? bltestBase64Encoded : bltestBinary);
02818            sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr,
02819                            "ciphertext", j);
02820            load_file_data(arena, &ct, filename, bltestBase64Encoded);
02821 #ifdef TRACK_BLTEST_BUG
02822            if (mode == bltestRSA) {
02823               fprintf(stderr, "[%s] Loaded data for  self-test #%d\n", __bltDBG, j);
02824            }
02825 #endif
02826            get_params(arena, params, mode, j);
02827 #ifdef TRACK_BLTEST_BUG
02828            if (mode == bltestRSA) {
02829               fprintf(stderr, "[%s] Got parameters for #%d\n", __bltDBG, j);
02830            }
02831 #endif
02832            /* Forward Operation (Encrypt/Sign/Hash)
02833            ** Align the input buffer (plaintext) according to request
02834            ** then perform operation and compare to ciphertext
02835            */
02836            /* XXX for now */
02837            rv = SECSuccess;
02838            if (encrypt) {
02839               bltestCopyIO(arena, &cipherInfo.input, &pt);
02840               misalignBuffer(arena, &cipherInfo.input, inoff);
02841               memset(&cipherInfo.output.buf, 0, sizeof cipherInfo.output.buf);
02842               rv |= cipherInit(&cipherInfo, PR_TRUE);
02843               misalignBuffer(arena, &cipherInfo.output, outoff);
02844 #ifdef TRACK_BLTEST_BUG
02845               if (mode == bltestRSA) {
02846                   fprintf(stderr, "[%s] Inited cipher context and buffers for #%d\n", __bltDBG, j);
02847               }
02848 #endif
02849               rv |= cipherDoOp(&cipherInfo);
02850 #ifdef TRACK_BLTEST_BUG
02851               if (mode == bltestRSA) {
02852                   fprintf(stderr, "[%s] Performed encrypt for #%d\n", __bltDBG, j);
02853               }
02854 #endif
02855               rv |= cipherFinish(&cipherInfo);
02856 #ifdef TRACK_BLTEST_BUG
02857               if (mode == bltestRSA) {
02858                   fprintf(stderr, "[%s] Finished encrypt for #%d\n", __bltDBG, j);
02859               }
02860 #endif
02861               rv |= verify_self_test(&cipherInfo.output, 
02862                                      &ct, mode, PR_TRUE, 0);
02863 #ifdef TRACK_BLTEST_BUG
02864               if (mode == bltestRSA) {
02865                   fprintf(stderr, "[%s] Verified self-test for #%d\n", __bltDBG, j);
02866               }
02867 #endif
02868               /* If testing hash, only one op to test */
02869               if (is_hashCipher(mode))
02870                   continue;
02871               /*if (rv) return rv;*/
02872            }
02873            if (!decrypt)
02874               continue;
02875            /* XXX for now */
02876            rv = SECSuccess;
02877            /* Reverse Operation (Decrypt/Verify)
02878            ** Align the input buffer (ciphertext) according to request
02879            ** then perform operation and compare to plaintext
02880            */
02881 #ifdef NSS_ENABLE_ECC
02882            if ((mode != bltestDSA) && (mode != bltestECDSA))
02883 #else
02884            if (mode != bltestDSA)
02885 #endif
02886               bltestCopyIO(arena, &cipherInfo.input, &ct);
02887            else
02888               bltestCopyIO(arena, &cipherInfo.input, &pt);
02889            misalignBuffer(arena, &cipherInfo.input, inoff);
02890            memset(&cipherInfo.output.buf, 0, sizeof cipherInfo.output.buf);
02891            rv |= cipherInit(&cipherInfo, PR_FALSE);
02892            misalignBuffer(arena, &cipherInfo.output, outoff);
02893 #ifdef TRACK_BLTEST_BUG
02894            if (mode == bltestRSA) {
02895               fprintf(stderr, "[%s] Inited cipher context and buffers for #%d\n", __bltDBG, j);
02896            }
02897 #endif
02898            srv = SECSuccess;
02899            srv |= cipherDoOp(&cipherInfo);
02900 #ifdef TRACK_BLTEST_BUG
02901            if (mode == bltestRSA) {
02902               fprintf(stderr, "[%s] Performed decrypt for #%d\n", __bltDBG, j);
02903            }
02904 #endif
02905            rv |= cipherFinish(&cipherInfo);
02906 #ifdef TRACK_BLTEST_BUG
02907            if (mode == bltestRSA) {
02908               fprintf(stderr, "[%s] Finished decrypt for #%d\n", __bltDBG, j);
02909            }
02910 #endif
02911            rv |= verify_self_test(&cipherInfo.output, 
02912                                   &pt, mode, PR_FALSE, srv);
02913 #ifdef TRACK_BLTEST_BUG
02914            if (mode == bltestRSA) {
02915               fprintf(stderr, "[%s] Verified self-test for #%d\n", __bltDBG, j);
02916            }
02917 #endif
02918            /*if (rv) return rv;*/
02919        }
02920     }
02921     return rv;
02922 }
02923 
02924 SECStatus
02925 dump_file(bltestCipherMode mode, char *filename)
02926 {
02927     bltestIO keydata;
02928     PRArenaPool *arena = NULL;
02929     arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
02930     if (mode == bltestRSA) {
02931        RSAPrivateKey *key;
02932        load_file_data(arena, &keydata, filename, bltestBase64Encoded);
02933        key = rsakey_from_filedata(&keydata.buf);
02934        dump_rsakey(key);
02935     } else if (mode == bltestDSA) {
02936 #if 0
02937        PQGParams *pqg;
02938        get_file_data(filename, &item, PR_TRUE);
02939        pqg = pqg_from_filedata(&item);
02940        dump_pqg(pqg);
02941 #endif
02942        DSAPrivateKey *key;
02943        load_file_data(arena, &keydata, filename, bltestBase64Encoded);
02944        key = dsakey_from_filedata(&keydata.buf);
02945        dump_dsakey(key);
02946 #ifdef NSS_ENABLE_ECC
02947     } else if (mode == bltestECDSA) {
02948        ECPrivateKey *key;
02949        load_file_data(arena, &keydata, filename, bltestBase64Encoded);
02950        key = eckey_from_filedata(&keydata.buf);
02951        dump_eckey(key);
02952 #endif
02953     }
02954     PORT_FreeArena(arena, PR_FALSE);
02955     return SECFailure;
02956 }
02957 
02958 void ThreadExecTest(void *data)
02959 {
02960     bltestCipherInfo *cipherInfo = (bltestCipherInfo*)data;
02961 
02962     if (cipherInfo->mCarlo == PR_TRUE) {
02963         int mciter;
02964         for (mciter=0; mciter<10000; mciter++) {
02965             cipherDoOp(cipherInfo);
02966             memcpy(cipherInfo->input.buf.data,
02967                    cipherInfo->output.buf.data,
02968                    cipherInfo->input.buf.len);
02969         }
02970     } else {
02971         cipherDoOp(cipherInfo);
02972     }
02973     cipherFinish(cipherInfo);
02974 }
02975 
02976 /* bltest commands */
02977 enum {
02978     cmd_Decrypt = 0,
02979     cmd_Encrypt,
02980     cmd_FIPS,
02981     cmd_Hash,
02982     cmd_Nonce,
02983     cmd_Dump,
02984     cmd_Sign,
02985     cmd_SelfTest,
02986     cmd_Verify
02987 };
02988 
02989 /* bltest options */
02990 enum {
02991     opt_B64 = 0,
02992     opt_BufSize,
02993     opt_Restart,
02994     opt_SelfTestDir,
02995     opt_Exponent,
02996     opt_SigFile,
02997     opt_KeySize,
02998     opt_Hex,
02999     opt_Input,
03000     opt_PQGFile,
03001     opt_Key,
03002     opt_HexWSpc,
03003     opt_Mode,
03004 #ifdef NSS_ENABLE_ECC
03005     opt_CurveName,
03006 #endif
03007     opt_Output,
03008     opt_Repetitions,
03009     opt_ZeroBuf,
03010     opt_Rounds,
03011     opt_Seed,
03012     opt_SigSeedFile,
03013     opt_CXReps,
03014     opt_IV,
03015     opt_WordSize,
03016     opt_UseSeed,
03017     opt_UseSigSeed,
03018     opt_SeedFile,
03019     opt_InputOffset,
03020     opt_OutputOffset,
03021     opt_MonteCarlo,
03022     opt_ThreadNum,
03023     opt_SecondsToRun,
03024     opt_CmdLine
03025 };
03026 
03027 static secuCommandFlag bltest_commands[] =
03028 {
03029     { /* cmd_Decrypt */ 'D', PR_FALSE, 0, PR_FALSE },
03030     { /* cmd_Encrypt */ 'E', PR_FALSE, 0, PR_FALSE },
03031     { /* cmd_FIPS    */ 'F', PR_FALSE, 0, PR_FALSE },
03032     { /* cmd_Hash    */ 'H', PR_FALSE, 0, PR_FALSE },
03033     { /* cmd_Nonce      */ 'N', PR_FALSE, 0, PR_FALSE },
03034     { /* cmd_Dump    */ 'P', PR_FALSE, 0, PR_FALSE },
03035     { /* cmd_Sign    */ 'S', PR_FALSE, 0, PR_FALSE },
03036     { /* cmd_SelfTest       */ 'T', PR_FALSE, 0, PR_FALSE },
03037     { /* cmd_Verify  */ 'V', PR_FALSE, 0, PR_FALSE }
03038 };
03039 
03040 static secuCommandFlag bltest_options[] =
03041 {
03042     { /* opt_B64       */ 'a', PR_FALSE, 0, PR_FALSE },
03043     { /* opt_BufSize   */ 'b', PR_TRUE,  0, PR_FALSE },
03044     { /* opt_Restart   */ 'c', PR_FALSE, 0, PR_FALSE },
03045     { /* opt_SelfTestDir  */ 'd', PR_TRUE,  0, PR_FALSE },
03046     { /* opt_Exponent         */ 'e', PR_TRUE,  0, PR_FALSE },
03047     { /* opt_SigFile      */ 'f', PR_TRUE,  0, PR_FALSE },
03048     { /* opt_KeySize   */ 'g', PR_TRUE,  0, PR_FALSE },
03049     { /* opt_Hex       */ 'h', PR_FALSE, 0, PR_FALSE },
03050     { /* opt_Input     */ 'i', PR_TRUE,  0, PR_FALSE },
03051     { /* opt_PQGFile   */ 'j', PR_TRUE,  0, PR_FALSE },
03052     { /* opt_Key       */ 'k', PR_TRUE,  0, PR_FALSE },
03053     { /* opt_HexWSpc   */ 'l', PR_FALSE, 0, PR_FALSE },
03054     { /* opt_Mode      */ 'm', PR_TRUE,  0, PR_FALSE },
03055 #ifdef NSS_ENABLE_ECC
03056     { /* opt_CurveName        */ 'n', PR_TRUE,  0, PR_FALSE },
03057 #endif
03058     { /* opt_Output    */ 'o', PR_TRUE,  0, PR_FALSE },
03059     { /* opt_Repetitions  */ 'p', PR_TRUE,  0, PR_FALSE },
03060     { /* opt_ZeroBuf   */ 'q', PR_FALSE, 0, PR_FALSE },
03061     { /* opt_Rounds    */ 'r', PR_TRUE,  0, PR_FALSE },
03062     { /* opt_Seed      */ 's', PR_TRUE,  0, PR_FALSE },
03063     { /* opt_SigSeedFile  */ 't', PR_TRUE,  0, PR_FALSE },
03064     { /* opt_CXReps       */ 'u', PR_TRUE,  0, PR_FALSE },
03065     { /* opt_IV               */ 'v', PR_TRUE,  0, PR_FALSE },
03066     { /* opt_WordSize         */ 'w', PR_TRUE,  0, PR_FALSE },
03067     { /* opt_UseSeed   */ 'x', PR_FALSE, 0, PR_FALSE },
03068     { /* opt_UseSigSeed       */ 'y', PR_FALSE, 0, PR_FALSE },
03069     { /* opt_SeedFile         */ 'z', PR_FALSE, 0, PR_FALSE },
03070     { /* opt_InputOffset  */ '1', PR_TRUE,  0, PR_FALSE },
03071     { /* opt_OutputOffset */ '2', PR_TRUE,  0, PR_FALSE },
03072     { /* opt_MonteCarlo   */ '3', PR_FALSE, 0, PR_FALSE },
03073     { /* opt_ThreadNum    */ '4', PR_TRUE,  0, PR_FALSE },
03074     { /* opt_SecondsToRun */ '5', PR_TRUE,  0, PR_FALSE },
03075     { /* opt_CmdLine   */ '-', PR_FALSE, 0, PR_FALSE }
03076 };
03077 
03078 int main(int argc, char **argv)
03079 {
03080     char *infileName, *outfileName, *keyfileName, *ivfileName;
03081     SECStatus rv = SECFailure;
03082 
03083     double              totalTime;
03084     PRIntervalTime      time1, time2;
03085     PRFileDesc          *outfile;           
03086     bltestCipherInfo    *cipherInfoListHead, *cipherInfo;
03087     bltestIOMode        ioMode;
03088     int                 bufsize, exponent, curThrdNum;
03089 #ifdef NSS_ENABLE_ECC
03090     char             *curveName = NULL;
03091 #endif
03092     int                      i, commandsEntered;
03093     int                      inoff, outoff;
03094     int                  threads = 1;
03095 
03096     secuCommand bltest;
03097     bltest.numCommands = sizeof(bltest_commands) / sizeof(secuCommandFlag);
03098     bltest.numOptions = sizeof(bltest_options) / sizeof(secuCommandFlag);
03099     bltest.commands = bltest_commands;
03100     bltest.options = bltest_options;
03101 
03102     progName = strrchr(argv[0], '/');
03103     if (!progName) 
03104        progName = strrchr(argv[0], '\\');
03105     progName = progName ? progName+1 : argv[0];
03106 
03107     rv = RNG_RNGInit();
03108     if (rv != SECSuccess) {
03109        SECU_PrintPRandOSError(progName);
03110        return -1;
03111     }
03112     RNG_SystemInfoForRNG();
03113 
03114     rv = SECU_ParseCommandLine(argc, argv, progName, &bltest);
03115     if (rv == SECFailure) {
03116         fprintf(stderr, "%s: command line parsing error!\n", progName);
03117         goto print_usage;
03118     }
03119     rv = SECFailure;
03120 
03121     cipherInfo = PORT_ZNew(bltestCipherInfo);
03122     cipherInfoListHead = cipherInfo;
03123     /* set some defaults */
03124     infileName = outfileName = keyfileName = ivfileName = NULL;
03125 
03126     /* Check the number of commands entered on the command line. */
03127     commandsEntered = 0;
03128     for (i=0; i<bltest.numCommands; i++)
03129        if (bltest.commands[i].activated)
03130            commandsEntered++;
03131 
03132     if (commandsEntered > 1 &&
03133        !(commandsEntered == 2 && bltest.commands[cmd_SelfTest].activated)) {
03134        fprintf(stderr, "%s: one command at a time!\n", progName);
03135         goto print_usage;
03136     }
03137 
03138     if (commandsEntered == 0) {
03139        fprintf(stderr, "%s: you must enter a command!\n", progName);
03140         goto print_usage;
03141     }
03142 
03143     if (bltest.commands[cmd_Sign].activated)
03144        bltest.commands[cmd_Encrypt].activated = PR_TRUE;
03145     if (bltest.commands[cmd_Verify].activated)
03146        bltest.commands[cmd_Decrypt].activated = PR_TRUE;
03147     if (bltest.commands[cmd_Hash].activated)
03148        bltest.commands[cmd_Encrypt].activated = PR_TRUE;
03149 
03150     inoff = outoff = 0;
03151     if (bltest.options[opt_InputOffset].activated)
03152        inoff = PORT_Atoi(bltest.options[opt_InputOffset].arg);
03153     if (bltest.options[opt_OutputOffset].activated)
03154        outoff = PORT_Atoi(bltest.options[opt_OutputOffset].arg);
03155 
03156     testdir = (bltest.options[opt_SelfTestDir].activated) ? 
03157                  strdup(bltest.options[opt_SelfTestDir].arg) : ".";
03158 
03159     /*
03160      * Handle three simple cases first
03161      */
03162 
03163     /* Do BLAPI self-test */
03164     if (bltest.commands[cmd_SelfTest].activated) {
03165        PRBool encrypt = PR_TRUE, decrypt = PR_TRUE;
03166        /* user may specified a set of ciphers to test.  parse them. */
03167        bltestCipherMode modesToTest[NUMMODES];
03168        int numModesToTest = 0;
03169        char *tok, *str;
03170        str = bltest.options[opt_Mode].arg;
03171        while (str) {
03172            tok = strchr(str, ',');
03173            if (tok) *tok = '\0';
03174            modesToTest[numModesToTest++] = get_mode(str);
03175            if (tok) {
03176               *tok = ',';
03177               str = tok + 1;
03178            } else {
03179               break;
03180            }
03181        }
03182        if (bltest.commands[cmd_Decrypt].activated &&
03183            !bltest.commands[cmd_Encrypt].activated)
03184            encrypt = PR_FALSE;
03185        if (bltest.commands[cmd_Encrypt].activated &&
03186            !bltest.commands[cmd_Decrypt].activated)
03187            decrypt = PR_FALSE;
03188        rv = blapi_selftest(modesToTest, numModesToTest, inoff, outoff,
03189                             encrypt, decrypt);
03190         PORT_Free(cipherInfo);
03191         return rv;
03192     }
03193 
03194     /* Do FIPS self-test */
03195     if (bltest.commands[cmd_FIPS].activated) {
03196        CK_RV ckrv = sftk_fipsPowerUpSelfTest();
03197        fprintf(stdout, "CK_RV: %ld.\n", ckrv);
03198         PORT_Free(cipherInfo);
03199         if (ckrv == CKR_OK)
03200             return SECSuccess;
03201         return SECFailure;
03202     }
03203 
03204     /*
03205      * Check command line arguments for Encrypt/Decrypt/Hash/Sign/Verify
03206      */
03207 
03208     if ((bltest.commands[cmd_Decrypt].activated ||
03209         bltest.commands[cmd_Verify].activated) &&
03210        bltest.options[opt_BufSize].activated) {
03211        fprintf(stderr, "%s: Cannot use a nonce as input to decrypt/verify.\n",
03212                       progName);
03213         goto print_usage;
03214     }
03215 
03216     if (bltest.options[opt_Mode].activated) {
03217        cipherInfo->mode = get_mode(bltest.options[opt_Mode].arg);
03218        if (cipherInfo->mode == bltestINVALID) {
03219             goto print_usage;
03220        }
03221     } else {
03222        fprintf(stderr, "%s: You must specify a cipher mode with -m.\n",
03223                       progName);
03224         goto print_usage;
03225     }
03226 
03227     
03228     if (bltest.options[opt_Repetitions].activated &&
03229         bltest.options[opt_SecondsToRun].activated) {
03230         fprintf(stderr, "%s: Operation time should be defined in either "
03231                 "repetitions(-p) or seconds(-5) not both",
03232                 progName);
03233         goto print_usage;
03234     }
03235 
03236     if (bltest.options[opt_Repetitions].activated) {
03237         cipherInfo->repetitionsToPerfom =
03238             PORT_Atoi(bltest.options[opt_Repetitions].arg);
03239     } else {
03240         cipherInfo->repetitionsToPerfom = 0;
03241     }
03242 
03243     if (bltest.options[opt_SecondsToRun].activated) {
03244         cipherInfo->seconds = PORT_Atoi(bltest.options[opt_SecondsToRun].arg);
03245     } else {
03246         cipherInfo->seconds = 0;
03247     }
03248 
03249 
03250     if (bltest.options[opt_CXReps].activated) {
03251         cipherInfo->cxreps = PORT_Atoi(bltest.options[opt_CXReps].arg);
03252     } else {
03253         cipherInfo->cxreps = 0;
03254     }
03255 
03256     if (bltest.options[opt_ThreadNum].activated) {
03257         threads = PORT_Atoi(bltest.options[opt_ThreadNum].arg);
03258         if (threads <= 0) {
03259             threads = 1;
03260         }
03261     }
03262 
03263     /* Dump a file (rsakey, dsakey, etc.) */
03264     if (bltest.commands[cmd_Dump].activated) {
03265         rv = dump_file(cipherInfo->mode, bltest.options[opt_Input].arg);
03266         PORT_Free(cipherInfo);
03267         return rv;
03268     }
03269 
03270     /* default input mode is binary */
03271     ioMode = (bltest.options[opt_B64].activated)     ? bltestBase64Encoded :
03272             (bltest.options[opt_Hex].activated)     ? bltestHexStream :
03273             (bltest.options[opt_HexWSpc].activated) ? bltestHexSpaceDelim :
03274                                                  bltestBinary;
03275 
03276     if (bltest.options[opt_Exponent].activated)
03277        exponent = PORT_Atoi(bltest.options[opt_Exponent].arg);
03278     else
03279        exponent = 65537;
03280 
03281 #ifdef NSS_ENABLE_ECC
03282     if (bltest.options[opt_CurveName].activated)
03283        curveName = PORT_Strdup(bltest.options[opt_CurveName].arg);
03284     else
03285        curveName = NULL;
03286 #endif
03287 
03288     if (bltest.commands[cmd_Verify].activated &&
03289         !bltest.options[opt_SigFile].activated) {
03290         fprintf(stderr, "%s: You must specify a signature file with -f.\n",
03291                 progName);
03292 
03293       print_usage:
03294         PORT_Free(cipherInfo);
03295         Usage();
03296     }
03297 
03298     if (bltest.options[opt_MonteCarlo].activated) {
03299         cipherInfo->mCarlo = PR_TRUE;
03300     } else {
03301         cipherInfo->mCarlo = PR_FALSE;
03302     }
03303 
03304     for (curThrdNum = 0;curThrdNum < threads;curThrdNum++) {
03305         int            keysize = 0;
03306         PRFileDesc     *file = NULL, *infile;
03307         bltestParams   *params;
03308         char           *instr = NULL;
03309         PRArenaPool    *arena;
03310 
03311         if (curThrdNum > 0) {
03312             bltestCipherInfo *newCInfo = PORT_ZNew(bltestCipherInfo);
03313             if (!newCInfo) {
03314                 fprintf(stderr, "%s: Can not allocate  memory.\n", progName);
03315                 goto exit_point;
03316             }
03317             newCInfo->mode = cipherInfo->mode;
03318             newCInfo->mCarlo = cipherInfo->mCarlo;
03319             newCInfo->repetitionsToPerfom =
03320                 cipherInfo->repetitionsToPerfom;
03321             newCInfo->seconds = cipherInfo->seconds;
03322             newCInfo->cxreps = cipherInfo->cxreps;
03323             cipherInfo->next = newCInfo;
03324             cipherInfo = newCInfo;
03325         }
03326         arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
03327         if (!arena) {
03328             fprintf(stderr, "%s: Can not allocate memory.\n", progName);
03329             goto exit_point;
03330         }
03331         cipherInfo->arena = arena;
03332         params = &cipherInfo->params;
03333         
03334         /* Set up an encryption key. */
03335         keysize = 0;
03336         file = NULL;
03337         if (is_symmkeyCipher(cipherInfo->mode)) {
03338             char *keystr = NULL;  /* if key is on command line */
03339             if (bltest.options[opt_Key].activated) {
03340                 if (bltest.options[opt_CmdLine].activated) {
03341                     keystr = bltest.options[opt_Key].arg;
03342                 } else {
03343                     file = PR_Open(bltest.options[opt_Key].arg,
03344                                    PR_RDONLY, 00660);
03345                 }
03346             } else {
03347                 if (bltest.options[opt_KeySize].activated)
03348                     keysize = PORT_Atoi(bltest.options[opt_KeySize].arg);
03349                 else
03350                     keysize = 8; /* use 64-bit default (DES) */
03351                 /* save the random key for reference */
03352                 file = PR_Open("tmp.key", PR_WRONLY|PR_CREATE_FILE, 00660);
03353             }
03354             params->key.mode = ioMode;
03355             setupIO(cipherInfo->arena, &params->key, file, keystr, keysize);
03356             if (file)
03357                 PR_Close(file);
03358         } else if (is_pubkeyCipher(cipherInfo->mode)) {
03359             if (bltest.options[opt_Key].activated) {
03360                 file = PR_Open(bltest.options[opt_Key].arg, PR_RDONLY, 00660);
03361             } else {
03362                 if (bltest.options[opt_KeySize].activated)
03363                     keysize = PORT_Atoi(bltest.options[opt_KeySize].arg);
03364                 else
03365                     keysize = 64; /* use 512-bit default */
03366                 file = PR_Open("tmp.key", PR_WRONLY|PR_CREATE_FILE, 00660);
03367             }
03368             params->key.mode = bltestBase64Encoded;
03369 #ifdef NSS_ENABLE_ECC
03370             pubkeyInitKey(cipherInfo, file, keysize, exponent, curveName);
03371 #else
03372             pubkeyInitKey(cipherInfo, file, keysize, exponent);
03373 #endif
03374             PR_Close(file);
03375         }
03376 
03377         /* set up an initialization vector. */
03378         if (cipher_requires_IV(cipherInfo->mode)) {
03379             char *ivstr = NULL;
03380             bltestSymmKeyParams *skp;
03381             file = NULL;
03382             if (cipherInfo->mode == bltestRC5_CBC)
03383                 skp = (bltestSymmKeyParams *)&params->rc5;
03384             else
03385                 skp = &params->sk;
03386             if (bltest.options[opt_IV].activated) {
03387                 if (bltest.options[opt_CmdLine].activated) {
03388                     ivstr = bltest.options[opt_IV].arg;
03389                 } else {
03390                     file = PR_Open(bltest.options[opt_IV].arg,
03391                                    PR_RDONLY, 00660);
03392                 }
03393             } else {
03394                 /* save the random iv for reference */
03395                 file = PR_Open("tmp.iv", PR_WRONLY|PR_CREATE_FILE, 00660);
03396             }
03397             memset(&skp->iv, 0, sizeof skp->iv);
03398             skp->iv.mode = ioMode;
03399             setupIO(cipherInfo->arena, &skp->iv, file, ivstr, keysize);
03400             if (file) {
03401                 PR_Close(file);
03402             }
03403         }
03404         
03405         if (bltest.commands[cmd_Verify].activated) {
03406             file = PR_Open(bltest.options[opt_SigFile].arg, PR_RDONLY, 00660);
03407             if (cipherInfo->mode == bltestDSA) {
03408                 memset(&cipherInfo->params.dsa.sig, 0, sizeof(bltestIO));
03409                 cipherInfo->params.dsa.sig.mode = ioMode;
03410                 setupIO(cipherInfo->arena, &cipherInfo->params.dsa.sig,
03411                         file, NULL, 0);
03412 #ifdef NSS_ENABLE_ECC
03413             } else if (cipherInfo->mode == bltestECDSA) {
03414                 memset(&cipherInfo->params.ecdsa.sig, 0, sizeof(bltestIO));
03415                 cipherInfo->params.ecdsa.sig.mode = ioMode;
03416                 setupIO(cipherInfo->arena, &cipherInfo->params.ecdsa.sig,
03417                         file, NULL, 0);
03418 #endif
03419             }
03420             if (file) {
03421                 PR_Close(file);
03422             }
03423         }
03424         
03425         if (bltest.options[opt_PQGFile].activated) {
03426             file = PR_Open(bltest.options[opt_PQGFile].arg, PR_RDONLY, 00660);
03427             params->dsa.pqgdata.mode = bltestBase64Encoded;
03428             setupIO(cipherInfo->arena, &params->dsa.pqgdata, file, NULL, 0);
03429             if (file) {
03430                 PR_Close(file);
03431             }
03432         }
03433 
03434         /* Set up the input buffer */
03435         if (bltest.options[opt_Input].activated) {
03436             if (bltest.options[opt_CmdLine].activated) {
03437                 instr = bltest.options[opt_Input].arg;
03438                 infile = NULL;
03439             } else {
03440                 /* form file name from testdir and input arg. */
03441                 char * filename = bltest.options[opt_Input].arg;
03442                 if (bltest.options[opt_SelfTestDir].activated && 
03443                     testdir && filename && filename[0] != '/') {
03444                     filename = PR_smprintf("%s/tests/%s/%s", testdir, 
03445                                            mode_strings[cipherInfo->mode],
03446                                            filename);
03447                     if (!filename) {
03448                         fprintf(stderr, "%s: Can not allocate memory.\n",
03449                                 progName);
03450                         goto exit_point;
03451                     }
03452                     infile = PR_Open(filename, PR_RDONLY, 00660);
03453                     PR_smprintf_free(filename);
03454                 } else {
03455                     infile = PR_Open(filename, PR_RDONLY, 00660);
03456                 }
03457             }
03458         } else if (bltest.options[opt_BufSize].activated) {
03459             /* save the random plaintext for reference */
03460             char *tmpFName = PR_smprintf("tmp.in.%d", curThrdNum);
03461             if (!tmpFName) {
03462                 fprintf(stderr, "%s: Can not allocate memory.\n", progName);
03463                 goto exit_point;
03464             }
03465             infile = PR_Open(tmpFName, PR_WRONLY|PR_CREATE_FILE, 00660);
03466             PR_smprintf_free(tmpFName);
03467         } else {
03468             infile = PR_STDIN;
03469         }
03470         if (!infile) {
03471             fprintf(stderr, "%s: Failed to open input file.\n", progName);
03472             goto exit_point;
03473         }
03474         cipherInfo->input.mode = ioMode;
03475 
03476         /* Set up the output stream */
03477         if (bltest.options[opt_Output].activated) {
03478             /* form file name from testdir and input arg. */
03479             char * filename = bltest.options[opt_Output].arg;
03480             if (bltest.options[opt_SelfTestDir].activated && 
03481                 testdir && filename && filename[0] != '/') {
03482                 filename = PR_smprintf("%s/tests/%s/%s", testdir, 
03483                                        mode_strings[cipherInfo->mode],
03484                                        filename);
03485                 if (!filename) {
03486                     fprintf(stderr, "%s: Can not allocate memory.\n", progName);
03487                     goto exit_point;
03488                 }
03489                 outfile = PR_Open(filename, PR_WRONLY|PR_CREATE_FILE, 00660);
03490                 PR_smprintf_free(filename);
03491             } else {
03492                 outfile = PR_Open(filename, PR_WRONLY|PR_CREATE_FILE, 00660);
03493             }
03494         } else {
03495             outfile = PR_STDOUT;
03496         }
03497         if (!outfile) {
03498             fprintf(stderr, "%s: Failed to open output file.\n", progName);
03499             rv = SECFailure;
03500             goto exit_point;
03501         }
03502         cipherInfo->output.mode = ioMode;
03503         if (bltest.options[opt_SelfTestDir].activated && ioMode == bltestBinary)
03504             cipherInfo->output.mode = bltestBase64Encoded;
03505 
03506         if (is_hashCipher(cipherInfo->mode))
03507             cipherInfo->params.hash.restart =
03508                 bltest.options[opt_Restart].activated;
03509 
03510         bufsize = 0;
03511         if (bltest.options[opt_BufSize].activated)
03512             bufsize = PORT_Atoi(bltest.options[opt_BufSize].arg);
03513 
03514         /*infile = NULL;*/
03515         setupIO(cipherInfo->arena, &cipherInfo->input, infile, instr, bufsize);
03516         if (infile && infile != PR_STDIN)
03517             PR_Close(infile);
03518         misalignBuffer(cipherInfo->arena, &cipherInfo->input, inoff);
03519 
03520         cipherInit(cipherInfo, bltest.commands[cmd_Encrypt].activated);
03521         misalignBuffer(cipherInfo->arena, &cipherInfo->output, outoff);
03522     }
03523 
03524     if (!bltest.commands[cmd_Nonce].activated) {
03525         TIMESTART();
03526         cipherInfo = cipherInfoListHead;
03527         while (cipherInfo != NULL) {
03528             cipherInfo->cipherThread = 
03529                 PR_CreateThread(PR_USER_THREAD,
03530                                     ThreadExecTest,
03531                                     cipherInfo,
03532                                     PR_PRIORITY_NORMAL,
03533                                     PR_GLOBAL_THREAD,
03534                                     PR_JOINABLE_THREAD,
03535                                     0);
03536             cipherInfo = cipherInfo->next;
03537         } 
03538 
03539         cipherInfo = cipherInfoListHead;
03540         while (cipherInfo != NULL) {
03541             PR_JoinThread(cipherInfo->cipherThread);
03542             finishIO(&cipherInfo->output, outfile);
03543             cipherInfo = cipherInfo->next;
03544         }
03545         TIMEFINISH(totalTime, 1);
03546     }
03547     
03548     cipherInfo = cipherInfoListHead;
03549     if (cipherInfo->repetitions > 0 || cipherInfo->cxreps > 0 ||
03550         threads > 1)
03551         dump_performance_info(cipherInfoListHead, totalTime,
03552                               bltest.commands[cmd_Encrypt].activated,
03553                              (cipherInfo->repetitions == 0));
03554     
03555     rv = SECSuccess;
03556 
03557   exit_point:
03558     if (outfile && outfile != PR_STDOUT)
03559        PR_Close(outfile);
03560     cipherInfo = cipherInfoListHead;
03561     while (cipherInfo != NULL) {
03562         bltestCipherInfo *tmpInfo = cipherInfo;
03563 
03564         if (cipherInfo->arena)
03565             PORT_FreeArena(cipherInfo->arena, PR_TRUE);
03566         cipherInfo = cipherInfo->next;
03567         PORT_Free(tmpInfo);
03568     }
03569 
03570     /*NSS_Shutdown();*/
03571 
03572     return SECSuccess;
03573 }