aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2019-04-12 00:57:38 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2019-04-18 10:15:03 -0400
commitf2bb770ae89641be0e80b15f12c134689c770ca7 (patch)
tree7cb757430c9681f8bb551e626b3e0a16523db98d /crypto
parent951d13328a8a366a3bc2f9321636ee09e6f61c99 (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.c128
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
129struct alg_test_desc { 129struct 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 */
751static 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 */
768static 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" */
792static 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
748static char *generate_random_sgl_divisions(struct test_sg_division *divs, 834static 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 */
1001static 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
1025too_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 */
903static void crypto_disable_simd_for_test(void) 1031static void crypto_disable_simd_for_test(void)
904{ 1032{