]> git.saurik.com Git - apple/libsecurity_codesigning.git/blob - lib/StaticCode.h
8350ddbe7dac13b4efb448c189f441eb142db09e
[apple/libsecurity_codesigning.git] / lib / StaticCode.h
1 /*
2 * Copyright (c) 2006-2007 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 // StaticCode - SecStaticCode API objects
26 //
27 #ifndef _H_STATICCODE
28 #define _H_STATICCODE
29
30 #include "cs.h"
31 #include "Requirements.h"
32 #include "requirement.h"
33 #include "diskrep.h"
34 #include "codedirectory.h"
35 #include <Security/SecTrust.h>
36 #include <CoreFoundation/CFData.h>
37
38 namespace Security {
39 namespace CodeSigning {
40
41
42 class SecCode;
43
44
45 //
46 // A SecStaticCode object represents the file system version of some code.
47 // There's a lot of pieces to this, and we'll bring them all into
48 // memory here (lazily) and let you fondle them with ease.
49 //
50 // Note that concrete knowledge of where stuff is stored resides in the DiskRep
51 // object we hold. DiskReps allocate, retrieve, and return data to us. We are
52 // responsible for interpreting, caching, and validating them. (In other words,
53 // DiskReps know where stuff is and how it is stored, but we know what it means.)
54 //
55 // Data accessors (returning CFDataRef, CFDictionaryRef, various pointers, etc.)
56 // cache those values internally and return unretained(!) references ("Get" style)
57 // that are valid as long as the SecStaticCode object's lifetime, or until
58 // resetValidity() is called, whichever is sooner. If you need to keep them,
59 // retain or copy them as needed.
60 //
61 class SecStaticCode : public SecCFObject {
62 NOCOPY(SecStaticCode)
63
64 protected:
65 //
66 // A context for resource validation operations, to tailor error response.
67 // The base class throws an exception immediately and ignores detail data.
68 //
69 class ValidationContext {
70 public:
71 virtual ~ValidationContext();
72 virtual void reportProblem(OSStatus rc, CFStringRef type, CFTypeRef value);
73 };
74
75 //
76 // A CollectingContext collects all error details and throws an annotated final error.
77 //
78 class CollectingContext : public ValidationContext {
79 public:
80 CollectingContext(SecStaticCode &c) : code(c), mStatus(noErr) { }
81 void reportProblem(OSStatus rc, CFStringRef type, CFTypeRef value);
82
83 operator OSStatus () const { return mStatus; }
84 void throwMe() __attribute__((noreturn));
85
86 SecStaticCode &code;
87
88 private:
89 CFRef<CFMutableDictionaryRef> mCollection;
90 OSStatus mStatus;
91 };
92
93 public:
94 SECCFFUNCTIONS(SecStaticCode, SecStaticCodeRef,
95 errSecCSInvalidObjectRef, gCFObjects().StaticCode)
96
97 // implicitly convert SecCodeRefs to their SecStaticCodeRefs
98 static SecStaticCode *requiredStatic(SecStaticCodeRef ref); // convert SecCodeRef
99 static SecCode *optionalDynamic(SecStaticCodeRef ref); // extract SecCodeRef or NULL
100
101 SecStaticCode(DiskRep *rep);
102 virtual ~SecStaticCode() throw();
103
104 bool equal(SecCFObject &other);
105 CFHashCode hash();
106
107 void detachedSignature(CFDataRef sig); // attach an explicitly given detached signature
108 void checkForSystemSignature(); // check for and attach system-supplied detached signature
109
110 const CodeDirectory *codeDirectory(bool check = true);
111 CFDataRef cdHash();
112 CFDataRef signature();
113 CFAbsoluteTime signingTime();
114 bool isSigned() { return codeDirectory(false) != NULL; }
115 DiskRep *diskRep() { return mRep; }
116 std::string mainExecutablePath() { return mRep->mainExecutablePath(); }
117 CFURLRef canonicalPath() const { return mRep->canonicalPath(); }
118 std::string identifier() { return codeDirectory()->identifier(); }
119 std::string format() const { return mRep->format(); }
120 std::string signatureSource();
121 CFDataRef component(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed);
122 CFDictionaryRef infoDictionary();
123 CFDictionaryRef entitlements();
124
125 CFDictionaryRef resourceDictionary();
126 CFURLRef resourceBase();
127 CFDataRef resource(std::string path);
128 CFDataRef resource(std::string path, ValidationContext &ctx);
129 void validateResource(std::string path, ValidationContext &ctx);
130
131 bool flag(uint32_t tested);
132
133 void resetValidity(); // clear validation caches (if something may have changed)
134
135 bool validated() const { return mValidated; }
136 bool valid() const
137 { assert(validated()); return mValidated && (mValidationResult == noErr); }
138
139 void validateDirectory();
140 void validateComponent(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed);
141 void validateResources();
142 void validateExecutable();
143
144 const Requirements *internalRequirements();
145 const Requirement *internalRequirement(SecRequirementType type);
146 const Requirement *designatedRequirement();
147 const Requirement *defaultDesignatedRequirement(); // newly allocated (caller owns)
148
149 void validateRequirements(SecRequirementType type, SecStaticCode *target,
150 OSStatus nullError = noErr); // target against my [type], throws
151 void validateRequirement(const Requirement *req, OSStatus failure); // me against [req], throws
152 bool satisfiesRequirement(const Requirement *req, OSStatus failure); // me against [req], returns on clean miss
153
154 // certificates are available after signature validation (they are stored in the CMS signature)
155 SecCertificateRef cert(int ix); // get a cert from the cert chain
156 CFArrayRef certificates(); // get the entire certificate chain
157
158 CFDictionaryRef signingInformation(SecCSFlags flags); // omnibus information-gathering API (creates new dictionary)
159
160 public:
161 class AllArchitectures;
162
163 protected:
164 CFDictionaryRef getDictionary(CodeDirectory::SpecialSlot slot, OSStatus fail); // component value as a dictionary
165 bool verifySignature();
166 SecPolicyRef verificationPolicy();
167
168 void defaultDesignatedAppleAnchor(Requirement::Maker &maker);
169 void defaultDesignatedNonAppleAnchor(Requirement::Maker &maker);
170 bool isAppleSDKSignature();
171
172 static void checkOptionalResource(CFTypeRef key, CFTypeRef value, void *context);
173
174 private:
175 RefPointer<DiskRep> mRep; // on-disk representation
176
177 // master validation state
178 bool mValidated; // core validation was attempted
179 OSStatus mValidationResult; // outcome of core validation
180 bool mValidationExpired; // outcome had expired certificates
181
182 // static executable validation state (nested within mValidated/mValid)
183 bool mExecutableValidated; // tried to validate executable file
184 bool mExecutableValid; // outcome if mExecutableValidated
185
186 // cached contents
187 CFRef<CFDataRef> mDir; // code directory data
188 CFRef<CFDataRef> mSignature; // CMS signature data
189 CFAbsoluteTime mSigningTime; // (signed) signing time
190 CFRef<CFDataRef> mCache[cdSlotCount]; // NULL => not tried, kCFNull => absent, other => present
191
192 // alternative cache forms (storage may depend on cached contents above)
193 CFRef<CFDictionaryRef> mInfoDict; // derived from mCache slot
194 CFRef<CFDictionaryRef> mEntitlements; // derived from mCache slot
195 CFRef<CFDictionaryRef> mResourceDict; // derived from mCache slot
196 const Requirement *mDesignatedReq; // cached designated req if we made one up
197 CFRef<CFDataRef> mCDHash; // hash of CodeDirectory
198
199 bool mGotResourceBase; // asked mRep for resourceBasePath
200 CFRef<CFURLRef> mResourceBase; // URL form of resource base directory
201
202 // signature verification outcome (mTrust == NULL => not done yet)
203 CFRef<SecTrustRef> mTrust; // outcome of crypto validation (valid or not)
204 CFRef<CFArrayRef> mCertChain;
205 CSSM_TP_APPLE_EVIDENCE_INFO *mEvalDetails;
206
207 // cached verification policy
208 CFRef<SecPolicyRef> mPolicy;
209 };
210
211
212 //
213 // Given a SecStaticCode, create an iterator that produces SecStaticCodes
214 // for all architectures encompassed by this static code reference.
215 //
216 class SecStaticCode::AllArchitectures : public SecPointer<SecStaticCode> {
217 public:
218 AllArchitectures(SecStaticCode *code);
219
220 SecStaticCode *operator () ();
221
222 private:
223 SecPointer<SecStaticCode> mBase;
224 enum { fatBinary, firstNonFat, atEnd } mState;
225 Universal::Architectures mArchitectures;
226 Universal::Architectures::const_iterator mCurrent;
227 };
228
229
230 } // end namespace CodeSigning
231 } // end namespace Security
232
233 #endif // !_H_STATICCODE