Details of the IIP 1.1 protocol bug

User X <[email protected]> Wed, 28 May 2003 15:55:57 +0200
Newsgroups gmane.comp.security.invisiblenet.iip.devel
Message-ID <[email protected]>
As discussed in the last IIP meeting 
http://mids.student.utwente.nl/~mids/iip/meeting44/livelog.txt 
a bug in the implementation of the crypto protocol for IIP 1.1 has 
been found.

This bug causes the outer key to lose 160 bits. It also changes
the way the outer and inner keys are compressed into a session
key.

The outer key provides authetication that a client is connecting
to the correct network. With the current IIP network the public
key length is 1536 bits. With this bug the effective key length
becomes 1376.

The inner key provides the session key.  With the current version
of IIP the key length 2048 bits. This bug does not cause any 
loss to the inner key.


This bug also causes changes in the way a computed shared keys 
are compressed into a session key. 
The hash of the shared key is then placed at the begining of
the shared key overwriting it. The remainder of the shared 
key is then xorred into the hash wrapping as needed.

This behaviour is undesirable but it should have no to very 
little effect on the strength of the session key.


Attached is the IIP 1.1 crypto protocol documentation with the 
implentation bugs added.

-UserX
cs-iip11c.txt (text/plain, 7.5 KB)
Notes:
    This protocol describes IIP 1.1 protocol as it currently runs with
    implentation bugs.
    Lines describing changes caused by a bug are prepended with "(BUG)".

Overview of the protocol:
    1) Do a DH key exchange for the outer key. Any public/private keys are
        used here.
    2) Encrypting with the outer key do a DH key exchange for the inner key.
    3) Encrypt all traffic with the combined inner and outer key.



Outer key:
    The outer key is only used to prove the node is who they say they are.
    Security of any private/public keys only need to last the lifespan
    of the node.

    A DH key exchange is done as described below.
    Public/Private keys SHOULD be used in this exchange.
    encryption/decryption keys are created as described below

Inner key:
    The inner key is used to encrypt actual traffic.
    The security of this key needs to last as long as the data is
    "valuable".

    A DH key exchange is done as described below except
    the exchange is encrypted with the outer key
    Public/Private keys MUST NOT be used in this exchange.
    encryption/decryption keys are added to as described below



DH key exhange:
    1) both ends send the preferred bit length for the outer DH key
        (this is 32 bit big endian integer)
    2) both sides must use the biggest value
    3) both sides creates a private key
        * a node can alternatively use preset one for identification
    4) both sides compute the public key from the private key and
        then sends it
        (this number is sent as a big endian integer,
        byte length = bitlength / 8)
    5) both sides then generate the shared key from this
        * a node can verify the received public key against
            an expected public key
            

Encryption/decryption key set:
    The protocol uses a set of keys which are rotated through regularly
    The number keys in the key set is currently 1.

Creation encryption/decryption keys:
    The keyset is first initialized to zero.
    The new key material is then combined as described below.

    //the keyset if first initialized to zeroes
        uint8 keyset[KEYSETSIZE];
        metset(keyset, 0, KEYSETSIZE);
    //then the new key material is added

Addition encryption/decryption keys:
    (BUG) The first time key material is added the first 20 bytes of
        the key material is zeroed.
    The new key material is then put through a SHA1 hash.
    (BUG) This hash is then placed in the first 20 bytes of the
        key material overwriting it.
    (BUG)(This step is not used) This hash is then xorred into the keyset.
    (BUG)The key material is then xorred into the keyset wrapping when
        it exceeds the keyset length.

Packet format:
    Header:
        2 bytes - big endian CRC 16 of the rest of the packet header
        2 bytes - big endian packet body length
        4 bytes - big endian CRC 32 of the packet's body (padding is
                    not part of the CRC)

        * A packet body length of zero signals that there is new
            key material and to perform a key rotation.
            The packet's body length is actually 20 bytes.
            See below for details of key rotation

    Body:
        x bytes - the data of the packet
        n bytes - padding to bring the body's size upto a multiple 8 bytes
                    (padding is not used in the CRC)


