1 /*
2  * tpVerifyParsed.cpp - wrapper for CSSM_TP_CertGroupVerify using parsd anchors.
3  */
4
5#include <Security/Security.h>
6#include "tpVerifyParsed.h"
7#include <Security/SecRootCertStorePriv.h>
8#include <Security/RootCertCachePriv.h>
9#include <string.h>
10#include <stdlib.h>
11#include <stdio.h>
12#include <clAppUtils/CertParser.h>
13#include <utilLib/common.h>
14
15/*
16 * The main task is converting a set of CSSM_DATA-style anchors into a
17 * SecParsedRootCertArrayRef.
18 */
19
20/* raw cert --> SecParsedRootCert */
21static int parseRootCert(
22	CSSM_CL_HANDLE clHand,
23	const CSSM_DATA &certData,
24	SecParsedRootCert &parsedRoot)
25{
26	try {
27		CertParser cert(clHand, certData);
28		uint32 len = 0;
29		const void *p = cert.fieldForOid(CSSMOID_X509V1SubjectName, len);
30		appCopyData(p, len, &parsedRoot.subject);
31
32		/* skip key and times, I think they are going away */
33		appCopyCssmData(&certData, &parsedRoot.certData);
34		return 0;
35	}
36	catch(...) {
37		printf("CertParser threw!\n");
38		return -1;
39	}
40}
41
42static void freeParsedRoot(
43	SecParsedRootCert &parsedRoot)
44{
45	if(parsedRoot.subject.Data) {
46		CSSM_FREE(parsedRoot.subject.Data);
47	}
48	if(parsedRoot.certData.Data) {
49		CSSM_FREE(parsedRoot.certData.Data);
50	}
51}
52
53static int createParsedCertArray(
54	CSSM_CL_HANDLE	clHand,
55	unsigned		numAnchorCerts,
56	CSSM_DATA_PTR	anchorCerts,
57	SecParsedRootCertArrayRef *arrayRef)		// RETURNED
58{
59	SecParsedRootCertArray *outArray = (SecParsedRootCertArray *)malloc(sizeof(*outArray));
60	memset(outArray, 0, sizeof(*outArray));
61	unsigned len = sizeof(SecParsedRootCert) * numAnchorCerts;
62	outArray->roots = (SecParsedRootCert *)malloc(len);
63	memset(outArray->roots, 0, len);
64	for(unsigned dex=0; dex<numAnchorCerts; dex++) {
65		if(parseRootCert(clHand, anchorCerts[dex], outArray->roots[dex])) {
66			return -1;
67		}
68	}
69	outArray->numRoots = numAnchorCerts;
70	*arrayRef = outArray;
71	return 0;
72}
73
74static void freeParsedCertArray(
75	SecParsedRootCertArrayRef arrayRef)
76{
77	for(unsigned dex=0; dex<arrayRef->numRoots; dex++) {
78		freeParsedRoot(arrayRef->roots[dex]);
79	}
80	free(arrayRef->roots);
81	free((void *)arrayRef);
82}
83
84CSSM_RETURN tpCertGroupVerifyParsed(
85	CSSM_TP_HANDLE						tpHand,
86	CSSM_CL_HANDLE						clHand,
87	CSSM_CSP_HANDLE 					cspHand,
88	CSSM_DL_DB_LIST_PTR					dbListPtr,
89	const CSSM_OID						*policy,		// optional
90	const CSSM_DATA						*fieldOpts,		// optional
91	const CSSM_DATA						*actionData,	// optional
92	void								*policyOpts,
93	const CSSM_CERTGROUP 				*certGroup,
94	CSSM_DATA_PTR						anchorCerts,
95	unsigned							numAnchorCerts,
96	CSSM_TP_STOP_ON						stopOn,		// CSSM_TP_STOP_ON_POLICY, etc.
97	CSSM_TIMESTRING						cssmTimeStr,// optional
98	CSSM_TP_VERIFY_CONTEXT_RESULT_PTR	result)		// optional, RETURNED
99{
100	/* main job is building a CSSM_TP_VERIFY_CONTEXT and its components */
101	CSSM_TP_VERIFY_CONTEXT		vfyCtx;
102	CSSM_TP_CALLERAUTH_CONTEXT	authCtx;
103
104	memset(&vfyCtx, 0, sizeof(CSSM_TP_VERIFY_CONTEXT));
105	vfyCtx.Action = CSSM_TP_ACTION_DEFAULT;
106	if(actionData) {
107		vfyCtx.ActionData = *actionData;
108	}
109	else {
110		vfyCtx.ActionData.Data = NULL;
111		vfyCtx.ActionData.Length = 0;
112	}
113	vfyCtx.Cred = &authCtx;
114
115	/* CSSM_TP_CALLERAUTH_CONTEXT components */
116	/*
117		typedef struct cssm_tp_callerauth_context {
118			CSSM_TP_POLICYINFO Policy;
119			CSSM_TIMESTRING VerifyTime;
120			CSSM_TP_STOP_ON VerificationAbortOn;
121			CSSM_TP_VERIFICATION_RESULTS_CALLBACK CallbackWithVerifiedCert;
122			uint32 NumberOfAnchorCerts;
123			CSSM_DATA_PTR AnchorCerts;
124			CSSM_DL_DB_LIST_PTR DBList;
125			CSSM_ACCESS_CREDENTIALS_PTR CallerCredentials;
126		} CSSM_TP_CALLERAUTH_CONTEXT, *CSSM_TP_CALLERAUTH_CONTEXT_PTR;
127	*/
128	/* zero or one policy here */
129	CSSM_FIELD	policyId;
130	if(policy != NULL) {
131		policyId.FieldOid = (CSSM_OID)*policy;
132		authCtx.Policy.NumberOfPolicyIds = 1;
133		authCtx.Policy.PolicyIds = &policyId;
134		if(fieldOpts != NULL) {
135			policyId.FieldValue = *fieldOpts;
136		}
137		else {
138			policyId.FieldValue.Data = NULL;
139			policyId.FieldValue.Length = 0;
140		}
141	}
142	else {
143		authCtx.Policy.NumberOfPolicyIds = 0;
144		authCtx.Policy.PolicyIds = NULL;
145	}
146	authCtx.Policy.PolicyControl = policyOpts;
147	authCtx.VerifyTime = cssmTimeStr;			// may be NULL
148	authCtx.VerificationAbortOn = stopOn;
149	authCtx.CallbackWithVerifiedCert = NULL;
150
151	/* here's the difference between this and tpCertGroupVerify */
152	SecParsedRootCertArrayRef arrayRef = NULL;
153	if(numAnchorCerts) {
154		if(createParsedCertArray(clHand, numAnchorCerts, anchorCerts, &arrayRef)) {
155			return -1;
156		}
157		authCtx.NumberOfAnchorCerts = APPLE_TP_PARSED_ANCHOR_INDICATOR;
158		authCtx.AnchorCerts = (CSSM_DATA_PTR)arrayRef;
159	}
160	else {
161		authCtx.NumberOfAnchorCerts = 0;
162		authCtx.AnchorCerts = NULL;
163	}
164	authCtx.DBList = dbListPtr;
165	authCtx.CallerCredentials = NULL;
166
167	CSSM_RETURN crtn = CSSM_TP_CertGroupVerify(tpHand,
168		clHand,
169		cspHand,
170		certGroup,
171		&vfyCtx,
172		result);
173
174	if(arrayRef) {
175		freeParsedCertArray(arrayRef);
176	}
177	return crtn;
178}
179