ikev2: Handle RFC 7427 signature authentication in pubkey authenticator
[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 scheme = SIGN_UNKNOWN;
116 hash_algorithm_t hash;
117 char *plugin_name;
118 uintptr_t config;
119 auth_rule_t rule;
120 key_type_t key_type;
121 bool have_config = FALSE;
122 int oid;
123
124 key_type = private->get_type(private);
125 enumerator = auth->create_enumerator(auth);
126 while (enumerator->enumerate(enumerator, &rule, &config))
127 {
128 if (rule != AUTH_RULE_SIGNATURE_SCHEME)
129 {
130 continue;
131 }
132 have_config = TRUE;
133 if (key_type == key_type_from_signature_scheme(config) &&
134 keymat->hash_algorithm_supported(keymat,
135 hasher_from_signature_scheme(config)))
136 {
137 scheme = config;
138 break;
139 }
140 }
141 enumerator->destroy(enumerator);
142
143 if (scheme == SIGN_UNKNOWN && !have_config)
144 {
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))
149 {
150 if (keymat->hash_algorithm_supported(keymat, hash))
151 {
152 oid = hasher_signature_algorithm_to_oid(hash, key_type);
153 if (oid != OID_UNKNOWN)
154 {
155 scheme = signature_scheme_from_oid(oid);
156 break;
157 }
158 }
159 }
160 enumerator->destroy(enumerator);
161 }
162 return scheme;
163 }
164
165 METHOD(authenticator_t, build, status_t,
166 private_pubkey_authenticator_t *this, message_t *message)
167 {
168 chunk_t octets = chunk_empty, auth_data;
169 status_t status = FAILED;
170 private_key_t *private;
171 identification_t *id;
172 auth_cfg_t *auth;
173 auth_payload_t *auth_payload;
174 auth_method_t auth_method;
175 signature_scheme_t scheme = SIGN_UNKNOWN;
176 keymat_v2_t *keymat;
177
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);
181 if (private == NULL)
182 {
183 DBG1(DBG_IKE, "no private key found for '%Y'", id);
184 return NOT_FOUND;
185 }
186 keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
187
188 if (this->ike_sa->supports_extension(this->ike_sa, EXT_SIGNATURE_AUTH))
189 {
190 scheme = select_signature_scheme(keymat, auth, private);
191 auth_method = AUTH_DS;
192 if (scheme == SIGN_UNKNOWN)
193 {
194 DBG1(DBG_IKE, "no common hash algorithm found to create signature "
195 "with %N key", key_type_names, private->get_type(private));
196 return status;
197 }
198 }
199 else
200 {
201 switch (private->get_type(private))
202 {
203 case KEY_RSA:
204 scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
205 auth_method = AUTH_RSA;
206 break;
207 case KEY_ECDSA:
208 /* deduct the signature scheme from the keysize */
209 switch (private->get_keysize(private))
210 {
211 case 256:
212 scheme = SIGN_ECDSA_256;
213 auth_method = AUTH_ECDSA_256;
214 break;
215 case 384:
216 scheme = SIGN_ECDSA_384;
217 auth_method = AUTH_ECDSA_384;
218 break;
219 case 521:
220 scheme = SIGN_ECDSA_521;
221 auth_method = AUTH_ECDSA_521;
222 break;
223 default:
224 DBG1(DBG_IKE, "%d bit ECDSA private key size not "
225 "supported", private->get_keysize(private));
226 return status;
227 }
228 break;
229 case KEY_BLISS:
230 /* we currently use SHA512 only */
231 scheme = SIGN_BLISS_WITH_SHA512;
232 auth_method = AUTH_BLISS;
233 break;
234 default:
235 DBG1(DBG_IKE, "private key of type %N not supported",
236 key_type_names, private->get_type(private));
237 return status;
238 }
239 }
240
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))
244 {
245 if (auth_method != AUTH_DS ||
246 build_signature_auth_data(&auth_data, scheme))
247 {
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);
253 status = SUCCESS;
254 }
255 }
256 DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N %s", id,
257 auth_method_names, auth_method,
258 (status == SUCCESS)? "successful":"failed");
259 chunk_free(&octets);
260 private->destroy(private);
261
262 return status;
263 }
264
265 METHOD(authenticator_t, process, status_t,
266 private_pubkey_authenticator_t *this, message_t *message)
267 {
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;
278 keymat_v2_t *keymat;
279
280 auth_payload = (auth_payload_t*)message->get_payload(message, PLV2_AUTH);
281 if (!auth_payload)
282 {
283 return FAILED;
284 }
285 auth_method = auth_payload->get_auth_method(auth_payload);
286 auth_data = auth_payload->get_data(auth_payload);
287 switch (auth_method)
288 {
289 case AUTH_RSA:
290 key_type = KEY_RSA;
291 scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
292 break;
293 case AUTH_ECDSA_256:
294 scheme = SIGN_ECDSA_256;
295 break;
296 case AUTH_ECDSA_384:
297 scheme = SIGN_ECDSA_384;
298 break;
299 case AUTH_ECDSA_521:
300 scheme = SIGN_ECDSA_521;
301 break;
302 case AUTH_BLISS:
303 key_type = KEY_BLISS;
304 scheme = SIGN_BLISS_WITH_SHA512;
305 break;
306 case AUTH_DS:
307 if (parse_signature_auth_data(&auth_data, &key_type, &scheme))
308 {
309 break;
310 }
311 /* fall-through */
312 default:
313 return INVALID_ARG;
314 }
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))
319 {
320 return FAILED;
321 }
322 auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
323 enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
324 key_type, id, auth);
325 while (enumerator->enumerate(enumerator, &public, &current_auth))
326 {
327 if (public->verify(public, scheme, octets, auth_data))
328 {
329 DBG1(DBG_IKE, "authentication of '%Y' with %N successful",
330 id, auth_method_names, auth_method);
331 status = SUCCESS;
332 auth->merge(auth, current_auth, FALSE);
333 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
334 break;
335 }
336 else
337 {
338 status = FAILED;
339 DBG1(DBG_IKE, "signature validation failed, looking for another key");
340 }
341 }
342 enumerator->destroy(enumerator);
343 chunk_free(&octets);
344 if (status == NOT_FOUND)
345 {
346 DBG1(DBG_IKE, "no trusted %N public key found for '%Y'",
347 key_type_names, key_type, id);
348 }
349 return status;
350 }
351
352 METHOD(authenticator_t, destroy, void,
353 private_pubkey_authenticator_t *this)
354 {
355 free(this);
356 }
357
358 /*
359 * Described in header.
360 */
361 pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa,
362 chunk_t received_nonce, chunk_t sent_init,
363 char reserved[3])
364 {
365 private_pubkey_authenticator_t *this;
366
367 INIT(this,
368 .public = {
369 .authenticator = {
370 .build = _build,
371 .process = (void*)return_failed,
372 .is_mutual = (void*)return_false,
373 .destroy = _destroy,
374 },
375 },
376 .ike_sa = ike_sa,
377 .ike_sa_init = sent_init,
378 .nonce = received_nonce,
379 );
380 memcpy(this->reserved, reserved, sizeof(this->reserved));
381
382 return &this->public;
383 }
384
385 /*
386 * Described in header.
387 */
388 pubkey_authenticator_t *pubkey_authenticator_create_verifier(ike_sa_t *ike_sa,
389 chunk_t sent_nonce, chunk_t received_init,
390 char reserved[3])
391 {
392 private_pubkey_authenticator_t *this;
393
394 INIT(this,
395 .public = {
396 .authenticator = {
397 .build = (void*)return_failed,
398 .process = _process,
399 .is_mutual = (void*)return_false,
400 .destroy = _destroy,
401 },
402 },
403 .ike_sa = ike_sa,
404 .ike_sa_init = received_init,
405 .nonce = sent_nonce,
406 );
407 memcpy(this->reserved, reserved, sizeof(this->reserved));
408
409 return &this->public;
410 }