]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/clAppUtils/crlUtils.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / SecurityTests / clxutils / clAppUtils / crlUtils.cpp
1 /*
2 * crlUtils.cpp - CRL CL/TP/DL utilities.
3 */
4 #include <Security/cssmtype.h>
5 #include <Security/cssmapi.h>
6 #include <utilLib/common.h>
7 #include <clAppUtils/timeStr.h>
8 #include <clAppUtils/crlUtils.h>
9 #include <Security/oidsattr.h>
10 #include <Security/oidscert.h>
11 #include <Security/oidscrl.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <security_cdsa_utilities/Schema.h> /* private API */
16
17 /* crlAddCrlToDb() removed due to build problem; obsoleted in favor of
18 * cuAddCrlToDb() in security_cdsa_utils
19 */
20 #define CRL_ADD_TO_DB 0
21
22 #if CRL_ADD_TO_DB
23 #include <Security/SecCertificatePriv.h> /* private */
24 /* SecInferLabelFromX509Name() */
25
26 /*
27 * Update an existing DLDB to be CRL-capable.
28 */
29 static CSSM_RETURN crlAddCrlSchema(
30 CSSM_DL_DB_HANDLE dlDbHand)
31 {
32 return CSSM_DL_CreateRelation(dlDbHand,
33 CSSM_DL_DB_RECORD_X509_CRL,
34 "CSSM_DL_DB_RECORD_X509_CRL",
35 Security::KeychainCore::Schema::X509CrlSchemaAttributeCount,
36 Security::KeychainCore::Schema::X509CrlSchemaAttributeList,
37 Security::KeychainCore::Schema::X509CrlSchemaIndexCount,
38 Security::KeychainCore::Schema::X509CrlSchemaIndexList);
39 }
40
41 static void crlInferCrlLabel(
42 const CSSM_X509_NAME *x509Name,
43 CSSM_DATA *label) // not mallocd; contents are
44 // from the x509Name
45 {
46 /* use private API for common "infer label" logic */
47 const CSSM_DATA *printValue = SecInferLabelFromX509Name(x509Name);
48 if(printValue == NULL) {
49 /* punt! */
50 label->Data = (uint8 *)"X509 CRL";
51 label->Length = 8;
52 }
53 else {
54 *label = *printValue;
55 }
56 }
57
58 /*
59 * Search extensions for specified OID, assumed to have underlying
60 * value type of uint32; returns the value and true if found.
61 */
62 static bool crlSearchNumericExtension(
63 const CSSM_X509_EXTENSIONS *extens,
64 const CSSM_OID *oid,
65 uint32 *val)
66 {
67 for(uint32 dex=0; dex<extens->numberOfExtensions; dex++) {
68 const CSSM_X509_EXTENSION *exten = &extens->extensions[dex];
69 if(!appCompareCssmData(&exten->extnId, oid)) {
70 continue;
71 }
72 if(exten->format != CSSM_X509_DATAFORMAT_PARSED) {
73 printf("***Malformed extension\n");
74 continue;
75 }
76 *val = *((uint32 *)exten->value.parsedValue);
77 return true;
78 }
79 return false;
80 }
81
82 /*
83 * Add a CRL to an existing DL/DB.
84 */
85 #define MAX_CRL_ATTRS 8
86
87 CSSM_RETURN crlAddCrlToDb(
88 CSSM_DL_DB_HANDLE dlDbHand,
89 CSSM_CL_HANDLE clHand,
90 const CSSM_DATA *crl)
91 {
92 CSSM_DB_ATTRIBUTE_DATA attrs[MAX_CRL_ATTRS];
93 CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs;
94 CSSM_DB_ATTRIBUTE_DATA_PTR attr = &attrs[0];
95 CSSM_DATA crlTypeData;
96 CSSM_DATA crlEncData;
97 CSSM_DATA printNameData;
98 CSSM_RETURN crtn;
99 CSSM_DB_UNIQUE_RECORD_PTR recordPtr;
100 CSSM_DATA_PTR issuer; // mallocd by CL
101 CSSM_DATA_PTR crlValue; // ditto
102 uint32 numFields;
103 CSSM_HANDLE result;
104 CSSM_CRL_ENCODING crlEnc = CSSM_CRL_ENCODING_DER;
105 const CSSM_X509_SIGNED_CRL *signedCrl;
106 const CSSM_X509_TBS_CERTLIST *tbsCrl;
107 CSSM_CRL_TYPE crlType;
108 CSSM_DATA thisUpdateData = {0, NULL};
109 CSSM_DATA nextUpdateData = {0, NULL};
110 char *thisUpdate, *nextUpdate;
111 unsigned timeLen;
112 uint32 crlNumber;
113 uint32 deltaCrlNumber;
114 CSSM_DATA crlNumberData;
115 CSSM_DATA deltaCrlNumberData;
116 bool crlNumberPresent = false;
117 bool deltaCrlPresent = false;
118
119 /* get normalized issuer name as Issuer attr */
120 crtn = CSSM_CL_CrlGetFirstFieldValue(clHand,
121 crl,
122 &CSSMOID_X509V1IssuerName,
123 &result,
124 &numFields,
125 &issuer);
126 if(crtn) {
127 printError("CSSM_CL_CrlGetFirstFieldValue(Issuer)", crtn);
128 return crtn;
129 }
130 CSSM_CL_CrlAbortQuery(clHand, result);
131
132 /* get parsed CRL from the CL */
133 crtn = CSSM_CL_CrlGetFirstFieldValue(clHand,
134 crl,
135 &CSSMOID_X509V2CRLSignedCrlCStruct,
136 &result,
137 &numFields,
138 &crlValue);
139 if(crtn) {
140 printError("CSSM_CL_CrlGetFirstFieldValue(Issuer)", crtn);
141 return crtn;
142 }
143 CSSM_CL_CrlAbortQuery(clHand, result);
144 if(crlValue == NULL) {
145 printf("***CSSM_CL_CrlGetFirstFieldValue: value error (1)\n");
146 return CSSMERR_CL_INVALID_CRL_POINTER;
147 }
148 if((crlValue->Data == NULL) ||
149 (crlValue->Length != sizeof(CSSM_X509_SIGNED_CRL))) {
150 printf("***CSSM_CL_CrlGetFirstFieldValue: value error (2)\n");
151 return CSSMERR_CL_INVALID_CRL_POINTER;
152 }
153 signedCrl = (const CSSM_X509_SIGNED_CRL *)crlValue->Data;
154 tbsCrl = &signedCrl->tbsCertList;
155
156 /* CrlType inferred from version */
157 if(tbsCrl->version.Length == 0) {
158 /* should never happen... */
159 crlType = CSSM_CRL_TYPE_X_509v1;
160 }
161 else {
162 uint8 vers = tbsCrl->version.Data[tbsCrl->version.Length - 1];
163 switch(vers) {
164 case 0:
165 crlType = CSSM_CRL_TYPE_X_509v1;
166 break;
167 case 1:
168 crlType = CSSM_CRL_TYPE_X_509v2;
169 break;
170 default:
171 printf("***Unknown version in CRL (%u)\n", vers);
172 crlType = CSSM_CRL_TYPE_X_509v1;
173 break;
174 }
175 }
176 crlTypeData.Data = (uint8 *)&crlType;
177 crlTypeData.Length = sizeof(CSSM_CRL_TYPE);
178 /* encoding more-or-less assumed here */
179 crlEncData.Data = (uint8 *)&crlEnc;
180 crlEncData.Length = sizeof(CSSM_CRL_ENCODING);
181
182 /* printName inferred from issuer */
183 crlInferCrlLabel(&tbsCrl->issuer, &printNameData);
184
185 /* cook up CSSM_TIMESTRING versions of this/next update */
186 thisUpdate = x509TimeToCssmTimestring(&tbsCrl->thisUpdate, &timeLen);
187 if(thisUpdate == NULL) {
188 printf("***Badly formatted thisUpdate\n");
189 }
190 else {
191 thisUpdateData.Data = (uint8 *)thisUpdate;
192 thisUpdateData.Length = timeLen;
193 }
194 nextUpdate = x509TimeToCssmTimestring(&tbsCrl->nextUpdate, &timeLen);
195 if(nextUpdate == NULL) {
196 printf("***Badly formatted nextUpdate\n");
197 }
198 else {
199 nextUpdateData.Data = (uint8 *)nextUpdate;
200 nextUpdateData.Length = timeLen;
201 }
202
203 /* optional CrlNumber and DeltaCrlNumber */
204 if(crlSearchNumericExtension(&tbsCrl->extensions,
205 &CSSMOID_CrlNumber,
206 &crlNumber)) {
207 crlNumberData.Data = (uint8 *)&crlNumber;
208 crlNumberData.Length = sizeof(uint32);
209 crlNumberPresent = true;
210 }
211 if(crlSearchNumericExtension(&tbsCrl->extensions,
212 &CSSMOID_DeltaCrlIndicator,
213 &deltaCrlNumber)) {
214 deltaCrlNumberData.Data = (uint8 *)&deltaCrlNumber;
215 deltaCrlNumberData.Length = sizeof(uint32);
216 deltaCrlPresent = true;
217 }
218 /* we spec six attributes, skipping alias and URI */
219 attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
220 attr->Info.Label.AttributeName = "CrlType";
221 attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32;
222 attr->NumberOfValues = 1;
223 attr->Value = &crlTypeData;
224 attr++;
225
226 attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
227 attr->Info.Label.AttributeName = "CrlEncoding";
228 attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32;
229 attr->NumberOfValues = 1;
230 attr->Value = &crlEncData;
231 attr++;
232
233 attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
234 attr->Info.Label.AttributeName = "PrintName";
235 attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
236 attr->NumberOfValues = 1;
237 attr->Value = &printNameData;
238 attr++;
239
240 attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
241 attr->Info.Label.AttributeName = "Issuer";
242 attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
243 attr->NumberOfValues = 1;
244 attr->Value = issuer;
245 attr++;
246
247 attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
248 attr->Info.Label.AttributeName = "ThisUpdate";
249 attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
250 attr->NumberOfValues = 1;
251 attr->Value = &thisUpdateData;
252 attr++;
253
254 attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
255 attr->Info.Label.AttributeName = "NextUpdate";
256 attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
257 attr->NumberOfValues = 1;
258 attr->Value = &nextUpdateData;
259 attr++;
260
261 /* now the optional attributes */
262 if(crlNumberPresent) {
263 attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
264 attr->Info.Label.AttributeName = "CrlNumber";
265 attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32;
266 attr->NumberOfValues = 1;
267 attr->Value = &crlNumberData;
268 attr++;
269 }
270 if(deltaCrlPresent) {
271 attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
272 attr->Info.Label.AttributeName = "DeltaCrlNumber";
273 attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32;
274 attr->NumberOfValues = 1;
275 attr->Value = &deltaCrlNumberData;
276 attr++;
277 }
278
279 recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_X509_CRL;
280 recordAttrs.SemanticInformation = 0;
281 recordAttrs.NumberOfAttributes = attr - attrs;
282 recordAttrs.AttributeData = attrs;
283
284 crtn = CSSM_DL_DataInsert(dlDbHand,
285 CSSM_DL_DB_RECORD_X509_CRL,
286 &recordAttrs,
287 crl,
288 &recordPtr);
289 if(crtn == CSSMERR_DL_INVALID_RECORDTYPE) {
290 /* gross hack of inserting this "new" schema that
291 * Keychain didn't specify */
292 crtn = crlAddCrlSchema(dlDbHand);
293 if(crtn == CSSM_OK) {
294 /* Retry with a fully capable DLDB */
295 crtn = CSSM_DL_DataInsert(dlDbHand,
296 CSSM_DL_DB_RECORD_X509_CRL,
297 &recordAttrs,
298 crl,
299 &recordPtr);
300 }
301 }
302 if(crtn) {
303 printError("CSSM_DL_DataInsert", crtn);
304 }
305 else {
306 CSSM_DL_FreeUniqueRecord(dlDbHand, recordPtr);
307 }
308
309 /* free all the stuff we allocated to get here */
310 CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1IssuerName, issuer);
311 CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V2CRLSignedCrlCStruct,
312 crlValue);
313 free(thisUpdate);
314 free(nextUpdate);
315 return crtn;
316 }
317
318 #endif /* CRL_ADD_TO_DB */