Added properly working CBC mode implementation to AES.
[crypto.git] / lib / silccrypt / aes.c
index 27a47cc95b43731f69c3f5fd33697fcf9811f8d3..95bdd68485d8c9b1857c32ffa896ec969c958c69 100644 (file)
@@ -34,7 +34,7 @@
 */
 
 #include "silccrypto.h"
-#include "rijndael_internal.h"
+#include "aes_internal.h"
 #include "aes.h"
 
 /*
 
 SILC_CIPHER_API_SET_KEY(aes)
 {
-  switch (cipher->mode) {
+  switch (ops->mode) {
+  case SILC_CIPHER_MODE_CTR:
+  case SILC_CIPHER_MODE_CFB:
+    aes_encrypt_key(key, keylen, &((AesContext *)context)->u.enc);
+    break;
+
   case SILC_CIPHER_MODE_CBC:
+  case SILC_CIPHER_MODE_ECB:
     if (encryption)
       aes_encrypt_key(key, keylen, &((AesContext *)context)->u.enc);
     else
       aes_decrypt_key(key, keylen, &((AesContext *)context)->u.dec);
     break;
 
-  case SILC_CIPHER_MODE_CTR:
-  case SILC_CIPHER_MODE_CFB:
-    aes_encrypt_key(key, keylen, &((AesContext *)context)->u.enc);
-    break;
-
   default:
     return FALSE;
   }
@@ -70,13 +71,9 @@ SILC_CIPHER_API_SET_IV(aes)
 {
   AesContext *aes = context;
 
-  switch (cipher->mode) {
+  switch (ops->mode) {
 
   case SILC_CIPHER_MODE_CTR:
-    /* Starts new block. */
-    aes->u.enc.inf.b[2] = 0;
-    break;
-
   case SILC_CIPHER_MODE_CFB:
     /* Starts new block. */
     aes->u.enc.inf.b[2] = 16;
@@ -87,11 +84,23 @@ SILC_CIPHER_API_SET_IV(aes)
   }
 }
 
-/* Returns the size of the cipher context. */
+/* Initialize */
+
+SILC_CIPHER_API_INIT(aes)
+{
+  AesContext *aes = silc_calloc(1, sizeof(AesContext));
+  if (aes)
+    aes->u.enc.inf.b[2] = 16;
+  return aes;
+}
+
+/* Unnitialize */
 
-SILC_CIPHER_API_CONTEXT_LEN(aes)
+SILC_CIPHER_API_UNINIT(aes)
 {
-  return sizeof(AesContext);
+  AesContext *aes = context;
+  memset(aes, 0, sizeof(*aes));
+  silc_free(aes);
 }
 
 /* Encrypts with the cipher. Source and destination buffers maybe one and
@@ -100,33 +109,29 @@ SILC_CIPHER_API_CONTEXT_LEN(aes)
 SILC_CIPHER_API_ENCRYPT(aes)
 {
   AesContext *aes = context;
-  SilcUInt32 ctr[4];
+  int i;
 
-  switch (cipher->mode) {
-  case SILC_CIPHER_MODE_CBC:
+  switch (ops->mode) {
+  case SILC_CIPHER_MODE_CTR:
+    SILC_CTR_MSB_128_8(iv, cipher->block, aes->u.enc.inf.b[2], src, dst,
+                      aes_encrypt(iv, cipher->block, &aes->u.enc));
+    break;
+
+  case SILC_CIPHER_MODE_ECB:
     {
-      int nb = len >> 4;
-
-      SILC_ASSERT((len & (16 - 1)) == 0);
-      if (len & (16 - 1))
-       return FALSE;
-
-      while(nb--) {
-       lp32(iv)[0] ^= lp32(src)[0];
-       lp32(iv)[1] ^= lp32(src)[1];
-       lp32(iv)[2] ^= lp32(src)[2];
-       lp32(iv)[3] ^= lp32(src)[3];
-       aes_encrypt(iv, iv, &aes->u.enc);
-       memcpy(dst, iv, 16);
+      SilcUInt32 nb = len >> 4;
+
+      while (nb--) {
+       aes_encrypt(src, dst, &aes->u.enc);
        src += 16;
        dst += 16;
       }
     }
     break;
 
-  case SILC_CIPHER_MODE_CTR:
-    SILC_CTR_MSB_128_8(iv, ctr, iv, aes->u.enc.inf.b[2], src, dst,
-                      aes_encrypt(iv, iv, &aes->u.enc));
+  case SILC_CIPHER_MODE_CBC:
+    SILC_CBC_ENC_MSB_128_8(len, iv, src, dst, i,
+                          aes_encrypt(iv, iv, &aes->u.enc));
     break;
 
   case SILC_CIPHER_MODE_CFB:
@@ -147,32 +152,29 @@ SILC_CIPHER_API_ENCRYPT(aes)
 SILC_CIPHER_API_DECRYPT(aes)
 {
   AesContext *aes = context;
+  unsigned char prev[16];
+  int i;
 
-  switch (cipher->mode) {
-  case SILC_CIPHER_MODE_CBC:
-    {
-      unsigned char tmp[16];
-      int nb = len >> 4;
+  switch (ops->mode) {
+  case SILC_CIPHER_MODE_CTR:
+    return silc_aes_encrypt(cipher, ops, context, src, dst, len, iv);
+    break;
 
-      if (len & (16 - 1))
-       return FALSE;
+  case SILC_CIPHER_MODE_ECB:
+    {
+      SilcUInt32 nb = len >> 4;
 
-      while(nb--) {
-       memcpy(tmp, src, 16);
+      while (nb--) {
        aes_decrypt(src, dst, &aes->u.dec);
-       lp32(dst)[0] ^= lp32(iv)[0];
-       lp32(dst)[1] ^= lp32(iv)[1];
-       lp32(dst)[2] ^= lp32(iv)[2];
-       lp32(dst)[3] ^= lp32(iv)[3];
-       memcpy(iv, tmp, 16);
        src += 16;
        dst += 16;
       }
     }
     break;
 
-  case SILC_CIPHER_MODE_CTR:
-    return silc_aes_encrypt(cipher, context, src, dst, len, iv);
+  case SILC_CIPHER_MODE_CBC:
+    SILC_CBC_DEC_MSB_128_8(len, iv, prev, src, dst, i,
+                          aes_decrypt(src, dst, &aes->u.dec));
     break;
 
   case SILC_CIPHER_MODE_CFB: