Contiki-NG
Loading...
Searching...
No Matches
cc2538-sha-256.c
Go to the documentation of this file.
1/*
2 * Original file:
3 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
4 * All rights reserved.
5 *
6 * Port to Contiki:
7 * Copyright (c) 2013, ADVANSEE - http://www.advansee.com/
8 * All rights reserved.
9 *
10 * Adaptation to platform-independent API:
11 * Copyright (c) 2021, Uppsala universitet
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 *
23 * 3. Neither the name of the copyright holder nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
31 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
38 * OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40/**
41 * \addtogroup cc2538-sha-256
42 * @{
43 *
44 * \file
45 * Implementation of the cc2538 SHA-256 driver
46 */
47
48#include "dev/cc2538-sha-256.h"
49#include "dev/udma.h"
50#include "dev/aes.h"
51#include "lib/aes-128.h"
52#include "lib/assert.h"
53#include <stdbool.h>
54
55/* Log configuration */
56#include "sys/log.h"
57#define LOG_MODULE "cc2538-sha-256"
58#define LOG_LEVEL LOG_LEVEL_NONE
59
60static const uint8_t empty_digest[SHA_256_DIGEST_LENGTH] = {
61 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
62 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
63 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
64 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
65};
66static sha_256_checkpoint_t checkpoint;
67static bool was_crypto_enabled;
68
69/*---------------------------------------------------------------------------*/
70static void
71enable_crypto(void)
72{
73 was_crypto_enabled = CRYPTO_IS_ENABLED();
74 if(!was_crypto_enabled) {
76 }
77 /* enable DMA path to the SHA-256 engine + Digest readout */
79}
80/*---------------------------------------------------------------------------*/
81static void
82disable_crypto(void)
83{
84 /* disable master control/DMA clock */
85 REG(AES_CTRL_ALG_SEL) = 0;
86 if(!was_crypto_enabled) {
88 }
89}
90/*---------------------------------------------------------------------------*/
91static void
92do_hash(const uint8_t *data, size_t len,
93 void *digest, uint64_t final_bit_count)
94{
95 /* DMA fails if data does not reside in RAM */
96 assert(udma_is_valid_source_address((uintptr_t)data));
97 /* all previous interrupts should have been acknowledged */
98 assert(!REG(AES_CTRL_INT_STAT));
99
100 /* set up AES interrupts */
103
104 if(checkpoint.bit_count) {
105 /* configure resumed hash session */
107 REG(AES_HASH_DIGEST_A) = checkpoint.state[0];
108 REG(AES_HASH_DIGEST_B) = checkpoint.state[1];
109 REG(AES_HASH_DIGEST_C) = checkpoint.state[2];
110 REG(AES_HASH_DIGEST_D) = checkpoint.state[3];
111 REG(AES_HASH_DIGEST_E) = checkpoint.state[4];
112 REG(AES_HASH_DIGEST_F) = checkpoint.state[5];
113 REG(AES_HASH_DIGEST_G) = checkpoint.state[6];
114 REG(AES_HASH_DIGEST_H) = checkpoint.state[7];
115 } else {
116 /* configure new hash session */
119 }
120
121 if(final_bit_count) {
122 /* configure for generating the final hash */
123 REG(AES_HASH_LENGTH_IN_L) = final_bit_count;
124 REG(AES_HASH_LENGTH_IN_H) = final_bit_count >> 32;
126 }
127
128 /* enable DMA channel 0 for message data */
130 /* set base address of the data in ext. memory */
131 REG(AES_DMAC_CH0_EXTADDR) = (uintptr_t)data;
132 /* set input data length in bytes */
133 REG(AES_DMAC_CH0_DMALENGTH) = len;
134 /* enable DMA channel 1 for result digest */
136 /* set base address of the digest buffer */
137 REG(AES_DMAC_CH1_EXTADDR) = (uintptr_t)digest;
138 /* set length of the result digest */
139 REG(AES_DMAC_CH1_DMALENGTH) = SHA_256_DIGEST_LENGTH;
140
141 /* wait for operation done (hash and DMAC are ready) */
143
144 /* clear the interrupt */
146
147 /* check for the absence of errors */
149 LOG_ERR("error at line %d\n", __LINE__);
151 }
152
153 /* all interrupts should have been acknowledged */
154 assert(!REG(AES_CTRL_INT_STAT));
155}
156/*---------------------------------------------------------------------------*/
157static void
158init(void)
159{
160 enable_crypto();
161}
162/*---------------------------------------------------------------------------*/
163static void
164update(const uint8_t *data, size_t len)
165{
166 while(len) {
167 size_t n;
168 if(!checkpoint.buf_len && (len > SHA_256_BLOCK_SIZE)) {
169 if(udma_is_valid_source_address((uintptr_t)data)) {
170 n = (len - 1) & ~(SHA_256_BLOCK_SIZE - 1);
171 do_hash(data, n, checkpoint.state, 0);
172 } else {
173 n = SHA_256_BLOCK_SIZE;
174 memcpy(checkpoint.buf, data, n);
175 do_hash(checkpoint.buf, n, checkpoint.state, 0);
176 }
177 checkpoint.bit_count += n << 3;
178 data += n;
179 len -= n;
180 } else {
181 n = MIN(len, SHA_256_BLOCK_SIZE - checkpoint.buf_len);
182 memcpy(checkpoint.buf + checkpoint.buf_len, data, n);
183 checkpoint.buf_len += n;
184 data += n;
185 len -= n;
186 if((checkpoint.buf_len == SHA_256_BLOCK_SIZE) && len) {
187 do_hash(checkpoint.buf, SHA_256_BLOCK_SIZE, checkpoint.state, 0);
188 checkpoint.bit_count += SHA_256_BLOCK_SIZE << 3;
189 checkpoint.buf_len = 0;
190 }
191 }
192 }
193}
194/*---------------------------------------------------------------------------*/
195static void
196finalize(uint8_t digest[static SHA_256_DIGEST_LENGTH])
197{
198 uint64_t final_bit_count = checkpoint.bit_count + (checkpoint.buf_len << 3);
199 if(!final_bit_count) {
200 /* the CC2538 would freeze otherwise */
201 memcpy(digest, empty_digest, sizeof(empty_digest));
202 } else {
203 do_hash(checkpoint.buf, checkpoint.buf_len, digest, final_bit_count);
204 }
205 disable_crypto();
206 checkpoint.buf_len = 0;
207 checkpoint.bit_count = 0;
208}
209/*---------------------------------------------------------------------------*/
210static void
211create_checkpoint(sha_256_checkpoint_t *cp)
212{
213 disable_crypto();
214 memcpy(cp, &checkpoint, sizeof(*cp));
215}
216/*---------------------------------------------------------------------------*/
217static void
218restore_checkpoint(const sha_256_checkpoint_t *cp)
219{
220 memcpy(&checkpoint, cp, sizeof(checkpoint));
221 enable_crypto();
222}
223/*---------------------------------------------------------------------------*/
224static void
225hash(const uint8_t *data, size_t len,
226 uint8_t digest[static SHA_256_DIGEST_LENGTH])
227{
228 if(!len) {
229 /* the CC2538 would freeze otherwise */
230 memcpy(digest, empty_digest, sizeof(empty_digest));
231 } else if(udma_is_valid_source_address((uintptr_t)data)) {
232 enable_crypto();
233 do_hash(data, len, digest, len << 3);
234 disable_crypto();
235 } else {
236 sha_256_hash(data, len, digest);
237 }
238}
239/*---------------------------------------------------------------------------*/
240const struct sha_256_driver cc2538_sha_256_driver = {
241 init,
242 update,
243 finalize,
246 hash,
247};
248/*---------------------------------------------------------------------------*/
249
250/** @} */
AES-128.
Header file for the cc2538 AES driver.
Header file for the cc2538 SHA-256 driver.
#define AES_CTRL_INT_CLR
Interrupt clear.
Definition aes.h:135
#define AES_HASH_DIGEST_C
Hash digest.
Definition aes.h:124
#define AES_DMAC_CH1_CTRL
Channel 1 control.
Definition aes.h:65
#define AES_CTRL_INT_CFG
Interrupt configuration.
Definition aes.h:133
#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_HASH_IO_BUF_CTRL_PAD_DMA_MESSAGE
Hash engine message padding required.
Definition aes.h:316
#define AES_CTRL_ALG_SEL_HASH
Select hash engine as DMA destination.
Definition aes.h:343
#define AES_CTRL_INT_STAT_DMA_BUS_ERR
DMA bus error detected.
Definition aes.h:405
#define AES_HASH_DIGEST_D
Hash digest.
Definition aes.h:125
#define AES_HASH_DIGEST_E
Hash digest.
Definition aes.h:126
#define AES_CTRL_ALG_SEL_TAG
DMA operation includes TAG.
Definition aes.h:342
#define AES_HASH_LENGTH_IN_L
Hash length.
Definition aes.h:120
#define AES_HASH_DIGEST_A
Hash digest.
Definition aes.h:122
#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_HASH_MODE_IN_NEW_HASH
New hash session.
Definition aes.h:335
#define AES_HASH_DIGEST_H
Hash digest.
Definition aes.h:129
#define AES_HASH_LENGTH_IN_H
Hash length.
Definition aes.h:121
#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_DMAC_CH1_EXTADDR
Channel 1 external address.
Definition aes.h:66
#define AES_HASH_DIGEST_G
Hash digest.
Definition aes.h:128
#define AES_HASH_MODE_IN_SHA256_MODE
Hash mode.
Definition aes.h:333
#define AES_HASH_DIGEST_F
Hash digest.
Definition aes.h:127
#define AES_CTRL_INT_CLR_RESULT_AV
Clear result available interrupt.
Definition aes.h:389
#define AES_HASH_IO_BUF_CTRL
Input/output buffer control and status.
Definition aes.h:118
#define AES_HASH_MODE_IN
Hash mode.
Definition aes.h:119
#define AES_CTRL_ALG_SEL
Algorithm select.
Definition aes.h:130
#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_HASH_DIGEST_B
Hash digest.
Definition aes.h:123
#define AES_CTRL_INT_STAT_RESULT_AV
Result available interrupt status.
Definition aes.h:413
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
bool udma_is_valid_source_address(uintptr_t source_address)
Checks if data can be DMAed from the given address.
Definition udma.c:59
Header file for the logging system.
Structure of SHA-256 drivers.
Definition sha-256.h:66
void(* create_checkpoint)(sha_256_checkpoint_t *checkpoint)
Saves the hash session, e.g., before pausing a protothread.
Definition sha-256.h:89
void(* finalize)(uint8_t digest[static 32])
Terminates the hash session and produces the digest.
Definition sha-256.h:84
void(* init)(void)
Starts a hash session.
Definition sha-256.h:71
void(* restore_checkpoint)(const sha_256_checkpoint_t *checkpoint)
Restores a hash session, e.g., after resuming a protothread.
Definition sha-256.h:94
void(* update)(const uint8_t *data, size_t len)
Processes a chunk of data.
Definition sha-256.h:78
void(* hash)(const uint8_t *data, size_t len, uint8_t digest[static 32])
Does init, update, and finalize at once.
Definition sha-256.h:102
Header file with register, macro and function declarations for the cc2538 micro-DMA controller module...