diff options
Diffstat (limited to 'src/regress/lib/libcrypto/sha/sha_test.c')
-rw-r--r-- | src/regress/lib/libcrypto/sha/sha_test.c | 286 |
1 files changed, 134 insertions, 152 deletions
diff --git a/src/regress/lib/libcrypto/sha/sha_test.c b/src/regress/lib/libcrypto/sha/sha_test.c index 82a0c4cceb..904924c890 100644 --- a/src/regress/lib/libcrypto/sha/sha_test.c +++ b/src/regress/lib/libcrypto/sha/sha_test.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* $OpenBSD: sha_test.c,v 1.6 2023/07/19 15:11:42 joshua Exp $ */ | 1 | /* $OpenBSD: sha_test.c,v 1.7 2025/05/22 03:35:40 joshua Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2022, 2023 Joshua Sing <joshua@hypera.dev> | 3 | * Copyright (c) 2022, 2023, 2025 Joshua Sing <joshua@joshuasing.dev> |
4 | * | 4 | * |
5 | * Permission to use, copy, modify, and distribute this software for any | 5 | * Permission to use, copy, modify, and distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -21,6 +21,8 @@ | |||
21 | #include <stdint.h> | 21 | #include <stdint.h> |
22 | #include <string.h> | 22 | #include <string.h> |
23 | 23 | ||
24 | #include "test.h" | ||
25 | |||
24 | struct sha_test { | 26 | struct sha_test { |
25 | const int algorithm; | 27 | const int algorithm; |
26 | const uint8_t in[128]; | 28 | const uint8_t in[128]; |
@@ -677,260 +679,240 @@ typedef unsigned char *(*sha_hash_func)(const unsigned char *, size_t, | |||
677 | unsigned char *); | 679 | unsigned char *); |
678 | 680 | ||
679 | static int | 681 | static int |
680 | sha_hash_from_algorithm(int algorithm, const char **out_label, | 682 | sha_hash_from_algorithm(int algorithm, sha_hash_func *out_func, |
681 | sha_hash_func *out_func, const EVP_MD **out_md, size_t *out_len) | 683 | const EVP_MD **out_md) |
682 | { | 684 | { |
683 | const char *label; | ||
684 | sha_hash_func sha_func; | 685 | sha_hash_func sha_func; |
685 | const EVP_MD *md; | 686 | const EVP_MD *md; |
686 | size_t len; | ||
687 | 687 | ||
688 | switch (algorithm) { | 688 | switch (algorithm) { |
689 | case NID_sha1: | 689 | case NID_sha1: |
690 | label = SN_sha1; | ||
691 | sha_func = SHA1; | 690 | sha_func = SHA1; |
692 | md = EVP_sha1(); | 691 | md = EVP_sha1(); |
693 | len = SHA_DIGEST_LENGTH; | ||
694 | break; | 692 | break; |
695 | case NID_sha224: | 693 | case NID_sha224: |
696 | label = SN_sha224; | ||
697 | sha_func = SHA224; | 694 | sha_func = SHA224; |
698 | md = EVP_sha224(); | 695 | md = EVP_sha224(); |
699 | len = SHA224_DIGEST_LENGTH; | ||
700 | break; | 696 | break; |
701 | case NID_sha256: | 697 | case NID_sha256: |
702 | label = SN_sha256; | ||
703 | sha_func = SHA256; | 698 | sha_func = SHA256; |
704 | md = EVP_sha256(); | 699 | md = EVP_sha256(); |
705 | len = SHA256_DIGEST_LENGTH; | ||
706 | break; | 700 | break; |
707 | case NID_sha384: | 701 | case NID_sha384: |
708 | label = SN_sha384; | ||
709 | sha_func = SHA384; | 702 | sha_func = SHA384; |
710 | md = EVP_sha384(); | 703 | md = EVP_sha384(); |
711 | len = SHA384_DIGEST_LENGTH; | ||
712 | break; | 704 | break; |
713 | case NID_sha512: | 705 | case NID_sha512: |
714 | label = SN_sha512; | ||
715 | sha_func = SHA512; | 706 | sha_func = SHA512; |
716 | md = EVP_sha512(); | 707 | md = EVP_sha512(); |
717 | len = SHA512_DIGEST_LENGTH; | ||
718 | break; | 708 | break; |
719 | case NID_sha3_224: | 709 | case NID_sha3_224: |
720 | label = SN_sha3_224; | ||
721 | sha_func = NULL; | 710 | sha_func = NULL; |
722 | md = EVP_sha3_224(); | 711 | md = EVP_sha3_224(); |
723 | len = 224 / 8; | ||
724 | break; | 712 | break; |
725 | case NID_sha3_256: | 713 | case NID_sha3_256: |
726 | label = SN_sha3_256; | ||
727 | sha_func = NULL; | 714 | sha_func = NULL; |
728 | md = EVP_sha3_256(); | 715 | md = EVP_sha3_256(); |
729 | len = 256 / 8; | ||
730 | break; | 716 | break; |
731 | case NID_sha3_384: | 717 | case NID_sha3_384: |
732 | label = SN_sha3_384; | ||
733 | sha_func = NULL; | 718 | sha_func = NULL; |
734 | md = EVP_sha3_384(); | 719 | md = EVP_sha3_384(); |
735 | len = 384 / 8; | ||
736 | break; | 720 | break; |
737 | case NID_sha3_512: | 721 | case NID_sha3_512: |
738 | label = SN_sha3_512; | ||
739 | sha_func = NULL; | 722 | sha_func = NULL; |
740 | md = EVP_sha3_512(); | 723 | md = EVP_sha3_512(); |
741 | len = 512 / 8; | ||
742 | break; | 724 | break; |
743 | default: | 725 | default: |
744 | fprintf(stderr, "FAIL: unknown algorithm (%d)\n", | ||
745 | algorithm); | ||
746 | return 0; | 726 | return 0; |
747 | } | 727 | } |
748 | 728 | ||
749 | if (out_label != NULL) | ||
750 | *out_label = label; | ||
751 | if (out_func != NULL) | 729 | if (out_func != NULL) |
752 | *out_func = sha_func; | 730 | *out_func = sha_func; |
753 | if (out_md != NULL) | 731 | if (out_md != NULL) |
754 | *out_md = md; | 732 | *out_md = md; |
755 | if (out_len != NULL) | ||
756 | *out_len = len; | ||
757 | 733 | ||
758 | return 1; | 734 | return 1; |
759 | } | 735 | } |
760 | 736 | ||
761 | static int | 737 | static void |
762 | sha_test(void) | 738 | test_sha_tv(struct test *t, const void *arg) |
763 | { | 739 | { |
740 | const struct sha_test *st = arg; | ||
764 | sha_hash_func sha_func; | 741 | sha_hash_func sha_func; |
765 | const struct sha_test *st; | ||
766 | EVP_MD_CTX *hash = NULL; | 742 | EVP_MD_CTX *hash = NULL; |
767 | const EVP_MD *md; | 743 | const EVP_MD *md; |
768 | uint8_t out[EVP_MAX_MD_SIZE]; | 744 | uint8_t out[EVP_MAX_MD_SIZE]; |
769 | size_t in_len, out_len; | 745 | size_t in_len, out_len; |
770 | size_t i; | ||
771 | const char *label; | ||
772 | int failed = 1; | ||
773 | 746 | ||
774 | if ((hash = EVP_MD_CTX_new()) == NULL) { | 747 | if ((hash = EVP_MD_CTX_new()) == NULL) { |
775 | fprintf(stderr, "FAIL: EVP_MD_CTX_new() failed\n"); | 748 | test_errorf(t, "EVP_MD_CTX_new()"); |
776 | goto failed; | 749 | goto fail; |
777 | } | 750 | } |
778 | 751 | ||
779 | for (i = 0; i < N_SHA_TESTS; i++) { | 752 | if (!sha_hash_from_algorithm(st->algorithm, &sha_func, &md)) |
780 | st = &sha_tests[i]; | 753 | goto fail; |
781 | if (!sha_hash_from_algorithm(st->algorithm, &label, &sha_func, | ||
782 | &md, &out_len)) | ||
783 | goto failed; | ||
784 | |||
785 | /* Digest */ | ||
786 | if (sha_func != NULL) { | ||
787 | memset(out, 0, sizeof(out)); | ||
788 | sha_func(st->in, st->in_len, out); | ||
789 | if (memcmp(st->out, out, out_len) != 0) { | ||
790 | fprintf(stderr, "FAIL (%s:%zu): mismatch\n", | ||
791 | label, i); | ||
792 | goto failed; | ||
793 | } | ||
794 | } | ||
795 | 754 | ||
796 | /* EVP single-shot digest */ | 755 | out_len = EVP_MD_size(md); |
797 | memset(out, 0, sizeof(out)); | ||
798 | if (!EVP_Digest(st->in, st->in_len, out, NULL, md, NULL)) { | ||
799 | fprintf(stderr, "FAIL (%s:%zu): EVP_Digest failed\n", | ||
800 | label, i); | ||
801 | goto failed; | ||
802 | } | ||
803 | 756 | ||
757 | /* Digest */ | ||
758 | if (sha_func != NULL) { | ||
759 | memset(out, 0, sizeof(out)); | ||
760 | sha_func(st->in, st->in_len, out); | ||
804 | if (memcmp(st->out, out, out_len) != 0) { | 761 | if (memcmp(st->out, out, out_len) != 0) { |
805 | fprintf(stderr, | 762 | test_errorf(t, "SHA: digest output mismatch"); |
806 | "FAIL (%s:%zu): EVP single-shot mismatch\n", | 763 | test_hexdiff(t, out, out_len, st->out); |
807 | label, i); | ||
808 | goto failed; | ||
809 | } | 764 | } |
765 | } | ||
810 | 766 | ||
811 | /* EVP digest */ | 767 | /* EVP single-shot digest */ |
812 | memset(out, 0, sizeof(out)); | 768 | memset(out, 0, sizeof(out)); |
813 | if (!EVP_DigestInit_ex(hash, md, NULL)) { | 769 | if (!EVP_Digest(st->in, st->in_len, out, NULL, md, NULL)) { |
814 | fprintf(stderr, | 770 | test_errorf(t, "EVP_Digest()"); |
815 | "FAIL (%s:%zu): EVP_DigestInit_ex failed\n", | 771 | goto fail; |
816 | label, i); | 772 | } |
817 | goto failed; | ||
818 | } | ||
819 | 773 | ||
820 | in_len = st->in_len / 2; | 774 | if (memcmp(st->out, out, out_len) != 0) { |
821 | if (!EVP_DigestUpdate(hash, st->in, in_len)) { | 775 | test_errorf(t, "EVP single-shot: output diget mismatch"); |
822 | fprintf(stderr, | 776 | test_hexdiff(t, out, out_len, st->out); |
823 | "FAIL (%s:%zu): EVP_DigestUpdate first half " | 777 | } |
824 | "failed\n", label, i); | ||
825 | goto failed; | ||
826 | } | ||
827 | 778 | ||
828 | if (!EVP_DigestUpdate(hash, st->in + in_len, | 779 | /* EVP digest */ |
829 | st->in_len - in_len)) { | 780 | memset(out, 0, sizeof(out)); |
830 | fprintf(stderr, | 781 | if (!EVP_DigestInit_ex(hash, md, NULL)) { |
831 | "FAIL (%s:%zu): EVP_DigestUpdate second half " | 782 | test_errorf(t, "EVP_DigestInit_ex() "); |
832 | "failed\n", label, i); | 783 | goto fail; |
833 | goto failed; | 784 | } |
834 | } | ||
835 | 785 | ||
836 | if (!EVP_DigestFinal_ex(hash, out, NULL)) { | 786 | in_len = st->in_len / 2; |
837 | fprintf(stderr, | 787 | if (!EVP_DigestUpdate(hash, st->in, in_len)) { |
838 | "FAIL (%s:%zu): EVP_DigestFinal_ex failed\n", | 788 | test_errorf(t, "EVP_DigestUpdate() first half"); |
839 | label, i); | 789 | goto fail; |
840 | goto failed; | 790 | } |
841 | } | ||
842 | 791 | ||
843 | if (memcmp(st->out, out, out_len) != 0) { | 792 | if (!EVP_DigestUpdate(hash, st->in + in_len, |
844 | fprintf(stderr, "FAIL (%s:%zu): EVP mismatch\n", | 793 | st->in_len - in_len)) { |
845 | label, i); | 794 | test_errorf(t, "EVP_DigestUpdate() second half"); |
846 | goto failed; | 795 | goto fail; |
847 | } | ||
848 | } | 796 | } |
849 | 797 | ||
850 | failed = 0; | 798 | if (!EVP_DigestFinal_ex(hash, out, NULL)) { |
799 | test_errorf(t, "EVP_DigestFinal_ex()"); | ||
800 | goto fail; | ||
801 | } | ||
851 | 802 | ||
852 | failed: | 803 | if (memcmp(st->out, out, out_len) != 0) { |
804 | test_errorf(t, "EVP: digest output mismatch"); | ||
805 | test_hexdiff(t, out, out_len, st->out); | ||
806 | } | ||
807 | |||
808 | |||
809 | fail: | ||
853 | EVP_MD_CTX_free(hash); | 810 | EVP_MD_CTX_free(hash); |
854 | return failed; | ||
855 | } | 811 | } |
856 | 812 | ||
857 | static int | 813 | static void |
858 | sha_repetition_test(void) | 814 | test_sha(struct test *t, const void *arg) |
859 | { | 815 | { |
860 | const struct sha_repetition_test *st; | 816 | const struct sha_test *st; |
817 | size_t i; | ||
818 | char *name; | ||
819 | |||
820 | for (i = 0; i < N_SHA_TESTS; i++) { | ||
821 | st = &sha_tests[i]; | ||
822 | if (asprintf(&name, "%s: '%s'", OBJ_nid2sn(st->algorithm), st->in) == -1) { | ||
823 | test_errorf(t, "create test name failed"); | ||
824 | return; | ||
825 | } | ||
826 | |||
827 | test_run(t, name, test_sha_tv, st); | ||
828 | free(name); | ||
829 | } | ||
830 | } | ||
831 | |||
832 | static void | ||
833 | test_sha_repetition_tv(struct test *t, const void *arg) | ||
834 | { | ||
835 | const struct sha_repetition_test *st = arg; | ||
861 | EVP_MD_CTX *hash = NULL; | 836 | EVP_MD_CTX *hash = NULL; |
862 | const EVP_MD *md; | 837 | const EVP_MD *md; |
863 | uint8_t buf[1024]; | 838 | uint8_t buf[1024]; |
864 | uint8_t out[EVP_MAX_MD_SIZE]; | 839 | uint8_t out[EVP_MAX_MD_SIZE]; |
865 | size_t out_len, part_len; | 840 | size_t out_len, part_len; |
866 | size_t i, j; | 841 | size_t i; |
867 | const char *label; | ||
868 | int failed = 1; | ||
869 | 842 | ||
870 | if ((hash = EVP_MD_CTX_new()) == NULL) { | 843 | if ((hash = EVP_MD_CTX_new()) == NULL) { |
871 | fprintf(stderr, "FAIL: EVP_MD_CTX_new() failed\n"); | 844 | test_errorf(t, "EVP_MD_CTX_new()"); |
872 | goto failed; | 845 | goto fail; |
873 | } | 846 | } |
874 | 847 | ||
875 | for (i = 0; i < N_SHA_REPETITION_TESTS; i++) { | 848 | if (!sha_hash_from_algorithm(st->algorithm, NULL, &md)) |
876 | st = &sha_repetition_tests[i]; | 849 | goto fail; |
877 | if (!sha_hash_from_algorithm(st->algorithm, &label, NULL, &md, | ||
878 | &out_len)) | ||
879 | goto failed; | ||
880 | |||
881 | /* EVP digest */ | ||
882 | if (!EVP_DigestInit_ex(hash, md, NULL)) { | ||
883 | fprintf(stderr, | ||
884 | "FAIL (%s:%zu): EVP_DigestInit_ex failed\n", | ||
885 | label, i); | ||
886 | goto failed; | ||
887 | } | ||
888 | 850 | ||
889 | memset(buf, st->in, sizeof(buf)); | 851 | out_len = EVP_MD_size(md); |
890 | 852 | ||
891 | for (j = 0; j < st->in_repetitions;) { | 853 | /* EVP digest */ |
892 | part_len = arc4random_uniform(sizeof(buf)); | 854 | if (!EVP_DigestInit_ex(hash, md, NULL)) { |
893 | if (part_len > st->in_repetitions - j) | 855 | test_errorf(t, "EVP_DigestInit_ex()"); |
894 | part_len = st->in_repetitions - j; | 856 | goto fail; |
857 | } | ||
895 | 858 | ||
896 | if (!EVP_DigestUpdate(hash, buf, part_len)) { | 859 | memset(buf, st->in, sizeof(buf)); |
897 | fprintf(stderr, | ||
898 | "FAIL (%s:%zu): EVP_DigestUpdate failed\n", | ||
899 | label, i); | ||
900 | goto failed; | ||
901 | } | ||
902 | 860 | ||
903 | j += part_len; | 861 | for (i = 0; i < st->in_repetitions;) { |
904 | } | 862 | part_len = arc4random_uniform(sizeof(buf)); |
863 | if (part_len > st->in_repetitions - i) | ||
864 | part_len = st->in_repetitions - i; | ||
905 | 865 | ||
906 | if (!EVP_DigestFinal_ex(hash, out, NULL)) { | 866 | if (!EVP_DigestUpdate(hash, buf, part_len)) { |
907 | fprintf(stderr, | 867 | test_errorf(t, "EVP_DigestUpdate()"); |
908 | "FAIL (%s:%zu): EVP_DigestFinal_ex failed\n", | 868 | goto fail; |
909 | label, i); | ||
910 | goto failed; | ||
911 | } | 869 | } |
912 | 870 | ||
913 | if (memcmp(st->out, out, out_len) != 0) { | 871 | i += part_len; |
914 | fprintf(stderr, "FAIL (%s:%zu): EVP mismatch\n", | 872 | } |
915 | label, i); | 873 | |
916 | goto failed; | 874 | if (!EVP_DigestFinal_ex(hash, out, NULL)) { |
917 | } | 875 | test_errorf(t, "EVP_DigestFinal_ex()"); |
876 | goto fail; | ||
918 | } | 877 | } |
919 | 878 | ||
920 | failed = 0; | 879 | if (memcmp(st->out, out, out_len) != 0) { |
880 | test_errorf(t, "EVP: digest output mismatch"); | ||
881 | test_hexdiff(t, out, out_len, st->out); | ||
882 | goto fail; | ||
883 | } | ||
921 | 884 | ||
922 | failed: | 885 | fail: |
923 | EVP_MD_CTX_free(hash); | 886 | EVP_MD_CTX_free(hash); |
924 | return failed; | 887 | } |
888 | |||
889 | static void | ||
890 | test_sha_repetition(struct test *t, const void *arg) | ||
891 | { | ||
892 | const struct sha_repetition_test *st; | ||
893 | size_t i; | ||
894 | char *name; | ||
895 | |||
896 | for (i = 0; i < N_SHA_REPETITION_TESTS; i++) { | ||
897 | st = &sha_repetition_tests[i]; | ||
898 | if (asprintf(&name, "%s: '%hhu' x %zu", OBJ_nid2sn(st->algorithm), | ||
899 | st->in, st->in_repetitions) == -1) { | ||
900 | test_errorf(t, "create test name failed"); | ||
901 | return; | ||
902 | } | ||
903 | |||
904 | test_run(t, name, test_sha_repetition_tv, st); | ||
905 | free(name); | ||
906 | } | ||
925 | } | 907 | } |
926 | 908 | ||
927 | int | 909 | int |
928 | main(int argc, char **argv) | 910 | main(int argc, char **argv) |
929 | { | 911 | { |
930 | int failed = 0; | 912 | struct test *t = test_init(); |
931 | 913 | ||
932 | failed |= sha_test(); | 914 | test_run(t, "sha", test_sha, NULL); |
933 | failed |= sha_repetition_test(); | 915 | test_run(t, "sha repetition", test_sha_repetition, NULL); |
934 | 916 | ||
935 | return failed; | 917 | return test_result(t); |
936 | } | 918 | } |