mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-05 16:46:26 +00:00
ee588c0e0d
the SECItem allocated in getECParams. r=alexei.volkov.
3574 lines
114 KiB
C
3574 lines
114 KiB
C
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public 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 the Initial Developer are Copyright (C) 1994-2000
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "blapi.h"
|
|
#include "secrng.h"
|
|
#include "prmem.h"
|
|
#include "prprf.h"
|
|
#include "prtime.h"
|
|
#include "prsystem.h"
|
|
#include "plstr.h"
|
|
#include "nssb64.h"
|
|
#include "secutil.h"
|
|
#include "plgetopt.h"
|
|
#include "softoken.h"
|
|
#include "nspr.h"
|
|
#include "nss.h"
|
|
|
|
#ifdef NSS_ENABLE_ECC
|
|
#include "ecl-curve.h"
|
|
SECStatus EC_DecodeParams(const SECItem *encodedParams,
|
|
ECParams **ecparams);
|
|
SECStatus EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
|
|
const ECParams *srcParams);
|
|
SECStatus secoid_Init(void);
|
|
#endif
|
|
|
|
/* Temporary - add debugging ouput on windows for RSA to track QA failure */
|
|
#ifdef _WIN32
|
|
#define TRACK_BLTEST_BUG
|
|
char __bltDBG[] = "BLTEST DEBUG";
|
|
#endif
|
|
|
|
char *progName;
|
|
char *testdir = NULL;
|
|
|
|
#define BLTEST_DEFAULT_CHUNKSIZE 4096
|
|
|
|
#define WORDSIZE sizeof(unsigned long)
|
|
|
|
#define CHECKERROR(rv, ln) \
|
|
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 = ((double)(time1))/reps;
|
|
|
|
#define TIMEMARK(seconds) \
|
|
time1 = PR_SecondsToInterval(seconds); \
|
|
{ \
|
|
PRInt64 tmp, L100; \
|
|
LL_I2L(L100, 100); \
|
|
if (time2 == 0) { \
|
|
time2 = 1; \
|
|
} \
|
|
LL_DIV(tmp, time1, time2); \
|
|
if (tmp < 10) { \
|
|
if (tmp == 0) { \
|
|
opsBetweenChecks = 1; \
|
|
} else { \
|
|
LL_L2I(opsBetweenChecks, tmp); \
|
|
} \
|
|
} else { \
|
|
opsBetweenChecks = 10; \
|
|
} \
|
|
} \
|
|
time2 = time1; \
|
|
time1 = PR_IntervalNow();
|
|
|
|
#define TIMETOFINISH() \
|
|
PR_IntervalNow() - time1 >= time2
|
|
|
|
static void Usage()
|
|
{
|
|
#define PRINTUSAGE(subject, option, predicate) \
|
|
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 | -5 time_interval]");
|
|
PRINTUSAGE("", "", "[-4 th_num]");
|
|
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("", "-4", "run test in multithread mode. th_num number of parallel threads");
|
|
PRINTUSAGE("", "-5", "run test for specified time interval(in seconds)");
|
|
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 | -5 time_interval] [-4 th_num]");
|
|
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");
|
|
PRINTUSAGE("", "-4", "run test in multithread mode. th_num number of parallel threads");
|
|
PRINTUSAGE("", "-5", "run test for specified time interval(in seconds)");
|
|
fprintf(stderr, "\n");
|
|
PRINTUSAGE(progName, "-H -m mode", "Hash a buffer");
|
|
PRINTUSAGE("", "", "[-i plaintext] [-o hash]");
|
|
PRINTUSAGE("", "", "[-b bufsize]");
|
|
PRINTUSAGE("", "", "[-p repetitions | -5 time_interval] [-4 th_num]");
|
|
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");
|
|
PRINTUSAGE("", "-4", "run test in multithread mode. th_num number of parallel threads");
|
|
PRINTUSAGE("", "-5", "run test for specified time interval(in seconds)");
|
|
fprintf(stderr, "\n");
|
|
PRINTUSAGE(progName, "-S -m mode", "Sign a buffer");
|
|
PRINTUSAGE("", "", "[-i plaintext] [-o signature] [-k key]");
|
|
PRINTUSAGE("", "", "[-b bufsize]");
|
|
#ifdef NSS_ENABLE_ECC
|
|
PRINTUSAGE("", "", "[-n curvename]");
|
|
#endif
|
|
PRINTUSAGE("", "", "[-p repetitions | -5 time_interval] [-4 th_num]");
|
|
PRINTUSAGE("", "-m", "cipher mode to use");
|
|
PRINTUSAGE("", "-i", "file which contains input buffer");
|
|
PRINTUSAGE("", "-o", "file for signature");
|
|
PRINTUSAGE("", "-k", "file which contains key");
|
|
#ifdef NSS_ENABLE_ECC
|
|
PRINTUSAGE("", "-n", "name of curve for EC key generation; one of:");
|
|
PRINTUSAGE("", "", " sect163k1, nistk163, sect163r1, sect163r2,");
|
|
PRINTUSAGE("", "", " nistb163, sect193r1, sect193r2, sect233k1, nistk233,");
|
|
PRINTUSAGE("", "", " sect233r1, nistb233, sect239k1, sect283k1, nistk283,");
|
|
PRINTUSAGE("", "", " sect283r1, nistb283, sect409k1, nistk409, sect409r1,");
|
|
PRINTUSAGE("", "", " nistb409, sect571k1, nistk571, sect571r1, nistb571,");
|
|
PRINTUSAGE("", "", " secp160k1, secp160r1, secp160r2, secp192k1, secp192r1,");
|
|
PRINTUSAGE("", "", " nistp192, secp224k1, secp224r1, nistp224, secp256k1,");
|
|
PRINTUSAGE("", "", " secp256r1, nistp256, secp384r1, nistp384, secp521r1,");
|
|
PRINTUSAGE("", "", " nistp521, prime192v1, prime192v2, prime192v3,");
|
|
PRINTUSAGE("", "", " prime239v1, prime239v2, prime239v3, c2pnb163v1,");
|
|
PRINTUSAGE("", "", " c2pnb163v2, c2pnb163v3, c2pnb176v1, c2tnb191v1,");
|
|
PRINTUSAGE("", "", " c2tnb191v2, c2tnb191v3, c2onb191v4, c2onb191v5,");
|
|
PRINTUSAGE("", "", " c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3,");
|
|
PRINTUSAGE("", "", " c2onb239v4, c2onb239v5, c2pnb272w1, c2pnb304w1,");
|
|
PRINTUSAGE("", "", " c2tnb359w1, c2pnb368w1, c2tnb431r1, secp112r1,");
|
|
PRINTUSAGE("", "", " secp112r2, secp128r1, secp128r2, sect113r1, sect113r2,");
|
|
PRINTUSAGE("", "", " sect131r1, sect131r2");
|
|
#endif
|
|
PRINTUSAGE("", "-p", "do performance test");
|
|
PRINTUSAGE("", "-4", "run test in multithread mode. th_num number of parallel threads");
|
|
PRINTUSAGE("", "-5", "run test for specified time interval(in seconds)");
|
|
fprintf(stderr, "\n");
|
|
PRINTUSAGE(progName, "-V -m mode", "Verify a signed buffer");
|
|
PRINTUSAGE("", "", "[-i plaintext] [-s signature] [-k key]");
|
|
PRINTUSAGE("", "", "[-p repetitions | -5 time_interval] [-4 th_num]");
|
|
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");
|
|
PRINTUSAGE("", "-4", "run test in multithread mode. th_num number of parallel threads");
|
|
PRINTUSAGE("", "-5", "run test for specified time interval(in seconds)");
|
|
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)
|
|
{
|
|
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, PRArenaPool *arena)
|
|
{
|
|
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_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
|
|
hex_from_2char(unsigned char *c2, unsigned char *byteval)
|
|
{
|
|
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; i<ni; i++, it++) {
|
|
len[0] = (it->len >> 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 ns, int ni, SECItem *filedata)
|
|
{
|
|
int fpos = 0;
|
|
int i, len;
|
|
unsigned char *buf = filedata->data;
|
|
for (i=0; i<ni; i++) {
|
|
len = (buf[fpos++] & 0xff) << 24;
|
|
len |= (buf[fpos++] & 0xff) << 16;
|
|
len |= (buf[fpos++] & 0xff) << 8;
|
|
len |= (buf[fpos++] & 0xff);
|
|
if (ns <= i) {
|
|
if (len > 0) {
|
|
it->len = len;
|
|
it->data = PORT_ArenaAlloc(arena, it->len);
|
|
PORT_Memcpy(it->data, &buf[fpos], it->len);
|
|
} else {
|
|
it->len = 0;
|
|
it->data = NULL;
|
|
}
|
|
it++;
|
|
}
|
|
fpos += len;
|
|
}
|
|
}
|
|
|
|
static RSAPrivateKey *
|
|
rsakey_from_filedata(SECItem *filedata)
|
|
{
|
|
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, 0, 9, filedata);
|
|
return key;
|
|
}
|
|
|
|
static PQGParams *
|
|
pqg_from_filedata(SECItem *filedata)
|
|
{
|
|
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, 0, 3, filedata);
|
|
return pqg;
|
|
}
|
|
|
|
static DSAPrivateKey *
|
|
dsakey_from_filedata(SECItem *filedata)
|
|
{
|
|
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, 0, 5, filedata);
|
|
return key;
|
|
}
|
|
|
|
#ifdef NSS_ENABLE_ECC
|
|
static ECPrivateKey *
|
|
eckey_from_filedata(SECItem *filedata)
|
|
{
|
|
ECPrivateKey *key;
|
|
PRArenaPool *arena;
|
|
SECStatus rv;
|
|
ECParams *tmpECParams = NULL;
|
|
arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
|
|
key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey));
|
|
/* read and convert params */
|
|
key->ecParams.arena = arena;
|
|
key_from_filedata(arena, &key->ecParams.DEREncoding, 0, 1, filedata);
|
|
rv = secoid_Init();
|
|
CHECKERROR(rv, __LINE__);
|
|
rv = EC_DecodeParams(&key->ecParams.DEREncoding, &tmpECParams);
|
|
CHECKERROR(rv, __LINE__);
|
|
rv = EC_CopyParams(key->ecParams.arena, &key->ecParams, tmpECParams);
|
|
CHECKERROR(rv, __LINE__);
|
|
rv = SECOID_Shutdown();
|
|
CHECKERROR(rv, __LINE__);
|
|
PORT_FreeArena(tmpECParams->arena, PR_TRUE);
|
|
/* read key */
|
|
key_from_filedata(arena, &key->publicValue, 1, 3, filedata);
|
|
return key;
|
|
}
|
|
|
|
typedef struct curveNameTagPairStr {
|
|
char *curveName;
|
|
SECOidTag curveOidTag;
|
|
} CurveNameTagPair;
|
|
|
|
#define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1
|
|
/* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */
|
|
|
|
static CurveNameTagPair nameTagPair[] =
|
|
{
|
|
{ "sect163k1", SEC_OID_SECG_EC_SECT163K1},
|
|
{ "nistk163", SEC_OID_SECG_EC_SECT163K1},
|
|
{ "sect163r1", SEC_OID_SECG_EC_SECT163R1},
|
|
{ "sect163r2", SEC_OID_SECG_EC_SECT163R2},
|
|
{ "nistb163", SEC_OID_SECG_EC_SECT163R2},
|
|
{ "sect193r1", SEC_OID_SECG_EC_SECT193R1},
|
|
{ "sect193r2", SEC_OID_SECG_EC_SECT193R2},
|
|
{ "sect233k1", SEC_OID_SECG_EC_SECT233K1},
|
|
{ "nistk233", SEC_OID_SECG_EC_SECT233K1},
|
|
{ "sect233r1", SEC_OID_SECG_EC_SECT233R1},
|
|
{ "nistb233", SEC_OID_SECG_EC_SECT233R1},
|
|
{ "sect239k1", SEC_OID_SECG_EC_SECT239K1},
|
|
{ "sect283k1", SEC_OID_SECG_EC_SECT283K1},
|
|
{ "nistk283", SEC_OID_SECG_EC_SECT283K1},
|
|
{ "sect283r1", SEC_OID_SECG_EC_SECT283R1},
|
|
{ "nistb283", SEC_OID_SECG_EC_SECT283R1},
|
|
{ "sect409k1", SEC_OID_SECG_EC_SECT409K1},
|
|
{ "nistk409", SEC_OID_SECG_EC_SECT409K1},
|
|
{ "sect409r1", SEC_OID_SECG_EC_SECT409R1},
|
|
{ "nistb409", SEC_OID_SECG_EC_SECT409R1},
|
|
{ "sect571k1", SEC_OID_SECG_EC_SECT571K1},
|
|
{ "nistk571", SEC_OID_SECG_EC_SECT571K1},
|
|
{ "sect571r1", SEC_OID_SECG_EC_SECT571R1},
|
|
{ "nistb571", SEC_OID_SECG_EC_SECT571R1},
|
|
{ "secp160k1", SEC_OID_SECG_EC_SECP160K1},
|
|
{ "secp160r1", SEC_OID_SECG_EC_SECP160R1},
|
|
{ "secp160r2", SEC_OID_SECG_EC_SECP160R2},
|
|
{ "secp192k1", SEC_OID_SECG_EC_SECP192K1},
|
|
{ "secp192r1", SEC_OID_SECG_EC_SECP192R1},
|
|
{ "nistp192", SEC_OID_SECG_EC_SECP192R1},
|
|
{ "secp224k1", SEC_OID_SECG_EC_SECP224K1},
|
|
{ "secp224r1", SEC_OID_SECG_EC_SECP224R1},
|
|
{ "nistp224", SEC_OID_SECG_EC_SECP224R1},
|
|
{ "secp256k1", SEC_OID_SECG_EC_SECP256K1},
|
|
{ "secp256r1", SEC_OID_SECG_EC_SECP256R1},
|
|
{ "nistp256", SEC_OID_SECG_EC_SECP256R1},
|
|
{ "secp384r1", SEC_OID_SECG_EC_SECP384R1},
|
|
{ "nistp384", SEC_OID_SECG_EC_SECP384R1},
|
|
{ "secp521r1", SEC_OID_SECG_EC_SECP521R1},
|
|
{ "nistp521", SEC_OID_SECG_EC_SECP521R1},
|
|
|
|
{ "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
|
|
{ "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
|
|
{ "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
|
|
{ "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
|
|
{ "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
|
|
{ "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
|
|
|
|
{ "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
|
|
{ "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
|
|
{ "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
|
|
{ "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
|
|
{ "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
|
|
{ "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
|
|
{ "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
|
|
{ "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
|
|
{ "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
|
|
{ "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
|
|
{ "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
|
|
{ "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
|
|
{ "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
|
|
{ "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
|
|
{ "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
|
|
{ "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
|
|
{ "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
|
|
{ "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
|
|
{ "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
|
|
{ "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
|
|
|
|
{ "secp112r1", SEC_OID_SECG_EC_SECP112R1},
|
|
{ "secp112r2", SEC_OID_SECG_EC_SECP112R2},
|
|
{ "secp128r1", SEC_OID_SECG_EC_SECP128R1},
|
|
{ "secp128r2", SEC_OID_SECG_EC_SECP128R2},
|
|
|
|
{ "sect113r1", SEC_OID_SECG_EC_SECT113R1},
|
|
{ "sect113r2", SEC_OID_SECG_EC_SECT113R2},
|
|
{ "sect131r1", SEC_OID_SECG_EC_SECT131R1},
|
|
{ "sect131r2", SEC_OID_SECG_EC_SECT131R2},
|
|
};
|
|
|
|
static SECKEYECParams *
|
|
getECParams(const char *curve)
|
|
{
|
|
SECKEYECParams *ecparams;
|
|
SECOidData *oidData = NULL;
|
|
SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
|
|
int i, numCurves;
|
|
|
|
if (curve != NULL) {
|
|
numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair);
|
|
for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN));
|
|
i++) {
|
|
if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
|
|
curveOidTag = nameTagPair[i].curveOidTag;
|
|
}
|
|
}
|
|
|
|
/* Return NULL if curve name is not recognized */
|
|
if ((curveOidTag == SEC_OID_UNKNOWN) ||
|
|
(oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
|
|
fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
|
|
return NULL;
|
|
}
|
|
|
|
ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
|
|
|
|
/*
|
|
* ecparams->data needs to contain the ASN encoding of an object ID (OID)
|
|
* representing the named curve. The actual OID is in
|
|
* oidData->oid.data so we simply prepend 0x06 and OID length
|
|
*/
|
|
ecparams->data[0] = SEC_ASN1_OBJECT_ID;
|
|
ecparams->data[1] = oidData->oid.len;
|
|
memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
|
|
|
|
return ecparams;
|
|
}
|
|
#endif /* NSS_ENABLE_ECC */
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
#ifdef NSS_ENABLE_ECC
|
|
static void
|
|
dump_ecp(ECParams *ecp)
|
|
{
|
|
/* TODO other fields */
|
|
SECU_PrintInteger(stdout, &ecp->base, "BASE POINT:", 0);
|
|
}
|
|
|
|
static void
|
|
dump_eckey(ECPrivateKey *key)
|
|
{
|
|
dump_ecp(&key->ecParams);
|
|
SECU_PrintInteger(stdout, &key->publicValue, "PUBLIC VALUE:", 0);
|
|
SECU_PrintInteger(stdout, &key->privateValue, "PRIVATE VALUE:", 0);
|
|
}
|
|
#endif
|
|
|
|
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 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);
|
|
}
|
|
|
|
typedef enum {
|
|
bltestBase64Encoded, /* Base64 encoded ASCII */
|
|
bltestBinary, /* straight binary */
|
|
bltestHexSpaceDelim, /* 0x12 0x34 0xab 0xCD ... */
|
|
bltestHexStream /* 1234abCD ... */
|
|
} bltestIOMode;
|
|
|
|
typedef struct
|
|
{
|
|
SECItem buf;
|
|
SECItem pBuf;
|
|
bltestIOMode mode;
|
|
PRFileDesc* file;
|
|
} bltestIO;
|
|
|
|
typedef SECStatus (* bltestSymmCipherFn)(void *cx,
|
|
unsigned char *output,
|
|
unsigned int *outputLen,
|
|
unsigned int maxOutputLen,
|
|
const unsigned char *input,
|
|
unsigned int inputLen);
|
|
|
|
typedef SECStatus (* bltestPubKeyCipherFn)(void *key,
|
|
SECItem *output,
|
|
const SECItem *input);
|
|
|
|
typedef SECStatus (* bltestHashCipherFn)(unsigned char *dest,
|
|
const unsigned char *src,
|
|
uint32 src_length);
|
|
|
|
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, /* . */
|
|
bltestAES_ECB, /* . */
|
|
bltestAES_CBC, /* . */
|
|
bltestRSA, /* Public Key Ciphers */
|
|
#ifdef NSS_ENABLE_ECC
|
|
bltestECDSA, /* . (Public Key Sig.) */
|
|
#endif
|
|
bltestDSA, /* . */
|
|
bltestMD2, /* Hash algorithms */
|
|
bltestMD5, /* . */
|
|
bltestSHA1, /* . */
|
|
bltestSHA256, /* . */
|
|
bltestSHA384, /* . */
|
|
bltestSHA512, /* . */
|
|
NUMMODES
|
|
} bltestCipherMode;
|
|
|
|
static char *mode_strings[] =
|
|
{
|
|
"des_ecb",
|
|
"des_cbc",
|
|
"des3_ecb",
|
|
"des3_cbc",
|
|
"rc2_ecb",
|
|
"rc2_cbc",
|
|
"rc4",
|
|
"rc5_ecb",
|
|
"rc5_cbc",
|
|
"aes_ecb",
|
|
"aes_cbc",
|
|
"rsa",
|
|
#ifdef NSS_ENABLE_ECC
|
|
"ecdsa",
|
|
#endif
|
|
/*"pqg",*/
|
|
"dsa",
|
|
"md2",
|
|
"md5",
|
|
"sha1",
|
|
"sha256",
|
|
"sha384",
|
|
"sha512",
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
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;
|
|
|
|
#ifdef NSS_ENABLE_ECC
|
|
typedef struct
|
|
{
|
|
bltestIO key;
|
|
char *curveName;
|
|
bltestIO sigseed;
|
|
bltestIO sig; /* if doing verify, have additional input */
|
|
ECPrivateKey *eckey;
|
|
} bltestECDSAParams;
|
|
#endif
|
|
|
|
typedef struct
|
|
{
|
|
bltestIO key; /* unused */
|
|
PRBool restart;
|
|
} bltestHashParams;
|
|
|
|
typedef union
|
|
{
|
|
bltestIO key;
|
|
bltestSymmKeyParams sk;
|
|
bltestRC5Params rc5;
|
|
bltestRSAParams rsa;
|
|
bltestDSAParams dsa;
|
|
#ifdef NSS_ENABLE_ECC
|
|
bltestECDSAParams ecdsa;
|
|
#endif
|
|
bltestHashParams hash;
|
|
} bltestParams;
|
|
|
|
typedef struct bltestCipherInfoStr bltestCipherInfo;
|
|
|
|
struct bltestCipherInfoStr {
|
|
PRArenaPool *arena;
|
|
/* link to next in multithreaded test */
|
|
bltestCipherInfo *next;
|
|
PRThread *cipherThread;
|
|
|
|
/* MonteCarlo test flag*/
|
|
PRBool mCarlo;
|
|
/* 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 repetitionsToPerfom;
|
|
int seconds;
|
|
int repetitions;
|
|
int cxreps;
|
|
double cxtime;
|
|
double optime;
|
|
};
|
|
|
|
PRBool
|
|
is_symmkeyCipher(bltestCipherMode mode)
|
|
{
|
|
/* change as needed! */
|
|
if (mode >= bltestDES_ECB && mode <= bltestAES_CBC)
|
|
return PR_TRUE;
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool
|
|
is_pubkeyCipher(bltestCipherMode mode)
|
|
{
|
|
/* change as needed! */
|
|
if (mode >= bltestRSA && mode <= bltestDSA)
|
|
return PR_TRUE;
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool
|
|
is_hashCipher(bltestCipherMode mode)
|
|
{
|
|
/* change as needed! */
|
|
if (mode >= bltestMD2 && mode <= bltestSHA512)
|
|
return PR_TRUE;
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRBool
|
|
is_sigCipher(bltestCipherMode mode)
|
|
{
|
|
/* change as needed! */
|
|
#ifdef NSS_ENABLE_ECC
|
|
if (mode >= bltestECDSA && mode <= bltestDSA)
|
|
#else
|
|
if (mode >= bltestDSA && mode <= bltestDSA)
|
|
#endif
|
|
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 ||
|
|
mode == bltestAES_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 = SECSuccess;
|
|
SECItem fileData;
|
|
SECItem *in;
|
|
unsigned char *tok;
|
|
unsigned 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; i<in->len; 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; i<in->len; 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 = SECSuccess;
|
|
PRInt32 nb;
|
|
unsigned char byteval;
|
|
SECItem *it;
|
|
char hexstr[5];
|
|
unsigned 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 == (PRInt32)it->len) ? SECSuccess : SECFailure;
|
|
break;
|
|
case bltestHexSpaceDelim:
|
|
hexstr[0] = '0';
|
|
hexstr[1] = 'x';
|
|
hexstr[4] = ' ';
|
|
for (i=0; i<it->len; i++) {
|
|
byteval = it->data[i];
|
|
rv = char2_from_hex(byteval, hexstr + 2);
|
|
nb = PR_Write(file, hexstr, 5);
|
|
if (rv)
|
|
break;
|
|
}
|
|
PR_Write(file, "\n", 1);
|
|
break;
|
|
case bltestHexStream:
|
|
for (i=0; i<it->len; i++) {
|
|
byteval = it->data[i];
|
|
rv = char2_from_hex(byteval, hexstr);
|
|
if (rv)
|
|
break;
|
|
nb = PR_Write(file, hexstr, 2);
|
|
}
|
|
PR_Write(file, "\n", 1);
|
|
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);
|
|
io->buf.len = length + 2*WORDSIZE; /* why doesn't realloc do this? */
|
|
/* 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
|
|
des_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
|
|
unsigned int maxOutputLen, const unsigned char *input,
|
|
unsigned int inputLen)
|
|
{
|
|
return DES_Encrypt((DESContext *)cx, output, outputLen, maxOutputLen,
|
|
input, inputLen);
|
|
}
|
|
|
|
SECStatus
|
|
des_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
|
|
unsigned int maxOutputLen, const unsigned char *input,
|
|
unsigned int inputLen)
|
|
{
|
|
return DES_Decrypt((DESContext *)cx, output, outputLen, maxOutputLen,
|
|
input, inputLen);
|
|
}
|
|
|
|
SECStatus
|
|
rc2_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
|
|
unsigned int maxOutputLen, const unsigned char *input,
|
|
unsigned int inputLen)
|
|
{
|
|
return RC2_Encrypt((RC2Context *)cx, output, outputLen, maxOutputLen,
|
|
input, inputLen);
|
|
}
|
|
|
|
SECStatus
|
|
rc2_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
|
|
unsigned int maxOutputLen, const unsigned char *input,
|
|
unsigned int inputLen)
|
|
{
|
|
return RC2_Decrypt((RC2Context *)cx, output, outputLen, maxOutputLen,
|
|
input, inputLen);
|
|
}
|
|
|
|
SECStatus
|
|
rc4_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
|
|
unsigned int maxOutputLen, const unsigned char *input,
|
|
unsigned int inputLen)
|
|
{
|
|
return RC4_Encrypt((RC4Context *)cx, output, outputLen, maxOutputLen,
|
|
input, inputLen);
|
|
}
|
|
|
|
SECStatus
|
|
rc4_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
|
|
unsigned int maxOutputLen, const unsigned char *input,
|
|
unsigned int inputLen)
|
|
{
|
|
return RC4_Decrypt((RC4Context *)cx, output, outputLen, maxOutputLen,
|
|
input, inputLen);
|
|
}
|
|
|
|
SECStatus
|
|
aes_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
|
|
unsigned int maxOutputLen, const unsigned char *input,
|
|
unsigned int inputLen)
|
|
{
|
|
return AES_Encrypt((AESContext *)cx, output, outputLen, maxOutputLen,
|
|
input, inputLen);
|
|
}
|
|
|
|
SECStatus
|
|
aes_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
|
|
unsigned int maxOutputLen, const unsigned char *input,
|
|
unsigned int inputLen)
|
|
{
|
|
return AES_Decrypt((AESContext *)cx, output, outputLen, maxOutputLen,
|
|
input, inputLen);
|
|
}
|
|
|
|
SECStatus
|
|
rsa_PublicKeyOp(void *key, SECItem *output, const SECItem *input)
|
|
{
|
|
return RSA_PublicKeyOp((RSAPublicKey *)key, output->data, input->data);
|
|
}
|
|
|
|
SECStatus
|
|
rsa_PrivateKeyOp(void *key, SECItem *output, const SECItem *input)
|
|
{
|
|
return RSA_PrivateKeyOp((RSAPrivateKey *)key, output->data, input->data);
|
|
}
|
|
|
|
SECStatus
|
|
dsa_signDigest(void *key, SECItem *output, const SECItem *input)
|
|
{
|
|
return DSA_SignDigest((DSAPrivateKey *)key, output, input);
|
|
}
|
|
|
|
SECStatus
|
|
dsa_verifyDigest(void *key, SECItem *output, const SECItem *input)
|
|
{
|
|
return DSA_VerifyDigest((DSAPublicKey *)key, output, input);
|
|
}
|
|
|
|
#ifdef NSS_ENABLE_ECC
|
|
SECStatus
|
|
ecdsa_signDigest(void *key, SECItem *output, const SECItem *input)
|
|
{
|
|
return ECDSA_SignDigest((ECPrivateKey *)key, output, input);
|
|
}
|
|
|
|
SECStatus
|
|
ecdsa_verifyDigest(void *key, SECItem *output, const SECItem *input)
|
|
{
|
|
return ECDSA_VerifyDigest((ECPublicKey *)key, output, input);
|
|
}
|
|
#endif
|
|
|
|
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; i<cipherInfo->cxreps; i++) {
|
|
dummycx[i] = (void*)DES_CreateContext(desp->key.buf.data,
|
|
desp->iv.buf.data,
|
|
minorMode, encrypt);
|
|
}
|
|
TIMEFINISH(cipherInfo->cxtime, 1.0);
|
|
for (i=0; i<cipherInfo->cxreps; 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; i<cipherInfo->cxreps; 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; i<cipherInfo->cxreps; 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; i<cipherInfo->cxreps; i++) {
|
|
dummycx[i] = (void*)RC4_CreateContext(rc4p->key.buf.data,
|
|
rc4p->key.buf.len);
|
|
}
|
|
TIMEFINISH(cipherInfo->cxtime, 1.0);
|
|
for (i=0; i<cipherInfo->cxreps; 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_aes_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
|
|
{
|
|
bltestSymmKeyParams *aesp = &cipherInfo->params.sk;
|
|
int minorMode;
|
|
int i;
|
|
int keylen = aesp->key.buf.len;
|
|
int blocklen = AES_BLOCK_SIZE;
|
|
PRIntervalTime time1, time2;
|
|
|
|
switch (cipherInfo->mode) {
|
|
case bltestAES_ECB: minorMode = NSS_AES; break;
|
|
case bltestAES_CBC: minorMode = NSS_AES_CBC; break;
|
|
default:
|
|
return SECFailure;
|
|
}
|
|
cipherInfo->cx = (void*)AES_CreateContext(aesp->key.buf.data,
|
|
aesp->iv.buf.data,
|
|
minorMode, encrypt,
|
|
keylen, blocklen);
|
|
if (cipherInfo->cxreps > 0) {
|
|
AESContext **dummycx;
|
|
dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(AESContext *));
|
|
TIMESTART();
|
|
for (i=0; i<cipherInfo->cxreps; i++) {
|
|
dummycx[i] = (void*)AES_CreateContext(aesp->key.buf.data,
|
|
aesp->iv.buf.data,
|
|
minorMode, encrypt,
|
|
keylen, blocklen);
|
|
}
|
|
TIMEFINISH(cipherInfo->cxtime, 1.0);
|
|
for (i=0; i<cipherInfo->cxreps; i++) {
|
|
AES_DestroyContext(dummycx[i], PR_TRUE);
|
|
}
|
|
PORT_Free(dummycx);
|
|
}
|
|
if (encrypt)
|
|
cipherInfo->cipher.symmkeyCipher = aes_Encrypt;
|
|
else
|
|
cipherInfo->cipher.symmkeyCipher = aes_Decrypt;
|
|
return SECSuccess;
|
|
}
|
|
|
|
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; i<cipherInfo->cxreps; i++)
|
|
dummyKey[i] = RSA_NewKey(rsap->keysizeInBits,
|
|
&rsap->rsakey->publicExponent);
|
|
TIMEFINISH(cipherInfo->cxtime, cipherInfo->cxreps);
|
|
/* Free the n key objects */
|
|
for (i=0; i<cipherInfo->cxreps; 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; i<cipherInfo->cxreps; 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; i<cipherInfo->cxreps; 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;
|
|
}
|
|
|
|
#ifdef NSS_ENABLE_ECC
|
|
SECStatus
|
|
bltest_ecdsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
|
|
{
|
|
int i;
|
|
ECPrivateKey **dummyKey;
|
|
PRIntervalTime time1, time2;
|
|
bltestECDSAParams *ecdsap = &cipherInfo->params.ecdsa;
|
|
/* ECDSA key gen was done during parameter setup */
|
|
cipherInfo->cx = cipherInfo->params.ecdsa.eckey;
|
|
/* For performance testing */
|
|
if (cipherInfo->cxreps > 0) {
|
|
/* Create space for n private key objects */
|
|
dummyKey = (ECPrivateKey **)PORT_ZAlloc(cipherInfo->cxreps *
|
|
sizeof(ECPrivateKey *));
|
|
/* Time n keygens, storing in the array */
|
|
TIMESTART();
|
|
for (i=0; i<cipherInfo->cxreps; i++) {
|
|
EC_NewKey(&ecdsap->eckey->ecParams, &dummyKey[i]);
|
|
}
|
|
TIMEFINISH(cipherInfo->cxtime, cipherInfo->cxreps);
|
|
/* Free the n key objects */
|
|
for (i=0; i<cipherInfo->cxreps; i++)
|
|
PORT_FreeArena(dummyKey[i]->ecParams.arena, PR_TRUE);
|
|
PORT_Free(dummyKey);
|
|
}
|
|
if (!cipherInfo->cx && ecdsap->key.buf.len > 0) {
|
|
cipherInfo->cx = eckey_from_filedata(&ecdsap->key.buf);
|
|
}
|
|
if (encrypt) {
|
|
cipherInfo->cipher.pubkeyCipher = ecdsa_signDigest;
|
|
} else {
|
|
/* Have to convert private key to public key. Memory
|
|
* is freed with private key's arena */
|
|
ECPublicKey *pubkey;
|
|
ECPrivateKey *key = (ECPrivateKey *)cipherInfo->cx;
|
|
pubkey = (ECPublicKey *)PORT_ArenaZAlloc(key->ecParams.arena,
|
|
sizeof(ECPublicKey));
|
|
pubkey->ecParams.type = key->ecParams.type;
|
|
pubkey->ecParams.fieldID.size = key->ecParams.fieldID.size;
|
|
pubkey->ecParams.fieldID.type = key->ecParams.fieldID.type;
|
|
pubkey->ecParams.fieldID.u.prime.len = key->ecParams.fieldID.u.prime.len;
|
|
pubkey->ecParams.fieldID.u.prime.data = key->ecParams.fieldID.u.prime.data;
|
|
pubkey->ecParams.fieldID.k1 = key->ecParams.fieldID.k1;
|
|
pubkey->ecParams.fieldID.k2 = key->ecParams.fieldID.k2;
|
|
pubkey->ecParams.fieldID.k3 = key->ecParams.fieldID.k3;
|
|
pubkey->ecParams.curve.a.len = key->ecParams.curve.a.len;
|
|
pubkey->ecParams.curve.a.data = key->ecParams.curve.a.data;
|
|
pubkey->ecParams.curve.b.len = key->ecParams.curve.b.len;
|
|
pubkey->ecParams.curve.b.data = key->ecParams.curve.b.data;
|
|
pubkey->ecParams.curve.seed.len = key->ecParams.curve.seed.len;
|
|
pubkey->ecParams.curve.seed.data = key->ecParams.curve.seed.data;
|
|
pubkey->ecParams.base.len = key->ecParams.base.len;
|
|
pubkey->ecParams.base.data = key->ecParams.base.data;
|
|
pubkey->ecParams.order.len = key->ecParams.order.len;
|
|
pubkey->ecParams.order.data = key->ecParams.order.data;
|
|
pubkey->ecParams.cofactor = key->ecParams.cofactor;
|
|
pubkey->ecParams.DEREncoding.len = key->ecParams.DEREncoding.len;
|
|
pubkey->ecParams.DEREncoding.data = key->ecParams.DEREncoding.data;
|
|
pubkey->ecParams.name= key->ecParams.name;
|
|
pubkey->publicValue.len = key->publicValue.len;
|
|
pubkey->publicValue.data = key->publicValue.data;
|
|
cipherInfo->cipher.pubkeyCipher = ecdsa_verifyDigest;
|
|
}
|
|
return SECSuccess;
|
|
}
|
|
#endif
|
|
|
|
/* XXX unfortunately, this is not defined in blapi.h */
|
|
SECStatus
|
|
md2_HashBuf(unsigned char *dest, const unsigned char *src, uint32 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, uint32 src_length)
|
|
{
|
|
MD2Context *cx, *cx_cpy;
|
|
unsigned char *cxbytes;
|
|
unsigned int len;
|
|
unsigned int i, quarter;
|
|
SECStatus rv = SECSuccess;
|
|
cx = MD2_NewContext();
|
|
MD2_Begin(cx);
|
|
/* divide message by 4, restarting 3 times */
|
|
quarter = (src_length + 3)/ 4;
|
|
for (i=0; i < 4 && src_length > 0; i++) {
|
|
MD2_Update(cx, src + i*quarter, 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_restart failed!\n", progName);
|
|
goto finish;
|
|
}
|
|
MD2_DestroyContext(cx_cpy, PR_TRUE);
|
|
PORT_Free(cxbytes);
|
|
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, uint32 src_length)
|
|
{
|
|
SECStatus rv = SECSuccess;
|
|
MD5Context *cx, *cx_cpy;
|
|
unsigned char *cxbytes;
|
|
unsigned int len;
|
|
unsigned int i, quarter;
|
|
cx = MD5_NewContext();
|
|
MD5_Begin(cx);
|
|
/* divide message by 4, restarting 3 times */
|
|
quarter = (src_length + 3)/ 4;
|
|
for (i=0; i < 4 && src_length > 0; i++) {
|
|
MD5_Update(cx, src + i*quarter, 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);
|
|
rv = SECFailure;
|
|
goto finish;
|
|
}
|
|
rv = PORT_Memcmp(cx, cx_cpy, len);
|
|
if (rv) {
|
|
MD5_DestroyContext(cx_cpy, PR_TRUE);
|
|
PR_fprintf(PR_STDERR, "%s: MD5_restart failed!\n", progName);
|
|
goto finish;
|
|
}
|
|
MD5_DestroyContext(cx_cpy, PR_TRUE);
|
|
PORT_Free(cxbytes);
|
|
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, uint32 src_length)
|
|
{
|
|
SECStatus rv = SECSuccess;
|
|
SHA1Context *cx, *cx_cpy;
|
|
unsigned char *cxbytes;
|
|
unsigned int len;
|
|
unsigned int i, quarter;
|
|
cx = SHA1_NewContext();
|
|
SHA1_Begin(cx);
|
|
/* divide message by 4, restarting 3 times */
|
|
quarter = (src_length + 3)/ 4;
|
|
for (i=0; i < 4 && src_length > 0; i++) {
|
|
SHA1_Update(cx, src + i*quarter, 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);
|
|
rv = SECFailure;
|
|
goto finish;
|
|
}
|
|
rv = PORT_Memcmp(cx, cx_cpy, len);
|
|
if (rv) {
|
|
SHA1_DestroyContext(cx_cpy, PR_TRUE);
|
|
PR_fprintf(PR_STDERR, "%s: SHA1_restart failed!\n", progName);
|
|
goto finish;
|
|
}
|
|
SHA1_DestroyContext(cx_cpy, PR_TRUE);
|
|
PORT_Free(cxbytes);
|
|
src_length -= quarter;
|
|
}
|
|
SHA1_End(cx, dest, &len, MD5_LENGTH);
|
|
finish:
|
|
SHA1_DestroyContext(cx, PR_TRUE);
|
|
return rv;
|
|
}
|
|
|
|
SECStatus
|
|
SHA256_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
|
|
{
|
|
SECStatus rv = SECSuccess;
|
|
SHA256Context *cx, *cx_cpy;
|
|
unsigned char *cxbytes;
|
|
unsigned int len;
|
|
unsigned int i, quarter;
|
|
cx = SHA256_NewContext();
|
|
SHA256_Begin(cx);
|
|
/* divide message by 4, restarting 3 times */
|
|
quarter = (src_length + 3)/ 4;
|
|
for (i=0; i < 4 && src_length > 0; i++) {
|
|
SHA256_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
|
|
len = SHA256_FlattenSize(cx);
|
|
cxbytes = PORT_Alloc(len);
|
|
SHA256_Flatten(cx, cxbytes);
|
|
cx_cpy = SHA256_Resurrect(cxbytes, NULL);
|
|
if (!cx_cpy) {
|
|
PR_fprintf(PR_STDERR, "%s: SHA256_Resurrect failed!\n", progName);
|
|
rv = SECFailure;
|
|
goto finish;
|
|
}
|
|
rv = PORT_Memcmp(cx, cx_cpy, len);
|
|
if (rv) {
|
|
SHA256_DestroyContext(cx_cpy, PR_TRUE);
|
|
PR_fprintf(PR_STDERR, "%s: SHA256_restart failed!\n", progName);
|
|
goto finish;
|
|
}
|
|
SHA256_DestroyContext(cx_cpy, PR_TRUE);
|
|
PORT_Free(cxbytes);
|
|
src_length -= quarter;
|
|
}
|
|
SHA256_End(cx, dest, &len, MD5_LENGTH);
|
|
finish:
|
|
SHA256_DestroyContext(cx, PR_TRUE);
|
|
return rv;
|
|
}
|
|
|
|
SECStatus
|
|
SHA384_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
|
|
{
|
|
SECStatus rv = SECSuccess;
|
|
SHA384Context *cx, *cx_cpy;
|
|
unsigned char *cxbytes;
|
|
unsigned int len;
|
|
unsigned int i, quarter;
|
|
cx = SHA384_NewContext();
|
|
SHA384_Begin(cx);
|
|
/* divide message by 4, restarting 3 times */
|
|
quarter = (src_length + 3)/ 4;
|
|
for (i=0; i < 4 && src_length > 0; i++) {
|
|
SHA384_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
|
|
len = SHA384_FlattenSize(cx);
|
|
cxbytes = PORT_Alloc(len);
|
|
SHA384_Flatten(cx, cxbytes);
|
|
cx_cpy = SHA384_Resurrect(cxbytes, NULL);
|
|
if (!cx_cpy) {
|
|
PR_fprintf(PR_STDERR, "%s: SHA384_Resurrect failed!\n", progName);
|
|
rv = SECFailure;
|
|
goto finish;
|
|
}
|
|
rv = PORT_Memcmp(cx, cx_cpy, len);
|
|
if (rv) {
|
|
SHA384_DestroyContext(cx_cpy, PR_TRUE);
|
|
PR_fprintf(PR_STDERR, "%s: SHA384_restart failed!\n", progName);
|
|
goto finish;
|
|
}
|
|
SHA384_DestroyContext(cx_cpy, PR_TRUE);
|
|
PORT_Free(cxbytes);
|
|
src_length -= quarter;
|
|
}
|
|
SHA384_End(cx, dest, &len, MD5_LENGTH);
|
|
finish:
|
|
SHA384_DestroyContext(cx, PR_TRUE);
|
|
return rv;
|
|
}
|
|
|
|
SECStatus
|
|
SHA512_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
|
|
{
|
|
SECStatus rv = SECSuccess;
|
|
SHA512Context *cx, *cx_cpy;
|
|
unsigned char *cxbytes;
|
|
unsigned int len;
|
|
unsigned int i, quarter;
|
|
cx = SHA512_NewContext();
|
|
SHA512_Begin(cx);
|
|
/* divide message by 4, restarting 3 times */
|
|
quarter = (src_length + 3)/ 4;
|
|
for (i=0; i < 4 && src_length > 0; i++) {
|
|
SHA512_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
|
|
len = SHA512_FlattenSize(cx);
|
|
cxbytes = PORT_Alloc(len);
|
|
SHA512_Flatten(cx, cxbytes);
|
|
cx_cpy = SHA512_Resurrect(cxbytes, NULL);
|
|
if (!cx_cpy) {
|
|
PR_fprintf(PR_STDERR, "%s: SHA512_Resurrect failed!\n", progName);
|
|
rv = SECFailure;
|
|
goto finish;
|
|
}
|
|
rv = PORT_Memcmp(cx, cx_cpy, len);
|
|
if (rv) {
|
|
SHA512_DestroyContext(cx_cpy, PR_TRUE);
|
|
PR_fprintf(PR_STDERR, "%s: SHA512_restart failed!\n", progName);
|
|
goto finish;
|
|
}
|
|
SHA512_DestroyContext(cx_cpy, PR_TRUE);
|
|
PORT_Free(cxbytes);
|
|
src_length -= quarter;
|
|
}
|
|
SHA512_End(cx, dest, &len, MD5_LENGTH);
|
|
finish:
|
|
SHA512_DestroyContext(cx, PR_TRUE);
|
|
return rv;
|
|
}
|
|
|
|
SECStatus
|
|
pubkeyInitKey(bltestCipherInfo *cipherInfo, PRFileDesc *file,
|
|
#ifdef NSS_ENABLE_ECC
|
|
int keysize, int exponent, char *curveName)
|
|
#else
|
|
int keysize, int exponent)
|
|
#endif
|
|
{
|
|
int i;
|
|
SECStatus rv = SECSuccess;
|
|
bltestRSAParams *rsap;
|
|
bltestDSAParams *dsap;
|
|
#ifdef NSS_ENABLE_ECC
|
|
bltestECDSAParams *ecdsap;
|
|
SECItem *tmpECParamsDER;
|
|
ECParams *tmpECParams = NULL;
|
|
SECItem ecSerialize[3];
|
|
#endif
|
|
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;
|
|
#ifdef NSS_ENABLE_ECC
|
|
case bltestECDSA:
|
|
ecdsap = &cipherInfo->params.ecdsa;
|
|
if (curveName != NULL) {
|
|
tmpECParamsDER = getECParams(curveName);
|
|
rv = secoid_Init();
|
|
CHECKERROR(rv, __LINE__);
|
|
rv = EC_DecodeParams(tmpECParamsDER, &tmpECParams) == SECFailure;
|
|
CHECKERROR(rv, __LINE__);
|
|
rv = EC_NewKey(tmpECParams, &ecdsap->eckey);
|
|
CHECKERROR(rv, __LINE__);
|
|
ecSerialize[0].type = tmpECParamsDER->type;
|
|
ecSerialize[0].data = tmpECParamsDER->data;
|
|
ecSerialize[0].len = tmpECParamsDER->len;
|
|
ecSerialize[1].type = ecdsap->eckey->publicValue.type;
|
|
ecSerialize[1].data = ecdsap->eckey->publicValue.data;
|
|
ecSerialize[1].len = ecdsap->eckey->publicValue.len;
|
|
ecSerialize[2].type = ecdsap->eckey->privateValue.type;
|
|
ecSerialize[2].data = ecdsap->eckey->privateValue.data;
|
|
ecSerialize[2].len = ecdsap->eckey->privateValue.len;
|
|
serialize_key(&(ecSerialize[0]), 3, file);
|
|
SECITEM_FreeItem(tmpECParamsDER, PR_TRUE);
|
|
PORT_FreeArena(tmpECParams->arena, PR_TRUE);
|
|
rv = SECOID_Shutdown();
|
|
CHECKERROR(rv, __LINE__);
|
|
} else {
|
|
setupIO(cipherInfo->arena, &cipherInfo->params.key, file, NULL, 0);
|
|
ecdsap->eckey = eckey_from_filedata(&cipherInfo->params.key.buf);
|
|
}
|
|
break;
|
|
#endif
|
|
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 bltestAES_ECB:
|
|
case bltestAES_CBC:
|
|
SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
|
|
cipherInfo->input.pBuf.len);
|
|
return bltest_aes_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;
|
|
#ifdef NSS_ENABLE_ECC
|
|
case bltestECDSA:
|
|
SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
|
|
2 * MAX_ECKEY_LEN);
|
|
return bltest_ecdsa_init(cipherInfo, encrypt);
|
|
break;
|
|
#endif
|
|
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 SECSuccess;
|
|
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 SECSuccess;
|
|
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 SECSuccess;
|
|
break;
|
|
case bltestSHA256:
|
|
restart = cipherInfo->params.hash.restart;
|
|
SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
|
|
SHA256_LENGTH);
|
|
cipherInfo->cipher.hashCipher = (restart) ? SHA256_restart
|
|
: SHA256_HashBuf;
|
|
return SECSuccess;
|
|
break;
|
|
case bltestSHA384:
|
|
restart = cipherInfo->params.hash.restart;
|
|
SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
|
|
SHA384_LENGTH);
|
|
cipherInfo->cipher.hashCipher = (restart) ? SHA384_restart
|
|
: SHA384_HashBuf;
|
|
return SECSuccess;
|
|
break;
|
|
case bltestSHA512:
|
|
restart = cipherInfo->params.hash.restart;
|
|
SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
|
|
SHA512_LENGTH);
|
|
cipherInfo->cipher.hashCipher = (restart) ? SHA512_restart
|
|
: SHA512_HashBuf;
|
|
return SECSuccess;
|
|
break;
|
|
default:
|
|
return SECFailure;
|
|
}
|
|
return SECSuccess;
|
|
}
|
|
|
|
SECStatus
|
|
dsaOp(bltestCipherInfo *cipherInfo)
|
|
{
|
|
PRIntervalTime time1, time2;
|
|
SECStatus rv = SECSuccess;
|
|
int i;
|
|
int maxLen = cipherInfo->output.pBuf.len;
|
|
SECItem dummyOut = { 0, 0, 0 };
|
|
SECITEM_AllocItem(NULL, &dummyOut, maxLen);
|
|
if (cipherInfo->cipher.pubkeyCipher == dsa_signDigest) {
|
|
if (cipherInfo->params.dsa.sigseed.buf.len > 0) {
|
|
bltestDSAParams *dsa = &cipherInfo->params.dsa;
|
|
DSAPrivateKey *key = (DSAPrivateKey *)cipherInfo->cx;
|
|
|
|
TIMESTART();
|
|
rv = DSA_SignDigestWithSeed(key,
|
|
&cipherInfo->output.pBuf,
|
|
&cipherInfo->input.pBuf,
|
|
dsa->sigseed.buf.data);
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
CHECKERROR(rv, __LINE__);
|
|
cipherInfo->repetitions = 0;
|
|
if (cipherInfo->repetitionsToPerfom != 0) {
|
|
TIMESTART();
|
|
for (i=0; i<cipherInfo->repetitionsToPerfom;
|
|
i++, cipherInfo->repetitions++) {
|
|
rv = DSA_SignDigestWithSeed(key, &dummyOut,
|
|
&cipherInfo->input.pBuf,
|
|
dsa->sigseed.buf.data);
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
} else {
|
|
int opsBetweenChecks = 0;
|
|
TIMEMARK(cipherInfo->seconds);
|
|
while (! (TIMETOFINISH())) {
|
|
int j = 0;
|
|
for (;j < opsBetweenChecks;j++) {
|
|
rv = DSA_SignDigestWithSeed(key, &dummyOut,
|
|
&cipherInfo->input.pBuf,
|
|
dsa->sigseed.buf.data);
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
cipherInfo->repetitions += j;
|
|
}
|
|
}
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
} else {
|
|
TIMESTART();
|
|
rv = DSA_SignDigest((DSAPrivateKey *)cipherInfo->cx,
|
|
&cipherInfo->output.pBuf,
|
|
&cipherInfo->input.pBuf);
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
CHECKERROR(rv, __LINE__);
|
|
cipherInfo->repetitions = 0;
|
|
if (cipherInfo->repetitionsToPerfom != 0) {
|
|
TIMESTART();
|
|
for (i=0; i<cipherInfo->repetitionsToPerfom;
|
|
i++, cipherInfo->repetitions++) {
|
|
rv = DSA_SignDigest((DSAPrivateKey *)cipherInfo->cx,
|
|
&dummyOut,
|
|
&cipherInfo->input.pBuf);
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
} else {
|
|
int opsBetweenChecks = 0;
|
|
TIMEMARK(cipherInfo->seconds);
|
|
while (! (TIMETOFINISH())) {
|
|
int j = 0;
|
|
for (;j < opsBetweenChecks;j++) {
|
|
rv = DSA_SignDigest((DSAPrivateKey *)cipherInfo->cx,
|
|
&dummyOut,
|
|
&cipherInfo->input.pBuf);
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
cipherInfo->repetitions += j;
|
|
}
|
|
}
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
}
|
|
bltestCopyIO(cipherInfo->arena, &cipherInfo->params.dsa.sig,
|
|
&cipherInfo->output);
|
|
} else {
|
|
TIMESTART();
|
|
rv = DSA_VerifyDigest((DSAPublicKey *)cipherInfo->cx,
|
|
&cipherInfo->params.dsa.sig.buf,
|
|
&cipherInfo->input.pBuf);
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
CHECKERROR(rv, __LINE__);
|
|
cipherInfo->repetitions = 0;
|
|
if (cipherInfo->repetitionsToPerfom != 0) {
|
|
TIMESTART();
|
|
for (i=0; i<cipherInfo->repetitionsToPerfom;
|
|
i++, cipherInfo->repetitions++) {
|
|
rv = DSA_VerifyDigest((DSAPublicKey *)cipherInfo->cx,
|
|
&cipherInfo->params.dsa.sig.buf,
|
|
&cipherInfo->input.pBuf);
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
} else {
|
|
int opsBetweenChecks = 0;
|
|
TIMEMARK(cipherInfo->seconds);
|
|
while (! (TIMETOFINISH())) {
|
|
int j = 0;
|
|
for (;j < opsBetweenChecks;j++) {
|
|
rv = DSA_VerifyDigest((DSAPublicKey *)cipherInfo->cx,
|
|
&cipherInfo->params.dsa.sig.buf,
|
|
&cipherInfo->input.pBuf);
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
cipherInfo->repetitions += j;
|
|
}
|
|
}
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
}
|
|
SECITEM_FreeItem(&dummyOut, PR_FALSE);
|
|
return rv;
|
|
}
|
|
|
|
#ifdef NSS_ENABLE_ECC
|
|
SECStatus
|
|
ecdsaOp(bltestCipherInfo *cipherInfo)
|
|
{
|
|
PRIntervalTime time1, time2;
|
|
SECStatus rv = SECSuccess;
|
|
int i;
|
|
int maxLen = cipherInfo->output.pBuf.len;
|
|
SECItem dummyOut = { 0, 0, 0 };
|
|
SECITEM_AllocItem(NULL, &dummyOut, maxLen);
|
|
if (cipherInfo->cipher.pubkeyCipher == ecdsa_signDigest) {
|
|
if (cipherInfo->params.ecdsa.sigseed.buf.len > 0) {
|
|
ECPrivateKey *key = (ECPrivateKey *)cipherInfo->cx;
|
|
bltestECDSAParams *ecdsa = &cipherInfo->params.ecdsa;
|
|
|
|
TIMESTART();
|
|
rv = ECDSA_SignDigestWithSeed(key,
|
|
&cipherInfo->output.pBuf,
|
|
&cipherInfo->input.pBuf,
|
|
ecdsa->sigseed.buf.data,
|
|
ecdsa->sigseed.buf.len);
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
CHECKERROR(rv, __LINE__);
|
|
cipherInfo->repetitions = 0;
|
|
if (cipherInfo->repetitionsToPerfom != 0) {
|
|
TIMESTART();
|
|
for (i=0; i<cipherInfo->repetitionsToPerfom;
|
|
i++, cipherInfo->repetitions++) {
|
|
rv = ECDSA_SignDigestWithSeed(key, &dummyOut,
|
|
&cipherInfo->input.pBuf,
|
|
ecdsa->sigseed.buf.data,
|
|
ecdsa->sigseed.buf.len);
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
} else {
|
|
int opsBetweenChecks = 0;
|
|
TIMEMARK(cipherInfo->seconds);
|
|
while (! (TIMETOFINISH())) {
|
|
int j = 0;
|
|
for (;j < opsBetweenChecks;j++) {
|
|
rv = ECDSA_SignDigestWithSeed(key, &dummyOut,
|
|
&cipherInfo->input.pBuf,
|
|
ecdsa->sigseed.buf.data,
|
|
ecdsa->sigseed.buf.len);
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
cipherInfo->repetitions += j;
|
|
}
|
|
}
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
} else {
|
|
TIMESTART();
|
|
rv = ECDSA_SignDigest((ECPrivateKey *)cipherInfo->cx,
|
|
&cipherInfo->output.pBuf,
|
|
&cipherInfo->input.pBuf);
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
CHECKERROR(rv, __LINE__);
|
|
cipherInfo->repetitions = 0;
|
|
if (cipherInfo->repetitionsToPerfom != 0) {
|
|
TIMESTART();
|
|
for (i=0; i<cipherInfo->repetitionsToPerfom;
|
|
i++, cipherInfo->repetitions++) {
|
|
rv = ECDSA_SignDigest((ECPrivateKey *)cipherInfo->cx,
|
|
&dummyOut,
|
|
&cipherInfo->input.pBuf);
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
} else {
|
|
int opsBetweenChecks = 0;
|
|
TIMEMARK(cipherInfo->seconds);
|
|
while (! (TIMETOFINISH())) {
|
|
int j = 0;
|
|
for (;j < opsBetweenChecks;j++) {
|
|
rv = ECDSA_SignDigest((ECPrivateKey *)cipherInfo->cx,
|
|
&dummyOut,
|
|
&cipherInfo->input.pBuf);
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
cipherInfo->repetitions += j;
|
|
}
|
|
}
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
}
|
|
bltestCopyIO(cipherInfo->arena, &cipherInfo->params.ecdsa.sig,
|
|
&cipherInfo->output);
|
|
} else {
|
|
TIMESTART();
|
|
rv = ECDSA_VerifyDigest((ECPublicKey *)cipherInfo->cx,
|
|
&cipherInfo->params.ecdsa.sig.buf,
|
|
&cipherInfo->input.pBuf);
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
CHECKERROR(rv, __LINE__);
|
|
cipherInfo->repetitions = 0;
|
|
if (cipherInfo->repetitionsToPerfom != 0) {
|
|
TIMESTART();
|
|
for (i=0; i<cipherInfo->repetitionsToPerfom;
|
|
i++, cipherInfo->repetitions++) {
|
|
rv = ECDSA_VerifyDigest((ECPublicKey *)cipherInfo->cx,
|
|
&cipherInfo->params.ecdsa.sig.buf,
|
|
&cipherInfo->input.pBuf);
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
} else {
|
|
int opsBetweenChecks = 0;
|
|
TIMEMARK(cipherInfo->seconds);
|
|
while (! (TIMETOFINISH())) {
|
|
int j = 0;
|
|
for (;j < opsBetweenChecks;j++) {
|
|
rv = ECDSA_VerifyDigest((ECPublicKey *)cipherInfo->cx,
|
|
&cipherInfo->params.ecdsa.sig.buf,
|
|
&cipherInfo->input.pBuf);
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
cipherInfo->repetitions += j;
|
|
}
|
|
}
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
}
|
|
SECITEM_FreeItem(&dummyOut, PR_FALSE);
|
|
return rv;
|
|
}
|
|
#endif
|
|
|
|
SECStatus
|
|
cipherDoOp(bltestCipherInfo *cipherInfo)
|
|
{
|
|
PRIntervalTime time1, time2;
|
|
SECStatus rv = SECSuccess;
|
|
int i, len;
|
|
int maxLen = cipherInfo->output.pBuf.len;
|
|
unsigned char *dummyOut;
|
|
if (cipherInfo->mode == bltestDSA)
|
|
return dsaOp(cipherInfo);
|
|
#ifdef NSS_ENABLE_ECC
|
|
else if (cipherInfo->mode == bltestECDSA)
|
|
return ecdsaOp(cipherInfo);
|
|
#endif
|
|
dummyOut = PORT_Alloc(maxLen);
|
|
if (is_symmkeyCipher(cipherInfo->mode)) {
|
|
TIMESTART();
|
|
rv = (*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx,
|
|
cipherInfo->output.pBuf.data,
|
|
&len, maxLen,
|
|
cipherInfo->input.pBuf.data,
|
|
cipherInfo->input.pBuf.len);
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
CHECKERROR(rv, __LINE__);
|
|
cipherInfo->repetitions = 0;
|
|
if (cipherInfo->repetitionsToPerfom != 0) {
|
|
TIMESTART();
|
|
for (i=0; i<cipherInfo->repetitionsToPerfom; i++,
|
|
cipherInfo->repetitions++) {
|
|
(*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx, dummyOut,
|
|
&len, maxLen,
|
|
cipherInfo->input.pBuf.data,
|
|
cipherInfo->input.pBuf.len);
|
|
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
} else {
|
|
int opsBetweenChecks = 0;
|
|
bltestIO *input = &cipherInfo->input;
|
|
TIMEMARK(cipherInfo->seconds);
|
|
while (! (TIMETOFINISH())) {
|
|
int j = 0;
|
|
for (;j < opsBetweenChecks;j++) {
|
|
(*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx,
|
|
dummyOut,
|
|
&len, maxLen,
|
|
input->pBuf.data,
|
|
input->pBuf.len);
|
|
}
|
|
cipherInfo->repetitions += j;
|
|
}
|
|
}
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
} else if (is_pubkeyCipher(cipherInfo->mode)) {
|
|
TIMESTART();
|
|
rv = (*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx,
|
|
&cipherInfo->output.pBuf,
|
|
&cipherInfo->input.pBuf);
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
CHECKERROR(rv, __LINE__);
|
|
cipherInfo->repetitions = 0;
|
|
if (cipherInfo->repetitionsToPerfom != 0) {
|
|
TIMESTART();
|
|
for (i=0; i<cipherInfo->repetitionsToPerfom;
|
|
i++, cipherInfo->repetitions++) {
|
|
SECItem dummy;
|
|
dummy.data = dummyOut;
|
|
dummy.len = maxLen;
|
|
(*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx, &dummy,
|
|
&cipherInfo->input.pBuf);
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
} else {
|
|
int opsBetweenChecks = 0;
|
|
TIMEMARK(cipherInfo->seconds);
|
|
while (! (TIMETOFINISH())) {
|
|
int j = 0;
|
|
for (;j < opsBetweenChecks;j++) {
|
|
SECItem dummy;
|
|
dummy.data = dummyOut;
|
|
dummy.len = maxLen;
|
|
(*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx, &dummy,
|
|
&cipherInfo->input.pBuf);
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
cipherInfo->repetitions += j;
|
|
}
|
|
}
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
} else if (is_hashCipher(cipherInfo->mode)) {
|
|
TIMESTART();
|
|
rv = (*cipherInfo->cipher.hashCipher)(cipherInfo->output.pBuf.data,
|
|
cipherInfo->input.pBuf.data,
|
|
cipherInfo->input.pBuf.len);
|
|
TIMEFINISH(cipherInfo->optime, 1.0);
|
|
CHECKERROR(rv, __LINE__);
|
|
cipherInfo->repetitions = 0;
|
|
if (cipherInfo->repetitionsToPerfom != 0) {
|
|
TIMESTART();
|
|
for (i=0; i<cipherInfo->repetitionsToPerfom;
|
|
i++, cipherInfo->repetitions++) {
|
|
(*cipherInfo->cipher.hashCipher)(dummyOut,
|
|
cipherInfo->input.pBuf.data,
|
|
cipherInfo->input.pBuf.len);
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
} else {
|
|
int opsBetweenChecks = 0;
|
|
TIMEMARK(cipherInfo->seconds);
|
|
while (! (TIMETOFINISH())) {
|
|
int j = 0;
|
|
for (;j < opsBetweenChecks;j++) {
|
|
bltestIO *input = &cipherInfo->input;
|
|
(*cipherInfo->cipher.hashCipher)(dummyOut,
|
|
input->pBuf.data,
|
|
input->pBuf.len);
|
|
CHECKERROR(rv, __LINE__);
|
|
}
|
|
cipherInfo->repetitions += j;
|
|
}
|
|
}
|
|
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 bltestAES_ECB:
|
|
case bltestAES_CBC:
|
|
AES_DestroyContext((AESContext *)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. */
|
|
#ifdef NSS_ENABLE_ECC
|
|
case bltestECDSA:
|
|
#endif
|
|
case bltestMD2: /* hash contexts are ephemeral */
|
|
case bltestMD5:
|
|
case bltestSHA1:
|
|
case bltestSHA256:
|
|
case bltestSHA384:
|
|
case bltestSHA512:
|
|
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);
|
|
}
|
|
}
|
|
|
|
static void
|
|
splitToReportUnit(PRInt64 res, int *resArr, int *del, int size)
|
|
{
|
|
PRInt64 remaining = res, tmp = 0;
|
|
PRInt64 Ldel;
|
|
int i = -1;
|
|
|
|
while (remaining > 0 && ++i < size) {
|
|
LL_I2L(Ldel, del[i]);
|
|
LL_MOD(tmp, remaining, Ldel);
|
|
LL_L2I(resArr[i], tmp);
|
|
LL_DIV(remaining, remaining, Ldel);
|
|
}
|
|
}
|
|
|
|
static char*
|
|
getHighUnitBytes(PRInt64 res)
|
|
{
|
|
int spl[] = {0, 0, 0, 0};
|
|
int del[] = {1024, 1024, 1024, 1024};
|
|
char *marks[] = {"b", "Kb", "Mb", "Gb"};
|
|
int i = 3;
|
|
|
|
splitToReportUnit(res, spl, del, 4);
|
|
|
|
for (;i>0;i--) {
|
|
if (spl[i] != 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return PR_smprintf("%d%s", spl[i], marks[i]);
|
|
}
|
|
|
|
|
|
static void
|
|
printPR_smpString(const char *sformat, char *reportStr,
|
|
const char *nformat, PRInt64 rNum)
|
|
{
|
|
if (reportStr) {
|
|
fprintf(stdout, sformat, reportStr);
|
|
PR_smprintf_free(reportStr);
|
|
} else {
|
|
int prnRes;
|
|
LL_L2I(prnRes, rNum);
|
|
fprintf(stdout, nformat, rNum);
|
|
}
|
|
}
|
|
|
|
static char*
|
|
getHighUnitOps(PRInt64 res)
|
|
{
|
|
int spl[] = {0, 0, 0, 0};
|
|
int del[] = {1000, 1000, 1000, 1000};
|
|
char *marks[] = {"", "T", "M", "B"};
|
|
int i = 3;
|
|
|
|
splitToReportUnit(res, spl, del, 4);
|
|
|
|
for (;i>0;i--) {
|
|
if (spl[i] != 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return PR_smprintf("%d%s", spl[i], marks[i]);
|
|
}
|
|
|
|
void
|
|
dump_performance_info(bltestCipherInfo *infoList, double totalTimeInt,
|
|
PRBool encrypt, PRBool cxonly)
|
|
{
|
|
bltestCipherInfo *info = infoList;
|
|
|
|
PRInt64 totalIn = 0;
|
|
PRBool td = PR_TRUE;
|
|
|
|
int repetitions = 0;
|
|
int cxreps = 0;
|
|
double cxtime = 0;
|
|
double optime = 0;
|
|
while (info != NULL) {
|
|
repetitions += info->repetitions;
|
|
cxreps += info->cxreps;
|
|
cxtime += info->cxtime;
|
|
optime += info->optime;
|
|
totalIn += info->input.buf.len * info->repetitions;
|
|
|
|
info = info->next;
|
|
}
|
|
info = infoList;
|
|
|
|
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 bltestAES_ECB:
|
|
case bltestAES_CBC:
|
|
case bltestRC2_ECB:
|
|
case bltestRC2_CBC:
|
|
case bltestRC4:
|
|
if (td)
|
|
fprintf(stdout, "%8s", "symmkey");
|
|
else
|
|
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;
|
|
#ifdef NSS_ENABLE_ECC
|
|
case bltestECDSA:
|
|
if (td)
|
|
fprintf(stdout, "%12s", "ec_curve");
|
|
else {
|
|
ECCurveName curveName = info->params.ecdsa.eckey->ecParams.name;
|
|
fprintf(stdout, "%12s",
|
|
ecCurve_map[curveName]? ecCurve_map[curveName]->text:
|
|
"Unsupported curve");
|
|
}
|
|
break;
|
|
#endif
|
|
case bltestMD2:
|
|
case bltestMD5:
|
|
case bltestSHA1:
|
|
case bltestSHA256:
|
|
case bltestSHA384:
|
|
case bltestSHA512:
|
|
default:
|
|
break;
|
|
}
|
|
if (!td) {
|
|
PRInt64 totalThroughPut;
|
|
|
|
printPR_smpString("%8s", getHighUnitOps(repetitions),
|
|
"%8d", repetitions);
|
|
|
|
printPR_smpString("%8s", getHighUnitOps(cxreps), "%8d", cxreps);
|
|
|
|
fprintf(stdout, "%12.3f", cxtime);
|
|
fprintf(stdout, "%12.3f", optime);
|
|
fprintf(stdout, "%12.03f", totalTimeInt / 1000);
|
|
|
|
totalThroughPut = (PRInt64)(totalIn / totalTimeInt * 1000);
|
|
printPR_smpString("%12s", getHighUnitBytes(totalThroughPut),
|
|
"%12d", totalThroughPut);
|
|
|
|
fprintf(stdout, "\n");
|
|
return;
|
|
}
|
|
|
|
fprintf(stdout, "%8s", "opreps");
|
|
fprintf(stdout, "%8s", "cxreps");
|
|
fprintf(stdout, "%12s", "context");
|
|
fprintf(stdout, "%12s", "op");
|
|
fprintf(stdout, "%12s", "time(sec)");
|
|
fprintf(stdout, "%12s", "thrgput");
|
|
fprintf(stdout, "\n");
|
|
fprintf(stdout, "%8s", mode_strings[info->mode]);
|
|
fprintf(stdout, "_%c", (cxonly) ? 'c' : (encrypt) ? 'e' : 'd');
|
|
printPR_smpString("%12s", getHighUnitBytes(totalIn), "%12d", totalIn);
|
|
|
|
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; mode<nummodes; mode++)
|
|
fprintf(stderr, "%s\n", mode_strings[mode]);
|
|
}
|
|
|
|
bltestCipherMode
|
|
get_mode(const char *modestring)
|
|
{
|
|
bltestCipherMode mode;
|
|
int nummodes = sizeof(mode_strings) / sizeof(char *);
|
|
for (mode=0; mode<nummodes; mode++)
|
|
if (PL_strcmp(modestring, mode_strings[mode]) == 0)
|
|
return mode;
|
|
fprintf(stderr, "%s: invalid mode: %s\n", progName, modestring);
|
|
return bltestINVALID;
|
|
}
|
|
|
|
void
|
|
load_file_data(PRArenaPool *arena, bltestIO *data,
|
|
char *fn, bltestIOMode ioMode)
|
|
{
|
|
PRFileDesc *file;
|
|
data->mode = 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:
|
|
case bltestAES_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:
|
|
case bltestAES_ECB:
|
|
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) {
|
|
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;
|
|
}
|
|
break;
|
|
#endif
|
|
case bltestRSA:
|
|
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
|
|
load_file_data(arena, ¶ms->rsa.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;
|
|
#ifdef NSS_ENABLE_ECC
|
|
case bltestECDSA:
|
|
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
|
|
load_file_data(arena, ¶ms->ecdsa.key, filename, bltestBase64Encoded);
|
|
params->ecdsa.eckey = eckey_from_filedata(¶ms->key.buf);
|
|
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "sigseed", j);
|
|
load_file_data(arena, ¶ms->ecdsa.sigseed, filename,
|
|
bltestBase64Encoded);
|
|
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "ciphertext",j);
|
|
load_file_data(arena, ¶ms->ecdsa.sig, filename, bltestBase64Encoded);
|
|
break;
|
|
#endif
|
|
case bltestMD2:
|
|
case bltestMD5:
|
|
case bltestSHA1:
|
|
case bltestSHA256:
|
|
case bltestSHA384:
|
|
case bltestSHA512:
|
|
/*params->hash.restart = PR_TRUE;*/
|
|
params->hash.restart = PR_FALSE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
SECStatus
|
|
verify_self_test(bltestIO *result, bltestIO *cmp, bltestCipherMode mode,
|
|
PRBool forward, SECStatus sigstatus)
|
|
{
|
|
int res;
|
|
char *modestr = mode_strings[mode];
|
|
res = SECITEM_CompareItem(&result->pBuf, &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 sigstatus;
|
|
} 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);
|
|
}
|
|
|
|
static SECStatus
|
|
blapi_selftest(bltestCipherMode *modes, int numModes, int inoff, int outoff,
|
|
PRBool encrypt, PRBool decrypt)
|
|
{
|
|
bltestCipherInfo cipherInfo;
|
|
bltestIO pt, ct;
|
|
bltestCipherMode mode;
|
|
bltestParams *params;
|
|
int i, j, nummodes, numtests;
|
|
char *modestr;
|
|
char filename[256];
|
|
PRFileDesc *file;
|
|
PRArenaPool *arena;
|
|
SECItem item;
|
|
PRBool finished;
|
|
SECStatus rv = SECSuccess, 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;
|
|
if (mode == bltestINVALID) {
|
|
fprintf(stderr, "%s: Skipping invalid mode.\n",progName);
|
|
continue;
|
|
}
|
|
modestr = mode_strings[mode];
|
|
cipherInfo.mode = mode;
|
|
params = &cipherInfo.params;
|
|
#ifdef TRACK_BLTEST_BUG
|
|
if (mode == bltestRSA) {
|
|
fprintf(stderr, "[%s] Self-Testing RSA\n", __bltDBG);
|
|
}
|
|
#endif
|
|
/* 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);
|
|
#ifdef TRACK_BLTEST_BUG
|
|
if (mode == bltestRSA) {
|
|
fprintf(stderr, "[%s] Loaded data from %s\n", __bltDBG, filename);
|
|
}
|
|
#endif
|
|
PR_Close(file);
|
|
/* loop over the tests in the directory */
|
|
numtests = 0;
|
|
for (j=0; j<item.len; j++) {
|
|
if (!isdigit(item.data[j])) {
|
|
break;
|
|
}
|
|
numtests *= 10;
|
|
numtests += (int) (item.data[j] - '0');
|
|
}
|
|
for (j=0; j<numtests; j++) {
|
|
#ifdef TRACK_BLTEST_BUG
|
|
if (mode == bltestRSA) {
|
|
fprintf(stderr, "[%s] Executing self-test #%d\n", __bltDBG, j);
|
|
}
|
|
#endif
|
|
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr,
|
|
"plaintext", j);
|
|
load_file_data(arena, &pt, filename,
|
|
#ifdef NSS_ENABLE_ECC
|
|
((mode == bltestDSA) || (mode == bltestECDSA))
|
|
#else
|
|
(mode == bltestDSA)
|
|
#endif
|
|
? bltestBase64Encoded : bltestBinary);
|
|
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr,
|
|
"ciphertext", j);
|
|
load_file_data(arena, &ct, filename, bltestBase64Encoded);
|
|
#ifdef TRACK_BLTEST_BUG
|
|
if (mode == bltestRSA) {
|
|
fprintf(stderr, "[%s] Loaded data for self-test #%d\n", __bltDBG, j);
|
|
}
|
|
#endif
|
|
get_params(arena, params, mode, j);
|
|
#ifdef TRACK_BLTEST_BUG
|
|
if (mode == bltestRSA) {
|
|
fprintf(stderr, "[%s] Got parameters for #%d\n", __bltDBG, j);
|
|
}
|
|
#endif
|
|
/* Forward Operation (Encrypt/Sign/Hash)
|
|
** Align the input buffer (plaintext) according to request
|
|
** then perform operation and compare to ciphertext
|
|
*/
|
|
/* XXX for now */
|
|
rv = SECSuccess;
|
|
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);
|
|
#ifdef TRACK_BLTEST_BUG
|
|
if (mode == bltestRSA) {
|
|
fprintf(stderr, "[%s] Inited cipher context and buffers for #%d\n", __bltDBG, j);
|
|
}
|
|
#endif
|
|
rv |= cipherDoOp(&cipherInfo);
|
|
#ifdef TRACK_BLTEST_BUG
|
|
if (mode == bltestRSA) {
|
|
fprintf(stderr, "[%s] Performed encrypt for #%d\n", __bltDBG, j);
|
|
}
|
|
#endif
|
|
rv |= cipherFinish(&cipherInfo);
|
|
#ifdef TRACK_BLTEST_BUG
|
|
if (mode == bltestRSA) {
|
|
fprintf(stderr, "[%s] Finished encrypt for #%d\n", __bltDBG, j);
|
|
}
|
|
#endif
|
|
rv |= verify_self_test(&cipherInfo.output,
|
|
&ct, mode, PR_TRUE, 0);
|
|
#ifdef TRACK_BLTEST_BUG
|
|
if (mode == bltestRSA) {
|
|
fprintf(stderr, "[%s] Verified self-test for #%d\n", __bltDBG, j);
|
|
}
|
|
#endif
|
|
/* If testing hash, only one op to test */
|
|
if (is_hashCipher(mode))
|
|
continue;
|
|
/*if (rv) return rv;*/
|
|
}
|
|
if (!decrypt)
|
|
continue;
|
|
/* XXX for now */
|
|
rv = SECSuccess;
|
|
/* Reverse Operation (Decrypt/Verify)
|
|
** Align the input buffer (ciphertext) according to request
|
|
** then perform operation and compare to plaintext
|
|
*/
|
|
#ifdef NSS_ENABLE_ECC
|
|
if ((mode != bltestDSA) && (mode != bltestECDSA))
|
|
#else
|
|
if (mode != bltestDSA)
|
|
#endif
|
|
bltestCopyIO(arena, &cipherInfo.input, &ct);
|
|
else
|
|
bltestCopyIO(arena, &cipherInfo.input, &pt);
|
|
misalignBuffer(arena, &cipherInfo.input, inoff);
|
|
memset(&cipherInfo.output.buf, 0, sizeof cipherInfo.output.buf);
|
|
rv |= cipherInit(&cipherInfo, PR_FALSE);
|
|
misalignBuffer(arena, &cipherInfo.output, outoff);
|
|
#ifdef TRACK_BLTEST_BUG
|
|
if (mode == bltestRSA) {
|
|
fprintf(stderr, "[%s] Inited cipher context and buffers for #%d\n", __bltDBG, j);
|
|
}
|
|
#endif
|
|
srv = SECSuccess;
|
|
srv |= cipherDoOp(&cipherInfo);
|
|
#ifdef TRACK_BLTEST_BUG
|
|
if (mode == bltestRSA) {
|
|
fprintf(stderr, "[%s] Performed decrypt for #%d\n", __bltDBG, j);
|
|
}
|
|
#endif
|
|
rv |= cipherFinish(&cipherInfo);
|
|
#ifdef TRACK_BLTEST_BUG
|
|
if (mode == bltestRSA) {
|
|
fprintf(stderr, "[%s] Finished decrypt for #%d\n", __bltDBG, j);
|
|
}
|
|
#endif
|
|
rv |= verify_self_test(&cipherInfo.output,
|
|
&pt, mode, PR_FALSE, srv);
|
|
#ifdef TRACK_BLTEST_BUG
|
|
if (mode == bltestRSA) {
|
|
fprintf(stderr, "[%s] Verified self-test for #%d\n", __bltDBG, j);
|
|
}
|
|
#endif
|
|
/*if (rv) return rv;*/
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
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);
|
|
#ifdef NSS_ENABLE_ECC
|
|
} else if (mode == bltestECDSA) {
|
|
ECPrivateKey *key;
|
|
load_file_data(arena, &keydata, filename, bltestBase64Encoded);
|
|
key = eckey_from_filedata(&keydata.buf);
|
|
dump_eckey(key);
|
|
#endif
|
|
}
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
return SECFailure;
|
|
}
|
|
|
|
void ThreadExecTest(void *data)
|
|
{
|
|
bltestCipherInfo *cipherInfo = (bltestCipherInfo*)data;
|
|
|
|
if (cipherInfo->mCarlo == PR_TRUE) {
|
|
int mciter;
|
|
for (mciter=0; mciter<10000; mciter++) {
|
|
cipherDoOp(cipherInfo);
|
|
memcpy(cipherInfo->input.buf.data,
|
|
cipherInfo->output.buf.data,
|
|
cipherInfo->input.buf.len);
|
|
}
|
|
} else {
|
|
cipherDoOp(cipherInfo);
|
|
}
|
|
cipherFinish(cipherInfo);
|
|
}
|
|
|
|
/* 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,
|
|
#ifdef NSS_ENABLE_ECC
|
|
opt_CurveName,
|
|
#endif
|
|
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_MonteCarlo,
|
|
opt_ThreadNum,
|
|
opt_SecondsToRun,
|
|
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 },
|
|
#ifdef NSS_ENABLE_ECC
|
|
{ /* opt_CurveName */ 'n', PR_TRUE, 0, PR_FALSE },
|
|
#endif
|
|
{ /* 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_MonteCarlo */ '3', PR_FALSE, 0, PR_FALSE },
|
|
{ /* opt_ThreadNum */ '4', PR_TRUE, 0, PR_FALSE },
|
|
{ /* opt_SecondsToRun */ '5', 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 = SECFailure;
|
|
|
|
double totalTime;
|
|
PRIntervalTime time1, time2;
|
|
PRFileDesc *outfile;
|
|
bltestCipherInfo *cipherInfoListHead, *cipherInfo;
|
|
bltestIOMode ioMode;
|
|
int bufsize, exponent, curThrdNum;
|
|
#ifdef NSS_ENABLE_ECC
|
|
char *curveName = NULL;
|
|
#endif
|
|
int i, commandsEntered;
|
|
int inoff, outoff;
|
|
int threads = 1;
|
|
|
|
secuCommand bltest;
|
|
bltest.numCommands = sizeof(bltest_commands) / sizeof(secuCommandFlag);
|
|
bltest.numOptions = sizeof(bltest_options) / sizeof(secuCommandFlag);
|
|
bltest.commands = bltest_commands;
|
|
bltest.options = bltest_options;
|
|
|
|
progName = strrchr(argv[0], '/');
|
|
if (!progName)
|
|
progName = strrchr(argv[0], '\\');
|
|
progName = progName ? progName+1 : argv[0];
|
|
|
|
rv = RNG_RNGInit();
|
|
if (rv != SECSuccess) {
|
|
SECU_PrintPRandOSError(progName);
|
|
return -1;
|
|
}
|
|
RNG_SystemInfoForRNG();
|
|
|
|
rv = SECU_ParseCommandLine(argc, argv, progName, &bltest);
|
|
if (rv == SECFailure) {
|
|
fprintf(stderr, "%s: command line parsing error!\n", progName);
|
|
goto print_usage;
|
|
}
|
|
rv = SECFailure;
|
|
|
|
cipherInfo = PORT_ZNew(bltestCipherInfo);
|
|
cipherInfoListHead = cipherInfo;
|
|
/* set some defaults */
|
|
infileName = outfileName = keyfileName = ivfileName = NULL;
|
|
|
|
/* Check the number of commands entered on the command line. */
|
|
commandsEntered = 0;
|
|
for (i=0; i<bltest.numCommands; i++)
|
|
if (bltest.commands[i].activated)
|
|
commandsEntered++;
|
|
|
|
if (commandsEntered > 1 &&
|
|
!(commandsEntered == 2 && bltest.commands[cmd_SelfTest].activated)) {
|
|
fprintf(stderr, "%s: one command at a time!\n", progName);
|
|
goto print_usage;
|
|
}
|
|
|
|
if (commandsEntered == 0) {
|
|
fprintf(stderr, "%s: you must enter a command!\n", progName);
|
|
goto print_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;
|
|
rv = blapi_selftest(modesToTest, numModesToTest, inoff, outoff,
|
|
encrypt, decrypt);
|
|
PORT_Free(cipherInfo);
|
|
return rv;
|
|
}
|
|
|
|
/* Do FIPS self-test */
|
|
if (bltest.commands[cmd_FIPS].activated) {
|
|
CK_RV ckrv = sftk_fipsPowerUpSelfTest();
|
|
fprintf(stdout, "CK_RV: %ld.\n", ckrv);
|
|
PORT_Free(cipherInfo);
|
|
if (ckrv == CKR_OK)
|
|
return SECSuccess;
|
|
return SECFailure;
|
|
}
|
|
|
|
/*
|
|
* 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);
|
|
goto print_usage;
|
|
}
|
|
|
|
if (bltest.options[opt_Mode].activated) {
|
|
cipherInfo->mode = get_mode(bltest.options[opt_Mode].arg);
|
|
if (cipherInfo->mode == bltestINVALID) {
|
|
goto print_usage;
|
|
}
|
|
} else {
|
|
fprintf(stderr, "%s: You must specify a cipher mode with -m.\n",
|
|
progName);
|
|
goto print_usage;
|
|
}
|
|
|
|
|
|
if (bltest.options[opt_Repetitions].activated &&
|
|
bltest.options[opt_SecondsToRun].activated) {
|
|
fprintf(stderr, "%s: Operation time should be defined in either "
|
|
"repetitions(-p) or seconds(-5) not both",
|
|
progName);
|
|
goto print_usage;
|
|
}
|
|
|
|
if (bltest.options[opt_Repetitions].activated) {
|
|
cipherInfo->repetitionsToPerfom =
|
|
PORT_Atoi(bltest.options[opt_Repetitions].arg);
|
|
} else {
|
|
cipherInfo->repetitionsToPerfom = 0;
|
|
}
|
|
|
|
if (bltest.options[opt_SecondsToRun].activated) {
|
|
cipherInfo->seconds = PORT_Atoi(bltest.options[opt_SecondsToRun].arg);
|
|
} else {
|
|
cipherInfo->seconds = 0;
|
|
}
|
|
|
|
|
|
if (bltest.options[opt_CXReps].activated) {
|
|
cipherInfo->cxreps = PORT_Atoi(bltest.options[opt_CXReps].arg);
|
|
} else {
|
|
cipherInfo->cxreps = 0;
|
|
}
|
|
|
|
if (bltest.options[opt_ThreadNum].activated) {
|
|
threads = PORT_Atoi(bltest.options[opt_ThreadNum].arg);
|
|
if (threads <= 0) {
|
|
threads = 1;
|
|
}
|
|
}
|
|
|
|
/* Dump a file (rsakey, dsakey, etc.) */
|
|
if (bltest.commands[cmd_Dump].activated) {
|
|
rv = dump_file(cipherInfo->mode, bltest.options[opt_Input].arg);
|
|
PORT_Free(cipherInfo);
|
|
return rv;
|
|
}
|
|
|
|
/* 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_Exponent].activated)
|
|
exponent = PORT_Atoi(bltest.options[opt_Exponent].arg);
|
|
else
|
|
exponent = 65537;
|
|
|
|
#ifdef NSS_ENABLE_ECC
|
|
if (bltest.options[opt_CurveName].activated)
|
|
curveName = PORT_Strdup(bltest.options[opt_CurveName].arg);
|
|
else
|
|
curveName = NULL;
|
|
#endif
|
|
|
|
if (bltest.commands[cmd_Verify].activated &&
|
|
!bltest.options[opt_SigFile].activated) {
|
|
fprintf(stderr, "%s: You must specify a signature file with -f.\n",
|
|
progName);
|
|
|
|
print_usage:
|
|
PORT_Free(cipherInfo);
|
|
Usage();
|
|
}
|
|
|
|
if (bltest.options[opt_MonteCarlo].activated) {
|
|
cipherInfo->mCarlo = PR_TRUE;
|
|
} else {
|
|
cipherInfo->mCarlo = PR_FALSE;
|
|
}
|
|
|
|
for (curThrdNum = 0;curThrdNum < threads;curThrdNum++) {
|
|
int keysize = 0;
|
|
PRFileDesc *file = NULL, *infile;
|
|
bltestParams *params;
|
|
char *instr = NULL;
|
|
PRArenaPool *arena;
|
|
|
|
if (curThrdNum > 0) {
|
|
bltestCipherInfo *newCInfo = PORT_ZNew(bltestCipherInfo);
|
|
if (!newCInfo) {
|
|
fprintf(stderr, "%s: Can not allocate memory.\n", progName);
|
|
goto exit_point;
|
|
}
|
|
newCInfo->mode = cipherInfo->mode;
|
|
newCInfo->mCarlo = cipherInfo->mCarlo;
|
|
newCInfo->repetitionsToPerfom =
|
|
cipherInfo->repetitionsToPerfom;
|
|
newCInfo->seconds = cipherInfo->seconds;
|
|
newCInfo->cxreps = cipherInfo->cxreps;
|
|
cipherInfo->next = newCInfo;
|
|
cipherInfo = newCInfo;
|
|
}
|
|
arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
|
|
if (!arena) {
|
|
fprintf(stderr, "%s: Can not allocate memory.\n", progName);
|
|
goto exit_point;
|
|
}
|
|
cipherInfo->arena = arena;
|
|
params = &cipherInfo->params;
|
|
|
|
/* 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);
|
|
}
|
|
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;
|
|
#ifdef NSS_ENABLE_ECC
|
|
pubkeyInitKey(cipherInfo, file, keysize, exponent, curveName);
|
|
#else
|
|
pubkeyInitKey(cipherInfo, file, keysize, exponent);
|
|
#endif
|
|
PR_Close(file);
|
|
}
|
|
|
|
/* set up an initialization vector. */
|
|
if (cipher_requires_IV(cipherInfo->mode)) {
|
|
char *ivstr = NULL;
|
|
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);
|
|
}
|
|
}
|
|
|
|
if (bltest.commands[cmd_Verify].activated) {
|
|
file = PR_Open(bltest.options[opt_SigFile].arg, PR_RDONLY, 00660);
|
|
if (cipherInfo->mode == bltestDSA) {
|
|
memset(&cipherInfo->params.dsa.sig, 0, sizeof(bltestIO));
|
|
cipherInfo->params.dsa.sig.mode = ioMode;
|
|
setupIO(cipherInfo->arena, &cipherInfo->params.dsa.sig,
|
|
file, NULL, 0);
|
|
#ifdef NSS_ENABLE_ECC
|
|
} else if (cipherInfo->mode == bltestECDSA) {
|
|
memset(&cipherInfo->params.ecdsa.sig, 0, sizeof(bltestIO));
|
|
cipherInfo->params.ecdsa.sig.mode = ioMode;
|
|
setupIO(cipherInfo->arena, &cipherInfo->params.ecdsa.sig,
|
|
file, NULL, 0);
|
|
#endif
|
|
}
|
|
if (file) {
|
|
PR_Close(file);
|
|
}
|
|
}
|
|
|
|
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);
|
|
if (file) {
|
|
PR_Close(file);
|
|
}
|
|
}
|
|
|
|
/* Set up the input buffer */
|
|
if (bltest.options[opt_Input].activated) {
|
|
if (bltest.options[opt_CmdLine].activated) {
|
|
instr = bltest.options[opt_Input].arg;
|
|
infile = NULL;
|
|
} else {
|
|
/* form file name from testdir and input arg. */
|
|
char * filename = bltest.options[opt_Input].arg;
|
|
if (bltest.options[opt_SelfTestDir].activated &&
|
|
testdir && filename && filename[0] != '/') {
|
|
filename = PR_smprintf("%s/tests/%s/%s", testdir,
|
|
mode_strings[cipherInfo->mode],
|
|
filename);
|
|
if (!filename) {
|
|
fprintf(stderr, "%s: Can not allocate memory.\n",
|
|
progName);
|
|
goto exit_point;
|
|
}
|
|
infile = PR_Open(filename, PR_RDONLY, 00660);
|
|
PR_smprintf_free(filename);
|
|
} else {
|
|
infile = PR_Open(filename, PR_RDONLY, 00660);
|
|
}
|
|
}
|
|
} else if (bltest.options[opt_BufSize].activated) {
|
|
/* save the random plaintext for reference */
|
|
char *tmpFName = PR_smprintf("tmp.in.%d", curThrdNum);
|
|
if (!tmpFName) {
|
|
fprintf(stderr, "%s: Can not allocate memory.\n", progName);
|
|
goto exit_point;
|
|
}
|
|
infile = PR_Open(tmpFName, PR_WRONLY|PR_CREATE_FILE, 00660);
|
|
PR_smprintf_free(tmpFName);
|
|
} else {
|
|
infile = PR_STDIN;
|
|
}
|
|
if (!infile) {
|
|
fprintf(stderr, "%s: Failed to open input file.\n", progName);
|
|
goto exit_point;
|
|
}
|
|
cipherInfo->input.mode = ioMode;
|
|
|
|
/* Set up the output stream */
|
|
if (bltest.options[opt_Output].activated) {
|
|
/* form file name from testdir and input arg. */
|
|
char * filename = bltest.options[opt_Output].arg;
|
|
if (bltest.options[opt_SelfTestDir].activated &&
|
|
testdir && filename && filename[0] != '/') {
|
|
filename = PR_smprintf("%s/tests/%s/%s", testdir,
|
|
mode_strings[cipherInfo->mode],
|
|
filename);
|
|
if (!filename) {
|
|
fprintf(stderr, "%s: Can not allocate memory.\n", progName);
|
|
goto exit_point;
|
|
}
|
|
outfile = PR_Open(filename, PR_WRONLY|PR_CREATE_FILE, 00660);
|
|
PR_smprintf_free(filename);
|
|
} else {
|
|
outfile = PR_Open(filename, PR_WRONLY|PR_CREATE_FILE, 00660);
|
|
}
|
|
} else {
|
|
outfile = PR_STDOUT;
|
|
}
|
|
if (!outfile) {
|
|
fprintf(stderr, "%s: Failed to open output file.\n", progName);
|
|
rv = SECFailure;
|
|
goto exit_point;
|
|
}
|
|
cipherInfo->output.mode = ioMode;
|
|
if (bltest.options[opt_SelfTestDir].activated && ioMode == bltestBinary)
|
|
cipherInfo->output.mode = bltestBase64Encoded;
|
|
|
|
if (is_hashCipher(cipherInfo->mode))
|
|
cipherInfo->params.hash.restart =
|
|
bltest.options[opt_Restart].activated;
|
|
|
|
bufsize = 0;
|
|
if (bltest.options[opt_BufSize].activated)
|
|
bufsize = PORT_Atoi(bltest.options[opt_BufSize].arg);
|
|
|
|
/*infile = NULL;*/
|
|
setupIO(cipherInfo->arena, &cipherInfo->input, infile, instr, bufsize);
|
|
if (infile && infile != PR_STDIN)
|
|
PR_Close(infile);
|
|
misalignBuffer(cipherInfo->arena, &cipherInfo->input, inoff);
|
|
|
|
cipherInit(cipherInfo, bltest.commands[cmd_Encrypt].activated);
|
|
misalignBuffer(cipherInfo->arena, &cipherInfo->output, outoff);
|
|
}
|
|
|
|
if (!bltest.commands[cmd_Nonce].activated) {
|
|
TIMESTART();
|
|
cipherInfo = cipherInfoListHead;
|
|
while (cipherInfo != NULL) {
|
|
cipherInfo->cipherThread =
|
|
PR_CreateThread(PR_USER_THREAD,
|
|
ThreadExecTest,
|
|
cipherInfo,
|
|
PR_PRIORITY_NORMAL,
|
|
PR_GLOBAL_THREAD,
|
|
PR_JOINABLE_THREAD,
|
|
0);
|
|
cipherInfo = cipherInfo->next;
|
|
}
|
|
|
|
cipherInfo = cipherInfoListHead;
|
|
while (cipherInfo != NULL) {
|
|
PR_JoinThread(cipherInfo->cipherThread);
|
|
finishIO(&cipherInfo->output, outfile);
|
|
cipherInfo = cipherInfo->next;
|
|
}
|
|
TIMEFINISH(totalTime, 1);
|
|
}
|
|
|
|
cipherInfo = cipherInfoListHead;
|
|
if (cipherInfo->repetitions > 0 || cipherInfo->cxreps > 0 ||
|
|
threads > 1)
|
|
dump_performance_info(cipherInfoListHead, totalTime,
|
|
bltest.commands[cmd_Encrypt].activated,
|
|
(cipherInfo->repetitions == 0));
|
|
|
|
rv = SECSuccess;
|
|
|
|
exit_point:
|
|
if (outfile && outfile != PR_STDOUT)
|
|
PR_Close(outfile);
|
|
cipherInfo = cipherInfoListHead;
|
|
while (cipherInfo != NULL) {
|
|
bltestCipherInfo *tmpInfo = cipherInfo;
|
|
|
|
if (cipherInfo->arena)
|
|
PORT_FreeArena(cipherInfo->arena, PR_TRUE);
|
|
cipherInfo = cipherInfo->next;
|
|
PORT_Free(tmpInfo);
|
|
}
|
|
|
|
/*NSS_Shutdown();*/
|
|
|
|
return SECSuccess;
|
|
}
|