diff options
author | Eric Biggers <ebiggers@google.com> | 2019-04-12 00:57:38 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2019-04-18 10:15:03 -0400 |
commit | f2bb770ae89641be0e80b15f12c134689c770ca7 (patch) | |
tree | 7cb757430c9681f8bb551e626b3e0a16523db98d /crypto | |
parent | 951d13328a8a366a3bc2f9321636ee09e6f61c99 (diff) |
crypto: testmgr - add helpers for fuzzing against generic implementation
Add some helper functions in preparation for fuzz testing algorithms
against their generic implementation.
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/testmgr.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 834eea50dfa7..feb3ff27e0b3 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c | |||
@@ -128,6 +128,7 @@ struct kpp_test_suite { | |||
128 | 128 | ||
129 | struct alg_test_desc { | 129 | struct alg_test_desc { |
130 | const char *alg; | 130 | const char *alg; |
131 | const char *generic_driver; | ||
131 | int (*test)(const struct alg_test_desc *desc, const char *driver, | 132 | int (*test)(const struct alg_test_desc *desc, const char *driver, |
132 | u32 type, u32 mask); | 133 | u32 type, u32 mask); |
133 | int fips_allowed; /* set if alg is allowed in fips mode */ | 134 | int fips_allowed; /* set if alg is allowed in fips mode */ |
@@ -745,6 +746,91 @@ static int build_cipher_test_sglists(struct cipher_test_sglists *tsgls, | |||
745 | } | 746 | } |
746 | 747 | ||
747 | #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS | 748 | #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS |
749 | |||
750 | /* Generate a random length in range [0, max_len], but prefer smaller values */ | ||
751 | static unsigned int generate_random_length(unsigned int max_len) | ||
752 | { | ||
753 | unsigned int len = prandom_u32() % (max_len + 1); | ||
754 | |||
755 | switch (prandom_u32() % 4) { | ||
756 | case 0: | ||
757 | return len % 64; | ||
758 | case 1: | ||
759 | return len % 256; | ||
760 | case 2: | ||
761 | return len % 1024; | ||
762 | default: | ||
763 | return len; | ||
764 | } | ||
765 | } | ||
766 | |||
767 | /* Sometimes make some random changes to the given data buffer */ | ||
768 | static void mutate_buffer(u8 *buf, size_t count) | ||
769 | { | ||
770 | size_t num_flips; | ||
771 | size_t i; | ||
772 | size_t pos; | ||
773 | |||
774 | /* Sometimes flip some bits */ | ||
775 | if (prandom_u32() % 4 == 0) { | ||
776 | num_flips = min_t(size_t, 1 << (prandom_u32() % 8), count * 8); | ||
777 | for (i = 0; i < num_flips; i++) { | ||
778 | pos = prandom_u32() % (count * 8); | ||
779 | buf[pos / 8] ^= 1 << (pos % 8); | ||
780 | } | ||
781 | } | ||
782 | |||
783 | /* Sometimes flip some bytes */ | ||
784 | if (prandom_u32() % 4 == 0) { | ||
785 | num_flips = min_t(size_t, 1 << (prandom_u32() % 8), count); | ||
786 | for (i = 0; i < num_flips; i++) | ||
787 | buf[prandom_u32() % count] ^= 0xff; | ||
788 | } | ||
789 | } | ||
790 | |||
791 | /* Randomly generate 'count' bytes, but sometimes make them "interesting" */ | ||
792 | static void generate_random_bytes(u8 *buf, size_t count) | ||
793 | { | ||
794 | u8 b; | ||
795 | u8 increment; | ||
796 | size_t i; | ||
797 | |||
798 | if (count == 0) | ||
799 | return; | ||
800 | |||
801 | switch (prandom_u32() % 8) { /* Choose a generation strategy */ | ||
802 | case 0: | ||
803 | case 1: | ||
804 | /* All the same byte, plus optional mutations */ | ||
805 | switch (prandom_u32() % 4) { | ||
806 | case 0: | ||
807 | b = 0x00; | ||
808 | break; | ||
809 | case 1: | ||
810 | b = 0xff; | ||
811 | break; | ||
812 | default: | ||
813 | b = (u8)prandom_u32(); | ||
814 | break; | ||
815 | } | ||
816 | memset(buf, b, count); | ||
817 | mutate_buffer(buf, count); | ||
818 | break; | ||
819 | case 2: | ||
820 | /* Ascending or descending bytes, plus optional mutations */ | ||
821 | increment = (u8)prandom_u32(); | ||
822 | b = (u8)prandom_u32(); | ||
823 | for (i = 0; i < count; i++, b += increment) | ||
824 | buf[i] = b; | ||
825 | mutate_buffer(buf, count); | ||
826 | break; | ||
827 | default: | ||
828 | /* Fully random bytes */ | ||
829 | for (i = 0; i < count; i++) | ||
830 | buf[i] = (u8)prandom_u32(); | ||
831 | } | ||
832 | } | ||
833 | |||
748 | static char *generate_random_sgl_divisions(struct test_sg_division *divs, | 834 | static char *generate_random_sgl_divisions(struct test_sg_division *divs, |
749 | size_t max_divs, char *p, char *end, | 835 | size_t max_divs, char *p, char *end, |
750 | bool gen_flushes, u32 req_flags) | 836 | bool gen_flushes, u32 req_flags) |
@@ -899,6 +985,48 @@ static void crypto_reenable_simd_for_test(void) | |||
899 | __this_cpu_write(crypto_simd_disabled_for_test, false); | 985 | __this_cpu_write(crypto_simd_disabled_for_test, false); |
900 | preempt_enable(); | 986 | preempt_enable(); |
901 | } | 987 | } |
988 | |||
989 | /* | ||
990 | * Given an algorithm name, build the name of the generic implementation of that | ||
991 | * algorithm, assuming the usual naming convention. Specifically, this appends | ||
992 | * "-generic" to every part of the name that is not a template name. Examples: | ||
993 | * | ||
994 | * aes => aes-generic | ||
995 | * cbc(aes) => cbc(aes-generic) | ||
996 | * cts(cbc(aes)) => cts(cbc(aes-generic)) | ||
997 | * rfc7539(chacha20,poly1305) => rfc7539(chacha20-generic,poly1305-generic) | ||
998 | * | ||
999 | * Return: 0 on success, or -ENAMETOOLONG if the generic name would be too long | ||
1000 | */ | ||
1001 | static int build_generic_driver_name(const char *algname, | ||
1002 | char driver_name[CRYPTO_MAX_ALG_NAME]) | ||
1003 | { | ||
1004 | const char *in = algname; | ||
1005 | char *out = driver_name; | ||
1006 | size_t len = strlen(algname); | ||
1007 | |||
1008 | if (len >= CRYPTO_MAX_ALG_NAME) | ||
1009 | goto too_long; | ||
1010 | do { | ||
1011 | const char *in_saved = in; | ||
1012 | |||
1013 | while (*in && *in != '(' && *in != ')' && *in != ',') | ||
1014 | *out++ = *in++; | ||
1015 | if (*in != '(' && in > in_saved) { | ||
1016 | len += 8; | ||
1017 | if (len >= CRYPTO_MAX_ALG_NAME) | ||
1018 | goto too_long; | ||
1019 | memcpy(out, "-generic", 8); | ||
1020 | out += 8; | ||
1021 | } | ||
1022 | } while ((*out++ = *in++) != '\0'); | ||
1023 | return 0; | ||
1024 | |||
1025 | too_long: | ||
1026 | pr_err("alg: generic driver name for \"%s\" would be too long\n", | ||
1027 | algname); | ||
1028 | return -ENAMETOOLONG; | ||
1029 | } | ||
902 | #else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ | 1030 | #else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ |
903 | static void crypto_disable_simd_for_test(void) | 1031 | static void crypto_disable_simd_for_test(void) |
904 | { | 1032 | { |