commit
90b3613053
32 changed files with 2687 additions and 2 deletions
23
.gitignore
vendored
23
.gitignore
vendored
|
@ -5,4 +5,25 @@
|
||||||
/docs/signing.html
|
/docs/signing.html
|
||||||
/olm-*.tgz
|
/olm-*.tgz
|
||||||
/README.html
|
/README.html
|
||||||
/tracing/README.html
|
/tracing/README.html
|
||||||
|
|
||||||
|
# Xcode
|
||||||
|
build/
|
||||||
|
DerivedData/
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
xcuserdata/
|
||||||
|
*.moved-aside
|
||||||
|
*.xcuserstate
|
||||||
|
*.hmap
|
||||||
|
*.ipa
|
||||||
|
*.dSYM.zip
|
||||||
|
*.dSYM
|
||||||
|
Pods/
|
||||||
|
*.xcworkspace
|
|
@ -1,3 +1,10 @@
|
||||||
|
Changes in `2.0.1 <http://matrix.org/git/olm/commit/?h=2.0.1>`_
|
||||||
|
===============================================================
|
||||||
|
|
||||||
|
This release includes the following changes since 2.0.0
|
||||||
|
|
||||||
|
* Add OLMKit, the Objective-C wrapper.
|
||||||
|
|
||||||
Changes in `2.0.0 <http://matrix.org/git/olm/commit/?h=2.0.0>`_
|
Changes in `2.0.0 <http://matrix.org/git/olm/commit/?h=2.0.0>`_
|
||||||
===============================================================
|
===============================================================
|
||||||
|
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
MAJOR := 2
|
MAJOR := 2
|
||||||
MINOR := 0
|
MINOR := 0
|
||||||
PATCH := 0
|
PATCH := 1
|
||||||
VERSION := $(MAJOR).$(MINOR).$(PATCH)
|
VERSION := $(MAJOR).$(MINOR).$(PATCH)
|
||||||
PREFIX ?= /usr/local
|
PREFIX ?= /usr/local
|
||||||
BUILD_DIR := build
|
BUILD_DIR := build
|
||||||
|
|
61
OLMKit.podspec
Normal file
61
OLMKit.podspec
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
Pod::Spec.new do |s|
|
||||||
|
|
||||||
|
# The libolm version
|
||||||
|
MAJOR = 2
|
||||||
|
MINOR = 0
|
||||||
|
PATCH = 1
|
||||||
|
|
||||||
|
s.name = "OLMKit"
|
||||||
|
s.version = "#{MAJOR}.#{MINOR}.#{PATCH}"
|
||||||
|
s.summary = "An Objective-C wrapper of olm (http://matrix.org/git/olm)"
|
||||||
|
|
||||||
|
s.description = <<-DESC
|
||||||
|
olm is an implementation of the Double Ratchet cryptographic ratchet in C++
|
||||||
|
DESC
|
||||||
|
|
||||||
|
s.homepage = "http://matrix.org/git/olm"
|
||||||
|
|
||||||
|
s.license = { :type => "Apache License, Version 2.0", :file => "LICENSE" }
|
||||||
|
|
||||||
|
s.authors = { "Chris Ballinger" => "chrisballinger@gmail.com",
|
||||||
|
"matrix.org" => "support@matrix.org" }
|
||||||
|
|
||||||
|
s.platform = :ios, "5.0"
|
||||||
|
|
||||||
|
# Expose the Objective-C wrapper API of libolm
|
||||||
|
s.public_header_files = "xcode/OLMKit/*.h"
|
||||||
|
|
||||||
|
s.source = {
|
||||||
|
:git => "https://matrix.org/git/olm.git",
|
||||||
|
:tag => s.version.to_s
|
||||||
|
}
|
||||||
|
|
||||||
|
s.source_files = "xcode/OLMKit/*.{h,m}", "include/**/*.{h,hh}", "src/*.{c,cpp}", "lib/crypto-algorithms/sha256.c", "lib/crypto-algorithms/aes.c", "lib/curve25519-donna/curve25519-donna.c"
|
||||||
|
|
||||||
|
# Those files (including .c) are included by ed25519.c. We do not want to compile them twice
|
||||||
|
s.preserve_paths = "lib/ed25519/**/*.{h,c}"
|
||||||
|
|
||||||
|
s.library = "c++"
|
||||||
|
|
||||||
|
|
||||||
|
# Use the same compiler options for C and C++ as olm/Makefile
|
||||||
|
|
||||||
|
s.compiler_flags = "-g -O3 -DOLMLIB_VERSION_MAJOR=#{MAJOR} -DOLMLIB_VERSION_MINOR=#{MINOR} -DOLMLIB_VERSION_PATCH=#{PATCH}"
|
||||||
|
|
||||||
|
# For headers search paths, manage first the normal installation. Then, use paths used
|
||||||
|
# when the pod is local
|
||||||
|
s.xcconfig = {
|
||||||
|
'USER_HEADER_SEARCH_PATHS' =>"${PODS_ROOT}/OLMKit/include ${PODS_ROOT}/OLMKit/lib #{File.join(File.dirname(__FILE__), 'include')} #{File.join(File.dirname(__FILE__), 'lib')}"
|
||||||
|
}
|
||||||
|
|
||||||
|
s.subspec 'olmc' do |olmc|
|
||||||
|
olmc.source_files = "src/*.{c}", "lib/curve25519-donna.h", "lib/crypto-algorithms/sha256.{h,c}", "lib/crypto-algorithms/aes.{h,c}", "lib/curve25519-donna/curve25519-donna.c"
|
||||||
|
olmc.compiler_flags = ' -std=c99 -fPIC'
|
||||||
|
end
|
||||||
|
|
||||||
|
s.subspec 'olmcpp' do |olmcpp|
|
||||||
|
olmcpp.source_files = "src/*.{cpp}"
|
||||||
|
olmcpp.compiler_flags = ' -std=c++11 -fPIC'
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
16
README.rst
16
README.rst
|
@ -33,6 +33,14 @@ To build the javascript bindings, install emscripten from http://kripken.github.
|
||||||
|
|
||||||
make js
|
make js
|
||||||
|
|
||||||
|
To build the Xcode workspace for Objective-C bindings, run:
|
||||||
|
|
||||||
|
.. code:: bash
|
||||||
|
|
||||||
|
cd xcode
|
||||||
|
pod install
|
||||||
|
open OLMKit.xcworkspace
|
||||||
|
|
||||||
Release process
|
Release process
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -50,6 +58,14 @@ Release process
|
||||||
git tag $VERSION -s
|
git tag $VERSION -s
|
||||||
git push --tags
|
git push --tags
|
||||||
|
|
||||||
|
# OLMKit CocoaPod release
|
||||||
|
# Make sure the version OLMKit.podspec is the same as the git tag
|
||||||
|
# (this must be checked before git tagging)
|
||||||
|
pod spec lint OLMKit.podspec --use-libraries --allow-warnings
|
||||||
|
pod trunk push OLMKit.podspec --use-libraries --allow-warnings
|
||||||
|
# Check the pod has been successully published with:
|
||||||
|
pod search OLMKit
|
||||||
|
|
||||||
It's probably sensible to do the above on a release branch (``release-vx.y.z``
|
It's probably sensible to do the above on a release branch (``release-vx.y.z``
|
||||||
by convention), and merge back to master once complete.
|
by convention), and merge back to master once complete.
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "aes.h"
|
#include "aes.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
/****************************** MACROS ******************************/
|
/****************************** MACROS ******************************/
|
||||||
// The least significant byte of the word is rotated to the end.
|
// The least significant byte of the word is rotated to the end.
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
/*************************** HEADER FILES ***************************/
|
/*************************** HEADER FILES ***************************/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
#include <string.h>
|
||||||
#include "sha256.h"
|
#include "sha256.h"
|
||||||
|
|
||||||
/****************************** MACROS ******************************/
|
/****************************** MACROS ******************************/
|
||||||
|
|
528
xcode/OLMKit.xcodeproj/project.pbxproj
Normal file
528
xcode/OLMKit.xcodeproj/project.pbxproj
Normal file
|
@ -0,0 +1,528 @@
|
||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 46;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
3274F6021D9A633A005282E4 /* OLMKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3274F5F81D9A633A005282E4 /* OLMKit.framework */; };
|
||||||
|
3274F6071D9A633A005282E4 /* OLMKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3274F6061D9A633A005282E4 /* OLMKitTests.m */; };
|
||||||
|
3274F6131D9A698E005282E4 /* OLMKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 3274F6121D9A698E005282E4 /* OLMKit.h */; };
|
||||||
|
32A151311DABDD4300400192 /* OLMKitGroupTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 32A151301DABDD4300400192 /* OLMKitGroupTests.m */; };
|
||||||
|
7DBAD311AEA85CF6DB80DCFA /* libPods-OLMKitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7123FABE917D0FB140E036B7 /* libPods-OLMKitTests.a */; };
|
||||||
|
D667051A0BA47E17CCC4E5D7 /* libPods-OLMKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F2F22FE8F173AF845B882805 /* libPods-OLMKit.a */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
3274F6031D9A633A005282E4 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 3274F5EF1D9A633A005282E4 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 3274F5F71D9A633A005282E4;
|
||||||
|
remoteInfo = OLMKit;
|
||||||
|
};
|
||||||
|
/* End PBXContainerItemProxy 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>"; };
|
||||||
|
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>"; };
|
||||||
|
3274F6011D9A633A005282E4 /* OLMKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OLMKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
3274F6061D9A633A005282E4 /* OLMKitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OLMKitTests.m; sourceTree = "<group>"; };
|
||||||
|
3274F6081D9A633A005282E4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
3274F6121D9A698E005282E4 /* OLMKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OLMKit.h; sourceTree = "<group>"; };
|
||||||
|
32A151301DABDD4300400192 /* OLMKitGroupTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OLMKitGroupTests.m; sourceTree = "<group>"; };
|
||||||
|
7123FABE917D0FB140E036B7 /* libPods-OLMKitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-OLMKitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
875BA7A520258EA15A31DD82 /* Pods-OLMKitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OLMKitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-OLMKitTests/Pods-OLMKitTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
D48E486DAE1F59F4F7EA8C25 /* Pods-OLMKitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OLMKitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-OLMKitTests/Pods-OLMKitTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
E50E6B16E3433A5EB3297DEE /* Pods-OLMKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OLMKit.debug.xcconfig"; path = "Pods/Target Support Files/Pods-OLMKit/Pods-OLMKit.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
F2F22FE8F173AF845B882805 /* libPods-OLMKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-OLMKit.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
3274F5F41D9A633A005282E4 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
D667051A0BA47E17CCC4E5D7 /* libPods-OLMKit.a in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
3274F5FE1D9A633A005282E4 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
3274F6021D9A633A005282E4 /* OLMKit.framework in Frameworks */,
|
||||||
|
7DBAD311AEA85CF6DB80DCFA /* libPods-OLMKitTests.a in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
1FA3F53DFAAAA773F07F5E56 /* Pods */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E50E6B16E3433A5EB3297DEE /* Pods-OLMKit.debug.xcconfig */,
|
||||||
|
1B226B371526F2782C9D6372 /* Pods-OLMKit.release.xcconfig */,
|
||||||
|
875BA7A520258EA15A31DD82 /* Pods-OLMKitTests.debug.xcconfig */,
|
||||||
|
D48E486DAE1F59F4F7EA8C25 /* Pods-OLMKitTests.release.xcconfig */,
|
||||||
|
);
|
||||||
|
name = Pods;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
3274F5EE1D9A633A005282E4 = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
3274F5FA1D9A633A005282E4 /* OLMKit */,
|
||||||
|
3274F6051D9A633A005282E4 /* OLMKitTests */,
|
||||||
|
3274F5F91D9A633A005282E4 /* Products */,
|
||||||
|
1FA3F53DFAAAA773F07F5E56 /* Pods */,
|
||||||
|
A5D2E6F079A29F7CC2A8D9FE /* Frameworks */,
|
||||||
|
);
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
3274F5F91D9A633A005282E4 /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
3274F5F81D9A633A005282E4 /* OLMKit.framework */,
|
||||||
|
3274F6011D9A633A005282E4 /* OLMKitTests.xctest */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
3274F5FA1D9A633A005282E4 /* OLMKit */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
3274F6121D9A698E005282E4 /* OLMKit.h */,
|
||||||
|
3274F5FC1D9A633A005282E4 /* Info.plist */,
|
||||||
|
);
|
||||||
|
path = OLMKit;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
3274F6051D9A633A005282E4 /* OLMKitTests */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
3274F6061D9A633A005282E4 /* OLMKitTests.m */,
|
||||||
|
32A151301DABDD4300400192 /* OLMKitGroupTests.m */,
|
||||||
|
3274F6081D9A633A005282E4 /* Info.plist */,
|
||||||
|
);
|
||||||
|
path = OLMKitTests;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
A5D2E6F079A29F7CC2A8D9FE /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
F2F22FE8F173AF845B882805 /* libPods-OLMKit.a */,
|
||||||
|
7123FABE917D0FB140E036B7 /* libPods-OLMKitTests.a */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXHeadersBuildPhase section */
|
||||||
|
3274F5F51D9A633A005282E4 /* Headers */ = {
|
||||||
|
isa = PBXHeadersBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
3274F6131D9A698E005282E4 /* OLMKit.h in Headers */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXHeadersBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
3274F5F71D9A633A005282E4 /* OLMKit */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 3274F60C1D9A633B005282E4 /* Build configuration list for PBXNativeTarget "OLMKit" */;
|
||||||
|
buildPhases = (
|
||||||
|
7FBCB292198F4156D9CA3B8D /* [CP] Check Pods Manifest.lock */,
|
||||||
|
3274F5F31D9A633A005282E4 /* Sources */,
|
||||||
|
3274F5F41D9A633A005282E4 /* Frameworks */,
|
||||||
|
3274F5F51D9A633A005282E4 /* Headers */,
|
||||||
|
3274F5F61D9A633A005282E4 /* Resources */,
|
||||||
|
30F93582035CD30D211A6C76 /* [CP] Copy Pods Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = OLMKit;
|
||||||
|
productName = OLMKit;
|
||||||
|
productReference = 3274F5F81D9A633A005282E4 /* OLMKit.framework */;
|
||||||
|
productType = "com.apple.product-type.framework";
|
||||||
|
};
|
||||||
|
3274F6001D9A633A005282E4 /* OLMKitTests */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 3274F60F1D9A633B005282E4 /* Build configuration list for PBXNativeTarget "OLMKitTests" */;
|
||||||
|
buildPhases = (
|
||||||
|
47E69E5BE6A019858DC41D4F /* [CP] Check Pods Manifest.lock */,
|
||||||
|
3274F5FD1D9A633A005282E4 /* Sources */,
|
||||||
|
3274F5FE1D9A633A005282E4 /* Frameworks */,
|
||||||
|
3274F5FF1D9A633A005282E4 /* Resources */,
|
||||||
|
0A185F0CAE96B33A4CD91B6A /* [CP] Embed Pods Frameworks */,
|
||||||
|
793D0533290528B7C0E17CAD /* [CP] Copy Pods Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
3274F6041D9A633A005282E4 /* PBXTargetDependency */,
|
||||||
|
);
|
||||||
|
name = OLMKitTests;
|
||||||
|
productName = OLMKitTests;
|
||||||
|
productReference = 3274F6011D9A633A005282E4 /* OLMKitTests.xctest */;
|
||||||
|
productType = "com.apple.product-type.bundle.unit-test";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
3274F5EF1D9A633A005282E4 /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
LastUpgradeCheck = 0810;
|
||||||
|
ORGANIZATIONNAME = matrix.org;
|
||||||
|
TargetAttributes = {
|
||||||
|
3274F5F71D9A633A005282E4 = {
|
||||||
|
CreatedOnToolsVersion = 8.0;
|
||||||
|
ProvisioningStyle = Automatic;
|
||||||
|
};
|
||||||
|
3274F6001D9A633A005282E4 = {
|
||||||
|
CreatedOnToolsVersion = 8.0;
|
||||||
|
ProvisioningStyle = Automatic;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
buildConfigurationList = 3274F5F21D9A633A005282E4 /* Build configuration list for PBXProject "OLMKit" */;
|
||||||
|
compatibilityVersion = "Xcode 3.2";
|
||||||
|
developmentRegion = English;
|
||||||
|
hasScannedForEncodings = 0;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
);
|
||||||
|
mainGroup = 3274F5EE1D9A633A005282E4;
|
||||||
|
productRefGroup = 3274F5F91D9A633A005282E4 /* Products */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
3274F5F71D9A633A005282E4 /* OLMKit */,
|
||||||
|
3274F6001D9A633A005282E4 /* OLMKitTests */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
3274F5F61D9A633A005282E4 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
3274F5FF1D9A633A005282E4 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
0A185F0CAE96B33A4CD91B6A /* [CP] Embed Pods Frameworks */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "[CP] Embed Pods Frameworks";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-OLMKitTests/Pods-OLMKitTests-frameworks.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
30F93582035CD30D211A6C76 /* [CP] Copy Pods Resources */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "[CP] Copy Pods Resources";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-OLMKit/Pods-OLMKit-resources.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
47E69E5BE6A019858DC41D4F /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
793D0533290528B7C0E17CAD /* [CP] Copy Pods Resources */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "[CP] Copy Pods Resources";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-OLMKitTests/Pods-OLMKitTests-resources.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
7FBCB292198F4156D9CA3B8D /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
3274F5F31D9A633A005282E4 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
3274F5FD1D9A633A005282E4 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
3274F6071D9A633A005282E4 /* OLMKitTests.m in Sources */,
|
||||||
|
32A151311DABDD4300400192 /* OLMKitGroupTests.m in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXTargetDependency section */
|
||||||
|
3274F6041D9A633A005282E4 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 3274F5F71D9A633A005282E4 /* OLMKit */;
|
||||||
|
targetProxy = 3274F6031D9A633A005282E4 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
3274F60A1D9A633B005282E4 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_TESTABILITY = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
VERSION_INFO_PREFIX = "";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
3274F60B1D9A633B005282E4 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
VERSION_INFO_PREFIX = "";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
3274F60D1D9A633B005282E4 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = E50E6B16E3433A5EB3297DEE /* Pods-OLMKit.debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_IDENTITY = "";
|
||||||
|
DEFINES_MODULE = YES;
|
||||||
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
|
INFOPLIST_FILE = OLMKit/Info.plist;
|
||||||
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.matrix.OLMKit;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
3274F60E1D9A633B005282E4 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 1B226B371526F2782C9D6372 /* Pods-OLMKit.release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_IDENTITY = "";
|
||||||
|
DEFINES_MODULE = YES;
|
||||||
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
|
INFOPLIST_FILE = OLMKit/Info.plist;
|
||||||
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.matrix.OLMKit;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
3274F6101D9A633B005282E4 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 875BA7A520258EA15A31DD82 /* Pods-OLMKitTests.debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
INFOPLIST_FILE = OLMKitTests/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.matrix.OLMKitTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
3274F6111D9A633B005282E4 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = D48E486DAE1F59F4F7EA8C25 /* Pods-OLMKitTests.release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
INFOPLIST_FILE = OLMKitTests/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.matrix.OLMKitTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
3274F5F21D9A633A005282E4 /* Build configuration list for PBXProject "OLMKit" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
3274F60A1D9A633B005282E4 /* Debug */,
|
||||||
|
3274F60B1D9A633B005282E4 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
3274F60C1D9A633B005282E4 /* Build configuration list for PBXNativeTarget "OLMKit" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
3274F60D1D9A633B005282E4 /* Debug */,
|
||||||
|
3274F60E1D9A633B005282E4 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
3274F60F1D9A633B005282E4 /* Build configuration list for PBXNativeTarget "OLMKitTests" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
3274F6101D9A633B005282E4 /* Debug */,
|
||||||
|
3274F6111D9A633B005282E4 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = 3274F5EF1D9A633A005282E4 /* Project object */;
|
||||||
|
}
|
26
xcode/OLMKit/Info.plist
Normal file
26
xcode/OLMKit/Info.plist
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string></string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
51
xcode/OLMKit/OLMAccount.h
Normal file
51
xcode/OLMKit/OLMAccount.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 Chris Ballinger
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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"
|
||||||
|
|
||||||
|
@class OLMSession;
|
||||||
|
|
||||||
|
@interface OLMAccount : NSObject <OLMSerializable, NSSecureCoding>
|
||||||
|
|
||||||
|
/** Creates new account */
|
||||||
|
- (instancetype) initNewAccount;
|
||||||
|
|
||||||
|
/** public identity keys. base64 encoded in "curve25519" and "ed25519" keys */
|
||||||
|
- (NSDictionary*) identityKeys;
|
||||||
|
|
||||||
|
/** signs message with ed25519 key for account */
|
||||||
|
- (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) markOneTimeKeysAsPublished;
|
||||||
|
|
||||||
|
/** The largest number of one time keys this account can store. */
|
||||||
|
- (NSUInteger) maxOneTimeKeys;
|
||||||
|
|
||||||
|
/** Generates a number of new one time keys. If the total number of keys stored
|
||||||
|
* by this account exceeds -maxOneTimeKeys then the old keys are
|
||||||
|
* discarded. */
|
||||||
|
- (void) generateOneTimeKeys:(NSUInteger)numberOfKeys;
|
||||||
|
|
||||||
|
@end
|
265
xcode/OLMKit/OLMAccount.m
Normal file
265
xcode/OLMKit/OLMAccount.m
Normal file
|
@ -0,0 +1,265 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 Chris Ballinger
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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 "OLMAccount.h"
|
||||||
|
#import "OLMAccount_Private.h"
|
||||||
|
#import "OLMSession.h"
|
||||||
|
#import "OLMSession_Private.h"
|
||||||
|
#import "OLMUtility.h"
|
||||||
|
|
||||||
|
@import Security;
|
||||||
|
|
||||||
|
@implementation OLMAccount
|
||||||
|
|
||||||
|
- (void) dealloc {
|
||||||
|
olm_clear_account(_account);
|
||||||
|
free(_account);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) initializeAccountMemory {
|
||||||
|
size_t accountSize = olm_account_size();
|
||||||
|
_account = malloc(accountSize);
|
||||||
|
NSParameterAssert(_account != nil);
|
||||||
|
if (!_account) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
_account = olm_account(_account);
|
||||||
|
NSParameterAssert(_account != nil);
|
||||||
|
if (!_account) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype) init {
|
||||||
|
self = [super init];
|
||||||
|
if (!self) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
BOOL success = [self initializeAccountMemory];
|
||||||
|
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);
|
||||||
|
[random resetBytesInRange:NSMakeRange(0, random.length)];
|
||||||
|
if (accountResult == olm_error()) {
|
||||||
|
const char *error = olm_account_last_error(_account);
|
||||||
|
NSLog(@"error creating account: %s", error);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger) maxOneTimeKeys {
|
||||||
|
return olm_account_max_number_of_one_time_keys(_account);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** public identity keys */
|
||||||
|
- (NSDictionary*) identityKeys {
|
||||||
|
size_t identityKeysLength = olm_account_identity_keys_length(_account);
|
||||||
|
uint8_t *identityKeysBytes = malloc(identityKeysLength);
|
||||||
|
if (!identityKeysBytes) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
size_t result = olm_account_identity_keys(_account, identityKeysBytes, identityKeysLength);
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *error = olm_account_last_error(_account);
|
||||||
|
NSLog(@"error getting id keys: %s", error);
|
||||||
|
free(identityKeysBytes);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSData *idKeyData = [NSData dataWithBytesNoCopy:identityKeysBytes length:identityKeysLength freeWhenDone:YES];
|
||||||
|
NSError *error = nil;
|
||||||
|
NSDictionary *keysDictionary = [NSJSONSerialization JSONObjectWithData:idKeyData options:0 error:&error];
|
||||||
|
if (error) {
|
||||||
|
NSLog(@"Could not decode JSON: %@", error.localizedDescription);
|
||||||
|
}
|
||||||
|
return keysDictionary;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)signMessage:(NSData *)messageData {
|
||||||
|
size_t signatureLength = olm_account_signature_length(_account);
|
||||||
|
uint8_t *signatureBytes = malloc(signatureLength);
|
||||||
|
if (!signatureBytes) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t result = olm_account_sign(_account, messageData.bytes, messageData.length, signatureBytes, signatureLength);
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *error = olm_account_last_error(_account);
|
||||||
|
NSLog(@"error signing message: %s", error);
|
||||||
|
free(signatureBytes);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSData *signatureData = [NSData dataWithBytesNoCopy:signatureBytes length:signatureLength freeWhenDone:YES];
|
||||||
|
return [[NSString alloc] initWithData:signatureData encoding:NSUTF8StringEncoding];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary*) oneTimeKeys {
|
||||||
|
size_t otkLength = olm_account_one_time_keys_length(_account);
|
||||||
|
uint8_t *otkBytes = malloc(otkLength);
|
||||||
|
if (!otkBytes) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
size_t result = olm_account_one_time_keys(_account, otkBytes, otkLength);
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *error = olm_account_last_error(_account);
|
||||||
|
NSLog(@"error getting id keys: %s", error);
|
||||||
|
free(otkBytes);
|
||||||
|
}
|
||||||
|
NSData *otk = [NSData dataWithBytesNoCopy:otkBytes length:otkLength freeWhenDone:YES];
|
||||||
|
NSError *error = nil;
|
||||||
|
NSDictionary *keysDictionary = [NSJSONSerialization JSONObjectWithData:otk options:0 error:&error];
|
||||||
|
if (error) {
|
||||||
|
NSLog(@"Could not decode JSON: %@", error.localizedDescription);
|
||||||
|
}
|
||||||
|
return keysDictionary;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void) generateOneTimeKeys:(NSUInteger)numberOfKeys {
|
||||||
|
size_t randomLength = olm_account_generate_one_time_keys_random_length(_account, numberOfKeys);
|
||||||
|
NSMutableData *random = [OLMUtility randomBytesOfLength:randomLength];
|
||||||
|
size_t result = olm_account_generate_one_time_keys(_account, numberOfKeys, random.mutableBytes, random.length);
|
||||||
|
[random resetBytesInRange:NSMakeRange(0, random.length)];
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *error = olm_account_last_error(_account);
|
||||||
|
NSLog(@"error generating keys: %s", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) removeOneTimeKeysForSession:(OLMSession *)session {
|
||||||
|
NSParameterAssert(session != nil);
|
||||||
|
if (!session) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
size_t result = olm_remove_one_time_keys(self.account, session.session);
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *error = olm_account_last_error(_account);
|
||||||
|
NSLog(@"olm_remove_one_time_keys error: %s", error);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)markOneTimeKeysAsPublished
|
||||||
|
{
|
||||||
|
olm_account_mark_keys_as_published(self.account);
|
||||||
|
}
|
||||||
|
|
||||||
|
#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:OLMErrorDomain 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:OLMErrorDomain 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:OLMErrorDomain 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
|
25
xcode/OLMKit/OLMAccount_Private.h
Normal file
25
xcode/OLMKit/OLMAccount_Private.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 Chris Ballinger
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "olm/olm.h"
|
||||||
|
|
||||||
|
@interface OLMAccount()
|
||||||
|
|
||||||
|
@property (nonatomic) OlmAccount *account;
|
||||||
|
|
||||||
|
@end
|
30
xcode/OLMKit/OLMInboundGroupSession.h
Normal file
30
xcode/OLMKit/OLMInboundGroupSession.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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 error:(NSError**)error;
|
||||||
|
|
||||||
|
- (NSString*)sessionIdentifier;
|
||||||
|
|
||||||
|
/** base64 ciphertext -> UTF-8 plaintext */
|
||||||
|
- (NSString*)decryptMessage:(NSString*)message messageIndex:(NSUInteger*)messageIndex error:(NSError**)error;
|
||||||
|
|
||||||
|
@end
|
244
xcode/OLMKit/OLMInboundGroupSession.m
Normal file
244
xcode/OLMKit/OLMInboundGroupSession.m
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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 error:(NSError**)error {
|
||||||
|
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 *olm_error = olm_inbound_group_session_last_error(session);
|
||||||
|
|
||||||
|
NSString *errorString = [NSString stringWithUTF8String:olm_error];
|
||||||
|
NSLog(@"olm_init_inbound_group_session error: %@", errorString);
|
||||||
|
|
||||||
|
if (error && olm_error && errorString) {
|
||||||
|
*error = [NSError errorWithDomain:OLMErrorDomain
|
||||||
|
code:0
|
||||||
|
userInfo:@{
|
||||||
|
NSLocalizedDescriptionKey: errorString,
|
||||||
|
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_init_inbound_group_session error: %@", errorString]
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
NSLog(@"olm_inbound_group_session_id error: %s", error);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSString *idString = [[NSString alloc] initWithData:idData encoding:NSUTF8StringEncoding];
|
||||||
|
return idString;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)decryptMessage:(NSString *)message messageIndex:(NSUInteger*)messageIndex error:(NSError**)error
|
||||||
|
{
|
||||||
|
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 *olm_error = olm_inbound_group_session_last_error(session);
|
||||||
|
|
||||||
|
NSString *errorString = [NSString stringWithUTF8String:olm_error];
|
||||||
|
NSLog(@"olm_group_decrypt_max_plaintext_length error: %@", errorString);
|
||||||
|
|
||||||
|
if (error && olm_error && errorString) {
|
||||||
|
*error = [NSError errorWithDomain:OLMErrorDomain
|
||||||
|
code:0
|
||||||
|
userInfo:@{
|
||||||
|
NSLocalizedDescriptionKey: errorString,
|
||||||
|
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_group_decrypt_max_plaintext_length error: %@", errorString]
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
// message buffer is destroyed by olm_group_decrypt_max_plaintext_length
|
||||||
|
mutMessage = messageData.mutableCopy;
|
||||||
|
NSMutableData *plaintextData = [NSMutableData dataWithLength:maxPlaintextLength];
|
||||||
|
|
||||||
|
uint32_t message_index;
|
||||||
|
size_t plaintextLength = olm_group_decrypt(session, mutMessage.mutableBytes, mutMessage.length, plaintextData.mutableBytes, plaintextData.length, &message_index);
|
||||||
|
if (plaintextLength == olm_error()) {
|
||||||
|
const char *olm_error = olm_inbound_group_session_last_error(session);
|
||||||
|
|
||||||
|
NSString *errorString = [NSString stringWithUTF8String:olm_error];
|
||||||
|
NSLog(@"olm_group_decrypt error: %@", errorString);
|
||||||
|
|
||||||
|
if (error && olm_error && errorString) {
|
||||||
|
*error = [NSError errorWithDomain:OLMErrorDomain
|
||||||
|
code:0
|
||||||
|
userInfo:@{
|
||||||
|
NSLocalizedDescriptionKey: errorString,
|
||||||
|
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_group_decrypt error: %@", errorString]
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
plaintextData.length = plaintextLength;
|
||||||
|
NSString *plaintext = [[NSString alloc] initWithData:plaintextData encoding:NSUTF8StringEncoding];
|
||||||
|
[plaintextData resetBytesInRange:NSMakeRange(0, plaintextData.length)];
|
||||||
|
|
||||||
|
if (messageIndex)
|
||||||
|
{
|
||||||
|
*messageIndex = message_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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:OLMErrorDomain 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:OLMErrorDomain 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
|
31
xcode/OLMKit/OLMKit.h
Normal file
31
xcode/OLMKit/OLMKit.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 Chris Ballinger
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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 <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
//! Project version string for OLMKit, the same as libolm.
|
||||||
|
NSString *OLMKitVersionString();
|
||||||
|
|
||||||
|
// In this header, you should import all the public headers of your framework using statements like #import <OLMKit/PublicHeader.h>
|
||||||
|
|
||||||
|
#import <OLMKit/OLMAccount.h>
|
||||||
|
#import <OLMKit/OLMSession.h>
|
||||||
|
#import <OLMKit/OLMMessage.h>
|
||||||
|
#import <OLMKit/OLMUtility.h>
|
||||||
|
#import <OLMKit/OLMInboundGroupSession.h>
|
||||||
|
#import <OLMKit/OLMOutboundGroupSession.h>
|
29
xcode/OLMKit/OLMKit.m
Normal file
29
xcode/OLMKit/OLMKit.m
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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 "OLMKit.h"
|
||||||
|
|
||||||
|
#include "olm/olm.h"
|
||||||
|
|
||||||
|
NSString *OLMKitVersionString()
|
||||||
|
{
|
||||||
|
uint8_t major, minor, patch;
|
||||||
|
|
||||||
|
olm_get_library_version(&major, &minor, &patch);
|
||||||
|
|
||||||
|
return [NSString stringWithFormat:@"%tu.%tu.%tu", major, minor, patch];
|
||||||
|
}
|
38
xcode/OLMKit/OLMMessage.h
Normal file
38
xcode/OLMKit/OLMMessage.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 Chris Ballinger
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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>
|
||||||
|
|
||||||
|
/*
|
||||||
|
from olm.hh
|
||||||
|
static const size_t OLM_MESSAGE_TYPE_PRE_KEY = 0;
|
||||||
|
static const size_t OLM_MESSAGE_TYPE_MESSAGE = 1;
|
||||||
|
*/
|
||||||
|
typedef NS_ENUM(NSInteger, OLMMessageType) {
|
||||||
|
OLMMessageTypePreKey = 0,
|
||||||
|
OLMMessageTypeMessage = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
@interface OLMMessage : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, copy, readonly, nonnull) NSString *ciphertext;
|
||||||
|
@property (readonly) OLMMessageType type;
|
||||||
|
|
||||||
|
- (nullable instancetype) initWithCiphertext:(nonnull NSString*)ciphertext type:(OLMMessageType)type;
|
||||||
|
|
||||||
|
@end
|
34
xcode/OLMKit/OLMMessage.m
Normal file
34
xcode/OLMKit/OLMMessage.m
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 Chris Ballinger
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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 "OLMMessage.h"
|
||||||
|
|
||||||
|
@implementation OLMMessage
|
||||||
|
|
||||||
|
- (nullable instancetype) initWithCiphertext:(nonnull NSString*)ciphertext type:(OLMMessageType)type {
|
||||||
|
NSParameterAssert(ciphertext != nil);
|
||||||
|
self = [super init];
|
||||||
|
if (!self) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
_ciphertext = [ciphertext copy];
|
||||||
|
_type = type;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
32
xcode/OLMKit/OLMOutboundGroupSession.h
Normal file
32
xcode/OLMKit/OLMOutboundGroupSession.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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 error:(NSError**)error;
|
||||||
|
|
||||||
|
@end
|
220
xcode/OLMKit/OLMOutboundGroupSession.m
Normal file
220
xcode/OLMKit/OLMOutboundGroupSession.m
Normal file
|
@ -0,0 +1,220 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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);
|
||||||
|
[random resetBytesInRange:NSMakeRange(0, random.length)];
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *error = olm_outbound_group_session_last_error(session);
|
||||||
|
NSLog(@"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);
|
||||||
|
NSLog(@"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);
|
||||||
|
NSLog(@"olm_outbound_group_session_key error: %s", error);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSString *sessionKey = [[NSString alloc] initWithData:sessionKeyData encoding:NSUTF8StringEncoding];
|
||||||
|
[sessionKeyData resetBytesInRange:NSMakeRange(0, sessionKeyData.length)];
|
||||||
|
return sessionKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)encryptMessage:(NSString *)message error:(NSError**)error {
|
||||||
|
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 *olm_error = olm_outbound_group_session_last_error(session);
|
||||||
|
|
||||||
|
NSString *errorString = [NSString stringWithUTF8String:olm_error];
|
||||||
|
NSLog(@"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;
|
||||||
|
}
|
||||||
|
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:OLMErrorDomain 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:OLMErrorDomain 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:OLMErrorDomain 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
|
29
xcode/OLMKit/OLMSerializable.h
Normal file
29
xcode/OLMKit/OLMSerializable.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 Chris Ballinger
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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>
|
||||||
|
|
||||||
|
@protocol OLMSerializable <NSObject>
|
||||||
|
|
||||||
|
/** Initializes from encrypted serialized data. Will throw error if invalid key or invalid base64. */
|
||||||
|
- (instancetype) initWithSerializedData:(NSString*)serializedData key:(NSData*)key error:(NSError**)error;
|
||||||
|
|
||||||
|
/** Serializes and encrypts object data, outputs base64 blob */
|
||||||
|
- (NSString*) serializeDataWithKey:(NSData*)key error:(NSError**)error;
|
||||||
|
|
||||||
|
@end
|
44
xcode/OLMKit/OLMSession.h
Normal file
44
xcode/OLMKit/OLMSession.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 Chris Ballinger
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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 "OLMAccount.h"
|
||||||
|
#import "OLMMessage.h"
|
||||||
|
|
||||||
|
@interface OLMSession : NSObject <OLMSerializable, NSSecureCoding>
|
||||||
|
|
||||||
|
- (instancetype) initOutboundSessionWithAccount:(OLMAccount*)account theirIdentityKey:(NSString*)theirIdentityKey theirOneTimeKey:(NSString*)theirOneTimeKey error:(NSError**)error;
|
||||||
|
|
||||||
|
- (instancetype) initInboundSessionWithAccount:(OLMAccount*)account oneTimeKeyMessage:(NSString*)oneTimeKeyMessage error:(NSError**)error;
|
||||||
|
|
||||||
|
- (instancetype) initInboundSessionWithAccount:(OLMAccount*)account theirIdentityKey:(NSString*)theirIdentityKey oneTimeKeyMessage:(NSString*)oneTimeKeyMessage error:(NSError**)error;
|
||||||
|
|
||||||
|
- (NSString*) sessionIdentifier;
|
||||||
|
|
||||||
|
- (BOOL) matchesInboundSession:(NSString*)oneTimeKeyMessage;
|
||||||
|
|
||||||
|
- (BOOL) matchesInboundSessionFrom:(NSString*)theirIdentityKey oneTimeKeyMessage:(NSString *)oneTimeKeyMessage;
|
||||||
|
|
||||||
|
/** UTF-8 plaintext -> base64 ciphertext */
|
||||||
|
- (OLMMessage*) encryptMessage:(NSString*)message error:(NSError**)error;
|
||||||
|
|
||||||
|
/** base64 ciphertext -> UTF-8 plaintext */
|
||||||
|
- (NSString*) decryptMessage:(OLMMessage*)message error:(NSError**)error;
|
||||||
|
|
||||||
|
@end
|
381
xcode/OLMKit/OLMSession.m
Normal file
381
xcode/OLMKit/OLMSession.m
Normal file
|
@ -0,0 +1,381 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 Chris Ballinger
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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 "OLMSession.h"
|
||||||
|
#import "OLMUtility.h"
|
||||||
|
#import "OLMAccount_Private.h"
|
||||||
|
#import "OLMSession_Private.h"
|
||||||
|
#include "olm/olm.h"
|
||||||
|
|
||||||
|
@implementation OLMSession
|
||||||
|
|
||||||
|
- (void) dealloc {
|
||||||
|
olm_clear_session(_session);
|
||||||
|
free(_session);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) initializeSessionMemory {
|
||||||
|
size_t size = olm_session_size();
|
||||||
|
_session = malloc(size);
|
||||||
|
NSParameterAssert(_session != nil);
|
||||||
|
if (!_session) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
_session = olm_session(_session);
|
||||||
|
NSParameterAssert(_session != nil);
|
||||||
|
if (!_session) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype) init {
|
||||||
|
self = [super init];
|
||||||
|
if (!self) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
BOOL success = [self initializeSessionMemory];
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype) initOutboundSessionWithAccount:(OLMAccount*)account theirIdentityKey:(NSString*)theirIdentityKey theirOneTimeKey:(NSString*)theirOneTimeKey error:(NSError**)error {
|
||||||
|
self = [self initWithAccount:account];
|
||||||
|
if (!self) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSMutableData *random = [OLMUtility randomBytesOfLength:olm_create_outbound_session_random_length(_session)];
|
||||||
|
NSData *idKey = [theirIdentityKey dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
NSData *otKey = [theirOneTimeKey dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
size_t result = olm_create_outbound_session(_session, account.account, idKey.bytes, idKey.length, otKey.bytes, otKey.length, random.mutableBytes, random.length);
|
||||||
|
[random resetBytesInRange:NSMakeRange(0, random.length)];
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *olm_error = olm_session_last_error(_session);
|
||||||
|
|
||||||
|
NSString *errorString = [NSString stringWithUTF8String:olm_error];
|
||||||
|
NSLog(@"olm_create_outbound_session error: %@", errorString);
|
||||||
|
|
||||||
|
if (error && olm_error && errorString) {
|
||||||
|
*error = [NSError errorWithDomain:OLMErrorDomain
|
||||||
|
code:0
|
||||||
|
userInfo:@{
|
||||||
|
NSLocalizedDescriptionKey: errorString,
|
||||||
|
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_create_outbound_session error: %@", errorString]
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype) initInboundSessionWithAccount:(OLMAccount*)account oneTimeKeyMessage:(NSString*)oneTimeKeyMessage error:(NSError**)error {
|
||||||
|
self = [self initWithAccount:account];
|
||||||
|
if (!self) {
|
||||||
|
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()) {
|
||||||
|
const char *olm_error = olm_session_last_error(_session);
|
||||||
|
|
||||||
|
NSString *errorString = [NSString stringWithUTF8String:olm_error];
|
||||||
|
NSLog(@"olm_create_inbound_session error: %@", errorString);
|
||||||
|
|
||||||
|
if (error && olm_error && errorString) {
|
||||||
|
*error = [NSError errorWithDomain:OLMErrorDomain
|
||||||
|
code:0
|
||||||
|
userInfo:@{
|
||||||
|
NSLocalizedDescriptionKey: errorString,
|
||||||
|
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_create_inbound_session error: %@", errorString]
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype) initInboundSessionWithAccount:(OLMAccount*)account theirIdentityKey:(NSString*)theirIdentityKey oneTimeKeyMessage:(NSString*)oneTimeKeyMessage error:(NSError**)error {
|
||||||
|
self = [self initWithAccount:account];
|
||||||
|
if (!self) {
|
||||||
|
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);
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *olm_error = olm_session_last_error(_session);
|
||||||
|
|
||||||
|
NSString *errorString = [NSString stringWithUTF8String:olm_error];
|
||||||
|
NSLog(@"olm_create_inbound_session_from error: %@", errorString);
|
||||||
|
|
||||||
|
if (error && olm_error && errorString) {
|
||||||
|
*error = [NSError errorWithDomain:OLMErrorDomain
|
||||||
|
code:0
|
||||||
|
userInfo:@{
|
||||||
|
NSLocalizedDescriptionKey: errorString,
|
||||||
|
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_create_inbound_session_from error: %@", errorString]
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString*) sessionIdentifier {
|
||||||
|
size_t length = olm_session_id_length(_session);
|
||||||
|
NSMutableData *idData = [NSMutableData dataWithLength:length];
|
||||||
|
if (!idData) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
size_t result = olm_session_id(_session, idData.mutableBytes, idData.length);
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *error = olm_session_last_error(_session);
|
||||||
|
NSLog(@"olm_session_id error: %s", error);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSString *idString = [[NSString alloc] initWithData:idData encoding:NSUTF8StringEncoding];
|
||||||
|
return idString;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)matchesInboundSession:(NSString *)oneTimeKeyMessage {
|
||||||
|
NSMutableData *otk = [NSMutableData dataWithData:[oneTimeKeyMessage dataUsingEncoding:NSUTF8StringEncoding]];
|
||||||
|
|
||||||
|
size_t result = olm_matches_inbound_session(_session, otk.mutableBytes, otk.length);
|
||||||
|
if (result == 1) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *error = olm_session_last_error(_session);
|
||||||
|
NSLog(@"olm_matches_inbound_session error: %s", error);
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)matchesInboundSessionFrom:(NSString *)theirIdentityKey oneTimeKeyMessage:(NSString *)oneTimeKeyMessage {
|
||||||
|
NSData *idKey = [theirIdentityKey dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
NSMutableData *otk = [NSMutableData dataWithData:[oneTimeKeyMessage dataUsingEncoding:NSUTF8StringEncoding]];
|
||||||
|
|
||||||
|
size_t result = olm_matches_inbound_session_from(_session,
|
||||||
|
idKey.bytes, idKey.length,
|
||||||
|
otk.mutableBytes, otk.length);
|
||||||
|
if (result == 1) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *error = olm_session_last_error(_session);
|
||||||
|
NSLog(@"olm_matches_inbound_session error: %s", error);
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (OLMMessage*) encryptMessage:(NSString*)message error:(NSError**)error {
|
||||||
|
size_t messageType = olm_encrypt_message_type(_session);
|
||||||
|
size_t randomLength = olm_encrypt_random_length(_session);
|
||||||
|
NSMutableData *random = [OLMUtility randomBytesOfLength:randomLength];
|
||||||
|
NSData *plaintextData = [message dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
size_t ciphertextLength = olm_encrypt_message_length(_session, plaintextData.length);
|
||||||
|
NSMutableData *ciphertext = [NSMutableData dataWithLength:ciphertextLength];
|
||||||
|
if (!ciphertext) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
size_t result = olm_encrypt(_session, plaintextData.bytes, plaintextData.length, random.mutableBytes, random.length, ciphertext.mutableBytes, ciphertext.length);
|
||||||
|
[random resetBytesInRange:NSMakeRange(0, random.length)];
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *olm_error = olm_session_last_error(_session);
|
||||||
|
|
||||||
|
NSString *errorString = [NSString stringWithUTF8String:olm_error];
|
||||||
|
NSLog(@"olm_encrypt error: %@", errorString);
|
||||||
|
|
||||||
|
if (error && olm_error && errorString) {
|
||||||
|
*error = [NSError errorWithDomain:OLMErrorDomain
|
||||||
|
code:0
|
||||||
|
userInfo:@{
|
||||||
|
NSLocalizedDescriptionKey: errorString,
|
||||||
|
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_encrypt error: %@", errorString]
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSString *ciphertextString = [[NSString alloc] initWithData:ciphertext encoding:NSUTF8StringEncoding];
|
||||||
|
OLMMessage *encryptedMessage = [[OLMMessage alloc] initWithCiphertext:ciphertextString type:messageType];
|
||||||
|
return encryptedMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString*) decryptMessage:(OLMMessage*)message error:(NSError**)error {
|
||||||
|
NSParameterAssert(message != nil);
|
||||||
|
NSData *messageData = [message.ciphertext dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
if (!messageData) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSMutableData *mutMessage = messageData.mutableCopy;
|
||||||
|
size_t maxPlaintextLength = olm_decrypt_max_plaintext_length(_session, message.type, mutMessage.mutableBytes, mutMessage.length);
|
||||||
|
if (maxPlaintextLength == olm_error()) {
|
||||||
|
const char *olm_error = olm_session_last_error(_session);
|
||||||
|
|
||||||
|
NSString *errorString = [NSString stringWithUTF8String:olm_error];
|
||||||
|
NSLog(@"olm_decrypt_max_plaintext_length error: %@", errorString);
|
||||||
|
|
||||||
|
if (error && olm_error && errorString) {
|
||||||
|
*error = [NSError errorWithDomain:OLMErrorDomain
|
||||||
|
code:0
|
||||||
|
userInfo:@{
|
||||||
|
NSLocalizedDescriptionKey: errorString,
|
||||||
|
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_decrypt_max_plaintext_length error: %@", errorString]
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
// message buffer is destroyed by olm_decrypt_max_plaintext_length
|
||||||
|
mutMessage = messageData.mutableCopy;
|
||||||
|
NSMutableData *plaintextData = [NSMutableData dataWithLength:maxPlaintextLength];
|
||||||
|
size_t plaintextLength = olm_decrypt(_session, message.type, mutMessage.mutableBytes, mutMessage.length, plaintextData.mutableBytes, plaintextData.length);
|
||||||
|
if (plaintextLength == olm_error()) {
|
||||||
|
const char *olm_error = olm_session_last_error(_session);
|
||||||
|
|
||||||
|
NSString *errorString = [NSString stringWithUTF8String:olm_error];
|
||||||
|
NSLog(@"olm_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**)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;
|
||||||
|
}
|
||||||
|
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:OLMErrorDomain 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:OLMErrorDomain 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
|
26
xcode/OLMKit/OLMSession_Private.h
Normal file
26
xcode/OLMKit/OLMSession_Private.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 Chris Ballinger
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "olm/olm.h"
|
||||||
|
|
||||||
|
@interface OLMSession()
|
||||||
|
|
||||||
|
@property (nonatomic) OlmSession *session;
|
||||||
|
@property (nonatomic, strong) OLMAccount *account;
|
||||||
|
|
||||||
|
@end
|
49
xcode/OLMKit/OLMUtility.h
Normal file
49
xcode/OLMKit/OLMUtility.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 Chris Ballinger
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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>
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const OLMErrorDomain;
|
||||||
|
|
||||||
|
@interface OLMUtility : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
Calculate the SHA-256 hash of the input and encodes it as base64.
|
||||||
|
|
||||||
|
@param message the message to hash.
|
||||||
|
@return the base64-encoded hash value.
|
||||||
|
*/
|
||||||
|
- (NSString*)sha256:(NSData*)message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Verify an ed25519 signature.
|
||||||
|
|
||||||
|
@param signature the base64-encoded signature to be checked.
|
||||||
|
@param key the ed25519 key.
|
||||||
|
@param message the message which was signed.
|
||||||
|
@param the result error if there is a problem with the verification.
|
||||||
|
If the key was too small then the message will be "OLM.INVALID_BASE64".
|
||||||
|
If the signature was invalid then the message will be "OLM.BAD_MESSAGE_MAC".
|
||||||
|
|
||||||
|
@return YES if valid.
|
||||||
|
*/
|
||||||
|
- (BOOL)verifyEd25519Signature:(NSString*)signature key:(NSString*)key message:(NSData*)message error:(NSError**)error;
|
||||||
|
|
||||||
|
+ (NSMutableData*) randomBytesOfLength:(NSUInteger)length;
|
||||||
|
|
||||||
|
@end
|
121
xcode/OLMKit/OLMUtility.m
Normal file
121
xcode/OLMKit/OLMUtility.m
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 Chris Ballinger
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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 "OLMUtility.h"
|
||||||
|
|
||||||
|
#include "olm/olm.h"
|
||||||
|
|
||||||
|
NSString *const OLMErrorDomain = @"org.matrix.olm";
|
||||||
|
|
||||||
|
@interface OLMUtility()
|
||||||
|
|
||||||
|
@property (nonatomic) OlmUtility *utility;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OLMUtility
|
||||||
|
|
||||||
|
- (void) dealloc {
|
||||||
|
olm_clear_utility(_utility);
|
||||||
|
free(_utility);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) initializeUtilityMemory {
|
||||||
|
size_t utilitySize = olm_utility_size();
|
||||||
|
_utility = malloc(utilitySize);
|
||||||
|
NSParameterAssert(_utility != nil);
|
||||||
|
if (!_utility) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
_utility = olm_utility(_utility);
|
||||||
|
NSParameterAssert(_utility != nil);
|
||||||
|
if (!_utility) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype) init {
|
||||||
|
self = [super init];
|
||||||
|
if (!self) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
BOOL success = [self initializeUtilityMemory];
|
||||||
|
if (!success) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)sha256:(NSData *)message {
|
||||||
|
size_t length = olm_sha256_length(_utility);
|
||||||
|
|
||||||
|
NSMutableData *shaData = [NSMutableData dataWithLength:length];
|
||||||
|
if (!shaData) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t result = olm_sha256(_utility, message.bytes, message.length, shaData.mutableBytes, shaData.length);
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *error = olm_utility_last_error(_utility);
|
||||||
|
NSLog(@"olm_sha256 error: %s", error);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *sha = [[NSString alloc] initWithData:shaData encoding:NSUTF8StringEncoding];
|
||||||
|
return sha;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)verifyEd25519Signature:(NSString*)signature key:(NSString*)key message:(NSData*)message error:(NSError**)error {
|
||||||
|
|
||||||
|
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
NSData *signatureData = [signature dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
|
||||||
|
size_t result = olm_ed25519_verify(_utility,
|
||||||
|
keyData.bytes, keyData.length,
|
||||||
|
message.bytes, message.length,
|
||||||
|
(void*)signatureData.bytes, signatureData.length
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == olm_error()) {
|
||||||
|
if (error) {
|
||||||
|
NSDictionary *userInfo = @{NSLocalizedFailureReasonErrorKey: [NSString stringWithUTF8String:olm_utility_last_error(_utility)]};
|
||||||
|
|
||||||
|
// @TODO
|
||||||
|
*error = [[NSError alloc] initWithDomain:@"OLMKitErrorDomain" code:0 userInfo:userInfo];
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSMutableData*) randomBytesOfLength:(NSUInteger)length {
|
||||||
|
NSMutableData *randomData = [NSMutableData dataWithLength:length];
|
||||||
|
if (!randomData) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
int result = SecRandomCopyBytes(kSecRandomDefault, randomData.length, randomData.mutableBytes);
|
||||||
|
if (result != 0) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return randomData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
22
xcode/OLMKitTests/Info.plist
Normal file
22
xcode/OLMKitTests/Info.plist
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>BNDL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
94
xcode/OLMKitTests/OLMKitGroupTests.m
Normal file
94
xcode/OLMKitTests/OLMKitGroupTests.m
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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 <XCTest/XCTest.h>
|
||||||
|
|
||||||
|
#import <OLMKit/OLMKit.h>
|
||||||
|
|
||||||
|
#include "olm/olm.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)testAliceAndBob {
|
||||||
|
NSError *error;
|
||||||
|
|
||||||
|
OLMOutboundGroupSession *aliceSession = [[OLMOutboundGroupSession alloc] initOutboundGroupSession];
|
||||||
|
XCTAssertGreaterThan(aliceSession.sessionIdentifier.length, 0);
|
||||||
|
XCTAssertGreaterThan(aliceSession.sessionKey.length, 0);
|
||||||
|
XCTAssertEqual(aliceSession.messageIndex, 0);
|
||||||
|
|
||||||
|
// Store the session key before starting encrypting
|
||||||
|
NSString *sessionKey = aliceSession.sessionKey;
|
||||||
|
|
||||||
|
NSString *message = @"Hello!";
|
||||||
|
NSString *aliceToBobMsg = [aliceSession encryptMessage:message error:&error];
|
||||||
|
|
||||||
|
XCTAssertEqual(aliceSession.messageIndex, 1);
|
||||||
|
XCTAssertGreaterThanOrEqual(aliceToBobMsg.length, 0);
|
||||||
|
XCTAssertNil(error);
|
||||||
|
|
||||||
|
OLMInboundGroupSession *bobSession = [[OLMInboundGroupSession alloc] initInboundGroupSessionWithSessionKey:sessionKey error:&error];
|
||||||
|
XCTAssertEqualObjects(aliceSession.sessionIdentifier, bobSession.sessionIdentifier);
|
||||||
|
XCTAssertNil(error);
|
||||||
|
|
||||||
|
NSUInteger messageIndex;
|
||||||
|
|
||||||
|
NSString *plaintext = [bobSession decryptMessage:aliceToBobMsg messageIndex:&messageIndex error:&error];
|
||||||
|
XCTAssertEqualObjects(message, plaintext);
|
||||||
|
|
||||||
|
XCTAssertEqual(messageIndex, 0);
|
||||||
|
XCTAssertNil(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testOutboundGroupSessionSerialization {
|
||||||
|
|
||||||
|
OLMOutboundGroupSession *aliceSession = [[OLMOutboundGroupSession alloc] initOutboundGroupSession];
|
||||||
|
|
||||||
|
NSData *aliceData = [NSKeyedArchiver archivedDataWithRootObject:aliceSession];
|
||||||
|
OLMOutboundGroupSession *aliceSession2 = [NSKeyedUnarchiver unarchiveObjectWithData:aliceData];
|
||||||
|
|
||||||
|
XCTAssertEqualObjects(aliceSession2.sessionKey, aliceSession.sessionKey);
|
||||||
|
XCTAssertEqualObjects(aliceSession2.sessionIdentifier, aliceSession.sessionIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testInboundGroupSessionSerialization {
|
||||||
|
|
||||||
|
OLMOutboundGroupSession *aliceSession = [[OLMOutboundGroupSession alloc] initOutboundGroupSession];
|
||||||
|
|
||||||
|
OLMInboundGroupSession *bobSession = [[OLMInboundGroupSession alloc] initInboundGroupSessionWithSessionKey:aliceSession.sessionKey error:nil];
|
||||||
|
|
||||||
|
NSData *bobData = [NSKeyedArchiver archivedDataWithRootObject:bobSession];
|
||||||
|
OLMInboundGroupSession *bobSession2 = [NSKeyedUnarchiver unarchiveObjectWithData:bobData];
|
||||||
|
|
||||||
|
XCTAssertEqualObjects(bobSession2.sessionIdentifier, aliceSession.sessionIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
206
xcode/OLMKitTests/OLMKitTests.m
Normal file
206
xcode/OLMKitTests/OLMKitTests.m
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 Chris Ballinger
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2016 Vector Creations 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 <XCTest/XCTest.h>
|
||||||
|
#import <OLMKit/OLMKit.h>
|
||||||
|
|
||||||
|
@interface OLMKitTests : XCTestCase
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OLMKitTests
|
||||||
|
|
||||||
|
- (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)testAliceAndBob {
|
||||||
|
NSError *error;
|
||||||
|
|
||||||
|
OLMAccount *alice = [[OLMAccount alloc] initNewAccount];
|
||||||
|
OLMAccount *bob = [[OLMAccount alloc] initNewAccount];
|
||||||
|
[bob generateOneTimeKeys:5];
|
||||||
|
NSDictionary *bobIdKeys = bob.identityKeys;
|
||||||
|
NSString *bobIdKey = bobIdKeys[@"curve25519"];
|
||||||
|
NSDictionary *bobOneTimeKeys = bob.oneTimeKeys;
|
||||||
|
NSParameterAssert(bobIdKey != nil);
|
||||||
|
NSParameterAssert(bobOneTimeKeys != nil);
|
||||||
|
__block NSString *bobOneTimeKey = nil;
|
||||||
|
NSDictionary *bobOtkCurve25519 = bobOneTimeKeys[@"curve25519"];
|
||||||
|
[bobOtkCurve25519 enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
|
||||||
|
bobOneTimeKey = obj;
|
||||||
|
}];
|
||||||
|
XCTAssert([bobOneTimeKey isKindOfClass:[NSString class]]);
|
||||||
|
|
||||||
|
OLMSession *aliceSession = [[OLMSession alloc] initOutboundSessionWithAccount:alice theirIdentityKey:bobIdKey theirOneTimeKey:bobOneTimeKey error:nil];
|
||||||
|
NSString *message = @"Hello!";
|
||||||
|
OLMMessage *aliceToBobMsg = [aliceSession encryptMessage:message error:&error];
|
||||||
|
XCTAssertNil(error);
|
||||||
|
|
||||||
|
OLMSession *bobSession = [[OLMSession alloc] initInboundSessionWithAccount:bob oneTimeKeyMessage:aliceToBobMsg.ciphertext error:nil];
|
||||||
|
NSString *plaintext = [bobSession decryptMessage:aliceToBobMsg error:&error];
|
||||||
|
XCTAssertEqualObjects(message, plaintext);
|
||||||
|
XCTAssertNil(error);
|
||||||
|
|
||||||
|
XCTAssert([bobSession matchesInboundSession:aliceToBobMsg.ciphertext]);
|
||||||
|
XCTAssertFalse([aliceSession matchesInboundSession:@"ARandomOtkMessage"]);
|
||||||
|
|
||||||
|
NSString *aliceIdKey = alice.identityKeys[@"curve25519"];
|
||||||
|
XCTAssert([bobSession matchesInboundSessionFrom:aliceIdKey oneTimeKeyMessage:aliceToBobMsg.ciphertext]);
|
||||||
|
XCTAssertFalse([bobSession matchesInboundSessionFrom:@"ARandomIdKey" oneTimeKeyMessage:aliceToBobMsg.ciphertext]);
|
||||||
|
XCTAssertFalse([bobSession matchesInboundSessionFrom:aliceIdKey oneTimeKeyMessage:@"ARandomOtkMessage"]);
|
||||||
|
|
||||||
|
BOOL success = [bob removeOneTimeKeysForSession:bobSession];
|
||||||
|
XCTAssertTrue(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) testBackAndForth {
|
||||||
|
OLMAccount *alice = [[OLMAccount alloc] initNewAccount];
|
||||||
|
OLMAccount *bob = [[OLMAccount alloc] initNewAccount];
|
||||||
|
[bob generateOneTimeKeys:1];
|
||||||
|
NSDictionary *bobIdKeys = bob.identityKeys;
|
||||||
|
NSString *bobIdKey = bobIdKeys[@"curve25519"];
|
||||||
|
NSDictionary *bobOneTimeKeys = bob.oneTimeKeys;
|
||||||
|
NSParameterAssert(bobIdKey != nil);
|
||||||
|
NSParameterAssert(bobOneTimeKeys != nil);
|
||||||
|
__block NSString *bobOneTimeKey = nil;
|
||||||
|
NSDictionary *bobOtkCurve25519 = bobOneTimeKeys[@"curve25519"];
|
||||||
|
[bobOtkCurve25519 enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
|
||||||
|
bobOneTimeKey = obj;
|
||||||
|
}];
|
||||||
|
XCTAssert([bobOneTimeKey isKindOfClass:[NSString class]]);
|
||||||
|
|
||||||
|
OLMSession *aliceSession = [[OLMSession alloc] initOutboundSessionWithAccount:alice theirIdentityKey:bobIdKey theirOneTimeKey:bobOneTimeKey error:nil];
|
||||||
|
NSString *message = @"Hello I'm Alice!";
|
||||||
|
OLMMessage *aliceToBobMsg = [aliceSession encryptMessage:message error:nil];
|
||||||
|
|
||||||
|
OLMSession *bobSession = [[OLMSession alloc] initInboundSessionWithAccount:bob oneTimeKeyMessage:aliceToBobMsg.ciphertext error:nil];
|
||||||
|
NSString *plaintext = [bobSession decryptMessage:aliceToBobMsg error:nil];
|
||||||
|
XCTAssertEqualObjects(message, plaintext);
|
||||||
|
BOOL success = [bob removeOneTimeKeysForSession:bobSession];
|
||||||
|
XCTAssertTrue(success);
|
||||||
|
|
||||||
|
NSString *msg1 = @"Hello I'm Bob!";
|
||||||
|
NSString *msg2 = @"Isn't life grand?";
|
||||||
|
NSString *msg3 = @"Let's go to the opera.";
|
||||||
|
|
||||||
|
OLMMessage *eMsg1 = [bobSession encryptMessage:msg1 error:nil];
|
||||||
|
OLMMessage *eMsg2 = [bobSession encryptMessage:msg2 error:nil];
|
||||||
|
OLMMessage *eMsg3 = [bobSession encryptMessage:msg3 error:nil];
|
||||||
|
|
||||||
|
NSString *dMsg1 = [aliceSession decryptMessage:eMsg1 error:nil];
|
||||||
|
NSString *dMsg2 = [aliceSession decryptMessage:eMsg2 error:nil];
|
||||||
|
NSString *dMsg3 = [aliceSession decryptMessage:eMsg3 error:nil];
|
||||||
|
XCTAssertEqualObjects(msg1, dMsg1);
|
||||||
|
XCTAssertEqualObjects(msg2, dMsg2);
|
||||||
|
XCTAssertEqualObjects(msg3, dMsg3);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) testAccountSerialization {
|
||||||
|
OLMAccount *bob = [[OLMAccount alloc] initNewAccount];
|
||||||
|
[bob generateOneTimeKeys:5];
|
||||||
|
NSDictionary *bobIdKeys = bob.identityKeys;
|
||||||
|
NSDictionary *bobOneTimeKeys = bob.oneTimeKeys;
|
||||||
|
|
||||||
|
NSData *bobData = [NSKeyedArchiver archivedDataWithRootObject:bob];
|
||||||
|
|
||||||
|
OLMAccount *bob2 = [NSKeyedUnarchiver unarchiveObjectWithData:bobData];
|
||||||
|
NSDictionary *bobIdKeys2 = bob2.identityKeys;
|
||||||
|
NSDictionary *bobOneTimeKeys2 = bob2.oneTimeKeys;
|
||||||
|
|
||||||
|
XCTAssertEqualObjects(bobIdKeys, bobIdKeys2);
|
||||||
|
XCTAssertEqualObjects(bobOneTimeKeys, bobOneTimeKeys2);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) testSessionSerialization {
|
||||||
|
NSError *error;
|
||||||
|
|
||||||
|
OLMAccount *alice = [[OLMAccount alloc] initNewAccount];
|
||||||
|
OLMAccount *bob = [[OLMAccount alloc] initNewAccount];
|
||||||
|
[bob generateOneTimeKeys:1];
|
||||||
|
NSDictionary *bobIdKeys = bob.identityKeys;
|
||||||
|
NSString *bobIdKey = bobIdKeys[@"curve25519"];
|
||||||
|
NSDictionary *bobOneTimeKeys = bob.oneTimeKeys;
|
||||||
|
NSParameterAssert(bobIdKey != nil);
|
||||||
|
NSParameterAssert(bobOneTimeKeys != nil);
|
||||||
|
__block NSString *bobOneTimeKey = nil;
|
||||||
|
NSDictionary *bobOtkCurve25519 = bobOneTimeKeys[@"curve25519"];
|
||||||
|
[bobOtkCurve25519 enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
|
||||||
|
bobOneTimeKey = obj;
|
||||||
|
}];
|
||||||
|
XCTAssert([bobOneTimeKey isKindOfClass:[NSString class]]);
|
||||||
|
|
||||||
|
OLMSession *aliceSession = [[OLMSession alloc] initOutboundSessionWithAccount:alice theirIdentityKey:bobIdKey theirOneTimeKey:bobOneTimeKey error:nil];
|
||||||
|
NSString *message = @"Hello I'm Alice!";
|
||||||
|
OLMMessage *aliceToBobMsg = [aliceSession encryptMessage:message error:&error];
|
||||||
|
XCTAssertNil(error);
|
||||||
|
|
||||||
|
|
||||||
|
OLMSession *bobSession = [[OLMSession alloc] initInboundSessionWithAccount:bob oneTimeKeyMessage:aliceToBobMsg.ciphertext error:nil];
|
||||||
|
NSString *plaintext = [bobSession decryptMessage:aliceToBobMsg error:nil];
|
||||||
|
XCTAssertEqualObjects(message, plaintext);
|
||||||
|
BOOL success = [bob removeOneTimeKeysForSession:bobSession];
|
||||||
|
XCTAssertTrue(success);
|
||||||
|
|
||||||
|
NSString *msg1 = @"Hello I'm Bob!";
|
||||||
|
NSString *msg2 = @"Isn't life grand?";
|
||||||
|
NSString *msg3 = @"Let's go to the opera.";
|
||||||
|
|
||||||
|
OLMMessage *eMsg1 = [bobSession encryptMessage:msg1 error:nil];
|
||||||
|
OLMMessage *eMsg2 = [bobSession encryptMessage:msg2 error:nil];
|
||||||
|
OLMMessage *eMsg3 = [bobSession encryptMessage:msg3 error:nil];
|
||||||
|
|
||||||
|
NSData *aliceData = [NSKeyedArchiver archivedDataWithRootObject:aliceSession];
|
||||||
|
OLMSession *alice2 = [NSKeyedUnarchiver unarchiveObjectWithData:aliceData];
|
||||||
|
|
||||||
|
NSString *dMsg1 = [alice2 decryptMessage:eMsg1 error:nil];
|
||||||
|
NSString *dMsg2 = [alice2 decryptMessage:eMsg2 error:nil];
|
||||||
|
NSString *dMsg3 = [alice2 decryptMessage:eMsg3 error:nil];
|
||||||
|
XCTAssertEqualObjects(msg1, dMsg1);
|
||||||
|
XCTAssertEqualObjects(msg2, dMsg2);
|
||||||
|
XCTAssertEqualObjects(msg3, dMsg3);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testEd25519Signing {
|
||||||
|
|
||||||
|
OLMUtility *olmUtility = [[OLMUtility alloc] init];
|
||||||
|
OLMAccount *alice = [[OLMAccount alloc] initNewAccount];
|
||||||
|
|
||||||
|
NSDictionary *aJSON = @{
|
||||||
|
@"key1": @"value1",
|
||||||
|
@"key2": @"value2"
|
||||||
|
};
|
||||||
|
NSData *message = [NSKeyedArchiver archivedDataWithRootObject:aJSON];
|
||||||
|
NSString *signature = [alice signMessage:message];
|
||||||
|
|
||||||
|
|
||||||
|
NSString *aliceEd25519Key = alice.identityKeys[@"ed25519"];
|
||||||
|
|
||||||
|
NSError *error;
|
||||||
|
BOOL result = [olmUtility verifyEd25519Signature:signature key:aliceEd25519Key message:message error:&error];
|
||||||
|
XCTAssert(result);
|
||||||
|
XCTAssertNil(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
7
xcode/Podfile
Normal file
7
xcode/Podfile
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
target "OLMKit" do
|
||||||
|
pod 'OLMKit', :path => '../OLMKit.podspec'
|
||||||
|
end
|
||||||
|
|
||||||
|
target "OLMKitTests" do
|
||||||
|
pod 'OLMKit', :path => '../OLMKit.podspec'
|
||||||
|
end
|
20
xcode/Podfile.lock
Normal file
20
xcode/Podfile.lock
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
PODS:
|
||||||
|
- OLMKit (2.0.1):
|
||||||
|
- OLMKit/olmc (= 2.0.1)
|
||||||
|
- OLMKit/olmcpp (= 2.0.1)
|
||||||
|
- OLMKit/olmc (2.0.1)
|
||||||
|
- OLMKit/olmcpp (2.0.1)
|
||||||
|
|
||||||
|
DEPENDENCIES:
|
||||||
|
- OLMKit (from `../OLMKit.podspec`)
|
||||||
|
|
||||||
|
EXTERNAL SOURCES:
|
||||||
|
OLMKit:
|
||||||
|
:path: ../OLMKit.podspec
|
||||||
|
|
||||||
|
SPEC CHECKSUMS:
|
||||||
|
OLMKit: 12a35a69f92c7facdd50b559128d1b4a17857ba7
|
||||||
|
|
||||||
|
PODFILE CHECKSUM: 4e261dae61d833ec5585ced2473023b98909fd35
|
||||||
|
|
||||||
|
COCOAPODS: 1.1.1
|
26
xcode/README.rst
Normal file
26
xcode/README.rst
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
OLMKit
|
||||||
|
======
|
||||||
|
|
||||||
|
OLMKit exposes an Objective-C wrapper to libolm.
|
||||||
|
|
||||||
|
The original work by Chris Ballinger can be found at https://github.com/chrisballinger/OLMKit.
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
You can embed OLMKit to your application project with CocoaPods. The pod for
|
||||||
|
the latest OLMKit release is::
|
||||||
|
|
||||||
|
pod 'OLMKit'
|
||||||
|
|
||||||
|
Development
|
||||||
|
-----------
|
||||||
|
Run `pod install` and open `OLMKit.xcworkspace`.
|
||||||
|
|
||||||
|
The project contains only tests files. The libolm and the Objective-C wrapper source files are loaded via the OLMKit CocoaPods pod.
|
||||||
|
|
||||||
|
To add a new source file, add it to the file system and run `pod update` to make CocoaPods insert it into OLMKit.xcworkspace.
|
||||||
|
|
||||||
|
Release
|
||||||
|
-------
|
||||||
|
See ../README.rst for the release of the CocoaPod.
|
||||||
|
|
Loading…
Reference in a new issue