1 /*
2  * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <stdlib.h>
8 #include <service/crypto/provider/crypto_context_pool.h>
9 #include <CppUTest/TestHarness.h>
10 
11 /*
12  * Component tests for the crypto_context_pool.
13  */
TEST_GROUP(CryptoContextPoolTests)14 TEST_GROUP(CryptoContextPoolTests)
15 {
16 	void setup()
17 	{
18 		crypto_context_pool_init(&pool_under_test);
19 	}
20 
21 	void teardown()
22 	{
23 		crypto_context_pool_deinit(&pool_under_test);
24 	}
25 
26 	struct crypto_context_pool pool_under_test;
27 };
28 
TEST(CryptoContextPoolTests,checkEmptyPool)29 TEST(CryptoContextPoolTests, checkEmptyPool)
30 {
31 	struct crypto_context *context =
32 		crypto_context_pool_find(&pool_under_test, CRYPTO_CONTEXT_OP_ID_HASH, 0, 0);
33 
34 	/* Expect a freshly initialized pool to fail to find a context */
35 	CHECK_FALSE(context);
36 }
37 
TEST(CryptoContextPoolTests,singleContext)38 TEST(CryptoContextPoolTests, singleContext)
39 {
40 	uint32_t op_handle;
41 	uint32_t client_id = 22;
42 
43 	struct crypto_context *initial_context =
44 		crypto_context_pool_alloc(&pool_under_test,
45 			CRYPTO_CONTEXT_OP_ID_HASH, client_id,
46 			&op_handle);
47 
48 	CHECK_TRUE(initial_context);
49 
50 	struct crypto_context *follow_on_context =
51 		crypto_context_pool_find(&pool_under_test,
52 		CRYPTO_CONTEXT_OP_ID_HASH, client_id,
53 		op_handle);
54 
55 	UNSIGNED_LONGS_EQUAL(initial_context, follow_on_context);
56 
57 	crypto_context_pool_free(&pool_under_test, initial_context);
58 }
59 
TEST(CryptoContextPoolTests,multipleContexts)60 TEST(CryptoContextPoolTests, multipleContexts)
61 {
62 	/* Test multiple concurrent contexts but never exceeding the pool size */
63 	struct crypto_context *context;
64 	uint32_t zombie_handle_1, zombie_handle_2;
65 
66 	/* First start a couple of zombie contexts.  This will occur if a client
67 	 * starts a transaction but never finishes it.  This could happen due to a
68 	 * misbehaving client or if a client process crashes.  This checks that
69 	 * recycling of least recently used contexts is working.
70 	 */
71 	context = crypto_context_pool_alloc(&pool_under_test,
72 				CRYPTO_CONTEXT_OP_ID_MAC, 77,
73 				&zombie_handle_1);
74 	CHECK_TRUE(context);
75 
76 	context = crypto_context_pool_alloc(&pool_under_test,
77 				CRYPTO_CONTEXT_OP_ID_CIPHER, 88,
78 				&zombie_handle_2);
79 	CHECK_TRUE(context);
80 
81 	/* Now run through the normal life-cycle for a load of concurrent contexts */
82 	for (unsigned int i = 0; i < 1000; ++i) {
83 
84 		uint32_t op_handles[CRYPTO_CONTEXT_POOL_SIZE];
85 		unsigned int num_concurrent = (rand() % CRYPTO_CONTEXT_POOL_SIZE) + 1;
86 
87 		/* Start some concurrent contexts, each belonging to different clients */
88 		for (unsigned int context_index = 0; context_index < num_concurrent; ++context_index) {
89 
90 			context = crypto_context_pool_alloc(&pool_under_test,
91 				CRYPTO_CONTEXT_OP_ID_HASH, context_index,
92 				&op_handles[context_index]);
93 
94 			CHECK_TRUE(context);
95 		}
96 
97 		/* Expect the find to work for all active contexts */
98 		for (unsigned int context_index = 0; context_index < num_concurrent; ++context_index) {
99 
100 			context = crypto_context_pool_find(&pool_under_test,
101 				CRYPTO_CONTEXT_OP_ID_HASH, context_index,
102 				op_handles[context_index]);
103 
104 			CHECK_TRUE(context);
105 		}
106 
107 		/* Then find and free all contexts */
108 		for (unsigned int context_index = 0; context_index < num_concurrent; ++context_index) {
109 
110 			context = crypto_context_pool_find(&pool_under_test,
111 				CRYPTO_CONTEXT_OP_ID_HASH, context_index,
112 				op_handles[context_index]);
113 
114 			CHECK_TRUE(context);
115 
116 			crypto_context_pool_free(&pool_under_test, context);
117 		}
118 	}
119 
120 	/* Expect the zombie contexts to have been recycled */
121 	context = crypto_context_pool_find(&pool_under_test,
122 				CRYPTO_CONTEXT_OP_ID_MAC, 77,
123 				zombie_handle_1);
124 	CHECK_FALSE(context);
125 
126 	context = crypto_context_pool_find(&pool_under_test,
127 				CRYPTO_CONTEXT_OP_ID_CIPHER, 88,
128 				zombie_handle_2);
129 	CHECK_FALSE(context);
130 }
131