1 /*
2  * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 
8 /************* Include Files ****************/
9 #include <stdint.h>
10 #include <string.h>
11 #include "cc_pal_log.h"
12 #include "cc_prod_error.h"
13 #include "prod_hw_defs.h"
14 #include "prod_crypto_driver.h"
15 #include "cmpu_derivation.h"
16 #include "cc_pal_mem.h"
17 #include "llf_rnd.h"
18 #include "driver_defs.h"
19 
20 
21 /* Description: Implementation of CTR_DRBG_Generate_algorithm, Taken from NIST SP800-90A, section 10.4.2
22    Parameters:
23     pInputBuff[IN] - the seed_material with some additional bytes to avoid copy of large buffers
24     actualInputDataSize[IN] - the actual size of teh seed without teh additions
25     pOutputBuff[OUT] - the generated buffer - 32 bytes
26  */
Derivation_Block_Cipher_df(uint32_t * pInputBuff,uint32_t actualInputDataSize,uint32_t * pOutput)27 static uint32_t Derivation_Block_Cipher_df(uint32_t   *pInputBuff,
28                                            uint32_t   actualInputDataSize,
29                                            uint32_t    *pOutput)
30 {
31     uint32_t  error = CC_OK;
32     uint8_t *initMac_ptr;
33     uint32_t i;
34     uint32_t additionalBytesSize = 0;
35     uint8_t *inputPtr = (uint8_t*)pInputBuff;
36     uint8_t keyBuff[CC_PROD_AES_Key256Bits_SIZE_IN_BYTES];
37     uint8_t ivBuff[CC_PROD_AES_IV_COUNTER_SIZE_IN_BYTES];
38     uint32_t  outDataSizeBytes = CC_PROD_AES_Key256Bits_SIZE_IN_BYTES+CC_PROD_AES_IV_COUNTER_SIZE_IN_BYTES;
39     uint32_t inputDataSize = actualInputDataSize;
40     uint8_t Key[CC_PROD_AES_Key256Bits_SIZE_IN_BYTES] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
41             0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F};
42     uint8_t InitialMac256[3][16] = {{0xF2,0x90,0x00,0xB6,0x2A,0x49,0x9F,0xD0,0xA9,0xF3,0x9A,0x6A,0xDD,0x2E,0x77,0x80},
43             {0x9D,0xBA,0x41,0xA7,0x77,0xF3,0xB4,0x6A,0x37,0xB7,0xAA,0xAE,0x49,0xD6,0xDF,0x8D},
44             {0x2F,0x7A,0x3C,0x60,0x07,0x08,0xD1,0x24,0xAC,0xD3,0xC5,0xDE,0x3B,0x65,0x84,0x47}};
45 
46     if ((NULL == pInputBuff) || (actualInputDataSize == 0) || (NULL == pOutput)) {
47         CC_PAL_LOG_ERR("invalid parameters\n");
48         return CC_PROD_INVALID_PARAM_ERR;
49     }
50     /* Steps from NIST - ignored
51        1. If (number_of_bits_to_return > max_number_of_bits), then return an ERROR_FLAG. */
52 
53     /* Steps from NIST
54        2. L = len (input_string)/8. Comment: L is the bitstring represention of the integer resulting from len (input_string)/8. L shall be represented as a 32-bit integer.
55        3. N = number_of_bits_to_return/8. Comment : N is the bitstring represention of the integer resulting from number_of_bits_to_return/8                    .
56           N shall be represented as a 32-bit integer.
57        4. S = L || N || input_string || 0x80.
58           Comment : Pad S with zeros, if necessary.
59        5. While (len (S) mod outlen) 0, S = S || 0x00. */
60     /* convert L,N to little endian */
61     pInputBuff[0] = CC_PROD_SET_WORD_AS_BE(actualInputDataSize); /* L */
62     pInputBuff[1] = CC_PROD_SET_WORD_AS_BE(outDataSizeBytes);    /* N */
63 
64     inputPtr[8+actualInputDataSize] = 0x80;
65     // pad with 0's the remaining bytes until we reach size which is outlenSize multiply
66     additionalBytesSize = CC_PROD_AES_BLOCK_SIZE_IN_BYTES - ((8+1+actualInputDataSize)&(CC_PROD_AES_BLOCK_SIZE_IN_BYTES-1));
67     CC_PalMemSetZero(&inputPtr[8+1+actualInputDataSize], additionalBytesSize);
68 
69     /* size of input to AES-MAC, rounded up to AES block */
70     inputDataSize += (8/*2w*/ + 1/*0x80*/ + additionalBytesSize);
71 
72 
73     /* Steps from NIST
74        Comment : Compute the starting value.
75        6. temp = the Null string.
76        7. i = 0. Comment : i shall be represented as a 32-bit integer, i.e., len (i) = 32.
77        8. K = Leftmost keylen bits of 0x00010203...1D1E1F.
78        9. While len (temp) < keylen + outlen, do
79        9.1 IV = i || 0outlen - len (i). Comment: The 32-bit integer represenation of i is padded with zeros to outlen bits.
80        9.2 temp = temp || BCC (K, (IV || S)).
81        9.3 i = i + 1. */
82     for (i = 0; i < (outDataSizeBytes >> 4); i++) {
83         /* set pointer to initial precomputed IV  value */
84         initMac_ptr = (uint8_t*)&InitialMac256[i][0];
85 
86         /* AES MAC */
87         error =  CC_PROD_Aes(CIPHER_CBC_MAC, CRYPTO_DIRECTION_ENCRYPT,
88                              USER_KEY,
89                              Key,sizeof(Key),
90                              initMac_ptr,CC_PROD_AES_IV_COUNTER_SIZE_IN_BYTES,
91                              pInputBuff,
92                              inputDataSize,
93                              pOutput + i*CC_PROD_AES_BLOCK_SIZE_IN_WORDS);
94         if (error != CC_OK) {
95             CC_PAL_LOG_ERR("Failed to CC_PROD_Aes, error 0x%x\n", error);
96             return error;
97         }
98 
99     }
100 
101     /* Steps from NIST
102        Comment: Compute the requested number of bits.
103        10. K = Leftmost keylen bits of temp.
104        11. X = Next outlen bits of temp. */
105     CC_PalMemCopy(keyBuff, (uint8_t*)pOutput, sizeof(keyBuff));
106     CC_PalMemCopy(ivBuff, (uint8_t*)(pOutput + CC_PROD_AES_Key256Bits_SIZE_IN_WORDS), sizeof(ivBuff));
107 
108 
109     /* Steps from NIST
110        12. temp = the Null string.
111        13. While len (temp) < number_of_bits_to_return, do
112        13.1 X = Block_Encrypt (K, X).
113        13.2 temp = temp || X.
114        14. requested_bits = Leftmost number_of_bits_to_return of temp. */
115     /* Encrypt (K,IV) by AES-CBC using output buff */
116     CC_PalMemSetZero((uint8_t*)pOutput, outDataSizeBytes);
117     error = CC_PROD_Aes(CIPHER_CBC, CRYPTO_DIRECTION_ENCRYPT,
118                         USER_KEY,
119                         keyBuff, sizeof(keyBuff),
120                         ivBuff, CC_PROD_AES_IV_COUNTER_SIZE_IN_BYTES,
121                         pOutput,
122                         outDataSizeBytes,
123                         pOutput);
124     if (error != CC_OK) {
125         CC_PAL_LOG_ERR("Failed to CC_PROD_Aes, error 0x%x\n", error);
126         return error;
127     }
128 
129     /* Steps from NIST
130        15. Return SUCCESS and requested_bits.*/
131     return CC_OK;
132 } /* END of Derivation_Block_Cipher_df */
133 
134 
135 
136 
137 /* increment vector by value of 1 */
Derivation_incrementVector(uint8_t * iv_ptr,uint32_t vecSizeInwords)138 static void Derivation_incrementVector(uint8_t *iv_ptr, uint32_t vecSizeInwords)
139 {
140     int32_t i;
141     uint32_t tmp, curr, tmp1;
142 
143     for (i = vecSizeInwords-1; i >= 0; i--) {
144         CC_PalMemCopy((uint8_t *)&tmp1, &iv_ptr[i*sizeof(uint32_t)], sizeof(tmp1));
145         tmp = CC_PROD_SET_WORD_AS_BE(tmp1);
146         curr = tmp;
147         tmp = ((tmp+1) & 0xFFFFFFFF);
148 
149         /* inverse the bytes order in a word */
150         tmp1 = CC_PROD_SET_WORD_AS_BE(tmp);
151         CC_PalMemCopy(&iv_ptr[i*sizeof(uint32_t)], (uint8_t *)&tmp1, sizeof(tmp));
152         if (tmp > curr) {
153             break;
154         }
155     }
156 }
157 
158 
159 
160 /* Description: Implementation of  CTR_DRBG_Update, Taken from NIST SP800-90A, section 10.2.1.2
161    Parameters:
162     provided_data[IN]: The data to be used. This must be exactly seedlen bits in length;
163             this length is guaranteed by the construction of the provided_data in the instantiate, reseed and generate functions.
164     Key[IN/OUT]: The current value of Key.
165     V[IN/OUT]: The current value of V.
166  */
Derivation_DRBG_Update(uint32_t * providedData_ptr,uint8_t * pKey,uint8_t * pIv)167 static uint32_t Derivation_DRBG_Update(uint32_t   *providedData_ptr,
168                                        uint8_t   *pKey,
169                                        uint8_t   *pIv)
170 {
171 
172     uint32_t  error = CC_OK;
173     uint32_t outDataSize = (CC_PROD_AES_Key256Bits_SIZE_IN_BYTES+CC_PROD_AES_IV_COUNTER_SIZE_IN_BYTES);
174     uint32_t  pOutput[CC_PROD_AES_Key256Bits_SIZE_IN_WORDS+CC_PROD_AES_IV_COUNTER_SIZE_IN_WORDS];
175     uint32_t i = 0;
176     AesContext_t aesCtx;
177 
178     /* Steps taken from NIST
179        1. temp = Null.
180        2. While (len (temp) < seedlen) do
181        2.1 V = (V + 1) mod 2outlen.
182        2.2 output_block = Block_Encrypt (Key, V).
183        2.3 temp = temp || ouput_block.
184        3. temp = Leftmost seedlen bits of temp.
185        4 temp = temp XOR provided_data. */
186     error =  CC_PROD_AesInit(&aesCtx, CIPHER_CTR, CRYPTO_DIRECTION_ENCRYPT,
187                              USER_KEY,
188                              pKey,CC_PROD_AES_Key256Bits_SIZE_IN_BYTES,
189                              pIv,CC_PROD_AES_IV_COUNTER_SIZE_IN_BYTES);
190     if (error != CC_OK) {
191         return error;
192     }
193     // dummy block to increment IV
194     error =  CC_PROD_AesProcess(&aesCtx,
195                                 providedData_ptr,  CC_PROD_AES_BLOCK_SIZE_IN_BYTES,
196                                 pOutput);
197     if (error != CC_OK) {
198         return error;
199     }
200     for (i = 0; i < (outDataSize >> 4); i++) {
201         error =  CC_PROD_AesProcess(&aesCtx,
202                                     providedData_ptr + i*CC_PROD_AES_BLOCK_SIZE_IN_WORDS, CC_PROD_AES_BLOCK_SIZE_IN_BYTES,
203                                     pOutput + i*CC_PROD_AES_BLOCK_SIZE_IN_WORDS);
204         if (error != CC_OK) {
205             return error;
206         }
207     }
208 
209     /* Steps taken from NIST
210        5. Key = Leftmost keylen bits of temp.
211        6. V = Rightmost outlen bits of temp. */
212     CC_PalMemCopy(pKey, (uint8_t*)pOutput, CC_PROD_AES_Key256Bits_SIZE_IN_BYTES);
213     CC_PalMemCopy(pIv, (uint8_t*)(pOutput+CC_PROD_AES_Key256Bits_SIZE_IN_WORDS), CC_PROD_AES_IV_COUNTER_SIZE_IN_BYTES);
214 
215     /*Steps taken from NIST
216       7. Return the new values of Key and V. */
217     return CC_OK;
218 }
219 
220 
221 
222 /* Description: Implementation of CTR_DRBG_Instantiate_algorithm, Taken from NIST SP800-90A, section 10.2.1.3.2
223    Parameters:
224     pKey[OUT] - the generated key
225     pIv[OUT] - the generated Iv
226  */
CC_PROD_Derivation_Instantiate(uint32_t * pEntrSrc,uint32_t sourceSize,uint8_t * pKey,uint8_t * pIv)227 uint32_t CC_PROD_Derivation_Instantiate (uint32_t *pEntrSrc,
228                                          uint32_t  sourceSize,
229                                          uint8_t *pKey,
230                                          uint8_t *pIv)
231 {
232     uint32_t  error = CC_OK;
233     uint32_t   pDfOutput[CC_PROD_AES_Key256Bits_SIZE_IN_WORDS+CC_PROD_AES_IV_COUNTER_SIZE_IN_WORDS] = {0};
234 
235     if ((NULL == pKey) || (NULL == pIv) || (NULL == pEntrSrc) || (0 == sourceSize) || (!IS_ALIGNED(sourceSize, sizeof(uint32_t)))) {
236         CC_PAL_LOG_ERR("invalid key parameters\n");
237         return CC_PROD_INVALID_PARAM_ERR;
238     }
239     /* Steps taken from NIST  - already done before calling CC_PROD_Derivation_Instantiate
240        1. seed_material = entropy_input || nonce || personalization_string.
241         (Comment: Ensure that the length of the seed_material is exactly seedlen bits.) */
242     /* Steps taken from NIST
243        2. seed_material = Derivation_Block_Cipher_df (seed_material, seedlen). */
244     error = Derivation_Block_Cipher_df(pEntrSrc, sourceSize, pDfOutput);
245     if (error != CC_OK) {
246         CC_PAL_LOG_ERR("failed Derivation_Block_Cipher_df, error is 0x%X\n", error);
247         return error;
248     }
249 
250     /* Steps taken from NIST
251        3. Key = 0keylen. Comment: keylen bits of zeros.
252        4. V = 0outlen. Comment: outlen bits of zeros. */
253     CC_PalMemSetZero(pKey, CC_PROD_AES_Key256Bits_SIZE_IN_BYTES);
254     CC_PalMemSetZero(pIv, CC_PROD_AES_IV_COUNTER_SIZE_IN_BYTES);
255     /* Steps taken from NIST
256        5. (Key, V) = Derivation_DRBG_Update (seed_material, Key, V). */
257     error = Derivation_DRBG_Update(pDfOutput, pKey, pIv);
258     if (error != CC_OK) {
259         CC_PAL_LOG_ERR("failed Derivation_DRBG_Update, error is 0x%X\n", error);
260         return error;
261     }
262 
263     /* Steps taken from NIST
264        6. reseed_counter = 1.  -- ignored here
265        7. Return V, Key, and reseed_counter as the initial_working_state. */
266     return CC_OK;
267 
268 }
269 
270 
271 /* Description: Implementation of CTR_DRBG_Generate_algorithm, Taken from NIST SP800-90A, section 10.2.1.5.2
272    Parameters:
273     pKey[IN] - the generated key
274     pIv[IN] - the generated Iv
275     pOutputBuff[OUT] - the generated buffer - 32 bytes
276  */
CC_PROD_Derivation_Generate(uint8_t * pKey,uint8_t * pIv,uint32_t * pOutputBuff,uint32_t outDataSize)277 uint32_t CC_PROD_Derivation_Generate(uint8_t *pKey,
278                                      uint8_t *pIv,
279                                      uint32_t *pOutputBuff,
280                                      uint32_t  outDataSize)
281 {
282     uint32_t  error = CC_OK;
283     uint32_t  i = 0;
284     uint32_t  numBlocks = (outDataSize >> 4);
285     uint32_t   temp[CC_PROD_AES_BLOCK_SIZE_IN_WORDS] = {0};
286 #ifndef CMPU_KAT
287     uint32_t   firstDummyBytes[CC_PROD_AES_BLOCK_SIZE_IN_WORDS] = {0};
288 #endif
289     AesContext_t aesCtx;
290 
291     if ((pKey == NULL) || (pIv == NULL) || (pOutputBuff == NULL)) {
292         CC_PAL_LOG_ERR("Invalid input Param\n");
293         return CC_PROD_INVALID_PARAM_ERR;
294     }
295 
296     /* Steps taken from NIST - all following are ignored, since th eworking state is one time
297        1. If reseed_counter > reseed_interval, then return an indication that a reseed is required.
298        2. If (additional_input Null), then
299        2.1 additional_input = Derivation_Block_Cipher_df (additional_input, seedlen).
300        2.2 (Key, V) = Derivation_DRBG_Update (additional_input, Key, V).
301        Else additional_input = 0seedlen. */
302 
303 
304 
305     /* Steps taken from NIST
306        3. temp = Null.
307        4. While (len (temp) < requested_number_of_bits) do:
308        4.1 V = (V + 1) mod 2outlen.
309        4.2 output_block = Block_Encrypt (Key, V).
310        4.3 temp = temp || output_block.
311        5. returned_bits = Leftmost requested_number_of_bits of temp. */
312     /* Increment counter V = V+1 */
313     Derivation_incrementVector(pIv, CC_PROD_AES_IV_COUNTER_SIZE_IN_WORDS);
314     /* Init AES operation on CTR mode */
315     error = CC_PROD_AesInit(&aesCtx, CIPHER_CTR, CRYPTO_DIRECTION_ENCRYPT,
316                             USER_KEY,
317                             pKey, CC_PROD_AES_Key256Bits_SIZE_IN_BYTES,
318                             pIv, CC_PROD_AES_IV_COUNTER_SIZE_IN_BYTES);
319     if (error != CC_OK) {
320         CC_PAL_LOG_ERR("Faild to CC_PROD_AesInit, error 0x%x\n", error);
321         return error;
322     }
323 #ifndef CMPU_KAT
324     error = CC_PROD_AesProcess(&aesCtx,
325                                temp, sizeof(temp),
326                                firstDummyBytes);
327     if (error != CC_OK) {
328         CC_PAL_LOG_ERR("Faild to CC_PROD_AesProcess, error 0x%x\n", error);
329         return error;
330     }
331 #endif
332 
333     /* generate full blocks of input data */
334     for (i = 0; i < numBlocks; i++) {
335         error = CC_PROD_AesProcess(&aesCtx,
336                                    temp, CC_PROD_AES_BLOCK_SIZE_IN_BYTES,
337                                    pOutputBuff + i*CC_PROD_AES_BLOCK_SIZE_IN_WORDS);
338         if (error != CC_OK) {
339             CC_PAL_LOG_ERR("Faild to CC_PROD_AesProcess, error 0x%x\n", error);
340             return error;
341         }
342     }
343 
344     /* Steps taken from NIST - all following are ignored, since th eworking state is one time
345        6. (Key, V) = Derivation_DRBG_Update (additional_input, Key, V).
346        7. reseed_counter = reseed_counter + 1. */
347 
348     /* Steps taken from NIST
349        8. Return SUCCESS and returned_bits; also return Key, V, and reseed_counter as the new_working_state. */
350     return CC_OK;
351 }
352 
353