summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fish.c70
-rw-r--r--plugin_xchat.c2
2 files changed, 68 insertions, 4 deletions
diff --git a/fish.c b/fish.c
index b68ba4a..b73fa78 100644
--- a/fish.c
+++ b/fish.c
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
+ Copyright (c) 2010-2015 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
@@ -25,6 +25,8 @@
#include <stdlib.h>
#include <string.h>
#include <openssl/blowfish.h>
+#include <openssl/bio.h>
+#include <openssl/evp.h>
#include "keystore.h"
#include "fish.h"
@@ -55,7 +57,9 @@ static const signed char fish_unbase64[256] = {
*((dest)++) = (source) & 0xFF; \
} while (0);
-
+/**
+ * Encrypts a message. Currently, only ECB mode is supported.
+ */
char *fish_encrypt(const char *key, size_t keylen, const char *message) {
BF_KEY bfkey;
size_t messagelen;
@@ -108,8 +112,59 @@ char *fish_encrypt(const char *key, size_t keylen, const char *message) {
return encrypted;
}
+/**
+ * Decrypts a message in CBC mode. The leading "*" should be included.
+ */
+char *fish_decrypt_cbc(const char *key, size_t keylen, const char *data) {
+ BF_KEY bfkey;
+ unsigned char *decrypted, *bindata = NULL;
+ BIO *b64 = NULL;
+ BF_set_key(&bfkey, keylen, (const unsigned char*)key);
+
+ // Skip leading "*" that indicates that the message is using CBC byte
+ if (*data != '*') goto err;
+ data++;
+
+ // Decode BASE64
+ b64 = BIO_new(BIO_f_base64());
+ if (!b64) goto err;
+ BIO *bmem = BIO_new(BIO_s_mem());
+ if (!bmem) goto err;
+ BIO *bio = BIO_push(b64, bmem);
+ int datalen = strlen(data);
+ if (BIO_write(bmem, data, datalen) != datalen) goto err;
+ BIO_flush(bio);
-char *fish_decrypt(const char *key, size_t keylen, const char *data) {
+ size_t binlen = BIO_pending(bmem);
+ bindata = malloc(binlen+1);
+ if (!bindata) goto err;
+ int outlen = BIO_read(bio, bindata, BIO_pending(bmem));
+ if (outlen < 8) goto err; // Must at least contain an IV
+ outlen -= 8;
+ outlen &= ~7;
+
+ // Decrypt using CBC
+ decrypted = malloc(outlen+1);
+ if (!decrypted) goto err;
+ if (outlen) {
+ unsigned char *iv = &bindata[0];
+ unsigned char *enc = &bindata[8];
+ BF_cbc_encrypt(enc, decrypted, outlen, &bfkey, iv, BF_DECRYPT);
+ }
+ BIO_free_all(b64);
+ decrypted[outlen] = '\0';
+ return (char*)decrypted;
+
+ err:
+ BIO_free_all(b64);
+ free(bindata);
+ return NULL;
+}
+
+/**
+ * Decrypts in ECB mode.
+ */
+static char *fish_decrypt_ecb(const char *key, size_t keylen, const char *data) {
BF_KEY bfkey;
size_t i;
char *decrypted;
@@ -153,6 +208,15 @@ char *fish_decrypt(const char *key, size_t keylen, const char *data) {
}
/**
+ * Decrypts a message using the given key. ECB or CBC mode is autodetected.
+ */
+char *fish_decrypt(const char *key, size_t keylen, const char *data) {
+ if (*data == '*') return fish_decrypt_cbc(key, keylen, data);
+ else return fish_decrypt_ecb(key, keylen, data);
+}
+
+
+/**
* Encrypts a message (see fish_decrypt). The key is searched for in the
* key store.
*/
diff --git a/plugin_xchat.c b/plugin_xchat.c
index ab71ff8..95b9a26 100644
--- a/plugin_xchat.c
+++ b/plugin_xchat.c
@@ -44,7 +44,7 @@
static const char plugin_name[] = "FiSHLiM";
static const char plugin_desc[] = "Encryption plugin for the FiSH protocol. Less is More!";
-static const char plugin_version[] = "0.0.17";
+static const char plugin_version[] = "0.0.18";
static const char usage_setkey[] = "Usage: SETKEY [<nick or #channel>] <password>, sets the key for a channel or nick";
static const char usage_delkey[] = "Usage: DELKEY <nick or #channel>, deletes the key for a channel or nick";