From 8cbcd772e87a2265156502f41d67bfc7d0890990 Mon Sep 17 00:00:00 2001 From: "mcgreer%netscape.com" Date: Fri, 1 Dec 2000 01:24:05 +0000 Subject: [PATCH] massive changes to blapitest to allow for more flexible input types and improved performance testing output. git-svn-id: svn://10.0.0.236/trunk@83170 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/security/nss/cmd/bltest/blapitest.c | 3685 ++++++++++--------- 1 file changed, 1987 insertions(+), 1698 deletions(-) diff --git a/mozilla/security/nss/cmd/bltest/blapitest.c b/mozilla/security/nss/cmd/bltest/blapitest.c index 92c0c2e43d1..264b189cd0e 100644 --- a/mozilla/security/nss/cmd/bltest/blapitest.c +++ b/mozilla/security/nss/cmd/bltest/blapitest.c @@ -3,25 +3,25 @@ * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ - * + * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. - * + * * The Original Code is the Netscape security libraries. - * + * * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. - * + * * Contributor(s): - * + * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and @@ -46,1809 +46,2098 @@ #include "softoken.h" char *progName; -char *testdir = "."; +char *testdir = NULL; + +#define BLTEST_DEFAULT_CHUNKSIZE 4096 + +#define WORDSIZE sizeof(unsigned long) #define CHECKERROR(rv, ln) \ - if (rv) { \ - char *errtxt = NULL; \ - if (PR_GetError() != 0) { \ - errtxt = PORT_Alloc(PR_GetErrorTextLength()); \ - PR_GetErrorText(errtxt); \ - } \ - PR_fprintf(PR_STDERR, "%s: ERR (%s) at line %d.\n", progName, \ - (errtxt) ? "" : errtxt, ln); \ - exit(-1); \ - } + if (rv) { \ + PRErrorCode prerror = PR_GetError(); \ + PR_fprintf(PR_STDERR, "%s: ERR %d (%s) at line %d.\n", progName, \ + prerror, SECU_Strerror(prerror), ln); \ + exit(-1); \ + } + +/* Macros for performance timing. */ +#define TIMESTART() \ + time1 = PR_IntervalNow(); + +#define TIMEFINISH(time, reps) \ + time2 = (PRIntervalTime)(PR_IntervalNow() - time1); \ + time1 = PR_IntervalToMilliseconds(time2); \ + time = ((float)(time1))/reps; static void Usage() { #define PRINTUSAGE(subject, option, predicate) \ - fprintf(stderr, "%10s %s\t%s\n", subject, option, predicate); - fprintf(stderr, "\n"); - PRINTUSAGE(progName, "[-DEHSV] -m", "List available cipher modes."); - fprintf(stderr, "\n"); - PRINTUSAGE(progName, "-E -m mode ", "Encrypt a buffer."); - PRINTUSAGE("", "", "[-i plaintext] [-o ciphertext] [-k key] [-v iv]"); - PRINTUSAGE("", "", "[-b bufsize] [-g keysize] [-erw]"); - PRINTUSAGE("", "", "[-p repetitions]"); - PRINTUSAGE("", "-m", "cipher mode to use."); - PRINTUSAGE("", "-i", "file which contains input buffer."); - PRINTUSAGE("", "-o", "file for output buffer."); - PRINTUSAGE("", "-k", "file which contains key."); - PRINTUSAGE("", "-v", "file which contains initialization vector."); - PRINTUSAGE("", "-b", "size of input buffer."); - PRINTUSAGE("", "-g", "key size (in bytes)."); - PRINTUSAGE("", "-p", "do performance test."); - PRINTUSAGE("(rsa)", "-e", "rsa public exponent."); -#if NSS_SOFTOKEN_DOES_RC5 - PRINTUSAGE("(rc5)", "-r", "number of rounds."); - PRINTUSAGE("(rc5)", "-w", "wordsize (32 or 64)."); -#endif - fprintf(stderr, "\n"); - PRINTUSAGE(progName, "-D -m mode", "Decrypt a buffer."); - PRINTUSAGE("", "", "[-i plaintext] [-o ciphertext] [-k key] [-v iv]"); - PRINTUSAGE("", "", "[-p repetitions]"); - PRINTUSAGE("", "-m", "cipher mode to use."); - PRINTUSAGE("", "-i", "file which contains input buffer."); - PRINTUSAGE("", "-o", "file for output buffer."); - PRINTUSAGE("", "-k", "file which contains key."); - PRINTUSAGE("", "-v", "file which contains initialization vector."); - PRINTUSAGE("", "-p", "do performance test."); - fprintf(stderr, "\n"); - PRINTUSAGE(progName, "-H -m mode", "Hash a buffer."); - PRINTUSAGE("", "", "[-i plaintext] [-o hash]"); - PRINTUSAGE("", "", "[-b bufsize]"); - PRINTUSAGE("", "", "[-p repetitions]"); - PRINTUSAGE("", "-m", "cipher mode to use."); - PRINTUSAGE("", "-i", "file which contains input buffer."); - PRINTUSAGE("", "-o", "file for hash."); - PRINTUSAGE("", "-b", "size of input buffer."); - PRINTUSAGE("", "-p", "do performance test."); - fprintf(stderr, "\n"); - PRINTUSAGE(progName, "-S -m mode", "Sign a buffer."); - PRINTUSAGE("", "", "[-i plaintext] [-o signature] [-k key]"); - PRINTUSAGE("", "", "[-b bufsize]"); - PRINTUSAGE("", "", "[-p repetitions]"); - PRINTUSAGE("", "-m", "cipher mode to use."); - PRINTUSAGE("", "-i", "file which contains input buffer."); - PRINTUSAGE("", "-o", "file for signature."); - PRINTUSAGE("", "-k", "file which contains key."); - PRINTUSAGE("", "-p", "do performance test."); - fprintf(stderr, "\n"); - PRINTUSAGE(progName, "-V -m mode", "Verify a signed buffer."); - PRINTUSAGE("", "", "[-i plaintext] [-s signature] [-k key]"); - PRINTUSAGE("", "", "[-p repetitions]"); - PRINTUSAGE("", "-m", "cipher mode to use."); - PRINTUSAGE("", "-i", "file which contains input buffer."); - PRINTUSAGE("", "-s", "file which contains signature of input buffer."); - PRINTUSAGE("", "-k", "file which contains key."); - PRINTUSAGE("", "-p", "do performance test."); - fprintf(stderr, "\n"); - PRINTUSAGE(progName, "-F", "Run the FIPS self-test."); - fprintf(stderr, "\n"); - PRINTUSAGE(progName, "-T [mode1 mode2 ...]", "Run the BLAPI self-test."); - fprintf(stderr, "\n"); - exit(1); + fprintf(stderr, "%10s %s\t%s\n", subject, option, predicate); + fprintf(stderr, "\n"); + PRINTUSAGE(progName, "[-DEHSV]", "List available cipher modes"); /* XXX */ + fprintf(stderr, "\n"); + PRINTUSAGE(progName, "-E -m mode ", "Encrypt a buffer"); + PRINTUSAGE("", "", "[-i plaintext] [-o ciphertext] [-k key] [-v iv]"); + PRINTUSAGE("", "", "[-b bufsize] [-g keysize] [-e exp] [-r rounds]"); + PRINTUSAGE("", "", "[-w wordsize] [-p repetitions]"); + PRINTUSAGE("", "-m", "cipher mode to use"); + PRINTUSAGE("", "-i", "file which contains input buffer"); + PRINTUSAGE("", "-o", "file for output buffer"); + PRINTUSAGE("", "-k", "file which contains key"); + PRINTUSAGE("", "-v", "file which contains initialization vector"); + PRINTUSAGE("", "-b", "size of input buffer"); + PRINTUSAGE("", "-g", "key size (in bytes)"); + PRINTUSAGE("", "-p", "do performance test"); + PRINTUSAGE("(rsa)", "-e", "rsa public exponent"); + PRINTUSAGE("(rc5)", "-r", "number of rounds"); + PRINTUSAGE("(rc5)", "-w", "wordsize (32 or 64)"); + fprintf(stderr, "\n"); + PRINTUSAGE(progName, "-D -m mode", "Decrypt a buffer"); + PRINTUSAGE("", "", "[-i plaintext] [-o ciphertext] [-k key] [-v iv]"); + PRINTUSAGE("", "", "[-p repetitions]"); + PRINTUSAGE("", "-m", "cipher mode to use"); + PRINTUSAGE("", "-i", "file which contains input buffer"); + PRINTUSAGE("", "-o", "file for output buffer"); + PRINTUSAGE("", "-k", "file which contains key"); + PRINTUSAGE("", "-v", "file which contains initialization vector"); + PRINTUSAGE("", "-p", "do performance test"); + fprintf(stderr, "\n"); + PRINTUSAGE(progName, "-H -m mode", "Hash a buffer"); + PRINTUSAGE("", "", "[-i plaintext] [-o hash]"); + PRINTUSAGE("", "", "[-b bufsize]"); + PRINTUSAGE("", "", "[-p repetitions]"); + PRINTUSAGE("", "-m", "cipher mode to use"); + PRINTUSAGE("", "-i", "file which contains input buffer"); + PRINTUSAGE("", "-o", "file for hash"); + PRINTUSAGE("", "-b", "size of input buffer"); + PRINTUSAGE("", "-p", "do performance test"); + fprintf(stderr, "\n"); + PRINTUSAGE(progName, "-S -m mode", "Sign a buffer"); + PRINTUSAGE("", "", "[-i plaintext] [-o signature] [-k key]"); + PRINTUSAGE("", "", "[-b bufsize]"); + PRINTUSAGE("", "", "[-p repetitions]"); + PRINTUSAGE("", "-m", "cipher mode to use"); + PRINTUSAGE("", "-i", "file which contains input buffer"); + PRINTUSAGE("", "-o", "file for signature"); + PRINTUSAGE("", "-k", "file which contains key"); + PRINTUSAGE("", "-p", "do performance test"); + fprintf(stderr, "\n"); + PRINTUSAGE(progName, "-V -m mode", "Verify a signed buffer"); + PRINTUSAGE("", "", "[-i plaintext] [-s signature] [-k key]"); + PRINTUSAGE("", "", "[-p repetitions]"); + PRINTUSAGE("", "-m", "cipher mode to use"); + PRINTUSAGE("", "-i", "file which contains input buffer"); + PRINTUSAGE("", "-s", "file which contains signature of input buffer"); + PRINTUSAGE("", "-k", "file which contains key"); + PRINTUSAGE("", "-p", "do performance test"); + fprintf(stderr, "\n"); + PRINTUSAGE(progName, "-N -m mode -b bufsize", + "Create a nonce plaintext and key"); + PRINTUSAGE("", "", "[-g keysize] [-u cxreps]"); + PRINTUSAGE("", "-g", "key size (in bytes)"); + PRINTUSAGE("", "-u", "number of repetitions of context creation"); + fprintf(stderr, "\n"); + PRINTUSAGE(progName, "-F", "Run the FIPS self-test"); + fprintf(stderr, "\n"); + PRINTUSAGE(progName, "-T [-m mode1,mode2...]", "Run the BLAPI self-test"); + fprintf(stderr, "\n"); + exit(1); } /* Helper functions for ascii<-->binary conversion/reading/writing */ +/* XXX argh */ +struct item_with_arena { + SECItem *item; + PRArenaPool *arena; +}; + static PRInt32 get_binary(void *arg, const unsigned char *ibuf, PRInt32 size) { - SECItem *binary = arg; - SECItem *tmp; - int index; - if (binary->data == NULL) { - tmp = SECITEM_AllocItem(NULL, NULL, size); - binary->data = tmp->data; - binary->len = tmp->len; - index = 0; - } else { - SECITEM_ReallocItem(NULL, binary, binary->len, binary->len + size); - index = binary->len; - } - PORT_Memcpy(&binary->data[index], ibuf, size); - return binary->len; -} - -static PRInt32 -get_ascii(void *arg, const char *ibuf, PRInt32 size) -{ - SECItem *ascii = arg; - SECItem *tmp; - int index; - if (ascii->data == NULL) { - tmp = SECITEM_AllocItem(NULL, NULL, size); - ascii->data = tmp->data; - ascii->len = tmp->len; - index = 0; - } else { - SECITEM_ReallocItem(NULL, ascii, ascii->len, ascii->len + size); - index = ascii->len; - } - PORT_Memcpy(&ascii->data[index], ibuf, size); - return ascii->len; + struct item_with_arena *it = arg; + SECItem *binary = it->item; + SECItem *tmp; + int index; + if (binary->data == NULL) { + tmp = SECITEM_AllocItem(it->arena, NULL, size); + binary->data = tmp->data; + binary->len = tmp->len; + index = 0; + } else { + SECITEM_ReallocItem(NULL, binary, binary->len, binary->len + size); + index = binary->len; + } + PORT_Memcpy(&binary->data[index], ibuf, size); + return binary->len; } static SECStatus -atob(SECItem *ascii, SECItem *binary) +atob(SECItem *ascii, SECItem *binary, PRArenaPool *arena) { - SECStatus status; - NSSBase64Decoder *cx; - int len; - binary->data = NULL; - binary->len = 0; - len = (strcmp(&ascii->data[ascii->len-2],"\r\n"))?ascii->len:ascii->len-2; - cx = NSSBase64Decoder_Create(get_binary, binary); - status = NSSBase64Decoder_Update(cx, (const char *)ascii->data, len); - status = NSSBase64Decoder_Destroy(cx, PR_FALSE); - return status; + SECStatus status; + NSSBase64Decoder *cx; + struct item_with_arena it; + int len; + binary->data = NULL; + binary->len = 0; + it.item = binary; + it.arena = arena; + len = (strcmp(&ascii->data[ascii->len-2],"\r\n"))?ascii->len:ascii->len-2; + cx = NSSBase64Decoder_Create(get_binary, &it); + status = NSSBase64Decoder_Update(cx, (const char *)ascii->data, len); + status = NSSBase64Decoder_Destroy(cx, PR_FALSE); + return status; } static PRInt32 output_ascii(void *arg, const char *obuf, PRInt32 size) { - PRFileDesc *outfile = arg; - PRInt32 nb = PR_Write(outfile, obuf, size); - if (nb != size) { - PORT_SetError(SEC_ERROR_IO); - return -1; - } - return nb; -} - -static SECStatus -btoa(SECItem *binary, SECItem *ascii) -{ - SECStatus status; - NSSBase64Encoder *cx; - ascii->data = NULL; - ascii->len = 0; - cx = NSSBase64Encoder_Create(get_ascii, ascii); - status = NSSBase64Encoder_Update(cx, binary->data, binary->len); - status = NSSBase64Encoder_Destroy(cx, PR_FALSE); - return status; + PRFileDesc *outfile = arg; + PRInt32 nb = PR_Write(outfile, obuf, size); + if (nb != size) { + PORT_SetError(SEC_ERROR_IO); + return -1; + } + return nb; } static SECStatus btoa_file(SECItem *binary, PRFileDesc *outfile) { - SECStatus status; - NSSBase64Encoder *cx; - SECItem ascii; - ascii.data = NULL; - ascii.len = 0; - if (binary->len == 0) - return SECSuccess; - cx = NSSBase64Encoder_Create(output_ascii, outfile); - status = NSSBase64Encoder_Update(cx, binary->data, binary->len); - status = NSSBase64Encoder_Destroy(cx, PR_FALSE); - status = PR_Write(outfile, "\r\n", 2); - return status; + SECStatus status; + NSSBase64Encoder *cx; + SECItem ascii; + ascii.data = NULL; + ascii.len = 0; + if (binary->len == 0) + return SECSuccess; + cx = NSSBase64Encoder_Create(output_ascii, outfile); + status = NSSBase64Encoder_Update(cx, binary->data, binary->len); + status = NSSBase64Encoder_Destroy(cx, PR_FALSE); + status = PR_Write(outfile, "\r\n", 2); + return status; } -static SECStatus -get_and_write_random_bytes(SECItem *item, PRInt32 numbytes, char *filename) +SECStatus +hex_from_2char(unsigned char *c2, unsigned char *byteval) { - SECStatus rv; - PRFileDesc *file; - item->len = numbytes; - item->data = (unsigned char *)PORT_ZAlloc(numbytes); - RNG_GenerateGlobalRandomBytes(item->data + 1, numbytes - 1); - file = PR_Open(filename, PR_WRONLY|PR_CREATE_FILE, 00660); - rv = btoa_file(item, file); - CHECKERROR((rv < 0), __LINE__); - return (rv < 0); + int i; + unsigned char offset; + *byteval = 0; + for (i=0; i<2; i++) { + if (c2[i] >= '0' && c2[i] <= '9') { + offset = c2[i] - '0'; + *byteval |= offset << 4*(1-i); + } else if (c2[i] >= 'a' && c2[i] <= 'f') { + offset = c2[i] - 'a'; + *byteval |= (offset + 10) << 4*(1-i); + } else if (c2[i] >= 'A' && c2[i] <= 'F') { + offset = c2[i] - 'A'; + *byteval |= (offset + 10) << 4*(1-i); + } else { + return SECFailure; + } + } + return SECSuccess; +} + +SECStatus +char2_from_hex(unsigned char byteval, unsigned char *c2) +{ + int i; + unsigned char offset; + for (i=0; i<2; i++) { + offset = (byteval >> 4*(1-i)) & 0x0f; + if (offset < 10) { + c2[i] = '0' + offset; + } else { + c2[i] = 'A' + offset - 10; + } + } + return SECSuccess; +} + +void +serialize_key(SECItem *it, int ni, PRFileDesc *file) +{ + unsigned char len[4]; + int i; + SECStatus status; + NSSBase64Encoder *cx; + SECItem ascii; + ascii.data = NULL; + ascii.len = 0; + cx = NSSBase64Encoder_Create(output_ascii, file); + for (i=0; ilen >> 24) & 0xff; + len[1] = (it->len >> 16) & 0xff; + len[2] = (it->len >> 8) & 0xff; + len[3] = (it->len & 0xff); + status = NSSBase64Encoder_Update(cx, len, 4); + status = NSSBase64Encoder_Update(cx, it->data, it->len); + } + status = NSSBase64Encoder_Destroy(cx, PR_FALSE); + status = PR_Write(file, "\r\n", 2); +} + +void +key_from_filedata(PRArenaPool *arena, SECItem *it, int ni, SECItem *filedata) +{ + int fpos = 0; + int i; + unsigned char *buf = filedata->data; + for (i=0; ilen = (buf[fpos++] & 0xff) << 24; + it->len |= (buf[fpos++] & 0xff) << 16; + it->len |= (buf[fpos++] & 0xff) << 8; + it->len |= (buf[fpos++] & 0xff); + if (it->len > 0) { + it->data = PORT_ArenaAlloc(arena, it->len); + PORT_Memcpy(it->data, &buf[fpos], it->len); + } else { + it->data = NULL; + } + fpos += it->len; + } } static RSAPrivateKey * rsakey_from_filedata(SECItem *filedata) { - PRArenaPool *arena; - RSAPrivateKey *key; - unsigned char *buf = filedata->data; - int fpos = 0; - int i; - SECItem *item; - /* Allocate space for key structure. */ - arena = PORT_NewArena(2048); - key = (RSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(RSAPrivateKey)); - key->arena = arena; - item = &key->version; - for (i=0; i<9; i++) { - item->len = (buf[fpos++] & 0xff) << 24; - item->len |= (buf[fpos++] & 0xff) << 16; - item->len |= (buf[fpos++] & 0xff) << 8; - item->len |= (buf[fpos++] & 0xff); - if (item->len > 0) { - item->data = PORT_ArenaAlloc(arena, item->len); - PORT_Memcpy(item->data, &buf[fpos], item->len); - } else { - item->data = NULL; - } - fpos += item->len; - item++; - } - return key; -} - -static void -rsakey_to_file(RSAPrivateKey *key, char *filename) -{ - PRFileDesc *file; - SECItem *item; - unsigned char len[4]; - int i; - SECStatus status; - NSSBase64Encoder *cx; - SECItem ascii; - ascii.data = NULL; - ascii.len = 0; - file = PR_Open(filename, PR_WRONLY|PR_CREATE_FILE, 00660); - cx = NSSBase64Encoder_Create(output_ascii, file); - item = &key->version; - for (i=0; i<9; i++) { - len[0] = (item->len >> 24) & 0xff; - len[1] = (item->len >> 16) & 0xff; - len[2] = (item->len >> 8) & 0xff; - len[3] = (item->len & 0xff); - status = NSSBase64Encoder_Update(cx, len, 4); - status = NSSBase64Encoder_Update(cx, item->data, item->len); - item++; - } - status = NSSBase64Encoder_Destroy(cx, PR_FALSE); - status = PR_Write(file, "\r\n", 2); - PR_Close(file); + RSAPrivateKey *key; + PRArenaPool *arena; + arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE); + key = (RSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(RSAPrivateKey)); + key->arena = arena; + key_from_filedata(arena, &key->version, 9, filedata); + return key; } static PQGParams * pqg_from_filedata(SECItem *filedata) { - PRArenaPool *arena; - PQGParams *pqg; - unsigned char *buf = filedata->data; - int fpos = 0; - int i; - SECItem *item; - /* Allocate space for key structure. */ - arena = PORT_NewArena(2048); - pqg = (PQGParams *)PORT_ArenaZAlloc(arena, sizeof(PQGParams)); - pqg->arena = arena; - item = &pqg->prime; - for (i=0; i<3; i++) { - item->len = (buf[fpos++] & 0xff) << 24; - item->len |= (buf[fpos++] & 0xff) << 16; - item->len |= (buf[fpos++] & 0xff) << 8; - item->len |= (buf[fpos++] & 0xff); - if (item->len > 0) { - item->data = PORT_ArenaAlloc(arena, item->len); - PORT_Memcpy(item->data, &buf[fpos], item->len); - } else { - item->data = NULL; - } - fpos += item->len; - item++; - } - return pqg; + PQGParams *pqg; + PRArenaPool *arena; + arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE); + pqg = (PQGParams *)PORT_ArenaZAlloc(arena, sizeof(PQGParams)); + pqg->arena = arena; + key_from_filedata(arena, &pqg->prime, 3, filedata); + return pqg; } static DSAPrivateKey * dsakey_from_filedata(SECItem *filedata) { - PRArenaPool *arena; - DSAPrivateKey *key; - unsigned char *buf = filedata->data; - int fpos = 0; - int i; - SECItem *item; - /* Allocate space for key structure. */ - arena = PORT_NewArena(2048); - key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey)); - key->params.arena = arena; - item = &key->params.prime; - for (i=0; i<5; i++) { - item->len = (buf[fpos++] & 0xff) << 24; - item->len |= (buf[fpos++] & 0xff) << 16; - item->len |= (buf[fpos++] & 0xff) << 8; - item->len |= (buf[fpos++] & 0xff); - if (item->len > 0) { - item->data = PORT_ArenaAlloc(arena, item->len); - PORT_Memcpy(item->data, &buf[fpos], item->len); - } else { - item->data = NULL; - } - fpos += item->len; - item++; - } - return key; -} - -static void -pqg_to_file(PQGParams *params, char *filename) -{ - PRFileDesc *file; - SECItem *item; - unsigned char len[4]; - int i; - SECStatus status; - NSSBase64Encoder *cx; - SECItem ascii; - ascii.data = NULL; - ascii.len = 0; - file = PR_Open(filename, PR_WRONLY|PR_CREATE_FILE, 00660); - cx = NSSBase64Encoder_Create(output_ascii, file); - item = ¶ms->prime; - for (i=0; i<3; i++) { - len[0] = (item->len >> 24) & 0xff; - len[1] = (item->len >> 16) & 0xff; - len[2] = (item->len >> 8) & 0xff; - len[3] = (item->len & 0xff); - status = NSSBase64Encoder_Update(cx, len, 4); - status = NSSBase64Encoder_Update(cx, item->data, item->len); - item++; - } - status = NSSBase64Encoder_Destroy(cx, PR_FALSE); - status = PR_Write(file, "\r\n", 2); -} - -static void -dsakey_to_file(DSAPrivateKey *key, char *filename) -{ - PRFileDesc *file; - SECItem *item; - unsigned char len[4]; - int i; - SECStatus status; - NSSBase64Encoder *cx; - SECItem ascii; - ascii.data = NULL; - ascii.len = 0; - file = PR_Open(filename, PR_WRONLY|PR_CREATE_FILE, 00660); - cx = NSSBase64Encoder_Create(output_ascii, file); - item = &key->params.prime; - for (i=0; i<5; i++) { - len[0] = (item->len >> 24) & 0xff; - len[1] = (item->len >> 16) & 0xff; - len[2] = (item->len >> 8) & 0xff; - len[3] = (item->len & 0xff); - status = NSSBase64Encoder_Update(cx, len, 4); - status = NSSBase64Encoder_Update(cx, item->data, item->len); - item++; - } - status = NSSBase64Encoder_Destroy(cx, PR_FALSE); - status = PR_Write(file, "\r\n", 2); + DSAPrivateKey *key; + PRArenaPool *arena; + arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE); + key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey)); + key->params.arena = arena; + key_from_filedata(arena, &key->params.prime, 5, filedata); + return key; } static void dump_pqg(PQGParams *pqg) { - SECU_PrintInteger(stdout, &pqg->prime, "PRIME:", 0); - SECU_PrintInteger(stdout, &pqg->subPrime, "SUBPRIME:", 0); - SECU_PrintInteger(stdout, &pqg->base, "BASE:", 0); + SECU_PrintInteger(stdout, &pqg->prime, "PRIME:", 0); + SECU_PrintInteger(stdout, &pqg->subPrime, "SUBPRIME:", 0); + SECU_PrintInteger(stdout, &pqg->base, "BASE:", 0); } static void dump_dsakey(DSAPrivateKey *key) { - dump_pqg(&key->params); - SECU_PrintInteger(stdout, &key->publicValue, "PUBLIC VALUE:", 0); - SECU_PrintInteger(stdout, &key->privateValue, "PRIVATE VALUE:", 0); + dump_pqg(&key->params); + SECU_PrintInteger(stdout, &key->publicValue, "PUBLIC VALUE:", 0); + SECU_PrintInteger(stdout, &key->privateValue, "PRIVATE VALUE:", 0); } static void dump_rsakey(RSAPrivateKey *key) { - SECU_PrintInteger(stdout, &key->version, "Version", 0); - SECU_PrintInteger(stdout, &key->modulus, "Modulus", 0); - SECU_PrintInteger(stdout, &key->publicExponent, "Public Exponent", 0); - SECU_PrintInteger(stdout, &key->privateExponent, "Private Exponent", 0); - SECU_PrintInteger(stdout, &key->prime1, "Prime 1", 0); - SECU_PrintInteger(stdout, &key->prime2, "Prime 2", 0); - SECU_PrintInteger(stdout, &key->exponent1, "Exponent 1", 0); - SECU_PrintInteger(stdout, &key->exponent2, "Exponent 2", 0); - SECU_PrintInteger(stdout, &key->coefficient, "Coefficient", 0); + SECU_PrintInteger(stdout, &key->version, "VERSION:", 0); + SECU_PrintInteger(stdout, &key->modulus, "MODULUS:", 0); + SECU_PrintInteger(stdout, &key->publicExponent, "PUBLIC EXP:", 0); + SECU_PrintInteger(stdout, &key->privateExponent, "PRIVATE EXP:", 0); + SECU_PrintInteger(stdout, &key->prime1, "CRT PRIME 1:", 0); + SECU_PrintInteger(stdout, &key->prime2, "CRT PRIME 2:", 0); + SECU_PrintInteger(stdout, &key->exponent1, "CRT EXP 1:", 0); + SECU_PrintInteger(stdout, &key->exponent2, "CRT EXP 2:", 0); + SECU_PrintInteger(stdout, &key->coefficient, "CRT COEFFICIENT:", 0); } -/* Multi-purpose crypto information */ -typedef struct +typedef enum { + bltestBase64Encoded, /* Base64 encoded ASCII */ + bltestBinary, /* straight binary */ + bltestHexSpaceDelim, /* 0x12 0x34 0xab 0xCD ... */ + bltestHexStream, /* 1234abCD ... */ +} bltestIOMode; + +typedef struct { - PRBool encrypt; - PRBool decrypt; - PRBool sign; - PRBool verify; - PRBool hash; - SECItem seed; - SECItem pqg; - SECItem key; - SECItem iv; - SECItem in; - SECItem out; - SECItem sigseed; - PRInt32 keysize; - PRInt32 bufsize; - PRBool useseed; - PRBool usesigseed; - PRBool performance; - PRBool multihash; - PQGParams *params; /* DSA only */ - unsigned int rounds; /* RC5 only */ - unsigned int wordsize; /* RC5 only */ - unsigned int rsapubexp; /* RSA only */ - unsigned int repetitions; /* performance tests only */ -} blapitestInfo; + SECItem buf; + SECItem pBuf; + bltestIOMode mode; + PRFileDesc* file; +} bltestIO; -/* Macros for performance timing. */ -#define TIMESTART() \ - if (info->performance) \ - time1 = PR_IntervalNow(); +typedef SECStatus (* bltestSymmCipherFn)(void *cx, + unsigned char *output, + unsigned int *outputLen, + unsigned int maxOutputLen, + unsigned char *input, + unsigned int inputLen); -#define TIMEFINISH(mode, nb) \ - if (info->performance) { \ - time2 = (PRIntervalTime)(PR_IntervalNow() - time1); \ - time1 = PR_IntervalToMilliseconds(time2); \ - printf("%s,%d,%.3f\n", mode, nb, ((float)(time1))/info->repetitions); \ - } +typedef SECStatus (* bltestPubKeyCipherFn)(void *key, + unsigned char *input, + unsigned char *output); -SECStatus -fillitem(SECItem *item, int numbytes, char *filename) -{ - if (item->len == 0) - return get_and_write_random_bytes(item, numbytes, filename); - return SECSuccess; -} +typedef SECStatus (* bltestHashCipherFn)(unsigned char *dest, + unsigned char *src, + uint32 src_length); -/************************ -** DES -************************/ +typedef enum { + bltestINVALID = -1, + bltestDES_ECB, /* Symmetric Key Ciphers */ + bltestDES_CBC, /* . */ + bltestDES_EDE_ECB, /* . */ + bltestDES_EDE_CBC, /* . */ + bltestRC2_ECB, /* . */ + bltestRC2_CBC, /* . */ + bltestRC4, /* . */ + bltestRC5_ECB, /* . */ + bltestRC5_CBC, /* . */ + bltestRSA, /* Public Key Ciphers */ + bltestDSA, /* . (Public Key Sig.) */ + bltestMD2, /* Hash algorithms */ + bltestMD5, /* . */ + bltestSHA1 /* . */ +} bltestCipherMode; -/* encrypt/decrypt for all DES */ -static SECStatus -des_common(DESContext *descx, blapitestInfo *info) -{ - PRInt32 maxsize; - SECStatus rv; - PRIntervalTime time1, time2; - int i, numiter; - numiter = info->repetitions; - maxsize = info->in.len; - info->out.data = (unsigned char *)PORT_ZAlloc(maxsize); - if (info->encrypt) { - TIMESTART(); - for (i=0; iout.data, &info->out.len, maxsize, - info->in.data, info->in.len); - TIMEFINISH("DES ENCRYPT", maxsize); - if (rv) { - fprintf(stderr, "%s: Failed to encrypt!\n", progName); - CHECKERROR(rv, __LINE__); - } - } else { - TIMESTART(); - for (i=0; iout.data, &info->out.len, maxsize, - info->in.data, info->in.len); - TIMEFINISH("DES DECRYPT", maxsize); - if (rv) { - fprintf(stderr, "%s: Failed to decrypt!\n", progName); - CHECKERROR(rv, __LINE__); - } - } - return rv; -} - -/* DES codebook mode */ -static SECStatus -des_ecb_test(blapitestInfo *info) -{ - SECStatus rv; - DESContext *descx; - PRIntervalTime time1, time2; - int i, numiter = info->repetitions; - fillitem(&info->key, DES_KEY_LENGTH, "tmp.key"); - fillitem(&info->in, info->bufsize, "tmp.pt"); - TIMESTART(); - for (i=0; ikey.data, NULL, NSS_DES, info->encrypt); - DES_DestroyContext(descx, PR_TRUE); - } - descx = DES_CreateContext(info->key.data, NULL, NSS_DES, info->encrypt); - TIMEFINISH("DES ECB CONTEXT CREATE", info->key.len); - if (!descx) { - fprintf(stderr,"%s: Failed to create encryption context!\n", progName); - return SECFailure; - } - rv = des_common(descx, info); - CHECKERROR(rv, __LINE__); - DES_DestroyContext(descx, PR_TRUE); - return rv; -} - -/* DES chaining mode */ -static SECStatus -des_cbc_test(blapitestInfo *info) -{ - SECStatus rv; - DESContext *descx; - PRIntervalTime time1, time2; - int i, numiter = info->repetitions; - fillitem(&info->key, DES_KEY_LENGTH, "tmp.key"); - fillitem(&info->in, info->bufsize, "tmp.pt"); - fillitem(&info->iv, DES_KEY_LENGTH, "tmp.iv"); - TIMESTART(); - for (i=0; ikey.data, info->iv.data, NSS_DES_CBC, - info->encrypt); - DES_DestroyContext(descx, PR_TRUE); - } - descx = DES_CreateContext(info->key.data, info->iv.data, NSS_DES_CBC, - info->encrypt); - TIMEFINISH("DES CBC CONTEXT CREATE", info->key.len); - if (!descx) { - PR_fprintf(PR_STDERR, - "%s: Failed to create encryption context!\n", progName); - return SECFailure; - } - if (info->performance) { - /* In chaining mode, repeated iterations of the encryption - * function using the same context will alter the final output. - * So, once the performance test is done, reset the context - * and perform a single iteration to obtain the correct result. - */ - int tmp = info->repetitions; - rv = des_common(descx, info); - DES_DestroyContext(descx, PR_TRUE); - descx = DES_CreateContext(info->key.data, info->iv.data, NSS_DES_CBC, - info->encrypt); - info->performance = PR_FALSE; - info->repetitions = 1; - rv = des_common(descx, info); - info->performance = PR_TRUE; - info->repetitions = tmp; - } else { - rv = des_common(descx, info); - } - CHECKERROR(rv, __LINE__); - DES_DestroyContext(descx, PR_TRUE); - return rv; -} - -/* 3-key Triple-DES codebook mode */ -static SECStatus -des_ede_ecb_test(blapitestInfo *info) -{ - SECStatus rv; - DESContext *descx; - PRIntervalTime time1, time2; - int i, numiter = info->repetitions; - fillitem(&info->key, 3*DES_KEY_LENGTH, "tmp.key"); - fillitem(&info->in, info->bufsize, "tmp.pt"); - TIMESTART(); - for (i=0; ikey.data, NULL, NSS_DES_EDE3, - info->encrypt); - DES_DestroyContext(descx, PR_TRUE); - } - descx = DES_CreateContext(info->key.data, NULL, NSS_DES_EDE3, - info->encrypt); - TIMEFINISH("3DES ECB CONTEXT CREATE", info->key.len); - if (!descx) { - fprintf(stderr,"%s: Failed to create encryption context!\n", progName); - return SECFailure; - } - rv = des_common(descx, info); - CHECKERROR(rv, __LINE__); - DES_DestroyContext(descx, PR_TRUE); - return rv; -} - -/* 3-key Triple-DES chaining mode */ -static SECStatus -des_ede_cbc_test(blapitestInfo *info) -{ - SECStatus rv; - DESContext *descx; - PRIntervalTime time1, time2; - int i, numiter = info->repetitions; - fillitem(&info->key, 3*DES_KEY_LENGTH, "tmp.key"); - fillitem(&info->in, info->bufsize, "tmp.pt"); - fillitem(&info->iv, DES_KEY_LENGTH, "tmp.iv"); - TIMESTART(); - for (i=0; ikey.data, info->iv.data, - NSS_DES_EDE3_CBC, info->encrypt); - DES_DestroyContext(descx, PR_TRUE); - } - descx = DES_CreateContext(info->key.data, info->iv.data, NSS_DES_EDE3_CBC, - info->encrypt); - TIMEFINISH("3DES CBC CONTEXT CREATE", info->key.len); - if (!descx) { - fprintf(stderr,"%s: Failed to create encryption context!\n", progName); - return SECFailure; - } - if (info->performance) { - /* In chaining mode, repeated iterations of the encryption - * function using the same context will alter the final output. - * So, once the performance test is done, reset the context - * and perform a single iteration to obtain the correct result. - */ - int tmp = info->repetitions; - rv = des_common(descx, info); - DES_DestroyContext(descx, PR_TRUE); - descx = DES_CreateContext(info->key.data, info->iv.data, - NSS_DES_EDE3_CBC, info->encrypt); - info->performance = PR_FALSE; - info->repetitions = 1; - rv = des_common(descx, info); - info->performance = PR_TRUE; - info->repetitions = tmp; - } else { - rv = des_common(descx, info); - } - CHECKERROR(rv, __LINE__); - DES_DestroyContext(descx, PR_TRUE); - return rv; -} - -/************************ -** RC2 -************************/ - -/* RC2 ECB */ -static SECStatus -rc2_ecb_test(blapitestInfo *info) -{ - SECStatus rv; - RC2Context *rc2cx; - PRIntervalTime time1, time2; - int i, numiter = info->repetitions; - fillitem(&info->key, info->keysize, "tmp.key"); - fillitem(&info->in, info->bufsize, "tmp.pt"); - TIMESTART(); - for (i=0; ikey.data, info->key.len, NULL, - NSS_RC2, info->key.len); - RC2_DestroyContext(rc2cx, PR_TRUE); - } - rc2cx = RC2_CreateContext(info->key.data, info->key.len, NULL, - NSS_RC2, info->key.len); - TIMEFINISH("RC2 ECB CONTEXT CREATE", info->key.len); - if (!rc2cx) { - fprintf(stderr,"%s: Failed to create encryption context!\n", progName); - return SECFailure; - } - info->out.len = 2*info->in.len; - info->out.data = (unsigned char *)PORT_ZAlloc(info->out.len); - if (info->encrypt) { - TIMESTART(); - for (i=0; iout.data, &info->out.len, - info->out.len, info->in.data, info->in.len); - TIMEFINISH("RC2 ECB ENCRYPT", info->in.len); - CHECKERROR(rv, __LINE__); - } else { - TIMESTART(); - for (i=0; iout.data, &info->out.len, - info->out.len, info->in.data, info->in.len); - TIMEFINISH("RC2 ECB DECRYPT", info->in.len); - CHECKERROR(rv, __LINE__); - } - RC2_DestroyContext(rc2cx, PR_TRUE); - return rv; -} - -/* RC2 CBC */ -static SECStatus -rc2_cbc_test(blapitestInfo *info) -{ - SECStatus rv; - RC2Context *rc2cx; - PRIntervalTime time1, time2; - int i, numiter = info->repetitions; - fillitem(&info->key, info->keysize, "tmp.key"); - fillitem(&info->in, info->bufsize, "tmp.pt"); - fillitem(&info->iv, info->bufsize, "tmp.iv"); - TIMESTART(); - for (i=0; ikey.data, info->key.len, info->iv.data, - NSS_RC2_CBC, info->key.len); - RC2_DestroyContext(rc2cx, PR_TRUE); - } - rc2cx = RC2_CreateContext(info->key.data, info->key.len, info->iv.data, - NSS_RC2_CBC, info->key.len); - TIMEFINISH("RC2 CBC CONTEXT CREATE", info->key.len); - if (!rc2cx) { - fprintf(stderr,"%s: Failed to create encryption context!\n", progName); - return SECFailure; - } - info->out.len = 2*info->in.len; - info->out.data = (unsigned char *)PORT_ZAlloc(info->out.len); - if (info->encrypt) { - TIMESTART(); - for (i=0; iout.data, &info->out.len, - info->out.len, info->in.data, info->in.len); - TIMEFINISH("RC2 CBC ENCRYPT", info->in.len); - if (info->performance) { - /* reset the context */ - RC2_DestroyContext(rc2cx, PR_TRUE); - rc2cx = RC2_CreateContext(info->key.data, info->key.len, - info->iv.data, NSS_RC2_CBC, info->key.len); - rv = RC2_Encrypt(rc2cx, info->out.data, &info->out.len, - info->out.len, info->in.data, info->in.len); - } - CHECKERROR(rv, __LINE__); - if (rv) { - fprintf(stderr, "%s: Failed to encrypt!\n", progName); - CHECKERROR(rv, __LINE__); - } - } else { - TIMESTART(); - for (i=0; iout.data, &info->out.len, - info->out.len, info->in.data, info->in.len); - TIMEFINISH("RC2 CBC DECRYPT", info->in.len); - if (info->performance) { - /* reset the context */ - RC2_DestroyContext(rc2cx, PR_TRUE); - rc2cx = RC2_CreateContext(info->key.data, info->key.len, - info->iv.data, NSS_RC2_CBC, info->key.len); - rv = RC2_Decrypt(rc2cx, info->out.data, &info->out.len, - info->out.len, info->in.data, info->in.len); - } - if (rv) { - fprintf(stderr, "%s: Failed to decrypt!\n", progName); - CHECKERROR(rv, __LINE__); - } - } - RC2_DestroyContext(rc2cx, PR_TRUE); - return rv; -} - -/************************ -** RC4 -************************/ - -static SECStatus -rc4_test(blapitestInfo *info) -{ - SECStatus rv; - RC4Context *rc4cx; - PRIntervalTime time1, time2; - int i, numiter; - numiter = info->repetitions; - fillitem(&info->key, info->keysize, "tmp.key"); - fillitem(&info->in, info->bufsize, "tmp.pt"); - TIMESTART(); - for (i=0; ikey.data, info->key.len); - RC4_DestroyContext(rc4cx, PR_TRUE); - } - rc4cx = RC4_CreateContext(info->key.data, info->key.len); - TIMEFINISH("RC4 CONTEXT CREATE", info->key.len); - if (!rc4cx) { - fprintf(stderr,"%s: Failed to create encryption context!\n", progName); - return SECFailure; - } - info->out.len = 2*info->in.len; - info->out.data = (unsigned char *)PORT_ZAlloc(info->out.len); - if (info->encrypt) { - TIMESTART(); - for (i=0; iout.data, &info->out.len, - info->out.len, info->in.data, info->in.len); - TIMEFINISH("RC4 ENCRYPT", info->in.len); - if (info->performance) { - /* reset the context */ - RC4_DestroyContext(rc4cx, PR_TRUE); - rc4cx = RC4_CreateContext(info->key.data, info->key.len); - rv = RC4_Encrypt(rc4cx, info->out.data, &info->out.len, - info->out.len, info->in.data, info->in.len); - } - if (rv) { - fprintf(stderr, "%s: Failed to encrypt!\n", progName); - CHECKERROR(rv, __LINE__); - } - } else { - TIMESTART(); - for (i=0; iout.data, &info->out.len, - info->out.len, info->in.data, info->in.len); - TIMEFINISH("RC4 DECRYPT", info->in.len); - if (info->performance) { - /* reset the context */ - RC4_DestroyContext(rc4cx, PR_TRUE); - rc4cx = RC4_CreateContext(info->key.data, info->key.len); - rv = RC4_Decrypt(rc4cx, info->out.data, &info->out.len, - info->out.len, info->in.data, info->in.len); - } - if (rv) { - fprintf(stderr, "%s: Failed to decrypt!\n", progName); - CHECKERROR(rv, __LINE__); - } - } - RC4_DestroyContext(rc4cx, PR_TRUE); - return rv; -} - -#if NSS_SOFTOKEN_DOES_RC5 -/************************ -** RC5 -************************/ - -/* RC5 ECB */ -static SECStatus -rc5_ecb_test(blapitestInfo *info) -{ - SECStatus rv; - RC5Context *rc5cx; - PRIntervalTime time1, time2; - int i, numiter; - numiter = info->repetitions; - fillitem(&info->key, info->keysize, "tmp.key"); - fillitem(&info->in, info->bufsize, "tmp.pt"); - TIMESTART(); - for (i=0; ikey, info->rounds, info->wordsize, - NULL, NSS_RC5); - RC5_DestroyContext(rc5cx, PR_TRUE); - } - rc5cx = RC5_CreateContext(&info->key, info->rounds, info->wordsize, - NULL, NSS_RC5); - TIMEFINISH("RC5 ECB CONTEXT CREATE", info->key.len); - if (!rc5cx) { - fprintf(stderr,"%s: Failed to create encryption context!\n", progName); - return SECFailure; - } - info->out.len = 2*info->in.len; - info->out.data = (unsigned char *)PORT_ZAlloc(info->out.len); - if (info->encrypt) { - TIMESTART(); - for (i=0; iout.data, &info->out.len, - info->out.len, info->in.data, info->in.len); - TIMEFINISH("RC5 ECB ENCRYPT", info->in.len); - if (rv) { - fprintf(stderr, "%s: Failed to encrypt!\n", progName); - CHECKERROR(rv, __LINE__); - } - } else { - TIMESTART(); - for (i=0; iout.data, &info->out.len, - info->out.len, info->in.data, info->in.len); - TIMEFINISH("RC5 ECB ENCRYPT", info->in.len); - if (rv) { - fprintf(stderr, "%s: Failed to decrypt!\n", progName); - CHECKERROR(rv, __LINE__); - } - } - RC5_DestroyContext(rc5cx, PR_TRUE); - return rv; -} - -/* RC5 CBC */ -static SECStatus -rc5_cbc_test(blapitestInfo *info) -{ - SECStatus rv; - RC5Context *rc5cx; - PRIntervalTime time1, time2; - int i, numiter; - numiter = info->repetitions; - fillitem(&info->key, info->keysize, "tmp.key"); - fillitem(&info->in, info->bufsize, "tmp.pt"); - fillitem(&info->iv, info->bufsize, "tmp.iv"); - TIMESTART(); - for (i=0; ikey, info->rounds, info->wordsize, - info->iv.data, NSS_RC5_CBC); - RC5_DestroyContext(rc5cx, PR_TRUE); - } - rc5cx = RC5_CreateContext(&info->key, info->rounds, info->wordsize, - info->iv.data, NSS_RC5_CBC); - TIMEFINISH("RC5 CBC CONTEXT CREATE", info->key.len); - if (!rc5cx) { - fprintf(stderr,"%s: Failed to create encryption context!\n", progName); - return SECFailure; - } - info->out.len = 2*info->in.len; - info->out.data = (unsigned char *)PORT_ZAlloc(info->out.len); - if (info->encrypt) { - TIMESTART(); - for (i=0; iout.data, &info->out.len, - info->out.len, info->in.data, info->in.len); - TIMEFINISH("RC5 CBC ENCRYPT", info->in.len); - if (info->performance) { - /* reset the context */ - RC5_DestroyContext(rc5cx, PR_TRUE); - rc5cx = RC5_CreateContext(&info->key, info->rounds, info->wordsize, - info->iv.data, NSS_RC5_CBC); - rv = RC5_Encrypt(rc5cx, info->out.data, &info->out.len, - info->out.len, info->in.data, info->in.len); - } - if (rv) { - fprintf(stderr, "%s: Failed to encrypt!\n", progName); - CHECKERROR(rv, __LINE__); - } - } else { - TIMESTART(); - for (i=0; iout.data, &info->out.len, - info->out.len, info->in.data, info->in.len); - TIMEFINISH("RC5 CBC DECRYPT", info->in.len); - if (info->performance) { - /* reset the context */ - RC5_DestroyContext(rc5cx, PR_TRUE); - rc5cx = RC5_CreateContext(&info->key, info->rounds, info->wordsize, - info->iv.data, NSS_RC5_CBC); - rv = RC5_Decrypt(rc5cx, info->out.data, &info->out.len, - info->out.len, info->in.data, info->in.len); - } - if (rv) { - fprintf(stderr, "%s: Failed to decrypt!\n", progName); - CHECKERROR(rv, __LINE__); - } - } - RC5_DestroyContext(rc5cx, PR_TRUE); - return rv; -} -#endif - -static SECStatus -rsa_test(blapitestInfo *info) -{ - RSAPrivateKey *key; - SECItem expitem; - SECStatus rv; - PRIntervalTime time1, time2; - int i, j, numiter; - unsigned int modLen; - numiter = info->repetitions; - fillitem(&info->in, info->bufsize, "tmp.pt"); - if (info->key.len > 0) { - key = rsakey_from_filedata(&info->key); - } else { - expitem.len = 4; - expitem.data = (unsigned char *)PORT_ZAlloc(4); - expitem.data[0] = (info->rsapubexp >> 24) & 0xff; - expitem.data[1] = (info->rsapubexp >> 16) & 0xff; - expitem.data[2] = (info->rsapubexp >> 8) & 0xff; - expitem.data[3] = (info->rsapubexp & 0xff); - TIMESTART(); - for (i=0; ikeysize*8, &expitem); - PORT_FreeArena(key->arena, PR_TRUE); - } - key = RSA_NewKey(info->keysize*8, &expitem); - TIMEFINISH("RSA KEY GEN", info->keysize); - rsakey_to_file(key, "tmp.key"); - } - if (key->modulus.data[0] == 0) { - /* integer value of input must be less than modulus */ - if (info->in.data[0] >= key->modulus.data[1]) - return SECFailure; - } else { - if (info->in.data[0] >= key->modulus.data[0]) - return SECFailure; - } - modLen = key->modulus.len - !key->modulus.data[0]; - if (info->in.len % modLen != 0) { - fprintf(stderr, "Input buffer must be a multiple of modulus length!\n"); - return SECFailure; - } - info->out.len = info->in.len; - info->out.data = (unsigned char *)PORT_ZAlloc(info->out.len); - if (info->encrypt) { - RSAPublicKey pubkey; - SECITEM_CopyItem(key->arena, &pubkey.modulus, &key->modulus); - SECITEM_CopyItem(key->arena, &pubkey.publicExponent, - &key->publicExponent); - TIMESTART(); - for (i=0; iin.len; j+=pubkey.modulus.len) { - rv = RSA_PublicKeyOp(&pubkey, &info->out.data[j], - &info->in.data[j]); - } - } - TIMEFINISH("RSA ENCRYPT", info->in.len); - CHECKERROR(rv, __LINE__); - } else { - TIMESTART(); - for (i=info->repetitions; i>0; i--) { - for (j=0; jin.len; j+=key->modulus.len) { - rv = RSA_PrivateKeyOp(key, &info->out.data[j], - &info->in.data[j]); - } - } - TIMEFINISH("RSA DECRYPT", info->in.len); - CHECKERROR(rv, __LINE__); - } - PORT_FreeArena(key->arena, PR_TRUE); - return SECSuccess; -} - -static SECStatus -pqg_test(blapitestInfo *info) -{ - SECStatus rv = SECSuccess; - PQGVerify *verify; - PRIntervalTime time1, time2; - int i, numiter; - numiter = info->repetitions; - if (info->pqg.len > 0) { - info->params = pqg_from_filedata(&info->pqg); - } else { - TIMESTART(); - for (i=0; ikeysize, &info->params, &verify); - PORT_FreeArena(info->params->arena, PR_TRUE); - } - rv = PQG_ParamGen(info->keysize, &info->params, &verify); - TIMEFINISH("PQG PARAM GEN", info->keysize); - pqg_to_file(info->params, "tmp.pqg"); - } - CHECKERROR(rv, __LINE__); - return rv; -} - -static SECStatus -dsa_test(blapitestInfo *info) -{ - DSAPrivateKey *key; - SECStatus rv = SECSuccess; - PRIntervalTime time1, time2; - int i, numiter; - numiter = info->repetitions; - fillitem(&info->in, info->bufsize, "tmp.pt"); - if (info->key.len > 0) { - key = dsakey_from_filedata(&info->key); - } else { - pqg_test(info); - if (info->useseed) { - if (info->seed.len == 0) - get_and_write_random_bytes(&info->seed, DSA_SUBPRIME_LEN, - "tmp.seed"); - rv = DSA_NewKeyFromSeed(info->params, info->seed.data, &key); - } else { - rv = DSA_NewKey(info->params, &key); - } - CHECKERROR(rv, __LINE__); - dsakey_to_file(key, "tmp.key"); - } - if (info->sign) { - info->out.len = DSA_SIGNATURE_LEN; - info->out.data = (unsigned char *)PORT_ZAlloc(info->out.len); - if (info->usesigseed) { - if (info->sigseed.len == 0) - get_and_write_random_bytes(&info->sigseed, DSA_SUBPRIME_LEN, - "tmp.sigseed"); - TIMESTART(); - rv = DSA_SignDigestWithSeed(key, &info->out, &info->in, - info->sigseed.data); - TIMEFINISH("DSA SIGN", info->in.len); - } else { - TIMESTART(); - for (i=0; iout, &info->in); - TIMEFINISH("DSA SIGN", info->in.len); - } - CHECKERROR(rv, __LINE__); - } else { - DSAPublicKey pubkey; - PRArenaPool *arena; - arena = key->params.arena; - SECITEM_CopyItem(arena, &pubkey.params.prime, &key->params.prime); - SECITEM_CopyItem(arena, &pubkey.params.subPrime, &key->params.subPrime); - SECITEM_CopyItem(arena, &pubkey.params.base, &key->params.base); - SECITEM_CopyItem(arena, &pubkey.publicValue, &key->publicValue); - TIMESTART(); - for (i=0; iout, &info->in); - TIMEFINISH("DSA VERIFY", info->in.len); - if (rv != SECSuccess) { - PR_fprintf(PR_STDOUT, "Signature failed verification!\n"); - CHECKERROR(rv, __LINE__); - } /*else { - PR_fprintf(PR_STDOUT, "Signature verified.\n"); - }*/ - } - PORT_FreeArena(key->params.arena, PR_TRUE); - return SECSuccess; -} - -static SECStatus -md5_multi_test(blapitestInfo *info) -{ - SECStatus rv = SECSuccess; - MD5Context *md5cx; - unsigned int len; - MD5Context *foomd5cx; - unsigned char *foomd5; - int i; - if (info->in.len == 0) { - rv = get_and_write_random_bytes(&info->in, info->bufsize, "tmp.pt"); - CHECKERROR(rv, __LINE__); - } - md5cx = MD5_NewContext(); - if (!md5cx) { - PR_fprintf(PR_STDERR, - "%s: Failed to create hash context!\n", progName); - return SECFailure; - } - info->out.len = MD5_LENGTH; - info->out.data = (unsigned char *)PORT_ZAlloc(info->out.len); - MD5_Begin(md5cx); - for (i=0; ibufsize/8; i++) { - MD5_Update(md5cx, &info->in.data[i*8], 8); - len = MD5_FlattenSize(md5cx); - foomd5 = PORT_Alloc(len); - MD5_Flatten(md5cx, foomd5); - foomd5cx = MD5_Resurrect(foomd5, NULL); - rv = PORT_Memcmp(foomd5cx, md5cx, len); - if (rv != SECSuccess) - PR_fprintf(PR_STDERR, "%s: MD5_Resurrect failed!\n", progName); - MD5_DestroyContext(foomd5cx, PR_TRUE); - PORT_Free(foomd5); - } - MD5_End(md5cx, info->out.data, &len, MD5_LENGTH); - if (len != MD5_LENGTH) - PR_fprintf(PR_STDERR, "%s: Bad hash size %d.\n", progName, len); - MD5_DestroyContext(md5cx, PR_TRUE); - return rv; -} - -static SECStatus -md5_test(blapitestInfo *info) -{ - SECStatus rv = SECSuccess; - PRIntervalTime time1, time2; - int i; - if (!info->hash) return SECFailure; - if (info->multihash) return md5_multi_test(info); - if (info->in.len == 0) { - rv = get_and_write_random_bytes(&info->in, info->bufsize, "tmp.pt"); - CHECKERROR(rv, __LINE__); - } - info->out.len = MD5_LENGTH; - info->out.data = (unsigned char *)PORT_ZAlloc(info->out.len); - TIMESTART(); - for (i=info->repetitions; i>0; i--) { - MD5_HashBuf(info->out.data, info->in.data, info->in.len); - } - TIMEFINISH("MD5 HASH", info->in.len); - return rv; -} - -static SECStatus -md2_multi_test(blapitestInfo *info) -{ - SECStatus rv = SECSuccess; - MD2Context *md2cx; - unsigned int len; - MD2Context *foomd2cx; - unsigned char *foomd2; - int i; - if (!info->hash) return SECFailure; - if (info->in.len == 0) { - rv = get_and_write_random_bytes(&info->in, info->bufsize, "tmp.pt"); - CHECKERROR(rv, __LINE__); - } - md2cx = MD2_NewContext(); - if (!md2cx) { - PR_fprintf(PR_STDERR, - "%s: Failed to create hash context!\n", progName); - return SECFailure; - } - info->out.len = MD2_LENGTH; - info->out.data = (unsigned char *)PORT_ZAlloc(info->out.len); - MD2_Begin(md2cx); - for (i=0; ibufsize/8; i++) { - MD2_Update(md2cx, &info->in.data[i*8], 8); - len = MD2_FlattenSize(md2cx); - foomd2 = PORT_Alloc(len); - MD2_Flatten(md2cx, foomd2); - foomd2cx = MD2_Resurrect(foomd2, NULL); - rv = PORT_Memcmp(foomd2cx, md2cx, len); - if (rv != SECSuccess) - PR_fprintf(PR_STDERR, "%s: MD2_Resurrect failed!\n", progName); - MD2_DestroyContext(foomd2cx, PR_TRUE); - PORT_Free(foomd2); - } - MD2_End(md2cx, info->out.data, &len, MD2_LENGTH); - if (len != MD2_LENGTH) - PR_fprintf(PR_STDERR, "%s: Bad hash size %d.\n", progName, len); - MD2_DestroyContext(md2cx, PR_TRUE); - return rv; -} - -static SECStatus -md2_test(blapitestInfo *info) -{ - unsigned int len; - MD2Context *cx = MD2_NewContext(); - SECStatus rv = SECSuccess; - PRIntervalTime time1, time2; - int i; - if (!info->hash) return SECFailure; - if (info->multihash) return md2_multi_test(info); - if (info->in.len == 0) { - rv = get_and_write_random_bytes(&info->in, info->bufsize, "tmp.pt"); - CHECKERROR(rv, __LINE__); - } - info->out.len = 16; - info->out.data = (unsigned char *)PORT_ZAlloc(info->out.len); - info->in.data[info->in.len] = '\0'; - TIMESTART(); - for (i=0; irepetitions; i++) { - MD2_Begin(cx); - MD2_Update(cx, info->in.data, info->in.len); - MD2_End(cx, info->out.data, &len, 16); - } - TIMEFINISH("MD2 HASH", info->in.len); - MD2_DestroyContext(cx, PR_TRUE); - return rv; -} - -static SECStatus -sha1_multi_test(blapitestInfo *info) -{ - SECStatus rv = SECSuccess; - SHA1Context *sha1cx; - unsigned int len; - SHA1Context *foosha1cx; - unsigned char *foosha1; - int i; - if (info->in.len == 0) { - rv = get_and_write_random_bytes(&info->in, info->bufsize, "tmp.pt"); - CHECKERROR(rv, __LINE__); - } - sha1cx = SHA1_NewContext(); - if (!sha1cx) { - PR_fprintf(PR_STDERR, - "%s: Failed to create hash context!\n", progName); - return SECFailure; - } - info->out.len = SHA1_LENGTH; - info->out.data = (unsigned char *)PORT_ZAlloc(info->out.len); - SHA1_Begin(sha1cx); - for (i=0; ibufsize/8; i++) { - SHA1_Update(sha1cx, &info->in.data[i*8], 8); - len = SHA1_FlattenSize(sha1cx); - foosha1 = PORT_Alloc(len); - SHA1_Flatten(sha1cx, foosha1); - foosha1cx = SHA1_Resurrect(foosha1, NULL); - rv = PORT_Memcmp(foosha1cx, sha1cx, len); - if (rv != SECSuccess) - PR_fprintf(PR_STDERR, "%s: SHA1_Resurrect failed!\n", progName); - SHA1_DestroyContext(foosha1cx, PR_TRUE); - PORT_Free(foosha1); - } - SHA1_End(sha1cx, info->out.data, &len, SHA1_LENGTH); - if (len != SHA1_LENGTH) - PR_fprintf(PR_STDERR, "%s: Bad hash size %d.\n", progName, len); - SHA1_DestroyContext(sha1cx, PR_TRUE); - return rv; -} - -static SECStatus -sha1_test(blapitestInfo *info) -{ - unsigned int len; - SHA1Context *cx = SHA1_NewContext(); - SECStatus rv = SECSuccess; - PRIntervalTime time1, time2; - int i; - if (!info->hash) return SECFailure; - if (info->multihash) return sha1_multi_test(info); - if (info->in.len == 0) { - rv = get_and_write_random_bytes(&info->in, info->bufsize, "tmp.pt"); - CHECKERROR(rv, __LINE__); - } - info->out.len = SHA1_LENGTH; - info->out.data = (unsigned char *)PORT_ZAlloc(info->out.len); - info->in.data[info->in.len] = '\0'; - TIMESTART(); - for (i=info->repetitions; i>0; i--) { - SHA1_Begin(cx); - SHA1_Update(cx, info->in.data, info->in.len); - SHA1_End(cx, info->out.data, &len, SHA1_LENGTH); - } - TIMEFINISH("SHA1 HASH", info->in.len); - SHA1_DestroyContext(cx, PR_TRUE); - return rv; -} - -typedef SECStatus (* blapitestCryptoFn)(blapitestInfo *); - -static blapitestCryptoFn crypto_fns[] = -{ - des_ecb_test, - des_cbc_test, - des_ede_ecb_test, - des_ede_cbc_test, - rc2_ecb_test, - rc2_cbc_test, - rc4_test, -#if NSS_SOFTOKEN_DOES_RC5 - rc5_ecb_test, - rc5_cbc_test, -#endif - rsa_test, - NULL, - pqg_test, - dsa_test, - NULL, - md5_test, - md2_test, - sha1_test, - NULL -}; +#define NUMMODES 14 static char *mode_strings[] = { - "des_ecb", - "des_cbc", - "des3_ecb", - "des3_cbc", - "rc2_ecb", - "rc2_cbc", - "rc4", -#if NSS_SOFTOKEN_DOES_RC5 - "rc5_ecb", - "rc5_cbc", -#endif - "rsa", - "#endencrypt", - "pqg", - "dsa", - "#endsign", - "md5", - "md2", - "sha1", - "#endhash" + "des_ecb", + "des_cbc", + "des3_ecb", + "des3_cbc", + "rc2_ecb", + "rc2_cbc", + "rc4", + "rc5_ecb", + "rc5_cbc", + "rsa", + /*"pqg",*/ + "dsa", + "md2", + "md5", + "sha1", }; -static void -printmodes(blapitestInfo *info) +typedef struct { - int i = 0; - char *mode = mode_strings[0]; - PR_fprintf(PR_STDERR, "Available modes: (specify with -m)\n", progName); - while (mode[0] != '#') { - if (info->encrypt || info->decrypt) - fprintf(stderr, "%s\n", mode); - mode = mode_strings[++i]; - } - mode = mode_strings[++i]; - while (mode[0] != '#') { - if (info->sign || info->verify) - fprintf(stderr, "%s\n", mode); - mode = mode_strings[++i]; - } - mode = mode_strings[++i]; - while (mode[0] != '#') { - if (info->hash) - fprintf(stderr, "%s\n", mode); - mode = mode_strings[++i]; - } + bltestIO key; + bltestIO iv; +} bltestSymmKeyParams; + +typedef struct +{ + bltestIO key; + bltestIO iv; + int rounds; + int wordsize; +} bltestRC5Params; + +typedef struct +{ + bltestIO key; + int keysizeInBits; + RSAPrivateKey *rsakey; +} bltestRSAParams; + +typedef struct +{ + bltestIO key; + bltestIO pqgdata; + unsigned int j; + bltestIO keyseed; + bltestIO sigseed; + bltestIO sig; /* if doing verify, have additional input */ + PQGParams *pqg; + DSAPrivateKey *dsakey; +} bltestDSAParams; + +typedef struct +{ + bltestIO key; /* unused */ + PRBool restart; +} bltestHashParams; + +typedef union +{ + bltestIO key; + bltestSymmKeyParams sk; + bltestRC5Params rc5; + bltestRSAParams rsa; + bltestDSAParams dsa; + bltestHashParams hash; +} bltestParams; + +typedef struct +{ + PRArenaPool *arena; + /* cipher context */ + void *cx; + /* I/O streams */ + bltestIO input; + bltestIO output; + /* Cipher-specific parameters */ + bltestParams params; + /* Cipher mode */ + bltestCipherMode mode; + /* Cipher function (encrypt/decrypt/sign/verify/hash) */ + union { + bltestSymmCipherFn symmkeyCipher; + bltestPubKeyCipherFn pubkeyCipher; + bltestHashCipherFn hashCipher; + } cipher; + /* performance testing */ + int repetitions; + int cxreps; + float cxtime; + float optime; +} bltestCipherInfo; + +PRBool +is_symmkeyCipher(bltestCipherMode mode) +{ + /* change as needed! */ + if (mode >= bltestDES_ECB && mode <= bltestRC5_CBC) + return PR_TRUE; + return PR_FALSE; } -static blapitestCryptoFn -get_test_mode(const char *modestring) +PRBool +is_pubkeyCipher(bltestCipherMode mode) { - int i; - int nummodes = sizeof(mode_strings) / sizeof(char *); - for (i=0; i= bltestRSA && mode <= bltestDSA) + return PR_TRUE; + return PR_FALSE; } -static void -get_params(blapitestInfo *info, char *mode, int num) +PRBool +is_hashCipher(bltestCipherMode mode) { - SECItem *item; - /* XXX - * this should use NSPR, but the string functions (strchr and atoi) - * barf when the commented code below is used. - PRFileDesc *file; - */ - FILE *file; - char filename[256]; - char *mark, *param, *val; - int index = 0; - int len; - sprintf(filename, "%s/tests/%s/params%d", testdir, mode, num); - /* - file = PR_Open(filename, PR_RDONLY, 00440); - if (file) - SECU_FileToItem(item, file); + /* change as needed! */ + if (mode >= bltestMD2 && mode <= bltestSHA1) + return PR_TRUE; + return PR_FALSE; +} + +PRBool +is_sigCipher(bltestCipherMode mode) +{ + /* change as needed! */ + if (mode >= bltestDSA && mode <= bltestDSA) + return PR_TRUE; + return PR_FALSE; +} + +PRBool +cipher_requires_IV(bltestCipherMode mode) +{ + /* change as needed! */ + if (mode == bltestDES_CBC || mode == bltestDES_EDE_CBC || + mode == bltestRC2_CBC || mode == bltestRC5_CBC) + return PR_TRUE; + return PR_FALSE; +} + +SECStatus finishIO(bltestIO *output, PRFileDesc *file); + +SECStatus +setupIO(PRArenaPool *arena, bltestIO *input, PRFileDesc *file, + char *str, int numBytes) +{ + SECStatus rv; + SECItem fileData; + SECItem *in; + unsigned char *tok; + int i, j; + + if (file && (numBytes == 0 || file == PR_STDIN)) { + /* grabbing data from a file */ + rv = SECU_FileToItem(&fileData, file); + if (rv != SECSuccess) { + PR_Close(file); + return SECFailure; + } + in = &fileData; + } else if (str) { + /* grabbing data from command line */ + fileData.data = str; + fileData.len = PL_strlen(str); + in = &fileData; + } else if (file) { + /* create nonce */ + SECITEM_AllocItem(arena, &input->buf, numBytes); + RNG_GenerateGlobalRandomBytes(input->buf.data, numBytes); + return finishIO(input, file); + } else { + return SECFailure; + } + + switch (input->mode) { + case bltestBase64Encoded: + rv = atob(in, &input->buf, arena); + break; + case bltestBinary: + if (in->data[in->len-1] == '\n') --in->len; + if (in->data[in->len-1] == '\r') --in->len; + SECITEM_CopyItem(arena, &input->buf, in); + break; + case bltestHexSpaceDelim: + SECITEM_AllocItem(arena, &input->buf, in->len/5); + for (i=0, j=0; ilen; i+=5, j++) { + tok = &in->data[i]; + if (tok[0] != '0' || tok[1] != 'x' || tok[4] != ' ') + /* bad hex token */ + break; + + rv = hex_from_2char(&tok[2], input->buf.data + j); + if (rv) + break; + } + break; + case bltestHexStream: + SECITEM_AllocItem(arena, &input->buf, in->len/2); + for (i=0, j=0; ilen; i+=2, j++) { + tok = &in->data[i]; + rv = hex_from_2char(tok, input->buf.data + j); + if (rv) + break; + } + break; + } + + if (file) + SECITEM_FreeItem(&fileData, PR_FALSE); + return rv; +} + +SECStatus +finishIO(bltestIO *output, PRFileDesc *file) +{ + SECStatus rv; + PRInt32 nb; + unsigned char byteval; + SECItem *it; + char hexstr[5]; + int i; + if (output->pBuf.len > 0) { + it = &output->pBuf; + } else { + it = &output->buf; + } + switch (output->mode) { + case bltestBase64Encoded: + rv = btoa_file(it, file); + break; + case bltestBinary: + nb = PR_Write(file, it->data, it->len); + rv = (nb == it->len) ? SECSuccess : SECFailure; + break; + case bltestHexSpaceDelim: + hexstr[0] = '0'; + hexstr[1] = 'x'; + hexstr[4] = ' '; + for (i=0; ilen; i++) { + byteval = it->data[i]; + rv = char2_from_hex(byteval, hexstr + 2); + nb = PR_Write(file, hexstr, 5); + if (rv) + break; + } + break; + case bltestHexStream: + for (i=0; ilen; i++) { + byteval = it->data[i]; + rv = char2_from_hex(byteval, hexstr); + if (rv) + break; + nb = PR_Write(file, hexstr, 2); + } + break; + } + return rv; +} + +void +bltestCopyIO(PRArenaPool *arena, bltestIO *dest, bltestIO *src) +{ + SECITEM_CopyItem(arena, &dest->buf, &src->buf); + if (src->pBuf.len > 0) { + dest->pBuf.len = src->pBuf.len; + dest->pBuf.data = dest->buf.data + (src->pBuf.data - src->buf.data); + } + dest->mode = src->mode; + dest->file = src->file; +} + +void +misalignBuffer(PRArenaPool *arena, bltestIO *io, int off) +{ + ptrdiff_t offset = (ptrdiff_t)io->buf.data % WORDSIZE; + int length = io->buf.len; + if (offset != off) { + SECITEM_ReallocItem(arena, &io->buf, length, length + 2*WORDSIZE); + /* offset may have changed? */ + offset = (ptrdiff_t)io->buf.data % WORDSIZE; + if (offset != off) { + memmove(io->buf.data + off, io->buf.data, length); + io->pBuf.data = io->buf.data + off; + io->pBuf.len = length; + } else { + io->pBuf.data = io->buf.data; + io->pBuf.len = length; + } + } else { + io->pBuf.data = io->buf.data; + io->pBuf.len = length; + } +} + +SECStatus +bltest_des_init(bltestCipherInfo *cipherInfo, PRBool encrypt) +{ + PRIntervalTime time1, time2; + bltestSymmKeyParams *desp = &cipherInfo->params.sk; + int minorMode; + int i; + switch (cipherInfo->mode) { + case bltestDES_ECB: minorMode = NSS_DES; break; + case bltestDES_CBC: minorMode = NSS_DES_CBC; break; + case bltestDES_EDE_ECB: minorMode = NSS_DES_EDE3; break; + case bltestDES_EDE_CBC: minorMode = NSS_DES_EDE3_CBC; break; + default: + return SECFailure; + } + cipherInfo->cx = (void*)DES_CreateContext(desp->key.buf.data, + desp->iv.buf.data, + minorMode, encrypt); + if (cipherInfo->cxreps > 0) { + DESContext **dummycx; + dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(DESContext *)); + TIMESTART(); + for (i=0; icxreps; i++) { + dummycx[i] = (void*)DES_CreateContext(desp->key.buf.data, + desp->iv.buf.data, + minorMode, encrypt); + } + TIMEFINISH(cipherInfo->cxtime, 1.0); + for (i=0; icxreps; i++) { + DES_DestroyContext(dummycx[i], PR_TRUE); + } + PORT_Free(dummycx); + } + if (encrypt) + cipherInfo->cipher.symmkeyCipher = DES_Encrypt; + else + cipherInfo->cipher.symmkeyCipher = DES_Decrypt; + return SECSuccess; +} + +SECStatus +bltest_rc2_init(bltestCipherInfo *cipherInfo, PRBool encrypt) +{ + PRIntervalTime time1, time2; + bltestSymmKeyParams *rc2p = &cipherInfo->params.sk; + int minorMode; + int i; + switch (cipherInfo->mode) { + case bltestRC2_ECB: minorMode = NSS_RC2; break; + case bltestRC2_CBC: minorMode = NSS_RC2_CBC; break; + default: + return SECFailure; + } + cipherInfo->cx = (void*)RC2_CreateContext(rc2p->key.buf.data, + rc2p->key.buf.len, + rc2p->iv.buf.data, + minorMode, + rc2p->key.buf.len); + if (cipherInfo->cxreps > 0) { + RC2Context **dummycx; + dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(RC2Context *)); + TIMESTART(); + for (i=0; icxreps; i++) { + dummycx[i] = (void*)RC2_CreateContext(rc2p->key.buf.data, + rc2p->key.buf.len, + rc2p->iv.buf.data, + minorMode, + rc2p->key.buf.len); + } + TIMEFINISH(cipherInfo->cxtime, 1.0); + for (i=0; icxreps; i++) { + RC2_DestroyContext(dummycx[i], PR_TRUE); + } + PORT_Free(dummycx); + } + if (encrypt) + cipherInfo->cipher.symmkeyCipher = RC2_Encrypt; + else + cipherInfo->cipher.symmkeyCipher = RC2_Decrypt; + return SECSuccess; +} + +SECStatus +bltest_rc4_init(bltestCipherInfo *cipherInfo, PRBool encrypt) +{ + PRIntervalTime time1, time2; + int i; + bltestSymmKeyParams *rc4p = &cipherInfo->params.sk; + cipherInfo->cx = (void*)RC4_CreateContext(rc4p->key.buf.data, + rc4p->key.buf.len); + if (cipherInfo->cxreps > 0) { + RC4Context **dummycx; + dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(RC4Context *)); + TIMESTART(); + for (i=0; icxreps; i++) { + dummycx[i] = (void*)RC4_CreateContext(rc4p->key.buf.data, + rc4p->key.buf.len); + } + TIMEFINISH(cipherInfo->cxtime, 1.0); + for (i=0; icxreps; i++) { + RC4_DestroyContext(dummycx[i], PR_TRUE); + } + PORT_Free(dummycx); + } + if (encrypt) + cipherInfo->cipher.symmkeyCipher = RC4_Encrypt; + else + cipherInfo->cipher.symmkeyCipher = RC4_Decrypt; + return SECSuccess; +} + +SECStatus +bltest_rc5_init(bltestCipherInfo *cipherInfo, PRBool encrypt) +{ +#if NSS_SOFTOKEN_DOES_RC5 + PRIntervalTime time1, time2; + bltestRC5Params *rc5p = &cipherInfo->params.rc5; + int minorMode; + switch (cipherInfo->mode) { + case bltestRC5_ECB: minorMode = NSS_RC5; break; + case bltestRC5_CBC: minorMode = NSS_RC5_CBC; break; + default: + return SECFailure; + } + TIMESTART(); + cipherInfo->cx = (void*)RC5_CreateContext(&rc5p->key.buf, + rc5p->rounds, rc5p->wordsize, + rc5p->iv.buf.data, minorMode); + TIMEFINISH(cipherInfo->cxtime, 1.0); + if (encrypt) + cipherInfo->cipher.symmkeyCipher = RC5_Encrypt; + else + cipherInfo->cipher.symmkeyCipher = RC5_Decrypt; + return SECSuccess; +#else + return SECFailure; +#endif +} + +SECStatus +bltest_rsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt) +{ + int i; + RSAPrivateKey **dummyKey; + PRIntervalTime time1, time2; + bltestRSAParams *rsap = &cipherInfo->params.rsa; + /* RSA key gen was done during parameter setup */ + cipherInfo->cx = cipherInfo->params.rsa.rsakey; + /* For performance testing */ + if (cipherInfo->cxreps > 0) { + /* Create space for n private key objects */ + dummyKey = (RSAPrivateKey **)PORT_Alloc(cipherInfo->cxreps * + sizeof(RSAPrivateKey *)); + /* Time n keygens, storing in the array */ + TIMESTART(); + for (i=0; icxreps; i++) + dummyKey[i] = RSA_NewKey(rsap->keysizeInBits, + &rsap->rsakey->publicExponent); + TIMEFINISH(cipherInfo->cxtime, cipherInfo->cxreps); + /* Free the n key objects */ + for (i=0; icxreps; i++) + PORT_FreeArena(dummyKey[i]->arena, PR_TRUE); + PORT_Free(dummyKey); + } + if (encrypt) { + /* Have to convert private key to public key. Memory + * is freed with private key's arena */ + RSAPublicKey *pubkey; + RSAPrivateKey *key = (RSAPrivateKey *)cipherInfo->cx; + pubkey = (RSAPublicKey *)PORT_ArenaAlloc(key->arena, + sizeof(RSAPublicKey)); + pubkey->modulus.len = key->modulus.len; + pubkey->modulus.data = key->modulus.data; + pubkey->publicExponent.len = key->publicExponent.len; + pubkey->publicExponent.data = key->publicExponent.data; + cipherInfo->cx = (void *)pubkey; + cipherInfo->cipher.pubkeyCipher = RSA_PublicKeyOp; + } else { + cipherInfo->cipher.pubkeyCipher = RSA_PrivateKeyOp; + } + return SECSuccess; +} + +SECStatus +bltest_pqg_init(bltestDSAParams *dsap) +{ + SECStatus rv, res; + PQGVerify *vfy = NULL; + rv = PQG_ParamGen(dsap->j, &dsap->pqg, &vfy); + CHECKERROR(rv, __LINE__); + rv = PQG_VerifyParams(dsap->pqg, vfy, &res); + CHECKERROR(res, __LINE__); + CHECKERROR(rv, __LINE__); + return rv; +} + +SECStatus +bltest_dsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt) +{ + int i; + DSAPrivateKey **dummyKey; + PQGParams *dummypqg; + PRIntervalTime time1, time2; + bltestDSAParams *dsap = &cipherInfo->params.dsa; + PQGVerify *ignore = NULL; + /* DSA key gen was done during parameter setup */ + cipherInfo->cx = cipherInfo->params.dsa.dsakey; + /* For performance testing */ + if (cipherInfo->cxreps > 0) { + /* Create space for n private key objects */ + dummyKey = (DSAPrivateKey **)PORT_ZAlloc(cipherInfo->cxreps * + sizeof(DSAPrivateKey *)); + /* Time n keygens, storing in the array */ + TIMESTART(); + for (i=0; icxreps; i++) { + dummypqg = NULL; + PQG_ParamGen(dsap->j, &dummypqg, &ignore); + DSA_NewKey(dummypqg, &dummyKey[i]); + } + TIMEFINISH(cipherInfo->cxtime, cipherInfo->cxreps); + /* Free the n key objects */ + for (i=0; icxreps; i++) + PORT_FreeArena(dummyKey[i]->params.arena, PR_TRUE); + PORT_Free(dummyKey); + } + if (!dsap->pqg && dsap->pqgdata.buf.len > 0) { + dsap->pqg = pqg_from_filedata(&dsap->pqgdata.buf); + } + if (!cipherInfo->cx && dsap->key.buf.len > 0) { + cipherInfo->cx = dsakey_from_filedata(&dsap->key.buf); + } + if (encrypt) { + cipherInfo->cipher.pubkeyCipher = DSA_SignDigest; + } else { + /* Have to convert private key to public key. Memory + * is freed with private key's arena */ + DSAPublicKey *pubkey; + DSAPrivateKey *key = (DSAPrivateKey *)cipherInfo->cx; + pubkey = (DSAPublicKey *)PORT_ArenaZAlloc(key->params.arena, + sizeof(DSAPublicKey)); + pubkey->params.prime.len = key->params.prime.len; + pubkey->params.prime.data = key->params.prime.data; + pubkey->params.subPrime.len = key->params.subPrime.len; + pubkey->params.subPrime.data = key->params.subPrime.data; + pubkey->params.base.len = key->params.base.len; + pubkey->params.base.data = key->params.base.data; + pubkey->publicValue.len = key->publicValue.len; + pubkey->publicValue.data = key->publicValue.data; + cipherInfo->cipher.pubkeyCipher = DSA_VerifyDigest; + } + return SECSuccess; +} + +/* XXX unfortunately, this is not defined in blapi.h */ +SECStatus +md2_HashBuf(unsigned char *dest, const unsigned char *src, PRUint32 src_length) +{ + unsigned int len; + MD2Context *cx = MD2_NewContext(); + if (cx == NULL) return SECFailure; + MD2_Begin(cx); + MD2_Update(cx, src, src_length); + MD2_End(cx, dest, &len, MD2_LENGTH); + MD2_DestroyContext(cx, PR_TRUE); + return SECSuccess; +} + +SECStatus +md2_restart(unsigned char *dest, const unsigned char *src, PRUint32 src_length) +{ + MD2Context *cx, *cx_cpy; + unsigned char *cxbytes; + unsigned char *psrc = src; + unsigned int len; + int i, quarter; + SECStatus rv; + cx = MD2_NewContext(); + /* divide message by 4, restarting 3 times */ + quarter = src_length / 4; + for (i=0; i<4; i++) { + MD2_Update(cx, psrc, PR_MIN(quarter, src_length)); + len = MD2_FlattenSize(cx); + cxbytes = PORT_Alloc(len); + MD2_Flatten(cx, cxbytes); + cx_cpy = MD2_Resurrect(cxbytes, NULL); + if (!cx_cpy) { + PR_fprintf(PR_STDERR, "%s: MD2_Resurrect failed!\n", progName); + goto finish; + } + rv = PORT_Memcmp(cx, cx_cpy, len); + if (rv) { + MD2_DestroyContext(cx_cpy, PR_TRUE); + PR_fprintf(PR_STDERR, "%s: MD2_Resurrect failed!\n", progName); + goto finish; + } + MD2_DestroyContext(cx_cpy, PR_TRUE); + PORT_Free(cxbytes); + psrc += quarter; + src_length -= quarter; + } + MD2_End(cx, dest, &len, MD2_LENGTH); +finish: + MD2_DestroyContext(cx, PR_TRUE); + return rv; +} + +SECStatus +md5_restart(unsigned char *dest, const unsigned char *src, PRUint32 src_length) +{ + SECStatus rv; + MD5Context *cx, *cx_cpy; + unsigned char *cxbytes; + unsigned char *psrc = src; + unsigned int len; + int quarter; + int i; + cx = MD5_NewContext(); + /* divide message by 4, restarting 3 times */ + quarter = src_length / 4; + for (i=0; i<4; i++) { + MD5_Update(cx, psrc, PR_MIN(quarter, src_length)); + len = MD5_FlattenSize(cx); + cxbytes = PORT_Alloc(len); + MD5_Flatten(cx, cxbytes); + cx_cpy = MD5_Resurrect(cxbytes, NULL); + if (!cx_cpy) { + PR_fprintf(PR_STDERR, "%s: MD5_Resurrect failed!\n", progName); + goto finish; + } + rv = PORT_Memcmp(cx, cx_cpy, len); + if (rv) { + MD5_DestroyContext(cx_cpy, PR_TRUE); + PR_fprintf(PR_STDERR, "%s: MD5_Resurrect failed!\n", progName); + goto finish; + } + MD5_DestroyContext(cx_cpy, PR_TRUE); + PORT_Free(cxbytes); + psrc += quarter; + src_length -= quarter; + } + MD5_End(cx, dest, &len, MD5_LENGTH); +finish: + MD5_DestroyContext(cx, PR_TRUE); + return rv; +} + +SECStatus +sha1_restart(unsigned char *dest, const unsigned char *src, PRUint32 src_length) +{ + SECStatus rv; + SHA1Context *cx, *cx_cpy; + unsigned char *cxbytes; + unsigned char *psrc = src; + unsigned int len; + int quarter; + int i; + cx = SHA1_NewContext(); + /* divide message by 4, restarting 3 times */ + quarter = src_length / 4; + for (i=0; i<4; i++) { + SHA1_Update(cx, psrc, PR_MIN(quarter, src_length)); + len = SHA1_FlattenSize(cx); + cxbytes = PORT_Alloc(len); + SHA1_Flatten(cx, cxbytes); + cx_cpy = SHA1_Resurrect(cxbytes, NULL); + if (!cx_cpy) { + PR_fprintf(PR_STDERR, "%s: SHA1_Resurrect failed!\n", progName); + goto finish; + } + rv = PORT_Memcmp(cx, cx_cpy, len); + if (rv) { + SHA1_DestroyContext(cx_cpy, PR_TRUE); + PR_fprintf(PR_STDERR, "%s: SHA1_Resurrect failed!\n", progName); + goto finish; + } + SHA1_DestroyContext(cx_cpy, PR_TRUE); + PORT_Free(cxbytes); + psrc += quarter; + src_length -= quarter; + } + SHA1_End(cx, dest, &len, MD5_LENGTH); +finish: + SHA1_DestroyContext(cx, PR_TRUE); + return rv; +} + +SECStatus +pubkeyInitKey(bltestCipherInfo *cipherInfo, PRFileDesc *file, + int keysize, int exponent) +{ + int i; + SECStatus rv; + bltestRSAParams *rsap; + bltestDSAParams *dsap; + switch (cipherInfo->mode) { + case bltestRSA: + rsap = &cipherInfo->params.rsa; + if (keysize > 0) { + SECItem expitem = { 0, 0, 0 }; + SECITEM_AllocItem(cipherInfo->arena, &expitem, sizeof(int)); + for (i = 1; i <= sizeof(int); i++) + expitem.data[i-1] = exponent >> (8*(sizeof(int) - i)); + rsap->rsakey = RSA_NewKey(keysize * 8, &expitem); + serialize_key(&rsap->rsakey->version, 9, file); + rsap->keysizeInBits = keysize * 8; + } else { + setupIO(cipherInfo->arena, &cipherInfo->params.key, file, NULL, 0); + rsap->rsakey = rsakey_from_filedata(&cipherInfo->params.key.buf); + rsap->keysizeInBits = rsap->rsakey->modulus.len * 8; + } + break; + case bltestDSA: + dsap = &cipherInfo->params.dsa; + if (keysize > 0) { + dsap->j = PQG_PBITS_TO_INDEX(8*keysize); + if (!dsap->pqg) + bltest_pqg_init(dsap); + rv = DSA_NewKey(dsap->pqg, &dsap->dsakey); + CHECKERROR(rv, __LINE__); + serialize_key(&dsap->dsakey->params.prime, 5, file); + } else { + setupIO(cipherInfo->arena, &cipherInfo->params.key, file, NULL, 0); + dsap->dsakey = dsakey_from_filedata(&cipherInfo->params.key.buf); + dsap->j = PQG_PBITS_TO_INDEX(8*dsap->dsakey->params.prime.len); + } + break; + default: + return SECFailure; + } + return SECSuccess; +} + +SECStatus +cipherInit(bltestCipherInfo *cipherInfo, PRBool encrypt) +{ + PRBool restart; + switch (cipherInfo->mode) { + case bltestDES_ECB: + case bltestDES_CBC: + case bltestDES_EDE_ECB: + case bltestDES_EDE_CBC: + SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, + cipherInfo->input.pBuf.len); + return bltest_des_init(cipherInfo, encrypt); + break; + case bltestRC2_ECB: + case bltestRC2_CBC: + SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, + cipherInfo->input.pBuf.len); + return bltest_rc2_init(cipherInfo, encrypt); + break; + case bltestRC4: + SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, + cipherInfo->input.pBuf.len); + return bltest_rc4_init(cipherInfo, encrypt); + break; + case bltestRC5_ECB: + case bltestRC5_CBC: +#if NSS_SOFTOKEN_DOES_RC5 + SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, + cipherInfo->input.pBuf.len); +#endif + return bltest_rc5_init(cipherInfo, encrypt); + break; + case bltestRSA: + SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, + cipherInfo->input.pBuf.len); + return bltest_rsa_init(cipherInfo, encrypt); + break; + case bltestDSA: + SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, + DSA_SIGNATURE_LEN); + return bltest_dsa_init(cipherInfo, encrypt); + break; + case bltestMD2: + restart = cipherInfo->params.hash.restart; + SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, + MD2_LENGTH); + cipherInfo->cipher.hashCipher = (restart) ? md2_restart : md2_HashBuf; + return (cipherInfo->cx != NULL) ? SECSuccess : SECFailure; + break; + case bltestMD5: + restart = cipherInfo->params.hash.restart; + SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, + MD5_LENGTH); + cipherInfo->cipher.hashCipher = (restart) ? md5_restart : MD5_HashBuf; + return (cipherInfo->cx != NULL) ? SECSuccess : SECFailure; + break; + case bltestSHA1: + restart = cipherInfo->params.hash.restart; + SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, + SHA1_LENGTH); + cipherInfo->cipher.hashCipher = (restart) ? sha1_restart : SHA1_HashBuf; + return (cipherInfo->cx != NULL) ? SECSuccess : SECFailure; + break; + default: + return SECFailure; + } + return SECSuccess; +} + +SECStatus +dsaOp(bltestCipherInfo *cipherInfo) +{ + PRIntervalTime time1, time2; + SECStatus rv; + int i; + int maxLen = cipherInfo->output.pBuf.len; + SECItem dummyOut = { 0, 0, 0 }; + SECITEM_AllocItem(NULL, &dummyOut, maxLen); + if (cipherInfo->cipher.pubkeyCipher == + (bltestPubKeyCipherFn)DSA_SignDigest) { + if (cipherInfo->params.dsa.sigseed.buf.len > 0) { + rv = DSA_SignDigestWithSeed((DSAPrivateKey *)cipherInfo->cx, + &cipherInfo->output.pBuf, + &cipherInfo->input.pBuf, + cipherInfo->params.dsa.sigseed.buf.data); + CHECKERROR(rv, __LINE__); + TIMESTART(); + for (i=0; irepetitions; i++) { + rv |= DSA_SignDigestWithSeed((DSAPrivateKey *)cipherInfo->cx, + &dummyOut, + &cipherInfo->input.pBuf, + cipherInfo->params.dsa.sigseed.buf.data); + } + TIMEFINISH(cipherInfo->optime, 1.0); + CHECKERROR(rv, __LINE__); + } else { + rv = DSA_SignDigest((DSAPrivateKey *)cipherInfo->cx, + &cipherInfo->output.pBuf, + &cipherInfo->input.pBuf); + CHECKERROR(rv, __LINE__); + TIMESTART(); + for (i=0; irepetitions; i++) { + DSA_SignDigest((DSAPrivateKey *)cipherInfo->cx, &dummyOut, + &cipherInfo->input.pBuf); + } + TIMEFINISH(cipherInfo->optime, 1.0); + } + bltestCopyIO(cipherInfo->arena, &cipherInfo->params.dsa.sig, + &cipherInfo->output); + } else { + rv = DSA_VerifyDigest((DSAPublicKey *)cipherInfo->cx, + &cipherInfo->params.dsa.sig.buf, + &cipherInfo->input.pBuf); + CHECKERROR(rv, __LINE__); + TIMESTART(); + for (i=0; irepetitions; i++) { + DSA_VerifyDigest((DSAPublicKey *)cipherInfo->cx, + &cipherInfo->params.dsa.sig.buf, + &cipherInfo->input.pBuf); + } + TIMEFINISH(cipherInfo->optime, 1.0); + } + SECITEM_FreeItem(&dummyOut, PR_FALSE); + return rv; +} + +SECStatus +cipherDoOp(bltestCipherInfo *cipherInfo) +{ + PRIntervalTime time1, time2; + SECStatus rv; + int i, len; + int maxLen = cipherInfo->output.pBuf.len; + unsigned char *dummyOut; + if (cipherInfo->mode == bltestDSA) + return dsaOp(cipherInfo); + dummyOut = PORT_Alloc(maxLen); + if (is_symmkeyCipher(cipherInfo->mode)) { + rv = (*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx, + cipherInfo->output.pBuf.data, + &len, maxLen, + cipherInfo->input.pBuf.data, + cipherInfo->input.pBuf.len); + TIMESTART(); + for (i=0; irepetitions; i++) { + (*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx, dummyOut, + &len, maxLen, + cipherInfo->input.pBuf.data, + cipherInfo->input.pBuf.len); + + } + TIMEFINISH(cipherInfo->optime, 1.0); + } else if (is_pubkeyCipher(cipherInfo->mode)) { + rv = (*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx, + cipherInfo->output.pBuf.data, + cipherInfo->input.pBuf.data); + TIMESTART(); + for (i=0; irepetitions; i++) { + (*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx, dummyOut, + cipherInfo->input.pBuf.data); + } + TIMEFINISH(cipherInfo->optime, 1.0); + } else if (is_hashCipher(cipherInfo->mode)) { + rv = (*cipherInfo->cipher.hashCipher)(cipherInfo->output.pBuf.data, + cipherInfo->input.pBuf.data, + cipherInfo->input.pBuf.len); + TIMESTART(); + for (i=0; irepetitions; i++) { + (*cipherInfo->cipher.hashCipher)(dummyOut, + cipherInfo->input.pBuf.data, + cipherInfo->input.pBuf.len); + } + TIMEFINISH(cipherInfo->optime, 1.0); + } + PORT_Free(dummyOut); + return rv; +} + +SECStatus +cipherFinish(bltestCipherInfo *cipherInfo) +{ + switch (cipherInfo->mode) { + case bltestDES_ECB: + case bltestDES_CBC: + case bltestDES_EDE_ECB: + case bltestDES_EDE_CBC: + DES_DestroyContext((DESContext *)cipherInfo->cx, PR_TRUE); + break; + case bltestRC2_ECB: + case bltestRC2_CBC: + RC2_DestroyContext((RC2Context *)cipherInfo->cx, PR_TRUE); + break; + case bltestRC4: + RC4_DestroyContext((RC4Context *)cipherInfo->cx, PR_TRUE); + break; +#if NSS_SOFTOKEN_DOES_RC5 + case bltestRC5_ECB: + case bltestRC5_CBC: + RC5_DestroyContext((RC5Context *)cipherInfo->cx, PR_TRUE); + break; +#endif + case bltestRSA: /* keys are alloc'ed within cipherInfo's arena, */ + case bltestDSA: /* will be freed with it. */ + case bltestMD2: /* hash contexts are ephemeral */ + case bltestMD5: + case bltestSHA1: + return SECSuccess; + break; + default: + return SECFailure; + } + return SECSuccess; +} + +void +print_exponent(SECItem *exp) +{ + int i; + int e = 0; + if (exp->len <= 4) { + for (i=exp->len; i >=0; --i) e |= exp->data[exp->len-i] << 8*(i-1); + fprintf(stdout, "%12d", e); + } else { + e = 8*exp->len; + fprintf(stdout, "~2**%-8d", e); + } +} + +void +dump_performance_info(bltestCipherInfo *info, PRBool encrypt, PRBool cxonly) +{ + PRBool td = PR_TRUE; + fprintf(stdout, "#%9s", "mode"); + fprintf(stdout, "%12s", "in"); +print_td: + switch (info->mode) { + case bltestDES_ECB: + case bltestDES_CBC: + case bltestDES_EDE_ECB: + case bltestDES_EDE_CBC: + case bltestRC2_ECB: + case bltestRC2_CBC: + case bltestRC4: + if (td) + fprintf(stdout, "%8s", "symmkey"); else - return; - param = (char *)item->data; - */ + fprintf(stdout, "%8d", 8*info->params.sk.key.buf.len); + break; +#if NSS_SOFTOKEN_DOES_RC5 + case bltestRC5_ECB: + case bltestRC5_CBC: + if (info->params.sk.key.buf.len > 0) + printf("symmetric key(bytes)=%d,", info->params.sk.key.buf.len); + if (info->rounds > 0) + printf("rounds=%d,", info->params.rc5.rounds); + if (info->wordsize > 0) + printf("wordsize(bytes)=%d,", info->params.rc5.wordsize); + break; +#endif + case bltestRSA: + if (td) { + fprintf(stdout, "%8s", "rsa_mod"); + fprintf(stdout, "%12s", "rsa_pe"); + } else { + fprintf(stdout, "%8d", info->params.rsa.keysizeInBits); + print_exponent(&info->params.rsa.rsakey->publicExponent); + } + break; + case bltestDSA: + if (td) + fprintf(stdout, "%8s", "pqg_mod"); + else + fprintf(stdout, "%8d", PQG_INDEX_TO_PBITS(info->params.dsa.j)); + break; + case bltestMD2: + case bltestMD5: + case bltestSHA1: + default: + break; + } + if (!td) { + fprintf(stdout, "%8d", info->repetitions); + fprintf(stdout, "%8d", info->cxreps); + fprintf(stdout, "%10.3f", info->cxtime); + fprintf(stdout, "%10.3f", info->optime); + fprintf(stdout, "\n"); + return; + } + + fprintf(stdout, "%8s", "opreps"); + fprintf(stdout, "%8s", "cxreps"); + fprintf(stdout, "%10s", "context"); + fprintf(stdout, "%10s", "op"); + fprintf(stdout, "\n"); + fprintf(stdout, "%8s", mode_strings[info->mode]); + fprintf(stdout, "_%c", (cxonly) ? 'c' : (encrypt) ? 'e' : 'd'); + fprintf(stdout, "%12d", info->input.buf.len * info->repetitions); + + td = !td; + goto print_td; +} + +void +printmodes() +{ + bltestCipherMode mode; + int nummodes = sizeof(mode_strings) / sizeof(char *); + fprintf(stderr, "%s: Available modes (specify with -m):\n", progName); + for (mode=0; modemode = ioMode; + data->file = NULL; /* don't use -- not saving anything */ + data->pBuf.data = NULL; + data->pBuf.len = 0; + file = PR_Open(fn, PR_RDONLY, 00660); + if (file) + setupIO(arena, data, file, NULL, 0); +} + +void +get_params(PRArenaPool *arena, bltestParams *params, + bltestCipherMode mode, int j) +{ + char filename[256]; + char *modestr = mode_strings[mode]; +#if NSS_SOFTOKEN_DOES_RC5 + FILE *file; + char *mark, *param, *val; + int index = 0; +#endif + switch (mode) { + case bltestDES_CBC: + case bltestDES_EDE_CBC: + case bltestRC2_CBC: + sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "iv", j); + load_file_data(arena, ¶ms->sk.iv, filename, bltestBinary); + case bltestDES_ECB: + case bltestDES_EDE_ECB: + case bltestRC2_ECB: + case bltestRC4: + sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j); + load_file_data(arena, ¶ms->sk.key, filename, bltestBinary); + break; +#if NSS_SOFTOKEN_DOES_RC5 + case bltestRC5_ECB: + case bltestRC5_CBC: + sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "iv", j); + load_file_data(arena, ¶ms->sk.iv, filename, bltestBinary); + sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j); + load_file_data(arena, ¶ms->sk.key, filename, bltestBinary); + sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, + "params", j); file = fopen(filename, "r"); if (!file) return; param = malloc(100); len = fread(param, 1, 100, file); while (index < len) { - mark = PL_strchr(param, '='); - *mark = '\0'; - val = mark + 1; - mark = PL_strchr(val, '\n'); - *mark = '\0'; - if (PL_strcmp(param, "rounds") == 0) { - info->rounds = atoi(val); - } else if (PL_strcmp(param, "wordsize") == 0) { - info->wordsize = atoi(val); - } - index += PL_strlen(param) + PL_strlen(val) + 2; - param = mark + 1; + mark = PL_strchr(param, '='); + *mark = '\0'; + val = mark + 1; + mark = PL_strchr(val, '\n'); + *mark = '\0'; + if (PL_strcmp(param, "rounds") == 0) { + params->rc5.rounds = atoi(val); + } else if (PL_strcmp(param, "wordsize") == 0) { + params->rc5.wordsize = atoi(val); + } + index += PL_strlen(param) + PL_strlen(val) + 2; + param = mark + 1; } -} - -static SECStatus -get_ascii_file_data(SECItem *item, char *mode, char *type, int num) -{ - char filename[256]; - PRFileDesc *file; - SECStatus rv; - sprintf(filename, "%s/tests/%s/%s%d", testdir, mode, type, num); - file = PR_Open(filename, PR_RDONLY, 00440); - if (!file) { - /* Not a failure if "mode" does not need "type". */ - return SECSuccess; - } - if (((PL_strcmp(mode, "rsa") == 0 || PL_strcmp(mode, "dsa") == 0) && - PL_strcmp(type, "key") == 0) || - (PL_strcmp(mode, "dsa") == 0 && PL_strcmp(type, "plaintext") == 0)) { - rv = SECU_FileToItem(item, file); - atob(SECITEM_DupItem(item), item); - } else { - rv = SECU_TextFileToItem(item, file); - } - PR_Close(file); - return rv; -} - -static SECStatus -blapi_selftest(char **modesToTest, int numModesToTest, - PRBool encrypt, PRBool decrypt) -{ - blapitestCryptoFn cryptofn; - blapitestInfo info; - SECItem output = { 0, 0, 0 }; - SECItem asciiOut = { 0, 0, 0 }; - SECItem inpCopy = { 0, 0, 0 }; - SECItem item = { 0, 0, 0 }; - SECStatus rv; - char filename[256]; - PRFileDesc *file; - char *mode; - int i, j, nummodes; - - RNG_RNGInit(); - RNG_SystemInfoForRNG(); - PORT_Memset(&info, 0, sizeof(info)); - info.repetitions = 1; - info.useseed = PR_TRUE; - info.usesigseed = PR_TRUE; - if (modesToTest) { - /* user gave a list of modes to test */ - nummodes = numModesToTest; - } else { - /* test all modes */ - nummodes = sizeof(mode_strings) / sizeof(char *); - } - for (i=0; irsa.key, filename, bltestBase64Encoded); + params->rsa.rsakey = rsakey_from_filedata(¶ms->key.buf); + break; + case bltestDSA: + sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j); + load_file_data(arena, ¶ms->dsa.key, filename, bltestBase64Encoded); + params->dsa.dsakey = dsakey_from_filedata(¶ms->key.buf); + sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "pqg", j); + load_file_data(arena, ¶ms->dsa.pqgdata, filename, + bltestBase64Encoded); + params->dsa.pqg = pqg_from_filedata(¶ms->dsa.pqgdata.buf); + sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "keyseed", j); + load_file_data(arena, ¶ms->dsa.keyseed, filename, + bltestBase64Encoded); + sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "sigseed", j); + load_file_data(arena, ¶ms->dsa.sigseed, filename, + bltestBase64Encoded); + sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "ciphertext",j); + load_file_data(arena, ¶ms->dsa.sig, filename, bltestBase64Encoded); + break; + case bltestMD2: + case bltestMD5: + case bltestSHA1: + /*params->hash.restart = PR_TRUE;*/ + params->hash.restart = PR_FALSE; + break; + default: + break; + } } SECStatus -dump_file(char *mode, char *filename) +verify_self_test(bltestIO *result, bltestIO *cmp, bltestCipherMode mode, + PRBool forward, SECStatus sigstatus) { - SECItem item; - if (PL_strcmp(mode, "rsa") == 0) { - RSAPrivateKey *key; - get_file_data(filename, &item, PR_TRUE); - key = rsakey_from_filedata(&item); - dump_rsakey(key); - } else if (PL_strcmp(mode, "pqg") == 0) { - PQGParams *pqg; - get_file_data(filename, &item, PR_TRUE); - pqg = pqg_from_filedata(&item); - dump_pqg(pqg); - } else if (PL_strcmp(mode, "dsa") == 0) { - DSAPrivateKey *key; - get_file_data(filename, &item, PR_TRUE); - key = dsakey_from_filedata(&item); - dump_dsakey(key); + int res; + char *modestr = mode_strings[mode]; + res = SECITEM_CompareItem(&result->buf, &cmp->buf); + if (is_sigCipher(mode)) { + if (forward) { + if (res == 0) { + printf("Signature self-test for %s passed.\n", modestr); + } else { + printf("Signature self-test for %s failed!\n", modestr); + } + } else { + if (sigstatus == SECSuccess) { + printf("Verification self-test for %s passed.\n", modestr); + } else { + printf("Verification self-test for %s failed!\n", modestr); + } } - return SECFailure; + } else if (is_hashCipher(mode)) { + if (res == 0) { + printf("Hash self-test for %s passed.\n", modestr); + } else { + printf("Hash self-test for %s failed!\n", modestr); + } + } else { + if (forward) { + if (res == 0) { + printf("Encryption self-test for %s passed.\n", modestr); + } else { + printf("Encryption self-test for %s failed!\n", modestr); + } + } else { + if (res == 0) { + printf("Decryption self-test for %s passed.\n", modestr); + } else { + printf("Decryption self-test for %s failed!\n", modestr); + } + } + } + return (res != 0); } -int main(int argc, char **argv) +static SECStatus +blapi_selftest(bltestCipherMode *modes, int numModes, int inoff, int outoff, + PRBool encrypt, PRBool decrypt) { - char *infile, *outfile, *keyfile, *ivfile, *sigfile, *seedfile, - *sigseedfile, *pqgfile; - PRBool b64 = PR_TRUE; - blapitestInfo info; - blapitestCryptoFn cryptofn = NULL; - PLOptState *optstate; - PLOptStatus status; - PRBool dofips = PR_FALSE; - PRBool doselftest = PR_FALSE; - PRBool zerobuffer = PR_FALSE; - char *dumpfile = NULL; - char *mode = NULL; - char *modesToTest[20]; - int numModesToTest = 0; - SECStatus rv; + bltestCipherInfo cipherInfo; + bltestIO pt, ct; + bltestCipherMode mode; + bltestParams *params; + int i, j, nummodes; + char *modestr; + char filename[256]; + PRFileDesc *file; + PRArenaPool *arena; + SECItem item; + PRBool finished; + SECStatus rv, srv; + + PORT_Memset(&cipherInfo, 0, sizeof(cipherInfo)); + arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE); + cipherInfo.arena = arena; + + finished = PR_FALSE; + nummodes = (numModes == 0) ? NUMMODES : numModes; + for (i=0; i < nummodes && !finished; i++) { + if (i == bltestRC5_ECB || i == bltestRC5_CBC) continue; + if (numModes > 0) + mode = modes[i]; + else + mode = i; + modestr = mode_strings[mode]; + cipherInfo.mode = mode; + params = &cipherInfo.params; + if (mode == bltestINVALID) { + fprintf(stderr, "%s: Skipping invalid mode %s.\n",progName,modestr); + continue; + } + /* get the number of tests in the directory */ + sprintf(filename, "%s/tests/%s/%s", testdir, modestr, "numtests"); + file = PR_Open(filename, PR_RDONLY, 00660); + if (!file) { + fprintf(stderr, "%s: File %s does not exist.\n", progName,filename); + return SECFailure; + } + rv = SECU_FileToItem(&item, file); + PR_Close(file); + /* loop over the tests in the directory */ + for (j=0; j<(int)(item.data[0] - '0'); j++) { /* XXX bug when > 10 */ + sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, + "plaintext", j); + if (mode == bltestDSA) + load_file_data(arena, &pt, filename, bltestBase64Encoded); + else + load_file_data(arena, &pt, filename, bltestBinary); + sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, + "ciphertext", j); + load_file_data(arena, &ct, filename, bltestBase64Encoded); + get_params(arena, params, mode, j); + /* Forward Operation (Encrypt/Sign/Hash) + ** Align the input buffer (plaintext) according to request + ** then perform operation and compare to ciphertext + */ + if (encrypt) { + bltestCopyIO(arena, &cipherInfo.input, &pt); + misalignBuffer(arena, &cipherInfo.input, inoff); + memset(&cipherInfo.output.buf, 0, sizeof cipherInfo.output.buf); + rv |= cipherInit(&cipherInfo, PR_TRUE); + misalignBuffer(arena, &cipherInfo.output, outoff); + rv |= cipherDoOp(&cipherInfo); + rv |= cipherFinish(&cipherInfo); + rv |= verify_self_test(&cipherInfo.output, + &ct, mode, PR_TRUE, 0); + /* If testing hash, only one op to test */ + if (is_hashCipher(mode)) + continue; + /*if (rv) return rv;*/ + /* XXX for now */ + rv = SECSuccess; + } + if (!decrypt) + continue; + /* Reverse Operation (Decrypt/Verify) + ** Align the input buffer (ciphertext) according to request + ** then perform operation and compare to plaintext + */ + if (mode != bltestDSA) + bltestCopyIO(arena, &cipherInfo.input, &ct); + else + bltestCopyIO(arena, &cipherInfo.input, &pt); + misalignBuffer(arena, &cipherInfo.input, outoff); + memset(&cipherInfo.output.buf, 0, sizeof cipherInfo.output.buf); + rv |= cipherInit(&cipherInfo, PR_FALSE); + misalignBuffer(arena, &cipherInfo.output, outoff); + srv = SECSuccess; + srv |= cipherDoOp(&cipherInfo); + rv |= cipherFinish(&cipherInfo); + rv |= verify_self_test(&cipherInfo.output, + &pt, mode, PR_FALSE, srv); + /*if (rv) return rv;*/ + /* XXX for now */ + rv = SECSuccess; + } + } + return SECSuccess; +} + +SECStatus +dump_file(bltestCipherMode mode, char *filename) +{ + bltestIO keydata; + PRArenaPool *arena = NULL; + arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE); + if (mode == bltestRSA) { + RSAPrivateKey *key; + load_file_data(arena, &keydata, filename, bltestBase64Encoded); + key = rsakey_from_filedata(&keydata.buf); + dump_rsakey(key); + } else if (mode == bltestDSA) { +#if 0 + PQGParams *pqg; + get_file_data(filename, &item, PR_TRUE); + pqg = pqg_from_filedata(&item); + dump_pqg(pqg); +#endif + DSAPrivateKey *key; + load_file_data(arena, &keydata, filename, bltestBase64Encoded); + key = dsakey_from_filedata(&keydata.buf); + dump_dsakey(key); + } + PORT_FreeArena(arena, PR_FALSE); + return SECFailure; +} + +/* bltest commands */ +enum { + cmd_Decrypt = 0, + cmd_Encrypt, + cmd_FIPS, + cmd_Hash, + cmd_Nonce, + cmd_Dump, + cmd_Sign, + cmd_SelfTest, + cmd_Verify +}; + +/* bltest options */ +enum { + opt_B64 = 0, + opt_BufSize, + opt_Restart, + opt_SelfTestDir, + opt_Exponent, + opt_SigFile, + opt_KeySize, + opt_Hex, + opt_Input, + opt_PQGFile, + opt_Key, + opt_HexWSpc, + opt_Mode, + opt_Output, + opt_Repetitions, + opt_ZeroBuf, + opt_Rounds, + opt_Seed, + opt_SigSeedFile, + opt_CXReps, + opt_IV, + opt_WordSize, + opt_UseSeed, + opt_UseSigSeed, + opt_SeedFile, + opt_InputOffset, + opt_OutputOffset, + opt_CmdLine +}; + +static secuCommandFlag bltest_commands[] = +{ + { /* cmd_Decrypt */ 'D', PR_FALSE, 0, PR_FALSE }, + { /* cmd_Encrypt */ 'E', PR_FALSE, 0, PR_FALSE }, + { /* cmd_FIPS */ 'F', PR_FALSE, 0, PR_FALSE }, + { /* cmd_Hash */ 'H', PR_FALSE, 0, PR_FALSE }, + { /* cmd_Nonce */ 'N', PR_FALSE, 0, PR_FALSE }, + { /* cmd_Dump */ 'P', PR_FALSE, 0, PR_FALSE }, + { /* cmd_Sign */ 'S', PR_FALSE, 0, PR_FALSE }, + { /* cmd_SelfTest */ 'T', PR_FALSE, 0, PR_FALSE }, + { /* cmd_Verify */ 'V', PR_FALSE, 0, PR_FALSE } +}; + +static secuCommandFlag bltest_options[] = +{ + { /* opt_B64 */ 'a', PR_FALSE, 0, PR_FALSE }, + { /* opt_BufSize */ 'b', PR_TRUE, 0, PR_FALSE }, + { /* opt_Restart */ 'c', PR_FALSE, 0, PR_FALSE }, + { /* opt_SelfTestDir */ 'd', PR_TRUE, 0, PR_FALSE }, + { /* opt_Exponent */ 'e', PR_TRUE, 0, PR_FALSE }, + { /* opt_SigFile */ 'f', PR_TRUE, 0, PR_FALSE }, + { /* opt_KeySize */ 'g', PR_TRUE, 0, PR_FALSE }, + { /* opt_Hex */ 'h', PR_FALSE, 0, PR_FALSE }, + { /* opt_Input */ 'i', PR_TRUE, 0, PR_FALSE }, + { /* opt_PQGFile */ 'j', PR_TRUE, 0, PR_FALSE }, + { /* opt_Key */ 'k', PR_TRUE, 0, PR_FALSE }, + { /* opt_HexWSpc */ 'l', PR_FALSE, 0, PR_FALSE }, + { /* opt_Mode */ 'm', PR_TRUE, 0, PR_FALSE }, + { /* opt_Output */ 'o', PR_TRUE, 0, PR_FALSE }, + { /* opt_Repetitions */ 'p', PR_TRUE, 0, PR_FALSE }, + { /* opt_ZeroBuf */ 'q', PR_FALSE, 0, PR_FALSE }, + { /* opt_Rounds */ 'r', PR_TRUE, 0, PR_FALSE }, + { /* opt_Seed */ 's', PR_TRUE, 0, PR_FALSE }, + { /* opt_SigSeedFile */ 't', PR_TRUE, 0, PR_FALSE }, + { /* opt_CXReps */ 'u', PR_TRUE, 0, PR_FALSE }, + { /* opt_IV */ 'v', PR_TRUE, 0, PR_FALSE }, + { /* opt_WordSize */ 'w', PR_TRUE, 0, PR_FALSE }, + { /* opt_UseSeed */ 'x', PR_FALSE, 0, PR_FALSE }, + { /* opt_UseSigSeed */ 'y', PR_FALSE, 0, PR_FALSE }, + { /* opt_SeedFile */ 'z', PR_FALSE, 0, PR_FALSE }, + { /* opt_InputOffset */ '1', PR_TRUE, 0, PR_FALSE }, + { /* opt_OutputOffset */ '2', PR_TRUE, 0, PR_FALSE }, + { /* opt_CmdLine */ '-', PR_FALSE, 0, PR_FALSE } +}; + +int main(int argc, char **argv) +{ + char *infileName, *outfileName, *keyfileName, *ivfileName; + SECStatus rv; + + bltestCipherInfo cipherInfo; + bltestParams *params; + PRFileDesc *file, *infile, *outfile; + char *instr = NULL; + PRArenaPool *arena; + bltestIOMode ioMode; + int keysize, bufsize, exponent; + int i, commandsEntered; + int inoff, outoff; + + secuCommand bltest; + bltest.numCommands = sizeof(bltest_commands) / sizeof(secuCommandFlag); + bltest.numOptions = sizeof(bltest_options) / sizeof(secuCommandFlag); + bltest.commands = bltest_commands; + bltest.options = bltest_options; - PORT_Memset(&info, 0, sizeof(info)); - info.bufsize = 8; - info.keysize = DES_KEY_LENGTH; - info.rsapubexp = 65537; - info.rounds = 10; - info.wordsize = 4; - infile=outfile=keyfile=pqgfile=ivfile=sigfile=seedfile=sigseedfile=NULL; - info.repetitions = 1; progName = strrchr(argv[0], '/'); progName = progName ? progName+1 : argv[0]; - optstate = PL_CreateOptState(argc, argv, - "DEFHP:STVab:d:ce:g:j:i:o:p:k:m:t:qr:s:v:w:xyz:"); - while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { - switch (optstate->option) { - case 'D': info.decrypt = PR_TRUE; break; - case 'E': info.encrypt = PR_TRUE; break; - case 'F': dofips = PR_TRUE; break; - case 'H': info.hash = PR_TRUE; break; - case 'P': dumpfile = PL_strdup(optstate->value); break; - case 'S': info.sign = PR_TRUE; break; - case 'T': doselftest = PR_TRUE; break; - case 'V': info.verify = PR_TRUE; break; - case 'a': b64 = PR_FALSE; break; - case 'b': info.bufsize = PORT_Atoi(optstate->value); break; - case 'c': info.multihash = PR_TRUE; break; - case 'd': testdir = PL_strdup(optstate->value); break; - case 'e': info.rsapubexp = PORT_Atoi(optstate->value); break; - case 'g': info.keysize = PORT_Atoi(optstate->value); break; - case 'i': infile = PL_strdup(optstate->value); break; - case 'j': pqgfile = PL_strdup(optstate->value); break; - case 'k': keyfile = PL_strdup(optstate->value); break; - case 'm': cryptofn = get_test_mode(optstate->value); - mode = PL_strdup(optstate->value); - break; - case 'o': outfile = PL_strdup(optstate->value); break; - case 'p': info.performance = PR_TRUE; - info.repetitions = PORT_Atoi(optstate->value); - break; - case 'q': zerobuffer = PR_TRUE; break; - case 'r': info.rounds = PORT_Atoi(optstate->value); break; - case 's': sigfile = PL_strdup(optstate->value); break; - case 't': sigseedfile = PL_strdup(optstate->value); break; - case 'v': ivfile = PL_strdup(optstate->value); break; - case 'w': info.wordsize = PORT_Atoi(optstate->value); break; - case 'x': info.useseed = PR_TRUE; break; - case 'y': info.usesigseed = PR_TRUE; break; - case 'z': seedfile = PL_strdup(optstate->value); break; - case '\0': if (optstate->value[0] != '-') - modesToTest[numModesToTest++] = - PL_strdup(optstate->value); - break; - default: break; - } + + NSS_Init(NULL); + + rv = SECU_ParseCommandLine(argc, argv, progName, &bltest); + + PORT_Memset(&cipherInfo, 0, sizeof(cipherInfo)); + arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE); + cipherInfo.arena = arena; + params = &cipherInfo.params; + /* set some defaults */ + infileName = outfileName = keyfileName = ivfileName = NULL; + + /* Check the number of commands entered on the command line. */ + commandsEntered = 0; + for (i=0; i 1 && + !(commandsEntered == 2 && bltest.commands[cmd_SelfTest].activated)) { + fprintf(stderr, "%s: one command at a time!\n", progName); + Usage(); + } + if (commandsEntered == 0) { + fprintf(stderr, "%s: you must enter a command!\n", progName); + Usage(); + } + + if (bltest.commands[cmd_Sign].activated) + bltest.commands[cmd_Encrypt].activated = PR_TRUE; + if (bltest.commands[cmd_Verify].activated) + bltest.commands[cmd_Decrypt].activated = PR_TRUE; + if (bltest.commands[cmd_Hash].activated) + bltest.commands[cmd_Encrypt].activated = PR_TRUE; + + inoff = outoff = 0; + if (bltest.options[opt_InputOffset].activated) + inoff = PORT_Atoi(bltest.options[opt_InputOffset].arg); + if (bltest.options[opt_OutputOffset].activated) + outoff = PORT_Atoi(bltest.options[opt_OutputOffset].arg); + + testdir = (bltest.options[opt_SelfTestDir].activated) ? + strdup(bltest.options[opt_SelfTestDir].arg) : "."; + + /* + * Handle three simple cases first + */ + + /* Do BLAPI self-test */ + if (bltest.commands[cmd_SelfTest].activated) { + PRBool encrypt = PR_TRUE, decrypt = PR_TRUE; + /* user may specified a set of ciphers to test. parse them. */ + bltestCipherMode modesToTest[NUMMODES]; + int numModesToTest = 0; + char *tok, *str; + str = bltest.options[opt_Mode].arg; + while (str) { + tok = strchr(str, ','); + if (tok) *tok = '\0'; + modesToTest[numModesToTest++] = get_mode(str); + if (tok) { + *tok = ','; + str = tok + 1; + } else { + break; + } } + if (bltest.commands[cmd_Decrypt].activated && + !bltest.commands[cmd_Encrypt].activated) + encrypt = PR_FALSE; + if (bltest.commands[cmd_Encrypt].activated && + !bltest.commands[cmd_Decrypt].activated) + decrypt = PR_FALSE; + return blapi_selftest(modesToTest, numModesToTest, inoff, outoff, + encrypt, decrypt); + } - if (dumpfile) - return dump_file(mode, dumpfile); + /* Do FIPS self-test */ + if (bltest.commands[cmd_FIPS].activated) { + CK_RV ckrv = pk11_fipsPowerUpSelfTest(); + fprintf(stdout, "CK_RV: %ld.\n", ckrv); + return 0; + } - if (doselftest) { - if (!info.encrypt && !info.decrypt) { - info.encrypt = info.decrypt = PR_TRUE; /* do both */ - } - if (numModesToTest > 0) { - return blapi_selftest(modesToTest, numModesToTest, - info.encrypt, info.decrypt); - } else { - return blapi_selftest(NULL, 0, info.encrypt, info.decrypt); - } + /* + * Check command line arguments for Encrypt/Decrypt/Hash/Sign/Verify + */ + + if ((bltest.commands[cmd_Decrypt].activated || + bltest.commands[cmd_Verify].activated) && + bltest.options[opt_BufSize].activated) { + fprintf(stderr, "%s: cannot use a nonce as input to decrypt/verify.\n", + progName); + Usage(); + } + + if (bltest.options[opt_Mode].activated) { + cipherInfo.mode = get_mode(bltest.options[opt_Mode].arg); + if (cipherInfo.mode == bltestINVALID) { + fprintf(stderr, "%s: Invalid mode \"%s\"\n", progName, + bltest.options[opt_Mode].arg); + Usage(); } + } else { + fprintf(stderr, "%s: You must specify a cipher mode with -m.\n", + progName); + Usage(); + } - if (dofips) { - CK_RV foo = pk11_fipsPowerUpSelfTest(); - PR_fprintf(PR_STDOUT, "CK_RV: %d.\n", foo); - return 0; + if (bltest.options[opt_Repetitions].activated) { + cipherInfo.repetitions = PORT_Atoi(bltest.options[opt_Repetitions].arg); + } else { + cipherInfo.repetitions = 0; + } + + + if (bltest.options[opt_CXReps].activated) { + cipherInfo.cxreps = PORT_Atoi(bltest.options[opt_CXReps].arg); + } else { + cipherInfo.cxreps = 0; + } + + /* Dump a file (rsakey, dsakey, etc.) */ + if (bltest.commands[cmd_Dump].activated) { + return dump_file(cipherInfo.mode, bltest.options[opt_Input].arg); + } + + /* default input mode is binary */ + ioMode = (bltest.options[opt_B64].activated) ? bltestBase64Encoded : + (bltest.options[opt_Hex].activated) ? bltestHexStream : + (bltest.options[opt_HexWSpc].activated) ? bltestHexSpaceDelim : + bltestBinary; + + if (bltest.options[opt_KeySize].activated) + keysize = PORT_Atoi(bltest.options[opt_KeySize].arg); + else + keysize = 0; + + if (bltest.options[opt_Exponent].activated) + exponent = PORT_Atoi(bltest.options[opt_Exponent].arg); + else + exponent = 65537; + + /* Set up an encryption key. */ + keysize = 0; + file = NULL; + if (is_symmkeyCipher(cipherInfo.mode)) { + char *keystr = NULL; /* if key is on command line */ + if (bltest.options[opt_Key].activated) { + if (bltest.options[opt_CmdLine].activated) { + keystr = bltest.options[opt_Key].arg; + } else { + file = PR_Open(bltest.options[opt_Key].arg, PR_RDONLY, 00660); + } + } else { + if (bltest.options[opt_KeySize].activated) + keysize = PORT_Atoi(bltest.options[opt_KeySize].arg); + else + keysize = 8; /* use 64-bit default (DES) */ + /* save the random key for reference */ + file = PR_Open("tmp.key", PR_WRONLY|PR_CREATE_FILE, 00660); } - - if (!info.encrypt && !info.decrypt && !info.hash && - !info.sign && !info.verify) - Usage(); - - if (!cryptofn) { - printmodes(&info); - return -1; + params->key.mode = ioMode; + setupIO(cipherInfo.arena, ¶ms->key, file, keystr, keysize); + if (file) + PR_Close(file); + } else if (is_pubkeyCipher(cipherInfo.mode)) { + if (bltest.options[opt_Key].activated) { + file = PR_Open(bltest.options[opt_Key].arg, PR_RDONLY, 00660); + } else { + if (bltest.options[opt_KeySize].activated) + keysize = PORT_Atoi(bltest.options[opt_KeySize].arg); + else + keysize = 64; /* use 512-bit default */ + file = PR_Open("tmp.key", PR_WRONLY|PR_CREATE_FILE, 00660); } + params->key.mode = bltestBase64Encoded; + pubkeyInitKey(&cipherInfo, file, keysize, exponent); + PR_Close(file); + } - if (info.decrypt && !infile) - Usage(); - - if (info.performance) { - char buf[256]; - PRStatus stat; - stat = PR_GetSystemInfo(PR_SI_HOSTNAME, buf, sizeof(buf)); - printf("HOST: %s\n", buf); - stat = PR_GetSystemInfo(PR_SI_SYSNAME, buf, sizeof(buf)); - printf("SYSTEM: %s\n", buf); - stat = PR_GetSystemInfo(PR_SI_RELEASE, buf, sizeof(buf)); - printf("RELEASE: %s\n", buf); - stat = PR_GetSystemInfo(PR_SI_ARCHITECTURE, buf, sizeof(buf)); - printf("ARCH: %s\n", buf); + /* set up an initialization vector. */ + if (cipher_requires_IV(cipherInfo.mode)) { + char *ivstr; + bltestSymmKeyParams *skp; + file = NULL; + if (cipherInfo.mode == bltestRC5_CBC) + skp = (bltestSymmKeyParams *)¶ms->rc5; + else + skp = ¶ms->sk; + if (bltest.options[opt_IV].activated) { + if (bltest.options[opt_CmdLine].activated) { + ivstr = bltest.options[opt_IV].arg; + } else { + file = PR_Open(bltest.options[opt_IV].arg, PR_RDONLY, 00660); + } + } else { + /* save the random iv for reference */ + file = PR_Open("tmp.iv", PR_WRONLY|PR_CREATE_FILE, 00660); } + memset(&skp->iv, 0, sizeof skp->iv); + skp->iv.mode = ioMode; + setupIO(cipherInfo.arena, &skp->iv, file, ivstr, keysize); + if (file) + PR_Close(file); + } - RNG_RNGInit(); - RNG_SystemInfoForRNG(); - - if (keyfile) { - /* RSA and DSA keys are always b64 encoded. */ - if (b64 || PL_strcmp(mode,"rsa")==0 || PL_strcmp(mode,"dsa")==0) - get_file_data(keyfile, &info.key, PR_TRUE); - else - get_file_data(keyfile, &info.key, b64); + if (bltest.commands[cmd_Verify].activated) { + if (!bltest.options[opt_SigFile].activated) { + fprintf(stderr, "%s: You must specify a signature file with -f.\n", + progName); + exit(-1); } - if (ivfile) - get_file_data(ivfile, &info.iv, b64); - if (infile) - get_file_data(infile, &info.in, b64); - if (sigfile) - get_file_data(sigfile, &info.out, PR_TRUE); - if (seedfile) { - get_file_data(seedfile, &info.seed, b64); - info.useseed = PR_TRUE; + file = PR_Open(bltest.options[opt_SigFile].arg, PR_RDONLY, 00660); + memset(&cipherInfo.params.dsa.sig, 0, sizeof(bltestIO)); + cipherInfo.params.dsa.sig.mode = ioMode; + setupIO(cipherInfo.arena, &cipherInfo.params.dsa.sig, file, NULL, 0); + } + + if (bltest.options[opt_PQGFile].activated) { + file = PR_Open(bltest.options[opt_PQGFile].arg, PR_RDONLY, 00660); + params->dsa.pqgdata.mode = bltestBase64Encoded; + setupIO(cipherInfo.arena, ¶ms->dsa.pqgdata, file, NULL, 0); + } + + /* Set up the input buffer */ + if (bltest.options[opt_Input].activated) { + if (bltest.options[opt_CmdLine].activated) { + instr = bltest.options[opt_Input].arg; + } else { + infile = PR_Open(bltest.options[opt_Input].arg, PR_RDONLY, 00660); } - if (sigseedfile) { - get_file_data(sigseedfile, &info.sigseed, b64); - info.usesigseed = PR_TRUE; - } - if (pqgfile) - get_file_data(pqgfile, &info.pqg, PR_TRUE); + } else if (bltest.options[opt_BufSize].activated) { + /* save the random plaintext for reference */ + infile = PR_Open("tmp.in", PR_WRONLY|PR_CREATE_FILE, 00660); + } else { + infile = PR_STDIN; + } + cipherInfo.input.mode = ioMode; - if (zerobuffer) { - PRFileDesc *ifile; - info.in.len = info.bufsize; - info.in.data = PORT_ZAlloc(info.in.len); - ifile = PR_Open("tmp.pt", PR_WRONLY|PR_CREATE_FILE, 00660); - rv = btoa_file(&info.in, ifile); - CHECKERROR((rv < 0), __LINE__); - PR_Close(ifile); - } + /* Set up the output stream */ + if (bltest.options[opt_Output].activated) { + outfile = PR_Open(bltest.options[opt_Output].arg, + PR_WRONLY|PR_CREATE_FILE, 00660); + } else { + outfile = PR_STDOUT; + } + cipherInfo.output.mode = ioMode; - rv = (*cryptofn)(&info); - CHECKERROR(rv, __LINE__); + if (is_hashCipher(cipherInfo.mode)) + cipherInfo.params.hash.restart = bltest.options[opt_Restart].activated; - if (!sigfile && info.out.len > 0) { - PRFileDesc *ofile; - if (!outfile) - ofile = PR_Open("tmp.out", PR_WRONLY|PR_CREATE_FILE, 00660); - else - ofile = PR_Open(outfile, PR_WRONLY|PR_CREATE_FILE, 00660); - rv = btoa_file(&info.out, ofile); - PR_Close(ofile); - CHECKERROR((rv < 0), __LINE__); - } + bufsize = 0; + if (bltest.options[opt_BufSize].activated) + bufsize = PORT_Atoi(bltest.options[opt_BufSize].arg); - RNG_RNGShutdown(); + /*infile = NULL;*/ + setupIO(cipherInfo.arena, &cipherInfo.input, infile, instr, bufsize); + misalignBuffer(cipherInfo.arena, &cipherInfo.input, inoff); - return SECSuccess; + cipherInit(&cipherInfo, bltest.commands[cmd_Encrypt].activated); + misalignBuffer(cipherInfo.arena, &cipherInfo.output, outoff); + + if (!bltest.commands[cmd_Nonce].activated) { + cipherDoOp(&cipherInfo); + cipherFinish(&cipherInfo); + finishIO(&cipherInfo.output, outfile); + } + + if (cipherInfo.repetitions > 0 || cipherInfo.cxreps > 0) + dump_performance_info(&cipherInfo, + bltest.commands[cmd_Encrypt].activated, + (cipherInfo.repetitions == 0)); + + if (infile && infile != PR_STDIN) + PR_Close(infile); + if (outfile && outfile != PR_STDOUT) + PR_Close(outfile); + PORT_FreeArena(cipherInfo.arena, PR_TRUE); + + NSS_Shutdown(); + + return SECSuccess; }