Refactor OMEMO download into AESGCMDownload tool

This commit is contained in:
William Wennerström
2020-07-20 22:49:50 +02:00
parent fb002a59b6
commit 73f313b921
12 changed files with 386 additions and 23 deletions

View File

@@ -400,12 +400,12 @@ aes256gcm_crypt_file(FILE* in, FILE* out, off_t file_size,
goto out;
}
res = gcry_cipher_setkey(hd, key, AES256_GCM_KEY_LENGTH);
res = gcry_cipher_setkey(hd, key, OMEMO_AESGCM_KEY_LENGTH);
if (res != GPG_ERR_NO_ERROR) {
goto out;
}
res = gcry_cipher_setiv(hd, nonce, AES256_GCM_NONCE_LENGTH);
res = gcry_cipher_setiv(hd, nonce, OMEMO_AESGCM_NONCE_LENGTH);
if (res != GPG_ERR_NO_ERROR) {
goto out;
}
@@ -468,8 +468,8 @@ out:
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;
int key_size = OMEMO_AESGCM_KEY_LENGTH;
int nonce_size = OMEMO_AESGCM_NONCE_LENGTH;
char* fragment = gcry_malloc_secure((nonce_size + key_size) * 2 + 1);

View File

@@ -40,9 +40,6 @@
#define AES128_GCM_IV_LENGTH 12
#define AES128_GCM_TAG_LENGTH 16
#define AES256_GCM_KEY_LENGTH 32
#define AES256_GCM_NONCE_LENGTH 12
int omemo_crypto_init(void);
/**
* Callback for a secure random number generator.

View File

@@ -62,6 +62,9 @@
#include "xmpp/roster_list.h"
#include "xmpp/xmpp.h"
#define AESGCM_URL_NONCE_LEN (2 * OMEMO_AESGCM_NONCE_LENGTH)
#define AESGCM_URL_KEY_LEN (2 * OMEMO_AESGCM_KEY_LENGTH)
static gboolean loaded;
static void _generate_pre_keys(int count);
@@ -1664,12 +1667,12 @@ char*
omemo_encrypt_file(FILE* in, FILE* out, off_t file_size, int* gcry_res)
{
unsigned char* key = gcry_random_bytes_secure(
AES256_GCM_KEY_LENGTH,
OMEMO_AESGCM_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);
unsigned char nonce[OMEMO_AESGCM_NONCE_LENGTH];
gcry_create_nonce(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);
@@ -1684,7 +1687,96 @@ omemo_encrypt_file(FILE* in, FILE* out, off_t file_size, int* gcry_res)
return fragment;
}
//int omemo_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
_bytes_from_hex(const char* hex, size_t hex_size,
unsigned char* bytes, size_t bytes_size)
{
const unsigned char ht[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 01234567
0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 89:;<=>?
0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // @ABCDEFG
};
const size_t ht_size = sizeof(ht);
unsigned char b0;
unsigned char b1;
memset(bytes, 0, bytes_size);
for (int i = 0; (i < hex_size) && (i / 2 < bytes_size); i += 2) {
b0 = ((unsigned char)hex[i + 0] & 0x1f) ^ 0x10;
b1 = ((unsigned char)hex[i + 1] & 0x1f) ^ 0x10;
if (b0 <= ht_size && b1 <= ht_size) {
bytes[i / 2] = (unsigned char)(ht[b0] << 4) | ht[b1];
}
}
}
int
omemo_decrypt_file(FILE* in, FILE* out, off_t file_size, const char* fragment)
{
char nonce_hex[AESGCM_URL_NONCE_LEN];
char key_hex[AESGCM_URL_KEY_LEN];
const int nonce_pos = 0;
const int key_pos = AESGCM_URL_NONCE_LEN;
memcpy(nonce_hex, &(fragment[nonce_pos]), AESGCM_URL_NONCE_LEN);
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);
_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);
int crypt_res = aes256gcm_crypt_file(in, out, file_size, key, nonce, false);
gcry_free(key);
return crypt_res;
}
int
omemo_parse_aesgcm_url(const char* aesgcm_url,
char** https_url,
char** fragment)
{
CURLUcode ret;
CURLU* url = curl_url();
// Required to allow for the "aesgcm://" scheme that OMEMO Media Sharing
// uses.
unsigned int curl_flags = CURLU_NON_SUPPORT_SCHEME;
ret = curl_url_set(url, CURLUPART_URL, aesgcm_url, curl_flags);
if (ret) {
goto out;
}
ret = curl_url_get(url, CURLUPART_FRAGMENT, fragment, curl_flags);
if (ret) {
goto out;
}
if (strlen(*fragment) != AESGCM_URL_NONCE_LEN + AESGCM_URL_KEY_LEN) {
goto out;
}
ret = curl_url_set(url, CURLUPART_SCHEME, "https", curl_flags);
if (ret) {
goto out;
}
ret = curl_url_get(url, CURLUPART_URL, https_url, curl_flags);
if (ret) {
goto out;
}
out:
curl_url_cleanup(url);
return ret;
}

View File

@@ -40,7 +40,9 @@
#define OMEMO_ERR_UNSUPPORTED_CRYPTO -10000
#define OMEMO_ERR_GCRYPT -20000
#define OMEMO_AESGCM_URL_SCHEME "aesgcm"
#define OMEMO_AESGCM_NONCE_LENGTH 12
#define OMEMO_AESGCM_KEY_LENGTH 32
#define OMEMO_AESGCM_URL_SCHEME "aesgcm"
typedef enum {
PROF_OMEMOPOLICY_MANUAL,
@@ -99,4 +101,6 @@ char* omemo_on_message_send(ProfWin* win, const char* const message, gboolean re
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);
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);