Bladeren bron

* Move encrypt_binary() and decrypt_binary() to aes_util.c
* base64 now returns proper lengths for encode/decode, (need to convert to standardized base64 with proper padding though)

svn: 2935

Bryan Drewery 20 jaren geleden
bovenliggende
commit
9024a7d89f
8 gewijzigde bestanden met toevoegingen van 139 en 88 verwijderingen
  1. 47 13
      src/base64.c
  2. 1 1
      src/base64.h
  3. 2 72
      src/crypt.c
  4. 0 2
      src/crypt.h
  5. 1 0
      src/crypto/Makefile.in
  6. 78 0
      src/crypto/aes_util.c
  7. 9 0
      src/crypto/aes_util.h
  8. 1 0
      src/crypto/crypto.h

+ 47 - 13
src/base64.c

@@ -101,23 +101,28 @@ char *int_to_base64(unsigned int val)
   return buf_base64 + i;
 }
 
+#define NUM_ASCII_BYTES 3
+#define NUM_ENCODED_BYTES 4
 
 char *
-b64enc(const unsigned char *data, size_t len)
+b64enc(const unsigned char *data, size_t *len)
 {
-  char *dest = (char *) my_calloc(1, (len << 2) / 3 + 4 + 1);
-
-  b64enc_buf(data, len, dest);
+  size_t dlen = (((*len + (NUM_ASCII_BYTES - 1)) / NUM_ASCII_BYTES) * NUM_ENCODED_BYTES);
+  char *dest = (char *) my_calloc(1, dlen + 1);
+  b64enc_buf(data, *len, dest);
+  *len = dlen;
   return (dest);
 }
 
