keymat: Extract enc,inc algorithms from proposal
[strongswan.git] / src / charon-tkm / src / tkm / tkm_keymat.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 <daemon.h>
18 #include <sa/ikev2/keymat_v2.h>
19 #include <tkm/constants.h>
20 #include <tkm/client.h>
21
22 #include "tkm.h"
23 #include "tkm_utils.h"
24 #include "tkm_diffie_hellman.h"
25 #include "tkm_keymat.h"
26
27 typedef struct private_tkm_keymat_t private_tkm_keymat_t;
28
29 /**
30 * Private data of a keymat_t object.
31 */
32 struct private_tkm_keymat_t {
33
34 /**
35 * Public tkm_keymat_t interface.
36 */
37 tkm_keymat_t public;
38
39 /**
40 * IKEv2 keymat proxy (will be removed).
41 */
42 keymat_v2_t *proxy;
43
44 /**
45 * IKE_SA Role, initiator or responder
46 */
47 bool initiator;
48
49 };
50
51 METHOD(keymat_t, get_version, ike_version_t,
52 private_tkm_keymat_t *this)
53 {
54 return IKEV2;
55 }
56
57 METHOD(keymat_t, create_dh, diffie_hellman_t*,
58 private_tkm_keymat_t *this, diffie_hellman_group_t group)
59 {
60 return lib->crypto->create_dh(lib->crypto, group);
61 }
62
63 METHOD(keymat_t, create_nonce_gen, nonce_gen_t*,
64 private_tkm_keymat_t *this)
65 {
66 return lib->crypto->create_nonce_gen(lib->crypto);
67 }
68
69 METHOD(tkm_keymat_t, derive_ike_keys, bool,
70 private_tkm_keymat_t *this, proposal_t *proposal, diffie_hellman_t *dh,
71 chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id,
72 pseudo_random_function_t rekey_function, chunk_t rekey_skd)
73 {
74 /* Check encryption and integrity algorithms */
75 u_int16_t enc_alg, int_alg, key_size;
76 if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_alg, &key_size))
77 {
78 DBG1(DBG_IKE, "no %N selected", transform_type_names,
79 ENCRYPTION_ALGORITHM);
80 return FALSE;
81 }
82 if (encryption_algorithm_is_aead(enc_alg))
83 {
84 DBG1(DBG_IKE, "AEAD algorithm %N not supported",
85 encryption_algorithm_names, enc_alg);
86 return FALSE;
87 }
88 if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_alg, NULL))
89 {
90 DBG1(DBG_IKE, "no %N selected", transform_type_names,
91 INTEGRITY_ALGORITHM);
92 return FALSE;
93 }
94 DBG2(DBG_IKE, "using %N for encryption, %N for integrity",
95 encryption_algorithm_names, enc_alg,
96 integrity_algorithm_names, int_alg);
97
98 /* Acquire nonce context id */
99 chunk_t * const nonce = this->initiator ? &nonce_i : &nonce_r;
100 const uint64_t nc_id = tkm->chunk_map->get_id(tkm->chunk_map, nonce);
101 if (!nc_id)
102 {
103 DBG1(DBG_IKE, "unable to acquire context id for nonce");
104 return FALSE;
105 }
106
107 /* Get DH context id */
108 tkm_diffie_hellman_t * const tkm_dh = (tkm_diffie_hellman_t *)dh;
109 const dh_id_type dh_id = tkm_dh->get_id(tkm_dh);
110
111 nonce_type nonce_rem;
112 u_int64_t spi_loc, spi_rem;
113
114 if (this->initiator)
115 {
116 chunk_to_sequence(&nonce_r, &nonce_rem);
117 spi_loc = id->get_initiator_spi(id);
118 spi_rem = id->get_responder_spi(id);
119 }
120 else
121 {
122 chunk_to_sequence(&nonce_i, &nonce_rem);
123 spi_loc = id->get_responder_spi(id);
124 spi_rem = id->get_initiator_spi(id);
125 }
126
127 key_type sk_ai, sk_ar, sk_ei, sk_er;
128 DBG1(DBG_IKE, "deriving IKE keys (nc: %llu, dh: %llu, spi_loc: %llx, "
129 "spi_rem: %llx)", nc_id, dh_id, spi_loc, spi_rem);
130 /* Fake some data for now */
131 if (ike_isa_create(1, 1, 1, dh_id, nc_id, nonce_rem, 1, spi_loc, spi_rem,
132 &sk_ai, &sk_ar, &sk_ei, &sk_er) != TKM_OK)
133 {
134 DBG1(DBG_IKE, "key derivation failed");
135 return FALSE;
136 }
137
138 if (this->proxy->derive_ike_keys(this->proxy, proposal, dh, nonce_i,
139 nonce_r, id, rekey_function, rekey_skd))
140 {
141 tkm->chunk_map->remove(tkm->chunk_map, nonce);
142 if (ike_nc_reset(nc_id) != TKM_OK)
143 {
144 DBG1(DBG_IKE, "failed to reset nonce context %llu", nc_id);
145 }
146 tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, nc_id);
147
148 return TRUE;
149 }
150 return FALSE;
151 }
152
153 METHOD(tkm_keymat_t, derive_child_keys, bool,
154 private_tkm_keymat_t *this, proposal_t *proposal, diffie_hellman_t *dh,
155 chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i,
156 chunk_t *encr_r, chunk_t *integ_r)
157 {
158 DBG1(DBG_CHD, "deriving child keys");
159 return this->proxy->derive_child_keys(this->proxy, proposal, dh, nonce_i,
160 nonce_r, encr_i, integ_i, encr_r, integ_r);
161 }
162
163 METHOD(keymat_t, get_aead, aead_t*,
164 private_tkm_keymat_t *this, bool in)
165 {
166 DBG1(DBG_IKE, "returning aead transform");
167 return this->proxy->keymat.get_aead(&this->proxy->keymat, in);
168 }
169
170 METHOD(tkm_keymat_t, get_auth_octets, bool,
171 private_tkm_keymat_t *this, bool verify, chunk_t ike_sa_init,
172 chunk_t nonce, identification_t *id, char reserved[3], chunk_t *octets)
173 {
174 DBG1(DBG_IKE, "returning auth octets");
175 return this->proxy->get_auth_octets(this->proxy, verify, ike_sa_init, nonce,
176 id, reserved, octets);
177 }
178
179 METHOD(tkm_keymat_t, get_skd, pseudo_random_function_t,
180 private_tkm_keymat_t *this, chunk_t *skd)
181 {
182 DBG1(DBG_IKE, "returning skd");
183 return this->proxy->get_skd(this->proxy, skd);
184 }
185
186 METHOD(tkm_keymat_t, get_psk_sig, bool,
187 private_tkm_keymat_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce,
188 chunk_t secret, identification_t *id, char reserved[3], chunk_t *sig)
189 {
190 DBG1(DBG_IKE, "returning PSK signature");
191 return this->proxy->get_psk_sig(this->proxy, verify, ike_sa_init, nonce,
192 secret, id, reserved, sig);
193 }
194
195 METHOD(keymat_t, destroy, void,
196 private_tkm_keymat_t *this)
197 {
198 free(this);
199 }
200
201 /**
202 * See header.
203 */
204 tkm_keymat_t *tkm_keymat_create(bool initiator)
205 {
206 private_tkm_keymat_t *this;
207
208 INIT(this,
209 .public = {
210 .keymat = {
211 .get_version = _get_version,
212 .create_dh = _create_dh,
213 .create_nonce_gen = _create_nonce_gen,
214 .get_aead = _get_aead,
215 .destroy = _destroy,
216 },
217 .derive_ike_keys = _derive_ike_keys,
218 .derive_child_keys = _derive_child_keys,
219 .get_skd = _get_skd,
220 .get_auth_octets = _get_auth_octets,
221 .get_psk_sig = _get_psk_sig,
222 },
223 .initiator = initiator,
224 .proxy = keymat_v2_create(initiator),
225 );
226
227 return &this->public;
228 }