1/* 2 * Copyright (c) 2006-2012 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// requirement - Code Requirement Blob description 26// 27#ifndef _H_REQUIREMENT 28#define _H_REQUIREMENT 29 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" 35#include <map> 36 37namespace Security { 38namespace CodeSigning { 39 40 41// 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). 49// 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. 53// 54class Requirement: public Blob<Requirement, 0xfade0c00> { 55public: 56 class Maker; // makes Requirement blobs 57 class Context; // evaluation context 58 class Reader; // structured reader 59 class Interpreter; // evaluation engine 60 61 // different forms of Requirements. Right now, we only support exprForm ("opExprs") 62 enum Kind { 63 exprForm = 1 // prefix expr form 64 }; 65 66 void kind(Kind k) { mKind = k; } 67 Kind kind() const { return Kind(uint32_t(mKind)); } 68 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 72 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) 76 77 // the SHA1 hash of the canonical "Apple Anchor", i.e. the X509 Anchor 78 // that is considered "Apple's anchor certificate", as defined by hashOfCertificate(). 79#if defined(TEST_APPLE_ANCHOR) 80 static const char testAppleAnchorEnv[]; 81 static const SHA1::Digest &testAppleAnchorHash(); 82#endif //TEST_APPLE_ANCHOR 83 84 // common alignment rule for all requirement forms 85 static const size_t baseAlignment = sizeof(uint32_t); // (we might as well say "four") 86 87 // canonical (source) names of Requirement types (matched to SecRequirementType in CSCommon.h) 88 static const char *const typeNames[]; 89 90 IFDUMP(void dump() const); 91 92private: 93 Endian<uint32_t> mKind; // expression kind 94}; 95 96 97// 98// An interpretation context 99// 100class Requirement::Context { 101protected: 102 Context() 103 : certs(NULL), info(NULL), entitlements(NULL), identifier(""), directory(NULL) { } 104 105public: 106 Context(CFArrayRef certChain, CFDictionaryRef infoDict, CFDictionaryRef entitlementDict, 107 const std::string &ident, const CodeDirectory *dir) 108 : certs(certChain), info(infoDict), entitlements(entitlementDict), identifier(ident), directory(dir) { } 109 110 CFArrayRef certs; // certificate chain 111 CFDictionaryRef info; // Info.plist 112 CFDictionaryRef entitlements; // entitlement plist 113 std::string identifier; // signing identifier 114 const CodeDirectory *directory; // CodeDirectory 115 116 SecCertificateRef cert(int ix) const; // get a cert from the cert chain (NULL if not found) 117 unsigned int certCount() const; // length of cert chain (including root) 118}; 119 120 121// 122// exprForm opcodes. 123// 124// Opcodes are broken into flags in the (HBO) high byte, and an opcode value 125// in the remaining 24 bits. Note that opcodes will remain fairly small 126// (almost certainly <60000), so we have the third byte to play around with 127// in the future, if needed. For now, small opcodes effective reserve this byte 128// as zero. 129// The flag byte allows for limited understanding of unknown opcodes. It allows 130// the interpreter to use the known opcode parts of the program while semi-creatively 131// disregarding the parts it doesn't know about. An unrecognized opcode with zero 132// flag byte causes evaluation to categorically fail, since the semantics of such 133// an opcode cannot safely be predicted. 134// 135enum { 136 // semantic bits or'ed into the opcode 137 opFlagMask = 0xFF000000, // high bit flags 138 opGenericFalse = 0x80000000, // has size field; okay to default to false 139 opGenericSkip = 0x40000000, // has size field; skip and continue 140}; 141 142enum ExprOp { 143 opFalse, // unconditionally false 144 opTrue, // unconditionally true 145 opIdent, // match canonical code [string] 146 opAppleAnchor, // signed by Apple as Apple's product 147 opAnchorHash, // match anchor [cert hash] 148 opInfoKeyValue, // *legacy* - use opInfoKeyField [key; value] 149 opAnd, // binary prefix expr AND expr [expr; expr] 150 opOr, // binary prefix expr OR expr [expr; expr] 151 opCDHash, // match hash of CodeDirectory directly [cd hash] 152 opNot, // logical inverse [expr] 153 opInfoKeyField, // Info.plist key field [string; match suffix] 154 opCertField, // Certificate field [cert index; field name; match suffix] 155 opTrustedCert, // require trust settings to approve one particular cert [cert index] 156 opTrustedCerts, // require trust settings to approve the cert chain 157 opCertGeneric, // Certificate component by OID [cert index; oid; match suffix] 158 opAppleGenericAnchor, // signed by Apple in any capacity 159 opEntitlementField, // entitlement dictionary field [string; match suffix] 160 opCertPolicy, // Certificate policy by OID [cert index; oid; match suffix] 161 opNamedAnchor, // named anchor type 162 opNamedCode, // named subroutine 163 exprOpCount // (total opcode count in use) 164}; 165 166// match suffix opcodes 167enum MatchOperation { 168 matchExists, // anything but explicit "false" - no value stored 169 matchEqual, // equal (CFEqual) 170 matchContains, // partial match (substring) 171 matchBeginsWith, // partial match (initial substring) 172 matchEndsWith, // partial match (terminal substring) 173 matchLessThan, // less than (string with numeric comparison) 174 matchGreaterThan, // greater than (string with numeric comparison) 175 matchLessEqual, // less or equal (string with numeric comparison) 176 matchGreaterEqual, // greater or equal (string with numeric comparison) 177}; 178 179 180// 181// We keep Requirement groups in SuperBlobs, indexed by SecRequirementType 182// 183typedef SuperBlob<0xfade0c01> Requirements; 184 185 186// 187// Byte order flippers 188// 189inline CodeSigning::ExprOp h2n(CodeSigning::ExprOp op) 190{ 191 uint32_t intOp = (uint32_t) op; 192 return (CodeSigning::ExprOp) ::h2n(intOp); 193} 194 195inline CodeSigning::ExprOp n2h(CodeSigning::ExprOp op) 196{ 197 uint32_t intOp = (uint32_t) op; 198 return (CodeSigning::ExprOp) ::n2h(intOp); 199} 200 201 202inline CodeSigning::MatchOperation h2n(CodeSigning::MatchOperation op) 203{ 204 return CodeSigning::MatchOperation(::h2n((uint32_t) op)); 205} 206 207inline CodeSigning::MatchOperation n2h(CodeSigning::MatchOperation op) 208{ 209 return CodeSigning::MatchOperation(::n2h((uint32_t) op)); 210} 211 212 213} // CodeSigning 214} // Security 215 216#endif //_H_REQUIREMENT 217