#include <Security/Security.h>
#include <security_cdsa_utilities/cssmdates.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "cspwrap.h"
#include "common.h"
#include <CoreFoundation/CoreFoundation.h>
typedef unsigned privAlg;
enum {
ALG_ASC = 1,
ALG_DES,
ALG_AES,
ALG_BFISH,
ALG_RSA,
};
#define SYM_FIRST ALG_ASC
#define SYM_LAST ALG_BFISH
#define ASYM_FIRST ALG_RSA
#define ASYM_LAST ALG_RSA
#define KD_DB_NAME "keyDate.db"
#define KD_KEY_LABEL "keyStoreKey"
static CSSM_DATA keyLabelData = {12, (uint8 *)KD_KEY_LABEL};
static void usage(char **argv)
{
printf("usage: %s [options]\n", argv[0]);
printf(" Options:\n");
printf(" s(ymmetric only)\n");
printf(" a(symmetric only)\n");
printf(" t (key store only)\n");
printf(" D (CSPDL; default is bare CSP)\n");
printf(" q(uiet)\n");
printf(" h(elp)\n");
exit(1);
}
#pragma mark -
#pragma mark --- Utilities ---
static void setDate(
CSSM_DATE &cdate,
int deltaDays)
{
CFAbsoluteTime cfTime = CFAbsoluteTimeGetCurrent();
float fdelta = 60.0 * 60.0 * 24.0 * deltaDays;
cfTime += fdelta;
CFDateRef cfDate = CFDateCreate(NULL, cfTime);
CssmUniformDate cud(cfDate);
CFRelease(cfDate);
cdate = cud;
}
static int compareDates(
const CSSM_DATE *refDate, const CSSM_DATE *keyDate,
const char *op,
CSSM_BOOL quiet)
{
if(refDate == NULL) {
bool isZero = true;
unsigned char *cp = (unsigned char *)keyDate;
for(unsigned i=0; i<sizeof(CSSM_DATE); i++) {
if(*cp++ != 0) {
isZero = false;
break;
}
}
if(!isZero) {
printf("%s: refDate NULL, non-empty keyDate\n", op);
return testError(quiet);
}
else {
return 0;
}
}
if(memcmp(refDate, keyDate, sizeof(CSSM_DATE))) {
printf("%s: refDate/keyDate MISCOMPARE\n", op);
return testError(quiet);
}
else {
return 0;
}
}
#pragma mark -
#pragma mark -- Key generation ---
static int genSymKey(
CSSM_CSP_HANDLE cspHand,
CSSM_KEY_PTR symKey,
uint32 alg,
const char *keyAlgStr,
uint32 keySizeInBits,
CSSM_KEYATTR_FLAGS keyAttr,
CSSM_KEYUSE keyUsage,
CSSM_BOOL quiet,
bool setStartDate,
int startDeltaDays,
bool setEndDate,
int endDeltaDays,
CSSM_DL_DB_HANDLE *dlDbHand = NULL) {
CSSM_RETURN crtn;
CSSM_CC_HANDLE ccHand;
CSSM_DATE startDate;
CSSM_DATE endDate;
if(setStartDate) {
setDate(startDate, startDeltaDays);
}
if(setEndDate) {
setDate(endDate, endDeltaDays);
}
memset(symKey, 0, sizeof(CSSM_KEY));
crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
alg,
keySizeInBits, NULL, NULL, setStartDate ? &startDate : NULL,
setEndDate ? &endDate : NULL,
NULL, &ccHand);
if(crtn) {
printError("CSSM_CSP_CreateKeyGenContext", crtn);
return testError(quiet);
}
if(dlDbHand) {
crtn = cspAddDlDbToContext(ccHand, dlDbHand->DLHandle,
dlDbHand->DBHandle);
if(crtn) {
return testError(quiet);
}
}
crtn = CSSM_GenerateKey(ccHand,
keyUsage,
keyAttr,
&keyLabelData,
NULL, symKey);
if(crtn) {
printError("CSSM_GenerateKey", crtn);
return testError(quiet);
}
CSSM_DeleteContext(ccHand);
CSSM_KEYHEADER &hdr = symKey->KeyHeader;
CSSM_DATE *cdp = NULL;
if(setStartDate) {
cdp = &startDate;
}
if(compareDates(cdp, &hdr.StartDate, keyAlgStr, quiet)) {
return 1;
}
if(setEndDate) {
cdp = &endDate;
}
else {
cdp = NULL;
}
if(compareDates(cdp, &hdr.EndDate, keyAlgStr, quiet)) {
return 1;
}
return 0;
}
static int genKeyPair(
CSSM_CSP_HANDLE cspHand,
uint32 algorithm,
const char *keyAlgStr,
uint32 keySizeInBits,
CSSM_KEY_PTR pubKey,
CSSM_KEYATTR_FLAGS pubKeyAttr,
CSSM_KEYUSE pubKeyUsage,
CSSM_KEY_PTR privKey,
CSSM_KEYATTR_FLAGS privKeyAttr,
CSSM_KEYUSE privKeyUsage,
CSSM_BOOL quiet,
bool setStartDate,
int startDeltaDays,
bool setEndDate,
int endDeltaDays,
CSSM_DL_DB_HANDLE *dlDbHand = NULL) {
CSSM_RETURN crtn;
CSSM_CC_HANDLE ccHand;
CSSM_DATE startDate;
CSSM_DATE endDate;
if(setStartDate) {
setDate(startDate, startDeltaDays);
}
if(setEndDate) {
setDate(endDate, endDeltaDays);
}
memset(pubKey, 0, sizeof(CSSM_KEY));
memset(privKey, 0, sizeof(CSSM_KEY));
crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
algorithm,
keySizeInBits,
NULL, NULL, setStartDate ? &startDate : NULL,
setEndDate ? &endDate : NULL,
NULL, &ccHand);
if(crtn) {
printError("CSSM_CSP_CreateKeyGenContext", crtn);
return testError(quiet);
}
if(dlDbHand) {
crtn = cspAddDlDbToContext(ccHand, dlDbHand->DLHandle,
dlDbHand->DBHandle);
if(crtn) {
return testError(quiet);
}
}
crtn = CSSM_GenerateKeyPair(ccHand,
pubKeyUsage,
pubKeyAttr,
&keyLabelData,
pubKey,
privKeyUsage,
privKeyAttr,
&keyLabelData, NULL, privKey);
if(crtn) {
printError("CSSM_GenerateKeyPair", crtn);
return testError(quiet);
}
CSSM_DeleteContext(ccHand);
CSSM_KEYHEADER &pubHdr = pubKey->KeyHeader;
CSSM_KEYHEADER &privHdr = privKey->KeyHeader;
CSSM_DATE *cdp = NULL;
if(setStartDate) {
cdp = &startDate;
}
if(compareDates(cdp, &pubHdr.StartDate, keyAlgStr, quiet)) {
return 1;
}
if(compareDates(cdp, &privHdr.StartDate, keyAlgStr, quiet)) {
return 1;
}
if(setEndDate) {
cdp = &endDate;
}
else {
cdp = NULL;
}
if(compareDates(cdp, &pubHdr.EndDate, keyAlgStr, quiet)) {
return 1;
}
if(compareDates(cdp, &privHdr.EndDate, keyAlgStr, quiet)) {
return 1;
}
return 0;
}
void privAlgToCssm(
privAlg palg,
CSSM_ALGORITHMS *keyAlg,
CSSM_ALGORITHMS *signAlg, CSSM_ALGORITHMS *encrAlg, CSSM_ENCRYPT_MODE *encrMode,
CSSM_PADDING *encrPad,
uint32 *keySizeInBits,
const char **keyAlgStr)
{
*signAlg = *encrAlg = CSSM_ALGID_NONE; *encrMode = CSSM_ALGMODE_NONE;
*encrPad = CSSM_PADDING_NONE;
switch(palg) {
case ALG_ASC:
*encrAlg = *keyAlg = CSSM_ALGID_ASC;
*keySizeInBits = CSP_ASC_KEY_SIZE_DEFAULT;
*keyAlgStr = "ASC";
break;
case ALG_DES:
*encrAlg = *keyAlg = CSSM_ALGID_DES;
*keySizeInBits = CSP_DES_KEY_SIZE_DEFAULT;
*keyAlgStr = "DES";
*encrMode = CSSM_ALGMODE_CBCPadIV8;
*encrPad = CSSM_PADDING_PKCS7;
break;
case ALG_AES:
*encrAlg = *keyAlg = CSSM_ALGID_AES;
*keySizeInBits = CSP_AES_KEY_SIZE_DEFAULT;
*keyAlgStr = "AES";
*encrMode = CSSM_ALGMODE_CBCPadIV8;
*encrPad = CSSM_PADDING_PKCS7;
break;
case ALG_BFISH:
*encrAlg = *keyAlg = CSSM_ALGID_BLOWFISH;
*keySizeInBits = CSP_BFISH_KEY_SIZE_DEFAULT;
*keyAlgStr = "Blowfish";
*encrMode = CSSM_ALGMODE_CBCPadIV8;
*encrPad = CSSM_PADDING_PKCS7;
break;
case ALG_RSA:
*keyAlg = CSSM_ALGID_RSA;
*encrAlg = CSSM_ALGID_RSA;
*signAlg = CSSM_ALGID_SHA1WithRSA;
*keySizeInBits = 512;
*keyAlgStr = "RSA";
*encrPad = CSSM_PADDING_PKCS1;
break;
default:
printf("***BRRZAP! privAlgToCssm needs work\n");
exit(1);
}
return;
}
#pragma mark -
#pragma mark --- basic ops to detect INVALID_KEY_{START,END}_DATE ---
#define PTEXT_SIZE 64
#define IV_SIZE 16
static int doEncrypt(
CSSM_CSP_HANDLE cspHand,
const char *algStr,
CSSM_KEY_PTR key, CSSM_ALGORITHMS encrAlg,
CSSM_ENCRYPT_MODE encrMode,
CSSM_PADDING encrPad,
CSSM_RETURN expRtn, CSSM_BOOL quiet)
{
uint8 ptextData[PTEXT_SIZE];
CSSM_DATA ptext = {PTEXT_SIZE, ptextData};
uint8 someIvData[IV_SIZE];
CSSM_DATA someIv = {IV_SIZE, someIvData};
simpleGenData(&ptext, PTEXT_SIZE, PTEXT_SIZE);
simpleGenData(&someIv, IV_SIZE, IV_SIZE);
CSSM_CC_HANDLE cryptHand = 0;
CSSM_RETURN crtn;
CSSM_ACCESS_CREDENTIALS creds;
memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
if(key->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY) {
crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
encrAlg,
encrMode,
NULL, key,
&someIv,
encrPad,
NULL, &cryptHand);
if(crtn) {
printError("CSSM_CSP_CreateSymmetricContext", crtn);
return testError(quiet);
}
}
else if(key->KeyHeader.KeyClass == CSSM_KEYCLASS_PUBLIC_KEY) {
crtn = CSSM_CSP_CreateAsymmetricContext(cspHand,
encrAlg,
&creds, key,
encrPad,
&cryptHand);
if(crtn) {
printError("CSSM_CSP_CreateAsymmetricContext", crtn);
return testError(quiet);
}
}
else {
printf("***BRRZAP! Only encrypt with session and public keys\n");
exit(1);
}
CSSM_DATA ctext = {0, NULL};
CSSM_DATA remData = {0, NULL};
CSSM_SIZE bEncr;
int irtn = 0;
crtn = CSSM_EncryptData(cryptHand,
&ptext,
1,
&ctext,
1,
&bEncr,
&remData);
if(crtn != expRtn) {
if(expRtn == CSSM_OK) {
printError("CSSM_EncryptData", crtn);
printf("Unexpected error encrypting with %s\n", algStr);
}
else {
printf("***Encrypt with %s: expected %s, got %s.\n",
algStr, cssmErrToStr(expRtn),
cssmErrToStr(crtn));
}
irtn = testError(quiet);
}
appFreeCssmData(&ctext, CSSM_FALSE);
appFreeCssmData(&remData, CSSM_FALSE);
CSSM_DeleteContext(cryptHand);
return irtn;
}
typedef enum {
DR_BadStartDate, DR_BadEndDate, DR_BadData } DecrResult;
#define CTEXT_SIZE (PTEXT_SIZE )
static int doDecrypt(
CSSM_CSP_HANDLE cspHand,
const char *algStr,
CSSM_KEY_PTR key, CSSM_ALGORITHMS encrAlg,
CSSM_ENCRYPT_MODE encrMode,
CSSM_PADDING encrPad,
DecrResult expResult,
CSSM_BOOL quiet)
{
uint8 ctextData[CTEXT_SIZE];
CSSM_DATA ctext = {CTEXT_SIZE, ctextData};
uint8 someIvData[IV_SIZE];
CSSM_DATA someIv = {IV_SIZE, someIvData};
memset(ctextData, 0, CTEXT_SIZE); memset(someIvData, 0, IV_SIZE);
CSSM_CC_HANDLE cryptHand = 0;
CSSM_RETURN crtn;
CSSM_ACCESS_CREDENTIALS creds;
memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
if(key->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY) {
crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
encrAlg,
encrMode,
NULL, key,
&someIv,
encrPad,
NULL, &cryptHand);
if(crtn) {
printError("CSSM_CSP_CreateSymmetricContext", crtn);
return testError(quiet);
}
}
else if(key->KeyHeader.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY) {
crtn = CSSM_CSP_CreateAsymmetricContext(cspHand,
encrAlg,
&creds, key,
encrPad,
&cryptHand);
if(crtn) {
printError("CSSM_CSP_CreateAsymmetricContext", crtn);
return testError(quiet);
}
}
else {
printf("***BRRZAP! Only decrypt with session and private"
" keys\n");
exit(1);
}
CSSM_DATA ptext = {0, NULL};
CSSM_DATA remData = {0, NULL};
CSSM_SIZE bDecr;
int irtn = 0;
crtn = CSSM_DecryptData(cryptHand,
&ctext,
1,
&ptext,
1,
&bDecr,
&remData);
switch(expResult) {
case DR_BadStartDate:
if(crtn != CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE) {
printf("***Decrypt with %s: expected INVALID_KEY_START_DATE, "
"got %s.\n", algStr, cssmErrToStr(crtn));
irtn = testError(quiet);
}
break;
case DR_BadEndDate:
if(crtn != CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE) {
printf("***Decrypt with %s: expected INVALID_KEY_END_DATE, "
"got %s.\n", algStr, cssmErrToStr(crtn));
irtn = testError(quiet);
}
break;
case DR_BadData:
switch(crtn) {
case CSSM_OK: case CSSMERR_CSP_INVALID_DATA: case CSSMERR_CSP_INTERNAL_ERROR: break;
default:
printf("***Decrypt with %s: expected INVALID_DATA or OK, "
"got %s.\n",
algStr, cssmErrToStr(crtn));
irtn = testError(quiet);
break;
}
break;
}
appFreeCssmData(&ptext, CSSM_FALSE);
appFreeCssmData(&remData, CSSM_FALSE);
CSSM_DeleteContext(cryptHand);
return irtn;
}
static int doSign(
CSSM_CSP_HANDLE cspHand,
const char *algStr,
CSSM_KEY_PTR key, CSSM_ALGORITHMS sigAlg,
CSSM_RETURN expRtn, CSSM_BOOL quiet)
{
uint8 ptextData[PTEXT_SIZE];
CSSM_DATA ptext = {PTEXT_SIZE, ptextData};
CSSM_DATA sig = {0, NULL};
simpleGenData(&ptext, PTEXT_SIZE, PTEXT_SIZE);
CSSM_CC_HANDLE cryptHand = 0;
CSSM_RETURN crtn;
crtn = CSSM_CSP_CreateSignatureContext(cspHand,
sigAlg,
NULL, key,
&cryptHand);
if(crtn) {
printError("CSSM_CSP_CreateSignatureContext (1)", crtn);
return testError(quiet);
}
int irtn = 0;
crtn = CSSM_SignData(cryptHand,
&ptext,
1,
CSSM_ALGID_NONE,
&sig);
if(crtn != expRtn) {
if(expRtn == CSSM_OK) {
printError("CSSM_SignData", crtn);
printf("Unexpected error signing with %s\n", algStr);
}
else {
printf("***Sign with %s: expected %s, got %s.\n",
algStr, cssmErrToStr(expRtn),
cssmErrToStr(crtn));
}
irtn = testError(quiet);
}
appFreeCssmData(&sig, CSSM_FALSE);
CSSM_DeleteContext(cryptHand);
return irtn;
}
#define KD_VERIFY_FAIL_ERR CSSMERR_CSP_VERIFY_FAILED
static int doVerify(
CSSM_CSP_HANDLE cspHand,
const char *algStr,
CSSM_KEY_PTR key, CSSM_ALGORITHMS sigAlg,
CSSM_RETURN expRtn, CSSM_BOOL quiet)
{
uint8 ptextData[PTEXT_SIZE];
CSSM_DATA ptext = {PTEXT_SIZE, ptextData};
uint8 sigData[PTEXT_SIZE];
CSSM_DATA sig = {PTEXT_SIZE, sigData};
simpleGenData(&ptext, PTEXT_SIZE, PTEXT_SIZE);
memset(sigData, 0, PTEXT_SIZE);
CSSM_CC_HANDLE cryptHand = 0;
CSSM_RETURN crtn;
crtn = CSSM_CSP_CreateSignatureContext(cspHand,
sigAlg,
NULL, key,
&cryptHand);
if(crtn) {
printError("CSSM_CSP_CreateSignatureContext (2)", crtn);
return testError(quiet);
}
int irtn = 0;
crtn = CSSM_VerifyData(cryptHand,
&ptext,
1,
CSSM_ALGID_NONE,
&sig);
if(crtn != expRtn) {
if(expRtn == CSSM_OK) {
printError("CSSM_VerifyData", crtn);
printf("Unexpected error verifying with %s\n", algStr);
}
else {
printf("***Verify with %s: expected %s, got %s.\n",
algStr, cssmErrToStr(expRtn),
cssmErrToStr(crtn));
}
irtn = testError(quiet);
}
CSSM_DeleteContext(cryptHand);
return irtn;
}
#pragma mark -
#pragma mark -- test suites ---
int doSymTests(
CSSM_CSP_HANDLE cspHand,
privAlg palg,
CSSM_BOOL refKeys,
CSSM_BOOL quiet)
{
CSSM_ALGORITHMS keyAlg;
CSSM_ALGORITHMS signAlg;
CSSM_ALGORITHMS encrAlg;
CSSM_ENCRYPT_MODE encrMode;
CSSM_PADDING encrPad;
uint32 keySizeInBits;
const char *keyAlgStr;
privAlgToCssm(palg, &keyAlg, &signAlg, &encrAlg, &encrMode,
&encrPad, &keySizeInBits, &keyAlgStr);
CSSM_KEY symKey;
int irtn;
CSSM_KEYATTR_FLAGS keyAttr;
if(refKeys) {
keyAttr = CSSM_KEYATTR_RETURN_REF;
}
else {
keyAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
}
if(!quiet) {
printf("...testing %s with %s keys\n", keyAlgStr,
refKeys ? "Ref" : "Raw");
printf(" ...verifying empty Dates\n");
}
irtn = genSymKey(cspHand, &symKey, keyAlg, keyAlgStr, keySizeInBits,
keyAttr, CSSM_KEYUSE_ANY, quiet,
CSSM_FALSE, 0, CSSM_FALSE, 0); if(irtn) {
return irtn;
}
irtn = doEncrypt(cspHand, keyAlgStr, &symKey, encrAlg, encrMode,
encrPad, CSSM_OK, quiet);
if(irtn) {
printf("***Failure on encrypting with empty Key Dates\n");
return irtn;
}
irtn = doDecrypt(cspHand, keyAlgStr, &symKey, encrAlg, encrMode,
encrPad, DR_BadData, quiet);
if(irtn) {
printf("***Failure on decrypting with empty Key Dates\n");
return irtn;
}
cspFreeKey(cspHand, &symKey);
if(!quiet) {
printf(" ...verifying Good Dates\n");
}
irtn = genSymKey(cspHand, &symKey, keyAlg, keyAlgStr, keySizeInBits,
keyAttr, CSSM_KEYUSE_ANY, quiet,
CSSM_TRUE, 0, CSSM_TRUE, 1); if(irtn) {
return irtn;
}
irtn = doEncrypt(cspHand, keyAlgStr, &symKey, encrAlg, encrMode,
encrPad, CSSM_OK, quiet);
if(irtn) {
printf("***Failure on encrypting with good Key Dates\n");
return irtn;
}
irtn = doDecrypt(cspHand, keyAlgStr, &symKey, encrAlg, encrMode,
encrPad, DR_BadData, quiet);
if(irtn) {
printf("***Failure on decrypting with good Key Dates\n");
return irtn;
}
cspFreeKey(cspHand, &symKey);
if(!quiet) {
printf(" ...verifying Bad StartDate\n");
}
irtn = genSymKey(cspHand, &symKey, keyAlg, keyAlgStr, keySizeInBits,
keyAttr, CSSM_KEYUSE_ANY, quiet,
CSSM_TRUE, 1, CSSM_TRUE, 1); if(irtn) {
return irtn;
}
irtn = doEncrypt(cspHand, keyAlgStr, &symKey, encrAlg, encrMode,
encrPad, CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE, quiet);
if(irtn) {
printf("***Failure on encrypting with bad StartDate\n");
return irtn;
}
irtn = doDecrypt(cspHand, keyAlgStr, &symKey, encrAlg, encrMode,
encrPad, DR_BadStartDate, quiet);
if(irtn) {
printf("***Failure on decrypting with bad StartDate\n");
return irtn;
}
cspFreeKey(cspHand, &symKey);
if(!quiet) {
printf(" ...verifying Bad EndDate\n");
}
irtn = genSymKey(cspHand, &symKey, keyAlg, keyAlgStr, keySizeInBits,
keyAttr, CSSM_KEYUSE_ANY, quiet,
CSSM_TRUE, 0, CSSM_TRUE, -1); if(irtn) {
return irtn;
}
irtn = doEncrypt(cspHand, keyAlgStr, &symKey, encrAlg, encrMode,
encrPad, CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE, quiet);
if(irtn) {
printf("***Failure on encrypting with bad StartDate\n");
return irtn;
}
irtn = doDecrypt(cspHand, keyAlgStr, &symKey, encrAlg, encrMode,
encrPad, DR_BadEndDate, quiet);
if(irtn) {
printf("***Failure on decrypting with bad EndDate\n");
return irtn;
}
cspFreeKey(cspHand, &symKey);
return 0;
}
int doAsymTests(
CSSM_CSP_HANDLE cspHand,
privAlg palg,
CSSM_BOOL refKeys,
CSSM_BOOL quiet)
{
CSSM_ALGORITHMS keyAlg;
CSSM_ALGORITHMS sigAlg;
CSSM_ALGORITHMS encrAlg;
CSSM_ENCRYPT_MODE encrMode;
CSSM_PADDING encrPad;
uint32 keySizeInBits;
const char *keyAlgStr;
privAlgToCssm(palg, &keyAlg, &sigAlg, &encrAlg, &encrMode,
&encrPad, &keySizeInBits, &keyAlgStr);
CSSM_KEY pubKey;
CSSM_KEY privKey;
int irtn;
CSSM_KEYATTR_FLAGS pubKeyAttr = CSSM_KEYATTR_EXTRACTABLE;
CSSM_KEYATTR_FLAGS privKeyAttr = CSSM_KEYATTR_EXTRACTABLE;
if(refKeys) {
pubKeyAttr |= CSSM_KEYATTR_RETURN_REF;
privKeyAttr |= CSSM_KEYATTR_RETURN_REF;
}
else {
pubKeyAttr |= CSSM_KEYATTR_RETURN_DATA;
privKeyAttr |= CSSM_KEYATTR_RETURN_DATA;
}
if(!quiet) {
printf("...testing %s with %s keys\n", keyAlgStr,
refKeys ? "Ref" : "Raw");
printf(" ...verifying empty Dates\n");
}
irtn = genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits,
&pubKey, pubKeyAttr, CSSM_KEYUSE_ANY,
&privKey, privKeyAttr, CSSM_KEYUSE_ANY,
quiet,
CSSM_FALSE, 0, CSSM_FALSE, 0); if(irtn) {
return irtn;
}
irtn = doEncrypt(cspHand, keyAlgStr, &pubKey, encrAlg, encrMode,
encrPad, CSSM_OK, quiet);
if(irtn) {
printf("***Failure on encrypting with empty Key Dates\n");
return irtn;
}
irtn = doDecrypt(cspHand, keyAlgStr, &privKey, encrAlg, encrMode,
encrPad, DR_BadData, quiet);
if(irtn) {
printf("***Failure on decrypting with empty Key Dates\n");
return irtn;
}
irtn = doSign(cspHand, keyAlgStr, &privKey, sigAlg,
CSSM_OK, quiet);
if(irtn) {
printf("***Failure on signing with empty Key Dates\n");
return irtn;
}
irtn = doVerify(cspHand, keyAlgStr, &pubKey, sigAlg,
KD_VERIFY_FAIL_ERR, quiet);
if(irtn) {
printf("***Failure on verifying with empty Key Dates\n");
return irtn;
}
cspFreeKey(cspHand, &pubKey);
cspFreeKey(cspHand, &privKey);
if(!quiet) {
printf(" ...verifying Good Dates\n");
}
irtn = genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits,
&pubKey, pubKeyAttr, CSSM_KEYUSE_ANY,
&privKey, privKeyAttr, CSSM_KEYUSE_ANY,
quiet,
CSSM_TRUE, 0, CSSM_TRUE, 1); if(irtn) {
return irtn;
}
irtn = doEncrypt(cspHand, keyAlgStr, &pubKey, encrAlg, encrMode,
encrPad, CSSM_OK, quiet);
if(irtn) {
printf("***Failure on encrypting with good Key Dates\n");
return irtn;
}
irtn = doDecrypt(cspHand, keyAlgStr, &privKey, encrAlg, encrMode,
encrPad, DR_BadData, quiet);
if(irtn) {
printf("***Failure on decrypting with Good Key Dates\n");
return irtn;
}
irtn = doSign(cspHand, keyAlgStr, &privKey, sigAlg,
CSSM_OK, quiet);
if(irtn) {
printf("***Failure on signing with Good Key Dates\n");
return irtn;
}
irtn = doVerify(cspHand, keyAlgStr, &pubKey, sigAlg,
KD_VERIFY_FAIL_ERR, quiet);
if(irtn) {
printf("***Failure on verifying with Good Key Dates\n");
return irtn;
}
cspFreeKey(cspHand, &pubKey);
cspFreeKey(cspHand, &privKey);
if(!quiet) {
printf(" ...verifying Bad StartDate\n");
}
irtn = genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits,
&pubKey, pubKeyAttr, CSSM_KEYUSE_ANY,
&privKey, privKeyAttr, CSSM_KEYUSE_ANY,
quiet,
CSSM_TRUE, 1, CSSM_TRUE, 1); if(irtn) {
return irtn;
}
irtn = doEncrypt(cspHand, keyAlgStr, &pubKey, encrAlg, encrMode,
encrPad, CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE, quiet);
if(irtn) {
printf("***Failure on encrypting with bad StartDate\n");
return irtn;
}
irtn = doDecrypt(cspHand, keyAlgStr, &privKey, encrAlg, encrMode,
encrPad, DR_BadStartDate, quiet);
if(irtn) {
printf("***Failure on decrypting with bad StartDate\n");
return irtn;
}
irtn = doSign(cspHand, keyAlgStr, &privKey, sigAlg,
CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE, quiet);
if(irtn) {
printf("***Failure on signing with bad StartDate\n");
return irtn;
}
irtn = doVerify(cspHand, keyAlgStr, &pubKey, sigAlg,
CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE, quiet);
if(irtn) {
printf("***Failure on verifying with bad StartDate\n");
return irtn;
}
cspFreeKey(cspHand, &pubKey);
cspFreeKey(cspHand, &privKey);
if(!quiet) {
printf(" ...verifying Bad EndDate\n");
}
irtn = genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits,
&pubKey, pubKeyAttr, CSSM_KEYUSE_ANY,
&privKey, privKeyAttr, CSSM_KEYUSE_ANY,
quiet,
CSSM_TRUE, 0, CSSM_TRUE, -1); if(irtn) {
return irtn;
}
irtn = doEncrypt(cspHand, keyAlgStr, &pubKey, encrAlg, encrMode,
encrPad, CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE, quiet);
if(irtn) {
printf("***Failure on encrypting with bad EndDate\n");
return irtn;
}
irtn = doDecrypt(cspHand, keyAlgStr, &privKey, encrAlg, encrMode,
encrPad, DR_BadEndDate, quiet);
if(irtn) {
printf("***Failure on decrypting with bad EndDate\n");
return irtn;
}
irtn = doSign(cspHand, keyAlgStr, &privKey, sigAlg,
CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE, quiet);
if(irtn) {
printf("***Failure on signing with bad EndDate\n");
return irtn;
}
irtn = doVerify(cspHand, keyAlgStr, &pubKey, sigAlg,
CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE, quiet);
if(irtn) {
printf("***Failure on verifying with bad EndDate\n");
return irtn;
}
cspFreeKey(cspHand, &pubKey);
cspFreeKey(cspHand, &privKey);
return 0;
}
static int fetchStoredKey(
CSSM_DL_DB_HANDLE dlDbHand,
CT_KeyType lookupType,
CSSM_KEY_PTR compareKey,
const char *op,
CSSM_BOOL quiet,
CSSM_KEY_PTR *lookupKey) {
CSSM_KEY_PTR lookup = cspLookUpKeyByLabel(dlDbHand.DLHandle,
dlDbHand.DBHandle,
&keyLabelData,
lookupType);
if(lookup == NULL) {
printf("%s: Error looking up key in DB\n", op);
return testError(quiet);
}
if(compareDates(&compareKey->KeyHeader.StartDate,
&lookup->KeyHeader.StartDate,
op, quiet)) {
return 1;
}
*lookupKey = lookup;
return 0;
}
int doStoreTests(
CSSM_CSP_HANDLE cspHand, CSSM_DL_DB_HANDLE dlDbHand,
privAlg palg,
CSSM_BOOL isAsym,
CSSM_BOOL quiet)
{
CSSM_ALGORITHMS keyAlg;
CSSM_ALGORITHMS signAlg;
CSSM_ALGORITHMS encrAlg;
CSSM_ENCRYPT_MODE encrMode;
CSSM_PADDING encrPad;
uint32 keySizeInBits;
const char *keyAlgStr;
privAlgToCssm(palg, &keyAlg, &signAlg, &encrAlg, &encrMode,
&encrPad, &keySizeInBits, &keyAlgStr);
CSSM_KEY symKey;
CSSM_KEY privKey;
CSSM_KEY pubKey;
int irtn;
CSSM_KEY_PTR lookupKey = NULL; CSSM_KEY_PTR compareKey; CT_KeyType lookupType;
CSSM_KEYATTR_FLAGS pubKeyAttr =
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE |
CSSM_KEYATTR_PERMANENT;
CSSM_KEYATTR_FLAGS privKeyAttr =
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT;
if(!quiet) {
printf("...testing %s key storage\n", keyAlgStr);
printf(" ...verifying empty Dates\n");
}
if(isAsym) {
lookupType = CKT_Public;
compareKey = &pubKey;
irtn = genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits,
&pubKey, pubKeyAttr, CSSM_KEYUSE_ANY,
&privKey, privKeyAttr, CSSM_KEYUSE_ANY,
quiet,
CSSM_FALSE, 0, CSSM_FALSE, 0, &dlDbHand);
}
else {
lookupType = CKT_Session;
compareKey = &symKey;
irtn = genSymKey(cspHand, &symKey, keyAlg, keyAlgStr,
keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT,
CSSM_KEYUSE_ANY, quiet,
CSSM_FALSE, 0, CSSM_FALSE, 0, &dlDbHand);
}
if(irtn) {
return irtn;
}
if(fetchStoredKey(dlDbHand, lookupType,
compareKey, "Store key with empty Dates", quiet,
&lookupKey)) {
return 1;
}
irtn = doEncrypt(cspHand, keyAlgStr, lookupKey, encrAlg, encrMode,
encrPad, CSSM_OK, quiet);
if(irtn) {
printf("***Failure on encrypt, lookup with empty Key Dates\n");
return irtn;
}
if(isAsym) {
cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle,
&keyLabelData, &pubKey);
cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle,
&keyLabelData, &privKey);
}
else {
cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle,
&keyLabelData, &symKey);
}
cspFreeKey(cspHand, lookupKey);
if(!quiet) {
printf(" ...verifying Good Dates\n");
}
if(isAsym) {
lookupType = CKT_Public;
compareKey = &pubKey;
irtn = genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits,
&pubKey, pubKeyAttr, CSSM_KEYUSE_ANY,
&privKey, privKeyAttr, CSSM_KEYUSE_ANY,
quiet,
CSSM_TRUE, 0, CSSM_TRUE, 1, &dlDbHand);
}
else {
lookupType = CKT_Session;
compareKey = &symKey;
irtn = genSymKey(cspHand, &symKey, keyAlg, keyAlgStr,
keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT,
CSSM_KEYUSE_ANY, quiet,
CSSM_TRUE, 0, CSSM_TRUE, 1, &dlDbHand);
}
if(irtn) {
return irtn;
}
if(fetchStoredKey(dlDbHand, lookupType,
compareKey, "Store key with Good Dates", quiet,
&lookupKey)) {
return 1;
}
irtn = doEncrypt(cspHand, keyAlgStr, lookupKey, encrAlg, encrMode,
encrPad, CSSM_OK, quiet);
if(irtn) {
printf("***Failure on encrypt, lookup with Good Key Dates\n");
return irtn;
}
if(isAsym) {
cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle,
&keyLabelData, &pubKey);
cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle,
&keyLabelData, &privKey);
}
else {
cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle,
&keyLabelData, &symKey);
}
cspFreeKey(cspHand, lookupKey);
if(!quiet) {
printf(" ...verifying Bad StartDate\n");
}
if(isAsym) {
lookupType = CKT_Public;
compareKey = &pubKey;
irtn = genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits,
&pubKey, pubKeyAttr, CSSM_KEYUSE_ANY,
&privKey, privKeyAttr, CSSM_KEYUSE_ANY,
quiet,
CSSM_TRUE, 1, CSSM_TRUE, 1, &dlDbHand);
}
else {
lookupType = CKT_Session;
compareKey = &symKey;
irtn = genSymKey(cspHand, &symKey, keyAlg, keyAlgStr,
keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT,
CSSM_KEYUSE_ANY, quiet,
CSSM_TRUE, 1, CSSM_TRUE, 1, &dlDbHand);
}
if(irtn) {
return irtn;
}
if(fetchStoredKey(dlDbHand, lookupType,
compareKey, "Store key with Bad StartDate", quiet,
&lookupKey)) {
return 1;
}
irtn = doEncrypt(cspHand, keyAlgStr, lookupKey, encrAlg, encrMode,
encrPad, CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE, quiet);
if(irtn) {
printf("***Failure on encrypt, lookup with Bad Start Dates\n");
return irtn;
}
if(isAsym) {
cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle,
&keyLabelData, &pubKey);
cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle,
&keyLabelData, &privKey);
}
else {
cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle,
&keyLabelData, &symKey);
}
cspFreeKey(cspHand, lookupKey);
if(!quiet) {
printf(" ...verifying Bad EndDate\n");
}
if(isAsym) {
lookupType = CKT_Public;
compareKey = &pubKey;
irtn = genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits,
&pubKey, pubKeyAttr, CSSM_KEYUSE_ANY,
&privKey, privKeyAttr, CSSM_KEYUSE_ANY,
quiet,
CSSM_TRUE, 0, CSSM_TRUE, -1, &dlDbHand);
}
else {
lookupType = CKT_Session;
compareKey = &symKey;
irtn = genSymKey(cspHand, &symKey, keyAlg, keyAlgStr,
keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT,
CSSM_KEYUSE_ANY, quiet,
CSSM_TRUE, 0, CSSM_TRUE, -1, &dlDbHand);
}
if(irtn) {
return irtn;
}
if(fetchStoredKey(dlDbHand, lookupType,
compareKey, "Store key with Bad EndDate", quiet,
&lookupKey)) {
return 1;
}
irtn = doEncrypt(cspHand, keyAlgStr, lookupKey, encrAlg, encrMode,
encrPad, CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE, quiet);
if(irtn) {
printf("***Failure on encrypt, lookup with Bad End Dates\n");
return irtn;
}
if(isAsym) {
cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle,
&keyLabelData, &pubKey);
cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle,
&keyLabelData, &privKey);
}
else {
cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle,
&keyLabelData, &symKey);
}
cspFreeKey(cspHand, lookupKey);
return 0;
}
int main(int argc, char **argv)
{
CSSM_CSP_HANDLE cspHand;
int irtn;
CSSM_DL_DB_HANDLE dlDbHand = {0, 0};
char dbName[100];
CSSM_BOOL quiet = CSSM_FALSE;
CSSM_BOOL doSym = CSSM_TRUE;
CSSM_BOOL doAsym = CSSM_TRUE;
CSSM_BOOL doKeyStore = CSSM_TRUE;
CSSM_BOOL bareCsp = CSSM_TRUE;
int arg;
for(arg=1; arg<argc; arg++) {
switch(argv[arg][0]) {
case 's':
doAsym = doKeyStore = CSSM_FALSE;
break;
case 'a':
doSym = CSSM_FALSE;
break;
case 'D':
bareCsp = CSSM_FALSE;
break;
case 'q':
quiet = CSSM_TRUE;
break;
case 'h':
default:
usage(argv);
}
}
sprintf(dbName, "%s_%d", KD_DB_NAME, (int)getpid());
testStartBanner("keyDate", argc, argv);
cspHand = cspDlDbStartup(bareCsp, NULL);
if(cspHand == 0) {
exit(1);
}
if(!bareCsp) {
dlDbHand.DLHandle = dlStartup();
if(dlDbHand.DLHandle == 0) {
exit(1);
}
CSSM_RETURN crtn = dbCreateOpen(dlDbHand.DLHandle,
dbName, CSSM_TRUE, CSSM_TRUE, dbName,
&dlDbHand.DBHandle);
if(crtn) {
printf("Error creating %s. Aborting.\n", dbName);
exit(1);
}
}
privAlg palg;
if(doSym) {
for(palg=SYM_FIRST; palg<=SYM_LAST; palg++) {
irtn = doSymTests(cspHand, palg, CSSM_TRUE, quiet);
if(irtn) {
goto abort;
}
if(bareCsp) {
irtn = doSymTests(cspHand, palg, CSSM_FALSE, quiet);
if(irtn) {
goto abort;
}
}
else {
irtn = doStoreTests(cspHand, dlDbHand,
palg, CSSM_FALSE, quiet);
if(irtn) {
goto abort;
}
}
}
}
if(doAsym) {
for(palg=ASYM_FIRST; palg<=ASYM_LAST; palg++) {
irtn = doAsymTests(cspHand, palg, CSSM_TRUE, quiet);
if(irtn) {
goto abort;
}
if(bareCsp) {
irtn = doAsymTests(cspHand, palg, CSSM_TRUE, quiet);
if(irtn) {
goto abort;
}
}
else if(doKeyStore) {
irtn = doStoreTests(cspHand, dlDbHand,
palg, CSSM_TRUE, quiet);
if(irtn) {
goto abort;
}
}
}
}
abort:
if(irtn == 0) {
unlink(dbName);
}
return irtn;
}