diff options
Diffstat (limited to 'crypto/testmgr.c')
-rw-r--r-- | crypto/testmgr.c | 795 |
1 files changed, 343 insertions, 452 deletions
diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 6a870e21b0cf..e5d8a0b8aea5 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c | |||
@@ -72,18 +72,6 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) | |||
72 | #define XBUFSIZE 8 | 72 | #define XBUFSIZE 8 |
73 | 73 | ||
74 | /* | 74 | /* |
75 | * Indexes into the xbuf to simulate cross-page access. | ||
76 | */ | ||
77 | #define IDX1 32 | ||
78 | #define IDX2 32400 | ||
79 | #define IDX3 1511 | ||
80 | #define IDX4 8193 | ||
81 | #define IDX5 22222 | ||
82 | #define IDX6 17101 | ||
83 | #define IDX7 27333 | ||
84 | #define IDX8 3000 | ||
85 | |||
86 | /* | ||
87 | * Used by test_cipher() | 75 | * Used by test_cipher() |
88 | */ | 76 | */ |
89 | #define ENCRYPT 1 | 77 | #define ENCRYPT 1 |
@@ -149,9 +137,6 @@ struct alg_test_desc { | |||
149 | } suite; | 137 | } suite; |
150 | }; | 138 | }; |
151 | 139 | ||
152 | static const unsigned int IDX[8] = { | ||
153 | IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 }; | ||
154 | |||
155 | static void hexdump(unsigned char *buf, unsigned int len) | 140 | static void hexdump(unsigned char *buf, unsigned int len) |
156 | { | 141 | { |
157 | print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET, | 142 | print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET, |
@@ -346,6 +331,79 @@ static const struct testvec_config default_cipher_testvec_configs[] = { | |||
346 | } | 331 | } |
347 | }; | 332 | }; |
348 | 333 | ||
334 | static const struct testvec_config default_hash_testvec_configs[] = { | ||
335 | { | ||
336 | .name = "init+update+final aligned buffer", | ||
337 | .src_divs = { { .proportion_of_total = 10000 } }, | ||
338 | .finalization_type = FINALIZATION_TYPE_FINAL, | ||
339 | }, { | ||
340 | .name = "init+finup aligned buffer", | ||
341 | .src_divs = { { .proportion_of_total = 10000 } }, | ||
342 | .finalization_type = FINALIZATION_TYPE_FINUP, | ||
343 | }, { | ||
344 | .name = "digest aligned buffer", | ||
345 | .src_divs = { { .proportion_of_total = 10000 } }, | ||
346 | .finalization_type = FINALIZATION_TYPE_DIGEST, | ||
347 | }, { | ||
348 | .name = "init+update+final misaligned buffer", | ||
349 | .src_divs = { { .proportion_of_total = 10000, .offset = 1 } }, | ||
350 | .finalization_type = FINALIZATION_TYPE_FINAL, | ||
351 | }, { | ||
352 | .name = "digest buffer aligned only to alignmask", | ||
353 | .src_divs = { | ||
354 | { | ||
355 | .proportion_of_total = 10000, | ||
356 | .offset = 1, | ||
357 | .offset_relative_to_alignmask = true, | ||
358 | }, | ||
359 | }, | ||
360 | .finalization_type = FINALIZATION_TYPE_DIGEST, | ||
361 | }, { | ||
362 | .name = "init+update+update+final two even splits", | ||
363 | .src_divs = { | ||
364 | { .proportion_of_total = 5000 }, | ||
365 | { | ||
366 | .proportion_of_total = 5000, | ||
367 | .flush_type = FLUSH_TYPE_FLUSH, | ||
368 | }, | ||
369 | }, | ||
370 | .finalization_type = FINALIZATION_TYPE_FINAL, | ||
371 | }, { | ||
372 | .name = "digest uneven misaligned splits, may sleep", | ||
373 | .req_flags = CRYPTO_TFM_REQ_MAY_SLEEP, | ||
374 | .src_divs = { | ||
375 | { .proportion_of_total = 1900, .offset = 33 }, | ||
376 | { .proportion_of_total = 3300, .offset = 7 }, | ||
377 | { .proportion_of_total = 4800, .offset = 18 }, | ||
378 | }, | ||
379 | .finalization_type = FINALIZATION_TYPE_DIGEST, | ||
380 | }, { | ||
381 | .name = "digest misaligned splits crossing pages", | ||
382 | .src_divs = { | ||
383 | { | ||
384 | .proportion_of_total = 7500, | ||
385 | .offset = PAGE_SIZE - 32, | ||
386 | }, { | ||
387 | .proportion_of_total = 2500, | ||
388 | .offset = PAGE_SIZE - 7, | ||
389 | }, | ||
390 | }, | ||
391 | .finalization_type = FINALIZATION_TYPE_DIGEST, | ||
392 | }, { | ||
393 | .name = "import/export", | ||
394 | .src_divs = { | ||
395 | { | ||
396 | .proportion_of_total = 6500, | ||
397 | .flush_type = FLUSH_TYPE_REIMPORT, | ||
398 | }, { | ||
399 | .proportion_of_total = 3500, | ||
400 | .flush_type = FLUSH_TYPE_REIMPORT, | ||
401 | }, | ||
402 | }, | ||
403 | .finalization_type = FINALIZATION_TYPE_FINAL, | ||
404 | } | ||
405 | }; | ||
406 | |||
349 | static unsigned int count_test_sg_divisions(const struct test_sg_division *divs) | 407 | static unsigned int count_test_sg_divisions(const struct test_sg_division *divs) |
350 | { | 408 | { |
351 | unsigned int remaining = TEST_SG_TOTAL; | 409 | unsigned int remaining = TEST_SG_TOTAL; |
@@ -782,430 +840,320 @@ static void generate_random_testvec_config(struct testvec_config *cfg, | |||
782 | } | 840 | } |
783 | #endif /* CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ | 841 | #endif /* CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */ |
784 | 842 | ||
785 | static int ahash_guard_result(char *result, char c, int size) | 843 | static int check_nonfinal_hash_op(const char *op, int err, |
844 | u8 *result, unsigned int digestsize, | ||
845 | const char *driver, unsigned int vec_num, | ||
846 | const struct testvec_config *cfg) | ||
786 | { | 847 | { |
787 | int i; | 848 | if (err) { |
788 | 849 | pr_err("alg: hash: %s %s() failed with err %d on test vector %u, cfg=\"%s\"\n", | |
789 | for (i = 0; i < size; i++) { | 850 | driver, op, err, vec_num, cfg->name); |
790 | if (result[i] != c) | 851 | return err; |
791 | return -EINVAL; | ||
792 | } | ||
793 | |||
794 | return 0; | ||
795 | } | ||
796 | |||
797 | static int ahash_partial_update(struct ahash_request **preq, | ||
798 | struct crypto_ahash *tfm, const struct hash_testvec *template, | ||
799 | void *hash_buff, int k, int temp, struct scatterlist *sg, | ||
800 | const char *algo, char *result, struct crypto_wait *wait) | ||
801 | { | ||
802 | char *state; | ||
803 | struct ahash_request *req; | ||
804 | int statesize, ret = -EINVAL; | ||
805 | static const unsigned char guard[] = { 0x00, 0xba, 0xad, 0x00 }; | ||
806 | int digestsize = crypto_ahash_digestsize(tfm); | ||
807 | |||
808 | req = *preq; | ||
809 | statesize = crypto_ahash_statesize( | ||
810 | crypto_ahash_reqtfm(req)); | ||
811 | state = kmalloc(statesize + sizeof(guard), GFP_KERNEL); | ||
812 | if (!state) { | ||
813 | pr_err("alg: hash: Failed to alloc state for %s\n", algo); | ||
814 | goto out_nostate; | ||
815 | } | ||
816 | memcpy(state + statesize, guard, sizeof(guard)); | ||
817 | memset(result, 1, digestsize); | ||
818 | ret = crypto_ahash_export(req, state); | ||
819 | WARN_ON(memcmp(state + statesize, guard, sizeof(guard))); | ||
820 | if (ret) { | ||
821 | pr_err("alg: hash: Failed to export() for %s\n", algo); | ||
822 | goto out; | ||
823 | } | ||
824 | ret = ahash_guard_result(result, 1, digestsize); | ||
825 | if (ret) { | ||
826 | pr_err("alg: hash: Failed, export used req->result for %s\n", | ||
827 | algo); | ||
828 | goto out; | ||
829 | } | ||
830 | ahash_request_free(req); | ||
831 | req = ahash_request_alloc(tfm, GFP_KERNEL); | ||
832 | if (!req) { | ||
833 | pr_err("alg: hash: Failed to alloc request for %s\n", algo); | ||
834 | goto out_noreq; | ||
835 | } | ||
836 | ahash_request_set_callback(req, | ||
837 | CRYPTO_TFM_REQ_MAY_BACKLOG, | ||
838 | crypto_req_done, wait); | ||
839 | |||
840 | memcpy(hash_buff, template->plaintext + temp, | ||
841 | template->tap[k]); | ||
842 | sg_init_one(&sg[0], hash_buff, template->tap[k]); | ||
843 | ahash_request_set_crypt(req, sg, result, template->tap[k]); | ||
844 | ret = crypto_ahash_import(req, state); | ||
845 | if (ret) { | ||
846 | pr_err("alg: hash: Failed to import() for %s\n", algo); | ||
847 | goto out; | ||
848 | } | 852 | } |
849 | ret = ahash_guard_result(result, 1, digestsize); | 853 | if (!testmgr_is_poison(result, digestsize)) { |
850 | if (ret) { | 854 | pr_err("alg: hash: %s %s() used result buffer on test vector %u, cfg=\"%s\"\n", |
851 | pr_err("alg: hash: Failed, import used req->result for %s\n", | 855 | driver, op, vec_num, cfg->name); |
852 | algo); | 856 | return -EINVAL; |
853 | goto out; | ||
854 | } | 857 | } |
855 | ret = crypto_wait_req(crypto_ahash_update(req), wait); | 858 | return 0; |
856 | if (ret) | ||
857 | goto out; | ||
858 | *preq = req; | ||
859 | ret = 0; | ||
860 | goto out_noreq; | ||
861 | out: | ||
862 | ahash_request_free(req); | ||
863 | out_noreq: | ||
864 | kfree(state); | ||
865 | out_nostate: | ||
866 | return ret; | ||
867 | } | 859 | } |
868 | 860 | ||
869 | enum hash_test { | 861 | static int test_hash_vec_cfg(const char *driver, |
870 | HASH_TEST_DIGEST, | 862 | const struct hash_testvec *vec, |
871 | HASH_TEST_FINAL, | 863 | unsigned int vec_num, |
872 | HASH_TEST_FINUP | 864 | const struct testvec_config *cfg, |
873 | }; | 865 | struct ahash_request *req, |
874 | 866 | struct test_sglist *tsgl, | |
875 | static int __test_hash(struct crypto_ahash *tfm, | 867 | u8 *hashstate) |
876 | const struct hash_testvec *template, unsigned int tcount, | ||
877 | enum hash_test test_type, const int align_offset) | ||
878 | { | 868 | { |
879 | const char *algo = crypto_tfm_alg_driver_name(crypto_ahash_tfm(tfm)); | 869 | struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); |
880 | size_t digest_size = crypto_ahash_digestsize(tfm); | 870 | const unsigned int alignmask = crypto_ahash_alignmask(tfm); |
881 | unsigned int i, j, k, temp; | 871 | const unsigned int digestsize = crypto_ahash_digestsize(tfm); |
882 | struct scatterlist sg[8]; | 872 | const unsigned int statesize = crypto_ahash_statesize(tfm); |
883 | char *result; | 873 | const u32 req_flags = CRYPTO_TFM_REQ_MAY_BACKLOG | cfg->req_flags; |
884 | char *key; | 874 | const struct test_sg_division *divs[XBUFSIZE]; |
885 | struct ahash_request *req; | 875 | DECLARE_CRYPTO_WAIT(wait); |
886 | struct crypto_wait wait; | 876 | struct kvec _input; |
887 | void *hash_buff; | 877 | struct iov_iter input; |
888 | char *xbuf[XBUFSIZE]; | 878 | unsigned int i; |
889 | int ret = -ENOMEM; | 879 | struct scatterlist *pending_sgl; |
890 | 880 | unsigned int pending_len; | |
891 | result = kmalloc(digest_size, GFP_KERNEL); | 881 | u8 result[HASH_MAX_DIGESTSIZE + TESTMGR_POISON_LEN]; |
892 | if (!result) | 882 | int err; |
893 | return ret; | ||
894 | key = kmalloc(MAX_KEYLEN, GFP_KERNEL); | ||
895 | if (!key) | ||
896 | goto out_nobuf; | ||
897 | if (testmgr_alloc_buf(xbuf)) | ||
898 | goto out_nobuf; | ||
899 | 883 | ||
900 | crypto_init_wait(&wait); | 884 | /* Set the key, if specified */ |
885 | if (vec->ksize) { | ||
886 | err = crypto_ahash_setkey(tfm, vec->key, vec->ksize); | ||
887 | if (err) { | ||
888 | pr_err("alg: hash: %s setkey failed with err %d on test vector %u; flags=%#x\n", | ||
889 | driver, err, vec_num, | ||
890 | crypto_ahash_get_flags(tfm)); | ||
891 | return err; | ||
892 | } | ||
893 | } | ||
901 | 894 | ||
902 | req = ahash_request_alloc(tfm, GFP_KERNEL); | 895 | /* Build the scatterlist for the source data */ |
903 | if (!req) { | 896 | _input.iov_base = (void *)vec->plaintext; |
904 | printk(KERN_ERR "alg: hash: Failed to allocate request for " | 897 | _input.iov_len = vec->psize; |
905 | "%s\n", algo); | 898 | iov_iter_kvec(&input, WRITE, &_input, 1, vec->psize); |
906 | goto out_noreq; | 899 | err = build_test_sglist(tsgl, cfg->src_divs, alignmask, vec->psize, |
900 | &input, divs); | ||
901 | if (err) { | ||
902 | pr_err("alg: hash: %s: error preparing scatterlist for test vector %u, cfg=\"%s\"\n", | ||
903 | driver, vec_num, cfg->name); | ||
904 | return err; | ||
907 | } | 905 | } |
908 | ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, | ||
909 | crypto_req_done, &wait); | ||
910 | 906 | ||
911 | j = 0; | 907 | /* Do the actual hashing */ |
912 | for (i = 0; i < tcount; i++) { | ||
913 | if (template[i].np) | ||
914 | continue; | ||
915 | 908 | ||
916 | ret = -EINVAL; | 909 | testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm)); |
917 | if (WARN_ON(align_offset + template[i].psize > PAGE_SIZE)) | 910 | testmgr_poison(result, digestsize + TESTMGR_POISON_LEN); |
918 | goto out; | ||
919 | 911 | ||
920 | j++; | 912 | if (cfg->finalization_type == FINALIZATION_TYPE_DIGEST) { |
921 | memset(result, 0, digest_size); | 913 | /* Just using digest() */ |
914 | ahash_request_set_callback(req, req_flags, crypto_req_done, | ||
915 | &wait); | ||
916 | ahash_request_set_crypt(req, tsgl->sgl, result, vec->psize); | ||
917 | err = crypto_wait_req(crypto_ahash_digest(req), &wait); | ||
918 | if (err) { | ||
919 | pr_err("alg: hash: %s digest() failed with err %d on test vector %u, cfg=\"%s\"\n", | ||
920 | driver, err, vec_num, cfg->name); | ||
921 | return err; | ||
922 | } | ||
923 | goto result_ready; | ||
924 | } | ||
922 | 925 | ||
923 | hash_buff = xbuf[0]; | 926 | /* Using init(), zero or more update(), then final() or finup() */ |
924 | hash_buff += align_offset; | ||
925 | 927 | ||
926 | memcpy(hash_buff, template[i].plaintext, template[i].psize); | 928 | ahash_request_set_callback(req, req_flags, crypto_req_done, &wait); |
927 | sg_init_one(&sg[0], hash_buff, template[i].psize); | 929 | ahash_request_set_crypt(req, NULL, result, 0); |
930 | err = crypto_wait_req(crypto_ahash_init(req), &wait); | ||
931 | err = check_nonfinal_hash_op("init", err, result, digestsize, | ||
932 | driver, vec_num, cfg); | ||
933 | if (err) | ||
934 | return err; | ||
928 | 935 | ||
929 | if (template[i].ksize) { | 936 | pending_sgl = NULL; |
930 | crypto_ahash_clear_flags(tfm, ~0); | 937 | pending_len = 0; |
931 | if (template[i].ksize > MAX_KEYLEN) { | 938 | for (i = 0; i < tsgl->nents; i++) { |
932 | pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n", | 939 | if (divs[i]->flush_type != FLUSH_TYPE_NONE && |
933 | j, algo, template[i].ksize, MAX_KEYLEN); | 940 | pending_sgl != NULL) { |
934 | ret = -EINVAL; | 941 | /* update() with the pending data */ |
935 | goto out; | 942 | ahash_request_set_callback(req, req_flags, |
936 | } | 943 | crypto_req_done, &wait); |
937 | memcpy(key, template[i].key, template[i].ksize); | 944 | ahash_request_set_crypt(req, pending_sgl, result, |
938 | ret = crypto_ahash_setkey(tfm, key, template[i].ksize); | 945 | pending_len); |
939 | if (ret) { | 946 | err = crypto_wait_req(crypto_ahash_update(req), &wait); |
940 | printk(KERN_ERR "alg: hash: setkey failed on " | 947 | err = check_nonfinal_hash_op("update", err, |
941 | "test %d for %s: ret=%d\n", j, algo, | 948 | result, digestsize, |
942 | -ret); | 949 | driver, vec_num, cfg); |
943 | goto out; | 950 | if (err) |
944 | } | 951 | return err; |
952 | pending_sgl = NULL; | ||
953 | pending_len = 0; | ||
945 | } | 954 | } |
946 | 955 | if (divs[i]->flush_type == FLUSH_TYPE_REIMPORT) { | |
947 | ahash_request_set_crypt(req, sg, result, template[i].psize); | 956 | /* Test ->export() and ->import() */ |
948 | switch (test_type) { | 957 | testmgr_poison(hashstate + statesize, |
949 | case HASH_TEST_DIGEST: | 958 | TESTMGR_POISON_LEN); |
950 | ret = crypto_wait_req(crypto_ahash_digest(req), &wait); | 959 | err = crypto_ahash_export(req, hashstate); |
951 | if (ret) { | 960 | err = check_nonfinal_hash_op("export", err, |
952 | pr_err("alg: hash: digest failed on test %d " | 961 | result, digestsize, |
953 | "for %s: ret=%d\n", j, algo, -ret); | 962 | driver, vec_num, cfg); |
954 | goto out; | 963 | if (err) |
955 | } | 964 | return err; |
956 | break; | 965 | if (!testmgr_is_poison(hashstate + statesize, |
957 | 966 | TESTMGR_POISON_LEN)) { | |
958 | case HASH_TEST_FINAL: | 967 | pr_err("alg: hash: %s export() overran state buffer on test vector %u, cfg=\"%s\"\n", |
959 | memset(result, 1, digest_size); | 968 | driver, vec_num, cfg->name); |
960 | ret = crypto_wait_req(crypto_ahash_init(req), &wait); | 969 | return -EOVERFLOW; |
961 | if (ret) { | ||
962 | pr_err("alg: hash: init failed on test %d " | ||
963 | "for %s: ret=%d\n", j, algo, -ret); | ||
964 | goto out; | ||
965 | } | ||
966 | ret = ahash_guard_result(result, 1, digest_size); | ||
967 | if (ret) { | ||
968 | pr_err("alg: hash: init failed on test %d " | ||
969 | "for %s: used req->result\n", j, algo); | ||
970 | goto out; | ||
971 | } | ||
972 | ret = crypto_wait_req(crypto_ahash_update(req), &wait); | ||
973 | if (ret) { | ||
974 | pr_err("alg: hash: update failed on test %d " | ||
975 | "for %s: ret=%d\n", j, algo, -ret); | ||
976 | goto out; | ||
977 | } | ||
978 | ret = ahash_guard_result(result, 1, digest_size); | ||
979 | if (ret) { | ||
980 | pr_err("alg: hash: update failed on test %d " | ||
981 | "for %s: used req->result\n", j, algo); | ||
982 | goto out; | ||
983 | } | ||
984 | ret = crypto_wait_req(crypto_ahash_final(req), &wait); | ||
985 | if (ret) { | ||
986 | pr_err("alg: hash: final failed on test %d " | ||
987 | "for %s: ret=%d\n", j, algo, -ret); | ||
988 | goto out; | ||
989 | } | 970 | } |
990 | break; | ||
991 | 971 | ||
992 | case HASH_TEST_FINUP: | 972 | testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm)); |
993 | memset(result, 1, digest_size); | 973 | err = crypto_ahash_import(req, hashstate); |
994 | ret = crypto_wait_req(crypto_ahash_init(req), &wait); | 974 | err = check_nonfinal_hash_op("import", err, |
995 | if (ret) { | 975 | result, digestsize, |
996 | pr_err("alg: hash: init failed on test %d " | 976 | driver, vec_num, cfg); |
997 | "for %s: ret=%d\n", j, algo, -ret); | 977 | if (err) |
998 | goto out; | 978 | return err; |
999 | } | ||
1000 | ret = ahash_guard_result(result, 1, digest_size); | ||
1001 | if (ret) { | ||
1002 | pr_err("alg: hash: init failed on test %d " | ||
1003 | "for %s: used req->result\n", j, algo); | ||
1004 | goto out; | ||
1005 | } | ||
1006 | ret = crypto_wait_req(crypto_ahash_finup(req), &wait); | ||
1007 | if (ret) { | ||
1008 | pr_err("alg: hash: final failed on test %d " | ||
1009 | "for %s: ret=%d\n", j, algo, -ret); | ||
1010 | goto out; | ||
1011 | } | ||
1012 | break; | ||
1013 | } | 979 | } |
980 | if (pending_sgl == NULL) | ||
981 | pending_sgl = &tsgl->sgl[i]; | ||
982 | pending_len += tsgl->sgl[i].length; | ||
983 | } | ||
1014 | 984 | ||
1015 | if (memcmp(result, template[i].digest, | 985 | ahash_request_set_callback(req, req_flags, crypto_req_done, &wait); |
1016 | crypto_ahash_digestsize(tfm))) { | 986 | ahash_request_set_crypt(req, pending_sgl, result, pending_len); |
1017 | printk(KERN_ERR "alg: hash: Test %d failed for %s\n", | 987 | if (cfg->finalization_type == FINALIZATION_TYPE_FINAL) { |
1018 | j, algo); | 988 | /* finish with update() and final() */ |
1019 | hexdump(result, crypto_ahash_digestsize(tfm)); | 989 | err = crypto_wait_req(crypto_ahash_update(req), &wait); |
1020 | ret = -EINVAL; | 990 | err = check_nonfinal_hash_op("update", err, result, digestsize, |
1021 | goto out; | 991 | driver, vec_num, cfg); |
992 | if (err) | ||
993 | return err; | ||
994 | err = crypto_wait_req(crypto_ahash_final(req), &wait); | ||
995 | if (err) { | ||
996 | pr_err("alg: hash: %s final() failed with err %d on test vector %u, cfg=\"%s\"\n", | ||
997 | driver, err, vec_num, cfg->name); | ||
998 | return err; | ||
999 | } | ||
1000 | } else { | ||
1001 | /* finish with finup() */ | ||
1002 | err = crypto_wait_req(crypto_ahash_finup(req), &wait); | ||
1003 | if (err) { | ||
1004 | pr_err("alg: hash: %s finup() failed with err %d on test vector %u, cfg=\"%s\"\n", | ||
1005 | driver, err, vec_num, cfg->name); | ||
1006 | return err; | ||
1022 | } | 1007 | } |
1023 | } | 1008 | } |
1024 | 1009 | ||
1025 | if (test_type) | 1010 | result_ready: |
1026 | goto out; | 1011 | /* Check that the algorithm produced the correct digest */ |
1027 | 1012 | if (memcmp(result, vec->digest, digestsize) != 0) { | |
1028 | j = 0; | 1013 | pr_err("alg: hash: %s test failed (wrong result) on test vector %u, cfg=\"%s\"\n", |
1029 | for (i = 0; i < tcount; i++) { | 1014 | driver, vec_num, cfg->name); |
1030 | /* alignment tests are only done with continuous buffers */ | 1015 | return -EINVAL; |
1031 | if (align_offset != 0) | 1016 | } |
1032 | break; | 1017 | 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", | ||
1019 | driver, vec_num, cfg->name); | ||
1020 | return -EOVERFLOW; | ||
1021 | } | ||
1033 | 1022 | ||
1034 | if (!template[i].np) | 1023 | return 0; |
1035 | continue; | 1024 | } |
1036 | 1025 | ||
1037 | j++; | 1026 | static int test_hash_vec(const char *driver, const struct hash_testvec *vec, |
1038 | memset(result, 0, digest_size); | 1027 | unsigned int vec_num, struct ahash_request *req, |
1028 | struct test_sglist *tsgl, u8 *hashstate) | ||
1029 | { | ||
1030 | unsigned int i; | ||
1031 | int err; | ||
1039 | 1032 | ||
1040 | temp = 0; | 1033 | for (i = 0; i < ARRAY_SIZE(default_hash_testvec_configs); i++) { |
1041 | sg_init_table(sg, template[i].np); | 1034 | err = test_hash_vec_cfg(driver, vec, vec_num, |
1042 | ret = -EINVAL; | 1035 | &default_hash_testvec_configs[i], |
1043 | for (k = 0; k < template[i].np; k++) { | 1036 | req, tsgl, hashstate); |
1044 | if (WARN_ON(offset_in_page(IDX[k]) + | 1037 | if (err) |
1045 | template[i].tap[k] > PAGE_SIZE)) | 1038 | return err; |
1046 | goto out; | 1039 | } |
1047 | sg_set_buf(&sg[k], | ||
1048 | memcpy(xbuf[IDX[k] >> PAGE_SHIFT] + | ||
1049 | offset_in_page(IDX[k]), | ||
1050 | template[i].plaintext + temp, | ||
1051 | template[i].tap[k]), | ||
1052 | template[i].tap[k]); | ||
1053 | temp += template[i].tap[k]; | ||
1054 | } | ||
1055 | |||
1056 | if (template[i].ksize) { | ||
1057 | if (template[i].ksize > MAX_KEYLEN) { | ||
1058 | pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n", | ||
1059 | j, algo, template[i].ksize, MAX_KEYLEN); | ||
1060 | ret = -EINVAL; | ||
1061 | goto out; | ||
1062 | } | ||
1063 | crypto_ahash_clear_flags(tfm, ~0); | ||
1064 | memcpy(key, template[i].key, template[i].ksize); | ||
1065 | ret = crypto_ahash_setkey(tfm, key, template[i].ksize); | ||
1066 | |||
1067 | if (ret) { | ||
1068 | printk(KERN_ERR "alg: hash: setkey " | ||
1069 | "failed on chunking test %d " | ||
1070 | "for %s: ret=%d\n", j, algo, -ret); | ||
1071 | goto out; | ||
1072 | } | ||
1073 | } | ||
1074 | 1040 | ||
1075 | ahash_request_set_crypt(req, sg, result, template[i].psize); | 1041 | #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS |
1076 | ret = crypto_wait_req(crypto_ahash_digest(req), &wait); | 1042 | if (!noextratests) { |
1077 | if (ret) { | 1043 | struct testvec_config cfg; |
1078 | pr_err("alg: hash: digest failed on chunking test %d for %s: ret=%d\n", | 1044 | char cfgname[TESTVEC_CONFIG_NAMELEN]; |
1079 | j, algo, -ret); | ||
1080 | goto out; | ||
1081 | } | ||
1082 | 1045 | ||
1083 | if (memcmp(result, template[i].digest, | 1046 | for (i = 0; i < fuzz_iterations; i++) { |
1084 | crypto_ahash_digestsize(tfm))) { | 1047 | generate_random_testvec_config(&cfg, cfgname, |
1085 | printk(KERN_ERR "alg: hash: Chunking test %d " | 1048 | sizeof(cfgname)); |
1086 | "failed for %s\n", j, algo); | 1049 | err = test_hash_vec_cfg(driver, vec, vec_num, &cfg, |
1087 | hexdump(result, crypto_ahash_digestsize(tfm)); | 1050 | req, tsgl, hashstate); |
1088 | ret = -EINVAL; | 1051 | if (err) |
1089 | goto out; | 1052 | return err; |
1090 | } | 1053 | } |
1091 | } | 1054 | } |
1055 | #endif | ||
1056 | return 0; | ||
1057 | } | ||
1092 | 1058 | ||
1093 | /* partial update exercise */ | 1059 | static int __alg_test_hash(const struct hash_testvec *vecs, |
1094 | j = 0; | 1060 | unsigned int num_vecs, const char *driver, |
1095 | for (i = 0; i < tcount; i++) { | 1061 | u32 type, u32 mask) |
1096 | /* alignment tests are only done with continuous buffers */ | 1062 | { |
1097 | if (align_offset != 0) | 1063 | struct crypto_ahash *tfm; |
1098 | break; | 1064 | struct ahash_request *req = NULL; |
1065 | struct test_sglist *tsgl = NULL; | ||
1066 | u8 *hashstate = NULL; | ||
1067 | unsigned int i; | ||
1068 | int err; | ||
1099 | 1069 | ||
1100 | if (template[i].np < 2) | 1070 | tfm = crypto_alloc_ahash(driver, type, mask); |
1101 | continue; | 1071 | if (IS_ERR(tfm)) { |
1072 | pr_err("alg: hash: failed to allocate transform for %s: %ld\n", | ||
1073 | driver, PTR_ERR(tfm)); | ||
1074 | return PTR_ERR(tfm); | ||
1075 | } | ||
1102 | 1076 | ||
1103 | j++; | 1077 | req = ahash_request_alloc(tfm, GFP_KERNEL); |
1104 | memset(result, 0, digest_size); | 1078 | if (!req) { |
1079 | pr_err("alg: hash: failed to allocate request for %s\n", | ||
1080 | driver); | ||
1081 | err = -ENOMEM; | ||
1082 | goto out; | ||
1083 | } | ||
1105 | 1084 | ||
1106 | ret = -EINVAL; | 1085 | tsgl = kmalloc(sizeof(*tsgl), GFP_KERNEL); |
1107 | hash_buff = xbuf[0]; | 1086 | if (!tsgl || init_test_sglist(tsgl) != 0) { |
1108 | memcpy(hash_buff, template[i].plaintext, | 1087 | pr_err("alg: hash: failed to allocate test buffers for %s\n", |
1109 | template[i].tap[0]); | 1088 | driver); |
1110 | sg_init_one(&sg[0], hash_buff, template[i].tap[0]); | 1089 | kfree(tsgl); |
1111 | 1090 | tsgl = NULL; | |
1112 | if (template[i].ksize) { | 1091 | err = -ENOMEM; |
1113 | crypto_ahash_clear_flags(tfm, ~0); | 1092 | goto out; |
1114 | if (template[i].ksize > MAX_KEYLEN) { | 1093 | } |
1115 | pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n", | ||
1116 | j, algo, template[i].ksize, MAX_KEYLEN); | ||
1117 | ret = -EINVAL; | ||
1118 | goto out; | ||
1119 | } | ||
1120 | memcpy(key, template[i].key, template[i].ksize); | ||
1121 | ret = crypto_ahash_setkey(tfm, key, template[i].ksize); | ||
1122 | if (ret) { | ||
1123 | pr_err("alg: hash: setkey failed on test %d for %s: ret=%d\n", | ||
1124 | j, algo, -ret); | ||
1125 | goto out; | ||
1126 | } | ||
1127 | } | ||
1128 | 1094 | ||
1129 | ahash_request_set_crypt(req, sg, result, template[i].tap[0]); | 1095 | hashstate = kmalloc(crypto_ahash_statesize(tfm) + TESTMGR_POISON_LEN, |
1130 | ret = crypto_wait_req(crypto_ahash_init(req), &wait); | 1096 | GFP_KERNEL); |
1131 | if (ret) { | 1097 | if (!hashstate) { |
1132 | pr_err("alg: hash: init failed on test %d for %s: ret=%d\n", | 1098 | pr_err("alg: hash: failed to allocate hash state buffer for %s\n", |
1133 | j, algo, -ret); | 1099 | driver); |
1134 | goto out; | 1100 | err = -ENOMEM; |
1135 | } | 1101 | goto out; |
1136 | ret = crypto_wait_req(crypto_ahash_update(req), &wait); | 1102 | } |
1137 | if (ret) { | ||
1138 | pr_err("alg: hash: update failed on test %d for %s: ret=%d\n", | ||
1139 | j, algo, -ret); | ||
1140 | goto out; | ||
1141 | } | ||
1142 | 1103 | ||
1143 | temp = template[i].tap[0]; | 1104 | for (i = 0; i < num_vecs; i++) { |
1144 | for (k = 1; k < template[i].np; k++) { | 1105 | err = test_hash_vec(driver, &vecs[i], i, req, tsgl, hashstate); |
1145 | ret = ahash_partial_update(&req, tfm, &template[i], | 1106 | if (err) |
1146 | hash_buff, k, temp, &sg[0], algo, result, | ||
1147 | &wait); | ||
1148 | if (ret) { | ||
1149 | pr_err("alg: hash: partial update failed on test %d for %s: ret=%d\n", | ||
1150 | j, algo, -ret); | ||
1151 | goto out_noreq; | ||
1152 | } | ||
1153 | temp += template[i].tap[k]; | ||
1154 | } | ||
1155 | ret = crypto_wait_req(crypto_ahash_final(req), &wait); | ||
1156 | if (ret) { | ||
1157 | pr_err("alg: hash: final failed on test %d for %s: ret=%d\n", | ||
1158 | j, algo, -ret); | ||
1159 | goto out; | ||
1160 | } | ||
1161 | if (memcmp(result, template[i].digest, | ||
1162 | crypto_ahash_digestsize(tfm))) { | ||
1163 | pr_err("alg: hash: Partial Test %d failed for %s\n", | ||
1164 | j, algo); | ||
1165 | hexdump(result, crypto_ahash_digestsize(tfm)); | ||
1166 | ret = -EINVAL; | ||
1167 | goto out; | 1107 | goto out; |
1168 | } | ||
1169 | } | 1108 | } |
1170 | 1109 | err = 0; | |
1171 | ret = 0; | ||
1172 | |||
1173 | out: | 1110 | out: |
1111 | kfree(hashstate); | ||
1112 | if (tsgl) { | ||
1113 | destroy_test_sglist(tsgl); | ||
1114 | kfree(tsgl); | ||
1115 | } | ||
1174 | ahash_request_free(req); | 1116 | ahash_request_free(req); |
1175 | out_noreq: | 1117 | crypto_free_ahash(tfm); |
1176 | testmgr_free_buf(xbuf); | 1118 | return err; |
1177 | out_nobuf: | ||
1178 | kfree(key); | ||
1179 | kfree(result); | ||
1180 | return ret; | ||
1181 | } | 1119 | } |
1182 | 1120 | ||
1183 | static int test_hash(struct crypto_ahash *tfm, | 1121 | static int alg_test_hash(const struct alg_test_desc *desc, const char *driver, |
1184 | const struct hash_testvec *template, | 1122 | u32 type, u32 mask) |
1185 | unsigned int tcount, enum hash_test test_type) | ||
1186 | { | 1123 | { |
1187 | unsigned int alignmask; | 1124 | const struct hash_testvec *template = desc->suite.hash.vecs; |
1188 | int ret; | 1125 | unsigned int tcount = desc->suite.hash.count; |
1126 | unsigned int nr_unkeyed, nr_keyed; | ||
1127 | int err; | ||
1189 | 1128 | ||
1190 | ret = __test_hash(tfm, template, tcount, test_type, 0); | 1129 | /* |
1191 | if (ret) | 1130 | * For OPTIONAL_KEY algorithms, we have to do all the unkeyed tests |
1192 | return ret; | 1131 | * first, before setting a key on the tfm. To make this easier, we |
1132 | * require that the unkeyed test vectors (if any) are listed first. | ||
1133 | */ | ||
1193 | 1134 | ||
1194 | /* test unaligned buffers, check with one byte offset */ | 1135 | for (nr_unkeyed = 0; nr_unkeyed < tcount; nr_unkeyed++) { |
1195 | ret = __test_hash(tfm, template, tcount, test_type, 1); | 1136 | if (template[nr_unkeyed].ksize) |
1196 | if (ret) | 1137 | break; |
1197 | return ret; | 1138 | } |
1139 | for (nr_keyed = 0; nr_unkeyed + nr_keyed < tcount; nr_keyed++) { | ||
1140 | if (!template[nr_unkeyed + nr_keyed].ksize) { | ||
1141 | pr_err("alg: hash: test vectors for %s out of order, " | ||
1142 | "unkeyed ones must come first\n", desc->alg); | ||
1143 | return -EINVAL; | ||
1144 | } | ||
1145 | } | ||
1198 | 1146 | ||
1199 | alignmask = crypto_tfm_alg_alignmask(&tfm->base); | 1147 | err = 0; |
1200 | if (alignmask) { | 1148 | if (nr_unkeyed) { |
1201 | /* Check if alignment mask for tfm is correctly set. */ | 1149 | err = __alg_test_hash(template, nr_unkeyed, driver, type, mask); |
1202 | ret = __test_hash(tfm, template, tcount, test_type, | 1150 | template += nr_unkeyed; |
1203 | alignmask + 1); | ||
1204 | if (ret) | ||
1205 | return ret; | ||
1206 | } | 1151 | } |
1207 | 1152 | ||
1208 | return 0; | 1153 | if (!err && nr_keyed) |
1154 | err = __alg_test_hash(template, nr_keyed, driver, type, mask); | ||
1155 | |||
1156 | return err; | ||
1209 | } | 1157 | } |
1210 | 1158 | ||
1211 | static int test_aead_vec_cfg(const char *driver, int enc, | 1159 | static int test_aead_vec_cfg(const char *driver, int enc, |
@@ -2113,67 +2061,6 @@ static int alg_test_comp(const struct alg_test_desc *desc, const char *driver, | |||
2113 | return err; | 2061 | return err; |
2114 | } | 2062 | } |
2115 | 2063 | ||
2116 | static int __alg_test_hash(const struct hash_testvec *template, | ||
2117 | unsigned int tcount, const char *driver, | ||
2118 | u32 type, u32 mask) | ||
2119 | { | ||
2120 | struct crypto_ahash *tfm; | ||
2121 | int err; | ||
2122 | |||
2123 | tfm = crypto_alloc_ahash(driver, type, mask); | ||
2124 | if (IS_ERR(tfm)) { | ||
2125 | printk(KERN_ERR "alg: hash: Failed to load transform for %s: " | ||
2126 | "%ld\n", driver, PTR_ERR(tfm)); | ||
2127 | return PTR_ERR(tfm); | ||
2128 | } | ||
2129 | |||
2130 | err = test_hash(tfm, template, tcount, HASH_TEST_DIGEST); | ||
2131 | if (!err) | ||
2132 | err = test_hash(tfm, template, tcount, HASH_TEST_FINAL); | ||
2133 | if (!err) | ||
2134 | err = test_hash(tfm, template, tcount, HASH_TEST_FINUP); | ||
2135 | crypto_free_ahash(tfm); | ||
2136 | return err; | ||
2137 | } | ||
2138 | |||
2139 | static int alg_test_hash(const struct alg_test_desc *desc, const char *driver, | ||
2140 | u32 type, u32 mask) | ||
2141 | { | ||
2142 | const struct hash_testvec *template = desc->suite.hash.vecs; | ||
2143 | unsigned int tcount = desc->suite.hash.count; | ||
2144 | unsigned int nr_unkeyed, nr_keyed; | ||
2145 | int err; | ||
2146 | |||
2147 | /* | ||
2148 | * For OPTIONAL_KEY algorithms, we have to do all the unkeyed tests | ||
2149 | * first, before setting a key on the tfm. To make this easier, we | ||
2150 | * require that the unkeyed test vectors (if any) are listed first. | ||
2151 | */ | ||
2152 | |||
2153 | for (nr_unkeyed = 0; nr_unkeyed < tcount; nr_unkeyed++) { | ||
2154 | if (template[nr_unkeyed].ksize) | ||
2155 | break; | ||
2156 | } | ||
2157 | for (nr_keyed = 0; nr_unkeyed + nr_keyed < tcount; nr_keyed++) { | ||
2158 | if (!template[nr_unkeyed + nr_keyed].ksize) { | ||
2159 | pr_err("alg: hash: test vectors for %s out of order, " | ||
2160 | "unkeyed ones must come first\n", desc->alg); | ||
2161 | return -EINVAL; | ||
2162 | } | ||
2163 | } | ||
2164 | |||
2165 | err = 0; | ||
2166 | if (nr_unkeyed) { | ||
2167 | err = __alg_test_hash(template, nr_unkeyed, driver, type, mask); | ||
2168 | template += nr_unkeyed; | ||
2169 | } | ||
2170 | |||
2171 | if (!err && nr_keyed) | ||
2172 | err = __alg_test_hash(template, nr_keyed, driver, type, mask); | ||
2173 | |||
2174 | return err; | ||
2175 | } | ||
2176 | |||
2177 | static int alg_test_crc32c(const struct alg_test_desc *desc, | 2064 | static int alg_test_crc32c(const struct alg_test_desc *desc, |
2178 | const char *driver, u32 type, u32 mask) | 2065 | const char *driver, u32 type, u32 mask) |
2179 | { | 2066 | { |
@@ -3956,6 +3843,10 @@ static void alg_check_testvec_configs(void) | |||
3956 | for (i = 0; i < ARRAY_SIZE(default_cipher_testvec_configs); i++) | 3843 | for (i = 0; i < ARRAY_SIZE(default_cipher_testvec_configs); i++) |
3957 | WARN_ON(!valid_testvec_config( | 3844 | WARN_ON(!valid_testvec_config( |
3958 | &default_cipher_testvec_configs[i])); | 3845 | &default_cipher_testvec_configs[i])); |
3846 | |||
3847 | for (i = 0; i < ARRAY_SIZE(default_hash_testvec_configs); i++) | ||
3848 | WARN_ON(!valid_testvec_config( | ||
3849 | &default_hash_testvec_configs[i])); | ||
3959 | } | 3850 | } |
3960 | 3851 | ||
3961 | static void testmgr_onetime_init(void) | 3852 | static void testmgr_onetime_init(void) |