]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. | |
3 | * | |
4 | * The contents of this file constitute Original Code as defined in and are | |
5 | * subject to the Apple Public Source License Version 1.2 (the 'License'). | |
6 | * You may not use this file except in compliance with the License. Please obtain | |
7 | * a copy of the License at http://www.apple.com/publicsource and read it before | |
8 | * using this file. | |
9 | * | |
10 | * This Original Code and all software distributed under the License are | |
11 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS | |
12 | * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT | |
13 | * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | |
14 | * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the | |
15 | * specific language governing rights and limitations under the License. | |
16 | */ | |
17 | ||
18 | ||
19 | // | |
20 | // Session_Cert.cpp - cert-related session functions. | |
21 | // | |
22 | ||
23 | #include "AppleX509CLSession.h" | |
24 | #include "DecodedCert.h" | |
25 | #include "DecodedCrl.h" | |
26 | #include "CLCachedEntry.h" | |
27 | #include "cldebugging.h" | |
28 | #include <Security/oidscert.h> | |
29 | ||
30 | void | |
31 | AppleX509CLSession::CertDescribeFormat( | |
32 | uint32 &NumberOfFields, | |
33 | CSSM_OID_PTR &OidList) | |
34 | { | |
35 | DecodedCert::describeFormat(*this, NumberOfFields, OidList); | |
36 | } | |
37 | ||
38 | void | |
39 | AppleX509CLSession::CertGetAllFields( | |
40 | const CssmData &Cert, | |
41 | uint32 &NumberOfFields, | |
42 | CSSM_FIELD_PTR &CertFields) | |
43 | { | |
44 | DecodedCert decodedCert(*this, Cert); | |
45 | decodedCert.getAllParsedCertFields(NumberOfFields, CertFields); | |
46 | } | |
47 | ||
48 | ||
49 | CSSM_HANDLE | |
50 | AppleX509CLSession::CertGetFirstFieldValue( | |
51 | const CssmData &EncodedCert, | |
52 | const CssmData &CertField, | |
53 | uint32 &NumberOfMatchedFields, | |
54 | CSSM_DATA_PTR &Value) | |
55 | { | |
56 | NumberOfMatchedFields = 0; | |
57 | Value = NULL; | |
58 | CssmAutoData aData(*this); | |
59 | ||
60 | DecodedCert *decodedCert = new DecodedCert(*this, EncodedCert); | |
61 | uint32 numMatches; | |
62 | ||
63 | /* this returns false if field not there, throws on bad OID */ | |
64 | bool brtn; | |
65 | try { | |
66 | brtn = decodedCert->getCertFieldData(CertField, | |
67 | 0, // index | |
68 | numMatches, | |
69 | aData); | |
70 | } | |
71 | catch (...) { | |
72 | delete decodedCert; | |
73 | throw; | |
74 | } | |
75 | if(!brtn) { | |
76 | delete decodedCert; | |
77 | return CSSM_INVALID_HANDLE; | |
78 | } | |
79 | ||
80 | /* cook up a CLCachedCert, stash it in cache */ | |
81 | CLCachedCert *cachedCert = new CLCachedCert(*decodedCert); | |
82 | cacheMap.addEntry(*cachedCert, cachedCert->handle()); | |
83 | ||
84 | /* cook up a CLQuery, stash it */ | |
85 | CLQuery *query = new CLQuery( | |
86 | CLQ_Cert, | |
87 | CertField, | |
88 | numMatches, | |
89 | false, // isFromCache | |
90 | cachedCert->handle()); | |
91 | queryMap.addEntry(*query, query->handle()); | |
92 | ||
93 | /* success - copy field data to outgoing Value */ | |
94 | Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); | |
95 | *Value = aData.release(); | |
96 | NumberOfMatchedFields = numMatches; | |
97 | return query->handle(); | |
98 | } | |
99 | ||
100 | ||
101 | bool | |
102 | AppleX509CLSession::CertGetNextFieldValue( | |
103 | CSSM_HANDLE ResultsHandle, | |
104 | CSSM_DATA_PTR &Value) | |
105 | { | |
106 | /* fetch & validate the query */ | |
107 | CLQuery *query = queryMap.lookupEntry(ResultsHandle); | |
108 | if(query == NULL) { | |
109 | CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); | |
110 | } | |
111 | if(query->queryType() != CLQ_Cert) { | |
112 | clErrorLog("CertGetNextFieldValue: bad queryType (%d)", (int)query->queryType()); | |
113 | CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); | |
114 | } | |
115 | if(query->nextIndex() >= query->numFields()) { | |
116 | return false; | |
117 | } | |
118 | ||
119 | /* fetch the associated cached cert */ | |
120 | CLCachedCert *cachedCert = lookupCachedCert(query->cachedObject()); | |
121 | uint32 dummy; | |
122 | CssmAutoData aData(*this); | |
123 | if(!cachedCert->cert().getCertFieldData(query->fieldId(), | |
124 | query->nextIndex(), | |
125 | dummy, | |
126 | aData)) { | |
127 | return false; | |
128 | } | |
129 | ||
130 | /* success - copy field data to outgoing Value */ | |
131 | Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); | |
132 | *Value = aData.release(); | |
133 | query->incrementIndex(); | |
134 | return true; | |
135 | } | |
136 | ||
137 | void | |
138 | AppleX509CLSession::CertCache( | |
139 | const CssmData &EncodedCert, | |
140 | CSSM_HANDLE &CertHandle) | |
141 | { | |
142 | DecodedCert *decodedCert = new DecodedCert(*this, EncodedCert); | |
143 | ||
144 | /* cook up a CLCachedCert, stash it in cache */ | |
145 | CLCachedCert *cachedCert = new CLCachedCert(*decodedCert); | |
146 | cacheMap.addEntry(*cachedCert, cachedCert->handle()); | |
147 | CertHandle = cachedCert->handle(); | |
148 | } | |
149 | ||
150 | CSSM_HANDLE | |
151 | AppleX509CLSession::CertGetFirstCachedFieldValue( | |
152 | CSSM_HANDLE CertHandle, | |
153 | const CssmData &CertField, | |
154 | uint32 &NumberOfMatchedFields, | |
155 | CSSM_DATA_PTR &Value) | |
156 | { | |
157 | /* fetch the associated cached cert */ | |
158 | CLCachedCert *cachedCert = lookupCachedCert(CertHandle); | |
159 | if(cachedCert == NULL) { | |
160 | CssmError::throwMe(CSSMERR_CL_INVALID_CACHE_HANDLE); | |
161 | } | |
162 | ||
163 | CssmAutoData aData(*this); | |
164 | uint32 numMatches; | |
165 | ||
166 | /* this returns false if field not there, throws on bad OID */ | |
167 | if(!cachedCert->cert().getCertFieldData(CertField, | |
168 | 0, // index | |
169 | numMatches, | |
170 | aData)) { | |
171 | return CSSM_INVALID_HANDLE; | |
172 | } | |
173 | ||
174 | /* cook up a CLQuery, stash it */ | |
175 | CLQuery *query = new CLQuery( | |
176 | CLQ_Cert, | |
177 | CertField, | |
178 | numMatches, | |
179 | true, // isFromCache | |
180 | cachedCert->handle()); | |
181 | queryMap.addEntry(*query, query->handle()); | |
182 | ||
183 | /* success - copy field data to outgoing Value */ | |
184 | Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); | |
185 | *Value = aData.release(); | |
186 | NumberOfMatchedFields = numMatches; | |
187 | return query->handle(); | |
188 | } | |
189 | ||
190 | ||
191 | bool | |
192 | AppleX509CLSession::CertGetNextCachedFieldValue( | |
193 | CSSM_HANDLE ResultsHandle, | |
194 | CSSM_DATA_PTR &Value) | |
195 | { | |
196 | /* Identical to, so just call... */ | |
197 | return CertGetNextFieldValue(ResultsHandle, Value); | |
198 | } | |
199 | ||
200 | void | |
201 | AppleX509CLSession::CertAbortCache( | |
202 | CSSM_HANDLE CertHandle) | |
203 | { | |
204 | /* fetch the associated cached cert, remove from map, delete it */ | |
205 | CLCachedCert *cachedCert = lookupCachedCert(CertHandle); | |
206 | if(cachedCert == NULL) { | |
207 | clErrorLog("CertAbortCache: cachedCert not found"); | |
208 | CssmError::throwMe(CSSMERR_CL_INVALID_CACHE_HANDLE); | |
209 | } | |
210 | cacheMap.removeEntry(cachedCert->handle()); | |
211 | delete cachedCert; | |
212 | } | |
213 | ||
214 | /* | |
215 | * Abort either type of cert field query (cache based or non-cache based) | |
216 | */ | |
217 | void | |
218 | AppleX509CLSession::CertAbortQuery( | |
219 | CSSM_HANDLE ResultsHandle) | |
220 | { | |
221 | /* fetch & validate the query */ | |
222 | CLQuery *query = queryMap.lookupEntry(ResultsHandle); | |
223 | if(query == NULL) { | |
224 | CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); | |
225 | } | |
226 | if(query->queryType() != CLQ_Cert) { | |
227 | clErrorLog("CertAbortQuery: bad queryType (%d)", (int)query->queryType()); | |
228 | CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); | |
229 | } | |
230 | ||
231 | if(!query->fromCache()) { | |
232 | /* the associated cached cert was created just for this query; dispose */ | |
233 | CLCachedCert *cachedCert = lookupCachedCert(query->cachedObject()); | |
234 | if(cachedCert == NULL) { | |
235 | /* should never happen */ | |
236 | clErrorLog("CertAbortQuery: cachedCert not found"); | |
237 | CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); | |
238 | } | |
239 | cacheMap.removeEntry(cachedCert->handle()); | |
240 | delete cachedCert; | |
241 | } | |
242 | queryMap.removeEntry(query->handle()); | |
243 | delete query; | |
244 | } | |
245 | ||
246 | void | |
247 | AppleX509CLSession::CertCreateTemplate( | |
248 | uint32 NumberOfFields, | |
249 | const CSSM_FIELD CertFields[], | |
250 | CssmData &CertTemplate) | |
251 | { | |
252 | /* cook up an empty Cert */ | |
253 | DecodedCert cert(*this); | |
254 | ||
255 | /* grind thru specified fields; exceptions are fatal */ | |
256 | for(uint32 dex=0; dex<NumberOfFields; dex++) { | |
257 | cert.setCertField( | |
258 | CssmOid::overlay(CertFields[dex].FieldOid), | |
259 | CssmData::overlay(CertFields[dex].FieldValue)); | |
260 | } | |
261 | ||
262 | /* TBD - ensure all required fields are set? We do this | |
263 | * when we sign the cert; maybe we should do it here. */ | |
264 | ||
265 | /* | |
266 | * We have the CertificateToSign in NSS format. Encode. | |
267 | */ | |
268 | CertTemplate.Data = NULL; | |
269 | CertTemplate.Length = 0; | |
270 | CssmRemoteData rData(*this, CertTemplate); | |
271 | cert.encodeTbs(rData); | |
272 | rData.release(); | |
273 | } | |
274 | ||
275 | ||
276 | void | |
277 | AppleX509CLSession::CertGetAllTemplateFields( | |
278 | const CssmData &CertTemplate, | |
279 | uint32 &NumberOfFields, | |
280 | CSSM_FIELD_PTR &CertFields) | |
281 | { | |
282 | DecodedCert cert(*this); // empty | |
283 | cert.decodeTbs(CertTemplate); | |
284 | cert.getAllParsedCertFields(NumberOfFields, CertFields); | |
285 | } | |
286 | ||
287 | void | |
288 | AppleX509CLSession::FreeFields( | |
289 | uint32 NumberOfFields, | |
290 | CSSM_FIELD_PTR &FieldArray) | |
291 | { | |
292 | unsigned i; | |
293 | CSSM_FIELD_PTR thisField; | |
294 | CSSM_OID_PTR thisOid; | |
295 | ||
296 | for(i=0; i<NumberOfFields; i++) { | |
297 | thisField = &FieldArray[i]; | |
298 | thisOid = &thisField->FieldOid; | |
299 | ||
300 | /* oid-specific handling of value */ | |
301 | /* BUG - the CssmRemoteData constructor clears the referent, | |
302 | * iff the referent is a CSSSM_DATA (as opposed to a CssmData). | |
303 | */ | |
304 | CssmData &cData = CssmData::overlay(thisField->FieldValue); | |
305 | CssmRemoteData rData(*this, cData); | |
306 | try { | |
307 | DecodedCert::freeCertFieldData(CssmOid::overlay(*thisOid), rData); | |
308 | } | |
309 | catch(...) { | |
310 | /* CRL field? */ | |
311 | DecodedCrl::freeCrlFieldData(CssmOid::overlay(*thisOid), rData); | |
312 | } | |
313 | /* and the oid itself */ | |
314 | free(thisOid->Data); | |
315 | thisOid->Data = NULL; | |
316 | thisOid->Length = 0; | |
317 | } | |
318 | free(FieldArray); | |
319 | } | |
320 | ||
321 | void | |
322 | AppleX509CLSession::FreeFieldValue( | |
323 | const CssmData &CertOrCrlOid, | |
324 | CssmData &Value) | |
325 | { | |
326 | CssmRemoteData cd(*this, Value); | |
327 | try { | |
328 | DecodedCert::freeCertFieldData(CertOrCrlOid, cd); | |
329 | } | |
330 | catch(...) { | |
331 | /* CRL field? */ | |
332 | DecodedCrl::freeCrlFieldData(CertOrCrlOid, cd); | |
333 | } | |
334 | free(&Value); | |
335 | } | |
336 | ||
337 | void | |
338 | AppleX509CLSession::CertGroupFromVerifiedBundle( | |
339 | CSSM_CC_HANDLE CCHandle, | |
340 | const CSSM_CERT_BUNDLE &CertBundle, | |
341 | const CssmData *SignerCert, | |
342 | CSSM_CERTGROUP_PTR &CertGroup) | |
343 | { | |
344 | unimplemented(); | |
345 | } | |
346 | ||
347 | void | |
348 | AppleX509CLSession::CertGroupToSignedBundle( | |
349 | CSSM_CC_HANDLE CCHandle, | |
350 | const CSSM_CERTGROUP &CertGroupToBundle, | |
351 | const CSSM_CERT_BUNDLE_HEADER *BundleInfo, | |
352 | CssmData &SignedBundle) | |
353 | { | |
354 | unimplemented(); | |
355 | } | |
356 | ||
357 | void | |
358 | AppleX509CLSession::PassThrough( | |
359 | CSSM_CC_HANDLE CCHandle, | |
360 | uint32 PassThroughId, | |
361 | const void *InputParams, | |
362 | void **OutputParams) | |
363 | { | |
364 | switch(PassThroughId) { | |
365 | case CSSM_APPLEX509CL_OBTAIN_CSR: | |
366 | { | |
367 | /* | |
368 | * Create a Cert Signing Request (CSR). | |
369 | * Input is a CSSM_APPLE_CL_CSR_REQUEST. | |
370 | * Output is a PEM-encoded CertSigningRequest (NSS type | |
371 | * NSS_SignedCertRequest from pkcs10). | |
372 | */ | |
373 | if(InputParams == NULL) { | |
374 | CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER); | |
375 | } | |
376 | if(OutputParams == NULL) { | |
377 | CssmError::throwMe(CSSMERR_CL_INVALID_OUTPUT_POINTER); | |
378 | } | |
379 | CSSM_APPLE_CL_CSR_REQUEST *csrReq = | |
380 | (CSSM_APPLE_CL_CSR_REQUEST *)InputParams; | |
381 | if((csrReq->subjectNameX509 == NULL) || | |
382 | (csrReq->signatureOid.Data == NULL) || | |
383 | (csrReq->subjectPublicKey == NULL) || | |
384 | (csrReq->subjectPrivateKey == NULL)) { | |
385 | CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER); | |
386 | } | |
387 | CSSM_DATA_PTR csrPtr = NULL; | |
388 | generateCsr(CCHandle, csrReq, csrPtr); | |
389 | *OutputParams = csrPtr; | |
390 | break; | |
391 | } | |
392 | case CSSM_APPLEX509CL_VERIFY_CSR: | |
393 | { | |
394 | /* | |
395 | * Perform signature verify of a CSR. | |
396 | * Input: CSSM_DATA referring to a DER-encoded CSR. | |
397 | * Output: Nothing, throws CSSMERR_CL_VERIFICATION_FAILURE | |
398 | * on failure. | |
399 | */ | |
400 | if(InputParams == NULL) { | |
401 | CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER); | |
402 | } | |
403 | const CSSM_DATA *csrPtr = (const CSSM_DATA *)InputParams; | |
404 | verifyCsr(csrPtr); | |
405 | break; | |
406 | } | |
407 | default: | |
408 | CssmError::throwMe(CSSMERR_CL_INVALID_PASSTHROUGH_ID); | |
409 | } | |
410 | } | |
411 |