From 5a6beaebdc560c5363e487cf04d4ba95c30b0595 Mon Sep 17 00:00:00 2001 From: Stefan Reitshamer Date: Mon, 10 Jul 2017 06:18:28 -0400 Subject: [PATCH] updated to support new encryptionv3.dat file --- repo/EncryptionDatFile.m | 44 +++++++++++++++++++++++++++++++++++++--- repo/ObjectEncryptorV2.h | 3 ++- repo/ObjectEncryptorV2.m | 33 +++++++++++++++++++++++++----- 3 files changed, 71 insertions(+), 9 deletions(-) diff --git a/repo/EncryptionDatFile.m b/repo/EncryptionDatFile.m index 830c367..3ea30c1 100644 --- a/repo/EncryptionDatFile.m +++ b/repo/EncryptionDatFile.m @@ -68,12 +68,24 @@ error:(NSError **)error { NSError *myError = nil; - // Try to read local v2 file. + // Try to read local v3 file. EncryptionDatFile *datFile = [[[EncryptionDatFile alloc] initFromLocalCacheWithEncryptionPassword:theEncryptionPassword target:theTarget computerUUID:theComputerUUID - encryptionVersion:2 + encryptionVersion:3 error:&myError] autorelease]; + if (datFile == nil) { + if ([myError code] != ERROR_NOT_FOUND) { + SETERRORFROMMYERROR; + return nil; + } + // Try to read local v2 file. + datFile = [[[EncryptionDatFile alloc] initFromLocalCacheWithEncryptionPassword:theEncryptionPassword + target:theTarget + computerUUID:theComputerUUID + encryptionVersion:2 + error:&myError] autorelease]; + } if (datFile == nil) { if ([myError code] != ERROR_NOT_FOUND) { SETERRORFROMMYERROR; @@ -86,6 +98,25 @@ encryptionVersion:1 error:&myError] autorelease]; } + if (datFile == nil) { + if ([myError code] != ERROR_NOT_FOUND) { + SETERRORFROMMYERROR; + return nil; + } + // Try to read v3 file from target. + datFile = [[[EncryptionDatFile alloc] initFromTargetWithEncryptionPassword:theEncryptionPassword + target:theTarget + computerUUID:theComputerUUID + encryptionVersion:3 + targetConnectionDelegate:theTCD + error:&myError] autorelease]; + if (datFile != nil) { + NSError *cacheError = nil; + if (![datFile saveToLocalCache:&cacheError]) { + HSLogError(@"failed to save encryption dat file to local cache: %@", cacheError); + } + } + } if (datFile == nil) { if ([myError code] != ERROR_NOT_FOUND) { SETERRORFROMMYERROR; @@ -300,7 +331,8 @@ } // Decrypt master keys. - size_t theMasterKeysLen = kCCKeySizeAES256 * 2 + kCCBlockSizeAES128; + NSUInteger expectedKeysLen = (encryptionVersion == 3) ? (kCCKeySizeAES256 * 3) : (kCCKeySizeAES256 * 2); + size_t theMasterKeysLen = expectedKeysLen + kCCBlockSizeAES128; NSMutableData *theMasterKeys = [NSMutableData dataWithLength:theMasterKeysLen]; size_t theMasterKeysActualLen = 0; const unsigned char *encryptedMasterKeys = bytes + strlen(HEADER) + SALT_LENGTH + CC_SHA256_DIGEST_LENGTH + IV_LENGTH; @@ -327,6 +359,12 @@ [masterKeys release]; masterKeys = [theMasterKeys copy]; + + if ([masterKeys length] != expectedKeysLen && encryptionVersion != 1) { + SETNSERROR([EncryptionDatFile errorDomain], -1, @"unexpected master keys length %ld (expected %ld)", [masterKeys length], expectedKeysLen); + return NO; + } + return YES; } diff --git a/repo/ObjectEncryptorV2.h b/repo/ObjectEncryptorV2.h index 78910df..76a922c 100644 --- a/repo/ObjectEncryptorV2.h +++ b/repo/ObjectEncryptorV2.h @@ -40,13 +40,14 @@ @interface ObjectEncryptorV2 : NSObject { Target *target; NSString *computerUUID; - NSData *computerUUIDData; + NSData *blobKeySaltData; NSData *masterKeys; const void *masterKey; const void *hmacKey; unsigned char *symmetricKey; NSLock *symmetricKeyLock; int encryptCount; + int encryptionVersion; } - (id)initWithTarget:(Target *)theTarget diff --git a/repo/ObjectEncryptorV2.m b/repo/ObjectEncryptorV2.m index 8ce1333..6d8a7f1 100644 --- a/repo/ObjectEncryptorV2.m +++ b/repo/ObjectEncryptorV2.m @@ -50,8 +50,9 @@ #define SYMMETRIC_KEY_LEN kCCKeySizeAES256 #define DATA_IV_AND_SYMMETRIC_KEY_LEN (IV_LEN + SYMMETRIC_KEY_LEN) #define ENCRYPTED_DATA_IV_AND_SYMMETRIC_KEY_LEN (DATA_IV_AND_SYMMETRIC_KEY_LEN + kCCBlockSizeAES128) -#define ENCRYPTION_VERSION (2) #define MAX_ENCRYPTIONS_PER_SYMMETRIC_KEY (256) +#define V3_MASTER_KEYS_LEN (kCCKeySizeAES256 * 3) +#define V2_MASTER_KEYS_LEN (kCCKeySizeAES256 * 2) @implementation ObjectEncryptorV2 @@ -63,7 +64,6 @@ if (self = [super init]) { target = [theTarget retain]; computerUUID = [theComputerUUID retain]; - computerUUIDData = [[computerUUID dataUsingEncoding:NSUTF8StringEncoding] retain]; symmetricKey = (unsigned char *)malloc(SYMMETRIC_KEY_LEN); @@ -71,6 +71,28 @@ masterKey = [masterKeys bytes]; hmacKey = (unsigned char *)masterKey + kCCKeySizeAES256; + encryptionVersion = [theEDF encryptionVersion]; + + if ([theEDF encryptionVersion] == 3) { + if ([masterKeys length] != V3_MASTER_KEYS_LEN) { + SETNSERROR([ObjectEncryptor errorDomain], -1, @"master keys data is not %d bytes", V3_MASTER_KEYS_LEN); + [self release]; + return nil; + } + blobKeySaltData = [[NSData alloc] initWithBytes:(hmacKey + kCCKeySizeAES256) length:kCCKeySizeAES256]; + } else if ([theEDF encryptionVersion] == 2) { + if ([masterKeys length] != V2_MASTER_KEYS_LEN) { + SETNSERROR([ObjectEncryptor errorDomain], -1, @"master keys data is not %d bytes", V2_MASTER_KEYS_LEN); + [self release]; + return nil; + } + blobKeySaltData = [[computerUUID dataUsingEncoding:NSUTF8StringEncoding] retain]; + } else { + SETNSERROR([ObjectEncryptor errorDomain], -1, @"unexpected encryption version: %d", [theEDF encryptionVersion]); + [self release]; + return nil; + } + [self resetSymmetricKey]; symmetricKeyLock = [[NSLock alloc] init]; [symmetricKeyLock setName:@"symmetric key lock"]; @@ -81,6 +103,7 @@ - (void)dealloc { [target release]; [computerUUID release]; + [blobKeySaltData release]; [masterKeys release]; free(symmetricKey); [symmetricKeyLock release]; @@ -91,14 +114,14 @@ #pragma ObjectEncryptorImpl - (BOOL)ensureDatFileExistsAtTargetWithEncryptionPassword:(NSString *)theEncryptionPassword targetConnectionDelegate:(id)theTCD error:(NSError **)error { NSError *myError = nil; - EncryptionDatFile *encryptionDatFile = [[[EncryptionDatFile alloc] initFromTargetWithEncryptionPassword:theEncryptionPassword target:target computerUUID:computerUUID encryptionVersion:ENCRYPTION_VERSION targetConnectionDelegate:theTCD error:&myError] autorelease]; + EncryptionDatFile *encryptionDatFile = [[[EncryptionDatFile alloc] initFromTargetWithEncryptionPassword:theEncryptionPassword target:target computerUUID:computerUUID encryptionVersion:encryptionVersion targetConnectionDelegate:theTCD error:&myError] autorelease]; if (encryptionDatFile == nil) { if ([myError code] != ERROR_NOT_FOUND) { SETERRORFROMMYERROR; return NO; } - encryptionDatFile = [[[EncryptionDatFile alloc] initFromLocalCacheWithEncryptionPassword:theEncryptionPassword target:target computerUUID:computerUUID encryptionVersion:ENCRYPTION_VERSION error:error] autorelease]; + encryptionDatFile = [[[EncryptionDatFile alloc] initFromLocalCacheWithEncryptionPassword:theEncryptionPassword target:target computerUUID:computerUUID encryptionVersion:encryptionVersion error:error] autorelease]; if (encryptionDatFile == nil) { SETERRORFROMMYERROR; return NO; @@ -122,7 +145,7 @@ unsigned char digest[CC_SHA1_DIGEST_LENGTH]; CC_SHA1_CTX ctx; CC_SHA1_Init(&ctx); - CC_SHA1_Update(&ctx, [computerUUIDData bytes], (CC_LONG)[computerUUIDData length]); + CC_SHA1_Update(&ctx, [blobKeySaltData bytes], (CC_LONG)[blobKeySaltData length]); CC_SHA1_Update(&ctx, [theData bytes], (CC_LONG)[theData length]); CC_SHA1_Final(digest, &ctx); return [NSString hexStringWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];