ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/hkdf.C
Revision: 1.3
Committed: Fri Sep 20 11:57:03 2013 UTC (10 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.2: +17 -10 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 hkdf.C -- RFC 5869 HKDF implementation
3 Copyright (C) 2013 Marc Lehmann <gvpe@schmorp.de>
4
5 This file is part of GVPE.
6
7 GVPE is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15 Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, see <http://www.gnu.org/licenses/>.
19
20 Additional permission under GNU GPL version 3 section 7
21
22 If you modify this Program, or any covered work, by linking or
23 combining it with the OpenSSL project's OpenSSL library (or a modified
24 version of that library), containing parts covered by the terms of the
25 OpenSSL or SSLeay licenses, the licensors of this Program grant you
26 additional permission to convey the resulting work. Corresponding
27 Source for a non-source form of such a combination shall include the
28 source code for the parts of OpenSSL used as well as that of the
29 covered work.
30 */
31
32 #include "config.h"
33
34 #include <cstring>
35
36 #include <openssl/opensslv.h>
37 #include <openssl/rand.h>
38 #include <openssl/hmac.h>
39
40 #include "util.h"
41 #include "hkdf.h"
42
43 // openssl 0.9.8 compatibility
44 #if OPENSSL_VERSION_NUMBER < 0x10100000
45 #define require101(exp) exp
46 #else
47 #define require101(exp) equire (exp)
48 #endif
49
50 hkdf::hkdf (const void *salt, int len, const EVP_MD *xtr_hash)
51 {
52 HMAC_CTX_init (&ctx);
53
54 if (!salt)
55 {
56 memset (prk, 0, sizeof prk);
57 salt = prk;
58 len = EVP_MD_size (xtr_hash);
59 }
60
61 require101 (HMAC_Init_ex (&ctx, salt, len, xtr_hash, 0));
62 }
63
64 hkdf::~hkdf ()
65 {
66 HMAC_CTX_cleanup (&ctx);
67 }
68
69 void
70 hkdf::extract (const void *ikm, int len)
71 {
72 require101 (HMAC_Update (&ctx, (u8 *)ikm, len));
73 }
74
75 void
76 hkdf::extract_done (const EVP_MD *prf_hash)
77 {
78 require101 (HMAC_Final (&ctx, prk, 0));
79 require101 (HMAC_Init_ex (&ctx, 0, 0, prf_hash, 0));
80 }
81
82 void
83 hkdf::expand (void *okm, int len, const void *info, int infolen)
84 {
85 u8 tn[sizeof prk];
86 u8 iter = 0;
87 int md_size = HMAC_size (&ctx);
88
89 while (len)
90 {
91 require101 (HMAC_Init_ex (&ctx, prk, md_size, 0, 0));
92
93 if (iter)
94 require101 (HMAC_Update (&ctx, tn, md_size));
95
96 require101 (HMAC_Update (&ctx, (u8 *)info, infolen));
97
98 ++iter;
99 require (iter);
100
101 require101 (HMAC_Update (&ctx, &iter, 1));
102
103 require101 (HMAC_Final (&ctx, tn, 0));
104
105 int ol = len > md_size ? md_size : len;
106
107 memcpy (okm, tn, ol);
108
109 okm = (void *)(ol + (char *)okm);
110 len -= ol;
111 }
112 }
113
114 // try to verify all test vectors from the RFC
115 // since I implemented the hkdf myself, and I am no crypto expert,
116 // we run verification on every startup.
117 void
118 hkdf::verify ()
119 {
120 struct unhex
121 {
122 u8 *p;
123 int l;
124
125 u8 s[256];
126
127 unhex (const char *hs)
128 {
129 l = 0;
130 p = 0;
131
132 if (!hs)
133 return;
134
135 p = s;
136
137 while (*hs)
138 {
139 int d1 = *hs >= '0' && *hs <= '9' ? *hs - '0' : *hs - 'a' + 10; ++hs;
140 int d2 = *hs >= '0' && *hs <= '9' ? *hs - '0' : *hs - 'a' + 10; ++hs;
141
142 *p++ = d1 * 16 + d2;
143 ++l;
144 }
145
146 p = s;
147 }
148 };
149
150 const struct hkdf_test
151 {
152 int hash;
153 const char *IKM, *salt, *info;
154 const char *PRK, *OKM;
155 } tests[] = {
156 { // 0
157 256,
158 "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
159 "000102030405060708090a0b0c",
160 "f0f1f2f3f4f5f6f7f8f9",
161 "077709362c2e32df0ddc3f0dc47bba63"
162 "90b6c73bb50f9c3122ec844ad7c2b3e5",
163 "3cb25f25faacd57a90434f64d0362f2a"
164 "2d2d0a90cf1a5a4c5db02d56ecc4c5bf"
165 "34007208d5b887185865"
166 }, { // 1
167 256,
168 "000102030405060708090a0b0c0d0e0f"
169 "101112131415161718191a1b1c1d1e1f"
170 "202122232425262728292a2b2c2d2e2f"
171 "303132333435363738393a3b3c3d3e3f"
172 "404142434445464748494a4b4c4d4e4f",
173 "606162636465666768696a6b6c6d6e6f"
174 "707172737475767778797a7b7c7d7e7f"
175 "808182838485868788898a8b8c8d8e8f"
176 "909192939495969798999a9b9c9d9e9f"
177 "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf",
178 "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
179 "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
180 "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
181 "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
182 "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
183 "06a6b88c5853361a06104c9ceb35b45c"
184 "ef760014904671014a193f40c15fc244",
185 "b11e398dc80327a1c8e7f78c596a4934"
186 "4f012eda2d4efad8a050cc4c19afa97c"
187 "59045a99cac7827271cb41c65e590e09"
188 "da3275600c2f09b8367793a9aca3db71"
189 "cc30c58179ec3e87c14c01d5c1f3434f"
190 "1d87"
191 }, { // 2
192 256,
193 "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
194 "",
195 "",
196 "19ef24a32c717b167f33a91d6f648bdf"
197 "96596776afdb6377ac434c1c293ccb04",
198 "8da4e775a563c18f715f802a063c5a31"
199 "b8a11f5c5ee1879ec3454e5f3c738d2d"
200 "9d201395faa4b61a96c8"
201 }, { // 3
202 1,
203 "0b0b0b0b0b0b0b0b0b0b0b",
204 "000102030405060708090a0b0c",
205 "f0f1f2f3f4f5f6f7f8f9",
206 "9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243",
207 "085a01ea1b10f36933068b56efa5ad81"
208 "a4f14b822f5b091568a9cdd4f155fda2"
209 "c22e422478d305f3f896"
210 }, { // 4
211 1,
212 "000102030405060708090a0b0c0d0e0f"
213 "101112131415161718191a1b1c1d1e1f"
214 "202122232425262728292a2b2c2d2e2f"
215 "303132333435363738393a3b3c3d3e3f"
216 "404142434445464748494a4b4c4d4e4f",
217 "606162636465666768696a6b6c6d6e6f"
218 "707172737475767778797a7b7c7d7e7f"
219 "808182838485868788898a8b8c8d8e8f"
220 "909192939495969798999a9b9c9d9e9f"
221 "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf",
222 "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
223 "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
224 "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
225 "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
226 "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
227 "8adae09a2a307059478d309b26c4115a224cfaf6",
228 "0bd770a74d1160f7c9f12cd5912a06eb"
229 "ff6adcae899d92191fe4305673ba2ffe"
230 "8fa3f1a4e5ad79f3f334b3b202b2173c"
231 "486ea37ce3d397ed034c7f9dfeb15c5e"
232 "927336d0441f4c4300e2cff0d0900b52"
233 "d3b4"
234 }, { // 5
235 1,
236 "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
237 "",
238 "",
239 "da8c8a73c7fa77288ec6f5e7c297786aa0d32d01",
240 "0ac1af7002b3d761d1e55298da9d0506"
241 "b9ae52057220a306e07b6b87e8df21d0"
242 "ea00033de03984d34918"
243 }, { // 6
244 1,
245 "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
246 0,
247 "",
248 "2adccada18779e7c2077ad2eb19d3f3e731385dd",
249 "2c91117204d745f3500d636a62f64f0a"
250 "b3bae548aa53d423b0d1f27ebba6f5e5"
251 "673a081d70cce7acfc48"
252 }
253 };
254
255 for (int i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
256 {
257 const hkdf_test &test = tests[i];
258
259 unhex salt (test.salt);
260 unhex ikm (test.IKM);
261 unhex info (test.info);
262 unhex prk_correct (test.PRK);
263 unhex okm_correct (test.OKM);
264
265 char okm[256];
266
267 hkdf h (salt.p, salt.l, test.hash == 1 ? EVP_sha1 () : EVP_sha256 ());
268 h.extract (ikm.p, ikm.l);
269 h.extract_done ();
270 h.expand (okm, okm_correct.l, info.p, info.l);
271
272 require (!memcmp (h.prk, prk_correct.p, prk_correct.l));
273 require (!memcmp (okm , okm_correct.p, okm_correct.l));
274 }
275 }
276