|
|
|
@ -56,13 +56,16 @@ static const NSUInteger kOWSBackupKeyLength = 32;
|
|
|
|
|
OWSAssert(srcFilePath.length > 0);
|
|
|
|
|
OWSAssert(encryptionKey.length > 0);
|
|
|
|
|
|
|
|
|
|
@autoreleasepool {
|
|
|
|
|
|
|
|
|
|
// TODO: Encrypt the file without loading it into memory.
|
|
|
|
|
NSData *_Nullable srcData = [NSData dataWithContentsOfFile:srcFilePath];
|
|
|
|
|
if (!srcData) {
|
|
|
|
|
OWSProdLogAndFail(@"%@ could not load file into memory", self.logTag);
|
|
|
|
|
if (srcData.length < 1) {
|
|
|
|
|
OWSProdLogAndFail(@"%@ could not load file into memory for encryption.", self.logTag);
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
return [self encryptDataAsTempFile:srcData encryptionKey:encryptionKey];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (nullable OWSBackupEncryptedItem *)encryptDataAsTempFile:(NSData *)srcData
|
|
|
|
@ -74,16 +77,20 @@ static const NSUInteger kOWSBackupKeyLength = 32;
|
|
|
|
|
return [self encryptDataAsTempFile:srcData encryptionKey:encryptionKey];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (nullable OWSBackupEncryptedItem *)encryptDataAsTempFile:(NSData *)srcData encryptionKey:(NSData *)encryptionKey
|
|
|
|
|
- (nullable OWSBackupEncryptedItem *)encryptDataAsTempFile:(NSData *)unencryptedData
|
|
|
|
|
encryptionKey:(NSData *)encryptionKey
|
|
|
|
|
{
|
|
|
|
|
OWSAssert(srcData);
|
|
|
|
|
OWSAssert(unencryptedData);
|
|
|
|
|
OWSAssert(encryptionKey.length > 0);
|
|
|
|
|
|
|
|
|
|
@autoreleasepool {
|
|
|
|
|
|
|
|
|
|
// TODO: Encrypt the data using key;
|
|
|
|
|
NSData *encryptedData = unencryptedData;
|
|
|
|
|
|
|
|
|
|
NSString *dstFilePath = [self.jobTempDirPath stringByAppendingPathComponent:[NSUUID UUID].UUIDString];
|
|
|
|
|
NSError *error;
|
|
|
|
|
BOOL success = [srcData writeToFile:dstFilePath options:NSDataWritingAtomic error:&error];
|
|
|
|
|
BOOL success = [encryptedData writeToFile:dstFilePath options:NSDataWritingAtomic error:&error];
|
|
|
|
|
if (!success || error) {
|
|
|
|
|
OWSProdLogAndFail(@"%@ error writing encrypted data: %@", self.logTag, error);
|
|
|
|
|
return nil;
|
|
|
|
@ -93,6 +100,7 @@ static const NSUInteger kOWSBackupKeyLength = 32;
|
|
|
|
|
item.filePath = dstFilePath;
|
|
|
|
|
item.encryptionKey = encryptionKey;
|
|
|
|
|
return item;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#pragma mark - Decrypt
|
|
|
|
@ -104,10 +112,12 @@ static const NSUInteger kOWSBackupKeyLength = 32;
|
|
|
|
|
OWSAssert(srcFilePath.length > 0);
|
|
|
|
|
OWSAssert(encryptionKey.length > 0);
|
|
|
|
|
|
|
|
|
|
@autoreleasepool {
|
|
|
|
|
|
|
|
|
|
// TODO: Decrypt the file without loading it into memory.
|
|
|
|
|
NSData *data = [self decryptFileAsData:srcFilePath encryptionKey:encryptionKey];
|
|
|
|
|
|
|
|
|
|
if (!data) {
|
|
|
|
|
if (data.length < 1) {
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -120,6 +130,7 @@ static const NSUInteger kOWSBackupKeyLength = 32;
|
|
|
|
|
[OWSFileSystem protectFileOrFolderAtPath:dstFilePath];
|
|
|
|
|
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (nullable NSData *)decryptFileAsData:(NSString *)srcFilePath encryptionKey:(NSData *)encryptionKey
|
|
|
|
@ -127,30 +138,36 @@ static const NSUInteger kOWSBackupKeyLength = 32;
|
|
|
|
|
OWSAssert(srcFilePath.length > 0);
|
|
|
|
|
OWSAssert(encryptionKey.length > 0);
|
|
|
|
|
|
|
|
|
|
@autoreleasepool {
|
|
|
|
|
|
|
|
|
|
if (![NSFileManager.defaultManager fileExistsAtPath:srcFilePath]) {
|
|
|
|
|
DDLogError(@"%@ missing downloaded file.", self.logTag);
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Decrypt the file without loading it into memory.
|
|
|
|
|
NSData *_Nullable srcData = [NSData dataWithContentsOfFile:srcFilePath];
|
|
|
|
|
if (!srcData) {
|
|
|
|
|
OWSProdLogAndFail(@"%@ could not load file into memory", self.logTag);
|
|
|
|
|
if (srcData.length < 1) {
|
|
|
|
|
OWSProdLogAndFail(@"%@ could not load file into memory for decryption.", self.logTag);
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NSData *_Nullable dstData = [self decryptDataAsData:srcData encryptionKey:encryptionKey];
|
|
|
|
|
return dstData;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (nullable NSData *)decryptDataAsData:(NSData *)srcData encryptionKey:(NSData *)encryptionKey
|
|
|
|
|
- (nullable NSData *)decryptDataAsData:(NSData *)encryptedData encryptionKey:(NSData *)encryptionKey
|
|
|
|
|
{
|
|
|
|
|
OWSAssert(srcData);
|
|
|
|
|
OWSAssert(encryptedData);
|
|
|
|
|
OWSAssert(encryptionKey.length > 0);
|
|
|
|
|
|
|
|
|
|
@autoreleasepool {
|
|
|
|
|
|
|
|
|
|
// TODO: Decrypt the data using key;
|
|
|
|
|
NSData *unencryptedData = encryptedData;
|
|
|
|
|
|
|
|
|
|
return srcData;
|
|
|
|
|
return unencryptedData;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#pragma mark - Compression
|
|
|
|
@ -159,6 +176,8 @@ static const NSUInteger kOWSBackupKeyLength = 32;
|
|
|
|
|
{
|
|
|
|
|
OWSAssert(srcData);
|
|
|
|
|
|
|
|
|
|
@autoreleasepool {
|
|
|
|
|
|
|
|
|
|
if (!srcData) {
|
|
|
|
|
OWSProdLogAndFail(@"%@ missing unencrypted data.", self.logTag);
|
|
|
|
|
return nil;
|
|
|
|
@ -172,27 +191,32 @@ static const NSUInteger kOWSBackupKeyLength = 32;
|
|
|
|
|
// This assumes that dst will always be smaller than src.
|
|
|
|
|
//
|
|
|
|
|
// We slightly pad the buffer size to account for the worst case.
|
|
|
|
|
uint8_t *dstBuffer = malloc(sizeof(uint8_t) * srcLength) + 64 * 1024;
|
|
|
|
|
size_t dstBufferLength = srcLength + 64 * 1024;
|
|
|
|
|
uint8_t *dstBuffer = malloc(sizeof(uint8_t) * dstBufferLength);
|
|
|
|
|
if (!dstBuffer) {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
// TODO: Should we use COMPRESSION_LZFSE?
|
|
|
|
|
size_t dstLength = compression_encode_buffer(dstBuffer, srcLength, srcBuffer, srcLength, NULL, COMPRESSION_LZFSE);
|
|
|
|
|
NSData *compressedData = [NSData dataWithBytes:dstBuffer length:dstLength];
|
|
|
|
|
size_t dstLength
|
|
|
|
|
= compression_encode_buffer(dstBuffer, dstBufferLength, srcBuffer, srcLength, NULL, COMPRESSION_LZFSE);
|
|
|
|
|
NSData *compressedData = [NSData dataWithBytesNoCopy:dstBuffer length:dstLength freeWhenDone:YES];
|
|
|
|
|
|
|
|
|
|
DDLogVerbose(@"%@ compressed %zd -> %zd = %0.2f",
|
|
|
|
|
self.logTag,
|
|
|
|
|
srcLength,
|
|
|
|
|
dstLength,
|
|
|
|
|
(srcLength > 0 ? (dstLength / (CGFloat)srcLength) : 0));
|
|
|
|
|
free(dstBuffer);
|
|
|
|
|
|
|
|
|
|
return compressedData;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (nullable NSData *)decompressData:(NSData *)srcData uncompressedDataLength:(NSUInteger)uncompressedDataLength
|
|
|
|
|
{
|
|
|
|
|
OWSAssert(srcData);
|
|
|
|
|
|
|
|
|
|
@autoreleasepool {
|
|
|
|
|
|
|
|
|
|
if (!srcData) {
|
|
|
|
|
OWSProdLogAndFail(@"%@ missing unencrypted data.", self.logTag);
|
|
|
|
|
return nil;
|
|
|
|
@ -204,22 +228,24 @@ static const NSUInteger kOWSBackupKeyLength = 32;
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
// We pad the buffer to be defensive.
|
|
|
|
|
uint8_t *dstBuffer = malloc(sizeof(uint8_t) * (uncompressedDataLength + 1024));
|
|
|
|
|
size_t dstBufferLength = uncompressedDataLength + 1024;
|
|
|
|
|
uint8_t *dstBuffer = malloc(sizeof(uint8_t) * dstBufferLength);
|
|
|
|
|
if (!dstBuffer) {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
// TODO: Should we use COMPRESSION_LZFSE?
|
|
|
|
|
size_t dstLength = compression_decode_buffer(dstBuffer, srcLength, srcBuffer, srcLength, NULL, COMPRESSION_LZFSE);
|
|
|
|
|
NSData *decompressedData = [NSData dataWithBytes:dstBuffer length:dstLength];
|
|
|
|
|
size_t dstLength
|
|
|
|
|
= compression_decode_buffer(dstBuffer, dstBufferLength, srcBuffer, srcLength, NULL, COMPRESSION_LZFSE);
|
|
|
|
|
NSData *decompressedData = [NSData dataWithBytesNoCopy:dstBuffer length:dstLength freeWhenDone:YES];
|
|
|
|
|
OWSAssert(decompressedData.length == uncompressedDataLength);
|
|
|
|
|
DDLogVerbose(@"%@ decompressed %zd -> %zd = %0.2f",
|
|
|
|
|
self.logTag,
|
|
|
|
|
srcLength,
|
|
|
|
|
dstLength,
|
|
|
|
|
(dstLength > 0 ? (srcLength / (CGFloat)dstLength) : 0));
|
|
|
|
|
free(dstBuffer);
|
|
|
|
|
|
|
|
|
|
return decompressedData;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|