diff options
Diffstat (limited to 'opt/profanity')
| -rw-r--r-- | opt/profanity/.footprint | 150 | ||||
| -rw-r--r-- | opt/profanity/.signature | 13 | ||||
| -rw-r--r-- | opt/profanity/MAKEPKG | 71 | ||||
| -rw-r--r-- | opt/profanity/crypto.c | 494 | ||||
| -rw-r--r-- | opt/profanity/crypto.h | 193 | ||||
| -rw-r--r-- | opt/profanity/omemo-publish-options.patch | 55 | ||||
| -rw-r--r-- | opt/profanity/openssl-aesgcm-download.patch | 24 | ||||
| -rw-r--r-- | opt/profanity/openssl-crypto.patch | 12 | ||||
| -rw-r--r-- | opt/profanity/openssl-omemo-c.patch | 136 | ||||
| -rw-r--r-- | opt/profanity/openssl-omemo-h.patch | 19 |
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); + |
