Previous Page
Next Page

8.3. CIPE

CIPE (crypto IP encapsulation) is another lightweight VPN that, like VTun, has some serious security problems. Unlike VTun, CIPE is implemented as a combination of a kernel module and a user-space daemon. Because of the kernel component, CIPE runs only on Linux and Microsoft Windows NT. Information and source code are available at the CIPE home page, <http://sites.inka.de/bigred/devel/cipe.html>.

We discuss CIPE 1.6, the latest version at the time of this writing. There are also two versions of the CIPE protocol. Version 3, which we discuss, tunnels IP datagramsthat is, it operates at the network layer. Version 4 operates at the link layer and can therefore be used to carry any type of interface-layer packet. The version 4 protocol is used mostly to build Ethernet bridges, and we will not discuss it further.

CIPE encapsulates encrypted IP datagrams in UDP datagrams, as shown in Figure 8.6.

Figure 8.6. CIPE Encapsulation


This has an advantage over the VPNs that we built using SSL and SSH in Chapter 6 and Chapter 7, because CIPE tunnels will not have nested TCP connections that interfere with each other and affect throughput. Because the UDP header has unencrypted port fields (Figure 2.14), CIPE can interoperate with NAT/PAT.

Encrypting, UDP encapsulating, and sending and receiving IP datagrams are done in the kernel module, which provides a network device to which IP datagrams are routed. The network devices at the local and remote hosts serve as the endpoints of the tunnel.

The user-space daemon, ciped, controls the configuration, starting, stopping, and key-exchange protocol of the VPN. In addition, ciped can run a script when a VPN is brought up or torn down. This facility is useful for configuring routes and logging.

CIPE has two modes of key negotiation. The first uses a long-lived static key, defined in the configuration file, to encrypt and send a short-lived session key to its peer. The peer does the same, so two session keys are in use during the lifetime of the VPN. The key that one side sends is called the sending key; the key that it receives from its peer is called the receiving key. As the names suggest, an endpoint will encrypt its outgoing packets with the sending key and decrypt its incoming packets with the receiving key. The protocol specifies that the session keys should be used no longer than 15 minutes nor encrypt more than 232 packets. These are the standard precautions intended to deny an attacker a large amount of data encrypted with the same key.

In the second method of key negotiation, the peers use Diffie-Hellman to agree on a key that replaces the long-lived static key. This key is written into the configuration file in place of the static key, and the VPN is brought up as before. The Diffie-Hellman exchange is made under the management of the pkcipe tool, which also rewrites the configuration file after completing the Diffie-Hellman exchange.

Once the peers have negotiated the session keys, IP datagrams delivered to the CIPE device are encrypted, encapsulated in a UDP datagram, and sent to the peer.

Binary Packet Format

We've already seen that CIPE encapsulates IP datagrams by adding a header and footer and placing the result in a UDP datagram. Now we want to look more closely at the header and footer. Together with the IP datagram, the header and the footer make up the CIPE binary packet, as shown in Figure 8.7. The K bit is 0 if the static key was used to encrypt the packet and 1 if the session key was used. The K bit is necessary because no information other than the K bit and IV is visible to the receiver before the packet is decrypted. The rest of the first 64 bits are random data, with the further requirement that bits 131 must not be all 0s. The first 64 bits, including the K bit, are used as an IV for the block encryption algorithm.

Figure 8.7. The CIPE Binary Packet


After the IP datagram itself, 0 to 7 random bytes are added to pad the packet to a size of 3 mod 8. The final 5 bytes comprise the P byte and 4 bytes of CRC-32. The P byte contains a 3-bit padding length field and a 2-bit packet type, as shown in Figure 8.8. The valid packet types are 00 for a data packet and 01 for a key-exchange packet. The other values are reserved.

Figure 8.8. The CIPE P Byte


The padding bytes are weak random bytes generated with a linear congruential random number generator similar to the C library function rand and seeded with bits from the system clock. The IV is generated by first setting bits 031 to a counter, initially 0, and bits 3263 to random bytes, using the same random number generator used for the padding. The resulting 64-bit block is encrypted with the Blowfish algorithm, using a key generated for this specific purpose. The result of the encryption is used as the IV, with bit 0 replaced by the K bit.

This process will be repeated up to five times to get an IV that does not have all 0s in bits 131.

When the counter exceeds 32,767, a new key is calculated for the IV generation process. This key is merely 16 random bytes generated with the same linear congruential algorithm used for the padding and second half of the IV.

Key Negotiation

As the VPN is being brought up, both peers have invalid session keys, so they use either the long-lived static key from the configuration file or the Diffie-Hellman key negotiated by pkcipe for this invocation of the VPN. In either event, this key is used only until a session key is negotiated. The session keys are obtained by reading 16 bytes from /dev/urandom, the Linux high-entropy random number generator.

