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