Moving charon to libcharon.
[strongswan.git] / src / libcharon / sa / authenticators / psk_authenticator.c
1 /*
2 * Copyright (C) 2005-2009 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
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 "psk_authenticator.h"
18
19 #include <daemon.h>
20 #include <encoding/payloads/auth_payload.h>
21
22 typedef struct private_psk_authenticator_t private_psk_authenticator_t;
23
24 /**
25 * Private data of an psk_authenticator_t object.
26 */
27 struct private_psk_authenticator_t {
28
29 /**
30 * Public authenticator_t interface.
31 */
32 psk_authenticator_t public;
33
34 /**
35 * Assigned IKE_SA
36 */
37 ike_sa_t *ike_sa;
38
39 /**
40 * nonce to include in AUTH calculation
41 */
42 chunk_t nonce;
43
44 /**
45 * IKE_SA_INIT message data to include in AUTH calculation
46 */
47 chunk_t ike_sa_init;
48 };
49
50 /*
51 * Implementation of authenticator_t.build for builder
52 */
53 static status_t build(private_psk_authenticator_t *this, message_t *message)
54 {
55 identification_t *my_id, *other_id;
56 auth_payload_t *auth_payload;
57 shared_key_t *key;
58 chunk_t auth_data;
59 keymat_t *keymat;
60
61 keymat = this->ike_sa->get_keymat(this->ike_sa);
62 my_id = this->ike_sa->get_my_id(this->ike_sa);
63 other_id = this->ike_sa->get_other_id(this->ike_sa);
64 DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N",
65 my_id, auth_method_names, AUTH_PSK);
66 key = charon->credentials->get_shared(charon->credentials, SHARED_IKE,
67 my_id, other_id);
68 if (key == NULL)
69 {
70 DBG1(DBG_IKE, "no shared key found for '%Y' - '%Y'", my_id, other_id);
71 return NOT_FOUND;
72 }
73 auth_data = keymat->get_psk_sig(keymat, FALSE, this->ike_sa_init,
74 this->nonce, key->get_key(key), my_id);
75 key->destroy(key);
76 DBG2(DBG_IKE, "successfully created shared key MAC");
77 auth_payload = auth_payload_create();
78 auth_payload->set_auth_method(auth_payload, AUTH_PSK);
79 auth_payload->set_data(auth_payload, auth_data);
80 chunk_free(&auth_data);
81 message->add_payload(message, (payload_t*)auth_payload);
82
83 return SUCCESS;
84 }
85
86 /**
87 * Implementation of authenticator_t.process for verifier
88 */
89 static status_t process(private_psk_authenticator_t *this, message_t *message)
90 {
91 chunk_t auth_data, recv_auth_data;
92 identification_t *my_id, *other_id;
93 auth_payload_t *auth_payload;
94 auth_cfg_t *auth;
95 shared_key_t *key;
96 enumerator_t *enumerator;
97 bool authenticated = FALSE;
98 int keys_found = 0;
99 keymat_t *keymat;
100
101 auth_payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
102 if (!auth_payload)
103 {
104 return FAILED;
105 }
106 keymat = this->ike_sa->get_keymat(this->ike_sa);
107 recv_auth_data = auth_payload->get_data(auth_payload);
108 my_id = this->ike_sa->get_my_id(this->ike_sa);
109 other_id = this->ike_sa->get_other_id(this->ike_sa);
110 enumerator = charon->credentials->create_shared_enumerator(
111 charon->credentials, SHARED_IKE, my_id, other_id);
112 while (!authenticated && enumerator->enumerate(enumerator, &key, NULL, NULL))
113 {
114 keys_found++;
115
116 auth_data = keymat->get_psk_sig(keymat, TRUE, this->ike_sa_init,
117 this->nonce, key->get_key(key), other_id);
118 if (auth_data.len && chunk_equals(auth_data, recv_auth_data))
119 {
120 DBG1(DBG_IKE, "authentication of '%Y' with %N successful",
121 other_id, auth_method_names, AUTH_PSK);
122 authenticated = TRUE;
123 }
124 chunk_free(&auth_data);
125 }
126 enumerator->destroy(enumerator);
127
128 if (!authenticated)
129 {
130 if (keys_found == 0)
131 {
132 DBG1(DBG_IKE, "no shared key found for '%Y' - '%Y'", my_id, other_id);
133 return NOT_FOUND;
134 }
135 DBG1(DBG_IKE, "tried %d shared key%s for '%Y' - '%Y', but MAC mismatched",
136 keys_found, keys_found == 1 ? "" : "s", my_id, other_id);
137 return FAILED;
138 }
139
140 auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
141 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
142 return SUCCESS;
143 }
144
145 /**
146 * Implementation of authenticator_t.process for builder
147 * Implementation of authenticator_t.build for verifier
148 */
149 static status_t return_failed()
150 {
151 return FAILED;
152 }
153
154 /**
155 * Implementation of authenticator_t.destroy.
156 */
157 static void destroy(private_psk_authenticator_t *this)
158 {
159 free(this);
160 }
161
162 /*
163 * Described in header.
164 */
165 psk_authenticator_t *psk_authenticator_create_builder(ike_sa_t *ike_sa,
166 chunk_t received_nonce, chunk_t sent_init)
167 {
168 private_psk_authenticator_t *this = malloc_thing(private_psk_authenticator_t);
169
170 this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))build;
171 this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))return_failed;
172 this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false;
173 this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
174
175 this->ike_sa = ike_sa;
176 this->ike_sa_init = sent_init;
177 this->nonce = received_nonce;
178
179 return &this->public;
180 }
181
182 /*
183 * Described in header.
184 */
185 psk_authenticator_t *psk_authenticator_create_verifier(ike_sa_t *ike_sa,
186 chunk_t sent_nonce, chunk_t received_init)
187 {
188 private_psk_authenticator_t *this = malloc_thing(private_psk_authenticator_t);
189
190 this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *messageh))return_failed;
191 this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process;
192 this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false;
193 this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
194
195 this->ike_sa = ike_sa;
196 this->ike_sa_init = received_init;
197 this->nonce = sent_nonce;
198
199 return &this->public;
200 }
201