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