2 * Copyright (c) 2000-2006,2011-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 // cssmdata.h -- Manager different CssmData types
28 #ifndef _H_CDSA_UTILITIES_CSSMDATA
29 #define _H_CDSA_UTILITIES_CSSMDATA
31 #include <security_utilities/alloc.h>
32 #include <security_utilities/refcount.h>
33 #include <security_cdsa_utilities/cssmerrors.h>
34 #include <Security/cssmerr.h>
35 #include <CoreFoundation/CoreFoundation.h>
41 // User-friendlier CSSM_DATA thingies.
42 // CssmData is a PODWrapper for CSSM_DATA, but is also used throughout
43 // the security code as a "byte blob" representation.
45 class CssmData
: public PodWrapper
<CssmData
, CSSM_DATA
> {
47 CssmData() { Data
= 0; Length
= 0; }
49 size_t length() const { return Length
; }
50 void *data() const { return Data
; }
51 void *end() const { return Data
+ Length
; }
54 // Create a CssmData from any pointer-to-byte-sized-object and length.
56 CssmData(void *data
, size_t length
)
57 { Data
= reinterpret_cast<UInt8
*>(data
); Length
= length
; }
58 CssmData(char *data
, size_t length
)
59 { Data
= reinterpret_cast<UInt8
*>(data
); Length
= length
; }
60 CssmData(unsigned char *data
, size_t length
)
61 { Data
= reinterpret_cast<UInt8
*>(data
); Length
= length
; }
62 CssmData(signed char *data
, size_t length
)
63 { Data
= reinterpret_cast<UInt8
*>(data
); Length
= length
; }
65 CssmData(CFDataRef cf
)
66 { Data
= const_cast<UInt8
*>(CFDataGetBytePtr(cf
)); Length
= CFDataGetLength(cf
); }
68 // the void * form accepts too much; explicitly deny all other types
69 private: template <class T
> CssmData(T
*, size_t); public:
71 // explicitly construct from a data-oid source
73 explicit CssmData(const T
&obj
)
74 { Data
= (UInt8
*)obj
.data(); Length
= obj
.length(); }
77 // Do allow generic "wrapping" of any data structure, but make it conspicuous
78 // since it's not necessarily the Right Thing (alignment and byte order wise).
79 // Also note that the T & form removes const-ness, since there is no ConstCssmData.
82 static CssmData
wrap(const T
&it
)
83 { return CssmData(const_cast<void *>(reinterpret_cast<const void *>(&it
)), sizeof(it
)); }
86 static CssmData
wrap(T
*data
, size_t length
)
87 { return CssmData(const_cast<void *>(static_cast<const void *>(data
)), length
); }
90 // Automatically convert a CssmData to any pointer-to-byte-sized-type.
92 operator signed char * () const { return reinterpret_cast<signed char *>(Data
); }
93 operator unsigned char * () const { return reinterpret_cast<unsigned char *>(Data
); }
94 operator char * () const { return reinterpret_cast<char *>(Data
); }
95 operator void * () const { return reinterpret_cast<void *>(Data
); }
98 // If you want to interpret the contents of a CssmData blob as a particular
99 // type, you have to be more explicit to show that you know what you're doing.
103 T
*interpretedAs() const { return reinterpret_cast<T
*>(Data
); }
106 T
*interpretedAs(CSSM_RETURN error
) const
107 { return interpretedAs
<T
>(sizeof(T
), error
); }
110 T
*interpretedAs(size_t len
, CSSM_RETURN error
) const
112 if (data() == NULL
|| length() != len
) CssmError::throwMe(error
);
113 return interpretedAs
<T
>();
117 void length(size_t newLength
) // shorten only
118 { assert(newLength
<= Length
); Length
= newLength
; }
120 void *at(off_t offset
) const
121 { assert(offset
>= 0 && (CSSM_SIZE
)offset
<= Length
); return Data
+ offset
; }
122 void *at(off_t offset
, size_t size
) const // length-checking version
123 { assert(offset
>= 0 && (CSSM_SIZE
)offset
+ size
<= Length
); return Data
+ offset
; }
125 template <class T
> T
*at(off_t offset
) const { return reinterpret_cast<T
*>(at(offset
)); }
126 template <class T
> T
*at(off_t offset
, size_t size
) const
127 { return reinterpret_cast<T
*>(at(offset
, size
)); }
129 unsigned char byte(off_t offset
) const { return *at
<unsigned char>(offset
); }
130 unsigned char &byte(off_t offset
) { return *at
<unsigned char>(offset
); }
132 void *use(size_t taken
) // logically remove some bytes
133 { assert(taken
<= Length
); void *r
= Data
; Length
-= taken
; Data
+= taken
; return r
; }
136 { Data
= NULL
; Length
= 0; }
138 string
toString () const; // convert to string type (no trailing null)
139 string
toHex() const; // hex string of binary blob
140 string
toOid() const; // standard OID string encoding (1.2.3...)
141 void fromHex(const char *digits
); // fill myself with hex data (no allocation)
143 operator bool () const { return Data
!= NULL
; }
144 bool operator ! () const { return Data
== NULL
; }
145 bool operator < (const CssmData
&other
) const;
146 bool operator == (const CssmData
&other
) const
147 { return length() == other
.length() && !memcmp(data(), other
.data(), length()); }
148 bool operator != (const CssmData
&other
) const
149 { return !(*this == other
); }
151 // Extract fixed-format data from a CssmData. Fixes any alignment trouble for you.
153 void extract(T
&destination
, CSSM_RETURN error
= CSSM_ERRCODE_INVALID_DATA
) const
155 if (length() != sizeof(destination
) || data() == NULL
)
156 CssmError::throwMe(error
);
157 memcpy(&destination
, data(), sizeof(destination
));
162 inline bool CssmData::operator < (const CssmData
&other
) const
164 if (Length
!= other
.Length
) // If lengths are not equal the shorter data is smaller.
165 return Length
< other
.Length
;
166 if (Length
== 0) // If lengths are both zero ignore the Data.
168 if (Data
== NULL
|| other
.Data
== NULL
) // arbitrary (but consistent) ordering
169 return Data
< other
.Data
;
170 return memcmp(Data
, other
.Data
, Length
) < 0; // Do a lexicographic compare on equal sized Data.
175 // CSSM_OIDs are CSSM_DATAs but will probably have different wrapping characteristics.
177 typedef CssmData CssmOid
;
181 // A convenient way to make a CssmData from a (const) string.
182 // Note that the underlying string is not memory-managed, so it
183 // should either be static or of sufficient (immutable) lifetime.
185 class StringData
: public CssmData
{
187 StringData(const char *s
) : CssmData(const_cast<char *>(s
), strlen(s
)) { }
188 StringData(const std::string
&s
) : CssmData(const_cast<char *>(s
.c_str()), s
.size()) { }
193 // A CssmData bundled up with a data buffer it refers to
195 template <size_t size
>
196 struct DataBuffer
: public CssmData
{
197 unsigned char buffer
[size
];
198 DataBuffer() : CssmData(buffer
, size
) { }
203 // Comparing CssmDatas for equality.
204 // Note: No ordering is established here.
205 // Both CSSM_DATAs have to exist.
207 bool operator == (const CSSM_DATA
&d1
, const CSSM_DATA
&d2
);
208 inline bool operator != (const CSSM_DATA
&d1
, const CSSM_DATA
&d2
)
209 { return !(d1
== d2
); }
213 // The following pseudo-code describes what (at minimum) is required for a class
214 // to be a "PseudoData". PseudoData arguments ("DataOids") are used in templates.
216 // class PseudoData {
217 // void *data() const ...
218 // size_t length() const ...
219 // operator const CssmData &() const ...
222 // All this can be satisfied, of course, by inheriting from CssmData.
227 // A common virtual parent for CssmData-like objects that actively manage the
228 // allocation status of their data blob. Note that this is about allocating
229 // the data(), not the CssmData structure itself.
230 // The ManagedData layer provides for little active memory management, since
231 // the underlying strategies are potentially very disparate. It does however
232 // have a well defined interface for *yielding up* its data for copying or transfer.
234 class CssmManagedData
{
236 CssmManagedData(Allocator
&alloc
) : allocator(alloc
) { }
237 virtual ~CssmManagedData();
239 Allocator
&allocator
;
241 virtual operator const CssmData
& () const { return get(); }
242 template <class T
> T
*data() const { return reinterpret_cast<T
*>(data()); }
243 void *data() const { return get().data(); }
244 size_t length() const { return get().length(); }
246 virtual CssmData
&get() const throw() = 0; // get shared copy, no ownership change
247 virtual CssmData
release() = 0; // give up copy, ownership is transferred
248 virtual void reset() = 0; // give up copy, data is discarded
252 inline bool operator == (const CssmManagedData
&d1
, const CssmData
&d2
)
253 { return d1
.get() == d2
; }
255 inline bool operator == (const CssmData
&d1
, const CssmManagedData
&d2
)
256 { return d1
== d2
.get(); }
258 inline bool operator == (const CssmManagedData
&d1
, const CssmManagedData
&d2
)
259 { return d1
.get() == d2
.get(); }
261 inline bool operator != (const CssmManagedData
&d1
, const CssmData
&d2
)
262 { return d1
.get() != d2
; }
264 inline bool operator != (const CssmData
&d1
, const CssmManagedData
&d2
)
265 { return d1
!= d2
.get(); }
267 inline bool operator != (const CssmManagedData
&d1
, const CssmManagedData
&d2
)
268 { return d1
.get() != d2
.get(); }
272 // A CssmOwnedData is a CssmManagedData that unilaterally owns its data storage.
273 // It has its CssmData object provided during construction.
275 class CssmOwnedData
: public CssmManagedData
{
277 CssmOwnedData(Allocator
&alloc
, CssmData
&mine
) : CssmManagedData(alloc
), referent(mine
) { }
279 CssmOwnedData(Allocator
&alloc
, CSSM_DATA
&mine
)
280 : CssmManagedData(alloc
), referent(CssmData::overlay(mine
)) { referent
.clear(); }
283 // Basic retrievals (this echoes features of CssmData)
285 operator void * () const { return referent
; }
286 operator char * () const { return referent
; }
287 operator signed char * () const { return referent
; }
288 operator unsigned char * () const { return referent
; }
290 operator bool () const { return referent
; }
291 bool operator ! () const { return !referent
; }
293 size_t length() const { return referent
.length(); }
299 void *malloc(size_t len
)
301 // pseudo-atomic reallocation semantics
302 CssmAutoPtr
<uint8
> alloc(allocator
, allocator
.malloc
<uint8
>(len
));
304 return referent
= CssmData(alloc
.release(), len
);
307 void *realloc(size_t newLen
)
309 // Allocator::realloc() should be pseudo-atomic (i.e. throw on error)
310 return referent
= CssmData(allocator
.realloc
<uint8
>(referent
.data(), newLen
), newLen
);
313 void length(size_t len
) { realloc(len
); }
317 // Manipulate existing data
319 void *append(const void *addData
, size_t addLength
)
321 size_t oldLength
= length();
322 realloc(oldLength
+ addLength
);
323 return memcpy(referent
.at(oldLength
), addData
, addLength
);
326 void *append(const CssmData
&data
)
327 { return append(data
.data(), data
.length()); }
331 // set() replaces current data with new, taking over ownership to the extent possible.
334 void set(T
*data
, size_t length
)
336 // assume that data was allocated by our allocator -- we can't be sure
338 referent
= CssmData(data
, length
);
341 void set(CssmManagedData
&source
);
342 void set(const CSSM_DATA
&source
) { set(source
.Data
, source
.Length
); }
343 // NOTE: General template set() cannot be used because all subclasses of CssmManagedData
344 // need to receive the special handling above. Use set(*.data(), *.length()) instead.
348 // copy() replaces current data with new, making a copy and leaving
349 // the source intact.
352 void copy(const T
*data
, size_t length
)
354 CssmAutoPtr
<void> newData(allocator
, memcpy(allocator
.malloc(length
), data
, length
));
356 referent
= CssmData(newData
.release(), length
);
359 void copy(const CssmData
&source
)
360 { if (&source
!= &referent
) copy(source
.data(), source
.length()); }
361 void copy(const CSSM_DATA
&source
)
362 { if (&source
!= &referent
) copy(source
.Data
, source
.Length
); }
363 void copy(CssmManagedData
&source
) { copy(source
.get()); }
364 template <class Data
>
365 void copy(const Data
&source
) { copy(source
.data(), source
.length()); }
369 // Assignment conservatively uses copy if allocator unknown, set if known
371 void operator = (CssmManagedData
&source
) { set(source
); }
372 void operator = (CssmOwnedData
&source
) { set(source
); }
373 void operator = (const CSSM_DATA
&source
) { copy(source
); }
375 CssmData
&get() const throw();
378 void fromOid(const char *oid
); // fill from text OID form (1.2.3...)
386 // A CssmAutoData is a CssmOwnedData that includes its CssmData object.
387 // This is the very simple case: The object includes ownership, data object,
390 class CssmAutoData
: public CssmOwnedData
{
392 CssmAutoData(Allocator
&alloc
) : CssmOwnedData(alloc
, mData
) { }
394 template <class Data
>
395 CssmAutoData(Allocator
&alloc
, const Data
&source
) : CssmOwnedData(alloc
, mData
)
398 CssmAutoData(CssmAutoData
&source
) : CssmOwnedData(source
.allocator
, mData
)
401 explicit CssmAutoData(CssmManagedData
&source
) : CssmOwnedData(source
.allocator
, mData
)
404 CssmAutoData(Allocator
&alloc
, const void *data
, size_t length
)
405 : CssmOwnedData(alloc
, mData
) { copy(data
, length
); }
407 ~CssmAutoData() { allocator
.free(mData
); }
412 // assignment (not usefully inherited)
413 void operator = (CssmManagedData
&source
) { set(source
); }
414 void operator = (CssmOwnedData
&source
) { set(source
); }
415 void operator = (CssmAutoData
&source
) { set(source
); }
416 template <class Data
>
417 void operator = (const Data
&source
) { copy(source
); }
425 // A CssmRemoteData is a CssmOwnedData that uses an external CssmData object.
426 // Its release operation clears an internal ownership flag but does not clear
427 // the CssmData values so they can be used to return values to an outside scope.
429 class CssmRemoteData
: public CssmOwnedData
{
431 CssmRemoteData(Allocator
&alloc
, CssmData
&mine
)
432 : CssmOwnedData(alloc
, mine
), iOwnTheData(true) { }
434 CssmRemoteData(Allocator
&alloc
, CSSM_DATA
&mine
)
435 : CssmOwnedData(alloc
, mine
), iOwnTheData(true) { }
438 { if (iOwnTheData
) allocator
.free(referent
); }
443 // assignment (not usefully inherited)
444 void operator = (CssmManagedData
&source
) { set(source
); }
445 void operator = (CssmOwnedData
&source
) { set(source
); }
446 void operator = (CssmAutoData
&source
) { set(source
); }
447 template <class Data
>
448 void operator = (const Data
&source
) { copy(source
); }
458 // Used by functions that take a CssmData and would like to allow it to be
459 // initialized with a static string, int or other basic type. The function *must*
460 // copy the Data of the CssmPolyData when doing so if it is to be used
461 // after the function returns. (For example by creating a CssmDataContainer from it).
462 class CssmPolyData
: public CssmData
{
464 uint8
*set(const T
&it
)
465 { return const_cast<uint8
*>(reinterpret_cast<const uint8
*>(&it
)); }
467 template <class char_T
>
468 CssmPolyData(const char_T
*s
) : CssmData(const_cast<char_T
*>(s
), strlen(s
)) {}
469 CssmPolyData(const string
&s
) : CssmData(const_cast<char *>(s
.c_str()), s
.size()) {}
470 CssmPolyData(const CSSM_DATA
&data
) : CssmData(data
.Data
, data
.Length
) {}
472 // Don't use a template constructor (for T &) here - it would eat way too much
473 CssmPolyData(const bool &t
) : CssmData(set(t
), sizeof(t
)) { }
474 CssmPolyData(const uint32
&t
) : CssmData(set(t
), sizeof(t
)) { }
475 CssmPolyData(const sint32
&t
) : CssmData(set(t
), sizeof(t
)) { }
476 CssmPolyData(const sint64
&t
) : CssmData(set(t
), sizeof(t
)) { }
477 CssmPolyData(const double &t
) : CssmData(set(t
), sizeof(t
)) { }
478 CssmPolyData(const unsigned long &t
) : CssmData(set(t
), sizeof(t
)) { }
479 CssmPolyData(const CSSM_GUID
&t
) : CssmData(set(t
), sizeof(t
)) { }
480 CssmPolyData(const StringPtr s
) : CssmData (reinterpret_cast<char*>(s
+ 1), uint32 (s
[0])) {}
483 class CssmDateData
: public CssmData
486 CssmDateData(const CSSM_DATE
&date
);
493 // Non POD refcounted CssmData wrapper that own the data it refers to.
495 class CssmDataContainer
: public CssmData
, public RefCount
498 CssmDataContainer(Allocator
&inAllocator
= Allocator::standard()) :
499 CssmData(), mAllocator(inAllocator
) {}
501 CssmDataContainer(const T
*data
, size_t length
, Allocator
&inAllocator
= Allocator::standard()) :
502 CssmData(inAllocator
.malloc(length
), length
), mAllocator(inAllocator
)
503 { if (length
) ::memcpy(Data
, data
, length
); }
504 void clear() { if (Data
) { mAllocator
.free(Data
); Data
= NULL
; Length
= 0; } }
505 void invalidate () {Data
= NULL
; Length
= 0;}
506 ~CssmDataContainer() { if (Data
) mAllocator
.free(Data
); }
507 void append(const CssmPolyData
&data
)
509 size_t newLength
= Length
+ data
.Length
;
510 Data
= reinterpret_cast<uint8
*>(mAllocator
.realloc(Data
, newLength
));
511 memcpy(Data
+ Length
, data
.Data
, data
.Length
);
514 CssmDataContainer(const CssmDataContainer
&other
)
515 : mAllocator(other
.mAllocator
)
517 Data
= reinterpret_cast<uint8
*>(mAllocator
.malloc(other
.Length
));
518 memcpy(Data
, other
.Data
, other
.Length
);
519 Length
= other
.Length
;
521 CssmDataContainer
& operator = (const CSSM_DATA
&other
)
524 Data
= reinterpret_cast<uint8
*>(mAllocator
.malloc(other
.Length
));
525 memcpy(Data
, other
.Data
, other
.Length
);
526 Length
= other
.Length
;
531 Allocator
&mAllocator
;
534 operator CssmDataContainer
* () const; // prohibit conversion-to-my-pointer
538 // CSSM_OIDs are CSSM_DATAs but will probably have different wrapping characteristics.
540 typedef CssmDataContainer CssmOidContainer
;
542 template <class Container
>
543 class CssmBuffer
: public RefPointer
<Container
>
546 CssmBuffer() : RefPointer
<Container
>(new Container()) {} // XXX This should may just set ptr to NULL.
548 CssmBuffer(const T
*data
, size_t length
, Allocator
&inAllocator
= Allocator::standard()) :
549 RefPointer
<Container
>(new Container(data
, length
, inAllocator
)) {}
550 CssmBuffer(const CSSM_DATA
&data
, Allocator
&inAllocator
= Allocator::standard()) :
551 RefPointer
<Container
>(new Container(data
.Data
, data
.Length
, inAllocator
)) {}
552 CssmBuffer(const CssmBuffer
& other
) : RefPointer
<Container
>(other
) {}
553 CssmBuffer(Container
*p
) : RefPointer
<Container
>(p
) {}
554 bool operator < (const CssmBuffer
&other
) const { return (**this) < (*other
); }
558 } // end namespace Security
560 #endif // _H_CDSA_UTILITIES_CSSMDATA