diff --git a/cpu/mc1322x/Makefile b/cpu/mc1322x/Makefile index 6edc8dc43e..29e6928ccc 100644 --- a/cpu/mc1322x/Makefile +++ b/cpu/mc1322x/Makefile @@ -4,6 +4,9 @@ DIRS = ifneq (,$(findstring mc1322x_adc,$(USEMODULE))) DIRS += adc endif +ifneq (,$(findstring mc1322x_asm,$(USEMODULE))) + DIRS += asm +endif all: $(BINDIR)$(MODULE).a @for i in $(DIRS) ; do $(MAKE) -C $$i ; done ; diff --git a/cpu/mc1322x/asm/Makefile b/cpu/mc1322x/asm/Makefile new file mode 100644 index 0000000000..6f90f68834 --- /dev/null +++ b/cpu/mc1322x/asm/Makefile @@ -0,0 +1,5 @@ +INCLUDES = -I$(RIOTBASE)/cpu/mc1322x/asm/include + +MODULE =mc1322x_asm + +include $(MAKEBASE)/Makefile.base diff --git a/cpu/mc1322x/asm/asm.c b/cpu/mc1322x/asm/asm.c new file mode 100644 index 0000000000..989a6176a7 --- /dev/null +++ b/cpu/mc1322x/asm/asm.c @@ -0,0 +1,182 @@ +/* + * asm.c - implementation of some basic encryptions using the mc1322x ASM module + * Copyright (C) 2013 Thomas Eichinger + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#include "asm.h" + +/** + * Turns on the ASM module and runs a self test. + * The self test needs 3330 clocks. + */ +void asm_turn_on(void) +{ + ASM->CONTROL_1_bits.ON = 1; + ASM->CONTROL_1_bits.NORMAL_MODE = 1; + ASM->CONTROL_1_bits.SELF_TEST = 1; + ASM->CONTROL_0_bits.START = 1; + + /* if the self test fails, this will never be true */ + while (!ASM->STATUS_bits.TEST_PASS) { + continue; + } + + ASM->CONTROL_1_bits.SELF_TEST = 0; +} + +/** + * Turns the ASM module off. + */ +void asm_turn_off(void) +{ + ASM->CONTROL_1_bits.ON = 0; +} + +/** + * For CTR encryption/decryption run this on each 128 bit block with the same CTR instance. + * This function blocks until the encryption/decryption finished after 13 clocks. + * + * \param keys The 128 bit key. \sa asm_keys_t + * \param data A 128 bit block to encrypt/decrypt. Holds the encrypted/decrypted + * data when finished \sa asm_data_t + * \param ctr Structure holding the counter for the encryption/decrpytion. The user + * is responsible to provide a decend counter function. \sa asm_ctr_t + */ +void asm_ctr_encryption_blocking(asm_keys_t *keys, asm_data_t *data, asm_ctr_t *ctr) +{ + ASM->ENC_KEY_0 = keys->value_0; + ASM->ENC_KEY_1 = keys->value_1; + ASM->ENC_KEY_2 = keys->value_2; + ASM->ENC_KEY_3 = keys->value_3; + + ASM->CONTROL_1_bits.CTR = 1; + + ASM->DATA_0 = data->value_0; + ASM->DATA_1 = data->value_1; + ASM->DATA_2 = data->value_2; + ASM->DATA_3 = data->value_3; + + ASM->COUNTER_0 = ctr->value_0; + ASM->COUNTER_1 = ctr->value_1; + ASM->COUNTER_2 = ctr->value_2; + ASM->COUNTER_3 = ctr->value_3; + + ASM->CONTROL_0_bits.START = 1; + + while (!ASM->STATUS_bits.DONE) { + continue; + } + + data->value_0 = ASM->COUNTER_RESULT_0; + data->value_1 = ASM->COUNTER_RESULT_1; + data->value_2 = ASM->COUNTER_RESULT_2; + data->value_3 = ASM->COUNTER_RESULT_3; +} + +/** + * Usage of the MAC functions. + * 1. Initialize with the keys. ( asm_cbc_mac_init(keys) ) + * 2. Update for each 128 bit block of data ( asm_cbc_mac_update(data) ) + * 3. Finish and read the computed data ( asm_cbc_mac_finish(data) ) + */ + +/** + * Initialize a MAC stream. + * \param keys Holding the 128 bit key \sa asm_keys_t + */ +void asm_cbc_mac_init(asm_keys_t *keys) +{ + ASM->CONTROL_0_bits.CLEAR = 1; + + ASM->ENC_KEY_0 = keys->value_0; + ASM->ENC_KEY_1 = keys->value_1; + ASM->ENC_KEY_2 = keys->value_2; + ASM->ENC_KEY_3 = keys->value_3; + + ASM->CONTROL_1_bits.CBC = 1; +} + +/** + * Updates a MAC stream. + * \param data Structure holding 128 bits of data. \sa asm_data_t + */ +void asm_cbc_mac_update_blocking(asm_data_t *data) +{ + ASM->DATA_0 = data->value_0; + ASM->DATA_1 = data->value_1; + ASM->DATA_2 = data->value_2; + ASM->DATA_3 = data->value_3; + + ASM->CONTROL_0_bits.START = 1; + + while (!ASM->STATUS_bits.DONE) { + continue; + } +} + +/** + * Finishes a MAC stream + * \param data Structure holding the result of the MAC computation. \sa asm_data_t + */ +void asm_cbc_mac_finish(asm_data_t *data) +{ + data->value_0 = ASM->CBC_MAC_RESULT_0; + data->value_1 = ASM->CBC_MAC_RESULT_1; + data->value_2 = ASM->CBC_MAC_RESULT_2; + data->value_3 = ASM->CBC_MAC_RESULT_3; + + ASM->CONTROL_0_bits.CLEAR = 1; +} + +/** + * Initialize a MAC stream for combined mode. + * \param keys Holding the 128 bit key \sa asm_keys_t + */ +void asm_ctr_cbc_mac_init(asm_keys_t *keys) +{ + asm_cbc_mac_init(keys); +} + +/** + * Updates a MAC stream and encrypts data. + * \param data Structure holding 128 bits of data to use in MAC stream and to encrypt. + Holds the encrypted data when finished. \sa asm_data_t + * \param ctr Structure holding the counter for the encryption/decrpytion. The user + * is responsible to provide a decend counter function. \sa asm_ctr_t + */ +void asm_ctr_cbc_mac_update(asm_data_t *data, asm_ctr_t *ctr) +{ + ASM->DATA_0 = data->value_0; + ASM->DATA_1 = data->value_1; + ASM->DATA_2 = data->value_2; + ASM->DATA_3 = data->value_3; + + ASM->COUNTER_0 = ctr->value_0; + ASM->COUNTER_1 = ctr->value_1; + ASM->COUNTER_2 = ctr->value_2; + ASM->COUNTER_3 = ctr->value_3; + + ASM->CONTROL_0_bits.START = 1; + + while (!ASM->STATUS_bits.DONE) { + continue; + } + + data->value_0 = ASM->COUNTER_RESULT_0; + data->value_1 = ASM->COUNTER_RESULT_1; + data->value_2 = ASM->COUNTER_RESULT_2; + data->value_3 = ASM->COUNTER_RESULT_3; +} +/** + * Finishes a MAC stream for combined mode + * \param data Structure holding the result of the MAC computation. \sa asm_data_t + */ +void asm_ctr_cbc_mac_finish(asm_data_t *data) +{ + asm_cbc_mac_finish(data); +} diff --git a/cpu/mc1322x/asm/include/asm.h b/cpu/mc1322x/asm/include/asm.h new file mode 100644 index 0000000000..dc301b6f7d --- /dev/null +++ b/cpu/mc1322x/asm/include/asm.h @@ -0,0 +1,104 @@ +/* + * asm.h - defines registers for the Advanced Security Module of the mc1322x + * Copyright (C) 2013 Thomas Eichinger + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#ifndef ASM_H +#define ASM_H + +#include + +#define ASM_BASE_ADDRESS 0x80008000 + +struct ASM_struct { + uint32_t ENC_KEY_0; ///< Encryption key 0:31 + uint32_t ENC_KEY_1; ///< Encryption key 32:63 + uint32_t ENC_KEY_2; ///< Encryption key 64:95 + uint32_t ENC_KEY_3; ///< Encryption key 96:127 + uint32_t DATA_0; ///< Data 0:31 + uint32_t DATA_1; ///< Data 32:63 + uint32_t DATA_2; ///< Data 64:95 + uint32_t DATA_3; ///< Data 96:127 + uint32_t COUNTER_0; ///< Counter 0:31 + uint32_t COUNTER_1; ///< Counter 32:63 + uint32_t COUNTER_2; ///< Counter 64:95 + uint32_t COUNTER_3; ///< Counter 96:127 + uint32_t COUNTER_RESULT_0; ///< Result of CTR calculation 0:31 + uint32_t COUNTER_RESULT_1; ///< Result of CTR calculation 32:63 + uint32_t COUNTER_RESULT_2; ///< Result of CTR calculation 64:95 + uint32_t COUNTER_RESULT_3; ///< Result of CTR calculation 96:127 + uint32_t CBC_MAC_RESULT_0; ///< Result of CBC-MAC 0:31 + uint32_t CBC_MAC_RESULT_1; ///< Result of CBC-MAC 32:63 + uint32_t CBC_MAC_RESULT_2; ///< Result of CBC-MAC 64:95 + uint32_t CBC_MAC_RESULT_3; ///< Result of CBC-MAC 96:127 + union { + uint32_t CONTROL_0; ///< Control 0 register + struct ASM_CONTROL_0 { + uint32_t : 24; + uint32_t START: 1; ///< Start calculation + uint32_t CLEAR: 1; ///< Clear all configurations + uint32_t LOAD_MAC: 1; ///< Load an initila MAC value to continue + uint32_t : 4; + uint32_t CLEAR_IRQ; ///< Clear ASM IRQ bit + } CONTROL_0_bits; + }; + union { + uint32_t CONTROL_1; ///< Control 1 register + struct ASM_CONTROL_1 { + uint32_t ON: 1; ///< Turn ASM module on + uint32_t NORMAL_MODE: 1;///< exit boot mode + uint32_t BYPASS: 1; ///< Data passes through unmodified + uint32_t : 21; + uint32_t CBC: 1; ///< enable CBC-MAC mode + uint32_t CTR: 1; ///< enable CTR mode + uint32_t SELF_TEST: 1; ///< switch to self test mode + uint32_t : 4; + uint32_t MASK_IRQ: 1; ///< disables the ASM IRQ + } CONTROL_1_bits; + }; + union { + uint32_t STATUS; ///< status register + struct ASM_STATUS { + uint32_t : 24; + uint32_t DONE: 1; ///< operation is done + uint32_t TEST_PASS: 1; ///< self test did pass + uint32_t : 6; + } STATUS_bits; + }; + uint32_t reserved; + uint32_t CBC_MAC_0; ///< Result of MAC calculation 0:31 + uint32_t CBC_MAC_1; ///< Result of MAC calculation 32:63 + uint32_t CBC_MAC_2; ///< Result of MAC calculation 64:95 + uint32_t CBC_MAC_3; ///< Result of MAC calculation 96:127 +}; + +static volatile struct ASM_struct *const ASM = (void *)(ASM_BASE_ADDRESS); + +struct ASM_Container { + uint32_t value_0; + uint32_t value_1; + uint32_t value_2; + uint32_t value_3; +}; +typedef struct ASM_Container asm_keys_t; +typedef struct ASM_Container asm_data_t; +typedef struct ASM_Container asm_ctr_t; + +/* function prototypes */ + +void asm_turn_on(void); +void asm_turn_off(void); +void asm_ctr_encryption_blocking(asm_keys_t *keys, asm_data_t *data, asm_ctr_t *ctr); +void asm_cbc_mac_init(asm_keys_t *keys); +void asm_cbc_mac_update_blocking(asm_data_t *data); +void asm_cbc_mac_finish(asm_data_t *data); +void asm_ctr_cbc_mac_init(asm_keys_t *keys); +void asm_ctr_cbc_mac_update(asm_data_t *data, asm_ctr_t *ctr); +void asm_ctr_cbc_mac_finish(asm_data_t *data); + +#endif /* ASM_H */