summaryrefslogtreecommitdiff
path: root/opt/profanity
diff options
context:
space:
mode:
Diffstat (limited to 'opt/profanity')
-rw-r--r--opt/profanity/.footprint150
-rw-r--r--opt/profanity/.signature13
-rw-r--r--opt/profanity/MAKEPKG71
-rw-r--r--opt/profanity/crypto.c494
-rw-r--r--opt/profanity/crypto.h193
-rw-r--r--opt/profanity/omemo-publish-options.patch55
-rw-r--r--opt/profanity/openssl-aesgcm-download.patch24
-rw-r--r--opt/profanity/openssl-crypto.patch12
-rw-r--r--opt/profanity/openssl-omemo-c.patch136
-rw-r--r--opt/profanity/openssl-omemo-h.patch19
10 files changed, 1167 insertions, 0 deletions
diff --git a/opt/profanity/.footprint b/opt/profanity/.footprint
new file mode 100644
index 0000000..76da9db
--- /dev/null
+++ b/opt/profanity/.footprint
@@ -0,0 +1,150 @@
+drwxr-xr-x root/root usr/
+drwxr-xr-x root/root usr/bin/
+-rwxr-xr-x root/root usr/bin/profanity
+drwxr-xr-x root/root usr/share/
+drwxr-xr-x root/root usr/share/doc/
+drwxr-xr-x root/root usr/share/doc/profanity/
+-rw-r--r-- root/root usr/share/doc/profanity/profrc.example
+-rw-r--r-- root/root usr/share/doc/profanity/theme_template
+drwxr-xr-x root/root usr/share/man/
+drwxr-xr-x root/root usr/share/man/man1/
+-rw-r--r-- root/root usr/share/man/man1/profanity-about.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-account.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-affiliation.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-alias.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-autoaway.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-autoconnect.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-autoping.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-avatar.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-ban.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-beep.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-blocked.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-bookmark.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-caps.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-carbons.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-changepassword.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-changes.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-charset.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-clear.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-close.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-cmd.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-color.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-connect.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-console.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-correct-editor.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-correct.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-correction.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-disco.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-disconnect.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-editor.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-executable.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-export.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-flash.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-form.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-gone.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-help.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-history.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-info.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-inpblock.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-inputwin.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-intype.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-invite.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-join.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-kick.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-lastactivity.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-log.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-logging.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-mainwin.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-mam.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-mood.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-msg.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-nick.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-notify.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-occupants.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-omemo.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-otr.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-outtype.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-ox-setup.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-ox.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-paste.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-pgp.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-ping.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-plugins.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-prefs.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-presence.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-priority.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-privacy.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-privileges.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-quit.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-receipts.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-reconnect.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-redraw.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-register.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-reload.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-resource.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-role.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-room.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-rooms.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-roster.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-save.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-script.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-sendfile.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-serversoftware.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-silence.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-slashguard.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-software.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-spellcheck.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-splash.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-stamp.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-states.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-status.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-statusbar.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-strophe.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-sub.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-subject.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-theme.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-time.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-titlebar.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-tls.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-tray.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-url.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-vcard.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-vercheck.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-who.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-win.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-wins.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-wintitle.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-wrap.1.gz
+-rw-r--r-- root/root usr/share/man/man1/profanity-xmlconsole.1.gz
+-rwxr-xr-x root/root usr/share/man/man1/profanity.1.gz
+drwxr-xr-x root/root usr/share/profanity/
+drwxr-xr-x root/root usr/share/profanity/icons/
+-rw-r--r-- root/root usr/share/profanity/icons/proIcon.png
+-rw-r--r-- root/root usr/share/profanity/icons/proIconMsg.png
+drwxr-xr-x root/root usr/share/profanity/themes/
+-rw-r--r-- root/root usr/share/profanity/themes/aqua
+-rw-r--r-- root/root usr/share/profanity/themes/batman
+-rw-r--r-- root/root usr/share/profanity/themes/bios
+-rw-r--r-- root/root usr/share/profanity/themes/boothj5
+-rw-r--r-- root/root usr/share/profanity/themes/boothj5_laptop
+-rw-r--r-- root/root usr/share/profanity/themes/boothj5_slack
+-rw-r--r-- root/root usr/share/profanity/themes/complex
+-rw-r--r-- root/root usr/share/profanity/themes/forest
+-rw-r--r-- root/root usr/share/profanity/themes/gruvbox
+-rw-r--r-- root/root usr/share/profanity/themes/gruvbox_transparent
+-rw-r--r-- root/root usr/share/profanity/themes/hacker
+-rw-r--r-- root/root usr/share/profanity/themes/headache
+-rw-r--r-- root/root usr/share/profanity/themes/irssi
+-rw-r--r-- root/root usr/share/profanity/themes/joker
+-rw-r--r-- root/root usr/share/profanity/themes/jubalian
+-rw-r--r-- root/root usr/share/profanity/themes/mono
+-rw-r--r-- root/root usr/share/profanity/themes/orange
+-rw-r--r-- root/root usr/share/profanity/themes/original
+-rw-r--r-- root/root usr/share/profanity/themes/original_bright
+-rw-r--r-- root/root usr/share/profanity/themes/shade
+-rw-r--r-- root/root usr/share/profanity/themes/simple
+-rw-r--r-- root/root usr/share/profanity/themes/snikket
+-rw-r--r-- root/root usr/share/profanity/themes/solarized-dark
+-rw-r--r-- root/root usr/share/profanity/themes/solarized-light
+-rw-r--r-- root/root usr/share/profanity/themes/spawn
+-rw-r--r-- root/root usr/share/profanity/themes/whiteness
diff --git a/opt/profanity/.signature b/opt/profanity/.signature
new file mode 100644
index 0000000..920437d
--- /dev/null
+++ b/opt/profanity/.signature
@@ -0,0 +1,13 @@
+RWTZ9IduCSQ/mEzV49oHAPzWE0jQ9CAuryOIaLrdaapv+Y9RxWs/EMgdC2ogBxTWx16tPXNeLbaua04Lah0t+DoO4okloNaz4g4=
+
+SHA256 (MAKEPKG) = 166071cf708978845b98ab513e0189d726d613b3fc4d5af15a5c803272a82a94
+SHA256 (.footprint) = dffc5317c7c371fa871fef049db0ba6ade06d29b4dc2e6882b313c370557fa39
+SHA256 (profanity-0.18.2.tar.xz) = 46964928742733fffcf8ca65d37ac0874c8ccd6270cbc065cb1013cee94e9e3b
+SHA256 (crypto.c) = 98d10f3d50e89d1f564a68ff38b02080449aa3bcb4d2bc83db0f2dae75eef007
+SHA256 (crypto.h) = 16f9e7ef3eeae11917e87eddad7705b296bad4cef0b30858d1a4f1e98463b71b
+SHA256 (openssl-crypto.patch) = 626783ffe584a69a05341884f30dd3032348b65a164a3769d2d953c4f51a2efe
+SHA256 (openssl-omemo-h.patch) = 3d38b7a7c720ab90e9eef6da343deab85dabc931fbf0216513b95bd91c20bc7d
+SHA256 (openssl-omemo-c.patch) = 4d25a38d95b537b3d037f8f523a8d8fc2970b31691b91716e0b1385f5a9bf4a7
+SHA256 (openssl-aesgcm-download.patch) = 7acb0733d32ad10e6cb2aff0d9ea22109f601ad0031ea36a9ed38a43f7bc50a2
+SHA256 (omemo-publish-options.patch) = 94c46b027928bc88c76ec3249f246e9e45760f518c39d1dae3d8ff4de0fd66b0
+SHA256 (profanity#0.18.2-3.pkg.tar.gz) = d54bb38e2f58903d3ed0f787c4fc7cd2451c824ed334491a8f80d4f9a69e9482
diff --git a/opt/profanity/MAKEPKG b/opt/profanity/MAKEPKG
new file mode 100644
index 0000000..7148ad1
--- /dev/null
+++ b/opt/profanity/MAKEPKG
@@ -0,0 +1,71 @@
+#!/bin/mkpkg
+# description: Ncurses XMPP client with OMEMO support
+# url: https://profanity-im.github.io/
+
+name=profanity
+version=0.18.2
+release=3
+depends=(libstrophe ncurses glib curl readline sqlite libsignal-protocol-c libressl)
+makedeps=(meson)
+source=(https://github.com/profanity-im/profanity/releases/download/$version/$name-$version.tar.xz
+ crypto.c
+ crypto.h
+ openssl-crypto.patch
+ openssl-omemo-h.patch
+ openssl-omemo-c.patch
+ openssl-aesgcm-download.patch
+ omemo-publish-options.patch)
+
+sha256sums=(
+ "46964928742733fffcf8ca65d37ac0874c8ccd6270cbc065cb1013cee94e9e3b"
+ "98d10f3d50e89d1f564a68ff38b02080449aa3bcb4d2bc83db0f2dae75eef007"
+ "16f9e7ef3eeae11917e87eddad7705b296bad4cef0b30858d1a4f1e98463b71b"
+ "626783ffe584a69a05341884f30dd3032348b65a164a3769d2d953c4f51a2efe"
+ "3d38b7a7c720ab90e9eef6da343deab85dabc931fbf0216513b95bd91c20bc7d"
+ "4d25a38d95b537b3d037f8f523a8d8fc2970b31691b91716e0b1385f5a9bf4a7"
+ "7acb0733d32ad10e6cb2aff0d9ea22109f601ad0031ea36a9ed38a43f7bc50a2"
+ "94c46b027928bc88c76ec3249f246e9e45760f518c39d1dae3d8ff4de0fd66b0"
+)
+
+patch() {
+ cd $name-$version
+
+ # Replace gcrypt with openssl in meson build
+ patch -p1 < $SRC/openssl-crypto.patch
+
+ # Replace omemo crypto backend with OpenSSL implementation
+ cp $SRC/crypto.c src/omemo/crypto.c
+ cp $SRC/crypto.h src/omemo/crypto.h
+
+ # Patch remaining gcrypt references
+ patch -p1 < $SRC/openssl-omemo-h.patch
+ patch -p1 < $SRC/openssl-omemo-c.patch
+ patch -p1 < $SRC/openssl-aesgcm-download.patch
+
+ # Publish OMEMO bundle and devicelist with publish-options even when the
+ # server domain does not advertise them (the account's own PEP does)
+ patch -p1 < $SRC/omemo-publish-options.patch
+}
+
+build() {
+ cd $name-$version
+
+ CC=clang CXX=clang++ meson setup build \
+ --prefix=/usr \
+ --mandir=/usr/share/man \
+ --buildtype=release \
+ -D omemo=enabled \
+ -D omemo-backend=libsignal
+
+ meson compile -C build
+ DESTDIR=$PKG meson install -C build
+
+}
+
+signify() {
+ untrusted comment: public key
+ RWTZ9IduCSQ/mL8337TEUinPwT92xFEUpD92hkS7IxcOnzTt9QdpohT3
+}
+
+# vim: filetype=sh
+
diff --git a/opt/profanity/crypto.c b/opt/profanity/crypto.c
new file mode 100644
index 0000000..c2b1068
--- /dev/null
+++ b/opt/profanity/crypto.c
@@ -0,0 +1,494 @@
+/*
+ * crypto.c
+ * vim: expandtab:ts=4:sts=4:sw=4
+ *
+ * Copyright (C) 2019 Paul Fariello <paul@fariello.eu>
+ *
+ * This file is part of Profanity.
+ *
+ * Profanity is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Profanity is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Profanity. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * In addition, as a special exception, the copyright holders give permission to
+ * link the code of portions of this program with the OpenSSL library under
+ * certain conditions as described in each individual source file, and
+ * distribute linked combinations including the two.
+ *
+ * You must obey the GNU General Public License in all respects for all of the
+ * code used other than OpenSSL. If you modify file(s) with this exception, you
+ * may extend this exception to your version of the file(s), but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version. If you delete this exception statement from all
+ * source files in the program, then also delete it here.
+ *
+ * krypt.sh: libgcrypt replaced with OpenSSL/LibreSSL backend.
+ */
+#include "config.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/rand.h>
+
+#include <signal/signal_protocol.h>
+#include <signal/signal_protocol_types.h>
+
+#include "log.h"
+#include "omemo/omemo.h"
+#include "omemo/crypto.h"
+
+#define AES256_GCM_TAG_LENGTH 16
+#define AES256_GCM_BUFFER_SIZE 1024
+
+int
+omemo_crypto_init(void)
+{
+ /* OpenSSL/LibreSSL self-initializes. Verify RAND is seeded. */
+ unsigned char test[1];
+ if (RAND_bytes(test, 1) != 1)
+ return -1;
+ return 0;
+}
+
+int
+omemo_random_func(uint8_t* data, size_t len, void* user_data)
+{
+ return RAND_bytes(data, (int)len) == 1 ? 0 : -1;
+}
+
+/*
+ * HMAC-SHA256
+ */
+
+int
+omemo_hmac_sha256_init_func(void** hmac_context, const uint8_t* key, size_t key_len, void* user_data)
+{
+ HMAC_CTX* ctx = HMAC_CTX_new();
+ if (!ctx)
+ return -1;
+
+ if (HMAC_Init_ex(ctx, key, (int)key_len, EVP_sha256(), NULL) != 1) {
+ HMAC_CTX_free(ctx);
+ return -1;
+ }
+
+ *hmac_context = ctx;
+ return 0;
+}
+
+int
+omemo_hmac_sha256_update_func(void* hmac_context, const uint8_t* data, size_t data_len, void* user_data)
+{
+ return HMAC_Update((HMAC_CTX*)hmac_context, data, data_len) == 1 ? 0 : -1;
+}
+
+int
+omemo_hmac_sha256_final_func(void* hmac_context, signal_buffer** output, void* user_data)
+{
+ unsigned char md[32];
+ unsigned int len = sizeof(md);
+
+ if (HMAC_Final((HMAC_CTX*)hmac_context, md, &len) != 1)
+ return -1;
+
+ *output = signal_buffer_create(md, len);
+ return *output ? 0 : -1;
+}
+
+void
+omemo_hmac_sha256_cleanup_func(void* hmac_context, void* user_data)
+{
+ HMAC_CTX_free((HMAC_CTX*)hmac_context);
+}
+
+/*
+ * SHA-512 digest
+ */
+
+int
+omemo_sha512_digest_init_func(void** digest_context, void* user_data)
+{
+ EVP_MD_CTX* ctx = EVP_MD_CTX_new();
+ if (!ctx)
+ return -1;
+
+ if (EVP_DigestInit_ex(ctx, EVP_sha512(), NULL) != 1) {
+ EVP_MD_CTX_free(ctx);
+ return -1;
+ }
+
+ *digest_context = ctx;
+ return 0;
+}
+
+int
+omemo_sha512_digest_update_func(void* digest_context, const uint8_t* data, size_t data_len, void* user_data)
+{
+ return EVP_DigestUpdate((EVP_MD_CTX*)digest_context, data, data_len) == 1 ? 0 : -1;
+}
+
+int
+omemo_sha512_digest_final_func(void* digest_context, signal_buffer** output, void* user_data)
+{
+ unsigned char md[64];
+ unsigned int len = sizeof(md);
+
+ if (EVP_DigestFinal_ex((EVP_MD_CTX*)digest_context, md, &len) != 1)
+ return -1;
+
+ *output = signal_buffer_create(md, len);
+ return *output ? 0 : -1;
+}
+
+void
+omemo_sha512_digest_cleanup_func(void* digest_context, void* user_data)
+{
+ EVP_MD_CTX_free((EVP_MD_CTX*)digest_context);
+}
+
+/*
+ * AES-256-CBC-PKCS5 encrypt/decrypt
+ * Used by libsignal-protocol-c for session key material.
+ */
+
+int
+omemo_encrypt_func(signal_buffer** output, int cipher,
+ const uint8_t* key, size_t key_len,
+ const uint8_t* iv, size_t iv_len,
+ const uint8_t* plaintext, size_t plaintext_len,
+ void* user_data)
+{
+ EVP_CIPHER_CTX* ctx = NULL;
+ unsigned char* ciphertext = NULL;
+ int outl = 0, finl = 0;
+ int ret = OMEMO_ERR_UNSUPPORTED_CRYPTO;
+
+ switch (key_len) {
+ case 32: break;
+ default: return OMEMO_ERR_UNSUPPORTED_CRYPTO;
+ }
+
+ switch (cipher) {
+ case SG_CIPHER_AES_CBC_PKCS5: break;
+ default: return OMEMO_ERR_UNSUPPORTED_CRYPTO;
+ }
+
+ /* worst case: plaintext + one full block of PKCS7 padding */
+ ciphertext = malloc(plaintext_len + 16);
+ if (!ciphertext)
+ return -1;
+
+ ctx = EVP_CIPHER_CTX_new();
+ if (!ctx)
+ goto out;
+
+ if (EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1)
+ goto out;
+
+ if (EVP_EncryptUpdate(ctx, ciphertext, &outl, plaintext, (int)plaintext_len) != 1)
+ goto out;
+
+ if (EVP_EncryptFinal_ex(ctx, ciphertext + outl, &finl) != 1)
+ goto out;
+
+ *output = signal_buffer_create(ciphertext, outl + finl);
+ ret = *output ? SG_SUCCESS : -1;
+
+out:
+ EVP_CIPHER_CTX_free(ctx);
+ free(ciphertext);
+ return ret;
+}
+
+int
+omemo_decrypt_func(signal_buffer** output, int cipher,
+ const uint8_t* key, size_t key_len,
+ const uint8_t* iv, size_t iv_len,
+ const uint8_t* ciphertext, size_t ciphertext_len,
+ void* user_data)
+{
+ EVP_CIPHER_CTX* ctx = NULL;
+ unsigned char* plaintext = NULL;
+ int outl = 0, finl = 0;
+ int ret = OMEMO_ERR_UNSUPPORTED_CRYPTO;
+
+ switch (key_len) {
+ case 32: break;
+ default: return OMEMO_ERR_UNSUPPORTED_CRYPTO;
+ }
+
+ switch (cipher) {
+ case SG_CIPHER_AES_CBC_PKCS5: break;
+ default: return OMEMO_ERR_UNSUPPORTED_CRYPTO;
+ }
+
+ plaintext = malloc(ciphertext_len);
+ if (!plaintext)
+ return -1;
+
+ ctx = EVP_CIPHER_CTX_new();
+ if (!ctx)
+ goto out;
+
+ if (EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1)
+ goto out;
+
+ if (EVP_DecryptUpdate(ctx, plaintext, &outl, ciphertext, (int)ciphertext_len) != 1)
+ goto out;
+
+ if (EVP_DecryptFinal_ex(ctx, plaintext + outl, &finl) != 1)
+ goto out;
+
+ *output = signal_buffer_create(plaintext, outl + finl);
+ ret = *output ? SG_SUCCESS : -1;
+
+out:
+ EVP_CIPHER_CTX_free(ctx);
+ free(plaintext);
+ return ret;
+}
+
+/*
+ * AES-128-GCM encrypt — used for the actual OMEMO message payload.
+ * Tag is returned separately from ciphertext.
+ */
+
+int
+aes128gcm_encrypt(unsigned char* ciphertext, size_t* ciphertext_len,
+ unsigned char* tag, size_t* tag_len,
+ const unsigned char* const plaintext, size_t plaintext_len,
+ const unsigned char* const iv, const unsigned char* const key)
+{
+ EVP_CIPHER_CTX* ctx = NULL;
+ int outl = 0, finl = 0;
+ int ret = -1;
+
+ ctx = EVP_CIPHER_CTX_new();
+ if (!ctx)
+ goto out;
+
+ if (EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL) != 1)
+ goto out;
+
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, AES128_GCM_IV_LENGTH, NULL) != 1)
+ goto out;
+
+ if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv) != 1)
+ goto out;
+
+ if (EVP_EncryptUpdate(ctx, ciphertext, &outl, plaintext, (int)plaintext_len) != 1)
+ goto out;
+
+ if (EVP_EncryptFinal_ex(ctx, ciphertext + outl, &finl) != 1)
+ goto out;
+
+ *ciphertext_len = outl + finl;
+
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, AES128_GCM_TAG_LENGTH, tag) != 1)
+ goto out;
+
+ *tag_len = AES128_GCM_TAG_LENGTH;
+ ret = 0;
+
+out:
+ EVP_CIPHER_CTX_free(ctx);
+ return ret;
+}
+
+/*
+ * AES-128-GCM decrypt.
+ * Tag is passed as a separate last parameter (not appended to ciphertext).
+ * iv_len is honoured so both 12-byte and 16-byte IVs work.
+ */
+
+int
+aes128gcm_decrypt(unsigned char* plaintext, size_t* plaintext_len,
+ const unsigned char* const ciphertext, size_t ciphertext_len,
+ const unsigned char* const iv, size_t iv_len,
+ const unsigned char* const key, const unsigned char* const tag)
+{
+ EVP_CIPHER_CTX* ctx = NULL;
+ int outl = 0, finl = 0;
+ int ret = -1;
+
+ ctx = EVP_CIPHER_CTX_new();
+ if (!ctx)
+ goto out;
+
+ if (EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL) != 1)
+ goto out;
+
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, (int)iv_len, NULL) != 1)
+ goto out;
+
+ if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv) != 1)
+ goto out;
+
+ if (EVP_DecryptUpdate(ctx, plaintext, &outl, ciphertext, (int)ciphertext_len) != 1)
+ goto out;
+
+ /* must set tag before calling Final */
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG,
+ AES128_GCM_TAG_LENGTH, (void*)tag) != 1)
+ goto out;
+
+ if (EVP_DecryptFinal_ex(ctx, plaintext + outl, &finl) != 1) {
+ log_error("OMEMO: aes128gcm_decrypt tag verification failed");
+ goto out;
+ }
+
+ *plaintext_len = outl + finl;
+ ret = 0;
+
+out:
+ EVP_CIPHER_CTX_free(ctx);
+ return ret;
+}
+
+/*
+ * AES-256-GCM file encrypt/decrypt.
+ * Single function: gboolean encrypt selects direction.
+ * Returns 0 on success, -1 on failure.
+ */
+
+int
+aes256gcm_crypt_file(FILE* in, FILE* out, off_t file_size,
+ unsigned char key[], unsigned char nonce[], gboolean encrypt)
+{
+ EVP_CIPHER_CTX* ctx = NULL;
+ unsigned char buf[AES256_GCM_BUFFER_SIZE];
+ unsigned char outbuf[AES256_GCM_BUFFER_SIZE + 16];
+ unsigned char tag[AES256_GCM_TAG_LENGTH];
+ off_t bytes_remaining;
+ int bytes, outl, finl;
+ int ret = -1;
+
+ ctx = EVP_CIPHER_CTX_new();
+ if (!ctx)
+ goto out;
+
+ if (encrypt) {
+ if (EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) != 1)
+ goto out;
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
+ OMEMO_AESGCM_NONCE_LENGTH, NULL) != 1)
+ goto out;
+ if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce) != 1)
+ goto out;
+
+ bytes_remaining = file_size;
+ while (bytes_remaining > 0) {
+ size_t read_size = bytes_remaining < (off_t)sizeof(buf)
+ ? (size_t)bytes_remaining : sizeof(buf);
+ bytes = fread(buf, 1, read_size, in);
+ if (bytes <= 0)
+ break;
+ if (EVP_EncryptUpdate(ctx, outbuf, &outl, buf, bytes) != 1)
+ goto out;
+ if (outl > 0 && fwrite(outbuf, 1, outl, out) != (size_t)outl)
+ goto out;
+ bytes_remaining -= bytes;
+ }
+ if (ferror(in))
+ goto out;
+
+ if (EVP_EncryptFinal_ex(ctx, outbuf, &finl) != 1)
+ goto out;
+ if (finl > 0 && fwrite(outbuf, 1, finl, out) != (size_t)finl)
+ goto out;
+
+ /* append authentication tag */
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG,
+ AES256_GCM_TAG_LENGTH, tag) != 1)
+ goto out;
+ if (fwrite(tag, 1, AES256_GCM_TAG_LENGTH, out) != AES256_GCM_TAG_LENGTH)
+ goto out;
+
+ } else {
+ /* decrypt: tag is the last AES256_GCM_TAG_LENGTH bytes of the file */
+ if (file_size < AES256_GCM_TAG_LENGTH)
+ goto out;
+ off_t data_size = file_size - AES256_GCM_TAG_LENGTH;
+
+ if (EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) != 1)
+ goto out;
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
+ OMEMO_AESGCM_NONCE_LENGTH, NULL) != 1)
+ goto out;
+ if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, nonce) != 1)
+ goto out;
+
+ bytes_remaining = data_size;
+ while (bytes_remaining > 0) {
+ size_t read_size = bytes_remaining < (off_t)sizeof(buf)
+ ? (size_t)bytes_remaining : sizeof(buf);
+ bytes = fread(buf, 1, read_size, in);
+ if (bytes <= 0)
+ break;
+ if (EVP_DecryptUpdate(ctx, outbuf, &outl, buf, bytes) != 1)
+ goto out;
+ if (outl > 0 && fwrite(outbuf, 1, outl, out) != (size_t)outl)
+ goto out;
+ bytes_remaining -= bytes;
+ }
+ if (ferror(in))
+ goto out;
+
+ /* read and verify tag */
+ if (fread(tag, 1, AES256_GCM_TAG_LENGTH, in) != AES256_GCM_TAG_LENGTH)
+ goto out;
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG,
+ AES256_GCM_TAG_LENGTH, tag) != 1)
+ goto out;
+ if (EVP_DecryptFinal_ex(ctx, outbuf, &finl) != 1) {
+ log_error("OMEMO: aes256gcm_crypt_file tag verification failed");
+ goto out;
+ }
+ if (finl > 0 && fwrite(outbuf, 1, finl, out) != (size_t)finl)
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ EVP_CIPHER_CTX_free(ctx);
+ return ret;
+}
+
+/*
+ * Build the aesgcm:// URL fragment: hex(nonce) + hex(key)
+ * Original used gcry_malloc_secure; plain malloc suffices here —
+ * this string is a URL fragment, not long-lived key material.
+ */
+
+char*
+aes256gcm_create_secure_fragment(unsigned char* key, unsigned char* nonce)
+{
+ int key_size = OMEMO_AESGCM_KEY_LENGTH;
+ int nonce_size = OMEMO_AESGCM_NONCE_LENGTH;
+ char* fragment = malloc((nonce_size + key_size) * 2 + 1);
+
+ if (!fragment)
+ return NULL;
+
+ for (int i = 0; i < nonce_size; i++)
+ sprintf(&(fragment[i * 2]), "%02x", nonce[i]);
+ for (int i = 0; i < key_size; i++)
+ sprintf(&(fragment[(i + nonce_size) * 2]), "%02x", key[i]);
+
+ return fragment;
+}
diff --git a/opt/profanity/crypto.h b/opt/profanity/crypto.h
new file mode 100644
index 0000000..3af989c
--- /dev/null
+++ b/opt/profanity/crypto.h
@@ -0,0 +1,193 @@
+/*
+ * crypto.h
+ * vim: expandtab:ts=4:sts=4:sw=4
+ *
+ * Copyright (C) 2019 Paul Fariello <paul@fariello.eu>
+ *
+ * This file is part of Profanity.
+ *
+ * Profanity is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Profanity is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Profanity. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * In addition, as a special exception, the copyright holders give permission to
+ * link the code of portions of this program with the OpenSSL library under
+ * certain conditions as described in each individual source file, and
+ * distribute linked combinations including the two.
+ *
+ * You must obey the GNU General Public License in all respects for all of the
+ * code used other than OpenSSL. If you modify file(s) with this exception, you
+ * may extend this exception to your version of the file(s), but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version. If you delete this exception statement from all
+ * source files in the program, then also delete it here.
+ *
+ */
+#include <stdio.h>
+#include <stdbool.h>
+#include <signal/signal_protocol_types.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/rand.h>
+
+#define AES128_GCM_KEY_LENGTH 16
+#define AES128_GCM_IV_LENGTH 12
+#define AES128_GCM_TAG_LENGTH 16
+
+int omemo_crypto_init(void);
+/**
+ * Callback for a secure random number generator.
+ * This function shall fill the provided buffer with random bytes.
+ *
+ * @param data pointer to the output buffer
+ * @param len size of the output buffer
+ * @return 0 on success, negative on failure
+ */
+int omemo_random_func(uint8_t* data, size_t len, void* user_data);
+
+/**
+ * Callback for an HMAC-SHA256 implementation.
+ * This function shall initialize an HMAC context with the provided key.
+ *
+ * @param hmac_context private HMAC context pointer
+ * @param key pointer to the key
+ * @param key_len length of the key
+ * @return 0 on success, negative on failure
+ */
+int omemo_hmac_sha256_init_func(void** hmac_context, const uint8_t* key, size_t key_len, void* user_data);
+
+/**
+ * Callback for an HMAC-SHA256 implementation.
+ * This function shall update the HMAC context with the provided data
+ *
+ * @param hmac_context private HMAC context pointer
+ * @param data pointer to the data
+ * @param data_len length of the data
+ * @return 0 on success, negative on failure
+ */
+int omemo_hmac_sha256_update_func(void* hmac_context, const uint8_t* data, size_t data_len, void* user_data);
+
+/**
+ * Callback for an HMAC-SHA256 implementation.
+ * This function shall finalize an HMAC calculation and populate the output
+ * buffer with the result.
+ *
+ * @param hmac_context private HMAC context pointer
+ * @param output buffer to be allocated and populated with the result
+ * @return 0 on success, negative on failure
+ */
+int omemo_hmac_sha256_final_func(void* hmac_context, signal_buffer** output, void* user_data);
+
+/**
+ * Callback for an HMAC-SHA256 implementation.
+ * This function shall free the private context allocated in
+ * hmac_sha256_init_func.
+ *
+ * @param hmac_context private HMAC context pointer
+ */
+void omemo_hmac_sha256_cleanup_func(void* hmac_context, void* user_data);
+
+/**
+ * Callback for a SHA512 message digest implementation.
+ * This function shall initialize a digest context.
+ *
+ * @param digest_context private digest context pointer
+ * @return 0 on success, negative on failure
+ */
+int omemo_sha512_digest_init_func(void** digest_context, void* user_data);
+
+/**
+ * Callback for a SHA512 message digest implementation.
+ * This function shall update the digest context with the provided data.
+ *
+ * @param digest_context private digest context pointer
+ * @param data pointer to the data
+ * @param data_len length of the data
+ * @return 0 on success, negative on failure
+ */
+int omemo_sha512_digest_update_func(void* digest_context, const uint8_t* data, size_t data_len, void* user_data);
+
+/**
+ * Callback for a SHA512 message digest implementation.
+ * This function shall finalize the digest calculation, populate the
+ * output buffer with the result, and prepare the context for reuse.
+ *
+ * @param digest_context private digest context pointer
+ * @param output buffer to be allocated and populated with the result
+ * @return 0 on success, negative on failure
+ */
+int omemo_sha512_digest_final_func(void* digest_context, signal_buffer** output, void* user_data);
+
+/**
+ * Callback for a SHA512 message digest implementation.
+ * This function shall free the private context allocated in
+ * sha512_digest_init_func.
+ *
+ * @param digest_context private digest context pointer
+ */
+void omemo_sha512_digest_cleanup_func(void* digest_context, void* user_data);
+
+/**
+ * Callback for an AES encryption implementation.
+ *
+ * @param output buffer to be allocated and populated with the ciphertext
+ * @param cipher specific cipher variant to use, either SG_CIPHER_AES_CTR_NOPADDING or SG_CIPHER_AES_CBC_PKCS5
+ * @param key the encryption key
+ * @param key_len length of the encryption key
+ * @param iv the initialization vector
+ * @param iv_len length of the initialization vector
+ * @param plaintext the plaintext to encrypt
+ * @param plaintext_len length of the plaintext
+ * @return 0 on success, negative on failure
+ */
+int omemo_encrypt_func(signal_buffer** output,
+ int cipher,
+ const uint8_t* key, size_t key_len,
+ const uint8_t* iv, size_t iv_len,
+ const uint8_t* plaintext, size_t plaintext_len,
+ void* user_data);
+
+/**
+ * Callback for an AES decryption implementation.
+ *
+ * @param output buffer to be allocated and populated with the plaintext
+ * @param cipher specific cipher variant to use, either SG_CIPHER_AES_CTR_NOPADDING or SG_CIPHER_AES_CBC_PKCS5
+ * @param key the encryption key
+ * @param key_len length of the encryption key
+ * @param iv the initialization vector
+ * @param iv_len length of the initialization vector
+ * @param ciphertext the ciphertext to decrypt
+ * @param ciphertext_len length of the ciphertext
+ * @return 0 on success, negative on failure
+ */
+int omemo_decrypt_func(signal_buffer** output,
+ int cipher,
+ const uint8_t* key, size_t key_len,
+ const uint8_t* iv, size_t iv_len,
+ const uint8_t* ciphertext, size_t ciphertext_len,
+ void* user_data);
+
+int aes128gcm_encrypt(unsigned char* ciphertext, size_t* ciphertext_len,
+ unsigned char* tag, size_t* tag_len,
+ const unsigned char* const plaintext, size_t plaintext_len,
+ const unsigned char* const iv, const unsigned char* const key);
+
+int aes128gcm_decrypt(unsigned char* plaintext,
+ size_t* plaintext_len, const unsigned char* const ciphertext,
+ size_t ciphertext_len, const unsigned char* const iv, size_t iv_len,
+ const unsigned char* const key, const unsigned char* const tag);
+
+int aes256gcm_crypt_file(FILE* in, FILE* out, off_t file_size,
+ unsigned char key[], unsigned char nonce[], gboolean encrypt);
+
+char* aes256gcm_create_secure_fragment(unsigned char* key,
+ unsigned char* nonce);
diff --git a/opt/profanity/omemo-publish-options.patch b/opt/profanity/omemo-publish-options.patch
new file mode 100644
index 0000000..daabd81
--- /dev/null
+++ b/opt/profanity/omemo-publish-options.patch
@@ -0,0 +1,55 @@
+Publish OMEMO bundle and device list with publish-options regardless of the
+server domain's advertised features.
+
+connection_supports() only inspects features_by_jid, which connection.c seeds
+with the server domain (conn.domain) plus whatever disco#items returns for that
+domain. The account's own bare JID -- which is what actually hosts the PEP
+service used for OMEMO -- is never added to that table. On deployments whose
+host disco#info is trimmed down, the check therefore fails even though the
+account itself advertises
+http://jabber.org/protocol/pubsub#publish-options.
+
+Two separate symptoms follow:
+
+ * omemo_bundle_publish() returned early and sent nothing at all, so the
+ bundles:<device_id> node was never created. Contacts fetching it got
+ item-not-found and no session could ever be established.
+
+ * omemo_devicelist_publish() published without publish-options, so the
+ devicelist node was auto-created with the server's default access model
+ (presence on Prosody) instead of open. Contacts without a presence
+ subscription could not read the device list, so they never learned which
+ bundle to request.
+
+Send publish-options unconditionally in both cases. If a server genuinely
+rejects them, the existing recovery paths handle it: _omemo_bundle_publish_result()
+falls back to configuring the node explicitly, and _omemo_devicelist_publish_result()
+reconfigures on precondition-not-met.
+
+--- a/src/xmpp/omemo.c
++++ b/src/xmpp/omemo.c
+@@ -44,11 +44,7 @@
+
+ log_debug("[OMEMO] publish device list");
+
+- if (connection_supports(XMPP_FEATURE_PUBSUB_PUBLISH_OPTIONS)) {
+- stanza_attach_publish_options(ctx, iq, "pubsub#access_model", "open");
+- } else {
+- log_debug("[OMEMO] Cannot publish devicelist: no PUBSUB feature announced");
+- }
++ stanza_attach_publish_options(ctx, iq, "pubsub#access_model", "open");
+
+ iq_id_handler_add(xmpp_stanza_get_id(iq), _omemo_devicelist_publish_result, NULL, NULL);
+
+@@ -90,11 +86,6 @@
+ void
+ omemo_bundle_publish(gboolean first)
+ {
+- if (!connection_supports(XMPP_FEATURE_PUBSUB_PUBLISH_OPTIONS)) {
+- cons_show("OMEMO: Cannot publish bundle: no PUBSUB feature announced");
+- log_debug("[OMEMO] Cannot publish bundle: no PUBSUB feature announced");
+- return;
+- }
+ log_debug("[OMEMO] publish own OMEMO bundle");
+ xmpp_ctx_t* const ctx = connection_get_ctx();
+ unsigned char* identity_key = NULL;
diff --git a/opt/profanity/openssl-aesgcm-download.patch b/opt/profanity/openssl-aesgcm-download.patch
new file mode 100644
index 0000000..c0a7ad4
--- /dev/null
+++ b/opt/profanity/openssl-aesgcm-download.patch
@@ -0,0 +1,24 @@
+--- a/src/tools/aesgcm_download.c
++++ b/src/tools/aesgcm_download.c
+@@ -105,17 +105,17 @@
+ return NULL;
+ }
+
+- gcry_error_t crypt_res;
++ int crypt_res;
+ crypt_res = omemo_decrypt_file(tmpfh, outfh,
+ bytes_received, fragment);
+ fclose(tmpfh);
+ remove(tmpname);
+
+- if (crypt_res != GPG_ERR_NO_ERROR) {
++ if (crypt_res != 0) {
+ http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, THEME_ERROR, ENTRY_ERROR,
+ "Downloading '%s' failed: Failed to decrypt "
+- "file (%s).",
+- aesgcm_dl->url, gcry_strerror(crypt_res));
++ "file (%d).",
++ aesgcm_dl->url, crypt_res);
+ } else {
+ http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, THEME_ONLINE, ENTRY_COMPLETED,
+ "Downloading '%s': done\nSaved to '%s'",
diff --git a/opt/profanity/openssl-crypto.patch b/opt/profanity/openssl-crypto.patch
new file mode 100644
index 0000000..7b384fe
--- /dev/null
+++ b/opt/profanity/openssl-crypto.patch
@@ -0,0 +1,12 @@
+--- a/meson.build
++++ b/meson.build
+@@ -273,7 +273,7 @@
+ omemo_dep = dependency('libomemo-c', version: '>= 0.5.1', required: true)
+ conf_data.set('HAVE_LIBOMEMO_C', 1)
+ endif
+- gcrypt_dep = dependency('libgcrypt', version: '>= 1.7.0', required: true)
++ gcrypt_dep = dependency('openssl', version: '>= 1.1.0', required: true)
+ build_omemo = true
+ conf_data.set('HAVE_OMEMO', 1)
+ endif
+
diff --git a/opt/profanity/openssl-omemo-c.patch b/opt/profanity/openssl-omemo-c.patch
new file mode 100644
index 0000000..45f6ac1
--- /dev/null
+++ b/opt/profanity/openssl-omemo-c.patch
@@ -0,0 +1,136 @@
+--- a/src/omemo/omemo.c
++++ b/src/omemo/omemo.c
+@@ -118,9 +118,9 @@
+
+ prof_add_shutdown_routine(_omemo_close);
+
+- gcry_error_t crypt_res = omemo_crypto_init();
++ int crypt_res = omemo_crypto_init();
+ if (crypt_res != 0) {
+- cons_show("Error initializing OMEMO crypto: %s", gcry_strerror(crypt_res));
++ cons_show("Error initializing OMEMO crypto: %d", crypt_res);
+ }
+
+ pthread_mutexattr_init(&omemo_static_data.attr);
+@@ -300,7 +300,7 @@
+ log_info("Generate long term OMEMO cryptography materials");
+
+ /* Device ID */
+- gcry_randomize(&omemo_ctx.device_id, 4, GCRY_VERY_STRONG_RANDOM);
++ RAND_bytes((unsigned char *)&omemo_ctx.device_id, 4);
+ omemo_ctx.device_id &= 0x7fffffff;
+ g_key_file_set_uint64(omemo_ctx.identity.keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_DEVICE_ID, omemo_ctx.device_id);
+ log_info("[OMEMO] device id: %d", omemo_ctx.device_id);
+@@ -708,7 +708,7 @@
+ log_error("[OMEMO] No prekeys found for %s device %d", jid, device_id);
+ goto out;
+ }
+- gcry_randomize(&prekey_index, sizeof(int), GCRY_STRONG_RANDOM);
++ RAND_bytes((unsigned char *)&prekey_index, sizeof(int));
+ prekey_index %= prekeys_len;
+ omemo_key_t* prekey = g_list_nth_data(prekeys, prekey_index);
+
+@@ -780,10 +780,11 @@
+ goto out;
+ }
+ tag_len = AES128_GCM_TAG_LENGTH;
+- tag = gcry_malloc_secure(tag_len);
+- key_tag = gcry_malloc_secure(AES128_GCM_KEY_LENGTH + AES128_GCM_TAG_LENGTH);
++ tag = malloc(tag_len);
++ key_tag = malloc(AES128_GCM_KEY_LENGTH + AES128_GCM_TAG_LENGTH);
+
+- key = gcry_random_bytes_secure(AES128_GCM_KEY_LENGTH + AES128_GCM_IV_LENGTH, GCRY_VERY_STRONG_RANDOM);
++ key = malloc(AES128_GCM_KEY_LENGTH + AES128_GCM_IV_LENGTH);
++ RAND_bytes(key, AES128_GCM_KEY_LENGTH + AES128_GCM_IV_LENGTH);
+ iv = key + AES128_GCM_KEY_LENGTH;
+
+ res = aes128gcm_encrypt(ciphertext, &ciphertext_len, tag, &tag_len, (const unsigned char* const)message, strlen(message), iv, key);
+@@ -999,9 +1000,9 @@
+ omemo_sessions_keyfile_save();
+ g_list_free_full(keys, (GDestroyNotify)omemo_key_free);
+ free(ciphertext);
+- gcry_free(key);
+- gcry_free(tag);
+- gcry_free(key_tag);
++ free(key);
++ free(tag);
++ free(key_tag);
+
+ return id;
+ }
+@@ -1158,7 +1159,7 @@
+ signal_buffer_data(plaintext_key) + AES128_GCM_KEY_LENGTH);
+ signal_buffer_free(plaintext_key);
+ if (res != 0) {
+- log_error("[OMEMO][RECV] cannot decrypt message: %s", gcry_strerror(res));
++ log_error("[OMEMO][RECV] cannot decrypt message, res=%d", res);
+ free(plaintext);
+ *error = OMEMO_ERR_DECRYPT_FAILED;
+ return NULL;
+@@ -2010,29 +2011,28 @@
+ void
+ omemo_free(void* a)
+ {
+- gcry_free(a);
++ free(a);
+ }
+
+ char*
+ omemo_encrypt_file(FILE* in, FILE* out, off_t file_size, int* gcry_res)
+ {
+- unsigned char* key = gcry_random_bytes_secure(
+- OMEMO_AESGCM_KEY_LENGTH,
+- GCRY_VERY_STRONG_RANDOM);
++ unsigned char* key = malloc(OMEMO_AESGCM_KEY_LENGTH);
++ RAND_bytes(key, OMEMO_AESGCM_KEY_LENGTH);
+
+ // Create nonce/IV with random bytes.
+ unsigned char nonce[OMEMO_AESGCM_NONCE_LENGTH];
+- gcry_create_nonce(nonce, OMEMO_AESGCM_NONCE_LENGTH);
++ RAND_bytes(nonce, OMEMO_AESGCM_NONCE_LENGTH);
+
+ char* fragment = aes256gcm_create_secure_fragment(key, nonce);
+ *gcry_res = aes256gcm_crypt_file(in, out, file_size, key, nonce, TRUE);
+
+- if (*gcry_res != GPG_ERR_NO_ERROR) {
+- gcry_free(fragment);
++ if (*gcry_res != 0) {
++ free(fragment);
+ fragment = NULL;
+ }
+
+- gcry_free(key);
++ free(key);
+
+ return fragment;
+ }
+@@ -2063,7 +2063,7 @@
+ }
+ }
+
+-gcry_error_t
++int
+ omemo_decrypt_file(FILE* in, FILE* out, off_t file_size, const char* fragment)
+ {
+ char nonce_hex[AESGCM_URL_NONCE_LEN];
+@@ -2076,17 +2076,17 @@
+ memcpy(key_hex, &(fragment[key_pos]), AESGCM_URL_KEY_LEN);
+
+ unsigned char nonce[OMEMO_AESGCM_NONCE_LENGTH];
+- unsigned char* key = gcry_malloc_secure(OMEMO_AESGCM_KEY_LENGTH);
++ unsigned char* key = malloc(OMEMO_AESGCM_KEY_LENGTH);
+
+ _bytes_from_hex(nonce_hex, AESGCM_URL_NONCE_LEN,
+ nonce, OMEMO_AESGCM_NONCE_LENGTH);
+ _bytes_from_hex(key_hex, AESGCM_URL_KEY_LEN,
+ key, OMEMO_AESGCM_KEY_LENGTH);
+
+- gcry_error_t crypt_res;
++ int crypt_res;
+ crypt_res = aes256gcm_crypt_file(in, out, file_size, key, nonce, FALSE);
+
+- gcry_free(key);
++ free(key);
+
+ return crypt_res;
+ }
diff --git a/opt/profanity/openssl-omemo-h.patch b/opt/profanity/openssl-omemo-h.patch
new file mode 100644
index 0000000..558d3ba
--- /dev/null
+++ b/opt/profanity/openssl-omemo-h.patch
@@ -0,0 +1,19 @@
+--- a/src/omemo/omemo.h
++++ b/src/omemo/omemo.h
+@@ -33,7 +33,6 @@
+ *
+ */
+ #include <glib.h>
+-#include <gcrypt.h>
+
+ #include "ui/ui.h"
+ #include "config/account.h"
+@@ -99,7 +98,7 @@
+ char* omemo_on_message_recv(const char* const from, uint32_t sid, const unsigned char* const iv, size_t iv_len, GList* keys, const unsigned char* const payload, size_t payload_len, gboolean muc, gboolean* trusted);
+
+ char* omemo_encrypt_file(FILE* in, FILE* out, off_t file_size, int* gcry_res);
+-gcry_error_t omemo_decrypt_file(FILE* in, FILE* out, off_t file_size, const char* fragment);
++int omemo_decrypt_file(FILE* in, FILE* out, off_t file_size, const char* fragment);
+ void omemo_free(void* a);
+ int omemo_parse_aesgcm_url(const char* aesgcm_url, char** https_url, char** fragment);
+