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

Configure Feed

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

crypto: hash - Use crypto_request_complete

Use the crypto_request_complete helper instead of calling the
completion function directly.

This patch also removes the voodoo programming previously used
for unaligned ahash operations and replaces it with a sub-request.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

+72 -103
+71 -102
crypto/ahash.c
··· 190 190 } 191 191 EXPORT_SYMBOL_GPL(crypto_ahash_setkey); 192 192 193 - static inline unsigned int ahash_align_buffer_size(unsigned len, 194 - unsigned long mask) 195 - { 196 - return len + (mask & ~(crypto_tfm_ctx_alignment() - 1)); 197 - } 198 - 199 - static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt) 193 + static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt, 194 + bool has_state) 200 195 { 201 196 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 202 197 unsigned long alignmask = crypto_ahash_alignmask(tfm); 203 198 unsigned int ds = crypto_ahash_digestsize(tfm); 204 - struct ahash_request_priv *priv; 199 + struct ahash_request *subreq; 200 + unsigned int subreq_size; 201 + unsigned int reqsize; 202 + u8 *result; 203 + gfp_t gfp; 204 + u32 flags; 205 205 206 - priv = kmalloc(sizeof(*priv) + ahash_align_buffer_size(ds, alignmask), 207 - (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? 208 - GFP_KERNEL : GFP_ATOMIC); 209 - if (!priv) 206 + subreq_size = sizeof(*subreq); 207 + reqsize = crypto_ahash_reqsize(tfm); 208 + reqsize = ALIGN(reqsize, crypto_tfm_ctx_alignment()); 209 + subreq_size += reqsize; 210 + subreq_size += ds; 211 + subreq_size += alignmask & ~(crypto_tfm_ctx_alignment() - 1); 212 + 213 + flags = ahash_request_flags(req); 214 + gfp = (flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL : GFP_ATOMIC; 215 + subreq = kmalloc(subreq_size, gfp); 216 + if (!subreq) 210 217 return -ENOMEM; 211 218 212 - /* 213 - * WARNING: Voodoo programming below! 214 - * 215 - * The code below is obscure and hard to understand, thus explanation 216 - * is necessary. See include/crypto/hash.h and include/linux/crypto.h 217 - * to understand the layout of structures used here! 218 - * 219 - * The code here will replace portions of the ORIGINAL request with 220 - * pointers to new code and buffers so the hashing operation can store 221 - * the result in aligned buffer. We will call the modified request 222 - * an ADJUSTED request. 223 - * 224 - * The newly mangled request will look as such: 225 - * 226 - * req { 227 - * .result = ADJUSTED[new aligned buffer] 228 - * .base.complete = ADJUSTED[pointer to completion function] 229 - * .base.data = ADJUSTED[*req (pointer to self)] 230 - * .priv = ADJUSTED[new priv] { 231 - * .result = ORIGINAL(result) 232 - * .complete = ORIGINAL(base.complete) 233 - * .data = ORIGINAL(base.data) 234 - * } 235 - */ 219 + ahash_request_set_tfm(subreq, tfm); 220 + ahash_request_set_callback(subreq, flags, cplt, req); 236 221 237 - priv->result = req->result; 238 - priv->complete = req->base.complete; 239 - priv->data = req->base.data; 240 - priv->flags = req->base.flags; 222 + result = (u8 *)(subreq + 1) + reqsize; 223 + result = PTR_ALIGN(result, alignmask + 1); 241 224 242 - /* 243 - * WARNING: We do not backup req->priv here! The req->priv 244 - * is for internal use of the Crypto API and the 245 - * user must _NOT_ _EVER_ depend on it's content! 246 - */ 225 + ahash_request_set_crypt(subreq, req->src, result, req->nbytes); 247 226 248 - req->result = PTR_ALIGN((u8 *)priv->ubuf, alignmask + 1); 249 - req->base.complete = cplt; 250 - req->base.data = req; 251 - req->priv = priv; 227 + if (has_state) { 228 + void *state; 229 + 230 + state = kmalloc(crypto_ahash_statesize(tfm), gfp); 231 + if (!state) { 232 + kfree(subreq); 233 + return -ENOMEM; 234 + } 235 + 236 + crypto_ahash_export(req, state); 237 + crypto_ahash_import(subreq, state); 238 + kfree_sensitive(state); 239 + } 240 + 241 + req->priv = subreq; 252 242 253 243 return 0; 254 244 } 255 245 256 246 static void ahash_restore_req(struct ahash_request *req, int err) 257 247 { 258 - struct ahash_request_priv *priv = req->priv; 248 + struct ahash_request *subreq = req->priv; 259 249 260 250 if (!err) 261 - memcpy(priv->result, req->result, 251 + memcpy(req->result, subreq->result, 262 252 crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); 263 253 264 - /* Restore the original crypto request. */ 265 - req->result = priv->result; 266 - 267 - ahash_request_set_callback(req, priv->flags, 268 - priv->complete, priv->data); 269 254 req->priv = NULL; 270 255 271 - /* Free the req->priv.priv from the ADJUSTED request. */ 272 - kfree_sensitive(priv); 273 - } 274 - 275 - static void ahash_notify_einprogress(struct ahash_request *req) 276 - { 277 - struct ahash_request_priv *priv = req->priv; 278 - struct crypto_async_request oreq; 279 - 280 - oreq.data = priv->data; 281 - 282 - priv->complete(&oreq, -EINPROGRESS); 256 + kfree_sensitive(subreq); 283 257 } 284 258 285 259 static void ahash_op_unaligned_done(struct crypto_async_request *req, int err) 286 260 { 287 261 struct ahash_request *areq = req->data; 288 262 289 - if (err == -EINPROGRESS) { 290 - ahash_notify_einprogress(areq); 291 - return; 292 - } 293 - 294 - /* 295 - * Restore the original request, see ahash_op_unaligned() for what 296 - * goes where. 297 - * 298 - * The "struct ahash_request *req" here is in fact the "req.base" 299 - * from the ADJUSTED request from ahash_op_unaligned(), thus as it 300 - * is a pointer to self, it is also the ADJUSTED "req" . 301 - */ 263 + if (err == -EINPROGRESS) 264 + goto out; 302 265 303 266 /* First copy req->result into req->priv.result */ 304 267 ahash_restore_req(areq, err); 305 268 269 + out: 306 270 /* Complete the ORIGINAL request. */ 307 - areq->base.complete(&areq->base, err); 271 + ahash_request_complete(areq, err); 308 272 } 309 273 310 274 static int ahash_op_unaligned(struct ahash_request *req, 311 - int (*op)(struct ahash_request *)) 275 + int (*op)(struct ahash_request *), 276 + bool has_state) 312 277 { 313 278 int err; 314 279 315 - err = ahash_save_req(req, ahash_op_unaligned_done); 280 + err = ahash_save_req(req, ahash_op_unaligned_done, has_state); 316 281 if (err) 317 282 return err; 318 283 319 - err = op(req); 284 + err = op(req->priv); 320 285 if (err == -EINPROGRESS || err == -EBUSY) 321 286 return err; 322 287 ··· 291 326 } 292 327 293 328 static int crypto_ahash_op(struct ahash_request *req, 294 - int (*op)(struct ahash_request *)) 329 + int (*op)(struct ahash_request *), 330 + bool has_state) 295 331 { 296 332 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 297 333 unsigned long alignmask = crypto_ahash_alignmask(tfm); 298 334 299 335 if ((unsigned long)req->result & alignmask) 300 - return ahash_op_unaligned(req, op); 336 + return ahash_op_unaligned(req, op, has_state); 301 337 302 338 return op(req); 303 339 } ··· 311 345 int ret; 312 346 313 347 crypto_stats_get(alg); 314 - ret = crypto_ahash_op(req, crypto_ahash_reqtfm(req)->final); 348 + ret = crypto_ahash_op(req, crypto_ahash_reqtfm(req)->final, true); 315 349 crypto_stats_ahash_final(nbytes, ret, alg); 316 350 return ret; 317 351 } ··· 325 359 int ret; 326 360 327 361 crypto_stats_get(alg); 328 - ret = crypto_ahash_op(req, crypto_ahash_reqtfm(req)->finup); 362 + ret = crypto_ahash_op(req, crypto_ahash_reqtfm(req)->finup, true); 329 363 crypto_stats_ahash_final(nbytes, ret, alg); 330 364 return ret; 331 365 } ··· 342 376 if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) 343 377 ret = -ENOKEY; 344 378 else 345 - ret = crypto_ahash_op(req, tfm->digest); 379 + ret = crypto_ahash_op(req, tfm->digest, false); 346 380 crypto_stats_ahash_final(nbytes, ret, alg); 347 381 return ret; 348 382 } ··· 357 391 358 392 ahash_restore_req(areq, err); 359 393 360 - areq->base.complete(&areq->base, err); 394 + ahash_request_complete(areq, err); 361 395 } 362 396 363 397 static int ahash_def_finup_finish1(struct ahash_request *req, int err) 364 398 { 399 + struct ahash_request *subreq = req->priv; 400 + 365 401 if (err) 366 402 goto out; 367 403 368 - req->base.complete = ahash_def_finup_done2; 404 + subreq->base.complete = ahash_def_finup_done2; 369 405 370 - err = crypto_ahash_reqtfm(req)->final(req); 406 + err = crypto_ahash_reqtfm(req)->final(subreq); 371 407 if (err == -EINPROGRESS || err == -EBUSY) 372 408 return err; 373 409 ··· 381 413 static void ahash_def_finup_done1(struct crypto_async_request *req, int err) 382 414 { 383 415 struct ahash_request *areq = req->data; 416 + struct ahash_request *subreq; 384 417 385 - if (err == -EINPROGRESS) { 386 - ahash_notify_einprogress(areq); 387 - return; 388 - } 418 + if (err == -EINPROGRESS) 419 + goto out; 389 420 390 - areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; 421 + subreq = areq->priv; 422 + subreq->base.flags &= CRYPTO_TFM_REQ_MAY_BACKLOG; 391 423 392 424 err = ahash_def_finup_finish1(areq, err); 393 - if (areq->priv) 425 + if (err == -EINPROGRESS || err == -EBUSY) 394 426 return; 395 427 396 - areq->base.complete(&areq->base, err); 428 + out: 429 + ahash_request_complete(areq, err); 397 430 } 398 431 399 432 static int ahash_def_finup(struct ahash_request *req) ··· 402 433 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 403 434 int err; 404 435 405 - err = ahash_save_req(req, ahash_def_finup_done1); 436 + err = ahash_save_req(req, ahash_def_finup_done1, true); 406 437 if (err) 407 438 return err; 408 439 409 - err = tfm->update(req); 440 + err = tfm->update(req->priv); 410 441 if (err == -EINPROGRESS || err == -EBUSY) 411 442 return err; 412 443
+1 -1
include/crypto/internal/hash.h
··· 199 199 200 200 static inline void ahash_request_complete(struct ahash_request *req, int err) 201 201 { 202 - req->base.complete(&req->base, err); 202 + crypto_request_complete(&req->base, err); 203 203 } 204 204 205 205 static inline u32 ahash_request_flags(struct ahash_request *req)