1 // SPDX-License-Identifier: GPL-2.0-or-later << 2 /* 1 /* 3 * Shared crypto simd helpers 2 * Shared crypto simd helpers 4 * 3 * 5 * Copyright (c) 2012 Jussi Kivilinna <jussi.k 4 * Copyright (c) 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi> 6 * Copyright (c) 2016 Herbert Xu <herbert@gond 5 * Copyright (c) 2016 Herbert Xu <herbert@gondor.apana.org.au> 7 * Copyright (c) 2019 Google LLC << 8 * 6 * 9 * Based on aesni-intel_glue.c by: 7 * Based on aesni-intel_glue.c by: 10 * Copyright (C) 2008, Intel Corp. 8 * Copyright (C) 2008, Intel Corp. 11 * Author: Huang Ying <ying.huang@intel.com 9 * Author: Huang Ying <ying.huang@intel.com> 12 */ << 13 << 14 /* << 15 * Shared crypto SIMD helpers. These function << 16 * an skcipher or AEAD algorithm that wraps an << 17 * wrapper ensures that the internal algorithm << 18 * where SIMD instructions are usable, i.e. wh << 19 * If SIMD is already usable, the wrapper dire << 20 * Otherwise it defers execution to a workqueu << 21 * 10 * 22 * This is an alternative to the internal algo !! 11 * This program is free software; you can redistribute it and/or modify 23 * the !may_use_simd() case itself. !! 12 * it under the terms of the GNU General Public License as published by >> 13 * the Free Software Foundation; either version 2 of the License, or >> 14 * (at your option) any later version. >> 15 * >> 16 * This program is distributed in the hope that it will be useful, >> 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of >> 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> 19 * GNU General Public License for more details. >> 20 * >> 21 * You should have received a copy of the GNU General Public License >> 22 * along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * 23 * 25 * Note that the wrapper algorithm is asynchro << 26 * CRYPTO_ALG_ASYNC flag set. Therefore it wo << 27 * explicitly allocate a synchronous algorithm << 28 */ 24 */ 29 25 30 #include <crypto/cryptd.h> 26 #include <crypto/cryptd.h> 31 #include <crypto/internal/aead.h> << 32 #include <crypto/internal/simd.h> 27 #include <crypto/internal/simd.h> 33 #include <crypto/internal/skcipher.h> 28 #include <crypto/internal/skcipher.h> 34 #include <linux/kernel.h> 29 #include <linux/kernel.h> 35 #include <linux/module.h> 30 #include <linux/module.h> 36 #include <linux/preempt.h> 31 #include <linux/preempt.h> 37 #include <asm/simd.h> 32 #include <asm/simd.h> 38 33 39 /* skcipher support */ << 40 << 41 struct simd_skcipher_alg { 34 struct simd_skcipher_alg { 42 const char *ialg_name; 35 const char *ialg_name; 43 struct skcipher_alg alg; 36 struct skcipher_alg alg; 44 }; 37 }; 45 38 46 struct simd_skcipher_ctx { 39 struct simd_skcipher_ctx { 47 struct cryptd_skcipher *cryptd_tfm; 40 struct cryptd_skcipher *cryptd_tfm; 48 }; 41 }; 49 42 50 static int simd_skcipher_setkey(struct crypto_ 43 static int simd_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, 51 unsigned int k 44 unsigned int key_len) 52 { 45 { 53 struct simd_skcipher_ctx *ctx = crypto 46 struct simd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm); 54 struct crypto_skcipher *child = &ctx-> 47 struct crypto_skcipher *child = &ctx->cryptd_tfm->base; >> 48 int err; 55 49 56 crypto_skcipher_clear_flags(child, CRY 50 crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); 57 crypto_skcipher_set_flags(child, crypt 51 crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(tfm) & 58 CRYPT 52 CRYPTO_TFM_REQ_MASK); 59 return crypto_skcipher_setkey(child, k !! 53 err = crypto_skcipher_setkey(child, key, key_len); >> 54 crypto_skcipher_set_flags(tfm, crypto_skcipher_get_flags(child) & >> 55 CRYPTO_TFM_RES_MASK); >> 56 return err; 60 } 57 } 61 58 62 static int simd_skcipher_encrypt(struct skciph 59 static int simd_skcipher_encrypt(struct skcipher_request *req) 63 { 60 { 64 struct crypto_skcipher *tfm = crypto_s 61 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 65 struct simd_skcipher_ctx *ctx = crypto 62 struct simd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm); 66 struct skcipher_request *subreq; 63 struct skcipher_request *subreq; 67 struct crypto_skcipher *child; 64 struct crypto_skcipher *child; 68 65 69 subreq = skcipher_request_ctx(req); 66 subreq = skcipher_request_ctx(req); 70 *subreq = *req; 67 *subreq = *req; 71 68 72 if (!crypto_simd_usable() || !! 69 if (!may_use_simd() || 73 (in_atomic() && cryptd_skcipher_qu 70 (in_atomic() && cryptd_skcipher_queued(ctx->cryptd_tfm))) 74 child = &ctx->cryptd_tfm->base 71 child = &ctx->cryptd_tfm->base; 75 else 72 else 76 child = cryptd_skcipher_child( 73 child = cryptd_skcipher_child(ctx->cryptd_tfm); 77 74 78 skcipher_request_set_tfm(subreq, child 75 skcipher_request_set_tfm(subreq, child); 79 76 80 return crypto_skcipher_encrypt(subreq) 77 return crypto_skcipher_encrypt(subreq); 81 } 78 } 82 79 83 static int simd_skcipher_decrypt(struct skciph 80 static int simd_skcipher_decrypt(struct skcipher_request *req) 84 { 81 { 85 struct crypto_skcipher *tfm = crypto_s 82 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 86 struct simd_skcipher_ctx *ctx = crypto 83 struct simd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm); 87 struct skcipher_request *subreq; 84 struct skcipher_request *subreq; 88 struct crypto_skcipher *child; 85 struct crypto_skcipher *child; 89 86 90 subreq = skcipher_request_ctx(req); 87 subreq = skcipher_request_ctx(req); 91 *subreq = *req; 88 *subreq = *req; 92 89 93 if (!crypto_simd_usable() || !! 90 if (!may_use_simd() || 94 (in_atomic() && cryptd_skcipher_qu 91 (in_atomic() && cryptd_skcipher_queued(ctx->cryptd_tfm))) 95 child = &ctx->cryptd_tfm->base 92 child = &ctx->cryptd_tfm->base; 96 else 93 else 97 child = cryptd_skcipher_child( 94 child = cryptd_skcipher_child(ctx->cryptd_tfm); 98 95 99 skcipher_request_set_tfm(subreq, child 96 skcipher_request_set_tfm(subreq, child); 100 97 101 return crypto_skcipher_decrypt(subreq) 98 return crypto_skcipher_decrypt(subreq); 102 } 99 } 103 100 104 static void simd_skcipher_exit(struct crypto_s 101 static void simd_skcipher_exit(struct crypto_skcipher *tfm) 105 { 102 { 106 struct simd_skcipher_ctx *ctx = crypto 103 struct simd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm); 107 104 108 cryptd_free_skcipher(ctx->cryptd_tfm); 105 cryptd_free_skcipher(ctx->cryptd_tfm); 109 } 106 } 110 107 111 static int simd_skcipher_init(struct crypto_sk 108 static int simd_skcipher_init(struct crypto_skcipher *tfm) 112 { 109 { 113 struct simd_skcipher_ctx *ctx = crypto 110 struct simd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm); 114 struct cryptd_skcipher *cryptd_tfm; 111 struct cryptd_skcipher *cryptd_tfm; 115 struct simd_skcipher_alg *salg; 112 struct simd_skcipher_alg *salg; 116 struct skcipher_alg *alg; 113 struct skcipher_alg *alg; 117 unsigned reqsize; 114 unsigned reqsize; 118 115 119 alg = crypto_skcipher_alg(tfm); 116 alg = crypto_skcipher_alg(tfm); 120 salg = container_of(alg, struct simd_s 117 salg = container_of(alg, struct simd_skcipher_alg, alg); 121 118 122 cryptd_tfm = cryptd_alloc_skcipher(sal 119 cryptd_tfm = cryptd_alloc_skcipher(salg->ialg_name, 123 CRY 120 CRYPTO_ALG_INTERNAL, 124 CRY 121 CRYPTO_ALG_INTERNAL); 125 if (IS_ERR(cryptd_tfm)) 122 if (IS_ERR(cryptd_tfm)) 126 return PTR_ERR(cryptd_tfm); 123 return PTR_ERR(cryptd_tfm); 127 124 128 ctx->cryptd_tfm = cryptd_tfm; 125 ctx->cryptd_tfm = cryptd_tfm; 129 126 130 reqsize = crypto_skcipher_reqsize(cryp !! 127 reqsize = sizeof(struct skcipher_request); 131 reqsize = max(reqsize, crypto_skcipher !! 128 reqsize += crypto_skcipher_reqsize(&cryptd_tfm->base); 132 reqsize += sizeof(struct skcipher_requ << 133 129 134 crypto_skcipher_set_reqsize(tfm, reqsi 130 crypto_skcipher_set_reqsize(tfm, reqsize); 135 131 136 return 0; 132 return 0; 137 } 133 } 138 134 139 struct simd_skcipher_alg *simd_skcipher_create !! 135 struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname, 140 << 141 136 const char *drvname, 142 137 const char *basename) 143 { 138 { 144 struct simd_skcipher_alg *salg; 139 struct simd_skcipher_alg *salg; >> 140 struct crypto_skcipher *tfm; >> 141 struct skcipher_alg *ialg; 145 struct skcipher_alg *alg; 142 struct skcipher_alg *alg; 146 int err; 143 int err; 147 144 >> 145 tfm = crypto_alloc_skcipher(basename, CRYPTO_ALG_INTERNAL, >> 146 CRYPTO_ALG_INTERNAL | CRYPTO_ALG_ASYNC); >> 147 if (IS_ERR(tfm)) >> 148 return ERR_CAST(tfm); >> 149 >> 150 ialg = crypto_skcipher_alg(tfm); >> 151 148 salg = kzalloc(sizeof(*salg), GFP_KERN 152 salg = kzalloc(sizeof(*salg), GFP_KERNEL); 149 if (!salg) { 153 if (!salg) { 150 salg = ERR_PTR(-ENOMEM); 154 salg = ERR_PTR(-ENOMEM); 151 goto out; !! 155 goto out_put_tfm; 152 } 156 } 153 157 154 salg->ialg_name = basename; 158 salg->ialg_name = basename; 155 alg = &salg->alg; 159 alg = &salg->alg; 156 160 157 err = -ENAMETOOLONG; 161 err = -ENAMETOOLONG; 158 if (snprintf(alg->base.cra_name, CRYPT 162 if (snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", algname) >= 159 CRYPTO_MAX_ALG_NAME) 163 CRYPTO_MAX_ALG_NAME) 160 goto out_free_salg; 164 goto out_free_salg; 161 165 162 if (snprintf(alg->base.cra_driver_name 166 if (snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", 163 drvname) >= CRYPTO_MAX_AL 167 drvname) >= CRYPTO_MAX_ALG_NAME) 164 goto out_free_salg; 168 goto out_free_salg; 165 169 166 alg->base.cra_flags = CRYPTO_ALG_ASYNC !! 170 alg->base.cra_flags = CRYPTO_ALG_ASYNC; 167 (ialg->base.cra_flags & CRYPTO << 168 alg->base.cra_priority = ialg->base.cr 171 alg->base.cra_priority = ialg->base.cra_priority; 169 alg->base.cra_blocksize = ialg->base.c 172 alg->base.cra_blocksize = ialg->base.cra_blocksize; 170 alg->base.cra_alignmask = ialg->base.c 173 alg->base.cra_alignmask = ialg->base.cra_alignmask; 171 alg->base.cra_module = ialg->base.cra_ 174 alg->base.cra_module = ialg->base.cra_module; 172 alg->base.cra_ctxsize = sizeof(struct 175 alg->base.cra_ctxsize = sizeof(struct simd_skcipher_ctx); 173 176 174 alg->ivsize = ialg->ivsize; 177 alg->ivsize = ialg->ivsize; 175 alg->chunksize = ialg->chunksize; 178 alg->chunksize = ialg->chunksize; 176 alg->min_keysize = ialg->min_keysize; 179 alg->min_keysize = ialg->min_keysize; 177 alg->max_keysize = ialg->max_keysize; 180 alg->max_keysize = ialg->max_keysize; 178 181 179 alg->init = simd_skcipher_init; 182 alg->init = simd_skcipher_init; 180 alg->exit = simd_skcipher_exit; 183 alg->exit = simd_skcipher_exit; 181 184 182 alg->setkey = simd_skcipher_setkey; 185 alg->setkey = simd_skcipher_setkey; 183 alg->encrypt = simd_skcipher_encrypt; 186 alg->encrypt = simd_skcipher_encrypt; 184 alg->decrypt = simd_skcipher_decrypt; 187 alg->decrypt = simd_skcipher_decrypt; 185 188 186 err = crypto_register_skcipher(alg); 189 err = crypto_register_skcipher(alg); 187 if (err) 190 if (err) 188 goto out_free_salg; 191 goto out_free_salg; 189 192 190 out: !! 193 out_put_tfm: >> 194 crypto_free_skcipher(tfm); 191 return salg; 195 return salg; 192 196 193 out_free_salg: 197 out_free_salg: 194 kfree(salg); 198 kfree(salg); 195 salg = ERR_PTR(err); 199 salg = ERR_PTR(err); 196 goto out; !! 200 goto out_put_tfm; 197 } 201 } 198 EXPORT_SYMBOL_GPL(simd_skcipher_create_compat) 202 EXPORT_SYMBOL_GPL(simd_skcipher_create_compat); 199 203 >> 204 struct simd_skcipher_alg *simd_skcipher_create(const char *algname, >> 205 const char *basename) >> 206 { >> 207 char drvname[CRYPTO_MAX_ALG_NAME]; >> 208 >> 209 if (snprintf(drvname, CRYPTO_MAX_ALG_NAME, "simd-%s", basename) >= >> 210 CRYPTO_MAX_ALG_NAME) >> 211 return ERR_PTR(-ENAMETOOLONG); >> 212 >> 213 return simd_skcipher_create_compat(algname, drvname, basename); >> 214 } >> 215 EXPORT_SYMBOL_GPL(simd_skcipher_create); >> 216 200 void simd_skcipher_free(struct simd_skcipher_a 217 void simd_skcipher_free(struct simd_skcipher_alg *salg) 201 { 218 { 202 crypto_unregister_skcipher(&salg->alg) 219 crypto_unregister_skcipher(&salg->alg); 203 kfree(salg); 220 kfree(salg); 204 } 221 } 205 EXPORT_SYMBOL_GPL(simd_skcipher_free); 222 EXPORT_SYMBOL_GPL(simd_skcipher_free); 206 223 207 int simd_register_skciphers_compat(struct skci 224 int simd_register_skciphers_compat(struct skcipher_alg *algs, int count, 208 struct simd 225 struct simd_skcipher_alg **simd_algs) 209 { 226 { 210 int err; 227 int err; 211 int i; 228 int i; 212 const char *algname; 229 const char *algname; 213 const char *drvname; 230 const char *drvname; 214 const char *basename; 231 const char *basename; 215 struct simd_skcipher_alg *simd; 232 struct simd_skcipher_alg *simd; 216 233 217 err = crypto_register_skciphers(algs, 234 err = crypto_register_skciphers(algs, count); 218 if (err) 235 if (err) 219 return err; 236 return err; 220 237 221 for (i = 0; i < count; i++) { 238 for (i = 0; i < count; i++) { 222 WARN_ON(strncmp(algs[i].base.c 239 WARN_ON(strncmp(algs[i].base.cra_name, "__", 2)); 223 WARN_ON(strncmp(algs[i].base.c 240 WARN_ON(strncmp(algs[i].base.cra_driver_name, "__", 2)); 224 algname = algs[i].base.cra_nam 241 algname = algs[i].base.cra_name + 2; 225 drvname = algs[i].base.cra_dri 242 drvname = algs[i].base.cra_driver_name + 2; 226 basename = algs[i].base.cra_dr 243 basename = algs[i].base.cra_driver_name; 227 simd = simd_skcipher_create_co !! 244 simd = simd_skcipher_create_compat(algname, drvname, basename); 228 err = PTR_ERR(simd); 245 err = PTR_ERR(simd); 229 if (IS_ERR(simd)) 246 if (IS_ERR(simd)) 230 goto err_unregister; 247 goto err_unregister; 231 simd_algs[i] = simd; 248 simd_algs[i] = simd; 232 } 249 } 233 return 0; 250 return 0; 234 251 235 err_unregister: 252 err_unregister: 236 simd_unregister_skciphers(algs, count, 253 simd_unregister_skciphers(algs, count, simd_algs); 237 return err; 254 return err; 238 } 255 } 239 EXPORT_SYMBOL_GPL(simd_register_skciphers_comp 256 EXPORT_SYMBOL_GPL(simd_register_skciphers_compat); 240 257 241 void simd_unregister_skciphers(struct skcipher 258 void simd_unregister_skciphers(struct skcipher_alg *algs, int count, 242 struct simd_skc 259 struct simd_skcipher_alg **simd_algs) 243 { 260 { 244 int i; 261 int i; 245 262 246 crypto_unregister_skciphers(algs, coun 263 crypto_unregister_skciphers(algs, count); 247 264 248 for (i = 0; i < count; i++) { 265 for (i = 0; i < count; i++) { 249 if (simd_algs[i]) { 266 if (simd_algs[i]) { 250 simd_skcipher_free(sim 267 simd_skcipher_free(simd_algs[i]); 251 simd_algs[i] = NULL; 268 simd_algs[i] = NULL; 252 } 269 } 253 } 270 } 254 } 271 } 255 EXPORT_SYMBOL_GPL(simd_unregister_skciphers); 272 EXPORT_SYMBOL_GPL(simd_unregister_skciphers); 256 273 257 /* AEAD support */ << 258 << 259 struct simd_aead_alg { << 260 const char *ialg_name; << 261 struct aead_alg alg; << 262 }; << 263 << 264 struct simd_aead_ctx { << 265 struct cryptd_aead *cryptd_tfm; << 266 }; << 267 << 268 static int simd_aead_setkey(struct crypto_aead << 269 unsigned int k << 270 { << 271 struct simd_aead_ctx *ctx = crypto_aea << 272 struct crypto_aead *child = &ctx->cryp << 273 << 274 crypto_aead_clear_flags(child, CRYPTO_ << 275 crypto_aead_set_flags(child, crypto_ae << 276 CRYPTO_TF << 277 return crypto_aead_setkey(child, key, << 278 } << 279 << 280 static int simd_aead_setauthsize(struct crypto << 281 { << 282 struct simd_aead_ctx *ctx = crypto_aea << 283 struct crypto_aead *child = &ctx->cryp << 284 << 285 return crypto_aead_setauthsize(child, << 286 } << 287 << 288 static int simd_aead_encrypt(struct aead_reque << 289 { << 290 struct crypto_aead *tfm = crypto_aead_ << 291 struct simd_aead_ctx *ctx = crypto_aea << 292 struct aead_request *subreq; << 293 struct crypto_aead *child; << 294 << 295 subreq = aead_request_ctx(req); << 296 *subreq = *req; << 297 << 298 if (!crypto_simd_usable() || << 299 (in_atomic() && cryptd_aead_queued << 300 child = &ctx->cryptd_tfm->base << 301 else << 302 child = cryptd_aead_child(ctx- << 303 << 304 aead_request_set_tfm(subreq, child); << 305 << 306 return crypto_aead_encrypt(subreq); << 307 } << 308 << 309 static int simd_aead_decrypt(struct aead_reque << 310 { << 311 struct crypto_aead *tfm = crypto_aead_ << 312 struct simd_aead_ctx *ctx = crypto_aea << 313 struct aead_request *subreq; << 314 struct crypto_aead *child; << 315 << 316 subreq = aead_request_ctx(req); << 317 *subreq = *req; << 318 << 319 if (!crypto_simd_usable() || << 320 (in_atomic() && cryptd_aead_queued << 321 child = &ctx->cryptd_tfm->base << 322 else << 323 child = cryptd_aead_child(ctx- << 324 << 325 aead_request_set_tfm(subreq, child); << 326 << 327 return crypto_aead_decrypt(subreq); << 328 } << 329 << 330 static void simd_aead_exit(struct crypto_aead << 331 { << 332 struct simd_aead_ctx *ctx = crypto_aea << 333 << 334 cryptd_free_aead(ctx->cryptd_tfm); << 335 } << 336 << 337 static int simd_aead_init(struct crypto_aead * << 338 { << 339 struct simd_aead_ctx *ctx = crypto_aea << 340 struct cryptd_aead *cryptd_tfm; << 341 struct simd_aead_alg *salg; << 342 struct aead_alg *alg; << 343 unsigned reqsize; << 344 << 345 alg = crypto_aead_alg(tfm); << 346 salg = container_of(alg, struct simd_a << 347 << 348 cryptd_tfm = cryptd_alloc_aead(salg->i << 349 CRYPTO_ << 350 if (IS_ERR(cryptd_tfm)) << 351 return PTR_ERR(cryptd_tfm); << 352 << 353 ctx->cryptd_tfm = cryptd_tfm; << 354 << 355 reqsize = crypto_aead_reqsize(cryptd_a << 356 reqsize = max(reqsize, crypto_aead_req << 357 reqsize += sizeof(struct aead_request) << 358 << 359 crypto_aead_set_reqsize(tfm, reqsize); << 360 << 361 return 0; << 362 } << 363 << 364 static struct simd_aead_alg *simd_aead_create_ << 365 << 366 << 367 << 368 { << 369 struct simd_aead_alg *salg; << 370 struct aead_alg *alg; << 371 int err; << 372 << 373 salg = kzalloc(sizeof(*salg), GFP_KERN << 374 if (!salg) { << 375 salg = ERR_PTR(-ENOMEM); << 376 goto out; << 377 } << 378 << 379 salg->ialg_name = basename; << 380 alg = &salg->alg; << 381 << 382 err = -ENAMETOOLONG; << 383 if (snprintf(alg->base.cra_name, CRYPT << 384 CRYPTO_MAX_ALG_NAME) << 385 goto out_free_salg; << 386 << 387 if (snprintf(alg->base.cra_driver_name << 388 drvname) >= CRYPTO_MAX_AL << 389 goto out_free_salg; << 390 << 391 alg->base.cra_flags = CRYPTO_ALG_ASYNC << 392 (ialg->base.cra_flags & CRYPTO << 393 alg->base.cra_priority = ialg->base.cr << 394 alg->base.cra_blocksize = ialg->base.c << 395 alg->base.cra_alignmask = ialg->base.c << 396 alg->base.cra_module = ialg->base.cra_ << 397 alg->base.cra_ctxsize = sizeof(struct << 398 << 399 alg->ivsize = ialg->ivsize; << 400 alg->maxauthsize = ialg->maxauthsize; << 401 alg->chunksize = ialg->chunksize; << 402 << 403 alg->init = simd_aead_init; << 404 alg->exit = simd_aead_exit; << 405 << 406 alg->setkey = simd_aead_setkey; << 407 alg->setauthsize = simd_aead_setauthsi << 408 alg->encrypt = simd_aead_encrypt; << 409 alg->decrypt = simd_aead_decrypt; << 410 << 411 err = crypto_register_aead(alg); << 412 if (err) << 413 goto out_free_salg; << 414 << 415 out: << 416 return salg; << 417 << 418 out_free_salg: << 419 kfree(salg); << 420 salg = ERR_PTR(err); << 421 goto out; << 422 } << 423 << 424 static void simd_aead_free(struct simd_aead_al << 425 { << 426 crypto_unregister_aead(&salg->alg); << 427 kfree(salg); << 428 } << 429 << 430 int simd_register_aeads_compat(struct aead_alg << 431 struct simd_aea << 432 { << 433 int err; << 434 int i; << 435 const char *algname; << 436 const char *drvname; << 437 const char *basename; << 438 struct simd_aead_alg *simd; << 439 << 440 err = crypto_register_aeads(algs, coun << 441 if (err) << 442 return err; << 443 << 444 for (i = 0; i < count; i++) { << 445 WARN_ON(strncmp(algs[i].base.c << 446 WARN_ON(strncmp(algs[i].base.c << 447 algname = algs[i].base.cra_nam << 448 drvname = algs[i].base.cra_dri << 449 basename = algs[i].base.cra_dr << 450 simd = simd_aead_create_compat << 451 err = PTR_ERR(simd); << 452 if (IS_ERR(simd)) << 453 goto err_unregister; << 454 simd_algs[i] = simd; << 455 } << 456 return 0; << 457 << 458 err_unregister: << 459 simd_unregister_aeads(algs, count, sim << 460 return err; << 461 } << 462 EXPORT_SYMBOL_GPL(simd_register_aeads_compat); << 463 << 464 void simd_unregister_aeads(struct aead_alg *al << 465 struct simd_aead_al << 466 { << 467 int i; << 468 << 469 crypto_unregister_aeads(algs, count); << 470 << 471 for (i = 0; i < count; i++) { << 472 if (simd_algs[i]) { << 473 simd_aead_free(simd_al << 474 simd_algs[i] = NULL; << 475 } << 476 } << 477 } << 478 EXPORT_SYMBOL_GPL(simd_unregister_aeads); << 479 << 480 MODULE_DESCRIPTION("Shared crypto SIMD helpers << 481 MODULE_LICENSE("GPL"); 274 MODULE_LICENSE("GPL"); 482 275
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.