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