mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
218 lines
7.6 KiB
C
218 lines
7.6 KiB
C
/*
|
|
* 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 <nicolai.schmittberger@fu-berlin.de>
|
|
* @author Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
|
|
#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_ */
|