From cdf676fe0cf3bfef30312aa057d1450993a51101 Mon Sep 17 00:00:00 2001 From: Gluzskiy Alexandr Date: Fri, 17 Feb 2017 07:21:29 +0300 Subject: protocols: jaber: omemo: used openssl based aes encryption and digest_sha512 code from https://github.com/WhisperSystems/libsignal-protocol-c/blob/master/tests/test_common.c --- protocols/JabberG/jabber.vcxproj | 17 +- protocols/JabberG/src/jabber_omemo.cpp | 284 +++++++++++++++++++++++++++++++++ 2 files changed, 300 insertions(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/JabberG/jabber.vcxproj b/protocols/JabberG/jabber.vcxproj index 6481f768a5..92d648a7d1 100755 --- a/protocols/JabberG/jabber.vcxproj +++ b/protocols/JabberG/jabber.vcxproj @@ -29,14 +29,29 @@ $(ProjectDir)..\..\libs\libaxolotl\src;%(AdditionalIncludeDirectories) + + winmm.lib;Wtsapi32.lib;netapi32.lib;pdh.lib;shlwapi.lib;Strmiids.lib;gdiplus.lib;dbghelp.lib;Setupapi.lib;msimg32.lib;comctl32.lib;ws2_32.lib;UxTheme.lib;Iphlpapi.lib;libeay32.lib;ssleay32.lib;%(AdditionalDependencies) + + + winmm.lib;Wtsapi32.lib;netapi32.lib;pdh.lib;shlwapi.lib;Strmiids.lib;gdiplus.lib;dbghelp.lib;Setupapi.lib;msimg32.lib;comctl32.lib;ws2_32.lib;UxTheme.lib;Iphlpapi.lib;libeay32.lib;ssleay32.lib;%(AdditionalDependencies) + + + winmm.lib;Wtsapi32.lib;netapi32.lib;pdh.lib;shlwapi.lib;Strmiids.lib;gdiplus.lib;dbghelp.lib;Setupapi.lib;msimg32.lib;comctl32.lib;ws2_32.lib;UxTheme.lib;Iphlpapi.lib;libeay32.lib;ssleay32.lib;%(AdditionalDependencies) + + + winmm.lib;Wtsapi32.lib;netapi32.lib;pdh.lib;shlwapi.lib;Strmiids.lib;gdiplus.lib;dbghelp.lib;Setupapi.lib;msimg32.lib;comctl32.lib;ws2_32.lib;UxTheme.lib;Iphlpapi.lib;libeay32.lib;ssleay32.lib;%(AdditionalDependencies) + {620e0be7-3763-4f35-9dbd-4770104e269c} + + + {6C0C35E7-6522-403C-BB60-9805CDB9E52F} {e2a369cd-eda3-414f-8ad0-e732cd7ee68c} false - \ No newline at end of file + diff --git a/protocols/JabberG/src/jabber_omemo.cpp b/protocols/JabberG/src/jabber_omemo.cpp index 825b98faf8..9af0a2bb39 100755 --- a/protocols/JabberG/src/jabber_omemo.cpp +++ b/protocols/JabberG/src/jabber_omemo.cpp @@ -25,6 +25,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "stdafx.h" #include +#include +#include +#include +#include namespace omemo { @@ -72,6 +76,279 @@ namespace omemo { mir_free(ctx->data); } + int sha512_digest_init_func(void **digest_context, void * /*user_data*/) + { + + int result = 0; + EVP_MD_CTX *ctx; + + ctx = EVP_MD_CTX_create(); + if (!ctx) { + result = SG_ERR_NOMEM; + goto complete; + } + + result = EVP_DigestInit_ex(ctx, EVP_sha512(), 0); + if (result == 1) { + result = SG_SUCCESS; + } + else { + result = SG_ERR_UNKNOWN; + } + + complete: + if (result < 0) { + if (ctx) { + EVP_MD_CTX_destroy(ctx); + } + } + else { + *digest_context = ctx; + } + return result; + } + + int sha512_digest_update_func(void *digest_context, const uint8_t *data, size_t data_len, void * /*user_data*/) + { + EVP_MD_CTX *ctx = (EVP_MD_CTX*)digest_context; + + int result = EVP_DigestUpdate(ctx, data, data_len); + + return (result == 1) ? SG_SUCCESS : SG_ERR_UNKNOWN; + } + + int sha512_digest_final_func(void *digest_context, signal_buffer **output, void * /*user_data*/) + { + int result = 0; + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int len = 0; + EVP_MD_CTX *ctx = (EVP_MD_CTX*)digest_context; + + result = EVP_DigestFinal_ex(ctx, md, &len); + if (result == 1) { + result = SG_SUCCESS; + } + else { + result = SG_ERR_UNKNOWN; + goto complete; + } + + result = EVP_DigestInit_ex(ctx, EVP_sha512(), 0); + if (result == 1) { + result = SG_SUCCESS; + } + else { + result = SG_ERR_UNKNOWN; + goto complete; + } + + signal_buffer *output_buffer = signal_buffer_create(md, len); + if (!output_buffer) { + result = SG_ERR_NOMEM; + goto complete; + } + + *output = output_buffer; + + complete: + return result; + } + + void sha512_digest_cleanup_func(void *digest_context, void * /*user_data*/) + { + EVP_MD_CTX *ctx = (EVP_MD_CTX *)digest_context; + EVP_MD_CTX_destroy(ctx); + } + + const EVP_CIPHER *aes_cipher(int cipher, size_t key_len) + { + if (cipher == SG_CIPHER_AES_CBC_PKCS5) { + if (key_len == 16) { + return EVP_aes_128_cbc(); + } + else if (key_len == 24) { + return EVP_aes_192_cbc(); + } + else if (key_len == 32) { + return EVP_aes_256_cbc(); + } + } + else if (cipher == SG_CIPHER_AES_CTR_NOPADDING) { + if (key_len == 16) { + return EVP_aes_128_ctr(); + } + else if (key_len == 24) { + return EVP_aes_192_ctr(); + } + else if (key_len == 32) { + return EVP_aes_256_ctr(); + } + } + return 0; + } + + int 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*/) + { + //TODO: use netlib for log + int result = 0; + uint8_t *out_buf = 0; + + const EVP_CIPHER *evp_cipher = aes_cipher(cipher, key_len); + if (!evp_cipher) { + //fprintf(stderr, "invalid AES mode or key size: %zu\n", key_len); + return SG_ERR_UNKNOWN; + } + + if (iv_len != 16) { + //fprintf(stderr, "invalid AES IV size: %zu\n", iv_len); + return SG_ERR_UNKNOWN; + } + + if (plaintext_len > INT_MAX - EVP_CIPHER_block_size(evp_cipher)) { + //fprintf(stderr, "invalid plaintext length: %zu\n", plaintext_len); + return SG_ERR_UNKNOWN; + } + + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + + result = EVP_EncryptInit_ex(&ctx, evp_cipher, 0, key, iv); + if (!result) { + //fprintf(stderr, "cannot initialize cipher\n"); + result = SG_ERR_UNKNOWN; + goto complete; + } + + if (cipher == SG_CIPHER_AES_CTR_NOPADDING) { + result = EVP_CIPHER_CTX_set_padding(&ctx, 0); + if (!result) { + //fprintf(stderr, "cannot set padding\n"); + result = SG_ERR_UNKNOWN; + goto complete; + } + } + + out_buf = (uint8_t*)mir_alloc(sizeof(uint8_t) * (plaintext_len + EVP_CIPHER_block_size(evp_cipher))); + if (!out_buf) { + //fprintf(stderr, "cannot allocate output buffer\n"); + result = SG_ERR_NOMEM; + goto complete; + } + + int out_len = 0; + result = EVP_EncryptUpdate(&ctx, + out_buf, &out_len, plaintext, (int)plaintext_len); + if (!result) { + //fprintf(stderr, "cannot encrypt plaintext\n"); + result = SG_ERR_UNKNOWN; + goto complete; + } + + int final_len = 0; + result = EVP_EncryptFinal_ex(&ctx, out_buf + out_len, &final_len); + if (!result) { + //fprintf(stderr, "cannot finish encrypting plaintext\n"); + result = SG_ERR_UNKNOWN; + goto complete; + } + + *output = signal_buffer_create(out_buf, out_len + final_len); + + complete: + EVP_CIPHER_CTX_cleanup(&ctx); + if (out_buf) { + mir_free(out_buf); + } + return result; + } + + int 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*/) + { + //TODO: use netlib for log + int result = 0; + uint8_t *out_buf = 0; + + const EVP_CIPHER *evp_cipher = aes_cipher(cipher, key_len); + if (!evp_cipher) { + //fprintf(stderr, "invalid AES mode or key size: %zu\n", key_len); + return SG_ERR_INVAL; + } + + if (iv_len != 16) { + //fprintf(stderr, "invalid AES IV size: %zu\n", iv_len); + return SG_ERR_INVAL; + } + + if (ciphertext_len > INT_MAX - EVP_CIPHER_block_size(evp_cipher)) { + //fprintf(stderr, "invalid ciphertext length: %zu\n", ciphertext_len); + return SG_ERR_UNKNOWN; + } + + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + + result = EVP_DecryptInit_ex(&ctx, evp_cipher, 0, key, iv); + if (!result) { + ///fprintf(stderr, "cannot initialize cipher\n"); + result = SG_ERR_UNKNOWN; + goto complete; + } + + if (cipher == SG_CIPHER_AES_CTR_NOPADDING) { + result = EVP_CIPHER_CTX_set_padding(&ctx, 0); + if (!result) { + //fprintf(stderr, "cannot set padding\n"); + result = SG_ERR_UNKNOWN; + goto complete; + } + } + + out_buf = (uint8_t*)mir_alloc(sizeof(uint8_t) * (ciphertext_len + EVP_CIPHER_block_size(evp_cipher))); + if (!out_buf) { + //fprintf(stderr, "cannot allocate output buffer\n"); + result = SG_ERR_UNKNOWN; + goto complete; + } + + int out_len = 0; + result = EVP_DecryptUpdate(&ctx, + out_buf, &out_len, ciphertext, (int)ciphertext_len); + if (!result) { + //fprintf(stderr, "cannot decrypt ciphertext\n"); + result = SG_ERR_UNKNOWN; + goto complete; + } + + int final_len = 0; + result = EVP_DecryptFinal_ex(&ctx, out_buf + out_len, &final_len); + if (!result) { + //fprintf(stderr, "cannot finish decrypting ciphertext\n"); + result = SG_ERR_UNKNOWN; + goto complete; + } + + *output = signal_buffer_create(out_buf, out_len + final_len); + + complete: + EVP_CIPHER_CTX_cleanup(&ctx); + if (out_buf) { + free(out_buf); + } + return result; + } + + + mir_cs _signal_cs; mir_cslockfull signal_mutex(_signal_cs); @@ -96,6 +373,13 @@ namespace omemo { provider.hmac_sha256_update_func = &hmac_sha256_update_func; provider.hmac_sha256_final_func = &hmac_sha256_final_func; provider.hmac_sha256_cleanup_func = &hmac_sha256_cleanup_func; + provider.sha512_digest_init_func = &sha512_digest_init_func; + provider.sha512_digest_update_func = &sha512_digest_update_func; + provider.sha512_digest_final_func = &sha512_digest_final_func; + provider.sha512_digest_cleanup_func = &sha512_digest_cleanup_func; + provider.encrypt_func = &encrypt_func; + provider.decrypt_func = &decrypt_func; + signal_context_set_crypto_provider(global_context, &provider); signal_context_set_locking_functions(global_context, &lock, &unlock); -- cgit v1.2.3