cc2538: aes: Make it possible to have several keys stored at once

Several keys can be kept at the same time in the key store, and several
keys can be loaded at once. Give access to these features.

The ccm-test example is also improved to better demonstrate the use of
the key store.

Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
This commit is contained in:
Benoît Thébaudeau 2015-05-15 19:56:15 +02:00
parent b92a5afcc4
commit 801315e819
3 changed files with 54 additions and 47 deletions

View file

@ -48,16 +48,18 @@
#include <stdint.h> #include <stdint.h>
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uint8_t uint8_t
aes_load_key(const void *key, uint8_t key_area) aes_load_keys(const void *keys, uint8_t count, uint8_t start_area)
{ {
uint32_t aligned_key[4]; uint32_t aes_key_store_size;
uint32_t areas;
uint32_t aligned_keys[32];
if(REG(AES_CTRL_ALG_SEL) != 0x00000000) { if(REG(AES_CTRL_ALG_SEL) != 0x00000000) {
return CRYPTO_RESOURCE_IN_USE; return CRYPTO_RESOURCE_IN_USE;
} }
/* The key address needs to be 4-byte aligned */ /* The keys base address needs to be 4-byte aligned */
rom_util_memcpy(aligned_key, key, sizeof(aligned_key)); rom_util_memcpy(aligned_keys, keys, count << 4);
/* Workaround for AES registers not retained after PM2 */ /* Workaround for AES registers not retained after PM2 */
REG(AES_CTRL_INT_CFG) = AES_CTRL_INT_CFG_LEVEL; REG(AES_CTRL_INT_CFG) = AES_CTRL_INT_CFG_LEVEL;
@ -71,25 +73,34 @@ aes_load_key(const void *key, uint8_t key_area)
REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE | REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE |
AES_CTRL_INT_CLR_RESULT_AV; AES_CTRL_INT_CLR_RESULT_AV;
/* Configure key store module (area, size): 128-bit key size */ /* Configure key store module (areas, size): 128-bit key size
REG(AES_KEY_STORE_SIZE) = (REG(AES_KEY_STORE_SIZE) & * Note that writing AES_KEY_STORE_SIZE deletes all stored keys */
~AES_KEY_STORE_SIZE_KEY_SIZE_M) | aes_key_store_size = REG(AES_KEY_STORE_SIZE);
AES_KEY_STORE_SIZE_KEY_SIZE_128; if((aes_key_store_size & AES_KEY_STORE_SIZE_KEY_SIZE_M) !=
AES_KEY_STORE_SIZE_KEY_SIZE_128) {
REG(AES_KEY_STORE_SIZE) = (aes_key_store_size &
~AES_KEY_STORE_SIZE_KEY_SIZE_M) |
AES_KEY_STORE_SIZE_KEY_SIZE_128;
}
/* Enable keys to write (e.g. Key 0) */ /* Free possibly already occupied key areas */
REG(AES_KEY_STORE_WRITE_AREA) = 0x00000001 << key_area; areas = ((0x00000001 << count) - 1) << start_area;
REG(AES_KEY_STORE_WRITTEN_AREA) = areas;
/* Enable key areas to write */
REG(AES_KEY_STORE_WRITE_AREA) = areas;
/* Configure DMAC /* Configure DMAC
* Enable DMA channel 0 */ * Enable DMA channel 0 */
REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN; REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN;
/* Base address of the key in ext. memory */ /* Base address of the keys in ext. memory */
REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)aligned_key; REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)aligned_keys;
/* Total key length in bytes (e.g. 16 for 1 x 128-bit key) */ /* Total keys length in bytes (e.g. 16 for 1 x 128-bit key) */
REG(AES_DMAC_CH0_DMALENGTH) = (REG(AES_DMAC_CH0_DMALENGTH) & REG(AES_DMAC_CH0_DMALENGTH) = (REG(AES_DMAC_CH0_DMALENGTH) &
~AES_DMAC_CH_DMALENGTH_DMALEN_M) | ~AES_DMAC_CH_DMALENGTH_DMALEN_M) |
(0x10 << AES_DMAC_CH_DMALENGTH_DMALEN_S); (count << (4 + AES_DMAC_CH_DMALENGTH_DMALEN_S));
/* Wait for operation to complete */ /* Wait for operation to complete */
while(!(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_RESULT_AV)); while(!(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_RESULT_AV));
@ -116,7 +127,7 @@ aes_load_key(const void *key, uint8_t key_area)
REG(AES_CTRL_ALG_SEL) = 0x00000000; REG(AES_CTRL_ALG_SEL) = 0x00000000;
/* Check status, if error return error code */ /* Check status, if error return error code */
if(!(REG(AES_KEY_STORE_WRITTEN_AREA) & (0x00000001 << key_area))) { if((REG(AES_KEY_STORE_WRITTEN_AREA) & areas) != areas) {
return AES_KEYSTORE_WRITE_ERROR; return AES_KEYSTORE_WRITE_ERROR;
} }

