Unverified Commit 2a640071 authored by Hubert Chathi's avatar Hubert Chathi Committed by GitHub

Merge branch 'master' into poljar/python-sas

parents fcfa5f12 709687a7
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.olm;
import android.util.Log;
import java.util.Arrays;
public class OlmPkSigning {
private static final String LOG_TAG = "OlmPkSigning";
/** PK Signing Id returned by JNI.
* This value uniquely identifies the native PK signing instance.
**/
private transient long mNativeId;
public OlmPkSigning() throws OlmException {
try {
mNativeId = createNewPkSigningJni();
} catch (Exception e) {
throw new OlmException(OlmException.EXCEPTION_CODE_PK_SIGNING_CREATION, e.getMessage());
}
}
private native long createNewPkSigningJni();
private native void releasePkSigningJni();
public void releaseSigning() {
if (0 != mNativeId) {
releasePkSigningJni();
}
mNativeId = 0;
}
public boolean isReleased() {
return (0 == mNativeId);
}
public static native int seedLength();
public static byte[] generateSeed() throws OlmException {
try {
return generateSeedJni();
} catch (Exception e) {
Log.e(LOG_TAG, "## generateSeed(): failed " + e.getMessage());
throw new OlmException(OlmException.EXCEPTION_CODE_PK_SIGNING_GENERATE_SEED, e.getMessage());
}
}
public static native byte[] generateSeedJni();
public String initWithSeed(byte[] seed) throws OlmException {
try {
byte[] pubKey = setKeyFromSeedJni(seed);
return new String(pubKey, "UTF-8");
} catch (Exception e) {
Log.e(LOG_TAG, "## initWithSeed(): failed " + e.getMessage());
throw new OlmException(OlmException.EXCEPTION_CODE_PK_SIGNING_INIT_WITH_SEED, e.getMessage());
}
}
public native byte[] setKeyFromSeedJni(byte[] seed);
public String sign(String aMessage) throws OlmException {
if (null == aMessage) {
return null;
}
byte[] messageBuffer = null;
try {
messageBuffer = aMessage.getBytes("UTF-8");
byte[] signature = pkSignJni(messageBuffer);
return new String(signature, "UTF-8");
} catch (Exception e) {
Log.e(LOG_TAG, "## pkSign(): failed " + e.getMessage());
throw new OlmException(OlmException.EXCEPTION_CODE_PK_SIGNING_SIGN, e.getMessage());
} finally {
if (null != messageBuffer) {
Arrays.fill(messageBuffer, (byte) 0);
}
}
}
private native byte[] pkSignJni(byte[] message);
}
......@@ -147,6 +147,14 @@ size_t olm_sas_calculate_mac(
void * mac, size_t mac_length
);
// for compatibility with an old version of Riot
size_t olm_sas_calculate_mac_long_kdf(
OlmSAS * sas,
void * input, size_t input_length,
const void * info, size_t info_length,
void * mac, size_t mac_length
);
/** @} */ // end of SAS group
#ifdef __cplusplus
......
......@@ -75,3 +75,19 @@ SAS.prototype['calculate_mac'] = restore_stack(function(input, info) {
);
return Pointer_stringify(mac_buffer);
});
SAS.prototype['calculate_mac_long_kdf'] = restore_stack(function(input, info) {
var input_array = array_from_string(input);
var input_buffer = stack(input_array);
var info_array = array_from_string(info);
var info_buffer = stack(info_array);
var mac_length = sas_method(Module['_olm_sas_mac_length'])(this.ptr);
var mac_buffer = stack(mac_length + NULL_BYTE_PADDING_LENGTH);
sas_method(Module['_olm_sas_calculate_mac_long_kdf'])(
this.ptr,
input_buffer, input_array.length,
info_buffer, info_array.length,
mac_buffer, mac_length
);
return Pointer_stringify(mac_buffer);
});
include olm.h
include include/olm/olm.h
include include/olm/pk.h
include Makefile
include olm_build.py
all: olm-python2 olm-python3
include/olm/olm.h: ../include/olm/olm.h ../include/olm/inbound_group_session.h ../include/olm/outbound_group_session.h
OLM_HEADERS = ../include/olm/olm.h ../include/olm/inbound_group_session.h \
../include/olm/outbound_group_session.h \
include/olm/olm.h: $(OLM_HEADERS)
mkdir -p include/olm
$(CPP) -I dummy -I ../include ../include/olm/olm.h -o include/olm/olm.h
# add memset to the header so that we can use it to clear buffers
echo 'void *memset(void *s, int c, size_t n);' >> include/olm/olm.h
include/olm/pk.h: include/olm/olm.h ../include/olm/pk.h
$(CPP) -I dummy -I ../include ../include/olm/pk.h -o include/olm/pk.h
include/olm/sas.h: include/olm/olm.h ../include/olm/sas.h
$(CPP) -I dummy -I ../include ../include/olm/sas.h -o include/olm/sas.h
olm-python2: include/olm/olm.h include/olm/sas.h
headers: include/olm/olm.h include/olm/pk.h include/olm/sas.h
olm-python2: headers
DEVELOP=$(DEVELOP) python2 setup.py build
olm-python3: include/olm/olm.h include/olm/sas.h
olm-python3: headers
DEVELOP=$(DEVELOP) python3 setup.py build
install: install-python2 install-python3
......
......@@ -36,4 +36,11 @@ from .group_session import (
OutboundGroupSession,
OlmGroupSessionError
)
from .pk import (
PkMessage,
PkEncryption,
PkDecryption,
PkEncryptionError,
PkDecryptionError
)
from .sas import Sas, OlmSasError
This diff is collapsed.
......@@ -18,6 +18,7 @@
from __future__ import unicode_literals
import os
import subprocess
from cffi import FFI
......@@ -32,6 +33,8 @@ link_args = ["-L../build"]
if DEVELOP and DEVELOP.lower() in ["yes", "true", "1"]:
link_args.append('-Wl,-rpath=../build')
headers_build = subprocess.Popen("make headers", shell=True)
headers_build.wait()
ffibuilder.set_source(
"_libolm",
......@@ -39,6 +42,7 @@ ffibuilder.set_source(
#include <olm/olm.h>
#include <olm/inbound_group_session.h>
#include <olm/outbound_group_session.h>
#include <olm/pk.h>
#include <olm/sas.h>
""",
libraries=["olm"],
......@@ -48,6 +52,9 @@ ffibuilder.set_source(
with open(os.path.join(PATH, "include/olm/olm.h")) as f:
ffibuilder.cdef(f.read(), override=True)
with open(os.path.join(PATH, "include/olm/pk.h")) as f:
ffibuilder.cdef(f.read(), override=True)
with open(os.path.join(PATH, "include/olm/sas.h")) as f:
ffibuilder.cdef(f.read(), override=True)
......
......@@ -22,6 +22,10 @@ setup(
packages=["olm"],
setup_requires=["cffi>=1.0.0"],
cffi_modules=["olm_build.py:ffibuilder"],
install_requires=["cffi>=1.0.0", "future", "typing"],
install_requires=[
"cffi>=1.0.0",
"future",
"typing;python_version<'3.5'"
],
zip_safe=False
)
import pytest
from olm import PkDecryption, PkDecryptionError, PkEncryption
class TestClass(object):
def test_invalid_encryption(self):
with pytest.raises(ValueError):
PkEncryption("")
def test_decrytion(self):
decryption = PkDecryption()
encryption = PkEncryption(decryption.public_key)
plaintext = "It's a secret to everybody."
message = encryption.encrypt(plaintext)
decrypted_plaintext = decryption.decrypt(message)
isinstance(decrypted_plaintext, str)
assert plaintext == decrypted_plaintext
def test_invalid_decrytion(self):
decryption = PkDecryption()
encryption = PkEncryption(decryption.public_key)
plaintext = "It's a secret to everybody."
message = encryption.encrypt(plaintext)
message.ephemeral_key = "?"
with pytest.raises(PkDecryptionError):
decryption.decrypt(message)
def test_pickling(self):
decryption = PkDecryption()
encryption = PkEncryption(decryption.public_key)
plaintext = "It's a secret to everybody."
message = encryption.encrypt(plaintext)
pickle = decryption.pickle()
unpickled = PkDecryption.from_pickle(pickle)
decrypted_plaintext = unpickled.decrypt(message)
assert plaintext == decrypted_plaintext
def test_invalid_unpickling(self):
with pytest.raises(ValueError):
PkDecryption.from_pickle("")
def test_invalid_pass_pickling(self):
decryption = PkDecryption()
pickle = decryption.pickle("Secret")
with pytest.raises(PkDecryptionError):
PkDecryption.from_pickle(pickle, "Not secret")
......@@ -139,3 +139,26 @@ size_t olm_sas_calculate_mac(
_olm_encode_base64((const uint8_t *)mac, SHA256_OUTPUT_LENGTH, (uint8_t *)mac);
return 0;
}
// for compatibility with an old version of Riot
size_t olm_sas_calculate_mac_long_kdf(
OlmSAS * sas,
void * input, size_t input_length,
const void * info, size_t info_length,
void * mac, size_t mac_length
) {
if (mac_length < olm_sas_mac_length(sas)) {
sas->last_error = OLM_OUTPUT_BUFFER_TOO_SMALL;
return (size_t)-1;
}
uint8_t key[256];
_olm_crypto_hkdf_sha256(
sas->secret, sizeof(sas->secret),
NULL, 0,
(const uint8_t *) info, info_length,
key, 256
);
_olm_crypto_hmac_sha256(key, 256, input, input_length, mac);
_olm_encode_base64((const uint8_t *)mac, SHA256_OUTPUT_LENGTH, (uint8_t *)mac);
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment