TF-M Reference Manual  1.2.0
TrustedFirmware-M
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tfm_attest_req_mngr.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <string.h>
10 #include "psa/crypto.h"
11 #include "attest.h"
12 
13 #ifdef TFM_PSA_API
15 #include "psa/client.h"
16 #include "psa/service.h"
17 #include "region_defs.h"
18 
19 #define ECC_P256_PUBLIC_KEY_SIZE PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(256)
20 #define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0]))
21 
22 typedef psa_status_t (*attest_func_t)(const psa_msg_t *msg);
23 
24 int32_t g_attest_caller_id;
25 
26 static psa_status_t psa_attest_get_token(const psa_msg_t *msg)
27 {
28  psa_status_t status = PSA_SUCCESS;
29  uint8_t challenge_buff[PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64];
30  uint8_t token_buff[PSA_INITIAL_ATTEST_TOKEN_MAX_SIZE];
31  uint32_t bytes_read = 0;
32  size_t challenge_size = msg->in_size[0];
33  size_t token_size = msg->out_size[0];
34  psa_invec in_vec[] = {
35  {challenge_buff, challenge_size}
36  };
37  psa_outvec out_vec[] = {
38  {token_buff, sizeof(token_buff)}
39  };
40 
41  if (challenge_size > PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64) {
43  }
44  if (token_size < sizeof(token_buff)) {
45  out_vec[0].len = token_size;
46  }
47  /* store the client ID here for later use in service */
48  g_attest_caller_id = msg->client_id;
49 
50  bytes_read = psa_read(msg->handle, 0,
51  challenge_buff, challenge_size);
52  if (bytes_read != challenge_size) {
54  }
55 
56  status = initial_attest_get_token(in_vec, IOVEC_LEN(in_vec),
57  out_vec, IOVEC_LEN(out_vec));
58  if (status == PSA_SUCCESS) {
59  psa_write(msg->handle, 0, out_vec[0].base, out_vec[0].len);
60  }
61 
62  return status;
63 }
64 
65 static psa_status_t psa_attest_get_token_size(const psa_msg_t *msg)
66 {
67  psa_status_t status = PSA_SUCCESS;
68  size_t challenge_size;
69  size_t token_size;
70  size_t bytes_read = 0;
71  psa_invec in_vec[] = {
72  {&challenge_size, msg->in_size[0]}
73  };
74  psa_outvec out_vec[] = {
75  {&token_size, msg->out_size[0]}
76  };
77 
78  if (msg->in_size[0] != sizeof(challenge_size)
79  || msg->out_size[0] != sizeof(token_size)) {
81  }
82 
83  /* store the client ID here for later use in service */
84  g_attest_caller_id = msg->client_id;
85 
86  bytes_read = psa_read(msg->handle, 0,
87  &challenge_size, msg->in_size[0]);
88  if (bytes_read != msg->in_size[0]) {
90  }
91 
92  status = initial_attest_get_token_size(in_vec, IOVEC_LEN(in_vec),
93  out_vec, IOVEC_LEN(out_vec));
94  if (status == PSA_SUCCESS) {
95  psa_write(msg->handle, 0, out_vec[0].base, out_vec[0].len);
96  }
97 
98  return status;
99 }
100 
101 static psa_status_t tfm_attest_get_public_key(const psa_msg_t *msg)
102 {
103  psa_status_t status = PSA_SUCCESS;
104  uint8_t key_buf[ECC_P256_PUBLIC_KEY_SIZE];
105  size_t key_len;
106  psa_ecc_family_t curve_type;
107 
108  psa_outvec out_vec[] = {
109  {.base = key_buf, .len = sizeof(key_buf)},
110  {.base = &curve_type, .len = sizeof(curve_type)},
111  {.base = &key_len, .len = sizeof(key_len)}
112  };
113 
114  if (msg->out_size[1] != out_vec[1].len ||
115  msg->out_size[2] != out_vec[2].len) {
117  }
118 
119  /* Store the client ID here for later use in service. */
120  g_attest_caller_id = msg->client_id;
121 
122  status = initial_attest_get_public_key(NULL, 0,
123  out_vec, IOVEC_LEN(out_vec));
124 
125  if (msg->out_size[0] < key_len) {
127  }
128 
129  if (status == PSA_SUCCESS) {
130  psa_write(msg->handle, 0, key_buf, key_len);
131  psa_write(msg->handle, 1, &curve_type, out_vec[1].len);
132  psa_write(msg->handle, 2, &key_len, out_vec[2].len);
133  }
134 
135  return status;
136 }
137 
138 /*
139  * Fixme: Temporarily implement abort as infinite loop,
140  * will replace it later.
141  */
142 static void tfm_abort(void)
143 {
144  while (1)
145  ;
146 }
147 
148 static void attest_signal_handle(psa_signal_t signal, attest_func_t pfn)
149 {
150  psa_msg_t msg;
151  psa_status_t status;
152 
153  status = psa_get(signal, &msg);
154  switch (msg.type) {
155  case PSA_IPC_CONNECT:
157  break;
158  case PSA_IPC_CALL:
159  status = (psa_status_t)pfn(&msg);
160  psa_reply(msg.handle, status);
161  break;
162  case PSA_IPC_DISCONNECT:
164  break;
165  default:
166  tfm_abort();
167  }
168 }
169 #endif
170 
172 {
173  psa_status_t err = attest_init();
174 #ifdef TFM_PSA_API
175  psa_signal_t signals;
176 
177  if (err != PSA_SUCCESS) {
178  tfm_abort();
179  }
180 
181  while (1) {
182  signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
183  if (signals & TFM_ATTEST_GET_TOKEN_SIGNAL) {
184  attest_signal_handle(TFM_ATTEST_GET_TOKEN_SIGNAL,
185  psa_attest_get_token);
186  } else if (signals & TFM_ATTEST_GET_TOKEN_SIZE_SIGNAL) {
187  attest_signal_handle(TFM_ATTEST_GET_TOKEN_SIZE_SIGNAL,
188  psa_attest_get_token_size);
189  } else if (signals & TFM_ATTEST_GET_PUBLIC_KEY_SIGNAL) {
190  attest_signal_handle(TFM_ATTEST_GET_PUBLIC_KEY_SIGNAL,
191  tfm_attest_get_public_key);
192  } else {
193  tfm_abort();
194  }
195  }
196 #else
197  return err;
198 #endif
199 }
psa_status_t initial_attest_get_token_size(const psa_invec *in_vec, uint32_t num_invec, psa_outvec *out_vec, uint32_t num_outvec)
Get the size of the initial attestation token.
Definition: attest_core.c:869
#define TFM_ATTEST_GET_PUBLIC_KEY_SIGNAL
uint32_t psa_signal_t
Definition: service.h:50
void * base
Definition: client.h:75
#define PSA_BLOCK
Definition: service.h:31
int32_t type
Definition: service.h:56
#define PSA_SUCCESS
Definition: crypto_values.h:35
#define PSA_ERROR_BUFFER_TOO_SMALL
Definition: crypto_values.h:77
Platform Security Architecture cryptography module.
#define ECC_P256_PUBLIC_KEY_SIZE
#define IOVEC_LEN(x)
psa_status_t initial_attest_get_public_key(const psa_invec *in_vec, uint32_t num_invec, psa_outvec *out_vec, uint32_t num_outvec)
Get the initial attestation public key.
Definition: attest_core.c:922
int32_t client_id
Definition: service.h:64
size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx, void *buffer, size_t num_bytes)
Read a message parameter or part of a message parameter from a client input vector.
Definition: psa_service.c:40
psa_status_t initial_attest_get_token(const psa_invec *in_vec, uint32_t num_invec, psa_outvec *out_vec, uint32_t num_outvec)
Get initial attestation token.
Definition: attest_core.c:833
psa_handle_t handle
Definition: service.h:61
#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64
#define PSA_ERROR_GENERIC_ERROR
Definition: crypto_values.h:43
#define PSA_ERROR_INVALID_ARGUMENT
psa_status_t attest_partition_init(void)
#define PSA_IPC_DISCONNECT
Definition: service.h:47
#define PSA_WAIT_ANY
Definition: service.h:36
size_t in_size[PSA_MAX_IOVEC]
Definition: service.h:70
void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx, const void *buffer, size_t num_bytes)
Write a message response to a client output vector.
Definition: psa_service.c:58
void psa_reply(psa_handle_t msg_handle, psa_status_t status)
Complete handling of a specific message and unblock the client.
Definition: psa_service.c:67
psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout)
Return the Secure Partition interrupt signals that have been asserted from a subset of signals provid...
Definition: psa_service.c:15
size_t len
Definition: client.h:76
#define TFM_ATTEST_GET_TOKEN_SIGNAL
#define PSA_IPC_CONNECT
Definition: service.h:45
#define TFM_ATTEST_GET_TOKEN_SIZE_SIGNAL
psa_status_t attest_init(void)
Initialise the initial attestation service during the TF-M boot up process.
Definition: attest_core.c:99
size_t out_size[PSA_MAX_IOVEC]
Definition: service.h:73
#define PSA_IPC_CALL
Definition: client.h:59
uint8_t psa_ecc_family_t
Definition: crypto_types.h:69
psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg)
Retrieve the message which corresponds to a given RoT Service signal and remove the message from the ...
Definition: psa_service.c:24
int32_t psa_status_t
Function return status.
Definition: crypto_types.h:43