View file

@ -470,12 +470,13 @@
* @{ * @{
*/ */
/** \brief Writes the key into the Key RAM /** \brief Writes keys into the Key RAM
* \param key Pointer to AES Key * \param keys Pointer to AES Keys
* \param key_area Area in Key RAM where to store the key (0 to 7) * \param count Number of keys (1 to 8 - \p start_area)
* \param start_area Start area in Key RAM where to store the key (0 to 7)
* \return \c CRYPTO_SUCCESS if successful, or CRYPTO/AES error code * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/AES error code
*/ */
uint8_t aes_load_key(const void *key, uint8_t key_area); uint8_t aes_load_keys(const void *keys, uint8_t count, uint8_t start_area);
/** @} */ /** @} */

View file

@ -73,10 +73,15 @@ PROCESS_THREAD(ccm_test_process, ev, data)
"keystore write error", "keystore write error",
"authentication failed" "authentication failed"
}; };
static const uint8_t keys[][16] = {
{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf }
};
static struct { static struct {
bool encrypt; bool encrypt;
uint8_t len_len; uint8_t len_len;
uint8_t key[16];
uint8_t key_area; uint8_t key_area;
uint8_t nonce[13]; uint8_t nonce[13];
uint8_t adata[26]; uint8_t adata[26];
@ -90,8 +95,6 @@ PROCESS_THREAD(ccm_test_process, ev, data)
{ {
true, /* encrypt */ true, /* encrypt */
2, /* len_len */ 2, /* len_len */
{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* key */
0, /* key_area */ 0, /* key_area */
{ 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, { 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0,
0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */ 0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */
@ -109,9 +112,7 @@ PROCESS_THREAD(ccm_test_process, ev, data)
}, { }, {
true, /* encrypt */ true, /* encrypt */
2, /* len_len */ 2, /* len_len */
{ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 1, /* key_area */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf }, /* key */
0, /* key_area */
{ 0xac, 0xde, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, { 0xac, 0xde, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x05, 0x02 }, /* nonce */ 0x00, 0x00, 0x00, 0x05, 0x02 }, /* nonce */
{ 0x08, 0xd0, 0x84, 0x21, 0x43, 0x01, 0x00, 0x00, { 0x08, 0xd0, 0x84, 0x21, 0x43, 0x01, 0x00, 0x00,
@ -127,8 +128,6 @@ PROCESS_THREAD(ccm_test_process, ev, data)
}, { }, {
true, /* encrypt */ true, /* encrypt */
2, /* len_len */ 2, /* len_len */
{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* key */
0, /* key_area */ 0, /* key_area */
{ 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, { 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0,
0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */ 0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */
@ -147,8 +146,6 @@ PROCESS_THREAD(ccm_test_process, ev, data)
}, { }, {
false, /* decrypt */ false, /* decrypt */
2, /* len_len */ 2, /* len_len */
{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* key */
0, /* key_area */ 0, /* key_area */
{ 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, { 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0,
0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */ 0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */
@ -166,9 +163,7 @@ PROCESS_THREAD(ccm_test_process, ev, data)
}, { }, {
false, /* decrypt */ false, /* decrypt */
2, /* len_len */ 2, /* len_len */
{ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 1, /* key_area */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf }, /* key */
0, /* key_area */
{ 0xac, 0xde, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, { 0xac, 0xde, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x05, 0x02 }, /* nonce */ 0x00, 0x00, 0x00, 0x05, 0x02 }, /* nonce */
{ 0x08, 0xd0, 0x84, 0x21, 0x43, 0x01, 0x00, 0x00, { 0x08, 0xd0, 0x84, 0x21, 0x43, 0x01, 0x00, 0x00,
@ -184,8 +179,6 @@ PROCESS_THREAD(ccm_test_process, ev, data)
}, { }, {
false, /* decrypt */ false, /* decrypt */
2, /* len_len */ 2, /* len_len */
{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* key */
0, /* key_area */ 0, /* key_area */
{ 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, { 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0,
0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */ 0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */
@ -213,6 +206,18 @@ PROCESS_THREAD(ccm_test_process, ev, data)
"Initializing cryptoprocessor..."); "Initializing cryptoprocessor...");
crypto_init(); crypto_init();
puts("-----------------------------------------\n"
"Filling key store...");
time = RTIMER_NOW();
ret = aes_load_keys(keys, sizeof(keys) / sizeof(keys[0]), 0);
time = RTIMER_NOW() - time;
printf("aes_load_keys(): %s, %lu us\n", str_res[ret],
(uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND));
PROCESS_PAUSE();
if(ret != CRYPTO_SUCCESS) {
goto fatal;
}
for(i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) { for(i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) {
printf("-----------------------------------------\n" printf("-----------------------------------------\n"
"Test vector #%d: %s\n" "Test vector #%d: %s\n"
@ -222,17 +227,6 @@ PROCESS_THREAD(ccm_test_process, ev, data)
vectors[i].len_len, vectors[i].key_area, vectors[i].len_len, vectors[i].key_area,
vectors[i].adata_len, vectors[i].mdata_len, vectors[i].mic_len); vectors[i].adata_len, vectors[i].mdata_len, vectors[i].mic_len);
time = RTIMER_NOW();
ret = aes_load_key(vectors[i].key, vectors[i].key_area);
time = RTIMER_NOW() - time;
total_time = time;
printf("aes_load_key(): %s, %lu us\n", str_res[ret],
(uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND));
PROCESS_PAUSE();
if(ret != CRYPTO_SUCCESS) {
continue;
}
time = RTIMER_NOW(); time = RTIMER_NOW();
if(vectors[i].encrypt) { if(vectors[i].encrypt) {
ret = ccm_auth_encrypt_start(vectors[i].len_len, vectors[i].key_area, ret = ccm_auth_encrypt_start(vectors[i].len_len, vectors[i].key_area,
@ -242,7 +236,7 @@ PROCESS_THREAD(ccm_test_process, ev, data)
&ccm_test_process); &ccm_test_process);
time2 = RTIMER_NOW(); time2 = RTIMER_NOW();
time = time2 - time; time = time2 - time;
total_time += time; total_time = time;
if(ret == CRYPTO_SUCCESS) { if(ret == CRYPTO_SUCCESS) {
PROCESS_WAIT_EVENT_UNTIL(ccm_auth_encrypt_check_status()); PROCESS_WAIT_EVENT_UNTIL(ccm_auth_encrypt_check_status());
time2 = RTIMER_NOW() - time2; time2 = RTIMER_NOW() - time2;
@ -290,7 +284,7 @@ PROCESS_THREAD(ccm_test_process, ev, data)
&ccm_test_process); &ccm_test_process);
time2 = RTIMER_NOW(); time2 = RTIMER_NOW();
time = time2 - time; time = time2 - time;
total_time += time; total_time = time;
if(ret == CRYPTO_SUCCESS) { if(ret == CRYPTO_SUCCESS) {
PROCESS_WAIT_EVENT_UNTIL(ccm_auth_decrypt_check_status()); PROCESS_WAIT_EVENT_UNTIL(ccm_auth_decrypt_check_status());
time2 = RTIMER_NOW() - time2; time2 = RTIMER_NOW() - time2;
@ -329,6 +323,7 @@ PROCESS_THREAD(ccm_test_process, ev, data)
(uint32_t)((uint64_t)total_time * 1000000 / RTIMER_SECOND)); (uint32_t)((uint64_t)total_time * 1000000 / RTIMER_SECOND));
} }
fatal:
puts("-----------------------------------------\n" puts("-----------------------------------------\n"
"Disabling cryptoprocessor..."); "Disabling cryptoprocessor...");
crypto_disable(); crypto_disable();