Modes of Operation

From Crypto++ Wiki
Jump to: navigation, search
Modes of Operation
Documentation
#include <cryptopp/modes.h>

Modes of Operation is a method of operating a block cipher on messages larger than cipher's block size. Crypto++ offers several modes of operation, including ECB, CBC, OFB, CFB, CBC-CTS, CCM, EAX, GCM, OCB. This wiki article will discuss the block cipher modes of operation provided by the library.

Generally speaking there are two categories of modes of operation. The first category is confidentiality-only modes, and they include ECB, CBC, CTR and OFB modes. The second category is authenticated encryption (authenc) modes, and they include CCM, EAX, GCM and OCB mode. Authenc provides both confidentiality and authenticity.

The confidentiality-only modes are found in modes.h. The Authenc modes of operation are in ccm.h, eax.h, gcm.h and ocb.h.

Note: if your project is using encryption alone to secure your data, encryption alone is usually not enough. Please take a moment to read Authenticated Encryption and understand why you should prefer to use CCM, GCM, or EAX over other modes, such as CBC or CTR.

Internal Cipher Modes

All cipher modes in the Crypto++ library provide a mode object that takes a cipher as a template parameter. Most code uses and internal cipher object, where the cipher is part of the mode class. In the example below, the CBC_Mode object has a AES class member, and the internal cipher is specified through a template parameter.

// Operate the cipher in the specified mode
CBC_Mode<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(key, key.size(), iv);

External Cipher Modes

External mode cipher objects allow you to use a separate cipher object for transformations. The library provides CFB_Mode_ExternalCipher, CFB_FIPS_Mode_ExternalCipher, OFB_Mode_ExternalCipher, CTR_Mode_ExternalCipher, ECB_Mode_ExternalCipher, CBC_Mode_ExternalCipher and CBC_CTS_Mode_ExternalCipher classes.

A second way to use a mode of operation is through an external cipher. External ciphers are exactly that what the name implies. Instead of the mode having an internal cipher object, it uses a reference to an external cipher. An example of CBC mode is shown below.

// Notice no mode for cipher
AES::Encryption cipher;
cipher.SetKey(key, key.size());

// Attach a mode of operation
CBC_Mode_ExternalCipher::Encryption encryptor(cipher, iv);

Wide Block Ciphers

Kalyna and Threefish are considered "wide block" block cipher because they use block sizes greater than 128-bits. There are pain points when using wide block ciphers, like incomplete support for some modes of operation. The problem is largely due to missing specifications for the wider block sizes, which means we don't know how to implement an algorithm in a standard way. A side effect is, no specifications lead to missing test vectors.

Examples of missing specifications include missing polynomials for CMAC and GCM modes of operation. It is not enough to simply use a low weight polynomial since there can be multiple primitive polynomials available. We are tracking the missing polynomials at Issue 423, Polynomials for CMAC and GCM mode.

Another example of a missing specification is counter mode operations. The mode could be as simple as using a larger counter, or it could use a zero-extended 128-bit counter. Sometimes the result of counter mode operation is reduced by a primitive polynomial, so it can also suffer missing polynomials detailed in CMAC and GCM.

Yet another example is CCM, EAX and GCM are authenticated encryption modes of operation. The modes produce an authentication tag and the tag has traditionally been the size of the block. In the case of AES, Camellia that's 128-bits and it is sufficient to authenticate the data. In the case of wide blocks we don't know if tags should be extended accordingly. As we understand the latest revision to OCB mode, the tags are not extended.

At this point in time we believe the status of wide block modes of operation are:

  • CMAC - may work, but we don't have test vectors
  • CBC - probably works, we had Kalyna test vectors
  • CTR - probably works, we had Kalyna test vectors
  • EAX - may work, but we don't have test vectors
  • GCM - does not work, we don't have an implementation
  • CCM - probably does not work, we don't have a specification
  • OCB - in progress, not ready for production
  • Others - modes like OFB and CFB probably work

