]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/lib/diskrep.h
Security-58286.260.20.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / diskrep.h
1 /*
2 * Copyright (c) 2006-2007,2011-2012,2014 Apple Inc. All Rights Reserved.
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 // diskrep - disk representations of code
26 //
27 #ifndef _H_DISKREP
28 #define _H_DISKREP
29
30 #include "cs.h"
31 #include "codedirectory.h"
32 #include "cdbuilder.h"
33 #include "requirement.h"
34 #include "resources.h"
35 #include <security_utilities/macho++.h> // for class Architecture
36 #include <security_utilities/refcount.h>
37 #include <security_utilities/superblob.h>
38 #include <CoreFoundation/CFData.h>
39
40 namespace Security {
41 namespace CodeSigning {
42
43 class ResourceBuilder;
44 class SecCodeSigner;
45
46
47 //
48 // DiskRep is an abstract interface to code somewhere located by
49 // a file system path. It presents the ability to read and write
50 // Code Signing-related information about such code without exposing
51 // the details of the storage locations or formats.
52 //
53 class DiskRep : public RefCount {
54 public:
55 class SigningContext;
56
57 typedef std::set<OSStatus> ToleratedErrors;
58
59 public:
60 DiskRep();
61 virtual ~DiskRep();
62 virtual DiskRep *base();
63 virtual CFDataRef component(CodeDirectory::SpecialSlot slot) = 0; // fetch component
64 virtual CFDataRef identification() = 0; // binary lookup identifier
65 virtual std::string mainExecutablePath() = 0; // path to main executable
66 virtual CFURLRef copyCanonicalPath() = 0; // path to whole code
67 virtual std::string resourcesRootPath(); // resource directory if any [none]
68 virtual void adjustResources(ResourceBuilder &builder); // adjust resource rule set [no change]
69 virtual void prepareForSigning(SigningContext& context); // pre-adjust signing defaults before argument preparation [none]
70 virtual Universal *mainExecutableImage(); // Mach-O image if Mach-O based [null]
71 virtual size_t signingBase(); // start offset of signed area in main executable [zero]
72 virtual size_t signingLimit() = 0; // size of signed area in main executable
73
74 // The executable segment, if present, denotes which part of the image can be mapped
75 // into a virtual address space as executable. Not all platforms check this.
76 virtual size_t execSegBase(const Architecture *arch); // start offset of executable segment in main executable [zero]
77 virtual size_t execSegLimit(const Architecture *arch) = 0; // size of executable segment in main executable
78
79 virtual std::string format() = 0; // human-readable type string
80 virtual CFArrayRef modifiedFiles(); // list of files modified by signing [main execcutable only]
81 virtual UnixPlusPlus::FileDesc &fd() = 0; // a cached file descriptor for main executable file
82 virtual void flush(); // flush caches (refetch as needed)
83 virtual CFDictionaryRef diskRepInformation(); // information from diskrep
84
85 virtual void registerStapledTicket();
86
87 // default values for signing operations
88 virtual std::string recommendedIdentifier(const SigningContext &ctx) = 0; // default identifier
89 virtual CFDictionaryRef defaultResourceRules(const SigningContext &ctx); // default resource rules [none]
90 virtual const Requirements *defaultRequirements(const Architecture *arch,
91 const SigningContext &ctx); // default internal requirements [none]
92 virtual size_t pageSize(const SigningContext &ctx); // default main executable page size [infinite, i.e. no paging]
93
94 virtual void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags); // perform strict validation
95 virtual CFArrayRef allowedResourceOmissions(); // allowed (default) resource omission rules
96
97 virtual bool appleInternalForcePlatform() const {return false;};
98
99 bool mainExecutableIsMachO() { return mainExecutableImage() != NULL; }
100
101 // shorthands
102 CFDataRef signature() { return component(cdSignatureSlot); }
103
104 public:
105 class Writer;
106 virtual Writer *writer(); // Writer factory
107
108 public:
109 // optional information that might be used to create a suitable DiskRep. All optional
110 struct Context {
111 Context() : arch(Architecture::none), version(NULL), offset(0), fileOnly(false), inMemory(NULL), size(0) { }
112 Architecture arch; // explicit architecture (choose amongst universal variants)
113 const char *version; // bundle version (string)
114 off_t offset; // explicit file offset
115 bool fileOnly; // only consider single-file representations (no bundles etc.)
116 const void *inMemory; // consider using in-memory copy at this address
117 size_t size; // size of this mach-o slice
118 };
119
120 static DiskRep *bestGuess(const char *path, const Context *ctx = NULL); // canonical heuristic, any path
121 static DiskRep *bestFileGuess(const char *path, const Context *ctx = NULL); // ctx (if any) + fileOnly
122 static DiskRep *bestGuess(const char *path, size_t archOffset); // Mach-O at given file offset only
123
124 // versions using std::string paths (merely a convenience)
125 static DiskRep *bestGuess(const std::string &path, const Context *ctx = NULL)
126 { return bestGuess(path.c_str(), ctx); }
127 static DiskRep *bestGuess(const std::string &path, size_t archOffset) { return bestGuess(path.c_str(), archOffset); }
128 static DiskRep *bestFileGuess(const std::string &path, const Context *ctx = NULL) { return bestFileGuess(path.c_str(), ctx); }
129
130 public:
131 // see DiskRep::Writer docs for why this is here
132 class SigningContext {
133 protected:
134 SigningContext() { }
135
136 public:
137 virtual std::string sdkPath(const std::string &path) const = 0;
138 virtual bool isAdhoc() const = 0;
139 virtual SecCSFlags signingFlags() const = 0;
140
141 virtual const CodeDirectory::HashAlgorithms &digestAlgorithms() const = 0;
142 virtual void setDigestAlgorithms(CodeDirectory::HashAlgorithms types) = 0;
143
144 void setDigestAlgorithm(CodeDirectory::HashAlgorithm type)
145 {
146 CodeDirectory::HashAlgorithms types;
147 types.insert(type);
148 setDigestAlgorithms(types);
149 }
150 };
151
152 protected:
153 // canonically derive a suggested signing identifier from some string
154 static std::string canonicalIdentifier(const std::string &name);
155
156 public:
157 static const size_t segmentedPageSize = 4096; // default page size for system-paged signatures
158 static const size_t monolithicPageSize = 0; // default page size for non-Mach-O executables
159 };
160
161 /*
162 * Editable Disk Reps allow editing of their existing code signature.
163 * Specifically, they allow for individual components to be replaced,
164 * while preserving all other components.
165 * Lots of restrictions apply, e.g. machO signatures' superblobs may
166 * not change in size, and components covered by the code directory
167 * cannot be replaced without adjusting the code directory.
168 * Replacing or adding CMS blobs (having reserved enough size in the
169 * superblob beforehand) is the original reason this trait exists.
170 */
171 class EditableDiskRep {
172 public:
173 typedef std::map<CodeDirectory::Slot, CFCopyRef<CFDataRef>> RawComponentMap;
174
175 /* Return all components in raw form.
176 * Signature editing will add all the components obtained hereby
177 * back to their specific slots, though some of them may have
178 * been replaced in the map.
179 */
180 virtual RawComponentMap createRawComponents() = 0;
181 };
182
183 //
184 // Write-access objects.
185 // At this layer they are quite abstract, carrying just the functionality needed
186 // for the signing machinery to place data wherever it should go. Each DiskRep subclass
187 // that supports writing signing data to a place inside the code needs to implement
188 // a subclass of Writer and return an instance in the DiskRep::writer() method when asked.
189 //
190 // The Writer class is subclassed interestingly by the Mach-O multi-architecture signing code,
191 // which is handled as a special case. This means that not all Writer subclass objects were made
192 // by DiskRep::writer, and it is unwise to assume so.
193 //
194 // Note that the methods that provide defaults for signing operations are in DiskRep rather
195 // than here. That's because writers abstract data *sending*, and are virtual on management
196 // of stored data, while DiskRep is virtual on the existing code object, which is where
197 // we get our defaults from.
198 //
199 class DiskRep::Writer : public RefCount {
200 public:
201 Writer(uint32_t attrs = 0);
202 virtual ~Writer();
203 virtual void component(CodeDirectory::SpecialSlot slot, CFDataRef data) = 0;
204 virtual uint32_t attributes() const;
205 virtual void addDiscretionary(CodeDirectory::Builder &builder);
206 virtual void remove();
207 virtual void flush();
208
209 bool attribute(uint32_t attr) const { return mAttributes & attr; }
210
211 void signature(CFDataRef data) { component(cdSignatureSlot, data); }
212 void codeDirectory(const CodeDirectory *cd, CodeDirectory::SpecialSlot slot)
213 { component(slot, CFTempData(cd->data(), cd->length())); }
214
215 #if TARGET_OS_OSX
216 bool getPreserveAFSC() { return mPreserveAFSC; }
217 void setPreserveAFSC(bool flag) { mPreserveAFSC = flag; }
218 #endif
219
220 private:
221 Architecture mArch;
222 uint32_t mAttributes;
223 #if TARGET_OS_OSX
224 bool mPreserveAFSC = false; // preserve AFSC compression
225 #endif
226 };
227
228 //
229 // Writer attributes. Defaults should be off-bits.
230 //
231 enum {
232 writerLastResort = 0x0001, // prefers not to store attributes itself
233 writerNoGlobal = 0x0002, // has only per-architecture storage
234 };
235
236
237 //
238 // A prefix DiskRep that filters (only) signature-dependent behavior and passes
239 // all code-dependent behavior off to an underlying (different) DiskRep.
240 // FilterRep subclasses are typically "stacked" on top of their base DiskRep, and
241 // then used in their place.
242 //
243 class FilterRep : public DiskRep {
244 public:
245 FilterRep(DiskRep *orig) : mOriginal(orig) { }
246
247 DiskRep *base() { return mOriginal; }
248
249 // things that look at signature components are filtered
250 CFDataRef component(CodeDirectory::SpecialSlot slot) = 0;
251
252 // the rest of the virtual behavior devolves on the original DiskRep
253 CFDataRef identification() { return mOriginal->identification(); }
254 std::string mainExecutablePath() { return mOriginal->mainExecutablePath(); }
255 CFURLRef copyCanonicalPath() { return mOriginal->copyCanonicalPath(); }
256 std::string resourcesRootPath() { return mOriginal->resourcesRootPath(); }
257 void adjustResources(ResourceBuilder &builder) { return mOriginal->adjustResources(builder); }
258 Universal *mainExecutableImage() { return mOriginal->mainExecutableImage(); }
259 size_t signingBase() { return mOriginal->signingBase(); }
260 size_t signingLimit() { return mOriginal->signingLimit(); }
261 size_t execSegBase(const Architecture *arch) { return mOriginal->execSegBase(arch); }
262 size_t execSegLimit(const Architecture *arch) { return mOriginal->execSegLimit(arch); }
263 std::string format() { return mOriginal->format(); }
264 CFArrayRef modifiedFiles() { return mOriginal->modifiedFiles(); }
265 UnixPlusPlus::FileDesc &fd() { return mOriginal->fd(); }
266 void flush() { return mOriginal->flush(); }
267
268 std::string recommendedIdentifier(const SigningContext &ctx)
269 { return mOriginal->recommendedIdentifier(ctx); }
270 CFDictionaryRef defaultResourceRules(const SigningContext &ctx)
271 { return mOriginal->defaultResourceRules(ctx); }
272 const Requirements *defaultRequirements(const Architecture *arch, const SigningContext &ctx)
273 { return mOriginal->defaultRequirements(arch, ctx); }
274 size_t pageSize(const SigningContext &ctx) { return mOriginal->pageSize(ctx); }
275
276 void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags) { mOriginal->strictValidate(cd, tolerated, flags); }
277 CFArrayRef allowedResourceOmissions() { return mOriginal->allowedResourceOmissions(); }
278
279 private:
280 RefPointer<DiskRep> mOriginal; // underlying representation
281 };
282
283
284 } // end namespace CodeSigning
285 } // end namespace Security
286
287 #endif // !_H_DISKREP