Added SILC Thread Queue API
[silc.git] / lib / silccrypt / twofish.c
index c52438125f83fc1cfd7719c5971491fffd7d7933..87d443c7fc91f67e4b8fc1140aa82b6e7040e0d4 100644 (file)
@@ -49,7 +49,7 @@ Mean:          378 cycles =    67.8 mbits/sec
 
 /* Sets the key for the cipher. */
 
-SILC_CIPHER_API_SET_KEY(twofish_cbc)
+SILC_CIPHER_API_SET_KEY(twofish)
 {
   SilcUInt32 k[8];
 
@@ -59,65 +59,96 @@ SILC_CIPHER_API_SET_KEY(twofish_cbc)
   return TRUE;
 }
 
+/* Sets IV for the cipher. */
+
+SILC_CIPHER_API_SET_IV(twofish)
+{
+  TwofishContext *twofish = context;
+
+  switch (cipher->mode) {
+
+  case SILC_CIPHER_MODE_CTR:
+    /* Starts new block. */
+    twofish->padlen = 0;
+    break;
+
+  case SILC_CIPHER_MODE_CFB:
+    /* Starts new block. */
+    twofish->padlen = 16;
+    break;
+
+  default:
+    break;
+  }
+}
+
 /* Returns the size of the cipher context. */
 
-SILC_CIPHER_API_CONTEXT_LEN(twofish_cbc)
+SILC_CIPHER_API_CONTEXT_LEN(twofish)
 {
   return sizeof(TwofishContext);
 }
 
-/* Encrypts with the cipher in CBC mode. Source and destination buffers
-   maybe one and same. */
+/* Encrypts with the cipher. Source and destination buffers maybe one
+   and same. */
 
-SILC_CIPHER_API_ENCRYPT(twofish_cbc)
+SILC_CIPHER_API_ENCRYPT(twofish)
 {
-  SilcUInt32 tiv[4];
+  TwofishContext *twofish = context;
+  SilcUInt32 tmp[4], ctr[4];
   int i;
 
-  SILC_ASSERT((len & (16 - 1)) == 0);
-  if (len & (16 - 1))
-    return FALSE;
-  SILC_CBC_GET_IV(tiv, iv);
+  switch (cipher->mode) {
 
-  SILC_CBC_ENC_PRE(tiv, src);
-  twofish_encrypt((TwofishContext *)context, tiv, tiv);
-  SILC_CBC_ENC_POST(tiv, dst, src);
+  case SILC_CIPHER_MODE_CBC:
+    SILC_CBC_ENC_LSB_128_32(len, iv, tmp, src, dst, i,
+                           twofish_encrypt(twofish, tmp, tmp));
+    break;
 
-  for (i = 16; i < len; i += 16) {
-    SILC_CBC_ENC_PRE(tiv, src);
-    twofish_encrypt((TwofishContext *)context, tiv, tiv);
-    SILC_CBC_ENC_POST(tiv, dst, src);
-  }
+  case SILC_CIPHER_MODE_CTR:
+    SILC_CTR_LSB_128_32(iv, ctr, tmp, twofish->padlen, src, dst,
+                       twofish_encrypt(twofish, tmp, tmp));
+    break;
+
+  case SILC_CIPHER_MODE_CFB:
+    SILC_CFB_ENC_LSB_128_32(iv, tmp, twofish->padlen, src, dst,
+                           twofish_encrypt(twofish, tmp, tmp));
+    break;
 
-  SILC_CBC_PUT_IV(tiv, iv);
+  default:
+    return FALSE;
+  }
 
   return TRUE;
 }
 
-/* Decrypts with the cipher in CBC mode. Source and destination buffers
-   maybe one and same. */
+/* Decrypts with the cipher. Source and destination buffers maybe one
+   and same. */
 
