Merge branch 'cbc'

This commit is contained in:
Pedro de Oliveira 2019-05-01 00:52:49 +01:00
commit 7e5ecc68fe
9 changed files with 345 additions and 71 deletions

11
README
View File

@ -2,8 +2,8 @@ Introduction
============
This is an encryption add-on for irssi, it's based on blowfish. It
supports private messages and channel encryption. It also includes a
secure key-exchange system.
supports private messages and channel encryption in ECB and CBC
modes. It also includes a secure key-exchange system.
Requirements
============
@ -148,7 +148,7 @@ Send a FiSHed action to the current window.
/setkey [servertag] [nick / #channel] <key>
Sets the key used to FiSH the messages for the current window or to the
specified target.
specified target. To use CBC mode, prefix the key with "cbc:".
/delkey [servertag] [nick/#channel]
@ -160,9 +160,10 @@ the specified target.
Shows the used key to FiSH the messages for the current window or to the
specified target. The key will appear in the target window.
/keyx
/keyx [-ecb] [nick]
Forces a DH key exchange in the current window.
Forces a DH key exchange in the current window or to the specified
target. The default mode is CBC, use "-ecb" to use ECB Mode.
/setinipw <password>

View File

@ -2,7 +2,7 @@
# Introduction
This is an encryption add-on for irssi, it's based on blowfish. It supports private messages and channel encryption. It also includes a secure key-exchange system.
This is an encryption add-on for irssi, it's based on blowfish. It supports private messages and channel encryption in **ECB** and **CBC** modes. It also includes a secure key-exchange system.
# Requirements
@ -161,7 +161,7 @@ Send a FiSHed action to the current window.
```
/setkey [servertag] [nick / #channel] <key>
```
Sets the key used to FiSH the messages for the current window or to the specified target.
Sets the key used to FiSH the messages for the current window or to the specified target. To use CBC mode, prefix the key with "cbc:".
```
/delkey [servertag] [nick/#channel]
@ -174,9 +174,9 @@ Unsets the key used to FiSH the messages for the current window or to the specif
Shows the used key to FiSH the messages for the current window or to the specified target. The key will appear in the target window.
```
/keyx
/keyx [-ecb] [nick]
```
Forces a DH key exchange in the current window.
Forces a DH key exchange in the current window or to the specified target. The default mode is CBC, use "-ecb" to use ECB Mode.
```
/setinipw <password>

View File

@ -1,6 +1,6 @@
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/FiSH_version.h.in ${CMAKE_CURRENT_SOURCE_DIR}/FiSH_version.h)
ADD_LIBRARY(fish MODULE base64.c blowfish.c inifile.c DH1080.c FiSH.c password.c)
ADD_LIBRARY(fish MODULE base64.c blowfish.c blowfish_cbc.c inifile.c DH1080.c FiSH.c password.c)
TARGET_LINK_LIBRARIES(fish crypto glib-2.0)
if (APPLE)

View File

@ -18,7 +18,7 @@ int getContactKey(const char *contactPtr, char *theKey)
int bRet = FALSE;
iniValue = allocateIni(contactPtr, "key", iniPath);
getIniValue(contactPtr, "key", "", iniValue.key, iniValue.iniKeySize, iniPath);
getIniValue(contactPtr, "key", "", iniValue.key, iniValue.keySize, iniPath);
// don't process, encrypted key not found in ini
if (strlen(iniValue.key) < 16) {
@ -29,11 +29,9 @@ int getContactKey(const char *contactPtr, char *theKey)
// encrypted key found
if (strncmp(iniValue.key, "+OK ", 4) == 0) {
if (theKey) {
// if it's not just a test, lets decrypt the key
decrypt_string((char *)iniKey, iniValue.key + 4, theKey,
strlen(iniValue.key + 4));
}
bRet = TRUE;
}
@ -110,8 +108,13 @@ int FiSH_encrypt(const SERVER_REC * serverRec, const char *msgPtr,
return 0;
}
strcpy(bf_dest, "+OK ");
encrypt_string(iniValue.key, msgPtr, bf_dest + 4, strlen(msgPtr));
if (iniValue.cbc == 1) {
strcpy(bf_dest, "+OK *");
encrypt_string_cbc(iniValue.key, msgPtr, bf_dest + 5, strlen(msgPtr));
} else {
strcpy(bf_dest, "+OK ");
encrypt_string(iniValue.key, msgPtr, bf_dest + 4, strlen(msgPtr));
}
freeIni(iniValue);
return 1;
@ -128,6 +131,8 @@ int FiSH_decrypt(const SERVER_REC * serverRec, char *msg_ptr,
char bf_dest[1000] = "";
char myMark[20] = "";
int msg_len, i, mark_broken_block = 0, action_found = 0;
int mode = 0;
int cbc_ret = 0;
if (IsNULLorEmpty(msg_ptr) || decrypted_msg == NULL || IsNULLorEmpty(target))
return 0;
@ -142,9 +147,19 @@ int FiSH_decrypt(const SERVER_REC * serverRec, char *msg_ptr,
else
return 0; // don't process, blowcrypt-prefix not found
// Verify base64 string
// Strip the * from the CBC mode
if (strncmp(msg_ptr, "*", 1) == 0) {
mode = 1;
msg_ptr++;
}
msg_len = strlen(msg_ptr);
if ((strspn(msg_ptr, B64) != (size_t) msg_len) || (msg_len < 12))
// Verify base64 string - only for ECB
if (mode == 0 && (strspn(msg_ptr, B64) != (size_t) msg_len))
return 0;
if (msg_len < 12)
return 0;
if (getIniSectionForContact(serverRec, target, contactName) == FALSE)
@ -163,7 +178,7 @@ int FiSH_decrypt(const SERVER_REC * serverRec, char *msg_ptr,
// block-align blowcrypt strings if truncated by IRC server (each block is 12 chars long)
// such a truncated block is destroyed and not needed anymore
if (msg_len != (msg_len / 12) * 12) {
if ((mode == 0) && (msg_len != (msg_len / 12) * 12)) {
msg_len = (msg_len / 12) * 12;
msg_ptr[msg_len] = '\0';
strncpy(myMark, settings_get_str("mark_broken_block"),
@ -174,7 +189,21 @@ int FiSH_decrypt(const SERVER_REC * serverRec, char *msg_ptr,
mark_broken_block = 1;
}
decrypt_string(iniValue.key, msg_ptr, bf_dest, msg_len);
if (iniValue.cbc == 1) {
cbc_ret = decrypt_string_cbc(iniValue.key, msg_ptr, bf_dest, msg_len);
} else {
decrypt_string(iniValue.key, msg_ptr, bf_dest, msg_len);
}
if (cbc_ret == -1) {
strncpy(myMark, settings_get_str("mark_broken_block"),
sizeof(myMark));
if (*myMark == '\0' || isNoChar(*myMark))
mark_broken_block = 0;
else
mark_broken_block = 1;
}
freeIni(iniValue);
if (*bf_dest == '\0')
@ -634,7 +663,7 @@ void cmd_helpfish(const char *arg, SERVER_REC * server, WI_ITEM_REC * item)
" /setkey [-<server tag>] [<nick | #channel>] <key>\n"
" /delkey [-<server tag>] [<nick | #channel>]\n"
" /key|showkey [-<server tag>] [<nick | #channel>]\n"
" /keyx [<nick>] (DH1080 KeyXchange)\n"
" /keyx [-ecb] [<nick>]\n"
" /setinipw <blow.ini_password>\n"
" /unsetinipw\n"
" /fishlogin\n");
@ -691,15 +720,15 @@ int recrypt_ini_file(const char *iniPath, const char *iniPath_new,
re_enc = 1;
bfKeySize = (strlen(value) * 2) * sizeof(char);
bfKey = (char *) malloc(bfKeySize);
bfKey = (char *) calloc(bfKeySize, sizeof(char));
decrypt_string(old_iniKey, value + 4, bfKey, strlen(value + 4));
newbfKeySize = (strlen(bfKey) * 2)* sizeof(char);
newbfKey = (char *) malloc(newbfKeySize);
newbfKey = (char *) calloc(newbfKeySize, sizeof(char));
encrypt_string(iniKey, bfKey, newbfKey, strlen(bfKey));
plusOkSize = (strlen(newbfKey) * 2) * sizeof(char);
plusOk = (char *) malloc(plusOkSize);
plusOk = (char *) calloc(plusOkSize, sizeof(char));
snprintf(plusOk, plusOkSize, "+OK %s", newbfKey);
setIniValue(groups[i], keys[j], plusOk, iniPath_new);
@ -740,14 +769,14 @@ void cmd_setinipw(const char *iniPW, SERVER_REC * server, WI_ITEM_REC * item)
char *new_iniKey;
old_iniKeySize = strlen(iniKey) * sizeof(char);
old_iniKey = (char *) malloc(old_iniKeySize);
old_iniKey = (char *) calloc(old_iniKeySize + 1, sizeof(char));
strcpy(old_iniKey, iniKey);
if (iniPW != NULL) {
int pw_len = strlen(iniPW);
size_t pw_len = strlen(iniPW);
new_iniKeySize = (pw_len * 2) * sizeof(char);
new_iniKey = (char *) malloc(new_iniKeySize);
new_iniKeySize = pw_len * 2 + 1;
new_iniKey = (char *) calloc(new_iniKeySize, sizeof(char));
if (pw_len < 1 || (size_t) pw_len > new_iniKeySize) {
printtext(server,
@ -790,7 +819,7 @@ void cmd_setinipw(const char *iniPW, SERVER_REC * server, WI_ITEM_REC * item)
htob64(key, B64digest, 32);
free(iniKey);
iniKey = (char *) malloc((strlen(B64digest)* 2) * sizeof(char));
iniKey = (char *) calloc(strlen(B64digest) * 2, sizeof(char));
strcpy(iniKey, B64digest); // this is used for encrypting blow.ini
@ -874,6 +903,24 @@ static void cmd_unsetinipw(const char *arg, SERVER_REC * server,
"\002FiSH:\002 Changed back to default blow.ini password, you won't have to enter it on start-up anymore!");
}
int detect_mode(const char *key)
{
char mode[4];
int BLOWFISH_ECB = 0;
int BLOWFISH_CBC = 1;
if (strlen(key) > 4) {
strncpy(mode, key, 3);
mode[3] = '\0';
if (strcmp(mode, "cbc") == 0) {
return BLOWFISH_CBC;
}
}
return BLOWFISH_ECB;
}
/**
* Sets the key for a nick / channel in a server
* @param data command
@ -886,6 +933,7 @@ void cmd_setkey(const char *data, SERVER_REC * server, WI_ITEM_REC * item)
char contactName[CONTACT_SIZE] = "";
char *encryptedKey;
int keySize;
int mode = 0;
const char *target, *key;
void *free_arg;
@ -930,9 +978,14 @@ void cmd_setkey(const char *data, SERVER_REC * server, WI_ITEM_REC * item)
}
keySize = (strlen(key) * 3) * sizeof(char);
encryptedKey = (char *) malloc(keySize);
encryptedKey = (char *) calloc(keySize, sizeof(char));
mode = detect_mode(key);
encrypt_key((char *)key, encryptedKey);
if (mode == 1) {
encrypt_key((char *)key + 4, encryptedKey);
} else {
encrypt_key((char *)key, encryptedKey);
}
if (getIniSectionForContact(server, target, contactName) == FALSE) {
bzero(encryptedKey, keySize);
@ -951,13 +1004,19 @@ void cmd_setkey(const char *data, SERVER_REC * server, WI_ITEM_REC * item)
return;
}
if (mode == 1) {
setIniValue(contactName, "cbc", "1", iniPath);
} else {
setIniValue(contactName, "cbc", "0", iniPath);
}
bzero(encryptedKey, keySize);
free(encryptedKey);
printtext(server, item != NULL ? window_item_get_target(item) : NULL,
MSGLEVEL_CRAP,
"\002FiSH:\002 Key for %s@%s successfully set!", target,
server->tag);
"\002FiSH:\002 Key for %s@%s (%s) successfully set!", target,
server->tag, mode == 1 ? "CBC" : "ECB");
cmd_params_free(free_arg);
}
@ -1054,63 +1113,101 @@ void cmd_key(const char *data, SERVER_REC * server, WI_ITEM_REC * item)
}
printtext(server, target, MSGLEVEL_CRAP,
"\002FiSH:\002 Key for %s@%s: %s", target, server->tag,
iniValue.key);
"\002FiSH:\002 Key for %s@%s: %s (%s)", target, server->tag,
iniValue.key, iniValue.cbc == 1 ? "CBC" : "ECB");
freeIni(iniValue);
}
void cmd_keyx(const char *target, SERVER_REC * server, WI_ITEM_REC * item)
void cmd_keyx(const char *data, SERVER_REC * server, WI_ITEM_REC * item)
{
GHashTable *optlist = NULL;
char *target = NULL;
void *free_arg = NULL;
int ecb = 0;
if (server == NULL) {
printtext(NULL, NULL, MSGLEVEL_CRAP,
"\002FiSH:\002 No connection to server.");
return;
goto fail;
}
if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_GETREST | PARAM_FLAG_OPTIONS,
"keyx", &optlist, &target))
goto fail;
ecb = g_hash_table_lookup(optlist, "ecb") != NULL;
if (item != NULL && IsNULLorEmpty(target))
target = (char *)window_item_get_target(item);
if (IsNULLorEmpty(target)) {
if (item != NULL)
target = window_item_get_target(item);
else {
printtext(NULL, NULL, MSGLEVEL_CRAP,
"\002FiSH:\002 Please define nick/#channel. Usage: /keyx <nick/#channel>");
return;
}
printtext(NULL, NULL, MSGLEVEL_CRAP,
"\002FiSH:\002 Please define nick/#channel. Usage: /keyx [-ecb] <nick>");
goto fail;
}
if (server_ischannel(server, target)) {
printtext(server, target, MSGLEVEL_CRAP,
"\002FiSH:\002 KeyXchange does not work for channels!");
return;
goto fail;
}
target = (char *)g_strchomp(target);
DH1080_gen(g_myPrivKey, g_myPubKey);
irc_send_cmdv((IRC_SERVER_REC *) server, "NOTICE %s :%s %s", target,
"DH1080_INIT", g_myPubKey);
irc_send_cmdv((IRC_SERVER_REC *) server, "NOTICE %s :%s%s%s", target,
DH1080_INIT, g_myPubKey, ecb == 0 ? CBC_SUFFIX : "");
printtext(server, item != NULL ? window_item_get_target(item) : NULL,
MSGLEVEL_CRAP,
"\002FiSH:\002 Sent my DH1080 public key to %s, waiting for reply ...",
target);
"\002FiSH:\002 Sent my DH1080 public key to %s@%s (%s), waiting for reply ...",
target, server->tag, ecb == 1 ? "ECB" : "CBC");
fail:
if(free_arg) {
cmd_params_free(free_arg);
}
}
void DH1080_received(SERVER_REC * server, char *msg, char *nick, char *address,
char *target)
{
int i;
char hisPubKey[300], contactName[CONTACT_SIZE] =
"", encryptedKey[KEYBUF_SIZE] = "";
int msg_len;
char hisPubKey[300];
char contactName[CONTACT_SIZE] = "";
char encryptedKey[KEYBUF_SIZE] = "";
// 0 for ECB, 1 for CBC
int mode = 0;
const unsigned int DH1080_INIT_LEN = strlen(DH1080_INIT);
const unsigned int DH1080_FINISH_LEN = strlen(DH1080_FINISH);
const unsigned int CBC_SUFFIX_LEN = strlen(CBC_SUFFIX);
if (server_ischannel(server, target) || server_ischannel(server, nick))
return; // no KeyXchange for channels...
i = strlen(msg);
if (i < 191 || i > 195)
msg_len = strlen(msg);
if (msg_len < 191 || msg_len > 199)
return;
if (strncmp(msg, "DH1080_INIT ", 12) == 0) {
strcpy(hisPubKey, msg + 12);
if (strspn(hisPubKey, B64ABC) != strlen(hisPubKey))
if (strncmp(msg, DH1080_INIT, DH1080_INIT_LEN) == 0) {
// Check for CBC at the end
if (strcmp(msg + msg_len - CBC_SUFFIX_LEN, " CBC") == 0) {
mode = 1;
}
if (mode == 0) {
strcpy(hisPubKey, msg + DH1080_INIT_LEN);
} else {
// Strip the " CBC" at the end
strncpy(hisPubKey, msg + DH1080_INIT_LEN, msg_len - DH1080_INIT_LEN - CBC_SUFFIX_LEN);
hisPubKey[msg_len - DH1080_INIT_LEN - CBC_SUFFIX_LEN] = '\0';
}
// This check only applies to ECB
if ((mode == 0) && (strspn(hisPubKey, B64ABC) != strlen(hisPubKey)))
return;
if (query_find(server, nick) == NULL) { // query window not found, lets create one
@ -1120,16 +1217,33 @@ void DH1080_received(SERVER_REC * server, char *msg, char *nick, char *address,
}
printtext(server, nick, MSGLEVEL_CRAP,
"\002FiSH:\002 Received DH1080 public key from %s, sending mine...",
nick);
"\002FiSH:\002 Received DH1080 public key from %s@%s (%s), sending mine...",
nick, server->tag, mode == 0 ? "ECB" : "CBC");
DH1080_gen(g_myPrivKey, g_myPubKey);
irc_send_cmdv((IRC_SERVER_REC *) server, "NOTICE %s :%s %s",
nick, "DH1080_FINISH", g_myPubKey);
} else if (strncmp(msg, "DH1080_FINISH ", 14) == 0)
strcpy(hisPubKey, msg + 14);
else
irc_send_cmdv((IRC_SERVER_REC *) server, "NOTICE %s :%s%s%s",
nick, DH1080_FINISH, g_myPubKey, mode == 1 ? CBC_SUFFIX : "");
} else if (strncmp(msg, DH1080_FINISH, DH1080_FINISH_LEN) == 0) {
msg_len = strlen(msg);
// Check for CBC at the end
if (strcmp(msg + msg_len - CBC_SUFFIX_LEN, CBC_SUFFIX) == 0) {
mode = 1;
}
if (mode == 0) {
strcpy(hisPubKey, msg + DH1080_FINISH_LEN);
} else {
// Strip the " CBC" at the end
strncpy(hisPubKey, msg + DH1080_FINISH_LEN, msg_len - DH1080_FINISH_LEN - CBC_SUFFIX_LEN);
hisPubKey[msg_len - DH1080_FINISH_LEN - CBC_SUFFIX_LEN] = '\0';
}
} else {
return;
}
if (DH1080_comp(g_myPrivKey, hisPubKey) == 0)
return;
@ -1148,10 +1262,17 @@ void DH1080_received(SERVER_REC * server, char *msg, char *nick, char *address,
return;
}
// Remember to use CBC mode
if ((mode == 1) && (setIniValue(contactName, "cbc", "1", iniPath) == -1)) {
printtext(server, nick, MSGLEVEL_CRAP,
"\002FiSH ERROR:\002 Unable to write to blow.ini, probably out of space or permission denied.");
return;
}
ZeroMemory(encryptedKey, KEYBUF_SIZE);
printtext(server, nick, MSGLEVEL_CRAP,
"\002FiSH:\002 Key for %s successfully set!", nick);
"\002FiSH:\002 Key for %s@%s (%s) successfully set!", nick, server->tag, mode == 0 ? "ECB" : "CBC");
}
/*
@ -1269,6 +1390,7 @@ void setup_fish()
command_bind("key", NULL, (SIGNAL_FUNC) cmd_key);
command_bind("showkey", NULL, (SIGNAL_FUNC) cmd_key);
command_bind("keyx", NULL, (SIGNAL_FUNC) cmd_keyx);
command_set_options("keyx", "-ecb");
command_bind("setinipw", NULL, (SIGNAL_FUNC) cmd_setinipw);
command_bind("unsetinipw", NULL, (SIGNAL_FUNC) cmd_unsetinipw);
@ -1294,7 +1416,7 @@ void authenticated_fish_setup(const char *password, void *rec) {
iniUsed = 0;
}
iniKey = (char *) malloc((strlen(password) * 10) * sizeof(char));
iniKey = (char *) calloc((strlen(password) * 10), sizeof(char));
iniUsed = 1;
iniValue = allocateIni("FiSH", "ini_password_Hash", iniPath);
@ -1307,7 +1429,7 @@ void authenticated_fish_setup(const char *password, void *rec) {
get_ini_password_hash(iniValue.keySize, iniValue.key);
B64digest = (char *) malloc((iniValue.keySize * 2) * sizeof(char));
B64digest = (char *) calloc((iniValue.keySize * 2), sizeof(char));
calculate_password_key_and_hash(password, iniKey, B64digest);
@ -1379,7 +1501,7 @@ void fish_init(void)
get_ini_password_hash(iniValue.keySize, iniValue.key);
if (strlen(iniValue.key) != 43) {
iniKey = (char *) malloc((strlen(default_iniKey)* 2) * sizeof(char));
iniKey = (char *) calloc((strlen(default_iniKey)* 2), sizeof(char));
iniUsed = 1;
strcpy(iniKey, default_iniKey);

View File

@ -5,6 +5,7 @@
#include "FiSH_version.h"
#include "inifile.h"
#include "blowfish.h"
#include "blowfish_cbc.h"
#include "DH1080.h"
#include "module.h"
#include "password.h"
@ -22,6 +23,9 @@ int keyx_query_created = 0;
#define ZeroMemory(dest,count) memset((void *)dest, 0, count)
#define IsNULLorEmpty(psz) (psz==NULL || *psz=='\0')
#define isNoChar(c) ((c) == 'n' || (c) == 'N' || (c) == '0')
#define DH1080_INIT "DH1080_INIT "
#define DH1080_FINISH "DH1080_FINISH "
#define CBC_SUFFIX " CBC"
char *isPlainPrefix(const char *msg);
char *strfcpy(char *dest, char *buffer, int destSize); // removes leading and trailing blanks from string

117
src/blowfish_cbc.c Normal file
View File

@ -0,0 +1,117 @@
#include "blowfish_cbc.h"
int
encrypt_string_cbc (const char *key, const char *str, char *dest, int len)
{
BF_KEY bf_key;
unsigned char ivec[BF_BLOCK] = {0};
BIO *l_mem = NULL, *l_b64 = NULL;
int ret = -1;
if (!key || !key[0])
return 0;
BF_set_key (&bf_key, strlen (key), (const unsigned char *) key);
l_b64 = BIO_new(BIO_f_base64());
if(!l_b64) {
goto fail;
}
BIO_set_flags(l_b64, BIO_FLAGS_BASE64_NO_NL);
l_mem = BIO_new(BIO_s_mem());
if(!l_mem) {
goto fail;
}
l_b64 = BIO_push(l_b64, l_mem);
{
/* for some f*cked up reason, Mircryption's CBC blowfish does not use an
explicit IV, but prepends 8 bytes of random data to the actual string
instead, so we have to do this too... */
unsigned char block[BF_BLOCK] = {0};
RAND_bytes(block, sizeof(block));
BF_cbc_encrypt(block, block, BF_BLOCK, &bf_key, ivec, BF_ENCRYPT);
if(BIO_write(l_b64, block, sizeof(block)) != sizeof(block)) {
goto fail;
}
}
while (len > 0)
{
const size_t blocksize = len < 8 ? len : BF_BLOCK;
unsigned char block[BF_BLOCK] = { 0 }; /* pad with zero */
memcpy (block, str, blocksize);
BF_cbc_encrypt(block, block, BF_BLOCK, &bf_key, ivec, BF_ENCRYPT);
if(BIO_write(l_b64, block, sizeof(block)) != sizeof(block)) {
goto fail;
}
len -= blocksize;
str += blocksize;
}
BUF_MEM *l_ptr = NULL;
BIO_flush(l_b64);
BIO_get_mem_ptr(l_b64, &l_ptr);
memcpy(dest, l_ptr->data, l_ptr->length);
dest[l_ptr->length] = 0;
ret = 1;
fail:
if(l_b64) {
BIO_free_all(l_b64);
}
return ret;
}
int
decrypt_string_cbc (const char *key, const char *str, char *dest, int len)
{
BF_KEY bf_key;
BIO *l_b64 = NULL;
int ret = -1;
unsigned char ivec[BF_BLOCK] = {0};
unsigned char block[BF_BLOCK] = {0};
char * dest_begin = dest;
int inlen = 0;
/* Pad encoded string with 0 bits in case it's bogus */
if (!key || !key[0])
return 0;
BF_set_key (&bf_key, strlen (key), (const unsigned char *) key);
l_b64 = BIO_new(BIO_f_base64());
if(!l_b64) {
goto fail;
}
BIO_set_flags(l_b64, BIO_FLAGS_BASE64_NO_NL);
BIO *l_mem = BIO_new_mem_buf(str, len);
if(!l_mem) {
goto fail;
}
l_b64 = BIO_push(l_b64, l_mem);
while ((inlen = BIO_read(l_b64, block, sizeof(block))) > 0)
{
if(inlen != BF_BLOCK) {
ret *= -1;
break;
}
BF_cbc_encrypt(block, block, BF_BLOCK, &bf_key, ivec, BF_DECRYPT);
memcpy (dest, block, BF_BLOCK);
dest += BF_BLOCK;
}
*dest++ = 0;
// get rid of first 8 bytes
memmove(dest_begin, dest_begin + BF_BLOCK, strlen(dest_begin + BF_BLOCK) + 1);
ret *= -1;
fail:
if(l_b64) {
BIO_free_all(l_b64);
}
return ret;
}

18
src/blowfish_cbc.h Normal file
View File

@ -0,0 +1,18 @@
#include <string.h>
#include <stdlib.h>
#include <openssl/blowfish.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/buffer.h>
#include "FiSH_version.h"
#ifdef HAVE_STDINT
#include <stdint.h>
#else
#ifdef HAVE_INTTYPES
#include <inttypes.h>
#endif
#endif
int decrypt_string_cbc(const char *key, const char *str, char *dest, int len);
int encrypt_string_cbc(const char *key, const char *str, char *dest, int len);

View File

@ -46,10 +46,13 @@
getIniValue(const char *section, const char *key, const char *default_value,
char *buffer, int buflen, const char *filepath)
{
GKeyFile *key_file;
GKeyFile *key_file = NULL;
GError *error = NULL;
gchar *value = NULL;
if(buflen <= 0) return -1;
buffer[0] = 0;
key_file = g_key_file_new();
// If file was read OK...
@ -60,7 +63,7 @@ getIniValue(const char *section, const char *key, const char *default_value,
value = g_key_file_get_string(key_file, section, key, &error);
if (value != NULL && error == NULL) {
strncpy(buffer, value, (size_t) buflen);
buffer[buflen] = '\0';
buffer[buflen-1] = '\0';
}
}
@ -71,6 +74,7 @@ getIniValue(const char *section, const char *key, const char *default_value,
if (error != NULL) {
g_clear_error (&error);
strncpy(buffer, default_value, (size_t) buflen);
buffer[buflen-1] = '\0';
}
return (int)strlen(buffer);
@ -200,10 +204,17 @@ void writeIniFile(GKeyFile * key_file, const char *filepath)
allocateIni(const char *section, const char *key, const char *filepath)
{
struct IniValue iniValue;
char mode[2] = {0};
iniValue.iniKeySize = getIniSize(section, key, filepath);
iniValue.keySize = (iniValue.iniKeySize * 2) * sizeof(char);
iniValue.key = (char *)malloc(iniValue.keySize);
iniValue.keySize = iniValue.iniKeySize * 2 + 1;
iniValue.key = (char *)calloc(iniValue.keySize, sizeof(char));
iniValue.cbc = 0;
getIniValue(section, "cbc", "0", mode, sizeof(mode), filepath);
if (strcmp(mode, "1") == 0) {
iniValue.cbc = 1;
}
return iniValue;
}

View File

@ -7,6 +7,7 @@ struct IniValue {
char *key;
int iniKeySize;
int keySize;
int cbc;
};
int setIniValue(const char *section, const char *key, const char *value,