In a few places we said, "probably works, we had Kalyna test vectors". There is a danger we cannot make the leap because Kalyna uses operations specified in DSTU, which is a Ukranian national standard. The standard may be different than what ISO/IEC, NESSIE, NIST or the IETF eventually produce.

Modes of Operation

The following examples show how to key a cipher with a mode. AES is used as an example, but any class that derives from BlockCipher can be used. The examples also use the forward transformation specified as Encryption. Decryption is used the same way as Encryption.

If you forget to specify a direction, Encryption or Decryption, then you will receive an error during compile. For example, the following code:

ECB_Mode<AES> encryptor;
encryptor.SetKey(key, key.size());

Will result in:

error: ‘struct CryptoPP::ECB_Mode<CryptoPP::Rijndael>’ has no member named ‘SetKey’
     encryptor.SetKey(key, key.size());

ECB

ECB mode does not uses an initialization vector. You should use SetKey instead of SetKeyWithIV. For more details on the mode see ECB on the wiki.

SecByteBlock key(AES::DEFAULT_KEYLENGTH);
std::memset(key, 0, key.size());

ECB_Mode<AES>::Encryption encryptor;
encryptor.SetKey(key, key.size());

CBC

CBC mode uses an initialization vector. You should use SetKeyWithIV instead of SetKey. For more details on the mode see CBC on the wiki.

SecByteBlock key(AES::DEFAULT_KEYLENGTH), iv(AES::BLOCKSIZE);
std::memset(key, 0, key.size());
std::memset(iv, 0, iv.size());

CBC_Mode<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(key, key.size(), iv);

OFB

OFB mode uses an initialization vector. You should use SetKeyWithIV instead of SetKey. For more details on the mode see OFB on the wiki.

SecByteBlock key(AES::DEFAULT_KEYLENGTH), iv(AES::BLOCKSIZE);
std::memset(key, 0, key.size());
std::memset(iv, 0, iv.size());

OFB_Mode<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(key, key.size(), iv);

CFB

CFB mode uses an initialization vector. You should use SetKeyWithIV instead of SetKey. For more details on the mode see CFB on the wiki.

SecByteBlock key(AES::DEFAULT_KEYLENGTH), iv(AES::BLOCKSIZE);
std::memset(key, 0, key.size());
std::memset(iv, 0, iv.size());

OFB_Mode<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(key, key.size(), iv);

CBC-CTS

CBC-CTS mode uses an initialization vector. You should use SetKeyWithIV instead of SetKey. For more details on the mode see CBC-CTS on the wiki.

SecByteBlock key(AES::DEFAULT_KEYLENGTH), iv(AES::BLOCKSIZE);
std::memset(key, 0, key.size());
std::memset(iv, 0, iv.size());

OFB_Mode<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(key, key.size(), iv);

CCM

CCM mode uses an initialization vector. You should use SetKeyWithIV instead of SetKey. For more details on the mode see CCM on the wiki.

SecByteBlock key(AES::DEFAULT_KEYLENGTH), iv(AES::BLOCKSIZE);
std::memset(key, 0, key.size());
std::memset(iv, 0, iv.size());

CCM<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(key, key.size(), iv);

EAX

EAX mode uses an initialization vector. You should use SetKeyWithIV instead of SetKey. For more details on the mode see CCM on the wiki.

SecByteBlock key(AES::DEFAULT_KEYLENGTH), iv(AES::BLOCKSIZE);
std::memset(key, 0, key.size());
std::memset(iv, 0, iv.size());

CCM<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(key, key.size(), iv);

GCM

EAX mode uses an initialization vector. You should use SetKeyWithIV instead of SetKey. For more details on the mode see CCM on the wiki.

SecByteBlock key(AES::DEFAULT_KEYLENGTH), iv(AES::BLOCKSIZE);
std::memset(key, 0, key.size());
std::memset(iv, 0, iv.size());

CCM<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(key, key.size(), iv);