2 * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved.
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
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.
20 // Session_Cert.cpp - cert-related session functions.
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>
31 AppleX509CLSession::CertDescribeFormat(
32 uint32
&NumberOfFields
,
33 CSSM_OID_PTR
&OidList
)
35 DecodedCert::describeFormat(*this, NumberOfFields
, OidList
);
39 AppleX509CLSession::CertGetAllFields(
41 uint32
&NumberOfFields
,
42 CSSM_FIELD_PTR
&CertFields
)
44 DecodedCert
decodedCert(*this, Cert
);
45 decodedCert
.getAllParsedCertFields(NumberOfFields
, CertFields
);
50 AppleX509CLSession::CertGetFirstFieldValue(
51 const CssmData
&EncodedCert
,
52 const CssmData
&CertField
,
53 uint32
&NumberOfMatchedFields
,
56 NumberOfMatchedFields
= 0;
58 CssmAutoData
aData(*this);
60 DecodedCert
*decodedCert
= new DecodedCert(*this, EncodedCert
);
63 /* this returns false if field not there, throws on bad OID */
66 brtn
= decodedCert
->getCertFieldData(CertField
,
77 return CSSM_INVALID_HANDLE
;
80 /* cook up a CLCachedCert, stash it in cache */
81 CLCachedCert
*cachedCert
= new CLCachedCert(*decodedCert
);
82 cacheMap
.addEntry(*cachedCert
, cachedCert
->handle());
84 /* cook up a CLQuery, stash it */
85 CLQuery
*query
= new CLQuery(
90 cachedCert
->handle());
91 queryMap
.addEntry(*query
, query
->handle());
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();
102 AppleX509CLSession::CertGetNextFieldValue(
103 CSSM_HANDLE ResultsHandle
,
104 CSSM_DATA_PTR
&Value
)
106 /* fetch & validate the query */
107 CLQuery
*query
= queryMap
.lookupEntry(ResultsHandle
);
109 CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE
);
111 if(query
->queryType() != CLQ_Cert
) {
112 clErrorLog("CertGetNextFieldValue: bad queryType (%d)", (int)query
->queryType());
113 CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE
);
115 if(query
->nextIndex() >= query
->numFields()) {
119 /* fetch the associated cached cert */
120 CLCachedCert
*cachedCert
= lookupCachedCert(query
->cachedObject());
122 CssmAutoData
aData(*this);
123 if(!cachedCert
->cert().getCertFieldData(query
->fieldId(),
130 /* success - copy field data to outgoing Value */
131 Value
= (CSSM_DATA_PTR
)malloc(sizeof(CSSM_DATA
));
132 *Value
= aData
.release();
133 query
->incrementIndex();
138 AppleX509CLSession::CertCache(
139 const CssmData
&EncodedCert
,
140 CSSM_HANDLE
&CertHandle
)
142 DecodedCert
*decodedCert
= new DecodedCert(*this, EncodedCert
);
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();
151 AppleX509CLSession::CertGetFirstCachedFieldValue(
152 CSSM_HANDLE CertHandle
,
153 const CssmData
&CertField
,
154 uint32
&NumberOfMatchedFields
,
155 CSSM_DATA_PTR
&Value
)
157 /* fetch the associated cached cert */
158 CLCachedCert
*cachedCert
= lookupCachedCert(CertHandle
);
159 if(cachedCert
== NULL
) {
160 CssmError::throwMe(CSSMERR_CL_INVALID_CACHE_HANDLE
);
163 CssmAutoData
aData(*this);
166 /* this returns false if field not there, throws on bad OID */
167 if(!cachedCert
->cert().getCertFieldData(CertField
,
171 return CSSM_INVALID_HANDLE
;
174 /* cook up a CLQuery, stash it */
175 CLQuery
*query
= new CLQuery(
180 cachedCert
->handle());
181 queryMap
.addEntry(*query
, query
->handle());
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();
192 AppleX509CLSession::CertGetNextCachedFieldValue(
193 CSSM_HANDLE ResultsHandle
,
194 CSSM_DATA_PTR
&Value
)
196 /* Identical to, so just call... */
197 return CertGetNextFieldValue(ResultsHandle
, Value
);
201 AppleX509CLSession::CertAbortCache(
202 CSSM_HANDLE CertHandle
)
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
);
210 cacheMap
.removeEntry(cachedCert
->handle());
215 * Abort either type of cert field query (cache based or non-cache based)
218 AppleX509CLSession::CertAbortQuery(
219 CSSM_HANDLE ResultsHandle
)
221 /* fetch & validate the query */
222 CLQuery
*query
= queryMap
.lookupEntry(ResultsHandle
);
224 CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE
);
226 if(query
->queryType() != CLQ_Cert
) {
227 clErrorLog("CertAbortQuery: bad queryType (%d)", (int)query
->queryType());
228 CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE
);
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
);
239 cacheMap
.removeEntry(cachedCert
->handle());
242 queryMap
.removeEntry(query
->handle());
247 AppleX509CLSession::CertCreateTemplate(
248 uint32 NumberOfFields
,
249 const CSSM_FIELD CertFields
[],
250 CssmData
&CertTemplate
)
252 /* cook up an empty Cert */
253 DecodedCert
cert(*this);
255 /* grind thru specified fields; exceptions are fatal */
256 for(uint32 dex
=0; dex
<NumberOfFields
; dex
++) {
258 CssmOid::overlay(CertFields
[dex
].FieldOid
),
259 CssmData::overlay(CertFields
[dex
].FieldValue
));
262 /* TBD - ensure all required fields are set? We do this
263 * when we sign the cert; maybe we should do it here. */
266 * We have the CertificateToSign in NSS format. Encode.
268 CertTemplate
.Data
= NULL
;
269 CertTemplate
.Length
= 0;
270 CssmRemoteData
rData(*this, CertTemplate
);
271 cert
.encodeTbs(rData
);
277 AppleX509CLSession::CertGetAllTemplateFields(
278 const CssmData
&CertTemplate
,
279 uint32
&NumberOfFields
,
280 CSSM_FIELD_PTR
&CertFields
)
282 DecodedCert
cert(*this); // empty
283 cert
.decodeTbs(CertTemplate
);
284 cert
.getAllParsedCertFields(NumberOfFields
, CertFields
);
288 AppleX509CLSession::FreeFields(
289 uint32 NumberOfFields
,
290 CSSM_FIELD_PTR
&FieldArray
)
293 CSSM_FIELD_PTR thisField
;
294 CSSM_OID_PTR thisOid
;
296 for(i
=0; i
<NumberOfFields
; i
++) {
297 thisField
= &FieldArray
[i
];
298 thisOid
= &thisField
->FieldOid
;
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).
304 CssmData
&cData
= CssmData::overlay(thisField
->FieldValue
);
305 CssmRemoteData
rData(*this, cData
);
307 DecodedCert::freeCertFieldData(CssmOid::overlay(*thisOid
), rData
);
311 DecodedCrl::freeCrlFieldData(CssmOid::overlay(*thisOid
), rData
);
313 /* and the oid itself */
315 thisOid
->Data
= NULL
;
322 AppleX509CLSession::FreeFieldValue(
323 const CssmData
&CertOrCrlOid
,
326 CssmRemoteData
cd(*this, Value
);
328 DecodedCert::freeCertFieldData(CertOrCrlOid
, cd
);
332 DecodedCrl::freeCrlFieldData(CertOrCrlOid
, cd
);
338 AppleX509CLSession::CertGroupFromVerifiedBundle(
339 CSSM_CC_HANDLE CCHandle
,
340 const CSSM_CERT_BUNDLE
&CertBundle
,
341 const CssmData
*SignerCert
,
342 CSSM_CERTGROUP_PTR
&CertGroup
)
348 AppleX509CLSession::CertGroupToSignedBundle(
349 CSSM_CC_HANDLE CCHandle
,
350 const CSSM_CERTGROUP
&CertGroupToBundle
,
351 const CSSM_CERT_BUNDLE_HEADER
*BundleInfo
,
352 CssmData
&SignedBundle
)
358 AppleX509CLSession::PassThrough(
359 CSSM_CC_HANDLE CCHandle
,
360 uint32 PassThroughId
,
361 const void *InputParams
,
364 switch(PassThroughId
) {
365 case CSSM_APPLEX509CL_OBTAIN_CSR
:
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).
373 if(InputParams
== NULL
) {
374 CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER
);
376 if(OutputParams
== NULL
) {
377 CssmError::throwMe(CSSMERR_CL_INVALID_OUTPUT_POINTER
);
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
);
387 CSSM_DATA_PTR csrPtr
= NULL
;
388 generateCsr(CCHandle
, csrReq
, csrPtr
);
389 *OutputParams
= csrPtr
;
392 case CSSM_APPLEX509CL_VERIFY_CSR
:
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
400 if(InputParams
== NULL
) {
401 CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER
);
403 const CSSM_DATA
*csrPtr
= (const CSSM_DATA
*)InputParams
;
408 CssmError::throwMe(CSSMERR_CL_INVALID_PASSTHROUGH_ID
);