]> git.saurik.com Git - apple/security.git/blame - cdsa/cdsa_utilities/context.h
Security-163.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / context.h
CommitLineData
bac41a7b
A
1/*
2 * Copyright (c) 2000-2001 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// context - CSSM cryptographic context objects
21//
22#ifndef _H_CONTEXT
23#define _H_CONTEXT
24
25#include <Security/utilities.h>
26#include <Security/debugging.h>
27#include <Security/cssmalloc.h>
28#include <Security/cssmwalkers.h>
29#include <Security/cssmacl.h> // to serialize/copy access credentials
df0e469f 30#include <Security/cssmdates.h>
bac41a7b
A
31
32#ifdef _CPP_CONTEXT
33# pragma export on
34#endif
35
36namespace Security
37{
38
39//
40// Context is a POD overlay for the CSSM_CONTEXT type. It does
41// add allocation functions and lots of good stuff.
42// Note that if you're outside CSSM proper, you are not supposed to
43// memory-manage Context structures on your own. Be a good boy and
44// call the CSSM API functions.
45// We also provide a POD overlay for CSSM_CONTEXT_ATTRIBUTE, with
46// the obvious semantics.
47//
48class Context : public PodWrapper<Context, CSSM_CONTEXT> {
49public:
df0e469f 50 Context(CSSM_CONTEXT_TYPE type, CSSM_ALGORITHMS algorithmId);
bac41a7b
A
51
52 uint32 attributesInUse() const { return NumberOfAttributes; }
53 CSSM_CONTEXT_TYPE type() const { return ContextType; }
54 CSSM_ALGORITHMS algorithm() const { return AlgorithmType; }
55 CSSM_CSP_HANDLE cspHandle() const { return CSPHandle; }
56
57 void deleteAttribute(CSSM_ATTRIBUTE_TYPE type);
58 size_t copyAttributes(CSSM_CONTEXT_ATTRIBUTE * &attrs, uint32 &count, CssmAllocator &alloc) const;
59
60 void copyFrom(const Context &source, CssmAllocator &alloc)
61 { source.copyAttributes(ContextAttributes, NumberOfAttributes, alloc); }
62
63public:
64 class Attr : public PodWrapper<Attr, CSSM_CONTEXT_ATTRIBUTE> {
65 public:
66 Attr() { }
67 Attr(const CSSM_CONTEXT_ATTRIBUTE &attr) { (CSSM_CONTEXT_ATTRIBUTE &)*this = attr; }
68
69 template <class T>
70 Attr(CSSM_ATTRIBUTE_TYPE typ, T &value, size_t size = 0)
71 {
72 AttributeType = typ;
73 // attribute component pointers are stupidly non-const; allow const input
74 Attribute.String = const_cast<char *>(reinterpret_cast<const char *>(&value));
75 AttributeLength = size ? size : sizeof(T);
76 }
77
78 Attr(CSSM_ATTRIBUTE_TYPE typ, uint32 value)
79 {
80 AttributeType = typ;
81 Attribute.Uint32 = value;
82 AttributeLength = 0;
83 }
84
85 CSSM_ATTRIBUTE_TYPE type() const { return AttributeType; }
86 uint32 baseType() const { return AttributeType & CSSM_ATTRIBUTE_TYPE_MASK; }
87
88 operator char * () const
89 { assert(baseType() == CSSM_ATTRIBUTE_DATA_STRING); return Attribute.String; }
90 operator CssmData & () const
91 { assert(baseType() == CSSM_ATTRIBUTE_DATA_CSSM_DATA);
92 return CssmData::overlay(*Attribute.Data); }
93 operator CssmCryptoData & () const
94 { assert(baseType() == CSSM_ATTRIBUTE_DATA_CRYPTO_DATA);
95 return CssmCryptoData::overlay(*Attribute.CryptoData); }
96 operator CssmKey & () const
97 { assert(baseType() == CSSM_ATTRIBUTE_DATA_KEY); return CssmKey::overlay(*Attribute.Key); }
98 operator AccessCredentials & () const
99 { assert(baseType() == CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS);
100 return AccessCredentials::overlay(*Attribute.AccessCredentials); }
101 operator uint32 () const
102 { assert(baseType() == CSSM_ATTRIBUTE_DATA_UINT32); return Attribute.Uint32; }
103 operator CSSM_DL_DB_HANDLE &() const
104 {
105 assert(baseType() == CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE);
df0e469f 106 if (Attribute.DLDBHandle == NULL)
bac41a7b 107 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_DL_DB_HANDLE);
df0e469f 108 return *Attribute.DLDBHandle;
bac41a7b 109 }
df0e469f
A
110 operator CssmDate & () const
111 { assert(baseType() == CSSM_ATTRIBUTE_DATA_DATE);
112 return CssmDate::overlay(*Attribute.Date); }
bac41a7b
A
113 // @@@ etc. etc. - add yours today!
114
115 void operator = (uint32 value) { Attribute.Uint32 = value; }
116 template <class T>
117 void operator = (T *ptr) { Attribute.String = reinterpret_cast<char *>(ptr); }
118
119 IFDUMP(void dump() const;) // debug dump this Attr to stdout (one line)
120 };
121
122 // Attributes by position
123 Attr *attributes() const { return Attr::overlay(ContextAttributes); }
124 Attr &operator [] (unsigned int ix)
125 { assert(ix < NumberOfAttributes); return static_cast<Attr &>(ContextAttributes[ix]); }
126 const Attr &operator [] (unsigned int ix) const
127 { assert(ix < NumberOfAttributes); return static_cast<Attr &>(ContextAttributes[ix]); }
128
129 // general attribute retrieval by type
130 Attr *find(CSSM_ATTRIBUTE_TYPE theType) const
131 { return find(theType, ContextAttributes, NumberOfAttributes); }
132
133 template <class Elem>
134 Elem &get(CSSM_ATTRIBUTE_TYPE type, CSSM_RETURN err) const
135 {
136 if (Attr *attr = find(type))
137 return static_cast<Elem &>(*attr);
138 else
139 CssmError::throwMe(err);
140 }
141
142 template <class Elem>
143 Elem *get(CSSM_ATTRIBUTE_TYPE type) const
144 {
145 if (Attr *attr = find(type))
146 // @@@ Invoking conversion operator to Elem & on *attr and taking address of result.
147 return &static_cast<Elem &>(*attr);
148 else
149 return NULL;
150 }
151
152 uint32 getInt(CSSM_ATTRIBUTE_TYPE type, CSSM_RETURN err) const
153 {
154 if (Attr *attr = find(type))
155 return static_cast<uint32>(*attr);
156 else
157 CssmError::throwMe(err);
158 }
159
160 uint32 getInt(CSSM_ATTRIBUTE_TYPE type) const
161 {
162 if (Attr *attr = find(type))
163 return static_cast<uint32>(*attr);
164 else
165 return 0;
166 }
29654253
A
167
168 bool getInt(CSSM_ATTRIBUTE_TYPE type, uint32 &value) const
169 {
170 if (Attr *attr = find(type)) {
171 value = static_cast<uint32>(*attr);
172 return true;
173 } else
174 return false;
175 }
bac41a7b
A
176
177public:
178 template <class T>
179 void replace(CSSM_ATTRIBUTE_TYPE type, const T &newValue) const
180 {
181 if (Attr *attr = find(type))
182 *attr = Attr(type, newValue);
183 else
184 CssmError::throwMe(CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT);
185 }
186
187public:
29654253 188 void *operator new (size_t size, CssmAllocator &alloc) throw(std::bad_alloc)
bac41a7b 189 { return alloc.malloc(size); }
29654253 190 void operator delete (void *addr, size_t, CssmAllocator &alloc) throw()
bac41a7b 191 { return alloc.free(addr); }
29654253 192 static void destroy(Context *context, CssmAllocator &alloc) throw()
bac41a7b
A
193 { alloc.free(context->ContextAttributes); alloc.free(context); }
194
195public:
196 // Post-IPC context fixup.
197 // This can only be called on a Built Context after IPC transmission.
198 void postIPC(void *base, CSSM_CONTEXT_ATTRIBUTE *ipcAttributes);
199
200public:
201 class Builder;
202
203 // dump to stdout, multiline format
204 IFDUMP(void dump(const char *title = NULL,
205 const CSSM_CONTEXT_ATTRIBUTE *attrs = NULL) const;)
206
207protected:
208 // find an attribute in a plain array of attribute structures (no context)
209 static Attr *find(CSSM_ATTRIBUTE_TYPE theType,
210 const CSSM_CONTEXT_ATTRIBUTE *attrs, unsigned int count);
211};
212
213
214namespace DataWalkers
215{
216
217template <class Action>
218void walk(Action &operate, CSSM_CONTEXT_ATTRIBUTE &attr)
219{
df0e469f 220 operate(attr);
bac41a7b
A
221 switch (attr.AttributeType & CSSM_ATTRIBUTE_TYPE_MASK) {
222 case CSSM_ATTRIBUTE_DATA_CSSM_DATA:
223 walk(operate, attr.Attribute.Data); break;
224 case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA:
225 walk(operate, attr.Attribute.CryptoData); break;
226 case CSSM_ATTRIBUTE_DATA_KEY:
227 walk(operate, attr.Attribute.Key); break;
228 case CSSM_ATTRIBUTE_DATA_STRING:
229 walk(operate, attr.Attribute.String); break;
230 case CSSM_ATTRIBUTE_DATA_DATE:
231 walk(operate, attr.Attribute.Date); break;
232 case CSSM_ATTRIBUTE_DATA_RANGE:
233 walk(operate, attr.Attribute.Range); break;
234 case CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS:
235 walk(operate, attr.Attribute.AccessCredentials); break;
236 case CSSM_ATTRIBUTE_DATA_VERSION:
237 walk(operate, attr.Attribute.Version); break;
238 case CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE:
df0e469f 239 walk(operate, attr.Attribute.DLDBHandle); break;
bac41a7b
A
240 case CSSM_ATTRIBUTE_NONE:
241 case CSSM_ATTRIBUTE_DATA_UINT32:
242 break;
243 default:
df0e469f
A
244 secdebug("walkers", "invalid attribute (%lx) in context", attr.AttributeType);
245 break;
bac41a7b
A
246 }
247}
248
df0e469f
A
249template <class Action>
250void walk(Action &operate, Context::Attr &attr)
251{
252 walk(operate, static_cast<CSSM_CONTEXT_ATTRIBUTE &>(attr));
253}
254
bac41a7b
A
255} // end namespace DataWalkers
256
257
258//
259// Context::Builder - make context attributes the fun way.
260//
261// A Context (aka CSSM_CONTEXT) has a pointer to an array of context attributes,
262// most of which contain pointers to other stuff with pointers to God Knows Where.
263// Instead of allocating this all over the heap, a Context::Builder performs
264// a two-pass algorithm that places all that stuff into a single heap node.
265// Specifically, the builder will allocate and create a vector of CSSM_CONTEXT_ATTRIBUTE
266// structures and all their subordinate heap storage.
267// A Builder does not deal in Context objects and does not care what you do with your
268// CSSM_CONTEXT_ATTRIBUTE array once it's delivered. Since it's a single heap node,
269// you can just free() it using the appropriate allocator when you're done with it.
270//
271// Theory of operation:
272// Builder works in two phases, called scan and build. During scan, you call setup()
273// with the desired data to be placed into the attribute vector. When done, call make()
274// to switch to build phase. Then call put() with the SAME sequence of values as in phase 1.
275// Finally, call done() to receive the pointer-and-count values.
276// @@@ Add comment about IPC use.
277//
278using namespace DataWalkers;
279
280class Context::Builder {
281protected:
282public:
283 Builder(CssmAllocator &alloc) : allocator(alloc)
284 { slotCount = 0; attributes = NULL; }
285 ~Builder() { allocator.free(attributes); }
286
287 CssmAllocator &allocator;
288
289 // switch to build phase
290 size_t make();
291 // deliver result
292 void done(CSSM_CONTEXT_ATTRIBUTE * &attributes, uint32 &count);
293
294public:
295 //
296 // Phase 1 (scan) dispatch. Call once for each attribute needed.
297 //
298 template <class T>
299 void setup(T p, CSSM_RETURN invalidError = CSSM_OK)
300 {
301 if (p) {
302 slotCount++;
303 walk(sizer, p);
304 } else if (invalidError)
305 CssmError::throwMe(invalidError);
306 }
307 // dynamic attribute type
308 void setup(const CSSM_CONTEXT_ATTRIBUTE &attr)
309 { slotCount++; walk(sizer, const_cast<CSSM_CONTEXT_ATTRIBUTE &>(attr)); }
310 void setup(const Context::Attr &attr) { setup(static_cast<const CSSM_CONTEXT_ATTRIBUTE &>(attr)); }
311
312 //
313 // Phase 2 (copy) dispatch. Call once for each attribute, in same order as setup().
314 //
315 template <class T>
316 void put(CSSM_ATTRIBUTE_TYPE type, const T *p)
317 {
318 if (p) {
319 assert(slot < slotCount); // check overflow
320 Attr &attribute = attributes[slot++];
321 attribute.AttributeType = type;
322 attribute.AttributeLength = size(p); //@@@ needed? how/when/what for?
323 attribute = walk(copier, p);
324 }
325 }
326 void put(CSSM_ATTRIBUTE_TYPE type, uint32 value)
327 {
328 if (value) {
329 assert(slot < slotCount); // check overflow
330 Attr &attribute = attributes[slot++];
331 attribute.AttributeType = type;
332 attribute.AttributeLength = 0; //@@@ unclear what that should be
333 attribute = value; // no heap data (immediate value)
334 }
335 }
336 void put(const CSSM_CONTEXT_ATTRIBUTE &attr)
337 {
338 assert(slot < slotCount);
339 Attr &attribute = attributes[slot++];
340 attribute = attr; // shallow copy
341 walk(copier, attribute); // deep copy
342 }
343 void put(const Context::Attr &attr) { put(static_cast<const CSSM_CONTEXT_ATTRIBUTE &>(attr)); }
344
345private:
346 // pass 1 state: collect sizes and counts
347 unsigned slotCount; // count of attribute slots in use
348 SizeWalker sizer; // memory size calculator
349
350 // pass 2 state: build the data set
351 Context::Attr *attributes; // attribute vector and start of block
352 CopyWalker copier; // data copy engine
353 uint32 slot; // writer slot position
354};
355
356} // end namespace Security
357
358#ifdef _CPP_CONTEXT
359# pragma export off
360#endif
361
362#endif //_H_CONTEXT