Major restructuring of the internals of SILC Cipher API
[crypto.git] / lib / silccrypt / cast5.c
index 227cae11418a2adc0fff01adac507036979ae423..2d5cf2206c62ccc5f353f6c4a739a7e06bb57df7 100644 (file)
@@ -3,7 +3,7 @@
 
 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
 
-#include "silc.h"
+#include "silccrypto.h"
 #include "cast5_internal.h"
 #include "cast5.h"
 
@@ -22,73 +22,76 @@ SILC_CIPHER_API_SET_KEY(cast5)
 
 SILC_CIPHER_API_SET_IV(cast5)
 {
-  if (cipher->mode == SILC_CIPHER_MODE_CTR) {
-    cast5_key *cast5 = context;
+  cast5_key *cast5 = context;
+
+  switch (ops->mode) {
+
+  case SILC_CIPHER_MODE_CTR:
+  case SILC_CIPHER_MODE_CFB:
+    /* Starts new block. */
+    cast5->padlen = 8;
+    break;
 
-    /* Starts new block */
-    cast5->padlen = 0;
+  default:
+    break;
   }
 }
 
-/* Returns the size of the cipher context. */
+/* Initialize */
+
+SILC_CIPHER_API_INIT(cast5)
+{
+  cast5_key *cast5 = silc_calloc(1, sizeof(cast5_key));
+  if (cast5)
+    cast5->padlen = 8;
+}
+
+/* Uninitialize */
 
-SILC_CIPHER_API_CONTEXT_LEN(cast5)
+SILC_CIPHER_API_UNINIT(cast5)
 {
-  return sizeof(cast5_key);
+  cast5_key *cast5 = context;
+  memset(cast5, 0, sizeof(*cast5));
+  silc_free(cast5);
 }
 
 SILC_CIPHER_API_ENCRYPT(cast5)
 {
   cast5_key *cast5 = context;
-  SilcUInt32 tmp[2], ctr[2];
+  SilcUInt32 tmp[2];
   int i;
 
-  switch (cipher->mode) {
-
-  case SILC_CIPHER_MODE_CBC:
-    SILC_ASSERT((len & (8 - 1)) == 0);
-    if (len & (8 - 1))
-      return FALSE;
-    SILC_CBC_MSB_GET_IV(tmp, iv, 8);
-
-    SILC_CBC_MSB_ENC_PRE(tmp, src, 8);
-    cast5_encrypt(cast5, tmp, tmp);
-    SILC_CBC_MSB_ENC_POST(tmp, dst, src, 8);
-
-    for (i = 8; i < len; i += 8) {
-      SILC_CBC_MSB_ENC_PRE(tmp, src, 8);
-      cast5_encrypt(cast5, tmp, tmp);
-      SILC_CBC_MSB_ENC_POST(tmp, dst, src, 8);
-    }
-
-    SILC_CBC_MSB_PUT_IV(tmp, iv, 8);
-    break;
+  switch (ops->mode) {
 
   case SILC_CIPHER_MODE_CTR:
-    SILC_GET32_MSB(ctr[0], iv);
-    SILC_GET32_MSB(ctr[1], iv + 4);
-
-    i = cast5->padlen;
-    if (!i)
-      i = 8;
-
-    while (len-- > 0) {
-      if (i == 8) {
-       if (++ctr[1] == 0)
-         ++ctr[0];
-
-       cast5_encrypt(cast5, ctr, tmp);
+    SILC_CTR_MSB_64_32(iv, tmp, cipher->block, cast5->padlen, src, dst,
+                      cast5_encrypt(cast5, tmp, tmp));
+    break;
 
-       SILC_PUT32_MSB(tmp[0], iv);
-       SILC_PUT32_MSB(tmp[1], iv + 4);
-       i = 0;
+  case SILC_CIPHER_MODE_ECB:
+    {
+      SilcUInt32 nb = len >> 3;
+
+      while (nb--) {
+        SILC_GET32_MSB(tmp[0], src);
+        SILC_GET32_MSB(tmp[1], src + 4);
+        cast5_encrypt(cast5, tmp, tmp);
+        SILC_PUT32_MSB(tmp[0], dst);
+        SILC_PUT32_MSB(tmp[1], dst + 4);
+        src += 8;
+        dst += 8;
       }
-      *dst++ = *src++ ^ iv[i++];
     }
-    cast5->padlen = i;
+    break;
 
-    SILC_PUT32_MSB(ctr[0], iv);
-    SILC_PUT32_MSB(ctr[1], iv + 4);
+  case SILC_CIPHER_MODE_CBC:
+    SILC_CBC_ENC_MSB_64_32(len, iv, tmp, src, dst, i,
+                          cast5_encrypt(cast5, tmp, tmp));
+    break;
+
+  case SILC_CIPHER_MODE_CFB:
+    SILC_CFB_ENC_MSB_64_32(iv, tmp, cast5->padlen, src, dst,
+                          cast5_encrypt(cast5, tmp, tmp));
     break;
 
   default:
@@ -100,32 +103,40 @@ SILC_CIPHER_API_ENCRYPT(cast5)
 
 SILC_CIPHER_API_DECRYPT(cast5)
 {
+  cast5_key *cast5 = context;
   SilcUInt32 tmp[2], tmp2[2], tiv[2];
   int i;
 
-  switch (cipher->mode) {
-
-  case SILC_CIPHER_MODE_CBC:
-    if (len & (8 - 1))
-      return FALSE;
-
-    SILC_CBC_MSB_GET_IV(tiv, iv, 8);
+  switch (ops->mode) {
 
-    SILC_CBC_MSB_DEC_PRE(tmp, src, 8);
-    cast5_decrypt((cast5_key *)context, tmp, tmp2);
-    SILC_CBC_MSB_DEC_POST(tmp2, dst, src, tmp, tiv, 8);
+  case SILC_CIPHER_MODE_CTR:
+    return silc_cast5_encrypt(cipher, ops, context, src, dst, len, iv);
+    break;
 
-    for (i = 8; i < len; i += 8) {
-      SILC_CBC_MSB_DEC_PRE(tmp, src, 8);
-      cast5_decrypt((cast5_key *)context, tmp, tmp2);
-      SILC_CBC_MSB_DEC_POST(tmp2, dst, src, tmp, tiv, 8);
+  case SILC_CIPHER_MODE_ECB:
+    {
+      SilcUInt32 nb = len >> 3;
+
+      while (nb--) {
+        SILC_GET32_LSB(tmp[0], src);
+        SILC_GET32_LSB(tmp[1], src + 4);
+        cast5_decrypt(cast5, tmp, tmp);
+        SILC_PUT32_LSB(tmp[0], dst);
+        SILC_PUT32_LSB(tmp[1], dst + 4);
+        src += 8;
+        dst += 8;
+      }
     }
+    break;
 
-    SILC_CBC_MSB_PUT_IV(tiv, iv, 8);
+  case SILC_CIPHER_MODE_CBC:
+    SILC_CBC_DEC_MSB_64_32(len, iv, tiv, tmp, tmp2, src, dst, i,
+                          cast5_decrypt(cast5, tmp, tmp2));
     break;
 
-  case SILC_CIPHER_MODE_CTR:
-    return silc_cast5_encrypt(cipher, context, src, dst, len, iv);
+  case SILC_CIPHER_MODE_CFB:
+    SILC_CFB_DEC_MSB_64_32(iv, tmp, cast5->padlen, src, dst,
+                          cast5_encrypt(cast5, tmp, tmp));
     break;
 
   default:
@@ -570,8 +581,7 @@ int cast5_setup(const unsigned char *key, int keylen, int num_rounds,
    return TRUE;
 }
 
-#define __ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
-
+#define __ROL(x, y) silc_rol(x, y)
 
 static inline SilcUInt32 FI(SilcUInt32 R, SilcUInt32 Km, SilcUInt32 Kr)
 {