Merge pull request #33 from keeshux/handle-mixed-data-v1-v2

Handle mixed DATA_V1/V2
This commit is contained in:
Davide De Rosa 2018-10-19 16:10:32 +02:00 committed by GitHub
commit aae3765db0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 166 additions and 123 deletions

View File

@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project _will soon adhere_ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Fixed
- Handling of mixed DATA_V1/DATA_V2 packets. [#30](https://github.com/keeshux/tunnelkit/issues/30)
## 1.1.2 (2018-10-18)
### Added

View File

@ -43,6 +43,13 @@ NS_ASSUME_NONNULL_BEGIN
@protocol DataPathEncrypter;
@protocol DataPathDecrypter;
typedef struct {
const uint8_t *iv;
int ivLength;
const uint8_t *ad;
int adLength;
} CryptoFlags;
// WARNING: dest must be able to hold ciphertext
@protocol Encrypter
@ -50,7 +57,7 @@ NS_ASSUME_NONNULL_BEGIN
- (int)digestLength;
- (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;
- (BOOL)encryptBytes:(const uint8_t *)bytes length:(NSInteger)length dest:(uint8_t *)dest destLength:(NSInteger *)destLength flags:(const CryptoFlags *_Nullable)flags error:(NSError **)error;
- (id<DataPathEncrypter>)dataPathEncrypter;
@ -63,8 +70,8 @@ NS_ASSUME_NONNULL_BEGIN
- (int)digestLength;
- (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)verifyBytes:(const uint8_t *)bytes length:(NSInteger)length extra:(nullable const uint8_t *)extra error:(NSError **)error;
- (BOOL)decryptBytes:(const uint8_t *)bytes length:(NSInteger)length dest:(uint8_t *)dest destLength:(NSInteger *)destLength flags:(const CryptoFlags *_Nullable)flags error:(NSError **)error;
- (BOOL)verifyBytes:(const uint8_t *)bytes length:(NSInteger)length flags:(const CryptoFlags *_Nullable)flags error:(NSError **)error;
- (id<DataPathDecrypter>)dataPathDecrypter;

View File

@ -43,14 +43,14 @@ NS_ASSUME_NONNULL_BEGIN
@interface CryptoAEAD : NSObject <Encrypter, Decrypter>
@property (nonatomic, assign) int extraLength;
- (instancetype)initWithCipherName:(NSString *)cipherName;
@end
@interface DataPathCryptoAEAD : NSObject <DataPathEncrypter, DataPathDecrypter>
@property (nonatomic, assign) uint32_t peerId;
- (instancetype)initWithCrypto:(CryptoAEAD *)crypto;
@end

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 extraPacketIdOffset;
@property (nonatomic, unsafe_unretained) EVP_CIPHER_CTX *cipherCtxEnc;
@property (nonatomic, unsafe_unretained) EVP_CIPHER_CTX *cipherCtxDec;
@ -72,8 +71,6 @@ const NSInteger CryptoAEADTagLength = 16;
self.cipherKeyLength = EVP_CIPHER_key_length(self.cipher);
self.cipherIVLength = EVP_CIPHER_iv_length(self.cipher);
self.extraLength = PacketIdLength;
self.extraPacketIdOffset = 0;
self.cipherCtxEnc = EVP_CIPHER_CTX_new();
self.cipherCtxDec = EVP_CIPHER_CTX_new();
@ -118,19 +115,19 @@ const NSInteger CryptoAEADTagLength = 16;
[self prepareIV:self.cipherIVEnc withHMACKey:hmacKey];
}
- (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
- (BOOL)encryptBytes:(const uint8_t *)bytes length:(NSInteger)length dest:(uint8_t *)dest destLength:(NSInteger *)destLength flags:(const CryptoFlags * _Nullable)flags error:(NSError * _Nullable __autoreleasing * _Nullable)error
{
NSParameterAssert(extra);
NSParameterAssert(flags);
int l1 = 0, l2 = 0;
int x = 0;
int code = 1;
assert(self.extraLength >= PacketIdLength);
memcpy(self.cipherIVEnc, extra + self.extraPacketIdOffset, PacketIdLength);
assert(flags->adLength >= PacketIdLength);
memcpy(self.cipherIVEnc, flags->iv, flags->ivLength);
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherInit(self.cipherCtxEnc, NULL, NULL, self.cipherIVEnc, -1);
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxEnc, NULL, &x, extra, self.extraLength);
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxEnc, NULL, &x, flags->ad, flags->adLength);
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxEnc, dest + CryptoAEADTagLength, &l1, bytes, (int)length);
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherFinal(self.cipherCtxEnc, dest + CryptoAEADTagLength + l1, &l2);
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CIPHER_CTX_ctrl(self.cipherCtxEnc, EVP_CTRL_GCM_GET_TAG, CryptoAEADTagLength, dest);
@ -164,20 +161,20 @@ const NSInteger CryptoAEADTagLength = 16;
[self prepareIV:self.cipherIVDec withHMACKey:hmacKey];
}
- (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
- (BOOL)decryptBytes:(const uint8_t *)bytes length:(NSInteger)length dest:(uint8_t *)dest destLength:(NSInteger *)destLength flags:(const CryptoFlags * _Nullable)flags error:(NSError * _Nullable __autoreleasing * _Nullable)error
{
NSParameterAssert(extra);
NSParameterAssert(flags);
int l1 = 0, l2 = 0;
int x = 0;
int code = 1;
assert(self.extraLength >= PacketIdLength);
memcpy(self.cipherIVDec, extra + self.extraPacketIdOffset, PacketIdLength);
assert(flags->adLength >= PacketIdLength);
memcpy(self.cipherIVDec, flags->iv, flags->ivLength);
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherInit(self.cipherCtxDec, NULL, NULL, self.cipherIVDec, -1);
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CIPHER_CTX_ctrl(self.cipherCtxDec, EVP_CTRL_GCM_SET_TAG, CryptoAEADTagLength, (uint8_t *)bytes);
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxDec, NULL, &x, extra, self.extraLength);
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxDec, NULL, &x, flags->ad, flags->adLength);
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherUpdate(self.cipherCtxDec, dest, &l1, bytes + CryptoAEADTagLength, (int)length - CryptoAEADTagLength);
TUNNEL_CRYPTO_TRACK_STATUS(code) EVP_CipherFinal(self.cipherCtxDec, dest + l1, &l2);
@ -192,7 +189,7 @@ const NSInteger CryptoAEADTagLength = 16;
TUNNEL_CRYPTO_RETURN_STATUS(code)
}
- (BOOL)verifyBytes:(const uint8_t *)bytes length:(NSInteger)length extra:(const uint8_t *)extra error:(NSError *__autoreleasing *)error
- (BOOL)verifyBytes:(const uint8_t *)bytes length:(NSInteger)length flags:(const CryptoFlags * _Nullable)flags error:(NSError * _Nullable __autoreleasing * _Nullable)error
{
[NSException raise:NSInvalidArgumentException format:@"Verification not supported"];
return NO;
@ -218,9 +215,6 @@ const NSInteger CryptoAEADTagLength = 16;
@interface DataPathCryptoAEAD ()
@property (nonatomic, strong) CryptoAEAD *crypto;
@property (nonatomic, assign) int headerLength;
@property (nonatomic, copy) void (^setDataHeader)(uint8_t *, uint8_t);
@property (nonatomic, copy) BOOL (^checkPeerId)(const uint8_t *);
@end
@ -239,28 +233,7 @@ const NSInteger CryptoAEADTagLength = 16;
- (void)setPeerId:(uint32_t)peerId
{
peerId &= 0xffffff;
if (peerId == PacketPeerIdDisabled) {
self.headerLength = PacketOpcodeLength;
self.crypto.extraLength = PacketIdLength;
self.crypto.extraPacketIdOffset = 0;
self.setDataHeader = ^(uint8_t *to, uint8_t key) {
PacketHeaderSet(to, PacketCodeDataV1, key, nil);
};
self.checkPeerId = NULL;
}
else {
self.headerLength = PacketOpcodeLength + PacketPeerIdLength;
self.crypto.extraLength = self.headerLength + PacketIdLength;
self.crypto.extraPacketIdOffset = self.headerLength;
self.setDataHeader = ^(uint8_t *to, uint8_t key) {
PacketHeaderSetDataV2(to, key, peerId);
};
self.checkPeerId = ^BOOL(const uint8_t *ptr) {
return (PacketHeaderGetDataV2PeerId(ptr) == peerId);
};
}
_peerId = peerId & 0xffffff;
}
- (NSInteger)encryptionCapacityWithLength:(NSInteger)length
@ -285,24 +258,34 @@ 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)[self.crypto encryptionCapacityWithLength:packetLength];
DATA_PATH_ENCRYPT_INIT(self.peerId)
const int capacity = headerLength + PacketIdLength + (int)[self.crypto encryptionCapacityWithLength:packetLength];
NSMutableData *encryptedPacket = [[NSMutableData alloc] initWithLength:capacity];
uint8_t *ptr = encryptedPacket.mutableBytes;
NSInteger encryptedPacketLength = INT_MAX;
self.setDataHeader(ptr, key);
*(uint32_t *)(ptr + self.headerLength) = htonl(packetId);
*(uint32_t *)(ptr + headerLength) = htonl(packetId);
const uint8_t *extra = ptr; // AD = header + peer id + packet id
if (!self.checkPeerId) {
extra += self.headerLength; // AD = packet id only
CryptoFlags flags;
flags.iv = ptr + headerLength;
flags.ivLength = PacketIdLength;
if (hasPeerId) {
PacketHeaderSetDataV2(ptr, key, self.peerId);
flags.ad = ptr;
flags.adLength = headerLength + PacketIdLength;
}
else {
PacketHeaderSet(ptr, PacketCodeDataV1, key, nil);
flags.ad = ptr + headerLength;
flags.adLength = PacketIdLength;
}
const BOOL success = [self.crypto encryptBytes:packetBytes
length:packetLength
dest:(ptr + self.headerLength + PacketIdLength) // skip header and packet id
dest:(ptr + headerLength + PacketIdLength) // skip header and packet id
destLength:&encryptedPacketLength
extra:extra
flags:&flags
error:error];
NSAssert(encryptedPacketLength <= capacity, @"Did not allocate enough bytes for payload");
@ -311,7 +294,7 @@ const NSInteger CryptoAEADTagLength = 16;
return nil;
}
encryptedPacket.length = self.headerLength + PacketIdLength + encryptedPacketLength;
encryptedPacket.length = headerLength + PacketIdLength + encryptedPacketLength;
return encryptedPacket;
}
@ -319,28 +302,42 @@ const NSInteger CryptoAEADTagLength = 16;
- (BOOL)decryptDataPacket:(NSData *)packet into:(uint8_t *)packetBytes length:(NSInteger *)packetLength packetId:(uint32_t *)packetId error:(NSError *__autoreleasing *)error
{
const uint8_t *extra = packet.bytes; // AD = header + peer id + packet id
if (!self.checkPeerId) {
extra += self.headerLength; // AD = packet id only
}
NSAssert(packet.length > 0, @"Decrypting an empty packet, how did it get this far?");
// skip header + packet id
const BOOL success = [self.crypto decryptBytes:(packet.bytes + self.headerLength + PacketIdLength)
length:(int)(packet.length - (self.headerLength + PacketIdLength))
dest:packetBytes
destLength:packetLength
extra:extra
error:error];
if (!success) {
DATA_PATH_DECRYPT_INIT(packet.bytes)
if (packet.length < headerLength) {
return NO;
}
if (self.checkPeerId && !self.checkPeerId(packet.bytes)) {
CryptoFlags flags;
flags.iv = packet.bytes + headerLength;
flags.ivLength = PacketIdLength;
if (hasPeerId) {
if (peerId != self.peerId) {
if (error) {
*error = TunnelKitErrorWithCode(TunnelKitErrorCodeDataPathPeerIdMismatch);
}
return NO;
}
*packetId = ntohl(*(const uint32_t *)(packet.bytes + self.headerLength));
flags.ad = packet.bytes;
flags.adLength = headerLength + PacketIdLength;
}
else {
flags.ad = packet.bytes + headerLength;
flags.adLength = PacketIdLength;
}
// skip header + packet id
const BOOL success = [self.crypto decryptBytes:(packet.bytes + headerLength + PacketIdLength)
length:(int)(packet.length - (headerLength + PacketIdLength))
dest:packetBytes
destLength:packetLength
flags:&flags
error:error];
if (!success) {
return NO;
}
*packetId = ntohl(*(const uint32_t *)(flags.iv));
return YES;
}

View File

@ -49,6 +49,8 @@ NS_ASSUME_NONNULL_BEGIN
@interface DataPathCryptoCBC : NSObject <DataPathEncrypter, DataPathDecrypter>
@property (nonatomic, assign) uint32_t peerId;
- (instancetype)initWithCrypto:(CryptoCBC *)crypto;
@end

View File

@ -141,7 +141,7 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
HMAC_Init_ex(self.hmacCtxEnc, hmacKey.bytes, self.hmacKeyLength, self.digest, NULL);
}
- (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
- (BOOL)encryptBytes:(const uint8_t *)bytes length:(NSInteger)length dest:(uint8_t *)dest destLength:(NSInteger *)destLength flags:(const CryptoFlags * _Nullable)flags error:(NSError * _Nullable __autoreleasing * _Nullable)error
{
uint8_t *outIV = dest + self.digestLength;
uint8_t *outEncrypted = dest + self.digestLength + self.cipherIVLength;
@ -200,7 +200,7 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
HMAC_Init_ex(self.hmacCtxDec, hmacKey.bytes, self.hmacKeyLength, self.digest, NULL);
}
- (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
- (BOOL)decryptBytes:(const uint8_t *)bytes length:(NSInteger)length dest:(uint8_t *)dest destLength:(NSInteger *)destLength flags:(const CryptoFlags * _Nullable)flags error:(NSError * _Nullable __autoreleasing * _Nullable)error
{
NSAssert(self.cipher, @"No cipher provided");
@ -229,7 +229,7 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
TUNNEL_CRYPTO_RETURN_STATUS(code)
}
- (BOOL)verifyBytes:(const uint8_t *)bytes length:(NSInteger)length extra:(const uint8_t *)extra error:(NSError *__autoreleasing *)error
- (BOOL)verifyBytes:(const uint8_t *)bytes length:(NSInteger)length flags:(const CryptoFlags * _Nullable)flags error:(NSError * _Nullable __autoreleasing * _Nullable)error
{
int l1 = 0;
int code = 1;
@ -260,9 +260,6 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
@interface DataPathCryptoCBC ()
@property (nonatomic, strong) CryptoCBC *crypto;
@property (nonatomic, assign) int headerLength;
@property (nonatomic, copy) void (^setDataHeader)(uint8_t *, uint8_t);
@property (nonatomic, copy) BOOL (^checkPeerId)(const uint8_t *);
@end
@ -281,24 +278,7 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
- (void)setPeerId:(uint32_t)peerId
{
peerId &= 0xffffff;
if (peerId == PacketPeerIdDisabled) {
self.headerLength = PacketOpcodeLength;
self.setDataHeader = ^(uint8_t *to, uint8_t key) {
PacketHeaderSet(to, PacketCodeDataV1, key, nil);
};
self.checkPeerId = NULL;
}
else {
self.headerLength = PacketOpcodeLength + PacketPeerIdLength;
self.setDataHeader = ^(uint8_t *to, uint8_t key) {
PacketHeaderSetDataV2(to, key, peerId);
};
self.checkPeerId = ^BOOL(const uint8_t *ptr) {
return (PacketHeaderGetDataV2PeerId(ptr) == peerId);
};
}
_peerId = peerId & 0xffffff;
}
- (NSInteger)encryptionCapacityWithLength:(NSInteger)length
@ -326,15 +306,17 @@ 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)[self.crypto encryptionCapacityWithLength:packetLength];
DATA_PATH_ENCRYPT_INIT(self.peerId)
const int capacity = headerLength + (int)[self.crypto encryptionCapacityWithLength:packetLength];
NSMutableData *encryptedPacket = [[NSMutableData alloc] initWithLength:capacity];
uint8_t *ptr = encryptedPacket.mutableBytes;
NSInteger encryptedPacketLength = INT_MAX;
const BOOL success = [self.crypto encryptBytes:packetBytes
length:packetLength
dest:(ptr + self.headerLength) // skip header byte
dest:(ptr + headerLength) // skip header bytes
destLength:&encryptedPacketLength
extra:NULL
flags:NULL
error:error];
NSAssert(encryptedPacketLength <= capacity, @"Did not allocate enough bytes for payload");
@ -343,8 +325,13 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
return nil;
}
self.setDataHeader(ptr, key);
encryptedPacket.length = self.headerLength + encryptedPacketLength;
if (hasPeerId) {
PacketHeaderSetDataV2(ptr, key, self.peerId);
}
else {
PacketHeaderSet(ptr, PacketCodeDataV1, key, nil);
}
encryptedPacket.length = headerLength + encryptedPacketLength;
return encryptedPacket;
}
@ -352,22 +339,31 @@ const NSInteger CryptoCBCMaxHMACLength = 100;
- (BOOL)decryptDataPacket:(NSData *)packet into:(uint8_t *)packetBytes length:(NSInteger *)packetLength packetId:(uint32_t *)packetId error:(NSError *__autoreleasing *)error
{
NSAssert(packet.length > 0, @"Decrypting an empty packet, how did it get this far?");
DATA_PATH_DECRYPT_INIT(packet.bytes)
if (packet.length < headerLength) {
return NO;
}
// skip header = (code, key)
const BOOL success = [self.crypto decryptBytes:(packet.bytes + self.headerLength)
length:(int)(packet.length - self.headerLength)
const BOOL success = [self.crypto decryptBytes:(packet.bytes + headerLength)
length:(int)(packet.length - headerLength)
dest:packetBytes
destLength:packetLength
extra:NULL
flags:NULL
error:error];
if (!success) {
return NO;
}
if (self.checkPeerId && !self.checkPeerId(packet.bytes)) {
if (hasPeerId) {
if (peerId != self.peerId) {
if (error) {
*error = TunnelKitErrorWithCode(TunnelKitErrorCodeDataPathPeerIdMismatch);
}
return NO;
}
}
*packetId = ntohl(*(uint32_t *)packetBytes);
return YES;
}

View File

@ -86,6 +86,8 @@
NSParameterAssert(decrypter);
NSParameterAssert(maxPackets > 0);
peerId &= 0xffffff;
if ((self = [super init])) {
self.encrypter = encrypter;
self.decrypter = decrypter;

View File

@ -38,11 +38,30 @@
NS_ASSUME_NONNULL_BEGIN
#define DATA_PATH_ENCRYPT_INIT(peerId) \
const BOOL hasPeerId = (peerId != PacketPeerIdDisabled); \
int headerLength = PacketOpcodeLength; \
if (hasPeerId) { \
headerLength += PacketPeerIdLength; \
}
#define DATA_PATH_DECRYPT_INIT(ptr) \
PacketCode code; \
PacketOpcodeGet(ptr, &code, NULL); \
uint32_t peerId = PacketPeerIdDisabled; \
const BOOL hasPeerId = (code == PacketCodeDataV2); \
int headerLength = PacketOpcodeLength; \
if (hasPeerId) { \
headerLength += PacketPeerIdLength; \
peerId = PacketHeaderGetDataV2PeerId(packet.bytes); \
}
typedef void (^DataPathAssembleBlock)(uint8_t *packetDest, NSInteger *packetLengthOffset, NSData *payload);
typedef void (^DataPathParseBlock)(uint8_t *payload, NSInteger *payloadOffset, NSInteger *headerLength, const uint8_t *packet, NSInteger packetLength);
@protocol DataPathChannel
- (uint32_t)peerId;
- (void)setPeerId:(uint32_t)peerId;
- (NSInteger)encryptionCapacityWithLength:(NSInteger)length;

View File

@ -62,6 +62,16 @@ typedef NS_ENUM(uint8_t, PacketCode) {
extern const uint8_t DataPacketPingData[16];
static inline void PacketOpcodeGet(const uint8_t *from, PacketCode *_Nullable code, uint8_t *_Nullable key)
{
if (code) {
*code = (PacketCode)(*from >> 3);
}
if (key) {
*key = *from & 0b111;
}
}
// Ruby: header
static inline int PacketHeaderSet(uint8_t *to, PacketCode code, uint8_t key, const uint8_t *_Nullable sessionId)
{

View File

@ -99,15 +99,17 @@ class DataPathEncryptionTests: XCTestCase {
if let peerId = peerId {
enc.setPeerId(peerId)
dec.setPeerId(peerId)
// XCTAssertEqual(enc.peerId(), peerId & 0xffffff)
// XCTAssertEqual(dec.peerId(), peerId & 0xffffff)
XCTAssertEqual(enc.peerId(), peerId & 0xffffff)
XCTAssertEqual(dec.peerId(), peerId & 0xffffff)
}
let expectedPayload = Data(hex: "00112233445566778899")
let key: UInt8 = 4
let encrypted = try! path.encryptPackets([expectedPayload], key: key)
print(encrypted.map { $0.toHex() })
let decrypted = try! path.decryptPackets(encrypted, keepAlive: nil)
print(decrypted.map { $0.toHex() })
let payload = decrypted.first!
XCTAssertEqual(payload, expectedPayload)
@ -117,8 +119,8 @@ class DataPathEncryptionTests: XCTestCase {
if let peerId = peerId {
enc.setPeerId(peerId)
dec.setPeerId(peerId)
// XCTAssertEqual(enc.peerId(), peerId & 0xffffff)
// XCTAssertEqual(dec.peerId(), peerId & 0xffffff)
XCTAssertEqual(enc.peerId(), peerId & 0xffffff)
XCTAssertEqual(dec.peerId(), peerId & 0xffffff)
}
let expectedPayload = Data(hex: "00112233445566778899")

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, extra: nil)
let _ = try! self.cbcEncrypter.encryptData(data, flags: nil)
}
}
}
@ -80,10 +80,11 @@ class EncryptionPerformanceTests: XCTestCase {
// 0.684s
func testGCMEncryption() {
let suite = TestUtils.generateDataSuite(1000, 100000)
let extra: [UInt8] = [0x11, 0x22, 0x33, 0x44]
let ad: [UInt8] = [0x11, 0x22, 0x33, 0x44]
var flags = CryptoFlags(packetId: 0, ad: ad, adLength: 4)
measure {
for data in suite {
let _ = try! self.gcmEncrypter.encryptData(data, extra: extra)
let _ = try! self.gcmEncrypter.encryptData(data, flags: &flags)
}
}
}

View File

@ -63,8 +63,8 @@ class EncryptionTests: XCTestCase {
let (client, server) = clientServer("aes-128-cbc", "sha256")
let plain = Data(hex: "00112233445566778899")
let encrypted = try! client.encrypter().encryptData(plain, extra: nil)
let decrypted = try! server.decrypter().decryptData(encrypted, extra: nil)
let encrypted = try! client.encrypter().encryptData(plain, flags: nil)
let decrypted = try! server.decrypter().decryptData(encrypted, flags: nil)
XCTAssertEqual(plain, decrypted)
}
@ -72,18 +72,19 @@ class EncryptionTests: XCTestCase {
let (client, server) = clientServer(nil, "sha256")
let plain = Data(hex: "00112233445566778899")
let encrypted = try! client.encrypter().encryptData(plain, extra: nil)
XCTAssertNoThrow(try server.decrypter().verifyData(encrypted, extra: nil))
let encrypted = try! client.encrypter().encryptData(plain, flags: nil)
XCTAssertNoThrow(try server.decrypter().verifyData(encrypted, flags: nil))
}
func testGCM() {
let (client, server) = clientServer("aes-256-gcm", nil)
// let packetId: UInt32 = 0x56341200
let extra: [UInt8] = [0x00, 0x12, 0x34, 0x56]
let ad: [UInt8] = [0x00, 0x12, 0x34, 0x56]
var flags = CryptoFlags(packetId: 0, ad: ad, adLength: 4)
let plain = Data(hex: "00112233445566778899")
let encrypted = try! client.encrypter().encryptData(plain, extra: extra)
let decrypted = try! server.decrypter().decryptData(encrypted, extra: extra)
let encrypted = try! client.encrypter().encryptData(plain, flags: &flags)
let decrypted = try! server.decrypter().decryptData(encrypted, flags: &flags)
XCTAssertEqual(plain, decrypted)
}

View File

@ -57,12 +57,12 @@ class TestUtils {
}
extension Encrypter {
func encryptData(_ data: Data, extra: [UInt8]?) throws -> Data {
func encryptData(_ data: Data, flags: UnsafePointer<CryptoFlags>?) 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)
try encryptBytes($0, length: srcLength, dest: &dest, destLength: &destLength, flags: flags)
}
dest.removeSubrange(destLength..<dest.count)
return Data(dest)
@ -70,21 +70,21 @@ extension Encrypter {
}
extension Decrypter {
func decryptData(_ data: Data, extra: [UInt8]?) throws -> Data {
func decryptData(_ data: Data, flags: UnsafePointer<CryptoFlags>?) 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)
try decryptBytes($0, length: srcLength, dest: &dest, destLength: &destLength, flags: flags)
}
dest.removeSubrange(destLength..<dest.count)
return Data(dest)
}
func verifyData(_ data: Data, extra: [UInt8]?) throws {
func verifyData(_ data: Data, flags: UnsafePointer<CryptoFlags>?) throws {
let srcLength = data.count
try data.withUnsafeBytes {
try verifyBytes($0, length: srcLength, extra: extra)
try verifyBytes($0, length: srcLength, flags: flags)
}
}
}