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
39 // Context is a POD overlay for the CSSM_CONTEXT type. It does
40 // add allocation functions and lots of good stuff.
41 // Note that if you're outside CSSM proper, you are not supposed to
42 // memory-manage Context structures on your own. Be a good boy and
43 // call the CSSM API functions.
44 // We also provide a POD overlay for CSSM_CONTEXT_ATTRIBUTE, with
45 // the obvious semantics.
47 class Context
: public PodWrapper
<Context
, CSSM_CONTEXT
> {
49 Context(CSSM_CONTEXT_TYPE type
, CSSM_ALGORITHMS algorithmId
)
50 { ContextType
= type
; AlgorithmType
= 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 // @@@ etc. etc. - add yours today!
112 void operator = (uint32 value
) { Attribute
.Uint32
= value
; }
114 void operator = (T
*ptr
) { Attribute
.String
= reinterpret_cast<char *>(ptr
); }
116 IFDUMP(void dump() const;) // debug dump this Attr to stdout (one line)
119 // Attributes by position
120 Attr
*attributes() const { return Attr::overlay(ContextAttributes
); }
121 Attr
&operator [] (unsigned int ix
)
122 { assert(ix
< NumberOfAttributes
); return static_cast<Attr
&>(ContextAttributes
[ix
]); }
123 const Attr
&operator [] (unsigned int ix
) const
124 { assert(ix
< NumberOfAttributes
); return static_cast<Attr
&>(ContextAttributes
[ix
]); }
126 // general attribute retrieval by type
127 Attr
*find(CSSM_ATTRIBUTE_TYPE theType
) const
128 { return find(theType
, ContextAttributes
, NumberOfAttributes
); }
130 template <class Elem
>
131 Elem
&get(CSSM_ATTRIBUTE_TYPE type
, CSSM_RETURN err
) const
133 if (Attr
*attr
= find(type
))
134 return static_cast<Elem
&>(*attr
);
136 CssmError::throwMe(err
);
139 template <class Elem
>
140 Elem
*get(CSSM_ATTRIBUTE_TYPE type
) const
142 if (Attr
*attr
= find(type
))
143 // @@@ Invoking conversion operator to Elem & on *attr and taking address of result.
144 return &static_cast<Elem
&>(*attr
);
149 uint32
getInt(CSSM_ATTRIBUTE_TYPE type
, CSSM_RETURN err
) const
151 if (Attr
*attr
= find(type
))
152 return static_cast<uint32
>(*attr
);
154 CssmError::throwMe(err
);
157 uint32
getInt(CSSM_ATTRIBUTE_TYPE type
) const
159 if (Attr
*attr
= find(type
))
160 return static_cast<uint32
>(*attr
);
167 void replace(CSSM_ATTRIBUTE_TYPE type
, const T
&newValue
) const
169 if (Attr
*attr
= find(type
))
170 *attr
= Attr(type
, newValue
);
172 CssmError::throwMe(CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT
);
176 void *operator new (size_t size
, CssmAllocator
&alloc
)
177 { return alloc
.malloc(size
); }
178 void operator delete (void *addr
, size_t, CssmAllocator
&alloc
)
179 { return alloc
.free(addr
); }
180 static void destroy(Context
*context
, CssmAllocator
&alloc
)
181 { alloc
.free(context
->ContextAttributes
); alloc
.free(context
); }
184 // Post-IPC context fixup.
185 // This can only be called on a Built Context after IPC transmission.
186 void postIPC(void *base
, CSSM_CONTEXT_ATTRIBUTE
*ipcAttributes
);
191 // dump to stdout, multiline format
192 IFDUMP(void dump(const char *title
= NULL
,
193 const CSSM_CONTEXT_ATTRIBUTE
*attrs
= NULL
) const;)
196 // find an attribute in a plain array of attribute structures (no context)
197 static Attr
*find(CSSM_ATTRIBUTE_TYPE theType
,
198 const CSSM_CONTEXT_ATTRIBUTE
*attrs
, unsigned int count
);
202 namespace DataWalkers
205 template <class Action
>
206 void walk(Action
&operate
, CSSM_CONTEXT_ATTRIBUTE
&attr
)
208 switch (attr
.AttributeType
& CSSM_ATTRIBUTE_TYPE_MASK
) {
209 case CSSM_ATTRIBUTE_DATA_CSSM_DATA
:
210 walk(operate
, attr
.Attribute
.Data
); break;
211 case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA
:
212 walk(operate
, attr
.Attribute
.CryptoData
); break;
213 case CSSM_ATTRIBUTE_DATA_KEY
:
214 walk(operate
, attr
.Attribute
.Key
); break;
215 case CSSM_ATTRIBUTE_DATA_STRING
:
216 walk(operate
, attr
.Attribute
.String
); break;
217 case CSSM_ATTRIBUTE_DATA_DATE
:
218 walk(operate
, attr
.Attribute
.Date
); break;
219 case CSSM_ATTRIBUTE_DATA_RANGE
:
220 walk(operate
, attr
.Attribute
.Range
); break;
221 case CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS
:
222 walk(operate
, attr
.Attribute
.AccessCredentials
); break;
223 case CSSM_ATTRIBUTE_DATA_VERSION
:
224 walk(operate
, attr
.Attribute
.Version
); break;
225 case CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE
:
226 walk(operate
, attr
.Attribute
.DLDbHandle
); break;
227 case CSSM_ATTRIBUTE_NONE
:
228 case CSSM_ATTRIBUTE_DATA_UINT32
:
231 assert(false); // unexpected type
235 } // end namespace DataWalkers
239 // Context::Builder - make context attributes the fun way.
241 // A Context (aka CSSM_CONTEXT) has a pointer to an array of context attributes,
242 // most of which contain pointers to other stuff with pointers to God Knows Where.
243 // Instead of allocating this all over the heap, a Context::Builder performs
244 // a two-pass algorithm that places all that stuff into a single heap node.
245 // Specifically, the builder will allocate and create a vector of CSSM_CONTEXT_ATTRIBUTE
246 // structures and all their subordinate heap storage.
247 // A Builder does not deal in Context objects and does not care what you do with your
248 // CSSM_CONTEXT_ATTRIBUTE array once it's delivered. Since it's a single heap node,
249 // you can just free() it using the appropriate allocator when you're done with it.
251 // Theory of operation:
252 // Builder works in two phases, called scan and build. During scan, you call setup()
253 // with the desired data to be placed into the attribute vector. When done, call make()
254 // to switch to build phase. Then call put() with the SAME sequence of values as in phase 1.
255 // Finally, call done() to receive the pointer-and-count values.
256 // @@@ Add comment about IPC use.
258 using namespace DataWalkers
;
260 class Context::Builder
{
263 Builder(CssmAllocator
&alloc
) : allocator(alloc
)
264 { slotCount
= 0; attributes
= NULL
; }
265 ~Builder() { allocator
.free(attributes
); }
267 CssmAllocator
&allocator
;
269 // switch to build phase
272 void done(CSSM_CONTEXT_ATTRIBUTE
* &attributes
, uint32
&count
);
276 // Phase 1 (scan) dispatch. Call once for each attribute needed.
279 void setup(T p
, CSSM_RETURN invalidError
= CSSM_OK
)
284 } else if (invalidError
)
285 CssmError::throwMe(invalidError
);
287 // dynamic attribute type
288 void setup(const CSSM_CONTEXT_ATTRIBUTE
&attr
)
289 { slotCount
++; walk(sizer
, const_cast<CSSM_CONTEXT_ATTRIBUTE
&>(attr
)); }
290 void setup(const Context::Attr
&attr
) { setup(static_cast<const CSSM_CONTEXT_ATTRIBUTE
&>(attr
)); }
293 // Phase 2 (copy) dispatch. Call once for each attribute, in same order as setup().
296 void put(CSSM_ATTRIBUTE_TYPE type
, const T
*p
)
299 assert(slot
< slotCount
); // check overflow
300 Attr
&attribute
= attributes
[slot
++];
301 attribute
.AttributeType
= type
;
302 attribute
.AttributeLength
= size(p
); //@@@ needed? how/when/what for?
303 attribute
= walk(copier
, p
);
306 void put(CSSM_ATTRIBUTE_TYPE type
, uint32 value
)
309 assert(slot
< slotCount
); // check overflow
310 Attr
&attribute
= attributes
[slot
++];
311 attribute
.AttributeType
= type
;
312 attribute
.AttributeLength
= 0; //@@@ unclear what that should be
313 attribute
= value
; // no heap data (immediate value)
316 void put(const CSSM_CONTEXT_ATTRIBUTE
&attr
)
318 assert(slot
< slotCount
);
319 Attr
&attribute
= attributes
[slot
++];
320 attribute
= attr
; // shallow copy
321 walk(copier
, attribute
); // deep copy
323 void put(const Context::Attr
&attr
) { put(static_cast<const CSSM_CONTEXT_ATTRIBUTE
&>(attr
)); }
326 // pass 1 state: collect sizes and counts
327 unsigned slotCount
; // count of attribute slots in use
328 SizeWalker sizer
; // memory size calculator
330 // pass 2 state: build the data set
331 Context::Attr
*attributes
; // attribute vector and start of block
332 CopyWalker copier
; // data copy engine
333 uint32 slot
; // writer slot position
336 } // end namespace Security