X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_cssm/lib/transition.cpp?ds=inline diff --git a/Security/libsecurity_cssm/lib/transition.cpp b/Security/libsecurity_cssm/lib/transition.cpp new file mode 100644 index 00000000..99c81b06 --- /dev/null +++ b/Security/libsecurity_cssm/lib/transition.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include + + +// +// Names for the standard Attachment types +// +typedef StandardAttachment CSPAttachment; +typedef StandardAttachment DLAttachment; +typedef StandardAttachment CLAttachment; +typedef StandardAttachment ACAttachment; +typedef StandardAttachment 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((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(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((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 + _(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((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((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((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(CSPHandle); + context = NULL; + } else { + // key specified by ccHandle + HandleContext *ctx = &enterContext(ccHandle); + try { + attachment = &ctx->attachment; + context = ctx; + CSPHandle = context->CSPHandle; + key = &context->get(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 _(context.attachment, true); + + // (2) Call CSP, acquiring module safe-lock for a moment (only) + CSSM_CONTEXT_ATTRIBUTE_PTR attributes; + uint32 count; + { + StLock _(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