diff options
author | Eric Biggers <ebiggers@google.com> | 2019-02-01 02:51:45 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2019-02-08 02:30:09 -0500 |
commit | 25f9dddb928aee83effd18d6d3093f6c0beb65a4 (patch) | |
tree | 529b12627e607b3d51f979213f91d933a8e5c443 | |
parent | 5b2706a4d45987dfa9102f9529a8436392526111 (diff) |
crypto: testmgr - implement random testvec_config generation
Add functions that generate a random testvec_config, in preparation for
using it for randomized fuzz tests.
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | crypto/testmgr.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 99f84160cb1d..ca3fd5f0c094 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/fips.h> | 28 | #include <linux/fips.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/once.h> | 30 | #include <linux/once.h> |
31 | #include <linux/random.h> | ||
31 | #include <linux/scatterlist.h> | 32 | #include <linux/scatterlist.h> |
32 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
33 | #include <linux/string.h> | 34 | #include <linux/string.h> |
@@ -603,6 +604,122 @@ static int build_cipher_test_sglists(struct cipher_test_sglists *tsgls, | |||
603 | alignmask, dst_total_len, NULL, NULL); | 604 | alignmask, dst_total_len, NULL, NULL); |
604 | } | 605 | } |
605 | 606 | ||
607 | #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS | ||
608 | static char *generate_random_sgl_divisions(struct test_sg_division *divs, | ||
609 | size_t max_divs, char *p, char *end, | ||
610 | bool gen_flushes) | ||
611 | { | ||
612 | struct test_sg_division *div = divs; | ||
613 | unsigned int remaining = TEST_SG_TOTAL; | ||
614 | |||
615 | do { | ||
616 | unsigned int this_len; | ||
617 | |||
618 | if (div == &divs[max_divs - 1] || prandom_u32() % 2 == 0) | ||
619 | this_len = remaining; | ||
620 | else | ||
621 | this_len = 1 + (prandom_u32() % remaining); | ||
622 | div->proportion_of_total = this_len; | ||
623 | |||
624 | if (prandom_u32() % 4 == 0) | ||
625 | div->offset = (PAGE_SIZE - 128) + (prandom_u32() % 128); | ||
626 | else if (prandom_u32() % 2 == 0) | ||
627 | div->offset = prandom_u32() % 32; | ||
628 | else | ||
629 | div->offset = prandom_u32() % PAGE_SIZE; | ||
630 | if (prandom_u32() % 8 == 0) | ||
631 | div->offset_relative_to_alignmask = true; | ||
632 | |||
633 | div->flush_type = FLUSH_TYPE_NONE; | ||
634 | if (gen_flushes) { | ||
635 | switch (prandom_u32() % 4) { | ||
636 | case 0: | ||
637 | div->flush_type = FLUSH_TYPE_REIMPORT; | ||
638 | break; | ||
639 | case 1: | ||
640 | div->flush_type = FLUSH_TYPE_FLUSH; | ||
641 | break; | ||
642 | } | ||
643 | } | ||
644 | |||
645 | BUILD_BUG_ON(TEST_SG_TOTAL != 10000); /* for "%u.%u%%" */ | ||
646 | p += scnprintf(p, end - p, "%s%u.%u%%@%s+%u%s", | ||
647 | div->flush_type == FLUSH_TYPE_NONE ? "" : | ||
648 | div->flush_type == FLUSH_TYPE_FLUSH ? | ||
649 | "<flush> " : "<reimport> ", | ||
650 | this_len / 100, this_len % 100, | ||
651 | div->offset_relative_to_alignmask ? | ||
652 | "alignmask" : "", | ||
653 | div->offset, this_len == remaining ? "" : ", "); | ||
654 | remaining -= this_len; | ||
655 | div++; | ||
656 | } while (remaining); | ||
657 | |||
658 | return p; | ||
659 | } | ||
660 | |||
661 | /* Generate a random testvec_config for fuzz testing */ | ||
662 | static void generate_random_testvec_config(struct testvec_config *cfg, | ||
663 | char *name, size_t max_namelen) | ||
664 | { | ||
665 | char *p = name; | ||
666 | char * const end = name + max_namelen; | ||
667 | |||
668 | memset(cfg, 0, sizeof(*cfg)); | ||
669 | |||
670 | cfg->name = name; | ||
671 | |||
672 | p += scnprintf(p, end - p, "random:"); | ||
673 | |||
674 | if (prandom_u32() % 2 == 0) { | ||
675 | cfg->inplace = true; | ||
676 | p += scnprintf(p, end - p, " inplace"); | ||
677 | } | ||
678 | |||
679 | if (prandom_u32() % 2 == 0) { | ||
680 | cfg->req_flags |= CRYPTO_TFM_REQ_MAY_SLEEP; | ||
681 | p += scnprintf(p, end - p, " may_sleep"); | ||
682 | } | ||
683 | |||
684 | switch (prandom_u32() % 4) { | ||
685 | case 0: | ||
686 | cfg->finalization_type = FINALIZATION_TYPE_FINAL; | ||
687 | p += scnprintf(p, end - p, " use_final"); | ||
688 | break; | ||
689 | case 1: | ||
690 | cfg->finalization_type = FINALIZATION_TYPE_FINUP; | ||
691 | p += scnprintf(p, end - p, " use_finup"); | ||
692 | break; | ||
693 | default: | ||
694 | cfg->finalization_type = FINALIZATION_TYPE_DIGEST; | ||
695 | p += scnprintf(p, end - p, " use_digest"); | ||
696 | break; | ||
697 | } | ||
698 | |||
699 | p += scnprintf(p, end - p, " src_divs=["); | ||
700 | p = generate_random_sgl_divisions(cfg->src_divs, | ||
701 | ARRAY_SIZE(cfg->src_divs), p, end, | ||
702 | (cfg->finalization_type != | ||
703 | FINALIZATION_TYPE_DIGEST)); | ||
704 | p += scnprintf(p, end - p, "]"); | ||
705 | |||
706 | if (!cfg->inplace && prandom_u32() % 2 == 0) { | ||
707 | p += scnprintf(p, end - p, " dst_divs=["); | ||
708 | p = generate_random_sgl_divisions(cfg->dst_divs, | ||
709 | ARRAY_SIZE(cfg->dst_divs), | ||
710 | p, end, false); | ||
711 | p += scnprintf(p, end - p, "]"); | ||
712 | } | ||
713 | |||
714 | if (prandom_u32() % 2 == 0) { | ||
715 | cfg->iv_offset = 1 + (prandom_u32() % MAX_ALGAPI_ALIGNMASK); | ||
716 | p += scnprintf(p, end - p, " iv_offset=%u", cfg->iv_offset); | ||
717 | } | ||
718 | |||
719 | WARN_ON_ONCE(!valid_testvec_config(cfg)); | ||
720 | } | ||
721 | #endif /* CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ | ||
722 | |||
606 | static int ahash_guard_result(char *result, char c, int size) | 723 | static int ahash_guard_result(char *result, char c, int size) |
607 | { | 724 | { |
608 | int i; | 725 | int i; |