Merge branch 'refactor-encryption'
This commit is contained in:
commit
1ba7e73e9c
|
@ -11,8 +11,8 @@
|
|||
0E07596020EF6D1400F38FD8 /* CryptoCBC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E07595C20EF6D1400F38FD8 /* CryptoCBC.m */; };
|
||||
0E07596320EF733F00F38FD8 /* CryptoMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E07596120EF733F00F38FD8 /* CryptoMacros.h */; };
|
||||
0E07596420EF733F00F38FD8 /* CryptoMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E07596120EF733F00F38FD8 /* CryptoMacros.h */; };
|
||||
0E07596B20EF79AB00F38FD8 /* Encryption.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E07596A20EF79AB00F38FD8 /* Encryption.h */; };
|
||||
0E07596C20EF79AB00F38FD8 /* Encryption.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E07596A20EF79AB00F38FD8 /* Encryption.h */; };
|
||||
0E07596B20EF79AB00F38FD8 /* Crypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E07596A20EF79AB00F38FD8 /* Crypto.h */; };
|
||||
0E07596C20EF79AB00F38FD8 /* Crypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E07596A20EF79AB00F38FD8 /* Crypto.h */; };
|
||||
0E07596E20EF79B400F38FD8 /* CryptoCBC.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E07596D20EF79B400F38FD8 /* CryptoCBC.h */; };
|
||||
0E07596F20EF79B400F38FD8 /* CryptoCBC.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E07596D20EF79B400F38FD8 /* CryptoCBC.h */; };
|
||||
0E07597E20F0060E00F38FD8 /* CryptoAEAD.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E07597C20F0060E00F38FD8 /* CryptoAEAD.h */; };
|
||||
|
@ -185,7 +185,7 @@
|
|||
/* Begin PBXFileReference section */
|
||||
0E07595C20EF6D1400F38FD8 /* CryptoCBC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CryptoCBC.m; sourceTree = "<group>"; };
|
||||
0E07596120EF733F00F38FD8 /* CryptoMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoMacros.h; sourceTree = "<group>"; };
|
||||
0E07596A20EF79AB00F38FD8 /* Encryption.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Encryption.h; sourceTree = "<group>"; };
|
||||
0E07596A20EF79AB00F38FD8 /* Crypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Crypto.h; sourceTree = "<group>"; };
|
||||
0E07596D20EF79B400F38FD8 /* CryptoCBC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoCBC.h; sourceTree = "<group>"; };
|
||||
0E07597C20F0060E00F38FD8 /* CryptoAEAD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoAEAD.h; sourceTree = "<group>"; };
|
||||
0E07597D20F0060E00F38FD8 /* CryptoAEAD.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CryptoAEAD.m; sourceTree = "<group>"; };
|
||||
|
@ -236,7 +236,7 @@
|
|||
0ED9C8632138139000621BA3 /* SessionProxy+CompressionFraming.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionProxy+CompressionFraming.swift"; sourceTree = "<group>"; };
|
||||
0EE7A79420F61EDC00B42E6A /* PacketMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PacketMacros.h; sourceTree = "<group>"; };
|
||||
0EE7A79720F6296F00B42E6A /* PacketMacros.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PacketMacros.m; sourceTree = "<group>"; };
|
||||
0EE7A79D20F6488400B42E6A /* DataPathEncryption.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataPathEncryption.h; sourceTree = "<group>"; };
|
||||
0EE7A79D20F6488400B42E6A /* DataPathCrypto.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataPathCrypto.h; sourceTree = "<group>"; };
|
||||
0EE7A7A020F664AB00B42E6A /* DataPathEncryptionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataPathEncryptionTests.swift; sourceTree = "<group>"; };
|
||||
0EEC49DB20B5E732008FEB91 /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
|
||||
0EFEB42A2006D3C800F81029 /* SessionProxy+EncryptionBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SessionProxy+EncryptionBridge.swift"; sourceTree = "<group>"; };
|
||||
|
@ -440,6 +440,7 @@
|
|||
0E12B2A721456C0200B4BAE9 /* ControlChannel.swift */,
|
||||
0E12B2AA2145E01700B4BAE9 /* ControlChannelSerializer.swift */,
|
||||
0EFEB44A2006D3C800F81029 /* CoreConfiguration.swift */,
|
||||
0E07596A20EF79AB00F38FD8 /* Crypto.h */,
|
||||
0E07597C20F0060E00F38FD8 /* CryptoAEAD.h */,
|
||||
0E07597D20F0060E00F38FD8 /* CryptoAEAD.m */,
|
||||
0EFEB4402006D3C800F81029 /* CryptoBox.h */,
|
||||
|
@ -450,8 +451,7 @@
|
|||
0EFEB4432006D3C800F81029 /* Data+Manipulation.swift */,
|
||||
0EFEB4352006D3C800F81029 /* DataPath.h */,
|
||||
0EFEB44C2006D3C800F81029 /* DataPath.m */,
|
||||
0EE7A79D20F6488400B42E6A /* DataPathEncryption.h */,
|
||||
0E07596A20EF79AB00F38FD8 /* Encryption.h */,
|
||||
0EE7A79D20F6488400B42E6A /* DataPathCrypto.h */,
|
||||
0EFEB4362006D3C800F81029 /* Errors.h */,
|
||||
0EFEB44B2006D3C800F81029 /* Errors.m */,
|
||||
0EFEB4452006D3C800F81029 /* IOInterface.swift */,
|
||||
|
@ -539,7 +539,7 @@
|
|||
0E07596E20EF79B400F38FD8 /* CryptoCBC.h in Headers */,
|
||||
0E07596320EF733F00F38FD8 /* CryptoMacros.h in Headers */,
|
||||
0EFEB46E2006D3C800F81029 /* TLSBox.h in Headers */,
|
||||
0E07596B20EF79AB00F38FD8 /* Encryption.h in Headers */,
|
||||
0E07596B20EF79AB00F38FD8 /* Crypto.h in Headers */,
|
||||
0EFEB46B2006D3C800F81029 /* CryptoBox.h in Headers */,
|
||||
0EFEB4592006D3C800F81029 /* Allocation.h in Headers */,
|
||||
0EFEB4582006D3C800F81029 /* MSS.h in Headers */,
|
||||
|
@ -561,7 +561,7 @@
|
|||
0E07596F20EF79B400F38FD8 /* CryptoCBC.h in Headers */,
|
||||
0E07596420EF733F00F38FD8 /* CryptoMacros.h in Headers */,
|
||||
0EEC49EA20B5F7F6008FEB91 /* ZeroingData.h in Headers */,
|
||||
0E07596C20EF79AB00F38FD8 /* Encryption.h in Headers */,
|
||||
0E07596C20EF79AB00F38FD8 /* Crypto.h in Headers */,
|
||||
0EEC49E120B5F7EA008FEB91 /* Allocation.h in Headers */,
|
||||
0EEC49E320B5F7F6008FEB91 /* DataPath.h in Headers */,
|
||||
0EF5CF282141E183004FF1BD /* CompressionFramingNative.h in Headers */,
|
||||
|
|
|
@ -50,15 +50,15 @@ extension ControlChannel {
|
|||
var offset = start
|
||||
let end = end ?? packet.count
|
||||
|
||||
guard end >= offset + PacketHeaderLength else {
|
||||
throw ControlChannelError("Missing header")
|
||||
guard end >= offset + PacketOpcodeLength else {
|
||||
throw ControlChannelError("Missing opcode")
|
||||
}
|
||||
let codeValue = packet[offset] >> 3
|
||||
guard let code = PacketCode(rawValue: codeValue) else {
|
||||
throw ControlChannelError("Unknown code: \(codeValue))")
|
||||
}
|
||||
let key = packet[offset] & 0b111
|
||||
offset += PacketHeaderLength
|
||||
offset += PacketOpcodeLength
|
||||
|
||||
log.debug("Control: Try read packet with code \(code) and key \(key)")
|
||||
|
||||
|
|
|
@ -52,7 +52,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@property (nonatomic, strong, readonly) NSData *_Nullable payload;
|
||||
@property (nonatomic, strong) NSDate *_Nullable sentDate;
|
||||
|
||||
- (NSInteger)serializeTo:(nullable uint8_t *)to;
|
||||
- (NSInteger)capacity;
|
||||
- (NSInteger)serializeTo:(uint8_t *)to;
|
||||
- (NSData *)serialized;
|
||||
|
||||
@end
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
const BOOL isAck = self.isAck;
|
||||
const NSUInteger ackLength = self.ackIds.count;
|
||||
NSCAssert(!isAck || ackLength > 0, @"Ack packet must provide positive ackLength");
|
||||
NSInteger n = PacketHeaderLength + PacketSessionIdLength;
|
||||
NSInteger n = PacketOpcodeLength + PacketSessionIdLength;
|
||||
n += PacketAckLengthLength;
|
||||
if (ackLength > 0) {
|
||||
n += ackLength * PacketIdLength + PacketSessionIdLength;
|
||||
|
@ -95,9 +95,6 @@
|
|||
// Ruby: send_ctrl
|
||||
- (NSInteger)serializeTo:(uint8_t *)to
|
||||
{
|
||||
if (!to) {
|
||||
return [self capacity];
|
||||
}
|
||||
uint8_t *ptr = to;
|
||||
ptr += PacketHeaderSet(ptr, self.code, self.key, self.sessionId.bytes);
|
||||
if (self.ackIds.count > 0) {
|
||||
|
@ -124,7 +121,7 @@
|
|||
ptr += self.payload.length;
|
||||
}
|
||||
}
|
||||
return (int)(ptr - to);
|
||||
return ptr - to;
|
||||
}
|
||||
|
||||
- (NSData *)serialized
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Encryption.h
|
||||
// Crypto.h
|
||||
// TunnelKit
|
||||
//
|
||||
// Created by Davide De Rosa on 3/3/17.
|
||||
|
@ -48,10 +48,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
- (void)configureEncryptionWithCipherKey:(nullable ZeroingData *)cipherKey hmacKey:(nullable ZeroingData *)hmacKey;
|
||||
- (int)digestLength;
|
||||
- (int)overheadLength;
|
||||
- (int)extraLength;
|
||||
|
||||
- (nullable NSData *)encryptData:(NSData *)data offset:(NSInteger)offset extra:(nullable const uint8_t *)extra error:(NSError **)error;
|
||||
- (NSInteger)encryptionCapacityWithLength:(NSInteger)length;
|
||||
- (BOOL)encryptBytes:(const uint8_t *)bytes length:(NSInteger)length dest:(uint8_t *)dest destLength:(NSInteger *)destLength extra:(nullable const uint8_t *)extra error:(NSError **)error;
|
||||
|
||||
- (id<DataPathEncrypter>)dataPathEncrypter;
|
||||
|
@ -63,13 +61,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
- (void)configureDecryptionWithCipherKey:(nullable ZeroingData *)cipherKey hmacKey:(nullable ZeroingData *)hmacKey;
|
||||
- (int)digestLength;
|
||||
- (int)overheadLength;
|
||||
- (int)extraLength;
|
||||
|
||||
- (nullable NSData *)decryptData:(NSData *)data offset:(NSInteger)offset extra:(nullable const uint8_t *)extra error:(NSError **)error;
|
||||
- (NSInteger)encryptionCapacityWithLength:(NSInteger)length;
|
||||
- (BOOL)decryptBytes:(const uint8_t *)bytes length:(NSInteger)length dest:(uint8_t *)dest destLength:(NSInteger *)destLength extra:(nullable const uint8_t *)extra error:(NSError **)error;
|
||||
- (BOOL)verifyData:(NSData *)data offset:(NSInteger)offset extra:(nullable const uint8_t *)extra error:(NSError **)error;
|
||||
- (BOOL)verifyBytes:(const uint8_t *)bytes length:(NSInteger)length extra:(const uint8_t *)extra error:(NSError **)error;
|
||||
- (BOOL)verifyBytes:(const uint8_t *)bytes length:(NSInteger)length extra:(nullable const uint8_t *)extra error:(NSError **)error;
|
||||
|
||||
- (id<DataPathDecrypter>)dataPathDecrypter;
|
||||
|
|
@ -36,8 +36,8 @@
|
|||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "Encryption.h"
|
||||
#import "DataPathEncryption.h"
|
||||
#import "Crypto.h"
|
||||
#import "DataPathCrypto.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
|
|
@ -50,7 +50,6 @@ const NSInteger CryptoAEADTagLength = 16;
|
|||
@property (nonatomic, unsafe_unretained) const EVP_CIPHER *cipher;
|
||||
@property (nonatomic, assign) int cipherKeyLength;
|
||||
@property (nonatomic, assign) int cipherIVLength; // 12 (AD packetId + HMAC key)
|
||||
@property (nonatomic, assign) int overheadLength;
|
||||
@property (nonatomic, assign) int extraPacketIdOffset;
|
||||
|
||||
@property (nonatomic, unsafe_unretained) EVP_CIPHER_CTX *cipherCtxEnc;
|
||||
|
@ -73,7 +72,6 @@ const NSInteger CryptoAEADTagLength = 16;
|
|||
|
||||
self.cipherKeyLength = EVP_CIPHER_key_length(self.cipher);
|
||||
self.cipherIVLength = EVP_CIPHER_iv_length(self.cipher);
|
||||
self.overheadLength = CryptoAEADTagLength;
|
||||
self.extraLength = PacketIdLength;
|
||||
self.extraPacketIdOffset = 0;
|
||||
|
||||
|
@ -102,6 +100,11 @@ const NSInteger CryptoAEADTagLength = 16;
|
|||
return 0;
|
||||
}
|
||||
|
||||
- (NSInteger)encryptionCapacityWithLength:(NSInteger)length
|
||||
{
|
||||
return safe_crypto_capacity(length, CryptoAEADTagLength);
|
||||
}
|
||||
|
||||
#pragma mark Encrypter
|
||||
|
||||
- (void)configureEncryptionWithCipherKey:(ZeroingData *)cipherKey hmacKey:(ZeroingData *)hmacKey
|
||||
|
@ -115,24 +118,6 @@ const NSInteger CryptoAEADTagLength = 16;
|
|||
[self prepareIV:self.cipherIVEnc withHMACKey:hmacKey];
|
||||
}
|
||||
|
||||
- (NSData *)encryptData:(NSData *)data offset:(NSInteger)offset extra:(const uint8_t *)extra error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
NSParameterAssert(data);
|
||||
NSParameterAssert(extra);
|
||||
|
||||
const uint8_t *bytes = data.bytes + offset;
|
||||
const int length = (int)(data.length - offset);
|
||||
const int maxOutputSize = (int)safe_crypto_capacity(data.length, self.overheadLength);
|
||||
|
||||
NSMutableData *dest = [[NSMutableData alloc] initWithLength:maxOutputSize];
|
||||
NSInteger encryptedLength = INT_MAX;
|
||||
if (![self encryptBytes:bytes length:length dest:dest.mutableBytes destLength:&encryptedLength extra:extra error:error]) {
|
||||
return nil;
|
||||
}
|
||||
dest.length = encryptedLength;
|
||||
return dest;
|
||||
}
|
||||
|
||||
- (BOOL)encryptBytes:(const uint8_t *)bytes length:(NSInteger)length dest:(uint8_t *)dest destLength:(NSInteger *)destLength extra:(const uint8_t *)extra error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
NSParameterAssert(extra);
|
||||
|
@ -179,24 +164,6 @@ const NSInteger CryptoAEADTagLength = 16;
|
|||
[self prepareIV:self.cipherIVDec withHMACKey:hmacKey];
|
||||
}
|
||||
|
||||
- (NSData *)decryptData:(NSData *)data offset:(NSInteger)offset extra:(const uint8_t *)extra error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
NSParameterAssert(data);
|
||||
NSParameterAssert(extra);
|
||||
|
||||
const uint8_t *bytes = data.bytes + offset;
|
||||
const int length = (int)(data.length - offset);
|
||||
const int maxOutputSize = (int)safe_crypto_capacity(data.length, self.overheadLength);
|
||||
|
||||
NSMutableData *dest = [[NSMutableData alloc] initWithLength:maxOutputSize];
|
||||
NSInteger decryptedLength;
|
||||
if (![self decryptBytes:bytes length:length dest:dest.mutableBytes destLength:&decryptedLength extra:extra error:error]) {
|
||||
return nil;
|
||||
}
|
||||
dest.length = decryptedLength;
|
||||
return dest;
|
||||
}
|
||||
|
||||
- (BOOL)decryptBytes:(const uint8_t *)bytes length:(NSInteger)length dest:(uint8_t *)dest destLength:(NSInteger *)destLength extra:(const uint8_t *)extra error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
NSParameterAssert(extra);
|
||||
|
@ -225,15 +192,9 @@ const NSInteger CryptoAEADTagLength = 16;
|
|||
TUNNEL_CRYPTO_RETURN_STATUS(code)
|
||||
}
|
||||
|
||||
- (BOOL)verifyData:(NSData *)data offset:(NSInteger)offset extra:(const uint8_t *)extra error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
NSAssert(NO, @"Verification not supported");
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)verifyBytes:(const uint8_t *)bytes length:(NSInteger)length extra:(const uint8_t *)extra error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
NSAssert(NO, @"Verification not supported");
|
||||
[NSException raise:NSInvalidArgumentException format:@"Verification not supported"];
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
@ -276,17 +237,12 @@ const NSInteger CryptoAEADTagLength = 16;
|
|||
|
||||
#pragma mark DataPathChannel
|
||||
|
||||
- (int)overheadLength
|
||||
{
|
||||
return self.crypto.overheadLength;
|
||||
}
|
||||
|
||||
- (void)setPeerId:(uint32_t)peerId
|
||||
{
|
||||
peerId &= 0xffffff;
|
||||
|
||||
if (peerId == PacketPeerIdDisabled) {
|
||||
self.headerLength = 1;
|
||||
self.headerLength = PacketOpcodeLength;
|
||||
self.crypto.extraLength = PacketIdLength;
|
||||
self.crypto.extraPacketIdOffset = 0;
|
||||
self.setDataHeader = ^(uint8_t *to, uint8_t key) {
|
||||
|
@ -295,7 +251,7 @@ const NSInteger CryptoAEADTagLength = 16;
|
|||
self.checkPeerId = NULL;
|
||||
}
|
||||
else {
|
||||
self.headerLength = 4;
|
||||
self.headerLength = PacketOpcodeLength + PacketPeerIdLength;
|
||||
self.crypto.extraLength = self.headerLength + PacketIdLength;
|
||||
self.crypto.extraPacketIdOffset = self.headerLength;
|
||||
self.setDataHeader = ^(uint8_t *to, uint8_t key) {
|
||||
|
@ -307,6 +263,11 @@ const NSInteger CryptoAEADTagLength = 16;
|
|||
}
|
||||
}
|
||||
|
||||
- (NSInteger)encryptionCapacityWithLength:(NSInteger)length
|
||||
{
|
||||
return [self.crypto encryptionCapacityWithLength:length];
|
||||
}
|
||||
|
||||
#pragma mark DataPathEncrypter
|
||||
|
||||
- (void)assembleDataPacketWithBlock:(DataPathAssembleBlock)block packetId:(uint32_t)packetId payload:(NSData *)payload into:(uint8_t *)packetBytes length:(NSInteger *)packetLength
|
||||
|
@ -324,7 +285,7 @@ const NSInteger CryptoAEADTagLength = 16;
|
|||
|
||||
- (NSData *)encryptedDataPacketWithKey:(uint8_t)key packetId:(uint32_t)packetId packetBytes:(const uint8_t *)packetBytes packetLength:(NSInteger)packetLength error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
const int capacity = self.headerLength + PacketIdLength + (int)safe_crypto_capacity(packetLength, self.crypto.overheadLength);
|
||||
const int capacity = self.headerLength + PacketIdLength + (int)[self.crypto encryptionCapacityWithLength:packetLength];
|
||||
NSMutableData *encryptedPacket = [[NSMutableData alloc] initWithLength:capacity];
|
||||
uint8_t *ptr = encryptedPacket.mutableBytes;
|
||||
NSInteger encryptedPacketLength = INT_MAX;
|
||||
|
|
|
@ -36,8 +36,8 @@
|
|||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "Encryption.h"
|
||||
#import "DataPathEncryption.h"
|
||||
#import "Crypto.h"
|
||||
#import "DataPathCrypto.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
|
|
@ -54,7 +54,6 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
|
|||
@property (nonatomic, assign) int cipherIVLength;
|
||||
@property (nonatomic, assign) int hmacKeyLength;
|
||||
@property (nonatomic, assign) int digestLength;
|
||||
@property (nonatomic, assign) int overheadLength;
|
||||
|
||||
@property (nonatomic, unsafe_unretained) EVP_CIPHER_CTX *cipherCtxEnc;
|
||||
@property (nonatomic, unsafe_unretained) EVP_CIPHER_CTX *cipherCtxDec;
|
||||
|
@ -87,7 +86,6 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
|
|||
// as seen in OpenVPN's crypto_openssl.c:md_kt_size()
|
||||
self.hmacKeyLength = EVP_MD_size(self.digest);
|
||||
self.digestLength = EVP_MD_size(self.digest);
|
||||
self.overheadLength = self.cipherIVLength + self.digestLength;
|
||||
|
||||
if (cipherName) {
|
||||
self.cipherCtxEnc = EVP_CIPHER_CTX_new();
|
||||
|
@ -120,6 +118,11 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
|
|||
return 0;
|
||||
}
|
||||
|
||||
- (NSInteger)encryptionCapacityWithLength:(NSInteger)length
|
||||
{
|
||||
return safe_crypto_capacity(length, self.digestLength + self.cipherIVLength);
|
||||
}
|
||||
|
||||
#pragma mark Encrypter
|
||||
|
||||
- (void)configureEncryptionWithCipherKey:(ZeroingData *)cipherKey hmacKey:(ZeroingData *)hmacKey
|
||||
|
@ -138,23 +141,6 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
|
|||
HMAC_Init_ex(self.hmacCtxEnc, hmacKey.bytes, self.hmacKeyLength, self.digest, NULL);
|
||||
}
|
||||
|
||||
- (NSData *)encryptData:(NSData *)data offset:(NSInteger)offset extra:(const uint8_t *)extra error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
NSParameterAssert(data);
|
||||
|
||||
const uint8_t *bytes = data.bytes + offset;
|
||||
const int length = (int)(data.length - offset);
|
||||
const int maxOutputSize = (int)safe_crypto_capacity(data.length, self.overheadLength);
|
||||
|
||||
NSMutableData *dest = [[NSMutableData alloc] initWithLength:maxOutputSize];
|
||||
NSInteger encryptedLength = INT_MAX;
|
||||
if (![self encryptBytes:bytes length:length dest:dest.mutableBytes destLength:&encryptedLength extra:extra error:error]) {
|
||||
return nil;
|
||||
}
|
||||
dest.length = encryptedLength;
|
||||
return dest;
|
||||
}
|
||||
|
||||
- (BOOL)encryptBytes:(const uint8_t *)bytes length:(NSInteger)length dest:(uint8_t *)dest destLength:(NSInteger *)destLength extra:(const uint8_t *)extra error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
uint8_t *outIV = dest + self.digestLength;
|
||||
|
@ -214,24 +200,6 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
|
|||
HMAC_Init_ex(self.hmacCtxDec, hmacKey.bytes, self.hmacKeyLength, self.digest, NULL);
|
||||
}
|
||||
|
||||
- (NSData *)decryptData:(NSData *)data offset:(NSInteger)offset extra:(const uint8_t *)extra error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
NSAssert(self.cipher, @"No cipher provided");
|
||||
NSParameterAssert(data);
|
||||
|
||||
const uint8_t *bytes = data.bytes + offset;
|
||||
const int length = (int)(data.length - offset);
|
||||
const int maxOutputSize = (int)safe_crypto_capacity(data.length, self.overheadLength);
|
||||
|
||||
NSMutableData *dest = [[NSMutableData alloc] initWithLength:maxOutputSize];
|
||||
NSInteger decryptedLength;
|
||||
if (![self decryptBytes:bytes length:length dest:dest.mutableBytes destLength:&decryptedLength extra:extra error:error]) {
|
||||
return nil;
|
||||
}
|
||||
dest.length = decryptedLength;
|
||||
return dest;
|
||||
}
|
||||
|
||||
- (BOOL)decryptBytes:(const uint8_t *)bytes length:(NSInteger)length dest:(uint8_t *)dest destLength:(NSInteger *)destLength extra:(const uint8_t *)extra error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
NSAssert(self.cipher, @"No cipher provided");
|
||||
|
@ -261,11 +229,6 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
|
|||
TUNNEL_CRYPTO_RETURN_STATUS(code)
|
||||
}
|
||||
|
||||
- (BOOL)verifyData:(NSData *)data offset:(NSInteger)offset extra:(const uint8_t *)extra error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
return [self verifyBytes:data.bytes length:data.length extra:extra error:error];
|
||||
}
|
||||
|
||||
- (BOOL)verifyBytes:(const uint8_t *)bytes length:(NSInteger)length extra:(const uint8_t *)extra error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
int l1 = 0;
|
||||
|
@ -316,24 +279,19 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
|
|||
|
||||
#pragma mark DataPathChannel
|
||||
|
||||
- (int)overheadLength
|
||||
{
|
||||
return self.crypto.overheadLength;
|
||||
}
|
||||
|
||||
- (void)setPeerId:(uint32_t)peerId
|
||||
{
|
||||
peerId &= 0xffffff;
|
||||
|
||||
if (peerId == PacketPeerIdDisabled) {
|
||||
self.headerLength = 1;
|
||||
self.headerLength = PacketOpcodeLength;
|
||||
self.setDataHeader = ^(uint8_t *to, uint8_t key) {
|
||||
PacketHeaderSet(to, PacketCodeDataV1, key, nil);
|
||||
};
|
||||
self.checkPeerId = NULL;
|
||||
}
|
||||
else {
|
||||
self.headerLength = 4;
|
||||
self.headerLength = PacketOpcodeLength + PacketPeerIdLength;
|
||||
self.setDataHeader = ^(uint8_t *to, uint8_t key) {
|
||||
PacketHeaderSetDataV2(to, key, peerId);
|
||||
};
|
||||
|
@ -343,6 +301,11 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
|
|||
}
|
||||
}
|
||||
|
||||
- (NSInteger)encryptionCapacityWithLength:(NSInteger)length
|
||||
{
|
||||
return [self.crypto encryptionCapacityWithLength:length];
|
||||
}
|
||||
|
||||
#pragma mark DataPathEncrypter
|
||||
|
||||
- (void)assembleDataPacketWithBlock:(DataPathAssembleBlock)block packetId:(uint32_t)packetId payload:(NSData *)payload into:(uint8_t *)packetBytes length:(NSInteger *)packetLength
|
||||
|
@ -363,7 +326,7 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
|
|||
|
||||
- (NSData *)encryptedDataPacketWithKey:(uint8_t)key packetId:(uint32_t)packetId packetBytes:(const uint8_t *)packetBytes packetLength:(NSInteger)packetLength error:(NSError *__autoreleasing *)error
|
||||
{
|
||||
const int capacity = self.headerLength + (int)safe_crypto_capacity(packetLength, self.crypto.overheadLength);
|
||||
const int capacity = self.headerLength + (int)[self.crypto encryptionCapacityWithLength:packetLength];
|
||||
NSMutableData *encryptedPacket = [[NSMutableData alloc] initWithLength:capacity];
|
||||
uint8_t *ptr = encryptedPacket.mutableBytes;
|
||||
NSInteger encryptedPacketLength = INT_MAX;
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#import <arpa/inet.h>
|
||||
|
||||
#import "DataPath.h"
|
||||
#import "DataPathEncryption.h"
|
||||
#import "DataPathCrypto.h"
|
||||
#import "MSS.h"
|
||||
#import "ReplayProtector.h"
|
||||
#import "Allocation.h"
|
||||
|
@ -120,7 +120,7 @@
|
|||
|
||||
- (void)adjustEncBufferToPacketSize:(int)size
|
||||
{
|
||||
const int neededCapacity = DataPathByteAlignment + (int)safe_crypto_capacity(size, self.encrypter.overheadLength);
|
||||
const int neededCapacity = DataPathByteAlignment + (int)[self.encrypter encryptionCapacityWithLength:size];
|
||||
if (self.encBufferCapacity >= neededCapacity) {
|
||||
return;
|
||||
}
|
||||
|
@ -132,7 +132,7 @@
|
|||
|
||||
- (void)adjustDecBufferToPacketSize:(int)size
|
||||
{
|
||||
const int neededCapacity = DataPathByteAlignment + (int)safe_crypto_capacity(size, self.decrypter.overheadLength);
|
||||
const int neededCapacity = DataPathByteAlignment + (int)[self.decrypter encryptionCapacityWithLength:size];
|
||||
if (self.decBufferCapacity >= neededCapacity) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// DataPathEncryption.h
|
||||
// DataPathCrypto.h
|
||||
// TunnelKit
|
||||
//
|
||||
// Created by Davide De Rosa on 7/11/18.
|
||||
|
@ -43,8 +43,8 @@ typedef void (^DataPathParseBlock)(uint8_t *payload, NSInteger *payloadOffset, N
|
|||
|
||||
@protocol DataPathChannel
|
||||
|
||||
- (int)overheadLength;
|
||||
- (void)setPeerId:(uint32_t)peerId;
|
||||
- (NSInteger)encryptionCapacityWithLength:(NSInteger)length;
|
||||
|
||||
@end
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
#define PacketHeaderLength ((NSInteger)1)
|
||||
#define PacketOpcodeLength ((NSInteger)1)
|
||||
#define PacketIdLength ((NSInteger)4)
|
||||
#define PacketSessionIdLength ((NSInteger)8)
|
||||
#define PacketAckLengthLength ((NSInteger)1)
|
||||
|
@ -66,7 +66,7 @@ extern const uint8_t DataPacketPingData[16];
|
|||
static inline int PacketHeaderSet(uint8_t *to, PacketCode code, uint8_t key, const uint8_t *_Nullable sessionId)
|
||||
{
|
||||
*(uint8_t *)to = (code << 3) | (key & 0b111);
|
||||
int offset = PacketHeaderLength;
|
||||
int offset = PacketOpcodeLength;
|
||||
if (sessionId) {
|
||||
memcpy(to + offset, sessionId, PacketSessionIdLength);
|
||||
offset += PacketSessionIdLength;
|
||||
|
@ -77,7 +77,7 @@ static inline int PacketHeaderSet(uint8_t *to, PacketCode code, uint8_t key, con
|
|||
static inline int PacketHeaderSetDataV2(uint8_t *to, uint8_t key, uint32_t peerId)
|
||||
{
|
||||
*(uint32_t *)to = ((PacketCodeDataV2 << 3) | (key & 0b111)) | htonl(peerId & 0xffffff);
|
||||
return PacketHeaderLength + PacketPeerIdLength;
|
||||
return PacketOpcodeLength + PacketPeerIdLength;
|
||||
}
|
||||
|
||||
static inline int PacketHeaderGetDataV2PeerId(const uint8_t *from)
|
||||
|
|
|
@ -66,6 +66,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
- (nullable NSString *)nullTerminatedStringFromOffset:(NSInteger)from;
|
||||
|
||||
- (BOOL)isEqualToData:(NSData *)data;
|
||||
- (NSData *)toData; // XXX: unsafe
|
||||
- (NSString *)toHex;
|
||||
|
||||
@end
|
||||
|
|
|
@ -276,6 +276,11 @@
|
|||
return !memcmp(_bytes, data.bytes, _count);
|
||||
}
|
||||
|
||||
- (NSData *)toData
|
||||
{
|
||||
return [NSData dataWithBytes:_bytes length:_count];
|
||||
}
|
||||
|
||||
- (NSString *)toHex
|
||||
{
|
||||
const NSUInteger capacity = _count * 2;
|
||||
|
|
|
@ -38,14 +38,14 @@ module __TunnelKitNative {
|
|||
header "Errors.h"
|
||||
header "ZeroingData.h"
|
||||
header "TLSBox.h"
|
||||
header "Crypto.h"
|
||||
header "CryptoBox.h"
|
||||
header "Encryption.h"
|
||||
header "MSS.h"
|
||||
header "PacketMacros.h"
|
||||
header "ControlPacket.h"
|
||||
header "ReplayProtector.h"
|
||||
header "CompressionFramingNative.h"
|
||||
header "DataPath.h"
|
||||
header "DataPathEncryption.h"
|
||||
header "DataPathCrypto.h"
|
||||
export *
|
||||
}
|
||||
|
|
|
@ -69,8 +69,8 @@ class DataManipulationTests: XCTestCase {
|
|||
let z2 = z1.withOffset(2, count: 3) // 5678ab
|
||||
let z3 = z2.appending(Z(Data(hex: "aaddcc"))) // 5678abaaddcc
|
||||
|
||||
XCTAssertEqual(z1.data, Data(hex: "12345678abcdef"))
|
||||
XCTAssertEqual(z2.data, Data(hex: "5678ab"))
|
||||
XCTAssertEqual(z3.data, Data(hex: "5678abaaddcc"))
|
||||
XCTAssertEqual(z1.toData(), Data(hex: "12345678abcdef"))
|
||||
XCTAssertEqual(z2.toData(), Data(hex: "5678ab"))
|
||||
XCTAssertEqual(z3.toData(), Data(hex: "5678abaaddcc"))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ class EncryptionPerformanceTests: XCTestCase {
|
|||
let suite = TestUtils.generateDataSuite(1000, 100000)
|
||||
measure {
|
||||
for data in suite {
|
||||
let _ = try! self.cbcEncrypter.encryptData(data, offset: 0, extra: nil)
|
||||
let _ = try! self.cbcEncrypter.encryptData(data, extra: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ class EncryptionPerformanceTests: XCTestCase {
|
|||
let extra: [UInt8] = [0x11, 0x22, 0x33, 0x44]
|
||||
measure {
|
||||
for data in suite {
|
||||
let _ = try! self.gcmEncrypter.encryptData(data, offset: 0, extra: extra)
|
||||
let _ = try! self.gcmEncrypter.encryptData(data, extra: extra)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,13 +40,19 @@ import XCTest
|
|||
@testable import __TunnelKitNative
|
||||
|
||||
class EncryptionTests: XCTestCase {
|
||||
private var cipherKey: ZeroingData!
|
||||
private var cipherEncKey: ZeroingData!
|
||||
|
||||
private var hmacKey: ZeroingData!
|
||||
private var cipherDecKey: ZeroingData!
|
||||
|
||||
private var hmacEncKey: ZeroingData!
|
||||
|
||||
private var hmacDecKey: ZeroingData!
|
||||
|
||||
override func setUp() {
|
||||
cipherKey = try! SecureRandom.safeData(length: 32)
|
||||
hmacKey = try! SecureRandom.safeData(length: 32)
|
||||
cipherEncKey = try! SecureRandom.safeData(length: 32)
|
||||
cipherDecKey = try! SecureRandom.safeData(length: 32)
|
||||
hmacEncKey = try! SecureRandom.safeData(length: 32)
|
||||
hmacDecKey = try! SecureRandom.safeData(length: 32)
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
|
@ -54,67 +60,38 @@ class EncryptionTests: XCTestCase {
|
|||
}
|
||||
|
||||
func testCBC() {
|
||||
let cbc = CryptoBox(cipherAlgorithm: "aes-128-cbc", digestAlgorithm: "sha256")
|
||||
try! cbc.configure(withCipherEncKey: cipherKey, cipherDecKey: cipherKey, hmacEncKey: hmacKey, hmacDecKey: hmacKey)
|
||||
let enc = cbc.encrypter()
|
||||
let dec = cbc.decrypter()
|
||||
|
||||
let (client, server) = clientServer("aes-128-cbc", "sha256")
|
||||
|
||||
let plain = Data(hex: "00112233445566778899")
|
||||
let encrypted = try! enc.encryptData(plain, offset: 0, extra: nil)
|
||||
let decrypted = try! dec.decryptData(encrypted, offset: 0, extra: nil)
|
||||
let encrypted = try! client.encrypter().encryptData(plain, extra: nil)
|
||||
let decrypted = try! server.decrypter().decryptData(encrypted, extra: nil)
|
||||
XCTAssertEqual(plain, decrypted)
|
||||
}
|
||||
|
||||
func testHMAC() {
|
||||
let cbc = CryptoBox(cipherAlgorithm: nil, digestAlgorithm: "sha256")
|
||||
try! cbc.configure(withCipherEncKey: nil, cipherDecKey: nil, hmacEncKey: hmacKey, hmacDecKey: hmacKey)
|
||||
let enc = cbc.encrypter()
|
||||
let dec = cbc.decrypter()
|
||||
|
||||
let (client, server) = clientServer(nil, "sha256")
|
||||
|
||||
let plain = Data(hex: "00112233445566778899")
|
||||
let encrypted = try! enc.encryptData(plain, offset: 0, extra: nil)
|
||||
do {
|
||||
try dec.verifyData(encrypted, offset: 0, extra: nil)
|
||||
XCTAssert(true)
|
||||
} catch {
|
||||
XCTAssert(false)
|
||||
}
|
||||
let encrypted = try! client.encrypter().encryptData(plain, extra: nil)
|
||||
XCTAssertNoThrow(try server.decrypter().verifyData(encrypted, extra: nil))
|
||||
}
|
||||
|
||||
func testGCM() {
|
||||
let gcm = CryptoBox(cipherAlgorithm: "aes-256-gcm", digestAlgorithm: nil)
|
||||
try! gcm.configure(withCipherEncKey: cipherKey, cipherDecKey: cipherKey, hmacEncKey: hmacKey, hmacDecKey: hmacKey)
|
||||
let enc = gcm.encrypter()
|
||||
let dec = gcm.decrypter()
|
||||
let (client, server) = clientServer("aes-256-gcm", nil)
|
||||
|
||||
// let packetId: UInt32 = 0x56341200
|
||||
let extra: [UInt8] = [0x00, 0x12, 0x34, 0x56]
|
||||
let plain = Data(hex: "00112233445566778899")
|
||||
let encrypted = try! enc.encryptData(plain, offset: 0, extra: extra)
|
||||
let decrypted = try! dec.decryptData(encrypted, offset: 0, extra: extra)
|
||||
let encrypted = try! client.encrypter().encryptData(plain, extra: extra)
|
||||
let decrypted = try! server.decrypter().decryptData(encrypted, extra: extra)
|
||||
XCTAssertEqual(plain, decrypted)
|
||||
}
|
||||
|
||||
// func testCryptoOperation() {
|
||||
// let data = Data(hex: "aabbccddeeff")
|
||||
//
|
||||
// print("Original : \(data.toHex())")
|
||||
// var enc: Data
|
||||
// var dec: Data
|
||||
//
|
||||
// enc = Data()
|
||||
// enc.append(try! encrypter.encryptData(data, offset: 0, packetId: 0))
|
||||
// print("Encrypted: \(enc.toHex())")
|
||||
// dec = try! decrypter.decryptData(enc, offset: 0, packetId: 0)
|
||||
// print("Decrypted: \(dec.toHex())")
|
||||
// XCTAssert(dec == data)
|
||||
//
|
||||
// let prefix = "abcdef"
|
||||
// enc = Data(hex: prefix)
|
||||
// enc.append(try! encrypter.encryptData(data, offset: 0, packetId: 0))
|
||||
// print("Encrypted: \(enc.toHex())")
|
||||
// dec = try! decrypter.decryptData(enc, offset: (prefix.count / 2), packetId: 0)
|
||||
// print("Decrypted: \(dec.toHex())")
|
||||
// XCTAssert(dec == data)
|
||||
// }
|
||||
private func clientServer(_ c: String?, _ d: String?) -> (CryptoBox, CryptoBox) {
|
||||
let client = CryptoBox(cipherAlgorithm: c, digestAlgorithm: d)
|
||||
let server = CryptoBox(cipherAlgorithm: c, digestAlgorithm: d)
|
||||
XCTAssertNoThrow(try client.configure(withCipherEncKey: cipherEncKey, cipherDecKey: cipherDecKey, hmacEncKey: hmacEncKey, hmacDecKey: hmacDecKey))
|
||||
XCTAssertNoThrow(try server.configure(withCipherEncKey: cipherDecKey, cipherDecKey: cipherEncKey, hmacEncKey: hmacDecKey, hmacDecKey: hmacEncKey))
|
||||
return (client, server)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,8 +56,35 @@ class TestUtils {
|
|||
}
|
||||
}
|
||||
|
||||
extension ZeroingData {
|
||||
var data: Data {
|
||||
return Data(bytes: bytes, count: count)
|
||||
extension Encrypter {
|
||||
func encryptData(_ data: Data, extra: [UInt8]?) throws -> Data {
|
||||
let srcLength = data.count
|
||||
var dest: [UInt8] = Array(repeating: 0, count: srcLength + 256)
|
||||
var destLength = 0
|
||||
try data.withUnsafeBytes {
|
||||
try encryptBytes($0, length: srcLength, dest: &dest, destLength: &destLength, extra: extra)
|
||||
}
|
||||
dest.removeSubrange(destLength..<dest.count)
|
||||
return Data(dest)
|
||||
}
|
||||
}
|
||||
|
||||
extension Decrypter {
|
||||
func decryptData(_ data: Data, extra: [UInt8]?) throws -> Data {
|
||||
let srcLength = data.count
|
||||
var dest: [UInt8] = Array(repeating: 0, count: srcLength + 256)
|
||||
var destLength = 0
|
||||
try data.withUnsafeBytes {
|
||||
try decryptBytes($0, length: srcLength, dest: &dest, destLength: &destLength, extra: extra)
|
||||
}
|
||||
dest.removeSubrange(destLength..<dest.count)
|
||||
return Data(dest)
|
||||
}
|
||||
|
||||
func verifyData(_ data: Data, extra: [UInt8]?) throws {
|
||||
let srcLength = data.count
|
||||
try data.withUnsafeBytes {
|
||||
try verifyBytes($0, length: srcLength, extra: extra)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue