Fixed CTR rekey. Rewrote IV Included CTR mode encryption/decryption silc.toolkit.1.1.4
authorPekka Riikonen <priikone@silcnet.org>
Mon, 5 Nov 2007 20:34:55 +0000 (20:34 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 5 Nov 2007 20:34:55 +0000 (20:34 +0000)
in packet engine.

CHANGES
lib/silccore/silcpacket.c
lib/silcske/silcske.c

diff --git a/CHANGES b/CHANGES
index 95824e06487f1e494b7bf5c1b665a5f5450dd14e..7a495d43cc94da59c8e16cb857290da6c82fb5a6 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,10 @@
+Mon Nov  5 22:24:25 EET 2007  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed CTR mode rekey.  Affected file is lib/silcske/silcske.c.
+
+       * Rewrote the IV Included CTR mode encryption/decryption in
+         packet engine.  Affected file is lib/silccore/silcpacket.c.
+
 Sun Nov  4 15:20:25 EET 2007  Pekka Riikonen <priikone@silcnet.org>
 
        * Removed module_path and module options from the server
index d03f0d8526afe25af61c55af203c050631f2c060..bea6357939731b0db4ba92ed16cda2cab5e83e9d 100644 (file)
@@ -1471,14 +1471,6 @@ static inline void silc_packet_send_ctr_increment(SilcPacketStream stream,
   unsigned char *iv = silc_cipher_get_iv(cipher);
   SilcUInt32 pc1, pc2;
 
-  /* Increment 64-bit packet counter */
-  SILC_GET32_MSB(pc1, iv + 4);
-  SILC_GET32_MSB(pc2, iv + 8);
-  if (++pc2 == 0)
-    ++pc1;
-  SILC_PUT32_MSB(pc1, iv + 4);
-  SILC_PUT32_MSB(pc2, iv + 8);
-
   /* Reset block counter */
   memset(iv + 12, 0, 4);
 
@@ -1489,11 +1481,24 @@ static inline void silc_packet_send_ctr_increment(SilcPacketStream stream,
     ret_iv[1] = ret_iv[0] + iv[4];
     ret_iv[2] = ret_iv[0] ^ ret_iv[1];
     ret_iv[3] = ret_iv[0] + ret_iv[2];
-    SILC_PUT32_MSB(pc2, ret_iv + 4);
+
+    /* Increment 32-bit packet counter */
+    SILC_GET32_MSB(pc1, iv + 8);
+    pc1++;
+    SILC_PUT32_MSB(pc1, ret_iv + 4);
+
     SILC_LOG_HEXDUMP(("IV"), ret_iv, 8);
 
     /* Set new nonce to counter block */
-    memcpy(iv + 4, ret_iv, 4);
+    memcpy(iv + 4, ret_iv, 8);
+  } else {
+    /* Increment 64-bit packet counter */
+    SILC_GET32_MSB(pc1, iv + 4);
+    SILC_GET32_MSB(pc2, iv + 8);
+    if (++pc2 == 0)
+      ++pc1;
+    SILC_PUT32_MSB(pc1, iv + 4);
+    SILC_PUT32_MSB(pc2, iv + 8);
   }
 
   SILC_LOG_HEXDUMP(("Counter Block"), iv, 16);
index 4db209868986ccd79ca41180a0d734e9423479e4..4a407490c4f91305c27b60a01351f04381a2ae0d 100644 (file)
@@ -3312,6 +3312,12 @@ SilcBool silc_ske_set_keys(SilcSKE ske,
       return FALSE;
   }
 
+  /* Allocate hash */
+  if (ret_hash) {
+    if (!silc_hash_alloc(silc_hash_get_name(prop->hash), ret_hash))
+      return FALSE;
+  }
+
   /* Set key material */
   memset(iv, 0, sizeof(iv));
   if (ske->responder) {
@@ -3320,10 +3326,22 @@ SilcBool silc_ske_set_keys(SilcSKE ske,
                          keymat->enc_key_len, TRUE);
 
       if (silc_cipher_get_mode(*ret_send_key) == SILC_CIPHER_MODE_CTR) {
-        memcpy(iv, ske->hash, 4);
-        memcpy(iv + 4, keymat->receive_iv, iv_included ? 4 : 8);
+       /* Counter mode */
+       if (!ske->rekeying) {
+         /* Set IV. */
+         memcpy(iv, ske->hash, 4);
+         if (!iv_included)
+           memcpy(iv + 4, keymat->receive_iv, 8);
+       } else {
+         /* Rekey, recompute the truncated hash value. */
+         silc_hash_make(prop->hash, keymat->receive_iv, 8, iv);
+         if (!iv_included)
+           memcpy(iv + 4, keymat->receive_iv, 8);
+       }
+
         silc_cipher_set_iv(*ret_send_key, iv);
       } else {
+       /* Other modes */
        silc_cipher_set_iv(*ret_send_key, keymat->receive_iv);
       }
     }
@@ -3332,10 +3350,22 @@ SilcBool silc_ske_set_keys(SilcSKE ske,
                          keymat->enc_key_len, FALSE);
 
       if (silc_cipher_get_mode(*ret_receive_key) == SILC_CIPHER_MODE_CTR) {
-        memcpy(iv, ske->hash, 4);
-        memcpy(iv + 4, keymat->send_iv, iv_included ? 4 : 8);
+       /* Counter mode */
+       if (!ske->rekeying) {
+         /* Set IV. */
+         memcpy(iv, ske->hash, 4);
+         if (!iv_included)
+           memcpy(iv + 4, keymat->send_iv, 8);
+       } else {
+         /* Rekey, recompute the truncated hash value. */
+         silc_hash_make(prop->hash, keymat->send_iv, 8, iv);
+         if (!iv_included)
+           memcpy(iv + 4, keymat->send_iv, 8);
+       }
+
         silc_cipher_set_iv(*ret_receive_key, iv);
       } else {
+       /* Other modes */
        silc_cipher_set_iv(*ret_receive_key, keymat->send_iv);
       }
     }
@@ -3351,10 +3381,22 @@ SilcBool silc_ske_set_keys(SilcSKE ske,
                          keymat->enc_key_len, TRUE);
 
       if (silc_cipher_get_mode(*ret_send_key) == SILC_CIPHER_MODE_CTR) {
-        memcpy(iv, ske->hash, 4);
-        memcpy(iv + 4, keymat->send_iv, iv_included ? 4 : 8);
+       /* Counter mode */
+       if (!ske->rekeying) {
+         /* Set IV. */
+         memcpy(iv, ske->hash, 4);
+         if (!iv_included)
+           memcpy(iv + 4, keymat->send_iv, 8);
+       } else {
+         /* Rekey, recompute the truncated hash value. */
+         silc_hash_make(prop->hash, keymat->send_iv, 8, iv);
+         if (!iv_included)
+           memcpy(iv + 4, keymat->send_iv, 8);
+       }
+
        silc_cipher_set_iv(*ret_send_key, iv);
       } else {
+       /* Other modes */
        silc_cipher_set_iv(*ret_send_key, keymat->send_iv);
       }
     }
