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

# User Rev Content
1 root 1.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 root 1.3 #include <openssl/opensslv.h>
37 root 1.1 #include <openssl/rand.h>
38     #include <openssl/hmac.h>
39    
40     #include "util.h"
41     #include "hkdf.h"
42    
43 root 1.3 // 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 root 1.2 hkdf::hkdf (const void *salt, int len, const EVP_MD *xtr_hash)
51 root 1.1 {
52     HMAC_CTX_init (&ctx);
53    
54     if (!salt)
55     {
56     memset (prk, 0, sizeof prk);
57     salt = prk;
58 root 1.2 len = EVP_MD_size (xtr_hash);
59 root 1.1 }
60    
61 root 1.3 require101 (HMAC_Init_ex (&ctx, salt, len, xtr_hash, 0));
62 root 1.1 }
63    
64     hkdf::~hkdf ()
65     {
66     HMAC_CTX_cleanup (&ctx);
67     }
68    
69     void
70     hkdf::extract (const void *ikm, int len)
71     {
72 root 1.3 require101 (HMAC_Update (&ctx, (u8 *)ikm, len));
73 root 1.1 }
74    
75     void
76 root 1.2 hkdf::extract_done (const EVP_MD *prf_hash)
77 root 1.1 {
78 root 1.3 require101 (HMAC_Final (&ctx, prk, 0));
79     require101 (HMAC_Init_ex (&ctx, 0, 0, prf_hash, 0));
80 root 1.1 }
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 root 1.3 require101 (HMAC_Init_ex (&ctx, prk, md_size, 0, 0));
92 root 1.1
93     if (iter)
94 root 1.3 require101 (HMAC_Update (&ctx, tn, md_size));
95 root 1.1
96 root 1.3 require101 (HMAC_Update (&ctx, (u8 *)info, infolen));
97 root 1.1
98     ++iter;
99     require (iter);
100    
101 root 1.3 require101 (HMAC_Update (&ctx, &iter, 1));
102 root 1.1
103 root 1.3 require101 (HMAC_Final (&ctx, tn, 0));
104 root 1.1
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