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