blob: faab34eb6eba7165cd85b98c9a5f2e2a0f6d7bb4 [file] [log] [blame]
// Copyright (C) 2017-2018 Baidu, Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Baidu, Inc., nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Worker.h"
#include "sample_libcrypto.h"
#include "../GeneralSettings.h"
#include "sha256.h"
// This is the private EC key of SP, the corresponding public EC key is
// hard coded in isv_enclave. It is based on NIST P-256 curve.
static const sample_ec256_private_t g_sp_priv_key = {
{
0x90, 0xe7, 0x6c, 0xbb, 0x2d, 0x52, 0xa1, 0xce,
0x3b, 0x66, 0xde, 0x11, 0x43, 0x9c, 0x87, 0xec,
0x1f, 0x86, 0x6a, 0x3b, 0x65, 0xb6, 0xae, 0xea,
0xad, 0x57, 0x34, 0x53, 0xd1, 0x03, 0x8c, 0x01
}
};
PSIWorker::PSIWorker(WebService *ws) : ws(ws) {}
PSIWorker::~PSIWorker() {}
int PSIWorker::sp_ra_proc_msg0_req(const uint32_t id) {
int ret = -1;
if (!this->g_is_sp_registered || (this->extended_epid_group_id != id)) {
Log("Received extended EPID group ID: %d", id);
extended_epid_group_id = id;
this->g_is_sp_registered = true;
ret = SP_OK;
}
return ret;
}
int PSIWorker::sp_ra_proc_msg1_req(Messages::MessageMSG1 msg1, Messages::MessageMSG2 *msg2) {
ra_samp_response_header_t **pp_msg2;
int ret = 0;
ra_samp_response_header_t* p_msg2_full = NULL;
sgx_ra_msg2_t *p_msg2 = NULL;
sample_ecc_state_handle_t ecc_state = NULL;
sample_status_t sample_ret = SAMPLE_SUCCESS;
bool derive_ret = false;
if (!g_is_sp_registered) {
return SP_UNSUPPORTED_EXTENDED_EPID_GROUP;
}
do {
//===================== RETRIEVE SIGRL FROM IAS =======================
uint8_t GID[4];
for (int i=0; i<4; i++)
GID[i] = msg1.gid(i);
reverse(begin(GID), end(GID));
string sigRl;
bool error = false;
error = this->ws->getSigRL(ByteArrayToString(GID, 4), &sigRl);
if (error)
return SP_RETRIEVE_SIGRL_ERROR;
uint8_t *sig_rl;
uint32_t sig_rl_size = StringToByteArray(sigRl, &sig_rl);
//=====================================================================
uint8_t gaXLittleEndian[32];
uint8_t gaYLittleEndian[32];
for (int i=0; i<32; i++) {
gaXLittleEndian[i] = msg1.gax(i);
gaYLittleEndian[i] = msg1.gay(i);
}
sample_ec256_public_t client_pub_key = {{0},{0}};
for (int x=0; x<DH_SHARED_KEY_LEN; x++) {
client_pub_key.gx[x] = gaXLittleEndian[x];
client_pub_key.gy[x] = gaYLittleEndian[x];
}
// Need to save the client's public ECCDH key to local storage
if (memcpy_s(&g_sp_db.g_a, sizeof(g_sp_db.g_a), &client_pub_key, sizeof(client_pub_key))) {
Log("Error, cannot do memcpy", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
// Generate the Service providers ECCDH key pair.
sample_ret = sample_ecc256_open_context(&ecc_state);
if(SAMPLE_SUCCESS != sample_ret) {
Log("Error, cannot get ECC context", log::error);
ret = -1;
break;
}
sample_ec256_public_t pub_key = {{0},{0}};
sample_ec256_private_t priv_key = {{0}};
sample_ret = sample_ecc256_create_key_pair(&priv_key, &pub_key, ecc_state);
if (SAMPLE_SUCCESS != sample_ret) {
Log("Error, cannot get key pair", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
// Need to save the SP ECCDH key pair to local storage.
if (memcpy_s(&g_sp_db.b, sizeof(g_sp_db.b), &priv_key,sizeof(priv_key)) ||
memcpy_s(&g_sp_db.g_b, sizeof(g_sp_db.g_b), &pub_key,sizeof(pub_key))) {
Log("Error, cannot do memcpy", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
// Generate the client/SP shared secret
sample_ec_dh_shared_t dh_key = {{0}};
sample_ret = sample_ecc256_compute_shared_dhkey(&priv_key, (sample_ec256_public_t *)&client_pub_key,
(sample_ec256_dh_shared_t *)&dh_key,
ecc_state);
if (SAMPLE_SUCCESS != sample_ret) {
Log("Error, compute share key fail", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
// smk is only needed for msg2 generation.
derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_SMK, &g_sp_db.smk_key);
if (derive_ret != true) {
Log("Error, derive key fail", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
// The rest of the keys are the shared secrets for future communication.
derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_MK, &g_sp_db.mk_key);
if (derive_ret != true) {
Log("Error, derive key fail", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_SK, &g_sp_db.sk_key);
if (derive_ret != true) {
Log("Error, derive key fail", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_VK, &g_sp_db.vk_key);
if (derive_ret != true) {
Log("Error, derive key fail", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
uint32_t msg2_size = sizeof(sgx_ra_msg2_t) + sig_rl_size;
p_msg2_full = (ra_samp_response_header_t*)malloc(msg2_size + sizeof(ra_samp_response_header_t));
if (!p_msg2_full) {
Log("Error, Error, out of memory", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
memset(p_msg2_full, 0, msg2_size + sizeof(ra_samp_response_header_t));
p_msg2_full->type = RA_MSG2;
p_msg2_full->size = msg2_size;
p_msg2_full->status[0] = 0;
p_msg2_full->status[1] = 0;
p_msg2 = (sgx_ra_msg2_t *) p_msg2_full->body;
uint8_t *spidBa;
HexStringToByteArray(Settings::spid, &spidBa);
for (int i=0; i<16; i++)
p_msg2->spid.id[i] = spidBa[i];
// Assemble MSG2
if(memcpy_s(&p_msg2->g_b, sizeof(p_msg2->g_b), &g_sp_db.g_b, sizeof(g_sp_db.g_b))) {
Log("Error, memcpy failed", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
p_msg2->quote_type = SAMPLE_QUOTE_LINKABLE_SIGNATURE;
p_msg2->kdf_id = AES_CMAC_KDF_ID;
// Create gb_ga
sgx_ec256_public_t gb_ga[2];
if (memcpy_s(&gb_ga[0], sizeof(gb_ga[0]), &g_sp_db.g_b, sizeof(g_sp_db.g_b)) ||
memcpy_s(&gb_ga[1], sizeof(gb_ga[1]), &g_sp_db.g_a, sizeof(g_sp_db.g_a))) {
Log("Error, memcpy failed", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
// Sign gb_ga
sample_ret = sample_ecdsa_sign((uint8_t *)&gb_ga, sizeof(gb_ga),
(sample_ec256_private_t *)&g_sp_priv_key,
(sample_ec256_signature_t *)&p_msg2->sign_gb_ga,
ecc_state);
if (SAMPLE_SUCCESS != sample_ret) {
Log("Error, sign ga_gb fail", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
// Generate the CMACsmk for gb||SPID||TYPE||KDF_ID||Sigsp(gb,ga)
uint8_t mac[SAMPLE_EC_MAC_SIZE] = {0};
uint32_t cmac_size = offsetof(sgx_ra_msg2_t, mac);
sample_ret = sample_rijndael128_cmac_msg(&g_sp_db.smk_key, (uint8_t *)&p_msg2->g_b, cmac_size, &mac);
if (SAMPLE_SUCCESS != sample_ret) {
Log("Error, cmac fail", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
if (memcpy_s(&p_msg2->mac, sizeof(p_msg2->mac), mac, sizeof(mac))) {
Log("Error, memcpy failed", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
if (memcpy_s(&p_msg2->sig_rl[0], sig_rl_size, sig_rl, sig_rl_size)) {
Log("Error, memcpy failed", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
p_msg2->sig_rl_size = sig_rl_size;
} while(0);
if (ret) {
*pp_msg2 = NULL;
SafeFree(p_msg2_full);
} else {
//================= SET MSG2 Fields ================
msg2->set_size(p_msg2_full->size);
for (auto x : p_msg2->g_b.gx)
msg2->add_public_key_gx(x);
for (auto x : p_msg2->g_b.gy)
msg2->add_public_key_gy(x);
for (auto x : p_msg2->spid.id)
msg2->add_spid(x);
msg2->set_quote_type(SAMPLE_QUOTE_LINKABLE_SIGNATURE);
msg2->set_cmac_kdf_id(AES_CMAC_KDF_ID);
for (auto x : p_msg2->sign_gb_ga.x) {
msg2->add_signature_x(x);
}
for (auto x : p_msg2->sign_gb_ga.y)
msg2->add_signature_y(x);
for (auto x : p_msg2->mac)
msg2->add_smac(x);
msg2->set_size_sigrl(p_msg2->sig_rl_size);
for (int i=0; i<p_msg2->sig_rl_size; i++)
msg2->add_sigrl(p_msg2->sig_rl[i]);
//=====================================================
}
if (ecc_state) {
sample_ecc256_close_context(ecc_state);
}
return ret;
}
sgx_ra_msg3_t* PSIWorker::assembleMSG3(Messages::MessageMSG3 msg) {
sgx_ra_msg3_t *p_msg3 = (sgx_ra_msg3_t*) malloc(msg.size());
for (int i=0; i<SGX_MAC_SIZE; i++)
p_msg3->mac[i] = msg.sgx_mac(i);
for (int i=0; i<SGX_ECP256_KEY_SIZE; i++) {
p_msg3->g_a.gx[i] = msg.gax_msg3(i);
p_msg3->g_a.gy[i] = msg.gay_msg3(i);
}
for (int i=0; i<256; i++)
p_msg3->ps_sec_prop.sgx_ps_sec_prop_desc[i] = msg.sec_property(i);
for (int i=0; i<1116; i++)
p_msg3->quote[i] = msg.quote(i);
return p_msg3;
}
// Process remote attestation message 3
int PSIWorker::sp_ra_proc_msg3_req(Messages::MessageMSG3 msg, Messages::AttestationMessage *att_msg) {
int ret = 0;
sample_status_t sample_ret = SAMPLE_SUCCESS;
const uint8_t *p_msg3_cmaced = NULL;
sgx_quote_t *p_quote = NULL;
sample_sha_state_handle_t sha_handle = NULL;
sample_report_data_t report_data = {0};
sample_ra_att_result_msg_t *p_att_result_msg = NULL;
ra_samp_response_header_t* p_att_result_msg_full = NULL;
uint32_t i;
sgx_ra_msg3_t *p_msg3 = NULL;
uint32_t att_result_msg_size;
int len_hmac_nonce = 0;
p_msg3 = assembleMSG3(msg);
// Check to see if we have registered?
if (!g_is_sp_registered) {
Log("Unsupported extended EPID group", log::error);
return -1;
}
do {
// Compare g_a in message 3 with local g_a.
if (memcmp(&g_sp_db.g_a, &p_msg3->g_a, sizeof(sgx_ec256_public_t))) {
Log("Error, g_a is not same", log::error);
ret = SP_PROTOCOL_ERROR;
break;
}
//Make sure that msg3_size is bigger than sample_mac_t.
uint32_t mac_size = msg.size() - sizeof(sample_mac_t);
p_msg3_cmaced = reinterpret_cast<const uint8_t*>(p_msg3);
p_msg3_cmaced += sizeof(sample_mac_t);
// Verify the message mac using SMK
sample_cmac_128bit_tag_t mac = {0};
sample_ret = sample_rijndael128_cmac_msg(&g_sp_db.smk_key, p_msg3_cmaced, mac_size, &mac);
if (SAMPLE_SUCCESS != sample_ret) {
Log("Error, cmac fail", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
if (memcmp(&p_msg3->mac, mac, sizeof(mac))) {
Log("Error, verify cmac fail", log::error);
ret = SP_INTEGRITY_FAILED;
break;
}
if (memcpy_s(&g_sp_db.ps_sec_prop, sizeof(g_sp_db.ps_sec_prop), &p_msg3->ps_sec_prop, sizeof(p_msg3->ps_sec_prop))) {
Log("Error, memcpy fail", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
p_quote = (sgx_quote_t *) p_msg3->quote;
// Verify the report_data in the Quote matches the expected value.
// The first 32 bytes of report_data are SHA256 HASH of {ga|gb|vk}.
// The second 32 bytes of report_data are set to zero.
sample_ret = sample_sha256_init(&sha_handle);
if (sample_ret != SAMPLE_SUCCESS) {
Log("Error, init hash failed", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
sample_ret = sample_sha256_update((uint8_t *)&(g_sp_db.g_a), sizeof(g_sp_db.g_a), sha_handle);
if (sample_ret != SAMPLE_SUCCESS) {
Log("Error, udpate hash failed", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
sample_ret = sample_sha256_update((uint8_t *)&(g_sp_db.g_b), sizeof(g_sp_db.g_b), sha_handle);
if (sample_ret != SAMPLE_SUCCESS) {
Log("Error, udpate hash failed", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
sample_ret = sample_sha256_update((uint8_t *)&(g_sp_db.vk_key), sizeof(g_sp_db.vk_key), sha_handle);
if (sample_ret != SAMPLE_SUCCESS) {
Log("Error, udpate hash failed", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
sample_ret = sample_sha256_get_hash(sha_handle, (sample_sha256_hash_t *)&report_data);
if (sample_ret != SAMPLE_SUCCESS) {
Log("Error, Get hash failed", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
if (memcmp((uint8_t *)&report_data, (uint8_t *)&(p_quote->report_body.report_data), sizeof(report_data))) {
Log("Error, verify hash failed", log::error);
ret = SP_INTEGRITY_FAILED;
break;
}
// Verify quote with attestation server.
ias_att_report_t attestation_report = {0};
ret = ias_verify_attestation_evidence(p_msg3->quote, p_msg3->ps_sec_prop.sgx_ps_sec_prop_desc, &attestation_report, ws);
if (0 != ret) {
ret = SP_IAS_FAILED;
break;
}
Log("Atestation Report:");
Log("\tid: %s", attestation_report.id);
Log("\tstatus: %d", attestation_report.status);
Log("\trevocation_reason: %u", attestation_report.revocation_reason);
Log("\tpse_status: %d", attestation_report.pse_status);
Log("Enclave Report:");
Log("\tSignature Type: 0x%x", p_quote->sign_type);
Log("\tSignature Basename: %s", ByteArrayToNoHexString(p_quote->basename.name, 32));
Log("\tattributes.flags: 0x%0lx", p_quote->report_body.attributes.flags);
Log("\tattributes.xfrm: 0x%0lx", p_quote->report_body.attributes.xfrm);
Log("\tmr_enclave: %s", ByteArrayToString(p_quote->report_body.mr_enclave.m, SGX_HASH_SIZE));
Log("\tmr_signer: %s", ByteArrayToString(p_quote->report_body.mr_signer.m, SGX_HASH_SIZE));
Log("\tisv_prod_id: 0x%0x", p_quote->report_body.isv_prod_id);
Log("\tisv_svn: 0x%0x", p_quote->report_body.isv_svn);
// Respond the client with the results of the attestation.
att_result_msg_size = sizeof(sample_ra_att_result_msg_t);
p_att_result_msg_full = (ra_samp_response_header_t*) malloc(att_result_msg_size + sizeof(ra_samp_response_header_t) + sizeof(validation_result));
if (!p_att_result_msg_full) {
Log("Error, out of memory", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
memset(p_att_result_msg_full, 0, att_result_msg_size + sizeof(ra_samp_response_header_t) + sizeof(validation_result));
p_att_result_msg_full->type = RA_ATT_RESULT;
p_att_result_msg_full->size = att_result_msg_size;
if (IAS_QUOTE_OK != attestation_report.status) {
p_att_result_msg_full->status[0] = 0xFF;
}
if (IAS_PSE_OK != attestation_report.pse_status) {
p_att_result_msg_full->status[1] = 0xFF;
}
p_att_result_msg = (sample_ra_att_result_msg_t *)p_att_result_msg_full->body;
bool isv_policy_passed = true;
p_att_result_msg->platform_info_blob = attestation_report.info_blob;
// Generate mac based on the mk key.
mac_size = sizeof(ias_platform_info_blob_t);
sample_ret = sample_rijndael128_cmac_msg(&g_sp_db.mk_key,
(const uint8_t*)&p_att_result_msg->platform_info_blob,
mac_size,
&p_att_result_msg->mac);
if (SAMPLE_SUCCESS != sample_ret) {
Log("Error, cmac fail", log::error);
ret = SP_INTERNAL_ERROR;
break;
}
// Generate shared secret and encrypt it with SK, if attestation passed.
uint8_t aes_gcm_iv[SAMPLE_SP_IV_SIZE] = {0};
p_att_result_msg->secret.payload_size = MAX_VERIFICATION_RESULT;
if ((IAS_QUOTE_OK == attestation_report.status) &&
(IAS_PSE_OK == attestation_report.pse_status) &&
(isv_policy_passed == true)) {
memset(validation_result, '\0', MAX_VERIFICATION_RESULT);
validation_result[0] = 0;
validation_result[1] = 1;
ret = sample_rijndael128GCM_encrypt(&g_sp_db.sk_key,
&validation_result[0],
p_att_result_msg->secret.payload_size,
p_att_result_msg->secret.payload,
&aes_gcm_iv[0],
SAMPLE_SP_IV_SIZE,
NULL,
0,
&p_att_result_msg->secret.payload_tag);
}
} while(0);
if (ret) {
SafeFree(p_att_result_msg_full);
return -1;
} else {
att_msg->set_size(att_result_msg_size);
ias_platform_info_blob_t platform_info_blob = p_att_result_msg->platform_info_blob;
att_msg->set_epid_group_status(platform_info_blob.sample_epid_group_status);
att_msg->set_tcb_evaluation_status(platform_info_blob.sample_tcb_evaluation_status);
att_msg->set_pse_evaluation_status(platform_info_blob.pse_evaluation_status);
for (int i=0; i<PSVN_SIZE; i++)
att_msg->add_latest_equivalent_tcb_psvn(platform_info_blob.latest_equivalent_tcb_psvn[i]);
for (int i=0; i<ISVSVN_SIZE; i++)
att_msg->add_latest_pse_isvsvn(platform_info_blob.latest_pse_isvsvn[i]);
for (int i=0; i<PSDA_SVN_SIZE; i++)
att_msg->add_latest_psda_svn(platform_info_blob.latest_psda_svn[i]);
for (int i=0; i<GID_SIZE; i++)
att_msg->add_performance_rekey_gid(platform_info_blob.performance_rekey_gid[i]);
for (int i=0; i<SAMPLE_NISTP256_KEY_SIZE; i++) {
att_msg->add_ec_sign256_x(platform_info_blob.signature.x[i]);
att_msg->add_ec_sign256_y(platform_info_blob.signature.y[i]);
}
for (int i=0; i<SAMPLE_MAC_SIZE; i++)
att_msg->add_mac_smk(p_att_result_msg->mac[i]);
att_msg->set_result_size(p_att_result_msg->secret.payload_size);
for (int i=0; i<12; i++)
att_msg->add_reserved(p_att_result_msg->secret.reserved[i]);
for (int i=0; i<16; i++)
att_msg->add_payload_tag(p_att_result_msg->secret.payload_tag[i]);
for (int i=0; i<p_att_result_msg->secret.payload_size; i++)
att_msg->add_payload(p_att_result_msg->secret.payload[i]);
}
return ret;
}
void PSIWorker::set_hash_path(string path) {
this->hash_path = path;
}
int PSIWorker::set_hash_salt(Messages::MessagePsiSalt msg) {
uint8_t salt[SALT_SIZE];
uint8_t ciphertext[SALT_SIZE];
sample_aes_gcm_128bit_tag_t in_mac = {0};
for (int i=0; i<SALT_SIZE; i++) {
ciphertext[i] = (uint8_t)msg.salt(i);
}
for (int i=0; i<sizeof(sample_aes_gcm_128bit_tag_t); i++) {
in_mac[i] = (uint8_t)msg.mac(i);
}
uint8_t aes_gcm_iv[SAMPLE_SP_IV_SIZE] = {0};
int ret = sample_rijndael128GCM_decrypt(&g_sp_db.sk_key,
&ciphertext[0],
SALT_SIZE,
&salt[0],
&aes_gcm_iv[0],
SAMPLE_SP_IV_SIZE,
NULL,
0,
&in_mac);
if (ret != SAMPLE_SUCCESS) {
Log("decrypt salt failed! %d", ret);
return -1;
}
string psi_salt = ByteArrayToString(salt, SALT_SIZE);
this->psi_salt = psi_salt;
//printf_array("salt: ", salt, SALT_SIZE);
Log("Received SALT: %s", psi_salt);
return 0;
}
bool PSIWorker::sp_psi_is_finish_get_data() {
return this->hash_vector_cursor >= this->hash_vector.size();
}
int PSIWorker::sp_psi_get_data_hash(Messages::MessagePsiHashData *data) {
int ret = 0;
if (this->hash_vector.size() <= 0) {
//read file
uint8_t * file_data = NULL;
int file_size = 0;
//No duplicate data by default
file_size = ReadFileToBuffer(this->hash_path, &file_data);
if (file_size <= 0) {
return -1;
}
char * p = (char*)file_data;
const char * s = p;
char* n = (char*)p;
for( ; p - s < file_size; p = n + 1) {
n = strchr(p, '\n');
if (n == NULL) {
//only one line or last line
n = p + strlen(p);
} else {
n[0] = '\0';
}
if (strlen(p) <= 0) {//ignore null line
continue;
}
sample_sha256_hash_t report_data = {0};
Sha256 sha256;
sha256.update((uint8_t*)p, strlen(p));
sha256.update((uint8_t*)this->psi_salt.c_str(), this->psi_salt.size());
sha256.hash((sample_sha256_hash_t * )&report_data);
string hash = ByteArrayToString(report_data, sizeof(sample_sha256_hash_t));
this->hash_vector.push_back(hash);
this->data_map[hash] = p;
Log("[PSI] Init data: %s, hash: %s", p, ByteArrayToString((const uint8_t*)&report_data, sizeof(sample_sha256_hash_t)));
}
Log("[PSI] Init all data, size: %d", this->hash_vector.size());
std::sort(this->hash_vector.begin(), this->hash_vector.end());
this->hash_vector_cursor = 0;
}
if (this->hash_vector_cursor >= this->hash_vector.size()) {
return -1;
}
int count = PSI_HASH_DATA_COUNT;
if (this->hash_vector_cursor + PSI_HASH_DATA_COUNT > this->hash_vector.size()) {
count = this->hash_vector.size() - this->hash_vector_cursor;
}
int payload_size = count * SAMPLE_SHA256_HASH_SIZE;
uint8_t payload[payload_size] = {0};
uint8_t enc_data[payload_size] = {0};
for (int i = 0; i < count; i++) {
uint8_t * arr = NULL;
int size = HexStringToByteArray(this->hash_vector[this->hash_vector_cursor + i], &arr);
if (size != sizeof(sample_sha256_hash_t)) {
Log("[PSI] Get hash vector , something error: %d, %d, %s", size, sizeof(sample_sha256_hash_t), this->hash_vector[this->hash_vector_cursor + i]);
return -1;
}
memcpy(payload + i*sizeof(sample_sha256_hash_t), arr, size);
}
this->hash_vector_cursor += count;
uint8_t aes_gcm_iv[SAMPLE_SP_IV_SIZE] = {0};
sample_aes_gcm_128bit_tag_t out_mac = {0};
ret = sample_rijndael128GCM_encrypt(&g_sp_db.sk_key,
payload,
payload_size,
enc_data,
&aes_gcm_iv[0],
SAMPLE_SP_IV_SIZE,
NULL,
0,
&out_mac);
if (ret == -1) {
Log("sample_rijndael128GCM_encrypt failed");
return -1;
}
int data_size = sizeof(uint32_t) + sizeof(sample_aes_gcm_128bit_tag_t) + payload_size;
data->set_size(data_size);
for (int i = 0; i < sizeof(sample_aes_gcm_128bit_tag_t); i++) {
data->add_mac(out_mac[i]);
}
for (int i = 0; i < payload_size; i++) {
data->add_data((uint32_t)enc_data[i]);
}
return 0;
}
int PSIWorker::sp_psi_intersect(Messages::MessagePsiIntersect msg) {
sample_aes_gcm_128bit_tag_t in_mac = {0};
for (int i = 0; i < sizeof(sample_aes_gcm_128bit_tag_t); i++) {
in_mac[i] = (uint8_t)msg.mac(i);
}
int data_size = msg.data_size();
uint8_t* data = (uint8_t*)malloc(data_size);
uint8_t* dec_data = (uint8_t*)malloc(data_size);
for (int i = 0; i < data_size; i++) {
data[i] = (uint8_t)msg.data(i);
}
uint8_t aes_gcm_iv[SAMPLE_SP_IV_SIZE] = {0};
int ret = sample_rijndael128GCM_decrypt(&g_sp_db.sk_key,
&data[0],
data_size,
&dec_data[0],
&aes_gcm_iv[0],
SAMPLE_SP_IV_SIZE,
NULL,
0,
&in_mac);
if (ret != SAMPLE_SUCCESS) {
Log("sample_rijndael128GCM_decrypt failed, %d", ret);
SafeFree(data);
SafeFree(dec_data);
return -1;
}
// int hash_cnt = data_size / SAMPLE_SHA256_HASH_SIZE;
// for (int i = 0; i < hash_cnt; i++) {
// sample_sha256_hash_t hash = {0};
// memcpy(hash, &dec_data[i*SAMPLE_SHA256_HASH_SIZE], SAMPLE_SHA256_HASH_SIZE);
// string hash_str = ByteArrayToString(hash, SAMPLE_SHA256_HASH_SIZE);
// Log("[PSI] Intersect result: %s", this->data_map[hash_str]);
// }
int hash_cnt = 0;
for (int i = 0; i < data_size && i < this->hash_vector.size(); i++) {
if (dec_data[i]) {
hash_cnt++;
string hash_str = this->hash_vector[i];
Log("[PSI] Intersect result: %s", this->data_map[hash_str]);
}
}
Log("[PSI] Intersect result count: %d", hash_cnt);
SafeFree(data);
SafeFree(dec_data);
return 0;
}