-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathverifier_regeneration.c
2129 lines (1720 loc) · 103 KB
/
verifier_regeneration.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
// ========================================================================================================
// ========================================================================================================
// **************************************** verifier_regeneration.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 "verifier_common.h"
#include "verifier_regen_funcs.h"
#include "commonDB_RT.h"
#include "commonDB_RT_PUFCash.h"
#include <signal.h>
#include "aes_128_ecb_openssl.h"
#include "aes_256_cbc_openssl.h"
#include "sha_3_256_openssl.h"
#include <openssl/evp.h>
extern struct tm *localtime_r (const time_t *__restrict __timer,
struct tm *__restrict __tp) __THROW;
extern int usleep (__useconds_t __useconds);
// THIS MUST BE THE SAME as that defined in device_common.h
//static volatile int keepRunning = 1;
typedef struct
{
int task_num;
int iteration_cnt;
SRFAlgoParamsStruct *SAP_ptr;
int TTP_request;
int Device_socket_desc;
int port_number;
int RANDOM;
int in_use;
int client_index;
int *client_sockets;
int TTP_num;
unsigned char **TTP_session_keys;
int num_TTPs;
char **TTP_IPs;
int num_customers;
char **customer_IPs;
int ip_length;
int max_string_len;
int num_preauth_n3_bytes;
int num_eCt_nonce_bytes;
int *TTP_socket_descs;
AccountStruct *Accounts_ptr;
pthread_mutex_t Thread_mutex;
pthread_cond_t Thread_cv;
} ThreadDataType;
// ========================================================================================================
// ========================================================================================================
// Alice withdrawal request.
void AliceWithdrawal(int max_string_len, SRFAlgoParamsStruct *SAP_ptr, int TTP_socket_desc, int RANDOM,
int num_eCt_nonce_bytes, char *TTP_IP, int port_number, unsigned char *SK_TF, int task_num,
int iteration_cnt)
{
char request_str[max_string_len];
int num_eCt;
// Sanity check
if ( SK_TF == NULL )
{ printf("ERROR: AliceWithdrawal(): SK_TF key is NULL\n"); exit(EXIT_FAILURE); }
// ==============================
// 1) Get encrypted Alice chip_num (or anon_chip_num) and Amt
char Alice_request_str[max_string_len];
int Alice_anon_chip_num;
unsigned char *eID_amt = Allocate1DUnsignedChar(AES_INPUT_NUM_BYTES);
// ****************************
// ADD CODE
// ****************************
// 2) Session Key with Alice THROUGH the TTP using the anonymous DB.
// First send control information that the verifier is using to the TTP.
sprintf(request_str, "%d %d %d", SAP_ptr->use_database_chlngs, SAP_ptr->num_PIs, SAP_ptr->num_POs);
if ( SockSendB((unsigned char *)request_str, strlen(request_str)+1, TTP_socket_desc) < 0 )
{ printf("ERROR: AliceWithdrawal(): Failed to send 'use_database_chlngs/num_PIs/num_POs' to TTP!\n"); exit(EXIT_FAILURE); }
// SESSION KEY GEN THROUGH THE TTP: Generate the Session key THROUGH THE TTP.
int fail_or_succeed;
if ( (fail_or_succeed = KEK_SessionKeyGen(max_string_len, SAP_ptr, TTP_socket_desc, RANDOM)) == 0 )
{ printf("WARNING: AliceWithdrawal(): Failed to generate a Session Key between Alice and the Bank THROUGH THE TTP!\n"); fflush(stdout); }
// Free up the vectors.
if ( SAP_ptr->database_NAT != NULL )
{
FreeVectorsAndMasks(&(SAP_ptr->num_vecs), &(SAP_ptr->num_rise_vecs), &(SAP_ptr->first_vecs_b), &(SAP_ptr->second_vecs_b), &(SAP_ptr->masks_b));
FreeAllTimingValsForChallenge(&(SAP_ptr->num_chips), &(SAP_ptr->PNR), &(SAP_ptr->PNF));
}
// Send ACK/NAK to the TTP to indicate if session key generation was successful or not.
if ( fail_or_succeed == 0 )
{
if ( SockSendB((unsigned char *)"NAK", strlen("NAK") + 1, TTP_socket_desc) < 0 )
{ printf("ERROR: AliceWithdrawal(): Failed to send 'NAK' to TTP!\n"); exit(EXIT_FAILURE); }
if ( SAP_ptr->SE_final_key != NULL )
free(SAP_ptr->SE_final_key);
return;
}
else
{
if ( SockSendB((unsigned char *)"ACK", strlen("ACK") + 1, TTP_socket_desc) < 0 )
{ printf("ERROR: AliceWithdrawal(): Failed to send 'ACK' to TTP!\n"); exit(EXIT_FAILURE); }
}
int SK_TA_num_bytes = SAP_ptr->SE_target_num_key_bits/8;
unsigned char *SK_TA = NULL;
SK_TA = SAP_ptr->SE_final_key;
SAP_ptr->SE_final_key = NULL;
// 3) Allocate space for the requested eCt.
int eCt_tot_bytes = num_eCt * SAP_ptr->eCt_num_bytes;
unsigned char *eCt_buffer = Allocate1DUnsignedChar(eCt_tot_bytes);
unsigned char *heCt_buffer = Allocate1DUnsignedChar(eCt_tot_bytes);
// Generate requested number of eCt, encrypt them and send them to TTP. Currently each are 16 bytes.
if ( read(RANDOM, eCt_buffer, eCt_tot_bytes) == -1 )
{ printf("ERROR: AliceWithdrawal(): Read /dev/urandom failed for eCt generation!\n"); exit(EXIT_FAILURE); }
// 4) Get encrypted LLK with SK_TA key from Alice.
unsigned char *eLLK = Allocate1DUnsignedChar(SAP_ptr->ZHK_A_num_bytes);
unsigned char *LLK = Allocate1DUnsignedChar(SAP_ptr->ZHK_A_num_bytes);
// ****************************
// ADD CODE
// ****************************
// 5) Decrypt LLK
// ****************************
// ADD CODE
// ****************************
// 6) Create heCt using Alice's LLK. XOR in Alice's LLK with the each eCt and hash each of them to create the heCt.
// ****************************
// ADD CODE
// ****************************
// 7) Store the eCt in the PUFCash_WRec.db as one big blob. NOTE: Multiple outstanding withdrawals is NOT supported
// right now because the LLK is used as a unique identifier in the PUFCash_WRec table of the PUFCash database (database
// scheme sets this is 'unique' which prevents duplicates. And Alice uses the same LLK for each successive withdrawal.
// But we must record the LLK to do the validation of the heCt later during deposits so it must be used. Might be
// a good idea to add another blob field to this table that records the SK_TA too and uses that as the unique id, otherwise
// live with the one withdrawal constraint.
pthread_mutex_lock(SAP_ptr->PUFCash_WRec_DB_mutex_ptr);
PUFCashAdd_WRec_Data(max_string_len, SAP_ptr->DB_PUFCash_V3, Alice_anon_chip_num, LLK, SAP_ptr->ZHK_A_num_bytes, eCt_buffer,
heCt_buffer, eCt_tot_bytes, num_eCt);
pthread_mutex_unlock(SAP_ptr->PUFCash_WRec_DB_mutex_ptr);
// 8) Encrypt eCt and heCt with SK_TA to eeCt and eheCt
// ****************************
// ADD CODE
// ****************************
// 9) Transmit encrypted eeCt and eheCt to FI
// ****************************
// ADD CODE
// ****************************
return;
}
// ========================================================================================================
// ========================================================================================================
// Device or TTP sends it's ID, (IP and bitstream number, 1 to 4).
void GetClientIDInformation(int max_string_len, SRFAlgoParamsStruct *SAP_ptr, int client_socket_desc,
int task_num, int iteration_cnt)
{
char my_info_str[max_string_len];
if ( SockGetB((unsigned char *)my_info_str, max_string_len, client_socket_desc) < 0 )
{ printf("ERROR: GetClientIDInformation(): Error receiving 'my_info_str' from client!\n"); exit(EXIT_FAILURE); }
#ifdef DEBUG
printf("ID str fetched from device %s\n", my_info_str); fflush(stdout);
#endif
if ( SAP_ptr->my_IP != NULL )
free(SAP_ptr->my_IP);
// The my_info_str length is longer than the IP because it has the bitstream number too but that's fine.
if ( (SAP_ptr->my_IP = (char *)calloc(strlen(my_info_str) + 1, sizeof(char))) == NULL )
{ printf("ERROR: GetClientIDInformation(): Failed to allocated storage for IP!\n"); exit(EXIT_FAILURE); }
if ( sscanf(my_info_str, "%d %f %s %d", &(SAP_ptr->my_chip_num), &(SAP_ptr->my_scaling_constant), SAP_ptr->my_IP, &(SAP_ptr->my_bitstream)) != 4 )
{ printf("ERROR: GetClientIDInformation(): Failed to sscanf the Chip num, ScalingConstant, IP, bitstream number!\n"); exit(EXIT_FAILURE); }
#ifdef DEBUG
printf("Fetched Chip %3d\tScalingConstant %f\tIP %s and Bitstream number %d from client!\n",
SAP_ptr->my_chip_num, SAP_ptr->my_scaling_constant, SAP_ptr->my_IP, SAP_ptr->my_bitstream); fflush(stdout);
#endif
// Send ACK to the Alice/Bob to allow it to continue
if ( SockSendB((unsigned char *)"ACK", strlen("ACK") + 1, client_socket_desc) < 0 )
{ printf("ERROR: GetClientIDInformation(): Failed to send 'ACK' to client!\n"); exit(EXIT_FAILURE); }
return;
}
// ========================================================================================================
// ========================================================================================================
// The ZeroTrust enrollment function on this IA side. Alice (NOT TTP) authenticates with the IA and generates
// a Session key. Alice or TTP then requests how many ATs to generate. IA gets ATs from Alice/TTP and stores
// them in its database for distribution to the other customers.
void ZeroTrust_Enroll(int max_string_len, SRFAlgoParamsStruct *SAP_ptr, int Alice_socket_desc,
int RANDOM, int TTP_request, unsigned char *session_key)
{
char request_str[max_string_len];
#ifdef DEBUG
printf("\nZeroTrust_Enroll(): BEGIN!\n"); fflush(stdout);
#endif
// Make sure the number of session key bits matches that used by the encryption function below.
if ( SAP_ptr->SE_target_num_key_bits != AES_KEY_NUM_BITS_256 )
{
printf("ERROR: ZeroTrust_Enroll(): Session key size %d NOT equal to AES key size %d!\n",
SAP_ptr->SE_target_num_key_bits, AES_KEY_NUM_BITS_256); exit(EXIT_FAILURE);
}
// Make sure the number of LLE key bits matches that used by the encryption function below.
if ( KEK_TARGET_NUM_KEY_BITS != AES_KEY_NUM_BITS_256 )
{
printf("ERROR: ZeroTrust_Enroll(): LLE key size (KEK_TARGET_NUM_KEY_BITS) %d NOT equal to AES key size %d!\n",
KEK_TARGET_NUM_KEY_BITS, AES_KEY_NUM_BITS_256); exit(EXIT_FAILURE);
}
// ********************************************************************************************************************
// *** ZeroTrust Enroll PART I: Mutually authenticate with Alice, and generate session key. TTP does NOT do this.
if ( TTP_request == 0 )
{
int gen_session_key = 1;
if ( KEK_ClientServerAuthenKeyGen(max_string_len, SAP_ptr, Alice_socket_desc, RANDOM, gen_session_key) == 0 )
{ printf("ERROR: ZeroTrust_Enroll(): Failed to authenticate Alice or the Bank!\n"); exit(EXIT_FAILURE); }
session_key = SAP_ptr->SE_final_key;
SAP_ptr->SE_final_key = NULL;
}
// ********************************************************************************************************************
// *** ZeroTrust ENROLL PART II: Send number of ATs to generate to Alice and get the Chlng_num that Alice wants to
// use to identify these AT.
int num_ATs_to_generate;
num_ATs_to_generate = ZERO_TRUST_ENROLL_NUM_AUTHEN_TOKENS;
#ifdef DEBUG
printf("ZeroTrust_Enroll(): Sending Alice %d ATs to generate!\n", num_ATs_to_generate); fflush(stdout);
#endif
// Create string for the number of Authentication Tokens.
sprintf(request_str, "%d", num_ATs_to_generate);
if ( SockSendB((unsigned char *)request_str, strlen(request_str) + 1, Alice_socket_desc) < 0 )
{ printf("ERROR: ZeroTrust_Enroll(): Error transmitting Number of ATs string to Alice!\n"); exit(EXIT_FAILURE); }
int Chlng_num;
if ( SockGetB((unsigned char *)request_str, max_string_len, Alice_socket_desc) < 0 )
{ printf("ERROR: ZeroTrust_Enroll(): Error receiving 'Chlng_num' from Alice!\n"); exit(EXIT_FAILURE); }
sscanf(request_str, "%d", &Chlng_num);
#ifdef DEBUG
printf("ZeroTrust_Enroll(): Got Chlng_num %d from Alice!\n", Chlng_num); fflush(stdout);
#endif
// ********************************************************************************************************************
// *** ZeroTrust ENROLL PART III: Get encrypted ZHK_A_nonce and the nonce itself and store in DB.
int ZHK_A_num_bytes = SAP_ptr->ZHK_A_num_bytes;
int plaintext_len_bytes;
unsigned char *ZHK_A_nonce_enc = Allocate1DUnsignedChar(ZHK_A_num_bytes);
unsigned char *nonce_enc = Allocate1DUnsignedChar(ZHK_A_num_bytes);
unsigned char *ZHK_A_nonce = Allocate1DUnsignedChar(ZHK_A_num_bytes);
unsigned char *nonce = Allocate1DUnsignedChar(ZHK_A_num_bytes);
int AT_num;
for ( AT_num = 0; AT_num < num_ATs_to_generate; AT_num++ )
{
// Get the encrypted ZHK_A_nonce
if ( SockGetB((unsigned char *)ZHK_A_nonce_enc, ZHK_A_num_bytes, Alice_socket_desc) != ZHK_A_num_bytes )
{ printf("ERROR: ZeroTrust_Enroll(): Error receiving 'ZHK_A_nonce_enc' from Alice!\n"); exit(EXIT_FAILURE); }
// Get the encrypted nonce_enc
if ( SockGetB((unsigned char *)nonce_enc, ZHK_A_num_bytes, Alice_socket_desc) != ZHK_A_num_bytes )
{ printf("ERROR: ZeroTrust_Enroll(): Error receiving 'nonce_enc' from Alice!\n"); exit(EXIT_FAILURE); }
// Decrypt them
plaintext_len_bytes = decrypt_256(session_key, SAP_ptr->AES_IV, ZHK_A_nonce_enc, ZHK_A_num_bytes, ZHK_A_nonce);
// Sanity check. Only works when packets are 1 or 2 blocks.
if ( plaintext_len_bytes != ZHK_A_num_bytes )
{
printf("ERROR: ZeroTrust_Enroll(): Decrypted len of ZHK_A_nonce %d NOT equal to expected length %d!\n",
plaintext_len_bytes, ZHK_A_num_bytes); exit(EXIT_FAILURE);
}
plaintext_len_bytes = decrypt_256(session_key, SAP_ptr->AES_IV, nonce_enc, ZHK_A_num_bytes, nonce);
// Sanity check. Only works when packets are 1 or 2 blocks.
if ( plaintext_len_bytes != ZHK_A_num_bytes )
{
printf("ERROR: ZeroTrust_Enroll(): Decrypted len of nonce %d NOT equal to expected length %d!\n",
plaintext_len_bytes, ZHK_A_num_bytes); exit(EXIT_FAILURE);
}
// Store them in the ZeroTrust table of the ZeroTrust Table Trust DB. Mark their status is 0 ('NOT USED').
// Mark their status is 0 ('NOT USED').
int status = 0;
ZeroTrustAddCustomerATs(max_string_len, SAP_ptr->DB_Trust_AT, SAP_ptr->chip_num, Chlng_num, ZHK_A_num_bytes, ZHK_A_nonce,
nonce, status);
}
// Send ACK to the Alice to allow it to continue.
if ( SockSendB((unsigned char *)"ACK", strlen("ACK") + 1, Alice_socket_desc) < 0 )
{ printf("ERROR: ZeroTrust_Enroll(): Failed to send 'ACK' to Alice!\n"); exit(EXIT_FAILURE); }
// Wait for Alice to acknowledge
if ( SockGetB((unsigned char *)request_str, max_string_len, Alice_socket_desc) != 4 )
{ printf("ERROR: ZeroTrust_Enroll(): Failed to get 'ACK' from Alice!\n"); exit(EXIT_FAILURE); }
if ( strcmp(request_str, "ACK") != 0 )
{ printf("ERROR: ZeroTrust_Enroll(): Failed to match 'ACK' string from Alice!\n"); exit(EXIT_FAILURE); }
if ( ZHK_A_nonce_enc != NULL )
free(ZHK_A_nonce_enc);
if ( nonce_enc != NULL )
free(nonce_enc);
if ( ZHK_A_nonce != NULL )
free(ZHK_A_nonce);
if ( nonce != NULL )
free(nonce);
// Do NOT free the session key if the TTP calls this.
if ( TTP_request == 0 )
{
if ( session_key != NULL )
free(session_key);
}
// Can add this in later as needed
if ( 0 )
{
if ( LoadOrSaveDb(SAP_ptr->DB_Trust_AT, SAP_ptr->DB_name_Trust_AT, 1) != 0 )
{
printf("Failed to store 'in memory' database to %s: %s\n", SAP_ptr->DB_name_Trust_AT, sqlite3_errmsg(SAP_ptr->DB_Trust_AT));
sqlite3_close(SAP_ptr->DB_Trust_AT); exit(EXIT_FAILURE);
}
}
#ifdef DEBUG
printf("\nZeroTrust_Enroll(): DONE!\n"); fflush(stdout);
#endif
return;
}
// ========================================================================================================
// ========================================================================================================
// The ZeroTrust AT distribution function. Alice (NOT TTP) first authenticates with the IA and generates
// a Session key. The IA then fetches ATs from the database (populated by Alice, Bob and TTP during provisioning)
// encrypts and sends them to Alice/Bob/TTP for ZeroTrust and ZeroTrust authentication and session key generation.
//
// NOTE: When TTP invokes this function, it wants the AT for a specific customer, not all customers.
void ZeroTrust_GetATs(int max_string_len, SRFAlgoParamsStruct *SAP_ptr, int client_socket_desc,
int RANDOM, int TTP_request, unsigned char *session_key)
{
char request_str[max_string_len];
int chip_num = -1;
#ifdef DEBUG
printf("\nZeroTrust_GetATs(): BEGIN!\n"); fflush(stdout);
#endif
// Make sure the number of session key bits matches that used by the encryption function below.
if ( SAP_ptr->SE_target_num_key_bits != AES_KEY_NUM_BITS_256 )
{
printf("ERROR: ZeroTrust_GetATs(): Session key size %d NOT equal to AES key size %d!\n",
SAP_ptr->SE_target_num_key_bits, AES_KEY_NUM_BITS_256); exit(EXIT_FAILURE);
}
// Make sure the number of LLE key bits matches that used by the encryption function below.
if ( KEK_TARGET_NUM_KEY_BITS != AES_KEY_NUM_BITS_256 )
{
printf("ERROR: ZeroTrust_GetATs(): LLE key size (KEK_TARGET_NUM_KEY_BITS) %d NOT equal to AES key size %d!\n",
KEK_TARGET_NUM_KEY_BITS, AES_KEY_NUM_BITS_256); exit(EXIT_FAILURE);
}
// ********************************************************************************************************************
// *** ZeroTrust Get ATs PART I: Mutually authenticate with Alice, and generate session key. TTP does NOT do this.
if ( TTP_request == 0 )
{
int gen_session_key = 1;
if ( KEK_ClientServerAuthenKeyGen(max_string_len, SAP_ptr, client_socket_desc, RANDOM, gen_session_key) == 0 )
{ printf("ERROR: ZeroTrust_GetATs(): Failed to authenticate Alice or the Bank!\n"); exit(EXIT_FAILURE); }
session_key = SAP_ptr->SE_final_key;
SAP_ptr->SE_final_key = NULL;
}
// For the TTP, get Alice's chip_num from TTP. The IA will fetch only one AT in this case.
else
{
if ( SockGetB((unsigned char *)request_str, max_string_len, client_socket_desc) < 0 )
{ printf("ERROR: ZeroTrust_GetATs(): Failed to get 'chip_num' from TTP!\n"); exit(EXIT_FAILURE); }
sscanf(request_str, "%d", &chip_num);
#ifdef DEBUG
printf("\tZeroTrust_GetATs(): TTP sent chip_num %d!\n", chip_num); fflush(stdout);
#endif
}
// ********************************************************************************************************************
// *** ZeroTrust Get ATs PART II: Get ATs from the DB for each device (except Alice) that has ATs currrently enrolled.
int num_customers, customer_num;
int *chip_num_arr = NULL;
int *chlng_num_arr = NULL;
unsigned char **ZHK_A_nonce_arr = NULL;
unsigned char **nonce_arr = NULL;
// Alice or TTP invokes this routine. When Alice invokes it, this routine fetches a unique AT for each customer in the
// ZeroTrust table. Setting get_only_customer_AT to 0 is a flag to fetch 'one for each customer'. When TTP calls it, this
// routine fetch an AT for a specific customer, given by the chip_num fetched above from the TTP.
int report_num_ATs_only = 0;
int get_only_customer_AT;
if ( TTP_request == 0 )
get_only_customer_AT = 0;
else
get_only_customer_AT = 1;
// For both Alice and the TTP, we set return_customer_AT_info to 1, which returns the actual data, which is allocated and
// stored in the array parameters. Note that this action sets the status of the AT as USED (can NOT be used again).
int return_customer_AT_info = 1;
int unused;
num_customers = ZeroTrustGetCustomerATs(max_string_len, SAP_ptr->DB_Trust_AT, &chip_num_arr, &chlng_num_arr,
SAP_ptr->ZHK_A_num_bytes, &ZHK_A_nonce_arr, &nonce_arr, get_only_customer_AT, chip_num,
return_customer_AT_info, report_num_ATs_only, &unused);
#ifdef DEBUG
printf("\tZeroTrust_GetATs(): Got Customer ATs for %d customers!\n", num_customers); fflush(stdout);
#endif
// ********************************************************************************************************************
// *** ZeroTrust Get ATs PART III: Send one for each device to Alice. Encrypt them.
unsigned char *AT_packet = NULL, *AT_packet_enc = NULL;
int AT_packet_size, AT_packet_size_enc;
// Size here is 2 integers and 2 * the size of ZHK_A and nonce (WHICH WE ASSUME ARE THE SAME SIZE).
AT_packet_size = 2*4 + 2*SAP_ptr->ZHK_A_num_bytes;
// MAKE SURE YOU pad the size to the nearest multpiple of AES_INPUT_NUM_BYTES. When the original packet size is divisible by
// AES_INPUT_NUM_BYTES, we ADD AN EXTRA block here.
AT_packet_size_enc = AT_packet_size;
AT_packet_size_enc += AES_INPUT_NUM_BYTES - (AT_packet_size % AES_INPUT_NUM_BYTES);
Allocate1DString((char **)(&AT_packet), AT_packet_size_enc);
Allocate1DString((char **)(&AT_packet_enc), AT_packet_size_enc);
#ifdef DEBUG
printf("\tZeroTrust_GetATs(): Allocated AT_packet/enc of size %d and %d!\n", AT_packet_size, AT_packet_size_enc); fflush(stdout);
#endif
// First send alice the number of customer ATs she will receive.
sprintf(request_str, "%d", num_customers);
if ( SockSendB((unsigned char *)request_str, strlen(request_str) + 1, client_socket_desc) < 0 )
{ printf("ERROR: ZeroTrust_GetATs(): Failed to send 'num_customers' string to Alice!\n"); exit(EXIT_FAILURE); }
#ifdef DEBUG
printf("\tZeroTrust_GetATs(): Sent number of customers to Alice '%s'!\n", request_str); fflush(stdout);
#endif
// For each customer AT, copy data into the encryption buffer, encrypt and transmit.
for ( customer_num = 0; customer_num < num_customers; customer_num++ )
{
// Put the two integers, customer chip_num and customer chlng_num, in the beginning of the packet, followed by
// ZHK_A_nonce and nonce.
int i, j = 0, k = 0, l = 0, m = 0;
for ( i = 0; i < AT_packet_size; i++ )
{
if ( i < 4 )
{ AT_packet[i] = (unsigned char)(chip_num_arr[customer_num] >> (j << 3)); j++; }
else if ( i < 2*4 )
{ AT_packet[i] = (unsigned char)(chlng_num_arr[customer_num] >> (k << 3)); k++; }
else if ( i < 2*4 + SAP_ptr->ZHK_A_num_bytes )
{ AT_packet[i] = ZHK_A_nonce_arr[customer_num][l]; l++; }
else if ( i < 2*4 + 2*SAP_ptr->ZHK_A_num_bytes )
{ AT_packet[i] = nonce_arr[customer_num][m]; m++; }
else
{ printf("ERROR: ZeroTrust_GetATs(): Packet byte TOO LARGER [%d]!\n", i); exit(EXIT_FAILURE); }
}
#ifdef DEBUG
printf("\t\tZeroTrust_GetATs(): Loaded customer number %d packet -- encrypting!\n", customer_num); fflush(stdout);
#endif
encrypt_256(session_key, SAP_ptr->AES_IV, AT_packet, AT_packet_size_enc, AT_packet_enc);
// Send encrypted packet to Alice/TTP
if ( SockSendB((unsigned char *)AT_packet_enc, AT_packet_size_enc, client_socket_desc) < 0 )
{ printf("ERROR: ZeroTrust_GetATs(): Failed to send AT packet to Alice!\n"); exit(EXIT_FAILURE); }
}
// Get ACK from Alice/TTP
char ack_str[max_string_len];
if ( SockGetB((unsigned char *)ack_str, max_string_len, client_socket_desc) < 0 )
{ printf("ERROR: ZeroTrust_GetATs(): Failed to get 'ACK' from Alice!\n"); exit(EXIT_FAILURE); }
if ( strcmp(ack_str, "ACK") != 0 )
{ printf("ERROR: ZeroTrust_GetATs(): Failed to match 'ACK' string from Alice!\n"); exit(EXIT_FAILURE); }
if ( SockSendB((unsigned char *)"ACK", strlen("ACK") + 1, client_socket_desc) < 0 )
{ printf("ERROR: ZeroTrust_GetATs(): Failed to send 'ACK' to Alice!\n"); exit(EXIT_FAILURE); }
if ( chip_num_arr != NULL )
free(chip_num_arr);
if ( chlng_num_arr != NULL )
free(chlng_num_arr);
for ( customer_num = 0; customer_num < num_customers; customer_num++ )
{
if ( ZHK_A_nonce_arr[customer_num] != NULL )
free(ZHK_A_nonce_arr[customer_num]);
if ( nonce_arr[customer_num] != NULL )
free(nonce_arr[customer_num]);
}
if ( ZHK_A_nonce_arr != NULL )
free(ZHK_A_nonce_arr);
if ( nonce_arr != NULL )
free(nonce_arr);
if ( AT_packet != NULL )
free(AT_packet);
if ( AT_packet_enc != NULL )
free(AT_packet_enc);
// Do NOT free the session key if the TTP calls this.
if ( TTP_request == 0 )
{
if ( session_key != NULL )
free(session_key);
}
// Can add this in later as needed
if ( 0 )
{
if ( LoadOrSaveDb(SAP_ptr->DB_Trust_AT, SAP_ptr->DB_name_Trust_AT, 1) != 0 )
{
printf("Failed to store 'in memory' database to %s: %s\n", SAP_ptr->DB_name_Trust_AT, sqlite3_errmsg(SAP_ptr->DB_Trust_AT));
sqlite3_close(SAP_ptr->DB_Trust_AT); exit(EXIT_FAILURE);
}
}
#ifdef DEBUG
printf("\nZeroTrust_GetATs(): DONE!\n"); fflush(stdout);
#endif
return;
}
// ========================================================================================================
// ========================================================================================================
// Transmit encrypted versions of the device IPs to a Master (or Slave) TTP or to Alice.
void TransmitDevice_IPInfo(int max_string_len, SRFAlgoParamsStruct *SAP_ptr, int num_devices,
int device_socket_desc, char **device_IPs, int ip_length, unsigned char *Session_key, int task_num,
int iteration_cnt)
{
char num_devices_str[max_string_len];
unsigned char *fIPs, *eIPs;
int IP_length_bytes;
int i, j;
// Device has already authenticated to Bank in an earlier transaction so no need for that here.
#ifdef DEBUG
printf("TransmitDevice_IPInfo: START!\n"); fflush(stdout);
#endif
// Sanity check
if ( num_devices == 0 || device_IPs == NULL )
{ printf("ERROR: TransmitDevice_IPInfo(): num_devices is 0 OR device_IPs is NULL!\n"); exit(EXIT_FAILURE); }
// Check that the session key is not NULL. This should never happen since if a TTP/Alice is requesting this information,
// it needed to authenticate first.
if ( Session_key == NULL )
{ printf("ERROR: TransmitDevice_IPInfo(): Session key is NULL!\n"); exit(EXIT_FAILURE); }
// Each IP, e.g., 192.168.xxx.xxx, is at most 15 bytes long + NULL termination makes it 16. If, e.g., num_devices is
// 4 and ip_length is 16, then we need to allocate 4*16 = 64 bytes here.
IP_length_bytes = (num_devices * ip_length);
IP_length_bytes += AES_INPUT_NUM_BYTES - (IP_length_bytes % AES_INPUT_NUM_BYTES);
fIPs = Allocate1DUnsignedChar(IP_length_bytes);
eIPs = Allocate1DUnsignedChar(IP_length_bytes);
#ifdef DEBUG
for ( i = 0; i < num_devices; i++ )
printf("Sending device IP '%s'\n", device_IPs[i]);
fflush(stdout);
#endif
// Copy the IPs into a flat array. We initialize to all zero above (calloc) so the strings will be NULL terminated.
for ( i = 0; i < num_devices; i++ )
for ( j = 0; j < ip_length; j++ )
fIPs[i*ip_length + j] = device_IPs[i][j];
#ifdef DEBUG
printf("IPs\n\t"); fflush(stdout);
for ( i = 0; i < num_devices * ip_length; i++ )
printf("%c ", fIPs[i]);
fflush(stdout);
#endif
// Encrypt IPs and transmit
encrypt_256(Session_key, SAP_ptr->AES_IV, fIPs, IP_length_bytes, eIPs);
// Send the number of devices as a string first.
sprintf(num_devices_str, "%d", num_devices);
if ( SockSendB((unsigned char *)num_devices_str, strlen(num_devices_str) + 1, device_socket_desc) < 0 )
{ printf("ERROR: TransmitDevice_IPInfo(): Send 'num_devices_str' failed\n"); exit(EXIT_FAILURE); }
// Send the encrypted IPs.
if ( SockSendB(eIPs, IP_length_bytes, device_socket_desc) < 0 )
{ printf("ERROR: TransmitDevice_IPInfo(): Send eIPs to device failed\n"); exit(EXIT_FAILURE); }
// Wait for ACK from device before proceeding.
char ack_str[max_string_len];
if ( SockGetB((unsigned char *)ack_str, max_string_len, device_socket_desc) < 0 )
{ printf("ERROR: TransmitDevice_IPInfo(): Failed to 'ACK' from device!\n"); exit(EXIT_FAILURE); }
if ( strcmp(ack_str, "ACK") != 0 )
{ printf("ERROR: TransmitDevice_IPInfo(): Failed to match 'ACK' string from device!\n"); exit(EXIT_FAILURE); }
// Send ACK to the device to allow it to continue
if ( SockSendB((unsigned char *)"ACK", strlen("ACK") + 1, device_socket_desc) < 0 )
{ printf("ERROR: TransmitDevice_IPInfo(): Failed to send 'ACK' to device!\n"); exit(EXIT_FAILURE); }
if ( fIPs != NULL )
free(fIPs);
if ( eIPs != NULL )
free(eIPs);
#ifdef DEBUG
printf("TransmitDevice_IPInfo: DONE!\n"); fflush(stdout);
#endif
return;
}
// ========================================================================================================
// ========================================================================================================
// TTP requests ID from customers at startup so it can create Account records with a default deposit amount.
// NOTE: In PUFCash V3.0, the accounts are maintained on the TTP(s).
void TransmitTTP_DeviceIDInfo(int max_string_len, SRFAlgoParamsStruct *SAP_ptr, sqlite3 *DB_NAT,
int TTP_num, int num_TTPs, int TTP_socket_desc, unsigned char **TTP_session_keys, int task_num,
int iteration_cnt)
{
SQLIntStruct PUF_instance_index_struct;
char request_str[max_string_len];
int chip_num;
// Get a list of all the chips (PUFInstance IDs) enrolled in the non-anonymous database. Use '%' for * and '_' for ?
GetPUFInstanceIDsForInstanceName(max_string_len, DB_NAT, &PUF_instance_index_struct, "%");
// Sanity check
if ( PUF_instance_index_struct.num_ints == 0 )
{ printf("ERROR: TransmitTTP_DeviceIDInfo(): No PUFInstances in Master database!\n"); exit(EXIT_FAILURE); }
// Encrypt and send the number of chip_nums first.
unsigned char *eReq = Allocate1DUnsignedChar(AES_INPUT_NUM_BYTES);
sprintf(request_str, "%d", PUF_instance_index_struct.num_ints);
encrypt_256(TTP_session_keys[TTP_num], SAP_ptr->AES_IV, (unsigned char *)request_str, AES_INPUT_NUM_BYTES, eReq);
if ( SockSendB(eReq, AES_INPUT_NUM_BYTES, TTP_socket_desc) < 0 )
{ printf("ERROR: TransmitTTP_DeviceIDInfo(): Failed to send 'number of chip_nums' to TTP!\n"); exit(EXIT_FAILURE); }
// Encrypt and transmit the chip_nums to the TTP.
for ( chip_num = 0; chip_num < PUF_instance_index_struct.num_ints; chip_num++ )
{
sprintf(request_str, "%d", PUF_instance_index_struct.int_arr[chip_num]);
encrypt_256(TTP_session_keys[TTP_num], SAP_ptr->AES_IV, (unsigned char *)request_str, AES_INPUT_NUM_BYTES, eReq);
if ( SockSendB(eReq, AES_INPUT_NUM_BYTES, TTP_socket_desc) < 0 )
{ printf("ERROR: TransmitTTP_DeviceIDInfo(): Failed to send a 'chip_num' to TTP!\n"); exit(EXIT_FAILURE); }
}
if ( eReq != NULL )
free(eReq);
if ( PUF_instance_index_struct.int_arr != NULL )
free(PUF_instance_index_struct.int_arr);
return;
}
// ========================================================================================================
// ========================================================================================================
// Device thread.
void BankThread(ThreadDataType *ThreadDataPtr)
{
SRFAlgoParamsStruct *SAP_ptr;
int TTP_request;
int Device_socket_desc;
int port_number;
int client_index;
int *client_sockets;
int TTP_num;
unsigned char **TTP_session_keys;
int num_TTPs;
char **TTP_IPs;
int num_customers;
char **customer_IPs;
int ip_length;
int max_string_len;
int num_eCt_nonce_bytes;
int RANDOM;
int task_num, iteration_cnt;
// Making this static here makes it global to all threads.
static pthread_mutex_t RT_DB_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t FileStat_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t GenChallenge_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t Authentication_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t PUFCash_WRec_DB_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t PUFCash_POP_DB_mutex = PTHREAD_MUTEX_INITIALIZER;
printf("BankThread: CALLED!\t(Task %d\tIterationCnt %d)\n", ThreadDataPtr->task_num, ThreadDataPtr->iteration_cnt); fflush(stdout);
#ifdef DEBUG
#endif
// Threads never return
while (1)
{
// Sleep waiting for the main program to receive connect request from Alice or a TTP, and assign a device_socket_desc
// No CPU cycles are wasted here in a busy wait, which is important when we query TTPs for performance information.
pthread_mutex_lock(&(ThreadDataPtr->Thread_mutex));
while ( ThreadDataPtr->in_use == 0 )
pthread_cond_wait(&(ThreadDataPtr->Thread_cv), &(ThreadDataPtr->Thread_mutex));
pthread_mutex_unlock(&(ThreadDataPtr->Thread_mutex));
task_num = ThreadDataPtr->task_num;
iteration_cnt = ThreadDataPtr->iteration_cnt;
// Get local copies/pointers from the data structure.
SAP_ptr = ThreadDataPtr->SAP_ptr;
TTP_request = ThreadDataPtr->TTP_request;
Device_socket_desc = ThreadDataPtr->Device_socket_desc;
port_number = ThreadDataPtr->port_number;
client_index = ThreadDataPtr->client_index;
client_sockets = ThreadDataPtr->client_sockets;
TTP_num = ThreadDataPtr->TTP_num;
TTP_session_keys = ThreadDataPtr->TTP_session_keys;
num_TTPs = ThreadDataPtr->num_TTPs;
TTP_IPs = ThreadDataPtr->TTP_IPs;
num_customers = ThreadDataPtr->num_customers;
customer_IPs = ThreadDataPtr->customer_IPs;
ip_length = ThreadDataPtr->ip_length;
max_string_len = ThreadDataPtr->max_string_len;
num_eCt_nonce_bytes = ThreadDataPtr->num_eCt_nonce_bytes;
RANDOM = ThreadDataPtr->RANDOM;
// If we set SAP_ptr->use_database_chlngs to 1, then we can NOT allow more than one thread to run GenChallengeDB() at the same time because we
// call rand(). If the device or TTP is going to get the same set of random numbers as this verifier is than after srand() is seeded with
// SAP_ptr->DB_ChallengeGen_seed, we must block other threads until the vector sequence is completely generated, i.e., rand() is NOT re-entrant!
// We can do this in main() or here once we've initialized the GenChallenge_mutex mutex above (it is static and therefore global to all threads).
SAP_ptr->RT_DB_mutex_ptr = &RT_DB_mutex;
SAP_ptr->FileStat_mutex_ptr = &FileStat_mutex;
SAP_ptr->GenChallenge_mutex_ptr = &GenChallenge_mutex;
SAP_ptr->Authentication_mutex_ptr = &Authentication_mutex;
SAP_ptr->PUFCash_WRec_DB_mutex_ptr = &PUFCash_WRec_DB_mutex;
SAP_ptr->PUFCash_POP_DB_mutex_ptr = &PUFCash_POP_DB_mutex;
// Get the request
char client_request_str[max_string_len];
int client_request;
struct timeval t1, t2;
long elapsed;
gettimeofday(&t2, 0);
#ifdef DEBUG
#endif
if ( SockGetB((unsigned char *)client_request_str, max_string_len, Device_socket_desc) < 0 )
{ printf("ERROR: BankThread(): Error receiving 'client_request_str' from Device or TTP (TTP_request? %d)!\n", TTP_request); exit(EXIT_FAILURE); }
#ifdef DEBUG
printf("BankThread(): Client request '%s'\tIs TTP request %d\tIterationCnt %d\n", client_request_str, TTP_request, iteration_cnt); fflush(stdout);
#endif
// ========================================================
// Supported client requests
client_request = -1;
if ( strcmp(client_request_str, "KEK-CHALLENGE-ENROLL") == 0 )
client_request = 1;
else if ( strcmp(client_request_str, "ZERO-TRUST-ENROLL") == 0 )
client_request = 3;
else if ( strcmp(client_request_str, "ZERO-TRUST-GET-ATS") == 0 )
client_request = 4;
else if ( strcmp(client_request_str, "WITHDRAW") == 0 )
client_request = 5;
else if ( strcmp(client_request_str, "TTP-AUTHENTICATION") == 0 )
client_request = 10;
else if ( strcmp(client_request_str, "ALICE-GET-TTP-IPS") == 0 )
client_request = 11;
else if ( strcmp(client_request_str, "ALICE-GET-CUSTOMER-IPS") == 0 )
client_request = 12;
else if ( strcmp(client_request_str, "TTP-MASTER-GET-TTP-IP-INFO") == 0 )
client_request = 13;
else if ( strcmp(client_request_str, "TTP-GET-DEVICE-IDS") == 0 )
client_request = 15;
else if ( strcmp(client_request_str, "CLIENT-AUTHENTICATION") == 0 )
client_request = 17;
else if ( strcmp(client_request_str, "CLIENT-SERVER-KEYGEN") == 0 )
client_request = 20;
if ( client_request == -1 )
{ printf("ERROR: BankThread(): Unknown 'client_request' '%s'!\n", client_request_str); exit(EXIT_FAILURE); }
// ===============================================================
// Alice/Bob is getting KEK challenge information DURING FIELD OPERATION. Here, we need to authenticate using the old information first.
if ( strcmp(client_request_str, "KEK-CHALLENGE-ENROLL") == 0 )
{
printf("\tKEK-CHALLENGE-ENROLL: BankThread(): Request from socket %d at index %d!\tIterationCnt %d\n",
Device_socket_desc, client_index, iteration_cnt); fflush(stdout);
#ifdef DEBUG
#endif
int prev_udc = SAP_ptr->use_database_chlngs;
SAP_ptr->use_database_chlngs = 1;
KEK_EnrollInField(max_string_len, SAP_ptr, Device_socket_desc, RANDOM);
SAP_ptr->use_database_chlngs = prev_udc;
}
// ===============================================================
// PUF-Cash 3.0: ZeroTrust: Alice makes this call. There is NO TTP involved in ZeroTrust
else if ( strcmp(client_request_str, "ZERO-TRUST-ENROLL") == 0 )
{
printf("\tZERO-TRUST-ENROLL: BankThread(): Request from socket %d at index %d!\tIterationCnt %d\n",
Device_socket_desc, client_index, iteration_cnt); fflush(stdout);
#ifdef DEBUG
#endif
// 7_5_2022: When developing PUFCash V3.0, I assumed only ONE TTP (AS). If more exist, then we'll need to make a decision here
// regarding which TTP to use.
if ( num_TTPs > 1 )
{ printf("ZERO-TRUST-ENROLL: BankThread(): NUMBER of TTPs %d > 1 -- FIX ME!\n", num_TTPs); exit(EXIT_FAILURE); }
// If Alice or Bob, we will authenticate and generate a session key in this function (ZeroTrust_Enroll). If TTP, we already have
// one (TTPs open up a permanent connection with IA, central Bank).
unsigned char *session_key;
if ( TTP_request == 0 )
session_key = NULL;
else
session_key = TTP_session_keys[0];
// ZeroTrust enrollment. NOTE: This requests comes in from a customer device,
ZeroTrust_Enroll(max_string_len, SAP_ptr, Device_socket_desc, RANDOM, TTP_request, session_key);
}
// ===============================================================
// PUF-Cash 3.0: ZeroTrust: Get ATs. Alice makes this call. There is NO TTP involved in ZeroTrust
else if ( strcmp(client_request_str, "ZERO-TRUST-GET-ATS") == 0 )
{
printf("\tZERO-TRUST-GET-ATS: BankThread(): Request from socket %d at index %d!\tIterationCnt %d\n",
Device_socket_desc, client_index, iteration_cnt); fflush(stdout);
#ifdef DEBUG
#endif
// 7_5_2022: When developing PUFCash V3.0, I assumed only ONE TTP (AS). If more exist, then we'll need to make a decision here
// regarding which TTP to use.
if ( num_TTPs > 1 )
{ printf("ZERO-TRUST-ENROLL: BankThread(): NUMBER of TTPs %d > 1 -- FIX ME!\n", num_TTPs); exit(EXIT_FAILURE); }
unsigned char *session_key;
if ( TTP_request == 0 )
session_key = NULL;
else
session_key = TTP_session_keys[0];
// ZeroTrust enrollment. NOTE: This requests comes in from a customer device or a TTP.
ZeroTrust_GetATs(max_string_len, SAP_ptr, Device_socket_desc, RANDOM, TTP_request, session_key);
}
// ===============================================================
// Alice is requesting a withdrawal.
else if ( strcmp(client_request_str, "WITHDRAW") == 0 )
{
// 11_12_2021: While developing PUF-Cash, I'm assuming only ONE TTP. If more exist, then we'll need to make a decision here regarding which TTP to use.
// Bank creates an encrypted withdrawal blob and sends to Alice. Alice uses this later when she contacts the TTP to get A-Chits.
if ( num_TTPs > 1 )
{ printf("WITHDRAW: BankThread(): NUMBER of TTPs %d > 1 -- FIX ME!\n", num_TTPs); exit(EXIT_FAILURE); }
printf("WITHDRAW: BankThread(): Request from socket %d at index %d!\tIterationCnt %d\n",
Device_socket_desc, client_index, iteration_cnt); fflush(stdout);
#ifdef DEBUG
#endif
AliceWithdrawal(max_string_len, SAP_ptr, Device_socket_desc, RANDOM, num_eCt_nonce_bytes, TTP_IPs[0], port_number,
TTP_session_keys[0], task_num, iteration_cnt);
}
// ===============================================================
// Authentication and session key generation request from TTP. NOTE: This socket stays open.
else if ( strcmp(client_request_str, "TTP-AUTHENTICATION") == 0 )
{
int gen_session_key;
if ( TTP_num == -1 )
{ printf("WARNING: BankThread(): TTP-AUTHENTICATION request but NOT from a TTP - IGNORING!\n"); fflush(stdout); }
else
{
printf("\tTTP-AUTHENTICATION: BankThread(): Request from socket %d at index %d!\tIterationCnt %d\n",
Device_socket_desc, client_index, iteration_cnt); fflush(stdout);
#ifdef DEBUG
#endif
// This MUST succeed. Exit is appropriate here if device or server authentication fails. Database mutex is for storing bitstring info to Runtime DB.
gen_session_key = 1;
if ( KEK_ClientServerAuthenKeyGen(max_string_len, SAP_ptr, Device_socket_desc, RANDOM, gen_session_key) == 0 )
{ printf("ERROR: BankThread(): Failed to authenticate or generate a session key with TTP!\n"); exit(EXIT_FAILURE); }
// Transfer the dynamically allocated key to preserve it forever. This array is shared among all the threads. Each TTP updates its own
// key so no need for mutex here.
TTP_session_keys[TTP_num] = SAP_ptr->SE_final_key;
SAP_ptr->SE_final_key = NULL;
}
}
// ===============================================================
// Alice does this at startup and periodically as needed. The Bank encrypts and transmits all of the TTP IPs to Alice.
else if ( strcmp(client_request_str, "ALICE-GET-TTP-IPS") == 0 )
{
int gen_session_key;
printf("\tALICE-GET-TTP-IPS: BankThread(): Request from socket %d at index %d!\tIterationCnt %d\n",
Device_socket_desc, client_index, iteration_cnt); fflush(stdout);
#ifdef DEBUG
#endif
gen_session_key = 1;
if ( KEK_ClientServerAuthenKeyGen(max_string_len, SAP_ptr, Device_socket_desc, RANDOM, gen_session_key) == 0 )
{ printf("ERROR: BankThread(): 'ALICE-GET-TTP-IPS': Failed to authenticate Alice or the Bank!\n"); exit(EXIT_FAILURE); }
TransmitDevice_IPInfo(max_string_len, SAP_ptr, num_TTPs, Device_socket_desc, TTP_IPs, ip_length, SAP_ptr->SE_final_key,
task_num, iteration_cnt);
if ( SAP_ptr->SE_final_key != NULL )
free(SAP_ptr->SE_final_key);
// 11_1_2021: Was not NULLing this out after freeing it.
SAP_ptr->SE_final_key = NULL;
}
// ===============================================================
// Alice does this at startup and periodically as needed. The Bank encrypts and transmits all of the customer IPs to Alice.
else if ( strcmp(client_request_str, "ALICE-GET-CUSTOMER-IPS") == 0 )
{
int gen_session_key;
printf("\tALICE-GET-CUSTOMER-IPS: BankThread(): Request from socket %d at index %d!\tIterationCnt %d\n",
Device_socket_desc, client_index, iteration_cnt); fflush(stdout);
#ifdef DEBUG
#endif
gen_session_key = 1;
if ( KEK_ClientServerAuthenKeyGen(max_string_len, SAP_ptr, Device_socket_desc, RANDOM, gen_session_key) == 0 )
{ printf("ERROR: BankThread(): 'ALICE-GET-CUSTOMER-IPS': Failed to authenticate Alice or the Bank!\n"); exit(EXIT_FAILURE); }
TransmitDevice_IPInfo(max_string_len, SAP_ptr, num_customers, Device_socket_desc, customer_IPs, ip_length, SAP_ptr->SE_final_key,