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