836e0b7f088dbdc0cb56e50dd992acda23d6b994
[strongswan.git] / src / charon-tkm / src / tkm / tkm_diffie_hellman.c
1 /*
2 * Copyrigth (C) 2012 Reto Buerki
3 * Copyright (C) 2012 Adrian-Ken Rueegsegger
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <tkm/client.h>
18 #include <tkm/constants.h>
19
20 #include "tkm.h"
21 #include "tkm_utils.h"
22 #include "tkm_diffie_hellman.h"
23
24 #include <daemon.h>
25 #include <collections/hashtable.h>
26
27 typedef struct private_tkm_diffie_hellman_t private_tkm_diffie_hellman_t;
28
29 static hashtable_t *group_map = NULL;
30
31 /**
32 * Private data of a tkm_diffie_hellman_t object.
33 */
34 struct private_tkm_diffie_hellman_t {
35
36 /**
37 * Public tkm_diffie_hellman_t interface.
38 */
39 tkm_diffie_hellman_t public;
40
41 /**
42 * Diffie Hellman group number.
43 */
44 diffie_hellman_group_t group;
45
46 /**
47 * Diffie Hellman public value.
48 */
49 dh_pubvalue_type pubvalue;
50
51 /**
52 * Context id.
53 */
54 dh_id_type context_id;
55
56 };
57
58 METHOD(diffie_hellman_t, get_my_public_value, void,
59 private_tkm_diffie_hellman_t *this, chunk_t *value)
60 {
61 sequence_to_chunk(this->pubvalue.data, this->pubvalue.size, value);
62 }
63
64 METHOD(diffie_hellman_t, get_shared_secret, status_t,
65 private_tkm_diffie_hellman_t *this, chunk_t *secret)
66 {
67 *secret = chunk_empty;
68 return SUCCESS;
69 }
70
71
72 METHOD(diffie_hellman_t, set_other_public_value, void,
73 private_tkm_diffie_hellman_t *this, chunk_t value)
74 {
75 // TODO: unvoid this function
76
77 dh_pubvalue_type othervalue;
78 othervalue.size = value.len;
79 memcpy(&othervalue.data, value.ptr, value.len);
80
81 ike_dh_generate_key(this->context_id, othervalue);
82 }
83
84 METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
85 private_tkm_diffie_hellman_t *this)
86 {
87 return this->group;
88 }
89
90 METHOD(diffie_hellman_t, destroy, void,
91 private_tkm_diffie_hellman_t *this)
92 {
93 if (ike_dh_reset(this->context_id) != TKM_OK)
94 {
95 DBG1(DBG_LIB, "failed to reset DH context %d", this->context_id);
96 }
97
98 tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_DH, this->context_id);
99 free(this);
100 }
101
102 METHOD(tkm_diffie_hellman_t, get_id, dh_id_type,
103 private_tkm_diffie_hellman_t *this)
104 {
105 return this->context_id;
106 }
107
108 static u_int hash(void *key)
109 {
110 diffie_hellman_group_t k = *(diffie_hellman_group_t*)key;
111 return chunk_hash(chunk_from_thing(k));
112 }
113
114 static bool equals(void *key, void *other_key)
115 {
116 return *(diffie_hellman_group_t*)key == *(diffie_hellman_group_t*)other_key;
117 }
118
119 /*
120 * Described in header.
121 */
122 int register_dh_mapping()
123 {
124 int count, i;
125 char *iana_id_str, *tkm_id_str;
126 diffie_hellman_group_t *iana_id;
127 u_int64_t *tkm_id;
128 hashtable_t *map;
129 enumerator_t *enumerator;
130
131 map = hashtable_create((hashtable_hash_t)hash,
132 (hashtable_equals_t)equals, 16);
133
134 enumerator = lib->settings->create_key_value_enumerator(lib->settings,
135 "%s.dh_mapping",
136 lib->ns);
137
138 while (enumerator->enumerate(enumerator, &iana_id_str, &tkm_id_str))
139 {
140 iana_id = malloc_thing(diffie_hellman_group_t);
141 *iana_id = settings_value_as_int(iana_id_str, 0);
142 tkm_id = malloc_thing(u_int64_t);
143 *tkm_id = settings_value_as_int(tkm_id_str, 0);
144
145 map->put(map, iana_id, tkm_id);
146 }
147 enumerator->destroy(enumerator);
148
149 count = map->get_count(map);
150 plugin_feature_t f[count + 1];
151 f[0] = PLUGIN_REGISTER(DH, tkm_diffie_hellman_create);
152
153 i = 1;
154 enumerator = map->create_enumerator(map);
155 while (enumerator->enumerate(enumerator, &iana_id, &tkm_id))
156 {
157 f[i] = PLUGIN_PROVIDE(DH, *iana_id);
158 i++;
159 }
160 enumerator->destroy(enumerator);
161
162 lib->plugins->add_static_features(lib->plugins, "tkm-dh", f, countof(f),
163 TRUE, NULL, NULL);
164
165 if (count > 0)
166 {
167 group_map = map;
168 }
169 else
170 {
171 map->destroy(map);
172 }
173
174 return count;
175 }
176
177 /*
178 * Described in header.
179 */
180 void destroy_dh_mapping()
181 {
182 enumerator_t *enumerator;
183 char *key, *value;
184
185 if (group_map)
186 {
187 enumerator = group_map->create_enumerator(group_map);
188 while (enumerator->enumerate(enumerator, &key, &value))
189 {
190 free(key);
191 free(value);
192 }
193 enumerator->destroy(enumerator);
194 group_map->destroy(group_map);
195 }
196 }
197
198 /*
199 * Described in header.
200 */
201 tkm_diffie_hellman_t *tkm_diffie_hellman_create(diffie_hellman_group_t group)
202 {
203 private_tkm_diffie_hellman_t *this;
204
205 if (!group_map)
206 {
207 return NULL;
208 }
209
210 INIT(this,
211 .public = {
212 .dh = {
213 .get_shared_secret = _get_shared_secret,
214 .set_other_public_value = _set_other_public_value,
215 .get_my_public_value = _get_my_public_value,
216 .get_dh_group = _get_dh_group,
217 .destroy = _destroy,
218 },
219 .get_id = _get_id,
220 },
221 .group = group,
222 .context_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_DH),
223 );
224
225 if (!this->context_id)
226 {
227 free(this);
228 return NULL;
229 }
230
231 u_int64_t *dha_id = group_map->get(group_map, &group);
232 if (!dha_id)
233 {
234 free(this);
235 return NULL;
236 }
237
238 if (ike_dh_create(this->context_id, *dha_id, &this->pubvalue) != TKM_OK)
239 {
240 free(this);
241 return NULL;
242 }
243
244 return &this->public;
245 }