xref: /openbmc/linux/fs/smb/server/crypto_ctx.c (revision 38c8a9a5)
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