+/*
+ * getCachedFields.cpp
+ *
+ * do a "CSSM_CL_CertGetFirstCachedFieldValue" 'n' times on a known good
+ * cert; with a variety of fields; verify same results each time.
+ */
+#include "testParams.h"
+#include <Security/cssm.h>
+#include <utilLib/common.h>
+#include <utilLib/cspwrap.h>
+#include <clAppUtils/clutils.h>
+#include <clAppUtils/tpUtils.h>
+#include <security_cdsa_utils/cuFileIo.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <Security/oidscert.h>
+#include <Security/x509defs.h>
+#include <Security/oidsattr.h>
+
+#define DO_PAUSE 0
+
+//static const char *CERT_FILE = "serverpremium.crt";
+static const char *CERT_FILE = "mypage.apple_v3.100.cer";
+
+#define NUM_INNER_LOOPS 10
+
+/* common data, our known good cert, shared by all threads */
+static unsigned char *certData = NULL;
+static unsigned certLength = 0;
+
+/*
+ * Hard coded list of field OIDs to fetch
+ */
+static const CSSM_OID *fieldOids[] =
+{
+ &CSSMOID_X509V1Version,
+ &CSSMOID_X509V1SubjectName,
+ &CSSMOID_X509V1IssuerName,
+ &CSSMOID_X509V1SerialNumber,
+ &CSSMOID_X509V1ValidityNotBefore,
+ &CSSMOID_X509V1ValidityNotAfter,
+ &CSSMOID_X509V1Signature
+ /* etc. */
+};
+#define NUM_FIELD_OIDS (sizeof(fieldOids) / sizeof(CSSM_OID *))
+
+
+/* read in our known good cert file, just once */
+int getCachedFieldsInit(TestParams *testParams)
+{
+ if(certData != NULL) {
+ return 0;
+ }
+ if(testParams->verbose) {
+ printf("getFields thread %d: reading cert file %s...\n",
+ testParams->threadNum, CERT_FILE);
+ }
+ if(readFile(CERT_FILE, &certData, &certLength)) {
+ printf("Error reading %s; aborting\n", CERT_FILE);
+ printf("***This test must be run from the clxutils/threadTest directory.\n");
+ return 1;
+ }
+ return 0;
+}
+
+static int compareFields(
+ const CSSM_OID *oid,
+ const CSSM_DATA *val1,
+ const CSSM_DATA *val2)
+{
+ /* data length must match */
+ if(val1->Length != val2->Length) {
+ printf("***FieldValue.Length miscompare\n");
+ return 1;
+ }
+
+ /*
+ * The hard part. Most OIDs have some kind of C struct pointer in their
+ * FieldValue.Data pointers, so comparison is on an oid-by-oid basis.
+ * We'll just do the easy ones, and the ones we suspect may be causing
+ * trouble.
+ */
+ if(appCompareCssmData(oid, &CSSMOID_X509V1Version)) {
+ if(!appCompareCssmData(val1, val2)) {
+ printf("***CSSMOID_X509V1Version mismatch\n");
+ return 1;
+ }
+ }
+ else if(appCompareCssmData(oid, &CSSMOID_X509V1SerialNumber)) {
+ if(!appCompareCssmData(val1, val2)) {
+ printf("***CSSMOID_X509V1SerialNumber mismatch\n");
+ return 1;
+ }
+ }
+ else if(appCompareCssmData(oid, &CSSMOID_X509V1ValidityNotBefore)) {
+ CSSM_X509_TIME *cssmTime1 = (CSSM_X509_TIME *)val1->Data;
+ CSSM_X509_TIME *cssmTime2 = (CSSM_X509_TIME *)val2->Data;
+ if(!appCompareCssmData(&cssmTime1->time, &cssmTime2->time)) {
+ printf("***CSSMOID_X509V1ValidityNotBefore mismatch\n");
+ return 1;
+ }
+ }
+ else if(appCompareCssmData(oid, &CSSMOID_X509V1ValidityNotAfter)) {
+ CSSM_X509_TIME *cssmTime1 = (CSSM_X509_TIME *)val1->Data;
+ CSSM_X509_TIME *cssmTime2 = (CSSM_X509_TIME *)val2->Data;
+ if(!appCompareCssmData(&cssmTime1->time, &cssmTime2->time)) {
+ printf("***CSSMOID_X509V1ValidityNotAfter mismatch\n");
+ return 1;
+ }
+ }
+ else if(appCompareCssmData(oid, &CSSMOID_X509V1CertificateIssuerUniqueId)) {
+ if(!appCompareCssmData(val1, val2)) {
+ printf("***CSSMOID_X509V1CertificateIssuerUniqueId mismatch\n");
+ return 1;
+ }
+ }
+ else if(appCompareCssmData(oid, &CSSMOID_X509V1CertificateSubjectUniqueId)) {
+ if(!appCompareCssmData(val1, val2)) {
+ printf("***CSSMOID_X509V1CertificateSubjectUniqueId mismatch\n");
+ return 1;
+ }
+ }
+ else if(appCompareCssmData(oid, &CSSMOID_X509V1Signature)) {
+ if(!appCompareCssmData(val1, val2)) {
+ printf("***CSSMOID_X509V1Signature mismatch\n");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int checkOneField(
+ CSSM_CL_HANDLE clHand,
+ CSSM_HANDLE cacheHand1,
+ CSSM_HANDLE cacheHand2,
+ const CSSM_OID *fieldOid)
+{
+ CSSM_DATA_PTR fieldData1 = NULL;
+ CSSM_DATA_PTR fieldData2 = NULL;
+ CSSM_RETURN crtn;
+ CSSM_HANDLE resultHand1 = 0;
+ CSSM_HANDLE resultHand2 = 0;
+ uint32 numFields = 0;
+ int rtn;
+
+ crtn = CSSM_CL_CertGetFirstCachedFieldValue(
+ clHand,
+ cacheHand1,
+ fieldOid,
+ &resultHand1,
+ &numFields,
+ &fieldData1);
+ if(crtn) {
+ return crtn;
+ }
+ if(numFields != 1) {
+ printf("Fiedl not present; try another cert\n");
+ return 1;
+ }
+ crtn = CSSM_CL_CertGetFirstCachedFieldValue(
+ clHand,
+ cacheHand2,
+ fieldOid,
+ &resultHand2,
+ &numFields,
+ &fieldData2);
+ if(crtn) {
+ return crtn;
+ }
+ rtn = compareFields(fieldOid, fieldData1, fieldData2);
+ CSSM_CL_CertAbortQuery(clHand, resultHand1);
+ CSSM_CL_CertAbortQuery(clHand, resultHand2);
+ CSSM_CL_FreeFieldValue(clHand, fieldOid, fieldData1);
+ CSSM_CL_FreeFieldValue(clHand, fieldOid, fieldData2);
+ return rtn;
+}
+
+int getCachedFields(TestParams *testParams)
+{
+ CSSM_RETURN crtn;
+ CSSM_HANDLE cacheHand1;
+ CSSM_HANDLE cacheHand2;
+ unsigned fieldNum;
+ unsigned loopNum;
+ CSSM_DATA cert;
+
+ for(loopNum=0; loopNum<testParams->numLoops; loopNum++) {
+ if(testParams->verbose) {
+ printf("getCachedFields loop %d\n", loopNum);
+ }
+ else if(!testParams->quiet) {
+ printChar(testParams->progressChar);
+ }
+
+ /* get two cached certs */
+ cert.Data = certData;
+ cert.Length = certLength;
+ crtn = CSSM_CL_CertCache(testParams->clHand, &cert, &cacheHand1);
+ if(crtn) {
+ printError("CSSM_CL_CertCache(1)", crtn);
+ return 1;
+ }
+ crtn = CSSM_CL_CertCache(testParams->clHand, &cert, &cacheHand2);
+ if(crtn) {
+ printError("CSSM_CL_CertCache(2)", crtn);
+ return 1;
+ }
+
+ /* grind thru the known OIDs */
+ for(fieldNum=0; fieldNum<NUM_FIELD_OIDS; fieldNum++) {
+ int rtn = checkOneField(testParams->clHand,
+ cacheHand1,
+ cacheHand2,
+ fieldOids[fieldNum]);
+ if(rtn) {
+ return 1;
+ }
+ }
+ CSSM_CL_CertAbortCache(testParams->clHand, cacheHand1);
+ CSSM_CL_CertAbortCache(testParams->clHand, cacheHand2);
+ /* leak debug */
+ #if DO_PAUSE
+ fpurge(stdin);
+ printf("Hit CR to continue: ");
+ getchar();
+ #endif
+ } /* outer loop */
+ return 0;
+}