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