diff options
-rw-r--r-- | drivers/crypto/padlock-sha.c | 269 |
1 files changed, 264 insertions, 5 deletions
diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c index adf075b6b9a8..06bdb4b2c6a6 100644 --- a/drivers/crypto/padlock-sha.c +++ b/drivers/crypto/padlock-sha.c | |||
@@ -288,9 +288,250 @@ static struct shash_alg sha256_alg = { | |||
288 | } | 288 | } |
289 | }; | 289 | }; |
290 | 290 | ||
291 | /* Add two shash_alg instance for hardware-implemented * | ||
292 | * multiple-parts hash supported by VIA Nano Processor.*/ | ||
293 | static int padlock_sha1_init_nano(struct shash_desc *desc) | ||
294 | { | ||
295 | struct sha1_state *sctx = shash_desc_ctx(desc); | ||
296 | |||
297 | *sctx = (struct sha1_state){ | ||
298 | .state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 }, | ||
299 | }; | ||
300 | |||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | static int padlock_sha1_update_nano(struct shash_desc *desc, | ||
305 | const u8 *data, unsigned int len) | ||
306 | { | ||
307 | struct sha1_state *sctx = shash_desc_ctx(desc); | ||
308 | unsigned int partial, done; | ||
309 | const u8 *src; | ||
310 | /*The PHE require the out buffer must 128 bytes and 16-bytes aligned*/ | ||
311 | u8 buf[128 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__ | ||
312 | ((aligned(STACK_ALIGN))); | ||
313 | u8 *dst = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT); | ||
314 | int ts_state; | ||
315 | |||
316 | partial = sctx->count & 0x3f; | ||
317 | sctx->count += len; | ||
318 | done = 0; | ||
319 | src = data; | ||
320 | memcpy(dst, (u8 *)(sctx->state), SHA1_DIGEST_SIZE); | ||
321 | |||
322 | if ((partial + len) >= SHA1_BLOCK_SIZE) { | ||
323 | |||
324 | /* Append the bytes in state's buffer to a block to handle */ | ||
325 | if (partial) { | ||
326 | done = -partial; | ||
327 | memcpy(sctx->buffer + partial, data, | ||
328 | done + SHA1_BLOCK_SIZE); | ||
329 | src = sctx->buffer; | ||
330 | ts_state = irq_ts_save(); | ||
331 | asm volatile (".byte 0xf3,0x0f,0xa6,0xc8" | ||
332 | : "+S"(src), "+D"(dst) \ | ||
333 | : "a"((long)-1), "c"((unsigned long)1)); | ||
334 | irq_ts_restore(ts_state); | ||
335 | done += SHA1_BLOCK_SIZE; | ||
336 | src = data + done; | ||
337 | } | ||
338 | |||
339 | /* Process the left bytes from the input data */ | ||
340 | if (len - done >= SHA1_BLOCK_SIZE) { | ||
341 | ts_state = irq_ts_save(); | ||
342 | asm volatile (".byte 0xf3,0x0f,0xa6,0xc8" | ||
343 | : "+S"(src), "+D"(dst) | ||
344 | : "a"((long)-1), | ||
345 | "c"((unsigned long)((len - done) / SHA1_BLOCK_SIZE))); | ||
346 | irq_ts_restore(ts_state); | ||
347 | done += ((len - done) - (len - done) % SHA1_BLOCK_SIZE); | ||
348 | src = data + done; | ||
349 | } | ||
350 | partial = 0; | ||
351 | } | ||
352 | memcpy((u8 *)(sctx->state), dst, SHA1_DIGEST_SIZE); | ||
353 | memcpy(sctx->buffer + partial, src, len - done); | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static int padlock_sha1_final_nano(struct shash_desc *desc, u8 *out) | ||
359 | { | ||
360 | struct sha1_state *state = (struct sha1_state *)shash_desc_ctx(desc); | ||
361 | unsigned int partial, padlen; | ||
362 | __be64 bits; | ||
363 | static const u8 padding[64] = { 0x80, }; | ||
364 | |||
365 | bits = cpu_to_be64(state->count << 3); | ||
366 | |||
367 | /* Pad out to 56 mod 64 */ | ||
368 | partial = state->count & 0x3f; | ||
369 | padlen = (partial < 56) ? (56 - partial) : ((64+56) - partial); | ||
370 | padlock_sha1_update_nano(desc, padding, padlen); | ||
371 | |||
372 | /* Append length field bytes */ | ||
373 | padlock_sha1_update_nano(desc, (const u8 *)&bits, sizeof(bits)); | ||
374 | |||
375 | /* Swap to output */ | ||
376 | padlock_output_block((uint32_t *)(state->state), (uint32_t *)out, 5); | ||
377 | |||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static int padlock_sha256_init_nano(struct shash_desc *desc) | ||
382 | { | ||
383 | struct sha256_state *sctx = shash_desc_ctx(desc); | ||
384 | |||
385 | *sctx = (struct sha256_state){ | ||
386 | .state = { SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3, \ | ||
387 | SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7}, | ||
388 | }; | ||
389 | |||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | static int padlock_sha256_update_nano(struct shash_desc *desc, const u8 *data, | ||
394 | unsigned int len) | ||
395 | { | ||
396 | struct sha256_state *sctx = shash_desc_ctx(desc); | ||
397 | unsigned int partial, done; | ||
398 | const u8 *src; | ||
399 | /*The PHE require the out buffer must 128 bytes and 16-bytes aligned*/ | ||
400 | u8 buf[128 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__ | ||
401 | ((aligned(STACK_ALIGN))); | ||
402 | u8 *dst = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT); | ||
403 | int ts_state; | ||
404 | |||
405 | partial = sctx->count & 0x3f; | ||
406 | sctx->count += len; | ||
407 | done = 0; | ||
408 | src = data; | ||
409 | memcpy(dst, (u8 *)(sctx->state), SHA256_DIGEST_SIZE); | ||
410 | |||
411 | if ((partial + len) >= SHA256_BLOCK_SIZE) { | ||
412 | |||
413 | /* Append the bytes in state's buffer to a block to handle */ | ||
414 | if (partial) { | ||
415 | done = -partial; | ||
416 | memcpy(sctx->buf + partial, data, | ||
417 | done + SHA256_BLOCK_SIZE); | ||
418 | src = sctx->buf; | ||
419 | ts_state = irq_ts_save(); | ||
420 | asm volatile (".byte 0xf3,0x0f,0xa6,0xd0" | ||
421 | : "+S"(src), "+D"(dst) | ||
422 | : "a"((long)-1), "c"((unsigned long)1)); | ||
423 | irq_ts_restore(ts_state); | ||
424 | done += SHA256_BLOCK_SIZE; | ||
425 | src = data + done; | ||
426 | } | ||
427 | |||
428 | /* Process the left bytes from input data*/ | ||
429 | if (len - done >= SHA256_BLOCK_SIZE) { | ||
430 | ts_state = irq_ts_save(); | ||
431 | asm volatile (".byte 0xf3,0x0f,0xa6,0xd0" | ||
432 | : "+S"(src), "+D"(dst) | ||
433 | : "a"((long)-1), | ||
434 | "c"((unsigned long)((len - done) / 64))); | ||
435 | irq_ts_restore(ts_state); | ||
436 | done += ((len - done) - (len - done) % 64); | ||
437 | src = data + done; | ||
438 | } | ||
439 | partial = 0; | ||
440 | } | ||
441 | memcpy((u8 *)(sctx->state), dst, SHA256_DIGEST_SIZE); | ||
442 | memcpy(sctx->buf + partial, src, len - done); | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | static int padlock_sha256_final_nano(struct shash_desc *desc, u8 *out) | ||
448 | { | ||
449 | struct sha256_state *state = | ||
450 | (struct sha256_state *)shash_desc_ctx(desc); | ||
451 | unsigned int partial, padlen; | ||
452 | __be64 bits; | ||
453 | static const u8 padding[64] = { 0x80, }; | ||
454 | |||
455 | bits = cpu_to_be64(state->count << 3); | ||
456 | |||
457 | /* Pad out to 56 mod 64 */ | ||
458 | partial = state->count & 0x3f; | ||
459 | padlen = (partial < 56) ? (56 - partial) : ((64+56) - partial); | ||
460 | padlock_sha256_update_nano(desc, padding, padlen); | ||
461 | |||
462 | /* Append length field bytes */ | ||
463 | padlock_sha256_update_nano(desc, (const u8 *)&bits, sizeof(bits)); | ||
464 | |||
465 | /* Swap to output */ | ||
466 | padlock_output_block((uint32_t *)(state->state), (uint32_t *)out, 8); | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int padlock_sha_export_nano(struct shash_desc *desc, | ||
472 | void *out) | ||
473 | { | ||
474 | int statesize = crypto_shash_statesize(desc->tfm); | ||
475 | void *sctx = shash_desc_ctx(desc); | ||
476 | |||
477 | memcpy(out, sctx, statesize); | ||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | static int padlock_sha_import_nano(struct shash_desc *desc, | ||
482 | const void *in) | ||
483 | { | ||
484 | int statesize = crypto_shash_statesize(desc->tfm); | ||
485 | void *sctx = shash_desc_ctx(desc); | ||
486 | |||
487 | memcpy(sctx, in, statesize); | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | static struct shash_alg sha1_alg_nano = { | ||
492 | .digestsize = SHA1_DIGEST_SIZE, | ||
493 | .init = padlock_sha1_init_nano, | ||
494 | .update = padlock_sha1_update_nano, | ||
495 | .final = padlock_sha1_final_nano, | ||
496 | .export = padlock_sha_export_nano, | ||
497 | .import = padlock_sha_import_nano, | ||
498 | .descsize = sizeof(struct sha1_state), | ||
499 | .statesize = sizeof(struct sha1_state), | ||
500 | .base = { | ||
501 | .cra_name = "sha1", | ||
502 | .cra_driver_name = "sha1-padlock-nano", | ||
503 | .cra_priority = PADLOCK_CRA_PRIORITY, | ||
504 | .cra_flags = CRYPTO_ALG_TYPE_SHASH, | ||
505 | .cra_blocksize = SHA1_BLOCK_SIZE, | ||
506 | .cra_module = THIS_MODULE, | ||
507 | } | ||
508 | }; | ||
509 | |||
510 | static struct shash_alg sha256_alg_nano = { | ||
511 | .digestsize = SHA256_DIGEST_SIZE, | ||
512 | .init = padlock_sha256_init_nano, | ||
513 | .update = padlock_sha256_update_nano, | ||
514 | .final = padlock_sha256_final_nano, | ||
515 | .export = padlock_sha_export_nano, | ||
516 | .import = padlock_sha_import_nano, | ||
517 | .descsize = sizeof(struct sha256_state), | ||
518 | .statesize = sizeof(struct sha256_state), | ||
519 | .base = { | ||
520 | .cra_name = "sha256", | ||
521 | .cra_driver_name = "sha256-padlock-nano", | ||
522 | .cra_priority = PADLOCK_CRA_PRIORITY, | ||
523 | .cra_flags = CRYPTO_ALG_TYPE_SHASH, | ||
524 | .cra_blocksize = SHA256_BLOCK_SIZE, | ||
525 | .cra_module = THIS_MODULE, | ||
526 | } | ||
527 | }; | ||
528 | |||
291 | static int __init padlock_init(void) | 529 | static int __init padlock_init(void) |
292 | { | 530 | { |
293 | int rc = -ENODEV; | 531 | int rc = -ENODEV; |
532 | struct cpuinfo_x86 *c = &cpu_data(0); | ||
533 | struct shash_alg *sha1; | ||
534 | struct shash_alg *sha256; | ||
294 | 535 | ||
295 | if (!cpu_has_phe) { | 536 | if (!cpu_has_phe) { |
296 | printk(KERN_NOTICE PFX "VIA PadLock Hash Engine not detected.\n"); | 537 | printk(KERN_NOTICE PFX "VIA PadLock Hash Engine not detected.\n"); |
@@ -302,11 +543,21 @@ static int __init padlock_init(void) | |||
302 | return -ENODEV; | 543 | return -ENODEV; |
303 | } | 544 | } |
304 | 545 | ||
305 | rc = crypto_register_shash(&sha1_alg); | 546 | /* Register the newly added algorithm module if on * |
547 | * VIA Nano processor, or else just do as before */ | ||
548 | if (c->x86_model < 0x0f) { | ||
549 | sha1 = &sha1_alg; | ||
550 | sha256 = &sha256_alg; | ||
551 | } else { | ||
552 | sha1 = &sha1_alg_nano; | ||
553 | sha256 = &sha256_alg_nano; | ||
554 | } | ||
555 | |||
556 | rc = crypto_register_shash(sha1); | ||
306 | if (rc) | 557 | if (rc) |
307 | goto out; | 558 | goto out; |
308 | 559 | ||
309 | rc = crypto_register_shash(&sha256_alg); | 560 | rc = crypto_register_shash(sha256); |
310 | if (rc) | 561 | if (rc) |
311 | goto out_unreg1; | 562 | goto out_unreg1; |
312 | 563 | ||
@@ -315,7 +566,8 @@ static int __init padlock_init(void) | |||
315 | return 0; | 566 | return 0; |
316 | 567 | ||
317 | out_unreg1: | 568 | out_unreg1: |
318 | crypto_unregister_shash(&sha1_alg); | 569 | crypto_unregister_shash(sha1); |
570 | |||
319 | out: | 571 | out: |
320 | printk(KERN_ERR PFX "VIA PadLock SHA1/SHA256 initialization failed.\n"); | 572 | printk(KERN_ERR PFX "VIA PadLock SHA1/SHA256 initialization failed.\n"); |
321 | return rc; | 573 | return rc; |
@@ -323,8 +575,15 @@ out: | |||
323 | 575 | ||
324 | static void __exit padlock_fini(void) | 576 | static void __exit padlock_fini(void) |
325 | { | 577 | { |
326 | crypto_unregister_shash(&sha1_alg); | 578 | struct cpuinfo_x86 *c = &cpu_data(0); |
327 | crypto_unregister_shash(&sha256_alg); | 579 | |
580 | if (c->x86_model >= 0x0f) { | ||
581 | crypto_unregister_shash(&sha1_alg_nano); | ||
582 | crypto_unregister_shash(&sha256_alg_nano); | ||
583 | } else { | ||
584 | crypto_unregister_shash(&sha1_alg); | ||
585 | crypto_unregister_shash(&sha256_alg); | ||
586 | } | ||
328 | } | 587 | } |
329 | 588 | ||
330 | module_init(padlock_init); | 589 | module_init(padlock_init); |