-
Notifications
You must be signed in to change notification settings - Fork 1
/
device_regen_funcs.c
3590 lines (2912 loc) · 171 KB
/
device_regen_funcs.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// ========================================================================================================
// ========================================================================================================
// ***************************************** device_regen_funcs.c *****************************************
// ========================================================================================================
// ========================================================================================================
//
//--------------------------------------------------------------------------------
// Company: IC-Safety, LLC and University of New Mexico
// Engineer: Professor Jim Plusquellic
// Exclusive License: IC-Safety, LLC
// Copyright: Univ. of New Mexico
//--------------------------------------------------------------------------------
#include "common.h"
#include "device_hardware.h"
#include "device_common.h"
#include "device_regen_funcs.h"
#include "commonDB_RT_PUFCash.h"
#include "aes_128_ecb_openssl.h"
#include "aes_256_cbc_openssl.h"
// ====================== DATABASE STUFF =========================
#include <sqlite3.h>
#include "commonDB.h"
// ====================== SHA-3 =========================
#include <openssl/bn.h>
#include <openssl/ecdh.h>
#include <openssl/err.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/rand.h>
#include "sha_3_256_openssl.h"
// ========================================================================================================
// ========================================================================================================
// For handling Ctrl-C. We MUST exit gracefully to keep the hardware from quitting at a point where the
// fine phase of the MMCM is has not be set back to 0. If it isn't, then re-running this program will
// likely fail because my local fine phase register (which is zero initially after a RESET) is out-of-sync
// with the MMCM phase (which is NOT zero). If we are in the middle of running the SRF PUF, then I set
// SAFE_TO_QUIT to 0, so this does not leave SRF in an undefined state, otherwise exit immediately.
int SAFE_TO_QUIT = 1;
void intHandler(int dummy)
{
printf("!!!!!!!!!!!!!!!! Ctrl-C pressed -- quitting program!\n");
fflush(stdout);
keepRunning = 0;
// Exit the loops in ttp_DB.c so we can save the database. Also just exit the loops in device_regeneration
// with the 'keepRunning' flag set to 0.
if ( SAFE_TO_QUIT == 1 )
exit(EXIT_SUCCESS);
}
// ========================================================================================================
// ========================================================================================================
// This converts the 2 vector sequences stored in the database and transmitted by the server to this device into
// one vector challenges. NOTE: num_PIs is num_chlng_bits/2.
// *** VEC_CHLNG ***
unsigned char **ConvertVecsToChallenge(int max_string_len, int num_vecs, int num_PIs, unsigned char **first_vecs_b,
unsigned char **second_vecs_b, int num_chlng_bits)
{
unsigned char **challenges_b;
int vec_num, i, j;
if ( (challenges_b = (unsigned char **)malloc(sizeof(unsigned char *) * num_vecs)) == NULL )
{ printf("ERROR: ConvertVecsToChallenge(): Failed to allocate storage for challenges_b array!\n"); exit(EXIT_FAILURE); }
for ( vec_num = 0; vec_num < num_vecs; vec_num++ )
{
if ( (challenges_b[vec_num] = (unsigned char *)malloc(sizeof(unsigned char)*num_chlng_bits/8)) == NULL )
{ printf("ERROR: ConvertVecsToChallenge(): Failed to allocate storage for challenges_b element!\n"); exit(EXIT_FAILURE); }
for ( i = 0, j = 0; i < num_PIs/8; i++, j++ )
challenges_b[vec_num][j] = first_vecs_b[vec_num][i];
for ( i = 0; i < num_PIs/8; i++, j++ )
challenges_b[vec_num][j] = second_vecs_b[vec_num][i];
}
return challenges_b;
}
// ========================================================================================================
// ========================================================================================================
// Collect all PNs. This is the longer operation associated with SRF (depending on the number of samples).
int CollectPNs(int max_string_len, int num_POs, int num_PIs, int vec_chunk_size, int max_generated_nonce_bytes,
volatile unsigned int *CtrlRegA, volatile unsigned int *DataRegA, unsigned int ctrl_mask, int num_vecs,
int num_rise_vecs, int has_masks, unsigned char **first_vecs_b, unsigned char **second_vecs_b,
unsigned char **masks_b, unsigned char *device_n1, int DUMP_BITSTRINGS, int debug_flag)
{
int vec_num, generated_device_num_n1_bytes;
// *** VEC_CHLNG ***
int num_chlng_bits = num_PIs * 2;
unsigned char **challenges_b;
struct timeval t0, t1;
long elapsed;
// ****************************************
// ***** Collect PNs
if ( debug_flag == 1 )
{
printf("CPN.1) Collecting ALL PNs and Generating Device Nonces in Parallel\n");
gettimeofday(&t0, 0);
}
// WARNING: IN_SIM_DONE_ALL_VECS is connected to the ready signal in the state machine and therefore will be 1 UNTIL the CollectPN state
// machine is started. In this C code, WE ALWAYS START THE hardware MstCtrl state machines BEFORE CALLING THIS ROUTINE (assert/deassert
// OUT_CP_PUF_START). I've added this while-loop check BEFORE the main while loop to wait for IN_SM_DONE_ALL_VECS to go low BEFORE entering
// the main while loop that delivers vectors to the hardware because this is technically a race condition. If the race is ever lost, where
// this C code executes the main while loop BEFORE MstCtrl has a chance to start CollectPNs, then you would get all zeros for the timing
// data (no vectors would have been delivered). This is prevented with this additional while loop check, which waits for IN_SM_DONE_ALL_VECS
// to got low.
while ( ((*DataRegA) & (1 << IN_SM_DONE_ALL_VECS)) != 0 );
// I store the challenges in the database as two vector sequences even though for SRF, there is only ONE configuration challenge.
// I'll eventually change the database structure, but right now, I simply split the one challenge into two pieces and store
// the first half in first_vecs_b and the second half in second_vecs_b. This routine simply joins these vectors pairs and
// returns 'challenges_b'.
// *** VEC_CHLNG ***
challenges_b = ConvertVecsToChallenge(max_string_len, num_vecs, num_PIs, first_vecs_b, second_vecs_b, num_chlng_bits);
// Vectors are requested as needed by the CollectPNs.vhd routine (no internal vector storage).
generated_device_num_n1_bytes = 0;
// Nasty BUG 6_3_2016 here -- VHDL was setting IN_SM_DONE_ALL_VECS BEFORE the last potential NONCE byte was generated and was hanging the
// VHDL/C code.
vec_num = 0;
while ( ((*DataRegA) & (1 << IN_SM_DONE_ALL_VECS)) == 0 )
{
// Transfer a vector to VHDL registers once it is requested. NOTE: It is the responsibility of the verifier to provide exactly enough rising vectors
// to supply 2048 rising PNs (falling vectors don't really matter since we exit this loop when CollectPNs indicates that it has all the timing
// values it needs). There can be more than 2048 rising PNs but once the limit is exceeded, no more rising vectors should be applied, i.e., the
// next vector MUST be a falling vector.
if ( ((*DataRegA) & (1 << IN_SM_LOAD_VEC_PAIR)) != 0 )
{
#ifdef DEBUG
printf("CollectPNs(): CPN ready %d\tPNDiff ready %d\tSHD_BG ready %d\tLM_ULM ready %d\tGPEVCAL ready %d\tDONE ALL VECS %d\n",
((*DataRegA) & (1 << IN_DEBUG_CPN_READY)) >> IN_DEBUG_CPN_READY,
((*DataRegA) & (1 << IN_DEBUG_PNDIFF_READY)) >> IN_DEBUG_PNDIFF_READY,
((*DataRegA) & (1 << IN_DEBUG_SHD_BG_READY)) >> IN_DEBUG_SHD_BG_READY,
((*DataRegA) & (1 << IN_DEBUG_LM_ULM_READY)) >> IN_DEBUG_LM_ULM_READY,
((*DataRegA) & (1 << IN_DEBUG_GPEVCAL_READY)) >> IN_DEBUG_GPEVCAL_READY,
((*DataRegA) & (1 << IN_SM_DONE_ALL_VECS)) >> IN_SM_DONE_ALL_VECS
); fflush(stdout);
#endif
// Sanity check
if ( vec_num == num_vecs )
{
printf("ERROR: CollectPNs(): Request for vec %d BEYOND largest available!\n", vec_num);
// Check for errors in overflow
if ( ((*DataRegA) & (1 << IN_PNDIFF_OVERFLOW_ERR)) != 0 )
printf("ERROR: CollectPNs(): PN Overflow error in hardware!\n");
exit(EXIT_FAILURE);
}
// *** VEC_CHLNG ***
LoadChlngAndMask(max_string_len, CtrlRegA, DataRegA, vec_num, challenges_b, ctrl_mask, num_chlng_bits, vec_chunk_size,
has_masks, num_POs, masks_b);
#ifdef DEBUG
PrintHeaderAndBinVals("", num_POs, masks_b[vec_num], 32);
#endif
#ifdef DEBUG
printf("Loaded challenge %d\n", vec_num); fflush(stdout);
#endif
vec_num++;
}
// While PNs are being generated, I simultaneously generate Nonce bytes. Variable number so be sure the array is large enough.
// Keep checking 'stopped' until the next vector request or the PN termination condition is met. WARNING: SECOND CONDITION
// MUST BE HERE OTHERWISE THIS MAY END UP 'stealing' A HD BYTE. If you see an error below 'PROGRAM ERROR: Expected helper data num
// bytes to be 256 -- READ 255 instead!', then this stole a byte.
if ( ((*DataRegA) & (1 << IN_SM_HANDSHAKE)) != 0 && ((*DataRegA) & (1 << IN_SM_DONE_ALL_VECS)) == 0 )
{
// BYTE-TO-WORD
if ( generated_device_num_n1_bytes + 1 >= max_generated_nonce_bytes )
{ printf("WARNING: Too many nonce bytes generated by hardware -- increase array size in program!\n"); fflush(stdout); }
// 7/1/2017: Note: In VHDL, I consistently fill in 16-bit words from low-order to high order so this makes the most sense, i.e., to
// read the low-order byte first (and store in a lower address) and then the high order byte. Note that when the number of bits is
// NOT a multiple of 8, we need to eliminate high order bits in the last byte.
else
{
device_n1[generated_device_num_n1_bytes] = (unsigned char)((*DataRegA) & 0x000000FF);
generated_device_num_n1_bytes++;
device_n1[generated_device_num_n1_bytes] = (unsigned char)(((*DataRegA) & 0x0000FF00) >> 8);
generated_device_num_n1_bytes++;
}
#ifdef DEBUG
printf("Got nonce word (16-bits) -- current number of nonce bytes %d\n", generated_device_num_n1_bytes); fflush(stdout);
#endif
*CtrlRegA = ctrl_mask | (1 << OUT_CP_HANDSHAKE);
while ( ((*DataRegA) & (1 << IN_SM_HANDSHAKE)) != 0 );
*CtrlRegA = ctrl_mask;
}
}
if ( vec_num != num_vecs )
{ printf("WARNING: CollectPNs(): NOT ALL VECTORS were processed: Processed only %d of %d!\n", vec_num, num_vecs); fflush(stdout); }
// Be sure control mask is restored after vector transfer is complete.
*CtrlRegA = ctrl_mask;
// EITHER THIS BE INCLUDED OR THE STUFF IN THE DEBUG statement DIRECTLY BELOW WHILE THE DEBUG code exists in the bitstream.
#ifdef DEBUG
while ( ((*DataRegA) & (1 << IN_SM_HANDSHAKE)) == 0 );
*CtrlRegA = ctrl_mask | (1 << OUT_CP_HANDSHAKE);
while ( ((*DataRegA) & (1 << IN_SM_HANDSHAKE)) != 0 );
*CtrlRegA = ctrl_mask | (1 << OUT_CP_LM_ULM_DONE);
*CtrlRegA = ctrl_mask;
#endif
#ifdef DEBUG
int PNs_stored[4096];
int i;
for ( i = 0; i < 4096; i++ )
{
while ( ((*DataRegA) & (1 << IN_SM_HANDSHAKE)) == 0 );
PNs_stored[i] = (int)((*DataRegA) & 0x0000FFFF);
printf("%4d) %9.4f\n", i, (float)PNs_stored[i]/16); fflush(stdout);
*CtrlRegA = ctrl_mask | (1 << OUT_CP_HANDSHAKE);
while ( ((*DataRegA) & (1 << IN_SM_HANDSHAKE)) != 0 );
if ( i == 4095 )
*CtrlRegA = ctrl_mask | (1 << OUT_CP_LM_ULM_DONE);
else
*CtrlRegA = ctrl_mask;
}
// Deassert 'DONE'
*CtrlRegA = ctrl_mask;
#endif
// Print out the nonces if requested
if ( DUMP_BITSTRINGS == 1 )
{
char header_str[max_string_len];
sprintf(header_str, "\n\tGenerated Device nonces n1:\n");
PrintHeaderAndHexVals(header_str, generated_device_num_n1_bytes, device_n1, 32);
}
if ( debug_flag == 1 )
{ gettimeofday(&t1, 0); elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec; printf("\tElapsed %ld us\n\n", (long)elapsed); }
fflush(stdout);
// Free up the challenges_b.
// *** VEC_CHLNG ***
for ( vec_num = 0; vec_num < num_vecs; vec_num++ )
if ( challenges_b[vec_num] != NULL )
free(challenges_b[vec_num]);
// Check for errors in overflow
if ( ((*DataRegA) & (1 << IN_PNDIFF_OVERFLOW_ERR)) != 0 )
{ printf("ERROR: CollectPNs(): PN Overflow error in hardware!\n"); exit(EXIT_FAILURE); }
#ifdef DEBUG
printf("CollectPNs(): CPN ready %d\tPNDiff ready %d\tSHD_BG ready %d\tLM_ULM ready %d\tGPEVCAL ready %d\tDONE ALL VECS %d\n",
((*DataRegA) & (1 << IN_DEBUG_CPN_READY)) >> IN_DEBUG_CPN_READY,
((*DataRegA) & (1 << IN_DEBUG_PNDIFF_READY)) >> IN_DEBUG_PNDIFF_READY,
((*DataRegA) & (1 << IN_DEBUG_SHD_BG_READY)) >> IN_DEBUG_SHD_BG_READY,
((*DataRegA) & (1 << IN_DEBUG_LM_ULM_READY)) >> IN_DEBUG_LM_ULM_READY,
((*DataRegA) & (1 << IN_DEBUG_GPEVCAL_READY)) >> IN_DEBUG_GPEVCAL_READY,
((*DataRegA) & (1 << IN_SM_DONE_ALL_VECS)) >> IN_SM_DONE_ALL_VECS
); fflush(stdout);
#endif
return generated_device_num_n1_bytes;
}
// ========================================================================================================
// ========================================================================================================
// Get verifier nonce, XOR with device nonce, send XOR nonce to verifier.
void NonceExchange(int max_string_len, int verifier_socket_desc, int num_required_nonce_bytes,
unsigned char *device_n1, int num_device_n1_nonces, unsigned char *verifier_n2, unsigned char *XOR_nonce,
int DUMP_BITSTRINGS, int debug_flag)
{
int i;
struct timeval t0, t1;
long elapsed;
// Sanity check.
if ( num_device_n1_nonces < num_required_nonce_bytes )
printf("WARNING: NonceExchange(): Hardware NONCE generation did not return enough binary bytes: returned %d require %d!\n",
num_device_n1_nonces, num_required_nonce_bytes);
// ****************************************
// ***** Receive nonce n2 from verifier
if ( debug_flag == 1 )
{
printf("NExch.1) Receiving verifier nonce n2\n");
gettimeofday(&t0, 0);
}
if ( SockGetB(verifier_n2, num_required_nonce_bytes, verifier_socket_desc) != num_required_nonce_bytes )
{ printf("ERROR: NonceExchange(): 'verifier_n2' bytes received is not equal to %d\n", num_required_nonce_bytes); exit(EXIT_FAILURE); }
if ( debug_flag == 1 )
{ gettimeofday(&t1, 0); elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec; printf("\tElapsed %ld us\n\n", (long)elapsed); }
// DEBUG: Dump out the values as hex
if ( debug_flag == 1 )
{
char header_str[max_string_len];
sprintf(header_str, "\tReceived Verifier nonces n2 (high to low):\n");
PrintHeaderAndHexVals(header_str, num_required_nonce_bytes, verifier_n2, 8);
}
// ****************************************
// ***** Create XOR nonce
if ( debug_flag == 1 )
{
printf("NExch.2) Creating XOR nonce (n1 XOR n2)\n");
gettimeofday(&t0, 0);
}
for ( i = 0; i < num_required_nonce_bytes; i++ )
XOR_nonce[i] = device_n1[i] ^ verifier_n2[i];
if ( debug_flag == 1 )
{ gettimeofday(&t1, 0); elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec; printf("\tElapsed %ld us\n\n", (long)elapsed); }
// Print out the final XOR nonce if requested
if ( DUMP_BITSTRINGS == 1 )
{
char header_str[max_string_len];
sprintf(header_str, "\tSending device XOR nonces (n1 XOR n2), high to low:\n");
PrintHeaderAndHexVals(header_str, num_required_nonce_bytes, XOR_nonce, 8);
}
// ****************************************
// ***** Send the XOR nonce (n1 XOR n2) to the verifier
if ( debug_flag == 1 )
{
printf("NExch.3) Sending XOR nonce (n1 XOR n2)' \n");
gettimeofday(&t0, 0);
}
if ( SockSendB(XOR_nonce, num_required_nonce_bytes, verifier_socket_desc) < 0 )
{ printf("ERROR: NonceExchange(): Send 'XOR_nonce' failed\n"); exit(EXIT_FAILURE); }
if ( debug_flag == 1 )
{ gettimeofday(&t1, 0); elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec; printf("\tElapsed %ld us\n\n", (long)elapsed); }
fflush(stdout);
return;
}
// ========================================================================================================
// ========================================================================================================
// Convenience function that sets the PN reuse flag in the hardware, restarts the SRF engine and then sends
// a request to the server for more SpreadFactors if SpreadFactor mode is pop or pop+perchip
void SetSRFReuseModeStartSRFRequestSpreadFactors(int max_string_len, SRFHardwareParamsStruct *SHP_ptr,
int do_server_SpreadFactors_next, int verifier_socket_desc)
{
char request_str[max_string_len];
struct timeval t0, t1;
long elapsed;
// Sanity check. PUF engine MUST be 'ready'
if ( (*(SHP_ptr->DataRegA) & (1 << IN_SM_READY)) == 0 )
{ printf("ERROR: SetSRFReuseModeStartSRFRequestSpreadFactors(): PUF Engine is NOT ready!\n"); exit(EXIT_FAILURE); }
// Re-start the PUF engine with the next LFSR seed. NOTE: This is not confirmed via a handshake, which it should be. Adding a usleep to make
// sure a 'slow' version of the hardware state machine sees the start signal.
SHP_ptr->ctrl_mask = SHP_ptr->ctrl_mask | (1 << OUT_CP_REUSE_PNS_MODE);
// Start SRF
*(SHP_ptr->CtrlRegA) = SHP_ptr->ctrl_mask | (1 << OUT_CP_PUF_START);
usleep(1000);
*(SHP_ptr->CtrlRegA) = SHP_ptr->ctrl_mask;
#ifdef DEBUG
printf("SetSRFReuseModeStartSRFRequestSpreadFactors(): RESTARTING PUF(): Sending SpreadFactors request!\n"); fflush(stdout);
#endif
// Tell server we need more SpreadFactors
if ( do_server_SpreadFactors_next == 1 )
{
strcpy(request_str, "SPREAD_FACTORS NEXT");
if ( SHP_ptr->DEBUG_FLAG == 1 )
{
printf("\tSending '%s'\n", request_str);
gettimeofday(&t0, 0);
}
if ( SockSendB((unsigned char *)request_str, strlen(request_str)+1, verifier_socket_desc) < 0 )
{ printf("ERROR: Send '%s' request failed\n", request_str); exit(EXIT_FAILURE); }
if ( SHP_ptr->DEBUG_FLAG == 1 )
{ gettimeofday(&t1, 0); elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec; printf("\tTOTAL EXEC TIME %ld us\n\n", (long)elapsed); }
}
#ifdef DEBUG
printf("SetSRFReuseModeStartSRFRequestSpreadFactors(): Sent SpreadFactors REQUEST -- returning!\n"); fflush(stdout);
#endif
return;
}
// ========================================================================================================
// ========================================================================================================
// Convenience function that simply sends 'done' request to server to stop computing and sending SpreadFactors.
void SendSpreadFactorsDone(int max_string_len, SRFHardwareParamsStruct *SHP_ptr, int verifier_socket_desc)
{
char request_str[max_string_len];
struct timeval t0, t1;
long elapsed;
strcpy(request_str, "SPREAD_FACTORS DONE");
if ( SHP_ptr->DEBUG_FLAG == 1 )
{
printf("\tSending '%s'\n", request_str);
gettimeofday(&t0, 0);
}
if ( SockSendB((unsigned char *)request_str, strlen(request_str)+1, verifier_socket_desc) < 0 )
{ printf("ERROR: Send '%s' request failed\n", request_str); exit(EXIT_FAILURE); }
if ( SHP_ptr->DEBUG_FLAG == 1 )
{ gettimeofday(&t1, 0); elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec; printf("\tTOTAL EXEC TIME %ld us\n\n", (long)elapsed); }
return;
}
// ========================================================================================================
// ========================================================================================================
// Get SpreadFactors from verifier. NOTE: This function is NOT called if current_function is DA or LL_Enroll
// and PBD mode is requested.
void GetSpreadFactors(int max_string_len, int num_SF_words, int num_SF_bytes, int verifier_socket_desc,
signed char *iSpreadFactors, int iSpreadFactorScaler, int current_function, int debug_flag)
{
int PND_num;
#ifdef DEBUG
printf("GetSpreadFactor(): CALLED\tFunction %d! (If called, we are retrieving SF of some type!)\n", current_function); fflush(stdout);
#endif
#ifdef DEBUG
int limit = 20;
#endif
struct timeval t0, t1;
long elapsed;
// Make sure iSpreadFactors is all zeros
for ( PND_num = 0; PND_num < num_SF_words; PND_num++ )
iSpreadFactors[PND_num] = 0;
// Get Population SpreadFactors from the verifier
if ( debug_flag == 1 )
{
printf("CO.1) Receiving SpreadFactors\n");
gettimeofday(&t0, 0);
}
if ( SockGetB((unsigned char *)iSpreadFactors, num_SF_bytes, verifier_socket_desc) != num_SF_bytes )
{ printf("ERROR: GetSpreadFactors(): 'SpreadFactor' bytes received is not equal to %d\n", num_SF_bytes); exit(EXIT_FAILURE); }
if ( debug_flag == 1 )
PrintHeaderAndHexVals((char *)"SpreadFactors:\n", num_SF_bytes, (unsigned char *)iSpreadFactors, 64);
if ( debug_flag == 1 )
{ gettimeofday(&t1, 0); elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec; printf("\tElapsed %ld us\n\n", (long)elapsed); }
fflush(stdout);
#ifdef DEBUG
printf("GetSpreadFactors(): num_SF_words %d\tnum_SF_bytes %d\n", num_SF_words, num_SF_bytes); fflush(stdout);
for ( PND_num = 0; PND_num < limit; PND_num++ )
printf("%4d)\tiSpreadFactors %+4d\tfSpreadFactors (DIV %d) %+9.4f\n", PND_num, iSpreadFactors[PND_num], iSpreadFactorScaler,
(float)iSpreadFactors[PND_num]/iSpreadFactorScaler);
#endif
#ifdef DEBUG
printf("GetSpreadFactor(): DONE!\n"); fflush(stdout);
#endif
return;
}
// ========================================================================================================
// ========================================================================================================
// Select and then transfer parameters to hardware. 'target_attempts' is used to increment the first LFSR
// seed (canNOT increment both otherwise we get the same sequence SpreadConstant by 1). When this routine called
// repeatedly to generate a 'target_num_key_bits', we use the same parameters except for the seeds.
//
// 10_17_2021: Added flags in hardware (3 more parameters) to do control options for the functions (from log pp. 6062).
// Load_SF: 1 when SFs need to be loaded
// computeSF: 1 when SFs need to be computed by the device
// PCR_PBD_PO mode: 0, 1 or 2 to indicate mode
// modify_PO mode: 1 when PO offsets loaded need to be modified to do inversion
// FUNC_DA FUNC_VA FUNC_SE LL_Enroll LL_Regen TRNG
// PO PCR PBD PO PCR PBD PO PCR PBD PO PCR PBD PO PCR PBD PO PCR PBD
// =======================================================================================================================
// SF: PO PO None PO PCR PBD PO PCR PBD PO PO None PO PCR PBD None None None
// ASF1: Y Y N Y Y Y Y Y Y Y Y N Y Y Y N N N
// Load_SF
//
// ASF2: N Y Y N N N N N N N Y Y N N N Y Y Y
// compute_PCR_PBD
//
// PCR_PBD_PO 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 1 1 1
// modify_PO Y Y N* N N N N N N Y Y N* N N N N N N
// dump_updated_SF Y Y Y N N N N N N Y Y Y N N N N N N
//
// * means setting this is irrelevant b/c PO SF are NOT loaded.
void SelectSetParams(int max_string_len, int num_required_PNDiffs, volatile unsigned int *CtrlRegA,
volatile unsigned int *DataRegA, unsigned int ctrl_mask, int num_required_nonce_bytes, int nonce_base_address,
unsigned char *XOR_nonce, unsigned int target_attempts, int force_threshold_zero, int fix_params,
unsigned int RangeConstant, unsigned short SpreadConstant, unsigned short Threshold, unsigned short TrimCodeConstant,
unsigned int ScalingConstant, int XMR_val, int num_KEK_authen_nonce_bits_remaining, int load_SF, int compute_PCR_PBD,
int modify_SF, int dump_updated_SF, int param_PCR_or_PBD_or_PO, int current_function, unsigned int *LFSR_seed_low_ptr,
unsigned int *LFSR_seed_high_ptr, int do_scaling, int debug_flag)
{
unsigned int LFSR_seed_low, LFSR_seed_high;
int num_params, param_num;
struct timeval t0, t1;
long elapsed;
num_params = 14;
// ****************************************
// ***** Select parameter values
if ( debug_flag == 1 )
{
printf("SPrms.1) Selecting parameters\n");
gettimeofday(&t0, 0);
}
// NOTE: WE DO NOT CHANGE RangeConstant, SpreadConstant, Threshold or TrimCodeConstant formal parameters above in this routine
// since I need to set RangeConstant to specific value in the Device Authentication functions.
if ( fix_params == 0 )
SelectParams(num_required_nonce_bytes, XOR_nonce, nonce_base_address, &LFSR_seed_low, &LFSR_seed_high, &RangeConstant,
&SpreadConstant, &Threshold, &TrimCodeConstant);
// If user wants to 'fix the parameters'
else
{
LFSR_seed_low = FIXED_LFSR_SEED_LOW;
LFSR_seed_high = FIXED_LFSR_SEED_HIGH;
RangeConstant = FIXED_RANGE_CONSTANT;
SpreadConstant = FIXED_SPREAD_CONSTANT;
Threshold = FIXED_THRESHOLD;
TrimCodeConstant = FIXED_TRIMCODE_CONSTANT;
// The equivalent of 1.0 (1 << SCALING_PRECISION_NB)
ScalingConstant = FIXED_SCALING_CONSTANT;
}
// 10_28_2022: Force Scaling Constant to 1 (which will prevent it from being used in the Verilog code) for PCR and PBD mode.
// It is NOT needed here because it REPLACES PCR mode and PBD uses low order integer bit to determine bit value.
// 11_12_2022: Added a 'do_scaling' flag. If this is 0, disable scaling. Set to 1 in the calling function. Currently this
// is done for COBRA and possibly for PARCE (SKE). It is 0 by default which forces a 1.0 for scaling, disabling it.
if ( do_scaling == 0 ) // || param_PCR_or_PBD_or_PO != SF_MODE_POPONLY )
{
// Cannot use 0.0 here -- it is a hardware parameter error. Using (scaled) 1.0 as the factor SKIPS any scaling in the hardware.
ScalingConstant = (1 << SCALING_PRECISION_NB);
#ifdef DEBUG
printf("SelectSetParams(): Mode is NOT PopOnly -- FORCING ScalingConstant to 1.0 => FixedPoint should be (1 << %d): %d!\n", SCALING_PRECISION_NB, ScalingConstant); fflush(stdout);
#endif
}
else
{
#ifdef DEBUG
printf("SelectSetParams(): PopOnly MODE -- Using ScalingConstant (FixedPoint) %d!\n", ScalingConstant); fflush(stdout);
#endif
}
if ( debug_flag == 1 )
{ gettimeofday(&t1, 0); elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec; printf("\tElapsed %ld us\n\n", (long)elapsed); }
// For iterating until we reach a 'target_num_key_bits'. Assume same 'XOR_nonce' bytes are used repeatedly. Just increment the first LFSR seed
// (do NOT increment BOTH otherwise you get the same sequence).
LFSR_seed_high = (LFSR_seed_high + target_attempts) % num_required_PNDiffs;
if ( force_threshold_zero == 1 )
Threshold = 0;
*LFSR_seed_low_ptr = LFSR_seed_low;
*LFSR_seed_high_ptr = LFSR_seed_high;
#ifdef DEBUG
printf("\tLFSR low %4u high %4u RC %3d SC %3d TH %2u TCC %2u SCC %5d XMR %2d Auth bits left %3d PCR/PBD/PO %d Load SF %d CompPCR/PBD %d Mod SF %d Dump SF %d\n",
LFSR_seed_low, LFSR_seed_high, RangeConstant, SpreadConstant, Threshold, TrimCodeConstant, ScalingConstant, XMR_val, num_KEK_authen_nonce_bits_remaining, param_PCR_or_PBD_or_PO,
load_SF, compute_PCR_PBD, modify_SF, dump_updated_SF); fflush(stdout);
#endif
// ****************************************
// ***** Transfer parameters into hardware.
if ( debug_flag == 1 )
{
printf("SPrms.2) Transferring params to hardware\n");
gettimeofday(&t0, 0);
}
// Wait for hardware to ask for first parameter. 4/28/2018: THIS USED TO BE A 'for loop' -- NO GOOD!!!!!! Made it a while loop.
// Must have been 'just getting lucky' in the past.
param_num = 0;
while ( param_num < num_params )
{
int out_val;
// NOTE: RangeConstant is an unsigned integer no bigger than the number of hardware bits in PNL_BRAM for the integer portion, i.e., 11 bits can hold
// (-1023 to +1023).
if ( ((*DataRegA) & (1 << IN_SM_HANDSHAKE)) != 0 )
{
if ( param_num == 0 )
out_val = LFSR_seed_low;
else if ( param_num == 1 )
out_val = LFSR_seed_high;
else if ( param_num == 2 )
out_val = RangeConstant;
else if ( param_num == 3 )
out_val = SpreadConstant;
else if ( param_num == 4 )
out_val = Threshold;
else if ( param_num == 5 )
out_val = XMR_val;
else if ( param_num == 6 )
out_val = num_KEK_authen_nonce_bits_remaining;
else if ( param_num == 7 )
{
// We MUST force PBD off unless we are doing DA and LL_ENROLL enrollment functions (NOTE: we also force PBD mode for the TRNG modes but that is done within
// the Verilog code). THIS ONLY determines if we run AddSpreadFactors in PCR or PBD mode in the hardware. compute_PCR_PBD controls whether we use PopOnly
// SF or not in the hardware. Here in the software, we use this parameter to determine if the user wants PopOnly (PO) and set 'compute_PCR_PBD' appropriately.
// NOTE: In the hardware, we use ONLY the low order bit of param_PCR_or_PBD_or_PO to determine PCR or PBD mode so when set to 2 for PopOnly, we would run
// PCR mode. HOWEVER, the hardware does NOT run AddSpreadFactors.v unless 'compute_PCR_PBD' is 1, which will NOT be the case if we are using PopOnly SF.
if ( current_function == FUNC_DA || current_function == FUNC_LL_ENROLL )
out_val = param_PCR_or_PBD_or_PO;
else
out_val = 0;
}
else if ( param_num == 8 )
out_val = load_SF;
else if ( param_num == 9 )
out_val = compute_PCR_PBD;
else if ( param_num == 10 )
out_val = modify_SF;
else if ( param_num == 11 )
out_val = dump_updated_SF;
else if ( param_num == 12 )
out_val = TrimCodeConstant;
else
out_val = ScalingConstant;
// 'OR' in the value into the low order 16 bits preserving the signed/unsigned nature of the value.
*CtrlRegA = ctrl_mask | (1 << OUT_CP_HANDSHAKE) | (0x0000FFFF & out_val);
while ( ((*DataRegA) & (1 << IN_SM_HANDSHAKE)) != 0 );
*CtrlRegA = ctrl_mask;
param_num++;
}
}
usleep(1000);
if ( ((*DataRegA) & (1 << IN_PARAM_ERR)) != 0 )
{ printf("ERROR: SelectSetParams(): Parameter error in hardware!\n"); exit(EXIT_FAILURE); }
if ( debug_flag == 1 )
{ gettimeofday(&t1, 0); elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec; printf("\tElapsed %ld us\n\n", (long)elapsed); }
fflush(stdout);
return;
}
// ========================================================================================================
// ========================================================================================================
// Load BRAM with data. We ALWAYS read or write 16-bit words from BRAM. If 'byte_or_word_data' is 0, then
// we use the ByteData array (8-bits each byte) and load a 16-bit word in the low-order byte to high_order
// byte order, i.e., low order byte of 16-bit word goes into byte 0, high order byte of 16-bit word goes
// into byte 1, etc. WE MUST INCREMENT val_num (the index into ByteData) BY 2, NOT 1. When 'byte_or_word_data'
// is 1, we transfer 16-bits to 16-bits. NOTE: I switched the meaning of 'byte_or_word' from the old code
// here.
void LoadUnloadBRAM(int max_string_len, int num_vals, volatile unsigned int *CtrlRegA, volatile unsigned int *DataRegA,
unsigned int ctrl_mask, unsigned char *ByteData, signed short *WordData, int load_or_unload, int byte_or_word_data,
int debug_flag)
{
int val_num, locked_up, increment;
// BYTE-TO-WORD
// Sanity check. When byte_or_word_data is 0, then we are transferring in byte data two bytes at-a-time, i.e., we transfer 16-bits at a time
// into the PL side so ensure num_vals is an even number.
if ( byte_or_word_data == 0 && (num_vals % 2) != 0 )
{ printf("ERROR: LoadUnloadBRAM(): 'num_vals' MUST BE an even number for ByteData transfers to BRAM!\n"); exit(EXIT_FAILURE); }
// ****************************************
// ***** Load BRAM with data
if ( debug_flag == 1 )
{
if ( load_or_unload == 0 )
printf("LB.1) Loading BRAM: Number of values to load %d\n", num_vals);
else
printf("LB.1) UnLoading BRAM: Number of values to unload %d\n", num_vals);
}
if ( byte_or_word_data == 0 )
increment = 2;
else
increment = 1;
for ( val_num = 0; val_num < num_vals; val_num += increment )
{
#ifdef DEBUG
printf("%4d) Load/unload %d\t\n", val_num, load_or_unload); fflush(stdout);
#endif
// Wait for 'stopped' from hardware to be asserted, which indicates that the hardware is ready to receive a byte.
locked_up = 0;
while ( ((*DataRegA) & (1 << IN_SM_HANDSHAKE)) == 0 )
{
locked_up++;
if ( locked_up > 10000000 )
{
printf("ERROR: LoadUnloadBRAM(): 'stopped' has not been asserted for the threshold number of cycles -- Locked UP?\n");
fflush(stdout);
locked_up = 0;
}
}
// Put the data bytes into the register and assert 'continue' (OUT_CP_HANDSHAKE). iSpreadFactors are loaded one in each 16-bit word of PNL BRAM, so
// byte_or_word_data is set to 1 for SpreadFactor loads/unloads
if ( load_or_unload == 0 )
{
if ( byte_or_word_data == 0 )
*CtrlRegA = ctrl_mask | (1 << OUT_CP_HANDSHAKE) | (0x000000FF & ByteData[val_num]) | (0x0000FF00 & (ByteData[val_num+1] << 8));
else
*CtrlRegA = ctrl_mask | (1 << OUT_CP_HANDSHAKE) | (0x0000FFFF & WordData[val_num]);
}
// When 'stopped' is asserted, the data is ready on the output register from the PNL BRAM -- get it.
else
{
if ( byte_or_word_data == 0 )
{
ByteData[val_num] = (0x000000FF & *DataRegA);
ByteData[val_num+1] = ((0x0000FF00 & *DataRegA) >> 8);
}
else
WordData[val_num] = (0x0000FFFF & *DataRegA);
*CtrlRegA = ctrl_mask | (1 << OUT_CP_HANDSHAKE);
}
// Wait for hardware to de-assert 'stopped' (it got the byte).
while ( ((*DataRegA) & (1 << IN_SM_HANDSHAKE)) != 0 );
// De-assert 'continue'. ALSO, assert 'done' (OUT_CP_LM_ULM_DONE) SIMULTANEOUSLY to tell hardware this is the last word.
if ( val_num == num_vals - increment )
*CtrlRegA = ctrl_mask | (1 << OUT_CP_LM_ULM_DONE);
else
*CtrlRegA = ctrl_mask;
}
// Handle case where 'num_vals' is 0.
if ( num_vals == 0 )
*CtrlRegA = ctrl_mask | (1 << OUT_CP_LM_ULM_DONE);
// De-assert 'OUT_CP_LM_ULM_DONE'
*CtrlRegA = ctrl_mask;
fflush(stdout);
return;
}
// ========================================================================================================
// ========================================================================================================
// Run the SRF engine, all processes including PNDiffs, GPEVCal, Load/AddSpreadFactors.
//#define DEBUG2 1
void RunSRFEngine(int max_string_len, int num_SF_words, volatile unsigned int *CtrlRegA,
volatile unsigned int *DataRegA, unsigned int ctrl_mask, signed char *iSpreadFactors,
int iSpreadFactorScaler, int current_function, int load_SF, int dump_updated_SF, int debug_flag)
{
int load_or_unload, byte_or_word_data;
struct timeval t0, t1;
long elapsed;
signed short *sSpreadFactors;
int SF_num;
float fSF;
// Sanity check. WARNING: THIS VARIABLE MUST BE SET TO 2 or 1.
if ( iSpreadFactorScaler != 1 && iSpreadFactorScaler != 2 )
{ printf("ERROR: RunSRFEngine(): iSpreadFactorScaler MUST BE set to 1 or 2!\n"); exit(EXIT_FAILURE); }
if ( (sSpreadFactors = (signed short *)calloc(num_SF_words, sizeof(signed short))) == NULL )
{ printf("ERROR: RunSRFEngine(): Failed to allocate storage for sSpreadFactors!\n"); exit(EXIT_FAILURE); }
#ifdef DEBUG2
int limit = 20;
#endif
// ****************************************
// ***** SRF engine starts once last param is loaded
if ( debug_flag == 1 )
printf("HE.1) Running PNDiff and GPEVCal\n\n");
// ****************************************
// ***** Load SpreadFactors. NOTE: THIS MUST BE DONE AFTER GPEVCal since the SpreadFactors are loaded in the same portion of memory.
if ( debug_flag == 1 )
{
printf("HE.2) Loading SpreadFactors\n");
gettimeofday(&t0, 0);
}
// Load up the server's PopSF when ((DA or LL_Enroll) and PCR) or any mode when Verifier Authentication, Session Key Gen or KEK Regeneration.
// 'num_SF_words' MUST be an even number. iSpreadFactors are loaded into a 16-bit word of PNL BRAM. Use the 'word' mode transfer for
// LoadUnloadBRAM. Do NOT load anything if ((DA or LL_Enroll) and PCB) or for either of the TRNG modes (which currently do NOT call RunSRFEngine
// so not needed really).
if ( load_SF == 1)
{
load_or_unload = 0;
byte_or_word_data = 1;
// With the conversion of SF to (signed char), I need to convert them here from (signed char) to (signed short) with the proper number of binary
// precision (we are using 4 binary digits of precision in the hardware). When the TrimCodeConstant is <= 32, the server preserves 1 binary decimal
// place in the (signed char) SF, otherwise NONE are preserved. So iSpreadFactorScaler is set to 2 when TrimCodeConstant <= 32 and 1 otherwise.
// Multiply the iSpreadFactors by 8 when iSpreadFactorScaler is 2, which adds three low order binary 0s to the sSpreadFactors.
// Multiply the iSpreadFactors by 16 when iSpreadFactorScaler is 1, which adds four low order binary 0s to the sSpreadFactors.
// i.e., 4 - 2 + 1 = 3, shift by 3 or multiply by 8, or 4 - 1 + 1 = 4, which is multiply by 16.
// NOTE: The verifier has already trimmed off the lower order precision bits and rounded appropriately.
for ( SF_num = 0; SF_num < num_SF_words; SF_num++ )
sSpreadFactors[SF_num] = (signed short)iSpreadFactors[SF_num] << (4 - iSpreadFactorScaler + 1);
LoadUnloadBRAM(max_string_len, num_SF_words, CtrlRegA, DataRegA, ctrl_mask, NULL, sSpreadFactors, load_or_unload, byte_or_word_data, debug_flag);
if ( debug_flag == 1 )
{ gettimeofday(&t1, 0); elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec; printf("\tElapsed %ld us\n\n", (long)elapsed); }
#ifdef DEBUG2
int i;
for ( i = 0; i < limit; i++ )
printf("%d)\tServer iSF %3d\tSHIFT RIGHT %d: fSF %9.4f\n", i, iSpreadFactors[i], (4 - iSpreadFactorScaler + 1), (float)sSpreadFactors[i]/16.0);
fflush(stdout);
#endif
}
#ifdef DEBUG
PrintHeaderAndHexVals("RunSRFEngine(): Pop. SpreadFactors (INPUT):\n", num_SF_words*SF_WORDS_TO_BYTES_MULT, (unsigned char *)iSpreadFactors, 32);
#endif
// Get computed PCR/PBD SpreadFactors from hardware engine if requested, overwriting the PopSF sent by the server earlier in the case of PCR (always done for
// DA or LL_Enroll mode).
// if ( current_function == FUNC_DA || current_function == FUNC_LL_ENROLL )
if ( dump_updated_SF == 1 )
{
#ifdef DEBUG2
printf("\nRunSRFEngine(): Getting updated SF\n"); fflush(stdout);
#endif
load_or_unload = 1;
byte_or_word_data = 1;
LoadUnloadBRAM(max_string_len, num_SF_words, CtrlRegA, DataRegA, ctrl_mask, NULL, sSpreadFactors, load_or_unload, byte_or_word_data, debug_flag);
// With the conversion of SF to (signed char), I need to convert them here from (signed short) to (signed char) with the proper number of binary
// precision (we are using 4 binary digits of precision in the hardware). When the TrimCodeConstant is <= 32, we can preserve 1 binary decimal
// place in the (signed char) SF, otherwise NONE are preserved. So iSpreadFactorScaler is set to 2 when TrimCodeConstant <= 32 and 1 otherwise.
for ( SF_num = 0; SF_num < num_SF_words; SF_num++ )
{
// First convert the (signed short) SF computed by the hardware to float, and then do the same conversion as we do in verifer_regen_funcs.
// Round off appropriately. With iSpreadFactorScaler at 2, and if I have 35.6875, then convert to 35.5000. But if I have 16.9375, convert to 17.000
// (anything larger than 16.75 should be 17.0, Anything larger than 16.25 should be 16.5, etc). Similarly, with iSpreadFactorScaler at 1,
// than anything larger than 16.5 should be 17, etc. NOTE: Use 0.5 here for all cases, i.e., when iSpreadFactorScaler is 2, we need to add 0.5 and
// NOT 0.25!
fSF = (float)sSpreadFactors[SF_num]/16.0;
if ( sSpreadFactors[SF_num] >= 0 )
iSpreadFactors[SF_num] = (signed char)(fSF * (float)iSpreadFactorScaler + 0.5);
else
iSpreadFactors[SF_num] = (signed char)(fSF * (float)iSpreadFactorScaler - 0.5);
// iSpreadFactors[SF_num] = (signed char)(sSpreadFactors[SF_num] >> (4 - iSpreadFactorScaler + 1));
}
#ifdef DEBUG
PrintHeaderAndHexVals("RunSRFEngine(): PCR (OUTPUT):\n", num_SF_words*SF_WORDS_TO_BYTES_MULT, (unsigned char *)iSpreadFactors, 32);
#endif
}
#ifdef DEBUG2
int i;
for ( i = 0; i < limit; i++ )
{
fSF = (float)sSpreadFactors[i]/16.0;
printf("Device fSF %9.4f\tiSF %4d\n", fSF, iSpreadFactors[i]);
}
fflush(stdout);
#endif
// ****************************************
// ***** Continue with PNDc
if ( debug_flag == 1 )
printf("HE.3) Running PNDc\n\n");
// ****************************************
// Check error flags. Should be done after full computation is completed but no way of knowing that at this point. Should be checked at the
// end of a function. 'PNDIFF' errors can result in PNs or PNDiffs exceeding max. GPEVCal includes errors related to failing to find the bounds
// of the distribution + parameter errors (range of 0)
usleep(1000);
if ( ((*DataRegA) & (1 << IN_PNDIFF_OVERFLOW_ERR)) != 0 )
{ printf("ERROR: RunSRFEngine(): PNDiff Overflow error in hardware!\n"); exit(EXIT_FAILURE); }
if ( ((*DataRegA) & (1 << IN_GPEVCAL_ERR)) != 0 )
{ printf("ERROR: RunSRFEngine(): GPEVCal Overflow error in hardware!\n"); exit(EXIT_FAILURE); }
fflush(stdout);
if ( sSpreadFactors != NULL )
free(sSpreadFactors);
//exit(EXIT_SUCCESS);
return;
}
// ========================================================================================================
// ========================================================================================================
// Convenience function that get SpreadFactors from server, selects parameters (LFSR_seed_low based on target_attempts),
// transfers the parameters to the Help engine and then loads the SpreadFactors and checks for hardware errors.
void GetSpreadFactorsSelectSetParamsRunSRF(int max_string_len, SRFHardwareParamsStruct *SHP_ptr, int target_attempts,
int force_threshold_zero, int current_function, int verifier_socket_desc)
{
// Get Pop SpreadFactors from Server. No SpreadFactors needed when function is DA or LL_Enroll under PBD mode.
if ( !((current_function == FUNC_DA || current_function == FUNC_LL_ENROLL) && SHP_ptr->param_PCR_or_PBD_or_PO == SF_MODE_PBD) )
GetSpreadFactors(max_string_len, SHP_ptr->num_SF_words, SHP_ptr->num_SF_bytes, verifier_socket_desc,
SHP_ptr->iSpreadFactors, SHP_ptr->iSpreadFactorScaler, current_function, SHP_ptr->DEBUG_FLAG);
// Select parameters based on the XOR_nonce and then transfer them into the hardware.
SelectSetParams(max_string_len, SHP_ptr->num_required_PNDiffs, SHP_ptr->CtrlRegA, SHP_ptr->DataRegA, SHP_ptr->ctrl_mask,
SHP_ptr->num_required_nonce_bytes, SHP_ptr->nonce_base_address, SHP_ptr->XOR_nonce, target_attempts, force_threshold_zero,
SHP_ptr->fix_params, SHP_ptr->param_RangeConstant, SHP_ptr->param_SpreadConstant, SHP_ptr->param_Threshold,
SHP_ptr->param_TrimCodeConstant, SHP_ptr->MyScalingConstant, SHP_ptr->XMR_val, SHP_ptr->num_KEK_authen_nonce_bits_remaining,
SHP_ptr->load_SF, SHP_ptr->compute_PCR_PBD, SHP_ptr->modify_PO, SHP_ptr->dump_updated_SF, SHP_ptr->param_PCR_or_PBD_or_PO,
current_function, &(SHP_ptr->param_LFSR_seed_low), &(SHP_ptr->param_LFSR_seed_high), SHP_ptr->do_scaling, SHP_ptr->DEBUG_FLAG);
// Run the SRF 'full comp' component, PNDiff, GPEVCal, LoadSpreadFactors (and retrieve SpreadFactors if Device Authentication).
RunSRFEngine(max_string_len, SHP_ptr->num_SF_words, SHP_ptr->CtrlRegA, SHP_ptr->DataRegA, SHP_ptr->ctrl_mask,
SHP_ptr->iSpreadFactors, SHP_ptr->iSpreadFactorScaler, current_function, SHP_ptr->load_SF, SHP_ptr->dump_updated_SF,
SHP_ptr->DEBUG_FLAG);
return;
}
// ========================================================================================================
// ========================================================================================================
// Function that transfers the authentication nonce into the SRF hardware for encoding with XMR_SHD within
// device authentication and for comparing with regenerated nonce within verifier authentication.
void TransferAuthenNonce(int max_string_len, SRFHardwareParamsStruct *SHP_ptr, unsigned char *nonce)
{
int load_or_unload, byte_or_word_data;
#ifdef DEBUG
printf("TransferAuthenNonce(): CALLED\n"); fflush(stdout);
#endif
load_or_unload = 0;
byte_or_word_data = 0;
LoadUnloadBRAM(max_string_len, SHP_ptr->num_KEK_authen_nonce_bits/8, SHP_ptr->CtrlRegA, SHP_ptr->DataRegA, SHP_ptr->ctrl_mask,
nonce, NULL, load_or_unload, byte_or_word_data, SHP_ptr->DEBUG_FLAG);
#ifdef DEBUG