Просмотр исходного кода

Merge branch 'aes_cbc'

* aes_cbc:
  * Default EncryptedStream format is now AES 256 CBC
  * Add AES_cbc
Bryan Drewery 16 лет назад
Родитель
Сommit
4a2844452d
6 измененных файлов с 135 добавлено и 23 удалено
  1. 38 18
      src/EncryptedStream.c
  2. 3 3
      src/EncryptedStream.h
  3. 35 2
      src/crypt.c
  4. 2 0
      src/crypt.h
  5. 55 0
      src/crypto/aes_util.c
  6. 2 0
      src/crypto/aes_util.h

+ 38 - 18
src/EncryptedStream.c

@@ -2,6 +2,7 @@
  *
  */
 #include "base64.h"
+#include "misc.h"
 #include <bdlib/src/String.h>
 #include <bdlib/src/base64.h>
 #include "EncryptedStream.h"
@@ -35,46 +36,56 @@ int EncryptedStream::loadFile (const int fd) {
     }
   }
 
+  bd::String IV;
+
+  if (enc_flags & ENC_AES_256_CBC) {
+    IV = in_buf(0, 16);
+    in_buf += 16;
+  }
+
   if (enc_flags & ENC_KEEP_NEWLINES) {
     bd::String buf(in_buf), line, out_buf;
     while (buf.length()) {
       line = newsplit(buf, '\n');
-      unapply_filters(line);
+      unapply_filters(line, IV);
       line += '\n';
       out_buf += line;
     }
     in_buf = out_buf;
   } else {
-    unapply_filters(in_buf);
+    unapply_filters(in_buf, IV);
   }
 
   str = in_buf;
   return 0;
 }
 
