TrollStore/Exploits/fastPathSign/src/codesign.m
2023-11-26 21:41:10 +01:00

164 lines
6.8 KiB
Objective-C

#include <Foundation/Foundation.h>
#include <Security/Security.h>
#include <TargetConditionals.h>
#ifdef __cplusplus
extern "C" {
#endif
#if TARGET_OS_OSX
#include <Security/SecCode.h>
#include <Security/SecStaticCode.h>
#else
// CSCommon.h
typedef struct CF_BRIDGED_TYPE(id) __SecCode const* SecStaticCodeRef; /* code on disk */
typedef CF_OPTIONS(uint32_t, SecCSFlags) {
kSecCSDefaultFlags = 0, /* no particular flags (default behavior) */
kSecCSConsiderExpiration = 1U << 31, /* consider expired certificates invalid */
kSecCSEnforceRevocationChecks = 1 << 30, /* force revocation checks regardless of preference settings */
kSecCSNoNetworkAccess = 1 << 29, /* do not use the network, cancels "kSecCSEnforceRevocationChecks" */
kSecCSReportProgress = 1 << 28, /* make progress report call-backs when configured */
kSecCSCheckTrustedAnchors = 1 << 27, /* build certificate chain to system trust anchors, not to any self-signed certificate */
kSecCSQuickCheck = 1 << 26, /* (internal) */
kSecCSApplyEmbeddedPolicy = 1 << 25, /* Apply Embedded (iPhone) policy regardless of the platform we're running on */
};
// SecStaticCode.h
OSStatus SecStaticCodeCreateWithPathAndAttributes(CFURLRef path, SecCSFlags flags, CFDictionaryRef attributes,
SecStaticCodeRef* __nonnull CF_RETURNS_RETAINED staticCode);
// SecCode.h
CF_ENUM(uint32_t){
kSecCSInternalInformation = 1 << 0, kSecCSSigningInformation = 1 << 1, kSecCSRequirementInformation = 1 << 2,
kSecCSDynamicInformation = 1 << 3, kSecCSContentInformation = 1 << 4, kSecCSSkipResourceDirectory = 1 << 5,
kSecCSCalculateCMSDigest = 1 << 6,
};
OSStatus SecCodeCopySigningInformation(SecStaticCodeRef code, SecCSFlags flags, CFDictionaryRef* __nonnull CF_RETURNS_RETAINED information);
extern const CFStringRef kSecCodeInfoEntitlements; /* generic */
extern const CFStringRef kSecCodeInfoIdentifier; /* generic */
extern const CFStringRef kSecCodeInfoRequirementData; /* Requirement */
#endif
typedef CF_OPTIONS(uint32_t, SecPreserveFlags) {
kSecCSPreserveIdentifier = 1 << 0,
kSecCSPreserveRequirements = 1 << 1,
kSecCSPreserveEntitlements = 1 << 2,
kSecCSPreserveResourceRules = 1 << 3,
kSecCSPreserveFlags = 1 << 4,
kSecCSPreserveTeamIdentifier = 1 << 5,
kSecCSPreserveDigestAlgorithm = 1 << 6,
kSecCSPreservePreEncryptHashes = 1 << 7,
kSecCSPreserveRuntime = 1 << 8,
};
// SecCodeSigner.h
#ifdef BRIDGED_SECCODESIGNER
typedef struct CF_BRIDGED_TYPE(id) __SecCodeSigner* SecCodeSignerRef SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
#else
typedef struct __SecCodeSigner* SecCodeSignerRef SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
#endif
extern const CFStringRef kSecCodeSignerEntitlements SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
extern const CFStringRef kSecCodeSignerIdentifier SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
extern const CFStringRef kSecCodeSignerIdentity SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
extern const CFStringRef kSecCodeSignerPreserveMetadata SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
extern const CFStringRef kSecCodeSignerRequirements SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
extern const CFStringRef kSecCodeSignerResourceRules SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
#ifdef BRIDGED_SECCODESIGNER
OSStatus SecCodeSignerCreate(CFDictionaryRef parameters, SecCSFlags flags, SecCodeSignerRef* __nonnull CF_RETURNS_RETAINED signer)
SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
#else
OSStatus SecCodeSignerCreate(CFDictionaryRef parameters, SecCSFlags flags, SecCodeSignerRef* signer)
SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
#endif
OSStatus SecCodeSignerAddSignatureWithErrors(SecCodeSignerRef signer, SecStaticCodeRef code, SecCSFlags flags, CFErrorRef* errors)
SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
// SecCodePriv.h
extern const CFStringRef kSecCodeInfoResourceDirectory; /* Internal */
#ifdef __cplusplus
}
#endif
int codesign_sign_adhoc(const char *path, bool preserveMetadata, NSDictionary *customEntitlements)
{
NSString *filePath = [NSString stringWithUTF8String:path];
OSStatus status = 0;
int retval = 200;
// the special value "-" (dash) indicates ad-hoc signing
SecIdentityRef identity = (SecIdentityRef)kCFNull;
NSMutableDictionary* parameters = [[NSMutableDictionary alloc] init];
parameters[(__bridge NSString*)kSecCodeSignerIdentity] = (__bridge id)identity;
uint64_t preserveMetadataFlags = 0;
if (preserveMetadata) {
preserveMetadataFlags = (kSecCSPreserveIdentifier | kSecCSPreserveRequirements | kSecCSPreserveEntitlements | kSecCSPreserveResourceRules);
if (!customEntitlements) {
preserveMetadataFlags |= kSecCSPreserveEntitlements;
}
parameters[(__bridge NSString*)kSecCodeSignerPreserveMetadata] = @(preserveMetadataFlags);
}
if (customEntitlements) {
NSError *error;
NSData *xmlData = [NSPropertyListSerialization dataWithPropertyList:customEntitlements format:NSPropertyListXMLFormat_v1_0 options:0 error:&error];
if (!xmlData) {
NSLog(@"Failed to encode entitlements: %@", error);
return -1;
}
else {
// Super easy to use API, definitely not busted...
// Did I forget to mention it just segfaults if you don't add this prefix?
uint32_t entitlementsData[xmlData.length+8];
entitlementsData[0] = OSSwapHostToBigInt32(0xFADE7171);
entitlementsData[1] = OSSwapHostToBigInt32(xmlData.length+8);
[xmlData getBytes:&entitlementsData[2] length:xmlData.length];
parameters[(__bridge NSString*)kSecCodeSignerEntitlements] = [NSData dataWithBytes:entitlementsData length:xmlData.length+8];
}
}
SecCodeSignerRef signerRef;
status = SecCodeSignerCreate((__bridge CFDictionaryRef)parameters, kSecCSDefaultFlags, &signerRef);
if (status == 0) {
SecStaticCodeRef code;
status = SecStaticCodeCreateWithPathAndAttributes((__bridge CFURLRef)[NSURL fileURLWithPath:filePath], kSecCSDefaultFlags, (__bridge CFDictionaryRef)@{}, &code);
if (status == 0) {
CFErrorRef errors;
status = SecCodeSignerAddSignatureWithErrors(signerRef, code, kSecCSDefaultFlags, &errors);
if (status == 0) {
CFDictionaryRef newSigningInformation;
// Difference from codesign: added kSecCSSigningInformation, kSecCSRequirementInformation, kSecCSInternalInformation
status = SecCodeCopySigningInformation(code, kSecCSDefaultFlags | kSecCSSigningInformation | kSecCSRequirementInformation | kSecCSInternalInformation, &newSigningInformation);
if (status == 0) {
retval = 0;
CFRelease(newSigningInformation);
} else {
retval = 203;
}
}
else {
printf("Error while signing: %s\n", ((__bridge NSError *)errors).description.UTF8String);
}
CFRelease(code);
}
else {
retval = 202;
}
CFRelease(signerRef);
}
else {
retval = 201;
}
return retval;
}