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. (In other words, 
  53 // DiskReps know where stuff is and how it is stored, but we know what it means.) 
  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. 
  61 class SecStaticCode 
: public SecCFObject 
{ 
  66         // A context for resource validation operations, to tailor error response. 
  67         // The base class throws an exception immediately and ignores detail data. 
  69         class ValidationContext 
{ 
  71                 virtual ~ValidationContext(); 
  72                 virtual void reportProblem(OSStatus rc
, CFStringRef type
, CFTypeRef value
); 
  76         // A CollectingContext collects all error details and throws an annotated final error. 
  78         class CollectingContext 
: public ValidationContext 
{ 
  80                 CollectingContext(SecStaticCode 
&c
) : code(c
), mStatus(noErr
) { } 
  81                 void reportProblem(OSStatus rc
, CFStringRef type
, CFTypeRef value
); 
  83                 operator OSStatus () const              { return mStatus
; } 
  84                 void throwMe() __attribute__((noreturn
)); 
  89                 CFRef
<CFMutableDictionaryRef
> mCollection
; 
  94         SECCFFUNCTIONS(SecStaticCode
, SecStaticCodeRef
, 
  95                 errSecCSInvalidObjectRef
, gCFObjects().StaticCode
) 
  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 
 101         SecStaticCode(DiskRep 
*rep
); 
 102     virtual ~SecStaticCode() throw(); 
 104     bool equal(SecCFObject 
&other
); 
 107         void detachedSignature(CFDataRef sig
);          // attach an explicitly given detached signature 
 108         void checkForSystemSignature();                         // check for and attach system-supplied detached signature 
 110         const CodeDirectory 
*codeDirectory(bool check 
= true); 
 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(); 
 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
); 
 131         bool flag(uint32_t tested
); 
 133         void resetValidity();                                           // clear validation caches (if something may have changed) 
 135         bool validated() const  { return mValidated
; } 
 137                 { assert(validated()); return mValidated 
&& (mValidationResult 
== noErr
); } 
 139         void validateDirectory(); 
 140         void validateComponent(CodeDirectory::SpecialSlot slot
, OSStatus fail 
= errSecCSSignatureFailed
); 
 141         void validateResources(); 
 142         void validateExecutable(); 
 144         const Requirements 
*internalRequirements(); 
 145         const Requirement 
*internalRequirement(SecRequirementType type
); 
 146         const Requirement 
*designatedRequirement(); 
 147         const Requirement 
*defaultDesignatedRequirement();              // newly allocated (caller owns) 
 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 
 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 
 158         CFDictionaryRef 
signingInformation(SecCSFlags flags
); // omnibus information-gathering API (creates new dictionary) 
 161         class AllArchitectures
; 
 164         CFDictionaryRef 
getDictionary(CodeDirectory::SpecialSlot slot
, OSStatus fail
); // component value as a dictionary 
 165         bool verifySignature(); 
 166         SecPolicyRef 
verificationPolicy(); 
 168         void defaultDesignatedAppleAnchor(Requirement::Maker 
&maker
); 
 169         void defaultDesignatedNonAppleAnchor(Requirement::Maker 
&maker
); 
 170         bool isAppleSDKSignature(); 
 172         static void checkOptionalResource(CFTypeRef key
, CFTypeRef value
, void *context
); 
 175         RefPointer
<DiskRep
> mRep
;                       // on-disk representation 
 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 
 182         // static executable validation state (nested within mValidated/mValid) 
 183         bool mExecutableValidated
;                      // tried to validate executable file 
 184         bool mExecutableValid
;                          // outcome if mExecutableValidated 
 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 
 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 
 199         bool mGotResourceBase
;                          // asked mRep for resourceBasePath 
 200         CFRef
<CFURLRef
> mResourceBase
;          // URL form of resource base directory 
 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
; 
 207         // cached verification policy 
 208         CFRef
<SecPolicyRef
> mPolicy
; 
 213 // Given a SecStaticCode, create an iterator that produces SecStaticCodes 
 214 // for all architectures encompassed by this static code reference. 
 216 class SecStaticCode::AllArchitectures 
: public SecPointer
<SecStaticCode
> { 
 218         AllArchitectures(SecStaticCode 
*code
); 
 220         SecStaticCode 
*operator () (); 
 223         SecPointer
<SecStaticCode
> mBase
; 
 224         enum { fatBinary
, firstNonFat
, atEnd 
} mState
; 
 225         Universal::Architectures mArchitectures
; 
 226         Universal::Architectures::const_iterator mCurrent
; 
 230 } // end namespace CodeSigning 
 231 } // end namespace Security 
 233 #endif // !_H_STATICCODE