diff options
Diffstat (limited to 'crypto/testmgr.c')
-rw-r--r-- | crypto/testmgr.c | 1242 |
1 files changed, 1079 insertions, 163 deletions
diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 8386038d67c7..c9e67c2bd725 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <crypto/akcipher.h> | 37 | #include <crypto/akcipher.h> |
38 | #include <crypto/kpp.h> | 38 | #include <crypto/kpp.h> |
39 | #include <crypto/acompress.h> | 39 | #include <crypto/acompress.h> |
40 | #include <crypto/internal/simd.h> | ||
40 | 41 | ||
41 | #include "internal.h" | 42 | #include "internal.h" |
42 | 43 | ||
@@ -44,6 +45,9 @@ static bool notests; | |||
44 | module_param(notests, bool, 0644); | 45 | module_param(notests, bool, 0644); |
45 | MODULE_PARM_DESC(notests, "disable crypto self-tests"); | 46 | MODULE_PARM_DESC(notests, "disable crypto self-tests"); |
46 | 47 | ||
48 | static bool panic_on_fail; | ||
49 | module_param(panic_on_fail, bool, 0444); | ||
50 | |||
47 | #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS | 51 | #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS |
48 | static bool noextratests; | 52 | static bool noextratests; |
49 | module_param(noextratests, bool, 0644); | 53 | module_param(noextratests, bool, 0644); |
@@ -52,6 +56,9 @@ MODULE_PARM_DESC(noextratests, "disable expensive crypto self-tests"); | |||
52 | static unsigned int fuzz_iterations = 100; | 56 | static unsigned int fuzz_iterations = 100; |
53 | module_param(fuzz_iterations, uint, 0644); | 57 | module_param(fuzz_iterations, uint, 0644); |
54 | MODULE_PARM_DESC(fuzz_iterations, "number of fuzz test iterations"); | 58 | MODULE_PARM_DESC(fuzz_iterations, "number of fuzz test iterations"); |
59 | |||
60 | DEFINE_PER_CPU(bool, crypto_simd_disabled_for_test); | ||
61 | EXPORT_PER_CPU_SYMBOL_GPL(crypto_simd_disabled_for_test); | ||
55 | #endif | 62 | #endif |
56 | 63 | ||
57 | #ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS | 64 | #ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS |
@@ -121,6 +128,7 @@ struct kpp_test_suite { | |||
121 | 128 | ||
122 | struct alg_test_desc { | 129 | struct alg_test_desc { |
123 | const char *alg; | 130 | const char *alg; |
131 | const char *generic_driver; | ||
124 | int (*test)(const struct alg_test_desc *desc, const char *driver, | 132 | int (*test)(const struct alg_test_desc *desc, const char *driver, |
125 | u32 type, u32 mask); | 133 | u32 type, u32 mask); |
126 | int fips_allowed; /* set if alg is allowed in fips mode */ | 134 | int fips_allowed; /* set if alg is allowed in fips mode */ |
@@ -230,12 +238,14 @@ enum finalization_type { | |||
230 | * @offset | 238 | * @offset |
231 | * @flush_type: for hashes, whether an update() should be done now vs. | 239 | * @flush_type: for hashes, whether an update() should be done now vs. |
232 | * continuing to accumulate data | 240 | * continuing to accumulate data |
241 | * @nosimd: if doing the pending update(), do it with SIMD disabled? | ||
233 | */ | 242 | */ |
234 | struct test_sg_division { | 243 | struct test_sg_division { |
235 | unsigned int proportion_of_total; | 244 | unsigned int proportion_of_total; |
236 | unsigned int offset; | 245 | unsigned int offset; |
237 | bool offset_relative_to_alignmask; | 246 | bool offset_relative_to_alignmask; |
238 | enum flush_type flush_type; | 247 | enum flush_type flush_type; |
248 | bool nosimd; | ||
239 | }; | 249 | }; |
240 | 250 | ||
241 | /** | 251 | /** |
@@ -255,6 +265,7 @@ struct test_sg_division { | |||
255 | * @iv_offset_relative_to_alignmask: if true, add the algorithm's alignmask to | 265 | * @iv_offset_relative_to_alignmask: if true, add the algorithm's alignmask to |
256 | * the @iv_offset | 266 | * the @iv_offset |
257 | * @finalization_type: what finalization function to use for hashes | 267 | * @finalization_type: what finalization function to use for hashes |
268 | * @nosimd: execute with SIMD disabled? Requires !CRYPTO_TFM_REQ_MAY_SLEEP. | ||
258 | */ | 269 | */ |
259 | struct testvec_config { | 270 | struct testvec_config { |
260 | const char *name; | 271 | const char *name; |
@@ -265,6 +276,7 @@ struct testvec_config { | |||
265 | unsigned int iv_offset; | 276 | unsigned int iv_offset; |
266 | bool iv_offset_relative_to_alignmask; | 277 | bool iv_offset_relative_to_alignmask; |
267 | enum finalization_type finalization_type; | 278 | enum finalization_type finalization_type; |
279 | bool nosimd; | ||
268 | }; | 280 | }; |
269 | 281 | ||
270 | #define TESTVEC_CONFIG_NAMELEN 192 | 282 | #define TESTVEC_CONFIG_NAMELEN 192 |
@@ -416,8 +428,11 @@ static unsigned int count_test_sg_divisions(const struct test_sg_division *divs) | |||
416 | return ndivs; | 428 | return ndivs; |
417 | } | 429 | } |
418 | 430 | ||
431 | #define SGDIVS_HAVE_FLUSHES BIT(0) | ||
432 | #define SGDIVS_HAVE_NOSIMD BIT(1) | ||
433 | |||
419 | static bool valid_sg_divisions(const struct test_sg_division *divs, | 434 | static bool valid_sg_divisions(const struct test_sg_division *divs, |
420 | unsigned int count, bool *any_flushes_ret) | 435 | unsigned int count, int *flags_ret) |
421 | { | 436 | { |
422 | unsigned int total = 0; | 437 | unsigned int total = 0; |
423 | unsigned int i; | 438 | unsigned int i; |
@@ -428,7 +443,9 @@ static bool valid_sg_divisions(const struct test_sg_division *divs, | |||
428 | return false; | 443 | return false; |
429 | total += divs[i].proportion_of_total; | 444 | total += divs[i].proportion_of_total; |
430 | if (divs[i].flush_type != FLUSH_TYPE_NONE) | 445 | if (divs[i].flush_type != FLUSH_TYPE_NONE) |
431 | *any_flushes_ret = true; | 446 | *flags_ret |= SGDIVS_HAVE_FLUSHES; |
447 | if (divs[i].nosimd) | ||
448 | *flags_ret |= SGDIVS_HAVE_NOSIMD; | ||
432 | } | 449 | } |
433 | return total == TEST_SG_TOTAL && | 450 | return total == TEST_SG_TOTAL && |
434 | memchr_inv(&divs[i], 0, (count - i) * sizeof(divs[0])) == NULL; | 451 | memchr_inv(&divs[i], 0, (count - i) * sizeof(divs[0])) == NULL; |
@@ -441,19 +458,18 @@ static bool valid_sg_divisions(const struct test_sg_division *divs, | |||
441 | */ | 458 | */ |
442 | static bool valid_testvec_config(const struct testvec_config *cfg) | 459 | static bool valid_testvec_config(const struct testvec_config *cfg) |
443 | { | 460 | { |
444 | bool any_flushes = false; | 461 | int flags = 0; |
445 | 462 | ||
446 | if (cfg->name == NULL) | 463 | if (cfg->name == NULL) |
447 | return false; | 464 | return false; |
448 | 465 | ||
449 | if (!valid_sg_divisions(cfg->src_divs, ARRAY_SIZE(cfg->src_divs), | 466 | if (!valid_sg_divisions(cfg->src_divs, ARRAY_SIZE(cfg->src_divs), |
450 | &any_flushes)) | 467 | &flags)) |
451 | return false; | 468 | return false; |
452 | 469 | ||
453 | if (cfg->dst_divs[0].proportion_of_total) { | 470 | if (cfg->dst_divs[0].proportion_of_total) { |
454 | if (!valid_sg_divisions(cfg->dst_divs, | 471 | if (!valid_sg_divisions(cfg->dst_divs, |
455 | ARRAY_SIZE(cfg->dst_divs), | 472 | ARRAY_SIZE(cfg->dst_divs), &flags)) |
456 | &any_flushes)) | ||
457 | return false; | 473 | return false; |
458 | } else { | 474 | } else { |
459 | if (memchr_inv(cfg->dst_divs, 0, sizeof(cfg->dst_divs))) | 475 | if (memchr_inv(cfg->dst_divs, 0, sizeof(cfg->dst_divs))) |
@@ -466,7 +482,12 @@ static bool valid_testvec_config(const struct testvec_config *cfg) | |||
466 | MAX_ALGAPI_ALIGNMASK + 1) | 482 | MAX_ALGAPI_ALIGNMASK + 1) |
467 | return false; | 483 | return false; |
468 | 484 | ||
469 | if (any_flushes && cfg->finalization_type == FINALIZATION_TYPE_DIGEST) | 485 | if ((flags & (SGDIVS_HAVE_FLUSHES | SGDIVS_HAVE_NOSIMD)) && |
486 | cfg->finalization_type == FINALIZATION_TYPE_DIGEST) | ||
487 | return false; | ||
488 | |||
489 | if ((cfg->nosimd || (flags & SGDIVS_HAVE_NOSIMD)) && | ||
490 | (cfg->req_flags & CRYPTO_TFM_REQ_MAY_SLEEP)) | ||
470 | return false; | 491 | return false; |
471 | 492 | ||
472 | return true; | 493 | return true; |
@@ -725,15 +746,101 @@ static int build_cipher_test_sglists(struct cipher_test_sglists *tsgls, | |||
725 | } | 746 | } |
726 | 747 | ||
727 | #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 | |||
728 | static char *generate_random_sgl_divisions(struct test_sg_division *divs, | 834 | static char *generate_random_sgl_divisions(struct test_sg_division *divs, |
729 | size_t max_divs, char *p, char *end, | 835 | size_t max_divs, char *p, char *end, |
730 | bool gen_flushes) | 836 | bool gen_flushes, u32 req_flags) |
731 | { | 837 | { |
732 | struct test_sg_division *div = divs; | 838 | struct test_sg_division *div = divs; |
733 | unsigned int remaining = TEST_SG_TOTAL; | 839 | unsigned int remaining = TEST_SG_TOTAL; |
734 | 840 | ||
735 | do { | 841 | do { |
736 | unsigned int this_len; | 842 | unsigned int this_len; |
843 | const char *flushtype_str; | ||
737 | 844 | ||
738 | if (div == &divs[max_divs - 1] || prandom_u32() % 2 == 0) | 845 | if (div == &divs[max_divs - 1] || prandom_u32() % 2 == 0) |
739 | this_len = remaining; | 846 | this_len = remaining; |
@@ -762,11 +869,31 @@ static char *generate_random_sgl_divisions(struct test_sg_division *divs, | |||
762 | } | 869 | } |
763 | } | 870 | } |
764 | 871 | ||
872 | if (div->flush_type != FLUSH_TYPE_NONE && | ||
873 | !(req_flags & CRYPTO_TFM_REQ_MAY_SLEEP) && | ||
874 | prandom_u32() % 2 == 0) | ||
875 | div->nosimd = true; | ||
876 | |||
877 | switch (div->flush_type) { | ||
878 | case FLUSH_TYPE_FLUSH: | ||
879 | if (div->nosimd) | ||
880 | flushtype_str = "<flush,nosimd>"; | ||
881 | else | ||
882 | flushtype_str = "<flush>"; | ||
883 | break; | ||
884 | case FLUSH_TYPE_REIMPORT: | ||
885 | if (div->nosimd) | ||
886 | flushtype_str = "<reimport,nosimd>"; | ||
887 | else | ||
888 | flushtype_str = "<reimport>"; | ||
889 | break; | ||
890 | default: | ||
891 | flushtype_str = ""; | ||
892 | break; | ||
893 | } | ||
894 | |||
765 | BUILD_BUG_ON(TEST_SG_TOTAL != 10000); /* for "%u.%u%%" */ | 895 | BUILD_BUG_ON(TEST_SG_TOTAL != 10000); /* for "%u.%u%%" */ |
766 | p += scnprintf(p, end - p, "%s%u.%u%%@%s+%u%s", | 896 | p += scnprintf(p, end - p, "%s%u.%u%%@%s+%u%s", flushtype_str, |
767 | div->flush_type == FLUSH_TYPE_NONE ? "" : | ||
768 | div->flush_type == FLUSH_TYPE_FLUSH ? | ||
769 | "<flush> " : "<reimport> ", | ||
770 | this_len / 100, this_len % 100, | 897 | this_len / 100, this_len % 100, |
771 | div->offset_relative_to_alignmask ? | 898 | div->offset_relative_to_alignmask ? |
772 | "alignmask" : "", | 899 | "alignmask" : "", |
@@ -816,18 +943,26 @@ static void generate_random_testvec_config(struct testvec_config *cfg, | |||
816 | break; | 943 | break; |
817 | } | 944 | } |
818 | 945 | ||
946 | if (!(cfg->req_flags & CRYPTO_TFM_REQ_MAY_SLEEP) && | ||
947 | prandom_u32() % 2 == 0) { | ||
948 | cfg->nosimd = true; | ||
949 | p += scnprintf(p, end - p, " nosimd"); | ||
950 | } | ||
951 | |||
819 | p += scnprintf(p, end - p, " src_divs=["); | 952 | p += scnprintf(p, end - p, " src_divs=["); |
820 | p = generate_random_sgl_divisions(cfg->src_divs, | 953 | p = generate_random_sgl_divisions(cfg->src_divs, |
821 | ARRAY_SIZE(cfg->src_divs), p, end, | 954 | ARRAY_SIZE(cfg->src_divs), p, end, |
822 | (cfg->finalization_type != | 955 | (cfg->finalization_type != |
823 | FINALIZATION_TYPE_DIGEST)); | 956 | FINALIZATION_TYPE_DIGEST), |
957 | cfg->req_flags); | ||
824 | p += scnprintf(p, end - p, "]"); | 958 | p += scnprintf(p, end - p, "]"); |
825 | 959 | ||
826 | if (!cfg->inplace && prandom_u32() % 2 == 0) { | 960 | if (!cfg->inplace && prandom_u32() % 2 == 0) { |
827 | p += scnprintf(p, end - p, " dst_divs=["); | 961 | p += scnprintf(p, end - p, " dst_divs=["); |
828 | p = generate_random_sgl_divisions(cfg->dst_divs, | 962 | p = generate_random_sgl_divisions(cfg->dst_divs, |
829 | ARRAY_SIZE(cfg->dst_divs), | 963 | ARRAY_SIZE(cfg->dst_divs), |
830 | p, end, false); | 964 | p, end, false, |
965 | cfg->req_flags); | ||
831 | p += scnprintf(p, end - p, "]"); | 966 | p += scnprintf(p, end - p, "]"); |
832 | } | 967 | } |
833 | 968 | ||
@@ -838,21 +973,100 @@ static void generate_random_testvec_config(struct testvec_config *cfg, | |||
838 | 973 | ||
839 | WARN_ON_ONCE(!valid_testvec_config(cfg)); | 974 | WARN_ON_ONCE(!valid_testvec_config(cfg)); |
840 | } | 975 | } |
841 | #endif /* CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ | 976 | |
977 | static void crypto_disable_simd_for_test(void) | ||
978 | { | ||
979 | preempt_disable(); | ||
980 | __this_cpu_write(crypto_simd_disabled_for_test, true); | ||
981 | } | ||
982 | |||
983 | static void crypto_reenable_simd_for_test(void) | ||
984 | { | ||
985 | __this_cpu_write(crypto_simd_disabled_for_test, false); | ||
986 | preempt_enable(); | ||
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 | } | ||
1030 | #else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ | ||
1031 | static void crypto_disable_simd_for_test(void) | ||
1032 | { | ||
1033 | } | ||
1034 | |||
1035 | static void crypto_reenable_simd_for_test(void) | ||
1036 | { | ||
1037 | } | ||
1038 | #endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ | ||
1039 | |||
1040 | static int do_ahash_op(int (*op)(struct ahash_request *req), | ||
1041 | struct ahash_request *req, | ||
1042 | struct crypto_wait *wait, bool nosimd) | ||
1043 | { | ||
1044 | int err; | ||
1045 | |||
1046 | if (nosimd) | ||
1047 | crypto_disable_simd_for_test(); | ||
1048 | |||
1049 | err = op(req); | ||
1050 | |||
1051 | if (nosimd) | ||
1052 | crypto_reenable_simd_for_test(); | ||
1053 | |||
1054 | return crypto_wait_req(err, wait); | ||
1055 | } | ||
842 | 1056 | ||
843 | static int check_nonfinal_hash_op(const char *op, int err, | 1057 | static int check_nonfinal_hash_op(const char *op, int err, |
844 | u8 *result, unsigned int digestsize, | 1058 | u8 *result, unsigned int digestsize, |
845 | const char *driver, unsigned int vec_num, | 1059 | const char *driver, const char *vec_name, |
846 | const struct testvec_config *cfg) | 1060 | const struct testvec_config *cfg) |
847 | { | 1061 | { |
848 | if (err) { | 1062 | if (err) { |
849 | pr_err("alg: hash: %s %s() failed with err %d on test vector %u, cfg=\"%s\"\n", | 1063 | pr_err("alg: hash: %s %s() failed with err %d on test vector %s, cfg=\"%s\"\n", |
850 | driver, op, err, vec_num, cfg->name); | 1064 | driver, op, err, vec_name, cfg->name); |
851 | return err; | 1065 | return err; |
852 | } | 1066 | } |
853 | if (!testmgr_is_poison(result, digestsize)) { | 1067 | if (!testmgr_is_poison(result, digestsize)) { |
854 | pr_err("alg: hash: %s %s() used result buffer on test vector %u, cfg=\"%s\"\n", | 1068 | pr_err("alg: hash: %s %s() used result buffer on test vector %s, cfg=\"%s\"\n", |
855 | driver, op, vec_num, cfg->name); | 1069 | driver, op, vec_name, cfg->name); |
856 | return -EINVAL; | 1070 | return -EINVAL; |
857 | } | 1071 | } |
858 | return 0; | 1072 | return 0; |
@@ -860,7 +1074,7 @@ static int check_nonfinal_hash_op(const char *op, int err, | |||
860 | 1074 | ||
861 | static int test_hash_vec_cfg(const char *driver, | 1075 | static int test_hash_vec_cfg(const char *driver, |
862 | const struct hash_testvec *vec, | 1076 | const struct hash_testvec *vec, |
863 | unsigned int vec_num, | 1077 | const char *vec_name, |
864 | const struct testvec_config *cfg, | 1078 | const struct testvec_config *cfg, |
865 | struct ahash_request *req, | 1079 | struct ahash_request *req, |
866 | struct test_sglist *tsgl, | 1080 | struct test_sglist *tsgl, |
@@ -885,11 +1099,18 @@ static int test_hash_vec_cfg(const char *driver, | |||
885 | if (vec->ksize) { | 1099 | if (vec->ksize) { |
886 | err = crypto_ahash_setkey(tfm, vec->key, vec->ksize); | 1100 | err = crypto_ahash_setkey(tfm, vec->key, vec->ksize); |
887 | if (err) { | 1101 | if (err) { |
888 | pr_err("alg: hash: %s setkey failed with err %d on test vector %u; flags=%#x\n", | 1102 | if (err == vec->setkey_error) |
889 | driver, err, vec_num, | 1103 | return 0; |
1104 | pr_err("alg: hash: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n", | ||
1105 | driver, vec_name, vec->setkey_error, err, | ||
890 | crypto_ahash_get_flags(tfm)); | 1106 | crypto_ahash_get_flags(tfm)); |
891 | return err; | 1107 | return err; |
892 | } | 1108 | } |
1109 | if (vec->setkey_error) { | ||
1110 | pr_err("alg: hash: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n", | ||
1111 | driver, vec_name, vec->setkey_error); | ||
1112 | return -EINVAL; | ||
1113 | } | ||
893 | } | 1114 | } |
894 | 1115 | ||
895 | /* Build the scatterlist for the source data */ | 1116 | /* Build the scatterlist for the source data */ |
@@ -899,8 +1120,8 @@ static int test_hash_vec_cfg(const char *driver, | |||
899 | err = build_test_sglist(tsgl, cfg->src_divs, alignmask, vec->psize, | 1120 | err = build_test_sglist(tsgl, cfg->src_divs, alignmask, vec->psize, |
900 | &input, divs); | 1121 | &input, divs); |
901 | if (err) { | 1122 | if (err) { |
902 | pr_err("alg: hash: %s: error preparing scatterlist for test vector %u, cfg=\"%s\"\n", | 1123 | pr_err("alg: hash: %s: error preparing scatterlist for test vector %s, cfg=\"%s\"\n", |
903 | driver, vec_num, cfg->name); | 1124 | driver, vec_name, cfg->name); |
904 | return err; | 1125 | return err; |
905 | } | 1126 | } |
906 | 1127 | ||
@@ -909,17 +1130,26 @@ static int test_hash_vec_cfg(const char *driver, | |||
909 | testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm)); | 1130 | testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm)); |
910 | testmgr_poison(result, digestsize + TESTMGR_POISON_LEN); | 1131 | testmgr_poison(result, digestsize + TESTMGR_POISON_LEN); |
911 | 1132 | ||
912 | if (cfg->finalization_type == FINALIZATION_TYPE_DIGEST) { | 1133 | if (cfg->finalization_type == FINALIZATION_TYPE_DIGEST || |
1134 | vec->digest_error) { | ||
913 | /* Just using digest() */ | 1135 | /* Just using digest() */ |
914 | ahash_request_set_callback(req, req_flags, crypto_req_done, | 1136 | ahash_request_set_callback(req, req_flags, crypto_req_done, |
915 | &wait); | 1137 | &wait); |
916 | ahash_request_set_crypt(req, tsgl->sgl, result, vec->psize); | 1138 | ahash_request_set_crypt(req, tsgl->sgl, result, vec->psize); |
917 | err = crypto_wait_req(crypto_ahash_digest(req), &wait); | 1139 | err = do_ahash_op(crypto_ahash_digest, req, &wait, cfg->nosimd); |
918 | if (err) { | 1140 | if (err) { |
919 | pr_err("alg: hash: %s digest() failed with err %d on test vector %u, cfg=\"%s\"\n", | 1141 | if (err == vec->digest_error) |
920 | driver, err, vec_num, cfg->name); | 1142 | return 0; |
1143 | pr_err("alg: hash: %s digest() failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n", | ||
1144 | driver, vec_name, vec->digest_error, err, | ||
1145 | cfg->name); | ||
921 | return err; | 1146 | return err; |
922 | } | 1147 | } |
1148 | if (vec->digest_error) { | ||
1149 | pr_err("alg: hash: %s digest() unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n", | ||
1150 | driver, vec_name, vec->digest_error, cfg->name); | ||
1151 | return -EINVAL; | ||
1152 | } | ||
923 | goto result_ready; | 1153 | goto result_ready; |
924 | } | 1154 | } |
925 | 1155 | ||
@@ -927,9 +1157,9 @@ static int test_hash_vec_cfg(const char *driver, | |||
927 | 1157 | ||
928 | ahash_request_set_callback(req, req_flags, crypto_req_done, &wait); | 1158 | ahash_request_set_callback(req, req_flags, crypto_req_done, &wait); |
929 | ahash_request_set_crypt(req, NULL, result, 0); | 1159 | ahash_request_set_crypt(req, NULL, result, 0); |
930 | err = crypto_wait_req(crypto_ahash_init(req), &wait); | 1160 | err = do_ahash_op(crypto_ahash_init, req, &wait, cfg->nosimd); |
931 | err = check_nonfinal_hash_op("init", err, result, digestsize, | 1161 | err = check_nonfinal_hash_op("init", err, result, digestsize, |
932 | driver, vec_num, cfg); | 1162 | driver, vec_name, cfg); |
933 | if (err) | 1163 | if (err) |
934 | return err; | 1164 | return err; |
935 | 1165 | ||
@@ -943,10 +1173,11 @@ static int test_hash_vec_cfg(const char *driver, | |||
943 | crypto_req_done, &wait); | 1173 | crypto_req_done, &wait); |
944 | ahash_request_set_crypt(req, pending_sgl, result, | 1174 | ahash_request_set_crypt(req, pending_sgl, result, |
945 | pending_len); | 1175 | pending_len); |
946 | err = crypto_wait_req(crypto_ahash_update(req), &wait); | 1176 | err = do_ahash_op(crypto_ahash_update, req, &wait, |
1177 | divs[i]->nosimd); | ||
947 | err = check_nonfinal_hash_op("update", err, | 1178 | err = check_nonfinal_hash_op("update", err, |
948 | result, digestsize, | 1179 | result, digestsize, |
949 | driver, vec_num, cfg); | 1180 | driver, vec_name, cfg); |
950 | if (err) | 1181 | if (err) |
951 | return err; | 1182 | return err; |
952 | pending_sgl = NULL; | 1183 | pending_sgl = NULL; |
@@ -959,13 +1190,13 @@ static int test_hash_vec_cfg(const char *driver, | |||
959 | err = crypto_ahash_export(req, hashstate); | 1190 | err = crypto_ahash_export(req, hashstate); |
960 | err = check_nonfinal_hash_op("export", err, | 1191 | err = check_nonfinal_hash_op("export", err, |
961 | result, digestsize, | 1192 | result, digestsize, |
962 | driver, vec_num, cfg); | 1193 | driver, vec_name, cfg); |
963 | if (err) | 1194 | if (err) |
964 | return err; | 1195 | return err; |
965 | if (!testmgr_is_poison(hashstate + statesize, | 1196 | if (!testmgr_is_poison(hashstate + statesize, |
966 | TESTMGR_POISON_LEN)) { | 1197 | TESTMGR_POISON_LEN)) { |
967 | pr_err("alg: hash: %s export() overran state buffer on test vector %u, cfg=\"%s\"\n", | 1198 | pr_err("alg: hash: %s export() overran state buffer on test vector %s, cfg=\"%s\"\n", |
968 | driver, vec_num, cfg->name); | 1199 | driver, vec_name, cfg->name); |
969 | return -EOVERFLOW; | 1200 | return -EOVERFLOW; |
970 | } | 1201 | } |
971 | 1202 | ||
@@ -973,7 +1204,7 @@ static int test_hash_vec_cfg(const char *driver, | |||
973 | err = crypto_ahash_import(req, hashstate); | 1204 | err = crypto_ahash_import(req, hashstate); |
974 | err = check_nonfinal_hash_op("import", err, | 1205 | err = check_nonfinal_hash_op("import", err, |
975 | result, digestsize, | 1206 | result, digestsize, |
976 | driver, vec_num, cfg); | 1207 | driver, vec_name, cfg); |
977 | if (err) | 1208 | if (err) |
978 | return err; | 1209 | return err; |
979 | } | 1210 | } |
@@ -986,23 +1217,23 @@ static int test_hash_vec_cfg(const char *driver, | |||
986 | ahash_request_set_crypt(req, pending_sgl, result, pending_len); | 1217 | ahash_request_set_crypt(req, pending_sgl, result, pending_len); |
987 | if (cfg->finalization_type == FINALIZATION_TYPE_FINAL) { | 1218 | if (cfg->finalization_type == FINALIZATION_TYPE_FINAL) { |
988 | /* finish with update() and final() */ | 1219 | /* finish with update() and final() */ |
989 | err = crypto_wait_req(crypto_ahash_update(req), &wait); | 1220 | err = do_ahash_op(crypto_ahash_update, req, &wait, cfg->nosimd); |
990 | err = check_nonfinal_hash_op("update", err, result, digestsize, | 1221 | err = check_nonfinal_hash_op("update", err, result, digestsize, |
991 | driver, vec_num, cfg); | 1222 | driver, vec_name, cfg); |
992 | if (err) | 1223 | if (err) |
993 | return err; | 1224 | return err; |
994 | err = crypto_wait_req(crypto_ahash_final(req), &wait); | 1225 | err = do_ahash_op(crypto_ahash_final, req, &wait, cfg->nosimd); |
995 | if (err) { | 1226 | if (err) { |
996 | pr_err("alg: hash: %s final() failed with err %d on test vector %u, cfg=\"%s\"\n", | 1227 | pr_err("alg: hash: %s final() failed with err %d on test vector %s, cfg=\"%s\"\n", |
997 | driver, err, vec_num, cfg->name); | 1228 | driver, err, vec_name, cfg->name); |
998 | return err; | 1229 | return err; |
999 | } | 1230 | } |
1000 | } else { | 1231 | } else { |
1001 | /* finish with finup() */ | 1232 | /* finish with finup() */ |
1002 | err = crypto_wait_req(crypto_ahash_finup(req), &wait); | 1233 | err = do_ahash_op(crypto_ahash_finup, req, &wait, cfg->nosimd); |
1003 | if (err) { | 1234 | if (err) { |
1004 | pr_err("alg: hash: %s finup() failed with err %d on test vector %u, cfg=\"%s\"\n", | 1235 | pr_err("alg: hash: %s finup() failed with err %d on test vector %s, cfg=\"%s\"\n", |
1005 | driver, err, vec_num, cfg->name); | 1236 | driver, err, vec_name, cfg->name); |
1006 | return err; | 1237 | return err; |
1007 | } | 1238 | } |
1008 | } | 1239 | } |
@@ -1010,13 +1241,13 @@ static int test_hash_vec_cfg(const char *driver, | |||
1010 | result_ready: | 1241 | result_ready: |
1011 | /* Check that the algorithm produced the correct digest */ | 1242 | /* Check that the algorithm produced the correct digest */ |
1012 | if (memcmp(result, vec->digest, digestsize) != 0) { | 1243 | if (memcmp(result, vec->digest, digestsize) != 0) { |
1013 | pr_err("alg: hash: %s test failed (wrong result) on test vector %u, cfg=\"%s\"\n", | 1244 | pr_err("alg: hash: %s test failed (wrong result) on test vector %s, cfg=\"%s\"\n", |
1014 | driver, vec_num, cfg->name); | 1245 | driver, vec_name, cfg->name); |
1015 | return -EINVAL; | 1246 | return -EINVAL; |
1016 | } | 1247 | } |
1017 | if (!testmgr_is_poison(&result[digestsize], TESTMGR_POISON_LEN)) { | 1248 | if (!testmgr_is_poison(&result[digestsize], TESTMGR_POISON_LEN)) { |
1018 | pr_err("alg: hash: %s overran result buffer on test vector %u, cfg=\"%s\"\n", | 1249 | pr_err("alg: hash: %s overran result buffer on test vector %s, cfg=\"%s\"\n", |
1019 | driver, vec_num, cfg->name); | 1250 | driver, vec_name, cfg->name); |
1020 | return -EOVERFLOW; | 1251 | return -EOVERFLOW; |
1021 | } | 1252 | } |
1022 | 1253 | ||
@@ -1027,11 +1258,14 @@ static int test_hash_vec(const char *driver, const struct hash_testvec *vec, | |||
1027 | unsigned int vec_num, struct ahash_request *req, | 1258 | unsigned int vec_num, struct ahash_request *req, |
1028 | struct test_sglist *tsgl, u8 *hashstate) | 1259 | struct test_sglist *tsgl, u8 *hashstate) |
1029 | { | 1260 | { |
1261 | char vec_name[16]; | ||
1030 | unsigned int i; | 1262 | unsigned int i; |
1031 | int err; | 1263 | int err; |
1032 | 1264 | ||
1265 | sprintf(vec_name, "%u", vec_num); | ||
1266 | |||
1033 | for (i = 0; i < ARRAY_SIZE(default_hash_testvec_configs); i++) { | 1267 | for (i = 0; i < ARRAY_SIZE(default_hash_testvec_configs); i++) { |
1034 | err = test_hash_vec_cfg(driver, vec, vec_num, | 1268 | err = test_hash_vec_cfg(driver, vec, vec_name, |
1035 | &default_hash_testvec_configs[i], | 1269 | &default_hash_testvec_configs[i], |
1036 | req, tsgl, hashstate); | 1270 | req, tsgl, hashstate); |
1037 | if (err) | 1271 | if (err) |
@@ -1046,7 +1280,7 @@ static int test_hash_vec(const char *driver, const struct hash_testvec *vec, | |||
1046 | for (i = 0; i < fuzz_iterations; i++) { | 1280 | for (i = 0; i < fuzz_iterations; i++) { |
1047 | generate_random_testvec_config(&cfg, cfgname, | 1281 | generate_random_testvec_config(&cfg, cfgname, |
1048 | sizeof(cfgname)); | 1282 | sizeof(cfgname)); |
1049 | err = test_hash_vec_cfg(driver, vec, vec_num, &cfg, | 1283 | err = test_hash_vec_cfg(driver, vec, vec_name, &cfg, |
1050 | req, tsgl, hashstate); | 1284 | req, tsgl, hashstate); |
1051 | if (err) | 1285 | if (err) |
1052 | return err; | 1286 | return err; |
@@ -1056,9 +1290,168 @@ static int test_hash_vec(const char *driver, const struct hash_testvec *vec, | |||
1056 | return 0; | 1290 | return 0; |
1057 | } | 1291 | } |
1058 | 1292 | ||
1293 | #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS | ||
1294 | /* | ||
1295 | * Generate a hash test vector from the given implementation. | ||
1296 | * Assumes the buffers in 'vec' were already allocated. | ||
1297 | */ | ||
1298 | static void generate_random_hash_testvec(struct crypto_shash *tfm, | ||
1299 | struct hash_testvec *vec, | ||
1300 | unsigned int maxkeysize, | ||
1301 | unsigned int maxdatasize, | ||
1302 | char *name, size_t max_namelen) | ||
1303 | { | ||
1304 | SHASH_DESC_ON_STACK(desc, tfm); | ||
1305 | |||
1306 | /* Data */ | ||
1307 | vec->psize = generate_random_length(maxdatasize); | ||
1308 | generate_random_bytes((u8 *)vec->plaintext, vec->psize); | ||
1309 | |||
1310 | /* | ||
1311 | * Key: length in range [1, maxkeysize], but usually choose maxkeysize. | ||
1312 | * If algorithm is unkeyed, then maxkeysize == 0 and set ksize = 0. | ||
1313 | */ | ||
1314 | vec->setkey_error = 0; | ||
1315 | vec->ksize = 0; | ||
1316 | if (maxkeysize) { | ||
1317 | vec->ksize = maxkeysize; | ||
1318 | if (prandom_u32() % 4 == 0) | ||
1319 | vec->ksize = 1 + (prandom_u32() % maxkeysize); | ||
1320 | generate_random_bytes((u8 *)vec->key, vec->ksize); | ||
1321 | |||
1322 | vec->setkey_error = crypto_shash_setkey(tfm, vec->key, | ||
1323 | vec->ksize); | ||
1324 | /* If the key couldn't be set, no need to continue to digest. */ | ||
1325 | if (vec->setkey_error) | ||
1326 | goto done; | ||
1327 | } | ||
1328 | |||
1329 | /* Digest */ | ||
1330 | desc->tfm = tfm; | ||
1331 | vec->digest_error = crypto_shash_digest(desc, vec->plaintext, | ||
1332 | vec->psize, (u8 *)vec->digest); | ||
1333 | done: | ||
1334 | snprintf(name, max_namelen, "\"random: psize=%u ksize=%u\"", | ||
1335 | vec->psize, vec->ksize); | ||
1336 | } | ||
1337 | |||
1338 | /* | ||
1339 | * Test the hash algorithm represented by @req against the corresponding generic | ||
1340 | * implementation, if one is available. | ||
1341 | */ | ||
1342 | static int test_hash_vs_generic_impl(const char *driver, | ||
1343 | const char *generic_driver, | ||
1344 | unsigned int maxkeysize, | ||
1345 | struct ahash_request *req, | ||
1346 | struct test_sglist *tsgl, | ||
1347 | u8 *hashstate) | ||
1348 | { | ||
1349 | struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); | ||
1350 | const unsigned int digestsize = crypto_ahash_digestsize(tfm); | ||
1351 | const unsigned int blocksize = crypto_ahash_blocksize(tfm); | ||
1352 | const unsigned int maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN; | ||
1353 | const char *algname = crypto_hash_alg_common(tfm)->base.cra_name; | ||
1354 | char _generic_driver[CRYPTO_MAX_ALG_NAME]; | ||
1355 | struct crypto_shash *generic_tfm = NULL; | ||
1356 | unsigned int i; | ||
1357 | struct hash_testvec vec = { 0 }; | ||
1358 | char vec_name[64]; | ||
1359 | struct testvec_config cfg; | ||
1360 | char cfgname[TESTVEC_CONFIG_NAMELEN]; | ||
1361 | int err; | ||
1362 | |||
1363 | if (noextratests) | ||
1364 | return 0; | ||
1365 | |||
1366 | if (!generic_driver) { /* Use default naming convention? */ | ||
1367 | err = build_generic_driver_name(algname, _generic_driver); | ||
1368 | if (err) | ||
1369 | return err; | ||
1370 | generic_driver = _generic_driver; | ||
1371 | } | ||
1372 | |||
1373 | if (strcmp(generic_driver, driver) == 0) /* Already the generic impl? */ | ||
1374 | return 0; | ||
1375 | |||
1376 | generic_tfm = crypto_alloc_shash(generic_driver, 0, 0); | ||
1377 | if (IS_ERR(generic_tfm)) { | ||
1378 | err = PTR_ERR(generic_tfm); | ||
1379 | if (err == -ENOENT) { | ||
1380 | pr_warn("alg: hash: skipping comparison tests for %s because %s is unavailable\n", | ||
1381 | driver, generic_driver); | ||
1382 | return 0; | ||
1383 | } | ||
1384 | pr_err("alg: hash: error allocating %s (generic impl of %s): %d\n", | ||
1385 | generic_driver, algname, err); | ||
1386 | return err; | ||
1387 | } | ||
1388 | |||
1389 | /* Check the algorithm properties for consistency. */ | ||
1390 | |||
1391 | if (digestsize != crypto_shash_digestsize(generic_tfm)) { | ||
1392 | pr_err("alg: hash: digestsize for %s (%u) doesn't match generic impl (%u)\n", | ||
1393 | driver, digestsize, | ||
1394 | crypto_shash_digestsize(generic_tfm)); | ||
1395 | err = -EINVAL; | ||
1396 | goto out; | ||
1397 | } | ||
1398 | |||
1399 | if (blocksize != crypto_shash_blocksize(generic_tfm)) { | ||
1400 | pr_err("alg: hash: blocksize for %s (%u) doesn't match generic impl (%u)\n", | ||
1401 | driver, blocksize, crypto_shash_blocksize(generic_tfm)); | ||
1402 | err = -EINVAL; | ||
1403 | goto out; | ||
1404 | } | ||
1405 | |||
1406 | /* | ||
1407 | * Now generate test vectors using the generic implementation, and test | ||
1408 | * the other implementation against them. | ||
1409 | */ | ||
1410 | |||
1411 | vec.key = kmalloc(maxkeysize, GFP_KERNEL); | ||
1412 | vec.plaintext = kmalloc(maxdatasize, GFP_KERNEL); | ||
1413 | vec.digest = kmalloc(digestsize, GFP_KERNEL); | ||
1414 | if (!vec.key || !vec.plaintext || !vec.digest) { | ||
1415 | err = -ENOMEM; | ||
1416 | goto out; | ||
1417 | } | ||
1418 | |||
1419 | for (i = 0; i < fuzz_iterations * 8; i++) { | ||
1420 | generate_random_hash_testvec(generic_tfm, &vec, | ||
1421 | maxkeysize, maxdatasize, | ||
1422 | vec_name, sizeof(vec_name)); | ||
1423 | generate_random_testvec_config(&cfg, cfgname, sizeof(cfgname)); | ||
1424 | |||
1425 | err = test_hash_vec_cfg(driver, &vec, vec_name, &cfg, | ||
1426 | req, tsgl, hashstate); | ||
1427 | if (err) | ||
1428 | goto out; | ||
1429 | cond_resched(); | ||
1430 | } | ||
1431 | err = 0; | ||
1432 | out: | ||
1433 | kfree(vec.key); | ||
1434 | kfree(vec.plaintext); | ||
1435 | kfree(vec.digest); | ||
1436 | crypto_free_shash(generic_tfm); | ||
1437 | return err; | ||
1438 | } | ||
1439 | #else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ | ||
1440 | static int test_hash_vs_generic_impl(const char *driver, | ||
1441 | const char *generic_driver, | ||
1442 | unsigned int maxkeysize, | ||
1443 | struct ahash_request *req, | ||
1444 | struct test_sglist *tsgl, | ||
1445 | u8 *hashstate) | ||
1446 | { | ||
1447 | return 0; | ||
1448 | } | ||
1449 | #endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ | ||
1450 | |||
1059 | static int __alg_test_hash(const struct hash_testvec *vecs, | 1451 | static int __alg_test_hash(const struct hash_testvec *vecs, |
1060 | unsigned int num_vecs, const char *driver, | 1452 | unsigned int num_vecs, const char *driver, |
1061 | u32 type, u32 mask) | 1453 | u32 type, u32 mask, |
1454 | const char *generic_driver, unsigned int maxkeysize) | ||
1062 | { | 1455 | { |
1063 | struct crypto_ahash *tfm; | 1456 | struct crypto_ahash *tfm; |
1064 | struct ahash_request *req = NULL; | 1457 | struct ahash_request *req = NULL; |
@@ -1106,7 +1499,8 @@ static int __alg_test_hash(const struct hash_testvec *vecs, | |||
1106 | if (err) | 1499 | if (err) |
1107 | goto out; | 1500 | goto out; |
1108 | } | 1501 | } |
1109 | err = 0; | 1502 | err = test_hash_vs_generic_impl(driver, generic_driver, maxkeysize, req, |
1503 | tsgl, hashstate); | ||
1110 | out: | 1504 | out: |
1111 | kfree(hashstate); | 1505 | kfree(hashstate); |
1112 | if (tsgl) { | 1506 | if (tsgl) { |
@@ -1124,6 +1518,7 @@ static int alg_test_hash(const struct alg_test_desc *desc, const char *driver, | |||
1124 | const struct hash_testvec *template = desc->suite.hash.vecs; | 1518 | const struct hash_testvec *template = desc->suite.hash.vecs; |
1125 | unsigned int tcount = desc->suite.hash.count; | 1519 | unsigned int tcount = desc->suite.hash.count; |
1126 | unsigned int nr_unkeyed, nr_keyed; | 1520 | unsigned int nr_unkeyed, nr_keyed; |
1521 | unsigned int maxkeysize = 0; | ||
1127 | int err; | 1522 | int err; |
1128 | 1523 | ||
1129 | /* | 1524 | /* |
@@ -1142,23 +1537,27 @@ static int alg_test_hash(const struct alg_test_desc *desc, const char *driver, | |||
1142 | "unkeyed ones must come first\n", desc->alg); | 1537 | "unkeyed ones must come first\n", desc->alg); |
1143 | return -EINVAL; | 1538 | return -EINVAL; |
1144 | } | 1539 | } |
1540 | maxkeysize = max_t(unsigned int, maxkeysize, | ||
1541 | template[nr_unkeyed + nr_keyed].ksize); | ||
1145 | } | 1542 | } |
1146 | 1543 | ||
1147 | err = 0; | 1544 | err = 0; |
1148 | if (nr_unkeyed) { | 1545 | if (nr_unkeyed) { |
1149 | err = __alg_test_hash(template, nr_unkeyed, driver, type, mask); | 1546 | err = __alg_test_hash(template, nr_unkeyed, driver, type, mask, |
1547 | desc->generic_driver, maxkeysize); | ||
1150 | template += nr_unkeyed; | 1548 | template += nr_unkeyed; |
1151 | } | 1549 | } |
1152 | 1550 | ||
1153 | if (!err && nr_keyed) | 1551 | if (!err && nr_keyed) |
1154 | err = __alg_test_hash(template, nr_keyed, driver, type, mask); | 1552 | err = __alg_test_hash(template, nr_keyed, driver, type, mask, |
1553 | desc->generic_driver, maxkeysize); | ||
1155 | 1554 | ||
1156 | return err; | 1555 | return err; |
1157 | } | 1556 | } |
1158 | 1557 | ||
1159 | static int test_aead_vec_cfg(const char *driver, int enc, | 1558 | static int test_aead_vec_cfg(const char *driver, int enc, |
1160 | const struct aead_testvec *vec, | 1559 | const struct aead_testvec *vec, |
1161 | unsigned int vec_num, | 1560 | const char *vec_name, |
1162 | const struct testvec_config *cfg, | 1561 | const struct testvec_config *cfg, |
1163 | struct aead_request *req, | 1562 | struct aead_request *req, |
1164 | struct cipher_test_sglists *tsgls) | 1563 | struct cipher_test_sglists *tsgls) |
@@ -1175,6 +1574,7 @@ static int test_aead_vec_cfg(const char *driver, int enc, | |||
1175 | cfg->iv_offset + | 1574 | cfg->iv_offset + |
1176 | (cfg->iv_offset_relative_to_alignmask ? alignmask : 0); | 1575 | (cfg->iv_offset_relative_to_alignmask ? alignmask : 0); |
1177 | struct kvec input[2]; | 1576 | struct kvec input[2]; |
1577 | int expected_error; | ||
1178 | int err; | 1578 | int err; |
1179 | 1579 | ||
1180 | /* Set the key */ | 1580 | /* Set the key */ |
@@ -1183,26 +1583,33 @@ static int test_aead_vec_cfg(const char *driver, int enc, | |||
1183 | else | 1583 | else |
1184 | crypto_aead_clear_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); | 1584 | crypto_aead_clear_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); |
1185 | err = crypto_aead_setkey(tfm, vec->key, vec->klen); | 1585 | err = crypto_aead_setkey(tfm, vec->key, vec->klen); |
1186 | if (err) { | 1586 | if (err && err != vec->setkey_error) { |
1187 | if (vec->fail) /* expectedly failed to set key? */ | 1587 | pr_err("alg: aead: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n", |
1188 | return 0; | 1588 | driver, vec_name, vec->setkey_error, err, |
1189 | pr_err("alg: aead: %s setkey failed with err %d on test vector %u; flags=%#x\n", | 1589 | crypto_aead_get_flags(tfm)); |
1190 | driver, err, vec_num, crypto_aead_get_flags(tfm)); | ||
1191 | return err; | 1590 | return err; |
1192 | } | 1591 | } |
1193 | if (vec->fail) { | 1592 | if (!err && vec->setkey_error) { |
1194 | pr_err("alg: aead: %s setkey unexpectedly succeeded on test vector %u\n", | 1593 | pr_err("alg: aead: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n", |
1195 | driver, vec_num); | 1594 | driver, vec_name, vec->setkey_error); |
1196 | return -EINVAL; | 1595 | return -EINVAL; |
1197 | } | 1596 | } |
1198 | 1597 | ||
1199 | /* Set the authentication tag size */ | 1598 | /* Set the authentication tag size */ |
1200 | err = crypto_aead_setauthsize(tfm, authsize); | 1599 | err = crypto_aead_setauthsize(tfm, authsize); |
1201 | if (err) { | 1600 | if (err && err != vec->setauthsize_error) { |
1202 | pr_err("alg: aead: %s setauthsize failed with err %d on test vector %u\n", | 1601 | pr_err("alg: aead: %s setauthsize failed on test vector %s; expected_error=%d, actual_error=%d\n", |
1203 | driver, err, vec_num); | 1602 | driver, vec_name, vec->setauthsize_error, err); |
1204 | return err; | 1603 | return err; |
1205 | } | 1604 | } |
1605 | if (!err && vec->setauthsize_error) { | ||
1606 | pr_err("alg: aead: %s setauthsize unexpectedly succeeded on test vector %s; expected_error=%d\n", | ||
1607 | driver, vec_name, vec->setauthsize_error); | ||
1608 | return -EINVAL; | ||
1609 | } | ||
1610 | |||
1611 | if (vec->setkey_error || vec->setauthsize_error) | ||
1612 | return 0; | ||
1206 | 1613 | ||
1207 | /* The IV must be copied to a buffer, as the algorithm may modify it */ | 1614 | /* The IV must be copied to a buffer, as the algorithm may modify it */ |
1208 | if (WARN_ON(ivsize > MAX_IVLEN)) | 1615 | if (WARN_ON(ivsize > MAX_IVLEN)) |
@@ -1224,8 +1631,8 @@ static int test_aead_vec_cfg(const char *driver, int enc, | |||
1224 | vec->plen), | 1631 | vec->plen), |
1225 | input, 2); | 1632 | input, 2); |
1226 | if (err) { | 1633 | if (err) { |
1227 | pr_err("alg: aead: %s %s: error preparing scatterlists for test vector %u, cfg=\"%s\"\n", | 1634 | pr_err("alg: aead: %s %s: error preparing scatterlists for test vector %s, cfg=\"%s\"\n", |
1228 | driver, op, vec_num, cfg->name); | 1635 | driver, op, vec_name, cfg->name); |
1229 | return err; | 1636 | return err; |
1230 | } | 1637 | } |
1231 | 1638 | ||
@@ -1235,23 +1642,12 @@ static int test_aead_vec_cfg(const char *driver, int enc, | |||
1235 | aead_request_set_crypt(req, tsgls->src.sgl_ptr, tsgls->dst.sgl_ptr, | 1642 | aead_request_set_crypt(req, tsgls->src.sgl_ptr, tsgls->dst.sgl_ptr, |
1236 | enc ? vec->plen : vec->clen, iv); | 1643 | enc ? vec->plen : vec->clen, iv); |
1237 | aead_request_set_ad(req, vec->alen); | 1644 | aead_request_set_ad(req, vec->alen); |
1238 | err = crypto_wait_req(enc ? crypto_aead_encrypt(req) : | 1645 | if (cfg->nosimd) |
1239 | crypto_aead_decrypt(req), &wait); | 1646 | crypto_disable_simd_for_test(); |
1240 | 1647 | err = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req); | |
1241 | aead_request_set_tfm(req, tfm); /* TODO: get rid of this */ | 1648 | if (cfg->nosimd) |
1242 | 1649 | crypto_reenable_simd_for_test(); | |
1243 | if (err) { | 1650 | err = crypto_wait_req(err, &wait); |
1244 | if (err == -EBADMSG && vec->novrfy) | ||
1245 | return 0; | ||
1246 | pr_err("alg: aead: %s %s failed with err %d on test vector %u, cfg=\"%s\"\n", | ||
1247 | driver, op, err, vec_num, cfg->name); | ||
1248 | return err; | ||
1249 | } | ||
1250 | if (vec->novrfy) { | ||
1251 | pr_err("alg: aead: %s %s unexpectedly succeeded on test vector %u, cfg=\"%s\"\n", | ||
1252 | driver, op, vec_num, cfg->name); | ||
1253 | return -EINVAL; | ||
1254 | } | ||
1255 | 1651 | ||
1256 | /* Check that the algorithm didn't overwrite things it shouldn't have */ | 1652 | /* Check that the algorithm didn't overwrite things it shouldn't have */ |
1257 | if (req->cryptlen != (enc ? vec->plen : vec->clen) || | 1653 | if (req->cryptlen != (enc ? vec->plen : vec->clen) || |
@@ -1263,8 +1659,8 @@ static int test_aead_vec_cfg(const char *driver, int enc, | |||
1263 | req->base.complete != crypto_req_done || | 1659 | req->base.complete != crypto_req_done || |
1264 | req->base.flags != req_flags || | 1660 | req->base.flags != req_flags || |
1265 | req->base.data != &wait) { | 1661 | req->base.data != &wait) { |
1266 | pr_err("alg: aead: %s %s corrupted request struct on test vector %u, cfg=\"%s\"\n", | 1662 | pr_err("alg: aead: %s %s corrupted request struct on test vector %s, cfg=\"%s\"\n", |
1267 | driver, op, vec_num, cfg->name); | 1663 | driver, op, vec_name, cfg->name); |
1268 | if (req->cryptlen != (enc ? vec->plen : vec->clen)) | 1664 | if (req->cryptlen != (enc ? vec->plen : vec->clen)) |
1269 | pr_err("alg: aead: changed 'req->cryptlen'\n"); | 1665 | pr_err("alg: aead: changed 'req->cryptlen'\n"); |
1270 | if (req->assoclen != vec->alen) | 1666 | if (req->assoclen != vec->alen) |
@@ -1286,14 +1682,29 @@ static int test_aead_vec_cfg(const char *driver, int enc, | |||
1286 | return -EINVAL; | 1682 | return -EINVAL; |
1287 | } | 1683 | } |
1288 | if (is_test_sglist_corrupted(&tsgls->src)) { | 1684 | if (is_test_sglist_corrupted(&tsgls->src)) { |
1289 | pr_err("alg: aead: %s %s corrupted src sgl on test vector %u, cfg=\"%s\"\n", | 1685 | pr_err("alg: aead: %s %s corrupted src sgl on test vector %s, cfg=\"%s\"\n", |
1290 | driver, op, vec_num, cfg->name); | 1686 | driver, op, vec_name, cfg->name); |
1291 | return -EINVAL; | 1687 | return -EINVAL; |
1292 | } | 1688 | } |
1293 | if (tsgls->dst.sgl_ptr != tsgls->src.sgl && | 1689 | if (tsgls->dst.sgl_ptr != tsgls->src.sgl && |
1294 | is_test_sglist_corrupted(&tsgls->dst)) { | 1690 | is_test_sglist_corrupted(&tsgls->dst)) { |
1295 | pr_err("alg: aead: %s %s corrupted dst sgl on test vector %u, cfg=\"%s\"\n", | 1691 | pr_err("alg: aead: %s %s corrupted dst sgl on test vector %s, cfg=\"%s\"\n", |
1296 | driver, op, vec_num, cfg->name); | 1692 | driver, op, vec_name, cfg->name); |
1693 | return -EINVAL; | ||
1694 | } | ||
1695 | |||
1696 | /* Check for success or failure */ | ||
1697 | expected_error = vec->novrfy ? -EBADMSG : vec->crypt_error; | ||
1698 | if (err) { | ||
1699 | if (err == expected_error) | ||
1700 | return 0; | ||
1701 | pr_err("alg: aead: %s %s failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n", | ||
1702 | driver, op, vec_name, expected_error, err, cfg->name); | ||
1703 | return err; | ||
1704 | } | ||
1705 | if (expected_error) { | ||
1706 | pr_err("alg: aead: %s %s unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n", | ||
1707 | driver, op, vec_name, expected_error, cfg->name); | ||
1297 | return -EINVAL; | 1708 | return -EINVAL; |
1298 | } | 1709 | } |
1299 | 1710 | ||
@@ -1302,13 +1713,13 @@ static int test_aead_vec_cfg(const char *driver, int enc, | |||
1302 | enc ? vec->clen : vec->plen, | 1713 | enc ? vec->clen : vec->plen, |
1303 | vec->alen, enc || !cfg->inplace); | 1714 | vec->alen, enc || !cfg->inplace); |
1304 | if (err == -EOVERFLOW) { | 1715 | if (err == -EOVERFLOW) { |
1305 | pr_err("alg: aead: %s %s overran dst buffer on test vector %u, cfg=\"%s\"\n", | 1716 | pr_err("alg: aead: %s %s overran dst buffer on test vector %s, cfg=\"%s\"\n", |
1306 | driver, op, vec_num, cfg->name); | 1717 | driver, op, vec_name, cfg->name); |
1307 | return err; | 1718 | return err; |
1308 | } | 1719 | } |
1309 | if (err) { | 1720 | if (err) { |
1310 | pr_err("alg: aead: %s %s test failed (wrong result) on test vector %u, cfg=\"%s\"\n", | 1721 | pr_err("alg: aead: %s %s test failed (wrong result) on test vector %s, cfg=\"%s\"\n", |
1311 | driver, op, vec_num, cfg->name); | 1722 | driver, op, vec_name, cfg->name); |
1312 | return err; | 1723 | return err; |
1313 | } | 1724 | } |
1314 | 1725 | ||
@@ -1320,14 +1731,17 @@ static int test_aead_vec(const char *driver, int enc, | |||
1320 | struct aead_request *req, | 1731 | struct aead_request *req, |
1321 | struct cipher_test_sglists *tsgls) | 1732 | struct cipher_test_sglists *tsgls) |
1322 | { | 1733 | { |
1734 | char vec_name[16]; | ||
1323 | unsigned int i; | 1735 | unsigned int i; |
1324 | int err; | 1736 | int err; |
1325 | 1737 | ||
1326 | if (enc && vec->novrfy) | 1738 | if (enc && vec->novrfy) |
1327 | return 0; | 1739 | return 0; |
1328 | 1740 | ||
1741 | sprintf(vec_name, "%u", vec_num); | ||
1742 | |||
1329 | for (i = 0; i < ARRAY_SIZE(default_cipher_testvec_configs); i++) { | 1743 | for (i = 0; i < ARRAY_SIZE(default_cipher_testvec_configs); i++) { |
1330 | err = test_aead_vec_cfg(driver, enc, vec, vec_num, | 1744 | err = test_aead_vec_cfg(driver, enc, vec, vec_name, |
1331 | &default_cipher_testvec_configs[i], | 1745 | &default_cipher_testvec_configs[i], |
1332 | req, tsgls); | 1746 | req, tsgls); |
1333 | if (err) | 1747 | if (err) |
@@ -1342,7 +1756,7 @@ static int test_aead_vec(const char *driver, int enc, | |||
1342 | for (i = 0; i < fuzz_iterations; i++) { | 1756 | for (i = 0; i < fuzz_iterations; i++) { |
1343 | generate_random_testvec_config(&cfg, cfgname, | 1757 | generate_random_testvec_config(&cfg, cfgname, |
1344 | sizeof(cfgname)); | 1758 | sizeof(cfgname)); |
1345 | err = test_aead_vec_cfg(driver, enc, vec, vec_num, | 1759 | err = test_aead_vec_cfg(driver, enc, vec, vec_name, |
1346 | &cfg, req, tsgls); | 1760 | &cfg, req, tsgls); |
1347 | if (err) | 1761 | if (err) |
1348 | return err; | 1762 | return err; |
@@ -1352,6 +1766,226 @@ static int test_aead_vec(const char *driver, int enc, | |||
1352 | return 0; | 1766 | return 0; |
1353 | } | 1767 | } |
1354 | 1768 | ||
1769 | #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS | ||
1770 | /* | ||
1771 | * Generate an AEAD test vector from the given implementation. | ||
1772 | * Assumes the buffers in 'vec' were already allocated. | ||
1773 | */ | ||
1774 | static void generate_random_aead_testvec(struct aead_request *req, | ||
1775 | struct aead_testvec *vec, | ||
1776 | unsigned int maxkeysize, | ||
1777 | unsigned int maxdatasize, | ||
1778 | char *name, size_t max_namelen) | ||
1779 | { | ||
1780 | struct crypto_aead *tfm = crypto_aead_reqtfm(req); | ||
1781 | const unsigned int ivsize = crypto_aead_ivsize(tfm); | ||
1782 | unsigned int maxauthsize = crypto_aead_alg(tfm)->maxauthsize; | ||
1783 | unsigned int authsize; | ||
1784 | unsigned int total_len; | ||
1785 | int i; | ||
1786 | struct scatterlist src[2], dst; | ||
1787 | u8 iv[MAX_IVLEN]; | ||
1788 | DECLARE_CRYPTO_WAIT(wait); | ||
1789 | |||
1790 | /* Key: length in [0, maxkeysize], but usually choose maxkeysize */ | ||
1791 | vec->klen = maxkeysize; | ||
1792 | if (prandom_u32() % 4 == 0) | ||
1793 | vec->klen = prandom_u32() % (maxkeysize + 1); | ||
1794 | generate_random_bytes((u8 *)vec->key, vec->klen); | ||
1795 | vec->setkey_error = crypto_aead_setkey(tfm, vec->key, vec->klen); | ||
1796 | |||
1797 | /* IV */ | ||
1798 | generate_random_bytes((u8 *)vec->iv, ivsize); | ||
1799 | |||
1800 | /* Tag length: in [0, maxauthsize], but usually choose maxauthsize */ | ||
1801 | authsize = maxauthsize; | ||
1802 | if (prandom_u32() % 4 == 0) | ||
1803 | authsize = prandom_u32() % (maxauthsize + 1); | ||
1804 | if (WARN_ON(authsize > maxdatasize)) | ||
1805 | authsize = maxdatasize; | ||
1806 | maxdatasize -= authsize; | ||
1807 | vec->setauthsize_error = crypto_aead_setauthsize(tfm, authsize); | ||
1808 | |||
1809 | /* Plaintext and associated data */ | ||
1810 | total_len = generate_random_length(maxdatasize); | ||
1811 | if (prandom_u32() % 4 == 0) | ||
1812 | vec->alen = 0; | ||
1813 | else | ||
1814 | vec->alen = generate_random_length(total_len); | ||
1815 | vec->plen = total_len - vec->alen; | ||
1816 | generate_random_bytes((u8 *)vec->assoc, vec->alen); | ||
1817 | generate_random_bytes((u8 *)vec->ptext, vec->plen); | ||
1818 | |||
1819 | vec->clen = vec->plen + authsize; | ||
1820 | |||
1821 | /* | ||
1822 | * If the key or authentication tag size couldn't be set, no need to | ||
1823 | * continue to encrypt. | ||
1824 | */ | ||
1825 | if (vec->setkey_error || vec->setauthsize_error) | ||
1826 | goto done; | ||
1827 | |||
1828 | /* Ciphertext */ | ||
1829 | sg_init_table(src, 2); | ||
1830 | i = 0; | ||
1831 | if (vec->alen) | ||
1832 | sg_set_buf(&src[i++], vec->assoc, vec->alen); | ||
1833 | if (vec->plen) | ||
1834 | sg_set_buf(&src[i++], vec->ptext, vec->plen); | ||
1835 | sg_init_one(&dst, vec->ctext, vec->alen + vec->clen); | ||
1836 | memcpy(iv, vec->iv, ivsize); | ||
1837 | aead_request_set_callback(req, 0, crypto_req_done, &wait); | ||
1838 | aead_request_set_crypt(req, src, &dst, vec->plen, iv); | ||
1839 | aead_request_set_ad(req, vec->alen); | ||
1840 | vec->crypt_error = crypto_wait_req(crypto_aead_encrypt(req), &wait); | ||
1841 | if (vec->crypt_error == 0) | ||
1842 | memmove((u8 *)vec->ctext, vec->ctext + vec->alen, vec->clen); | ||
1843 | done: | ||
1844 | snprintf(name, max_namelen, | ||
1845 | "\"random: alen=%u plen=%u authsize=%u klen=%u\"", | ||
1846 | vec->alen, vec->plen, authsize, vec->klen); | ||
1847 | } | ||
1848 | |||
1849 | /* | ||
1850 | * Test the AEAD algorithm represented by @req against the corresponding generic | ||
1851 | * implementation, if one is available. | ||
1852 | */ | ||
1853 | static int test_aead_vs_generic_impl(const char *driver, | ||
1854 | const struct alg_test_desc *test_desc, | ||
1855 | struct aead_request *req, | ||
1856 | struct cipher_test_sglists *tsgls) | ||
1857 | { | ||
1858 | struct crypto_aead *tfm = crypto_aead_reqtfm(req); | ||
1859 | const unsigned int ivsize = crypto_aead_ivsize(tfm); | ||
1860 | const unsigned int maxauthsize = crypto_aead_alg(tfm)->maxauthsize; | ||
1861 | const unsigned int blocksize = crypto_aead_blocksize(tfm); | ||
1862 | const unsigned int maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN; | ||
1863 | const char *algname = crypto_aead_alg(tfm)->base.cra_name; | ||
1864 | const char *generic_driver = test_desc->generic_driver; | ||
1865 | char _generic_driver[CRYPTO_MAX_ALG_NAME]; | ||
1866 | struct crypto_aead *generic_tfm = NULL; | ||
1867 | struct aead_request *generic_req = NULL; | ||
1868 | unsigned int maxkeysize; | ||
1869 | unsigned int i; | ||
1870 | struct aead_testvec vec = { 0 }; | ||
1871 | char vec_name[64]; | ||
1872 | struct testvec_config cfg; | ||
1873 | char cfgname[TESTVEC_CONFIG_NAMELEN]; | ||
1874 | int err; | ||
1875 | |||
1876 | if (noextratests) | ||
1877 | return 0; | ||
1878 | |||
1879 | if (!generic_driver) { /* Use default naming convention? */ | ||
1880 | err = build_generic_driver_name(algname, _generic_driver); | ||
1881 | if (err) | ||
1882 | return err; | ||
1883 | generic_driver = _generic_driver; | ||
1884 | } | ||
1885 | |||
1886 | if (strcmp(generic_driver, driver) == 0) /* Already the generic impl? */ | ||
1887 | return 0; | ||
1888 | |||
1889 | generic_tfm = crypto_alloc_aead(generic_driver, 0, 0); | ||
1890 | if (IS_ERR(generic_tfm)) { | ||
1891 | err = PTR_ERR(generic_tfm); | ||
1892 | if (err == -ENOENT) { | ||
1893 | pr_warn("alg: aead: skipping comparison tests for %s because %s is unavailable\n", | ||
1894 | driver, generic_driver); | ||
1895 | return 0; | ||
1896 | } | ||
1897 | pr_err("alg: aead: error allocating %s (generic impl of %s): %d\n", | ||
1898 | generic_driver, algname, err); | ||
1899 | return err; | ||
1900 | } | ||
1901 | |||
1902 | generic_req = aead_request_alloc(generic_tfm, GFP_KERNEL); | ||
1903 | if (!generic_req) { | ||
1904 | err = -ENOMEM; | ||
1905 | goto out; | ||
1906 | } | ||
1907 | |||
1908 | /* Check the algorithm properties for consistency. */ | ||
1909 | |||
1910 | if (maxauthsize != crypto_aead_alg(generic_tfm)->maxauthsize) { | ||
1911 | pr_err("alg: aead: maxauthsize for %s (%u) doesn't match generic impl (%u)\n", | ||
1912 | driver, maxauthsize, | ||
1913 | crypto_aead_alg(generic_tfm)->maxauthsize); | ||
1914 | err = -EINVAL; | ||
1915 | goto out; | ||
1916 | } | ||
1917 | |||
1918 | if (ivsize != crypto_aead_ivsize(generic_tfm)) { | ||
1919 | pr_err("alg: aead: ivsize for %s (%u) doesn't match generic impl (%u)\n", | ||
1920 | driver, ivsize, crypto_aead_ivsize(generic_tfm)); | ||
1921 | err = -EINVAL; | ||
1922 | goto out; | ||
1923 | } | ||
1924 | |||
1925 | if (blocksize != crypto_aead_blocksize(generic_tfm)) { | ||
1926 | pr_err("alg: aead: blocksize for %s (%u) doesn't match generic impl (%u)\n", | ||
1927 | driver, blocksize, crypto_aead_blocksize(generic_tfm)); | ||
1928 | err = -EINVAL; | ||
1929 | goto out; | ||
1930 | } | ||
1931 | |||
1932 | /* | ||
1933 | * Now generate test vectors using the generic implementation, and test | ||
1934 | * the other implementation against them. | ||
1935 | */ | ||
1936 | |||
1937 | maxkeysize = 0; | ||
1938 | for (i = 0; i < test_desc->suite.aead.count; i++) | ||
1939 | maxkeysize = max_t(unsigned int, maxkeysize, | ||
1940 | test_desc->suite.aead.vecs[i].klen); | ||
1941 | |||
1942 | vec.key = kmalloc(maxkeysize, GFP_KERNEL); | ||
1943 | vec.iv = kmalloc(ivsize, GFP_KERNEL); | ||
1944 | vec.assoc = kmalloc(maxdatasize, GFP_KERNEL); | ||
1945 | vec.ptext = kmalloc(maxdatasize, GFP_KERNEL); | ||
1946 | vec.ctext = kmalloc(maxdatasize, GFP_KERNEL); | ||
1947 | if (!vec.key || !vec.iv || !vec.assoc || !vec.ptext || !vec.ctext) { | ||
1948 | err = -ENOMEM; | ||
1949 | goto out; | ||
1950 | } | ||
1951 | |||
1952 | for (i = 0; i < fuzz_iterations * 8; i++) { | ||
1953 | generate_random_aead_testvec(generic_req, &vec, | ||
1954 | maxkeysize, maxdatasize, | ||
1955 | vec_name, sizeof(vec_name)); | ||
1956 | generate_random_testvec_config(&cfg, cfgname, sizeof(cfgname)); | ||
1957 | |||
1958 | err = test_aead_vec_cfg(driver, ENCRYPT, &vec, vec_name, &cfg, | ||
1959 | req, tsgls); | ||
1960 | if (err) | ||
1961 | goto out; | ||
1962 | err = test_aead_vec_cfg(driver, DECRYPT, &vec, vec_name, &cfg, | ||
1963 | req, tsgls); | ||
1964 | if (err) | ||
1965 | goto out; | ||
1966 | cond_resched(); | ||
1967 | } | ||
1968 | err = 0; | ||
1969 | out: | ||
1970 | kfree(vec.key); | ||
1971 | kfree(vec.iv); | ||
1972 | kfree(vec.assoc); | ||
1973 | kfree(vec.ptext); | ||
1974 | kfree(vec.ctext); | ||
1975 | crypto_free_aead(generic_tfm); | ||
1976 | aead_request_free(generic_req); | ||
1977 | return err; | ||
1978 | } | ||
1979 | #else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ | ||
1980 | static int test_aead_vs_generic_impl(const char *driver, | ||
1981 | const struct alg_test_desc *test_desc, | ||
1982 | struct aead_request *req, | ||
1983 | struct cipher_test_sglists *tsgls) | ||
1984 | { | ||
1985 | return 0; | ||
1986 | } | ||
1987 | #endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ | ||
1988 | |||
1355 | static int test_aead(const char *driver, int enc, | 1989 | static int test_aead(const char *driver, int enc, |
1356 | const struct aead_test_suite *suite, | 1990 | const struct aead_test_suite *suite, |
1357 | struct aead_request *req, | 1991 | struct aead_request *req, |
@@ -1411,6 +2045,10 @@ static int alg_test_aead(const struct alg_test_desc *desc, const char *driver, | |||
1411 | goto out; | 2045 | goto out; |
1412 | 2046 | ||
1413 | err = test_aead(driver, DECRYPT, suite, req, tsgls); | 2047 | err = test_aead(driver, DECRYPT, suite, req, tsgls); |
2048 | if (err) | ||
2049 | goto out; | ||
2050 | |||
2051 | err = test_aead_vs_generic_impl(driver, desc, req, tsgls); | ||
1414 | out: | 2052 | out: |
1415 | free_cipher_test_sglists(tsgls); | 2053 | free_cipher_test_sglists(tsgls); |
1416 | aead_request_free(req); | 2054 | aead_request_free(req); |
@@ -1462,13 +2100,20 @@ static int test_cipher(struct crypto_cipher *tfm, int enc, | |||
1462 | 2100 | ||
1463 | ret = crypto_cipher_setkey(tfm, template[i].key, | 2101 | ret = crypto_cipher_setkey(tfm, template[i].key, |
1464 | template[i].klen); | 2102 | template[i].klen); |
1465 | if (template[i].fail == !ret) { | 2103 | if (ret) { |
1466 | printk(KERN_ERR "alg: cipher: setkey failed " | 2104 | if (ret == template[i].setkey_error) |
1467 | "on test %d for %s: flags=%x\n", j, | 2105 | continue; |
1468 | algo, crypto_cipher_get_flags(tfm)); | 2106 | pr_err("alg: cipher: %s setkey failed on test vector %u; expected_error=%d, actual_error=%d, flags=%#x\n", |
2107 | algo, j, template[i].setkey_error, ret, | ||
2108 | crypto_cipher_get_flags(tfm)); | ||
1469 | goto out; | 2109 | goto out; |
1470 | } else if (ret) | 2110 | } |
1471 | continue; | 2111 | if (template[i].setkey_error) { |
2112 | pr_err("alg: cipher: %s setkey unexpectedly succeeded on test vector %u; expected_error=%d\n", | ||
2113 | algo, j, template[i].setkey_error); | ||
2114 | ret = -EINVAL; | ||
2115 | goto out; | ||
2116 | } | ||
1472 | 2117 | ||
1473 | for (k = 0; k < template[i].len; | 2118 | for (k = 0; k < template[i].len; |
1474 | k += crypto_cipher_blocksize(tfm)) { | 2119 | k += crypto_cipher_blocksize(tfm)) { |
@@ -1500,7 +2145,7 @@ out_nobuf: | |||
1500 | 2145 | ||
1501 | static int test_skcipher_vec_cfg(const char *driver, int enc, | 2146 | static int test_skcipher_vec_cfg(const char *driver, int enc, |
1502 | const struct cipher_testvec *vec, | 2147 | const struct cipher_testvec *vec, |
1503 | unsigned int vec_num, | 2148 | const char *vec_name, |
1504 | const struct testvec_config *cfg, | 2149 | const struct testvec_config *cfg, |
1505 | struct skcipher_request *req, | 2150 | struct skcipher_request *req, |
1506 | struct cipher_test_sglists *tsgls) | 2151 | struct cipher_test_sglists *tsgls) |
@@ -1526,15 +2171,16 @@ static int test_skcipher_vec_cfg(const char *driver, int enc, | |||
1526 | CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); | 2171 | CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); |
1527 | err = crypto_skcipher_setkey(tfm, vec->key, vec->klen); | 2172 | err = crypto_skcipher_setkey(tfm, vec->key, vec->klen); |
1528 | if (err) { | 2173 | if (err) { |
1529 | if (vec->fail) /* expectedly failed to set key? */ | 2174 | if (err == vec->setkey_error) |
1530 | return 0; | 2175 | return 0; |
1531 | pr_err("alg: skcipher: %s setkey failed with err %d on test vector %u; flags=%#x\n", | 2176 | pr_err("alg: skcipher: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n", |
1532 | driver, err, vec_num, crypto_skcipher_get_flags(tfm)); | 2177 | driver, vec_name, vec->setkey_error, err, |
2178 | crypto_skcipher_get_flags(tfm)); | ||
1533 | return err; | 2179 | return err; |
1534 | } | 2180 | } |
1535 | if (vec->fail) { | 2181 | if (vec->setkey_error) { |
1536 | pr_err("alg: skcipher: %s setkey unexpectedly succeeded on test vector %u\n", | 2182 | pr_err("alg: skcipher: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n", |
1537 | driver, vec_num); | 2183 | driver, vec_name, vec->setkey_error); |
1538 | return -EINVAL; | 2184 | return -EINVAL; |
1539 | } | 2185 | } |
1540 | 2186 | ||
@@ -1550,8 +2196,8 @@ static int test_skcipher_vec_cfg(const char *driver, int enc, | |||
1550 | memset(iv, 0, ivsize); | 2196 | memset(iv, 0, ivsize); |
1551 | } else { | 2197 | } else { |
1552 | if (vec->generates_iv) { | 2198 | if (vec->generates_iv) { |
1553 | pr_err("alg: skcipher: %s has ivsize=0 but test vector %u generates IV!\n", | 2199 | pr_err("alg: skcipher: %s has ivsize=0 but test vector %s generates IV!\n", |
1554 | driver, vec_num); | 2200 | driver, vec_name); |
1555 | return -EINVAL; | 2201 | return -EINVAL; |
1556 | } | 2202 | } |
1557 | iv = NULL; | 2203 | iv = NULL; |
@@ -1563,8 +2209,8 @@ static int test_skcipher_vec_cfg(const char *driver, int enc, | |||
1563 | err = build_cipher_test_sglists(tsgls, cfg, alignmask, | 2209 | err = build_cipher_test_sglists(tsgls, cfg, alignmask, |
1564 | vec->len, vec->len, &input, 1); | 2210 | vec->len, vec->len, &input, 1); |
1565 | if (err) { | 2211 | if (err) { |
1566 | pr_err("alg: skcipher: %s %s: error preparing scatterlists for test vector %u, cfg=\"%s\"\n", | 2212 | pr_err("alg: skcipher: %s %s: error preparing scatterlists for test vector %s, cfg=\"%s\"\n", |
1567 | driver, op, vec_num, cfg->name); | 2213 | driver, op, vec_name, cfg->name); |
1568 | return err; | 2214 | return err; |
1569 | } | 2215 | } |
1570 | 2216 | ||
@@ -1573,13 +2219,12 @@ static int test_skcipher_vec_cfg(const char *driver, int enc, | |||
1573 | skcipher_request_set_callback(req, req_flags, crypto_req_done, &wait); | 2219 | skcipher_request_set_callback(req, req_flags, crypto_req_done, &wait); |
1574 | skcipher_request_set_crypt(req, tsgls->src.sgl_ptr, tsgls->dst.sgl_ptr, | 2220 | skcipher_request_set_crypt(req, tsgls->src.sgl_ptr, tsgls->dst.sgl_ptr, |
1575 | vec->len, iv); | 2221 | vec->len, iv); |
1576 | err = crypto_wait_req(enc ? crypto_skcipher_encrypt(req) : | 2222 | if (cfg->nosimd) |
1577 | crypto_skcipher_decrypt(req), &wait); | 2223 | crypto_disable_simd_for_test(); |
1578 | if (err) { | 2224 | err = enc ? crypto_skcipher_encrypt(req) : crypto_skcipher_decrypt(req); |
1579 | pr_err("alg: skcipher: %s %s failed with err %d on test vector %u, cfg=\"%s\"\n", | 2225 | if (cfg->nosimd) |
1580 | driver, op, err, vec_num, cfg->name); | 2226 | crypto_reenable_simd_for_test(); |
1581 | return err; | 2227 | err = crypto_wait_req(err, &wait); |
1582 | } | ||
1583 | 2228 | ||
1584 | /* Check that the algorithm didn't overwrite things it shouldn't have */ | 2229 | /* Check that the algorithm didn't overwrite things it shouldn't have */ |
1585 | if (req->cryptlen != vec->len || | 2230 | if (req->cryptlen != vec->len || |
@@ -1590,8 +2235,8 @@ static int test_skcipher_vec_cfg(const char *driver, int enc, | |||
1590 | req->base.complete != crypto_req_done || | 2235 | req->base.complete != crypto_req_done || |
1591 | req->base.flags != req_flags || | 2236 | req->base.flags != req_flags || |
1592 | req->base.data != &wait) { | 2237 | req->base.data != &wait) { |
1593 | pr_err("alg: skcipher: %s %s corrupted request struct on test vector %u, cfg=\"%s\"\n", | 2238 | pr_err("alg: skcipher: %s %s corrupted request struct on test vector %s, cfg=\"%s\"\n", |
1594 | driver, op, vec_num, cfg->name); | 2239 | driver, op, vec_name, cfg->name); |
1595 | if (req->cryptlen != vec->len) | 2240 | if (req->cryptlen != vec->len) |
1596 | pr_err("alg: skcipher: changed 'req->cryptlen'\n"); | 2241 | pr_err("alg: skcipher: changed 'req->cryptlen'\n"); |
1597 | if (req->iv != iv) | 2242 | if (req->iv != iv) |
@@ -1611,14 +2256,28 @@ static int test_skcipher_vec_cfg(const char *driver, int enc, | |||
1611 | return -EINVAL; | 2256 | return -EINVAL; |
1612 | } | 2257 | } |
1613 | if (is_test_sglist_corrupted(&tsgls->src)) { | 2258 | if (is_test_sglist_corrupted(&tsgls->src)) { |
1614 | pr_err("alg: skcipher: %s %s corrupted src sgl on test vector %u, cfg=\"%s\"\n", | 2259 | pr_err("alg: skcipher: %s %s corrupted src sgl on test vector %s, cfg=\"%s\"\n", |
1615 | driver, op, vec_num, cfg->name); | 2260 | driver, op, vec_name, cfg->name); |
1616 | return -EINVAL; | 2261 | return -EINVAL; |
1617 | } | 2262 | } |
1618 | if (tsgls->dst.sgl_ptr != tsgls->src.sgl && | 2263 | if (tsgls->dst.sgl_ptr != tsgls->src.sgl && |
1619 | is_test_sglist_corrupted(&tsgls->dst)) { | 2264 | is_test_sglist_corrupted(&tsgls->dst)) { |
1620 | pr_err("alg: skcipher: %s %s corrupted dst sgl on test vector %u, cfg=\"%s\"\n", | 2265 | pr_err("alg: skcipher: %s %s corrupted dst sgl on test vector %s, cfg=\"%s\"\n", |
1621 | driver, op, vec_num, cfg->name); | 2266 | driver, op, vec_name, cfg->name); |
2267 | return -EINVAL; | ||
2268 | } | ||
2269 | |||
2270 | /* Check for success or failure */ | ||
2271 | if (err) { | ||
2272 | if (err == vec->crypt_error) | ||
2273 | return 0; | ||
2274 | pr_err("alg: skcipher: %s %s failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n", | ||
2275 | driver, op, vec_name, vec->crypt_error, err, cfg->name); | ||
2276 | return err; | ||
2277 | } | ||
2278 | if (vec->crypt_error) { | ||
2279 | pr_err("alg: skcipher: %s %s unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n", | ||
2280 | driver, op, vec_name, vec->crypt_error, cfg->name); | ||
1622 | return -EINVAL; | 2281 | return -EINVAL; |
1623 | } | 2282 | } |
1624 | 2283 | ||
@@ -1626,20 +2285,20 @@ static int test_skcipher_vec_cfg(const char *driver, int enc, | |||
1626 | err = verify_correct_output(&tsgls->dst, enc ? vec->ctext : vec->ptext, | 2285 | err = verify_correct_output(&tsgls->dst, enc ? vec->ctext : vec->ptext, |
1627 | vec->len, 0, true); | 2286 | vec->len, 0, true); |
1628 | if (err == -EOVERFLOW) { | 2287 | if (err == -EOVERFLOW) { |
1629 | pr_err("alg: skcipher: %s %s overran dst buffer on test vector %u, cfg=\"%s\"\n", | 2288 | pr_err("alg: skcipher: %s %s overran dst buffer on test vector %s, cfg=\"%s\"\n", |
1630 | driver, op, vec_num, cfg->name); | 2289 | driver, op, vec_name, cfg->name); |
1631 | return err; | 2290 | return err; |
1632 | } | 2291 | } |
1633 | if (err) { | 2292 | if (err) { |
1634 | pr_err("alg: skcipher: %s %s test failed (wrong result) on test vector %u, cfg=\"%s\"\n", | 2293 | pr_err("alg: skcipher: %s %s test failed (wrong result) on test vector %s, cfg=\"%s\"\n", |
1635 | driver, op, vec_num, cfg->name); | 2294 | driver, op, vec_name, cfg->name); |
1636 | return err; | 2295 | return err; |
1637 | } | 2296 | } |
1638 | 2297 | ||
1639 | /* If applicable, check that the algorithm generated the correct IV */ | 2298 | /* If applicable, check that the algorithm generated the correct IV */ |
1640 | if (vec->iv_out && memcmp(iv, vec->iv_out, ivsize) != 0) { | 2299 | if (vec->iv_out && memcmp(iv, vec->iv_out, ivsize) != 0) { |
1641 | pr_err("alg: skcipher: %s %s test failed (wrong output IV) on test vector %u, cfg=\"%s\"\n", | 2300 | pr_err("alg: skcipher: %s %s test failed (wrong output IV) on test vector %s, cfg=\"%s\"\n", |
1642 | driver, op, vec_num, cfg->name); | 2301 | driver, op, vec_name, cfg->name); |
1643 | hexdump(iv, ivsize); | 2302 | hexdump(iv, ivsize); |
1644 | return -EINVAL; | 2303 | return -EINVAL; |
1645 | } | 2304 | } |
@@ -1653,14 +2312,17 @@ static int test_skcipher_vec(const char *driver, int enc, | |||
1653 | struct skcipher_request *req, | 2312 | struct skcipher_request *req, |
1654 | struct cipher_test_sglists *tsgls) | 2313 | struct cipher_test_sglists *tsgls) |
1655 | { | 2314 | { |
2315 | char vec_name[16]; | ||
1656 | unsigned int i; | 2316 | unsigned int i; |
1657 | int err; | 2317 | int err; |
1658 | 2318 | ||
1659 | if (fips_enabled && vec->fips_skip) | 2319 | if (fips_enabled && vec->fips_skip) |
1660 | return 0; | 2320 | return 0; |
1661 | 2321 | ||
2322 | sprintf(vec_name, "%u", vec_num); | ||
2323 | |||
1662 | for (i = 0; i < ARRAY_SIZE(default_cipher_testvec_configs); i++) { | 2324 | for (i = 0; i < ARRAY_SIZE(default_cipher_testvec_configs); i++) { |
1663 | err = test_skcipher_vec_cfg(driver, enc, vec, vec_num, | 2325 | err = test_skcipher_vec_cfg(driver, enc, vec, vec_name, |
1664 | &default_cipher_testvec_configs[i], | 2326 | &default_cipher_testvec_configs[i], |
1665 | req, tsgls); | 2327 | req, tsgls); |
1666 | if (err) | 2328 | if (err) |
@@ -1675,7 +2337,7 @@ static int test_skcipher_vec(const char *driver, int enc, | |||
1675 | for (i = 0; i < fuzz_iterations; i++) { | 2337 | for (i = 0; i < fuzz_iterations; i++) { |
1676 | generate_random_testvec_config(&cfg, cfgname, | 2338 | generate_random_testvec_config(&cfg, cfgname, |
1677 | sizeof(cfgname)); | 2339 | sizeof(cfgname)); |
1678 | err = test_skcipher_vec_cfg(driver, enc, vec, vec_num, | 2340 | err = test_skcipher_vec_cfg(driver, enc, vec, vec_name, |
1679 | &cfg, req, tsgls); | 2341 | &cfg, req, tsgls); |
1680 | if (err) | 2342 | if (err) |
1681 | return err; | 2343 | return err; |
@@ -1685,6 +2347,186 @@ static int test_skcipher_vec(const char *driver, int enc, | |||
1685 | return 0; | 2347 | return 0; |
1686 | } | 2348 | } |
1687 | 2349 | ||
2350 | #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS | ||
2351 | /* | ||
2352 | * Generate a symmetric cipher test vector from the given implementation. | ||
2353 | * Assumes the buffers in 'vec' were already allocated. | ||
2354 | */ | ||
2355 | static void generate_random_cipher_testvec(struct skcipher_request *req, | ||
2356 | struct cipher_testvec *vec, | ||
2357 | unsigned int maxdatasize, | ||
2358 | char *name, size_t max_namelen) | ||
2359 | { | ||
2360 | struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); | ||
2361 | const unsigned int maxkeysize = tfm->keysize; | ||
2362 | const unsigned int ivsize = crypto_skcipher_ivsize(tfm); | ||
2363 | struct scatterlist src, dst; | ||
2364 | u8 iv[MAX_IVLEN]; | ||
2365 | DECLARE_CRYPTO_WAIT(wait); | ||
2366 | |||
2367 | /* Key: length in [0, maxkeysize], but usually choose maxkeysize */ | ||
2368 | vec->klen = maxkeysize; | ||
2369 | if (prandom_u32() % 4 == 0) | ||
2370 | vec->klen = prandom_u32() % (maxkeysize + 1); | ||
2371 | generate_random_bytes((u8 *)vec->key, vec->klen); | ||
2372 | vec->setkey_error = crypto_skcipher_setkey(tfm, vec->key, vec->klen); | ||
2373 | |||
2374 | /* IV */ | ||
2375 | generate_random_bytes((u8 *)vec->iv, ivsize); | ||
2376 | |||
2377 | /* Plaintext */ | ||
2378 | vec->len = generate_random_length(maxdatasize); | ||
2379 | generate_random_bytes((u8 *)vec->ptext, vec->len); | ||
2380 | |||
2381 | /* If the key couldn't be set, no need to continue to encrypt. */ | ||
2382 | if (vec->setkey_error) | ||
2383 | goto done; | ||
2384 | |||
2385 | /* Ciphertext */ | ||
2386 | sg_init_one(&src, vec->ptext, vec->len); | ||
2387 | sg_init_one(&dst, vec->ctext, vec->len); | ||
2388 | memcpy(iv, vec->iv, ivsize); | ||
2389 | skcipher_request_set_callback(req, 0, crypto_req_done, &wait); | ||
2390 | skcipher_request_set_crypt(req, &src, &dst, vec->len, iv); | ||
2391 | vec->crypt_error = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); | ||
2392 | done: | ||
2393 | snprintf(name, max_namelen, "\"random: len=%u klen=%u\"", | ||
2394 | vec->len, vec->klen); | ||
2395 | } | ||
2396 | |||
2397 | /* | ||
2398 | * Test the skcipher algorithm represented by @req against the corresponding | ||
2399 | * generic implementation, if one is available. | ||
2400 | */ | ||
2401 | static int test_skcipher_vs_generic_impl(const char *driver, | ||
2402 | const char *generic_driver, | ||
2403 | struct skcipher_request *req, | ||
2404 | struct cipher_test_sglists *tsgls) | ||
2405 | { | ||
2406 | struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); | ||
2407 | const unsigned int ivsize = crypto_skcipher_ivsize(tfm); | ||
2408 | const unsigned int blocksize = crypto_skcipher_blocksize(tfm); | ||
2409 | const unsigned int maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN; | ||
2410 | const char *algname = crypto_skcipher_alg(tfm)->base.cra_name; | ||
2411 | char _generic_driver[CRYPTO_MAX_ALG_NAME]; | ||
2412 | struct crypto_skcipher *generic_tfm = NULL; | ||
2413 | struct skcipher_request *generic_req = NULL; | ||
2414 | unsigned int i; | ||
2415 | struct cipher_testvec vec = { 0 }; | ||
2416 | char vec_name[64]; | ||
2417 | struct testvec_config cfg; | ||
2418 | char cfgname[TESTVEC_CONFIG_NAMELEN]; | ||
2419 | int err; | ||
2420 | |||
2421 | if (noextratests) | ||
2422 | return 0; | ||
2423 | |||
2424 | /* Keywrap isn't supported here yet as it handles its IV differently. */ | ||
2425 | if (strncmp(algname, "kw(", 3) == 0) | ||
2426 | return 0; | ||
2427 | |||
2428 | if (!generic_driver) { /* Use default naming convention? */ | ||
2429 | err = build_generic_driver_name(algname, _generic_driver); | ||
2430 | if (err) | ||
2431 | return err; | ||
2432 | generic_driver = _generic_driver; | ||
2433 | } | ||
2434 | |||
2435 | if (strcmp(generic_driver, driver) == 0) /* Already the generic impl? */ | ||
2436 | return 0; | ||
2437 | |||
2438 | generic_tfm = crypto_alloc_skcipher(generic_driver, 0, 0); | ||
2439 | if (IS_ERR(generic_tfm)) { | ||
2440 | err = PTR_ERR(generic_tfm); | ||
2441 | if (err == -ENOENT) { | ||
2442 | pr_warn("alg: skcipher: skipping comparison tests for %s because %s is unavailable\n", | ||
2443 | driver, generic_driver); | ||
2444 | return 0; | ||
2445 | } | ||
2446 | pr_err("alg: skcipher: error allocating %s (generic impl of %s): %d\n", | ||
2447 | generic_driver, algname, err); | ||
2448 | return err; | ||
2449 | } | ||
2450 | |||
2451 | generic_req = skcipher_request_alloc(generic_tfm, GFP_KERNEL); | ||
2452 | if (!generic_req) { | ||
2453 | err = -ENOMEM; | ||
2454 | goto out; | ||
2455 | } | ||
2456 | |||
2457 | /* Check the algorithm properties for consistency. */ | ||
2458 | |||
2459 | if (tfm->keysize != generic_tfm->keysize) { | ||
2460 | pr_err("alg: skcipher: max keysize for %s (%u) doesn't match generic impl (%u)\n", | ||
2461 | driver, tfm->keysize, generic_tfm->keysize); | ||
2462 | err = -EINVAL; | ||
2463 | goto out; | ||
2464 | } | ||
2465 | |||
2466 | if (ivsize != crypto_skcipher_ivsize(generic_tfm)) { | ||
2467 | pr_err("alg: skcipher: ivsize for %s (%u) doesn't match generic impl (%u)\n", | ||
2468 | driver, ivsize, crypto_skcipher_ivsize(generic_tfm)); | ||
2469 | err = -EINVAL; | ||
2470 | goto out; | ||
2471 | } | ||
2472 | |||
2473 | if (blocksize != crypto_skcipher_blocksize(generic_tfm)) { | ||
2474 | pr_err("alg: skcipher: blocksize for %s (%u) doesn't match generic impl (%u)\n", | ||
2475 | driver, blocksize, | ||
2476 | crypto_skcipher_blocksize(generic_tfm)); | ||
2477 | err = -EINVAL; | ||
2478 | goto out; | ||
2479 | } | ||
2480 | |||
2481 | /* | ||
2482 | * Now generate test vectors using the generic implementation, and test | ||
2483 | * the other implementation against them. | ||
2484 | */ | ||
2485 | |||
2486 | vec.key = kmalloc(tfm->keysize, GFP_KERNEL); | ||
2487 | vec.iv = kmalloc(ivsize, GFP_KERNEL); | ||
2488 | vec.ptext = kmalloc(maxdatasize, GFP_KERNEL); | ||
2489 | vec.ctext = kmalloc(maxdatasize, GFP_KERNEL); | ||
2490 | if (!vec.key || !vec.iv || !vec.ptext || !vec.ctext) { | ||
2491 | err = -ENOMEM; | ||
2492 | goto out; | ||
2493 | } | ||
2494 | |||
2495 | for (i = 0; i < fuzz_iterations * 8; i++) { | ||
2496 | generate_random_cipher_testvec(generic_req, &vec, maxdatasize, | ||
2497 | vec_name, sizeof(vec_name)); | ||
2498 | generate_random_testvec_config(&cfg, cfgname, sizeof(cfgname)); | ||
2499 | |||
2500 | err = test_skcipher_vec_cfg(driver, ENCRYPT, &vec, vec_name, | ||
2501 | &cfg, req, tsgls); | ||
2502 | if (err) | ||
2503 | goto out; | ||
2504 | err = test_skcipher_vec_cfg(driver, DECRYPT, &vec, vec_name, | ||
2505 | &cfg, req, tsgls); | ||
2506 | if (err) | ||
2507 | goto out; | ||
2508 | cond_resched(); | ||
2509 | } | ||
2510 | err = 0; | ||
2511 | out: | ||
2512 | kfree(vec.key); | ||
2513 | kfree(vec.iv); | ||
2514 | kfree(vec.ptext); | ||
2515 | kfree(vec.ctext); | ||
2516 | crypto_free_skcipher(generic_tfm); | ||
2517 | skcipher_request_free(generic_req); | ||
2518 | return err; | ||
2519 | } | ||
2520 | #else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ | ||
2521 | static int test_skcipher_vs_generic_impl(const char *driver, | ||
2522 | const char *generic_driver, | ||
2523 | struct skcipher_request *req, | ||
2524 | struct cipher_test_sglists *tsgls) | ||
2525 | { | ||
2526 | return 0; | ||
2527 | } | ||
2528 | #endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ | ||
2529 | |||
1688 | static int test_skcipher(const char *driver, int enc, | 2530 | static int test_skcipher(const char *driver, int enc, |
1689 | const struct cipher_test_suite *suite, | 2531 | const struct cipher_test_suite *suite, |
1690 | struct skcipher_request *req, | 2532 | struct skcipher_request *req, |
@@ -1744,6 +2586,11 @@ static int alg_test_skcipher(const struct alg_test_desc *desc, | |||
1744 | goto out; | 2586 | goto out; |
1745 | 2587 | ||
1746 | err = test_skcipher(driver, DECRYPT, suite, req, tsgls); | 2588 | err = test_skcipher(driver, DECRYPT, suite, req, tsgls); |
2589 | if (err) | ||
2590 | goto out; | ||
2591 | |||
2592 | err = test_skcipher_vs_generic_impl(driver, desc->generic_driver, req, | ||
2593 | tsgls); | ||
1747 | out: | 2594 | out: |
1748 | free_cipher_test_sglists(tsgls); | 2595 | free_cipher_test_sglists(tsgls); |
1749 | skcipher_request_free(req); | 2596 | skcipher_request_free(req); |
@@ -2179,7 +3026,6 @@ static int alg_test_crc32c(const struct alg_test_desc *desc, | |||
2179 | u32 *ctx = (u32 *)shash_desc_ctx(shash); | 3026 | u32 *ctx = (u32 *)shash_desc_ctx(shash); |
2180 | 3027 | ||
2181 | shash->tfm = tfm; | 3028 | shash->tfm = tfm; |
2182 | shash->flags = 0; | ||
2183 | 3029 | ||
2184 | *ctx = 420553207; | 3030 | *ctx = 420553207; |
2185 | err = crypto_shash_final(shash, (u8 *)&val); | 3031 | err = crypto_shash_final(shash, (u8 *)&val); |
@@ -2493,6 +3339,12 @@ static int alg_test_kpp(const struct alg_test_desc *desc, const char *driver, | |||
2493 | return err; | 3339 | return err; |
2494 | } | 3340 | } |
2495 | 3341 | ||
3342 | static u8 *test_pack_u32(u8 *dst, u32 val) | ||
3343 | { | ||
3344 | memcpy(dst, &val, sizeof(val)); | ||
3345 | return dst + sizeof(val); | ||
3346 | } | ||
3347 | |||
2496 | static int test_akcipher_one(struct crypto_akcipher *tfm, | 3348 | static int test_akcipher_one(struct crypto_akcipher *tfm, |
2497 | const struct akcipher_testvec *vecs) | 3349 | const struct akcipher_testvec *vecs) |
2498 | { | 3350 | { |
@@ -2503,10 +3355,11 @@ static int test_akcipher_one(struct crypto_akcipher *tfm, | |||
2503 | struct crypto_wait wait; | 3355 | struct crypto_wait wait; |
2504 | unsigned int out_len_max, out_len = 0; | 3356 | unsigned int out_len_max, out_len = 0; |
2505 | int err = -ENOMEM; | 3357 | int err = -ENOMEM; |
2506 | struct scatterlist src, dst, src_tab[2]; | 3358 | struct scatterlist src, dst, src_tab[3]; |
2507 | const char *m, *c; | 3359 | const char *m, *c; |
2508 | unsigned int m_size, c_size; | 3360 | unsigned int m_size, c_size; |
2509 | const char *op; | 3361 | const char *op; |
3362 | u8 *key, *ptr; | ||
2510 | 3363 | ||
2511 | if (testmgr_alloc_buf(xbuf)) | 3364 | if (testmgr_alloc_buf(xbuf)) |
2512 | return err; | 3365 | return err; |
@@ -2517,22 +3370,29 @@ static int test_akcipher_one(struct crypto_akcipher *tfm, | |||
2517 | 3370 | ||
2518 | crypto_init_wait(&wait); | 3371 | crypto_init_wait(&wait); |
2519 | 3372 | ||
3373 | key = kmalloc(vecs->key_len + sizeof(u32) * 2 + vecs->param_len, | ||
3374 | GFP_KERNEL); | ||
3375 | if (!key) | ||
3376 | goto free_xbuf; | ||
3377 | memcpy(key, vecs->key, vecs->key_len); | ||
3378 | ptr = key + vecs->key_len; | ||
3379 | ptr = test_pack_u32(ptr, vecs->algo); | ||
3380 | ptr = test_pack_u32(ptr, vecs->param_len); | ||
3381 | memcpy(ptr, vecs->params, vecs->param_len); | ||
3382 | |||
2520 | if (vecs->public_key_vec) | 3383 | if (vecs->public_key_vec) |
2521 | err = crypto_akcipher_set_pub_key(tfm, vecs->key, | 3384 | err = crypto_akcipher_set_pub_key(tfm, key, vecs->key_len); |
2522 | vecs->key_len); | ||
2523 | else | 3385 | else |
2524 | err = crypto_akcipher_set_priv_key(tfm, vecs->key, | 3386 | err = crypto_akcipher_set_priv_key(tfm, key, vecs->key_len); |
2525 | vecs->key_len); | ||
2526 | if (err) | 3387 | if (err) |
2527 | goto free_req; | 3388 | goto free_req; |
2528 | 3389 | ||
2529 | err = -ENOMEM; | ||
2530 | out_len_max = crypto_akcipher_maxsize(tfm); | ||
2531 | |||
2532 | /* | 3390 | /* |
2533 | * First run test which do not require a private key, such as | 3391 | * First run test which do not require a private key, such as |
2534 | * encrypt or verify. | 3392 | * encrypt or verify. |
2535 | */ | 3393 | */ |
3394 | err = -ENOMEM; | ||
3395 | out_len_max = crypto_akcipher_maxsize(tfm); | ||
2536 | outbuf_enc = kzalloc(out_len_max, GFP_KERNEL); | 3396 | outbuf_enc = kzalloc(out_len_max, GFP_KERNEL); |
2537 | if (!outbuf_enc) | 3397 | if (!outbuf_enc) |
2538 | goto free_req; | 3398 | goto free_req; |
@@ -2558,12 +3418,20 @@ static int test_akcipher_one(struct crypto_akcipher *tfm, | |||
2558 | goto free_all; | 3418 | goto free_all; |
2559 | memcpy(xbuf[0], m, m_size); | 3419 | memcpy(xbuf[0], m, m_size); |
2560 | 3420 | ||
2561 | sg_init_table(src_tab, 2); | 3421 | sg_init_table(src_tab, 3); |
2562 | sg_set_buf(&src_tab[0], xbuf[0], 8); | 3422 | sg_set_buf(&src_tab[0], xbuf[0], 8); |
2563 | sg_set_buf(&src_tab[1], xbuf[0] + 8, m_size - 8); | 3423 | sg_set_buf(&src_tab[1], xbuf[0] + 8, m_size - 8); |
2564 | sg_init_one(&dst, outbuf_enc, out_len_max); | 3424 | if (vecs->siggen_sigver_test) { |
2565 | akcipher_request_set_crypt(req, src_tab, &dst, m_size, | 3425 | if (WARN_ON(c_size > PAGE_SIZE)) |
2566 | out_len_max); | 3426 | goto free_all; |
3427 | memcpy(xbuf[1], c, c_size); | ||
3428 | sg_set_buf(&src_tab[2], xbuf[1], c_size); | ||
3429 | akcipher_request_set_crypt(req, src_tab, NULL, m_size, c_size); | ||
3430 | } else { | ||
3431 | sg_init_one(&dst, outbuf_enc, out_len_max); | ||
3432 | akcipher_request_set_crypt(req, src_tab, &dst, m_size, | ||
3433 | out_len_max); | ||
3434 | } | ||
2567 | akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, | 3435 | akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, |
2568 | crypto_req_done, &wait); | 3436 | crypto_req_done, &wait); |
2569 | 3437 | ||
@@ -2576,18 +3444,21 @@ static int test_akcipher_one(struct crypto_akcipher *tfm, | |||
2576 | pr_err("alg: akcipher: %s test failed. err %d\n", op, err); | 3444 | pr_err("alg: akcipher: %s test failed. err %d\n", op, err); |
2577 | goto free_all; | 3445 | goto free_all; |
2578 | } | 3446 | } |
2579 | if (req->dst_len != c_size) { | 3447 | if (!vecs->siggen_sigver_test) { |
2580 | pr_err("alg: akcipher: %s test failed. Invalid output len\n", | 3448 | if (req->dst_len != c_size) { |
2581 | op); | 3449 | pr_err("alg: akcipher: %s test failed. Invalid output len\n", |
2582 | err = -EINVAL; | 3450 | op); |
2583 | goto free_all; | 3451 | err = -EINVAL; |
2584 | } | 3452 | goto free_all; |
2585 | /* verify that encrypted message is equal to expected */ | 3453 | } |
2586 | if (memcmp(c, outbuf_enc, c_size)) { | 3454 | /* verify that encrypted message is equal to expected */ |
2587 | pr_err("alg: akcipher: %s test failed. Invalid output\n", op); | 3455 | if (memcmp(c, outbuf_enc, c_size) != 0) { |
2588 | hexdump(outbuf_enc, c_size); | 3456 | pr_err("alg: akcipher: %s test failed. Invalid output\n", |
2589 | err = -EINVAL; | 3457 | op); |
2590 | goto free_all; | 3458 | hexdump(outbuf_enc, c_size); |
3459 | err = -EINVAL; | ||
3460 | goto free_all; | ||
3461 | } | ||
2591 | } | 3462 | } |
2592 | 3463 | ||
2593 | /* | 3464 | /* |
@@ -2642,6 +3513,7 @@ free_all: | |||
2642 | kfree(outbuf_enc); | 3513 | kfree(outbuf_enc); |
2643 | free_req: | 3514 | free_req: |
2644 | akcipher_request_free(req); | 3515 | akcipher_request_free(req); |
3516 | kfree(key); | ||
2645 | free_xbuf: | 3517 | free_xbuf: |
2646 | testmgr_free_buf(xbuf); | 3518 | testmgr_free_buf(xbuf); |
2647 | return err; | 3519 | return err; |
@@ -2699,12 +3571,14 @@ static int alg_test_null(const struct alg_test_desc *desc, | |||
2699 | static const struct alg_test_desc alg_test_descs[] = { | 3571 | static const struct alg_test_desc alg_test_descs[] = { |
2700 | { | 3572 | { |
2701 | .alg = "adiantum(xchacha12,aes)", | 3573 | .alg = "adiantum(xchacha12,aes)", |
3574 | .generic_driver = "adiantum(xchacha12-generic,aes-generic,nhpoly1305-generic)", | ||
2702 | .test = alg_test_skcipher, | 3575 | .test = alg_test_skcipher, |
2703 | .suite = { | 3576 | .suite = { |
2704 | .cipher = __VECS(adiantum_xchacha12_aes_tv_template) | 3577 | .cipher = __VECS(adiantum_xchacha12_aes_tv_template) |
2705 | }, | 3578 | }, |
2706 | }, { | 3579 | }, { |
2707 | .alg = "adiantum(xchacha20,aes)", | 3580 | .alg = "adiantum(xchacha20,aes)", |
3581 | .generic_driver = "adiantum(xchacha20-generic,aes-generic,nhpoly1305-generic)", | ||
2708 | .test = alg_test_skcipher, | 3582 | .test = alg_test_skcipher, |
2709 | .suite = { | 3583 | .suite = { |
2710 | .cipher = __VECS(adiantum_xchacha20_aes_tv_template) | 3584 | .cipher = __VECS(adiantum_xchacha20_aes_tv_template) |
@@ -2921,6 +3795,12 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
2921 | .test = alg_test_null, | 3795 | .test = alg_test_null, |
2922 | .fips_allowed = 1, | 3796 | .fips_allowed = 1, |
2923 | }, { | 3797 | }, { |
3798 | /* Same as cbc(sm4) except the key is stored in | ||
3799 | * hardware secure memory which we reference by index | ||
3800 | */ | ||
3801 | .alg = "cbc(psm4)", | ||
3802 | .test = alg_test_null, | ||
3803 | }, { | ||
2924 | .alg = "cbc(serpent)", | 3804 | .alg = "cbc(serpent)", |
2925 | .test = alg_test_skcipher, | 3805 | .test = alg_test_skcipher, |
2926 | .suite = { | 3806 | .suite = { |
@@ -2947,6 +3827,7 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
2947 | } | 3827 | } |
2948 | }, { | 3828 | }, { |
2949 | .alg = "ccm(aes)", | 3829 | .alg = "ccm(aes)", |
3830 | .generic_driver = "ccm_base(ctr(aes-generic),cbcmac(aes-generic))", | ||
2950 | .test = alg_test_aead, | 3831 | .test = alg_test_aead, |
2951 | .fips_allowed = 1, | 3832 | .fips_allowed = 1, |
2952 | .suite = { | 3833 | .suite = { |
@@ -3055,6 +3936,13 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
3055 | .test = alg_test_null, | 3936 | .test = alg_test_null, |
3056 | .fips_allowed = 1, | 3937 | .fips_allowed = 1, |
3057 | }, { | 3938 | }, { |
3939 | |||
3940 | /* Same as ctr(sm4) except the key is stored in | ||
3941 | * hardware secure memory which we reference by index | ||
3942 | */ | ||
3943 | .alg = "ctr(psm4)", | ||
3944 | .test = alg_test_null, | ||
3945 | }, { | ||
3058 | .alg = "ctr(serpent)", | 3946 | .alg = "ctr(serpent)", |
3059 | .test = alg_test_skcipher, | 3947 | .test = alg_test_skcipher, |
3060 | .suite = { | 3948 | .suite = { |
@@ -3080,6 +3968,13 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
3080 | .cipher = __VECS(cts_mode_tv_template) | 3968 | .cipher = __VECS(cts_mode_tv_template) |
3081 | } | 3969 | } |
3082 | }, { | 3970 | }, { |
3971 | /* Same as cts(cbc((aes)) except the key is stored in | ||
3972 | * hardware secure memory which we reference by index | ||
3973 | */ | ||
3974 | .alg = "cts(cbc(paes))", | ||
3975 | .test = alg_test_null, | ||
3976 | .fips_allowed = 1, | ||
3977 | }, { | ||
3083 | .alg = "deflate", | 3978 | .alg = "deflate", |
3084 | .test = alg_test_comp, | 3979 | .test = alg_test_comp, |
3085 | .fips_allowed = 1, | 3980 | .fips_allowed = 1, |
@@ -3358,7 +4253,14 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
3358 | .kpp = __VECS(ecdh_tv_template) | 4253 | .kpp = __VECS(ecdh_tv_template) |
3359 | } | 4254 | } |
3360 | }, { | 4255 | }, { |
4256 | .alg = "ecrdsa", | ||
4257 | .test = alg_test_akcipher, | ||
4258 | .suite = { | ||
4259 | .akcipher = __VECS(ecrdsa_tv_template) | ||
4260 | } | ||
4261 | }, { | ||
3361 | .alg = "gcm(aes)", | 4262 | .alg = "gcm(aes)", |
4263 | .generic_driver = "gcm_base(ctr(aes-generic),ghash-generic)", | ||
3362 | .test = alg_test_aead, | 4264 | .test = alg_test_aead, |
3363 | .fips_allowed = 1, | 4265 | .fips_allowed = 1, |
3364 | .suite = { | 4266 | .suite = { |
@@ -3477,30 +4379,35 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
3477 | } | 4379 | } |
3478 | }, { | 4380 | }, { |
3479 | .alg = "lrw(aes)", | 4381 | .alg = "lrw(aes)", |
4382 | .generic_driver = "lrw(ecb(aes-generic))", | ||
3480 | .test = alg_test_skcipher, | 4383 | .test = alg_test_skcipher, |
3481 | .suite = { | 4384 | .suite = { |
3482 | .cipher = __VECS(aes_lrw_tv_template) | 4385 | .cipher = __VECS(aes_lrw_tv_template) |
3483 | } | 4386 | } |
3484 | }, { | 4387 | }, { |
3485 | .alg = "lrw(camellia)", | 4388 | .alg = "lrw(camellia)", |
4389 | .generic_driver = "lrw(ecb(camellia-generic))", | ||
3486 | .test = alg_test_skcipher, | 4390 | .test = alg_test_skcipher, |
3487 | .suite = { | 4391 | .suite = { |
3488 | .cipher = __VECS(camellia_lrw_tv_template) | 4392 | .cipher = __VECS(camellia_lrw_tv_template) |
3489 | } | 4393 | } |
3490 | }, { | 4394 | }, { |
3491 | .alg = "lrw(cast6)", | 4395 | .alg = "lrw(cast6)", |
4396 | .generic_driver = "lrw(ecb(cast6-generic))", | ||
3492 | .test = alg_test_skcipher, | 4397 | .test = alg_test_skcipher, |
3493 | .suite = { | 4398 | .suite = { |
3494 | .cipher = __VECS(cast6_lrw_tv_template) | 4399 | .cipher = __VECS(cast6_lrw_tv_template) |
3495 | } | 4400 | } |
3496 | }, { | 4401 | }, { |
3497 | .alg = "lrw(serpent)", | 4402 | .alg = "lrw(serpent)", |
4403 | .generic_driver = "lrw(ecb(serpent-generic))", | ||
3498 | .test = alg_test_skcipher, | 4404 | .test = alg_test_skcipher, |
3499 | .suite = { | 4405 | .suite = { |
3500 | .cipher = __VECS(serpent_lrw_tv_template) | 4406 | .cipher = __VECS(serpent_lrw_tv_template) |
3501 | } | 4407 | } |
3502 | }, { | 4408 | }, { |
3503 | .alg = "lrw(twofish)", | 4409 | .alg = "lrw(twofish)", |
4410 | .generic_driver = "lrw(ecb(twofish-generic))", | ||
3504 | .test = alg_test_skcipher, | 4411 | .test = alg_test_skcipher, |
3505 | .suite = { | 4412 | .suite = { |
3506 | .cipher = __VECS(tf_lrw_tv_template) | 4413 | .cipher = __VECS(tf_lrw_tv_template) |
@@ -3625,6 +4532,7 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
3625 | } | 4532 | } |
3626 | }, { | 4533 | }, { |
3627 | .alg = "rfc4106(gcm(aes))", | 4534 | .alg = "rfc4106(gcm(aes))", |
4535 | .generic_driver = "rfc4106(gcm_base(ctr(aes-generic),ghash-generic))", | ||
3628 | .test = alg_test_aead, | 4536 | .test = alg_test_aead, |
3629 | .fips_allowed = 1, | 4537 | .fips_allowed = 1, |
3630 | .suite = { | 4538 | .suite = { |
@@ -3632,6 +4540,7 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
3632 | } | 4540 | } |
3633 | }, { | 4541 | }, { |
3634 | .alg = "rfc4309(ccm(aes))", | 4542 | .alg = "rfc4309(ccm(aes))", |
4543 | .generic_driver = "rfc4309(ccm_base(ctr(aes-generic),cbcmac(aes-generic)))", | ||
3635 | .test = alg_test_aead, | 4544 | .test = alg_test_aead, |
3636 | .fips_allowed = 1, | 4545 | .fips_allowed = 1, |
3637 | .suite = { | 4546 | .suite = { |
@@ -3639,6 +4548,7 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
3639 | } | 4548 | } |
3640 | }, { | 4549 | }, { |
3641 | .alg = "rfc4543(gcm(aes))", | 4550 | .alg = "rfc4543(gcm(aes))", |
4551 | .generic_driver = "rfc4543(gcm_base(ctr(aes-generic),ghash-generic))", | ||
3642 | .test = alg_test_aead, | 4552 | .test = alg_test_aead, |
3643 | .suite = { | 4553 | .suite = { |
3644 | .aead = __VECS(aes_gcm_rfc4543_tv_template) | 4554 | .aead = __VECS(aes_gcm_rfc4543_tv_template) |
@@ -3835,6 +4745,7 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
3835 | }, | 4745 | }, |
3836 | }, { | 4746 | }, { |
3837 | .alg = "xts(aes)", | 4747 | .alg = "xts(aes)", |
4748 | .generic_driver = "xts(ecb(aes-generic))", | ||
3838 | .test = alg_test_skcipher, | 4749 | .test = alg_test_skcipher, |
3839 | .fips_allowed = 1, | 4750 | .fips_allowed = 1, |
3840 | .suite = { | 4751 | .suite = { |
@@ -3842,12 +4753,14 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
3842 | } | 4753 | } |
3843 | }, { | 4754 | }, { |
3844 | .alg = "xts(camellia)", | 4755 | .alg = "xts(camellia)", |
4756 | .generic_driver = "xts(ecb(camellia-generic))", | ||
3845 | .test = alg_test_skcipher, | 4757 | .test = alg_test_skcipher, |
3846 | .suite = { | 4758 | .suite = { |
3847 | .cipher = __VECS(camellia_xts_tv_template) | 4759 | .cipher = __VECS(camellia_xts_tv_template) |
3848 | } | 4760 | } |
3849 | }, { | 4761 | }, { |
3850 | .alg = "xts(cast6)", | 4762 | .alg = "xts(cast6)", |
4763 | .generic_driver = "xts(ecb(cast6-generic))", | ||
3851 | .test = alg_test_skcipher, | 4764 | .test = alg_test_skcipher, |
3852 | .suite = { | 4765 | .suite = { |
3853 | .cipher = __VECS(cast6_xts_tv_template) | 4766 | .cipher = __VECS(cast6_xts_tv_template) |
@@ -3861,12 +4774,14 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
3861 | .fips_allowed = 1, | 4774 | .fips_allowed = 1, |
3862 | }, { | 4775 | }, { |
3863 | .alg = "xts(serpent)", | 4776 | .alg = "xts(serpent)", |
4777 | .generic_driver = "xts(ecb(serpent-generic))", | ||
3864 | .test = alg_test_skcipher, | 4778 | .test = alg_test_skcipher, |
3865 | .suite = { | 4779 | .suite = { |
3866 | .cipher = __VECS(serpent_xts_tv_template) | 4780 | .cipher = __VECS(serpent_xts_tv_template) |
3867 | } | 4781 | } |
3868 | }, { | 4782 | }, { |
3869 | .alg = "xts(twofish)", | 4783 | .alg = "xts(twofish)", |
4784 | .generic_driver = "xts(ecb(twofish-generic))", | ||
3870 | .test = alg_test_skcipher, | 4785 | .test = alg_test_skcipher, |
3871 | .suite = { | 4786 | .suite = { |
3872 | .cipher = __VECS(tf_xts_tv_template) | 4787 | .cipher = __VECS(tf_xts_tv_template) |
@@ -4020,8 +4935,9 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) | |||
4020 | type, mask); | 4935 | type, mask); |
4021 | 4936 | ||
4022 | test_done: | 4937 | test_done: |
4023 | if (fips_enabled && rc) | 4938 | if (rc && (fips_enabled || panic_on_fail)) |
4024 | panic("%s: %s alg self test failed in fips mode!\n", driver, alg); | 4939 | panic("alg: self-tests for %s (%s) failed in %s mode!\n", |
4940 | driver, alg, fips_enabled ? "fips" : "panic_on_fail"); | ||
4025 | 4941 | ||
4026 | if (fips_enabled && !rc) | 4942 | if (fips_enabled && !rc) |
4027 | pr_info("alg: self-tests for %s (%s) passed\n", driver, alg); | 4943 | pr_info("alg: self-tests for %s (%s) passed\n", driver, alg); |