Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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