Compare commits

..

4 Commits

Author SHA1 Message Date
Matthew Chen
0bf784692d Add protocol context to protocol kit. 2018-01-25 16:40:13 -05:00
Matthew Chen
1db4aabd92 Add protocol context to protocol kit. 2018-01-23 13:58:38 -05:00
Matthew Chen
75df21ecdf Add protocol context to protocol kit. 2018-01-23 11:47:15 -05:00
Matthew Chen
7619f1eede Add protocol context to protocol kit. 2018-01-23 11:47:15 -05:00
74 changed files with 3638 additions and 3293 deletions

View File

@ -8,20 +8,14 @@ Pod::Spec.new do |s|
s.author = { "Frederic Jacobs" => "github@fredericjacobs.com" }
s.social_media_url = "http://twitter.com/FredericJacobs"
s.source = { :git => "https://github.com/WhisperSystems/AxolotlKit.git", :tag => "#{s.version}" }
s.source_files = "AxolotlKit/Classes/**/*.{h,m,swift}", "AxolotlKit/Private/*.{h,m,swift}"
s.public_header_files = "AxolotlKit/Classes/**/*.{h}"
s.source_files = "AxolotlKit/Classes/*.{h,m}", "AxolotlKit/Classes/**/*.{h,m}"
s.public_header_files = "AxolotlKit/Classes/*.{h}", "AxolotlKit/Classes/**/*.{h}"
s.prefix_header_file = "AxolotlKit/SPKPrefix.h"
s.ios.deployment_target = "10.0"
s.ios.deployment_target = "6.0"
s.osx.deployment_target = "10.8"
s.requires_arc = true
s.dependency 'Curve25519Kit', '~> 2.1.0'
s.dependency 'HKDFKit', '~> 0.0.3'
s.dependency 'ProtocolBuffers', '~> 1.9.8'
s.dependency 'CocoaLumberjack'
s.dependency 'SwiftProtobuf'
s.dependency 'SignalCoreKit'
s.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'AxolotlKitTests/**/*.{h,m,swift}'
end
end

View File

@ -310,7 +310,6 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
);
mainGroup = B6B98F6F197D838A00B16B5E;
@ -527,7 +526,7 @@
"$(inherited)",
);
INFOPLIST_FILE = "AxolotlKit/AxolotlKit-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
PRODUCT_BUNDLE_IDENTIFIER = org.whispersystems.SignalProtocolKitTestApp;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
@ -544,7 +543,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "";
INFOPLIST_FILE = "AxolotlKit/AxolotlKit-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
PRODUCT_BUNDLE_IDENTIFIER = org.whispersystems.SignalProtocolKitTestApp;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
@ -640,7 +639,7 @@
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
);
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@ -686,7 +685,7 @@
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
);
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";

View File

@ -8,15 +8,8 @@
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSUInteger, CipherMessageType) {
CipherMessageType_Prekey = 0,
CipherMessageType_Whisper,
};
@protocol CipherMessage <NSObject>
- (NSData *)serialized;
@property (nonatomic, readonly) CipherMessageType cipherMessageType;
- (NSData*)serialized;
@end

View File

