2 * Copyright (c) 2006-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@
25 // codedirectory - format and operations for code signing "code directory" structures
27 // A CodeDirectory is the top level object describing a particular instance
28 // of (static) code. It contains hashes of other objects that further describe
29 // parts of that code; these hashes hold the various pieces together.
31 // This means that if you reliably ascertain the contents of a CodeDirectory,
32 // you can verify the integrity of the entire code object it represents - the
33 // CodeDirectory can stand as a proxy for that code.
35 // Code signatures usually use CMS to sign the CodeDirectory to form full
36 // signature blobs; ad-hoc signatures simply record the interior hash of the
37 // CodeDirectory directly. The interior hash of the CodeDirectory is also widely
38 // used as concordance for a particular code instance - in essence, for
39 // different processes (or a process and the kernel) to "compare notes"
40 // to make sure they refer to the same code.
42 #ifndef _H_CODEDIRECTORY
43 #define _H_CODEDIRECTORY
45 #include <security_utilities/unix++.h>
46 #include <security_utilities/blob.h>
47 #include <security_utilities/cfutilities.h>
48 #include <security_utilities/hashing.h>
49 #include <Security/CSCommonPriv.h>
54 namespace CodeSigning
{
58 // Conventional string names for various code signature components.
59 // Depending on storage, these may end up as filenames, extended attribute names, etc.
61 #define kSecCS_CODEDIRECTORYFILE "CodeDirectory" // CodeDirectory
62 #define kSecCS_SIGNATUREFILE "CodeSignature" // CMS Signature
63 #define kSecCS_REQUIREMENTSFILE "CodeRequirements" // internal requirements
64 #define kSecCS_RESOURCEDIRFILE "CodeResources" // resource directory
65 #define kSecCS_ENTITLEMENTFILE "CodeEntitlements" // entitlement configuration
66 #define kSecCS_REPSPECIFICFILE "CodeRepSpecific" // DiskRep-specific use slot
67 #define kSecCS_TOPDIRECTORYFILE "CodeTopDirectory" // Top-level directory list
68 #define kSecCS_ENTITLEMENTDERFILE "CodeEntitlementDER" // DER entitlement representation
71 // Special hash slot values. In a CodeDirectory, these show up at negative slot
72 // indices. This enumeration is also used widely in various internal APIs, and as
73 // type values in embedded SuperBlobs.
75 // How to add a new special slot type:
76 // 1. Add the new name at the end of the primary or virtual slot array (below).
77 // 2a. For slots representing existing code pieces, follow the ball for cdInfoSlot.
78 // 2b. For slots representing global signature components, follow the ball for cdResourceDirSlot.
79 // 2c. For slots representing per-architecture signature components, follow the ball for cdEntitlementSlot.
80 // ("Follow the ball" -> Global search for that name and do likewise.)
84 // Primary slot numbers.
85 // These values are potentially present in the CodeDirectory hash array
86 // under their negative values. They are also used in APIs and SuperBlobs.
87 // Note that zero must not be used for these (it's page 0 of the main code array),
88 // and it is important to assign contiguous (very) small values for them.
90 cdInfoSlot
= 1, // Info.plist
91 cdRequirementsSlot
= 2, // internal requirements
92 cdResourceDirSlot
= 3, // resource directory
93 cdTopDirectorySlot
= 4, // Application specific slot
94 cdEntitlementSlot
= 5, // embedded entitlement configuration
95 cdRepSpecificSlot
= 6, // for use by disk rep
96 cdEntitlementDERSlot
= 7, // DER representation of entitlements
97 // (add further primary slot numbers here)
99 cdSlotCount
, // total number of special slots (+1 for slot 0)
100 cdSlotMax
= cdSlotCount
- 1, // highest special slot number (as a positive number)
103 // Virtual slot numbers.
104 // These values are NOT used in the CodeDirectory hash array. They are used as
105 // internal API identifiers and as types in SuperBlobs.
106 // Zero is okay to use here; and we assign that to the CodeDirectory itself so
107 // it shows up first in (properly sorted) SuperBlob indices. The rest of the
108 // numbers is set Far Away so the primary slot set can expand safely.
109 // It's okay to have large gaps in these assignments.
111 cdCodeDirectorySlot
= 0, // CodeDirectory
112 cdAlternateCodeDirectorySlots
= 0x1000, // alternate CodeDirectory array
113 cdAlternateCodeDirectoryLimit
= 0x1005, // 5+1 hashes should be enough for everyone...
114 cdSignatureSlot
= 0x10000, // CMS signature
115 cdIdentificationSlot
, // identification blob (detached signatures only)
116 cdTicketSlot
, // ticket embedded in signature (DMG only)
117 // (add further virtual slot numbers here)
122 // Special hash slot attributes.
123 // This is a central description of attributes of each slot.
124 // Various places in Code Signing pick up those attributes and act accordingly.
127 cdComponentPerArchitecture
= 1, // slot value differs for each Mach-O architecture
128 cdComponentIsBlob
= 2, // slot value is a Blob (need not be BlobWrapped)
133 // A signature with a nonzero platform identifier value, when endorsed as originated by Apple,
134 // identifies code as belonging to a particular operating system deliverable set. Some system
135 // components restrict functionality to platform binaries. The actual values are arbitrary.
137 typedef uint8_t PlatformIdentifier
;
138 static const PlatformIdentifier noPlatform
= 0;
139 static const unsigned int maxPlatform
= 255; // stored in a uint8_t
143 // A CodeDirectory is a typed Blob describing the secured pieces of a program.
144 // This structure describes the common header and provides access to the variable-size
145 // elements packed after it. For help in constructing a CodeDirectory, use the nested
148 // At the heart of a CodeDirectory lies a packed array of hash digests.
149 // The array's zero-index element is at offset hashOffset, and the array covers
150 // elements in the range [-nSpecialSlots .. nCodeSlots-1]. Non-negative indices
151 // denote pages of the main executable. Negative indices indicate "special" hashes,
152 // each of a different thing (see cd*Slot constants above).
153 // Special slots that are in range but not present are zeroed out. Unallocated special
154 // slots are also presumed absent; this is not an error. (Thus the range of special
155 // slots can be extended at will.)
157 // HOW TO MANAGE COMPATIBILITY:
158 // Each CodeDirectory has a format (compatibility) version. Two constants control
160 // * currentVersion is the version used for newly created CodeDirectories.
161 // * compatibilityLimit is the highest version the code will accept as compatible.
162 // Test for version < currentVersion to detect old formats that may need special
163 // handling; this is done in checkIntegrity(). The current code rejects versions
164 // below earliestVersion.
165 // Break backward compatibility by rejecting versions that are unsuitable.
166 // Accept currentVersion < version <= compatibilityLimit as versions newer than
167 // those understood by this code but engineered (by newer code) to be backward
168 // compatible. Reject version > compatibilityLimit as incomprehensible gibberish.
170 // When creating a new version, increment currentVersion. When adding new fixed fields,
171 // just append them; the flex fields will shift to make room. To add new flex fields,
172 // add a fixed field containing the new field's offset and add suitable computations
173 // to the Builder to place the new data (right) before the hash array. Remember to check
174 // for offset in-range in checkIntegrity(). Older code will then simply ignore your
175 // new fields on load/read.
176 // Add flag bits to the existing flags field to add features that step outside
177 // of the linear versioning stream. Leave the 'spare' fields alone unless you need
178 // something extraordinarily weird - they're meant to be the final escape when everything
180 // As you create new versions, consider moving the compatibilityLimit out to open up
181 // new room for backward compatibility.
182 // To break backward compatibility intentionally, move currentVersion beyond the
183 // old compatibilityLimit (and move compatibilityLimit further out).
185 class CodeDirectory
: public Blob
<CodeDirectory
, kSecCodeMagicCodeDirectory
> {
187 Endian
<uint32_t> version
; // compatibility version
188 Endian
<uint32_t> flags
; // setup and mode flags
189 Endian
<uint32_t> hashOffset
; // offset of hash slot element at index zero
190 Endian
<uint32_t> identOffset
; // offset of identifier string
191 Endian
<uint32_t> nSpecialSlots
; // number of special hash slots
192 Endian
<uint32_t> nCodeSlots
; // number of ordinary (code) hash slots
193 Endian
<uint32_t> codeLimit
; // limit to main image signature range
194 uint8_t hashSize
; // size of each hash digest (bytes)
195 uint8_t hashType
; // type of hash (kSecCodeSignatureHash* constants)
196 uint8_t platform
; // platform identifier; zero if not platform binary
197 uint8_t pageSize
; // log2(page size in bytes); 0 => infinite
198 Endian
<uint32_t> spare2
; // unused (must be zero)
199 Endian
<uint32_t> scatterOffset
; // offset of optional scatter vector (zero if absent)
200 Endian
<uint32_t> teamIDOffset
; // offset of optional teamID string
201 Endian
<uint32_t> spare3
; // unused (most be zero)
202 Endian
<uint64_t> codeLimit64
; // limit to main image signature range, 64 bits
203 Endian
<uint64_t> execSegBase
; // offset of executable segment
204 Endian
<uint64_t> execSegLimit
; // limit of executable segment
205 Endian
<uint64_t> execSegFlags
; // exec segment flags
207 Endian
<uint32_t> runtime
; // Runtime version encoded as an unsigned int
208 Endian
<uint32_t> preEncryptOffset
; // offset of pre-encrypt hash slots
210 // works with the version field; see comments above
211 static const uint32_t currentVersion
= 0x20500; // "version 2.5"
212 static const uint32_t compatibilityLimit
= 0x2F000; // "version 3 with wiggle room"
214 static const uint32_t earliestVersion
= 0x20001; // earliest supported version
215 static const uint32_t supportsScatter
= 0x20100; // first version to support scatter option
216 static const uint32_t supportsTeamID
= 0x20200; // first version to support team ID option
217 static const uint32_t supportsCodeLimit64
= 0x20300; // first version to support codeLimit64
218 static const uint32_t supportsExecSegment
= 0x20400; // first version to support exec base and limit
219 static const uint32_t supportsPreEncrypt
= 0x20500; // first version to support pre-encrypt hashes and runtime version
221 void checkIntegrity() const; // throws if inconsistent or unsupported version
223 typedef uint32_t HashAlgorithm
; // types of internal glue hashes
224 typedef std::set
<HashAlgorithm
> HashAlgorithms
;
225 typedef int Slot
; // slot index (negative for special slots)
226 typedef unsigned int SpecialSlot
; // positive special slot index (not for code slots)
228 const char *identifier() const { return at
<const char>(identOffset
); }
229 char *identifier() { return at
<char>(identOffset
); }
231 size_t signingLimit() const
232 { return (version
>= supportsCodeLimit64
&& codeLimit64
) ? size_t(codeLimit64
) : size_t(codeLimit
); }
234 // main hash array access
235 SpecialSlot
maxSpecialSlot() const;
237 unsigned char *getSlotMutable (Slot slot
, bool preEncrypt
)
239 assert(slot
>= int(-nSpecialSlots
) && slot
< int(nCodeSlots
));
242 if (version
>= supportsPreEncrypt
&& preEncryptOffset
!= 0) {
244 return at
<unsigned char>(preEncryptOffset
) + hashSize
* slot
;
249 return at
<unsigned char>(hashOffset
) + hashSize
* slot
;
253 const unsigned char *getSlot (Slot slot
, bool preEncrypt
) const
255 CodeDirectory
*cd
= const_cast<CodeDirectory
*>(this);
256 return const_cast<const unsigned char *>(cd
->getSlotMutable(slot
, preEncrypt
));
260 // The main page hash array can be "scattered" across the code file
261 // by specifying an array of Scatter elements, terminated with an
262 // element whose count field is zero.
263 // The scatter vector is optional; if absent, the hash array covers
264 // a single contiguous range of pages. CodeDirectory versions below
265 // supportsScatter never have scatter vectors (they lack the scatterOffset field).
268 Endian
<uint32_t> count
; // number of pages; zero for sentinel (only)
269 Endian
<uint32_t> base
; // first page number
270 Endian
<uint64_t> targetOffset
; // byte offset in target
271 Endian
<uint64_t> spare
; // reserved (must be zero)
273 Scatter
*scatterVector() // first scatter vector element (NULL if none)
274 { return (version
>= supportsScatter
&& scatterOffset
) ? at
<Scatter
>(scatterOffset
) : NULL
; }
275 const Scatter
*scatterVector() const
276 { return (version
>= supportsScatter
&& scatterOffset
) ? at
<const Scatter
>(scatterOffset
) : NULL
; }
278 const char *teamID() const { return version
>= supportsTeamID
&& teamIDOffset
? at
<const char>(teamIDOffset
) : NULL
; }
279 char *teamID() { return version
>= supportsTeamID
&& teamIDOffset
? at
<char>(teamIDOffset
) : NULL
; }
281 uint64_t execSegmentBase() const { return (version
>= supportsExecSegment
) ? execSegBase
.get() : 0; }
282 uint64_t execSegmentLimit() const { return (version
>= supportsExecSegment
) ? execSegLimit
.get() : 0; }
283 uint64_t execSegmentFlags() const { return (version
>= supportsExecSegment
) ? execSegFlags
.get() : 0; }
285 const unsigned char *preEncryptHashes() const { return getSlot(0, true); }
287 uint32_t runtimeVersion() const {return (version
>= supportsPreEncrypt
) ? runtime
.get() : 0; }
290 bool validateSlot(const void *data
, size_t size
, Slot slot
, bool preEncrypted
) const; // validate memory buffer against page slot
291 bool validateSlot(UnixPlusPlus::FileDesc fd
, size_t size
, Slot slot
, bool preEncrypted
) const; // read and validate file
292 bool slotIsPresent(Slot slot
) const;
297 static DynamicHash
*hashFor(HashAlgorithm hashType
); // create a DynamicHash subclass for (hashType) digests
298 DynamicHash
*getHash() const { return hashFor(this->hashType
); } // make one for me
299 CFDataRef
cdhash(bool truncate
= true) const;
301 static void multipleHashFileData(UnixPlusPlus::FileDesc fd
, size_t limit
, HashAlgorithms types
, void (^action
)(HashAlgorithm type
, DynamicHash
* hasher
));
302 bool verifyMemoryContent(CFDataRef data
, const Byte
* digest
) const;
304 static bool viableHash(HashAlgorithm type
);
305 static HashAlgorithm
bestHashOf(const HashAlgorithms
& types
);
307 std::string
hexHash(const unsigned char *hash
) const; // encode any canonical-type hash as a hex string
310 static size_t generateHash(DynamicHash
*hash
, UnixPlusPlus::FileDesc fd
, Hashing::Byte
*digest
, size_t limit
= 0); // hash to count or end of file
311 static size_t generateHash(DynamicHash
*hash
, const void *data
, size_t length
, Hashing::Byte
*digest
); // hash data buffer
315 // Information about SpecialSlots.
316 // This specifies meta-data about slots themselves;
317 // it does not work with the contents of hash slots.
319 static const char *canonicalSlotName(SpecialSlot slot
);
320 static unsigned slotAttributes(SpecialSlot slot
);
321 IFDEBUG(static const char * const debugSlotName
[]);
325 // Canonical screening code. Requires a fully formed CodeDirectory.
327 std::string
screeningCode() const;
335 #endif //_H_CODEDIRECTORY