2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2005-2009 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include "pubkey_authenticator.h"
21 #include <encoding/payloads/auth_payload.h>
23 typedef struct private_pubkey_authenticator_t private_pubkey_authenticator_t
;
26 * Private data of an pubkey_authenticator_t object.
28 struct private_pubkey_authenticator_t
{
31 * Public authenticator_t interface.
33 pubkey_authenticator_t
public;
41 * nonce to include in AUTH calculation
46 * IKE_SA_INIT message data to include in AUTH calculation
52 * Implementation of authenticator_t.build for builder
54 static status_t
build(private_pubkey_authenticator_t
*this, message_t
*message
)
56 chunk_t octets
, auth_data
;
57 status_t status
= FAILED
;
58 private_key_t
*private;
61 auth_payload_t
*auth_payload
;
62 auth_method_t auth_method
;
63 signature_scheme_t scheme
;
66 id
= this->ike_sa
->get_my_id(this->ike_sa
);
67 auth
= this->ike_sa
->get_auth_cfg(this->ike_sa
, TRUE
);
68 private = charon
->credentials
->get_private(charon
->credentials
, KEY_ANY
,
72 DBG1(DBG_IKE
, "no private key found for '%Y'", id
);
76 switch (private->get_type(private))
79 /* we currently use always SHA1 for signatures,
80 * TODO: support other hashes depending on configuration/auth */
81 scheme
= SIGN_RSA_EMSA_PKCS1_SHA1
;
82 auth_method
= AUTH_RSA
;
85 /* we try to deduct the signature scheme from the keysize */
86 switch (private->get_keysize(private))
89 scheme
= SIGN_ECDSA_256
;
90 auth_method
= AUTH_ECDSA_256
;
93 scheme
= SIGN_ECDSA_384
;
94 auth_method
= AUTH_ECDSA_384
;
97 scheme
= SIGN_ECDSA_521
;
98 auth_method
= AUTH_ECDSA_521
;
101 DBG1(DBG_IKE
, "%d bit ECDSA private key size not supported",
102 private->get_keysize(private));
107 DBG1(DBG_IKE
, "private key of type %N not supported",
108 key_type_names
, private->get_type(private));
111 keymat
= this->ike_sa
->get_keymat(this->ike_sa
);
112 octets
= keymat
->get_auth_octets(keymat
, FALSE
, this->ike_sa_init
,
114 if (private->sign(private, scheme
, octets
, &auth_data
))
116 auth_payload
= auth_payload_create();
117 auth_payload
->set_auth_method(auth_payload
, auth_method
);
118 auth_payload
->set_data(auth_payload
, auth_data
);
119 chunk_free(&auth_data
);
120 message
->add_payload(message
, (payload_t
*)auth_payload
);
123 DBG1(DBG_IKE
, "authentication of '%Y' (myself) with %N %s", id
,
124 auth_method_names
, auth_method
,
125 (status
== SUCCESS
)?
"successful":"failed");
127 private->destroy(private);
133 * Implementation of authenticator_t.process for verifier
135 static status_t
process(private_pubkey_authenticator_t
*this, message_t
*message
)
137 public_key_t
*public;
138 auth_method_t auth_method
;
139 auth_payload_t
*auth_payload
;
140 chunk_t auth_data
, octets
;
141 identification_t
*id
;
142 auth_cfg_t
*auth
, *current_auth
;
143 enumerator_t
*enumerator
;
144 key_type_t key_type
= KEY_ECDSA
;
145 signature_scheme_t scheme
;
146 status_t status
= NOT_FOUND
;
149 auth_payload
= (auth_payload_t
*)message
->get_payload(message
, AUTHENTICATION
);
154 auth_method
= auth_payload
->get_auth_method(auth_payload
);
158 /* We currently accept SHA1 signatures only
159 * TODO: allow other hash algorithms and note it in "auth" */
161 scheme
= SIGN_RSA_EMSA_PKCS1_SHA1
;
164 scheme
= SIGN_ECDSA_256
;
167 scheme
= SIGN_ECDSA_384
;
170 scheme
= SIGN_ECDSA_521
;
175 auth_data
= auth_payload
->get_data(auth_payload
);
176 id
= this->ike_sa
->get_other_id(this->ike_sa
);
177 keymat
= this->ike_sa
->get_keymat(this->ike_sa
);
178 octets
= keymat
->get_auth_octets(keymat
, TRUE
, this->ike_sa_init
,
180 auth
= this->ike_sa
->get_auth_cfg(this->ike_sa
, FALSE
);
181 enumerator
= charon
->credentials
->create_public_enumerator(
182 charon
->credentials
, key_type
, id
, auth
);
183 while (enumerator
->enumerate(enumerator
, &public, ¤t_auth
))
185 if (public->verify(public, scheme
, octets
, auth_data
))
187 DBG1(DBG_IKE
, "authentication of '%Y' with %N successful",
188 id
, auth_method_names
, auth_method
);
190 auth
->merge(auth
, current_auth
, FALSE
);
191 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
197 DBG1(DBG_IKE
, "signature validation failed, looking for another key");
200 enumerator
->destroy(enumerator
);
202 if (status
== NOT_FOUND
)
204 DBG1(DBG_IKE
, "no trusted %N public key found for '%Y'",
205 key_type_names
, key_type
, id
);
211 * Implementation of authenticator_t.process for builder
212 * Implementation of authenticator_t.build for verifier
214 static status_t
return_failed()
220 * Implementation of authenticator_t.destroy.
222 static void destroy(private_pubkey_authenticator_t
*this)
228 * Described in header.
230 pubkey_authenticator_t
*pubkey_authenticator_create_builder(ike_sa_t
*ike_sa
,
231 chunk_t received_nonce
, chunk_t sent_init
)
233 private_pubkey_authenticator_t
*this = malloc_thing(private_pubkey_authenticator_t
);
235 this->public.authenticator
.build
= (status_t(*)(authenticator_t
*, message_t
*message
))build
;
236 this->public.authenticator
.process
= (status_t(*)(authenticator_t
*, message_t
*message
))return_failed
;
237 this->public.authenticator
.destroy
= (void(*)(authenticator_t
*))destroy
;
239 this->ike_sa
= ike_sa
;
240 this->ike_sa_init
= sent_init
;
241 this->nonce
= received_nonce
;
243 return &this->public;
247 * Described in header.
249 pubkey_authenticator_t
*pubkey_authenticator_create_verifier(ike_sa_t
*ike_sa
,
250 chunk_t sent_nonce
, chunk_t received_init
)
252 private_pubkey_authenticator_t
*this = malloc_thing(private_pubkey_authenticator_t
);
254 this->public.authenticator
.build
= (status_t(*)(authenticator_t
*, message_t
*message
))return_failed
;
255 this->public.authenticator
.process
= (status_t(*)(authenticator_t
*, message_t
*message
))process
;
256 this->public.authenticator
.destroy
= (void(*)(authenticator_t
*))destroy
;
258 this->ike_sa
= ike_sa
;
259 this->ike_sa_init
= received_init
;
260 this->nonce
= sent_nonce
;
262 return &this->public;