First commit

This commit is contained in:
gbucchino
2026-06-15 10:31:58 +02:00
commit 33de82aa1c
12 changed files with 3107 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
#ifndef H_COMMON
#define H_COMMON
struct prng{
unsigned int p;
unsigned int q;
unsigned long long seed;
unsigned long long output;
} /*__attribute__((packed))*/;
#define CSPRNG_VERS 0x1
/* Define all commandes */
#define CSPRNG_CMD_GET_RNG 0x10
struct cmd{
int version;
int cmd;
};
#endif
Executable
+3
View File
@@ -0,0 +1,3 @@
#!/usr/bin/bash
gcc -o main uart.c test_bbs.c main.c && ./main $1
Executable
BIN
View File
Binary file not shown.
+86
View File
@@ -0,0 +1,86 @@
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include "common.h"
#include "uart.h"
#include "test_bbs.h"
static void bbs_module(){
struct prng *s_prng = {0};
int status = 0;
int fd;
int totalSuccess = 0;
int totalFailed = 0;
if ((fd = open("./reports", O_CREAT | O_RDWR, 00660)) < 0){
printf("Failed to create the report\n");
exit(-1);
}
//printf("%d %d %llu %llu\n", s_prng->p, s_prng->q, s_prng->seed, s_prng->output);
for (int i = 0; i < 100; i++){
char tmp[32];
snprintf(tmp, 32, "*** Test: %d ***\n", i);
write(fd, "***************\n", 16);
write(fd, tmp, strlen(tmp));
write(fd, "***************\n", 16);
status = send_uart(&s_prng);
int result = test_bbs(fd, s_prng->p, s_prng->q, s_prng->seed, s_prng->output);
if (!result){
printf("Test %d: success\n", i);
totalSuccess += 1;
}
else{
printf("Test %d: failed\n", i);
totalFailed += 1;
}
memset(s_prng, 0, sizeof(struct prng));
}
close(fd);
printf("Summary: \n");
printf("\tSuccess: %d\n", totalSuccess);
printf("\tFailed: %d\n", totalFailed);
}
static void stats_module(){
struct prng *s_prng = {0};
int status = 0;
int fd;
if ((fd = open("stats_stm32", O_CREAT | O_TRUNC | O_RDWR, 00760)) < 0){
printf("Failed to open the file\n");
perror("open()");
exit(-1);
}
for (size_t i = 0; i < 100; i++){
status = send_uart(&s_prng);
//printf("%d %d %llu %llu\n", s_prng->p, s_prng->q, s_prng->seed, s_prng->output);
char str[32];
memset(str, 0, 32);
snprintf(str, 32, "%llu", s_prng->output);
write(fd, str, strlen(str));
write(fd, "\n", 1);
}
close(fd);
}
int main(int argc, char *argv[]){
if (argc < 2){
printf("Please, specify the module to use: bbs or stats\n");
return -1;
}
if (strncmp(argv[1], "bbs", 5) == 0){
bbs_module();
}
else if (strncmp(argv[1], "stats", 5) == 0){
stats_module();
}
return 0;
}
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env python3
from math import erfc, sqrt
def monobit_test(bitseq: str):
"""
Frequency (Monobit) Test for a binary sequence. This tests count the number of '1' and '0' in a bit sequence and make a test statistics
This test is based on the NIST SP 800-22 document, that describe how to perform tests for PRNG algorithms:
https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-22r1a.pdf
Returns:
p_value (float): larger p-values suggest consistency with randomness.
"""
n = len(bitseq)
if n == 0:
raise ValueError("bitseq must not be empty")
if any(c not in "01" for c in bitseq):
raise ValueError("bitseq must contain only '0' and '1'")
# Count ones and zeros via +/-1 sum
s = sum(1 if c == "1" else -1 for c in bitseq)
# Compute the test statistic
sobs = abs(s) / sqrt(n)
# Compute p-value, based on the Complementary Error Function (erfc)
p_value = erfc(sobs / sqrt(2))
return p_value
+2500
View File
File diff suppressed because it is too large Load Diff
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env python3
from argparse import ArgumentParser
from monobit_test import monobit_test
import matplotlib.pyplot as plt
from math import ceil
parser = ArgumentParser(description="Stats")
parser.add_argument('-r', '--random', help='Random tests file')
args = parser.parse_args()
if args.random is None:
print("You must specify the random test file")
exit(-1)
data = None
with open(args.random, "r") as f:
data = f.readlines()
x = list()
y = list()
i = 0
totals = 0
totalsAverage = dict()
for entry in data:
rand = int(entry.replace("\n", ""))
stats = monobit_test(bin(rand)[2:])
totals += 1
# Je recupere juste le la value 0.x et je fais une moyenne
pvalue = str(stats)[0:3]
print(f"{rand}: {stats}: {pvalue}")
if pvalue not in totalsAverage:
totalsAverage[pvalue] = 0
totalsAverage[pvalue] += 1
y.append(stats) # Get the maximum value
x.append(i)
i += 1
plt.figure(figsize=(10, 6))
plt.bar(x, y, color='b')
plt.legend()
plt.show()
x = list()
y = list()
for entry in totalsAverage:
print(f"{entry}: {totalsAverage[entry]}")
x.append(entry)
y.append(totalsAverage[entry])
plt.figure(figsize=(10, 6))
plt.bar(x, y, color='b')
plt.legend()
plt.show()
Executable
+100
View File
@@ -0,0 +1,100 @@
7143956609604881876
6340670099509582644
4333063528847840840
5448018992326244964
15481972836083048938
3934379957052359253
13152513937849694277
2356684764018913277
10058073522818051299
15962996786604220673
3942988100900722377
10934163235194474014
6599067683569711565
7600599936755187680
2405724269070210974
11933146282488597358
17258108528392989763
12351616828616339343
7704667635734705225
16062004988962659328
15732156458016953228
14216936927168641841
807742483240682402
5475393661225397918
2470077164568330899
2964143963273089349
14050280231004325874
4794409721138831186
5910878502533703035
2891170948527933857
16676943507448926252
15462900432179282703
15507435142494667442
1677813438968503920
9609228843553996341
213089384859731146
162552557704144544
17597685084860323452
9354024014538640154
10077682396898715931
1521103123871795714
14552281874167193074
7283173614658258684
1919461955721824711
8144830301161275821
5855722041235443106
5627126812385231187
5265259268987312118
13492757238726588169
1815285119994321873
2052410304797613645
12319629048524816380
10214415561913379519
12055736959121855087
4582950055558425767
9620899185974271789
14305339244738711898
1332066268470078589
16454992780571219535
15994724435223301341
17693254104230191035
15179585275573828959
17953669566852115206
4850685134783252795
5237775842428082632
14605220744584287293
17843194877515927408
7145744655039698832
6202054781425764022
11162432947491746585
17870660189937233770
11846030029933436476
17502604038329397571
12900957045976627210
2229699146690248944
14464066371164287761
15434304277948242038
9948953088560674393
18173717715545186381
1961227897653913140
12873961365795314954
348868410274517725
3542539594548864311
6226010854009674672
3970283356438754992
8882086061509035049
12550402613932570435
6339289237626352931
5101542075764696572
1928582022423371495
17470386898714041417
2164929531054351313
1781755032125269242
9577013602259270449
1097648098100462529
1688066412708239185
11765217448167006791
2982376079644557045
10305427686653677079
786171841716133178
+162
View File
@@ -0,0 +1,162 @@
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include "test_bbs.h"
static int gcd(unsigned long a, unsigned long b){
if (b == 0)
return a;
return gcd(b, a % b);
}
static int isPrimeNumber(unsigned int x){
for (int i = 0; i < SIEVES_LEN; i++){
if (x % sieves[i] == 0)
return 0;
}
return 1;
}
/*
* This function check if the prime number x is congruent 3 modulo 4
*/
static int isCongruent(unsigned int x){
int res = x % 4;
if (res != 3)
return res;
return -1;
}
/*
* This function convert a bit sequences store in the char * to unsigned long long
*/
static unsigned long long bitToUl(char *bits){
unsigned long long o = 0;
for (int i = 0; i < strlen(bits); i++)
o = (o << 1) + bits[i] - '0';
return o;
}
/*
* This function write to the report file
*/
static void writeToReport(int fd, const char *buf, ...){
char str[BUF_FILE];
va_list va;
va_start(va, buf);
//snprintf(str, BUF_FILE, buf, va);
vsnprintf(str, BUF_FILE, buf, va);
write(fd, str, strlen(str));
va_end(va);
}
/*
* This function test the BBS algorithm received from the STM32 board
* Return 0 if succeed otherwise return -1
*/
int test_bbs(int fd, unsigned int p, unsigned int q, unsigned long long seed, unsigned long long g){
int res = 0;
/*
* Check if p and q are prime numbers
*/
writeToReport(fd, "Testing p (%d)\n", p);
res = isPrimeNumber(p);
if (!res){
writeToReport(fd, "p is not a prime number. The has failed.\n");
return -1;
}
writeToReport(fd, "p is a prime number. The test has succeeded.\n\n", q);
writeToReport(fd, "Testing q (%d)\n", q);
res = isPrimeNumber(q);
if (!res){
writeToReport(fd, "q is not a prime number. The has failed.\n");
return -1;
}
writeToReport(fd, "q is a prime number. The test has succeeded.\n\n", q);
// Check if is congruent 3 modulo 4
writeToReport(fd, "Testing p congruent 3 modulo 4:\n");
res = isCongruent(p);
if (res >= 0){
writeToReport(
fd,
"p is not congruent 3 modulo 4, but congruent %d. The test has failed.\n",
res
);
return -1;
}
writeToReport(
fd,
"p is congruent 3 modulo 4. The test has succeeded.\n\n"
);
writeToReport(fd, "Testing q congruent 3 modulo 4:\n");
res = isCongruent(q);
if (res >= 0){
writeToReport(fd,
"q is not congruent 3 modulo 4, but congruent %d. The test has failed.\n",
res
);
return -1;
}
writeToReport(fd, "q is congruent 3 modulo 4. The test has succeeded.\n\n");
// Check if n is correct
unsigned long long n = (unsigned long long)p * (unsigned long long)q;
writeToReport(fd, "n: %llu\n", n);
// Check if seed is in the range 1 < seed < n - 1
writeToReport(fd, "Testing seed:\n");
if (seed < 1 || seed > n - 1){
writeToReport(
fd,
"Seed (%llu) is not in the range 1 < seed < n - 1. "
"The test has failed\n",
seed
);
return -1;
}
writeToReport(fd, "The seed test has passed.\n\n");
// Check if seed satisfy the equation: gcd(seed, n) = 1
writeToReport(fd, "Testing gcd(seed, n) = 1:\n");
int res_gcd = gcd(seed, n);
if (res_gcd != 1){
writeToReport(
fd,
"the result of the gcd(seed, n) = %d. "
"The test has failed.\n",
res_gcd
);
return -1;
}
writeToReport(fd, "gcd (seed, n) = %d. The has passed.\n\n", res_gcd);
// Check least bit significant
unsigned long long tmp = (seed * seed) % n;
char bits[ITER_BBS];
memset(bits, 0, ITER_BBS);
int pos = 0;
for (size_t i = 1; i < ITER_BBS; i++){
unsigned long long x = (tmp * tmp) % n;
bits[pos++] = (x & 1) + '0';
tmp = x;
}
/* We convert the bit sequence to unsigned long long */
unsigned long long output = bitToUl(bits);
if (output != g){
writeToReport(fd, "The random generated has failed.\n");
return -1;
}
writeToReport(fd, "Random number: %llu\n", g);
writeToReport(fd, "All tests has passed with success, the BBS algorithm works.\n\n");
return 0;
}
+49
View File
@@ -0,0 +1,49 @@
#ifndef H_TEST_BBS
#define H_TEST_BBS
#include <string.h>
#include <stdarg.h>
#define SIEVES_LEN 430
#define ITER_BBS 100
#define BUF_FILE 192
static int gcd(unsigned long, unsigned long);
static int isPrimeNumber(unsigned int);
static int isCongruent(unsigned int);
static int testGCD(unsigned long long, unsigned long long);
static unsigned long long bitToUl(char *);
static void writeToReport(int fd, const char *buf, ...);
int test_bbs(int, unsigned int, unsigned int, unsigned long long, unsigned long long);
static int sieves[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,
103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181,
191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277,
281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383,
389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487,
491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709,
719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827,
829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947,
953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051,
1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163,
1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279,
1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399,
1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489,
1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601,
1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709,
1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831,
1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951,
1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069,
2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179,
2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297,
2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399,
2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543,
2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671,
2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753,
2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879,
2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999};
#endif
+88
View File
@@ -0,0 +1,88 @@
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <termios.h>
#include "common.h"
int set_serial_device(int fd){
struct termios serial_cnf;
if (tcgetattr(fd, &serial_cnf) < 0){
printf("It's a TTY device\n");
close(fd);
return -1;
}
cfsetispeed(&serial_cnf, B115200);
cfsetospeed(&serial_cnf, B115200);
serial_cnf.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
serial_cnf.c_iflag &= ~(IXON | IXOFF | IXANY); // Disable software flow control
serial_cnf.c_iflag &= ~(INLCR | ICRNL | IGNCR);
serial_cnf.c_cflag &= ~CRTSCTS; // Disable hardware control
serial_cnf.c_cflag |= CREAD | CLOCAL;
/* Set 8N1 (8 bits, no parity, 1 stop bit) */
serial_cnf.c_cflag &= ~PARENB; // No parity
serial_cnf.c_cflag &= ~CSTOPB; // 1 stop bit
serial_cnf.c_cflag &= ~CSIZE; // clear data
serial_cnf.c_cflag |= CS8; // 8 data bits
serial_cnf.c_oflag &= ~OPOST; // Disable output processing
serial_cnf.c_cc[VMIN] = 1;
serial_cnf.c_cc[VTIME] = 0;
tcflush(fd, TCIFLUSH);
if (tcsetattr(fd, TCSANOW/*TCSAFLUSH*/, &serial_cnf) < 0) {
printf("Failed to serial_cnfure the serial port\n");
close(fd);
return -1;
}
return 0;
}
static unsigned short csum(unsigned short *buf, int nwords) {
unsigned long sum = 0;
while (nwords > 0) {
sum += *buf++;
nwords--;
}
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
return (unsigned short)(~sum);
}
int send_uart(struct prng **s_prng){
int fd;
if ((fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY)) < 0){
printf("Failed to read the device\n");
exit(-1);
}
set_serial_device(fd);
char buffer[sizeof(struct prng)];
u_int8_t cmd = 1;
//printf("Sending command...\n");
size_t len = write(fd, &cmd, 1);
//printf("Data sent: %ld\n\n", len);
// Read data
//printf("Receiving data...\n");
int total_len = 0;
while (total_len < sizeof(struct prng)){
len = read(fd, buffer + total_len, sizeof(struct prng));
//printf("Len recv: %ld\n", len);
total_len += len;
}
*s_prng = (struct prng *)buffer;
close(fd);
return 0;
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef H_UART
#define H_UART
#include "common.h"
int set_serial_device(int);
int send_uart(struct prng **);
#endif