-void EncryptedStream::apply_filters(bd::String& buf) const {
-#ifdef unimplemented
-  if (enc_flags & ENC_AES_256_CBC)
-    buf = encrypt_string_cbc(key, buf);
-#endif
-  if (enc_flags & ENC_AES_256_ECB)
+void EncryptedStream::apply_filters(bd::String& buf, const bd::String& IV) const {
+  if (enc_flags & ENC_AES_256_CBC) {
+    unsigned char* iv = (unsigned char*) strdup(IV.c_str());
+    buf = encrypt_string_cbc(key, buf, iv);
+    free(iv);
+  } else if (enc_flags & ENC_AES_256_ECB)
     buf = encrypt_string(key, buf);
+
   if (enc_flags & ENC_BASE64_BROKEN)
     buf = broken_base64Encode(buf);
   if (enc_flags & ENC_BASE64)
     buf = bd::base64Encode(buf);
 }
 
-void EncryptedStream::unapply_filters(bd::String& buf) const {
+void EncryptedStream::unapply_filters(bd::String& buf, const bd::String& IV) const {
   if (enc_flags & ENC_BASE64_BROKEN)
     buf = broken_base64Decode(buf);
   if (enc_flags & ENC_BASE64)
     buf = bd::base64Decode(buf);
-#ifdef unimplemented
-  if (enc_flags & ENC_AES_256_CBC)
-    buf = decrypt_string_cbc(key, buf);
-#endif
-  if (enc_flags & ENC_AES_256_ECB)
+
+  if (enc_flags & ENC_AES_256_CBC) {
+    unsigned char* iv = (unsigned char*) strdup(IV.c_str());
+    buf = decrypt_string_cbc(key, buf, iv);
+    free(iv);
+  }
+  else if (enc_flags & ENC_AES_256_ECB)
     buf = decrypt_string(key, buf);
 }
 
@@ -82,26 +93,35 @@ int EncryptedStream::writeFile (const int fd) const {
   if (!key.length()) return bd::Stream::writeFile(fd);
 
   /* Encrypt the stream before writing it out */
-  bd::String out_buf;
+  bd::String IV;
+  if (enc_flags & ENC_AES_256_CBC) {
+    char rand_string[17] = "";
+    make_rand_str(rand_string, sizeof(rand_string) - 1);
+    IV = bd::String(rand_string, 16);
+  }
 
+  bd::String out_buf;
   if (enc_flags & ENC_KEEP_NEWLINES) {
     bd::String buf(str), line;
     while (buf.length()) {
       line = newsplit(buf, '\n');
-      apply_filters(line);
+      apply_filters(line, IV);
       line += '\n';
       out_buf += line;
     }
 
   } else {
     out_buf = str;
-    apply_filters(out_buf);
+    apply_filters(out_buf, IV);
   }
 
   if (enc_flags & ENC_NO_HEADER)
     return bd::Stream(out_buf).writeFile(fd);
 
   const char encoding[3] = {0x7F, enc_flags, 0x7F};
-  bd::String encrypted = bd::String(encoding, 3) + out_buf;
+  bd::String encrypted(encoding, 3);
+  if (enc_flags & ENC_AES_256_CBC)
+    encrypted += IV;
+  encrypted += out_buf;
   return bd::Stream(encrypted).writeFile(fd);
 }

+ 3 - 3
src/EncryptedStream.h

@@ -18,14 +18,14 @@ namespace bd {
 #define ENC_KEEP_NEWLINES	16
 #define ENC_NO_HEADER		32
 
-#define ENC_DEFAULT 		(ENC_AES_256_ECB)
+#define ENC_DEFAULT 		(ENC_AES_256_CBC)
 
 class EncryptedStream : public bd::Stream {
   private:
         bd::String key;
         mutable char enc_flags;
-        void apply_filters(bd::String& buf) const;
-        void unapply_filters(bd::String& buf) const;
+        void apply_filters(bd::String& buf, const bd::String& IV) const;
+        void unapply_filters(bd::String& buf, const bd::String& IV) const;
 
   protected:
 

+ 35 - 2
src/crypt.c

@@ -36,7 +36,7 @@ char *encrypt_string(const char *keydata, char *in)
 }
 
 /**
- * @brief Encrypt a string
+ * @brief Encrypt a string with AES 256 ECB
  * @param key The key to encrypt with
  * @param data The string to encrypt
  * @return A new, encrypted string
@@ -50,6 +50,22 @@ bd::String encrypt_string(const bd::String& key, const bd::String& data) {
   return encrypted;
 }
 
+/**
+ * @brief Encrypt a string with AES 256 CBC
+ * @param key The key to encrypt with
+ * @param data The string to encrypt
+ * @param IV The IV to use (WARNING: This is modified inplace)
+ * @return A new, encrypted string
+ */
+bd::String encrypt_string_cbc(const bd::String& key, const bd::String& data, unsigned char* IV) {
+  if (!key) return data;
+  size_t len = data.length();
+  char *bdata = (char*) aes_encrypt_cbc_binary(key.c_str(), (unsigned char*) data.c_str(), &len, IV);
+  bd::String encrypted(bdata, len);
+  free(bdata);
+  return encrypted;
+}
+
 char *decrypt_string(const char *keydata, char *in)
 {
   size_t len = strlen(in);
@@ -69,7 +85,7 @@ char *decrypt_string(const char *keydata, char *in)
 }
 
 /**
- * @brief Decrypt a string
+ * @brief Decrypt an AES 256 ECB ciphered string
  * @param key The key to decrypt with
  * @param data The string to decrypt
  * @return A new, decrypted string
@@ -84,6 +100,23 @@ bd::String decrypt_string(const bd::String& key, const bd::String& data) {
   return decrypted;
 }
 
+/**
+ * @brief Decrypt anAES 256 CBC ciphered string
+ * @param key The key to decrypt with
+ * @param data The string to decrypt
+ * @param IV The IV to use (WARNING: This is modified inplace)
+ * @return A new, decrypted string
+ */
+bd::String decrypt_string_cbc(const bd::String& key, const bd::String& data, unsigned char* IV) {
+  if (!key) return data;
+  size_t len = data.length();
+  char *bdata = (char*) aes_decrypt_cbc_binary(key.c_str(), (unsigned char*) data.c_str(), &len, IV);
+  bd::String decrypted(bdata, len);
+  OPENSSL_cleanse(bdata, len);
+  free(bdata);
+  return decrypted;
+}
+
 int salted_sha1cmp(const char *salted_hash, const char *string) {
   char* cmp = salted_sha1(string, &salted_hash[1]); //Pass in the salt from the given hash
   int n = strcmp(salted_hash, cmp);

+ 2 - 0
src/crypt.h

@@ -28,10 +28,12 @@ int sha1cmp(const char *, const char*);
 
 char *encrypt_string(const char *, char *);
 bd::String encrypt_string(const bd::String&, const bd::String&);
+bd::String encrypt_string_cbc(const bd::String&, const bd::String&, unsigned char *);
 char *decrypt_string(const char *, char *);
 char *salted_sha1(const char *, const char* = NULL);
 int salted_sha1cmp(const char *, const char*);
 bd::String decrypt_string(const bd::String&, const bd::String&);
+bd::String decrypt_string_cbc(const bd::String&, const bd::String&, unsigned char *);
 char *cryptit (char *);
 char *decryptit (char *);
 void Encrypt_File(char *, char *);

+ 55 - 0
src/crypto/aes_util.c

@@ -76,3 +76,58 @@ aes_decrypt_ecb_binary(const char *keydata, unsigned char *in, size_t *len)
   out[*len] = 0;
   return out;
 }
+
+unsigned char *
+aes_encrypt_cbc_binary(const char *keydata, unsigned char *in, size_t *inlen, unsigned char *ivec)
+{
+  size_t len = *inlen;
+  unsigned char *out = NULL;
+
+  /* First pad indata to CRYPT_BLOCKSIZE multiple */
+  if (len % CRYPT_BLOCKSIZE)             /* more than 1 block? */
+    len += (CRYPT_BLOCKSIZE - (len % CRYPT_BLOCKSIZE));
+
+  out = (unsigned char *) my_calloc(1, len + 1);
+  *inlen = len;
+
+  if (!keydata || !*keydata) {
+    /* No key, no encryption */
+    memcpy(out, in, len);
+  } else {
+    char key[CRYPT_KEYSIZE + 1] = "";
+
+    strlcpy(key, keydata, sizeof(key));
+    AES_set_encrypt_key((const unsigned char *) key, CRYPT_KEYBITS, &e_key);
+    AES_cbc_encrypt(in, out, len, &e_key, ivec, AES_ENCRYPT);
+    OPENSSL_cleanse(key, sizeof(key));
+    OPENSSL_cleanse(&e_key, sizeof(e_key));
+  }
+  out[len] = 0;
+  return out;
+}
+
+unsigned char *
+aes_decrypt_cbc_binary(const char *keydata, unsigned char *in, size_t *len, unsigned char* ivec)
+{
+  unsigned char *out = NULL;
+
+  *len -= *len % CRYPT_BLOCKSIZE;
+  out = (unsigned char *) my_calloc(1, *len + 1);
+
+  if (!keydata || !*keydata) {
+    /* No key, no decryption */
+  } else {
+    /* Init/fetch key */
+    char key[CRYPT_KEYSIZE + 1] = "";
+
+    strlcpy(key, keydata, sizeof(key));
+    AES_set_decrypt_key((const unsigned char *) key, CRYPT_KEYBITS, &d_key);
+    AES_cbc_encrypt(in, out, *len, &d_key, ivec, AES_DECRYPT);
+    OPENSSL_cleanse(key, sizeof(key));
+    OPENSSL_cleanse(&d_key, sizeof(d_key));
+  }
+
+  *len = strlen((char*) out);
+  out[*len] = 0;
+  return out;
+}

+ 2 - 0
src/crypto/aes_util.h

@@ -9,4 +9,6 @@
 
 unsigned char *aes_encrypt_ecb_binary(const char *, unsigned char *, size_t *);
 unsigned char *aes_decrypt_ecb_binary(const char *, unsigned char *, size_t *);
+unsigned char *aes_encrypt_cbc_binary(const char *, unsigned char *, size_t *, unsigned char *);
+unsigned char *aes_decrypt_cbc_binary(const char *, unsigned char *, size_t *, unsigned char *);
 #endif