From d5b1dc0eb6ee9c4caee6c73b9cf26133c875a1c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Wennerstr=C3=B6m?= Date: Sun, 28 Jun 2020 12:17:21 +0200 Subject: [PATCH] Move setup for AESGCM to omemo/crypto --- src/command/cmd_funcs.c | 71 ++++++++++------------------------------- src/omemo/crypto.c | 50 +++++++++++++++++++++++++---- src/omemo/crypto.h | 9 +++--- src/tools/http_upload.c | 2 ++ 4 files changed, 68 insertions(+), 64 deletions(-) diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index d16cd938..74a21a09 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -4812,27 +4812,13 @@ cmd_disco(ProfWin* window, const char* const command, gchar** args) return TRUE; } -char *create_aesgcm_fragment(unsigned char *key, int key_size, - unsigned char *nonce, int nonce_size) { - char fragment[(nonce_size+key_size)*2+1]; - - 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 strdup(fragment); -} - gboolean cmd_sendfile(ProfWin* window, const char* const command, gchar** args) { jabber_conn_status_t conn_status = connection_get_status(); char *filename = args[0]; - unsigned char *key = NULL; + char *alt_scheme = NULL; + char *alt_fragment = NULL; // expand ~ to $HOME if (filename[0] == '~' && filename[1] == '/') { @@ -4870,8 +4856,6 @@ cmd_sendfile(ProfWin* window, const char* const command, gchar** args) } FILE *fh = fdopen(fd, "rb"); - char *alt_scheme = NULL; - char *alt_fragment = NULL; switch (window->type) { case WIN_MUC: @@ -4881,37 +4865,25 @@ cmd_sendfile(ProfWin* window, const char* const command, gchar** args) assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); if (chatwin->is_omemo && !prefs_get_boolean(PREF_OMEMO_SENDFILE)) { + + // Create temporary file for writing ciphertext. int tmpfd; if ((tmpfd = g_file_open_tmp("profanity.XXXXXX", NULL, NULL)) == -1) { - cons_show_error("Unable to create temporary file for encrypted transfer."); - win_println(window, THEME_ERROR, "-", "Unable to create temporary file for encrypted transfer."); + char *msg = "Unable to create temporary file for encrypted transfer."; + cons_show_error(msg); + win_println(window, THEME_ERROR, "-", msg); fclose(fh); goto out; } - FILE *tmpfh = fdopen(tmpfd, "wb"); int crypt_res = GPG_ERR_NO_ERROR; - - // TODO(wstrm): Move these to omemo/crypto.c - unsigned char nonce[AES256_GCM_NONCE_LENGTH]; - key = gcry_malloc_secure(AES256_GCM_KEY_LENGTH); - if (key == NULL) { - cons_show_error("Cannot allocate secure memory for encryption."); - win_println(window, THEME_ERROR, "-", "Cannot allocate secure memory for encryption."); - fclose(fh); - fclose(tmpfh); - goto out; - } - - key = gcry_random_bytes_secure(AES256_GCM_KEY_LENGTH, GCRY_VERY_STRONG_RANDOM); - gcry_create_nonce(nonce, AES256_GCM_NONCE_LENGTH); - - crypt_res = aes256gcm_encrypt_file(fh, tmpfh, file_size(fd), key, nonce); - + alt_scheme = AESGCM_URL_SCHEME; + alt_fragment = aes256gcm_encrypt_file(fh, tmpfh, file_size(fd), &crypt_res); if (crypt_res != 0) { - cons_show_error("Failed to encrypt file."); - win_println(window, THEME_ERROR, "-", "Failed to encrypt file."); + char *msg = "Failed to encrypt file."; + cons_show_error(msg); + win_println(window, THEME_ERROR, "-", msg); fclose(fh); fclose(tmpfh); goto out; @@ -4927,11 +4899,6 @@ cmd_sendfile(ProfWin* window, const char* const command, gchar** args) fd = tmpfd; fh = tmpfh; - alt_scheme = AESGCM_URL_SCHEME; - alt_fragment = create_aesgcm_fragment( - key, AES256_GCM_KEY_LENGTH, - nonce, AES256_GCM_NONCE_LENGTH); - break; } @@ -4943,11 +4910,7 @@ cmd_sendfile(ProfWin* window, const char* const command, gchar** args) } break; } - case WIN_PRIVATE: - { - // We don't support encryption in private MUC windows. - break; - } + case WIN_PRIVATE: // We don't support encryption in private MUC windows. default: cons_show_error("Unsupported window for file transmission."); goto out; @@ -4972,14 +4935,14 @@ cmd_sendfile(ProfWin* window, const char* const command, gchar** args) upload->filehandle = fh; upload->filesize = file_size(fd); upload->mime_type = file_mime_type(filename); - upload->alt_scheme = alt_scheme; - upload->alt_fragment = alt_fragment; + upload->alt_scheme = strdup(alt_scheme); + upload->alt_fragment = strdup(alt_fragment); iq_http_upload_request(upload); out: - if (key != NULL) - gcry_free(key); + if (alt_fragment != NULL) + aes256gcm_fragment_free(alt_fragment); if (filename != NULL) free(filename); diff --git a/src/omemo/crypto.c b/src/omemo/crypto.c index 6d6ba519..7dd3be10 100644 --- a/src/omemo/crypto.c +++ b/src/omemo/crypto.c @@ -463,12 +463,50 @@ out: return res; } -int aes256gcm_encrypt_file(FILE *in, FILE *out, off_t file_size, - unsigned char key[], unsigned char nonce[]) { - return aes256gcm_crypt_file(in, out, file_size, key, nonce, true); +char *aes256gcm_create_secure_fragment(unsigned char *key, unsigned char *nonce) { + int key_size = AES256_GCM_KEY_LENGTH; + int nonce_size = AES256_GCM_NONCE_LENGTH; + + char *fragment = gcry_malloc_secure((nonce_size+key_size)*2+1); + + 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; } -int aes256gcm_decrypt_file(FILE *in, FILE *out, off_t file_size, - unsigned char key[], unsigned char nonce[]) { - return aes256gcm_crypt_file(in, out, file_size, key, nonce, false); +void aes256gcm_fragment_free(char *fragment) { + gcry_free(fragment); } + +char *aes256gcm_encrypt_file(FILE *in, FILE *out, off_t file_size, int *gcry_res) { + unsigned char *key = gcry_random_bytes_secure( + AES256_GCM_KEY_LENGTH, + GCRY_VERY_STRONG_RANDOM); + + // Create nonce/IV with random bytes. + unsigned char nonce[AES256_GCM_NONCE_LENGTH]; + gcry_create_nonce(nonce, AES256_GCM_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); + fragment = NULL; + } + + gcry_free(key); + + return fragment; +} + +//int aes256gcm_decrypt_file(FILE *in, FILE *out, off_t file_size, +// unsigned char key[], unsigned char nonce[]) { +// return aes256gcm_crypt_file(in, out, file_size, key, nonce, false); +//} diff --git a/src/omemo/crypto.h b/src/omemo/crypto.h index 916486b7..34cbb82c 100644 --- a/src/omemo/crypto.h +++ b/src/omemo/crypto.h @@ -185,8 +185,9 @@ int aes128gcm_decrypt(unsigned char *plaintext, 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_encrypt_file(FILE *in, FILE *out, off_t file_size, - unsigned char key[], unsigned char nonce[]); +char *aes256gcm_encrypt_file(FILE *in, FILE *out, off_t file_size, int *gcry_res); -int aes256gcm_decrypt_file(FILE *in, FILE *out, off_t file_size, - unsigned char key[], unsigned char nonce[]); +//int aes256gcm_decrypt_file(FILE *in, FILE *out, off_t file_size, +// unsigned char key[], unsigned char nonce[]); + +void aes256gcm_fragment_free(char *fragment); diff --git a/src/tools/http_upload.c b/src/tools/http_upload.c index 69587c08..d9742e30 100644 --- a/src/tools/http_upload.c +++ b/src/tools/http_upload.c @@ -328,6 +328,8 @@ http_file_put(void *userdata) free(upload->mime_type); free(upload->get_url); free(upload->put_url); + free(upload->alt_scheme); + free(upload->alt_fragment); free(upload); return NULL;