@@ -3363,10 +3405,23 @@ SilcBool silc_ske_set_keys(SilcSKE ske,
                          keymat->enc_key_len, FALSE);
 
       if (silc_cipher_get_mode(*ret_receive_key) == SILC_CIPHER_MODE_CTR) {
-        memcpy(iv, ske->hash, 4);
-        memcpy(iv + 4, keymat->receive_iv, iv_included ? 4 : 8);
+       /* Counter mode */
+       if (!ske->rekeying) {
+         /* Set IV.  If IV Included flag was negotiated we only set the
+            truncated hash value. */
+         memcpy(iv, ske->hash, 4);
+         if (!iv_included)
+           memcpy(iv + 4, keymat->receive_iv, 8);
+       } else {
+         /* Rekey, recompute the truncated hash value. */
+         silc_hash_make(prop->hash, keymat->receive_iv, 8, iv);
+         if (!iv_included)
+           memcpy(iv + 4, keymat->receive_iv, 8);
+       }
+
        silc_cipher_set_iv(*ret_receive_key, iv);
       } else {
+       /* Other modes */
        silc_cipher_set_iv(*ret_receive_key, keymat->receive_iv);
       }
     }
@@ -3378,12 +3433,6 @@ SilcBool silc_ske_set_keys(SilcSKE ske,
                        keymat->hmac_key_len);
   }
 
-  /* Allocate hash */
-  if (ret_hash) {
-    if (!silc_hash_alloc(silc_hash_get_name(prop->hash), ret_hash))
-      return FALSE;
-  }
-
   return TRUE;
 }