2 * crlUtils.cpp - CRL CL/TP/DL utilities.
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>
15 #include <security_cdsa_utilities/Schema.h> /* private API */
17 /* crlAddCrlToDb() removed due to build problem; obsoleted in favor of
18 * cuAddCrlToDb() in security_cdsa_utils
20 #define CRL_ADD_TO_DB 0
23 #include <Security/SecCertificatePriv.h> /* private */
24 /* SecInferLabelFromX509Name() */
27 * Update an existing DLDB to be CRL-capable.
29 static CSSM_RETURN
crlAddCrlSchema(
30 CSSM_DL_DB_HANDLE dlDbHand
)
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
);
41 static void crlInferCrlLabel(
42 const CSSM_X509_NAME
*x509Name
,
43 CSSM_DATA
*label
) // not mallocd; contents are
46 /* use private API for common "infer label" logic */
47 const CSSM_DATA
*printValue
= SecInferLabelFromX509Name(x509Name
);
48 if(printValue
== NULL
) {
50 label
->Data
= (uint8
*)"X509 CRL";
59 * Search extensions for specified OID, assumed to have underlying
60 * value type of uint32; returns the value and true if found.
62 static bool crlSearchNumericExtension(
63 const CSSM_X509_EXTENSIONS
*extens
,
67 for(uint32 dex
=0; dex
<extens
->numberOfExtensions
; dex
++) {
68 const CSSM_X509_EXTENSION
*exten
= &extens
->extensions
[dex
];
69 if(!appCompareCssmData(&exten
->extnId
, oid
)) {
72 if(exten
->format
!= CSSM_X509_DATAFORMAT_PARSED
) {
73 printf("***Malformed extension\n");
76 *val
= *((uint32
*)exten
->value
.parsedValue
);
83 * Add a CRL to an existing DL/DB.
85 #define MAX_CRL_ATTRS 8
87 CSSM_RETURN
crlAddCrlToDb(
88 CSSM_DL_DB_HANDLE dlDbHand
,
89 CSSM_CL_HANDLE clHand
,
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
;
97 CSSM_DATA printNameData
;
99 CSSM_DB_UNIQUE_RECORD_PTR recordPtr
;
100 CSSM_DATA_PTR issuer
; // mallocd by CL
101 CSSM_DATA_PTR crlValue
; // ditto
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
;
113 uint32 deltaCrlNumber
;
114 CSSM_DATA crlNumberData
;
115 CSSM_DATA deltaCrlNumberData
;
116 bool crlNumberPresent
= false;
117 bool deltaCrlPresent
= false;
119 /* get normalized issuer name as Issuer attr */
120 crtn
= CSSM_CL_CrlGetFirstFieldValue(clHand
,
122 &CSSMOID_X509V1IssuerName
,
127 printError("CSSM_CL_CrlGetFirstFieldValue(Issuer)", crtn
);
130 CSSM_CL_CrlAbortQuery(clHand
, result
);
132 /* get parsed CRL from the CL */
133 crtn
= CSSM_CL_CrlGetFirstFieldValue(clHand
,
135 &CSSMOID_X509V2CRLSignedCrlCStruct
,
140 printError("CSSM_CL_CrlGetFirstFieldValue(Issuer)", crtn
);
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
;
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
;
153 signedCrl
= (const CSSM_X509_SIGNED_CRL
*)crlValue
->Data
;
154 tbsCrl
= &signedCrl
->tbsCertList
;
156 /* CrlType inferred from version */
157 if(tbsCrl
->version
.Length
== 0) {
158 /* should never happen... */
159 crlType
= CSSM_CRL_TYPE_X_509v1
;
162 uint8 vers
= tbsCrl
->version
.Data
[tbsCrl
->version
.Length
- 1];
165 crlType
= CSSM_CRL_TYPE_X_509v1
;
168 crlType
= CSSM_CRL_TYPE_X_509v2
;
171 printf("***Unknown version in CRL (%u)\n", vers
);
172 crlType
= CSSM_CRL_TYPE_X_509v1
;
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
);
182 /* printName inferred from issuer */
183 crlInferCrlLabel(&tbsCrl
->issuer
, &printNameData
);
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");
191 thisUpdateData
.Data
= (uint8
*)thisUpdate
;
192 thisUpdateData
.Length
= timeLen
;
194 nextUpdate
= x509TimeToCssmTimestring(&tbsCrl
->nextUpdate
, &timeLen
);
195 if(nextUpdate
== NULL
) {
196 printf("***Badly formatted nextUpdate\n");
199 nextUpdateData
.Data
= (uint8
*)nextUpdate
;
200 nextUpdateData
.Length
= timeLen
;
203 /* optional CrlNumber and DeltaCrlNumber */
204 if(crlSearchNumericExtension(&tbsCrl
->extensions
,
207 crlNumberData
.Data
= (uint8
*)&crlNumber
;
208 crlNumberData
.Length
= sizeof(uint32
);
209 crlNumberPresent
= true;
211 if(crlSearchNumericExtension(&tbsCrl
->extensions
,
212 &CSSMOID_DeltaCrlIndicator
,
214 deltaCrlNumberData
.Data
= (uint8
*)&deltaCrlNumber
;
215 deltaCrlNumberData
.Length
= sizeof(uint32
);
216 deltaCrlPresent
= true;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
279 recordAttrs
.DataRecordType
= CSSM_DL_DB_RECORD_X509_CRL
;
280 recordAttrs
.SemanticInformation
= 0;
281 recordAttrs
.NumberOfAttributes
= attr
- attrs
;
282 recordAttrs
.AttributeData
= attrs
;
284 crtn
= CSSM_DL_DataInsert(dlDbHand
,
285 CSSM_DL_DB_RECORD_X509_CRL
,
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
,
303 printError("CSSM_DL_DataInsert", crtn
);
306 CSSM_DL_FreeUniqueRecord(dlDbHand
, recordPtr
);
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
,
318 #endif /* CRL_ADD_TO_DB */