ikev2: Select a signature scheme appropriate for the given key
[strongswan.git] / src / libcharon / sa / ikev2 / authenticators / pubkey_authenticator.c
1 /*
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
6 *
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>.
11 *
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
15 * for more details.
16 */
17
18 #include "pubkey_authenticator.h"
19
20 #include <daemon.h>
21 #include <encoding/payloads/auth_payload.h>
22 #include <sa/ikev2/keymat_v2.h>
23 #include <asn1/asn1.h>
24 #include <asn1/oid.h>
25
26 typedef struct private_pubkey_authenticator_t private_pubkey_authenticator_t;
27
28 /**
29 * Private data of an pubkey_authenticator_t object.
30 */
31 struct private_pubkey_authenticator_t {
32
33 /**
34 * Public authenticator_t interface.
35 */
36 pubkey_authenticator_t public;
37
38 /**
39 * Assigned IKE_SA
40 */
41 ike_sa_t *ike_sa;
42
43 /**
44 * nonce to include in AUTH calculation
45 */
46 chunk_t nonce;
47
48 /**
49 * IKE_SA_INIT message data to include in AUTH calculation
50 */
51 chunk_t ike_sa_init;
52
53 /**
54 * Reserved bytes of ID payload
55 */
56 char reserved[3];
57 };
58
59 /**
60 * Parse authentication data used for Signature Authentication as per RFC 7427
61 */
62 static bool parse_signature_auth_data(chunk_t *auth_data, key_type_t *key_type,
63 signature_scheme_t *scheme)
64 {
65 u_int8_t len;
66 int oid;
67
68 if (!auth_data->len)
69 {
70 return FALSE;
71 }
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)
78 {
79 return FALSE;
80 }
81 *key_type = key_type_from_signature_scheme(*scheme);
82 *auth_data = chunk_skip(*auth_data, len);
83 return TRUE;
84 }
85
86 /**
87 * Build authentication data used for Signature Authentication as per RFC 7427
88 */
89 static bool build_signature_auth_data(chunk_t *auth_data,
90 signature_scheme_t scheme)
91 {
92 chunk_t data;
93 u_int8_t len;
94 int oid;
95
96 oid = signature_scheme_to_oid(scheme);
97 if (oid == OID_UNKNOWN)
98 {
99 return FALSE;
100 }
101 data = asn1_algorithmIdentifier(oid);
102 len = data.len;
103 *auth_data = chunk_cat("cmm", chunk_from_thing(len), data, *auth_data);
104 return TRUE;
105 }
106
107 /**
108 * Select a signature scheme based on our configuration, the other peer's
109 * capabilities and the private key
110 */
111 static signature_scheme_t select_signature_scheme(keymat_v2_t *keymat,
112 auth_cfg_t *auth, private_key_t *private)
113 {
114 enumerator_t *enumerator;
115 signature_scheme_t selected = SIGN_UNKNOWN, scheme;
116 uintptr_t config;
117 auth_rule_t rule;
118 key_type_t key_type;
119 bool have_config = FALSE;
120
121 key_type = private->get_type(private);
122 enumerator = auth->create_enumerator(auth);
123 while (enumerator->enumerate(enumerator, &rule, &config))
124 {
125 if (rule != AUTH_RULE_SIGNATURE_SCHEME)
126 {
127 continue;
128 }
129 have_config = TRUE;
130 if (key_type == key_type_from_signature_scheme(config) &&
131 keymat->hash_algorithm_supported(keymat,
132 hasher_from_signature_scheme(config)))
133 {
134 selected = config;
135 break;
136 }
137 }
138 enumerator->destroy(enumerator);
139
140 if (selected == SIGN_UNKNOWN && !have_config)
141 {
142 /* if no specific configuration, find a scheme appropriate for the key
143 * and supported by the other peer */
144 enumerator = signature_schemes_for_key(key_type,
145 private->get_keysize(private));
146 while (enumerator->enumerate(enumerator, &scheme))
147 {
148 if (keymat->hash_algorithm_supported(keymat,
149 hasher_from_signature_scheme(scheme)))
150 {
151 selected = scheme;
152 break;
153 }
154 }
155 enumerator->destroy(enumerator);
156 }
157 return selected;
158 }
159
160 METHOD(authenticator_t, build, status_t,
161 private_pubkey_authenticator_t *this, message_t *message)
162 {
163 chunk_t octets = chunk_empty, auth_data;
164 status_t status = FAILED;
165 private_key_t *private;
166 identification_t *id;
167 auth_cfg_t *auth;
168 auth_payload_t *auth_payload;
169 auth_method_t auth_method;
170 signature_scheme_t scheme = SIGN_UNKNOWN;
171 keymat_v2_t *keymat;
172
173 id = this->ike_sa->get_my_id(this->ike_sa);
174 auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
175 private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, id, auth);
176 if (private == NULL)
177 {
178 DBG1(DBG_IKE, "no private key found for '%Y'", id);
179 return NOT_FOUND;
180 }
181 keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
182
183 if (this->ike_sa->supports_extension(this->ike_sa, EXT_SIGNATURE_AUTH))
184 {
185 scheme = select_signature_scheme(keymat, auth, private);
186 auth_method = AUTH_DS;
187 if (scheme == SIGN_UNKNOWN)
188 {
189 DBG1(DBG_IKE, "no common hash algorithm found to create signature "
190 "with %N key", key_type_names, private->get_type(private));
191 return status;
192 }
193 }
194 else
195 {
196 switch (private->get_type(private))
197 {
198 case KEY_RSA:
199 scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
200 auth_method = AUTH_RSA;
201 break;
202 case KEY_ECDSA:
203 /* deduct the signature scheme from the keysize */
204 switch (private->get_keysize(private))
205 {
206 case 256:
207 scheme = SIGN_ECDSA_256;
208 auth_method = AUTH_ECDSA_256;
209 break;
210 case 384:
211 scheme = SIGN_ECDSA_384;
212 auth_method = AUTH_ECDSA_384;
213 break;
214 case 521:
215 scheme = SIGN_ECDSA_521;
216 auth_method = AUTH_ECDSA_521;
217 break;
218 default:
219 DBG1(DBG_IKE, "%d bit ECDSA private key size not "
220 "supported", private->get_keysize(private));
221 return status;
222 }
223 break;
224 default:
225 DBG1(DBG_IKE, "private key of type %N not supported",
226 key_type_names, private->get_type(private));
227 return status;
228 }
229 }
230
231 if (keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init,
232 this->nonce, id, this->reserved, &octets) &&
233 private->sign(private, scheme, octets, &auth_data))
234 {
235 if (auth_method != AUTH_DS ||
236 build_signature_auth_data(&auth_data, scheme))
237 {
238 auth_payload = auth_payload_create();
239 auth_payload->set_auth_method(auth_payload, auth_method);
240 auth_payload->set_data(auth_payload, auth_data);
241 chunk_free(&auth_data);
242 message->add_payload(message, (payload_t*)auth_payload);
243 status = SUCCESS;
244 }
245 }
246 DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N %s", id,
247 auth_method == AUTH_DS ? signature_scheme_names : auth_method_names,
248 auth_method == AUTH_DS ? scheme : auth_method,
249 status == SUCCESS ? "successful" : "failed");
250 chunk_free(&octets);
251 private->destroy(private);
252
253 return status;
254 }
255
256 METHOD(authenticator_t, process, status_t,
257 private_pubkey_authenticator_t *this, message_t *message)
258 {
259 public_key_t *public;
260 auth_method_t auth_method;
261 auth_payload_t *auth_payload;
262 chunk_t auth_data, octets;
263 identification_t *id;
264 auth_cfg_t *auth, *current_auth;
265 enumerator_t *enumerator;
266 key_type_t key_type = KEY_ECDSA;
267 signature_scheme_t scheme;
268 status_t status = NOT_FOUND;
269 keymat_v2_t *keymat;
270
271 auth_payload = (auth_payload_t*)message->get_payload(message, PLV2_AUTH);
272 if (!auth_payload)
273 {
274 return FAILED;
275 }
276 auth_method = auth_payload->get_auth_method(auth_payload);
277 auth_data = auth_payload->get_data(auth_payload);
278 switch (auth_method)
279 {
280 case AUTH_RSA:
281 key_type = KEY_RSA;
282 scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
283 break;
284 case AUTH_ECDSA_256:
285 scheme = SIGN_ECDSA_256;
286 break;
287 case AUTH_ECDSA_384:
288 scheme = SIGN_ECDSA_384;
289 break;
290 case AUTH_ECDSA_521:
291 scheme = SIGN_ECDSA_521;
292 break;
293 case AUTH_DS:
294 if (parse_signature_auth_data(&auth_data, &key_type, &scheme))
295 {
296 break;
297 }
298 /* fall-through */
299 default:
300 return INVALID_ARG;
301 }
302 id = this->ike_sa->get_other_id(this->ike_sa);
303 keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
304 if (!keymat->get_auth_octets(keymat, TRUE, this->ike_sa_init,
305 this->nonce, id, this->reserved, &octets))
306 {
307 return FAILED;
308 }
309 auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
310 enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
311 key_type, id, auth);
312 while (enumerator->enumerate(enumerator, &public, &current_auth))
313 {
314 if (public->verify(public, scheme, octets, auth_data))
315 {
316 DBG1(DBG_IKE, "authentication of '%Y' with %N successful", id,
317 auth_method == AUTH_DS ? signature_scheme_names : auth_method_names,
318 auth_method == AUTH_DS ? scheme : auth_method);
319 status = SUCCESS;
320 auth->merge(auth, current_auth, FALSE);
321 auth->add(auth, AUTH_RULE_SIGNATURE_SCHEME, (uintptr_t)scheme);
322 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
323 break;
324 }
325 else
326 {
327 status = FAILED;
328 DBG1(DBG_IKE, "signature validation failed, looking for another key");
329 }
330 }
331 enumerator->destroy(enumerator);
332 chunk_free(&octets);
333 if (status == NOT_FOUND)
334 {
335 DBG1(DBG_IKE, "no trusted %N public key found for '%Y'",
336 key_type_names, key_type, id);
337 }
338 return status;
339 }
340
341 METHOD(authenticator_t, destroy, void,
342 private_pubkey_authenticator_t *this)
343 {
344 free(this);
345 }
346
347 /*
348 * Described in header.
349 */
350 pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa,
351 chunk_t received_nonce, chunk_t sent_init,
352 char reserved[3])
353 {
354 private_pubkey_authenticator_t *this;
355
356 INIT(this,
357 .public = {
358 .authenticator = {
359 .build = _build,
360 .process = (void*)return_failed,
361 .is_mutual = (void*)return_false,
362 .destroy = _destroy,
363 },
364 },
365 .ike_sa = ike_sa,
366 .ike_sa_init = sent_init,
367 .nonce = received_nonce,
368 );
369 memcpy(this->reserved, reserved, sizeof(this->reserved));
370
371 return &this->public;
372 }
373
374 /*
375 * Described in header.
376 */
377 pubkey_authenticator_t *pubkey_authenticator_create_verifier(ike_sa_t *ike_sa,
378 chunk_t sent_nonce, chunk_t received_init,
379 char reserved[3])
380 {
381 private_pubkey_authenticator_t *this;
382
383 INIT(this,
384 .public = {
385 .authenticator = {
386 .build = (void*)return_failed,
387 .process = _process,
388 .is_mutual = (void*)return_false,
389 .destroy = _destroy,
390 },
391 },
392 .ike_sa = ike_sa,
393 .ike_sa_init = received_init,
394 .nonce = sent_nonce,
395 );
396 memcpy(this->reserved, reserved, sizeof(this->reserved));
397
398 return &this->public;
399 }