bool Type::IsValidPropertyList( PropertyListFormat format ) const { CFPropertyListFormat cfFormat; cfFormat = kCFPropertyListXMLFormat_v1_0; if( format == PropertyListFormatBinary ) { cfFormat = kCFPropertyListBinaryFormat_v1_0; } return this->IsValid() && CFPropertyListIsValid( this->GetCFObject(), cfFormat ); }
void StartMux() { MuxAgent = USBMuxAgentCreate(); if (MuxAgent) { MuxAgent->socket = SDM_USBMux_SocketCreate(); MuxAgent->socketSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, MuxAgent->socket, 0x0, MuxAgent->socketQueue); dispatch_source_set_event_handler(MuxAgent->socketSource, ^{ struct USBMuxPacket *packet = (struct USBMuxPacket *)calloc(0x1, sizeof(struct USBMuxPacket)); USBMuxReceive(MuxAgent->socket, packet); if (CFPropertyListIsValid(packet->payload, kCFPropertyListXMLFormat_v1_0)) { if (CFDictionaryContainsKey(packet->payload, CFSTR("MessageType"))) { CFStringRef type = CFDictionaryGetValue(packet->payload, CFSTR("MessageType")); if (CFStringCompare(type, USBMuxPacketMessage[kUSBMuxPacketResultType], 0x0) == 0x0) { } else if (CFStringCompare(type, USBMuxPacketMessage[kUSBMuxPacketAttachType], 0x0) == 0x0) { } else if (CFStringCompare(type, USBMuxPacketMessage[kUSBMuxPacketDetachType], 0x0) == 0x0) { } } else { if (CFDictionaryContainsKey(packet->payload, CFSTR("Logs"))) { } else if (CFDictionaryContainsKey(packet->payload, CFSTR("DeviceList"))) { } else if (CFDictionaryContainsKey(packet->payload, CFSTR("ListenerList"))) { } else { } } } else { printf("socketSourceEventHandler: failed to decodeCFPropertyList from packet payload\n"); } }); dispatch_source_set_cancel_handler(MuxAgent->socketSource, ^{ printf("socketSourceEventCancelHandler: source canceled\n"); });
int read_plist( char *plpath, CFDictionaryRef *dr ) { CFURLRef cfurl = NULL; CFReadStreamRef cfrs = NULL; CFDictionaryRef cfdict = NULL; CFPropertyListFormat fmt = kCFPropertyListXMLFormat_v1_0; CFStreamError err; int rc = 0; char respath[ MAXPATHLEN ]; if ( plpath == NULL ) { fprintf( stderr, "%s: Invalid plist path\n", __FUNCTION__ ); return( -1 ); } if ( realpath( plpath, respath ) == NULL ) { fprintf( stderr, "%s: realpath failed: %s\n", __FUNCTION__, strerror( errno )); return( -1 ); } /* * must convert C string path to CFURL to read the plist * from disk. no convenience methods here like Cocoa's * -dictionaryWithContentsOfFile: */ if (( cfurl = CFURLCreateFromFileSystemRepresentation( kCFAllocatorDefault, ( const UInt8 * )respath, ( CFIndex )strlen( respath ), false )) == NULL ) { fprintf( stderr, "%s: failed to create URL for %s\n", __FUNCTION__, respath ); return( -1 ); } if (( cfrs = CFReadStreamCreateWithFile( kCFAllocatorDefault, cfurl )) == NULL ) { fprintf( stderr, "%s: failed to create read stream\n", __FUNCTION__ ); rc = -1; goto cleanup; } if ( CFReadStreamOpen( cfrs ) == false ) { err = CFReadStreamGetError( cfrs ); fprintf( stderr, "%s: failed to open read stream\n", __FUNCTION__ ); if ( err.domain == kCFStreamErrorDomainPOSIX ) { fprintf( stderr, "%s: %s\n", plpath, strerror( errno )); } else { fprintf( stderr, "domain %d, error %d\n", ( int )err.domain, ( int )err.error ); } rc = -1; goto cleanup; } if (( cfdict = CFPropertyListCreateWithStream( kCFAllocatorDefault, cfrs, 0, kCFPropertyListImmutable, &fmt, NULL )) == NULL ) { fprintf( stderr, "%s: failed to read plist\n", __FUNCTION__ ); rc = -1; goto cleanup; } if ( !CFPropertyListIsValid( cfdict, fmt )) { fprintf( stderr, "%s: invalid plist\n", plpath ); CFRelease( cfdict ); cfdict = NULL; rc = -1; } cleanup: if ( cfurl != NULL ) { CFRelease( cfurl ); } if ( cfrs != NULL ) { CFReadStreamClose( cfrs ); CFRelease( cfrs ); } *dr = cfdict; return( rc ); }
CFDictionaryRef APCreateDictionaryForLicenseData(CFDataRef data) { if (!rsaKey->n || !rsaKey->e) return NULL; // Make the property list from the data CFStringRef errorString = NULL; CFPropertyListRef propertyList; propertyList = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, data, kCFPropertyListMutableContainers, &errorString); if (errorString || CFDictionaryGetTypeID() != CFGetTypeID(propertyList) || !CFPropertyListIsValid(propertyList, kCFPropertyListXMLFormat_v1_0)) { if (propertyList) CFRelease(propertyList); return NULL; } // Load the signature CFMutableDictionaryRef licenseDictionary = (CFMutableDictionaryRef)propertyList; if (!CFDictionaryContainsKey(licenseDictionary, CFSTR("Signature"))) { CFRelease(licenseDictionary); return NULL; } CFDataRef sigData = CFDictionaryGetValue(licenseDictionary, CFSTR("Signature")); CFIndex sigDataLength = CFDataGetLength(sigData); UInt8 sigBytes[sigDataLength]; CFDataGetBytes(sigData, CFRangeMake(0, sigDataLength), sigBytes); CFDictionaryRemoveValue(licenseDictionary, CFSTR("Signature")); // Decrypt the signature int checkDigestMaxSize = RSA_size(rsaKey)-11; unsigned char checkDigest[checkDigestMaxSize]; if (RSA_public_decrypt((int) sigDataLength, sigBytes, checkDigest, rsaKey, RSA_PKCS1_PADDING) != SHA_DIGEST_LENGTH) { CFRelease(licenseDictionary); return NULL; } // Get the license hash CFMutableStringRef hashCheck = CFStringCreateMutable(kCFAllocatorDefault,0); int hashIndex; for (hashIndex = 0; hashIndex < SHA_DIGEST_LENGTH; hashIndex++) CFStringAppendFormat(hashCheck, nil, CFSTR("%02x"), checkDigest[hashIndex]); APSetHash(hashCheck); CFRelease(hashCheck); if (blacklist && (CFArrayContainsValue(blacklist, CFRangeMake(0, CFArrayGetCount(blacklist)), hash) == true)) return NULL; // Get the number of elements CFIndex count = CFDictionaryGetCount(licenseDictionary); // Load the keys and build up the key array CFMutableArrayRef keyArray = CFArrayCreateMutable(kCFAllocatorDefault, count, NULL); CFStringRef keys[count]; CFDictionaryGetKeysAndValues(licenseDictionary, (const void**)&keys, NULL); int i; for (i = 0; i < count; i++) CFArrayAppendValue(keyArray, keys[i]); // Sort the array int context = kCFCompareCaseInsensitive; CFArraySortValues(keyArray, CFRangeMake(0, count), (CFComparatorFunction)CFStringCompare, &context); // Setup up the hash context SHA_CTX ctx; SHA1_Init(&ctx); // Convert into UTF8 strings for (i = 0; i < count; i++) { char *valueBytes; CFIndex valueLengthAsUTF8; CFStringRef key = CFArrayGetValueAtIndex(keyArray, i); CFStringRef value = CFDictionaryGetValue(licenseDictionary, key); // Account for the null terminator valueLengthAsUTF8 = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value), kCFStringEncodingUTF8) + 1; valueBytes = (char *)malloc(valueLengthAsUTF8); CFStringGetCString(value, valueBytes, valueLengthAsUTF8, kCFStringEncodingUTF8); SHA1_Update(&ctx, valueBytes, strlen(valueBytes)); free(valueBytes); } unsigned char digest[SHA_DIGEST_LENGTH]; SHA1_Final(digest, &ctx); if (keyArray != NULL) CFRelease(keyArray); // Check if the signature is a match for (i = 0; i < SHA_DIGEST_LENGTH; i++) { if (checkDigest[i] ^ digest[i]) { CFRelease(licenseDictionary); return NULL; } } // If it's a match, we return the dictionary; otherwise, we never reach this return licenseDictionary; }
CFDictionaryRef APCreateDictionaryForLicenseData(CFDataRef data) { __block CFPropertyListRef propertyList = NULL; __block CFDataRef hashData = NULL; __block CFErrorRef error = NULL; __block SecTransformRef verifyFunction = NULL; __block CFBooleanRef valid = NULL; void(^cleanup)(void) = ^(void) { if (propertyList != NULL) { CFRelease(propertyList); propertyList = NULL; } if (hashData != NULL) { CFRelease(hashData); hashData = NULL; } if (error != NULL) { CFShow(error); CFRelease(error); error = NULL; } if (verifyFunction != NULL) { CFRelease(verifyFunction); verifyFunction = NULL; } if (valid != NULL) { CFRelease(valid); valid = NULL; } }; if (!publicKeyRef) { CFShow(CFSTR("Public key is invalid")); return NULL; } // Make the property list from the data CFStringRef errorString = NULL; propertyList = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, data, kCFPropertyListMutableContainers, &errorString); if (errorString || CFDictionaryGetTypeID() != CFGetTypeID(propertyList) || !CFPropertyListIsValid(propertyList, kCFPropertyListXMLFormat_v1_0)) { if (propertyList) CFRelease(propertyList); return NULL; } CFMutableDictionaryRef licenseDictionary = (CFMutableDictionaryRef)propertyList; CFDataRef signature = CFDictionaryGetValue(licenseDictionary, CFSTR("Signature")); if (!signature) { CFShow(CFSTR("No signature")); cleanup(); return NULL; } hashData = APCreateHashFromDictionary(licenseDictionary); CFStringRef hashCheck = APCopyHexStringFromData(hashData); APSetHash(hashCheck); CFRelease(hashCheck); // Check the hash against license blacklist if (blacklist && CFArrayContainsValue(blacklist, CFRangeMake(0, CFArrayGetCount(blacklist)), hash)) { cleanup(); return NULL; } // Verify the signed hash using the public key, passing the raw hash data as the input verifyFunction = SecVerifyTransformCreate(publicKeyRef, signature, &error); if (error) { cleanup(); return NULL; } SecTransformSetAttribute(verifyFunction, kSecTransformInputAttributeName, hashData, &error); if (error) { cleanup(); return NULL; } SecTransformSetAttribute(verifyFunction, kSecInputIsAttributeName, kSecInputIsRaw, &error); if (error) { cleanup(); return NULL; } valid = SecTransformExecute(verifyFunction, &error); if (error) { cleanup(); return NULL; } if (valid != kCFBooleanTrue) { cleanup(); return NULL; } CFDictionaryRef resultDict = CFDictionaryCreateCopy(kCFAllocatorDefault, licenseDictionary); cleanup(); return resultDict; }