1/*
2 * Copyright (c) 2000-2002 Apple Computer, 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#ifndef _H_CDSA_CLIENT_CSPCLIENT
23#define _H_CDSA_CLIENT_CSPCLIENT  1
24
25#include <security_cdsa_client/cssmclient.h>
26#include <security_cdsa_utilities/context.h>
27#include <security_cdsa_utilities/cssmacl.h>
28
29namespace Security {
30namespace CssmClient {
31
32
33//
34// A CSP attachment
35//
36class CSPImpl : public AttachmentImpl
37{
38public:
39	CSPImpl(const Guid &guid);
40	CSPImpl(const Module &module);
41	virtual ~CSPImpl();
42
43    // the least inappropriate place for this one
44    void freeKey(CssmKey &key, const AccessCredentials *cred = NULL, bool permanent = false);
45};
46
47class CSP : public Attachment
48{
49public:
50	typedef CSPImpl Impl;
51
52	explicit CSP(Impl *impl) : Attachment(impl) {}
53	CSP(const Guid &guid) : Attachment(new Impl(guid)) {}
54	CSP(const Module &module) : Attachment(new Impl(module)) {}
55
56	Impl *operator ->() const { return &impl<Impl>(); }
57	Impl &operator *() const { return impl<Impl>(); }
58};
59
60//
61// A cryptographic context.
62// Contexts always belong to CSPs (CSP attachments).
63//
64class Context : public ObjectImpl
65{
66public:
67	Context(const CSP &csp, CSSM_ALGORITHMS alg = CSSM_ALGID_NONE);
68	~Context();
69
70	CSP attachment() const { return parent<CSP>(); }
71	Module module() const { return attachment()->module(); }
72
73	CSSM_ALGORITHMS algorithm() const { return mAlgorithm; }
74	void algorithm(CSSM_ALGORITHMS alg);
75
76	const AccessCredentials *cred() const	{ return mCred; }
77	void cred(const CSSM_ACCESS_CREDENTIALS *cred);
78	void cred(const CSSM_ACCESS_CREDENTIALS &cred) { this->cred(&cred); }
79
80public:
81	CSSM_CC_HANDLE handle() { activate(); return mHandle; }
82
83    uint32 getOutputSize(uint32 inputSize, bool encrypt = true);
84    void getOutputSize(CSSM_QUERY_SIZE_DATA &sizes, uint32 count, bool encrypt = true);
85
86public:
87	// don't use this section unless you know what you're doing!
88	void override(const ::Context &ctx);
89
90	template <class T>
91	void set(CSSM_ATTRIBUTE_TYPE type, const T &value)
92	{
93		if (isActive()) {
94			::Context::Attr attr(type, value);
95			check(CSSM_UpdateContextAttributes(mHandle, 1, &attr));
96		}
97	}
98
99	void set(CSSM_ATTRIBUTE_TYPE type, uint32 value)
100	{
101		if (isActive()) {
102			::Context::Attr attr(type, value);
103			check(CSSM_UpdateContextAttributes(mHandle, 1, &attr));
104		}
105	}
106
107    template <class T>
108    void add(CSSM_ATTRIBUTE_TYPE type, const T &value)
109    { activate(); set(type, value); }
110
111    void add(CSSM_ATTRIBUTE_TYPE type, uint32 value)
112    { activate(); set(type, value); }
113
114protected:
115	void deactivate();
116
117	virtual void init(); // Subclasses must implement if they support staged operations.
118
119	void unstaged()
120	{ activate(); if (mStaged) CssmError::throwMe(CSSMERR_CSP_STAGED_OPERATION_IN_PROGRESS); }
121
122	void staged()
123	{ if (!mStaged) init(); }
124
125	const AccessCredentials *neededCred()
126	{ return AccessCredentials::needed(mCred); }
127
128protected:
129	CSSM_ALGORITHMS mAlgorithm;		// intended algorithm
130	CSSM_CC_HANDLE mHandle;			// CSSM CC handle
131	bool mStaged;					// staged in progress
132	const AccessCredentials *mCred;	// if explicitly set
133    RecursiveMutex mActivateMutex;
134};
135
136
137//
138// An RccBearer holds a ResourceControlContext. Note that this is a composite
139// of an AccessCredentials and an AclEntryInput. We allow setting the whole
140// thing, or its two components separately. A complete rcc set (via ::rcc)
141// overrides any components.
142// @@@ Perhaps we should merge components into a specified rcc? Iffy, though...
143// Note: We call the credential components "opCred" to distinguish it from
144// the "cred" of a CredBearer; some classes are both. As a rule, the "cred" goes
145// into the context, while the "opCred" gets passed as an argument.
146//
147class RccBearer {
148public:
149	RccBearer() : mOpCred(NULL), mOwner(NULL), mRcc(NULL) { }
150
151	const AccessCredentials *opCred() const		{ return mOpCred; }
152	void opCred(const CSSM_ACCESS_CREDENTIALS *cred) { mOpCred = AccessCredentials::overlay(cred); }
153	void opCred(const CSSM_ACCESS_CREDENTIALS &cred) { this->opCred(&cred); }
154	const AclEntryInput *owner() const			{ return mOwner; }
155	void owner(const CSSM_ACL_ENTRY_INPUT *owner) { mOwner = AclEntryInput::overlay(owner); }
156	void owner(const CSSM_ACL_ENTRY_INPUT &owner) { this->owner(&owner); }
157	void owner(const CSSM_ACL_ENTRY_PROTOTYPE *owner);
158	void owner(const CSSM_ACL_ENTRY_PROTOTYPE &owner) { this->owner(&owner); }
159	const ResourceControlContext *rcc() const	{ return mRcc; }
160	void rcc(const CSSM_RESOURCE_CONTROL_CONTEXT *rcc)
161			{ mRcc = ResourceControlContext::overlay(rcc); }
162	void rcc(const CSSM_RESOURCE_CONTROL_CONTEXT &rcc) { this->rcc(&rcc); }
163
164protected:
165	const ResourceControlContext &compositeRcc() const;
166
167private:
168	// an RCC contains both a cred and entryInput
169	// mCred/mAcl are only considered if mRcc is not set (NULL)
170	const AccessCredentials *mOpCred;
171	const AclEntryInput *mOwner;
172	const ResourceControlContext *mRcc;
173
174	mutable ResourceControlContext mWorkRcc; // work area
175	mutable AclEntryInput mWorkInput;		// work area
176};
177
178
179//
180// A PassThough context
181//
182class PassThrough : public Context
183{
184public:
185	PassThrough(const CSP &csp) : Context(csp) { }
186
187public:
188	void operator () (uint32 passThroughId, const void *inData, void **outData);
189
190	template <class TIn, class TOut>
191	void operator () (uint32 passThroughId, const TIn *inData, TOut **outData)
192	{ operator () (passThroughId, (const void *)inData, (void **)outData); }
193
194	template <class TIn>
195	void operator () (uint32 passThroughId, const TIn *inData)
196	{ operator () (passThroughId, (const void *)inData, NULL); }
197
198	const CSSM_KEY *key() const { return mKey; }
199	void key(const CSSM_KEY *k) { mKey = k; set(CSSM_ATTRIBUTE_KEY, k); }
200
201protected:
202	void activate();
203
204protected:
205	const CSSM_KEY *mKey;
206};
207
208
209//
210// A Digest context
211//
212class Digest : public Context
213{
214public:
215	Digest(const CSP &csp, CSSM_ALGORITHMS alg) : Context(csp, alg) { }
216
217public:
218	// integrated
219	void digest(const CssmData &data, CssmData &digest) { this->digest(&data, 1, digest); }
220	void digest(const CssmData *data, uint32 count, CssmData &digest);
221
222	// staged
223	void digest(const CssmData &data) { digest(&data, 1); }
224	void digest(const CssmData *data, uint32 count);
225	void operator () (CssmData &digest);
226	CssmData operator () () { CssmData digest; (*this)(digest); return digest; }
227
228protected:
229	void activate();
230};
231
232
233//
234// A [P]RNG context
235//
236class Random : public Context
237{
238public:
239	Random(const CSP &csp, CSSM_ALGORITHMS alg) : Context(csp, alg), mSeed(NULL), mSize(1) { }
240	Random(const CSP &csp, CSSM_ALGORITHMS alg, const CssmCryptoData &seed)
241		: Context(csp, alg), mSeed(&seed), mSize(1) { }
242	Random(const CSP &csp, CSSM_ALGORITHMS alg, uint32 size)
243		: Context(csp, alg), mSeed(NULL), mSize(size) { }
244	Random(const CSP &csp, CSSM_ALGORITHMS alg, const CssmCryptoData &seed, uint32 size)
245		: Context(csp, alg), mSeed(&seed), mSize(size) { }
246
247	void seed(const CssmCryptoData &data);
248	void size(uint32 size);
249
250public:
251	void generate(CssmData &data, uint32 size = 0);
252
253	// alternate function-call form
254	CssmData operator () (uint32 size = 0)
255	{ CssmData output; generate(output, size); return output; }
256
257protected:
258	void activate();
259
260private:
261	const CssmCryptoData *mSeed;
262	uint32 mSize;
263};
264
265
266} // end namespace CssmClient
267} // end namespace Security
268
269#endif // _H_CDSA_CLIENT_CSPCLIENT
270