]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_apple_x509_cl/lib/Session_Cert.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / libsecurity_apple_x509_cl / lib / Session_Cert.cpp
1 /*
2 * Copyright (c) 2000-2001,2011,2014 Apple 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