aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/testmgr.c
diff options
context:
space:
mode:
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)