sgx_status_t derive_key( const sgx_ec256_dh_shared_t* shared_key, const char* label, uint32_t label_length, sgx_ec_key_128bit_t* derived_key) { sgx_status_t se_ret = SGX_SUCCESS; uint8_t cmac_key[MAC_KEY_SIZE]; sgx_ec_key_128bit_t key_derive_key; if (!shared_key || !derived_key || !label) { return SGX_ERROR_INVALID_PARAMETER; } /*check integer overflow */ if (label_length > EC_DERIVATION_BUFFER_SIZE(label_length)) { return SGX_ERROR_INVALID_PARAMETER; } memset(cmac_key, 0, MAC_KEY_SIZE); se_ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t *)cmac_key, (uint8_t*)shared_key, sizeof(sgx_ec256_dh_shared_t), (sgx_cmac_128bit_tag_t *)&key_derive_key); if (SGX_SUCCESS != se_ret) { memset_s(&key_derive_key, sizeof(key_derive_key), 0, sizeof(key_derive_key)); INTERNAL_SGX_ERROR_CODE_CONVERTOR(se_ret); return se_ret; } /* derivation_buffer = counter(0x01) || label || 0x00 || output_key_len(0x0080) */ uint32_t derivation_buffer_length = EC_DERIVATION_BUFFER_SIZE(label_length); uint8_t *p_derivation_buffer = (uint8_t *)malloc(derivation_buffer_length); if (p_derivation_buffer == NULL) { return SGX_ERROR_OUT_OF_MEMORY; } memset(p_derivation_buffer, 0, derivation_buffer_length); /*counter = 0x01 */ p_derivation_buffer[0] = 0x01; /*label*/ memcpy(&p_derivation_buffer[1], label, label_length); /*output_key_len=0x0080*/ uint16_t *key_len = (uint16_t *)&p_derivation_buffer[derivation_buffer_length - 2]; *key_len = 0x0080; se_ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t *)&key_derive_key, p_derivation_buffer, derivation_buffer_length, (sgx_cmac_128bit_tag_t *)derived_key); memset_s(&key_derive_key, sizeof(key_derive_key), 0, sizeof(key_derive_key)); free(p_derivation_buffer); if(SGX_SUCCESS != se_ret) { INTERNAL_SGX_ERROR_CODE_CONVERTOR(se_ret); } return se_ret; }
// Derive key from shared key and key id. // key id should be sample_derive_key_type_t. bool derive_key( const sample_ec_dh_shared_t *p_shared_key, uint8_t key_id, sample_ec_key_128bit_t* derived_key) { sample_status_t sample_ret = SAMPLE_SUCCESS; uint8_t cmac_key[MAC_KEY_SIZE]; sample_ec_key_128bit_t key_derive_key; memset(&cmac_key, 0, MAC_KEY_SIZE); sample_ret = sample_rijndael128_cmac_msg( (sample_cmac_128bit_key_t *)&cmac_key, (uint8_t*)p_shared_key, sizeof(sample_ec_dh_shared_t), (sample_cmac_128bit_tag_t *)&key_derive_key); if (sample_ret != SAMPLE_SUCCESS) { // memset here can be optimized away by compiler, so please use memset_s on // windows for production code and similar functions on other OSes. memset(&key_derive_key, 0, sizeof(key_derive_key)); return false; } const char *label = NULL; uint32_t label_length = 0; switch (key_id) { case SAMPLE_DERIVE_KEY_SMK: label = str_SMK; label_length = sizeof(str_SMK) -1; break; case SAMPLE_DERIVE_KEY_SK: label = str_SK; label_length = sizeof(str_SK) -1; break; case SAMPLE_DERIVE_KEY_MK: label = str_MK; label_length = sizeof(str_MK) -1; break; case SAMPLE_DERIVE_KEY_VK: label = str_VK; label_length = sizeof(str_VK) -1; break; default: // memset here can be optimized away by compiler, so please use memset_s on // windows for production code and similar functions on other OSes. memset(&key_derive_key, 0, sizeof(key_derive_key)); return false; break; } /* derivation_buffer = counter(0x01) || label || 0x00 || output_key_len(0x0080) */ uint32_t derivation_buffer_length = EC_DERIVATION_BUFFER_SIZE(label_length); uint8_t *p_derivation_buffer = (uint8_t *)malloc(derivation_buffer_length); if (p_derivation_buffer == NULL) { // memset here can be optimized away by compiler, so please use memset_s on // windows for production code and similar functions on other OSes. memset(&key_derive_key, 0, sizeof(key_derive_key)); return false; } memset(p_derivation_buffer, 0, derivation_buffer_length); /*counter = 0x01 */ p_derivation_buffer[0] = 0x01; /*label*/ memcpy(&p_derivation_buffer[1], label, label_length); /*output_key_len=0x0080*/ uint16_t *key_len = (uint16_t *)(&(p_derivation_buffer[derivation_buffer_length - 2])); *key_len = 0x0080; sample_ret = sample_rijndael128_cmac_msg( (sample_cmac_128bit_key_t *)&key_derive_key, p_derivation_buffer, derivation_buffer_length, (sample_cmac_128bit_tag_t *)derived_key); free(p_derivation_buffer); // memset here can be optimized away by compiler, so please use memset_s on // windows for production code and similar functions on other OSes. memset(&key_derive_key, 0, sizeof(key_derive_key)); if (sample_ret != SAMPLE_SUCCESS) { return false; } return true; }