Skip to content

Commit a0a9b54

Browse files
authored
Merge pull request ARMmbed#7057 from theamirocohen/trng_test
Add TRNG API test
2 parents 4957dd5 + e92f41a commit a0a9b54

File tree

6 files changed

+1479
-0
lines changed

6 files changed

+1479
-0
lines changed

TESTS/host_tests/trng_reset.py

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
"""
2+
Copyright (c) 2018 ARM Limited
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
"""
15+
16+
"""
17+
This script is the host script for trng test sequence, it send the
18+
step signaling sequence and receive and transmit data to the device after
19+
reset if necesarry (default loading and storing mechanism while reseting the device
20+
is NVstore, in case NVstore isn't enabled we'll use current infrastructure,
21+
for more details see main.cpp file)
22+
"""
23+
24+
import time
25+
from mbed_host_tests import BaseHostTest
26+
from mbed_host_tests.host_tests_runner.host_test_default import DefaultTestSelector
27+
from time import sleep
28+
29+
DEFAULT_CYCLE_PERIOD = 1.0
30+
MSG_VALUE_DUMMY = '0'
31+
MSG_TRNG_READY = 'ready'
32+
MSG_TRNG_BUFFER = 'buffer'
33+
MSG_TRNG_TEST_STEP1 = 'check_step1'
34+
MSG_TRNG_TEST_STEP2 = 'check_step2'
35+
MSG_KEY_SYNC = '__sync'
36+
MSG_KEY_RESET_COMPLETE = 'reset_complete'
37+
MSG_KEY_TEST_SUITE_ENDED = 'Test_suite_ended'
38+
MSG_KEY_EXIT = 'exit'
39+
40+
class TRNGResetTest(BaseHostTest):
41+
"""Test for the TRNG API.
42+
"""
43+
44+
def __init__(self):
45+
super(TRNGResetTest, self).__init__()
46+
self.did_reset = False
47+
self.ready = False
48+
self.suite_ended = False
49+
self.buffer = 0
50+
self.test_steps_sequence = self.test_steps()
51+
# Advance the coroutine to it's first yield statement.
52+
self.test_steps_sequence.send(None)
53+
54+
#define callback functions for msg handling
55+
def setup(self):
56+
self.register_callback(MSG_TRNG_READY, self.cb_device_ready)
57+
self.register_callback(MSG_TRNG_BUFFER, self.cb_trng_buffer)
58+
self.register_callback(MSG_KEY_TEST_SUITE_ENDED, self.cb_device_test_suit_ended)
59+
self.register_callback(MSG_KEY_RESET_COMPLETE, self.cb_reset_complete)
60+
61+
#receive sent data from device before reset
62+
def cb_trng_buffer(self, key, value, timestamp):
63+
"""Acknowledge device rebooted correctly and feed the test execution
64+
"""
65+
self.buffer = value
66+
67+
try:
68+
if self.test_steps_sequence.send(value):
69+
self.notify_complete(True)
70+
except (StopIteration, RuntimeError) as exc:
71+
self.notify_complete(False)
72+
73+
def cb_device_ready(self, key, value, timestamp):
74+
"""Acknowledge device rebooted correctly and feed the test execution
75+
"""
76+
self.ready = True
77+
78+
try:
79+
if self.test_steps_sequence.send(value):
80+
self.notify_complete(True)
81+
except (StopIteration, RuntimeError) as exc:
82+
self.notify_complete(False)
83+
84+
def cb_reset_complete(self, key, value, timestamp):
85+
"""Acknowledge reset complete
86+
"""
87+
self.did_reset = True
88+
89+
try:
90+
if self.test_steps_sequence.send(value):
91+
self.notify_complete(True)
92+
except (StopIteration, RuntimeError) as exc:
93+
self.notify_complete(False)
94+
95+
def cb_device_test_suit_ended(self, key, value, timestamp):
96+
"""Acknowledge device finished a test step correctly and feed the test execution
97+
"""
98+
self.suite_ended = True
99+
100+
try:
101+
if self.test_steps_sequence.send(value):
102+
self.notify_complete(True)
103+
except (StopIteration, RuntimeError) as exc:
104+
self.notify_complete(False)
105+
106+
#define test steps and actions
107+
def test_steps(self):
108+
"""Test step 1
109+
"""
110+
wait_for_communication = yield
111+
112+
self.ready = False
113+
self.did_reset = False
114+
self.suite_ended = False
115+
self.send_kv(MSG_TRNG_TEST_STEP1, MSG_VALUE_DUMMY)
116+
wait_for_communication = yield
117+
if self.buffer == 0:
118+
raise RuntimeError('Phase 1: No buffer received.')
119+
120+
self.reset()
121+
122+
"""Test step 2 (After reset)
123+
"""
124+
wait_for_communication = yield
125+
if self.did_reset == False:
126+
raise RuntimeError('Phase 1: Platform did not reset as expected.')
127+
128+
self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY)
129+
130+
wait_for_communication = yield
131+
132+
if self.ready == False:
133+
raise RuntimeError('Phase 1: Platform not ready as expected.')
134+
135+
self.send_kv(MSG_TRNG_TEST_STEP2, self.buffer)
136+
137+
wait_for_communication = yield
138+
139+
if self.suite_ended == False:
140+
raise RuntimeError('Test failed.')
141+
142+
self.send_kv(MSG_KEY_EXIT, MSG_VALUE_DUMMY)
143+
144+
# The sequence is correct -- test passed.
145+
yield
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
/*
2+
* Copyright (c) 2018 ARM Limited. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Licensed under the Apache License, Version 2.0 (the License); you may
5+
* not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "base64b.h"
18+
19+
using namespace std;
20+
21+
static char IntToBase64Char(uint8_t intVal)
22+
{
23+
const char *base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
24+
return base64Digits[intVal & 0x3F];
25+
}
26+
27+
#define BASE_64_PAD 0xFF
28+
static base64_result_e Base64CharToInt(char base64, uint8_t *intVal)
29+
{
30+
if (NULL == intVal) {
31+
return BASE64_INVALID_PARAMETER;
32+
}
33+
34+
if ((base64 >= 'A') && (base64 <= 'Z')) {
35+
*intVal = base64 - 'A' ;
36+
} else if ((base64 >= 'a') && (base64 <= 'z')) {
37+
*intVal = base64 - 'a' + 26;
38+
} else if ((base64 >= '0') && (base64 <= '9')) {
39+
*intVal = base64 - '0' + 52;
40+
} else if (base64 == '+') {
41+
*intVal = 62;
42+
} else if (base64 == '/') {
43+
*intVal = 63;
44+
} else if (base64 == '=') {
45+
*intVal = BASE_64_PAD;
46+
} else {
47+
return BASE64_ERROR;
48+
}
49+
50+
return BASE64_SUCCESS;
51+
}
52+
53+
base64_result_e trng_DecodeNBase64(const char *string,
54+
uint32_t stringMaxSize,
55+
void *buffer,
56+
uint32_t bufferSize,
57+
uint32_t *lengthWritten,
58+
uint32_t *charsProcessed)
59+
{
60+
base64_result_e result = BASE64_SUCCESS;
61+
uint32_t bitOffset = 0;
62+
uint8_t *writePtr = (uint8_t *)buffer;
63+
uint8_t *bufferEnd = (uint8_t *)buffer + bufferSize;
64+
uint8_t tempVal = 0;
65+
uint32_t currPos = 0;
66+
uint32_t localBytesWritten = 0;
67+
uint32_t localCharsProcessed = 0;
68+
bool isEndOfString = false;
69+
70+
if ((NULL == string) || (NULL == buffer) || (bufferSize == 0)) {
71+
return BASE64_INVALID_PARAMETER;
72+
}
73+
74+
*writePtr = 0;
75+
while (( currPos < stringMaxSize ) &&
76+
( string[currPos] != 0 ) &&
77+
( writePtr < bufferEnd ) &&
78+
( !isEndOfString )) {
79+
uint8_t val;
80+
81+
if (string[currPos] == 0) {
82+
break;
83+
}
84+
85+
result = Base64CharToInt(string[currPos++], &val);
86+
if (result != BASE64_SUCCESS) {
87+
break;
88+
}
89+
90+
if (val != BASE_64_PAD) {
91+
if (bitOffset <= 2) {
92+
tempVal |= val << (2 - bitOffset);
93+
if (bitOffset == 2) {
94+
*writePtr++ = tempVal;
95+
tempVal = 0;
96+
}
97+
} else {
98+
*writePtr++ = (uint8_t)(tempVal | (val >> (bitOffset - 2)));
99+
tempVal = (uint8_t)(val << (10 - bitOffset));
100+
}
101+
} else { // found BASE_64_PAD
102+
// At most two pad characters may occur at the end of the encoded stream
103+
if (bitOffset == 2) {
104+
isEndOfString = true; // The last padding byte has been processed.
105+
} else if (bitOffset != 4) {
106+
return BASE64_ERROR; // Incorrect padding
107+
}
108+
}
109+
110+
bitOffset = (bitOffset + 6) & 0x7;
111+
if (bitOffset == 0) {
112+
localBytesWritten = (uint32_t)(writePtr - (uint8_t *)buffer);
113+
localCharsProcessed = currPos;
114+
}
115+
}
116+
if (charsProcessed == NULL) {
117+
localBytesWritten = (uint32_t)(writePtr - (uint8_t *)buffer);
118+
} else {
119+
*charsProcessed = localCharsProcessed;
120+
}
121+
if (lengthWritten != NULL) {
122+
*lengthWritten = localBytesWritten;
123+
} else if (bufferSize != localBytesWritten) {
124+
return BASE64_BUFFER_TOO_SMALL;
125+
}
126+
127+
// Check if additional bytes should have been processed but buffer isn't sufficient.
128+
if (( result == BASE64_SUCCESS ) &&
129+
( !isEndOfString ) &&
130+
( currPos < stringMaxSize ) &&
131+
( string[currPos] != 0 ) &&
132+
( string[currPos] != '=' ) ) {
133+
return BASE64_BUFFER_TOO_SMALL;
134+
}
135+
136+
if (result != BASE64_SUCCESS) {
137+
return result;
138+
}
139+
140+
return BASE64_SUCCESS;
141+
}
142+
143+
base64_result_e trng_EncodeBase64(const void *buffer, uint32_t bufferSize, char *string, uint32_t stringSize)
144+
{
145+
uint32_t bitOffset = 0;
146+
147+
const uint8_t *readPtr = (const uint8_t *)buffer;
148+
const uint8_t *bufferEnd = (const uint8_t *)buffer + bufferSize;
149+
150+
char *writePtr = string;
151+
char *stringEnd = string + stringSize - 1;
152+
153+
if ((NULL == string) || (NULL == buffer) || (stringSize == 0)) {
154+
return BASE64_INVALID_PARAMETER;
155+
}
156+
157+
stringSize--;
158+
while (readPtr < bufferEnd && writePtr < stringEnd) {
159+
uint8_t tempVal = 0;
160+
switch (bitOffset) {
161+
case 0:
162+
*writePtr++ = IntToBase64Char(*readPtr >> 2); // take upper 6 bits
163+
break;
164+
case 6:
165+
tempVal = *readPtr++ << 4;
166+
if (readPtr < bufferEnd) {
167+
tempVal |= *readPtr >> 4;
168+
}
169+
*writePtr++ = IntToBase64Char(tempVal);
170+
break;
171+
case 4:
172+
tempVal = *readPtr++ << 2;
173+
if (readPtr < bufferEnd) {
174+
tempVal |= *readPtr >> 6;
175+
}
176+
*writePtr++ = IntToBase64Char(tempVal);
177+
break;
178+
case 2:
179+
*writePtr++ = IntToBase64Char(*readPtr++);
180+
break;
181+
default:
182+
return BASE64_ERROR; // we should never reach this code.
183+
}
184+
bitOffset = (bitOffset + 6) & 0x7;
185+
}
186+
while (bitOffset > 0 && writePtr < stringEnd) {
187+
*writePtr++ = '=';
188+
bitOffset = (bitOffset + 6) & 0x7;
189+
}
190+
*writePtr = 0;
191+
192+
if ((readPtr < bufferEnd) || (bitOffset != 0)) {
193+
return (BASE64_BUFFER_TOO_SMALL);
194+
}
195+
196+
return (BASE64_SUCCESS);
197+
}

TESTS/mbed_hal/trng/base64b/base64b.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2018 ARM Limited. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Licensed under the Apache License, Version 2.0 (the License); you may
5+
* not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <stdint.h>
18+
#include <stdlib.h>
19+
#include <string>
20+
21+
typedef enum {
22+
BASE64_SUCCESS = 0,
23+
BASE64_INVALID_PARAMETER = 1,
24+
BASE64_BUFFER_TOO_SMALL = 2,
25+
BASE64_ERROR = 3,
26+
} base64_result_e;
27+
28+
base64_result_e trng_EncodeBase64(const void *buffer, uint32_t bufferSize, char *string, uint32_t stringSize);
29+
base64_result_e trng_DecodeNBase64(const char *string, uint32_t stringMaxSize, void *buffer, uint32_t bufferSize,
30+
uint32_t *lengthWritten, uint32_t *charsProcessed);
31+
32+

0 commit comments

Comments
 (0)