/ OSX / libsecurity_cdsa_client / lib / cspclient.cpp
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