2  * Copyright (c) 2006-2012 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 // requirement - Code Requirement Blob description 
  27 #ifndef _H_REQUIREMENT 
  28 #define _H_REQUIREMENT 
  30 #include <security_utilities/blob.h> 
  31 #include <security_utilities/superblob.h> 
  32 #include <security_utilities/hashing.h> 
  33 #include <Security/CodeSigning.h> 
  34 #include "codedirectory.h" 
  38 namespace CodeSigning 
{ 
  42 // Single requirement. 
  43 // This is a contiguous binary blob, starting with this header 
  44 // and followed by binary expr-code. All links within the blob 
  45 // are offset-relative to the start of the header. 
  46 // This is designed to be a binary stable format. Note that we restrict 
  47 // outselves to 4GB maximum size (4 byte size/offset), and we expect real 
  48 // Requirement blobs to be fairly small (a few kilobytes at most). 
  50 // The "kind" field allows for adding different kinds of Requirements altogether 
  51 // in the future. We expect to stay within the framework of "opExpr" requirements, 
  52 // but it never hurts to have a way out. 
  54 class Requirement
: public Blob
<Requirement
, 0xfade0c00> { 
  56         class Maker
;                            // makes Requirement blobs 
  57         class Context
;                          // evaluation context 
  58         class Reader
;                           // structured reader 
  59         class Interpreter
;                      // evaluation engine 
  61         // different forms of Requirements. Right now, we only support exprForm ("opExprs") 
  63                 exprForm 
= 1                    // prefix expr form 
  66         void kind(Kind k
) { mKind 
= k
; } 
  67         Kind 
kind() const { return Kind(uint32_t(mKind
)); } 
  69         // validate this requirement against a code context 
  70         void validate(const Context 
&ctx
, OSStatus failure 
= errSecCSReqFailed
) const;  // throws on all failures 
  71         bool validates(const Context 
&ctx
, OSStatus failure 
= errSecCSReqFailed
) const; // returns on clean miss 
  73         // certificate positions (within a standard certificate chain) 
  74         static const int leafCert 
= 0;          // index for leaf (first in chain) 
  75         static const int anchorCert 
= -1;       // index for anchor (last in chain) 
  77 #if defined(TEST_APPLE_ANCHOR) 
  78         static const char testAppleAnchorEnv
[]; 
  79         static const SHA1::Digest 
&testAppleAnchorHash(); 
  80 #endif //TEST_APPLE_ANCHOR 
  82         // common alignment rule for all requirement forms 
  83         static const size_t baseAlignment 
= sizeof(uint32_t); // (we might as well say "four") 
  85     // canonical (source) names of Requirement types (matched to SecRequirementType in CSCommon.h) 
  86     static const char *const typeNames
[]; 
  88         IFDUMP(void dump() const); 
  91         Endian
<uint32_t> mKind
;                 // expression kind 
  96 // An interpretation context 
  98 class Requirement::Context 
{ 
 101                 : certs(NULL
), info(NULL
), entitlements(NULL
), identifier(""), directory(NULL
) { } 
 104         Context(CFArrayRef certChain
, CFDictionaryRef infoDict
, CFDictionaryRef entitlementDict
, 
 105                         const std::string 
&ident
, const CodeDirectory 
*dir
) 
 106                 : certs(certChain
), info(infoDict
), entitlements(entitlementDict
), identifier(ident
), directory(dir
) { } 
 108         CFArrayRef certs
;                                                               // certificate chain 
 109         CFDictionaryRef info
;                                                   // Info.plist 
 110         CFDictionaryRef entitlements
;                                   // entitlement plist 
 111         std::string identifier
;                                         // signing identifier 
 112         const CodeDirectory 
*directory
;                         // CodeDirectory 
 114         SecCertificateRef 
cert(int ix
) const;                   // get a cert from the cert chain (NULL if not found) 
 115         unsigned int certCount() const;                         // length of cert chain (including root) 
 122 // Opcodes are broken into flags in the (HBO) high byte, and an opcode value 
 123 // in the remaining 24 bits. Note that opcodes will remain fairly small 
 124 // (almost certainly <60000), so we have the third byte to play around with 
 125 // in the future, if needed. For now, small opcodes effective reserve this byte 
 127 // The flag byte allows for limited understanding of unknown opcodes. It allows 
 128 // the interpreter to use the known opcode parts of the program while semi-creatively 
 129 // disregarding the parts it doesn't know about. An unrecognized opcode with zero 
 130 // flag byte causes evaluation to categorically fail, since the semantics of such 
 131 // an opcode cannot safely be predicted. 
 134         // semantic bits or'ed into the opcode 
 135         opFlagMask 
=     0xFF000000,    // high bit flags 
 136         opGenericFalse 
= 0x80000000,    // has size field; okay to default to false 
 137         opGenericSkip 
=  0x40000000,    // has size field; skip and continue 
 141         opFalse
,                                                // unconditionally false 
 142         opTrue
,                                                 // unconditionally true 
 143         opIdent
,                                                // match canonical code [string] 
 144         opAppleAnchor
,                                  // signed by Apple as Apple's product 
 145         opAnchorHash
,                                   // match anchor [cert hash] 
 146         opInfoKeyValue
,                                 // *legacy* - use opInfoKeyField [key; value] 
 147         opAnd
,                                                  // binary prefix expr AND expr [expr; expr] 
 148         opOr
,                                                   // binary prefix expr OR expr [expr; expr] 
 149         opCDHash
,                                               // match hash of CodeDirectory directly [cd hash] 
 150         opNot
,                                                  // logical inverse [expr] 
 151         opInfoKeyField
,                                 // Info.plist key field [string; match suffix] 
 152         opCertField
,                                    // Certificate field [cert index; field name; match suffix] 
 153         opTrustedCert
,                                  // require trust settings to approve one particular cert [cert index] 
 154         opTrustedCerts
,                                 // require trust settings to approve the cert chain 
 155         opCertGeneric
,                                  // Certificate component by OID [cert index; oid; match suffix] 
 156         opAppleGenericAnchor
,                   // signed by Apple in any capacity 
 157         opEntitlementField
,                             // entitlement dictionary field [string; match suffix] 
 158         opCertPolicy
,                                   // Certificate policy by OID [cert index; oid; match suffix] 
 159         opNamedAnchor
,                                  // named anchor type 
 160         opNamedCode
,                                    // named subroutine 
 161         opPlatform
,                                             // platform constraint [integer] 
 162         exprOpCount                                             
// (total opcode count in use) 
 165 // match suffix opcodes 
 166 enum MatchOperation 
{ 
 167         matchExists
,                                    // anything but explicit "false" - no value stored 
 168         matchEqual
,                                             // equal (CFEqual) 
 169         matchContains
,                                  // partial match (substring) 
 170         matchBeginsWith
,                                // partial match (initial substring) 
 171         matchEndsWith
,                                  // partial match (terminal substring) 
 172         matchLessThan
,                                  // less than (string with numeric comparison) 
 173         matchGreaterThan
,                               // greater than (string with numeric comparison) 
 174         matchLessEqual
,                                 // less or equal (string with numeric comparison) 
 175         matchGreaterEqual
,                              // greater or equal (string with numeric comparison) 
 180 // We keep Requirement groups in SuperBlobs, indexed by SecRequirementType 
 182 typedef SuperBlob
<0xfade0c01> Requirements
; 
 186 // Byte order flippers 
 188 inline CodeSigning::ExprOp 
h2n(CodeSigning::ExprOp op
) 
 190         uint32_t intOp 
= (uint32_t) op
; 
 191         return (CodeSigning::ExprOp
) ::h2n(intOp
); 
 194 inline CodeSigning::ExprOp 
n2h(CodeSigning::ExprOp op
) 
 196         uint32_t intOp 
= (uint32_t) op
; 
 197         return (CodeSigning::ExprOp
) ::n2h(intOp
); 
 201 inline CodeSigning::MatchOperation 
h2n(CodeSigning::MatchOperation op
) 
 203         return CodeSigning::MatchOperation(::h2n((uint32_t) op
)); 
 206 inline CodeSigning::MatchOperation 
n2h(CodeSigning::MatchOperation op
) 
 208         return CodeSigning::MatchOperation(::n2h((uint32_t) op
)); 
 215 #endif //_H_REQUIREMENT