summaryrefslogtreecommitdiffstats
path: root/crypto/testmgr.c
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2019-02-01 02:51:48 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2019-02-08 02:30:09 -0500
commit4cc2dcf95f1c2849e489df91c07aee5f368a39f9 (patch)
treede4f14b41449004fc6300e4719bd363ad4b74cd7 /crypto/testmgr.c
parented96804ff1a5f94bdf4cda73ee81ba4545a076e5 (diff)
crypto: testmgr - convert hash testing to use testvec_configs
Convert alg_test_hash() to use the new test framework, adding a list of testvec_configs to test by default. When the extra self-tests are enabled, randomly generated testvec_configs are tested as well. This improves hash test coverage mainly because now all algorithms have a variety of data layouts tested, whereas before each algorithm was responsible for declaring its own chunked test cases which were often missing or provided poor test coverage. The new code also tests both the MAY_SLEEP and !MAY_SLEEP cases and buffers that cross pages. This already found bugs in the hash walk code and in the arm32 and arm64 implementations of crct10dif. I removed the hash chunked test vectors that were the same as non-chunked ones, but left the ones that were unique. Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/testmgr.c')
-rw-r--r--crypto/testmgr.c795
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
152static const unsigned int IDX[8] = {
153 IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 };
154
155static void hexdump(unsigned char *buf, unsigned int len) 140static 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
334static 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
349static unsigned int count_test_sg_divisions(const struct test_sg_division *divs) 407static 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
785static int ahash_guard_result(char *result, char c, int size) 843static 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
797static 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;
861out:
862 ahash_request_free(req);
863out_noreq:
864 kfree(state);
865out_nostate:
866 return ret;
867} 859}
868 860
869enum hash_test { 861static 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,
875static 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) 1010result_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++; 1026static 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 */ 1059static 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
1173out: 1110out:
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);
1175out_noreq: 1117 crypto_free_ahash(tfm);
1176 testmgr_free_buf(xbuf); 1118 return err;
1177out_nobuf:
1178 kfree(key);
1179 kfree(result);
1180 return ret;
1181} 1119}
1182 1120
1183static int test_hash(struct crypto_ahash *tfm, 1121static 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
1211static int test_aead_vec_cfg(const char *driver, int enc, 1159static 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
2116static 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
2139static 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
2177static int alg_test_crc32c(const struct alg_test_desc *desc, 2064static 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
3961static void testmgr_onetime_init(void) 3852static void testmgr_onetime_init(void)