]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/cssmdata.h
Security-28.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / cssmdata.h
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 // cssmdata.h -- Manager different CssmData types
21 //
22 #ifndef _H_CDSA_UTILITIES_CSSMDATA
23 #define _H_CDSA_UTILITIES_CSSMDATA
24
25 #include <Security/utilities.h>
26 #include <Security/cssmalloc.h>
27 #include <Security/refcount.h>
28
29 #ifdef _CPP_CDSA_UTILITIES_CSSMDATA
30 #pragma export on
31 #endif
32
33 namespace Security
34 {
35
36 //
37 // The following pseudo-code describes what (at minimum) is required for a class
38 // to be a "PseudoData". PseudoData arguments are used in templates.
39 //
40 // class PseudoData {
41 // void *data() const ...
42 // size_t length() const ...
43 // operator const CssmData &() const ...
44 // }
45 //
46 // All this can be satisfied, of course, by inheriting form CssmData.
47 //
48
49
50 //
51 // A common virtual parent for CssmData-like objects that actively manage the
52 // allocation status of their data blob. Note that this is about allocating
53 // the data(), not the CssmData structure itself.
54 // The ManagedData layer provides for little active memory management, since
55 // the underlying strategies are potentially very disparate. It does however
56 // have a well defined interface for *yielding up* its data for copying or transfer.
57 //
58 class CssmManagedData {
59 public:
60 CssmManagedData(CssmAllocator &alloc) : allocator(alloc) { }
61 virtual ~CssmManagedData();
62
63 CssmAllocator &allocator;
64
65 virtual operator const CssmData & () const { return get(); }
66 template <class T> T *data() const { return reinterpret_cast<T *>(data()); }
67 void *data() const { return get().data(); }
68 size_t length() const { return get().length(); }
69
70 virtual CssmData &get() const throw() = 0; // get shared copy, no ownership change
71 virtual CssmData release() = 0; // give up copy, ownership is transferred
72 virtual void reset() = 0; // give up copy, data is discarded
73 };
74
75
76 //
77 // A CssmOwnedData is a CssmManagedData that unilaterally owns its data storage.
78 // It has its CssmData object provided during construction.
79 //
80 class CssmOwnedData : public CssmManagedData {
81 public:
82 CssmOwnedData(CssmAllocator &alloc, CssmData &mine) : CssmManagedData(alloc), referent(mine) { }
83
84 CssmOwnedData(CssmAllocator &alloc, CSSM_DATA &mine)
85 : CssmManagedData(alloc), referent(CssmData::overlay(mine)) { referent.clear(); }
86
87 //
88 // Basic retrievals (this echoes features of CssmData)
89 //
90 operator void * () const { return referent; }
91 operator char * () const { return referent; }
92 operator signed char * () const { return referent; }
93 operator unsigned char * () const { return referent; }
94
95 operator bool () const { return referent; }
96 bool operator ! () const { return !referent; }
97
98 size_t length() const { return referent.length(); }
99
100
101 //
102 // Basic allocators
103 //
104 void *malloc(size_t len)
105 {
106 // pseudo-atomic reallocation semantics
107 CssmAutoPtr<uint8> alloc(allocator, allocator.malloc<uint8>(len));
108 reset();
109 return referent = CssmData(alloc.release(), len);
110 }
111
112 void *realloc(size_t newLen)
113 {
114 // CssmAllocator::realloc() should be pseudo-atomic (i.e. throw on error)
115 return referent = CssmData(allocator.realloc<uint8>(referent.data(), newLen), newLen);
116 }
117
118 void length(size_t len) { realloc(len); }
119
120
121 //
122 // Manipulate existing data
123 //
124 void *append(const void *addData, size_t addLength)
125 {
126 size_t oldLength = length();
127 realloc(oldLength + addLength);
128 return memcpy(referent.at(oldLength), addData, addLength);
129 }
130
131 void *append(const CssmData &data)
132 { return append(data.data(), data.length()); }
133
134 //
135 // set() replaces current data with new, taking over ownership to the extent possible.
136 //
137 template <class T>
138 void set(T *data, size_t length)
139 {
140 // assume that data was allocated by our allocator -- we can't be sure
141 reset();
142 referent = CssmData(data, length);
143 }
144
145 void set(CssmManagedData &source);
146 void set(const CSSM_DATA &source) { set(source.Data, source.Length); }
147 // NOTE: General template set() cannot be used because all subclasses of CssmManagedData
148 // need to receive the special handling above. Use set(*.data(), *.length()) instead.
149
150
151 //
152 // copy() replaces current data with new, making a copy and leaving
153 // the source intact.
154 //
155 template <class T>
156 void copy(const T *data, size_t length)
157 {
158 // don't leave any open windows for Mr. Murphy
159 CssmAutoPtr<void> newData(allocator, memcpy(allocator.malloc(length), data, length));
160 reset();
161 referent = CssmData(newData.release(), length);
162 }
163
164 void copy(const CssmData &source)
165 { if (&source != &referent) copy(source.data(), source.length()); }
166 void copy(const CSSM_DATA &source)
167 { if (&source != &referent) copy(source.Data, source.Length); }
168 void copy(CssmManagedData &source) { copy(source.get()); }
169 template <class Data>
170 void copy(const Data &source) { copy(source.data(), source.length()); }
171
172
173 //
174 // Assignment conservatively uses copy if allocator unknown, set if known
175 //
176 void operator = (CssmManagedData &source) { set(source); }
177 void operator = (CssmOwnedData &source) { set(source); }
178 void operator = (const CSSM_DATA &source) { copy(source); }
179
180 CssmData &get() const throw() { return referent; }
181
182 protected:
183 CssmData &referent;
184 };
185
186
187 //
188 // A CssmAutoData is a CssmOwnedData that includes its CssmData object.
189 // This is the very simple case: The object includes ownership, data object,
190 // and data storage.
191 //
192 class CssmAutoData : public CssmOwnedData {
193 public:
194 CssmAutoData(CssmAllocator &alloc) : CssmOwnedData(alloc, mData) { }
195
196 template <class Data>
197 CssmAutoData(CssmAllocator &alloc, const Data &source) : CssmOwnedData(alloc, mData)
198 { *this = source; }
199
200 explicit CssmAutoData(CssmManagedData &source) : CssmOwnedData(source.allocator, mData)
201 { set(source); }
202
203 CssmAutoData(CssmAllocator &alloc, const void *data, size_t length)
204 : CssmOwnedData(alloc, mData) { copy(data, length); }
205
206 ~CssmAutoData() { allocator.free(mData); }
207
208 CssmData release();
209 void reset();
210
211 // assignment (not usefully inherited)
212 void operator = (CssmManagedData &source) { set(source); }
213 void operator = (CssmOwnedData &source) { set(source); }
214 void operator = (CssmAutoData &source) { set(source); }
215 template <class Data>
216 void operator = (const Data &source) { copy(source); }
217
218 private:
219 CssmData mData;
220 };
221
222
223 //
224 // A CssmRemoteData is a CssmOwnedData that uses an external CssmData object.
225 // Its release operation clears an internal ownership flag but does not clear
226 // the CssmData values so they can be used to return values to an outside scope.
227 //
228 class CssmRemoteData : public CssmOwnedData {
229 public:
230 CssmRemoteData(CssmAllocator &alloc, CssmData &mine)
231 : CssmOwnedData(alloc, mine), iOwnTheData(true) { }
232
233 CssmRemoteData(CssmAllocator &alloc, CSSM_DATA &mine)
234 : CssmOwnedData(alloc, mine), iOwnTheData(true) { }
235
236 ~CssmRemoteData()
237 { if (iOwnTheData) allocator.free(referent); }
238
239 CssmData release();
240 void reset();
241
242 // assignment (not usefully inherited)
243 void operator = (CssmManagedData &source) { set(source); }
244 void operator = (CssmOwnedData &source) { set(source); }
245 void operator = (CssmAutoData &source) { set(source); }
246 template <class Data>
247 void operator = (const Data &source) { copy(source); }
248
249 private:
250 bool iOwnTheData;
251 };
252
253
254 //
255 // CssmPolyData
256 //
257 // Used by functions that take a CssmData and would like to allow it to be
258 // initialized with a static string, int or other basic type. The function *must*
259 // copy the Data of the CssmPolyData when doing so if it is to be used
260 // after the function returns. (For example by creating a CssmDataContainer from it).
261 class CssmPolyData : public CssmData {
262 template <class T>
263 uint8 *set(const T &it)
264 { return const_cast<uint8 *>(reinterpret_cast<const uint8 *>(&it)); }
265 public:
266 template <class char_T>
267 CssmPolyData(const char_T *s) : CssmData(const_cast<char_T *>(s), strlen(s)) {}
268 CssmPolyData(const string &s) : CssmData(const_cast<char *>(s.c_str()), s.size()) {}
269 CssmPolyData(const CSSM_DATA &data) : CssmData(data.Data, data.Length) {}
270
271 // Don't use a template constructor (for T &) here - it would eat way too much
272 CssmPolyData(const bool &t) : CssmData(set(t), sizeof(t)) { }
273 CssmPolyData(const uint32 &t) : CssmData(set(t), sizeof(t)) { }
274 CssmPolyData(const sint32 &t) : CssmData(set(t), sizeof(t)) { }
275 CssmPolyData(const sint64 &t) : CssmData(set(t), sizeof(t)) { }
276 CssmPolyData(const double &t) : CssmData(set(t), sizeof(t)) { }
277 };
278
279 class CssmDateData : public CssmData
280 {
281 public:
282 CssmDateData(const CSSM_DATE &date);
283 private:
284 uint8 buffer[8];
285 };
286
287 class CssmGuidData : public CssmData
288 {
289 public:
290 CssmGuidData(const CSSM_GUID &guid);
291 private:
292 char buffer[Guid::stringRepLength + 1];
293 };
294
295
296 //
297 // CssmDLPolyData
298 //
299 class CssmDLPolyData
300 {
301 public:
302 CssmDLPolyData(const CSSM_DATA &data, CSSM_DB_ATTRIBUTE_FORMAT format)
303 : mData(CssmData::overlay(data)), mFormat(format) {}
304
305 // @@@ Don't use assert, but throw an exception.
306 // @@@ Do a size check on mData as well.
307
308 // @@@ This method is dangerous since the returned string is not guaranteed to be zero terminated.
309 operator const char *() const
310 {
311 assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_STRING
312 || mFormat == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE);
313 return reinterpret_cast<const char *>(mData.Data);
314 }
315 operator bool() const
316 {
317 assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_UINT32 || mFormat == CSSM_DB_ATTRIBUTE_FORMAT_SINT32);
318 return *reinterpret_cast<uint32 *>(mData.Data);
319 }
320 operator uint32() const
321 {
322 assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_UINT32);
323 return *reinterpret_cast<uint32 *>(mData.Data);
324 }
325 operator const uint32 *() const
326 {
327 assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32);
328 return reinterpret_cast<const uint32 *>(mData.Data);
329 }
330 operator sint32() const
331 {
332 assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_SINT32);
333 return *reinterpret_cast<sint32 *>(mData.Data);
334 }
335 operator double() const
336 {
337 assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_REAL);
338 return *reinterpret_cast<double *>(mData.Data);
339 }
340 operator CSSM_DATE () const;
341 operator Guid () const;
342 operator const CssmData &() const
343 {
344 return mData;
345 }
346
347 private:
348 const CssmData &mData;
349 CSSM_DB_ATTRIBUTE_FORMAT mFormat;
350 };
351
352
353 //
354 // Non POD refcounted CssmData wrapper that own the data it refers to.
355 //
356 class CssmDataContainer : public CssmData, public RefCount
357 {
358 public:
359 CssmDataContainer(CssmAllocator &inAllocator = CssmAllocator::standard()) :
360 CssmData(), mAllocator(inAllocator) {}
361 template <class T>
362 CssmDataContainer(const T *data, size_t length, CssmAllocator &inAllocator = CssmAllocator::standard()) :
363 CssmData(inAllocator.malloc(length), length), mAllocator(inAllocator)
364 { if (length) ::memcpy(Data, data, length); }
365 void clear() { if (Data) { mAllocator.free(Data); Data = NULL; Length = 0; } }
366 ~CssmDataContainer() { if (Data) mAllocator.free(Data); }
367 void append(const CssmPolyData &data)
368 {
369 uint32 newLength = Length + data.Length;
370 Data = reinterpret_cast<uint8 *>(mAllocator.realloc(Data, newLength));
371 memcpy(Data + Length, data.Data, data.Length);
372 Length = newLength;
373 }
374 CssmDataContainer(const CssmDataContainer &other)
375 : mAllocator(other.mAllocator)
376 {
377 Data = reinterpret_cast<uint8 *>(mAllocator.malloc(other.Length));
378 memcpy(Data, other.Data, other.Length);
379 Length = other.Length;
380 }
381 CssmDataContainer & operator = (const CSSM_DATA &other)
382 {
383 clear();
384 Data = reinterpret_cast<uint8 *>(mAllocator.malloc(other.Length));
385 memcpy(Data, other.Data, other.Length);
386 Length = other.Length;
387 return *this;
388 }
389
390 public:
391 CssmAllocator &mAllocator;
392
393 private:
394 operator CssmDataContainer * () const; // prohibit conversion-to-my-pointer
395 };
396
397 //
398 // CSSM_OIDs are CSSM_DATAs but will probably have different wrapping characteristics.
399 //
400 typedef CssmDataContainer CssmOidContainer;
401
402 template <class Container>
403 class CssmBuffer : public RefPointer<Container>
404 {
405 public:
406 CssmBuffer() : RefPointer<Container>(new Container()) {} // XXX This should may just set ptr to NULL.
407 template <class T>
408 CssmBuffer(const T *data, size_t length, CssmAllocator &inAllocator = CssmAllocator::standard()) :
409 RefPointer<Container>(new Container(data, length, inAllocator)) {}
410 CssmBuffer(const CSSM_DATA &data, CssmAllocator &inAllocator = CssmAllocator::standard()) :
411 RefPointer<Container>(new Container(data.Data, data.Length, inAllocator)) {}
412 CssmBuffer(const CssmBuffer& other) : RefPointer<Container>(other) {}
413 CssmBuffer(Container *p) : RefPointer<Container>(p) {}
414 bool CssmBuffer::operator < (const CssmBuffer &other) const { return (**this) < (*other); }
415 };
416
417 } // end namespace Security
418
419 #ifdef _CPP_CSSMDATA
420 #pragma export off
421 #endif
422
423 #endif // _H_CDSA_UTILITIES_CSSMDATA