| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "optee-message.h" |
| |
| #include <endian.h> |
| #include <string.h> |
| |
| #include <limits> |
| #include <memory> |
| |
| #include "optee-llcpp.h" |
| #include "optee-util.h" |
| |
| namespace optee { |
| |
| namespace { |
| |
| // Converts a big endian UUID from a MessageParam value to a host endian TEEC_UUID. |
| // The fields of a UUID are stored in big endian in a MessageParam by the TEE and is thus why the |
| // parameter value cannot be directly reinterpreted as a UUID. |
| void ConvertMessageParamToUuid(const MessageParam::Value& src, TEEC_UUID* dst) { |
| // Convert TEEC_UUID fields from big endian to host endian |
| dst->timeLow = betoh32(src.uuid_big_endian.timeLow); |
| dst->timeMid = betoh16(src.uuid_big_endian.timeMid); |
| dst->timeHiAndVersion = betoh16(src.uuid_big_endian.timeHiAndVersion); |
| |
| // Because clockSeqAndNode is uint8_t, no need to convert endianness - just memcpy |
| memcpy(dst->clockSeqAndNode, src.uuid_big_endian.clockSeqAndNode, |
| sizeof(src.uuid_big_endian.clockSeqAndNode)); |
| } |
| |
| constexpr bool IsDirectionInput(fuchsia_tee::Direction direction) { |
| return (direction == fuchsia_tee::Direction::INPUT) || |
| (direction == fuchsia_tee::Direction::INOUT); |
| } |
| |
| constexpr bool IsDirectionOutput(fuchsia_tee::Direction direction) { |
| return (direction == fuchsia_tee::Direction::OUTPUT) || |
| (direction == fuchsia_tee::Direction::INOUT); |
| } |
| |
| } // namespace |
| |
| zx_status_t Message::TryInitializeParameters( |
| size_t starting_param_index, fidl::VectorView<fuchsia_tee::Parameter> parameter_set, |
| SharedMemoryManager::ClientMemoryPool* temp_memory_pool) { |
| zx_status_t status = ZX_OK; |
| for (size_t i = 0; i < parameter_set.count(); i++) { |
| MessageParam& optee_param = params()[starting_param_index + i]; |
| fuchsia_tee::Parameter& zx_param = parameter_set[i]; |
| |
| switch (zx_param.which()) { |
| case fuchsia_tee::Parameter::Tag::kNone: |
| optee_param.attribute = MessageParam::kAttributeTypeNone; |
| break; |
| case fuchsia_tee::Parameter::Tag::kValue: |
| status = TryInitializeValue(zx_param.value(), &optee_param); |
| break; |
| case fuchsia_tee::Parameter::Tag::kBuffer: |
| status = TryInitializeBuffer(&zx_param.mutable_buffer(), temp_memory_pool, &optee_param); |
| break; |
| default: |
| return ZX_ERR_INVALID_ARGS; |
| } |
| |
| if (status != ZX_OK) { |
| return status; |
| } |
| } |
| |
| return status; |
| } |
| |
| zx_status_t Message::TryInitializeValue(const fuchsia_tee::Value& value, MessageParam* out_param) { |
| ZX_DEBUG_ASSERT(out_param != nullptr); |
| |
| if (!value.has_direction()) { |
| return ZX_ERR_INVALID_ARGS; |
| } |
| |
| switch (value.direction()) { |
| case fuchsia_tee::Direction::INPUT: |
| out_param->attribute = MessageParam::kAttributeTypeValueInput; |
| break; |
| case fuchsia_tee::Direction::OUTPUT: |
| out_param->attribute = MessageParam::kAttributeTypeValueOutput; |
| break; |
| case fuchsia_tee::Direction::INOUT: |
| out_param->attribute = MessageParam::kAttributeTypeValueInOut; |
| break; |
| default: |
| return ZX_ERR_INVALID_ARGS; |
| } |
| |
| if (IsDirectionInput(value.direction())) { |
| out_param->payload.value.generic.a = value.has_a() ? value.a() : 0; |
| out_param->payload.value.generic.b = value.has_b() ? value.b() : 0; |
| out_param->payload.value.generic.c = value.has_c() ? value.c() : 0; |
| } |
| |
| return ZX_OK; |
| } |
| |
| zx_status_t Message::TryInitializeBuffer(fuchsia_tee::Buffer* buffer, |
| SharedMemoryManager::ClientMemoryPool* temp_memory_pool, |
| MessageParam* out_param) { |
| ZX_DEBUG_ASSERT(buffer != nullptr); |
| ZX_DEBUG_ASSERT(temp_memory_pool != nullptr); |
| ZX_DEBUG_ASSERT(out_param != nullptr); |
| |
| if (!buffer->has_direction() || !buffer->has_size() || !buffer->has_offset()) { |
| return ZX_ERR_INVALID_ARGS; |
| } |
| |
| // Take ownership of the provided VMO. If we have to return early for any reason, this will |
| // take care of closing the VMO. |
| zx::vmo vmo; |
| if (buffer->has_vmo()) { |
| vmo = std::move(buffer->vmo()); |
| } |
| |
| MessageParam::AttributeType attribute; |
| switch (buffer->direction()) { |
| case fuchsia_tee::Direction::INPUT: |
| attribute = MessageParam::kAttributeTypeTempMemInput; |
| break; |
| case fuchsia_tee::Direction::OUTPUT: |
| attribute = MessageParam::kAttributeTypeTempMemOutput; |
| break; |
| case fuchsia_tee::Direction::INOUT: |
| attribute = MessageParam::kAttributeTypeTempMemInOut; |
| break; |
| default: |
| return ZX_ERR_INVALID_ARGS; |
| } |
| |
| // If an invalid VMO was provided, this is a null memory reference. |
| if (!vmo.is_valid()) { |
| // No need to allocate a temporary buffer from the shared memory pool, |
| out_param->attribute = attribute; |
| out_param->payload.temporary_memory.buffer = 0; |
| out_param->payload.temporary_memory.size = buffer->size(); |
| out_param->payload.temporary_memory.shared_memory_reference = 0; |
| return ZX_OK; |
| } |
| |
| // For most buffer types, we must allocate a temporary shared memory buffer within the physical |
| // pool to share it with the TEE. We'll attach them to the Message object so that they can be |
| // looked up upon return from TEE and to tie the lifetimes of the Message and the temporary |
| // shared memory together. |
| SharedMemoryPtr shared_mem; |
| zx_status_t status = temp_memory_pool->Allocate(buffer->size(), &shared_mem); |
| if (status != ZX_OK) { |
| LOG(ERROR, "failed to allocate temporary shared memory (%" PRIu64 ")", buffer->size()); |
| return status; |
| } |
| |
| uint64_t paddr = static_cast<uint64_t>(shared_mem->paddr()); |
| |
| TemporarySharedMemory temp_shared_mem{std::move(vmo), buffer->offset(), buffer->size(), |
| std::move(shared_mem)}; |
| |
| // Input buffers should be copied into the shared memory buffer. Output only buffers can skip |
| // this step. |
| if (IsDirectionInput(buffer->direction())) { |
| status = temp_shared_mem.SyncToSharedMemory(); |
| if (status != ZX_OK) { |
| LOG(ERROR, "shared memory sync failed (%d)", status); |
| return status; |
| } |
| } |
| |
| allocated_temp_memory_.push_back(std::move(temp_shared_mem)); |
| uint64_t index = static_cast<uint64_t>(allocated_temp_memory_.size()) - 1; |
| |
| out_param->attribute = attribute; |
| out_param->payload.temporary_memory.buffer = paddr; |
| out_param->payload.temporary_memory.size = buffer->size(); |
| out_param->payload.temporary_memory.shared_memory_reference = index; |
| return ZX_OK; |
| } |
| |
| zx_status_t Message::CreateOutputParameterSet(size_t starting_param_index, |
| ParameterSet* out_parameter_set) { |
| ZX_DEBUG_ASSERT(out_parameter_set != nullptr); |
| |
| if (header()->num_params < starting_param_index) { |
| LOG(ERROR, "Message contained fewer parameters (%" PRIu32 ") than required %zd", |
| header()->num_params, starting_param_index); |
| return ZX_ERR_INVALID_ARGS; |
| } |
| |
| // Ensure that the number of parameters returned by the TEE does not exceed the parameter set |
| // array of parameters. |
| const size_t count = header()->num_params - starting_param_index; |
| if (count > fuchsia_tee::MAX_PARAMETERSET_COUNT) { |
| LOG(ERROR, "Message contained more parameters (%zd) than allowed", count); |
| return ZX_ERR_INVALID_ARGS; |
| } |
| |
| std::vector<Parameter> parameters; |
| parameters.reserve(count); |
| |
| for (size_t i = 0; i < count; i++) { |
| const MessageParam& optee_param = params()[i + starting_param_index]; |
| Parameter parameter; |
| |
| switch (optee_param.attribute) { |
| case MessageParam::kAttributeTypeNone: { |
| parameter.set_none(); |
| break; |
| } |
| case MessageParam::kAttributeTypeValueInput: |
| case MessageParam::kAttributeTypeValueOutput: |
| case MessageParam::kAttributeTypeValueInOut: |
| parameter.set_value(CreateOutputValueParameter(optee_param)); |
| break; |
| case MessageParam::kAttributeTypeTempMemInput: |
| case MessageParam::kAttributeTypeTempMemOutput: |
| case MessageParam::kAttributeTypeTempMemInOut: { |
| Buffer buffer; |
| if (zx_status_t status = CreateOutputBufferParameter(optee_param, &buffer); |
| status != ZX_OK) { |
| return status; |
| } |
| parameter.set_buffer(std::move(buffer)); |
| break; |
| } |
| case MessageParam::kAttributeTypeRegMemInput: |
| case MessageParam::kAttributeTypeRegMemOutput: |
| case MessageParam::kAttributeTypeRegMemInOut: |
| default: |
| break; |
| } |
| |
| parameters.push_back(std::move(parameter)); |
| } |
| |
| out_parameter_set->set_parameters(std::move(parameters)); |
| return ZX_OK; |
| } |
| |
| Value Message::CreateOutputValueParameter(const MessageParam& optee_param) { |
| Value zx_value; |
| |
| fuchsia_tee::Direction direction; |
| |
| switch (optee_param.attribute) { |
| case MessageParam::kAttributeTypeValueInput: |
| direction = fuchsia_tee::Direction::INPUT; |
| break; |
| case MessageParam::kAttributeTypeValueOutput: |
| direction = fuchsia_tee::Direction::OUTPUT; |
| break; |
| case MessageParam::kAttributeTypeValueInOut: |
| direction = fuchsia_tee::Direction::INOUT; |
| break; |
| default: |
| ZX_PANIC("Invalid OP-TEE attribute specified\n"); |
| } |
| |
| const MessageParam::Value& optee_value = optee_param.payload.value; |
| |
| if (IsDirectionOutput(direction)) { |
| // Only transmit value parameter members if the parameter is marked as output. |
| zx_value.set_a(optee_value.generic.a); |
| zx_value.set_b(optee_value.generic.b); |
| zx_value.set_c(optee_value.generic.c); |
| } |
| zx_value.set_direction(direction); |
| |
| return zx_value; |
| } |
| |
| zx_status_t Message::CreateOutputBufferParameter(const MessageParam& optee_param, |
| Buffer* out_buffer) { |
| ZX_DEBUG_ASSERT(out_buffer != nullptr); |
| |
| fuchsia_tee::Direction direction; |
| switch (optee_param.attribute) { |
| case MessageParam::kAttributeTypeTempMemInput: |
| direction = fuchsia_tee::Direction::INPUT; |
| break; |
| case MessageParam::kAttributeTypeTempMemOutput: |
| direction = fuchsia_tee::Direction::OUTPUT; |
| break; |
| case MessageParam::kAttributeTypeTempMemInOut: |
| direction = fuchsia_tee::Direction::INOUT; |
| break; |
| default: |
| ZX_PANIC("Invalid OP-TEE attribute specified\n"); |
| } |
| out_buffer->set_direction(direction); |
| |
| const MessageParam::TemporaryMemory& optee_temp_mem = optee_param.payload.temporary_memory; |
| |
| const size_t size = optee_temp_mem.size; |
| out_buffer->set_size(size); |
| |
| if (optee_temp_mem.buffer == 0) { |
| // If there was no buffer and this was just a size check, just return the size. |
| return ZX_OK; |
| } |
| |
| if (optee_temp_mem.shared_memory_reference >= allocated_temp_memory_.size()) { |
| LOG(ERROR, "TEE returned an invalid shared_memory_reference (%" PRIu64 ")", |
| optee_temp_mem.shared_memory_reference); |
| return ZX_ERR_INVALID_ARGS; |
| } |
| |
| auto& temp_shared_memory = allocated_temp_memory_[optee_temp_mem.shared_memory_reference]; |
| |
| if (!temp_shared_memory.is_valid()) { |
| LOG(ERROR, "invalid TemporarySharedMemory attempted to be used"); |
| return ZX_ERR_INVALID_ARGS; |
| } |
| |
| // For output buffers, we need to sync the shared memory buffer back to the VMO. It's possible |
| // that the returned size is smaller or larger than the originally provided buffer. |
| if (IsDirectionOutput(direction)) { |
| if (zx_status_t status = temp_shared_memory.SyncToVmo(size); status != ZX_OK) { |
| LOG(ERROR, "SharedMemory writeback to vmo failed (%d)", status); |
| return status; |
| } |
| } |
| |
| out_buffer->set_vmo(zx::vmo(temp_shared_memory.ReleaseVmo())); |
| out_buffer->set_offset(temp_shared_memory.vmo_offset()); |
| |
| return ZX_OK; |
| } |
| |
| Message::TemporarySharedMemory::TemporarySharedMemory(zx::vmo vmo, uint64_t vmo_offset, size_t size, |
| std::unique_ptr<SharedMemory> shared_memory) |
| : vmo_(std::move(vmo)), |
| vmo_offset_(vmo_offset), |
| size_(size), |
| shared_memory_(std::move(shared_memory)) {} |
| |
| zx_status_t Message::TemporarySharedMemory::SyncToSharedMemory() { |
| ZX_DEBUG_ASSERT(is_valid()); |
| return vmo_.read(reinterpret_cast<void*>(shared_memory_->vaddr()), vmo_offset_, size_); |
| } |
| |
| zx_status_t Message::TemporarySharedMemory::SyncToVmo(size_t actual_size) { |
| ZX_DEBUG_ASSERT(is_valid()); |
| // If the actual size of the data is larger than the size of the vmo, then we should skip the |
| // actual write. This is a valid scenario and the Trusted World will be responsible for |
| // providing the short buffer error code in it's result. |
| if (actual_size > size_) { |
| return ZX_OK; |
| } |
| // TODO(fxbug.dev/35763): synchronize only actual_size bytes. |
| // Currently we synchronize the whole shared memory back to the vmo |
| // as a workaround, even though that should be unnecessary. |
| return vmo_.write(reinterpret_cast<void*>(shared_memory_->vaddr()), vmo_offset_, size_); |
| } |
| |
| zx_handle_t Message::TemporarySharedMemory::ReleaseVmo() { return vmo_.release(); } |
| |
| fit::result<OpenSessionMessage, zx_status_t> OpenSessionMessage::TryCreate( |
| SharedMemoryManager::DriverMemoryPool* message_pool, |
| SharedMemoryManager::ClientMemoryPool* temp_memory_pool, const Uuid& trusted_app, |
| fidl::VectorView<fuchsia_tee::Parameter> parameter_set) { |
| ZX_DEBUG_ASSERT(message_pool != nullptr); |
| ZX_DEBUG_ASSERT(temp_memory_pool != nullptr); |
| |
| const size_t num_params = parameter_set.count() + kNumFixedOpenSessionParams; |
| ZX_DEBUG_ASSERT(num_params <= std::numeric_limits<uint32_t>::max()); |
| |
| SharedMemoryPtr memory; |
| zx_status_t status = message_pool->Allocate(CalculateSize(num_params), &memory); |
| if (status != ZX_OK) { |
| return fit::error(status); |
| } |
| |
| OpenSessionMessage message(std::move(memory)); |
| |
| message.header()->command = Command::kOpenSession; |
| message.header()->cancel_id = 0; |
| message.header()->num_params = static_cast<uint32_t>(num_params); |
| |
| MessageParam& trusted_app_param = message.params()[kTrustedAppParamIndex]; |
| MessageParam& client_app_param = message.params()[kClientAppParamIndex]; |
| |
| trusted_app_param.attribute = |
| MessageParam::kAttributeTypeMeta | MessageParam::kAttributeTypeValueInput; |
| trusted_app.ToUint64Pair(&trusted_app_param.payload.value.generic.a, |
| &trusted_app_param.payload.value.generic.b); |
| |
| client_app_param.attribute = |
| MessageParam::kAttributeTypeMeta | MessageParam::kAttributeTypeValueInput; |
| // Not really any need to provide client app uuid, so just fill in with 0s |
| client_app_param.payload.value.generic.a = 0; |
| client_app_param.payload.value.generic.b = 0; |
| client_app_param.payload.value.generic.c = TEEC_LOGIN_PUBLIC; |
| |
| status = message.TryInitializeParameters(kNumFixedOpenSessionParams, std::move(parameter_set), |
| temp_memory_pool); |
| if (status != ZX_OK) { |
| return fit::error(status); |
| } |
| |
| return fit::ok(std::move(message)); |
| } |
| |
| fit::result<CloseSessionMessage, zx_status_t> CloseSessionMessage::TryCreate( |
| SharedMemoryManager::DriverMemoryPool* message_pool, uint32_t session_id) { |
| ZX_DEBUG_ASSERT(message_pool != nullptr); |
| |
| SharedMemoryPtr memory; |
| zx_status_t status = message_pool->Allocate(CalculateSize(kNumParams), &memory); |
| if (status != ZX_OK) { |
| return fit::error(status); |
| } |
| |
| CloseSessionMessage message(std::move(memory)); |
| message.header()->command = Command::kCloseSession; |
| message.header()->num_params = static_cast<uint32_t>(kNumParams); |
| message.header()->session_id = session_id; |
| |
| return fit::ok(std::move(message)); |
| } |
| |
| fit::result<InvokeCommandMessage, zx_status_t> InvokeCommandMessage::TryCreate( |
| SharedMemoryManager::DriverMemoryPool* message_pool, |
| SharedMemoryManager::ClientMemoryPool* temp_memory_pool, uint32_t session_id, |
| uint32_t command_id, fidl::VectorView<fuchsia_tee::Parameter> parameter_set) { |
| ZX_DEBUG_ASSERT(message_pool != nullptr); |
| |
| const size_t num_params = parameter_set.count(); |
| |
| SharedMemoryPtr memory; |
| zx_status_t status = message_pool->Allocate(CalculateSize(num_params), &memory); |
| if (status != ZX_OK) { |
| return fit::error(status); |
| } |
| |
| InvokeCommandMessage message(std::move(memory)); |
| |
| message.header()->command = Command::kInvokeCommand; |
| message.header()->session_id = session_id; |
| message.header()->app_function = command_id; |
| message.header()->cancel_id = 0; |
| message.header()->num_params = static_cast<uint32_t>(num_params); |
| |
| status = message.TryInitializeParameters(0, std::move(parameter_set), temp_memory_pool); |
| if (status != ZX_OK) { |
| return fit::error(status); |
| } |
| |
| return fit::ok(std::move(message)); |
| } |
| |
| fit::result<RpcMessage, zx_status_t> RpcMessage::CreateFromSharedMemory(SharedMemory* memory) { |
| size_t memory_size = memory->size(); |
| if (memory_size < sizeof(MessageHeader)) { |
| LOG(ERROR, |
| "shared memory region passed into RPC command could not be parsed into a valid message!"); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // The header portion is at least valid, so create an `RpcMessage` in order to access and |
| // validate the header. |
| RpcMessage message(memory); |
| |
| if (memory_size < CalculateSize(message.header()->num_params)) { |
| LOG(ERROR, |
| "shared memory region passed into RPC command could not be parsed into a valid message!"); |
| message.header()->return_origin = TEEC_ORIGIN_COMMS; |
| message.header()->return_code = TEEC_ERROR_BAD_PARAMETERS; |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| return fit::ok(std::move(message)); |
| } |
| |
| fit::result<LoadTaRpcMessage, zx_status_t> LoadTaRpcMessage::CreateFromRpcMessage( |
| RpcMessage&& rpc_message) { |
| ZX_DEBUG_ASSERT(rpc_message.command() == RpcMessage::Command::kLoadTa); |
| |
| LoadTaRpcMessage result_message(std::move(rpc_message)); |
| if (result_message.header()->num_params != kNumParams) { |
| LOG(ERROR, "RPC command to load trusted app received unexpected number of parameters! (%u)", |
| result_message.header()->num_params); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse the UUID of the trusted application from the parameters |
| MessageParam& uuid_param = result_message.params()[kUuidParamIndex]; |
| switch (uuid_param.attribute) { |
| case MessageParam::kAttributeTypeValueInput: |
| case MessageParam::kAttributeTypeValueInOut: |
| ConvertMessageParamToUuid(uuid_param.payload.value, &result_message.ta_uuid_); |
| break; |
| default: |
| LOG(ERROR, "RPC command to load trusted app received unexpected first parameter!"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse where in memory to write the trusted application |
| MessageParam& memory_reference_param = result_message.params()[kMemoryReferenceParamIndex]; |
| switch (memory_reference_param.attribute) { |
| case MessageParam::kAttributeTypeTempMemOutput: |
| case MessageParam::kAttributeTypeTempMemInOut: { |
| MessageParam::TemporaryMemory& temp_mem = memory_reference_param.payload.temporary_memory; |
| result_message.mem_id_ = temp_mem.shared_memory_reference; |
| result_message.mem_size_ = static_cast<size_t>(temp_mem.size); |
| result_message.mem_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer); |
| result_message.out_ta_size_ = &temp_mem.size; |
| break; |
| } |
| case MessageParam::kAttributeTypeRegMemOutput: |
| case MessageParam::kAttributeTypeRegMemInOut: |
| LOG(ERROR, "received unsupported registered memory parameter!"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_NOT_IMPLEMENTED); |
| return fit::error(ZX_ERR_NOT_SUPPORTED); |
| default: |
| LOG(ERROR, "RPC command to load trusted app received unexpected second parameter!"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| return fit::ok(std::move(result_message)); |
| } |
| |
| fit::result<RpmbRpcMessage, zx_status_t> RpmbRpcMessage::CreateFromRpcMessage( |
| RpcMessage&& rpc_message) { |
| ZX_DEBUG_ASSERT(rpc_message.command() == RpcMessage::Command::kAccessReplayProtectedMemoryBlock); |
| |
| RpmbRpcMessage result_message(std::move(rpc_message)); |
| if (result_message.header()->num_params != kNumParams) { |
| LOG(ERROR, "RPC command to access RPMB storage received unexpected number of parameters! (%u)", |
| result_message.header()->num_params); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| MessageParam& tx_frame_memory_reference_param = |
| result_message.params()[kTxMemoryReferenceParamIndex]; |
| switch (tx_frame_memory_reference_param.attribute) { |
| case MessageParam::kAttributeTypeTempMemInput: { |
| MessageParam::TemporaryMemory& temp_mem = |
| tx_frame_memory_reference_param.payload.temporary_memory; |
| result_message.tx_frame_mem_id_ = temp_mem.shared_memory_reference; |
| result_message.tx_frame_mem_size_ = static_cast<size_t>(temp_mem.size); |
| result_message.tx_frame_mem_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer); |
| break; |
| } |
| case MessageParam::kAttributeTypeRegMemInput: |
| LOG(ERROR, "received unsupported registered memory parameter!"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_NOT_IMPLEMENTED); |
| return fit::error(ZX_ERR_NOT_SUPPORTED); |
| default: |
| LOG(ERROR, "RPC command to load trusted app received unexpected first parameter!"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| MessageParam& rx_frame_memory_reference_param = |
| result_message.params()[kRxMemoryReferenceParamIndex]; |
| switch (rx_frame_memory_reference_param.attribute) { |
| case MessageParam::kAttributeTypeTempMemOutput: { |
| MessageParam::TemporaryMemory& temp_mem = |
| rx_frame_memory_reference_param.payload.temporary_memory; |
| result_message.rx_frame_mem_id_ = temp_mem.shared_memory_reference; |
| result_message.rx_frame_mem_size_ = static_cast<size_t>(temp_mem.size); |
| result_message.rx_frame_mem_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer); |
| break; |
| } |
| case MessageParam::kAttributeTypeRegMemOutput: |
| LOG(ERROR, "received unsupported registered memory parameter!"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_NOT_IMPLEMENTED); |
| return fit::error(ZX_ERR_NOT_SUPPORTED); |
| default: |
| LOG(ERROR, "RPC command to load trusted app received unexpected second parameter!"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| return fit::ok(std::move(result_message)); |
| } |
| |
| fit::result<GetTimeRpcMessage, zx_status_t> GetTimeRpcMessage::CreateFromRpcMessage( |
| RpcMessage&& rpc_message) { |
| ZX_DEBUG_ASSERT(rpc_message.command() == RpcMessage::Command::kGetTime); |
| |
| GetTimeRpcMessage result_message(std::move(rpc_message)); |
| if (result_message.header()->num_params != kNumParams) { |
| LOG(ERROR, "RPC command to get current time received unexpected number of parameters! (%u)", |
| result_message.header()->num_params); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse the output time parameter |
| MessageParam& time_param = result_message.params()[kTimeParamIndex]; |
| if (time_param.attribute != MessageParam::kAttributeTypeValueOutput) { |
| LOG(ERROR, "RPC command to get current time received unexpected first parameter!"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| result_message.out_secs_ = &time_param.payload.value.get_time_specs.seconds; |
| result_message.out_nanosecs_ = &time_param.payload.value.get_time_specs.nanoseconds; |
| |
| return fit::ok(std::move(result_message)); |
| } |
| |
| fit::result<AllocateMemoryRpcMessage, zx_status_t> AllocateMemoryRpcMessage::CreateFromRpcMessage( |
| RpcMessage&& rpc_message) { |
| ZX_DEBUG_ASSERT(rpc_message.command() == RpcMessage::Command::kAllocateMemory); |
| |
| AllocateMemoryRpcMessage result_message(std::move(rpc_message)); |
| if (result_message.header()->num_params != kNumParams) { |
| LOG(ERROR, |
| "RPC command to allocate shared memory received unexpected number of parameters (%u)!", |
| result_message.header()->num_params); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse the memory specifications parameter |
| MessageParam& value_param = result_message.params()[kMemorySpecsParamIndex]; |
| if (value_param.attribute != MessageParam::kAttributeTypeValueInput) { |
| LOG(ERROR, "RPC command to allocate shared memory received unexpected first parameter!"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| auto& memory_specs_param = value_param.payload.value.allocate_memory_specs; |
| |
| switch (memory_specs_param.memory_type) { |
| case SharedMemoryType::kApplication: |
| case SharedMemoryType::kKernel: |
| case SharedMemoryType::kGlobal: |
| result_message.memory_type_ = static_cast<SharedMemoryType>(memory_specs_param.memory_type); |
| break; |
| default: |
| LOG(ERROR, "received unknown memory type %" PRIu64 " to allocate", |
| memory_specs_param.memory_type); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| result_message.memory_size_ = static_cast<size_t>(memory_specs_param.memory_size); |
| |
| // Set up the memory output parameter |
| MessageParam& out_param = result_message.params()[kOutputTemporaryMemoryParamIndex]; |
| out_param.attribute = MessageParam::AttributeType::kAttributeTypeTempMemOutput; |
| MessageParam::TemporaryMemory& out_temp_mem_param = out_param.payload.temporary_memory; |
| result_message.out_memory_size_ = &out_temp_mem_param.size; |
| result_message.out_memory_buffer_ = &out_temp_mem_param.buffer; |
| result_message.out_memory_id_ = &out_temp_mem_param.shared_memory_reference; |
| |
| return fit::ok(std::move(result_message)); |
| } |
| |
| fit::result<FreeMemoryRpcMessage, zx_status_t> FreeMemoryRpcMessage::CreateFromRpcMessage( |
| RpcMessage&& rpc_message) { |
| ZX_DEBUG_ASSERT(rpc_message.command() == RpcMessage::Command::kFreeMemory); |
| |
| FreeMemoryRpcMessage result_message(std::move(rpc_message)); |
| if (result_message.header()->num_params != kNumParams) { |
| LOG(ERROR, "RPC command to free shared memory received unexpected number of parameters! (%u)", |
| result_message.header()->num_params); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse the memory specifications parameter |
| MessageParam& value_param = result_message.params()[kMemorySpecsParamIndex]; |
| if (value_param.attribute != MessageParam::kAttributeTypeValueInput) { |
| LOG(ERROR, "RPC command to free shared memory received unexpected first parameter!"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| auto& memory_specs_param = value_param.payload.value.free_memory_specs; |
| |
| switch (memory_specs_param.memory_type) { |
| case SharedMemoryType::kApplication: |
| case SharedMemoryType::kKernel: |
| case SharedMemoryType::kGlobal: |
| result_message.memory_type_ = static_cast<SharedMemoryType>(memory_specs_param.memory_type); |
| break; |
| default: |
| LOG(ERROR, "received unknown memory type %" PRIu64 " to free", |
| memory_specs_param.memory_type); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| result_message.memory_id_ = memory_specs_param.memory_id; |
| return fit::ok(std::move(result_message)); |
| } |
| |
| fit::result<FileSystemRpcMessage, zx_status_t> FileSystemRpcMessage::CreateFromRpcMessage( |
| RpcMessage&& rpc_message) { |
| ZX_DEBUG_ASSERT(rpc_message.command() == RpcMessage::Command::kAccessFileSystem); |
| |
| FileSystemRpcMessage result_message(std::move(rpc_message)); |
| if (result_message.header()->num_params < kMinNumParams) { |
| LOG(ERROR, "RPC command to access file system received unexpected number of parameters (%u)", |
| result_message.header()->num_params); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse the file system command parameter |
| MessageParam& command_param = result_message.params()[kFileSystemCommandParamIndex]; |
| switch (command_param.attribute) { |
| case MessageParam::kAttributeTypeValueInput: |
| case MessageParam::kAttributeTypeValueInOut: |
| break; |
| default: |
| LOG(ERROR, "RPC command to access file system received unexpected first parameter!"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| uint64_t command_num = command_param.payload.value.file_system_command.command_number; |
| if (command_num >= kNumFileSystemCommands) { |
| LOG(ERROR, "received unknown file system command %" PRIu64, command_num); |
| result_message.set_return_code(TEEC_ERROR_NOT_SUPPORTED); |
| return fit::error(ZX_ERR_NOT_SUPPORTED); |
| } |
| |
| result_message.fs_command_ = static_cast<FileSystemCommand>(command_num); |
| return fit::ok(std::move(result_message)); |
| } |
| |
| fit::result<OpenFileFileSystemRpcMessage, zx_status_t> |
| OpenFileFileSystemRpcMessage::CreateFromFsRpcMessage(FileSystemRpcMessage&& fs_message) { |
| ZX_DEBUG_ASSERT(fs_message.file_system_command() == FileSystemCommand::kOpenFile); |
| |
| OpenFileFileSystemRpcMessage result_message(std::move(fs_message)); |
| if (result_message.header()->num_params != kNumParams) { |
| LOG(ERROR, "RPC command to open file received unexpected number of parameters (%u)", |
| result_message.header()->num_params); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse the file name parameter |
| MessageParam& path_param = result_message.params()[kPathParamIndex]; |
| switch (path_param.attribute) { |
| case MessageParam::kAttributeTypeTempMemInput: { |
| MessageParam::TemporaryMemory& temp_mem = path_param.payload.temporary_memory; |
| result_message.path_mem_id_ = temp_mem.shared_memory_reference; |
| result_message.path_mem_size_ = temp_mem.size; |
| result_message.path_mem_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer); |
| break; |
| } |
| case MessageParam::kAttributeTypeRegMemInput: |
| LOG(ERROR, "received unsupported registered memory parameter"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_NOT_IMPLEMENTED); |
| return fit::error(ZX_ERR_NOT_SUPPORTED); |
| default: |
| LOG(ERROR, "RPC command to open file received unexpected second parameter"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse the output file identifier parameter |
| MessageParam& out_fs_object_id_param = result_message.params()[kOutFileSystemObjectIdParamIndex]; |
| if (out_fs_object_id_param.attribute != MessageParam::kAttributeTypeValueOutput) { |
| LOG(ERROR, "RPC command to open file received unexpected third parameter"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| result_message.out_fs_object_id_ = |
| &out_fs_object_id_param.payload.value.file_system_object.identifier; |
| |
| return fit::ok(std::move(result_message)); |
| } |
| |
| fit::result<CreateFileFileSystemRpcMessage, zx_status_t> |
| CreateFileFileSystemRpcMessage::CreateFromFsRpcMessage(FileSystemRpcMessage&& fs_message) { |
| ZX_DEBUG_ASSERT(fs_message.file_system_command() == FileSystemCommand::kCreateFile); |
| |
| CreateFileFileSystemRpcMessage result_message(std::move(fs_message)); |
| if (result_message.header()->num_params != kNumParams) { |
| LOG(ERROR, "RPC command to create file received unexpected number of parameters (%u)", |
| result_message.header()->num_params); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse the file name parameter |
| MessageParam& path_param = result_message.params()[kPathParamIndex]; |
| switch (path_param.attribute) { |
| case MessageParam::kAttributeTypeTempMemInput: { |
| MessageParam::TemporaryMemory& temp_mem = path_param.payload.temporary_memory; |
| result_message.path_mem_id_ = temp_mem.shared_memory_reference; |
| result_message.path_mem_size_ = temp_mem.size; |
| result_message.path_mem_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer); |
| break; |
| } |
| case MessageParam::kAttributeTypeRegMemInput: |
| LOG(ERROR, "received unsupported registered memory parameter"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_NOT_IMPLEMENTED); |
| return fit::error(ZX_ERR_NOT_SUPPORTED); |
| default: |
| LOG(ERROR, "RPC command to create file received unexpected second parameter"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse the output file identifier parameter |
| MessageParam& out_fs_object_param = result_message.params()[kOutFileSystemObjectIdParamIndex]; |
| if (out_fs_object_param.attribute != MessageParam::kAttributeTypeValueOutput) { |
| LOG(ERROR, "RPC command to create file received unexpected third parameter"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| result_message.out_fs_object_id_ = |
| &out_fs_object_param.payload.value.file_system_object.identifier; |
| |
| return fit::ok(std::move(result_message)); |
| } |
| |
| fit::result<CloseFileFileSystemRpcMessage, zx_status_t> |
| CloseFileFileSystemRpcMessage::CreateFromFsRpcMessage(FileSystemRpcMessage&& fs_message) { |
| ZX_DEBUG_ASSERT(fs_message.file_system_command() == FileSystemCommand::kCloseFile); |
| |
| CloseFileFileSystemRpcMessage result_message(std::move(fs_message)); |
| if (result_message.header()->num_params != kNumParams) { |
| LOG(ERROR, "RPC command to close file received unexpected number of parameters (%u)", |
| result_message.header()->num_params); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse the file name parameter |
| MessageParam& command_param = result_message.params()[kFileSystemCommandParamIndex]; |
| |
| // The attribute was already validated by FileSystemRpcMessage |
| ZX_DEBUG_ASSERT(command_param.attribute == MessageParam::kAttributeTypeValueInput || |
| command_param.attribute == MessageParam::kAttributeTypeValueInOut); |
| |
| result_message.fs_object_id_ = command_param.payload.value.file_system_command.object_identifier; |
| |
| return fit::ok(std::move(result_message)); |
| } |
| |
| fit::result<ReadFileFileSystemRpcMessage, zx_status_t> |
| ReadFileFileSystemRpcMessage::CreateFromFsRpcMessage(FileSystemRpcMessage&& fs_message) { |
| ZX_DEBUG_ASSERT(fs_message.file_system_command() == FileSystemCommand::kReadFile); |
| |
| ReadFileFileSystemRpcMessage result_message(std::move(fs_message)); |
| if (result_message.header()->num_params != kNumParams) { |
| LOG(ERROR, "RPC command to read file received unexpected number of parameters (%u)", |
| result_message.header()->num_params); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse the file name parameter |
| MessageParam& command_param = result_message.params()[kFileSystemCommandParamIndex]; |
| |
| // The attribute was already validated by FileSystemRpcMessage |
| ZX_DEBUG_ASSERT(command_param.attribute == MessageParam::kAttributeTypeValueInput || |
| command_param.attribute == MessageParam::kAttributeTypeValueInOut); |
| |
| result_message.fs_object_id_ = command_param.payload.value.file_system_command.object_identifier; |
| result_message.file_offset_ = command_param.payload.value.file_system_command.object_offset; |
| |
| // Parse the output memory parameter |
| MessageParam& out_mem_param = result_message.params()[kOutReadBufferMemoryParamIndex]; |
| switch (out_mem_param.attribute) { |
| case MessageParam::kAttributeTypeTempMemOutput: { |
| MessageParam::TemporaryMemory& temp_mem = out_mem_param.payload.temporary_memory; |
| result_message.file_contents_mem_id_ = temp_mem.shared_memory_reference; |
| result_message.file_contents_mem_size_ = static_cast<size_t>(temp_mem.size); |
| result_message.file_contents_mem_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer); |
| result_message.out_file_contents_size_ = &temp_mem.size; |
| break; |
| } |
| case MessageParam::kAttributeTypeRegMemInput: |
| LOG(ERROR, "received unsupported registered memory parameter"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_NOT_IMPLEMENTED); |
| return fit::error(ZX_ERR_NOT_SUPPORTED); |
| default: |
| LOG(ERROR, "RPC command to read file received unexpected second parameter"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_NOT_SUPPORTED); |
| } |
| |
| return fit::ok(std::move(result_message)); |
| } |
| |
| fit::result<WriteFileFileSystemRpcMessage, zx_status_t> |
| WriteFileFileSystemRpcMessage::CreateFromFsRpcMessage(FileSystemRpcMessage&& fs_message) { |
| ZX_DEBUG_ASSERT(fs_message.file_system_command() == FileSystemCommand::kWriteFile); |
| |
| WriteFileFileSystemRpcMessage result_message(std::move(fs_message)); |
| if (result_message.header()->num_params != kNumParams) { |
| LOG(ERROR, "RPC command to write file received unexpected number of parameters (%u)", |
| result_message.header()->num_params); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse the file name parameter |
| MessageParam& command_param = result_message.params()[kFileSystemCommandParamIndex]; |
| |
| // The attribute was already validated by FileSystemRpcMessage |
| ZX_DEBUG_ASSERT(command_param.attribute == MessageParam::kAttributeTypeValueInput || |
| command_param.attribute == MessageParam::kAttributeTypeValueInOut); |
| |
| result_message.fs_object_id_ = command_param.payload.value.file_system_command.object_identifier; |
| result_message.file_offset_ = command_param.payload.value.file_system_command.object_offset; |
| |
| // Parse the write memory parameter |
| MessageParam& mem_param = result_message.params()[kWriteBufferMemoryParam]; |
| switch (mem_param.attribute) { |
| case MessageParam::kAttributeTypeTempMemInput: { |
| MessageParam::TemporaryMemory& temp_mem = mem_param.payload.temporary_memory; |
| result_message.file_contents_mem_id_ = temp_mem.shared_memory_reference; |
| result_message.file_contents_mem_size_ = static_cast<size_t>(temp_mem.size); |
| result_message.file_contents_mem_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer); |
| break; |
| } |
| case MessageParam::kAttributeTypeRegMemInput: |
| LOG(ERROR, "received unsupported registered memory parameter"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_NOT_IMPLEMENTED); |
| return fit::error(ZX_ERR_NOT_SUPPORTED); |
| default: |
| LOG(ERROR, "RPC command to write file received unexpected second parameter"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| return fit::ok(std::move(result_message)); |
| } |
| |
| fit::result<TruncateFileFileSystemRpcMessage, zx_status_t> |
| TruncateFileFileSystemRpcMessage::CreateFromFsRpcMessage(FileSystemRpcMessage&& fs_message) { |
| ZX_DEBUG_ASSERT(fs_message.file_system_command() == FileSystemCommand::kTruncateFile); |
| |
| TruncateFileFileSystemRpcMessage result_message(std::move(fs_message)); |
| if (result_message.header()->num_params != kNumParams) { |
| LOG(ERROR, "RPC command to truncate file received unexpected number of parameters (%u)", |
| result_message.header()->num_params); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse the file command parameter |
| MessageParam& command_param = result_message.params()[kFileSystemCommandParamIndex]; |
| |
| // The attribute was already validated by FileSystemRpcMessage |
| ZX_DEBUG_ASSERT(command_param.attribute == MessageParam::kAttributeTypeValueInput || |
| command_param.attribute == MessageParam::kAttributeTypeValueInOut); |
| |
| result_message.fs_object_id_ = command_param.payload.value.file_system_command.object_identifier; |
| result_message.target_file_size_ = command_param.payload.value.file_system_command.object_offset; |
| |
| return fit::ok(std::move(result_message)); |
| } |
| |
| fit::result<RemoveFileFileSystemRpcMessage, zx_status_t> |
| RemoveFileFileSystemRpcMessage::CreateFromFsRpcMessage(FileSystemRpcMessage&& fs_message) { |
| ZX_DEBUG_ASSERT(fs_message.file_system_command() == FileSystemCommand::kRemoveFile); |
| |
| RemoveFileFileSystemRpcMessage result_message(std::move(fs_message)); |
| if (result_message.header()->num_params != kNumParams) { |
| LOG(ERROR, "RPC command to remove file received unexpected number of parameters (%u)", |
| result_message.header()->num_params); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse the file name parameter |
| MessageParam& path_param = result_message.params()[kFileNameParamIndex]; |
| switch (path_param.attribute) { |
| case MessageParam::kAttributeTypeTempMemInput: { |
| MessageParam::TemporaryMemory& temp_mem = path_param.payload.temporary_memory; |
| result_message.path_mem_id_ = temp_mem.shared_memory_reference; |
| result_message.path_mem_size_ = temp_mem.size; |
| result_message.path_mem_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer); |
| break; |
| } |
| case MessageParam::kAttributeTypeRegMemInput: |
| LOG(ERROR, "received unsupported registered memory parameter"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_NOT_IMPLEMENTED); |
| return fit::error(ZX_ERR_NOT_SUPPORTED); |
| default: |
| LOG(ERROR, "RPC command to remove file received unexpected second parameter"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| return fit::ok(std::move(result_message)); |
| } |
| |
| fit::result<RenameFileFileSystemRpcMessage, zx_status_t> |
| RenameFileFileSystemRpcMessage::CreateFromFsRpcMessage(FileSystemRpcMessage&& fs_message) { |
| ZX_DEBUG_ASSERT(fs_message.file_system_command() == FileSystemCommand::kRenameFile); |
| |
| RenameFileFileSystemRpcMessage result_message(std::move(fs_message)); |
| if (result_message.header()->num_params != kNumParams) { |
| LOG(ERROR, "RPC command to rename file received unexpected number of parameters (%u)", |
| result_message.header()->num_params); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse the overwrite value |
| MessageParam& command_param = result_message.params()[kFileSystemCommandParamIndex]; |
| |
| // The attribute was already validated by FileSystemRpcMessage |
| ZX_DEBUG_ASSERT(command_param.attribute == MessageParam::kAttributeTypeValueInput || |
| command_param.attribute == MessageParam::kAttributeTypeValueInOut); |
| |
| result_message.should_overwrite_ = (command_param.payload.value.generic.b != 0); |
| |
| // Parse the old file name parameter |
| MessageParam& old_file_name_param = result_message.params()[kOldFileNameParamIndex]; |
| switch (old_file_name_param.attribute) { |
| case MessageParam::kAttributeTypeTempMemInput: { |
| MessageParam::TemporaryMemory& temp_mem = old_file_name_param.payload.temporary_memory; |
| result_message.old_file_name_mem_id_ = temp_mem.shared_memory_reference; |
| result_message.old_file_name_mem_size_ = temp_mem.size; |
| result_message.old_file_name_mem_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer); |
| break; |
| } |
| case MessageParam::kAttributeTypeRegMemInput: |
| LOG(ERROR, "received unsupported registered memory parameter"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_NOT_IMPLEMENTED); |
| return fit::error(ZX_ERR_NOT_SUPPORTED); |
| default: |
| LOG(ERROR, "RPC command to rename file received unexpected second parameter"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| // Parse the new file name parameter |
| MessageParam& new_file_name_param = result_message.params()[kNewFileNameParamIndex]; |
| switch (new_file_name_param.attribute) { |
| case MessageParam::kAttributeTypeTempMemInput: { |
| MessageParam::TemporaryMemory& temp_mem = new_file_name_param.payload.temporary_memory; |
| result_message.new_file_name_mem_id_ = temp_mem.shared_memory_reference; |
| result_message.new_file_name_mem_size_ = temp_mem.size; |
| result_message.new_file_name_mem_paddr_ = static_cast<zx_paddr_t>(temp_mem.buffer); |
| break; |
| } |
| case MessageParam::kAttributeTypeRegMemInput: |
| LOG(ERROR, "received unsupported registered memory parameter"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_NOT_IMPLEMENTED); |
| return fit::error(ZX_ERR_NOT_SUPPORTED); |
| default: |
| LOG(ERROR, "RPC command to rename file received unexpected third parameter"); |
| result_message.set_return_origin(TEEC_ORIGIN_COMMS); |
| result_message.set_return_code(TEEC_ERROR_BAD_PARAMETERS); |
| return fit::error(ZX_ERR_INVALID_ARGS); |
| } |
| |
| return fit::ok(std::move(result_message)); |
| } |
| |
| } // namespace optee |