inline std::vector<uint8_t> udg::crypto::seal_data(const uint8_t* data, uint32_t len) { uint32_t out_size = sgx_calc_sealed_data_size(0, len); std::vector<uint8_t> out; out.resize(out_size); auto res = sgx_seal_data(0, nullptr, len, data, out_size, (sgx_sealed_data_t*)(&out[0])); if (res != SGX_SUCCESS) { throw udg::crypto::data_integrity_exception(); } return out; }
void ecall_test_seal_unseal(){ migrate_log("[TEST] [SEAL UNSEAL]\n"); int ret; int secretValue = 1337; uint32_t sealed_data_size = sgx_calc_sealed_data_size(0, sizeof(int)); void* sealed_data = malloc(sealed_data_size); ret = sgx_seal_migratable_data(0, NULL,sizeof(int),(uint8_t*)&secretValue, sealed_data_size, (sgx_sealed_data_t*)sealed_data); migrate_log("Sealed blob with ret code %x\n", ret); int unsealed_value; uint32_t unsealed_size = sizeof(int); ret = sgx_unseal_migratable_data((sgx_sealed_data_t*) sealed_data, NULL, 0, (uint8_t*)&unsealed_value, &unsealed_size); migrate_log("Unsealed blob with ret code %x\n", ret); migrate_log("Sealed value was %u and unsealed was %u\n", secretValue, unsealed_value); if(secretValue == unsealed_value){ migrate_log("[TEST] [SEAL UNSEAL] SUCCESSFULL\n"); } else { migrate_log("[TEST] [SEAL UNSEAL] ERROR\n"); } }
extern "C" sgx_status_t sgx_mac_aadata_ex(const uint16_t key_policy, const sgx_attributes_t attribute_mask, const sgx_misc_select_t misc_mask, const uint32_t additional_MACtext_length, const uint8_t *p_additional_MACtext, const uint32_t sealed_data_size, sgx_sealed_data_t *p_sealed_data) { sgx_status_t err = SGX_ERROR_UNEXPECTED; sgx_report_t report; sgx_key_id_t keyID; sgx_key_request_t tmp_key_request; uint8_t payload_iv[SGX_SEAL_IV_SIZE]; memset(&payload_iv, 0, sizeof(payload_iv)); uint32_t sealedDataSize = sgx_calc_sealed_data_size(additional_MACtext_length, 0); // Check for overflow if (sealedDataSize == UINT32_MAX) { return SGX_ERROR_INVALID_PARAMETER; } // // Check parameters // // check key_request->key_policy reserved bits are not set and one of policy bits are set if ((key_policy & ~(SGX_KEYPOLICY_MRENCLAVE | SGX_KEYPOLICY_MRSIGNER)) || ((key_policy & (SGX_KEYPOLICY_MRENCLAVE | SGX_KEYPOLICY_MRSIGNER)) == 0)) { return SGX_ERROR_INVALID_PARAMETER; } if ((attribute_mask.flags & 0x3) != 0x3) { return SGX_ERROR_INVALID_PARAMETER; } // The AAD must be provided if ((additional_MACtext_length == 0) || (p_additional_MACtext == NULL)) { return SGX_ERROR_INVALID_PARAMETER; } // Ensure AAD does not cross enclave boundary if (!(sgx_is_within_enclave(p_additional_MACtext, additional_MACtext_length) || sgx_is_outside_enclave(p_additional_MACtext, additional_MACtext_length))) { return SGX_ERROR_INVALID_PARAMETER; } // Ensure sealed data blob is within an enclave during the sealing process if ((p_sealed_data == NULL) || (!sgx_is_within_enclave(p_sealed_data, sealed_data_size))) { return SGX_ERROR_INVALID_PARAMETER; } if (sealedDataSize != sealed_data_size) { return SGX_ERROR_INVALID_PARAMETER; } memset(&report, 0, sizeof(sgx_report_t)); memset(p_sealed_data, 0, sealedDataSize); memset(&keyID, 0, sizeof(sgx_key_id_t)); memset(&tmp_key_request, 0, sizeof(sgx_key_request_t)); // Get the report to obtain isv_svn and cpu_svn err = sgx_create_report(NULL, NULL, &report); if (err != SGX_SUCCESS) { goto clear_return; } // Get a random number to populate the key_id of the key_request err = sgx_read_rand(reinterpret_cast<uint8_t *>(&keyID), sizeof(sgx_key_id_t)); if (err != SGX_SUCCESS) { goto clear_return; } memcpy(&(tmp_key_request.cpu_svn), &(report.body.cpu_svn), sizeof(sgx_cpu_svn_t)); memcpy(&(tmp_key_request.isv_svn), &(report.body.isv_svn), sizeof(sgx_isv_svn_t)); tmp_key_request.key_name = SGX_KEYSELECT_SEAL; tmp_key_request.key_policy = key_policy; tmp_key_request.attribute_mask.flags = attribute_mask.flags; tmp_key_request.attribute_mask.xfrm = attribute_mask.xfrm; memcpy(&(tmp_key_request.key_id), &keyID, sizeof(sgx_key_id_t)); tmp_key_request.misc_mask = misc_mask; err = sgx_seal_data_iv(additional_MACtext_length, p_additional_MACtext, 0, NULL, payload_iv, &tmp_key_request, p_sealed_data); if (err == SGX_SUCCESS) { // Copy data from the temporary key request buffer to the sealed data blob memcpy(&(p_sealed_data->key_request), &tmp_key_request, sizeof(sgx_key_request_t)); } clear_return: // Clear temp state memset_s(&report, sizeof(sgx_report_t), 0, sizeof(sgx_report_t)); memset_s(&keyID, sizeof(sgx_key_id_t), 0, sizeof(sgx_key_id_t)); return err; }
extern "C" sgx_status_t sgx_unmac_aadata(const sgx_sealed_data_t *p_sealed_data, uint8_t *p_additional_MACtext, uint32_t *p_additional_MACtext_length) { sgx_status_t err = SGX_ERROR_UNEXPECTED; // Ensure the the sgx_sealed_data_t members are all inside enclave before using them. if ((p_sealed_data == NULL) || (!sgx_is_within_enclave(p_sealed_data, sizeof(sgx_sealed_data_t)))) { return SGX_ERROR_INVALID_PARAMETER; } // If using this API, the sealed blob must have no encrypted data. // So the encryt_text_length must be 0. uint32_t encrypt_text_length = sgx_get_encrypt_txt_len(p_sealed_data); if (encrypt_text_length != 0) { return SGX_ERROR_MAC_MISMATCH; // Return error indicating the blob is corrupted } // The sealed blob must have AAD. So the add_text_length must not be 0. uint32_t add_text_length = sgx_get_add_mac_txt_len(p_sealed_data); if (add_text_length == UINT32_MAX || add_text_length == 0) { return SGX_ERROR_MAC_MISMATCH; // Return error indicating the blob is corrupted } uint32_t sealedDataSize = sgx_calc_sealed_data_size(add_text_length, encrypt_text_length); if (sealedDataSize == UINT32_MAX) { return SGX_ERROR_MAC_MISMATCH; // Return error indicating the blob is corrupted } // // Check parameters // // Ensure sealed data blob is within an enclave during the sealing process if (!sgx_is_within_enclave(p_sealed_data, sealedDataSize)) { return SGX_ERROR_INVALID_PARAMETER; } if (p_additional_MACtext == NULL || p_additional_MACtext_length == NULL) { return SGX_ERROR_INVALID_PARAMETER; } // Ensure AAD does not cross enclave boundary if (!(sgx_is_within_enclave(p_additional_MACtext, add_text_length) || sgx_is_outside_enclave(p_additional_MACtext, add_text_length))) { return SGX_ERROR_INVALID_PARAMETER; } uint32_t additional_MACtext_length = *p_additional_MACtext_length; if (additional_MACtext_length < add_text_length) { return SGX_ERROR_INVALID_PARAMETER; } err = sgx_unseal_data_helper(p_sealed_data, p_additional_MACtext, add_text_length, NULL, encrypt_text_length); if (err == SGX_SUCCESS) { *p_additional_MACtext_length = add_text_length; } return err; }
/* * @func encrypt_ip modifies the content of some sections. * @param INOUT uint8_t* elf_buf, buffer of ELF binary * @param size_t elf_size, size of ELF binary in bytes * @param IN uint8_t* key, AES-GCM-128 key * @param bool debug, true iff enclave is requried to support debug * @return encip_ret_e: * ENCIP_ERROR_ENCRYPTIP_INVALID_PARAM if any input parameter is NULL * Respective error results in case any of the following functions fail: * parse_elf, get_pcl_tbl init_random_iv, encrypt_or_clear_ip_sections or sha256 * ENCIP_ERROR_MEM_ALLOC if memory allocation fails * ENCIP_ERROR_SEALED_BUF_SIZE if sealed buf size exceeds the size allocated for it in PCL table * ENCIP_SUCCESS if success */ encip_ret_e encrypt_ip(INOUT uint8_t* elf_buf, size_t elf_size, IN uint8_t* key, bool debug) { if(NULL == elf_buf || NULL == key) return ENCIP_ERROR_ENCRYPTIP_INVALID_PARAM; encip_ret_e ret = ENCIP_ERROR_FAIL; pcl_data_t dat = { .elf_sec = 0, .shstrndx = 0, .sections_names = NULL, .phdr = NULL, .nsections = 0, .nsegments = 0, }; pcl_table_t* tbl = NULL; ret = parse_elf(elf_buf, elf_size, &dat); if(ENCIP_ERROR(ret)) return ret; ret = get_pcl_tbl(elf_buf, elf_size, &dat, &tbl); if(ENCIP_ERROR(ret)) return ret; // Verify state of binary: if(PCL_CIPHER == tbl->pcl_state) return ENCIP_ERROR_ALREADY_ENCRYPTED; if(PCL_PLAIN != tbl->pcl_state) return ENCIP_ERROR_IMPROPER_STATE; // Encrypt or clear IP sections: uint32_t num_rvas = 0; ret = encrypt_or_clear_ip_sections(&dat, key, elf_buf, elf_size, tbl, &num_rvas, debug); if(ENCIP_ERROR(ret)) return ret; // Set GUID: memcpy(tbl->pcl_guid, g_pcl_guid, sizeof(tbl->pcl_guid)); // Set sealed blob size: tbl->sealed_blob_size = (size_t)sgx_calc_sealed_data_size(SGX_PCL_GUID_SIZE, SGX_AESGCM_KEY_SIZE); // Verify calculated size equals hard coded size of buffer in PCL table: if(PCL_SEALED_BLOB_SIZE != tbl->sealed_blob_size) return ENCIP_ERROR_SEALED_BUF_SIZE; // Set num RVAs: tbl->num_rvas = num_rvas; // Set decryption key sha256 hash result: ret = sha256(key, SGX_AESGCM_KEY_SIZE, tbl->decryption_key_hash); if(ENCIP_ERROR(ret)) return ret; // Set PCL state tbl->pcl_state = PCL_CIPHER; return ENCIP_SUCCESS; } /* * @func print_usage prints sgx_encrypt usage instructions * @param IN char* encip_name is the name of the application */ void print_usage(IN char* encip_name) { printf("\n"); printf("\tUsage: \n"); printf("\t %s -i <input enclave so file name> -o <output enclave so file name> -k <key file name> [-d]\n", encip_name); printf("\t -d (optional) prevents the tool from disabling the debug capabilities\n"); printf("\n"); }
uint32_t ecall_get_required_size(uint32_t add_mac_txt_size, uint32_t txt_encrypt_size){ return sgx_calc_sealed_data_size(add_mac_txt_size, txt_encrypt_size); }