Added CTR mode to AES. Simplified cipher implementation API more.
authorPekka Riikonen <priikone@silcnet.org>
Tue, 19 Dec 2006 18:41:20 +0000 (18:41 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 19 Dec 2006 18:41:20 +0000 (18:41 +0000)
17 files changed:
apps/irssi/silc.conf
lib/silccrypt/aes.c
lib/silccrypt/aes.h
lib/silccrypt/blowfish.c
lib/silccrypt/blowfish.h
lib/silccrypt/cast.c
lib/silccrypt/cast.h
lib/silccrypt/none.c
lib/silccrypt/none.h
lib/silccrypt/rc5.c
lib/silccrypt/rc5.h
lib/silccrypt/silccipher.c
lib/silccrypt/silccipher.h
lib/silccrypt/tests/test_aes.c
lib/silccrypt/twofish.c
lib/silccrypt/twofish.h
lib/silcutil/tests/test_silcfsm.c

index ba405d717cfc4ef0c8f1656911a2790119c2abf1..30cc7c5fe8f677bc1f04e2bd7ac9a157bd785c76 100644 (file)
@@ -208,7 +208,7 @@ statusbar = {
 #
 settings = {
   "server" = {
-    crypto_default_cipher = "aes-256-cbc";
+    crypto_default_cipher = "aes-256-ctr";
     crypto_default_hash = "sha1";
     crypto_default_hmac = "hmac-sha1-96";
   };
index d05bb7684a0bfb717d88ff1c7f0452c19e856256..bb78fd166bf88675fe9e366902c2a58c679686fd 100644 (file)
  * SILC Crypto API for AES
  */
 
+/* CBC mode */
+
 /* Sets the key for the cipher. */
 
-SILC_CIPHER_API_SET_KEY(aes)
+SILC_CIPHER_API_SET_KEY(aes_cbc)
 {
   if (encryption)
     aes_encrypt_key(key, keylen, &((AesContext *)context)->u.enc);
@@ -54,7 +56,7 @@ SILC_CIPHER_API_SET_KEY(aes)
 
 /* Returns the size of the cipher context. */
 
-SILC_CIPHER_API_CONTEXT_LEN(aes)
+SILC_CIPHER_API_CONTEXT_LEN(aes_cbc)
 {
   return sizeof(AesContext);
 }
@@ -62,10 +64,14 @@ SILC_CIPHER_API_CONTEXT_LEN(aes)
 /* Encrypts with the cipher in CBC mode. Source and destination buffers
    maybe one and same. */
 
-SILC_CIPHER_API_ENCRYPT_CBC(aes)
+SILC_CIPHER_API_ENCRYPT(aes_cbc)
 {
   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];
@@ -83,11 +89,14 @@ SILC_CIPHER_API_ENCRYPT_CBC(aes)
 /* Decrypts with the cipher in CBC mode. Source and destination buffers
    maybe one and same. */
 
-SILC_CIPHER_API_DECRYPT_CBC(aes)
+SILC_CIPHER_API_DECRYPT(aes_cbc)
 {
   unsigned char tmp[16];
   int nb = len >> 4;
 
+  if (len & (16 - 1))
+    return FALSE;
+
   while(nb--) {
     memcpy(tmp, src, 16);
     aes_decrypt(src, dst, &((AesContext *)context)->u.dec);
@@ -103,6 +112,78 @@ SILC_CIPHER_API_DECRYPT_CBC(aes)
   return TRUE;
 }
 
+/* CTR mode */
+
+/* Sets the key for the cipher. */
+
+SILC_CIPHER_API_SET_KEY(aes_ctr)
+{
+  AesContext *aes = context;
+  memset(&aes->u.enc, 0, sizeof(aes->u.enc));
+  aes_encrypt_key(key, keylen, &aes->u.enc);
+  return TRUE;
+}
+
+/* Returns the size of the cipher context. */
+
+SILC_CIPHER_API_CONTEXT_LEN(aes_ctr)
+{
+  return sizeof(AesContext);
+}
+
+/* Encrypts with the cipher in CTR mode. Source and destination buffers
+   maybe one and same.  Assumes MSB first ordered counter. */
+
+SILC_CIPHER_API_ENCRYPT(aes_ctr)
+{
+  AesContext *aes = context;
+  SilcUInt32 ctr[4];
+  int i;
+
+  SILC_GET32_MSB(ctr[0], iv);
+  SILC_GET32_MSB(ctr[1], iv + 4);
+  SILC_GET32_MSB(ctr[2], iv + 8);
+  SILC_GET32_MSB(ctr[3], iv + 12);
+
+  i = aes->u.enc.inf.b[2];
+  if (!i)
+    i = 16;
+
+  while (len-- > 0) {
+    if (i == 16) {
+      if (++ctr[3] == 0)
+       if (++ctr[2] == 0)
+         if (++ctr[1] == 0)
+           ++ctr[0];
+
+      SILC_PUT32_MSB(ctr[0], iv);
+      SILC_PUT32_MSB(ctr[1], iv + 4);
+      SILC_PUT32_MSB(ctr[2], iv + 8);
+      SILC_PUT32_MSB(ctr[3], iv + 12);
+
+      aes_encrypt(iv, iv, &aes->u.enc);
+      i = 0;
+    }
+    *dst++ = *src++ ^ iv[i++];
+  }
+  aes->u.enc.inf.b[2] = i;
+
+  SILC_PUT32_MSB(ctr[0], iv);
+  SILC_PUT32_MSB(ctr[1], iv + 4);
+  SILC_PUT32_MSB(ctr[2], iv + 8);
+  SILC_PUT32_MSB(ctr[3], iv + 12);
+
+  return TRUE;
+}
+
+/* Decrypts with the cipher in CTR mode. Source and destination buffers
+   maybe one and same. */
+
+SILC_CIPHER_API_DECRYPT(aes_ctr)
+{
+  return silc_aes_ctr_encrypt(context, src, dst, len, iv);
+}
+
 /****************************************************************************/
 
 #if defined(__cplusplus)
index 18666454861dd49110932dad473eeeaa8a572f51..d5bf528f28c9780706c3187a4ccaf0e54b59caca 100644 (file)
 #define AES_H
 
 /*
- * SILC Crypto API for Rijndael
+ * SILC Crypto API for AES
  */
 
-SILC_CIPHER_API_SET_KEY(aes);
-SILC_CIPHER_API_CONTEXT_LEN(aes);
-SILC_CIPHER_API_ENCRYPT_CBC(aes);
-SILC_CIPHER_API_DECRYPT_CBC(aes);
+SILC_CIPHER_API_SET_KEY(aes_cbc);
+SILC_CIPHER_API_ENCRYPT(aes_cbc);
+SILC_CIPHER_API_DECRYPT(aes_cbc);
+SILC_CIPHER_API_CONTEXT_LEN(aes_cbc);
+SILC_CIPHER_API_SET_KEY(aes_ctr);
+SILC_CIPHER_API_ENCRYPT(aes_ctr);
+SILC_CIPHER_API_DECRYPT(aes_ctr);
+SILC_CIPHER_API_CONTEXT_LEN(aes_ctr);
 
 #endif
index 25b9deab08da1082cbe6a93de645a298562e42b4..860787a330c54574044fb97be8b3e8a464f95091 100644 (file)
@@ -43,7 +43,7 @@
 
 /* Sets the key for the cipher. */
 
-SILC_CIPHER_API_SET_KEY(blowfish)
+SILC_CIPHER_API_SET_KEY(blowfish_cbc)
 {
   blowfish_set_key((BlowfishContext *)context, (unsigned char *)key, keylen);
   return TRUE;
@@ -51,7 +51,7 @@ SILC_CIPHER_API_SET_KEY(blowfish)
 
 /* Returns the size of the cipher context. */
 
-SILC_CIPHER_API_CONTEXT_LEN(blowfish)
+SILC_CIPHER_API_CONTEXT_LEN(blowfish_cbc)
 {
   return sizeof(BlowfishContext);
 }
@@ -59,7 +59,7 @@ SILC_CIPHER_API_CONTEXT_LEN(blowfish)
 /* Encrypts with the cipher in CBC mode. Source and destination buffers
    maybe one and same. */
 
-SILC_CIPHER_API_ENCRYPT_CBC(blowfish)
+SILC_CIPHER_API_ENCRYPT(blowfish_cbc)
 {
   SilcUInt32 tiv[4];
   int i;
@@ -84,7 +84,7 @@ SILC_CIPHER_API_ENCRYPT_CBC(blowfish)
 /* Decrypts with the cipher in CBC mode. Source and destination buffers
    maybe one and same. */
 
-SILC_CIPHER_API_DECRYPT_CBC(blowfish)
+SILC_CIPHER_API_DECRYPT(blowfish_cbc)
 {
   SilcUInt32 tmp[4], tmp2[4], tiv[4];
   int i;
index 6f3db65440d18598c7b32cb3ee38a8b22aada8ff..2a76db06a561803b742fbb8ccf5a599c7cd0ec0f 100644 (file)
@@ -24,9 +24,9 @@
  * SILC Crypto API for Blowfish
  */
 
-SILC_CIPHER_API_SET_KEY(blowfish);
-SILC_CIPHER_API_CONTEXT_LEN(blowfish);
-SILC_CIPHER_API_ENCRYPT_CBC(blowfish);
-SILC_CIPHER_API_DECRYPT_CBC(blowfish);
+SILC_CIPHER_API_SET_KEY(blowfish_cbc);
+SILC_CIPHER_API_CONTEXT_LEN(blowfish_cbc);
+SILC_CIPHER_API_ENCRYPT(blowfish_cbc);
+SILC_CIPHER_API_DECRYPT(blowfish_cbc);
 
 #endif
index 522078871f7b06adb4aa23aa8895a636d33f52c3..e1e1a816ad47fc06f060f79116c0c1a9d71b21ff 100644 (file)
@@ -70,7 +70,7 @@ Mean:          674 cycles =    38.0 mbits/sec
 
 /* Sets the key for the cipher. */
 
-SILC_CIPHER_API_SET_KEY(cast)
+SILC_CIPHER_API_SET_KEY(cast_cbc)
 {
   SilcUInt32 k[8];
 
@@ -82,7 +82,7 @@ SILC_CIPHER_API_SET_KEY(cast)
 
 /* Returns the size of the cipher context. */
 
-SILC_CIPHER_API_CONTEXT_LEN(cast)
+SILC_CIPHER_API_CONTEXT_LEN(cast_cbc)
 {
   return sizeof(CastContext);
 }
@@ -90,11 +90,15 @@ SILC_CIPHER_API_CONTEXT_LEN(cast)
 /* Encrypts with the cipher in CBC mode. Source and destination buffers
    maybe one and same. */
 
-SILC_CIPHER_API_ENCRYPT_CBC(cast)
+SILC_CIPHER_API_ENCRYPT(cast_cbc)
 {
   SilcUInt32 tiv[4];
   int i;
 
+  SILC_ASSERT((len & (16 - 1)) == 0);
+  if (len & (16 - 1))
+    return FALSE;
+
   SILC_CBC_GET_IV(tiv, iv);
 
   SILC_CBC_ENC_PRE(tiv, src);
@@ -115,11 +119,14 @@ SILC_CIPHER_API_ENCRYPT_CBC(cast)
 /* Decrypts with the cipher in CBC mode. Source and destination buffers
    maybe one and same. */
 
-SILC_CIPHER_API_DECRYPT_CBC(cast)
+SILC_CIPHER_API_DECRYPT(cast_cbc)
 {
   SilcUInt32 tmp[4], tmp2[4], tiv[4];
   int i;
 
+  if (len & (16 - 1))
+    return FALSE;
+
   SILC_CBC_GET_IV(tiv, iv);
 
   SILC_CBC_DEC_PRE(tmp, src);
index 0630628a496571bf489885b46680ba3fa5913116..092a1cf05718f27507b54be8a234a790e6af15ef 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1999 - 2000 Pekka Riikonen
+  Copyright (C) 1999 - 2000, 2006 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -24,9 +24,9 @@
  * SILC Crypto API for Cast-256
  */
 
-SILC_CIPHER_API_SET_KEY(cast);
-SILC_CIPHER_API_CONTEXT_LEN(cast);
-SILC_CIPHER_API_ENCRYPT_CBC(cast);
-SILC_CIPHER_API_DECRYPT_CBC(cast);
+SILC_CIPHER_API_SET_KEY(cast_cbc);
+SILC_CIPHER_API_CONTEXT_LEN(cast_cbc);
+SILC_CIPHER_API_ENCRYPT(cast_cbc);
+SILC_CIPHER_API_DECRYPT(cast_cbc);
 
 #endif
index 3c45849a9eaa3609961e5b50b4771c215f7ca837..d8b790121c5af70cb382c64e9527edbb586f8a85 100644 (file)
@@ -34,13 +34,13 @@ SILC_CIPHER_API_CONTEXT_LEN(none)
   return 1;
 }
 
-SILC_CIPHER_API_ENCRYPT_CBC(none)
+SILC_CIPHER_API_ENCRYPT(none)
 {
   memcpy(dst, src, len);
   return TRUE;
 }
 
-SILC_CIPHER_API_DECRYPT_CBC(none)
+SILC_CIPHER_API_DECRYPT(none)
 {
   memcpy(dst, src, len);
   return TRUE;
index 261b1c16fdbde874092113e61f8208b40f71e1f7..b0f3a38ba602be8bf3767981c921438a0aec8fdb 100644 (file)
   GNU General Public License for more details.
 
 */
-/*
- * $Id$
- * $Log$
- * Revision 1.3  2006/12/15 15:22:48  priikone
- *     Added assembler AES for x86 and x86_64.
- *     Simplified Cipher implementation API.
- *
- * Revision 1.2  2005/05/10 18:31:17  priikone
- *     Merged silc_1_0_branch to trunk.
- *
- * Revision 1.1.1.1.4.1  2005/04/30 15:31:26  priikone
- *     Header changes.
- *
- * Revision 1.1.1.1  2000/06/27 11:36:54  priikone
- *     Importet from internal CVS/Added Log headers.
- *
- *
- */
 
 #ifndef NONE_H
 #define NONE_H
@@ -44,7 +26,7 @@
 
 SILC_CIPHER_API_SET_KEY(none);
 SILC_CIPHER_API_CONTEXT_LEN(none);
-SILC_CIPHER_API_ENCRYPT_CBC(none);
-SILC_CIPHER_API_DECRYPT_CBC(none);
+SILC_CIPHER_API_ENCRYPT(none);
+SILC_CIPHER_API_DECRYPT(none);
 
 #endif
index 30c5dffd396075c05a3fe137976607e3bb8b66b3..ea377c5814e10ce2a507f85ec33943d7f3326714 100644 (file)
@@ -48,7 +48,7 @@
 
 /* Sets the key for the cipher. */
 
-SILC_CIPHER_API_SET_KEY(rc5)
+SILC_CIPHER_API_SET_KEY(rc5_cbc)
 {
   SilcUInt32 k[8];
 
@@ -60,7 +60,7 @@ SILC_CIPHER_API_SET_KEY(rc5)
 
 /* Returns the size of the cipher context. */
 
-SILC_CIPHER_API_CONTEXT_LEN(rc5)
+SILC_CIPHER_API_CONTEXT_LEN(rc5_cbc)
 {
   return sizeof(RC5Context);
 }
@@ -68,7 +68,7 @@ SILC_CIPHER_API_CONTEXT_LEN(rc5)
 /* Encrypts with the cipher in CBC mode. Source and destination buffers
    maybe one and same. */
 
-SILC_CIPHER_API_ENCRYPT_CBC(rc5)
+SILC_CIPHER_API_ENCRYPT(rc5_cbc)
 {
   SilcUInt32 tiv[4];
   int i;
@@ -93,7 +93,7 @@ SILC_CIPHER_API_ENCRYPT_CBC(rc5)
 /* Decrypts with the cipher in CBC mode. Source and destination buffers
    maybe one and same. */
 
-SILC_CIPHER_API_DECRYPT_CBC(rc5)
+SILC_CIPHER_API_DECRYPT(rc5_cbc)
 {
   SilcUInt32 tmp[4], tmp2[4], tiv[4];
   int i;
index ea36d8089e984621cbe0aaa68cbaeb68c7b4eb6c..d269c66118d0e0f4bc294ed12b4f6c39bfb2fe97 100644 (file)
@@ -24,9 +24,9 @@
  * SILC Crypto API for RC5
  */
 
-SILC_CIPHER_API_SET_KEY(rc5);
-SILC_CIPHER_API_CONTEXT_LEN(rc5);
-SILC_CIPHER_API_ENCRYPT_CBC(rc5);
-SILC_CIPHER_API_DECRYPT_CBC(rc5);
+SILC_CIPHER_API_SET_KEY(rc5_cbc);
+SILC_CIPHER_API_CONTEXT_LEN(rc5_cbc);
+SILC_CIPHER_API_ENCRYPT(rc5_cbc);
+SILC_CIPHER_API_DECRYPT(rc5_cbc);
 
 #endif
index 1832566fec29c45286b3a926c316f63f779746c8..e967e831bc0076ac81dd63f4019543ebd08da8a1 100644 (file)
@@ -33,50 +33,31 @@ struct SilcCipherStruct {
 SilcDList silc_cipher_list = NULL;
 #endif /* SILC_EPOC */
 
+/* Macro to define cipher to cipher list */
+#define SILC_CIPHER_API_DEF(name, cipher, keylen, blocklen, ivlen)     \
+{ name, silc_##cipher##_set_key, silc_##cipher##_encrypt,              \
+  silc_##cipher##_decrypt, silc_##cipher##_context_len,                        \
+  keylen, blocklen, ivlen }
+
 /* Static list of ciphers for silc_cipher_register_default(). */
 const SilcCipherObject silc_default_ciphers[] =
 {
-  { "aes-256-cbc", silc_aes_set_key,
-    silc_aes_encrypt_cbc, silc_aes_decrypt_cbc, silc_aes_context_len,
-    256, 16, 16 },
-  { "aes-192-cbc", silc_aes_set_key,
-    silc_aes_encrypt_cbc, silc_aes_decrypt_cbc, silc_aes_context_len,
-    192, 16, 16 },
-  { "aes-128-cbc", silc_aes_set_key,
-    silc_aes_encrypt_cbc, silc_aes_decrypt_cbc, silc_aes_context_len,
-    128, 16, 16 },
-  { "twofish-256-cbc", silc_twofish_set_key,
-    silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
-    silc_twofish_context_len,
-    256, 16, 16 },
-  { "twofish-192-cbc", silc_twofish_set_key,
-    silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
-    silc_twofish_context_len,
-    192, 16, 16 },
-  { "twofish-128-cbc", silc_twofish_set_key,
-    silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
-    silc_twofish_context_len,
-    128, 16, 16 },
-  { "cast-256-cbc", silc_cast_set_key,
-    silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
-    silc_cast_context_len,
-    256, 16, 16 },
-  { "cast-192-cbc", silc_cast_set_key,
-    silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
-    silc_cast_context_len,
-    192, 16, 16 },
-  { "cast-128-cbc", silc_cast_set_key,
-    silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
-    silc_cast_context_len,
-    128, 16, 16 },
+  SILC_CIPHER_API_DEF("aes-256-ctr", aes_ctr, 256, 16, 16),
+  SILC_CIPHER_API_DEF("aes-192-ctr", aes_ctr, 192, 16, 16),
+  SILC_CIPHER_API_DEF("aes-128-ctr", aes_ctr, 128, 16, 16),
+  SILC_CIPHER_API_DEF("aes-256-cbc", aes_cbc, 256, 16, 16),
+  SILC_CIPHER_API_DEF("aes-192-cbc", aes_cbc, 192, 16, 16),
+  SILC_CIPHER_API_DEF("aes-128-cbc", aes_cbc, 128, 16, 16),
+  SILC_CIPHER_API_DEF("twofish-256-cbc", twofish_cbc, 256, 16, 16),
+  SILC_CIPHER_API_DEF("twofish-192-cbc", twofish_cbc, 192, 16, 16),
+  SILC_CIPHER_API_DEF("twofish-128-cbc", twofish_cbc, 128, 16, 16),
+  SILC_CIPHER_API_DEF("cast-256-cbc", cast_cbc, 256, 16, 16),
+  SILC_CIPHER_API_DEF("cast-192-cbc", cast_cbc, 192, 16, 16),
+  SILC_CIPHER_API_DEF("cast-128-cbc", cast_cbc, 128, 16, 16),
 #ifdef SILC_DEBUG
-  { "none", silc_none_set_key,
-    silc_none_encrypt_cbc, silc_none_decrypt_cbc,
-    silc_none_context_len,
-    0, 0, 0 },
+  SILC_CIPHER_API_DEF("none", none, 0, 0, 0),
 #endif /* SILC_DEBUG */
-
-  { NULL, NULL, NULL, NULL, NULL, 0, 0, 0 }
+  { NULL, NULL, 0, 0, 0 }
 };
 
 /* Register a new cipher into SILC. This is used at the initialization of
@@ -311,9 +292,6 @@ SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
                             unsigned char *dst, SilcUInt32 len,
                             unsigned char *iv)
 {
-  SILC_ASSERT((len & (cipher->cipher->block_len - 1)) == 0);
-  if (silc_unlikely(len & (cipher->cipher->block_len - 1)))
-    return FALSE;
   return cipher->cipher->encrypt(cipher->context, src, dst, len,
                                 iv ? iv : cipher->iv);
 }
@@ -324,8 +302,6 @@ SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
                             unsigned char *dst, SilcUInt32 len,
                             unsigned char *iv)
 {
-  if (silc_unlikely(len & (cipher->cipher->block_len - 1)))
-    return FALSE;
   return cipher->cipher->decrypt(cipher->context, src, dst, len,
                                 iv ? iv : cipher->iv);
 }
index c020d280414688a7ad0579acb3ef0ac973d5636a..3c557f2321d68aefb0a4bac6329449fadafc1c61 100644 (file)
@@ -51,9 +51,9 @@ typedef struct {
   char *name;
   SilcBool (*set_key)(void *, const unsigned char *, SilcUInt32, SilcBool);
   SilcBool (*encrypt)(void *, const unsigned char *, unsigned char *,
-                 SilcUInt32, unsigned char *);
+                     SilcUInt32, unsigned char *);
   SilcBool (*decrypt)(void *, const unsigned char *, unsigned char *,
-                 SilcUInt32, unsigned char *);
+                     SilcUInt32, unsigned char *);
   SilcUInt32 (*context_len)();
   unsigned int key_len   : 12;
   unsigned int block_len : 10;
@@ -79,31 +79,34 @@ extern DLLAPI const SilcCipherObject silc_default_ciphers[];
    of the module. All SILC Crypto API compliant modules must support
    these function names (use macros below to assure this). */
 #define SILC_CIPHER_SIM_SET_KEY "set_key"
-#define SILC_CIPHER_SIM_ENCRYPT_CBC "encrypt_cbc"
-#define SILC_CIPHER_SIM_DECRYPT_CBC "decrypt_cbc"
+#define SILC_CIPHER_SIM_ENCRYPT "encrypt"
+#define SILC_CIPHER_SIM_DECRYPT "decrypt"
 #define SILC_CIPHER_SIM_CONTEXT_LEN "context_len"
+#define SILC_CIPHER_SIM_SET_IV "set_iv"
 
 /* These macros can be used to implement the SILC Crypto API and to avoid
    errors in the API these macros should be used always. */
-#define SILC_CIPHER_API_SET_KEY(cipher)                        \
+#define SILC_CIPHER_API_SET_KEY(cipher)                                \
 SilcBool silc_##cipher##_set_key(void *context,                \
-                            const unsigned char *key,  \
-                            SilcUInt32 keylen,         \
-                            SilcBool encryption)
-#define SILC_CIPHER_API_ENCRYPT_CBC(cipher)                    \
-SilcBool silc_##cipher##_encrypt_cbc(void *context,                    \
+                                const unsigned char *key,      \
+                                SilcUInt32 keylen,             \
+                                SilcBool encryption)
+#define SILC_CIPHER_API_ENCRYPT(cipher)                        \
+SilcBool silc_##cipher##_encrypt(void *context,                \
                                 const unsigned char *src,      \
-                                unsigned char *dst,            \
+                                unsigned char *dst,            \
                                 SilcUInt32 len,                \
-                                unsigned char *iv)
-#define SILC_CIPHER_API_DECRYPT_CBC(cipher)                    \
-SilcBool silc_##cipher##_decrypt_cbc(void *context,                    \
-                                const unsigned char *src,      \
+                                unsigned char *iv)
+#define SILC_CIPHER_API_DECRYPT(cipher)                                \
+SilcBool silc_##cipher##_decrypt(void *context,                \
+                                const unsigned char *src,      \
                                 unsigned char *dst,            \
                                 SilcUInt32 len,                \
                                 unsigned char *iv)
-#define SILC_CIPHER_API_CONTEXT_LEN(cipher)                    \
+#define SILC_CIPHER_API_CONTEXT_LEN(cipher)    \
 SilcUInt32 silc_##cipher##_context_len()
+#define SILC_CIPHER_API_SET_IV(cipher) \
+SilcBool silc_##cipher##_set_iv(void *context, const unsigned char *iv)
 
 /* Prototypes */
 
index 1048cc5173eaec438233e060723c2b9b5b587306..0a104598a4d215bb977993de7901e75d4290c56c 100644 (file)
@@ -19,11 +19,36 @@ const unsigned char p2[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c
 int p2_len = 32;
 const unsigned char c2[] = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a\x3a\x86\x30\x28\xb5\xe1\xdc\x0a\x75\x86\x60\x2d\x25\x3c\xff\xf9\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1";
 
+/* CTR test vectors from RFC3686. */
+
+/* 16 bytes plaintext, 128 bits key */
+const unsigned char key3[] = "\xAE\x68\x52\xF8\x12\x10\x67\xCC\x4B\xF7\xA5\x76\x55\x77\xF3\x9E";
+int key3_len = 16 * 8;
+const unsigned char iv3[] = "\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+const unsigned char p3[] = "Single block msg";
+int p3_len = 16;
+const unsigned char c3[] = "\xE4\x09\x5D\x4F\xB7\xA7\xB3\x79\x2D\x61\x75\xA3\x26\x13\x11\xB8";
+
+/* 32 bytes plaintext, 128 bits key */
+const unsigned char key4[] = "\x7E\x24\x06\x78\x17\xFA\xE0\xD7\x43\xD6\xCE\x1F\x32\x53\x91\x63";
+int key4_len = 16 * 8;
+const unsigned char iv4[] = "\x00\x6C\xB6\xDB\xC0\x54\x3B\x59\xDA\x48\xD9\x0B\x00\x00\x00\x00";
+const unsigned char p4[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
+int p4_len = 32;
+const unsigned char c4[] = "\x51\x04\xA1\x06\x16\x8A\x72\xD9\x79\x0D\x41\xEE\x8E\xDA\xD3\x88\xEB\x2E\x1E\xFC\x46\xDA\x57\xC8\xFC\xE6\x30\xDF\x91\x41\xBE\x28";
+
+/* 36 bytes plaintext, 256 bits key */
+const unsigned char key5[] = "\xFF\x7A\x61\x7C\xE6\x91\x48\xE4\xF1\x72\x6E\x2F\x43\x58\x1D\xE2\xAA\x62\xD9\xF8\x05\x53\x2E\xDF\xF1\xEE\xD6\x87\xFB\x54\x15\x3D";
+int key5_len = 32 * 8;
+const unsigned char iv5[] = "\x00\x1C\xC5\xB7\x51\xA5\x1D\x70\xA1\xC1\x11\x48\x00\x00\x00\x00";
+const unsigned char p5[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23";
+int p5_len = 36;
+const unsigned char c5[] = "\xEB\x6C\x52\x82\x1D\x0B\xBB\xF7\xCE\x75\x94\x46\x2A\xCA\x4F\xAA\xB4\x07\xDF\x86\x65\x69\xFD\x07\xF4\x8C\xC0\xB5\x83\xD6\x07\x1F\x1E\xC0\xE6\xB8";
 
 int main(int argc, char **argv)
 {
   SilcBool success = FALSE;
-  SilcCipher cipher;
+  SilcCipher cipher, cipher2;
   unsigned char dst[256], pdst[256];
   int i;
 
@@ -36,23 +61,23 @@ int main(int argc, char **argv)
   SILC_LOG_DEBUG(("Registering builtin hash functions"));
   silc_cipher_register_default();
 
-  if (!silc_cipher_is_supported("aes-128-cbc")) {
-    SILC_LOG_DEBUG(("aes-128-cbc is not supported"));
-    goto err;
-  }
-
   SILC_LOG_DEBUG(("Allocating AES-CBC cipher"));
   if (!silc_cipher_alloc("aes-128-cbc", &cipher)) {
     SILC_LOG_DEBUG(("Allocating AES-CBC cipher failed"));
     goto err;
   }
+  if (!silc_cipher_alloc("aes-128-cbc", &cipher2)) {
+    SILC_LOG_DEBUG(("Allocating AES-CBC cipher failed"));
+    goto err;
+  }
 
   /* First test vector */
   SILC_LOG_DEBUG(("First test vector"));
   memset(dst, 0, sizeof(dst));
   memset(pdst, 0, sizeof(pdst));
   silc_cipher_set_iv(cipher, iv1);
-  assert(silc_cipher_set_key(cipher, key1, key1_len));
+  assert(silc_cipher_set_key(cipher, key1, key1_len, TRUE));
+  assert(silc_cipher_set_key(cipher2, key1, key1_len, FALSE));
   assert(silc_cipher_encrypt(cipher, p1, dst, p1_len, NULL));
   SILC_LOG_DEBUG(("block len %d, key len %d, name %s",
                 silc_cipher_get_block_len(cipher),
@@ -66,8 +91,8 @@ int main(int argc, char **argv)
     goto err;
   }
   SILC_LOG_DEBUG(("Encrypt is successful"));
-  silc_cipher_set_iv(cipher, iv1);
-  assert(silc_cipher_decrypt(cipher, dst, pdst, p1_len, NULL));
+  silc_cipher_set_iv(cipher2, iv1);
+  assert(silc_cipher_decrypt(cipher2, dst, pdst, p1_len, NULL));
   SILC_LOG_HEXDUMP(("Decrypted plaintext"), (unsigned char *)pdst, p1_len);
   SILC_LOG_HEXDUMP(("Expected plaintext"), (unsigned char *)p1, p1_len);
   if (memcmp(pdst, p1, p1_len)) {
@@ -82,7 +107,8 @@ int main(int argc, char **argv)
   memset(dst, 0, sizeof(dst));
   memset(pdst, 0, sizeof(pdst));
   silc_cipher_set_iv(cipher, iv2);
-  assert(silc_cipher_set_key(cipher, key2, key2_len));
+  assert(silc_cipher_set_key(cipher, key2, key2_len, TRUE));
+  assert(silc_cipher_set_key(cipher2, key2, key2_len, FALSE));
   assert(silc_cipher_encrypt(cipher, p2, dst, p2_len, NULL));
   SILC_LOG_DEBUG(("block len %d, key len %d, name %s",
                 silc_cipher_get_block_len(cipher),
@@ -96,8 +122,8 @@ int main(int argc, char **argv)
     goto err;
   }
   SILC_LOG_DEBUG(("Encrypt is successful"));
-  silc_cipher_set_iv(cipher, iv2);
-  assert(silc_cipher_decrypt(cipher, dst, pdst, p2_len, NULL));
+  silc_cipher_set_iv(cipher2, iv2);
+  assert(silc_cipher_decrypt(cipher2, dst, pdst, p2_len, NULL));
   SILC_LOG_HEXDUMP(("Decrypted plaintext"), (unsigned char *)pdst, p2_len);
   SILC_LOG_HEXDUMP(("Expected plaintext"), (unsigned char *)p2, p2_len);
   if (memcmp(pdst, p2, p2_len)) {
@@ -105,6 +131,116 @@ int main(int argc, char **argv)
     goto err;
   }
   SILC_LOG_DEBUG(("Decrypt is successful"));
+  silc_cipher_free(cipher);
+  silc_cipher_free(cipher2);
+
+
+  SILC_LOG_DEBUG(("Allocating aes-128-ctr cipher"));
+  if (!silc_cipher_alloc("aes-128-ctr", &cipher)) {
+    SILC_LOG_DEBUG(("Allocating aes-128-ctr cipher failed"));
+    goto err;
+  }
+
+  /* Third test vector */
+  SILC_LOG_DEBUG(("Third test vector"));
+  memset(dst, 0, sizeof(dst));
+  memset(pdst, 0, sizeof(pdst));
+  silc_cipher_set_iv(cipher, iv3);
+  assert(silc_cipher_set_key(cipher, key3, key3_len, TRUE));
+  assert(silc_cipher_encrypt(cipher, p3, dst, p3_len, NULL));
+  SILC_LOG_DEBUG(("block len %d, key len %d, name %s",
+                silc_cipher_get_block_len(cipher),
+                silc_cipher_get_key_len(cipher),
+                silc_cipher_get_name(cipher)));
+  SILC_LOG_HEXDUMP(("Plaintext"), (unsigned char *)p3, p3_len);
+  SILC_LOG_HEXDUMP(("Ciphertext"), (unsigned char *)dst, p3_len);
+  SILC_LOG_HEXDUMP(("Expected ciphertext"), (unsigned char *)c3, p3_len);
+  if (memcmp(dst, c3, p3_len)) {
+    SILC_LOG_DEBUG(("Encrypt failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Encrypt is successful"));
+  silc_cipher_set_iv(cipher, iv3);
+  assert(silc_cipher_decrypt(cipher, dst, pdst, p3_len, NULL));
+  SILC_LOG_HEXDUMP(("Decrypted plaintext"), (unsigned char *)pdst, p3_len);
+  SILC_LOG_HEXDUMP(("Expected plaintext"), (unsigned char *)p3, p3_len);
+  if (memcmp(pdst, p3, p3_len)) {
+    SILC_LOG_DEBUG(("Decrypt failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Decrypt is successful"));
+
+
+  /* Fourth test vector */
+  SILC_LOG_DEBUG(("Fourth test vector"));
+  memset(dst, 0, sizeof(dst));
+  memset(pdst, 0, sizeof(pdst));
+  silc_cipher_set_iv(cipher, iv4);
+  assert(silc_cipher_set_key(cipher, key4, key4_len, TRUE));
+  assert(silc_cipher_encrypt(cipher, p4, dst, p4_len, NULL));
+  SILC_LOG_DEBUG(("block len %d, key len %d, name %s",
+                silc_cipher_get_block_len(cipher),
+                silc_cipher_get_key_len(cipher),
+                silc_cipher_get_name(cipher)));
+  SILC_LOG_HEXDUMP(("Plaintext"), (unsigned char *)p4, p4_len);
+  SILC_LOG_HEXDUMP(("Ciphertext"), (unsigned char *)dst, p4_len);
+  SILC_LOG_HEXDUMP(("Expected ciphertext"), (unsigned char *)c4, p4_len);
+  if (memcmp(dst, c4, p4_len)) {
+    SILC_LOG_DEBUG(("Encrypt failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Encrypt is successful"));
+  silc_cipher_set_iv(cipher, iv4);
+  assert(silc_cipher_decrypt(cipher, dst, pdst, p4_len, NULL));
+  SILC_LOG_HEXDUMP(("Decrypted plaintext"), (unsigned char *)pdst, p4_len);
+  SILC_LOG_HEXDUMP(("Expected plaintext"), (unsigned char *)p4, p4_len);
+  if (memcmp(pdst, p4, p4_len)) {
+    SILC_LOG_DEBUG(("Decrypt failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Decrypt is successful"));
+  silc_cipher_free(cipher);
+
+  SILC_LOG_DEBUG(("Allocating aes-256-ctr cipher"));
+  if (!silc_cipher_alloc("aes-256-ctr", &cipher)) {
+    SILC_LOG_DEBUG(("Allocating aes-256-ctr cipher failed"));
+    goto err;
+  }
+  if (!silc_cipher_alloc("aes-256-ctr", &cipher2)) {
+    SILC_LOG_DEBUG(("Allocating aes-256-ctr cipher failed"));
+    goto err;
+  }
+
+  /* Fifth test vector */
+  SILC_LOG_DEBUG(("Fifth test vector"));
+  memset(dst, 0, sizeof(dst));
+  memset(pdst, 0, sizeof(pdst));
+  silc_cipher_set_iv(cipher, iv5);
+  assert(silc_cipher_set_key(cipher, key5, key5_len, TRUE));
+  assert(silc_cipher_set_key(cipher2, key5, key5_len, FALSE));
+  assert(silc_cipher_encrypt(cipher, p5, dst, p5_len, NULL));
+  SILC_LOG_DEBUG(("block len %d, key len %d, name %s",
+                silc_cipher_get_block_len(cipher),
+                silc_cipher_get_key_len(cipher),
+                silc_cipher_get_name(cipher)));
+  SILC_LOG_HEXDUMP(("Plaintext"), (unsigned char *)p5, p5_len);
+  SILC_LOG_HEXDUMP(("Ciphertext"), (unsigned char *)dst, p5_len);
+  SILC_LOG_HEXDUMP(("Expected ciphertext"), (unsigned char *)c5, p5_len);
+  if (memcmp(dst, c5, p5_len)) {
+    SILC_LOG_DEBUG(("Encrypt failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Encrypt is successful"));
+  silc_cipher_set_iv(cipher2, iv5);
+  assert(silc_cipher_decrypt(cipher2, dst, pdst, p5_len, NULL));
+  SILC_LOG_HEXDUMP(("Decrypted plaintext"), (unsigned char *)pdst, p5_len);
+  SILC_LOG_HEXDUMP(("Expected plaintext"), (unsigned char *)p5, p5_len);
+  if (memcmp(pdst, p5, p5_len)) {
+    SILC_LOG_DEBUG(("Decrypt failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Decrypt is successful"));
+  silc_cipher_free(cipher2);
 
   success = TRUE;
 
index e388a951caf083baff2150a90fe7365d68718d02..c52438125f83fc1cfd7719c5971491fffd7d7933 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)
+SILC_CIPHER_API_SET_KEY(twofish_cbc)
 {
   SilcUInt32 k[8];
 
@@ -61,7 +61,7 @@ SILC_CIPHER_API_SET_KEY(twofish)
 
 /* Returns the size of the cipher context. */
 
-SILC_CIPHER_API_CONTEXT_LEN(twofish)
+SILC_CIPHER_API_CONTEXT_LEN(twofish_cbc)
 {
   return sizeof(TwofishContext);
 }
@@ -69,11 +69,14 @@ SILC_CIPHER_API_CONTEXT_LEN(twofish)
 /* Encrypts with the cipher in CBC mode. Source and destination buffers
    maybe one and same. */
 
-SILC_CIPHER_API_ENCRYPT_CBC(twofish)
+SILC_CIPHER_API_ENCRYPT(twofish_cbc)
 {
   SilcUInt32 tiv[4];
   int i;
 
+  SILC_ASSERT((len & (16 - 1)) == 0);
+  if (len & (16 - 1))
+    return FALSE;
   SILC_CBC_GET_IV(tiv, iv);
 
   SILC_CBC_ENC_PRE(tiv, src);
@@ -94,11 +97,14 @@ SILC_CIPHER_API_ENCRYPT_CBC(twofish)
 /* Decrypts with the cipher in CBC mode. Source and destination buffers
    maybe one and same. */
 
-SILC_CIPHER_API_DECRYPT_CBC(twofish)
+SILC_CIPHER_API_DECRYPT(twofish_cbc)
 {
   SilcUInt32 tmp[4], tmp2[4], tiv[4];
   int i;
 
+  if (len & (16 - 1))
+    return FALSE;
+
   SILC_CBC_GET_IV(tiv, iv);
 
   SILC_CBC_DEC_PRE(tmp, src);
index 2f67d7ab514e3aa3dc387262b8fd08224de5f877..ba845960c0d6c4a8208659fe59f5c2b435aed306 100644 (file)
@@ -24,9 +24,9 @@
  * SILC Crypto API for Twofish
  */
 
-SILC_CIPHER_API_SET_KEY(twofish);
-SILC_CIPHER_API_CONTEXT_LEN(twofish);
-SILC_CIPHER_API_ENCRYPT_CBC(twofish);
-SILC_CIPHER_API_DECRYPT_CBC(twofish);
+SILC_CIPHER_API_SET_KEY(twofish_cbc);
+SILC_CIPHER_API_CONTEXT_LEN(twofish_cbc);
+SILC_CIPHER_API_ENCRYPT(twofish_cbc);
+SILC_CIPHER_API_DECRYPT(twofish_cbc);
 
 #endif
index 04cd98067711dc29014b8ade1128ca17a4fd11bd..df11891ba2bb90c1b817355a51340a9c8fc96dcf 100644 (file)
@@ -386,43 +386,6 @@ int main(int argc, char **argv)
     silc_log_set_debug_string("*fsm*,*async*");
   }
 
-{
-#define SSILC_GET32_MSB(l, cp)                         \
-do {                                                   \
-  (l) = ((SilcUInt32)(SilcUInt8)(cp)[3]) << 24         \
-    | ((SilcUInt32)(SilcUInt8)(cp)[2] << 16)           \
-    | ((SilcUInt32)(SilcUInt8)(cp)[1] << 8)            \
-    | ((SilcUInt32)(SilcUInt8)(cp)[0]);                        \
-} while(0)
-  unsigned char tmp[8], tmp2[8];
-  SilcUInt32 t1, t2, t3, t4;
-
-  tmp[0] = 0x11;
-  tmp[1] = 0x22;
-  tmp[2] = 0x33;
-  tmp[3] = 0x44;
-  tmp[4] = 0x55;
-  tmp[5] = 0x66;
-  tmp[6] = 0x77;
-  tmp[7] = 0x88;
-
-  SILC_LOG_HEXDUMP(("DATA"), tmp, 4);
-
-  SILC_GET32_LSB(t1, tmp);
-  SILC_LOG_DEBUG(("GET_LSB: %x", t1));
-  
-  SSILC_GET32_MSB(t1, tmp);
-  SILC_LOG_DEBUG(("GET_MSB: %x", t1));
-
-  SILC_PUT32_LSB(t1, tmp2);
-  SILC_LOG_HEXDUMP(("PUT_LSB"), tmp2, 4);
-
-  SILC_PUT32_MSB(t1, tmp2);
-  SILC_LOG_HEXDUMP(("PUT_MSB"), tmp2, 4);
-
-  exit(1);
-}
-
   SILC_LOG_DEBUG(("Allocating scheduler"));
   schedule = silc_schedule_init(0, NULL);