1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://opensource.org/licenses/CDDL-1.0.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2013 Saso Kiselkov. All rights reserved.
24  */
25 
26 /*
27  * This is just to keep the compiler happy about sys/time.h not declaring
28  * gettimeofday due to -D_KERNEL (we can do this since we're actually
29  * running in userspace, but we need -D_KERNEL for the remaining Edon-R code).
30  */
31 
32 #include <sys/edonr.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <sys/time.h>
37 #include <sys/stdtypes.h>
38 
39 /*
40  * Test messages from:
41  * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
42  */
43 static const char *test_msg0 = "abc";
44 static const char *test_msg1 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklm"
45 	"nlmnomnopnopq";
46 static const char *test_msg2 = "abcdefghbcdefghicdefghijdefghijkefghijklfgh"
47 	"ijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
48 
49 /*
50  * Test digests computed by hand. There's no formal standard or spec for edonr.
51  */
52 static const uint8_t	edonr_224_test_digests[][28] = {
53 	{
54 		/* for test_msg0 */
55 		0x56, 0x63, 0xc4, 0x93, 0x95, 0x20, 0xfa, 0xf6,
56 		0x12, 0x31, 0x65, 0xa4, 0x66, 0xf2, 0x56, 0x01,
57 		0x95, 0x2e, 0xa9, 0xe4, 0x24, 0xdd, 0xc9, 0x6b,
58 		0xef, 0xd0, 0x40, 0x94
59 	},
60 	{
61 		/* for test_msg1 */
62 		0xd0, 0x13, 0xe4, 0x87, 0x4d, 0x06, 0x8d, 0xca,
63 		0x4e, 0x14, 0xb9, 0x37, 0x2f, 0xce, 0x12, 0x20,
64 		0x60, 0xf8, 0x5c, 0x0a, 0xfd, 0x7a, 0x7d, 0x97,
65 		0x88, 0x2b, 0x05, 0x75
66 	}
67 	/* no test vector for test_msg2 */
68 };
69 
70 static const uint8_t	edonr_256_test_digests[][32] = {
71 	{
72 		/* for test_msg0 */
73 		0x54, 0xd7, 0x8b, 0x13, 0xc7, 0x4e, 0xda, 0x5a,
74 		0xed, 0xc2, 0x71, 0xcc, 0x88, 0x1f, 0xb2, 0x2f,
75 		0x83, 0x99, 0xaf, 0xd3, 0x04, 0x0b, 0x6a, 0x39,
76 		0x2d, 0x73, 0x94, 0x05, 0x50, 0x8d, 0xd8, 0x51
77 	},
78 	{
79 		/* for test_msg1 */
80 		0x49, 0x2d, 0x0b, 0x19, 0xab, 0x1e, 0xde, 0x3a,
81 		0xea, 0x9b, 0xf2, 0x39, 0x3a, 0xb1, 0x21, 0xde,
82 		0x21, 0xf6, 0x80, 0x1f, 0xad, 0xbe, 0x8b, 0x07,
83 		0xc7, 0xfb, 0xe6, 0x99, 0x0e, 0x4d, 0x73, 0x63
84 	}
85 	/* no test vectorfor test_msg2 */
86 };
87 
88 static const uint8_t	edonr_384_test_digests[][48] = {
89 	{
90 		/* for test_msg0 */
91 		0x0e, 0x7c, 0xd7, 0x85, 0x78, 0x77, 0xe0, 0x89,
92 		0x5b, 0x1c, 0xdf, 0x49, 0xf4, 0x1d, 0x20, 0x9c,
93 		0x72, 0x7d, 0x2e, 0x57, 0x9b, 0x9b, 0x9a, 0xdc,
94 		0x60, 0x27, 0x97, 0x82, 0xb9, 0x90, 0x72, 0xec,
95 		0x7e, 0xce, 0xd3, 0x16, 0x5f, 0x47, 0x75, 0x48,
96 		0xfa, 0x60, 0x72, 0x7e, 0x01, 0xc7, 0x7c, 0xc6
97 	},
98 	{
99 		/* no test vector for test_msg1 */
100 		0
101 	},
102 	{
103 		/* for test_msg2 */
104 		0xe2, 0x34, 0xa1, 0x02, 0x83, 0x76, 0xae, 0xe6,
105 		0x82, 0xd9, 0x38, 0x32, 0x0e, 0x00, 0x78, 0xd2,
106 		0x34, 0xdb, 0xb9, 0xbd, 0xf0, 0x08, 0xa8, 0x0f,
107 		0x63, 0x1c, 0x3d, 0x4a, 0xfd, 0x0a, 0xe9, 0x59,
108 		0xdc, 0xd4, 0xce, 0xcd, 0x8d, 0x67, 0x6c, 0xea,
109 		0xbb, 0x1a, 0x32, 0xed, 0x5c, 0x6b, 0xf1, 0x7f
110 	}
111 };
112 
113 static const uint8_t	edonr_512_test_digests[][64] = {
114 	{
115 		/* for test_msg0 */
116 		0x1b, 0x14, 0xdb, 0x15, 0x5f, 0x1d, 0x40, 0x65,
117 		0x94, 0xb8, 0xce, 0xf7, 0x0a, 0x43, 0x62, 0xec,
118 		0x6b, 0x5d, 0xe6, 0xa5, 0xda, 0xf5, 0x0e, 0xc9,
119 		0x99, 0xe9, 0x87, 0xc1, 0x9d, 0x30, 0x49, 0xe2,
120 		0xde, 0x59, 0x77, 0xbb, 0x05, 0xb1, 0xbb, 0x22,
121 		0x00, 0x50, 0xa1, 0xea, 0x5b, 0x46, 0xa9, 0xf1,
122 		0x74, 0x0a, 0xca, 0xfb, 0xf6, 0xb4, 0x50, 0x32,
123 		0xad, 0xc9, 0x0c, 0x62, 0x83, 0x72, 0xc2, 0x2b
124 	},
125 	{
126 		/* no test vector for test_msg1 */
127 		0
128 	},
129 	{
130 		/* for test_msg2 */
131 		0x53, 0x51, 0x07, 0x0d, 0xc5, 0x1c, 0x3b, 0x2b,
132 		0xac, 0xa5, 0xa6, 0x0d, 0x02, 0x52, 0xcc, 0xb4,
133 		0xe4, 0x92, 0x1a, 0x96, 0xfe, 0x5a, 0x69, 0xe7,
134 		0x6d, 0xad, 0x48, 0xfd, 0x21, 0xa0, 0x84, 0x5a,
135 		0xd5, 0x7f, 0x88, 0x0b, 0x3e, 0x4a, 0x90, 0x7b,
136 		0xc5, 0x03, 0x15, 0x18, 0x42, 0xbb, 0x94, 0x9e,
137 		0x1c, 0xba, 0x74, 0x39, 0xa6, 0x40, 0x9a, 0x34,
138 		0xb8, 0x43, 0x6c, 0xb4, 0x69, 0x21, 0x58, 0x3c
139 	}
140 };
141 
142 int
143 main(int argc, char *argv[])
144 {
145 	boolean_t	failed = B_FALSE;
146 	uint64_t	cpu_mhz = 0;
147 
148 	if (argc == 2)
149 		cpu_mhz = atoi(argv[1]);
150 
151 #define	EDONR_ALGO_TEST(_m, mode, testdigest)				\
152 	do {								\
153 		EdonRState	ctx;					\
154 		uint8_t		digest[mode / 8];			\
155 		EdonRInit(&ctx, mode);					\
156 		EdonRUpdate(&ctx, (const uint8_t *) _m, strlen(_m) * 8);\
157 		EdonRFinal(&ctx, digest);				\
158 		(void) printf("Edon-R-%-6sMessage: " #_m		\
159 		    "\tResult: ", #mode);				\
160 		if (memcmp(digest, testdigest, mode / 8) == 0) {	\
161 			(void) printf("OK\n");				\
162 		} else {						\
163 			(void) printf("FAILED!\n");			\
164 			failed = B_TRUE;				\
165 		}							\
166 	} while (0)
167 
168 #define	EDONR_PERF_TEST(mode)						\
169 	do {								\
170 		EdonRState	ctx;					\
171 		uint8_t		digest[mode / 8];			\
172 		uint8_t		block[131072];				\
173 		uint64_t	delta;					\
174 		double		cpb = 0;				\
175 		int		i;					\
176 		struct timeval	start, end;				\
177 		memset(block, 0, sizeof (block));			\
178 		(void) gettimeofday(&start, NULL);			\
179 		EdonRInit(&ctx, mode);					\
180 		for (i = 0; i < 8192; i++)				\
181 			EdonRUpdate(&ctx, block, sizeof (block) * 8);	\
182 		EdonRFinal(&ctx, digest);				\
183 		(void) gettimeofday(&end, NULL);			\
184 		delta = (end.tv_sec * 1000000llu + end.tv_usec) -	\
185 		    (start.tv_sec * 1000000llu + start.tv_usec);	\
186 		if (cpu_mhz != 0) {					\
187 			cpb = (cpu_mhz * 1e6 * ((double)delta /		\
188 			    1000000)) / (8192 * 128 * 1024);		\
189 		}							\
190 		(void) printf("Edon-R-%-6s%llu us (%.02f CPB)\n", #mode,\
191 		    (u_longlong_t)delta, cpb);				\
192 	} while (0)
193 
194 	(void) printf("Running algorithm correctness tests:\n");
195 	EDONR_ALGO_TEST(test_msg0, 224, edonr_224_test_digests[0]);
196 	EDONR_ALGO_TEST(test_msg1, 224, edonr_224_test_digests[1]);
197 	EDONR_ALGO_TEST(test_msg0, 256, edonr_256_test_digests[0]);
198 	EDONR_ALGO_TEST(test_msg1, 256, edonr_256_test_digests[1]);
199 	EDONR_ALGO_TEST(test_msg0, 384, edonr_384_test_digests[0]);
200 	EDONR_ALGO_TEST(test_msg2, 384, edonr_384_test_digests[2]);
201 	EDONR_ALGO_TEST(test_msg0, 512, edonr_512_test_digests[0]);
202 	EDONR_ALGO_TEST(test_msg2, 512, edonr_512_test_digests[2]);
203 	if (failed)
204 		return (1);
205 
206 	(void) printf("Running performance tests (hashing 1024 MiB of "
207 	    "data):\n");
208 	EDONR_PERF_TEST(256);
209 	EDONR_PERF_TEST(512);
210 
211 	return (0);
212 }
213