Embedded Systems Project 2020
Mouzakitis Nikolaos TP4460
February 18, 2020
Contents
1 Code analysis 1
1.1 Simple scheme . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.1 Processor A90 . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.2 Processor A91 . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 SHA1 scheme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.1 Processor A90 . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.2 Processor A91 . . . . . . . . . . . . . . . . . . . . . . . . 9
1.3 SHA1-Blockchain scheme . . . . . . . . . . . . . . . . . . . . . . 13
1.3.1 Processor A90 . . . . . . . . . . . . . . . . . . . . . . . . 13
1.3.2 Processor A91 . . . . . . . . . . . . . . . . . . . . . . . . 17
2 Results with linear search 23
3 Theoretical question: Scaling the synchronization into more
than 2 processors 24
3.1 Two processors require access for different purpose each . . . . . 24
3.2 Two processors contribute together into a single authentication
access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1
Abstract
Code of the project is explained, as well as a graph is presented, comparing the
three different versions used for getting access after entering password. First
one is the simple one without any cryptography, second one is the version with
SHA-1 and the last one is the one using blockchain.
A small not for the code; in all of the 3 scheme the DCache is disabled and
this was done, because code wouldn’t run, and when core A90 change a variable
and could print the right value, in the same time core A91 always print the
wrong value(old one).
1Code analysis
1.1 Simple scheme
In the simple scheme, A90 places the password given by the user in the buffer0,
and then changes the shared variable a0 to signal A91 to do the authentication.
1.1.1 Processor A90
"a90.c"
#include "xparameters.h"
#include "xgpio.h"
#include "xscutimer.h"
#include <sleep.h>
#include <xil_cache.h>
#include "ZedboardOLED.h"
#include <stdio.h>
XScuTimer Timer;
void writeBuf(unsigned char *buf0, char *s, uint8_t len)
{
for(int i = 0; i < len; i++)
buf0[i] = s[i];
return ;
}
void readBuf(unsigned char *dest, unsigned char *s, uint8_t len)
{
for(int i=0; i < len; i++)
dest[i] = s[i];
return;
}
void printBuf(unsigned char *buf, uint8_t len) {
for(int i = 0; i < len; i++)
xil_printf("%c", buf[i]);
xil_printf("n");
}
int main (void)
1
{
unsigned char tmpbuf[16];
unsigned int Status, newvalue, this;
unsigned int * a0 = (unsigned int *) 0x1BF00000;
unsigned int * a1 = (unsigned int *) 0x1BF00008;
unsigned char *buffer0 = ( unsigned char *)0x1BF01000;
unsigned char *buffer1 = ( unsigned char *) 0x1BF01030;
*a0 = 0;
*a1 = 0;
Xil_DCacheDisable();
xil_printf("-- Start of the Program --rn");
xil_printf("a0 : %d a1: %d rn", *a0, *a1);
//xil_printf("%x a %x b rn", a0, a1);
usleep(400);
// PS Timer related definitions
XScuTimer_Config *ConfigPtr;
XScuTimer *TimerInstancePtr = &Timer;
// Initialize the timer
ConfigPtr = XScuTimer_LookupConfig (XPAR_PS7_SCUTIMER_0_DEVICE_ID);
Status = XScuTimer_CfgInitialize
(TimerInstancePtr, ConfigPtr, ConfigPtr->BaseAddr);
if(Status != XST_SUCCESS){
xil_printf("Timer init() failedrn");
return XST_FAILURE;
}
///XScuTimer_LoadTimer(TimerInstancePtr, 32500000);
XScuTimer_LoadTimer(TimerInstancePtr, 4000000000);
// Set AutoLoad mode
XScuTimer_EnableAutoReload(TimerInstancePtr);
xil_printf("Enter your password please: ");
char userinput[16];
scanf("%s",userinput);
writeBuf( buffer0, userinput,16);
//writeBuf( buffer0, "0123456789abcdef",16);
xil_printf("-- Written buffer0 rn");
readBuf(tmpbuf, userinput, 16);
//readBuf(tmpbuf, buffer0, 16);
printBuf(tmpbuf,16);
*a0 = 1; //changing the value of shared variable.
// Start the timer
XScuTimer_Start (TimerInstancePtr);
while( (*a1 != 1) ) {
2
usleep(500);
}
XScuTimer_Stop(TimerInstancePtr);
newvalue = XScuTimer_GetCounterValue(TimerInstancePtr);
this = 4000000000 - newvalue;
xil_printf("Cycles counted: %d for reply.rn", this);
*a1 = 0;
*a0 = 0;
readBuf(tmpbuf, buffer1, 8);
xil_printf("Status : rn");
printBuf(tmpbuf, 8);
return 0;
}
After including all the required libraries for each function used, a Timer is
created that will help to calculate the machine cycles.
Function writeBuf writes a character array within another, something like
string copy from the C library with given lenght(like strncpy).
Function printBuf prints a string, one character at a time for a given lenght.
In the code, we do disable the DCache(had various problems to synchronize the
2 processors;tried Invalidating and Flushing, but in the end to get the meassur-
ments, it became disabled.)
Values a0, a1 are used to synchronize the actions between the 2 proces-
sors(A90,A91) and are shared among them. Buffer0 and buffer1 are also shared
between the 2 processors and the first one is used for the input to A91 while
the second one holds the output. Output is a simple character array ’accepted’
or ’declined’.
Next the configuration of the Scu timer takes place. Timer is loaded with
value 4000000000 that is close enough to the largest 32-bit value that it can
hold to avoid underflows in the meassurment process.
User enters the 16 character password, and that is written in buffer0. Chang-
ing the value a0 to 1, so the A91 processor which is polling the variable can start
working on the authentication. Timer starts counting, while the processor(A90)
polls now the shared variable a1.
When (A91) changes the variable to 1, A90 stops the timer and counts the
cycles spent and prints them to the debug terminal.
1.1.2 Processor A91
"a91.c"
#include "xparameters.h"
#include "xgpio.h"
#include <sleep.h>
#include "xscutimer.h"
#include <xil_cache.h>
#include "ZedboardOLED.h"
3
#include <string.h>
#include <stdio.h>
#define ACCEPT "accepted"
#define DECLINE "declined"
XScuTimer Timer; /* Cortex A9 SCU Private Timer Instance */
#define USERS 1024
unsigned char passwords[USERS][16];
void writeBuf(unsigned char *buf0, char *s, uint8_t len)
{
for(int i = 0; i < len; i++)
buf0[i] = s[i];
return ;
}
void readBuf(unsigned char *dest, unsigned char *s, uint8_t len)
{
for(int i=0; i < len; i++)
dest[i] = s[i];
//return;
}
void printBuf(unsigned char *buf, uint8_t len) {
for(int i = 0; i < len; i++)
xil_printf("%c", buf[i]);
xil_printf("n");
}
int matches(unsigned char *in) {
for( int i = 0; i < USERS; i++){
//xil_printf("Testing: %drn", i);
if( strncmp( (const char *)in, (const char *) passwords[i], 16) ==
0)
return i+1;
}
return 0;
}
int main (void)
{
///Xil_DCacheInvalidate();
Xil_DCacheDisable();
4
// passwords stored.
clear_OLED(); // clear the OLED
print_message("Enter password:",1);
volatile unsigned int * a0 = (unsigned int *) 0x1BF00000;
volatile unsigned int * a1 = (unsigned int *) 0x1BF00008;
volatile unsigned char *buffer0 = ( unsigned char *) 0x1BF01000;
volatile unsigned char *buffer1 = ( unsigned char *) 0x1BF01030;
char thesi[4];
*a0 = 0;
char snum[5];
char tnum[4];
for(int i = 0; i < USERS; i++) {
strcpy(passwords[i], "abcdefghabcdefgh");
memcpy(snum, "00000", 5);
memcpy(tnum, "0000", 4);
sprintf(snum, "%4d",i);
sprintf(tnum, "%d",i);
int len = strlen(tnum);
if(len!=4)
sprintf(passwords[i], "%s", snum);
else
sprintf(passwords[i], "%s", tnum);
if(len == 1) {
passwords[i][0] = ’0’;
passwords[i][1] = ’0’;
passwords[i][2] = ’0’;
} else if(len == 2) {
passwords[i][0] = ’0’;
passwords[i][1] = ’0’;
} else if(len == 3)
passwords[i][0] = ’0’;
else if(len == 4)
passwords[i][0] = ’1’;
passwords[i][4] = ’a’;
//for(int j = 0; j < 16; j++)
// xil_printf("%c",passwords[i][j]);
// xil_printf("nr");
}
xil_printf("Passwds generatednr");
memcpy(thesi, 32, 4); // in a non printable char.
usleep(1000000);
5
xil_printf("-- Start of the Program --rn");
xil_printf("a0 : %d a1: %d rn", *a0, *a1);
//xil_printf("%x a %x b rn", a0, a1);
unsigned char input[16];
xil_printf("nWaiting to read buffer0rn");
///Xil_DCacheInvalidate();
while( (*a0) != 1) {
;
//xil_printf("a0 : %drn", *a0);
//xil_printf("a1 : %drn", *a1);
//xil_printf("wait..rn");
///Xil_DCacheInvalidate();
//Xil_DCacheInvalidate();
//sleep(1);
}
readBuf(input, buffer0 , 16);
//xil_printf("Read the buffer0 rn");
//printBuf(input, 16);
int ret = matches(input);
xil_printf("ret value: %drn",ret);
clear_OLED();
if( ret != 0) {
xil_printf("Accept authorization. rn");
print_message("Access Granted",1);
sprintf(thesi, "%4d",ret);
for(int j = 0; j < 4; j++)
print_char(thesi[j],2,j);
writeBuf(buffer1, ACCEPT, strlen(ACCEPT));
}else {
xil_printf("Decline authorization. rn");
print_message("Access Declined",1);
writeBuf(buffer1, DECLINE, strlen(DECLINE));
}
*a1 = 1;
///Xil_DCacheFlush();
return 0 ;
}
The code for the A91 processor also includes the specific header files needed.
Defines the number of users as well as the output character arrays.
In the first loop of the main(), we have a part of the code that will create
passwords of the form "xxxxafghabcdefgh" where xxxx will be the number of
the element in the array(f.e 9 will be "0009afghabcdefgh" while 1013 will be
stored as password "1013afghabcdefgh) ; to avoid writing big arrays and though
increasing the text size of the application. Also the array called passwords
stores the valid passwords that will be accepted. Function readBuf copies into
the first argument pointer len number of bytes from the character array which
starts at the pointer argument ’s’.
Funtion matches search linear throught the password’s array and compares
6
the input given by the user to each one of the elemnts of the array. It does
return the position found since we need to print that possition on the screen.
In the main(), again DCache is disabled, and the OLED screen is cleared.
Then the prompt "Enter password:" appears on the on-board screen.
input array will hold the input given by the user and copied from the buffer0,
where A90 processor will store the user’s input.
The processor then starts polling the a0 variable. When it becomes 1, is
copying the buffer0 to the input. and calls the function matches. On board
screen is cleared and based in the return value of the previously called function
will write "Access Granted" and will print the possition found or it will print
"Access Declined".
1.2 SHA1 scheme
In the SHA1 scheme, A91 core, do not compare the input with the users raw
password, but it precalculates the 20-bytes SHA1 on each valid password and
then compares the input fetched from buffer0 to the SHA1-encrypted array. In
A90 core now, after getting user’s input, the encryption is created and placed
into the buffer0.
1.2.1 Processor A90
"a90sha1.c"
#include "xparameters.h"
#include "xgpio.h"
#include "xscutimer.h"
#include <sleep.h>
#include <xil_cache.h>
#include "ZedboardOLED.h"
#include <stdio.h>
#include "sha1.h"
XScuTimer Timer; /* Cortex A9 SCU Private Timer Instance */
void writeBuf(unsigned char *buf0, char *s, uint8_t len)
{
for(int i = 0; i < len; i++)
buf0[i] = s[i];
return ;
}
void readBuf(unsigned char *dest, unsigned char *s, uint8_t len)
{
for(int i=0; i < len; i++)
dest[i] = s[i];
return;
}
void printBuf(unsigned char *buf, uint8_t len) {
for(int i = 0; i < len; i++)
xil_printf("%x ", buf[i]);
xil_printf("n");
}
7
int main (void)
{
unsigned char tmpbuf[16];
unsigned char encrypted[SHA1_BLOCK_SIZE];
unsigned int Status, newvalue, this;
unsigned int * a0 = (unsigned int *) 0x1BF00000;
unsigned int * a1 = (unsigned int *) 0x1BF00008;
unsigned char *buffer0 = ( unsigned char *) 0x1BF01000;
unsigned char *buffer1 = ( unsigned char *) 0x1BF01030;
*a0 = 0;
//Xil_DCacheFlush();
Xil_DCacheDisable();
Xil_ICacheDisable();
xil_printf("-- Start of the Program --rn");
xil_printf("a0 : %d a1: %d rn", *a0, *a1);
//xil_printf("%x a %x b rn", a0, a1);
//usleep(400);
// PS Timer related definitions
XScuTimer_Config *ConfigPtr;
XScuTimer *TimerInstancePtr = &Timer;
// Initialize the timer
ConfigPtr = XScuTimer_LookupConfig (XPAR_PS7_SCUTIMER_0_DEVICE_ID);
Status = XScuTimer_CfgInitialize (TimerInstancePtr, ConfigPtr,
ConfigPtr->BaseAddr);
if(Status != XST_SUCCESS){
xil_printf("Timer init() failedrn");
return XST_FAILURE;
}
XScuTimer_LoadTimer(TimerInstancePtr, 4000000000);
// Set AutoLoad mode
XScuTimer_EnableAutoReload(TimerInstancePtr);
xil_printf("Enter your password please: ");
char userinput[16];
scanf("%s",userinput);
SHA1_CTX ctx;
sha1_init(&ctx);
sha1_update(&ctx, userinput, 16);
sha1_final(&ctx, encrypted);
writeBuf( buffer0, encrypted,SHA1_BLOCK_SIZE);
//writeBuf( buffer0, "0123456789abcdef",16);
xil_printf("-- Written buffer0 rn");
readBuf(tmpbuf, encrypted, SHA1_BLOCK_SIZE);
//readBuf(tmpbuf, buffer0, 16);
printBuf(tmpbuf,SHA1_BLOCK_SIZE);
*a0 = 1; //changing the value of shared variable.
8
//Xil_DCacheFlush();
// Start the timer
XScuTimer_Start (TimerInstancePtr);
while( (*a1 != 1) ) {
// Xil_DCacheInvalidate();
usleep(500);
}
XScuTimer_Stop(TimerInstancePtr);
newvalue = XScuTimer_GetCounterValue(TimerInstancePtr);
this = 4000000000 - newvalue;
xil_printf("Cycles counted: %d for reply.rn", this);
*a1 = 0;
*a0 = 0;
//Xil_DCacheFlush();
//Xil_DCacheInvalidate();
readBuf(tmpbuf, buffer1, 8);
xil_printf("Status : rn");
printBuf(tmpbuf, 8);
return 0;
}
In the processor A90’s code, there are not many differences than the previous
one. All needed libraries are included, and the shared memory addresses remain
the same.
One is the encrypted array which will hold the encryption under SHA-1 of
the user’s input. The output will be 20 bytes long as we can see by inspecting
the sha1.c code provided. SHA1 process take place in lines[68-72] and from the
16-bit user input we end up with a 20 byte long encrypted hash.
The rest remains as in the previous simple scheme. DCache and ICache are
also disabled in this scheme as well. The main difference from the previous
scheme is that in this scheme, A90 processor do not share with the A91 the
users input but the SHA1 applied on that input.
1.2.2 Processor A91
"a91sha1.c"
#include "xparameters.h"
#include "xgpio.h"
#include <sleep.h>
#include "xscutimer.h"
#include <xil_cache.h>
#include "ZedboardOLED.h"
#include <string.h>
#include <stdio.h>
9
#include "sha1.h"
#define ACCEPT "accepted"
#define DECLINE "declined"
XScuTimer Timer; /* Cortex A9 SCU Private Timer Instance */
#define USERS 1024
unsigned char passwords[USERS][16];
unsigned char encrypted[USERS][SHA1_BLOCK_SIZE]; // storing the sha1 of
each password.
void fill_encrypted(void)
{
xil_printf("i am here1n");
for(int i = 0; i < USERS; i++) {
SHA1_CTX ctx;
sha1_init(&ctx);
sha1_update(&ctx, passwords[i], 16);
sha1_final(&ctx, encrypted[i]);
/*
xil_printf("SHA1[");
for( int j = 0; j < 16; j++) {
xil_printf("%c",passwords[i][j]);
}
xil_printf("] = ");
for(int w = 0; w < SHA1_BLOCK_SIZE; w++)
xil_printf("%4x", encrypted[i][w]);
xil_printf("n");
*/
}
xil_printf("i am here2n");
}
void writeBuf(unsigned char *buf0, char *s, uint8_t len)
{
for(int i = 0; i < len; i++)
buf0[i] = s[i];
return ;
}
void readBuf(unsigned char *dest, unsigned char *s, uint8_t len)
{
for(int i=0; i < len; i++)
dest[i] = s[i];
return;
}
void printBuf(unsigned char *buf, uint8_t len) {
for(int i = 0; i < len; i++)
xil_printf("%x ", buf[i]);
xil_printf("n");
10
}
int matches(unsigned char *in) {
for( int i = 0; i < USERS; i++){
//xil_printf("Testing: %drn", i);
if( strncmp( (const char *)in, (const char *) encrypted[i],
SHA1_BLOCK_SIZE) == 0)
return i+1;
}
return 0;
}
int main (void)
{
xil_printf("-- Start of the Program --rn");
char snum[5];
char tnum[4];
for(int i = 0; i < USERS; i++) {
strcpy(passwords[i], "abcdefghabcdefgh");
memcpy(snum, "00000", 5);
memcpy(tnum, "0000", 4);
sprintf(snum, "%4d",i);
sprintf(tnum, "%d",i);
int len = strlen(tnum);
if(len!=4)
sprintf(passwords[i], "%s", snum);
else
sprintf(passwords[i], "%s", tnum);
if(len == 1) {
passwords[i][0] = ’0’;
passwords[i][1] = ’0’;
passwords[i][2] = ’0’;
} else if(len == 2) {
passwords[i][0] = ’0’;
passwords[i][1] = ’0’;
} else if(len == 3)
passwords[i][0] = ’0’;
else if(len == 4)
passwords[i][0] = ’1’;
passwords[i][4] = ’a’;
//for(int j = 0; j < 16; j++)
// xil_printf("%c",passwords[i][j]);
// xil_printf("nr");
}
xil_printf("Passwds generatednr");
11
fill_encrypted();
//Xil_DCacheInvalidate();
Xil_DCacheDisable();
Xil_ICacheDisable();
clear_OLED(); // clear the OLED
print_message("Enter password2:",1);
unsigned int * a0 = (unsigned int *) 0x1BF00000;
unsigned int * a1 = (unsigned int *) 0x1BF00008;
unsigned char *buffer0 = ( unsigned char *) 0x1BF01000;
unsigned char *buffer1 = ( unsigned char *) 0x1BF01030;
char thesi[4];
*a0 = 0;
memcpy(thesi, 32, 4); // in a non printable char.
usleep(1000000);
xil_printf("-- Start of the Program --rn");
xil_printf("a0 : %d a1: %d rn", *a0, *a1);
//xil_printf("%x a %x b rn", a0, a1);
unsigned char input[16];
xil_printf("nWaiting to read buffer0rn");
//Xil_DCacheInvalidate();
while( (*a0) != 1) {
//xil_printf("a0 : %drn", *a0);
//xil_printf("a1 : %drn", *a1);
//xil_printf("wait..rn");
//Xil_DCacheInvalidate();
//Xil_DCacheInvalidate();
//sleep(1);
}
readBuf(input, buffer0 , 20);
xil_printf("Read the buffer0 rn");
printBuf(input, 20);
int ret = matches(input);
xil_printf("ret value: %drn",ret);
clear_OLED();
if( ret != 0) {
xil_printf("Accept authorization. rn");
print_message("Access Granted",1);
sprintf(thesi, "%4d",ret);
for(int j = 0; j < 4; j++)
print_char(thesi[j],2,j);
writeBuf(buffer1, ACCEPT, strlen(ACCEPT));
}else {
xil_printf("Decline authorization. rn");
print_message("Access Declined",1);
writeBuf(buffer1, DECLINE, strlen(DECLINE));
}
12
*a1 = 1;
//Xil_DCacheFlush();
return 0 ;
}
As for the code on the A91 processor for the SHA1 scheme, the main differ-
ence is the existance of encrypted array, that has length same with the number
of the valid users.
Function fill_encrypted traverses througth the passwords array and cre-
ated the SHA1 hash of each one, storing it on the encrypted array.
Function matches in this code, search again in a linear way, througth en-
crypted array this time and compares the shared hash from A90 to each one
stored into the matrix.
There is not many to explain in the main() that are different from the simple
scheme described in the previous section, expept that fill_encrypted is called
at first to initiate and create the hashes of the passwords; to be ready for the
comparison latter on.
1.3 SHA1-Blockchain scheme
In the last scheme, processor A90, provides three inputs to the A91 core each
time. The first one is the encrypted(SHA1) password that the user entered.
The other two are the cycles counted from the last success log-in, as well as the
hash of the hashed password incremented by the cycles time provided as the
second argument.
Of course in the first log-in attempt, cycles counted are zero.
When A91 gets the signal, fetches the encrypted password, will check it
against to its encypted passwords and in anycase will call the function fill_blockchain
to save the new calculations for each element in the matrix. Afterwards in func-
tion matches ; if encrypted password passes the test, the blockchain array will
also be tested before accepting and authenticating the request.
1.3.1 Processor A90
"a90sha1_blockchain.c"
#include "xparameters.h"
#include "xgpio.h"
#include "xscutimer.h"
#include <sleep.h>
#include <xil_cache.h>
#include "ZedboardOLED.h"
#include <stdio.h>
#include "sha1.h"
XScuTimer Timer; /* Cortex A9 SCU Private Timer Instance */
void writeBuf(unsigned char *buf0, char *s, uint8_t len)
{
for(int i = 0; i < len; i++)
buf0[i] = s[i];
13
return ;
}
void readBuf(unsigned char *dest, unsigned char *s, uint8_t len)
{
for(int i=0; i < len; i++)
dest[i] = s[i];
return;
}
void printBuf(unsigned char *buf, uint8_t len) {
for(int i = 0; i < len; i++)
xil_printf("%x ", buf[i]);
xil_printf("n");
}
int main (void)
{
unsigned char tmpbuf[16];
unsigned char encrypted[SHA1_BLOCK_SIZE];
unsigned char hashed_block_array[SHA1_BLOCK_SIZE];
unsigned int Status, newvalue, this, test_this;
unsigned int * a0 = (unsigned int *) 0x1BF00000;
unsigned int * a1 = (unsigned int *) 0x1BF00008;
unsigned char *buffer0 = ( unsigned char *) 0x1BF01000;
unsigned char *buffer1 = ( unsigned char *) 0x1BF01030;
unsigned int *time_i = (unsigned int *) 0x1BF01050;
unsigned char *hashed_block = (unsigned char *) 0x1BF01070;
int turn = 0;
this = 0; // just to be sure in case of first failed attempt,
// wont take any random value as time_i.
Xil_DCacheDisable();
while(1) {
*a0 = 0;
//Xil_DCacheFlush();
xil_printf("-- Start of the Program --rn");
xil_printf("a0 : %d a1: %d rn", *a0, *a1);
//xil_printf("%x a %x b rn", a0, a1);
//usleep(400);
// PS Timer related definitions
XScuTimer_Config *ConfigPtr;
XScuTimer *TimerInstancePtr = &Timer;
// Initialize the timer
ConfigPtr = XScuTimer_LookupConfig (XPAR_PS7_SCUTIMER_0_DEVICE_ID);
Status = XScuTimer_CfgInitialize (TimerInstancePtr, ConfigPtr,
ConfigPtr->BaseAddr);
if(Status != XST_SUCCESS){
14
xil_printf("Timer init() failedrn");
return XST_FAILURE;
}
XScuTimer_LoadTimer(TimerInstancePtr, 4000000000);
// Set AutoLoad mode
XScuTimer_EnableAutoReload(TimerInstancePtr);
xil_printf("Enter your password please: ");
char userinput[16];
scanf("%s",userinput);
xil_printf("doing ctx init.rn ");
SHA1_CTX ctx;
sha1_init(&ctx);
sha1_update(&ctx, userinput, 16);
sha1_final(&ctx, encrypted);
xil_printf("doing ctx finished. rn");
// written encrypted on shared address.
writeBuf( buffer0, encrypted,SHA1_BLOCK_SIZE);
//writeBuf( buffer0, "0123456789abcdef",16);
xil_printf("-- Written buffer0 rn");
readBuf(tmpbuf, encrypted, SHA1_BLOCK_SIZE);
//readBuf(tmpbuf, buffer0, 16);
printBuf(tmpbuf,SHA1_BLOCK_SIZE);
if(turn == 0) {
xil_printf("turn 0rn");
*time_i = 0;
*hashed_block = 0;
} else {
xil_printf("turn with blockchainrn");
//written time_i on shared address.
*time_i = this;
for(int k = 0; k < SHA1_BLOCK_SIZE; k++)
hashed_block_array[k] = encrypted[k];
unsigned int *add_pointer = (unsigned int
*)&hashed_block_array[SHA1_BLOCK_SIZE-4];
*add_pointer = *add_pointer + this;
SHA1_CTX ctx2;
sha1_init(&ctx2);
sha1_update(&ctx2, hashed_block_array, 20);
sha1_final(&ctx2, encrypted);
//written the blockchain hash on shared address.
writeBuf( hashed_block, encrypted,SHA1_BLOCK_SIZE);
xil_printf("--written blockchain: time: %ldnr bchain: nr",
this);
readBuf(tmpbuf, hashed_block, SHA1_BLOCK_SIZE);
15
printBuf(tmpbuf,SHA1_BLOCK_SIZE);
xil_printf("--n’r");
}
*a0 = 1; //changing the value of shared variable.
//Xil_DCacheFlush();
// Start the timer
XScuTimer_Start (TimerInstancePtr);
while( (*a1 != 1) ) {
// Xil_DCacheInvalidate();
usleep(500);
}
XScuTimer_Stop(TimerInstancePtr);
newvalue = XScuTimer_GetCounterValue(TimerInstancePtr);
test_this = 4000000000 - newvalue;
xil_printf("Cycles counted: %d for reply.rn", test_this);
*a1 = 0;
*a0 = 0;
//Xil_DCacheFlush();
//Xil_DCacheInvalidate();
readBuf(tmpbuf, buffer1, 8);
xil_printf("Status : rn");
printBuf(tmpbuf, 8);
if( !strncmp(tmpbuf, "accepted", 8)) {
this = test_this;
xil_printf("keeping the timern");
} else {
xil_printf("declined, not keeping the timenr");
}
turn = 1;
}
return 0;
}
In main program, we disable data cache, and we go into an endless loop.
Instructions are like the previous schemes initializing all required things for the
scu_timer and getting input from the user. After, the SHA-1 encryption of the
input is stored into encrypted array, and written in buffer0 shared address so
A91 core can access it. If there is the first time running, time_i and hash_block
are having the values 0.
If not, we copy the encrypted password into the hashed_block_array and
then we assign an unsigned int pointer( uints have 4 bytes lenght in this
machine) to the 16th byte of the hashed_block_array.
This happens, to be able with the next instruction *add_pointer = *add_pointer
+ this; to be able to make the addition of the cycles meassured from previous
authentication to the hash.
In the end the whole result is again hashed one more time with SHA-1
16
algorithm and the 20 bytes output is stored into hashed_block shared address
with the A91 core. Then the value of the variable a0 is modified to signal the
A91 core. Timer starts to count the cycles and after polling the shared variable
a1 ; timer stops to take the meassurment. An extra test follows since we do not
intent keeping the values of the timer when there is not a succesful attempt. In
the end turn variable is used as a flag and always stays to 1. Is used to escape
the first part of the if statement which is only used on the first log-in.
1.3.2 Processor A91
"a91sha1_blockchain.c"
#include "xparameters.h"
#include "xgpio.h"
#include <sleep.h>
#include "xscutimer.h"
#include <xil_cache.h>
#include "ZedboardOLED.h"
#include <string.h>
#include <stdio.h>
#include "sha1.h"
#define ACCEPT "accepted"
#define DECLINE "declined"
//#define DEBUG_PRINT 1
XScuTimer Timer; /* Cortex A9 SCU Private Timer Instance */
unsigned int * a0 = (unsigned int *) 0x1BF00000;
unsigned int * a1 = (unsigned int *) 0x1BF00008;
unsigned char *buffer0 = ( unsigned char *) 0x1BF01000;
unsigned char *buffer1 = ( unsigned char *) 0x1BF01030;
unsigned int *time_i = (unsigned int *) 0x1BF01050;
unsigned char *hashed_block = (unsigned char *) 0x1BF01070;
int turn = 0;
#define USERS 1024
unsigned char passwords[USERS][16];
unsigned char encrypted[USERS][SHA1_BLOCK_SIZE]; // storing the sha1 of
each password.
unsigned char blockchain[USERS][SHA1_BLOCK_SIZE]; // storing the
blockchain_stuff(time_i hashed after added on the hased password)
unsigned char blockchain2[USERS][SHA1_BLOCK_SIZE];
// fill_encrypted: creates the hashes of the values that will be needed
to
// compare agaist the hash(value) of the given password.
void fill_encrypted(void)
{
for(int i = 0; i < USERS; i++) {
17
SHA1_CTX ctx;
sha1_init(&ctx);
sha1_update(&ctx, passwords[i], 16);
sha1_final(&ctx, encrypted[i]);
#ifdef DEBUG_PRINT
xil_printf("SHA1[");
for( int j = 0; j < 16; j++) {
xil_printf("%c",passwords[i][j]);
}
xil_printf("] = ");
for(int w = 0; w < SHA1_BLOCK_SIZE; w++)
xil_printf("%4x", encrypted[i][w]);
xil_printf("n");
#endif
}
}
// filling the array with hash( hash(password_i +time_i))
void fill_blockchain(void)
{
for(int i = 0; i < USERS; i++) {
//getting the hash(password) in each element.
//for(int k = 0; k < SHA1_BLOCK_SIZE; k++)
memcpy(blockchain[i], encrypted[i], 20);
//blockchain[i][0] = encrypted[k];
SHA1_CTX ctx;
sha1_init(&ctx);
// add time_i received from the shared memory.
//printBuf(blockchain[i],20);
unsigned int *add_pointer = (unsigned int
*)&blockchain[i][SHA1_BLOCK_SIZE-4];
*add_pointer = *add_pointer + (*time_i);
sha1_update(&ctx, blockchain[i], 20);
sha1_final(&ctx, blockchain[i]); // could work for blockchain
array also? i should look the code in sha1.c
#ifdef DEBUG_PRINT
xil_printf("BlockSHA1[");
for( int j = 0; j < 16; j++) {
xil_printf("%c",passwords[i][j]);
}
xil_printf("] = ");
18
for(int w = 0; w < SHA1_BLOCK_SIZE; w++)
xil_printf("%4x", blockchain[i][w]);
xil_printf("n");
#endif
}
}
void writeBuf(unsigned char *buf0, char *s, uint8_t len)
{
for(int i = 0; i < len; i++)
buf0[i] = s[i];
return ;
}
void readBuf(unsigned char *dest, unsigned char *s, uint8_t len)
{
for(int i=0; i < len; i++)
dest[i] = s[i];
return;
}
void printBuf(unsigned char *buf, uint8_t len) {
for(int i = 0; i < len; i++)
xil_printf("%x ", buf[i]);
xil_printf("n");
}
int matches(unsigned char *in) {
if(turn == 0) {
for( int i = 0; i < USERS; i++){
//xil_printf("Testing0: %drn", i);
//printBuf(encrypted[i],20);
if( strncmp( (const char *)in, (const char *) encrypted[i],
SHA1_BLOCK_SIZE) == 0)
return i+1;
}
} else {
for( int i = 0; i < USERS; i++){
//xil_printf("Testing1: %drn", i);
if( strncmp( (const char *)in, (const char *) encrypted[i],
SHA1_BLOCK_SIZE) == 0)
{
#ifdef DEBUG_PRINT
xil_printf("Passed first test--printing hashblockrn");
printBuf(hashed_block, 20);
xil_printf("Passed first test--printing blockchain[i]rn");
19
//printBuf(&blockchain[i], 20);
#endif
if( strncmp( (const char *)hashed_block, (const char *)
blockchain[i], SHA1_BLOCK_SIZE) == 0 )
return i+1;
else
break; //we assume we got great collision resistance.
}
}
}
return 0;
}
int main (void)
{
xil_printf("-- Start of the Program --rn");
//char * snum = "0000";
char snum[5];
char tnum[4];
for(int i = 0; i < USERS; i++) {
strcpy(passwords[i], "abcdefghabcdefgh");
memcpy(snum, "00000", 5);
memcpy(tnum, "0000", 4);
sprintf(snum, "%4d",i);
sprintf(tnum, "%d",i);
int len = strlen(tnum);
if(len!=4)
sprintf(passwords[i], "%s", snum);
else
sprintf(passwords[i], "%s", tnum);
if(len == 1) {
passwords[i][0] = ’0’;
passwords[i][1] = ’0’;
passwords[i][2] = ’0’;
} else if(len == 2) {
passwords[i][0] = ’0’;
passwords[i][1] = ’0’;
} else if(len == 3)
passwords[i][0] = ’0’;
else if(len == 4)
passwords[i][0] = ’1’;
passwords[i][4] = ’a’;
//for(int j = 0; j < 16; j++)
20
// xil_printf("%c",passwords[i][j]);
// xil_printf("nr");
}
xil_printf("Passwds generatednr");
Xil_DCacheDisable();
Xil_ICacheDisable();
while(1) {
fill_encrypted();
xil_printf("filled encrnr");
//Xil_DCacheInvalidate();
clear_OLED(); // clear the OLED
print_message("Enter password2:",1);
char thesi[4];
*a0 = 0;
memcpy(thesi, 32, 4); // in a non printable char.
usleep(1000000);
xil_printf("a0 : %d a1: %d rn", *a0, *a1);
//xil_printf("%x a %x b rn", a0, a1);
unsigned char input[16];
unsigned char input_block[20];
xil_printf("nWaiting to read buffer0rn");
//Xil_DCacheInvalidate();
while( (*a0) != 1) {
//xil_printf("a0 : %drn", *a0);
//xil_printf("a1 : %drn", *a1);
//xil_printf("wait..rn");
//Xil_DCacheInvalidate();
//Xil_DCacheInvalidate();
//sleep(1);
}
//xil_printf("out of sync looprn");
if(turn == 1) {
#ifdef DEBUG_PRINT
readBuf(input_block, hashed_block, 20);
xil_printf("Hashed block provided: rn");
printBuf(input_block, 20);
xil_printf("time_i received: %ldrn", *time_i);
#endif
fill_blockchain();
}
21
readBuf(input, buffer0 , 20);
//xil_printf("Read the buffer0 rn");
//printBuf(input, 20);
int ret = matches(input);
//xil_printf("ret value: %drn",ret);
clear_OLED();
if( ret != 0) {
xil_printf("Accept authorization. rn");
print_message("Access Granted",1);
sprintf(thesi, "%4d",ret);
for(int j = 0; j < 4; j++)
print_char(thesi[j],2,j);
writeBuf(buffer1, ACCEPT, strlen(ACCEPT));
}else {
xil_printf("Decline authorization. rn");
print_message("Access Declined",1);
writeBuf(buffer1, DECLINE, strlen(DECLINE));
}
*a1 = 1;
turn =1;
}
//Xil_DCacheFlush();
return 0 ;
}
22
2Results with linear search
It is important to define the way the results were obtained: for variable number
of users, the worst case in terms of machine cycles were meassured. Since the
algorithm searchs within the matrix to compare character arrays; the worst case
always is when the desired password lies last.
As one can observe, the SHA1/blockchain scheme has significant more over-
head than the 2 other schemes. As well that very quick the line related to the
SHA1, is increasing because in contrast to the simple scheme it doesn’t compare
16 bytes but 20 bytes each time, as the 20-byte output of SHA1.
Figure 2.1: Results meassured for the 3 different schemes of log in.
23
3Theoretical question: Scaling the synchronization
into more than 2 processors
In the event that there are more than two processors involved into the con-
structed scheme, we could separate different cases.
3.1 Two processors require access for different
purpose each
One case is when 2 or more cores require to get access with their password on
another processor’s resources.
According to the shared memory paradigm used in the above implemen-
tation, a system could be defined, where the processors(f.e A90,A91) get user
inputs and A93 has responsible to reply with ACCESS/DECLINE of their au-
thentication request. We could have shared variable a0,a1 that are accessed in
RoundRobin way by the processor A93; checking the variables this time and
not polling forever.
3.2 Two processors contribute together into a
single authentication access
Another case could be that in fact for the authentication to be complete more
than 1 cores need to contribute with their inputs. Using shared variables with
polling this time (till the A93 extracts both buffers as the inputs) and different
address locations for each buffer respective to the contirbuting to input processor
could solve the problem. For the reply, both(A90, A91) can poll the same
variable, and when detect that it has changed they can check for the result.
24

Embedded systemsproject_2020

  • 1.
    Embedded Systems Project2020 Mouzakitis Nikolaos TP4460 February 18, 2020
  • 2.
    Contents 1 Code analysis1 1.1 Simple scheme . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.1.1 Processor A90 . . . . . . . . . . . . . . . . . . . . . . . . 1 1.1.2 Processor A91 . . . . . . . . . . . . . . . . . . . . . . . . 3 1.2 SHA1 scheme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.2.1 Processor A90 . . . . . . . . . . . . . . . . . . . . . . . . 7 1.2.2 Processor A91 . . . . . . . . . . . . . . . . . . . . . . . . 9 1.3 SHA1-Blockchain scheme . . . . . . . . . . . . . . . . . . . . . . 13 1.3.1 Processor A90 . . . . . . . . . . . . . . . . . . . . . . . . 13 1.3.2 Processor A91 . . . . . . . . . . . . . . . . . . . . . . . . 17 2 Results with linear search 23 3 Theoretical question: Scaling the synchronization into more than 2 processors 24 3.1 Two processors require access for different purpose each . . . . . 24 3.2 Two processors contribute together into a single authentication access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 1
  • 3.
    Abstract Code of theproject is explained, as well as a graph is presented, comparing the three different versions used for getting access after entering password. First one is the simple one without any cryptography, second one is the version with SHA-1 and the last one is the one using blockchain. A small not for the code; in all of the 3 scheme the DCache is disabled and this was done, because code wouldn’t run, and when core A90 change a variable and could print the right value, in the same time core A91 always print the wrong value(old one).
  • 4.
    1Code analysis 1.1 Simplescheme In the simple scheme, A90 places the password given by the user in the buffer0, and then changes the shared variable a0 to signal A91 to do the authentication. 1.1.1 Processor A90 "a90.c" #include "xparameters.h" #include "xgpio.h" #include "xscutimer.h" #include <sleep.h> #include <xil_cache.h> #include "ZedboardOLED.h" #include <stdio.h> XScuTimer Timer; void writeBuf(unsigned char *buf0, char *s, uint8_t len) { for(int i = 0; i < len; i++) buf0[i] = s[i]; return ; } void readBuf(unsigned char *dest, unsigned char *s, uint8_t len) { for(int i=0; i < len; i++) dest[i] = s[i]; return; } void printBuf(unsigned char *buf, uint8_t len) { for(int i = 0; i < len; i++) xil_printf("%c", buf[i]); xil_printf("n"); } int main (void) 1
  • 5.
    { unsigned char tmpbuf[16]; unsignedint Status, newvalue, this; unsigned int * a0 = (unsigned int *) 0x1BF00000; unsigned int * a1 = (unsigned int *) 0x1BF00008; unsigned char *buffer0 = ( unsigned char *)0x1BF01000; unsigned char *buffer1 = ( unsigned char *) 0x1BF01030; *a0 = 0; *a1 = 0; Xil_DCacheDisable(); xil_printf("-- Start of the Program --rn"); xil_printf("a0 : %d a1: %d rn", *a0, *a1); //xil_printf("%x a %x b rn", a0, a1); usleep(400); // PS Timer related definitions XScuTimer_Config *ConfigPtr; XScuTimer *TimerInstancePtr = &Timer; // Initialize the timer ConfigPtr = XScuTimer_LookupConfig (XPAR_PS7_SCUTIMER_0_DEVICE_ID); Status = XScuTimer_CfgInitialize (TimerInstancePtr, ConfigPtr, ConfigPtr->BaseAddr); if(Status != XST_SUCCESS){ xil_printf("Timer init() failedrn"); return XST_FAILURE; } ///XScuTimer_LoadTimer(TimerInstancePtr, 32500000); XScuTimer_LoadTimer(TimerInstancePtr, 4000000000); // Set AutoLoad mode XScuTimer_EnableAutoReload(TimerInstancePtr); xil_printf("Enter your password please: "); char userinput[16]; scanf("%s",userinput); writeBuf( buffer0, userinput,16); //writeBuf( buffer0, "0123456789abcdef",16); xil_printf("-- Written buffer0 rn"); readBuf(tmpbuf, userinput, 16); //readBuf(tmpbuf, buffer0, 16); printBuf(tmpbuf,16); *a0 = 1; //changing the value of shared variable. // Start the timer XScuTimer_Start (TimerInstancePtr); while( (*a1 != 1) ) { 2
  • 6.
    usleep(500); } XScuTimer_Stop(TimerInstancePtr); newvalue = XScuTimer_GetCounterValue(TimerInstancePtr); this= 4000000000 - newvalue; xil_printf("Cycles counted: %d for reply.rn", this); *a1 = 0; *a0 = 0; readBuf(tmpbuf, buffer1, 8); xil_printf("Status : rn"); printBuf(tmpbuf, 8); return 0; } After including all the required libraries for each function used, a Timer is created that will help to calculate the machine cycles. Function writeBuf writes a character array within another, something like string copy from the C library with given lenght(like strncpy). Function printBuf prints a string, one character at a time for a given lenght. In the code, we do disable the DCache(had various problems to synchronize the 2 processors;tried Invalidating and Flushing, but in the end to get the meassur- ments, it became disabled.) Values a0, a1 are used to synchronize the actions between the 2 proces- sors(A90,A91) and are shared among them. Buffer0 and buffer1 are also shared between the 2 processors and the first one is used for the input to A91 while the second one holds the output. Output is a simple character array ’accepted’ or ’declined’. Next the configuration of the Scu timer takes place. Timer is loaded with value 4000000000 that is close enough to the largest 32-bit value that it can hold to avoid underflows in the meassurment process. User enters the 16 character password, and that is written in buffer0. Chang- ing the value a0 to 1, so the A91 processor which is polling the variable can start working on the authentication. Timer starts counting, while the processor(A90) polls now the shared variable a1. When (A91) changes the variable to 1, A90 stops the timer and counts the cycles spent and prints them to the debug terminal. 1.1.2 Processor A91 "a91.c" #include "xparameters.h" #include "xgpio.h" #include <sleep.h> #include "xscutimer.h" #include <xil_cache.h> #include "ZedboardOLED.h" 3
  • 7.
    #include <string.h> #include <stdio.h> #defineACCEPT "accepted" #define DECLINE "declined" XScuTimer Timer; /* Cortex A9 SCU Private Timer Instance */ #define USERS 1024 unsigned char passwords[USERS][16]; void writeBuf(unsigned char *buf0, char *s, uint8_t len) { for(int i = 0; i < len; i++) buf0[i] = s[i]; return ; } void readBuf(unsigned char *dest, unsigned char *s, uint8_t len) { for(int i=0; i < len; i++) dest[i] = s[i]; //return; } void printBuf(unsigned char *buf, uint8_t len) { for(int i = 0; i < len; i++) xil_printf("%c", buf[i]); xil_printf("n"); } int matches(unsigned char *in) { for( int i = 0; i < USERS; i++){ //xil_printf("Testing: %drn", i); if( strncmp( (const char *)in, (const char *) passwords[i], 16) == 0) return i+1; } return 0; } int main (void) { ///Xil_DCacheInvalidate(); Xil_DCacheDisable(); 4
  • 8.
    // passwords stored. clear_OLED();// clear the OLED print_message("Enter password:",1); volatile unsigned int * a0 = (unsigned int *) 0x1BF00000; volatile unsigned int * a1 = (unsigned int *) 0x1BF00008; volatile unsigned char *buffer0 = ( unsigned char *) 0x1BF01000; volatile unsigned char *buffer1 = ( unsigned char *) 0x1BF01030; char thesi[4]; *a0 = 0; char snum[5]; char tnum[4]; for(int i = 0; i < USERS; i++) { strcpy(passwords[i], "abcdefghabcdefgh"); memcpy(snum, "00000", 5); memcpy(tnum, "0000", 4); sprintf(snum, "%4d",i); sprintf(tnum, "%d",i); int len = strlen(tnum); if(len!=4) sprintf(passwords[i], "%s", snum); else sprintf(passwords[i], "%s", tnum); if(len == 1) { passwords[i][0] = ’0’; passwords[i][1] = ’0’; passwords[i][2] = ’0’; } else if(len == 2) { passwords[i][0] = ’0’; passwords[i][1] = ’0’; } else if(len == 3) passwords[i][0] = ’0’; else if(len == 4) passwords[i][0] = ’1’; passwords[i][4] = ’a’; //for(int j = 0; j < 16; j++) // xil_printf("%c",passwords[i][j]); // xil_printf("nr"); } xil_printf("Passwds generatednr"); memcpy(thesi, 32, 4); // in a non printable char. usleep(1000000); 5
  • 9.
    xil_printf("-- Start ofthe Program --rn"); xil_printf("a0 : %d a1: %d rn", *a0, *a1); //xil_printf("%x a %x b rn", a0, a1); unsigned char input[16]; xil_printf("nWaiting to read buffer0rn"); ///Xil_DCacheInvalidate(); while( (*a0) != 1) { ; //xil_printf("a0 : %drn", *a0); //xil_printf("a1 : %drn", *a1); //xil_printf("wait..rn"); ///Xil_DCacheInvalidate(); //Xil_DCacheInvalidate(); //sleep(1); } readBuf(input, buffer0 , 16); //xil_printf("Read the buffer0 rn"); //printBuf(input, 16); int ret = matches(input); xil_printf("ret value: %drn",ret); clear_OLED(); if( ret != 0) { xil_printf("Accept authorization. rn"); print_message("Access Granted",1); sprintf(thesi, "%4d",ret); for(int j = 0; j < 4; j++) print_char(thesi[j],2,j); writeBuf(buffer1, ACCEPT, strlen(ACCEPT)); }else { xil_printf("Decline authorization. rn"); print_message("Access Declined",1); writeBuf(buffer1, DECLINE, strlen(DECLINE)); } *a1 = 1; ///Xil_DCacheFlush(); return 0 ; } The code for the A91 processor also includes the specific header files needed. Defines the number of users as well as the output character arrays. In the first loop of the main(), we have a part of the code that will create passwords of the form "xxxxafghabcdefgh" where xxxx will be the number of the element in the array(f.e 9 will be "0009afghabcdefgh" while 1013 will be stored as password "1013afghabcdefgh) ; to avoid writing big arrays and though increasing the text size of the application. Also the array called passwords stores the valid passwords that will be accepted. Function readBuf copies into the first argument pointer len number of bytes from the character array which starts at the pointer argument ’s’. Funtion matches search linear throught the password’s array and compares 6
  • 10.
    the input givenby the user to each one of the elemnts of the array. It does return the position found since we need to print that possition on the screen. In the main(), again DCache is disabled, and the OLED screen is cleared. Then the prompt "Enter password:" appears on the on-board screen. input array will hold the input given by the user and copied from the buffer0, where A90 processor will store the user’s input. The processor then starts polling the a0 variable. When it becomes 1, is copying the buffer0 to the input. and calls the function matches. On board screen is cleared and based in the return value of the previously called function will write "Access Granted" and will print the possition found or it will print "Access Declined". 1.2 SHA1 scheme In the SHA1 scheme, A91 core, do not compare the input with the users raw password, but it precalculates the 20-bytes SHA1 on each valid password and then compares the input fetched from buffer0 to the SHA1-encrypted array. In A90 core now, after getting user’s input, the encryption is created and placed into the buffer0. 1.2.1 Processor A90 "a90sha1.c" #include "xparameters.h" #include "xgpio.h" #include "xscutimer.h" #include <sleep.h> #include <xil_cache.h> #include "ZedboardOLED.h" #include <stdio.h> #include "sha1.h" XScuTimer Timer; /* Cortex A9 SCU Private Timer Instance */ void writeBuf(unsigned char *buf0, char *s, uint8_t len) { for(int i = 0; i < len; i++) buf0[i] = s[i]; return ; } void readBuf(unsigned char *dest, unsigned char *s, uint8_t len) { for(int i=0; i < len; i++) dest[i] = s[i]; return; } void printBuf(unsigned char *buf, uint8_t len) { for(int i = 0; i < len; i++) xil_printf("%x ", buf[i]); xil_printf("n"); } 7
  • 11.
    int main (void) { unsignedchar tmpbuf[16]; unsigned char encrypted[SHA1_BLOCK_SIZE]; unsigned int Status, newvalue, this; unsigned int * a0 = (unsigned int *) 0x1BF00000; unsigned int * a1 = (unsigned int *) 0x1BF00008; unsigned char *buffer0 = ( unsigned char *) 0x1BF01000; unsigned char *buffer1 = ( unsigned char *) 0x1BF01030; *a0 = 0; //Xil_DCacheFlush(); Xil_DCacheDisable(); Xil_ICacheDisable(); xil_printf("-- Start of the Program --rn"); xil_printf("a0 : %d a1: %d rn", *a0, *a1); //xil_printf("%x a %x b rn", a0, a1); //usleep(400); // PS Timer related definitions XScuTimer_Config *ConfigPtr; XScuTimer *TimerInstancePtr = &Timer; // Initialize the timer ConfigPtr = XScuTimer_LookupConfig (XPAR_PS7_SCUTIMER_0_DEVICE_ID); Status = XScuTimer_CfgInitialize (TimerInstancePtr, ConfigPtr, ConfigPtr->BaseAddr); if(Status != XST_SUCCESS){ xil_printf("Timer init() failedrn"); return XST_FAILURE; } XScuTimer_LoadTimer(TimerInstancePtr, 4000000000); // Set AutoLoad mode XScuTimer_EnableAutoReload(TimerInstancePtr); xil_printf("Enter your password please: "); char userinput[16]; scanf("%s",userinput); SHA1_CTX ctx; sha1_init(&ctx); sha1_update(&ctx, userinput, 16); sha1_final(&ctx, encrypted); writeBuf( buffer0, encrypted,SHA1_BLOCK_SIZE); //writeBuf( buffer0, "0123456789abcdef",16); xil_printf("-- Written buffer0 rn"); readBuf(tmpbuf, encrypted, SHA1_BLOCK_SIZE); //readBuf(tmpbuf, buffer0, 16); printBuf(tmpbuf,SHA1_BLOCK_SIZE); *a0 = 1; //changing the value of shared variable. 8
  • 12.
    //Xil_DCacheFlush(); // Start thetimer XScuTimer_Start (TimerInstancePtr); while( (*a1 != 1) ) { // Xil_DCacheInvalidate(); usleep(500); } XScuTimer_Stop(TimerInstancePtr); newvalue = XScuTimer_GetCounterValue(TimerInstancePtr); this = 4000000000 - newvalue; xil_printf("Cycles counted: %d for reply.rn", this); *a1 = 0; *a0 = 0; //Xil_DCacheFlush(); //Xil_DCacheInvalidate(); readBuf(tmpbuf, buffer1, 8); xil_printf("Status : rn"); printBuf(tmpbuf, 8); return 0; } In the processor A90’s code, there are not many differences than the previous one. All needed libraries are included, and the shared memory addresses remain the same. One is the encrypted array which will hold the encryption under SHA-1 of the user’s input. The output will be 20 bytes long as we can see by inspecting the sha1.c code provided. SHA1 process take place in lines[68-72] and from the 16-bit user input we end up with a 20 byte long encrypted hash. The rest remains as in the previous simple scheme. DCache and ICache are also disabled in this scheme as well. The main difference from the previous scheme is that in this scheme, A90 processor do not share with the A91 the users input but the SHA1 applied on that input. 1.2.2 Processor A91 "a91sha1.c" #include "xparameters.h" #include "xgpio.h" #include <sleep.h> #include "xscutimer.h" #include <xil_cache.h> #include "ZedboardOLED.h" #include <string.h> #include <stdio.h> 9
  • 13.
    #include "sha1.h" #define ACCEPT"accepted" #define DECLINE "declined" XScuTimer Timer; /* Cortex A9 SCU Private Timer Instance */ #define USERS 1024 unsigned char passwords[USERS][16]; unsigned char encrypted[USERS][SHA1_BLOCK_SIZE]; // storing the sha1 of each password. void fill_encrypted(void) { xil_printf("i am here1n"); for(int i = 0; i < USERS; i++) { SHA1_CTX ctx; sha1_init(&ctx); sha1_update(&ctx, passwords[i], 16); sha1_final(&ctx, encrypted[i]); /* xil_printf("SHA1["); for( int j = 0; j < 16; j++) { xil_printf("%c",passwords[i][j]); } xil_printf("] = "); for(int w = 0; w < SHA1_BLOCK_SIZE; w++) xil_printf("%4x", encrypted[i][w]); xil_printf("n"); */ } xil_printf("i am here2n"); } void writeBuf(unsigned char *buf0, char *s, uint8_t len) { for(int i = 0; i < len; i++) buf0[i] = s[i]; return ; } void readBuf(unsigned char *dest, unsigned char *s, uint8_t len) { for(int i=0; i < len; i++) dest[i] = s[i]; return; } void printBuf(unsigned char *buf, uint8_t len) { for(int i = 0; i < len; i++) xil_printf("%x ", buf[i]); xil_printf("n"); 10
  • 14.
    } int matches(unsigned char*in) { for( int i = 0; i < USERS; i++){ //xil_printf("Testing: %drn", i); if( strncmp( (const char *)in, (const char *) encrypted[i], SHA1_BLOCK_SIZE) == 0) return i+1; } return 0; } int main (void) { xil_printf("-- Start of the Program --rn"); char snum[5]; char tnum[4]; for(int i = 0; i < USERS; i++) { strcpy(passwords[i], "abcdefghabcdefgh"); memcpy(snum, "00000", 5); memcpy(tnum, "0000", 4); sprintf(snum, "%4d",i); sprintf(tnum, "%d",i); int len = strlen(tnum); if(len!=4) sprintf(passwords[i], "%s", snum); else sprintf(passwords[i], "%s", tnum); if(len == 1) { passwords[i][0] = ’0’; passwords[i][1] = ’0’; passwords[i][2] = ’0’; } else if(len == 2) { passwords[i][0] = ’0’; passwords[i][1] = ’0’; } else if(len == 3) passwords[i][0] = ’0’; else if(len == 4) passwords[i][0] = ’1’; passwords[i][4] = ’a’; //for(int j = 0; j < 16; j++) // xil_printf("%c",passwords[i][j]); // xil_printf("nr"); } xil_printf("Passwds generatednr"); 11
  • 15.
    fill_encrypted(); //Xil_DCacheInvalidate(); Xil_DCacheDisable(); Xil_ICacheDisable(); clear_OLED(); // clearthe OLED print_message("Enter password2:",1); unsigned int * a0 = (unsigned int *) 0x1BF00000; unsigned int * a1 = (unsigned int *) 0x1BF00008; unsigned char *buffer0 = ( unsigned char *) 0x1BF01000; unsigned char *buffer1 = ( unsigned char *) 0x1BF01030; char thesi[4]; *a0 = 0; memcpy(thesi, 32, 4); // in a non printable char. usleep(1000000); xil_printf("-- Start of the Program --rn"); xil_printf("a0 : %d a1: %d rn", *a0, *a1); //xil_printf("%x a %x b rn", a0, a1); unsigned char input[16]; xil_printf("nWaiting to read buffer0rn"); //Xil_DCacheInvalidate(); while( (*a0) != 1) { //xil_printf("a0 : %drn", *a0); //xil_printf("a1 : %drn", *a1); //xil_printf("wait..rn"); //Xil_DCacheInvalidate(); //Xil_DCacheInvalidate(); //sleep(1); } readBuf(input, buffer0 , 20); xil_printf("Read the buffer0 rn"); printBuf(input, 20); int ret = matches(input); xil_printf("ret value: %drn",ret); clear_OLED(); if( ret != 0) { xil_printf("Accept authorization. rn"); print_message("Access Granted",1); sprintf(thesi, "%4d",ret); for(int j = 0; j < 4; j++) print_char(thesi[j],2,j); writeBuf(buffer1, ACCEPT, strlen(ACCEPT)); }else { xil_printf("Decline authorization. rn"); print_message("Access Declined",1); writeBuf(buffer1, DECLINE, strlen(DECLINE)); } 12
  • 16.
    *a1 = 1; //Xil_DCacheFlush(); return0 ; } As for the code on the A91 processor for the SHA1 scheme, the main differ- ence is the existance of encrypted array, that has length same with the number of the valid users. Function fill_encrypted traverses througth the passwords array and cre- ated the SHA1 hash of each one, storing it on the encrypted array. Function matches in this code, search again in a linear way, througth en- crypted array this time and compares the shared hash from A90 to each one stored into the matrix. There is not many to explain in the main() that are different from the simple scheme described in the previous section, expept that fill_encrypted is called at first to initiate and create the hashes of the passwords; to be ready for the comparison latter on. 1.3 SHA1-Blockchain scheme In the last scheme, processor A90, provides three inputs to the A91 core each time. The first one is the encrypted(SHA1) password that the user entered. The other two are the cycles counted from the last success log-in, as well as the hash of the hashed password incremented by the cycles time provided as the second argument. Of course in the first log-in attempt, cycles counted are zero. When A91 gets the signal, fetches the encrypted password, will check it against to its encypted passwords and in anycase will call the function fill_blockchain to save the new calculations for each element in the matrix. Afterwards in func- tion matches ; if encrypted password passes the test, the blockchain array will also be tested before accepting and authenticating the request. 1.3.1 Processor A90 "a90sha1_blockchain.c" #include "xparameters.h" #include "xgpio.h" #include "xscutimer.h" #include <sleep.h> #include <xil_cache.h> #include "ZedboardOLED.h" #include <stdio.h> #include "sha1.h" XScuTimer Timer; /* Cortex A9 SCU Private Timer Instance */ void writeBuf(unsigned char *buf0, char *s, uint8_t len) { for(int i = 0; i < len; i++) buf0[i] = s[i]; 13
  • 17.
    return ; } void readBuf(unsignedchar *dest, unsigned char *s, uint8_t len) { for(int i=0; i < len; i++) dest[i] = s[i]; return; } void printBuf(unsigned char *buf, uint8_t len) { for(int i = 0; i < len; i++) xil_printf("%x ", buf[i]); xil_printf("n"); } int main (void) { unsigned char tmpbuf[16]; unsigned char encrypted[SHA1_BLOCK_SIZE]; unsigned char hashed_block_array[SHA1_BLOCK_SIZE]; unsigned int Status, newvalue, this, test_this; unsigned int * a0 = (unsigned int *) 0x1BF00000; unsigned int * a1 = (unsigned int *) 0x1BF00008; unsigned char *buffer0 = ( unsigned char *) 0x1BF01000; unsigned char *buffer1 = ( unsigned char *) 0x1BF01030; unsigned int *time_i = (unsigned int *) 0x1BF01050; unsigned char *hashed_block = (unsigned char *) 0x1BF01070; int turn = 0; this = 0; // just to be sure in case of first failed attempt, // wont take any random value as time_i. Xil_DCacheDisable(); while(1) { *a0 = 0; //Xil_DCacheFlush(); xil_printf("-- Start of the Program --rn"); xil_printf("a0 : %d a1: %d rn", *a0, *a1); //xil_printf("%x a %x b rn", a0, a1); //usleep(400); // PS Timer related definitions XScuTimer_Config *ConfigPtr; XScuTimer *TimerInstancePtr = &Timer; // Initialize the timer ConfigPtr = XScuTimer_LookupConfig (XPAR_PS7_SCUTIMER_0_DEVICE_ID); Status = XScuTimer_CfgInitialize (TimerInstancePtr, ConfigPtr, ConfigPtr->BaseAddr); if(Status != XST_SUCCESS){ 14
  • 18.
    xil_printf("Timer init() failedrn"); returnXST_FAILURE; } XScuTimer_LoadTimer(TimerInstancePtr, 4000000000); // Set AutoLoad mode XScuTimer_EnableAutoReload(TimerInstancePtr); xil_printf("Enter your password please: "); char userinput[16]; scanf("%s",userinput); xil_printf("doing ctx init.rn "); SHA1_CTX ctx; sha1_init(&ctx); sha1_update(&ctx, userinput, 16); sha1_final(&ctx, encrypted); xil_printf("doing ctx finished. rn"); // written encrypted on shared address. writeBuf( buffer0, encrypted,SHA1_BLOCK_SIZE); //writeBuf( buffer0, "0123456789abcdef",16); xil_printf("-- Written buffer0 rn"); readBuf(tmpbuf, encrypted, SHA1_BLOCK_SIZE); //readBuf(tmpbuf, buffer0, 16); printBuf(tmpbuf,SHA1_BLOCK_SIZE); if(turn == 0) { xil_printf("turn 0rn"); *time_i = 0; *hashed_block = 0; } else { xil_printf("turn with blockchainrn"); //written time_i on shared address. *time_i = this; for(int k = 0; k < SHA1_BLOCK_SIZE; k++) hashed_block_array[k] = encrypted[k]; unsigned int *add_pointer = (unsigned int *)&hashed_block_array[SHA1_BLOCK_SIZE-4]; *add_pointer = *add_pointer + this; SHA1_CTX ctx2; sha1_init(&ctx2); sha1_update(&ctx2, hashed_block_array, 20); sha1_final(&ctx2, encrypted); //written the blockchain hash on shared address. writeBuf( hashed_block, encrypted,SHA1_BLOCK_SIZE); xil_printf("--written blockchain: time: %ldnr bchain: nr", this); readBuf(tmpbuf, hashed_block, SHA1_BLOCK_SIZE); 15
  • 19.
    printBuf(tmpbuf,SHA1_BLOCK_SIZE); xil_printf("--n’r"); } *a0 = 1;//changing the value of shared variable. //Xil_DCacheFlush(); // Start the timer XScuTimer_Start (TimerInstancePtr); while( (*a1 != 1) ) { // Xil_DCacheInvalidate(); usleep(500); } XScuTimer_Stop(TimerInstancePtr); newvalue = XScuTimer_GetCounterValue(TimerInstancePtr); test_this = 4000000000 - newvalue; xil_printf("Cycles counted: %d for reply.rn", test_this); *a1 = 0; *a0 = 0; //Xil_DCacheFlush(); //Xil_DCacheInvalidate(); readBuf(tmpbuf, buffer1, 8); xil_printf("Status : rn"); printBuf(tmpbuf, 8); if( !strncmp(tmpbuf, "accepted", 8)) { this = test_this; xil_printf("keeping the timern"); } else { xil_printf("declined, not keeping the timenr"); } turn = 1; } return 0; } In main program, we disable data cache, and we go into an endless loop. Instructions are like the previous schemes initializing all required things for the scu_timer and getting input from the user. After, the SHA-1 encryption of the input is stored into encrypted array, and written in buffer0 shared address so A91 core can access it. If there is the first time running, time_i and hash_block are having the values 0. If not, we copy the encrypted password into the hashed_block_array and then we assign an unsigned int pointer( uints have 4 bytes lenght in this machine) to the 16th byte of the hashed_block_array. This happens, to be able with the next instruction *add_pointer = *add_pointer + this; to be able to make the addition of the cycles meassured from previous authentication to the hash. In the end the whole result is again hashed one more time with SHA-1 16
  • 20.
    algorithm and the20 bytes output is stored into hashed_block shared address with the A91 core. Then the value of the variable a0 is modified to signal the A91 core. Timer starts to count the cycles and after polling the shared variable a1 ; timer stops to take the meassurment. An extra test follows since we do not intent keeping the values of the timer when there is not a succesful attempt. In the end turn variable is used as a flag and always stays to 1. Is used to escape the first part of the if statement which is only used on the first log-in. 1.3.2 Processor A91 "a91sha1_blockchain.c" #include "xparameters.h" #include "xgpio.h" #include <sleep.h> #include "xscutimer.h" #include <xil_cache.h> #include "ZedboardOLED.h" #include <string.h> #include <stdio.h> #include "sha1.h" #define ACCEPT "accepted" #define DECLINE "declined" //#define DEBUG_PRINT 1 XScuTimer Timer; /* Cortex A9 SCU Private Timer Instance */ unsigned int * a0 = (unsigned int *) 0x1BF00000; unsigned int * a1 = (unsigned int *) 0x1BF00008; unsigned char *buffer0 = ( unsigned char *) 0x1BF01000; unsigned char *buffer1 = ( unsigned char *) 0x1BF01030; unsigned int *time_i = (unsigned int *) 0x1BF01050; unsigned char *hashed_block = (unsigned char *) 0x1BF01070; int turn = 0; #define USERS 1024 unsigned char passwords[USERS][16]; unsigned char encrypted[USERS][SHA1_BLOCK_SIZE]; // storing the sha1 of each password. unsigned char blockchain[USERS][SHA1_BLOCK_SIZE]; // storing the blockchain_stuff(time_i hashed after added on the hased password) unsigned char blockchain2[USERS][SHA1_BLOCK_SIZE]; // fill_encrypted: creates the hashes of the values that will be needed to // compare agaist the hash(value) of the given password. void fill_encrypted(void) { for(int i = 0; i < USERS; i++) { 17
  • 21.
    SHA1_CTX ctx; sha1_init(&ctx); sha1_update(&ctx, passwords[i],16); sha1_final(&ctx, encrypted[i]); #ifdef DEBUG_PRINT xil_printf("SHA1["); for( int j = 0; j < 16; j++) { xil_printf("%c",passwords[i][j]); } xil_printf("] = "); for(int w = 0; w < SHA1_BLOCK_SIZE; w++) xil_printf("%4x", encrypted[i][w]); xil_printf("n"); #endif } } // filling the array with hash( hash(password_i +time_i)) void fill_blockchain(void) { for(int i = 0; i < USERS; i++) { //getting the hash(password) in each element. //for(int k = 0; k < SHA1_BLOCK_SIZE; k++) memcpy(blockchain[i], encrypted[i], 20); //blockchain[i][0] = encrypted[k]; SHA1_CTX ctx; sha1_init(&ctx); // add time_i received from the shared memory. //printBuf(blockchain[i],20); unsigned int *add_pointer = (unsigned int *)&blockchain[i][SHA1_BLOCK_SIZE-4]; *add_pointer = *add_pointer + (*time_i); sha1_update(&ctx, blockchain[i], 20); sha1_final(&ctx, blockchain[i]); // could work for blockchain array also? i should look the code in sha1.c #ifdef DEBUG_PRINT xil_printf("BlockSHA1["); for( int j = 0; j < 16; j++) { xil_printf("%c",passwords[i][j]); } xil_printf("] = "); 18
  • 22.
    for(int w =0; w < SHA1_BLOCK_SIZE; w++) xil_printf("%4x", blockchain[i][w]); xil_printf("n"); #endif } } void writeBuf(unsigned char *buf0, char *s, uint8_t len) { for(int i = 0; i < len; i++) buf0[i] = s[i]; return ; } void readBuf(unsigned char *dest, unsigned char *s, uint8_t len) { for(int i=0; i < len; i++) dest[i] = s[i]; return; } void printBuf(unsigned char *buf, uint8_t len) { for(int i = 0; i < len; i++) xil_printf("%x ", buf[i]); xil_printf("n"); } int matches(unsigned char *in) { if(turn == 0) { for( int i = 0; i < USERS; i++){ //xil_printf("Testing0: %drn", i); //printBuf(encrypted[i],20); if( strncmp( (const char *)in, (const char *) encrypted[i], SHA1_BLOCK_SIZE) == 0) return i+1; } } else { for( int i = 0; i < USERS; i++){ //xil_printf("Testing1: %drn", i); if( strncmp( (const char *)in, (const char *) encrypted[i], SHA1_BLOCK_SIZE) == 0) { #ifdef DEBUG_PRINT xil_printf("Passed first test--printing hashblockrn"); printBuf(hashed_block, 20); xil_printf("Passed first test--printing blockchain[i]rn"); 19
  • 23.
    //printBuf(&blockchain[i], 20); #endif if( strncmp((const char *)hashed_block, (const char *) blockchain[i], SHA1_BLOCK_SIZE) == 0 ) return i+1; else break; //we assume we got great collision resistance. } } } return 0; } int main (void) { xil_printf("-- Start of the Program --rn"); //char * snum = "0000"; char snum[5]; char tnum[4]; for(int i = 0; i < USERS; i++) { strcpy(passwords[i], "abcdefghabcdefgh"); memcpy(snum, "00000", 5); memcpy(tnum, "0000", 4); sprintf(snum, "%4d",i); sprintf(tnum, "%d",i); int len = strlen(tnum); if(len!=4) sprintf(passwords[i], "%s", snum); else sprintf(passwords[i], "%s", tnum); if(len == 1) { passwords[i][0] = ’0’; passwords[i][1] = ’0’; passwords[i][2] = ’0’; } else if(len == 2) { passwords[i][0] = ’0’; passwords[i][1] = ’0’; } else if(len == 3) passwords[i][0] = ’0’; else if(len == 4) passwords[i][0] = ’1’; passwords[i][4] = ’a’; //for(int j = 0; j < 16; j++) 20
  • 24.
    // xil_printf("%c",passwords[i][j]); // xil_printf("nr"); } xil_printf("Passwdsgeneratednr"); Xil_DCacheDisable(); Xil_ICacheDisable(); while(1) { fill_encrypted(); xil_printf("filled encrnr"); //Xil_DCacheInvalidate(); clear_OLED(); // clear the OLED print_message("Enter password2:",1); char thesi[4]; *a0 = 0; memcpy(thesi, 32, 4); // in a non printable char. usleep(1000000); xil_printf("a0 : %d a1: %d rn", *a0, *a1); //xil_printf("%x a %x b rn", a0, a1); unsigned char input[16]; unsigned char input_block[20]; xil_printf("nWaiting to read buffer0rn"); //Xil_DCacheInvalidate(); while( (*a0) != 1) { //xil_printf("a0 : %drn", *a0); //xil_printf("a1 : %drn", *a1); //xil_printf("wait..rn"); //Xil_DCacheInvalidate(); //Xil_DCacheInvalidate(); //sleep(1); } //xil_printf("out of sync looprn"); if(turn == 1) { #ifdef DEBUG_PRINT readBuf(input_block, hashed_block, 20); xil_printf("Hashed block provided: rn"); printBuf(input_block, 20); xil_printf("time_i received: %ldrn", *time_i); #endif fill_blockchain(); } 21
  • 25.
    readBuf(input, buffer0 ,20); //xil_printf("Read the buffer0 rn"); //printBuf(input, 20); int ret = matches(input); //xil_printf("ret value: %drn",ret); clear_OLED(); if( ret != 0) { xil_printf("Accept authorization. rn"); print_message("Access Granted",1); sprintf(thesi, "%4d",ret); for(int j = 0; j < 4; j++) print_char(thesi[j],2,j); writeBuf(buffer1, ACCEPT, strlen(ACCEPT)); }else { xil_printf("Decline authorization. rn"); print_message("Access Declined",1); writeBuf(buffer1, DECLINE, strlen(DECLINE)); } *a1 = 1; turn =1; } //Xil_DCacheFlush(); return 0 ; } 22
  • 26.
    2Results with linearsearch It is important to define the way the results were obtained: for variable number of users, the worst case in terms of machine cycles were meassured. Since the algorithm searchs within the matrix to compare character arrays; the worst case always is when the desired password lies last. As one can observe, the SHA1/blockchain scheme has significant more over- head than the 2 other schemes. As well that very quick the line related to the SHA1, is increasing because in contrast to the simple scheme it doesn’t compare 16 bytes but 20 bytes each time, as the 20-byte output of SHA1. Figure 2.1: Results meassured for the 3 different schemes of log in. 23
  • 27.
    3Theoretical question: Scalingthe synchronization into more than 2 processors In the event that there are more than two processors involved into the con- structed scheme, we could separate different cases. 3.1 Two processors require access for different purpose each One case is when 2 or more cores require to get access with their password on another processor’s resources. According to the shared memory paradigm used in the above implemen- tation, a system could be defined, where the processors(f.e A90,A91) get user inputs and A93 has responsible to reply with ACCESS/DECLINE of their au- thentication request. We could have shared variable a0,a1 that are accessed in RoundRobin way by the processor A93; checking the variables this time and not polling forever. 3.2 Two processors contribute together into a single authentication access Another case could be that in fact for the authentication to be complete more than 1 cores need to contribute with their inputs. Using shared variables with polling this time (till the A93 extracts both buffers as the inputs) and different address locations for each buffer respective to the contirbuting to input processor could solve the problem. For the reply, both(A90, A91) can poll the same variable, and when detect that it has changed they can check for the result. 24