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