]>
Commit | Line | Data |
---|---|---|
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 | ||
36 | namespace 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 | // | |
48 | class Context : public PodWrapper<Context, CSSM_CONTEXT> { | |
49 | public: | |
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 | ||
63 | public: | |
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 | |
177 | public: | |
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 | ||
187 | public: | |
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 | ||
195 | public: | |
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 | ||
200 | public: | |
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 | ||
207 | protected: | |
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 | ||
214 | namespace DataWalkers | |
215 | { | |
216 | ||
217 | template <class Action> | |
218 | void 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 |
249 | template <class Action> |
250 | void 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 | // | |
278 | using namespace DataWalkers; | |
279 | ||
280 | class Context::Builder { | |
281 | protected: | |
282 | public: | |
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 | ||
294 | public: | |
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 | ||
345 | private: | |
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 |