From 3148157ea4262082d957f45b36016c44f8e1415a Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Tue, 2 Apr 2019 23:39:05 -0400 Subject: [PATCH 1/6] add support for an incorrect KDF that snuck into Riot 1.0 --- include/olm/sas.h | 8 ++++++++ javascript/olm_sas.js | 16 ++++++++++++++++ src/sas.c | 23 +++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/include/olm/sas.h b/include/olm/sas.h index 46d4176..ec90ae7 100644 --- a/include/olm/sas.h +++ b/include/olm/sas.h @@ -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 diff --git a/javascript/olm_sas.js b/javascript/olm_sas.js index d5044ce..a2f82ee 100644 --- a/javascript/olm_sas.js +++ b/javascript/olm_sas.js @@ -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); +}); diff --git a/src/sas.c b/src/sas.c index c5be73f..b5a3131 100644 --- a/src/sas.c +++ b/src/sas.c @@ -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; +} From ad024b334751a905eb7e3dd33f83835ecdb84ae8 Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Thu, 4 Apr 2019 23:11:56 -0400 Subject: [PATCH 2/6] add missing OlmPkSigning class --- .../java/org/matrix/olm/OlmPkSigning.java | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 android/olm-sdk/src/main/java/org/matrix/olm/OlmPkSigning.java diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/OlmPkSigning.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmPkSigning.java new file mode 100644 index 0000000..89cb556 --- /dev/null +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmPkSigning.java @@ -0,0 +1,100 @@ +/* + * 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); +} From 0883a922ff39981e27cff7e677a6f79a5f324fab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Wed, 28 Nov 2018 14:54:08 +0100 Subject: [PATCH 3/6] python: Make the typing module a requirement only for old python versions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Typing is part of standard library from python 3.5 and from python 3.7 onwards trying to install it results in an error. This patch disables typing installation on python versions that are newer than 3.5. Signed-off-by: Damir Jelić --- python/setup.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index 4b0deb1..5742fd9 100644 --- a/python/setup.py +++ b/python/setup.py @@ -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 ) From f160d693b627a1159ed5837a4e9630100ab3f67e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Wed, 28 Nov 2018 14:54:09 +0100 Subject: [PATCH 4/6] python: Add PK bindings. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds bindings to the PK part of the Olm library contained in the pk.h header file. Encryption, decryption as well as pickling/unpickling of the decryption object is supported. Signed-off-by: Damir Jelić --- python/Makefile | 12 +- python/olm/__init__.py | 7 + python/olm/pk.py | 346 ++++++++++++++++++++++++++++++++++++++++ python/olm_build.py | 4 + python/tests/pk_test.py | 49 ++++++ 5 files changed, 415 insertions(+), 3 deletions(-) create mode 100644 python/olm/pk.py create mode 100644 python/tests/pk_test.py diff --git a/python/Makefile b/python/Makefile index 5da703a..546de13 100644 --- a/python/Makefile +++ b/python/Makefile @@ -1,15 +1,21 @@ 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 -olm-python2: 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 + +olm-python2: include/olm/olm.h include/olm/pk.h DEVELOP=$(DEVELOP) python2 setup.py build -olm-python3: include/olm/olm.h +olm-python3: include/olm/olm.h include/olm/pk.h DEVELOP=$(DEVELOP) python3 setup.py build install: install-python2 install-python3 diff --git a/python/olm/__init__.py b/python/olm/__init__.py index 015c4f8..7b7423b 100644 --- a/python/olm/__init__.py +++ b/python/olm/__init__.py @@ -36,3 +36,10 @@ from .group_session import ( OutboundGroupSession, OlmGroupSessionError ) +from .pk import ( + PkMessage, + PkEncryption, + PkDecryption, + PkEncryptionError, + PkDecryptionError +) diff --git a/python/olm/pk.py b/python/olm/pk.py new file mode 100644 index 0000000..b67d5a4 --- /dev/null +++ b/python/olm/pk.py @@ -0,0 +1,346 @@ +# -*- coding: utf-8 -*- +# libolm python bindings +# Copyright © 2018 Damir Jelić +# +# 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. +"""libolm PK module. + +This module contains bindings to the PK part of the Olm library. +It contains two classes PkDecryption and PkEncryption that are used to +establish an encrypted communication channel using public key encryption. + +Examples: + >>> decryption = PkDecryption() + >>> encryption = PkEncryption(decryption.public_key) + >>> plaintext = "It's a secret to everybody." + >>> message = encryption.encrypt(plaintext) + >>> decrypted_plaintext = decryption.decrypt(message) + +""" + +from builtins import super +from typing import AnyStr, Type +from future.utils import bytes_to_native_str + +from _libolm import ffi, lib # type: ignore +from ._finalize import track_for_finalization +from ._compat import URANDOM, to_bytearray + + +class PkEncryptionError(Exception): + """libolm Pk encryption exception.""" + + +class PkDecryptionError(Exception): + """libolm Pk decryption exception.""" + + +def _clear_pk_encryption(pk_struct): + lib.olm_clear_pk_encryption(pk_struct) + + +class PkMessage(object): + """A PK encrypted message.""" + + def __init__(self, ephemeral_key, mac, ciphertext): + # type: (str, str, str) -> None + """Create a new PK encrypted message. + + Args: + ephemeral_key(str): the public part of the ephemeral key + used (together with the recipient's key) to generate a symmetric + encryption key. + mac(str): Message Authentication Code of the encrypted message + ciphertext(str): The cipher text of the encrypted message + """ + self.ephemeral_key = ephemeral_key + self.mac = mac + self.ciphertext = ciphertext + + +class PkEncryption(object): + """PkEncryption class. + + Represents the decryption part of a PK encrypted channel. + """ + + def __init__(self, recipient_key): + # type: (AnyStr) -> None + """Create a new PK encryption object. + + Args: + recipient_key(str): a public key that will be used for encryption + """ + if not recipient_key: + raise ValueError("Recipient key can't be empty") + + self._buf = ffi.new("char[]", lib.olm_pk_encryption_size()) + self._pk_encryption = lib.olm_pk_encryption(self._buf) + track_for_finalization(self, self._pk_encryption, _clear_pk_encryption) + + byte_key = to_bytearray(recipient_key) + lib.olm_pk_encryption_set_recipient_key( + self._pk_encryption, + ffi.from_buffer(byte_key), + len(byte_key) + ) + + # clear out copies of the key + if byte_key is not recipient_key: # pragma: no cover + for i in range(0, len(byte_key)): + byte_key[i] = 0 + + def _check_error(self, ret): # pragma: no cover + # type: (int) -> None + if ret != lib.olm_error(): + return + + last_error = bytes_to_native_str( + ffi.string(lib.olm_pk_encryption_last_error(self._pk_encryption))) + + raise PkEncryptionError(last_error) + + def encrypt(self, plaintext): + # type: (AnyStr) -> PkMessage + """Encrypt a message. + + Returns the encrypted PkMessage. + + Args: + plaintext(str): A string that will be encrypted using the + PkEncryption object. + """ + byte_plaintext = to_bytearray(plaintext) + + r_length = lib.olm_pk_encrypt_random_length(self._pk_encryption) + random = URANDOM(r_length) + random_buffer = ffi.new("char[]", random) + + ciphertext_length = lib.olm_pk_ciphertext_length( + self._pk_encryption, len(byte_plaintext) + ) + ciphertext = ffi.new("char[]", ciphertext_length) + + mac_length = lib.olm_pk_mac_length(self._pk_encryption) + mac = ffi.new("char[]", mac_length) + + ephemeral_key_size = lib.olm_pk_key_length() + ephemeral_key = ffi.new("char[]", ephemeral_key_size) + + ret = lib.olm_pk_encrypt( + self._pk_encryption, + ffi.from_buffer(byte_plaintext), len(byte_plaintext), + ciphertext, ciphertext_length, + mac, mac_length, + ephemeral_key, ephemeral_key_size, + random_buffer, r_length + ) + + try: + self._check_error(ret) + finally: # pragma: no cover + # clear out copies of plaintext + if byte_plaintext is not plaintext: + for i in range(0, len(byte_plaintext)): + byte_plaintext[i] = 0 + + message = PkMessage( + bytes_to_native_str( + ffi.unpack(ephemeral_key, ephemeral_key_size)), + bytes_to_native_str( + ffi.unpack(mac, mac_length)), + bytes_to_native_str( + ffi.unpack(ciphertext, ciphertext_length)) + ) + return message + + +def _clear_pk_decryption(pk_struct): + lib.olm_clear_pk_decryption(pk_struct) + + +class PkDecryption(object): + """PkDecryption class. + + Represents the decryption part of a PK encrypted channel. + + Attributes: + public_key (str): The public key of the PkDecryption object, can be + shared and used to create a PkEncryption object. + + """ + + def __new__(cls): + # type: (Type[PkDecryption]) -> PkDecryption + obj = super().__new__(cls) + obj._buf = ffi.new("char[]", lib.olm_pk_decryption_size()) + obj._pk_decryption = lib.olm_pk_decryption(obj._buf) + obj.public_key = None + track_for_finalization(obj, obj._pk_decryption, _clear_pk_decryption) + return obj + + def __init__(self): + if False: # pragma: no cover + self._pk_decryption = self._pk_decryption # type: ffi.cdata + + random_length = lib.olm_pk_private_key_length() + random = URANDOM(random_length) + random_buffer = ffi.new("char[]", random) + + key_length = lib.olm_pk_key_length() + key_buffer = ffi.new("char[]", key_length) + + ret = lib.olm_pk_key_from_private( + self._pk_decryption, + key_buffer, key_length, + random_buffer, random_length + ) + self._check_error(ret) + self.public_key = bytes_to_native_str(ffi.unpack( + key_buffer, + key_length + )) + + def _check_error(self, ret): + # type: (int) -> None + if ret != lib.olm_error(): + return + + last_error = bytes_to_native_str( + ffi.string(lib.olm_pk_decryption_last_error(self._pk_decryption))) + + raise PkDecryptionError(last_error) + + def pickle(self, passphrase=""): + # type: (str) -> bytes + """Store a PkDecryption object. + + Stores a PkDecryption object as a base64 string. Encrypts the object + using the supplied passphrase. Returns a byte object containing the + base64 encoded string of the pickled session. + + Args: + passphrase(str, optional): The passphrase to be used to encrypt + the object. + """ + byte_key = to_bytearray(passphrase) + + pickle_length = lib.olm_pickle_pk_decryption_length( + self._pk_decryption + ) + pickle_buffer = ffi.new("char[]", pickle_length) + + ret = lib.olm_pickle_pk_decryption( + self._pk_decryption, + ffi.from_buffer(byte_key), len(byte_key), + pickle_buffer, pickle_length + ) + try: + self._check_error(ret) + finally: + # zero out copies of the passphrase + for i in range(0, len(byte_key)): + byte_key[i] = 0 + + return ffi.unpack(pickle_buffer, pickle_length) + + @classmethod + def from_pickle(cls, pickle, passphrase=""): + # types: (bytes, str) -> PkDecryption + """Restore a previously stored PkDecryption object. + + Creates a PkDecryption object from a pickled base64 string. Decrypts + the pickled object using the supplied passphrase. + Raises PkDecryptionError on failure. If the passphrase + doesn't match the one used to encrypt the session then the error + message for the exception will be "BAD_ACCOUNT_KEY". If the base64 + couldn't be decoded then the error message will be "INVALID_BASE64". + + Args: + pickle(bytes): Base64 encoded byte string containing the pickled + PkDecryption object + passphrase(str, optional): The passphrase used to encrypt the + object + """ + if not pickle: + raise ValueError("Pickle can't be empty") + + byte_key = to_bytearray(passphrase) + pickle_buffer = ffi.new("char[]", pickle) + + pubkey_length = lib.olm_pk_key_length() + pubkey_buffer = ffi.new("char[]", pubkey_length) + + obj = cls.__new__(cls) + + ret = lib.olm_unpickle_pk_decryption( + obj._pk_decryption, + ffi.from_buffer(byte_key), len(byte_key), + pickle_buffer, len(pickle), + pubkey_buffer, pubkey_length) + + try: + obj._check_error(ret) + finally: + for i in range(0, len(byte_key)): + byte_key[i] = 0 + + obj.public_key = bytes_to_native_str(ffi.unpack( + pubkey_buffer, + pubkey_length + )) + + return obj + + def decrypt(self, message): + # type (PkMessage) -> str + """Decrypt a previously encrypted Pk message. + + Returns the decrypted plaintext. + Raises PkDecryptionError on failure. + + Args: + message(PkMessage): the pk message to decrypt. + """ + ephemeral_key = to_bytearray(message.ephemeral_key) + ephemeral_key_size = len(ephemeral_key) + + mac = to_bytearray(message.mac) + mac_length = len(mac) + + ciphertext = to_bytearray(message.ciphertext) + ciphertext_length = len(ciphertext) + + max_plaintext_length = lib.olm_pk_max_plaintext_length( + self._pk_decryption, + ciphertext_length + ) + plaintext_buffer = ffi.new("char[]", max_plaintext_length) + + ret = lib.olm_pk_decrypt( + self._pk_decryption, + ffi.from_buffer(ephemeral_key), ephemeral_key_size, + ffi.from_buffer(mac), mac_length, + ffi.from_buffer(ciphertext), ciphertext_length, + plaintext_buffer, max_plaintext_length) + self._check_error(ret) + + plaintext = (ffi.unpack( + plaintext_buffer, + ret + )) + + # clear out copies of the plaintext + lib.memset(plaintext_buffer, 0, max_plaintext_length) + + return bytes_to_native_str(plaintext) diff --git a/python/olm_build.py b/python/olm_build.py index ee836d8..d3eda79 100644 --- a/python/olm_build.py +++ b/python/olm_build.py @@ -39,6 +39,7 @@ ffibuilder.set_source( #include #include #include + #include """, libraries=["olm"], extra_compile_args=compile_args, @@ -47,5 +48,8 @@ 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) + if __name__ == "__main__": ffibuilder.compile(verbose=True) diff --git a/python/tests/pk_test.py b/python/tests/pk_test.py new file mode 100644 index 0000000..f2aa147 --- /dev/null +++ b/python/tests/pk_test.py @@ -0,0 +1,49 @@ +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") From f1d45c2cd330f239e41b50d6be14df7795a57c9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Wed, 28 Nov 2018 14:54:10 +0100 Subject: [PATCH 5/6] python: Fix the MANIFEST file. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds the Olm header files to the manifest, this results in the header files being added to source distributions of the python-olm module. The headers are required to build the module. Including them in the source distribution is the easiest way to make sure that builds from the source distribution will succeed provided that the Olm C library is already installed. Signed-off-by: Damir Jelić --- python/MANIFEST.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/MANIFEST.in b/python/MANIFEST.in index bfddd4f..db6309d 100644 --- a/python/MANIFEST.in +++ b/python/MANIFEST.in @@ -1,3 +1,4 @@ -include olm.h +include include/olm/olm.h +include include/olm/pk.h include Makefile include olm_build.py From 709687a7b56d6768831766459940b6f0bb078d85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Wed, 28 Nov 2018 14:54:11 +0100 Subject: [PATCH 6/6] python: Build the build headers with setup.py. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows downstream users to install this python module with pip as well as allowing people to declare it as a dependency in their setup.py. Signed-off-by: Damir Jelić --- python/Makefile | 6 ++++-- python/olm_build.py | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/python/Makefile b/python/Makefile index 546de13..7f0121d 100644 --- a/python/Makefile +++ b/python/Makefile @@ -12,10 +12,12 @@ include/olm/olm.h: $(OLM_HEADERS) 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 -olm-python2: include/olm/olm.h include/olm/pk.h +headers: include/olm/olm.h include/olm/pk.h + +olm-python2: headers DEVELOP=$(DEVELOP) python2 setup.py build -olm-python3: include/olm/olm.h include/olm/pk.h +olm-python3: headers DEVELOP=$(DEVELOP) python3 setup.py build install: install-python2 install-python3 diff --git a/python/olm_build.py b/python/olm_build.py index d3eda79..97ab3b2 100644 --- a/python/olm_build.py +++ b/python/olm_build.py @@ -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",