2 * Copyright (c) 2006-2015 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 // SecCode - API frame for SecCode objects.
27 // Note that some SecCode* functions take SecStaticCodeRef arguments in order to
28 // accept either static or dynamic code references, operating on the respective
29 // StaticCode. Those functions are in SecStaticCode.cpp, not here, despite their name.
34 #include <security_utilities/cfmunge.h>
35 #include <security_utilities/logging.h>
36 #include <xpc/private.h>
38 using namespace CodeSigning
;
42 // CFError user info keys
44 const CFStringRef kSecCFErrorArchitecture
= CFSTR("SecCSArchitecture");
45 const CFStringRef kSecCFErrorPattern
= CFSTR("SecCSPattern");
46 const CFStringRef kSecCFErrorResourceSeal
= CFSTR("SecCSResourceSeal");
47 const CFStringRef kSecCFErrorResourceAdded
= CFSTR("SecCSResourceAdded");
48 const CFStringRef kSecCFErrorResourceAltered
= CFSTR("SecCSResourceAltered");
49 const CFStringRef kSecCFErrorResourceMissing
= CFSTR("SecCSResourceMissing");
50 const CFStringRef kSecCFErrorResourceSideband
= CFSTR("SecCSResourceHasSidebandData");
51 const CFStringRef kSecCFErrorInfoPlist
= CFSTR("SecCSInfoPlist");
52 const CFStringRef kSecCFErrorGuestAttributes
= CFSTR("SecCSGuestAttributes");
53 const CFStringRef kSecCFErrorRequirementSyntax
= CFSTR("SecRequirementSyntax");
54 const CFStringRef kSecCFErrorPath
= CFSTR("SecComponentPath");
58 // CF-standard type code functions
60 CFTypeID
SecCodeGetTypeID(void)
63 return gCFObjects().Code
.typeID
;
64 END_CSAPI1(_kCFRuntimeNotATypeID
)
69 // Get a reference to the calling code.
71 OSStatus
SecCodeCopySelf(SecCSFlags flags
, SecCodeRef
*selfRef
)
76 CFRef
<CFMutableDictionaryRef
> attributes
= makeCFMutableDictionary(1,
77 kSecGuestAttributePid
, CFTempNumber(getpid()).get());
78 CodeSigning::Required(selfRef
) = SecCode::autoLocateGuest(attributes
, flags
)->handle(false);
85 // Get the dynamic status of a code.
87 OSStatus
SecCodeGetStatus(SecCodeRef codeRef
, SecCSFlags flags
, SecCodeStatus
*status
)
92 CodeSigning::Required(status
) = SecCode::required(codeRef
)->status();
99 // Change the dynamic status of a code
101 OSStatus
SecCodeSetStatus(SecCodeRef codeRef
, SecCodeStatusOperation operation
,
102 CFDictionaryRef arguments
, SecCSFlags flags
)
107 SecCode::required(codeRef
)->status(operation
, arguments
);
114 // Get the StaticCode for an Code
116 OSStatus
SecCodeCopyStaticCode(SecCodeRef codeRef
, SecCSFlags flags
, SecStaticCodeRef
*staticCodeRef
)
120 checkFlags(flags
, kSecCSUseAllArchitectures
);
121 SecPointer
<SecStaticCode
> staticCode
= SecCode::required(codeRef
)->staticCode();
122 if (flags
& kSecCSUseAllArchitectures
)
123 if (Universal
* macho
= staticCode
->diskRep()->mainExecutableImage()) // Mach-O main executable
124 if (macho
->narrowed()) {
125 // create a new StaticCode comprising the whole fat file
126 RefPointer
<DiskRep
> rep
= DiskRep::bestGuess(staticCode
->diskRep()->mainExecutablePath());
127 staticCode
= new SecStaticCode(rep
);
129 CodeSigning::Required(staticCodeRef
) = staticCode
? staticCode
->handle() : NULL
;
136 // Get the host for an Code
138 OSStatus
SecCodeCopyHost(SecCodeRef guestRef
, SecCSFlags flags
, SecCodeRef
*hostRef
)
143 SecPointer
<SecCode
> host
= SecCode::required(guestRef
)->host();
144 CodeSigning::Required(hostRef
) = host
? host
->handle() : NULL
;
151 // Find a guest by attribute(s)
153 const CFStringRef kSecGuestAttributeCanonical
= CFSTR("canonical");
154 const CFStringRef kSecGuestAttributeHash
= CFSTR("codedirectory-hash");
155 const CFStringRef kSecGuestAttributeMachPort
= CFSTR("mach-port");
156 const CFStringRef kSecGuestAttributePid
= CFSTR("pid");
157 const CFStringRef kSecGuestAttributeAudit
= CFSTR("audit");
158 const CFStringRef kSecGuestAttributeDynamicCode
= CFSTR("dynamicCode");
159 const CFStringRef kSecGuestAttributeDynamicCodeInfoPlist
= CFSTR("dynamicCodeInfoPlist");
160 const CFStringRef kSecGuestAttributeArchitecture
= CFSTR("architecture");
161 const CFStringRef kSecGuestAttributeSubarchitecture
= CFSTR("subarchitecture");
164 OSStatus
SecCodeCopyGuestWithAttributes(SecCodeRef hostRef
,
165 CFDictionaryRef attributes
, SecCSFlags flags
, SecCodeRef
*guestRef
)
171 if (SecCode
*guest
= SecCode::required(hostRef
)->locateGuest(attributes
))
172 CodeSigning::Required(guestRef
) = guest
->handle(false);
174 return errSecCSNoSuchCode
;
176 CodeSigning::Required(guestRef
) = SecCode::autoLocateGuest(attributes
, flags
)->handle(false);
183 // Deprecated since 10.6, DO NOT USE. This can be raced.
184 // Use SecCodeCreateWithAuditToken instead.
186 OSStatus
SecCodeCreateWithPID(pid_t pid
, SecCSFlags flags
, SecCodeRef
*processRef
)
191 if (SecCode
*guest
= KernelCode::active()->locateGuest(CFTemp
<CFDictionaryRef
>("{%O=%d}", kSecGuestAttributePid
, pid
)))
192 CodeSigning::Required(processRef
) = guest
->handle(false);
194 return errSecCSNoSuchCode
;
200 // Shorthand for getting the SecCodeRef for a UNIX process
202 OSStatus
SecCodeCreateWithAuditToken(const audit_token_t
*audit
,
203 SecCSFlags flags
, SecCodeRef
*processRef
)
208 CFRef
<CFDataRef
> auditData
= makeCFData(audit
, sizeof(audit_token_t
));
209 if (SecCode
*guest
= KernelCode::active()->locateGuest(CFTemp
<CFDictionaryRef
>("{%O=%O}", kSecGuestAttributeAudit
, auditData
.get()))) {
210 CodeSigning::Required(processRef
) = guest
->handle(false);
212 return errSecCSNoSuchCode
;
218 OSStatus
SecCodeCreateWithXPCMessage(xpc_object_t message
, SecCSFlags flags
,
219 SecCodeRef
* __nonnull CF_RETURNS_RETAINED target
)
225 if (xpc_get_type(message
) != XPC_TYPE_DICTIONARY
) {
226 return errSecCSInvalidObjectRef
;
229 xpc_connection_t connection
= xpc_dictionary_get_remote_connection(message
);
230 if (connection
== NULL
) {
231 return errSecCSInvalidObjectRef
;
234 audit_token_t t
= {0};
235 xpc_connection_get_audit_token(connection
, &t
);
237 return SecCodeCreateWithAuditToken(&t
, flags
, target
);
242 #endif // TARGET_OS_OSX
246 // Check validity of an Code
248 OSStatus
SecCodeCheckValidity(SecCodeRef codeRef
, SecCSFlags flags
,
249 SecRequirementRef requirementRef
)
251 return SecCodeCheckValidityWithErrors(codeRef
, flags
, requirementRef
, NULL
);
254 OSStatus
SecCodeCheckValidityWithErrors(SecCodeRef codeRef
, SecCSFlags flags
,
255 SecRequirementRef requirementRef
, CFErrorRef
*errors
)
260 kSecCSConsiderExpiration
261 | kSecCSStrictValidate
262 | kSecCSStrictValidateStructure
263 | kSecCSRestrictSidebandData
264 | kSecCSEnforceRevocationChecks
266 SecPointer
<SecCode
> code
= SecCode::required(codeRef
);
267 code
->checkValidity(flags
);
268 if (const SecRequirement
*req
= SecRequirement::optional(requirementRef
))
269 code
->staticCode()->validateRequirement(req
->requirement(), errSecCSReqFailed
);
276 // Collect suitably laundered information about the code signature of a SecStaticCode
277 // and return it as a CFDictionary.
279 // This API contracts to return a few pieces of information even for unsigned
280 // code. This means that a SecStaticCodeRef is usable as a basic indentifier
281 // (i.e. handle) for any code out there.
283 const CFStringRef kSecCodeInfoCertificates
= CFSTR("certificates");
284 const CFStringRef kSecCodeInfoChangedFiles
= CFSTR("changed-files");
285 const CFStringRef kSecCodeInfoCMS
= CFSTR("cms");
286 const CFStringRef kSecCodeInfoDesignatedRequirement
= CFSTR("designated-requirement");
287 const CFStringRef kSecCodeInfoEntitlements
= CFSTR("entitlements");
288 const CFStringRef kSecCodeInfoEntitlementsDict
= CFSTR("entitlements-dict");
289 const CFStringRef kSecCodeInfoFlags
= CFSTR("flags");
290 const CFStringRef kSecCodeInfoFormat
= CFSTR("format");
291 const CFStringRef kSecCodeInfoDigestAlgorithm
= CFSTR("digest-algorithm");
292 const CFStringRef kSecCodeInfoDigestAlgorithms
= CFSTR("digest-algorithms");
293 const CFStringRef kSecCodeInfoPlatformIdentifier
= CFSTR("platform-identifier");
294 const CFStringRef kSecCodeInfoIdentifier
= CFSTR("identifier");
295 const CFStringRef kSecCodeInfoImplicitDesignatedRequirement
= CFSTR("implicit-requirement");
296 const CFStringRef kSecCodeInfoMainExecutable
= CFSTR("main-executable");
297 const CFStringRef kSecCodeInfoPList
= CFSTR("info-plist");
298 const CFStringRef kSecCodeInfoRequirements
= CFSTR("requirements");
299 const CFStringRef kSecCodeInfoRequirementData
= CFSTR("requirement-data");
300 const CFStringRef kSecCodeInfoSource
= CFSTR("source");
301 const CFStringRef kSecCodeInfoStatus
= CFSTR("status");
302 const CFStringRef kSecCodeInfoTeamIdentifier
= CFSTR("teamid");
303 const CFStringRef kSecCodeInfoTime
= CFSTR("signing-time");
304 const CFStringRef kSecCodeInfoTimestamp
= CFSTR("signing-timestamp");
305 const CFStringRef kSecCodeInfoTrust
= CFSTR("trust");
306 const CFStringRef kSecCodeInfoUnique
= CFSTR("unique");
307 const CFStringRef kSecCodeInfoCdHashes
= CFSTR("cdhashes");
308 const CFStringRef kSecCodeInfoCdHashesFull
= CFSTR("cdhashes-full");
309 const CFStringRef kSecCodeInfoRuntimeVersion
= CFSTR("runtime-version");
311 const CFStringRef kSecCodeInfoCodeDirectory
= CFSTR("CodeDirectory");
312 const CFStringRef kSecCodeInfoCodeOffset
= CFSTR("CodeOffset");
313 const CFStringRef kSecCodeInfoDiskRepInfo
= CFSTR("DiskRepInfo");
314 const CFStringRef kSecCodeInfoResourceDirectory
= CFSTR("ResourceDirectory");
315 const CFStringRef kSecCodeInfoNotarizationDate
= CFSTR("NotarizationDate");
316 const CFStringRef kSecCodeInfoCMSDigestHashType
= CFSTR("CMSDigestHashType");
317 const CFStringRef kSecCodeInfoCMSDigest
= CFSTR("CMSDigest");
318 const CFStringRef kSecCodeInfoSignatureVersion
= CFSTR("SignatureVersion");
320 /* DiskInfoRepInfo types */
321 const CFStringRef kSecCodeInfoDiskRepVersionPlatform
= CFSTR("VersionPlatform");
322 const CFStringRef kSecCodeInfoDiskRepVersionMin
= CFSTR("VersionMin");
323 const CFStringRef kSecCodeInfoDiskRepVersionSDK
= CFSTR("VersionSDK");
324 const CFStringRef kSecCodeInfoDiskRepNoLibraryValidation
= CFSTR("NoLibraryValidation");
327 OSStatus
SecCodeCopySigningInformation(SecStaticCodeRef codeRef
, SecCSFlags flags
,
328 CFDictionaryRef
*infoRef
)
333 kSecCSInternalInformation
334 | kSecCSSigningInformation
335 | kSecCSRequirementInformation
336 | kSecCSDynamicInformation
337 | kSecCSContentInformation
338 | kSecCSSkipResourceDirectory
339 | kSecCSCalculateCMSDigest
);
341 SecPointer
<SecStaticCode
> code
= SecStaticCode::requiredStatic(codeRef
);
342 CFRef
<CFDictionaryRef
> info
= code
->signingInformation(flags
);
344 if (flags
& kSecCSDynamicInformation
)
345 if (SecPointer
<SecCode
> dcode
= SecStaticCode::optionalDynamic(codeRef
))
346 info
.take(cfmake
<CFDictionaryRef
>("{+%O,%O=%u}", info
.get(), kSecCodeInfoStatus
, dcode
->status()));
348 CodeSigning::Required(infoRef
) = info
.yield();