]> git.saurik.com Git - apple/security.git/blob - AppleX509CL/Session_Cert.cpp
Security-163.tar.gz
[apple/security.git] / AppleX509CL / Session_Cert.cpp
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 CssmRemoteData rData(*this, CertTemplate);
269 cert.encodeTbs(rData);
270 rData.release();
271 }
272
273
274 void
275 AppleX509CLSession::CertGetAllTemplateFields(
276 const CssmData &CertTemplate,
277 uint32 &NumberOfFields,
278 CSSM_FIELD_PTR &CertFields)
279 {
280 DecodedCert cert(*this); // empty
281 cert.decodeTbs(CertTemplate);
282 cert.getAllParsedCertFields(NumberOfFields, CertFields);
283 }
284
285 void
286 AppleX509CLSession::FreeFields(
287 uint32 NumberOfFields,
288 CSSM_FIELD_PTR &FieldArray)
289 {
290 unsigned i;
291 CSSM_FIELD_PTR thisField;
292 CSSM_OID_PTR thisOid;
293
294 for(i=0; i<NumberOfFields; i++) {
295 thisField = &FieldArray[i];
296 thisOid = &thisField->FieldOid;
297
298 /* oid-specific handling of value */
299 /* BUG - the CssmRemoteData constructor clears the referent,
300 * iff the referent is a CSSSM_DATA (as opposed to a CssmData).
301 */
302 CssmData &cData = CssmData::overlay(thisField->FieldValue);
303 CssmRemoteData rData(*this, cData);
304 try {
305 DecodedCert::freeCertFieldData(CssmOid::overlay(*thisOid), rData);
306 }
307 catch(...) {
308 /* CRL field? */
309 DecodedCrl::freeCrlFieldData(CssmOid::overlay(*thisOid), rData);
310 }
311 /* and the oid itself */
312 free(thisOid->Data);
313 thisOid->Data = NULL;
314 thisOid->Length = 0;
315 }
316 free(FieldArray);
317 }
318
319 void
320 AppleX509CLSession::FreeFieldValue(
321 const CssmData &CertOrCrlOid,
322 CssmData &Value)
323 {
324 CssmRemoteData cd(*this, Value);
325 try {
326 DecodedCert::freeCertFieldData(CertOrCrlOid, cd);
327 }
328 catch(...) {
329 /* CRL field? */
330 DecodedCrl::freeCrlFieldData(CertOrCrlOid, cd);
331 }
332 free(&Value);
333 }
334
335 void
336 AppleX509CLSession::CertGroupFromVerifiedBundle(
337 CSSM_CC_HANDLE CCHandle,
338 const CSSM_CERT_BUNDLE &CertBundle,
339 const CssmData *SignerCert,
340 CSSM_CERTGROUP_PTR &CertGroup)
341 {
342 unimplemented();
343 }
344
345 void
346 AppleX509CLSession::CertGroupToSignedBundle(
347 CSSM_CC_HANDLE CCHandle,
348 const CSSM_CERTGROUP &CertGroupToBundle,
349 const CSSM_CERT_BUNDLE_HEADER *BundleInfo,
350 CssmData &SignedBundle)
351 {
352 unimplemented();
353 }
354
355 void
356 AppleX509CLSession::PassThrough(
357 CSSM_CC_HANDLE CCHandle,
358 uint32 PassThroughId,
359 const void *InputParams,
360 void **OutputParams)
361 {
362 switch(PassThroughId) {
363 case CSSM_APPLEX509CL_OBTAIN_CSR:
364 {
365 /*
366 * Create a Cert Signing Request (CSR).
367 * Input is a CSSM_APPLE_CL_CSR_REQUEST.
368 * Output is a PEM-encoded CertSigningRequest (NSS type
369 * NSS_SignedCertRequest from pkcs10).
370 */
371 if(InputParams == NULL) {
372 CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER);
373 }
374 if(OutputParams == NULL) {
375 CssmError::throwMe(CSSMERR_CL_INVALID_OUTPUT_POINTER);
376 }
377 CSSM_APPLE_CL_CSR_REQUEST *csrReq =
378 (CSSM_APPLE_CL_CSR_REQUEST *)InputParams;
379 if((csrReq->subjectNameX509 == NULL) ||
380 (csrReq->signatureOid.Data == NULL) ||
381 (csrReq->subjectPublicKey == NULL) ||
382 (csrReq->subjectPrivateKey == NULL)) {
383 CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER);
384 }
385 CSSM_DATA_PTR csrPtr = NULL;
386 generateCsr(CCHandle, csrReq, csrPtr);
387 *OutputParams = csrPtr;
388 break;
389 }
390 case CSSM_APPLEX509CL_VERIFY_CSR:
391 {
392 /*
393 * Perform signature verify of a CSR.
394 * Input: CSSM_DATA referring to a DER-encoded CSR.
395 * Output: Nothing, throws CSSMERR_CL_VERIFICATION_FAILURE
396 * on failure.
397 */
398 if(InputParams == NULL) {
399 CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER);
400 }
401 const CSSM_DATA *csrPtr = (const CSSM_DATA *)InputParams;
402 verifyCsr(csrPtr);
403 break;
404 }
405 default:
406 CssmError::throwMe(CSSMERR_CL_INVALID_PASSTHROUGH_ID);
407 }
408 }
409