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_utilities/debugging_internal.h>
34 #include <Security/CodeSigning.h>
35 #include "codedirectory.h"
39 namespace CodeSigning
{
43 // Single requirement.
44 // This is a contiguous binary blob, starting with this header
45 // and followed by binary expr-code. All links within the blob
46 // are offset-relative to the start of the header.
47 // This is designed to be a binary stable format. Note that we restrict
48 // outselves to 4GB maximum size (4 byte size/offset), and we expect real
49 // Requirement blobs to be fairly small (a few kilobytes at most).
51 // The "kind" field allows for adding different kinds of Requirements altogether
52 // in the future. We expect to stay within the framework of "opExpr" requirements,
53 // but it never hurts to have a way out.
55 class Requirement
: public Blob
<Requirement
, 0xfade0c00> {
57 class Maker
; // makes Requirement blobs
58 class Context
; // evaluation context
59 class Reader
; // structured reader
60 class Interpreter
; // evaluation engine
62 // different forms of Requirements. Right now, we only support exprForm ("opExprs")
64 exprForm
= 1 // prefix expr form
67 void kind(Kind k
) { mKind
= k
; }
68 Kind
kind() const { return Kind(uint32_t(mKind
)); }
70 // validate this requirement against a code context
71 void validate(const Context
&ctx
, OSStatus failure
= errSecCSReqFailed
) const; // throws on all failures
72 bool validates(const Context
&ctx
, OSStatus failure
= errSecCSReqFailed
) const; // returns on clean miss
74 // certificate positions (within a standard certificate chain)
75 static const int leafCert
= 0; // index for leaf (first in chain)
76 static const int anchorCert
= -1; // index for anchor (last in chain)
78 #if defined(TEST_APPLE_ANCHOR)
79 static const char testAppleAnchorEnv
[];
80 static const SHA1::Digest
&testAppleAnchorHash();
81 #endif //TEST_APPLE_ANCHOR
83 // common alignment rule for all requirement forms
84 static const size_t baseAlignment
= sizeof(uint32_t); // (we might as well say "four")
86 // canonical (source) names of Requirement types (matched to SecRequirementType in CSCommon.h)
87 static const char *const typeNames
[];
89 IFDUMP(void dump() const);
93 Endian
<uint32_t> mKind
; // expression kind
98 // An interpretation context
100 class Requirement::Context
{
103 : certs(NULL
), info(NULL
), entitlements(NULL
), identifier(""), directory(NULL
) { }
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
) { }
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
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)
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
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.
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
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 opPlatform
, // platform constraint [integer]
164 exprOpCount
// (total opcode count in use)
167 // match suffix opcodes
168 enum MatchOperation
{
169 matchExists
, // anything but explicit "false" - no value stored
170 matchEqual
, // equal (CFEqual)
171 matchContains
, // partial match (substring)
172 matchBeginsWith
, // partial match (initial substring)
173 matchEndsWith
, // partial match (terminal substring)
174 matchLessThan
, // less than (string with numeric comparison)
175 matchGreaterThan
, // greater than (string with numeric comparison)
176 matchLessEqual
, // less or equal (string with numeric comparison)
177 matchGreaterEqual
, // greater or equal (string with numeric comparison)
182 // We keep Requirement groups in SuperBlobs, indexed by SecRequirementType
184 typedef SuperBlob
<0xfade0c01> Requirements
;
188 // Byte order flippers
190 inline CodeSigning::ExprOp
h2n(CodeSigning::ExprOp op
)
192 uint32_t intOp
= (uint32_t) op
;
193 return (CodeSigning::ExprOp
) ::h2n(intOp
);
196 inline CodeSigning::ExprOp
n2h(CodeSigning::ExprOp op
)
198 uint32_t intOp
= (uint32_t) op
;
199 return (CodeSigning::ExprOp
) ::n2h(intOp
);
203 inline CodeSigning::MatchOperation
h2n(CodeSigning::MatchOperation op
)
205 return CodeSigning::MatchOperation(::h2n((uint32_t) op
));
208 inline CodeSigning::MatchOperation
n2h(CodeSigning::MatchOperation op
)
210 return CodeSigning::MatchOperation(::n2h((uint32_t) op
));
217 #endif //_H_REQUIREMENT