int secure_decrypt_data_not_decrypted (const char *passphrase) { char **keys, *buffer, *decrypted; const char *value; int num_ok, num_keys, i, length_buffer, length_decrypted, rc; /* we need a passphrase to decrypt data! */ if (!passphrase || !passphrase[0]) return 0; num_ok = 0; keys = string_split (hashtable_get_string (secure_hashtable_data_encrypted, "keys"), ",", 0, 0, &num_keys); if (keys) { for (i = 0; i < num_keys; i++) { value = hashtable_get (secure_hashtable_data_encrypted, keys[i]); if (value && value[0]) { buffer = malloc (strlen (value) + 1); if (buffer) { length_buffer = string_decode_base16 (value, buffer); decrypted = NULL; length_decrypted = 0; rc = secure_decrypt_data (buffer, length_buffer, secure_hash_algo[CONFIG_INTEGER(secure_config_crypt_hash_algo)], secure_cipher[CONFIG_INTEGER(secure_config_crypt_cipher)], passphrase, &decrypted, &length_decrypted); if ((rc == 0) && decrypted) { hashtable_set (secure_hashtable_data, keys[i], decrypted); hashtable_remove (secure_hashtable_data_encrypted, keys[i]); num_ok++; } if (decrypted) free (decrypted); free (buffer); } } } string_free_split (keys); } return num_ok; }
TEST(String, BaseN) { char str[1024]; const char *str_abc = "abc"; const char *str_abc_base64 = "YWJj"; const char *str_base64[][2] = { { "", "" }, { "A", "QQ==" }, { "B", "Qg==" }, { "C", "Qw==" }, { "D", "RA==" }, { "abc", "YWJj" }, { "This is a test.", "VGhpcyBpcyBhIHRlc3Qu" }, { "This is a test..", "VGhpcyBpcyBhIHRlc3QuLg==" }, { "This is a test...", "VGhpcyBpcyBhIHRlc3QuLi4=" }, { "This is a test....", "VGhpcyBpcyBhIHRlc3QuLi4u" }, { "This is a long long long sentence here...", "VGhpcyBpcyBhIGxvbmcgbG9uZyBsb25nIHNlbnRlbmNlIGhlcmUuLi4=" }, { "Another example for base64", "QW5vdGhlciBleGFtcGxlIGZvciBiYXNlNjQ=" }, { "Another example for base64.", "QW5vdGhlciBleGFtcGxlIGZvciBiYXNlNjQu" }, { "Another example for base64..", "QW5vdGhlciBleGFtcGxlIGZvciBiYXNlNjQuLg==" }, { "Another example for base64...", "QW5vdGhlciBleGFtcGxlIGZvciBiYXNlNjQuLi4=" }, { NULL, NULL } }; int i, length; /* string_encode_base16 */ string_encode_base16 (NULL, 0, NULL); string_encode_base16 (NULL, 0, str); string_encode_base16 ("", 0, NULL); str[0] = 0xAA; string_encode_base16 ("", -1, str); BYTES_EQUAL(0x0, str[0]); str[0] = 0xAA; string_encode_base16 ("", 0, str); BYTES_EQUAL(0x0, str[0]); string_encode_base16 ("abc", 3, str); STRCMP_EQUAL("616263", str); /* string_decode_base16 */ LONGS_EQUAL(0, string_decode_base16 (NULL, NULL)); LONGS_EQUAL(0, string_decode_base16 (NULL, str)); LONGS_EQUAL(0, string_decode_base16 ("", NULL)); LONGS_EQUAL(0, string_decode_base16 ("", str)); LONGS_EQUAL(3, string_decode_base16 ("616263", str)); STRCMP_EQUAL("abc", str); /* string_encode_base64 */ string_encode_base64 (NULL, 0, NULL); string_encode_base64 (NULL, 0, str); string_encode_base64 ("", 0, NULL); str[0] = 0xAA; string_encode_base64 ("", -1, str); BYTES_EQUAL(0x0, str[0]); str[0] = 0xAA; string_encode_base64 ("", 0, str); BYTES_EQUAL(0x0, str[0]); for (i = 0; str_base64[i][0]; i++) { string_encode_base64 (str_base64[i][0], strlen (str_base64[i][0]), str); STRCMP_EQUAL(str_base64[i][1], str); } /* string_decode_base64 */ LONGS_EQUAL(0, string_decode_base64 (NULL, NULL)); LONGS_EQUAL(0, string_decode_base64 (NULL, str)); LONGS_EQUAL(0, string_decode_base64 ("", NULL)); LONGS_EQUAL(0, string_decode_base64 ("", str)); for (i = 0; str_base64[i][0]; i++) { length = string_decode_base64 (str_base64[i][1], str); STRCMP_EQUAL(str_base64[i][0], str); LONGS_EQUAL(strlen (str_base64[i][0]), length); } }
int secure_data_read_cb (void *data, struct t_config_file *config_file, struct t_config_section *section, const char *option_name, const char *value) { char *buffer, *decrypted, str_error[1024]; int length_buffer, length_decrypted, rc; /* make C compiler happy */ (void) data; (void) config_file; (void) section; if (!option_name || !value || !value[0]) { return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; } /* special line indicating if a passphrase must be used to decrypt data */ if (strcmp (option_name, SECURE_DATA_PASSPHRASE_FLAG) == 0) { secure_data_encrypted = config_file_string_to_boolean (value); if (secure_data_encrypted && !secure_passphrase && !gui_init_ok) { /* if a passphrase file is set, use it */ if (CONFIG_STRING(secure_config_crypt_passphrase_file)[0]) secure_passphrase = secure_get_passphrase_from_file (CONFIG_STRING(secure_config_crypt_passphrase_file)); /* ask passphrase to the user (if no file, or file not found) */ if (!secure_passphrase) secure_get_passphrase_from_user (""); } return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; } if (!secure_data_encrypted) { /* clear data: just store value in hashtable */ hashtable_set (secure_hashtable_data, option_name, value); return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; } /* check that passphrase is set */ if (!secure_passphrase) { gui_chat_printf (NULL, _("%sPassphrase is not set, unable to decrypt data \"%s\""), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], option_name); hashtable_set (secure_hashtable_data_encrypted, option_name, value); return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; } /* decrypt data */ buffer = malloc (strlen (value) + 1); if (!buffer) return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; length_buffer = string_decode_base16 (value, buffer); while (1) { decrypted = NULL; length_decrypted = 0; rc = secure_decrypt_data (buffer, length_buffer, secure_hash_algo[CONFIG_INTEGER(secure_config_crypt_hash_algo)], secure_cipher[CONFIG_INTEGER(secure_config_crypt_cipher)], secure_passphrase, &decrypted, &length_decrypted); if (rc == 0) { if (decrypted) { hashtable_set (secure_hashtable_data, option_name, decrypted); free (decrypted); break; } } else { if (decrypted) free (decrypted); if (gui_init_ok) { gui_chat_printf (NULL, _("%sWrong passphrase, unable to decrypt data " "\"%s\""), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], option_name); break; } snprintf (str_error, sizeof (str_error), _("*** Wrong passphrase (decrypt error: %s) ***"), secure_decrypt_error[(rc * -1) - 1]); secure_get_passphrase_from_user (str_error); if (!secure_passphrase) { gui_chat_printf (NULL, _("%sPassphrase is not set, unable to decrypt " "data \"%s\""), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], option_name); hashtable_set (secure_hashtable_data_encrypted, option_name, value); break; } } } free (buffer); return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; }