mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Unified Cipher API and Block cipher operation modes
This commit is contained in:
parent
5813db3249
commit
4a4235c622
@ -110,6 +110,9 @@ endif
|
||||
ifneq (,$(filter ng_nomac,$(USEMODULE)))
|
||||
DIRS += net/link_layer/ng_nomac
|
||||
endif
|
||||
ifneq (,$(filter cipher_modes,$(USEMODULE)))
|
||||
DIRS += crypto/modes
|
||||
endif
|
||||
ifneq (,$(filter ng_pktbuf,$(USEMODULE)))
|
||||
DIRS += net/crosslayer/ng_pktbuf
|
||||
endif
|
||||
|
@ -44,14 +44,15 @@
|
||||
/**
|
||||
* @brief Interface to the 3DES cipher
|
||||
*/
|
||||
block_cipher_interface_t tripledes_interface = {
|
||||
"3DES",
|
||||
static const cipher_interface_t tripledes_interface = {
|
||||
THREEDES_BLOCK_SIZE,
|
||||
THREEDES_MAX_KEY_SIZE,
|
||||
tripledes_init,
|
||||
tripledes_encrypt,
|
||||
tripledes_decrypt,
|
||||
tripledes_setup_key,
|
||||
tripledes_get_preferred_block_size
|
||||
tripledes_decrypt
|
||||
};
|
||||
const cipher_id_t CIPHER_3DES = &tripledes_interface;
|
||||
|
||||
|
||||
/**
|
||||
* @brief struct for the 3DES key expansion
|
||||
@ -247,15 +248,14 @@ static const uint32_t SP8[64] = {
|
||||
};
|
||||
|
||||
|
||||
int tripledes_init(cipher_context_t *context, uint8_t blockSize, uint8_t keySize,
|
||||
uint8_t *key)
|
||||
int tripledes_init(cipher_context_t *context, const uint8_t *key,
|
||||
uint8_t keySize)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
//printf("%-40s: Entry\r\n", __FUNCTION__);
|
||||
// 16 byte blocks only
|
||||
if (blockSize != THREEDES_BLOCK_SIZE) {
|
||||
printf("%-40s: blockSize != 3DES_BLOCK_SIZE...\r\n", __FUNCTION__);
|
||||
// Make sure that context is large enough. If this is not the case,
|
||||
// you should build with -DTHREEDES
|
||||
if(CIPHER_MAX_CONTEXT_SIZE < THREEDES_MAX_KEY_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -275,14 +275,7 @@ int tripledes_init(cipher_context_t *context, uint8_t blockSize, uint8_t keySize
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tripledes_setup_key(cipher_context_t *context, uint8_t *key,
|
||||
uint8_t keysize) //To change !!!
|
||||
{
|
||||
return tripledes_init(context, tripledes_get_preferred_block_size(),
|
||||
keysize, key);
|
||||
}
|
||||
|
||||
int tripledes_encrypt(cipher_context_t *context, uint8_t *plain, uint8_t *crypt)
|
||||
int tripledes_encrypt(const cipher_context_t *context, const uint8_t *plain, uint8_t *crypt)
|
||||
{
|
||||
int res;
|
||||
struct des3_key_s *key = malloc(sizeof(des3_key_s));
|
||||
@ -317,7 +310,7 @@ int tripledes_encrypt(cipher_context_t *context, uint8_t *plain, uint8_t *crypt)
|
||||
}
|
||||
|
||||
|
||||
int tripledes_decrypt(cipher_context_t *context, uint8_t *crypt, uint8_t *plain)
|
||||
int tripledes_decrypt(const cipher_context_t *context, const uint8_t *crypt, uint8_t *plain)
|
||||
{
|
||||
int res;
|
||||
struct des3_key_s *key = malloc(sizeof(des3_key_s));
|
||||
@ -351,11 +344,6 @@ int tripledes_decrypt(cipher_context_t *context, uint8_t *crypt, uint8_t *plain)
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t tripledes_get_preferred_block_size(void)
|
||||
{
|
||||
return THREEDES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
static void cookey(const uint32_t *raw1, uint32_t *keyout)
|
||||
{
|
||||
uint32_t *cook;
|
||||
|
@ -40,14 +40,14 @@
|
||||
/**
|
||||
* Interface to the aes cipher
|
||||
*/
|
||||
block_cipher_interface_t aes_interface = {
|
||||
"AES",
|
||||
static const cipher_interface_t aes_interface = {
|
||||
AES_BLOCK_SIZE,
|
||||
AES_KEY_SIZE,
|
||||
aes_init,
|
||||
aes_encrypt,
|
||||
aes_decrypt,
|
||||
aes_setup_key,
|
||||
aes_get_preferred_block_size
|
||||
aes_decrypt
|
||||
};
|
||||
const cipher_id_t CIPHER_AES_128 = &aes_interface;
|
||||
|
||||
static const u32 Te0[256] = {
|
||||
0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
|
||||
@ -720,27 +720,25 @@ static const u32 rcon[] = {
|
||||
};
|
||||
|
||||
|
||||
int aes_init(cipher_context_t *context, uint8_t blockSize, uint8_t keySize,
|
||||
uint8_t *key)
|
||||
int aes_init(cipher_context_t *context, const uint8_t *key, uint8_t keySize)
|
||||
{
|
||||
//printf("%-40s: Entry\r\n", __FUNCTION__);
|
||||
// 16 byte blocks only
|
||||
if (blockSize != AES_BLOCK_SIZE) {
|
||||
printf("%-40s: blockSize != AES_BLOCK_SIZE...\r\n", __FUNCTION__);
|
||||
uint8_t i;
|
||||
|
||||
// Make sure that context is large enough. If this is not the case,
|
||||
// you should build with -DAES
|
||||
if(CIPHER_MAX_CONTEXT_SIZE < AES_KEY_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t i;
|
||||
|
||||
//key must be at least CIPHERS_KEYSIZE Bytes long
|
||||
if (keySize < CIPHERS_KEYSIZE) {
|
||||
//key must be at least CIPHERS_MAX_KEY_SIZE Bytes long
|
||||
if (keySize < CIPHERS_MAX_KEY_SIZE) {
|
||||
//fill up by concatenating key to as long as needed
|
||||
for (i = 0; i < CIPHERS_KEYSIZE; i++) {
|
||||
for (i = 0; i < CIPHERS_MAX_KEY_SIZE; i++) {
|
||||
context->context[i] = key[(i % keySize)];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < CIPHERS_KEYSIZE; i++) {
|
||||
for (i = 0; i < CIPHERS_MAX_KEY_SIZE; i++) {
|
||||
context->context[i] = key[i];
|
||||
}
|
||||
}
|
||||
@ -748,11 +746,6 @@ int aes_init(cipher_context_t *context, uint8_t blockSize, uint8_t keySize,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int aes_setup_key(cipher_context_t *context, uint8_t *key, uint8_t keysize)
|
||||
{
|
||||
return aes_init(context, aes_get_preferred_block_size(), keysize, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand the cipher key into the encryption key schedule.
|
||||
*/
|
||||
@ -943,7 +936,7 @@ static int aes_set_decrypt_key(const unsigned char *userKey, const int bits,
|
||||
* Encrypt a single block
|
||||
* in and out can overlap
|
||||
*/
|
||||
int aes_encrypt(cipher_context_t *context, uint8_t *plainBlock,
|
||||
int aes_encrypt(const cipher_context_t *context, const uint8_t *plainBlock,
|
||||
uint8_t *cipherBlock)
|
||||
{
|
||||
//setup AES_KEY
|
||||
@ -1202,7 +1195,7 @@ int aes_encrypt(cipher_context_t *context, uint8_t *plainBlock,
|
||||
* Decrypt a single block
|
||||
* in and out can overlap
|
||||
*/
|
||||
int aes_decrypt(cipher_context_t *context, uint8_t *cipherBlock,
|
||||
int aes_decrypt(const cipher_context_t *context, const uint8_t *cipherBlock,
|
||||
uint8_t *plainBlock)
|
||||
{
|
||||
//setup AES_KEY
|
||||
@ -1458,9 +1451,4 @@ int aes_decrypt(cipher_context_t *context, uint8_t *cipherBlock,
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t aes_get_preferred_block_size(void)
|
||||
{
|
||||
return AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
#endif /* AES_ASM */
|
||||
|
50
sys/crypto/ciphers.c
Normal file
50
sys/crypto/ciphers.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
*
|
||||
* 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 ciphers.c
|
||||
* @author Nico von Geyso <nico.geyso@fu-berlin.de>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "crypto/ciphers.h"
|
||||
|
||||
|
||||
int cipher_init(cipher_t* cipher, cipher_id_t cipher_id, const uint8_t* key,
|
||||
uint8_t key_size)
|
||||
{
|
||||
if (key_size > cipher_id->max_key_size) {
|
||||
return CIPHER_ERR_INVALID_KEY_SIZE;
|
||||
}
|
||||
|
||||
cipher->interface = cipher_id;
|
||||
return cipher->interface->init(&cipher->context, key, key_size);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int cipher_encrypt(const cipher_t* cipher, const uint8_t* input, uint8_t* output)
|
||||
{
|
||||
return cipher->interface->encrypt(&cipher->context, input, output);
|
||||
}
|
||||
|
||||
|
||||
int cipher_decrypt(const cipher_t* cipher, const uint8_t* input, uint8_t* output)
|
||||
{
|
||||
return cipher->interface->decrypt(&cipher->context, input, output);
|
||||
}
|
||||
|
||||
|
||||
int cipher_get_block_size(const cipher_t* cipher)
|
||||
{
|
||||
return cipher->interface->block_size;
|
||||
}
|
@ -8,6 +8,42 @@
|
||||
|
||||
/**
|
||||
* @defgroup sys_crypto Crypto
|
||||
* @ingroup sys
|
||||
* @brief The crypto module is a lose collection of different crypto and hash algorithms
|
||||
* @brief RIOT provides a collection of block cipher ciphers, different
|
||||
operation modes and cryptographic hash algorithms.
|
||||
*
|
||||
* \section ciphers Ciphers
|
||||
*
|
||||
* Riot supports the following block ciphers:
|
||||
* * AES-128
|
||||
* * 3DES
|
||||
* * Twofish
|
||||
* * Skipjack
|
||||
* * NULL
|
||||
*
|
||||
* You can use them directly by adding "crypto" to your USEMODULE-List.
|
||||
* While you can use the ciphers functions directly, you should resort to
|
||||
* the generic API for block ciphers whenever possible.
|
||||
*
|
||||
* Example:
|
||||
* \code
|
||||
* #include "crypto/ciphers.h"
|
||||
*
|
||||
* ciphter_t cipher;
|
||||
* uint8_t key[16] = {0}, plain_text[16] = {0}, cipher_text[16] = {0};
|
||||
*
|
||||
* if (cipher_init(&cipher, CIPHER_AES_128, key, key_len) < 0)
|
||||
* printf("Cipher init failed!\n");
|
||||
*
|
||||
* if (cipher_encrypt(&cipher, plain_text, cipher_text) < 0)
|
||||
* printf("Cipher encryption!\n");
|
||||
* \endcode
|
||||
*
|
||||
* If you need to encrypt data of arbitrary size take a look at the different
|
||||
* operation modes like: CBC, CTR or CCM.
|
||||
*
|
||||
* Additional examples can be found in the test suite.
|
||||
*
|
||||
* \section hashes Hashes
|
||||
*
|
||||
* RIOT currently supports sha256 as a cryptographic hash implementation.
|
||||
*/
|
||||
|
35
sys/crypto/helper.c
Normal file
35
sys/crypto/helper.c
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Nico von Geyso <nico.geyso@fu-berlin.de>
|
||||
* Copyright (C) 2015 René Kijewski <rene.kijewski@fu-berlin.de>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "crypto/helper.h"
|
||||
|
||||
void crypto_block_inc_ctr(uint8_t block[16], int L)
|
||||
{
|
||||
uint8_t *b = &block[15];
|
||||
for (int i = 0; i < L; ++i, --b) {
|
||||
if (++*b != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int crypto_equals(uint8_t *a, uint8_t *b, size_t len)
|
||||
{
|
||||
uint8_t diff = 0;
|
||||
for (size_t i = 0; i < len; ++i, ++a, ++b) {
|
||||
diff |= (*a ^ *b);
|
||||
}
|
||||
|
||||
diff |= (diff >> 1) | (diff << 7);
|
||||
diff |= (diff >> 2) | (diff << 6);
|
||||
diff |= (diff >> 4) | (diff << 4);
|
||||
++diff;
|
||||
|
||||
return diff;
|
||||
}
|
2
sys/crypto/modes/Makefile
Normal file
2
sys/crypto/modes/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
MODULE = cipher_modes
|
||||
include $(RIOTBASE)/Makefile.base
|
88
sys/crypto/modes/cbc.c
Normal file
88
sys/crypto/modes/cbc.c
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
*
|
||||
* 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_modes
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Crypto mode - cipher block chaining
|
||||
*
|
||||
* @author Nico von Geyso <nico.geyso@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include "crypto/modes/cbc.h"
|
||||
|
||||
int cipher_encrypt_cbc(cipher_t* cipher, uint8_t iv[16],
|
||||
uint8_t* input, size_t length, uint8_t* output)
|
||||
{
|
||||
size_t offset = 0;
|
||||
uint8_t block_size, input_block[CIPHER_MAX_BLOCK_SIZE] = {0},
|
||||
*output_block_last;
|
||||
|
||||
block_size = cipher_get_block_size(cipher);
|
||||
if (length % block_size != 0) {
|
||||
return CIPHER_ERR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
output_block_last = iv;
|
||||
do {
|
||||
/* CBC-Mode: XOR plaintext with ciphertext of (n-1)-th block */
|
||||
memcpy(input_block, input + offset, block_size);
|
||||
for (int i = 0; i < block_size; ++i) {
|
||||
input_block[i] ^= output_block_last[i];
|
||||
}
|
||||
|
||||
if (cipher_encrypt(cipher, input_block, output + offset) != 1) {
|
||||
return CIPHER_ERR_ENC_FAILED;
|
||||
}
|
||||
|
||||
output_block_last = output + offset;
|
||||
offset += block_size;
|
||||
} while (offset < length);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
int cipher_decrypt_cbc(cipher_t* cipher, uint8_t iv[16],
|
||||
uint8_t* input, size_t length, uint8_t* output)
|
||||
{
|
||||
size_t offset = 0;
|
||||
uint8_t* input_block, *output_block, *input_block_last, block_size;
|
||||
|
||||
|
||||
block_size = cipher_get_block_size(cipher);
|
||||
if (length % block_size != 0) {
|
||||
return CIPHER_ERR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
input_block_last = iv;
|
||||
do {
|
||||
input_block = input + offset;
|
||||
output_block = output + offset;
|
||||
|
||||
if (cipher_decrypt(cipher, input_block, output_block) != 1) {
|
||||
return CIPHER_ERR_DEC_FAILED;
|
||||
}
|
||||
|
||||
/* CBC-Mode: XOR plaintext with ciphertext of (n-1)-th block */
|
||||
for (uint8_t i = 0; i < block_size; ++i) {
|
||||
output_block[i] ^= input_block_last[i];
|
||||
}
|
||||
|
||||
input_block_last = input_block;
|
||||
offset += block_size;
|
||||
} while (offset < length);
|
||||
|
||||
return offset;
|
||||
}
|
257
sys/crypto/modes/ccm.c
Normal file
257
sys/crypto/modes/ccm.c
Normal file
@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
*
|
||||
* 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_modes
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Crypto mode - counter with CBC-MAC
|
||||
*
|
||||
* @author Nico von Geyso <nico.geyso@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "debug.h"
|
||||
#include "crypto/helper.h"
|
||||
#include "crypto/modes/ctr.h"
|
||||
#include "crypto/modes/ccm.h"
|
||||
|
||||
static inline int min(int a, int b)
|
||||
{
|
||||
if (a < b) {
|
||||
return a;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
int ccm_compute_cbc_mac(cipher_t* cipher, uint8_t iv[16],
|
||||
uint8_t* input, size_t length, uint8_t* mac)
|
||||
{
|
||||
uint8_t offset, block_size, mac_enc[16] = {0};
|
||||
|
||||
block_size = cipher_get_block_size(cipher);
|
||||
memcpy(mac, iv, 16);
|
||||
offset = 0;
|
||||
do {
|
||||
uint8_t block_size_input = (length - offset > block_size) ?
|
||||
block_size : length - offset;
|
||||
|
||||
/* CBC-Mode: XOR plaintext with ciphertext of (n-1)-th block */
|
||||
for (int i = 0; i < block_size_input; ++i) {
|
||||
mac[i] ^= input[offset + i];
|
||||
}
|
||||
|
||||
if (cipher_encrypt(cipher, mac, mac_enc) != 1) {
|
||||
return CIPHER_ERR_ENC_FAILED;
|
||||
}
|
||||
|
||||
memcpy(mac, mac_enc, block_size);
|
||||
offset += block_size_input;
|
||||
} while (offset < length);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
int ccm_create_mac_iv(cipher_t* cipher, uint8_t auth_data_len, uint8_t M,
|
||||
uint8_t L, uint8_t* nonce, uint8_t nonce_len,
|
||||
size_t plaintext_len, uint8_t X1[16])
|
||||
{
|
||||
uint8_t M_, L_;
|
||||
|
||||
/* ensure everything is set to zero */
|
||||
memset(X1, 0, 16);
|
||||
|
||||
/* set flags in B[0] - bit format:
|
||||
7 6 5..3 2..0
|
||||
Reserved Adata M_ L_ */
|
||||
M_ = (M - 2) / 2;
|
||||
L_ = L - 1;
|
||||
X1[0] = 64 * (auth_data_len > 0) + 8 * M_ + L_;
|
||||
|
||||
/* copy nonce to B[1..15-L] */
|
||||
memcpy(&X1[1], nonce, min(nonce_len, 15 - L));
|
||||
|
||||
/* write plaintext_len to B[15..16-L] */
|
||||
for (uint8_t i = 15; i > 16 - L; --i) {
|
||||
X1[i] = plaintext_len & 0xff;
|
||||
plaintext_len >>= 8;
|
||||
}
|
||||
|
||||
/* if there is still data, plaintext_len was too big */
|
||||
if (plaintext_len > 0) {
|
||||
return CIPHER_ERR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
if (cipher_encrypt(cipher, X1, X1) != 1) {
|
||||
return CIPHER_ERR_ENC_FAILED;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ccm_compute_adata_mac(cipher_t* cipher, uint8_t* auth_data,
|
||||
uint32_t auth_data_len, uint8_t X1[16])
|
||||
{
|
||||
if (auth_data_len > 0) {
|
||||
int len;
|
||||
|
||||
/* 16 octet block size + max. 10 len encoding */
|
||||
uint8_t auth_data_encoded[26], len_encoding = 0;
|
||||
|
||||
if ( auth_data_len < (((uint32_t) 2) << 16)) { /* length (0x0001 ... 0xFEFF) */
|
||||
len_encoding = 2;
|
||||
|
||||
auth_data_encoded[1] = auth_data_len & 0xFF;
|
||||
auth_data_encoded[0] = (auth_data_len >> 8) & 0xFF;
|
||||
} else {
|
||||
DEBUG("UNSUPPORTED Adata length");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(auth_data_encoded + len_encoding, auth_data, auth_data_len);
|
||||
len = ccm_compute_cbc_mac(cipher, X1, auth_data_encoded, auth_data_len + len_encoding, X1);
|
||||
if (len < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cipher_encrypt_ccm(cipher_t* cipher, uint8_t* auth_data, uint32_t auth_data_len,
|
||||
uint8_t mac_length, uint8_t length_encoding,
|
||||
uint8_t* nonce, size_t nonce_len,
|
||||
uint8_t* input, size_t input_len,
|
||||
uint8_t* output)
|
||||
{
|
||||
int len = -1;
|
||||
uint32_t length_max;
|
||||
uint8_t nonce_counter[16] = {0}, mac_iv[16] = {0}, mac[16] = {0},
|
||||
stream_block[16] = {0}, zero_block[16] = {0}, block_size;
|
||||
|
||||
if (mac_length % 2 != 0 || mac_length < 4 || mac_length > 16) {
|
||||
return CCM_ERR_INVALID_MAC_LENGTH;
|
||||
}
|
||||
|
||||
length_max = 2 << (8 * length_encoding);
|
||||
if (length_encoding < 2 || length_encoding > 8 ||
|
||||
input_len - auth_data_len > length_max) {
|
||||
return CCM_ERR_INVALID_LENGTH_ENCODING;
|
||||
}
|
||||
|
||||
/* Create B0, encrypt it (X1) and use it as mac_iv */
|
||||
block_size = cipher_get_block_size(cipher);
|
||||
if (ccm_create_mac_iv(cipher, auth_data_len, mac_length, length_encoding,
|
||||
nonce, nonce_len, input_len, mac_iv) < 0) {
|
||||
return CCM_ERR_INVALID_DATA_LENGTH;
|
||||
}
|
||||
|
||||
/* MAC calulation (T) with additional data and plaintext */
|
||||
ccm_compute_adata_mac(cipher, auth_data, auth_data_len, mac_iv);
|
||||
len = ccm_compute_cbc_mac(cipher, mac_iv, input, input_len, mac);
|
||||
if (len < 0) {
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Compute first stream block */
|
||||
nonce_counter[0] = length_encoding - 1;
|
||||
memcpy(&nonce_counter[1], nonce,
|
||||
min(nonce_len, (size_t) 15 - length_encoding));
|
||||
len = cipher_encrypt_ctr(cipher, nonce_counter, block_size,
|
||||
zero_block, block_size, stream_block);
|
||||
if (len < 0) {
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Encrypt message in counter mode */
|
||||
crypto_block_inc_ctr(nonce_counter, block_size - nonce_len);
|
||||
len = cipher_encrypt_ctr(cipher, nonce_counter, nonce_len, input,
|
||||
input_len, output);
|
||||
if (len < 0) {
|
||||
return len;
|
||||
}
|
||||
|
||||
/* auth value: mac ^ first stream block */
|
||||
for (uint8_t i = 0; i < mac_length; ++i) {
|
||||
output[len + i] = mac[i] ^ stream_block[i];
|
||||
}
|
||||
|
||||
return len + mac_length;
|
||||
}
|
||||
|
||||
|
||||
int cipher_decrypt_ccm(cipher_t* cipher, uint8_t* auth_data,
|
||||
uint32_t auth_data_len, uint8_t mac_length,
|
||||
uint8_t length_encoding, uint8_t* nonce, size_t nonce_len,
|
||||
uint8_t* input, size_t input_len, uint8_t* plain)
|
||||
{
|
||||
int len = -1;
|
||||
uint32_t length_max;
|
||||
uint8_t nonce_counter[16] = {0}, mac_iv[16] = {0}, mac[16] = {0},
|
||||
mac_recv[16] = {0}, stream_block[16] = {0}, zero_block[16] = {0},
|
||||
plain_len, block_size;
|
||||
|
||||
if (mac_length % 2 != 0 || mac_length < 4 || mac_length > 16) {
|
||||
return CCM_ERR_INVALID_MAC_LENGTH;
|
||||
}
|
||||
|
||||
length_max = 2 << (8 * length_encoding);
|
||||
if (length_encoding < 2 || length_encoding > 8 ||
|
||||
input_len - auth_data_len > length_max) {
|
||||
return CCM_ERR_INVALID_LENGTH_ENCODING;
|
||||
}
|
||||
|
||||
/* Compute first stream block */
|
||||
nonce_counter[0] = length_encoding - 1;
|
||||
block_size = cipher_get_block_size(cipher);
|
||||
memcpy(&nonce_counter[1], nonce, min(nonce_len, (size_t) 15 - length_encoding));
|
||||
len = cipher_encrypt_ctr(cipher, nonce_counter, block_size, zero_block,
|
||||
block_size, stream_block);
|
||||
if (len < 0) {
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Decrypt message in counter mode */
|
||||
plain_len = input_len - mac_length;
|
||||
crypto_block_inc_ctr(nonce_counter, block_size - nonce_len);
|
||||
len = cipher_encrypt_ctr(cipher, nonce_counter, nonce_len, input,
|
||||
plain_len, plain);
|
||||
if (len < 0) {
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Create B0, encrypt it (X1) and use it as mac_iv */
|
||||
if (ccm_create_mac_iv(cipher, auth_data_len, mac_length, length_encoding,
|
||||
nonce, nonce_len, plain_len, mac_iv) < 0) {
|
||||
return CCM_ERR_INVALID_DATA_LENGTH;
|
||||
}
|
||||
|
||||
/* MAC calulation (T) with additional data and plaintext */
|
||||
ccm_compute_adata_mac(cipher, auth_data, auth_data_len, mac_iv);
|
||||
len = ccm_compute_cbc_mac(cipher, mac_iv, plain, plain_len, mac);
|
||||
if (len < 0) {
|
||||
return len;
|
||||
}
|
||||
|
||||
/* mac = input[plain_len...plain_len+mac_length] ^ first stream block */
|
||||
for (uint8_t i = 0; i < mac_length; ++i) {
|
||||
mac_recv[i] = input[len + i] ^ stream_block[i];
|
||||
}
|
||||
|
||||
if (!crypto_equals(mac_recv, mac, mac_length)) {
|
||||
return CCM_ERR_INVALID_CBC_MAC;
|
||||
}
|
||||
|
||||
return plain_len;
|
||||
}
|
58
sys/crypto/modes/ctr.c
Normal file
58
sys/crypto/modes/ctr.c
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
*
|
||||
* 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_modes
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Crypto mode - Counter
|
||||
*
|
||||
* @author Nico von Geyso <nico.geyso@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "crypto/helper.h"
|
||||
#include "crypto/modes/ctr.h"
|
||||
|
||||
int cipher_encrypt_ctr(cipher_t* cipher, uint8_t nonce_counter[16],
|
||||
uint8_t nonce_len, uint8_t* input, size_t length,
|
||||
uint8_t* output)
|
||||
{
|
||||
size_t offset = 0;
|
||||
uint8_t stream_block[16] = {0}, block_size;
|
||||
|
||||
block_size = cipher_get_block_size(cipher);
|
||||
do {
|
||||
uint8_t block_size_input;
|
||||
|
||||
if (cipher_encrypt(cipher, nonce_counter, stream_block) != 1) {
|
||||
return CIPHER_ERR_ENC_FAILED;
|
||||
}
|
||||
|
||||
block_size_input = (length - offset > block_size) ?
|
||||
block_size : length - offset;
|
||||
for (uint8_t i = 0; i < block_size_input; ++i) {
|
||||
output[offset + i] = stream_block[i] ^ input[offset + i];
|
||||
}
|
||||
|
||||
offset += block_size_input;
|
||||
crypto_block_inc_ctr(nonce_counter, block_size - nonce_len);
|
||||
} while (offset < length);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
int cipher_decrypt_ctr(cipher_t* cipher, uint8_t nonce_counter[16],
|
||||
uint8_t nonce_len, uint8_t* input, size_t length,
|
||||
uint8_t* output)
|
||||
{
|
||||
return cipher_encrypt_ctr(cipher, nonce_counter, nonce_len, input,
|
||||
length, output);
|
||||
}
|
66
sys/crypto/modes/ecb.c
Normal file
66
sys/crypto/modes/ecb.c
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
*
|
||||
* 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_modes
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Crypto mode - electronic code book
|
||||
*
|
||||
* @author Nico von Geyso <nico.geyso@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "crypto/modes/ecb.h"
|
||||
|
||||
int cipher_encrypt_ecb(cipher_t* cipher, uint8_t* input,
|
||||
size_t length, uint8_t* output)
|
||||
{
|
||||
size_t offset;
|
||||
uint8_t block_size;
|
||||
|
||||
block_size = cipher_get_block_size(cipher);
|
||||
if (length % block_size != 0) {
|
||||
return CIPHER_ERR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
do {
|
||||
if (cipher_encrypt(cipher, input + offset, output + offset) != 1) {
|
||||
return CIPHER_ERR_ENC_FAILED;
|
||||
}
|
||||
|
||||
offset += block_size;
|
||||
} while (offset < length);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
int cipher_decrypt_ecb(cipher_t* cipher, uint8_t* input,
|
||||
size_t length, uint8_t* output)
|
||||
{
|
||||
size_t offset = 0;
|
||||
uint8_t block_size;
|
||||
|
||||
block_size = cipher_get_block_size(cipher);
|
||||
if (length % block_size != 0) {
|
||||
return CIPHER_ERR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
do {
|
||||
if (cipher_decrypt(cipher, input + offset, output + offset) != 1) {
|
||||
return CIPHER_ERR_DEC_FAILED;
|
||||
}
|
||||
|
||||
offset += block_size;
|
||||
} while (offset < length);
|
||||
|
||||
return offset;
|
||||
}
|
@ -36,29 +36,17 @@
|
||||
/**
|
||||
* @brief Interface to the rc5 cipher
|
||||
*/
|
||||
block_cipher_interface_t rc5_interface = {
|
||||
"RC5",
|
||||
static const cipher_interface_t rc5_interface = {
|
||||
BLOCK_SIZE,
|
||||
CIPHERS_MAX_KEY_SIZE,
|
||||
rc5_init,
|
||||
rc5_encrypt,
|
||||
rc5_decrypt,
|
||||
rc5_setup_key,
|
||||
rc5_get_preferred_block_size
|
||||
rc5_decrypt
|
||||
};
|
||||
const cipher_id_t CIPHER_RC5 = &rc5_interface;
|
||||
|
||||
|
||||
int rc5_init(cipher_context_t *context, uint8_t blockSize, uint8_t keySize, uint8_t *key)
|
||||
{
|
||||
(void)keySize;
|
||||
// 8 byte blocks only
|
||||
if (blockSize != BLOCK_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rc5_setup_key(context, key, 0);
|
||||
}
|
||||
|
||||
|
||||
int rc5_encrypt(cipher_context_t *context, uint8_t *block,
|
||||
int rc5_encrypt(const cipher_context_t *context, const uint8_t *block,
|
||||
uint8_t *cipherBlock)
|
||||
{
|
||||
register uint32_t l;
|
||||
@ -91,7 +79,7 @@ int rc5_encrypt(cipher_context_t *context, uint8_t *block,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rc5_decrypt(cipher_context_t *context, uint8_t *cipherBlock,
|
||||
int rc5_decrypt(const cipher_context_t *context, const uint8_t *cipherBlock,
|
||||
uint8_t *plainBlock)
|
||||
{
|
||||
register uint32_t l;
|
||||
@ -125,13 +113,20 @@ int rc5_decrypt(cipher_context_t *context, uint8_t *cipherBlock,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rc5_setup_key(cipher_context_t *context, uint8_t *key, uint8_t keysize)
|
||||
int rc5_init(cipher_context_t *context, const uint8_t *key, uint8_t keySize)
|
||||
{
|
||||
(void)keysize;
|
||||
(void) keySize;
|
||||
uint32_t *L, l, A, B, *S;
|
||||
uint8_t ii, jj;
|
||||
int8_t i;
|
||||
uint8_t tmp[8];
|
||||
|
||||
// Make sure that context is large enough. If this is not the case,
|
||||
// you should build with -DRC5.
|
||||
if(CIPHER_MAX_CONTEXT_SIZE < RC5_CONTEXT_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc5_context_t *rc5_context = (rc5_context_t *) context->context;
|
||||
S = rc5_context->skey;
|
||||
|
||||
@ -179,16 +174,3 @@ int rc5_setup_key(cipher_context_t *context, uint8_t *key, uint8_t keysize)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the preferred block size that this cipher operates with. It is
|
||||
* always safe to call this function before the init() call has been made.
|
||||
*
|
||||
* @return the preferred block size for this cipher. In the case where the
|
||||
* cipher operates with multiple block sizes, this will pick one
|
||||
* particular size (deterministically).
|
||||
*/
|
||||
uint8_t rc5_get_preferred_block_size(void)
|
||||
{
|
||||
return BLOCK_SIZE;
|
||||
}
|
||||
|
@ -53,14 +53,14 @@
|
||||
/**
|
||||
* @brief Interface to the skipjack cipher
|
||||
*/
|
||||
block_cipher_interface_t skipjack_interface = {
|
||||
"SkipJack",
|
||||
static const cipher_interface_t skipjack_interface = {
|
||||
BLOCK_SIZE,
|
||||
CIPHERS_MAX_KEY_SIZE,
|
||||
skipjack_init,
|
||||
skipjack_encrypt,
|
||||
skipjack_decrypt,
|
||||
skipjack_setup_key,
|
||||
skipjack_get_preferred_block_size
|
||||
skipjack_decrypt
|
||||
};
|
||||
const cipher_id_t CIPHER_SKIPJACK = &skipjack_interface;
|
||||
|
||||
// F-BOX
|
||||
// It can live in either RAM (faster access) or program memory (save ram,
|
||||
@ -94,17 +94,6 @@ static const uint8_t SJ_F[] /*__attribute__((C))*/ = {
|
||||
};
|
||||
|
||||
|
||||
int skipjack_init(cipher_context_t *context, uint8_t blockSize, uint8_t keySize,
|
||||
uint8_t *key)
|
||||
{
|
||||
// 8 byte blocks only
|
||||
if (blockSize != BLOCK_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return skipjack_setup_key(context, key, keySize);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief convert 2x uint8_t to uint16_t
|
||||
*
|
||||
@ -112,7 +101,7 @@ int skipjack_init(cipher_context_t *context, uint8_t blockSize, uint8_t keySize,
|
||||
* @param s pointer to the resulting uint16_t
|
||||
*
|
||||
*/
|
||||
static void c2sM(uint8_t *c, uint16_t *s)
|
||||
static void c2sM(const uint8_t *c, uint16_t *s)
|
||||
{
|
||||
memcpy(s, c, sizeof(uint16_t));
|
||||
return;
|
||||
@ -124,21 +113,22 @@ static void c2sM(uint8_t *c, uint16_t *s)
|
||||
* @param s pointer to the uint16_t input
|
||||
* @param c pointer to the first resulting uint8_ts
|
||||
*/
|
||||
static void s2cM(uint16_t s, uint8_t *c)
|
||||
static void s2cM(const uint16_t s, uint8_t *c)
|
||||
{
|
||||
memcpy(c, &s, sizeof(uint16_t));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int skipjack_encrypt(cipher_context_t *context, uint8_t *plainBlock,
|
||||
int skipjack_encrypt(const cipher_context_t *context, const uint8_t *plainBlock,
|
||||
uint8_t *cipherBlock)
|
||||
{
|
||||
|
||||
// prologue 10 pushs = 20 cycles
|
||||
/*register*/ uint8_t counter = 1;
|
||||
skipjack_context_t *skipjack_context = (skipjack_context_t *)context->context;
|
||||
/*register*/ uint8_t *skey = skipjack_context->skey;
|
||||
cipher_context_t *skipjack_context = (cipher_context_t *)context->context;
|
||||
/*register*/ uint8_t *skey = skipjack_context->context;
|
||||
|
||||
/*register*/ uint16_t w1, w2, w3, w4, tmp;
|
||||
/*register*/ uint8_t bLeft, bRight;
|
||||
|
||||
@ -173,7 +163,7 @@ int skipjack_encrypt(cipher_context_t *context, uint8_t *plainBlock,
|
||||
RULE_A(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
}
|
||||
|
||||
skey = skipjack_context->skey;
|
||||
skey = skipjack_context->context;
|
||||
|
||||
while (counter < 9) { // 3x
|
||||
RULE_A(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
@ -183,13 +173,13 @@ int skipjack_encrypt(cipher_context_t *context, uint8_t *plainBlock,
|
||||
RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
}
|
||||
|
||||
skey = skipjack_context->skey;
|
||||
skey = skipjack_context->context;
|
||||
|
||||
while (counter < 16) { // 5x
|
||||
RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
}
|
||||
|
||||
skey = skipjack_context->skey;
|
||||
skey = skipjack_context->context;
|
||||
// 1x
|
||||
RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
|
||||
@ -197,7 +187,7 @@ int skipjack_encrypt(cipher_context_t *context, uint8_t *plainBlock,
|
||||
RULE_A(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
}
|
||||
|
||||
skey = skipjack_context->skey;
|
||||
skey = skipjack_context->context;
|
||||
|
||||
while (counter < 25) { // 4x
|
||||
RULE_A(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
@ -205,13 +195,13 @@ int skipjack_encrypt(cipher_context_t *context, uint8_t *plainBlock,
|
||||
|
||||
// 1x
|
||||
RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
skey = skipjack_context->skey;
|
||||
skey = skipjack_context->context;
|
||||
|
||||
while (counter < 31) { // 5x
|
||||
RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
}
|
||||
|
||||
skey = skipjack_context->skey;
|
||||
skey = skipjack_context->context;
|
||||
|
||||
while (counter < 33) { // 2x
|
||||
RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
@ -232,12 +222,12 @@ int skipjack_encrypt(cipher_context_t *context, uint8_t *plainBlock,
|
||||
}
|
||||
|
||||
|
||||
int skipjack_decrypt(cipher_context_t *context, uint8_t *cipherBlock,
|
||||
int skipjack_decrypt(const cipher_context_t *context, const uint8_t *cipherBlock,
|
||||
uint8_t *plainBlock)
|
||||
{
|
||||
/*register*/ uint8_t counter = 32;
|
||||
skipjack_context_t *skipjack_context = (skipjack_context_t *)context->context;
|
||||
/*register*/ uint8_t *skey = skipjack_context->skey + 4;
|
||||
cipher_context_t *skipjack_context = (cipher_context_t *)context->context;
|
||||
/*register*/ uint8_t *skey = skipjack_context->context + 4;
|
||||
/*register*/ uint16_t w1, w2, w3, w4, tmp;
|
||||
/*register*/ uint8_t bLeft, bRight;
|
||||
|
||||
@ -271,13 +261,13 @@ int skipjack_decrypt(cipher_context_t *context, uint8_t *cipherBlock,
|
||||
RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
}
|
||||
|
||||
skey = skipjack_context->skey + 16;
|
||||
skey = skipjack_context->context + 16;
|
||||
|
||||
while (counter > 25) { //5x
|
||||
RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
}
|
||||
|
||||
skey = skipjack_context->skey + 16;
|
||||
skey = skipjack_context->context + 16;
|
||||
//1x
|
||||
RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
|
||||
@ -285,7 +275,7 @@ int skipjack_decrypt(cipher_context_t *context, uint8_t *cipherBlock,
|
||||
RULE_A_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
}
|
||||
|
||||
skey = skipjack_context->skey + 16;
|
||||
skey = skipjack_context->context + 16;
|
||||
|
||||
while (counter > 16) { //4x
|
||||
RULE_A_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
@ -293,13 +283,13 @@ int skipjack_decrypt(cipher_context_t *context, uint8_t *cipherBlock,
|
||||
|
||||
//1x
|
||||
RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
skey = skipjack_context->skey + 16;
|
||||
skey = skipjack_context->context + 16;
|
||||
|
||||
while (counter > 10) { //5x
|
||||
RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
}
|
||||
|
||||
skey = skipjack_context->skey + 16;
|
||||
skey = skipjack_context->context + 16;
|
||||
|
||||
while (counter > 8) { // 2x
|
||||
RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
@ -309,7 +299,7 @@ int skipjack_decrypt(cipher_context_t *context, uint8_t *cipherBlock,
|
||||
RULE_A_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
}
|
||||
|
||||
skey = skipjack_context->skey + 16;
|
||||
skey = skipjack_context->context + 16;
|
||||
|
||||
while (counter > 0) { // 5x
|
||||
RULE_A_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
|
||||
@ -327,31 +317,32 @@ int skipjack_decrypt(cipher_context_t *context, uint8_t *cipherBlock,
|
||||
}
|
||||
|
||||
|
||||
int skipjack_setup_key(cipher_context_t *context, uint8_t *key, uint8_t keysize)
|
||||
int skipjack_init(cipher_context_t *context, const uint8_t *key, uint8_t keysize)
|
||||
{
|
||||
int i = 0;
|
||||
skipjack_context_t *skipjack_context = (skipjack_context_t *)context->context;
|
||||
uint8_t *skey = skipjack_context->skey;
|
||||
|
||||
// Make sure that context is large enough. If this is not the case,
|
||||
// you should build with -DSKIPJACK.
|
||||
if(CIPHER_MAX_CONTEXT_SIZE < SKIPJACK_CONTEXT_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cipher_context_t *skipjack_context = (cipher_context_t *)context->context;
|
||||
uint8_t *skey = skipjack_context->context;
|
||||
|
||||
// for keys which are smaller than 160 bits, concatenate until they reach
|
||||
// 160 bits in size. Note that key expansion is just concatenation.
|
||||
if (keysize < CIPHERS_KEYSIZE) {
|
||||
if (keysize < CIPHERS_MAX_KEY_SIZE) {
|
||||
//fill up by concatenating key to as long as needed
|
||||
for (i = 0; i < CIPHERS_KEYSIZE; i++) {
|
||||
for (i = 0; i < CIPHERS_MAX_KEY_SIZE; i++) {
|
||||
skey[i] = key[(i % keysize)];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < CIPHERS_KEYSIZE; i++) {
|
||||
for (i = 0; i < CIPHERS_MAX_KEY_SIZE; i++) {
|
||||
skey[i] = key[i];
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
uint8_t skipjack_get_preferred_block_size(void)
|
||||
{
|
||||
return BLOCK_SIZE;
|
||||
}
|
||||
|
@ -32,17 +32,17 @@
|
||||
|
||||
|
||||
//prototype
|
||||
static int twofish_set_key(twofish_context_t *ctx, uint8_t *key, uint8_t keylen);
|
||||
static int twofish_setup_key(twofish_context_t *ctx, const uint8_t *key, uint8_t keylen);
|
||||
|
||||
// twofish interface
|
||||
block_cipher_interface_t twofish_interface = {
|
||||
"TWOFISH",
|
||||
static const cipher_interface_t twofish_interface = {
|
||||
TWOFISH_BLOCK_SIZE,
|
||||
TWOFISH_KEY_SIZE,
|
||||
twofish_init,
|
||||
twofish_encrypt,
|
||||
twofish_decrypt,
|
||||
twofish_setup_key,
|
||||
twofish_get_preferred_block_size
|
||||
twofish_decrypt
|
||||
};
|
||||
const cipher_id_t CIPHER_TWOFISH = &twofish_interface;
|
||||
|
||||
/* These two tables are the q0 and q1 permutations, exactly as described in
|
||||
* the Twofish paper. */
|
||||
@ -473,27 +473,26 @@ static uint8_t calc_sb_tbl[512] = {
|
||||
|
||||
|
||||
|
||||
int twofish_init(cipher_context_t *context, uint8_t blockSize, uint8_t keySize,
|
||||
uint8_t *key)
|
||||
int twofish_init(cipher_context_t *context, const uint8_t *key,
|
||||
uint8_t keySize)
|
||||
{
|
||||
//printf("%-40s: Entry\r\n", __FUNCTION__);
|
||||
// 16 byte blocks only
|
||||
if (blockSize != TWOFISH_BLOCK_SIZE) {
|
||||
printf("%-40s: blockSize != TWOFISH_BLOCK_SIZE...\r\n", __FUNCTION__);
|
||||
uint8_t i;
|
||||
|
||||
// Make sure that context is large enough. If this is not the case,
|
||||
// you should build with -DTWOFISH.
|
||||
if(CIPHER_MAX_CONTEXT_SIZE < TWOFISH_CONTEXT_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t i;
|
||||
|
||||
//key must be at least CIPHERS_KEYSIZE Bytes long
|
||||
if (keySize < CIPHERS_KEYSIZE) {
|
||||
//key must be at least CIPHERS_MAX_KEY_SIZE Bytes long
|
||||
if (keySize < CIPHERS_MAX_KEY_SIZE) {
|
||||
//fill up by concatenating key to as long as needed
|
||||
for (i = 0; i < CIPHERS_KEYSIZE; i++) {
|
||||
for (i = 0; i < CIPHERS_MAX_KEY_SIZE; i++) {
|
||||
context->context[i] = key[(i % keySize)];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < CIPHERS_KEYSIZE; i++) {
|
||||
for (i = 0; i < CIPHERS_MAX_KEY_SIZE; i++) {
|
||||
context->context[i] = key[i];
|
||||
}
|
||||
}
|
||||
@ -501,12 +500,6 @@ int twofish_init(cipher_context_t *context, uint8_t blockSize, uint8_t keySize,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int twofish_setup_key(cipher_context_t *context, uint8_t *key, uint8_t keysize)
|
||||
{
|
||||
return twofish_init(context, twofish_get_preferred_block_size(),
|
||||
keysize, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform the key setup.
|
||||
* Note that this works only with 128- and 256-bit keys, despite the
|
||||
@ -518,7 +511,7 @@ int twofish_setup_key(cipher_context_t *context, uint8_t *key, uint8_t keysize)
|
||||
*
|
||||
* @return -1 if invalid key-length, 0 otherwise
|
||||
*/
|
||||
static int twofish_set_key(twofish_context_t *ctx, uint8_t *key, uint8_t keylen)
|
||||
static int twofish_setup_key(twofish_context_t *ctx, const uint8_t *key, uint8_t keylen)
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
@ -658,7 +651,7 @@ static int twofish_set_key(twofish_context_t *ctx, uint8_t *key, uint8_t keylen)
|
||||
|
||||
|
||||
/* Encrypt one block. in and out may be the same. */
|
||||
int twofish_encrypt(cipher_context_t *context, uint8_t *in, uint8_t *out)
|
||||
int twofish_encrypt(const cipher_context_t *context, const uint8_t *in, uint8_t *out)
|
||||
{
|
||||
int res;
|
||||
//setup the twofish-specific context
|
||||
@ -670,7 +663,7 @@ int twofish_encrypt(cipher_context_t *context, uint8_t *in, uint8_t *out)
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = twofish_set_key(ctx, context->context, TWOFISH_KEY_SIZE);
|
||||
res = twofish_setup_key(ctx, context->context, TWOFISH_KEY_SIZE);
|
||||
|
||||
if (res < 0) {
|
||||
printf("%-40s: [ERROR] twofish_setKey failed with Code %i\r\n",
|
||||
@ -716,7 +709,7 @@ int twofish_encrypt(cipher_context_t *context, uint8_t *in, uint8_t *out)
|
||||
}
|
||||
|
||||
/* Decrypt one block. in and out may be the same. */
|
||||
int twofish_decrypt(cipher_context_t *context, uint8_t *in, uint8_t *out)
|
||||
int twofish_decrypt(const cipher_context_t *context, const uint8_t *in, uint8_t *out)
|
||||
{
|
||||
int res;
|
||||
twofish_context_t *ctx = malloc(sizeof(twofish_context_t));
|
||||
@ -727,7 +720,7 @@ int twofish_decrypt(cipher_context_t *context, uint8_t *in, uint8_t *out)
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = twofish_set_key(ctx, context->context, TWOFISH_KEY_SIZE);
|
||||
res = twofish_setup_key(ctx, context->context, TWOFISH_KEY_SIZE);
|
||||
|
||||
if (res < 0) {
|
||||
printf("%-40s: [ERROR] twofish_setKey failed with Code %i\r\n",
|
||||
@ -771,8 +764,3 @@ int twofish_decrypt(cipher_context_t *context, uint8_t *in, uint8_t *out)
|
||||
free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t twofish_get_preferred_block_size(void)
|
||||
{
|
||||
return TWOFISH_BLOCK_SIZE;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#define THREEDES_BLOCK_SIZE 8
|
||||
#define THREEDES_KEY_SIZE PARSEC_KEYSIZE
|
||||
#define THREEDES_MAX_KEY_SIZE 24
|
||||
|
||||
#define ROLc(x, y) \
|
||||
((((unsigned long) (x) << (unsigned long) ((y) & 31)) | \
|
||||
@ -81,27 +81,14 @@ static const uint32_t bigbyte[24] = {
|
||||
*
|
||||
* @param context the cipher_context_t-struct to save the
|
||||
* initialization of the cipher in
|
||||
* @param blockSize the used blocksize - this must match
|
||||
* the cipher-blocksize
|
||||
* @param keySize the size of the key
|
||||
* @param key a pointer to the key
|
||||
*
|
||||
* @return 0 if blocksize doesn't match else 1
|
||||
*/
|
||||
int tripledes_init(cipher_context_t *context, uint8_t blockSize, uint8_t keySize,
|
||||
uint8_t *key);
|
||||
* @param keySize the size of the key
|
||||
|
||||
/**
|
||||
* @brief updates the used key for this context after initialization has
|
||||
* already been done
|
||||
*
|
||||
* @param context the cipher_context_t-struct to save the updated key in
|
||||
* @param key a pointer to the key
|
||||
* @param keysize the length of the key
|
||||
*
|
||||
* @return 0 if initialized blocksize is wrong, 1 else
|
||||
* @return Whether initialization was successful. The command may be
|
||||
* unsuccessful if the key size is not valid.
|
||||
*/
|
||||
int tripledes_setup_key(cipher_context_t *context, uint8_t *key, uint8_t keysize);
|
||||
int tripledes_init(cipher_context_t *context, const uint8_t* key, uint8_t keySize);
|
||||
|
||||
/**
|
||||
* @brief encrypts one plain-block and saves the result in crypt.
|
||||
@ -120,7 +107,7 @@ int tripledes_setup_key(cipher_context_t *context, uint8_t *key, uint8_t keysize
|
||||
* -2 if the key could not be setup correctly
|
||||
* 1 if encryption was successful
|
||||
*/
|
||||
int tripledes_encrypt(cipher_context_t *context, uint8_t *plain, uint8_t *crypt);
|
||||
int tripledes_encrypt(const cipher_context_t *context, const uint8_t *plain, uint8_t *crypt);
|
||||
|
||||
/**
|
||||
* @brief decrypts one cipher-block and saves the plain-block in plain.
|
||||
@ -139,18 +126,7 @@ int tripledes_encrypt(cipher_context_t *context, uint8_t *plain, uint8_t *crypt)
|
||||
* -2 if the key could not be setup correctly
|
||||
* 1 if decryption was successful
|
||||
*/
|
||||
int tripledes_decrypt(cipher_context_t *context, uint8_t *crypt, uint8_t *plain);
|
||||
|
||||
/**
|
||||
* @brief returns the blocksize of the 3DES algorithm
|
||||
*/
|
||||
uint8_t tripledes_get_preferred_block_size(void);
|
||||
|
||||
/**
|
||||
* Interface to access the functions
|
||||
*
|
||||
*/
|
||||
extern block_cipher_interface_t tripledes_interface;
|
||||
int tripledes_decrypt(const cipher_context_t *context, const uint8_t *crypt, uint8_t *plain);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -77,28 +77,13 @@ typedef struct {
|
||||
*
|
||||
* @param context the cipher_context_t-struct to save the initialization
|
||||
* of the cipher in
|
||||
* @param blockSize the used blocksize - this must match the
|
||||
* cipher-blocksize
|
||||
* @param keySize the size of the key
|
||||
* @param key a pointer to the key
|
||||
*
|
||||
* @return 0 if blocksize doesn't match else 1
|
||||
* @return Whether initialization was successful. The command may be
|
||||
* unsuccessful if the key size is not valid.
|
||||
*/
|
||||
int aes_init(cipher_context_t *context, uint8_t blockSize, uint8_t keySize,
|
||||
uint8_t *key);
|
||||
|
||||
/**
|
||||
* @brief updates the used key for this context after initialization has
|
||||
* already been done
|
||||
*
|
||||
* @param context the cipher_context_t-struct to save the updated key
|
||||
* in
|
||||
* @param key a pointer to the key
|
||||
* @param keysize the length of the key
|
||||
*
|
||||
* @return 0 if initialized blocksize is wrong, 1 else
|
||||
*/
|
||||
int aes_setup_key(cipher_context_t *context, uint8_t *key, uint8_t keysize);
|
||||
int aes_init(cipher_context_t *context, const uint8_t *key, uint8_t keySize);
|
||||
|
||||
/**
|
||||
* @brief encrypts one plainBlock-block and saves the result in cipherblock.
|
||||
@ -115,7 +100,7 @@ int aes_setup_key(cipher_context_t *context, uint8_t *key, uint8_t keysize);
|
||||
*
|
||||
* @return 1 or result of aes_set_encrypt_key if it failed
|
||||
*/
|
||||
int aes_encrypt(cipher_context_t *context, uint8_t *plain_block,
|
||||
int aes_encrypt(const cipher_context_t *context, const uint8_t *plain_block,
|
||||
uint8_t *cipher_block);
|
||||
|
||||
/**
|
||||
@ -134,20 +119,9 @@ int aes_encrypt(cipher_context_t *context, uint8_t *plain_block,
|
||||
* @return 1 or negative value if cipher key cannot be expanded into
|
||||
* decryption key schedule
|
||||
*/
|
||||
int aes_decrypt(cipher_context_t *context, uint8_t *cipher_block,
|
||||
int aes_decrypt(const cipher_context_t *context, const uint8_t *cipher_block,
|
||||
uint8_t *plain_block);
|
||||
|
||||
/**
|
||||
* @brief returns the blocksize of the AES algorithm
|
||||
*/
|
||||
uint8_t aes_get_preferred_block_size(void);
|
||||
|
||||
/**
|
||||
* Interface to access the functions
|
||||
*
|
||||
*/
|
||||
extern block_cipher_interface_t aes_inerface;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -22,6 +22,8 @@
|
||||
#ifndef __CIPHERS_H_
|
||||
#define __CIPHERS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -30,84 +32,142 @@ extern "C" {
|
||||
|
||||
/* Set the algorithms that should be compiled in here. When these defines
|
||||
* are set, then packets will be compiled 5 times.
|
||||
*
|
||||
* */
|
||||
#define AES
|
||||
// #define RC5
|
||||
// #define THREEDES
|
||||
// #define AES
|
||||
// #define TWOFISH
|
||||
// #define SKIPJACK
|
||||
*/
|
||||
// #define CRYPTO_THREEDES
|
||||
// #define CRYPTO_AES
|
||||
// #define CRYPTO_TWOFISH
|
||||
// #define CRYPTO_SKIPJACK
|
||||
|
||||
/** @brief the length of keys in bytes */
|
||||
#define PARSEC_MAX_BLOCK_CIPHERS 5
|
||||
#define CIPHERS_KEYSIZE 20
|
||||
#define CIPHERS_MAX_KEY_SIZE 20
|
||||
#define CIPHER_MAX_BLOCK_SIZE 16
|
||||
|
||||
|
||||
/**
|
||||
* Context sizes needed for the different ciphers.
|
||||
* Always order by number of bytes descending!!! <br><br>
|
||||
*
|
||||
* threedes needs 24 bytes <br>
|
||||
* aes needs CIPHERS_MAX_KEY_SIZE bytes <br>
|
||||
* twofish needs CIPHERS_MAX_KEY_SIZE bytes <br>
|
||||
* skipjack needs 20 bytes
|
||||
*/
|
||||
#if defined(CRYPTO_THREEDES)
|
||||
#define CIPHER_MAX_CONTEXT_SIZE 24
|
||||
#elif defined(CRYPTO_AES)
|
||||
#define CIPHER_MAX_CONTEXT_SIZE CIPHERS_MAX_KEY_SIZE
|
||||
#elif defined(CRYPTO_TWOFISH)
|
||||
#define CIPHER_MAX_CONTEXT_SIZE CIPHERS_MAX_KEY_SIZE
|
||||
#elif defined(CRYPTO_SKIPJACK)
|
||||
#define CIPHER_MAX_CONTEXT_SIZE 20
|
||||
#else
|
||||
// 0 is not a possibility because 0-sized arrays are not allowed in ISO C
|
||||
#define CIPHER_MAX_CONTEXT_SIZE 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* error codes
|
||||
*/
|
||||
#define CIPHER_ERR_INVALID_KEY_SIZE -3
|
||||
#define CIPHER_ERR_INVALID_LENGTH -4
|
||||
#define CIPHER_ERR_ENC_FAILED -5
|
||||
#define CIPHER_ERR_DEC_FAILED -6
|
||||
|
||||
/**
|
||||
* @brief the context for cipher-operations
|
||||
* always order by number of bytes descending!!! <br>
|
||||
* rc5 needs 104 bytes <br>
|
||||
* threedes needs 24 bytes <br>
|
||||
* aes needs PARSEC_KEYSIZE bytes <br>
|
||||
* twofish needs PARSEC_KEYSIZE bytes <br>
|
||||
* skipjack needs 20 bytes <br>
|
||||
* identity needs 1 byte <br>
|
||||
*/
|
||||
typedef struct {
|
||||
#if defined(RC5)
|
||||
uint8_t context[104]; /**< supports RC5 and lower */
|
||||
#elif defined(THREEDES)
|
||||
uint8_t context[24]; /**< supports ThreeDES and lower */
|
||||
#elif defined(AES)
|
||||
uint8_t context[CIPHERS_KEYSIZE]; /**< supports AES and lower */
|
||||
#elif defined(TWOFISH)
|
||||
uint8_t context[CIPHERS_KEYSIZE]; /**< supports TwoFish and lower */
|
||||
#elif defined(SKIPJACK)
|
||||
uint8_t context[20]; /**< supports SkipJack and lower */
|
||||
#endif
|
||||
uint8_t context[CIPHER_MAX_CONTEXT_SIZE]; /**< buffer for cipher operations */
|
||||
} cipher_context_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief BlockCipher-Interface for the Cipher-Algorithms
|
||||
*/
|
||||
typedef struct {
|
||||
/** the name of the cipher algorithm as a string */
|
||||
char name[10];
|
||||
typedef struct cipher_interface_st {
|
||||
/** Blocksize of this cipher */
|
||||
uint8_t block_size;
|
||||
|
||||
/** Maximum key size for this cipher */
|
||||
uint8_t max_key_size;
|
||||
|
||||
/** the init function */
|
||||
int (*BlockCipher_init)(cipher_context_t *context, uint8_t blockSize,
|
||||
uint8_t keySize, uint8_t *key);
|
||||
int (*init)(cipher_context_t* ctx, const uint8_t* key, uint8_t key_size);
|
||||
|
||||
/** the encrypt function */
|
||||
int (*BlockCipher_encrypt)(cipher_context_t *context, uint8_t *plainBlock,
|
||||
uint8_t *cipherBlock);
|
||||
int (*encrypt)(const cipher_context_t* ctx, const uint8_t* plain_block,
|
||||
uint8_t* cipher_block);
|
||||
|
||||
/** the decrypt function */
|
||||
int (*BlockCipher_decrypt)(cipher_context_t *context, uint8_t *cipherBlock,
|
||||
uint8_t *plainBlock);
|
||||
/** the setupKey function */
|
||||
int (*setupKey)(cipher_context_t *context, uint8_t *key, uint8_t keysize);
|
||||
/** read the BlockSize of this Cipher */
|
||||
uint8_t (*BlockCipherInfo_getPreferredBlockSize)(void);
|
||||
} block_cipher_interface_t;
|
||||
int (*decrypt)(const cipher_context_t* ctx, const uint8_t* cipher_block,
|
||||
uint8_t* plain_block);
|
||||
} cipher_interface_t;
|
||||
|
||||
|
||||
typedef const cipher_interface_t *cipher_id_t;
|
||||
|
||||
extern const cipher_id_t CIPHER_3DES;
|
||||
extern const cipher_id_t CIPHER_AES_128;
|
||||
extern const cipher_id_t CIPHER_TWOFISH;
|
||||
extern const cipher_id_t CIPHER_SKIPJACK;
|
||||
|
||||
|
||||
/**
|
||||
* @brief The cipher mode context
|
||||
*/
|
||||
typedef struct CipherModeContext {
|
||||
cipher_context_t cc; /**< CipherContext for the cipher-operations */
|
||||
uint8_t context[24]; /**< context for the block-cipher-modes' */
|
||||
} CipherModeContext;
|
||||
|
||||
|
||||
/**
|
||||
* @brief struct for an archive of all available ciphers
|
||||
* @brief basic struct for using block ciphers
|
||||
* contains the cipher interface and the context
|
||||
*/
|
||||
typedef struct {
|
||||
/** the number of available ciphers */
|
||||
uint8_t NoCiphers;
|
||||
/** the ciphers in form or BlockCipherInterface_ts */
|
||||
block_cipher_interface_t ciphers[PARSEC_MAX_BLOCK_CIPHERS];
|
||||
} block_cipher_archive_t;
|
||||
const cipher_interface_t* interface; /**< BlockCipher-Interface for the
|
||||
Cipher-Algorithms */
|
||||
cipher_context_t context; /**< The encryption context (buffer)
|
||||
for the algorithm */
|
||||
} cipher_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialize new cipher state
|
||||
*
|
||||
* @param cipher cipher struct to init (already allocated memory)
|
||||
* @param cipher_id cipher algorithm id
|
||||
* @param key encryption key to use
|
||||
* @param key_size length of the encryption key
|
||||
*/
|
||||
int cipher_init(cipher_t* cipher, cipher_id_t cipher_id, const uint8_t* key,
|
||||
uint8_t key_size);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Encrypt data of BLOCK_SIZE length
|
||||
* *
|
||||
*
|
||||
* @param cipher Already initialized cipher struct
|
||||
* @param input pointer to input data to encrypt
|
||||
* @param output pointer to allocated memory for encrypted data. It has to
|
||||
* be of size BLOCK_SIZE
|
||||
*/
|
||||
int cipher_encrypt(const cipher_t* cipher, const uint8_t* input, uint8_t* output);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Decrypt data of BLOCK_SIZE length
|
||||
* *
|
||||
*
|
||||
* @param cipher Already initialized cipher struct
|
||||
* @param input pointer to input data (of size BLOCKS_SIZE) to decrypt
|
||||
* @param output pointer to allocated memory for decrypted data. It has to
|
||||
* be of size BLOCK_SIZE
|
||||
*/
|
||||
int cipher_decrypt(const cipher_t* cipher, const uint8_t* input, uint8_t* output);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get block size of cipher
|
||||
* *
|
||||
*
|
||||
* @param cipher Already initialized cipher struct
|
||||
*/
|
||||
int cipher_get_block_size(const cipher_t* cipher);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
55
sys/include/crypto/helper.h
Normal file
55
sys/include/crypto/helper.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
*
|
||||
* 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 helper.h
|
||||
* @brief helper functions for sys_crypto_modes
|
||||
*
|
||||
* @author Freie Universitaet Berlin, Computer Systems & Telematics
|
||||
* @author Nico von Geyso <nico.geyso@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef __CRYPTO_MODES_HELPER_H_
|
||||
#define __CRYPTO_MODES_HELPER_H_
|
||||
|
||||
#include "kernel.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Increment a counter encoded in an 16 octet block. The counter is
|
||||
* encoded from the least significant bit in the following form:
|
||||
* block[15-L..15])
|
||||
*
|
||||
* @param block encoded block
|
||||
* @param L length of counter
|
||||
*/
|
||||
void crypto_block_inc_ctr(uint8_t block[16], int L);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Compares two blocks of same size in deterministic time.
|
||||
*
|
||||
* @param a block a
|
||||
* @param b block b
|
||||
* @param len size of both blocks
|
||||
*
|
||||
* @returns 0 iff the blocks are non-equal.
|
||||
*/
|
||||
int crypto_equals(uint8_t *a, uint8_t *b, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CRYPTO_MODES_HELPER_H_ */
|
62
sys/include/crypto/modes/cbc.h
Normal file
62
sys/include/crypto/modes/cbc.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
*
|
||||
* 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 cbc.h
|
||||
* @brief Cipher block chaining mode of operation for block ciphers
|
||||
*
|
||||
* @author Freie Universitaet Berlin, Computer Systems & Telematics
|
||||
* @author Nico von Geyso <nico.geyso@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef __CRYPTO_MODES_CBC_H_
|
||||
#define __CRYPTO_MODES_CBC_H_
|
||||
|
||||
#include "kernel.h"
|
||||
#include "crypto/ciphers.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Encrypt data of arbitrary length in cipher block chaining mode.
|
||||
*
|
||||
* @param cipher Already initialized cipher struct
|
||||
* @param iv 16 octet initialization vector. Must never be used more
|
||||
* than once for a given key.
|
||||
* @param input pointer to input data to encrypt
|
||||
* @param input_len length of the input data
|
||||
* @param output pointer to allocated memory for encrypted data. It has to
|
||||
* be of size data_len + BLOCK_SIZE - data_len % BLOCK_SIZE.
|
||||
*/
|
||||
int cipher_encrypt_cbc(cipher_t* cipher, uint8_t iv[16], uint8_t* input,
|
||||
size_t input_len, uint8_t* output);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Decrypt encrypted data in cipher block chaining mode.
|
||||
*
|
||||
* @param cipher Already initialized cipher struct
|
||||
* @param iv 16 octet initialization vector.
|
||||
* @param input pointer to input data to decrypt
|
||||
* @param input_len length of the input data
|
||||
* @param output pointer to allocated memory for plaintext data. It has to
|
||||
* be of size input_len.
|
||||
*/
|
||||
int cipher_decrypt_cbc(cipher_t* cipher, uint8_t iv[16], uint8_t* input,
|
||||
size_t input_len, uint8_t* output);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CRYPTO_MODES_CBC_H_ */
|
89
sys/include/crypto/modes/ccm.h
Normal file
89
sys/include/crypto/modes/ccm.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
*
|
||||
* 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 ccm.h
|
||||
* @brief Counter with CBC-MAC mode of operation for block ciphers
|
||||
*
|
||||
* @author Freie Universitaet Berlin, Computer Systems & Telematics
|
||||
* @author Nico von Geyso <nico.geyso@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef __CRYPTO_MODES_CCM_H_
|
||||
#define __CRYPTO_MODES_CCM_H_
|
||||
|
||||
#include "kernel.h"
|
||||
#include "crypto/ciphers.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CCM_ERR_INVALID_NONCE_LENGTH -2
|
||||
#define CCM_ERR_INVALID_CBC_MAC -3
|
||||
#define CCM_ERR_INVALID_DATA_LENGTH -3
|
||||
#define CCM_ERR_INVALID_LENGTH_ENCODING -4
|
||||
#define CCM_ERR_INVALID_MAC_LENGTH -5
|
||||
|
||||
/**
|
||||
* @brief Encrypt and authenticate data of arbitrary length in ccm mode.
|
||||
*
|
||||
* @param cipher Already initialized cipher struct
|
||||
* @param auth_data Additional data to authenticate in MAC
|
||||
* @param auth_data_len Length of additional data
|
||||
* @param mac_length length of the appended MAC (between 4 and 16 - only
|
||||
* even values)
|
||||
* @param length_encoding maximal supported length of plaintext
|
||||
* (2^(8*length_enc)).
|
||||
* @param nonce Nounce for ctr mode encryption
|
||||
* @param nonce_len Length of the nonce in octets
|
||||
* (maximum: 16-length_encoding)
|
||||
* @param input pointer to input data to encrypt
|
||||
* @param input_len length of the input data
|
||||
* @param output pointer to allocated memory for encrypted data. It
|
||||
* has to be of size data_len + mac_length.
|
||||
* @return length of encrypted data or error code
|
||||
*/
|
||||
int cipher_encrypt_ccm(cipher_t* cipher, uint8_t* auth_data,
|
||||
uint32_t auth_data_len, uint8_t mac_length,
|
||||
uint8_t length_encoding, uint8_t* nonce, size_t nonce_len,
|
||||
uint8_t* input, size_t input_len, uint8_t* output);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Decrypt data of arbitrary length in ccm mode.
|
||||
*
|
||||
* @param cipher Already initialized cipher struct
|
||||
* @param auth_data Additional data to authenticate in MAC
|
||||
* @param auth_data_len Length of additional data
|
||||
* @param mac_length length of the appended MAC (between 4 and 16 - only
|
||||
* even values)
|
||||
* @param length_encoding maximal supported length of plaintext
|
||||
* (2^(8*length_enc)).
|
||||
* @param nonce Nounce for ctr mode encryption
|
||||
* @param nonce_len Length of the nonce in octets
|
||||
* (maximum: 16-length_encoding)
|
||||
* @param input pointer to input data to decrypt
|
||||
* @param input_len length of the input data
|
||||
* @param output pointer to allocated memory for decrypted data. It
|
||||
* has to be of size data_len - mac_length.
|
||||
* @return length of encrypted data or error code
|
||||
*/
|
||||
int cipher_decrypt_ccm(cipher_t* cipher, uint8_t* auth_data,
|
||||
uint32_t auth_data_len, uint8_t mac_length,
|
||||
uint8_t length_encoding, uint8_t* nonce, size_t nonce_len,
|
||||
uint8_t* input, size_t input_len, uint8_t* output);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CRYPTO_MODES_CCM_H_ */
|
74
sys/include/crypto/modes/ctr.h
Normal file
74
sys/include/crypto/modes/ctr.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
*
|
||||
* 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 ctr.h
|
||||
* @brief Counter mode of operation for block ciphers
|
||||
*
|
||||
* @author Freie Universitaet Berlin, Computer Systems & Telematics
|
||||
* @author Nico von Geyso <nico.geyso@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef __CRYPTO_MODES_CTR_H_
|
||||
#define __CRYPTO_MODES_CTR_H_
|
||||
|
||||
#include "kernel.h"
|
||||
#include "crypto/ciphers.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Encrypt data of arbitrary length in counter mode.
|
||||
*
|
||||
* @param cipher Already initialized cipher struct
|
||||
* @param nonce_counter A nounce and a counter encoded in 16 octets. The counter
|
||||
* will be modified in each block encryption.
|
||||
* @param nonce_len Length of the nonce in octets. As nounce and counter
|
||||
* have to fit in one aligned 16 octet block, maximum
|
||||
* length of nonce is limited by input_len:
|
||||
* 16 - log_2(input_len)
|
||||
* @param input pointer to input data to encrypt
|
||||
* @param length length of the input data
|
||||
* @param output pointer to allocated memory for encrypted data. It has
|
||||
* to be of size data_len.
|
||||
*/
|
||||
int cipher_encrypt_ctr(cipher_t* cipher, uint8_t nonce_counter[16],
|
||||
uint8_t nonce_len, uint8_t* input, size_t length,
|
||||
uint8_t* output);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Decrypt data of arbitrary length in counter mode. Encryption and
|
||||
* decryption in ctr mode are basically the same.
|
||||
*
|
||||
* @param cipher Already initialized cipher struct
|
||||
* @param nonce_counter A nounce and a counter encoded in 16 octets. The counter
|
||||
* will be modified in each block encryption.
|
||||
* @param nonce_len Length of the nonce in octets. As nounce and counter
|
||||
* have to fit in one aligned 16 octet block, maximum
|
||||
* length of nonce is limited by input_len:
|
||||
* 16 - log_2(input_len)
|
||||
* @param input pointer to input data to encrypt
|
||||
* @param length length of the input data
|
||||
* @param output pointer to allocated memory for encrypted data. It has
|
||||
* to be of size data_len.
|
||||
*/
|
||||
int cipher_decrypt_ctr(cipher_t* cipher, uint8_t nonce_counter[16],
|
||||
uint8_t nonce_len, uint8_t* input, size_t length,
|
||||
uint8_t* output);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CRYPTO_MODES_CTR_H_*/
|
63
sys/include/crypto/modes/ecb.h
Normal file
63
sys/include/crypto/modes/ecb.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
*
|
||||
* 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 ecb.h
|
||||
* @brief Electronic code book mode of operation for block ciphers
|
||||
*
|
||||
* @author Freie Universitaet Berlin, Computer Systems & Telematics
|
||||
* @author Nico von Geyso <nico.geyso@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef __CRYPTO_MODES_ECB_H_
|
||||
#define __CRYPTO_MODES_ECB_H_
|
||||
|
||||
#include "kernel.h"
|
||||
#include "crypto/ciphers.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Encrypt data of arbitrary length in ecb mode. Caution each identical
|
||||
* block results in an identical encrypted block. Normally you do not
|
||||
* want to use ECB.
|
||||
*
|
||||
*
|
||||
* @param cipher Already initialized cipher struct
|
||||
* @param input pointer to input data to encrypt
|
||||
* @param length length of the input data
|
||||
* @param output pointer to allocated memory for encrypted data. It has to
|
||||
* be of size data_len + BLOCK_SIZE - data_len % BLOCK_SIZE.
|
||||
*/
|
||||
int cipher_encrypt_ecb(cipher_t* cipher, uint8_t* input, size_t length,
|
||||
uint8_t* output);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Decrypts data of arbitrary length in ecb mode.
|
||||
*
|
||||
*
|
||||
* @param cipher Already initialized cipher struct
|
||||
* @param input pointer to input data to decrypt
|
||||
* @param length length of the input data
|
||||
* @param output pointer to allocated memory for plaintext data. It has to
|
||||
* be of size `lengh`.
|
||||
*/
|
||||
int cipher_decrypt_ecb(cipher_t* cipher, uint8_t* input, size_t length,
|
||||
uint8_t* output);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CRYPTO_MODES_ECB_H_*/
|
@ -56,12 +56,14 @@ extern "C" {
|
||||
|
||||
// 2 * (ROUNDS +1) * 4
|
||||
// 2 * 13 * 4 = 104 bytes
|
||||
#define RC5_CONTEXT_SIZE (2 * (RC5_ROUNDS + 1))
|
||||
|
||||
/**
|
||||
* @brief the cipher_context_t adapted for RC5
|
||||
*/
|
||||
typedef struct {
|
||||
/** @cond INTERNAL */
|
||||
uint32_t skey [2 * (RC5_ROUNDS + 1)];
|
||||
uint32_t skey [RC5_CONTEXT_SIZE];
|
||||
/** @endcond */
|
||||
} rc5_context_t;
|
||||
|
||||
@ -70,17 +72,14 @@ typedef struct {
|
||||
*
|
||||
* @param context the cipher_context_t-struct to save the initialization
|
||||
* of the cipher in
|
||||
* @param blockSize the used blocksize - this must match the
|
||||
* cipher-blocksize
|
||||
* @param keySize the size of the key
|
||||
* @param key a pointer to the key
|
||||
*
|
||||
* @return Whether initialization was successful. The command may be
|
||||
* unsuccessful if the key size or blockSize are not valid for the
|
||||
* unsuccessful if the key size is not valid for the
|
||||
* given cipher implementation.
|
||||
*/
|
||||
int rc5_init(cipher_context_t *context, uint8_t blockSize, uint8_t keySize,
|
||||
uint8_t *key);
|
||||
int rc5_init(cipher_context_t *context, const uint8_t *key, uint8_t keySize);
|
||||
|
||||
/**
|
||||
* @brief Encrypts a single block (of blockSize) using the passed context.
|
||||
@ -99,7 +98,7 @@ int rc5_init(cipher_context_t *context, uint8_t blockSize, uint8_t keySize,
|
||||
* @return Whether the encryption was successful. Possible failure reasons
|
||||
* include not calling init().
|
||||
*/
|
||||
int rc5_encrypt(cipher_context_t *context, uint8_t *plain_block, uint8_t *cipher_block);
|
||||
int rc5_encrypt(const cipher_context_t *context, const uint8_t *plain_block, uint8_t *cipher_block);
|
||||
|
||||
/**
|
||||
* @brief Decrypts a single block (of blockSize) using the key and the
|
||||
@ -112,36 +111,9 @@ int rc5_encrypt(cipher_context_t *context, uint8_t *plain_block, uint8_t *cipher
|
||||
* @return Whether the decryption was successful. Possible failure reasons
|
||||
* include not calling init() or an unimplimented decrypt function.
|
||||
*/
|
||||
int rc5_decrypt(cipher_context_t *context, uint8_t *cipherBlock,
|
||||
int rc5_decrypt(const cipher_context_t *context, const uint8_t *cipherBlock,
|
||||
uint8_t *plainBlock);
|
||||
|
||||
/**
|
||||
* @brief Sets up the key for usage with RC5
|
||||
* Performs the key expansion on the real secret.
|
||||
*
|
||||
* @param context the cipher_context_t-struct to save the updated key in
|
||||
* @param key a pointer to the secret key
|
||||
* @param keysize the length of the secret key
|
||||
*
|
||||
* @return SUCCESS
|
||||
*/
|
||||
int rc5_setup_key(cipher_context_t *context, uint8_t *key, uint8_t keysize);
|
||||
|
||||
/**
|
||||
* @brief Returns the preferred block size that this cipher operates with.
|
||||
* It is always safe to call this function before the init() call has
|
||||
* been made.
|
||||
*
|
||||
* @return the preferred block size for this cipher.
|
||||
*/
|
||||
uint8_t rc5_get_preferred_block_size(void);
|
||||
|
||||
/**
|
||||
* Interface to access the functions
|
||||
*
|
||||
*/
|
||||
extern block_cipher_interface_t rc5_interface;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -87,13 +87,8 @@ extern "C" {
|
||||
counter--; \
|
||||
skey -= 4; }
|
||||
|
||||
/**
|
||||
* @brief The cipher_context_t adapted for SkipJack
|
||||
*/
|
||||
typedef struct {
|
||||
/** 2 times keysize. makes unrolling keystream easier / efficient */
|
||||
uint8_t skey [ 20 ];
|
||||
} skipjack_context_t;
|
||||
/** 2 times keysize. makes unrolling keystream easier / efficient */
|
||||
#define SKIPJACK_CONTEXT_SIZE 20
|
||||
|
||||
/**
|
||||
* @brief Initialize the SkipJack-BlockCipher context.
|
||||
@ -102,15 +97,13 @@ typedef struct {
|
||||
* initialization call. It should be passed to future
|
||||
* invocations of this module which use this particular
|
||||
* key.
|
||||
* @param blockSize size of the block in bytes.
|
||||
* @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 or blockSize are not valid.
|
||||
* unsuccessful if the key size is not valid.
|
||||
*/
|
||||
int skipjack_init(cipher_context_t *context, uint8_t blockSize, uint8_t keySize,
|
||||
uint8_t *key);
|
||||
int skipjack_init(cipher_context_t *context, const uint8_t *key, uint8_t keySize);
|
||||
|
||||
/**
|
||||
* @brief Encrypts a single block (of blockSize) using the passed context.
|
||||
@ -123,7 +116,7 @@ int skipjack_init(cipher_context_t *context, uint8_t blockSize, uint8_t keySize,
|
||||
* @return Whether the encryption was successful. Possible failure reasons
|
||||
* include not calling init().
|
||||
*/
|
||||
int skipjack_encrypt(cipher_context_t *context, uint8_t *plainBlock,
|
||||
int skipjack_encrypt(const cipher_context_t *context, const uint8_t *plainBlock,
|
||||
uint8_t *cipherBlock);
|
||||
|
||||
/**
|
||||
@ -137,39 +130,9 @@ int skipjack_encrypt(cipher_context_t *context, uint8_t *plainBlock,
|
||||
* @return Whether the decryption was successful. Possible failure reasons
|
||||
* include not calling init()
|
||||
*/
|
||||
int skipjack_decrypt(cipher_context_t *context, uint8_t *cipherBlock,
|
||||
int skipjack_decrypt(const cipher_context_t *context, const uint8_t *cipherBlock,
|
||||
uint8_t *plainBlock);
|
||||
|
||||
/**
|
||||
* @brief Sets up the context to use the passed key for usage with SkipJack
|
||||
* Performs the key expansion on the real secret.
|
||||
*
|
||||
* @param context the cipher_context_t-struct to save the updated key in
|
||||
* @param key a pointer to the secret key
|
||||
* @param keysize the length of the secret key
|
||||
*
|
||||
* @return SUCCESS
|
||||
*/
|
||||
int skipjack_setup_key(cipher_context_t *context, uint8_t *key, uint8_t keysize);
|
||||
|
||||
/**
|
||||
* @brief Returns the preferred block size that this cipher operates with.
|
||||
* It is always safe to call this function before the init() call has
|
||||
* been made.
|
||||
*
|
||||
* @return the preferred block size for this cipher. In the case where the
|
||||
* cipher operates with multiple block sizes, this will pick one
|
||||
* particular size (deterministically).
|
||||
*/
|
||||
uint8_t skipjack_get_preferred_block_size(void);
|
||||
|
||||
|
||||
/**
|
||||
* Interface to access the functions
|
||||
*
|
||||
*/
|
||||
extern block_cipher_interface_t skipjack_interface;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -34,6 +34,7 @@ extern "C" {
|
||||
|
||||
#define TWOFISH_BLOCK_SIZE 16
|
||||
#define TWOFISH_KEY_SIZE 16 //only alternative is 32!
|
||||
#define TWOFISH_CONTEXT_SIZE 20
|
||||
|
||||
/**
|
||||
* Macro to perform one column of the RS matrix multiplication. The
|
||||
@ -218,26 +219,13 @@ typedef struct {
|
||||
* call. It should be passed to future invocations of
|
||||
* this module
|
||||
* which use this particular key.
|
||||
* @param block_size size of the block in bytes.
|
||||
* @param key_size key size in bytes
|
||||
* @param key pointer to the key
|
||||
*
|
||||
* @return Whether initialization was successful. The command may be
|
||||
* unsuccessful if the key size or blockSize are not valid.
|
||||
* unsuccessful if the key size is not valid.
|
||||
*/
|
||||
int twofish_init(cipher_context_t *context, uint8_t block_size, uint8_t key_size, uint8_t *key);
|
||||
|
||||
/**
|
||||
* @brief Sets up the context to use the passed key for usage with TwoFish
|
||||
* Performs the key expansion on the real secret.
|
||||
*
|
||||
* @param context the CipherContext-struct to save the updated key in
|
||||
* @param key a pointer to the secret key
|
||||
* @param key_size the length of the secret key
|
||||
*
|
||||
* @return SUCCESS
|
||||
*/
|
||||
int twofish_setup_key(cipher_context_t *context, uint8_t *key, uint8_t key_size);
|
||||
int twofish_init(cipher_context_t *context, const uint8_t *key, uint8_t key_size);
|
||||
|
||||
/**
|
||||
* @brief Encrypts a single block (of blockSize) using the passed context.
|
||||
@ -250,7 +238,7 @@ int twofish_setup_key(cipher_context_t *context, uint8_t *key, uint8_t key_size)
|
||||
* @return Whether the encryption was successful. Possible failure reasons
|
||||
* include not calling init().
|
||||
*/
|
||||
int twofish_encrypt(cipher_context_t *context, uint8_t *in, uint8_t *out);
|
||||
int twofish_encrypt(const cipher_context_t *context, const uint8_t *in, uint8_t *out);
|
||||
|
||||
/**
|
||||
* @brief Decrypts a single block (of blockSize) using the passed context.
|
||||
@ -263,24 +251,7 @@ int twofish_encrypt(cipher_context_t *context, uint8_t *in, uint8_t *out);
|
||||
* @return Whether the decryption was successful. Possible failure reasons
|
||||
* include not calling init()
|
||||
*/
|
||||
int twofish_decrypt(cipher_context_t *context, uint8_t *in, uint8_t *out);
|
||||
|
||||
/**
|
||||
* @brief Returns the preferred block size that this cipher operates with.
|
||||
* It is always safe to call this function before the init() call has
|
||||
* been made.
|
||||
*
|
||||
* @return the preferred block size for this cipher. In the case where the
|
||||
* cipher operates with multiple block sizes, this will pick one
|
||||
* particular size (deterministically).
|
||||
*/
|
||||
uint8_t twofish_get_preferred_block_size(void);
|
||||
|
||||
/**
|
||||
* Interface to access the functions
|
||||
*
|
||||
*/
|
||||
extern block_cipher_interface_t twofish_interface;
|
||||
int twofish_decrypt(const cipher_context_t *context, const uint8_t *in, uint8_t *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -4,7 +4,8 @@ include ../Makefile.tests_common
|
||||
BOARD_INSUFFICIENT_RAM := airfy-beacon chronos msb-430 msb-430h pca10000 \
|
||||
pca10005 redbee-econotag spark-core stm32f0discovery \
|
||||
telosb wsn430-v1_3b wsn430-v1_4 z1 nucleo-f334 \
|
||||
yunjia-nrf51822 samr21-xpro arduino-mega2560
|
||||
yunjia-nrf51822 samr21-xpro arduino-mega2560 \
|
||||
airfy-beacon
|
||||
|
||||
USEMODULE += embunit
|
||||
|
||||
|
@ -1 +1,3 @@
|
||||
USEMODULE += crypto
|
||||
USEMODULE += cipher_modes
|
||||
CFLAGS += -DCRYPTO_THREEDES
|
||||
|
92
tests/unittests/tests-crypto/tests-crypto-3des.c
Normal file
92
tests/unittests/tests-crypto/tests-crypto-3des.c
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Nico von Geyso
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "crypto/3des.h"
|
||||
#include "tests-crypto.h"
|
||||
|
||||
static uint8_t TEST_0_KEY[] = {
|
||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||
0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF
|
||||
};
|
||||
|
||||
static uint8_t TEST_0_INP[] = {
|
||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7
|
||||
};
|
||||
static uint8_t TEST_0_ENC[] = {
|
||||
0xDF, 0x0B, 0x6C, 0x9C, 0x31, 0xCD, 0x0C, 0xE4
|
||||
};
|
||||
|
||||
static uint8_t TEST_1_KEY[] = {
|
||||
0x23, 0xA0, 0x18, 0x53, 0xFA, 0xB3, 0x89, 0x23,
|
||||
0x65, 0x89, 0x2A, 0xBC, 0x43, 0x99, 0xCC, 0x00
|
||||
};
|
||||
|
||||
static uint8_t TEST_1_INP[] = {
|
||||
0x11, 0x53, 0x81, 0xE2, 0x5F, 0x33, 0xE7, 0x41
|
||||
};
|
||||
static uint8_t TEST_1_ENC[] = {
|
||||
0x6C, 0x71, 0x5C, 0xC2, 0x58, 0x13, 0xEC, 0x6E
|
||||
};
|
||||
|
||||
static void test_crypto_tripledes_encrypt(void)
|
||||
{
|
||||
cipher_context_t ctx;
|
||||
int err;
|
||||
uint8_t data[THREEDES_BLOCK_SIZE];
|
||||
|
||||
err = tripledes_init(&ctx, TEST_0_KEY, 16);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
err = tripledes_encrypt(&ctx, TEST_0_INP, data);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
TEST_ASSERT_MESSAGE(1 == compare(TEST_0_ENC, data, THREEDES_BLOCK_SIZE), "wrong ciphertext");
|
||||
|
||||
err = tripledes_init(&ctx, TEST_1_KEY, 16);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
err = tripledes_encrypt(&ctx, TEST_1_INP, data);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
TEST_ASSERT_MESSAGE(1 == compare(TEST_1_ENC, data, THREEDES_BLOCK_SIZE), "wrong ciphertext");
|
||||
}
|
||||
|
||||
static void test_crypto_tripledes_decrypt(void)
|
||||
{
|
||||
|
||||
cipher_context_t ctx;
|
||||
int err;
|
||||
uint8_t data[THREEDES_BLOCK_SIZE];
|
||||
|
||||
err = tripledes_init(&ctx, TEST_0_KEY, 16);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
err = tripledes_decrypt(&ctx, TEST_0_ENC, data);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
TEST_ASSERT_MESSAGE(1 == compare(TEST_0_INP, data, THREEDES_BLOCK_SIZE), "wrong plaintext");
|
||||
|
||||
err = tripledes_init(&ctx, TEST_1_KEY, 16);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
err = tripledes_decrypt(&ctx, TEST_1_ENC, data);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
TEST_ASSERT_MESSAGE(1 == compare(TEST_1_INP, data, THREEDES_BLOCK_SIZE), "wrong plaintext");
|
||||
}
|
||||
|
||||
Test* tests_crypto_3des_tests(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_crypto_tripledes_encrypt),
|
||||
new_TestFixture(test_crypto_tripledes_decrypt),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(crypto_tripledes_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test*)&crypto_tripledes_tests;
|
||||
}
|
96
tests/unittests/tests-crypto/tests-crypto-aes.c
Normal file
96
tests/unittests/tests-crypto/tests-crypto-aes.c
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Nico von Geyso
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "crypto/aes.h"
|
||||
#include "tests-crypto.h"
|
||||
|
||||
static uint8_t TEST_0_KEY[] = {
|
||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||
0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF
|
||||
};
|
||||
|
||||
static uint8_t TEST_0_INP[] = {
|
||||
0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF,
|
||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||
};
|
||||
static uint8_t TEST_0_ENC[] = {
|
||||
0x37, 0x29, 0xa3, 0x6c, 0xaf, 0xe9, 0x84, 0xff,
|
||||
0x46, 0x22, 0x70, 0x42, 0xee, 0x24, 0x83, 0xf6
|
||||
};
|
||||
|
||||
static uint8_t TEST_1_KEY[] = {
|
||||
0x23, 0xA0, 0x18, 0x53, 0xFA, 0xB3, 0x89, 0x23,
|
||||
0x65, 0x89, 0x2A, 0xBC, 0x43, 0x99, 0xCC, 0x00
|
||||
};
|
||||
|
||||
static uint8_t TEST_1_INP[] = {
|
||||
0x11, 0x53, 0x81, 0xE2, 0x5F, 0x33, 0xE7, 0x41,
|
||||
0xBB, 0x12, 0x67, 0x38, 0xE9, 0x12, 0x54, 0x23
|
||||
};
|
||||
static uint8_t TEST_1_ENC[] = {
|
||||
0xD7, 0x9A, 0x54, 0x0E, 0x61, 0x33, 0x03, 0x72,
|
||||
0x59, 0x0f, 0x87, 0x91, 0xEF, 0xB0, 0xF8, 0x16
|
||||
};
|
||||
|
||||
static void test_crypto_aes_encrypt(void)
|
||||
{
|
||||
cipher_context_t ctx;
|
||||
int err;
|
||||
uint8_t data[AES_BLOCK_SIZE];
|
||||
|
||||
err = aes_init(&ctx, TEST_0_KEY, AES_KEY_SIZE);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
err = aes_encrypt(&ctx, TEST_0_INP, data);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
TEST_ASSERT_MESSAGE(1 == compare(TEST_0_ENC, data, AES_BLOCK_SIZE), "wrong ciphertext");
|
||||
|
||||
err = aes_init(&ctx, TEST_1_KEY, AES_KEY_SIZE);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
err = aes_encrypt(&ctx, TEST_1_INP, data);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
TEST_ASSERT_MESSAGE(1 == compare(TEST_1_ENC, data, AES_BLOCK_SIZE), "wrong ciphertext");
|
||||
}
|
||||
|
||||
static void test_crypto_aes_decrypt(void)
|
||||
{
|
||||
|
||||
cipher_context_t ctx;
|
||||
int err;
|
||||
uint8_t data[AES_BLOCK_SIZE];
|
||||
|
||||
err = aes_init(&ctx, TEST_0_KEY, AES_KEY_SIZE);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
err = aes_decrypt(&ctx, TEST_0_ENC, data);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
TEST_ASSERT_MESSAGE(1 == compare(TEST_0_INP, data, AES_BLOCK_SIZE), "wrong plaintext");
|
||||
|
||||
err = aes_init(&ctx, TEST_1_KEY, AES_KEY_SIZE);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
err = aes_decrypt(&ctx, TEST_1_ENC, data);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
TEST_ASSERT_MESSAGE(1 == compare(TEST_1_INP, data, AES_BLOCK_SIZE), "wrong plaintext");
|
||||
}
|
||||
|
||||
Test* tests_crypto_aes_tests(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_crypto_aes_encrypt),
|
||||
new_TestFixture(test_crypto_aes_decrypt),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(crypto_aes_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test*)&crypto_aes_tests;
|
||||
}
|
72
tests/unittests/tests-crypto/tests-crypto-cipher.c
Normal file
72
tests/unittests/tests-crypto/tests-crypto-cipher.c
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Nico von Geyso
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "crypto/ciphers.h"
|
||||
#include "tests-crypto.h"
|
||||
|
||||
static uint8_t TEST_KEY[] = {
|
||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||
0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF
|
||||
};
|
||||
|
||||
static uint8_t TEST_INP[] = {
|
||||
0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF,
|
||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7
|
||||
};
|
||||
|
||||
static uint8_t TEST_ENC_AES[] = {
|
||||
0x37, 0x29, 0xa3, 0x6c, 0xaf, 0xe9, 0x84, 0xff,
|
||||
0x46, 0x22, 0x70, 0x42, 0xee, 0x24, 0x83, 0xf6
|
||||
};
|
||||
|
||||
static void test_crypto_cipher_aes_encrypt(void)
|
||||
{
|
||||
cipher_t cipher;
|
||||
int err, cmp;
|
||||
uint8_t data[16] = {0};
|
||||
|
||||
err = cipher_init(&cipher, CIPHER_AES_128, TEST_KEY, 16);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
err = cipher_encrypt(&cipher, TEST_INP, data);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
cmp = compare(TEST_ENC_AES, data, 16);
|
||||
TEST_ASSERT_MESSAGE(1 == cmp , "wrong ciphertext");
|
||||
}
|
||||
|
||||
static void test_crypto_cipher_aes_decrypt(void)
|
||||
{
|
||||
cipher_t cipher;
|
||||
int err, cmp;
|
||||
uint8_t data[16];
|
||||
|
||||
err = cipher_init(&cipher, CIPHER_AES_128, TEST_KEY, 16);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
err = cipher_decrypt(&cipher, TEST_ENC_AES, data);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
cmp = compare(TEST_INP, data, 16);
|
||||
TEST_ASSERT_MESSAGE(1 == cmp , "wrong plaintext");
|
||||
}
|
||||
|
||||
Test* tests_crypto_cipher_tests(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_crypto_cipher_aes_encrypt),
|
||||
new_TestFixture(test_crypto_cipher_aes_decrypt)
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(crypto_cipher_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test*)&crypto_cipher_tests;
|
||||
}
|
127
tests/unittests/tests-crypto/tests-crypto-modes-cbc.c
Normal file
127
tests/unittests/tests-crypto/tests-crypto-modes-cbc.c
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Nico von Geyso
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "crypto/ciphers.h"
|
||||
#include "crypto/modes/cbc.h"
|
||||
#include "tests-crypto.h"
|
||||
|
||||
/*
|
||||
* all test vectors are from "Recommendation for Block Cipher Modes of
|
||||
* Operation - Methods and Techniques" by Morris Dworkin / NIST
|
||||
*
|
||||
* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||
*/
|
||||
|
||||
|
||||
/* PACKET VECTOR #1 (Page 27) */
|
||||
static uint8_t TEST_1_KEY[] = {
|
||||
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
|
||||
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
|
||||
};
|
||||
static uint8_t TEST_1_KEY_LEN = 16;
|
||||
|
||||
static uint8_t TEST_1_IV[16] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
|
||||
};
|
||||
|
||||
static uint8_t TEST_1_PLAIN[] = {
|
||||
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
|
||||
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
|
||||
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
|
||||
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
|
||||
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
|
||||
0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
|
||||
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
|
||||
0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
|
||||
};
|
||||
static uint8_t TEST_1_PLAIN_LEN = 64;
|
||||
|
||||
static uint8_t TEST_1_CIPHER[] = {
|
||||
0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46,
|
||||
0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d,
|
||||
0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee,
|
||||
0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2,
|
||||
0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b,
|
||||
0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16,
|
||||
0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09,
|
||||
0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7
|
||||
};
|
||||
static uint8_t TEST_1_CIPHER_LEN = 64;
|
||||
|
||||
static void test_encrypt_op(uint8_t* key, uint8_t key_len, uint8_t iv[16],
|
||||
uint8_t* input, uint8_t input_len, uint8_t* output,
|
||||
uint8_t output_len)
|
||||
{
|
||||
cipher_t cipher;
|
||||
int len, err, cmp;
|
||||
uint8_t data[64];
|
||||
|
||||
err = cipher_init(&cipher, CIPHER_AES_128, key, key_len);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
len = cipher_encrypt_cbc(&cipher, iv, input, input_len, data);
|
||||
TEST_ASSERT_MESSAGE(len > 0, "Encryption failed");
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(output_len, len);
|
||||
cmp = compare(output, data, len);
|
||||
TEST_ASSERT_MESSAGE(1 == cmp , "wrong ciphertext");
|
||||
|
||||
}
|
||||
|
||||
static void test_decrypt_op(uint8_t* key, uint8_t key_len, uint8_t iv[16],
|
||||
uint8_t* input, uint8_t input_len, uint8_t* output,
|
||||
uint8_t output_len)
|
||||
{
|
||||
cipher_t cipher;
|
||||
int len, err, cmp;
|
||||
uint8_t data[64];
|
||||
|
||||
err = cipher_init(&cipher, CIPHER_AES_128, key, key_len);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
len = cipher_decrypt_cbc(&cipher, iv, input, input_len, data);
|
||||
TEST_ASSERT_MESSAGE(len > 0, "Encryption failed");
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(output_len, len);
|
||||
cmp = compare(output, data, len);
|
||||
TEST_ASSERT_MESSAGE(1 == cmp , "wrong ciphertext");
|
||||
|
||||
}
|
||||
|
||||
static void test_crypto_modes_cbc_encrypt(void)
|
||||
{
|
||||
test_encrypt_op(TEST_1_KEY, TEST_1_KEY_LEN, TEST_1_IV, TEST_1_PLAIN,
|
||||
TEST_1_PLAIN_LEN, TEST_1_CIPHER, TEST_1_CIPHER_LEN);
|
||||
}
|
||||
|
||||
static void test_crypto_modes_cbc_decrypt(void)
|
||||
{
|
||||
test_decrypt_op(TEST_1_KEY, TEST_1_KEY_LEN, TEST_1_IV, TEST_1_CIPHER,
|
||||
TEST_1_CIPHER_LEN, TEST_1_PLAIN, TEST_1_PLAIN_LEN);
|
||||
}
|
||||
|
||||
|
||||
Test* tests_crypto_modes_cbc_tests(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_crypto_modes_cbc_encrypt),
|
||||
new_TestFixture(test_crypto_modes_cbc_decrypt)
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(crypto_modes_cbc_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test*)&crypto_modes_cbc_tests;
|
||||
}
|
161
tests/unittests/tests-crypto/tests-crypto-modes-ccm.c
Normal file
161
tests/unittests/tests-crypto/tests-crypto-modes-ccm.c
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Nico von Geyso
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "crypto/ciphers.h"
|
||||
#include "crypto/modes/ccm.h"
|
||||
#include "tests-crypto.h"
|
||||
|
||||
/* PACKET VECTOR #1 (RFC 3610 - Page 10) */
|
||||
static uint8_t TEST_1_KEY[] = {
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
|
||||
0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF
|
||||
};
|
||||
static uint8_t TEST_1_KEY_LEN = 16;
|
||||
|
||||
static uint8_t TEST_1_NONCE[] = {
|
||||
0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0,
|
||||
0xA1, 0xA2, 0xA3, 0xA4, 0xA5
|
||||
};
|
||||
static uint8_t TEST_1_NONCE_LEN = 13;
|
||||
|
||||
static uint8_t TEST_1_INPUT[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* additional auth data */
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* input */
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* input */
|
||||
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E /* input */
|
||||
};
|
||||
static uint8_t TEST_1_INPUT_LEN = 23;
|
||||
static uint8_t TEST_1_ADATA_LEN = 8;
|
||||
|
||||
static uint8_t TEST_1_EXPECTED[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x58, 0x8C, 0x97, 0x9A, 0x61, 0xC6, 0x63, 0xD2,
|
||||
0xF0, 0x66, 0xD0, 0xC2, 0xC0, 0xF9, 0x89, 0x80,
|
||||
0x6D, 0x5F, 0x6B, 0x61, 0xDA, 0xC3, 0x84, 0x17,
|
||||
0xE8, 0xD1, 0x2C, 0xFD, 0xF9, 0x26, 0xE0
|
||||
};
|
||||
static uint8_t TEST_1_EXPECTED_LEN = 39;
|
||||
|
||||
/* PACKET VECTOR #2 (RFC 3610 - Page 10) */
|
||||
static uint8_t TEST_2_KEY[] = {
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
|
||||
0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF
|
||||
};
|
||||
static uint8_t TEST_2_KEY_LEN = 16;
|
||||
|
||||
static uint8_t TEST_2_NONCE[] = {
|
||||
0x00, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01, 0xA0,
|
||||
0xA1, 0xA2, 0xA3, 0xA4, 0xA5
|
||||
};
|
||||
static uint8_t TEST_2_NONCE_LEN = 13;
|
||||
|
||||
static uint8_t TEST_2_INPUT[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
|
||||
};
|
||||
static uint8_t TEST_2_INPUT_LEN = 24;
|
||||
static uint8_t TEST_2_ADATA_LEN = 8;
|
||||
|
||||
static uint8_t TEST_2_EXPECTED[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x72, 0xC9, 0x1A, 0x36, 0xE1, 0x35, 0xF8, 0xCF,
|
||||
0x29, 0x1C, 0xA8, 0x94, 0x08, 0x5C, 0x87, 0xE3,
|
||||
0xCC, 0x15, 0xC4, 0x39, 0xC9, 0xE4, 0x3A, 0x3B,
|
||||
0xA0, 0x91, 0xD5, 0x6E, 0x10, 0x40, 0x09, 0x16
|
||||
};
|
||||
static uint8_t TEST_2_EXPECTED_LEN = 40;
|
||||
|
||||
static void test_encrypt_op(uint8_t* key, uint8_t key_len, uint8_t* adata,
|
||||
uint8_t adata_len, uint8_t* nonce, uint8_t nonce_len, uint8_t* plain,
|
||||
uint8_t plain_len, uint8_t* output_expected, uint8_t output_expected_len)
|
||||
{
|
||||
cipher_t cipher;
|
||||
int len, err, cmp;
|
||||
uint8_t data[60];
|
||||
|
||||
err = cipher_init(&cipher, CIPHER_AES_128, key, key_len);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
len = cipher_encrypt_ccm(&cipher, adata, adata_len, 8, 2, nonce,
|
||||
nonce_len, plain, plain_len, data);
|
||||
TEST_ASSERT_MESSAGE(len > 0, "Encryption failed");
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(output_expected_len, len);
|
||||
cmp = compare(output_expected, data, len);
|
||||
TEST_ASSERT_MESSAGE(1 == cmp , "wrong ciphertext");
|
||||
|
||||
}
|
||||
|
||||
static void test_decrypt_op(uint8_t* key, uint8_t key_len, uint8_t* adata,
|
||||
uint8_t adata_len, uint8_t* nonce, uint8_t nonce_len, uint8_t* encrypted,
|
||||
uint8_t encrypted_len, uint8_t* output_expected, uint8_t output_expected_len)
|
||||
{
|
||||
cipher_t cipher;
|
||||
int len, err, cmp;
|
||||
uint8_t data[60];
|
||||
|
||||
err = cipher_init(&cipher, CIPHER_AES_128, key, key_len);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
len = cipher_decrypt_ccm(&cipher, adata, adata_len, 8, 2, nonce,
|
||||
nonce_len, encrypted, encrypted_len, data);
|
||||
TEST_ASSERT_MESSAGE(len > 0, "Decryption failed");
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(output_expected_len, len);
|
||||
cmp = compare(output_expected, data, len);
|
||||
TEST_ASSERT_MESSAGE(1 == cmp , "wrong ciphertext");
|
||||
|
||||
}
|
||||
|
||||
static void test_crypto_modes_ccm_encrypt(void)
|
||||
{
|
||||
test_encrypt_op(TEST_1_KEY, TEST_1_KEY_LEN, TEST_1_INPUT, TEST_1_ADATA_LEN,
|
||||
TEST_1_NONCE, TEST_1_NONCE_LEN, TEST_1_INPUT + TEST_1_ADATA_LEN,
|
||||
TEST_1_INPUT_LEN, TEST_1_EXPECTED + TEST_1_ADATA_LEN,
|
||||
TEST_1_EXPECTED_LEN - TEST_1_ADATA_LEN);
|
||||
|
||||
test_encrypt_op(TEST_2_KEY, TEST_2_KEY_LEN, TEST_2_INPUT, TEST_2_ADATA_LEN,
|
||||
TEST_2_NONCE, TEST_2_NONCE_LEN, TEST_2_INPUT + TEST_2_ADATA_LEN,
|
||||
TEST_2_INPUT_LEN, TEST_2_EXPECTED + TEST_2_ADATA_LEN,
|
||||
TEST_2_EXPECTED_LEN - TEST_2_ADATA_LEN);
|
||||
}
|
||||
|
||||
static void test_crypto_modes_ccm_decrypt(void)
|
||||
{
|
||||
test_decrypt_op(TEST_1_KEY, TEST_1_KEY_LEN, TEST_1_INPUT, TEST_1_ADATA_LEN,
|
||||
TEST_1_NONCE, TEST_1_NONCE_LEN, TEST_1_EXPECTED + TEST_1_ADATA_LEN,
|
||||
TEST_1_EXPECTED_LEN - TEST_1_ADATA_LEN, TEST_1_INPUT + TEST_1_ADATA_LEN,
|
||||
TEST_1_INPUT_LEN);
|
||||
|
||||
test_decrypt_op(TEST_2_KEY, TEST_2_KEY_LEN, TEST_2_INPUT, TEST_2_ADATA_LEN,
|
||||
TEST_2_NONCE, TEST_2_NONCE_LEN, TEST_2_EXPECTED + TEST_2_ADATA_LEN,
|
||||
TEST_2_EXPECTED_LEN - TEST_2_ADATA_LEN, TEST_2_INPUT + TEST_2_ADATA_LEN,
|
||||
TEST_2_INPUT_LEN);
|
||||
}
|
||||
|
||||
|
||||
Test* tests_crypto_modes_ccm_tests(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_crypto_modes_ccm_encrypt),
|
||||
new_TestFixture(test_crypto_modes_ccm_decrypt)
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(crypto_modes_ccm_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test*)&crypto_modes_ccm_tests;
|
||||
}
|
133
tests/unittests/tests-crypto/tests-crypto-modes-ctr.c
Normal file
133
tests/unittests/tests-crypto/tests-crypto-modes-ctr.c
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Nico von Geyso
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "crypto/ciphers.h"
|
||||
#include "crypto/modes/ctr.h"
|
||||
#include "tests-crypto.h"
|
||||
|
||||
/*
|
||||
* all test vectors are from "Recommendation for Block Cipher Modes of
|
||||
* Operation - Methods and Techniques" by Morris Dworkin / NIST
|
||||
*
|
||||
* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||
*/
|
||||
|
||||
|
||||
/* PACKET VECTOR #1 (Page 55) */
|
||||
static uint8_t TEST_1_KEY[] = {
|
||||
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
|
||||
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
|
||||
};
|
||||
static uint8_t TEST_1_KEY_LEN = 16;
|
||||
|
||||
static uint8_t TEST_1_COUNTER[16] = {
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
|
||||
};
|
||||
|
||||
static uint8_t TEST_1_PLAIN[] = {
|
||||
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
|
||||
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
|
||||
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
|
||||
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
|
||||
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
|
||||
0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
|
||||
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
|
||||
0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
|
||||
};
|
||||
static uint8_t TEST_1_PLAIN_LEN = 64;
|
||||
|
||||
static uint8_t TEST_1_CIPHER[] = {
|
||||
0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26,
|
||||
0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce,
|
||||
0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff,
|
||||
0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff,
|
||||
0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e,
|
||||
0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab,
|
||||
0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1,
|
||||
0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee
|
||||
};
|
||||
static uint8_t TEST_1_CIPHER_LEN = 64;
|
||||
|
||||
static void test_encrypt_op(uint8_t* key, uint8_t key_len, uint8_t ctr[16],
|
||||
uint8_t* input, uint8_t input_len, uint8_t* output,
|
||||
uint8_t output_len)
|
||||
{
|
||||
cipher_t cipher;
|
||||
int len, err, cmp;
|
||||
uint8_t data[64];
|
||||
|
||||
err = cipher_init(&cipher, CIPHER_AES_128, key, key_len);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
len = cipher_encrypt_ctr(&cipher, ctr, 0, input, input_len, data);
|
||||
TEST_ASSERT_MESSAGE(len > 0, "Encryption failed");
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(output_len, len);
|
||||
cmp = compare(output, data, len);
|
||||
TEST_ASSERT_MESSAGE(1 == cmp , "wrong ciphertext");
|
||||
|
||||
}
|
||||
|
||||
static void test_decrypt_op(uint8_t* key, uint8_t key_len, uint8_t ctr[16],
|
||||
uint8_t* input, uint8_t input_len, uint8_t* output,
|
||||
uint8_t output_len)
|
||||
{
|
||||
cipher_t cipher;
|
||||
int len, err, cmp;
|
||||
uint8_t data[64];
|
||||
|
||||
err = cipher_init(&cipher, CIPHER_AES_128, key, key_len);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
len = cipher_decrypt_ctr(&cipher, ctr, 0, input, input_len, data);
|
||||
TEST_ASSERT_MESSAGE(len > 0, "Encryption failed");
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(output_len, len);
|
||||
cmp = compare(output, data, len);
|
||||
TEST_ASSERT_MESSAGE(1 == cmp , "wrong ciphertext");
|
||||
|
||||
}
|
||||
|
||||
static void test_crypto_modes_ctr_encrypt(void)
|
||||
{
|
||||
uint8_t ctr[16];
|
||||
|
||||
memcpy(ctr, TEST_1_COUNTER, 16);
|
||||
test_encrypt_op(TEST_1_KEY, TEST_1_KEY_LEN, ctr, TEST_1_PLAIN,
|
||||
TEST_1_PLAIN_LEN, TEST_1_CIPHER, TEST_1_CIPHER_LEN);
|
||||
}
|
||||
|
||||
static void test_crypto_modes_ctr_decrypt(void)
|
||||
{
|
||||
uint8_t ctr[16];
|
||||
|
||||
memcpy(ctr, TEST_1_COUNTER, 16);
|
||||
test_decrypt_op(TEST_1_KEY, TEST_1_KEY_LEN, ctr, TEST_1_CIPHER,
|
||||
TEST_1_CIPHER_LEN, TEST_1_PLAIN, TEST_1_PLAIN_LEN);
|
||||
}
|
||||
|
||||
|
||||
Test* tests_crypto_modes_ctr_tests(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_crypto_modes_ctr_encrypt),
|
||||
new_TestFixture(test_crypto_modes_ctr_decrypt)
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(crypto_modes_ctr_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test*)&crypto_modes_ctr_tests;
|
||||
}
|
122
tests/unittests/tests-crypto/tests-crypto-modes-ecb.c
Normal file
122
tests/unittests/tests-crypto/tests-crypto-modes-ecb.c
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Nico von Geyso
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "crypto/ciphers.h"
|
||||
#include "crypto/modes/ecb.h"
|
||||
#include "tests-crypto.h"
|
||||
|
||||
/*
|
||||
* all test vectors are from "Recommendation for Block Cipher Modes of
|
||||
* Operation - Methods and Techniques" by Morris Dworkin / NIST
|
||||
*
|
||||
* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||
*/
|
||||
|
||||
|
||||
/* PACKET VECTOR #1 (Page 24) */
|
||||
static uint8_t TEST_1_KEY[] = {
|
||||
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
|
||||
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
|
||||
};
|
||||
static uint8_t TEST_1_KEY_LEN = 16;
|
||||
|
||||
static uint8_t TEST_1_PLAIN[] = {
|
||||
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
|
||||
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
|
||||
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
|
||||
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
|
||||
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
|
||||
0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
|
||||
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
|
||||
0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
|
||||
};
|
||||
static uint8_t TEST_1_PLAIN_LEN = 64;
|
||||
|
||||
static uint8_t TEST_1_CIPHER[] = {
|
||||
0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60,
|
||||
0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97,
|
||||
0xf5, 0xd3, 0xd5, 0x85, 0x03, 0xb9, 0x69, 0x9d,
|
||||
0xe7, 0x85, 0x89, 0x5a, 0x96, 0xfd, 0xba, 0xaf,
|
||||
0x43, 0xb1, 0xcd, 0x7f, 0x59, 0x8e, 0xce, 0x23,
|
||||
0x88, 0x1b, 0x00, 0xe3, 0xed, 0x03, 0x06, 0x88,
|
||||
0x7b, 0x0c, 0x78, 0x5e, 0x27, 0xe8, 0xad, 0x3f,
|
||||
0x82, 0x23, 0x20, 0x71, 0x04, 0x72, 0x5d, 0xd4
|
||||
};
|
||||
static uint8_t TEST_1_CIPHER_LEN = 64;
|
||||
|
||||
static void test_encrypt_op(uint8_t* key, uint8_t key_len, uint8_t* input,
|
||||
uint8_t input_len, uint8_t* output,
|
||||
uint8_t output_len)
|
||||
{
|
||||
cipher_t cipher;
|
||||
int len, err, cmp;
|
||||
uint8_t data[64];
|
||||
|
||||
err = cipher_init(&cipher, CIPHER_AES_128, key, key_len);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
len = cipher_encrypt_ecb(&cipher, input, input_len, data);
|
||||
TEST_ASSERT_MESSAGE(len > 0, "Encryption failed");
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(output_len, len);
|
||||
cmp = compare(output, data, len);
|
||||
TEST_ASSERT_MESSAGE(1 == cmp , "wrong ciphertext");
|
||||
|
||||
}
|
||||
|
||||
static void test_decrypt_op(uint8_t* key, uint8_t key_len, uint8_t* input,
|
||||
uint8_t input_len, uint8_t* output,
|
||||
uint8_t output_len)
|
||||
{
|
||||
cipher_t cipher;
|
||||
int len, err, cmp;
|
||||
uint8_t data[64];
|
||||
|
||||
err = cipher_init(&cipher, CIPHER_AES_128, key, key_len);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
len = cipher_decrypt_ecb(&cipher, input, input_len, data);
|
||||
TEST_ASSERT_MESSAGE(len > 0, "Encryption failed");
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(output_len, len);
|
||||
cmp = compare(output, data, len);
|
||||
TEST_ASSERT_MESSAGE(1 == cmp , "wrong ciphertext");
|
||||
|
||||
}
|
||||
|
||||
static void test_crypto_modes_ecb_encrypt(void)
|
||||
{
|
||||
test_encrypt_op(TEST_1_KEY, TEST_1_KEY_LEN, TEST_1_PLAIN, TEST_1_PLAIN_LEN,
|
||||
TEST_1_CIPHER, TEST_1_CIPHER_LEN);
|
||||
}
|
||||
|
||||
static void test_crypto_modes_ecb_decrypt(void)
|
||||
{
|
||||
test_decrypt_op(TEST_1_KEY, TEST_1_KEY_LEN, TEST_1_CIPHER, TEST_1_CIPHER_LEN,
|
||||
TEST_1_PLAIN, TEST_1_PLAIN_LEN);
|
||||
}
|
||||
|
||||
|
||||
Test* tests_crypto_modes_ecb_tests(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_crypto_modes_ecb_encrypt),
|
||||
new_TestFixture(test_crypto_modes_ecb_decrypt)
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(crypto_modes_ecb_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test*)&crypto_modes_ecb_tests;
|
||||
}
|
96
tests/unittests/tests-crypto/tests-crypto-twofish.c
Normal file
96
tests/unittests/tests-crypto/tests-crypto-twofish.c
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Nico von Geyso
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "crypto/twofish.h"
|
||||
#include "tests-crypto.h"
|
||||
|
||||
static uint8_t TEST_0_KEY[] = {
|
||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||
0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF
|
||||
};
|
||||
|
||||
static uint8_t TEST_0_INP[] = {
|
||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||
0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF
|
||||
};
|
||||
static uint8_t TEST_0_ENC[] = {
|
||||
0x9F, 0xB6, 0x33, 0x37, 0x15, 0x1B, 0xE9, 0xC7,
|
||||
0x13, 0x06, 0xD1, 0x59, 0xEA, 0x7A, 0xFA, 0xA4
|
||||
};
|
||||
|
||||
static uint8_t TEST_1_KEY[] = {
|
||||
0x23, 0xA0, 0x18, 0x53, 0xFA, 0xB3, 0x89, 0x23,
|
||||
0x65, 0x89, 0x2A, 0xBC, 0x43, 0x99, 0xCC, 0x00
|
||||
};
|
||||
|
||||
static uint8_t TEST_1_INP[] = {
|
||||
0x11, 0x53, 0x81, 0xE2, 0x5F, 0x33, 0xE7, 0x41,
|
||||
0xBB, 0x12, 0x67, 0x38, 0xE9, 0x12, 0x54, 0x23
|
||||
};
|
||||
static uint8_t TEST_1_ENC[] = {
|
||||
0xEA, 0x27, 0x44, 0xBB, 0x15, 0x56, 0xDB, 0xF3,
|
||||
0x33, 0xD4, 0x90, 0x09, 0x44, 0x7B, 0x83, 0x57
|
||||
};
|
||||
|
||||
static void test_crypto_twofish_encrypt(void)
|
||||
{
|
||||
cipher_context_t ctx;
|
||||
int err;
|
||||
uint8_t data[TWOFISH_BLOCK_SIZE];
|
||||
|
||||
err = twofish_init(&ctx, TEST_0_KEY, TWOFISH_KEY_SIZE);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
err = twofish_encrypt(&ctx, TEST_0_INP, data);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
TEST_ASSERT_MESSAGE(1 == compare(TEST_0_ENC, data, TWOFISH_BLOCK_SIZE), "wrong ciphertext");
|
||||
|
||||
err = twofish_init(&ctx, TEST_1_KEY, TWOFISH_KEY_SIZE);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
err = twofish_encrypt(&ctx, TEST_1_INP, data);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
TEST_ASSERT_MESSAGE(1 == compare(TEST_1_ENC, data, TWOFISH_BLOCK_SIZE), "wrong ciphertext");
|
||||
}
|
||||
|
||||
static void test_crypto_twofish_decrypt(void)
|
||||
{
|
||||
|
||||
cipher_context_t ctx;
|
||||
int err;
|
||||
uint8_t data[TWOFISH_BLOCK_SIZE];
|
||||
|
||||
err = twofish_init(&ctx, TEST_0_KEY, TWOFISH_KEY_SIZE);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
err = twofish_decrypt(&ctx, TEST_0_ENC, data);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
TEST_ASSERT_MESSAGE(1 == compare(TEST_0_INP, data, TWOFISH_BLOCK_SIZE), "wrong plaintext");
|
||||
|
||||
err = twofish_init(&ctx, TEST_1_KEY, TWOFISH_KEY_SIZE);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
|
||||
err = twofish_decrypt(&ctx, TEST_1_ENC, data);
|
||||
TEST_ASSERT_EQUAL_INT(1, err);
|
||||
TEST_ASSERT_MESSAGE(1 == compare(TEST_1_INP, data, TWOFISH_BLOCK_SIZE), "wrong plaintext");
|
||||
}
|
||||
|
||||
Test* tests_crypto_twofish_tests(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_crypto_twofish_encrypt),
|
||||
new_TestFixture(test_crypto_twofish_decrypt),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(crypto_twofish_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test*)&crypto_twofish_tests;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Philipp Rosenkranz
|
||||
* Copyright (C) 2014 Nico von Geyso
|
||||
*
|
||||
* 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
|
||||
@ -12,4 +13,12 @@ void tests_crypto(void)
|
||||
{
|
||||
TESTS_RUN(tests_crypto_sha256_tests());
|
||||
TESTS_RUN(tests_crypto_chacha_tests());
|
||||
TESTS_RUN(tests_crypto_aes_tests());
|
||||
TESTS_RUN(tests_crypto_3des_tests());
|
||||
TESTS_RUN(tests_crypto_twofish_tests());
|
||||
TESTS_RUN(tests_crypto_cipher_tests());
|
||||
TESTS_RUN(tests_crypto_modes_ccm_tests());
|
||||
TESTS_RUN(tests_crypto_modes_ecb_tests());
|
||||
TESTS_RUN(tests_crypto_modes_cbc_tests());
|
||||
TESTS_RUN(tests_crypto_modes_ctr_tests());
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Philipp Rosenkranz
|
||||
* Copyright (C) 2014 Nico von Geyso
|
||||
*
|
||||
* 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
|
||||
@ -19,6 +20,7 @@
|
||||
#define TESTS_CRYPTO_H_
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "kernel.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -43,6 +45,26 @@ Test *tests_crypto_sha256_tests(void);
|
||||
*/
|
||||
Test *tests_crypto_chacha_tests(void);
|
||||
|
||||
static inline int compare(uint8_t a[16], uint8_t b[16], uint8_t len)
|
||||
{
|
||||
int result = 1;
|
||||
|
||||
for (uint8_t i = 0; i < len; ++i) {
|
||||
result &= a[i] == b[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Test* tests_crypto_aes_tests(void);
|
||||
Test* tests_crypto_3des_tests(void);
|
||||
Test* tests_crypto_twofish_tests(void);
|
||||
Test* tests_crypto_cipher_tests(void);
|
||||
Test* tests_crypto_modes_ccm_tests(void);
|
||||
Test* tests_crypto_modes_ecb_tests(void);
|
||||
Test* tests_crypto_modes_cbc_tests(void);
|
||||
Test* tests_crypto_modes_ctr_tests(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user