138 lines
3.9 KiB
Objective-C
138 lines
3.9 KiB
Objective-C
//
|
|
// CryptoBox.m
|
|
// TunnelKit
|
|
//
|
|
// Created by Davide De Rosa on 2/4/17.
|
|
// Copyright © 2018 London Trust Media. All rights reserved.
|
|
//
|
|
|
|
#import <openssl/evp.h>
|
|
#import <openssl/hmac.h>
|
|
#import <openssl/rand.h>
|
|
|
|
#import "CryptoBox.h"
|
|
#import "CryptoMacros.h"
|
|
#import "Allocation.h"
|
|
#import "Errors.h"
|
|
|
|
#import "CryptoCBC.h"
|
|
#import "CryptoAEAD.h"
|
|
|
|
@interface CryptoBox ()
|
|
|
|
@property (nonatomic, strong) NSString *cipherAlgorithm;
|
|
@property (nonatomic, strong) NSString *digestAlgorithm;
|
|
|
|
@property (nonatomic, strong) id<Encrypter> encrypter;
|
|
@property (nonatomic, strong) id<Decrypter> decrypter;
|
|
|
|
@end
|
|
|
|
@implementation CryptoBox
|
|
|
|
+ (void)initialize
|
|
{
|
|
}
|
|
|
|
+ (BOOL)preparePRNGWithSeed:(const uint8_t *)seed length:(NSInteger)length
|
|
{
|
|
unsigned char x[1];
|
|
// make sure its initialized before seeding
|
|
if (RAND_bytes(x, 1) != 1) {
|
|
return NO;
|
|
}
|
|
RAND_seed(seed, (int)length);
|
|
return YES;
|
|
}
|
|
|
|
- (instancetype)initWithCipherAlgorithm:(NSString *)cipherAlgorithm digestAlgorithm:(NSString *)digestAlgorithm
|
|
{
|
|
NSParameterAssert(cipherAlgorithm);
|
|
// NSParameterAssert(digestAlgorithm);
|
|
|
|
if ((self = [super init])) {
|
|
self.cipherAlgorithm = [cipherAlgorithm lowercaseString];
|
|
self.digestAlgorithm = [digestAlgorithm lowercaseString];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
self.encrypter = nil;
|
|
self.decrypter = nil;
|
|
}
|
|
|
|
// these keys are coming from the OpenVPN negotiation despite the cipher
|
|
- (BOOL)configureWithCipherEncKey:(ZeroingData *)cipherEncKey
|
|
cipherDecKey:(ZeroingData *)cipherDecKey
|
|
hmacEncKey:(ZeroingData *)hmacEncKey
|
|
hmacDecKey:(ZeroingData *)hmacDecKey
|
|
error:(NSError *__autoreleasing *)error
|
|
{
|
|
NSParameterAssert(cipherEncKey);
|
|
NSParameterAssert(cipherDecKey);
|
|
NSParameterAssert(hmacEncKey);
|
|
NSParameterAssert(hmacDecKey);
|
|
|
|
if ([self.cipherAlgorithm hasSuffix:@"-cbc"]) {
|
|
if (!self.digestAlgorithm) {
|
|
if (error) {
|
|
*error = TunnelKitErrorWithCode(TunnelKitErrorCodeCryptoBoxAlgorithm);
|
|
}
|
|
return NO;
|
|
}
|
|
CryptoCBC *cbc = [[CryptoCBC alloc] initWithCipherName:self.cipherAlgorithm
|
|
digestName:self.digestAlgorithm];
|
|
self.encrypter = cbc;
|
|
self.decrypter = cbc;
|
|
}
|
|
else if ([self.cipherAlgorithm hasSuffix:@"-gcm"]) {
|
|
CryptoAEAD *gcm = [[CryptoAEAD alloc] initWithCipherName:self.cipherAlgorithm];
|
|
self.encrypter = gcm;
|
|
self.decrypter = gcm;
|
|
}
|
|
// not supported
|
|
else {
|
|
if (error) {
|
|
*error = TunnelKitErrorWithCode(TunnelKitErrorCodeCryptoBoxAlgorithm);
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
[self.encrypter configureEncryptionWithCipherKey:cipherEncKey hmacKey:hmacEncKey];
|
|
[self.decrypter configureDecryptionWithCipherKey:cipherDecKey hmacKey:hmacDecKey];
|
|
|
|
return YES;
|
|
}
|
|
|
|
+ (BOOL)hmacWithDigestName:(NSString *)digestName
|
|
secret:(const uint8_t *)secret
|
|
secretLength:(NSInteger)secretLength
|
|
data:(const uint8_t *)data
|
|
dataLength:(NSInteger)dataLength
|
|
hmac:(uint8_t *)hmac
|
|
hmacLength:(NSInteger *)hmacLength
|
|
error:(NSError **)error
|
|
{
|
|
NSParameterAssert(digestName);
|
|
NSParameterAssert(secret);
|
|
NSParameterAssert(data);
|
|
|
|
unsigned int l = 0;
|
|
int code = 1;
|
|
|
|
HMAC_CTX *ctx = HMAC_CTX_new();
|
|
TUNNEL_CRYPTO_TRACK_STATUS(code) HMAC_CTX_reset(ctx);
|
|
TUNNEL_CRYPTO_TRACK_STATUS(code) HMAC_Init_ex(ctx, secret, (int)secretLength, EVP_get_digestbyname([digestName cStringUsingEncoding:NSASCIIStringEncoding]), NULL);
|
|
TUNNEL_CRYPTO_TRACK_STATUS(code) HMAC_Update(ctx, data, dataLength);
|
|
TUNNEL_CRYPTO_TRACK_STATUS(code) HMAC_Final(ctx, hmac, &l);
|
|
HMAC_CTX_free(ctx);
|
|
|
|
*hmacLength = l;
|
|
|
|
TUNNEL_CRYPTO_RETURN_STATUS(code)
|
|
}
|
|
|
|
@end
|