#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <Security/cssm.h>
#include "cspwrap.h"
#include "common.h"
#include "cspdlTesting.h"
#define AES_BLOCK_SIZE 16
#define LOOPS_DEF 10
#define MIN_PTEXT_SIZE AES_BLOCK_SIZE
#define MAX_PTEXT_SIZE 1000
#define MAX_PASSWORD_SIZE 64
#define MAX_SALT_SIZE 32
#define MIN_ITER_COUNT 1000
#define MAX_ITER_COUNT 2000
#define MAX_IV_SIZE AES_BLOCK_SIZE
#define APPLE_PBE_MIN_PASSWORD 8
#define APPLE_PBE_MIN_SALT 8
CSSM_DATA staticIv = {MAX_IV_SIZE, (uint8 *)"someIvOrOther..."};
typedef unsigned privAlg;
enum {
pbe_pbkdf2 = 1,
pbe_PKCS12 = 1,
pbe_MD5,
pbe_MD2,
pbe_SHA1,
pka_ASC,
pka_RC4,
pka_DES,
pka_RC2,
pka_RC5,
pka_3DES,
pka_AES
};
#define PBE_ALG_FIRST pbe_pbkdf2
#define PBE_ALG_LAST pbe_pbkdf2
#define ENCR_ALG_FIRST pka_ASC
#define ENCR_ALG_LAST pka_AES
#define ENCR_ALG_LAST_EXPORT pka_RC5
typedef struct {
CSSM_CSP_HANDLE cspHand;
CSSM_ALGORITHMS keyAlg;
CSSM_ALGORITHMS encrAlg;
uint32 keySizeInBits;
uint32 effectiveKeySizeInBits; const char *keyAlgStr;
CSSM_ENCRYPT_MODE encrMode;
CSSM_PADDING encrPad;
CSSM_ALGORITHMS deriveAlg;
const char *deriveAlgStr;
CSSM_DATA_PTR ptext;
CSSM_DATA_PTR password;
CSSM_DATA_PTR salt;
uint32 iterCount;
CSSM_BOOL useInitVector; uint32 ivSize;
CSSM_BOOL genInitVector; CSSM_BOOL useRefKey;
CSSM_BOOL quiet;
} testArgs;
static void usage(char **argv)
{
printf("usage: %s [options]\n", argv[0]);
printf(" Options:\n");
printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
printf(" e(xport)\n");
printf(" r(epeatOnly)\n");
printf(" z(ero length password)\n");
printf(" p(ause after each loop)\n");
printf(" D (CSP/DL; default = bare CSP)\n");
printf(" q(uiet)\n");
printf(" h(elp)\n");
exit(1);
}
static void algInfo(privAlg alg, CSSM_ALGORITHMS *cdsaAlg, CSSM_ALGORITHMS *encrAlg, CSSM_ENCRYPT_MODE *mode, CSSM_PADDING *padding, CSSM_BOOL *useInitVector, uint32 *ivSize, CSSM_BOOL *genInitVector, const char **algStr) {
*mode = CSSM_ALGMODE_NONE;
*useInitVector = CSSM_FALSE;
*genInitVector = CSSM_FALSE; *padding = CSSM_PADDING_PKCS1;
*ivSize = 8; *encrAlg = CSSM_ALGID_NONE;
switch(alg) {
case pbe_pbkdf2:
*cdsaAlg = CSSM_ALGID_PKCS5_PBKDF2;
*algStr = "PBKDF2";
return;
#if 0
case pbe_PKCS12:
*cdsaAlg = CSSM_ALGID_SHA1_PBE_PKCS12;
*algStr = "PKCS12";
return;
case pbe_MD5:
*cdsaAlg = CSSM_ALGID_MD5_PBE;
*algStr = "MD5";
return;
case pbe_MD2:
*cdsaAlg = CSSM_ALGID_MD2_PBE;
*algStr = "MD2";
return;
case pbe_SHA1:
*cdsaAlg = CSSM_ALGID_SHA1_PBE;
*algStr = "SHA1";
return;
case pka_ASC:
*cdsaAlg = CSSM_ALGID_ASC;
*algStr = "ASC";
return;
#endif
case pka_DES:
*cdsaAlg = *encrAlg = CSSM_ALGID_DES;
*useInitVector = CSSM_TRUE;
*mode = CSSM_ALGMODE_CBCPadIV8;
*algStr = "DES";
return;
case pka_3DES:
*cdsaAlg = CSSM_ALGID_3DES_3KEY;
*encrAlg = CSSM_ALGID_3DES_3KEY_EDE;
*useInitVector = CSSM_TRUE;
*mode = CSSM_ALGMODE_CBCPadIV8;
*algStr = "3DES";
return;
case pka_AES:
*cdsaAlg = *encrAlg = CSSM_ALGID_AES;
*useInitVector = CSSM_TRUE;
*mode = CSSM_ALGMODE_CBCPadIV8;
*padding = CSSM_PADDING_PKCS5;
*ivSize = AES_BLOCK_SIZE; *algStr = "AES";
return;
case pka_RC2:
*cdsaAlg = *encrAlg = CSSM_ALGID_RC2;
*useInitVector = CSSM_TRUE;
*mode = CSSM_ALGMODE_CBCPadIV8;
*algStr = "RC2";
return;
case pka_RC4:
*cdsaAlg = *encrAlg = CSSM_ALGID_RC4;
*mode = CSSM_ALGMODE_NONE;
*algStr = "RC4";
return;
case pka_RC5:
*cdsaAlg = *encrAlg = CSSM_ALGID_RC5;
*algStr = "RC5";
*mode = CSSM_ALGMODE_CBCPadIV8;
*useInitVector = CSSM_TRUE;
return;
case pka_ASC:
*cdsaAlg = *encrAlg = CSSM_ALGID_ASC;
*algStr = "ASC";
*mode = CSSM_ALGMODE_NONE;
return;
default:
printf("BRRZZZT! Update algInfo()!\n");
testError(CSSM_TRUE);
}
}
static CSSM_BOOL compareData(const CSSM_DATA_PTR d1,
const CSSM_DATA_PTR d2)
{
if(d1->Length != d2->Length) {
return CSSM_FALSE;
}
if(memcmp(d1->Data, d2->Data, d1->Length)) {
return CSSM_FALSE;
}
return CSSM_TRUE;
}
static uint8 randBit()
{
return 1 << genRand(0, 7);
}
#define SAFE_CTEXT_ARRAY 0
static int encryptCom(CSSM_CSP_HANDLE cspHand,
const char *testName,
CSSM_DATA_PTR ptext,
CSSM_KEY_PTR key,
CSSM_ALGORITHMS alg,
CSSM_ENCRYPT_MODE mode,
CSSM_PADDING padding, CSSM_DATA_PTR iv, uint32 effectiveKeySizeInBits, CSSM_DATA_PTR ctext, CSSM_BOOL quiet)
{
CSSM_CC_HANDLE cryptHand;
CSSM_RETURN crtn;
CSSM_SIZE bytesEncrypted;
CSSM_DATA remData;
int rtn;
#if SAFE_CTEXT_ARRAY
CSSM_DATA safeCtext[2];
safeCtext[0] = *ctext;
safeCtext[1].Data = NULL;
safeCtext[1].Length = 10; #else
#endif
cryptHand = genCryptHandle(cspHand,
alg,
mode,
padding,
key,
NULL, iv, effectiveKeySizeInBits,
0); if(cryptHand == 0) {
return testError(quiet);
}
remData.Data = NULL;
remData.Length = 0;
crtn = CSSM_EncryptData(cryptHand,
ptext,
1,
#if SAFE_CTEXT_ARRAY
&safeCtext[0],
#else
ctext,
#endif
1,
&bytesEncrypted,
&remData);
#if SAFE_CTEXT_ARRAY
*ctext = safeCtext[0];
#endif
if(crtn) {
printError("CSSM_EncryptData", crtn);
rtn = testError(quiet);
goto done;
}
if(remData.Length != 0) {
ctext->Data = (uint8 *)appRealloc(ctext->Data, bytesEncrypted, NULL);
memmove(ctext->Data + ctext->Length,
remData.Data,
bytesEncrypted - ctext->Length);
appFreeCssmData(&remData, CSSM_FALSE);
}
ctext->Length = bytesEncrypted;
rtn = 0;
done:
if(CSSM_DeleteContext(cryptHand)) {
printError("CSSM_DeleteContext", 0);
rtn = 1;
}
return rtn;
}
static int decryptCom(CSSM_CSP_HANDLE cspHand,
const char *testName,
CSSM_DATA_PTR ctext,
CSSM_KEY_PTR key,
CSSM_ALGORITHMS alg,
CSSM_ENCRYPT_MODE mode,
CSSM_PADDING padding,
CSSM_DATA_PTR iv, uint32 effectiveKeySizeInBits, CSSM_DATA_PTR ptext, CSSM_BOOL quiet)
{
CSSM_CC_HANDLE cryptHand;
CSSM_RETURN crtn;
CSSM_SIZE bytesDecrypted;
CSSM_DATA remData;
int rtn;
cryptHand = genCryptHandle(cspHand,
alg,
mode,
padding,
key,
NULL, iv, effectiveKeySizeInBits,
0); if(cryptHand == 0) {
return testError(quiet);
}
remData.Data = NULL;
remData.Length = 0;
crtn = CSSM_DecryptData(cryptHand,
ctext,
1,
ptext,
1,
&bytesDecrypted,
&remData);
if(crtn) {
printError("CSSM_DecryptData", crtn);
rtn = testError(quiet);
goto done;
}
if(remData.Length != 0) {
ptext->Data = (uint8 *)appRealloc(ptext->Data, bytesDecrypted, NULL);
memmove(ptext->Data + ptext->Length,
remData.Data,
bytesDecrypted - ptext->Length);
appFreeCssmData(&remData, CSSM_FALSE);
}
ptext->Length = bytesDecrypted;
rtn = 0;
done:
if(CSSM_DeleteContext(cryptHand)) {
printError("CSSM_DeleteContext", 0);
rtn = 1;
}
return rtn;
}
#define TRAP_WRITER_ERR 1
static int testCommon(CSSM_CSP_HANDLE cspHand,
const char *testName,
CSSM_ALGORITHMS encrAlg,
CSSM_ENCRYPT_MODE encrMode,
CSSM_PADDING encrPad,
uint32 effectiveKeySizeInBits,
CSSM_DATA_PTR ptext,
CSSM_KEY_PTR key1,
CSSM_DATA_PTR iv1,
CSSM_KEY_PTR key2,
CSSM_DATA_PTR iv2,
CSSM_BOOL quiet)
{
CSSM_DATA ctext1;
CSSM_DATA ctext2;
ctext1.Data = NULL;
ctext1.Length = 0;
ctext2.Data = NULL;
ctext2.Length = 0;
if(encryptCom(cspHand,
testName,
ptext,
key1,
encrAlg,
encrMode,
encrPad,
iv1,
effectiveKeySizeInBits,
&ctext1,
quiet)) {
return 1;
}
#if TRAP_WRITER_ERR
if(ctext2.Data != NULL){
printf("Hey! encryptCom(ptext, ctext1 modified ctext2!\n");
if(testError(quiet)) {
return 1;
}
}
#endif
if(encryptCom(cspHand,
testName,
ptext,
key2,
encrAlg,
encrMode,
encrPad,
iv2,
effectiveKeySizeInBits,
&ctext2,
quiet)) {
return 1;
}
if(compareData(&ctext1, &ctext2)) {
printf("***%s: Unexpected Data compare!\n", testName);
return testError(quiet);
}
appFreeCssmData(&ctext1, CSSM_FALSE);
appFreeCssmData(&ctext2, CSSM_FALSE);
return 0;
}
#define KEY_LABEL1 "noLabel1"
#define KEY_LABEL2 "noLabel2"
#define KEY_LABEL_LEN strlen(KEY_LABEL1)
#define REPEAT_ON_ERROR 1
static int repeatTest(testArgs *targs)
{
CSSM_KEY_PTR key1;
CSSM_KEY_PTR key2;
CSSM_DATA iv1;
CSSM_DATA iv2;
CSSM_DATA_PTR ivp1;
CSSM_DATA_PTR ivp2;
CSSM_DATA ctext;
CSSM_DATA rptext;
CSSM_BOOL gotErr = CSSM_FALSE;
if(targs->useInitVector) {
if(targs->genInitVector) {
ivp1 = &iv1;
ivp2 = &iv2;
}
else {
staticIv.Length = targs->ivSize;
ivp1 = ivp2 = &staticIv;
}
}
else {
ivp1 = ivp2 = NULL;
}
iv1.Data = NULL;
iv1.Length = 0;
iv2.Data = NULL;
iv2.Length = 0;
ctext.Data = NULL;
ctext.Length = 0;
rptext.Data = NULL;
rptext.Length = 0;
repeatDerive:
key1 = cspDeriveKey(targs->cspHand,
targs->deriveAlg,
targs->keyAlg,
KEY_LABEL1,
KEY_LABEL_LEN,
CSSM_KEYUSE_ENCRYPT,
targs->keySizeInBits,
targs->useRefKey,
targs->password,
targs->salt,
targs->iterCount,
&iv1);
if(key1 == NULL) {
return testError(targs->quiet);
}
key2 = cspDeriveKey(targs->cspHand,
targs->deriveAlg,
targs->keyAlg,
KEY_LABEL2,
KEY_LABEL_LEN,
CSSM_KEYUSE_DECRYPT,
targs->keySizeInBits,
targs->useRefKey,
targs->password,
targs->salt,
targs->iterCount,
&iv2);
if(key2 == NULL) {
return testError(targs->quiet);
}
repeatEnc:
if(encryptCom(targs->cspHand,
"repeatTest",
targs->ptext,
key1,
targs->encrAlg,
targs->encrMode,
targs->encrPad,
ivp1,
targs->effectiveKeySizeInBits,
&ctext,
targs->quiet)) {
return 1;
}
if(decryptCom(targs->cspHand,
"repeatTest",
&ctext,
key2,
targs->encrAlg,
targs->encrMode,
targs->encrPad,
ivp2,
targs->effectiveKeySizeInBits,
&rptext,
targs->quiet)) {
return 1;
}
if(gotErr || !compareData(targs->ptext, &rptext)) {
printf("***Data miscompare in repeatTest\n");
if(REPEAT_ON_ERROR) {
char str;
gotErr = CSSM_TRUE;
fpurge(stdin);
printf("Repeat enc/dec (r), repeat derive (d), continue (c), abort (any)? ");
str = getchar();
switch(str) {
case 'r':
appFreeCssmData(&ctext, CSSM_FALSE);
appFreeCssmData(&rptext, CSSM_FALSE);
goto repeatEnc;
case 'd':
appFreeCssmData(&ctext, CSSM_FALSE);
appFreeCssmData(&rptext, CSSM_FALSE);
appFreeCssmData(&iv1, CSSM_FALSE);
appFreeCssmData(&iv2, CSSM_FALSE);
cspFreeKey(targs->cspHand, key1);
cspFreeKey(targs->cspHand, key2);
goto repeatDerive;
case 'c':
break;
default:
return 1;
}
}
else {
return testError(targs->quiet);
}
}
appFreeCssmData(&ctext, CSSM_FALSE);
appFreeCssmData(&rptext, CSSM_FALSE);
appFreeCssmData(&iv1, CSSM_FALSE);
appFreeCssmData(&iv2, CSSM_FALSE);
cspFreeKey(targs->cspHand, key1);
cspFreeKey(targs->cspHand, key2);
CSSM_FREE(key1);
CSSM_FREE(key2);
return 0;
}
static int iterTest(testArgs *targs)
{
CSSM_KEY_PTR key1;
CSSM_KEY_PTR key2;
CSSM_DATA iv1;
CSSM_DATA iv2;
CSSM_DATA_PTR ivp1;
CSSM_DATA_PTR ivp2;
if(targs->useInitVector) {
if(targs->genInitVector) {
ivp1 = &iv1;
ivp2 = &iv2;
}
else {
staticIv.Length = targs->ivSize;
ivp1 = ivp2 = &staticIv;
}
}
else {
ivp1 = ivp2 = NULL;
}
iv1.Data = NULL;
iv1.Length = 0;
iv2.Data = NULL;
iv2.Length = 0;
key1 = cspDeriveKey(targs->cspHand,
targs->deriveAlg,
targs->keyAlg,
KEY_LABEL1,
KEY_LABEL_LEN,
CSSM_KEYUSE_ENCRYPT,
targs->keySizeInBits,
targs->useRefKey,
targs->password,
targs->salt,
targs->iterCount,
&iv1);
if(key1 == NULL) {
return testError(targs->quiet);
}
key2 = cspDeriveKey(targs->cspHand,
targs->deriveAlg,
targs->keyAlg,
KEY_LABEL2,
KEY_LABEL_LEN,
CSSM_KEYUSE_ENCRYPT,
targs->keySizeInBits,
targs->useRefKey,
targs->password,
targs->salt,
targs->iterCount + 1, &iv2);
if(key2 == NULL) {
return testError(targs->quiet);
}
if(testCommon(targs->cspHand,
"iterTest",
targs->encrAlg,
targs->encrMode,
targs->encrPad,
targs->effectiveKeySizeInBits,
targs->ptext,
key1,
ivp1,
key2,
ivp2,
targs->quiet)) {
return 1;
}
appFreeCssmData(&iv1, CSSM_FALSE);
appFreeCssmData(&iv2, CSSM_FALSE);
cspFreeKey(targs->cspHand, key1);
cspFreeKey(targs->cspHand, key2);
CSSM_FREE(key1);
CSSM_FREE(key2);
return 0;
}
static int passwordTest(testArgs *targs)
{
CSSM_KEY_PTR key1;
CSSM_KEY_PTR key2;
CSSM_DATA iv1;
CSSM_DATA iv2;
CSSM_DATA_PTR ivp1;
CSSM_DATA_PTR ivp2;
uint32 mungeDex;
uint32 mungeBits;
if(targs->useInitVector) {
if(targs->genInitVector) {
ivp1 = &iv1;
ivp2 = &iv2;
}
else {
staticIv.Length = targs->ivSize;
ivp1 = ivp2 = &staticIv;
}
}
else {
ivp1 = ivp2 = NULL;
}
iv1.Data = NULL;
iv1.Length = 0;
iv2.Data = NULL;
iv2.Length = 0;
key1 = cspDeriveKey(targs->cspHand,
targs->deriveAlg,
targs->keyAlg,
KEY_LABEL1,
KEY_LABEL_LEN,
CSSM_KEYUSE_ENCRYPT,
targs->keySizeInBits,
targs->useRefKey,
targs->password,
targs->salt,
targs->iterCount,
&iv1);
if(key1 == NULL) {
return testError(targs->quiet);
}
mungeDex = genRand(0, targs->password->Length - 1);
mungeBits = randBit();
targs->password->Data[mungeDex] ^= mungeBits;
key2 = cspDeriveKey(targs->cspHand,
targs->deriveAlg,
targs->keyAlg,
KEY_LABEL2,
KEY_LABEL_LEN,
CSSM_KEYUSE_ENCRYPT,
targs->keySizeInBits,
targs->useRefKey,
targs->password, targs->salt,
targs->iterCount,
&iv2);
if(key2 == NULL) {
return testError(targs->quiet);
}
if(testCommon(targs->cspHand,
"passwordTest",
targs->encrAlg,
targs->encrMode,
targs->encrPad,
targs->effectiveKeySizeInBits,
targs->ptext,
key1,
ivp1,
key2,
ivp2,
targs->quiet)) {
return 1;
}
targs->password->Data[mungeDex] ^= mungeBits;
appFreeCssmData(&iv1, CSSM_FALSE);
appFreeCssmData(&iv2, CSSM_FALSE);
cspFreeKey(targs->cspHand, key1);
cspFreeKey(targs->cspHand, key2);
CSSM_FREE(key1);
CSSM_FREE(key2);
return 0;
}
static int saltTest(testArgs *targs)
{
CSSM_KEY_PTR key1;
CSSM_KEY_PTR key2;
CSSM_DATA iv1;
CSSM_DATA iv2;
CSSM_DATA_PTR ivp1;
CSSM_DATA_PTR ivp2;
uint32 mungeDex;
uint32 mungeBits;
if(targs->useInitVector) {
if(targs->genInitVector) {
ivp1 = &iv1;
ivp2 = &iv2;
}
else {
staticIv.Length = targs->ivSize;
ivp1 = ivp2 = &staticIv;
}
}
else {
ivp1 = ivp2 = NULL;
}
iv1.Data = NULL;
iv1.Length = 0;
iv2.Data = NULL;
iv2.Length = 0;
key1 = cspDeriveKey(targs->cspHand,
targs->deriveAlg,
targs->keyAlg,
KEY_LABEL1,
KEY_LABEL_LEN,
CSSM_KEYUSE_ENCRYPT,
targs->keySizeInBits,
targs->useRefKey,
targs->password,
targs->salt,
targs->iterCount,
&iv1);
if(key1 == NULL) {
return testError(targs->quiet);
}
mungeDex = genRand(0, targs->salt->Length - 1);
mungeBits = randBit();
targs->salt->Data[mungeDex] ^= mungeBits;
key2 = cspDeriveKey(targs->cspHand,
targs->deriveAlg,
targs->keyAlg,
KEY_LABEL2,
KEY_LABEL_LEN,
CSSM_KEYUSE_ENCRYPT,
targs->keySizeInBits,
targs->useRefKey,
targs->password,
targs->salt, targs->iterCount,
&iv2);
if(key2 == NULL) {
return testError(targs->quiet);
}
if(testCommon(targs->cspHand,
"saltTest",
targs->encrAlg,
targs->encrMode,
targs->encrPad,
targs->effectiveKeySizeInBits,
targs->ptext,
key1,
ivp1,
key2,
ivp2,
targs->quiet)) {
return 1;
}
targs->salt->Data[mungeDex] ^= mungeBits;
appFreeCssmData(&iv1, CSSM_FALSE);
appFreeCssmData(&iv2, CSSM_FALSE);
cspFreeKey(targs->cspHand, key1);
cspFreeKey(targs->cspHand, key2);
CSSM_FREE(key1);
CSSM_FREE(key2);
return 0;
}
static int initVectTest(testArgs *targs)
{
CSSM_KEY_PTR key1;
CSSM_DATA iv1;
CSSM_DATA iv2;
uint32 mungeDex;
uint32 mungeBits;
if(targs->genInitVector) {
iv1.Data = NULL;
iv1.Length = 0;
}
else {
iv1 = staticIv;
}
key1 = cspDeriveKey(targs->cspHand,
targs->deriveAlg,
targs->keyAlg,
KEY_LABEL1,
KEY_LABEL_LEN,
CSSM_KEYUSE_ENCRYPT,
targs->keySizeInBits,
targs->useRefKey,
targs->password,
targs->salt,
targs->iterCount,
&iv1);
if(key1 == NULL) {
return testError(targs->quiet);
}
iv2.Data = (uint8 *)CSSM_MALLOC(iv1.Length);
iv2.Length = iv1.Length;
memmove(iv2.Data, iv1.Data, iv1.Length);
mungeDex = genRand(0, iv1.Length - 1);
mungeBits = randBit();
iv2.Data[mungeDex] ^= mungeBits;
if(testCommon(targs->cspHand,
"initVectTest",
targs->encrAlg,
targs->encrMode,
targs->encrPad,
targs->effectiveKeySizeInBits,
targs->ptext,
key1,
&iv1,
key1,
&iv2, targs->quiet)) {
return 1;
}
if(targs->genInitVector) {
appFreeCssmData(&iv1, CSSM_FALSE);
}
appFreeCssmData(&iv2, CSSM_FALSE);
cspFreeKey(targs->cspHand, key1);
CSSM_FREE(key1);
return 0;
}
#if 0
static int deriveAlgTest(testArgs *targs)
{
CSSM_KEY_PTR key1;
CSSM_KEY_PTR key2;
CSSM_DATA iv1;
CSSM_DATA iv2;
CSSM_DATA_PTR ivp1;
CSSM_DATA_PTR ivp2;
uint32 mungeAlg;
if(targs->useInitVector) {
if(targs->genInitVector) {
ivp1 = &iv1;
ivp2 = &iv2;
}
else {
staticIv.Length = targs->ivSize;
ivp1 = ivp2 = &staticIv;
}
}
else {
ivp1 = ivp2 = NULL;
}
iv1.Data = NULL;
iv1.Length = 0;
iv2.Data = NULL;
iv2.Length = 0;
key1 = cspDeriveKey(targs->cspHand,
targs->deriveAlg,
targs->keyAlg,
KEY_LABEL1,
KEY_LABEL_LEN,
CSSM_KEYUSE_ENCRYPT,
targs->keySizeInBits,
targs->useRefKey,
targs->password,
targs->salt,
targs->iterCount,
&iv1);
if(key1 == NULL) {
return testError(quiet);
}
switch(targs->deriveAlg) {
case CSSM_ALGID_MD5_PBE:
mungeAlg = CSSM_ALGID_MD2_PBE;
break;
case CSSM_ALGID_MD2_PBE:
mungeAlg = CSSM_ALGID_SHA1_PBE;
break;
case CSSM_ALGID_SHA1_PBE:
mungeAlg = CSSM_ALGID_SHA1_PBE_PKCS12;
break;
case CSSM_ALGID_SHA1_PBE_PKCS12:
mungeAlg = CSSM_ALGID_MD5_PBE;
break;
default:
printf("BRRRZZZT! Update deriveAlgTest()!\n");
return testError(quiet);
}
key2 = cspDeriveKey(targs->cspHand,
mungeAlg, targs->keyAlg,
KEY_LABEL2,
KEY_LABEL_LEN,
CSSM_KEYUSE_ENCRYPT,
targs->keySizeInBits,
targs->useRefKey,
targs->password, targs->salt,
targs->iterCount,
&iv2);
if(key2 == NULL) {
return testError(quiet);
}
if(testCommon(targs->cspHand,
"deriveAlgTest",
targs->encrAlg,
targs->encrMode,
targs->encrPad,
targs->effectiveKeySizeInBits,
targs->ptext,
key1,
ivp1,
key2,
ivp2,
targs->quiet)) {
return 1;
}
appFreeCssmData(&iv1, CSSM_FALSE);
appFreeCssmData(&iv2, CSSM_FALSE);
cspFreeKey(targs->cspHand, key1);
cspFreeKey(targs->cspHand, key2);
CSSM_FREE(key1);
CSSM_FREE(key2);
return 0;
}
#endif
int main(int argc, char **argv)
{
int arg;
char *argp;
unsigned loop;
CSSM_DATA ptext;
testArgs targs;
CSSM_DATA pwd;
CSSM_DATA salt;
privAlg pbeAlg;
privAlg encrAlg;
privAlg lastEncrAlg;
int rtn = 0;
CSSM_BOOL fooBool;
CSSM_BOOL refKeysOnly = CSSM_FALSE;
int i;
unsigned loops = LOOPS_DEF;
CSSM_BOOL quiet = CSSM_FALSE;
CSSM_BOOL doPause = CSSM_FALSE;
CSSM_BOOL doExport = CSSM_FALSE;
CSSM_BOOL repeatOnly = CSSM_FALSE;
CSSM_BOOL bareCsp = CSSM_TRUE;
CSSM_BOOL zeroLenPassword = CSSM_FALSE;
#if macintosh
argc = ccommand(&argv);
#endif
for(arg=1; arg<argc; arg++) {
argp = argv[arg];
switch(argp[0]) {
case 'l':
loops = atoi(&argp[2]);
break;
case 'q':
quiet = CSSM_TRUE;
break;
case 'D':
bareCsp = CSSM_FALSE;
#if CSPDL_ALL_KEYS_ARE_REF
refKeysOnly = CSSM_TRUE;
#endif
break;
case 'p':
doPause = CSSM_TRUE;
break;
case 'e':
doExport = CSSM_TRUE;
break;
case 'r':
repeatOnly = CSSM_TRUE;
break;
case 'z':
zeroLenPassword = CSSM_TRUE;
break;
case 'h':
default:
usage(argv);
}
}
pwd.Data = (uint8 *)CSSM_MALLOC(MAX_PASSWORD_SIZE);
ptext.Data = (uint8 *)CSSM_MALLOC(MAX_PTEXT_SIZE);
salt.Data = (uint8 *)CSSM_MALLOC(MAX_SALT_SIZE);
printf("Starting pbeTest; args: ");
for(i=1; i<argc; i++) {
printf("%s ", argv[i]);
}
printf("\n");
targs.cspHand = cspDlDbStartup(bareCsp, NULL);
if(targs.cspHand == 0) {
exit(1);
}
targs.ptext = &ptext;
targs.password = &pwd;
targs.salt = &salt;
targs.quiet = quiet;
if(doExport) {
lastEncrAlg = ENCR_ALG_LAST_EXPORT;
}
else {
lastEncrAlg = ENCR_ALG_LAST;
}
for(loop=1; ; loop++) {
if(!quiet) {
printf("...loop %d\n", loop);
}
simpleGenData(&ptext, MIN_PTEXT_SIZE, MAX_PTEXT_SIZE);
if(zeroLenPassword) {
pwd.Length = 0; }
else {
simpleGenData(&pwd, APPLE_PBE_MIN_PASSWORD, MAX_PASSWORD_SIZE);
}
simpleGenData(&salt, APPLE_PBE_MIN_SALT, MAX_SALT_SIZE);
targs.iterCount = genRand(MIN_ITER_COUNT, MAX_ITER_COUNT);
if(refKeysOnly) {
targs.useRefKey = CSSM_TRUE;
}
else {
targs.useRefKey = (loop & 1) ? CSSM_FALSE : CSSM_TRUE;
}
for(encrAlg=ENCR_ALG_FIRST; encrAlg<=lastEncrAlg; encrAlg++) {
algInfo(encrAlg,
&targs.keyAlg,
&targs.encrAlg,
&targs.encrMode,
&targs.encrPad,
&targs.useInitVector,
&targs.ivSize,
&fooBool, &targs.keyAlgStr);
targs.effectiveKeySizeInBits = randKeySizeBits(targs.keyAlg, OT_Encrypt);
targs.keySizeInBits = (targs.effectiveKeySizeInBits + 7) & ~7;
if(targs.keySizeInBits == targs.effectiveKeySizeInBits) {
targs.effectiveKeySizeInBits = 0;
}
if(!quiet) {
printf(" ...Encrypt alg %s keySizeInBits %u effectKeySize %u\n",
targs.keyAlgStr, (unsigned)targs.keySizeInBits,
(unsigned)targs.effectiveKeySizeInBits);
}
for(pbeAlg=PBE_ALG_FIRST; pbeAlg<=PBE_ALG_LAST; pbeAlg++) {
uint32 foo;
algInfo(pbeAlg,
&targs.deriveAlg,
&foo, &foo, &foo,
&fooBool, &foo, &targs.genInitVector,
&targs.deriveAlgStr);
if(!quiet) {
printf(" ...PBE alg %s\n", targs.deriveAlgStr);
}
if(repeatTest(&targs)) {
rtn = 1;
goto testDone;
}
if(repeatOnly) {
continue;
}
if(iterTest(&targs)) {
rtn = 1;
goto testDone;
}
#if 0
if(deriveAlgTest(&targs)) {
rtn = 1;
goto testDone;
}
#endif
if(!zeroLenPassword) {
if(passwordTest(&targs)) {
rtn = 1;
goto testDone;
}
}
if(saltTest(&targs)) {
rtn = 1;
goto testDone;
}
if(targs.useInitVector) {
if(initVectTest(&targs)) {
rtn = 1;
goto testDone;
}
}
}
}
if(doPause) {
if(testError(quiet)) {
break;
}
}
if(loops && (loop == loops)) {
break;
}
}
testDone:
CSSM_ModuleDetach(targs.cspHand);
if(!quiet && (rtn == 0)) {
printf("%s test complete\n", argv[0]);
}
return rtn;
}