Unverified Commit 2784e495 authored by manuroe's avatar manuroe Committed by GitHub
Browse files

Merge pull request #70 from matrix-org/manuroe/objc_pk

OLMKit: Add objc wrappers for pk encryption/decryption
parents 2cace25f cc9a97f0
File deleted
...@@ -114,7 +114,7 @@ size_t olm_clear_pk_decryption( ...@@ -114,7 +114,7 @@ size_t olm_clear_pk_decryption(
/** Get the number of bytes required to store an olm private key /** Get the number of bytes required to store an olm private key
*/ */
size_t olm_pk_private_key_length(); size_t olm_pk_private_key_length(void);
/** DEPRECATED: Use olm_pk_private_key_length() /** DEPRECATED: Use olm_pk_private_key_length()
*/ */
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
3244277D2175EF700023EDF1 /* OLMKitPkTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3244277C2175EF700023EDF1 /* OLMKitPkTests.m */; };
3274F6021D9A633A005282E4 /* OLMKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3274F5F81D9A633A005282E4 /* OLMKit.framework */; }; 3274F6021D9A633A005282E4 /* OLMKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3274F5F81D9A633A005282E4 /* OLMKit.framework */; };
3274F6071D9A633A005282E4 /* OLMKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3274F6061D9A633A005282E4 /* OLMKitTests.m */; }; 3274F6071D9A633A005282E4 /* OLMKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3274F6061D9A633A005282E4 /* OLMKitTests.m */; };
3274F6131D9A698E005282E4 /* OLMKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 3274F6121D9A698E005282E4 /* OLMKit.h */; }; 3274F6131D9A698E005282E4 /* OLMKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 3274F6121D9A698E005282E4 /* OLMKit.h */; };
...@@ -27,6 +28,7 @@ ...@@ -27,6 +28,7 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
1B226B371526F2782C9D6372 /* Pods-OLMKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OLMKit.release.xcconfig"; path = "Pods/Target Support Files/Pods-OLMKit/Pods-OLMKit.release.xcconfig"; sourceTree = "<group>"; }; 1B226B371526F2782C9D6372 /* Pods-OLMKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OLMKit.release.xcconfig"; path = "Pods/Target Support Files/Pods-OLMKit/Pods-OLMKit.release.xcconfig"; sourceTree = "<group>"; };
3244277C2175EF700023EDF1 /* OLMKitPkTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OLMKitPkTests.m; sourceTree = "<group>"; };
3274F5F81D9A633A005282E4 /* OLMKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OLMKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3274F5F81D9A633A005282E4 /* OLMKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OLMKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3274F5FC1D9A633A005282E4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 3274F5FC1D9A633A005282E4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3274F6011D9A633A005282E4 /* OLMKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OLMKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3274F6011D9A633A005282E4 /* OLMKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OLMKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
...@@ -105,6 +107,7 @@ ...@@ -105,6 +107,7 @@
3274F6051D9A633A005282E4 /* OLMKitTests */ = { 3274F6051D9A633A005282E4 /* OLMKitTests */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
3244277C2175EF700023EDF1 /* OLMKitPkTests.m */,
3274F6061D9A633A005282E4 /* OLMKitTests.m */, 3274F6061D9A633A005282E4 /* OLMKitTests.m */,
32A151301DABDD4300400192 /* OLMKitGroupTests.m */, 32A151301DABDD4300400192 /* OLMKitGroupTests.m */,
3274F6081D9A633A005282E4 /* Info.plist */, 3274F6081D9A633A005282E4 /* Info.plist */,
...@@ -279,6 +282,7 @@ ...@@ -279,6 +282,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
3274F6071D9A633A005282E4 /* OLMKitTests.m in Sources */, 3274F6071D9A633A005282E4 /* OLMKitTests.m in Sources */,
3244277D2175EF700023EDF1 /* OLMKitPkTests.m in Sources */,
32A151311DABDD4300400192 /* OLMKitGroupTests.m in Sources */, 32A151311DABDD4300400192 /* OLMKitGroupTests.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
......
...@@ -193,6 +193,7 @@ ...@@ -193,6 +193,7 @@
} }
NSMutableData *pickle = [serializedData dataUsingEncoding:NSUTF8StringEncoding].mutableCopy; NSMutableData *pickle = [serializedData dataUsingEncoding:NSUTF8StringEncoding].mutableCopy;
size_t result = olm_unpickle_account(_account, key.bytes, key.length, pickle.mutableBytes, pickle.length); size_t result = olm_unpickle_account(_account, key.bytes, key.length, pickle.mutableBytes, pickle.length);
[pickle resetBytesInRange:NSMakeRange(0, pickle.length)];
if (result == olm_error()) { if (result == olm_error()) {
const char *olm_error = olm_account_last_error(_account); const char *olm_error = olm_account_last_error(_account);
NSString *errorString = [NSString stringWithUTF8String:olm_error]; NSString *errorString = [NSString stringWithUTF8String:olm_error];
...@@ -219,6 +220,7 @@ ...@@ -219,6 +220,7 @@
return nil; return nil;
} }
NSString *pickleString = [[NSString alloc] initWithData:pickled encoding:NSUTF8StringEncoding]; NSString *pickleString = [[NSString alloc] initWithData:pickled encoding:NSUTF8StringEncoding];
[pickled resetBytesInRange:NSMakeRange(0, pickled.length)];
return pickleString; return pickleString;
} }
......
...@@ -227,6 +227,7 @@ ...@@ -227,6 +227,7 @@
} }
NSMutableData *pickle = [serializedData dataUsingEncoding:NSUTF8StringEncoding].mutableCopy; NSMutableData *pickle = [serializedData dataUsingEncoding:NSUTF8StringEncoding].mutableCopy;
size_t result = olm_unpickle_inbound_group_session(session, key.bytes, key.length, pickle.mutableBytes, pickle.length); size_t result = olm_unpickle_inbound_group_session(session, key.bytes, key.length, pickle.mutableBytes, pickle.length);
[pickle resetBytesInRange:NSMakeRange(0, pickle.length)];
if (result == olm_error()) { if (result == olm_error()) {
const char *olm_error = olm_inbound_group_session_last_error(session); const char *olm_error = olm_inbound_group_session_last_error(session);
NSString *errorString = [NSString stringWithUTF8String:olm_error]; NSString *errorString = [NSString stringWithUTF8String:olm_error];
...@@ -253,6 +254,7 @@ ...@@ -253,6 +254,7 @@
return nil; return nil;
} }
NSString *pickleString = [[NSString alloc] initWithData:pickled encoding:NSUTF8StringEncoding]; NSString *pickleString = [[NSString alloc] initWithData:pickled encoding:NSUTF8StringEncoding];
[pickled resetBytesInRange:NSMakeRange(0, pickled.length)];
return pickleString; return pickleString;
} }
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#import <OLMKit/OLMUtility.h> #import <OLMKit/OLMUtility.h>
#import <OLMKit/OLMInboundGroupSession.h> #import <OLMKit/OLMInboundGroupSession.h>
#import <OLMKit/OLMOutboundGroupSession.h> #import <OLMKit/OLMOutboundGroupSession.h>
#import <OLMKit/OLMPkEncryption.h>
#import <OLMKit/OLMPkDecryption.h>
@interface OLMKit : NSObject @interface OLMKit : NSObject
......
...@@ -148,6 +148,7 @@ ...@@ -148,6 +148,7 @@
} }
NSMutableData *pickle = [serializedData dataUsingEncoding:NSUTF8StringEncoding].mutableCopy; NSMutableData *pickle = [serializedData dataUsingEncoding:NSUTF8StringEncoding].mutableCopy;
size_t result = olm_unpickle_outbound_group_session(session, key.bytes, key.length, pickle.mutableBytes, pickle.length); size_t result = olm_unpickle_outbound_group_session(session, key.bytes, key.length, pickle.mutableBytes, pickle.length);
[pickle resetBytesInRange:NSMakeRange(0, pickle.length)];
if (result == olm_error()) { if (result == olm_error()) {
const char *olm_error = olm_outbound_group_session_last_error(session); const char *olm_error = olm_outbound_group_session_last_error(session);
NSString *errorString = [NSString stringWithUTF8String:olm_error]; NSString *errorString = [NSString stringWithUTF8String:olm_error];
...@@ -174,6 +175,7 @@ ...@@ -174,6 +175,7 @@
return nil; return nil;
} }
NSString *pickleString = [[NSString alloc] initWithData:pickled encoding:NSUTF8StringEncoding]; NSString *pickleString = [[NSString alloc] initWithData:pickled encoding:NSUTF8StringEncoding];
[pickled resetBytesInRange:NSMakeRange(0, pickled.length)];
return pickleString; return pickleString;
} }
......
/*
Copyright 2018 New Vector 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.0OLMPKEncryption
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 "OLMPkMessage.h"
NS_ASSUME_NONNULL_BEGIN
@interface OLMPkEncryption : NSObject
/**
Set the recipient's public key for encrypting to.
@param recipientKey the recipient's public key.
*/
- (void)setRecipientKey:(NSString*)recipientKey;
/**
Encrypt a plaintext for the recipient.
@param message the message to encrypt.
@param error the error if any.
@return the encrypted message.
*/
- (OLMPkMessage *)encryptMessage:(NSString*)message error:(NSError* _Nullable *)error;
@end
NS_ASSUME_NONNULL_END
/*
Copyright 2018 New Vector 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 "OLMPkEncryption.h"
#include "olm/olm.h"
#include "olm/pk.h"
#include "OLMUtility.h"
@interface OLMPkEncryption ()
{
OlmPkEncryption *session;
}
@end
@implementation OLMPkEncryption
- (void)dealloc {
olm_clear_pk_encryption(session);
free(session);
}
- (instancetype)init {
self = [super init];
if (self) {
session = (OlmPkEncryption *)malloc(olm_pk_encryption_size());
olm_pk_encryption(session);
}
return self;
}
- (void)setRecipientKey:(NSString*)recipientKey {
NSData *recipientKeyData = [recipientKey dataUsingEncoding:NSUTF8StringEncoding];
olm_pk_encryption_set_recipient_key(session, recipientKeyData.bytes, recipientKeyData.length);
}
- (OLMPkMessage *)encryptMessage:(NSString *)message error:(NSError *__autoreleasing _Nullable *)error {
NSData *plaintextData = [message dataUsingEncoding:NSUTF8StringEncoding];
size_t randomLength = olm_pk_encrypt_random_length(session);
NSMutableData *random = [OLMUtility randomBytesOfLength:randomLength];
if (!random) {
return nil;
}
size_t ciphertextLength = olm_pk_ciphertext_length(session, plaintextData.length);
NSMutableData *ciphertext = [NSMutableData dataWithLength:ciphertextLength];
if (!ciphertext) {
return nil;
}
size_t macLength = olm_pk_mac_length(session);
NSMutableData *macData = [NSMutableData dataWithLength:macLength];
if (!ciphertext) {
return nil;
}
size_t ephemeralKeyLength = olm_pk_key_length();
NSMutableData *ephemeralKeyData = [NSMutableData dataWithLength:ephemeralKeyLength];
if (!ciphertext) {
return nil;
}
size_t result = olm_pk_encrypt(session,
plaintextData.bytes, plaintextData.length,
ciphertext.mutableBytes, ciphertext.length,
macData.mutableBytes, macLength,
ephemeralKeyData.mutableBytes, ephemeralKeyLength,
random.mutableBytes, randomLength);
if (result == olm_error()) {
const char *olm_error = olm_pk_encryption_last_error(session);
NSString *errorString = [NSString stringWithUTF8String:olm_error];
NSLog(@"[OLMPkEncryption] encryptMessage: olm_group_encrypt error: %@", errorString);
if (error && olm_error && errorString) {
*error = [NSError errorWithDomain:OLMErrorDomain
code:0
userInfo:@{
NSLocalizedDescriptionKey: errorString,
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_group_encrypt error: %@", errorString]
}];
}
return nil;
}
OLMPkMessage *encryptedMessage = [[OLMPkMessage alloc]
initWithCiphertext:[[NSString alloc] initWithData:ciphertext encoding:NSUTF8StringEncoding]
mac:[[NSString alloc] initWithData:macData encoding:NSUTF8StringEncoding]
ephemeralKey:[[NSString alloc] initWithData:ephemeralKeyData encoding:NSUTF8StringEncoding]];
return encryptedMessage;
}
@end
/*
Copyright 2018 New Vector 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"
#import "OLMPkMessage.h"
NS_ASSUME_NONNULL_BEGIN
@interface OLMPkDecryption : NSObject <OLMSerializable, NSSecureCoding>
/**
Initialise the key from the private part of a key as returned by `privateKey`.
Note that the pubkey is a base64 encoded string, but the private key is
an unencoded byte array.
@param privateKey the private key part.
@param error the error if any.
@return the associated public key.
*/
- (NSString *)setPrivateKey:(NSData*)privateKey error:(NSError* _Nullable *)error;
/**
Generate a new key to use for decrypting messages.
@param error the error if any.
@return the public part of the generated key.
*/
- (NSString *)generateKey:(NSError* _Nullable *)error;
/**
Get the private key.
@return the private key;
*/
- (NSData *)privateKey;
/**
Decrypt a ciphertext.
@param message the cipher message to decrypt.
@param error the error if any.
@return the decrypted message.
*/
- (NSString *)decryptMessage:(OLMPkMessage*)message error:(NSError* _Nullable *)error;
@end
NS_ASSUME_NONNULL_END
/*
Copyright 2018 New Vector 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 "OLMPkDecryption.h"
#include "olm/olm.h"
#include "olm/pk.h"
#include "OLMUtility.h"
@interface OLMPkDecryption ()
{
OlmPkDecryption *session;
}
@end
@implementation OLMPkDecryption
- (void)dealloc {
olm_clear_pk_decryption(session);
free(session);
}
- (instancetype)init {
self = [super init];
if (self) {
session = (OlmPkDecryption *)malloc(olm_pk_decryption_size());
olm_pk_decryption(session);
}
return self;
}
- (NSString *)setPrivateKey:(NSData *)privateKey error:(NSError *__autoreleasing _Nullable *)error {
size_t publicKeyLength = olm_pk_key_length();
NSMutableData *publicKeyData = [NSMutableData dataWithLength:publicKeyLength];
if (!publicKeyData) {
return nil;
}
size_t result = olm_pk_key_from_private(session,
publicKeyData.mutableBytes, publicKeyLength,
(void*)privateKey.bytes, privateKey.length);
if (result == olm_error()) {
const char *olm_error = olm_pk_decryption_last_error(session);
NSLog(@"[OLMPkDecryption] setPrivateKey: olm_pk_key_from_private error: %s", olm_error);
NSString *errorString = [NSString stringWithUTF8String:olm_error];
if (error && olm_error && errorString) {
*error = [NSError errorWithDomain:OLMErrorDomain
code:0
userInfo:@{
NSLocalizedDescriptionKey: errorString,
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_pk_key_from_private error: %@", errorString]
}];
}
return nil;
}
NSString *publicKey = [[NSString alloc] initWithData:publicKeyData encoding:NSUTF8StringEncoding];
return publicKey;
}
- (NSString *)generateKey:(NSError *__autoreleasing _Nullable *)error {
size_t randomLength = olm_pk_private_key_length();
NSMutableData *random = [OLMUtility randomBytesOfLength:randomLength];
if (!random) {
return nil;
}
size_t publicKeyLength = olm_pk_key_length();
NSMutableData *publicKeyData = [NSMutableData dataWithLength:publicKeyLength];
if (!publicKeyData) {
return nil;
}
size_t result = olm_pk_key_from_private(session,
publicKeyData.mutableBytes, publicKeyData.length,
random.mutableBytes, randomLength);
[random resetBytesInRange:NSMakeRange(0, randomLength)];
if (result == olm_error()) {
const char *olm_error = olm_pk_decryption_last_error(session);
NSLog(@"[OLMPkDecryption] generateKey: olm_pk_key_from_private error: %s", olm_error);
NSString *errorString = [NSString stringWithUTF8String:olm_error];
if (error && olm_error && errorString) {
*error = [NSError errorWithDomain:OLMErrorDomain
code:0
userInfo:@{
NSLocalizedDescriptionKey: errorString,
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_pk_key_from_private error: %@", errorString]
}];
}
return nil;
}
NSString *publicKey = [[NSString alloc] initWithData:publicKeyData encoding:NSUTF8StringEncoding];
return publicKey;
}
- (NSData *)privateKey {
size_t privateKeyLength = olm_pk_private_key_length();
NSMutableData *privateKeyData = [NSMutableData dataWithLength:privateKeyLength];
if (!privateKeyData) {
return nil;
}
size_t result = olm_pk_get_private_key(session,
privateKeyData.mutableBytes, privateKeyLength);
if (result == olm_error()) {
const char *olm_error = olm_pk_decryption_last_error(session);
NSLog(@"[OLMPkDecryption] privateKey: olm_pk_get_private_key error: %s", olm_error);
return nil;
}
NSData *privateKey = [privateKeyData copy];
[privateKeyData resetBytesInRange:NSMakeRange(0, privateKeyData.length)];
return privateKey;
}
-(NSString *)decryptMessage:(OLMPkMessage *)message error:(NSError *__autoreleasing _Nullable *)error {
NSData *messageData = [message.ciphertext dataUsingEncoding:NSUTF8StringEncoding];
NSData *macData = [message.mac dataUsingEncoding:NSUTF8StringEncoding];
NSData *ephemeralKeyData = [message.ephemeralKey dataUsingEncoding:NSUTF8StringEncoding];
if (!messageData || !macData || !ephemeralKeyData) {
return nil;
}
NSMutableData *mutMessage = messageData.mutableCopy;
size_t maxPlaintextLength = olm_pk_max_plaintext_length(session, mutMessage.length);
if (maxPlaintextLength == olm_error()) {
const char *olm_error = olm_pk_decryption_last_error(session);
NSString *errorString = [NSString stringWithUTF8String:olm_error];
NSLog(@"[OLMPkDecryption] decryptMessage: olm_pk_max_plaintext_length error: %@", errorString);
if (error && olm_error && errorString) {
*error = [NSError errorWithDomain:OLMErrorDomain
code:0
userInfo:@{
NSLocalizedDescriptionKey: errorString,
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_pk_max_plaintext_length error: %@", errorString]
}];
}
return nil;
}
mutMessage = messageData.mutableCopy;
NSMutableData *plaintextData = [NSMutableData dataWithLength:maxPlaintextLength];
size_t plaintextLength = olm_pk_decrypt(session,
ephemeralKeyData.bytes, ephemeralKeyData.length,
macData.bytes, macData.length,
mutMessage.mutableBytes, mutMessage.length,
plaintextData.mutableBytes, plaintextData.length);
if (plaintextLength == olm_error()) {
const char *olm_error = olm_pk_decryption_last_error(session);
NSString *errorString = [NSString stringWithUTF8String:olm_error];
NSLog(@"[OLMPkDecryption] decryptMessage: olm_pk_decrypt error: %@", errorString);
if (error && olm_error && errorString) {
*error = [NSError errorWithDomain:OLMErrorDomain
code:0
userInfo:@{
NSLocalizedDescriptionKey: errorString,
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_decrypt error: %@", errorString]
}];
}
return nil;
}
plaintextData.length = plaintextLength;
NSString *plaintext = [[NSString alloc] initWithData:plaintextData encoding:NSUTF8StringEncoding];
[plaintextData resetBytesInRange:NSMakeRange(0, plaintextData.length)];
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:OLMErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Bad length."}];
}
return nil;
}
size_t ephemeralLength = olm_pk_key_length();
NSMutableData *ephemeralBuffer = [NSMutableData dataWithLength:ephemeralLength];
NSMutableData *pickle = [serializedData dataUsingEncoding:NSUTF8StringEncoding].mutableCopy;
size_t result = olm_unpickle_pk_decryption(session,
key.bytes, key.length,
pickle.mutableBytes, pickle.length,
ephemeralBuffer.mutableBytes, ephemeralLength);
[pickle resetBytesInRange:NSMakeRange(0, pickle.length)];
if (result == olm_error()) {