1 /*
2  * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h>
8 #include <service/locator/interface/service_locator.h>
9 #include <CppUTest/TestHarness.h>
10 
11 /*
12  * Security tests to check key store partition protects access to keys
13  */
TEST_GROUP(CryptoSecurityPartitioningTests)14 TEST_GROUP(CryptoSecurityPartitioningTests)
15 {
16 	void setup()
17 	{
18 		m_crypto_service_context = NULL;
19 		m_rpc_session_a = NULL;
20 		m_rpc_session_b = NULL;
21 		m_client_a = NULL;
22 		m_client_b = NULL;
23 
24 		service_locator_init();
25 
26 		m_crypto_service_context = service_locator_query("sn:trustedfirmware.org:crypto:0");
27 		CHECK_TRUE(m_crypto_service_context);
28 
29 		/*
30 		 * Open two RPC sessions, one for client a and the other for client b.
31 		 * Both have different client identities, assigned when the rpc session is opened.
32 		 */
33 		m_rpc_session_a = service_context_open(m_crypto_service_context);
34 		CHECK_TRUE(m_rpc_session_a);
35 		m_client_a = new packedc_crypto_client(m_rpc_session_a);
36 
37 		m_rpc_session_b = service_context_open(m_crypto_service_context);
38 		CHECK_TRUE(m_rpc_session_b);
39 		m_client_b = new packedc_crypto_client(m_rpc_session_b);
40 	}
41 
42 	void teardown()
43 	{
44 		delete m_client_a;
45 		m_client_a = NULL;
46 
47 		delete m_client_b;
48 		m_client_b = NULL;
49 
50 		if (m_crypto_service_context) {
51 			if (m_rpc_session_a) {
52 				service_context_close(m_crypto_service_context, m_rpc_session_a);
53 				m_rpc_session_a = NULL;
54 			}
55 
56 			if (m_rpc_session_b) {
57 				service_context_close(m_crypto_service_context, m_rpc_session_b);
58 				m_rpc_session_b = NULL;
59 			}
60 
61 			service_context_relinquish(m_crypto_service_context);
62 			m_crypto_service_context = NULL;
63 		}
64 	}
65 
66 	struct service_context *m_crypto_service_context;
67 	struct rpc_caller_session *m_rpc_session_a;
68 	struct rpc_caller_session *m_rpc_session_b;
69 	crypto_client *m_client_a;
70 	crypto_client *m_client_b;
71 };
72 
TEST(CryptoSecurityPartitioningTests,unauthorizedKeyDestroy)73 TEST(CryptoSecurityPartitioningTests, unauthorizedKeyDestroy)
74 {
75 	psa_status_t status = PSA_ERROR_GENERIC_ERROR;
76 	psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
77 
78 	psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
79 	psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
80 	psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
81 	psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
82 	psa_set_key_bits(&attributes, 256);
83 
84 	/* Generate a key in the context of client a */
85 	psa_key_id_t key_id = PSA_KEY_ID_NULL;
86 	status = m_client_a->generate_key(&attributes, &key_id);
87 	CHECK_EQUAL(PSA_SUCCESS, status);
88 
89 	/* Client b attempts to destroy it but shouldn't be permitted */
90 	status = m_client_b->destroy_key(key_id);
91 	CHECK_EQUAL(PSA_ERROR_INVALID_HANDLE, status);
92 
93 	/* Client a should be permitted */
94 	status = m_client_a->destroy_key(key_id);
95 	CHECK_EQUAL(PSA_SUCCESS, status);
96 
97 	psa_reset_key_attributes(&attributes);
98 }
99 
TEST(CryptoSecurityPartitioningTests,independentKeyIdSpace)100 TEST(CryptoSecurityPartitioningTests, independentKeyIdSpace)
101 {
102 	psa_status_t status = PSA_ERROR_GENERIC_ERROR;
103 	psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
104 
105 	psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
106 	psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
107 	psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
108 	psa_set_key_bits(&attributes, 256);
109 
110 	/*
111 	 * Use the same key id from both clients.  Expect clients to have
112 	 * independent key id spaces.
113 	 */
114 	psa_key_id_t common_key_id = 1111;
115 
116 	/* Client A generates key */
117 	psa_key_id_t key_id_a = PSA_KEY_ID_NULL;
118 	psa_set_key_id(&attributes, common_key_id);
119 	status = m_client_a->generate_key(&attributes, &key_id_a);
120 	CHECK_EQUAL(PSA_SUCCESS, status);
121 	CHECK_EQUAL(common_key_id, key_id_a);
122 
123 	/* Client B does the same using the same key_id */
124 	psa_key_id_t key_id_b = PSA_KEY_ID_NULL;
125 	psa_set_key_id(&attributes, common_key_id);
126 	status = m_client_b->generate_key(&attributes, &key_id_b);
127 	CHECK_EQUAL(PSA_SUCCESS, status);
128 	CHECK_EQUAL(common_key_id, key_id_b);
129 
130 	/* Expect both clients to have access to their own keys */
131 	status = m_client_a->destroy_key(key_id_a);
132 	CHECK_EQUAL(PSA_SUCCESS, status);
133 	status = m_client_b->destroy_key(key_id_b);
134 	CHECK_EQUAL(PSA_SUCCESS, status);
135 
136 	psa_reset_key_attributes(&attributes);
137 }
138