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 #ifdef	_KERNEL
32 #undef	_KERNEL
33 #endif
34 
35 #include <sys/edonr.h>
36 #include <stdlib.h>
37 #include <strings.h>
38 #include <stdio.h>
39 #include <sys/time.h>
40 #include <note.h>
41 
42 /*
43  * Test messages from:
44  * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
45  */
46 const char	*test_msg0 = "abc";
47 const char	*test_msg1 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmn"
48 	"lmnomnopnopq";
49 const char	*test_msg2 = "abcdefghbcdefghicdefghijdefghijkefghijklfghi"
50 	"jklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
51 
52 /*
53  * Test digests computed by hand. There's no formal standard or spec for edonr.
54  */
55 const uint8_t	edonr_224_test_digests[][28] = {
56 	{
57 		/* for test_msg0 */
58 		0x56, 0x63, 0xc4, 0x93, 0x95, 0x20, 0xfa, 0xf6,
59 		0x12, 0x31, 0x65, 0xa4, 0x66, 0xf2, 0x56, 0x01,
60 		0x95, 0x2e, 0xa9, 0xe4, 0x24, 0xdd, 0xc9, 0x6b,
61 		0xef, 0xd0, 0x40, 0x94
62 	},
63 	{
64 		/* for test_msg1 */
65 		0xd0, 0x13, 0xe4, 0x87, 0x4d, 0x06, 0x8d, 0xca,
66 		0x4e, 0x14, 0xb9, 0x37, 0x2f, 0xce, 0x12, 0x20,
67 		0x60, 0xf8, 0x5c, 0x0a, 0xfd, 0x7a, 0x7d, 0x97,
68 		0x88, 0x2b, 0x05, 0x75
69 	}
70 	/* no test vector for test_msg2 */
71 };
72 
73 const uint8_t	edonr_256_test_digests[][32] = {
74 	{
75 		/* for test_msg0 */
76 		0x54, 0xd7, 0x8b, 0x13, 0xc7, 0x4e, 0xda, 0x5a,
77 		0xed, 0xc2, 0x71, 0xcc, 0x88, 0x1f, 0xb2, 0x2f,
78 		0x83, 0x99, 0xaf, 0xd3, 0x04, 0x0b, 0x6a, 0x39,
79 		0x2d, 0x73, 0x94, 0x05, 0x50, 0x8d, 0xd8, 0x51
80 	},
81 	{
82 		/* for test_msg1 */
83 		0x49, 0x2d, 0x0b, 0x19, 0xab, 0x1e, 0xde, 0x3a,
84 		0xea, 0x9b, 0xf2, 0x39, 0x3a, 0xb1, 0x21, 0xde,
85 		0x21, 0xf6, 0x80, 0x1f, 0xad, 0xbe, 0x8b, 0x07,
86 		0xc7, 0xfb, 0xe6, 0x99, 0x0e, 0x4d, 0x73, 0x63
87 	}
88 	/* no test vectorfor test_msg2 */
89 };
90 
91 const uint8_t	edonr_384_test_digests[][48] = {
92 	{
93 		/* for test_msg0 */
94 		0x0e, 0x7c, 0xd7, 0x85, 0x78, 0x77, 0xe0, 0x89,
95 		0x5b, 0x1c, 0xdf, 0x49, 0xf4, 0x1d, 0x20, 0x9c,
96 		0x72, 0x7d, 0x2e, 0x57, 0x9b, 0x9b, 0x9a, 0xdc,
97 		0x60, 0x27, 0x97, 0x82, 0xb9, 0x90, 0x72, 0xec,
98 		0x7e, 0xce, 0xd3, 0x16, 0x5f, 0x47, 0x75, 0x48,
99 		0xfa, 0x60, 0x72, 0x7e, 0x01, 0xc7, 0x7c, 0xc6
100 	},
101 	{
102 		/* no test vector for test_msg1 */
103 		0
104 	},
105 	{
106 		/* for test_msg2 */
107 		0xe2, 0x34, 0xa1, 0x02, 0x83, 0x76, 0xae, 0xe6,
108 		0x82, 0xd9, 0x38, 0x32, 0x0e, 0x00, 0x78, 0xd2,
109 		0x34, 0xdb, 0xb9, 0xbd, 0xf0, 0x08, 0xa8, 0x0f,
110 		0x63, 0x1c, 0x3d, 0x4a, 0xfd, 0x0a, 0xe9, 0x59,
111 		0xdc, 0xd4, 0xce, 0xcd, 0x8d, 0x67, 0x6c, 0xea,
112 		0xbb, 0x1a, 0x32, 0xed, 0x5c, 0x6b, 0xf1, 0x7f
113 	}
114 };
115 
116 const uint8_t	edonr_512_test_digests[][64] = {
117 	{
118 		/* for test_msg0 */
119 		0x1b, 0x14, 0xdb, 0x15, 0x5f, 0x1d, 0x40, 0x65,
120 		0x94, 0xb8, 0xce, 0xf7, 0x0a, 0x43, 0x62, 0xec,
121 		0x6b, 0x5d, 0xe6, 0xa5, 0xda, 0xf5, 0x0e, 0xc9,
122 		0x99, 0xe9, 0x87, 0xc1, 0x9d, 0x30, 0x49, 0xe2,
123 		0xde, 0x59, 0x77, 0xbb, 0x05, 0xb1, 0xbb, 0x22,
124 		0x00, 0x50, 0xa1, 0xea, 0x5b, 0x46, 0xa9, 0xf1,
125 		0x74, 0x0a, 0xca, 0xfb, 0xf6, 0xb4, 0x50, 0x32,
126 		0xad, 0xc9, 0x0c, 0x62, 0x83, 0x72, 0xc2, 0x2b
127 	},
128 	{
129 		/* no test vector for test_msg1 */
130 		0
131 	},
132 	{
133 		/* for test_msg2 */
134 		0x53, 0x51, 0x07, 0x0d, 0xc5, 0x1c, 0x3b, 0x2b,
135 		0xac, 0xa5, 0xa6, 0x0d, 0x02, 0x52, 0xcc, 0xb4,
136 		0xe4, 0x92, 0x1a, 0x96, 0xfe, 0x5a, 0x69, 0xe7,
137 		0x6d, 0xad, 0x48, 0xfd, 0x21, 0xa0, 0x84, 0x5a,
138 		0xd5, 0x7f, 0x88, 0x0b, 0x3e, 0x4a, 0x90, 0x7b,
139 		0xc5, 0x03, 0x15, 0x18, 0x42, 0xbb, 0x94, 0x9e,
140 		0x1c, 0xba, 0x74, 0x39, 0xa6, 0x40, 0x9a, 0x34,
141 		0xb8, 0x43, 0x6c, 0xb4, 0x69, 0x21, 0x58, 0x3c
142 	}
143 };
144 
145 int
main(int argc,char * argv[])146 main(int argc, char *argv[])
147 {
148 	boolean_t	failed = B_FALSE;
149 	uint64_t	cpu_mhz = 0;
150 
151 	if (argc == 2)
152 		cpu_mhz = atoi(argv[1]);
153 
154 #define	EDONR_ALGO_TEST(_m, mode, testdigest)				\
155 	do {								\
156 		EdonRState	ctx;					\
157 		uint8_t		digest[mode / 8];			\
158 		EdonRInit(&ctx, mode);					\
159 		EdonRUpdate(&ctx, (const uint8_t *) _m, strlen(_m) * 8);\
160 		EdonRFinal(&ctx, digest);				\
161 		(void) printf("Edon-R-%-6sMessage: " #_m		\
162 		    "\tResult: ", #mode);				\
163 		if (bcmp(digest, testdigest, mode / 8) == 0) {		\
164 			(void) printf("OK\n");				\
165 		} else {						\
166 			(void) printf("FAILED!\n");			\
167 			failed = B_TRUE;				\
168 		}							\
169 		NOTE(CONSTCOND)						\
170 	} while (0)
171 
172 #define	EDONR_PERF_TEST(mode)						\
173 	do {								\
174 		EdonRState	ctx;					\
175 		uint8_t		digest[mode / 8];			\
176 		uint8_t		block[131072];				\
177 		uint64_t	delta;					\
178 		double		cpb = 0;				\
179 		int		i;					\
180 		struct timeval	start, end;				\
181 		bzero(block, sizeof (block));				\
182 		(void) gettimeofday(&start, NULL);			\
183 		EdonRInit(&ctx, mode);					\
184 		for (i = 0; i < 8192; i++)				\
185 			EdonRUpdate(&ctx, block, sizeof (block) * 8);	\
186 		EdonRFinal(&ctx, digest);				\
187 		(void) gettimeofday(&end, NULL);			\
188 		delta = (end.tv_sec * 1000000llu + end.tv_usec) -	\
189 		    (start.tv_sec * 1000000llu + start.tv_usec);	\
190 		if (cpu_mhz != 0) {					\
191 			cpb = (cpu_mhz * 1e6 * ((double)delta /		\
192 			    1000000)) / (8192 * 128 * 1024);		\
193 		}							\
194 		(void) printf("Edon-R-%-6s%llu us (%.02f CPB)\n", #mode,\
195 		    (u_longlong_t)delta, cpb);				\
196 		NOTE(CONSTCOND)						\
197 	} while (0)
198 
199 	(void) printf("Running algorithm correctness tests:\n");
200 	EDONR_ALGO_TEST(test_msg0, 224, edonr_224_test_digests[0]);
201 	EDONR_ALGO_TEST(test_msg1, 224, edonr_224_test_digests[1]);
202 	EDONR_ALGO_TEST(test_msg0, 256, edonr_256_test_digests[0]);
203 	EDONR_ALGO_TEST(test_msg1, 256, edonr_256_test_digests[1]);
204 	EDONR_ALGO_TEST(test_msg0, 384, edonr_384_test_digests[0]);
205 	EDONR_ALGO_TEST(test_msg2, 384, edonr_384_test_digests[2]);
206 	EDONR_ALGO_TEST(test_msg0, 512, edonr_512_test_digests[0]);
207 	EDONR_ALGO_TEST(test_msg2, 512, edonr_512_test_digests[2]);
208 	if (failed)
209 		return (1);
210 
211 	(void) printf("Running performance tests (hashing 1024 MiB of "
212 	    "data):\n");
213 	EDONR_PERF_TEST(256);
214 	EDONR_PERF_TEST(512);
215 
216 	return (0);
217 }
218