// // Copyright (c) 2019 Open Whisper Systems. All rights reserved. // #import "OWSHTTPSecurityPolicy.h" #import #import NS_ASSUME_NONNULL_BEGIN @implementation OWSHTTPSecurityPolicy + (instancetype)sharedPolicy { static OWSHTTPSecurityPolicy *httpSecurityPolicy = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ httpSecurityPolicy = [[self alloc] initWithOWSPolicy]; }); return httpSecurityPolicy; } - (instancetype)initWithOWSPolicy { self = [[super class] defaultPolicy]; if (self) { self.pinnedCertificates = [NSSet setWithArray:@[ [self.class certificateDataForService:@"textsecure"] ]]; } return self; } + (NSData *)dataFromCertificateFileForService:(NSString *)service { NSBundle *bundle = [NSBundle bundleForClass:self.class]; NSString *path = [bundle pathForResource:service ofType:@"cer"]; if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { OWSFail(@"Missing signing certificate for service %@", service); } NSData *data = [NSData dataWithContentsOfFile:path]; OWSAssert(data.length > 0); return data; } + (NSData *)certificateDataForService:(NSString *)service { SecCertificateRef certRef = [self certificateForService:service]; return (__bridge_transfer NSData *)SecCertificateCopyData(certRef); } + (SecCertificateRef)certificateForService:(NSString *)service { NSData *certificateData = [self dataFromCertificateFileForService:service]; return SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(certificateData)); } - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(nullable NSString *)domain { NSMutableArray *policies = [NSMutableArray array]; [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)]; if (SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies) != errSecSuccess) { OWSLogError(@"The trust policy couldn't be set."); return NO; } NSMutableArray *pinnedCertificates = [NSMutableArray array]; for (NSData *certificateData in self.pinnedCertificates) { [pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)]; } if (SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates) != errSecSuccess) { OWSLogError(@"The anchor certificates couldn't be set."); return NO; } if (!AFServerTrustIsValid(serverTrust)) { return NO; } return YES; } static BOOL AFServerTrustIsValid(SecTrustRef serverTrust) { BOOL isValid = NO; SecTrustResultType result; __Require_noErr_Quiet(SecTrustEvaluate(serverTrust, &result), _out); isValid = (result == kSecTrustResultUnspecified); _out: return isValid; } NSData *SSKTextSecureServiceCertificateData() { return [OWSHTTPSecurityPolicy dataFromCertificateFileForService:@"textsecure"]; } @end NS_ASSUME_NONNULL_END