cspclient.cpp
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 24 namespace Security { 25 namespace CssmClient { 26 27 28 // 29 // Manage CSP attachments 30 // 31 CSPImpl::CSPImpl(const Guid &guid) : AttachmentImpl(guid, CSSM_SERVICE_CSP) 32 { 33 } 34 35 CSPImpl::CSPImpl(const Module &module) : AttachmentImpl(module, CSSM_SERVICE_CSP) 36 { 37 } 38 39 CSPImpl::~CSPImpl() 40 { 41 } 42 43 44 // 45 // Delete a key explicitly 46 // 47 void 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 // 56 Context::Context(const CSP &csp, CSSM_ALGORITHMS alg) : ObjectImpl(csp), mAlgorithm(alg), mHandle(NULL), mStaged(false), mCred(NULL) 57 { 58 } 59 60 Context::~Context() 61 { 62 try 63 { 64 deactivate(); 65 } catch(...) {} 66 } 67 68 void Context::init() 69 { 70 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); 71 } 72 73 void Context::deactivate() 74 { 75 StLock<Mutex> _(mActivateMutex); 76 if (mActive) 77 { 78 mActive = false; 79 check(CSSM_DeleteContext(mHandle)); 80 } 81 } 82 83 84 void Context::algorithm(CSSM_ALGORITHMS alg) 85 { 86 if (isActive()) 87 abort(); //@@@ can't (currently?) change algorithm with active context 88 mAlgorithm = alg; 89 } 90 91 92 void Context::cred(const CSSM_ACCESS_CREDENTIALS *cred) 93 { 94 mCred = AccessCredentials::overlay(cred); 95 set(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, *mCred); 96 } 97 98 99 // 100 // Query context operation output sizes. 101 // 102 uint32 Context::getOutputSize(uint32 inputSize, bool encrypt /*= true*/) 103 { 104 CSSM_QUERY_SIZE_DATA data; 105 data.SizeInputBlock = inputSize; 106 getOutputSize(data, 1, encrypt); 107 return data.SizeOutputBlock; 108 } 109 110 void Context::getOutputSize(CSSM_QUERY_SIZE_DATA &sizes, uint32 count, bool encrypt /*= true*/) 111 { 112 check(CSSM_QuerySize(handle(), encrypt, count, &sizes)); 113 } 114 115 116 // 117 // The override() method of Context is an expert feature. It replaces the entire 118 // context with a context object provided. It is up to the caller to keep this context 119 // consistent with the purpose of the Context subclass he is (mis)using. 120 // This feature is currently used by the SecurityServer. 121 // 122 void Context::override(const Security::Context &ctx) 123 { 124 if (!isActive()) { 125 // make a valid context object (it doesn't matter what kind - keep it cheap) 126 check(CSSM_CSP_CreateDigestContext(attachment()->handle(), CSSM_ALGID_NONE, &mHandle)); 127 } 128 // now replace everything with the context data provided 129 check(CSSM_SetContext(mHandle, &ctx)); 130 mActive = true; // now active 131 } 132 133 134 // 135 // RccContexts 136 // 137 const ResourceControlContext &RccBearer::compositeRcc() const 138 { 139 // explicitly specified RCC wins 140 if (mRcc) 141 return *mRcc; 142 143 // cobble one up from the pieces 144 if (mOwner) 145 mWorkRcc.input() = *mOwner; 146 else 147 mWorkRcc.clearPod(); 148 mWorkRcc.credentials(mOpCred); 149 return mWorkRcc; 150 } 151 152 153 void RccBearer::owner(const CSSM_ACL_ENTRY_PROTOTYPE *owner) 154 { 155 if (owner) { 156 mWorkInput = *owner; 157 this->owner(mWorkInput); 158 } else 159 this->owner((AclEntryInput*)NULL); 160 } 161 162 163 // 164 // Manage PassThrough contexts 165 // 166 167 // 168 // Invoke passThrough 169 // 170 void 171 PassThrough::operator() (uint32 passThroughId, const void *inData, void **outData) 172 { 173 check(CSSM_CSP_PassThrough(handle(), passThroughId, inData, outData)); 174 } 175 176 void PassThrough::activate() 177 { 178 StLock<Mutex> _(mActivateMutex); 179 if (!mActive) { 180 check(CSSM_CSP_CreatePassThroughContext(attachment()->handle(), mKey, &mHandle)); 181 mActive = true; 182 } 183 } 184 185 186 // 187 // Manage Digest contexts 188 // 189 void Digest::activate() 190 { 191 StLock<Mutex> _(mActivateMutex); 192 if (!mActive) { 193 check(CSSM_CSP_CreateDigestContext(attachment()->handle(), mAlgorithm, &mHandle)); 194 mActive = true; 195 } 196 } 197 198 199 void Digest::digest(const CssmData *data, uint32 count, CssmData &digest) 200 { 201 activate(); 202 if (mStaged) 203 Error::throwMe(CSSMERR_CSP_STAGED_OPERATION_IN_PROGRESS); 204 check(CSSM_DigestData(handle(), data, count, &digest)); 205 } 206 207 void Digest::digest(const CssmData *data, uint32 count) 208 { 209 activate(); 210 if (!mStaged) { 211 check(CSSM_DigestDataInit(handle())); 212 mStaged = true; 213 } 214 check(CSSM_DigestDataUpdate(handle(), data, count)); 215 } 216 217 void Digest::operator () (CssmData &digest) 218 { 219 if (!mStaged) 220 Error::throwMe(CSSMERR_CSP_STAGED_OPERATION_NOT_STARTED); 221 check(CSSM_DigestDataFinal(handle(), &digest)); 222 mStaged = false; 223 } 224 225 226 // 227 // Random number generation 228 // 229 void Random::seed(const CssmCryptoData &seedData) 230 { 231 mSeed = &seedData; 232 set(CSSM_ATTRIBUTE_SEED, seedData); 233 } 234 235 void Random::size(uint32 sz) 236 { 237 mSize = sz; 238 set(CSSM_ATTRIBUTE_OUTPUT_SIZE, sz); 239 } 240 241 242 void Random::activate() 243 { 244 StLock<Mutex> _(mActivateMutex); 245 if (!mActive) { 246 check(CSSM_CSP_CreateRandomGenContext(attachment()->handle(), mAlgorithm, 247 mSeed, mSize, &mHandle)); 248 mActive = true; 249 } 250 } 251 252 253 void Random::generate(CssmData &data, uint32 newSize) 254 { 255 if (newSize) 256 size(newSize); 257 activate(); 258 assert(!mStaged); // not a stage-able operation 259 check(CSSM_GenerateRandom(handle(), &data)); 260 } 261 262 } // end namespace CssmClient 263 } // end namespace Security