diff options
author | Nils Durner <durner@gnunet.org> | 2010-06-29 15:58:34 +0000 |
---|---|---|
committer | Nils Durner <durner@gnunet.org> | 2010-06-29 15:58:34 +0000 |
commit | 0bd8cc55c82bedce06f65f52ea446f82427d2c0d (patch) | |
tree | 0b077ae3d52819ad5be412b94f678b71a4e5dcb9 /src/util/crypto_hkdf.c | |
parent | 4b6526cb3b6b9f323b3f9f4020db2f493d286939 (diff) | |
download | gnunet-0bd8cc55c82bedce06f65f52ea446f82427d2c0d.tar.gz gnunet-0bd8cc55c82bedce06f65f52ea446f82427d2c0d.zip |
HKDF (does not work yet)
Diffstat (limited to 'src/util/crypto_hkdf.c')
-rw-r--r-- | src/util/crypto_hkdf.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/src/util/crypto_hkdf.c b/src/util/crypto_hkdf.c new file mode 100644 index 000000000..efde3b868 --- /dev/null +++ b/src/util/crypto_hkdf.c | |||
@@ -0,0 +1,192 @@ | |||
1 | /* | ||
2 | Copyright (c) 2010 Nils Durner | ||
3 | |||
4 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
5 | of this software and associated documentation files (the "Software"), to deal | ||
6 | in the Software without restriction, including without limitation the rights | ||
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
8 | copies of the Software, and to permit persons to whom the Software is | ||
9 | furnished to do so, subject to the following conditions: | ||
10 | |||
11 | The above copyright notice and this permission notice shall be included in | ||
12 | all copies or substantial portions of the Software. | ||
13 | |||
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
20 | THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | /** | ||
24 | * @file src/util/crypto_hkdf.c | ||
25 | * @brief Hash-based KDF as defined in draft-krawczyk-hkdf-01 | ||
26 | * @see http://tools.ietf.org/html/draft-krawczyk-hkdf-01 | ||
27 | * @author Nils Durner | ||
28 | */ | ||
29 | |||
30 | #include "platform.h" | ||
31 | #include "gnunet_crypto_lib.h" | ||
32 | |||
33 | /** | ||
34 | * @brief Compute the HMAC | ||
35 | * @param mac gcrypt MAC handle | ||
36 | * @param key HMAC key | ||
37 | * @param key_len length of key | ||
38 | * @param buf message to be processed | ||
39 | * @param buf_len length of buf | ||
40 | * @return HMAC, freed by caller via gcry_md_close/_reset | ||
41 | */ | ||
42 | static void * | ||
43 | doHMAC (gcry_md_hd_t mac, const void *key, const size_t key_len, | ||
44 | const void *buf, const size_t buf_len) | ||
45 | { | ||
46 | gcry_md_setkey (mac, key, key_len); | ||
47 | gcry_md_write (mac, buf, buf_len); | ||
48 | |||
49 | return (void *) gcry_md_read (mac, 0); | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * @brief Generate pseudo-random key | ||
54 | * @param mac gcrypt HMAC handle | ||
55 | * @param xts salt | ||
56 | * @param xts_len length of the salt | ||
57 | * @param skm source key material | ||
58 | * @param skm_len length of skm | ||
59 | * @param prk result buffer (allocated by caller; at least gcry_md_dlen() bytes) | ||
60 | * @return GNUNET_YES on success | ||
61 | */ | ||
62 | static int | ||
63 | getPRK (gcry_md_hd_t mac, const void *xts, const unsigned long long xts_len, | ||
64 | const void *skm, const unsigned long long skm_len, void *prk) | ||
65 | { | ||
66 | void *ret; | ||
67 | |||
68 | ret = doHMAC (mac, xts, xts_len, skm, skm_len); | ||
69 | if (ret == NULL) | ||
70 | return GNUNET_SYSERR; | ||
71 | memcpy (prk, ret, gcry_md_get_algo_dlen (gcry_md_get_algo (mac))); | ||
72 | |||
73 | return GNUNET_YES; | ||
74 | } | ||
75 | |||
76 | static void dump(void *p, unsigned int l) | ||
77 | { | ||
78 | unsigned int i; | ||
79 | |||
80 | printf("\n"); | ||
81 | for (i = 0; i < l; i++) | ||
82 | { | ||
83 | printf("%2x", ((char *) p)[i]); | ||
84 | } | ||
85 | printf("\n"); | ||
86 | } | ||
87 | |||
88 | /** | ||
89 | * @brief Derive key | ||
90 | * @param xtr_algo hash algorithm for the extraction phase, GCRY_MD_... | ||
91 | * @param prf_algo hash algorithm for the expansion phase, GCRY_MD_... | ||
92 | * @param xts salt | ||
93 | * @param xts_len length of xts | ||
94 | * @param skm source key material | ||
95 | * @param skm_len length of skm | ||
96 | * @param ctx context info | ||
97 | * @param ctx_len length of ctx | ||
98 | * @param out_len desired length of the derived key | ||
99 | * @param result buffer for the derived key, allocated by caller | ||
100 | * @return GNUNET_YES on success | ||
101 | */ | ||
102 | int | ||
103 | GNUNET_CRYPTO_hkdf (int xtr_algo, int prf_algo, const void *xts, | ||
104 | const size_t xts_len, const void *skm, const size_t skm_len, | ||
105 | const void *ctx, const size_t ctx_len, const unsigned long long out_len, | ||
106 | void *result) | ||
107 | { | ||
108 | void *prk, *hc, *plain; | ||
109 | unsigned long long plain_len; | ||
110 | unsigned long i, t, d; | ||
111 | unsigned int k, xtr_len; | ||
112 | int ret; | ||
113 | gcry_md_hd_t xtr, prf; | ||
114 | |||
115 | prk = plain = NULL; | ||
116 | xtr_len = gcry_md_get_algo_dlen (xtr_algo); | ||
117 | k = gcry_md_get_algo_dlen (prf_algo); | ||
118 | gcry_md_open(&xtr, xtr_algo, GCRY_MD_FLAG_HMAC); | ||
119 | gcry_md_open(&prf, prf_algo, GCRY_MD_FLAG_HMAC); | ||
120 | |||
121 | if (out_len > (2 ^ 32 * k) || !xtr_algo || !prf_algo) | ||
122 | return GNUNET_SYSERR; | ||
123 | |||
124 | prk = GNUNET_malloc (xtr_len); | ||
125 | |||
126 | memset (result, 0, out_len); | ||
127 | gcry_md_reset (xtr); | ||
128 | if (getPRK (xtr, xts, xts_len, skm, skm_len, prk) | ||
129 | != GNUNET_YES) | ||
130 | goto hkdf_error; | ||
131 | dump(prk, xtr_len); | ||
132 | |||
133 | /* K(1) */ | ||
134 | plain_len = k + ctx_len + 4; | ||
135 | plain = GNUNET_malloc (plain_len); | ||
136 | memset (plain, 0, k); | ||
137 | memcpy (plain + k, ctx, ctx_len); | ||
138 | t = out_len / k; | ||
139 | if (t > 0) | ||
140 | { | ||
141 | memset (plain + k + ctx_len, 0, 4); | ||
142 | gcry_md_reset (prf); | ||
143 | hc = doHMAC (prf, prk, k, plain, plain_len); | ||
144 | if (hc == NULL) | ||
145 | goto hkdf_error; | ||
146 | memcpy (result, hc, k); | ||
147 | result += k; | ||
148 | } | ||
149 | |||
150 | /* K(i+1) */ | ||
151 | for (i = 1; i < t; i++) | ||
152 | { | ||
153 | memcpy (plain, result - k, k); | ||
154 | memcpy (plain + k + ctx_len, &i, 4); | ||
155 | gcry_md_reset (prf); | ||
156 | hc = doHMAC (prf, prk, k, plain, plain_len); | ||
157 | if (hc == NULL) | ||
158 | goto hkdf_error; | ||
159 | memcpy (result, hc, k); | ||
160 | result += k; | ||
161 | } | ||
162 | |||
163 | /* K(t):d */ | ||
164 | d = out_len % k; | ||
165 | if (d > 0) | ||
166 | { | ||
167 | if (t > 0) | ||
168 | memcpy (plain, result - k, k); | ||
169 | memcpy (plain + k + ctx_len, &i, 4); | ||
170 | gcry_md_reset (prf); | ||
171 | hc = doHMAC (prf, prk, k, plain, plain_len); | ||
172 | if (hc == NULL) | ||
173 | goto hkdf_error; | ||
174 | memcpy (result, hc, d); | ||
175 | } | ||
176 | |||
177 | ret = GNUNET_YES; | ||
178 | goto hkdf_ok; | ||
179 | |||
180 | hkdf_error: | ||
181 | ret = GNUNET_SYSERR; | ||
182 | hkdf_ok: | ||
183 | GNUNET_free (prk); | ||
184 | GNUNET_free_non_null (plain); | ||
185 | gcry_md_close (prf); | ||
186 | gcry_md_close (xtr); | ||
187 | |||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | |||
192 | /* end of crypto_hkdf.c */ | ||