more debugging output for PSK authentication
[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 return octets;
155 }
156
157 /**
158 * Implementation of private_authenticator_t.build_shared_key_signature.
159 */
160 static chunk_t build_shared_key_signature(private_authenticator_t *this,
161 chunk_t last_message,
162 chunk_t nonce,
163 identification_t *id,
164 bool initiator,
165 chunk_t secret)
166 {
167 chunk_t key_pad = {ptr: IKEV2_KEY_PAD, len:strlen(IKEV2_KEY_PAD)};
168 u_int8_t key_buffer[this->prf->get_block_size(this->prf)];
169 chunk_t key = {ptr: key_buffer, len: sizeof(key_buffer)};
170 chunk_t auth_data;
171
172 chunk_t octets = this->build_tbs_octets(this, last_message, nonce, id, initiator);
173
174 /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */
175 this->prf->set_key(this->prf, secret);
176 this->prf->get_bytes(this->prf, key_pad, key_buffer);
177 this->prf->set_key(this->prf, key);
178 this->prf->allocate_bytes(this->prf, octets, &auth_data);
179 this->logger->log_chunk(this->logger, RAW|LEVEL2,
180 "octets = message + nonce + prf(Sk_px, IDx')", octets);
181 this->logger->log_chunk(this->logger, PRIVATE|LEVEL2,
182 "secret", secret);
183 this->logger->log_chunk(this->logger, RAW|LEVEL2,
184 "keypad", key_pad);
185 this->logger->log_chunk(this->logger, RAW|LEVEL2,
186 "prf(secret, keypad)", key);
187 this->logger->log_chunk(this->logger,RAW | LEVEL2,
188 "AUTH = prf(prf(secret, keypad), octets)", auth_data);
189 chunk_free(&octets);
190
191 return auth_data;
192 }
193
194 /**
195 * Implementation of authenticator_t.verify_auth_data.
196 */
197 static status_t verify_auth_data (private_authenticator_t *this,
198 auth_payload_t *auth_payload,
199 chunk_t last_received_packet,
200 chunk_t my_nonce,
201 identification_t *my_id,
202 identification_t *other_id,
203 bool initiator)
204 {
205 switch(auth_payload->get_auth_method(auth_payload))
206 {
207 case SHARED_KEY_MESSAGE_INTEGRITY_CODE:
208 {
209 chunk_t auth_data = auth_payload->get_data(auth_payload);
210 chunk_t shared_key;
211 status_t status;
212
213 status = charon->credentials->get_shared_key(charon->credentials,
214 my_id,
215 other_id,
216 &shared_key);
217 if (status != SUCCESS)
218 {
219 this->logger->log(this->logger, ERROR, "no shared key found for '%s' and '%s'",
220 my_id->get_string(my_id), other_id->get_string(other_id));
221 return status;
222 }
223
224 chunk_t my_auth_data = this->build_shared_key_signature(this,
225 last_received_packet,
226 my_nonce,
227 other_id,
228 initiator,
229 shared_key);
230 chunk_free(&shared_key);
231
232 if (auth_data.len != my_auth_data.len)
233 {
234 chunk_free(&my_auth_data);
235 status = FAILED;
236 }
237 else if (memcmp(auth_data.ptr,my_auth_data.ptr, my_auth_data.len) == 0)
238 {
239 this->logger->log(this->logger, CONTROL, "authentication of '%s' with pre-shared key successful",
240 other_id->get_string(other_id));
241 status = SUCCESS;
242 }
243 else
244 {
245 this->logger->log(this->logger, ERROR, "authentication of '%s' with pre-shared key failed",
246 other_id->get_string(other_id));
247 status = FAILED;
248 }
249 chunk_free(&my_auth_data);
250 return status;
251 }
252 case RSA_DIGITAL_SIGNATURE:
253 {
254 status_t status;
255 chunk_t octets;
256 chunk_t auth_data = auth_payload->get_data(auth_payload);
257
258 rsa_public_key_t *public_key =
259 charon->credentials->get_trusted_public_key(charon->credentials, other_id);
260
261 if (public_key == NULL)
262 {
263 this->logger->log(this->logger, ERROR, "no RSA public key found for '%s'",
264 other_id->get_string(other_id));
265 return NOT_FOUND;
266 }
267
268 octets = this->build_tbs_octets(this, last_received_packet, my_nonce, other_id, initiator);
269
270 status = public_key->verify_emsa_pkcs1_signature(public_key, octets, auth_data);
271 if (status == SUCCESS)
272 {
273 this->logger->log(this->logger, CONTROL, "authentication of '%s' with RSA signature successful",
274 other_id->get_string(other_id));
275 }
276 else
277 {
278 this->logger->log(this->logger, ERROR, "authentication of '%s' with RSA signature failed",
279 other_id->get_string(other_id));
280 }
281 chunk_free(&octets);
282 return status;
283 }
284 default:
285 {
286 return NOT_SUPPORTED;
287 }
288 }
289 }
290
291 /**
292 * Implementation of authenticator_t.compute_auth_data.
293 */
294 static status_t compute_auth_data (private_authenticator_t *this,
295 auth_payload_t **auth_payload,
296 chunk_t last_sent_packet,
297 chunk_t other_nonce,
298 identification_t *my_id,
299 identification_t *other_id,
300 bool initiator)
301 {
302 switch (this->auth_method)
303 {
304 case SHARED_KEY_MESSAGE_INTEGRITY_CODE:
305 {
306 chunk_t shared_key;
307 chunk_t auth_data;
308
309 status_t status = charon->credentials->get_shared_key(charon->credentials,
310 my_id,
311 other_id,
312 &shared_key);
313
314 if (status != SUCCESS)
315 {
316 this->logger->log(this->logger, ERROR, "no shared key found for '%s' and '%s'",
317 my_id->get_string(my_id), other_id->get_string(other_id));
318 return status;
319 }
320
321 auth_data = this->build_shared_key_signature(this,
322 last_sent_packet,
323 other_nonce,
324 my_id,
325 initiator,
326 shared_key);
327 chunk_free(&shared_key);
328 *auth_payload = auth_payload_create();
329 (*auth_payload)->set_auth_method(*auth_payload, SHARED_KEY_MESSAGE_INTEGRITY_CODE);
330 (*auth_payload)->set_data(*auth_payload, auth_data);
331
332 chunk_free(&auth_data);
333 return SUCCESS;
334 }
335 case RSA_DIGITAL_SIGNATURE:
336 {
337 char buf[BUF_LEN];
338 chunk_t octets;
339 chunk_t auth_data;
340 status_t status;
341 rsa_public_key_t *my_pubkey;
342 rsa_private_key_t *my_key;
343
344 this->logger->log(this->logger, CONTROL|LEVEL1, "looking for RSA public key belonging to '%s'",
345 my_id->get_string(my_id));
346
347 my_pubkey = charon->credentials->get_rsa_public_key(charon->credentials, my_id);
348 if (my_pubkey == NULL)
349 {
350 this->logger->log(this->logger, ERROR, "no RSA public key found for '%s'",
351 my_id->get_string(my_id));
352 return NOT_FOUND;
353 }
354 this->logger->log(this->logger, CONTROL|LEVEL2, "matching RSA public key found");
355
356 chunk_to_hex(buf, BUF_LEN, my_pubkey->get_keyid(my_pubkey));
357 this->logger->log(this->logger, CONTROL|LEVEL1, "looking for RSA private key with keyid %s", buf);
358
359 my_key = charon->credentials->get_rsa_private_key(charon->credentials, my_pubkey);
360 if (my_key == NULL)
361 {
362 char buf[BUF_LEN];
363
364 chunk_to_hex(buf, BUF_LEN, my_pubkey->get_keyid(my_pubkey));
365 this->logger->log(this->logger, ERROR, "no RSA private key found with for %s with keyid %s",
366 my_id->get_string(my_id), buf);
367 return NOT_FOUND;
368 }
369 this->logger->log(this->logger, CONTROL|LEVEL2, "matching RSA private key found");
370
371 octets = this->build_tbs_octets(this, last_sent_packet, other_nonce, my_id, initiator);
372 status = my_key->build_emsa_pkcs1_signature(my_key, HASH_SHA1, octets, &auth_data);
373 chunk_free(&octets);
374
375 if (status != SUCCESS)
376 {
377 my_key->destroy(my_key);
378 return status;
379 }
380 this->logger->log(this->logger, CONTROL|LEVEL2, "successfully signed with RSA private key");
381
382 *auth_payload = auth_payload_create();
383 (*auth_payload)->set_auth_method(*auth_payload, RSA_DIGITAL_SIGNATURE);
384 (*auth_payload)->set_data(*auth_payload, auth_data);
385
386 my_key->destroy(my_key);
387 chunk_free(&auth_data);
388 return SUCCESS;
389 }
390 default:
391 {
392 return NOT_SUPPORTED;
393 }
394 }
395 }
396
397 /**
398 * Implementation of authenticator_t.destroy.
399 */
400 static void destroy (private_authenticator_t *this)
401 {
402 free(this);
403 }
404
405 /*
406 * Described in header.
407 */
408 authenticator_t *authenticator_create(ike_sa_t *ike_sa, auth_method_t auth_method)
409 {
410 private_authenticator_t *this = malloc_thing(private_authenticator_t);
411
412 /* Public functions */
413 this->public.destroy = (void(*)(authenticator_t*))destroy;
414 this->public.verify_auth_data = (status_t (*) (authenticator_t*,auth_payload_t*,chunk_t,
415 chunk_t,identification_t*,identification_t*,bool)) verify_auth_data;
416 this->public.compute_auth_data = (status_t (*) (authenticator_t*,auth_payload_t**,chunk_t,
417 chunk_t,identification_t*,identification_t*,bool)) compute_auth_data;
418
419 /* private functions */
420 this->build_tbs_octets = build_tbs_octets;
421 this->build_shared_key_signature = build_shared_key_signature;
422
423 /* private data */
424 this->ike_sa = ike_sa;
425 this->auth_method = auth_method;
426 this->prf = this->ike_sa->get_prf(this->ike_sa);
427 this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
428
429 return &(this->public);
430 }