2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
20 // context - CSSM cryptographic context objects
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
30 #include <Security/cssmdates.h>
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.
48 class Context
: public PodWrapper
<Context
, CSSM_CONTEXT
> {
50 Context(CSSM_CONTEXT_TYPE type
, CSSM_ALGORITHMS algorithmId
);
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
; }
57 void deleteAttribute(CSSM_ATTRIBUTE_TYPE type
);
58 size_t copyAttributes(CSSM_CONTEXT_ATTRIBUTE
* &attrs
, uint32
&count
, CssmAllocator
&alloc
) const;
60 void copyFrom(const Context
&source
, CssmAllocator
&alloc
)
61 { source
.copyAttributes(ContextAttributes
, NumberOfAttributes
, alloc
); }
64 class Attr
: public PodWrapper
<Attr
, CSSM_CONTEXT_ATTRIBUTE
> {
67 Attr(const CSSM_CONTEXT_ATTRIBUTE
&attr
) { (CSSM_CONTEXT_ATTRIBUTE
&)*this = attr
; }
70 Attr(CSSM_ATTRIBUTE_TYPE typ
, T
&value
, size_t size
= 0)
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
);
78 Attr(CSSM_ATTRIBUTE_TYPE typ
, uint32 value
)
81 Attribute
.Uint32
= value
;
85 CSSM_ATTRIBUTE_TYPE
type() const { return AttributeType
; }
86 uint32
baseType() const { return AttributeType
& CSSM_ATTRIBUTE_TYPE_MASK
; }
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
105 assert(baseType() == CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE
);
106 if (Attribute
.DLDBHandle
== NULL
)
107 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_DL_DB_HANDLE
);
108 return *Attribute
.DLDBHandle
;
110 operator CssmDate
& () const
111 { assert(baseType() == CSSM_ATTRIBUTE_DATA_DATE
);
112 return CssmDate::overlay(*Attribute
.Date
); }
113 // @@@ etc. etc. - add yours today!
115 void operator = (uint32 value
) { Attribute
.Uint32
= value
; }
117 void operator = (T
*ptr
) { Attribute
.String
= reinterpret_cast<char *>(ptr
); }
119 IFDUMP(void dump() const;) // debug dump this Attr to stdout (one line)
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
]); }
129 // general attribute retrieval by type
130 Attr
*find(CSSM_ATTRIBUTE_TYPE theType
) const
131 { return find(theType
, ContextAttributes
, NumberOfAttributes
); }
133 template <class Elem
>
134 Elem
&get(CSSM_ATTRIBUTE_TYPE type
, CSSM_RETURN err
) const
136 if (Attr
*attr
= find(type
))
137 return static_cast<Elem
&>(*attr
);
139 CssmError::throwMe(err
);
142 template <class Elem
>
143 Elem
*get(CSSM_ATTRIBUTE_TYPE type
) const
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
);
152 uint32
getInt(CSSM_ATTRIBUTE_TYPE type
, CSSM_RETURN err
) const
154 if (Attr
*attr
= find(type
))
155 return static_cast<uint32
>(*attr
);
157 CssmError::throwMe(err
);
160 uint32
getInt(CSSM_ATTRIBUTE_TYPE type
) const
162 if (Attr
*attr
= find(type
))
163 return static_cast<uint32
>(*attr
);
168 bool getInt(CSSM_ATTRIBUTE_TYPE type
, uint32
&value
) const
170 if (Attr
*attr
= find(type
)) {
171 value
= static_cast<uint32
>(*attr
);
179 void replace(CSSM_ATTRIBUTE_TYPE type
, const T
&newValue
) const
181 if (Attr
*attr
= find(type
))
182 *attr
= Attr(type
, newValue
);
184 CssmError::throwMe(CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT
);
188 void *operator new (size_t size
, CssmAllocator
&alloc
) throw(std::bad_alloc
)
189 { return alloc
.malloc(size
); }
190 void operator delete (void *addr
, size_t, CssmAllocator
&alloc
) throw()
191 { return alloc
.free(addr
); }
192 static void destroy(Context
*context
, CssmAllocator
&alloc
) throw()
193 { alloc
.free(context
->ContextAttributes
); alloc
.free(context
); }
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
);
203 // dump to stdout, multiline format
204 IFDUMP(void dump(const char *title
= NULL
,
205 const CSSM_CONTEXT_ATTRIBUTE
*attrs
= NULL
) const;)
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
);
214 namespace DataWalkers
217 template <class Action
>
218 void walk(Action
&operate
, CSSM_CONTEXT_ATTRIBUTE
&attr
)
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
:
239 walk(operate
, attr
.Attribute
.DLDBHandle
); break;
240 case CSSM_ATTRIBUTE_NONE
:
241 case CSSM_ATTRIBUTE_DATA_UINT32
:
244 secdebug("walkers", "invalid attribute (%lx) in context", attr
.AttributeType
);
249 template <class Action
>
250 void walk(Action
&operate
, Context::Attr
&attr
)
252 walk(operate
, static_cast<CSSM_CONTEXT_ATTRIBUTE
&>(attr
));
255 } // end namespace DataWalkers
259 // Context::Builder - make context attributes the fun way.
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.
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.
278 using namespace DataWalkers
;
280 class Context::Builder
{
283 Builder(CssmAllocator
&alloc
) : allocator(alloc
)
284 { slotCount
= 0; attributes
= NULL
; }
285 ~Builder() { allocator
.free(attributes
); }
287 CssmAllocator
&allocator
;
289 // switch to build phase
292 void done(CSSM_CONTEXT_ATTRIBUTE
* &attributes
, uint32
&count
);
296 // Phase 1 (scan) dispatch. Call once for each attribute needed.
299 void setup(T p
, CSSM_RETURN invalidError
= CSSM_OK
)
304 } else if (invalidError
)
305 CssmError::throwMe(invalidError
);
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
)); }
313 // Phase 2 (copy) dispatch. Call once for each attribute, in same order as setup().
316 void put(CSSM_ATTRIBUTE_TYPE type
, const T
*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
);
326 void put(CSSM_ATTRIBUTE_TYPE type
, uint32 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)
336 void put(const CSSM_CONTEXT_ATTRIBUTE
&attr
)
338 assert(slot
< slotCount
);
339 Attr
&attribute
= attributes
[slot
++];
340 attribute
= attr
; // shallow copy
341 walk(copier
, attribute
); // deep copy
343 void put(const Context::Attr
&attr
) { put(static_cast<const CSSM_CONTEXT_ATTRIBUTE
&>(attr
)); }
346 // pass 1 state: collect sizes and counts
347 unsigned slotCount
; // count of attribute slots in use
348 SizeWalker sizer
; // memory size calculator
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
356 } // end namespace Security