case ALGO_AES_GEN: return TEE_TYPE_AES;
case ALGO_RSA_GEN: return TEE_TYPE_RSA_KEYPAIR;
case ALGO_DSA_GEN: return TEE_TYPE_DSA_KEYPAIR;
+ case ALGO_KEM_GEN: return TEE_TYPE_GENERIC_SECRET;
default: return 0;
}
}
TEE_Free(user_data.data);
return ret;
}
+
+TEE_Result KM_ExecCmdEncapsulateKey(TEE_Param param[4])
+{
+ TEE_Result ret = TEE_SUCCESS;
+
+ void *in_buffer_ptr = param[1].memref.buffer;
+ void *out_buffer_ptr = param[2].memref.buffer;
+ uint32_t buffer_size_guard = param[1].memref.size;
+ uint32_t out_buffer_size_guard = param[2].memref.size;
+
+ uint32_t has_pub_pwd = 0;
+ KM_BinaryData pub_key_id = {0, NULL};
+ KM_BinaryData pub_key = {0, NULL};
+ KM_BinaryData shared_secret_id = {0, NULL};
+ KM_BinaryData encrypted_shared_secret = {0, NULL};
+ KM_BinaryData shared_secret_tag = {0, NULL};
+ KM_PwdData pub_pwd, shared_secret_pwd;
+ uint32_t has_shared_secret_pwd = 0;
+ uint32_t pub_key_len = 0;
+ uint8_t* shared_secret = NULL;
+ uint8_t* ciphertext = NULL;
+ OQS_KEM* kem = NULL;
+ TEE_ObjectHandle key = TEE_HANDLE_NULL;
+
+ tz_kem kem_type = param[0].value.a;
+
+ ret = KM_DeserializeBinaryData(&in_buffer_ptr, &buffer_size_guard, &pub_key_id);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in deserialization of hash(pub_key_id), ret = %x", ret);
+ goto clean;
+ }
+
+ ret = KM_DeserializeFlagAndPw(&in_buffer_ptr, &buffer_size_guard, &has_pub_pwd, &pub_pwd);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in deserialization of public flag and password, ret = %x", ret);
+ goto clean;
+ }
+
+ ret = KM_DeserializeFlagAndPw(&in_buffer_ptr, &buffer_size_guard, &has_shared_secret_pwd, &shared_secret_pwd);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in deserialization of shared secret flag and password, ret = %x", ret);
+ goto clean;
+ }
+
+ ret = KM_DeserializeBinaryData(&in_buffer_ptr, &buffer_size_guard, &shared_secret_id);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in deserialization of hash(shared_secret_id), ret = %x", ret);
+ goto clean;
+ }
+
+ kem = createNewKem(kem_type);
+ if (kem == NULL) {
+ LOG("Invalid OQS algorithm name was provided, or the \
+ requested algorithm was disabled at compile-time.");
+ ret = TEE_ERROR_GENERIC;
+ goto clean;
+ }
+
+ ret = KM_GetDataSize(&pub_key_len, &pub_key_id,
+ has_pub_pwd, &pub_pwd, TYPE_GENERIC_SECRET);
+ if (ret != TEE_SUCCESS) {
+ LOG("Failed to read object data size from storage");
+ goto clean;
+ }
+
+ if (pub_key_len != kem->length_public_key) {
+ LOG("KEM type differs from public key KEM type");
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto clean;
+ }
+
+ pub_key.data = TEE_Malloc(pub_key_len, 0);
+ if (pub_key.data == NULL) {
+ LOG("Failed to assign memory. requested size=%d", pub_key_len);
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto clean;
+ }
+ pub_key.data_size = pub_key_len;
+
+ ret = KM_GetData(pub_key.data, pub_key.data_size, &pub_key_id,
+ has_pub_pwd, &pub_pwd, TYPE_GENERIC_SECRET);
+ if (ret != TEE_SUCCESS) {
+ LOG("Failed to read object data from storage");
+ goto clean;
+ }
+
+ shared_secret = TEE_Malloc(kem->length_shared_secret*sizeof(uint8_t), 0);
+ ciphertext = TEE_Malloc(kem->length_ciphertext*sizeof(uint8_t), 0);
+ if (shared_secret == NULL || ciphertext == NULL) {
+ LOG("Failed to allocate buffers");
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto clean;
+ }
+
+ OQS_STATUS rc = OQS_KEM_encaps(kem, ciphertext, shared_secret, pub_key.data);
+ if (rc != OQS_SUCCESS) {
+ LOG("Error in KEM key encapsulation: %x", rc);
+ ret = TEE_ERROR_GENERIC;
+ goto clean;
+ }
+
+ KM_BinaryData out_ciphertext = {kem->length_ciphertext, ciphertext};
+ KM_BinaryData out_shared_secret = {kem->length_shared_secret, shared_secret};
+
+ ret = KM_Serialize(&out_buffer_ptr, &out_buffer_size_guard, out_ciphertext.data, out_ciphertext.data_size);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in serialization");
+ goto clean;
+ }
+
+ if (has_shared_secret_pwd) {
+ ret = KM_EncryptBinary(&shared_secret_pwd, &out_shared_secret, &encrypted_shared_secret, &shared_secret_tag);
+ if (ret != TEE_SUCCESS) {
+ LOG("Failed to encrypt new key");
+ goto clean;
+ }
+ ret = KM_Serialize(&out_buffer_ptr, &out_buffer_size_guard, shared_secret_tag.data, shared_secret_tag.data_size);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in serialization");
+ goto clean;
+ }
+ ret = KM_CreateKey(TEE_TYPE_AES, encrypted_shared_secret.data_size * 8, encrypted_shared_secret.data, &key);
+ } else {
+ ret = KM_CreateKey(TEE_TYPE_AES, out_shared_secret.data_size * 8, out_shared_secret.data, &key);
+ }
+ if (ret != TEE_SUCCESS) {
+ LOG("Failed to create key");
+ goto clean;
+ }
+
+ ret = KM_SaveKey(NULL, 0, key, shared_secret_id.data, shared_secret_id.data_size);
+ if (TEE_SUCCESS != ret) {
+ LOG("Failed to save generated key");
+ goto clean;
+ }
+
+clean:
+ TEE_CloseObject(key);
+ TEE_Free(pub_key.data);
+ TEE_Free(shared_secret_tag.data);
+ TEE_Free(encrypted_shared_secret.data);
+ TEE_Free(shared_secret);
+ TEE_Free(ciphertext);
+ OQS_KEM_free(kem);
+ return ret;
+}
+
+TEE_Result KM_ExecCmdDecapsulateKey(TEE_Param param[4])
+{
+ TEE_Result ret = TEE_SUCCESS;
+
+ void *in_buffer_ptr = param[1].memref.buffer;
+ void *out_buffer_ptr = param[2].memref.buffer;
+ uint32_t in_buffer_size_guard = param[1].memref.size;
+ uint32_t out_buffer_size_guard = param[2].memref.size;
+
+ uint32_t has_priv_pwd = 0, has_shared_secret_pwd = 0;
+ KM_BinaryData priv_key_id = {0, NULL};
+ KM_BinaryData priv_key = {0, NULL};
+ KM_BinaryData shared_secret_id = {0, NULL};
+ KM_BinaryData ciphertext = {0, NULL};
+ KM_BinaryData encrypted_shared_secret = {0, NULL};
+ KM_BinaryData shared_secret_tag = {0, NULL};
+ KM_PwdData priv_pwd, shared_secret_pwd;
+ uint32_t priv_key_len = 0;
+ uint8_t* shared_secret = NULL;
+ OQS_KEM* kem = NULL;
+ TEE_ObjectHandle key = TEE_HANDLE_NULL;
+
+ tz_kem kem_type = param[0].value.a;
+
+ ret = KM_DeserializeBinaryData(&in_buffer_ptr, &in_buffer_size_guard, &priv_key_id);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in deserialization of hash(priv_key_id), ret = %x", ret);
+ goto clean;
+ }
+
+ ret = KM_DeserializeFlagAndPw(&in_buffer_ptr, &in_buffer_size_guard, &has_priv_pwd, &priv_pwd);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in deserialization of private flag and password, ret = %x", ret);
+ goto clean;
+ }
+
+ ret = KM_DeserializeFlagAndPw(&in_buffer_ptr, &in_buffer_size_guard, &has_shared_secret_pwd, &shared_secret_pwd);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in deserialization of shared secret flag and password, ret = %x", ret);
+ goto clean;
+ }
+
+ ret = KM_DeserializeBinaryData(&in_buffer_ptr, &in_buffer_size_guard, &shared_secret_id);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in deserialization of hash(shared_secret_id), ret = %x", ret);
+ goto clean;
+ }
+
+ ret = KM_DeserializeBinaryData(&in_buffer_ptr, &in_buffer_size_guard, &ciphertext);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in deserialization of hash(ciphertext), ret = %x", ret);
+ goto clean;
+ }
+
+ kem = createNewKem(kem_type);
+ if (kem == NULL) {
+ LOG("Invalid OQS algorithm name was provided, or the \
+ requested algorithm was disabled at compile-time.");
+ ret = TEE_ERROR_GENERIC;
+ goto clean;
+ }
+
+ ret = KM_GetDataSize(&priv_key_len, &priv_key_id,
+ has_priv_pwd, &priv_pwd, TYPE_GENERIC_SECRET);
+ if (ret != TEE_SUCCESS) {
+ LOG("Failed to read object data size from storage");
+ goto clean;
+ }
+
+ if (priv_key_len != kem->length_secret_key) {
+ LOG("KEM type differs from private key KEM type");
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto clean;
+ }
+
+ priv_key.data = TEE_Malloc(priv_key_len, 0);
+ if (priv_key.data == NULL) {
+ LOG("Failed to assign memory. requested size=%d", priv_key_len);
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto clean;
+ }
+ priv_key.data_size = priv_key_len;
+
+ ret = KM_GetData(priv_key.data, priv_key.data_size, &priv_key_id,
+ has_priv_pwd, &priv_pwd, TYPE_GENERIC_SECRET);
+ if (ret != TEE_SUCCESS) {
+ LOG("Failed to read object data from storage");
+ goto clean;
+ }
+
+ shared_secret = TEE_Malloc(kem->length_shared_secret*sizeof(uint8_t), 0);
+ if (shared_secret == NULL) {
+ LOG("Failed to allocate buffer");
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto clean;
+ }
+
+ OQS_STATUS rc = OQS_KEM_decaps(kem, shared_secret, ciphertext.data, priv_key.data);
+ if (rc != OQS_SUCCESS) {
+ LOG("Error in KEM key decapsulation: %x", rc);
+ ret = TEE_ERROR_GENERIC;
+ goto clean;
+ }
+
+ KM_BinaryData out_shared_secret = {kem->length_shared_secret, shared_secret};
+
+ if (has_shared_secret_pwd) {
+ ret = KM_EncryptBinary(&shared_secret_pwd, &out_shared_secret, &encrypted_shared_secret, &shared_secret_tag);
+ if (ret != TEE_SUCCESS) {
+ LOG("Failed to encrypt new key");
+ goto clean;
+ }
+ ret = KM_Serialize(&out_buffer_ptr, &out_buffer_size_guard, shared_secret_tag.data, shared_secret_tag.data_size);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in serialization");
+ goto clean;
+ }
+ ret = KM_CreateKey(TEE_TYPE_AES, encrypted_shared_secret.data_size * 8, encrypted_shared_secret.data, &key);
+ } else {
+ ret = KM_CreateKey(TEE_TYPE_AES, out_shared_secret.data_size * 8, out_shared_secret.data, &key);
+ }
+ if (ret != TEE_SUCCESS) {
+ LOG("Failed to create key");
+ goto clean;
+ }
+
+ ret = KM_SaveKey(NULL, 0, key, shared_secret_id.data, shared_secret_id.data_size);
+ if (TEE_SUCCESS != ret) {
+ LOG("Failed to save generated key");
+ goto clean;
+ }
+
+clean:
+ TEE_CloseObject(key);
+ TEE_Free(priv_key.data);
+ TEE_Free(shared_secret_tag.data);
+ TEE_Free(encrypted_shared_secret.data);
+ TEE_Free(shared_secret);
+ OQS_KEM_free(kem);
+ return ret;
+}
+