summary refs log tree commit diff stats
path: root/plugins/fishlim/fish.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/fishlim/fish.c')
-rw-r--r--plugins/fishlim/fish.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/plugins/fishlim/fish.c b/plugins/fishlim/fish.c
new file mode 100644
index 00000000..cb977d7f
--- /dev/null
+++ b/plugins/fishlim/fish.c
@@ -0,0 +1,192 @@
+/*
+
+  Copyright (c) 2010 Samuel Lidén Borell <samuel@slbdata.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 <stdlib.h>
+#include <string.h>
+#include <openssl/blowfish.h>
+
+#include "keystore.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 *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 = malloc(((messagelen-1)/8)*12 + 12 + 1); // each 8-byte block becomes 12 bytes
+    end = encrypted;
+    if (!encrypted) return NULL;
+     
+    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 *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 = malloc(strlen(data)+1);
+    end = decrypted;
+    if (!decrypted) return NULL;
+    
+    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] |= 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 fish_decrypt). The key is searched for in the
+ * key store.
+ */
+char *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 = fish_encrypt(key, strlen(key), data);
+    
+    free(key);
+    return encrypted;
+}
+
+/**
+ * Decrypts a message (see fish_decrypt). The key is searched for in the
+ * key store.
+ */
+char *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 = fish_decrypt(key, strlen(key), data);
+    
+    free(key);
+    return decrypted;
+}
+
+