ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/hkdf.C
Revision: 1.1
Committed: Tue Jul 16 16:44:36 2013 UTC (10 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Log Message:
3.x

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     #include <openssl/rand.h>
37     #include <openssl/hmac.h>
38    
39     #include "util.h"
40     #include "hkdf.h"
41    
42     hkdf::hkdf (const void *salt, int len, const EVP_MD *hash)
43     {
44     HMAC_CTX_init (&ctx);
45    
46     if (!salt)
47     {
48     memset (prk, 0, sizeof prk);
49     salt = prk;
50     len = EVP_MD_size (hash);
51     }
52    
53     require (HMAC_Init_ex (&ctx, salt, len, hash, 0));
54     }
55    
56     hkdf::~hkdf ()
57     {
58     HMAC_CTX_cleanup (&ctx);
59     }
60    
61     void
62     hkdf::extract (const void *ikm, int len)
63     {
64     require (HMAC_Update (&ctx, (u8 *)ikm, len));
65     }
66    
67     void
68     hkdf::extract_done ()
69     {
70     require (HMAC_Final (&ctx, prk, 0));
71     }
72    
73     void
74     hkdf::expand (void *okm, int len, const void *info, int infolen)
75     {
76     u8 tn[sizeof prk];
77     u8 iter = 0;
78     int md_size = HMAC_size (&ctx);
79    
80     while (len)
81     {
82     require (HMAC_Init_ex (&ctx, prk, md_size, 0, 0));
83    
84     if (iter)
85     require (HMAC_Update (&ctx, tn, md_size));
86    
87     require (HMAC_Update (&ctx, (u8 *)info, infolen));
88    
89    
90     ++iter;
91     require (iter);
92    
93     require (HMAC_Update (&ctx, &iter, 1));
94    
95     require (HMAC_Final (&ctx, tn, 0));
96    
97     int ol = len > md_size ? md_size : len;
98    
99     memcpy (okm, tn, ol);
100    
101     okm = (void *)(ol + (char *)okm);
102     len -= ol;
103     }
104     }
105    
106     // try to verify all test vectors from the RFC
107     // since I implemented the hkdf myself, and I am no crypto expert,
108     // we run verification on every startup.
109     void
110     hkdf::verify ()
111     {
112     struct unhex
113     {
114     u8 *p;
115     int l;
116    
117     u8 s[256];
118    
119     unhex (const char *hs)
120     {
121     l = 0;
122     p = 0;
123    
124     if (!hs)
125     return;
126    
127     p = s;
128    
129     while (*hs)
130     {
131     int d1 = *hs >= '0' && *hs <= '9' ? *hs - '0' : *hs - 'a' + 10; ++hs;
132     int d2 = *hs >= '0' && *hs <= '9' ? *hs - '0' : *hs - 'a' + 10; ++hs;
133    
134     *p++ = d1 * 16 + d2;
135     ++l;
136     }
137    
138     p = s;
139     }
140     };
141    
142     const struct hkdf_test
143     {
144     int hash;
145     const char *IKM, *salt, *info;
146     const char *PRK, *OKM;
147     } tests[] = {
148     { // 0
149     256,
150     "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
151     "000102030405060708090a0b0c",
152     "f0f1f2f3f4f5f6f7f8f9",
153     "077709362c2e32df0ddc3f0dc47bba63"
154     "90b6c73bb50f9c3122ec844ad7c2b3e5",
155     "3cb25f25faacd57a90434f64d0362f2a"
156     "2d2d0a90cf1a5a4c5db02d56ecc4c5bf"
157     "34007208d5b887185865"
158     }, { // 1
159     256,
160     "000102030405060708090a0b0c0d0e0f"
161     "101112131415161718191a1b1c1d1e1f"
162     "202122232425262728292a2b2c2d2e2f"
163     "303132333435363738393a3b3c3d3e3f"
164     "404142434445464748494a4b4c4d4e4f",
165     "606162636465666768696a6b6c6d6e6f"
166     "707172737475767778797a7b7c7d7e7f"
167     "808182838485868788898a8b8c8d8e8f"
168     "909192939495969798999a9b9c9d9e9f"
169     "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf",
170     "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
171     "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
172     "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
173     "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
174     "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
175     "06a6b88c5853361a06104c9ceb35b45c"
176     "ef760014904671014a193f40c15fc244",
177     "b11e398dc80327a1c8e7f78c596a4934"
178     "4f012eda2d4efad8a050cc4c19afa97c"
179     "59045a99cac7827271cb41c65e590e09"
180     "da3275600c2f09b8367793a9aca3db71"
181     "cc30c58179ec3e87c14c01d5c1f3434f"
182     "1d87"
183     }, { // 2
184     256,
185     "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
186     "",
187     "",
188     "19ef24a32c717b167f33a91d6f648bdf"
189     "96596776afdb6377ac434c1c293ccb04",
190     "8da4e775a563c18f715f802a063c5a31"
191     "b8a11f5c5ee1879ec3454e5f3c738d2d"
192     "9d201395faa4b61a96c8"
193     }, { // 3
194     1,
195     "0b0b0b0b0b0b0b0b0b0b0b",
196     "000102030405060708090a0b0c",
197     "f0f1f2f3f4f5f6f7f8f9",
198     "9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243",
199     "085a01ea1b10f36933068b56efa5ad81"
200     "a4f14b822f5b091568a9cdd4f155fda2"
201     "c22e422478d305f3f896"
202     }, { // 4
203     1,
204     "000102030405060708090a0b0c0d0e0f"
205     "101112131415161718191a1b1c1d1e1f"
206     "202122232425262728292a2b2c2d2e2f"
207     "303132333435363738393a3b3c3d3e3f"
208     "404142434445464748494a4b4c4d4e4f",
209     "606162636465666768696a6b6c6d6e6f"
210     "707172737475767778797a7b7c7d7e7f"
211     "808182838485868788898a8b8c8d8e8f"
212     "909192939495969798999a9b9c9d9e9f"
213     "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf",
214     "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
215     "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
216     "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
217     "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
218     "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
219     "8adae09a2a307059478d309b26c4115a224cfaf6",
220     "0bd770a74d1160f7c9f12cd5912a06eb"
221     "ff6adcae899d92191fe4305673ba2ffe"
222     "8fa3f1a4e5ad79f3f334b3b202b2173c"
223     "486ea37ce3d397ed034c7f9dfeb15c5e"
224     "927336d0441f4c4300e2cff0d0900b52"
225     "d3b4"
226     }, { // 5
227     1,
228     "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
229     "",
230     "",
231     "da8c8a73c7fa77288ec6f5e7c297786aa0d32d01",
232     "0ac1af7002b3d761d1e55298da9d0506"
233     "b9ae52057220a306e07b6b87e8df21d0"
234     "ea00033de03984d34918"
235     }, { // 6
236     1,
237     "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
238     0,
239     "",
240     "2adccada18779e7c2077ad2eb19d3f3e731385dd",
241     "2c91117204d745f3500d636a62f64f0a"
242     "b3bae548aa53d423b0d1f27ebba6f5e5"
243     "673a081d70cce7acfc48"
244     }
245     };
246    
247     for (int i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
248     {
249     const hkdf_test &test = tests[i];
250    
251     unhex salt (test.salt);
252     unhex ikm (test.IKM);
253     unhex info (test.info);
254     unhex prk_correct (test.PRK);
255     unhex okm_correct (test.OKM);
256    
257     char okm[256];
258    
259     hkdf h (salt.p, salt.l, test.hash == 1 ? EVP_sha1 () : EVP_sha256 ());
260     h.extract (ikm.p, ikm.l);
261     h.extract_done ();
262     h.expand (okm, okm_correct.l, info.p, info.l);
263    
264     require (!memcmp (h.prk, prk_correct.p, prk_correct.l));
265     require (!memcmp (okm , okm_correct.p, okm_correct.l));
266     }
267     }
268