]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_codesigning/lib/codedirectory.h
Security-58286.41.2.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / codedirectory.h
CommitLineData
b1ab9ed8 1/*
d8f41ccd 2 * Copyright (c) 2006-2012,2014 Apple Inc. All Rights Reserved.
b1ab9ed8
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24//
25// codedirectory - format and operations for code signing "code directory" structures
26//
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.
30//
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.
34//
35// Code signatures usually use CMS to sign the CodeDirectory to form full
5c19dc3a
A
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
b1ab9ed8
A
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.
41//
42#ifndef _H_CODEDIRECTORY
43#define _H_CODEDIRECTORY
44
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>
e3d460c9 50#include <set>
b1ab9ed8
A
51
52
53namespace Security {
54namespace CodeSigning {
55
56
57//
58// Conventional string names for various code signature components.
59// Depending on storage, these may end up as filenames, extended attribute names, etc.
60//
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
b1ab9ed8 65#define kSecCS_ENTITLEMENTFILE "CodeEntitlements" // entitlement configuration
e3d460c9
A
66#define kSecCS_REPSPECIFICFILE "CodeRepSpecific" // DiskRep-specific use slot
67#define kSecCS_TOPDIRECTORYFILE "CodeTopDirectory" // Top-level directory list
b1ab9ed8
A
68
69
70//
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.
74//
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.)
81//
82enum {
83 //
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.
89 //
90 cdInfoSlot = 1, // Info.plist
91 cdRequirementsSlot = 2, // internal requirements
92 cdResourceDirSlot = 3, // resource directory
e3d460c9 93 cdTopDirectorySlot = 4, // Application specific slot
b1ab9ed8 94 cdEntitlementSlot = 5, // embedded entitlement configuration
e3d460c9 95 cdRepSpecificSlot = 6, // for use by disk rep
b1ab9ed8
A
96 // (add further primary slot numbers here)
97
98 cdSlotCount, // total number of special slots (+1 for slot 0)
99 cdSlotMax = cdSlotCount - 1, // highest special slot number (as a positive number)
100
101 //
102 // Virtual slot numbers.
103 // These values are NOT used in the CodeDirectory hash array. They are used as
104 // internal API identifiers and as types in SuperBlobs.
105 // Zero is okay to use here; and we assign that to the CodeDirectory itself so
106 // it shows up first in (properly sorted) SuperBlob indices. The rest of the
107 // numbers is set Far Away so the primary slot set can expand safely.
108 // It's okay to have large gaps in these assignments.
109 //
110 cdCodeDirectorySlot = 0, // CodeDirectory
e3d460c9
A
111 cdAlternateCodeDirectorySlots = 0x1000, // alternate CodeDirectory array
112 cdAlternateCodeDirectoryLimit = 0x1005, // 5+1 hashes should be enough for everyone...
b1ab9ed8 113 cdSignatureSlot = 0x10000, // CMS signature
e3d460c9 114 cdIdentificationSlot, // identification blob (detached signatures only)
b1ab9ed8
A
115 // (add further virtual slot numbers here)
116};
117
118
119//
120// Special hash slot attributes.
121// This is a central description of attributes of each slot.
122// Various places in Code Signing pick up those attributes and act accordingly.
123//
124enum {
125 cdComponentPerArchitecture = 1, // slot value differs for each Mach-O architecture
126 cdComponentIsBlob = 2, // slot value is a Blob (need not be BlobWrapped)
127};
5c19dc3a
A
128
129
130//
131// A signature with a nonzero platform identifier value, when endorsed as originated by Apple,
132// identifies code as belonging to a particular operating system deliverable set. Some system
133// components restrict functionality to platform binaries. The actual values are arbitrary.
134//
135typedef uint8_t PlatformIdentifier;
136static const PlatformIdentifier noPlatform = 0;
137static const unsigned int maxPlatform = 255; // stored in a uint8_t
b1ab9ed8
A
138
139
140//
141// A CodeDirectory is a typed Blob describing the secured pieces of a program.
142// This structure describes the common header and provides access to the variable-size
143// elements packed after it. For help in constructing a CodeDirectory, use the nested
144// Builder class.
145//
146// At the heart of a CodeDirectory lies a packed array of hash digests.
147// The array's zero-index element is at offset hashOffset, and the array covers
148// elements in the range [-nSpecialSlots .. nCodeSlots-1]. Non-negative indices
149// denote pages of the main executable. Negative indices indicate "special" hashes,
150// each of a different thing (see cd*Slot constants above).
151// Special slots that are in range but not present are zeroed out. Unallocated special
152// slots are also presumed absent; this is not an error. (Thus the range of special
153// slots can be extended at will.)
154//
155// HOW TO MANAGE COMPATIBILITY:
156// Each CodeDirectory has a format (compatibility) version. Two constants control
157// versioning:
158// * currentVersion is the version used for newly created CodeDirectories.
159// * compatibilityLimit is the highest version the code will accept as compatible.
160// Test for version < currentVersion to detect old formats that may need special
161// handling; this is done in checkIntegrity(). The current code rejects versions
162// below earliestVersion.
163// Break backward compatibility by rejecting versions that are unsuitable.
164// Accept currentVersion < version <= compatibilityLimit as versions newer than
165// those understood by this code but engineered (by newer code) to be backward
166// compatible. Reject version > compatibilityLimit as incomprehensible gibberish.
167//
168// When creating a new version, increment currentVersion. When adding new fixed fields,
169// just append them; the flex fields will shift to make room. To add new flex fields,
170// add a fixed field containing the new field's offset and add suitable computations
171// to the Builder to place the new data (right) before the hash array. Remember to check
172// for offset in-range in checkIntegrity(). Older code will then simply ignore your
173// new fields on load/read.
174// Add flag bits to the existing flags field to add features that step outside
175// of the linear versioning stream. Leave the 'spare' fields alone unless you need
176// something extraordinarily weird - they're meant to be the final escape when everything
177// else fails.
178// As you create new versions, consider moving the compatibilityLimit out to open up
179// new room for backward compatibility.
180// To break backward compatibility intentionally, move currentVersion beyond the
181// old compatibilityLimit (and move compatibilityLimit further out).
182//
183class CodeDirectory: public Blob<CodeDirectory, kSecCodeMagicCodeDirectory> {
184public:
185 Endian<uint32_t> version; // compatibility version
186 Endian<uint32_t> flags; // setup and mode flags
187 Endian<uint32_t> hashOffset; // offset of hash slot element at index zero
188 Endian<uint32_t> identOffset; // offset of identifier string
189 Endian<uint32_t> nSpecialSlots; // number of special hash slots
190 Endian<uint32_t> nCodeSlots; // number of ordinary (code) hash slots
191 Endian<uint32_t> codeLimit; // limit to main image signature range
192 uint8_t hashSize; // size of each hash digest (bytes)
193 uint8_t hashType; // type of hash (kSecCodeSignatureHash* constants)
5c19dc3a 194 uint8_t platform; // platform identifier; zero if not platform binary
b1ab9ed8
A
195 uint8_t pageSize; // log2(page size in bytes); 0 => infinite
196 Endian<uint32_t> spare2; // unused (must be zero)
197 Endian<uint32_t> scatterOffset; // offset of optional scatter vector (zero if absent)
420ff9d9 198 Endian<uint32_t> teamIDOffset; // offset of optional teamID string
e3d460c9
A
199 Endian<uint32_t> spare3; // unused (most be zero)
200 Endian<uint64_t> codeLimit64; // limit to main image signature range, 64 bits
866f8763
A
201 Endian<uint64_t> execSegBase; // offset of executable segment
202 Endian<uint64_t> execSegLimit; // limit of executable segment
203 Endian<uint64_t> execSegFlags; // exec segment flags
204
b1ab9ed8 205 // works with the version field; see comments above
866f8763 206 static const uint32_t currentVersion = 0x20400; // "version 2.4"
b1ab9ed8
A
207 static const uint32_t compatibilityLimit = 0x2F000; // "version 3 with wiggle room"
208
209 static const uint32_t earliestVersion = 0x20001; // earliest supported version
210 static const uint32_t supportsScatter = 0x20100; // first version to support scatter option
e3d460c9
A
211 static const uint32_t supportsTeamID = 0x20200; // first version to support team ID option
212 static const uint32_t supportsCodeLimit64 = 0x20300; // first version to support codeLimit64
866f8763
A
213 static const uint32_t supportsExecSegment = 0x20400; // first version to support exec base and limit
214
b1ab9ed8
A
215 void checkIntegrity() const; // throws if inconsistent or unsupported version
216
217 typedef uint32_t HashAlgorithm; // types of internal glue hashes
e3d460c9 218 typedef std::set<HashAlgorithm> HashAlgorithms;
b1ab9ed8
A
219 typedef int Slot; // slot index (negative for special slots)
220 typedef unsigned int SpecialSlot; // positive special slot index (not for code slots)
221
222 const char *identifier() const { return at<const char>(identOffset); }
223 char *identifier() { return at<char>(identOffset); }
e3d460c9
A
224
225 size_t signingLimit() const
226 { return (version >= supportsCodeLimit64 && codeLimit64) ? size_t(codeLimit64) : size_t(codeLimit); }
420ff9d9 227
b1ab9ed8
A
228 // main hash array access
229 SpecialSlot maxSpecialSlot() const;
230
231 unsigned char *operator [] (Slot slot)
232 {
233 assert(slot >= int(-nSpecialSlots) && slot < int(nCodeSlots));
234 return at<unsigned char>(hashOffset) + hashSize * slot;
235 }
236
237 const unsigned char *operator [] (Slot slot) const
238 {
239 assert(slot >= int(-nSpecialSlots) && slot < int(nCodeSlots));
240 return at<unsigned char>(hashOffset) + hashSize * slot;
241 }
242
243 //
244 // The main page hash array can be "scattered" across the code file
245 // by specifying an array of Scatter elements, terminated with an
246 // element whose count field is zero.
247 // The scatter vector is optional; if absent, the hash array covers
248 // a single contiguous range of pages. CodeDirectory versions below
249 // supportsScatter never have scatter vectors (they lack the scatterOffset field).
250 //
251 struct Scatter {
252 Endian<uint32_t> count; // number of pages; zero for sentinel (only)
253 Endian<uint32_t> base; // first page number
254 Endian<uint64_t> targetOffset; // byte offset in target
255 Endian<uint64_t> spare; // reserved (must be zero)
256 };
257 Scatter *scatterVector() // first scatter vector element (NULL if none)
258 { return (version >= supportsScatter && scatterOffset) ? at<Scatter>(scatterOffset) : NULL; }
259 const Scatter *scatterVector() const
260 { return (version >= supportsScatter && scatterOffset) ? at<const Scatter>(scatterOffset) : NULL; }
420ff9d9
A
261
262 const char *teamID() const { return version >= supportsTeamID && teamIDOffset ? at<const char>(teamIDOffset) : NULL; }
263 char *teamID() { return version >= supportsTeamID && teamIDOffset ? at<char>(teamIDOffset) : NULL; }
866f8763
A
264
265 uint64_t execSegmentBase() const { return (version >= supportsExecSegment) ? execSegBase.get() : 0; }
266 uint64_t execSegmentLimit() const { return (version >= supportsExecSegment) ? execSegLimit.get() : 0; }
267 uint64_t execSegmentFlags() const { return (version >= supportsExecSegment) ? execSegFlags.get() : 0; }
268
b1ab9ed8
A
269public:
270 bool validateSlot(const void *data, size_t size, Slot slot) const; // validate memory buffer against page slot
271 bool validateSlot(UnixPlusPlus::FileDesc fd, size_t size, Slot slot) const; // read and validate file
272 bool slotIsPresent(Slot slot) const;
273
274 class Builder;
275
276public:
277 static DynamicHash *hashFor(HashAlgorithm hashType); // create a DynamicHash subclass for (hashType) digests
278 DynamicHash *getHash() const { return hashFor(this->hashType); } // make one for me
5c19dc3a 279 CFDataRef cdhash() const;
e3d460c9
A
280
281 static void multipleHashFileData(UnixPlusPlus::FileDesc fd, size_t limit, HashAlgorithms types, void (^action)(HashAlgorithm type, DynamicHash* hasher));
fa7225c8
A
282 bool verifyMemoryContent(CFDataRef data, const Byte* digest) const;
283
e3d460c9
A
284 static bool viableHash(HashAlgorithm type);
285 static HashAlgorithm bestHashOf(const HashAlgorithms& types);
313fa17b
A
286
287 std::string hexHash(const unsigned char *hash) const; // encode any canonical-type hash as a hex string
b1ab9ed8
A
288
289protected:
290 static size_t generateHash(DynamicHash *hash, UnixPlusPlus::FileDesc fd, Hashing::Byte *digest, size_t limit = 0); // hash to count or end of file
291 static size_t generateHash(DynamicHash *hash, const void *data, size_t length, Hashing::Byte *digest); // hash data buffer
292
293public:
294 //
295 // Information about SpecialSlots.
296 // This specifies meta-data about slots themselves;
297 // it does not work with the contents of hash slots.
298 //
299 static const char *canonicalSlotName(SpecialSlot slot);
300 static unsigned slotAttributes(SpecialSlot slot);
301 IFDEBUG(static const char * const debugSlotName[]);
313fa17b
A
302
303public:
304 //
305 // Canonical screening code. Requires a fully formed CodeDirectory.
306 //
307 std::string screeningCode() const;
b1ab9ed8
A
308};
309
310
311} // CodeSigning
312} // Security
313
314
315#endif //_H_CODEDIRECTORY