/* * Copyright (c) 2000-2002 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. */ // // cspclient - client interface to CSSM CSPs and their operations // #include namespace Security { namespace CssmClient { // // Manage CSP attachments // CSPImpl::CSPImpl(const Guid &guid) : AttachmentImpl(guid, CSSM_SERVICE_CSP) { } CSPImpl::CSPImpl(const Module &module) : AttachmentImpl(module, CSSM_SERVICE_CSP) { } CSPImpl::~CSPImpl() { } // // Delete a key explicitly // void CSPImpl::freeKey(CssmKey &key, const AccessCredentials *cred, bool permanent) { check(CSSM_FreeKey(handle(), cred, &key, permanent)); } // // Manage generic context objects // Context::Context(const CSP &csp, CSSM_ALGORITHMS alg) : ObjectImpl(csp), mAlgorithm(alg), mStaged(false), mCred(NULL) { } Context::~Context() { try { deactivate(); } catch(...) {} } void Context::init() { CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); } void Context::deactivate() { if (mActive) { mActive = false; check(CSSM_DeleteContext(mHandle)); } } void Context::algorithm(CSSM_ALGORITHMS alg) { if (isActive()) abort(); //@@@ can't (currently?) change algorithm with active context mAlgorithm = alg; } void Context::cred(const CSSM_ACCESS_CREDENTIALS *cred) { mCred = AccessCredentials::overlay(cred); set(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, *mCred); } // // Query context operation output sizes. // uint32 Context::getOutputSize(uint32 inputSize, bool encrypt /*= true*/) { CSSM_QUERY_SIZE_DATA data; data.SizeInputBlock = inputSize; getOutputSize(data, 1, encrypt); return data.SizeOutputBlock; } void Context::getOutputSize(CSSM_QUERY_SIZE_DATA &sizes, uint32 count, bool encrypt /*= true*/) { check(CSSM_QuerySize(handle(), encrypt, count, &sizes)); } // // The override() method of Context is an expert feature. It replaces the entire // context with a context object provided. It is up to the caller to keep this context // consistent with the purpose of the Context subclass he is (mis)using. // This feature is currently used by the SecurityServer. // void Context::override(const Security::Context &ctx) { if (!isActive()) { // make a valid context object (it doesn't matter what kind - keep it cheap) check(CSSM_CSP_CreateDigestContext(attachment()->handle(), CSSM_ALGID_NONE, &mHandle)); } // now replace everything with the context data provided check(CSSM_SetContext(mHandle, &ctx)); mActive = true; // now active } // // RccContexts // const ResourceControlContext &RccBearer::compositeRcc() const { // explicitly specified RCC wins if (mRcc) return *mRcc; // cobble one up from the pieces if (mOwner) mWorkRcc.input() = *mOwner; else mWorkRcc.clearPod(); mWorkRcc.credentials(mOpCred); return mWorkRcc; } void RccBearer::owner(const CSSM_ACL_ENTRY_PROTOTYPE *owner) { if (owner) { mWorkInput = *owner; this->owner(mWorkInput); } else this->owner((AclEntryInput*)NULL); } // // Manage PassThrough contexts // // // Invoke passThrough // void PassThrough::operator() (uint32 passThroughId, const void *inData, void **outData) { check(CSSM_CSP_PassThrough(handle(), passThroughId, inData, outData)); } void PassThrough::activate() { if (!mActive) { check(CSSM_CSP_CreatePassThroughContext(attachment()->handle(), mKey, &mHandle)); mActive = true; } } // // Manage Digest contexts // void Digest::activate() { if (!mActive) { check(CSSM_CSP_CreateDigestContext(attachment()->handle(), mAlgorithm, &mHandle)); mActive = true; } } void Digest::digest(const CssmData *data, uint32 count, CssmData &digest) { activate(); if (mStaged) Error::throwMe(CSSMERR_CSP_STAGED_OPERATION_IN_PROGRESS); check(CSSM_DigestData(handle(), data, count, &digest)); } void Digest::digest(const CssmData *data, uint32 count) { activate(); if (!mStaged) { check(CSSM_DigestDataInit(handle())); mStaged = true; } check(CSSM_DigestDataUpdate(handle(), data, count)); } void Digest::operator () (CssmData &digest) { if (!mStaged) Error::throwMe(CSSMERR_CSP_STAGED_OPERATION_NOT_STARTED); check(CSSM_DigestDataFinal(handle(), &digest)); mStaged = false; } // // Random number generation // void Random::seed(const CssmCryptoData &seedData) { mSeed = &seedData; set(CSSM_ATTRIBUTE_SEED, seedData); } void Random::size(uint32 sz) { mSize = sz; set(CSSM_ATTRIBUTE_OUTPUT_SIZE, sz); } void Random::activate() { if (!mActive) { check(CSSM_CSP_CreateRandomGenContext(attachment()->handle(), mAlgorithm, mSeed, mSize, &mHandle)); mActive = true; } } void Random::generate(CssmData &data, uint32 newSize) { if (newSize) size(newSize); activate(); assert(!mStaged); // not a stage-able operation check(CSSM_GenerateRandom(handle(), &data)); } } // end namespace CssmClient } // end namespace Security