Clean up data.

pull/1/head
Matthew Chen 7 years ago committed by Michael Kirk
parent 1824d7dcef
commit 87f4b0ac2e

@ -107,8 +107,12 @@ NS_ASSUME_NONNULL_BEGIN
NSData *_Nullable avatarData = [Contact avatarDataForCNContact:cnContact]; NSData *_Nullable avatarData = [Contact avatarDataForCNContact:cnContact];
if (avatarData) { if (avatarData) {
NSUInteger hashValue = 0; NSUInteger hashValue = 0;
NSData *hashData = [Cryptography computeSHA256Digest:avatarData truncatedToBytes:sizeof(hashValue)]; NSData *_Nullable hashData = [Cryptography computeSHA256Digest:avatarData truncatedToBytes:sizeof(hashValue)];
[hashData getBytes:&hashValue length:sizeof(hashValue)]; if (hashData) {
[hashData getBytes:&hashValue length:sizeof(hashValue)];
} else {
OWSProdLogAndFail(@"%@ could not compute hash for avatar.", self.logTag);
}
_imageHash = hashValue; _imageHash = hashValue;
} else { } else {
_imageHash = 0; _imageHash = 0;

@ -455,12 +455,16 @@ NS_ASSUME_NONNULL_BEGIN
{ {
NSData *contactData = [colorSeed dataUsingEncoding:NSUTF8StringEncoding]; NSData *contactData = [colorSeed dataUsingEncoding:NSUTF8StringEncoding];
NSUInteger hashingLength = sizeof(unsigned long long); unsigned long long hash = 0;
unsigned long long choose; NSUInteger hashingLength = sizeof(hash);
NSData *hashData = [Cryptography computeSHA256Digest:contactData truncatedToBytes:hashingLength]; NSData *_Nullable hashData = [Cryptography computeSHA256Digest:contactData truncatedToBytes:hashingLength];
[hashData getBytes:&choose length:hashingLength]; if (hashData) {
[hashData getBytes:&hash length:hashingLength];
NSUInteger index = (choose % [self.conversationColorNames count]); } else {
OWSProdLogAndFail(@"%@ could not compute hash for color seed.", self.logTag);
}
NSUInteger index = (hash % [self.conversationColorNames count]);
return [self.conversationColorNames objectAtIndex:index]; return [self.conversationColorNames objectAtIndex:index];
} }

@ -222,11 +222,11 @@ static const CGFloat kAttachmentDownloadProgressTheta = 0.001f;
failure:(void (^)(NSError *error))failureHandler failure:(void (^)(NSError *error))failureHandler
{ {
NSError *decryptError; NSError *decryptError;
NSData *plaintext = [Cryptography decryptAttachment:cipherText NSData *_Nullable plaintext = [Cryptography decryptAttachment:cipherText
withKey:attachment.encryptionKey withKey:attachment.encryptionKey
digest:attachment.digest digest:attachment.digest
unpaddedSize:attachment.byteCount unpaddedSize:attachment.byteCount
error:&decryptError]; error:&decryptError];
if (decryptError) { if (decryptError) {
DDLogError(@"%@ failed to decrypt with error: %@", self.logTag, decryptError); DDLogError(@"%@ failed to decrypt with error: %@", self.logTag, decryptError);

@ -120,9 +120,15 @@ static const CGFloat kAttachmentUploadProgressTheta = 0.001f;
NSData *encryptionKey; NSData *encryptionKey;
NSData *digest; NSData *digest;
NSData *encryptedAttachmentData = NSData *_Nullable encryptedAttachmentData =
[Cryptography encryptAttachmentData:attachmentData outKey:&encryptionKey outDigest:&digest]; [Cryptography encryptAttachmentData:attachmentData outKey:&encryptionKey outDigest:&digest];
if (!encryptedAttachmentData) {
OWSProdLogAndFail(@"%@ could not encrypt attachment data.", self.logTag);
error = OWSErrorMakeFailedToSendOutgoingMessageError();
error.isRetryable = YES;
[self reportError:error];
return;
}
attachmentStream.encryptionKey = encryptionKey; attachmentStream.encryptionKey = encryptionKey;
attachmentStream.digest = digest; attachmentStream.digest = digest;

@ -738,8 +738,9 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@try { @try {
NSData *decryptedPayload = [Cryptography decryptAppleMessagePayload:message.body NSData *_Nullable decryptedPayload =
withSignalingKey:TSAccountManager.signalingKey]; [Cryptography decryptAppleMessagePayload:message.body
withSignalingKey:TSAccountManager.signalingKey];
if (!decryptedPayload) { if (!decryptedPayload) {
DDLogWarn(@"%@ Failed to decrypt incoming payload or bad HMAC", self.logTag); DDLogWarn(@"%@ Failed to decrypt incoming payload or bad HMAC", self.logTag);

@ -39,35 +39,30 @@ typedef NS_ENUM(NSInteger, TSMACType) {
+ (uint32_t)randomUInt32; + (uint32_t)randomUInt32;
+ (uint64_t)randomUInt64; + (uint64_t)randomUInt64;
#pragma mark SHA and HMAC methods #pragma mark - SHA and HMAC methods
// Full length SHA256 digest for `data` // Full length SHA256 digest for `data`
+ (NSData *)computeSHA256Digest:(NSData *)data; + (nullable NSData *)computeSHA256Digest:(NSData *)data;
// Truncated SHA256 digest for `data` // Truncated SHA256 digest for `data`
+ (NSData *)computeSHA256Digest:(NSData *)data truncatedToBytes:(NSUInteger)truncatedBytes; + (nullable NSData *)computeSHA256Digest:(NSData *)data truncatedToBytes:(NSUInteger)truncatedBytes;
+ (NSString *)truncatedSHA1Base64EncodedWithoutPadding:(NSString *)string; + (nullable NSString *)truncatedSHA1Base64EncodedWithoutPadding:(NSString *)string;
+ (NSString *)computeSHA1DigestForString:(NSString *)input;
+ (NSData *)computeSHA256HMAC:(NSData *)dataToHMAC withHMACKey:(NSData *)HMACKey; + (nullable NSData *)decryptAppleMessagePayload:(NSData *)payload withSignalingKey:(NSString *)signalingKeyString;
+ (NSData *)computeSHA1HMAC:(NSData *)dataToHMAC withHMACKey:(NSData *)HMACKey;
+ (NSData *)truncatedSHA1HMAC:(NSData *)dataToHMAC withHMACKey:(NSData *)HMACKey truncation:(NSUInteger)bytes;
+ (NSData *)decryptAppleMessagePayload:(NSData *)payload withSignalingKey:(NSString *)signalingKeyString;
#pragma mark encrypt and decrypt attachment data #pragma mark encrypt and decrypt attachment data
// Though digest can and will be nil for legacy clients, we now reject attachments lacking a digest. // Though digest can and will be nil for legacy clients, we now reject attachments lacking a digest.
+ (NSData *)decryptAttachment:(NSData *)dataToDecrypt + (nullable NSData *)decryptAttachment:(NSData *)dataToDecrypt
withKey:(NSData *)key withKey:(NSData *)key
digest:(nullable NSData *)digest digest:(nullable NSData *)digest
unpaddedSize:(UInt32)unpaddedSize unpaddedSize:(UInt32)unpaddedSize
error:(NSError **)error; error:(NSError **)error;
+ (NSData *)encryptAttachmentData:(NSData *)attachmentData + (nullable NSData *)encryptAttachmentData:(NSData *)attachmentData
outKey:(NSData *_Nonnull *_Nullable)outKey outKey:(NSData *_Nonnull *_Nullable)outKey
outDigest:(NSData *_Nonnull *_Nullable)outDigest; outDigest:(NSData *_Nonnull *_Nullable)outDigest;
+ (nullable NSData *)encryptAESGCMWithData:(NSData *)plaintextData key:(OWSAES256Key *)key; + (nullable NSData *)encryptAESGCMWithData:(NSData *)plaintextData key:(OWSAES256Key *)key;
+ (nullable NSData *)decryptAESGCMWithData:(NSData *)encryptedData key:(OWSAES256Key *)key; + (nullable NSData *)decryptAESGCMWithData:(NSData *)encryptedData key:(OWSAES256Key *)key;

@ -18,7 +18,6 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
// Returned by many OpenSSL functions - indicating success // Returned by many OpenSSL functions - indicating success
const int kOpenSSLSuccess = 1; const int kOpenSSLSuccess = 1;
@ -98,7 +97,7 @@ const NSUInteger kAES256_KeyByteLength = 32;
@implementation Cryptography @implementation Cryptography
#pragma mark random bytes methods #pragma mark - random bytes methods
+ (NSData *)generateRandomBytes:(NSUInteger)numberBytes + (NSData *)generateRandomBytes:(NSUInteger)numberBytes
{ {
@ -123,93 +122,119 @@ const NSUInteger kAES256_KeyByteLength = 32;
return result; return result;
} }
#pragma mark SHA1 #pragma mark - SHA1
+ (NSString *)truncatedSHA1Base64EncodedWithoutPadding:(NSString *)string { // Used by TSContactManager to send hashed/truncated contact list to server.
/* used by TSContactManager to send hashed/truncated contact list to server */ + (nullable NSString *)truncatedSHA1Base64EncodedWithoutPadding:(NSString *)string
NSMutableData *hashData = [NSMutableData dataWithLength:20]; {
NSData *_Nullable stringData = [string dataUsingEncoding:NSUTF8StringEncoding];
if (!stringData) {
OWSFail(@"%@ could not convert string to utf-8.", self.logTag);
return nil;
}
if (stringData.length >= UINT32_MAX) {
OWSFail(@"%@ string data is too long.", self.logTag);
return nil;
}
uint32_t dataLength = (uint32_t)stringData.length;
CC_SHA1([string dataUsingEncoding:NSUTF8StringEncoding].bytes, NSMutableData *hashData = [NSMutableData dataWithLength:20];
(unsigned int)[string dataUsingEncoding:NSUTF8StringEncoding].length, CC_SHA1(stringData.bytes, dataLength, hashData.mutableBytes);
hashData.mutableBytes);
NSData *truncatedData = [hashData subdataWithRange:NSMakeRange(0, 10)]; NSData *truncatedData = [hashData subdataWithRange:NSMakeRange(0, 10)];
return [[truncatedData base64EncodedString] stringByReplacingOccurrencesOfString:@"=" withString:@""]; return [[truncatedData base64EncodedString] stringByReplacingOccurrencesOfString:@"=" withString:@""];
} }
+ (NSString *)computeSHA1DigestForString:(NSString *)input { #pragma mark - SHA256 Digest
// Here we are taking in our string hash, placing that inside of a C Char Array, then parsing it through the SHA1
// encryption method.
const char *cstr = [input cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:input.length];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, (unsigned int)data.length, digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) { + (nullable NSData *)computeSHA256Digest:(NSData *)data
[output appendFormat:@"%02x", digest[i]];
}
return output;
}
#pragma mark SHA256 Digest
+ (NSData *)computeSHA256Digest:(NSData *)data
{ {
return [self computeSHA256Digest:(NSData *)data truncatedToBytes:CC_SHA256_DIGEST_LENGTH]; return [self computeSHA256Digest:data truncatedToBytes:CC_SHA256_DIGEST_LENGTH];
} }
+ (NSData *)computeSHA256Digest:(NSData *)data truncatedToBytes:(NSUInteger)truncatedBytes + (nullable NSData *)computeSHA256Digest:(NSData *)data truncatedToBytes:(NSUInteger)truncatedBytes
{ {
if (data.length >= UINT32_MAX) {
OWSFail(@"%@ data is too long.", self.logTag);
return nil;
}
uint32_t dataLength = (uint32_t)data.length;
uint8_t digest[CC_SHA256_DIGEST_LENGTH]; uint8_t digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(data.bytes, (unsigned int)data.length, digest); CC_SHA256(data.bytes, dataLength, digest);
return return
[[NSData dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH] subdataWithRange:NSMakeRange(0, truncatedBytes)]; [[NSData dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH] subdataWithRange:NSMakeRange(0, truncatedBytes)];
} }
#pragma mark - HMAC/SHA256
+ (nullable NSData *)computeSHA256HMAC:(NSData *)data withHMACKey:(NSData *)HMACKey
{
if (data.length >= SIZE_MAX) {
OWSFail(@"%@ data is too long.", self.logTag);
return nil;
}
size_t dataLength = (size_t)data.length;
if (HMACKey.length >= SIZE_MAX) {
OWSFail(@"%@ HMAC key is too long.", self.logTag);
return nil;
}
size_t hmacKeyLength = (size_t)HMACKey.length;
#pragma mark HMAC/SHA256
+ (NSData *)computeSHA256HMAC:(NSData *)dataToHMAC withHMACKey:(NSData *)HMACKey {
uint8_t ourHmac[CC_SHA256_DIGEST_LENGTH] = {0}; uint8_t ourHmac[CC_SHA256_DIGEST_LENGTH] = {0};
CCHmac(kCCHmacAlgSHA256, [HMACKey bytes], [HMACKey length], [dataToHMAC bytes], [dataToHMAC length], ourHmac); CCHmac(kCCHmacAlgSHA256, [HMACKey bytes], hmacKeyLength, [data bytes], dataLength, ourHmac);
return [NSData dataWithBytes:ourHmac length:CC_SHA256_DIGEST_LENGTH]; return [NSData dataWithBytes:ourHmac length:CC_SHA256_DIGEST_LENGTH];
} }
+ (NSData *)computeSHA1HMAC:(NSData *)dataToHMAC withHMACKey:(NSData *)HMACKey { + (nullable NSData *)computeSHA1HMAC:(NSData *)data withHMACKey:(NSData *)HMACKey
{
if (data.length >= SIZE_MAX) {
OWSFail(@"%@ data is too long.", self.logTag);
return nil;
}
size_t dataLength = (size_t)data.length;
if (HMACKey.length >= SIZE_MAX) {
OWSFail(@"%@ HMAC key is too long.", self.logTag);
return nil;
}
size_t hmacKeyLength = (size_t)HMACKey.length;
uint8_t ourHmac[CC_SHA256_DIGEST_LENGTH] = {0}; uint8_t ourHmac[CC_SHA256_DIGEST_LENGTH] = {0};
CCHmac(kCCHmacAlgSHA1, [HMACKey bytes], [HMACKey length], [dataToHMAC bytes], [dataToHMAC length], ourHmac); CCHmac(kCCHmacAlgSHA1, [HMACKey bytes], hmacKeyLength, [data bytes], dataLength, ourHmac);
return [NSData dataWithBytes:ourHmac length:CC_SHA256_DIGEST_LENGTH]; return [NSData dataWithBytes:ourHmac length:CC_SHA256_DIGEST_LENGTH];
} }
+ (nullable NSData *)truncatedSHA1HMAC:(NSData *)dataToHMAC withHMACKey:(NSData *)HMACKey truncation:(NSUInteger)bytes
+ (NSData *)truncatedSHA1HMAC:(NSData *)dataToHMAC withHMACKey:(NSData *)HMACKey truncation:(NSUInteger)bytes { {
return [[Cryptography computeSHA1HMAC:dataToHMAC withHMACKey:HMACKey] subdataWithRange:NSMakeRange(0, bytes)]; return [[Cryptography computeSHA1HMAC:dataToHMAC withHMACKey:HMACKey] subdataWithRange:NSMakeRange(0, bytes)];
} }
+ (NSData *)truncatedSHA256HMAC:(NSData *)dataToHMAC withHMACKey:(NSData *)HMACKey truncation:(NSUInteger)bytes { + (nullable NSData *)truncatedSHA256HMAC:(NSData *)dataToHMAC withHMACKey:(NSData *)HMACKey truncation:(NSUInteger)bytes
{
return [[Cryptography computeSHA256HMAC:dataToHMAC withHMACKey:HMACKey] subdataWithRange:NSMakeRange(0, bytes)]; return [[Cryptography computeSHA256HMAC:dataToHMAC withHMACKey:HMACKey] subdataWithRange:NSMakeRange(0, bytes)];
} }
#pragma mark - AES CBC Mode
#pragma mark AES CBC Mode
/** /**
* AES256 CBC encrypt then mac. Used to decrypt both signal messages and attachment blobs * AES256 CBC encrypt then mac. Used to decrypt both signal messages and attachment blobs
* *
* @return decrypted data or nil if hmac invalid/decryption fails * @return decrypted data or nil if hmac invalid/decryption fails
*/ */
+ (NSData *)decryptCBCMode:(NSData *)dataToDecrypt + (nullable NSData *)decryptCBCMode:(NSData *)dataToDecrypt
key:(NSData *)key key:(NSData *)key
IV:(NSData *)iv IV:(NSData *)iv
version:(nullable NSData *)version version:(nullable NSData *)version
HMACKey:(NSData *)hmacKey HMACKey:(NSData *)hmacKey
HMACType:(TSMACType)hmacType HMACType:(TSMACType)hmacType
matchingHMAC:(NSData *)hmac matchingHMAC:(NSData *)hmac
digest:(nullable NSData *)digest digest:(nullable NSData *)digest
{ {
if (dataToDecrypt.length >= (SIZE_MAX - kCCBlockSizeAES128)) {
OWSFail(@"%@ data is too long.", self.logTag);
return nil;
}
// Verify hmac of: version? || iv || encrypted data // Verify hmac of: version? || iv || encrypted data
NSMutableData *dataToAuth = [NSMutableData data]; NSMutableData *dataToAuth = [NSMutableData data];
if (version != nil) { if (version != nil) {
@ -219,7 +244,7 @@ const NSUInteger kAES256_KeyByteLength = 32;
[dataToAuth appendData:iv]; [dataToAuth appendData:iv];
[dataToAuth appendData:dataToDecrypt]; [dataToAuth appendData:dataToDecrypt];
NSData *ourHmacData; NSData *_Nullable ourHmacData;
if (hmacType == TSHMACSHA1Truncated10Bytes) { if (hmacType == TSHMACSHA1Truncated10Bytes) {
ourHmacData = [Cryptography truncatedSHA1HMAC:dataToAuth withHMACKey:hmacKey truncation:10]; ourHmacData = [Cryptography truncatedSHA1HMAC:dataToAuth withHMACKey:hmacKey truncation:10];
@ -245,7 +270,7 @@ const NSUInteger kAES256_KeyByteLength = 32;
if (digest) { if (digest) {
DDLogDebug(@"%@ verifying their digest", self.logTag); DDLogDebug(@"%@ verifying their digest", self.logTag);
[dataToAuth appendData:ourHmacData]; [dataToAuth appendData:ourHmacData];
NSData *ourDigest = [Cryptography computeSHA256Digest:dataToAuth]; NSData *_Nullable ourDigest = [Cryptography computeSHA256Digest:dataToAuth];
if (!ourDigest || ![ourDigest ows_constantTimeIsEqualToData:digest]) { if (!ourDigest || ![ourDigest ows_constantTimeIsEqualToData:digest]) {
DDLogWarn(@"%@ Bad digest on decrypting payload", self.logTag); DDLogWarn(@"%@ Bad digest on decrypting payload", self.logTag);
// Don't log digest in prod // Don't log digest in prod
@ -288,8 +313,10 @@ const NSUInteger kAES256_KeyByteLength = 32;
return nil; return nil;
} }
#pragma mark methods which use AES CBC #pragma mark - methods which use AES CBC
+ (NSData *)decryptAppleMessagePayload:(NSData *)payload withSignalingKey:(NSString *)signalingKeyString {
+ (nullable NSData *)decryptAppleMessagePayload:(NSData *)payload withSignalingKey:(NSString *)signalingKeyString
{
OWSAssert(payload); OWSAssert(payload);
OWSAssert(signalingKeyString); OWSAssert(signalingKeyString);
@ -317,11 +344,11 @@ const NSUInteger kAES256_KeyByteLength = 32;
digest:nil]; digest:nil];
} }
+ (NSData *)decryptAttachment:(NSData *)dataToDecrypt + (nullable NSData *)decryptAttachment:(NSData *)dataToDecrypt
withKey:(NSData *)key withKey:(NSData *)key
digest:(nullable NSData *)digest digest:(nullable NSData *)digest
unpaddedSize:(UInt32)unpaddedSize unpaddedSize:(UInt32)unpaddedSize
error:(NSError **)error error:(NSError **)error
{ {
if (digest.length <= 0) { if (digest.length <= 0) {
// This *could* happen with sufficiently outdated clients. // This *could* happen with sufficiently outdated clients.
@ -352,15 +379,20 @@ const NSUInteger kAES256_KeyByteLength = 32;
NSData *hmac = [dataToDecrypt NSData *hmac = [dataToDecrypt
subdataWithRange:NSMakeRange([dataToDecrypt length] - HMAC256_OUTPUT_LENGTH, HMAC256_OUTPUT_LENGTH)]; subdataWithRange:NSMakeRange([dataToDecrypt length] - HMAC256_OUTPUT_LENGTH, HMAC256_OUTPUT_LENGTH)];
NSData *paddedPlainText = [Cryptography decryptCBCMode:encryptedAttachment NSData *_Nullable paddedPlainText = [Cryptography decryptCBCMode:encryptedAttachment
key:encryptionKey key:encryptionKey
IV:iv IV:iv
version:nil version:nil
HMACKey:hmacKey HMACKey:hmacKey
HMACType:TSHMACSHA256AttachementType HMACType:TSHMACSHA256AttachementType
matchingHMAC:hmac matchingHMAC:hmac
digest:digest]; digest:digest];
if (unpaddedSize == 0) { if (!paddedPlainText) {
OWSFail(@"%@ couldn't decrypt attachment.", self.logTag);
*error = OWSErrorWithCodeDescription(
OWSErrorCodeFailedToDecryptMessage, NSLocalizedString(@"ERROR_MESSAGE_INVALID_MESSAGE", @""));
return nil;
} else if (unpaddedSize == 0) {
// Work around for legacy iOS client's which weren't setting padding size. // Work around for legacy iOS client's which weren't setting padding size.
// Since we know those clients pre-date attachment padding we return the entire data. // Since we know those clients pre-date attachment padding we return the entire data.
DDLogWarn(@"%@ Decrypted attachment with unspecified size.", self.logTag); DDLogWarn(@"%@ Decrypted attachment with unspecified size.", self.logTag);
@ -399,10 +431,16 @@ const NSUInteger kAES256_KeyByteLength = 32;
} }
} }
+ (NSData *)encryptAttachmentData:(NSData *)attachmentData + (nullable NSData *)encryptAttachmentData:(NSData *)attachmentData
outKey:(NSData *_Nonnull *_Nullable)outKey outKey:(NSData *_Nonnull *_Nullable)outKey
outDigest:(NSData *_Nonnull *_Nullable)outDigest outDigest:(NSData *_Nonnull *_Nullable)outDigest
{ {
// Due to paddedSize, we need to divide by two.
if (attachmentData.length >= SIZE_MAX / 2) {
DDLogError(@"%@ data is too long.", self.logTag);
return nil;
}
NSData *iv = [Cryptography generateRandomBytes:AES_CBC_IV_LENGTH]; NSData *iv = [Cryptography generateRandomBytes:AES_CBC_IV_LENGTH];
NSData *encryptionKey = [Cryptography generateRandomBytes:AES_KEY_SIZE]; NSData *encryptionKey = [Cryptography generateRandomBytes:AES_KEY_SIZE];
NSData *hmacKey = [Cryptography generateRandomBytes:HMAC256_KEY_LENGTH]; NSData *hmacKey = [Cryptography generateRandomBytes:HMAC256_KEY_LENGTH];
@ -453,13 +491,22 @@ const NSUInteger kAES256_KeyByteLength = 32;
[encryptedPaddedData appendData:cipherText]; [encryptedPaddedData appendData:cipherText];
// compute hmac of: iv || encrypted data // compute hmac of: iv || encrypted data
NSData *hmac = NSData *_Nullable hmac =
[Cryptography truncatedSHA256HMAC:encryptedPaddedData withHMACKey:hmacKey truncation:HMAC256_OUTPUT_LENGTH]; [Cryptography truncatedSHA256HMAC:encryptedPaddedData withHMACKey:hmacKey truncation:HMAC256_OUTPUT_LENGTH];
if (!hmac) {
OWSFail(@"%@ could not compute SHA 256 HMAC.", self.logTag);
return nil;
}
[encryptedPaddedData appendData:hmac]; [encryptedPaddedData appendData:hmac];
// compute digest of: iv || encrypted data || hmac // compute digest of: iv || encrypted data || hmac
*outDigest = [self computeSHA256Digest:encryptedPaddedData]; NSData *_Nullable digest = [self computeSHA256Digest:encryptedPaddedData];
if (!digest) {
OWSFail(@"%@ data is too long.", self.logTag);
return nil;
}
*outDigest = digest;
return [encryptedPaddedData copy]; return [encryptedPaddedData copy];
} }
@ -594,6 +641,11 @@ const NSUInteger kAES256_KeyByteLength = 32;
// feeding each chunk to EVP_DecryptUpdate, which can be called multiple times. // feeding each chunk to EVP_DecryptUpdate, which can be called multiple times.
// For simplicity, we currently decrypt the entire ciphertext in one shot. // For simplicity, we currently decrypt the entire ciphertext in one shot.
int decryptedBytes = 0; int decryptedBytes = 0;
if (ciphertext.length >= INT_MAX) {
OWSFail(@"%@ ciphertext too large", self.logTag);
return nil;
}
if (EVP_DecryptUpdate(ctx, plaintext.mutableBytes, &decryptedBytes, ciphertext.bytes, (int)ciphertext.length) if (EVP_DecryptUpdate(ctx, plaintext.mutableBytes, &decryptedBytes, ciphertext.bytes, (int)ciphertext.length)
!= kOpenSSLSuccess) { != kOpenSSLSuccess) {
OWSFail(@"%@ decryptUpdate failed", self.logTag); OWSFail(@"%@ decryptUpdate failed", self.logTag);
@ -606,6 +658,10 @@ const NSUInteger kAES256_KeyByteLength = 32;
} }
// Set expected tag value. Works in OpenSSL 1.0.1d and later // Set expected tag value. Works in OpenSSL 1.0.1d and later
if (authTagFromEncrypt.length >= INT_MAX) {
OWSFail(@"%@ authTagFromEncrypt too large", self.logTag);
return nil;
}
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, (int)authTagFromEncrypt.length, (void *)authTagFromEncrypt.bytes) if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, (int)authTagFromEncrypt.length, (void *)authTagFromEncrypt.bytes)
!= kOpenSSLSuccess) { != kOpenSSLSuccess) {
OWSFail(@"%@ Failed to set auth tag in decrypt.", self.logTag); OWSFail(@"%@ Failed to set auth tag in decrypt.", self.logTag);

Loading…
Cancel
Save