session-ios/SessionProtocolKit/Signal/CipherMessage/PreKeyWhisperMessage.m

150 lines
5.3 KiB
Objective-C

//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "PreKeyWhisperMessage.h"
#import "AxolotlExceptions.h"
#import "Constants.h"
#import "SerializationUtilities.h"
#import <SessionProtocolKit/SessionProtocolKit-Swift.h>
#import <SignalCoreKit/SCKExceptionWrapper.h>
#import <SignalCoreKit/OWSAsserts.h>
NS_ASSUME_NONNULL_BEGIN
@interface PreKeyWhisperMessage ()
@property (nonatomic, readwrite) NSData *identityKey;
@property (nonatomic, readwrite) NSData *baseKey;
@property (nonatomic, readwrite) NSData *serialized;
@end
#pragma mark -
@implementation PreKeyWhisperMessage
- (instancetype)init_throws_withWhisperMessage:(WhisperMessage *)whisperMessage
registrationId:(int)registrationId
prekeyId:(int)prekeyId
signedPrekeyId:(int)signedPrekeyId
baseKey:(NSData *)baseKey
identityKey:(NSData *)identityKey
{
OWSAssert(whisperMessage);
OWSAssert(baseKey);
OWSAssert(identityKey);
if (self = [super init]) {
_registrationId = registrationId;
_version = whisperMessage.version;
_prekeyID = prekeyId;
_signedPrekeyId = signedPrekeyId;
_baseKey = baseKey;
_identityKey = identityKey;
_message = whisperMessage;
SPKProtoTSProtoPreKeyWhisperMessageBuilder *messageBuilder = [SPKProtoTSProtoPreKeyWhisperMessage builderWithSignedPreKeyID:signedPrekeyId
baseKey:baseKey
identityKey:identityKey
message:whisperMessage.serialized];
[messageBuilder setRegistrationID:registrationId];
if (prekeyId != -1) {
[messageBuilder setPreKeyID:prekeyId];
}
Byte versionByte = [SerializationUtilities intsToByteHigh:_version low:CURRENT_VERSION];
NSMutableData *serialized = [NSMutableData dataWithBytes:&versionByte length:1];
NSError *error;
NSData *_Nullable messageData = [messageBuilder buildSerializedDataAndReturnError:&error];
if (!messageData || error) {
OWSFailDebug(@"Could not serialize proto: %@.", error);
OWSRaiseException(InvalidMessageException, @"Could not serialize proto.");
}
[serialized appendData:messageData];
_serialized = [serialized copy];
}
return self;
}
- (nullable instancetype)initWithData:(NSData *)serialized error:(NSError **)outError
{
@try {
self = [self init_throws_withData:serialized];
return self;
} @catch (NSException *exception) {
*outError = SCKExceptionWrapperErrorMake(exception);
return nil;
}
}
- (instancetype)init_throws_withData:(NSData *)serialized
{
if (self = [super init]) {
if (serialized.length < 1) {
OWSFailDebug(@"Empty data");
OWSRaiseException(InvalidMessageException, @"Empty data");
}
Byte version;
[serialized getBytes:&version length:1];
_version = [SerializationUtilities highBitsToIntFromByte:version];
if (_version > CURRENT_VERSION && _version < MINIMUM_SUPPORTED_VERSION) {
@throw [NSException exceptionWithName:InvalidVersionException
reason:@"Unknown version"
userInfo:@{ @"version" : [NSNumber numberWithInt:_version] }];
}
NSUInteger messageDataLength;
ows_sub_overflow(serialized.length, 1, &messageDataLength);
NSData *messageData = [serialized subdataWithRange:NSMakeRange(1, messageDataLength)];
NSError *error;
SPKProtoTSProtoPreKeyWhisperMessage *_Nullable preKeyWhisperMessage =
[SPKProtoTSProtoPreKeyWhisperMessage parseData:messageData error:&error];
if (!preKeyWhisperMessage || error) {
OWSFailDebug(@"Could not parse proto: %@.", error);
OWSRaiseException(InvalidMessageException, @"Could not parse proto.");
}
_serialized = serialized;
_registrationId = preKeyWhisperMessage.registrationID;
// This method is called when decrypting a received PreKeyMessage, but to be symmetrical with
// encrypting a PreKeyWhisperMessage before sending, we use "-1" to indicate *no* unsigned prekey was
// included.
_prekeyID = preKeyWhisperMessage.hasPreKeyID ? preKeyWhisperMessage.preKeyID : -1;
_signedPrekeyId = preKeyWhisperMessage.signedPreKeyID;
_baseKey = preKeyWhisperMessage.baseKey;
_identityKey = preKeyWhisperMessage.identityKey;
_message = [[WhisperMessage alloc] init_throws_withData:preKeyWhisperMessage.message];
}
return self;
}
- (CipherMessageType)cipherMessageType {
return CipherMessageType_Prekey;
}
#pragma mark - Logging
+ (NSString *)logTag
{
return [NSString stringWithFormat:@"[%@]", self.class];
}
- (NSString *)logTag
{
return self.class.logTag;
}
@end
NS_ASSUME_NONNULL_END