// ======================================================================================================== // ======================================================================================================== // **************************************** verifier_enrollment.c ***************************************** // ======================================================================================================== // ======================================================================================================== #include "common.h" #include "verifier_common.h" // ======================================================================================================== // ======================================================================================================== // Receive timing values and write them to an outfile. This routine receives the set of output lines for each // vector, one at a time. The token sends 'CONT' when it finishes sending all output lines for a given vector, // and 'DONE' when the whole process is complete. int ReceiveTimingVals(int str_length, int token_client_socket_desc, FILE **OUTFILE_ptr) { char buffer[str_length]; // Receive timing values and write them into the *OUTFILE_ptr. while (1) { if ( SockGetB((unsigned char *)buffer, str_length, token_client_socket_desc) < 0 ) { printf("ERROR: ReceiveTimingVals(): Error receiving timing value line\n"); fflush(stdout); exit(EXIT_FAILURE); } // One the last transmission of a timing value line, the token sends the 'DONE' string INSTEAD OF THE 'CONT' string. if ( strcmp(buffer, "DONE") == 0 ) { // Write a final in output file. fprintf(*OUTFILE_ptr, "\n"); break; } // The token sends a 'CONT' string when all the timing values lines (with each line containing all samples) is complete for the current vector. // Break in this case so we can collect data in parallel with multiple tokens inserted into the temp. chamber. if ( strcmp(buffer, "CONT") == 0 ) break; fprintf(*OUTFILE_ptr, "%s\n", buffer); } if ( strcmp(buffer, "DONE") == 0 ) return 1; return 0; } // ======================================================================================================== // ======================================================================================================== // ======================================================================================================== // ======================================================================================================== // For enrollment, the token is the 'server' while the verifier is the 'client' unsigned char *first_vecs_b[MAX_VECS]; unsigned char *second_vecs_b[MAX_VECS]; unsigned char *masks[MAX_VECS]; int main(int argc , char *argv[]) { char vec_file_prefix[MAX_STRING_LEN]; char vec_file_midfix[MAX_STRING_LEN]; char vec_file_path[MAX_STRING_LEN]; char mask_file_path[MAX_STRING_LEN]; int num_vecs, num_rise_vecs; char server_IP[MAX_STRING_LEN]; int server_socket_desc = 0; int client_socket_desc = 0; struct sockaddr_in server_addr; int server_port_number; int has_masks; char outfile_name_prefix[MAX_STRING_LEN]; char outfile_name_midfix[MAX_STRING_LEN]; char outfile_name_suffix[MAX_STRING_LEN]; char outfile_name[MAX_STRING_LEN]; int version_num, num_versions; char fu_command_prefix[MAX_STRING_LEN]; char fu_command_string[MAX_STRING_LEN]; int vec_len_bits; int num_outputs; int done; struct timeval t0, t1; long elapsed; FILE *OUTFILE; // =============================================================================== // COMMAND LINE. if ( argc != 2 ) { printf("ERROR: verifier_enrollment : server IP (192.168.1.20)\n\n"); fflush(stdout); exit(EXIT_FAILURE); } strcpy(server_IP, argv[1]); // ============================================ PARAMETERS ===================================================== // token port numbers server_port_number = 8888; has_masks = 1; // 19 instances of KG_FU num_versions = 19; // Vector filenames for 3 functional units in this experiment. strcpy(vec_file_midfix, "TVChar_NumSeeds_15_optimalKEK_TVN_0.60_WID_1.10"); // Functional unit characteristics. vec_len_bits = 64; num_outputs = 64; // Specify a directory to save the data in or "" for current directory. strcpy(outfile_name_prefix, ""); // ============================================================================================================= // Open the sockets to the token and begin listening. Next to last param is 0 to indicate that we want to do MORE than just 'accept' a // connection. printf("\nWaiting for incoming connections from clients for Enrollment ....\n\n"); fflush(stdout); OpenSocketServer(MAX_STRING_LEN, &server_socket_desc, server_IP, server_port_number, &client_socket_desc, &server_addr, 0, 0); printf("Opened token listening port\n"); gettimeofday(&t0, 0); // Construct command prefix to send to token. strcpy(fu_command_prefix, "KG_FU"); sprintf(vec_file_prefix, "%s_%s", fu_command_prefix, vec_file_midfix); // Read vectors and masks. sprintf(mask_file_path, "%s_masks.txt", vec_file_prefix); sprintf(vec_file_path, "%s.txt", vec_file_prefix); num_vecs = ReadVectorAndMaskFiles(MAX_STRING_LEN, vec_file_path, MAX_VECS, vec_len_bits, &num_rise_vecs, first_vecs_b, second_vecs_b, has_masks, mask_file_path, num_outputs, masks); // --------------------------------------- // Iterate over all versions (placements) of the functional unit. for ( version_num = 0; version_num < num_versions; version_num++ ) { // Add the version component of the bitstream name sprintf(fu_command_string, "V%d_%s", version_num+1, fu_command_prefix); // Send the FU/command string to token. if ( SockSendB((unsigned char *)fu_command_string, strlen(fu_command_string) + 1, client_socket_desc) < 0 ) { printf("ERROR: Send '%s' failed\n", fu_command_string); fflush(stdout); exit(EXIT_FAILURE); } // Send num_vecs and vector pairs to the token. SendVectorsAndMasks(MAX_STRING_LEN, num_vecs, MAX_VECS, client_socket_desc, num_rise_vecs, vec_len_bits, first_vecs_b, second_vecs_b, has_masks, num_outputs, masks); // Construct outfile name suffix. Distinguish between enroll and regeneration TV corners. sprintf(outfile_name_suffix, "_25C_1.00V"); strcat(outfile_name_suffix, "_E"); strcat(outfile_name_suffix, "_PUFNums.txt"); // Receive timing values from token and write to an output file. The token sends a 'CONT' string when all the timing values lines (with each line containing all // samples) is complete for the current vector and ReceiveTimingVals returns 0. When the all timing values for last vector are transmitted by the token, the // token sends 'DONE', which causes ReceiveTimingVals to return 1. This allows us to collect data in parallel with multiple tokens. // Get output midfix name, which includes the chip name ('prefix' is the data directory name set above). if ( SockGetB((unsigned char *)outfile_name_midfix, MAX_STRING_LEN, client_socket_desc) < 0 ) { printf("ERROR: Error receiving outfile_name_midfix '%s'\n", outfile_name_midfix); fflush(stdout); exit(EXIT_FAILURE); } sprintf(outfile_name, "%s%s%s", outfile_name_prefix, outfile_name_midfix, outfile_name_suffix); printf("Saving values to '%s'\n", outfile_name); fflush(stdout); if ( (OUTFILE = fopen(outfile_name, "w")) == NULL ) { printf("ERROR: Could NOT open output filename '%s'\n", outfile_name); fflush(stdout); exit(EXIT_FAILURE); } done = 0; while ( done == 0 ) done = ReceiveTimingVals(MAX_STRING_LEN, client_socket_desc, &OUTFILE); fclose(OUTFILE); gettimeofday(&t1, 0); elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec; printf("\tElapsed %ld s\n", (long)elapsed/1000000); fflush(stdout); } // Tell the token it's done. strcpy(fu_command_string, "EXIT"); if ( SockSendB((unsigned char *)fu_command_string, strlen(fu_command_string) + 1, client_socket_desc) < 0 ) { printf("ERROR: Send '%s' failed\n", fu_command_string); fflush(stdout); exit(EXIT_FAILURE); } close(client_socket_desc); close(server_socket_desc); return 0; }