The random/urandom device gathers entropy from hardware events, such as keystroke timings and device interrupts. This entropy is used to generate high-quality random numbers. If the entropy pool becomes depleted, the urandom interface will supply random numbers that are theoretically vulnerable to cryptographic attack. No such attacks are publicly known, however, and the entropy pool is continually refreshed, so we can probably ignore this weakness for most applications. The random interface will block when there is not enough entropy, so the problem does not exist for it.

The peers negotiate the session keys by the exchange of key-exchange packets (Figure 8.9).

Figure 8.9. The CIPE Key-Exchange Packet


These packets are at least 64 and at most 320 bytes long. A variable amount of random padding is added after the timestamp in an effort to make the identification of key-exchange packets more difficult.

The three types of key-exchange packets are shown in Figure 8.10.

Figure 8.10. Key-Exchange Packet Types

Number

Type

Purpose

1

NK_REQ

requests that peer send new key

2

NK_IND

packet contains new key

3

NK_ACK

confirms receipt of new key


The typical key exchange involves the exchange of four packets. Each side informs the other of the session key it will use as a sending key; the peer receiving this key, its receiving key, acknowledges its receipt by sending an ACK packet. The exchange for one of the session keys is shown in Figure 8.11.

Figure 8.11. CIPE Key-Exchange Protocol


The other peer, the responder in Figure 8.11, initiates a similar exchange to negotiate the other session key. To the sender of an NK_IND packet, the packet contains a sending key; to the receiver of the packet, it contains a receiving key. The NK_ACK packet contains the CRC of the key whose receipt the peer is acknowledging.

If a peer receives a packet with the K bit set but does not have a valid receiving key, it can request its peer to send it a new session key with the NK_REQ packet. In this case, the exchange is like that shown in Figure 8.12.

Figure 8.12. Peer Requests a New Receiving Key


If the sender of an NK_IND packet does not receive an NK_ACK packet within the timeout period, it will send another NK_IND packet with a new key. Recall that key-exchange packets are encapsulated in UDP datagrams, so it's possible that either the NK_IND or the NK_ACK packet could be lost, requiring this resend.

After a peer sends 32,767 packets with a sending key, it invalidates the key and informs its peer of the new key by sending it an NK_IND packet. Similarly, after a key has been used for a specified amount of time10 minutes by defaultthe peer will invalidate the key and send its peer a new key. If a peer receives more than 65,534 packets with the same receiving key or more than twice the key-timeout period has elapsed for the receiving key, the peer will send an NK_REQ packet requesting a new key.

CIPE uses two mechanisms to avoid replay attacks on its key-exchange protocol. First, it remembers the last 256 CRCs from NK_IND packets and will rejectby not ACKinga key having a CRC in the list. A similar check is made for the CRCs in NK_ACK packets.

Second, CIPE places a timestamp in each key-exchange packet (see Figure 8.9). If the difference between the timestamp and the current time exceeds a configured maximum, CIPE will reject the packet. Because this feature requires that the system clocks of the two systems be more or less synchronized, its use is optionalspecifying a timeout of 0 seconds will disable it.

PKCIPE

Since version 1.5, CIPE has had the ability to negotiate its static key on the fly rather than using the long-lived key stored permanently in the configuration file. CIPE does this by means of the pkcipe utility, which negotiates a session-specific static key, using the Diffie-Hellman algorithm.

As does VTun, PKCIPE uses the OpenSSL libraries to handle encryption, random number generation, big-number arithmetic, and the Diffie-Hellman exchange. Also like VTun, PKCIPE does not use the SSL protocol but merely makes use of the cryptographic primitives supplied by the library.

The PKCIPE negotiation takes place over a TCP connection, so the protocol does not have to concern itself with reliability. The PKCIPE protocol accomplishes three main tasks:

  1. Negotiates a static key for this session

  2. Authenticates the peers to each other with RSA

  3. Negotiates session parameters

We will examine each of these functions as we discuss the protocol.

PKCIPE has its own packet format, as shown in Figure 8.13.

Figure 8.13. The PKCIPE Packet Format


The first byte is called the marker and is always 0x2a. The length field is the total length of the type and data fields. Each byte of the length field is exclusive-ORed with 0x50.

The type field identifies the message type carried by the packet. Figure 8.14 shows the values that type can take. The data field carries the payload of the message and depends on the message type.

Figure 8.14. PKCIPE Message Types

Value

Name

Meaning

0

PKT_DEBUG

ignore, but log these messages

1

PKT_ERROR

a protocol error has occurred

2

PKT_DONE

protocol completed successfully

17

PKT_NONCE

nonce used for key generation

18

PKT_DHKEY

Diffie-Hellman public key

19

PKT_IDENT

host identification

20

PKT_SIGN

signature over certain packets

21

PKT_READY

CIPE started

