1 /*
2  * CDDL HEADER START
3  *
4  * This file and its contents are supplied under the terms of the
5  * Common Development and Distribution License ("CDDL"), version 1.0.
6  * You may only use this file in accordance with the terms of version
7  * 1.0 of the CDDL.
8  *
9  * A full copy of the text of the CDDL should have accompanied this
10  * source.  A copy of the CDDL is also available via the Internet at
11  * http://www.illumos.org/license/CDDL.
12  *
13  * CDDL HEADER END
14  */
15 
16 /*
17  * Copyright (c) 2017, Datto, Inc. All rights reserved.
18  */
19 
20 #include <stdio.h>
21 #include <strings.h>
22 #include <sys/crypto/icp.h>
23 #include <sys/sha2.h>
24 #include <sys/hkdf.h>
25 
26 #define	NELEMS(x)  (sizeof (x) / sizeof ((x)[0]))
27 
28 /*
29  * Byte arrays are given as char pointers so that they
30  * can be specified as strings.
31  */
32 typedef struct hkdf_tv {
33 	/* test vector input values */
34 	char		*ikm;
35 	uint_t		ikm_len;
36 	char		*salt;
37 	uint_t		salt_len;
38 	char		*info;
39 	uint_t		info_len;
40 	uint_t		okm_len;
41 
42 	/* expected output */
43 	char		*okm;
44 } hkdf_tv_t;
45 
46 /*
47  * XXX Neither NIST nor IETF has published official test
48  * vectors for testing HKDF with SHA512. The following
49  * vectors should be updated if these are ever published.
50  * The current vectors were taken from:
51  * https://www.kullo.net/blog/hkdf-sha-512-test-vectors/
52  */
53 static hkdf_tv_t test_vectors[] = {
54 	{
55 		.ikm =	"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
56 			"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
57 			"\x0b\x0b\x0b\x0b\x0b\x0b",
58 		.ikm_len = 22,
59 		.salt =	"\x00\x01\x02\x03\x04\x05\x06\x07"
60 			"\x08\x09\x0a\x0b\x0c",
61 		.salt_len = 13,
62 		.info =	"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
63 			"\xf8\xf9",
64 		.info_len = 10,
65 		.okm_len = 42,
66 		.okm =	"\x83\x23\x90\x08\x6c\xda\x71\xfb"
67 			"\x47\x62\x5b\xb5\xce\xb1\x68\xe4"
68 			"\xc8\xe2\x6a\x1a\x16\xed\x34\xd9"
69 			"\xfc\x7f\xe9\x2c\x14\x81\x57\x93"
70 			"\x38\xda\x36\x2c\xb8\xd9\xf9\x25"
71 			"\xd7\xcb",
72 	},
73 	{
74 		.ikm = 	"\x00\x01\x02\x03\x04\x05\x06\x07"
75 			"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
76 			"\x10\x11\x12\x13\x14\x15\x16\x17"
77 			"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
78 			"\x20\x21\x22\x23\x24\x25\x26\x27"
79 			"\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
80 			"\x30\x31\x32\x33\x34\x35\x36\x37"
81 			"\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
82 			"\x40\x41\x42\x43\x44\x45\x46\x47"
83 			"\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
84 		.ikm_len = 80,
85 		.salt =	"\x60\x61\x62\x63\x64\x65\x66\x67"
86 			"\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
87 			"\x70\x71\x72\x73\x74\x75\x76\x77"
88 			"\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
89 			"\x80\x81\x82\x83\x84\x85\x86\x87"
90 			"\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
91 			"\x90\x91\x92\x93\x94\x95\x96\x97"
92 			"\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
93 			"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
94 			"\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
95 		.salt_len = 80,
96 		.info =	"\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
97 			"\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
98 			"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
99 			"\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
100 			"\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
101 			"\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
102 			"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
103 			"\xe8\xe9\xea\xeb\xec\xed\xee\xef"
104 			"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
105 			"\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
106 		.info_len = 80,
107 		.okm_len = 42,
108 		.okm =	"\xce\x6c\x97\x19\x28\x05\xb3\x46"
109 			"\xe6\x16\x1e\x82\x1e\xd1\x65\x67"
110 			"\x3b\x84\xf4\x00\xa2\xb5\x14\xb2"
111 			"\xfe\x23\xd8\x4c\xd1\x89\xdd\xf1"
112 			"\xb6\x95\xb4\x8c\xbd\x1c\x83\x88"
113 			"\x44\x11\x37\xb3\xce\x28\xf1\x6a"
114 			"\xa6\x4b\xa3\x3b\xa4\x66\xb2\x4d"
115 			"\xf6\xcf\xcb\x02\x1e\xcf\xf2\x35"
116 			"\xf6\xa2\x05\x6c\xe3\xaf\x1d\xe4"
117 			"\x4d\x57\x20\x97\xa8\x50\x5d\x9e"
118 			"\x7a\x93",
119 	},
120 	{
121 		.ikm =	"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
122 			"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
123 			"\x0b\x0b\x0b\x0b\x0b\x0b",
124 		.ikm_len = 22,
125 		.salt =	NULL,
126 		.salt_len = 0,
127 		.info =	NULL,
128 		.info_len = 0,
129 		.okm_len = 42,
130 		.okm =	"\xf5\xfa\x02\xb1\x82\x98\xa7\x2a"
131 			"\x8c\x23\x89\x8a\x87\x03\x47\x2c"
132 			"\x6e\xb1\x79\xdc\x20\x4c\x03\x42"
133 			"\x5c\x97\x0e\x3b\x16\x4b\xf9\x0f"
134 			"\xff\x22\xd0\x48\x36\xd0\xe2\x34"
135 			"\x3b\xac",
136 	},
137 	{
138 		.ikm =	"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
139 			"\x0b\x0b\x0b",
140 		.ikm_len = 11,
141 		.salt =	"\x00\x01\x02\x03\x04\x05\x06\x07"
142 			"\x08\x09\x0a\x0b\x0c",
143 		.salt_len = 13,
144 		.info =	"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
145 			"\xf8\xf9",
146 		.info_len = 10,
147 		.okm_len = 42,
148 		.okm =	"\x74\x13\xe8\x99\x7e\x02\x06\x10"
149 			"\xfb\xf6\x82\x3f\x2c\xe1\x4b\xff"
150 			"\x01\x87\x5d\xb1\xca\x55\xf6\x8c"
151 			"\xfc\xf3\x95\x4d\xc8\xaf\xf5\x35"
152 			"\x59\xbd\x5e\x30\x28\xb0\x80\xf7"
153 			"\xc0\x68",
154 	},
155 	{
156 		.ikm =	"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
157 			"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
158 			"\x0c\x0c\x0c\x0c\x0c\x0c",
159 		.ikm_len = 22,
160 		.salt =	NULL,
161 		.salt_len = 0,
162 		.info = NULL,
163 		.info_len = 0,
164 		.okm_len = 42,
165 		.okm =	"\x14\x07\xd4\x60\x13\xd9\x8b\xc6"
166 			"\xde\xce\xfc\xfe\xe5\x5f\x0f\x90"
167 			"\xb0\xc7\xf6\x3d\x68\xeb\x1a\x80"
168 			"\xea\xf0\x7e\x95\x3c\xfc\x0a\x3a"
169 			"\x52\x40\xa1\x55\xd6\xe4\xda\xa9"
170 			"\x65\xbb",
171 	},
172 };
173 
174 static void
175 hexdump(char *str, uint8_t *src, uint_t len)
176 {
177 	int i;
178 
179 	printf("\t%s\t", str);
180 	for (i = 0; i < len; i++) {
181 		printf("%02x", src[i] & 0xff);
182 	}
183 	printf("\n");
184 }
185 
186 static int
187 run_test(int i, hkdf_tv_t *tv)
188 {
189 	int ret;
190 	uint8_t okey[SHA512_DIGEST_LENGTH];
191 
192 	printf("TEST %d:\t", i);
193 
194 	ret = hkdf_sha512((uint8_t *)tv->ikm, tv->ikm_len, (uint8_t *)tv->salt,
195 	    tv->salt_len, (uint8_t *)tv->info, tv->info_len, okey, tv->okm_len);
196 	if (ret != 0) {
197 		printf("HKDF failed with error code %d\n", ret);
198 		return (ret);
199 	}
200 
201 	if (bcmp(okey, tv->okm, tv->okm_len) != 0) {
202 		printf("Output Mismatch\n");
203 		hexdump("Expected:", (uint8_t *)tv->okm, tv->okm_len);
204 		hexdump("Actual:  ", okey, tv->okm_len);
205 		return (1);
206 	}
207 
208 	printf("Passed\n");
209 
210 	return (0);
211 }
212 
213 int
214 main(int argc, char **argv)
215 {
216 	int ret, i;
217 
218 	icp_init();
219 
220 	for (i = 0; i < NELEMS(test_vectors); i++) {
221 		ret = run_test(i, &test_vectors[i]);
222 		if (ret != 0)
223 			break;
224 	}
225 
226 	icp_fini();
227 
228 	if (ret == 0) {
229 		printf("All tests passed successfully.\n");
230 		return (0);
231 	} else {
232 		printf("Test failed.\n");
233 		return (1);
234 	}
235 }
236