+/* Encode 3 8-bit bytes to 4 6-bit characters */
 void
 b64enc_buf(const unsigned char *data, size_t len, char *dest)
 {
-#define DB(x) ((unsigned char) (x + i < len ? data[x + i] : 0))
+#define DB(x) ((unsigned char) ((x + i) < len ? data[x + i] : 0))
   register size_t t, i;
 
-  for (i = 0, t = 0; i < len; i += 3, t += 4) {
+  /* 4-byte blocks */
+  for (i = 0, t = 0; i < len; i += NUM_ASCII_BYTES, t += NUM_ENCODED_BYTES) {
     dest[t] = base64[DB(0) >> 2];
     dest[t + 1] = base64[((DB(0) & 3) << 4) | (DB(1) >> 4)];
     dest[t + 2] = base64[((DB(1) & 0x0F) << 2) | (DB(2) >> 6)];
@@ -130,26 +135,55 @@ b64enc_buf(const unsigned char *data, size_t len, char *dest)
 char *
 b64dec(const unsigned char *data, size_t *len)
 {
+//  size_t dlen = (((*len >> 2) * 3) - 2);
   char *dest = (char *) my_calloc(1, ((*len * 3) >> 2) + 6 + 1);
-
+//  char *dest = (char *) my_calloc(1, dlen + 1);
   b64dec_buf(data, len, dest);
-  return (dest);
+//*len = dlen;
+  return dest;
 }
 
+/* Decode 4 6-bit characters to 3 8-bit bytes */
 void
 b64dec_buf(const unsigned char *data, size_t *len, char *dest)
 {
 #define DB(x) ((unsigned char) (x + i < *len ? base64r[(unsigned char) data[x + i]] : 0))
+//#define XB(x) ((unsigned char) (x + i < *len ? (unsigned char) data[x + i] : 0))
   register size_t t, i;
+//  const size_t wholeBlocks = (*len / NUM_ENCODED_BYTES);
+//  const size_t remainingBytes (*len % NUM_ENCODED_BYTES);
+//  size_t maxTotal = (wholeBlocks + (0 != remainingBytes)) * NUM_ASCII_BYTES;
+  register int pads = 0;
+
+  for (i = 0, t = 0; i < *len; i += NUM_ENCODED_BYTES, t += NUM_ASCII_BYTES) {
 
-  for (i = 0, t = 0; i < *len; i += 4, t += 3) {
     dest[t] = (DB(0) << 2) + (DB(1) >> 4);
     dest[t + 1] = ((DB(1) & 0x0F) << 4) + (DB(2) >> 2);
     dest[t + 2] = ((DB(2) & 3) << 6) + DB(3);
+    /* Check for nulls (padding) - the >= check is because binary data might contain VALID NULLS */
+    if ((i + NUM_ENCODED_BYTES) >= *len) {
+      if (dest[t] == 0) ++pads;
+      if (dest[t+1] == 0) ++pads;
+      if (dest[t+2] == 0) ++pads;
+    }
+/*
+printf("i: %d *len: %d\n", i, *len);
+if (dest[t] == 0) printf("t:%d %d+%d '%c'\n", t, (XB(0) << 2), (XB(1) >> 4), base64r[(XB(0) << 2)] + base64r[(XB(1) >> 4)]);
+else printf("t/%d\n", t);
+if (dest[t+1] == 0) printf("t+1:%d %d+%d '%c'\n", t+1, ((XB(1) & 0x0F) << 4), (XB(2) >> 2), base64r[((XB(1) & 0x0F) << 4)] + base64r[(XB(2) >> 2)]);
+else printf("t+1/%d\n", t+1);
+if (dest[t+2] == 0) printf("t+2:%d %d+%d '%c'\n", t+2, ((XB(2) & 3) << 6), XB(3), base64r[((XB(2) & 3) << 6)] + base64r[XB(3)]);
+else printf("t+2/%d\n", t+2);
+*/
   };
 #undef DB
-  t += 3;
-  t -= (t % 4);
-  dest[t] = 0;
-  *len = t;
+//  t += 3;
+//  t -= (t % 4);
+//*len = t;
+//dest[t] = 0;
+
+  *len = t - pads;
+//printf("pads: %d\n", pads);
+//*len = t;
+  dest[*len] = 0;
 }

+ 1 - 1
src/base64.h

@@ -6,7 +6,7 @@
 char *int_to_base64(unsigned int);
 int base64_to_int(char *);
 
-char *b64enc(const unsigned char *data, size_t len);
+char *b64enc(const unsigned char *data, size_t *len);
 void b64enc_buf(const unsigned char *data, size_t len, char *dest);
 
 char *b64dec(const unsigned char *data, size_t *len);

+ 2 - 72
src/crypt.c

@@ -14,76 +14,6 @@
 #include "src/crypto/crypto.h"
 #include <stdarg.h>
 
-#define CRYPT_BLOCKSIZE AES_BLOCK_SIZE
-#define CRYPT_KEYBITS 256
-#define CRYPT_KEYSIZE (CRYPT_KEYBITS >> 3)
-
-AES_KEY e_key, d_key;
-
-unsigned char *
-encrypt_binary(const char *keydata, unsigned char *in, size_t *inlen)
-{
-  size_t len = *inlen;
-  int blocks = 0, block = 0;
-  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);
-  egg_memcpy(out, in, *inlen);
-  *inlen = len;
-
-  if (!keydata || !*keydata) {
-    /* No key, no encryption */
-    egg_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);
-    /* Now loop through the blocks and crypt them */
-    blocks = len / CRYPT_BLOCKSIZE;
-    for (block = blocks - 1; block >= 0; block--)
-      AES_encrypt(&out[block * CRYPT_BLOCKSIZE], &out[block * CRYPT_BLOCKSIZE], &e_key);
-    OPENSSL_cleanse(key, sizeof(key));
-    OPENSSL_cleanse(&e_key, sizeof(e_key));
-  }
-  out[len] = 0;
-  return out;
-}
-
-unsigned char *
-decrypt_binary(const char *keydata, unsigned char *in, size_t *len)
-{
-  int blocks = 0, block = 0;
-  unsigned char *out = NULL;
-
-  *len -= *len % CRYPT_BLOCKSIZE;
-  out = (unsigned char *) my_calloc(1, *len + 1);
-  egg_memcpy(out, in, *len);
-
-  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);
-    /* Now loop through the blocks and crypt them */
-    blocks = *len / CRYPT_BLOCKSIZE;
-
-    for (block = blocks - 1; block >= 0; block--)
-      AES_decrypt(&out[block * CRYPT_BLOCKSIZE], &out[block * CRYPT_BLOCKSIZE], &d_key);
-    OPENSSL_cleanse(key, sizeof(key));
-    OPENSSL_cleanse(&d_key, sizeof(d_key));
-  }
-
-  return out;
-}
-
 char *encrypt_string(const char *keydata, char *in)
 {
   size_t len = 0;
@@ -93,8 +23,8 @@ char *encrypt_string(const char *keydata, char *in)
   len = strlen(in);
   bdata = encrypt_binary(keydata, (unsigned char *) in, &len);
   if (keydata && *keydata) {
-    res = b64enc(bdata, len);
-    OPENSSL_cleanse(bdata, len);
+    res = b64enc(bdata, &len);
+    OPENSSL_cleanse(bdata, *len);
     free(bdata);
     return res;
   } else {

+ 0 - 2
src/crypt.h

@@ -23,8 +23,6 @@ char *MD5FILE(const char *);
 char *SHA1(const char *);
 int sha1cmp(const char *, const char*);
 
-unsigned char *encrypt_binary(const char *, unsigned char *, size_t *);
-unsigned char *decrypt_binary(const char *, unsigned char *, size_t *);
 char *encrypt_string(const char *, char *);
 char *decrypt_string(const char *, char *);
 char *salted_sha1(const char *, const char* = NULL);

+ 1 - 0
src/crypto/Makefile.in

@@ -13,6 +13,7 @@ depcomp = /bin/sh $(top_srcdir)/autotools/depcomp
 @SET_MAKE@
 
 OBJS = aes.o \
+	aes_util.o \
 	cleanse.o \
 	md5.o \
 	sha.o

+ 78 - 0
src/crypto/aes_util.c

@@ -0,0 +1,78 @@
+/* aes_util.c
+ *
+ */
+
+#include "aes.h"
+#include "src/compat/compat.h"
+
+#define CRYPT_BLOCKSIZE AES_BLOCK_SIZE
+#define CRYPT_KEYBITS 256
+#define CRYPT_KEYSIZE (CRYPT_KEYBITS >> 3)
+
+AES_KEY e_key, d_key;
+
+unsigned char *
+encrypt_binary(const char *keydata, unsigned char *in, size_t *inlen)
+{
+  size_t len = *inlen;
+  int blocks = 0, block = 0;
+  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);
+  egg_memcpy(out, in, *inlen);
+  *inlen = len;
+
+  if (!keydata || !*keydata) {
+    /* No key, no encryption */
+    egg_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);
+    /* Now loop through the blocks and crypt them */
+    blocks = len / CRYPT_BLOCKSIZE;
+    for (block = blocks - 1; block >= 0; --block)
+      AES_encrypt(&out[block * CRYPT_BLOCKSIZE], &out[block * CRYPT_BLOCKSIZE], &e_key);
+    OPENSSL_cleanse(key, sizeof(key));
+    OPENSSL_cleanse(&e_key, sizeof(e_key));
+  }
+  out[len] = 0;
+  return out;
+}
+
+unsigned char *
+decrypt_binary(const char *keydata, unsigned char *in, size_t *len)
+{
+  int blocks = 0, block = 0;
+  unsigned char *out = NULL;
+
+  *len -= *len % CRYPT_BLOCKSIZE;
+  out = (unsigned char *) my_calloc(1, *len + 1);
+  egg_memcpy(out, in, *len);
+
+  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);
+    /* Now loop through the blocks and decrypt them */
+    blocks = *len / CRYPT_BLOCKSIZE;
+
+    for (block = blocks - 1; block >= 0; --block)
+      AES_decrypt(&out[block * CRYPT_BLOCKSIZE], &out[block * CRYPT_BLOCKSIZE], &d_key);
+    OPENSSL_cleanse(key, sizeof(key));
+    OPENSSL_cleanse(&d_key, sizeof(d_key));
+  }
+
+  *len = strlen((char*) out);
+  out[*len] = 0;
+  return out;
+}

+ 9 - 0
src/crypto/aes_util.h

@@ -0,0 +1,9 @@
+/* aes_util.h
+ *
+ */
+
+#ifndef _AES_UTIL_H
+#define _AES_UTIL_H 1
+unsigned char *encrypt_binary(const char *, unsigned char *, size_t *);
+unsigned char *decrypt_binary(const char *, unsigned char *, size_t *);
+#endif

+ 1 - 0
src/crypto/crypto.h

@@ -5,5 +5,6 @@
 #include "md5.h"
 #include "sha.h"
 #include "aes.h"
+#include "aes_util.h"
 
 #endif /* !_CRYPTO_H */