22

PKT_OPT_REQ

option request

67

PKT_MAGIC

identifies the PKCIPE protocol version


The check field is either a 1-byte sum of the type and data fields (PKCIPE version 2) or a 20-byte SHA-1 hash of the type and data fields (PKCIPE version 3).

Figure 8.15 shows the first part of a typical PKCIPE exchange.

Figure 8.15. The PKCIPE Protocol


The PKT_MAGIC packet indicates the highest PKCIPE protocol version that the sender supports. The peers will use the lowest protocol version in these messages. The PKT_MAGIC message itself is sent using protocol version 2 so that either version of the protocol can understand it. The message data consists of an ASCII string of the form CIPE/03 vvvvv xxxxx *, where vvvvv is the PKCIPE program version, and xxxxx is a short description of the version. Notice that the C in CIPE serves as the message type.

Next, the peers exchange nonces. Each nonce is a random number of at least 8 bytes. After the Diffie-Hellman exchange, which comes next, the peers will combine these nonces with the Diffie-Hellman shared secret and use the result for key generation. The PKT_DHKEY messages contain the public keys (gx mod p) from which the peers derive the shared secret. PKCIPE uses a fixed group and generator for the Diffie-Hellman exchange, which are compiled into the PKCIPE binary.

At this point, the peers independently generate three keys. The peers will use two of these to encrypt the remainder of the PKCIPE protocol with RC4 (one key for each direction). The third key is the static key that CIPE will use in place of the long-lived static key from the configuration file.

The key generation is similar to that for TLS (Chapter 6). First, the peers calculate the four constants A0, . . . , A3, where

A0 = (NONCElocal NONCEremote) || padding

Ai = H(secret, Ai-1) (i > 0)

The three keys are then

Ki = H(secret, Ai || A0) (1 i 3)

where NONCElocal and NONCEremote are the local and remote nonces, padding is enough nulls to pad the result of the exclusive-OR to 16 bytes, and H(x, y) is the SHA-1 HMAC of x and y.

Next, the peers identify and authenticate themselves to each other. The protocol exchanges for this are shown in Figure 8.16.

Figure 8.16. Identification and Authentication


At installation time, each peer generates an RSA key pair. The private key is kept locally, and the public key is provided to any peer that the local host might want to connect to. Each peer will send a fingerprint of its public key in the PKT_IDENT message to allow its peer to make a quick check that each side has associated the correct RSA key with its peer.

The PKT_IDENT message data has the form ffffffff iiii...i, where the ffffffff is the fingerprint of the sending peer's public key, and the iiii...i is an arbitrary string identifying the peer.

The "fingerprint" is actually a simple checksum of the modulus of the public key. The checksum is formed by grouping the bytes of the modulus in 4-byte sets, starting with the high-order bytes, and discarding any bytes remaining after the last 4-byte set is formed. These 4-byte sets are then exclusive-ORed together to form the 32-bit checksum.

On receiving the PKT_IDENT message, each side looks up its peer's public key, using the identification string, and verifies that the fingerprint is correct. If so, the peer will sign the PKT_DHKEY and PKT_IDENT packets that it sent and the PKT_NONCE packet that it received. The signature is generated using the RSASSA-V1_5-SIGN operation specified in PKCS #1 [RSA Laboratories 2002]. This signature is sent to the peer in a PKT_SIGN message.

At this point, both peers have identified and authenticated the other side and have generated a static key to use for this session. In the remainder of the protocol, shown in Figure 8.17, the peers negotiate options, start their respective ciped daemons, and terminate the TCP connection.

Figure 8.17. Final Step in the PKCIPE Protocol


With CIPE 1.6.0, the only option is the UDP address that the peer should send its CIPE messages to. This option is necessary because the peer's CIPE address can be different from its PKCIPE address. The address is sent in a PKT_OPT_REQ packet as a string of the form me=aaaa...a, where aaaa...a is the address the peer should use.

After a peer has finished with option negotiation, it will write the static key and other user options to a configuration file and start ciped. After ciped starts, the peer will send a PKT_READY message, telling the other side that it has started its side of the tunnel and that the other side should do the same. When the other side responds with its own PKT_READY, the peer will send a PKT_DONE message and disconnect. At this point, both sides of the tunnel have been started and will be ready for traffic as soon as they finish negotiating their session keys.

Control Messages

A CIPE endpoint can send its peer control messages as well as data. Figure 8.18 lists the seven control messages and their uses.

Figure 8.18. CIPE Control Messages

Value

Name

Use

0x70

CT_DUMMY

a no-op used for keep-alive purposes

0x71

CT_DEBUG

contains a debug message to be logged

0x72

CT_PING

echo request

0x73

CT_PONG

echo reply

0x74

CT_KILL

requests peer to exit

0x75

CT_CONFREQ

informs peer of sender's configuration

