Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
pal_drbg_test.c
00001 // ---------------------------------------------------------------------------- 00002 // Copyright 2016-2019 ARM Ltd. 00003 // 00004 // SPDX-License-Identifier: Apache-2.0 00005 // 00006 // Licensed under the Apache License, Version 2.0 (the "License"); 00007 // you may not use this file except in compliance with the License. 00008 // You may obtain a copy of the License at 00009 // 00010 // http://www.apache.org/licenses/LICENSE-2.0 00011 // 00012 // Unless required by applicable law or agreed to in writing, software 00013 // distributed under the License is distributed on an "AS IS" BASIS, 00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 // See the License for the specific language governing permissions and 00016 // limitations under the License. 00017 // ---------------------------------------------------------------------------- 00018 00019 #include "pal.h" 00020 #include "unity.h" 00021 #include "unity_fixture.h" 00022 #include "pal_plat_drbg.h" 00023 #include "pal_plat_drbg.h" 00024 #include "test_runners.h" 00025 00026 #include <string.h> 00027 #include <stdlib.h> 00028 00029 #define TRACE_GROUP "PAL" 00030 00031 TEST_GROUP(pal_drbg); 00032 00033 #define PAL_RANDOM_TEST_LOOP 100000 00034 #define PAL_RANDOM_ARRAY_TEST_SIZE 100 00035 #define PAL_RANDOM_BUFFER_ARRAY_TEST_SIZE 60 00036 00037 #define PAL_RUNNING_TEST_TIME 5 //estimation on length of test in seconds 00038 #define PAL_TEST_HIGH_RES_TIMER 100 00039 #define PAL_TEST_HIGH_RES_TIMER2 10 00040 #define PAL_TEST_PERCENTAGE_LOW 95 00041 #define PAL_TEST_PERCENTAGE_HIGH 105 00042 #define PAL_TEST_PERCENTAGE_HUNDRED 100 00043 00044 00045 TEST_SETUP(pal_drbg) 00046 { 00047 palStatus_t status = PAL_SUCCESS; 00048 status = pal_init(); 00049 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 00050 00051 #if !PAL_USE_HW_TRNG 00052 // If no hardware trng - entropy must be injected for random to work 00053 uint8_t entropy_buf[48] = { 0 }; 00054 status = pal_osEntropyInject(entropy_buf, sizeof(entropy_buf)); 00055 TEST_ASSERT(status == PAL_SUCCESS || status == PAL_ERR_ENTROPY_EXISTS); 00056 #endif 00057 00058 } 00059 00060 TEST_TEAR_DOWN(pal_drbg) 00061 { 00062 pal_destroy(); 00063 } 00064 00065 00066 struct randBuf 00067 { 00068 uint8_t rand[6]; 00069 }; 00070 00071 /*! \brief Check the random APIs. For each API, the test calls the random API in a loop 00072 * and stores the result. When the loop finishes, we verify that the count of the 00073 * duplication in the stored values is less than the defined random margin value for each API. 00074 * 00075 * | # | Step | Expected | 00076 * |--- |-----------------------------------------------------------------------------|--------------------------| 00077 * | 1 | Fill array with random 32bit values using `pal_osRandom32bit` in a loop. | PAL_SUCCESS | 00078 * | 2 | Check array for matching values and make sure there are not too many. | PAL_SUCCESS | 00079 * | 3 | Fill array with random values using `pal_osRandomUniform` in a loop. | PAL_SUCCESS | 00080 * | 4 | Check array for matching values and make sure there are not too many. | PAL_SUCCESS | 00081 * | 5 | Fill array with random byte sequences using `pal_osRandomBuffer` in a loop. | PAL_SUCCESS | 00082 * | 6 | Check array for matching values and make sure there are not too many. | PAL_SUCCESS | 00083 * | 7 | Call pal_osRandom32bit with NULL output parameter. | PAL_ERR_INVALID_ARGUMENT | 00084 * | 8 | Call pal_osRandomBuffer with NULL output parameter. | PAL_ERR_INVALID_ARGUMENT | 00085 * | 9 | Call pal_osRandomUniform with NULL output parameter. | PAL_ERR_INVALID_ARGUMENT | 00086 * | 10 | Call pal_osRandomBuffer while pal is not initialized. | PAL_ERR_NOT_INITIALIZED | 00087 */ 00088 TEST(pal_drbg, RandomUnityTest) 00089 { 00090 palStatus_t status = PAL_SUCCESS; 00091 uint32_t randomArray[PAL_RANDOM_ARRAY_TEST_SIZE]; 00092 struct randBuf randomBufArray[PAL_RANDOM_BUFFER_ARRAY_TEST_SIZE]; 00093 uint32_t randomMargin = 0; 00094 00095 memset(randomArray, 0x0, sizeof(randomArray)); 00096 memset(randomBufArray, 0x0, sizeof(randomBufArray)); 00097 /*#1*/ 00098 for(int i = 0; i < PAL_RANDOM_ARRAY_TEST_SIZE ; ++i) 00099 { 00100 status = pal_osRandom32bit(&randomArray[i]); 00101 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 00102 } 00103 /*#2*/ 00104 for(int k = 0; k < PAL_RANDOM_ARRAY_TEST_SIZE ; ++k) 00105 { 00106 for (int j = k+1 ; j < PAL_RANDOM_ARRAY_TEST_SIZE ; ++j) 00107 { 00108 if (randomArray[k] == randomArray[j]) 00109 { 00110 ++randomMargin; 00111 } 00112 } 00113 randomArray[k] = 0; 00114 } 00115 TEST_ASSERT_TRUE(20 >= randomMargin); 00116 randomMargin = 0; 00117 /*#5*/ 00118 for (int i = 0; i < PAL_RANDOM_BUFFER_ARRAY_TEST_SIZE ; ++i) 00119 { 00120 status = pal_osRandomBuffer(randomBufArray[i].rand, sizeof(randomBufArray[i].rand)); 00121 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 00122 } 00123 /*#6*/ 00124 for(int k = 0; k < PAL_RANDOM_BUFFER_ARRAY_TEST_SIZE ; ++k) 00125 { 00126 for (int j = k+1 ; j < PAL_RANDOM_BUFFER_ARRAY_TEST_SIZE ; ++j) 00127 { 00128 if(0 == memcmp(randomBufArray[k].rand, randomBufArray[j].rand, sizeof(uint8_t)*6)) 00129 { 00130 ++randomMargin; 00131 } 00132 } 00133 } 00134 00135 TEST_ASSERT_TRUE(10 >= randomMargin); 00136 00137 #ifdef DEBUG 00138 /*#7*/ 00139 status = pal_osRandom32bit(NULL); 00140 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 00141 00142 /*#8*/ 00143 status = pal_osRandomBuffer(NULL, 0); 00144 TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status); 00145 00146 00147 #endif 00148 00149 #if (PAL_INITIALIZED_BEFORE_TESTS == 0) 00150 /*#10*/ 00151 pal_destroy(); 00152 00153 status = pal_osRandomBuffer(randomBufArray[0].rand, sizeof(randomBufArray[0].rand)); 00154 TEST_ASSERT_EQUAL_HEX(PAL_ERR_NOT_INITIALIZED , status); 00155 #endif 00156 } 00157 00158 00159 /*! \brief call the random API in a PAL_RANDOM_TEST_LOOP loop. 00160 * | # | Step | Expected | 00161 * |---|--------------------------------|-------------| 00162 * | 1 | Call `pal_osRandomBuffer` in a PAL_RANDOM_TEST_LOOP loop . PAL_SUCCESS | 00163 */ 00164 TEST(pal_drbg, loopRandomBigNumber) 00165 { 00166 palStatus_t status = PAL_SUCCESS; 00167 uint8_t loopRandomArray[PAL_RANDOM_ARRAY_TEST_SIZE]; 00168 00169 for (int i = 0; i < PAL_RANDOM_TEST_LOOP; ++i) 00170 { 00171 status = pal_osRandomBuffer(loopRandomArray, sizeof(loopRandomArray)); 00172 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 00173 } 00174 } 00175 00176 // the following functions are not part of PAL's external API hence extern 00177 extern palStatus_t pal_plat_noiseWriteValue(const int32_t* data, uint8_t startBit, uint8_t lenBits, uint8_t* bitsWritten); 00178 extern palStatus_t pal_plat_noiseWriteBuffer(int32_t* buffer, uint16_t lenBits, uint16_t* bitsWritten); 00179 extern palStatus_t pal_plat_noiseRead(int32_t buffer[PAL_NOISE_BUFFER_LEN], bool partial, uint16_t* bitsRead); 00180 00181 /*! \brief This test verifies the functionality of noise collection 00182 * 00183 * | # | Step | Expected | 00184 * |---|--------------------------------------------------------------------------------------------|-------------| 00185 * | 1 | Reset the noise buffer by reading whatever is available | PAL_SUCCESS | 00186 * | 2 | Write an entire int32_t (all bits) and verify writes and that full read not possible | PAL_SUCCESS | 00187 * | 3 | Write only some bits of the int32_t and verify writes and that full read not possible | PAL_SUCCESS | 00188 * | 4 | Write only some bits of the int32_t, implicitly causing splitting the value into 2 indexes | PAL_SUCCESS | 00189 * | 5 | Read whatever was collected thus far (partial read) and verify output | PAL_SUCCESS | 00190 * | 6 | Try to read again and verify buffer is empty | PAL_SUCCESS | 00191 * | 7 | Write a buffer excluding the last 7 bits of the last index and verify results | PAL_SUCCESS | 00192 * | 8 | Fill the buffer and try to write some more data into it | PAL_SUCCESS | 00193 */ 00194 TEST(pal_drbg, pal_noise) 00195 { 00196 palStatus_t status; 00197 int32_t outBuffer[PAL_NOISE_BUFFER_LEN] = { 0 }; 00198 int32_t inBuffer[] = { 0xB76EC265, 0xD16ACE6E, 0xF56AAD6A }; 00199 uint16_t bitsWritten = 0; 00200 uint16_t bitsRead = 0; 00201 int32_t writeValue; 00202 uint8_t i; 00203 00204 /*#1*/ 00205 pal_plat_noiseRead(outBuffer, true, &bitsRead); 00206 memset(outBuffer, 0, PAL_NOISE_SIZE_BYTES); 00207 00208 /*#2*/ 00209 writeValue = 0xCB76102A; 00210 status = pal_plat_noiseWriteValue(&writeValue, 0, 32, (uint8_t*)&bitsWritten); // write all bits 00211 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 00212 TEST_ASSERT_EQUAL(32, bitsWritten); 00213 status = pal_plat_noiseRead(outBuffer, false, &bitsRead); 00214 TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_NOISE_BUFFER_NOT_FULL , status); 00215 TEST_ASSERT_EQUAL(0, bitsRead); 00216 00217 /*#3*/ 00218 status = pal_plat_noiseWriteValue(&writeValue, 3, 20, (uint8_t*)&bitsWritten); // write some of the bits, starting at bit index 3 00219 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 00220 TEST_ASSERT_EQUAL(20, bitsWritten); 00221 status = pal_plat_noiseRead(outBuffer, false, &bitsRead); 00222 TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_NOISE_BUFFER_NOT_FULL , status); 00223 TEST_ASSERT_EQUAL(0, bitsRead); 00224 00225 /*#4*/ 00226 status = pal_plat_noiseWriteValue(&writeValue, 16, 16, (uint8_t*)&bitsWritten); // write some of the bits, starting at bit index 16, this functionality tests splitting the bits into 2 different indexes 00227 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 00228 TEST_ASSERT_EQUAL(16, bitsWritten); 00229 status = pal_plat_noiseRead(outBuffer, false, &bitsRead); 00230 TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_NOISE_BUFFER_NOT_FULL , status); 00231 TEST_ASSERT_EQUAL(0, bitsRead); 00232 00233 /*#5*/ 00234 status = pal_plat_noiseRead(outBuffer, true, &bitsRead); // read whatever collected (resets buffer) 00235 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 00236 TEST_ASSERT_EQUAL(64, bitsRead); // even though we wrote 68 bits by now, output should be 64 since the last byte is not full so we should not receive it back 00237 TEST_ASSERT_EQUAL_HEX(0xCB76102A, outBuffer[0]); 00238 TEST_ASSERT_EQUAL_HEX(0xB76EC205, outBuffer[1]); 00239 TEST_ASSERT_EQUAL_HEX(0, outBuffer[2]); 00240 memset(outBuffer, 0, PAL_NOISE_SIZE_BYTES); 00241 00242 /*#6*/ 00243 status = pal_plat_noiseRead(outBuffer, false, &bitsRead); 00244 TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_NOISE_BUFFER_EMPTY , status); 00245 TEST_ASSERT_EQUAL(0, bitsRead); 00246 00247 /*#7*/ 00248 status = pal_plat_noiseWriteBuffer(inBuffer, ((sizeof(inBuffer) * CHAR_BIT) - 7), &bitsWritten); // write all except for the last 7 bits of index 2 00249 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 00250 TEST_ASSERT_EQUAL(((sizeof(inBuffer) * CHAR_BIT) - 7), bitsWritten); 00251 status = pal_plat_noiseRead(outBuffer, false, &bitsRead); 00252 TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_NOISE_BUFFER_NOT_FULL , status); 00253 TEST_ASSERT_EQUAL(0, bitsRead); 00254 status = pal_plat_noiseRead(outBuffer, true, &bitsRead); // read whatever collected (resets buffer) 00255 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 00256 TEST_ASSERT_NOT_EQUAL(0, bitsRead); 00257 TEST_ASSERT_EQUAL_HEX(inBuffer[0], outBuffer[0]); 00258 TEST_ASSERT_EQUAL_HEX(inBuffer[1], outBuffer[1]); 00259 TEST_ASSERT_EQUAL_HEX(0x6AAD6A, outBuffer[2]); 00260 00261 /*#8*/ 00262 for (i = 0; i <= (sizeof(inBuffer) / sizeof(int32_t)); ++i) 00263 { 00264 status = pal_plat_noiseWriteBuffer(inBuffer, (sizeof(inBuffer) * CHAR_BIT), &bitsWritten); 00265 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 00266 TEST_ASSERT_EQUAL_HEX((sizeof(inBuffer) * CHAR_BIT), bitsWritten); 00267 } 00268 status = pal_plat_noiseWriteBuffer(inBuffer, (sizeof(inBuffer) * CHAR_BIT), &bitsWritten); 00269 TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_NOISE_BUFFER_FULL , status); 00270 TEST_ASSERT_EQUAL_HEX(0, bitsWritten); 00271 }
Generated on Mon Aug 29 2022 19:53:40 by