-SILC_CIPHER_API_DECRYPT(twofish_cbc)
+SILC_CIPHER_API_DECRYPT(twofish)
 {
+  TwofishContext *twofish = context;
   SilcUInt32 tmp[4], tmp2[4], tiv[4];
   int i;
 
-  if (len & (16 - 1))
-    return FALSE;
+  switch (cipher->mode) {
 
-  SILC_CBC_GET_IV(tiv, iv);
+  case SILC_CIPHER_MODE_CBC:
+    SILC_CBC_DEC_LSB_128_32(len, iv, tiv, tmp, tmp2, src, dst, i,
+                           twofish_decrypt(twofish, tmp, tmp2));
 
-  SILC_CBC_DEC_PRE(tmp, src);
-  twofish_decrypt((TwofishContext *)context, tmp, tmp2);
-  SILC_CBC_DEC_POST(tmp2, dst, src, tmp, tiv);
+  case SILC_CIPHER_MODE_CTR:
+    return silc_twofish_encrypt(cipher, context, src, dst, len, iv);
+    break;
 
-  for (i = 16; i < len; i += 16) {
-    SILC_CBC_DEC_PRE(tmp, src);
-    twofish_decrypt((TwofishContext *)context, tmp, tmp2);
-    SILC_CBC_DEC_POST(tmp2, dst, src, tmp, tiv);
-  }
+  case SILC_CIPHER_MODE_CFB:
+    SILC_CFB_DEC_LSB_128_32(iv, tmp, twofish->padlen, src, dst,
+                           twofish_encrypt(twofish, tmp, tmp));
+    break;
 
-  SILC_CBC_PUT_IV(tiv, iv);
+  default:
+    return FALSE;
+  }
 
   return TRUE;
 }
@@ -173,7 +204,7 @@ u1byte qp(const u4byte n, const u1byte x)
     a3 = a2 ^ b2; b3 = ror4[b2] ^ ashx[a2];
     a4 = qt2[n][a3]; b4 = qt3[n][b3];
     return (b4 << 4) | a4;
-};
+}
 
 #ifdef  Q_TABLES
 
@@ -190,7 +221,7 @@ void gen_qtab(void)
         q(0,i) = qp(0, (u1byte)i);
         q(1,i) = qp(1, (u1byte)i);
     }
-};
+}
 
 #else
 
@@ -216,7 +247,7 @@ void gen_mtab(void)
         m_tab[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24);
         m_tab[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24);
     }
-};
+}
 
 #define mds(n,x)    m_tab[n][x]
 
@@ -295,7 +326,7 @@ u4byte h_fun(TwofishContext *ctx, const u4byte x, const u4byte key[])
     return b0 | (b3 << 8) | (b2 << 16) | (b1 << 24);
 
 #endif
-};
+}
 
 #ifdef  MK_TABLE
 
@@ -364,7 +395,7 @@ void gen_mk_tab(TwofishContext *ctx, u4byte key[])
 #endif
             }
     }
-};
+}
 
 #  ifdef ONE_STEP
 #    define g0_fun(x) ( mk_tab[0][byte(x,0)] ^ mk_tab[1][byte(x,1)] \
@@ -443,7 +474,7 @@ u4byte mds_rem(u4byte p0, u4byte p1)
     }
 
     return p1;
-};
+}
 
 /* initialise the key schedule from the user supplied key   */
 
@@ -491,7 +522,7 @@ u4byte *twofish_set_key(TwofishContext *ctx,
 #endif
 
     return l_key;
-};
+}
 
 /* encrypt a block of text  */
 
@@ -522,7 +553,7 @@ void twofish_encrypt(TwofishContext *ctx,
     out_blk[1] = blk[3] ^ l_key[5];
     out_blk[2] = blk[0] ^ l_key[6];
     out_blk[3] = blk[1] ^ l_key[7];
-};
+}
 
 /* decrypt a block of text  */
 
@@ -553,4 +584,4 @@ void twofish_decrypt(TwofishContext *ctx,
     out_blk[1] = blk[3] ^ l_key[1];
     out_blk[2] = blk[0] ^ l_key[2];
     out_blk[3] = blk[1] ^ l_key[3];
-};
+}