tests/puf_sram: add test application
This commit is contained in:
parent
2f86d6fcd8
commit
2262a6e309
7
tests/puf_sram/Makefile
Normal file
7
tests/puf_sram/Makefile
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
BOARD ?= nucleo-f411re
|
||||||
|
|
||||||
|
include ../Makefile.tests_common
|
||||||
|
|
||||||
|
USEMODULE += puf_sram
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.include
|
||||||
33
tests/puf_sram/README.md
Normal file
33
tests/puf_sram/README.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Tool Introduction
|
||||||
|
This tool is designed to interface with a test to get the random numbers generated by the using a hash of a block of uninitialized SRAM. In order to run the test a certain hardware setup is required due to the requirement to power off the DUT (device under test) for a certain time. Furthermore, the module detects button and/or software resets. If you push the reset button for example (without powering off the DUT), a warning should be printed to the console.
|
||||||
|
|
||||||
|
# Setup
|
||||||
|
## Required Tools
|
||||||
|
- DUT (a supported RIOT target board)
|
||||||
|
- USB to UART converter that supports setting the RTS pin and 5 volts (ie. FT232RL FTDI USB to TTL adapter)
|
||||||
|
- MOSFET to control power to the DUT (ie. STP36NF06L)
|
||||||
|
- Jumper cables
|
||||||
|
- Solderless breadboard
|
||||||
|
|
||||||
|
## Wiring Example
|
||||||
|
1. RTS <--> MOSFET gate pin (FT232RL RTS - STP36NF06L 1)
|
||||||
|
2. +5V <--> MOSFET drain pin (FT232RL 5V - STP36NF06L 2)
|
||||||
|
3. DUT Power <--> MOSFET source pin (E15 - STP36NF06L 3)
|
||||||
|
4. DUT UART TX <--> USB to UART RX
|
||||||
|
5. GND <--> GND
|
||||||
|
|
||||||
|
## Example Setup
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
# Running the test
|
||||||
|
1. Plug the USB to UART converter in (it should be done first so it can autoconnect to the serial port)
|
||||||
|
2. Program the DUT with the puf_sram test
|
||||||
|
3. Connect all wires
|
||||||
|
4. change jumpers to only run on power provided by the USB to USRT converter
|
||||||
|
5. Run the example_test.py
|
||||||
|
|
||||||
|
# Running Custom Tests
|
||||||
|
Different tests can be run using the get_seed_list(self, n=10000, off_time=1, allow_print=False)
|
||||||
|
n -> the number of samples to take
|
||||||
|
off_time -> The time that the device is powered off to properly randomize the RAM
|
||||||
31
tests/puf_sram/main.c
Normal file
31
tests/puf_sram/main.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 HAW Hamburg
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup tests
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Test application for the random number generator based of SRAM
|
||||||
|
*
|
||||||
|
* @author Kevin Weiss <kevin.weiss@haw-hamburg.de>
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "puf_sram.h"
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
puts("Start: Test random number generator");
|
||||||
|
|
||||||
|
printf("Success: Data for puf_sram_seed: [0x%08lX]", puf_sram_seed);
|
||||||
|
|
||||||
|
puts("End: Test finished");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
47
tests/puf_sram/tests/example_test.py
Normal file
47
tests/puf_sram/tests/example_test.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (C) 2018 Kevin Weiss <kevin.weiss@haw-hamburg.de>
|
||||||
|
# Copyright (C) 2018 Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||||
|
#
|
||||||
|
# This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
# General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
# directory for more details.
|
||||||
|
|
||||||
|
import puf_sram_if
|
||||||
|
import numpy
|
||||||
|
|
||||||
|
|
||||||
|
def min_erntropy(all_meas):
|
||||||
|
p1 = numpy.zeros(len(all_meas[0]))
|
||||||
|
# number of ones for each bit
|
||||||
|
for i in range(0, len(all_meas[0])):
|
||||||
|
tmp = list(map(lambda x: int(x[i]), all_meas))
|
||||||
|
p1[i] = numpy.count_nonzero(tmp)
|
||||||
|
|
||||||
|
# probability of ones
|
||||||
|
p1 = numpy.divide(p1, float(len(all_meas)))
|
||||||
|
# probability of zeros
|
||||||
|
p0 = 1 - p1
|
||||||
|
|
||||||
|
p0_1_max = numpy.maximum(p1, p0)
|
||||||
|
log2_p0_1_max = numpy.log2(p0_1_max)
|
||||||
|
H_min = numpy.sum(-log2_p0_1_max)
|
||||||
|
H_min_rel = 100 * H_min/len(p0_1_max)
|
||||||
|
|
||||||
|
return [H_min, H_min_rel]
|
||||||
|
|
||||||
|
|
||||||
|
def main_func():
|
||||||
|
puf_sram = puf_sram_if.PufSram()
|
||||||
|
seeds = puf_sram.get_seed_list(n=500, off_time=1, allow_print=True)
|
||||||
|
seeds = [format(x, '0>32b') for x in seeds]
|
||||||
|
H_min, H_min_rel = min_erntropy(seeds)
|
||||||
|
|
||||||
|
print("Number of seeds: %i " % len(seeds))
|
||||||
|
print("Seed length : %i Bit " % len(seeds[0]))
|
||||||
|
print("Abs. Entropy : %02.02f Bit " % H_min)
|
||||||
|
print("Rel. Entropy : %02.02f perc. " % H_min_rel)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main_func()
|
||||||
62
tests/puf_sram/tests/puf_sram_if.py
Normal file
62
tests/puf_sram/tests/puf_sram_if.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (C) 2018 Kevin Weiss <kevin.weiss@haw-hamburg.de>
|
||||||
|
#
|
||||||
|
# This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
# General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
# directory for more details.
|
||||||
|
|
||||||
|
import serial
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
class PufSram:
|
||||||
|
|
||||||
|
def __init__(self, port='/dev/ttyUSB0', baud=115200):
|
||||||
|
self.__dev = serial.Serial(port, baud, timeout=10)
|
||||||
|
if(self.__dev.isOpen() is False):
|
||||||
|
self.__dev.open()
|
||||||
|
|
||||||
|
def repower(self, shutdown_time=1):
|
||||||
|
self.__dev.setRTS(True)
|
||||||
|
time.sleep(shutdown_time)
|
||||||
|
self.__dev.setRTS(False)
|
||||||
|
|
||||||
|
def read_data(self):
|
||||||
|
data = None
|
||||||
|
start = False
|
||||||
|
str = 'no_exit'
|
||||||
|
while (str != ''):
|
||||||
|
str = self.__dev.readline()
|
||||||
|
if (b'Start: ' in str):
|
||||||
|
start = True
|
||||||
|
if ((b'Success: ' in str) and (start is True)):
|
||||||
|
if (b'[' in str) and (b']' in str):
|
||||||
|
data_str = str[str.find(b"[")+1:str.find(b"]")]
|
||||||
|
data = int(data_str, 0)
|
||||||
|
if ((b'End: ' in str) and (data is not None)):
|
||||||
|
return data
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_seed_list(self, n=10000, off_time=1, allow_print=False):
|
||||||
|
data = list()
|
||||||
|
for i in range(0, n):
|
||||||
|
self.repower(off_time)
|
||||||
|
data.append(self.read_data())
|
||||||
|
if (allow_print):
|
||||||
|
print('Iteration %i/%i' % (i, n))
|
||||||
|
print(data[-1])
|
||||||
|
return data
|
||||||
|
|
||||||
|
def connect(self, dev):
|
||||||
|
if (dev.isOpen()):
|
||||||
|
dev.close()
|
||||||
|
self.__dev = self
|
||||||
|
if(self.__dev.isOpen() is False):
|
||||||
|
self.__dev.open()
|
||||||
|
|
||||||
|
def disconnect(self):
|
||||||
|
self.__dev.close()
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self.__dev.close()
|
||||||
Loading…
x
Reference in New Issue
Block a user