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