Contiki-NG
Loading...
Searching...
No Matches
cc2538-ccm-star.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019, Hasso-Plattner-Institut.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/**
33 * \addtogroup cc2538-ccm-star
34 * @{
35 *
36 * \file
37 * Implementation of the CCM* driver for the CC2538 SoC
38 * \author
39 * Konrad Krentz <konrad.krentz@gmail.com>
40 */
41
42#include "dev/cc2538-ccm-star.h"
43#include "dev/aes.h"
44#include "dev/cc2538-aes-128.h"
45#include "lib/assert.h"
46#include <stdbool.h>
47#include <string.h>
48
49#define CCM_L 2
50#define CCM_FLAGS_LEN 1
51
52/* Log configuration */
53#include "sys/log.h"
54#define LOG_MODULE "cc2538-ccm-star"
55#define LOG_LEVEL LOG_LEVEL_NONE
56
57typedef union {
58 uint8_t u8[AES_128_BLOCK_SIZE];
59 uint32_t u32[AES_128_BLOCK_SIZE / sizeof(uint32_t)];
60} block_t;
61
62/*---------------------------------------------------------------------------*/
63static void
64set_key(const uint8_t *key)
65{
66 cc2538_aes_128_driver.set_key(key);
67}
68/*---------------------------------------------------------------------------*/
69static void
70aead(const uint8_t *nonce, uint8_t *m, uint16_t m_len, const uint8_t *a,
71 uint16_t a_len, uint8_t *result, uint8_t mic_len, int forward)
72{
73 if(!a_len && !m_len) {
74 /* fall back on software implementation as the hardware implementation
75 * would freeze */
76 ccm_star_driver.aead(nonce, m, m_len, a, a_len, result, mic_len, forward);
77 return;
78 }
79
80 bool was_crypto_enabled = CRYPTO_IS_ENABLED();
81 if(!was_crypto_enabled) {
83 }
84
85 /* all previous interrupts should have been acknowledged */
86 assert(!REG(AES_CTRL_INT_STAT));
87
88 /* set up AES interrupts */
92
93 /* enable the DMA path to the AES engine */
95
96 /* configure the key store to provide pre-loaded AES key */
97 REG(AES_KEY_STORE_READ_AREA) = CC2538_AES_128_KEY_AREA;
98
99 /* prepare IV while the AES key loads */
100 {
101 block_t iv;
102 iv.u8[0] = CCM_L - 1;
103 memcpy(iv.u8 + CCM_FLAGS_LEN, nonce, CCM_STAR_NONCE_LENGTH);
104 memset(iv.u8 + CCM_FLAGS_LEN + CCM_STAR_NONCE_LENGTH,
105 0,
106 AES_128_BLOCK_SIZE - CCM_FLAGS_LEN - CCM_STAR_NONCE_LENGTH);
107
108 /* wait until the AES key is loaded */
110
111 /* check that the key was loaded without errors */
113 LOG_ERR("error at line %d\n", __LINE__);
114 /* clear error */
116 goto exit;
117 }
118
119 /* write the initialization vector */
120 REG(AES_AES_IV_0) = iv.u32[0];
121 REG(AES_AES_IV_1) = iv.u32[1];
122 REG(AES_AES_IV_2) = iv.u32[2];
123 REG(AES_AES_IV_3) = iv.u32[3];
124 }
125
126 /* configure AES engine */
127 REG(AES_AES_CTRL) = AES_AES_CTRL_SAVE_CONTEXT /* Save context */
128 | (((MAX(mic_len, 2) - 2) >> 1) << AES_AES_CTRL_CCM_M_S) /* M */
129 | ((CCM_L - 1) << AES_AES_CTRL_CCM_L_S) /* L */
130 | AES_AES_CTRL_CCM /* CCM */
131 | AES_AES_CTRL_CTR_WIDTH_128 /* CTR width 128 */
132 | AES_AES_CTRL_CTR /* CTR */
133 | (forward ? AES_AES_CTRL_DIRECTION_ENCRYPT : 0); /* En/decryption */
134 /* write m_len (lo) */
135 REG(AES_AES_C_LENGTH_0) = m_len;
136 /* write m_len (hi) */
137 REG(AES_AES_C_LENGTH_1) = 0;
138 /* write a_len */
139 REG(AES_AES_AUTH_LENGTH) = a_len;
140
141 /* configure DMAC to fetch "a" */
142 if(a_len) {
143 /* enable DMA channel 0 */
145 /* base address of "a" in external memory */
146 REG(AES_DMAC_CH0_EXTADDR) = (uintptr_t)a;
147 /* length of the input data to be transferred */
148 REG(AES_DMAC_CH0_DMALENGTH) = a_len;
149
150 /* wait for completion of the DMA transfer */
152
153 /* acknowledge the interrupt */
155
156 /* check for errors */
158 LOG_ERR("error at line %d\n", __LINE__);
159 /* clear error */
161 goto exit;
162 }
163 }
164
165 /* configure DMAC to fetch "m" */
166 if(m_len) {
167 /* disable DMA_IN interrupt for this transfer */
169 /* enable DMA channel 0 */
171 /* base address of "m" in external memory */
172 REG(AES_DMAC_CH0_EXTADDR) = (uintptr_t)m;
173 /* length of the input data to be transferred */
174 REG(AES_DMAC_CH0_DMALENGTH) = m_len;
175 /* enable DMA channel 1 */
177 /* base address of the output in external memory */
178 REG(AES_DMAC_CH1_EXTADDR) = (uintptr_t)m;
179 /* length of the output data to be transferred */
180 REG(AES_DMAC_CH1_DMALENGTH) = m_len;
181 }
182
183 /* wait for completion */
185
186 /* acknowledge interrupt */
188
189 /* check for errors */
190 uint32_t errors = REG(AES_CTRL_INT_STAT)
192 if(errors) {
193 LOG_ERR("error at line %d\n", __LINE__);
194 /* clear errors */
195 REG(AES_CTRL_INT_CLR) = errors;
196 goto exit;
197 }
198
199 /* wait for the context ready bit */
201
202 /* read tag */
203 {
204 block_t tag;
205 tag.u32[0] = REG(AES_AES_TAG_OUT_0);
206 tag.u32[1] = REG(AES_AES_TAG_OUT_1);
207 tag.u32[2] = REG(AES_AES_TAG_OUT_2);
208
209 /* this read clears the ‘saved_context_ready’ flag */
210 tag.u32[3] = REG(AES_AES_TAG_OUT_3);
211
212 memcpy(result, tag.u8, mic_len);
213 }
214
215exit:
216 /* all interrupts should have been acknowledged */
217 assert(!REG(AES_CTRL_INT_STAT));
218
219 /* disable master control/DMA clock */
220 REG(AES_CTRL_ALG_SEL) = 0;
221 if(!was_crypto_enabled) {
223 }
224}
225/*---------------------------------------------------------------------------*/
226const struct ccm_star_driver cc2538_ccm_star_driver = {
227 set_key,
228 aead
229};
230/*---------------------------------------------------------------------------*/
231
232/** @} */
Header file for the cc2538 AES driver.
Header file of the AES-128 driver for the CC2538 SoC.
Header file of the AES-CCM* driver for the CC2538 SoC.
#define AES_CTRL_INT_CLR
Interrupt clear.
Definition aes.h:135
#define AES_AES_IV_0
AES initialization vector.
Definition aes.h:86
#define AES_AES_CTRL_SAVED_CONTEXT_READY
AES auth.
Definition aes.h:271
#define AES_DMAC_CH1_CTRL
Channel 1 control.
Definition aes.h:65
#define AES_AES_CTRL_DIRECTION_ENCRYPT
Encrypt.
Definition aes.h:297
#define AES_AES_CTRL_CTR_WIDTH_128
CTR counter width: 128 bits.
Definition aes.h:285
#define AES_CTRL_INT_CFG
Interrupt configuration.
Definition aes.h:133
#define AES_AES_TAG_OUT_2
TAG.
Definition aes.h:100
#define AES_CTRL_INT_CFG_LEVEL
Level interrupt type.
Definition aes.h:366
#define AES_DMAC_CH1_DMALENGTH
Channel 1 DMA length.
Definition aes.h:67
#define AES_AES_IV_3
AES initialization vector.
Definition aes.h:89
#define AES_AES_CTRL_CCM_M_S
CCM auth.
Definition aes.h:276
#define AES_CTRL_INT_EN_DMA_IN_DONE
DMA input done interrupt enabled.
Definition aes.h:372
#define AES_AES_CTRL
AES input/output buffer control and mode.
Definition aes.h:90
#define AES_AES_CTRL_CCM_L_S
CCM length field width shift.
Definition aes.h:278
#define AES_CTRL_INT_STAT_KEY_ST_RD_ERR
Read error detected.
Definition aes.h:409
#define AES_CTRL_INT_STAT_DMA_BUS_ERR
DMA bus error detected.
Definition aes.h:405
#define AES_AES_AUTH_LENGTH
Authentication length.
Definition aes.h:93
#define AES_AES_CTRL_CCM
AES-CCM mode.
Definition aes.h:279
#define AES_DMAC_CH0_CTRL
Channel 0 control.
Definition aes.h:60
#define AES_DMAC_CH_CTRL_EN
Channel enable.
Definition aes.h:146
#define AES_KEY_STORE_READ_AREA_BUSY
Key store operation busy.
Definition aes.h:258
#define AES_AES_IV_2
AES initialization vector.
Definition aes.h:88
#define AES_AES_TAG_OUT_1
TAG.
Definition aes.h:99
#define AES_CTRL_INT_CLR_DMA_IN_DONE
Clear DMA in done interrupt.
Definition aes.h:387
#define AES_DMAC_CH0_EXTADDR
Channel 0 external address.
Definition aes.h:61
#define AES_CTRL_INT_EN_RESULT_AV
Result available interrupt enabled.
Definition aes.h:374
#define AES_KEY_STORE_READ_AREA
Key store read area.
Definition aes.h:77
#define AES_DMAC_CH1_EXTADDR
Channel 1 external address.
Definition aes.h:66
#define AES_AES_C_LENGTH_1
AES crypto length (MSW)
Definition aes.h:92
#define AES_AES_TAG_OUT_0
TAG.
Definition aes.h:98
#define AES_AES_CTRL_SAVE_CONTEXT
Auth.
Definition aes.h:273
#define AES_AES_TAG_OUT_3
TAG.
Definition aes.h:101
#define AES_AES_C_LENGTH_0
AES crypto length (LSW)
Definition aes.h:91
#define AES_CTRL_INT_STAT_DMA_IN_DONE
DMA data in done interrupt status.
Definition aes.h:411
#define AES_CTRL_INT_CLR_RESULT_AV
Clear result available interrupt.
Definition aes.h:389
#define AES_CTRL_ALG_SEL
Algorithm select.
Definition aes.h:130
#define AES_CTRL_ALG_SEL_AES
Select AES engine as DMA source/destination.
Definition aes.h:344
#define AES_AES_CTRL_CTR
AES-CTR mode.
Definition aes.h:290
#define AES_CTRL_INT_STAT
Interrupt status.
Definition aes.h:137
#define AES_DMAC_CH0_DMALENGTH
Channel 0 DMA length.
Definition aes.h:62
#define AES_CTRL_INT_EN
Interrupt enable.
Definition aes.h:134
#define AES_CTRL_INT_STAT_RESULT_AV
Result available interrupt status.
Definition aes.h:413
#define AES_AES_IV_1
AES initialization vector.
Definition aes.h:87
void crypto_enable(void)
Enables the AES/SHA cryptoprocessor.
Definition crypto.c:92
#define CRYPTO_IS_ENABLED()
Indicates whether the AES/SHA cryptoprocessor is enabled.
Definition crypto.h:69
void crypto_disable(void)
Disables the AES/SHA cryptoprocessor.
Definition crypto.c:101
Header file for the logging system.
void(* set_key)(const uint8_t *key)
Sets the current key.
Definition aes-128.h:62
Structure of CCM* drivers.
Definition ccm-star.h:56
void(* aead)(const uint8_t *nonce, uint8_t *m, uint16_t m_len, const uint8_t *a, uint16_t a_len, uint8_t *result, uint8_t mic_len, int forward)
Combines authentication and encryption.
Definition ccm-star.h:75
void(* set_key)(const uint8_t *key)
Sets the key in use.
Definition ccm-star.h:64