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