void read_server_msg(Client* client) { int valread = read(client->maintainer_fd, client->server_msg.buffer+client->server_msg.offset, BUFFER_SIZE-client->server_msg.offset); if(valread == 0) exit(1); client->server_msg.offset += valread; if(client->server_msg.offset == client->server_msg.total_len) { if(ENCRYPTION_ENABLED) decrypt_msg(client->server_msg.buffer, client->keypair); client->server_msg.offset=0; logger("<Client><read_server_msg>got message from server\n"); process_server_msg(client); } }
int main(int argc, const char * argv[]) { int returnvalue; settimestamp(TRUE); set_sigchld_handler(); returnvalue = 0; switch(getParam(argc, argv)) { case ENCRYPT: { //encode char buffer[BUF_SIZE]; char * result; unsigned int i; setKey(loadKey("test.key")); while(!feof(stdin)) { if(fgets(buffer, BUF_SIZE, stdin) == 0) break; buffer[strlen(buffer)] = '\0'; printf("%s\n", encrypt_msg(buffer)); } break; } case DECRYPT: { char buffer[BUF_SIZE]; setKey(loadKey("test.key")); while(!feof(stdin)) { if(fgets(buffer, BUF_SIZE, stdin) == 0) break; printf("%s\n", decrypt_msg(buffer)); } break; } case GENERATE_KEY: { //generate key unsigned int len; if(argc == 3) sscanf(argv[2], "%i", &len); else len=64; printf("%s\n", generateKey(len)); break; } case BASE64ENCODE: { char buffer[BUF_SIZE]; while(!feof(stdin)) { if(fgets(buffer, BUF_SIZE, stdin) == 0) break; printf("%s\n", base64encode(buffer, strlen(buffer))); } break; } case BASE64DECODE: { char buffer[BUF_SIZE]; while(!feof(stdin)) { if(fgets(buffer, BUF_SIZE, stdin) == 0) break; printf("%s\n", base64decode(buffer).data); } break; } case SERVER: { daemonize(); if(argc > 2) { setlogdir(argv[2]); } else { setlogdir("~/logs"); } initlogfile(SERVER_LOG); serverlog("server started"); //sleep(60); //debug... returnvalue = start_server(); serverlog("server stopped"); terminate_log(); break; } case NOPARAM: default: { //print usage: printf("usage: %s <option>\noptions: [ -g <length> | -d | -e ]\n", argv[0]); break; } } return 0; }
/******************************************************************* ** Function name: invoke_service_wrapper ** Descrption: ** This function is used to invoke a service call ** Parameters: ** tick - the number of milliseconds that have elapsed since the system was started, ** used to detect which session is idle for the longest time. ** req_msg - service request message ** req_msg_size - size of request message ** resp_msg - service response message ** resp_msg_size - size of response message ** Returns: ae_error_t *******************************************************************/ ae_error_t invoke_service_wrapper ( /* IN */ uint64_t tick, /* IN */ uint8_t* req_msg, /* IN */ uint32_t req_msg_size, /* OUT */ uint8_t* resp_msg, /* IN */ uint32_t resp_msg_size) { // check parameter ae_error_t ae_ret = AE_SUCCESS; pse_message_t* pse_req_msg = (pse_message_t*)req_msg; pse_message_t* pse_resp_msg = (pse_message_t*)resp_msg; pse_op_error_t op_ret; if (!req_msg || !resp_msg) { return PSE_OP_PARAMETER_ERROR; } // // make sure the header is inside enclave // if (req_msg_size < sizeof(pse_message_t)) { return PSE_OP_PARAMETER_ERROR; } // // if this mispredicts, we might overflow below // sgx_lfence(); if (pse_req_msg->payload_size > UINT32_MAX - sizeof(pse_message_t) // check potential overflow || req_msg_size != sizeof(pse_message_t) + pse_req_msg->payload_size) { return PSE_OP_PARAMETER_ERROR; } if (resp_msg_size < sizeof(pse_message_t) // make sure the header is inside enclave || pse_req_msg->exp_resp_size > UINT32_MAX - sizeof(pse_message_t) // check potential overflow || resp_msg_size < sizeof(pse_message_t) + pse_req_msg->exp_resp_size) { return PSE_OP_PARAMETER_ERROR; } // // put LFENCE here mostly for pse_req_msg->payload_size // check above. I don't think we use // pse_req_msg->exp_resp_size to calculate // any pointers. // sgx_lfence(); pse_session_t* session = sid2session(pse_req_msg->session_id); // ephemeral session must have been established if(!is_eph_session_active()) { // the ephemeral session is not active return PSE_OP_EPHEMERAL_SESSION_INVALID; } //if session is invalid (session not exists or established, or sequence num overflow) if (!is_isv_session_valid(session)) { return PSE_OP_SESSION_INVALID; } // update session tick update_session_tick_count(session, tick); //clear response message memset(resp_msg, 0, resp_msg_size); uint8_t* req = (uint8_t*)malloc(pse_req_msg->payload_size); uint8_t* resp= NULL; uint32_t session_seq_num = get_session_seq_num(session); do { BREAK_ON_MALLOC_FAIL(req, ae_ret) // decrypt service request message using session key if(false == decrypt_msg(pse_req_msg, req, (sgx_key_128bit_t*)session->active.AEK)) { ae_ret = PSE_OP_SERVICE_MSG_ERROR; break; } pse_req_hdr_t* req_hdr = (pse_req_hdr_t*)req; // check session sequence number if(req_hdr->seq_num != session_seq_num) { ae_ret = PSE_OP_SESSION_INVALID; //close session free_session(session); break; } // Dispatch the service request to the proper handler int i; int service_count = static_cast<int>(sizeof(service_handler) / sizeof(service_handler_t)); for (i = 0; i < service_count; i++) { // // might mispredict the end of the loop // sgx_lfence(); if (req_hdr->service_id == service_handler[i].service_id && req_hdr->service_cmd == service_handler[i].service_cmd) { if (pse_req_msg->payload_size != service_handler[i].req_size || pse_req_msg->exp_resp_size < service_handler[i].resp_size) // response message buffer must be large enough to hold response data { ae_ret = PSE_OP_SERVICE_MSG_ERROR; goto clean_up; } resp = (uint8_t*)malloc(service_handler[i].resp_size); if (resp == NULL) { ae_ret = PSE_OP_INTERNAL_ERROR; goto clean_up; } // // in case payload_size, req_size comparisons // mispredict // sgx_lfence(); // serve the request op_ret = service_handler[i].srv_pfn(session->isv_attributes, req, resp); if(op_ret != OP_SUCCESS) { ae_ret = error_reinterpret(op_ret); goto clean_up; } // set payload size for valid requests pse_resp_msg->payload_size = service_handler[i].resp_size; break; } } if (i == service_count) { // service_id or service_cmd mismatch resp = (uint8_t*)malloc(sizeof(pse_resp_hdr_t)); BREAK_ON_MALLOC_FAIL(resp, ae_ret) // for unknown requests, payload data only includes response header pse_resp_msg->payload_size = sizeof(pse_resp_hdr_t); // set error status ((pse_resp_hdr_t*)resp)->status = PSE_ERROR_UNKNOWN_REQ; } // prepare the response message pse_resp_hdr_t* resp_hdr = (pse_resp_hdr_t*)resp; pse_resp_msg->exp_resp_size = 0; pse_resp_msg->session_id = pse_req_msg->session_id; //set response header, status code is already set in service functions resp_hdr->seq_num = session_seq_num + 1; // addition overflow already checked in is_isv_session_valid() resp_hdr->service_id = req_hdr->service_id; resp_hdr->service_cmd = req_hdr->service_cmd; // update sequence number for current session set_session_seq_num(session, resp_hdr->seq_num + 1); // encrypt the response message if(false == encrypt_msg((pse_message_t*)pse_resp_msg, (uint8_t*)resp, (sgx_key_128bit_t*)session->active.AEK)) { ae_ret = PSE_OP_INTERNAL_ERROR; break; } } while (0); clean_up: SAFE_FREE(req); SAFE_FREE(resp); return ae_ret; }