summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGluzskiy Alexandr <sss@sss.chaoslab.ru>2017-02-17 07:21:29 +0300
committerGluzskiy Alexandr <sss@sss.chaoslab.ru>2017-02-17 07:25:16 +0300
commitcdf676fe0cf3bfef30312aa057d1450993a51101 (patch)
tree00e05e58c5c51a29b3814815b39dc7aae22bb5ec
parenta73b940fda6f92db9543039b6219ed9f80db3c4e (diff)
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
-rwxr-xr-xprotocols/JabberG/jabber.vcxproj17
-rwxr-xr-xprotocols/JabberG/src/jabber_omemo.cpp284
2 files changed, 300 insertions, 1 deletions
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 @@
<ClCompile>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\libs\libaxolotl\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
+ <Link>
+ <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">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)</AdditionalDependencies>
+ </Link>
+ <Link>
+ <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">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)</AdditionalDependencies>
+ </Link>
+ <Link>
+ <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">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)</AdditionalDependencies>
+ </Link>
+ <Link>
+ <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">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)</AdditionalDependencies>
+ </Link>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="..\..\libs\libaxolotl\libaxolotl.vcxproj">
<Project>{620e0be7-3763-4f35-9dbd-4770104e269c}</Project>
</ProjectReference>
+ <ProjectReference Include="..\..\plugins\OpenSSL\OpenSSL.vcxproj">
+ <Project>{6C0C35E7-6522-403C-BB60-9805CDB9E52F}</Project>
+ </ProjectReference>
<ProjectReference Include="..\..\libs\zlib\zlib.vcxproj">
<Project>{e2a369cd-eda3-414f-8ad0-e732cd7ee68c}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
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 <signal_protocol.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/rand.h>
+#include <openssl/sha.h>
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);