0x76

CT_CONF

response to CT_CONFREQ


Control messages are carried in key-exchange packets and except as noted later are encrypted. The CT_DEBUG and CT_KILL messages carry a string that the peer will log. The CT_PING and CT_PONG messages are a method of ensuring that a peer is still reachable. The CT_PING message carries a string, which the peer copies to a CT_PONG message and returns to the sender of the CT_PING.

The CT_CONFREQ message informs the peer of an endpoint's fixed configuration. Figure 8.19 shows the contents of the CT_CONFREQ and CT_CONF messages.

Figure 8.19. CIPE Configuration Message Data

Offset

Value

Meaning

03

filler

ignored

48

CIPE

the ASCII name of the protocol

9

3 or 4

CIPE protocol version

10

"b" or "@"

type of encryption

1112

 

major/minor version number of software

13

0 or 1

broken-key interpretation flag


Except for the type of encryption and broken-key interpretation flag, the items in Figure 8.19 are self-explanatory. By default, CIPE uses Blowfish encryption, in which case the byte at offset 10 will be a "b." CIPE can also be compiled to use the Linux Crypto API for those kernels that support it. In that case, the byte at offset 10 is a "@."

An earlier version of CIPE had a bug in the code that read and interpreted the static key. The code gave the hex digits a through f the values 1 through 6 rather than 10 through 15. The flag at offset 13 is 0 if CIPE was compiled with the broken-key interpretation code and 1 otherwise.

When a peer receives a CT_CONFREQ message, it checks the configuration against its own to make sure that they agree and to warn the user if not. The receiver of the message answers with a CT_CONF message containing its configuration.

The CT_CONFREQ and CT_CONF messages are sent unencrypted because they contain information about what encryption algorithm should be used and because they contain information that the peers should have before it is known whether they have matching static keys. CIPE signals the unencrypted packet by having an IV that is all 0s, including the K bit.

CIPE Security

CIPE was developed when Intel 80386 processors and 2400 bps modems were common hardware, and this fact is reflected in its design. We see this most strikingly in the binary packet format, where several design decisions were made with the limited processing power and bandwidth of the hardware in mind.

The first thing we notice is the use of a CRC-32 checksum instead of a MAC. As we saw before in Chapter 7, this is a serious weakness. We also notice that the CRC really is just a checksum, and not a weak MAC, because no key is associated with it. Although there are no known exploits of this weak integrity checking, the method of [Futoransky, Kargieman, and Pacetti 1998] could probably be used to devise one.

The next problem with the binary packet is the limited padding. Because the P byte (Figure 8.8) uses only 3 bits for the length of the padding, we are restricted to a maximum of 7 bytes. This has some implications. First, it means that we must use a 64-bit block size for our block encryption. As discussed in Chapter 3, most experts agree that a 64-bit block size is too small. In particular, it means that AES and other modern block ciphers are not available for use with CIPE.

Second, it means that it is difficult to hide the true message size and that the VPN is therefore subject to at least limited traffic analysis. For example, we know that key-exchange packets are between 64 and 320 bytes long. If the other traffic in the tunnel has either shorter or longer packets, it is possible to identify and interfere with the key-exchange packets.

Another serious concern with the CIPE protocol is the lack of sequence numbers, which renders CIPE susceptible to replay, deletion, and insertion attacks. This lack is especially serious if the key-exchange packets can be identified, as discussed earlier. In that case, an attacker can prevent key updates; force the use of an old, compromised key; or perhaps even manipulate keys in transit. To some extent, CIPE protects against these attacks with the timestamps and cached key CRCs, but these safeguards aren't foolproof. In any event, we still have the concern that critical packets, such as fund transfer requests, can be replayed.

The decision to omit sequence numbers from CIPE is a consequence of the use of UDP as the transport protocol. As we've seen, this is preferable to using a reliable protocol, such as TCP, because we don't get two reliable protocols competing with each other and adversely affecting throughput. On the other hand, using an unreliable protocol means that packets, and thus their sequence numbers, can be lost or delivered out of order. It's easy to see how this can make using sequence numbers to enhance the security of the protocol difficult. We should note, however, that tinc and OpenVPN, which use UDP encapsulation, and IPsec, which operates at the IP layer, also have unreliable delivery and use sequence numbers to prevent replay and insertion attacks. We will see how this works later in this chapter and in Chapter 11.

Although CIPE is probably more secure than VTun, we should exercise careful consideration before deploying it in any situation that requires serious security. In the absence of active attacks, CIPE appears to provide reasonable privacy, so it could find useful work as a data-cloaking protocol for low-value data transfer. It probably should not be used to carry high-value data or in situations in which active attacks are likely. As always, we must consider the threat model that we are attempting to protect against. There is a further discussion of CIPE security in [Gutmann 2003b].


Previous Page
Next Page