1 /*
2 * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 #include "string.h"
7 #include "stdio.h"
8 #include "stdlib.h"
9
10 #include "cc_pal_types.h"
11 #include "mbedtls/ctr_drbg.h"
12
13 #include "run_integration_helper.h"
14 #include "run_integration_test.h"
15 #include "run_integration_pal_log.h"
16 #include "run_integration_flash.h"
17
18 /**
19 * Assigns into ppBuffAligned the next aligned 32bit address relative to pBuff.
20 *
21 * @param pBuff
22 * @param ppBuffAligned
23 */
runIt_buffAlign32(uint8_t * pBuff,uint32_t ** ppBuffAligned,uint32_t wantedBuffSize,const char * name)24 void runIt_buffAlign32(uint8_t* pBuff, uint32_t **ppBuffAligned, uint32_t wantedBuffSize, const char * name)
25 {
26 uint32_t address = (uint32_t)pBuff;
27 uint32_t remainder = (sizeof(uint32_t) - (address % sizeof(uint32_t))) % sizeof(uint32_t);
28 *ppBuffAligned = (uint32_t*)(address + remainder);
29
30 CC_UNUSED_PARAM(wantedBuffSize);
31 CC_UNUSED_PARAM(name);
32
33 #if defined(RUNIT_DEBUG_ALLOC)
34 RUNIT_PRINT_DBG("%-30.30s pBuff[%"PRIxPTR"] ppBuffAligned[%"PRIxPTR"] wantedBuffSize[%04"PRIu32"]\n", name, (uintptr_t)pBuff, (uintptr_t)*ppBuffAligned, wantedBuffSize);
35 #endif
36 }
37
runIt_unhexify(unsigned char * obuf,const char * ibuf)38 int runIt_unhexify(unsigned char *obuf, const char *ibuf)
39 {
40 #define assert(a) do{} while(0)
41 unsigned char c, c2;
42 int len = strlen(ibuf) / 2;
43 assert(strlen( ibuf ) % 2 == 0); /* must be even number of bytes */
44
45 while (*ibuf != 0)
46 {
47 c = *ibuf++;
48 if (c >= '0' && c <= '9')
49 c -= '0';
50 else if (c >= 'a' && c <= 'f')
51 c -= 'a' - 10;
52 else if (c >= 'A' && c <= 'F')
53 c -= 'A' - 10;
54 else
55 assert(0);
56
57 c2 = *ibuf++;
58 if (c2 >= '0' && c2 <= '9')
59 c2 -= '0';
60 else if (c2 >= 'a' && c2 <= 'f')
61 c2 -= 'a' - 10;
62 else if (c2 >= 'A' && c2 <= 'F')
63 c2 -= 'A' - 10;
64 else
65 assert(0);
66
67 *obuf++ = (c << 4) | c2;
68 }
69
70 return len;
71 }
72
runIt_hexify(unsigned char * obuf,const unsigned char * ibuf,int len)73 void runIt_hexify(unsigned char *obuf, const unsigned char *ibuf, int len)
74 {
75 unsigned char l, h;
76
77 while (len != 0)
78 {
79 h = *ibuf / 16;
80 l = *ibuf % 16;
81
82 if (h < 10)
83 *obuf++ = '0' + h;
84 else
85 *obuf++ = 'a' + h - 10;
86
87 if (l < 10)
88 *obuf++ = '0' + l;
89 else
90 *obuf++ = 'a' + l - 10;
91
92 ++ibuf;
93 len--;
94 }
95 }
96
97 /**
98 * This function just returns data from rand().
99 * Although predictable and often similar on multiple
100 * runs, this does not result in identical random on
101 * each run. So do not use this if the results of a
102 * test depend on the random data that is generated.
103 *
104 * rng_state shall be NULL.
105 */
runIt_rndStdRand(void * rng_state,unsigned char * output,size_t len)106 static int runIt_rndStdRand(void *rng_state, unsigned char *output, size_t len)
107 {
108 #if !defined(__OpenBSD__)
109 size_t i;
110
111 if (rng_state != NULL)
112 rng_state = NULL;
113
114 for (i = 0; i < len; ++i)
115 output[i] = rand();
116 #else
117 if( rng_state != NULL )
118 rng_state = NULL;
119
120 arc4random_buf( output, len );
121 #endif /* !OpenBSD */
122
123 return (0);
124 }
125
126 /**
127 * This function returns random based on a buffer it receives.
128 *
129 * rng_state shall be a pointer to a rnd_buf_info structure.
130 *
131 * The number of bytes released from the buffer on each call to
132 * the random function is specified by per_call. (Can be between
133 * 1 and 4)
134 *
135 * After the buffer is empty it will return rand();
136 */
runIt_rndBufferRand(void * rng_state,unsigned char * output,size_t len)137 int runIt_rndBufferRand(void *rng_state, unsigned char *output, size_t len)
138 {
139 rnd_buf_info *info = (rnd_buf_info *) rng_state;
140 size_t use_len;
141
142 if (rng_state == NULL)
143 return (runIt_rndStdRand( NULL, output, len));
144
145 use_len = len;
146 if (len > info->length)
147 use_len = info->length;
148
149 if (use_len)
150 {
151 memcpy(output, info->buf, use_len);
152 info->buf += use_len;
153 info->length -= use_len;
154 }
155
156 if (len - use_len > 0)
157 return (runIt_rndStdRand( NULL, output + use_len, len - use_len));
158
159 return (0);
160 }
161
runIt_free(RunItPtr * ptrElement)162 int runIt_free(RunItPtr *ptrElement)
163 {
164 int rc = 0;
165 RUNIT_ASSERT(ptrElement != NULL);
166
167 mbedtls_free(ptrElement->buf);
168
169 bail:
170 return rc;
171 }
172
runIt_malloc(RunItPtr * ptrElement,size_t length)173 int runIt_malloc(RunItPtr *ptrElement, size_t length)
174 {
175 int rc = 0;
176 RUNIT_ASSERT(ptrElement != NULL);
177
178 memset(ptrElement, 0, sizeof(*ptrElement));
179
180 ptrElement->buf = mbedtls_calloc(1, length + RUNIT_ALIGN32_SLACK + sizeof(uint32_t));
181 runIt_buffAlign32(ptrElement->buf, &(ptrElement->ba), length, "temp");
182 ptrElement->length = length;
183
184 bail:
185 return rc;
186 }
187
188 /**
189 * @brief Function needed by some of CC API.
190 * Converts between CC API signature to internal flash read function
191 * This specific function implementation reads the flash content in newly allocated memory.
192 *
193 * @param flashAddress [input]
194 * @param memDst [output]
195 * @param sizeToRead [input]
196 * @param context [input] not used
197 *
198 * @return CC_OK on success
199 */
runIt_flashReadWrap(void * flashAddress,uint8_t * memDst,uint32_t sizeToRead,void * context)200 uint32_t runIt_flashReadWrap(void* flashAddress, /*! Flash address to read from */
201 uint8_t *memDst, /*! memory destination to read the data to */
202 uint32_t sizeToRead, /*! size to read from Flash (in bytes) */
203 void* context)
204 {
205 CC_UNUSED_PARAM(context);
206
207 if (runIt_flashRead((uint32_t)flashAddress, memDst, sizeToRead) != RUNIT_ERROR__OK)
208 return 1;
209
210 return 0;
211 }
212
213
runIt_buildRandomBuffer(uint8_t * pBuf,size_t bufSize)214 int runIt_buildRandomBuffer(uint8_t *pBuf, size_t bufSize)
215 {
216 uint32_t chunkSize = 0;
217 uint32_t doneSize = 0;
218
219 while (doneSize < bufSize)
220 {
221 chunkSize = (bufSize - doneSize > MBEDTLS_CTR_DRBG_MAX_REQUEST) ? MBEDTLS_CTR_DRBG_MAX_REQUEST : (bufSize - doneSize);
222 if (gpRndContext->rndGenerateVectFunc(gpRndContext->rndState, pBuf + doneSize, chunkSize) == 0)
223 {
224 doneSize += chunkSize;
225 }
226 else
227 {
228 return RUNIT_ERROR__FAIL;
229 }
230 }
231
232 return RUNIT_ERROR__OK;
233 }
234