ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/hkdf.C
Revision: 1.5
Committed: Thu Jun 30 11:43:38 2016 UTC (7 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.4: +11 -37 lines
Log Message:
*** empty log message ***

File Contents

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