diff options
author | Bakasura <bakasura@protonmail.ch> | 2020-07-13 18:27:27 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-13 16:27:27 -0700 |
commit | c5a798beec0f24f6828cd3c43bbefd1e18a9d33a (patch) | |
tree | 3d79de60cbcaf71562bf93c8b59db926eb020671 /plugins/fishlim/tests | |
parent | 2f376953f3fd7d358aa25bf29c01d70a57d40e0c (diff) |
FiSHLiM: Support for CBC mode + more commands (#2347)
Diffstat (limited to 'plugins/fishlim/tests')
-rw-r--r-- | plugins/fishlim/tests/fake/keystore.c | 47 | ||||
-rw-r--r-- | plugins/fishlim/tests/meson.build | 17 | ||||
-rw-r--r-- | plugins/fishlim/tests/old_version/fish.c | 194 | ||||
-rw-r--r-- | plugins/fishlim/tests/old_version/fish.h | 39 | ||||
-rw-r--r-- | plugins/fishlim/tests/old_version/meson.build | 4 | ||||
-rw-r--r-- | plugins/fishlim/tests/tests.c | 248 |
6 files changed, 549 insertions, 0 deletions
diff --git a/plugins/fishlim/tests/fake/keystore.c b/plugins/fishlim/tests/fake/keystore.c new file mode 100644 index 00000000..855b3451 --- /dev/null +++ b/plugins/fishlim/tests/fake/keystore.c @@ -0,0 +1,47 @@ +/* + + Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#include "../../fish.h" + + +/** + * Extracts a key from the key store file. + */ +char *keystore_get_key(const char *nick, enum fish_mode *mode) { + return NULL; +} + +/** + * Sets a key in the key store file. + */ +gboolean keystore_store_key(const char *nick, const char *key, enum fish_mode mode) { + return NULL; +} + +/** + * Deletes a nick from the key store. + */ +gboolean keystore_delete_nick(const char *nick) { + return NULL; +} diff --git a/plugins/fishlim/tests/meson.build b/plugins/fishlim/tests/meson.build new file mode 100644 index 00000000..3b75018e --- /dev/null +++ b/plugins/fishlim/tests/meson.build @@ -0,0 +1,17 @@ +subdir('old_version') + +fishlim_test_sources = [ + 'tests.c', + 'fake/keystore.c', + '../fish.c', + '../utils.c', +] + +fishlim_tests = executable('fishlim_tests', fishlim_test_sources, + dependencies: [libgio_dep, libssl_dep], + link_with : fishlim_old_lib +) + +test('Fishlim Tests', fishlim_tests, + timeout: 90 +) diff --git a/plugins/fishlim/tests/old_version/fish.c b/plugins/fishlim/tests/old_version/fish.c new file mode 100644 index 00000000..ff0b8fea --- /dev/null +++ b/plugins/fishlim/tests/old_version/fish.c @@ -0,0 +1,194 @@ +/* + + Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#ifdef __APPLE__ +#define __AVAILABILITYMACROS__ +#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER +#endif + +#include <stdlib.h> +#include <string.h> +#include <openssl/blowfish.h> + +#include "fish.h" + +#define IB 64 +static const char fish_base64[64] = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static const signed char fish_unbase64[256] = { + IB,IB,IB,IB,IB,IB,IB,IB, IB,IB,IB,IB,IB,IB,IB,IB, + IB,IB,IB,IB,IB,IB,IB,IB, IB,IB,IB,IB,IB,IB,IB,IB, +/* ! " # $ % & ' ( ) * + , - . / */ + IB,IB,IB,IB,IB,IB,IB,IB, IB,IB,IB,IB,IB,IB, 0, 1, +/* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ + 2, 3, 4, 5, 6, 7, 8, 9, 10,11,IB,IB,IB,IB,IB,IB, +/* @ A B C D E F G H I J K L M N O */ + IB,38,39,40,41,42,43,44, 45,46,47,48,49,50,51,52, +/* P Q R S T U V W X Y Z [ \ ] ^ _*/ + 53,54,55,56,57,58,59,60, 61,62,63,IB,IB,IB,IB,IB, +/* ` a b c d e f g h i j k l m n o */ + IB,12,13,14,15,16,17,18, 19,20,21,22,23,24,25,26, +/* p q r s t u v w x y z { | } ~ <del> */ + 27,28,29,30,31,32,33,34, 35,36,37,IB,IB,IB,IB,IB, +}; + +#define GET_BYTES(dest, source) do { \ + *((dest)++) = ((source) >> 24) & 0xFF; \ + *((dest)++) = ((source) >> 16) & 0xFF; \ + *((dest)++) = ((source) >> 8) & 0xFF; \ + *((dest)++) = (source) & 0xFF; \ +} while (0); + + +char *__old_fish_encrypt(const char *key, size_t keylen, const char *message) { + BF_KEY bfkey; + size_t messagelen; + size_t i; + int j; + char *encrypted; + char *end; + unsigned char bit; + unsigned char word; + unsigned char d; + BF_set_key(&bfkey, keylen, (const unsigned char*)key); + + messagelen = strlen(message); + if (messagelen == 0) return NULL; + encrypted = g_malloc(((messagelen - 1) / 8) * 12 + 12 + 1); /* each 8-byte block becomes 12 bytes */ + end = encrypted; + + while (*message) { + /* Read 8 bytes (a Blowfish block) */ + BF_LONG binary[2] = { 0, 0 }; + unsigned char c; + for (i = 0; i < 8; i++) { + c = message[i]; + binary[i >> 2] |= c << 8*(3 - (i&3)); + if (c == '\0') break; + } + message += 8; + + /* Encrypt block */ + BF_encrypt(binary, &bfkey); + + /* Emit FiSH-BASE64 */ + bit = 0; + word = 1; + for (j = 0; j < 12; j++) { + d = fish_base64[(binary[word] >> bit) & 63]; + *(end++) = d; + bit += 6; + if (j == 5) { + bit = 0; + word = 0; + } + } + + /* Stop if a null terminator was found */ + if (c == '\0') break; + } + *end = '\0'; + return encrypted; +} + + +char *__old_fish_decrypt(const char *key, size_t keylen, const char *data) { + BF_KEY bfkey; + size_t i; + char *decrypted; + char *end; + unsigned char bit; + unsigned char word; + unsigned char d; + BF_set_key(&bfkey, keylen, (const unsigned char*)key); + + decrypted = g_malloc(strlen(data) + 1); + end = decrypted; + + while (*data) { + /* Convert from FiSH-BASE64 */ + BF_LONG binary[2] = { 0, 0 }; + bit = 0; + word = 1; + for (i = 0; i < 12; i++) { + d = fish_unbase64[(const unsigned char)*(data++)]; + if (d == IB) goto decrypt_end; + binary[word] |= (unsigned long)d << bit; + bit += 6; + if (i == 5) { + bit = 0; + word = 0; + } + } + + /* Decrypt block */ + BF_decrypt(binary, &bfkey); + + /* Copy to buffer */ + GET_BYTES(end, binary[0]); + GET_BYTES(end, binary[1]); + } + + decrypt_end: + *end = '\0'; + return decrypted; +} + +/** + * Encrypts a message (see __old_fish_decrypt). The key is searched for in the + * key store. + */ +char *__old_fish_encrypt_for_nick(const char *nick, const char *data) { + char *key; + char *encrypted; + + /* Look for key */ + /*key = keystore_get_key(nick);*/ + if (!key) return NULL; + + /* Encrypt */ + encrypted = __old_fish_encrypt(key, strlen(key), data); + + g_free(key); + return encrypted; +} + +/** + * Decrypts a message (see __old_fish_decrypt). The key is searched for in the + * key store. + */ +char *__old_fish_decrypt_from_nick(const char *nick, const char *data) { + char *key; + char *decrypted; + /* Look for key */ + /*key = keystore_get_key(nick);*/ + if (!key) return NULL; + + /* Decrypt */ + decrypted = __old_fish_decrypt(key, strlen(key), data); + + g_free(key); + return decrypted; +} + + diff --git a/plugins/fishlim/tests/old_version/fish.h b/plugins/fishlim/tests/old_version/fish.h new file mode 100644 index 00000000..b4c66572 --- /dev/null +++ b/plugins/fishlim/tests/old_version/fish.h @@ -0,0 +1,39 @@ +/* + + Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#ifndef FISH_OLD_H +#define FISH_OLD_H + +#include <stddef.h> + +#include <glib.h> + +char *__old_fish_encrypt(const char *key, size_t keylen, const char *message); +char *__old_fish_decrypt(const char *key, size_t keylen, const char *data); +char *__old_fish_encrypt_for_nick(const char *nick, const char *data); +char *__old_fish_decrypt_from_nick(const char *nick, const char *data); + +#endif + + diff --git a/plugins/fishlim/tests/old_version/meson.build b/plugins/fishlim/tests/old_version/meson.build new file mode 100644 index 00000000..54647d71 --- /dev/null +++ b/plugins/fishlim/tests/old_version/meson.build @@ -0,0 +1,4 @@ +fishlim_old_lib = shared_library('fishlim_old_lib', + ['fish.c'], + dependencies: [libgio_dep, libssl_dep], +) diff --git a/plugins/fishlim/tests/tests.c b/plugins/fishlim/tests/tests.c new file mode 100644 index 00000000..e34532bf --- /dev/null +++ b/plugins/fishlim/tests/tests.c @@ -0,0 +1,248 @@ +/* + + Copyright (c) 2020 <bakasura@protonmail.ch> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#ifndef PLUGIN_HEXCHAT_FISHLIM_TEST_H +#define PLUGIN_HEXCHAT_FISHLIM_TEST_H + +// Libs +#include <stdio.h> +#include <glib.h> +// Project Libs +#include "../fish.h" +#include "../utils.h" +#include "old_version/fish.h" + +/** + * Auxiliary function: Generate a random string + * @param out Preallocated string to fill + * @param len Size of bytes to fill + */ +void random_string(char *out, size_t len) { + GRand *rand = NULL; + int i = 0; + + rand = g_rand_new(); + for (i = 0; i < len; ++i) { + out[i] = g_rand_int_range(rand, 1, 256); + } + + out[len] = 0; + + g_rand_free(rand); +} + + +/** + * Check encrypt and decrypt in ECB mode and compare with old implementation + */ +void __ecb() { + char *bo64 = NULL, *b64 = NULL; + char *deo = NULL, *de = NULL; + int key_len, message_len = 0; + char key[57]; + char message[1000]; + + /* Generate key 32–448 bits (Yes, I start with 8 bits) */ + for (key_len = 1; key_len < 57; ++key_len) { + + random_string(key, key_len); + + for (message_len = 1; message_len < 1000; ++message_len) { + random_string(message, message_len); + + /* Encrypt */ + bo64 = __old_fish_encrypt(key, key_len, message); + g_assert_nonnull(bo64); + b64 = fish_encrypt(key, key_len, message, message_len, FISH_ECB_MODE); + g_assert_nonnull(b64); + g_assert_cmpuint(g_strcmp0(b64, bo64), == , 0); + + /* Decrypt */ + /* Linear */ + deo = __old_fish_decrypt(key, key_len, bo64); + de = fish_decrypt_str(key, key_len, b64, FISH_ECB_MODE); + g_assert_nonnull(deo); + g_assert_nonnull(de); + g_assert_cmpuint(g_strcmp0(de, message), == , 0); + g_assert_cmpuint(g_strcmp0(deo, message), == , 0); + g_assert_cmpuint(g_strcmp0(de, deo), == , 0); + g_free(deo); + g_free(de); + /* Mixed */ + deo = __old_fish_decrypt(key, key_len, b64); + de = fish_decrypt_str(key, key_len, bo64, FISH_ECB_MODE); + g_assert_nonnull(deo); + g_assert_nonnull(de); + g_assert_cmpuint(g_strcmp0(de, message), == , 0); + g_assert_cmpuint(g_strcmp0(deo, message), == , 0); + g_assert_cmpuint(g_strcmp0(de, deo), == , 0); + g_free(deo); + g_free(de); + + /* Free */ + g_free(bo64); + g_free(b64); + } + } +} + +/** + * Check encrypt and decrypt in CBC mode + */ +void __cbc() { + char *b64 = NULL; + char *de = NULL; + int key_len, message_len = 0; + char key[57]; + char message[1000]; + + /* Generate key 32–448 bits (Yes, I start with 8 bits) */ + for (key_len = 1; key_len < 57; ++key_len) { + + random_string(key, key_len); + + for (message_len = 1; message_len < 1000; ++message_len) { + random_string(message, message_len); + + /* Encrypt */ + b64 = fish_encrypt(key, key_len, message, message_len, FISH_CBC_MODE); + g_assert_nonnull(b64); + + /* Decrypt */ + /* Linear */ + de = fish_decrypt_str(key, key_len, b64, FISH_CBC_MODE); + g_assert_nonnull(de); + g_assert_cmpuint(g_strcmp0(de, message), == , 0); + g_free(de); + + /* Free */ + g_free(b64); + } + } +} + +/** + * Check the calculation of final length from an encoded string in Base64 + */ +void __base64_len() { + char *b64 = NULL; + int i, message_len = 0; + char message[1000]; + + for (i = 0; i < 10; ++i) { + + for (message_len = 1; message_len < 1000; ++message_len) { + random_string(message, message_len); + b64 = g_base64_encode((const unsigned char *) message, message_len); + g_assert_nonnull(b64); + g_assert_cmpuint(strlen(b64), == , base64_len(message_len)); + g_free(b64); + } + } +} + +/** + * Check the calculation of final length from an encoded string in BlowcryptBase64 + */ +void __base64_fish_len() { + char *b64 = NULL; + int i, message_len = 0; + char message[1000]; + + for (i = 0; i < 10; ++i) { + + for (message_len = 1; message_len < 1000; ++message_len) { + random_string(message, message_len); + b64 = fish_base64_encode(message, message_len); + g_assert_nonnull(b64); + g_assert_cmpuint(strlen(b64), == , base64_fish_len(message_len)); + g_free(b64); + } + } +} + + +/** + * Check the calculation of final length from an encrypted string in ECB mode + */ +void __base64_ecb_len() { + char *b64 = NULL; + int key_len, message_len = 0; + char key[57]; + char message[1000]; + + /* Generate key 32–448 bits (Yes, I start with 8 bits) */ + for (key_len = 1; key_len < 57; ++key_len) { + + random_string(key, key_len); + + for (message_len = 1; message_len < 1000; ++message_len) { + random_string(message, message_len); + b64 = fish_encrypt(key, key_len, message, message_len, FISH_ECB_MODE); + g_assert_nonnull(b64); + g_assert_cmpuint(strlen(b64), == , ecb_len(message_len)); + g_free(b64); + } + } +} + +/** + * Check the calculation of final length from an encrypted string in CBC mode + */ +void __base64_cbc_len() { + char *b64 = NULL; + int key_len, message_len = 0; + char key[57]; + char message[1000]; + + /* Generate key 32–448 bits (Yes, I start with 8 bits) */ + for (key_len = 1; key_len < 57; ++key_len) { + + random_string(key, key_len); + + for (message_len = 1; message_len < 1000; ++message_len) { + random_string(message, message_len); + b64 = fish_encrypt(key, key_len, message, message_len, FISH_CBC_MODE); + g_assert_nonnull(b64); + g_assert_cmpuint(strlen(b64), == , cbc_len(message_len)); + g_free(b64); + } + } +} + +int main(int argc, char *argv[]) { + + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/fishlim/__ecb", __ecb); + g_test_add_func("/fishlim/__cbc", __ecb); + g_test_add_func("/fishlim/__base64_len", __base64_len); + g_test_add_func("/fishlim/__base64_fish_len", __base64_fish_len); + g_test_add_func("/fishlim/__base64_ecb_len", __base64_ecb_len); + g_test_add_func("/fishlim/__base64_cbc_len", __base64_cbc_len); + + return g_test_run(); +} + +#endif //PLUGIN_HEXCHAT_FISHLIM_TEST_H \ No newline at end of file |