2 * Copyright (C) 2008-2015 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>
22 #include <sa/ikev2/keymat_v2.h>
23 #include <asn1/asn1.h>
26 typedef struct private_pubkey_authenticator_t private_pubkey_authenticator_t
;
29 * Private data of an pubkey_authenticator_t object.
31 struct private_pubkey_authenticator_t
{
34 * Public authenticator_t interface.
36 pubkey_authenticator_t
public;
44 * nonce to include in AUTH calculation
49 * IKE_SA_INIT message data to include in AUTH calculation
54 * Reserved bytes of ID payload
60 * Parse authentication data used for Signature Authentication as per RFC 7427
62 static bool parse_signature_auth_data(chunk_t
*auth_data
, key_type_t
*key_type
,
63 signature_scheme_t
*scheme
)
72 len
= auth_data
->ptr
[0];
73 *auth_data
= chunk_skip(*auth_data
, 1);
74 /* we currently don't support schemes that require parameters */
75 oid
= asn1_parse_algorithmIdentifier(*auth_data
, 1, NULL
);
76 *scheme
= signature_scheme_from_oid(oid
);
77 if (*scheme
== SIGN_UNKNOWN
)
81 *key_type
= key_type_from_signature_scheme(*scheme
);
82 *auth_data
= chunk_skip(*auth_data
, len
);
87 * Build authentication data used for Signature Authentication as per RFC 7427
89 static bool build_signature_auth_data(chunk_t
*auth_data
,
90 signature_scheme_t scheme
)
96 oid
= signature_scheme_to_oid(scheme
);
97 if (oid
== OID_UNKNOWN
)
101 data
= asn1_algorithmIdentifier(oid
);
103 *auth_data
= chunk_cat("cmm", chunk_from_thing(len
), data
, *auth_data
);
108 * Select a signature scheme based on our configuration, the other peer's
109 * capabilities and the private key
111 static signature_scheme_t
select_signature_scheme(keymat_v2_t
*keymat
,
112 auth_cfg_t
*auth
, private_key_t
*private)
114 enumerator_t
*enumerator
;
115 signature_scheme_t scheme
= SIGN_UNKNOWN
;
116 hash_algorithm_t hash
;
121 bool have_config
= FALSE
;
124 key_type
= private->get_type(private);
125 enumerator
= auth
->create_enumerator(auth
);
126 while (enumerator
->enumerate(enumerator
, &rule
, &config
))
128 if (rule
!= AUTH_RULE_SIGNATURE_SCHEME
)
133 if (key_type
== key_type_from_signature_scheme(config
) &&
134 keymat
->hash_algorithm_supported(keymat
,
135 hasher_from_signature_scheme(config
)))
141 enumerator
->destroy(enumerator
);
143 if (scheme
== SIGN_UNKNOWN
&& !have_config
)
145 /* if no specific configuration, find a scheme supported by us, the
146 * other peer and the key */
147 enumerator
= lib
->crypto
->create_hasher_enumerator(lib
->crypto
);
148 while (enumerator
->enumerate(enumerator
, &hash
, &plugin_name
))
150 if (keymat
->hash_algorithm_supported(keymat
, hash
))
152 oid
= hasher_signature_algorithm_to_oid(hash
, key_type
);
153 if (oid
!= OID_UNKNOWN
)
155 scheme
= signature_scheme_from_oid(oid
);
160 enumerator
->destroy(enumerator
);
165 METHOD(authenticator_t
, build
, status_t
,
166 private_pubkey_authenticator_t
*this, message_t
*message
)
168 chunk_t octets
= chunk_empty
, auth_data
;
169 status_t status
= FAILED
;
170 private_key_t
*private;
171 identification_t
*id
;
173 auth_payload_t
*auth_payload
;
174 auth_method_t auth_method
;
175 signature_scheme_t scheme
= SIGN_UNKNOWN
;
178 id
= this->ike_sa
->get_my_id(this->ike_sa
);
179 auth
= this->ike_sa
->get_auth_cfg(this->ike_sa
, TRUE
);
180 private = lib
->credmgr
->get_private(lib
->credmgr
, KEY_ANY
, id
, auth
);
183 DBG1(DBG_IKE
, "no private key found for '%Y'", id
);
186 keymat
= (keymat_v2_t
*)this->ike_sa
->get_keymat(this->ike_sa
);
188 if (this->ike_sa
->supports_extension(this->ike_sa
, EXT_SIGNATURE_AUTH
))
190 scheme
= select_signature_scheme(keymat
, auth
, private);
191 auth_method
= AUTH_DS
;
192 if (scheme
== SIGN_UNKNOWN
)
194 DBG1(DBG_IKE
, "no common hash algorithm found to create signature "
195 "with %N key", key_type_names
, private->get_type(private));
201 switch (private->get_type(private))
204 scheme
= SIGN_RSA_EMSA_PKCS1_SHA1
;
205 auth_method
= AUTH_RSA
;
208 /* deduct the signature scheme from the keysize */
209 switch (private->get_keysize(private))
212 scheme
= SIGN_ECDSA_256
;
213 auth_method
= AUTH_ECDSA_256
;
216 scheme
= SIGN_ECDSA_384
;
217 auth_method
= AUTH_ECDSA_384
;
220 scheme
= SIGN_ECDSA_521
;
221 auth_method
= AUTH_ECDSA_521
;
224 DBG1(DBG_IKE
, "%d bit ECDSA private key size not "
225 "supported", private->get_keysize(private));
230 /* we currently use SHA512 only */
231 scheme
= SIGN_BLISS_WITH_SHA512
;
232 auth_method
= AUTH_BLISS
;
235 DBG1(DBG_IKE
, "private key of type %N not supported",
236 key_type_names
, private->get_type(private));
241 if (keymat
->get_auth_octets(keymat
, FALSE
, this->ike_sa_init
,
242 this->nonce
, id
, this->reserved
, &octets
) &&
243 private->sign(private, scheme
, octets
, &auth_data
))
245 if (auth_method
!= AUTH_DS
||
246 build_signature_auth_data(&auth_data
, scheme
))
248 auth_payload
= auth_payload_create();
249 auth_payload
->set_auth_method(auth_payload
, auth_method
);
250 auth_payload
->set_data(auth_payload
, auth_data
);
251 chunk_free(&auth_data
);
252 message
->add_payload(message
, (payload_t
*)auth_payload
);
256 DBG1(DBG_IKE
, "authentication of '%Y' (myself) with %N %s", id
,
257 auth_method_names
, auth_method
,
258 (status
== SUCCESS
)?
"successful":"failed");
260 private->destroy(private);
265 METHOD(authenticator_t
, process
, status_t
,
266 private_pubkey_authenticator_t
*this, message_t
*message
)
268 public_key_t
*public;
269 auth_method_t auth_method
;
270 auth_payload_t
*auth_payload
;
271 chunk_t auth_data
, octets
;
272 identification_t
*id
;
273 auth_cfg_t
*auth
, *current_auth
;
274 enumerator_t
*enumerator
;
275 key_type_t key_type
= KEY_ECDSA
;
276 signature_scheme_t scheme
;
277 status_t status
= NOT_FOUND
;
280 auth_payload
= (auth_payload_t
*)message
->get_payload(message
, PLV2_AUTH
);
285 auth_method
= auth_payload
->get_auth_method(auth_payload
);
286 auth_data
= auth_payload
->get_data(auth_payload
);
291 scheme
= SIGN_RSA_EMSA_PKCS1_SHA1
;
294 scheme
= SIGN_ECDSA_256
;
297 scheme
= SIGN_ECDSA_384
;
300 scheme
= SIGN_ECDSA_521
;
303 key_type
= KEY_BLISS
;
304 scheme
= SIGN_BLISS_WITH_SHA512
;
307 if (parse_signature_auth_data(&auth_data
, &key_type
, &scheme
))
315 id
= this->ike_sa
->get_other_id(this->ike_sa
);
316 keymat
= (keymat_v2_t
*)this->ike_sa
->get_keymat(this->ike_sa
);
317 if (!keymat
->get_auth_octets(keymat
, TRUE
, this->ike_sa_init
,
318 this->nonce
, id
, this->reserved
, &octets
))
322 auth
= this->ike_sa
->get_auth_cfg(this->ike_sa
, FALSE
);
323 enumerator
= lib
->credmgr
->create_public_enumerator(lib
->credmgr
,
325 while (enumerator
->enumerate(enumerator
, &public, ¤t_auth
))
327 if (public->verify(public, scheme
, octets
, auth_data
))
329 DBG1(DBG_IKE
, "authentication of '%Y' with %N successful",
330 id
, auth_method_names
, auth_method
);
332 auth
->merge(auth
, current_auth
, FALSE
);
333 auth
->add(auth
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
339 DBG1(DBG_IKE
, "signature validation failed, looking for another key");
342 enumerator
->destroy(enumerator
);
344 if (status
== NOT_FOUND
)
346 DBG1(DBG_IKE
, "no trusted %N public key found for '%Y'",
347 key_type_names
, key_type
, id
);
352 METHOD(authenticator_t
, destroy
, void,
353 private_pubkey_authenticator_t
*this)
359 * Described in header.
361 pubkey_authenticator_t
*pubkey_authenticator_create_builder(ike_sa_t
*ike_sa
,
362 chunk_t received_nonce
, chunk_t sent_init
,
365 private_pubkey_authenticator_t
*this;
371 .process
= (void*)return_failed
,
372 .is_mutual
= (void*)return_false
,
377 .ike_sa_init
= sent_init
,
378 .nonce
= received_nonce
,
380 memcpy(this->reserved
, reserved
, sizeof(this->reserved
));
382 return &this->public;
386 * Described in header.
388 pubkey_authenticator_t
*pubkey_authenticator_create_verifier(ike_sa_t
*ike_sa
,
389 chunk_t sent_nonce
, chunk_t received_init
,
392 private_pubkey_authenticator_t
*this;
397 .build
= (void*)return_failed
,
399 .is_mutual
= (void*)return_false
,
404 .ike_sa_init
= received_init
,
407 memcpy(this->reserved
, reserved
, sizeof(this->reserved
));
409 return &this->public;