X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/clxutils/certSerialEncodeTest/certSerialEncodeTest.cpp diff --git a/SecurityTests/clxutils/certSerialEncodeTest/certSerialEncodeTest.cpp b/SecurityTests/clxutils/certSerialEncodeTest/certSerialEncodeTest.cpp new file mode 100644 index 00000000..2027dde6 --- /dev/null +++ b/SecurityTests/clxutils/certSerialEncodeTest/certSerialEncodeTest.cpp @@ -0,0 +1,358 @@ +/* Copyright (c) 2006 Apple Computer, Inc. + * + * certSerialEncodeTest.cpp + * + * Verify proper encoding of unsigned integer as a DER_encoded signed integer. + * Verifies Radar 4471281. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SUBJ_KEY_LABEL "subjectKey" +#define ROOT_KEY_LABEL "rootKey" +/* default key and signature algorithm */ +#define SIG_ALG_DEFAULT CSSM_ALGID_SHA1WithRSA +#define SIG_OID_DEFAULT CSSMOID_SHA1WithRSA +#define KEY_ALG_DEFAULT CSSM_ALGID_RSA + +/* for write certs/keys option */ +#define ROOT_CERT_FILE_NAME "ssRootCert.cer" +#define SUBJ_CERT_FILE_NAME "ssSubjCert.cer" + +/* public key in ref form, TP supports this as of 1/30/02 */ +#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); +} + +/* + * RDN components + */ +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)) + +/* test cases */ +typedef struct { + uint32 serialIn; /* --> CSSM_TP_SubmitCredRequest */ + CSSM_SIZE expectLen; + const uint8 *expect; +} SerialNumber; + +/* 0x7f */ +static const uint8 sn0_Data[1] = {0x7f}; +static const SerialNumber sn0 = {0x7f, 1, sn0_Data }; + +/* 0x80 */ +static const uint8 sn1_Data[2] = {0x00, 0x80}; +static const SerialNumber sn1 = {0x80, 2, sn1_Data }; + +/* 0x7ff */ +static const uint8 sn2_Data[2] = {0x07, 0xff}; +static const SerialNumber sn2 = {0x7ff, 2, sn2_Data }; + +/* 0x80ff */ +static const uint8 sn3_Data[3] = {0x00, 0x80, 0xff}; +static const SerialNumber sn3 = {0x80ff, 3, sn3_Data }; + +/* 0xfffffff */ +static const uint8 sn4_Data[4] = {0x0f, 0xff, 0xff, 0xff}; +static const SerialNumber sn4 = {0xfffffff, 4, sn4_Data }; + +/* 0x0fffffff */ +static const uint8 sn5_Data[4] = {0x0f, 0xff, 0xff, 0xff}; +static const SerialNumber sn5 = {0x0fffffff, 4, sn5_Data }; + +/* 0x80000000 */ +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, // CL handle + CSSM_CSP_HANDLE cspHand, // CSP handle + CSSM_TP_HANDLE tpHand, // TP handle + 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; // mallocd by CSSM_TP_SubmitCredRequest + 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; + + /* certReq for root */ + 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; // now + certReq.notAfter = 10000; // seconds from now + certReq.numExtensions = 0; + certReq.extensions = NULL; + + reqSet.NumberOfRequests = 1; + reqSet.Requests = &certReq; + + /* a big CSSM_TP_CALLERAUTH_CONTEXT just to specify an OID */ + 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; + + /* generate root cert */ + if(!quiet) { + printf("Creating root cert...\n"); + } + crtn = CSSM_TP_SubmitCredRequest(tpHand, + NULL, // PreferredAuthority + 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, // CallerAuthCredentials + &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); + } + + /* make sure it self-verifies */ + crtn = CSSM_CL_CertVerify(clHand, 0 /* CCHandle */, + signedRootCert, signedRootCert, + NULL, 0); + if(crtn) { + cssmPerror("CSSM_CL_CertVerify", crtn); + printf("***Created cert does not self-verify\n"); + ourRtn = -1; + goto errOut; + } + + /* extract the field we're interested in verifying */ + 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; dexData[dex] != serialNumExp[dex]) { + printf("***SerialNumber mismatch at index %u: exp %02X got %02X\n", + dex, (unsigned)serialNumExp[dex], + (unsigned)foundSerial->Data[dex]); + ourRtn = -1; + } + } + /* free retrieved serial number and the result set itself */ + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1SerialNumber, foundSerial); + CSSM_FREE(signedRootCert->Data); + CSSM_FREE(encCert); + CSSM_FREE(resultSet); + /* Per the spec, this is supposed to be Opaque to us and the TP is supposed to free + * it when it goes out of scope...but libsecurity_keychains's + * CertificateRequest::submitDotMac() frees this...that would have to change + * in order for the TP to free this properly. Someday maybe. No big deal. + */ + CSSM_FREE(refId.Data); +errOut: + return ourRtn; +} + +int main(int argc, char **argv) +{ + CSSM_CL_HANDLE clHand; // CL handle + CSSM_CSP_HANDLE cspHand; // CSP handle + CSSM_TP_HANDLE tpHand; // TP handle + CSSM_KEY rootPubKey; // root's RSA public key blob + CSSM_KEY rootPrivKey; // root's RSA private key - ref format + CSSM_RETURN crtn; + int arg; + unsigned dex; + int ourRtn = 0; + uint32 keySizeInBits = 512; + CSSM_BOOL doPause = CSSM_FALSE; + + /* user-spec'd variables */ + CSSM_BOOL writeBlobs = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + + for(arg=1; argserialIn); + } + 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; +} + +