X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/ce3c8656732c924baf7e88df75eab50891bdc471..fa7225c82381bac4432a6edf16f53b5370238d85:/codesign_wrapper/codesign.c diff --git a/codesign_wrapper/codesign.c b/codesign_wrapper/codesign.c deleted file mode 100644 index 72c03a37..00000000 --- a/codesign_wrapper/codesign.c +++ /dev/null @@ -1,276 +0,0 @@ - -#include "codesign.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define DEBUG_ASSERT_PRODUCTION_CODE 0 -#include - -/* - * Magic numbers used by Code Signing - */ -enum { - CSMAGIC_REQUIREMENT = 0xfade0c00, /* single Requirement blob */ - CSMAGIC_REQUIREMENTS = 0xfade0c01, /* Requirements vector (internal requirements) */ - CSMAGIC_CODEDIRECTORY = 0xfade0c02, /* CodeDirectory blob */ - CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0, /* embedded form of signature data */ - CSMAGIC_DETACHED_SIGNATURE = 0xfade0cc1, /* multi-arch collection of embedded signatures */ - - CSSLOT_CODEDIRECTORY = 0, /* slot index for CodeDirectory */ -}; - - -/* - * Structure of an embedded-signature SuperBlob - */ -typedef struct __BlobIndex { - uint32_t type; /* type of entry */ - uint32_t offset; /* offset of entry */ -} CS_BlobIndex; - -typedef struct __SuperBlob { - uint32_t magic; /* magic number */ - uint32_t length; /* total length of SuperBlob */ - uint32_t count; /* number of index entries following */ - CS_BlobIndex index[]; /* (count) entries */ - /* followed by Blobs in no particular order as indicated by offsets in index */ -} CS_SuperBlob; - - -/* - * C form of a CodeDirectory. - */ -typedef struct __CodeDirectory { - uint32_t magic; /* magic number (CSMAGIC_CODEDIRECTORY) */ - uint32_t length; /* total length of CodeDirectory blob */ - uint32_t version; /* compatibility version */ - uint32_t flags; /* setup and mode flags */ - uint32_t hashOffset; /* offset of hash slot element at index zero */ - uint32_t identOffset; /* offset of identifier string */ - uint32_t nSpecialSlots; /* number of special hash slots */ - uint32_t nCodeSlots; /* number of ordinary (code) hash slots */ - uint32_t codeLimit; /* limit to main image signature range */ - uint8_t hashSize; /* size of each hash in bytes */ - uint8_t hashType; /* type of hash (cdHashType* constants) */ - uint8_t spare1; /* unused (must be zero) */ - uint8_t pageSize; /* log2(page size in bytes); 0 => infinite */ - uint32_t spare2; /* unused (must be zero) */ - /* followed by dynamic content as located by offset fields above */ -} CS_CodeDirectory; - - - //assert(page < ntohl(cd->nCodeSlots)); - //return base + ntohl(cd->hashOffset) + page * 20; - - -static CFMutableDictionaryRef lc_code_sig(uint8_t *lc_code_signature, size_t lc_code_signature_len) -{ - CFDataRef codedir = NULL; - CFDataRef message = NULL; - CFMutableDictionaryRef code_signature = - CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - require(code_signature, out); - - CS_SuperBlob *sb = (CS_SuperBlob*)lc_code_signature; - require(ntohl(sb->magic) == CSMAGIC_EMBEDDED_SIGNATURE, out); - uint32_t count; - for (count = 0; count < ntohl(sb->count); count++) { - //uint32_t type = ntohl(sb->index[count].type); - uint32_t offset = ntohl(sb->index[count].offset); - uint8_t *bytes = lc_code_signature + offset; - //fprintf(stderr, "blob[%d]: (type: 0x%.08x, offset: %p)\n", count, type, (void*)offset); - uint32_t magic = ntohl(*(uint32_t*)bytes); - uint32_t length = ntohl(*(uint32_t*)(bytes+4)); - //fprintf(stderr, " magic: 0x%.08x length: %d\n", magic, length); - switch(magic) { - case 0xfade0c01: //write_data("requirements", bytes, length); - break; - case 0xfade0c02: //write_data("codedir", bytes, length); - codedir = CFDataCreate(kCFAllocatorDefault, bytes, length); - require(codedir, out); - CFDictionarySetValue(code_signature, CFSTR("CodeDirectory"), codedir); - CFRelease(codedir); - uint8_t *cursor = bytes; - require_string(htonl(*(uint32_t*)(cursor+8)) >= 0x20001, out, "incompatible version"); - require_string(htonl(*(uint32_t*)(cursor+8)) <= 0x2F000, out, "incompatible version"); - uint32_t hash_offset = htonl(*(uint32_t*)(cursor+16)); - require_string(htonl(*(uint32_t*)(cursor+24)) >= 5, out, "no entitlements slot yet"); - require_string(*(cursor+36) == 20, out, "unexpected hash size"); - require_string(*(cursor+37) == 1, out, "unexpected hash type"); - message = CFDataCreate(kCFAllocatorDefault, cursor+hash_offset-5*20, 20); - require(message, out); - CFDictionarySetValue(code_signature, CFSTR("EntitlementsCDHash"), message); - CFRelease(message); - break; - case 0xfade0b01: //write_data("signed", lc_code_signature, bytes-lc_code_signature); - if (length == 8) { - fprintf(stderr, "Ad-hoc signed binary\n"); - goto out; - } else { - message = CFDataCreate(kCFAllocatorDefault, bytes+8, length-8); - require(message, out); - CFDictionarySetValue(code_signature, CFSTR("SignedData"), message); - CFRelease(message); - } - break; - case 0xfade7171: - { - unsigned char digest[CC_SHA1_DIGEST_LENGTH]; - CCDigest(kCCDigestSHA1, bytes, length, digest); - message = CFDataCreate(kCFAllocatorDefault, digest, sizeof(digest)); - require(message, out); - CFDictionarySetValue(code_signature, CFSTR("EntitlementsHash"), message); - CFRelease(message); - message = CFDataCreate(kCFAllocatorDefault, bytes+8, length-8); - require(message, out); - CFDictionarySetValue(code_signature, CFSTR("Entitlements"), message); - CFRelease(message); - break; - } - default: - fprintf(stderr, "Skipping block with magic: 0x%x\n", magic); - break; - } - } - return code_signature; -out: - if (code_signature) CFRelease(code_signature); - return NULL; -} - -#if 1 -static FILE * -open_bundle(const char * path, const char * mode) -{ - char full_path[1024] = {}; - CFStringRef path_cfstring = NULL; - CFURLRef path_url = NULL; - CFBundleRef bundle = NULL; - - path_cfstring = CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path); - require(path_cfstring, out); - path_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_cfstring, kCFURLPOSIXPathStyle, true); - require(path_url, out); - bundle = CFBundleCreate(kCFAllocatorDefault, path_url); - require(bundle, out); - CFURLRef exec = CFBundleCopyExecutableURL(bundle); - require(exec, out); - require(CFURLGetFileSystemRepresentation(exec, true, (uint8_t*)full_path, sizeof(full_path)), out); -out: - if (path_cfstring) CFRelease(path_cfstring); - if (path_url) CFRelease(path_url); - if (bundle) CFRelease(bundle); - - return fopen(full_path, "r"); -} -#else -static FILE * -open_bundle(const char *path, const char *mode) -{ - char full_path[1024] = {}; - const char *slash; - char *dot; - slash = rindex(path, '/'); - if (!slash) slash = path; - require(strlcpy(full_path, path, sizeof(full_path)) < sizeof(full_path), out); - require(strlcat(full_path, "/", sizeof(full_path)), out); - require(strlcat(full_path, slash, sizeof(full_path)), out); - require(dot = rindex(full_path, '.'), out); - *dot = '\0'; - return fopen(full_path, "r"); -out: - return NULL; -} -#endif - -CFMutableDictionaryRef load_code_signature(FILE *binary, size_t slice_offset) -{ - bool signature_found = false; - CFMutableDictionaryRef result = NULL; - union { - struct load_command lc; - struct linkedit_data_command le_lc; - } cmd; - do { - require(1 == fread(&cmd.lc, sizeof(cmd.lc), 1, binary), out); - if (cmd.lc.cmd == LC_CODE_SIGNATURE) { - require(1 == fread((uint8_t *)&cmd.lc + sizeof(cmd.lc), sizeof(cmd.le_lc) - sizeof(cmd.lc), 1, binary), out); - require_noerr(fseek(binary, slice_offset+cmd.le_lc.dataoff, SEEK_SET), out); - size_t length = cmd.le_lc.datasize; - uint8_t *data = malloc(length); - require(length && data, out); - require(1 == fread(data, length, 1, binary), out); - signature_found = true; - result = lc_code_sig(data, length); - free(data); - break; - } - require_noerr(fseek(binary, cmd.lc.cmdsize-sizeof(cmd.lc), SEEK_CUR), out); - } while(cmd.lc.cmd || cmd.lc.cmdsize); /* count lc */ -out: - if (!signature_found) - fprintf(stderr, "No LC_CODE_SIGNATURE segment found\n"); - return result; -} - -CFArrayRef load_code_signatures(const char *path) -{ - bool fully_parsed_binary = false; - CFMutableDictionaryRef result = NULL; - CFMutableArrayRef results = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - - FILE *binary = open_bundle(path, "r"); - require(binary, out); - - struct mach_header header; - require(1 == fread(&header, sizeof(header), 1, binary), out); - if (header.magic == 0xfeedface) { - result = load_code_signature(binary, 0 /*non fat*/); - require(result, out); - CFArrayAppendValue(results, result); - } - else - { - struct fat_header fat; - require(!fseek(binary, 0L, SEEK_SET), out); - require(1 == fread(&fat, sizeof(fat), 1, binary), out); - require(htonl(fat.magic) == FAT_MAGIC, out); - uint32_t slice, slices = htonl(fat.nfat_arch); - struct fat_arch *archs = calloc(slices, sizeof(struct fat_arch)); - require(slices == fread(archs, sizeof(struct fat_arch), slices, binary), out); - for (slice = 0; slice < slices; slice++) { - uint32_t slice_offset = htonl(archs[slice].offset); - require(!fseek(binary, slice_offset, SEEK_SET), out); - require(1 == fread(&header, sizeof(header), 1, binary), out); - require(header.magic == 0xfeedface, out); - result = load_code_signature(binary, slice_offset); - require(result, out); - CFArrayAppendValue(results, result); - CFRelease(result); - } - } - fully_parsed_binary = true; -out: - if (!fully_parsed_binary) { - if (results) { - CFRelease(results); - results = NULL; - } - } - if (binary) - fclose(binary); - return results; -}