session-ios/SignalUtilitiesKit/OWSHTTPSecurityPolicy.m

107 lines
3.0 KiB
Objective-C

//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "OWSHTTPSecurityPolicy.h"
#import <AssertMacros.h>
#import <SessionProtocolKit/SessionProtocolKit.h>
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