Mypal/security/nss/cmd/bltest/blapitest.c

4227 lines
144 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#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 "basicutil.h"
#include "plgetopt.h"
#include "softoken.h"
#include "nspr.h"
#include "secport.h"
#include "secoid.h"
#include "nssutil.h"
#include "ecl-curve.h"
#include "pkcs1_vectors.h"
SECStatus EC_DecodeParams(const SECItem *encodedParams,
ECParams **ecparams);
SECStatus EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
const ECParams *srcParams);
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, PORT_ErrorToString(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; \
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, "[-DEHSVR]", "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("", "--aad", "File with contains additional auth data");
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)");
PRINTUSAGE("", "--aad", "File with contains additional auth data");
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]");
PRINTUSAGE("", "", "[-n curvename]");
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");
PRINTUSAGE("", "-n", "name of curve for EC key generation; one of:");
PRINTUSAGE("", "", " nistp256, nistp384, nistp521");
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, "-R [-g keysize] [-e exp]",
"Test the RSA populate key function");
PRINTUSAGE("", "", "[-r repetitions]");
PRINTUSAGE("", "-g", "key size (in bytes)");
PRINTUSAGE("", "-e", "rsa public exponent");
PRINTUSAGE("", "-r", "repetitions of the test");
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;
PLArenaPool *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, PLArenaPool *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 = (strncmp((const char *)&ascii->data[ascii->len - 2], "\r\n", 2)) ? 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;
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, 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;
NSSBase64Encoder *cx;
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);
NSSBase64Encoder_Update(cx, len, 4);
NSSBase64Encoder_Update(cx, it->data, it->len);
}
NSSBase64Encoder_Destroy(cx, PR_FALSE);
PR_Write(file, "\r\n", 2);
}
void
key_from_filedata(PLArenaPool *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(PLArenaPool *arena, SECItem *filedata)
{
RSAPrivateKey *key;
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(PLArenaPool *arena, SECItem *filedata)
{
PQGParams *pqg;
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(PLArenaPool *arena, SECItem *filedata)
{
DSAPrivateKey *key;
key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey));
key->params.arena = arena;
key_from_filedata(arena, &key->params.prime, 0, 5, filedata);
return key;
}
static ECPrivateKey *
eckey_from_filedata(PLArenaPool *arena, SECItem *filedata)
{
ECPrivateKey *key;
SECStatus rv;
ECParams *tmpECParams = NULL;
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;
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 },
{ "curve25519", SEC_OID_CURVE25519 },
};
static SECItem *
getECParams(const char *curve)
{
SECItem *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;
}
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);
}
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);
}
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 (*bltestAEADFn)(void *cx,
unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input,
unsigned int inputLen,
const unsigned char *nonce,
unsigned int nonceLen,
const unsigned char *ad,
unsigned int adLen);
typedef SECStatus (*bltestPubKeyCipherFn)(void *key,
SECItem *output,
const SECItem *input);
typedef SECStatus (*bltestHashCipherFn)(unsigned char *dest,
const unsigned char *src,
PRUint32 src_length);
/* Note: Algorithms are grouped in order to support is_symmkeyCipher /
* is_pubkeyCipher / is_hashCipher / is_sigCipher
*/
typedef enum {
bltestINVALID = -1,
bltestDES_ECB, /* Symmetric Key Ciphers */
bltestDES_CBC, /* . */
bltestDES_EDE_ECB, /* . */
bltestDES_EDE_CBC, /* . */
#ifndef NSS_DISABLE_DEPRECATED_RC2
bltestRC2_ECB, /* . */
bltestRC2_CBC, /* . */
#endif
bltestRC4, /* . */
#ifdef NSS_SOFTOKEN_DOES_RC5
bltestRC5_ECB, /* . */
bltestRC5_CBC, /* . */
#endif
bltestAES_ECB, /* . */
bltestAES_CBC, /* . */
bltestAES_CTS, /* . */
bltestAES_CTR, /* . */
bltestAES_GCM, /* . */
bltestCAMELLIA_ECB, /* . */
bltestCAMELLIA_CBC, /* . */
#ifndef NSS_DISABLE_DEPRECATED_SEED
bltestSEED_ECB, /* SEED algorithm */
bltestSEED_CBC, /* SEED algorithm */
#endif
bltestCHACHA20, /* ChaCha20 + Poly1305 */
bltestRSA, /* Public Key Ciphers */
bltestRSA_OAEP, /* . (Public Key Enc.) */
bltestRSA_PSS, /* . (Public Key Sig.) */
bltestECDSA, /* . (Public Key Sig.) */
bltestDSA, /* . (Public Key Sig.) */
bltestMD2, /* Hash algorithms */
bltestMD5, /* . */
bltestSHA1, /* . */
bltestSHA224, /* . */
bltestSHA256, /* . */
bltestSHA384, /* . */
bltestSHA512, /* . */
NUMMODES
} bltestCipherMode;
static char *mode_strings[] =
{
"des_ecb",
"des_cbc",
"des3_ecb",
"des3_cbc",
#ifndef NSS_DISABLE_DEPRECATED_RC2
"rc2_ecb",
"rc2_cbc",
#endif
"rc4",
#ifdef NSS_SOFTOKEN_DOES_RC5
"rc5_ecb",
"rc5_cbc",
#endif
"aes_ecb",
"aes_cbc",
"aes_cts",
"aes_ctr",
"aes_gcm",
"camellia_ecb",
"camellia_cbc",
#ifndef NSS_DISABLE_DEPRECATED_SEED
"seed_ecb",
"seed_cbc",
#endif
"chacha20_poly1305",
"rsa",
"rsa_oaep",
"rsa_pss",
"ecdsa",
/*"pqg",*/
"dsa",
"md2",
"md5",
"sha1",
"sha224",
"sha256",
"sha384",
"sha512",
};
typedef struct
{
bltestIO key;
bltestIO iv;
} bltestSymmKeyParams;
typedef struct
{
bltestSymmKeyParams sk; /* must be first */
bltestIO aad;
} bltestAuthSymmKeyParams;
typedef struct
{
bltestIO key;
bltestIO iv;
int rounds;
int wordsize;
} bltestRC5Params;
typedef struct
{
bltestIO key;
int keysizeInBits;
/* OAEP & PSS */
HASH_HashType hashAlg;
HASH_HashType maskHashAlg;
bltestIO seed; /* salt if PSS */
} bltestRSAParams;
typedef struct
{
bltestIO pqgdata;
unsigned int keysize;
bltestIO keyseed;
bltestIO sigseed;
PQGParams *pqg;
} bltestDSAParams;
typedef struct
{
char *curveName;
bltestIO sigseed;
} bltestECDSAParams;
typedef struct
{
bltestIO key;
void *privKey;
void *pubKey;
bltestIO sig; /* if doing verify, the signature (which may come
* from sigfile. */
union {
bltestRSAParams rsa;
bltestDSAParams dsa;
bltestECDSAParams ecdsa;
} cipherParams;
} bltestAsymKeyParams;
typedef struct
{
bltestIO key; /* unused */
PRBool restart;
} bltestHashParams;
typedef union {
bltestIO key;
bltestSymmKeyParams sk;
bltestAuthSymmKeyParams ask;
bltestRC5Params rc5;
bltestAsymKeyParams asymk;
bltestHashParams hash;
} bltestParams;
typedef struct bltestCipherInfoStr bltestCipherInfo;
struct bltestCipherInfoStr {
PLArenaPool *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;
bltestAEADFn aeadCipher;
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! */
#ifndef NSS_DISABLE_DEPRECATED_SEED
if (mode >= bltestDES_ECB && mode <= bltestSEED_CBC)
#else
if (mode >= bltestDES_ECB && mode <= bltestCAMELLIA_CBC)
#endif
return PR_TRUE;
return PR_FALSE;
}
PRBool
is_aeadCipher(bltestCipherMode mode)
{
/* change as needed! */
switch (mode) {
case bltestCHACHA20:
return PR_TRUE;
default:
return PR_FALSE;
}
}
PRBool
is_authCipher(bltestCipherMode mode)
{
/* change as needed! */
switch (mode) {
case bltestAES_GCM:
case bltestCHACHA20:
return PR_TRUE;
default:
return PR_FALSE;
}
}
PRBool
is_singleShotCipher(bltestCipherMode mode)
{
/* change as needed! */
switch (mode) {
case bltestAES_GCM:
case bltestAES_CTS:
case bltestCHACHA20:
return PR_TRUE;
default:
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! */
if (mode >= bltestRSA_PSS && mode <= bltestDSA)
return PR_TRUE;
return PR_FALSE;
}
PRBool
cipher_requires_IV(bltestCipherMode mode)
{
/* change as needed! */
switch (mode) {
case bltestDES_CBC:
case bltestDES_EDE_CBC:
#ifndef NSS_DISABLE_DEPRECATED_RC2
case bltestRC2_CBC:
#endif
#ifdef NSS_SOFTOKEN_DOES_RC5
case bltestRC5_CBC:
#endif
case bltestAES_CBC:
case bltestAES_CTS:
case bltestAES_CTR:
case bltestAES_GCM:
case bltestCAMELLIA_CBC:
#ifndef NSS_DISABLE_DEPRECATED_SEED
case bltestSEED_CBC:
#endif
case bltestCHACHA20:
return PR_TRUE;
default:
return PR_FALSE;
}
}
SECStatus finishIO(bltestIO *output, PRFileDesc *file);
SECStatus
setupIO(PLArenaPool *arena, bltestIO *input, PRFileDesc *file,
char *str, int numBytes)
{
SECStatus rv = SECSuccess;
SECItem fileData;
SECItem *in;
unsigned char *tok;
unsigned int i, j;
PRBool needToFreeFile = PR_FALSE;
if (file && (numBytes == 0 || file == PR_STDIN)) {
/* grabbing data from a file */
rv = SECU_FileToItem(&fileData, file);
if (rv != SECSuccess)
return SECFailure;
in = &fileData;
needToFreeFile = PR_TRUE;
} else if (str) {
/* grabbing data from command line */
fileData.data = (unsigned char *)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:
if (in->len == 0) {
input->buf.data = NULL;
input->buf.len = 0;
break;
}
rv = atob(in, &input->buf, arena);
break;
case bltestBinary:
if (in->len == 0) {
input->buf.data = NULL;
input->buf.len = 0;
break;
}
if (in->data[in->len - 1] == '\n')
--in->len;
if (in->data[in->len - 1] == '\r')
--in->len;
rv = 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 (needToFreeFile)
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;
}
SECStatus
bltestCopyIO(PLArenaPool *arena, bltestIO *dest, bltestIO *src)
{
if (SECITEM_CopyItem(arena, &dest->buf, &src->buf) != SECSuccess) {
return SECFailure;
}
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;
return SECSuccess;
}
void
misalignBuffer(PLArenaPool *arena, bltestIO *io, int off)
{
ptrdiff_t offset = (ptrdiff_t)io->buf.data % WORDSIZE;
int length = io->buf.len;
if (offset != off) {
SECITEM_ReallocItemV2(arena, &io->buf, length + 2 * WORDSIZE);
/* offset may have changed? */
offset = (ptrdiff_t)io->buf.data % WORDSIZE;
if (offset != off) {
memmove(io->buf.data + off, io->buf.data, length);
io->pBuf.data = io->buf.data + off;
io->pBuf.len = length;
} else {
io->pBuf.data = io->buf.data;
io->pBuf.len = length;
}
} else {
io->pBuf.data = io->buf.data;
io->pBuf.len = length;
}
}
SECStatus
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);
}
#ifndef NSS_DISABLE_DEPRECATED_RC2
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);
}
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
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
chacha20_poly1305_Encrypt(void *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen,
const unsigned char *nonce, unsigned int nonceLen,
const unsigned char *ad, unsigned int adLen)
{
return ChaCha20Poly1305_Seal((ChaCha20Poly1305Context *)cx, output,
outputLen, maxOutputLen, input, inputLen,
nonce, nonceLen, ad, adLen);
}
SECStatus
chacha20_poly1305_Decrypt(void *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen,
const unsigned char *nonce, unsigned int nonceLen,
const unsigned char *ad, unsigned int adLen)
{
return ChaCha20Poly1305_Open((ChaCha20Poly1305Context *)cx, output,
outputLen, maxOutputLen, input, inputLen,
nonce, nonceLen, ad, adLen);
}
SECStatus
camellia_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
unsigned int maxOutputLen, const unsigned char *input,
unsigned int inputLen)
{
return Camellia_Encrypt((CamelliaContext *)cx, output, outputLen,
maxOutputLen,
input, inputLen);
}
SECStatus
camellia_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
unsigned int maxOutputLen, const unsigned char *input,
unsigned int inputLen)
{
return Camellia_Decrypt((CamelliaContext *)cx, output, outputLen,
maxOutputLen,
input, inputLen);
}
#ifndef NSS_DISABLE_DEPRECATED_SEED
SECStatus
seed_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
unsigned int maxOutputLen, const unsigned char *input,
unsigned int inputLen)
{
return SEED_Encrypt((SEEDContext *)cx, output, outputLen, maxOutputLen,
input, inputLen);
}
SECStatus
seed_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
unsigned int maxOutputLen, const unsigned char *input,
unsigned int inputLen)
{
return SEED_Decrypt((SEEDContext *)cx, output, outputLen, maxOutputLen,
input, inputLen);
}
#endif /* NSS_DISABLE_DEPRECATED_SEED */
SECStatus
rsa_PublicKeyOp(void *cx, SECItem *output, const SECItem *input)
{
bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
RSAPublicKey *pubKey = (RSAPublicKey *)params->pubKey;
SECStatus rv = RSA_PublicKeyOp(pubKey, output->data, input->data);
if (rv == SECSuccess) {
output->len = pubKey->modulus.data[0] ? pubKey->modulus.len : pubKey->modulus.len - 1;
}
return rv;
}
SECStatus
rsa_PrivateKeyOp(void *cx, SECItem *output, const SECItem *input)
{
bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
RSAPrivateKey *privKey = (RSAPrivateKey *)params->privKey;
SECStatus rv = RSA_PrivateKeyOp(privKey, output->data, input->data);
if (rv == SECSuccess) {
output->len = privKey->modulus.data[0] ? privKey->modulus.len : privKey->modulus.len - 1;
}
return rv;
}
SECStatus
rsa_signDigestPSS(void *cx, SECItem *output, const SECItem *input)
{
bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
bltestRSAParams *rsaParams = &params->cipherParams.rsa;
return RSA_SignPSS((RSAPrivateKey *)params->privKey,
rsaParams->hashAlg,
rsaParams->maskHashAlg,
rsaParams->seed.buf.data,
rsaParams->seed.buf.len,
output->data, &output->len, output->len,
input->data, input->len);
}
SECStatus
rsa_verifyDigestPSS(void *cx, SECItem *output, const SECItem *input)
{
bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
bltestRSAParams *rsaParams = &params->cipherParams.rsa;
return RSA_CheckSignPSS((RSAPublicKey *)params->pubKey,
rsaParams->hashAlg,
rsaParams->maskHashAlg,
rsaParams->seed.buf.len,
output->data, output->len,
input->data, input->len);
}
SECStatus
rsa_encryptOAEP(void *cx, SECItem *output, const SECItem *input)
{
bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
bltestRSAParams *rsaParams = &params->cipherParams.rsa;
return RSA_EncryptOAEP((RSAPublicKey *)params->pubKey,
rsaParams->hashAlg,
rsaParams->maskHashAlg,
NULL, 0,
rsaParams->seed.buf.data,
rsaParams->seed.buf.len,
output->data, &output->len, output->len,
input->data, input->len);
}
SECStatus
rsa_decryptOAEP(void *cx, SECItem *output, const SECItem *input)
{
bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
bltestRSAParams *rsaParams = &params->cipherParams.rsa;
return RSA_DecryptOAEP((RSAPrivateKey *)params->privKey,
rsaParams->hashAlg,
rsaParams->maskHashAlg,
NULL, 0,
output->data, &output->len, output->len,
input->data, input->len);
}
SECStatus
dsa_signDigest(void *cx, SECItem *output, const SECItem *input)
{
bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
if (params->cipherParams.dsa.sigseed.buf.len > 0) {
return DSA_SignDigestWithSeed((DSAPrivateKey *)params->privKey,
output, input,
params->cipherParams.dsa.sigseed.buf.data);
}
return DSA_SignDigest((DSAPrivateKey *)params->privKey, output, input);
}
SECStatus
dsa_verifyDigest(void *cx, SECItem *output, const SECItem *input)
{
bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
return DSA_VerifyDigest((DSAPublicKey *)params->pubKey, output, input);
}
SECStatus
ecdsa_signDigest(void *cx, SECItem *output, const SECItem *input)
{
bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
if (params->cipherParams.ecdsa.sigseed.buf.len > 0) {
return ECDSA_SignDigestWithSeed(
(ECPrivateKey *)params->privKey,
output, input,
params->cipherParams.ecdsa.sigseed.buf.data,
params->cipherParams.ecdsa.sigseed.buf.len);
}
return ECDSA_SignDigest((ECPrivateKey *)params->privKey, output, input);
}
SECStatus
ecdsa_verifyDigest(void *cx, SECItem *output, const SECItem *input)
{
bltestAsymKeyParams *params = (bltestAsymKeyParams *)cx;
return ECDSA_VerifyDigest((ECPublicKey *)params->pubKey, output, input);
}
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;
}
#ifndef NSS_DISABLE_DEPRECATED_RC2
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;
}
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
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)
{
#ifdef 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;
bltestAuthSymmKeyParams *gcmp = &cipherInfo->params.ask;
int minorMode;
int i;
int keylen = aesp->key.buf.len;
unsigned int blocklen = AES_BLOCK_SIZE;
PRIntervalTime time1, time2;
unsigned char *params;
int len;
CK_AES_CTR_PARAMS ctrParams;
CK_NSS_GCM_PARAMS gcmParams;
params = aesp->iv.buf.data;
switch (cipherInfo->mode) {
case bltestAES_ECB:
minorMode = NSS_AES;
break;
case bltestAES_CBC:
minorMode = NSS_AES_CBC;
break;
case bltestAES_CTS:
minorMode = NSS_AES_CTS;
break;
case bltestAES_CTR:
minorMode = NSS_AES_CTR;
ctrParams.ulCounterBits = 32;
len = PR_MIN(aesp->iv.buf.len, blocklen);
PORT_Memset(ctrParams.cb, 0, blocklen);
PORT_Memcpy(ctrParams.cb, aesp->iv.buf.data, len);
params = (unsigned char *)&ctrParams;
break;
case bltestAES_GCM:
minorMode = NSS_AES_GCM;
gcmParams.pIv = gcmp->sk.iv.buf.data;
gcmParams.ulIvLen = gcmp->sk.iv.buf.len;
gcmParams.pAAD = gcmp->aad.buf.data;
gcmParams.ulAADLen = gcmp->aad.buf.len;
gcmParams.ulTagBits = blocklen * 8;
params = (unsigned char *)&gcmParams;
break;
default:
return SECFailure;
}
cipherInfo->cx = (void *)AES_CreateContext(aesp->key.buf.data,
params,
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,
params,
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_camellia_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
{
bltestSymmKeyParams *camelliap = &cipherInfo->params.sk;
int minorMode;
int i;
int keylen = camelliap->key.buf.len;
PRIntervalTime time1, time2;
switch (cipherInfo->mode) {
case bltestCAMELLIA_ECB:
minorMode = NSS_CAMELLIA;
break;
case bltestCAMELLIA_CBC:
minorMode = NSS_CAMELLIA_CBC;
break;
default:
return SECFailure;
}
cipherInfo->cx = (void *)Camellia_CreateContext(camelliap->key.buf.data,
camelliap->iv.buf.data,
minorMode, encrypt,
keylen);
if (cipherInfo->cxreps > 0) {
CamelliaContext **dummycx;
dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(CamelliaContext *));
TIMESTART();
for (i = 0; i < cipherInfo->cxreps; i++) {
dummycx[i] = (void *)Camellia_CreateContext(camelliap->key.buf.data,
camelliap->iv.buf.data,
minorMode, encrypt,
keylen);
}
TIMEFINISH(cipherInfo->cxtime, 1.0);
for (i = 0; i < cipherInfo->cxreps; i++) {
Camellia_DestroyContext(dummycx[i], PR_TRUE);
}
PORT_Free(dummycx);
}
if (encrypt)
cipherInfo->cipher.symmkeyCipher = camellia_Encrypt;
else
cipherInfo->cipher.symmkeyCipher = camellia_Decrypt;
return SECSuccess;
}
#ifndef NSS_DISABLE_DEPRECATED_SEED
SECStatus
bltest_seed_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
{
PRIntervalTime time1, time2;
bltestSymmKeyParams *seedp = &cipherInfo->params.sk;
int minorMode;
int i;
switch (cipherInfo->mode) {
case bltestSEED_ECB:
minorMode = NSS_SEED;
break;
case bltestSEED_CBC:
minorMode = NSS_SEED_CBC;
break;
default:
return SECFailure;
}
cipherInfo->cx = (void *)SEED_CreateContext(seedp->key.buf.data,
seedp->iv.buf.data,
minorMode, encrypt);
if (cipherInfo->cxreps > 0) {
SEEDContext **dummycx;
dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(SEEDContext *));
TIMESTART();
for (i = 0; i < cipherInfo->cxreps; i++) {
dummycx[i] = (void *)SEED_CreateContext(seedp->key.buf.data,
seedp->iv.buf.data,
minorMode, encrypt);
}
TIMEFINISH(cipherInfo->cxtime, 1.0);
for (i = 0; i < cipherInfo->cxreps; i++) {
SEED_DestroyContext(dummycx[i], PR_TRUE);
}
PORT_Free(dummycx);
}
if (encrypt)
cipherInfo->cipher.symmkeyCipher = seed_Encrypt;
else
cipherInfo->cipher.symmkeyCipher = seed_Decrypt;
return SECSuccess;
}
#endif /* NSS_DISABLE_DEPRECATED_SEED */
SECStatus
bltest_chacha20_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
{
const unsigned int tagLen = 16;
const bltestSymmKeyParams *sk = &cipherInfo->params.sk;
cipherInfo->cx = ChaCha20Poly1305_CreateContext(sk->key.buf.data,
sk->key.buf.len, tagLen);
if (encrypt)
cipherInfo->cipher.aeadCipher = chacha20_poly1305_Encrypt;
else
cipherInfo->cipher.aeadCipher = chacha20_poly1305_Decrypt;
return SECSuccess;
}
SECStatus
bltest_rsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
{
int i;
RSAPrivateKey **dummyKey;
RSAPrivateKey *privKey;
RSAPublicKey *pubKey;
PRIntervalTime time1, time2;
bltestAsymKeyParams *asymk = &cipherInfo->params.asymk;
bltestRSAParams *rsap = &asymk->cipherParams.rsa;
/* RSA key gen was done during parameter setup */
cipherInfo->cx = asymk;
privKey = (RSAPrivateKey *)asymk->privKey;
/* 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,
&privKey->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 && !is_sigCipher(cipherInfo->mode)) ||
(!encrypt && is_sigCipher(cipherInfo->mode))) {
/* Have to convert private key to public key. Memory
* is freed with private key's arena */
pubKey = (RSAPublicKey *)PORT_ArenaAlloc(privKey->arena,
sizeof(RSAPublicKey));
pubKey->modulus.len = privKey->modulus.len;
pubKey->modulus.data = privKey->modulus.data;
pubKey->publicExponent.len = privKey->publicExponent.len;
pubKey->publicExponent.data = privKey->publicExponent.data;
asymk->pubKey = (void *)pubKey;
}
switch (cipherInfo->mode) {
case bltestRSA:
cipherInfo->cipher.pubkeyCipher = encrypt ? rsa_PublicKeyOp
: rsa_PrivateKeyOp;
break;
case bltestRSA_PSS:
cipherInfo->cipher.pubkeyCipher = encrypt ? rsa_signDigestPSS
: rsa_verifyDigestPSS;
break;
case bltestRSA_OAEP:
cipherInfo->cipher.pubkeyCipher = encrypt ? rsa_encryptOAEP
: rsa_decryptOAEP;
break;
default:
break;
}
return SECSuccess;
}
SECStatus
blapi_pqg_param_gen(unsigned int keysize, PQGParams **pqg, PQGVerify **vfy)
{
if (keysize < 1024) {
int j = PQG_PBITS_TO_INDEX(keysize);
return PQG_ParamGen(j, pqg, vfy);
}
return PQG_ParamGenV2(keysize, 0, 0, pqg, vfy);
}
SECStatus
bltest_pqg_init(bltestDSAParams *dsap)
{
SECStatus rv, res;
PQGVerify *vfy = NULL;
rv = blapi_pqg_param_gen(dsap->keysize, &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;
bltestAsymKeyParams *asymk = &cipherInfo->params.asymk;
bltestDSAParams *dsap = &asymk->cipherParams.dsa;
PQGVerify *ignore = NULL;
cipherInfo->cx = asymk;
/* 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;
blapi_pqg_param_gen(dsap->keysize, &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(cipherInfo->arena, &dsap->pqgdata.buf);
}
if (!asymk->privKey && asymk->key.buf.len > 0) {
asymk->privKey = dsakey_from_filedata(cipherInfo->arena, &asymk->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 *)asymk->privKey;
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;
asymk->pubKey = pubkey;
cipherInfo->cipher.pubkeyCipher = dsa_verifyDigest;
}
return SECSuccess;
}
SECStatus
bltest_ecdsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
{
int i;
ECPrivateKey **dummyKey;
PRIntervalTime time1, time2;
bltestAsymKeyParams *asymk = &cipherInfo->params.asymk;
cipherInfo->cx = asymk;
/* 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(&((ECPrivateKey *)asymk->privKey)->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 (!asymk->privKey && asymk->key.buf.len > 0) {
asymk->privKey = eckey_from_filedata(cipherInfo->arena, &asymk->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 *)asymk->privKey;
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;
asymk->pubKey = pubkey;
cipherInfo->cipher.pubkeyCipher = ecdsa_verifyDigest;
}
return SECSuccess;
}
/* XXX unfortunately, this is not defined in blapi.h */
SECStatus
md2_HashBuf(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
{
unsigned int len;
MD2Context *cx = MD2_NewContext();
if (cx == NULL)
return SECFailure;
MD2_Begin(cx);
MD2_Update(cx, src, src_length);
MD2_End(cx, dest, &len, MD2_LENGTH);
MD2_DestroyContext(cx, PR_TRUE);
return SECSuccess;
}
SECStatus
md2_restart(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
{
MD2Context *cx, *cx_cpy;
unsigned char *cxbytes;
unsigned 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, PRUint32 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, PRUint32 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
SHA224_restart(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
{
SECStatus rv = SECSuccess;
SHA224Context *cx, *cx_cpy;
unsigned char *cxbytes;
unsigned int len;
unsigned int i, quarter;
cx = SHA224_NewContext();
SHA224_Begin(cx);
/* divide message by 4, restarting 3 times */
quarter = (src_length + 3) / 4;
for (i = 0; i < 4 && src_length > 0; i++) {
SHA224_Update(cx, src + i * quarter, PR_MIN(quarter, src_length));
len = SHA224_FlattenSize(cx);
cxbytes = PORT_Alloc(len);
SHA224_Flatten(cx, cxbytes);
cx_cpy = SHA224_Resurrect(cxbytes, NULL);
if (!cx_cpy) {
PR_fprintf(PR_STDERR, "%s: SHA224_Resurrect failed!\n", progName);
rv = SECFailure;
goto finish;
}
rv = PORT_Memcmp(cx, cx_cpy, len);
if (rv) {
SHA224_DestroyContext(cx_cpy, PR_TRUE);
PR_fprintf(PR_STDERR, "%s: SHA224_restart failed!\n", progName);
goto finish;
}
SHA224_DestroyContext(cx_cpy, PR_TRUE);
PORT_Free(cxbytes);
src_length -= quarter;
}
SHA224_End(cx, dest, &len, MD5_LENGTH);
finish:
SHA224_DestroyContext(cx, PR_TRUE);
return rv;
}
SECStatus
SHA256_restart(unsigned char *dest, const unsigned char *src, PRUint32 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, PRUint32 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, PRUint32 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,
int keysize, int exponent, char *curveName)
{
int i;
SECStatus rv = SECSuccess;
bltestAsymKeyParams *asymk = &cipherInfo->params.asymk;
bltestRSAParams *rsap;
RSAPrivateKey **rsaKey = NULL;
bltestDSAParams *dsap;
DSAPrivateKey **dsaKey = NULL;
SECItem *tmpECParamsDER;
ECParams *tmpECParams = NULL;
SECItem ecSerialize[3];
ECPrivateKey **ecKey = NULL;
switch (cipherInfo->mode) {
case bltestRSA:
case bltestRSA_PSS:
case bltestRSA_OAEP:
rsap = &asymk->cipherParams.rsa;
rsaKey = (RSAPrivateKey **)&asymk->privKey;
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));
*rsaKey = RSA_NewKey(keysize * 8, &expitem);
serialize_key(&(*rsaKey)->version, 9, file);
rsap->keysizeInBits = keysize * 8;
} else {
setupIO(cipherInfo->arena, &asymk->key, file, NULL, 0);
*rsaKey = rsakey_from_filedata(cipherInfo->arena, &asymk->key.buf);
rsap->keysizeInBits = (*rsaKey)->modulus.len * 8;
}
break;
case bltestDSA:
dsap = &asymk->cipherParams.dsa;
dsaKey = (DSAPrivateKey **)&asymk->privKey;
if (keysize > 0) {
dsap->keysize = keysize * 8;
if (!dsap->pqg)
bltest_pqg_init(dsap);
rv = DSA_NewKey(dsap->pqg, dsaKey);
CHECKERROR(rv, __LINE__);
serialize_key(&(*dsaKey)->params.prime, 5, file);
} else {
setupIO(cipherInfo->arena, &asymk->key, file, NULL, 0);
*dsaKey = dsakey_from_filedata(cipherInfo->arena, &asymk->key.buf);
dsap->keysize = (*dsaKey)->params.prime.len * 8;
}
break;
case bltestECDSA:
ecKey = (ECPrivateKey **)&asymk->privKey;
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, ecKey);
CHECKERROR(rv, __LINE__);
ecSerialize[0].type = tmpECParamsDER->type;
ecSerialize[0].data = tmpECParamsDER->data;
ecSerialize[0].len = tmpECParamsDER->len;
ecSerialize[1].type = (*ecKey)->publicValue.type;
ecSerialize[1].data = (*ecKey)->publicValue.data;
ecSerialize[1].len = (*ecKey)->publicValue.len;
ecSerialize[2].type = (*ecKey)->privateValue.type;
ecSerialize[2].data = (*ecKey)->privateValue.data;
ecSerialize[2].len = (*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, &asymk->key, file, NULL, 0);
*ecKey = eckey_from_filedata(cipherInfo->arena, &asymk->key.buf);
}
break;
default:
return SECFailure;
}
return SECSuccess;
}
SECStatus
cipherInit(bltestCipherInfo *cipherInfo, PRBool encrypt)
{
PRBool restart;
int outlen;
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;
#ifndef NSS_DISABLE_DEPRECATED_RC2
case bltestRC2_ECB:
case bltestRC2_CBC:
SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
cipherInfo->input.pBuf.len);
return bltest_rc2_init(cipherInfo, encrypt);
break;
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
case bltestRC4:
SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
cipherInfo->input.pBuf.len);
return bltest_rc4_init(cipherInfo, encrypt);
break;
#ifdef NSS_SOFTOKEN_DOES_RC5
case bltestRC5_ECB:
case bltestRC5_CBC:
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:
case bltestAES_CTS:
case bltestAES_CTR:
case bltestAES_GCM:
outlen = cipherInfo->input.pBuf.len;
if (cipherInfo->mode == bltestAES_GCM && encrypt) {
outlen += 16;
}
SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, outlen);
return bltest_aes_init(cipherInfo, encrypt);
break;
case bltestCAMELLIA_ECB:
case bltestCAMELLIA_CBC:
SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
cipherInfo->input.pBuf.len);
return bltest_camellia_init(cipherInfo, encrypt);
break;
#ifndef NSS_DISABLE_DEPRECATED_SEED
case bltestSEED_ECB:
case bltestSEED_CBC:
SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
cipherInfo->input.pBuf.len);
return bltest_seed_init(cipherInfo, encrypt);
break;
#endif /* NSS_DISABLE_DEPRECATED_SEED */
case bltestCHACHA20:
outlen = cipherInfo->input.pBuf.len + (encrypt ? 16 : 0);
SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, outlen);
return bltest_chacha20_init(cipherInfo, encrypt);
break;
case bltestRSA:
case bltestRSA_OAEP:
case bltestRSA_PSS:
if (encrypt || cipherInfo->mode != bltestRSA_PSS) {
/* Don't allocate a buffer for PSS in verify mode, as no actual
* output is produced. */
SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
RSA_MAX_MODULUS_BITS / 8);
}
return bltest_rsa_init(cipherInfo, encrypt);
break;
case bltestDSA:
if (encrypt) {
SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
DSA_MAX_SIGNATURE_LEN);
}
return bltest_dsa_init(cipherInfo, encrypt);
break;
case bltestECDSA:
if (encrypt) {
SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
2 * MAX_ECKEY_LEN);
}
return bltest_ecdsa_init(cipherInfo, encrypt);
break;
case bltestMD2:
restart = cipherInfo->params.hash.restart;
SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
MD2_LENGTH);
cipherInfo->cipher.hashCipher = (restart) ? md2_restart : md2_HashBuf;
return 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 bltestSHA224:
restart = cipherInfo->params.hash.restart;
SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
SHA224_LENGTH);
cipherInfo->cipher.hashCipher = (restart) ? SHA224_restart
: SHA224_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
cipherDoOp(bltestCipherInfo *cipherInfo)
{
PRIntervalTime time1, time2;
SECStatus rv = SECSuccess;
int i;
unsigned int len;
unsigned int maxLen = cipherInfo->output.pBuf.len;
unsigned char *dummyOut;
dummyOut = PORT_Alloc(maxLen);
if (is_symmkeyCipher(cipherInfo->mode)) {
const unsigned char *input = cipherInfo->input.pBuf.data;
unsigned int inputLen = is_singleShotCipher(cipherInfo->mode) ? cipherInfo->input.pBuf.len
: PR_MIN(cipherInfo->input.pBuf.len, 16);
unsigned char *output = cipherInfo->output.pBuf.data;
unsigned int outputLen = maxLen;
unsigned int totalOutputLen = 0;
TIMESTART();
rv = (*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx,
output, &len, outputLen,
input, inputLen);
CHECKERROR(rv, __LINE__);
totalOutputLen += len;
if (cipherInfo->input.pBuf.len > inputLen) {
input += inputLen;
inputLen = cipherInfo->input.pBuf.len - inputLen;
output += len;
outputLen -= len;
rv = (*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx,
output, &len, outputLen,
input, inputLen);
CHECKERROR(rv, __LINE__);
totalOutputLen += len;
}
cipherInfo->output.pBuf.len = totalOutputLen;
TIMEFINISH(cipherInfo->optime, 1.0);
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;
TIMEMARK(cipherInfo->seconds);
while (!(TIMETOFINISH())) {
int j = 0;
for (; j < opsBetweenChecks; j++) {
(*cipherInfo->cipher.symmkeyCipher)(
cipherInfo->cx, dummyOut, &len, maxLen,
cipherInfo->input.pBuf.data,
cipherInfo->input.pBuf.len);
}
cipherInfo->repetitions += j;
}
}
TIMEFINISH(cipherInfo->optime, 1.0);
} else if (is_aeadCipher(cipherInfo->mode)) {
const unsigned char *input = cipherInfo->input.pBuf.data;
unsigned int inputLen = cipherInfo->input.pBuf.len;
unsigned char *output = cipherInfo->output.pBuf.data;
unsigned int outputLen;
bltestSymmKeyParams *sk = &cipherInfo->params.sk;
bltestAuthSymmKeyParams *ask = &cipherInfo->params.ask;
TIMESTART();
rv = (*cipherInfo->cipher.aeadCipher)(
cipherInfo->cx,
output, &outputLen, maxLen,
input, inputLen,
sk->iv.buf.data, sk->iv.buf.len,
ask->aad.buf.data, ask->aad.buf.len);
CHECKERROR(rv, __LINE__);
cipherInfo->output.pBuf.len = outputLen;
TIMEFINISH(cipherInfo->optime, 1.0);
cipherInfo->repetitions = 0;
if (cipherInfo->repetitionsToPerfom != 0) {
TIMESTART();
for (i = 0; i < cipherInfo->repetitionsToPerfom; i++,
cipherInfo->repetitions++) {
rv = (*cipherInfo->cipher.aeadCipher)(
cipherInfo->cx,
output, &outputLen, maxLen,
input, inputLen,
sk->iv.buf.data, sk->iv.buf.len,
ask->aad.buf.data, ask->aad.buf.len);
CHECKERROR(rv, __LINE__);
}
} else {
int opsBetweenChecks = 0;
TIMEMARK(cipherInfo->seconds);
while (!(TIMETOFINISH())) {
int j = 0;
for (; j < opsBetweenChecks; j++) {
(*cipherInfo->cipher.aeadCipher)(
cipherInfo->cx,
output, &outputLen, maxLen,
input, inputLen,
sk->iv.buf.data, sk->iv.buf.len,
ask->aad.buf.data, ask->aad.buf.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)
{
SECStatus rv = SECSuccess;
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_GCM:
case bltestAES_ECB:
case bltestAES_CBC:
case bltestAES_CTS:
case bltestAES_CTR:
AES_DestroyContext((AESContext *)cipherInfo->cx, PR_TRUE);
break;
case bltestCAMELLIA_ECB:
case bltestCAMELLIA_CBC:
Camellia_DestroyContext((CamelliaContext *)cipherInfo->cx, PR_TRUE);
break;
#ifndef NSS_DISABLE_DEPRECATED_SEED
case bltestSEED_ECB:
case bltestSEED_CBC:
SEED_DestroyContext((SEEDContext *)cipherInfo->cx, PR_TRUE);
break;
#endif /* NSS_DISABLE_DEPRECATED_SEED */
case bltestCHACHA20:
ChaCha20Poly1305_DestroyContext((ChaCha20Poly1305Context *)
cipherInfo->cx,
PR_TRUE);
break;
#ifndef NSS_DISABLE_DEPRECATED_RC2
case bltestRC2_ECB:
case bltestRC2_CBC:
RC2_DestroyContext((RC2Context *)cipherInfo->cx, PR_TRUE);
break;
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
case bltestRC4:
RC4_DestroyContext((RC4Context *)cipherInfo->cx, PR_TRUE);
break;
#ifdef 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 bltestRSA_PSS: /* will be freed with it. */
case bltestRSA_OAEP:
case bltestDSA:
case bltestECDSA:
case bltestMD2: /* hash contexts are ephemeral */
case bltestMD5:
case bltestSHA1:
case bltestSHA224:
case bltestSHA256:
case bltestSHA384:
case bltestSHA512:
return SECSuccess;
break;
default:
return SECFailure;
}
return rv;
}
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 {
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 += (PRInt64)info->input.buf.len * (PRInt64)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 bltestAES_CTS:
case bltestAES_CTR:
case bltestAES_GCM:
case bltestCAMELLIA_ECB:
case bltestCAMELLIA_CBC:
#ifndef NSS_DISABLE_DEPRECATED_SEED
case bltestSEED_ECB:
case bltestSEED_CBC:
#endif
#ifndef NSS_DISABLE_DEPRECATED_RC2
case bltestRC2_ECB:
case bltestRC2_CBC:
#endif
case bltestRC4:
if (td)
fprintf(stdout, "%8s", "symmkey");
else
fprintf(stdout, "%8d", 8 * info->params.sk.key.buf.len);
break;
#ifdef 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:
case bltestRSA_PSS:
case bltestRSA_OAEP:
if (td) {
fprintf(stdout, "%8s", "rsa_mod");
fprintf(stdout, "%12s", "rsa_pe");
} else {
bltestAsymKeyParams *asymk = &info->params.asymk;
fprintf(stdout, "%8d", asymk->cipherParams.rsa.keysizeInBits);
print_exponent(
&((RSAPrivateKey *)asymk->privKey)->publicExponent);
}
break;
case bltestDSA:
if (td) {
fprintf(stdout, "%8s", "pqg_mod");
} else {
fprintf(stdout, "%8d", info->params.asymk.cipherParams.dsa.keysize);
}
break;
case bltestECDSA:
if (td) {
fprintf(stdout, "%12s", "ec_curve");
} else {
ECPrivateKey *key = (ECPrivateKey *)info->params.asymk.privKey;
ECCurveName curveName = key->ecParams.name;
fprintf(stdout, "%12s",
ecCurve_map[curveName] ? ecCurve_map[curveName]->text : "Unsupported curve");
}
break;
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(PLArenaPool *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);
PR_Close(file);
}
}
HASH_HashType
mode_str_to_hash_alg(const SECItem *modeStr)
{
bltestCipherMode mode;
char *tempModeStr = NULL;
if (!modeStr || modeStr->len == 0)
return HASH_AlgNULL;
tempModeStr = PORT_Alloc(modeStr->len + 1);
if (!tempModeStr)
return HASH_AlgNULL;
memcpy(tempModeStr, modeStr->data, modeStr->len);
tempModeStr[modeStr->len] = '\0';
mode = get_mode(tempModeStr);
PORT_Free(tempModeStr);
switch (mode) {
case bltestMD2:
return HASH_AlgMD2;
case bltestMD5:
return HASH_AlgMD5;
case bltestSHA1:
return HASH_AlgSHA1;
case bltestSHA224:
return HASH_AlgSHA224;
case bltestSHA256:
return HASH_AlgSHA256;
case bltestSHA384:
return HASH_AlgSHA384;
case bltestSHA512:
return HASH_AlgSHA512;
default:
return HASH_AlgNULL;
}
}
void
get_params(PLArenaPool *arena, bltestParams *params,
bltestCipherMode mode, int j)
{
char filename[256];
char *modestr = mode_strings[mode];
bltestIO tempIO;
#ifdef NSS_SOFTOKEN_DOES_RC5
FILE *file;
char *mark, *param, *val;
int index = 0;
#endif
switch (mode) {
case bltestAES_GCM:
case bltestCHACHA20:
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "aad", j);
load_file_data(arena, &params->ask.aad, filename, bltestBinary);
case bltestDES_CBC:
case bltestDES_EDE_CBC:
#ifndef NSS_DISABLE_DEPRECATED_RC2
case bltestRC2_CBC:
#endif
case bltestAES_CBC:
case bltestAES_CTS:
case bltestAES_CTR:
case bltestCAMELLIA_CBC:
#ifndef NSS_DISABLE_DEPRECATED_SEED
case bltestSEED_CBC:
#endif
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "iv", j);
load_file_data(arena, &params->sk.iv, filename, bltestBinary);
case bltestDES_ECB:
case bltestDES_EDE_ECB:
#ifndef NSS_DISABLE_DEPRECATED_RC2
case bltestRC2_ECB:
#endif
case bltestRC4:
case bltestAES_ECB:
case bltestCAMELLIA_ECB:
#ifndef NSS_DISABLE_DEPRECATED_SEED
case bltestSEED_ECB:
#endif
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
load_file_data(arena, &params->sk.key, filename, bltestBinary);
break;
#ifdef 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, &params->sk.iv, filename, bltestBinary);
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
load_file_data(arena, &params->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_PSS:
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "ciphertext", j);
load_file_data(arena, &params->asymk.sig, filename, bltestBase64Encoded);
/* fall through */
case bltestRSA_OAEP:
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "seed", j);
load_file_data(arena, &params->asymk.cipherParams.rsa.seed,
filename, bltestBase64Encoded);
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "hash", j);
load_file_data(arena, &tempIO, filename, bltestBinary);
params->asymk.cipherParams.rsa.hashAlg =
mode_str_to_hash_alg(&tempIO.buf);
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "maskhash", j);
load_file_data(arena, &tempIO, filename, bltestBinary);
params->asymk.cipherParams.rsa.maskHashAlg =
mode_str_to_hash_alg(&tempIO.buf);
/* fall through */
case bltestRSA:
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
load_file_data(arena, &params->asymk.key, filename,
bltestBase64Encoded);
params->asymk.privKey =
(void *)rsakey_from_filedata(arena, &params->asymk.key.buf);
break;
case bltestDSA:
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
load_file_data(arena, &params->asymk.key, filename, bltestBase64Encoded);
params->asymk.privKey =
(void *)dsakey_from_filedata(arena, &params->asymk.key.buf);
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "pqg", j);
load_file_data(arena, &params->asymk.cipherParams.dsa.pqgdata, filename,
bltestBase64Encoded);
params->asymk.cipherParams.dsa.pqg =
pqg_from_filedata(arena, &params->asymk.cipherParams.dsa.pqgdata.buf);
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "keyseed", j);
load_file_data(arena, &params->asymk.cipherParams.dsa.keyseed, filename,
bltestBase64Encoded);
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "sigseed", j);
load_file_data(arena, &params->asymk.cipherParams.dsa.sigseed, filename,
bltestBase64Encoded);
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "ciphertext", j);
load_file_data(arena, &params->asymk.sig, filename, bltestBase64Encoded);
break;
case bltestECDSA:
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
load_file_data(arena, &params->asymk.key, filename, bltestBase64Encoded);
params->asymk.privKey =
(void *)eckey_from_filedata(arena, &params->asymk.key.buf);
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "sigseed", j);
load_file_data(arena, &params->asymk.cipherParams.ecdsa.sigseed,
filename, bltestBase64Encoded);
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "ciphertext", j);
load_file_data(arena, &params->asymk.sig, filename, bltestBase64Encoded);
break;
case bltestMD2:
case bltestMD5:
case bltestSHA1:
case bltestSHA224:
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)
{
PRBool equal;
char *modestr = mode_strings[mode];
equal = SECITEM_ItemsAreEqual(&result->pBuf, &cmp->buf);
if (is_sigCipher(mode)) {
if (forward) {
if (equal) {
printf("Signature self-test for %s passed.\n", modestr);
} else {
printf("Signature self-test for %s failed!\n", modestr);
}
return equal ? SECSuccess : SECFailure;
} 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 (equal) {
printf("Hash self-test for %s passed.\n", modestr);
} else {
printf("Hash self-test for %s failed!\n", modestr);
}
} else {
if (forward) {
if (equal) {
printf("Encryption self-test for %s passed.\n", modestr);
} else {
printf("Encryption self-test for %s failed!\n", modestr);
}
} else {
if (equal) {
printf("Decryption self-test for %s passed.\n", modestr);
} else {
printf("Decryption self-test for %s failed!\n", modestr);
}
}
}
return equal ? SECSuccess : SECFailure;
}
static SECStatus
ReadFileToItem(PLArenaPool *arena, SECItem *dst, const char *filename)
{
SECItem tmp = { siBuffer, NULL, 0 };
PRFileDesc *file;
SECStatus rv;
file = PR_Open(filename, PR_RDONLY, 00660);
if (!file) {
return SECFailure;
}
rv = SECU_FileToItem(&tmp, file);
rv |= SECITEM_CopyItem(arena, dst, &tmp);
SECITEM_FreeItem(&tmp, PR_FALSE);
PR_Close(file);
return rv;
}
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;
unsigned int i, j, nummodes, numtests;
char *modestr;
char filename[256];
PLArenaPool *arena;
SECItem item;
SECStatus rv = SECSuccess, srv;
PORT_Memset(&cipherInfo, 0, sizeof(cipherInfo));
arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
cipherInfo.arena = arena;
nummodes = (numModes == 0) ? NUMMODES : numModes;
for (i = 0; i < nummodes; i++) {
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;
/* get the number of tests in the directory */
sprintf(filename, "%s/tests/%s/%s", testdir, modestr, "numtests");
if (ReadFileToItem(arena, &item, filename) != SECSuccess) {
fprintf(stderr, "%s: Cannot read file %s.\n", progName, filename);
rv = SECFailure;
continue;
}
/* 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++) {
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr,
"plaintext", j);
load_file_data(arena, &pt, filename,
is_sigCipher(mode) ? bltestBase64Encoded
: bltestBinary);
sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr,
"ciphertext", j);
load_file_data(arena, &ct, filename, bltestBase64Encoded);
get_params(arena, params, mode, j);
/* Forward Operation (Encrypt/Sign/Hash)
** Align the input buffer (plaintext) according to request
** then perform operation and compare to ciphertext
*/
if (encrypt) {
rv |= bltestCopyIO(arena, &cipherInfo.input, &pt);
misalignBuffer(arena, &cipherInfo.input, inoff);
memset(&cipherInfo.output.buf, 0, sizeof cipherInfo.output.buf);
rv |= cipherInit(&cipherInfo, PR_TRUE);
misalignBuffer(arena, &cipherInfo.output, outoff);
rv |= cipherDoOp(&cipherInfo);
rv |= cipherFinish(&cipherInfo);
rv |= verify_self_test(&cipherInfo.output,
&ct, mode, PR_TRUE, SECSuccess);
/* If testing hash, only one op to test */
if (is_hashCipher(mode))
continue;
if (is_sigCipher(mode)) {
/* Verify operations support detached signature files. For
** consistency between tests that run Sign/Verify back to
** back (eg: self-tests) and tests that are only running
** verify operations, copy the output into the sig buf,
** and then copy the sig buf back out when verifying. For
** self-tests, this is unnecessary copying, but for
** verify-only operations, this ensures that the output
** buffer is properly configured
*/
rv |= bltestCopyIO(arena, &params->asymk.sig, &cipherInfo.output);
}
}
if (!decrypt)
continue;
/* Reverse Operation (Decrypt/Verify)
** Align the input buffer (ciphertext) according to request
** then perform operation and compare to plaintext
*/
if (is_sigCipher(mode)) {
rv |= bltestCopyIO(arena, &cipherInfo.input, &pt);
rv |= bltestCopyIO(arena, &cipherInfo.output, &params->asymk.sig);
} else {
rv |= bltestCopyIO(arena, &cipherInfo.input, &ct);
memset(&cipherInfo.output.buf, 0, sizeof cipherInfo.output.buf);
}
misalignBuffer(arena, &cipherInfo.input, inoff);
rv |= cipherInit(&cipherInfo, PR_FALSE);
misalignBuffer(arena, &cipherInfo.output, outoff);
srv = SECSuccess;
srv |= cipherDoOp(&cipherInfo);
rv |= cipherFinish(&cipherInfo);
rv |= verify_self_test(&cipherInfo.output,
&pt, mode, PR_FALSE, srv);
}
}
PORT_FreeArena(arena, PR_FALSE);
return rv;
}
SECStatus
dump_file(bltestCipherMode mode, char *filename)
{
bltestIO keydata;
PLArenaPool *arena = NULL;
arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
if (!arena) {
return SECFailure;
}
if (mode == bltestRSA || mode == bltestRSA_PSS || mode == bltestRSA_OAEP) {
RSAPrivateKey *key;
load_file_data(arena, &keydata, filename, bltestBase64Encoded);
key = rsakey_from_filedata(arena, &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(arena, &keydata.buf);
dump_dsakey(key);
} else if (mode == bltestECDSA) {
ECPrivateKey *key;
load_file_data(arena, &keydata, filename, bltestBase64Encoded);
key = eckey_from_filedata(arena, &keydata.buf);
dump_eckey(key);
}
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);
}
static void
rsaPrivKeyReset(RSAPrivateKey *tstKey)
{
PLArenaPool *arena;
tstKey->version.data = NULL;
tstKey->version.len = 0;
tstKey->modulus.data = NULL;
tstKey->modulus.len = 0;
tstKey->publicExponent.data = NULL;
tstKey->publicExponent.len = 0;
tstKey->privateExponent.data = NULL;
tstKey->privateExponent.len = 0;
tstKey->prime1.data = NULL;
tstKey->prime1.len = 0;
tstKey->prime2.data = NULL;
tstKey->prime2.len = 0;
tstKey->exponent1.data = NULL;
tstKey->exponent1.len = 0;
tstKey->exponent2.data = NULL;
tstKey->exponent2.len = 0;
tstKey->coefficient.data = NULL;
tstKey->coefficient.len = 0;
arena = tstKey->arena;
tstKey->arena = NULL;
if (arena) {
PORT_FreeArena(arena, PR_TRUE);
}
}
#define RSA_TEST_EQUAL(comp) \
if (!SECITEM_ItemsAreEqual(&(src->comp), &(dest->comp))) { \
fprintf(stderr, "key->" #comp " not equal"); \
if (src->comp.len != dest->comp.len) { \
fprintf(stderr, "src_len = %d, dest_len = %d", \
src->comp.len, dest->comp.len); \
} \
fprintf(stderr, "\n"); \
areEqual = PR_FALSE; \
}
static PRBool
rsaPrivKeysAreEqual(RSAPrivateKey *src, RSAPrivateKey *dest)
{
PRBool areEqual = PR_TRUE;
RSA_TEST_EQUAL(modulus)
RSA_TEST_EQUAL(publicExponent)
RSA_TEST_EQUAL(privateExponent)
RSA_TEST_EQUAL(prime1)
RSA_TEST_EQUAL(prime2)
RSA_TEST_EQUAL(exponent1)
RSA_TEST_EQUAL(exponent2)
RSA_TEST_EQUAL(coefficient)
if (!areEqual) {
fprintf(stderr, "original key:\n");
dump_rsakey(src);
fprintf(stderr, "recreated key:\n");
dump_rsakey(dest);
}
return areEqual;
}
static int
doRSAPopulateTestKV()
{
RSAPrivateKey tstKey = { 0 };
SECStatus rv;
int failed = 0;
int i;
tstKey.arena = NULL;
/* Test public exponent, private exponent, modulus cases from
* pkcs1v15sign-vectors.txt. Some are valid PKCS#1 keys but not valid RSA
* ones (de = 1 mod lcm(p 1, q 1))
*/
for (i = 0; i < PR_ARRAY_SIZE(PKCS1_VECTORS); ++i) {
struct pkcs1_test_vector *v = &PKCS1_VECTORS[i];
rsaPrivKeyReset(&tstKey);
tstKey.privateExponent.data = v->d;
tstKey.privateExponent.len = v->d_len;
tstKey.publicExponent.data = v->e;
tstKey.publicExponent.len = v->e_len;
tstKey.modulus.data = v->n;
tstKey.modulus.len = v->n_len;
rv = RSA_PopulatePrivateKey(&tstKey);
if (rv != SECSuccess) {
fprintf(stderr, "RSA Populate failed: pkcs1v15sign-vector %d\n", i);
failed = 1;
} else if (memcmp(v->q, tstKey.prime1.data, v->q_len) ||
tstKey.prime1.len != v->q_len) {
fprintf(stderr, "RSA Populate key mismatch: pkcs1v15sign-vector %d q\n", i);
failed = 1;
} else if (memcmp(v->p, tstKey.prime2.data, v->p_len) ||
tstKey.prime1.len != v->p_len) {
fprintf(stderr, "RSA Populate key mismatch: pkcs1v15sign-vector %d p\n", i);
failed = 1;
} else {
fprintf(stderr, "RSA Populate success: pkcs1v15sign-vector %d p\n", i);
}
}
PORT_FreeArena(tstKey.arena, PR_TRUE);
return failed;
}
/*
* Test the RSA populate command to see that it can really build
* keys from its components.
*/
static int
doRSAPopulateTest(unsigned int keySize, unsigned long exponent)
{
RSAPrivateKey *srcKey;
RSAPrivateKey tstKey = { 0 };
SECItem expitem = { 0, 0, 0 };
SECStatus rv;
unsigned char pubExp[32];
int expLen = 0;
int failed = 0;
int i;
for (i = 0; i < sizeof(unsigned long); i++) {
int shift = (sizeof(unsigned long) - i - 1) * 8;
if (expLen || (exponent && ((unsigned long)0xffL << shift))) {
pubExp[expLen] = (unsigned char)((exponent >> shift) & 0xff);
expLen++;
}
}
expitem.data = pubExp;
expitem.len = expLen;
srcKey = RSA_NewKey(keySize, &expitem);
if (srcKey == NULL) {
fprintf(stderr, "RSA Key Gen failed");
return -1;
}
/* test the basic case - most common, public exponent, modulus, prime */
tstKey.arena = NULL;
rsaPrivKeyReset(&tstKey);
tstKey.publicExponent = srcKey->publicExponent;
tstKey.modulus = srcKey->modulus;
tstKey.prime1 = srcKey->prime1;
rv = RSA_PopulatePrivateKey(&tstKey);
if (rv != SECSuccess) {
fprintf(stderr, "RSA Populate failed: pubExp mod p\n");
failed = 1;
} else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
fprintf(stderr, "RSA Populate key mismatch: pubExp mod p\n");
failed = 1;
}
/* test the basic2 case, public exponent, modulus, prime2 */
rsaPrivKeyReset(&tstKey);
tstKey.publicExponent = srcKey->publicExponent;
tstKey.modulus = srcKey->modulus;
tstKey.prime1 = srcKey->prime2; /* test with q in the prime1 position */
rv = RSA_PopulatePrivateKey(&tstKey);
if (rv != SECSuccess) {
fprintf(stderr, "RSA Populate failed: pubExp mod q\n");
failed = 1;
} else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
fprintf(stderr, "RSA Populate key mismatch: pubExp mod q\n");
failed = 1;
}
/* test the medium case, private exponent, prime1, prime2 */
rsaPrivKeyReset(&tstKey);
tstKey.privateExponent = srcKey->privateExponent;
tstKey.prime1 = srcKey->prime2; /* purposefully swap them to make */
tstKey.prime2 = srcKey->prime1; /* sure populated swaps them back */
rv = RSA_PopulatePrivateKey(&tstKey);
if (rv != SECSuccess) {
fprintf(stderr, "RSA Populate failed: privExp p q\n");
failed = 1;
} else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
fprintf(stderr, "RSA Populate key mismatch: privExp p q\n");
failed = 1;
}
/* test the advanced case, public exponent, private exponent, prime2 */
rsaPrivKeyReset(&tstKey);
tstKey.privateExponent = srcKey->privateExponent;
tstKey.publicExponent = srcKey->publicExponent;
tstKey.prime2 = srcKey->prime2; /* use q in the prime2 position */
rv = RSA_PopulatePrivateKey(&tstKey);
if (rv != SECSuccess) {
fprintf(stderr, "RSA Populate failed: pubExp privExp q\n");
fprintf(stderr, " - not fatal\n");
/* it's possible that we can't uniquely determine the original key
* from just the exponents and prime. Populate returns an error rather
* than return the wrong key. */
} else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
/* if we returned a key, it *must* be correct */
fprintf(stderr, "RSA Populate key mismatch: pubExp privExp q\n");
rv = RSA_PrivateKeyCheck(&tstKey);
failed = 1;
}
/* test the advanced case2, public exponent, private exponent, modulus */
rsaPrivKeyReset(&tstKey);
tstKey.privateExponent = srcKey->privateExponent;
tstKey.publicExponent = srcKey->publicExponent;
tstKey.modulus = srcKey->modulus;
rv = RSA_PopulatePrivateKey(&tstKey);
if (rv != SECSuccess) {
fprintf(stderr, "RSA Populate failed: pubExp privExp mod\n");
failed = 1;
} else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
fprintf(stderr, "RSA Populate key mismatch: pubExp privExp mod\n");
failed = 1;
}
PORT_FreeArena(srcKey->arena, PR_TRUE);
return failed ? -1 : 0;
}
/* bltest commands */
enum {
cmd_Decrypt = 0,
cmd_Encrypt,
cmd_FIPS,
cmd_Hash,
cmd_Nonce,
cmd_Dump,
cmd_RSAPopulate,
cmd_RSAPopulateKV,
cmd_Sign,
cmd_SelfTest,
cmd_Verify
};
/* bltest options */
enum {
opt_B64 = 0,
opt_BufSize,
opt_Restart,
opt_SelfTestDir,
opt_Exponent,
opt_SigFile,
opt_KeySize,
opt_Hex,
opt_Input,
opt_PQGFile,
opt_Key,
opt_HexWSpc,
opt_Mode,
opt_CurveName,
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_AAD,
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_RSAPopulate */ 'R', PR_FALSE, 0, PR_FALSE },
{ /* cmd_RSAPopulateKV */ 'K', PR_FALSE, 0, PR_FALSE },
{ /* cmd_Sign */ 'S', PR_FALSE, 0, PR_FALSE },
{ /* cmd_SelfTest */ 'T', PR_FALSE, 0, PR_FALSE },
{ /* cmd_Verify */ 'V', PR_FALSE, 0, PR_FALSE }
};
static secuCommandFlag bltest_options[] =
{
{ /* opt_B64 */ 'a', PR_FALSE, 0, PR_FALSE },
{ /* opt_BufSize */ 'b', PR_TRUE, 0, PR_FALSE },
{ /* opt_Restart */ 'c', PR_FALSE, 0, PR_FALSE },
{ /* opt_SelfTestDir */ 'd', PR_TRUE, 0, PR_FALSE },
{ /* opt_Exponent */ 'e', PR_TRUE, 0, PR_FALSE },
{ /* opt_SigFile */ 'f', PR_TRUE, 0, PR_FALSE },
{ /* opt_KeySize */ 'g', PR_TRUE, 0, PR_FALSE },
{ /* opt_Hex */ 'h', PR_FALSE, 0, PR_FALSE },
{ /* opt_Input */ 'i', PR_TRUE, 0, PR_FALSE },
{ /* opt_PQGFile */ 'j', PR_TRUE, 0, PR_FALSE },
{ /* opt_Key */ 'k', PR_TRUE, 0, PR_FALSE },
{ /* opt_HexWSpc */ 'l', PR_FALSE, 0, PR_FALSE },
{ /* opt_Mode */ 'm', PR_TRUE, 0, PR_FALSE },
{ /* opt_CurveName */ 'n', PR_TRUE, 0, PR_FALSE },
{ /* opt_Output */ 'o', PR_TRUE, 0, PR_FALSE },
{ /* opt_Repetitions */ 'p', PR_TRUE, 0, PR_FALSE },
{ /* opt_ZeroBuf */ 'q', PR_FALSE, 0, PR_FALSE },
{ /* opt_Rounds */ 'r', PR_TRUE, 0, PR_FALSE },
{ /* opt_Seed */ 's', PR_TRUE, 0, PR_FALSE },
{ /* opt_SigSeedFile */ 't', PR_TRUE, 0, PR_FALSE },
{ /* opt_CXReps */ 'u', PR_TRUE, 0, PR_FALSE },
{ /* opt_IV */ 'v', PR_TRUE, 0, PR_FALSE },
{ /* opt_WordSize */ 'w', PR_TRUE, 0, PR_FALSE },
{ /* opt_UseSeed */ 'x', PR_FALSE, 0, PR_FALSE },
{ /* opt_UseSigSeed */ 'y', PR_FALSE, 0, PR_FALSE },
{ /* opt_SeedFile */ 'z', PR_FALSE, 0, PR_FALSE },
{ /* opt_AAD */ 0, PR_TRUE, 0, PR_FALSE, "aad" },
{ /* 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)
{
SECStatus rv = SECFailure;
double totalTime = 0.0;
PRIntervalTime time1, time2;
PRFileDesc *outfile = NULL;
bltestCipherInfo *cipherInfoListHead, *cipherInfo = NULL;
bltestIOMode ioMode;
int bufsize, exponent, curThrdNum;
char *curveName = NULL;
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 = NSS_InitializePRErrorTable();
if (rv != SECSuccess) {
SECU_PrintPRandOSError(progName);
return -1;
}
rv = RNG_RNGInit();
if (rv != SECSuccess) {
SECU_PrintPRandOSError(progName);
return -1;
}
rv = BL_Init();
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;
/* 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
*/
/* test the RSA_PopulatePrivateKey function with known vectors */
if (bltest.commands[cmd_RSAPopulateKV].activated) {
PORT_Free(cipherInfo);
return doRSAPopulateTestKV();
}
/* test the RSA_PopulatePrivateKey function */
if (bltest.commands[cmd_RSAPopulate].activated) {
unsigned int keySize = 1024;
unsigned long keyExponent = 65537;
int rounds = 1;
int ret = -1;
if (bltest.options[opt_KeySize].activated) {
keySize = PORT_Atoi(bltest.options[opt_KeySize].arg);
}
if (bltest.options[opt_Rounds].activated) {
rounds = PORT_Atoi(bltest.options[opt_Rounds].arg);
}
if (bltest.options[opt_Exponent].activated) {
keyExponent = PORT_Atoi(bltest.options[opt_Exponent].arg);
}
for (i = 0; i < rounds; i++) {
printf("Running RSA Populate test round %d\n", i);
ret = doRSAPopulateTest(keySize, keyExponent);
if (ret != 0) {
break;
}
}
if (ret != 0) {
fprintf(stderr, "RSA Populate test round %d: FAILED\n", i);
}
PORT_Free(cipherInfo);
return ret;
}
/* 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 == SECSuccess ? 0 : 1;
}
/* Do FIPS self-test */
if (bltest.commands[cmd_FIPS].activated) {
CK_RV ckrv = sftk_FIPSEntryOK();
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;
if (bltest.options[opt_CurveName].activated)
curveName = PORT_Strdup(bltest.options[opt_CurveName].arg);
else
curveName = NULL;
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:
if (cipherInfo) {
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;
PLArenaPool *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) ||
is_aeadCipher(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, &params->key, file, keystr, keysize);
if (file)
PR_Close(file);
} else if (is_pubkeyCipher(cipherInfo->mode)) {
if (bltest.options[opt_Key].activated) {
file = PR_Open(bltest.options[opt_Key].arg, PR_RDONLY, 00660);
} else {
if (bltest.options[opt_KeySize].activated)
keysize = PORT_Atoi(bltest.options[opt_KeySize].arg);
else
keysize = 64; /* use 512-bit default */
file = PR_Open("tmp.key", PR_WRONLY | PR_CREATE_FILE, 00660);
}
params->key.mode = bltestBase64Encoded;
pubkeyInitKey(cipherInfo, file, keysize, exponent, curveName);
PR_Close(file);
}
/* set up an initialization vector. */
if (cipher_requires_IV(cipherInfo->mode)) {
char *ivstr = NULL;
bltestSymmKeyParams *skp;
file = NULL;
#ifdef NSS_SOFTOKEN_DOES_RC5
if (cipherInfo->mode == bltestRC5_CBC)
skp = (bltestSymmKeyParams *)&params->rc5;
else
#endif
skp = &params->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);
}
}
/* set up an initialization vector. */
if (is_authCipher(cipherInfo->mode)) {
char *aadstr = NULL;
bltestAuthSymmKeyParams *askp;
file = NULL;
askp = &params->ask;
if (bltest.options[opt_AAD].activated) {
if (bltest.options[opt_CmdLine].activated) {
aadstr = bltest.options[opt_AAD].arg;
} else {
file = PR_Open(bltest.options[opt_AAD].arg,
PR_RDONLY, 00660);
}
} else {
file = NULL;
}
memset(&askp->aad, 0, sizeof askp->aad);
askp->aad.mode = ioMode;
setupIO(cipherInfo->arena, &askp->aad, file, aadstr, 0);
if (file) {
PR_Close(file);
}
}
if (bltest.commands[cmd_Verify].activated) {
file = PR_Open(bltest.options[opt_SigFile].arg, PR_RDONLY, 00660);
if (is_sigCipher(cipherInfo->mode)) {
memset(&params->asymk.sig, 0, sizeof(bltestIO));
params->asymk.sig.mode = ioMode;
setupIO(cipherInfo->arena, &params->asymk.sig, file, NULL, 0);
}
if (file) {
PR_Close(file);
}
}
if (bltest.options[opt_PQGFile].activated) {
file = PR_Open(bltest.options[opt_PQGFile].arg, PR_RDONLY, 00660);
params->asymk.cipherParams.dsa.pqgdata.mode = bltestBase64Encoded;
setupIO(cipherInfo->arena, &params->asymk.cipherParams.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;
}