2 * Copyrigth (C) 2012 Reto Buerki
3 * Copyright (C) 2012 Adrian-Ken Rueegsegger
4 * Hochschule fuer Technik Rapperswil
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>.
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
18 #include <encoding/payloads/auth_payload.h>
19 #include <utils/chunk.h>
20 #include <tkm/types.h>
21 #include <tkm/constants.h>
22 #include <tkm/client.h>
25 #include "tkm_listener.h"
26 #include "tkm_keymat.h"
27 #include "tkm_utils.h"
29 typedef struct private_tkm_listener_t private_tkm_listener_t
;
32 * Private data of a tkm_listener_t object.
34 struct private_tkm_listener_t
{
37 * Public tkm_listener_t interface.
39 tkm_listener_t
public;
44 * Return id of remote identity.
46 * TODO: Replace this with the lookup for the remote identitiy id.
48 * Currently the reqid of the first child SA in peer config of IKE SA is
49 * returned. Might choose wrong reqid if IKE SA has multiple child configs
50 * with different reqids.
52 * @param peer_cfg Remote peer config
53 * @return remote identity id if found, 0 otherwise
55 static ri_id_type
get_remote_identity_id(peer_cfg_t
*peer
)
57 ri_id_type remote_id
= 0;
59 enumerator_t
* children
= peer
->create_child_cfg_enumerator(peer
);
61 /* pick the reqid of the first child, no need to enumerate all children. */
62 children
->enumerate(children
, &child
);
63 remote_id
= child
->get_reqid(child
);
64 children
->destroy(children
);
70 * Build a TKM certificate chain context with given cc id.
72 * @param ike_sa IKE SA containing auth config to build certificate chain from
73 * @param cc_id Certificate chain ID
74 * @return TRUE if certificate chain was built successfully,
77 static bool build_cert_chain(const ike_sa_t
* const ike_sa
, cc_id_type cc_id
)
79 DBG1(DBG_IKE
, "building certificate chain context %llu for IKE SA %s",
80 cc_id
, ike_sa
->get_name((ike_sa_t
*)ike_sa
));
85 rounds
= ike_sa
->create_auth_cfg_enumerator((ike_sa_t
*)ike_sa
, FALSE
);
86 while (rounds
->enumerate(rounds
, &auth
))
88 cert
= auth
->get(auth
, AUTH_RULE_SUBJECT_CERT
);
91 /* set user certificate */
92 chunk_t enc_user_cert
;
93 if (!cert
->get_encoding(cert
, CERT_ASN1_DER
, &enc_user_cert
))
95 DBG1(DBG_IKE
, "unable to extract encoded user certificate");
96 rounds
->destroy(rounds
);
100 ri_id_type ri_id
= get_remote_identity_id(ike_sa
->get_peer_cfg((ike_sa_t
*)ike_sa
));
101 certificate_type user_cert
;
102 chunk_to_sequence(&enc_user_cert
, &user_cert
,
103 sizeof(certificate_type
));
104 chunk_free(&enc_user_cert
);
105 if (ike_cc_set_user_certificate(cc_id
, ri_id
, 1, user_cert
) != TKM_OK
)
107 DBG1(DBG_IKE
, "error setting user certificate of cert chain"
108 " (cc_id: %llu)", cc_id
);
109 rounds
->destroy(rounds
);
113 /* process intermediate CA certificates */
115 enumerator_t
*enumerator
= auth
->create_enumerator(auth
);
116 while (enumerator
->enumerate(enumerator
, &rule
, &cert
))
118 if (rule
== AUTH_RULE_IM_CERT
)
121 if (!cert
->get_encoding(cert
, CERT_ASN1_DER
, &enc_im_cert
))
123 DBG1(DBG_IKE
, "unable to extract encoded intermediate CA"
125 rounds
->destroy(rounds
);
126 enumerator
->destroy(enumerator
);
130 certificate_type im_cert
;
131 chunk_to_sequence(&enc_im_cert
, &im_cert
,
132 sizeof(certificate_type
));
133 chunk_free(&enc_im_cert
);
134 if (ike_cc_add_certificate(cc_id
, 1, im_cert
) != TKM_OK
)
136 DBG1(DBG_IKE
, "error adding intermediate certificate to"
137 " cert chain (cc_id: %llu)", cc_id
);
138 rounds
->destroy(rounds
);
139 enumerator
->destroy(enumerator
);
144 enumerator
->destroy(enumerator
);
146 /* finally add CA certificate */
147 cert
= auth
->get(auth
, AUTH_RULE_CA_CERT
);
151 if (!cert
->get_encoding(cert
, CERT_ASN1_DER
, &enc_ca_cert
))
153 DBG1(DBG_IKE
, "unable to extract encoded CA certificate");
154 rounds
->destroy(rounds
);
158 const ca_id_type ca_id
= 1;
159 certificate_type ca_cert
;
160 chunk_to_sequence(&enc_ca_cert
, &ca_cert
,
161 sizeof(certificate_type
));
162 chunk_free(&enc_ca_cert
);
163 if (ike_cc_add_certificate(cc_id
, 1, ca_cert
) != TKM_OK
)
165 DBG1(DBG_IKE
, "error adding CA certificate to cert chain "
166 "(cc_id: %llu)", cc_id
);
167 rounds
->destroy(rounds
);
171 if (ike_cc_check_ca(cc_id
, ca_id
) != TKM_OK
)
173 DBG1(DBG_IKE
, "certificate chain (cc_id: %llu) not based on"
174 " trusted CA (ca_id: %llu)", cc_id
, ca_id
);
175 rounds
->destroy(rounds
);
179 rounds
->destroy(rounds
);
184 DBG1(DBG_IKE
, "no CA certificate");
189 DBG1(DBG_IKE
, "no subject certificate for remote peer");
193 rounds
->destroy(rounds
);
197 METHOD(listener_t
, alert
, bool,
198 private_tkm_listener_t
*this, ike_sa_t
*ike_sa
,
199 alert_t alert
, va_list args
)
201 if (alert
== ALERT_KEEP_ON_CHILD_SA_FAILURE
)
203 tkm_keymat_t
* const keymat
= (tkm_keymat_t
*)ike_sa
->get_keymat(ike_sa
);
204 const isa_id_type isa_id
= keymat
->get_isa_id(keymat
);
205 DBG1(DBG_IKE
, "TKM alert listener called for ISA context %llu", isa_id
);
206 if (ike_isa_skip_create_first(isa_id
) != TKM_OK
)
208 DBG1(DBG_IKE
, "Skip of first child SA creation failed for ISA "
209 "context %llu", isa_id
);
216 METHOD(listener_t
, authorize
, bool,
217 private_tkm_listener_t
*this, ike_sa_t
*ike_sa
,
218 bool final
, bool *success
)
225 tkm_keymat_t
* const keymat
= (tkm_keymat_t
*)ike_sa
->get_keymat(ike_sa
);
226 const isa_id_type isa_id
= keymat
->get_isa_id(keymat
);
227 DBG1(DBG_IKE
, "TKM authorize listener called for ISA context %llu", isa_id
);
229 const cc_id_type cc_id
= tkm
->idmgr
->acquire_id(tkm
->idmgr
, TKM_CTX_CC
);
232 DBG1(DBG_IKE
, "unable to acquire CC context id");
236 const bool cc_success
= build_cert_chain(ike_sa
, cc_id
);
239 DBG1(DBG_IKE
, "unable to build certificate chain");
244 const chunk_t
* const auth
= keymat
->get_auth_payload(keymat
);
247 DBG1(DBG_IKE
, "no AUTHENTICATION data available");
251 const chunk_t
* const other_init_msg
= keymat
->get_peer_init_msg(keymat
);
252 if (!other_init_msg
->ptr
)
254 DBG1(DBG_IKE
, "no peer init message available");
258 signature_type signature
;
259 chunk_to_sequence(auth
, &signature
, sizeof(signature_type
));
260 init_message_type init_msg
;
261 chunk_to_sequence(other_init_msg
, &init_msg
, sizeof(init_message_type
));
263 if (ike_isa_auth(isa_id
, cc_id
, init_msg
, signature
) != TKM_OK
)
265 DBG1(DBG_IKE
, "TKM based authentication failed"
266 " for ISA context %llu", isa_id
);
271 DBG1(DBG_IKE
, "TKM based authentication successful"
272 " for ISA context %llu", isa_id
);
279 METHOD(listener_t
, message
, bool,
280 private_tkm_listener_t
*this, ike_sa_t
*ike_sa
,
281 message_t
*message
, bool incoming
, bool plain
)
283 if (!incoming
|| !plain
|| message
->get_exchange_type(message
) != IKE_AUTH
)
288 tkm_keymat_t
* const keymat
= (tkm_keymat_t
*)ike_sa
->get_keymat(ike_sa
);
289 const isa_id_type isa_id
= keymat
->get_isa_id(keymat
);
290 DBG1(DBG_IKE
, "saving AUTHENTICATION payload for authorize hook"
291 " (ISA context %llu)", isa_id
);
293 auth_payload_t
* const auth_payload
=
294 (auth_payload_t
*)message
->get_payload(message
, AUTHENTICATION
);
297 const chunk_t auth_data
= auth_payload
->get_data(auth_payload
);
298 keymat
->set_auth_payload(keymat
, &auth_data
);
302 DBG1(DBG_IKE
, "unable to extract AUTHENTICATION payload, authorize will"
309 METHOD(tkm_listener_t
, destroy
, void,
310 private_tkm_listener_t
*this)
318 tkm_listener_t
*tkm_listener_create()
320 private_tkm_listener_t
*this;
325 .authorize
= _authorize
,
333 return &this->public;