certSerialEncodeTest.cpp [plain text]
#include <utilLib/common.h>
#include <utilLib/cspwrap.h>
#include <security_cdsa_utils/cuFileIo.h>
#include <clAppUtils/clutils.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <Security/cssm.h>
#include <Security/x509defs.h>
#include <Security/oidsattr.h>
#include <Security/oidscert.h>
#include <Security/oidsalg.h>
#include <Security/certextensions.h>
#include <Security/cssmapple.h>
#include <string.h>
#define SUBJ_KEY_LABEL "subjectKey"
#define ROOT_KEY_LABEL "rootKey"
#define SIG_ALG_DEFAULT CSSM_ALGID_SHA1WithRSA
#define SIG_OID_DEFAULT CSSMOID_SHA1WithRSA
#define KEY_ALG_DEFAULT CSSM_ALGID_RSA
#define ROOT_CERT_FILE_NAME "ssRootCert.cer"
#define SUBJ_CERT_FILE_NAME "ssSubjCert.cer"
#define PUB_KEY_IS_REF CSSM_TRUE
static void usage(char **argv)
{
printf("Usage: %s [options]\n", argv[0]);
printf("Options:\n");
printf(" w[rite certs]\n");
printf(" p(ause for MallocDebug)\n");
printf(" q(uiet)\n");
exit(1);
}
static CSSM_APPLE_TP_NAME_OID rootRdn[] =
{
{ "Apple Computer", &CSSMOID_OrganizationName },
{ "The Big Cheesy Debug Root", &CSSMOID_CommonName }
};
#define NUM_ROOT_NAMES (sizeof(rootRdn) / sizeof(CSSM_APPLE_TP_NAME_OID))
typedef struct {
uint32 serialIn;
CSSM_SIZE expectLen;
const uint8 *expect;
} SerialNumber;
static const uint8 sn0_Data[1] = {0x7f};
static const SerialNumber sn0 = {0x7f, 1, sn0_Data };
static const uint8 sn1_Data[2] = {0x00, 0x80};
static const SerialNumber sn1 = {0x80, 2, sn1_Data };
static const uint8 sn2_Data[2] = {0x07, 0xff};
static const SerialNumber sn2 = {0x7ff, 2, sn2_Data };
static const uint8 sn3_Data[3] = {0x00, 0x80, 0xff};
static const SerialNumber sn3 = {0x80ff, 3, sn3_Data };
static const uint8 sn4_Data[4] = {0x0f, 0xff, 0xff, 0xff};
static const SerialNumber sn4 = {0xfffffff, 4, sn4_Data };
static const uint8 sn5_Data[4] = {0x0f, 0xff, 0xff, 0xff};
static const SerialNumber sn5 = {0x0fffffff, 4, sn5_Data };
static const uint8 sn6_Data[5] = {0x00, 0x80, 0x00, 0x00, 0x00};
static const SerialNumber sn6 = {0x80000000, 5, sn6_Data };
static const SerialNumber *serialNumbers[] = {
&sn0, &sn1, &sn2, &sn3, &sn4, &sn5, &sn6
};
#define NUM_SERIAL_NUMS (sizeof(serialNumbers) / sizeof(serialNumbers[0]))
static int doTest(
CSSM_CL_HANDLE clHand, CSSM_CSP_HANDLE cspHand, CSSM_TP_HANDLE tpHand, CSSM_KEY_PTR subjPubKey,
CSSM_KEY_PTR signerPrivKey,
uint32 serialNumIn,
CSSM_SIZE serialNumExpLen,
const uint8 *serialNumExp,
CSSM_BOOL quiet,
CSSM_BOOL writeBlobs)
{
CSSM_DATA refId; CSSM_APPLE_TP_CERT_REQUEST certReq;
CSSM_TP_REQUEST_SET reqSet;
sint32 estTime;
CSSM_BOOL confirmRequired;
CSSM_TP_RESULT_SET_PTR resultSet;
CSSM_ENCODED_CERT *encCert;
CSSM_TP_CALLERAUTH_CONTEXT CallerAuthContext;
CSSM_FIELD policyId;
CSSM_RETURN crtn;
CSSM_DATA *signedRootCert;
int ourRtn = 0;
CSSM_DATA_PTR foundSerial = NULL;
CSSM_HANDLE resultHand = 0;
uint32 numFields;
memset(&certReq, 0, sizeof(CSSM_APPLE_TP_CERT_REQUEST));
certReq.cspHand = cspHand;
certReq.clHand = clHand;
certReq.serialNumber = serialNumIn;
certReq.numSubjectNames = NUM_ROOT_NAMES;
certReq.subjectNames = rootRdn;
certReq.numIssuerNames = 0;
certReq.issuerNames = NULL;
certReq.certPublicKey = subjPubKey;
certReq.issuerPrivateKey = signerPrivKey;
certReq.signatureAlg = CSSM_ALGID_SHA1WithRSA;
certReq.signatureOid = CSSMOID_SHA1WithRSA;
certReq.notBefore = 0; certReq.notAfter = 10000; certReq.numExtensions = 0;
certReq.extensions = NULL;
reqSet.NumberOfRequests = 1;
reqSet.Requests = &certReq;
memset(&CallerAuthContext, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT));
memset(&policyId, 0, sizeof(CSSM_FIELD));
policyId.FieldOid = CSSMOID_APPLE_TP_LOCAL_CERT_GEN;
CallerAuthContext.Policy.NumberOfPolicyIds = 1;
CallerAuthContext.Policy.PolicyIds = &policyId;
if(!quiet) {
printf("Creating root cert...\n");
}
crtn = CSSM_TP_SubmitCredRequest(tpHand,
NULL, CSSM_TP_AUTHORITY_REQUEST_CERTISSUE,
&reqSet,
&CallerAuthContext,
&estTime,
&refId);
if(crtn) {
printError("CSSM_TP_SubmitCredRequest", crtn);
ourRtn = -1;
goto errOut;
}
crtn = CSSM_TP_RetrieveCredResult(tpHand,
&refId,
NULL, &estTime,
&confirmRequired,
&resultSet);
if(crtn) {
printError("CSSM_TP_RetrieveCredResult", crtn);
ourRtn = -1;
goto errOut;
}
if(resultSet == NULL) {
printf("***CSSM_TP_RetrieveCredResult returned NULL result set.\n");
ourRtn = -1;
goto errOut;
}
encCert = (CSSM_ENCODED_CERT *)resultSet->Results;
signedRootCert = &encCert->CertBlob;
if(writeBlobs) {
writeFile(ROOT_CERT_FILE_NAME, signedRootCert->Data, signedRootCert->Length);
printf("...wrote %lu bytes to %s\n", signedRootCert->Length,
ROOT_CERT_FILE_NAME);
}
crtn = CSSM_CL_CertVerify(clHand, 0 ,
signedRootCert, signedRootCert,
NULL, 0);
if(crtn) {
cssmPerror("CSSM_CL_CertVerify", crtn);
printf("***Created cert does not self-verify\n");
ourRtn = -1;
goto errOut;
}
crtn = CSSM_CL_CertGetFirstFieldValue(clHand, signedRootCert,
&CSSMOID_X509V1SerialNumber, &resultHand, &numFields, &foundSerial);
if(crtn) {
cssmPerror("CSSM_CL_CertGetFirstFieldValue(serialNumber)", crtn);
printf("***Can't obtain serial number\n");
ourRtn = -1;
goto errOut;
}
CSSM_CL_CertAbortQuery(clHand, resultHand);
if(foundSerial->Length != serialNumExpLen) {
printf("***expected serialNumber len 0x%lu, got 0x%lu\n",
(unsigned long)serialNumExpLen, (unsigned long)foundSerial->Length);
ourRtn = -1;
goto errOut;
}
for(unsigned dex=0; dex<serialNumExpLen; dex++) {
if(foundSerial->Data[dex] != serialNumExp[dex]) {
printf("***SerialNumber mismatch at index %u: exp %02X got %02X\n",
dex, (unsigned)serialNumExp[dex],
(unsigned)foundSerial->Data[dex]);
ourRtn = -1;
}
}
CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1SerialNumber, foundSerial);
CSSM_FREE(signedRootCert->Data);
CSSM_FREE(encCert);
CSSM_FREE(resultSet);
CSSM_FREE(refId.Data);
errOut:
return ourRtn;
}
int main(int argc, char **argv)
{
CSSM_CL_HANDLE clHand; CSSM_CSP_HANDLE cspHand; CSSM_TP_HANDLE tpHand; CSSM_KEY rootPubKey; CSSM_KEY rootPrivKey; CSSM_RETURN crtn;
int arg;
unsigned dex;
int ourRtn = 0;
uint32 keySizeInBits = 512;
CSSM_BOOL doPause = CSSM_FALSE;
CSSM_BOOL writeBlobs = CSSM_FALSE;
CSSM_BOOL quiet = CSSM_FALSE;
for(arg=1; arg<argc; arg++) {
switch(argv[arg][0]) {
case 'w':
writeBlobs = CSSM_TRUE;
break;
case 'q':
quiet = CSSM_TRUE;
break;
case 'p':
doPause = CSSM_TRUE;
break;
default:
usage(argv);
}
}
testStartBanner("certSerialEncodeTest", argc, argv);
clHand = clStartup();
if(clHand == 0) {
return -1;
}
tpHand = tpStartup();
if(tpHand == 0) {
return -1;
}
cspHand = cspStartup();
if(cspHand == 0) {
return -1;
}
crtn = cspGenKeyPair(cspHand,
CSSM_ALGID_RSA,
ROOT_KEY_LABEL,
strlen(ROOT_KEY_LABEL),
keySizeInBits,
&rootPubKey,
CSSM_FALSE, CSSM_KEYUSE_VERIFY,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
&rootPrivKey,
writeBlobs ? CSSM_FALSE : CSSM_TRUE, CSSM_KEYUSE_SIGN,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
CSSM_FALSE);
if(crtn) {
ourRtn = -1;
goto abort;
}
for(dex=0; dex<NUM_SERIAL_NUMS; dex++) {
const SerialNumber *sn = serialNumbers[dex];
if(!quiet) {
printf("...testing serial number 0x%lx\n", (unsigned long)sn->serialIn);
}
ourRtn = doTest(clHand, cspHand, tpHand,
&rootPubKey, &rootPrivKey,
sn->serialIn, sn->expectLen, sn->expect,
quiet, writeBlobs);
if(ourRtn) {
break;
}
if(doPause) {
fpurge(stdin);
printf("Pausing for MallocDebug. a to abort, anything else to continue: ");
if(getchar() == 'a') {
break;
}
}
}
cspFreeKey(cspHand, &rootPubKey);
cspFreeKey(cspHand, &rootPrivKey);
abort:
if(cspHand != 0) {
CSSM_ModuleDetach(cspHand);
}
if(clHand != 0) {
CSSM_ModuleDetach(clHand);
}
if(tpHand != 0) {
CSSM_ModuleDetach(tpHand);
}
if((ourRtn == 0) && !quiet) {
printf("certSerialEncodeTest test succeeded\n");
}
return ourRtn;
}