]>
git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/blob.h
2 * Copyright (c) 2006,2011-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@
25 // blob - generic extensible binary blob frame
27 // To define a new type of binary blob:
28 // class MyBlob : public Blob<MyBlob, magic number> { ... }
29 // Pick a unique magic number (32-bit). Blobs are understood to be a MyBlob
30 // header possibly followed by more data as a contiguous memory area. Length
31 // is overall (including the header), so a fixed-size blob would have length
32 // sizeof(MyBlob). Both length and magic are stored in NBO.
34 // You are highly encouraged to follow these rules:
35 // Store all integers in NBO, including offsets.
36 // Use internal offsets to "point to" dynamically-sized elements past the
37 // header (using the at<Type>(offset) method for access).
38 // Don't use pointers in your blob.
39 // If you follow those rules, your blobs will be fully relocatable, byte-order
40 // independent, and generally spreading happiness around your code.
45 #include <security_utilities/endian.h>
46 #include <security_utilities/memutils.h>
47 #include <security_utilities/errors.h>
53 // All blobs in memory have this form.
54 // You can have polymorphic memory blobs (C style) using different magics numbers.
58 typedef uint32_t Offset
;
59 typedef uint32_t Magic
;
61 Magic
magic() const { return mMagic
; }
62 size_t length() const { return mLength
; }
64 void initialize(Magic magic
, size_t length
= 0)
65 { mMagic
= magic
; mLength
= (uint32_t)length
; }
67 bool validateBlob(Magic magic
, size_t minSize
= 0, size_t maxSize
= 0) const;
69 template <class T
, class Offset
>
71 { return LowLevelMemoryUtilities::increment
<T
>(this, offset
); }
73 template <class T
, class Offset
>
74 const T
*at(Offset offset
) const
75 { return LowLevelMemoryUtilities::increment
<const T
>(this, offset
); }
77 template <class Offset1
, class Offset2
>
78 bool contains(Offset1 offset
, Offset2 size
) const
79 { return offset
>= 0 && size_t(offset
) >= sizeof(BlobCore
) && (size_t(offset
) + size
) <= this->length(); }
81 template <class Base
, class Offset
>
82 bool contains(Base
*ptr
, Offset size
) const
83 { return contains(LowLevelMemoryUtilities::difference(ptr
, this), size
); }
85 char *stringAt(Offset offset
);
86 const char *stringAt(Offset offset
) const;
88 void *data() { return this; }
89 const void *data() const { return this; }
90 void length(size_t size
) { mLength
= (uint32_t)size
; }
92 BlobCore
*clone() const
94 if (BlobCore
*copy
= (BlobCore
*)malloc(this->length())) {
95 memcpy(copy
, this, this->length());
98 UnixError::throwMe(ENOMEM
);
101 template <class BlobType
>
102 bool is() const { return magic() == BlobType::typeMagic
; }
104 static BlobCore
*readBlob(std::FILE *file
) { return readBlob(file
, 0, 0, 0); }
105 static BlobCore
*readBlob(int fd
) { return readBlob(fd
, 0, 0, 0); }
108 static BlobCore
*readBlob(std::FILE *file
, uint32_t magic
, size_t minSize
, size_t maxSize
); // streaming
109 static BlobCore
*readBlob(int fd
, uint32_t magic
, size_t minSize
, size_t maxSize
); // streaming
110 static BlobCore
*readBlob(int fd
, size_t offset
, uint32_t magic
, size_t minSize
, size_t maxSize
); // pread(2)@offset
113 Endian
<uint32_t> mMagic
;
114 Endian
<uint32_t> mLength
;
118 // basic validation helper
119 inline bool BlobCore::validateBlob(Magic magic
, size_t minSize
/* = 0 */, size_t maxSize
/* = 0 */) const
121 uint32_t length
= this->mLength
;
122 if (magic
&& magic
!= this->mMagic
) {
126 if (minSize
? (length
< minSize
) : (length
< sizeof(BlobCore
))) {
130 if (maxSize
&& length
> maxSize
) {
139 // Typed Blobs (BlobCores that know their real type and magic)
141 template <class BlobType
, uint32_t _magic
>
142 class Blob
: public BlobCore
{
144 void initialize(size_t size
= 0) { BlobCore::initialize(_magic
, size
); }
146 static const Magic typeMagic
= _magic
;
148 bool validateBlob() const
149 { return BlobCore::validateBlob(_magic
, sizeof(BlobType
)); }
151 bool validateBlob(size_t extLength
) const
152 { return extLength
>= sizeof(BlobType
) && validateBlob() && mLength
== extLength
; }
154 static BlobType
*specific(BlobCore
*blob
, bool unalloc
= false)
156 if (BlobType
*p
= static_cast<BlobType
*>(blob
)) {
157 if (p
->validateBlob())
165 static const BlobType
*specific(const BlobCore
*blob
)
167 const BlobType
*p
= static_cast<const BlobType
*>(blob
);
168 if (p
&& p
->validateBlob())
173 BlobType
*clone() const
174 { assert(validateBlob()); return specific(this->BlobCore::clone()); }
176 static BlobType
*readBlob(int fd
)
177 { return specific(BlobCore::readBlob(fd
, _magic
, sizeof(BlobType
), 0), true); }
179 static BlobType
*readBlob(int fd
, size_t offset
, size_t maxSize
= 0)
180 { return specific(BlobCore::readBlob(fd
, offset
, _magic
, sizeof(BlobType
), maxSize
), true); }
182 static BlobType
*readBlob(std::FILE *file
)
183 { return specific(BlobCore::readBlob(file
, _magic
, sizeof(BlobType
), 0), true); }
188 // A generic blob wrapped around arbitrary (flat) binary data.
189 // This can be used to "regularize" plain binary data, so it can be handled
190 // as a genuine Blob (e.g. for insertion into a SuperBlob).
192 class BlobWrapper
: public Blob
<BlobWrapper
, 0xfade0b01> {
194 static BlobWrapper
*alloc(size_t length
, Magic magic
= BlobWrapper::typeMagic
);
195 static BlobWrapper
*alloc(const void *data
, size_t length
, Magic magic
= BlobWrapper::typeMagic
);
197 unsigned char dataArea
[0];
199 // override data/length to point to the payload (only)
200 void *data() { return dataArea
; }
201 const void *data() const { return dataArea
; }
202 size_t length() const { return BlobCore::length() - sizeof(BlobCore
); }