blob: 847eec15aa858e70f6e4f3023562b189eeeeddd7 [file] [log] [blame]
Imre Kisca48b872023-10-17 18:32:01 +02001/*
2 * Copyright (c) 2023, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include "rpmb_provider.h"
8#include "components/service/rpmb/backend/rpmb_backend.h"
9#include "protocols/service/rpmb/packed-c/rpmb_proto.h"
10#include "util.h"
11#include <string.h>
12
13static rpc_status_t get_dev_info_handler(void *context, struct rpc_request *req)
14{
15 struct rpmb_provider *this_context = (struct rpmb_provider *)context;
16 struct rpmb_request_get_dev_info *request_desc = NULL;
17 struct rpmb_response_get_dev_info *response_desc = NULL;
18
19 if (req->request.data_length < sizeof(*request_desc))
20 return RPC_ERROR_INVALID_REQUEST_BODY;
21
22 if (req->response.size < sizeof(*response_desc))
23 return RPC_ERROR_INVALID_RESPONSE_BODY;
24
25 request_desc = (struct rpmb_request_get_dev_info *)(req->request.data);
26 response_desc = (struct rpmb_response_get_dev_info *)(req->response.data);
27
28 req->service_status = rpmb_backend_get_dev_info(this_context->backend, request_desc->dev_id,
29 &response_desc->dev_info);
30
31 if (!req->service_status)
32 req->response.data_length = sizeof(*response_desc);
33
34 return RPC_SUCCESS;
35}
36
37static bool validate_size(size_t header_size, uint32_t frame_count, size_t available_length,
38 size_t *total_size)
39{
40 /*
41 * Checking if [data frame count] * [data frame size] + [header size] fits into the RPC
42 * buffer.
43 */
44
45 if (MUL_OVERFLOW(frame_count, sizeof(struct rpmb_data_frame), total_size))
46 return false;
47
48 if (ADD_OVERFLOW(*total_size, header_size, total_size))
49 return false;
50
51 if (*total_size > available_length)
52 return false;
53
54 return true;
55}
56
57static rpc_status_t data_request_handler(void *context, struct rpc_request *req)
58{
59 struct rpmb_provider *this_context = (struct rpmb_provider *)context;
60 struct rpmb_request_data_request *request_desc = NULL;
61 struct rpmb_response_data_request *response_desc = NULL;
62 size_t response_frame_count = 0;
63 size_t total_size = 0;
64
65 if (req->request.data_length < sizeof(*request_desc))
66 return RPC_ERROR_INVALID_REQUEST_BODY;
67
68 request_desc = (struct rpmb_request_data_request *)(req->request.data);
69
70 if (!validate_size(sizeof(*request_desc), request_desc->request_frame_count,
71 req->request.data_length, &total_size))
72 return RPC_ERROR_INVALID_REQUEST_BODY;
73
74 if (!validate_size(sizeof(*response_desc), request_desc->max_response_frame_count,
75 req->response.size, &total_size))
76 return RPC_ERROR_INVALID_RESPONSE_BODY;
77
78 response_desc = (struct rpmb_response_data_request *)(req->response.data);
79 response_frame_count = request_desc->max_response_frame_count;
80
81 req->service_status = rpmb_backend_data_request(
82 this_context->backend,
83 request_desc->dev_id,
84 request_desc->request_frames,
85 request_desc->request_frame_count,
86 response_desc->response_frames,
87 &response_frame_count);
88
89 if (!req->service_status) {
90 if (!validate_size(sizeof(*response_desc), response_frame_count,
91 req->response.size, &total_size))
92 return RPC_ERROR_INVALID_RESPONSE_BODY;
93
94 response_desc->response_frame_count = response_frame_count;
95 req->response.data_length = total_size;
96 }
97
98 return RPC_SUCCESS;
99}
100
101static const struct service_handler handler_table[] = {
102 {TS_RPMB_OPCODE_GET_DEV_INFO, get_dev_info_handler},
103 {TS_RPMB_OPCODE_DATA_REQUEST, data_request_handler},
104};
105
106struct rpc_service_interface *rpmb_provider_init(struct rpmb_provider *context,
107 struct rpmb_backend *backend,
108 const struct rpc_uuid *service_uuid)
109{
110 struct rpc_service_interface *rpc_interface = NULL;
111
112 if (!context || !backend || !service_uuid)
113 return NULL;
114
115 service_provider_init(&context->base_provider, context, service_uuid, handler_table,
116 ARRAY_SIZE(handler_table));
117
118 rpc_interface = service_provider_get_rpc_interface(&context->base_provider);
119
120 context->backend = backend;
121
122 return rpc_interface;
123}
124
125void rpmb_provider_deinit(struct rpmb_provider *context)
126{
127 (void)context;
128}