hkdf_hmac_sha256.c revision 1.1 1 1.1 riastrad /* $NetBSD: hkdf_hmac_sha256.c,v 1.1 2022/08/12 10:49:17 riastradh Exp $ */
2 1.1 riastrad
3 1.1 riastrad /*-
4 1.1 riastrad * Copyright (c) 2022 The NetBSD Foundation, Inc.
5 1.1 riastrad * All rights reserved.
6 1.1 riastrad *
7 1.1 riastrad * Redistribution and use in source and binary forms, with or without
8 1.1 riastrad * modification, are permitted provided that the following conditions
9 1.1 riastrad * are met:
10 1.1 riastrad * 1. Redistributions of source code must retain the above copyright
11 1.1 riastrad * notice, this list of conditions and the following disclaimer.
12 1.1 riastrad * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 riastrad * notice, this list of conditions and the following disclaimer in the
14 1.1 riastrad * documentation and/or other materials provided with the distribution.
15 1.1 riastrad *
16 1.1 riastrad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 1.1 riastrad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 1.1 riastrad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 1.1 riastrad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 1.1 riastrad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 1.1 riastrad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 1.1 riastrad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 1.1 riastrad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 1.1 riastrad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 1.1 riastrad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 1.1 riastrad * POSSIBILITY OF SUCH DAMAGE.
27 1.1 riastrad */
28 1.1 riastrad
29 1.1 riastrad #include <sys/cdefs.h>
30 1.1 riastrad __RCSID("$NetBSD: hkdf_hmac_sha256.c,v 1.1 2022/08/12 10:49:17 riastradh Exp $");
31 1.1 riastrad
32 1.1 riastrad #include <sys/sha2.h>
33 1.1 riastrad
34 1.1 riastrad #include <stdint.h>
35 1.1 riastrad #include <string.h>
36 1.1 riastrad
37 1.1 riastrad #include "hkdf_hmac_sha256.h"
38 1.1 riastrad
39 1.1 riastrad /* RFC 2104: HMAC */
40 1.1 riastrad
41 1.1 riastrad struct hmacsha256 {
42 1.1 riastrad SHA256_CTX sha256;
43 1.1 riastrad uint8_t key[SHA256_BLOCK_LENGTH];
44 1.1 riastrad };
45 1.1 riastrad
46 1.1 riastrad static void
47 1.1 riastrad hmacsha256_init(struct hmacsha256 *H, const void *key, size_t keylen)
48 1.1 riastrad {
49 1.1 riastrad uint8_t hkey[SHA256_DIGEST_LENGTH];
50 1.1 riastrad uint8_t ipad[SHA256_BLOCK_LENGTH];
51 1.1 riastrad unsigned i;
52 1.1 riastrad
53 1.1 riastrad if (keylen > SHA256_BLOCK_LENGTH) { /* XXX should not happen here */
54 1.1 riastrad SHA256_Init(&H->sha256);
55 1.1 riastrad SHA256_Update(&H->sha256, key, keylen);
56 1.1 riastrad SHA256_Final(hkey, &H->sha256);
57 1.1 riastrad key = hkey;
58 1.1 riastrad keylen = sizeof(hkey);
59 1.1 riastrad }
60 1.1 riastrad
61 1.1 riastrad memset(H->key, 0, sizeof(H->key));
62 1.1 riastrad memcpy(H->key, key, keylen);
63 1.1 riastrad
64 1.1 riastrad for (i = 0; i < SHA256_BLOCK_LENGTH; i++)
65 1.1 riastrad ipad[i] = 0x36 ^ H->key[i];
66 1.1 riastrad
67 1.1 riastrad SHA256_Init(&H->sha256);
68 1.1 riastrad SHA256_Update(&H->sha256, ipad, SHA256_BLOCK_LENGTH);
69 1.1 riastrad
70 1.1 riastrad explicit_memset(hkey, 0, sizeof(hkey));
71 1.1 riastrad explicit_memset(ipad, 0, sizeof(ipad));
72 1.1 riastrad }
73 1.1 riastrad
74 1.1 riastrad static void
75 1.1 riastrad hmacsha256_update(struct hmacsha256 *H, const void *buf, size_t buflen)
76 1.1 riastrad {
77 1.1 riastrad
78 1.1 riastrad SHA256_Update(&H->sha256, buf, buflen);
79 1.1 riastrad }
80 1.1 riastrad
81 1.1 riastrad static void
82 1.1 riastrad hmacsha256_final(uint8_t h[static SHA256_DIGEST_LENGTH],
83 1.1 riastrad struct hmacsha256 *H)
84 1.1 riastrad {
85 1.1 riastrad uint8_t opad[SHA256_BLOCK_LENGTH];
86 1.1 riastrad unsigned i;
87 1.1 riastrad
88 1.1 riastrad for (i = 0; i < SHA256_BLOCK_LENGTH; i++)
89 1.1 riastrad opad[i] = 0x5c ^ H->key[i];
90 1.1 riastrad
91 1.1 riastrad SHA256_Final(h, &H->sha256);
92 1.1 riastrad SHA256_Init(&H->sha256);
93 1.1 riastrad SHA256_Update(&H->sha256, opad, SHA256_BLOCK_LENGTH);
94 1.1 riastrad SHA256_Update(&H->sha256, h, SHA256_DIGEST_LENGTH);
95 1.1 riastrad SHA256_Final(h, &H->sha256);
96 1.1 riastrad
97 1.1 riastrad explicit_memset(opad, 0, sizeof(opad));
98 1.1 riastrad explicit_memset(H, 0, sizeof(*H));
99 1.1 riastrad }
100 1.1 riastrad
101 1.1 riastrad /* RFC 5869 HKDF, Sec. 2.3 HKDF-Expand */
102 1.1 riastrad
103 1.1 riastrad int
104 1.1 riastrad hkdf_hmac_sha256(void *okm, size_t L,
105 1.1 riastrad const void *prk, size_t prklen,
106 1.1 riastrad const void *info, size_t infolen)
107 1.1 riastrad {
108 1.1 riastrad struct hmacsha256 hmacsha256;
109 1.1 riastrad size_t n, tlen;
110 1.1 riastrad uint8_t T[SHA256_DIGEST_LENGTH], *p = okm;
111 1.1 riastrad uint8_t i;
112 1.1 riastrad
113 1.1 riastrad if (L > 255*SHA256_DIGEST_LENGTH)
114 1.1 riastrad return -1;
115 1.1 riastrad if (L == 0)
116 1.1 riastrad return 0;
117 1.1 riastrad
118 1.1 riastrad for (tlen = 0, i = 1; L > 0; i++, tlen = SHA256_DIGEST_LENGTH) {
119 1.1 riastrad hmacsha256_init(&hmacsha256, prk, prklen);
120 1.1 riastrad hmacsha256_update(&hmacsha256, T, tlen);
121 1.1 riastrad hmacsha256_update(&hmacsha256, info, infolen);
122 1.1 riastrad hmacsha256_update(&hmacsha256, &i, 1);
123 1.1 riastrad hmacsha256_final(T, &hmacsha256);
124 1.1 riastrad n = (L < SHA256_DIGEST_LENGTH ? L : SHA256_DIGEST_LENGTH);
125 1.1 riastrad memcpy(p, T, n);
126 1.1 riastrad p += n;
127 1.1 riastrad L -= n;
128 1.1 riastrad }
129 1.1 riastrad
130 1.1 riastrad explicit_memset(T, 0, sizeof(T));
131 1.1 riastrad return 0;
132 1.1 riastrad }
133 1.1 riastrad
134 1.1 riastrad #if 0
135 1.1 riastrad #include <stdarg.h>
136 1.1 riastrad #include <stdio.h>
137 1.1 riastrad
138 1.1 riastrad static void
139 1.1 riastrad hexdump(const void *buf, size_t len, const char *fmt, ...)
140 1.1 riastrad {
141 1.1 riastrad va_list va;
142 1.1 riastrad const uint8_t *p = buf;
143 1.1 riastrad size_t i;
144 1.1 riastrad
145 1.1 riastrad printf("### ");
146 1.1 riastrad va_start(va, fmt);
147 1.1 riastrad vprintf(fmt, va);
148 1.1 riastrad va_end(va);
149 1.1 riastrad printf(" (%zu bytes):\n", len);
150 1.1 riastrad for (i = 0; i < len; i++) {
151 1.1 riastrad if (i % 8 == 0)
152 1.1 riastrad printf(" ");
153 1.1 riastrad printf(" %02x", p[i]);
154 1.1 riastrad if (i % 16 == 15)
155 1.1 riastrad printf("\n");
156 1.1 riastrad }
157 1.1 riastrad if (i % 16)
158 1.1 riastrad printf("\n");
159 1.1 riastrad }
160 1.1 riastrad #endif
161 1.1 riastrad
162 1.1 riastrad int
163 1.1 riastrad hkdf_hmac_sha256_selftest(void)
164 1.1 riastrad {
165 1.1 riastrad const struct {
166 1.1 riastrad size_t L;
167 1.1 riastrad const uint8_t *okm;
168 1.1 riastrad size_t prklen;
169 1.1 riastrad const uint8_t *prk;
170 1.1 riastrad size_t infolen;
171 1.1 riastrad const uint8_t *info;
172 1.1 riastrad } C[] = {
173 1.1 riastrad [0] = { /* A.1 Test Case 1 with SHA-256 */
174 1.1 riastrad .L = 42,
175 1.1 riastrad .okm = (const uint8_t[]) {
176 1.1 riastrad 0x3c,0xb2,0x5f,0x25, 0xfa,0xac,0xd5,0x7a,
177 1.1 riastrad 0x90,0x43,0x4f,0x64, 0xd0,0x36,0x2f,0x2a,
178 1.1 riastrad 0x2d,0x2d,0x0a,0x90, 0xcf,0x1a,0x5a,0x4c,
179 1.1 riastrad 0x5d,0xb0,0x2d,0x56, 0xec,0xc4,0xc5,0xbf,
180 1.1 riastrad 0x34,0x00,0x72,0x08, 0xd5,0xb8,0x87,0x18,
181 1.1 riastrad 0x58,0x65,
182 1.1 riastrad },
183 1.1 riastrad .prklen = 32,
184 1.1 riastrad .prk = (const uint8_t[]) {
185 1.1 riastrad 0x07,0x77,0x09,0x36, 0x2c,0x2e,0x32,0xdf,
186 1.1 riastrad 0x0d,0xdc,0x3f,0x0d, 0xc4,0x7b,0xba,0x63,
187 1.1 riastrad 0x90,0xb6,0xc7,0x3b, 0xb5,0x0f,0x9c,0x31,
188 1.1 riastrad 0x22,0xec,0x84,0x4a, 0xd7,0xc2,0xb3,0xe5,
189 1.1 riastrad },
190 1.1 riastrad .infolen = 10,
191 1.1 riastrad .info = (const uint8_t[]) {
192 1.1 riastrad 0xf0,0xf1,0xf2,0xf3, 0xf4,0xf5,0xf6,0xf7,
193 1.1 riastrad 0xf8,0xf9,
194 1.1 riastrad },
195 1.1 riastrad },
196 1.1 riastrad [1] = { /* A.2 Test Case 2 with SHA-256, longer I/O */
197 1.1 riastrad .L = 82,
198 1.1 riastrad .okm = (const uint8_t[]) {
199 1.1 riastrad 0xb1,0x1e,0x39,0x8d, 0xc8,0x03,0x27,0xa1,
200 1.1 riastrad 0xc8,0xe7,0xf7,0x8c, 0x59,0x6a,0x49,0x34,
201 1.1 riastrad 0x4f,0x01,0x2e,0xda, 0x2d,0x4e,0xfa,0xd8,
202 1.1 riastrad 0xa0,0x50,0xcc,0x4c, 0x19,0xaf,0xa9,0x7c,
203 1.1 riastrad 0x59,0x04,0x5a,0x99, 0xca,0xc7,0x82,0x72,
204 1.1 riastrad 0x71,0xcb,0x41,0xc6, 0x5e,0x59,0x0e,0x09,
205 1.1 riastrad 0xda,0x32,0x75,0x60, 0x0c,0x2f,0x09,0xb8,
206 1.1 riastrad 0x36,0x77,0x93,0xa9, 0xac,0xa3,0xdb,0x71,
207 1.1 riastrad 0xcc,0x30,0xc5,0x81, 0x79,0xec,0x3e,0x87,
208 1.1 riastrad 0xc1,0x4c,0x01,0xd5, 0xc1,0xf3,0x43,0x4f,
209 1.1 riastrad 0x1d,0x87,
210 1.1 riastrad },
211 1.1 riastrad .prklen = 32,
212 1.1 riastrad .prk = (const uint8_t[]) {
213 1.1 riastrad 0x06,0xa6,0xb8,0x8c, 0x58,0x53,0x36,0x1a,
214 1.1 riastrad 0x06,0x10,0x4c,0x9c, 0xeb,0x35,0xb4,0x5c,
215 1.1 riastrad 0xef,0x76,0x00,0x14, 0x90,0x46,0x71,0x01,
216 1.1 riastrad 0x4a,0x19,0x3f,0x40, 0xc1,0x5f,0xc2,0x44,
217 1.1 riastrad },
218 1.1 riastrad .infolen = 80,
219 1.1 riastrad .info = (const uint8_t[]) {
220 1.1 riastrad 0xb0,0xb1,0xb2,0xb3, 0xb4,0xb5,0xb6,0xb7,
221 1.1 riastrad 0xb8,0xb9,0xba,0xbb, 0xbc,0xbd,0xbe,0xbf,
222 1.1 riastrad 0xc0,0xc1,0xc2,0xc3, 0xc4,0xc5,0xc6,0xc7,
223 1.1 riastrad 0xc8,0xc9,0xca,0xcb, 0xcc,0xcd,0xce,0xcf,
224 1.1 riastrad 0xd0,0xd1,0xd2,0xd3, 0xd4,0xd5,0xd6,0xd7,
225 1.1 riastrad 0xd8,0xd9,0xda,0xdb, 0xdc,0xdd,0xde,0xdf,
226 1.1 riastrad 0xe0,0xe1,0xe2,0xe3, 0xe4,0xe5,0xe6,0xe7,
227 1.1 riastrad 0xe8,0xe9,0xea,0xeb, 0xec,0xed,0xee,0xef,
228 1.1 riastrad 0xf0,0xf1,0xf2,0xf3, 0xf4,0xf5,0xf6,0xf7,
229 1.1 riastrad 0xf8,0xf9,0xfa,0xfb, 0xfc,0xfd,0xfe,0xff,
230 1.1 riastrad },
231 1.1 riastrad },
232 1.1 riastrad [2] = { /* A.3 Test Case 3 with SHA-256, empty info */
233 1.1 riastrad .L = 42,
234 1.1 riastrad .okm = (const uint8_t[]) {
235 1.1 riastrad 0x8d,0xa4,0xe7,0x75, 0xa5,0x63,0xc1,0x8f,
236 1.1 riastrad 0x71,0x5f,0x80,0x2a, 0x06,0x3c,0x5a,0x31,
237 1.1 riastrad 0xb8,0xa1,0x1f,0x5c, 0x5e,0xe1,0x87,0x9e,
238 1.1 riastrad 0xc3,0x45,0x4e,0x5f, 0x3c,0x73,0x8d,0x2d,
239 1.1 riastrad 0x9d,0x20,0x13,0x95, 0xfa,0xa4,0xb6,0x1a,
240 1.1 riastrad 0x96,0xc8,
241 1.1 riastrad },
242 1.1 riastrad .prklen = 32,
243 1.1 riastrad .prk = (const uint8_t[]) {
244 1.1 riastrad 0x19,0xef,0x24,0xa3, 0x2c,0x71,0x7b,0x16,
245 1.1 riastrad 0x7f,0x33,0xa9,0x1d, 0x6f,0x64,0x8b,0xdf,
246 1.1 riastrad 0x96,0x59,0x67,0x76, 0xaf,0xdb,0x63,0x77,
247 1.1 riastrad 0xac,0x43,0x4c,0x1c, 0x29,0x3c,0xcb,0x04,
248 1.1 riastrad },
249 1.1 riastrad .infolen = 0,
250 1.1 riastrad .info = NULL,
251 1.1 riastrad },
252 1.1 riastrad };
253 1.1 riastrad uint8_t okm[128];
254 1.1 riastrad unsigned i;
255 1.1 riastrad
256 1.1 riastrad for (i = 0; i < __arraycount(C); i++) {
257 1.1 riastrad if (hkdf_hmac_sha256(okm, C[i].L, C[i].prk, C[i].prklen,
258 1.1 riastrad C[i].info, C[i].infolen))
259 1.1 riastrad return -1;
260 1.1 riastrad if (memcmp(okm, C[i].okm, C[i].L))
261 1.1 riastrad return -1;
262 1.1 riastrad }
263 1.1 riastrad
264 1.1 riastrad return 0;
265 1.1 riastrad }
266 1.1 riastrad
267 1.1 riastrad #if 0
268 1.1 riastrad int
269 1.1 riastrad main(void)
270 1.1 riastrad {
271 1.1 riastrad return hkdf_hmac_sha256_selftest();
272 1.1 riastrad }
273 1.1 riastrad #endif
274