2 * Copyright (c) 2006-2007 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 // StaticCode - SecStaticCode API objects
31 #include "Requirements.h"
32 #include "requirement.h"
34 #include "codedirectory.h"
35 #include <Security/SecTrust.h>
36 #include <CoreFoundation/CFData.h>
39 namespace CodeSigning
{
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.
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.
54 class SecStaticCode
: public SecCFObject
{
59 // A context for resource validation operations, to tailor error response.
60 // The base class throws an exception immediately and ignores detail data.
62 class ValidationContext
{
64 virtual ~ValidationContext();
65 virtual void reportProblem(OSStatus rc
, CFStringRef type
, CFTypeRef value
);
69 // A CollectingContext collects all error details and throws an annotated final error.
71 class CollectingContext
: public ValidationContext
{
73 CollectingContext(SecStaticCode
&c
) : code(c
), mStatus(noErr
) { }
74 void reportProblem(OSStatus rc
, CFStringRef type
, CFTypeRef value
);
76 operator OSStatus () const { return mStatus
; }
77 void throwMe() __attribute__((noreturn
));
82 CFRef
<CFMutableDictionaryRef
> mCollection
;
87 SECCFFUNCTIONS(SecStaticCode
, SecStaticCodeRef
,
88 errSecCSInvalidObjectRef
, gCFObjects().StaticCode
)
90 // implicitly convert SecCodeRefs to their SecStaticCodeRefs
91 static SecStaticCode
*requiredStatic(SecStaticCodeRef ref
); // convert SecCodeRef
92 static SecCode
*optionalDynamic(SecStaticCodeRef ref
); // extract SecCodeRef or NULL
94 SecStaticCode(DiskRep
*rep
);
95 virtual ~SecStaticCode() throw();
97 bool equal(SecCFObject
&other
);
100 void detachedSignature(CFDataRef sig
); // attach an explicitly given detached signature
101 void checkForSystemSignature(); // check for and attach system-supplied detached signature
103 const CodeDirectory
*codeDirectory(bool check
= true);
105 CFDataRef
signature();
106 CFAbsoluteTime
signingTime();
107 bool isSigned() { return codeDirectory(false) != NULL
; }
108 DiskRep
*diskRep() { return mRep
; }
109 std::string
mainExecutablePath() { return mRep
->mainExecutablePath(); }
110 CFURLRef
canonicalPath() const { return mRep
->canonicalPath(); }
111 std::string
identifier() { return codeDirectory()->identifier(); }
112 std::string
format() const { return mRep
->format(); }
113 std::string
signatureSource();
114 CFDataRef
component(CodeDirectory::SpecialSlot slot
);
115 CFDictionaryRef
infoDictionary();
116 CFDictionaryRef
entitlements();
118 CFDictionaryRef
resourceDictionary();
119 CFURLRef
resourceBase();
120 CFDataRef
resource(std::string path
);
121 CFDataRef
resource(std::string path
, ValidationContext
&ctx
);
122 void validateResource(string path
, ValidationContext
&ctx
);
124 bool flag(uint32_t tested
);
126 void resetValidity();
128 bool validated() const { return mValidated
; }
130 { assert(validated()); return mValidated
&& (mValidationResult
== noErr
); }
132 void validateDirectory();
133 void validateComponent(CodeDirectory::SpecialSlot slot
);
134 void validateResources();
135 void validateExecutable();
137 const Requirements
*internalRequirements();
138 const Requirement
*internalRequirement(SecRequirementType type
);
139 const Requirement
*designatedRequirement();
140 const Requirement
*defaultDesignatedRequirement(); // newly allocated (caller owns)
142 void validateRequirements(SecRequirementType type
, SecStaticCode
*target
,
143 OSStatus nullError
= noErr
);
144 void validateRequirements(const Requirement
*req
, OSStatus failure
);
146 SecCertificateRef
cert(int ix
); // get a cert from the cert chain
147 CFArrayRef
certificates(); // get the entire certificate chain
149 CFDictionaryRef
signingInformation(SecCSFlags flags
); // information-gathering API
152 CFDictionaryRef
getDictionary(CodeDirectory::SpecialSlot slot
);
153 bool verifySignature();
154 SecPolicyRef
verificationPolicy();
156 void defaultDesignatedAppleAnchor(Requirement::Maker
&maker
);
157 void defaultDesignatedNonAppleAnchor(Requirement::Maker
&maker
);
158 bool isAppleSDKSignature();
160 static void checkOptionalResource(CFTypeRef key
, CFTypeRef value
, void *context
);
163 RefPointer
<DiskRep
> mRep
; // on-disk representation
165 // master validation state
166 bool mValidated
; // core validation was attempted
167 OSStatus mValidationResult
; // outcome of core validation
168 bool mValidationExpired
; // outcome had expired certificates
170 // static executable validation state (nested within mValidated/mValid)
171 bool mExecutableValidated
; // tried to validate executable file
172 bool mExecutableValid
; // outcome if mExecutableValidated
175 CFRef
<CFDataRef
> mDir
; // code directory data
176 CFRef
<CFDataRef
> mSignature
; // CMS signature data
177 CFAbsoluteTime mSigningTime
; // (signed) signing time
178 CFRef
<CFDataRef
> mCache
[cdSlotCount
]; // NULL => not tried, kCFNull => absent, other => present
180 // alternative cache forms (storage may depend on cached contents above)
181 CFRef
<CFDictionaryRef
> mInfoDict
; // derived from mCache slot
182 CFRef
<CFDictionaryRef
> mEntitlements
; // derived from mCache slot
183 CFRef
<CFDictionaryRef
> mResourceDict
; // derived from mCache slot
184 const Requirement
*mDesignatedReq
; // cached designated req if we made one up
185 CFRef
<CFDataRef
> mCDHash
; // hash of CodeDirectory
187 bool mGotResourceBase
; // asked mRep for resourceBasePath
188 CFRef
<CFURLRef
> mResourceBase
; // URL form of resource base directory
190 // signature verification outcome (mTrust == NULL => not done yet)
191 CFRef
<SecTrustRef
> mTrust
; // outcome of crypto validation (valid or not)
192 CFRef
<CFArrayRef
> mCertChain
;
193 CSSM_TP_APPLE_EVIDENCE_INFO
*mEvalDetails
;
195 // cached verification policy
196 CFRef
<SecPolicyRef
> mPolicy
;
200 } // end namespace CodeSigning
201 } // end namespace Security
203 #endif // !_H_STATICCODE