1*38c8a9a5SSteve French // SPDX-License-Identifier: GPL-2.0-or-later
2*38c8a9a5SSteve French /*
3*38c8a9a5SSteve French * Copyright (C) 2019 Samsung Electronics Co., Ltd.
4*38c8a9a5SSteve French */
5*38c8a9a5SSteve French
6*38c8a9a5SSteve French #include <linux/kernel.h>
7*38c8a9a5SSteve French #include <linux/string.h>
8*38c8a9a5SSteve French #include <linux/err.h>
9*38c8a9a5SSteve French #include <linux/slab.h>
10*38c8a9a5SSteve French #include <linux/wait.h>
11*38c8a9a5SSteve French #include <linux/sched.h>
12*38c8a9a5SSteve French
13*38c8a9a5SSteve French #include "glob.h"
14*38c8a9a5SSteve French #include "crypto_ctx.h"
15*38c8a9a5SSteve French
16*38c8a9a5SSteve French struct crypto_ctx_list {
17*38c8a9a5SSteve French spinlock_t ctx_lock;
18*38c8a9a5SSteve French int avail_ctx;
19*38c8a9a5SSteve French struct list_head idle_ctx;
20*38c8a9a5SSteve French wait_queue_head_t ctx_wait;
21*38c8a9a5SSteve French };
22*38c8a9a5SSteve French
23*38c8a9a5SSteve French static struct crypto_ctx_list ctx_list;
24*38c8a9a5SSteve French
free_aead(struct crypto_aead * aead)25*38c8a9a5SSteve French static inline void free_aead(struct crypto_aead *aead)
26*38c8a9a5SSteve French {
27*38c8a9a5SSteve French if (aead)
28*38c8a9a5SSteve French crypto_free_aead(aead);
29*38c8a9a5SSteve French }
30*38c8a9a5SSteve French
free_shash(struct shash_desc * shash)31*38c8a9a5SSteve French static void free_shash(struct shash_desc *shash)
32*38c8a9a5SSteve French {
33*38c8a9a5SSteve French if (shash) {
34*38c8a9a5SSteve French crypto_free_shash(shash->tfm);
35*38c8a9a5SSteve French kfree(shash);
36*38c8a9a5SSteve French }
37*38c8a9a5SSteve French }
38*38c8a9a5SSteve French
alloc_aead(int id)39*38c8a9a5SSteve French static struct crypto_aead *alloc_aead(int id)
40*38c8a9a5SSteve French {
41*38c8a9a5SSteve French struct crypto_aead *tfm = NULL;
42*38c8a9a5SSteve French
43*38c8a9a5SSteve French switch (id) {
44*38c8a9a5SSteve French case CRYPTO_AEAD_AES_GCM:
45*38c8a9a5SSteve French tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
46*38c8a9a5SSteve French break;
47*38c8a9a5SSteve French case CRYPTO_AEAD_AES_CCM:
48*38c8a9a5SSteve French tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
49*38c8a9a5SSteve French break;
50*38c8a9a5SSteve French default:
51*38c8a9a5SSteve French pr_err("Does not support encrypt ahead(id : %d)\n", id);
52*38c8a9a5SSteve French return NULL;
53*38c8a9a5SSteve French }
54*38c8a9a5SSteve French
55*38c8a9a5SSteve French if (IS_ERR(tfm)) {
56*38c8a9a5SSteve French pr_err("Failed to alloc encrypt aead : %ld\n", PTR_ERR(tfm));
57*38c8a9a5SSteve French return NULL;
58*38c8a9a5SSteve French }
59*38c8a9a5SSteve French
60*38c8a9a5SSteve French return tfm;
61*38c8a9a5SSteve French }
62*38c8a9a5SSteve French
alloc_shash_desc(int id)63*38c8a9a5SSteve French static struct shash_desc *alloc_shash_desc(int id)
64*38c8a9a5SSteve French {
65*38c8a9a5SSteve French struct crypto_shash *tfm = NULL;
66*38c8a9a5SSteve French struct shash_desc *shash;
67*38c8a9a5SSteve French
68*38c8a9a5SSteve French switch (id) {
69*38c8a9a5SSteve French case CRYPTO_SHASH_HMACMD5:
70*38c8a9a5SSteve French tfm = crypto_alloc_shash("hmac(md5)", 0, 0);
71*38c8a9a5SSteve French break;
72*38c8a9a5SSteve French case CRYPTO_SHASH_HMACSHA256:
73*38c8a9a5SSteve French tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
74*38c8a9a5SSteve French break;
75*38c8a9a5SSteve French case CRYPTO_SHASH_CMACAES:
76*38c8a9a5SSteve French tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
77*38c8a9a5SSteve French break;
78*38c8a9a5SSteve French case CRYPTO_SHASH_SHA256:
79*38c8a9a5SSteve French tfm = crypto_alloc_shash("sha256", 0, 0);
80*38c8a9a5SSteve French break;
81*38c8a9a5SSteve French case CRYPTO_SHASH_SHA512:
82*38c8a9a5SSteve French tfm = crypto_alloc_shash("sha512", 0, 0);
83*38c8a9a5SSteve French break;
84*38c8a9a5SSteve French default:
85*38c8a9a5SSteve French return NULL;
86*38c8a9a5SSteve French }
87*38c8a9a5SSteve French
88*38c8a9a5SSteve French if (IS_ERR(tfm))
89*38c8a9a5SSteve French return NULL;
90*38c8a9a5SSteve French
91*38c8a9a5SSteve French shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
92*38c8a9a5SSteve French GFP_KERNEL);
93*38c8a9a5SSteve French if (!shash)
94*38c8a9a5SSteve French crypto_free_shash(tfm);
95*38c8a9a5SSteve French else
96*38c8a9a5SSteve French shash->tfm = tfm;
97*38c8a9a5SSteve French return shash;
98*38c8a9a5SSteve French }
99*38c8a9a5SSteve French
ctx_free(struct ksmbd_crypto_ctx * ctx)100*38c8a9a5SSteve French static void ctx_free(struct ksmbd_crypto_ctx *ctx)
101*38c8a9a5SSteve French {
102*38c8a9a5SSteve French int i;
103*38c8a9a5SSteve French
104*38c8a9a5SSteve French for (i = 0; i < CRYPTO_SHASH_MAX; i++)
105*38c8a9a5SSteve French free_shash(ctx->desc[i]);
106*38c8a9a5SSteve French for (i = 0; i < CRYPTO_AEAD_MAX; i++)
107*38c8a9a5SSteve French free_aead(ctx->ccmaes[i]);
108*38c8a9a5SSteve French kfree(ctx);
109*38c8a9a5SSteve French }
110*38c8a9a5SSteve French
ksmbd_find_crypto_ctx(void)111*38c8a9a5SSteve French static struct ksmbd_crypto_ctx *ksmbd_find_crypto_ctx(void)
112*38c8a9a5SSteve French {
113*38c8a9a5SSteve French struct ksmbd_crypto_ctx *ctx;
114*38c8a9a5SSteve French
115*38c8a9a5SSteve French while (1) {
116*38c8a9a5SSteve French spin_lock(&ctx_list.ctx_lock);
117*38c8a9a5SSteve French if (!list_empty(&ctx_list.idle_ctx)) {
118*38c8a9a5SSteve French ctx = list_entry(ctx_list.idle_ctx.next,
119*38c8a9a5SSteve French struct ksmbd_crypto_ctx,
120*38c8a9a5SSteve French list);
121*38c8a9a5SSteve French list_del(&ctx->list);
122*38c8a9a5SSteve French spin_unlock(&ctx_list.ctx_lock);
123*38c8a9a5SSteve French return ctx;
124*38c8a9a5SSteve French }
125*38c8a9a5SSteve French
126*38c8a9a5SSteve French if (ctx_list.avail_ctx > num_online_cpus()) {
127*38c8a9a5SSteve French spin_unlock(&ctx_list.ctx_lock);
128*38c8a9a5SSteve French wait_event(ctx_list.ctx_wait,
129*38c8a9a5SSteve French !list_empty(&ctx_list.idle_ctx));
130*38c8a9a5SSteve French continue;
131*38c8a9a5SSteve French }
132*38c8a9a5SSteve French
133*38c8a9a5SSteve French ctx_list.avail_ctx++;
134*38c8a9a5SSteve French spin_unlock(&ctx_list.ctx_lock);
135*38c8a9a5SSteve French
136*38c8a9a5SSteve French ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), GFP_KERNEL);
137*38c8a9a5SSteve French if (!ctx) {
138*38c8a9a5SSteve French spin_lock(&ctx_list.ctx_lock);
139*38c8a9a5SSteve French ctx_list.avail_ctx--;
140*38c8a9a5SSteve French spin_unlock(&ctx_list.ctx_lock);
141*38c8a9a5SSteve French wait_event(ctx_list.ctx_wait,
142*38c8a9a5SSteve French !list_empty(&ctx_list.idle_ctx));
143*38c8a9a5SSteve French continue;
144*38c8a9a5SSteve French }
145*38c8a9a5SSteve French break;
146*38c8a9a5SSteve French }
147*38c8a9a5SSteve French return ctx;
148*38c8a9a5SSteve French }
149*38c8a9a5SSteve French
ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx * ctx)150*38c8a9a5SSteve French void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx)
151*38c8a9a5SSteve French {
152*38c8a9a5SSteve French if (!ctx)
153*38c8a9a5SSteve French return;
154*38c8a9a5SSteve French
155*38c8a9a5SSteve French spin_lock(&ctx_list.ctx_lock);
156*38c8a9a5SSteve French if (ctx_list.avail_ctx <= num_online_cpus()) {
157*38c8a9a5SSteve French list_add(&ctx->list, &ctx_list.idle_ctx);
158*38c8a9a5SSteve French spin_unlock(&ctx_list.ctx_lock);
159*38c8a9a5SSteve French wake_up(&ctx_list.ctx_wait);
160*38c8a9a5SSteve French return;
161*38c8a9a5SSteve French }
162*38c8a9a5SSteve French
163*38c8a9a5SSteve French ctx_list.avail_ctx--;
164*38c8a9a5SSteve French spin_unlock(&ctx_list.ctx_lock);
165*38c8a9a5SSteve French ctx_free(ctx);
166*38c8a9a5SSteve French }
167*38c8a9a5SSteve French
____crypto_shash_ctx_find(int id)168*38c8a9a5SSteve French static struct ksmbd_crypto_ctx *____crypto_shash_ctx_find(int id)
169*38c8a9a5SSteve French {
170*38c8a9a5SSteve French struct ksmbd_crypto_ctx *ctx;
171*38c8a9a5SSteve French
172*38c8a9a5SSteve French if (id >= CRYPTO_SHASH_MAX)
173*38c8a9a5SSteve French return NULL;
174*38c8a9a5SSteve French
175*38c8a9a5SSteve French ctx = ksmbd_find_crypto_ctx();
176*38c8a9a5SSteve French if (ctx->desc[id])
177*38c8a9a5SSteve French return ctx;
178*38c8a9a5SSteve French
179*38c8a9a5SSteve French ctx->desc[id] = alloc_shash_desc(id);
180*38c8a9a5SSteve French if (ctx->desc[id])
181*38c8a9a5SSteve French return ctx;
182*38c8a9a5SSteve French ksmbd_release_crypto_ctx(ctx);
183*38c8a9a5SSteve French return NULL;
184*38c8a9a5SSteve French }
185*38c8a9a5SSteve French
ksmbd_crypto_ctx_find_hmacmd5(void)186*38c8a9a5SSteve French struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacmd5(void)
187*38c8a9a5SSteve French {
188*38c8a9a5SSteve French return ____crypto_shash_ctx_find(CRYPTO_SHASH_HMACMD5);
189*38c8a9a5SSteve French }
190*38c8a9a5SSteve French
ksmbd_crypto_ctx_find_hmacsha256(void)191*38c8a9a5SSteve French struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void)
192*38c8a9a5SSteve French {
193*38c8a9a5SSteve French return ____crypto_shash_ctx_find(CRYPTO_SHASH_HMACSHA256);
194*38c8a9a5SSteve French }
195*38c8a9a5SSteve French
ksmbd_crypto_ctx_find_cmacaes(void)196*38c8a9a5SSteve French struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void)
197*38c8a9a5SSteve French {
198*38c8a9a5SSteve French return ____crypto_shash_ctx_find(CRYPTO_SHASH_CMACAES);
199*38c8a9a5SSteve French }
200*38c8a9a5SSteve French
ksmbd_crypto_ctx_find_sha256(void)201*38c8a9a5SSteve French struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha256(void)
202*38c8a9a5SSteve French {
203*38c8a9a5SSteve French return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA256);
204*38c8a9a5SSteve French }
205*38c8a9a5SSteve French
ksmbd_crypto_ctx_find_sha512(void)206*38c8a9a5SSteve French struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void)
207*38c8a9a5SSteve French {
208*38c8a9a5SSteve French return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA512);
209*38c8a9a5SSteve French }
210*38c8a9a5SSteve French
____crypto_aead_ctx_find(int id)211*38c8a9a5SSteve French static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id)
212*38c8a9a5SSteve French {
213*38c8a9a5SSteve French struct ksmbd_crypto_ctx *ctx;
214*38c8a9a5SSteve French
215*38c8a9a5SSteve French if (id >= CRYPTO_AEAD_MAX)
216*38c8a9a5SSteve French return NULL;
217*38c8a9a5SSteve French
218*38c8a9a5SSteve French ctx = ksmbd_find_crypto_ctx();
219*38c8a9a5SSteve French if (ctx->ccmaes[id])
220*38c8a9a5SSteve French return ctx;
221*38c8a9a5SSteve French
222*38c8a9a5SSteve French ctx->ccmaes[id] = alloc_aead(id);
223*38c8a9a5SSteve French if (ctx->ccmaes[id])
224*38c8a9a5SSteve French return ctx;
225*38c8a9a5SSteve French ksmbd_release_crypto_ctx(ctx);
226*38c8a9a5SSteve French return NULL;
227*38c8a9a5SSteve French }
228*38c8a9a5SSteve French
ksmbd_crypto_ctx_find_gcm(void)229*38c8a9a5SSteve French struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void)
230*38c8a9a5SSteve French {
231*38c8a9a5SSteve French return ____crypto_aead_ctx_find(CRYPTO_AEAD_AES_GCM);
232*38c8a9a5SSteve French }
233*38c8a9a5SSteve French
ksmbd_crypto_ctx_find_ccm(void)234*38c8a9a5SSteve French struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void)
235*38c8a9a5SSteve French {
236*38c8a9a5SSteve French return ____crypto_aead_ctx_find(CRYPTO_AEAD_AES_CCM);
237*38c8a9a5SSteve French }
238*38c8a9a5SSteve French
ksmbd_crypto_destroy(void)239*38c8a9a5SSteve French void ksmbd_crypto_destroy(void)
240*38c8a9a5SSteve French {
241*38c8a9a5SSteve French struct ksmbd_crypto_ctx *ctx;
242*38c8a9a5SSteve French
243*38c8a9a5SSteve French while (!list_empty(&ctx_list.idle_ctx)) {
244*38c8a9a5SSteve French ctx = list_entry(ctx_list.idle_ctx.next,
245*38c8a9a5SSteve French struct ksmbd_crypto_ctx,
246*38c8a9a5SSteve French list);
247*38c8a9a5SSteve French list_del(&ctx->list);
248*38c8a9a5SSteve French ctx_free(ctx);
249*38c8a9a5SSteve French }
250*38c8a9a5SSteve French }
251*38c8a9a5SSteve French
ksmbd_crypto_create(void)252*38c8a9a5SSteve French int ksmbd_crypto_create(void)
253*38c8a9a5SSteve French {
254*38c8a9a5SSteve French struct ksmbd_crypto_ctx *ctx;
255*38c8a9a5SSteve French
256*38c8a9a5SSteve French spin_lock_init(&ctx_list.ctx_lock);
257*38c8a9a5SSteve French INIT_LIST_HEAD(&ctx_list.idle_ctx);
258*38c8a9a5SSteve French init_waitqueue_head(&ctx_list.ctx_wait);
259*38c8a9a5SSteve French ctx_list.avail_ctx = 1;
260*38c8a9a5SSteve French
261*38c8a9a5SSteve French ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), GFP_KERNEL);
262*38c8a9a5SSteve French if (!ctx)
263*38c8a9a5SSteve French return -ENOMEM;
264*38c8a9a5SSteve French list_add(&ctx->list, &ctx_list.idle_ctx);
265*38c8a9a5SSteve French return 0;
266*38c8a9a5SSteve French }
267