aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPDataAdditions.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/SPDataAdditions.m')
-rw-r--r--Source/SPDataAdditions.m58
1 files changed, 45 insertions, 13 deletions
diff --git a/Source/SPDataAdditions.m b/Source/SPDataAdditions.m
index 4a07c437..8002595c 100644
--- a/Source/SPDataAdditions.m
+++ b/Source/SPDataAdditions.m
@@ -35,7 +35,6 @@
#import "SPDataAdditions.h"
#include <zlib.h>
-#include <openssl/aes.h>
#include <CommonCrypto/CommonCrypto.h>
#include <stdlib.h>
@@ -172,23 +171,50 @@ uint32_t LimitUInt32(NSUInteger i);
- (NSData *)dataDecryptedWithPassword:(NSString *)password
{
// Create the key from the password hash
- NSData *passwordDigest = [[password dataUsingEncoding:NSUTF8StringEncoding] sha1Hash];
+ NSData *passwordDigest = [[[password dataUsingEncoding:NSUTF8StringEncoding] sha1Hash] subdataWithRange:NSMakeRange(0, kCCKeySizeAES128)];
+
+ return [self dataDecryptedWithKey:passwordDigest];
- // AES-128-cbc decrypt the data
- AES_KEY aesKey;
- AES_set_decrypt_key([passwordDigest bytes], 128, &aesKey);
+}
+
+- (NSData *)dataDecryptedWithKey:(NSData *)aesKey
+{
+ if([aesKey length] != kCCKeySizeAES128)
+ @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Key length invalid. Must be kCCKeySizeAES128 bytes!" userInfo:nil];
+
+ if([self length] < (2*kCCBlockSizeAES128) || [self length] > UINT32_MAX)
+ @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Length of encrypted NSData must be in range 32 to 2^32!" userInfo:nil];
// Total length = encrypted length + IV
- NSInteger totalLength = [self length];
- NSInteger encryptedLength = totalLength - 16;
+ NSUInteger totalLength = [self length];
+ NSUInteger encryptedLength = totalLength - kCCBlockSizeAES128; // >=0 ensured above
// Take the IV from the first 128-bit block
- unsigned char iv[16];
- memcpy(iv, [self bytes], 16);
+ unsigned char iv[kCCBlockSizeAES128];
+ memcpy(iv, [self bytes], kCCBlockSizeAES128);
// Decrypt the data
- unsigned char *decryptedBytes = (unsigned char*)malloc(encryptedLength);
- AES_cbc_encrypt([self bytes] + 16, decryptedBytes, encryptedLength, &aesKey, iv, AES_DECRYPT);
+ unsigned char *decryptedBytes = calloc(1,encryptedLength);
+
+ CCCryptorStatus res = CCCrypt(
+ kCCDecrypt, // operation mode
+ kCCAlgorithmAES128, // algorithm
+ 0, // options. We use our own padding algorithm and CBC is the default
+ [aesKey bytes], // key bytes
+ kCCKeySizeAES128, // key length
+ iv, // iv bytes (length == block size)
+ ([self bytes] + kCCBlockSizeAES128), // raw data
+ encryptedLength, // length of raw data
+ decryptedBytes, // output buffer. overwriting input is OK
+ encryptedLength, // output buffer size
+ NULL // number of bytes written. not relevant here
+ );
+
+ if(res != kCCSuccess) {
+ @throw [NSException exceptionWithName:SPCommonCryptoExceptionName
+ reason:[NSString stringWithFormat:@"CCCrypt() failed! (CCCryptorStatus=%d)",res]
+ userInfo:@{@"cryptorStatus":@(res)}];
+ }
// If decryption was successful, these blocks will be zeroed
if ( *((UInt32*)decryptedBytes + ((encryptedLength / 4) - 4)) ||
@@ -200,8 +226,14 @@ uint32_t LimitUInt32(NSUInteger i);
}
// Get the size of the data from the last 32-bit chunk
- NSInteger bigIntDataLength = *((UInt32*)decryptedBytes + ((encryptedLength / 4) - 1));
- NSInteger dataLength = NSSwapBigIntToHost((unsigned int)bigIntDataLength);
+ uint32_t bigIntDataLength = *((UInt32*)decryptedBytes + ((encryptedLength / sizeof(UInt32)) - 1));
+ uint32_t dataLength = NSSwapBigIntToHost(bigIntDataLength);
+
+ if(dataLength >= (encryptedLength-sizeof(UInt32))) { //this way dataLength can still reach into padding, but we own that memory anyway.
+ @throw [NSException exceptionWithName:NSInternalInconsistencyException
+ reason:[NSString stringWithFormat:@"dataLength=%u exceeds encryptedLength=%lu! Either the message is incomplete, decrypting resulted in invalid data, or this is a malicious message!",dataLength,encryptedLength]
+ userInfo:nil];
+ }
return [NSData dataWithBytesNoCopy:decryptedBytes length:dataLength];
}