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 // codedirectory - format and operations for code signing "code directory" structures
27 // A CodeDirectory is a contiguous binary blob containing a two-tiered
28 // hash of (much of) the contents of a real StaticCode object.
29 // It consists of a header followed by an array of hash vector elements.
31 // This structure is meant to be self-describing, binary stable, and endian independent.
33 #ifndef _H_CODEDIRECTORY
34 #define _H_CODEDIRECTORY
36 #include <security_utilities/unix++.h>
37 #include <security_utilities/blob.h>
38 #include <security_utilities/cfutilities.h>
39 #include <security_utilities/hashing.h>
43 namespace CodeSigning
{
47 // Types of hashes supported.
48 // Actually, right now, only SHA1 is really supported.
54 cdHashTypeDefault
= cdHashTypeSHA1
59 // Conventional string names for various code signature components.
60 // Depending on storage, these may end up as filenames, extended attribute names, etc.
62 #define kSecCS_CODEDIRECTORYFILE "CodeDirectory" // CodeDirectory
63 #define kSecCS_SIGNATUREFILE "CodeSignature" // CMS Signature
64 #define kSecCS_REQUIREMENTSFILE "CodeRequirements" // internal requirements
65 #define kSecCS_RESOURCEDIRFILE "CodeResources" // resource directory
66 #define kSecCS_APPLICATIONFILE "CodeApplication" // application-specific resource
70 // Special hash slot values. In a CodeDirectory, these show up at negative slot
71 // indices. This enumeration is also used widely in various internal APIs, and as
72 // type values in embedded SuperBlobs.
76 // Primary slot numbers.
77 // These values are potentially present in the CodeDirectory hash array
78 // under their negative values. They are also used in APIs and SuperBlobs.
79 // Note that zero must not be used for these (it's page 0 of the main code array),
80 // and it's good to assign contiguous (very) small values for them.
82 cdInfoSlot
= 1, // Info.plist
83 cdRequirementsSlot
= 2, // internal requirements
84 cdResourceDirSlot
= 3, // resource directory
85 cdApplicationSlot
= 4, // Application specific slot
86 // (add further primary slot numbers here)
88 cdSlotCount
, // total number of special slots (+1 for slot 0)
89 cdSlotMax
= cdSlotCount
- 1, // highest special slot number
92 // Virtual slot numbers.
93 // These values are NOT used in the CodeDirectory hash array. The are used as
94 // internal API identifiers and as types in in-image SuperBlobs.
95 // Zero is okay to use here; and we assign that to the CodeDirectory itself so
96 // it shows up first in (properly sorted) SuperBlob indices. The rest of the
97 // numbers is set Far Away so the primary slot set can expand safely.
98 // It's okay to have gaps in these assignments.
100 cdCodeDirectorySlot
= 0, // CodeDirectory
101 cdSignatureSlot
= 0x10000, // CMS signature
102 // (add further virtual slot numbers here)
107 // Special hash slot attributes.
108 // This is a central description of attributes of each slot.
109 // Various places in Code Signing pick up those attributes and act accordingly.
112 cdComponentPerArchitecture
= 1, // slot value differs for each Mach-O architecture
113 cdComponentIsBlob
= 2, // slot value is a Blob (need not be BlobWrapped)
118 // A CodeDirectory is a typed Blob describing the secured pieces of a program.
119 // This structure describes the common header and provides access to the variable-size
120 // elements packed after it. For help in constructing a CodeDirectory, use the nested
123 // The hashes are stored as an array of digests. The array covers the range
124 // [-nSpecialSlots .. nCodeSlots-1]. Non-negative indices denote pages of the main
125 // executable. Negative indices indicate "special" hashes, each of a different thing
126 // (see cd*Slot constants above). Special slots that are in range but not present
127 // are zeroed out. Unallocated special slots are also presumed absent; this is not
128 // an error. (Thus the range of special slots can be extended at will.)
130 // HOW TO MANAGE COMPATIBILITY:
131 // Each CodeDirectory has a format (compatibility) version. Three constants control
133 // * currentVersion is the version used for newly created CodeDirectories.
134 // * compatibilityLimit is the highest version the code will accept as compatible.
135 // Test for version < currentVersion to detect old formats that may need special
136 // handling. The current code rejects those; add backward cases to checkVersion().
137 // Break backward compatibility by rejecting versions that are unsuitable.
138 // Accept currentVersion < version <= compatibilityLimit as versions newer than
139 // those understood by this code but engineered (by newer code) to be backward
140 // compatible. Reject version > compatibilityLimit as incomprehensible gibberish.
142 // When creating a new version, increment currentVersion. When adding new fixed fields,
143 // just append them; the flex fields will shift to make room. To add new flex fields,
144 // add a fixed field containing the new field's offset and add suitable computations
145 // to the Builder to place the new data (right) before the hash array. Older code will
146 // then simply ignore your new fields on load/read.
147 // Add flag bits to the existing flags field to add features that step outside
148 // of the linear versioning stream. Leave the 'spare' fields alone unless you need
149 // something extraordinarily weird - they're meant to be the final escape when everything
151 // As you create new versions, consider moving the compatibilityLimit out to open up
152 // new room for backward compatibility.
153 // To break backward compatibility intentionally, move currentVersion beyond the
154 // old compatibilityLimit (and move compatibilityLimit further out).
156 class CodeDirectory
: public Blob
<CodeDirectory
, 0xfade0c02> {
159 Endian
<uint32_t> version
; // compatibility version
160 Endian
<uint32_t> flags
; // setup and mode flags
161 Endian
<uint32_t> hashOffset
; // offset of hash slot element at index zero
162 Endian
<uint32_t> identOffset
; // offset of identifier string
163 Endian
<uint32_t> nSpecialSlots
; // number of special hash slots
164 Endian
<uint32_t> nCodeSlots
; // number of ordinary (code) hash slots
165 Endian
<uint32_t> codeLimit
; // limit to main image signature range
166 uint8_t hashSize
; // size of each hash in bytes
167 uint8_t hashType
; // type of hash (cdHashType* constants)
168 uint8_t spare1
; // unused (must be zero)
169 uint8_t pageSize
; // log2(page size in bytes); 0 => infinite
170 Endian
<uint32_t> spare2
; // unused (must be zero)
172 // works with the version field; see comments above
173 static const uint32_t currentVersion
= 0x20001; // "version 2"
174 static const uint32_t compatibilityLimit
= 0x2F000; // "version 3 with wiggle room"
176 void checkVersion() const; // throws if not compatible with this code
178 typedef int Slot
; // slot index (negative for special slots)
179 typedef unsigned int SpecialSlot
; // positive special slot index (not for code slots)
181 const char *identifier() const { return at
<const char>(identOffset
); }
182 char *identifier() { return at
<char>(identOffset
); }
184 unsigned char *operator [] (Slot slot
)
186 assert(slot
>= int(-nSpecialSlots
) && slot
< int(nCodeSlots
));
187 return at
<unsigned char>(hashOffset
) + hashSize
* slot
;
190 const unsigned char *operator [] (Slot slot
) const
192 assert(slot
>= int(-nSpecialSlots
) && slot
< int(nCodeSlots
));
193 return at
<unsigned char>(hashOffset
) + hashSize
* slot
;
196 bool validateSlot(const void *data
, size_t size
, Slot slot
) const;
197 bool validateSlot(UnixPlusPlus::FileDesc fd
, size_t size
, Slot slot
) const;
198 bool slotIsPresent(Slot slot
) const;
203 static size_t hash(UnixPlusPlus::FileDesc fd
, Hash::Byte
*digest
, size_t limit
= 0);
204 static size_t hash(const void *data
, size_t length
, Hash::Byte
*digest
);
208 // Information about SpecialSlots
210 static const char *canonicalSlotName(SpecialSlot slot
);
211 static unsigned slotAttributes(SpecialSlot slot
);
212 IFDEBUG(static const char * const debugSlotName
[]);
216 // Canonical text forms for (only) the user-settable flags
223 static const FlagItem flagItems
[]; // terminated with NULL item
225 static uint32_t textFlags(std::string text
);
233 #endif //_H_CODEDIRECTORY