aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto
diff options
context:
space:
mode:
authorBrilly Wu <brillywu@viatech.com.cn>2011-03-26 22:45:00 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2011-03-26 22:45:18 -0400
commit0475add3c27a43a6599fe6338f8fffe919a13547 (patch)
tree4744ac7bdf8135e89fe8b5a24ced20c292103eda /drivers/crypto
parent7dfc2179ec7339a180e822a5af7eb1294da245cf (diff)
crypto: padlock - Add SHA-1/256 module for VIA Nano
Add new SHA-1/256 module that never needs any fallback and just calls the PadLock hardware instruction supported from VIA Nano processors to implement the "update" and "final" function. They are respectively named "sha1_alg_nano" and "sha256_alg_nano", and will be used on any VIA Nano processor or the later ones. On VIA C7 CPU, the "sha1_alg" and "sha256_alg" modules will still be used as before. Signed-off-by: Brilly Wu <brillywu@viatech.com.cn> Signed-off-by: Kary Jin <karyjin@viatech.com.cn> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto')
-rw-r--r--drivers/crypto/padlock-sha.c269
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.*/
293static 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
304static 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
358static 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
381static 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
393static 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
447static 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
471static 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
481static 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
491static 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
510static 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
291static int __init padlock_init(void) 529static 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
317out_unreg1: 568out_unreg1:
318 crypto_unregister_shash(&sha1_alg); 569 crypto_unregister_shash(sha1);
570
319out: 571out:
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
324static void __exit padlock_fini(void) 576static 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
330module_init(padlock_init); 589module_init(padlock_init);