blob: c2bb03542d072dd17e64dc7fbdf78cb3c5238e7e [file] [log] [blame]
Julian Hall700aa362021-05-13 15:30:39 +01001/*
2 * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <stddef.h>
8#include <string.h>
9#include "iat_client.h"
10#include <common/tlv/tlv.h>
11#include <psa/initial_attestation.h>
12#include <protocols/service/attestation/packed-c/get_token.h>
13#include <protocols/service/attestation/packed-c/get_token_size.h>
14#include <protocols/service/attestation/packed-c/opcodes.h>
15#include <protocols/rpc/common/packed-c/status.h>
16
17/**
18 * @brief The singleton psa_iat_client instance
19 *
20 * The psa attestation C API assumes a single backend service provider. This
21 * structure defines the state used by the psa_iat_client that communicates
22 * with a remote provider using the provided rpc caller.
23 */
24static struct psa_iat_client
25{
26 struct rpc_caller *caller;
27 int rpc_status;
28} instance;
29
30
31psa_status_t psa_iat_client_init(struct rpc_caller *caller)
32{
33 instance.caller = caller;
34 instance.rpc_status = TS_RPC_CALL_ACCEPTED;
35
36 return PSA_SUCCESS;
37}
38
39void psa_iat_client_deinit(void)
40{
41 instance.caller = NULL;
42}
43
44int psa_iat_client_rpc_status(void)
45{
46 return instance.rpc_status;
47}
48
49psa_status_t psa_initial_attest_get_token(
50 const uint8_t *auth_challenge, size_t challenge_size,
51 uint8_t *token_buf, size_t token_buf_size, size_t *token_size)
52{
53 psa_status_t psa_status = PSA_ERROR_INVALID_ARGUMENT;
54 size_t req_len = tlv_required_space(challenge_size);
55
Julian Hallb7db5802021-07-26 16:20:40 +010056 if (!token_buf || !token_buf_size) return PSA_ERROR_INVALID_ARGUMENT;
57
Julian Hall700aa362021-05-13 15:30:39 +010058 struct tlv_record challenge_record;
59 challenge_record.tag = TS_ATTESTATION_GET_TOKEN_IN_TAG_AUTH_CHALLENGE;
60 challenge_record.length = challenge_size;
61 challenge_record.value = auth_challenge;
62
63 rpc_call_handle call_handle;
64 uint8_t *req_buf;
65
66 *token_size = 0;
67
68 call_handle = rpc_caller_begin(instance.caller, &req_buf, req_len);
69
70 if (call_handle) {
71
72 uint8_t *resp_buf;
73 size_t resp_len;
74 int opstatus;
75 struct tlv_iterator req_iter;
76
77 tlv_iterator_begin(&req_iter, req_buf, req_len);
78 tlv_encode(&req_iter, &challenge_record);
79
80 instance.rpc_status = rpc_caller_invoke(instance.caller, call_handle,
81 TS_ATTESTATION_OPCODE_GET_TOKEN, &opstatus, &resp_buf, &resp_len);
82
83 if (instance.rpc_status == TS_RPC_CALL_ACCEPTED) {
84
85 psa_status = opstatus;
86
87 if (psa_status == PSA_SUCCESS) {
88
89 struct tlv_const_iterator resp_iter;
90 struct tlv_record decoded_record;
91 tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len);
92
93 if (tlv_find_decode(&resp_iter,
94 TS_ATTESTATION_GET_TOKEN_OUT_TAG_TOKEN, &decoded_record)) {
95
96 if (decoded_record.length <= token_buf_size) {
97
98 memcpy(token_buf, decoded_record.value, decoded_record.length);
99 *token_size = decoded_record.length;
100 }
101 else {
102 /* Provided buffer is too small */
103 psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
104 }
105 }
106 else {
107 /* Mandatory response parameter missing */
108 psa_status = PSA_ERROR_GENERIC_ERROR;
109 }
110 }
111 }
112
113 rpc_caller_end(instance.caller, call_handle);
114 }
115
116 return psa_status;
117}
118
119psa_status_t psa_initial_attest_get_token_size(
120 size_t challenge_size, size_t *token_size)
121{
122 psa_status_t psa_status = PSA_ERROR_INVALID_ARGUMENT;
123 struct ts_attestation_get_token_size_in req_msg;
124 size_t req_len = sizeof(struct ts_attestation_get_token_size_in);
125
126 *token_size = 0; /* For failure case */
127
128 req_msg.challenge_size = challenge_size;
129
130 rpc_call_handle call_handle;
131 uint8_t *req_buf;
132
133 call_handle = rpc_caller_begin(instance.caller, &req_buf, req_len);
134
135 if (call_handle) {
136
137 uint8_t *resp_buf;
138 size_t resp_len;
139 int opstatus;
140 struct tlv_iterator req_iter;
141
142 memcpy(req_buf, &req_msg, req_len);
143
144 instance.rpc_status = rpc_caller_invoke(instance.caller, call_handle,
145 TS_ATTESTATION_OPCODE_GET_TOKEN_SIZE, &opstatus, &resp_buf, &resp_len);
146
147 if (instance.rpc_status == TS_RPC_CALL_ACCEPTED) {
148
149 psa_status = opstatus;
150
151 if (psa_status == PSA_SUCCESS) {
152
153 if (resp_len >= sizeof(struct ts_attestation_get_token_size_out)) {
154
155 struct ts_attestation_get_token_size_out resp_msg;
156 memcpy(&resp_msg, resp_buf, sizeof(struct ts_attestation_get_token_size_out));
157 *token_size = resp_msg.token_size;
158 }
159 else {
160 /* Failed to decode response message */
161 psa_status = PSA_ERROR_GENERIC_ERROR;
162 }
163 }
164 }
165
166 rpc_caller_end(instance.caller, call_handle);
167 }
168
169 return psa_status;
170}