]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_apple_x509_cl/lib/Session_Cert.cpp
Security-55163.44.tar.gz
[apple/security.git] / libsecurity_apple_x509_cl / lib / Session_Cert.cpp
diff --git a/libsecurity_apple_x509_cl/lib/Session_Cert.cpp b/libsecurity_apple_x509_cl/lib/Session_Cert.cpp
new file mode 100644 (file)
index 0000000..baef233
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
+ * 
+ * The contents of this file constitute Original Code as defined in and are
+ * subject to the Apple Public Source License Version 1.2 (the 'License').
+ * You may not use this file except in compliance with the License. Please obtain
+ * a copy of the License at http://www.apple.com/publicsource and read it before
+ * using this file.
+ * 
+ * This Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
+ * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
+ * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
+ * specific language governing rights and limitations under the License.
+ */
+
+
+//
+// Session_Cert.cpp - cert-related session functions.
+//
+
+#include "AppleX509CLSession.h"
+#include "DecodedCert.h"
+#include "DecodedCrl.h"
+#include "CLCachedEntry.h"
+#include "cldebugging.h"
+#include <Security/oidscert.h>
+
+void
+AppleX509CLSession::CertDescribeFormat(
+       uint32 &NumberOfFields,
+       CSSM_OID_PTR &OidList)
+{
+       DecodedCert::describeFormat(*this, NumberOfFields, OidList);
+}
+
+void
+AppleX509CLSession::CertGetAllFields(
+       const CssmData &Cert,
+       uint32 &NumberOfFields,
+       CSSM_FIELD_PTR &CertFields)
+{
+       DecodedCert decodedCert(*this, Cert);
+       decodedCert.getAllParsedCertFields(NumberOfFields, CertFields);
+}
+
+
+CSSM_HANDLE
+AppleX509CLSession::CertGetFirstFieldValue(
+       const CssmData &EncodedCert,
+       const CssmData &CertField,
+       uint32 &NumberOfMatchedFields,
+       CSSM_DATA_PTR &Value)
+{
+       NumberOfMatchedFields = 0;
+       Value = NULL;
+       CssmAutoData aData(*this);
+       
+       DecodedCert *decodedCert = new DecodedCert(*this, EncodedCert);
+       uint32 numMatches;
+       
+       /* this returns false if field not there, throws on bad OID */
+       bool brtn;
+       try {
+               brtn = decodedCert->getCertFieldData(CertField, 
+                       0,                              // index
+                       numMatches, 
+                       aData);
+       }
+       catch (...) {
+               delete decodedCert;
+               throw;
+       }
+       if(!brtn) {
+               delete decodedCert;
+               return CSSM_INVALID_HANDLE;
+       }
+
+       /* cook up a CLCachedCert, stash it in cache */
+       CLCachedCert *cachedCert = new CLCachedCert(*decodedCert);
+       cacheMap.addEntry(*cachedCert, cachedCert->handle());
+       
+       /* cook up a CLQuery, stash it */
+       CLQuery *query = new CLQuery(
+               CLQ_Cert, 
+               CertField, 
+               numMatches,
+               false,                          // isFromCache
+               cachedCert->handle());
+       queryMap.addEntry(*query, query->handle());
+       
+       /* success - copy field data to outgoing Value */
+       Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA));
+       *Value = aData.release();
+       NumberOfMatchedFields = numMatches;
+       return query->handle();
+}
+
+
+bool
+AppleX509CLSession::CertGetNextFieldValue(
+       CSSM_HANDLE ResultsHandle,
+       CSSM_DATA_PTR &Value)
+{
+       /* fetch & validate the query */
+       CLQuery *query = queryMap.lookupEntry(ResultsHandle);
+       if(query == NULL) {
+               CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE);
+       }
+       if(query->queryType() != CLQ_Cert) {
+               clErrorLog("CertGetNextFieldValue: bad queryType (%d)", (int)query->queryType());
+               CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE);
+       }
+       if(query->nextIndex() >= query->numFields()) {
+               return false;
+       }
+
+       /* fetch the associated cached cert */
+       CLCachedCert *cachedCert = lookupCachedCert(query->cachedObject());
+       uint32 dummy;
+       CssmAutoData aData(*this);
+       if(!cachedCert->cert().getCertFieldData(query->fieldId(), 
+               query->nextIndex(), 
+               dummy,
+               aData))  {
+               return false;
+       }
+               
+       /* success - copy field data to outgoing Value */
+       Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA));
+       *Value = aData.release();
+       query->incrementIndex();
+       return true;
+}
+
+void
+AppleX509CLSession::CertCache(
+       const CssmData &EncodedCert,
+       CSSM_HANDLE &CertHandle)
+{
+       DecodedCert *decodedCert = new DecodedCert(*this, EncodedCert);
+       
+       /* cook up a CLCachedCert, stash it in cache */
+       CLCachedCert *cachedCert = new CLCachedCert(*decodedCert);
+       cacheMap.addEntry(*cachedCert, cachedCert->handle());
+       CertHandle = cachedCert->handle();
+}
+
+CSSM_HANDLE
+AppleX509CLSession::CertGetFirstCachedFieldValue(
+       CSSM_HANDLE CertHandle,
+       const CssmData &CertField,
+       uint32 &NumberOfMatchedFields,
+       CSSM_DATA_PTR &Value)
+{
+       /* fetch the associated cached cert */
+       CLCachedCert *cachedCert = lookupCachedCert(CertHandle);
+       if(cachedCert == NULL) {
+               CssmError::throwMe(CSSMERR_CL_INVALID_CACHE_HANDLE);
+       }
+       
+       CssmAutoData aData(*this);
+       uint32 numMatches;
+
+       /* this returns false if field not there, throws on bad OID */
+       if(!cachedCert->cert().getCertFieldData(CertField, 
+                       0,                              // index
+                       numMatches, 
+                       aData)) {
+               return CSSM_INVALID_HANDLE;
+       }
+
+       /* cook up a CLQuery, stash it */
+       CLQuery *query = new CLQuery(
+               CLQ_Cert, 
+               CertField, 
+               numMatches,
+               true,                           // isFromCache
+               cachedCert->handle());
+       queryMap.addEntry(*query, query->handle());
+       
+       /* success - copy field data to outgoing Value */
+       Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA));
+       *Value = aData.release();
+       NumberOfMatchedFields = numMatches;
+       return query->handle();
+}
+
+
+bool
+AppleX509CLSession::CertGetNextCachedFieldValue(
+       CSSM_HANDLE ResultsHandle,
+       CSSM_DATA_PTR &Value)
+{
+       /* Identical to, so just call... */
+       return CertGetNextFieldValue(ResultsHandle, Value);
+}
+
+void
+AppleX509CLSession::CertAbortCache(
+       CSSM_HANDLE CertHandle)
+{
+       /* fetch the associated cached cert, remove from map, delete it */
+       CLCachedCert *cachedCert = lookupCachedCert(CertHandle);
+       if(cachedCert == NULL) {
+               clErrorLog("CertAbortCache: cachedCert not found");
+               CssmError::throwMe(CSSMERR_CL_INVALID_CACHE_HANDLE);
+       }
+       cacheMap.removeEntry(cachedCert->handle());
+       delete cachedCert;
+}
+
+/*
+ * Abort either type of cert field query (cache based or non-cache based)
+ */
+void
+AppleX509CLSession::CertAbortQuery(
+       CSSM_HANDLE ResultsHandle)
+{
+       /* fetch & validate the query */
+       CLQuery *query = queryMap.lookupEntry(ResultsHandle);
+       if(query == NULL) {
+               CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE);
+       }
+       if(query->queryType() != CLQ_Cert) {
+               clErrorLog("CertAbortQuery: bad queryType (%d)", (int)query->queryType());
+               CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE);
+       }
+       
+       if(!query->fromCache()) {
+               /* the associated cached cert was created just for this query; dispose */
+               CLCachedCert *cachedCert = lookupCachedCert(query->cachedObject());
+               if(cachedCert == NULL) {
+                       /* should never happen */
+                       clErrorLog("CertAbortQuery: cachedCert not found");
+                       CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
+               }
+               cacheMap.removeEntry(cachedCert->handle());
+               delete cachedCert;
+       }
+       queryMap.removeEntry(query->handle());
+       delete query;
+}
+
+void
+AppleX509CLSession::CertCreateTemplate(
+       uint32 NumberOfFields,
+       const CSSM_FIELD CertFields[],
+       CssmData &CertTemplate)
+{
+       /* cook up an empty Cert */
+       DecodedCert cert(*this);
+
+       /* grind thru specified fields; exceptions are fatal */
+       for(uint32 dex=0; dex<NumberOfFields; dex++) {
+               cert.setCertField(
+                       CssmOid::overlay(CertFields[dex].FieldOid), 
+                       CssmData::overlay(CertFields[dex].FieldValue));
+       }
+       
+       /* TBD - ensure all required fields are set? We do this 
+        * when we sign the cert; maybe we should do it here. */
+       
+       /* 
+        * We have the CertificateToSign in NSS format. Encode.
+        */
+       CertTemplate.Data = NULL;
+       CertTemplate.Length = 0;
+       CssmRemoteData rData(*this, CertTemplate);
+       cert.encodeTbs(rData);
+       rData.release();
+}
+
+
+void
+AppleX509CLSession::CertGetAllTemplateFields(
+       const CssmData &CertTemplate,
+       uint32 &NumberOfFields,
+       CSSM_FIELD_PTR &CertFields)
+{
+       DecodedCert     cert(*this);            // empty
+       cert.decodeTbs(CertTemplate);
+       cert.getAllParsedCertFields(NumberOfFields, CertFields);
+}
+
+void
+AppleX509CLSession::FreeFields(
+       uint32 NumberOfFields,
+       CSSM_FIELD_PTR &FieldArray)
+{
+       unsigned                i;
+       CSSM_FIELD_PTR  thisField;
+       CSSM_OID_PTR    thisOid;
+       
+       for(i=0; i<NumberOfFields; i++) {
+               thisField = &FieldArray[i];
+               thisOid = &thisField->FieldOid;
+               
+               /* oid-specific handling of value */
+               /* BUG - the CssmRemoteData constructor clears the referent,
+                * iff the referent is a CSSSM_DATA (as opposed to a CssmData).
+                */
+               CssmData &cData = CssmData::overlay(thisField->FieldValue);
+               CssmRemoteData rData(*this, cData);
+               try {
+                       DecodedCert::freeCertFieldData(CssmOid::overlay(*thisOid), rData);
+               }
+               catch(...) {
+                       /* CRL field? */
+                       DecodedCrl::freeCrlFieldData(CssmOid::overlay(*thisOid), rData);
+               }
+               /* and the oid itself */
+               free(thisOid->Data);
+               thisOid->Data = NULL;
+               thisOid->Length = 0;
+       }
+       free(FieldArray);
+}
+
+void
+AppleX509CLSession::FreeFieldValue(
+       const CssmData &CertOrCrlOid,
+       CssmData &Value)
+{
+       CssmRemoteData cd(*this, Value);
+       try {
+               DecodedCert::freeCertFieldData(CertOrCrlOid, cd);
+       }
+       catch(...) {
+               /* CRL field? */
+               DecodedCrl::freeCrlFieldData(CertOrCrlOid, cd);
+       }
+       free(&Value);
+}
+
+void
+AppleX509CLSession::CertGroupFromVerifiedBundle(
+       CSSM_CC_HANDLE CCHandle,
+       const CSSM_CERT_BUNDLE &CertBundle,
+       const CssmData *SignerCert,
+       CSSM_CERTGROUP_PTR &CertGroup)
+{
+       unimplemented();
+}
+
+void
+AppleX509CLSession::CertGroupToSignedBundle(
+       CSSM_CC_HANDLE CCHandle,
+       const CSSM_CERTGROUP &CertGroupToBundle,
+       const CSSM_CERT_BUNDLE_HEADER *BundleInfo,
+       CssmData &SignedBundle)
+{
+       unimplemented();
+}
+
+void
+AppleX509CLSession::PassThrough(
+       CSSM_CC_HANDLE CCHandle,
+       uint32 PassThroughId,
+       const void *InputParams,
+       void **OutputParams)
+{
+       switch(PassThroughId) {
+               case CSSM_APPLEX509CL_OBTAIN_CSR:
+               {
+                       /*
+                        * Create a Cert Signing Request (CSR).
+                        * Input is a CSSM_APPLE_CL_CSR_REQUEST.
+                        * Output is a PEM-encoded CertSigningRequest (NSS type
+                        * NSS_SignedCertRequest from pkcs10). 
+                        */
+                       if(InputParams == NULL) {
+                               CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER);
+                       }
+                       if(OutputParams == NULL) {
+                               CssmError::throwMe(CSSMERR_CL_INVALID_OUTPUT_POINTER);
+                       }
+                       CSSM_APPLE_CL_CSR_REQUEST *csrReq = 
+                               (CSSM_APPLE_CL_CSR_REQUEST *)InputParams;
+                       if((csrReq->subjectNameX509 == NULL) ||
+                       (csrReq->signatureOid.Data == NULL) ||
+                       (csrReq->subjectPublicKey == NULL) ||
+                       (csrReq->subjectPrivateKey == NULL)) {
+                               CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER);
+                       }
+                       CSSM_DATA_PTR csrPtr = NULL;
+                       generateCsr(CCHandle, csrReq, csrPtr);
+                       *OutputParams = csrPtr;
+                       break;
+               }       
+               case CSSM_APPLEX509CL_VERIFY_CSR:
+               {
+                       /*
+                        * Perform signature verify of a CSR.
+                        * Input:  CSSM_DATA referring to a DER-encoded CSR.
+                        * Output: Nothing, throws CSSMERR_CL_VERIFICATION_FAILURE
+                        *         on failure.
+                        */
+                       if(InputParams == NULL) {
+                               CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER);
+                       }
+                       const CSSM_DATA *csrPtr = (const CSSM_DATA *)InputParams;
+                       verifyCsr(csrPtr);
+                       break;
+               }       
+               default:
+                       CssmError::throwMe(CSSMERR_CL_INVALID_PASSTHROUGH_ID);
+       }
+}
+