Class desfire::cmac_keychain

Class Documentation

class cmac_keychain

Class which holds and derives subkeys to use when computing CMAC.

CMAC as used by Desfire pads and xors the data with two different keys, derived from the cryptographic implementation (by encrypting sequences of zeroes). This class manages the subkeys for CMAC operations.

Public Functions

inline cmac_keychain(std::size_t block_size, std::uint8_t last_byte_xor)

Initialize a new CMAC keychain with zero subkeys.

Parameters:
  • block_size – Size of the block used in the crypto object (8 bytes for 3K3DES, 16 for AES128).

  • last_byte_xor – Used in subkey generation, this is specific to the Desfire implementation. Refer to prepare_subkey for more details; the values used are xor_byte_3k3des for 3K3DES, and xor_byte_aes for AES128.

inline range<std::uint8_t*> key_pad() const

Key to use for messages that need padding.

inline range<std::uint8_t*> key_nopad() const

Key to use for messages that do not need padding.

inline std::size_t block_size() const

Block size of the underlying crypto implementation.

Returns:

The block size in bytes specified in cmac_provider::cmac_provider.

inline std::uint8_t last_byte_xor() const

The value used in subkey generation for the underlying crypto implementation.

Returns:

The value specified in cmac_provider::cmac_provider.

void initialize_subkeys(crypto &crypto)

Recomputes the subkeys.

This method performs the following key-derivation operations:

  1. Call crypto::do_crypto with crypto_operation::mac, a zero-filled IV and a zero-filled data.

  2. Pass the result through prepare_subkey with last_byte_xor. This produces the first key that is used for messages that need padding.

  3. Pass the newly generated key through prepare_subkey again, with last_byte_xor. This produces the second key, that is used for messages that do not need padding.

Note

This method actually performs cryptographic operations via crypto::do_crypto in order to derive the subkeys used in the CMAC operation. This is the reason why it’s not performed automatically in the constructor: the crypto object in the constructor is allowed to not be fully initialized at that point in time. However, it must be fully initialized when this method is called. The rationale is that this class might be used as a member variable in some crypto subclass: since it’s abstract, we first need to initialize the subclass in order to have full access to crypto::do_crypto, and thus we perform delayed subkey initialization.

Parameters:

crypto – Cryptographic implementation to use for deriving the keys. Make sure that the block size matches to what used in the constructor (i.e. block_size).

void prepare_cmac_data(bin_data &data) const

Prepares data for CMAC operation by padding it and XORing with the appropriate key.

This performs a subset of the operations of cmac_provider::compute_cmac, namely:

  1. Pads data with 80 00 .. 00.

  2. XORs the last block with the appropriate key, depending on whether it was padded or not.

Parameters:

data – Data to pad and XOR, modified in-place. Will be resized to a multiple of block_size.

void prepare_cmac_data(bin_data &data, std::size_t desired_padded_length) const

Prepares data for CMAC operation by padding it and XORing with the appropriate key.

This performs a subset of the operations of cmac_provider::compute_cmac, namely:

  1. Pads data with 80 00 .. 00 up to desired_padded_length.

  2. XORs the last block with the appropriate key, depending on whether it was padded or not.

Parameters:
  • data – Data to pad and XOR, modified in-place. Will be resized to a multiple of the block size.

  • desired_padded_length – Minimum length for the padded message. Will be rounded to the next multiple of block_size.

Public Static Functions

static void prepare_subkey(range<std::uint8_t*> subkey, std::uint8_t last_byte_xor)

Transform a cryptogram into a subkey to use for CMACing.

This seems to be something specific to Desfire. First some cryptographic operation is performed, then the result is shifted and if the MSB is 1, the last byte is XORed with last_byte_xor. Maybe it is done to precondition the algorithm to be more resistant?

Parameters:
  • subkey – Cryptogram resulting from running a regular crypto_operation::mac on the appropriate IV. Upon exit, this contains the result (the shift and XOR operations are performed in-place on this range).

  • last_byte_xor – Value that is XORed with the last byte if the MSB of the shifted subkey is 1.

Public Static Attributes

static constexpr auto xor_byte_des = desfire::bits::crypto_cmac_xor_byte_des

Xor byte for DES cipher (presumed).

static constexpr auto xor_byte_2k3des = desfire::bits::crypto_cmac_xor_byte_2k3des

Xor byte for 2K3DES cipher (presumed).

static constexpr auto xor_byte_3k3des = desfire::bits::crypto_cmac_xor_byte_3k3des

Xor byte for 3K3DES cipher.

static constexpr auto xor_byte_aes = desfire::bits::crypto_cmac_xor_byte_aes

Xor byte for AES128 cipher.