Merge branch 'refactor-encryption'

This commit is contained in:
Davide De Rosa 2018-09-20 23:21:43 +02:00
commit 1ba7e73e9c
19 changed files with 129 additions and 202 deletions

View File

@ -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 */,

View File

@ -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)")

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -36,8 +36,8 @@
#import <Foundation/Foundation.h>
#import "Encryption.h"
#import "DataPathEncryption.h"
#import "Crypto.h"
#import "DataPathCrypto.h"
NS_ASSUME_NONNULL_BEGIN

View File

@ -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;

View File

@ -36,8 +36,8 @@
#import <Foundation/Foundation.h>
#import "Encryption.h"
#import "DataPathEncryption.h"
#import "Crypto.h"
#import "DataPathCrypto.h"
NS_ASSUME_NONNULL_BEGIN

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -66,6 +66,7 @@ NS_ASSUME_NONNULL_BEGIN
- (nullable NSString *)nullTerminatedStringFromOffset:(NSInteger)from;
- (BOOL)isEqualToData:(NSData *)data;
- (NSData *)toData; // XXX: unsafe
- (NSString *)toHex;
@end

View File

@ -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;

View File

@ -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 *
}

View File

@ -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"))
}
}

View File

@ -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)
}
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}
}