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
);
165 bool getInt(CSSM_ATTRIBUTE_TYPE type
, uint32
&value
) const
167 if (Attr
*attr
= find(type
)) {
168 value
= static_cast<uint32
>(*attr
);
176 void replace(CSSM_ATTRIBUTE_TYPE type
, const T
&newValue
) const
178 if (Attr
*attr
= find(type
))
179 *attr
= Attr(type
, newValue
);
181 CssmError::throwMe(CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT
);
185 void *operator new (size_t size
, CssmAllocator
&alloc
) throw(std::bad_alloc
)
186 { return alloc
.malloc(size
); }
187 void operator delete (void *addr
, size_t, CssmAllocator
&alloc
) throw()
188 { return alloc
.free(addr
); }
189 static void destroy(Context
*context
, CssmAllocator
&alloc
) throw()
190 { alloc
.free(context
->ContextAttributes
); alloc
.free(context
); }
193 // Post-IPC context fixup.
194 // This can only be called on a Built Context after IPC transmission.
195 void postIPC(void *base
, CSSM_CONTEXT_ATTRIBUTE
*ipcAttributes
);
200 // dump to stdout, multiline format
201 IFDUMP(void dump(const char *title
= NULL
,
202 const CSSM_CONTEXT_ATTRIBUTE
*attrs
= NULL
) const;)
205 // find an attribute in a plain array of attribute structures (no context)
206 static Attr
*find(CSSM_ATTRIBUTE_TYPE theType
,
207 const CSSM_CONTEXT_ATTRIBUTE
*attrs
, unsigned int count
);
211 namespace DataWalkers
214 template <class Action
>
215 void walk(Action
&operate
, CSSM_CONTEXT_ATTRIBUTE
&attr
)
217 switch (attr
.AttributeType
& CSSM_ATTRIBUTE_TYPE_MASK
) {
218 case CSSM_ATTRIBUTE_DATA_CSSM_DATA
:
219 walk(operate
, attr
.Attribute
.Data
); break;
220 case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA
:
221 walk(operate
, attr
.Attribute
.CryptoData
); break;
222 case CSSM_ATTRIBUTE_DATA_KEY
:
223 walk(operate
, attr
.Attribute
.Key
); break;
224 case CSSM_ATTRIBUTE_DATA_STRING
:
225 walk(operate
, attr
.Attribute
.String
); break;
226 case CSSM_ATTRIBUTE_DATA_DATE
:
227 walk(operate
, attr
.Attribute
.Date
); break;
228 case CSSM_ATTRIBUTE_DATA_RANGE
:
229 walk(operate
, attr
.Attribute
.Range
); break;
230 case CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS
:
231 walk(operate
, attr
.Attribute
.AccessCredentials
); break;
232 case CSSM_ATTRIBUTE_DATA_VERSION
:
233 walk(operate
, attr
.Attribute
.Version
); break;
234 case CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE
:
235 walk(operate
, attr
.Attribute
.DLDbHandle
); break;
236 case CSSM_ATTRIBUTE_NONE
:
237 case CSSM_ATTRIBUTE_DATA_UINT32
:
240 assert(false); // unexpected type
244 } // end namespace DataWalkers
248 // Context::Builder - make context attributes the fun way.
250 // A Context (aka CSSM_CONTEXT) has a pointer to an array of context attributes,
251 // most of which contain pointers to other stuff with pointers to God Knows Where.
252 // Instead of allocating this all over the heap, a Context::Builder performs
253 // a two-pass algorithm that places all that stuff into a single heap node.
254 // Specifically, the builder will allocate and create a vector of CSSM_CONTEXT_ATTRIBUTE
255 // structures and all their subordinate heap storage.
256 // A Builder does not deal in Context objects and does not care what you do with your
257 // CSSM_CONTEXT_ATTRIBUTE array once it's delivered. Since it's a single heap node,
258 // you can just free() it using the appropriate allocator when you're done with it.
260 // Theory of operation:
261 // Builder works in two phases, called scan and build. During scan, you call setup()
262 // with the desired data to be placed into the attribute vector. When done, call make()
263 // to switch to build phase. Then call put() with the SAME sequence of values as in phase 1.
264 // Finally, call done() to receive the pointer-and-count values.
265 // @@@ Add comment about IPC use.
267 using namespace DataWalkers
;
269 class Context::Builder
{
272 Builder(CssmAllocator
&alloc
) : allocator(alloc
)
273 { slotCount
= 0; attributes
= NULL
; }
274 ~Builder() { allocator
.free(attributes
); }
276 CssmAllocator
&allocator
;
278 // switch to build phase
281 void done(CSSM_CONTEXT_ATTRIBUTE
* &attributes
, uint32
&count
);
285 // Phase 1 (scan) dispatch. Call once for each attribute needed.
288 void setup(T p
, CSSM_RETURN invalidError
= CSSM_OK
)
293 } else if (invalidError
)
294 CssmError::throwMe(invalidError
);
296 // dynamic attribute type
297 void setup(const CSSM_CONTEXT_ATTRIBUTE
&attr
)
298 { slotCount
++; walk(sizer
, const_cast<CSSM_CONTEXT_ATTRIBUTE
&>(attr
)); }
299 void setup(const Context::Attr
&attr
) { setup(static_cast<const CSSM_CONTEXT_ATTRIBUTE
&>(attr
)); }
302 // Phase 2 (copy) dispatch. Call once for each attribute, in same order as setup().
305 void put(CSSM_ATTRIBUTE_TYPE type
, const T
*p
)
308 assert(slot
< slotCount
); // check overflow
309 Attr
&attribute
= attributes
[slot
++];
310 attribute
.AttributeType
= type
;
311 attribute
.AttributeLength
= size(p
); //@@@ needed? how/when/what for?
312 attribute
= walk(copier
, p
);
315 void put(CSSM_ATTRIBUTE_TYPE type
, uint32 value
)
318 assert(slot
< slotCount
); // check overflow
319 Attr
&attribute
= attributes
[slot
++];
320 attribute
.AttributeType
= type
;
321 attribute
.AttributeLength
= 0; //@@@ unclear what that should be
322 attribute
= value
; // no heap data (immediate value)
325 void put(const CSSM_CONTEXT_ATTRIBUTE
&attr
)
327 assert(slot
< slotCount
);
328 Attr
&attribute
= attributes
[slot
++];
329 attribute
= attr
; // shallow copy
330 walk(copier
, attribute
); // deep copy
332 void put(const Context::Attr
&attr
) { put(static_cast<const CSSM_CONTEXT_ATTRIBUTE
&>(attr
)); }
335 // pass 1 state: collect sizes and counts
336 unsigned slotCount
; // count of attribute slots in use
337 SizeWalker sizer
; // memory size calculator
339 // pass 2 state: build the data set
340 Context::Attr
*attributes
; // attribute vector and start of block
341 CopyWalker copier
; // data copy engine
342 uint32 slot
; // writer slot position
345 } // end namespace Security