From 98aaa3fc670aed4c334ee06000600cd2e07c4584 Mon Sep 17 00:00:00 2001 From: Peter Date: Tue, 2 Aug 2016 17:01:22 +0300 Subject: [PATCH 1/3] no message --- MTProtoKit/MTHttpWorker.m | 6 ++++++ MTProtoKit/MTTcpConnection.m | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/MTProtoKit/MTHttpWorker.m b/MTProtoKit/MTHttpWorker.m index a05e353689..2e4e38c63d 100644 --- a/MTProtoKit/MTHttpWorker.m +++ b/MTProtoKit/MTHttpWorker.m @@ -69,6 +69,12 @@ MTInternalIdClass(MTHttpWorker) int32_t randomId = 0; arc4random_buf(&randomId, 4); +/*#ifdef DEBUG + if (![address isIpv6]) { + address = [[MTDatacenterAddress alloc] initWithIp:@"127.0.0.1" port:443 preferForMedia:address.preferForMedia restrictToTcp:address.restrictToTcp]; + } +#endif*/ + NSString *urlString = [[NSString alloc] initWithFormat:@"http://%@:%d/api%" PRIx32 "", address.ip, (int)address.port, randomId]; self = [super initWithBaseURL:[[NSURL alloc] initWithString:urlString]]; diff --git a/MTProtoKit/MTTcpConnection.m b/MTProtoKit/MTTcpConnection.m index 25707bf9b1..65a1e5fca8 100644 --- a/MTProtoKit/MTTcpConnection.m +++ b/MTProtoKit/MTTcpConnection.m @@ -111,7 +111,14 @@ static void init_ctr(struct ctr_state *state, const unsigned char *iv) { _internalId = [[MTInternalId(MTTcpConnection) alloc] init]; +/*#ifdef DEBUG + if (![address isIpv6]) { + address = [[MTDatacenterAddress alloc] initWithIp:@"127.0.0.1" port:443 preferForMedia:address.preferForMedia restrictToTcp:address.restrictToTcp]; + } +#endif*/ + _address = address; + _interface = interface; if (context.apiEnvironment.datacenterAddressOverrides[@(datacenterId)] != nil) { From 01f22552f6f459f409d6274cb821702838a3988f Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 2 Sep 2016 21:56:36 +0300 Subject: [PATCH 2/3] no message --- MTProtoKit/MTInputStream.m | 2 + MTProtoKit/MTMessageEncryptionKey.h | 2 + MTProtoKit/MTMessageEncryptionKey.m | 51 +++++++++++- MTProtoKit/MTProto.m | 122 ++++++++++++++++++++++------ 4 files changed, 149 insertions(+), 28 deletions(-) diff --git a/MTProtoKit/MTInputStream.m b/MTProtoKit/MTInputStream.m index 055da2c0b3..35eb3e0d30 100644 --- a/MTProtoKit/MTInputStream.m +++ b/MTProtoKit/MTInputStream.m @@ -68,6 +68,8 @@ static inline int roundUpInput(int numToRound, int multiple) { if (MTLogEnabled()) { MTLog(@"***** Couldn't read int32"); + + @throw [[NSException alloc] initWithName:@"MTInputStreamException" reason:@"readInt32 end of stream" userInfo:@{}]; } } diff --git a/MTProtoKit/MTMessageEncryptionKey.h b/MTProtoKit/MTMessageEncryptionKey.h index 2f82ace6e8..364cef36a6 100644 --- a/MTProtoKit/MTMessageEncryptionKey.h +++ b/MTProtoKit/MTMessageEncryptionKey.h @@ -14,6 +14,8 @@ @property (nonatomic, strong, readonly) NSData *iv; + (instancetype)messageEncryptionKeyForAuthKey:(NSData *)authKey messageKey:(NSData *)messageKey toClient:(bool)toClient; ++ (instancetype)messageEncryptionKeyV2ForAuthKey:(NSData *)authKey messageKey:(NSData *)messageKey toClient:(bool)toClient; + - (instancetype)initWithKey:(NSData *)key iv:(NSData *)iv; @end diff --git a/MTProtoKit/MTMessageEncryptionKey.m b/MTProtoKit/MTMessageEncryptionKey.m index 55c2e0f771..f5e31d4999 100644 --- a/MTProtoKit/MTMessageEncryptionKey.m +++ b/MTProtoKit/MTMessageEncryptionKey.m @@ -19,8 +19,6 @@ NSAssert(messageKey != nil, @"message key should not be nil"); #endif -#warning TODO more precise length check - if (authKey == nil || authKey.length == 0 || messageKey == nil || messageKey.length == 0) return nil; @@ -77,6 +75,55 @@ return result; } ++ (instancetype)messageEncryptionKeyV2ForAuthKey:(NSData *)authKey messageKey:(NSData *)messageKey toClient:(bool)toClient { +#ifdef DEBUG + NSAssert(authKey != nil, @"authKey should not be nil"); + NSAssert(messageKey != nil, @"message key should not be nil"); +#endif + + if (authKey == nil || authKey.length == 0 || messageKey == nil || messageKey.length == 0) + return nil; + + /* + sha256_a = SHA256 (msg_key + substr (auth_key, x, 36)); + + sha256_b = SHA256 (substr (auth_key, 40+x, 36) + msg_key); + + aes_key = substr (sha256_a, 0, 8) + substr (sha256_b, 8, 16) + substr (sha256_a, 24, 8); + aes_iv = substr (sha256_b, 0, 8) + substr (sha256_a, 8, 16) + substr (sha256_b, 24, 8); + */ + + int xValue = toClient ? 8 : 0; + + NSMutableData *sha256_a_data = [[NSMutableData alloc] init]; + [sha256_a_data appendData:messageKey]; + [sha256_a_data appendBytes:authKey.bytes + xValue length:36]; + + NSData *sha256_a = MTSha256(sha256_a_data); + + NSMutableData *sha256_b_data = [[NSMutableData alloc] init]; + [sha256_b_data appendBytes:authKey.bytes + 40 + xValue length:36]; + [sha256_b_data appendData:messageKey]; + + NSData *sha256_b = MTSha256(sha256_b_data); + + NSMutableData *aesKey = [[NSMutableData alloc] init]; + [aesKey appendBytes:sha256_a.bytes + 0 length:8]; + [aesKey appendBytes:sha256_b.bytes + 8 length:16]; + [aesKey appendBytes:sha256_a.bytes + 24 length:8]; + + NSMutableData *aesIv = [[NSMutableData alloc] init]; + [aesIv appendBytes:sha256_b.bytes + 0 length:8]; + [aesIv appendBytes:sha256_a.bytes + 8 length:16]; + [aesIv appendBytes:sha256_b.bytes + 24 length:8]; + + MTMessageEncryptionKey *result = [[MTMessageEncryptionKey alloc] init]; + result->_key = [[NSData alloc] initWithData:aesKey]; + result->_iv = [[NSData alloc] initWithData:aesIv]; + + return result; +} + - (instancetype)initWithKey:(NSData *)key iv:(NSData *)iv { self = [super init]; diff --git a/MTProtoKit/MTProto.m b/MTProtoKit/MTProto.m index 2a84cd03a0..a85ec8f1ee 100644 --- a/MTProtoKit/MTProto.m +++ b/MTProtoKit/MTProto.m @@ -51,6 +51,8 @@ #import #import +#define MTProtoV2 1 + typedef enum { MTProtoStateAwaitingDatacenterScheme = 1, MTProtoStateAwaitingDatacenterAuthorization = 2, @@ -1144,21 +1146,25 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; [decryptedOs writeInt32:(int32_t)messageData.length]; [decryptedOs writeData:messageData]; - uint8_t randomBytes[15]; - arc4random_buf(randomBytes, 15); - for (int i = 0; ((int)messageData.length + i) % 16 != 0; i++) - { - [decryptedOs write:&randomBytes[i] maxLength:1]; - } + NSData *decryptedData = [self paddedData:[decryptedOs currentBytes]]; - NSData *decryptedData = [decryptedOs currentBytes]; +#if MTProtoV2 + int xValue = 0; + NSMutableData *msgKeyLargeData = [[NSMutableData alloc] init]; + [msgKeyLargeData appendBytes:_authInfo.authKey.bytes + 88 + xValue length:32]; + [msgKeyLargeData appendData:decryptedData]; + NSData *msgKeyLarge = MTSha256(msgKeyLargeData); + NSData *messageKey = [msgKeyLarge subdataWithRange:NSMakeRange(8, 16)]; + MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyV2ForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false]; +#else NSData *messageKeyFull = MTSubdataSha1(decryptedData, 0, 32 + messageData.length); NSData *messageKey = [[NSData alloc] initWithBytes:(((int8_t *)messageKeyFull.bytes) + messageKeyFull.length - 16) length:16]; + MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false]; +#endif NSData *transactionData = nil; - MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false]; if (encryptionKey != nil) { NSMutableData *encryptedData = [[NSMutableData alloc] initWithCapacity:14 + decryptedData.length]; @@ -1259,27 +1265,32 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; [decryptedOs writeInt32:(int32_t)containerData.length]; [decryptedOs writeData:containerData]; - uint8_t randomBytes[15]; - arc4random_buf(randomBytes, 15); - for (int i = 0; ((int)containerData.length + i) % 16 != 0; i++) - { - [decryptedOs write:&randomBytes[i] maxLength:1]; - } + NSData *decryptedData = [self paddedData:[decryptedOs currentBytes]]; - NSData *decryptedData = [decryptedOs currentBytes]; +#if MTProtoV2 + int xValue = 0; + NSMutableData *msgKeyLargeData = [[NSMutableData alloc] init]; + [msgKeyLargeData appendBytes:_authInfo.authKey.bytes + 88 + xValue length:32]; + [msgKeyLargeData appendData:decryptedData]; + NSData *msgKeyLarge = MTSha256(msgKeyLargeData); + NSData *messageKey = [msgKeyLarge subdataWithRange:NSMakeRange(8, 16)]; + MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyV2ForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false]; + int32_t nQuickAckId = *((int32_t *)(msgKeyLarge.bytes)); +#else NSData *messageKeyFull = MTSubdataSha1(decryptedData, 0, 32 + containerData.length); NSData *messageKey = [[NSData alloc] initWithBytes:(((int8_t *)messageKeyFull.bytes) + messageKeyFull.length - 16) length:16]; - + MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false]; int32_t nQuickAckId = *((int32_t *)(messageKeyFull.bytes)); +#endif + nQuickAckId = nQuickAckId & 0x7fffffff; if (quickAckId != NULL) *quickAckId = nQuickAckId; - MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false]; if (encryptionKey != nil) { - NSMutableData *encryptedData = [[NSMutableData alloc] initWithCapacity:14 + decryptedData.length]; + NSMutableData *encryptedData = [[NSMutableData alloc] init]; [encryptedData appendData:decryptedData]; MTAesEncryptInplace(encryptedData, encryptionKey.key, encryptionKey.iv); @@ -1307,6 +1318,39 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; return messageData; } +- (NSData *)paddedData:(NSData *)data { + NSMutableData *padded = [[NSMutableData alloc] initWithData:data]; + uint8_t randomBytes[128]; + arc4random_buf(randomBytes, 128); +#if MTProtoV2 + int take = 0; + while (take < 12) { + [padded appendBytes:randomBytes + take length:1]; + take++; + } + + while (padded.length % 16 != 0) { + [padded appendBytes:randomBytes + take length:1]; + take++; + } + + int remainingCount = arc4random_uniform(72 + 1 - take); + while (remainingCount % 16 != 0) { + remainingCount--; + } + + for (int i = 0; i < remainingCount; i++) { + [padded appendBytes:randomBytes + take length:1]; + take++; + } +#else + for (int i = 0; ((int)data.length + i) % 16 != 0; i++) { + [padded appendBytes:randomBytes + i length:1]; + } +#endif + return padded; +} + - (NSData *)_dataForEncryptedMessage:(MTPreparedMessage *)preparedMessage sessionInfo:(MTSessionInfo *)sessionInfo quickAckId:(int32_t *)quickAckId { MTOutputStream *decryptedOs = [[MTOutputStream alloc] init]; @@ -1319,15 +1363,18 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; [decryptedOs writeInt32:(int32_t)preparedMessage.data.length]; [decryptedOs writeData:preparedMessage.data]; - uint8_t randomBytes[15]; - arc4random_buf(randomBytes, 15); - for (int i = 0; ((int)preparedMessage.data.length + i) % 16 != 0; i++) - { - [decryptedOs write:&randomBytes[i] maxLength:1]; - } + NSData *decryptedData = [self paddedData:[decryptedOs currentBytes]]; - NSData *decryptedData = [decryptedOs currentBytes]; +#if MTProtoV2 + int xValue = 0; + NSMutableData *msgKeyLargeData = [[NSMutableData alloc] init]; + [msgKeyLargeData appendBytes:_authInfo.authKey.bytes + 88 + xValue length:32]; + [msgKeyLargeData appendData:decryptedData]; + NSData *msgKeyLarge = MTSha256(msgKeyLargeData); + NSData *messageKey = [msgKeyLarge subdataWithRange:NSMakeRange(8, 16)]; + MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyV2ForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false]; +#else NSData *messageKeyFull = MTSubdataSha1(decryptedData, 0, 32 + preparedMessage.data.length); NSData *messageKey = [[NSData alloc] initWithBytes:(((int8_t *)messageKeyFull.bytes) + messageKeyFull.length - 16) length:16]; @@ -1337,6 +1384,8 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; *quickAckId = nQuickAckId; MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:messageKey toClient:false]; +#endif + if (encryptionKey != nil) { NSMutableData *encryptedData = [[NSMutableData alloc] initWithCapacity:14 + decryptedData.length]; @@ -1437,7 +1486,11 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; if (keyId != 0 && _authInfo != nil) { NSData *messageKey = [is readData:16]; +#if MTProtoV2 + MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyV2ForAuthKey:_authInfo.authKey messageKey:messageKey toClient:true]; +#else MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:messageKey toClient:true]; +#endif NSMutableData *messageData = [is readMutableData:(data.length - 24)]; while (messageData.length % 16 != 0) @@ -1682,7 +1735,13 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; return nil; NSData *embeddedMessageKey = [data subdataWithRange:NSMakeRange(8, 16)]; + +#if MTProtoV2 + MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyV2ForAuthKey:_authInfo.authKey messageKey:embeddedMessageKey toClient:true]; +#else MTMessageEncryptionKey *encryptionKey = [MTMessageEncryptionKey messageEncryptionKeyForAuthKey:_authInfo.authKey messageKey:embeddedMessageKey toClient:true]; +#endif + if (encryptionKey == nil) return nil; @@ -1691,11 +1750,22 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; int32_t messageDataLength = 0; [decryptedData getBytes:&messageDataLength range:NSMakeRange(28, 4)]; - if (messageDataLength < 0 || messageDataLength < (int32_t)decryptedData.length - 32 - 16 || messageDataLength > (int32_t)decryptedData.length - 32) + if (messageDataLength < 0 || messageDataLength > (int32_t)decryptedData.length) return nil; +#if MTProtoV2 + int xValue = 8; + NSMutableData *msgKeyLargeData = [[NSMutableData alloc] init]; + [msgKeyLargeData appendBytes:_authInfo.authKey.bytes + 88 + xValue length:32]; + [msgKeyLargeData appendData:decryptedData]; + + NSData *msgKeyLarge = MTSha256(msgKeyLargeData); + NSData *messageKey = [msgKeyLarge subdataWithRange:NSMakeRange(8, 16)]; +#else NSData *messageKeyFull = MTSubdataSha1(decryptedData, 0, 32 + messageDataLength); NSData *messageKey = [[NSData alloc] initWithBytes:(((int8_t *)messageKeyFull.bytes) + messageKeyFull.length - 16) length:16]; +#endif + if (![messageKey isEqualToData:embeddedMessageKey]) return nil; From 24d097edbc174162662cc18ecffaa44b4d9bc46f Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 2 Sep 2016 22:21:19 +0300 Subject: [PATCH 3/3] no message --- MTProtoKit/MTSerialization.h | 9 +++++++-- MtProtoKit.xcodeproj/project.pbxproj | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/MTProtoKit/MTSerialization.h b/MTProtoKit/MTSerialization.h index 1edba393d2..b5dd9c522a 100644 --- a/MTProtoKit/MTSerialization.h +++ b/MTProtoKit/MTSerialization.h @@ -8,8 +8,13 @@ #import -#import -#import +#ifdef MtProtoKitDynamicFramework +# import +# import +#else +# import +# import +#endif typedef MTExportedAuthorizationData *(^MTExportAuthorizationResponseParser)(NSData *); typedef MTDatacenterAddressListData *(^MTRequestDatacenterAddressListParser)(NSData *); diff --git a/MtProtoKit.xcodeproj/project.pbxproj b/MtProtoKit.xcodeproj/project.pbxproj index 7ea2737f3f..0db1e858d6 100644 --- a/MtProtoKit.xcodeproj/project.pbxproj +++ b/MtProtoKit.xcodeproj/project.pbxproj @@ -510,6 +510,7 @@ D0D225101B4D817B0085E26D /* MtProtoKitDynamic.h in Headers */ = {isa = PBXBuildFile; fileRef = D0D2250F1B4D817B0085E26D /* MtProtoKitDynamic.h */; settings = {ATTRIBUTES = (Public, ); }; }; D0D225161B4D817B0085E26D /* MtProtoKitDynamic.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D2250B1B4D817B0085E26D /* MtProtoKitDynamic.framework */; }; D0D2251D1B4D817B0085E26D /* MtProtoKitDynamicTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D0D2251C1B4D817B0085E26D /* MtProtoKitDynamicTests.m */; }; + D0D2689E1D7A055400C422DA /* libcrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D0CD990F1D75C16100F41187 /* libcrypto.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -770,6 +771,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D0D2689E1D7A055400C422DA /* libcrypto.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2386,8 +2388,8 @@ isa = XCBuildConfiguration; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ENABLE_MODULES = YES; ARCHS = "$(ARCHS_STANDARD)"; + CLANG_ENABLE_MODULES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; COPY_PHASE_STRIP = YES; @@ -2421,6 +2423,7 @@ ); MACH_O_TYPE = staticlib; MTL_ENABLE_DEBUG_INFO = NO; + ONLY_ACTIVE_ARCH = NO; OTHER_LDFLAGS = "-lz"; PRODUCT_BUNDLE_IDENTIFIER = "org.telegram.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_MODULE_NAME = MtProtoKit; @@ -2550,8 +2553,8 @@ isa = XCBuildConfiguration; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ENABLE_MODULES = YES; ARCHS = "$(ARCHS_STANDARD)"; + CLANG_ENABLE_MODULES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; COPY_PHASE_STRIP = NO; @@ -2589,6 +2592,7 @@ ); MACH_O_TYPE = staticlib; MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = NO; OTHER_LDFLAGS = "-lz"; PRODUCT_BUNDLE_IDENTIFIER = "org.telegram.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_MODULE_NAME = MtProtoKit; @@ -2641,6 +2645,7 @@ ); MACH_O_TYPE = staticlib; MTL_ENABLE_DEBUG_INFO = NO; + ONLY_ACTIVE_ARCH = NO; OTHER_LDFLAGS = "-lz"; PRODUCT_BUNDLE_IDENTIFIER = "org.telegram.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_MODULE_NAME = MtProtoKit;