Key rotation:
    After receiving (or sending) the key material of a key rotation
    packet the new key is xorred with the next key in the key set.
    The key set is then rotated.
    (First (current) key becomes last, second (next) key becomes the
    first (current), etc)
    Blowfish is then initialized with the new key on the decryption
    (or encryption if key rotation was sent) side.

    Combine new key material:
        +-------+
        |new key|--+
        +-------+  |
                 (xor)
                   |
        1       2  v
        +-----+ +-----+
        |Key A| |Key B|
        +-----+ +-----+

    Rotate key set:
           +---------+
           |         |
        1  |      2  v
        +-----+   +-----+
        |Key B|<--|Key A|
        +-----+   +-----+
    


Encryption/Decryption:
    Although both encryption/decryption start out with the same key
    it is expected for the two to diverge from each other over time
    thus the encryption and decrpytion must maintain different keysets
    and counters.
    
    
Encryption:
    The encryption's counter is xorred with the data
    and the counter is then "incremented" (see below).

    The encrypted block from the previous encryption is
    xorred with the data.
    (This step is known as CBC)
    (A buffer of zeroes is used if there was no previous block)

    The data is then encrypted using blowfish using the first key
    of the encryption keyset.

                counter       counter       counter
                   |             |             |
        +-------+  |  +-------+  |  +-------+  |
        |  data |  |  |  data |  |  |  data |  |
        +-------+  |  +-------+  |  +-------+  |
            |      |      |      |      |      |
          (xor)<---+    (xor)<---+    (xor)<---+
            |             |             |
     +--->(xor)    +--->(xor)    +--->(xor)
     |      |      |      |      |      |
     |      v      |      v      |      v
     |   /-----\   |   /-----\   |   /-----\
     |  (encrypt)  |  (encrypt)  |  (encrypt)
     |   \-----/   |   \-----/   |   \-----/
     |      |      |      |      |      |
   --+      +------+      +------+      +-----
            |             |             |
            v             v             v
        +-------+     +-------+     +-------+
        |E(data)|     |E(data)|     |E(data)|
        +-------+     +-------+     +-------+

Decryption:
    The data is decrypted using blowfish using the first key
    of the decryption keyset.

    The encrypted block from the previous decryption is
    xorred with the data.
    (This step is known as CBC)
    (A buffer of zeroes is used if there was no previous block)

    The encryption's counter is xorred with the data
    and the counter is then "incremented" (see below).


        +-------+     +-------+     +-------+
        |E(data)|     |E(data)|     |E(data)|
        +-------+     +-------+     +-------+
            |             |             |
   --+      +------+      +------+      +-----
     |      |      |      |      |      |
     |      v      |      v      |      v
     |   /-----\   |   /-----\   |   /-----\
     |  (decrypt)  |  (decrypt)  |  (decrypt)
     |   \-----/   |   \-----/   |   \-----/
     |      |      |      |      |      |
     +--->(xor)    +--->(xor)    +--->(xor)
            |             |             |
          (xor)<---+    (xor)<---+    (xor)<---+
            |      |      |      |      |      |
            v      |      v      |      v      |
        +-------+  |  +-------+  |  +-------+  |
        |  data |  |  |  data |  |  |  data |  |
        +-------+  |  +-------+  |  +-------+  |
                   |             |             |
                counter       counter       counter

Encryption/decryption Counter:
    A counter when first used it set to all zeroes.

    uint8 counter[8] = {0, 0, 0, 0,  0, 0, 0, 0};

    A counter is "incremented" by doing:

    void bigendianIncrement(uint8 *buffer, size_t length);

    bigendianIncrement(counter, 8);
    bigendianIncrement(counter, 7);
    bigendianIncrement(counter, 6);
    bigendianIncrement(counter, 5);
    bigendianIncrement(counter, 4);
    bigendianIncrement(counter, 3);
    bigendianIncrement(counter, 2);
    bigendianIncrement(counter, 1);