Thomas Gleixner | 2874c5f | 2019-05-27 08:55:01 +0200 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 2 | /* |
| 3 | * Asynchronous Cryptographic Hash operations. |
| 4 | * |
Eric Biggers | 4d707a4 | 2023-10-22 01:10:55 -0700 | [diff] [blame] | 5 | * This is the implementation of the ahash (asynchronous hash) API. It differs |
| 6 | * from shash (synchronous hash) in that ahash supports asynchronous operations, |
| 7 | * and it hashes data from scatterlists instead of virtually addressed buffers. |
| 8 | * |
| 9 | * The ahash API provides access to both ahash and shash algorithms. The shash |
| 10 | * API only provides access to shash algorithms. |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 11 | * |
| 12 | * Copyright (c) 2008 Loc Ho <lho@amcc.com> |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 13 | */ |
| 14 | |
Herbert Xu | 2003625 | 2008-07-07 22:19:53 +0800 | [diff] [blame] | 15 | #include <crypto/scatterwalk.h> |
Herbert Xu | 42808e5 | 2023-02-16 18:35:15 +0800 | [diff] [blame] | 16 | #include <linux/cryptouser.h> |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 17 | #include <linux/err.h> |
| 18 | #include <linux/kernel.h> |
| 19 | #include <linux/module.h> |
| 20 | #include <linux/sched.h> |
| 21 | #include <linux/slab.h> |
| 22 | #include <linux/seq_file.h> |
Herbert Xu | 42808e5 | 2023-02-16 18:35:15 +0800 | [diff] [blame] | 23 | #include <linux/string.h> |
Steffen Klassert | 6238cba | 2011-09-27 07:41:07 +0200 | [diff] [blame] | 24 | #include <net/netlink.h> |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 25 | |
Herbert Xu | 42808e5 | 2023-02-16 18:35:15 +0800 | [diff] [blame] | 26 | #include "hash.h" |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 27 | |
Herbert Xu | b64d143 | 2023-09-14 16:28:23 +0800 | [diff] [blame] | 28 | #define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000e |
| 29 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 30 | static inline struct crypto_istat_hash *ahash_get_stat(struct ahash_alg *alg) |
Eric Biggers | ecf889b | 2023-10-22 01:10:58 -0700 | [diff] [blame] | 31 | { |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 32 | return hash_get_stat(&alg->halg); |
Eric Biggers | ecf889b | 2023-10-22 01:10:58 -0700 | [diff] [blame] | 33 | } |
| 34 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 35 | static inline int crypto_ahash_errstat(struct ahash_alg *alg, int err) |
Eric Biggers | ecf889b | 2023-10-22 01:10:58 -0700 | [diff] [blame] | 36 | { |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 37 | if (!IS_ENABLED(CONFIG_CRYPTO_STATS)) |
| 38 | return err; |
| 39 | |
| 40 | if (err && err != -EINPROGRESS && err != -EBUSY) |
| 41 | atomic64_inc(&ahash_get_stat(alg)->err_cnt); |
| 42 | |
| 43 | return err; |
| 44 | } |
| 45 | |
| 46 | /* |
| 47 | * For an ahash tfm that is using an shash algorithm (instead of an ahash |
| 48 | * algorithm), this returns the underlying shash tfm. |
| 49 | */ |
| 50 | static inline struct crypto_shash *ahash_to_shash(struct crypto_ahash *tfm) |
| 51 | { |
| 52 | return *(struct crypto_shash **)crypto_ahash_ctx(tfm); |
| 53 | } |
| 54 | |
| 55 | static inline struct shash_desc *prepare_shash_desc(struct ahash_request *req, |
| 56 | struct crypto_ahash *tfm) |
| 57 | { |
Eric Biggers | ecf889b | 2023-10-22 01:10:58 -0700 | [diff] [blame] | 58 | struct shash_desc *desc = ahash_request_ctx(req); |
| 59 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 60 | desc->tfm = ahash_to_shash(tfm); |
| 61 | return desc; |
Eric Biggers | ecf889b | 2023-10-22 01:10:58 -0700 | [diff] [blame] | 62 | } |
| 63 | |
| 64 | int shash_ahash_update(struct ahash_request *req, struct shash_desc *desc) |
| 65 | { |
| 66 | struct crypto_hash_walk walk; |
| 67 | int nbytes; |
| 68 | |
| 69 | for (nbytes = crypto_hash_walk_first(req, &walk); nbytes > 0; |
| 70 | nbytes = crypto_hash_walk_done(&walk, nbytes)) |
| 71 | nbytes = crypto_shash_update(desc, walk.data, nbytes); |
| 72 | |
| 73 | return nbytes; |
| 74 | } |
| 75 | EXPORT_SYMBOL_GPL(shash_ahash_update); |
| 76 | |
Eric Biggers | ecf889b | 2023-10-22 01:10:58 -0700 | [diff] [blame] | 77 | int shash_ahash_finup(struct ahash_request *req, struct shash_desc *desc) |
| 78 | { |
| 79 | struct crypto_hash_walk walk; |
| 80 | int nbytes; |
| 81 | |
| 82 | nbytes = crypto_hash_walk_first(req, &walk); |
| 83 | if (!nbytes) |
| 84 | return crypto_shash_final(desc, req->result); |
| 85 | |
| 86 | do { |
| 87 | nbytes = crypto_hash_walk_last(&walk) ? |
| 88 | crypto_shash_finup(desc, walk.data, nbytes, |
| 89 | req->result) : |
| 90 | crypto_shash_update(desc, walk.data, nbytes); |
| 91 | nbytes = crypto_hash_walk_done(&walk, nbytes); |
| 92 | } while (nbytes > 0); |
| 93 | |
| 94 | return nbytes; |
| 95 | } |
| 96 | EXPORT_SYMBOL_GPL(shash_ahash_finup); |
| 97 | |
Eric Biggers | ecf889b | 2023-10-22 01:10:58 -0700 | [diff] [blame] | 98 | int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc) |
| 99 | { |
| 100 | unsigned int nbytes = req->nbytes; |
| 101 | struct scatterlist *sg; |
| 102 | unsigned int offset; |
| 103 | int err; |
| 104 | |
| 105 | if (nbytes && |
| 106 | (sg = req->src, offset = sg->offset, |
| 107 | nbytes <= min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset))) { |
| 108 | void *data; |
| 109 | |
| 110 | data = kmap_local_page(sg_page(sg)); |
| 111 | err = crypto_shash_digest(desc, data + offset, nbytes, |
| 112 | req->result); |
| 113 | kunmap_local(data); |
| 114 | } else |
| 115 | err = crypto_shash_init(desc) ?: |
| 116 | shash_ahash_finup(req, desc); |
| 117 | |
| 118 | return err; |
| 119 | } |
| 120 | EXPORT_SYMBOL_GPL(shash_ahash_digest); |
| 121 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 122 | static void crypto_exit_ahash_using_shash(struct crypto_tfm *tfm) |
Eric Biggers | ecf889b | 2023-10-22 01:10:58 -0700 | [diff] [blame] | 123 | { |
| 124 | struct crypto_shash **ctx = crypto_tfm_ctx(tfm); |
| 125 | |
| 126 | crypto_free_shash(*ctx); |
| 127 | } |
| 128 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 129 | static int crypto_init_ahash_using_shash(struct crypto_tfm *tfm) |
Eric Biggers | ecf889b | 2023-10-22 01:10:58 -0700 | [diff] [blame] | 130 | { |
| 131 | struct crypto_alg *calg = tfm->__crt_alg; |
Eric Biggers | ecf889b | 2023-10-22 01:10:58 -0700 | [diff] [blame] | 132 | struct crypto_ahash *crt = __crypto_ahash_cast(tfm); |
| 133 | struct crypto_shash **ctx = crypto_tfm_ctx(tfm); |
| 134 | struct crypto_shash *shash; |
| 135 | |
| 136 | if (!crypto_mod_get(calg)) |
| 137 | return -EAGAIN; |
| 138 | |
| 139 | shash = crypto_create_tfm(calg, &crypto_shash_type); |
| 140 | if (IS_ERR(shash)) { |
| 141 | crypto_mod_put(calg); |
| 142 | return PTR_ERR(shash); |
| 143 | } |
| 144 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 145 | crt->using_shash = true; |
Eric Biggers | ecf889b | 2023-10-22 01:10:58 -0700 | [diff] [blame] | 146 | *ctx = shash; |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 147 | tfm->exit = crypto_exit_ahash_using_shash; |
Eric Biggers | ecf889b | 2023-10-22 01:10:58 -0700 | [diff] [blame] | 148 | |
| 149 | crypto_ahash_set_flags(crt, crypto_shash_get_flags(shash) & |
| 150 | CRYPTO_TFM_NEED_KEY); |
Eric Biggers | ecf889b | 2023-10-22 01:10:58 -0700 | [diff] [blame] | 151 | crt->reqsize = sizeof(struct shash_desc) + crypto_shash_descsize(shash); |
| 152 | |
| 153 | return 0; |
| 154 | } |
| 155 | |
Herbert Xu | 2003625 | 2008-07-07 22:19:53 +0800 | [diff] [blame] | 156 | static int hash_walk_next(struct crypto_hash_walk *walk) |
| 157 | { |
Herbert Xu | 2003625 | 2008-07-07 22:19:53 +0800 | [diff] [blame] | 158 | unsigned int offset = walk->offset; |
| 159 | unsigned int nbytes = min(walk->entrylen, |
| 160 | ((unsigned int)(PAGE_SIZE)) - offset); |
| 161 | |
Ard Biesheuvel | aa96951 | 2022-12-13 17:13:10 +0100 | [diff] [blame] | 162 | walk->data = kmap_local_page(walk->pg); |
Herbert Xu | 2003625 | 2008-07-07 22:19:53 +0800 | [diff] [blame] | 163 | walk->data += offset; |
Herbert Xu | 2003625 | 2008-07-07 22:19:53 +0800 | [diff] [blame] | 164 | walk->entrylen -= nbytes; |
| 165 | return nbytes; |
| 166 | } |
| 167 | |
| 168 | static int hash_walk_new_entry(struct crypto_hash_walk *walk) |
| 169 | { |
| 170 | struct scatterlist *sg; |
| 171 | |
| 172 | sg = walk->sg; |
Herbert Xu | 2003625 | 2008-07-07 22:19:53 +0800 | [diff] [blame] | 173 | walk->offset = sg->offset; |
Herbert Xu | 13f4bb7 | 2016-05-04 17:52:56 +0800 | [diff] [blame] | 174 | walk->pg = sg_page(walk->sg) + (walk->offset >> PAGE_SHIFT); |
| 175 | walk->offset = offset_in_page(walk->offset); |
Herbert Xu | 2003625 | 2008-07-07 22:19:53 +0800 | [diff] [blame] | 176 | walk->entrylen = sg->length; |
| 177 | |
| 178 | if (walk->entrylen > walk->total) |
| 179 | walk->entrylen = walk->total; |
| 180 | walk->total -= walk->entrylen; |
| 181 | |
| 182 | return hash_walk_next(walk); |
| 183 | } |
| 184 | |
| 185 | int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err) |
| 186 | { |
Herbert Xu | 2003625 | 2008-07-07 22:19:53 +0800 | [diff] [blame] | 187 | walk->data -= walk->offset; |
| 188 | |
Ard Biesheuvel | aa96951 | 2022-12-13 17:13:10 +0100 | [diff] [blame] | 189 | kunmap_local(walk->data); |
Ira Weiny | 8afa25a | 2020-08-10 17:40:15 -0700 | [diff] [blame] | 190 | crypto_yield(walk->flags); |
Herbert Xu | 2003625 | 2008-07-07 22:19:53 +0800 | [diff] [blame] | 191 | |
| 192 | if (err) |
| 193 | return err; |
| 194 | |
Eric Biggers | 77568e5 | 2019-01-31 23:51:41 -0800 | [diff] [blame] | 195 | if (walk->entrylen) { |
Herbert Xu | d315a0e | 2009-05-31 23:09:22 +1000 | [diff] [blame] | 196 | walk->offset = 0; |
| 197 | walk->pg++; |
Herbert Xu | 2003625 | 2008-07-07 22:19:53 +0800 | [diff] [blame] | 198 | return hash_walk_next(walk); |
Herbert Xu | d315a0e | 2009-05-31 23:09:22 +1000 | [diff] [blame] | 199 | } |
Herbert Xu | 2003625 | 2008-07-07 22:19:53 +0800 | [diff] [blame] | 200 | |
| 201 | if (!walk->total) |
| 202 | return 0; |
| 203 | |
Cristian Stoica | 5be4d4c | 2015-01-20 10:06:16 +0200 | [diff] [blame] | 204 | walk->sg = sg_next(walk->sg); |
Herbert Xu | 2003625 | 2008-07-07 22:19:53 +0800 | [diff] [blame] | 205 | |
| 206 | return hash_walk_new_entry(walk); |
| 207 | } |
| 208 | EXPORT_SYMBOL_GPL(crypto_hash_walk_done); |
| 209 | |
| 210 | int crypto_hash_walk_first(struct ahash_request *req, |
| 211 | struct crypto_hash_walk *walk) |
| 212 | { |
| 213 | walk->total = req->nbytes; |
| 214 | |
Tim Chen | 6d9529c | 2014-07-10 16:18:08 -0700 | [diff] [blame] | 215 | if (!walk->total) { |
| 216 | walk->entrylen = 0; |
Herbert Xu | 2003625 | 2008-07-07 22:19:53 +0800 | [diff] [blame] | 217 | return 0; |
Tim Chen | 6d9529c | 2014-07-10 16:18:08 -0700 | [diff] [blame] | 218 | } |
Herbert Xu | 2003625 | 2008-07-07 22:19:53 +0800 | [diff] [blame] | 219 | |
Herbert Xu | 2003625 | 2008-07-07 22:19:53 +0800 | [diff] [blame] | 220 | walk->sg = req->src; |
Ira Weiny | 8afa25a | 2020-08-10 17:40:15 -0700 | [diff] [blame] | 221 | walk->flags = req->base.flags; |
Herbert Xu | 2003625 | 2008-07-07 22:19:53 +0800 | [diff] [blame] | 222 | |
| 223 | return hash_walk_new_entry(walk); |
| 224 | } |
| 225 | EXPORT_SYMBOL_GPL(crypto_hash_walk_first); |
| 226 | |
Eric Biggers | ba7d743 | 2019-01-06 18:47:42 -0800 | [diff] [blame] | 227 | static int ahash_nosetkey(struct crypto_ahash *tfm, const u8 *key, |
| 228 | unsigned int keylen) |
| 229 | { |
| 230 | return -ENOSYS; |
| 231 | } |
| 232 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 233 | static void ahash_set_needkey(struct crypto_ahash *tfm, struct ahash_alg *alg) |
Eric Biggers | ba7d743 | 2019-01-06 18:47:42 -0800 | [diff] [blame] | 234 | { |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 235 | if (alg->setkey != ahash_nosetkey && |
| 236 | !(alg->halg.base.cra_flags & CRYPTO_ALG_OPTIONAL_KEY)) |
Eric Biggers | ba7d743 | 2019-01-06 18:47:42 -0800 | [diff] [blame] | 237 | crypto_ahash_set_flags(tfm, CRYPTO_TFM_NEED_KEY); |
| 238 | } |
| 239 | |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 240 | int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key, |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 241 | unsigned int keylen) |
| 242 | { |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 243 | if (likely(tfm->using_shash)) { |
| 244 | struct crypto_shash *shash = ahash_to_shash(tfm); |
| 245 | int err; |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 246 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 247 | err = crypto_shash_setkey(shash, key, keylen); |
| 248 | if (unlikely(err)) { |
| 249 | crypto_ahash_set_flags(tfm, |
| 250 | crypto_shash_get_flags(shash) & |
| 251 | CRYPTO_TFM_NEED_KEY); |
| 252 | return err; |
| 253 | } |
| 254 | } else { |
| 255 | struct ahash_alg *alg = crypto_ahash_alg(tfm); |
| 256 | int err; |
| 257 | |
| 258 | err = alg->setkey(tfm, key, keylen); |
| 259 | if (unlikely(err)) { |
| 260 | ahash_set_needkey(tfm, alg); |
| 261 | return err; |
| 262 | } |
Eric Biggers | ba7d743 | 2019-01-06 18:47:42 -0800 | [diff] [blame] | 263 | } |
Eric Biggers | 9fa68f6 | 2018-01-03 11:16:27 -0800 | [diff] [blame] | 264 | crypto_ahash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY); |
| 265 | return 0; |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 266 | } |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 267 | EXPORT_SYMBOL_GPL(crypto_ahash_setkey); |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 268 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 269 | int crypto_ahash_init(struct ahash_request *req) |
| 270 | { |
| 271 | struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); |
| 272 | |
| 273 | if (likely(tfm->using_shash)) |
| 274 | return crypto_shash_init(prepare_shash_desc(req, tfm)); |
| 275 | if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) |
| 276 | return -ENOKEY; |
| 277 | return crypto_ahash_alg(tfm)->init(req); |
| 278 | } |
| 279 | EXPORT_SYMBOL_GPL(crypto_ahash_init); |
| 280 | |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 281 | static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt, |
| 282 | bool has_state) |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 283 | { |
| 284 | struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 285 | unsigned int ds = crypto_ahash_digestsize(tfm); |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 286 | struct ahash_request *subreq; |
| 287 | unsigned int subreq_size; |
| 288 | unsigned int reqsize; |
| 289 | u8 *result; |
| 290 | gfp_t gfp; |
| 291 | u32 flags; |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 292 | |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 293 | subreq_size = sizeof(*subreq); |
| 294 | reqsize = crypto_ahash_reqsize(tfm); |
| 295 | reqsize = ALIGN(reqsize, crypto_tfm_ctx_alignment()); |
| 296 | subreq_size += reqsize; |
| 297 | subreq_size += ds; |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 298 | |
| 299 | flags = ahash_request_flags(req); |
| 300 | gfp = (flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL : GFP_ATOMIC; |
| 301 | subreq = kmalloc(subreq_size, gfp); |
| 302 | if (!subreq) |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 303 | return -ENOMEM; |
| 304 | |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 305 | ahash_request_set_tfm(subreq, tfm); |
| 306 | ahash_request_set_callback(subreq, flags, cplt, req); |
Marek Vasut | ab6bf4e | 2014-03-14 02:37:04 +0100 | [diff] [blame] | 307 | |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 308 | result = (u8 *)(subreq + 1) + reqsize; |
Herbert Xu | ef0579b | 2017-04-10 17:27:57 +0800 | [diff] [blame] | 309 | |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 310 | ahash_request_set_crypt(subreq, req->src, result, req->nbytes); |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 311 | |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 312 | if (has_state) { |
| 313 | void *state; |
| 314 | |
| 315 | state = kmalloc(crypto_ahash_statesize(tfm), gfp); |
| 316 | if (!state) { |
| 317 | kfree(subreq); |
| 318 | return -ENOMEM; |
| 319 | } |
| 320 | |
| 321 | crypto_ahash_export(req, state); |
| 322 | crypto_ahash_import(subreq, state); |
| 323 | kfree_sensitive(state); |
| 324 | } |
| 325 | |
| 326 | req->priv = subreq; |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 327 | |
Marek Vasut | 1ffc9fb | 2014-03-14 02:37:05 +0100 | [diff] [blame] | 328 | return 0; |
| 329 | } |
| 330 | |
Herbert Xu | ef0579b | 2017-04-10 17:27:57 +0800 | [diff] [blame] | 331 | static void ahash_restore_req(struct ahash_request *req, int err) |
Marek Vasut | 1ffc9fb | 2014-03-14 02:37:05 +0100 | [diff] [blame] | 332 | { |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 333 | struct ahash_request *subreq = req->priv; |
Marek Vasut | 1ffc9fb | 2014-03-14 02:37:05 +0100 | [diff] [blame] | 334 | |
Herbert Xu | ef0579b | 2017-04-10 17:27:57 +0800 | [diff] [blame] | 335 | if (!err) |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 336 | memcpy(req->result, subreq->result, |
Herbert Xu | ef0579b | 2017-04-10 17:27:57 +0800 | [diff] [blame] | 337 | crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); |
| 338 | |
Marek Vasut | 1ffc9fb | 2014-03-14 02:37:05 +0100 | [diff] [blame] | 339 | req->priv = NULL; |
| 340 | |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 341 | kfree_sensitive(subreq); |
Marek Vasut | 1ffc9fb | 2014-03-14 02:37:05 +0100 | [diff] [blame] | 342 | } |
| 343 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 344 | int crypto_ahash_update(struct ahash_request *req) |
| 345 | { |
| 346 | struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); |
| 347 | struct ahash_alg *alg; |
| 348 | |
| 349 | if (likely(tfm->using_shash)) |
| 350 | return shash_ahash_update(req, ahash_request_ctx(req)); |
| 351 | |
| 352 | alg = crypto_ahash_alg(tfm); |
| 353 | if (IS_ENABLED(CONFIG_CRYPTO_STATS)) |
| 354 | atomic64_add(req->nbytes, &ahash_get_stat(alg)->hash_tlen); |
| 355 | return crypto_ahash_errstat(alg, alg->update(req)); |
| 356 | } |
| 357 | EXPORT_SYMBOL_GPL(crypto_ahash_update); |
| 358 | |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 359 | int crypto_ahash_final(struct ahash_request *req) |
| 360 | { |
Corentin Labbe | f7d76e0 | 2018-11-29 14:42:21 +0000 | [diff] [blame] | 361 | struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 362 | struct ahash_alg *alg; |
Corentin Labbe | cac5818 | 2018-09-19 10:10:54 +0000 | [diff] [blame] | 363 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 364 | if (likely(tfm->using_shash)) |
| 365 | return crypto_shash_final(ahash_request_ctx(req), req->result); |
| 366 | |
| 367 | alg = crypto_ahash_alg(tfm); |
Herbert Xu | 42808e5 | 2023-02-16 18:35:15 +0800 | [diff] [blame] | 368 | if (IS_ENABLED(CONFIG_CRYPTO_STATS)) |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 369 | atomic64_inc(&ahash_get_stat(alg)->hash_cnt); |
| 370 | return crypto_ahash_errstat(alg, alg->final(req)); |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 371 | } |
| 372 | EXPORT_SYMBOL_GPL(crypto_ahash_final); |
| 373 | |
| 374 | int crypto_ahash_finup(struct ahash_request *req) |
| 375 | { |
Corentin Labbe | f7d76e0 | 2018-11-29 14:42:21 +0000 | [diff] [blame] | 376 | struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 377 | struct ahash_alg *alg; |
Corentin Labbe | cac5818 | 2018-09-19 10:10:54 +0000 | [diff] [blame] | 378 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 379 | if (likely(tfm->using_shash)) |
| 380 | return shash_ahash_finup(req, ahash_request_ctx(req)); |
| 381 | |
| 382 | alg = crypto_ahash_alg(tfm); |
Herbert Xu | 42808e5 | 2023-02-16 18:35:15 +0800 | [diff] [blame] | 383 | if (IS_ENABLED(CONFIG_CRYPTO_STATS)) { |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 384 | struct crypto_istat_hash *istat = ahash_get_stat(alg); |
Herbert Xu | 42808e5 | 2023-02-16 18:35:15 +0800 | [diff] [blame] | 385 | |
| 386 | atomic64_inc(&istat->hash_cnt); |
| 387 | atomic64_add(req->nbytes, &istat->hash_tlen); |
| 388 | } |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 389 | return crypto_ahash_errstat(alg, alg->finup(req)); |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 390 | } |
| 391 | EXPORT_SYMBOL_GPL(crypto_ahash_finup); |
| 392 | |
| 393 | int crypto_ahash_digest(struct ahash_request *req) |
| 394 | { |
Eric Biggers | 9fa68f6 | 2018-01-03 11:16:27 -0800 | [diff] [blame] | 395 | struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 396 | struct ahash_alg *alg; |
Eric Biggers | c626910 | 2023-10-22 01:10:44 -0700 | [diff] [blame] | 397 | int err; |
Eric Biggers | 9fa68f6 | 2018-01-03 11:16:27 -0800 | [diff] [blame] | 398 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 399 | if (likely(tfm->using_shash)) |
| 400 | return shash_ahash_digest(req, prepare_shash_desc(req, tfm)); |
| 401 | |
| 402 | alg = crypto_ahash_alg(tfm); |
Herbert Xu | 42808e5 | 2023-02-16 18:35:15 +0800 | [diff] [blame] | 403 | if (IS_ENABLED(CONFIG_CRYPTO_STATS)) { |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 404 | struct crypto_istat_hash *istat = ahash_get_stat(alg); |
Herbert Xu | 42808e5 | 2023-02-16 18:35:15 +0800 | [diff] [blame] | 405 | |
| 406 | atomic64_inc(&istat->hash_cnt); |
| 407 | atomic64_add(req->nbytes, &istat->hash_tlen); |
| 408 | } |
| 409 | |
Eric Biggers | 9fa68f6 | 2018-01-03 11:16:27 -0800 | [diff] [blame] | 410 | if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) |
Eric Biggers | c626910 | 2023-10-22 01:10:44 -0700 | [diff] [blame] | 411 | err = -ENOKEY; |
| 412 | else |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 413 | err = alg->digest(req); |
Herbert Xu | 42808e5 | 2023-02-16 18:35:15 +0800 | [diff] [blame] | 414 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 415 | return crypto_ahash_errstat(alg, err); |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 416 | } |
| 417 | EXPORT_SYMBOL_GPL(crypto_ahash_digest); |
| 418 | |
Herbert Xu | 255e48e | 2023-02-08 13:58:44 +0800 | [diff] [blame] | 419 | static void ahash_def_finup_done2(void *data, int err) |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 420 | { |
Herbert Xu | 255e48e | 2023-02-08 13:58:44 +0800 | [diff] [blame] | 421 | struct ahash_request *areq = data; |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 422 | |
Herbert Xu | ef0579b | 2017-04-10 17:27:57 +0800 | [diff] [blame] | 423 | if (err == -EINPROGRESS) |
| 424 | return; |
| 425 | |
| 426 | ahash_restore_req(areq, err); |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 427 | |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 428 | ahash_request_complete(areq, err); |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 429 | } |
| 430 | |
| 431 | static int ahash_def_finup_finish1(struct ahash_request *req, int err) |
| 432 | { |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 433 | struct ahash_request *subreq = req->priv; |
| 434 | |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 435 | if (err) |
| 436 | goto out; |
| 437 | |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 438 | subreq->base.complete = ahash_def_finup_done2; |
Herbert Xu | ef0579b | 2017-04-10 17:27:57 +0800 | [diff] [blame] | 439 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 440 | err = crypto_ahash_alg(crypto_ahash_reqtfm(req))->final(subreq); |
Gilad Ben-Yossef | 4e5b0ad | 2017-10-18 08:00:36 +0100 | [diff] [blame] | 441 | if (err == -EINPROGRESS || err == -EBUSY) |
Herbert Xu | ef0579b | 2017-04-10 17:27:57 +0800 | [diff] [blame] | 442 | return err; |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 443 | |
| 444 | out: |
Herbert Xu | ef0579b | 2017-04-10 17:27:57 +0800 | [diff] [blame] | 445 | ahash_restore_req(req, err); |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 446 | return err; |
| 447 | } |
| 448 | |
Herbert Xu | 255e48e | 2023-02-08 13:58:44 +0800 | [diff] [blame] | 449 | static void ahash_def_finup_done1(void *data, int err) |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 450 | { |
Herbert Xu | 255e48e | 2023-02-08 13:58:44 +0800 | [diff] [blame] | 451 | struct ahash_request *areq = data; |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 452 | struct ahash_request *subreq; |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 453 | |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 454 | if (err == -EINPROGRESS) |
| 455 | goto out; |
Herbert Xu | ef0579b | 2017-04-10 17:27:57 +0800 | [diff] [blame] | 456 | |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 457 | subreq = areq->priv; |
| 458 | subreq->base.flags &= CRYPTO_TFM_REQ_MAY_BACKLOG; |
Herbert Xu | ef0579b | 2017-04-10 17:27:57 +0800 | [diff] [blame] | 459 | |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 460 | err = ahash_def_finup_finish1(areq, err); |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 461 | if (err == -EINPROGRESS || err == -EBUSY) |
Herbert Xu | ef0579b | 2017-04-10 17:27:57 +0800 | [diff] [blame] | 462 | return; |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 463 | |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 464 | out: |
| 465 | ahash_request_complete(areq, err); |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 466 | } |
| 467 | |
| 468 | static int ahash_def_finup(struct ahash_request *req) |
| 469 | { |
| 470 | struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); |
Marek Vasut | d4a7a0f | 2014-03-14 02:37:06 +0100 | [diff] [blame] | 471 | int err; |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 472 | |
Herbert Xu | d958804 | 2023-02-10 20:20:20 +0800 | [diff] [blame] | 473 | err = ahash_save_req(req, ahash_def_finup_done1, true); |
Marek Vasut | d4a7a0f | 2014-03-14 02:37:06 +0100 | [diff] [blame] | 474 | if (err) |
| 475 | return err; |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 476 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 477 | err = crypto_ahash_alg(tfm)->update(req->priv); |
Gilad Ben-Yossef | 4e5b0ad | 2017-10-18 08:00:36 +0100 | [diff] [blame] | 478 | if (err == -EINPROGRESS || err == -EBUSY) |
Herbert Xu | ef0579b | 2017-04-10 17:27:57 +0800 | [diff] [blame] | 479 | return err; |
| 480 | |
Marek Vasut | d4a7a0f | 2014-03-14 02:37:06 +0100 | [diff] [blame] | 481 | return ahash_def_finup_finish1(req, err); |
Herbert Xu | 66f6ce5 | 2009-07-15 12:40:40 +0800 | [diff] [blame] | 482 | } |
| 483 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 484 | int crypto_ahash_export(struct ahash_request *req, void *out) |
| 485 | { |
| 486 | struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); |
| 487 | |
| 488 | if (likely(tfm->using_shash)) |
| 489 | return crypto_shash_export(ahash_request_ctx(req), out); |
| 490 | return crypto_ahash_alg(tfm)->export(req, out); |
| 491 | } |
| 492 | EXPORT_SYMBOL_GPL(crypto_ahash_export); |
| 493 | |
| 494 | int crypto_ahash_import(struct ahash_request *req, const void *in) |
| 495 | { |
| 496 | struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); |
| 497 | |
| 498 | if (likely(tfm->using_shash)) |
| 499 | return crypto_shash_import(prepare_shash_desc(req, tfm), in); |
| 500 | if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) |
| 501 | return -ENOKEY; |
| 502 | return crypto_ahash_alg(tfm)->import(req, in); |
| 503 | } |
| 504 | EXPORT_SYMBOL_GPL(crypto_ahash_import); |
| 505 | |
Herbert Xu | e73d340 | 2020-08-18 18:25:34 +1000 | [diff] [blame] | 506 | static void crypto_ahash_exit_tfm(struct crypto_tfm *tfm) |
| 507 | { |
| 508 | struct crypto_ahash *hash = __crypto_ahash_cast(tfm); |
| 509 | struct ahash_alg *alg = crypto_ahash_alg(hash); |
| 510 | |
| 511 | alg->exit_tfm(hash); |
| 512 | } |
| 513 | |
Herbert Xu | 88056ec | 2009-07-14 12:28:26 +0800 | [diff] [blame] | 514 | static int crypto_ahash_init_tfm(struct crypto_tfm *tfm) |
| 515 | { |
| 516 | struct crypto_ahash *hash = __crypto_ahash_cast(tfm); |
| 517 | struct ahash_alg *alg = crypto_ahash_alg(hash); |
Herbert Xu | 88056ec | 2009-07-14 12:28:26 +0800 | [diff] [blame] | 518 | |
Herbert Xu | c7535fb | 2023-04-20 18:05:16 +0800 | [diff] [blame] | 519 | crypto_ahash_set_statesize(hash, alg->halg.statesize); |
| 520 | |
Eric Biggers | 85b84327 | 2023-10-22 01:10:59 -0700 | [diff] [blame] | 521 | if (tfm->__crt_alg->cra_type == &crypto_shash_type) |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 522 | return crypto_init_ahash_using_shash(tfm); |
Herbert Xu | 88056ec | 2009-07-14 12:28:26 +0800 | [diff] [blame] | 523 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 524 | ahash_set_needkey(hash, alg); |
Herbert Xu | 88056ec | 2009-07-14 12:28:26 +0800 | [diff] [blame] | 525 | |
Herbert Xu | e73d340 | 2020-08-18 18:25:34 +1000 | [diff] [blame] | 526 | if (alg->exit_tfm) |
| 527 | tfm->exit = crypto_ahash_exit_tfm; |
| 528 | |
| 529 | return alg->init_tfm ? alg->init_tfm(hash) : 0; |
Herbert Xu | 88056ec | 2009-07-14 12:28:26 +0800 | [diff] [blame] | 530 | } |
| 531 | |
| 532 | static unsigned int crypto_ahash_extsize(struct crypto_alg *alg) |
| 533 | { |
Eric Biggers | 85b84327 | 2023-10-22 01:10:59 -0700 | [diff] [blame] | 534 | if (alg->cra_type == &crypto_shash_type) |
Herbert Xu | 2495cf2 | 2016-06-29 18:03:47 +0800 | [diff] [blame] | 535 | return sizeof(struct crypto_shash *); |
Herbert Xu | 88056ec | 2009-07-14 12:28:26 +0800 | [diff] [blame] | 536 | |
Herbert Xu | 2495cf2 | 2016-06-29 18:03:47 +0800 | [diff] [blame] | 537 | return crypto_alg_extsize(alg); |
Herbert Xu | 88056ec | 2009-07-14 12:28:26 +0800 | [diff] [blame] | 538 | } |
| 539 | |
Eric Biggers | 48fb3e5 | 2020-01-02 20:04:35 -0800 | [diff] [blame] | 540 | static void crypto_ahash_free_instance(struct crypto_instance *inst) |
| 541 | { |
| 542 | struct ahash_instance *ahash = ahash_instance(inst); |
| 543 | |
Eric Biggers | 48fb3e5 | 2020-01-02 20:04:35 -0800 | [diff] [blame] | 544 | ahash->free(ahash); |
| 545 | } |
| 546 | |
Herbert Xu | c0f9e01 | 2023-02-16 18:35:28 +0800 | [diff] [blame] | 547 | static int __maybe_unused crypto_ahash_report( |
| 548 | struct sk_buff *skb, struct crypto_alg *alg) |
Steffen Klassert | 6238cba | 2011-09-27 07:41:07 +0200 | [diff] [blame] | 549 | { |
| 550 | struct crypto_report_hash rhash; |
| 551 | |
Eric Biggers | 37db69e | 2018-11-03 14:56:03 -0700 | [diff] [blame] | 552 | memset(&rhash, 0, sizeof(rhash)); |
| 553 | |
| 554 | strscpy(rhash.type, "ahash", sizeof(rhash.type)); |
Steffen Klassert | 6238cba | 2011-09-27 07:41:07 +0200 | [diff] [blame] | 555 | |
| 556 | rhash.blocksize = alg->cra_blocksize; |
| 557 | rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize; |
| 558 | |
Eric Biggers | 37db69e | 2018-11-03 14:56:03 -0700 | [diff] [blame] | 559 | return nla_put(skb, CRYPTOCFGA_REPORT_HASH, sizeof(rhash), &rhash); |
Steffen Klassert | 6238cba | 2011-09-27 07:41:07 +0200 | [diff] [blame] | 560 | } |
| 561 | |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 562 | static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg) |
Gideon Israel Dsouza | d8c34b9 | 2016-12-31 21:26:23 +0530 | [diff] [blame] | 563 | __maybe_unused; |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 564 | static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg) |
| 565 | { |
| 566 | seq_printf(m, "type : ahash\n"); |
| 567 | seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ? |
| 568 | "yes" : "no"); |
| 569 | seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); |
Herbert Xu | 88056ec | 2009-07-14 12:28:26 +0800 | [diff] [blame] | 570 | seq_printf(m, "digestsize : %u\n", |
| 571 | __crypto_hash_alg_common(alg)->digestsize); |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 572 | } |
| 573 | |
Herbert Xu | 42808e5 | 2023-02-16 18:35:15 +0800 | [diff] [blame] | 574 | static int __maybe_unused crypto_ahash_report_stat( |
| 575 | struct sk_buff *skb, struct crypto_alg *alg) |
| 576 | { |
| 577 | return crypto_hash_report_stat(skb, alg, "ahash"); |
| 578 | } |
| 579 | |
Eric Biggers | 6d1b41f | 2020-01-02 19:59:07 -0800 | [diff] [blame] | 580 | static const struct crypto_type crypto_ahash_type = { |
Herbert Xu | 88056ec | 2009-07-14 12:28:26 +0800 | [diff] [blame] | 581 | .extsize = crypto_ahash_extsize, |
| 582 | .init_tfm = crypto_ahash_init_tfm, |
Eric Biggers | 48fb3e5 | 2020-01-02 20:04:35 -0800 | [diff] [blame] | 583 | .free = crypto_ahash_free_instance, |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 584 | #ifdef CONFIG_PROC_FS |
| 585 | .show = crypto_ahash_show, |
| 586 | #endif |
Ondrej Mosnacek | b8969a1 | 2023-05-02 10:02:33 +0200 | [diff] [blame] | 587 | #if IS_ENABLED(CONFIG_CRYPTO_USER) |
Steffen Klassert | 6238cba | 2011-09-27 07:41:07 +0200 | [diff] [blame] | 588 | .report = crypto_ahash_report, |
Herbert Xu | c0f9e01 | 2023-02-16 18:35:28 +0800 | [diff] [blame] | 589 | #endif |
Herbert Xu | 42808e5 | 2023-02-16 18:35:15 +0800 | [diff] [blame] | 590 | #ifdef CONFIG_CRYPTO_STATS |
| 591 | .report_stat = crypto_ahash_report_stat, |
| 592 | #endif |
Herbert Xu | 88056ec | 2009-07-14 12:28:26 +0800 | [diff] [blame] | 593 | .maskclear = ~CRYPTO_ALG_TYPE_MASK, |
| 594 | .maskset = CRYPTO_ALG_TYPE_AHASH_MASK, |
| 595 | .type = CRYPTO_ALG_TYPE_AHASH, |
| 596 | .tfmsize = offsetof(struct crypto_ahash, base), |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 597 | }; |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 598 | |
Eric Biggers | 84a9c93 | 2020-01-02 19:58:50 -0800 | [diff] [blame] | 599 | int crypto_grab_ahash(struct crypto_ahash_spawn *spawn, |
| 600 | struct crypto_instance *inst, |
| 601 | const char *name, u32 type, u32 mask) |
| 602 | { |
| 603 | spawn->base.frontend = &crypto_ahash_type; |
| 604 | return crypto_grab_spawn(&spawn->base, inst, name, type, mask); |
| 605 | } |
| 606 | EXPORT_SYMBOL_GPL(crypto_grab_ahash); |
| 607 | |
Herbert Xu | 88056ec | 2009-07-14 12:28:26 +0800 | [diff] [blame] | 608 | struct crypto_ahash *crypto_alloc_ahash(const char *alg_name, u32 type, |
| 609 | u32 mask) |
| 610 | { |
| 611 | return crypto_alloc_tfm(alg_name, &crypto_ahash_type, type, mask); |
| 612 | } |
| 613 | EXPORT_SYMBOL_GPL(crypto_alloc_ahash); |
| 614 | |
Herbert Xu | 8d18e34 | 2016-01-23 13:52:40 +0800 | [diff] [blame] | 615 | int crypto_has_ahash(const char *alg_name, u32 type, u32 mask) |
| 616 | { |
| 617 | return crypto_type_has_alg(alg_name, &crypto_ahash_type, type, mask); |
| 618 | } |
| 619 | EXPORT_SYMBOL_GPL(crypto_has_ahash); |
| 620 | |
Herbert Xu | ed3630b | 2023-04-13 14:24:19 +0800 | [diff] [blame] | 621 | struct crypto_ahash *crypto_clone_ahash(struct crypto_ahash *hash) |
| 622 | { |
| 623 | struct hash_alg_common *halg = crypto_hash_alg_common(hash); |
| 624 | struct crypto_tfm *tfm = crypto_ahash_tfm(hash); |
| 625 | struct crypto_ahash *nhash; |
| 626 | struct ahash_alg *alg; |
| 627 | int err; |
| 628 | |
| 629 | if (!crypto_hash_alg_has_setkey(halg)) { |
| 630 | tfm = crypto_tfm_get(tfm); |
| 631 | if (IS_ERR(tfm)) |
| 632 | return ERR_CAST(tfm); |
| 633 | |
| 634 | return hash; |
| 635 | } |
| 636 | |
| 637 | nhash = crypto_clone_tfm(&crypto_ahash_type, tfm); |
| 638 | |
| 639 | if (IS_ERR(nhash)) |
| 640 | return nhash; |
| 641 | |
Herbert Xu | ed3630b | 2023-04-13 14:24:19 +0800 | [diff] [blame] | 642 | nhash->reqsize = hash->reqsize; |
Herbert Xu | c7535fb | 2023-04-20 18:05:16 +0800 | [diff] [blame] | 643 | nhash->statesize = hash->statesize; |
Herbert Xu | ed3630b | 2023-04-13 14:24:19 +0800 | [diff] [blame] | 644 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 645 | if (likely(hash->using_shash)) { |
| 646 | struct crypto_shash **nctx = crypto_ahash_ctx(nhash); |
| 647 | struct crypto_shash *shash; |
| 648 | |
| 649 | shash = crypto_clone_shash(ahash_to_shash(hash)); |
| 650 | if (IS_ERR(shash)) { |
| 651 | err = PTR_ERR(shash); |
| 652 | goto out_free_nhash; |
| 653 | } |
Dmitry Safonov | 9aedd10 | 2023-11-07 02:37:17 +0000 | [diff] [blame] | 654 | nhash->using_shash = true; |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 655 | *nctx = shash; |
| 656 | return nhash; |
| 657 | } |
Herbert Xu | ed3630b | 2023-04-13 14:24:19 +0800 | [diff] [blame] | 658 | |
| 659 | err = -ENOSYS; |
| 660 | alg = crypto_ahash_alg(hash); |
| 661 | if (!alg->clone_tfm) |
| 662 | goto out_free_nhash; |
| 663 | |
| 664 | err = alg->clone_tfm(nhash, hash); |
| 665 | if (err) |
| 666 | goto out_free_nhash; |
| 667 | |
| 668 | return nhash; |
| 669 | |
| 670 | out_free_nhash: |
| 671 | crypto_free_ahash(nhash); |
| 672 | return ERR_PTR(err); |
| 673 | } |
| 674 | EXPORT_SYMBOL_GPL(crypto_clone_ahash); |
| 675 | |
Herbert Xu | 01c2dec | 2009-07-14 14:06:06 +0800 | [diff] [blame] | 676 | static int ahash_prepare_alg(struct ahash_alg *alg) |
| 677 | { |
| 678 | struct crypto_alg *base = &alg->halg.base; |
Herbert Xu | 42808e5 | 2023-02-16 18:35:15 +0800 | [diff] [blame] | 679 | int err; |
Herbert Xu | 01c2dec | 2009-07-14 14:06:06 +0800 | [diff] [blame] | 680 | |
Herbert Xu | 42808e5 | 2023-02-16 18:35:15 +0800 | [diff] [blame] | 681 | if (alg->halg.statesize == 0) |
Herbert Xu | 01c2dec | 2009-07-14 14:06:06 +0800 | [diff] [blame] | 682 | return -EINVAL; |
| 683 | |
Herbert Xu | 42808e5 | 2023-02-16 18:35:15 +0800 | [diff] [blame] | 684 | err = hash_prepare_alg(&alg->halg); |
| 685 | if (err) |
| 686 | return err; |
| 687 | |
Herbert Xu | 01c2dec | 2009-07-14 14:06:06 +0800 | [diff] [blame] | 688 | base->cra_type = &crypto_ahash_type; |
Herbert Xu | 01c2dec | 2009-07-14 14:06:06 +0800 | [diff] [blame] | 689 | base->cra_flags |= CRYPTO_ALG_TYPE_AHASH; |
| 690 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 691 | if (!alg->finup) |
| 692 | alg->finup = ahash_def_finup; |
| 693 | if (!alg->setkey) |
| 694 | alg->setkey = ahash_nosetkey; |
| 695 | |
Herbert Xu | 01c2dec | 2009-07-14 14:06:06 +0800 | [diff] [blame] | 696 | return 0; |
| 697 | } |
| 698 | |
| 699 | int crypto_register_ahash(struct ahash_alg *alg) |
| 700 | { |
| 701 | struct crypto_alg *base = &alg->halg.base; |
| 702 | int err; |
| 703 | |
| 704 | err = ahash_prepare_alg(alg); |
| 705 | if (err) |
| 706 | return err; |
| 707 | |
| 708 | return crypto_register_alg(base); |
| 709 | } |
| 710 | EXPORT_SYMBOL_GPL(crypto_register_ahash); |
| 711 | |
Eric Biggers | c6d633a | 2019-12-15 15:51:19 -0800 | [diff] [blame] | 712 | void crypto_unregister_ahash(struct ahash_alg *alg) |
Herbert Xu | 01c2dec | 2009-07-14 14:06:06 +0800 | [diff] [blame] | 713 | { |
Eric Biggers | c6d633a | 2019-12-15 15:51:19 -0800 | [diff] [blame] | 714 | crypto_unregister_alg(&alg->halg.base); |
Herbert Xu | 01c2dec | 2009-07-14 14:06:06 +0800 | [diff] [blame] | 715 | } |
| 716 | EXPORT_SYMBOL_GPL(crypto_unregister_ahash); |
| 717 | |
Rabin Vincent | 6f7473c | 2017-08-10 14:53:52 +0200 | [diff] [blame] | 718 | int crypto_register_ahashes(struct ahash_alg *algs, int count) |
| 719 | { |
| 720 | int i, ret; |
| 721 | |
| 722 | for (i = 0; i < count; i++) { |
| 723 | ret = crypto_register_ahash(&algs[i]); |
| 724 | if (ret) |
| 725 | goto err; |
| 726 | } |
| 727 | |
| 728 | return 0; |
| 729 | |
| 730 | err: |
| 731 | for (--i; i >= 0; --i) |
| 732 | crypto_unregister_ahash(&algs[i]); |
| 733 | |
| 734 | return ret; |
| 735 | } |
| 736 | EXPORT_SYMBOL_GPL(crypto_register_ahashes); |
| 737 | |
| 738 | void crypto_unregister_ahashes(struct ahash_alg *algs, int count) |
| 739 | { |
| 740 | int i; |
| 741 | |
| 742 | for (i = count - 1; i >= 0; --i) |
| 743 | crypto_unregister_ahash(&algs[i]); |
| 744 | } |
| 745 | EXPORT_SYMBOL_GPL(crypto_unregister_ahashes); |
| 746 | |
Herbert Xu | 01c2dec | 2009-07-14 14:06:06 +0800 | [diff] [blame] | 747 | int ahash_register_instance(struct crypto_template *tmpl, |
| 748 | struct ahash_instance *inst) |
| 749 | { |
| 750 | int err; |
| 751 | |
Eric Biggers | d4fdc2d | 2020-01-02 20:04:40 -0800 | [diff] [blame] | 752 | if (WARN_ON(!inst->free)) |
| 753 | return -EINVAL; |
| 754 | |
Herbert Xu | 01c2dec | 2009-07-14 14:06:06 +0800 | [diff] [blame] | 755 | err = ahash_prepare_alg(&inst->alg); |
| 756 | if (err) |
| 757 | return err; |
| 758 | |
| 759 | return crypto_register_instance(tmpl, ahash_crypto_instance(inst)); |
| 760 | } |
| 761 | EXPORT_SYMBOL_GPL(ahash_register_instance); |
| 762 | |
Eric Biggers | cd6ed77 | 2018-01-03 11:16:22 -0800 | [diff] [blame] | 763 | bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg) |
| 764 | { |
| 765 | struct crypto_alg *alg = &halg->base; |
| 766 | |
Eric Biggers | 85b84327 | 2023-10-22 01:10:59 -0700 | [diff] [blame] | 767 | if (alg->cra_type == &crypto_shash_type) |
Eric Biggers | cd6ed77 | 2018-01-03 11:16:22 -0800 | [diff] [blame] | 768 | return crypto_shash_alg_has_setkey(__crypto_shash_alg(alg)); |
| 769 | |
Eric Biggers | 2f1f34c | 2023-10-22 01:11:00 -0700 | [diff] [blame] | 770 | return __crypto_ahash_alg(alg)->setkey != ahash_nosetkey; |
Eric Biggers | cd6ed77 | 2018-01-03 11:16:22 -0800 | [diff] [blame] | 771 | } |
| 772 | EXPORT_SYMBOL_GPL(crypto_hash_alg_has_setkey); |
| 773 | |
Loc Ho | 004a403 | 2008-05-14 20:41:47 +0800 | [diff] [blame] | 774 | MODULE_LICENSE("GPL"); |
| 775 | MODULE_DESCRIPTION("Asynchronous cryptographic hash type"); |