/* 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 "chacha20poly1305.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_CTR,
/* ChaCha20 block cipher */
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,
/* . */
bltestSHA3_224,
/* . */
bltestSHA3_256,
/* . */
bltestSHA3_384,
/* . */
bltestSHA3_512,
/* . */
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_ctr",
"chacha20_poly1305",
"rsa",
"rsa_oaep",
"rsa_pss",
"ecdsa",
/*"pqg",*/
"dsa",
"md2",
"md5",
"sha1",
"sha224",
"sha256",
"sha384",
"sha512",
"sha3_224",
"sha3_256",
"sha3_384",
"sha3_512",
};
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! */
if (mode >= bltestDES_ECB && mode <= bltestCHACHA20_CTR)
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_CTR:
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 <= bltestSHA3_512)
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_CTR:
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_Encrypt(
void *cx,
unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input,
unsigned int inputLen)
{
if (maxOutputLen < inputLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
ChaCha20Context *ctx = cx;
*outputLen = inputLen;
return ChaCha20_Xor(output, input, inputLen, ctx->key, ctx->nonce,
ctx->counter);
}
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 = ¶ms->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 = ¶ms->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 = ¶ms->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 = ¶ms->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_ctr_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
{
const PRUint32 counter = 1;
bltestSymmKeyParams *sk = &cipherInfo->params.sk;
cipherInfo->cx = ChaCha20_CreateContext(sk->key.buf.data, sk->key.buf.len,
sk->iv.buf.data, sk->iv.buf.len,
counter);
if (cipherInfo->cx == NULL) {
PR_fprintf(PR_STDERR,
"ChaCha20_CreateContext() returned NULL\n"
"key must be 32 bytes, iv must be 12 bytes\n");
return SECFailure;
}
cipherInfo->cipher.symmkeyCipher = chacha20_Encrypt;
return SECSuccess;
}
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;
--> --------------------
--> maximum size reached
--> --------------------