diff --git a/src/common.c b/src/common.c index 3c694f57c1..c231504341 100644 --- a/src/common.c +++ b/src/common.c @@ -942,3 +942,14 @@ prof_get_version(void) return g_strdup_printf("%s", PACKAGE_VERSION); } } + +void +prof_wipe_string(char* str) +{ + if (str) { + volatile char* p = (volatile char*)str; + while (*p) { + *p++ = 0; + } + } +} diff --git a/src/common.h b/src/common.h index 3c18c56ddf..2a8c621e7d 100644 --- a/src/common.h +++ b/src/common.h @@ -135,6 +135,8 @@ free_keyfile(prof_keyfile_t* keyfile); resource = NULL; \ } while (0) +void prof_wipe_string(char* str); + typedef enum { CONTACT_OFFLINE, CONTACT_ONLINE, diff --git a/src/config/account.c b/src/config/account.c index 8bb9137a30..f7e06bd79f 100644 --- a/src/config/account.c +++ b/src/config/account.c @@ -180,6 +180,7 @@ account_free(ProfAccount* account) free(account->name); free(account->jid); + prof_wipe_string(account->password); free(account->password); free(account->eval_password); free(account->resource); diff --git a/src/omemo/crypto.c b/src/omemo/crypto.c index 66a0bcfeaf..b19db31398 100644 --- a/src/omemo/crypto.c +++ b/src/omemo/crypto.c @@ -210,7 +210,7 @@ omemo_encrypt_func(signal_buffer** output, int cipher, const uint8_t* key, size_ assert(FALSE); } - padded_plaintext = malloc(plaintext_len + padding); + padded_plaintext = gcry_malloc_secure(plaintext_len + padding); memcpy(padded_plaintext, plaintext, plaintext_len); memset(padded_plaintext + plaintext_len, padding, padding); @@ -219,7 +219,7 @@ omemo_encrypt_func(signal_buffer** output, int cipher, const uint8_t* key, size_ gcry_cipher_encrypt(hd, ciphertext, ciphertext_len, padded_plaintext, plaintext_len + padding); *output = signal_buffer_create(ciphertext, ciphertext_len); - free(padded_plaintext); + gcry_free(padded_plaintext); free(ciphertext); gcry_cipher_close(hd); @@ -268,17 +268,26 @@ omemo_decrypt_func(signal_buffer** output, int cipher, const uint8_t* key, size_ } plaintext_len = ciphertext_len; - plaintext = malloc(plaintext_len); + plaintext = gcry_malloc_secure(plaintext_len); gcry_cipher_decrypt(hd, plaintext, plaintext_len, ciphertext, ciphertext_len); switch (cipher) { case SG_CIPHER_AES_CBC_PKCS5: + if (plaintext_len == 0) { + ret = SG_ERR_UNKNOWN; + goto out; + } padding = plaintext[plaintext_len - 1]; break; default: assert(FALSE); } + if (padding == 0 || padding > 16 || padding > plaintext_len) { + ret = SG_ERR_UNKNOWN; + goto out; + } + for (int i = 0; i < padding; i++) { if (plaintext[plaintext_len - 1 - i] != padding) { ret = SG_ERR_UNKNOWN; @@ -289,7 +298,7 @@ omemo_decrypt_func(signal_buffer** output, int cipher, const uint8_t* key, size_ *output = signal_buffer_create(plaintext, plaintext_len - padding); out: - free(plaintext); + gcry_free(plaintext); gcry_cipher_close(hd); diff --git a/src/pgp/gpg.c b/src/pgp/gpg.c index 3132ada83c..d8bd51e7d7 100644 --- a/src/pgp/gpg.c +++ b/src/pgp/gpg.c @@ -101,10 +101,12 @@ _p_gpg_close(void) key_ac = NULL; if (passphrase) { + prof_wipe_string(passphrase); GFREE_SET_NULL(passphrase); } if (passphrase_attempt) { + prof_wipe_string(passphrase_attempt); GFREE_SET_NULL(passphrase_attempt); } } diff --git a/src/tools/aesgcm_download.c b/src/tools/aesgcm_download.c index b7e7cd85db..09353c80d9 100644 --- a/src/tools/aesgcm_download.c +++ b/src/tools/aesgcm_download.c @@ -30,6 +30,7 @@ #include "ui/ui.h" #include "ui/window.h" #include "common.h" +#include "log.h" void* aesgcm_file_get(void* userdata) @@ -116,30 +117,35 @@ aesgcm_file_get(void* userdata) "Downloading '%s' failed: Failed to decrypt " "file (%s).", aesgcm_dl->url, gcry_strerror(crypt_res)); + log_error("OMEMO: AESGCM download file integrity check failed for '%s': %s", + aesgcm_dl->url, gcry_strerror(crypt_res)); + remove(aesgcm_dl->filename); } else { http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, THEME_ONLINE, ENTRY_COMPLETED, "Downloading '%s': done\nSaved to '%s'", aesgcm_dl->url, aesgcm_dl->filename); win_mark_received(aesgcm_dl->window, aesgcm_dl->id); - } - if (aesgcm_dl->cmd_template != NULL) { - gchar** argv = format_call_external_argv(aesgcm_dl->cmd_template, - aesgcm_dl->filename, - aesgcm_dl->filename); - - // TODO: Log the error. - if (!call_external(argv)) { - http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, THEME_ERROR, ENTRY_ERROR, - "Downloading '%s' failed: Unable to call " - "command '%s' with file at '%s' (%s).", - aesgcm_dl->url, - aesgcm_dl->cmd_template, - aesgcm_dl->filename, - "TODO: Log the error"); + if (aesgcm_dl->cmd_template != NULL) { + gchar** argv = format_call_external_argv(aesgcm_dl->cmd_template, + aesgcm_dl->filename, + aesgcm_dl->filename); + + if (!call_external(argv)) { + http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, THEME_ERROR, ENTRY_ERROR, + "Downloading '%s' failed: Unable to call " + "command '%s' with file at '%s' (%s).", + aesgcm_dl->url, + aesgcm_dl->cmd_template, + aesgcm_dl->filename, + "Failed to run command"); + } + + g_strfreev(argv); } + } - g_strfreev(argv); + if (aesgcm_dl->cmd_template != NULL) { free(aesgcm_dl->cmd_template); } diff --git a/src/xmpp/session.c b/src/xmpp/session.c index 3c747d4cef..06a3b8d019 100644 --- a/src/xmpp/session.c +++ b/src/xmpp/session.c @@ -616,6 +616,7 @@ static void _session_free_internals(void) { FREE_SET_NULL(saved_account.name); + prof_wipe_string(saved_account.passwd); FREE_SET_NULL(saved_account.passwd); GFREE_SET_NULL(reconnect.altdomain); if (last_moods) { @@ -630,6 +631,7 @@ _session_free_saved_details(void) { FREE_SET_NULL(saved_details.name); FREE_SET_NULL(saved_details.jid); + prof_wipe_string(saved_details.passwd); FREE_SET_NULL(saved_details.passwd); FREE_SET_NULL(saved_details.altdomain); FREE_SET_NULL(saved_details.tls_policy);