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