@ -1,32 +1,26 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// PrekeyWhisperMessage.h
// AxolotlKit
//
// Created by Frederic Jacobs on 23/07/14.
// Copyright (c) 2014 Frederic Jacobs. All rights reserved.
//
#import "WhisperMessage.h"
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#import "WhisperMessage.h"
@interface PreKeyWhisperMessage : NSObject <CipherMessage>
- (instancetype)init_throws_withData:(NSData *)serialized NS_SWIFT_UNAVAILABLE("throws objc exceptions");
- (nullable instancetype)initWithData:(NSData *)serialized error:(NSError **)outError;
- (instancetype)initWithData:(NSData *)serialized;
- (instancetype)init_throws_withWhisperMessage:(WhisperMessage *)whisperMessage
registrationId:(int)registrationId
prekeyId:(int)prekeyId
signedPrekeyId:(int)signedPrekeyId
baseKey:(NSData *)baseKey
identityKey:(NSData *)identityKey NS_SWIFT_UNAVAILABLE("throws objc exceptions");
- (instancetype)initWithWhisperMessage:(WhisperMessage*)whisperMessage registrationId:(int)registrationId prekeyId:(int)prekeyId signedPrekeyId:(int)signedPrekeyId baseKey:(NSData*)baseKey identityKey:(NSData*)identityKey;
@property (nonatomic, readonly) int registrationId;
@property (nonatomic, readonly) int version;
@property (nonatomic, readonly) int prekeyID;
@property (nonatomic, readonly) int signedPrekeyId;
@property (nonatomic, readonly) NSData *baseKey;
@property (nonatomic, readonly) NSData *identityKey;
@property (nonatomic, readonly) int registrationId;
@property (nonatomic, readonly) int version;
@property (nonatomic, readonly) int prekeyID;
@property (nonatomic, readonly) int signedPrekeyId;
@property (nonatomic, readonly) NSData *baseKey;
@property (nonatomic, readonly) NSData *identityKey;
@property (nonatomic, readonly) WhisperMessage *message;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,148 +1,93 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// PrekeyWhisperMessage.m
// AxolotlKit
//
// Created by Frederic Jacobs on 23/07/14.
// Copyright (c) 2014 Frederic Jacobs. All rights reserved.
//
#import "PreKeyWhisperMessage.h"
#import "AxolotlExceptions.h"
#import "PreKeyWhisperMessage.h"
#import "Constants.h"
#import "WhisperTextProtocol.pb.h"
#import "SerializationUtilities.h"
#import <AxolotlKit/AxolotlKit-Swift.h>
#import <SignalCoreKit/SCKExceptionWrapper.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];
-(instancetype)initWithWhisperMessage:(WhisperMessage*)whisperMessage registrationId:(int)registrationId prekeyId:(int)prekeyId signedPrekeyId:(int)signedPrekeyId baseKey:(NSData*)baseKey identityKey:(NSData*)identityKey{
self = [super init];
if (self) {
_registrationId = registrationId;
_version = whisperMessage.version;
_prekeyID = prekeyId;
_signedPrekeyId = signedPrekeyId;
_baseKey = baseKey;
_identityKey = identityKey;
_message = whisperMessage;
}
TSProtoPreKeyWhisperMessageBuilder *builder = [TSProtoPreKeyWhisperMessage builder];
[builder setSignedPreKeyId:signedPrekeyId];
[builder setBaseKey:baseKey];
[builder setIdentityKey:identityKey];
[builder setMessage:whisperMessage.serialized];
[builder setRegistrationId:registrationId];
if (prekeyId != -1) {
[builder setPreKeyId:prekeyId];
}
Byte versionByte = [SerializationUtilities intsToByteHigh:_version low:CURRENT_VERSION];
NSMutableData *serialized = [NSMutableData dataWithBytes:&versionByte length:1];
NSData *messageBytes = builder.build.data;
[serialized appendData:messageBytes];
_serialized = [NSData dataWithData:serialized];
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");
}
- (instancetype)initWithData:(NSData*)serialized{
self = [super init];
if (self) {
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] }];
@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.");
NSData *message = [serialized subdataWithRange:NSMakeRange(1, serialized.length-1)];
TSProtoPreKeyWhisperMessage *preKeyWhisperMessage = [TSProtoPreKeyWhisperMessage parseFromData:message];
if (!preKeyWhisperMessage.hasSignedPreKeyId || !preKeyWhisperMessage.hasBaseKey || !preKeyWhisperMessage.hasIdentityKey || !preKeyWhisperMessage.hasMessage) {
@throw [NSException exceptionWithName:InvalidMessageException reason:@"Incomplete Message" userInfo:@{}];
}
_serialized = serialized;
_registrationId = preKeyWhisperMessage.registrationID;
_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
// encrypting a PreKeyWhisperMessage before sending, we use "-1" to indicate *no* unsignd 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];
_prekeyID = preKeyWhisperMessage.hasPreKeyId ? preKeyWhisperMessage.preKeyId : -1;
_signedPrekeyId = preKeyWhisperMessage.signedPreKeyId;
_baseKey = preKeyWhisperMessage.baseKey;
_identityKey = preKeyWhisperMessage.identityKey;
_message = [[WhisperMessage alloc] initWithData: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

View File

@ -1,40 +1,29 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// WhisperMessage.h
// AxolotlKit
//
// Created by Frederic Jacobs on 23/07/14.
// Copyright (c) 2014 Frederic Jacobs. All rights reserved.
//
#import "CipherMessage.h"
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#import "CipherMessage.h"
@class ECKeyPair;
@interface WhisperMessage : NSObject <CipherMessage>
@property (nonatomic, readonly) int version;
@property (nonatomic, readonly) NSData *senderRatchetKey;
@property (nonatomic, readonly) int previousCounter;
@property (nonatomic, readonly) int counter;
@property (nonatomic, readonly) NSData *cipherText;
@property (nonatomic, readonly) NSData *serialized;
@property (nonatomic, readonly) int version;
@property (nonatomic, readonly) NSData *senderRatchetKey;
@property (nonatomic, readonly) int previousCounter;
@property (nonatomic, readonly) int counter;
@property (nonatomic, readonly) NSData *cipherText;
@property (nonatomic, readonly) NSData *serialized;
- (instancetype)init_throws_withData:(NSData *)serialized NS_SWIFT_UNAVAILABLE("throws objc exceptions");
- (nullable instancetype)initWithData:(NSData *)serialized error:(NSError **)outError;
- (instancetype)initWithData:(NSData*)serialized;
- (instancetype)init_throws_withVersion:(int)version
macKey:(NSData *)macKey
senderRatchetKey:(NSData *)senderRatchetKey
counter:(int)counter
previousCounter:(int)previousCounter
cipherText:(NSData *)cipherText
senderIdentityKey:(NSData *)senderIdentityKey
receiverIdentityKey:(NSData *)receiverIdentityKey NS_SWIFT_UNAVAILABLE("throws objc exceptions");
- (instancetype)initWithVersion:(int)version macKey:(NSData*)macKey senderRatchetKey:(NSData*)senderRatchetKey counter:(int)counter previousCounter:(int)previousCounter cipherText:(NSData*)cipherText senderIdentityKey:(NSData*)senderIdentityKey receiverIdentityKey:(NSData*)receiverIdentityKey;
- (void)throws_verifyMacWithVersion:(int)messageVersion
senderIdentityKey:(NSData *)senderIdentityKey
receiverIdentityKey:(NSData *)receiverIdentityKey
macKey:(NSData *)macKey NS_SWIFT_UNAVAILABLE("throws objc exceptions");
- (void)verifyMacWithVersion:(int)messageVersion senderIdentityKey:(NSData *)senderIdentityKey receiverIdentityKey:(NSData*)receiverIdentityKey macKey:(NSData *)macKey;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,200 +1,114 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "WhisperMessage.h"
#import "AxolotlExceptions.h"
#import "Constants.h"
#import "WhisperMessage.h"
#import "WhisperTextProtocol.pb.h"
#import "NSData+keyVersionByte.h"
#import "SerializationUtilities.h"
#import <AxolotlKit/AxolotlKit-Swift.h>
#import <SignalCoreKit/NSData+OWS.h>
#import <SignalCoreKit/SCKExceptionWrapper.h>
#import <SignalCoreKit/SignalCoreKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
#define VERSION_LENGTH 1
@implementation WhisperMessage
- (instancetype)init_throws_withVersion:(int)version
macKey:(NSData *)macKey
senderRatchetKey:(NSData *)senderRatchetKey
counter:(int)counter
previousCounter:(int)previousCounter
cipherText:(NSData *)cipherText
senderIdentityKey:(NSData *)senderIdentityKey
receiverIdentityKey:(NSData *)receiverIdentityKey
{
OWSAssert(macKey);
OWSAssert(senderRatchetKey);
OWSAssert(cipherText);
OWSAssert(cipherText);
OWSAssert(senderIdentityKey);
OWSAssert(receiverIdentityKey);
- (instancetype)initWithVersion:(int)version macKey:(NSData*)macKey senderRatchetKey:(NSData*)senderRatchetKey counter:(int)counter previousCounter:(int)previousCounter cipherText:(NSData*)cipherText senderIdentityKey:(NSData*)senderIdentityKey receiverIdentityKey:(NSData*)receiverIdentityKey{
self = [super init];
Byte versionByte = [SerializationUtilities intsToByteHigh:version low:CURRENT_VERSION];
NSMutableData *serialized = [NSMutableData dataWithBytes:&versionByte length:1];
if (self = [super init]) {
Byte versionByte = [SerializationUtilities intsToByteHigh:version low:CURRENT_VERSION];
NSMutableData *serialized = [NSMutableData dataWithBytes:&versionByte length:1];
SPKProtoTSProtoWhisperMessageBuilder *messageBuilder = [SPKProtoTSProtoWhisperMessage builderWithRatchetKey:senderRatchetKey
counter:counter
ciphertext:cipherText];
[messageBuilder setPreviousCounter:previousCounter];
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];
NSData *mac = [SerializationUtilities throws_macWithVersion:version
identityKey:[senderIdentityKey prependKeyType]
receiverIdentityKey:[receiverIdentityKey prependKeyType]
macKey:macKey
serialized:serialized];
[serialized appendData:mac];
_version = version;
NSData *message = [[[[[[[TSProtoWhisperMessage builder]
setRatchetKey:senderRatchetKey]
setCounter:counter]
setPreviousCounter:previousCounter]
setCiphertext:cipherText]
build] data];
[serialized appendData:message];
NSData *mac = [SerializationUtilities macWithVersion:version
identityKey:[senderIdentityKey prependKeyType]
receiverIdentityKey:[receiverIdentityKey prependKeyType]
macKey:macKey
serialized:serialized];
[serialized appendData:mac];
if (self) {
_version = version;
_senderRatchetKey = senderRatchetKey;
_previousCounter = previousCounter;
_counter = counter;
_cipherText = cipherText;
_serialized = [serialized copy];
_previousCounter = previousCounter;
_counter = counter;
_cipherText = cipherText;
_serialized = serialized;
}
return self;
}
- (instancetype)initWithData:(NSData*)serialized{
if (serialized.length <= (VERSION_LENGTH + MAC_LENGTH)) {
@throw [NSException exceptionWithName:InvalidMessageException reason:@"Message size is too short to have content" userInfo:@{}];
}
Byte version;
[serialized getBytes:&version length:VERSION_LENGTH];
NSData *messageAndMac = [serialized subdataWithRange:NSMakeRange(VERSION_LENGTH, serialized.length - VERSION_LENGTH)];
NSData *message = [messageAndMac subdataWithRange:NSMakeRange(0, messageAndMac.length - MAC_LENGTH)];
if ([SerializationUtilities highBitsToIntFromByte:version] < MINIMUM_SUPPORTED_VERSION) {
@throw [NSException exceptionWithName:LegacyMessageException reason:@"Message was sent with an unsupported version of the TextSecure protocol." userInfo:@{}];
}
if ([SerializationUtilities highBitsToIntFromByte:version] > CURRENT_VERSION) {
@throw [NSException exceptionWithName:InvalidMessageException reason:@"Unknown Version" userInfo:@{@"Version": [NSNumber numberWithChar:[SerializationUtilities highBitsToIntFromByte:version]]}];
}
TSProtoWhisperMessage *whisperMessage = [TSProtoWhisperMessage parseFromData:message];
if (!whisperMessage.hasCiphertext || !whisperMessage.hasCounter || !whisperMessage.hasRatchetKey) {
@throw [NSException exceptionWithName:InvalidMessageException reason:@"Incomplete Message" userInfo:@{}];
}
_serialized = serialized;
_senderRatchetKey = [whisperMessage.ratchetKey removeKeyType];
_version = [SerializationUtilities highBitsToIntFromByte:version];
_counter = whisperMessage.counter;
_previousCounter = whisperMessage.previousCounter;
_cipherText = whisperMessage.ciphertext;
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;
- (void)verifyMacWithVersion:(int)messageVersion senderIdentityKey:(NSData *)senderIdentityKey receiverIdentityKey:(NSData*)receiverIdentityKey macKey:(NSData *)macKey{
NSData *data = [self.serialized subdataWithRange:NSMakeRange(0, self.serialized.length - MAC_LENGTH)];
NSData *theirMac = [self.serialized subdataWithRange:NSMakeRange(self.serialized.length - MAC_LENGTH, MAC_LENGTH)];
NSData *ourMac = [SerializationUtilities macWithVersion:messageVersion
identityKey:[senderIdentityKey prependKeyType]
receiverIdentityKey:[receiverIdentityKey prependKeyType]
macKey:macKey
serialized:data];
if (![theirMac isEqualToData:ourMac]) {
DDLogError(@"%@ Bad Mac! Their Mac: %@ Our Mac: %@", self.tag, theirMac, ourMac);
@throw [NSException exceptionWithName:InvalidMessageException reason:@"Bad Mac!" userInfo:@{}];
}
}
- (instancetype)init_throws_withData:(NSData *)serialized
{
if (self = [super init]) {
if (serialized.length <= (VERSION_LENGTH + MAC_LENGTH)) {
@throw [NSException exceptionWithName:InvalidMessageException
reason:@"Message size is too short to have content"
userInfo:@{}];
}
Byte version;
[serialized getBytes:&version length:VERSION_LENGTH];
NSUInteger messageAndMacLength;
ows_sub_overflow(serialized.length, VERSION_LENGTH, &messageAndMacLength);
NSData *messageAndMac = [serialized subdataWithRange:NSMakeRange(VERSION_LENGTH, messageAndMacLength)];
NSUInteger messageLength;
ows_sub_overflow(messageAndMac.length, MAC_LENGTH, &messageLength);
NSData *messageData = [messageAndMac subdataWithRange:NSMakeRange(0, messageLength)];
if ([SerializationUtilities highBitsToIntFromByte:version] < MINIMUM_SUPPORTED_VERSION) {
@throw [NSException
exceptionWithName:LegacyMessageException
reason:@"Message was sent with an unsupported version of the TextSecure protocol."
userInfo:@{}];
}
if ([SerializationUtilities highBitsToIntFromByte:version] > CURRENT_VERSION) {
@throw [NSException exceptionWithName:InvalidMessageException
reason:@"Unknown Version"
userInfo:@{
@"Version" : [NSNumber
numberWithChar:[SerializationUtilities highBitsToIntFromByte:version]]
}];
}
NSError *error;
SPKProtoTSProtoWhisperMessage *_Nullable whisperMessage =
[SPKProtoTSProtoWhisperMessage parseData:messageData error:&error];
if (!whisperMessage || error) {
OWSFailDebug(@"Could not parse proto: %@.", error);
OWSRaiseException(InvalidMessageException, @"Could not parse proto.");
}
_serialized = serialized;
_senderRatchetKey = [whisperMessage.ratchetKey throws_removeKeyType];
_version = [SerializationUtilities highBitsToIntFromByte:version];
_counter = whisperMessage.counter;
_previousCounter = whisperMessage.previousCounter;
_cipherText = whisperMessage.ciphertext;
}
return self;
}
- (void)throws_verifyMacWithVersion:(int)messageVersion
senderIdentityKey:(NSData *)senderIdentityKey
receiverIdentityKey:(NSData *)receiverIdentityKey
macKey:(NSData *)macKey
{
OWSAssert(senderIdentityKey);
OWSAssert(receiverIdentityKey);
OWSAssert(macKey);
OWSDataParser *dataParser = [[OWSDataParser alloc] initWithData:self.serialized];
NSError *error;
NSUInteger messageLength;
if (__builtin_sub_overflow(self.serialized.length, MAC_LENGTH, &messageLength)) {
OWSFailDebug(@"Data too short");
OWSRaiseException(InvalidMessageException, @"Data too short");
}
NSData *_Nullable data = [dataParser nextDataWithLength:messageLength
name:@"message data"
error:&error];
if (!data || error) {
OWSFailDebug(@"Could not parse data: %@.", error);
OWSRaiseException(InvalidMessageException, @"Could not parse data.");
}
NSData *_Nullable theirMac = [dataParser nextDataWithLength:MAC_LENGTH
name:@"mac data"
error:&error];
if (!theirMac || error) {
OWSFailDebug(@"Could not parse their mac: %@.", error);
OWSRaiseException(InvalidMessageException, @"Could not parse their mac.");
}
NSData *ourMac = [SerializationUtilities throws_macWithVersion:messageVersion
identityKey:[senderIdentityKey prependKeyType]
receiverIdentityKey:[receiverIdentityKey prependKeyType]
macKey:macKey
serialized:data];
if (![theirMac ows_constantTimeIsEqualToData:ourMac]) {
OWSFailDebug(@"Bad Mac! Their Mac: %@ Our Mac: %@", theirMac, ourMac);
OWSRaiseException(InvalidMessageException, @"Bad Mac!");
}
}
- (CipherMessageType)cipherMessageType {
return CipherMessageType_Whisper;
}
#pragma mark - Logging
+ (NSString *)logTag
+ (NSString *)tag
{
return [NSString stringWithFormat:@"[%@]", self.class];
}
- (NSString *)logTag
- (NSString *)tag
{
return self.class.logTag;
return self.class.tag;
}
@end
NS_ASSUME_NONNULL_END

View File

@ -1,11 +1,13 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// AES-CBC.h
// AxolotlKit
//
// Created by Frederic Jacobs on 22/07/14.
// Copyright (c) 2014 Frederic Jacobs. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface AES_CBC : NSObject
/**
@ -18,9 +20,7 @@ NS_ASSUME_NONNULL_BEGIN
* @return ciphertext
*/
+ (NSData *)throws_encryptCBCMode:(NSData *)data
withKey:(NSData *)key
withIV:(NSData *)iv NS_SWIFT_UNAVAILABLE("throws objc exceptions");
+(NSData*)encryptCBCMode:(NSData*)data withKey:(NSData*)key withIV:(NSData*)iv;
/**
* Decrypts with AES in CBC mode
@ -32,10 +32,6 @@ NS_ASSUME_NONNULL_BEGIN
* @return plaintext
*/
+ (NSData *)throws_decryptCBCMode:(NSData *)data
withKey:(NSData *)key
withIV:(NSData *)iv NS_SWIFT_UNAVAILABLE("throws objc exceptions");
+(NSData*)decryptCBCMode:(NSData*)data withKey:(NSData*)key withIV:(NSData*)iv;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,104 +1,71 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// AES-CBC.m
// AxolotlKit
//
// Created by Frederic Jacobs on 22/07/14.
// Copyright (c) 2014 Frederic Jacobs. All rights reserved.
//
#import "AES-CBC.h"
#import "AxolotlExceptions.h"
#import "MessageKeys.h"
#import <CommonCrypto/CommonCryptor.h>
#import <CommonCrypto/CommonHMAC.h>
#import "AES-CBC.h"
#import <Security/Security.h>
NS_ASSUME_NONNULL_BEGIN
#import <CommonCrypto/CommonHMAC.h>
#import <CommonCrypto/CommonCryptor.h>
@implementation AES_CBC
#pragma mark AESCBC Mode
+ (NSData *)throws_encryptCBCMode:(NSData *)data withKey:(NSData *)key withIV:(NSData *)iv
{
if (!data) {
@throw [NSException exceptionWithName:CipherException reason:@"Missing data to encrypt." userInfo:nil];
}
if (data.length >= SIZE_MAX - kCCBlockSizeAES128) {
@throw [NSException exceptionWithName:CipherException reason:@"Oversize data." userInfo:nil];
}
if (key.length != 32) {
@throw [NSException exceptionWithName:CipherException reason:@"AES key should be 256 bits." userInfo:nil];
}
if (iv.length != 16) {
@throw [NSException exceptionWithName:CipherException reason:@"AES-CBC IV should be 128 bits." userInfo:nil];
}
size_t bufferSize;
ows_add_overflow(data.length, kCCBlockSizeAES128, &bufferSize);
NSMutableData *_Nullable bufferData = [NSMutableData dataWithLength:bufferSize];
OWSAssert(bufferData != nil);
size_t bytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
[key bytes],
[key length],
[iv bytes],
[data bytes],
[data length],
bufferData.mutableBytes,
bufferSize,
&bytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [bufferData subdataWithRange:NSMakeRange(0, bytesEncrypted)];
} else {
@throw [NSException exceptionWithName:CipherException
reason:@"We encountered an issue while encrypting."
userInfo:nil];
+(NSData*)encryptCBCMode:(NSData*)data withKey:(NSData*)key withIV:(NSData*)iv{
NSAssert(data, @"Missing data to encrypt");
NSAssert([key length] == 32, @"AES key should be 256 bits");
NSAssert([iv length] == 16, @"AES-CBC IV should be 128 bits");
size_t bufferSize = [data length] + kCCBlockSizeAES128;
void* buffer = malloc(bufferSize);
size_t bytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
[key bytes], [key length],
[iv bytes],
[data bytes], [data length],
buffer, bufferSize,
&bytesEncrypted);
if (cryptStatus == kCCSuccess){
NSData *data = [NSData dataWithBytes:buffer length:bytesEncrypted];
free(buffer);
return data;
} else{
free(buffer);
@throw [NSException exceptionWithName:CipherException reason:@"We encountered an issue while encrypting." userInfo:nil];
}
}
+ (NSData *)throws_decryptCBCMode:(NSData *)data withKey:(NSData *)key withIV:(NSData *)iv
{
if (!data) {
@throw [NSException exceptionWithName:CipherException reason:@"Missing data to decrypt." userInfo:nil];
}
if (data.length >= SIZE_MAX - kCCBlockSizeAES128) {
@throw [NSException exceptionWithName:CipherException reason:@"Oversize data." userInfo:nil];
}
if (key.length != 32) {
@throw [NSException exceptionWithName:CipherException reason:@"AES key should be 256 bits." userInfo:nil];
}
if (iv.length != 16) {
@throw [NSException exceptionWithName:CipherException reason:@"AES-CBC IV should be 128 bits." userInfo:nil];
}
size_t bufferSize;
ows_add_overflow(data.length, kCCBlockSizeAES128, &bufferSize);
NSMutableData *_Nullable bufferData = [NSMutableData dataWithLength:bufferSize];
OWSAssert(bufferData != nil);
size_t bytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
[key bytes],
[key length],
[iv bytes],
[data bytes],
[data length],
bufferData.mutableBytes,
bufferSize,
&bytesDecrypted);
+(NSData*) decryptCBCMode:(NSData*)data withKey:(NSData*)key withIV:(NSData*)iv {
size_t bufferSize = [data length] + kCCBlockSizeAES128;
void* buffer = malloc(bufferSize);
size_t bytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
[key bytes], [key length],
[iv bytes],
[data bytes], [data length],
buffer, bufferSize,
&bytesDecrypted);
if (cryptStatus == kCCSuccess) {
return [bufferData subdataWithRange:NSMakeRange(0, bytesDecrypted)];
} else {
@throw [NSException exceptionWithName:CipherException
reason:@"We encountered an issue while decrypting."
userInfo:nil];
NSData *plaintext = [NSData dataWithBytes:buffer length:bytesDecrypted];
free(buffer);
return plaintext;
} else{
free(buffer);
@throw [NSException exceptionWithName:CipherException reason:@"We encountered an issue while decrypting." userInfo:nil];
}
}
@end
NS_ASSUME_NONNULL_END

View File

@ -1,11 +1,13 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// AxolotlKeyFetch.h
// AxolotlKit
//
// Created by Frederic Jacobs on 21/07/14.
// Copyright (c) 2014 Frederic Jacobs. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface PreKeyBundle : NSObject <NSSecureCoding>
@property (nonatomic, readonly) NSData *identityKey;
@ -17,15 +19,13 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) int signedPreKeyId;
@property (nonatomic, readonly) NSData *signedPreKeySignature;
- (nullable instancetype)initWithRegistrationId:(int)registrationId
deviceId:(int)deviceId
preKeyId:(int)preKeyId
preKeyPublic:(NSData *)preKeyPublic
signedPreKeyPublic:(NSData *)signedPreKeyPublic
signedPreKeyId:(int)signedPreKeyId
signedPreKeySignature:(NSData *)signedPreKeySignature
identityKey:(NSData *)identityKey;
- (instancetype)initWithRegistrationId:(int)registrationId
deviceId:(int)deviceId
preKeyId:(int)preKeyId
preKeyPublic:(NSData*)preKeyPublic
signedPreKeyPublic:(NSData*)signedPreKeyPublic
signedPreKeyId:(int)signedPreKeyId
signedPreKeySignature:(NSData*)signedPreKeySignature
identityKey:(NSData*)identityKey;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,10 +1,13 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// AxolotlKeyFetch.m
// AxolotlKit
//
// Created by Frederic Jacobs on 21/07/14.
// Copyright (c) 2014 Frederic Jacobs. All rights reserved.
//
#import "PreKeyBundle.h"
NS_ASSUME_NONNULL_BEGIN
static NSString* const kCoderPKBIdentityKey = @"kCoderPKBIdentityKey";
static NSString* const kCoderPKBregistrationId = @"kCoderPKBregistrationId";
@ -17,34 +20,17 @@ static NSString* const kCoderPKBsignedPreKeySignature = @"kCoderPKBsignedPreKeyS
@implementation PreKeyBundle
- (nullable instancetype)initWithRegistrationId:(int)registrationId
deviceId:(int)deviceId
preKeyId:(int)preKeyId
preKeyPublic:(NSData *)preKeyPublic
signedPreKeyPublic:(NSData *)signedPreKeyPublic
signedPreKeyId:(int)signedPreKeyId
signedPreKeySignature:(NSData *)signedPreKeySignature
identityKey:(NSData *)identityKey
{
if (preKeyPublic && preKeyPublic.length != 33) {
OWSFailDebug(@"preKeyPublic && preKeyPublic.length != 33");
return nil;
}
if (signedPreKeyPublic.length != 33) {
OWSFailDebug(@"signedPreKeyPublic.length != 33");
return nil;
}
if (!signedPreKeySignature) {
OWSFailDebug(@"!signedPreKeySignature");
return nil;
}
if (identityKey.length != 33) {
OWSFailDebug(@"identityKey.length != 33");
return nil;
}
- (instancetype)initWithRegistrationId:(int)registrationId
deviceId:(int)deviceId
preKeyId:(int)preKeyId
preKeyPublic:(NSData*)preKeyPublic
signedPreKeyPublic:(NSData*)signedPreKeyPublic
signedPreKeyId:(int)signedPreKeyId
signedPreKeySignature:(NSData*)signedPreKeySignature
identityKey:(NSData*)identityKey{
self = [super init];
if (self) {
_identityKey = identityKey;
_registrationId = registrationId;
@ -59,8 +45,7 @@ static NSString* const kCoderPKBsignedPreKeySignature = @"kCoderPKBsignedPreKeyS
return self;
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
{
- (id)initWithCoder:(NSCoder *)aDecoder{
int registrationId = [aDecoder decodeIntForKey:kCoderPKBregistrationId];
int deviceId = [aDecoder decodeIntForKey:kCoderPKBdeviceId];
int preKeyId = [aDecoder decodeIntForKey:kCoderPKBpreKeyId];
@ -101,5 +86,3 @@ static NSString* const kCoderPKBsignedPreKeySignature = @"kCoderPKBsignedPreKeyS
}
@end
NS_ASSUME_NONNULL_END

View File

@ -5,20 +5,12 @@
#import <Curve25519Kit/Curve25519.h>
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface PreKeyRecord : NSObject <NSSecureCoding>
@property (nonatomic, readonly) int Id;
@property (nonatomic, readonly) ECKeyPair *keyPair;
@property (nonatomic, readonly, nullable) NSDate *createdAt;
- (instancetype)initWithId:(int)identifier
keyPair:(ECKeyPair *)keyPair
createdAt:(NSDate *)createdAt;
- (void)setCreatedAtToNow;
- (instancetype)initWithId:(int)identifier keyPair:(ECKeyPair*)keyPair;
@end
NS_ASSUME_NONNULL_END

View File

@ -8,11 +8,8 @@
#import "PreKeyRecord.h"
NS_ASSUME_NONNULL_BEGIN
static NSString* const kCoderPreKeyId = @"kCoderPreKeyId";
static NSString* const kCoderPreKeyPair = @"kCoderPreKeyPair";
static NSString* const kCoderCreatedAt = @"kCoderCreatedAt";
@implementation PreKeyRecord
@ -20,41 +17,26 @@ static NSString* const kCoderCreatedAt = @"kCoderCreatedAt";
return YES;
}
- (instancetype)initWithId:(int)identifier
keyPair:(ECKeyPair*)keyPair
createdAt:(NSDate *)createdAt
{
OWSAssert(keyPair);
- (instancetype)initWithId:(int)identifier keyPair:(ECKeyPair*)keyPair{
self = [super init];
if (self) {
_Id = identifier;
_keyPair = keyPair;
_createdAt = createdAt;
}
return self;
}
- (nullable id)initWithCoder:(NSCoder *)aDecoder {
return [self initWithId:[aDecoder decodeIntForKey:kCoderPreKeyId]
keyPair:[aDecoder decodeObjectOfClass:[ECKeyPair class] forKey:kCoderPreKeyPair]
createdAt:[aDecoder decodeObjectOfClass:[NSDate class] forKey:kCoderCreatedAt]];
- (id)initWithCoder:(NSCoder *)aDecoder{
return [self initWithId:[aDecoder decodeIntForKey:kCoderPreKeyId] keyPair:[aDecoder decodeObjectOfClass:[ECKeyPair class] forKey:kCoderPreKeyPair]];
}
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeInteger:_Id forKey:kCoderPreKeyId];
[aCoder encodeObject:_keyPair forKey:kCoderPreKeyPair];
if (_createdAt != nil) {
[aCoder encodeObject:_createdAt forKey:kCoderCreatedAt];
}
}
- (void)setCreatedAtToNow {
_createdAt = [NSDate date];
}
@end
NS_ASSUME_NONNULL_END

View File

@ -6,8 +6,6 @@
#import "PreKeyRecord.h"
#import <Curve25519Kit/Curve25519.h>
NS_ASSUME_NONNULL_BEGIN
@interface SignedPreKeyRecord : PreKeyRecord <NSSecureCoding>
@property (nonatomic, readonly) NSData *signature;
@ -16,10 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) BOOL wasAcceptedByService;
- (instancetype)initWithId:(int)identifier keyPair:(ECKeyPair *)keyPair signature:(NSData*)signature generatedAt:(NSDate*)generatedAt;
- (instancetype)initWithId:(int)identifier keyPair:(ECKeyPair *)keyPair NS_UNAVAILABLE;
- (void)markAsAcceptedByService;
@end
NS_ASSUME_NONNULL_END

View File

@ -4,8 +4,6 @@
#import "SignedPrekeyRecord.h"
NS_ASSUME_NONNULL_BEGIN
static NSString* const kCoderPreKeyId = @"kCoderPreKeyId";
static NSString* const kCoderPreKeyPair = @"kCoderPreKeyPair";
static NSString* const kCoderPreKeyDate = @"kCoderPreKeyDate";
@ -24,13 +22,7 @@ static NSString *const kCoderPreKeyWasAcceptedByService = @"kCoderPreKeyWasAccep
generatedAt:(NSDate *)generatedAt
wasAcceptedByService:(BOOL)wasAcceptedByService
{
OWSAssert(keyPair);
OWSAssert(signature);
OWSAssert(generatedAt);
self = [super initWithId:identifier
keyPair:keyPair
createdAt:generatedAt];
self = [super initWithId:identifier keyPair:keyPair];
if (self) {
_signature = signature;
@ -42,9 +34,7 @@ static NSString *const kCoderPreKeyWasAcceptedByService = @"kCoderPreKeyWasAccep
}
- (instancetype)initWithId:(int)identifier keyPair:(ECKeyPair *)keyPair signature:(NSData*)signature generatedAt:(NSDate *)generatedAt{
self = [super initWithId:identifier
keyPair:keyPair
createdAt:generatedAt];
self = [super initWithId:identifier keyPair:keyPair];
if (self) {
_signature = signature;
@ -54,7 +44,7 @@ static NSString *const kCoderPreKeyWasAcceptedByService = @"kCoderPreKeyWasAccep
return self;
}
- (nullable id)initWithCoder:(NSCoder *)aDecoder{
- (id)initWithCoder:(NSCoder *)aDecoder{
return [self initWithId:[aDecoder decodeIntForKey:kCoderPreKeyId]
keyPair:[aDecoder decodeObjectOfClass:[ECKeyPair class] forKey:kCoderPreKeyPair]
signature:[aDecoder decodeObjectOfClass:[NSData class] forKey:kCoderPreKeySignature]
@ -71,7 +61,7 @@ static NSString *const kCoderPreKeyWasAcceptedByService = @"kCoderPreKeyWasAccep
}
- (instancetype)initWithId:(int)identifier keyPair:(ECKeyPair*)keyPair{
OWSAbstractMethod();
NSAssert(FALSE, @"Signed PreKeys need a signature");
return nil;
}
@ -81,5 +71,3 @@ static NSString *const kCoderPreKeyWasAcceptedByService = @"kCoderPreKeyWasAccep
}
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,435 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
#import "ProtocolBuffers/ProtocolBuffers.h"
// @@protoc_insertion_point(imports)
@class TSProtoKeyExchangeMessage;
@class TSProtoKeyExchangeMessageBuilder;
@class TSProtoPreKeyWhisperMessage;
@class TSProtoPreKeyWhisperMessageBuilder;
@class TSProtoSenderKeyDistributionMessage;
@class TSProtoSenderKeyDistributionMessageBuilder;
@class TSProtoSenderKeyMessage;
@class TSProtoSenderKeyMessageBuilder;
@class TSProtoWhisperMessage;
@class TSProtoWhisperMessageBuilder;
#ifndef __has_feature
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
#endif // __has_feature
#ifndef NS_RETURNS_NOT_RETAINED
#if __has_feature(attribute_ns_returns_not_retained)
#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
#else
#define NS_RETURNS_NOT_RETAINED
#endif
#endif
@interface WhisperTextProtocolRoot : NSObject {
}
+ (PBExtensionRegistry*) extensionRegistry;
+ (void) registerAllExtensions:(PBMutableExtensionRegistry*) registry;
@end
@interface TSProtoWhisperMessage : PBGeneratedMessage {
@private
BOOL hasRatchetKey_:1;
BOOL hasCiphertext_:1;
BOOL hasCounter_:1;
BOOL hasPreviousCounter_:1;
NSData* ratchetKey;
NSData* ciphertext;
UInt32 counter;
UInt32 previousCounter;
}
- (BOOL) hasRatchetKey;
- (BOOL) hasCounter;
- (BOOL) hasPreviousCounter;
- (BOOL) hasCiphertext;
@property (readonly, strong) NSData* ratchetKey;
@property (readonly) UInt32 counter;
@property (readonly) UInt32 previousCounter;
@property (readonly, strong) NSData* ciphertext;
+ (TSProtoWhisperMessage*) defaultInstance;
- (TSProtoWhisperMessage*) defaultInstance;
- (BOOL) isInitialized;
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
- (TSProtoWhisperMessageBuilder*) builder;
+ (TSProtoWhisperMessageBuilder*) builder;
+ (TSProtoWhisperMessageBuilder*) builderWithPrototype:(TSProtoWhisperMessage*) prototype;
- (TSProtoWhisperMessageBuilder*) toBuilder;
+ (TSProtoWhisperMessage*) parseFromData:(NSData*) data;
+ (TSProtoWhisperMessage*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (TSProtoWhisperMessage*) parseFromInputStream:(NSInputStream*) input;
+ (TSProtoWhisperMessage*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (TSProtoWhisperMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input;
+ (TSProtoWhisperMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
@end
@interface TSProtoWhisperMessageBuilder : PBGeneratedMessageBuilder {
@private
TSProtoWhisperMessage* result;
}
- (TSProtoWhisperMessage*) defaultInstance;
- (TSProtoWhisperMessageBuilder*) clear;
- (TSProtoWhisperMessageBuilder*) clone;
- (TSProtoWhisperMessage*) build;
- (TSProtoWhisperMessage*) buildPartial;
- (TSProtoWhisperMessageBuilder*) mergeFrom:(TSProtoWhisperMessage*) other;
- (TSProtoWhisperMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
- (TSProtoWhisperMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
- (BOOL) hasRatchetKey;
- (NSData*) ratchetKey;
- (TSProtoWhisperMessageBuilder*) setRatchetKey:(NSData*) value;
- (TSProtoWhisperMessageBuilder*) clearRatchetKey;
- (BOOL) hasCounter;
- (UInt32) counter;
- (TSProtoWhisperMessageBuilder*) setCounter:(UInt32) value;
- (TSProtoWhisperMessageBuilder*) clearCounter;
- (BOOL) hasPreviousCounter;
- (UInt32) previousCounter;
- (TSProtoWhisperMessageBuilder*) setPreviousCounter:(UInt32) value;
- (TSProtoWhisperMessageBuilder*) clearPreviousCounter;
- (BOOL) hasCiphertext;
- (NSData*) ciphertext;
- (TSProtoWhisperMessageBuilder*) setCiphertext:(NSData*) value;
- (TSProtoWhisperMessageBuilder*) clearCiphertext;
@end
@interface TSProtoPreKeyWhisperMessage : PBGeneratedMessage {
@private
BOOL hasBaseKey_:1;
BOOL hasIdentityKey_:1;
BOOL hasMessage_:1;
BOOL hasRegistrationId_:1;
BOOL hasPreKeyId_:1;
BOOL hasSignedPreKeyId_:1;
NSData* baseKey;
NSData* identityKey;
NSData* message;
UInt32 registrationId;
UInt32 preKeyId;
UInt32 signedPreKeyId;
}
- (BOOL) hasRegistrationId;
- (BOOL) hasPreKeyId;
- (BOOL) hasSignedPreKeyId;
- (BOOL) hasBaseKey;
- (BOOL) hasIdentityKey;
- (BOOL) hasMessage;
@property (readonly) UInt32 registrationId;
@property (readonly) UInt32 preKeyId;
@property (readonly) UInt32 signedPreKeyId;
@property (readonly, strong) NSData* baseKey;
@property (readonly, strong) NSData* identityKey;
@property (readonly, strong) NSData* message;
+ (TSProtoPreKeyWhisperMessage*) defaultInstance;
- (TSProtoPreKeyWhisperMessage*) defaultInstance;
- (BOOL) isInitialized;
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
- (TSProtoPreKeyWhisperMessageBuilder*) builder;
+ (TSProtoPreKeyWhisperMessageBuilder*) builder;
+ (TSProtoPreKeyWhisperMessageBuilder*) builderWithPrototype:(TSProtoPreKeyWhisperMessage*) prototype;
- (TSProtoPreKeyWhisperMessageBuilder*) toBuilder;
+ (TSProtoPreKeyWhisperMessage*) parseFromData:(NSData*) data;
+ (TSProtoPreKeyWhisperMessage*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (TSProtoPreKeyWhisperMessage*) parseFromInputStream:(NSInputStream*) input;
+ (TSProtoPreKeyWhisperMessage*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (TSProtoPreKeyWhisperMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input;
+ (TSProtoPreKeyWhisperMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
@end
@interface TSProtoPreKeyWhisperMessageBuilder : PBGeneratedMessageBuilder {
@private
TSProtoPreKeyWhisperMessage* result;
}
- (TSProtoPreKeyWhisperMessage*) defaultInstance;
- (TSProtoPreKeyWhisperMessageBuilder*) clear;
- (TSProtoPreKeyWhisperMessageBuilder*) clone;
- (TSProtoPreKeyWhisperMessage*) build;
- (TSProtoPreKeyWhisperMessage*) buildPartial;
- (TSProtoPreKeyWhisperMessageBuilder*) mergeFrom:(TSProtoPreKeyWhisperMessage*) other;
- (TSProtoPreKeyWhisperMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
- (TSProtoPreKeyWhisperMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
- (BOOL) hasRegistrationId;
- (UInt32) registrationId;
- (TSProtoPreKeyWhisperMessageBuilder*) setRegistrationId:(UInt32) value;
- (TSProtoPreKeyWhisperMessageBuilder*) clearRegistrationId;
- (BOOL) hasPreKeyId;
- (UInt32) preKeyId;
- (TSProtoPreKeyWhisperMessageBuilder*) setPreKeyId:(UInt32) value;
- (TSProtoPreKeyWhisperMessageBuilder*) clearPreKeyId;
- (BOOL) hasSignedPreKeyId;
- (UInt32) signedPreKeyId;
- (TSProtoPreKeyWhisperMessageBuilder*) setSignedPreKeyId:(UInt32) value;
- (TSProtoPreKeyWhisperMessageBuilder*) clearSignedPreKeyId;
- (BOOL) hasBaseKey;
- (NSData*) baseKey;
- (TSProtoPreKeyWhisperMessageBuilder*) setBaseKey:(NSData*) value;
- (TSProtoPreKeyWhisperMessageBuilder*) clearBaseKey;
- (BOOL) hasIdentityKey;
- (NSData*) identityKey;
- (TSProtoPreKeyWhisperMessageBuilder*) setIdentityKey:(NSData*) value;
- (TSProtoPreKeyWhisperMessageBuilder*) clearIdentityKey;
- (BOOL) hasMessage;
- (NSData*) message;
- (TSProtoPreKeyWhisperMessageBuilder*) setMessage:(NSData*) value;
- (TSProtoPreKeyWhisperMessageBuilder*) clearMessage;
@end
@interface TSProtoKeyExchangeMessage : PBGeneratedMessage {
@private
BOOL hasBaseKey_:1;
BOOL hasRatchetKey_:1;
BOOL hasIdentityKey_:1;
BOOL hasBaseKeySignature_:1;
BOOL hasId_:1;
NSData* baseKey;
NSData* ratchetKey;
NSData* identityKey;
NSData* baseKeySignature;
UInt32 id;
}
- (BOOL) hasId;
- (BOOL) hasBaseKey;
- (BOOL) hasRatchetKey;
- (BOOL) hasIdentityKey;
- (BOOL) hasBaseKeySignature;
@property (readonly) UInt32 id;
@property (readonly, strong) NSData* baseKey;
@property (readonly, strong) NSData* ratchetKey;
@property (readonly, strong) NSData* identityKey;
@property (readonly, strong) NSData* baseKeySignature;
+ (TSProtoKeyExchangeMessage*) defaultInstance;
- (TSProtoKeyExchangeMessage*) defaultInstance;
- (BOOL) isInitialized;
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
- (TSProtoKeyExchangeMessageBuilder*) builder;
+ (TSProtoKeyExchangeMessageBuilder*) builder;
+ (TSProtoKeyExchangeMessageBuilder*) builderWithPrototype:(TSProtoKeyExchangeMessage*) prototype;
- (TSProtoKeyExchangeMessageBuilder*) toBuilder;
+ (TSProtoKeyExchangeMessage*) parseFromData:(NSData*) data;
+ (TSProtoKeyExchangeMessage*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (TSProtoKeyExchangeMessage*) parseFromInputStream:(NSInputStream*) input;
+ (TSProtoKeyExchangeMessage*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (TSProtoKeyExchangeMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input;
+ (TSProtoKeyExchangeMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
@end
@interface TSProtoKeyExchangeMessageBuilder : PBGeneratedMessageBuilder {
@private
TSProtoKeyExchangeMessage* result;
}
- (TSProtoKeyExchangeMessage*) defaultInstance;
- (TSProtoKeyExchangeMessageBuilder*) clear;
- (TSProtoKeyExchangeMessageBuilder*) clone;
- (TSProtoKeyExchangeMessage*) build;
- (TSProtoKeyExchangeMessage*) buildPartial;
- (TSProtoKeyExchangeMessageBuilder*) mergeFrom:(TSProtoKeyExchangeMessage*) other;
- (TSProtoKeyExchangeMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
- (TSProtoKeyExchangeMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
- (BOOL) hasId;
- (UInt32) id;
- (TSProtoKeyExchangeMessageBuilder*) setId:(UInt32) value;
- (TSProtoKeyExchangeMessageBuilder*) clearId;
- (BOOL) hasBaseKey;
- (NSData*) baseKey;
- (TSProtoKeyExchangeMessageBuilder*) setBaseKey:(NSData*) value;
- (TSProtoKeyExchangeMessageBuilder*) clearBaseKey;
- (BOOL) hasRatchetKey;
- (NSData*) ratchetKey;
- (TSProtoKeyExchangeMessageBuilder*) setRatchetKey:(NSData*) value;
- (TSProtoKeyExchangeMessageBuilder*) clearRatchetKey;
- (BOOL) hasIdentityKey;
- (NSData*) identityKey;
- (TSProtoKeyExchangeMessageBuilder*) setIdentityKey:(NSData*) value;
- (TSProtoKeyExchangeMessageBuilder*) clearIdentityKey;
- (BOOL) hasBaseKeySignature;
- (NSData*) baseKeySignature;
- (TSProtoKeyExchangeMessageBuilder*) setBaseKeySignature:(NSData*) value;
- (TSProtoKeyExchangeMessageBuilder*) clearBaseKeySignature;
@end
@interface TSProtoSenderKeyMessage : PBGeneratedMessage {
@private
BOOL hasCiphertext_:1;
BOOL hasId_:1;
BOOL hasIteration_:1;
NSData* ciphertext;
UInt32 id;
UInt32 iteration;
}
- (BOOL) hasId;
- (BOOL) hasIteration;
- (BOOL) hasCiphertext;
@property (readonly) UInt32 id;
@property (readonly) UInt32 iteration;
@property (readonly, strong) NSData* ciphertext;
+ (TSProtoSenderKeyMessage*) defaultInstance;
- (TSProtoSenderKeyMessage*) defaultInstance;
- (BOOL) isInitialized;
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
- (TSProtoSenderKeyMessageBuilder*) builder;
+ (TSProtoSenderKeyMessageBuilder*) builder;
+ (TSProtoSenderKeyMessageBuilder*) builderWithPrototype:(TSProtoSenderKeyMessage*) prototype;
- (TSProtoSenderKeyMessageBuilder*) toBuilder;
+ (TSProtoSenderKeyMessage*) parseFromData:(NSData*) data;
+ (TSProtoSenderKeyMessage*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (TSProtoSenderKeyMessage*) parseFromInputStream:(NSInputStream*) input;
+ (TSProtoSenderKeyMessage*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (TSProtoSenderKeyMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input;
+ (TSProtoSenderKeyMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
@end
@interface TSProtoSenderKeyMessageBuilder : PBGeneratedMessageBuilder {
@private
TSProtoSenderKeyMessage* result;
}
- (TSProtoSenderKeyMessage*) defaultInstance;
- (TSProtoSenderKeyMessageBuilder*) clear;
- (TSProtoSenderKeyMessageBuilder*) clone;
- (TSProtoSenderKeyMessage*) build;
- (TSProtoSenderKeyMessage*) buildPartial;
- (TSProtoSenderKeyMessageBuilder*) mergeFrom:(TSProtoSenderKeyMessage*) other;
- (TSProtoSenderKeyMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
- (TSProtoSenderKeyMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
- (BOOL) hasId;
- (UInt32) id;
- (TSProtoSenderKeyMessageBuilder*) setId:(UInt32) value;
- (TSProtoSenderKeyMessageBuilder*) clearId;
- (BOOL) hasIteration;
- (UInt32) iteration;
- (TSProtoSenderKeyMessageBuilder*) setIteration:(UInt32) value;
- (TSProtoSenderKeyMessageBuilder*) clearIteration;
- (BOOL) hasCiphertext;
- (NSData*) ciphertext;
- (TSProtoSenderKeyMessageBuilder*) setCiphertext:(NSData*) value;
- (TSProtoSenderKeyMessageBuilder*) clearCiphertext;
@end
@interface TSProtoSenderKeyDistributionMessage : PBGeneratedMessage {
@private
BOOL hasChainKey_:1;
BOOL hasSigningKey_:1;
BOOL hasId_:1;
BOOL hasIteration_:1;
NSData* chainKey;
NSData* signingKey;
UInt32 id;
UInt32 iteration;
}
- (BOOL) hasId;
- (BOOL) hasIteration;
- (BOOL) hasChainKey;
- (BOOL) hasSigningKey;
@property (readonly) UInt32 id;
@property (readonly) UInt32 iteration;
@property (readonly, strong) NSData* chainKey;
@property (readonly, strong) NSData* signingKey;
+ (TSProtoSenderKeyDistributionMessage*) defaultInstance;
- (TSProtoSenderKeyDistributionMessage*) defaultInstance;
- (BOOL) isInitialized;
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
- (TSProtoSenderKeyDistributionMessageBuilder*) builder;
+ (TSProtoSenderKeyDistributionMessageBuilder*) builder;
+ (TSProtoSenderKeyDistributionMessageBuilder*) builderWithPrototype:(TSProtoSenderKeyDistributionMessage*) prototype;
- (TSProtoSenderKeyDistributionMessageBuilder*) toBuilder;
+ (TSProtoSenderKeyDistributionMessage*) parseFromData:(NSData*) data;
+ (TSProtoSenderKeyDistributionMessage*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (TSProtoSenderKeyDistributionMessage*) parseFromInputStream:(NSInputStream*) input;
+ (TSProtoSenderKeyDistributionMessage*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (TSProtoSenderKeyDistributionMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input;
+ (TSProtoSenderKeyDistributionMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
@end
@interface TSProtoSenderKeyDistributionMessageBuilder : PBGeneratedMessageBuilder {
@private
TSProtoSenderKeyDistributionMessage* result;
}
- (TSProtoSenderKeyDistributionMessage*) defaultInstance;
- (TSProtoSenderKeyDistributionMessageBuilder*) clear;
- (TSProtoSenderKeyDistributionMessageBuilder*) clone;
- (TSProtoSenderKeyDistributionMessage*) build;
- (TSProtoSenderKeyDistributionMessage*) buildPartial;
- (TSProtoSenderKeyDistributionMessageBuilder*) mergeFrom:(TSProtoSenderKeyDistributionMessage*) other;
- (TSProtoSenderKeyDistributionMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
- (TSProtoSenderKeyDistributionMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
- (BOOL) hasId;
- (UInt32) id;
- (TSProtoSenderKeyDistributionMessageBuilder*) setId:(UInt32) value;
- (TSProtoSenderKeyDistributionMessageBuilder*) clearId;
- (BOOL) hasIteration;
- (UInt32) iteration;
- (TSProtoSenderKeyDistributionMessageBuilder*) setIteration:(UInt32) value;
- (TSProtoSenderKeyDistributionMessageBuilder*) clearIteration;
- (BOOL) hasChainKey;
- (NSData*) chainKey;
- (TSProtoSenderKeyDistributionMessageBuilder*) setChainKey:(NSData*) value;
- (TSProtoSenderKeyDistributionMessageBuilder*) clearChainKey;
- (BOOL) hasSigningKey;
- (NSData*) signingKey;
- (TSProtoSenderKeyDistributionMessageBuilder*) setSigningKey:(NSData*) value;
- (TSProtoSenderKeyDistributionMessageBuilder*) clearSigningKey;
@end
// @@protoc_insertion_point(global_scope)

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +1,18 @@
// iOS - since we use a modern proto-compiler, we must specify
// the legacy proto format.
syntax = "proto2";
// iOS - package name determines class prefix
package SPKProtos;
package textsecure;
message TSProtoWhisperMessage {
// @required
optional bytes ratchetKey = 1;
// @required
optional uint32 counter = 2;
optional uint32 previousCounter = 3;
// @required
optional bytes ciphertext = 4;
}
message TSProtoPreKeyWhisperMessage {
optional uint32 registrationId = 5;
optional uint32 preKeyId = 1;
// @required
optional uint32 signedPreKeyId = 6;
// @required
optional bytes baseKey = 2;
// @required
optional bytes identityKey = 3;
// @required
optional bytes message = 4; // WhisperMessage
}

View File

@ -1,12 +0,0 @@
PROTOC=protoc \
--proto_path='./'
WRAPPER_SCRIPT=../../../../Signal-iOS/Scripts/ProtoWrappers.py \
--proto-dir='./' --verbose --add-log-tag
all: webrtc_data_proto
webrtc_data_proto: WhisperTextProtocol.proto
$(PROTOC) --swift_out=. \
WhisperTextProtocol.proto
$(WRAPPER_SCRIPT) --dst-dir=. \
--wrapper-prefix=SPKProto --proto-prefix=SPKProtos --proto-file=WhisperTextProtocol.proto

View File

@ -1,647 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
// WARNING: This code is generated. Only edit within the markers.
public enum SPKProtoError: Error {
case invalidProtobuf(description: String)
}
// MARK: - SPKProtoTSProtoWhisperMessage
@objc public class SPKProtoTSProtoWhisperMessage: NSObject {
// MARK: - SPKProtoTSProtoWhisperMessageBuilder
@objc public class func builder(ratchetKey: Data, counter: UInt32, ciphertext: Data) -> SPKProtoTSProtoWhisperMessageBuilder {
return SPKProtoTSProtoWhisperMessageBuilder(ratchetKey: ratchetKey, counter: counter, ciphertext: ciphertext)
}
@objc public class SPKProtoTSProtoWhisperMessageBuilder: NSObject {
private var proto = SPKProtos_TSProtoWhisperMessage()
@objc fileprivate override init() {}
@objc fileprivate init(ratchetKey: Data, counter: UInt32, ciphertext: Data) {
super.init()
setRatchetKey(ratchetKey)
setCounter(counter)
setCiphertext(ciphertext)
}
@objc public func setRatchetKey(_ valueParam: Data) {
proto.ratchetKey = valueParam
}
@objc public func setCounter(_ valueParam: UInt32) {
proto.counter = valueParam
}
@objc public func setPreviousCounter(_ valueParam: UInt32) {
proto.previousCounter = valueParam
}
@objc public func setCiphertext(_ valueParam: Data) {
proto.ciphertext = valueParam
}
@objc public func build() throws -> SPKProtoTSProtoWhisperMessage {
return try SPKProtoTSProtoWhisperMessage.parseProto(proto)
}
@objc public func buildSerializedData() throws -> Data {
return try SPKProtoTSProtoWhisperMessage.parseProto(proto).serializedData()
}
}
fileprivate let proto: SPKProtos_TSProtoWhisperMessage
@objc public let ratchetKey: Data
@objc public let counter: UInt32
@objc public let ciphertext: Data
@objc public var previousCounter: UInt32 {
return proto.previousCounter
}
@objc public var hasPreviousCounter: Bool {
return proto.hasPreviousCounter
}
private init(proto: SPKProtos_TSProtoWhisperMessage,
ratchetKey: Data,
counter: UInt32,
ciphertext: Data) {
self.proto = proto
self.ratchetKey = ratchetKey
self.counter = counter
self.ciphertext = ciphertext
}
@objc
public func serializedData() throws -> Data {
return try self.proto.serializedData()
}
@objc public class func parseData(_ serializedData: Data) throws -> SPKProtoTSProtoWhisperMessage {
let proto = try SPKProtos_TSProtoWhisperMessage(serializedData: serializedData)
return try parseProto(proto)
}
fileprivate class func parseProto(_ proto: SPKProtos_TSProtoWhisperMessage) throws -> SPKProtoTSProtoWhisperMessage {
guard proto.hasRatchetKey else {
throw SPKProtoError.invalidProtobuf(description: "\(logTag) missing required field: ratchetKey")
}
let ratchetKey = proto.ratchetKey
guard proto.hasCounter else {
throw SPKProtoError.invalidProtobuf(description: "\(logTag) missing required field: counter")
}
let counter = proto.counter
guard proto.hasCiphertext else {
throw SPKProtoError.invalidProtobuf(description: "\(logTag) missing required field: ciphertext")
}
let ciphertext = proto.ciphertext
// MARK: - Begin Validation Logic for SPKProtoTSProtoWhisperMessage -
// MARK: - End Validation Logic for SPKProtoTSProtoWhisperMessage -
let result = SPKProtoTSProtoWhisperMessage(proto: proto,
ratchetKey: ratchetKey,
counter: counter,
ciphertext: ciphertext)
return result
}
}
#if DEBUG
extension SPKProtoTSProtoWhisperMessage {
@objc public func serializedDataIgnoringErrors() -> Data? {
return try! self.serializedData()
}
}
extension SPKProtoTSProtoWhisperMessage.SPKProtoTSProtoWhisperMessageBuilder {
@objc public func buildIgnoringErrors() -> SPKProtoTSProtoWhisperMessage? {
return try! self.build()
}
}
#endif
// MARK: - SPKProtoTSProtoPreKeyWhisperMessage
@objc public class SPKProtoTSProtoPreKeyWhisperMessage: NSObject {
// MARK: - SPKProtoTSProtoPreKeyWhisperMessageBuilder
@objc public class func builder(signedPreKeyID: UInt32, baseKey: Data, identityKey: Data, message: Data) -> SPKProtoTSProtoPreKeyWhisperMessageBuilder {
return SPKProtoTSProtoPreKeyWhisperMessageBuilder(signedPreKeyID: signedPreKeyID, baseKey: baseKey, identityKey: identityKey, message: message)
}
@objc public class SPKProtoTSProtoPreKeyWhisperMessageBuilder: NSObject {
private var proto = SPKProtos_TSProtoPreKeyWhisperMessage()
@objc fileprivate override init() {}
@objc fileprivate init(signedPreKeyID: UInt32, baseKey: Data, identityKey: Data, message: Data) {
super.init()
setSignedPreKeyID(signedPreKeyID)
setBaseKey(baseKey)
setIdentityKey(identityKey)
setMessage(message)
}
@objc public func setRegistrationID(_ valueParam: UInt32) {
proto.registrationID = valueParam
}
@objc public func setPreKeyID(_ valueParam: UInt32) {
proto.preKeyID = valueParam
}
@objc public func setSignedPreKeyID(_ valueParam: UInt32) {
proto.signedPreKeyID = valueParam
}
@objc public func setBaseKey(_ valueParam: Data) {
proto.baseKey = valueParam
}
@objc public func setIdentityKey(_ valueParam: Data) {
proto.identityKey = valueParam
}
@objc public func setMessage(_ valueParam: Data) {
proto.message = valueParam
}
@objc public func build() throws -> SPKProtoTSProtoPreKeyWhisperMessage {
return try SPKProtoTSProtoPreKeyWhisperMessage.parseProto(proto)
}
@objc public func buildSerializedData() throws -> Data {
return try SPKProtoTSProtoPreKeyWhisperMessage.parseProto(proto).serializedData()
}
}
fileprivate let proto: SPKProtos_TSProtoPreKeyWhisperMessage
@objc public let signedPreKeyID: UInt32
@objc public let baseKey: Data
@objc public let identityKey: Data
@objc public let message: Data
@objc public var registrationID: UInt32 {
return proto.registrationID
}
@objc public var hasRegistrationID: Bool {
return proto.hasRegistrationID
}
@objc public var preKeyID: UInt32 {
return proto.preKeyID
}
@objc public var hasPreKeyID: Bool {
return proto.hasPreKeyID
}
private init(proto: SPKProtos_TSProtoPreKeyWhisperMessage,
signedPreKeyID: UInt32,
baseKey: Data,
identityKey: Data,
message: Data) {
self.proto = proto
self.signedPreKeyID = signedPreKeyID
self.baseKey = baseKey
self.identityKey = identityKey
self.message = message
}
@objc
public func serializedData() throws -> Data {
return try self.proto.serializedData()
}
@objc public class func parseData(_ serializedData: Data) throws -> SPKProtoTSProtoPreKeyWhisperMessage {
let proto = try SPKProtos_TSProtoPreKeyWhisperMessage(serializedData: serializedData)
return try parseProto(proto)
}
fileprivate class func parseProto(_ proto: SPKProtos_TSProtoPreKeyWhisperMessage) throws -> SPKProtoTSProtoPreKeyWhisperMessage {
guard proto.hasSignedPreKeyID else {
throw SPKProtoError.invalidProtobuf(description: "\(logTag) missing required field: signedPreKeyID")
}
let signedPreKeyID = proto.signedPreKeyID
guard proto.hasBaseKey else {
throw SPKProtoError.invalidProtobuf(description: "\(logTag) missing required field: baseKey")
}
let baseKey = proto.baseKey
guard proto.hasIdentityKey else {
throw SPKProtoError.invalidProtobuf(description: "\(logTag) missing required field: identityKey")
}
let identityKey = proto.identityKey
guard proto.hasMessage else {
throw SPKProtoError.invalidProtobuf(description: "\(logTag) missing required field: message")
}
let message = proto.message
// MARK: - Begin Validation Logic for SPKProtoTSProtoPreKeyWhisperMessage -
// MARK: - End Validation Logic for SPKProtoTSProtoPreKeyWhisperMessage -
let result = SPKProtoTSProtoPreKeyWhisperMessage(proto: proto,
signedPreKeyID: signedPreKeyID,
baseKey: baseKey,
identityKey: identityKey,
message: message)
return result
}
}
#if DEBUG
extension SPKProtoTSProtoPreKeyWhisperMessage {
@objc public func serializedDataIgnoringErrors() -> Data? {
return try! self.serializedData()
}
}
extension SPKProtoTSProtoPreKeyWhisperMessage.SPKProtoTSProtoPreKeyWhisperMessageBuilder {
@objc public func buildIgnoringErrors() -> SPKProtoTSProtoPreKeyWhisperMessage? {
return try! self.build()
}
}
#endif
// MARK: - SPKProtoTSProtoKeyExchangeMessage
@objc public class SPKProtoTSProtoKeyExchangeMessage: NSObject {
// MARK: - SPKProtoTSProtoKeyExchangeMessageBuilder
@objc public class func builder() -> SPKProtoTSProtoKeyExchangeMessageBuilder {
return SPKProtoTSProtoKeyExchangeMessageBuilder()
}
@objc public class SPKProtoTSProtoKeyExchangeMessageBuilder: NSObject {
private var proto = SPKProtos_TSProtoKeyExchangeMessage()
@objc fileprivate override init() {}
@objc public func setId(_ valueParam: UInt32) {
proto.id = valueParam
}
@objc public func setBaseKey(_ valueParam: Data) {
proto.baseKey = valueParam
}
@objc public func setRatchetKey(_ valueParam: Data) {
proto.ratchetKey = valueParam
}
@objc public func setIdentityKey(_ valueParam: Data) {
proto.identityKey = valueParam
}
@objc public func setBaseKeySignature(_ valueParam: Data) {
proto.baseKeySignature = valueParam
}
@objc public func build() throws -> SPKProtoTSProtoKeyExchangeMessage {
return try SPKProtoTSProtoKeyExchangeMessage.parseProto(proto)
}
@objc public func buildSerializedData() throws -> Data {
return try SPKProtoTSProtoKeyExchangeMessage.parseProto(proto).serializedData()
}
}
fileprivate let proto: SPKProtos_TSProtoKeyExchangeMessage
@objc public var id: UInt32 {
return proto.id
}
@objc public var hasID: Bool {
return proto.hasID
}
@objc public var baseKey: Data? {
guard proto.hasBaseKey else {
return nil
}
return proto.baseKey
}
@objc public var hasBaseKey: Bool {
return proto.hasBaseKey
}
@objc public var ratchetKey: Data? {
guard proto.hasRatchetKey else {
return nil
}
return proto.ratchetKey
}
@objc public var hasRatchetKey: Bool {
return proto.hasRatchetKey
}
@objc public var identityKey: Data? {
guard proto.hasIdentityKey else {
return nil
}
return proto.identityKey
}
@objc public var hasIdentityKey: Bool {
return proto.hasIdentityKey
}
@objc public var baseKeySignature: Data? {
guard proto.hasBaseKeySignature else {
return nil
}
return proto.baseKeySignature
}
@objc public var hasBaseKeySignature: Bool {
return proto.hasBaseKeySignature
}
private init(proto: SPKProtos_TSProtoKeyExchangeMessage) {
self.proto = proto
}
@objc
public func serializedData() throws -> Data {
return try self.proto.serializedData()
}
@objc public class func parseData(_ serializedData: Data) throws -> SPKProtoTSProtoKeyExchangeMessage {
let proto = try SPKProtos_TSProtoKeyExchangeMessage(serializedData: serializedData)
return try parseProto(proto)
}
fileprivate class func parseProto(_ proto: SPKProtos_TSProtoKeyExchangeMessage) throws -> SPKProtoTSProtoKeyExchangeMessage {
// MARK: - Begin Validation Logic for SPKProtoTSProtoKeyExchangeMessage -
// MARK: - End Validation Logic for SPKProtoTSProtoKeyExchangeMessage -
let result = SPKProtoTSProtoKeyExchangeMessage(proto: proto)
return result
}
}
#if DEBUG
extension SPKProtoTSProtoKeyExchangeMessage {
@objc public func serializedDataIgnoringErrors() -> Data? {
return try! self.serializedData()
}
}
extension SPKProtoTSProtoKeyExchangeMessage.SPKProtoTSProtoKeyExchangeMessageBuilder {
@objc public func buildIgnoringErrors() -> SPKProtoTSProtoKeyExchangeMessage? {
return try! self.build()
}
}
#endif
// MARK: - SPKProtoTSProtoSenderKeyMessage
@objc public class SPKProtoTSProtoSenderKeyMessage: NSObject {
// MARK: - SPKProtoTSProtoSenderKeyMessageBuilder
@objc public class func builder() -> SPKProtoTSProtoSenderKeyMessageBuilder {
return SPKProtoTSProtoSenderKeyMessageBuilder()
}
@objc public class SPKProtoTSProtoSenderKeyMessageBuilder: NSObject {
private var proto = SPKProtos_TSProtoSenderKeyMessage()
@objc fileprivate override init() {}
@objc public func setId(_ valueParam: UInt32) {
proto.id = valueParam
}
@objc public func setIteration(_ valueParam: UInt32) {
proto.iteration = valueParam
}
@objc public func setCiphertext(_ valueParam: Data) {
proto.ciphertext = valueParam
}
@objc public func build() throws -> SPKProtoTSProtoSenderKeyMessage {
return try SPKProtoTSProtoSenderKeyMessage.parseProto(proto)
}
@objc public func buildSerializedData() throws -> Data {
return try SPKProtoTSProtoSenderKeyMessage.parseProto(proto).serializedData()
}
}
fileprivate let proto: SPKProtos_TSProtoSenderKeyMessage
@objc public var id: UInt32 {
return proto.id
}
@objc public var hasID: Bool {
return proto.hasID
}
@objc public var iteration: UInt32 {
return proto.iteration
}
@objc public var hasIteration: Bool {
return proto.hasIteration
}
@objc public var ciphertext: Data? {
guard proto.hasCiphertext else {
return nil
}
return proto.ciphertext
}
@objc public var hasCiphertext: Bool {
return proto.hasCiphertext
}
private init(proto: SPKProtos_TSProtoSenderKeyMessage) {
self.proto = proto
}
@objc
public func serializedData() throws -> Data {
return try self.proto.serializedData()
}
@objc public class func parseData(_ serializedData: Data) throws -> SPKProtoTSProtoSenderKeyMessage {
let proto = try SPKProtos_TSProtoSenderKeyMessage(serializedData: serializedData)
return try parseProto(proto)
}
fileprivate class func parseProto(_ proto: SPKProtos_TSProtoSenderKeyMessage) throws -> SPKProtoTSProtoSenderKeyMessage {
// MARK: - Begin Validation Logic for SPKProtoTSProtoSenderKeyMessage -
// MARK: - End Validation Logic for SPKProtoTSProtoSenderKeyMessage -
let result = SPKProtoTSProtoSenderKeyMessage(proto: proto)
return result
}
}
#if DEBUG
extension SPKProtoTSProtoSenderKeyMessage {
@objc public func serializedDataIgnoringErrors() -> Data? {
return try! self.serializedData()
}
}
extension SPKProtoTSProtoSenderKeyMessage.SPKProtoTSProtoSenderKeyMessageBuilder {
@objc public func buildIgnoringErrors() -> SPKProtoTSProtoSenderKeyMessage? {
return try! self.build()
}
}
#endif
// MARK: - SPKProtoTSProtoSenderKeyDistributionMessage
@objc public class SPKProtoTSProtoSenderKeyDistributionMessage: NSObject {
// MARK: - SPKProtoTSProtoSenderKeyDistributionMessageBuilder
@objc public class func builder() -> SPKProtoTSProtoSenderKeyDistributionMessageBuilder {
return SPKProtoTSProtoSenderKeyDistributionMessageBuilder()
}
@objc public class SPKProtoTSProtoSenderKeyDistributionMessageBuilder: NSObject {
private var proto = SPKProtos_TSProtoSenderKeyDistributionMessage()
@objc fileprivate override init() {}
@objc public func setId(_ valueParam: UInt32) {
proto.id = valueParam
}
@objc public func setIteration(_ valueParam: UInt32) {
proto.iteration = valueParam
}
@objc public func setChainKey(_ valueParam: Data) {
proto.chainKey = valueParam
}
@objc public func setSigningKey(_ valueParam: Data) {
proto.signingKey = valueParam
}
@objc public func build() throws -> SPKProtoTSProtoSenderKeyDistributionMessage {
return try SPKProtoTSProtoSenderKeyDistributionMessage.parseProto(proto)
}
@objc public func buildSerializedData() throws -> Data {
return try SPKProtoTSProtoSenderKeyDistributionMessage.parseProto(proto).serializedData()
}
}
fileprivate let proto: SPKProtos_TSProtoSenderKeyDistributionMessage
@objc public var id: UInt32 {
return proto.id
}
@objc public var hasID: Bool {
return proto.hasID
}
@objc public var iteration: UInt32 {
return proto.iteration
}
@objc public var hasIteration: Bool {
return proto.hasIteration
}
@objc public var chainKey: Data? {
guard proto.hasChainKey else {
return nil
}
return proto.chainKey
}
@objc public var hasChainKey: Bool {
return proto.hasChainKey
}
@objc public var signingKey: Data? {
guard proto.hasSigningKey else {
return nil
}
return proto.signingKey
}
@objc public var hasSigningKey: Bool {
return proto.hasSigningKey
}
private init(proto: SPKProtos_TSProtoSenderKeyDistributionMessage) {
self.proto = proto
}
@objc
public func serializedData() throws -> Data {
return try self.proto.serializedData()
}
@objc public class func parseData(_ serializedData: Data) throws -> SPKProtoTSProtoSenderKeyDistributionMessage {
let proto = try SPKProtos_TSProtoSenderKeyDistributionMessage(serializedData: serializedData)
return try parseProto(proto)
}
fileprivate class func parseProto(_ proto: SPKProtos_TSProtoSenderKeyDistributionMessage) throws -> SPKProtoTSProtoSenderKeyDistributionMessage {
// MARK: - Begin Validation Logic for SPKProtoTSProtoSenderKeyDistributionMessage -
// MARK: - End Validation Logic for SPKProtoTSProtoSenderKeyDistributionMessage -
let result = SPKProtoTSProtoSenderKeyDistributionMessage(proto: proto)
return result
}
}
#if DEBUG
extension SPKProtoTSProtoSenderKeyDistributionMessage {
@objc public func serializedDataIgnoringErrors() -> Data? {
return try! self.serializedData()
}
}
extension SPKProtoTSProtoSenderKeyDistributionMessage.SPKProtoTSProtoSenderKeyDistributionMessageBuilder {
@objc public func buildIgnoringErrors() -> SPKProtoTSProtoSenderKeyDistributionMessage? {
return try! self.build()
}
}
#endif

View File

@ -1,556 +0,0 @@
// DO NOT EDIT.
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: WhisperTextProtocol.proto
//
// For information on using the generated types, please see the documenation:
// https://github.com/apple/swift-protobuf/
/// iOS - since we use a modern proto-compiler, we must specify
/// the legacy proto format.
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that your are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
struct SPKProtos_TSProtoWhisperMessage {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
/// @required
var ratchetKey: Data {
get {return _ratchetKey ?? SwiftProtobuf.Internal.emptyData}
set {_ratchetKey = newValue}
}
/// Returns true if `ratchetKey` has been explicitly set.
var hasRatchetKey: Bool {return self._ratchetKey != nil}
/// Clears the value of `ratchetKey`. Subsequent reads from it will return its default value.
mutating func clearRatchetKey() {self._ratchetKey = nil}
/// @required
var counter: UInt32 {
get {return _counter ?? 0}
set {_counter = newValue}
}
/// Returns true if `counter` has been explicitly set.
var hasCounter: Bool {return self._counter != nil}
/// Clears the value of `counter`. Subsequent reads from it will return its default value.
mutating func clearCounter() {self._counter = nil}
var previousCounter: UInt32 {
get {return _previousCounter ?? 0}
set {_previousCounter = newValue}
}
/// Returns true if `previousCounter` has been explicitly set.
var hasPreviousCounter: Bool {return self._previousCounter != nil}
/// Clears the value of `previousCounter`. Subsequent reads from it will return its default value.
mutating func clearPreviousCounter() {self._previousCounter = nil}
/// @required
var ciphertext: Data {
get {return _ciphertext ?? SwiftProtobuf.Internal.emptyData}
set {_ciphertext = newValue}
}
/// Returns true if `ciphertext` has been explicitly set.
var hasCiphertext: Bool {return self._ciphertext != nil}
/// Clears the value of `ciphertext`. Subsequent reads from it will return its default value.
mutating func clearCiphertext() {self._ciphertext = nil}
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
fileprivate var _ratchetKey: Data? = nil
fileprivate var _counter: UInt32? = nil
fileprivate var _previousCounter: UInt32? = nil
fileprivate var _ciphertext: Data? = nil
}
struct SPKProtos_TSProtoPreKeyWhisperMessage {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var registrationID: UInt32 {
get {return _registrationID ?? 0}
set {_registrationID = newValue}
}
/// Returns true if `registrationID` has been explicitly set.
var hasRegistrationID: Bool {return self._registrationID != nil}
/// Clears the value of `registrationID`. Subsequent reads from it will return its default value.
mutating func clearRegistrationID() {self._registrationID = nil}
var preKeyID: UInt32 {
get {return _preKeyID ?? 0}
set {_preKeyID = newValue}
}
/// Returns true if `preKeyID` has been explicitly set.
var hasPreKeyID: Bool {return self._preKeyID != nil}
/// Clears the value of `preKeyID`. Subsequent reads from it will return its default value.
mutating func clearPreKeyID() {self._preKeyID = nil}
/// @required
var signedPreKeyID: UInt32 {
get {return _signedPreKeyID ?? 0}
set {_signedPreKeyID = newValue}
}
/// Returns true if `signedPreKeyID` has been explicitly set.
var hasSignedPreKeyID: Bool {return self._signedPreKeyID != nil}
/// Clears the value of `signedPreKeyID`. Subsequent reads from it will return its default value.
mutating func clearSignedPreKeyID() {self._signedPreKeyID = nil}
/// @required
var baseKey: Data {
get {return _baseKey ?? SwiftProtobuf.Internal.emptyData}
set {_baseKey = newValue}
}
/// Returns true if `baseKey` has been explicitly set.
var hasBaseKey: Bool {return self._baseKey != nil}
/// Clears the value of `baseKey`. Subsequent reads from it will return its default value.
mutating func clearBaseKey() {self._baseKey = nil}
/// @required
var identityKey: Data {
get {return _identityKey ?? SwiftProtobuf.Internal.emptyData}
set {_identityKey = newValue}
}
/// Returns true if `identityKey` has been explicitly set.
var hasIdentityKey: Bool {return self._identityKey != nil}
/// Clears the value of `identityKey`. Subsequent reads from it will return its default value.
mutating func clearIdentityKey() {self._identityKey = nil}
/// @required
var message: Data {
get {return _message ?? SwiftProtobuf.Internal.emptyData}
set {_message = newValue}
}
/// Returns true if `message` has been explicitly set.
var hasMessage: Bool {return self._message != nil}
/// Clears the value of `message`. Subsequent reads from it will return its default value.
mutating func clearMessage() {self._message = nil}
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
fileprivate var _registrationID: UInt32? = nil
fileprivate var _preKeyID: UInt32? = nil
fileprivate var _signedPreKeyID: UInt32? = nil
fileprivate var _baseKey: Data? = nil
fileprivate var _identityKey: Data? = nil
fileprivate var _message: Data? = nil
}
struct SPKProtos_TSProtoKeyExchangeMessage {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var id: UInt32 {
get {return _id ?? 0}
set {_id = newValue}
}
/// Returns true if `id` has been explicitly set.
var hasID: Bool {return self._id != nil}
/// Clears the value of `id`. Subsequent reads from it will return its default value.
mutating func clearID() {self._id = nil}
var baseKey: Data {
get {return _baseKey ?? SwiftProtobuf.Internal.emptyData}
set {_baseKey = newValue}
}
/// Returns true if `baseKey` has been explicitly set.
var hasBaseKey: Bool {return self._baseKey != nil}
/// Clears the value of `baseKey`. Subsequent reads from it will return its default value.
mutating func clearBaseKey() {self._baseKey = nil}
var ratchetKey: Data {
get {return _ratchetKey ?? SwiftProtobuf.Internal.emptyData}
set {_ratchetKey = newValue}
}
/// Returns true if `ratchetKey` has been explicitly set.
var hasRatchetKey: Bool {return self._ratchetKey != nil}
/// Clears the value of `ratchetKey`. Subsequent reads from it will return its default value.
mutating func clearRatchetKey() {self._ratchetKey = nil}
var identityKey: Data {
get {return _identityKey ?? SwiftProtobuf.Internal.emptyData}
set {_identityKey = newValue}
}
/// Returns true if `identityKey` has been explicitly set.
var hasIdentityKey: Bool {return self._identityKey != nil}
/// Clears the value of `identityKey`. Subsequent reads from it will return its default value.
mutating func clearIdentityKey() {self._identityKey = nil}
var baseKeySignature: Data {
get {return _baseKeySignature ?? SwiftProtobuf.Internal.emptyData}
set {_baseKeySignature = newValue}
}
/// Returns true if `baseKeySignature` has been explicitly set.
var hasBaseKeySignature: Bool {return self._baseKeySignature != nil}
/// Clears the value of `baseKeySignature`. Subsequent reads from it will return its default value.
mutating func clearBaseKeySignature() {self._baseKeySignature = nil}
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
fileprivate var _id: UInt32? = nil
fileprivate var _baseKey: Data? = nil
fileprivate var _ratchetKey: Data? = nil
fileprivate var _identityKey: Data? = nil
fileprivate var _baseKeySignature: Data? = nil
}
struct SPKProtos_TSProtoSenderKeyMessage {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var id: UInt32 {
get {return _id ?? 0}
set {_id = newValue}
}
/// Returns true if `id` has been explicitly set.
var hasID: Bool {return self._id != nil}
/// Clears the value of `id`. Subsequent reads from it will return its default value.
mutating func clearID() {self._id = nil}
var iteration: UInt32 {
get {return _iteration ?? 0}
set {_iteration = newValue}
}
/// Returns true if `iteration` has been explicitly set.
var hasIteration: Bool {return self._iteration != nil}
/// Clears the value of `iteration`. Subsequent reads from it will return its default value.
mutating func clearIteration() {self._iteration = nil}
var ciphertext: Data {
get {return _ciphertext ?? SwiftProtobuf.Internal.emptyData}
set {_ciphertext = newValue}
}
/// Returns true if `ciphertext` has been explicitly set.
var hasCiphertext: Bool {return self._ciphertext != nil}
/// Clears the value of `ciphertext`. Subsequent reads from it will return its default value.
mutating func clearCiphertext() {self._ciphertext = nil}
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
fileprivate var _id: UInt32? = nil
fileprivate var _iteration: UInt32? = nil
fileprivate var _ciphertext: Data? = nil
}
struct SPKProtos_TSProtoSenderKeyDistributionMessage {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var id: UInt32 {
get {return _id ?? 0}
set {_id = newValue}
}
/// Returns true if `id` has been explicitly set.
var hasID: Bool {return self._id != nil}
/// Clears the value of `id`. Subsequent reads from it will return its default value.
mutating func clearID() {self._id = nil}
var iteration: UInt32 {
get {return _iteration ?? 0}
set {_iteration = newValue}
}
/// Returns true if `iteration` has been explicitly set.
var hasIteration: Bool {return self._iteration != nil}
/// Clears the value of `iteration`. Subsequent reads from it will return its default value.
mutating func clearIteration() {self._iteration = nil}
var chainKey: Data {
get {return _chainKey ?? SwiftProtobuf.Internal.emptyData}
set {_chainKey = newValue}
}
/// Returns true if `chainKey` has been explicitly set.
var hasChainKey: Bool {return self._chainKey != nil}
/// Clears the value of `chainKey`. Subsequent reads from it will return its default value.
mutating func clearChainKey() {self._chainKey = nil}
var signingKey: Data {
get {return _signingKey ?? SwiftProtobuf.Internal.emptyData}
set {_signingKey = newValue}
}
/// Returns true if `signingKey` has been explicitly set.
var hasSigningKey: Bool {return self._signingKey != nil}
/// Clears the value of `signingKey`. Subsequent reads from it will return its default value.
mutating func clearSigningKey() {self._signingKey = nil}
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
fileprivate var _id: UInt32? = nil
fileprivate var _iteration: UInt32? = nil
fileprivate var _chainKey: Data? = nil
fileprivate var _signingKey: Data? = nil
}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "SPKProtos"
extension SPKProtos_TSProtoWhisperMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".TSProtoWhisperMessage"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "ratchetKey"),
2: .same(proto: "counter"),
3: .same(proto: "previousCounter"),
4: .same(proto: "ciphertext"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1: try decoder.decodeSingularBytesField(value: &self._ratchetKey)
case 2: try decoder.decodeSingularUInt32Field(value: &self._counter)
case 3: try decoder.decodeSingularUInt32Field(value: &self._previousCounter)
case 4: try decoder.decodeSingularBytesField(value: &self._ciphertext)
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if let v = self._ratchetKey {
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
}
if let v = self._counter {
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 2)
}
if let v = self._previousCounter {
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 3)
}
if let v = self._ciphertext {
try visitor.visitSingularBytesField(value: v, fieldNumber: 4)
}
try unknownFields.traverse(visitor: &visitor)
}
func _protobuf_generated_isEqualTo(other: SPKProtos_TSProtoWhisperMessage) -> Bool {
if self._ratchetKey != other._ratchetKey {return false}
if self._counter != other._counter {return false}
if self._previousCounter != other._previousCounter {return false}
if self._ciphertext != other._ciphertext {return false}
if unknownFields != other.unknownFields {return false}
return true
}
}
extension SPKProtos_TSProtoPreKeyWhisperMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".TSProtoPreKeyWhisperMessage"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
5: .same(proto: "registrationId"),
1: .same(proto: "preKeyId"),
6: .same(proto: "signedPreKeyId"),
2: .same(proto: "baseKey"),
3: .same(proto: "identityKey"),
4: .same(proto: "message"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1: try decoder.decodeSingularUInt32Field(value: &self._preKeyID)
case 2: try decoder.decodeSingularBytesField(value: &self._baseKey)
case 3: try decoder.decodeSingularBytesField(value: &self._identityKey)
case 4: try decoder.decodeSingularBytesField(value: &self._message)
case 5: try decoder.decodeSingularUInt32Field(value: &self._registrationID)
case 6: try decoder.decodeSingularUInt32Field(value: &self._signedPreKeyID)
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if let v = self._preKeyID {
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 1)
}
if let v = self._baseKey {
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
}
if let v = self._identityKey {
try visitor.visitSingularBytesField(value: v, fieldNumber: 3)
}
if let v = self._message {
try visitor.visitSingularBytesField(value: v, fieldNumber: 4)
}
if let v = self._registrationID {
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 5)
}
if let v = self._signedPreKeyID {
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 6)
}
try unknownFields.traverse(visitor: &visitor)
}
func _protobuf_generated_isEqualTo(other: SPKProtos_TSProtoPreKeyWhisperMessage) -> Bool {
if self._registrationID != other._registrationID {return false}
if self._preKeyID != other._preKeyID {return false}
if self._signedPreKeyID != other._signedPreKeyID {return false}
if self._baseKey != other._baseKey {return false}
if self._identityKey != other._identityKey {return false}
if self._message != other._message {return false}
if unknownFields != other.unknownFields {return false}
return true
}
}
extension SPKProtos_TSProtoKeyExchangeMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".TSProtoKeyExchangeMessage"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "id"),
2: .same(proto: "baseKey"),
3: .same(proto: "ratchetKey"),
4: .same(proto: "identityKey"),
5: .same(proto: "baseKeySignature"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1: try decoder.decodeSingularUInt32Field(value: &self._id)
case 2: try decoder.decodeSingularBytesField(value: &self._baseKey)
case 3: try decoder.decodeSingularBytesField(value: &self._ratchetKey)
case 4: try decoder.decodeSingularBytesField(value: &self._identityKey)
case 5: try decoder.decodeSingularBytesField(value: &self._baseKeySignature)
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if let v = self._id {
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 1)
}
if let v = self._baseKey {
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
}
if let v = self._ratchetKey {
try visitor.visitSingularBytesField(value: v, fieldNumber: 3)
}
if let v = self._identityKey {
try visitor.visitSingularBytesField(value: v, fieldNumber: 4)
}
if let v = self._baseKeySignature {
try visitor.visitSingularBytesField(value: v, fieldNumber: 5)
}
try unknownFields.traverse(visitor: &visitor)
}
func _protobuf_generated_isEqualTo(other: SPKProtos_TSProtoKeyExchangeMessage) -> Bool {
if self._id != other._id {return false}
if self._baseKey != other._baseKey {return false}
if self._ratchetKey != other._ratchetKey {return false}
if self._identityKey != other._identityKey {return false}
if self._baseKeySignature != other._baseKeySignature {return false}
if unknownFields != other.unknownFields {return false}
return true
}
}
extension SPKProtos_TSProtoSenderKeyMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".TSProtoSenderKeyMessage"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "id"),
2: .same(proto: "iteration"),
3: .same(proto: "ciphertext"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1: try decoder.decodeSingularUInt32Field(value: &self._id)
case 2: try decoder.decodeSingularUInt32Field(value: &self._iteration)
case 3: try decoder.decodeSingularBytesField(value: &self._ciphertext)
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if let v = self._id {
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 1)
}
if let v = self._iteration {
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 2)
}
if let v = self._ciphertext {
try visitor.visitSingularBytesField(value: v, fieldNumber: 3)
}
try unknownFields.traverse(visitor: &visitor)
}
func _protobuf_generated_isEqualTo(other: SPKProtos_TSProtoSenderKeyMessage) -> Bool {
if self._id != other._id {return false}
if self._iteration != other._iteration {return false}
if self._ciphertext != other._ciphertext {return false}
if unknownFields != other.unknownFields {return false}
return true
}
}
extension SPKProtos_TSProtoSenderKeyDistributionMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".TSProtoSenderKeyDistributionMessage"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "id"),
2: .same(proto: "iteration"),
3: .same(proto: "chainKey"),
4: .same(proto: "signingKey"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1: try decoder.decodeSingularUInt32Field(value: &self._id)
case 2: try decoder.decodeSingularUInt32Field(value: &self._iteration)
case 3: try decoder.decodeSingularBytesField(value: &self._chainKey)
case 4: try decoder.decodeSingularBytesField(value: &self._signingKey)
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if let v = self._id {
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 1)
}
if let v = self._iteration {
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 2)
}
if let v = self._chainKey {
try visitor.visitSingularBytesField(value: v, fieldNumber: 3)
}
if let v = self._signingKey {
try visitor.visitSingularBytesField(value: v, fieldNumber: 4)
}
try unknownFields.traverse(visitor: &visitor)
}
func _protobuf_generated_isEqualTo(other: SPKProtos_TSProtoSenderKeyDistributionMessage) -> Bool {
if self._id != other._id {return false}
if self._iteration != other._iteration {return false}
if self._chainKey != other._chainKey {return false}
if self._signingKey != other._signingKey {return false}
if unknownFields != other.unknownFields {return false}
return true
}
}

View File

@ -13,13 +13,7 @@
@synthesize ourIdentityKeyPair=_ourIdentityKeyPair, theirIdentityKey=_theirIdentityKey;
- (instancetype)initWithIdentityKey:(ECKeyPair*)myIdentityKey theirIdentityKey:(NSData*)theirIdentityKey ourBaseKey:(ECKeyPair*)ourBaseKey theirSignedPreKey:(NSData*)theirSignedPreKey theirOneTimePreKey:(NSData*)theirOneTimePreKey theirRatchetKey:(NSData*)theirRatchetKey{
OWSAssert(myIdentityKey);
OWSAssert(theirIdentityKey);
OWSAssert(ourBaseKey);
OWSAssert(theirSignedPreKey);
OWSAssert(theirRatchetKey);
self = [super init];
if (self) {

View File

@ -13,13 +13,6 @@
@synthesize theirIdentityKey=_theirIdentityKey, ourIdentityKeyPair=_ourIdentityKeyPair;
- (instancetype)initWithMyIdentityKeyPair:(ECKeyPair*)ourIdentityKeyPair theirIdentityKey:(NSData*)theirIdentityKey ourSignedPrekey:(ECKeyPair*)ourSignedPrekey ourRatchetKey:(ECKeyPair*)ourRatchetKey ourOneTimePrekey:(ECKeyPair*)ourOneTimeKeyPair theirBaseKey:(NSData*)theirBaseKey{
OWSAssert(ourIdentityKeyPair);
OWSAssert(theirIdentityKey);
OWSAssert(ourSignedPrekey);
OWSAssert(ourRatchetKey);
OWSAssert(theirBaseKey);
self = [super init];
if (self) {

View File

@ -1,25 +1,26 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// ChainKey.h
// AxolotlKit
//
// Created by Frederic Jacobs on 26/08/14.
// Copyright (c) 2014 Frederic Jacobs. All rights reserved.
//
#import "Chain.h"
#import "MessageKeys.h"
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface ChainKey : NSObject <NSSecureCoding>
@property (nonatomic, readonly) int index;
@property (nonatomic, readonly) NSData *key;
-(instancetype)initWithData:(NSData*)chainKey index:(int)index;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithData:(NSData *)chainKey index:(int)index NS_DESIGNATED_INITIALIZER;
-(instancetype)nextChainKey;
- (instancetype)nextChainKey;
-(MessageKeys*)messageKeys;
- (MessageKeys *)throws_messageKeys NS_SWIFT_UNAVAILABLE("throws objc exceptions");
-(NSData*)baseMaterial:(NSData*)seed;
@property (readonly) int index;
@property (readonly) NSData *key;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,95 +1,74 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "ChainKey.h"
#import "TSDerivedSecrets.h"
#import <CommonCrypto/CommonCrypto.h>
#import <Curve25519Kit/Curve25519.h>
NS_ASSUME_NONNULL_BEGIN
#import <CommonCrypto/CommonCrypto.h>
@implementation ChainKey
static NSString *const kCoderKey = @"kCoderKey";
static NSString *const kCoderIndex = @"kCoderIndex";
static NSString* const kCoderKey = @"kCoderKey";
static NSString* const kCoderIndex = @"kCoderIndex";
#define kTSKeySeedLength 1
static uint8_t kMessageKeySeed[kTSKeySeedLength] = { 01 };
static uint8_t kChainKeySeed[kTSKeySeedLength] = { 02 };
static uint8_t kMessageKeySeed[kTSKeySeedLength] = {01};
static uint8_t kChainKeySeed[kTSKeySeedLength] = {02};
+ (BOOL)supportsSecureCoding
{
+ (BOOL)supportsSecureCoding{
return YES;
}
- (nullable id)initWithCoder:(NSCoder *)aDecoder
{
NSData *key = [aDecoder decodeObjectOfClass:[NSData class] forKey:kCoderKey];
int index = [aDecoder decodeIntForKey:kCoderIndex];
return [self initWithData:key index:index];
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_key forKey:kCoderKey];
[aCoder encodeInt:_index forKey:kCoderIndex];
}
- (instancetype)initWithData:(NSData *)chainKey index:(int)index
{
OWSAssert(chainKey.length == 32);
OWSAssert(index >= 0);
self = [super init];
- (id)initWithCoder:(NSCoder *)aDecoder{
self = [super init];
if (self) {
_key = chainKey;
_index = index;
_key = [aDecoder decodeObjectOfClass:[NSData class] forKey:kCoderKey];
_index = [aDecoder decodeIntForKey:kCoderIndex];
}
return self;
}
- (instancetype)nextChainKey
{
NSData *nextCK = [self baseMaterial:[NSData dataWithBytes:kChainKeySeed length:kTSKeySeedLength]];
OWSAssert(nextCK.length == 32);
int nextIndex;
ows_add_overflow(self.index, 1, &nextIndex);
return [[ChainKey alloc] initWithData:nextCK index:nextIndex];
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:_key forKey:kCoderKey];
[aCoder encodeInt:_index forKey:kCoderIndex];
}
- (MessageKeys *)throws_messageKeys
{
-(instancetype)initWithData:(NSData *)chainKey index:(int)index{
SPKAssert(chainKey.length == ECCKeyLength);
self = [super init];
if (self) {
_key = chainKey;
_index = index;
}
return self;
}
- (instancetype) nextChainKey{
NSData* nextCK = [self baseMaterial:[NSData dataWithBytes:kChainKeySeed length:kTSKeySeedLength]];
return [[ChainKey alloc] initWithData:nextCK index:self.index+1];
}
- (MessageKeys*)messageKeys{
NSData *inputKeyMaterial = [self baseMaterial:[NSData dataWithBytes:kMessageKeySeed length:kTSKeySeedLength]];
TSDerivedSecrets *derivedSecrets = [TSDerivedSecrets throws_derivedMessageKeysWithData:inputKeyMaterial];
return [[MessageKeys alloc] initWithCipherKey:derivedSecrets.cipherKey
macKey:derivedSecrets.macKey
iv:derivedSecrets.iv
index:self.index];
TSDerivedSecrets *derivedSecrets = [TSDerivedSecrets derivedMessageKeysWithData:inputKeyMaterial];
return [[MessageKeys alloc] initWithCipherKey:derivedSecrets.cipherKey macKey:derivedSecrets.macKey iv:derivedSecrets.iv index:self.index];
}
- (NSData *)baseMaterial:(NSData *)seed
{
OWSAssert(self.key);
OWSAssert(self.key.length == 32);
OWSAssert(seed);
OWSAssert(seed.length == kTSKeySeedLength);
NSMutableData *_Nullable bufferData = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
OWSAssert(bufferData);
- (NSData*)baseMaterial:(NSData*)seed{
uint8_t result[CC_SHA256_DIGEST_LENGTH] = {0};
CCHmacContext ctx;
CCHmacInit(&ctx, kCCHmacAlgSHA256, [self.key bytes], [self.key length]);
CCHmacUpdate(&ctx, [seed bytes], [seed length]);
CCHmacFinal(&ctx, bufferData.mutableBytes);
return [bufferData copy];
CCHmacFinal(&ctx, result);
return [NSData dataWithBytes:result length:sizeof(result)];
}
@end
NS_ASSUME_NONNULL_END

View File

@ -37,11 +37,6 @@ static NSString* const kCoderMessageKeysIndex = @"kCoderMessageKeysIndex";
- (instancetype)initWithCipherKey:(NSData*)cipherKey macKey:(NSData*)macKey iv:(NSData *)data index:(int)index{
OWSAssert(cipherKey);
OWSAssert(macKey);
OWSAssert(data);
self = [super init];
if (self) {

View File

@ -1,12 +1,15 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// RKCK.h
// AxolotlKit
//
// Created by Frederic Jacobs on 1/15/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SessionState.h"
#import "Chain.h"
#import "RootKey.h"
#import "SessionState.h"
#import <Foundation/Foundation.h>
@class ECKeyPair;
@interface RKCK : NSObject
@ -16,4 +19,4 @@
-(instancetype) initWithRK:(RootKey*)rootKey CK:(ChainKey*)chainKey;
@end
@end

View File

@ -9,9 +9,6 @@
@implementation RKCK
- (instancetype)initWithRK:(RootKey*)rootKey CK:(ChainKey*)chainKey{
OWSAssert(rootKey);
OWSAssert(chainKey);
self = [super init];
self.rootKey = rootKey;
self.chainKey = chainKey;

View File

@ -1,41 +1,27 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// RatchetingSession.h
// AxolotlKit
//
// Created by Frederic Jacobs on 26/07/14.
// Copyright (c) 2014 Frederic Jacobs. All rights reserved.
//
#import <Foundation/Foundation.h>
@class SessionState;
@class AliceAxolotlParameters;
@class BobAxolotlParameters;
@class ECKeyPair;
@class SessionState;
@interface RatchetingSession : NSObject
+ (void)throws_initializeSession:(SessionState *)session
sessionVersion:(int)sessionVersion
AliceParameters:(AliceAxolotlParameters *)parameters NS_SWIFT_UNAVAILABLE("throws objc exceptions");
+ (void)initializeSession:(SessionState*)session sessionVersion:(int)sessionVersion AliceParameters:(AliceAxolotlParameters*)parameters;
+ (BOOL)initializeSession:(SessionState *)session
sessionVersion:(int)sessionVersion
aliceParameters:(AliceAxolotlParameters *)aliceParameters
error:(NSError **)outError;
+ (void)throws_initializeSession:(SessionState *)session
sessionVersion:(int)sessionVersion
BobParameters:(BobAxolotlParameters *)parameters NS_SWIFT_UNAVAILABLE("throws objc exceptions");
+ (BOOL)initializeSession:(SessionState *)session
sessionVersion:(int)sessionVersion
bobParameters:(BobAxolotlParameters *)bobParameters
error:(NSError **)outError;
+ (void)initializeSession:(SessionState*)session sessionVersion:(int)sessionVersion BobParameters:(BobAxolotlParameters*)parameters;
/**
* For testing purposes
*/
+ (void)throws_initializeSession:(SessionState *)session
sessionVersion:(int)sessionVersion
AliceParameters:(AliceAxolotlParameters *)parameters
senderRatchet:(ECKeyPair *)ratchet NS_SWIFT_UNAVAILABLE("throws objc exceptions");
+ (void)initializeSession:(SessionState*)session sessionVersion:(int)sessionVersion AliceParameters:(AliceAxolotlParameters*)parameters senderRatchet:(ECKeyPair*)ratchet;
@end

View File

@ -1,40 +1,36 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "RatchetingSession.h"
#import "AliceAxolotlParameters.h"
#import "BobAxolotlParameters.h"
#import "ChainKey.h"
#import "RootKey.h"
#import "SessionState.h"
#import <Curve25519Kit/Curve25519.h>
#import <HKDFKit/HKDFKit.h>
#import <SignalCoreKit/SCKExceptionWrapper.h>
#import <Curve25519Kit/Curve25519.h>
#import "ChainKey.h"
@interface DHEResult : NSObject
@property (nonatomic, readonly) RootKey *rootKey;
@property (nonatomic, readonly) NSData *chainKey;
- (instancetype)init_throws_withMasterKey:(NSData *)data NS_SWIFT_UNAVAILABLE("throws objc exceptions");
- (instancetype)initWithMasterKey:(NSData*)data;
@end
@implementation DHEResult
- (instancetype)init_throws_withMasterKey:(NSData *)data
{
// DHE Result is expected to be the result of 3 or 4 DHEs outputting 32 bytes each,
// plus the 32 discontinuity bytes added to make V3 incompatible with V2
OWSAssert([data length] == 32 * 4 || [data length] == 32 * 5);
- (instancetype)initWithMasterKey:(NSData*)data{
NSAssert([data length] != 32*4 || [data length] != 32*3, @"DHE Result is expected to be the result of 3 or 4 DHEs outputting 32 bytes each");
self = [super init];
const char *HKDFDefaultSalt[4] = {0};
NSData *salt = [NSData dataWithBytes:HKDFDefaultSalt length:sizeof(HKDFDefaultSalt)];
NSData *info = [@"WhisperText" dataUsingEncoding:NSUTF8StringEncoding];
NSData *derivedMaterial = [HKDFKit throws_deriveKey:data info:info salt:salt outputSize:64];
OWSAssert(derivedMaterial.length == 64);
NSData *derivedMaterial = [HKDFKit deriveKey:data info:info salt:salt outputSize:64];
_rootKey = [[RootKey alloc] initWithData:[derivedMaterial subdataWithRange:NSMakeRange(0, 32)]];
_chainKey = [derivedMaterial subdataWithRange:NSMakeRange(32, 32)];
@ -46,92 +42,37 @@
@implementation RatchetingSession
+ (void)throws_initializeSession:(SessionState *)session
sessionVersion:(int)sessionVersion
AliceParameters:(AliceAxolotlParameters *)parameters
{
OWSAssert(session);
OWSAssert(parameters);
+ (void)initializeSession:(SessionState*)session sessionVersion:(int)sessionVersion AliceParameters:(AliceAxolotlParameters*)parameters{
ECKeyPair *sendingRatchetKey = [Curve25519 generateKeyPair];
OWSAssert(sendingRatchetKey);
[self throws_initializeSession:session
sessionVersion:sessionVersion
AliceParameters:parameters
senderRatchet:sendingRatchetKey];
[self initializeSession:session sessionVersion:sessionVersion AliceParameters:parameters senderRatchet:sendingRatchetKey];
}
+ (BOOL)initializeSession:(SessionState *)session
sessionVersion:(int)sessionVersion
bobParameters:(BobAxolotlParameters *)bobParameters
error:(NSError **)outError
{
return [SCKExceptionWrapper
tryBlock:^{
[self throws_initializeSession:session sessionVersion:sessionVersion BobParameters:bobParameters];
}
error:outError];
}
+ (void)throws_initializeSession:(SessionState *)session
sessionVersion:(int)sessionVersion
BobParameters:(BobAxolotlParameters *)parameters
{
OWSAssert(session);
OWSAssert(parameters);
+ (void)initializeSession:(SessionState*)session sessionVersion:(int)sessionVersion BobParameters:(BobAxolotlParameters*)parameters{
[session setVersion:sessionVersion];
[session setRemoteIdentityKey:parameters.theirIdentityKey];
[session setLocalIdentityKey:parameters.ourIdentityKeyPair.publicKey];
DHEResult *result = [self throws_DHEKeyAgreement:parameters];
OWSAssert(result);
DHEResult *result = [self DHEKeyAgreement:parameters];
[session setSenderChain:parameters.ourRatchetKey chainKey:[[ChainKey alloc]initWithData:result.chainKey index:0]];
[session setRootKey:result.rootKey];
}
+ (BOOL)initializeSession:(SessionState *)session
sessionVersion:(int)sessionVersion
aliceParameters:(AliceAxolotlParameters *)aliceParameters
error:(NSError **)outError
{
return [SCKExceptionWrapper
tryBlock:^{
[self throws_initializeSession:session sessionVersion:sessionVersion AliceParameters:aliceParameters];
}
error:outError];
}
+ (void)throws_initializeSession:(SessionState *)session
sessionVersion:(int)sessionVersion
AliceParameters:(AliceAxolotlParameters *)parameters
senderRatchet:(ECKeyPair *)sendingRatchet
{
OWSAssert(session);
OWSAssert(parameters);
OWSAssert(sendingRatchet);
+ (void)initializeSession:(SessionState*)session sessionVersion:(int)sessionVersion AliceParameters:(AliceAxolotlParameters*)parameters senderRatchet:(ECKeyPair*)sendingRatchet{
[session setVersion:sessionVersion];
[session setRemoteIdentityKey:parameters.theirIdentityKey];
[session setLocalIdentityKey:parameters.ourIdentityKeyPair.publicKey];
DHEResult *result = [self throws_DHEKeyAgreement:parameters];
OWSAssert(result);
RKCK *sendingChain =
[result.rootKey throws_createChainWithTheirEphemeral:parameters.theirRatchetKey ourEphemeral:sendingRatchet];
OWSAssert(sendingChain);
DHEResult *result = [self DHEKeyAgreement:parameters];
RKCK *sendingChain = [result.rootKey createChainWithTheirEphemeral:parameters.theirRatchetKey ourEphemeral:sendingRatchet];
[session addReceiverChain:parameters.theirRatchetKey chainKey:[[ChainKey alloc]initWithData:result.chainKey index:0]];
[session setSenderChain:sendingRatchet chainKey:sendingChain.chainKey];
[session setRootKey:sendingChain.rootKey];
}
+ (DHEResult *)throws_DHEKeyAgreement:(id<AxolotlParameters>)parameters
{
OWSAssert(parameters);
+ (DHEResult*)DHEKeyAgreement:(id<AxolotlParameters>)parameters{
NSMutableData *masterKey = [NSMutableData data];
[masterKey appendData:[self discontinuityBytes]];
@ -139,32 +80,24 @@
if ([parameters isKindOfClass:[AliceAxolotlParameters class]]) {
AliceAxolotlParameters *params = (AliceAxolotlParameters*)parameters;
[masterKey appendData:[Curve25519 throws_generateSharedSecretFromPublicKey:params.theirSignedPreKey
andKeyPair:params.ourIdentityKeyPair]];
[masterKey appendData:[Curve25519 throws_generateSharedSecretFromPublicKey:params.theirIdentityKey
andKeyPair:params.ourBaseKey]];
[masterKey appendData:[Curve25519 throws_generateSharedSecretFromPublicKey:params.theirSignedPreKey
andKeyPair:params.ourBaseKey]];
[masterKey appendData:[Curve25519 generateSharedSecretFromPublicKey:params.theirSignedPreKey andKeyPair:params.ourIdentityKeyPair]];
[masterKey appendData:[Curve25519 generateSharedSecretFromPublicKey:params.theirIdentityKey andKeyPair:params.ourBaseKey]];
[masterKey appendData:[Curve25519 generateSharedSecretFromPublicKey:params.theirSignedPreKey andKeyPair:params.ourBaseKey]];
if (params.theirOneTimePrekey) {
[masterKey appendData:[Curve25519 throws_generateSharedSecretFromPublicKey:params.theirOneTimePrekey
andKeyPair:params.ourBaseKey]];
[masterKey appendData:[Curve25519 generateSharedSecretFromPublicKey:params.theirOneTimePrekey andKeyPair:params.ourBaseKey]];
}
} else if ([parameters isKindOfClass:[BobAxolotlParameters class]]){
BobAxolotlParameters *params = (BobAxolotlParameters*)parameters;
[masterKey appendData:[Curve25519 throws_generateSharedSecretFromPublicKey:params.theirIdentityKey
andKeyPair:params.ourSignedPrekey]];
[masterKey appendData:[Curve25519 throws_generateSharedSecretFromPublicKey:params.theirBaseKey
andKeyPair:params.ourIdentityKeyPair]];
[masterKey appendData:[Curve25519 throws_generateSharedSecretFromPublicKey:params.theirBaseKey
andKeyPair:params.ourSignedPrekey]];
[masterKey appendData:[Curve25519 generateSharedSecretFromPublicKey:params.theirIdentityKey andKeyPair:params.ourSignedPrekey]];
[masterKey appendData:[Curve25519 generateSharedSecretFromPublicKey:params.theirBaseKey andKeyPair:params.ourIdentityKeyPair]];
[masterKey appendData:[Curve25519 generateSharedSecretFromPublicKey:params.theirBaseKey andKeyPair:params.ourSignedPrekey]];
if (params.ourOneTimePrekey) {
[masterKey appendData:[Curve25519 throws_generateSharedSecretFromPublicKey:params.theirBaseKey
andKeyPair:params.ourOneTimePrekey]];
[masterKey appendData:[Curve25519 generateSharedSecretFromPublicKey:params.theirBaseKey andKeyPair:params.ourOneTimePrekey]];
}
}
return [[DHEResult alloc] init_throws_withMasterKey:masterKey];
return [[DHEResult alloc] initWithMasterKey:masterKey];
}
/**

View File

@ -41,9 +41,6 @@ static NSString* const kCoderMessageKeys = @"kCoderMessageKeys";
}
- (instancetype)initWithChainKey:(ChainKey *)chainKey senderRatchetKey:(NSData *)senderRatchet{
OWSAssert(chainKey);
OWSAssert(senderRatchet);
self = [super init];
self.chainKey = chainKey;

View File

@ -1,17 +1,19 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// RootKey.h
// AxolotlKit
//
// Created by Frederic Jacobs on 22/07/14.
// Copyright (c) 2014 Frederic Jacobs. All rights reserved.
//
#import <Foundation/Foundation.h>
@class ECKeyPair;
@class RKCK;
@class ECKeyPair;
@interface RootKey : NSObject <NSSecureCoding>
- (instancetype)initWithData:(NSData *)data;
- (RKCK *)throws_createChainWithTheirEphemeral:(NSData *)theirEphemeral
ourEphemeral:(ECKeyPair *)ourEphemeral NS_SWIFT_UNAVAILABLE("throws objc exceptions");
- (RKCK*)createChainWithTheirEphemeral:(NSData*)theirEphemeral ourEphemeral:(ECKeyPair*)ourEphemeral;
@property (nonatomic, readonly) NSData *keyData;

View File

@ -1,12 +1,12 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "RootKey.h"
#import "ChainKey.h"
#import "RKCK.h"
#import "TSDerivedSecrets.h"
#import "RKCK.h"
#import <Curve25519Kit/Curve25519.h>
#import "ChainKey.h"
static NSString* const kCoderData = @"kCoderData";
@ -33,7 +33,7 @@ static NSString* const kCoderData = @"kCoderData";
- (instancetype)initWithData:(NSData *)data{
self = [super init];
OWSAssert(data.length == 32);
SPKAssert(data.length == ECCKeyLength);
if (self) {
_keyData = data;
@ -42,17 +42,11 @@ static NSString* const kCoderData = @"kCoderData";
return self;
}
- (RKCK *)throws_createChainWithTheirEphemeral:(NSData *)theirEphemeral ourEphemeral:(ECKeyPair *)ourEphemeral
{
OWSAssert(theirEphemeral);
OWSAssert(ourEphemeral);
- (RKCK*)createChainWithTheirEphemeral:(NSData*)theirEphemeral ourEphemeral:(ECKeyPair*)ourEphemeral{
NSData *sharedSecret = [Curve25519 generateSharedSecretFromPublicKey:theirEphemeral andKeyPair:ourEphemeral];
SPKAssert(sharedSecret.length == ECCKeyLength);
NSData *sharedSecret = [Curve25519 throws_generateSharedSecretFromPublicKey:theirEphemeral andKeyPair:ourEphemeral];
OWSAssert(sharedSecret.length == 32);
TSDerivedSecrets *secrets =
[TSDerivedSecrets throws_derivedRatchetedSecretsWithSharedSecret:sharedSecret rootKey:_keyData];
OWSAssert(secrets);
TSDerivedSecrets *secrets = [TSDerivedSecrets derivedRatchetedSecretsWithSharedSecret:sharedSecret rootKey:_keyData];
RKCK *newRKCK = [[RKCK alloc] initWithRK:[[RootKey alloc] initWithData:secrets.cipherKey]
CK:[[ChainKey alloc] initWithData:secrets.macKey index:0]];

View File

@ -35,8 +35,8 @@ static NSString* const kCoderSenderRatchet = @"kCoderSenderRatchet";
- (instancetype)initWithChainKey:(ChainKey *)chainKey senderRatchetKeyPair:(ECKeyPair *)keyPair{
self = [super init];
OWSAssert(chainKey.key.length == 32);
OWSAssert(keyPair);
SPKAssert(chainKey.key.length == ECCKeyLength);
SPKAssert(keyPair);
if (self) {
_chainKey = chainKey;

View File

@ -1,17 +1,18 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// TSDerivedSecrets.h
// AxolotlKit
//
// Created by Frederic Jacobs on 29/03/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface TSDerivedSecrets : NSData
+ (instancetype)throws_derivedInitialSecretsWithMasterKey:(NSData *)masterKey
NS_SWIFT_UNAVAILABLE("throws objc exceptions");
+ (instancetype)throws_derivedRatchetedSecretsWithSharedSecret:(NSData *)masterKey
rootKey:(NSData *)rootKey
NS_SWIFT_UNAVAILABLE("throws objc exceptions");
+ (instancetype)throws_derivedMessageKeysWithData:(NSData *)data NS_SWIFT_UNAVAILABLE("throws objc exceptions");
+ (instancetype)derivedInitialSecretsWithMasterKey:(NSData*)masterKey;
+ (instancetype)derivedRatchetedSecretsWithSharedSecret:(NSData*)masterKey rootKey:(NSData*)rootKey;
+ (instancetype)derivedMessageKeysWithData:(NSData*)data;
@property NSData *cipherKey;
@property NSData *macKey;

View File

@ -1,20 +1,17 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "TSDerivedSecrets.h"
#import "HKDFKit.h"
#import <Curve25519Kit/Curve25519.h>
#import <HKDFKit/HKDFKit.h>
@implementation TSDerivedSecrets
+ (instancetype)throws_derivedSecretsWithSeed:(NSData *)masterKey salt:(NSData *)salt info:(NSData *)info
{
OWSAssert(masterKey.length == 32);
OWSAssert(info);
+ (instancetype)derivedSecretsWithSeed:(NSData*)masterKey salt:(NSData*)salt info:(NSData*)info{
TSDerivedSecrets *secrets = [[TSDerivedSecrets alloc] init];
OWSAssert(secrets);
SPKAssert(masterKey.length == ECCKeyLength);
if (!salt) {
const char *HKDFDefaultSalt[4] = {0};
@ -22,7 +19,7 @@
}
@try {
NSData *derivedMaterial = [HKDFKit throws_deriveKey:masterKey info:info salt:salt outputSize:96];
NSData *derivedMaterial = [HKDFKit deriveKey:masterKey info:info salt:salt outputSize:96];
secrets.cipherKey = [derivedMaterial subdataWithRange:NSMakeRange(0, 32)];
secrets.macKey = [derivedMaterial subdataWithRange:NSMakeRange(32, 32)];
secrets.iv = [derivedMaterial subdataWithRange:NSMakeRange(64, 16)];
@ -31,36 +28,25 @@
@throw NSInvalidArgumentException;
}
OWSAssert(secrets.cipherKey.length == 32);
OWSAssert(secrets.macKey.length == 32);
OWSAssert(secrets.iv.length == 16);
SPKAssert(secrets.cipherKey.length == ECCKeyLength);
SPKAssert(secrets.macKey.length == ECCKeyLength);
return secrets;
}
+ (instancetype)throws_derivedInitialSecretsWithMasterKey:(NSData *)masterKey
{
OWSAssert(masterKey);
+ (instancetype)derivedInitialSecretsWithMasterKey:(NSData*)masterKey{
NSData *info = [@"WhisperText" dataUsingEncoding:NSUTF8StringEncoding];
return [self throws_derivedSecretsWithSeed:masterKey salt:nil info:info];
return [self derivedSecretsWithSeed:masterKey salt:nil info:info];
}
+ (instancetype)throws_derivedRatchetedSecretsWithSharedSecret:(NSData *)masterKey rootKey:(NSData *)rootKey
{
OWSAssert(masterKey);
OWSAssert(rootKey);
+ (instancetype)derivedRatchetedSecretsWithSharedSecret:(NSData*)masterKey rootKey:(NSData*)rootKey{
NSData *info = [@"WhisperRatchet" dataUsingEncoding:NSUTF8StringEncoding];
return [self throws_derivedSecretsWithSeed:masterKey salt:rootKey info:info];
return [self derivedSecretsWithSeed:masterKey salt:rootKey info:info];
}
+ (instancetype)throws_derivedMessageKeysWithData:(NSData *)data
{
OWSAssert(data);
+ (instancetype)derivedMessageKeysWithData:(NSData*)data{
NSData *info = [@"WhisperMessageKeys" dataUsingEncoding:NSUTF8StringEncoding];
return [self throws_derivedSecretsWithSeed:data salt:nil info:info];
return [self derivedSecretsWithSeed:data salt:nil info:info];
}
@end

View File

@ -1,9 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <AxolotlKit/AxolotlStore.h>
#import <AxolotlKit/SPKMockProtocolStore.h>
#import <Curve25519Kit/Curve25519.h>
#import <SignalCoreKit/NSObject+OWS.h>
#import <SignalCoreKit/OWSAsserts.h>

View File

@ -0,0 +1,76 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
NS_ASSUME_NONNULL_BEGIN
#ifndef SPKAssert
#ifdef DEBUG
#define USE_SPK_ASSERTS
#define SPK_CONVERT_TO_STRING(X) #X
#define SPK_CONVERT_EXPR_TO_STRING(X) SPK_CONVERT_TO_STRING(X)
// SPKAssert() and SPKFail() should be used in Obj-C methods.
// SPKCAssert() and SPKCFail() should be used in free functions.
#define SPKAssert(X) \
if (!(X)) { \
DDLogError(@"%s Assertion failed: %s", __PRETTY_FUNCTION__, SPK_CONVERT_EXPR_TO_STRING(X)); \
[DDLog flushLog]; \
NSAssert(0, @"Assertion failed: %s", SPK_CONVERT_EXPR_TO_STRING(X)); \
}
#define SPKCAssert(X) \
if (!(X)) { \
DDLogError(@"%s Assertion failed: %s", __PRETTY_FUNCTION__, SPK_CONVERT_EXPR_TO_STRING(X)); \
[DDLog flushLog]; \
NSCAssert(0, @"Assertion failed: %s", SPK_CONVERT_EXPR_TO_STRING(X)); \
}
#define SPKFail(message, ...) \
{ \
NSString *formattedMessage = [NSString stringWithFormat:message, ##__VA_ARGS__]; \
DDLogError(@"%s %@", __PRETTY_FUNCTION__, formattedMessage); \
[DDLog flushLog]; \
NSAssert(0, formattedMessage); \
}
#define SPKCFail(message, ...) \
{ \
NSString *formattedMessage = [NSString stringWithFormat:message, ##__VA_ARGS__]; \
DDLogError(@"%s %@", __PRETTY_FUNCTION__, formattedMessage); \
[DDLog flushLog]; \
NSCAssert(0, formattedMessage); \
}
#define SPKFailNoFormat(message) \
{ \
DDLogError(@"%s %@", __PRETTY_FUNCTION__, message); \
[DDLog flushLog]; \
NSAssert(0, message); \
}
#define SPKCFailNoFormat(message) \
{ \
DDLogError(@"%s %@", __PRETTY_FUNCTION__, message); \
[DDLog flushLog]; \
NSCAssert(0, message); \
}
#else
#define SPKAssert(X)
#define SPKCAssert(X)
#define SPKFail(message, ...)
#define SPKCFail(message, ...)
#define SPKFailNoFormat(X)
#define SPKCFailNoFormat(X)
#endif
#endif
NS_ASSUME_NONNULL_END

View File

@ -1,12 +1,11 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "AxolotlStore.h"
#import "IdentityKeyStore.h"
#import "PreKeyStore.h"
#import "PreKeyWhisperMessage.h"
#import "SPKProtocolContext.h"
#import "SessionState.h"
#import "SessionStore.h"
#import "SignedPreKeyStore.h"
@ -24,23 +23,12 @@ NS_ASSUME_NONNULL_BEGIN
// protocolContext is an optional parameter that can be used to ensure that all
// identity and session store writes are coordinated and/or occur within a single
// transaction.
- (id<CipherMessage>)throws_encryptMessage:(NSData *)paddedMessage
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext NS_SWIFT_UNAVAILABLE("throws objc exceptions");
- (nullable id<CipherMessage>)encryptMessage:(NSData *)paddedMessage
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
error:(NSError **)outError;
- (id<CipherMessage>)encryptMessage:(NSData *)paddedMessage protocolContext:(nullable id)protocolContext;
- (NSData *)throws_decrypt:(id<CipherMessage>)whisperMessage
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext NS_SWIFT_UNAVAILABLE("throws objc exceptions");
- (nullable NSData *)decrypt:(id<CipherMessage>)whisperMessage
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
error:(NSError **)outError;
- (NSData *)decrypt:(id<CipherMessage>)whisperMessage protocolContext:(nullable id)protocolContext;
- (int)throws_remoteRegistrationId:(nullable id<SPKProtocolReadContext>)protocolContext
NS_SWIFT_UNAVAILABLE("throws objc exceptions");
- (int)throws_sessionVersion:(nullable id<SPKProtocolReadContext>)protocolContext
NS_SWIFT_UNAVAILABLE("throws objc exceptions");
- (int)remoteRegistrationId:(nullable id)protocolContext;
- (int)sessionVersion:(nullable id)protocolContext;
@end

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "SessionCipher.h"
@ -19,11 +19,12 @@
#import <Curve25519Kit/Curve25519.h>
#import <Curve25519Kit/Ed25519.h>
#import <HKDFKit/HKDFKit.h>
#import <SignalCoreKit/SCKExceptionWrapper.h>
#import <SignalCoreKit/NSData+OWS.h>
NS_ASSUME_NONNULL_BEGIN
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(major, minor) \
([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){.majorVersion = major, .minorVersion = minor, .patchVersion = 0}])
@interface SessionCipher ()
@property (nonatomic, readonly) NSString *recipientId;
@ -41,8 +42,6 @@ NS_ASSUME_NONNULL_BEGIN
@implementation SessionCipher
- (instancetype)initWithAxolotlStore:(id<AxolotlStore>)sessionStore recipientId:(NSString*)recipientId deviceId:(int)deviceId{
OWSAssert(sessionStore);
OWSAssert(recipientId);
return [self initWithSessionStore:sessionStore
preKeyStore:sessionStore
signedPreKeyStore:sessionStore
@ -57,12 +56,6 @@ NS_ASSUME_NONNULL_BEGIN
identityKeyStore:(id<IdentityKeyStore>)identityKeyStore
recipientId:(NSString*)recipientId
deviceId:(int)deviceId{
OWSAssert(sessionStore);
OWSAssert(preKeyStore);
OWSAssert(signedPreKeyStore);
OWSAssert(identityKeyStore);
OWSAssert(recipientId);
self = [super init];
if (self){
@ -70,7 +63,6 @@ NS_ASSUME_NONNULL_BEGIN
_deviceId = deviceId;
_sessionStore = sessionStore;
_identityKeyStore = identityKeyStore;
_prekeyStore = preKeyStore;
_sessionBuilder = [[SessionBuilder alloc] initWithSessionStore:sessionStore
preKeyStore:preKeyStore
signedPreKeyStore:signedPreKeyStore
@ -82,29 +74,15 @@ NS_ASSUME_NONNULL_BEGIN
return self;
}
- (nullable id<CipherMessage>)encryptMessage:(NSData *)paddedMessage
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
error:(NSError **)outError
- (id<CipherMessage>)encryptMessage:(NSData *)paddedMessage protocolContext:(nullable id)protocolContext
{
__block id<CipherMessage> result;
[SCKExceptionWrapper
tryBlock:^{
result = [self throws_encryptMessage:paddedMessage protocolContext:protocolContext];
}
error:outError];
return result;
}
- (id<CipherMessage>)throws_encryptMessage:(NSData *)paddedMessage protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
{
OWSAssert(paddedMessage);
SPKAssert(paddedMessage);
SessionRecord *sessionRecord =
[self.sessionStore loadSession:self.recipientId deviceId:self.deviceId protocolContext:protocolContext];
SessionState *sessionState = sessionRecord.sessionState;
ChainKey *chainKey = sessionState.senderChainKey;
MessageKeys *messageKeys = [chainKey throws_messageKeys];
MessageKeys *messageKeys = chainKey.messageKeys;
NSData *senderRatchetKey = sessionState.senderRatchetKey;
int previousCounter = sessionState.previousCounter;
int sessionVersion = sessionState.version;
@ -113,7 +91,7 @@ NS_ASSUME_NONNULL_BEGIN
recipientId:self.recipientId
direction:TSMessageDirectionOutgoing
protocolContext:protocolContext]) {
OWSLogWarn(
DDLogWarn(
@"%@ Previously known identity key for while encrypting for recipient: %@", self.tag, self.recipientId);
@throw [NSException exceptionWithName:UntrustedIdentityKeyException
reason:@"There is a previously known identity key."
@ -124,33 +102,31 @@ NS_ASSUME_NONNULL_BEGIN
recipientId:self.recipientId
protocolContext:protocolContext];
NSData *ciphertextBody =
[AES_CBC throws_encryptCBCMode:paddedMessage withKey:messageKeys.cipherKey withIV:messageKeys.iv];
NSData *ciphertextBody = [AES_CBC encryptCBCMode:paddedMessage withKey:messageKeys.cipherKey withIV:messageKeys.iv];
id<CipherMessage> cipherMessage =
[[WhisperMessage alloc] init_throws_withVersion:sessionVersion
macKey:messageKeys.macKey
senderRatchetKey:senderRatchetKey.prependKeyType
counter:chainKey.index
previousCounter:previousCounter
cipherText:ciphertextBody
senderIdentityKey:sessionState.localIdentityKey.prependKeyType
receiverIdentityKey:sessionState.remoteIdentityKey.prependKeyType];
[[WhisperMessage alloc] initWithVersion:sessionVersion
macKey:messageKeys.macKey
senderRatchetKey:senderRatchetKey.prependKeyType
counter:chainKey.index
previousCounter:previousCounter
cipherText:ciphertextBody
senderIdentityKey:sessionState.localIdentityKey.prependKeyType
receiverIdentityKey:sessionState.remoteIdentityKey.prependKeyType];
if ([sessionState hasUnacknowledgedPreKeyMessage]) {
PendingPreKey *items = [sessionState unacknowledgedPreKeyMessageItems];
int localRegistrationId = [sessionState localRegistrationId];
OWSLogInfo(@"Building PreKeyWhisperMessage for: %@.%lu with preKeyId: %d",
self.recipientId, (unsigned long) self.deviceId, items.preKeyId);
DDLogInfo(@"Building PreKeyWhisperMessage for: %@ with preKeyId: %d", self.recipientId, items.preKeyId);
cipherMessage =
[[PreKeyWhisperMessage alloc] init_throws_withWhisperMessage:cipherMessage
registrationId:localRegistrationId
prekeyId:items.preKeyId
signedPrekeyId:items.signedPreKeyId
baseKey:items.baseKey.prependKeyType
identityKey:sessionState.localIdentityKey.prependKeyType];
[[PreKeyWhisperMessage alloc] initWithWhisperMessage:cipherMessage
registrationId:localRegistrationId
prekeyId:items.preKeyId
signedPrekeyId:items.signedPreKeyId
baseKey:items.baseKey.prependKeyType
identityKey:sessionState.localIdentityKey.prependKeyType];
}
[sessionState setSenderChainKey:[chainKey nextChainKey]];
@ -162,57 +138,29 @@ NS_ASSUME_NONNULL_BEGIN
return cipherMessage;
}
- (nullable NSData *)decrypt:(id<CipherMessage>)whisperMessage
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
error:(NSError **)outError
- (NSData *)decrypt:(id<CipherMessage>)whisperMessage protocolContext:(nullable id)protocolContext
{
__block NSData *_Nullable result;
[SCKExceptionWrapper
tryBlock:^{
result = [self throws_decrypt:whisperMessage protocolContext:protocolContext];
}
error:outError];
SPKAssert(whisperMessage);
return result;
}
- (NSData *)throws_decrypt:(id<CipherMessage>)whisperMessage protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
{
OWSAssert(whisperMessage);
switch (whisperMessage.cipherMessageType) {
case CipherMessageType_Whisper:
if (![whisperMessage isKindOfClass:[WhisperMessage class]]) {
OWSFail(@"Unexpected message type: %@", [whisperMessage class]);
return nil;
}
return [self throws_decryptWhisperMessage:(WhisperMessage *)whisperMessage protocolContext:protocolContext];
case CipherMessageType_Prekey:
if (![whisperMessage isKindOfClass:[PreKeyWhisperMessage class]]) {
OWSFail(@"Unexpected message type: %@", [whisperMessage class]);
return nil;
}
return [self throws_decryptPreKeyWhisperMessage:(PreKeyWhisperMessage *)whisperMessage
protocolContext:protocolContext];
default:
OWSFailDebug(@"Unexpected message type: %@", [whisperMessage class]);
break;
if ([whisperMessage isKindOfClass:[PreKeyWhisperMessage class]]) {
return
[self decryptPreKeyWhisperMessage:(PreKeyWhisperMessage *)whisperMessage protocolContext:protocolContext];
} else{
return [self decryptWhisperMessage:whisperMessage protocolContext:protocolContext];
}
}
- (NSData *)throws_decryptPreKeyWhisperMessage:(PreKeyWhisperMessage *)preKeyWhisperMessage
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
- (NSData *)decryptPreKeyWhisperMessage:(PreKeyWhisperMessage *)preKeyWhisperMessage
protocolContext:(nullable id)protocolContext
{
OWSAssert(preKeyWhisperMessage);
SPKAssert(preKeyWhisperMessage);
SessionRecord *sessionRecord =
[self.sessionStore loadSession:self.recipientId deviceId:self.deviceId protocolContext:protocolContext];
int unsignedPreKeyId = [self.sessionBuilder throws_processPrekeyWhisperMessage:preKeyWhisperMessage
withSession:sessionRecord
protocolContext:protocolContext];
NSData *plaintext = [self throws_decryptWithSessionRecord:sessionRecord
whisperMessage:preKeyWhisperMessage.message
protocolContext:protocolContext];
int unsignedPreKeyId = [self.sessionBuilder processPrekeyWhisperMessage:preKeyWhisperMessage withSession:sessionRecord protocolContext:protocolContext];
NSData *plaintext = [self decryptWithSessionRecord:sessionRecord
whisperMessage:preKeyWhisperMessage.message
protocolContext:protocolContext];
[self.sessionStore storeSession:self.recipientId
deviceId:self.deviceId
@ -221,44 +169,35 @@ NS_ASSUME_NONNULL_BEGIN
// If there was an unsigned PreKey
if (unsignedPreKeyId >= 0) {
[self.prekeyStore removePreKey:unsignedPreKeyId
protocolContext:protocolContext];
[self.prekeyStore removePreKey:unsignedPreKeyId];
}
return plaintext;
}
- (NSData *)throws_decryptWhisperMessage:(WhisperMessage *)whisperMessage protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
- (NSData *)decryptWhisperMessage:(WhisperMessage *)whisperMessage protocolContext:(nullable id)protocolContext
{
OWSAssert(whisperMessage);
SPKAssert(whisperMessage);
SessionRecord *sessionRecord =
[self.sessionStore loadSession:self.recipientId deviceId:self.deviceId protocolContext:protocolContext];
NSData *plaintext = [self throws_decryptWithSessionRecord:sessionRecord
whisperMessage:whisperMessage
protocolContext:protocolContext];
NSData *plaintext =
[self decryptWithSessionRecord:sessionRecord whisperMessage:whisperMessage protocolContext:protocolContext];
// Our current session state may not have a remote identity key
// if we decrypted this message using an old session. It's safe
// to ignore this, as the identity key message was already surfaced
// when it originally changed.
if (sessionRecord.sessionState.remoteIdentityKey) {
if (![self.identityKeyStore isTrustedIdentityKey:sessionRecord.sessionState.remoteIdentityKey
recipientId:self.recipientId
direction:TSMessageDirectionIncoming
protocolContext:protocolContext]) {
OWSLogWarn(
@"%@ Previously known identity key for while decrypting from recipient: %@", self.tag, self.recipientId);
@throw [NSException exceptionWithName:UntrustedIdentityKeyException
reason:@"There is a previously known identity key."
userInfo:@{}];
}
[self.identityKeyStore saveRemoteIdentity:sessionRecord.sessionState.remoteIdentityKey
recipientId:self.recipientId
protocolContext:protocolContext];
if (![self.identityKeyStore isTrustedIdentityKey:sessionRecord.sessionState.remoteIdentityKey
recipientId:self.recipientId
direction:TSMessageDirectionIncoming
protocolContext:protocolContext]) {
DDLogWarn(
@"%@ Previously known identity key for while decrypting from recipient: %@", self.tag, self.recipientId);
@throw [NSException exceptionWithName:UntrustedIdentityKeyException
reason:@"There is a previously known identity key."
userInfo:@{}];
}
[self.identityKeyStore saveRemoteIdentity:sessionRecord.sessionState.remoteIdentityKey
recipientId:self.recipientId
protocolContext:protocolContext];
[self.sessionStore storeSession:self.recipientId
deviceId:self.deviceId
session:sessionRecord
@ -267,68 +206,65 @@ NS_ASSUME_NONNULL_BEGIN
return plaintext;
}
- (void)logDecryptionFailureForWhisperMessage:(WhisperMessage *)whisperMessage sessionState:(SessionState *)sessionState
{
OWSFailDebug(@"Failed to decrypt whisper message with ratchet key: %@ and counter: %d. Session loaded using recipientId: %@ and deviceId: %d. Local session has base key: %@ and counter: %d", whisperMessage.senderRatchetKey.hexadecimalString, whisperMessage.counter, self.recipientId, self.deviceId, sessionState.senderRatchetKey.hexadecimalString, sessionState.previousCounter);
}
- (NSData *)throws_decryptWithSessionRecord:(SessionRecord *)sessionRecord
whisperMessage:(WhisperMessage *)whisperMessage
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
- (NSData *)decryptWithSessionRecord:(SessionRecord *)sessionRecord
whisperMessage:(WhisperMessage *)whisperMessage
protocolContext:(nullable id)protocolContext
{
OWSAssert(sessionRecord);
OWSAssert(whisperMessage);
SPKAssert(sessionRecord);
SPKAssert(whisperMessage);
SessionState *sessionState = [sessionRecord sessionState];
NSMutableArray *exceptions = [NSMutableArray array];
@try {
NSData *decryptedData = [self throws_decryptWithSessionState:sessionState
whisperMessage:whisperMessage
protocolContext:protocolContext];
OWSLogDebug(@"%@ successfully decrypted with current session state: %@", self.tag, sessionState);
NSData *decryptedData =
[self decryptWithSessionState:sessionState whisperMessage:whisperMessage protocolContext:protocolContext];
DDLogDebug(@"%@ successfully decrypted with current session state: %@", self.tag, sessionState);
return decryptedData;
}
@catch (NSException *exception) {
if ([exception.name isEqualToString:InvalidMessageException]) {
[exceptions addObject:exception];
} else {
[self logDecryptionFailureForWhisperMessage:whisperMessage sessionState:sessionState];
@throw exception;
}
}
// If we can decrypt the message with an "old" session state, that means the sender is using an "old" session.
// We can continue to receive messages from this sender, but we will send to them using our current session.
__block NSData *_Nullable decryptedData;
// In which case, we promote that session to "active" so as to converge on a single session for sending/receiving.
__block NSUInteger stateToPromoteIdx;
__block NSData *decryptedData;
[[sessionRecord previousSessionStates]
enumerateObjectsUsingBlock:^(SessionState *_Nonnull previousState, NSUInteger idx, BOOL *_Nonnull stop) {
@try {
decryptedData = [self throws_decryptWithSessionState:previousState
whisperMessage:whisperMessage
protocolContext:protocolContext];
OWSLogInfo(@"%@ successfully decrypted with PREVIOUS session state: %@", self.tag, previousState);
OWSAssert(decryptedData != nil);
decryptedData = [self decryptWithSessionState:previousState
whisperMessage:whisperMessage
protocolContext:protocolContext];
DDLogInfo(@"%@ successfully decrypted with PREVIOUS session state: %@", self.tag, previousState);
NSAssert(decryptedData != nil, @"Expected exception or non-nil data");
stateToPromoteIdx = idx;
*stop = YES;
} @catch (NSException *exception) {
if (![exception.name isEqualToString:InvalidMessageException]) {
[self logDecryptionFailureForWhisperMessage:whisperMessage sessionState:sessionState];
}
[exceptions addObject:exception];
}
}];
if (decryptedData) {
SessionState *sessionStateToPromote = [sessionRecord previousSessionStates][stateToPromoteIdx];
NSAssert(sessionStateToPromote != nil, @"the session state we just used is now missing");
DDLogInfo(@"%@ promoting session: %@", self.tag, sessionStateToPromote);
[[sessionRecord previousSessionStates] removeObjectAtIndex:stateToPromoteIdx];
[sessionRecord promoteState:sessionStateToPromote];
return decryptedData;
}
BOOL containsActiveSession =
[self.sessionStore containsSession:self.recipientId deviceId:self.deviceId protocolContext:protocolContext];
OWSLogError(@"%@ No valid session for recipient: %@.%lu containsActiveSession: %@, previousStates: %lu",
DDLogError(@"%@ No valid session for recipient: %@ containsActiveSession: %@, previousStates: %lu",
self.tag,
self.recipientId,
(unsigned long) self.deviceId,
(containsActiveSession ? @"YES" : @"NO"),
(unsigned long)sessionRecord.previousSessionStates.count);
@ -346,12 +282,12 @@ NS_ASSUME_NONNULL_BEGIN
}
}
- (NSData *)throws_decryptWithSessionState:(SessionState *)sessionState
whisperMessage:(WhisperMessage *)whisperMessage
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
- (NSData *)decryptWithSessionState:(SessionState *)sessionState
whisperMessage:(WhisperMessage *)whisperMessage
protocolContext:(nullable id)protocolContext
{
OWSAssert(sessionState);
OWSAssert(whisperMessage);
SPKAssert(sessionState);
SPKAssert(whisperMessage);
if (![sessionState hasSenderChain]) {
@throw [NSException exceptionWithName:InvalidMessageException reason:@"Uninitialized session!" userInfo:nil];
@ -366,65 +302,58 @@ NS_ASSUME_NONNULL_BEGIN
}
int messageVersion = whisperMessage.version;
NSData *theirEphemeral = whisperMessage.senderRatchetKey.throws_removeKeyType;
NSData *theirEphemeral = whisperMessage.senderRatchetKey.removeKeyType;
int counter = whisperMessage.counter;
ChainKey *chainKey = [self throws_getOrCreateChainKeys:sessionState theirEphemeral:theirEphemeral];
OWSAssert(chainKey);
MessageKeys *messageKeys = [self throws_getOrCreateMessageKeysForSession:sessionState
theirEphemeral:theirEphemeral
chainKey:chainKey
counter:counter];
OWSAssert(messageKeys);
ChainKey *chainKey = [self getOrCreateChainKeys:sessionState theirEphemeral:theirEphemeral];
SPKAssert(chainKey);
MessageKeys *messageKeys = [self getOrCreateMessageKeysForSession:sessionState theirEphemeral:theirEphemeral chainKey:chainKey counter:counter];
SPKAssert(messageKeys);
[whisperMessage throws_verifyMacWithVersion:messageVersion
senderIdentityKey:sessionState.remoteIdentityKey
receiverIdentityKey:sessionState.localIdentityKey
macKey:messageKeys.macKey];
[whisperMessage verifyMacWithVersion:messageVersion
senderIdentityKey:sessionState.remoteIdentityKey
receiverIdentityKey:sessionState.localIdentityKey
macKey:messageKeys.macKey];
NSData *plaintext =
[AES_CBC throws_decryptCBCMode:whisperMessage.cipherText withKey:messageKeys.cipherKey withIV:messageKeys.iv];
[AES_CBC decryptCBCMode:whisperMessage.cipherText withKey:messageKeys.cipherKey withIV:messageKeys.iv];
[sessionState clearUnacknowledgedPreKeyMessage];
return plaintext;
}
- (ChainKey *)throws_getOrCreateChainKeys:(SessionState *)sessionState theirEphemeral:(NSData *)theirEphemeral
- (ChainKey *)getOrCreateChainKeys:(SessionState *)sessionState
theirEphemeral:(NSData *)theirEphemeral
{
OWSAssert(sessionState);
OWSGuardWithException(theirEphemeral, InvalidMessageException);
OWSGuardWithException(theirEphemeral.length == 32, InvalidMessageException);
SPKAssert(sessionState);
SPKAssert(theirEphemeral);
SPKAssert(theirEphemeral.length == ECCKeyLength);
@try {
if ([sessionState hasReceiverChain:theirEphemeral]) {
OWSLogInfo(@"%@ %@.%d has existing receiver chain.", self.tag, self.recipientId, self.deviceId);
DDLogInfo(@"%@ %@.%d has existing receiver chain.", self.tag, self.recipientId, self.deviceId);
return [sessionState receiverChainKey:theirEphemeral];
} else{
OWSLogInfo(@"%@ %@.%d creating new chains.", self.tag, self.recipientId, self.deviceId);
DDLogInfo(@"%@ %@.%d creating new chains.", self.tag, self.recipientId, self.deviceId);
RootKey *rootKey = [sessionState rootKey];
OWSAssert(rootKey.keyData.length == 32);
SPKAssert(rootKey.keyData.length == ECCKeyLength);
ECKeyPair *ourEphemeral = [sessionState senderRatchetKeyPair];
OWSAssert(ourEphemeral.publicKey.length == 32);
SPKAssert(ourEphemeral.publicKey.length == ECCKeyLength);
RKCK *receiverChain =
[rootKey throws_createChainWithTheirEphemeral:theirEphemeral ourEphemeral:ourEphemeral];
RKCK *receiverChain = [rootKey createChainWithTheirEphemeral:theirEphemeral ourEphemeral:ourEphemeral];
ECKeyPair *ourNewEphemeral = [Curve25519 generateKeyPair];
OWSAssert(ourNewEphemeral.publicKey.length == 32);
SPKAssert(ourNewEphemeral.publicKey.length == ECCKeyLength);
RKCK *senderChain = [receiverChain.rootKey throws_createChainWithTheirEphemeral:theirEphemeral
ourEphemeral:ourNewEphemeral];
RKCK *senderChain = [receiverChain.rootKey createChainWithTheirEphemeral:theirEphemeral ourEphemeral:ourNewEphemeral];
OWSAssert(senderChain.rootKey.keyData.length == 32);
SPKAssert(senderChain.rootKey.keyData.length == ECCKeyLength);
[sessionState setRootKey:senderChain.rootKey];
OWSAssert(receiverChain.chainKey.key.length == 32);
SPKAssert(receiverChain.chainKey.key.length == ECCKeyLength);
[sessionState addReceiverChain:theirEphemeral chainKey:receiverChain.chainKey];
int previousCounter;
ows_sub_overflow(sessionState.senderChainKey.index, 1, &previousCounter);
[sessionState setPreviousCounter:MAX(previousCounter, 0)];
[sessionState setPreviousCounter:MAX(sessionState.senderChainKey.index-1 , 0)];
[sessionState setSenderChain:ourNewEphemeral chainKey:senderChain.chainKey];
return receiverChain.chainKey;
@ -435,55 +364,47 @@ NS_ASSUME_NONNULL_BEGIN
}
}
- (MessageKeys *)throws_getOrCreateMessageKeysForSession:(SessionState *)sessionState
theirEphemeral:(NSData *)theirEphemeral
chainKey:(ChainKey *)chainKey
counter:(int)counter
- (MessageKeys *)getOrCreateMessageKeysForSession:(SessionState *)sessionState
theirEphemeral:(NSData *)theirEphemeral
chainKey:(ChainKey *)chainKey
counter:(int)counter
{
OWSAssert(sessionState);
OWSGuardWithException(theirEphemeral, InvalidMessageException);
OWSGuardWithException(theirEphemeral.length == 32, InvalidMessageException);
OWSAssert(chainKey);
SPKAssert(sessionState);
SPKAssert(theirEphemeral);
SPKAssert(chainKey);
if (chainKey.index > counter) {
if ([sessionState hasMessageKeys:theirEphemeral counter:counter]) {
return [sessionState removeMessageKeys:theirEphemeral counter:counter];
} else {
OWSLogInfo(
DDLogInfo(
@"%@ %@.%d Duplicate message for counter: %d", self.tag, self.recipientId, self.deviceId, counter);
OWSLogFlush();
@throw [NSException exceptionWithName:DuplicateMessageException reason:@"Received message with old counter!" userInfo:@{}];
}
}
NSUInteger kCounterLimit = 25000;
int counterOffset;
if (__builtin_sub_overflow(counter, chainKey.index, &counterOffset)) {
OWSFailDebug(@"Overflow while calculating counter offset");
OWSRaiseException(InvalidMessageException, @"Overflow while calculating counter offset");
}
if (counterOffset > kCounterLimit) {
OWSLogError(@"%@ %@.%d Exceeded future message limit: %lu, index: %d, counter: %d)",
NSUInteger kCounterLimit = 2000;
if (counter - chainKey.index > kCounterLimit) {
DDLogError(@"%@ %@.%d Exceeded future message limit: %lu, index: %d, counter: %d)",
self.tag,
self.recipientId,
self.deviceId,
(unsigned long)kCounterLimit,
chainKey.index,
counter);
OWSLogFlush();
@throw [NSException exceptionWithName:InvalidMessageException
reason:@"Exceeded message keys chain length limit"
userInfo:@{}];
}
while (chainKey.index < counter) {
MessageKeys *messageKeys = [chainKey throws_messageKeys];
MessageKeys *messageKeys = [chainKey messageKeys];
[sessionState setMessageKeys:theirEphemeral messageKeys:messageKeys];
chainKey = chainKey.nextChainKey;
}
[sessionState setReceiverChainKey:theirEphemeral chainKey:[chainKey nextChainKey]];
return [chainKey throws_messageKeys];
return [chainKey messageKeys];
}
/**
@ -498,9 +419,11 @@ NS_ASSUME_NONNULL_BEGIN
return versionByte;
}
- (int)throws_remoteRegistrationId:(nullable id<SPKProtocolReadContext>)protocolContext
- (int)remoteRegistrationId:(nullable id)protocolContext
{
SessionRecord *_Nullable record =
SessionRecord *record =
[self.sessionStore loadSession:self.recipientId deviceId:_deviceId protocolContext:protocolContext];
if (!record) {
@ -510,9 +433,10 @@ NS_ASSUME_NONNULL_BEGIN
return record.sessionState.remoteRegistrationId;
}
- (int)throws_sessionVersion:(nullable id<SPKProtocolReadContext>)protocolContext
- (int)sessionVersion:(nullable id)protocolContext
{
SessionRecord *_Nullable record =
SessionRecord *record =
[self.sessionStore loadSession:self.recipientId deviceId:_deviceId protocolContext:protocolContext];
if (!record) {

View File

@ -1,12 +1,11 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "AxolotlStore.h"
#import "IdentityKeyStore.h"
#import "PreKeyBundle.h"
#import "PreKeyStore.h"
#import "SPKProtocolContext.h"
#import "SessionStore.h"
#import "SignedPreKeyStore.h"
#import <Foundation/Foundation.h>
@ -30,15 +29,11 @@ extern const int kPreKeyOfLastResortId;
recipientId:(NSString *)recipientId
deviceId:(int)deviceId;
- (void)throws_processPrekeyBundle:(PreKeyBundle *)preKeyBundle
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext NS_SWIFT_UNAVAILABLE("throws objc exceptions");
- (BOOL)processPrekeyBundle:(PreKeyBundle *)preKeyBundle
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
error:(NSError **)outError;
- (void)processPrekeyBundle:(PreKeyBundle *)preKeyBundle protocolContext:(nullable id)protocolContext;
- (int)throws_processPrekeyWhisperMessage:(PreKeyWhisperMessage *)message
withSession:(SessionRecord *)sessionRecord
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext NS_SWIFT_UNAVAILABLE("throws objc exceptions");
- (int)processPrekeyWhisperMessage:(PreKeyWhisperMessage *)message
withSession:(SessionRecord *)sessionRecord
protocolContext:(nullable id)protocolContext;
@end

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "SessionBuilder.h"
@ -15,8 +15,6 @@
#import "SessionState.h"
#import <Curve25519Kit/Curve25519.h>
#import <Curve25519Kit/Ed25519.h>
#import <SignalCoreKit/NSData+OWS.h>
#import <SignalCoreKit/SCKExceptionWrapper.h>
NS_ASSUME_NONNULL_BEGIN
@ -41,9 +39,6 @@ const int kPreKeyOfLastResortId = 0xFFFFFF;
@implementation SessionBuilder
- (instancetype)initWithAxolotlStore:(id<AxolotlStore>)sessionStore recipientId:(NSString*)recipientId deviceId:(int)deviceId{
OWSAssert(sessionStore);
OWSAssert(recipientId);
return [self initWithSessionStore:sessionStore
preKeyStore:sessionStore
signedPreKeyStore:sessionStore
@ -58,13 +53,6 @@ const int kPreKeyOfLastResortId = 0xFFFFFF;
identityKeyStore:(id<IdentityKeyStore>)identityKeyStore
recipientId:(NSString*)recipientId
deviceId:(int)deviceId{
OWSAssert(sessionStore);
OWSAssert(preKeyStore);
OWSAssert(signedPreKeyStore);
OWSAssert(identityKeyStore);
OWSAssert(recipientId);
self = [super init];
if (self) {
@ -79,23 +67,12 @@ const int kPreKeyOfLastResortId = 0xFFFFFF;
return self;
}
- (BOOL)processPrekeyBundle:(PreKeyBundle *)preKeyBundle
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
error:(NSError **)outError
- (void)processPrekeyBundle:(PreKeyBundle *)preKeyBundle protocolContext:(nullable id)protocolContext
{
return [SCKExceptionWrapper
tryBlock:^{
[self throws_processPrekeyBundle:preKeyBundle protocolContext:protocolContext];
}
error:outError];
}
SPKAssert(preKeyBundle);
- (void)throws_processPrekeyBundle:(PreKeyBundle *)preKeyBundle protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
{
OWSAssert(preKeyBundle);
NSData *theirIdentityKey = preKeyBundle.identityKey.throws_removeKeyType;
NSData *theirSignedPreKey = preKeyBundle.signedPreKeyPublic.throws_removeKeyType;
NSData *theirIdentityKey = preKeyBundle.identityKey.removeKeyType;
NSData *theirSignedPreKey = preKeyBundle.signedPreKeyPublic.removeKeyType;
if (![self.identityStore isTrustedIdentityKey:theirIdentityKey
recipientId:self.recipientId
@ -104,17 +81,14 @@ const int kPreKeyOfLastResortId = 0xFFFFFF;
@throw [NSException exceptionWithName:UntrustedIdentityKeyException reason:@"Identity key is not valid" userInfo:@{}];
}
// NOTE: we use preKeyBundle.signedPreKeyPublic which has the key type byte.
if (![Ed25519 throws_verifySignature:preKeyBundle.signedPreKeySignature
publicKey:theirIdentityKey
data:preKeyBundle.signedPreKeyPublic]) {
if (![Ed25519 verifySignature:preKeyBundle.signedPreKeySignature publicKey:theirIdentityKey data:preKeyBundle.signedPreKeyPublic]) {
@throw [NSException exceptionWithName:InvalidKeyException reason:@"KeyIsNotValidlySigned" userInfo:nil];
}
SessionRecord *sessionRecord =
[self.sessionStore loadSession:self.recipientId deviceId:preKeyBundle.deviceId protocolContext:protocolContext];
ECKeyPair *ourBaseKey = [Curve25519 generateKeyPair];
NSData *theirOneTimePreKey = preKeyBundle.preKeyPublic.throws_removeKeyType;
NSData *theirOneTimePreKey = preKeyBundle.preKeyPublic.removeKeyType;
int theirOneTimePreKeyId = preKeyBundle.preKeyId;
int theirSignedPreKeyId = preKeyBundle.signedPreKeyId;
@ -130,10 +104,8 @@ const int kPreKeyOfLastResortId = 0xFFFFFF;
if (!sessionRecord.isFresh) {
[sessionRecord archiveCurrentState];
}
[RatchetingSession throws_initializeSession:[sessionRecord sessionState]
sessionVersion:CURRENT_VERSION
AliceParameters:params];
[RatchetingSession initializeSession:[sessionRecord sessionState] sessionVersion:CURRENT_VERSION AliceParameters:params];
DDLogInfo(@"setUnacknowledgedPreKeyMessage for: %@ with preKeyId: %d", self.recipientId, theirOneTimePreKeyId);
@ -146,6 +118,12 @@ const int kPreKeyOfLastResortId = 0xFFFFFF;
BOOL previousIdentityExisted = [self.identityStore saveRemoteIdentity:theirIdentityKey
recipientId:self.recipientId
protocolContext:protocolContext];
if (previousIdentityExisted) {
DDLogInfo(@"%@ PKBundle removing previous session states for changed identity for recipient:%@",
self.tag,
self.recipientId);
[sessionRecord removePreviousSessionStates];
}
[self.sessionStore storeSession:self.recipientId
deviceId:self.deviceId
@ -153,15 +131,15 @@ const int kPreKeyOfLastResortId = 0xFFFFFF;
protocolContext:protocolContext];
}
- (int)throws_processPrekeyWhisperMessage:(PreKeyWhisperMessage *)message
withSession:(SessionRecord *)sessionRecord
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
- (int)processPrekeyWhisperMessage:(PreKeyWhisperMessage *)message
withSession:(SessionRecord *)sessionRecord
protocolContext:(nullable id)protocolContext
{
OWSAssert(message);
OWSAssert(sessionRecord);
SPKAssert(message);
SPKAssert(sessionRecord);
int messageVersion = message.version;
NSData *theirIdentityKey = message.identityKey.throws_removeKeyType;
NSData *theirIdentityKey = message.identityKey.removeKeyType;
if (![self.identityStore isTrustedIdentityKey:theirIdentityKey
recipientId:self.recipientId
@ -174,8 +152,7 @@ const int kPreKeyOfLastResortId = 0xFFFFFF;
switch (messageVersion) {
case 3:
unSignedPrekeyId =
[self throws_processPrekeyV3:message withSession:sessionRecord protocolContext:protocolContext];
unSignedPrekeyId = [self processPrekeyV3:message withSession:sessionRecord protocolContext:protocolContext];
break;
default:
@throw [NSException exceptionWithName:InvalidVersionException reason:@"Trying to initialize with unknown version" userInfo:@{}];
@ -189,48 +166,28 @@ const int kPreKeyOfLastResortId = 0xFFFFFF;
return unSignedPrekeyId;
}
- (int)throws_processPrekeyV3:(PreKeyWhisperMessage *)message
withSession:(SessionRecord *)sessionRecord
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
- (int)processPrekeyV3:(PreKeyWhisperMessage *)message
withSession:(SessionRecord *)sessionRecord
protocolContext:(nullable id)protocolContext
{
OWSAssert(message);
OWSAssert(sessionRecord);
NSData *baseKey = message.baseKey.throws_removeKeyType;
NSData *baseKey = message.baseKey.removeKeyType;
if ([sessionRecord hasSessionState:message.version baseKey:baseKey]) {
return -1;
}
SignedPreKeyRecord *_Nullable signedPreKeyRecord = [self.signedPreKeyStore loadSignedPreKey:message.signedPrekeyId
protocolContext:protocolContext];
if (signedPreKeyRecord == nil) {
OWSLogWarn(@"Signed prekey id: %lu, prekey id: %lu.",
(unsigned long) message.signedPrekeyId,
(unsigned long) message.prekeyID);
OWSLogWarn(@"Available signed prekey ids: %@",
[self.signedPreKeyStore availableSignedPreKeyIdsWithProtocolContext:protocolContext]);
OWSRaiseException(InvalidKeyIdException, @"No signed prekey found matching key id");
}
ECKeyPair *ourSignedPrekey = signedPreKeyRecord.keyPair;
ECKeyPair *ourSignedPrekey = [self.signedPreKeyStore loadSignedPrekey:message.signedPrekeyId].keyPair;
ECKeyPair *_Nullable ourOneTimePreKey;
if (message.prekeyID >= 0) {
PreKeyRecord *_Nullable preKey = [self.prekeyStore loadPreKey:message.prekeyID
protocolContext:protocolContext];
if (preKey == nil) {
OWSFailDebug(@"Missing prekeyID: %lu", (unsigned long) message.prekeyID);
OWSRaiseException(InvalidKeyIdException, @"No pre key found matching key id");
}
ourOneTimePreKey = preKey.keyPair;
ourOneTimePreKey = [self.prekeyStore loadPreKey:message.prekeyID].keyPair;
} else {
DDLogWarn(@"%@ Processing PreKey message which had no one-time prekey.", self.tag);
}
BobAxolotlParameters *params =
[[BobAxolotlParameters alloc] initWithMyIdentityKeyPair:[self.identityStore identityKeyPair:protocolContext]
theirIdentityKey:message.identityKey.throws_removeKeyType
theirIdentityKey:message.identityKey.removeKeyType
ourSignedPrekey:ourSignedPrekey
ourRatchetKey:ourSignedPrekey
ourOneTimePrekey:ourOneTimePreKey
@ -239,11 +196,9 @@ const int kPreKeyOfLastResortId = 0xFFFFFF;
if (!sessionRecord.isFresh) {
[sessionRecord archiveCurrentState];
}
[RatchetingSession throws_initializeSession:sessionRecord.sessionState
sessionVersion:message.version
BobParameters:params];
[RatchetingSession initializeSession:sessionRecord.sessionState sessionVersion:message.version BobParameters:params];
[sessionRecord.sessionState setLocalRegistrationId:[self.identityStore localRegistrationId:protocolContext]];
[sessionRecord.sessionState setRemoteRegistrationId:message.registrationId];
[sessionRecord.sessionState setAliceBaseKey:baseKey];

View File

@ -8,14 +8,17 @@
@interface SessionRecord : NSObject <NSSecureCoding>
- (instancetype)init;
- (instancetype)initWithSessionState:(SessionState*)sessionState;
- (BOOL)hasSessionState:(int)version baseKey:(NSData*)aliceBaseKey;
- (SessionState*)sessionState;
- (NSArray<SessionState *> *)previousSessionStates;
- (NSMutableArray<SessionState *> *)previousSessionStates;
- (void)removePreviousSessionStates;
- (BOOL)isFresh;
- (void)markAsUnFresh;
- (void)archiveCurrentState;
- (void)promoteState:(SessionState*)promotedState;
- (void)setState:(SessionState*)sessionState;
@end

View File

@ -53,6 +53,17 @@
return self;
}
- (instancetype)initWithSessionState:(SessionState *)sessionState{
assert(sessionState);
self = [self init];
self.sessionState = sessionState;
self.fresh = false;
return self;
}
- (BOOL)hasSessionState:(int)version baseKey:(NSData *)aliceBaseKey{
if (self.sessionState.version == version && [aliceBaseKey isEqualToData:self.sessionState.aliceBaseKey]) {
return YES;
@ -71,11 +82,16 @@
return _sessionState;
}
- (NSArray<SessionState *> *)previousSessionStates
- (NSMutableArray<SessionState *> *)previousSessionStates
{
return _previousStates;
}
- (void)removePreviousSessionStates
{
[_previousStates removeAllObjects];
}
- (BOOL)isFresh{
return _fresh;
}
@ -86,10 +102,6 @@
}
- (void)archiveCurrentState{
if (self.sessionState.isFresh) {
OWSLogInfo(@"Skipping archive, current session state is fresh.");
return;
}
[self promoteState:[SessionState new]];
}
@ -98,11 +110,8 @@
self.sessionState = promotedState;
if (self.previousStates.count > ARCHIVED_STATES_MAX_LENGTH) {
NSUInteger deleteCount;
ows_sub_overflow(self.previousStates.count, ARCHIVED_STATES_MAX_LENGTH, &deleteCount);
NSIndexSet *indexesToDelete =
[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(ARCHIVED_STATES_MAX_LENGTH, deleteCount)];
[self.previousStates removeObjectsAtIndexes:indexesToDelete];
NSIndexSet *indexesToDelete = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(ARCHIVED_STATES_MAX_LENGTH, self.previousStates.count - ARCHIVED_STATES_MAX_LENGTH)];
[self.previousSessionStates removeObjectsAtIndexes:indexesToDelete];
}
}

View File

@ -39,8 +39,6 @@
@property(nonatomic)int remoteRegistrationId;
@property(nonatomic)int localRegistrationId;
@property (nonatomic, readonly) BOOL isFresh;
- (NSData*)senderRatchetKey;
- (ECKeyPair*)senderRatchetKeyPair;

View File

@ -21,8 +21,6 @@ static NSString* const kCoderBaseKey = @"kCoderBaseKey";
}
-(instancetype)initWithBaseKey:(NSData*)baseKey preKeyId:(int)preKeyId signedPreKeyId:(int)signedPrekeyId{
OWSAssert(baseKey);
self = [super init];
if (self) {
_preKeyId = preKeyId;
@ -119,11 +117,6 @@ static NSString* const kCoderPendingPrekey = @"kCoderPendingPrekey";
[aCoder encodeObject:self.pendingPreKey forKey:kCoderPendingPrekey];
}
- (BOOL)isFresh
{
return self.remoteIdentityKey == nil && self.localIdentityKey == nil && self.sendingChain == nil && self.receivingChains.count == 0 && self.pendingPreKey == nil;
}
- (NSData*)senderRatchetKey{
return [[self senderRatchetKeyPair] publicKey];
}
@ -154,7 +147,7 @@ static NSString* const kCoderPendingPrekey = @"kCoderPendingPrekey";
cai.index = index;
return cai;
}
ows_add_overflow(index, 1, &index);
index++;
}
return nil;
@ -162,23 +155,18 @@ static NSString* const kCoderPendingPrekey = @"kCoderPendingPrekey";
- (ChainKey *)receiverChainKey:(NSData *)senderEphemeral
{
OWSAssert(senderEphemeral);
ChainAndIndex *receiverChainAndIndex = [self receiverChain:senderEphemeral];
ReceivingChain *receiverChain = (ReceivingChain*)receiverChainAndIndex.chain;
if (receiverChain == nil) {
return nil;
} else{
OWSAssert(receiverChain.chainKey.key);
SPKAssert(receiverChain.chainKey.key);
return [[ChainKey alloc] initWithData:receiverChain.chainKey.key index:receiverChain.chainKey.index];
}
}
- (void)setReceiverChainKey:(NSData*)senderEphemeral chainKey:(ChainKey*)nextChainKey{
OWSAssert(senderEphemeral);
OWSAssert(nextChainKey);
ChainAndIndex *chainAndIndex = [self receiverChain:senderEphemeral];
ReceivingChain *chain = (ReceivingChain*)chainAndIndex.chain;
@ -189,8 +177,7 @@ static NSString* const kCoderPendingPrekey = @"kCoderPendingPrekey";
}
- (void)addReceiverChain:(NSData*)senderRatchetKey chainKey:(ChainKey*)chainKey{
OWSAssert(senderRatchetKey);
OWSAssert(chainKey);
ReceivingChain *receivingChain = [[ReceivingChain alloc] initWithChainKey:chainKey senderRatchetKey:senderRatchetKey];
[self.receivingChains addObject:receivingChain];
@ -204,9 +191,6 @@ static NSString* const kCoderPendingPrekey = @"kCoderPendingPrekey";
}
- (void)setSenderChain:(ECKeyPair*)senderRatchetKeyPair chainKey:(ChainKey*)chainKey{
OWSAssert(senderRatchetKeyPair);
OWSAssert(chainKey);
self.sendingChain = [[SendingChain alloc]initWithChainKey:chainKey senderRatchetKeyPair:senderRatchetKeyPair];
}
@ -215,8 +199,6 @@ static NSString* const kCoderPendingPrekey = @"kCoderPendingPrekey";
}
- (void)setSenderChainKey:(ChainKey*)nextChainKey{
OWSAssert(nextChainKey);
SendingChain *sendingChain = self.sendingChain;
sendingChain.chainKey = nextChainKey;
@ -224,7 +206,6 @@ static NSString* const kCoderPendingPrekey = @"kCoderPendingPrekey";
}
- (BOOL)hasMessageKeys:(NSData*)senderRatchetKey counter:(int)counter{
OWSAssert(senderRatchetKey);
ChainAndIndex *chainAndIndex = [self receiverChain:senderRatchetKey];
ReceivingChain *receivingChain = (ReceivingChain*)chainAndIndex.chain;
@ -268,15 +249,10 @@ static NSString* const kCoderPendingPrekey = @"kCoderPendingPrekey";
}
-(void)setReceiverChain:(int)index updatedChain:(ReceivingChain*)recvchain{
OWSAssert(recvchain);
[self.receivingChains replaceObjectAtIndex:index withObject:recvchain];
}
- (void)setMessageKeys:(NSData*)senderRatchetKey messageKeys:(MessageKeys*)messageKeys{
OWSAssert(senderRatchetKey);
OWSAssert(messageKeys);
ChainAndIndex *chainAndIndex = [self receiverChain:senderRatchetKey];
ReceivingChain *chain = (ReceivingChain*)chainAndIndex.chain;
[chain.messageKeysList addObject:messageKeys];
@ -285,8 +261,6 @@ static NSString* const kCoderPendingPrekey = @"kCoderPendingPrekey";
}
- (void)setUnacknowledgedPreKeyMessage:(int)preKeyId signedPreKey:(int)signedPreKeyId baseKey:(NSData*)baseKey{
OWSAssert(baseKey);
PendingPreKey *pendingPreKey = [[PendingPreKey alloc] initWithBaseKey:baseKey preKeyId:preKeyId signedPreKeyId:signedPreKeyId];
self.pendingPreKey = pendingPreKey;

View File

@ -1,8 +1,7 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "SPKProtocolContext.h"
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@ -18,9 +17,9 @@ typedef NS_ENUM(NSInteger, TSMessageDirection) {
// See a discussion of the protocolContext in SessionCipher.h.
@protocol IdentityKeyStore <NSObject>
- (nullable ECKeyPair *)identityKeyPair:(nullable id<SPKProtocolWriteContext>)protocolContext;
- (nullable ECKeyPair *)identityKeyPair:(nullable id)protocolContext;
- (int)localRegistrationId:(nullable id<SPKProtocolWriteContext>)protocolContext;
- (int)localRegistrationId:(nullable id)protocolContext;
/**
* Record a recipients identity key
@ -33,7 +32,7 @@ typedef NS_ENUM(NSInteger, TSMessageDirection) {
*/
- (BOOL)saveRemoteIdentity:(NSData *)identityKey
recipientId:(NSString *)recipientId
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext;
protocolContext:(nullable id)protocolContext;
/**
* @param identityKey key data used to identify the recipient
@ -47,12 +46,7 @@ typedef NS_ENUM(NSInteger, TSMessageDirection) {
- (BOOL)isTrustedIdentityKey:(NSData *)identityKey
recipientId:(NSString *)recipientId
direction:(TSMessageDirection)direction
protocolContext:(nullable id<SPKProtocolReadContext>)protocolContext;
- (nullable NSData *)identityKeyForRecipientId:(NSString *)recipientId;
- (nullable NSData *)identityKeyForRecipientId:(NSString *)recipientId
protocolContext:(nullable id<SPKProtocolReadContext>)protocolContext;
protocolContext:(nullable id)protocolContext;
@end

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "PreKeyRecord.h"
@ -9,14 +9,13 @@ NS_ASSUME_NONNULL_BEGIN
@protocol PreKeyStore <NSObject>
- (nullable PreKeyRecord *)loadPreKey:(int)preKeyId
protocolContext:(nullable id<SPKProtocolReadContext>)protocolContext;
- (PreKeyRecord *)loadPreKey:(int)preKeyId;
- (void)storePreKey:(int)preKeyId preKeyRecord:(PreKeyRecord *)record
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext;
- (void)storePreKey:(int)preKeyId preKeyRecord:(PreKeyRecord *)record;
- (void)removePreKey:(int)preKeyId
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext;
- (BOOL)containsPreKey:(int)preKeyId;
- (void)removePreKey:(int)preKeyId;
@end

View File

@ -1,8 +1,7 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "SPKProtocolContext.h"
#import "SessionRecord.h"
#import <Foundation/Foundation.h>
@ -21,24 +20,25 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (SessionRecord *)loadSession:(NSString *)contactIdentifier
deviceId:(int)deviceId
protocolContext:(nullable id<SPKProtocolReadContext>)protocolContext;
protocolContext:(nullable id)protocolContext;
- (NSArray *)subDevicesSessions:(NSString *)contactIdentifier protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext __attribute__((deprecated));
// Deprecated.
- (NSArray *)subDevicesSessions:(NSString *)contactIdentifier protocolContext:(nullable id)protocolContext;
- (void)storeSession:(NSString *)contactIdentifier
deviceId:(int)deviceId
session:(SessionRecord *)session
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext;
protocolContext:(nullable id)protocolContext;
- (BOOL)containsSession:(NSString *)contactIdentifier
deviceId:(int)deviceId
protocolContext:(nullable id<SPKProtocolReadContext>)protocolContext;
protocolContext:(nullable id)protocolContext;
- (void)deleteSessionForContact:(NSString *)contactIdentifier
deviceId:(int)deviceId
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext;
protocolContext:(nullable id)protocolContext;
- (void)deleteAllSessionsForContact:(NSString *)contactIdentifier protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext;
- (void)deleteAllSessionsForContact:(NSString *)contactIdentifier protocolContext:(nullable id)protocolContext;
@end

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "SignedPrekeyRecord.h"
@ -9,22 +9,17 @@ NS_ASSUME_NONNULL_BEGIN
@protocol SignedPreKeyStore <NSObject>
- (nullable SignedPreKeyRecord *)loadSignedPreKey:(int)signedPreKeyId
protocolContext:(nullable id<SPKProtocolReadContext>)protocolContext;
- (SignedPreKeyRecord *)loadSignedPrekey:(int)signedPreKeyId;
- (NSArray<SignedPreKeyRecord *> *)loadSignedPreKeysWithProtocolContext:(nullable id<SPKProtocolReadContext>)protocolContext;
- (nullable SignedPreKeyRecord *)loadSignedPrekeyOrNil:(int)signedPreKeyId;
- (void)storeSignedPreKey:(int)signedPreKeyId
signedPreKeyRecord:(SignedPreKeyRecord *)signedPreKeyRecord
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext;
- (NSArray<SignedPreKeyRecord *> *)loadSignedPreKeys;
- (BOOL)containsSignedPreKey:(int)signedPreKeyId
protocolContext:(nullable id<SPKProtocolReadContext>)protocolContext;
- (void)storeSignedPreKey:(int)signedPreKeyId signedPreKeyRecord:(SignedPreKeyRecord *)signedPreKeyRecord;
- (void)removeSignedPreKey:(int)signedPreKeyId
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext;
- (BOOL)containsSignedPreKey:(int)signedPreKeyId;
- (NSArray<NSString *> *)availableSignedPreKeyIdsWithProtocolContext:(nullable id<SPKProtocolReadContext>)protocolContext;
- (void)removeSignedPreKey:(int)signedPrekeyId;
@end

View File

@ -1,16 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "AxolotlStore.h"
NS_ASSUME_NONNULL_BEGIN
@interface SPKMockProtocolStore : NSObject <AxolotlStore>
- (instancetype)initWithIdentityKeyPair:(ECKeyPair *)identityKeyPair
localRegistrationId:(int)localRegistrationId NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,264 +0,0 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "SPKMockProtocolStore.h"
#import "AxolotlExceptions.h"
NS_ASSUME_NONNULL_BEGIN
@interface SPKMockProtocolStore ()
@property NSMutableDictionary<NSString *, NSMutableDictionary *> *sessionRecords;
// Signed PreKey Store
@property NSMutableDictionary *preKeyStore;
@property NSMutableDictionary *signedPreKeyStore;
@property NSMutableDictionary *trustedKeys;
@property ECKeyPair *identityKeyPair;
@property int localRegistrationId;
@end
@implementation SPKMockProtocolStore
#pragma mark General
- (instancetype)init
{
return [self initWithIdentityKeyPair:[Curve25519 generateKeyPair] localRegistrationId:arc4random() % 16380];
}
- (instancetype)initWithIdentityKeyPair:(ECKeyPair *)identityKeyPair localRegistrationId:(int)localRegistrationId
{
self = [super init];
if (self) {
_identityKeyPair = identityKeyPair;
_localRegistrationId = localRegistrationId;
_preKeyStore = [NSMutableDictionary dictionary];
_signedPreKeyStore = [NSMutableDictionary dictionary];
_trustedKeys = [NSMutableDictionary dictionary];
_sessionRecords = [NSMutableDictionary dictionary];
}
return self;
}
#pragma mark Signed PreKey Store
- (nullable SignedPreKeyRecord *)loadSignedPreKey:(int)signedPreKeyId
protocolContext:(nullable id<SPKProtocolReadContext>)protocolContext
{
return [self.signedPreKeyStore objectForKey:[NSNumber numberWithInt:signedPreKeyId]];
}
- (NSArray<SignedPreKeyRecord *> *)loadSignedPreKeysWithProtocolContext:(nullable id<SPKProtocolReadContext>)protocolContext
{
NSMutableArray *results = [NSMutableArray array];
for (SignedPreKeyRecord *signedPrekey in [self.signedPreKeyStore allValues]) {
[results addObject:signedPrekey];
}
return results;
}
- (NSArray<NSString *> *)availableSignedPreKeyIdsWithProtocolContext:(nullable id<SPKProtocolReadContext>)protocolContext
{
return @[];
}
- (void)storeSignedPreKey:(int)signedPreKeyId
signedPreKeyRecord:(SignedPreKeyRecord *)signedPreKeyRecord
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
{
[self.signedPreKeyStore setObject:signedPreKeyRecord forKey:[NSNumber numberWithInteger:signedPreKeyId]];
}
- (BOOL)containsSignedPreKey:(int)signedPreKeyId
protocolContext:(nullable id<SPKProtocolReadContext>)protocolContext
{
if ([[self.signedPreKeyStore allKeys] containsObject:[NSNumber numberWithInteger:signedPreKeyId]]) {
return TRUE;
}
return FALSE;
}
- (void)removeSignedPreKey:(int)signedPreKeyId
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
{
[self.signedPreKeyStore removeObjectForKey:[NSNumber numberWithInteger:signedPreKeyId]];
}
#pragma mark PreKey Store
- (nullable PreKeyRecord *)loadPreKey:(int)preKeyId
protocolContext:(nullable id<SPKProtocolReadContext>)protocolContext;
{
return [self.preKeyStore objectForKey:[NSNumber numberWithInt:preKeyId]];
}
- (NSArray *)loadPreKeys
{
NSMutableArray *results = [NSMutableArray array];
for (PreKeyRecord *prekey in [self.preKeyStore allValues]) {
[results addObject:prekey];
}
return results;
}
- (void)storePreKey:(int)preKeyId preKeyRecord:(PreKeyRecord *)record
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
{
[self.preKeyStore setObject:record forKey:[NSNumber numberWithInt:preKeyId]];
}
- (void)removePreKey:(int)preKeyId
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
{
[self.preKeyStore removeObjectForKey:[NSNumber numberWithInt:preKeyId]];
}
#pragma mark IdentityKeyStore
- (nullable ECKeyPair *)identityKeyPair:(nullable id<SPKProtocolWriteContext>)protocolContext
{
return self.identityKeyPair;
}
- (int)localRegistrationId:(nullable id<SPKProtocolWriteContext>)protocolContext
{
return self.localRegistrationId;
}
- (BOOL)saveRemoteIdentity:(NSData *)identityKey
recipientId:(NSString *)recipientId
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
{
NSData *existingKey = [self.trustedKeys objectForKey:recipientId];
if ([existingKey isEqualToData:existingKey]) {
return NO;
}
[self.trustedKeys setObject:identityKey forKey:recipientId];
return YES;
}
- (BOOL)isTrustedIdentityKey:(NSData *)identityKey
recipientId:(NSString *)recipientId
direction:(TSMessageDirection)direction
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
{
NSData *data = [self.trustedKeys objectForKey:recipientId];
if (!data) {
// Trust on first use
return YES;
}
switch (direction) {
case TSMessageDirectionIncoming:
return YES;
case TSMessageDirectionOutgoing:
// In a real implementation you may wish to ensure the use has been properly notified of any
// recent identity change before sending outgoing messages.
return [data isEqualToData:identityKey];
case TSMessageDirectionUnknown:
NSAssert(NO, @"unknown message direction");
return NO;
}
}
- (nullable NSData *)identityKeyForRecipientId:(NSString *)recipientId
{
return [self identityKeyForRecipientId:recipientId protocolContext:nil];
}
- (nullable NSData *)identityKeyForRecipientId:(NSString *)recipientId
protocolContext:(nullable id<SPKProtocolReadContext>)protocolContext
{
NSData *_Nullable data = [self.trustedKeys objectForKey:recipientId];
return data;
}
#pragma mark Session Store
- (SessionRecord *)loadSession:(NSString *)contactIdentifier
deviceId:(int)deviceId
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
{
SessionRecord *sessionRecord = [[self deviceSessionRecordsForContactIdentifier:contactIdentifier]
objectForKey:[NSNumber numberWithInteger:deviceId]];
if (!sessionRecord) {
sessionRecord = [SessionRecord new];
}
return sessionRecord;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
- (NSArray *)subDevicesSessions:(NSString *)contactIdentifier protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
{
return [[self deviceSessionRecordsForContactIdentifier:contactIdentifier] allKeys];
}
#pragma clang diagnostic pop
- (NSMutableDictionary *)deviceSessionRecordsForContactIdentifier:(NSString *)contactIdentifier
{
return [self.sessionRecords objectForKey:contactIdentifier];
}
- (void)storeSession:(NSString *)contactIdentifier
deviceId:(int)deviceId
session:(SessionRecord *)session
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
{
NSAssert(session, @"Session can't be nil");
NSMutableDictionary *deviceSessions = self.sessionRecords[contactIdentifier];
if (!deviceSessions) {
deviceSessions = [NSMutableDictionary new];
}
deviceSessions[@(deviceId)] = session;
self.sessionRecords[contactIdentifier] = deviceSessions;
}
- (BOOL)containsSession:(NSString *)contactIdentifier
deviceId:(int)deviceId
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
{
if ([[self.sessionRecords objectForKey:contactIdentifier] objectForKey:[NSNumber numberWithInt:deviceId]]) {
return YES;
}
return NO;
}
- (void)deleteSessionForContact:(NSString *)contactIdentifier
deviceId:(int)deviceId
protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
{
NSMutableDictionary<NSNumber *, SessionRecord *> *sessions =
[self deviceSessionRecordsForContactIdentifier:contactIdentifier];
[sessions removeObjectForKey:@(deviceId)];
}
- (void)deleteAllSessionsForContact:(NSString *)contactIdentifier protocolContext:(nullable id<SPKProtocolWriteContext>)protocolContext
{
[self.sessionRecords removeObjectForKey:contactIdentifier];
}
@end
NS_ASSUME_NONNULL_END

View File

@ -1,18 +1,16 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// NSData+keyVersionByte.h
// AxolotlKit
//
// Created by Frederic Jacobs on 26/10/14.
// Copyright (c) 2014 Frederic Jacobs. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSData (keyVersionByte)
- (instancetype)prependKeyType;
- (instancetype)throws_removeKeyType NS_SWIFT_UNAVAILABLE("throws objc exceptions");
- (nullable instancetype)removeKeyTypeAndReturnError:(NSError **)outError;
- (instancetype)removeKeyType;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,12 +1,13 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// NSData+keyVersionByte.m
// AxolotlKit
//
// Created by Frederic Jacobs on 26/10/14.
// Copyright (c) 2014 Frederic Jacobs. All rights reserved.
//
#import "NSData+keyVersionByte.h"
#import "AxolotlExceptions.h"
#import <SignalCoreKit/SCKExceptionWrapper.h>
NS_ASSUME_NONNULL_BEGIN
#import "NSData+keyVersionByte.h"
@implementation NSData (keyVersionByte)
@ -17,36 +18,20 @@ const Byte DJB_TYPE = 0x05;
NSMutableData *data = [NSMutableData dataWithBytes:&DJB_TYPE length:1];
[data appendData:self.copy];
return data;
} else {
OWSLogDebug(@"key length: %lu", (unsigned long)self.length);
}
return self;
}
- (nullable instancetype)removeKeyTypeAndReturnError:(NSError **)outError
{
@try {
return self.throws_removeKeyType;
} @catch (NSException *exception) {
*outError = SCKExceptionWrapperErrorMake(exception);
return nil;
}
}
- (instancetype)throws_removeKeyType
{
- (instancetype)removeKeyType {
if (self.length == 33) {
if ([[self subdataWithRange:NSMakeRange(0, 1)] isEqualToData:[NSData dataWithBytes:&DJB_TYPE length:1]]) {
return [self subdataWithRange:NSMakeRange(1, 32)];
} else{
@throw [NSException exceptionWithName:InvalidKeyException reason:@"Key type is incorrect" userInfo:@{}];
}
} else {
OWSLogDebug(@"key length: %lu", (unsigned long)self.length);
} else{
return self;
}
}
@end
NS_ASSUME_NONNULL_END

View File

@ -1,17 +0,0 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@protocol SPKProtocolReadContext <NSObject>
@end
@protocol SPKProtocolWriteContext <SPKProtocolReadContext>
@end
NS_ASSUME_NONNULL_END

View File

@ -1,11 +1,9 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#define MAC_LENGTH 8
@interface SerializationUtilities : NSObject
@ -16,12 +14,6 @@ NS_ASSUME_NONNULL_BEGIN
+ (Byte)intsToByteHigh:(int)highValue low:(int)lowValue;
+ (NSData *)throws_macWithVersion:(int)version
identityKey:(NSData *)senderIdentityKey
receiverIdentityKey:(NSData *)receiverIdentityKey
macKey:(NSData *)macKey
serialized:(NSData *)serialized NS_SWIFT_UNAVAILABLE("throws objc exceptions");
+ (NSData*)macWithVersion:(int)version identityKey:(NSData*)senderIdentityKey receiverIdentityKey:(NSData*)receiverIdentityKey macKey:(NSData*)macKey serialized:(NSData*)serialized;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,80 +1,37 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "SerializationUtilities.h"
#import <CommonCrypto/CommonCrypto.h>
NS_ASSUME_NONNULL_BEGIN
@implementation SerializationUtilities
+ (int)highBitsToIntFromByte:(Byte)byte
{
+ (int)highBitsToIntFromByte:(Byte)byte{
return (byte & 0xFF) >> 4;
}
+ (int)lowBitsToIntFromByte:(Byte)byte
{
+ (int)lowBitsToIntFromByte:(Byte)byte{
return (byte & 0xF);
}
+ (Byte)intsToByteHigh:(int)highValue low:(int)lowValue
{
+ (Byte)intsToByteHigh:(int)highValue low:(int)lowValue{
return (Byte)((highValue << 4 | lowValue) & 0xFF);
}
+ (NSData *)throws_macWithVersion:(int)version
identityKey:(NSData *)senderIdentityKey
receiverIdentityKey:(NSData *)receiverIdentityKey
macKey:(NSData *)macKey
serialized:(NSData *)serialized
{
if (!macKey) {
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Missing macKey." userInfo:nil];
}
if (macKey.length >= SIZE_MAX) {
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Oversize macKey." userInfo:nil];
}
if (!senderIdentityKey) {
@throw
[NSException exceptionWithName:NSInvalidArgumentException reason:@"Missing senderIdentityKey" userInfo:nil];
}
if (senderIdentityKey.length >= SIZE_MAX) {
@throw [NSException exceptionWithName:NSInvalidArgumentException
reason:@"Oversize senderIdentityKey"
userInfo:nil];
}
if (!receiverIdentityKey) {
@throw [NSException exceptionWithName:NSInvalidArgumentException
reason:@"Missing receiverIdentityKey"
userInfo:nil];
}
if (receiverIdentityKey.length >= SIZE_MAX) {
@throw [NSException exceptionWithName:NSInvalidArgumentException
reason:@"Oversize receiverIdentityKey"
userInfo:nil];
}
if (!serialized) {
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Missing serialized." userInfo:nil];
}
if (serialized.length >= SIZE_MAX) {
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Oversize serialized." userInfo:nil];
}
NSMutableData *_Nullable bufferData = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
OWSAssert(bufferData);
+ (NSData*)macWithVersion:(int)version identityKey:(NSData*)senderIdentityKey receiverIdentityKey:(NSData*)receiverIdentityKey macKey:(NSData*)macKey serialized:(NSData*)serialized {
uint8_t ourHmac[CC_SHA256_DIGEST_LENGTH] = {0};
CCHmacContext context;
CCHmacInit(&context, kCCHmacAlgSHA256, [macKey bytes], [macKey length]);
CCHmacInit (&context, kCCHmacAlgSHA256, [macKey bytes], [macKey length]);
CCHmacUpdate(&context, [senderIdentityKey bytes], [senderIdentityKey length]);
CCHmacUpdate(&context, [receiverIdentityKey bytes], [receiverIdentityKey length]);
CCHmacUpdate(&context, [serialized bytes], [serialized length]);
CCHmacFinal(&context, bufferData.mutableBytes);
return [bufferData subdataWithRange:NSMakeRange(0, MAC_LENGTH)];
CCHmacFinal (&context, &ourHmac);
return [NSData dataWithBytes:ourHmac length:MAC_LENGTH];
}
@end
NS_ASSUME_NONNULL_END
@end

View File

@ -1,7 +1,14 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "SPKAsserts.h"
#import <CocoaLumberjack/CocoaLumberjack.h>
#import <Foundation/Foundation.h>
#import <SignalCoreKit/NSObject+OWS.h>
#import <SignalCoreKit/OWSAsserts.h>
@import CocoaLumberjack;
#ifdef DEBUG
static const NSUInteger ddLogLevel = DDLogLevelAll;
#else
static const NSUInteger ddLogLevel = DDLogLevelInfo;
#endif

View File

@ -0,0 +1,15 @@
//
// AxolotlInMemoryStore.h
// AxolotlKit
//
// Created by Frederic Jacobs on 17/10/14.
// Copyright (c) 2014 Frederic Jacobs. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AxolotlStore.h"
@interface AxolotlInMemoryStore : NSObject <AxolotlStore>
@end

View File

@ -0,0 +1,230 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "AxolotlInMemoryStore.h"
#import "AxolotlExceptions.h"
NS_ASSUME_NONNULL_BEGIN
@interface AxolotlInMemoryStore ()
@property NSMutableDictionary<NSString *, NSMutableDictionary *> *sessionRecords;
// Signed PreKey Store
@property NSMutableDictionary *preKeyStore;
@property NSMutableDictionary *signedPreKeyStore;
@property NSMutableDictionary *trustedKeys;
@property ECKeyPair *_identityKeyPair;
@property int _localRegistrationId;
@end
@implementation AxolotlInMemoryStore
# pragma mark General
- (instancetype)init{
self = [super init];
if (self) {
self._identityKeyPair = [Curve25519 generateKeyPair];
self._localRegistrationId = arc4random() % 16380;
_preKeyStore = [NSMutableDictionary dictionary];
_signedPreKeyStore = [NSMutableDictionary dictionary];
_trustedKeys = [NSMutableDictionary dictionary];
_sessionRecords = [NSMutableDictionary dictionary];
}
return self;
}
# pragma mark Signed PreKey Store
- (SignedPreKeyRecord *)loadSignedPrekey:(int)signedPreKeyId{
if (![[self.signedPreKeyStore allKeys] containsObject:[NSNumber numberWithInt:signedPreKeyId]]) {
@throw [NSException exceptionWithName:InvalidKeyIdException reason:@"No such signedprekeyrecord" userInfo:nil];
}
return [self.signedPreKeyStore objectForKey:[NSNumber numberWithInt:signedPreKeyId]];
}
- (nullable SignedPreKeyRecord *)loadSignedPrekeyOrNil:(int)signedPreKeyId
{
if ([self containsSignedPreKey:signedPreKeyId]) {
return [self loadSignedPrekey:signedPreKeyId];
} else {
return nil;
}
}
- (NSArray<SignedPreKeyRecord *> *)loadSignedPreKeys
{
NSMutableArray *results = [NSMutableArray array];
for (SignedPreKeyRecord *signedPrekey in [self.signedPreKeyStore allValues]) {
[results addObject:signedPrekey];
}
return results;
}
- (void)storeSignedPreKey:(int)signedPreKeyId signedPreKeyRecord:(SignedPreKeyRecord *)signedPreKeyRecord{
[self.signedPreKeyStore setObject:signedPreKeyRecord forKey:[NSNumber numberWithInteger:signedPreKeyId]];
}
- (BOOL)containsSignedPreKey:(int)signedPreKeyId{
if ([[self.signedPreKeyStore allKeys] containsObject:[NSNumber numberWithInteger:signedPreKeyId]]) {
return TRUE;
}
return FALSE;
}
- (void)removeSignedPreKey:(int)signedPrekeyId{
[self.signedPreKeyStore removeObjectForKey:[NSNumber numberWithInteger:signedPrekeyId]];
}
# pragma mark PreKey Store
- (PreKeyRecord *)loadPreKey:(int)preKeyId{
if (![[self.preKeyStore allKeys] containsObject:[NSNumber numberWithInt:preKeyId]]) {
@throw [NSException exceptionWithName:InvalidKeyIdException reason:@"No such signedprekeyrecord" userInfo:nil];
}
return [self.preKeyStore objectForKey:[NSNumber numberWithInt:preKeyId]];
}
- (NSArray *)loadPreKeys{
NSMutableArray *results = [NSMutableArray array];
for (PreKeyRecord *prekey in [self.preKeyStore allValues]) {
[results addObject:prekey];
}
return results;
}
- (void)storePreKey:(int)preKeyId preKeyRecord:(PreKeyRecord *)record{
[self.preKeyStore setObject:record forKey:[NSNumber numberWithInt:preKeyId]];
}
- (BOOL)containsPreKey:(int)preKeyId{
if ([[self.preKeyStore allKeys] containsObject:[NSNumber numberWithInteger:preKeyId]]) {
return TRUE;
}
return FALSE;
}
- (void)removePreKey:(int)preKeyId{
[self.preKeyStore removeObjectForKey:[NSNumber numberWithInt:preKeyId]];
}
# pragma mark IdentityKeyStore
- (nullable ECKeyPair *)identityKeyPair
{
return __identityKeyPair;
}
- (int)localRegistrationId{
return __localRegistrationId;
}
- (BOOL)saveRemoteIdentity:(NSData *)identityKey recipientId:(NSString *)recipientId
{
NSData *existingKey = [self.trustedKeys objectForKey:recipientId];
if ([existingKey isEqualToData:existingKey]) {
return NO;
}
[self.trustedKeys setObject:identityKey forKey:recipientId];
return YES;
}
- (BOOL)isTrustedIdentityKey:(NSData *)identityKey
recipientId:(NSString *)recipientId
direction:(TSMessageDirection)direction
{
NSData *data = [self.trustedKeys objectForKey:recipientId];
if (!data) {
// Trust on first use
return YES;
}
switch (direction) {
case TSMessageDirectionIncoming:
return YES;
case TSMessageDirectionOutgoing:
// In a real implementation you may wish to ensure the use has been properly notified of any
// recent identity change before sending outgoing messages.
return [data isEqualToData:identityKey];
case TSMessageDirectionUnknown:
NSAssert(NO, @"unknown message direction");
return NO;
}
}
# pragma mark Session Store
-(SessionRecord*)loadSession:(NSString*)contactIdentifier deviceId:(int)deviceId{
SessionRecord *sessionRecord = [[self deviceSessionRecordsForContactIdentifier:contactIdentifier] objectForKey:[NSNumber numberWithInteger:deviceId]];
if (!sessionRecord) {
sessionRecord = [SessionRecord new];
}
return sessionRecord;
}
- (NSArray*)subDevicesSessions:(NSString*)contactIdentifier{
return [[self deviceSessionRecordsForContactIdentifier:contactIdentifier] allKeys];
}
- (NSMutableDictionary *)deviceSessionRecordsForContactIdentifier:(NSString *)contactIdentifier
{
return [self.sessionRecords objectForKey:contactIdentifier];
}
- (void)storeSession:(NSString*)contactIdentifier deviceId:(int)deviceId session:(SessionRecord *)session{
NSAssert(session, @"Session can't be nil");
NSMutableDictionary *deviceSessions = self.sessionRecords[contactIdentifier];
if (!deviceSessions) {
deviceSessions = [NSMutableDictionary new];
}
deviceSessions[@(deviceId)] = session;
self.sessionRecords[contactIdentifier] = deviceSessions;
}
- (BOOL)containsSession:(NSString*)contactIdentifier deviceId:(int)deviceId{
if ([[self.sessionRecords objectForKey:contactIdentifier] objectForKey:[NSNumber numberWithInt:deviceId]]){
return YES;
}
return NO;
}
- (void)deleteSessionForContact:(NSString *)contactIdentifier deviceId:(int)deviceId
{
NSMutableDictionary<NSNumber *, SessionRecord *> *sessions =
[self deviceSessionRecordsForContactIdentifier:contactIdentifier];
[sessions removeObjectForKey:@(deviceId)];
}
- (void)deleteAllSessionsForContact:(NSString *)contactIdentifier
{
[self.sessionRecords removeObjectForKey:contactIdentifier];
}
@end
NS_ASSUME_NONNULL_END

View File

@ -1,16 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import XCTest
// Cocoapods-generated test targets (like this one)
// fail to link if:
//
// * They only contain Obj-C tests.
// * They depend on pods that use Swift.
//
// The work around is to add (this) empty swift file
// to our test target.
//
// See: https://github.com/CocoaPods/CocoaPods/issues/7170

View File

@ -0,0 +1,17 @@
//
// AxolotlKit_Tests.m
// AxolotlKit Tests
//
// Created by Frederic Jacobs on 21/07/14.
// Copyright (c) 2014 Frederic Jacobs. All rights reserved.
//
#import <XCTest/XCTest.h>
@interface AxolotlKit_Tests : XCTestCase
@end
@implementation AxolotlKit_Tests
@end

View File

@ -1,11 +1,13 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "ECKeyPair+ECKeyPairTesting.h"
#import <Curve25519Kit/Curve25519.h>
#import <Curve25519Kit/Ed25519.h>
#import <XCTest/XCTest.h>
@interface ECCTests : XCTestCase
@ -73,15 +75,13 @@
(Byte) 0xe6, (Byte) 0x29};
NSData *sharedSecret = [NSData dataWithBytes:sharedBytes length:32];
ECKeyPair *aliceKeyPair = [ECKeyPair throws_keyPairWithPrivateKey:alicePrivateKey publicKey:alicePublicKey];
ECKeyPair *bobKeyPair = [ECKeyPair throws_keyPairWithPrivateKey:bobPrivateKey publicKey:bobPublicKey];
NSData *aliceShared =
[Curve25519 throws_generateSharedSecretFromPublicKey:[bobKeyPair publicKey] andKeyPair:aliceKeyPair];
NSData *bobShared =
[Curve25519 throws_generateSharedSecretFromPublicKey:[aliceKeyPair publicKey] andKeyPair:bobKeyPair];
ECKeyPair *aliceKeyPair = [ECKeyPair keyPairWithPrivateKey:alicePrivateKey publicKey:alicePublicKey];
ECKeyPair *bobKeyPair = [ECKeyPair keyPairWithPrivateKey:bobPrivateKey publicKey:bobPublicKey];
NSData *aliceShared = [Curve25519 generateSharedSecretFromPublicKey:[bobKeyPair publicKey] andKeyPair:aliceKeyPair];
NSData *bobShared = [Curve25519 generateSharedSecretFromPublicKey:[aliceKeyPair publicKey] andKeyPair:bobKeyPair];
XCTAssert([aliceShared isEqualToData:sharedSecret], @"Alice's shared secret is equal to the expected one.");
XCTAssert([bobShared isEqualToData:sharedSecret], @"Bob's shared secret is equal to the expected one.");
}
@ -90,11 +90,8 @@
for (int i=0;i<100;i++) {
ECKeyPair *aliceKeyPair = [Curve25519 generateKeyPair];
ECKeyPair *bobKeyPair = [Curve25519 generateKeyPair];
XCTAssert([[Curve25519 throws_generateSharedSecretFromPublicKey:[aliceKeyPair publicKey] andKeyPair:bobKeyPair]
isEqualToData:[Curve25519 throws_generateSharedSecretFromPublicKey:[bobKeyPair publicKey]
andKeyPair:aliceKeyPair]],
@"Randomly generated keypairs produce same shared secret.");
XCTAssert([[Curve25519 generateSharedSecretFromPublicKey:[aliceKeyPair publicKey] andKeyPair:bobKeyPair] isEqualToData:[Curve25519 generateSharedSecretFromPublicKey:[bobKeyPair publicKey] andKeyPair:aliceKeyPair]], @"Randomly generated keypairs produce same shared secret.");
}
}
@ -143,11 +140,11 @@
NSData *ephemPublic = [NSData dataWithBytes:aliceEphemeralPublic length:33];
NSData *signature = [NSData dataWithBytes:aliceSignature length:ECCSignatureLength];
if (![Ed25519 throws_verifySignature:signature publicKey:alicePublic data:ephemPublic]) {
if (![Ed25519 verifySignature:signature publicKey:alicePublic data:ephemPublic]) {
XCTAssert(NO, @"Sig verification failed!");
}
for (int i=0;i<[signature length];i++) {
NSMutableData *modifiedSignature = [signature mutableCopy];
@ -159,8 +156,8 @@
replacedByte ^= 0x01;
[modifiedSignature replaceBytesInRange:NSMakeRange(i, 1) withBytes:&replacedByte length:1];
if ([Ed25519 throws_verifySignature:modifiedSignature publicKey:alicePublic data:ephemPublic]) {
if ([Ed25519 verifySignature:modifiedSignature publicKey:alicePublic data:ephemPublic]) {
XCTAssert(NO, @"Modified signature shouldn't be verified correctly");
}
}

View File

@ -1,9 +1,14 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// HKDFTest.m
//
//
// Created by Frederic Jacobs on 23/09/14.
//
//
#import <HKDFKit/HKDFKit.h>
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import <HKDFKit/HKDFKit.h>
@interface HKDFTest : XCTestCase
@ -40,7 +45,7 @@
NSData *okmData = [NSData dataWithBytes:okm length:42];
NSData *actualOutput = [HKDFKit throws_deriveKey:ikmData info:infoData salt:saltData outputSize:42];
NSData *actualOutput = [HKDFKit deriveKey:ikmData info:infoData salt:saltData outputSize:42];
XCTAssert([okmData isEqualToData:actualOutput], @"HKDF output matches test vector");
}
@ -122,7 +127,7 @@
NSData *okmData = [NSData dataWithBytes:okm length:82];
NSData *actualOutput = [HKDFKit throws_deriveKey:ikmData info:infoData salt:saltData outputSize:82];
NSData *actualOutput = [HKDFKit deriveKey:ikmData info:infoData salt:saltData outputSize:82];
XCTAssert([actualOutput isEqualToData:okmData], @"HKDF output matches long test vector");
}

View File

@ -5,7 +5,6 @@
#import <XCTest/XCTest.h>
#import <AxolotlKit/PreKeyBundle.h>
#import <AxolotlKit/NSData+keyVersionByte.h>
#import <Curve25519Kit/Curve25519.h>
@interface PreKeyBundleTests : XCTestCase
@ -28,11 +27,11 @@
PreKeyBundle *bundle = [[PreKeyBundle alloc] initWithRegistrationId:1
deviceId:2
preKeyId:3
preKeyPublic:[Curve25519 generateKeyPair].publicKey.prependKeyType
signedPreKeyPublic:[Curve25519 generateKeyPair].publicKey.prependKeyType
preKeyPublic:[Curve25519 generateKeyPair].publicKey
signedPreKeyPublic:[Curve25519 generateKeyPair].publicKey
signedPreKeyId:4
signedPreKeySignature:[Curve25519 generateKeyPair].publicKey
identityKey:[Curve25519 generateKeyPair].publicKey.prependKeyType];
identityKey:[Curve25519 generateKeyPair].publicKey];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:bundle];

View File

@ -1,11 +1,12 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import <AxolotlKit/AxolotlKit-Swift.h>
#import <XCTest/XCTest.h>
#import <AxolotlKit/PreKeyWhisperMessage.h>
#import <AxolotlKit/WhisperMessage.h>
#import <XCTest/XCTest.h>
#import <AxolotlKit/WhisperTextProtocol.pb.h>
@interface ProtobuffsTests : XCTestCase
@ -28,21 +29,18 @@
NSData *cipherText = [@"CipherText" dataUsingEncoding:NSUTF8StringEncoding];
int counter = 2;
int previousCounter = 1;
SPKProtoTSProtoWhisperMessageBuilder *builder =
[SPKProtoTSProtoWhisperMessage builderWithRatchetKey:ratchetKey
counter:counter
ciphertext:cipherText];
[builder setPreviousCounter:previousCounter];
SPKProtoTSProtoWhisperMessage *message = [builder buildIgnoringErrors];
NSData *serializedMessage = [message serializedDataIgnoringErrors];
NSError *error;
SPKProtoTSProtoWhisperMessage *_Nullable deserialized =
[SPKProtoTSProtoWhisperMessage parseData:serializedMessage error:&error];
XCTAssertNotNil(deserialized);
XCTAssertNil(error);
TSProtoWhisperMessage *helloMessage = [[[[[[[TSProtoWhisperMessage builder]
setCounter:1]
setRatchetKey:ratchetKey]
setCiphertext:cipherText]
setCounter:counter]
setPreviousCounter:previousCounter] build];
NSData *serializedMessage = [helloMessage data];
TSProtoWhisperMessage *deserialized = [TSProtoWhisperMessage parseFromData:serializedMessage];
XCTAssert(deserialized.counter == counter);
XCTAssert(deserialized.previousCounter == previousCounter);
XCTAssert([deserialized.ratchetKey isEqualToData:ratchetKey]);

View File

@ -1,19 +1,22 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "ECKeyPair+ECKeyPairTesting.h"
#import <AxolotlKit/AliceAxolotlParameters.h>
#import <AxolotlKit/BobAxolotlParameters.h>
#import <AxolotlKit/ChainKey.h>
#import <AxolotlKit/RatchetingSession.h>
#import <AxolotlKit/SPKMockProtocolStore.h>
#import <AxolotlKit/SessionCipher.h>
#import <AxolotlKit/SessionRecord.h>
#import <AxolotlKit/SessionState.h>
#import <XCTest/XCTest.h>
#import <Curve25519Kit/Curve25519.h>
#import <Curve25519Kit/Ed25519.h>
#import <XCTest/XCTest.h>
#import "AxolotlInMemoryStore.h"
#import "AliceAxolotlParameters.h"
#import "BobAxolotlParameters.h"
#import "SessionCipher.h"
#import "SessionState.h"
#import "RatchetingSession.h"
#import "SessionRecord.h"
#import "ChainKey.h"
#import "ECKeyPair+ECKeyPairTesting.h"
@interface RatchetingSessionTest : XCTestCase
@ -296,27 +299,22 @@
(Byte) 0x8D, (Byte) 0xF7, (Byte) 0x22, (Byte) 0xDC,
(Byte) 0x22, (Byte) 0x76, (Byte) 0xC3, (Byte) 0xA6};
NSData *aliceCipherTextData = [NSData dataWithBytes:aliceCipherText length:32];
ECKeyPair *aliceIdentityKey =
[ECKeyPair throws_keyPairWithPrivateKey:aliceIdentityPrivateKeyData publicKey:aliceIdentityPublicKeyData];
ECKeyPair *bobIdentityKey =
[ECKeyPair throws_keyPairWithPrivateKey:bobIdentityPrivateKeyData publicKey:bobIdentityPublicKeyData];
ECKeyPair *aliceBaseKey =
[ECKeyPair throws_keyPairWithPrivateKey:aliceBasePrivateKeyData publicKey:aliceBasePublicKeyData];
ECKeyPair *bobBaseKey =
[ECKeyPair throws_keyPairWithPrivateKey:bobBasePrivateKeyData publicKey:bobBasePublicKeyData];
ECKeyPair *aliceSendingRatchet =
[ECKeyPair throws_keyPairWithPrivateKey:aliceSendingRatchetPrivateData publicKey:aliceSendingRatchetPublicData];
ECKeyPair *aliceIdentityKey = [ECKeyPair keyPairWithPrivateKey:aliceIdentityPrivateKeyData publicKey:aliceIdentityPublicKeyData];
ECKeyPair *bobIdentityKey = [ECKeyPair keyPairWithPrivateKey:bobIdentityPrivateKeyData publicKey:bobIdentityPublicKeyData];
ECKeyPair *aliceBaseKey = [ECKeyPair keyPairWithPrivateKey:aliceBasePrivateKeyData publicKey:aliceBasePublicKeyData];
ECKeyPair *bobBaseKey = [ECKeyPair keyPairWithPrivateKey:bobBasePrivateKeyData publicKey:bobBasePublicKeyData];
ECKeyPair *aliceSendingRatchet = [ECKeyPair keyPairWithPrivateKey:aliceSendingRatchetPrivateData publicKey:aliceSendingRatchetPublicData];
// ---
SPKMockProtocolStore *aliceStore = [SPKMockProtocolStore new];
SPKMockProtocolStore *bobStore = [SPKMockProtocolStore new];
AxolotlInMemoryStore *aliceStore = [AxolotlInMemoryStore new];
AxolotlInMemoryStore *bobStore = [AxolotlInMemoryStore new];
SessionRecord *aliceSessionRecord = [SessionRecord new];
SessionRecord *bobSessionRecord = [SessionRecord new];
@ -324,16 +322,11 @@
AliceAxolotlParameters *aliceAxolotlParams = [[AliceAxolotlParameters alloc] initWithIdentityKey:aliceIdentityKey theirIdentityKey:bobIdentityKey.publicKey ourBaseKey:aliceBaseKey theirSignedPreKey:bobBaseKey.publicKey theirOneTimePreKey:nil theirRatchetKey:bobBaseKey.publicKey];
BobAxolotlParameters *bobAxolotlParams = [[BobAxolotlParameters alloc] initWithMyIdentityKeyPair:bobIdentityKey theirIdentityKey:aliceIdentityKey.publicKey ourSignedPrekey:bobBaseKey ourRatchetKey:bobBaseKey ourOneTimePrekey:nil theirBaseKey:aliceBaseKey.publicKey];
[RatchetingSession throws_initializeSession:aliceSessionRecord.sessionState
sessionVersion:3
AliceParameters:aliceAxolotlParams
senderRatchet:aliceSendingRatchet];
[RatchetingSession throws_initializeSession:bobSessionRecord.sessionState
sessionVersion:3
BobParameters:bobAxolotlParams];
[RatchetingSession initializeSession:aliceSessionRecord.sessionState sessionVersion:3 AliceParameters:aliceAxolotlParams senderRatchet:aliceSendingRatchet];
[RatchetingSession initializeSession:bobSessionRecord.sessionState sessionVersion:3 BobParameters:bobAxolotlParams];
NSString *aliceIdentifier = @"+483294823482";
NSString *bobIdentifier = @"+389424728942";
@ -341,45 +334,42 @@
XCTAssert([[@"This is a plaintext message." dataUsingEncoding:NSUTF8StringEncoding] isEqualToData:alicePlaintextData], @"Encoding is not correct");
XCTAssert([aliceSessionRecord.sessionState.rootKey.keyData isEqualToData:aliceSessionRecordRootKeyData]);
XCTAssert([aliceSessionRecord.sessionState.senderChainKey.key isEqualToData:aliceSendingChainKeyData]);
XCTAssert([aliceSendingCipherKeyData
isEqualToData:aliceSessionRecord.sessionState.senderChainKey.throws_messageKeys.cipherKey]);
XCTAssert(
[aliceSendingIVKeyData isEqualToData:aliceSessionRecord.sessionState.senderChainKey.throws_messageKeys.iv]);
XCTAssert([aliceSendingMacKeyData
isEqualToData:aliceSessionRecord.sessionState.senderChainKey.throws_messageKeys.macKey]);
[aliceStore storeSession:bobIdentifier deviceId:1 session:aliceSessionRecord protocolContext:nil];
XCTAssert([aliceSendingCipherKeyData isEqualToData:aliceSessionRecord.sessionState.senderChainKey.messageKeys.cipherKey]);
XCTAssert([aliceSendingIVKeyData isEqualToData:aliceSessionRecord.sessionState.senderChainKey.messageKeys.iv]);
XCTAssert([aliceSendingMacKeyData isEqualToData:aliceSessionRecord.sessionState.senderChainKey.messageKeys.macKey]);
[aliceStore storeSession:bobIdentifier deviceId:1 session:aliceSessionRecord];
SessionCipher *aliceSessionCipher = [[SessionCipher alloc] initWithAxolotlStore:aliceStore recipientId:bobIdentifier deviceId:1];
WhisperMessage *message = [aliceSessionCipher throws_encryptMessage:alicePlaintextData protocolContext:nil];
WhisperMessage *message = [aliceSessionCipher encryptMessage:alicePlaintextData];
XCTAssert([aliceCipherTextData isEqualToData:message.cipherText]);
// Logging's Bob's Session initialization and first message decryption
XCTAssert([bobRootKeyData isEqualToData:bobSessionRecord.sessionState.rootKey.keyData]);
[bobStore storeSession:aliceIdentifier deviceId:1 session:bobSessionRecord protocolContext:nil];
[bobStore storeSession:aliceIdentifier deviceId:1 session:bobSessionRecord];
SessionCipher *bobSessionCipher = [[SessionCipher alloc] initWithAxolotlStore:bobStore recipientId:aliceIdentifier deviceId:1];
NSData *plainData = [bobSessionCipher throws_decrypt:message protocolContext:nil];
NSData *plainData = [bobSessionCipher decrypt:message];
XCTAssert([plainData isEqualToData:alicePlaintextData]);
for (int i = 0; i<100; i++) {
NSData *message = [[NSString stringWithFormat:@"Message: %i", i] dataUsingEncoding:NSUTF8StringEncoding];
WhisperMessage *encrypted = [aliceSessionCipher throws_encryptMessage:message protocolContext:nil];
XCTAssert([message isEqualToData:[bobSessionCipher throws_decrypt:encrypted protocolContext:nil]]);
WhisperMessage *encrypted = [aliceSessionCipher encryptMessage:message];
XCTAssert([message isEqualToData:[bobSessionCipher decrypt:encrypted]]);
}
for (int i = 0; i<100; i++) {
NSData *message = [[NSString stringWithFormat:@"Message: %i", i] dataUsingEncoding:NSUTF8StringEncoding];
WhisperMessage *encrypted = [bobSessionCipher throws_encryptMessage:message protocolContext:nil];
XCTAssert([message isEqualToData:[aliceSessionCipher throws_decrypt:encrypted protocolContext:nil]]);
WhisperMessage *encrypted = [bobSessionCipher encryptMessage:message];
XCTAssert([message isEqualToData:[aliceSessionCipher decrypt:encrypted]]);
}
NSMutableArray *plainTexts = [NSMutableArray new];
@ -388,12 +378,11 @@
for (int i = 0 ; i < 100; i++) {
NSData *message = [[NSString stringWithFormat:@"Message: %i", i] dataUsingEncoding:NSUTF8StringEncoding];
[plainTexts addObject:message];
[cipherMessages addObject:[bobSessionCipher throws_encryptMessage:message protocolContext:nil]];
[cipherMessages addObject:[bobSessionCipher encryptMessage:message]];
}
for (int i = 0; i < plainTexts.count; i++) {
XCTAssert([[aliceSessionCipher throws_decrypt:[cipherMessages objectAtIndex:i] protocolContext:nil]
isEqualToData:[plainTexts objectAtIndex:i]]);
XCTAssert([[aliceSessionCipher decrypt:[cipherMessages objectAtIndex:i]] isEqualToData:[plainTexts objectAtIndex:i]]);
}
}
@ -658,27 +647,22 @@
(Byte) 0x8D, (Byte) 0xF7, (Byte) 0x22, (Byte) 0xDC,
(Byte) 0x22, (Byte) 0x76, (Byte) 0xC3, (Byte) 0xA6};
NSData *aliceCipherTextData = [NSData dataWithBytes:aliceCipherText length:32];
ECKeyPair *aliceIdentityKey =
[ECKeyPair throws_keyPairWithPrivateKey:aliceIdentityPrivateKeyData publicKey:aliceIdentityPublicKeyData];
ECKeyPair *bobIdentityKey =
[ECKeyPair throws_keyPairWithPrivateKey:bobIdentityPrivateKeyData publicKey:bobIdentityPublicKeyData];
ECKeyPair *aliceBaseKey =
[ECKeyPair throws_keyPairWithPrivateKey:aliceBasePrivateKeyData publicKey:aliceBasePublicKeyData];
ECKeyPair *bobBaseKey =
[ECKeyPair throws_keyPairWithPrivateKey:bobBasePrivateKeyData publicKey:bobBasePublicKeyData];
ECKeyPair *aliceSendingRatchet =
[ECKeyPair throws_keyPairWithPrivateKey:aliceSendingRatchetPrivateData publicKey:aliceSendingRatchetPublicData];
ECKeyPair *aliceIdentityKey = [ECKeyPair keyPairWithPrivateKey:aliceIdentityPrivateKeyData publicKey:aliceIdentityPublicKeyData];
ECKeyPair *bobIdentityKey = [ECKeyPair keyPairWithPrivateKey:bobIdentityPrivateKeyData publicKey:bobIdentityPublicKeyData];
ECKeyPair *aliceBaseKey = [ECKeyPair keyPairWithPrivateKey:aliceBasePrivateKeyData publicKey:aliceBasePublicKeyData];
ECKeyPair *bobBaseKey = [ECKeyPair keyPairWithPrivateKey:bobBasePrivateKeyData publicKey:bobBasePublicKeyData];
ECKeyPair *aliceSendingRatchet = [ECKeyPair keyPairWithPrivateKey:aliceSendingRatchetPrivateData publicKey:aliceSendingRatchetPublicData];
// ---
SPKMockProtocolStore *aliceStore = [SPKMockProtocolStore new];
SPKMockProtocolStore *bobStore = [SPKMockProtocolStore new];
AxolotlInMemoryStore *aliceStore = [AxolotlInMemoryStore new];
AxolotlInMemoryStore *bobStore = [AxolotlInMemoryStore new];
SessionRecord *aliceSessionRecord = [SessionRecord new];
SessionRecord *bobSessionRecord = [SessionRecord new];
@ -686,16 +670,11 @@
AliceAxolotlParameters *aliceAxolotlParams = [[AliceAxolotlParameters alloc] initWithIdentityKey:aliceIdentityKey theirIdentityKey:bobIdentityKey.publicKey ourBaseKey:aliceBaseKey theirSignedPreKey:bobBaseKey.publicKey theirOneTimePreKey:nil theirRatchetKey:bobBaseKey.publicKey];
BobAxolotlParameters *bobAxolotlParams = [[BobAxolotlParameters alloc] initWithMyIdentityKeyPair:bobIdentityKey theirIdentityKey:aliceIdentityKey.publicKey ourSignedPrekey:bobBaseKey ourRatchetKey:bobBaseKey ourOneTimePrekey:nil theirBaseKey:aliceBaseKey.publicKey];
[RatchetingSession throws_initializeSession:aliceSessionRecord.sessionState
sessionVersion:3
AliceParameters:aliceAxolotlParams
senderRatchet:aliceSendingRatchet];
[RatchetingSession throws_initializeSession:bobSessionRecord.sessionState
sessionVersion:3
BobParameters:bobAxolotlParams];
[RatchetingSession initializeSession:aliceSessionRecord.sessionState sessionVersion:3 AliceParameters:aliceAxolotlParams senderRatchet:aliceSendingRatchet];
[RatchetingSession initializeSession:bobSessionRecord.sessionState sessionVersion:3 BobParameters:bobAxolotlParams];
NSString *aliceIdentifier = @"+483294823482";
NSString *bobIdentifier = @"+389424728942";
@ -703,29 +682,26 @@
XCTAssert([[@"This is a plaintext message." dataUsingEncoding:NSUTF8StringEncoding] isEqualToData:alicePlaintextData], @"Encoding is not correct");
XCTAssert([aliceSessionRecord.sessionState.rootKey.keyData isEqualToData:aliceSessionRecordRootKeyData]);
XCTAssert([aliceSessionRecord.sessionState.senderChainKey.key isEqualToData:aliceSendingChainKeyData]);
XCTAssert([aliceSendingCipherKeyData
isEqualToData:aliceSessionRecord.sessionState.senderChainKey.throws_messageKeys.cipherKey]);
XCTAssert(
[aliceSendingIVKeyData isEqualToData:aliceSessionRecord.sessionState.senderChainKey.throws_messageKeys.iv]);
XCTAssert([aliceSendingMacKeyData
isEqualToData:aliceSessionRecord.sessionState.senderChainKey.throws_messageKeys.macKey]);
[aliceStore storeSession:bobIdentifier deviceId:1 session:aliceSessionRecord protocolContext:nil];
XCTAssert([aliceSendingCipherKeyData isEqualToData:aliceSessionRecord.sessionState.senderChainKey.messageKeys.cipherKey]);
XCTAssert([aliceSendingIVKeyData isEqualToData:aliceSessionRecord.sessionState.senderChainKey.messageKeys.iv]);
XCTAssert([aliceSendingMacKeyData isEqualToData:aliceSessionRecord.sessionState.senderChainKey.messageKeys.macKey]);
[aliceStore storeSession:bobIdentifier deviceId:1 session:aliceSessionRecord];
SessionCipher *aliceSessionCipher = [[SessionCipher alloc] initWithAxolotlStore:aliceStore recipientId:bobIdentifier deviceId:1];
WhisperMessage *message = [aliceSessionCipher throws_encryptMessage:alicePlaintextData protocolContext:nil];
WhisperMessage *message = [aliceSessionCipher encryptMessage:alicePlaintextData];
XCTAssert([aliceCipherTextData isEqualToData:message.cipherText]);
// Logging's Bob's Session initialization and first message decryption
XCTAssert([bobRootKeyData isEqualToData:bobSessionRecord.sessionState.rootKey.keyData]);
[bobStore storeSession:aliceIdentifier deviceId:1 session:bobSessionRecord protocolContext:nil];
[bobStore storeSession:aliceIdentifier deviceId:1 session:bobSessionRecord];
SessionCipher *bobSessionCipher = [[SessionCipher alloc] initWithAxolotlStore:bobStore recipientId:aliceIdentifier deviceId:1];
NSData *plainData = [bobSessionCipher throws_decrypt:message protocolContext:nil];
NSData *plainData = [bobSessionCipher decrypt:message];
XCTAssert([plainData isEqualToData:alicePlaintextData]);
@ -735,12 +711,11 @@
for (int i = 0 ; i < 30; i++) {
NSData *message = [[NSString stringWithFormat:@"Message: %i", i] dataUsingEncoding:NSUTF8StringEncoding];
[plainTexts addObject:message];
[cipherMessages addObject:[bobSessionCipher throws_encryptMessage:message protocolContext:nil]];
[cipherMessages addObject:[bobSessionCipher encryptMessage:message]];
}
for (NSUInteger i = plainTexts.count-1; i > 0; i--) {
XCTAssert([[aliceSessionCipher throws_decrypt:[cipherMessages objectAtIndex:i] protocolContext:nil]
isEqualToData:[plainTexts objectAtIndex:i]]);
XCTAssert([[aliceSessionCipher decrypt:[cipherMessages objectAtIndex:i]] isEqualToData:[plainTexts objectAtIndex:i]]);
}
}

View File

@ -1,30 +1,25 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "AxolotlInMemoryStore.h"
#import <AxolotlKit/AxolotlExceptions.h>
#import <AxolotlKit/NSData+keyVersionByte.h>
#import <AxolotlKit/SPKMockProtocolStore.h>
#import <AxolotlKit/SessionBuilder.h>
#import <AxolotlKit/SessionCipher.h>
#import <Curve25519Kit/Ed25519.h>
#import <SignalCoreKit/NSData+OWS.h>
#import <XCTest/XCTest.h>
@interface PreKeyWhisperMessage ()
#import <Curve25519Kit/Ed25519.h>
@interface PreKeyWhisperMessage ()
@property (nonatomic, readwrite) NSData *identityKey;
@property (nonatomic, readwrite) NSData *baseKey;
@end
#pragma mark -
@interface SessionBuilderTests : XCTestCase
@end
#pragma mark -
@implementation SessionBuilderTests
@ -47,57 +42,46 @@
NSString *BOB_RECIPIENT_ID = @"+3828923892";
NSString *ALICE_RECIPIENT_ID = @"alice@gmail.com";
SPKMockProtocolStore *aliceStore = [SPKMockProtocolStore new];
AxolotlInMemoryStore *aliceStore = [AxolotlInMemoryStore new];
SessionBuilder *aliceSessionBuilder = [[SessionBuilder alloc] initWithAxolotlStore:aliceStore recipientId:BOB_RECIPIENT_ID deviceId:1];
SPKMockProtocolStore *bobStore = [SPKMockProtocolStore new];
AxolotlInMemoryStore *bobStore = [AxolotlInMemoryStore new];
ECKeyPair *bobPreKeyPair = [Curve25519 generateKeyPair];
ECKeyPair *bobSignedPreKeyPair = [Curve25519 generateKeyPair];
NSData *bobSignedPreKeySignature =
[Ed25519 throws_sign:bobSignedPreKeyPair.publicKey.prependKeyType withKeyPair:[bobStore identityKeyPair:nil]];
PreKeyBundle *bobPreKey = [[PreKeyBundle alloc]initWithRegistrationId:[bobStore localRegistrationId:nil]
NSData *bobSignedPreKeySignature = [Ed25519 sign:bobSignedPreKeyPair.publicKey withKeyPair:bobStore.identityKeyPair];
PreKeyBundle *bobPreKey = [[PreKeyBundle alloc]initWithRegistrationId:bobStore.localRegistrationId
deviceId:1
preKeyId:31337
preKeyPublic:bobPreKeyPair.publicKey.prependKeyType
signedPreKeyPublic:bobSignedPreKeyPair.publicKey.prependKeyType
preKeyPublic:bobPreKeyPair.publicKey
signedPreKeyPublic:bobSignedPreKeyPair.publicKey
signedPreKeyId:22
signedPreKeySignature:bobSignedPreKeySignature
identityKey:[bobStore identityKeyPair:nil].publicKey.prependKeyType];
[aliceSessionBuilder throws_processPrekeyBundle:bobPreKey protocolContext:nil];
XCTAssert([aliceStore containsSession:BOB_RECIPIENT_ID deviceId:1 protocolContext:nil]);
XCTAssert([aliceStore loadSession:BOB_RECIPIENT_ID deviceId:1 protocolContext:nil].sessionState.version == 3);
identityKey:bobStore.identityKeyPair.publicKey];
[aliceSessionBuilder processPrekeyBundle:bobPreKey];
XCTAssert([aliceStore containsSession:BOB_RECIPIENT_ID deviceId:1]);
XCTAssert([aliceStore loadSession:BOB_RECIPIENT_ID deviceId:1].sessionState.version == 3);
NSString *originalMessage = @"Freedom is the right to tell people what they do not want to hear.";
SessionCipher *aliceSessionCipher = [[SessionCipher alloc] initWithAxolotlStore:aliceStore recipientId:BOB_RECIPIENT_ID deviceId:1];
WhisperMessage *outgoingMessage =
[aliceSessionCipher throws_encryptMessage:[originalMessage dataUsingEncoding:NSUTF8StringEncoding]
protocolContext:nil];
WhisperMessage *outgoingMessage = [aliceSessionCipher encryptMessage:[originalMessage dataUsingEncoding:NSUTF8StringEncoding]];
XCTAssert([outgoingMessage isKindOfClass:[PreKeyWhisperMessage class]], @"Message should be PreKey type");
PreKeyWhisperMessage *incomingMessage = (PreKeyWhisperMessage*)outgoingMessage;
[bobStore storePreKey:31337 preKeyRecord:[[PreKeyRecord alloc] initWithId:bobPreKey.preKeyId
keyPair:bobPreKeyPair
createdAt:[NSDate date]]
protocolContext:nil];
[bobStore storeSignedPreKey:22
signedPreKeyRecord:[[SignedPreKeyRecord alloc] initWithId:22
keyPair:bobSignedPreKeyPair
signature:bobSignedPreKeySignature
generatedAt:[NSDate date]]
protocolContext:nil];
[bobStore storePreKey:31337 preKeyRecord:[[PreKeyRecord alloc] initWithId:bobPreKey.preKeyId keyPair:bobPreKeyPair]];
[bobStore storeSignedPreKey:22 signedPreKeyRecord:[[SignedPreKeyRecord alloc] initWithId:22 keyPair:bobSignedPreKeyPair signature:bobSignedPreKeySignature generatedAt:[NSDate date]]];
SessionCipher *bobSessionCipher = [[SessionCipher alloc] initWithAxolotlStore:bobStore recipientId:ALICE_RECIPIENT_ID deviceId:1];
[bobSessionCipher throws_decrypt:incomingMessage protocolContext:nil];
XCTAssert([bobStore containsSession:ALICE_RECIPIENT_ID deviceId:1 protocolContext:nil]);
XCTAssert([bobStore loadSession:ALICE_RECIPIENT_ID deviceId:1 protocolContext:nil].sessionState.version == 3);
XCTAssert([bobStore loadSession:ALICE_RECIPIENT_ID deviceId:1 protocolContext:nil].sessionState.aliceBaseKey != nil);
}
[bobSessionCipher decrypt:incomingMessage];
XCTAssert([bobStore containsSession:ALICE_RECIPIENT_ID deviceId:1]);
XCTAssert([bobStore loadSession:ALICE_RECIPIENT_ID deviceId:1].sessionState.version == 3);
XCTAssert([bobStore loadSession:ALICE_RECIPIENT_ID deviceId:1].sessionState.aliceBaseKey != nil);
}
/**
* Tests the case where an attacker would send a new PreKeyWhisperMessage with another IdentityKey
@ -107,57 +91,53 @@
NSString *BOB_RECIPIENT_ID = @"+3828923892";
SPKMockProtocolStore *aliceStore = [SPKMockProtocolStore new];
AxolotlInMemoryStore *aliceStore = [AxolotlInMemoryStore new];
SessionBuilder *aliceSessionBuilder = [[SessionBuilder alloc] initWithAxolotlStore:aliceStore recipientId:BOB_RECIPIENT_ID deviceId:1];
SPKMockProtocolStore *bobStore = [SPKMockProtocolStore new];
AxolotlInMemoryStore *bobStore = [AxolotlInMemoryStore new];
ECKeyPair *bobIdentityKeyPair1 = [Curve25519 generateKeyPair];
ECKeyPair *bobPreKeyPair1 = [Curve25519 generateKeyPair];
ECKeyPair *bobSignedPreKeyPair1 = [Curve25519 generateKeyPair];
NSData *bobSignedPreKeySignature1 =
[Ed25519 throws_sign:bobSignedPreKeyPair1.publicKey.prependKeyType withKeyPair:bobIdentityKeyPair1];
NSData *bobSignedPreKeySignature1 = [Ed25519 sign:bobSignedPreKeyPair1.publicKey withKeyPair:bobIdentityKeyPair1];
PreKeyBundle *bobPreKey1 = [[PreKeyBundle alloc] initWithRegistrationId:[bobStore localRegistrationId:nil]
PreKeyBundle *bobPreKey1 = [[PreKeyBundle alloc] initWithRegistrationId:bobStore.localRegistrationId
deviceId:1
preKeyId:31337
preKeyPublic:bobPreKeyPair1.publicKey.prependKeyType
signedPreKeyPublic:bobSignedPreKeyPair1.publicKey.prependKeyType
preKeyPublic:bobPreKeyPair1.publicKey
signedPreKeyPublic:bobSignedPreKeyPair1.publicKey
signedPreKeyId:22
signedPreKeySignature:bobSignedPreKeySignature1
identityKey:bobIdentityKeyPair1.publicKey.prependKeyType];
identityKey:bobIdentityKeyPair1.publicKey];
[aliceSessionBuilder throws_processPrekeyBundle:bobPreKey1 protocolContext:nil];
[aliceSessionBuilder processPrekeyBundle:bobPreKey1];
XCTAssert([aliceStore containsSession:BOB_RECIPIENT_ID deviceId:1 protocolContext:nil]);
XCTAssert([aliceStore loadSession:BOB_RECIPIENT_ID deviceId:1 protocolContext:nil].sessionState.version == 3);
XCTAssert([aliceStore containsSession:BOB_RECIPIENT_ID deviceId:1]);
XCTAssert([aliceStore loadSession:BOB_RECIPIENT_ID deviceId:1].sessionState.version == 3);
NSString *messageText = @"Freedom is the right to tell people what they do not want to hear.";
SessionCipher *aliceSessionCipher = [[SessionCipher alloc] initWithAxolotlStore:aliceStore recipientId:BOB_RECIPIENT_ID deviceId:1];
WhisperMessage *outgoingMessage1 =
[aliceSessionCipher throws_encryptMessage:[messageText dataUsingEncoding:NSUTF8StringEncoding]
protocolContext:nil];
[aliceSessionCipher encryptMessage:[messageText dataUsingEncoding:NSUTF8StringEncoding]];
XCTAssert([outgoingMessage1 isKindOfClass:[PreKeyWhisperMessage class]], @"Message should be PreKey type");
ECKeyPair *bobIdentityKeyPair2 = [Curve25519 generateKeyPair];
ECKeyPair *bobPreKeyPair2 = [Curve25519 generateKeyPair];
ECKeyPair *bobSignedPreKeyPair2 = [Curve25519 generateKeyPair];
NSData *bobSignedPreKeySignature2 =
[Ed25519 throws_sign:bobSignedPreKeyPair2.publicKey.prependKeyType withKeyPair:bobIdentityKeyPair2];
NSData *bobSignedPreKeySignature2 = [Ed25519 sign:bobSignedPreKeyPair2.publicKey withKeyPair:bobIdentityKeyPair2];
PreKeyBundle *bobPreKey2 = [[PreKeyBundle alloc] initWithRegistrationId:[bobStore localRegistrationId:nil]
PreKeyBundle *bobPreKey2 = [[PreKeyBundle alloc] initWithRegistrationId:bobStore.localRegistrationId
deviceId:1
preKeyId:31337
preKeyPublic:bobPreKeyPair2.publicKey.prependKeyType
signedPreKeyPublic:bobSignedPreKeyPair2.publicKey.prependKeyType
preKeyPublic:bobPreKeyPair2.publicKey
signedPreKeyPublic:bobSignedPreKeyPair2.publicKey
signedPreKeyId:22
signedPreKeySignature:bobSignedPreKeySignature2
identityKey:bobIdentityKeyPair2.publicKey.prependKeyType];
identityKey:bobIdentityKeyPair2.publicKey];
XCTAssertThrowsSpecificNamed([aliceSessionBuilder throws_processPrekeyBundle:bobPreKey2 protocolContext:nil],
NSException,
UntrustedIdentityKeyException);
XCTAssertThrowsSpecificNamed(
[aliceSessionBuilder processPrekeyBundle:bobPreKey2], NSException, UntrustedIdentityKeyException);
}

View File

@ -1,28 +1,27 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import <AxolotlKit/AliceAxolotlParameters.h>
#import <AxolotlKit/BobAxolotlParameters.h>
#import <AxolotlKit/ChainKey.h>
#import <AxolotlKit/RatchetingSession.h>
#import <AxolotlKit/SPKMockProtocolStore.h>
#import <AxolotlKit/SessionBuilder.h>
#import <AxolotlKit/SessionCipher.h>
#import <AxolotlKit/SessionState.h>
#import <Curve25519Kit/Curve25519.h>
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
@interface SessionRecord (Private)
- (void)promoteState:(SessionState *)promotedState;
@end
#import "AliceAxolotlParameters.h"
#import "AxolotlInMemoryStore.h"
#import "BobAxolotlParameters.h"
#import "ChainKey.h"
#import "RatchetingSession.h"
#import "SessionBuilder.h"
#import "SessionCipher.h"
#import <Curve25519Kit/Curve25519.h>
#import "SessionState.h"
@interface SessionCipherTest : XCTestCase
@property (nonatomic, readonly) NSString *aliceIdentifier;
@property (nonatomic, readonly) NSString *bobIdentifier;
@property (nonatomic, readonly) SPKMockProtocolStore *aliceStore;
@property (nonatomic, readonly) SPKMockProtocolStore *bobStore;
@property (nonatomic, readonly) AxolotlInMemoryStore *aliceStore;
@property (nonatomic, readonly) AxolotlInMemoryStore *bobStore;
@end
@ -40,8 +39,8 @@
- (void)setUp {
[super setUp];
_aliceStore = [SPKMockProtocolStore new];
_bobStore = [SPKMockProtocolStore new];
_aliceStore = [AxolotlInMemoryStore new];
_bobStore = [AxolotlInMemoryStore new];
}
- (void)tearDown {
@ -53,10 +52,34 @@
SessionRecord *aliceSessionRecord = [SessionRecord new];
SessionRecord *bobSessionRecord = [SessionRecord new];
[self throws_sessionInitializationWithAliceSessionRecord:aliceSessionRecord bobSessionRecord:bobSessionRecord];
[self sessionInitializationWithAliceSessionRecord:aliceSessionRecord bobSessionRecord:bobSessionRecord];
[self runInteractionWithAliceRecord:aliceSessionRecord bobRecord:bobSessionRecord];
}
- (void)testBasicSessionCipherDispatchQueue {
SessionRecord *aliceSessionRecord = [SessionRecord new];
SessionRecord *bobSessionRecord = [SessionRecord new];
XCTestExpectation *expectation = [self expectationWithDescription:@"session cipher completed"];
dispatch_queue_t sessionCipherDispatchQueue = dispatch_queue_create("session cipher queue", DISPATCH_QUEUE_SERIAL);
[SessionCipher setSessionCipherDispatchQueue:sessionCipherDispatchQueue];
dispatch_async(sessionCipherDispatchQueue, ^{
[self sessionInitializationWithAliceSessionRecord:aliceSessionRecord bobSessionRecord:bobSessionRecord];
[self runInteractionWithAliceRecord:aliceSessionRecord bobRecord:bobSessionRecord];
[expectation fulfill];
});
[self waitForExpectationsWithTimeout:5.0 handler:^(NSError * _Nullable error) {
if (error) {
XCTFail(@"Expectation failed with error: %@", error);
}
}];
[SessionCipher setSessionCipherDispatchQueue:nil];
}
- (void)testPromotingOldSessionState
{
SessionRecord *aliceSessionRecord = [SessionRecord new];
@ -64,9 +87,9 @@
// 1.) Given Alice and Bob have initialized some session together
SessionState *initialSessionState = bobSessionRecord.sessionState;
[self throws_sessionInitializationWithAliceSessionRecord:aliceSessionRecord bobSessionRecord:bobSessionRecord];
[self sessionInitializationWithAliceSessionRecord:aliceSessionRecord bobSessionRecord:bobSessionRecord];
SessionRecord *activeSession = [self.bobStore loadSession:self.aliceIdentifier deviceId:1 protocolContext:nil];
SessionRecord *activeSession = [self.bobStore loadSession:self.aliceIdentifier deviceId:1];
XCTAssertNotNil(activeSession);
XCTAssertEqualObjects(initialSessionState, activeSession.sessionState);
@ -74,24 +97,23 @@
SessionState *newSessionState = [SessionState new];
[bobSessionRecord promoteState:newSessionState];
XCTAssertEqual(1, bobSessionRecord.previousSessionStates.count);
[self.bobStore storeSession:self.aliceIdentifier deviceId:1 session:bobSessionRecord protocolContext:nil];
[self.bobStore storeSession:self.aliceIdentifier deviceId:1 session:bobSessionRecord];
activeSession = [self.bobStore loadSession:self.aliceIdentifier deviceId:1 protocolContext:nil];
activeSession = [self.bobStore loadSession:self.aliceIdentifier deviceId:1];
XCTAssertNotNil(activeSession);
XCTAssertNotEqualObjects(initialSessionState, activeSession.sessionState);
XCTAssertEqualObjects(newSessionState, activeSession.sessionState);
// 3.) Bob should decrypt with initial session after receiving a message from that old session,
// but importantly *not* promote it to be the active session.
// 3.) Bob should promote back the initial session after receiving a message from that old session.
[self runInteractionWithAliceRecord:aliceSessionRecord bobRecord:bobSessionRecord];
XCTAssertNotEqualObjects(initialSessionState, activeSession.sessionState);
XCTAssertEqualObjects(newSessionState, activeSession.sessionState);
XCTAssertNotEqualObjects(newSessionState, activeSession.sessionState);
XCTAssertEqualObjects(initialSessionState, activeSession.sessionState);
XCTAssertEqual(1, bobSessionRecord.previousSessionStates.count);
XCTAssertEqual(0, aliceSessionRecord.previousSessionStates.count);
}
- (void)throws_sessionInitializationWithAliceSessionRecord:(SessionRecord *)aliceSessionRecord
bobSessionRecord:(SessionRecord *)bobSessionRecord
- (void)sessionInitializationWithAliceSessionRecord:(SessionRecord *)aliceSessionRecord
bobSessionRecord:(SessionRecord *)bobSessionRecord
{
SessionState *aliceSessionState = aliceSessionRecord.sessionState;
@ -107,16 +129,16 @@
AliceAxolotlParameters *aliceParams = [[AliceAxolotlParameters alloc] initWithIdentityKey:aliceIdentityKeyPair theirIdentityKey:[bobIdentityKeyPair publicKey] ourBaseKey:aliceBaseKey theirSignedPreKey:[bobBaseKey publicKey] theirOneTimePreKey:[bobOneTimePK publicKey] theirRatchetKey:[bobBaseKey publicKey]];
BobAxolotlParameters *bobParams = [[BobAxolotlParameters alloc] initWithMyIdentityKeyPair:bobIdentityKeyPair theirIdentityKey:[aliceIdentityKeyPair publicKey] ourSignedPrekey:bobBaseKey ourRatchetKey:bobBaseKey ourOneTimePrekey:bobOneTimePK theirBaseKey:[aliceBaseKey publicKey]];
[RatchetingSession initializeSession:bobSessionState sessionVersion:3 BobParameters:bobParams];
[RatchetingSession initializeSession:aliceSessionState sessionVersion:3 AliceParameters:aliceParams];
[RatchetingSession throws_initializeSession:bobSessionState sessionVersion:3 BobParameters:bobParams];
[self.aliceStore saveRemoteIdentity:bobIdentityKeyPair.publicKey recipientId:self.bobIdentifier];
[self.aliceStore storeSession:self.bobIdentifier deviceId:1 session:aliceSessionRecord];
[RatchetingSession throws_initializeSession:aliceSessionState sessionVersion:3 AliceParameters:aliceParams];
[self.aliceStore saveRemoteIdentity:bobIdentityKeyPair.publicKey recipientId:self.bobIdentifier protocolContext:nil];
[self.aliceStore storeSession:self.bobIdentifier deviceId:1 session:aliceSessionRecord protocolContext:nil];
[self.bobStore saveRemoteIdentity:aliceIdentityKeyPair.publicKey recipientId:self.aliceIdentifier protocolContext:nil];
[self.bobStore storeSession:self.aliceIdentifier deviceId:1 session:bobSessionRecord protocolContext:nil];
[self.bobStore saveRemoteIdentity:aliceIdentityKeyPair.publicKey recipientId:self.aliceIdentifier];
[self.bobStore storeSession:self.aliceIdentifier deviceId:1 session:bobSessionRecord];
XCTAssert([aliceSessionState.remoteIdentityKey isEqualToData:bobSessionState.localIdentityKey]);
}
@ -128,10 +150,10 @@
[[SessionCipher alloc] initWithAxolotlStore:self.bobStore recipientId:self.aliceIdentifier deviceId:1];
NSData *alicePlainText = [@"This is a plaintext message!" dataUsingEncoding:NSUTF8StringEncoding];
WhisperMessage *cipherText = [aliceSessionCipher throws_encryptMessage:alicePlainText protocolContext:nil];
NSData *bobPlaintext = [bobSessionCipher throws_decrypt:cipherText protocolContext:nil];
WhisperMessage *cipherText = [aliceSessionCipher encryptMessage:alicePlainText];
NSData *bobPlaintext = [bobSessionCipher decrypt:cipherText];
XCTAssert([bobPlaintext isEqualToData:alicePlainText]);
}

View File

@ -1,16 +1,15 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// ECKeyPair+ECKeyPairTesting.h
// AxolotlKit
//
// Created by Frederic Jacobs on 26/10/14.
// Copyright (c) 2014 Frederic Jacobs. All rights reserved.
//
#import "Curve25519.h"
NS_ASSUME_NONNULL_BEGIN
@interface ECKeyPair (ECKeyPairTesting)
+ (ECKeyPair *)throws_keyPairWithPrivateKey:(NSData *)privateKey
publicKey:(NSData *)publicKey NS_SWIFT_UNAVAILABLE("throws objc exceptions");
+(ECKeyPair*)keyPairWithPrivateKey:(NSData*)privateKey publicKey:(NSData*)publicKey;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,30 +1,30 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// ECKeyPair+ECKeyPairTesting.m
// AxolotlKit
//
// Created by Frederic Jacobs on 26/10/14.
// Copyright (c) 2014 Frederic Jacobs. All rights reserved.
//
#import "ECKeyPair+ECKeyPairTesting.h"
#import "NSData+keyVersionByte.h"
NS_ASSUME_NONNULL_BEGIN
@implementation ECKeyPair (testing)
+ (ECKeyPair *)throws_keyPairWithPrivateKey:(NSData *)privateKey publicKey:(NSData *)publicKey
{
+(ECKeyPair*)keyPairWithPrivateKey:(NSData*)privateKey publicKey:(NSData*)publicKey{
if (([publicKey length] == 33)) {
publicKey = [publicKey throws_removeKeyType];
publicKey = [publicKey removeKeyType];
}
if ([privateKey length] != ECCKeyLength && [publicKey length] != ECCKeyLength) {
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Public or Private key is not required size" userInfo:@{@"PrivateKey":privateKey, @"Public Key":publicKey}];
}
NSError *error;
ECKeyPair *_Nullable keyPairCopy = [[ECKeyPair alloc] initWithPublicKeyData:[publicKey copy] privateKeyData:[privateKey copy] error:&error];
OWSAssertDebug(error == nil && keyPairCopy != nil);
return keyPairCopy;
ECKeyPair *keyPair = [ECKeyPair new];
memcpy(keyPair->publicKey, [publicKey bytes], ECCKeyLength);
memcpy(keyPair->privateKey, [privateKey bytes], ECCKeyLength);
return keyPair;
}
@end
NS_ASSUME_NONNULL_END

View File

@ -1,9 +1,10 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import <AxolotlKit/WhisperMessage.h>
#import <Curve25519Kit/Curve25519.h>
#import <AxolotlKit/WhisperMessage.h>
#import <XCTest/XCTest.h>
@interface WhisperMessageSerialization : XCTestCase
@ -29,30 +30,17 @@
NSData *cipherText = [@"I'm not really ciphertext" dataUsingEncoding:NSUTF8StringEncoding];
ECKeyPair *senderIdentityKey = [Curve25519 generateKeyPair];
ECKeyPair *receiverIdentityKey = [Curve25519 generateKeyPair];
WhisperMessage *message = [[WhisperMessage alloc] init_throws_withVersion:3
macKey:fakeMacKey.publicKey
senderRatchetKey:keyPair.publicKey
counter:counter
previousCounter:0
cipherText:cipherText
senderIdentityKey:senderIdentityKey.publicKey
receiverIdentityKey:receiverIdentityKey.publicKey];
WhisperMessage *deserializedMessage = [[WhisperMessage alloc] init_throws_withData:message.serialized];
WhisperMessage *message = [[WhisperMessage alloc] initWithVersion:3 macKey:fakeMacKey.publicKey senderRatchetKey:keyPair.publicKey counter:counter previousCounter:0 cipherText:cipherText senderIdentityKey:senderIdentityKey.publicKey receiverIdentityKey:receiverIdentityKey.publicKey];
WhisperMessage *deserializedMessage = [[WhisperMessage alloc] initWithData:message.serialized];
XCTAssert([[message.serialized subdataWithRange:NSMakeRange(0, message.serialized.length-8)] isEqualToData:[deserializedMessage.serialized subdataWithRange:NSMakeRange(0, deserializedMessage.serialized.length-8)]]);
[message throws_verifyMacWithVersion:3
senderIdentityKey:senderIdentityKey.publicKey
receiverIdentityKey:receiverIdentityKey.publicKey
macKey:fakeMacKey.publicKey];
[deserializedMessage throws_verifyMacWithVersion:3
senderIdentityKey:senderIdentityKey.publicKey
receiverIdentityKey:receiverIdentityKey.publicKey
macKey:fakeMacKey.publicKey];
[message verifyMacWithVersion:3 senderIdentityKey:senderIdentityKey.publicKey receiverIdentityKey:receiverIdentityKey.publicKey macKey:fakeMacKey.publicKey];
[deserializedMessage verifyMacWithVersion:3 senderIdentityKey:senderIdentityKey.publicKey receiverIdentityKey:receiverIdentityKey.publicKey macKey:fakeMacKey.publicKey];
XCTAssert([message.cipherText isEqualToData:deserializedMessage.cipherText]);
XCTAssert(message.version == deserializedMessage.version);
XCTAssert([message.serialized isEqualToData:deserializedMessage.serialized]);

View File

@ -1,87 +1,80 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.0)
activesupport (4.2.10)
CFPropertyList (2.3.5)
activesupport (4.2.8)
i18n (~> 0.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
atomos (0.1.3)
addressable (2.5.0)
public_suffix (~> 2.0, >= 2.0.2)
babosa (1.0.2)
claide (1.0.2)
cocoapods (1.5.3)
claide (1.0.1)
cocoapods (1.2.0)
activesupport (>= 4.0.2, < 5)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.5.3)
cocoapods-deintegrate (>= 1.0.2, < 2.0)
cocoapods-downloader (>= 1.2.0, < 2.0)
claide (>= 1.0.1, < 2.0)
cocoapods-core (= 1.2.0)
cocoapods-deintegrate (>= 1.0.1, < 2.0)
cocoapods-downloader (>= 1.1.3, < 2.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-stats (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.3.0, < 2.0)
cocoapods-trunk (>= 1.1.2, < 2.0)
cocoapods-try (>= 1.1.0, < 2.0)
colored2 (~> 3.1)
colored (~> 1.2)
escape (~> 0.0.4)
fourflusher (~> 2.0.1)
gh_inspector (~> 1.0)
molinillo (~> 0.6.5)
molinillo (~> 0.5.5)
nap (~> 1.0)
ruby-macho (~> 1.1)
xcodeproj (>= 1.5.7, < 2.0)
cocoapods-core (1.5.3)
activesupport (>= 4.0.2, < 6)
ruby-macho (~> 0.2.5)
xcodeproj (>= 1.4.1, < 2.0)
cocoapods-core (1.2.0)
activesupport (>= 4.0.2, < 5)
fuzzy_match (~> 2.0.4)
nap (~> 1.0)
cocoapods-deintegrate (1.0.2)
cocoapods-downloader (1.2.2)
cocoapods-deintegrate (1.0.1)
cocoapods-downloader (1.1.3)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.0)
cocoapods-stats (1.0.0)
cocoapods-trunk (1.3.1)
cocoapods-trunk (1.1.2)
nap (>= 0.8, < 2.0)
netrc (~> 0.11)
netrc (= 0.7.8)
cocoapods-try (1.1.0)
colored (1.2)
colored2 (3.1.2)
commander-fastlane (4.4.6)
commander-fastlane (4.4.4)
highline (~> 1.7.2)
concurrent-ruby (1.1.3)
declarative (0.0.10)
declarative-option (0.1.0)
domain_name (0.5.20180417)
domain_name (0.5.20170223)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.5.0)
emoji_regex (0.1.1)
dotenv (2.2.0)
escape (0.0.4)
excon (0.62.0)
faraday (0.15.3)
excon (0.55.0)
faraday (0.11.0)
multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.6)
faraday (>= 0.7.4)
http-cookie (~> 1.0.0)
faraday_middleware (0.12.2)
faraday_middleware (0.11.0.1)
faraday (>= 0.7.4, < 1.0)
fastimage (2.1.4)
fastlane (2.108.0)
CFPropertyList (>= 2.3, < 4.0.0)
fastimage (2.1.0)
fastlane (2.23.0)
activesupport (< 5)
addressable (>= 2.3, < 3.0.0)
babosa (>= 1.0.2, < 2.0.0)
bundler (>= 1.12.0, < 2.0.0)
colored
commander-fastlane (>= 4.4.6, < 5.0.0)
commander-fastlane (>= 4.4.0, < 5.0.0)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (~> 0.1)
excon (>= 0.45.0, < 1.0.0)
faraday (~> 0.9)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 0.9)
fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-api-client (>= 0.21.2, < 0.24.0)
fastimage (>= 1.6)
gh_inspector (>= 1.0.1, < 2.0.0)
google-api-client (~> 0.9.2)
highline (>= 1.7.2, < 2.0.0)
json (< 3.0.0)
mini_magick (~> 4.5.1)
@ -89,105 +82,99 @@ GEM
multi_xml (~> 0.5)
multipart-post (~> 2.0.0)
plist (>= 3.1.0, < 4.0.0)
public_suffix (~> 2.0.0)
rubyzip (>= 1.2.2, < 2.0.0)
rubyzip (>= 1.1.0, < 2.0.0)
security (= 0.1.3)
simctl (~> 1.6.3)
slack-notifier (>= 2.0.0, < 3.0.0)
slack-notifier (>= 1.3, < 2.0.0)
terminal-notifier (>= 1.6.2, < 2.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
tty-screen (~> 0.5.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.6.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcodeproj (>= 0.20, < 2.0.0)
xcpretty (>= 0.2.4, < 1.0.0)
xcpretty-travis-formatter (>= 0.0.3)
fourflusher (2.0.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
google-api-client (0.23.9)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.5, < 0.7.0)
httpclient (>= 2.8.1, < 3.0)
mime-types (~> 3.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
signet (~> 0.9)
googleauth (0.6.7)
faraday (~> 0.12)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
gh_inspector (1.0.3)
google-api-client (0.9.28)
addressable (~> 2.3)
googleauth (~> 0.5)
httpclient (~> 2.7)
hurley (~> 0.1)
memoist (~> 0.11)
mime-types (>= 1.6)
representable (~> 2.3.0)
retriable (~> 2.0)
googleauth (0.5.1)
faraday (~> 0.9)
jwt (~> 1.4)
logging (~> 2.0)
memoist (~> 0.12)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
os (~> 0.9)
signet (~> 0.7)
highline (1.7.10)
highline (1.7.8)
http-cookie (1.0.3)
domain_name (~> 0.5)
httpclient (2.8.3)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
json (2.1.0)
jwt (2.1.0)
memoist (0.16.0)
mime-types (3.2.2)
hurley (0.2)
i18n (0.8.1)
json (2.0.3)
jwt (1.5.6)
little-plugger (1.1.4)
logging (2.2.0)
little-plugger (~> 1.1)
multi_json (~> 1.10)
memoist (0.15.0)
mime-types (3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812)
mime-types-data (3.2016.0521)
mini_magick (4.5.1)
minitest (5.11.3)
molinillo (0.6.6)
multi_json (1.13.1)
minitest (5.10.1)
molinillo (0.5.7)
multi_json (1.12.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
nanaimo (0.2.6)
nanaimo (0.2.3)
nap (1.1.0)
naturally (2.2.0)
netrc (0.11.0)
os (1.0.0)
plist (3.4.0)
netrc (0.7.8)
os (0.9.6)
plist (3.2.0)
public_suffix (2.0.5)
representable (3.0.4)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rouge (2.0.7)
ruby-macho (1.3.1)
rubyzip (1.2.2)
representable (2.3.0)
uber (~> 0.0.7)
retriable (2.1.0)
rouge (1.11.1)
ruby-macho (0.2.6)
rubyzip (1.2.1)
security (0.1.3)
signet (0.11.0)
signet (0.7.3)
addressable (~> 2.3)
faraday (~> 0.9)
jwt (>= 1.5, < 3.0)
jwt (~> 1.5)
multi_json (~> 1.10)
simctl (1.6.5)
CFPropertyList
naturally
slack-notifier (2.3.2)
terminal-notifier (1.8.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
slack-notifier (1.5.1)
terminal-notifier (1.7.1)
terminal-table (1.7.3)
unicode-display_width (~> 1.1.1)
thread_safe (0.3.6)
tty-cursor (0.6.0)
tty-screen (0.6.5)
tty-spinner (0.8.0)
tty-cursor (>= 0.5.0)
tzinfo (1.2.5)
tty-screen (0.5.0)
tzinfo (1.2.3)
thread_safe (~> 0.1)
uber (0.1.0)
uber (0.0.15)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.5)
unicode-display_width (1.4.0)
unf_ext (0.0.7.2)
unicode-display_width (1.1.3)
word_wrap (1.0.0)
xcodeproj (1.7.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.2.6)
xcpretty (0.3.0)
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.0)
xcodeproj (1.4.2)
CFPropertyList (~> 2.3.3)
activesupport (>= 3)
claide (>= 1.0.1, < 2.0)
colored (~> 1.2)
nanaimo (~> 0.2.3)
xcpretty (0.2.4)
rouge (~> 1.8)
xcpretty-travis-formatter (0.0.4)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
@ -198,4 +185,4 @@ DEPENDENCIES
fastlane
BUNDLED WITH
1.16.2
1.14.6

View File

@ -1,4 +1,4 @@
**Deprecation Warning**: It is recommended that the swift interface of [libsignal-client](https://github.com/signalapp/libsignal-client) be used for all new iOS applications. This library is no longer used by us or maintained.
**Deprecation Warning**: It is recommended that [libsignal-protocol-c](https://github.com/whispersystems/libsignal-protocol-c) be used for all new applications.
# SignalProtocolKit [![Build Status](https://travis-ci.org/WhisperSystems/AxolotlKit.svg?branch=master)](https://travis-ci.org/WhisperSystems/AxolotlKit)