]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_cssm/lib/transition.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_cssm / lib / transition.cpp
diff --git a/Security/libsecurity_cssm/lib/transition.cpp b/Security/libsecurity_cssm/lib/transition.cpp
new file mode 100644 (file)
index 0000000..99c81b0
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+ * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved.
+ * 
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The 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.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+//
+// transition - transition layer for CSSM API/SPI calls.
+//
+// This file defines all functions that connect the CSSM API (CSSM_*)
+// to a plugin's SPI (CSSM_SPI_*) functions. The bulk of these functions
+// is automatically generated by the Perl script transition.pl (thanks, Larry!)
+// from the cssm*.h official header files, under control of the configuration
+// file transition.cfg. Those that need special magic are marked "custom" in
+// transition.cfg and are defined here.
+//
+// @@@ Reconsider CSP locking for context operations
+//
+#include "cssmint.h"
+#include "attachfactory.h"
+#include "manager.h"
+#include "cssmcontext.h"
+#include <Security/cssmcspi.h>
+#include <Security/cssmdli.h>
+#include <Security/cssmcli.h>
+#include <Security/cssmaci.h>
+#include <Security/cssmtpi.h>
+#include <Security/cssmkrapi.h>
+#include <Security/cssmkrspi.h>
+#include <security_cdsa_utilities/cssmbridge.h>
+
+
+//
+// Names for the standard Attachment types
+//
+typedef StandardAttachment<CSSM_SERVICE_CSP, CSSM_SPI_CSP_FUNCS> CSPAttachment;
+typedef StandardAttachment<CSSM_SERVICE_DL, CSSM_SPI_DL_FUNCS> DLAttachment;
+typedef StandardAttachment<CSSM_SERVICE_CL, CSSM_SPI_CL_FUNCS> CLAttachment;
+typedef StandardAttachment<CSSM_SERVICE_AC, CSSM_SPI_AC_FUNCS> ACAttachment;
+typedef StandardAttachment<CSSM_SERVICE_TP, CSSM_SPI_TP_FUNCS> TPAttachment;
+
+
+//
+// A conditional locking class for always-right(TM) lock management.
+//
+class TransitLock {
+public:
+       Attachment &attachment;
+       
+       TransitLock(Attachment &att) : attachment(att)
+       {
+               attachment.module.safeLock();
+       }
+       
+       ~TransitLock()
+       {
+               attachment.module.safeUnlock();
+               attachment.exit();
+       }
+};
+
+
+//
+// Context management functions
+//
+CSSM_RETURN CSSMAPI
+CSSM_CSP_CreateSignatureContext (CSSM_CSP_HANDLE CSPHandle,
+                                 CSSM_ALGORITHMS AlgorithmID,
+                                 const CSSM_ACCESS_CREDENTIALS *AccessCred,
+                                 const CSSM_KEY *Key,
+                                 CSSM_CC_HANDLE *NewContextHandle)
+{
+    BEGIN_API
+    HandleContext::Maker maker(CSPHandle);
+    maker.setup(AccessCred);
+    maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY);
+    maker.make();
+    maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred);
+    maker.put(CSSM_ATTRIBUTE_KEY, Key);
+    Required(NewContextHandle) = maker(CSSM_ALGCLASS_SIGNATURE, AlgorithmID);
+    END_API(CSSM)
+}
+
+
+CSSM_RETURN CSSMAPI
+CSSM_CSP_CreateSymmetricContext (CSSM_CSP_HANDLE CSPHandle,
+                                 CSSM_ALGORITHMS AlgorithmID,
+                                 CSSM_ENCRYPT_MODE Mode,
+                                 const CSSM_ACCESS_CREDENTIALS *AccessCred,
+                                 const CSSM_KEY *Key,
+                                 const CSSM_DATA *InitVector,
+                                 CSSM_PADDING Padding,
+                                 void *Reserved,
+                                 CSSM_CC_HANDLE *NewContextHandle)
+{
+    BEGIN_API
+    if (Reserved != NULL)
+        CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER);
+    HandleContext::Maker maker(CSPHandle);
+    maker.setup(Mode);
+    maker.setup(AccessCred);
+    maker.setup(Key);
+    maker.setup(InitVector);
+    maker.setup(Padding);
+    maker.make();
+    maker.put(CSSM_ATTRIBUTE_MODE, Mode);
+    maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred);
+    maker.put(CSSM_ATTRIBUTE_KEY, Key);
+    maker.put(CSSM_ATTRIBUTE_INIT_VECTOR, InitVector);
+    maker.put(CSSM_ATTRIBUTE_PADDING, Padding);
+    Required(NewContextHandle) = maker(CSSM_ALGCLASS_SYMMETRIC, AlgorithmID);
+    END_API(CSSM)
+}
+
+
+CSSM_RETURN CSSMAPI
+CSSM_CSP_CreateDigestContext (CSSM_CSP_HANDLE CSPHandle,
+                              CSSM_ALGORITHMS AlgorithmID,
+                              CSSM_CC_HANDLE *NewContextHandle)
+{
+    BEGIN_API
+    HandleContext::Maker maker(CSPHandle);
+    maker.make();
+    Required(NewContextHandle) = maker(CSSM_ALGCLASS_DIGEST, AlgorithmID);
+    END_API(CSSM)
+}
+
+
+CSSM_RETURN CSSMAPI
+CSSM_CSP_CreateMacContext (CSSM_CSP_HANDLE CSPHandle,
+                           CSSM_ALGORITHMS AlgorithmID,
+                           const CSSM_KEY *Key,
+                           CSSM_CC_HANDLE *NewContextHandle)
+{
+    BEGIN_API
+    HandleContext::Maker maker(CSPHandle);
+    maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY);
+    maker.make();
+    maker.put(CSSM_ATTRIBUTE_KEY, Key);
+    Required(NewContextHandle) = maker(CSSM_ALGCLASS_MAC, AlgorithmID);
+    END_API(CSSM)
+}
+
+
+CSSM_RETURN CSSMAPI
+CSSM_CSP_CreateRandomGenContext (CSSM_CSP_HANDLE CSPHandle,
+                                 CSSM_ALGORITHMS AlgorithmID,
+                                 const CSSM_CRYPTO_DATA *Seed,
+                                 CSSM_SIZE Length,
+                                 CSSM_CC_HANDLE *NewContextHandle)
+{
+    BEGIN_API
+    HandleContext::Maker maker(CSPHandle);
+    maker.setup(Seed);
+    maker.setup(Length, CSSMERR_CSP_INVALID_ATTR_OUTPUT_SIZE);
+    maker.make();
+    maker.put(CSSM_ATTRIBUTE_SEED, Seed);
+    maker.put(CSSM_ATTRIBUTE_OUTPUT_SIZE, (uint32_t)Length);
+    Required(NewContextHandle) = maker(CSSM_ALGCLASS_RANDOMGEN, AlgorithmID);
+    END_API(CSSM)
+}
+
+
+CSSM_RETURN CSSMAPI
+CSSM_CSP_CreateAsymmetricContext (CSSM_CSP_HANDLE CSPHandle,
+                                  CSSM_ALGORITHMS AlgorithmID,
+                                  const CSSM_ACCESS_CREDENTIALS *AccessCred,
+                                  const CSSM_KEY *Key,
+                                  CSSM_PADDING Padding,
+                                  CSSM_CC_HANDLE *NewContextHandle)
+{
+    BEGIN_API
+    HandleContext::Maker maker(CSPHandle);
+    maker.setup(AccessCred, CSSMERR_CSP_MISSING_ATTR_ACCESS_CREDENTIALS);
+    maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY);
+    maker.setup(Padding);
+    maker.make();
+    maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred);
+    maker.put(CSSM_ATTRIBUTE_KEY, Key);
+    maker.put(CSSM_ATTRIBUTE_PADDING, Padding);
+    Required(NewContextHandle) = maker(CSSM_ALGCLASS_ASYMMETRIC, AlgorithmID);
+    END_API(CSSM)
+}
+
+
+CSSM_RETURN CSSMAPI
+CSSM_CSP_CreateDeriveKeyContext (CSSM_CSP_HANDLE CSPHandle,
+                                 CSSM_ALGORITHMS AlgorithmID,
+                                 CSSM_KEY_TYPE DeriveKeyType,
+                                 uint32 DeriveKeyLengthInBits,
+                                 const CSSM_ACCESS_CREDENTIALS *AccessCred,
+                                 const CSSM_KEY *BaseKey,
+                                 uint32 IterationCount,
+                                 const CSSM_DATA *Salt,
+                                 const CSSM_CRYPTO_DATA *Seed,
+                                 CSSM_CC_HANDLE *NewContextHandle)
+{
+    BEGIN_API
+    HandleContext::Maker maker(CSPHandle);
+    maker.setup(DeriveKeyType, CSSMERR_CSP_INVALID_ATTR_KEY_TYPE);
+    maker.setup(DeriveKeyLengthInBits, CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH);
+    maker.setup(AccessCred);
+    maker.setup(BaseKey);
+    maker.setup(IterationCount);
+    maker.setup(Salt);
+    maker.setup(Seed);
+    maker.make();
+    maker.put(CSSM_ATTRIBUTE_KEY_TYPE, DeriveKeyType);
+    maker.put(CSSM_ATTRIBUTE_KEY_LENGTH, DeriveKeyLengthInBits);
+    maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred);
+    maker.put(CSSM_ATTRIBUTE_KEY, BaseKey);
+    maker.put(CSSM_ATTRIBUTE_ITERATION_COUNT, IterationCount);
+    maker.put(CSSM_ATTRIBUTE_SALT, Salt);
+    maker.put(CSSM_ATTRIBUTE_SEED, Seed);
+    Required(NewContextHandle) = maker(CSSM_ALGCLASS_DERIVEKEY, AlgorithmID);
+    END_API(CSSM)
+}
+
+
+CSSM_RETURN CSSMAPI
+CSSM_CSP_CreateKeyGenContext (CSSM_CSP_HANDLE CSPHandle,
+                              CSSM_ALGORITHMS AlgorithmID,
+                              uint32 KeySizeInBits,
+                              const CSSM_CRYPTO_DATA *Seed,
+                              const CSSM_DATA *Salt,
+                              const CSSM_DATE *StartDate,
+                              const CSSM_DATE *EndDate,
+                              const CSSM_DATA *Params,
+                              CSSM_CC_HANDLE *NewContextHandle)
+{
+    BEGIN_API
+    HandleContext::Maker maker(CSPHandle);
+    maker.setup(KeySizeInBits, CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH);
+    maker.setup(Seed);
+    maker.setup(Salt);
+    maker.setup(StartDate);
+    maker.setup(EndDate);
+    maker.setup(Params);
+    maker.make();
+    maker.put(CSSM_ATTRIBUTE_KEY_LENGTH, KeySizeInBits);
+    maker.put(CSSM_ATTRIBUTE_SEED, Seed);
+    maker.put(CSSM_ATTRIBUTE_SALT, Salt);
+    maker.put(CSSM_ATTRIBUTE_START_DATE, StartDate);
+    maker.put(CSSM_ATTRIBUTE_END_DATE, EndDate);
+    maker.put(CSSM_ATTRIBUTE_ALG_PARAMS, Params);
+    Required(NewContextHandle) = maker(CSSM_ALGCLASS_KEYGEN, AlgorithmID);
+    END_API(CSSM)
+}
+
+
+CSSM_RETURN CSSMAPI
+CSSM_CSP_CreatePassThroughContext (CSSM_CSP_HANDLE CSPHandle,
+                                   const CSSM_KEY *Key,
+                                   CSSM_CC_HANDLE *NewContextHandle)
+{
+    BEGIN_API
+    HandleContext::Maker maker(CSPHandle);
+    maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY);
+    maker.make();
+    maker.put(CSSM_ATTRIBUTE_KEY, Key);
+    Required(NewContextHandle) = maker(CSSM_ALGCLASS_NONE, CSSM_ALGID_NONE);
+    END_API(CSSM)
+}
+
+
+//
+// CSSM_GetContext makes a deep copy of a CSP context and hands it to the
+// caller. The result is NOT a HandleContext, but a bare Context that is
+// in no dictionaries etc. User must delete it by calling CSSM_FreeContext.
+//
+CSSM_RETURN CSSMAPI
+CSSM_GetContext (CSSM_CC_HANDLE CCHandle,
+                 CSSM_CONTEXT_PTR *ContextP)
+{
+    BEGIN_API
+#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE
+    HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
+    Context *newContext = new(context.attachment) Context(context.type(), context.algorithm());
+    try {
+        newContext->CSPHandle = context.attachment.handle();
+        newContext->copyFrom(context, context.attachment);
+        Required(ContextP) = newContext;
+    } catch (...) {
+        context.attachment.free(newContext);
+        throw;
+    }
+    END_API(CSSM)
+}
+
+
+//
+// Since we allocated all the data in one fell heap, our FreeContext
+// function is disappointingly simple.
+//
+CSSM_RETURN CSSMAPI
+CSSM_FreeContext (CSSM_CONTEXT_PTR ContextP)
+{
+    BEGIN_API
+    Context *context = &Context::required(ContextP);
+    context->destroy(context, HandleObject::find<CSPAttachment>(context->CSPHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE));
+    END_API(CSSM)
+}
+
+
+CSSM_RETURN CSSMAPI
+CSSM_SetContext (CSSM_CC_HANDLE CCHandle,
+                 const CSSM_CONTEXT *ContextP)
+{
+    BEGIN_API
+    const Context &source = Context::required(ContextP);
+#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE
+    HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
+
+    CSSM_CONTEXT_ATTRIBUTE *oldAttributes = context.ContextAttributes;
+    uint32 oldCount = context.NumberOfAttributes;
+       CSSM_CONTEXT_TYPE oldType = context.ContextType;
+    CSSM_ALGORITHMS oldAlgorithm = context.AlgorithmType;
+    
+    context.copyFrom(source, context.attachment);
+       context.ContextType = source.ContextType;
+    context.AlgorithmType = source.AlgorithmType;
+    
+    if (CSSM_RETURN err = context.validateChange(CSSM_CONTEXT_EVENT_UPDATE)) {
+               context.attachment.free(context.ContextAttributes);     // free rejected attribute blob
+       context.ContextAttributes = oldAttributes;      // restore...
+       context.NumberOfAttributes = oldCount;          // ... old
+               context.ContextType = oldType;                          //  ... values
+       context.AlgorithmType = oldAlgorithm;           //   ... in context
+       CssmError::throwMe(err);                                                // tell the caller it failed
+    }
+    
+    context.attachment.free(oldAttributes);
+    END_API(CSSM)
+}
+
+
+CSSM_RETURN CSSMAPI
+CSSM_DeleteContext (CSSM_CC_HANDLE CCHandle)
+{
+    BEGIN_API
+    HandleContext &context = enterContext(CCHandle);
+       StLock<CountingMutex, &CountingMutex::enter, &CountingMutex::exit> 
+               _(context.attachment, true);
+    
+    // ignore error return from CSP event notify (can't decline deletion)
+    context.validateChange(CSSM_CONTEXT_EVENT_DELETE);
+       
+    context.destroy(&context, context.attachment);
+    END_API(CSSM)
+}
+
+
+//
+// The GetContextAttribute API is fatally flawed. The standard implies a deep
+// copy of the attribute value, but no release function exists. Instead, we
+// return a shallow copy (sharing structure) which you need not release, but
+// which becomes invalid when the source Context is destroyed.
+//
+CSSM_RETURN CSSMAPI
+CSSM_GetContextAttribute (const CSSM_CONTEXT *Context,
+                          uint32 AttributeType,
+                          CSSM_CONTEXT_ATTRIBUTE_PTR *ContextAttribute)
+{
+    BEGIN_API
+    CSSM_ATTRIBUTE_TYPE type = CSSM_ATTRIBUTE_TYPE(AttributeType);     // CDSA defect
+    Required(ContextAttribute) = Context::required(Context).find(type);
+    END_API(CSSM)
+}
+
+
+CSSM_RETURN CSSMAPI
+CSSM_UpdateContextAttributes (CSSM_CC_HANDLE CCHandle,
+                              uint32 NumberAttributes,
+                              const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes)
+{
+    BEGIN_API
+#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE
+    HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
+    context.mergeAttributes(ContextAttributes, NumberAttributes);
+    END_API(CSSM)
+}
+
+
+CSSM_RETURN CSSMAPI
+CSSM_DeleteContextAttributes (CSSM_CC_HANDLE CCHandle,
+                              uint32 NumberOfAttributes,
+                              const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes)
+{
+    BEGIN_API
+    if (NumberOfAttributes == 0)
+        return CSSM_OK;        // I suppose
+    Required(ContextAttributes); // preflight
+#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE
+    HandleContext &context = HandleObject::find<HandleContext>((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
+    for (uint32 n = 0; n < NumberOfAttributes; n++)
+        context.deleteAttribute(ContextAttributes[n].AttributeType);
+    END_API(CSSM)
+}
+
+
+//
+// Miscellaneous odds and ends - these functions just need a wee bit of
+// manual massaging to fit.
+//
+CSSM_RETURN CSSMAPI
+CSSM_DigestDataClone (CSSM_CC_HANDLE ccHandle,
+                      CSSM_CC_HANDLE *newCCHandle)
+{
+       BEGIN_API
+#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE
+    HandleContext &context = HandleObject::findAndLock<HandleContext>((CSSM_HANDLE)ccHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
+       TransitLock _(context.attachment);
+    HandleContext *newContext =
+       new(context.attachment) HandleContext(context.attachment, context.type(), context.algorithm());
+    try {
+        newContext->CSPHandle = context.attachment.handle();
+        newContext->copyFrom(context, context.attachment);
+               context.attachment.downcalls.DigestDataClone(context.attachment.handle(), ccHandle, newContext->handle());
+        Required(newCCHandle) = newContext->handle();
+    } catch (...) {
+       newContext->destroy(newContext, context.attachment);
+        throw;
+    }
+       END_API(CSSM)
+}
+
+
+CSSM_RETURN CSSMAPI
+CSSM_QueryKeySizeInBits (CSSM_CSP_HANDLE CSPHandle,
+                         CSSM_CC_HANDLE ccHandle,
+                         const CSSM_KEY *key,
+                         CSSM_KEY_SIZE_PTR keySize)
+{
+       //@@@ could afford not to lock attachment in have-CC case
+       BEGIN_API
+       Required(keySize);
+       Context *context;
+       CSPAttachment *attachment;
+       if (ccHandle == (CSSM_CC_HANDLE) HandleObject::invalidHandle) {
+               // key specified by CSPHandle and Key
+               attachment = &enterAttachment<CSPAttachment>(CSPHandle);
+               context = NULL;
+       } else {
+               // key specified by ccHandle
+               HandleContext *ctx = &enterContext(ccHandle);
+               try {
+                       attachment = &ctx->attachment;
+            context = ctx;
+                       CSPHandle = context->CSPHandle;
+                       key = &context->get<CssmKey>(CSSM_ATTRIBUTE_KEY,
+                                                                                CSSMERR_CSP_INVALID_KEY);
+               } catch (...) {
+                       attachment->exit();
+                       throw;
+               }
+       }
+       TransitLock _(*attachment);
+       CSSM_RETURN result = attachment->downcalls.QueryKeySizeInBits(CSPHandle,
+                       ccHandle, context, key, keySize);
+       return result;
+       END_API(CSSM)
+}
+
+
+CSSM_RETURN CSSMAPI
+CSSM_GenerateAlgorithmParams (CSSM_CC_HANDLE CCHandle,
+                              uint32 ParamBits,
+                              CSSM_DATA_PTR Param)
+{
+       BEGIN_API
+    // this function has more subtle locking than usual. Pay attention:
+
+    // (1) Resolve context and ensure attachment exit
+       HandleContext &context = enterContext(CCHandle);
+    StLock<CountingMutex, &CountingMutex::enter, &CountingMutex::exit> _(context.attachment, true);
+    
+    // (2) Call CSP, acquiring module safe-lock for a moment (only)
+       CSSM_CONTEXT_ATTRIBUTE_PTR attributes;
+       uint32 count;
+    {
+        StLock<Module, &Module::safeLock, &Module::safeUnlock> _(context.attachment.module);
+        if (CSSM_RETURN err =
+                context.attachment.downcalls.GenerateAlgorithmParams(context.attachment.handle(),
+                CCHandle, &context,
+                ParamBits, Param,
+                &count, &attributes))
+            CssmError::throwMe(err);
+    }
+    
+    // (3) Merge the attributes returned into the context, which will (again) acquire the module safe-lock internally
+       if (count)
+           context.mergeAttributes(attributes, count);
+    // the memory at (attributes, count) belongs to the CSP; don't free it here
+       END_API(CSSM)
+}
+
+
+//
+// Include the auto-generated functions
+//
+#include <derived_src/transition.gen>