1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2017,2021, NXP
4 * All rights reserved.
5 *
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 */
9
10 #include "fsl_mmcau.h"
11 #include "cau_api.h"
12
13 #define MMCAU_AES_BLOCK_SIZE (16)
14 #define MMCAU_DES_BLOCK_SIZE (8)
15
16 #define MMCAU_MD5_STATE_SIZE (16)
17 #define MMCAU_SHA1_STATE_SIZE (20)
18 #define MMCAU_SHA256_STATE_SIZE (32)
19
20 /* these are maximum for CAU API has functions. HAST_STATE shall be set to maximum of MD5_STATE,SHA1_STATE and
21 * SHA256_STATE */
22 #define MMCAU_HASH_STATE_SIZE (32)
23 #define MMCAU_HASH_BLOCK_SIZE (64)
24
25 /* typedef for pointer to CAU API functions */
26 typedef void (*cau_hash_api_t)(const uint8_t *msgData, const int numBlocks, uint32_t *hashState);
27 typedef void (*cau_hash_md5_api_t)(const uint8_t *msgData, const int numBlocks, uint8_t *hashState);
28
29 /*******************************************************************************
30 * Code
31 ******************************************************************************/
mmcau_memcpy(void * dst,const void * src,size_t size)32 static void mmcau_memcpy(void *dst, const void *src, size_t size)
33 {
34 register uint8_t *to = dst;
35 register const uint8_t *from = src;
36 while (size != 0U)
37 {
38 *to = *from;
39 size--;
40 to++;
41 from++;
42 }
43 }
44
45 /* check if in pointer is aligned. if not, copy in to inAlign. return pointer to aligned data. */
mmcau_align_const(const void * in,void * inAlign,size_t size)46 static const void *mmcau_align_const(const void *in, void *inAlign, size_t size)
47 {
48 const void *inWork = in;
49 const uint32_t *src = (const uint32_t *)in;
50 /* if one or two least significant bits in the address are set, the address is unaligned */
51 if (0U != ((uint32_t)src & 0x3u))
52 {
53 mmcau_memcpy(inAlign, in, size);
54 inWork = inAlign;
55 }
56
57 return inWork;
58 }
59
60 /* check if out pointer is aligned. if not, set bool variable to notify caller. return pointer to aligned data. */
mmcau_align(void * out,void * outAlign,bool * copyOut)61 static void *mmcau_align(void *out, void *outAlign, bool *copyOut)
62 {
63 void *outWork;
64 uint32_t *dst = (uint32_t *)out;
65 /* if one or two least significant bits in the address are set, the address is unaligned */
66 if (0U != ((uint32_t)dst & 0x3u))
67 {
68 outWork = outAlign;
69 *copyOut = true;
70 }
71 else
72 {
73 outWork = out;
74 *copyOut = false;
75 }
76
77 return outWork;
78 }
79
80 /* common function for AES process. "encrypt" argument selects between en-/de-cryption */
mmcau_AesCrypt(const uint8_t * in,const uint8_t * keySch,uint32_t aesRounds,uint8_t * out,bool encrypt)81 static status_t mmcau_AesCrypt(const uint8_t *in, const uint8_t *keySch, uint32_t aesRounds, uint8_t *out, bool encrypt)
82 {
83 status_t status;
84
85 /* check validity of input arguments */
86 if (((aesRounds != 10u) && (aesRounds != 12u) && (aesRounds != 14u)) || (NULL == in) || (NULL == out) ||
87 (NULL == keySch))
88 {
89 status = kStatus_InvalidArgument;
90 }
91 else
92 {
93 uint8_t inAlign[MMCAU_AES_BLOCK_SIZE]; /* 16 bytes aligned input block */
94 uint8_t outAlign[MMCAU_AES_BLOCK_SIZE]; /* 16 bytes aligned output block */
95 uint32_t keySchAlign[60]; /* max 60 longwords in case of 32 bytes AES key */
96 size_t keySchSize = 0;
97 const uint8_t *keySchWork;
98 const uint8_t *inWork;
99 uint8_t *outWork;
100 bool copyOut;
101
102 /* compute keySchSize in bytes per CAU API documentation */
103 if (aesRounds == 10u)
104 {
105 keySchSize = 44u * sizeof(uint32_t);
106 }
107 else if (aesRounds == 12u)
108 {
109 keySchSize = 52u * sizeof(uint32_t);
110 }
111 else /* aesRounds = 14u */
112 {
113 keySchSize = 60u * sizeof(uint32_t);
114 }
115
116 /* align pointers */
117 inWork = mmcau_align_const(in, inAlign, MMCAU_AES_BLOCK_SIZE);
118 keySchWork = mmcau_align_const(keySch, keySchAlign, keySchSize);
119 outWork = mmcau_align(out, outAlign, ©Out);
120
121 /* call actual CAU API */
122 if (encrypt)
123 {
124 cau_aes_encrypt(inWork, keySchWork, (int)aesRounds, outWork);
125 }
126 else
127 {
128 cau_aes_decrypt(inWork, keySchWork, (int)aesRounds, outWork);
129 }
130 /* copy to unaligned out pointer */
131 if (copyOut)
132 {
133 mmcau_memcpy(out, outAlign, MMCAU_AES_BLOCK_SIZE);
134 }
135
136 status = kStatus_Success;
137 }
138 return status;
139 }
140
141 /* common function for DES process. "encrypt" argument selects between en-/de-cryption */
mmcau_DesCrypt(const uint8_t * in,const uint8_t * key,uint8_t * out,bool encrypt)142 static status_t mmcau_DesCrypt(const uint8_t *in, const uint8_t *key, uint8_t *out, bool encrypt)
143 {
144 status_t status;
145
146 if ((in != NULL) && (key != NULL) && (out != NULL))
147 {
148 uint8_t keyAlign[MMCAU_DES_BLOCK_SIZE]; /* 8 bytes key size aligned */
149 uint8_t inAlign[MMCAU_DES_BLOCK_SIZE]; /* 8 bytes input block aligned */
150 uint8_t outAlign[MMCAU_DES_BLOCK_SIZE]; /* 8 bytes output block aligned */
151 const uint8_t *inWork;
152 const uint8_t *keyWork;
153 uint8_t *outWork;
154 bool copyOut;
155
156 /* align pointers */
157 inWork = mmcau_align_const(in, inAlign, MMCAU_DES_BLOCK_SIZE);
158 keyWork = mmcau_align_const(key, keyAlign, MMCAU_DES_BLOCK_SIZE);
159 outWork = mmcau_align(out, outAlign, ©Out);
160
161 /* call CAU API */
162 if (encrypt)
163 {
164 cau_des_encrypt(inWork, keyWork, outWork);
165 }
166 else
167 {
168 cau_des_decrypt(inWork, keyWork, outWork);
169 }
170
171 if (copyOut)
172 {
173 mmcau_memcpy(out, outAlign, MMCAU_DES_BLOCK_SIZE);
174 }
175 status = kStatus_Success;
176 }
177 else
178 {
179 status = kStatus_InvalidArgument;
180 }
181
182 return status;
183 }
184
mmcau_hash_API(cau_hash_api_t cauFunc,const uint8_t * msgData,uint32_t numBlocks,void * hashState,size_t stateSize)185 static status_t mmcau_hash_API(
186 cau_hash_api_t cauFunc, const uint8_t *msgData, uint32_t numBlocks, void *hashState, size_t stateSize)
187 {
188 status_t status;
189
190 if ((msgData != NULL) && (hashState != NULL) && (numBlocks != 0U))
191 {
192 const uint8_t *msgDataWork;
193 void *hashStateWork;
194 uint8_t msgDataAlign[MMCAU_HASH_BLOCK_SIZE];
195 uint8_t hashStateAlign[MMCAU_HASH_STATE_SIZE];
196 bool copyInOut;
197
198 /* get aligned pointers */
199 msgDataWork = mmcau_align_const(msgData, msgDataAlign, MMCAU_HASH_BLOCK_SIZE);
200 hashStateWork = mmcau_align(hashState, hashStateAlign, ©InOut);
201 if (copyInOut)
202 {
203 mmcau_memcpy(hashStateAlign, hashState, stateSize);
204 }
205 /* CAU API */
206 cauFunc(msgDataWork, numBlocks, hashStateWork);
207 /* copy result to misaligned address */
208 if (copyInOut)
209 {
210 mmcau_memcpy(hashState, hashStateAlign, stateSize);
211 }
212 status = kStatus_Success;
213 }
214 else
215 {
216 status = kStatus_InvalidArgument;
217 }
218 return status;
219 }
220
mmcau_hash_MD5API(cau_hash_md5_api_t cauFunc,const uint8_t * msgData,uint32_t numBlocks,void * hashState,size_t stateSize)221 static status_t mmcau_hash_MD5API(
222 cau_hash_md5_api_t cauFunc, const uint8_t *msgData, uint32_t numBlocks, void *hashState, size_t stateSize)
223 {
224 status_t status;
225
226 if ((msgData != NULL) && (hashState != NULL) && (numBlocks != 0U))
227 {
228 const uint8_t *msgDataWork;
229 void *hashStateWork;
230 uint8_t msgDataAlign[MMCAU_HASH_BLOCK_SIZE];
231 uint8_t hashStateAlign[MMCAU_HASH_STATE_SIZE];
232 bool copyInOut;
233
234 /* get aligned pointers */
235 msgDataWork = mmcau_align_const(msgData, msgDataAlign, MMCAU_HASH_BLOCK_SIZE);
236 hashStateWork = mmcau_align(hashState, hashStateAlign, ©InOut);
237 if (copyInOut)
238 {
239 mmcau_memcpy(hashStateAlign, hashState, stateSize);
240 }
241 /* CAU API */
242 cauFunc(msgDataWork, numBlocks, hashStateWork);
243 /* copy result to misaligned address */
244 if (copyInOut)
245 {
246 mmcau_memcpy(hashState, hashStateAlign, stateSize);
247 }
248 status = kStatus_Success;
249 }
250 else
251 {
252 status = kStatus_InvalidArgument;
253 }
254 return status;
255 }
256
MMCAU_AES_SetKey(const uint8_t * key,const size_t keySize,uint8_t * keySch)257 status_t MMCAU_AES_SetKey(const uint8_t *key, const size_t keySize, uint8_t *keySch)
258 {
259 status_t status;
260
261 /* check validity of input arguments */
262 if (((keySize != 16u) && (keySize != 24u) && (keySize != 32u)) || (NULL == key) || (NULL == keySch))
263 {
264 status = kStatus_InvalidArgument;
265 }
266 else
267 {
268 uint8_t keyAlign[32] = {0}; /* max 32 bytes key supported by CAU lib */
269 uint32_t keySchAlign[60] = {0}; /* max 60 longwords in case of 32 bytes AES key */
270 const uint8_t *keyWork; /* aligned CAU lib input address argument */
271 uint8_t *keySchWork; /* aligned CAU lib output address argument */
272 bool copyOut;
273 size_t sizeOut = 0;
274
275 keyWork = mmcau_align_const(key, keyAlign, sizeof(keyAlign));
276 keySchWork = mmcau_align(keySch, keySchAlign, ©Out);
277
278 /* call CAU lib API with all addresses aligned */
279 cau_aes_set_key(keyWork, ((int)keySize * 8), keySchWork);
280
281 /* in case we have aligned output to local, copy the result out */
282 if (copyOut)
283 {
284 if (keySize == 16u)
285 {
286 sizeOut = 44u * sizeof(uint32_t);
287 }
288 else if (keySize == 24u)
289 {
290 sizeOut = 52u * sizeof(uint32_t);
291 }
292 else /* keySize = 32u */
293 {
294 sizeOut = 60u * sizeof(uint32_t);
295 }
296
297 mmcau_memcpy(keySch, keySchAlign, sizeOut);
298 }
299
300 status = kStatus_Success;
301 }
302
303 return status;
304 }
305
MMCAU_AES_EncryptEcb(const uint8_t * in,const uint8_t * keySch,uint32_t aesRounds,uint8_t * out)306 status_t MMCAU_AES_EncryptEcb(const uint8_t *in, const uint8_t *keySch, uint32_t aesRounds, uint8_t *out)
307 {
308 return mmcau_AesCrypt(in, keySch, aesRounds, out, true /* true for encryption */);
309 }
310
MMCAU_AES_DecryptEcb(const uint8_t * in,const uint8_t * keySch,uint32_t aesRounds,uint8_t * out)311 status_t MMCAU_AES_DecryptEcb(const uint8_t *in, const uint8_t *keySch, uint32_t aesRounds, uint8_t *out)
312 {
313 return mmcau_AesCrypt(in, keySch, aesRounds, out, false /* false for decryption */);
314 }
315
MMCAU_DES_ChkParity(const uint8_t * key)316 status_t MMCAU_DES_ChkParity(const uint8_t *key)
317 {
318 status_t status;
319
320 if (key != NULL)
321 {
322 uint8_t keyAlign[8]; /* 8 bytes key size aligned */
323 const uint8_t *keyWork;
324
325 /* align key[] */
326 keyWork = mmcau_align_const(key, keyAlign, sizeof(keyAlign));
327
328 /* call CAU API */
329 if (0 == cau_des_chk_parity(keyWork))
330 {
331 status = kStatus_Success;
332 }
333 else
334 {
335 status = kStatus_Fail;
336 }
337 }
338 else
339 {
340 status = kStatus_InvalidArgument;
341 }
342
343 return status;
344 }
345
MMCAU_DES_EncryptEcb(const uint8_t * in,const uint8_t * key,uint8_t * out)346 status_t MMCAU_DES_EncryptEcb(const uint8_t *in, const uint8_t *key, uint8_t *out)
347 {
348 return mmcau_DesCrypt(in, key, out, true /* 1 for encryption */);
349 }
350
MMCAU_DES_DecryptEcb(const uint8_t * in,const uint8_t * key,uint8_t * out)351 status_t MMCAU_DES_DecryptEcb(const uint8_t *in, const uint8_t *key, uint8_t *out)
352 {
353 return mmcau_DesCrypt(in, key, out, false /* 0 for decryption */);
354 }
355
356 /* cau_md5_initialize_output() */
MMCAU_MD5_InitializeOutput(uint32_t * md5State)357 status_t MMCAU_MD5_InitializeOutput(uint32_t *md5State)
358 {
359 status_t status;
360
361 if (md5State != NULL)
362 {
363 uint8_t hashStateAlign[MMCAU_HASH_STATE_SIZE];
364 void *hashStateWork;
365 bool copyInOut;
366 /* align pointer */
367 hashStateWork = mmcau_align(md5State, hashStateAlign, ©InOut);
368 if (copyInOut)
369 {
370 mmcau_memcpy(hashStateAlign, md5State, MMCAU_MD5_STATE_SIZE);
371 }
372 /* CAU API */
373 cau_md5_initialize_output(hashStateWork);
374 /* copy result to unaligned pointer */
375 if (copyInOut)
376 {
377 mmcau_memcpy(md5State, hashStateAlign, MMCAU_MD5_STATE_SIZE);
378 }
379 status = kStatus_Success;
380 }
381 else
382 {
383 status = kStatus_InvalidArgument;
384 }
385 return status;
386 }
387
388 /* cau_md5_hash_n */
MMCAU_MD5_HashN(const uint8_t * msgData,uint32_t numBlocks,uint32_t * md5State)389 status_t MMCAU_MD5_HashN(const uint8_t *msgData, uint32_t numBlocks, uint32_t *md5State)
390 {
391 return mmcau_hash_MD5API((cau_hash_md5_api_t)cau_md5_hash_n, msgData, numBlocks, md5State, MMCAU_MD5_STATE_SIZE);
392 }
393
394 /* cau_md5_update */
MMCAU_MD5_Update(const uint8_t * msgData,uint32_t numBlocks,uint32_t * md5State)395 status_t MMCAU_MD5_Update(const uint8_t *msgData, uint32_t numBlocks, uint32_t *md5State)
396 {
397 return mmcau_hash_MD5API((cau_hash_md5_api_t)cau_md5_update, msgData, numBlocks, md5State, MMCAU_MD5_STATE_SIZE);
398 }
399
400 /* cau_sha1_initialize_output */
MMCAU_SHA1_InitializeOutput(uint32_t * sha1State)401 status_t MMCAU_SHA1_InitializeOutput(uint32_t *sha1State)
402 {
403 status_t status;
404
405 if (sha1State != NULL)
406 {
407 uint8_t hashStateAlign[MMCAU_HASH_STATE_SIZE];
408 void *hashStateWork;
409 bool copyInOut;
410 /* align pointer */
411 hashStateWork = mmcau_align(sha1State, hashStateAlign, ©InOut);
412 if (copyInOut)
413 {
414 mmcau_memcpy(hashStateAlign, sha1State, MMCAU_SHA1_STATE_SIZE);
415 }
416 /* CAU API */
417 cau_sha1_initialize_output(hashStateWork);
418 /* copy result to unaligned pointer */
419 if (copyInOut)
420 {
421 mmcau_memcpy(sha1State, hashStateAlign, MMCAU_SHA1_STATE_SIZE);
422 }
423 status = kStatus_Success;
424 }
425 else
426 {
427 status = kStatus_InvalidArgument;
428 }
429 return status;
430 }
431
432 /* cau_sha1_hash_n */
MMCAU_SHA1_HashN(const uint8_t * msgData,uint32_t numBlocks,uint32_t * sha1State)433 status_t MMCAU_SHA1_HashN(const uint8_t *msgData, uint32_t numBlocks, uint32_t *sha1State)
434 {
435 return mmcau_hash_API((cau_hash_api_t)cau_sha1_hash_n, msgData, numBlocks, sha1State, MMCAU_SHA1_STATE_SIZE);
436 }
437
438 /* cau_sha1_update */
MMCAU_SHA1_Update(const uint8_t * msgData,uint32_t numBlocks,uint32_t * sha1State)439 status_t MMCAU_SHA1_Update(const uint8_t *msgData, uint32_t numBlocks, uint32_t *sha1State)
440 {
441 return mmcau_hash_API((cau_hash_api_t)cau_sha1_update, msgData, numBlocks, sha1State, MMCAU_SHA1_STATE_SIZE);
442 }
443
444 /* cau_sha256_initialize_output(). not this function has different return value (int) that the other two (void) */
MMCAU_SHA256_InitializeOutput(uint32_t * sha256State)445 status_t MMCAU_SHA256_InitializeOutput(uint32_t *sha256State)
446 {
447 status_t status;
448 int ret;
449
450 if (sha256State != NULL)
451 {
452 uint8_t hashStateAlign[MMCAU_HASH_STATE_SIZE];
453 void *hashStateWork;
454 bool copyInOut;
455 /* align pointer */
456 hashStateWork = mmcau_align(sha256State, hashStateAlign, ©InOut);
457 if (copyInOut)
458 {
459 mmcau_memcpy(hashStateAlign, sha256State, MMCAU_SHA256_STATE_SIZE);
460 }
461 /* CAU API */
462 ret = cau_sha256_initialize_output(hashStateWork);
463 /* copy result to unaligned pointer */
464 if (copyInOut)
465 {
466 mmcau_memcpy(sha256State, hashStateAlign, MMCAU_SHA256_STATE_SIZE);
467 }
468 if (ret == 0)
469 {
470 status = kStatus_Success;
471 }
472 else
473 {
474 status = kStatus_Fail;
475 }
476 }
477 else
478 {
479 status = kStatus_InvalidArgument;
480 }
481 return status;
482 }
483
484 /* cau_sha256_hash_n */
MMCAU_SHA256_HashN(const uint8_t * input,uint32_t numBlocks,uint32_t * sha256State)485 status_t MMCAU_SHA256_HashN(const uint8_t *input, uint32_t numBlocks, uint32_t *sha256State)
486 {
487 return mmcau_hash_API((cau_hash_api_t)cau_sha256_hash_n, input, numBlocks, sha256State, MMCAU_SHA256_STATE_SIZE);
488 }
489
490 /* cau_sha256_update */
MMCAU_SHA256_Update(const uint8_t * input,uint32_t numBlocks,uint32_t * sha256State)491 status_t MMCAU_SHA256_Update(const uint8_t *input, uint32_t numBlocks, uint32_t *sha256State)
492 {
493 return mmcau_hash_API((cau_hash_api_t)cau_sha256_update, input, numBlocks, sha256State, MMCAU_SHA256_STATE_SIZE);
494 }
495