diff --git a/Podfile.lock b/Podfile.lock index 3ae641b9b..05cec605f 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -168,7 +168,7 @@ SPEC CHECKSUMS: PureLayout: 4d550abe49a94f24c2808b9b95db9131685fe4cd Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c - SignalServiceKit: bfac5572f3a1ff8a853ead9b5413274a075f3cb4 + SignalServiceKit: 1594ae26a08129175c6ca91690602aa47898f24c SocketRocket: dbb1554b8fc288ef8ef370d6285aeca7361be31e SQLCipher: 43d12c0eb9c57fb438749618fc3ce0065509a559 TwistedOakCollapsingFutures: f359b90f203e9ab13dfb92c9ff41842a7fe1cd0c diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 324703f87..5a1e56b02 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -2090,6 +2090,7 @@ "${PODS_ROOT}/SAMKeychain/Support/SAMKeychain.bundle", "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/textsecure.cer", "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/GIAG2.crt", + "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/GTSGIAG3.crt", ); name = "[CP] Copy Pods Resources"; outputPaths = ( diff --git a/SignalServiceKit.podspec b/SignalServiceKit.podspec index b71357df1..5c2cf8eae 100644 --- a/SignalServiceKit.podspec +++ b/SignalServiceKit.podspec @@ -28,7 +28,8 @@ An Objective-C library for communicating with the Signal messaging service. s.source_files = 'SignalServiceKit/src/**/*.{h,m,mm}' s.resources = ['SignalServiceKit/src/Security/PinningCertificate/textsecure.cer', - 'SignalServiceKit/src/Security/PinningCertificate/GIAG2.crt'] + 'SignalServiceKit/src/Security/PinningCertificate/GIAG2.crt', + 'SignalServiceKit/src/Security/PinningCertificate/GTSGIAG3.crt'] s.prefix_header_file = 'SignalServiceKit/src/TSPrefix.h' s.xcconfig = { 'OTHER_CFLAGS' => '$(inherited) -DSQLITE_HAS_CODEC' } diff --git a/SignalServiceKit/src/Network/OWSSignalService.m b/SignalServiceKit/src/Network/OWSSignalService.m index 037ab126c..90fee8fb0 100644 --- a/SignalServiceKit/src/Network/OWSSignalService.m +++ b/SignalServiceKit/src/Network/OWSSignalService.m @@ -5,6 +5,7 @@ #import "OWSSignalService.h" #import "NSNotificationCenter+OWS.h" #import "OWSCensorshipConfiguration.h" +#import "OWSError.h" #import "OWSHTTPSecurityPolicy.h" #import "TSAccountManager.h" #import "TSConstants.h" @@ -259,35 +260,63 @@ NSString *const kNSNotificationName_IsCensorshipCircumventionActiveDidChange = #pragma mark - Google Pinning Policy ++ (nullable NSData *)certificateDataWithName:(NSString *)name error:(NSError **)error +{ + if (!name.length) { + OWSFail(@"%@ expected name with length > 0", self.tag); + *error = OWSErrorMakeAssertionError(); + return nil; + } + + NSString *path = [NSBundle.mainBundle pathForResource:name ofType:@"crt"]; + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + OWSFail(@"%@ Missing certificate for name: %@", self.tag, name); + *error = OWSErrorMakeAssertionError(); + return nil; + } + + NSData *_Nullable certData = [NSData dataWithContentsOfFile:path options:0 error:error]; + + if (*error != nil) { + OWSFail(@"%@ Failed to read cert file with path: %@", self.tag, path); + return nil; + } + + if (certData.length == 0) { + OWSFail(@"%@ empty certData for name: %@", self.tag, name); + return nil; + } + + DDLogVerbose(@"%@ read cert data with name: %@ length: %lu", self.tag, name, (unsigned long)certData.length); + return certData; +} + /** * We use the Google Pinning Policy when connecting to our censorship circumventing reflector, * which is hosted on Google. */ -+ (AFSecurityPolicy *)googlePinningPolicy { ++ (AFSecurityPolicy *)googlePinningPolicy +{ static AFSecurityPolicy *securityPolicy = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSError *error; - NSString *path = [NSBundle.mainBundle pathForResource:@"GIAG2" ofType:@"crt"]; - - if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { - @throw [NSException - exceptionWithName:@"Missing server certificate" - reason:[NSString stringWithFormat:@"Missing signing certificate for service googlePinningPolicy"] - userInfo:nil]; + NSData *GIAG2CertData = [self certificateDataWithName:@"GIAG2" error:&error]; + if (error) { + DDLogError(@"%@ Failed to get GIAG2 certificate data with error: %@", self.tag, error); + @throw [NSException exceptionWithName:@"OWSSignalService_UnableToReadCertificate" + reason:error.description + userInfo:nil]; } - - NSData *googleCertData = [NSData dataWithContentsOfFile:path options:0 error:&error]; - if (!googleCertData) { - if (error) { - @throw [NSException exceptionWithName:@"OWSSignalServiceHTTPSecurityPolicy" reason:@"Couln't read google pinning cert" userInfo:nil]; - } else { - NSString *reason = [NSString stringWithFormat:@"Reading google pinning cert faile with error: %@", error]; - @throw [NSException exceptionWithName:@"OWSSignalServiceHTTPSecurityPolicy" reason:reason userInfo:nil]; - } + NSData *GTSGIAG3CertData = [self certificateDataWithName:@"GTSGIAG3" error:&error]; + if (error) { + DDLogError(@"%@ Failed to get GIAG3 certificate data with error: %@", self.tag, error); + @throw [NSException exceptionWithName:@"OWSSignalService_UnableToReadCertificate" + reason:error.description + userInfo:nil]; } - - NSSet *certificates = [NSSet setWithObject:googleCertData]; + + NSSet *certificates = [NSSet setWithArray:@[ GIAG2CertData, GTSGIAG3CertData ]]; securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:certificates]; }); return securityPolicy; diff --git a/SignalServiceKit/src/Security/PinningCertificate/GTSGIAG3.crt b/SignalServiceKit/src/Security/PinningCertificate/GTSGIAG3.crt new file mode 100644 index 000000000..ffb1a0ff9 Binary files /dev/null and b/SignalServiceKit/src/Security/PinningCertificate/GTSGIAG3.crt differ