diff --git a/MessagesBridge.xcodeproj/project.pbxproj b/MessagesBridge.xcodeproj/project.pbxproj index bddcc17..4147485 100644 --- a/MessagesBridge.xcodeproj/project.pbxproj +++ b/MessagesBridge.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + CD14F185219E2A6800E7DD22 /* NSData+AES.m in Sources */ = {isa = PBXBuildFile; fileRef = CD14F184219E2A6800E7DD22 /* NSData+AES.m */; }; + CD14F18E219E2DB400E7DD22 /* CryptoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CD14F18D219E2DB400E7DD22 /* CryptoTests.m */; }; + CD14F194219E2F9C00E7DD22 /* NSData+AES.m in Sources */ = {isa = PBXBuildFile; fileRef = CD14F184219E2A6800E7DD22 /* NSData+AES.m */; }; CD602056219B5DFD0024D9C5 /* MBIMBridgeOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = CD602055219B5DFD0024D9C5 /* MBIMBridgeOperation.m */; }; CD60205C219B623F0024D9C5 /* MBIMMessagesListOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = CD60205B219B623F0024D9C5 /* MBIMMessagesListOperation.m */; }; CD60205F219B674B0024D9C5 /* MBIMConversationListOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = CD60205E219B674B0024D9C5 /* MBIMConversationListOperation.m */; }; @@ -114,6 +117,11 @@ 1A33B43C219A5ACD0034485A /* OSXDebugDefaults.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = OSXDebugDefaults.xcconfig; sourceTree = ""; }; 1A33B43D219A5ACD0034485A /* ReleaseDefaults.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = ReleaseDefaults.xcconfig; sourceTree = ""; }; 1A33B43E219A5BD80034485A /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + CD14F183219E2A6800E7DD22 /* NSData+AES.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSData+AES.h"; sourceTree = ""; }; + CD14F184219E2A6800E7DD22 /* NSData+AES.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSData+AES.m"; sourceTree = ""; }; + CD14F18B219E2DB400E7DD22 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + CD14F18D219E2DB400E7DD22 /* CryptoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CryptoTests.m; sourceTree = ""; }; + CD14F18F219E2DB400E7DD22 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; CD602054219B5DFD0024D9C5 /* MBIMBridgeOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MBIMBridgeOperation.h; sourceTree = ""; }; CD602055219B5DFD0024D9C5 /* MBIMBridgeOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MBIMBridgeOperation.m; sourceTree = ""; }; CD60205A219B623F0024D9C5 /* MBIMMessagesListOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MBIMMessagesListOperation.h; sourceTree = ""; }; @@ -135,6 +143,13 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + CD14F188219E2DB400E7DD22 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; CD83E15F219BE91500F4CCEA /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -165,6 +180,7 @@ 1A33B439219A5ACD0034485A /* Config Files */, 1A0C445C219A457C00F2AC00 /* Pilfered Headers */, CD83E162219BE91600F4CCEA /* agentHook */, + CD14F18C219E2DB400E7DD22 /* Tests */, 1A0C4448219A38E100F2AC00 /* Products */, 1A0C445E219A45B400F2AC00 /* Frameworks */, ); @@ -175,6 +191,7 @@ children = ( CDF62332219A895D00690038 /* kordophoned */, CD83E161219BE91500F4CCEA /* libagentHook.dylib */, + CD14F18B219E2DB400E7DD22 /* Tests.xctest */, ); name = Products; sourceTree = ""; @@ -222,6 +239,24 @@ path = "Config Files"; sourceTree = ""; }; + CD14F182219E2A4C00E7DD22 /* Crypto */ = { + isa = PBXGroup; + children = ( + CD14F183219E2A6800E7DD22 /* NSData+AES.h */, + CD14F184219E2A6800E7DD22 /* NSData+AES.m */, + ); + path = Crypto; + sourceTree = ""; + }; + CD14F18C219E2DB400E7DD22 /* Tests */ = { + isa = PBXGroup; + children = ( + CD14F18D219E2DB400E7DD22 /* CryptoTests.m */, + CD14F18F219E2DB400E7DD22 /* Info.plist */, + ); + path = Tests; + sourceTree = ""; + }; CD60204C219B5D710024D9C5 /* Operations */ = { isa = PBXGroup; children = ( @@ -272,6 +307,7 @@ CDF62333219A895D00690038 /* kordophone */ = { isa = PBXGroup; children = ( + CD14F182219E2A4C00E7DD22 /* Crypto */, CD83E150219BDB4F00F4CCEA /* Hooking */, 1A0C446D219A4BCD00F2AC00 /* Bridge */, CDF62334219A895D00690038 /* main.m */, @@ -292,6 +328,23 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + CD14F18A219E2DB400E7DD22 /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = CD14F190219E2DB400E7DD22 /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + CD14F187219E2DB400E7DD22 /* Sources */, + CD14F188219E2DB400E7DD22 /* Frameworks */, + CD14F189219E2DB400E7DD22 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = Tests; + productReference = CD14F18B219E2DB400E7DD22 /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; CD83E160219BE91500F4CCEA /* agentHook */ = { isa = PBXNativeTarget; buildConfigurationList = CD83E167219BE91600F4CCEA /* Build configuration list for PBXNativeTarget "agentHook" */; @@ -337,6 +390,9 @@ LastUpgradeCheck = 1100; ORGANIZATIONNAME = "James Magahern"; TargetAttributes = { + CD14F18A219E2DB400E7DD22 = { + CreatedOnToolsVersion = 11.0; + }; CD83E160219BE91500F4CCEA = { CreatedOnToolsVersion = 11.0; }; @@ -366,6 +422,7 @@ targets = ( CDF62331219A895D00690038 /* kordophoned */, CD83E160219BE91500F4CCEA /* agentHook */, + CD14F18A219E2DB400E7DD22 /* Tests */, ); }; /* End PBXProject section */ @@ -422,7 +479,26 @@ }; /* End PBXReferenceProxy section */ +/* Begin PBXResourcesBuildPhase section */ + CD14F189219E2DB400E7DD22 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ + CD14F187219E2DB400E7DD22 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CD14F194219E2F9C00E7DD22 /* NSData+AES.m in Sources */, + CD14F18E219E2DB400E7DD22 /* CryptoTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; CD83E15E219BE91500F4CCEA /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -440,6 +516,7 @@ CDF6233A219A8A5600690038 /* MBIMBridge.m in Sources */, CDF62335219A895D00690038 /* main.m in Sources */, CD60205C219B623F0024D9C5 /* MBIMMessagesListOperation.m in Sources */, + CD14F185219E2A6800E7DD22 /* NSData+AES.m in Sources */, CD602062219B68950024D9C5 /* MBIMSendMessageOperation.m in Sources */, CD602056219B5DFD0024D9C5 /* MBIMBridgeOperation.m in Sources */, CD60205F219B674B0024D9C5 /* MBIMConversationListOperation.m in Sources */, @@ -581,6 +658,40 @@ }; name = Release; }; + CD14F191219E2DB400E7DD22 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + CD14F192219E2DB400E7DD22 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; CD83E168219BE91600F4CCEA /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -655,6 +766,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + CD14F190219E2DB400E7DD22 /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CD14F191219E2DB400E7DD22 /* Debug */, + CD14F192219E2DB400E7DD22 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; CD83E167219BE91600F4CCEA /* Build configuration list for PBXNativeTarget "agentHook" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Tests/CryptoTests.m b/Tests/CryptoTests.m new file mode 100644 index 0000000..eca7828 --- /dev/null +++ b/Tests/CryptoTests.m @@ -0,0 +1,48 @@ +// +// Tests.m +// Tests +// +// Created by James Magahern on 11/15/18. +// Copyright © 2018 James Magahern. All rights reserved. +// + +#import + +#import "NSData+AES.h" + +// base64 encoded +static NSString *const kTestKey = @"QMeDmiHj8eCFVfrQWQfDpw=="; + +@interface Tests : XCTestCase +@property (nonatomic, strong) NSString *commonPayload; +@property (nonatomic, strong) NSData *commonIVData; +@property (nonatomic, strong) NSData *symmetricKeyData; +@end + +@implementation Tests + +- (void)setUp { + self.commonPayload = @"Hey this is a test"; + + NSString *IVDataString = [[NSUUID UUID] UUIDString]; + self.commonIVData = [IVDataString dataUsingEncoding:NSUTF8StringEncoding]; + + self.symmetricKeyData = [[NSData alloc] initWithBase64EncodedString:kTestKey options:0]; + XCTAssert(self.commonIVData && self.symmetricKeyData); +} + +- (void)testEncryptionAndDecryption +{ + NSData *inputData = [self.commonPayload dataUsingEncoding:NSUTF8StringEncoding]; + + NSError *error = nil; + NSData *encryptedData = [inputData encryptedDataWithKey:self.symmetricKeyData iv:self.commonIVData error:&error]; + XCTAssert(!error); + + NSData *decryptedData = [encryptedData decryptedDataWithKey:self.symmetricKeyData iv:self.commonIVData error:&error]; + XCTAssert(!error); + + XCTAssert([decryptedData isEqualToData:inputData]); +} + +@end diff --git a/Tests/Info.plist b/Tests/Info.plist new file mode 100644 index 0000000..6c40a6c --- /dev/null +++ b/Tests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/kordophone/Crypto/NSData+AES.h b/kordophone/Crypto/NSData+AES.h new file mode 100644 index 0000000..7530ba7 --- /dev/null +++ b/kordophone/Crypto/NSData+AES.h @@ -0,0 +1,17 @@ +// +// NSData+AES.h +// MessagesBridge +// +// Created by James Magahern on 11/15/18. +// Copyright © 2018 James Magahern. All rights reserved. +// + +#import +#import + +@interface NSData (AES) + +- (NSData *)encryptedDataWithKey:(NSData *)key iv:(NSData *)iv error:(NSError **)error; +- (NSData *)decryptedDataWithKey:(NSData *)key iv:(NSData *)iv error:(NSError **)error; + +@end diff --git a/kordophone/Crypto/NSData+AES.m b/kordophone/Crypto/NSData+AES.m new file mode 100644 index 0000000..d69614c --- /dev/null +++ b/kordophone/Crypto/NSData+AES.m @@ -0,0 +1,58 @@ +// +// NSData+AES.m +// MessagesBridge +// +// Created by James Magahern on 11/15/18. +// Copyright © 2018 James Magahern. All rights reserved. +// + +#import "NSData+AES.h" + +@implementation NSData (AES) + ++ (NSData *)AES128Operation:(CCOperation)operation + withInputData:(NSData *)inputData + key:(NSData *)key + iv:(NSData *)iv + error:(NSError **)error +{ + size_t dataMoved = 0; + NSMutableData *outputData = [NSMutableData dataWithLength:(inputData.length + kCCBlockSizeAES128)]; + CCCryptorStatus status = CCCrypt( + operation, + kCCAlgorithmAES, + kCCOptionPKCS7Padding, + key.bytes, + key.length, + iv.bytes, + inputData.bytes, + inputData.length, + outputData.mutableBytes, + outputData.length, + &dataMoved + ); + + if (status == kCCSuccess) { + outputData.length = dataMoved; + } else { + *error = [NSError errorWithDomain:@"CommonCryptoError" + code:status + userInfo:nil]; + + outputData = nil; + } + + return outputData; +} + +- (NSData *)encryptedDataWithKey:(NSData *)key iv:(NSData *)iv error:(NSError *__autoreleasing *)error +{ + return [[self class] AES128Operation:kCCEncrypt withInputData:self key:key iv:iv error:error]; +} + +- (NSData *)decryptedDataWithKey:(NSData *)key iv:(NSData *)iv error:(NSError *__autoreleasing *)error +{ + return [[self class] AES128Operation:kCCDecrypt withInputData:self key:key iv:iv error:error]; +} + +@end