+bool SecCodeSigner::Signer::booleanEntitlement(CFDictionaryRef entDict, CFStringRef key) {
+ CFBooleanRef entValue = (CFBooleanRef)CFDictionaryGetValue(entDict, key);
+
+ if (entValue == NULL || CFGetTypeID(entValue) != CFBooleanGetTypeID()) {
+ return false;
+ }
+
+ return CFBooleanGetValue(entValue);
+}
+
+uint64_t SecCodeSigner::Signer::entitlementsToExecSegFlags(CFDataRef entitlements)
+{
+ if (!entitlements) {
+ return 0;
+ }
+
+ const EntitlementBlob *blob = reinterpret_cast<const EntitlementBlob *>(CFDataGetBytePtr(entitlements));
+
+ if (blob == NULL || !blob->validateBlob(CFDataGetLength(entitlements))) {
+ return 0;
+ }
+
+ try {
+ CFRef<CFDictionaryRef> entDict = blob->entitlements();
+
+ uint64_t flags = 0;
+
+ flags |= booleanEntitlement(entDict, CFSTR("get-task-allow")) ? kSecCodeExecSegAllowUnsigned : 0;
+ flags |= booleanEntitlement(entDict, CFSTR("run-unsigned-code")) ? kSecCodeExecSegAllowUnsigned : 0;
+ flags |= booleanEntitlement(entDict, CFSTR("com.apple.private.cs.debugger")) ? kSecCodeExecSegDebugger : 0;
+ flags |= booleanEntitlement(entDict, CFSTR("dynamic-codesigning")) ? kSecCodeExecSegJit : 0;
+ flags |= booleanEntitlement(entDict, CFSTR("com.apple.private.skip-library-validation")) ? kSecCodeExecSegSkipLibraryVal : 0;
+ flags |= booleanEntitlement(entDict, CFSTR("com.apple.private.amfi.can-load-cdhash")) ? kSecCodeExecSegCanLoadCdHash : 0;
+ flags |= booleanEntitlement(entDict, CFSTR("com.apple.private.amfi.can-execute-cdhash")) ? kSecCodeExecSegCanExecCdHash : 0;
+
+ return flags;
+
+ } catch (const CommonError &err) {
+ // Not fatal.
+ secwarning("failed to parse entitlements: %s", err.what());
+ return 0;
+ }
+}