/* * Copyright (C) 2013 Freie Universität Berlin, Computer Systems & Telematics * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level * directory for more details. */ /** * @ingroup sys_crypto * @{ * * @file * @brief Headers of the implementation of the CBC Mode of Operation * * Implementation of the CBC Mode of Operation with Ciphertext-Stealing for encryption. * * @author Freie Universitaet Berlin, Computer Systems & Telematics. * @author Nicolai Schmittberger * @author Zakaria Kasmi */ #include #include #include #include #ifndef CBCMODE_H_ #define CBCMODE_H_ #include "crypto/ciphers.h" #ifdef __cplusplus extern "C" { #endif #define MIN(a, b) ( ((a) < (b)) ? (a) : (b)) #define DBG_CRYPTO 1 enum { // we allocate some static buffers on the stack; they have to be less // than this size CBCMODE_MAX_BLOCK_SIZE = 8, CBCMODE_MAX_BLOCK_SIZE_AES = 16 }; /*// We run a simple state machine in the incremental decrypt: // // +--> ONE_BLOCK // | // ---| // | // +--> GENERAL --+---> TWO_LEFT_A ----> TWO_LEFT_B // ^ | // | | // +------+ */ enum { ONE_BLOCK, GENERAL, TWO_LEFT_A, TWO_LEFT_B }; #define FAIL 0 #define SUCCESS 1 /** * @brief The context for processing the en-/decryption in the CBC-Mode with * CTS * * @param spill1 test1 */ typedef struct CBCModeContext { /** Spill-Block 1 for temporary usage */ uint8_t spill1 [CBCMODE_MAX_BLOCK_SIZE ]; /** Spill-Block 2 for temporary usage */ uint8_t spill2 [CBCMODE_MAX_BLOCK_SIZE ]; /** the blocksize currently used */ uint8_t bsize; /** how many more bytes of ciphertext do we need to recv */ uint16_t remaining; /** how many bytes of plaintext we've deciphered. */ uint16_t completed; /** TRUE iff spill1 is the accumulator and spill2 holds prev cipher text. */ /** false o.w. */ uint8_t accum; /** into the accumulator */ uint8_t offset; /** state enum */ uint8_t state; } /*__attribute__ ((packed)) */ CBCModeContext; /* * @brief Initialize the Mode. It uses the underlying BlockCipher's * preferred block cipher mode, and passes the key and keySize * parameters to the underlying BlockCipher. * * @param context structure to hold the opaque data from this * initialization call. It should be passed to future * invocations of this module which use this particular key. * It also contains the opaque context for the underlying * BlockCipher as well. * @param keySize key size in bytes * @param key pointer to the key * * @return Whether initialization was successful. The command may be * unsuccessful if the key size is not valid for the given cipher * implementation. It can also fail if the preferred block size of * the cipher does not agree with the preferred size of the mode. */ int block_cipher_mode_init(CipherModeContext *context, uint8_t key_size, uint8_t *key); /** * @brief same as BlockCipherMode_init but with the possibility to specify * the index of the cipher in the archive * * @param context structure to hold the opaque data from this * initialization call. It should be passed to future * invocations of this module which use this particular * key. It also contains the opaque context for the * underlying BlockCipher as well. * @param key_size key size in bytes. * @param key pointer to the key. * @param cipher_index the index of the cipher-algorithm to init in the * (cipher-)archive * * @return Whether initialization was successful. The command may be * unsuccessful if the key size is not valid for the given cipher * implementation. It can also fail if the preferred block size of * the cipher does not agree with the preferred size of the mode. */ int block_cipher_mode_init0(CipherModeContext *context, uint8_t key_size, uint8_t *key, uint8_t cipher_index); /** * @brief prints the debug-messages passed by @ref dump_buffer * * @param mode the mode of the debug-message * @param format pointer to the message */ void dbg(uint8_t mode, const char *format, ...); /** * @brief dumps the passed buffer to the console * * @param bufName pointer to the name of the buffer * @param buf pointer to the buffer itself * @param size the size of the buffer in bytes */ void dump_buffer(char *bufName, uint8_t *buf, uint8_t size); /** * @brief Encrypts num_bytes of plaintext blocks (each of size blockSize) * using the key from the init phase. The IV is a pointer to the * initialization vector (of size equal to the blockSize) which is * used to initialize the encryption. * In place encryption should work provided that the plain and and * cipher buffer are the same. (they may either be the same or * non-overlapping. partial overlaps are not supported). * * @param context context object for this encryption * @param plain_blocks a plaintext block numBlocks, where each block is of * blockSize bytes * @param cipher_blocks an array of numBlocks * blockSize bytes to hold the * resulting cyphertext * @param num_bytes number of data blocks to encrypt * @param IV an array of the initialization vector. It should be * of block size bytes * * @return Whether the encryption was successful. Possible failure reasons * include not calling init(). */ int block_cipher_mode_encrypt(CipherModeContext *context, uint8_t *plain_blocks, uint8_t *cipher_blocks, uint16_t num_bytes, uint8_t *IV); /** * @brief Decrypts num_bytes of ciphertext blocks (each of size blockSize) * using the key from the init phase. The IV is a pointer to the * initialization vector (of size equal to the blockSize) which is * used to initialize the decryption. * In place decryption should work provided that the plain and and * cipher buffer are the same. (they may either be the same or * non-overlapping. partial overlaps are not supported). * * @param context context object for this decryption * @param cipher_blocks an array of num_bytes * blockSize bytes that holds * the cipher text * @param plain_blocks an array of num_bytes * blockSize bytes to hold the * resulting plaintext. * @param num_bytes number of data blocks to encrypt * @param IV an array of the initialization vector. It should be * of block size bytes * * @return Whether the decryption was successful. Possible failure reasons * include not calling init(). */ int block_cipher_mode_decrypt(CipherModeContext *context, uint8_t *cipher_blocks, uint8_t *plain_blocks, uint16_t num_bytes, uint8_t *IV); #ifdef __cplusplus } #endif /** @} */ #endif /* CBCMODE_H_ */