1 /*
2 * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <psa/error.h>
8 #include <psa/lifecycle.h>
9 #include <qcbor/qcbor_spiffy_decode.h>
10 #include <t_cose/t_cose_sign1_verify.h>
11 #include <service/attestation/claims/claims_register.h>
12 #include <service/attestation/claims/sources/event_log/event_log_claim_source.h>
13 #include <service/attestation/claims/sources/event_log/mock/mock_event_log.h>
14 #include <service/attestation/claims/sources/boot_seed_generator/boot_seed_generator.h>
15 #include <service/attestation/claims/sources/null_lifecycle/null_lifecycle_claim_source.h>
16 #include <service/attestation/claims/sources/instance_id/instance_id_claim_source.h>
17 #include <service/attestation/reporter/attest_report.h>
18 #include <service/attestation/reporter/dump/raw/raw_report_dump.h>
19 #include <service/attestation/key_mngr/attest_key_mngr.h>
20 #include <service/attestation/key_mngr/local/local_attest_key_mngr.h>
21 #include <protocols/service/attestation/packed-c/eat.h>
22 #include <service/crypto/client/psa/psa_crypto_client.h>
23 #include <service_locator.h>
24 #include <CppUTest/TestHarness.h>
25
26
TEST_GROUP(AttestationReporterTests)27 TEST_GROUP(AttestationReporterTests)
28 {
29 void setup()
30 {
31 struct claim_source *claim_source;
32
33 report = NULL;
34 report_len = 0;
35
36 open_crypto_session();
37 local_attest_key_mngr_init(LOCAL_ATTEST_KEY_MNGR_VOLATILE_IAK);
38
39 /* The set of registered claim_sources determines the content
40 * of a generated attestation source. The set and type of
41 * claim_sources registered will be deployment specific.
42 */
43 claims_register_init();
44
45 /* Boot measurement claim source */
46 claim_source = event_log_claim_source_init(&event_log_claim_source,
47 mock_event_log_start(), mock_event_log_size());
48 claims_register_add_claim_source(CLAIM_CATEGORY_BOOT_MEASUREMENT, claim_source);
49
50 /* Boot seed claim source */
51 claim_source = boot_seed_generator_init(&boot_seed_claim_source);
52 claims_register_add_claim_source(CLAIM_CATEGORY_DEVICE, claim_source);
53
54 /* Lifecycle state claim source */
55 claim_source = null_lifecycle_claim_source_init(&lifecycle_claim_source);
56 claims_register_add_claim_source(CLAIM_CATEGORY_DEVICE, claim_source);
57
58 /* Instance ID claim source */
59 claim_source = instance_id_claim_source_init(&instance_id_claim_source);
60 claims_register_add_claim_source(CLAIM_CATEGORY_DEVICE, claim_source);
61 }
62
63 void teardown()
64 {
65 attest_report_destroy(report);
66 claims_register_deinit();
67 local_attest_key_mngr_deinit();
68 close_crypto_session();
69 }
70
71 void open_crypto_session()
72 {
73 m_crypto_service_context = service_locator_query("sn:trustedfirmware.org:crypto:0");
74 if (m_crypto_service_context) {
75 m_crypto_session = service_context_open(m_crypto_service_context);
76 if (m_crypto_session) {
77 psa_crypto_client_init(m_crypto_session);
78 psa_crypto_init();
79 }
80 }
81 }
82
83 void close_crypto_session()
84 {
85 psa_crypto_client_deinit();
86
87 if (m_crypto_service_context && m_crypto_session) {
88 service_context_close(m_crypto_service_context, m_crypto_session);
89 m_crypto_session = NULL;
90
91 service_context_relinquish(m_crypto_service_context);
92 m_crypto_service_context = NULL;
93 }
94 }
95
96 struct service_context *m_crypto_service_context;
97 struct rpc_caller_session *m_crypto_session;
98 struct event_log_claim_source event_log_claim_source;
99 struct boot_seed_generator boot_seed_claim_source;
100 struct null_lifecycle_claim_source lifecycle_claim_source;
101 struct instance_id_claim_source instance_id_claim_source;
102 const uint8_t *report;
103 size_t report_len;
104 };
105
TEST(AttestationReporterTests,createReport)106 TEST(AttestationReporterTests, createReport)
107 {
108 int status;
109
110 /* Client inputs */
111 int32_t client_id = 0x552791aa;
112 const uint8_t auth_challenge[] = {
113 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,
114 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32
115 };
116
117 /* Retrieve the IAK id */
118 psa_key_id_t iak_id;
119 status = attest_key_mngr_get_iak_id(&iak_id);
120 LONGS_EQUAL(PSA_SUCCESS, status);
121
122 /* Create a report */
123 status = attest_report_create(client_id,
124 auth_challenge, sizeof(auth_challenge),
125 &report, &report_len);
126
127 /* Expect the operation to succeed and a non-zero length
128 * report created.
129 */
130 LONGS_EQUAL(PSA_SUCCESS, status);
131 CHECK_TRUE(report);
132 CHECK_TRUE(report_len);
133
134 /* Verify the signature */
135 struct t_cose_sign1_verify_ctx verify_ctx;
136 struct t_cose_key key_pair;
137
138 key_pair.k.key_handle = iak_id;
139 key_pair.crypto_lib = T_COSE_CRYPTO_LIB_PSA;
140 UsefulBufC signed_cose;
141 UsefulBufC report_body;
142
143 signed_cose.ptr = report;
144 signed_cose.len = report_len;
145
146 t_cose_sign1_verify_init(&verify_ctx, 0);
147 t_cose_sign1_set_verification_key(&verify_ctx, key_pair);
148
149 status = t_cose_sign1_verify(&verify_ctx, signed_cose, &report_body, NULL);
150 LONGS_EQUAL(T_COSE_SUCCESS, status);
151
152 /* Check the report contents */
153 QCBORDecodeContext decode_ctx;
154
155 QCBORDecode_Init(&decode_ctx, report_body, QCBOR_DECODE_MODE_NORMAL);
156 QCBORDecode_EnterMap(&decode_ctx, NULL);
157
158 /* Check client id */
159 int64_t decoded_client_id = 0;
160 QCBORDecode_GetInt64InMapN(&decode_ctx,
161 EAT_ARM_PSA_CLAIM_ID_CLIENT_ID, &decoded_client_id);
162
163 LONGS_EQUAL(QCBOR_SUCCESS, QCBORDecode_GetError(&decode_ctx));
164 LONGS_EQUAL(client_id, decoded_client_id);
165
166 /* Check the auth challenge */
167 UsefulBufC auth_challenge_buf;
168 auth_challenge_buf.ptr = NULL;
169 auth_challenge_buf.len = 0;
170 QCBORDecode_GetByteStringInMapN(&decode_ctx,
171 EAT_ARM_PSA_CLAIM_ID_CHALLENGE, &auth_challenge_buf);
172
173 LONGS_EQUAL(QCBOR_SUCCESS, QCBORDecode_GetError(&decode_ctx));
174 CHECK_TRUE(auth_challenge_buf.ptr);
175 UNSIGNED_LONGS_EQUAL(sizeof(auth_challenge), auth_challenge_buf.len);
176 MEMCMP_EQUAL(auth_challenge, auth_challenge_buf.ptr, sizeof(auth_challenge));
177
178 /* Check the boot seed */
179 UsefulBufC boot_seed_buf;
180 boot_seed_buf.ptr = NULL;
181 boot_seed_buf.len = 0;
182 QCBORDecode_GetByteStringInMapN(&decode_ctx,
183 EAT_ARM_PSA_CLAIM_ID_BOOT_SEED, &boot_seed_buf);
184
185 LONGS_EQUAL(QCBOR_SUCCESS, QCBORDecode_GetError(&decode_ctx));
186 CHECK_TRUE(boot_seed_buf.ptr);
187 UNSIGNED_LONGS_EQUAL(sizeof(boot_seed_claim_source.boot_seed), boot_seed_buf.len);
188
189 /* Check the lifecycle state */
190 int64_t decoded_lifecycle_state = 0;
191 QCBORDecode_GetInt64InMapN(&decode_ctx,
192 EAT_ARM_PSA_CLAIM_ID_SECURITY_LIFECYCLE, &decoded_lifecycle_state);
193
194 LONGS_EQUAL(QCBOR_SUCCESS, QCBORDecode_GetError(&decode_ctx));
195 LONGS_EQUAL(PSA_LIFECYCLE_UNKNOWN, decoded_lifecycle_state);
196
197 /* Check the instance ID */
198 UsefulBufC instance_id_buf;
199 instance_id_buf.ptr = NULL;
200 instance_id_buf.len = 0;
201 QCBORDecode_GetByteStringInMapN(&decode_ctx,
202 EAT_ARM_PSA_CLAIM_ID_INSTANCE_ID, &instance_id_buf);
203
204 LONGS_EQUAL(QCBOR_SUCCESS, QCBORDecode_GetError(&decode_ctx));
205 CHECK_TRUE(instance_id_buf.ptr);
206 UNSIGNED_LONGS_EQUAL(sizeof(instance_id_claim_source.instance_id), instance_id_buf.len);
207
208 /* Shouldn't expect to see the 'NO_SW_COMPONENTS' claim */
209 int64_t no_sw = 0;
210 QCBORDecode_GetInt64InMapN(&decode_ctx, EAT_ARM_PSA_CLAIM_ID_NO_SW_COMPONENTS, &no_sw);
211 LONGS_EQUAL(QCBOR_ERR_LABEL_NOT_FOUND, QCBORDecode_GetAndResetError(&decode_ctx));
212 CHECK_FALSE(no_sw);
213
214 /* Check the sw components */
215 QCBORDecode_EnterArrayFromMapN(&decode_ctx, EAT_ARM_PSA_CLAIM_ID_SW_COMPONENTS);
216 LONGS_EQUAL(QCBOR_SUCCESS, QCBORDecode_GetError(&decode_ctx));
217
218 /* Iterate over all array members */
219 size_t sw_component_count = 0;
220 while (true) {
221
222 QCBORDecode_EnterMap(&decode_ctx, NULL);
223
224 if (QCBORDecode_GetAndResetError(&decode_ctx) == QCBOR_SUCCESS) {
225
226 CHECK_TRUE(sw_component_count < mock_event_Log_measurement_count());
227
228 UsefulBufC property;
229 const struct mock_event_log_measurement *measurement =
230 mock_event_Log_measurement(sw_component_count);
231
232 /* Check measurement id */
233 QCBORDecode_GetTextStringInMapN(&decode_ctx,
234 EAT_SW_COMPONENT_CLAIM_ID_MEASUREMENT_TYPE, &property);
235 LONGS_EQUAL(QCBOR_SUCCESS, QCBORDecode_GetError(&decode_ctx));
236 CHECK_TRUE(property.ptr);
237 CHECK_TRUE(property.len);
238 MEMCMP_EQUAL(measurement->id, property.ptr, property.len);
239
240 /* Check measurement digest */
241 QCBORDecode_GetByteStringInMapN(&decode_ctx,
242 EAT_SW_COMPONENT_CLAIM_ID_MEASUREMENT_VALUE, &property);
243 LONGS_EQUAL(QCBOR_SUCCESS, QCBORDecode_GetError(&decode_ctx));
244 CHECK_TRUE(property.ptr);
245 CHECK_TRUE(property.len);
246 MEMCMP_EQUAL(measurement->digest, property.ptr, property.len);
247
248 QCBORDecode_ExitMap(&decode_ctx);
249
250 ++sw_component_count;
251 }
252 else {
253 /* No more sw components */
254 break;
255 }
256 }
257
258 QCBORDecode_ExitArray(&decode_ctx);
259 LONGS_EQUAL(QCBOR_SUCCESS, QCBORDecode_GetError(&decode_ctx));
260
261 QCBORError qcbor_error;
262 QCBORDecode_ExitMap(&decode_ctx);
263 qcbor_error = QCBORDecode_Finish(&decode_ctx);
264 LONGS_EQUAL(QCBOR_SUCCESS, qcbor_error);
265 }
266