From b69b56d0bb5524c40b0720d65396f78d44c5c684 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 18 Feb 2021 14:57:43 +0100 Subject: [PATCH 1/2] OLMKit: New pickle version using a pickle key provided externally Improve ObjC wrappers so that they can use a pickle key provided by the olm lib user. This new behavior is optional to not break existing usage. It is retro compatible and use pickle versioning already in place. Existing key will be unpickled with pickle v1 and pickled with pickle v2 if an external pickle key is provided. --- xcode/OLMKit/OLMAccount.m | 23 ++++++++++++++++++--- xcode/OLMKit/OLMInboundGroupSession.m | 27 ++++++++++++++++++++----- xcode/OLMKit/OLMKit.h | 28 +++++++++++++++++++++++--- xcode/OLMKit/OLMKit.m | 11 ++++++++++ xcode/OLMKit/OLMOutboundGroupSession.m | 25 ++++++++++++++++++++--- xcode/OLMKit/OLMPkDecryption.m | 28 ++++++++++++++++++++------ 6 files changed, 122 insertions(+), 20 deletions(-) diff --git a/xcode/OLMKit/OLMAccount.m b/xcode/OLMKit/OLMAccount.m index 9e48c2d..55e50a1 100644 --- a/xcode/OLMKit/OLMAccount.m +++ b/xcode/OLMKit/OLMAccount.m @@ -21,6 +21,7 @@ #import "OLMSession.h" #import "OLMSession_Private.h" #import "OLMUtility.h" +#import "OLMKit.h" @import Security; @@ -243,6 +244,13 @@ self = [self initWithSerializedData:pickle key:key error:&error]; } + else if ([version isEqualToString:@"2"]) { + NSString *pickle = [decoder decodeObjectOfClass:[NSString class] forKey:@"pickle"]; + NSData *key = OLMKit.sharedInstance.pickleKeyDelegate.pickleKey; + NSParameterAssert(key); + + self = [self initWithSerializedData:pickle key:key error:&error]; + } NSParameterAssert(error == nil); NSParameterAssert(self != nil); @@ -254,14 +262,23 @@ } - (void)encodeWithCoder:(NSCoder *)encoder { - NSData *key = [OLMUtility randomBytesOfLength:32]; + NSData *key = OLMKit.sharedInstance.pickleKeyDelegate.pickleKey; + if (key) + { + [encoder encodeObject:@"2" forKey:@"version"]; + } + else + { + key = [OLMUtility randomBytesOfLength:32]; + [encoder encodeObject:key forKey:@"key"]; + [encoder encodeObject:@"1" forKey:@"version"]; + } + NSError *error = nil; NSString *pickle = [self serializeDataWithKey:key error:&error]; NSParameterAssert(pickle.length > 0 && error == nil); [encoder encodeObject:pickle forKey:@"pickle"]; - [encoder encodeObject:key forKey:@"key"]; - [encoder encodeObject:@"1" forKey:@"version"]; } diff --git a/xcode/OLMKit/OLMInboundGroupSession.m b/xcode/OLMKit/OLMInboundGroupSession.m index 9e57741..7e0eace 100644 --- a/xcode/OLMKit/OLMInboundGroupSession.m +++ b/xcode/OLMKit/OLMInboundGroupSession.m @@ -19,6 +19,7 @@ #import "OLMUtility.h" #include "olm/olm.h" +#import "OLMKit.h" @interface OLMInboundGroupSession () { @@ -277,7 +278,14 @@ self = [self initWithSerializedData:pickle key:key error:&error]; } - + else if ([version isEqualToString:@"2"]) { + NSString *pickle = [decoder decodeObjectOfClass:[NSString class] forKey:@"pickle"]; + NSData *key = OLMKit.sharedInstance.pickleKeyDelegate.pickleKey; + NSParameterAssert(key); + + self = [self initWithSerializedData:pickle key:key error:&error]; + } + NSParameterAssert(error == nil); NSParameterAssert(self != nil); if (!self) { @@ -288,14 +296,23 @@ } - (void)encodeWithCoder:(NSCoder *)encoder { - NSData *key = [OLMUtility randomBytesOfLength:32]; + NSData *key = OLMKit.sharedInstance.pickleKeyDelegate.pickleKey; + if (key) + { + [encoder encodeObject:@"2" forKey:@"version"]; + } + else + { + key = [OLMUtility randomBytesOfLength:32]; + [encoder encodeObject:key forKey:@"key"]; + [encoder encodeObject:@"1" forKey:@"version"]; + } + NSError *error = nil; NSString *pickle = [self serializeDataWithKey:key error:&error]; NSParameterAssert(pickle.length > 0 && error == nil); - + [encoder encodeObject:pickle forKey:@"pickle"]; - [encoder encodeObject:key forKey:@"key"]; - [encoder encodeObject:@"1" forKey:@"version"]; } @end diff --git a/xcode/OLMKit/OLMKit.h b/xcode/OLMKit/OLMKit.h index 54496a0..fc660dd 100644 --- a/xcode/OLMKit/OLMKit.h +++ b/xcode/OLMKit/OLMKit.h @@ -31,9 +31,31 @@ #import #import -@interface OLMKit : NSObject -//! Project version string for OLMKit, the same as libolm. -+ (NSString*)versionString; +NS_ASSUME_NONNULL_BEGIN + +/** + `OLMKitPickleKeyDelegate` provides the key to use for every pickle operation. + */ +@protocol OLMKitPickleKeyDelegate + +- (NSData*)pickleKey; @end + + +@interface OLMKit : NSObject + +/// Project version string for OLMKit, the same as libolm. ++ (NSString*)versionString; + +/// The optional delegate that provides the pickle key. +/// If not provided, OLMKit will use default pickle keys. +@property (nonatomic, weak, nullable) id pickleKeyDelegate; + +/// The singleton instance. ++ (instancetype)sharedInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/xcode/OLMKit/OLMKit.m b/xcode/OLMKit/OLMKit.m index c383650..332f0dd 100644 --- a/xcode/OLMKit/OLMKit.m +++ b/xcode/OLMKit/OLMKit.m @@ -30,4 +30,15 @@ return [NSString stringWithFormat:@"%tu.%tu.%tu", major, minor, patch]; } ++ (instancetype)sharedInstance +{ + static OLMKit *sharedInstance = nil; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[self alloc] init]; + }); + return sharedInstance; +} + @end diff --git a/xcode/OLMKit/OLMOutboundGroupSession.m b/xcode/OLMKit/OLMOutboundGroupSession.m index a0a7cc6..3a4ef3d 100644 --- a/xcode/OLMKit/OLMOutboundGroupSession.m +++ b/xcode/OLMKit/OLMOutboundGroupSession.m @@ -20,6 +20,8 @@ #import "OLMUtility.h" #include "olm/olm.h" +#import "OLMKit.h" + @interface OLMOutboundGroupSession () { OlmOutboundGroupSession *session; @@ -198,6 +200,14 @@ self = [self initWithSerializedData:pickle key:key error:&error]; } + else if ([version isEqualToString:@"2"]) { + NSString *pickle = [decoder decodeObjectOfClass:[NSString class] forKey:@"pickle"]; + NSData *key = OLMKit.sharedInstance.pickleKeyDelegate.pickleKey; + NSParameterAssert(key); + + self = [self initWithSerializedData:pickle key:key error:&error]; + } + NSParameterAssert(error == nil); NSParameterAssert(self != nil); @@ -209,14 +219,23 @@ } - (void)encodeWithCoder:(NSCoder *)encoder { - NSData *key = [OLMUtility randomBytesOfLength:32]; + NSData *key = OLMKit.sharedInstance.pickleKeyDelegate.pickleKey; + if (key) + { + [encoder encodeObject:@"2" forKey:@"version"]; + } + else + { + key = [OLMUtility randomBytesOfLength:32]; + [encoder encodeObject:key forKey:@"key"]; + [encoder encodeObject:@"1" forKey:@"version"]; + } + NSError *error = nil; NSString *pickle = [self serializeDataWithKey:key error:&error]; NSParameterAssert(pickle.length > 0 && error == nil); [encoder encodeObject:pickle forKey:@"pickle"]; - [encoder encodeObject:key forKey:@"key"]; - [encoder encodeObject:@"1" forKey:@"version"]; } @end diff --git a/xcode/OLMKit/OLMPkDecryption.m b/xcode/OLMKit/OLMPkDecryption.m index 4af2c71..cf77375 100644 --- a/xcode/OLMKit/OLMPkDecryption.m +++ b/xcode/OLMKit/OLMPkDecryption.m @@ -19,6 +19,7 @@ #include "olm/olm.h" #include "olm/pk.h" #include "OLMUtility.h" +#import "OLMKit.h" @interface OLMPkDecryption () { @@ -274,7 +275,14 @@ self = [self initWithSerializedData:pickle key:key error:&error]; } - + else if ([version isEqualToString:@"2"]) { + NSString *pickle = [decoder decodeObjectOfClass:[NSString class] forKey:@"pickle"]; + NSData *key = OLMKit.sharedInstance.pickleKeyDelegate.pickleKey; + NSParameterAssert(key); + + self = [self initWithSerializedData:pickle key:key error:&error]; + } + NSParameterAssert(error == nil); NSParameterAssert(self != nil); if (!self) { @@ -285,15 +293,23 @@ } - (void)encodeWithCoder:(NSCoder *)encoder { - NSData *key = [OLMUtility randomBytesOfLength:32]; - NSError *error = nil; + NSData *key = OLMKit.sharedInstance.pickleKeyDelegate.pickleKey; + if (key) + { + [encoder encodeObject:@"2" forKey:@"version"]; + } + else + { + key = [OLMUtility randomBytesOfLength:32]; + [encoder encodeObject:key forKey:@"key"]; + [encoder encodeObject:@"1" forKey:@"version"]; + } + NSError *error = nil; NSString *pickle = [self serializeDataWithKey:key error:&error]; NSParameterAssert(pickle.length > 0 && error == nil); - + [encoder encodeObject:pickle forKey:@"pickle"]; - [encoder encodeObject:key forKey:@"key"]; - [encoder encodeObject:@"1" forKey:@"version"]; } @end From 4be7cc367b06ca4ee7649cb10f14a23052f3c9ee Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 19 Feb 2021 12:00:03 +0100 Subject: [PATCH 2/2] OLMKit: Forgot to implement pickle v2 for OLMSession --- xcode/OLMKit/OLMSession.m | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/xcode/OLMKit/OLMSession.m b/xcode/OLMKit/OLMSession.m index fc58a08..d10e222 100644 --- a/xcode/OLMKit/OLMSession.m +++ b/xcode/OLMKit/OLMSession.m @@ -21,6 +21,7 @@ #import "OLMAccount_Private.h" #import "OLMSession_Private.h" #include "olm/olm.h" +#import "OLMKit.h" @implementation OLMSession @@ -359,6 +360,13 @@ self = [self initWithSerializedData:pickle key:key error:&error]; } + else if ([version isEqualToString:@"2"]) { + NSString *pickle = [decoder decodeObjectOfClass:[NSString class] forKey:@"pickle"]; + NSData *key = OLMKit.sharedInstance.pickleKeyDelegate.pickleKey; + NSParameterAssert(key); + + self = [self initWithSerializedData:pickle key:key error:&error]; + } NSParameterAssert(error == nil); NSParameterAssert(self != nil); @@ -370,14 +378,23 @@ } - (void)encodeWithCoder:(NSCoder *)encoder { - NSData *key = [OLMUtility randomBytesOfLength:32]; + NSData *key = OLMKit.sharedInstance.pickleKeyDelegate.pickleKey; + if (key) + { + [encoder encodeObject:@"2" forKey:@"version"]; + } + else + { + key = [OLMUtility randomBytesOfLength:32]; + [encoder encodeObject:key forKey:@"key"]; + [encoder encodeObject:@"1" forKey:@"version"]; + } + NSError *error = nil; NSString *pickle = [self serializeDataWithKey:key error:&error]; NSParameterAssert(pickle.length > 0 && error == nil); [encoder encodeObject:pickle forKey:@"pickle"]; - [encoder encodeObject:key forKey:@"key"]; - [encoder encodeObject:@"1" forKey:@"version"]; } @end