/******************************************** KeyMaster V2 OEM API ALLWINNER TECH.CO 2018-01-18 ********************************************/ #define LOG_TAG "Keymaster_na" #define LOG_NDEBUG 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "include/keymaster_errno.h" #include "include/keymaster_def.h" #include #include #include #include typedef keymaster2_device_t keymaster_device_t; typedef UniquePtr Unique_keymaster_device_t; enum { MSG_KEYMASTER_V2_INITIALIZE = 0x201, MSG_KEYMASTER_V2_TERMINATE = 0x202, MSG_KEYMASTER_V2_CONFIGURE = 0x210, MSG_KEYMASTER_V2_ADD_RNG_ENTROPY = 0x212, MSG_KEYMASTER_V2_GENERATE_KEY = 0x214, MSG_KEYMASTER_V2_GET_KEY_CHARAC = 0x216, MSG_KEYMASTER_V2_IMPORT_KEY = 0x21B, MSG_KEYMASTER_V2_EXPORT_KEY = 0x21D, MSG_KEYMASTER_V2_ATTEST_KEY = 0x21E, MSG_KEYMASTER_V2_UPGRAGE_KEY = 0x220, MSG_KEYMASTER_V2_DELETE_KEY = 0x222, MSG_KEYMASTER_V2_DELETE_ALL_KEYS = 0x224, MSG_KEYMASTER_V2_BEGIN = 0x226, MSG_KEYMASTER_V2_UPDATE = 0x228, MSG_KEYMASTER_V2_FINISH = 0x22A, MSG_KEYMASTER_V2_ABORT = 0x22C, MSG_KEYMASTER_V2_MAX }; #define TEE_KEYMASTER_KEY_INOUT_COMMON_SIZE (70 * 1024) //UUID for keymaster v2 static const uint8_t KeyMaster_v2_UUID[16] = { 0x49,0xb5,0xf7,0xf5,0x64,0xba,0xfe,0x44, 0x9b,0x74,0xf3,0xfc,0x35,0x7c,0x7c,0x61 }; static pthread_mutex_t gKeyMasterV2Mutex = PTHREAD_MUTEX_INITIALIZER; static TEEC_Context *gKeyMasterV2Context = NULL; static TEEC_Session *gKeyMasterV2Session = NULL; static bool keymaster_v2_configured = 0; typedef struct { uint32_t buf; int size; }TEE_params_set; typedef struct { int buff_count; int buff_total_size; }TEE_params_expand; typedef struct { uint32_t params; /* may be NULL if length == 0 */ uint32_t length; } tee_keymaster_key_param_set_t; typedef struct { uint32_t data_offset; uint32_t data_length; } tee_keymaster_blob_t; typedef struct { keymaster_tag_t tag; union { uint32_t enumerated; /* KM_ENUM and KM_ENUM_REP */ bool boolean; /* KM_BOOL */ uint32_t integer; /* KM_INT and KM_INT_REP */ uint64_t long_integer; /* KM_LONG */ uint64_t date_time; /* KM_DATE */ tee_keymaster_blob_t blob; /* KM_BIGNUM and KM_BYTES*/ }; }tee_keymaster_key_param_t; typedef struct { uint32_t entries_offset; uint32_t entry_count; } tee_keymaster_cert_chain_t; typedef struct { tee_keymaster_key_param_set_t hw_enforced; tee_keymaster_key_param_set_t sw_enforced; } tee_keymaster_key_characteristics_t; static inline int tag_is_blob(keymaster_tag_t tag) { keymaster_tag_type_t t = (keymaster_tag_type_t)(tag & (0xF << 28)); return ( t== KM_BYTES || t == KM_BIGNUM); } #if 0 void tee_hexdump(unsigned char * data, int size) { int i = 0; int line ; char tmp[32 + 16 + 11 + 1]; int offset = 0; ALOGV("data buf=%p, size=%d\n", data, size); for(line = 0; offset < size; line ++ ) { sprintf(&tmp[0], "0x%08x: ", line*16); if(size - offset >= 16) { for(i = 0; i < 16; i++) { sprintf(&tmp[(i + 1) * 3 + 8], "%02x ", data[offset + i]); } offset += 16; } else { for(i = 0; i < size - offset; i++) { sprintf(&tmp[(i + 1) * 3 + 8], "%02x ", data[offset + i]); } offset = size; } tmp[32 + 16 + 11] = '\0'; ALOGV("%s", tmp); } } static void tee_ParamSet_view(const keymaster_key_param_set_t* set) { size_t i; keymaster_key_param_t* params = set->params; ALOGV("params count=%d", (unsigned int)set->length); for(i=0;ilength;i++) { ALOGV("params[%d].tag = 0x%x", (unsigned int)i, params[i].tag); if (tag_is_blob(params[i].tag)) { ALOGV(" buffer: size=0x%x", (unsigned int)params[i].blob.data_length); } else { ALOGV(" value: 0x%x", params[i].integer); } } } #endif static size_t compute_param_set_length(const keymaster_key_param_set_t* set) { size_t i, total_length; keymaster_key_param_t* params = set->params; total_length = sizeof(tee_keymaster_key_param_set_t) + sizeof(tee_keymaster_key_param_t) * set->length; for(i=0;ilength;i++) { if (tag_is_blob(params[i].tag)) { total_length += params[i].blob.data_length; } } return total_length; } static size_t tee_copy_params2_buf(uint8_t* buf, const keymaster_key_param_set_t *params) { size_t i, buf_size = 0; tee_keymaster_key_param_t *tee_params_buf; uint8_t *tee_data_buf; tee_keymaster_key_param_set_t *set = (tee_keymaster_key_param_set_t *)buf; //tee_hexdump((uint8_t*)params->params, 256); //fill key_param_set set->params = sizeof(tee_keymaster_key_param_set_t); set->length = params->length; //fill key_params tee_params_buf =(tee_keymaster_key_param_t*)(buf + sizeof(tee_keymaster_key_param_set_t)); tee_data_buf = buf + sizeof(tee_keymaster_key_param_set_t) + sizeof(tee_keymaster_key_param_t) * params->length; //fill blob for(i=0;ilength;i++) { tee_params_buf[i].tag = params->params[i].tag; keymaster_tag_type_t type = keymaster_tag_get_type(params->params[i].tag); switch(type){ case KM_INVALID: break; case KM_ENUM: case KM_ENUM_REP: tee_params_buf[i].enumerated = params->params[i].enumerated; break; case KM_BOOL: tee_params_buf[i].boolean = params->params[i].boolean; break; case KM_UINT: case KM_UINT_REP: tee_params_buf[i].integer = params->params[i].integer; break; case KM_ULONG: case KM_ULONG_REP: tee_params_buf[i].long_integer = params->params[i].long_integer; break; case KM_DATE: tee_params_buf[i].date_time = params->params[i].date_time; break; case KM_BIGNUM: case KM_BYTES: tee_params_buf[i].blob.data_offset = (uint32_t)(tee_data_buf - buf); tee_params_buf[i].blob.data_length = params->params[i].blob.data_length; memcpy(tee_data_buf, params->params[i].blob.data, params->params[i].blob.data_length); tee_data_buf += params->params[i].blob.data_length; break; } } buf_size = (size_t)(tee_data_buf - buf); return buf_size; } static void tee_CopyToParamSet(uint8_t *src, keymaster_key_param_set_t *set, uint8_t *base) { tee_keymaster_key_param_set_t *tee_input = (tee_keymaster_key_param_set_t *)src; uint8_t *params_buf = base + tee_input->params; uint32_t length = tee_input->length; set->length = length; if (length == 0) { set->params = NULL; return ; } set->params = reinterpret_cast (malloc(sizeof(keymaster_key_param_t) * length)); memset(set->params, 0, sizeof(keymaster_key_param_t) * length); tee_keymaster_key_param_t *param = (tee_keymaster_key_param_t *)params_buf; keymaster_key_param_t *dst = set->params; for (size_t i = 0; i < length; ++i) { dst[i].tag = param[i].tag; keymaster_tag_type_t type = keymaster_tag_get_type(param[i].tag); switch(type){ case KM_INVALID: break; case KM_ENUM: case KM_ENUM_REP: dst[i].enumerated = param[i].enumerated; break; case KM_BOOL: dst[i].boolean = param[i].boolean; break; case KM_UINT: case KM_UINT_REP: dst[i].integer= param[i].integer; break; case KM_ULONG: case KM_ULONG_REP: dst[i].long_integer= param[i].long_integer; break; case KM_DATE: dst[i].date_time= param[i].date_time; break; case KM_BIGNUM: case KM_BYTES: void *tmp = malloc(param[i].blob.data_length); memcpy(tmp, (void *)(base + param[i].blob.data_offset), param[i].blob.data_length); dst[i].blob.data = reinterpret_cast(tmp); dst[i].blob.data_length = param[i].blob.data_length; break; } } } int KeyMaster_V2_Initialize(void) { ALOGV("%s %d", __func__, __LINE__); pthread_mutex_lock(&gKeyMasterV2Mutex); if(gKeyMasterV2Context != NULL) { pthread_mutex_unlock(&gKeyMasterV2Mutex); return -1; } gKeyMasterV2Context = (TEEC_Context *)malloc(sizeof(TEEC_Context)); gKeyMasterV2Session = (TEEC_Session *)malloc(sizeof(TEEC_Session)); assert(gKeyMasterV2Context != NULL); assert(gKeyMasterV2Session != NULL); pthread_mutex_unlock(&gKeyMasterV2Mutex); TEEC_Result success = TEEC_InitializeContext(NULL, gKeyMasterV2Context); if (success != TEEC_SUCCESS) { ALOGE("initialize context failed"); return -1; } success = TEEC_OpenSession(gKeyMasterV2Context, gKeyMasterV2Session, (const TEEC_UUID *)&KeyMaster_v2_UUID[0], TEEC_LOGIN_PUBLIC, NULL, NULL, NULL); if(success != TEEC_SUCCESS) { ALOGE("open session failed"); return -1; } TEEC_Operation operation; memset(&operation, 0, sizeof(TEEC_Operation)); operation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE); operation.started = 1; success = TEEC_InvokeCommand(gKeyMasterV2Session, MSG_KEYMASTER_V2_INITIALIZE, &operation, NULL); return (int) success; } int KeyMaster_V2_Terminate(void) { ALOGV("%s %d", __func__, __LINE__); pthread_mutex_lock(&gKeyMasterV2Mutex); if(gKeyMasterV2Context == NULL) { pthread_mutex_unlock(&gKeyMasterV2Mutex); return 0; } TEEC_Operation operation; memset(&operation, 0, sizeof(TEEC_Operation)); operation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE); operation.started = 1; TEEC_Result success = TEEC_InvokeCommand(gKeyMasterV2Session, MSG_KEYMASTER_V2_TERMINATE, &operation, NULL); if (success != TEEC_SUCCESS) { ALOGE("call invoke command error"); } TEEC_CloseSession(gKeyMasterV2Session); TEEC_FinalizeContext(gKeyMasterV2Context); free(gKeyMasterV2Session); free(gKeyMasterV2Context); gKeyMasterV2Session = NULL; gKeyMasterV2Context = NULL; pthread_mutex_unlock(&gKeyMasterV2Mutex); keymaster_v2_configured = 0; return (int) success; } keymaster_error_t KeyMaster_V2_Configure(const keymaster_device_t* dev, const keymaster_key_param_set_t* params){ ALOGV("%s %d", __func__, __LINE__); if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; keymaster_error_t err_type = KM_ERROR_OK; uint32_t paramsize; paramsize = compute_param_set_length(params); TEEC_SharedMemory paramMem; paramMem.size = paramsize; paramMem.flags = TEEC_MEM_INPUT ; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, ¶mMem) != TEEC_SUCCESS) { ALOGE("allocate share memory fail"); return KM_ERROR_UNKNOWN_ERROR; } tee_copy_params2_buf((uint8_t*)paramMem.buffer, params); TEEC_Operation operation; memset(&operation, 0, sizeof(TEEC_Operation)); operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, TEEC_NONE, TEEC_NONE, TEEC_NONE); operation.started = 1; operation.params[0].memref.parent = ¶mMem; operation.params[0].memref.offset = 0; operation.params[0].memref.size = 0; int success = TEEC_InvokeCommand(gKeyMasterV2Session, MSG_KEYMASTER_V2_CONFIGURE, &operation, NULL); if (!success){ keymaster_v2_configured = 1; } if (success < KM_ERROR_UNKNOWN_ERROR){ err_type = KM_ERROR_UNKNOWN_ERROR; }else { err_type = (keymaster_error_t) success; } //__configure_err: TEEC_ReleaseSharedMemory(¶mMem); if(err_type != KM_ERROR_OK) ALOGE("%s failed with %d", __func__, err_type); return err_type; } keymaster_error_t KeyMaster_V2_Add_Rng_Entropy(const keymaster_device_t* dev, const uint8_t* data, size_t data_length){ ALOGV("%s %d", __func__, __LINE__); if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!keymaster_v2_configured) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; keymaster_error_t err_type = KM_ERROR_OK; TEEC_SharedMemory data_p; data_p.size = data_length; data_p.flags = TEEC_MEM_INPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &data_p) != TEEC_SUCCESS) { ALOGE("%s: allocate output data share memory fail", __func__); return KM_ERROR_UNKNOWN_ERROR; } memcpy(data_p.buffer, data, data_length); TEEC_Operation operation; memset(&operation, 0, sizeof(TEEC_Operation)); operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, TEEC_NONE, TEEC_NONE, TEEC_NONE); operation.started = 1; operation.params[0].memref.parent = &data_p; operation.params[0].memref.offset = 0; operation.params[0].memref.size = 0; int success = TEEC_InvokeCommand(gKeyMasterV2Session, MSG_KEYMASTER_V2_ADD_RNG_ENTROPY, &operation, NULL); if (success < KM_ERROR_UNKNOWN_ERROR){ err_type = KM_ERROR_UNKNOWN_ERROR; }else { err_type = (keymaster_error_t) success; } //__add_rng_entropy_err: TEEC_ReleaseSharedMemory(&data_p); if(err_type != KM_ERROR_OK) ALOGE("%s failed with %d", __func__, err_type); return err_type; } keymaster_error_t KeyMaster_V2_Generate_Key(const keymaster_device_t* dev, const keymaster_key_param_set_t* params, keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t* characteristics){ ALOGV("%s %d", __func__, __LINE__); if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!key_blob) return KM_ERROR_OUTPUT_PARAMETER_NULL; if (!keymaster_v2_configured) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; keymaster_error_t err_type = KM_ERROR_OK; uint32_t paramsize; paramsize = compute_param_set_length(params); TEEC_SharedMemory tee_params_p; tee_params_p.size = paramsize; tee_params_p.flags = TEEC_MEM_INPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &tee_params_p) != TEEC_SUCCESS) { ALOGE("%s: allocate params share memory fail", __func__); return KM_ERROR_UNKNOWN_ERROR; } //ALOGE("tee_params_p.buffer=%p", tee_params_p.buffer); tee_copy_params2_buf((uint8_t*)tee_params_p.buffer, params); //tee_hexdump((uint8_t*)tee_params_p.buffer, params_buf_size); TEEC_SharedMemory tee_material_p; tee_material_p.size = TEE_KEYMASTER_KEY_INOUT_COMMON_SIZE; tee_material_p.flags = TEEC_MEM_OUTPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &tee_material_p) != TEEC_SUCCESS) { ALOGE("%s: allocate key material share memory fail", __func__); TEEC_ReleaseSharedMemory(&tee_params_p); return KM_ERROR_UNKNOWN_ERROR; } TEEC_SharedMemory tee_characteristics_p; tee_characteristics_p.size = TEE_KEYMASTER_KEY_INOUT_COMMON_SIZE; tee_characteristics_p.flags = TEEC_MEM_OUTPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &tee_characteristics_p) != TEEC_SUCCESS) { ALOGE("%s: allocate characteristics share memory fail", __func__); TEEC_ReleaseSharedMemory(&tee_params_p); TEEC_ReleaseSharedMemory(&tee_material_p); return KM_ERROR_UNKNOWN_ERROR; } TEEC_Operation operation; memset(&operation, 0, sizeof(TEEC_Operation)); operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_NONE); operation.started = 1; operation.params[0].memref.parent = &tee_params_p; operation.params[0].memref.offset = 0; operation.params[0].memref.size = 0; operation.params[1].memref.parent = &tee_material_p; operation.params[1].memref.offset = 0; operation.params[1].memref.size = 0; operation.params[2].memref.parent = &tee_characteristics_p; operation.params[2].memref.offset = 0; operation.params[2].memref.size = 0; int success = TEEC_InvokeCommand(gKeyMasterV2Session, MSG_KEYMASTER_V2_GENERATE_KEY, &operation, NULL); if (success) { if (success < KM_ERROR_UNKNOWN_ERROR) { err_type = KM_ERROR_UNKNOWN_ERROR; } else { err_type = (keymaster_error_t)success; } }else{ key_blob->key_material_size = operation.params[1].memref.size; uint8_t* tmp = reinterpret_cast(malloc(key_blob->key_material_size)); if (!tmp){ err_type = KM_ERROR_MEMORY_ALLOCATION_FAILED; goto __generate_key_err; } memcpy(tmp, tee_material_p.buffer, key_blob->key_material_size); key_blob->key_material = tmp; //ALOGV("key_blob", 0); //tee_hexdump((uint8_t*)key_blob->key_material, key_blob->key_material_size); if (characteristics) { tee_keymaster_key_characteristics_t *tee_enforced = (tee_keymaster_key_characteristics_t *)tee_characteristics_p.buffer; tee_CopyToParamSet((uint8_t*)&(tee_enforced->hw_enforced), &(characteristics->hw_enforced), (uint8_t*)tee_enforced); tee_CopyToParamSet((uint8_t*)&(tee_enforced->sw_enforced), &(characteristics->sw_enforced), (uint8_t*)tee_enforced); //tee_ParamSet_view(&characteristics->hw_enforced); //tee_ParamSet_view(&characteristics->sw_enforced); err_type = KM_ERROR_OK; } } __generate_key_err: TEEC_ReleaseSharedMemory(&tee_params_p); TEEC_ReleaseSharedMemory(&tee_material_p); TEEC_ReleaseSharedMemory(&tee_characteristics_p); if(err_type != KM_ERROR_OK) ALOGE("%s failed with %d", __func__, err_type); return err_type; } keymaster_error_t KeyMaster_V2_Get_Key_Characteristics(const keymaster_device_t* dev, const keymaster_key_blob_t* key_blob, const keymaster_blob_t* client_id, const keymaster_blob_t* app_data, keymaster_key_characteristics_t* characteristics){ ALOGV("%s %d", __func__, __LINE__); if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!characteristics) return KM_ERROR_OUTPUT_PARAMETER_NULL; if (!keymaster_v2_configured) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; int client_id_flag, app_data_flag; keymaster_error_t err_type = KM_ERROR_OK; TEEC_SharedMemory key_blob_p; key_blob_p.size = key_blob->key_material_size; key_blob_p.flags = TEEC_MEM_INPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &key_blob_p) != TEEC_SUCCESS) { ALOGE("%s: allocate key blob share memory fail", __func__); return KM_ERROR_UNKNOWN_ERROR; } memcpy(key_blob_p.buffer, key_blob->key_material, key_blob->key_material_size); TEEC_SharedMemory client_id_p; if (client_id) { client_id_p.size = client_id->data_length; client_id_p.flags = TEEC_MEM_INPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &client_id_p) != TEEC_SUCCESS) { ALOGE("%s: allocate client id blob share memory fail", __func__); TEEC_ReleaseSharedMemory(&key_blob_p); return KM_ERROR_UNKNOWN_ERROR; } memcpy(client_id_p.buffer, client_id->data, client_id->data_length); client_id_flag = TEEC_MEMREF_WHOLE; } else { client_id_p.buffer = NULL; client_id_flag = TEEC_VALUE_INPUT; } TEEC_SharedMemory app_data_p; if (app_data) { app_data_p.size = app_data->data_length; app_data_p.flags = TEEC_MEM_INPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &app_data_p) != TEEC_SUCCESS) { ALOGE("%s: allocate app data blob share memory fail", __func__); TEEC_ReleaseSharedMemory(&key_blob_p); if (client_id) TEEC_ReleaseSharedMemory(&client_id_p); return KM_ERROR_UNKNOWN_ERROR; } memcpy(app_data_p.buffer, app_data->data, app_data->data_length); app_data_flag = TEEC_MEMREF_WHOLE; } else { app_data_p.buffer = NULL; app_data_flag = TEEC_VALUE_INPUT; } TEEC_SharedMemory tee_characteristics_p; tee_characteristics_p.size = TEE_KEYMASTER_KEY_INOUT_COMMON_SIZE; tee_characteristics_p.flags = TEEC_MEM_OUTPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &tee_characteristics_p) != TEEC_SUCCESS) { ALOGE("%s: allocate characteristics share memory fail", __func__); TEEC_ReleaseSharedMemory(&key_blob_p); if (client_id) TEEC_ReleaseSharedMemory(&client_id_p); if (app_data) TEEC_ReleaseSharedMemory(&app_data_p); return KM_ERROR_UNKNOWN_ERROR; } TEEC_Operation operation; memset(&operation, 0, sizeof(TEEC_Operation)); operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, client_id_flag, app_data_flag, TEEC_MEMREF_WHOLE); operation.started = 1; operation.params[0].memref.parent = &key_blob_p; operation.params[0].memref.offset = 0; operation.params[0].memref.size = 0; if (client_id) { operation.params[1].memref.parent = &client_id_p; operation.params[1].memref.offset = 0; operation.params[1].memref.size = 0; //ALOGV("client_id 1 is full", 0); } else { operation.params[1].value.a = 0; //ALOGV("client_id 1 is data", 0); } if (app_data) { operation.params[2].memref.parent = &app_data_p; operation.params[2].memref.offset = 0; operation.params[2].memref.size = 0; //ALOGV("app_data 2 is full", 0); } else { operation.params[2].value.a = 0; //ALOGV("app_data 2 is data", 0); } operation.params[3].memref.parent = &tee_characteristics_p; operation.params[3].memref.offset = 0; operation.params[3].memref.size = 0; int success = TEEC_InvokeCommand(gKeyMasterV2Session, MSG_KEYMASTER_V2_GET_KEY_CHARAC, &operation, NULL); if (success) { if (success < KM_ERROR_UNKNOWN_ERROR) { err_type = KM_ERROR_UNKNOWN_ERROR; } else { err_type = (keymaster_error_t)success; } } else { //tee_hexdump((uint8_t*)tee_characteristics_p.buffer, 512); tee_keymaster_key_characteristics_t *tee_enforced = (tee_keymaster_key_characteristics_t *)tee_characteristics_p.buffer; tee_CopyToParamSet((uint8_t*)&tee_enforced->hw_enforced, &characteristics->hw_enforced, (uint8_t*)tee_enforced); tee_CopyToParamSet((uint8_t*)&tee_enforced->sw_enforced, &characteristics->sw_enforced, (uint8_t*)tee_enforced); //tee_ParamSet_view(&characteristics->hw_enforced); //tee_ParamSet_view(&characteristics->sw_enforced); } //__get_key_characteristics_err: TEEC_ReleaseSharedMemory(&key_blob_p); if (client_id) TEEC_ReleaseSharedMemory(&client_id_p); if (app_data) TEEC_ReleaseSharedMemory(&app_data_p); TEEC_ReleaseSharedMemory(&tee_characteristics_p); if(err_type != KM_ERROR_OK) ALOGE("%s failed with %d", __func__, err_type); return err_type; } keymaster_error_t KeyMaster_V2_Import_Key(const keymaster_device_t* dev, const keymaster_key_param_set_t* params, keymaster_key_format_t key_format, const keymaster_blob_t* key_data, keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t* characteristics){ ALOGV("%s %d", __func__, __LINE__); if (!dev || !params || !key_data) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!key_blob) return KM_ERROR_OUTPUT_PARAMETER_NULL; if (!keymaster_v2_configured) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; //if (characteristics) // *characteristics = nullptr; keymaster_error_t err_type = KM_ERROR_OK; uint32_t params_size; params_size = compute_param_set_length(params); uint32_t paramsize; paramsize = sizeof(TEE_params_expand) + sizeof(TEE_params_set) +sizeof(TEE_params_set) + sizeof(TEE_params_set) + params_size/*params*/+ sizeof(keymaster_key_format_t)/*key_format*/ + key_data->data_length/*key_data */; TEEC_SharedMemory paramMem; paramMem.size = paramsize; paramMem.flags = TEEC_MEM_INPUT ; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, ¶mMem) != TEEC_SUCCESS) { ALOGE("allocate share memory fail"); return KM_ERROR_UNKNOWN_ERROR; } { /***************copy data*****************/ uint8_t *buf = (uint8_t *)paramMem.buffer; memset(buf, 0, paramsize); TEE_params_expand *param_expand = (TEE_params_expand *)buf; param_expand->buff_count = 3; TEE_params_set *params_set = (TEE_params_set *)(buf + sizeof(TEE_params_expand)); uint32_t offset = param_expand->buff_count * sizeof(TEE_params_set) + \ sizeof(TEE_params_expand); uint8_t *tmp_buf = buf + offset; uint32_t this_len; int i = 0; /*params*/ this_len = params_size; params_set[i].buf = offset; params_set[i].size = this_len; tee_copy_params2_buf(tmp_buf, params); offset += this_len; tmp_buf += this_len; i++; /*key_format*/ this_len = sizeof(keymaster_key_format_t); params_set[i].buf = offset; params_set[i].size = this_len; memcpy(tmp_buf, &key_format, this_len); offset += this_len; tmp_buf += this_len; i++; /*key_data*/ this_len = key_data->data_length; params_set[i].buf = offset; params_set[i].size = this_len; memcpy(tmp_buf, key_data->data, this_len); } TEEC_SharedMemory tee_material_p; tee_material_p.size = TEE_KEYMASTER_KEY_INOUT_COMMON_SIZE; tee_material_p.flags = TEEC_MEM_OUTPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &tee_material_p) != TEEC_SUCCESS) { ALOGE("%s: allocate key blob share memory fail", __func__); return KM_ERROR_UNKNOWN_ERROR; } TEEC_SharedMemory tee_characteristics_p; int tee_chara_flag = TEEC_MEMREF_WHOLE; if (characteristics) { tee_characteristics_p.size = TEE_KEYMASTER_KEY_INOUT_COMMON_SIZE; tee_characteristics_p.flags = TEEC_MEM_OUTPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &tee_characteristics_p) != TEEC_SUCCESS) { ALOGE("%s: allocate characteristics share memory fail", __func__); TEEC_ReleaseSharedMemory(&tee_material_p); return KM_ERROR_UNKNOWN_ERROR; } } else { tee_chara_flag = TEEC_VALUE_INPUT; } TEEC_Operation operation; memset(&operation, 0, sizeof(TEEC_Operation)); operation.started = 1; operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, tee_chara_flag, TEEC_NONE); operation.params[0].memref.parent = ¶mMem; operation.params[0].memref.offset = 0; operation.params[0].memref.size = 0; operation.params[1].memref.parent = &tee_material_p; operation.params[1].memref.offset = 0; operation.params[1].memref.size = 0; if (characteristics) { operation.params[2].memref.parent = &tee_characteristics_p; operation.params[2].memref.offset = 0; operation.params[2].memref.size = 0; } else { operation.params[2].value.a = 0; } int success = TEEC_InvokeCommand(gKeyMasterV2Session, MSG_KEYMASTER_V2_IMPORT_KEY, &operation, NULL); if (success) { if (success < KM_ERROR_UNKNOWN_ERROR) { err_type = KM_ERROR_UNKNOWN_ERROR; } else { err_type = (keymaster_error_t)success; } } else { key_blob->key_material_size = operation.params[1].memref.size; key_blob->key_material = reinterpret_cast(malloc(key_blob->key_material_size)); if (!key_blob->key_material) { err_type = KM_ERROR_MEMORY_ALLOCATION_FAILED; goto __import_key_err; } memcpy(const_cast(key_blob->key_material), tee_material_p.buffer, key_blob->key_material_size); //tee_hexdump((uint8_t*)tee_characteristics_p.buffer, 512); if (characteristics) { keymaster_key_characteristics_t *tee_enforced = (keymaster_key_characteristics_t *)tee_characteristics_p.buffer; tee_CopyToParamSet((uint8_t*)&tee_enforced->hw_enforced, &characteristics->hw_enforced, (uint8_t*)tee_enforced); tee_CopyToParamSet((uint8_t*)&tee_enforced->sw_enforced, &characteristics->sw_enforced, (uint8_t*)tee_enforced); //tee_ParamSet_view(&characteristics->hw_enforced); //tee_ParamSet_view(&characteristics->sw_enforced); err_type = KM_ERROR_OK; } } __import_key_err: TEEC_ReleaseSharedMemory(¶mMem); TEEC_ReleaseSharedMemory(&tee_material_p); if (characteristics) TEEC_ReleaseSharedMemory(&tee_characteristics_p); if(err_type != KM_ERROR_OK) ALOGE("%s failed with %d", __func__, err_type); return err_type; } keymaster_error_t KeyMaster_V2_Export_Key(const keymaster_device_t* dev, keymaster_key_format_t export_format, const keymaster_key_blob_t* key_to_export, const keymaster_blob_t* client_id, const keymaster_blob_t* app_data, keymaster_blob_t* export_data){ ALOGV("%s %d", __func__, __LINE__); if (!dev || !key_to_export || !key_to_export->key_material) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!export_data) return KM_ERROR_OUTPUT_PARAMETER_NULL; if (!keymaster_v2_configured) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; export_data->data = nullptr; export_data->data_length = 0; keymaster_error_t err_type = KM_ERROR_OK; uint32_t paramsize; paramsize = sizeof(TEE_params_set) + sizeof(keymaster_key_format_t) /*export_format*/+ sizeof(TEE_params_set) + key_to_export->key_material_size /*key_to_export*/+ sizeof(TEE_params_set) + /*client_id */ sizeof(TEE_params_set) + /*app_data */ sizeof(TEE_params_expand); if (client_id) paramsize += client_id->data_length; if (app_data) paramsize += app_data->data_length; TEEC_SharedMemory paramMem; paramMem.size = paramsize; paramMem.flags = TEEC_MEM_INPUT ; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, ¶mMem) != TEEC_SUCCESS) { ALOGE("allocate share memory fail"); return KM_ERROR_UNKNOWN_ERROR; } uint8_t *buf = (uint8_t *)paramMem.buffer; memset(buf, 0, paramsize); TEE_params_expand *param_expand = (TEE_params_expand *)buf; param_expand->buff_count = 4; TEE_params_set *params_set = (TEE_params_set *)(buf + sizeof(TEE_params_expand)); size_t offset = param_expand->buff_count * sizeof(TEE_params_set) + \ sizeof(TEE_params_expand); uint8_t *tmp_buf = buf + offset; int i = 0; uint32_t this_len; /*export_format*/ this_len = sizeof(keymaster_key_format_t); params_set[i].buf = offset; params_set[i++].size = this_len; memcpy(tmp_buf, &export_format, this_len); offset += this_len; tmp_buf += this_len; //ALOGV("params_set[0].buf=%p", params_set[0].buf); //ALOGV("params_set[0].size=0x%x", params_set[0].size); //tee_hexdump(params_set[0].buf + (uint32_t)buf, params_set[0].size); /*key_to_export*/ this_len = key_to_export->key_material_size; params_set[i].buf = offset; params_set[i++].size = this_len; memcpy(tmp_buf, key_to_export->key_material, this_len); this_len = (this_len + 3) & (~3); offset += this_len; tmp_buf += this_len; //ALOGV("params_set[1].buf=%p", params_set[1].buf); //ALOGV("params_set[1].size=0x%x", params_set[1].size); //tee_hexdump(params_set[1].buf + (uint32_t)buf, params_set[1].size); /*client_id*/ if (client_id) { this_len = client_id->data_length; params_set[i].buf = offset; params_set[i].size = this_len; memcpy(tmp_buf, client_id->data, this_len); this_len = (this_len + 3) & (~3); offset += this_len; tmp_buf += this_len; } else { params_set[i].buf = 0; params_set[i].size = 0; } i++; /*app_data*/ if (app_data) { this_len = app_data->data_length; params_set[i].buf = offset; params_set[i].size = this_len; memcpy(tmp_buf, app_data->data, this_len); this_len = (this_len + 3) & (~3); offset += this_len; tmp_buf += this_len; } else { params_set[i].buf = 0; params_set[i].size = 0; } TEEC_SharedMemory export_data_p; export_data_p.size = TEE_KEYMASTER_KEY_INOUT_COMMON_SIZE; export_data_p.flags = TEEC_MEM_OUTPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &export_data_p) != TEEC_SUCCESS) { ALOGE("%s: allocate export_data params share memory fail", __func__); TEEC_ReleaseSharedMemory(¶mMem); return KM_ERROR_UNKNOWN_ERROR; } TEEC_Operation operation; memset(&operation, 0, sizeof(TEEC_Operation)); operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_NONE, TEEC_NONE); operation.started = 1; operation.params[0].memref.parent = ¶mMem; operation.params[0].memref.offset = 0; operation.params[0].memref.size = 0; operation.params[1].memref.parent = &export_data_p; operation.params[1].memref.offset = 0; operation.params[1].memref.size = 0; int success = TEEC_InvokeCommand(gKeyMasterV2Session, MSG_KEYMASTER_V2_EXPORT_KEY, &operation, NULL); if (success) { if (success < KM_ERROR_UNKNOWN_ERROR) { err_type = KM_ERROR_UNKNOWN_ERROR; } else { err_type = (keymaster_error_t)success; } } else { export_data->data_length = operation.params[1].memref.size; uint8_t* tmp = reinterpret_cast(malloc(export_data->data_length)); if (!tmp) { err_type = KM_ERROR_MEMORY_ALLOCATION_FAILED; } else { memcpy(tmp, export_data_p.buffer, export_data->data_length); export_data->data = tmp; } } //__export_key_err: TEEC_ReleaseSharedMemory(¶mMem); TEEC_ReleaseSharedMemory(&export_data_p); if(err_type != KM_ERROR_OK) ALOGE("%s failed with %d", __func__, err_type); return err_type; } keymaster_error_t KeyMaster_V2_Attest_Key(const keymaster_device_t* dev, const keymaster_key_blob_t* key_to_attest, const keymaster_key_param_set_t* attest_params, keymaster_cert_chain_t* cert_chain){ ALOGV("%s %d", __func__, __LINE__); if (!dev || !key_to_attest || !attest_params || !cert_chain) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!keymaster_v2_configured) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; keymaster_error_t err_type = KM_ERROR_OK; TEEC_SharedMemory key_to_attest_p; key_to_attest_p.size = key_to_attest->key_material_size; key_to_attest_p.flags = TEEC_MEM_INPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &key_to_attest_p) != TEEC_SUCCESS) { ALOGE("%s: allocate key to attest blob share memory fail", __func__); return KM_ERROR_UNKNOWN_ERROR; } memcpy(key_to_attest_p.buffer, key_to_attest->key_material, key_to_attest->key_material_size); //ALOGV("key_to_attest: %d", key_to_attest->key_material_size); //tee_hexdump((uint8_t*)key_to_attest_p.buffer, key_to_attest->key_material_size); //tee_ParamSet_view(attest_params); uint32_t attest_params_size; attest_params_size = compute_param_set_length(attest_params); TEEC_SharedMemory tee_key_params_p; tee_key_params_p.size = attest_params_size; tee_key_params_p.flags = TEEC_MEM_INPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &tee_key_params_p) != TEEC_SUCCESS) { ALOGE("%s: allocate key params share memory fail", __func__); TEEC_ReleaseSharedMemory(&key_to_attest_p); return KM_ERROR_UNKNOWN_ERROR; } tee_copy_params2_buf((uint8_t*)tee_key_params_p.buffer, attest_params); TEEC_SharedMemory tee_cert_chain_p; tee_cert_chain_p.size = TEE_KEYMASTER_KEY_INOUT_COMMON_SIZE; tee_cert_chain_p.flags = TEEC_MEM_OUTPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &tee_cert_chain_p) != TEEC_SUCCESS) { ALOGE("%s: allocate cert chain share memory fail", __func__); TEEC_ReleaseSharedMemory(&key_to_attest_p); TEEC_ReleaseSharedMemory(&tee_key_params_p); return KM_ERROR_UNKNOWN_ERROR; } TEEC_Operation operation; memset(&operation, 0, sizeof(TEEC_Operation)); operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_NONE); operation.started = 1; operation.params[0].memref.parent = &key_to_attest_p; operation.params[0].memref.offset = 0; operation.params[0].memref.size = 0; operation.params[1].memref.parent = &tee_key_params_p; operation.params[1].memref.offset = 0; operation.params[1].memref.size = 0; operation.params[2].memref.parent = &tee_cert_chain_p; operation.params[2].memref.offset = 0; operation.params[2].memref.size = 0; int success = TEEC_InvokeCommand(gKeyMasterV2Session, MSG_KEYMASTER_V2_ATTEST_KEY, &operation, NULL); if (success) { if (success < KM_ERROR_UNKNOWN_ERROR) { err_type = KM_ERROR_UNKNOWN_ERROR; } else { err_type = (keymaster_error_t)success; } } else { // Allocate and clear storage for cert_chain. tee_keymaster_cert_chain_t *rsp_chain = (tee_keymaster_cert_chain_t *)tee_cert_chain_p.buffer; //tee_hexdump((uint8_t*)tee_cert_chain_p.buffer, 64); cert_chain->entries = reinterpret_cast( malloc(rsp_chain->entry_count * sizeof(*cert_chain->entries))); if (!cert_chain->entries) { err_type = KM_ERROR_MEMORY_ALLOCATION_FAILED; } else { cert_chain->entry_count = rsp_chain->entry_count; for (keymaster_blob_t& entry : keymaster::array_range(cert_chain->entries, cert_chain->entry_count)) entry = {}; // Copy cert_chain contents size_t i = 0; uint8_t* buffer = (uint8_t*)tee_cert_chain_p.buffer; tee_keymaster_blob_t *entry = (tee_keymaster_blob_t *)(buffer + sizeof(tee_keymaster_cert_chain_t)); for (i=0;ientry_count;i++) { cert_chain->entries[i].data = reinterpret_cast(malloc(entry[i].data_length)); if (!cert_chain->entries[i].data) { keymaster_free_cert_chain(cert_chain); err_type = KM_ERROR_MEMORY_ALLOCATION_FAILED; goto __attest_key_err; } cert_chain->entries[i].data_length = entry[i].data_length; memcpy(const_cast(cert_chain->entries[i].data), entry[i].data_offset + buffer, entry[i].data_length); //tee_hexdump((uint8_t *)(entry[i].data_offset + buffer), entry[i].data_length); } } } __attest_key_err: TEEC_ReleaseSharedMemory(&key_to_attest_p); TEEC_ReleaseSharedMemory(&tee_key_params_p); TEEC_ReleaseSharedMemory(&tee_cert_chain_p); if(err_type != KM_ERROR_OK) ALOGE("%s failed with %d", __func__, err_type); return err_type; } keymaster_error_t KeyMaster_V2_Upgrade_Key(const keymaster_device_t* dev, const keymaster_key_blob_t* key_to_upgrade, const keymaster_key_param_set_t* upgrade_params, keymaster_key_blob_t* upgraded_key){ ALOGV("%s %d", __func__, __LINE__); if (!dev || !key_to_upgrade || !upgrade_params) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!upgraded_key) return KM_ERROR_OUTPUT_PARAMETER_NULL; if (!keymaster_v2_configured) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; keymaster_error_t err_type = KM_ERROR_OK; TEEC_SharedMemory key_to_upgrade_p; key_to_upgrade_p.size = key_to_upgrade->key_material_size; key_to_upgrade_p.flags = TEEC_MEM_INPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &key_to_upgrade_p) != TEEC_SUCCESS) { ALOGE("%s: allocate key to upgrade key share memory fail", __func__); return KM_ERROR_UNKNOWN_ERROR; } memcpy(key_to_upgrade_p.buffer, key_to_upgrade->key_material,key_to_upgrade->key_material_size); //tee_hexdump((uint8_t*)key_to_upgrade_p.buffer, key_to_upgrade->key_material_size); uint32_t upgrade_params_size; upgrade_params_size = compute_param_set_length(upgrade_params); TEEC_SharedMemory tee_key_params_p; tee_key_params_p.size = upgrade_params_size; tee_key_params_p.flags = TEEC_MEM_INPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &tee_key_params_p) != TEEC_SUCCESS) { ALOGE("%s: allocate key params share memory fail", __func__); TEEC_ReleaseSharedMemory(&key_to_upgrade_p); return KM_ERROR_UNKNOWN_ERROR; } tee_copy_params2_buf((uint8_t*)tee_key_params_p.buffer, upgrade_params); TEEC_SharedMemory upgraded_key_p; upgraded_key_p.size = TEE_KEYMASTER_KEY_INOUT_COMMON_SIZE; upgraded_key_p.flags = TEEC_MEM_OUTPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &upgraded_key_p) != TEEC_SUCCESS) { ALOGE("%s: allocate cert chain share memory fail", __func__); TEEC_ReleaseSharedMemory(&key_to_upgrade_p); TEEC_ReleaseSharedMemory(&tee_key_params_p); return KM_ERROR_UNKNOWN_ERROR; } TEEC_Operation operation; memset(&operation, 0, sizeof(TEEC_Operation)); operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_NONE); operation.started = 1; operation.params[0].memref.parent = &key_to_upgrade_p; operation.params[0].memref.offset = 0; operation.params[0].memref.size = 0; operation.params[1].memref.parent = &tee_key_params_p; operation.params[1].memref.offset = 0; operation.params[1].memref.size = 0; operation.params[2].memref.parent = &upgraded_key_p; operation.params[2].memref.offset = 0; operation.params[2].memref.size = 0; int success = TEEC_InvokeCommand(gKeyMasterV2Session, MSG_KEYMASTER_V2_UPGRAGE_KEY, &operation, NULL); if (success) { if (success < KM_ERROR_UNKNOWN_ERROR) { err_type = KM_ERROR_UNKNOWN_ERROR; } else { err_type = (keymaster_error_t)success; } } else { upgraded_key->key_material_size = operation.params[2].memref.size; uint8_t* tmp = reinterpret_cast(malloc(upgraded_key->key_material_size)); if (!tmp) { err_type = KM_ERROR_MEMORY_ALLOCATION_FAILED; goto __upgrade_key_err; } memcpy(tmp, upgraded_key_p.buffer, upgraded_key->key_material_size); upgraded_key->key_material = tmp; //tee_hexdump(tmp, upgraded_key->key_material_size); } __upgrade_key_err: TEEC_ReleaseSharedMemory(&key_to_upgrade_p); TEEC_ReleaseSharedMemory(&tee_key_params_p); TEEC_ReleaseSharedMemory(&upgraded_key_p); if(err_type != KM_ERROR_OK) ALOGE("%s failed with %d", __func__, err_type); return err_type; } keymaster_error_t KeyMaster_V2_Delete_Key(const keymaster_device_t* dev, const keymaster_key_blob_t* key){ ALOGV("%s %d", __func__, __LINE__); if (!dev || !key || !key->key_material) return KM_ERROR_UNEXPECTED_NULL_POINTER; keymaster_error_t err_type = KM_ERROR_OK; TEEC_SharedMemory key_p; key_p.size = key->key_material_size; key_p.flags = TEEC_MEM_INPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &key_p) != TEEC_SUCCESS) { ALOGE("%s: allocate delete key share memory fail", __func__); return KM_ERROR_UNKNOWN_ERROR; } memcpy(key_p.buffer, key->key_material, key->key_material_size); TEEC_Operation operation; memset(&operation, 0, sizeof(TEEC_Operation)); operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, TEEC_NONE, TEEC_NONE, TEEC_NONE); operation.started = 1; operation.params[0].memref.parent = &key_p; operation.params[0].memref.offset = 0; operation.params[0].memref.size = 0; int success = TEEC_InvokeCommand(gKeyMasterV2Session, MSG_KEYMASTER_V2_DELETE_KEY, &operation, NULL); if (success < KM_ERROR_UNKNOWN_ERROR) { err_type = KM_ERROR_UNKNOWN_ERROR; } else { err_type = (keymaster_error_t)success; } //__delete_Key_err: TEEC_ReleaseSharedMemory(&key_p); if(err_type != KM_ERROR_OK) ALOGE("%s failed with %d", __func__, err_type); return err_type; } keymaster_error_t KeyMaster_V2_Delete_All_Keys(const keymaster_device_t* dev){ ALOGV("%s %d", __func__, __LINE__); if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!keymaster_v2_configured) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; keymaster_error_t err_type = KM_ERROR_OK; TEEC_Operation operation; memset(&operation, 0, sizeof(TEEC_Operation)); operation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE); operation.started = 1; int success = TEEC_InvokeCommand(gKeyMasterV2Session, MSG_KEYMASTER_V2_DELETE_ALL_KEYS, &operation, NULL); if (success < KM_ERROR_UNKNOWN_ERROR) { err_type = KM_ERROR_UNKNOWN_ERROR; } else { err_type = (keymaster_error_t)success; } //__delete_all_keys_err: if(err_type != KM_ERROR_OK) ALOGE("%s failed with %d", __func__, err_type); return err_type; } keymaster_error_t KeyMaster_V2_Begin(const keymaster_device_t* dev, keymaster_purpose_t purpose, const keymaster_key_blob_t* key, const keymaster_key_param_set_t* in_params, keymaster_key_param_set_t* out_params, keymaster_operation_handle_t* operation_handle){ ALOGV("%s %d", __func__, __LINE__); if (!dev || !key || !key->key_material) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!operation_handle) return KM_ERROR_OUTPUT_PARAMETER_NULL; if (!keymaster_v2_configured) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; if (out_params) { out_params->params = nullptr; out_params->length = 0; } //ALOGV("key length=%d\n", key->key_material_size); keymaster_error_t err_type = KM_ERROR_OK; uint32_t in_params_size; in_params_size = compute_param_set_length(in_params); uint32_t paramsize; paramsize = sizeof(TEE_params_expand) + sizeof(TEE_params_set) + sizeof(keymaster_purpose_t) /*purpose*/+ sizeof(TEE_params_set) + key->key_material_size /*key*/+ sizeof(TEE_params_set) + in_params_size;/*in_params */ TEEC_SharedMemory paramMem; paramMem.size = paramsize; paramMem.flags = TEEC_MEM_INPUT ; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, ¶mMem) != TEEC_SUCCESS) { ALOGE("allocate share memory fail"); return KM_ERROR_UNKNOWN_ERROR; } uint8_t *buf = (uint8_t *)paramMem.buffer; memset(buf, 0, paramsize); //ALOGV("buf=%p", buf); TEE_params_expand *param_expand = (TEE_params_expand *)buf; param_expand->buff_count = 3; TEE_params_set *params_set = (TEE_params_set *)(buf + sizeof(TEE_params_expand)); size_t offset = param_expand->buff_count * sizeof(TEE_params_set) + \ sizeof(TEE_params_expand); uint8_t *tmp_buf = buf + offset; uint32_t this_len; int i = 0; /*purpose*/ this_len = sizeof(keymaster_purpose_t); params_set[i].buf = offset; params_set[i++].size = this_len; memcpy(tmp_buf, &purpose, this_len); offset += this_len; tmp_buf += this_len; //ALOGV("params_set[0].buf=%x", params_set[0].buf); //ALOGV("params_set[0].size=0x%x", params_set[0].size); //tee_hexdump(buf + params_set[0].buf, params_set[0].size); /*key*/ this_len = key->key_material_size; params_set[i].buf = offset; params_set[i++].size = this_len; memcpy(tmp_buf, key->key_material, this_len); this_len = (this_len + 3) & (~3); offset += this_len; tmp_buf += this_len; //ALOGV("params_set[1].buf=%x", params_set[1].buf); //ALOGV("params_set[1].size=0x%x", params_set[1].size); //tee_hexdump(buf + params_set[1].buf, params_set[1].size); /*params*/ params_set[i].buf = offset; params_set[i].size = in_params_size; //tee_ParamSet_view(in_params); //ALOGV("params buf=%p\n", buf + params_set[2].buf); //ALOGV("params_set[2].buf=0x%x", params_set[2].buf); tee_copy_params2_buf(buf + params_set[i].buf, in_params); TEEC_SharedMemory out_params_p; out_params_p.size = TEE_KEYMASTER_KEY_INOUT_COMMON_SIZE; out_params_p.flags = TEEC_MEM_OUTPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &out_params_p) != TEEC_SUCCESS) { ALOGE("%s: allocate output params share memory fail", __func__); TEEC_ReleaseSharedMemory(¶mMem); return KM_ERROR_UNKNOWN_ERROR; } TEEC_Operation operation; memset(&operation, 0, sizeof(TEEC_Operation)); operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_VALUE_OUTPUT, TEEC_NONE); operation.started = 1; operation.params[0].memref.parent = ¶mMem; operation.params[0].memref.offset = 0; operation.params[0].memref.size = 0; operation.params[1].memref.parent = &out_params_p; operation.params[1].memref.offset = 0; operation.params[1].memref.size = 0; int success = TEEC_InvokeCommand(gKeyMasterV2Session, MSG_KEYMASTER_V2_BEGIN, &operation, NULL); if (success) { if (success < KM_ERROR_UNKNOWN_ERROR) { err_type = KM_ERROR_UNKNOWN_ERROR; } else { err_type = (keymaster_error_t)success; } } else { tee_keymaster_key_param_set_t *set = (tee_keymaster_key_param_set_t *)out_params_p.buffer; //fix tee_output_params if (set->length) { if (out_params) { tee_CopyToParamSet((uint8_t*)out_params_p.buffer, out_params, (uint8_t*)out_params_p.buffer); } else { err_type = KM_ERROR_OUTPUT_PARAMETER_NULL; goto __begin_err; } } *operation_handle = operation.params[2].value.b; *operation_handle <<= 32; *operation_handle |= operation.params[2].value.a; } __begin_err: TEEC_ReleaseSharedMemory(¶mMem); TEEC_ReleaseSharedMemory(&out_params_p); if(err_type != KM_ERROR_OK) ALOGE("%s failed with %d", __func__, err_type); return err_type; } keymaster_error_t KeyMaster_V2_Update(const keymaster_device_t* dev, keymaster_operation_handle_t operation_handle, const keymaster_key_param_set_t* in_params, const keymaster_blob_t* input, size_t* input_consumed, keymaster_key_param_set_t* out_params, keymaster_blob_t* output){ ALOGV("%s %d", __func__, __LINE__); if (!dev || !input) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!input_consumed) return KM_ERROR_OUTPUT_PARAMETER_NULL; if (!keymaster_v2_configured) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; if (out_params) { out_params->params = nullptr; out_params->length = 0; } if (output) { output->data = nullptr; output->data_length = 0; } keymaster_error_t err_type = KM_ERROR_OK; uint32_t in_params_size; if(in_params) { in_params_size = compute_param_set_length(in_params); } else { in_params_size = 0; } uint32_t paramsize; paramsize = sizeof(TEE_params_expand) + sizeof(TEE_params_set) + sizeof(keymaster_operation_handle_t) /*operation_handle*/+ sizeof(TEE_params_set) + in_params_size /*in_params */+ sizeof(TEE_params_set) + input->data_length; /*input*/ TEEC_SharedMemory paramMem; paramMem.size = paramsize; paramMem.flags = TEEC_MEM_INPUT ; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, ¶mMem) != TEEC_SUCCESS) { ALOGE("allocate share memory fail"); return KM_ERROR_UNKNOWN_ERROR; } uint8_t *buf = (uint8_t *)paramMem.buffer; memset(buf, 0, paramsize); //ALOGV("buf=%p", buf); TEE_params_expand *param_expand = (TEE_params_expand *)buf; param_expand->buff_count = 3; TEE_params_set *params_set = (TEE_params_set *)(buf + sizeof(TEE_params_expand)); size_t offset = param_expand->buff_count * sizeof(TEE_params_set) + \ sizeof(TEE_params_expand); uint8_t *tmp_buf = buf + offset; int i = 0; uint32_t this_len; /*operation_handle*/ this_len = sizeof(keymaster_operation_handle_t); params_set[i].buf = offset; params_set[i++].size = this_len; memcpy(tmp_buf, &operation_handle, this_len); offset += this_len; tmp_buf += this_len; /*in_params*/ if (in_params) { this_len = in_params_size; params_set[i].buf = offset; params_set[i].size = this_len; tee_copy_params2_buf(buf + params_set[i].buf, in_params); //tee_ParamSet_view(in_params); //ALOGV("params buf=%p\n", buf + params_set[i].buf); //ALOGV("params_set[1].buf=%x", params_set[i].buf); } else { this_len = 0; params_set[i].buf = 0; params_set[i].size = 0; } offset += this_len; tmp_buf += this_len; i++; /*input*/ this_len = input->data_length; params_set[i].buf = offset; params_set[i].size = this_len; memcpy(tmp_buf, input->data, this_len); //tee_hexdump((uint8_t *)input->data, input->data_length); //ALOGV("params_set[2].buf=%p", params_set[2].buf); //ALOGV("params_set[2].size=0x%x", params_set[2].size); //tee_hexdump(params_set[2].buf + (uint32_t)buf, params_set[2].size); TEEC_SharedMemory out_params_p; out_params_p.size = TEE_KEYMASTER_KEY_INOUT_COMMON_SIZE; out_params_p.flags = TEEC_MEM_OUTPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &out_params_p) != TEEC_SUCCESS) { ALOGE("%s: allocate output params share memory fail", __func__); TEEC_ReleaseSharedMemory(¶mMem); return KM_ERROR_UNKNOWN_ERROR; } TEEC_SharedMemory tee_output_p; tee_output_p.size = TEE_KEYMASTER_KEY_INOUT_COMMON_SIZE; tee_output_p.flags = TEEC_MEM_OUTPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &tee_output_p) != TEEC_SUCCESS) { ALOGE("%s: allocate output share memory fail", __func__); TEEC_ReleaseSharedMemory(¶mMem); TEEC_ReleaseSharedMemory(&out_params_p); return KM_ERROR_UNKNOWN_ERROR; } TEEC_Operation operation; memset(&operation, 0, sizeof(TEEC_Operation)); operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_VALUE_OUTPUT); operation.started = 1; operation.params[0].memref.parent = ¶mMem; operation.params[0].memref.offset = 0; operation.params[0].memref.size = 0; operation.params[1].memref.parent = &out_params_p; operation.params[1].memref.offset = 0; operation.params[1].memref.size = 0; operation.params[2].memref.parent = &tee_output_p; operation.params[2].memref.offset = 0; operation.params[2].memref.size = 0; int success = TEEC_InvokeCommand(gKeyMasterV2Session, MSG_KEYMASTER_V2_UPDATE, &operation, NULL); if (success) { if (success < KM_ERROR_UNKNOWN_ERROR) { err_type = KM_ERROR_UNKNOWN_ERROR; } else { err_type = (keymaster_error_t)success; } } else { //fix tee_output_params tee_CopyToParamSet((uint8_t*)out_params_p.buffer, out_params, (uint8_t*)out_params_p.buffer); *input_consumed = operation.params[3].value.a; if (output) { output->data_length = operation.params[2].memref.size; uint8_t* tmp = reinterpret_cast(malloc(output->data_length)); if (!tmp) err_type = KM_ERROR_MEMORY_ALLOCATION_FAILED; else { memcpy(tmp, tee_output_p.buffer, output->data_length); output->data = tmp; } } else if (operation.params[2].memref.size > 0) err_type = KM_ERROR_OUTPUT_PARAMETER_NULL; } //__update_err: TEEC_ReleaseSharedMemory(¶mMem); TEEC_ReleaseSharedMemory(&out_params_p); TEEC_ReleaseSharedMemory(&tee_output_p); if(err_type != KM_ERROR_OK) ALOGE("%s failed with %d", __func__, err_type); return err_type; } keymaster_error_t KeyMaster_V2_Finish(const keymaster_device_t* dev, keymaster_operation_handle_t operation_handle, const keymaster_key_param_set_t* in_params, const keymaster_blob_t* input, const keymaster_blob_t* signature, keymaster_key_param_set_t* out_params, keymaster_blob_t* output){ ALOGV("%s %d", __func__, __LINE__); if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!keymaster_v2_configured) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; if (out_params) { out_params->params = nullptr; out_params->length = 0; } if (output) { output->data = nullptr; output->data_length = 0; } uint32_t in_params_size; in_params_size = compute_param_set_length(in_params); uint32_t paramsize; paramsize = sizeof(TEE_params_set) + sizeof(keymaster_operation_handle_t)/*operation_handle*/+ sizeof(TEE_params_set) + in_params_size /*in_params*/+ sizeof(TEE_params_set) +/*rest for input*/ sizeof(TEE_params_set) /*rest for signature*/; if (input) paramsize += input->data_length; /*input*/ if (signature) paramsize += signature->data_length; /*signature*/ TEEC_SharedMemory paramMem; paramMem.size = paramsize; paramMem.flags = TEEC_MEM_INPUT ; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, ¶mMem) != TEEC_SUCCESS) { ALOGE("allocate share memory fail"); return KM_ERROR_UNKNOWN_ERROR; } uint8_t *buf = (uint8_t *)paramMem.buffer; memset(buf, 0, paramsize); TEE_params_expand *param_expand = (TEE_params_expand *)buf; param_expand->buff_count = 4; TEE_params_set *params_set = (TEE_params_set *)(buf + sizeof(TEE_params_expand)); size_t offset = param_expand->buff_count * sizeof(TEE_params_set) + \ sizeof(TEE_params_expand); uint8_t *tmp_buf = buf + offset; int i = 0; /*operation_handle*/ params_set[i].buf = offset; params_set[i++].size = sizeof(keymaster_operation_handle_t); memcpy(tmp_buf, &operation_handle, sizeof(keymaster_operation_handle_t)); offset += sizeof(keymaster_operation_handle_t); tmp_buf += sizeof(keymaster_operation_handle_t); /*in_params*/ params_set[i].buf = offset; params_set[i].size = in_params_size; tee_copy_params2_buf(buf + params_set[i].buf, in_params); offset += in_params_size; tmp_buf += in_params_size; /*input*/ if (input) { params_set[++i].buf = offset; params_set[i].size = input->data_length; memcpy(tmp_buf, input->data, input->data_length); offset += input->data_length; tmp_buf += input->data_length; } else { params_set[++i].buf = 0; params_set[i].size = 0; } /*signature*/ if (signature) { params_set[++i].buf = offset; params_set[i].size = signature->data_length; memcpy(tmp_buf, signature->data, signature->data_length); } else { params_set[++i].buf = 0; params_set[i].size = 0; } TEEC_SharedMemory out_params_p; out_params_p.size = TEE_KEYMASTER_KEY_INOUT_COMMON_SIZE; out_params_p.flags = TEEC_MEM_OUTPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &out_params_p) != TEEC_SUCCESS) { ALOGE("%s: allocate output params share memory fail", __func__); TEEC_ReleaseSharedMemory(¶mMem); return KM_ERROR_UNKNOWN_ERROR; } TEEC_SharedMemory tee_output_p; tee_output_p.size = TEE_KEYMASTER_KEY_INOUT_COMMON_SIZE; tee_output_p.flags = TEEC_MEM_OUTPUT; if(TEEC_AllocateSharedMemory(gKeyMasterV2Context, &tee_output_p) != TEEC_SUCCESS) { ALOGE("%s: allocate output share memory fail", __func__); TEEC_ReleaseSharedMemory(¶mMem); TEEC_ReleaseSharedMemory(&out_params_p); return KM_ERROR_UNKNOWN_ERROR; } TEEC_Operation operation; memset(&operation, 0, sizeof(TEEC_Operation)); operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_NONE); operation.started = 1; operation.params[0].memref.parent = ¶mMem; operation.params[0].memref.offset = 0; operation.params[0].memref.size = 0; operation.params[1].memref.parent = &out_params_p; operation.params[1].memref.offset = 0; operation.params[1].memref.size = 0; operation.params[2].memref.parent = &tee_output_p; operation.params[2].memref.offset = 0; operation.params[2].memref.size = 0; int success = TEEC_InvokeCommand(gKeyMasterV2Session, MSG_KEYMASTER_V2_FINISH, &operation, NULL); keymaster_error_t err_type = KM_ERROR_OK; if (success) { if (success < KM_ERROR_UNKNOWN_ERROR) { err_type = KM_ERROR_UNKNOWN_ERROR; } else { err_type = (keymaster_error_t)success; } } else { //fix tee_output_params //tee_hexdump((uint8_t*)out_params_p.buffer, 16); tee_keymaster_key_param_set_t *set = (tee_keymaster_key_param_set_t *)out_params_p.buffer; if (set->length) { if (out_params) { tee_CopyToParamSet((uint8_t*)out_params_p.buffer, out_params, (uint8_t*)out_params_p.buffer); } else { err_type = KM_ERROR_OUTPUT_PARAMETER_NULL; goto __finish_err; } } if (output) { output->data_length = operation.params[2].memref.size; uint8_t* tmp = reinterpret_cast(malloc(output->data_length)); if (!tmp) err_type = KM_ERROR_MEMORY_ALLOCATION_FAILED; else { memcpy(tmp, tee_output_p.buffer, output->data_length); output->data = tmp; } } else if (operation.params[2].memref.size > 0) err_type = KM_ERROR_OUTPUT_PARAMETER_NULL; } __finish_err: TEEC_ReleaseSharedMemory(¶mMem); TEEC_ReleaseSharedMemory(&out_params_p); TEEC_ReleaseSharedMemory(&tee_output_p); if(err_type != KM_ERROR_OK) ALOGE("%s failed with %d", __func__, err_type); return err_type; } keymaster_error_t KeyMaster_V2_Abort(const keymaster_device_t* dev, keymaster_operation_handle_t operation_handle){ ALOGV("%s %d", __func__, __LINE__); if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!keymaster_v2_configured) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; keymaster_error_t err_type = KM_ERROR_OK; TEEC_Operation operation; memset(&operation, 0, sizeof(TEEC_Operation)); operation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); operation.started = 1; operation.params[0].value.a = (operation_handle >> 0 ) & 0xffffffff; operation.params[0].value.b = (operation_handle >> 32 ) & 0xffffffff; int success = TEEC_InvokeCommand(gKeyMasterV2Session, MSG_KEYMASTER_V2_ABORT,&operation, NULL); if (success < KM_ERROR_UNKNOWN_ERROR) { err_type = KM_ERROR_UNKNOWN_ERROR; } else { err_type = (keymaster_error_t)success; } //__abort_err: if(err_type != KM_ERROR_OK) ALOGE("%s failed with %d", __func__, err_type); return err_type; } static int sunxi_tee_keymaster_v2_device_close(hw_device_t *dev) { KeyMaster_V2_Terminate(); delete dev; return 0; } static int sunxi_tee_keymaster_v2_device_open(const hw_module_t* module, const char* name, hw_device_t** device) { if (strcmp(name, KEYSTORE_KEYMASTER) != 0) return -EINVAL; ALOGD("%s:: Enter AW tee keymaster v2\n",__func__); Unique_keymaster_device_t dev(new keymaster_device_t); if (dev.get() == NULL) return -ENOMEM; dev->context = (void *)AW_KEYMASTER_V2_TEE_HAL; dev->common.tag = HARDWARE_DEVICE_TAG; dev->common.version = 1; dev->common.module = const_cast(module); dev->common.close = sunxi_tee_keymaster_v2_device_close; dev->flags = KEYMASTER_BLOBS_ARE_STANDALONE | KEYMASTER_SUPPORTS_EC; dev->configure = KeyMaster_V2_Configure; dev->add_rng_entropy = KeyMaster_V2_Add_Rng_Entropy; dev->generate_key = KeyMaster_V2_Generate_Key; dev->get_key_characteristics = KeyMaster_V2_Get_Key_Characteristics; dev->import_key = KeyMaster_V2_Import_Key; dev->export_key = KeyMaster_V2_Export_Key; dev->attest_key = KeyMaster_V2_Attest_Key; dev->upgrade_key = KeyMaster_V2_Upgrade_Key; dev->delete_key = KeyMaster_V2_Delete_Key; dev->delete_all_keys = KeyMaster_V2_Delete_All_Keys; dev->begin = KeyMaster_V2_Begin; dev->update = KeyMaster_V2_Update; dev->finish = KeyMaster_V2_Finish; dev->abort = KeyMaster_V2_Abort; *device = reinterpret_cast(dev.release()); KeyMaster_V2_Initialize(); ALOGD("%s:AW keymaster v2 open sucessfully!\n",__func__); return 0; } static struct hw_module_methods_t keystore_module_methods = { .open = sunxi_tee_keymaster_v2_device_open, }; struct keystore_module HAL_MODULE_INFO_SYM __attribute__ ((visibility ("default"))) = { .common = { .tag = HARDWARE_MODULE_TAG, .module_api_version = KEYMASTER_MODULE_API_VERSION_2_0, .hal_api_version = HARDWARE_HAL_API_VERSION, .id = KEYSTORE_HARDWARE_MODULE_ID, .name = "AllWinnerTech KeyMaster V2 Tee HAL", .author = "The Android Open Source Project", .methods = &keystore_module_methods, .dso = 0, .reserved = {}, }, };