aboutsummaryrefslogtreecommitdiff
path: root/xcode/OLMKit
diff options
context:
space:
mode:
authorChris Ballinger <chrisballinger@gmail.com>2016-04-13 16:53:47 -0700
committerChris Ballinger <chrisballinger@gmail.com>2016-04-13 16:53:47 -0700
commitdaab2a58af947cddd67fe9f30dd3a9fc327650c0 (patch)
tree6d2e3abfc160198ec1d8e521a74b1f1d236c0ea3 /xcode/OLMKit
parentf505113fb7a6d61015ad8050b3fb4e26df029150 (diff)
OLMAccount and OLMSession serialization
Diffstat (limited to 'xcode/OLMKit')
-rw-r--r--xcode/OLMKit/OLMAccount.h8
-rw-r--r--xcode/OLMKit/OLMAccount.m113
-rw-r--r--xcode/OLMKit/OLMSerializable.h6
-rw-r--r--xcode/OLMKit/OLMSession.h6
-rw-r--r--xcode/OLMKit/OLMSession.m124
-rw-r--r--xcode/OLMKit/OLMSession_Private.h16
6 files changed, 239 insertions, 34 deletions
diff --git a/xcode/OLMKit/OLMAccount.h b/xcode/OLMKit/OLMAccount.h
index cfa7129..a2923f9 100644
--- a/xcode/OLMKit/OLMAccount.h
+++ b/xcode/OLMKit/OLMAccount.h
@@ -9,7 +9,9 @@
#import <Foundation/Foundation.h>
#import "OLMSerializable.h"
-@interface OLMAccount : NSObject <OLMSerializable>
+@class OLMSession;
+
+@interface OLMAccount : NSObject <OLMSerializable, NSSecureCoding>
/** Creates new account */
- (instancetype) initNewAccount;
@@ -18,11 +20,13 @@
- (NSDictionary*) identityKeys;
/** signs message with ed25519 key for account */
-- (NSData*) signMessage:(NSData*)messageData;
+- (NSString*) signMessage:(NSData*)messageData;
/** Public parts of the unpublished one time keys for the account */
- (NSDictionary*) oneTimeKeys;
+- (BOOL) removeOneTimeKeysForSession:(OLMSession*)session;
+
/** Marks the current set of one time keys as being published. */
- (void) markKeysAsPublished;
diff --git a/xcode/OLMKit/OLMAccount.m b/xcode/OLMKit/OLMAccount.m
index d56b6b4..4561a37 100644
--- a/xcode/OLMKit/OLMAccount.m
+++ b/xcode/OLMKit/OLMAccount.m
@@ -8,6 +8,8 @@
#import "OLMAccount.h"
#import "OLMAccount_Private.h"
+#import "OLMSession.h"
+#import "OLMSession_Private.h"
#import "OLMUtility.h"
@import Security;
@@ -34,7 +36,7 @@
return YES;
}
-- (instancetype) initNewAccount {
+- (instancetype) init {
self = [super init];
if (!self) {
return nil;
@@ -43,6 +45,14 @@
if (!success) {
return nil;
}
+ return self;
+}
+
+- (instancetype) initNewAccount {
+ self = [self init];
+ if (!self) {
+ return nil;
+ }
size_t randomLength = olm_create_account_random_length(_account);
NSMutableData *random = [OLMUtility randomBytesOfLength:randomLength];
size_t accountResult = olm_create_account(_account, random.mutableBytes, random.length);
@@ -114,5 +124,106 @@
}
}
+- (BOOL) removeOneTimeKeysForSession:(OLMSession *)session {
+ NSParameterAssert(session != nil);
+ if (!session) {
+ return nil;
+ }
+ size_t result = olm_remove_one_time_keys(self.account, session.session);
+ if (result == olm_error()) {
+ const char *error = olm_session_last_error(session.session);
+ NSAssert(NO, @"olm_remove_one_time_keys error: %s", error);
+ return NO;
+ }
+ return YES;
+}
+
+#pragma mark OLMSerializable
+
+/** Initializes from encrypted serialized data. Will throw error if invalid key or invalid base64. */
+- (instancetype) initWithSerializedData:(NSString*)serializedData key:(NSData*)key error:(NSError**)error {
+ self = [self init];
+ if (!self) {
+ return nil;
+ }
+ NSParameterAssert(key.length > 0);
+ NSParameterAssert(serializedData.length > 0);
+ if (key.length == 0 || serializedData.length == 0) {
+ if (error) {
+ *error = [NSError errorWithDomain:@"org.matrix.olm" code:0 userInfo:@{NSLocalizedDescriptionKey: @"Bad length."}];
+ }
+ return nil;
+ }
+ NSMutableData *pickle = [serializedData dataUsingEncoding:NSUTF8StringEncoding].mutableCopy;
+ size_t result = olm_unpickle_account(_account, key.bytes, key.length, pickle.mutableBytes, pickle.length);
+ if (result == olm_error()) {
+ const char *olm_error = olm_account_last_error(_account);
+ NSString *errorString = [NSString stringWithUTF8String:olm_error];
+ if (error && errorString) {
+ *error = [NSError errorWithDomain:@"org.matrix.olm" code:0 userInfo:@{NSLocalizedDescriptionKey: errorString}];
+ }
+ return nil;
+ }
+ return self;
+}
+
+/** Serializes and encrypts object data, outputs base64 blob */
+- (NSString*) serializeDataWithKey:(NSData*)key error:(NSError**)error {
+ NSParameterAssert(key.length > 0);
+ size_t length = olm_pickle_account_length(_account);
+ NSMutableData *pickled = [NSMutableData dataWithLength:length];
+ size_t result = olm_pickle_account(_account, key.bytes, key.length, pickled.mutableBytes, pickled.length);
+ if (result == olm_error()) {
+ const char *olm_error = olm_account_last_error(_account);
+ NSString *errorString = [NSString stringWithUTF8String:olm_error];
+ if (error && errorString) {
+ *error = [NSError errorWithDomain:@"org.matrix.olm" code:0 userInfo:@{NSLocalizedDescriptionKey: errorString}];
+ }
+ return nil;
+ }
+ NSString *pickleString = [[NSString alloc] initWithData:pickled encoding:NSUTF8StringEncoding];
+ return pickleString;
+}
+
+#pragma mark NSSecureCoding
+
++ (BOOL) supportsSecureCoding {
+ return YES;
+}
+
+#pragma mark NSCoding
+
+- (id)initWithCoder:(NSCoder *)decoder {
+ NSString *version = [decoder decodeObjectOfClass:[NSString class] forKey:@"version"];
+
+ NSError *error = nil;
+
+ if ([version isEqualToString:@"1"]) {
+ NSString *pickle = [decoder decodeObjectOfClass:[NSString class] forKey:@"pickle"];
+ NSData *key = [decoder decodeObjectOfClass:[NSData class] forKey:@"key"];
+
+ self = [self initWithSerializedData:pickle key:key error:&error];
+ }
+
+ NSParameterAssert(error == nil);
+ NSParameterAssert(self != nil);
+ if (!self) {
+ return nil;
+ }
+
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)encoder {
+ NSData *key = [OLMUtility randomBytesOfLength:32];
+ 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/OLMSerializable.h b/xcode/OLMKit/OLMSerializable.h
index afacdaa..b4b115a 100644
--- a/xcode/OLMKit/OLMSerializable.h
+++ b/xcode/OLMKit/OLMSerializable.h
@@ -11,9 +11,9 @@
@protocol OLMSerializable <NSObject>
/** Initializes from encrypted serialized data. Will throw error if invalid key or invalid base64. */
-- (instancetype) initWithSerializedData:(NSData*)serializedData key:(NSData*)key error:(NSError**)error;
+- (instancetype) initWithSerializedData:(NSString*)serializedData key:(NSData*)key error:(NSError**)error;
-/** Serializes and encrypts object data */
-- (NSData*) serializeDataWithKey:(NSData*)key;
+/** Serializes and encrypts object data, outputs base64 blob */
+- (NSString*) serializeDataWithKey:(NSData*)key error:(NSError**)error;
@end
diff --git a/xcode/OLMKit/OLMSession.h b/xcode/OLMKit/OLMSession.h
index 1a075e4..c209564 100644
--- a/xcode/OLMKit/OLMSession.h
+++ b/xcode/OLMKit/OLMSession.h
@@ -11,9 +11,7 @@
#import "OLMAccount.h"
#import "OLMMessage.h"
-@interface OLMSession : NSObject <OLMSerializable>
-
-@property (nonatomic, strong) OLMAccount *account;
+@interface OLMSession : NSObject <OLMSerializable, NSSecureCoding>
- (instancetype) initOutboundSessionWithAccount:(OLMAccount*)account theirIdentityKey:(NSString*)theirIdentityKey theirOneTimeKey:(NSString*)theirOneTimeKey;
@@ -27,8 +25,6 @@
- (BOOL) matchesInboundSessionFrom:(NSString*)theirIdentityKey oneTimeKeyMessage:(NSString *)oneTimeKeyMessage;
-- (BOOL) removeOneTimeKeys;
-
/** UTF-8 plaintext -> base64 ciphertext */
- (OLMMessage*) encryptMessage:(NSString*)message;
diff --git a/xcode/OLMKit/OLMSession.m b/xcode/OLMKit/OLMSession.m
index fa7cb62..119079f 100644
--- a/xcode/OLMKit/OLMSession.m
+++ b/xcode/OLMKit/OLMSession.m
@@ -9,12 +9,9 @@
#import "OLMSession.h"
#import "OLMUtility.h"
#import "OLMAccount_Private.h"
+#import "OLMSession_Private.h"
@import olm;
-@interface OLMSession()
-@property (nonatomic) OlmSession *session;
-@end
-
@implementation OLMSession
- (void) dealloc {
@@ -37,7 +34,7 @@
return YES;
}
-- (instancetype) initWithAccount:(OLMAccount*)account {
+- (instancetype) init {
self = [super init];
if (!self) {
return nil;
@@ -46,6 +43,18 @@
if (!success) {
return nil;
}
+ return self;
+}
+
+- (instancetype) initWithAccount:(OLMAccount*)account {
+ self = [self init];
+ if (!self) {
+ return nil;
+ }
+ NSParameterAssert(account != nil && account.account != NULL);
+ if (account == nil || account.account == NULL) {
+ return nil;
+ }
_account = account;
return self;
}
@@ -72,10 +81,6 @@
if (!self) {
return nil;
}
- BOOL success = [self initializeSessionMemory];
- if (!success) {
- return nil;
- }
NSMutableData *otk = [NSMutableData dataWithData:[oneTimeKeyMessage dataUsingEncoding:NSUTF8StringEncoding]];
size_t result = olm_create_inbound_session(_session, account.account, otk.mutableBytes, oneTimeKeyMessage.length);
if (result == olm_error()) {
@@ -91,10 +96,6 @@
if (!self) {
return nil;
}
- BOOL success = [self initializeSessionMemory];
- if (!success) {
- return nil;
- }
NSData *idKey = [theirIdentityKey dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *otk = [NSMutableData dataWithData:[oneTimeKeyMessage dataUsingEncoding:NSUTF8StringEncoding]];
size_t result = olm_create_inbound_session_from(_session, account.account, idKey.bytes, idKey.length, otk.mutableBytes, otk.length);
@@ -143,16 +144,6 @@
return encryptedMessage;
}
-- (BOOL) removeOneTimeKeys {
- size_t result = olm_remove_one_time_keys(_account.account, _session);
- if (result == olm_error()) {
- const char *error = olm_session_last_error(_session);
- NSAssert(NO, @"olm_remove_one_time_keys error: %s", error);
- return NO;
- }
- return YES;
-}
-
- (NSString*) decryptMessage:(OLMMessage*)message {
NSParameterAssert(message != nil);
NSData *messageData = [message.ciphertext dataUsingEncoding:NSUTF8StringEncoding];
@@ -180,4 +171,91 @@
return plaintext;
}
+#pragma mark OLMSerializable
+
+/** Initializes from encrypted serialized data. Will throw error if invalid key or invalid base64. */
+- (instancetype) initWithSerializedData:(NSString*)serializedData key:(NSData*)key error:(NSError**)error {
+ self = [self init];
+ if (!self) {
+ return nil;
+ }
+ NSParameterAssert(key.length > 0);
+ NSParameterAssert(serializedData.length > 0);
+ if (key.length == 0 || serializedData.length == 0) {
+ if (error) {
+ *error = [NSError errorWithDomain:@"org.matrix.olm" code:0 userInfo:@{NSLocalizedDescriptionKey: @"Bad length."}];
+ }
+ return nil;
+ }
+ NSMutableData *pickle = [serializedData dataUsingEncoding:NSUTF8StringEncoding].mutableCopy;
+ size_t result = olm_unpickle_session(_session, key.bytes, key.length, pickle.mutableBytes, pickle.length);
+ if (result == olm_error()) {
+ const char *olm_error = olm_session_last_error(_session);
+ NSString *errorString = [NSString stringWithUTF8String:olm_error];
+ if (error && errorString) {
+ *error = [NSError errorWithDomain:@"org.matrix.olm" code:0 userInfo:@{NSLocalizedDescriptionKey: errorString}];
+ }
+ return nil;
+ }
+ return self;
+}
+
+/** Serializes and encrypts object data, outputs base64 blob */
+- (NSString*) serializeDataWithKey:(NSData*)key error:(NSError**)error {
+ NSParameterAssert(key.length > 0);
+ size_t length = olm_pickle_session_length(_session);
+ NSMutableData *pickled = [NSMutableData dataWithLength:length];
+ size_t result = olm_pickle_session(_session, key.bytes, key.length, pickled.mutableBytes, pickled.length);
+ if (result == olm_error()) {
+ const char *olm_error = olm_session_last_error(_session);
+ NSString *errorString = [NSString stringWithUTF8String:olm_error];
+ if (error && errorString) {
+ *error = [NSError errorWithDomain:@"org.matrix.olm" code:0 userInfo:@{NSLocalizedDescriptionKey: errorString}];
+ }
+ return nil;
+ }
+ NSString *pickleString = [[NSString alloc] initWithData:pickled encoding:NSUTF8StringEncoding];
+ return pickleString;
+}
+
+#pragma mark NSSecureCoding
+
++ (BOOL) supportsSecureCoding {
+ return YES;
+}
+
+#pragma mark NSCoding
+
+- (id)initWithCoder:(NSCoder *)decoder {
+ NSString *version = [decoder decodeObjectOfClass:[NSString class] forKey:@"version"];
+
+ NSError *error = nil;
+
+ if ([version isEqualToString:@"1"]) {
+ NSString *pickle = [decoder decodeObjectOfClass:[NSString class] forKey:@"pickle"];
+ NSData *key = [decoder decodeObjectOfClass:[NSData class] forKey:@"key"];
+
+ self = [self initWithSerializedData:pickle key:key error:&error];
+ }
+
+ NSParameterAssert(error == nil);
+ NSParameterAssert(self != nil);
+ if (!self) {
+ return nil;
+ }
+
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)encoder {
+ NSData *key = [OLMUtility randomBytesOfLength:32];
+ 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/OLMSession_Private.h b/xcode/OLMKit/OLMSession_Private.h
new file mode 100644
index 0000000..d906b14
--- /dev/null
+++ b/xcode/OLMKit/OLMSession_Private.h
@@ -0,0 +1,16 @@
+//
+// OLMSession_Private.h
+// olm
+//
+// Created by Chris Ballinger on 4/13/16.
+//
+//
+
+@import olm;
+
+@interface OLMSession()
+
+@property (nonatomic) OlmSession *session;
+@property (nonatomic, strong) OLMAccount *account;
+
+@end \ No newline at end of file