From 456d1c479addd83ac44a7c4322878e98aaf148b5 Mon Sep 17 00:00:00 2001 From: Frederic Jacobs Date: Thu, 26 Feb 2015 19:15:46 +0100 Subject: [PATCH] Fixes #530 --- Signal.xcodeproj/project.pbxproj | 4 ++ .../Messages/TSMessagesManager+sendMessages.m | 3 +- .../textsecure/Util/NSData+messagePadding.h | 2 + .../textsecure/Util/NSData+messagePadding.m | 31 ++++++++++++- Signal/test/textsecure/MessagePaddingTests.m | 44 +++++++++++++++++++ .../translations/en.lproj/Localizable.strings | 2 +- 6 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 Signal/test/textsecure/MessagePaddingTests.m diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 10aeac17c..41c312d73 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -305,6 +305,7 @@ B60FB9A71A46F099006A5A66 /* TSAllocAttachmentRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B60FB9A61A46F099006A5A66 /* TSAllocAttachmentRequest.m */; }; B60FB9AD1A46F831006A5A66 /* UIImage+contentTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = B60FB9AC1A46F831006A5A66 /* UIImage+contentTypes.m */; }; B60FB9B01A4711D4006A5A66 /* TSAttachmentEncryptionResult.m in Sources */ = {isa = PBXBuildFile; fileRef = B60FB9AF1A4711D4006A5A66 /* TSAttachmentEncryptionResult.m */; }; + B617E9241A9F962600753F00 /* MessagePaddingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B617E9231A9F962600753F00 /* MessagePaddingTests.m */; }; B62D53F71A23CCAD009AAF82 /* TSMessageAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = B62D53F61A23CCAD009AAF82 /* TSMessageAdapter.m */; }; B62EFBEC1A91352F0072ADD3 /* TSInvalidIdentityKeyErrorMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = B62EFBE71A91352F0072ADD3 /* TSInvalidIdentityKeyErrorMessage.m */; }; B62EFBED1A91352F0072ADD3 /* TSInvalidIdentityKeyReceivingErrorMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = B62EFBE91A91352F0072ADD3 /* TSInvalidIdentityKeyReceivingErrorMessage.m */; }; @@ -872,6 +873,7 @@ B60FB9AC1A46F831006A5A66 /* UIImage+contentTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+contentTypes.m"; sourceTree = ""; }; B60FB9AE1A4711D4006A5A66 /* TSAttachmentEncryptionResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAttachmentEncryptionResult.h; sourceTree = ""; }; B60FB9AF1A4711D4006A5A66 /* TSAttachmentEncryptionResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachmentEncryptionResult.m; sourceTree = ""; }; + B617E9231A9F962600753F00 /* MessagePaddingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MessagePaddingTests.m; sourceTree = ""; }; B62D53F51A23CCAD009AAF82 /* TSMessageAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSMessageAdapter.h; sourceTree = ""; }; B62D53F61A23CCAD009AAF82 /* TSMessageAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSMessageAdapter.m; sourceTree = ""; }; B62EFBE61A91352F0072ADD3 /* TSInvalidIdentityKeyErrorMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSInvalidIdentityKeyErrorMessage.h; sourceTree = ""; }; @@ -2232,6 +2234,7 @@ B6B095E21A1D25C5008BFAA6 /* TSStoragePreKeyStoreTests.m */, B6B095E31A1D25C5008BFAA6 /* TSStorageSignedPreKeyStore.m */, B640C4761A477B0F005C7C8A /* TSAttachementsTest.m */, + B617E9231A9F962600753F00 /* MessagePaddingTests.m */, ); path = textsecure; sourceTree = ""; @@ -3817,6 +3820,7 @@ 76EB062918170B33006006FC /* BadArgument.m in Sources */, A157076A17F0CD6D007C2BD6 /* ZrtpTest.m in Sources */, A157076B17F0CD6D007C2BD6 /* LowLatencyConnectorTest.m in Sources */, + B617E9241A9F962600753F00 /* MessagePaddingTests.m in Sources */, B65031CF1A7862AA002EBBBD /* SignedPreKeyDeletionTests.m in Sources */, 76EB061718170B33006006FC /* AnonymousOccurrenceLogger.m in Sources */, 76EB05F118170B33006006FC /* PhoneManager.m in Sources */, diff --git a/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.m b/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.m index 46bcc8dc6..79f0ed182 100644 --- a/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.m +++ b/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.m @@ -16,6 +16,7 @@ #import "Environment.h" #import "PreferencesUtil.h" #import "IncomingPushMessageSignal.pb.h" +#import "NSData+messagePadding.h" #import "TSStorageManager.h" #import "TSStorageManager+SessionStore.h" #import "TSStorageManager+IdentityKeyStore.h" @@ -237,7 +238,7 @@ dispatch_queue_t sendingQueue() { recipientId:identifier deviceId:[deviceNumber intValue]]; - id encryptedMessage = [cipher encryptMessage:plainText]; + id encryptedMessage = [cipher encryptMessage:[plainText paddedMessageBody]]; NSData *serializedMessage = encryptedMessage.serialized; TSWhisperMessageType messageType = [self messageTypeForCipherMessage:encryptedMessage]; diff --git a/Signal/src/textsecure/Util/NSData+messagePadding.h b/Signal/src/textsecure/Util/NSData+messagePadding.h index 18fb78154..6f4fb01a3 100644 --- a/Signal/src/textsecure/Util/NSData+messagePadding.h +++ b/Signal/src/textsecure/Util/NSData+messagePadding.h @@ -12,4 +12,6 @@ - (NSData*)removePadding; +- (NSData*)paddedMessageBody; + @end diff --git a/Signal/src/textsecure/Util/NSData+messagePadding.m b/Signal/src/textsecure/Util/NSData+messagePadding.m index 20646c774..b133d992a 100644 --- a/Signal/src/textsecure/Util/NSData+messagePadding.m +++ b/Signal/src/textsecure/Util/NSData+messagePadding.m @@ -16,12 +16,12 @@ Byte data[self.length]; [self getBytes:data length:self.length]; - for (long i = (long)self.length-1; i >= 0; i--) { if (data[i] == (Byte)0x80) { paddingStart = (unsigned long) i; break; } else if (data[i] != (Byte)0x00) { + DDLogWarn(@"Failed to remove padding, returning unstripped padding"); return self; } } @@ -29,4 +29,33 @@ return [self subdataWithRange:NSMakeRange(0, paddingStart)]; } + +- (NSData*)paddedMessageBody { + // From https://github.com/WhisperSystems/TextSecure/blob/master/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/push/PushTransportDetails.java#L55 + // NOTE: This is dumb. We have our own padding scheme, but so does the cipher. + // The +1 -1 here is to make sure the Cipher has room to add one padding byte, + // otherwise it'll add a full 16 extra bytes. + + NSUInteger paddedMessageLength = [self paddedMessageLength:(self.length + 1)]-1; + NSMutableData *paddedMessage = [NSMutableData dataWithLength:paddedMessageLength]; + + Byte paddingByte = 0x80; + + [paddedMessage replaceBytesInRange:NSMakeRange(0, self.length) withBytes:[self bytes]]; + [paddedMessage replaceBytesInRange:NSMakeRange(self.length, 1) withBytes:&paddingByte]; + + return paddedMessage; +} + +- (NSUInteger)paddedMessageLength:(NSUInteger)messageLength { + NSUInteger messageLengthWithTerminator = messageLength + 1; + NSUInteger messagePartCount = messageLengthWithTerminator / 160; + + if (messageLengthWithTerminator % 160 != 0) { + messagePartCount++; + } + + return messagePartCount * 160; +} + @end diff --git a/Signal/test/textsecure/MessagePaddingTests.m b/Signal/test/textsecure/MessagePaddingTests.m new file mode 100644 index 000000000..4b00dcfa2 --- /dev/null +++ b/Signal/test/textsecure/MessagePaddingTests.m @@ -0,0 +1,44 @@ +// +// MessagePaddingTests.m +// Signal +// +// Created by Frederic Jacobs on 26/02/15. +// Copyright (c) 2015 Open Whisper Systems. All rights reserved. +// + +#import "Cryptography.h" +#import "NSData+messagePadding.h" +#import + +@interface MessagePaddingTests : XCTestCase + +@end + +@implementation MessagePaddingTests + +- (void)testV3Padding { + for (NSUInteger i=0;i<159;i++) { + NSData *data = [NSMutableData dataWithLength:i]; + XCTAssert([data paddedMessageBody].length == 159); + } + + for (NSUInteger i=159;i<319;i++) { + NSData *data = [NSMutableData dataWithLength:i]; + XCTAssert([data paddedMessageBody].length == 319); + } + + for (NSUInteger i=319;i<479;i++) { + NSData *data = [NSMutableData dataWithLength:i]; + XCTAssert([data paddedMessageBody].length == 479); + } +} + +- (void)testV3RandomPadding{ + for (int i = 0; i < 1000; i++) { + NSData *randomMessage = [Cryptography generateRandomBytes:501]; + NSData *paddedMessage = [randomMessage paddedMessageBody]; + XCTAssert([[paddedMessage removePadding] isEqualToData:randomMessage]); + } +} + +@end diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 30f50de25..77f402775 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -13,7 +13,7 @@ "DATESTRING_TODAY" = "Today"; "DISABLING_BACKUP_FAILED" = "We encountered an issue while disabling the backup of your call log. Call logs might leak in your iTunes/iCloud backups."; "ERROR_WAS_DETECTED_TITLE" = "Bummer!"; -"ERROR_WAS_DETECTED_SUBMIT" = "An bug was detected. Help us make Signal better by reporting this incident."; +"ERROR_WAS_DETECTED_SUBMIT" = "A bug was detected. Help us make Signal better by reporting this incident."; "END_CALL_BAD_INTERACTION_WITH_SERVER" = "Server Failed!"; "END_CALL_BUTTON_TITLE" = "End"; "END_CALL_HANDSHAKE_FAILED" = "Handshake Failed!";