xref: /openbsd/regress/lib/libcrypto/hmac/hmactest.c (revision e2b8045f)
1 /*	$OpenBSD: hmactest.c,v 1.8 2024/05/30 17:01:38 tb Exp $	*/
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 
59 #include <stdio.h>
60 #include <string.h>
61 #include <stdlib.h>
62 
63 #include <openssl/hmac.h>
64 #ifndef OPENSSL_NO_MD5
65 #include <openssl/md5.h>
66 #endif
67 
68 #ifndef OPENSSL_NO_MD5
69 static struct test_st {
70 	unsigned char key[16];
71 	int key_len;
72 	unsigned char data[64];
73 	int data_len;
74 	unsigned char *digest;
75 } test[8] = {
76 	{	"",
77 		0,
78 		"More text test vectors to stuff up EBCDIC machines :-)",
79 		54,
80 		(unsigned char *)"e9139d1e6ee064ef8cf514fc7dc83e86",
81 	},
82 	{	{0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,
83 		 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,},
84 		16,
85 		"Hi There",
86 		8,
87 		(unsigned char *)"9294727a3638bb1c13f48ef8158bfc9d",
88 	},
89 	{	"Jefe",
90 		4,
91 		"what do ya want for nothing?",
92 		28,
93 		(unsigned char *)"750c783e6ab0b503eaa86e310a5db738",
94 	},
95 	{	{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
96 		 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,},
97 		16,
98 		{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,
99 		 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,
100 		 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,
101 		 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,
102 		 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,
103 		 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,
104 		 0xdd,0xdd},
105 		50,
106 		(unsigned char *)"56be34521d144c88dbb8c733f0e8b3f6",
107 	},
108 	{	"",
109 		0,
110 		"My test data",
111 		12,
112 		(unsigned char *)"61afdecb95429ef494d61fdee15990cabf0826fc"
113 	},
114 	{	"",
115 		0,
116 		"My test data",
117 		12,
118 		(unsigned char *)"2274b195d90ce8e03406f4b526a47e0787a88a65479938f1a5baa3ce0f079776"
119 	},
120 	{	"123456",
121 		6,
122 		"My test data",
123 		12,
124 		(unsigned char *)"bab53058ae861a7f191abe2d0145cbb123776a6369ee3f9d79ce455667e411dd"
125 	},
126 	{	"12345",
127 		5,
128 		"My test data again",
129 		12,
130 		(unsigned char *)"7dbe8c764c068e3bcd6e6b0fbcd5e6fc197b15bb"
131 	}
132 };
133 #endif
134 
135 static char *pt(unsigned char *md, unsigned int len);
136 
137 int
main(int argc,char * argv[])138 main(int argc, char *argv[])
139 {
140 #ifndef OPENSSL_NO_MD5
141 	int i;
142 	char *p;
143 #endif
144 	int err = 0;
145 	HMAC_CTX *ctx = NULL, *ctx2 = NULL;
146 	unsigned char buf[EVP_MAX_MD_SIZE];
147 	unsigned int len;
148 
149 #ifdef OPENSSL_NO_MD5
150 	printf("test skipped: MD5 disabled\n");
151 #else
152 
153 	for (i = 0; i < 4; i++) {
154 		p = pt(HMAC(EVP_md5(),
155 			test[i].key, test[i].key_len,
156 			test[i].data, test[i].data_len, buf, NULL),
157 			MD5_DIGEST_LENGTH);
158 
159 		if (strcmp(p, (char *)test[i].digest) != 0) {
160 			printf("error calculating HMAC on %d entry'\n", i);
161 			printf("got %s instead of %s\n", p, test[i].digest);
162 			err++;
163 		} else
164 			printf("test %d ok\n", i);
165 	}
166 #endif /* OPENSSL_NO_MD5 */
167 
168 /* test4 */
169 	if ((ctx = HMAC_CTX_new()) == NULL) {
170 		printf("HMAC_CTX_init failed (test 4)\n");
171 		exit(1);
172 	}
173 	if (HMAC_Init_ex(ctx, NULL, 0, NULL, NULL)) {
174 		printf("Should fail to initialise HMAC with empty MD and key (test 4)\n");
175 		err++;
176 		goto test5;
177 	}
178 	if (HMAC_Update(ctx, test[4].data, test[4].data_len)) {
179 		printf("Should fail HMAC_Update with ctx not set up (test 4)\n");
180 		err++;
181 		goto test5;
182 	}
183 	if (HMAC_Init_ex(ctx, NULL, 0, EVP_sha1(), NULL)) {
184 		printf("Should fail to initialise HMAC with empty key (test 4)\n");
185 		err++;
186 		goto test5;
187 	}
188 	if (HMAC_Update(ctx, test[4].data, test[4].data_len)) {
189 		printf("Should fail HMAC_Update with ctx not set up (test 4)\n");
190 		err++;
191 		goto test5;
192 	}
193 	printf("test 4 ok\n");
194  test5:
195 	HMAC_CTX_reset(ctx);
196 	if (HMAC_Init_ex(ctx, test[4].key, test[4].key_len, NULL, NULL)) {
197 		printf("Should fail to initialise HMAC with empty MD (test 5)\n");
198 		err++;
199 		goto test6;
200 	}
201 	if (HMAC_Update(ctx, test[4].data, test[4].data_len)) {
202 		printf("Should fail HMAC_Update with ctx not set up (test 5)\n");
203 		err++;
204 		goto test6;
205 	}
206 	if (HMAC_Init_ex(ctx, test[4].key, -1, EVP_sha1(), NULL)) {
207 		printf("Should fail to initialise HMAC with invalid key len(test 5)\n");
208 		err++;
209 		goto test6;
210 	}
211 	if (!HMAC_Init_ex(ctx, test[4].key, test[4].key_len, EVP_sha1(), NULL)) {
212 		printf("Failed to initialise HMAC (test 5)\n");
213 		err++;
214 		goto test6;
215 	}
216 	if (!HMAC_Update(ctx, test[4].data, test[4].data_len)) {
217 		printf("Error updating HMAC with data (test 5)\n");
218 		err++;
219 		goto test6;
220 	}
221 	if (!HMAC_Final(ctx, buf, &len)) {
222 		printf("Error finalising data (test 5)\n");
223 		err++;
224 		goto test6;
225 	}
226 	p = pt(buf, len);
227 	if (strcmp(p, (char *)test[4].digest) != 0) {
228 		printf("Error calculating interim HMAC on test 5\n");
229 		printf("got %s instead of %s\n", p, test[4].digest);
230 		err++;
231 		goto test6;
232 	}
233 	if (HMAC_Init_ex(ctx, NULL, 0, EVP_sha256(), NULL)) {
234 		printf("Should disallow changing MD without a new key (test 5)\n");
235 		err++;
236 		goto test6;
237 	}
238 	if (!HMAC_Init_ex(ctx, test[4].key, test[4].key_len, EVP_sha256(), NULL)) {
239 		printf("Failed to reinitialise HMAC (test 5)\n");
240 		err++;
241 		goto test6;
242 	}
243 	if (!HMAC_Update(ctx, test[5].data, test[5].data_len)) {
244 		printf("Error updating HMAC with data (sha256) (test 5)\n");
245 		err++;
246 		goto test6;
247 	}
248 	if (!HMAC_Final(ctx, buf, &len)) {
249 		printf("Error finalising data (sha256) (test 5)\n");
250 		err++;
251 		goto test6;
252 	}
253 	p = pt(buf, len);
254 	if (strcmp(p, (char *)test[5].digest) != 0) {
255 		printf("Error calculating 2nd interim HMAC on test 5\n");
256 		printf("got %s instead of %s\n", p, test[5].digest);
257 		err++;
258 		goto test6;
259 	}
260 	if (!HMAC_Init_ex(ctx, test[6].key, test[6].key_len, NULL, NULL)) {
261 		printf("Failed to reinitialise HMAC with key (test 5)\n");
262 		err++;
263 		goto test6;
264 	}
265 	if (!HMAC_Update(ctx, test[6].data, test[6].data_len)) {
266 		printf("Error updating HMAC with data (new key) (test 5)\n");
267 		err++;
268 		goto test6;
269 	}
270 	if (!HMAC_Final(ctx, buf, &len)) {
271 		printf("Error finalising data (new key) (test 5)\n");
272 		err++;
273 		goto test6;
274 	}
275 	p = pt(buf, len);
276 	if (strcmp(p, (char *)test[6].digest) != 0) {
277 		printf("error calculating HMAC on test 5\n");
278 		printf("got %s instead of %s\n", p, test[6].digest);
279 		err++;
280 	} else {
281 		printf("test 5 ok\n");
282 	}
283  test6:
284 	HMAC_CTX_reset(ctx);
285 	if (!HMAC_Init_ex(ctx, test[7].key, test[7].key_len, EVP_sha1(), NULL)) {
286 		printf("Failed to initialise HMAC (test 6)\n");
287 		err++;
288 		goto end;
289 	}
290 	if (!HMAC_Update(ctx, test[7].data, test[7].data_len)) {
291 		printf("Error updating HMAC with data (test 6)\n");
292 		err++;
293 		goto end;
294 	}
295 	if ((ctx2 = HMAC_CTX_new()) == NULL) {
296 		printf("HMAC_CTX_new failed (test 6)\n");
297 		exit(1);
298 	}
299 	if (!HMAC_CTX_copy(ctx2, ctx)) {
300 		printf("Failed to copy HMAC_CTX (test 6)\n");
301 		err++;
302 		goto end;
303 	}
304 	if (!HMAC_Final(ctx2, buf, &len)) {
305 		printf("Error finalising data (test 6)\n");
306 		err++;
307 		goto end;
308 	}
309 	p = pt(buf, len);
310 	if (strcmp(p, (char *)test[7].digest) != 0) {
311 		printf("Error calculating HMAC on test 6\n");
312 		printf("got %s instead of %s\n", p, test[7].digest);
313 		err++;
314 	} else {
315 		printf("test 6 ok\n");
316 	}
317 end:
318 	HMAC_CTX_free(ctx);
319 	HMAC_CTX_free(ctx2);
320 	exit(err);
321 	return(0);
322 }
323 
324 #ifndef OPENSSL_NO_MD5
325 static char *
pt(unsigned char * md,unsigned int len)326 pt(unsigned char *md, unsigned int len)
327 {
328 	unsigned int i;
329 	static char buf[80];
330 
331 	for (i = 0; i < len; i++)
332 		snprintf(buf + i * 2, sizeof(buf) - i * 2, "%02x", md[i]);
333 	return(buf);
334 }
335 #endif
336