2 * @file authenticator.c
4 * @brief Implementation of authenticator_t.
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
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>.
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
23 #include "authenticator.h"
25 #include <utils/allocator.h>
29 * Key pad for the AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
31 #define IKE_V2_KEY_PAD "Key Pad for IKEv2"
34 * Length of key pad in bytes.
36 #define IKE_V2_KEY_PAD_LEN strlen(IKE_V2_KEY_PAD)
39 typedef struct private_authenticator_t private_authenticator_t
;
42 * Private data of an authenticator_t object.
44 struct private_authenticator_t
{
47 * Public authenticator_t interface.
49 authenticator_t
public;
52 * Assigned IKE_SA. Needed to get objects of type prf_t, sa_config_t and logger_t.
54 protected_ike_sa_t
*ike_sa
;
57 * PRF taken from the IKE_SA.
64 * Using logger of IKE_SA.
69 * @brief Creates the octets which are signed (RSA) or MACed (shared secret) as described in section
72 * @param this calling object
73 * @param last_message the last message to include in created octets
74 * (either binary form of IKE_SA_INIT request or IKE_SA_INIT response)
75 * @param other_nonce Nonce data received from other peer
76 * @param my_id id_payload_t object representing an ID payload
77 * @param initiator Type of peer. TRUE, if it is original initiator, FALSE otherwise
78 * @return octets as described in section 2.15. Memory gets allocated and has to get
79 * destroyed by caller.
81 chunk_t (*allocate_octets
) (private_authenticator_t
*this,
88 * @brief Creates the AUTH data using auth method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
90 * @param this calling object
91 * @param last_message the last message
92 * (either binary form of IKE_SA_INIT request or IKE_SA_INIT response)
93 * @param nonce Nonce data to include in auth data compution
94 * @param id_payload id_payload_t object representing an ID payload
95 * @param initiator Type of peer. TRUE, if it is original initiator, FALSE otherwise
96 * @param shared_secret shared secret as chunk_t. If shared secret is a string,
97 * the NULL termination is not included.
98 * @return AUTH data as dscribed in section 2.15 for
99 * AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
100 * Memory gets allocated and has to get destroyed by caller.
102 chunk_t (*allocate_auth_data_with_preshared_secret
) (private_authenticator_t
*this,
103 chunk_t last_message
,
105 id_payload_t
*id_payload
,
107 chunk_t preshared_secret
);
111 * Implementation of private_authenticator_t.allocate_octets.
113 static chunk_t
allocate_octets(private_authenticator_t
*this,
114 chunk_t last_message
,
119 chunk_t id_chunk
= my_id
->get_data(my_id
);
120 u_int8_t id_with_header
[4 + id_chunk
.len
];
122 * IKEv2 for linux (http://sf.net/projects/ikev2/)
123 * is not compatible with IKEv2 Draft and so not compatible with this
124 * implementation, cause AUTH data are computed without
125 * ID type and the three reserved bytes.
127 chunk_t id_with_header_chunk
= {ptr
:id_with_header
, len
: sizeof(id_with_header
)};
128 u_int8_t
*current_pos
;
131 id_with_header
[0] = my_id
->get_id_type(my_id
);
133 * Reserved bytes are not in any case zero.
135 id_with_header
[1] = 0x00;
136 id_with_header
[2] = 0x00;
137 id_with_header
[3] = 0x00;
138 memcpy(id_with_header
+ 4,id_chunk
.ptr
,id_chunk
.len
);
142 this->prf
->set_key(this->prf
,this->ike_sa
->get_key_pi(this->ike_sa
));
146 this->prf
->set_key(this->prf
,this->ike_sa
->get_key_pr(this->ike_sa
));
150 /* 4 bytes are id type and reserved fields of id payload */
151 octets
.len
= last_message
.len
+ other_nonce
.len
+ this->prf
->get_block_size(this->prf
);
152 octets
.ptr
= allocator_alloc(octets
.len
);
153 current_pos
= octets
.ptr
;
154 memcpy(current_pos
,last_message
.ptr
,last_message
.len
);
155 current_pos
+= last_message
.len
;
156 memcpy(current_pos
,other_nonce
.ptr
,other_nonce
.len
);
157 current_pos
+= other_nonce
.len
;
158 this->prf
->get_bytes(this->prf
,id_with_header_chunk
,current_pos
);
160 this->logger
->log_chunk(this->logger
,RAW
| LEVEL2
, "Octets (Mesage + Nonce + prf(Sk_px,Idx)",&octets
);
165 * Implementation of private_authenticator_t.allocate_auth_data_with_preshared_secret.
167 static chunk_t
allocate_auth_data_with_preshared_secret (private_authenticator_t
*this,
168 chunk_t last_message
,
170 id_payload_t
*id_payload
,
172 chunk_t preshared_secret
)
174 chunk_t key_pad
= {ptr
: IKE_V2_KEY_PAD
, len
:IKE_V2_KEY_PAD_LEN
};
175 u_int8_t key_buffer
[this->prf
->get_block_size(this->prf
)];
176 chunk_t key
= {ptr
: key_buffer
, len
: sizeof(key_buffer
)};
179 chunk_t octets
= this->allocate_octets(this,last_message
,nonce
,id_payload
,initiator
);
182 * AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>)
185 this->prf
->set_key(this->prf
,preshared_secret
);
186 this->prf
->get_bytes(this->prf
,key_pad
,key_buffer
);
187 this->prf
->set_key(this->prf
,key
);
188 this->prf
->allocate_bytes(this->prf
,octets
,&auth_data
);
189 allocator_free_chunk(&octets
);
190 this->logger
->log_chunk(this->logger
,RAW
| LEVEL2
, "Authenticated data",&auth_data
);
196 * Implementation of authenticator_t.verify_auth_data.
198 static status_t
verify_auth_data (private_authenticator_t
*this,
199 auth_payload_t
*auth_payload
,
200 chunk_t last_received_packet
,
202 id_payload_t
*other_id_payload
,
205 switch(auth_payload
->get_auth_method(auth_payload
))
207 case SHARED_KEY_MESSAGE_INTEGRITY_CODE
:
209 identification_t
*other_id
= other_id_payload
->get_identification(other_id_payload
);
210 chunk_t auth_data
= auth_payload
->get_data(auth_payload
);
211 chunk_t preshared_secret
;
214 status
= charon
->configuration_manager
->get_shared_secret(charon
->configuration_manager
,
217 other_id
->destroy(other_id
);
218 if (status
!= SUCCESS
)
223 chunk_t my_auth_data
= this->allocate_auth_data_with_preshared_secret(this,
224 last_received_packet
,
230 if (auth_data
.len
!= my_auth_data
.len
)
232 allocator_free_chunk(&my_auth_data
);
235 if (memcmp(auth_data
.ptr
,my_auth_data
.ptr
,my_auth_data
.len
) == 0)
243 allocator_free_chunk(&my_auth_data
);
246 case RSA_DIGITAL_SIGNATURE
:
248 identification_t
*other_id
= other_id_payload
->get_identification(other_id_payload
);
249 rsa_public_key_t
*public_key
;
251 chunk_t octets
, auth_data
;
253 auth_data
= auth_payload
->get_data(auth_payload
);
255 status
= charon
->configuration_manager
->get_rsa_public_key(charon
->configuration_manager
,
258 other_id
->destroy(other_id
);
259 if (status
!= SUCCESS
)
264 octets
= this->allocate_octets(this,last_received_packet
,my_nonce
,other_id_payload
,initiator
);
266 status
= public_key
->verify_emsa_pkcs1_signature(public_key
, octets
, auth_data
);
268 allocator_free_chunk(&octets
);
273 return NOT_SUPPORTED
;
279 * Implementation of authenticator_t.compute_auth_data.
281 static status_t
compute_auth_data (private_authenticator_t
*this,
282 auth_payload_t
**auth_payload
,
283 chunk_t last_sent_packet
,
285 id_payload_t
*my_id_payload
,
288 sa_config_t
*sa_config
= this->ike_sa
->get_sa_config(this->ike_sa
);
290 switch(sa_config
->get_auth_method(sa_config
))
292 case SHARED_KEY_MESSAGE_INTEGRITY_CODE
:
294 identification_t
*my_id
=my_id_payload
->get_identification(my_id_payload
);
295 chunk_t preshared_secret
;
298 status
= charon
->configuration_manager
->get_shared_secret(charon
->configuration_manager
,
302 my_id
->destroy(my_id
);
303 if (status
!= SUCCESS
)
308 chunk_t auth_data
= this->allocate_auth_data_with_preshared_secret(this,
315 *auth_payload
= auth_payload_create();
316 (*auth_payload
)->set_auth_method((*auth_payload
),SHARED_KEY_MESSAGE_INTEGRITY_CODE
);
317 (*auth_payload
)->set_data((*auth_payload
),auth_data
);
319 allocator_free_chunk(&auth_data
);
322 case RSA_DIGITAL_SIGNATURE
:
324 identification_t
*my_id
= my_id_payload
->get_identification(my_id_payload
);
325 rsa_private_key_t
*private_key
;
327 chunk_t octets
, auth_data
;
329 status
= charon
->configuration_manager
->get_rsa_private_key(charon
->configuration_manager
,
332 my_id
->destroy(my_id
);
333 if (status
!= SUCCESS
)
338 octets
= this->allocate_octets(this,last_sent_packet
,other_nonce
,my_id_payload
,initiator
);
340 status
= private_key
->build_emsa_pkcs1_signature(private_key
, HASH_SHA1
, octets
, &auth_data
);
341 allocator_free_chunk(&octets
);
342 if (status
!= SUCCESS
)
347 *auth_payload
= auth_payload_create();
348 (*auth_payload
)->set_auth_method((*auth_payload
), RSA_DIGITAL_SIGNATURE
);
349 (*auth_payload
)->set_data((*auth_payload
),auth_data
);
351 allocator_free_chunk(&auth_data
);
356 return NOT_SUPPORTED
;
362 * Implementation of authenticator_t.destroy.
364 static void destroy (private_authenticator_t
*this)
366 allocator_free(this);
370 * Described in header.
372 authenticator_t
*authenticator_create(protected_ike_sa_t
*ike_sa
)
374 private_authenticator_t
*this = allocator_alloc_thing(private_authenticator_t
);
376 /* Public functions */
377 this->public.destroy
= (void(*)(authenticator_t
*))destroy
;
378 this->public.verify_auth_data
= (status_t (*) (authenticator_t
*,auth_payload_t
*, chunk_t
,chunk_t
,id_payload_t
*,bool)) verify_auth_data
;
379 this->public.compute_auth_data
= (status_t (*) (authenticator_t
*,auth_payload_t
**, chunk_t
,chunk_t
,id_payload_t
*,bool)) compute_auth_data
;
381 /* private functions */
382 this->allocate_octets
= allocate_octets
;
383 this->allocate_auth_data_with_preshared_secret
= allocate_auth_data_with_preshared_secret
;
386 this->ike_sa
= ike_sa
;
387 this->prf
= this->ike_sa
->get_prf(this->ike_sa
);
388 this->logger
= this->ike_sa
->get_logger(this->ike_sa
);
390 return &(this->public);