OLMKit: Add megolm api: OLMInboundGroupSession and OLMOutboundGroupSession
This commit is contained in:
parent
2ca67ace60
commit
2bd912990f
6 changed files with 504 additions and 0 deletions
29
xcode/OLMKit/OLMInboundGroupSession.h
Normal file
29
xcode/OLMKit/OLMInboundGroupSession.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Copyright 2016 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OLMSerializable.h"
|
||||
|
||||
@interface OLMInboundGroupSession : NSObject <OLMSerializable, NSSecureCoding>
|
||||
|
||||
- (instancetype) initInboundGroupSessionWithSessionKey:(NSString*)sessionKey;
|
||||
|
||||
- (NSString*)sessionIdentifier;
|
||||
|
||||
/** base64 ciphertext -> UTF-8 plaintext */
|
||||
- (NSString*)decryptMessage:(NSString*)message;
|
||||
|
||||
@end
|
198
xcode/OLMKit/OLMInboundGroupSession.m
Normal file
198
xcode/OLMKit/OLMInboundGroupSession.m
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
Copyright 2016 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "OLMInboundGroupSession.h"
|
||||
|
||||
#import "OLMUtility.h"
|
||||
#include "olm/olm.h"
|
||||
|
||||
@interface OLMInboundGroupSession ()
|
||||
{
|
||||
OlmInboundGroupSession *session;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@implementation OLMInboundGroupSession
|
||||
|
||||
- (void)dealloc {
|
||||
olm_clear_inbound_group_session(session);
|
||||
free(session);
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
session = malloc(olm_inbound_group_session_size());
|
||||
if (session) {
|
||||
session = olm_inbound_group_session(session);
|
||||
}
|
||||
|
||||
if (!session) {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initInboundGroupSessionWithSessionKey:(NSString *)sessionKey {
|
||||
self = [self init];
|
||||
if (self) {
|
||||
NSData *sessionKeyData = [sessionKey dataUsingEncoding:NSUTF8StringEncoding];
|
||||
size_t result = olm_init_inbound_group_session(session, sessionKeyData.bytes, sessionKeyData.length);
|
||||
if (result == olm_error()) {
|
||||
const char *error = olm_inbound_group_session_last_error(session);
|
||||
NSAssert(NO, @"olm_init_inbound_group_session error: %s", error);
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)sessionIdentifier {
|
||||
size_t length = olm_inbound_group_session_id_length(session);
|
||||
NSMutableData *idData = [NSMutableData dataWithLength:length];
|
||||
if (!idData) {
|
||||
return nil;
|
||||
}
|
||||
size_t result = olm_inbound_group_session_id(session, idData.mutableBytes, idData.length);
|
||||
if (result == olm_error()) {
|
||||
const char *error = olm_inbound_group_session_last_error(session);
|
||||
NSAssert(NO, @"olm_inbound_group_session_id error: %s", error);
|
||||
return nil;
|
||||
}
|
||||
NSString *idString = [[NSString alloc] initWithData:idData encoding:NSUTF8StringEncoding];
|
||||
return idString;
|
||||
}
|
||||
|
||||
- (NSString *)decryptMessage:(NSString *)message
|
||||
{
|
||||
NSParameterAssert(message != nil);
|
||||
NSData *messageData = [message dataUsingEncoding:NSUTF8StringEncoding];
|
||||
if (!messageData) {
|
||||
return nil;
|
||||
}
|
||||
NSMutableData *mutMessage = messageData.mutableCopy;
|
||||
size_t maxPlaintextLength = olm_group_decrypt_max_plaintext_length(session, mutMessage.mutableBytes, mutMessage.length);
|
||||
if (maxPlaintextLength == olm_error()) {
|
||||
const char *error = olm_inbound_group_session_last_error(session);
|
||||
NSAssert(NO, @"olm_group_decrypt_max_plaintext_length error: %s", error);
|
||||
return nil;
|
||||
}
|
||||
// message buffer is destroyed by olm_group_decrypt_max_plaintext_length
|
||||
mutMessage = messageData.mutableCopy;
|
||||
NSMutableData *plaintextData = [NSMutableData dataWithLength:maxPlaintextLength];
|
||||
size_t plaintextLength = olm_group_decrypt(session, mutMessage.mutableBytes, mutMessage.length, plaintextData.mutableBytes, plaintextData.length);
|
||||
if (plaintextLength == olm_error()) {
|
||||
const char *error = olm_inbound_group_session_last_error(session);
|
||||
NSAssert(NO, @"olm_group_decrypt error: %s", error);
|
||||
return nil;
|
||||
}
|
||||
plaintextData.length = plaintextLength;
|
||||
NSString *plaintext = [[NSString alloc] initWithData:plaintextData encoding:NSUTF8StringEncoding];
|
||||
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 *__autoreleasing *)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_inbound_group_session(session, key.bytes, key.length, pickle.mutableBytes, pickle.length);
|
||||
if (result == olm_error()) {
|
||||
const char *olm_error = olm_inbound_group_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_inbound_group_session_length(session);
|
||||
NSMutableData *pickled = [NSMutableData dataWithLength:length];
|
||||
size_t result = olm_pickle_inbound_group_session(session, key.bytes, key.length, pickled.mutableBytes, pickled.length);
|
||||
if (result == olm_error()) {
|
||||
const char *olm_error = olm_inbound_group_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
|
|
@ -17,3 +17,5 @@ NSString *OLMKitVersionString();
|
|||
#import <OLMKit/OLMSession.h>
|
||||
#import <OLMKit/OLMMessage.h>
|
||||
#import <OLMKit/OLMUtility.h>
|
||||
#import <OLMKit/OLMInboundGroupSession.h>
|
||||
#import <OLMKit/OLMOutboundGroupSession.h>
|
||||
|
|
31
xcode/OLMKit/OLMOutboundGroupSession.h
Normal file
31
xcode/OLMKit/OLMOutboundGroupSession.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
Copyright 2016 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "OLMSerializable.h"
|
||||
|
||||
@interface OLMOutboundGroupSession : NSObject <OLMSerializable, NSSecureCoding>
|
||||
|
||||
- (instancetype) initOutboundGroupSession;
|
||||
|
||||
- (NSString*)sessionIdentifier;
|
||||
- (NSUInteger)messageIndex;
|
||||
- (NSString*)sessionKey;
|
||||
|
||||
/** UTF-8 plaintext -> base64 ciphertext */
|
||||
- (NSString*)encryptMessage:(NSString*)message;
|
||||
|
||||
@end
|
205
xcode/OLMKit/OLMOutboundGroupSession.m
Normal file
205
xcode/OLMKit/OLMOutboundGroupSession.m
Normal file
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
Copyright 2016 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "OLMOutboundGroupSession.h"
|
||||
|
||||
#import "OLMUtility.h"
|
||||
#include "olm/olm.h"
|
||||
|
||||
@interface OLMOutboundGroupSession ()
|
||||
{
|
||||
OlmOutboundGroupSession *session;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation OLMOutboundGroupSession
|
||||
|
||||
- (void)dealloc {
|
||||
olm_clear_outbound_group_session(session);
|
||||
free(session);
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
session = malloc(olm_outbound_group_session_size());
|
||||
if (session) {
|
||||
session = olm_outbound_group_session(session);
|
||||
}
|
||||
|
||||
if (!session) {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initOutboundGroupSession {
|
||||
self = [self init];
|
||||
if (self) {
|
||||
NSMutableData *random = [OLMUtility randomBytesOfLength:olm_init_outbound_group_session_random_length(session)];
|
||||
|
||||
size_t result = olm_init_outbound_group_session(session, random.mutableBytes, random.length);
|
||||
if (result == olm_error()) {
|
||||
const char *error = olm_outbound_group_session_last_error(session);
|
||||
NSAssert(NO, @"olm_init_outbound_group_session error: %s", error);
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)sessionIdentifier {
|
||||
size_t length = olm_outbound_group_session_id_length(session);
|
||||
NSMutableData *idData = [NSMutableData dataWithLength:length];
|
||||
if (!idData) {
|
||||
return nil;
|
||||
}
|
||||
size_t result = olm_outbound_group_session_id(session, idData.mutableBytes, idData.length);
|
||||
if (result == olm_error()) {
|
||||
const char *error = olm_outbound_group_session_last_error(session);
|
||||
NSAssert(NO, @"olm_outbound_group_session_id error: %s", error);
|
||||
return nil;
|
||||
}
|
||||
NSString *idString = [[NSString alloc] initWithData:idData encoding:NSUTF8StringEncoding];
|
||||
return idString;
|
||||
}
|
||||
|
||||
- (NSUInteger)messageIndex {
|
||||
return olm_outbound_group_session_message_index(session);
|
||||
}
|
||||
|
||||
- (NSString *)sessionKey {
|
||||
size_t length = olm_outbound_group_session_key_length(session);
|
||||
NSMutableData *sessionKeyData = [NSMutableData dataWithLength:length];
|
||||
if (!sessionKeyData) {
|
||||
return nil;
|
||||
}
|
||||
size_t result = olm_outbound_group_session_key(session, sessionKeyData.mutableBytes, sessionKeyData.length);
|
||||
if (result == olm_error()) {
|
||||
const char *error = olm_outbound_group_session_last_error(session);
|
||||
NSAssert(NO, @"olm_outbound_group_session_key error: %s", error);
|
||||
return nil;
|
||||
}
|
||||
NSString *sessionKey = [[NSString alloc] initWithData:sessionKeyData encoding:NSUTF8StringEncoding];
|
||||
return sessionKey;
|
||||
}
|
||||
|
||||
- (NSString *)encryptMessage:(NSString *)message {
|
||||
NSData *plaintextData = [message dataUsingEncoding:NSUTF8StringEncoding];
|
||||
size_t ciphertextLength = olm_group_encrypt_message_length(session, plaintextData.length);
|
||||
NSMutableData *ciphertext = [NSMutableData dataWithLength:ciphertextLength];
|
||||
if (!ciphertext) {
|
||||
return nil;
|
||||
}
|
||||
size_t result = olm_group_encrypt(session, plaintextData.bytes, plaintextData.length, ciphertext.mutableBytes, ciphertext.length);
|
||||
if (result == olm_error()) {
|
||||
const char *error = olm_outbound_group_session_last_error(session);
|
||||
NSAssert(NO, @"olm_group_encrypt error: %s", error);
|
||||
return nil;
|
||||
}
|
||||
return [[NSString alloc] initWithData:ciphertext encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
#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 *__autoreleasing *)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_outbound_group_session(session, key.bytes, key.length, pickle.mutableBytes, pickle.length);
|
||||
if (result == olm_error()) {
|
||||
const char *olm_error = olm_outbound_group_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_outbound_group_session_length(session);
|
||||
NSMutableData *pickled = [NSMutableData dataWithLength:length];
|
||||
size_t result = olm_pickle_outbound_group_session(session, key.bytes, key.length, pickled.mutableBytes, pickled.length);
|
||||
if (result == olm_error()) {
|
||||
const char *olm_error = olm_outbound_group_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
|
39
xcode/OLMKitTests/OLMKitGroupTests.m
Normal file
39
xcode/OLMKitTests/OLMKitGroupTests.m
Normal file
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// OLMKitGroupTests.m
|
||||
// OLMKit
|
||||
//
|
||||
// Created by Emmanuel ROHEE on 10/10/16.
|
||||
// Copyright © 2016 matrix.org. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
@interface OLMKitGroupTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation OLMKitGroupTests
|
||||
|
||||
- (void)setUp {
|
||||
[super setUp];
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
- (void)tearDown {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
[super tearDown];
|
||||
}
|
||||
|
||||
- (void)testExample {
|
||||
// This is an example of a functional test case.
|
||||
// Use XCTAssert and related functions to verify your tests produce the correct results.
|
||||
}
|
||||
|
||||
- (void)testPerformanceExample {
|
||||
// This is an example of a performance test case.
|
||||
[self measureBlock:^{
|
||||
// Put the code you want to measure the time of here.
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in a new issue