mirror of
https://github.com/corda/corda.git
synced 2025-01-24 13:28:07 +00:00
6662022bf8
Signed-off-by: Li, Xun <xun.li@email.com>
235 lines
8.5 KiB
C++
235 lines
8.5 KiB
C++
/*
|
|
* Copyright (C) 2011-2016 Intel Corporation. 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 Intel Corporation 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.
|
|
*
|
|
*/
|
|
|
|
|
|
/**
|
|
* File: helper.cpp
|
|
* Description: Cpp file to some helper function to extract some enclave information
|
|
*
|
|
* Wrap functions to get PPID, PWK, PSID, PSVN, PSK and seal/unseal function
|
|
*/
|
|
|
|
#include "helper.h"
|
|
#include "string.h"
|
|
#include "sgx_error.h"
|
|
#include "sgx_utils.h"
|
|
#include "cipher.h"
|
|
#include "sgx_trts.h"
|
|
#include "sgx_tcrypto.h"
|
|
#include <stdlib.h>
|
|
#include "byte_order.h"
|
|
|
|
|
|
//Function to get provisioning key using the provided PSVN
|
|
//If the psvn is NULL, both CPUSVN and ISVSVN is set to 0 (used for PPID generation only)
|
|
//Input: psvn, the psvn used to generate provisioning key
|
|
//Output: key, the provisioning key to return
|
|
// return PVEC_SUCCESS on success
|
|
static pve_status_t get_provision_key(sgx_key_128bit_t *key, const psvn_t *psvn)
|
|
{
|
|
sgx_status_t se_ret = SGX_SUCCESS;
|
|
sgx_key_request_t wrap_key_req;
|
|
|
|
//memset here will also set cpusvn isvsvn to 0 for the case when psvn==NULL
|
|
memset(&wrap_key_req, 0, sizeof(sgx_key_request_t));
|
|
if(psvn==NULL){
|
|
//keeping isv_svn and cpu_svn all 0 according to spec (this is for calcuation of PPID)
|
|
}else{
|
|
memcpy(&wrap_key_req.cpu_svn, &psvn->cpu_svn, sizeof(wrap_key_req.cpu_svn));
|
|
memcpy(&wrap_key_req.isv_svn, &psvn->isv_svn, sizeof(wrap_key_req.isv_svn));
|
|
}
|
|
wrap_key_req.key_name = SGX_KEYSELECT_PROVISION; //provisioning key
|
|
wrap_key_req.attribute_mask.xfrm = 0;
|
|
wrap_key_req.misc_mask = 0xFFFFFFFF;
|
|
wrap_key_req.attribute_mask.flags = ~SGX_FLAGS_MODE64BIT; //set all bits except the SGX_FLAGS_MODE64BIT
|
|
|
|
se_ret = sgx_get_key(&wrap_key_req, key);
|
|
if(SGX_SUCCESS != se_ret)
|
|
{
|
|
return sgx_error_to_pve_error(se_ret);
|
|
}
|
|
return PVEC_SUCCESS;
|
|
}
|
|
|
|
pve_status_t get_ppid(ppid_t* ppid)
|
|
{
|
|
sgx_key_128bit_t key_tmp;
|
|
sgx_status_t sgx_status = SGX_SUCCESS;
|
|
memset(&key_tmp, 0, sizeof(key_tmp));
|
|
|
|
//get Provisioning Key with both CPUSVN and ISVSVN set to 0
|
|
pve_status_t status = get_provision_key(&key_tmp, NULL);
|
|
|
|
if(status != PVEC_SUCCESS){
|
|
(void)memset_s(&key_tmp,sizeof(key_tmp), 0, sizeof(key_tmp));
|
|
return status;
|
|
}
|
|
|
|
uint8_t content[16];
|
|
memset(&content, 0, sizeof(content));
|
|
//generate the mac as PPID
|
|
static_assert(sizeof(sgx_cmac_128bit_key_t) == sizeof(sgx_key_128bit_t), "size of sgx_cmac_128bit_key_t and sgx_key_128bit_t should be same");
|
|
static_assert(sizeof(sgx_cmac_128bit_tag_t) == sizeof(ppid_t), "size of sgx_cmac_128bit_tag_t and ppit_t should be same");
|
|
if((sgx_status=sgx_rijndael128_cmac_msg(reinterpret_cast<const sgx_cmac_128bit_key_t *>(&key_tmp),
|
|
content, sizeof(content), reinterpret_cast<sgx_cmac_128bit_tag_t *>(ppid)))!=SGX_SUCCESS){
|
|
status = sgx_error_to_pve_error(sgx_status);
|
|
}else{
|
|
status = PVEC_SUCCESS;
|
|
}
|
|
(void)memset_s(&key_tmp,sizeof(key_tmp), 0, sizeof(key_tmp));//clear provisioning key in stack
|
|
return status;
|
|
}
|
|
|
|
#define PROV_WRAP_2 "PROV_WRAP_2"
|
|
#define PROV_WRAP_2_LEN 11
|
|
#define START_OFF_PROV_WRAP_2 1
|
|
#define START_OFF_NONCE_2 14
|
|
#define OFF_BYTE_ZERO 30
|
|
#define OFF_BYTE_0X80 31
|
|
//Get Provisioning Wrap2 Key with respect to the PSVN
|
|
pve_status_t get_pwk2(
|
|
const psvn_t* psvn,
|
|
const uint8_t n2[NONCE_2_SIZE],
|
|
sgx_key_128bit_t* wrap_key)
|
|
{
|
|
|
|
if( psvn == NULL)
|
|
return PVEC_PARAMETER_ERROR;
|
|
uint8_t content[32];
|
|
sgx_status_t sgx_status = SGX_SUCCESS;
|
|
sgx_key_128bit_t key_tmp;
|
|
pve_status_t status = PVEC_SUCCESS;
|
|
|
|
memset(&key_tmp, 0, sizeof(key_tmp));
|
|
status = get_provision_key(&key_tmp, psvn); //Generate Provisioning Key with respect to the psvn
|
|
if(status != PVEC_SUCCESS)
|
|
goto ret_point;
|
|
|
|
memset(&content, 0, sizeof(content));
|
|
content[0] = 0x01;
|
|
memcpy(&content[START_OFF_PROV_WRAP_2], PROV_WRAP_2, PROV_WRAP_2_LEN); // byte 1-11 : "PROV_WRAP_2" (ascii encoded)
|
|
memcpy(&content[START_OFF_NONCE_2], n2, NONCE_2_SIZE);
|
|
content[OFF_BYTE_ZERO] = 0x00; //fill zero in byte offset 30
|
|
content[OFF_BYTE_0X80] = 0x80; //fill 0x80 in byte offset 31
|
|
|
|
//get the cmac of provision key as PWK2
|
|
static_assert(sizeof(sgx_cmac_128bit_key_t)==sizeof(key_tmp), "size of sgx_cmac_128bit_key_t should be same as sgx_key_128bit_t");
|
|
static_assert(sizeof(sgx_cmac_128bit_tag_t)==sizeof(sgx_key_128bit_t),"size of sgx_cmac_128bit_tag_t should be same as sgx_key_128bit_t");
|
|
if((sgx_status = sgx_rijndael128_cmac_msg(reinterpret_cast<const sgx_cmac_128bit_key_t *>(&key_tmp),
|
|
reinterpret_cast<const uint8_t *>(content), sizeof(content),
|
|
reinterpret_cast<sgx_cmac_128bit_tag_t *>(wrap_key)))!=SGX_SUCCESS){
|
|
status = sgx_error_to_pve_error(sgx_status);
|
|
}else{
|
|
status = PVEC_SUCCESS;
|
|
}
|
|
ret_point:
|
|
(void)memset_s(&key_tmp,sizeof(key_tmp), 0 ,sizeof(key_tmp)); //clear provisioninig key in stack
|
|
return status;
|
|
}
|
|
|
|
//Function to generate Provisioning Sealing Key given the psvn
|
|
//The key is used to seal the private parameter f before sending to backend server
|
|
pve_status_t get_pve_psk(
|
|
const psvn_t* psvn,
|
|
sgx_key_128bit_t* seal_key)
|
|
{
|
|
|
|
sgx_status_t se_ret = SGX_SUCCESS;
|
|
sgx_key_request_t seal_key_req;
|
|
|
|
if(psvn == NULL)
|
|
return PVEC_PARAMETER_ERROR;
|
|
|
|
memset(&seal_key_req, 0, sizeof(sgx_key_request_t));
|
|
memcpy(&seal_key_req.cpu_svn, &psvn->cpu_svn, SGX_CPUSVN_SIZE);
|
|
memcpy(&seal_key_req.isv_svn, &psvn->isv_svn, sizeof(psvn->isv_svn));
|
|
seal_key_req.key_name = SGX_KEYSELECT_PROVISION_SEAL; //provisioning sealling key
|
|
|
|
seal_key_req.attribute_mask.xfrm = 0;
|
|
seal_key_req.attribute_mask.flags = ~SGX_FLAGS_MODE64BIT;
|
|
|
|
se_ret = sgx_get_key(&seal_key_req, seal_key);
|
|
if(SGX_SUCCESS != se_ret)
|
|
{
|
|
return sgx_error_to_pve_error(se_ret);
|
|
}
|
|
|
|
return PVEC_SUCCESS;
|
|
}
|
|
|
|
//simple wrapper for memcpy but checking type of parameter
|
|
void pve_memcpy_out(external_memory_byte_t *dst, const void *src, uint32_t size)
|
|
{
|
|
memcpy(dst, src, size);
|
|
}
|
|
|
|
void pve_memcpy_in(void *dst, const external_memory_byte_t *src, uint32_t size)
|
|
{
|
|
memcpy(dst, src, size);
|
|
}
|
|
|
|
pve_status_t se_read_rand_error_to_pve_error(sgx_status_t error)
|
|
{
|
|
if(error == SGX_SUCCESS)return PVEC_SUCCESS;
|
|
else if(error == SGX_ERROR_INVALID_PARAMETER) return PVEC_UNEXPECTED_ERROR;
|
|
else return PVEC_READ_RAND_ERROR; //read rand hardware error
|
|
}
|
|
|
|
pve_status_t epid_error_to_pve_error(EpidStatus epid_result)
|
|
{
|
|
if(kEpidNoErr == epid_result)
|
|
return PVEC_SUCCESS;
|
|
switch(epid_result){
|
|
case kEpidMemAllocErr:
|
|
case kEpidNoMemErr:
|
|
return PVEC_MALLOC_ERROR;
|
|
case kEpidSigInvalid:
|
|
return PVEC_INVALID_EPID_KEY;
|
|
default:
|
|
return PVEC_EPID_ERROR;
|
|
}
|
|
}
|
|
|
|
pve_status_t sgx_error_to_pve_error(sgx_status_t status)
|
|
{
|
|
switch(status){
|
|
case SGX_SUCCESS:
|
|
return PVEC_SUCCESS;
|
|
case SGX_ERROR_OUT_OF_MEMORY:
|
|
return PVEC_MALLOC_ERROR;
|
|
case SGX_ERROR_INVALID_CPUSVN:
|
|
case SGX_ERROR_INVALID_ISVSVN:
|
|
return PVEC_INVALID_CPU_ISV_SVN;
|
|
default:
|
|
return PVEC_SE_ERROR;
|
|
}
|
|
}
|