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