1 |
|
|
/* $OpenBSD: ike_auth.c,v 1.113 2015/04/21 01:44:47 jsg Exp $ */ |
2 |
|
|
/* $EOM: ike_auth.c,v 1.59 2000/11/21 00:21:31 angelos Exp $ */ |
3 |
|
|
|
4 |
|
|
/* |
5 |
|
|
* Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. |
6 |
|
|
* Copyright (c) 1999 Niels Provos. All rights reserved. |
7 |
|
|
* Copyright (c) 1999 Angelos D. Keromytis. All rights reserved. |
8 |
|
|
* Copyright (c) 2000, 2001, 2003 Håkan Olsson. All rights reserved. |
9 |
|
|
* |
10 |
|
|
* Redistribution and use in source and binary forms, with or without |
11 |
|
|
* modification, are permitted provided that the following conditions |
12 |
|
|
* are met: |
13 |
|
|
* 1. Redistributions of source code must retain the above copyright |
14 |
|
|
* notice, this list of conditions and the following disclaimer. |
15 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
16 |
|
|
* notice, this list of conditions and the following disclaimer in the |
17 |
|
|
* documentation and/or other materials provided with the distribution. |
18 |
|
|
* |
19 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
20 |
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
21 |
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
22 |
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
23 |
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
24 |
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 |
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 |
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 |
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
28 |
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 |
|
|
*/ |
30 |
|
|
|
31 |
|
|
/* |
32 |
|
|
* This code was written under funding by Ericsson Radio Systems. |
33 |
|
|
*/ |
34 |
|
|
|
35 |
|
|
#include <sys/types.h> |
36 |
|
|
#include <sys/stat.h> |
37 |
|
|
#include <netinet/in.h> |
38 |
|
|
#include <arpa/inet.h> |
39 |
|
|
|
40 |
|
|
#include <errno.h> |
41 |
|
|
#include <fcntl.h> |
42 |
|
|
#include <stdlib.h> |
43 |
|
|
#include <string.h> |
44 |
|
|
#include <unistd.h> |
45 |
|
|
#include <regex.h> |
46 |
|
|
#include <keynote.h> |
47 |
|
|
#include <policy.h> |
48 |
|
|
|
49 |
|
|
#include "cert.h" |
50 |
|
|
#include "conf.h" |
51 |
|
|
#include "constants.h" |
52 |
|
|
#if defined (USE_DNSSEC) |
53 |
|
|
#include "dnssec.h" |
54 |
|
|
#endif |
55 |
|
|
#include "exchange.h" |
56 |
|
|
#include "hash.h" |
57 |
|
|
#include "ike_auth.h" |
58 |
|
|
#include "ipsec.h" |
59 |
|
|
#include "ipsec_doi.h" |
60 |
|
|
#include "libcrypto.h" |
61 |
|
|
#include "log.h" |
62 |
|
|
#include "message.h" |
63 |
|
|
#include "monitor.h" |
64 |
|
|
#include "prf.h" |
65 |
|
|
#include "transport.h" |
66 |
|
|
#include "util.h" |
67 |
|
|
#include "key.h" |
68 |
|
|
#include "x509.h" |
69 |
|
|
|
70 |
|
|
#ifdef notyet |
71 |
|
|
static u_int8_t *enc_gen_skeyid(struct exchange *, size_t *); |
72 |
|
|
#endif |
73 |
|
|
static u_int8_t *pre_shared_gen_skeyid(struct exchange *, size_t *); |
74 |
|
|
|
75 |
|
|
static int pre_shared_decode_hash(struct message *); |
76 |
|
|
static int pre_shared_encode_hash(struct message *); |
77 |
|
|
|
78 |
|
|
static u_int8_t *sig_gen_skeyid(struct exchange *, size_t *); |
79 |
|
|
static int rsa_sig_decode_hash(struct message *); |
80 |
|
|
static int rsa_sig_encode_hash(struct message *); |
81 |
|
|
|
82 |
|
|
static int get_raw_key_from_file(int, u_int8_t *, size_t, RSA **); |
83 |
|
|
|
84 |
|
|
static int ike_auth_hash(struct exchange *, u_int8_t *); |
85 |
|
|
|
86 |
|
|
static struct ike_auth ike_auth[] = { |
87 |
|
|
{ |
88 |
|
|
IKE_AUTH_PRE_SHARED, pre_shared_gen_skeyid, |
89 |
|
|
pre_shared_decode_hash, |
90 |
|
|
pre_shared_encode_hash |
91 |
|
|
}, |
92 |
|
|
#ifdef notdef |
93 |
|
|
{ |
94 |
|
|
IKE_AUTH_DSS, sig_gen_skeyid, |
95 |
|
|
pre_shared_decode_hash, |
96 |
|
|
pre_shared_encode_hash |
97 |
|
|
}, |
98 |
|
|
#endif |
99 |
|
|
{ |
100 |
|
|
IKE_AUTH_RSA_SIG, sig_gen_skeyid, |
101 |
|
|
rsa_sig_decode_hash, |
102 |
|
|
rsa_sig_encode_hash |
103 |
|
|
}, |
104 |
|
|
#ifdef notdef |
105 |
|
|
{ |
106 |
|
|
IKE_AUTH_RSA_ENC, enc_gen_skeyid, |
107 |
|
|
pre_shared_decode_hash, |
108 |
|
|
pre_shared_encode_hash |
109 |
|
|
}, |
110 |
|
|
{ |
111 |
|
|
IKE_AUTH_RSA_ENC_REV, enc_gen_skeyid, |
112 |
|
|
pre_shared_decode_hash, |
113 |
|
|
pre_shared_encode_hash |
114 |
|
|
}, |
115 |
|
|
#endif |
116 |
|
|
}; |
117 |
|
|
|
118 |
|
|
struct ike_auth * |
119 |
|
|
ike_auth_get(u_int16_t id) |
120 |
|
|
{ |
121 |
|
|
size_t i; |
122 |
|
|
|
123 |
|
|
for (i = 0; i < sizeof ike_auth / sizeof ike_auth[0]; i++) |
124 |
|
|
if (id == ike_auth[i].id) |
125 |
|
|
return &ike_auth[i]; |
126 |
|
|
return 0; |
127 |
|
|
} |
128 |
|
|
|
129 |
|
|
/* |
130 |
|
|
* Find and decode the configured key (pre-shared or public) for the |
131 |
|
|
* peer denoted by ID. Stash the len in KEYLEN. |
132 |
|
|
*/ |
133 |
|
|
static void * |
134 |
|
|
ike_auth_get_key(int type, char *id, char *local_id, size_t *keylen) |
135 |
|
|
{ |
136 |
|
|
char *key, *buf; |
137 |
|
|
char *keyfile, *privkeyfile; |
138 |
|
|
FILE *keyfp; |
139 |
|
|
RSA *rsakey; |
140 |
|
|
size_t fsize, pkflen; |
141 |
|
|
int fd; |
142 |
|
|
|
143 |
|
|
switch (type) { |
144 |
|
|
case IKE_AUTH_PRE_SHARED: |
145 |
|
|
/* Get the pre-shared key for our peer. */ |
146 |
|
|
key = conf_get_str(id, "Authentication"); |
147 |
|
|
if (!key && local_id) |
148 |
|
|
key = conf_get_str(local_id, "Authentication"); |
149 |
|
|
|
150 |
|
|
if (!key) { |
151 |
|
|
log_print("ike_auth_get_key: " |
152 |
|
|
"no key found for peer \"%s\" or local ID \"%s\"", |
153 |
|
|
id, local_id ? local_id : "<none>"); |
154 |
|
|
return 0; |
155 |
|
|
} |
156 |
|
|
/* If the key starts with 0x it is in hex format. */ |
157 |
|
|
if (strncasecmp(key, "0x", 2) == 0) { |
158 |
|
|
*keylen = (strlen(key) - 1) / 2; |
159 |
|
|
buf = malloc(*keylen); |
160 |
|
|
if (!buf) { |
161 |
|
|
log_error("ike_auth_get_key: malloc (%lu) " |
162 |
|
|
"failed", (unsigned long)*keylen); |
163 |
|
|
return 0; |
164 |
|
|
} |
165 |
|
|
if (hex2raw(key + 2, (unsigned char *)buf, *keylen)) { |
166 |
|
|
free(buf); |
167 |
|
|
log_print("ike_auth_get_key: invalid hex key " |
168 |
|
|
"%s", key); |
169 |
|
|
return 0; |
170 |
|
|
} |
171 |
|
|
key = buf; |
172 |
|
|
} else { |
173 |
|
|
buf = key; |
174 |
|
|
key = strdup(buf); |
175 |
|
|
if (!key) { |
176 |
|
|
log_error("ike_auth_get_key: strdup() failed"); |
177 |
|
|
return 0; |
178 |
|
|
} |
179 |
|
|
*keylen = strlen(key); |
180 |
|
|
} |
181 |
|
|
break; |
182 |
|
|
|
183 |
|
|
case IKE_AUTH_RSA_SIG: |
184 |
|
|
if (local_id && (keyfile = conf_get_str("KeyNote", |
185 |
|
|
"Credential-directory")) != 0) { |
186 |
|
|
struct stat sb; |
187 |
|
|
struct keynote_deckey dc; |
188 |
|
|
char *privkeyfile, *buf2; |
189 |
|
|
size_t size; |
190 |
|
|
|
191 |
|
|
if (asprintf(&privkeyfile, "%s/%s/%s", keyfile, |
192 |
|
|
local_id, PRIVATE_KEY_FILE) == -1) { |
193 |
|
|
log_print("ike_auth_get_key: failed to asprintf()"); |
194 |
|
|
return 0; |
195 |
|
|
} |
196 |
|
|
keyfile = privkeyfile; |
197 |
|
|
|
198 |
|
|
fd = monitor_open(keyfile, O_RDONLY, 0); |
199 |
|
|
if (fd < 0) { |
200 |
|
|
free(keyfile); |
201 |
|
|
goto ignorekeynote; |
202 |
|
|
} |
203 |
|
|
|
204 |
|
|
if (fstat(fd, &sb) < 0) { |
205 |
|
|
log_print("ike_auth_get_key: fstat failed"); |
206 |
|
|
free(keyfile); |
207 |
|
|
close(fd); |
208 |
|
|
return 0; |
209 |
|
|
} |
210 |
|
|
size = (size_t)sb.st_size; |
211 |
|
|
|
212 |
|
|
buf = calloc(size + 1, sizeof(char)); |
213 |
|
|
if (!buf) { |
214 |
|
|
log_print("ike_auth_get_key: failed allocating" |
215 |
|
|
" %lu bytes", (unsigned long)size + 1); |
216 |
|
|
free(keyfile); |
217 |
|
|
close(fd); |
218 |
|
|
return 0; |
219 |
|
|
} |
220 |
|
|
if (read(fd, buf, size) != (ssize_t)size) { |
221 |
|
|
free(buf); |
222 |
|
|
log_print("ike_auth_get_key: " |
223 |
|
|
"failed reading %lu bytes from \"%s\"", |
224 |
|
|
(unsigned long)size, keyfile); |
225 |
|
|
free(keyfile); |
226 |
|
|
close(fd); |
227 |
|
|
return 0; |
228 |
|
|
} |
229 |
|
|
close(fd); |
230 |
|
|
|
231 |
|
|
/* Parse private key string */ |
232 |
|
|
buf2 = kn_get_string(buf); |
233 |
|
|
free(buf); |
234 |
|
|
|
235 |
|
|
if (!buf2 || kn_decode_key(&dc, buf2, |
236 |
|
|
KEYNOTE_PRIVATE_KEY) == -1) { |
237 |
|
|
free(buf2); |
238 |
|
|
log_print("ike_auth_get_key: failed decoding " |
239 |
|
|
"key in \"%s\"", keyfile); |
240 |
|
|
free(keyfile); |
241 |
|
|
return 0; |
242 |
|
|
} |
243 |
|
|
free(buf2); |
244 |
|
|
|
245 |
|
|
if (dc.dec_algorithm != KEYNOTE_ALGORITHM_RSA) { |
246 |
|
|
log_print("ike_auth_get_key: wrong algorithm " |
247 |
|
|
"type %d in \"%s\"", dc.dec_algorithm, |
248 |
|
|
keyfile); |
249 |
|
|
free(keyfile); |
250 |
|
|
kn_free_key(&dc); |
251 |
|
|
return 0; |
252 |
|
|
} |
253 |
|
|
free(keyfile); |
254 |
|
|
return dc.dec_key; |
255 |
|
|
} |
256 |
|
|
ignorekeynote: |
257 |
|
|
/* Otherwise, try X.509 */ |
258 |
|
|
|
259 |
|
|
privkeyfile = keyfile = NULL; |
260 |
|
|
fd = -1; |
261 |
|
|
|
262 |
|
|
if (local_id) { |
263 |
|
|
/* Look in Private-key-directory. */ |
264 |
|
|
keyfile = conf_get_str("X509-certificates", |
265 |
|
|
"Private-key-directory"); |
266 |
|
|
pkflen = strlen(keyfile) + strlen(local_id) + sizeof "/"; |
267 |
|
|
privkeyfile = calloc(pkflen, sizeof(char)); |
268 |
|
|
if (!privkeyfile) { |
269 |
|
|
log_print("ike_auth_get_key: failed to " |
270 |
|
|
"allocate %lu bytes", (unsigned long)pkflen); |
271 |
|
|
return 0; |
272 |
|
|
} |
273 |
|
|
|
274 |
|
|
snprintf(privkeyfile, pkflen, "%s/%s", keyfile, |
275 |
|
|
local_id); |
276 |
|
|
keyfile = privkeyfile; |
277 |
|
|
|
278 |
|
|
fd = monitor_open(keyfile, O_RDONLY, 0); |
279 |
|
|
if (fd < 0 && errno != ENOENT) { |
280 |
|
|
log_print("ike_auth_get_key: failed opening " |
281 |
|
|
"\"%s\"", keyfile); |
282 |
|
|
free(privkeyfile); |
283 |
|
|
privkeyfile = NULL; |
284 |
|
|
keyfile = NULL; |
285 |
|
|
} |
286 |
|
|
} |
287 |
|
|
|
288 |
|
|
if (fd < 0) { |
289 |
|
|
/* No key found, try default key. */ |
290 |
|
|
keyfile = conf_get_str("X509-certificates", |
291 |
|
|
"Private-key"); |
292 |
|
|
|
293 |
|
|
fd = monitor_open(keyfile, O_RDONLY, 0); |
294 |
|
|
if (fd < 0) { |
295 |
|
|
log_print("ike_auth_get_key: failed opening " |
296 |
|
|
"\"%s\"", keyfile); |
297 |
|
|
return 0; |
298 |
|
|
} |
299 |
|
|
} |
300 |
|
|
|
301 |
|
|
if (check_file_secrecy_fd(fd, keyfile, &fsize)) { |
302 |
|
|
free(privkeyfile); |
303 |
|
|
close(fd); |
304 |
|
|
return 0; |
305 |
|
|
} |
306 |
|
|
|
307 |
|
|
if ((keyfp = fdopen(fd, "r")) == NULL) { |
308 |
|
|
log_print("ike_auth_get_key: fdopen failed"); |
309 |
|
|
free(privkeyfile); |
310 |
|
|
close(fd); |
311 |
|
|
return 0; |
312 |
|
|
} |
313 |
|
|
#if SSLEAY_VERSION_NUMBER >= 0x00904100L |
314 |
|
|
rsakey = PEM_read_RSAPrivateKey(keyfp, NULL, NULL, NULL); |
315 |
|
|
#else |
316 |
|
|
rsakey = PEM_read_RSAPrivateKey(keyfp, NULL, NULL); |
317 |
|
|
#endif |
318 |
|
|
fclose(keyfp); |
319 |
|
|
|
320 |
|
|
free(privkeyfile); |
321 |
|
|
|
322 |
|
|
if (!rsakey) { |
323 |
|
|
log_print("ike_auth_get_key: " |
324 |
|
|
"PEM_read_bio_RSAPrivateKey failed"); |
325 |
|
|
return 0; |
326 |
|
|
} |
327 |
|
|
return rsakey; |
328 |
|
|
|
329 |
|
|
default: |
330 |
|
|
log_print("ike_auth_get_key: unknown key type %d", type); |
331 |
|
|
return 0; |
332 |
|
|
} |
333 |
|
|
|
334 |
|
|
return key; |
335 |
|
|
} |
336 |
|
|
|
337 |
|
|
static u_int8_t * |
338 |
|
|
pre_shared_gen_skeyid(struct exchange *exchange, size_t *sz) |
339 |
|
|
{ |
340 |
|
|
struct prf *prf; |
341 |
|
|
struct ipsec_exch *ie = exchange->data; |
342 |
|
|
u_int8_t *skeyid, *buf = 0; |
343 |
|
|
unsigned char *key; |
344 |
|
|
size_t keylen; |
345 |
|
|
|
346 |
|
|
/* |
347 |
|
|
* If we're the responder and have the initiator's ID (which is the |
348 |
|
|
* case in Aggressive mode), try to find the preshared key in the |
349 |
|
|
* section of the initiator's Phase 1 ID. This allows us to do |
350 |
|
|
* mobile user support with preshared keys. |
351 |
|
|
*/ |
352 |
|
|
if (!exchange->initiator && exchange->id_i) { |
353 |
|
|
switch (exchange->id_i[0]) { |
354 |
|
|
case IPSEC_ID_IPV4_ADDR: |
355 |
|
|
case IPSEC_ID_IPV6_ADDR: |
356 |
|
|
util_ntoa((char **) &buf, |
357 |
|
|
exchange->id_i[0] == IPSEC_ID_IPV4_ADDR ? AF_INET : |
358 |
|
|
AF_INET6, exchange->id_i + ISAKMP_ID_DATA_OFF - |
359 |
|
|
ISAKMP_GEN_SZ); |
360 |
|
|
if (!buf) |
361 |
|
|
return 0; |
362 |
|
|
break; |
363 |
|
|
|
364 |
|
|
case IPSEC_ID_FQDN: |
365 |
|
|
case IPSEC_ID_USER_FQDN: |
366 |
|
|
buf = calloc(exchange->id_i_len - ISAKMP_ID_DATA_OFF + |
367 |
|
|
ISAKMP_GEN_SZ + 1, sizeof(char)); |
368 |
|
|
if (!buf) { |
369 |
|
|
log_print("pre_shared_gen_skeyid: malloc (%lu" |
370 |
|
|
") failed", |
371 |
|
|
(unsigned long)exchange->id_i_len - |
372 |
|
|
ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1); |
373 |
|
|
return 0; |
374 |
|
|
} |
375 |
|
|
memcpy(buf, |
376 |
|
|
exchange->id_i + ISAKMP_ID_DATA_OFF - |
377 |
|
|
ISAKMP_GEN_SZ, |
378 |
|
|
exchange->id_i_len - ISAKMP_ID_DATA_OFF + |
379 |
|
|
ISAKMP_GEN_SZ); |
380 |
|
|
break; |
381 |
|
|
|
382 |
|
|
/* XXX Support more ID types ? */ |
383 |
|
|
default: |
384 |
|
|
break; |
385 |
|
|
} |
386 |
|
|
} |
387 |
|
|
/* |
388 |
|
|
* Get the pre-shared key for our peer. This will work even if the key |
389 |
|
|
* has been passed to us through a mechanism like PFKEYv2. |
390 |
|
|
*/ |
391 |
|
|
key = ike_auth_get_key(IKE_AUTH_PRE_SHARED, exchange->name, |
392 |
|
|
(char *)buf, &keylen); |
393 |
|
|
free(buf); |
394 |
|
|
|
395 |
|
|
/* Fail if no key could be found. */ |
396 |
|
|
if (!key) |
397 |
|
|
return 0; |
398 |
|
|
|
399 |
|
|
/* Store the secret key for later policy processing. */ |
400 |
|
|
exchange->recv_key = calloc(keylen + 1, sizeof(char)); |
401 |
|
|
exchange->recv_keytype = ISAKMP_KEY_PASSPHRASE; |
402 |
|
|
if (!exchange->recv_key) { |
403 |
|
|
log_error("pre_shared_gen_skeyid: malloc (%lu) failed", |
404 |
|
|
(unsigned long)keylen); |
405 |
|
|
free(key); |
406 |
|
|
return 0; |
407 |
|
|
} |
408 |
|
|
memcpy(exchange->recv_key, key, keylen); |
409 |
|
|
exchange->recv_certtype = ISAKMP_CERTENC_NONE; |
410 |
|
|
free(key); |
411 |
|
|
|
412 |
|
|
prf = prf_alloc(ie->prf_type, ie->hash->type, exchange->recv_key, |
413 |
|
|
keylen); |
414 |
|
|
if (!prf) |
415 |
|
|
return 0; |
416 |
|
|
|
417 |
|
|
*sz = prf->blocksize; |
418 |
|
|
skeyid = malloc(*sz); |
419 |
|
|
if (!skeyid) { |
420 |
|
|
log_error("pre_shared_gen_skeyid: malloc (%lu) failed", |
421 |
|
|
(unsigned long)*sz); |
422 |
|
|
prf_free(prf); |
423 |
|
|
return 0; |
424 |
|
|
} |
425 |
|
|
prf->Init(prf->prfctx); |
426 |
|
|
prf->Update(prf->prfctx, exchange->nonce_i, exchange->nonce_i_len); |
427 |
|
|
prf->Update(prf->prfctx, exchange->nonce_r, exchange->nonce_r_len); |
428 |
|
|
prf->Final(skeyid, prf->prfctx); |
429 |
|
|
prf_free(prf); |
430 |
|
|
return skeyid; |
431 |
|
|
} |
432 |
|
|
|
433 |
|
|
/* Both DSS & RSA signature authentication use this algorithm. */ |
434 |
|
|
static u_int8_t * |
435 |
|
|
sig_gen_skeyid(struct exchange *exchange, size_t *sz) |
436 |
|
|
{ |
437 |
|
|
struct prf *prf; |
438 |
|
|
struct ipsec_exch *ie = exchange->data; |
439 |
|
|
u_int8_t *skeyid; |
440 |
|
|
unsigned char *key; |
441 |
|
|
|
442 |
|
|
key = malloc(exchange->nonce_i_len + exchange->nonce_r_len); |
443 |
|
|
if (!key) |
444 |
|
|
return 0; |
445 |
|
|
memcpy(key, exchange->nonce_i, exchange->nonce_i_len); |
446 |
|
|
memcpy(key + exchange->nonce_i_len, exchange->nonce_r, |
447 |
|
|
exchange->nonce_r_len); |
448 |
|
|
|
449 |
|
|
LOG_DBG((LOG_NEGOTIATION, 80, "sig_gen_skeyid: PRF type %d, hash %d", |
450 |
|
|
ie->prf_type, ie->hash->type)); |
451 |
|
|
LOG_DBG_BUF((LOG_NEGOTIATION, 80, |
452 |
|
|
"sig_gen_skeyid: SKEYID initialized with", |
453 |
|
|
(u_int8_t *)key, exchange->nonce_i_len + exchange->nonce_r_len)); |
454 |
|
|
|
455 |
|
|
prf = prf_alloc(ie->prf_type, ie->hash->type, key, |
456 |
|
|
exchange->nonce_i_len + exchange->nonce_r_len); |
457 |
|
|
free(key); |
458 |
|
|
if (!prf) |
459 |
|
|
return 0; |
460 |
|
|
|
461 |
|
|
*sz = prf->blocksize; |
462 |
|
|
skeyid = malloc(*sz); |
463 |
|
|
if (!skeyid) { |
464 |
|
|
log_error("sig_gen_skeyid: malloc (%lu) failed", |
465 |
|
|
(unsigned long)*sz); |
466 |
|
|
prf_free(prf); |
467 |
|
|
return 0; |
468 |
|
|
} |
469 |
|
|
LOG_DBG((LOG_NEGOTIATION, 80, "sig_gen_skeyid: g^xy length %lu", |
470 |
|
|
(unsigned long)ie->g_x_len)); |
471 |
|
|
LOG_DBG_BUF((LOG_NEGOTIATION, 80, |
472 |
|
|
"sig_gen_skeyid: SKEYID fed with g^xy", ie->g_xy, ie->g_x_len)); |
473 |
|
|
|
474 |
|
|
prf->Init(prf->prfctx); |
475 |
|
|
prf->Update(prf->prfctx, ie->g_xy, ie->g_x_len); |
476 |
|
|
prf->Final(skeyid, prf->prfctx); |
477 |
|
|
prf_free(prf); |
478 |
|
|
return skeyid; |
479 |
|
|
} |
480 |
|
|
|
481 |
|
|
#ifdef notdef |
482 |
|
|
/* |
483 |
|
|
* Both standard and revised RSA encryption authentication use this SKEYID |
484 |
|
|
* computation. |
485 |
|
|
*/ |
486 |
|
|
static u_int8_t * |
487 |
|
|
enc_gen_skeyid(struct exchange *exchange, size_t *sz) |
488 |
|
|
{ |
489 |
|
|
struct prf *prf; |
490 |
|
|
struct ipsec_exch *ie = exchange->data; |
491 |
|
|
struct hash *hash = ie->hash; |
492 |
|
|
u_int8_t *skeyid; |
493 |
|
|
|
494 |
|
|
hash->Init(hash->ctx); |
495 |
|
|
hash->Update(hash->ctx, exchange->nonce_i, exchange->nonce_i_len); |
496 |
|
|
hash->Update(hash->ctx, exchange->nonce_r, exchange->nonce_r_len); |
497 |
|
|
hash->Final(hash->digest, hash->ctx); |
498 |
|
|
prf = prf_alloc(ie->prf_type, hash->type, hash->digest, *sz); |
499 |
|
|
if (!prf) |
500 |
|
|
return 0; |
501 |
|
|
|
502 |
|
|
*sz = prf->blocksize; |
503 |
|
|
skeyid = malloc(*sz); |
504 |
|
|
if (!skeyid) { |
505 |
|
|
log_error("enc_gen_skeyid: malloc (%d) failed", *sz); |
506 |
|
|
prf_free(prf); |
507 |
|
|
return 0; |
508 |
|
|
} |
509 |
|
|
prf->Init(prf->prfctx); |
510 |
|
|
prf->Update(prf->prfctx, exchange->cookies, ISAKMP_HDR_COOKIES_LEN); |
511 |
|
|
prf->Final(skeyid, prf->prfctx); |
512 |
|
|
prf_free(prf); |
513 |
|
|
return skeyid; |
514 |
|
|
} |
515 |
|
|
#endif /* notdef */ |
516 |
|
|
|
517 |
|
|
static int |
518 |
|
|
pre_shared_decode_hash(struct message *msg) |
519 |
|
|
{ |
520 |
|
|
struct exchange *exchange = msg->exchange; |
521 |
|
|
struct ipsec_exch *ie = exchange->data; |
522 |
|
|
struct payload *payload; |
523 |
|
|
size_t hashsize = ie->hash->hashsize; |
524 |
|
|
char header[80]; |
525 |
|
|
int initiator = exchange->initiator; |
526 |
|
|
u_int8_t **hash_p; |
527 |
|
|
|
528 |
|
|
/* Choose the right fields to fill-in. */ |
529 |
|
|
hash_p = initiator ? &ie->hash_r : &ie->hash_i; |
530 |
|
|
|
531 |
|
|
payload = payload_first(msg, ISAKMP_PAYLOAD_HASH); |
532 |
|
|
if (!payload) { |
533 |
|
|
log_print("pre_shared_decode_hash: no HASH payload found"); |
534 |
|
|
return -1; |
535 |
|
|
} |
536 |
|
|
/* Check that the hash is of the correct size. */ |
537 |
|
|
if (GET_ISAKMP_GEN_LENGTH(payload->p) - ISAKMP_GEN_SZ != hashsize) |
538 |
|
|
return -1; |
539 |
|
|
|
540 |
|
|
/* XXX Need this hash be in the SA? */ |
541 |
|
|
*hash_p = malloc(hashsize); |
542 |
|
|
if (!*hash_p) { |
543 |
|
|
log_error("pre_shared_decode_hash: malloc (%lu) failed", |
544 |
|
|
(unsigned long)hashsize); |
545 |
|
|
return -1; |
546 |
|
|
} |
547 |
|
|
memcpy(*hash_p, payload->p + ISAKMP_HASH_DATA_OFF, hashsize); |
548 |
|
|
snprintf(header, sizeof header, "pre_shared_decode_hash: HASH_%c", |
549 |
|
|
initiator ? 'R' : 'I'); |
550 |
|
|
LOG_DBG_BUF((LOG_MISC, 80, header, *hash_p, hashsize)); |
551 |
|
|
|
552 |
|
|
payload->flags |= PL_MARK; |
553 |
|
|
return 0; |
554 |
|
|
} |
555 |
|
|
|
556 |
|
|
/* Decrypt the HASH in SIG, we already need a parsed ID payload. */ |
557 |
|
|
static int |
558 |
|
|
rsa_sig_decode_hash(struct message *msg) |
559 |
|
|
{ |
560 |
|
|
struct cert_handler *handler; |
561 |
|
|
struct exchange *exchange = msg->exchange; |
562 |
|
|
struct ipsec_exch *ie = exchange->data; |
563 |
|
|
struct payload *p; |
564 |
|
|
void *cert = 0; |
565 |
|
|
u_int8_t *rawcert = 0, **hash_p, **id_cert, *id; |
566 |
|
|
u_int32_t rawcertlen, *id_cert_len; |
567 |
|
|
RSA *key = 0; |
568 |
|
|
size_t hashsize = ie->hash->hashsize, id_len; |
569 |
|
|
char header[80]; |
570 |
|
|
int len, initiator = exchange->initiator; |
571 |
|
|
int found = 0, n, i, id_found; |
572 |
|
|
#if defined (USE_DNSSEC) |
573 |
|
|
u_int8_t *rawkey = 0; |
574 |
|
|
u_int32_t rawkeylen; |
575 |
|
|
#endif |
576 |
|
|
|
577 |
|
|
/* Choose the right fields to fill-in. */ |
578 |
|
|
hash_p = initiator ? &ie->hash_r : &ie->hash_i; |
579 |
|
|
id = initiator ? exchange->id_r : exchange->id_i; |
580 |
|
|
id_len = initiator ? exchange->id_r_len : exchange->id_i_len; |
581 |
|
|
|
582 |
|
|
if (!id || id_len == 0) { |
583 |
|
|
log_print("rsa_sig_decode_hash: ID is missing"); |
584 |
|
|
return -1; |
585 |
|
|
} |
586 |
|
|
/* |
587 |
|
|
* XXX Assume we should use the same kind of certification as the |
588 |
|
|
* remote... moreover, just use the first CERT payload to decide what |
589 |
|
|
* to use. |
590 |
|
|
*/ |
591 |
|
|
p = payload_first(msg, ISAKMP_PAYLOAD_CERT); |
592 |
|
|
if (!p) |
593 |
|
|
handler = cert_get(ISAKMP_CERTENC_KEYNOTE); |
594 |
|
|
else |
595 |
|
|
handler = cert_get(GET_ISAKMP_CERT_ENCODING(p->p)); |
596 |
|
|
if (!handler) { |
597 |
|
|
log_print("rsa_sig_decode_hash: cert_get (%d) failed", |
598 |
|
|
p ? GET_ISAKMP_CERT_ENCODING(p->p) : -1); |
599 |
|
|
return -1; |
600 |
|
|
} |
601 |
|
|
/* |
602 |
|
|
* We need the policy session initialized now, so we can add |
603 |
|
|
* credentials etc. |
604 |
|
|
*/ |
605 |
|
|
exchange->policy_id = kn_init(); |
606 |
|
|
if (exchange->policy_id == -1) { |
607 |
|
|
log_print("rsa_sig_decode_hash: failed to initialize policy " |
608 |
|
|
"session"); |
609 |
|
|
return -1; |
610 |
|
|
} |
611 |
|
|
|
612 |
|
|
/* Obtain a certificate from our certificate storage. */ |
613 |
|
|
if (handler->cert_obtain(id, id_len, 0, &rawcert, &rawcertlen)) { |
614 |
|
|
if (handler->id == ISAKMP_CERTENC_X509_SIG) { |
615 |
|
|
cert = handler->cert_get(rawcert, rawcertlen); |
616 |
|
|
if (!cert) |
617 |
|
|
LOG_DBG((LOG_CRYPTO, 50, "rsa_sig_decode_hash:" |
618 |
|
|
" certificate malformed")); |
619 |
|
|
else { |
620 |
|
|
if (!handler->cert_get_key(cert, &key)) { |
621 |
|
|
log_print("rsa_sig_decode_hash: " |
622 |
|
|
"decoding certificate failed"); |
623 |
|
|
handler->cert_free(cert); |
624 |
|
|
} else { |
625 |
|
|
found++; |
626 |
|
|
LOG_DBG((LOG_CRYPTO, 40, |
627 |
|
|
"rsa_sig_decode_hash: using cert " |
628 |
|
|
"of type %d", handler->id)); |
629 |
|
|
exchange->recv_cert = cert; |
630 |
|
|
exchange->recv_certtype = handler->id; |
631 |
|
|
x509_generate_kn(exchange->policy_id, |
632 |
|
|
cert); |
633 |
|
|
} |
634 |
|
|
} |
635 |
|
|
} else if (handler->id == ISAKMP_CERTENC_KEYNOTE) |
636 |
|
|
handler->cert_insert(exchange->policy_id, rawcert); |
637 |
|
|
free(rawcert); |
638 |
|
|
} |
639 |
|
|
/* |
640 |
|
|
* Walk over potential CERT payloads in this message. |
641 |
|
|
* XXX I believe this is the wrong spot for this. CERTs can appear |
642 |
|
|
* anytime. |
643 |
|
|
*/ |
644 |
|
|
TAILQ_FOREACH(p, &msg->payload[ISAKMP_PAYLOAD_CERT], link) { |
645 |
|
|
p->flags |= PL_MARK; |
646 |
|
|
|
647 |
|
|
/* |
648 |
|
|
* When we have found a key, just walk over the rest, marking |
649 |
|
|
* them. |
650 |
|
|
*/ |
651 |
|
|
if (found) |
652 |
|
|
continue; |
653 |
|
|
|
654 |
|
|
handler = cert_get(GET_ISAKMP_CERT_ENCODING(p->p)); |
655 |
|
|
if (!handler) { |
656 |
|
|
LOG_DBG((LOG_MISC, 30, "rsa_sig_decode_hash: " |
657 |
|
|
"no handler for %s CERT encoding", |
658 |
|
|
constant_name(isakmp_certenc_cst, |
659 |
|
|
GET_ISAKMP_CERT_ENCODING(p->p)))); |
660 |
|
|
continue; |
661 |
|
|
} |
662 |
|
|
cert = handler->cert_get(p->p + ISAKMP_CERT_DATA_OFF, |
663 |
|
|
GET_ISAKMP_GEN_LENGTH(p->p) - ISAKMP_CERT_DATA_OFF); |
664 |
|
|
if (!cert) { |
665 |
|
|
log_print("rsa_sig_decode_hash: " |
666 |
|
|
"can not get data from CERT"); |
667 |
|
|
continue; |
668 |
|
|
} |
669 |
|
|
if (!handler->cert_validate(cert)) { |
670 |
|
|
handler->cert_free(cert); |
671 |
|
|
log_print("rsa_sig_decode_hash: received CERT can't " |
672 |
|
|
"be validated"); |
673 |
|
|
continue; |
674 |
|
|
} |
675 |
|
|
if (GET_ISAKMP_CERT_ENCODING(p->p) == |
676 |
|
|
ISAKMP_CERTENC_X509_SIG) { |
677 |
|
|
if (!handler->cert_get_subjects(cert, &n, &id_cert, |
678 |
|
|
&id_cert_len)) { |
679 |
|
|
handler->cert_free(cert); |
680 |
|
|
log_print("rsa_sig_decode_hash: can not get " |
681 |
|
|
"subject from CERT"); |
682 |
|
|
continue; |
683 |
|
|
} |
684 |
|
|
id_found = 0; |
685 |
|
|
for (i = 0; i < n; i++) |
686 |
|
|
if (id_cert_len[i] == id_len && |
687 |
|
|
id[0] == id_cert[i][0] && |
688 |
|
|
memcmp(id + 4, id_cert[i] + 4, id_len - 4) |
689 |
|
|
== 0) { |
690 |
|
|
id_found++; |
691 |
|
|
break; |
692 |
|
|
} |
693 |
|
|
if (!id_found) { |
694 |
|
|
handler->cert_free(cert); |
695 |
|
|
log_print("rsa_sig_decode_hash: no CERT " |
696 |
|
|
"subject match the ID"); |
697 |
|
|
free(id_cert); |
698 |
|
|
continue; |
699 |
|
|
} |
700 |
|
|
cert_free_subjects(n, id_cert, id_cert_len); |
701 |
|
|
} |
702 |
|
|
if (!handler->cert_get_key(cert, &key)) { |
703 |
|
|
handler->cert_free(cert); |
704 |
|
|
log_print("rsa_sig_decode_hash: decoding payload CERT " |
705 |
|
|
"failed"); |
706 |
|
|
continue; |
707 |
|
|
} |
708 |
|
|
/* We validated the cert, cache it for later use. */ |
709 |
|
|
handler->cert_insert(exchange->policy_id, cert); |
710 |
|
|
|
711 |
|
|
exchange->recv_cert = cert; |
712 |
|
|
exchange->recv_certtype = GET_ISAKMP_CERT_ENCODING(p->p); |
713 |
|
|
|
714 |
|
|
if (exchange->recv_certtype == ISAKMP_CERTENC_KEYNOTE) { |
715 |
|
|
struct keynote_deckey dc; |
716 |
|
|
char *pp; |
717 |
|
|
|
718 |
|
|
dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; |
719 |
|
|
dc.dec_key = key; |
720 |
|
|
|
721 |
|
|
pp = kn_encode_key(&dc, INTERNAL_ENC_PKCS1, |
722 |
|
|
ENCODING_HEX, KEYNOTE_PUBLIC_KEY); |
723 |
|
|
if (pp == NULL) { |
724 |
|
|
kn_free_key(&dc); |
725 |
|
|
log_print("rsa_sig_decode_hash: failed to " |
726 |
|
|
"ASCII-encode key"); |
727 |
|
|
return -1; |
728 |
|
|
} |
729 |
|
|
if (asprintf(&exchange->keynote_key, "rsa-hex:%s", |
730 |
|
|
pp) == -1) { |
731 |
|
|
free(pp); |
732 |
|
|
kn_free_key(&dc); |
733 |
|
|
log_print("rsa_sig_decode_hash: failed to asprintf()"); |
734 |
|
|
return -1; |
735 |
|
|
} |
736 |
|
|
free(pp); |
737 |
|
|
} |
738 |
|
|
found++; |
739 |
|
|
} |
740 |
|
|
|
741 |
|
|
#if defined (USE_DNSSEC) |
742 |
|
|
/* |
743 |
|
|
* If no certificate provided a key, try to find a validated DNSSEC |
744 |
|
|
* KEY. |
745 |
|
|
*/ |
746 |
|
|
if (!found) { |
747 |
|
|
rawkey = dns_get_key(IKE_AUTH_RSA_SIG, msg, &rawkeylen); |
748 |
|
|
|
749 |
|
|
/* We need to convert 'void *rawkey' into 'RSA *key'. */ |
750 |
|
|
if (dns_RSA_dns_to_x509(rawkey, rawkeylen, &key) == 0) |
751 |
|
|
found++; |
752 |
|
|
else |
753 |
|
|
log_print("rsa_sig_decode_hash: KEY to RSA key " |
754 |
|
|
"conversion failed"); |
755 |
|
|
|
756 |
|
|
free(rawkey); |
757 |
|
|
} |
758 |
|
|
#endif /* USE_DNSSEC */ |
759 |
|
|
|
760 |
|
|
/* If we still have not found a key, try to read it from a file. */ |
761 |
|
|
if (!found) |
762 |
|
|
if (get_raw_key_from_file(IKE_AUTH_RSA_SIG, id, id_len, &key) |
763 |
|
|
!= -1) |
764 |
|
|
found++; |
765 |
|
|
|
766 |
|
|
if (!found) { |
767 |
|
|
log_print("rsa_sig_decode_hash: no public key found"); |
768 |
|
|
return -1; |
769 |
|
|
} |
770 |
|
|
p = payload_first(msg, ISAKMP_PAYLOAD_SIG); |
771 |
|
|
if (!p) { |
772 |
|
|
log_print("rsa_sig_decode_hash: missing signature payload"); |
773 |
|
|
RSA_free(key); |
774 |
|
|
return -1; |
775 |
|
|
} |
776 |
|
|
/* Check that the sig is of the correct size. */ |
777 |
|
|
len = GET_ISAKMP_GEN_LENGTH(p->p) - ISAKMP_SIG_SZ; |
778 |
|
|
if (len != RSA_size(key)) { |
779 |
|
|
RSA_free(key); |
780 |
|
|
log_print("rsa_sig_decode_hash: " |
781 |
|
|
"SIG payload length does not match public key"); |
782 |
|
|
return -1; |
783 |
|
|
} |
784 |
|
|
*hash_p = malloc(len); |
785 |
|
|
if (!*hash_p) { |
786 |
|
|
RSA_free(key); |
787 |
|
|
log_error("rsa_sig_decode_hash: malloc (%d) failed", len); |
788 |
|
|
return -1; |
789 |
|
|
} |
790 |
|
|
len = RSA_public_decrypt(len, p->p + ISAKMP_SIG_DATA_OFF, *hash_p, key, |
791 |
|
|
RSA_PKCS1_PADDING); |
792 |
|
|
if (len == -1) { |
793 |
|
|
RSA_free(key); |
794 |
|
|
log_print("rsa_sig_decode_hash: RSA_public_decrypt () failed"); |
795 |
|
|
return -1; |
796 |
|
|
} |
797 |
|
|
/* Store key for later use */ |
798 |
|
|
exchange->recv_key = key; |
799 |
|
|
exchange->recv_keytype = ISAKMP_KEY_RSA; |
800 |
|
|
|
801 |
|
|
if (len != (int)hashsize) { |
802 |
|
|
free(*hash_p); |
803 |
|
|
*hash_p = 0; |
804 |
|
|
log_print("rsa_sig_decode_hash: len %lu != hashsize %lu", |
805 |
|
|
(unsigned long)len, (unsigned long)hashsize); |
806 |
|
|
return -1; |
807 |
|
|
} |
808 |
|
|
snprintf(header, sizeof header, "rsa_sig_decode_hash: HASH_%c", |
809 |
|
|
initiator ? 'R' : 'I'); |
810 |
|
|
LOG_DBG_BUF((LOG_MISC, 80, header, *hash_p, hashsize)); |
811 |
|
|
|
812 |
|
|
p->flags |= PL_MARK; |
813 |
|
|
return 0; |
814 |
|
|
} |
815 |
|
|
|
816 |
|
|
static int |
817 |
|
|
pre_shared_encode_hash(struct message *msg) |
818 |
|
|
{ |
819 |
|
|
struct exchange *exchange = msg->exchange; |
820 |
|
|
struct ipsec_exch *ie = exchange->data; |
821 |
|
|
size_t hashsize = ie->hash->hashsize; |
822 |
|
|
char header[80]; |
823 |
|
|
int initiator = exchange->initiator; |
824 |
|
|
u_int8_t *buf; |
825 |
|
|
|
826 |
|
|
buf = ipsec_add_hash_payload(msg, hashsize); |
827 |
|
|
if (!buf) |
828 |
|
|
return -1; |
829 |
|
|
|
830 |
|
|
if (ike_auth_hash(exchange, buf + ISAKMP_HASH_DATA_OFF) == -1) |
831 |
|
|
return -1; |
832 |
|
|
|
833 |
|
|
snprintf(header, sizeof header, "pre_shared_encode_hash: HASH_%c", |
834 |
|
|
initiator ? 'I' : 'R'); |
835 |
|
|
LOG_DBG_BUF((LOG_MISC, 80, header, buf + ISAKMP_HASH_DATA_OFF, |
836 |
|
|
hashsize)); |
837 |
|
|
return 0; |
838 |
|
|
} |
839 |
|
|
|
840 |
|
|
/* Encrypt the HASH into a SIG type. */ |
841 |
|
|
static int |
842 |
|
|
rsa_sig_encode_hash(struct message *msg) |
843 |
|
|
{ |
844 |
|
|
struct exchange *exchange = msg->exchange; |
845 |
|
|
struct ipsec_exch *ie = exchange->data; |
846 |
|
|
size_t hashsize = ie->hash->hashsize, id_len; |
847 |
|
|
struct cert_handler *handler; |
848 |
|
|
char header[80]; |
849 |
|
|
int initiator = exchange->initiator, idtype; |
850 |
|
|
u_int8_t *buf, *data, *buf2, *id; |
851 |
|
|
u_int32_t datalen; |
852 |
|
|
int32_t sigsize; |
853 |
|
|
void *sent_key; |
854 |
|
|
|
855 |
|
|
id = initiator ? exchange->id_i : exchange->id_r; |
856 |
|
|
id_len = initiator ? exchange->id_i_len : exchange->id_r_len; |
857 |
|
|
|
858 |
|
|
/* We may have been provided these by the kernel */ |
859 |
|
|
buf = (u_int8_t *)conf_get_str(exchange->name, "Credentials"); |
860 |
|
|
if (buf && (idtype = conf_get_num(exchange->name, "Credential_Type", |
861 |
|
|
-1)) != -1) { |
862 |
|
|
exchange->sent_certtype = idtype; |
863 |
|
|
handler = cert_get(idtype); |
864 |
|
|
if (!handler) { |
865 |
|
|
log_print("rsa_sig_encode_hash: cert_get (%d) failed", |
866 |
|
|
idtype); |
867 |
|
|
return -1; |
868 |
|
|
} |
869 |
|
|
exchange->sent_cert = |
870 |
|
|
handler->cert_from_printable((char *)buf); |
871 |
|
|
if (!exchange->sent_cert) { |
872 |
|
|
log_print("rsa_sig_encode_hash: failed to retrieve " |
873 |
|
|
"certificate"); |
874 |
|
|
return -1; |
875 |
|
|
} |
876 |
|
|
handler->cert_serialize(exchange->sent_cert, &data, &datalen); |
877 |
|
|
if (!data) { |
878 |
|
|
log_print("rsa_sig_encode_hash: cert serialization " |
879 |
|
|
"failed"); |
880 |
|
|
return -1; |
881 |
|
|
} |
882 |
|
|
goto aftercert; /* Skip all the certificate discovery */ |
883 |
|
|
} |
884 |
|
|
/* XXX This needs to be configurable. */ |
885 |
|
|
idtype = ISAKMP_CERTENC_KEYNOTE; |
886 |
|
|
|
887 |
|
|
/* Find a certificate with subjectAltName = id. */ |
888 |
|
|
handler = cert_get(idtype); |
889 |
|
|
if (!handler) { |
890 |
|
|
idtype = ISAKMP_CERTENC_X509_SIG; |
891 |
|
|
handler = cert_get(idtype); |
892 |
|
|
if (!handler) { |
893 |
|
|
log_print("rsa_sig_encode_hash: cert_get(%d) failed", |
894 |
|
|
idtype); |
895 |
|
|
return -1; |
896 |
|
|
} |
897 |
|
|
} |
898 |
|
|
if (handler->cert_obtain(id, id_len, 0, &data, &datalen) == 0) { |
899 |
|
|
if (idtype == ISAKMP_CERTENC_KEYNOTE) { |
900 |
|
|
idtype = ISAKMP_CERTENC_X509_SIG; |
901 |
|
|
handler = cert_get(idtype); |
902 |
|
|
if (!handler) { |
903 |
|
|
log_print("rsa_sig_encode_hash: cert_get(%d) " |
904 |
|
|
"failed", idtype); |
905 |
|
|
return -1; |
906 |
|
|
} |
907 |
|
|
if (handler->cert_obtain(id, id_len, 0, &data, |
908 |
|
|
&datalen) == 0) { |
909 |
|
|
LOG_DBG((LOG_MISC, 10, "rsa_sig_encode_hash: " |
910 |
|
|
"no certificate to send for id %s", |
911 |
|
|
ipsec_id_string(id, id_len))); |
912 |
|
|
goto skipcert; |
913 |
|
|
} |
914 |
|
|
} else { |
915 |
|
|
LOG_DBG((LOG_MISC, 10, |
916 |
|
|
"rsa_sig_encode_hash: no certificate to send" |
917 |
|
|
" for id %s", ipsec_id_string(id, id_len))); |
918 |
|
|
goto skipcert; |
919 |
|
|
} |
920 |
|
|
} |
921 |
|
|
/* Let's store the certificate we are going to use */ |
922 |
|
|
exchange->sent_certtype = idtype; |
923 |
|
|
exchange->sent_cert = handler->cert_get(data, datalen); |
924 |
|
|
if (!exchange->sent_cert) { |
925 |
|
|
free(data); |
926 |
|
|
log_print("rsa_sig_encode_hash: failed to get certificate " |
927 |
|
|
"from wire encoding"); |
928 |
|
|
return -1; |
929 |
|
|
} |
930 |
|
|
aftercert: |
931 |
|
|
|
932 |
|
|
buf = realloc(data, ISAKMP_CERT_SZ + datalen); |
933 |
|
|
if (!buf) { |
934 |
|
|
log_error("rsa_sig_encode_hash: realloc (%p, %d) failed", data, |
935 |
|
|
ISAKMP_CERT_SZ + datalen); |
936 |
|
|
free(data); |
937 |
|
|
return -1; |
938 |
|
|
} |
939 |
|
|
memmove(buf + ISAKMP_CERT_SZ, buf, datalen); |
940 |
|
|
SET_ISAKMP_CERT_ENCODING(buf, idtype); |
941 |
|
|
if (message_add_payload(msg, ISAKMP_PAYLOAD_CERT, buf, |
942 |
|
|
ISAKMP_CERT_SZ + datalen, 1)) { |
943 |
|
|
free(buf); |
944 |
|
|
return -1; |
945 |
|
|
} |
946 |
|
|
skipcert: |
947 |
|
|
|
948 |
|
|
/* Again, we may have these from the kernel */ |
949 |
|
|
buf = (u_int8_t *)conf_get_str(exchange->name, "PKAuthentication"); |
950 |
|
|
if (buf) { |
951 |
|
|
key_from_printable(ISAKMP_KEY_RSA, ISAKMP_KEYTYPE_PRIVATE, |
952 |
|
|
(char *)buf, &data, &datalen); |
953 |
|
|
if (!data) { |
954 |
|
|
log_print("rsa_sig_encode_hash: badly formatted RSA " |
955 |
|
|
"private key"); |
956 |
|
|
return 0; |
957 |
|
|
} |
958 |
|
|
sent_key = key_internalize(ISAKMP_KEY_RSA, |
959 |
|
|
ISAKMP_KEYTYPE_PRIVATE, data, datalen); |
960 |
|
|
if (!sent_key) { |
961 |
|
|
log_print("rsa_sig_encode_hash: bad RSA private key " |
962 |
|
|
"from dynamic SA acquisition subsystem"); |
963 |
|
|
return 0; |
964 |
|
|
} |
965 |
|
|
} else { |
966 |
|
|
/* Try through the regular means. */ |
967 |
|
|
switch (id[ISAKMP_ID_TYPE_OFF - ISAKMP_GEN_SZ]) { |
968 |
|
|
case IPSEC_ID_IPV4_ADDR: |
969 |
|
|
case IPSEC_ID_IPV6_ADDR: |
970 |
|
|
util_ntoa((char **)&buf2, |
971 |
|
|
id[ISAKMP_ID_TYPE_OFF - ISAKMP_GEN_SZ] == |
972 |
|
|
IPSEC_ID_IPV4_ADDR ? AF_INET : AF_INET6, |
973 |
|
|
id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ); |
974 |
|
|
if (!buf2) |
975 |
|
|
return 0; |
976 |
|
|
break; |
977 |
|
|
|
978 |
|
|
case IPSEC_ID_FQDN: |
979 |
|
|
case IPSEC_ID_USER_FQDN: |
980 |
|
|
buf2 = calloc(id_len - ISAKMP_ID_DATA_OFF + |
981 |
|
|
ISAKMP_GEN_SZ + 1, sizeof(char)); |
982 |
|
|
if (!buf2) { |
983 |
|
|
log_print("rsa_sig_encode_hash: malloc (%lu) " |
984 |
|
|
"failed", (unsigned long)id_len - |
985 |
|
|
ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1); |
986 |
|
|
return 0; |
987 |
|
|
} |
988 |
|
|
memcpy(buf2, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, |
989 |
|
|
id_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); |
990 |
|
|
break; |
991 |
|
|
|
992 |
|
|
/* XXX Support more ID types? */ |
993 |
|
|
default: |
994 |
|
|
buf2 = 0; |
995 |
|
|
return 0; |
996 |
|
|
} |
997 |
|
|
|
998 |
|
|
sent_key = ike_auth_get_key(IKE_AUTH_RSA_SIG, exchange->name, |
999 |
|
|
(char *)buf2, 0); |
1000 |
|
|
free(buf2); |
1001 |
|
|
|
1002 |
|
|
/* Did we find a key? */ |
1003 |
|
|
if (!sent_key) { |
1004 |
|
|
log_print("rsa_sig_encode_hash: " |
1005 |
|
|
"could not get private key"); |
1006 |
|
|
return -1; |
1007 |
|
|
} |
1008 |
|
|
} |
1009 |
|
|
|
1010 |
|
|
/* Enable RSA blinding. */ |
1011 |
|
|
if (RSA_blinding_on(sent_key, NULL) != 1) { |
1012 |
|
|
log_error("rsa_sig_encode_hash: RSA_blinding_on () failed."); |
1013 |
|
|
RSA_free(sent_key); |
1014 |
|
|
return -1; |
1015 |
|
|
} |
1016 |
|
|
/* XXX hashsize is not necessarily prf->blocksize. */ |
1017 |
|
|
buf = malloc(hashsize); |
1018 |
|
|
if (!buf) { |
1019 |
|
|
log_error("rsa_sig_encode_hash: malloc (%lu) failed", |
1020 |
|
|
(unsigned long)hashsize); |
1021 |
|
|
RSA_free(sent_key); |
1022 |
|
|
return -1; |
1023 |
|
|
} |
1024 |
|
|
if (ike_auth_hash(exchange, buf) == -1) { |
1025 |
|
|
free(buf); |
1026 |
|
|
RSA_free(sent_key); |
1027 |
|
|
return -1; |
1028 |
|
|
} |
1029 |
|
|
snprintf(header, sizeof header, "rsa_sig_encode_hash: HASH_%c", |
1030 |
|
|
initiator ? 'I' : 'R'); |
1031 |
|
|
LOG_DBG_BUF((LOG_MISC, 80, header, buf, hashsize)); |
1032 |
|
|
|
1033 |
|
|
data = malloc(RSA_size(sent_key)); |
1034 |
|
|
if (!data) { |
1035 |
|
|
log_error("rsa_sig_encode_hash: malloc (%d) failed", |
1036 |
|
|
RSA_size(sent_key)); |
1037 |
|
|
free(buf); |
1038 |
|
|
RSA_free(sent_key); |
1039 |
|
|
return -1; |
1040 |
|
|
} |
1041 |
|
|
sigsize = RSA_private_encrypt(hashsize, buf, data, sent_key, |
1042 |
|
|
RSA_PKCS1_PADDING); |
1043 |
|
|
if (sigsize == -1) { |
1044 |
|
|
log_print("rsa_sig_encode_hash: " |
1045 |
|
|
"RSA_private_encrypt () failed"); |
1046 |
|
|
free(data); |
1047 |
|
|
free(buf); |
1048 |
|
|
RSA_free(sent_key); |
1049 |
|
|
return -1; |
1050 |
|
|
} |
1051 |
|
|
datalen = (u_int32_t) sigsize; |
1052 |
|
|
|
1053 |
|
|
free(buf); |
1054 |
|
|
RSA_free(sent_key); |
1055 |
|
|
|
1056 |
|
|
buf = realloc(data, ISAKMP_SIG_SZ + datalen); |
1057 |
|
|
if (!buf) { |
1058 |
|
|
log_error("rsa_sig_encode_hash: realloc (%p, %d) failed", data, |
1059 |
|
|
ISAKMP_SIG_SZ + datalen); |
1060 |
|
|
free(data); |
1061 |
|
|
return -1; |
1062 |
|
|
} |
1063 |
|
|
memmove(buf + ISAKMP_SIG_SZ, buf, datalen); |
1064 |
|
|
|
1065 |
|
|
snprintf(header, sizeof header, "rsa_sig_encode_hash: SIG_%c", |
1066 |
|
|
initiator ? 'I' : 'R'); |
1067 |
|
|
LOG_DBG_BUF((LOG_MISC, 80, header, buf + ISAKMP_SIG_DATA_OFF, |
1068 |
|
|
datalen)); |
1069 |
|
|
if (message_add_payload(msg, ISAKMP_PAYLOAD_SIG, buf, |
1070 |
|
|
ISAKMP_SIG_SZ + datalen, 1)) { |
1071 |
|
|
free(buf); |
1072 |
|
|
return -1; |
1073 |
|
|
} |
1074 |
|
|
return 0; |
1075 |
|
|
} |
1076 |
|
|
|
1077 |
|
|
int |
1078 |
|
|
ike_auth_hash(struct exchange *exchange, u_int8_t *buf) |
1079 |
|
|
{ |
1080 |
|
|
struct ipsec_exch *ie = exchange->data; |
1081 |
|
|
struct prf *prf; |
1082 |
|
|
struct hash *hash = ie->hash; |
1083 |
|
|
int initiator = exchange->initiator; |
1084 |
|
|
u_int8_t *id; |
1085 |
|
|
size_t id_len; |
1086 |
|
|
|
1087 |
|
|
/* Choose the right fields to fill-in. */ |
1088 |
|
|
id = initiator ? exchange->id_i : exchange->id_r; |
1089 |
|
|
id_len = initiator ? exchange->id_i_len : exchange->id_r_len; |
1090 |
|
|
|
1091 |
|
|
/* Allocate the prf and start calculating our HASH. */ |
1092 |
|
|
prf = prf_alloc(ie->prf_type, hash->type, ie->skeyid, ie->skeyid_len); |
1093 |
|
|
if (!prf) |
1094 |
|
|
return -1; |
1095 |
|
|
|
1096 |
|
|
prf->Init(prf->prfctx); |
1097 |
|
|
prf->Update(prf->prfctx, initiator ? ie->g_xi : ie->g_xr, ie->g_x_len); |
1098 |
|
|
prf->Update(prf->prfctx, initiator ? ie->g_xr : ie->g_xi, ie->g_x_len); |
1099 |
|
|
prf->Update(prf->prfctx, exchange->cookies + |
1100 |
|
|
(initiator ? ISAKMP_HDR_ICOOKIE_OFF : ISAKMP_HDR_RCOOKIE_OFF), |
1101 |
|
|
ISAKMP_HDR_ICOOKIE_LEN); |
1102 |
|
|
prf->Update(prf->prfctx, exchange->cookies + |
1103 |
|
|
(initiator ? ISAKMP_HDR_RCOOKIE_OFF : ISAKMP_HDR_ICOOKIE_OFF), |
1104 |
|
|
ISAKMP_HDR_ICOOKIE_LEN); |
1105 |
|
|
prf->Update(prf->prfctx, ie->sa_i_b, ie->sa_i_b_len); |
1106 |
|
|
prf->Update(prf->prfctx, id, id_len); |
1107 |
|
|
prf->Final(buf, prf->prfctx); |
1108 |
|
|
prf_free(prf); |
1109 |
|
|
return 0; |
1110 |
|
|
} |
1111 |
|
|
|
1112 |
|
|
static int |
1113 |
|
|
get_raw_key_from_file(int type, u_int8_t *id, size_t id_len, RSA **rsa) |
1114 |
|
|
{ |
1115 |
|
|
char filename[FILENAME_MAX]; |
1116 |
|
|
char *fstr; |
1117 |
|
|
FILE *keyfp; |
1118 |
|
|
|
1119 |
|
|
if (type != IKE_AUTH_RSA_SIG) { /* XXX More types? */ |
1120 |
|
|
LOG_DBG((LOG_NEGOTIATION, 20, "get_raw_key_from_file: " |
1121 |
|
|
"invalid auth type %d\n", type)); |
1122 |
|
|
return -1; |
1123 |
|
|
} |
1124 |
|
|
*rsa = 0; |
1125 |
|
|
|
1126 |
|
|
fstr = conf_get_str("General", "Pubkey-directory"); |
1127 |
|
|
if (!fstr) |
1128 |
|
|
fstr = CONF_DFLT_PUBKEY_DIR; |
1129 |
|
|
|
1130 |
|
|
if (snprintf(filename, sizeof filename, "%s/", fstr) > |
1131 |
|
|
(int)sizeof filename - 1) |
1132 |
|
|
return -1; |
1133 |
|
|
|
1134 |
|
|
fstr = ipsec_id_string(id, id_len); |
1135 |
|
|
if (!fstr) { |
1136 |
|
|
LOG_DBG((LOG_NEGOTIATION, 50, "get_raw_key_from_file: " |
1137 |
|
|
"ipsec_id_string failed")); |
1138 |
|
|
return -1; |
1139 |
|
|
} |
1140 |
|
|
strlcat(filename, fstr, sizeof filename - strlen(filename)); |
1141 |
|
|
free(fstr); |
1142 |
|
|
|
1143 |
|
|
/* If the file does not exist, fail silently. */ |
1144 |
|
|
keyfp = monitor_fopen(filename, "r"); |
1145 |
|
|
if (keyfp) { |
1146 |
|
|
*rsa = PEM_read_RSA_PUBKEY(keyfp, NULL, NULL, NULL); |
1147 |
|
|
if (!*rsa) { |
1148 |
|
|
rewind(keyfp); |
1149 |
|
|
*rsa = PEM_read_RSAPublicKey(keyfp, NULL, NULL, NULL); |
1150 |
|
|
} |
1151 |
|
|
if (!*rsa) |
1152 |
|
|
log_print("get_raw_key_from_file: failed to get " |
1153 |
|
|
"public key %s", filename); |
1154 |
|
|
fclose(keyfp); |
1155 |
|
|
} else if (errno != ENOENT) { |
1156 |
|
|
log_error("get_raw_key_from_file: monitor_fopen " |
1157 |
|
|
"(\"%s\", \"r\") failed", filename); |
1158 |
|
|
return -1; |
1159 |
|
|
} else |
1160 |
|
|
LOG_DBG((LOG_NEGOTIATION, 50, |
1161 |
|
|
"get_raw_key_from_file: file %s not found", filename)); |
1162 |
|
|
|
1163 |
|
|
return (*rsa ? 0 : -1); |
1164 |
|
|
} |