1/* 2 * Copyright (c) 2000-2002,2011-2012,2014 Apple Inc. All Rights Reserved. 3 * 4 * The contents of this file constitute Original Code as defined in and are 5 * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 * You may not use this file except in compliance with the License. Please obtain 7 * a copy of the License at http://www.apple.com/publicsource and read it before 8 * using this file. 9 * 10 * This Original Code and all software distributed under the License are 11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 * specific language governing rights and limitations under the License. 16 */ 17 18 19// 20// cspclient - client interface to CSSM CSPs and their operations 21// 22#include <security_cdsa_client/cspclient.h> 23 24namespace Security { 25namespace CssmClient { 26 27 28// 29// Manage CSP attachments 30// 31CSPImpl::CSPImpl(const Guid &guid) : AttachmentImpl(guid, CSSM_SERVICE_CSP) 32{ 33} 34 35CSPImpl::CSPImpl(const Module &module) : AttachmentImpl(module, CSSM_SERVICE_CSP) 36{ 37} 38 39CSPImpl::~CSPImpl() 40{ 41} 42 43 44// 45// Delete a key explicitly 46// 47void CSPImpl::freeKey(CssmKey &key, const AccessCredentials *cred, bool permanent) 48{ 49 check(CSSM_FreeKey(handle(), cred, &key, permanent)); 50} 51 52 53// 54// Manage generic context objects 55// 56Context::Context(const CSP &csp, CSSM_ALGORITHMS alg) 57: ObjectImpl(csp), mAlgorithm(alg), mStaged(false), mCred(NULL) 58{ 59} 60 61Context::~Context() 62{ 63 try 64 { 65 deactivate(); 66 } catch(...) {} 67} 68 69void Context::init() 70{ 71 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); 72} 73 74void Context::deactivate() 75{ 76 StLock<Mutex> _(mActivateMutex); 77 if (mActive) 78 { 79 mActive = false; 80 check(CSSM_DeleteContext(mHandle)); 81 } 82} 83 84 85void Context::algorithm(CSSM_ALGORITHMS alg) 86{ 87 if (isActive()) 88 abort(); //@@@ can't (currently?) change algorithm with active context 89 mAlgorithm = alg; 90} 91 92 93void Context::cred(const CSSM_ACCESS_CREDENTIALS *cred) 94{ 95 mCred = AccessCredentials::overlay(cred); 96 set(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, *mCred); 97} 98 99 100// 101// Query context operation output sizes. 102// 103uint32 Context::getOutputSize(uint32 inputSize, bool encrypt /*= true*/) 104{ 105 CSSM_QUERY_SIZE_DATA data; 106 data.SizeInputBlock = inputSize; 107 getOutputSize(data, 1, encrypt); 108 return data.SizeOutputBlock; 109} 110 111void Context::getOutputSize(CSSM_QUERY_SIZE_DATA &sizes, uint32 count, bool encrypt /*= true*/) 112{ 113 check(CSSM_QuerySize(handle(), encrypt, count, &sizes)); 114} 115 116 117// 118// The override() method of Context is an expert feature. It replaces the entire 119// context with a context object provided. It is up to the caller to keep this context 120// consistent with the purpose of the Context subclass he is (mis)using. 121// This feature is currently used by the SecurityServer. 122// 123void Context::override(const Security::Context &ctx) 124{ 125 if (!isActive()) { 126 // make a valid context object (it doesn't matter what kind - keep it cheap) 127 check(CSSM_CSP_CreateDigestContext(attachment()->handle(), CSSM_ALGID_NONE, &mHandle)); 128 } 129 // now replace everything with the context data provided 130 check(CSSM_SetContext(mHandle, &ctx)); 131 mActive = true; // now active 132} 133 134 135// 136// RccContexts 137// 138const ResourceControlContext &RccBearer::compositeRcc() const 139{ 140 // explicitly specified RCC wins 141 if (mRcc) 142 return *mRcc; 143 144 // cobble one up from the pieces 145 if (mOwner) 146 mWorkRcc.input() = *mOwner; 147 else 148 mWorkRcc.clearPod(); 149 mWorkRcc.credentials(mOpCred); 150 return mWorkRcc; 151} 152 153 154void RccBearer::owner(const CSSM_ACL_ENTRY_PROTOTYPE *owner) 155{ 156 if (owner) { 157 mWorkInput = *owner; 158 this->owner(mWorkInput); 159 } else 160 this->owner((AclEntryInput*)NULL); 161} 162 163 164// 165// Manage PassThrough contexts 166// 167 168// 169// Invoke passThrough 170// 171void 172PassThrough::operator() (uint32 passThroughId, const void *inData, void **outData) 173{ 174 check(CSSM_CSP_PassThrough(handle(), passThroughId, inData, outData)); 175} 176 177void PassThrough::activate() 178{ 179 StLock<Mutex> _(mActivateMutex); 180 if (!mActive) { 181 check(CSSM_CSP_CreatePassThroughContext(attachment()->handle(), mKey, &mHandle)); 182 mActive = true; 183 } 184} 185 186 187// 188// Manage Digest contexts 189// 190void Digest::activate() 191{ 192 StLock<Mutex> _(mActivateMutex); 193 if (!mActive) { 194 check(CSSM_CSP_CreateDigestContext(attachment()->handle(), mAlgorithm, &mHandle)); 195 mActive = true; 196 } 197} 198 199 200void Digest::digest(const CssmData *data, uint32 count, CssmData &digest) 201{ 202 activate(); 203 if (mStaged) 204 Error::throwMe(CSSMERR_CSP_STAGED_OPERATION_IN_PROGRESS); 205 check(CSSM_DigestData(handle(), data, count, &digest)); 206} 207 208void Digest::digest(const CssmData *data, uint32 count) 209{ 210 activate(); 211 if (!mStaged) { 212 check(CSSM_DigestDataInit(handle())); 213 mStaged = true; 214 } 215 check(CSSM_DigestDataUpdate(handle(), data, count)); 216} 217 218void Digest::operator () (CssmData &digest) 219{ 220 if (!mStaged) 221 Error::throwMe(CSSMERR_CSP_STAGED_OPERATION_NOT_STARTED); 222 check(CSSM_DigestDataFinal(handle(), &digest)); 223 mStaged = false; 224} 225 226 227// 228// Random number generation 229// 230void Random::seed(const CssmCryptoData &seedData) 231{ 232 mSeed = &seedData; 233 set(CSSM_ATTRIBUTE_SEED, seedData); 234} 235 236void Random::size(uint32 sz) 237{ 238 mSize = sz; 239 set(CSSM_ATTRIBUTE_OUTPUT_SIZE, sz); 240} 241 242 243void Random::activate() 244{ 245 StLock<Mutex> _(mActivateMutex); 246 if (!mActive) { 247 check(CSSM_CSP_CreateRandomGenContext(attachment()->handle(), mAlgorithm, 248 mSeed, mSize, &mHandle)); 249 mActive = true; 250 } 251} 252 253 254void Random::generate(CssmData &data, uint32 newSize) 255{ 256 if (newSize) 257 size(newSize); 258 activate(); 259 assert(!mStaged); // not a stage-able operation 260 check(CSSM_GenerateRandom(handle(), &data)); 261} 262 263} // end namespace CssmClient 264} // end namespace Security 265