#ifdef pcode
partial description...
for each asymmetric alg {
gen pub key with KEYUSE_ENCRYPT
make sure you cannot use it for vfy or decrypt
make sure you cannot use it for encrypting with other alg
gen priv key with KEYUSE_DECRYPT
make sure you cannot use it for sign or decrypt
make sure you cannot use it for decrypting with other alg
gen priv key with KEYUSE_SIGN
make sure you cannot use it for encrypt or decrypt
gen pub with KEYUSE_VERIFY
make sure you cannot use it for encrypt or decrypt
}
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <Security/cssm.h>
#include <Security/cssmapple.h>
#include "cspwrap.h"
#include "common.h"
#include "cspdlTesting.h"
typedef unsigned privAlg;
enum {
ALG_ASC = 1,
ALG_DES,
ALG_RC2,
ALG_RC4,
ALG_RC5,
ALG_3DES,
ALG_AES,
ALG_RSA,
ALG_FEE,
ALG_ECDSA,
ALG_DSA
};
#define SYM_FIRST ALG_ASC
#define SYM_LAST ALG_AES
#define ASYM_FIRST ALG_RSA
#define ASYM_LAST ALG_ECDSA
#define OP_SIGN 0x0001
#define OP_VERIFY 0x0002
#define OP_ENCRYPT 0x0004
#define OP_DECRYPT 0x0008
#define OP_GENMAC 0x0010
#define OP_VFYMAC 0x0020
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(" q(uiet)\n");
printf(" h(elp)\n");
exit(1);
}
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_RETURN expectRtn,
CSSM_BOOL quiet,
CSSM_BOOL freeKey, const char *testStr)
{
CSSM_RETURN crtn;
CSSM_CC_HANDLE ccHand;
CSSM_DATA dummyLabel = {4, (uint8 *)"foo"};
int irtn;
memset(symKey, 0, sizeof(CSSM_KEY));
crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
alg,
keySizeInBits, NULL, NULL, NULL, NULL, NULL, &ccHand);
if(crtn) {
printError("CSSM_CSP_CreateKeyGenContext", crtn);
return testError(quiet);
}
crtn = CSSM_GenerateKey(ccHand,
keyUsage,
keyAttr,
&dummyLabel,
NULL, symKey);
if(crtn != expectRtn) {
printf("***Testing %s for alg %s:\n", testStr, keyAlgStr);
printf(" CSSM_GenerateKey: expect %s\n", cssmErrToStr(expectRtn));
printf(" CSSM_GenerateKey: got %s\n", cssmErrToStr(crtn));
irtn = testError(quiet);
}
else {
irtn = 0;
}
CSSM_DeleteContext(ccHand);
if(freeKey && (crtn == CSSM_OK)) {
cspFreeKey(cspHand, symKey);
}
return irtn;
}
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_RETURN expectRtn,
CSSM_BOOL quiet,
CSSM_BOOL freeKeys, const char *testStr)
{
CSSM_RETURN crtn;
CSSM_CC_HANDLE ccHand;
CSSM_DATA keyLabelData = {4, (uint8 *)"foo"};
int irtn;
memset(pubKey, 0, sizeof(CSSM_KEY));
memset(privKey, 0, sizeof(CSSM_KEY));
crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
algorithm,
keySizeInBits,
NULL, NULL, NULL, NULL, NULL, &ccHand);
if(crtn) {
printError("CSSM_CSP_CreateKeyGenContext", crtn);
return testError(quiet);
}
switch(algorithm) {
case CSSM_ALGID_RSA:
break;
case CSSM_ALGID_DSA:
{
CSSM_DATA dummy = {0, NULL};
crtn = CSSM_GenerateAlgorithmParams(ccHand,
keySizeInBits, &dummy);
if(crtn) {
printError("CSSM_GenerateAlgorithmParams", crtn);
return testError(quiet);
}
appFreeCssmData(&dummy, CSSM_FALSE);
}
break;
default:
break;
}
crtn = CSSM_GenerateKeyPair(ccHand,
pubKeyUsage,
pubKeyAttr,
&keyLabelData,
pubKey,
privKeyUsage,
privKeyAttr,
&keyLabelData, NULL, privKey);
if(crtn != expectRtn) {
printf("***Testing %s for alg %s:\n", testStr, keyAlgStr);
printf(" CSSM_GenerateKeyPair: expect %s\n", cssmErrToStr(expectRtn));
printf(" CSSM_GenerateKeyPair: got %s\n", cssmErrToStr(crtn));
irtn = testError(quiet);
}
else {
irtn = 0;
}
CSSM_DeleteContext(ccHand);
if(freeKeys && (crtn == CSSM_OK)) {
cspFreeKey(cspHand, pubKey);
cspFreeKey(cspHand, privKey);
}
return irtn;
}
int nullWrapTest(
CSSM_CSP_HANDLE cspHand,
CSSM_KEY_PTR key,
CSSM_BOOL quiet,
CSSM_RETURN expectRtn,
const char *keyAlgStr,
const char *testStr)
{
CSSM_CC_HANDLE ccHand;
CSSM_RETURN crtn;
CSSM_ACCESS_CREDENTIALS creds;
CSSM_KEY wrappedKey; int irtn;
memset(&wrappedKey, 0, sizeof(CSSM_KEY));
memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
CSSM_ALGID_NONE,
CSSM_ALGMODE_NONE,
&creds, NULL, NULL, CSSM_PADDING_NONE,
0, &ccHand);
if(crtn) {
printError("cspWrapKey/CreateContext", crtn);
return testError(quiet);
}
crtn = CSSM_WrapKey(ccHand,
&creds,
key,
NULL, &wrappedKey);
if(crtn != expectRtn) {
printf("***Testing %s for alg %s:\n", testStr, keyAlgStr);
printf(" CSSM_WrapKey: expect %s\n", cssmErrToStr(expectRtn));
printf(" CSSM_WrapKey: got %s\n", cssmErrToStr(crtn));
irtn = testError(quiet);
}
else {
irtn = 0;
}
CSSM_DeleteContext(ccHand);
return irtn;
}
#define WRAPPING_KEY_ALG CSSM_ALGID_DES
#define WRAPPING_KEY_SIZE CSP_DES_KEY_SIZE_DEFAULT
static int badWrapTest(
CSSM_CSP_HANDLE cspHand,
CSSM_KEY_PTR unwrappedKey,
CSSM_KEYBLOB_FORMAT wrapForm,
CSSM_BOOL quiet,
const char *keyAlgStr,
const char *testStr)
{
CSSM_CC_HANDLE ccHand;
CSSM_RETURN crtn;
CSSM_ACCESS_CREDENTIALS creds;
CSSM_KEY wrappedKey; CSSM_KEY wrappingKey;
int irtn;
if(genSymKey(cspHand, &wrappingKey, CSSM_ALGID_DES, "DES",
CSP_DES_KEY_SIZE_DEFAULT,
CSSM_KEYATTR_RETURN_REF,
CSSM_KEYUSE_ANY, CSSM_OK, quiet,
CSSM_FALSE, "not a test case")) {
return 1;
}
memset(&wrappedKey, 0, sizeof(CSSM_KEY));
memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
CSSM_ALGID_DES,
CSSM_ALGMODE_CBCPadIV8,
&creds, &wrappingKey,
NULL, CSSM_PADDING_PKCS5,
0, &ccHand);
if(crtn) {
printError("cspWrapKey/CreateContext", crtn);
return testError(quiet);
}
crtn = CSSM_WrapKey(ccHand,
&creds,
unwrappedKey,
NULL, &wrappedKey);
if(crtn != CSSMERR_CSP_INVALID_KEYATTR_MASK) {
printf("***Testing %s for alg %s:\n", testStr, keyAlgStr);
printf(" CSSM_WrapKey: expect CSSMERR_CSP_INVALID_KEYATTR_MASK, got %s\n",
cssmErrToStr(crtn));
irtn = testError(quiet);
}
else {
irtn = 0;
}
CSSM_DeleteContext(ccHand);
cspFreeKey(cspHand, &wrappingKey);
return irtn;
}
static int badEncrypt(
CSSM_CSP_HANDLE cspHand,
CSSM_KEY_PTR key,
const char *keyAlgStr,
CSSM_ALGORITHMS opAlg,
CSSM_RETURN expectRtn,
CSSM_BOOL quiet,
const char *goodUseStr,
const char *badUseStr)
{
CSSM_CC_HANDLE cryptHand;
CSSM_DATA ptext = {4, (uint8 *)"foo"};
CSSM_DATA ctext = {0, NULL};
CSSM_DATA remData = {0, NULL};
CSSM_RETURN crtn;
CSSM_SIZE bytesEncrypted;
int irtn;
cryptHand = genCryptHandle(cspHand, opAlg, CSSM_ALGMODE_NONE, CSSM_PADDING_NONE,
key, NULL , NULL , 0, 0);
if(cryptHand == 0) {
return testError(quiet);
}
crtn = CSSM_EncryptData(cryptHand, &ptext, 1, &ctext, 1, &bytesEncrypted, &remData);
if(crtn != expectRtn) {
printf("***Testing %s key w/%s during %s:\n", keyAlgStr, goodUseStr, badUseStr);
printf(" CSSM_EncryptData: expect %s\n", cssmErrToStr(expectRtn));
printf(" CSSM_EncryptData: got %s\n", cssmErrToStr(crtn));
irtn = testError(quiet);
}
else {
irtn = 0;
}
CSSM_DeleteContext(cryptHand);
return irtn;
}
static int badDecrypt(
CSSM_CSP_HANDLE cspHand,
CSSM_KEY_PTR key,
const char *keyAlgStr,
CSSM_ALGORITHMS opAlg,
CSSM_RETURN expectRtn,
CSSM_BOOL quiet,
const char *goodUseStr,
const char *badUseStr)
{
CSSM_CC_HANDLE cryptHand;
CSSM_DATA ctext = {4, (uint8 *)"foo"};
CSSM_DATA ptext = {0, NULL};
CSSM_DATA remData = {0, NULL};
CSSM_RETURN crtn;
CSSM_SIZE bytesDecrypted;
int irtn;
cryptHand = genCryptHandle(cspHand, opAlg, CSSM_ALGMODE_NONE, CSSM_PADDING_NONE,
key, NULL , NULL , 0, 0);
if(cryptHand == 0) {
return testError(quiet);
}
crtn = CSSM_DecryptData(cryptHand, &ctext, 1, &ptext, 1, &bytesDecrypted, &remData);
if(crtn != expectRtn) {
printf("***Testing %s key w/%s during %s:\n", keyAlgStr, goodUseStr, badUseStr);
printf(" CSSM_DecryptData: expect %s\n", cssmErrToStr(expectRtn));
printf(" CSSM_DecryptData: got %s\n", cssmErrToStr(crtn));
irtn = testError(quiet);
}
else {
irtn = 0;
}
CSSM_DeleteContext(cryptHand);
return irtn;
}
static int badHdrTest(
CSSM_CSP_HANDLE cspHand,
CSSM_KEY_PTR key,
CSSM_BOOL quiet,
const char *keyAlgStr)
{
CSSM_KEYHEADER *hdr = &key->KeyHeader;
CSSM_KEYHEADER savedHdr = *hdr;
hdr->HeaderVersion++;
if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE,
keyAlgStr, "Munged hdr(HeaderVersion)")) {
return 1;
}
*hdr = savedHdr;
hdr->CspId.Data1++;
if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE,
keyAlgStr, "Munged hdr(CspId.Data1)")) {
return 1;
}
*hdr = savedHdr;
hdr->AlgorithmId++;
if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE,
keyAlgStr, "Munged hdr(AlgorithmId)")) {
return 1;
}
*hdr = savedHdr;
switch(hdr->KeyClass) {
case CSSM_KEYCLASS_PUBLIC_KEY:
hdr->KeyClass = CSSM_KEYCLASS_PRIVATE_KEY; break;
case CSSM_KEYCLASS_PRIVATE_KEY:
hdr->KeyClass = CSSM_KEYCLASS_SESSION_KEY; break;
case CSSM_KEYCLASS_SESSION_KEY:
hdr->KeyClass = CSSM_KEYCLASS_PUBLIC_KEY; break;
default:
printf("***BRZZAP! badHdrTest needs work\n");
exit(1);
}
if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE,
keyAlgStr, "Munged hdr(KeyClass)")) {
return 1;
}
*hdr = savedHdr;
hdr->LogicalKeySizeInBits++;
if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE,
keyAlgStr, "Munged hdr(LogicalKeySizeInBits)")) {
return 1;
}
*hdr = savedHdr;
hdr->KeyAttr++;
if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE,
keyAlgStr, "Munged hdr(KeyAttr)")) {
return 1;
}
*hdr = savedHdr;
hdr->StartDate.Day[0]++;
if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE,
keyAlgStr, "Munged hdr(StartDate.Day)")) {
return 1;
}
*hdr = savedHdr;
hdr->EndDate.Year[1]++;
if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE,
keyAlgStr, "Munged hdr(EndDate.Year)")) {
return 1;
}
*hdr = savedHdr;
hdr->WrapAlgorithmId++;
if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE,
keyAlgStr, "Munged hdr(WrapAlgorithmId)")) {
return 1;
}
*hdr = savedHdr;
hdr->WrapMode++;
if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE,
keyAlgStr, "Munged hdr(WrapMode)")) {
return 1;
}
*hdr = savedHdr;
return 0;
}
CSSM_ALGORITHMS badOpAlg(
CSSM_ALGORITHMS opAlg)
{
switch(opAlg) {
case CSSM_ALGID_DES: return CSSM_ALGID_3DES_3KEY_EDE;
case CSSM_ALGID_3DES_3KEY_EDE: return CSSM_ALGID_RC2;
case CSSM_ALGID_RC2: return CSSM_ALGID_RC5;
case CSSM_ALGID_RC5: return CSSM_ALGID_AES;
case CSSM_ALGID_AES: return CSSM_ALGID_DES;
case CSSM_ALGID_ASC: return CSSM_ALGID_RC4;
case CSSM_ALGID_RC4: return CSSM_ALGID_ASC;
case CSSM_ALGID_RSA: return CSSM_ALGID_FEEDEXP;
case CSSM_ALGID_FEEDEXP: return CSSM_ALGID_RSA;
case CSSM_ALGID_SHA1WithRSA: return CSSM_ALGID_SHA1WithDSA;
case CSSM_ALGID_SHA1WithDSA: return CSSM_ALGID_SHA1WithECDSA;
case CSSM_ALGID_SHA1WithECDSA: return CSSM_ALGID_SHA1WithRSA;
default: printf("***BRRZAP! badOpAlg needs work.\n"); exit(1);
}
return 0;
}
#define SYM_USAGE_ENABLE 1
static int badSymUsage(
CSSM_CSP_HANDLE cspHand,
CSSM_ALGORITHMS keyAlg, const char *keyAlgStr,
uint32 keySizeInBits,
CSSM_KEYUSE keyUse, CSSM_ALGORITHMS goodEncrAlg, CSSM_ALGORITHMS goodSignAlg, unsigned badOpFlags, unsigned goodOp, CSSM_ALGORITHMS badAlg, CSSM_BOOL quiet,
const char *useStr)
{
CSSM_KEY symKey;
int irtn;
if(genSymKey(cspHand, &symKey, keyAlg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF, keyUse, CSSM_OK, quiet, CSSM_FALSE, useStr)) {
return 1;
}
#if SYM_USAGE_ENABLE
if(!quiet) {
printf(" ...testing key usage\n");
}
if(badOpFlags & OP_ENCRYPT) {
irtn = badEncrypt(cspHand, &symKey, keyAlgStr, goodEncrAlg,
CSSMERR_CSP_KEY_USAGE_INCORRECT, quiet, useStr, "ENCRYPT");
if(irtn) {
goto abort;
}
}
if(badOpFlags & OP_DECRYPT) {
irtn = badDecrypt(cspHand, &symKey, keyAlgStr, goodEncrAlg,
CSSMERR_CSP_KEY_USAGE_INCORRECT, quiet, useStr, "DECRYPT");
if(irtn) {
goto abort;
}
}
#endif
if(!quiet) {
printf(" ...testing key/algorithm match\n");
}
if(goodOp & OP_ENCRYPT) {
irtn = badEncrypt(cspHand, &symKey, keyAlgStr, badAlg,
CSSMERR_CSP_ALGID_MISMATCH, quiet, useStr, "ENCRYPT w/bad alg");
if(irtn) {
goto abort;
}
}
if(goodOp & OP_DECRYPT) {
irtn = badDecrypt(cspHand, &symKey, keyAlgStr, badAlg,
CSSMERR_CSP_ALGID_MISMATCH, quiet, useStr, "DECRYPT w/bad alg");
if(irtn) {
goto abort;
}
}
abort:
cspFreeKey(cspHand, &symKey);
return irtn;
}
int symUsageTest(
CSSM_CSP_HANDLE cspHand,
CSSM_ALGORITHMS keyAlg,
const char *keyAlgStr,
CSSM_ALGORITHMS encrAlg,
CSSM_ALGORITHMS signAlg,
uint32 keySizeInBits,
CSSM_BOOL quiet)
{
if(!quiet) {
printf(" ...testing encrypt-enabled key\n");
}
if(badSymUsage(cspHand, keyAlg, keyAlgStr, keySizeInBits, CSSM_KEYUSE_ENCRYPT,
encrAlg, signAlg, OP_DECRYPT, OP_ENCRYPT, badOpAlg(encrAlg),
quiet, "ENCRYPT")) {
return 1;
}
if(!quiet) {
printf(" ...testing decrypt-enabled key\n");
}
if(badSymUsage(cspHand, keyAlg, keyAlgStr, keySizeInBits, CSSM_KEYUSE_DECRYPT,
encrAlg, signAlg, OP_ENCRYPT, OP_DECRYPT, badOpAlg(encrAlg),
quiet, "DECRYPT")) {
return 1;
}
return 0;
}
int symAttrTest(
CSSM_CSP_HANDLE cspHand,
CSSM_ALGORITHMS alg,
const char *keyAlgStr,
uint32 keySizeInBits,
CSSM_BOOL bareCsp,
CSSM_BOOL quiet)
{
CSSM_KEY key;
if(!quiet) {
printf(" ...testing key attr\n");
}
if(bareCsp || CSPDL_ALWAYS_SENSITIVE_CHECK) {
if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_ALWAYS_SENSITIVE,
CSSM_KEYUSE_ANY, CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet,
CSSM_TRUE, "ALWAYS_SENSITIVE")) {
return 1;
}
}
if(bareCsp || CSPDL_NEVER_EXTRACTABLE_CHECK) {
if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_NEVER_EXTRACTABLE,
CSSM_KEYUSE_ANY, CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet,
CSSM_TRUE, "NEVER_EXTRACTABLE")) {
return 1;
}
}
if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT,
CSSM_KEYUSE_ANY,
bareCsp ? CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK :
CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE,
quiet,
CSSM_TRUE, "PERMANENT")) {
return 1;
}
if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PRIVATE,
CSSM_KEYUSE_ANY, CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK, quiet,
CSSM_TRUE, "PRIVATE")) {
return 1;
}
if(bareCsp) {
if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_DATA ,
CSSM_KEYUSE_ANY,
CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet,
CSSM_TRUE, "RETURN_DATA | !EXTRACTABLE")) {
return 1;
}
if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_SENSITIVE,
CSSM_KEYUSE_ANY, CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet,
CSSM_TRUE, "RETURN_DATA | SENSITIVE")) {
return 1;
}
if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_RETURN_REF,
CSSM_KEYUSE_ANY, CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet,
CSSM_TRUE, "RETURN_DATA | RETURN_REF")) {
return 1;
}
}
return 0;
}
int symNullWrapTest(
CSSM_CSP_HANDLE cspHand,
CSSM_ALGORITHMS alg,
const char *keyAlgStr,
uint32 keySizeInBits,
CSSM_BOOL quiet)
{
CSSM_KEY key;
if(!quiet) {
printf(" ...testing access to inaccessible key bits via NULL wrap\n");
}
if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE,
CSSM_KEYUSE_ANY, CSSM_OK, quiet,
CSSM_FALSE, "SENSITIVE | RETURN_REF")) {
return 1;
}
if(nullWrapTest(cspHand, &key, quiet, CSSMERR_CSP_INVALID_KEYATTR_MASK,
keyAlgStr, "KEYATTR_SENSITIVE")) {
return 1;
}
cspFreeKey(cspHand, &key);
if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF ,
CSSM_KEYUSE_ANY, CSSM_OK, quiet,
CSSM_FALSE, "!EXTRACTABLE | RETURN_REF")) {
return 1;
}
if(nullWrapTest(cspHand, &key, quiet, CSSMERR_CSP_INVALID_KEYATTR_MASK,
keyAlgStr, "!EXTRACTABLE")) {
return 1;
}
cspFreeKey(cspHand, &key);
return 0;
}
int symBadWrapTest(
CSSM_CSP_HANDLE cspHand,
CSSM_ALGORITHMS alg,
const char *keyAlgStr,
uint32 keySizeInBits,
CSSM_BOOL quiet)
{
CSSM_KEY unwrappedKey;
if(!quiet) {
printf(" ...testing access to !EXTRACTABLE key bits via PKCS7 wrap\n");
}
if(genSymKey(cspHand, &unwrappedKey, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE,
CSSM_KEYUSE_ANY, CSSM_OK, quiet,
CSSM_FALSE, "SENSITIVE | RETURN_REF")) {
return 1;
}
if(badWrapTest(cspHand,
&unwrappedKey,
CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7,
quiet, keyAlgStr,
"!EXTRACTABLE wrap")) {
return 1;
}
cspFreeKey(cspHand, &unwrappedKey);
return 0;
}
int asymBadWrapTest(
CSSM_CSP_HANDLE cspHand,
CSSM_ALGORITHMS alg,
const char *keyAlgStr,
uint32 keySizeInBits,
CSSM_BOOL quiet)
{
CSSM_KEY pubKey;
CSSM_KEY privKey;
if(!quiet) {
printf(" ...testing access to !EXTRACTABLE key bits via CUSTOM wrap\n");
}
if(genKeyPair(cspHand, alg, keyAlgStr, keySizeInBits,
&pubKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE,
CSSM_KEYUSE_ANY,
&privKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE,
CSSM_KEYUSE_ANY,
CSSM_OK, quiet, CSSM_FALSE, "RETURN_REF | SENSITIVE")) {
return 1;
}
if(badWrapTest(cspHand,
&privKey,
CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM,
quiet, keyAlgStr,
"!EXTRACTABLE wrap")) {
return 1;
}
cspFreeKey(cspHand, &privKey);
cspFreeKey(cspHand, &pubKey);
return 0;
}
int symHeaderTest(
CSSM_CSP_HANDLE cspHand,
CSSM_ALGORITHMS keyAlg,
const char *keyAlgStr,
CSSM_ALGORITHMS encrAlg,
CSSM_ALGORITHMS signAlg,
uint32 keySizeInBits,
CSSM_BOOL quiet)
{
CSSM_KEY key;
if(!quiet) {
printf(" ...testing munged ref key header\n");
}
if(genSymKey(cspHand, &key, keyAlg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE,
CSSM_KEYUSE_ANY, CSSM_OK, quiet,
CSSM_FALSE, "RETURN_REF")) {
return 1;
}
if(badHdrTest(cspHand, &key, quiet, keyAlgStr)) {
return 1;
}
cspFreeKey(cspHand, &key);
return 0;
}
static int pubKeyAttrTest(
CSSM_CSP_HANDLE cspHand,
CSSM_ALGORITHMS alg,
const char *keyAlgStr,
uint32 keySizeInBits,
CSSM_KEYATTR_FLAGS pubKeyAttr,
CSSM_RETURN expectRtn,
CSSM_BOOL quiet,
const char *testStr)
{
CSSM_KEY pubKey;
CSSM_KEY privKey;
return genKeyPair(cspHand, alg, keyAlgStr, keySizeInBits,
&pubKey, pubKeyAttr, CSSM_KEYUSE_ANY,
&privKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE, CSSM_KEYUSE_ANY,
expectRtn, quiet, CSSM_TRUE, testStr);
}
static int privKeyAttrTest(
CSSM_CSP_HANDLE cspHand,
CSSM_ALGORITHMS alg,
const char *keyAlgStr,
uint32 keySizeInBits,
CSSM_KEYATTR_FLAGS privKeyAttr,
CSSM_RETURN expectRtn,
CSSM_BOOL quiet,
const char *testStr)
{
CSSM_KEY pubKey;
CSSM_KEY privKey;
return genKeyPair(cspHand, alg, keyAlgStr, keySizeInBits,
&pubKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE,
CSSM_KEYUSE_ANY,
&privKey, privKeyAttr, CSSM_KEYUSE_ANY,
expectRtn, quiet, CSSM_TRUE, testStr);
}
static int asymAttrTest(
CSSM_CSP_HANDLE cspHand,
CSSM_ALGORITHMS alg,
const char *keyAlgStr,
uint32 keySizeInBits,
CSSM_BOOL bareCsp,
CSSM_BOOL quiet)
{
#if CSPDL_ALL_KEYS_ARE_PERMANENT
printf(" ...SKIPING asymAttrTest due to Radar 3732910\n");
return 0;
#endif
if(!quiet) {
printf(" ...testing key attr\n");
}
if(bareCsp || CSPDL_ALWAYS_SENSITIVE_CHECK) {
if(pubKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_ALWAYS_SENSITIVE,
CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, "ALWAYS_SENSITIVE pub")) {
return 1;
}
}
if(bareCsp || CSPDL_NEVER_EXTRACTABLE_CHECK) {
if(pubKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_NEVER_EXTRACTABLE,
CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, "NEVER_EXTRACTABLE pub")) {
return 1;
}
}
if(pubKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT |
CSSM_KEYATTR_EXTRACTABLE,
bareCsp ?
CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK :
CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE,
quiet, "PERMANENT pub")) {
return 1;
}
if(pubKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PRIVATE |
CSSM_KEYATTR_EXTRACTABLE,
CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK, quiet, "PRIVATE pub")) {
return 1;
}
if(bareCsp) {
if(pubKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_DATA ,
CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet,
"RETURN_DATA | !EXTRACTABLE pub")) {
return 1;
}
}
if(pubKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF ,
CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet,
"RETURN_REF | !EXTRACTABLE pub")) {
return 1;
}
if(bareCsp) {
if(pubKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_SENSITIVE,
CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, "RETURN_DATA | SENSITIVE pub")) {
return 1;
}
}
if(pubKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE,
CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, "RETURN_REF | !SENSITIVE pub")) {
return 1;
}
if(bareCsp || CSPDL_ALWAYS_SENSITIVE_CHECK) {
if(privKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_ALWAYS_SENSITIVE,
CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, "ALWAYS_SENSITIVE priv")) {
return 1;
}
}
if(bareCsp || CSPDL_NEVER_EXTRACTABLE_CHECK) {
if(privKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_NEVER_EXTRACTABLE,
CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, "NEVER_EXTRACTABLE priv")) {
return 1;
}
}
if(privKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT,
bareCsp ? CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK :
CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE,
quiet, "PERMANENT priv")) {
return 1;
}
if(privKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PRIVATE,
CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK, quiet, "PRIVATE priv")) {
return 1;
}
if(bareCsp) {
if(privKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_DATA ,
CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet,
"RETURN_DATA | !EXTRACTABLE priv")) {
return 1;
}
if(privKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits,
CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_SENSITIVE,
CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, "RETURN_DATA | SENSITIVE priv")) {
return 1;
}
}
return 0;
}
static int asymNullWrapTest(
CSSM_CSP_HANDLE cspHand,
CSSM_ALGORITHMS alg,
const char *keyAlgStr,
uint32 keySizeInBits,
CSSM_BOOL quiet)
{
CSSM_KEY pubKey;
CSSM_KEY privKey;
if(!quiet) {
printf(" ...testing access to inaccessible key bits via NULL wrap\n");
}
if(genKeyPair(cspHand, alg, keyAlgStr, keySizeInBits,
&pubKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE,
CSSM_KEYUSE_ANY,
&privKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE,
CSSM_KEYUSE_ANY,
CSSM_OK, quiet, CSSM_FALSE, "RETURN_REF | SENSITIVE")) {
return 1;
}
if(nullWrapTest(cspHand, &privKey, quiet, CSSMERR_CSP_INVALID_KEYATTR_MASK,
keyAlgStr, "SENSITIVE")) {
return 1;
}
cspFreeKey(cspHand, &privKey);
cspFreeKey(cspHand, &pubKey);
if(genKeyPair(cspHand, alg, keyAlgStr, keySizeInBits,
&pubKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE,
CSSM_KEYUSE_ANY,
&privKey, CSSM_KEYATTR_RETURN_REF , CSSM_KEYUSE_ANY,
CSSM_OK, quiet, CSSM_FALSE, "RETURN_REF | !EXTRACTABLE")) {
return 1;
}
if(nullWrapTest(cspHand, &privKey, quiet, CSSMERR_CSP_INVALID_KEYATTR_MASK,
keyAlgStr, "!EXTRACTABLE")) {
return 1;
}
cspFreeKey(cspHand, &privKey);
cspFreeKey(cspHand, &pubKey);
return 0;
}
int asymHeaderTest(
CSSM_CSP_HANDLE cspHand,
CSSM_ALGORITHMS keyAlg,
const char *keyAlgStr,
CSSM_ALGORITHMS encrAlg,
CSSM_ALGORITHMS signAlg,
uint32 keySizeInBits,
CSSM_BOOL quiet)
{
CSSM_KEY privKey;
CSSM_KEY pubKey;
if(!quiet) {
printf(" ...testing munged ref key header\n");
}
if(genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits,
&pubKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE,
CSSM_KEYUSE_ANY,
&privKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE,
CSSM_KEYUSE_ANY,
CSSM_OK, quiet, CSSM_FALSE, "RETURN_REF")) {
return 1;
}
if(badHdrTest(cspHand, &privKey, quiet, keyAlgStr)) {
return 1;
}
if(badHdrTest(cspHand, &pubKey, quiet, keyAlgStr)) {
return 1;
}
cspFreeKey(cspHand, &privKey);
cspFreeKey(cspHand, &pubKey);
return 0;
}
void privAlgToCssm(
privAlg palg,
CSSM_ALGORITHMS *keyAlg,
CSSM_ALGORITHMS *signAlg, CSSM_ALGORITHMS *encrAlg, uint32 *keySizeInBits,
const char **keyAlgStr)
{
*signAlg = *encrAlg = CSSM_ALGID_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";
break;
case ALG_3DES:
*encrAlg = CSSM_ALGID_3DES_3KEY_EDE;
*keyAlg = CSSM_ALGID_3DES_3KEY;
*keySizeInBits = CSP_DES3_KEY_SIZE_DEFAULT;
*keyAlgStr = "3DES";
break;
case ALG_RC2:
*encrAlg = *keyAlg = CSSM_ALGID_RC2;
*keySizeInBits = CSP_RC2_KEY_SIZE_DEFAULT;
*keyAlgStr = "RC2";
break;
case ALG_RC4:
*encrAlg = *keyAlg = CSSM_ALGID_RC4;
*keySizeInBits = CSP_RC4_KEY_SIZE_DEFAULT;
*keyAlgStr = "RC4";
break;
case ALG_RC5:
*encrAlg = *keyAlg = CSSM_ALGID_RC5;
*keySizeInBits = CSP_RC5_KEY_SIZE_DEFAULT;
*keyAlgStr = "RC5";
break;
case ALG_AES:
*encrAlg = *keyAlg = CSSM_ALGID_AES;
*keySizeInBits = CSP_AES_KEY_SIZE_DEFAULT;
*keyAlgStr = "AES";
break;
case ALG_RSA:
*keyAlg = CSSM_ALGID_RSA;
*encrAlg = CSSM_ALGID_RSA;
*signAlg = CSSM_ALGID_SHA1WithRSA;
*keySizeInBits = CSP_RSA_KEY_SIZE_DEFAULT;
*keyAlgStr = "RSA";
break;
case ALG_DSA:
*keyAlg = CSSM_ALGID_DSA;
*signAlg = CSSM_ALGID_SHA1WithDSA;
*keySizeInBits = CSP_DSA_KEY_SIZE_DEFAULT;
*keyAlgStr = "DSA";
break;
case ALG_FEE:
*keyAlg = CSSM_ALGID_FEE;
*signAlg = CSSM_ALGID_SHA1WithECDSA;
*encrAlg = CSSM_ALGID_FEEDEXP;
*keySizeInBits = CSP_FEE_KEY_SIZE_DEFAULT;
*keyAlgStr = "FEE";
break;
case ALG_ECDSA:
*keyAlg = CSSM_ALGID_ECDSA;
*signAlg = CSSM_ALGID_SHA1WithECDSA;
*keySizeInBits = CSP_ECDSA_KEY_SIZE_DEFAULT;
*keyAlgStr = "ECDSA";
break;
default:
printf("***BRRZAP! privAlgToCssm needs work\n");
exit(1);
}
return;
}
int main(int argc, char **argv)
{
int arg;
char *argp;
CSSM_CSP_HANDLE cspHand;
CSSM_ALGORITHMS keyAlg; CSSM_ALGORITHMS signAlg; CSSM_ALGORITHMS encrAlg; privAlg palg;
uint32 keySizeInBits;
int rtn;
int i;
const char *keyAlgStr;
CSSM_BOOL quiet = CSSM_FALSE;
CSSM_BOOL doSym = CSSM_TRUE;
CSSM_BOOL doAsym = CSSM_TRUE;
CSSM_BOOL bareCsp = CSSM_TRUE;
for(arg=1; arg<argc; arg++) {
argp = argv[arg];
switch(argp[0]) {
case 'q':
quiet = CSSM_TRUE;
break;
case 's':
doAsym = CSSM_FALSE;
break;
case 'a':
doSym = CSSM_FALSE;
break;
case 'D':
bareCsp = CSSM_FALSE;
break;
case 'h':
default:
usage(argv);
}
}
cspHand = cspDlDbStartup(bareCsp, NULL);
if(cspHand == 0) {
exit(1);
}
printf("Starting badattr; args: ");
for(i=1; i<argc; i++) {
printf("%s ", argv[i]);
}
printf("\n");
if(doSym) {
for(palg=SYM_FIRST; palg<=SYM_LAST; palg++) {
privAlgToCssm(palg, &keyAlg, &signAlg, &encrAlg, &keySizeInBits, &keyAlgStr);
if(!quiet) {
printf(" ...alg %s\n", keyAlgStr);
}
rtn = symAttrTest(cspHand, keyAlg, keyAlgStr, keySizeInBits, bareCsp,
quiet);
if(rtn) {
goto abort;
}
rtn = symNullWrapTest(cspHand, keyAlg, keyAlgStr, keySizeInBits, quiet);
if(rtn) {
goto abort;
}
rtn = symBadWrapTest(cspHand, keyAlg, keyAlgStr, keySizeInBits, quiet);
if(rtn) {
goto abort;
}
rtn = symUsageTest(cspHand, keyAlg, keyAlgStr, encrAlg, signAlg,
keySizeInBits, quiet);
if(rtn) {
goto abort;
}
if(bareCsp || CSPDL_MUNGE_HEADER_CHECK) {
rtn = symHeaderTest(cspHand, keyAlg, keyAlgStr, encrAlg, signAlg,
keySizeInBits, quiet);
if(rtn) {
goto abort;
}
}
else if(!quiet) {
printf(" ...SKIPPING munged ref key header test\n");
}
}
}
if(doAsym) {
for(palg=ASYM_FIRST; palg<=ASYM_LAST; palg++) {
privAlgToCssm(palg, &keyAlg, &signAlg, &encrAlg, &keySizeInBits,
&keyAlgStr);
if(!quiet) {
printf(" ...alg %s\n", keyAlgStr);
}
rtn = asymAttrTest(cspHand, keyAlg, keyAlgStr, keySizeInBits,
bareCsp, quiet);
if(rtn) {
goto abort;
}
rtn = asymNullWrapTest(cspHand, keyAlg, keyAlgStr, keySizeInBits, quiet);
if(rtn) {
goto abort;
}
rtn = asymBadWrapTest(cspHand, keyAlg, keyAlgStr, keySizeInBits, quiet);
if(rtn) {
goto abort;
}
if(bareCsp || CSPDL_MUNGE_HEADER_CHECK) {
rtn = asymHeaderTest(cspHand, keyAlg, keyAlgStr, encrAlg, signAlg,
keySizeInBits, quiet);
if(rtn) {
goto abort;
}
}
else if(!quiet) {
printf(" ...SKIPPING munged ref key header test\n");
}
}
}
abort:
cspShutdown(cspHand, bareCsp);
if((rtn == 0) && !quiet) {
printf("%s complete\n", argv[0]);
}
return rtn;
}