2 * Shared crypto simd helpers
4 * Copyright (c) 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
5 * Copyright (c) 2016 Herbert Xu <herbert@gondor.apana.org.au>
7 * Based on aesni-intel_glue.c by:
8 * Copyright (C) 2008, Intel Corp.
9 * Author: Huang Ying <ying.huang@intel.com>
11 * This program is free software; you can redistribute it and/or modify
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.
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.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
28 #include <crypto/cryptd.h>
29 #include <crypto/internal/simd.h>
30 #include <crypto/internal/skcipher.h>
31 #include <linux/kernel.h>
32 #include <linux/module.h>
33 #include <linux/preempt.h>
36 struct simd_skcipher_alg
{
37 const char *ialg_name
;
38 struct skcipher_alg alg
;
41 struct simd_skcipher_ctx
{
42 struct cryptd_skcipher
*cryptd_tfm
;
45 static int simd_skcipher_setkey(struct crypto_skcipher
*tfm
, const u8
*key
,
48 struct simd_skcipher_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
49 struct crypto_skcipher
*child
= &ctx
->cryptd_tfm
->base
;
52 crypto_skcipher_clear_flags(child
, CRYPTO_TFM_REQ_MASK
);
53 crypto_skcipher_set_flags(child
, crypto_skcipher_get_flags(tfm
) &
55 err
= crypto_skcipher_setkey(child
, key
, key_len
);
56 crypto_skcipher_set_flags(tfm
, crypto_skcipher_get_flags(child
) &
61 static int simd_skcipher_encrypt(struct skcipher_request
*req
)
63 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
64 struct simd_skcipher_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
65 struct skcipher_request
*subreq
;
66 struct crypto_skcipher
*child
;
68 subreq
= skcipher_request_ctx(req
);
71 if (!may_use_simd() ||
72 (in_atomic() && cryptd_skcipher_queued(ctx
->cryptd_tfm
)))
73 child
= &ctx
->cryptd_tfm
->base
;
75 child
= cryptd_skcipher_child(ctx
->cryptd_tfm
);
77 skcipher_request_set_tfm(subreq
, child
);
79 return crypto_skcipher_encrypt(subreq
);
82 static int simd_skcipher_decrypt(struct skcipher_request
*req
)
84 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
85 struct simd_skcipher_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
86 struct skcipher_request
*subreq
;
87 struct crypto_skcipher
*child
;
89 subreq
= skcipher_request_ctx(req
);
92 if (!may_use_simd() ||
93 (in_atomic() && cryptd_skcipher_queued(ctx
->cryptd_tfm
)))
94 child
= &ctx
->cryptd_tfm
->base
;
96 child
= cryptd_skcipher_child(ctx
->cryptd_tfm
);
98 skcipher_request_set_tfm(subreq
, child
);
100 return crypto_skcipher_decrypt(subreq
);
103 static void simd_skcipher_exit(struct crypto_skcipher
*tfm
)
105 struct simd_skcipher_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
107 cryptd_free_skcipher(ctx
->cryptd_tfm
);
110 static int simd_skcipher_init(struct crypto_skcipher
*tfm
)
112 struct simd_skcipher_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
113 struct cryptd_skcipher
*cryptd_tfm
;
114 struct simd_skcipher_alg
*salg
;
115 struct skcipher_alg
*alg
;
118 alg
= crypto_skcipher_alg(tfm
);
119 salg
= container_of(alg
, struct simd_skcipher_alg
, alg
);
121 cryptd_tfm
= cryptd_alloc_skcipher(salg
->ialg_name
,
123 CRYPTO_ALG_INTERNAL
);
124 if (IS_ERR(cryptd_tfm
))
125 return PTR_ERR(cryptd_tfm
);
127 ctx
->cryptd_tfm
= cryptd_tfm
;
129 reqsize
= crypto_skcipher_reqsize(cryptd_skcipher_child(cryptd_tfm
));
130 reqsize
= max(reqsize
, crypto_skcipher_reqsize(&cryptd_tfm
->base
));
131 reqsize
+= sizeof(struct skcipher_request
);
133 crypto_skcipher_set_reqsize(tfm
, reqsize
);
138 struct simd_skcipher_alg
*simd_skcipher_create_compat(const char *algname
,
140 const char *basename
)
142 struct simd_skcipher_alg
*salg
;
143 struct crypto_skcipher
*tfm
;
144 struct skcipher_alg
*ialg
;
145 struct skcipher_alg
*alg
;
148 tfm
= crypto_alloc_skcipher(basename
, CRYPTO_ALG_INTERNAL
,
149 CRYPTO_ALG_INTERNAL
| CRYPTO_ALG_ASYNC
);
151 return ERR_CAST(tfm
);
153 ialg
= crypto_skcipher_alg(tfm
);
155 salg
= kzalloc(sizeof(*salg
), GFP_KERNEL
);
157 salg
= ERR_PTR(-ENOMEM
);
161 salg
->ialg_name
= basename
;
165 if (snprintf(alg
->base
.cra_name
, CRYPTO_MAX_ALG_NAME
, "%s", algname
) >=
169 if (snprintf(alg
->base
.cra_driver_name
, CRYPTO_MAX_ALG_NAME
, "%s",
170 drvname
) >= CRYPTO_MAX_ALG_NAME
)
173 alg
->base
.cra_flags
= CRYPTO_ALG_ASYNC
;
174 alg
->base
.cra_priority
= ialg
->base
.cra_priority
;
175 alg
->base
.cra_blocksize
= ialg
->base
.cra_blocksize
;
176 alg
->base
.cra_alignmask
= ialg
->base
.cra_alignmask
;
177 alg
->base
.cra_module
= ialg
->base
.cra_module
;
178 alg
->base
.cra_ctxsize
= sizeof(struct simd_skcipher_ctx
);
180 alg
->ivsize
= ialg
->ivsize
;
181 alg
->chunksize
= ialg
->chunksize
;
182 alg
->min_keysize
= ialg
->min_keysize
;
183 alg
->max_keysize
= ialg
->max_keysize
;
185 alg
->init
= simd_skcipher_init
;
186 alg
->exit
= simd_skcipher_exit
;
188 alg
->setkey
= simd_skcipher_setkey
;
189 alg
->encrypt
= simd_skcipher_encrypt
;
190 alg
->decrypt
= simd_skcipher_decrypt
;
192 err
= crypto_register_skcipher(alg
);
197 crypto_free_skcipher(tfm
);
205 EXPORT_SYMBOL_GPL(simd_skcipher_create_compat
);
207 struct simd_skcipher_alg
*simd_skcipher_create(const char *algname
,
208 const char *basename
)
210 char drvname
[CRYPTO_MAX_ALG_NAME
];
212 if (snprintf(drvname
, CRYPTO_MAX_ALG_NAME
, "simd-%s", basename
) >=
214 return ERR_PTR(-ENAMETOOLONG
);
216 return simd_skcipher_create_compat(algname
, drvname
, basename
);
218 EXPORT_SYMBOL_GPL(simd_skcipher_create
);
220 void simd_skcipher_free(struct simd_skcipher_alg
*salg
)
222 crypto_unregister_skcipher(&salg
->alg
);
225 EXPORT_SYMBOL_GPL(simd_skcipher_free
);
227 MODULE_LICENSE("GPL");