added PSK support
[strongswan.git] / src / charon / sa / authenticator.c
1 /**
2 * @file authenticator.c
3 *
4 * @brief Implementation of authenticator_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include <string.h>
25
26 #include "authenticator.h"
27
28 #include <daemon.h>
29
30 /**
31 * Key pad for the AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
32 */
33 #define IKEV2_KEY_PAD "Key Pad for IKEv2"
34
35
36 typedef struct private_authenticator_t private_authenticator_t;
37
38 /**
39 * Private data of an authenticator_t object.
40 */
41 struct private_authenticator_t {
42
43 /**
44 * Public authenticator_t interface.
45 */
46 authenticator_t public;
47
48 /**
49 * Assigned IKE_SA. Needed to get objects of type prf_t and logger_t.
50 */
51 ike_sa_t *ike_sa;
52
53 /**
54 * auth_method to create own signature/mac/whatever..
55 */
56 auth_method_t auth_method;
57
58 /**
59 * PRF taken from the IKE_SA.
60 */
61 prf_t *prf;
62
63 /**
64 * A logger for.
65 *
66 * Using logger of IKE_SA.
67 */
68 logger_t *logger;
69
70 /**
71 * @brief Builds the octets to be signed (RSA or PSK) as described in section 2.15 of RFC 4306.
72 *
73 * @param this calling object
74 * @param last_message the last message to include in created octets
75 * (either binary form of IKE_SA_INIT request or IKE_SA_INIT response)
76 * @param other_nonce Nonce data received from other peer
77 * @param id ID of signer
78 * @param initiator Type of peer. TRUE, if it is original initiator, FALSE otherwise
79 * @return octets as described in section 2.15. Memory gets allocated and has to get
80 * destroyed by caller.
81 */
82 chunk_t (*build_tbs_octets) (private_authenticator_t *this,
83 chunk_t last_message,
84 chunk_t other_nonce,
85 identification_t *id,
86 bool initiator);
87
88 /**
89 * @brief Creates the AUTH data using auth method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
90 *
91 * @param this calling object
92 * @param last_message the last message
93 * (either binary form of IKE_SA_INIT request or IKE_SA_INIT response)
94 * @param nonce Nonce data to include in auth data compution
95 * @param id ID of signer
96 * @param initiator Type of peer. TRUE, if it is original initiator, FALSE otherwise
97 * @param secret shared secret as chunk_t. If shared secret is a string,
98 * the NULL termination is not included.
99 * @return AUTH data as dscribed in section 2.15 for
100 * AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
101 * Memory gets allocated and has to get destroyed by caller.
102 */
103 chunk_t (*build_shared_key_signature) (private_authenticator_t *this,
104 chunk_t last_message,
105 chunk_t nonce,
106 identification_t *id,
107 bool initiator,
108 chunk_t secret);
109 };
110
111 /**
112 * Implementation of private_authenticator_t.build_tbs_octets.
113 */
114 static chunk_t build_tbs_octets(private_authenticator_t *this,
115 chunk_t last_message,
116 chunk_t other_nonce,
117 identification_t *id,
118 bool initiator)
119 {
120 prf_t *prf;
121
122 chunk_t id_encoding = id->get_encoding(id);
123 u_int8_t id_with_header[4 + id_encoding.len];
124 chunk_t id_with_header_chunk = {ptr:id_with_header, len: sizeof(id_with_header)};
125
126 u_int8_t *current_pos;
127 chunk_t octets;
128
129 id_with_header[0] = id->get_type(id);
130 id_with_header[1] = 0x00;
131 id_with_header[2] = 0x00;
132 id_with_header[3] = 0x00;
133 memcpy(id_with_header + 4, id_encoding.ptr, id_encoding.len);
134
135 if (initiator)
136 {
137 prf = this->ike_sa->get_prf_auth_i(this->ike_sa);
138 }
139 else
140 {
141 prf = this->ike_sa->get_prf_auth_r(this->ike_sa);
142 }
143
144 /* 4 bytes are id type and reserved fields of id payload */
145 octets.len = last_message.len + other_nonce.len + prf->get_block_size(prf);
146 octets.ptr = malloc(octets.len);
147 current_pos = octets.ptr;
148 memcpy(current_pos, last_message.ptr, last_message.len);
149 current_pos += last_message.len;
150 memcpy(current_pos, other_nonce.ptr, other_nonce.len);
151 current_pos += other_nonce.len;
152 prf->get_bytes(prf, id_with_header_chunk, current_pos);
153
154 this->logger->log_chunk(this->logger,RAW | LEVEL2, "octets (message + nonce + prf(Sk_px,Idx)",octets);
155 return octets;
156 }
157
158 /**
159 * Implementation of private_authenticator_t.build_shared_key_signature.
160 */
161 static chunk_t build_shared_key_signature(private_authenticator_t *this,
162 chunk_t last_message,
163 chunk_t nonce,
164 identification_t *id,
165 bool initiator,
166 chunk_t secret)
167 {
168 chunk_t key_pad = {ptr: IKEV2_KEY_PAD, len:strlen(IKEV2_KEY_PAD)};
169 u_int8_t key_buffer[this->prf->get_block_size(this->prf)];
170 chunk_t key = {ptr: key_buffer, len: sizeof(key_buffer)};
171 chunk_t auth_data;
172
173 chunk_t octets = this->build_tbs_octets(this, last_message, nonce, id, initiator);
174
175 /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */
176 this->prf->set_key(this->prf, secret);
177 this->prf->get_bytes(this->prf, key_pad, key_buffer);
178 this->prf->set_key(this->prf, key);
179 this->prf->allocate_bytes(this->prf, octets, &auth_data);
180 chunk_free(&octets);
181 this->logger->log_chunk(this->logger,RAW | LEVEL2, "authenticated data", auth_data);
182
183 return auth_data;
184 }
185
186 /**
187 * Implementation of authenticator_t.verify_auth_data.
188 */
189 static status_t verify_auth_data (private_authenticator_t *this,
190 auth_payload_t *auth_payload,
191 chunk_t last_received_packet,
192 chunk_t my_nonce,
193 identification_t *my_id,
194 identification_t *other_id,
195 bool initiator)
196 {
197 switch(auth_payload->get_auth_method(auth_payload))
198 {
199 case SHARED_KEY_MESSAGE_INTEGRITY_CODE:
200 {
201 chunk_t auth_data = auth_payload->get_data(auth_payload);
202 chunk_t shared_key;
203 status_t status;
204
205 status = charon->credentials->get_shared_key(charon->credentials,
206 my_id,
207 other_id,
208 &shared_key);
209 if (status != SUCCESS)
210 {
211 this->logger->log(this->logger, ERROR, "no shared key found for '%s' and '%s'",
212 my_id->get_string(my_id), other_id->get_string(other_id));
213 return status;
214 }
215
216 chunk_t my_auth_data = this->build_shared_key_signature(this,
217 last_received_packet,
218 my_nonce,
219 other_id,
220 initiator,
221 shared_key);
222 chunk_free(&shared_key);
223
224 if (auth_data.len != my_auth_data.len)
225 {
226 chunk_free(&my_auth_data);
227 status = FAILED;
228 }
229 else if (memcmp(auth_data.ptr,my_auth_data.ptr, my_auth_data.len) == 0)
230 {
231 this->logger->log(this->logger, CONTROL, "authentication of '%s' with pre-shared key successful",
232 other_id->get_string(other_id));
233 status = SUCCESS;
234 }
235 else
236 {
237 this->logger->log(this->logger, ERROR, "authentication of '%s' with pre-shared key failed",
238 other_id->get_string(other_id));
239 status = FAILED;
240 }
241 chunk_free(&my_auth_data);
242 return status;
243 }
244 case RSA_DIGITAL_SIGNATURE:
245 {
246 status_t status;
247 chunk_t octets;
248 chunk_t auth_data = auth_payload->get_data(auth_payload);
249
250 rsa_public_key_t *public_key =
251 charon->credentials->get_trusted_public_key(charon->credentials, other_id);
252
253 if (public_key == NULL)
254 {
255 this->logger->log(this->logger, ERROR, "no RSA public key found for '%s'",
256 other_id->get_string(other_id));
257 return NOT_FOUND;
258 }
259
260 octets = this->build_tbs_octets(this, last_received_packet, my_nonce, other_id, initiator);
261
262 status = public_key->verify_emsa_pkcs1_signature(public_key, octets, auth_data);
263 if (status == SUCCESS)
264 {
265 this->logger->log(this->logger, CONTROL, "authentication of '%s' with RSA signature successful",
266 other_id->get_string(other_id));
267 }
268 else
269 {
270 this->logger->log(this->logger, ERROR, "authentication of '%s' with RSA signature failed",
271 other_id->get_string(other_id));
272 }
273 chunk_free(&octets);
274 return status;
275 }
276 default:
277 {
278 return NOT_SUPPORTED;
279 }
280 }
281 }
282
283 /**
284 * Implementation of authenticator_t.compute_auth_data.
285 */
286 static status_t compute_auth_data (private_authenticator_t *this,
287 auth_payload_t **auth_payload,
288 chunk_t last_sent_packet,
289 chunk_t other_nonce,
290 identification_t *my_id,
291 identification_t *other_id,
292 bool initiator)
293 {
294 switch (this->auth_method)
295 {
296 case SHARED_KEY_MESSAGE_INTEGRITY_CODE:
297 {
298 chunk_t shared_key;
299 chunk_t auth_data;
300
301 status_t status = charon->credentials->get_shared_key(charon->credentials,
302 my_id,
303 other_id,
304 &shared_key);
305
306 if (status != SUCCESS)
307 {
308 this->logger->log(this->logger, ERROR, "no shared key found for '%s' and '%s'",
309 my_id->get_string(my_id), other_id->get_string(other_id));
310 return status;
311 }
312
313 auth_data = this->build_shared_key_signature(this,
314 last_sent_packet,
315 other_nonce,
316 my_id,
317 initiator,
318 shared_key);
319 chunk_free(&shared_key);
320 *auth_payload = auth_payload_create();
321 (*auth_payload)->set_auth_method(*auth_payload, SHARED_KEY_MESSAGE_INTEGRITY_CODE);
322 (*auth_payload)->set_data(*auth_payload, auth_data);
323
324 chunk_free(&auth_data);
325 return SUCCESS;
326 }
327 case RSA_DIGITAL_SIGNATURE:
328 {
329 char buf[BUF_LEN];
330 chunk_t octets;
331 chunk_t auth_data;
332 status_t status;
333 rsa_public_key_t *my_pubkey;
334 rsa_private_key_t *my_key;
335
336 this->logger->log(this->logger, CONTROL|LEVEL1, "looking for RSA public key belonging to '%s'",
337 my_id->get_string(my_id));
338
339 my_pubkey = charon->credentials->get_rsa_public_key(charon->credentials, my_id);
340 if (my_pubkey == NULL)
341 {
342 this->logger->log(this->logger, ERROR, "no RSA public key found for '%s'",
343 my_id->get_string(my_id));
344 return NOT_FOUND;
345 }
346 this->logger->log(this->logger, CONTROL|LEVEL2, "matching RSA public key found");
347
348 chunk_to_hex(buf, BUF_LEN, my_pubkey->get_keyid(my_pubkey));
349 this->logger->log(this->logger, CONTROL|LEVEL1, "looking for RSA private key with keyid %s", buf);
350
351 my_key = charon->credentials->get_rsa_private_key(charon->credentials, my_pubkey);
352 if (my_key == NULL)
353 {
354 char buf[BUF_LEN];
355
356 chunk_to_hex(buf, BUF_LEN, my_pubkey->get_keyid(my_pubkey));
357 this->logger->log(this->logger, ERROR, "no RSA private key found with for %s with keyid %s",
358 my_id->get_string(my_id), buf);
359 return NOT_FOUND;
360 }
361 this->logger->log(this->logger, CONTROL|LEVEL2, "matching RSA private key found");
362
363 octets = this->build_tbs_octets(this, last_sent_packet, other_nonce, my_id, initiator);
364 status = my_key->build_emsa_pkcs1_signature(my_key, HASH_SHA1, octets, &auth_data);
365 chunk_free(&octets);
366
367 if (status != SUCCESS)
368 {
369 my_key->destroy(my_key);
370 return status;
371 }
372 this->logger->log(this->logger, CONTROL|LEVEL2, "successfully signed with RSA private key");
373
374 *auth_payload = auth_payload_create();
375 (*auth_payload)->set_auth_method(*auth_payload, RSA_DIGITAL_SIGNATURE);
376 (*auth_payload)->set_data(*auth_payload, auth_data);
377
378 my_key->destroy(my_key);
379 chunk_free(&auth_data);
380 return SUCCESS;
381 }
382 default:
383 {
384 return NOT_SUPPORTED;
385 }
386 }
387 }
388
389 /**
390 * Implementation of authenticator_t.destroy.
391 */
392 static void destroy (private_authenticator_t *this)
393 {
394 free(this);
395 }
396
397 /*
398 * Described in header.
399 */
400 authenticator_t *authenticator_create(ike_sa_t *ike_sa, auth_method_t auth_method)
401 {
402 private_authenticator_t *this = malloc_thing(private_authenticator_t);
403
404 /* Public functions */
405 this->public.destroy = (void(*)(authenticator_t*))destroy;
406 this->public.verify_auth_data = (status_t (*) (authenticator_t*,auth_payload_t*,chunk_t,
407 chunk_t,identification_t*,identification_t*,bool)) verify_auth_data;
408 this->public.compute_auth_data = (status_t (*) (authenticator_t*,auth_payload_t**,chunk_t,
409 chunk_t,identification_t*,identification_t*,bool)) compute_auth_data;
410
411 /* private functions */
412 this->build_tbs_octets = build_tbs_octets;
413 this->build_shared_key_signature = build_shared_key_signature;
414
415 /* private data */
416 this->ike_sa = ike_sa;
417 this->auth_method = auth_method;
418 this->prf = this->ike_sa->get_prf(this->ike_sa);
419 this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
420
421 return &(this->public);
422 }