diff options
-rw-r--r-- | crypto/drbg.c | 233 | ||||
-rw-r--r-- | include/crypto/drbg.h | 7 |
2 files changed, 128 insertions, 112 deletions
diff --git a/crypto/drbg.c b/crypto/drbg.c index 3f0b7e0f8bac..d6621a6181d7 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c | |||
@@ -370,13 +370,12 @@ static int drbg_fini_sym_kernel(struct drbg_state *drbg); | |||
370 | /* BCC function for CTR DRBG as defined in 10.4.3 */ | 370 | /* BCC function for CTR DRBG as defined in 10.4.3 */ |
371 | static int drbg_ctr_bcc(struct drbg_state *drbg, | 371 | static int drbg_ctr_bcc(struct drbg_state *drbg, |
372 | unsigned char *out, const unsigned char *key, | 372 | unsigned char *out, const unsigned char *key, |
373 | struct drbg_string *in) | 373 | struct list_head *in) |
374 | { | 374 | { |
375 | int ret = -EFAULT; | 375 | int ret = 0; |
376 | struct drbg_string *curr = in; | 376 | struct drbg_string *curr = NULL; |
377 | size_t inpos = curr->len; | ||
378 | const unsigned char *pos = curr->buf; | ||
379 | struct drbg_string data; | 377 | struct drbg_string data; |
378 | short cnt = 0; | ||
380 | 379 | ||
381 | drbg_string_fill(&data, out, drbg_blocklen(drbg)); | 380 | drbg_string_fill(&data, out, drbg_blocklen(drbg)); |
382 | 381 | ||
@@ -384,39 +383,29 @@ static int drbg_ctr_bcc(struct drbg_state *drbg, | |||
384 | memset(out, 0, drbg_blocklen(drbg)); | 383 | memset(out, 0, drbg_blocklen(drbg)); |
385 | 384 | ||
386 | /* 10.4.3 step 2 / 4 */ | 385 | /* 10.4.3 step 2 / 4 */ |
387 | while (inpos) { | 386 | list_for_each_entry(curr, in, list) { |
388 | short cnt = 0; | 387 | const unsigned char *pos = curr->buf; |
388 | size_t len = curr->len; | ||
389 | /* 10.4.3 step 4.1 */ | 389 | /* 10.4.3 step 4.1 */ |
390 | for (cnt = 0; cnt < drbg_blocklen(drbg); cnt++) { | 390 | while (len) { |
391 | out[cnt] ^= *pos; | 391 | /* 10.4.3 step 4.2 */ |
392 | pos++; inpos--; | 392 | if (drbg_blocklen(drbg) == cnt) { |
393 | /* | 393 | cnt = 0; |
394 | * The following branch implements the linked list | 394 | ret = drbg_kcapi_sym(drbg, key, out, &data); |
395 | * iteration of drbg_string *in. If we are at the | 395 | if (ret) |
396 | * end of the current list member, we have to start | 396 | return ret; |
397 | * using the next member if available. The inpos | ||
398 | * value always points to the current byte and will | ||
399 | * be zero if we have processed the last byte of | ||
400 | * the last linked list member. | ||
401 | */ | ||
402 | if (0 == inpos) { | ||
403 | curr = curr->next; | ||
404 | if (NULL != curr) { | ||
405 | pos = curr->buf; | ||
406 | inpos = curr->len; | ||
407 | } else { | ||
408 | inpos = 0; | ||
409 | break; | ||
410 | } | ||
411 | } | 397 | } |
398 | out[cnt] ^= *pos; | ||
399 | pos++; | ||
400 | cnt++; | ||
401 | len--; | ||
412 | } | 402 | } |
413 | /* 10.4.3 step 4.2 */ | ||
414 | ret = drbg_kcapi_sym(drbg, key, out, &data); | ||
415 | if (ret) | ||
416 | return ret; | ||
417 | /* 10.4.3 step 2 */ | ||
418 | } | 403 | } |
419 | return 0; | 404 | /* 10.4.3 step 4.2 for last block */ |
405 | if (cnt) | ||
406 | ret = drbg_kcapi_sym(drbg, key, out, &data); | ||
407 | |||
408 | return ret; | ||
420 | } | 409 | } |
421 | 410 | ||
422 | /* | 411 | /* |
@@ -461,13 +450,13 @@ static int drbg_ctr_bcc(struct drbg_state *drbg, | |||
461 | /* Derivation Function for CTR DRBG as defined in 10.4.2 */ | 450 | /* Derivation Function for CTR DRBG as defined in 10.4.2 */ |
462 | static int drbg_ctr_df(struct drbg_state *drbg, | 451 | static int drbg_ctr_df(struct drbg_state *drbg, |
463 | unsigned char *df_data, size_t bytes_to_return, | 452 | unsigned char *df_data, size_t bytes_to_return, |
464 | struct drbg_string *addtl) | 453 | struct list_head *seedlist) |
465 | { | 454 | { |
466 | int ret = -EFAULT; | 455 | int ret = -EFAULT; |
467 | unsigned char L_N[8]; | 456 | unsigned char L_N[8]; |
468 | /* S3 is input */ | 457 | /* S3 is input */ |
469 | struct drbg_string S1, S2, S4, cipherin; | 458 | struct drbg_string S1, S2, S4, cipherin; |
470 | struct drbg_string *tempstr = addtl; | 459 | LIST_HEAD(bcc_list); |
471 | unsigned char *pad = df_data + drbg_statelen(drbg); | 460 | unsigned char *pad = df_data + drbg_statelen(drbg); |
472 | unsigned char *iv = pad + drbg_blocklen(drbg); | 461 | unsigned char *iv = pad + drbg_blocklen(drbg); |
473 | unsigned char *temp = iv + drbg_blocklen(drbg); | 462 | unsigned char *temp = iv + drbg_blocklen(drbg); |
@@ -484,6 +473,7 @@ static int drbg_ctr_df(struct drbg_state *drbg, | |||
484 | unsigned char *X; | 473 | unsigned char *X; |
485 | size_t generated_len = 0; | 474 | size_t generated_len = 0; |
486 | size_t inputlen = 0; | 475 | size_t inputlen = 0; |
476 | struct drbg_string *seed = NULL; | ||
487 | 477 | ||
488 | memset(pad, 0, drbg_blocklen(drbg)); | 478 | memset(pad, 0, drbg_blocklen(drbg)); |
489 | memset(iv, 0, drbg_blocklen(drbg)); | 479 | memset(iv, 0, drbg_blocklen(drbg)); |
@@ -496,8 +486,8 @@ static int drbg_ctr_df(struct drbg_state *drbg, | |||
496 | return -EINVAL; | 486 | return -EINVAL; |
497 | 487 | ||
498 | /* 10.4.2 step 2 -- calculate the entire length of all input data */ | 488 | /* 10.4.2 step 2 -- calculate the entire length of all input data */ |
499 | for (; NULL != tempstr; tempstr = tempstr->next) | 489 | list_for_each_entry(seed, seedlist, list) |
500 | inputlen += tempstr->len; | 490 | inputlen += seed->len; |
501 | drbg_int2byte(&L_N[0], inputlen, 4); | 491 | drbg_int2byte(&L_N[0], inputlen, 4); |
502 | 492 | ||
503 | /* 10.4.2 step 3 */ | 493 | /* 10.4.2 step 3 */ |
@@ -518,20 +508,12 @@ static int drbg_ctr_df(struct drbg_state *drbg, | |||
518 | 508 | ||
519 | /* 10.4.2 step 4 -- first fill the linked list and then order it */ | 509 | /* 10.4.2 step 4 -- first fill the linked list and then order it */ |
520 | drbg_string_fill(&S1, iv, drbg_blocklen(drbg)); | 510 | drbg_string_fill(&S1, iv, drbg_blocklen(drbg)); |
511 | list_add_tail(&S1.list, &bcc_list); | ||
521 | drbg_string_fill(&S2, L_N, sizeof(L_N)); | 512 | drbg_string_fill(&S2, L_N, sizeof(L_N)); |
513 | list_add_tail(&S2.list, &bcc_list); | ||
514 | list_splice_tail(seedlist, &bcc_list); | ||
522 | drbg_string_fill(&S4, pad, padlen); | 515 | drbg_string_fill(&S4, pad, padlen); |
523 | S1.next = &S2; | 516 | list_add_tail(&S4.list, &bcc_list); |
524 | S2.next = addtl; | ||
525 | |||
526 | /* | ||
527 | * Splice in addtl between S2 and S4 -- we place S4 at the end | ||
528 | * of the input data chain. As this code is only triggered when | ||
529 | * addtl is not NULL, no NULL checks are necessary. | ||
530 | */ | ||
531 | tempstr = addtl; | ||
532 | while (tempstr->next) | ||
533 | tempstr = tempstr->next; | ||
534 | tempstr->next = &S4; | ||
535 | 517 | ||
536 | /* 10.4.2 step 9 */ | 518 | /* 10.4.2 step 9 */ |
537 | while (templen < (drbg_keylen(drbg) + (drbg_blocklen(drbg)))) { | 519 | while (templen < (drbg_keylen(drbg) + (drbg_blocklen(drbg)))) { |
@@ -542,7 +524,7 @@ static int drbg_ctr_df(struct drbg_state *drbg, | |||
542 | */ | 524 | */ |
543 | drbg_int2byte(iv, i, 4); | 525 | drbg_int2byte(iv, i, 4); |
544 | /* 10.4.2 step 9.2 -- BCC and concatenation with temp */ | 526 | /* 10.4.2 step 9.2 -- BCC and concatenation with temp */ |
545 | ret = drbg_ctr_bcc(drbg, temp + templen, K, &S1); | 527 | ret = drbg_ctr_bcc(drbg, temp + templen, K, &bcc_list); |
546 | if (ret) | 528 | if (ret) |
547 | goto out; | 529 | goto out; |
548 | /* 10.4.2 step 9.3 */ | 530 | /* 10.4.2 step 9.3 */ |
@@ -586,8 +568,8 @@ out: | |||
586 | } | 568 | } |
587 | 569 | ||
588 | /* update function of CTR DRBG as defined in 10.2.1.2 */ | 570 | /* update function of CTR DRBG as defined in 10.2.1.2 */ |
589 | static int drbg_ctr_update(struct drbg_state *drbg, | 571 | static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed, |
590 | struct drbg_string *addtl, int reseed) | 572 | int reseed) |
591 | { | 573 | { |
592 | int ret = -EFAULT; | 574 | int ret = -EFAULT; |
593 | /* 10.2.1.2 step 1 */ | 575 | /* 10.2.1.2 step 1 */ |
@@ -603,9 +585,8 @@ static int drbg_ctr_update(struct drbg_state *drbg, | |||
603 | memset(df_data, 0, drbg_statelen(drbg)); | 585 | memset(df_data, 0, drbg_statelen(drbg)); |
604 | 586 | ||
605 | /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */ | 587 | /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */ |
606 | if (addtl && 0 < addtl->len) { | 588 | if (seed) { |
607 | ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg), | 589 | ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg), seed); |
608 | addtl); | ||
609 | if (ret) | 590 | if (ret) |
610 | goto out; | 591 | goto out; |
611 | } | 592 | } |
@@ -665,8 +646,10 @@ static int drbg_ctr_generate(struct drbg_state *drbg, | |||
665 | 646 | ||
666 | /* 10.2.1.5.2 step 2 */ | 647 | /* 10.2.1.5.2 step 2 */ |
667 | if (addtl && 0 < addtl->len) { | 648 | if (addtl && 0 < addtl->len) { |
668 | addtl->next = NULL; | 649 | LIST_HEAD(addtllist); |
669 | ret = drbg_ctr_update(drbg, addtl, 1); | 650 | |
651 | list_add_tail(&addtl->list, &addtllist); | ||
652 | ret = drbg_ctr_update(drbg, &addtllist, 1); | ||
670 | if (ret) | 653 | if (ret) |
671 | return 0; | 654 | return 0; |
672 | } | 655 | } |
@@ -697,16 +680,21 @@ static int drbg_ctr_generate(struct drbg_state *drbg, | |||
697 | drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1); | 680 | drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1); |
698 | } | 681 | } |
699 | 682 | ||
700 | /* 10.2.1.5.2 step 6 */ | ||
701 | if (addtl) | ||
702 | addtl->next = NULL; | ||
703 | /* | 683 | /* |
684 | * 10.2.1.5.2 step 6 | ||
704 | * The following call invokes the DF function again which could be | 685 | * The following call invokes the DF function again which could be |
705 | * optimized. In step 2, the "additional_input" after step 2 is the | 686 | * optimized. In step 2, the "additional_input" after step 2 is the |
706 | * output of the DF function. If this result would be saved, the DF | 687 | * output of the DF function. If this result would be saved, the DF |
707 | * function would not need to be invoked again at this point. | 688 | * function would not need to be invoked again at this point. |
708 | */ | 689 | */ |
709 | ret = drbg_ctr_update(drbg, addtl, 1); | 690 | if (addtl && 0 < addtl->len) { |
691 | LIST_HEAD(addtllist); | ||
692 | |||
693 | list_add_tail(&addtl->list, &addtllist); | ||
694 | ret = drbg_ctr_update(drbg, &addtllist, 1); | ||
695 | } else { | ||
696 | ret = drbg_ctr_update(drbg, NULL, 1); | ||
697 | } | ||
710 | if (ret) | 698 | if (ret) |
711 | len = ret; | 699 | len = ret; |
712 | 700 | ||
@@ -729,19 +717,21 @@ static struct drbg_state_ops drbg_ctr_ops = { | |||
729 | 717 | ||
730 | #if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC) | 718 | #if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC) |
731 | static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key, | 719 | static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key, |
732 | unsigned char *outval, const struct drbg_string *in); | 720 | unsigned char *outval, const struct list_head *in); |
733 | static int drbg_init_hash_kernel(struct drbg_state *drbg); | 721 | static int drbg_init_hash_kernel(struct drbg_state *drbg); |
734 | static int drbg_fini_hash_kernel(struct drbg_state *drbg); | 722 | static int drbg_fini_hash_kernel(struct drbg_state *drbg); |
735 | #endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */ | 723 | #endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */ |
736 | 724 | ||
737 | #ifdef CONFIG_CRYPTO_DRBG_HMAC | 725 | #ifdef CONFIG_CRYPTO_DRBG_HMAC |
738 | /* update function of HMAC DRBG as defined in 10.1.2.2 */ | 726 | /* update function of HMAC DRBG as defined in 10.1.2.2 */ |
739 | static int drbg_hmac_update(struct drbg_state *drbg, | 727 | static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed, |
740 | struct drbg_string *seed, int reseed) | 728 | int reseed) |
741 | { | 729 | { |
742 | int ret = -EFAULT; | 730 | int ret = -EFAULT; |
743 | int i = 0; | 731 | int i = 0; |
744 | struct drbg_string seed1, seed2, cipherin; | 732 | struct drbg_string seed1, seed2, vdata; |
733 | LIST_HEAD(seedlist); | ||
734 | LIST_HEAD(vdatalist); | ||
745 | 735 | ||
746 | if (!reseed) { | 736 | if (!reseed) { |
747 | /* 10.1.2.3 step 2 */ | 737 | /* 10.1.2.3 step 2 */ |
@@ -750,13 +740,16 @@ static int drbg_hmac_update(struct drbg_state *drbg, | |||
750 | } | 740 | } |
751 | 741 | ||
752 | drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg)); | 742 | drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg)); |
743 | list_add_tail(&seed1.list, &seedlist); | ||
753 | /* buffer of seed2 will be filled in for loop below with one byte */ | 744 | /* buffer of seed2 will be filled in for loop below with one byte */ |
754 | drbg_string_fill(&seed2, NULL, 1); | 745 | drbg_string_fill(&seed2, NULL, 1); |
755 | seed1.next = &seed2; | 746 | list_add_tail(&seed2.list, &seedlist); |
756 | /* input data of seed is allowed to be NULL at this point */ | 747 | /* input data of seed is allowed to be NULL at this point */ |
757 | seed2.next = seed; | 748 | if (seed) |
749 | list_splice_tail(seed, &seedlist); | ||
758 | 750 | ||
759 | drbg_string_fill(&cipherin, drbg->V, drbg_statelen(drbg)); | 751 | drbg_string_fill(&vdata, drbg->V, drbg_statelen(drbg)); |
752 | list_add_tail(&vdata.list, &vdatalist); | ||
760 | for (i = 2; 0 < i; i--) { | 753 | for (i = 2; 0 < i; i--) { |
761 | /* first round uses 0x0, second 0x1 */ | 754 | /* first round uses 0x0, second 0x1 */ |
762 | unsigned char prefix = DRBG_PREFIX0; | 755 | unsigned char prefix = DRBG_PREFIX0; |
@@ -764,17 +757,17 @@ static int drbg_hmac_update(struct drbg_state *drbg, | |||
764 | prefix = DRBG_PREFIX1; | 757 | prefix = DRBG_PREFIX1; |
765 | /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */ | 758 | /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */ |
766 | seed2.buf = &prefix; | 759 | seed2.buf = &prefix; |
767 | ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seed1); | 760 | ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seedlist); |
768 | if (ret) | 761 | if (ret) |
769 | return ret; | 762 | return ret; |
770 | 763 | ||
771 | /* 10.1.2.2 step 2 and 5 -- HMAC for V */ | 764 | /* 10.1.2.2 step 2 and 5 -- HMAC for V */ |
772 | ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &cipherin); | 765 | ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &vdatalist); |
773 | if (ret) | 766 | if (ret) |
774 | return ret; | 767 | return ret; |
775 | 768 | ||
776 | /* 10.1.2.2 step 3 */ | 769 | /* 10.1.2.2 step 3 */ |
777 | if (!seed || 0 == seed->len) | 770 | if (!seed) |
778 | return ret; | 771 | return ret; |
779 | } | 772 | } |
780 | 773 | ||
@@ -790,20 +783,24 @@ static int drbg_hmac_generate(struct drbg_state *drbg, | |||
790 | int len = 0; | 783 | int len = 0; |
791 | int ret = 0; | 784 | int ret = 0; |
792 | struct drbg_string data; | 785 | struct drbg_string data; |
786 | LIST_HEAD(datalist); | ||
793 | 787 | ||
794 | /* 10.1.2.5 step 2 */ | 788 | /* 10.1.2.5 step 2 */ |
795 | if (addtl && 0 < addtl->len) { | 789 | if (addtl && 0 < addtl->len) { |
796 | addtl->next = NULL; | 790 | LIST_HEAD(addtllist); |
797 | ret = drbg_hmac_update(drbg, addtl, 1); | 791 | |
792 | list_add_tail(&addtl->list, &addtllist); | ||
793 | ret = drbg_hmac_update(drbg, &addtllist, 1); | ||
798 | if (ret) | 794 | if (ret) |
799 | return ret; | 795 | return ret; |
800 | } | 796 | } |
801 | 797 | ||
802 | drbg_string_fill(&data, drbg->V, drbg_statelen(drbg)); | 798 | drbg_string_fill(&data, drbg->V, drbg_statelen(drbg)); |
799 | list_add_tail(&data.list, &datalist); | ||
803 | while (len < buflen) { | 800 | while (len < buflen) { |
804 | unsigned int outlen = 0; | 801 | unsigned int outlen = 0; |
805 | /* 10.1.2.5 step 4.1 */ | 802 | /* 10.1.2.5 step 4.1 */ |
806 | ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &data); | 803 | ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &datalist); |
807 | if (ret) | 804 | if (ret) |
808 | return ret; | 805 | return ret; |
809 | outlen = (drbg_blocklen(drbg) < (buflen - len)) ? | 806 | outlen = (drbg_blocklen(drbg) < (buflen - len)) ? |
@@ -817,9 +814,14 @@ static int drbg_hmac_generate(struct drbg_state *drbg, | |||
817 | } | 814 | } |
818 | 815 | ||
819 | /* 10.1.2.5 step 6 */ | 816 | /* 10.1.2.5 step 6 */ |
820 | if (addtl) | 817 | if (addtl && 0 < addtl->len) { |
821 | addtl->next = NULL; | 818 | LIST_HEAD(addtllist); |
822 | ret = drbg_hmac_update(drbg, addtl, 1); | 819 | |
820 | list_add_tail(&addtl->list, &addtllist); | ||
821 | ret = drbg_hmac_update(drbg, &addtllist, 1); | ||
822 | } else { | ||
823 | ret = drbg_hmac_update(drbg, NULL, 1); | ||
824 | } | ||
823 | if (ret) | 825 | if (ret) |
824 | return ret; | 826 | return ret; |
825 | 827 | ||
@@ -858,13 +860,13 @@ static struct drbg_state_ops drbg_hmac_ops = { | |||
858 | /* Derivation Function for Hash DRBG as defined in 10.4.1 */ | 860 | /* Derivation Function for Hash DRBG as defined in 10.4.1 */ |
859 | static int drbg_hash_df(struct drbg_state *drbg, | 861 | static int drbg_hash_df(struct drbg_state *drbg, |
860 | unsigned char *outval, size_t outlen, | 862 | unsigned char *outval, size_t outlen, |
861 | struct drbg_string *entropy) | 863 | struct list_head *entropylist) |
862 | { | 864 | { |
863 | int ret = 0; | 865 | int ret = 0; |
864 | size_t len = 0; | 866 | size_t len = 0; |
865 | unsigned char input[5]; | 867 | unsigned char input[5]; |
866 | unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg); | 868 | unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg); |
867 | struct drbg_string data1; | 869 | struct drbg_string data; |
868 | 870 | ||
869 | memset(tmp, 0, drbg_blocklen(drbg)); | 871 | memset(tmp, 0, drbg_blocklen(drbg)); |
870 | 872 | ||
@@ -873,14 +875,14 @@ static int drbg_hash_df(struct drbg_state *drbg, | |||
873 | drbg_int2byte(&input[1], (outlen * 8), 4); | 875 | drbg_int2byte(&input[1], (outlen * 8), 4); |
874 | 876 | ||
875 | /* 10.4.1 step 4.1 -- concatenation of data for input into hash */ | 877 | /* 10.4.1 step 4.1 -- concatenation of data for input into hash */ |
876 | drbg_string_fill(&data1, input, 5); | 878 | drbg_string_fill(&data, input, 5); |
877 | data1.next = entropy; | 879 | list_add(&data.list, entropylist); |
878 | 880 | ||
879 | /* 10.4.1 step 4 */ | 881 | /* 10.4.1 step 4 */ |
880 | while (len < outlen) { | 882 | while (len < outlen) { |
881 | short blocklen = 0; | 883 | short blocklen = 0; |
882 | /* 10.4.1 step 4.1 */ | 884 | /* 10.4.1 step 4.1 */ |
883 | ret = drbg_kcapi_hash(drbg, NULL, tmp, &data1); | 885 | ret = drbg_kcapi_hash(drbg, NULL, tmp, entropylist); |
884 | if (ret) | 886 | if (ret) |
885 | goto out; | 887 | goto out; |
886 | /* 10.4.1 step 4.2 */ | 888 | /* 10.4.1 step 4.2 */ |
@@ -897,11 +899,13 @@ out: | |||
897 | } | 899 | } |
898 | 900 | ||
899 | /* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */ | 901 | /* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */ |
900 | static int drbg_hash_update(struct drbg_state *drbg, struct drbg_string *seed, | 902 | static int drbg_hash_update(struct drbg_state *drbg, struct list_head *seed, |
901 | int reseed) | 903 | int reseed) |
902 | { | 904 | { |
903 | int ret = 0; | 905 | int ret = 0; |
904 | struct drbg_string data1, data2; | 906 | struct drbg_string data1, data2; |
907 | LIST_HEAD(datalist); | ||
908 | LIST_HEAD(datalist2); | ||
905 | unsigned char *V = drbg->scratchpad; | 909 | unsigned char *V = drbg->scratchpad; |
906 | unsigned char prefix = DRBG_PREFIX1; | 910 | unsigned char prefix = DRBG_PREFIX1; |
907 | 911 | ||
@@ -913,26 +917,25 @@ static int drbg_hash_update(struct drbg_state *drbg, struct drbg_string *seed, | |||
913 | /* 10.1.1.3 step 1 */ | 917 | /* 10.1.1.3 step 1 */ |
914 | memcpy(V, drbg->V, drbg_statelen(drbg)); | 918 | memcpy(V, drbg->V, drbg_statelen(drbg)); |
915 | drbg_string_fill(&data1, &prefix, 1); | 919 | drbg_string_fill(&data1, &prefix, 1); |
920 | list_add_tail(&data1.list, &datalist); | ||
916 | drbg_string_fill(&data2, V, drbg_statelen(drbg)); | 921 | drbg_string_fill(&data2, V, drbg_statelen(drbg)); |
917 | data1.next = &data2; | 922 | list_add_tail(&data2.list, &datalist); |
918 | data2.next = seed; | ||
919 | } else { | ||
920 | drbg_string_fill(&data1, seed->buf, seed->len); | ||
921 | data1.next = seed->next; | ||
922 | } | 923 | } |
924 | list_splice_tail(seed, &datalist); | ||
923 | 925 | ||
924 | /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */ | 926 | /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */ |
925 | ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &data1); | 927 | ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &datalist); |
926 | if (ret) | 928 | if (ret) |
927 | goto out; | 929 | goto out; |
928 | 930 | ||
929 | /* 10.1.1.2 / 10.1.1.3 step 4 */ | 931 | /* 10.1.1.2 / 10.1.1.3 step 4 */ |
930 | prefix = DRBG_PREFIX0; | 932 | prefix = DRBG_PREFIX0; |
931 | drbg_string_fill(&data1, &prefix, 1); | 933 | drbg_string_fill(&data1, &prefix, 1); |
934 | list_add_tail(&data1.list, &datalist2); | ||
932 | drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg)); | 935 | drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg)); |
933 | data1.next = &data2; | 936 | list_add_tail(&data2.list, &datalist2); |
934 | /* 10.1.1.2 / 10.1.1.3 step 4 */ | 937 | /* 10.1.1.2 / 10.1.1.3 step 4 */ |
935 | ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &data1); | 938 | ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &datalist2); |
936 | 939 | ||
937 | out: | 940 | out: |
938 | memset(drbg->scratchpad, 0, drbg_statelen(drbg)); | 941 | memset(drbg->scratchpad, 0, drbg_statelen(drbg)); |
@@ -945,7 +948,7 @@ static int drbg_hash_process_addtl(struct drbg_state *drbg, | |||
945 | { | 948 | { |
946 | int ret = 0; | 949 | int ret = 0; |
947 | struct drbg_string data1, data2; | 950 | struct drbg_string data1, data2; |
948 | struct drbg_string *data3; | 951 | LIST_HEAD(datalist); |
949 | unsigned char prefix = DRBG_PREFIX2; | 952 | unsigned char prefix = DRBG_PREFIX2; |
950 | 953 | ||
951 | /* this is value w as per documentation */ | 954 | /* this is value w as per documentation */ |
@@ -958,11 +961,10 @@ static int drbg_hash_process_addtl(struct drbg_state *drbg, | |||
958 | /* 10.1.1.4 step 2a */ | 961 | /* 10.1.1.4 step 2a */ |
959 | drbg_string_fill(&data1, &prefix, 1); | 962 | drbg_string_fill(&data1, &prefix, 1); |
960 | drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg)); | 963 | drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg)); |
961 | data3 = addtl; | 964 | list_add_tail(&data1.list, &datalist); |
962 | data1.next = &data2; | 965 | list_add_tail(&data2.list, &datalist); |
963 | data2.next = data3; | 966 | list_add_tail(&addtl->list, &datalist); |
964 | data3->next = NULL; | 967 | ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist); |
965 | ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1); | ||
966 | if (ret) | 968 | if (ret) |
967 | goto out; | 969 | goto out; |
968 | 970 | ||
@@ -985,6 +987,7 @@ static int drbg_hash_hashgen(struct drbg_state *drbg, | |||
985 | unsigned char *src = drbg->scratchpad; | 987 | unsigned char *src = drbg->scratchpad; |
986 | unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg); | 988 | unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg); |
987 | struct drbg_string data; | 989 | struct drbg_string data; |
990 | LIST_HEAD(datalist); | ||
988 | unsigned char prefix = DRBG_PREFIX1; | 991 | unsigned char prefix = DRBG_PREFIX1; |
989 | 992 | ||
990 | memset(src, 0, drbg_statelen(drbg)); | 993 | memset(src, 0, drbg_statelen(drbg)); |
@@ -994,10 +997,11 @@ static int drbg_hash_hashgen(struct drbg_state *drbg, | |||
994 | memcpy(src, drbg->V, drbg_statelen(drbg)); | 997 | memcpy(src, drbg->V, drbg_statelen(drbg)); |
995 | 998 | ||
996 | drbg_string_fill(&data, src, drbg_statelen(drbg)); | 999 | drbg_string_fill(&data, src, drbg_statelen(drbg)); |
1000 | list_add_tail(&data.list, &datalist); | ||
997 | while (len < buflen) { | 1001 | while (len < buflen) { |
998 | unsigned int outlen = 0; | 1002 | unsigned int outlen = 0; |
999 | /* 10.1.1.4 step hashgen 4.1 */ | 1003 | /* 10.1.1.4 step hashgen 4.1 */ |
1000 | ret = drbg_kcapi_hash(drbg, NULL, dst, &data); | 1004 | ret = drbg_kcapi_hash(drbg, NULL, dst, &datalist); |
1001 | if (ret) { | 1005 | if (ret) { |
1002 | len = ret; | 1006 | len = ret; |
1003 | goto out; | 1007 | goto out; |
@@ -1032,6 +1036,7 @@ static int drbg_hash_generate(struct drbg_state *drbg, | |||
1032 | unsigned char req[8]; | 1036 | unsigned char req[8]; |
1033 | unsigned char prefix = DRBG_PREFIX3; | 1037 | unsigned char prefix = DRBG_PREFIX3; |
1034 | struct drbg_string data1, data2; | 1038 | struct drbg_string data1, data2; |
1039 | LIST_HEAD(datalist); | ||
1035 | 1040 | ||
1036 | /* 10.1.1.4 step 2 */ | 1041 | /* 10.1.1.4 step 2 */ |
1037 | ret = drbg_hash_process_addtl(drbg, addtl); | 1042 | ret = drbg_hash_process_addtl(drbg, addtl); |
@@ -1044,9 +1049,10 @@ static int drbg_hash_generate(struct drbg_state *drbg, | |||
1044 | memset(drbg->scratchpad, 0, drbg_blocklen(drbg)); | 1049 | memset(drbg->scratchpad, 0, drbg_blocklen(drbg)); |
1045 | /* 10.1.1.4 step 4 */ | 1050 | /* 10.1.1.4 step 4 */ |
1046 | drbg_string_fill(&data1, &prefix, 1); | 1051 | drbg_string_fill(&data1, &prefix, 1); |
1052 | list_add_tail(&data1.list, &datalist); | ||
1047 | drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg)); | 1053 | drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg)); |
1048 | data1.next = &data2; | 1054 | list_add_tail(&data2.list, &datalist); |
1049 | ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1); | 1055 | ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist); |
1050 | if (ret) { | 1056 | if (ret) { |
1051 | len = ret; | 1057 | len = ret; |
1052 | goto out; | 1058 | goto out; |
@@ -1099,6 +1105,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, | |||
1099 | unsigned char *entropy = NULL; | 1105 | unsigned char *entropy = NULL; |
1100 | size_t entropylen = 0; | 1106 | size_t entropylen = 0; |
1101 | struct drbg_string data1; | 1107 | struct drbg_string data1; |
1108 | LIST_HEAD(seedlist); | ||
1102 | 1109 | ||
1103 | /* 9.1 / 9.2 / 9.3.1 step 3 */ | 1110 | /* 9.1 / 9.2 / 9.3.1 step 3 */ |
1104 | if (pers && pers->len > (drbg_max_addtl(drbg))) { | 1111 | if (pers && pers->len > (drbg_max_addtl(drbg))) { |
@@ -1133,18 +1140,19 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, | |||
1133 | get_random_bytes(entropy, entropylen); | 1140 | get_random_bytes(entropy, entropylen); |
1134 | drbg_string_fill(&data1, entropy, entropylen); | 1141 | drbg_string_fill(&data1, entropy, entropylen); |
1135 | } | 1142 | } |
1143 | list_add_tail(&data1.list, &seedlist); | ||
1136 | 1144 | ||
1137 | /* | 1145 | /* |
1138 | * concatenation of entropy with personalization str / addtl input) | 1146 | * concatenation of entropy with personalization str / addtl input) |
1139 | * the variable pers is directly handed in by the caller, so check its | 1147 | * the variable pers is directly handed in by the caller, so check its |
1140 | * contents whether it is appropriate | 1148 | * contents whether it is appropriate |
1141 | */ | 1149 | */ |
1142 | if (pers && pers->buf && 0 < pers->len && NULL == pers->next) { | 1150 | if (pers && pers->buf && 0 < pers->len) { |
1143 | data1.next = pers; | 1151 | list_add_tail(&pers->list, &seedlist); |
1144 | pr_devel("DRBG: using personalization string\n"); | 1152 | pr_devel("DRBG: using personalization string\n"); |
1145 | } | 1153 | } |
1146 | 1154 | ||
1147 | ret = drbg->d_ops->update(drbg, &data1, reseed); | 1155 | ret = drbg->d_ops->update(drbg, &seedlist, reseed); |
1148 | if (ret) | 1156 | if (ret) |
1149 | goto out; | 1157 | goto out; |
1150 | 1158 | ||
@@ -1642,15 +1650,16 @@ static int drbg_fini_hash_kernel(struct drbg_state *drbg) | |||
1642 | } | 1650 | } |
1643 | 1651 | ||
1644 | static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key, | 1652 | static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key, |
1645 | unsigned char *outval, const struct drbg_string *in) | 1653 | unsigned char *outval, const struct list_head *in) |
1646 | { | 1654 | { |
1647 | struct sdesc *sdesc = (struct sdesc *)drbg->priv_data; | 1655 | struct sdesc *sdesc = (struct sdesc *)drbg->priv_data; |
1656 | struct drbg_string *input = NULL; | ||
1648 | 1657 | ||
1649 | if (key) | 1658 | if (key) |
1650 | crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg)); | 1659 | crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg)); |
1651 | crypto_shash_init(&sdesc->shash); | 1660 | crypto_shash_init(&sdesc->shash); |
1652 | for (; NULL != in; in = in->next) | 1661 | list_for_each_entry(input, in, list) |
1653 | crypto_shash_update(&sdesc->shash, in->buf, in->len); | 1662 | crypto_shash_update(&sdesc->shash, input->buf, input->len); |
1654 | return crypto_shash_final(&sdesc->shash, outval); | 1663 | return crypto_shash_final(&sdesc->shash, outval); |
1655 | } | 1664 | } |
1656 | #endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */ | 1665 | #endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */ |
@@ -1785,12 +1794,15 @@ static int drbg_kcapi_random(struct crypto_rng *tfm, u8 *rdata, | |||
1785 | return drbg_generate_long(drbg, rdata, dlen, NULL); | 1794 | return drbg_generate_long(drbg, rdata, dlen, NULL); |
1786 | } else { | 1795 | } else { |
1787 | struct drbg_gen *data = (struct drbg_gen *)rdata; | 1796 | struct drbg_gen *data = (struct drbg_gen *)rdata; |
1797 | struct drbg_string addtl; | ||
1788 | /* catch NULL pointer */ | 1798 | /* catch NULL pointer */ |
1789 | if (!data) | 1799 | if (!data) |
1790 | return 0; | 1800 | return 0; |
1791 | drbg_set_testdata(drbg, data->test_data); | 1801 | drbg_set_testdata(drbg, data->test_data); |
1802 | /* linked list variable is now local to allow modification */ | ||
1803 | drbg_string_fill(&addtl, data->addtl->buf, data->addtl->len); | ||
1792 | return drbg_generate_long(drbg, data->outbuf, data->outlen, | 1804 | return drbg_generate_long(drbg, data->outbuf, data->outlen, |
1793 | data->addtl); | 1805 | &addtl); |
1794 | } | 1806 | } |
1795 | } | 1807 | } |
1796 | 1808 | ||
@@ -1820,7 +1832,10 @@ static int drbg_kcapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) | |||
1820 | if (!data) | 1832 | if (!data) |
1821 | return drbg_instantiate(drbg, NULL, coreref, pr); | 1833 | return drbg_instantiate(drbg, NULL, coreref, pr); |
1822 | drbg_set_testdata(drbg, data->test_data); | 1834 | drbg_set_testdata(drbg, data->test_data); |
1823 | return drbg_instantiate(drbg, data->addtl, coreref, pr); | 1835 | /* linked list variable is now local to allow modification */ |
1836 | drbg_string_fill(&seed_string, data->addtl->buf, | ||
1837 | data->addtl->len); | ||
1838 | return drbg_instantiate(drbg, &seed_string, coreref, pr); | ||
1824 | } | 1839 | } |
1825 | } | 1840 | } |
1826 | 1841 | ||
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h index b507c5b6020a..4065dfca146a 100644 --- a/include/crypto/drbg.h +++ b/include/crypto/drbg.h | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <crypto/rng.h> | 50 | #include <crypto/rng.h> |
51 | #include <linux/fips.h> | 51 | #include <linux/fips.h> |
52 | #include <linux/spinlock.h> | 52 | #include <linux/spinlock.h> |
53 | #include <linux/list.h> | ||
53 | 54 | ||
54 | /* | 55 | /* |
55 | * Concatenation Helper and string operation helper | 56 | * Concatenation Helper and string operation helper |
@@ -64,7 +65,7 @@ | |||
64 | struct drbg_string { | 65 | struct drbg_string { |
65 | const unsigned char *buf; | 66 | const unsigned char *buf; |
66 | size_t len; | 67 | size_t len; |
67 | struct drbg_string *next; | 68 | struct list_head list; |
68 | }; | 69 | }; |
69 | 70 | ||
70 | static inline void drbg_string_fill(struct drbg_string *string, | 71 | static inline void drbg_string_fill(struct drbg_string *string, |
@@ -72,7 +73,7 @@ static inline void drbg_string_fill(struct drbg_string *string, | |||
72 | { | 73 | { |
73 | string->buf = buf; | 74 | string->buf = buf; |
74 | string->len = len; | 75 | string->len = len; |
75 | string->next = NULL; | 76 | INIT_LIST_HEAD(&string->list); |
76 | } | 77 | } |
77 | 78 | ||
78 | struct drbg_state; | 79 | struct drbg_state; |
@@ -97,7 +98,7 @@ struct drbg_core { | |||
97 | }; | 98 | }; |
98 | 99 | ||
99 | struct drbg_state_ops { | 100 | struct drbg_state_ops { |
100 | int (*update)(struct drbg_state *drbg, struct drbg_string *seed, | 101 | int (*update)(struct drbg_state *drbg, struct list_head *seed, |
101 | int reseed); | 102 | int reseed); |
102 | int (*generate)(struct drbg_state *drbg, | 103 | int (*generate)(struct drbg_state *drbg, |
103 | unsigned char *buf, unsigned int buflen, | 104 | unsigned char *buf, unsigned int buflen, |