1 /*
2  * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef CRYPTO_CONTEXT_POOL_H
8 #define CRYPTO_CONTEXT_POOL_H
9 
10 #include <stdint.h>
11 #include <service/crypto/backend/crypto_backend.h>
12 
13 /**
14  * Some crypto transactions require state to be held between separate
15  * service operations.  A typical multi-call transaction such as a
16  * hash calculation comprises a setup, one or more updates and a finish
17  * operation.  This pool is used for allocating state context for multi-call
18  * transactions.  For a well behaved client, a fresh context is allocated
19  * on a setup and freed on the finish.  To cope with badly behaved clients
20  * that may never finish a transaction, if no free contexts are available
21  * for a new transaction, the least recently used active context is
22  * recycled.
23  */
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 /**
30  *  Identifier for the operation type that a context is used for.
31  */
32 enum crypto_context_op_id
33 {
34 	CRYPTO_CONTEXT_OP_ID_NONE,
35 	CRYPTO_CONTEXT_OP_ID_HASH,
36 	CRYPTO_CONTEXT_OP_ID_MAC,
37 	CRYPTO_CONTEXT_OP_ID_CIPHER,
38 	CRYPTO_CONTEXT_OP_ID_AEAD,
39 	CRYPTO_CONTEXT_OP_ID_KEY_DERIVATION
40 };
41 
42 /**
43  * A crypto context, used to hold state for a multi-step transaction.
44  */
45 struct crypto_context
46 {
47 	enum crypto_context_op_id usage;
48 	uint32_t client_id;
49 	uint32_t op_handle;
50 	struct crypto_context *next;
51 	struct crypto_context *prev;
52 
53 	union context_variant
54 	{
55 		psa_hash_operation_t hash;
56 		psa_mac_operation_t mac;
57 		psa_cipher_operation_t cipher;
58 		psa_aead_operation_t aead;
59 		psa_key_derivation_operation_t key_derivation;
60 	} op;
61 };
62 
63 /**
64  * The default pool size.  This may be overridden to meet the needs
65  * of a particular deployment.
66  */
67 #ifndef CRYPTO_CONTEXT_POOL_SIZE
68 #define CRYPTO_CONTEXT_POOL_SIZE            (10)
69 #endif
70 
71 /**
72  * The crypto context pool structure.
73  */
74 struct crypto_context_pool
75 {
76 	struct crypto_context contexts[CRYPTO_CONTEXT_POOL_SIZE];
77 	struct crypto_context *free;
78 	struct crypto_context *active_head;
79 	struct crypto_context *active_tail;
80 	uint32_t most_recent_op_handle;
81 };
82 
83 /*
84  * Initializes a crypto_context_pool, called once during setup.
85  */
86 void crypto_context_pool_init(struct crypto_context_pool *pool);
87 
88 /*
89  * De-initializes a crypto_context_pool, called once during tear-down.
90  */
91 void crypto_context_pool_deinit(struct crypto_context_pool *pool);
92 
93 /*
94  * Allocate a fresh context.  On success, a pointer to a crypto_context object
95  * is returned and an op handle is provided for reacqiring the context during
96  * sunsequent operations.
97  */
98 struct crypto_context *crypto_context_pool_alloc(struct crypto_context_pool *pool,
99 	enum crypto_context_op_id usage,
100 	uint32_t client_id,
101 	uint32_t *op_handle);
102 
103 /*
104  * Frees a context after use.
105  */
106 void crypto_context_pool_free(struct crypto_context_pool *pool,
107 	struct crypto_context *context);
108 
109 /*
110  * Find an allocated context.  Returns NULL is no qualifying context is held.
111  */
112 struct crypto_context *crypto_context_pool_find(struct crypto_context_pool *pool,
113 	enum crypto_context_op_id usage,
114 	uint32_t client_id,
115 	uint32_t op_handle);
116 
117 
118 #ifdef __cplusplus
119 } /* extern "C" */
120 #endif
121 
122 #endif /* CRYPTO_CONTEXT_POOL_H */
123