1
2 /******************************************************************************
3 * Filename: crypto.c
4 * Revised: 2019-01-25 13:11:50 +0100 (Fri, 25 Jan 2019)
5 * Revision: 54285
6 *
7 * Description: Driver for the aes functions of the crypto module
8 *
9 * Copyright (c) 2015 - 2017, Texas Instruments Incorporated
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1) Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2) Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3) Neither the name of the ORGANIZATION nor the names of its contributors may
23 * be used to endorse or promote products derived from this software without
24 * specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 *
38 ******************************************************************************/
39
40 #include "aes.h"
41
42 //*****************************************************************************
43 //
44 // Handle support for DriverLib in ROM:
45 // This section will undo prototype renaming made in the header file
46 //
47 //*****************************************************************************
48 #if !defined(DOXYGEN)
49 #undef AESStartDMAOperation
50 #define AESStartDMAOperation NOROM_AESStartDMAOperation
51 #undef AESSetInitializationVector
52 #define AESSetInitializationVector NOROM_AESSetInitializationVector
53 #undef AESWriteCCMInitializationVector
54 #define AESWriteCCMInitializationVector NOROM_AESWriteCCMInitializationVector
55 #undef AESReadTag
56 #define AESReadTag NOROM_AESReadTag
57 #undef AESVerifyTag
58 #define AESVerifyTag NOROM_AESVerifyTag
59 #undef AESWriteToKeyStore
60 #define AESWriteToKeyStore NOROM_AESWriteToKeyStore
61 #undef AESReadFromKeyStore
62 #define AESReadFromKeyStore NOROM_AESReadFromKeyStore
63 #undef AESWaitForIRQFlags
64 #define AESWaitForIRQFlags NOROM_AESWaitForIRQFlags
65 #undef AESConfigureCCMCtrl
66 #define AESConfigureCCMCtrl NOROM_AESConfigureCCMCtrl
67 #endif
68
69
70
71 //*****************************************************************************
72 //
73 // Load the initialization vector.
74 //
75 //*****************************************************************************
AESSetInitializationVector(const uint32_t * initializationVector)76 void AESSetInitializationVector(const uint32_t *initializationVector)
77 {
78 // Write initialization vector to the aes registers
79 HWREG(CRYPTO_BASE + CRYPTO_O_AESIV0) = initializationVector[0];
80 HWREG(CRYPTO_BASE + CRYPTO_O_AESIV1) = initializationVector[1];
81 HWREG(CRYPTO_BASE + CRYPTO_O_AESIV2) = initializationVector[2];
82 HWREG(CRYPTO_BASE + CRYPTO_O_AESIV3) = initializationVector[3];
83 }
84
85 //*****************************************************************************
86 //
87 // Start a crypto DMA operation.
88 //
89 //*****************************************************************************
AESStartDMAOperation(const uint8_t * channel0Addr,uint32_t channel0Length,uint8_t * channel1Addr,uint32_t channel1Length)90 void AESStartDMAOperation(const uint8_t *channel0Addr, uint32_t channel0Length, uint8_t *channel1Addr, uint32_t channel1Length)
91 {
92 if (channel0Length && channel0Addr) {
93 // We actually want to perform an operation. Clear any outstanding events.
94 HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = CRYPTO_IRQCLR_RESULT_AVAIL_M | CRYPTO_IRQEN_DMA_IN_DONE_M; // This might need AES_IRQEN_DMA_IN_DONE as well
95
96 while(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & (CRYPTO_IRQSTAT_DMA_IN_DONE_M | CRYPTO_IRQSTAT_RESULT_AVAIL_M));
97
98 // Configure the DMA controller - enable both DMA channels.
99 HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1;
100
101 // Base address of the payload data in ext. memory.
102 HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = (uint32_t)channel0Addr;
103
104 // Payload data length in bytes, equal to the cipher text length.
105 HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = channel0Length;
106 }
107
108 if (channel1Length && channel1Addr) {
109 // Enable DMA channel 1.
110 HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 1;
111
112 // Base address of the output data buffer.
113 HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1EXTADDR) = (uint32_t)channel1Addr;
114
115 // Output data length in bytes, equal to the cipher text length.
116 HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1LEN) = channel1Length;
117 }
118 }
119
120 //*****************************************************************************
121 //
122 // Poll the IRQ status register and return.
123 //
124 //*****************************************************************************
AESWaitForIRQFlags(uint32_t irqFlags)125 uint32_t AESWaitForIRQFlags(uint32_t irqFlags)
126 {
127 uint32_t irqTrigger = 0;
128 // Wait for the DMA operation to complete. Add a delay to make sure we are
129 // not flooding the bus with requests too much.
130 do {
131 CPUdelay(1);
132 }
133 while(!(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & irqFlags & (CRYPTO_IRQSTAT_DMA_IN_DONE_M |
134 CRYPTO_IRQSTAT_RESULT_AVAIL_M |
135 CRYPTO_IRQSTAT_DMA_BUS_ERR_M |
136 CRYPTO_IRQSTAT_KEY_ST_WR_ERR_M)));
137
138 // Save the IRQ trigger source
139 irqTrigger = HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & irqFlags;
140
141 // Clear IRQ flags
142 HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = irqTrigger;
143
144 return irqTrigger;
145 }
146
147 //*****************************************************************************
148 //
149 // Transfer a key from CM3 memory to a key store location.
150 //
151 //*****************************************************************************
AESWriteToKeyStore(const uint8_t * aesKey,uint32_t aesKeyLength,uint32_t keyStoreArea)152 uint32_t AESWriteToKeyStore(const uint8_t *aesKey, uint32_t aesKeyLength, uint32_t keyStoreArea)
153 {
154 // Check the arguments.
155 ASSERT((keyStoreArea == AES_KEY_AREA_0) ||
156 (keyStoreArea == AES_KEY_AREA_1) ||
157 (keyStoreArea == AES_KEY_AREA_2) ||
158 (keyStoreArea == AES_KEY_AREA_3) ||
159 (keyStoreArea == AES_KEY_AREA_4) ||
160 (keyStoreArea == AES_KEY_AREA_5) ||
161 (keyStoreArea == AES_KEY_AREA_6) ||
162 (keyStoreArea == AES_KEY_AREA_7));
163
164 ASSERT((aesKeyLength == AES_128_KEY_LENGTH_BYTES) ||
165 (aesKeyLength == AES_192_KEY_LENGTH_BYTES) ||
166 (aesKeyLength == AES_256_KEY_LENGTH_BYTES));
167
168 uint32_t keySize = 0;
169
170 switch (aesKeyLength) {
171 case AES_128_KEY_LENGTH_BYTES:
172 keySize = CRYPTO_KEYSIZE_SIZE_128_BIT;
173 break;
174 case AES_192_KEY_LENGTH_BYTES:
175 keySize = CRYPTO_KEYSIZE_SIZE_192_BIT;
176 break;
177 case AES_256_KEY_LENGTH_BYTES:
178 keySize = CRYPTO_KEYSIZE_SIZE_256_BIT;
179 break;
180 }
181
182 // Clear any previously written key at the keyLocation
183 AESInvalidateKey(keyStoreArea);
184
185 // Disable the external interrupt to stop the interrupt form propagating
186 // from the module to the System CPU.
187 IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ);
188
189 // Enable internal interrupts.
190 HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_IRQTYPE_LEVEL_M;
191 HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_DMA_IN_DONE_M | CRYPTO_IRQEN_RESULT_AVAIL_M;
192
193 // Configure master control module.
194 HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = CRYPTO_ALGSEL_KEY_STORE;
195
196 // Clear any outstanding events.
197 HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE | CRYPTO_IRQCLR_RESULT_AVAIL);
198
199 // Configure the size of keys contained within the key store
200 // Do not write to the register if the correct key size is already set.
201 // Writing to this register causes all current keys to be invalidated.
202 uint32_t keyStoreKeySize = HWREG(CRYPTO_BASE + CRYPTO_O_KEYSIZE);
203 if (keySize != keyStoreKeySize) {
204 HWREG(CRYPTO_BASE + CRYPTO_O_KEYSIZE) = keySize;
205 }
206
207 // Enable key to write (e.g. Key 0).
208 HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITEAREA) = 1 << keyStoreArea;
209
210 // Total key length in bytes (16 for 1 x 128-bit key and 32 for 1 x 256-bit key).
211 AESStartDMAOperation(aesKey, aesKeyLength, 0, 0);
212
213 // Wait for the DMA operation to complete.
214 uint32_t irqTrigger = AESWaitForIRQFlags(CRYPTO_IRQCLR_RESULT_AVAIL | CRYPTO_IRQCLR_DMA_IN_DONE | CRYPTO_IRQSTAT_DMA_BUS_ERR | CRYPTO_IRQSTAT_KEY_ST_WR_ERR);
215
216 // Re-enable interrupts globally.
217 IntPendClear(INT_CRYPTO_RESULT_AVAIL_IRQ);
218 IntEnable(INT_CRYPTO_RESULT_AVAIL_IRQ);
219
220 // If we had a bus error or the key is not in the CRYPTO_O_KEYWRITTENAREA, return an error.
221 if ((irqTrigger & (CRYPTO_IRQSTAT_DMA_BUS_ERR_M | CRYPTO_IRQSTAT_KEY_ST_WR_ERR_M)) || !(HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITTENAREA) & (1 << keyStoreArea))) {
222 // There was an error in writing to the keyStore.
223 return AES_KEYSTORE_ERROR;
224 }
225 else {
226 return AES_SUCCESS;
227 }
228 }
229
230 //*****************************************************************************
231 //
232 // Transfer a key from the keyStoreArea to the internal buffer of the module.
233 //
234 //*****************************************************************************
AESReadFromKeyStore(uint32_t keyStoreArea)235 uint32_t AESReadFromKeyStore(uint32_t keyStoreArea)
236 {
237 // Check the arguments.
238 ASSERT((keyStoreArea == AES_KEY_AREA_0) ||
239 (keyStoreArea == AES_KEY_AREA_1) ||
240 (keyStoreArea == AES_KEY_AREA_2) ||
241 (keyStoreArea == AES_KEY_AREA_3) ||
242 (keyStoreArea == AES_KEY_AREA_4) ||
243 (keyStoreArea == AES_KEY_AREA_5) ||
244 (keyStoreArea == AES_KEY_AREA_6) ||
245 (keyStoreArea == AES_KEY_AREA_7));
246
247 // Check if there is a valid key in the specified keyStoreArea
248 if (!(HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITTENAREA) & (1 << keyStoreArea))) {
249 return AES_KEYSTORE_AREA_INVALID;
250 }
251
252 // Enable keys to read (e.g. Key 0).
253 HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) = keyStoreArea;
254
255 // Wait until key is loaded to the AES module.
256 // We cannot simply poll the IRQ status as only an error is communicated through
257 // the IRQ status and not the completion of the transfer.
258 do {
259 CPUdelay(1);
260 }
261 while((HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) & CRYPTO_KEYREADAREA_BUSY_M));
262
263 // Check for keyStore read error.
264 if((HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & CRYPTO_IRQSTAT_KEY_ST_RD_ERR_M)) {
265 return AES_KEYSTORE_ERROR;
266 }
267 else {
268 return AES_SUCCESS;
269 }
270 }
271
272 //*****************************************************************************
273 //
274 // Read the tag after a completed CCM, GCM, or CBC-MAC operation.
275 //
276 //*****************************************************************************
AESReadTag(uint8_t * tag,uint32_t tagLength)277 uint32_t AESReadTag(uint8_t *tag, uint32_t tagLength)
278 {
279 // The intermediate array is used instead of a caller-provided one
280 // to enable a simple API with no unintuitive alignment or size requirements.
281 // This is a trade-off of stack-depth vs ease-of-use that came out on the
282 // ease-of-use side.
283 uint32_t computedTag[AES_BLOCK_SIZE / sizeof(uint32_t)];
284
285 // Wait until the computed tag is ready.
286 while (!(HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) & CRYPTO_AESCTL_SAVED_CONTEXT_RDY_M));
287
288 // Read computed tag out from the HW registers
289 // Need to read out all 128 bits in four reads to correctly clear CRYPTO_AESCTL_SAVED_CONTEXT_RDY flag
290 computedTag[0] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT0);
291 computedTag[1] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT1);
292 computedTag[2] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT2);
293 computedTag[3] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT3);
294
295 memcpy(tag, computedTag, tagLength);
296
297 return AES_SUCCESS;
298 }
299
300 //*****************************************************************************
301 //
302 // Verify the provided tag against the computed tag after a completed CCM or
303 // GCM operation.
304 //
305 //*****************************************************************************
AESVerifyTag(const uint8_t * tag,uint32_t tagLength)306 uint32_t AESVerifyTag(const uint8_t *tag, uint32_t tagLength)
307 {
308 uint32_t resultStatus;
309 // The intermediate array is allocated on the stack to ensure users do not
310 // point the tag they provide and the one computed at the same location.
311 // That would cause memcmp to compare an array against itself. We could add
312 // a check that verifies that the arrays are not the same. If we did that and
313 // modified AESReadTag to just copy all 128 bits into a provided array,
314 // we could save 16 bytes of stack space while making the API much more
315 // complicated.
316 uint8_t computedTag[AES_BLOCK_SIZE];
317
318 resultStatus = AESReadTag(computedTag, tagLength);
319
320 if (resultStatus != AES_SUCCESS) {
321 return resultStatus;
322 }
323
324 resultStatus = memcmp(computedTag, tag, tagLength);
325
326 if (resultStatus != 0) {
327 return AES_TAG_VERIFICATION_FAILED;
328 }
329
330 return AES_SUCCESS;
331 }
332
333 //*****************************************************************************
334 //
335 // Configure the AES module for CCM mode
336 //
337 //*****************************************************************************
AESConfigureCCMCtrl(uint32_t nonceLength,uint32_t macLength,bool encrypt)338 void AESConfigureCCMCtrl(uint32_t nonceLength, uint32_t macLength, bool encrypt)
339 {
340 uint32_t ctrlVal = 0;
341
342 ctrlVal = ((15 - nonceLength - 1) << CRYPTO_AESCTL_CCM_L_S);
343 if ( macLength >= 2 ) {
344 ctrlVal |= ((( macLength - 2 ) >> 1 ) << CRYPTO_AESCTL_CCM_M_S );
345 }
346 ctrlVal |= CRYPTO_AESCTL_CCM |
347 CRYPTO_AESCTL_CTR |
348 CRYPTO_AESCTL_SAVE_CONTEXT |
349 CRYPTO_AESCTL_CTR_WIDTH_128_BIT;
350 ctrlVal |= encrypt ? CRYPTO_AESCTL_DIR : 0;
351
352 AESSetCtrl(ctrlVal);
353 }
354
355 //*****************************************************************************
356 //
357 // Configure an IV for CCM mode of operation
358 //
359 //*****************************************************************************
AESWriteCCMInitializationVector(const uint8_t * nonce,uint32_t nonceLength)360 void AESWriteCCMInitializationVector(const uint8_t *nonce, uint32_t nonceLength)
361 {
362 union {
363 uint32_t word[4];
364 uint8_t byte[16];
365 } initializationVector = {{0}};
366
367 initializationVector.byte[0] = 15 - nonceLength - 1;
368
369 memcpy(&(initializationVector.byte[1]), nonce, nonceLength);
370
371 AESSetInitializationVector(initializationVector.word);
372 }
373