/* * Copyright (c) 2000-2004 Apple Computer, 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