blob: 56bc961d2206ec756be9354e72053bfbab12270e [file] [log] [blame]
Imre Kis6d36f5c2023-10-17 18:32:16 +02001/*
2 * Copyright (c) 2023, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include "rpmb_client.h"
8#include "protocols/service/rpmb/packed-c/rpmb_proto.h"
9#include "util.h"
10#include <string.h>
11
12static psa_status_t rpmb_client_get_dev_info(void *context, uint32_t dev_id,
13 struct rpmb_dev_info *dev_info)
14{
15 struct rpmb_client *this_context = (struct rpmb_client *)context;
16 struct rpmb_request_get_dev_info *request_desc = NULL;
17 struct rpmb_response_get_dev_info *response_desc = NULL;
18 size_t response_length = 0;
19 rpc_call_handle handle = 0;
20 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
21 service_status_t service_status = 0;
22 psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
23
24 handle = rpc_caller_session_begin(this_context->session, (uint8_t **)&request_desc,
25 sizeof(*request_desc), sizeof(*response_desc));
26 if (!handle)
27 return PSA_ERROR_GENERIC_ERROR;
28
29 request_desc->dev_id = dev_id;
30
31 rpc_status = rpc_caller_session_invoke(handle, TS_RPMB_OPCODE_GET_DEV_INFO,
32 (uint8_t **)&response_desc, &response_length,
33 &service_status);
34 if (rpc_status != RPC_SUCCESS || response_length != sizeof(*response_desc))
35 goto session_end;
36
37 psa_status = service_status;
38
39 if (psa_status == PSA_SUCCESS)
40 *dev_info = response_desc->dev_info;
41
42session_end:
43 rpc_status = rpc_caller_session_end(handle);
44 if (psa_status == PSA_SUCCESS && rpc_status != RPC_SUCCESS)
45 psa_status = PSA_ERROR_GENERIC_ERROR;
46
47 return psa_status;
48}
49
50static bool calculate_size(size_t header_size, uint32_t frame_count, size_t *frames_size,
51 size_t *total_size)
52{
53 /* Calculating [data frame count] * [data frame size] + [header size] */
54
55 if (MUL_OVERFLOW(frame_count, sizeof(struct rpmb_data_frame), frames_size))
56 return false;
57
58 if (ADD_OVERFLOW(*frames_size, header_size, total_size))
59 return false;
60
61 return true;
62}
63
64static psa_status_t rpmb_client_data_request(void *context, uint32_t dev_id,
65 const struct rpmb_data_frame *request_frames,
66 size_t request_frame_count,
67 struct rpmb_data_frame *response_frames,
68 size_t *response_frame_count)
69{
70 struct rpmb_client *this_context = (struct rpmb_client *)context;
71 /* Request */
72 struct rpmb_request_data_request *request_desc = NULL;
73 size_t request_frames_length = 0;
74 size_t request_length = 0;
75 /* Response */
76 struct rpmb_response_data_request *response_desc = NULL;
77 size_t response_frames_max_length = 0;
78 size_t response_frames_length = 0;
79 size_t response_max_length = 0;
80 size_t response_length = 0;
81 rpc_call_handle handle = 0;
82 /* Status */
83 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
84 service_status_t service_status = 0;
85 psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
86
87 /* Calculating request lengths */
88 if (!calculate_size(sizeof(*request_desc), request_frame_count,
89 &request_frames_length, &request_length))
90 return PSA_ERROR_INVALID_ARGUMENT;
91
92 /* Calculating response lengths */
93 if (!calculate_size(sizeof(*response_desc), *response_frame_count,
94 &response_frames_max_length, &response_max_length))
95 return PSA_ERROR_INVALID_ARGUMENT;
96
97 handle = rpc_caller_session_begin(this_context->session, (uint8_t **)&request_desc,
98 request_length, response_max_length);
99 if (!handle)
100 goto out;
101
102 request_desc->dev_id = dev_id;
103 request_desc->request_frame_count = request_frame_count;
104 request_desc->max_response_frame_count = *response_frame_count;
105 memcpy(request_desc->request_frames, request_frames, request_frames_length);
106
107 rpc_status = rpc_caller_session_invoke(handle, TS_RPMB_OPCODE_DATA_REQUEST,
108 (uint8_t **)&response_desc, &response_length,
109 &service_status);
110 if (rpc_status != RPC_SUCCESS)
111 goto session_end;
112
113 /* Checking if the response length is too small or large */
114 if (response_length < sizeof(*response_desc) || response_length > response_max_length)
115 goto session_end;
116
117 /* Checking if the response data frames have the expected length */
118 if (!calculate_size(sizeof(*response_desc), response_desc->response_frame_count,
119 &response_frames_length, &response_max_length))
120 goto session_end;
121
122 if (response_length != response_max_length)
123 goto session_end;
124
125 psa_status = service_status;
126
127 if (psa_status == PSA_SUCCESS) {
128 memcpy(response_frames, response_desc->response_frames, response_frames_length);
129 *response_frame_count = response_desc->response_frame_count;
130 } else {
131 *response_frame_count = 0;
132 }
133
134session_end:
135 rpc_status = rpc_caller_session_end(handle);
136 if (psa_status == PSA_SUCCESS && rpc_status != RPC_SUCCESS)
137 psa_status = PSA_ERROR_GENERIC_ERROR;
138
139out:
140 return psa_status;
141}
142
143struct rpmb_backend *rpmb_client_init(struct rpmb_client *context,
144 struct rpc_caller_session *session)
145{
146 static const struct rpmb_backend_interface interface = {
147 rpmb_client_get_dev_info,
148 rpmb_client_data_request
149 };
150
151 if (!context || !session)
152 return NULL;
153
154 context->backend.context = context;
155 context->backend.interface = &interface;
156 context->session = session;
157
158 return &context->backend;
159}
160
161void rpmb_client_deinit(struct rpmb_client *context)
162{
163 (void)context;
164}