2 * Copyright (c) 2006 Apple Computer, 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.
53 // CodeDirectory slot numbers, used to index the EmbeddedSignatureBlob (from codedirectory.h, internal)
54 cdRequirementsSlot
= 2 // embedded signature: internal requirements
58 // Code Signing magic blob types (from <Security/CSCommonPriv.h>)
59 kSecCodeMagicRequirement
= 0xfade0c00, /* single requirement */
60 kSecCodeMagicRequirementSet
= 0xfade0c01, /* requirement set */
61 kSecCodeMagicEmbeddedSignature
= 0xfade0cc0, /* single-architecture embedded signature */
63 kSecCodeMagicDRList
= 0xfade0c05
68 kSecDesignatedRequirementType
= 3 /* designated requirement */
72 // All blobs in memory have this form.
73 // You can have polymorphic memory blobs (C style) using different magics numbers.
77 typedef uint32_t Offset
;
78 typedef uint32_t Magic
;
80 Magic
magic() const { return mMagic
; }
81 size_t length() const { return mLength
; }
83 void initialize(Magic mag
, size_t len
= 0)
84 { mMagic
= mag
; mLength
= len
; }
86 bool validateBlob(Magic magic
, size_t minSize
= 0, size_t maxSize
= 0) const;
88 template <class T
, class Offset
>
90 { return LowLevelMemoryUtilities::increment
<T
>(this, offset
); }
92 template <class T
, class Offset
>
93 const T
*at(Offset offset
) const
94 { return LowLevelMemoryUtilities::increment
<const T
>(this, offset
); }
96 template <class Offset1
, class Offset2
>
97 bool contains(Offset1 offset
, Offset2 size
) const
98 { return offset
>= 0 && size_t(offset
) >= sizeof(BlobCore
) && (size_t(offset
) + size
) <= this->length(); }
100 template <class Base
, class Offset
>
101 bool contains(Base
*ptr
, Offset size
) const
102 { return contains(LowLevelMemoryUtilities::difference(ptr
, this), size
); }
104 char *stringAt(Offset offset
);
105 const char *stringAt(Offset offset
) const;
107 void *data() { return this; }
108 const void *data() const { return this; }
109 void length(size_t size
) { mLength
= size
; }
111 template <class BlobType
>
112 bool is() const { return magic() == BlobType::typeMagic
; }
114 static BlobCore
*readBlob(std::FILE *file
) { return readBlob(file
, 0, 0, 0); }
115 static BlobCore
*readBlob(int fd
) { return readBlob(fd
, 0, 0, 0); }
118 static BlobCore
*readBlob(std::FILE *file
, uint32_t magic
, size_t minSize
, size_t maxSize
); // streaming
119 static BlobCore
*readBlob(int fd
, uint32_t magic
, size_t minSize
, size_t maxSize
); // streaming
120 static BlobCore
*readBlob(int fd
, size_t offset
, uint32_t magic
, size_t minSize
, size_t maxSize
); // pread(2)@offset
123 Endian
<uint32_t> mMagic
;
124 Endian
<uint32_t> mLength
;
128 // basic validation helper
129 inline bool BlobCore::validateBlob(Magic mag
, size_t minSize
/* = 0 */, size_t maxSize
/* = 0 */) const
131 uint32_t len
= this->mLength
;
132 if (mag
&& (mag
!= this->mMagic
)) {
136 if (minSize
? (len
< minSize
) : (len
< sizeof(BlobCore
))) {
140 if (maxSize
&& len
> maxSize
) {
149 // Typed Blobs (BlobCores that know their real type and magic)
151 template <class BlobType
, uint32_t _magic
>
152 class Blob
: public BlobCore
{
154 void initialize(size_t size
= 0) { BlobCore::initialize(_magic
, size
); }
156 static const Magic typeMagic
= _magic
;
158 bool validateBlob() const
159 { return BlobCore::validateBlob(_magic
, sizeof(BlobType
)); }
161 bool validateBlob(size_t extLength
) const
162 { return validateBlob() && mLength
== extLength
; }
164 static BlobType
*specific(BlobCore
*blob
, bool unalloc
= false)
166 if (BlobType
*p
= static_cast<BlobType
*>(blob
)) {
167 if (p
->validateBlob())
175 static const BlobType
*specific(const BlobCore
*blob
)
177 const BlobType
*p
= static_cast<const BlobType
*>(blob
);
178 if (p
&& p
->validateBlob())
183 BlobType
*clone() const
184 { assert(validateBlob()); return specific(this->BlobCore::clone()); }
186 static BlobType
*readBlob(int fd
)
187 { return specific(BlobCore::readBlob(fd
, _magic
, sizeof(BlobType
), 0), true); }
189 static BlobType
*readBlob(int fd
, size_t offset
, size_t maxSize
= 0)
190 { return specific(BlobCore::readBlob(fd
, offset
, _magic
, sizeof(BlobType
), maxSize
), true); }
192 static BlobType
*readBlob(std::FILE *file
)
193 { return specific(BlobCore::readBlob(file
, _magic
, sizeof(BlobType
), 0), true); }
198 // A generic blob wrapped around arbitrary (flat) binary data.
199 // This can be used to "regularize" plain binary data, so it can be handled
200 // as a genuine Blob (e.g. for insertion into a SuperBlob).
202 class BlobWrapper
: public Blob
<BlobWrapper
, 0xfade0b01> {
204 static BlobWrapper
*alloc(size_t length
, Magic magic
= BlobWrapper::typeMagic
);
205 static BlobWrapper
*alloc(const void *data
, size_t length
, Magic magic
= BlobWrapper::typeMagic
);
207 unsigned char dataArea
[0];
209 // override data/length to point to the payload (only)
210 void *data() { return dataArea
; }
211 const void *data() const { return dataArea
; }
212 size_t length() const { return BlobCore::length() - sizeof(BlobCore
); }