X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/libsecurity_cdsa_plugin/lib/CSPsession.cpp?ds=inline diff --git a/libsecurity_cdsa_plugin/lib/CSPsession.cpp b/libsecurity_cdsa_plugin/lib/CSPsession.cpp deleted file mode 100644 index d3eb9608..00000000 --- a/libsecurity_cdsa_plugin/lib/CSPsession.cpp +++ /dev/null @@ -1,1156 +0,0 @@ -/* - * 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. - */ - - -// -// CSPsession - Plugin framework for CSP plugin modules -// -#include -#include -#include - - -typedef CSPFullPluginSession::CSPContext CSPContext; - - -// -// PluginContext construction -// -CSPPluginSession::PluginContext::~PluginContext() -{ /* virtual */ } - -CSPFullPluginSession::AlgorithmFactory::~AlgorithmFactory() -{ /* virtual */ } - - -// -// Internal utilities -// -CssmData CSPFullPluginSession::makeBuffer(size_t size, Allocator &alloc) -{ - return CssmData(alloc.malloc(size), size); -} - -inline size_t CSPFullPluginSession::totalBufferSize(const CssmData *data, uint32 count) -{ - size_t size = 0; - for (uint32 n = 0; n < count; n++) - size += data[n].length(); - return size; -} - - -// -// Notify a context that its underlying CSSM context has (well, may have) changed. -// The default reaction is to ask the frame to delete the context and start over. -// -bool CSPPluginSession::PluginContext::changed(const Context &context) -{ - return false; // delete me, please -} - - -// -// The Session's init() function calls your setupContext() method to prepare -// it for action, then calls the context's init() method. -// -CSPContext *CSPFullPluginSession::init(CSSM_CC_HANDLE ccHandle, - CSSM_CONTEXT_TYPE type, - const Context &context, bool encoding) -{ - CSPContext *ctx = getContext(ccHandle); - checkOperation(context.type(), type); - - // ask the implementation to set up an internal context - setupContext(ctx, context, encoding); - assert(ctx != NULL); // must have context now (@@@ throw INTERNAL_ERROR instead?) - ctx->mType = context.type(); - ctx->mDirection = encoding; - setContext(ccHandle, ctx); - - // initialize the context and return it - ctx->init(context, encoding); - return ctx; -} - - -// -// Retrieve a context for a staged operation in progress. -// -CSPContext *CSPFullPluginSession::getStagedContext(CSSM_CC_HANDLE ccHandle, - CSSM_CONTEXT_TYPE type, bool encoding) -{ - CSPContext *ctx = getContext(ccHandle); - if (ctx == NULL) - CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT); //@@@ better diagnostic? - checkOperation(ctx->type(), type); - if (ctx->encoding() != encoding) - CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT); - return ctx; -} - - -// -// The Session's checkState() function is called for subsequent staged operations -// (update/final) to verify that the user didn't screw up the sequencing. -// -void CSPFullPluginSession::checkOperation(CSSM_CONTEXT_TYPE ctxType, CSSM_CONTEXT_TYPE opType) -{ - switch (opType) { - case CSSM_ALGCLASS_NONE: // no check - return; - case CSSM_ALGCLASS_CRYPT: // symmetric or asymmetric encryption - if (ctxType == CSSM_ALGCLASS_SYMMETRIC || - ctxType == CSSM_ALGCLASS_ASYMMETRIC) - return; - default: // plain match - if (ctxType == opType) - return; - } - CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT); -} - - -// -// The default implementations of the primary context operations throw internal -// errors. You must implement any of these that are actually called by the -// operations involved. The others, of course, can be left alone. -// -void CSPContext::init(const Context &context, bool encoding) -{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } - -void CSPContext::update(const CssmData &data) -{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } - -void CSPContext::update(void *inp, size_t &inSize, void *outp, size_t &outSize) -{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } - -void CSPContext::final(CssmData &out) -{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } - -void CSPContext::final(const CssmData &in) -{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } - -void CSPContext::generate(const Context &, CssmKey &pubKey, CssmKey &privKey) -{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } - -void CSPContext::generate(const Context &, uint32, CssmData ¶ms, - uint32 &attrCount, Context::Attr * &attrs) -{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } - -size_t CSPContext::inputSize(size_t outSize) -{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } - -size_t CSPContext::outputSize(bool final, size_t inSize) -{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } - -void CSPContext::minimumProgress(size_t &in, size_t &out) -{ CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } - -CSPFullPluginSession::CSPContext *CSPContext::clone(Allocator &) -{ CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); } - -void CSPContext::setDigestAlgorithm(CSSM_ALGORITHMS digestAlg) -{ CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); } - -void CSPContext::update(const CssmData *in, - uint32 inCount, Writer &writer) -{ - const CssmData *lastIn = in + inCount; - CssmData current; - for (;;) { - if (current.length() == 0) { - if (in == lastIn) - return; // all done - current = *in++; - continue; // Just in case next block is zero length too. - } - // match up current input and output buffers - void *outP; size_t outSize; - writer.nextBlock(outP, outSize); - size_t inSize = inputSize(outSize); - if (inSize > current.length()) - inSize = current.length(); // cap to remaining input buffer - if (inSize > 0) { - // we can stuff into the current output buffer - do it - update(current.data(), inSize, outP, outSize); - current.use(inSize); - writer.use(outSize); - } else { - // We have remaining output buffer space, but not enough - // for the algorithm to make progress with it. We must proceed with - // a bounce buffer and split it manually into this and the next buffer(s). - size_t minOutput; - minimumProgress(inSize, minOutput); - assert(minOutput > outSize); // PluginContext consistency (not fatal) - char splitBuffer[128]; - assert(minOutput <= sizeof(splitBuffer)); // @@@ static buffer for now - outSize = sizeof(splitBuffer); - if (current.length() < inSize) - inSize = current.length(); // cap to data remaining in input buffer - update(current.data(), inSize, splitBuffer, outSize); - assert(inSize > 0); // progress made - writer.put(splitBuffer, outSize); // stuff into buffer, the hard way - current.use(inSize); - } - } -} - -void CSPContext::final(CssmData &out, Allocator &alloc) -{ - size_t needed = outputSize(true, 0); - if (out) { - if (out.length() < needed) - CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); - } else { - out = makeBuffer(needed, alloc); - } - final(out); -} - -void CSPContext::final(Writer &writer, Allocator &alloc) -{ - if (size_t needed = outputSize(true, 0)) { - // need to generate additional output - writer.allocate(needed, alloc); // belt + suspender - - void *addr; size_t size; - writer.nextBlock(addr, size); // next single block available - if (needed <= size) { // rest fits into one block - CssmData chunk(addr, size); - final(chunk); - writer.use(chunk.length()); - } else { // need to split it up - char splitBuffer[128]; - assert(needed <= sizeof(splitBuffer)); - CssmData chunk(splitBuffer, sizeof(splitBuffer)); - final(chunk); - writer.put(chunk.data(), chunk.length()); - } - } -} - - -// -// Default context response functions -// -CSPPluginSession::PluginContext * -CSPPluginSession::contextCreate(CSSM_CC_HANDLE, const Context &) -{ - return NULL; // request no local context -} - -void CSPPluginSession::contextUpdate(CSSM_CC_HANDLE ccHandle, - const Context &context, PluginContext * &ctx) -{ - // call update notifier in context object - if (ctx && !ctx->changed(context)) { - // context requested that it be removed - delete ctx; - ctx = NULL; - } -} - -void CSPPluginSession::contextDelete(CSSM_CC_HANDLE, const Context &, PluginContext *) -{ - // do nothing (you can't prohibit deletion here) -} - - -// -// Default event notification handler. -// This default handler calls the virtual context* methods to dispose of context actions. -// -void CSPPluginSession::EventNotify(CSSM_CONTEXT_EVENT event, - CSSM_CC_HANDLE ccHandle, const Context &context) -{ - switch (event) { - case CSSM_CONTEXT_EVENT_CREATE: - if (PluginContext *ctx = contextCreate(ccHandle, context)) { - StLock _(contextMapLock); - assert(contextMap[ccHandle] == NULL); // check context re-creation - contextMap[ccHandle] = ctx; - } - break; - case CSSM_CONTEXT_EVENT_UPDATE: - // note that the handler can change the map entry (even to NULL, if desired) - { - StLock _(contextMapLock); - contextUpdate(ccHandle, context, contextMap[ccHandle]); - } - break; - case CSSM_CONTEXT_EVENT_DELETE: - { - StLock _(contextMapLock); - if (PluginContext *ctx = contextMap[ccHandle]) { - contextDelete(ccHandle, context, ctx); - delete ctx; - } - contextMap.erase(ccHandle); - } - break; - default: - CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); // unexpected event code - } -} - - -// -// Defaults for methods you *should* implement. -// If you don't, they'll throw UNIMPLEMENTED. -// -void CSPFullPluginSession::getKeySize(const CssmKey &key, CSSM_KEY_SIZE &size) -{ unimplemented(); } - - -// -// Encryption and decryption -// -void CSPFullPluginSession::EncryptData(CSSM_CC_HANDLE ccHandle, - const Context &context, - const CssmData clearBufs[], - uint32 clearBufCount, - CssmData cipherBufs[], - uint32 cipherBufCount, - CSSM_SIZE &bytesEncrypted, - CssmData &remData, - CSSM_PRIVILEGE privilege) -{ - Writer writer(cipherBufs, cipherBufCount, &remData); - CSPContext *ctx = init(ccHandle, CSSM_ALGCLASS_CRYPT, context, true); - size_t outNeeded = ctx->outputSize(true, totalBufferSize(clearBufs, clearBufCount)); - writer.allocate(outNeeded, *this); - ctx->update(clearBufs, clearBufCount, writer); - ctx->final(writer, *this); - bytesEncrypted = writer.close(); -} - -void CSPFullPluginSession::EncryptDataInit(CSSM_CC_HANDLE ccHandle, - const Context &context, - CSSM_PRIVILEGE Privilege) -{ - init(ccHandle, CSSM_ALGCLASS_CRYPT, context, true); -} - -void CSPFullPluginSession::EncryptDataUpdate(CSSM_CC_HANDLE ccHandle, - const CssmData clearBufs[], - uint32 clearBufCount, - CssmData cipherBufs[], - uint32 cipherBufCount, - CSSM_SIZE &bytesEncrypted) -{ - CSPContext *alg = getStagedContext(ccHandle, CSSM_ALGCLASS_CRYPT, true); - Writer writer(cipherBufs, cipherBufCount); - size_t outNeeded = alg->outputSize(false, totalBufferSize(clearBufs, clearBufCount)); - writer.allocate(outNeeded, *this); - alg->update(clearBufs, clearBufCount, writer); - bytesEncrypted = writer.close(); -} - -void CSPFullPluginSession::EncryptDataFinal(CSSM_CC_HANDLE ccHandle, - CssmData &remData) -{ - getStagedContext(ccHandle, CSSM_ALGCLASS_CRYPT, true)->final(remData, *this); -} - - -void CSPFullPluginSession::DecryptData(CSSM_CC_HANDLE ccHandle, - const Context &context, - const CssmData cipherBufs[], - uint32 cipherBufCount, - CssmData clearBufs[], - uint32 clearBufCount, - CSSM_SIZE &bytesDecrypted, - CssmData &remData, - CSSM_PRIVILEGE privilege) -{ - Writer writer(clearBufs, clearBufCount, &remData); - CSPContext *ctx = init(ccHandle, CSSM_ALGCLASS_CRYPT, context, false); - size_t outNeeded = ctx->outputSize(true, totalBufferSize(cipherBufs, cipherBufCount)); - writer.allocate(outNeeded, *this); - ctx->update(cipherBufs, cipherBufCount, writer); - ctx->final(writer, *this); - bytesDecrypted = writer.close(); -} - -void CSPFullPluginSession::DecryptDataInit(CSSM_CC_HANDLE ccHandle, - const Context &context, - CSSM_PRIVILEGE Privilege) -{ - init(ccHandle, CSSM_ALGCLASS_CRYPT, context, false); -} - -void CSPFullPluginSession::DecryptDataUpdate(CSSM_CC_HANDLE ccHandle, - const CssmData cipherBufs[], - uint32 cipherBufCount, - CssmData clearBufs[], - uint32 clearBufCount, - CSSM_SIZE &bytesDecrypted) -{ - CSPContext *ctx = getStagedContext(ccHandle, CSSM_ALGCLASS_CRYPT, false); - Writer writer(clearBufs, clearBufCount); - size_t outNeeded = ctx->outputSize(false, totalBufferSize(cipherBufs, cipherBufCount)); - writer.allocate(outNeeded, *this); - ctx->update(cipherBufs, cipherBufCount, writer); - bytesDecrypted = writer.close(); -} - -void CSPFullPluginSession::DecryptDataFinal(CSSM_CC_HANDLE ccHandle, - CssmData &remData) -{ - getStagedContext(ccHandle, CSSM_ALGCLASS_CRYPT, false)->final(remData, *this); -} - -void CSPFullPluginSession::QuerySize(CSSM_CC_HANDLE ccHandle, - const Context &context, - CSSM_BOOL encrypt, - uint32 querySizeCount, - QuerySizeData *dataBlock) -{ - if (querySizeCount == 0) - return; // nothing ventured, nothing gained - CSPContext *ctx = getContext(ccHandle); // existing context? - if (ctx == NULL) // force internal context creation (as best we can) - ctx = init(ccHandle, context.type(), context, encrypt); - // If QuerySizeCount > 1, we assume this inquires about a staged - // operation, and the LAST item gets the 'final' treatment. - //@@@ Intel revised algspec says "use the staged flag" -- TBD - for (uint32 n = 0; n < querySizeCount; n++) { - // the outputSize() call might throw CSSMERR_CSP_QUERY_SIZE_UNKNOWN - dataBlock[n].SizeOutputBlock = - (uint32)ctx->outputSize(n == querySizeCount-1, dataBlock[n].inputSize()); - } - //@@@ if we forced a context creation, should we discard it now? -} - - -// -// Key wrapping and unwrapping. -// -void CSPFullPluginSession::WrapKey(CSSM_CC_HANDLE CCHandle, - const Context &Context, - const AccessCredentials &AccessCred, - const CssmKey &Key, - const CssmData *DescriptiveData, - CssmKey &WrappedKey, - CSSM_PRIVILEGE Privilege) -{ - unimplemented(); -} - -void CSPFullPluginSession::UnwrapKey(CSSM_CC_HANDLE CCHandle, - const Context &Context, - const CssmKey *PublicKey, - const CssmKey &WrappedKey, - uint32 KeyUsage, - uint32 KeyAttr, - const CssmData *KeyLabel, - const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, - CssmKey &UnwrappedKey, - CssmData &DescriptiveData, - CSSM_PRIVILEGE Privilege) -{ - unimplemented(); -} - -void CSPFullPluginSession::DeriveKey(CSSM_CC_HANDLE CCHandle, - const Context &Context, - CssmData &Param, - uint32 KeyUsage, - uint32 KeyAttr, - const CssmData *KeyLabel, - const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, - CssmKey &DerivedKey) -{ - unimplemented(); -} - - -// -// Message Authentication Codes. -// Almost like signatures (signatures with symmetric keys), though the -// underlying implementation may be somewhat different. -// -void CSPFullPluginSession::GenerateMac(CSSM_CC_HANDLE ccHandle, - const Context &context, - const CssmData dataBufs[], - uint32 dataBufCount, - CssmData &mac) -{ - GenerateMacInit(ccHandle, context); - GenerateMacUpdate(ccHandle, dataBufs, dataBufCount); - GenerateMacFinal(ccHandle, mac); -} - -void CSPFullPluginSession::GenerateMacInit(CSSM_CC_HANDLE ccHandle, - const Context &context) -{ - init(ccHandle, CSSM_ALGCLASS_MAC, context, true); -} - -void CSPFullPluginSession::GenerateMacUpdate(CSSM_CC_HANDLE ccHandle, - const CssmData dataBufs[], - uint32 dataBufCount) -{ - getStagedContext(ccHandle, CSSM_ALGCLASS_MAC, true)->update(dataBufs, dataBufCount); -} - -void CSPFullPluginSession::GenerateMacFinal(CSSM_CC_HANDLE ccHandle, - CssmData &mac) -{ - getStagedContext(ccHandle, CSSM_ALGCLASS_MAC, true)->final(mac, *this); -} - -void CSPFullPluginSession::VerifyMac(CSSM_CC_HANDLE ccHandle, - const Context &context, - const CssmData dataBufs[], - uint32 dataBufCount, - const CssmData &mac) -{ - VerifyMacInit(ccHandle, context); - VerifyMacUpdate(ccHandle, dataBufs, dataBufCount); - VerifyMacFinal(ccHandle, mac); -} - -void CSPFullPluginSession::VerifyMacInit(CSSM_CC_HANDLE ccHandle, - const Context &context) -{ - init(ccHandle, CSSM_ALGCLASS_MAC, context, false); -} - -void CSPFullPluginSession::VerifyMacUpdate(CSSM_CC_HANDLE ccHandle, - const CssmData dataBufs[], - uint32 dataBufCount) -{ - getStagedContext(ccHandle, CSSM_ALGCLASS_MAC, false)->update(dataBufs, dataBufCount); -} - -void CSPFullPluginSession::VerifyMacFinal(CSSM_CC_HANDLE ccHandle, - const CssmData &mac) -{ - getStagedContext(ccHandle, CSSM_ALGCLASS_MAC, false)->final(mac); -} - - -// -// Signatures -// -void CSPFullPluginSession::SignData(CSSM_CC_HANDLE ccHandle, - const Context &context, - const CssmData dataBufs[], - uint32 dataBufCount, - CSSM_ALGORITHMS digestAlgorithm, - CssmData &Signature) -{ - SignDataInit(ccHandle, context); - if(digestAlgorithm != CSSM_ALGID_NONE) { - getStagedContext(ccHandle, CSSM_ALGCLASS_SIGNATURE, - true)->setDigestAlgorithm(digestAlgorithm); - } - SignDataUpdate(ccHandle, dataBufs, dataBufCount); - SignDataFinal(ccHandle, Signature); -} - -void CSPFullPluginSession::SignDataInit(CSSM_CC_HANDLE ccHandle, - const Context &context) -{ - init(ccHandle, CSSM_ALGCLASS_SIGNATURE, context, true); -} - -void CSPFullPluginSession::SignDataUpdate(CSSM_CC_HANDLE ccHandle, - const CssmData dataBufs[], - uint32 dataBufCount) -{ - getStagedContext(ccHandle, CSSM_ALGCLASS_SIGNATURE, true)->update(dataBufs, dataBufCount); -} - -void CSPFullPluginSession::SignDataFinal(CSSM_CC_HANDLE ccHandle, - CssmData &signature) -{ - getStagedContext(ccHandle, CSSM_ALGCLASS_SIGNATURE, true)->final(signature, *this); -} - - -void CSPFullPluginSession::VerifyData(CSSM_CC_HANDLE ccHandle, - const Context &context, - const CssmData dataBufs[], - uint32 dataBufCount, - CSSM_ALGORITHMS digestAlgorithm, - const CssmData &Signature) -{ - VerifyDataInit(ccHandle, context); - if(digestAlgorithm != CSSM_ALGID_NONE) { - getStagedContext(ccHandle, CSSM_ALGCLASS_SIGNATURE, - false)->setDigestAlgorithm(digestAlgorithm); - } - VerifyDataUpdate(ccHandle, dataBufs, dataBufCount); - VerifyDataFinal(ccHandle, Signature); -} - -void CSPFullPluginSession::VerifyDataInit(CSSM_CC_HANDLE ccHandle, const Context &context) -{ - init(ccHandle, CSSM_ALGCLASS_SIGNATURE, context, false); -} - -void CSPFullPluginSession::VerifyDataUpdate(CSSM_CC_HANDLE ccHandle, - const CssmData dataBufs[], - uint32 dataBufCount) -{ - getStagedContext(ccHandle, CSSM_ALGCLASS_SIGNATURE, false)->update(dataBufs, dataBufCount); -} - -void CSPFullPluginSession::VerifyDataFinal(CSSM_CC_HANDLE ccHandle, - const CssmData &signature) -{ - getStagedContext(ccHandle, CSSM_ALGCLASS_SIGNATURE, false)->final(signature); -} - - -// -// Digesting -// -void CSPFullPluginSession::DigestData(CSSM_CC_HANDLE ccHandle, - const Context &context, - const CssmData dataBufs[], - uint32 DataBufCount, - CssmData &Digest) -{ - DigestDataInit(ccHandle, context); - DigestDataUpdate(ccHandle, dataBufs, DataBufCount); - DigestDataFinal(ccHandle, Digest); -} - -void CSPFullPluginSession::DigestDataInit(CSSM_CC_HANDLE ccHandle, const Context &context) -{ - init(ccHandle, CSSM_ALGCLASS_DIGEST, context); -} - -void CSPFullPluginSession::DigestDataUpdate(CSSM_CC_HANDLE ccHandle, - const CssmData dataBufs[], - uint32 dataBufCount) -{ - getStagedContext(ccHandle, CSSM_ALGCLASS_DIGEST)->update(dataBufs, dataBufCount); -} - -void CSPFullPluginSession::DigestDataFinal(CSSM_CC_HANDLE ccHandle, - CssmData &digest) -{ - getStagedContext(ccHandle, CSSM_ALGCLASS_DIGEST)->final(digest, *this); -} - -void CSPFullPluginSession::DigestDataClone(CSSM_CC_HANDLE ccHandle, - CSSM_CC_HANDLE clonedCCHandle) -{ - CSPContext *cloned = getStagedContext(ccHandle, CSSM_ALGCLASS_DIGEST)->clone(*this); - cloned->mDirection = true; - cloned->mType = CSSM_ALGCLASS_DIGEST; - setContext(clonedCCHandle, cloned); -} - - -// -// Key generation, Derivation, and inquiry -// -void CSPFullPluginSession::GenerateKey(CSSM_CC_HANDLE ccHandle, - const Context &context, - uint32 keyUsage, - uint32 keyAttr, - const CssmData *keyLabel, - const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry, - CssmKey &key, - CSSM_PRIVILEGE privilege) -{ - CSPContext *alg = init(ccHandle, CSSM_ALGCLASS_KEYGEN, context); - setKey(key, context, CSSM_KEYCLASS_SESSION_KEY, keyAttr, keyUsage); - CssmKey blank; // dummy 2nd key (not used) - alg->generate(context, key, blank); -} - -class ContextMinder -{ -private: - CSSM_CC_HANDLE mHandle; - -public: - ContextMinder(CSSM_CC_HANDLE ccHandle) : mHandle(ccHandle) {} - ~ContextMinder() {CSSM_DeleteContext(mHandle);} -}; - - - -void CSPFullPluginSession::GenerateKeyPair(CSSM_CC_HANDLE ccHandle, - const Context &context, - uint32 publicKeyUsage, - uint32 publicKeyAttr, - const CssmData *publicKeyLabel, - CssmKey &publicKey, - uint32 privateKeyUsage, - uint32 privateKeyAttr, - const CssmData *privateKeyLabel, - const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry, - CssmKey &privateKey, - CSSM_PRIVILEGE privilege) -{ - CSPContext *alg = init(ccHandle, CSSM_ALGCLASS_KEYGEN, context); - - setKey(publicKey, context, CSSM_KEYCLASS_PUBLIC_KEY, publicKeyAttr, publicKeyUsage); - setKey(privateKey, context, CSSM_KEYCLASS_PRIVATE_KEY, privateKeyAttr, privateKeyUsage); - alg->generate(context, publicKey, privateKey); - - //@@@ handle labels - //@@@ handle reference keys - - bool encryptPublic = publicKeyUsage & CSSM_KEYUSE_ENCRYPT; - bool encryptPrivate = privateKeyUsage & CSSM_KEYUSE_ENCRYPT; - - if (!(encryptPublic || encryptPrivate)) - { - return ; - } - - // time to do the FIPS required test! - CSSM_CSP_HANDLE moduleHandle = handle(); - CSSM_CC_HANDLE encryptHandle; - CSSM_ACCESS_CREDENTIALS nullCreds; - memset(&nullCreds, 0, sizeof(nullCreds)); - - CSSM_KEY_PTR encryptingKey, decryptingKey; - if (encryptPublic) - { - encryptingKey = &publicKey; - decryptingKey = &privateKey; - } - else - { - encryptingKey = &privateKey; - decryptingKey = &publicKey; - } - - // make data to be encrypted - unsigned bytesInKey = encryptingKey->KeyHeader.LogicalKeySizeInBits / 8; - u_int8_t buffer[bytesInKey]; - unsigned i; - - for (i = 0; i < bytesInKey; ++i) - { - buffer[i] = i; - } - - CSSM_DATA clearBuf = {bytesInKey, buffer}; - CSSM_DATA cipherBuf; // have the CSP allocate the resulting memory - CSSM_SIZE bytesEncrypted; - CSSM_DATA remData = {0, NULL}; - CSSM_DATA decryptedBuf = {bytesInKey, buffer}; - - CSSM_RETURN result = CSSM_CSP_CreateAsymmetricContext(moduleHandle, encryptingKey->KeyHeader.AlgorithmId, &nullCreds, encryptingKey, CSSM_PADDING_NONE, &encryptHandle); - if (result != CSSM_OK) - { - CssmError::throwMe(result); - } - - ContextMinder encryptMinder(encryptHandle); // auto throw away if we error out - - CSSM_QUERY_SIZE_DATA qsData; - qsData.SizeInputBlock = bytesInKey; - result = CSSM_QuerySize(encryptHandle, CSSM_TRUE, 1, &qsData); - if (result == CSSMERR_CSP_INVALID_ALGORITHM) - { - return; - } - - uint8 cipherBuffer[qsData.SizeOutputBlock]; - cipherBuf.Length = qsData.SizeOutputBlock; - cipherBuf.Data = cipherBuffer; - - // do the encryption - result = CSSM_EncryptData(encryptHandle, &clearBuf, 1, &cipherBuf, 1, &bytesEncrypted, &remData); - if (result != CSSM_OK) - { - CssmError::throwMe(result); - } - - // check the result - if (memcmp(cipherBuf.Data, clearBuf.Data, clearBuf.Length) == 0) - { - // we have a match, that's not good news... - abort(); - } - - // clean up - if (remData.Data != NULL) - { - free(remData.Data); - } - - // make a context to perform the decryption - CSSM_CC_HANDLE decryptHandle; - result = CSSM_CSP_CreateAsymmetricContext(moduleHandle, encryptingKey->KeyHeader.AlgorithmId, &nullCreds, decryptingKey, CSSM_PADDING_NONE, &decryptHandle); - ContextMinder decryptMinder(decryptHandle); - - if (result != CSSM_OK) - { - CssmError::throwMe(result); - } - - result = CSSM_DecryptData(decryptHandle, &cipherBuf, 1, &decryptedBuf, 1, &bytesEncrypted, &remData); - if (result != CSSM_OK) - { - CssmError::throwMe(result); - } - - // check the results - for (i = 0; i < bytesInKey; ++i) - { - if (decryptedBuf.Data[i] != (i & 0xFF)) - { - // bad news - abort(); - } - } - - if (remData.Data != NULL) - { - free(remData.Data); - } -} - -void CSPFullPluginSession::ObtainPrivateKeyFromPublicKey(const CssmKey &PublicKey, - CssmKey &PrivateKey) -{ - unimplemented(); -} - -void CSPFullPluginSession::QueryKeySizeInBits(CSSM_CC_HANDLE ccHandle, - const Context *context, - const CssmKey *key, - CSSM_KEY_SIZE &keySize) -{ - if (context) { - getKeySize(context->get(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY), - keySize); - } else { - getKeySize(CssmKey::required(key), keySize); - } -} - - -// -// Free a key object. -// -void CSPFullPluginSession::FreeKey(const AccessCredentials *AccessCred, - CssmKey &key, - CSSM_BOOL Delete) -{ - free(key.data()); -} - - -// -// Random number and parameter generation -// -void CSPFullPluginSession::GenerateRandom(CSSM_CC_HANDLE ccHandle, - const Context &context, - CssmData &randomNumber) -{ - init(ccHandle, CSSM_ALGCLASS_RANDOMGEN, context)->final(randomNumber, *this); -} - -void CSPFullPluginSession::GenerateAlgorithmParams(CSSM_CC_HANDLE ccHandle, - const Context &context, - uint32 paramBits, - CssmData ¶m, - uint32 &attrCount, - CSSM_CONTEXT_ATTRIBUTE_PTR &attrs) -{ - Context::Attr *attrList; - init(ccHandle, CSSM_ALGCLASS_NONE, context)->generate(context, paramBits, - param, attrCount, attrList); - attrs = attrList; -} - - -// -// Login/Logout and token operational maintainance. -// These mean little without support by the actual implementation, but we can help... -// @@@ Should this be in CSP[non-Full]PluginSession? -// -void CSPFullPluginSession::Login(const AccessCredentials &AccessCred, - const CssmData *LoginName, - const void *Reserved) -{ - if (Reserved != NULL) - CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER); - - // default implementation refuses to log in - //@@@ should hand it to implementation virtual defaulting to this - CssmError::throwMe(CSSMERR_CSP_INVALID_LOGIN_NAME); -} - -void CSPFullPluginSession::Logout() -{ - if (!loggedIn(false)) - CssmError::throwMe(CSSMERR_CSP_NOT_LOGGED_IN); -} - -void CSPFullPluginSession::VerifyDevice(const CssmData &DeviceCert) -{ - CssmError::throwMe(CSSMERR_CSP_DEVICE_VERIFY_FAILED); -} - -void CSPFullPluginSession::GetOperationalStatistics(CSPOperationalStatistics &statistics) -{ - memset(&statistics, 0, sizeof(statistics)); - statistics.UserAuthenticated = loggedIn(); - //@@@ collect device flags - capability matrix setup? - //@@@ collect token limitation parameters (static) - capability matrix setup? - //@@@ collect token statistics (dynamic) - dynamic accounting call-downs? -} - - -// -// Utterly miscellaneous, rarely used, strange functions -// -void CSPFullPluginSession::RetrieveCounter(CssmData &Counter) -{ - unimplemented(); -} - -void CSPFullPluginSession::RetrieveUniqueId(CssmData &UniqueID) -{ - unimplemented(); -} - -void CSPFullPluginSession::GetTimeValue(CSSM_ALGORITHMS TimeAlgorithm, CssmData &TimeData) -{ - unimplemented(); -} - - -// -// ACL retrieval and change operations -// -void CSPFullPluginSession::GetKeyOwner(const CssmKey &Key, - CSSM_ACL_OWNER_PROTOTYPE &Owner) -{ - unimplemented(); -} - -void CSPFullPluginSession::ChangeKeyOwner(const AccessCredentials &AccessCred, - const CssmKey &Key, - const CSSM_ACL_OWNER_PROTOTYPE &NewOwner) -{ - unimplemented(); -} - -void CSPFullPluginSession::GetKeyAcl(const CssmKey &Key, - const CSSM_STRING *SelectionTag, - uint32 &NumberOfAclInfos, - CSSM_ACL_ENTRY_INFO_PTR &AclInfos) -{ - unimplemented(); -} - -void CSPFullPluginSession::ChangeKeyAcl(const AccessCredentials &AccessCred, - const CSSM_ACL_EDIT &AclEdit, - const CssmKey &Key) -{ - unimplemented(); -} - -void CSPFullPluginSession::GetLoginOwner(CSSM_ACL_OWNER_PROTOTYPE &Owner) -{ - unimplemented(); -} - -void CSPFullPluginSession::ChangeLoginOwner(const AccessCredentials &AccessCred, - const CSSM_ACL_OWNER_PROTOTYPE &NewOwner) -{ - unimplemented(); -} - -void CSPFullPluginSession::GetLoginAcl(const CSSM_STRING *SelectionTag, - uint32 &NumberOfAclInfos, - CSSM_ACL_ENTRY_INFO_PTR &AclInfos) -{ - unimplemented(); -} - -void CSPFullPluginSession::ChangeLoginAcl(const AccessCredentials &AccessCred, - const CSSM_ACL_EDIT &AclEdit) -{ - unimplemented(); -} - - - -// -// Passthroughs (by default, unimplemented) -// -void CSPFullPluginSession::PassThrough(CSSM_CC_HANDLE CCHandle, - const Context &Context, - uint32 PassThroughId, - const void *InData, - void **OutData) -{ - unimplemented(); -} - - -// -// KeyPool -- ReferencedKey management functionality -// -KeyPool::KeyPool() -{ -} - -KeyPool::~KeyPool() -{ - StLock _(mKeyMapLock); - // Delete every ReferencedKey in the pool, but be careful to deactivate them first - // to keep them from calling erase (which would cause deadlock since we already hold mKeyMapLock). - KeyMap::iterator end = mKeyMap.end(); - for (KeyMap::iterator it = mKeyMap.begin(); it != end; ++it) - { - try - { - it->second->deactivate(); - } - catch(...) {} - delete it->second; - } - mKeyMap.clear(); -} - -void -KeyPool::add(ReferencedKey &referencedKey) -{ - StLock _(mKeyMapLock); - bool inserted; - inserted = mKeyMap.insert(KeyMap::value_type(referencedKey.keyReference(), &referencedKey)).second; - // Since add is only called from the constructor of ReferencedKey we should - // never add a key that is already in mKeyMap - assert(inserted); -} - -ReferencedKey & -KeyPool::findKey(const CSSM_KEY &key) const -{ - return findKeyReference(ReferencedKey::keyReference(key)); -} - -ReferencedKey & -KeyPool::findKeyReference(ReferencedKey::KeyReference keyReference) const -{ - StLock _(mKeyMapLock); - KeyMap::const_iterator it = mKeyMap.find(keyReference); - if (it == mKeyMap.end()) - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); - - return *it->second; -} - -void -KeyPool::erase(ReferencedKey &referencedKey) -{ - erase(referencedKey.keyReference()); -} - -ReferencedKey & -KeyPool::erase(ReferencedKey::KeyReference keyReference) -{ - StLock _(mKeyMapLock); - KeyMap::iterator it = mKeyMap.find(keyReference); - if (it == mKeyMap.end()) - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); - - ReferencedKey &referencedKey = *it->second; - mKeyMap.erase(it); - return referencedKey; -} - -// Erase keyReference from mKeyMap, free the ioKey, and delete the ReferencedKey -void -KeyPool::freeKey(Allocator &allocator, CSSM_KEY &ioKey) -{ - delete &erase(ReferencedKey::freeReferenceKey(allocator, ioKey)); -} - -// -// ReferencedKey class -// -ReferencedKey::ReferencedKey(KeyPool &keyPool) : mKeyPool(&keyPool) -{ - mKeyPool->add(*this); -} - -ReferencedKey::~ReferencedKey() -{ - if (isActive()) - mKeyPool->erase(*this); -} - -ReferencedKey::KeyReference -ReferencedKey::keyReference() -{ - // @@@ Possibly check isActive() and return an invalid reference if it is not set. - return reinterpret_cast(this); -} - -// -// Making, retrieving and freeing Key references of CssmKeys -// -void -ReferencedKey::makeReferenceKey(Allocator &allocator, KeyReference keyReference, CSSM_KEY &key) -{ - key.KeyHeader.BlobType = CSSM_KEYBLOB_REFERENCE; - key.KeyHeader.Format = CSSM_KEYBLOB_REF_FORMAT_INTEGER; - key.KeyData.Length = sizeof(KeyReference); - key.KeyData.Data = allocator.alloc(sizeof(KeyReference)); - uint8 *cp = key.KeyData.Data; - for (int i = sizeof(KeyReference); --i >= 0;) - { - cp[i] = keyReference & 0xff; - keyReference = keyReference >> 8; - } -} - -ReferencedKey::KeyReference -ReferencedKey::keyReference(const CSSM_KEY &key) -{ - if (key.KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE - || key.KeyHeader.Format != CSSM_KEYBLOB_REF_FORMAT_INTEGER - || key.KeyData.Length != sizeof(KeyReference) - || key.KeyData.Data == NULL) - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); - - const uint8 *cp = key.KeyData.Data; - KeyReference keyReference = 0; - for (uint32 i = 0; i < sizeof(KeyReference); ++i) - keyReference = (keyReference << 8) + cp[i]; - - return keyReference; -} - -ReferencedKey::KeyReference -ReferencedKey::freeReferenceKey(Allocator &allocator, CSSM_KEY &key) -{ - KeyReference aKeyReference = keyReference(key); - allocator.free(key.KeyData.Data); - key.KeyData.Data = NULL; - key.KeyData.Length = 0; - return aKeyReference; -}