]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/racoon/oakley.c
ipsec-164.10.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / oakley.c
CommitLineData
d1e348cf
A
1/* $NetBSD: oakley.c,v 1.9.6.2 2007/04/04 13:08:28 vanhu Exp $ */
2
3/* Id: oakley.c,v 1.32 2006/05/26 12:19:46 manubsd Exp */
52b7d2ce
A
4
5/*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "config.h"
35
36#include <sys/types.h>
37#include <sys/param.h>
38#include <sys/socket.h> /* XXX for subjectaltname */
39#include <netinet/in.h> /* XXX for subjectaltname */
40
e8d9021d 41#ifdef HAVE_OPENSSL
52b7d2ce 42#include <openssl/pkcs7.h>
d1e348cf 43#include <openssl/x509.h>
e8d9021d 44#endif
52b7d2ce
A
45
46#include <stdlib.h>
47#include <stdio.h>
48#include <string.h>
49#include <errno.h>
d1e348cf
A
50#include <arpa/inet.h>
51#include <TargetConditionals.h>
52b7d2ce
A
52
53#if TIME_WITH_SYS_TIME
54# include <sys/time.h>
55# include <time.h>
56#else
57# if HAVE_SYS_TIME_H
58# include <sys/time.h>
59# else
60# include <time.h>
61# endif
62#endif
d1e348cf
A
63#ifdef ENABLE_HYBRID
64#include <resolv.h>
65#endif
52b7d2ce
A
66
67#include "var.h"
68#include "misc.h"
69#include "vmbuf.h"
70#include "str2val.h"
71#include "plog.h"
72#include "debug.h"
73
74#include "isakmp_var.h"
75#include "isakmp.h"
76#ifdef ENABLE_HYBRID
77#include "isakmp_xauth.h"
78#include "isakmp_cfg.h"
79#endif
80#include "oakley.h"
81#include "admin.h"
82#include "privsep.h"
83#include "localconf.h"
52b7d2ce
A
84#include "policy.h"
85#include "handler.h"
86#include "ipsec_doi.h"
87#include "algorithm.h"
88#include "dhgroup.h"
89#include "sainfo.h"
90#include "proposal.h"
91#include "crypto_openssl.h"
52b7d2ce 92#include "crypto_cssm.h"
d1e348cf 93#if HAVE_OPENDIR
52b7d2ce
A
94#include "open_dir.h"
95#endif
96#include "dnssec.h"
97#include "sockmisc.h"
98#include "strnames.h"
99#include "gcmalloc.h"
e8d9021d 100#include <CoreFoundation/CoreFoundation.h>
d1e348cf 101#include "remoteconf.h"
fce29cd9 102#include "vpn_control.h"
e8d9021d
A
103#if TARGET_OS_EMBEDDED
104#include <Security/SecCertificate.h>
105#include <Security/SecCertificatePriv.h>
106#endif
52b7d2ce
A
107#ifdef HAVE_GSSAPI
108#include "gssapi.h"
109#endif
e8d9021d 110#include "vpn_control_var.h"
52b7d2ce
A
111
112#define OUTBOUND_SA 0
113#define INBOUND_SA 1
114
52b7d2ce
A
115#define CERT_CHECKID_FROM_PEER 0
116#define CERT_CHECKID_FROM_RMCONFIG 1
52b7d2ce 117
e8d9021d 118#ifdef HAVE_OPENSSL
52b7d2ce
A
119#define INITDHVAL(a, s, d, t) \
120do { \
e8d9021d
A
121vchar_t buf; \
122buf.v = str2val((s), 16, &buf.l); \
123memset(&a, 0, sizeof(struct dhgroup)); \
124a.type = (t); \
125a.prime = vdup(&buf); \
126a.gen1 = 2; \
127a.gen2 = 0; \
128racoon_free(buf.v); \
52b7d2ce 129} while(0);
e8d9021d
A
130#else /* HAVE_OPENSSL */
131#define INITDHVAL(a, s, d, t) \
132do { \
133vchar_t buf; \
134buf.v = str2val((s), 16, &buf.l); \
135memset(&a, 0, sizeof(struct dhgroup)); \
136a.desc = (d); \
137a.type = (t); \
138a.prime = vdup(&buf); \
139a.gen1 = 2; \
140a.gen2 = 0; \
141racoon_free(buf.v); \
142} while(0);
143#endif /* HAVE_OPENSSL */
52b7d2ce
A
144
145struct dhgroup dh_modp768;
146struct dhgroup dh_modp1024;
147struct dhgroup dh_modp1536;
148struct dhgroup dh_modp2048;
149struct dhgroup dh_modp3072;
150struct dhgroup dh_modp4096;
151struct dhgroup dh_modp6144;
152struct dhgroup dh_modp8192;
153
154
155static int oakley_check_dh_pub __P((vchar_t *, vchar_t **));
156static int oakley_compute_keymat_x __P((struct ph2handle *, int, int));
157static int get_cert_fromlocal __P((struct ph1handle *, int));
e8d9021d
A
158static int oakley_check_certid __P((struct ph1handle *iph1, int));
159static int oakley_check_certid_1 __P((vchar_t *, int, int, void*, cert_status_t *certStatus));
52b7d2ce
A
160static int check_typeofcertname __P((int, int));
161static cert_t *save_certbuf __P((struct isakmp_gen *));
e8d9021d 162#ifdef HAVE_OPENSSL
52b7d2ce 163static cert_t *save_certx509 __P((X509 *));
e8d9021d 164#endif
52b7d2ce
A
165static int oakley_padlen __P((int, int));
166
52b7d2ce 167static int base64toCFData(vchar_t *, CFDataRef*);
e8d9021d
A
168static cert_t *oakley_appendcert_to_certchain(cert_t *, cert_t *);
169
170static void oakley_cert_prettyprint (vchar_t *cert)
171{
172 char *p = NULL;
173#ifdef HAVE_OPENSSL
174 p = eay_get_x509text(cert);
175#else
176 /* add new cert dump code here */
52b7d2ce 177#endif
e8d9021d
A
178 plog(LLV_DEBUG, LOCATION, NULL, "%s", p ? p : "\n");
179 racoon_free(p);
180}
52b7d2ce
A
181
182int
183oakley_get_defaultlifetime()
184{
185 return OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
186}
187
188int
189oakley_dhinit()
190{
191 /* set DH MODP */
192 INITDHVAL(dh_modp768, OAKLEY_PRIME_MODP768,
193 OAKLEY_ATTR_GRP_DESC_MODP768, OAKLEY_ATTR_GRP_TYPE_MODP);
194 INITDHVAL(dh_modp1024, OAKLEY_PRIME_MODP1024,
195 OAKLEY_ATTR_GRP_DESC_MODP1024, OAKLEY_ATTR_GRP_TYPE_MODP);
196 INITDHVAL(dh_modp1536, OAKLEY_PRIME_MODP1536,
197 OAKLEY_ATTR_GRP_DESC_MODP1536, OAKLEY_ATTR_GRP_TYPE_MODP);
198 INITDHVAL(dh_modp2048, OAKLEY_PRIME_MODP2048,
199 OAKLEY_ATTR_GRP_DESC_MODP2048, OAKLEY_ATTR_GRP_TYPE_MODP);
200 INITDHVAL(dh_modp3072, OAKLEY_PRIME_MODP3072,
201 OAKLEY_ATTR_GRP_DESC_MODP3072, OAKLEY_ATTR_GRP_TYPE_MODP);
202 INITDHVAL(dh_modp4096, OAKLEY_PRIME_MODP4096,
203 OAKLEY_ATTR_GRP_DESC_MODP4096, OAKLEY_ATTR_GRP_TYPE_MODP);
204 INITDHVAL(dh_modp6144, OAKLEY_PRIME_MODP6144,
205 OAKLEY_ATTR_GRP_DESC_MODP6144, OAKLEY_ATTR_GRP_TYPE_MODP);
206 INITDHVAL(dh_modp8192, OAKLEY_PRIME_MODP8192,
207 OAKLEY_ATTR_GRP_DESC_MODP8192, OAKLEY_ATTR_GRP_TYPE_MODP);
208
209 return 0;
210}
211
212void
213oakley_dhgrp_free(dhgrp)
214 struct dhgroup *dhgrp;
215{
216 if (dhgrp->prime)
217 vfree(dhgrp->prime);
218 if (dhgrp->curve_a)
219 vfree(dhgrp->curve_a);
220 if (dhgrp->curve_b)
221 vfree(dhgrp->curve_b);
222 if (dhgrp->order)
223 vfree(dhgrp->order);
224 racoon_free(dhgrp);
225}
226
227/*
228 * RFC2409 5
229 * The length of the Diffie-Hellman public value MUST be equal to the
230 * length of the prime modulus over which the exponentiation was
231 * performed, prepending zero bits to the value if necessary.
232 */
233static int
234oakley_check_dh_pub(prime, pub0)
235 vchar_t *prime, **pub0;
236{
237 vchar_t *tmp;
238 vchar_t *pub = *pub0;
239
240 if (prime->l == pub->l)
241 return 0;
242
243 if (prime->l < pub->l) {
244 /* what should i do ? */
245 plog(LLV_ERROR, LOCATION, NULL,
246 "invalid public information was generated.\n");
247 return -1;
248 }
249
250 /* prime->l > pub->l */
251 tmp = vmalloc(prime->l);
252 if (tmp == NULL) {
253 plog(LLV_ERROR, LOCATION, NULL,
254 "failed to get DH buffer.\n");
255 return -1;
256 }
257 memcpy(tmp->v + prime->l - pub->l, pub->v, pub->l);
258
259 vfree(*pub0);
260 *pub0 = tmp;
261
262 return 0;
263}
264
265/*
266 * compute sharing secret of DH
267 * IN: *dh, *pub, *priv, *pub_p
268 * OUT: **gxy
269 */
e8d9021d 270#ifdef HAVE_OPENSSL
52b7d2ce 271int
e8d9021d 272oakley_dh_compute(const struct dhgroup *dh, vchar_t *pub, vchar_t *priv, vchar_t *pub_p, vchar_t **gxy)
52b7d2ce
A
273{
274#ifdef ENABLE_STATS
275 struct timeval start, end;
276#endif
277 if ((*gxy = vmalloc(dh->prime->l)) == NULL) {
278 plog(LLV_ERROR, LOCATION, NULL,
279 "failed to get DH buffer.\n");
280 return -1;
281 }
282
283#ifdef ENABLE_STATS
284 gettimeofday(&start, NULL);
285#endif
286 switch (dh->type) {
287 case OAKLEY_ATTR_GRP_TYPE_MODP:
288 if (eay_dh_compute(dh->prime, dh->gen1, pub, priv, pub_p, gxy) < 0) {
289 plog(LLV_ERROR, LOCATION, NULL,
290 "failed to compute dh value.\n");
291 return -1;
292 }
293 break;
294 case OAKLEY_ATTR_GRP_TYPE_ECP:
295 case OAKLEY_ATTR_GRP_TYPE_EC2N:
296 plog(LLV_ERROR, LOCATION, NULL,
297 "dh type %d isn't supported.\n", dh->type);
298 return -1;
299 default:
300 plog(LLV_ERROR, LOCATION, NULL,
301 "invalid dh type %d.\n", dh->type);
302 return -1;
303 }
304
305#ifdef ENABLE_STATS
306 gettimeofday(&end, NULL);
307 syslog(LOG_NOTICE, "%s(%s%d): %8.6f", __func__,
308 s_attr_isakmp_group(dh->type), dh->prime->l << 3,
309 timedelta(&start, &end));
310#endif
311
312 plog(LLV_DEBUG, LOCATION, NULL, "compute DH's shared.\n");
313 plogdump(LLV_DEBUG, (*gxy)->v, (*gxy)->l);
314
315 return 0;
316}
e8d9021d
A
317#else
318int
319oakley_dh_compute(const struct dhgroup *dh, vchar_t *pub_p, size_t publicKeySize, vchar_t **gxy, SecDHContext dhC)
320{
321
322 vchar_t *computed_key = NULL;
323 size_t computed_keylen;
324 size_t maxKeyLen;
325
326#ifdef ENABLE_STATS
327 struct timeval start, end;
328 gettimeofday(&start, NULL);
329#endif
330
331 plog(LLV_DEBUG, LOCATION, NULL, "compute DH result.\n");
332
333 maxKeyLen = SecDHGetMaxKeyLength(dhC);
334 computed_key = vmalloc(maxKeyLen);
335 if (computed_key == NULL) {
336 plog(LLV_ERROR, LOCATION, NULL, "memory error.\n");
337 goto fail;
338 }
339 computed_keylen = computed_key->l;
340 if (SecDHComputeKey(dhC, pub_p->v + (maxKeyLen - publicKeySize), publicKeySize,
341 computed_key->v, &computed_keylen)) {
342 plog(LLV_ERROR, LOCATION, NULL, "failed to compute dh value.\n");
343 goto fail;
344 }
345
346#ifdef ENABLE_STATS
347 gettimeofday(&end, NULL);
348 syslog(LOG_NOTICE, "%s(%s%d): %8.6f", __func__,
349 s_attr_isakmp_group(dh->type), dh->prime->l << 3,
350 timedelta(&start, &end));
351#endif
352
353 *gxy = vmalloc(maxKeyLen);
354 if (*gxy == NULL) {
355 plog(LLV_ERROR, LOCATION, NULL, "memory error.\n");
356 goto fail;
357 }
358 memcpy((*gxy)->v + (maxKeyLen - computed_keylen), computed_key->v, computed_keylen);
359 plog(LLV_DEBUG, LOCATION, NULL, "compute DH's shared.\n");
360 plogdump(LLV_DEBUG, (*gxy)->v, (*gxy)->l);
361 SecDHDestroy(dhC);
362 vfree(computed_key);
363 return 0;
364
365fail:
366 SecDHDestroy(dhC);
367 vfree(*gxy);
368 vfree(computed_key);
369 return -1;
370}
371
372#endif
52b7d2ce
A
373
374/*
375 * generate values of DH
376 * IN: *dh
377 * OUT: **pub, **priv
378 */
e8d9021d 379#ifdef HAVE_OPENSSL
52b7d2ce
A
380int
381oakley_dh_generate(dh, pub, priv)
382 const struct dhgroup *dh;
383 vchar_t **pub, **priv;
384{
385#ifdef ENABLE_STATS
386 struct timeval start, end;
387 gettimeofday(&start, NULL);
388#endif
389 switch (dh->type) {
390 case OAKLEY_ATTR_GRP_TYPE_MODP:
391 if (eay_dh_generate(dh->prime, dh->gen1, dh->gen2, pub, priv) < 0) {
392 plog(LLV_ERROR, LOCATION, NULL,
393 "failed to compute dh value.\n");
394 return -1;
395 }
396 break;
397
398 case OAKLEY_ATTR_GRP_TYPE_ECP:
399 case OAKLEY_ATTR_GRP_TYPE_EC2N:
400 plog(LLV_ERROR, LOCATION, NULL,
401 "dh type %d isn't supported.\n", dh->type);
402 return -1;
403 default:
404 plog(LLV_ERROR, LOCATION, NULL,
405 "invalid dh type %d.\n", dh->type);
406 return -1;
407 }
408
409#ifdef ENABLE_STATS
410 gettimeofday(&end, NULL);
411 syslog(LOG_NOTICE, "%s(%s%d): %8.6f", __func__,
412 s_attr_isakmp_group(dh->type), dh->prime->l << 3,
413 timedelta(&start, &end));
414#endif
415
416 if (oakley_check_dh_pub(dh->prime, pub) != 0)
417 return -1;
418
419 plog(LLV_DEBUG, LOCATION, NULL, "compute DH's private.\n");
420 plogdump(LLV_DEBUG, (*priv)->v, (*priv)->l);
421 plog(LLV_DEBUG, LOCATION, NULL, "compute DH's public.\n");
422 plogdump(LLV_DEBUG, (*pub)->v, (*pub)->l);
423
424 return 0;
425}
e8d9021d
A
426#else
427int
428oakley_dh_generate(const struct dhgroup *dh, vchar_t **pub, size_t *publicKeySize, SecDHContext *dhC)
429{
430 vchar_t *public = NULL;
431 size_t maxKeyLen;
432
433#ifdef ENABLE_STATS
434 struct timeval start, end;
435 gettimeofday(&start, NULL);
436#endif
437
438 plog(LLV_DEBUG, LOCATION, NULL, "generate DH key pair.\n");
439 *pub = NULL;
440 switch (dh->type) {
441 case OAKLEY_ATTR_GRP_TYPE_MODP:
85f41bec 442#define SECDH_MODP_GENERATOR OAKLEY_ATTR_GRP_DESC_MODP1024
e8d9021d
A
443 if (dh->desc != OAKLEY_ATTR_GRP_DESC_MODP1024 && dh->desc != OAKLEY_ATTR_GRP_DESC_MODP1536) {
444 plog(LLV_ERROR, LOCATION, NULL, "Invalid dh group.\n");
445 goto fail;
446 }
85f41bec 447 if (SecDHCreate(SECDH_MODP_GENERATOR, dh->prime->v, dh->prime->l, 0, NULL, 0, dhC)) {
e8d9021d
A
448 plog(LLV_ERROR, LOCATION, NULL, "failed to create dh context.\n");
449 goto fail;
450 }
451 maxKeyLen = SecDHGetMaxKeyLength(*dhC);
452 public = vmalloc(maxKeyLen);
453 *publicKeySize = public->l;
454 if (public == NULL) {
455 plog(LLV_ERROR, LOCATION, NULL, "memory error.\n");
456 goto fail;
457 }
458 if (SecDHGenerateKeypair(*dhC, public->v, publicKeySize)) {
459 plog(LLV_ERROR, LOCATION, NULL, "failed to generate dh key pair.\n");
460 goto fail;
461 }
462 plog(LLV_DEBUG, LOCATION, NULL, "got DH key pair.\n");
463
464 *pub = vmalloc(maxKeyLen);
465 if (*pub == NULL) {
466 plog(LLV_ERROR, LOCATION, NULL, "memory error.\n");
467 goto fail;
468 }
469 /* copy and fill with leading zeros */
470 memcpy((*pub)->v + (maxKeyLen - *publicKeySize), public->v, *publicKeySize);
471 break;
472
473 case OAKLEY_ATTR_GRP_TYPE_ECP:
474 case OAKLEY_ATTR_GRP_TYPE_EC2N:
475 plog(LLV_ERROR, LOCATION, NULL,
476 "dh type %d isn't supported.\n", dh->type);
477 goto fail;
478 default:
479 plog(LLV_ERROR, LOCATION, NULL,
480 "invalid dh type %d.\n", dh->type);
481 goto fail;
482 }
483
484#ifdef ENABLE_STATS
485 gettimeofday(&end, NULL);
486 syslog(LOG_NOTICE, "%s(%s%d): %8.6f", __func__,
487 s_attr_isakmp_group(dh->type), dh->prime->l << 3,
488 timedelta(&start, &end));
489#endif
490
491 if (oakley_check_dh_pub(dh->prime, pub) != 0) {
492 plog(LLV_DEBUG, LOCATION, NULL, "failed DH public key size check.\n");
493 goto fail;
494 }
495
496 plog(LLV_DEBUG, LOCATION, NULL, "compute DH's private.\n");
497 plog(LLV_DEBUG, LOCATION, NULL, "compute DH's public.\n");
498 plogdump(LLV_DEBUG, (*pub)->v, (*pub)->l);
499
500 vfree(public);
501 return 0;
502
503fail:
504 SecDHDestroy(*dhC);
505 vfree(*pub);
506 vfree(public);
507 return -1;
508
509}
510#endif
52b7d2ce
A
511
512/*
513 * copy pre-defined dhgroup values.
514 */
515int
516oakley_setdhgroup(group, dhgrp)
517 int group;
518 struct dhgroup **dhgrp;
519{
520 struct dhgroup *g;
521
522 *dhgrp = NULL; /* just make sure, initialize */
523
524 g = alg_oakley_dhdef_group(group);
525 if (g == NULL) {
526 plog(LLV_ERROR, LOCATION, NULL,
527 "invalid DH parameter grp=%d.\n", group);
528 return -1;
529 }
530
531 if (!g->type || !g->prime || !g->gen1) {
532 /* unsuported */
533 plog(LLV_ERROR, LOCATION, NULL,
534 "unsupported DH parameters grp=%d.\n", group);
535 return -1;
536 }
537
538 *dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
539 if (*dhgrp == NULL) {
540 plog(LLV_ERROR, LOCATION, NULL,
541 "failed to get DH buffer.\n");
542 return 0;
543 }
544
545 /* set defined dh vlaues */
546 memcpy(*dhgrp, g, sizeof(*g));
547 (*dhgrp)->prime = vdup(g->prime);
548
549 return 0;
550}
551
552/*
553 * PRF
554 *
555 * NOTE: we do not support prf with different input/output bitwidth,
556 * so we do not implement RFC2409 Appendix B (DOORAK-MAC example) in
557 * oakley_compute_keymat(). If you add support for such prf function,
558 * modify oakley_compute_keymat() accordingly.
559 */
560vchar_t *
561oakley_prf(key, buf, iph1)
562 vchar_t *key, *buf;
563 struct ph1handle *iph1;
564{
565 vchar_t *res = NULL;
566 int type;
567
568 if (iph1->approval == NULL) {
569 /*
570 * it's before negotiating hash algorithm.
571 * We use md5 as default.
572 */
573 type = OAKLEY_ATTR_HASH_ALG_MD5;
574 } else
575 type = iph1->approval->hashtype;
576
577 res = alg_oakley_hmacdef_one(type, key, buf);
578 if (res == NULL) {
579 plog(LLV_ERROR, LOCATION, NULL,
580 "invalid hmac algorithm %d.\n", type);
581 return NULL;
582 }
583
584 return res;
585}
586
587/*
588 * hash
589 */
590vchar_t *
591oakley_hash(buf, iph1)
592 vchar_t *buf;
593 struct ph1handle *iph1;
594{
595 vchar_t *res = NULL;
596 int type;
597
598 if (iph1->approval == NULL) {
599 /*
600 * it's before negotiating hash algorithm.
601 * We use md5 as default.
602 */
603 type = OAKLEY_ATTR_HASH_ALG_MD5;
604 } else
605 type = iph1->approval->hashtype;
606
607 res = alg_oakley_hashdef_one(type, buf);
608 if (res == NULL) {
609 plog(LLV_ERROR, LOCATION, NULL,
610 "invalid hash algorithm %d.\n", type);
611 return NULL;
612 }
613
614 return res;
615}
616
617/*
618 * compute KEYMAT
619 * see seciton 5.5 Phase 2 - Quick Mode in isakmp-oakley-05.
620 */
621int
622oakley_compute_keymat(iph2, side)
623 struct ph2handle *iph2;
624 int side;
625{
626 int error = -1;
627
628 /* compute sharing secret of DH when PFS */
629 if (iph2->approval->pfs_group && iph2->dhpub_p) {
e8d9021d 630#ifdef HAVE_OPENSSL
52b7d2ce 631 if (oakley_dh_compute(iph2->pfsgrp, iph2->dhpub,
e8d9021d
A
632 iph2->dhpriv, iph2->dhpub_p, &iph2->dhgxy) < 0)
633#else
634 if (oakley_dh_compute(iph2->pfsgrp, iph2->dhpub_p, iph2->publicKeySize, &iph2->dhgxy, iph2->dhC) < 0)
635#endif
52b7d2ce
A
636 goto end;
637 }
638
639 /* compute keymat */
640 if (oakley_compute_keymat_x(iph2, side, INBOUND_SA) < 0
641 || oakley_compute_keymat_x(iph2, side, OUTBOUND_SA) < 0)
642 goto end;
643
644 plog(LLV_DEBUG, LOCATION, NULL, "KEYMAT computed.\n");
645
646 error = 0;
647
648end:
649 return error;
650}
651
652/*
653 * compute KEYMAT.
654 * KEYMAT = prf(SKEYID_d, protocol | SPI | Ni_b | Nr_b).
655 * If PFS is desired and KE payloads were exchanged,
656 * KEYMAT = prf(SKEYID_d, g(qm)^xy | protocol | SPI | Ni_b | Nr_b)
657 *
658 * NOTE: we do not support prf with different input/output bitwidth,
659 * so we do not implement RFC2409 Appendix B (DOORAK-MAC example).
660 */
661static int
662oakley_compute_keymat_x(iph2, side, sa_dir)
663 struct ph2handle *iph2;
664 int side;
665 int sa_dir;
666{
667 vchar_t *buf = NULL, *res = NULL, *bp;
668 char *p;
669 int len;
670 int error = -1;
671 int pfs = 0;
672 int dupkeymat; /* generate K[1-dupkeymat] */
673 struct saproto *pr;
674 struct satrns *tr;
675 int encklen, authklen, l;
676
677 pfs = ((iph2->approval->pfs_group && iph2->dhgxy) ? 1 : 0);
678
679 len = pfs ? iph2->dhgxy->l : 0;
680 len += (1
681 + sizeof(u_int32_t) /* XXX SPI size */
682 + iph2->nonce->l
683 + iph2->nonce_p->l);
684 buf = vmalloc(len);
685 if (buf == NULL) {
686 plog(LLV_ERROR, LOCATION, NULL,
687 "failed to get keymat buffer.\n");
688 goto end;
689 }
690
691 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
692 p = buf->v;
693
694 /* if PFS */
695 if (pfs) {
696 memcpy(p, iph2->dhgxy->v, iph2->dhgxy->l);
697 p += iph2->dhgxy->l;
698 }
699
700 p[0] = pr->proto_id;
701 p += 1;
702
703 memcpy(p, (sa_dir == INBOUND_SA ? &pr->spi : &pr->spi_p),
704 sizeof(pr->spi));
705 p += sizeof(pr->spi);
706
707 bp = (side == INITIATOR ? iph2->nonce : iph2->nonce_p);
708 memcpy(p, bp->v, bp->l);
709 p += bp->l;
710
711 bp = (side == INITIATOR ? iph2->nonce_p : iph2->nonce);
712 memcpy(p, bp->v, bp->l);
713 p += bp->l;
714
715 /* compute IV */
716 plog(LLV_DEBUG, LOCATION, NULL, "KEYMAT compute with\n");
717 plogdump(LLV_DEBUG, buf->v, buf->l);
718
719 /* res = K1 */
720 res = oakley_prf(iph2->ph1->skeyid_d, buf, iph2->ph1);
721 if (res == NULL)
722 goto end;
723
724 /* compute key length needed */
725 encklen = authklen = 0;
726 switch (pr->proto_id) {
727 case IPSECDOI_PROTO_IPSEC_ESP:
728 for (tr = pr->head; tr; tr = tr->next) {
729 l = alg_ipsec_encdef_keylen(tr->trns_id,
730 tr->encklen);
731 if (l > encklen)
732 encklen = l;
733
734 l = alg_ipsec_hmacdef_hashlen(tr->authtype);
735 if (l > authklen)
736 authklen = l;
737 }
738 break;
739 case IPSECDOI_PROTO_IPSEC_AH:
740 for (tr = pr->head; tr; tr = tr->next) {
741 l = alg_ipsec_hmacdef_hashlen(tr->trns_id);
742 if (l > authklen)
743 authklen = l;
744 }
745 break;
746 default:
747 break;
748 }
749 plog(LLV_DEBUG, LOCATION, NULL, "encklen=%d authklen=%d\n",
750 encklen, authklen);
751
752 dupkeymat = (encklen + authklen) / 8 / res->l;
753 dupkeymat += 2; /* safety mergin */
754 if (dupkeymat < 3)
755 dupkeymat = 3;
756 plog(LLV_DEBUG, LOCATION, NULL,
757 "generating %zu bits of key (dupkeymat=%d)\n",
758 dupkeymat * 8 * res->l, dupkeymat);
759 if (0 < --dupkeymat) {
760 vchar_t *prev = res; /* K(n-1) */
761 vchar_t *seed = NULL; /* seed for Kn */
762 size_t l;
763
764 /*
765 * generating long key (isakmp-oakley-08 5.5)
766 * KEYMAT = K1 | K2 | K3 | ...
767 * where
768 * src = [ g(qm)^xy | ] protocol | SPI | Ni_b | Nr_b
769 * K1 = prf(SKEYID_d, src)
770 * K2 = prf(SKEYID_d, K1 | src)
771 * K3 = prf(SKEYID_d, K2 | src)
772 * Kn = prf(SKEYID_d, K(n-1) | src)
773 */
774 plog(LLV_DEBUG, LOCATION, NULL,
775 "generating K1...K%d for KEYMAT.\n",
776 dupkeymat + 1);
777
778 seed = vmalloc(prev->l + buf->l);
779 if (seed == NULL) {
780 plog(LLV_ERROR, LOCATION, NULL,
781 "failed to get keymat buffer.\n");
782 if (prev && prev != res)
783 vfree(prev);
784 goto end;
785 }
786
787 while (dupkeymat--) {
788 vchar_t *this = NULL; /* Kn */
d1e348cf 789 int update_prev;
52b7d2ce
A
790
791 memcpy(seed->v, prev->v, prev->l);
792 memcpy(seed->v + prev->l, buf->v, buf->l);
793 this = oakley_prf(iph2->ph1->skeyid_d, seed,
794 iph2->ph1);
795 if (!this) {
796 plog(LLV_ERROR, LOCATION, NULL,
797 "oakley_prf memory overflow\n");
798 if (prev && prev != res)
799 vfree(prev);
800 vfree(this);
801 vfree(seed);
802 goto end;
803 }
804
d1e348cf
A
805 update_prev = (prev && prev == res) ? 1 : 0;
806
52b7d2ce
A
807 l = res->l;
808 res = vrealloc(res, l + this->l);
d1e348cf
A
809
810 if (update_prev)
811 prev = res;
812
52b7d2ce
A
813 if (res == NULL) {
814 plog(LLV_ERROR, LOCATION, NULL,
815 "failed to get keymat buffer.\n");
816 if (prev && prev != res)
817 vfree(prev);
818 vfree(this);
819 vfree(seed);
820 goto end;
821 }
822 memcpy(res->v + l, this->v, this->l);
823
824 if (prev && prev != res)
825 vfree(prev);
826 prev = this;
827 this = NULL;
828 }
829
830 if (prev && prev != res)
831 vfree(prev);
832 vfree(seed);
833 }
834
835 plogdump(LLV_DEBUG, res->v, res->l);
836
837 if (sa_dir == INBOUND_SA)
838 pr->keymat = res;
839 else
840 pr->keymat_p = res;
841 res = NULL;
842 }
843
844 error = 0;
845
846end:
847 if (error) {
848 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
849 if (pr->keymat) {
850 vfree(pr->keymat);
851 pr->keymat = NULL;
852 }
853 if (pr->keymat_p) {
854 vfree(pr->keymat_p);
855 pr->keymat_p = NULL;
856 }
857 }
858 }
859
860 if (buf != NULL)
861 vfree(buf);
862 if (res)
863 vfree(res);
864
865 return error;
866}
867
52b7d2ce
A
868
869/*
870 * compute HASH(3) prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b)
871 * see seciton 5.5 Phase 2 - Quick Mode in isakmp-oakley-05.
872 */
873vchar_t *
874oakley_compute_hash3(iph1, msgid, body)
875 struct ph1handle *iph1;
876 u_int32_t msgid;
877 vchar_t *body;
878{
879 vchar_t *buf = 0, *res = 0;
880 int len;
881 int error = -1;
882
883 /* create buffer */
884 len = 1 + sizeof(u_int32_t) + body->l;
885 buf = vmalloc(len);
886 if (buf == NULL) {
887 plog(LLV_DEBUG, LOCATION, NULL,
888 "failed to get hash buffer\n");
889 goto end;
890 }
891
892 buf->v[0] = 0;
893
894 memcpy(buf->v + 1, (char *)&msgid, sizeof(msgid));
895
896 memcpy(buf->v + 1 + sizeof(u_int32_t), body->v, body->l);
897
898 plog(LLV_DEBUG, LOCATION, NULL, "HASH with: \n");
899 plogdump(LLV_DEBUG, buf->v, buf->l);
900
901 /* compute HASH */
902 res = oakley_prf(iph1->skeyid_a, buf, iph1);
903 if (res == NULL)
904 goto end;
905
906 error = 0;
907
908 plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n");
909 plogdump(LLV_DEBUG, res->v, res->l);
910
911end:
912 if (buf != NULL)
913 vfree(buf);
914 return res;
915}
916
917/*
918 * compute HASH type of prf(SKEYID_a, M-ID | buffer)
919 * e.g.
920 * for quick mode HASH(1):
921 * prf(SKEYID_a, M-ID | SA | Ni [ | KE ] [ | IDci | IDcr ])
922 * for quick mode HASH(2):
923 * prf(SKEYID_a, M-ID | Ni_b | SA | Nr [ | KE ] [ | IDci | IDcr ])
924 * for Informational exchange:
925 * prf(SKEYID_a, M-ID | N/D)
926 */
927vchar_t *
928oakley_compute_hash1(iph1, msgid, body)
929 struct ph1handle *iph1;
930 u_int32_t msgid;
931 vchar_t *body;
932{
933 vchar_t *buf = NULL, *res = NULL;
934 char *p;
935 int len;
936 int error = -1;
937
938 /* create buffer */
939 len = sizeof(u_int32_t) + body->l;
940 buf = vmalloc(len);
941 if (buf == NULL) {
942 plog(LLV_DEBUG, LOCATION, NULL,
943 "failed to get hash buffer\n");
944 goto end;
945 }
946
947 p = buf->v;
948
949 memcpy(buf->v, (char *)&msgid, sizeof(msgid));
950 p += sizeof(u_int32_t);
951
952 memcpy(p, body->v, body->l);
953
954 plog(LLV_DEBUG, LOCATION, NULL, "HASH with:\n");
955 plogdump(LLV_DEBUG, buf->v, buf->l);
956
957 /* compute HASH */
958 res = oakley_prf(iph1->skeyid_a, buf, iph1);
959 if (res == NULL)
960 goto end;
961
962 error = 0;
963
964 plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n");
965 plogdump(LLV_DEBUG, res->v, res->l);
966
967end:
968 if (buf != NULL)
969 vfree(buf);
970 return res;
971}
972
973/*
974 * compute phase1 HASH
975 * main/aggressive
976 * I-digest = prf(SKEYID, g^i | g^r | CKY-I | CKY-R | SAi_b | ID_i1_b)
977 * R-digest = prf(SKEYID, g^r | g^i | CKY-R | CKY-I | SAi_b | ID_r1_b)
978 * for gssapi, also include all GSS tokens, and call gss_wrap on the result
979 */
980vchar_t *
981oakley_ph1hash_common(iph1, sw)
982 struct ph1handle *iph1;
983 int sw;
984{
985 vchar_t *buf = NULL, *res = NULL, *bp;
986 char *p, *bp2;
987 int len, bl;
988 int error = -1;
989#ifdef HAVE_GSSAPI
990 vchar_t *gsstokens = NULL;
991#endif
992
993 /* create buffer */
994 len = iph1->dhpub->l
995 + iph1->dhpub_p->l
996 + sizeof(cookie_t) * 2
997 + iph1->sa->l
998 + (sw == GENERATE ? iph1->id->l : iph1->id_p->l);
999
1000#ifdef HAVE_GSSAPI
d1e348cf 1001 if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
52b7d2ce
A
1002 if (iph1->gi_i != NULL && iph1->gi_r != NULL) {
1003 bp = (sw == GENERATE ? iph1->gi_i : iph1->gi_r);
1004 len += bp->l;
1005 }
1006 if (sw == GENERATE)
1007 gssapi_get_itokens(iph1, &gsstokens);
1008 else
1009 gssapi_get_rtokens(iph1, &gsstokens);
1010 if (gsstokens == NULL)
1011 return NULL;
1012 len += gsstokens->l;
1013 }
1014#endif
1015
1016 buf = vmalloc(len);
1017 if (buf == NULL) {
1018 plog(LLV_ERROR, LOCATION, NULL,
1019 "failed to get hash buffer\n");
1020 goto end;
1021 }
1022
1023 p = buf->v;
1024
1025 bp = (sw == GENERATE ? iph1->dhpub : iph1->dhpub_p);
1026 memcpy(p, bp->v, bp->l);
1027 p += bp->l;
1028
1029 bp = (sw == GENERATE ? iph1->dhpub_p : iph1->dhpub);
1030 memcpy(p, bp->v, bp->l);
1031 p += bp->l;
1032
1033 if (iph1->side == INITIATOR)
1034 bp2 = (sw == GENERATE ?
1035 (char *)&iph1->index.i_ck : (char *)&iph1->index.r_ck);
1036 else
1037 bp2 = (sw == GENERATE ?
1038 (char *)&iph1->index.r_ck : (char *)&iph1->index.i_ck);
1039 bl = sizeof(cookie_t);
1040 memcpy(p, bp2, bl);
1041 p += bl;
1042
1043 if (iph1->side == INITIATOR)
1044 bp2 = (sw == GENERATE ?
1045 (char *)&iph1->index.r_ck : (char *)&iph1->index.i_ck);
1046 else
1047 bp2 = (sw == GENERATE ?
1048 (char *)&iph1->index.i_ck : (char *)&iph1->index.r_ck);
1049 bl = sizeof(cookie_t);
1050 memcpy(p, bp2, bl);
1051 p += bl;
1052
1053 bp = iph1->sa;
1054 memcpy(p, bp->v, bp->l);
1055 p += bp->l;
1056
1057 bp = (sw == GENERATE ? iph1->id : iph1->id_p);
1058 memcpy(p, bp->v, bp->l);
1059 p += bp->l;
1060
1061#ifdef HAVE_GSSAPI
d1e348cf 1062 if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
52b7d2ce
A
1063 if (iph1->gi_i != NULL && iph1->gi_r != NULL) {
1064 bp = (sw == GENERATE ? iph1->gi_i : iph1->gi_r);
1065 memcpy(p, bp->v, bp->l);
1066 p += bp->l;
1067 }
1068 memcpy(p, gsstokens->v, gsstokens->l);
1069 p += gsstokens->l;
1070 }
1071#endif
1072
1073 plog(LLV_DEBUG, LOCATION, NULL, "HASH with:\n");
1074 plogdump(LLV_DEBUG, buf->v, buf->l);
1075
1076 /* compute HASH */
1077 res = oakley_prf(iph1->skeyid, buf, iph1);
1078 if (res == NULL)
1079 goto end;
1080
1081 error = 0;
1082
d1e348cf
A
1083 plog(LLV_DEBUG, LOCATION, NULL, "HASH (%s) computed:\n",
1084 iph1->side == INITIATOR ? "init" : "resp");
52b7d2ce
A
1085 plogdump(LLV_DEBUG, res->v, res->l);
1086
1087end:
1088 if (buf != NULL)
1089 vfree(buf);
1090#ifdef HAVE_GSSAPI
1091 if (gsstokens != NULL)
1092 vfree(gsstokens);
1093#endif
1094 return res;
1095}
1096
1097/*
1098 * compute HASH_I on base mode.
1099 * base:psk,rsa
1100 * HASH_I = prf(SKEYID, g^xi | CKY-I | CKY-R | SAi_b | IDii_b)
1101 * base:sig
1102 * HASH_I = prf(hash(Ni_b | Nr_b), g^xi | CKY-I | CKY-R | SAi_b | IDii_b)
1103 */
1104vchar_t *
1105oakley_ph1hash_base_i(iph1, sw)
1106 struct ph1handle *iph1;
1107 int sw;
1108{
1109 vchar_t *buf = NULL, *res = NULL, *bp;
1110 vchar_t *hashkey = NULL;
1111 vchar_t *hash = NULL; /* for signature mode */
1112 char *p;
1113 int len;
1114 int error = -1;
1115
1116 /* sanity check */
1117 if (iph1->etype != ISAKMP_ETYPE_BASE) {
1118 plog(LLV_ERROR, LOCATION, NULL,
1119 "invalid etype for this hash function\n");
1120 return NULL;
1121 }
1122
d1e348cf 1123 switch (AUTHMETHOD(iph1)) {
52b7d2ce
A
1124 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
1125 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
1126 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
d1e348cf
A
1127#ifdef ENABLE_HYBRID
1128 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
1129 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
1130 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
1131 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
1132 case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
1133 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
1134#endif
52b7d2ce
A
1135 if (iph1->skeyid == NULL) {
1136 plog(LLV_ERROR, LOCATION, NULL, "no SKEYID found.\n");
1137 return NULL;
1138 }
1139 hashkey = iph1->skeyid;
1140 break;
1141
1142 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
1143 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
d1e348cf 1144#ifdef HAVE_GSSAPI
52b7d2ce 1145 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
d1e348cf 1146#endif
52b7d2ce 1147#ifdef ENABLE_HYBRID
52b7d2ce 1148 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
d1e348cf 1149 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
52b7d2ce 1150 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
d1e348cf
A
1151 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
1152 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
1153 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
1154 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
1155 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
52b7d2ce
A
1156#endif
1157 /* make hash for seed */
1158 len = iph1->nonce->l + iph1->nonce_p->l;
1159 buf = vmalloc(len);
1160 if (buf == NULL) {
1161 plog(LLV_ERROR, LOCATION, NULL,
1162 "failed to get hash buffer\n");
1163 goto end;
1164 }
1165 p = buf->v;
1166
1167 bp = (sw == GENERATE ? iph1->nonce_p : iph1->nonce);
1168 memcpy(p, bp->v, bp->l);
1169 p += bp->l;
1170
1171 bp = (sw == GENERATE ? iph1->nonce : iph1->nonce_p);
1172 memcpy(p, bp->v, bp->l);
1173 p += bp->l;
1174
1175 hash = oakley_hash(buf, iph1);
1176 if (hash == NULL)
1177 goto end;
1178 vfree(buf);
1179 buf = NULL;
1180
1181 hashkey = hash;
1182 break;
1183
1184 default:
1185 plog(LLV_ERROR, LOCATION, NULL,
1186 "not supported authentication method %d\n",
1187 iph1->approval->authmethod);
1188 return NULL;
1189
1190 }
1191
1192 len = (sw == GENERATE ? iph1->dhpub->l : iph1->dhpub_p->l)
1193 + sizeof(cookie_t) * 2
1194 + iph1->sa->l
1195 + (sw == GENERATE ? iph1->id->l : iph1->id_p->l);
1196 buf = vmalloc(len);
1197 if (buf == NULL) {
1198 plog(LLV_ERROR, LOCATION, NULL,
1199 "failed to get hash buffer\n");
1200 goto end;
1201 }
1202 p = buf->v;
1203
1204 bp = (sw == GENERATE ? iph1->dhpub : iph1->dhpub_p);
1205 memcpy(p, bp->v, bp->l);
1206 p += bp->l;
1207
1208 memcpy(p, &iph1->index.i_ck, sizeof(cookie_t));
1209 p += sizeof(cookie_t);
1210 memcpy(p, &iph1->index.r_ck, sizeof(cookie_t));
1211 p += sizeof(cookie_t);
1212
1213 memcpy(p, iph1->sa->v, iph1->sa->l);
1214 p += iph1->sa->l;
1215
1216 bp = (sw == GENERATE ? iph1->id : iph1->id_p);
1217 memcpy(p, bp->v, bp->l);
1218 p += bp->l;
1219
1220 plog(LLV_DEBUG, LOCATION, NULL, "HASH_I with:\n");
1221 plogdump(LLV_DEBUG, buf->v, buf->l);
1222
1223 /* compute HASH */
1224 res = oakley_prf(hashkey, buf, iph1);
1225 if (res == NULL)
1226 goto end;
1227
1228 error = 0;
1229
1230 plog(LLV_DEBUG, LOCATION, NULL, "HASH_I computed:\n");
1231 plogdump(LLV_DEBUG, res->v, res->l);
1232
1233end:
1234 if (hash != NULL)
1235 vfree(hash);
1236 if (buf != NULL)
1237 vfree(buf);
1238 return res;
1239}
1240
1241/*
1242 * compute HASH_R on base mode for signature method.
1243 * base:
1244 * HASH_R = prf(hash(Ni_b | Nr_b), g^xi | g^xr | CKY-I | CKY-R | SAi_b | IDii_b)
1245 */
1246vchar_t *
1247oakley_ph1hash_base_r(iph1, sw)
1248 struct ph1handle *iph1;
1249 int sw;
1250{
1251 vchar_t *buf = NULL, *res = NULL, *bp;
1252 vchar_t *hash = NULL;
1253 char *p;
1254 int len;
1255 int error = -1;
1256
1257 /* sanity check */
1258 if (iph1->etype != ISAKMP_ETYPE_BASE) {
1259 plog(LLV_ERROR, LOCATION, NULL,
1260 "invalid etype for this hash function\n");
1261 return NULL;
1262 }
d1e348cf
A
1263
1264 switch(AUTHMETHOD(iph1)) {
1265 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
1266 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
52b7d2ce 1267#ifdef ENABLE_HYBRID
d1e348cf
A
1268 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
1269 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
1270 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
1271 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
1272 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
1273 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
1274 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
1275 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
1276 case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
52b7d2ce 1277#endif
d1e348cf
A
1278 break;
1279 default:
52b7d2ce
A
1280 plog(LLV_ERROR, LOCATION, NULL,
1281 "not supported authentication method %d\n",
1282 iph1->approval->authmethod);
1283 return NULL;
d1e348cf 1284 break;
52b7d2ce
A
1285 }
1286
1287 /* make hash for seed */
1288 len = iph1->nonce->l + iph1->nonce_p->l;
1289 buf = vmalloc(len);
1290 if (buf == NULL) {
1291 plog(LLV_ERROR, LOCATION, NULL,
1292 "failed to get hash buffer\n");
1293 goto end;
1294 }
1295 p = buf->v;
1296
1297 bp = (sw == GENERATE ? iph1->nonce_p : iph1->nonce);
1298 memcpy(p, bp->v, bp->l);
1299 p += bp->l;
1300
1301 bp = (sw == GENERATE ? iph1->nonce : iph1->nonce_p);
1302 memcpy(p, bp->v, bp->l);
1303 p += bp->l;
1304
1305 hash = oakley_hash(buf, iph1);
1306 if (hash == NULL)
1307 goto end;
1308 vfree(buf);
1309 buf = NULL;
1310
1311 /* make really hash */
1312 len = (sw == GENERATE ? iph1->dhpub_p->l : iph1->dhpub->l)
1313 + (sw == GENERATE ? iph1->dhpub->l : iph1->dhpub_p->l)
1314 + sizeof(cookie_t) * 2
1315 + iph1->sa->l
1316 + (sw == GENERATE ? iph1->id_p->l : iph1->id->l);
1317 buf = vmalloc(len);
1318 if (buf == NULL) {
1319 plog(LLV_ERROR, LOCATION, NULL,
1320 "failed to get hash buffer\n");
1321 goto end;
1322 }
1323 p = buf->v;
1324
1325
1326 bp = (sw == GENERATE ? iph1->dhpub_p : iph1->dhpub);
1327 memcpy(p, bp->v, bp->l);
1328 p += bp->l;
1329
1330 bp = (sw == GENERATE ? iph1->dhpub : iph1->dhpub_p);
1331 memcpy(p, bp->v, bp->l);
1332 p += bp->l;
1333
1334 memcpy(p, &iph1->index.i_ck, sizeof(cookie_t));
1335 p += sizeof(cookie_t);
1336 memcpy(p, &iph1->index.r_ck, sizeof(cookie_t));
1337 p += sizeof(cookie_t);
1338
1339 memcpy(p, iph1->sa->v, iph1->sa->l);
1340 p += iph1->sa->l;
1341
1342 bp = (sw == GENERATE ? iph1->id_p : iph1->id);
1343 memcpy(p, bp->v, bp->l);
1344 p += bp->l;
1345
d1e348cf 1346 plog(LLV_DEBUG, LOCATION, NULL, "HASH_R with:\n");
52b7d2ce
A
1347 plogdump(LLV_DEBUG, buf->v, buf->l);
1348
1349 /* compute HASH */
1350 res = oakley_prf(hash, buf, iph1);
1351 if (res == NULL)
1352 goto end;
1353
1354 error = 0;
1355
d1e348cf 1356 plog(LLV_DEBUG, LOCATION, NULL, "HASH_R computed:\n");
52b7d2ce
A
1357 plogdump(LLV_DEBUG, res->v, res->l);
1358
1359end:
1360 if (buf != NULL)
1361 vfree(buf);
1362 if (hash)
1363 vfree(hash);
1364 return res;
1365}
1366
e8d9021d
A
1367#if HAVE_OPENDIR
1368static int
1369oakley_verify_userid(iph1)
1370 struct ph1handle *iph1;
1371{
1372 cert_t *p;
1373 vchar_t *user_id;
1374 int user_id_found = 0;
1375
1376 for (p = iph1->cert_p; p; p = p->chain) {
1377 user_id = eay_get_x509_common_name(&p->cert);
1378 if (user_id) {
1379 user_id_found = 1;
1380 // the following functions will check if user_id == 0
1381 if (open_dir_authorize_id(user_id, iph1->rmconf->open_dir_auth_group)) {
1382 vfree(user_id);
1383 return 0;
1384 }
1385 vfree(user_id);
1386 }
1387 }
1388 if (user_id_found) {
1389 plog(LLV_ERROR, LOCATION, NULL,
1390 "the peer is not authorized for access.\n");
1391 } else {
1392 plog(LLV_ERROR, LOCATION, NULL,
1393 "the peer is not authorized for access - user ID not found.\n");
1394 }
1395 return ISAKMP_NTYPE_AUTHENTICATION_FAILED;
1396}
1397#endif /* HAVE_OPENDIR */
1398
e8d9021d
A
1399#ifdef HAVE_OPENSSL
1400static int
1401oakley_check_x509cert(certchain, capath, cafile, local)
1402 cert_t *certchain;
1403 char *capath;
1404 char *cafile;
1405 int local;
1406{
1407 cert_t *p;
1408 int result = 0;
1409
1410 for (p = certchain; p; p = p->chain) {
1411 if ((result = eay_check_x509cert(&p->cert,
1412 capath,
1413 cafile,
1414 local))) {
1415 break;
1416 }
1417 }
1418 return result;
1419}
1420#endif /* HAVE_OPENSSL */
1421
52b7d2ce
A
1422/*
1423 * compute each authentication method in phase 1.
1424 * OUT:
1425 * 0: OK
1426 * -1: error
1427 * other: error to be reply with notification.
1428 * the value is notification type.
1429 */
1430int
1431oakley_validate_auth(iph1)
1432 struct ph1handle *iph1;
1433{
1434 vchar_t *my_hash = NULL;
1435 int result;
1436#ifdef HAVE_GSSAPI
1437 vchar_t *gsshash = NULL;
1438#endif
1439#ifdef ENABLE_STATS
1440 struct timeval start, end;
1441#endif
e8d9021d 1442 SecKeyRef publicKeyRef;
52b7d2ce
A
1443
1444#ifdef ENABLE_STATS
1445 gettimeofday(&start, NULL);
1446#endif
d1e348cf
A
1447
1448 switch (AUTHMETHOD(iph1)) {
52b7d2ce 1449 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
d1e348cf
A
1450#ifdef ENABLE_HYBRID
1451 case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
1452 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
1453#endif
52b7d2ce
A
1454 /* validate HASH */
1455 {
1456 char *r_hash;
1457
1458 if (iph1->id_p == NULL || iph1->pl_hash == NULL) {
1459 plog(LLV_ERROR, LOCATION, iph1->remote,
1460 "few isakmp message received.\n");
1461 return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1462 }
d1e348cf
A
1463#ifdef ENABLE_HYBRID
1464 if (AUTHMETHOD(iph1) == FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I &&
1465 ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0))
1466 {
1467 plog(LLV_ERROR, LOCATION, NULL, "No SIG was passed, "
1468 "hybrid auth is enabled, "
1469 "but peer is no Xauth compliant\n");
1470 return ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED;
1471 break;
1472 }
1473#endif
52b7d2ce
A
1474 r_hash = (caddr_t)(iph1->pl_hash + 1);
1475
d1e348cf 1476 plog(LLV_DEBUG, LOCATION, NULL, "HASH received:\n");
52b7d2ce
A
1477 plogdump(LLV_DEBUG, r_hash,
1478 ntohs(iph1->pl_hash->h.len) - sizeof(*iph1->pl_hash));
1479
1480 switch (iph1->etype) {
1481 case ISAKMP_ETYPE_IDENT:
1482 case ISAKMP_ETYPE_AGG:
1483 my_hash = oakley_ph1hash_common(iph1, VALIDATE);
1484 break;
1485 case ISAKMP_ETYPE_BASE:
1486 if (iph1->side == INITIATOR)
1487 my_hash = oakley_ph1hash_common(iph1, VALIDATE);
1488 else
1489 my_hash = oakley_ph1hash_base_i(iph1, VALIDATE);
1490 break;
1491 default:
1492 plog(LLV_ERROR, LOCATION, NULL,
1493 "invalid etype %d\n", iph1->etype);
1494 return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
1495 }
1496 if (my_hash == NULL)
1497 return ISAKMP_INTERNAL_ERROR;
1498
1499 result = memcmp(my_hash->v, r_hash, my_hash->l);
1500 vfree(my_hash);
1501
1502 if (result) {
1503 plog(LLV_ERROR, LOCATION, NULL, "HASH mismatched\n");
1504 return ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1505 }
1506
1507 plog(LLV_DEBUG, LOCATION, NULL, "HASH for PSK validated.\n");
1508 }
1509 break;
1510 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
1511 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
1512#ifdef ENABLE_HYBRID
d1e348cf
A
1513 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
1514 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
1515 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
1516 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
1517 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
1518 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
52b7d2ce
A
1519#endif
1520 {
1521 int error = 0;
1522 int certtype = 0;
1523
1524 /* validation */
1525 if (iph1->id_p == NULL) {
1526 plog(LLV_ERROR, LOCATION, iph1->remote,
1527 "no ID payload was passed.\n");
1528 return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1529 }
1530 if (iph1->sig_p == NULL) {
1531 plog(LLV_ERROR, LOCATION, iph1->remote,
1532 "no SIG payload was passed.\n");
1533 return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1534 }
1535
1536 plog(LLV_DEBUG, LOCATION, NULL, "SIGN passed:\n");
1537 plogdump(LLV_DEBUG, iph1->sig_p->v, iph1->sig_p->l);
1538
1539 /* get peer's cert */
1540 switch (iph1->rmconf->getcert_method) {
1541 case ISAKMP_GETCERT_PAYLOAD:
1542 if (iph1->cert_p == NULL) {
1543 plog(LLV_ERROR, LOCATION, NULL,
1544 "no peer's CERT payload found.\n");
1545 return ISAKMP_INTERNAL_ERROR;
1546 }
1547 break;
e8d9021d 1548#ifdef HAVE_OPENSSL
52b7d2ce
A
1549 case ISAKMP_GETCERT_LOCALFILE:
1550 switch (iph1->rmconf->certtype) {
1551 case ISAKMP_CERT_X509SIGN:
1552 if (iph1->rmconf->peerscertfile == NULL) {
1553 plog(LLV_ERROR, LOCATION, NULL,
1554 "no peer's CERT file found.\n");
1555 return ISAKMP_INTERNAL_ERROR;
1556 }
1557
1558 /* don't use cached cert */
1559 if (iph1->cert_p != NULL) {
1560 oakley_delcert(iph1->cert_p);
1561 iph1->cert_p = NULL;
1562 }
1563
1564 error = get_cert_fromlocal(iph1, 0);
1565 break;
1566
52b7d2ce
A
1567 }
1568 if (error)
1569 return ISAKMP_INTERNAL_ERROR;
1570 break;
e8d9021d 1571#endif
52b7d2ce
A
1572 case ISAKMP_GETCERT_DNS:
1573 if (iph1->rmconf->peerscertfile != NULL) {
1574 plog(LLV_ERROR, LOCATION, NULL,
1575 "why peer's CERT file is defined "
1576 "though getcert method is dns ?\n");
1577 return ISAKMP_INTERNAL_ERROR;
1578 }
1579
1580 /* don't use cached cert */
1581 if (iph1->cert_p != NULL) {
1582 oakley_delcert(iph1->cert_p);
1583 iph1->cert_p = NULL;
1584 }
1585
1586 iph1->cert_p = dnssec_getcert(iph1->id_p);
1587 if (iph1->cert_p == NULL) {
1588 plog(LLV_ERROR, LOCATION, NULL,
1589 "no CERT RR found.\n");
1590 return ISAKMP_INTERNAL_ERROR;
1591 }
1592 break;
1593 default:
1594 plog(LLV_ERROR, LOCATION, NULL,
1595 "invalid getcert_mothod: %d\n",
1596 iph1->rmconf->getcert_method);
1597 return ISAKMP_INTERNAL_ERROR;
1598 }
1599
1600 /* compare ID payload and certificate name */
1601 if (iph1->rmconf->verify_cert &&
52b7d2ce 1602 (error = oakley_check_certid(iph1, CERT_CHECKID_FROM_PEER)) != 0)
52b7d2ce 1603 return error;
52b7d2ce
A
1604
1605 /* check configured peers identifier against cert IDs */
1606 /* allows checking of specified ID against multiple ids in the cert */
1607 /* such as multiple domain names */
d1e348cf 1608#if !TARGET_OS_EMBEDDED
52b7d2ce
A
1609 if (iph1->rmconf->cert_verification_option == VERIFICATION_OPTION_PEERS_IDENTIFIER &&
1610 (error = oakley_check_certid(iph1, CERT_CHECKID_FROM_RMCONFIG)) != 0)
1611 return error;
d1e348cf 1612#endif
52b7d2ce 1613
d1e348cf 1614#if HAVE_OPENDIR
52b7d2ce
A
1615 /* check cert common name against Open Directory authentication group */
1616 if (iph1->rmconf->cert_verification_option == VERIFICATION_OPTION_OPEN_DIR) {
e8d9021d
A
1617 if (oakley_verify_userid(iph1)) {
1618 return ISAKMP_NTYPE_AUTHENTICATION_FAILED;
52b7d2ce
A
1619 }
1620 }
d1e348cf 1621#endif /* HAVE_OPENDIR */
52b7d2ce
A
1622
1623 /* verify certificate */
1624 if (iph1->rmconf->verify_cert
1625 && iph1->rmconf->getcert_method == ISAKMP_GETCERT_PAYLOAD) {
1626 certtype = iph1->rmconf->certtype;
1627#ifdef ENABLE_HYBRID
d1e348cf
A
1628 switch (AUTHMETHOD(iph1)) {
1629 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
1630 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
52b7d2ce
A
1631 certtype = iph1->cert_p->type;
1632 break;
1633 default:
1634 break;
1635 }
1636#endif
1637 switch (certtype) {
1638 case ISAKMP_CERT_X509SIGN:
d1e348cf
A
1639 {
1640 /* use ID from remote configuration */
1641 /* check each ID in list */
1642 struct idspec *id_spec;
1643 CFStringRef hostname = NULL;
1644 char *peers_id;
1645 struct genlist_entry *gpb = NULL;
1646
1647 if (iph1->rmconf->cert_verification_option == VERIFICATION_OPTION_PEERS_IDENTIFIER) {
1648 id_spec = genlist_next(iph1->rmconf->idvl_p, &gpb); /* expect only one id */
1649 if (id_spec->idtype == IDTYPE_ADDRESS) {
85f41bec 1650 switch ((ALIGNED_CAST(struct sockaddr_storage *)(id_spec->id->v))->ss_family) {
d1e348cf 1651 case AF_INET:
85f41bec 1652 peers_id = inet_ntoa((ALIGNED_CAST(struct sockaddr_in *)(id_spec->id->v))->sin_addr);
d1e348cf
A
1653 hostname = CFStringCreateWithCString(NULL, peers_id, kCFStringEncodingUTF8);
1654 break;
1655#ifdef INET6
1656 case AF_INET6:
1657 return ISAKMP_NTYPE_INVALID_ID_INFORMATION; /* not currently supported for embedded */
1658 break;
1659#endif
1660 default:
1661 plog(LLV_ERROR, LOCATION, NULL,
1662 "unknown address type for peers identifier.\n");
1663 return ISAKMP_NTYPE_AUTHENTICATION_FAILED;
1664 break;
1665 }
1666 } else
1667 hostname = CFStringCreateWithBytes(NULL, (u_int8_t *)id_spec->id->v, id_spec->id->l, kCFStringEncodingUTF8, FALSE);
1668 }
e8d9021d 1669 error = crypto_cssm_check_x509cert(oakley_get_peer_cert_from_certchain(iph1), iph1->cert_p, hostname, &publicKeyRef);
d1e348cf
A
1670 if (hostname)
1671 CFRelease(hostname);
1672 }
85f41bec 1673 break;
52b7d2ce
A
1674
1675 default:
1676 plog(LLV_ERROR, LOCATION, NULL,
1677 "no supported certtype %d\n", certtype);
1678 return ISAKMP_INTERNAL_ERROR;
1679 }
1680 if (error != 0) {
1681 plog(LLV_ERROR, LOCATION, NULL,
1682 "the peer's certificate is not verified.\n");
1683 return ISAKMP_NTYPE_INVALID_CERT_AUTHORITY;
1684 }
1685 }
1686
52b7d2ce
A
1687 plog(LLV_DEBUG, LOCATION, NULL, "CERT validated\n");
1688
1689 /* compute hash */
1690 switch (iph1->etype) {
1691 case ISAKMP_ETYPE_IDENT:
1692 case ISAKMP_ETYPE_AGG:
1693 my_hash = oakley_ph1hash_common(iph1, VALIDATE);
1694 break;
1695 case ISAKMP_ETYPE_BASE:
1696 if (iph1->side == INITIATOR)
1697 my_hash = oakley_ph1hash_base_r(iph1, VALIDATE);
1698 else
1699 my_hash = oakley_ph1hash_base_i(iph1, VALIDATE);
1700 break;
1701 default:
1702 plog(LLV_ERROR, LOCATION, NULL,
1703 "invalid etype %d\n", iph1->etype);
1704 return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
1705 }
1706 if (my_hash == NULL)
1707 return ISAKMP_INTERNAL_ERROR;
1708
1709
1710 certtype = iph1->rmconf->certtype;
1711#ifdef ENABLE_HYBRID
d1e348cf
A
1712 switch (AUTHMETHOD(iph1)) {
1713 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
1714 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
52b7d2ce
A
1715 certtype = iph1->cert_p->type;
1716 break;
1717 default:
1718 break;
1719 }
1720#endif
1721 /* check signature */
1722 switch (certtype) {
1723 case ISAKMP_CERT_X509SIGN:
1724 case ISAKMP_CERT_DNS:
85f41bec
A
1725 if (publicKeyRef == NULL)
1726 plog(LLV_ERROR, LOCATION, NULL, "@@@@@@ publicKeyRef is NULL\n");
e8d9021d
A
1727 error = crypto_cssm_verify_x509sign(publicKeyRef, my_hash, iph1->sig_p);
1728 if (error)
1729 plog(LLV_ERROR, LOCATION, NULL, "error verifying signature %s\n", GetSecurityErrorString(error));
1730
1731 CFRelease(publicKeyRef);
52b7d2ce 1732 break;
52b7d2ce 1733
52b7d2ce
A
1734 default:
1735 plog(LLV_ERROR, LOCATION, NULL,
1736 "no supported certtype %d\n",
1737 certtype);
1738 vfree(my_hash);
1739 return ISAKMP_INTERNAL_ERROR;
1740 }
1741
1742 vfree(my_hash);
1743 if (error != 0) {
1744 plog(LLV_ERROR, LOCATION, NULL,
1745 "Invalid SIG.\n");
1746 return ISAKMP_NTYPE_INVALID_SIGNATURE;
1747 }
1748 plog(LLV_DEBUG, LOCATION, NULL, "SIG authenticated\n");
1749 }
1750 break;
1751#ifdef ENABLE_HYBRID
d1e348cf
A
1752 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
1753 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
52b7d2ce
A
1754 {
1755 if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) {
1756 plog(LLV_ERROR, LOCATION, NULL, "No SIG was passed, "
1757 "hybrid auth is enabled, "
1758 "but peer is no Xauth compliant\n");
1759 return ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED;
1760 break;
1761 }
1762 plog(LLV_INFO, LOCATION, NULL, "No SIG was passed, "
1763 "but hybrid auth is enabled\n");
1764
1765 return 0;
1766 break;
1767 }
1768#endif
1769#ifdef HAVE_GSSAPI
1770 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
d1e348cf
A
1771 /* check if we're not into XAUTH_PSKEY_I instead */
1772#ifdef ENABLE_HYBRID
1773 if (iph1->rmconf->xauth)
1774 break;
1775#endif
52b7d2ce
A
1776 switch (iph1->etype) {
1777 case ISAKMP_ETYPE_IDENT:
1778 case ISAKMP_ETYPE_AGG:
1779 my_hash = oakley_ph1hash_common(iph1, VALIDATE);
1780 break;
1781 default:
1782 plog(LLV_ERROR, LOCATION, NULL,
1783 "invalid etype %d\n", iph1->etype);
1784 return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
1785 }
1786
1787 if (my_hash == NULL) {
1788 if (gssapi_more_tokens(iph1))
1789 return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
1790 else
1791 return ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1792 }
1793
1794 gsshash = gssapi_unwraphash(iph1);
1795 if (gsshash == NULL) {
1796 vfree(my_hash);
1797 return ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1798 }
1799
1800 result = memcmp(my_hash->v, gsshash->v, my_hash->l);
1801 vfree(my_hash);
1802 vfree(gsshash);
1803
1804 if (result) {
1805 plog(LLV_ERROR, LOCATION, NULL, "HASH mismatched\n");
1806 return ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1807 }
1808 plog(LLV_DEBUG, LOCATION, NULL, "hash compared OK\n");
1809 break;
1810#endif
1811 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
1812 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
d1e348cf
A
1813#ifdef ENABLE_HYBRID
1814 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
1815 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
1816 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
1817 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
1818#endif
52b7d2ce
A
1819 if (iph1->id_p == NULL || iph1->pl_hash == NULL) {
1820 plog(LLV_ERROR, LOCATION, iph1->remote,
1821 "few isakmp message received.\n");
1822 return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1823 }
1824 plog(LLV_ERROR, LOCATION, iph1->remote,
1825 "not supported authmethod type %s\n",
1826 s_oakley_attr_method(iph1->approval->authmethod));
1827 return ISAKMP_INTERNAL_ERROR;
1828 default:
1829 plog(LLV_ERROR, LOCATION, iph1->remote,
1830 "invalid authmethod %d why ?\n",
1831 iph1->approval->authmethod);
1832 return ISAKMP_INTERNAL_ERROR;
1833 }
1834#ifdef ENABLE_STATS
1835 gettimeofday(&end, NULL);
1836 syslog(LOG_NOTICE, "%s(%s): %8.6f", __func__,
1837 s_oakley_attr_method(iph1->approval->authmethod),
1838 timedelta(&start, &end));
1839#endif
1840
1841 return 0;
1842}
1843
e8d9021d
A
1844int
1845oakley_find_status_in_certchain (cert_t *certchain, cert_status_t certStatus)
1846{
1847 cert_t *p;
1848
1849 for (p = certchain; p; p = p->chain) {
1850 if (p->status == certStatus) {
1851 return 1;
1852 }
1853 }
1854 return 0;
1855}
1856
1857static
1858int
1859oakley_vpncontrol_notify_ike_failed_if_mycert_invalid (struct ph1handle *iph1,
1860 int notify_initiator)
1861{
1862#if TARGET_OS_EMBEDDED
1863 int premature = oakley_find_status_in_certchain(iph1->cert, CERT_STATUS_PREMATURE);
1864 int expired = oakley_find_status_in_certchain(iph1->cert, CERT_STATUS_EXPIRED);
1865 if (premature || expired) {
1866 u_int32_t address;
1867 u_int32_t fail_reason;
1868
85f41bec 1869 if (iph1->remote->ss_family == AF_INET)
e8d9021d
A
1870 address = ((struct sockaddr_in *)(iph1->remote))->sin_addr.s_addr;
1871 else
1872 address = 0;
1873 if (premature) {
1874 fail_reason = VPNCTL_NTYPE_LOCAL_CERT_PREMATURE;
1875 } else {
1876 fail_reason = VPNCTL_NTYPE_LOCAL_CERT_EXPIRED;
1877 }
1878 vpncontrol_notify_ike_failed(fail_reason, notify_initiator, address, 0, NULL);
1879 return -1;
1880 }
1881#endif /* TARGET_OS_EMBEDDED */
1882 return 0;
1883}
1884
52b7d2ce
A
1885/* get my certificate
1886 * NOTE: include certificate type.
1887 */
1888int
1889oakley_getmycert(iph1)
1890 struct ph1handle *iph1;
1891{
fce29cd9 1892 int err;
fce29cd9 1893
52b7d2ce
A
1894 switch (iph1->rmconf->certtype) {
1895 case ISAKMP_CERT_X509SIGN:
1896 if (iph1->cert)
1897 return 0;
fce29cd9 1898 if ( !(err = get_cert_fromlocal(iph1, 1))){
e8d9021d 1899 if (oakley_vpncontrol_notify_ike_failed_if_mycert_invalid(iph1, FROM_LOCAL)) {
fce29cd9
A
1900 return -1;
1901 }
1902 }
fce29cd9 1903 return err;
85f41bec 1904
52b7d2ce
A
1905 default:
1906 plog(LLV_ERROR, LOCATION, NULL,
1907 "Unknown certtype #%d\n",
1908 iph1->rmconf->certtype);
1909 return -1;
1910 }
1911
1912}
1913
1914/*
1915 * get a CERT from local file.
1916 * IN:
1917 * my != 0 my cert.
1918 * my == 0 peer's cert.
1919 */
1920static int
1921get_cert_fromlocal(iph1, my)
1922 struct ph1handle *iph1;
1923 int my;
1924{
85f41bec 1925#ifdef HAVE_OPENSSL
52b7d2ce 1926 char path[MAXPATHLEN];
85f41bec 1927#endif
52b7d2ce
A
1928 vchar_t *cert = NULL;
1929 cert_t **certpl;
1930 char *certfile;
1931 int error = -1;
fce29cd9 1932 cert_status_t status = CERT_STATUS_OK;
52b7d2ce
A
1933
1934 if (my) {
1935 certfile = iph1->rmconf->mycertfile;
1936 certpl = &iph1->cert;
1937 } else {
1938 certfile = iph1->rmconf->peerscertfile;
1939 certpl = &iph1->cert_p;
1940 }
52b7d2ce 1941 if (!certfile && iph1->rmconf->identity_in_keychain == 0) {
52b7d2ce
A
1942 plog(LLV_ERROR, LOCATION, NULL, "no CERT defined.\n");
1943 return 0;
1944 }
1945
1946 switch (iph1->rmconf->certtype) {
1947 case ISAKMP_CERT_X509SIGN:
52b7d2ce
A
1948 if (iph1->rmconf->identity_in_keychain) {
1949 CFDataRef dataRef;
1950
d1e348cf 1951 if (iph1->rmconf->keychainCertRef == NULL || base64toCFData(iph1->rmconf->keychainCertRef, &dataRef))
52b7d2ce 1952 goto end;
fce29cd9
A
1953 cert = crypto_cssm_get_x509cert(dataRef, &status);
1954 plog(LLV_DEBUG, LOCATION, NULL, "done with chking cert status %d\n",status);
52b7d2ce
A
1955 CFRelease(dataRef);
1956 break;
1957 } // else fall thru
e8d9021d 1958#ifdef HAVE_OPENSSL
52b7d2ce
A
1959 case ISAKMP_CERT_DNS:
1960 /* make public file name */
1961 getpathname(path, sizeof(path), LC_PATHTYPE_CERT, certfile);
1962 cert = eay_get_x509cert(path);
1963 if (cert) {
e8d9021d 1964 oakley_cert_prettyprint(cert);
52b7d2ce
A
1965 };
1966 break;
e8d9021d 1967#endif
52b7d2ce
A
1968 default:
1969 plog(LLV_ERROR, LOCATION, NULL,
1970 "not supported certtype %d\n",
1971 iph1->rmconf->certtype);
1972 goto end;
1973 }
1974
1975 if (!cert) {
1976 plog(LLV_ERROR, LOCATION, NULL,
1977 "failed to get %s CERT.\n",
1978 my ? "my" : "peers");
1979 goto end;
1980 }
1981
1982 *certpl = oakley_newcert();
1983 if (!*certpl) {
1984 plog(LLV_ERROR, LOCATION, NULL,
1985 "failed to get cert buffer.\n");
1986 goto end;
1987 }
1988 (*certpl)->pl = vmalloc(cert->l + 1);
1989 if ((*certpl)->pl == NULL) {
1990 plog(LLV_ERROR, LOCATION, NULL,
1991 "failed to get cert buffer\n");
1992 oakley_delcert(*certpl);
1993 *certpl = NULL;
1994 goto end;
1995 }
1996 memcpy((*certpl)->pl->v + 1, cert->v, cert->l);
1997 (*certpl)->pl->v[0] = iph1->rmconf->certtype;
1998 (*certpl)->type = iph1->rmconf->certtype;
fce29cd9 1999 (*certpl)->status = status;
52b7d2ce
A
2000 (*certpl)->cert.v = (*certpl)->pl->v + 1;
2001 (*certpl)->cert.l = (*certpl)->pl->l - 1;
2002
2003 plog(LLV_DEBUG, LOCATION, NULL, "created CERT payload:\n");
2004 plogdump(LLV_DEBUG, (*certpl)->pl->v, (*certpl)->pl->l);
e8d9021d
A
2005 oakley_cert_prettyprint(cert);
2006
52b7d2ce
A
2007 error = 0;
2008
2009end:
2010 if (cert != NULL)
2011 vfree(cert);
2012
2013 return error;
2014}
2015
52b7d2ce
A
2016
2017/* get signature */
2018int
2019oakley_getsign(iph1)
2020 struct ph1handle *iph1;
2021{
85f41bec 2022#ifdef HAVE_OPENSSL
52b7d2ce 2023 char path[MAXPATHLEN];
85f41bec 2024#endif
52b7d2ce
A
2025 vchar_t *privkey = NULL;
2026 int error = -1;
2027
2028 switch (iph1->rmconf->certtype) {
2029 case ISAKMP_CERT_X509SIGN:
52b7d2ce
A
2030 // cert in keychain - use cssm to sign
2031 if (iph1->rmconf->identity_in_keychain) {
2032 CFDataRef dataRef;
2033
d1e348cf 2034 if (iph1->rmconf->keychainCertRef == NULL || base64toCFData(iph1->rmconf->keychainCertRef, &dataRef))
52b7d2ce
A
2035 goto end;
2036 iph1->sig = crypto_cssm_getsign(dataRef, iph1->hash);
2037 CFRelease(dataRef);
2038 break;
2039 } // else fall thru
52b7d2ce
A
2040 default:
2041 plog(LLV_ERROR, LOCATION, NULL,
2042 "Unknown certtype #%d\n",
2043 iph1->rmconf->certtype);
2044 goto end;
2045 }
2046
2047 if (iph1->sig == NULL) {
2048 plog(LLV_ERROR, LOCATION, NULL, "failed to sign.\n");
2049 goto end;
2050 }
2051
2052 plog(LLV_DEBUG, LOCATION, NULL, "SIGN computed:\n");
2053 plogdump(LLV_DEBUG, iph1->sig->v, iph1->sig->l);
2054
2055 error = 0;
2056
2057end:
2058 if (privkey != NULL)
2059 vfree(privkey);
2060
2061 return error;
2062}
2063
e8d9021d
A
2064void
2065oakley_verify_certid(iph1)
2066struct ph1handle *iph1;
2067{
2068 if (iph1->rmconf->verify_cert &&
2069 oakley_check_certid(iph1, CERT_CHECKID_FROM_PEER)){
2070 plog(LLV_DEBUG, LOCATION, NULL,
2071 "Discarding CERT: does not match ID:\n");
2072 oakley_delcert(iph1->cert_p);
2073 iph1->cert_p = NULL;
2074 }
2075}
2076
2077static int
2078oakley_check_certid_in_certchain(certchain, idtype, idlen, id)
2079 cert_t *certchain;
2080 int idtype;
2081 int idlen;
2082 void *id;
2083{
2084 cert_t *p;
2085
2086 for (p = certchain; p; p = p->chain) {
2087 if (oakley_check_certid_1(&p->cert, idtype, idlen, id, &p->status) == 0) {
2088 return 0;
2089 }
2090 }
2091 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2092}
2093
2094cert_t *
2095oakley_get_peer_cert_from_certchain(iph1)
2096 struct ph1handle * iph1;
2097{
2098 cert_t *p;
2099 struct ipsecdoi_id_b *id_b;
2100 int idlen;
2101 void *peers_id;
2102
2103 if (!iph1->id_p || !iph1->cert_p) {
2104 plog(LLV_ERROR, LOCATION, NULL, "no ID nor CERT found.\n");
2105 return NULL;
2106 }
2107 if (!iph1->cert_p->chain) {
2108 // no chain: simply return the only cert
2109 return iph1->cert_p;
2110 }
2111
85f41bec 2112 id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)iph1->id_p->v;
e8d9021d
A
2113 peers_id = id_b + 1;
2114 idlen = iph1->id_p->l - sizeof(*id_b);
2115 for (p = iph1->cert_p; p; p = p->chain) {
2116 if (oakley_check_certid_1(&p->cert, id_b->type, idlen, peers_id, &p->status) == 0) {
2117 return p;
2118 }
2119 }
2120 return NULL;
2121}
52b7d2ce
A
2122
2123/*
2124 * compare certificate name and ID value.
2125 */
2126static int
2127oakley_check_certid(iph1, which_id)
2128 struct ph1handle *iph1;
2129 int which_id;
2130{
2131 struct ipsecdoi_id_b *id_b;
2132 int idlen;
2133 u_int8_t doi_type = 255;
2134 void *peers_id = NULL;
2135 struct genlist_entry *gpb = NULL;
2136
2137 if (which_id == CERT_CHECKID_FROM_PEER) {
2138 /* use ID from peer */
2139 if (iph1->id_p == NULL || iph1->cert_p == NULL) {
2140 plog(LLV_ERROR, LOCATION, NULL, "no ID nor CERT found.\n");
2141 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2142 }
85f41bec 2143 id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)iph1->id_p->v;
52b7d2ce
A
2144 doi_type = id_b->type;
2145 peers_id = id_b + 1;
2146 idlen = iph1->id_p->l - sizeof(*id_b);
2147
e8d9021d 2148 return oakley_check_certid_in_certchain(iph1->cert_p, doi_type, idlen, peers_id);
52b7d2ce
A
2149
2150 } else {
2151 /* use ID from remote configuration */
2152 /* check each ID in list */
2153 struct idspec *id_spec;
2154
2155 for (id_spec = genlist_next (iph1->rmconf->idvl_p, &gpb); id_spec; id_spec = genlist_next (0, &gpb)) {
2156
2157 if (id_spec->idtype == IDTYPE_ADDRESS) {
85f41bec 2158 switch ((ALIGNED_CAST(struct sockaddr_storage *)(id_spec->id->v))->ss_family) {
52b7d2ce
A
2159 case AF_INET:
2160 doi_type = IPSECDOI_ID_IPV4_ADDR;
2161 idlen = sizeof(struct in_addr);
85f41bec 2162 peers_id = &((ALIGNED_CAST(struct sockaddr_in *)(id_spec->id->v))->sin_addr.s_addr);
52b7d2ce
A
2163 break;
2164 #ifdef INET6
2165 case AF_INET6:
2166 doi_type = IPSECDOI_ID_IPV6_ADDR;
2167 idlen = sizeof(struct in6_addr);
85f41bec 2168 peers_id = &((ALIGNED_CAST(struct sockaddr_in6 *)(id_spec->id->v))->sin6_addr.s6_addr);
52b7d2ce
A
2169 break;
2170 #endif
2171 default:
2172 plog(LLV_ERROR, LOCATION, NULL,
2173 "unknown address type for peers identifier.\n");
2174 return ISAKMP_NTYPE_AUTHENTICATION_FAILED;
2175 break;
2176 }
2177
2178 } else {
2179 doi_type = idtype2doi(id_spec->idtype);
2180 peers_id = id_spec->id->v;
2181 idlen = id_spec->id->l;
2182 }
e8d9021d 2183 if (oakley_check_certid_in_certchain(iph1->cert_p, doi_type, idlen, peers_id) == 0)
52b7d2ce
A
2184 return 0;
2185 }
e8d9021d 2186 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
52b7d2ce
A
2187 }
2188}
2189
2190static int
e8d9021d
A
2191oakley_check_certid_1(cert, idtype, idlen, id, certStatus)
2192 vchar_t *cert;
52b7d2ce
A
2193 int idtype;
2194 int idlen;
2195 void *id;
e8d9021d 2196 cert_status_t *certStatus;
52b7d2ce
A
2197{
2198
85f41bec 2199 int len;
52b7d2ce
A
2200 int error;
2201
85f41bec
A
2202#if !TARGET_OS_EMBEDDED
2203 int type;
2204 vchar_t *name = NULL;
2205 char *altname = NULL;
2206#endif
2207
52b7d2ce
A
2208 switch (idtype) {
2209 case IPSECDOI_ID_DER_ASN1_DN:
e8d9021d
A
2210#if TARGET_OS_EMBEDDED
2211 {
2212 SecCertificateRef certificate;
2213 CFDataRef subject;
2214 UInt8* namePtr;
2215
2216 certificate = crypto_cssm_x509cert_get_SecCertificateRef(cert);
2217 if (certificate == NULL) {
2218 plog(LLV_ERROR, LOCATION, NULL, "failed to get SecCertificateRef\n");
2219 if (certStatus && !*certStatus) {
2220 *certStatus = CERT_STATUS_INVALID;
2221 }
2222 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2223 }
2224 subject = SecCertificateCopySubjectSequence(certificate);
2225 if (subject == NULL) {
2226 plog(LLV_ERROR, LOCATION, NULL, "failed to get subjectName\n");
2227 if (certStatus && !*certStatus) {
2228 *certStatus = CERT_STATUS_INVALID_SUBJNAME;
2229 }
2230 CFRelease(certificate);
2231 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2232 }
2233 len = CFDataGetLength(subject);
2234 namePtr = CFDataGetBytePtr(subject);
2235 if (idlen != len) {
2236 plog(LLV_ERROR, LOCATION, NULL, "Invalid ID length in phase 1.\n");
2237 if (certStatus && !*certStatus) {
2238 *certStatus = CERT_STATUS_INVALID_SUBJNAME;
2239 }
2240 CFRelease(subject);
2241 CFRelease(certificate);
2242 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2243 }
2244 error = memcmp(id, namePtr, idlen);
2245 if (error != 0) {
2246 plog(LLV_ERROR, LOCATION, NULL,
2247 "ID mismatched with subjectName.\n");
2248 plog(LLV_ERROR, LOCATION, NULL,
2249 "subjectName (type %s):\n",
2250 s_ipsecdoi_ident(idtype));
2251 plogdump(LLV_ERROR, namePtr, len);
2252 plog(LLV_ERROR, LOCATION, NULL,
2253 "ID:\n");
2254 plogdump(LLV_ERROR, id, idlen);
2255 if (certStatus && !*certStatus) {
2256 *certStatus = CERT_STATUS_INVALID_SUBJNAME;
2257 }
2258 CFRelease(certificate);
2259 CFRelease(subject);
2260 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2261 }
85f41bec
A
2262 CFRelease(certificate);
2263 CFRelease(subject);
e8d9021d
A
2264 }
2265#else
2266 name = eay_get_x509asn1subjectname(cert);
52b7d2ce
A
2267 if (!name) {
2268 plog(LLV_ERROR, LOCATION, NULL,
2269 "failed to get subjectName\n");
e8d9021d
A
2270 if (certStatus && !*certStatus) {
2271 *certStatus = CERT_STATUS_INVALID_SUBJNAME;
2272 }
52b7d2ce
A
2273 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2274 }
2275 if (idlen != name->l) {
2276 plog(LLV_ERROR, LOCATION, NULL,
2277 "Invalid ID length in phase 1.\n");
2278 vfree(name);
e8d9021d
A
2279 if (certStatus && !*certStatus) {
2280 *certStatus = CERT_STATUS_INVALID_SUBJNAME;
2281 }
52b7d2ce
A
2282 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2283 }
2284 error = memcmp(id, name->v, idlen);
52b7d2ce
A
2285 if (error != 0) {
2286 plog(LLV_ERROR, LOCATION, NULL,
2287 "ID mismatched with subjectName.\n");
e8d9021d
A
2288 plog(LLV_ERROR, LOCATION, NULL,
2289 "subjectName (type %s):\n",
2290 s_ipsecdoi_ident(idtype));
2291 plogdump(LLV_ERROR, name->v, name->l);
2292 plog(LLV_ERROR, LOCATION, NULL,
2293 "ID:\n");
2294 plogdump(LLV_ERROR, id, idlen);
2295 vfree(name);
2296 if (certStatus && !*certStatus) {
2297 *certStatus = CERT_STATUS_INVALID_SUBJNAME;
2298 }
52b7d2ce
A
2299 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2300 }
e8d9021d
A
2301 vfree(name);
2302#endif
52b7d2ce 2303 return 0;
e8d9021d 2304
52b7d2ce
A
2305 case IPSECDOI_ID_IPV4_ADDR:
2306 case IPSECDOI_ID_IPV6_ADDR:
2307 {
e8d9021d
A
2308#if TARGET_OS_EMBEDDED
2309 CFIndex pos, count;
2310 SecCertificateRef certificate;
2311 CFArrayRef addresses;
85f41bec 2312#define ADDRESS_BUF_SIZE 64
e8d9021d
A
2313
2314 certificate = crypto_cssm_x509cert_get_SecCertificateRef(cert);
2315 if (certificate == NULL) {
2316 plog(LLV_ERROR, LOCATION, NULL,
2317 "failed to get SecCertificateRef\n");
2318 if (certStatus && !*certStatus) {
2319 *certStatus = CERT_STATUS_INVALID;
2320 }
2321 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2322 }
2323 addresses = SecCertificateCopyIPAddresses(certificate);
2324 if (addresses == NULL) {
2325 plog(LLV_ERROR, LOCATION, NULL, "failed to get subjectName\n");
2326 if (certStatus && !*certStatus) {
2327 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2328 }
2329 CFRelease(certificate);
2330 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2331 }
2332 count = CFArrayGetCount(addresses);
2333 for (pos = 0; pos < count; pos++) {
2334
2335 CFStringRef address;
2336 CFIndex addressLen;
2337 char *addressBuf, numAddress[128];
2338 int result;
2339
2340 address = CFArrayGetValueAtIndex(addresses, pos);
2341 addressLen = CFStringGetLength(address);
2342 if (addressLen == 0)
2343 continue;
85f41bec 2344 addressBuf = racoon_malloc(ADDRESS_BUF_SIZE);
e8d9021d
A
2345 if (addressBuf == NULL) {
2346 plog(LLV_ERROR, LOCATION, NULL, "out of memory\n");
85f41bec
A
2347 CFRelease(addresses);
2348 CFRelease(certificate);
e8d9021d
A
2349 return -1;
2350 }
85f41bec 2351 if (CFStringGetCString(address, addressBuf, ADDRESS_BUF_SIZE, kCFStringEncodingUTF8) == TRUE) {
e8d9021d
A
2352 result = inet_pton(idtype == IPSECDOI_ID_IPV4_ADDR ? AF_INET : AF_INET6, addressBuf, numAddress);
2353 racoon_free(addressBuf);
2354 if (result == 0)
2355 continue; // wrong type or invalid address
85f41bec 2356 if (!memcmp(id, numAddress, idtype == IPSECDOI_ID_IPV4_ADDR ? 32 : 128) == 0) { // found a match ?
e8d9021d
A
2357 CFRelease(addresses);
2358 CFRelease(certificate);
2359 return 0;
2360 }
2361 } else
2362 racoon_free(addressBuf);
2363 }
2364 plog(LLV_ERROR, LOCATION, NULL, "ID mismatched with subjectAltName.\n");
2365 plog(LLV_ERROR, LOCATION, NULL,
2366 "subjectAltName (expected type %s):\n", s_ipsecdoi_ident(idtype));
2367 plog(LLV_ERROR, LOCATION, NULL, "ID:\n");
2368 plogdump(LLV_ERROR, id, idlen);
2369 CFRelease(addresses);
2370 CFRelease(certificate);
2371 if (certStatus && !*certStatus) {
2372 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2373 }
2374 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2375#else
52b7d2ce
A
2376 /*
2377 * Openssl returns the IPAddress as an ASN1 octet string (binary format)
2378 * followed by a trailing NULL. 5 bytes for IPv4 and 17 bytes for IPv6
2379 */
2380 #define SUBJ_ALT_NAME_IPV4_ADDRESS_LEN 5
2381 #define SUBJ_ALT_NAME_IPV6_ADDRESS_LEN 17
2382
2383 int pos;
2384
2385 if (idtype == IPSECDOI_ID_IPV4_ADDR && idlen != sizeof(struct in_addr)
2386 || idtype == IPSECDOI_ID_IPV6_ADDR && idlen != sizeof(struct in6_addr)) {
2387 plog(LLV_ERROR, LOCATION, NULL,
2388 "invalid address length passed.\n");
2389 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2390 }
2391
2392 for (pos = 1; ; pos++) {
e8d9021d 2393 if (eay_get_x509subjectaltname(cert, &altname, &type, pos, &len) !=0) {
52b7d2ce
A
2394 plog(LLV_ERROR, LOCATION, NULL,
2395 "failed to get subjectAltName\n");
e8d9021d
A
2396 if (certStatus && !*certStatus) {
2397 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2398 }
52b7d2ce
A
2399 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2400 }
2401
2402 /* it's the end condition of the loop. */
2403 if (!altname) {
e8d9021d
A
2404 plog(LLV_ERROR, LOCATION, NULL,
2405 "invalid subjectAltName\n");
2406 if (certStatus && !*certStatus) {
2407 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2408 }
52b7d2ce
A
2409 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2410 }
2411
2412 if (check_typeofcertname(idtype, type) != 0) {
2413 /* wrong type - skip this one */
2414 racoon_free(altname);
2415 altname = NULL;
2416 continue;
2417 }
2418
2419 if (len == SUBJ_ALT_NAME_IPV4_ADDRESS_LEN) { /* IPv4 */
2420 if (idtype != IPSECDOI_ID_IPV4_ADDR) {
2421 /* wrong IP address type - skip this one */
2422 racoon_free(altname);
2423 altname = NULL;
2424 continue;
2425 }
2426 }
2427#ifdef INET6
2428 else if (len == SUBJ_ALT_NAME_IPV6_ADDRESS_LEN) { /* IPv6 */
2429 if (idtype != IPSECDOI_ID_IPV6_ADDR) {
2430 /* wrong IP address type - skip this one */
2431 racoon_free(altname);
2432 altname = NULL;
2433 continue;
2434 }
2435 }
2436#endif
2437 else {
2438 /* invalid IP address length in certificate - bad or bogus certificate */
2439 plog(LLV_ERROR, LOCATION, NULL,
2440 "invalid IP address in certificate.\n");
e8d9021d
A
2441 plog(LLV_ERROR, LOCATION, NULL,
2442 "subjectAltName (expected type %s, got type %s):\n",
2443 s_ipsecdoi_ident(idtype),
2444 s_ipsecdoi_ident(type));
2445 plogdump(LLV_ERROR, altname, len);
52b7d2ce
A
2446 racoon_free(altname);
2447 altname = NULL;
e8d9021d
A
2448 if (certStatus && !*certStatus) {
2449 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2450 }
52b7d2ce
A
2451 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2452 }
2453
2454 /* compare the addresses */
2455 error = memcmp(id, altname, idlen);
e8d9021d 2456 if (error)
52b7d2ce 2457 continue;
52b7d2ce 2458 racoon_free(altname);
52b7d2ce 2459 return 0;
e8d9021d
A
2460 }
2461 /* failed to find a match */
52b7d2ce 2462 plog(LLV_ERROR, LOCATION, NULL,
e8d9021d
A
2463 "ID mismatched with subjectAltName.\n");
2464 plog(LLV_ERROR, LOCATION, NULL,
2465 "subjectAltName (expected type %s, got type %s):\n",
2466 s_ipsecdoi_ident(idtype),
2467 s_ipsecdoi_ident(type));
2468 plogdump(LLV_ERROR, altname, len);
2469 plog(LLV_ERROR, LOCATION, NULL,
2470 "ID:\n");
2471 plogdump(LLV_ERROR, id, idlen);
2472 racoon_free(altname);
2473 if (certStatus && !*certStatus)
2474 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
52b7d2ce 2475 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
e8d9021d
A
2476
2477#endif /* TARGET_OS_EMBEDDED */
52b7d2ce
A
2478 }
2479
e8d9021d
A
2480#if TARGET_OS_EMBEDDED
2481 case IPSECDOI_ID_FQDN:
2482 {
2483 CFIndex pos, count;
2484 SecCertificateRef certificate;
2485 CFArrayRef names;
2486 CFStringRef name, ID;
2487
2488 certificate = crypto_cssm_x509cert_get_SecCertificateRef(cert);
2489 if (certificate == NULL) {
52b7d2ce 2490 plog(LLV_ERROR, LOCATION, NULL,
e8d9021d
A
2491 "failed to get SecCertificateRef\n");
2492 if (certStatus && !*certStatus) {
2493 *certStatus = CERT_STATUS_INVALID;
2494 }
52b7d2ce
A
2495 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2496 }
e8d9021d
A
2497 names = SecCertificateCopyDNSNames(certificate);
2498 if (names == NULL) {
52b7d2ce 2499 plog(LLV_ERROR, LOCATION, NULL,
e8d9021d
A
2500 "failed to get subjectName\n");
2501 if (certStatus && !*certStatus) {
2502 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2503 }
2504 CFRelease(certificate);
2505 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
52b7d2ce 2506 }
e8d9021d
A
2507 count = CFArrayGetCount(names);
2508 ID = CFStringCreateWithCString(NULL, id, kCFStringEncodingUTF8);
2509 if (ID== NULL) {
2510 plog(LLV_ERROR, LOCATION, NULL, "memory error\n");
2511 CFRelease(names);
2512 CFRelease(certificate);
2513
52b7d2ce 2514 }
e8d9021d
A
2515 for (pos = 0; pos < count; pos++) {
2516 name = CFArrayGetValueAtIndex(names, pos);
2517 if (CFStringCompare(name, ID, 0) == kCFCompareEqualTo) {
2518 CFRelease(ID);
2519 CFRelease(names);
2520 CFRelease(certificate);
2521 return 0;
52b7d2ce 2522 }
52b7d2ce 2523 }
e8d9021d
A
2524 plog(LLV_ERROR, LOCATION, NULL, "ID mismatched with subjectAltName.\n");
2525 plog(LLV_ERROR, LOCATION, NULL,
2526 "subjectAltName (expected type %s):\n", s_ipsecdoi_ident(idtype));
2527 plog(LLV_ERROR, LOCATION, NULL, "ID:\n");
2528 plogdump(LLV_ERROR, id, idlen);
2529 CFRelease(ID);
2530 CFRelease(names);
2531 CFRelease(certificate);
2532 if (certStatus && !*certStatus) {
2533 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2534 }
2535 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2536 }
2537
2538 case IPSECDOI_ID_USER_FQDN:
2539 {
2540 CFIndex pos, count;
2541
2542 SecCertificateRef certificate;
2543 CFArrayRef names;
2544 CFStringRef name, ID;
2545
2546 certificate = crypto_cssm_x509cert_get_SecCertificateRef(cert);
2547 if (certificate == NULL) {
52b7d2ce 2548 plog(LLV_ERROR, LOCATION, NULL,
e8d9021d
A
2549 "failed to get SecCertificateRef\n");
2550 if (certStatus && !*certStatus) {
2551 *certStatus = CERT_STATUS_INVALID;
2552 }
52b7d2ce
A
2553 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2554 }
e8d9021d
A
2555 names = SecCertificateCopyRFC822Names(certificate);
2556 if (names == NULL) {
52b7d2ce 2557 plog(LLV_ERROR, LOCATION, NULL,
e8d9021d
A
2558 "failed to get subjectName\n");
2559 if (certStatus && !*certStatus) {
2560 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2561 }
2562 CFRelease(certificate);
52b7d2ce
A
2563 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2564 }
e8d9021d
A
2565 count = CFArrayGetCount(names);
2566 ID = CFStringCreateWithCString(NULL, id, kCFStringEncodingUTF8);
2567 if (ID == NULL) {
52b7d2ce 2568 plog(LLV_ERROR, LOCATION, NULL,
e8d9021d
A
2569 "memory error\n");
2570 if (certStatus && !*certStatus) {
2571 *certStatus = CERT_STATUS_INVALID;
2572 }
2573 CFRelease(names);
2574 CFRelease(certificate);
2575 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2576 }
2577 for (pos = 0; pos < count; pos++) {
2578 name = CFArrayGetValueAtIndex(names, pos);
2579 if (CFStringCompare(name, ID, 0) == kCFCompareEqualTo) {
2580 CFRelease(ID);
2581 CFRelease(names);
2582 CFRelease(certificate);
2583 return 0;
2584 }
52b7d2ce 2585 }
e8d9021d
A
2586 plog(LLV_ERROR, LOCATION, NULL, "ID mismatched with subjectAltName.\n");
2587 plog(LLV_ERROR, LOCATION, NULL,
2588 "subjectAltName (expected type %s):\n", s_ipsecdoi_ident(idtype));
2589 plog(LLV_ERROR, LOCATION, NULL, "ID:\n");
2590 plogdump(LLV_ERROR, id, idlen);
2591 CFRelease(ID);
2592 CFRelease(names);
2593 CFRelease(certificate);
2594 if (certStatus && !*certStatus) {
2595 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2596 }
2597 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
52b7d2ce 2598 }
e8d9021d 2599#else
52b7d2ce
A
2600 case IPSECDOI_ID_FQDN:
2601 case IPSECDOI_ID_USER_FQDN:
2602 {
2603 int pos;
2604
2605 for (pos = 1; ; pos++) {
e8d9021d 2606 if (eay_get_x509subjectaltname(cert, &altname, &type, pos, &len) != 0) {
52b7d2ce
A
2607 plog(LLV_ERROR, LOCATION, NULL,
2608 "failed to get subjectAltName\n");
e8d9021d
A
2609 if (certStatus && !*certStatus) {
2610 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2611 }
52b7d2ce
A
2612 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2613 }
2614
2615 /* it's the end condition of the loop. */
2616 if (!altname) {
2617 plog(LLV_ERROR, LOCATION, NULL,
e8d9021d
A
2618 "invalid subjectAltName\n");
2619 if (certStatus && !*certStatus) {
2620 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2621 }
2622 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
52b7d2ce
A
2623 }
2624
e8d9021d
A
2625 if (check_typeofcertname(idtype, type) != 0) {
2626 /* wrong general type - skip this one */
2627 racoon_free(altname);
2628 altname = NULL;
2629 continue;
2630 }
52b7d2ce 2631
e8d9021d
A
2632 if (idlen != strlen(altname)) {
2633 /* wrong length - skip this one */
2634 racoon_free(altname);
2635 altname = NULL;
2636 continue;
2637 }
2638 error = memcmp(id, altname, idlen);
2639 if (error)
2640 continue;
52b7d2ce 2641 racoon_free(altname);
e8d9021d 2642 return 0;
52b7d2ce 2643 }
e8d9021d
A
2644 plog(LLV_ERROR, LOCATION, NULL, "ID mismatched with subjectAltName.\n");
2645 plog(LLV_ERROR, LOCATION, NULL,
2646 "subjectAltName (expected type %s, got type %s):\n",
2647 s_ipsecdoi_ident(idtype),
2648 s_ipsecdoi_ident(type));
2649 plogdump(LLV_ERROR, altname, len);
2650 plog(LLV_ERROR, LOCATION, NULL,
2651 "ID:\n");
2652 plogdump(LLV_ERROR, id, idlen);
52b7d2ce 2653 racoon_free(altname);
e8d9021d
A
2654 if (certStatus && !*certStatus)
2655 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2656 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
52b7d2ce 2657 }
e8d9021d 2658#endif
52b7d2ce
A
2659 default:
2660 plog(LLV_ERROR, LOCATION, NULL,
2661 "Impropper ID type passed: %s.\n",
e8d9021d 2662 s_ipsecdoi_ident(idtype));
52b7d2ce 2663 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
e8d9021d 2664 }
52b7d2ce
A
2665 /*NOTREACHED*/
2666}
e8d9021d 2667#ifdef HAVE_OPENSSL
52b7d2ce
A
2668static int
2669check_typeofcertname(doi, genid)
2670 int doi, genid;
2671{
2672 switch (doi) {
2673 case IPSECDOI_ID_IPV4_ADDR:
2674 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
2675 case IPSECDOI_ID_IPV6_ADDR:
2676 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
2677 case IPSECDOI_ID_IPV4_ADDR_RANGE:
2678 case IPSECDOI_ID_IPV6_ADDR_RANGE:
2679 if (genid != GENT_IPADD)
2680 return -1;
2681 return 0;
2682 case IPSECDOI_ID_FQDN:
2683 if (genid != GENT_DNS)
2684 return -1;
2685 return 0;
2686 case IPSECDOI_ID_USER_FQDN:
2687 if (genid != GENT_EMAIL)
2688 return -1;
2689 return 0;
2690 case IPSECDOI_ID_DER_ASN1_DN: /* should not be passed to this function*/
2691 case IPSECDOI_ID_DER_ASN1_GN:
2692 case IPSECDOI_ID_KEY_ID:
2693 default:
2694 return -1;
2695 }
2696 /*NOTREACHED*/
2697}
e8d9021d 2698#endif
52b7d2ce
A
2699
2700/*
2701 * save certificate including certificate type.
2702 */
2703int
2704oakley_savecert(iph1, gen)
2705 struct ph1handle *iph1;
2706 struct isakmp_gen *gen;
2707{
2708 cert_t **c;
2709 u_int8_t type;
e8d9021d 2710#ifdef HAVE_OPENSSL
52b7d2ce
A
2711 STACK_OF(X509) *certs=NULL;
2712 PKCS7 *p7;
e8d9021d 2713#endif
52b7d2ce
A
2714 type = *(u_int8_t *)(gen + 1) & 0xff;
2715
2716 switch (type) {
2717 case ISAKMP_CERT_DNS:
2718 plog(LLV_WARNING, LOCATION, NULL,
2719 "CERT payload is unnecessary in DNSSEC. "
2720 "ignore this CERT payload.\n");
2721 return 0;
2722 case ISAKMP_CERT_PKCS7:
2723 case ISAKMP_CERT_PGP:
2724 case ISAKMP_CERT_X509SIGN:
2725 case ISAKMP_CERT_KERBEROS:
2726 case ISAKMP_CERT_SPKI:
2727 c = &iph1->cert_p;
2728 break;
2729 case ISAKMP_CERT_CRL:
2730 c = &iph1->crl_p;
2731 break;
2732 case ISAKMP_CERT_X509KE:
2733 case ISAKMP_CERT_X509ATTR:
2734 case ISAKMP_CERT_ARL:
2735 plog(LLV_ERROR, LOCATION, NULL,
2736 "No supported such CERT type %d\n", type);
2737 return -1;
2738 default:
2739 plog(LLV_ERROR, LOCATION, NULL,
2740 "Invalid CERT type %d\n", type);
2741 return -1;
2742 }
2743
52b7d2ce
A
2744 if (*c) {
2745 plog(LLV_WARNING, LOCATION, NULL,
e8d9021d 2746 "preexisting CERT payload... chaining.\n");
52b7d2ce 2747 }
e8d9021d 2748#ifdef HAVE_OPENSSL
52b7d2ce
A
2749 if (type == ISAKMP_CERT_PKCS7) {
2750 u_char *bp;
2751 int i;
2752
2753 /* Skip the header */
2754 bp = (u_char *)(gen + 1);
2755 /* And the first byte is the certificate type,
2756 * we know that already
2757 */
2758 bp++;
2759 p7 = d2i_PKCS7(NULL, (void *)&bp,
2760 ntohs(gen->len) - sizeof(*gen) - 1);
2761
2762 if (!p7) {
2763 plog(LLV_ERROR, LOCATION, NULL,
2764 "Failed to parse PKCS#7 CERT.\n");
2765 return -1;
2766 }
2767
2768 /* Copied this from the openssl pkcs7 application;
2769 * there"s little by way of documentation for any of
2770 * it. I can only presume it"s correct.
2771 */
2772
2773 i = OBJ_obj2nid(p7->type);
2774 switch (i) {
2775 case NID_pkcs7_signed:
2776 certs=p7->d.sign->cert;
2777 break;
2778 case NID_pkcs7_signedAndEnveloped:
2779 certs=p7->d.signed_and_enveloped->cert;
2780 break;
2781 default:
2782 break;
2783 }
2784
2785 if (!certs) {
2786 plog(LLV_ERROR, LOCATION, NULL,
2787 "CERT PKCS#7 bundle contains no certs.\n");
2788 PKCS7_free(p7);
2789 return -1;
2790 }
2791
2792 for (i = 0; i < sk_X509_num(certs); i++) {
2793 int len;
2794 u_char *bp;
e8d9021d 2795 cert_t *new;
52b7d2ce
A
2796 X509 *cert = sk_X509_value(certs,i);
2797
2798 plog(LLV_DEBUG, LOCATION, NULL,
2799 "Trying PKCS#7 cert %d.\n", i);
2800
2801 /* We'll just try each cert in turn */
e8d9021d
A
2802 new = save_certx509(cert);
2803 if (!new) {
52b7d2ce
A
2804 plog(LLV_ERROR, LOCATION, NULL,
2805 "Failed to get CERT buffer.\n");
2806 continue;
2807 }
e8d9021d
A
2808 *c = oakley_appendcert_to_certchain(*c, new);
2809 plog(LLV_DEBUG, LOCATION, NULL, "CERT saved:\n");
2810 plogdump(LLV_DEBUG, new->cert.v, new->cert.l);
2811 oakley_cert_prettyprint(&new->cert);
52b7d2ce
A
2812 }
2813 PKCS7_free(p7);
2814
e8d9021d
A
2815 } else
2816#endif
2817 {
2818 cert_t *new;
2819 new = save_certbuf(gen);
2820 if (!new) {
52b7d2ce
A
2821 plog(LLV_ERROR, LOCATION, NULL,
2822 "Failed to get CERT buffer.\n");
2823 return -1;
2824 }
2825
e8d9021d 2826 switch (new->type) {
52b7d2ce
A
2827 case ISAKMP_CERT_DNS:
2828 plog(LLV_WARNING, LOCATION, NULL,
2829 "CERT payload is unnecessary in DNSSEC. "
2830 "ignore it.\n");
2831 return 0;
2832 case ISAKMP_CERT_PGP:
2833 case ISAKMP_CERT_X509SIGN:
2834 case ISAKMP_CERT_KERBEROS:
2835 case ISAKMP_CERT_SPKI:
2836 /* Ignore cert if it doesn't match identity
2837 * XXX If verify cert is disabled, we still just take
2838 * the first certificate....
2839 */
e8d9021d
A
2840 *c = oakley_appendcert_to_certchain(*c, new);
2841 plog(LLV_DEBUG, LOCATION, NULL, "CERT saved:\n");
2842 plogdump(LLV_DEBUG, new->cert.v, new->cert.l);
2843 oakley_cert_prettyprint(&new->cert);
52b7d2ce
A
2844 break;
2845 case ISAKMP_CERT_CRL:
e8d9021d 2846 *c = oakley_appendcert_to_certchain(*c, new);
52b7d2ce 2847 plog(LLV_DEBUG, LOCATION, NULL, "CRL saved:\n");
e8d9021d
A
2848 plogdump(LLV_DEBUG, new->cert.v, new->cert.l);
2849 oakley_cert_prettyprint(&new->cert);
52b7d2ce
A
2850 break;
2851 case ISAKMP_CERT_X509KE:
2852 case ISAKMP_CERT_X509ATTR:
2853 case ISAKMP_CERT_ARL:
2854 default:
2855 /* XXX */
e8d9021d 2856 oakley_delcert(new);
52b7d2ce
A
2857 return 0;
2858 }
2859 }
2860
2861 return 0;
2862}
2863
2864/*
2865 * save certificate including certificate type.
2866 */
2867int
2868oakley_savecr(iph1, gen)
2869 struct ph1handle *iph1;
2870 struct isakmp_gen *gen;
2871{
2872 cert_t **c;
2873 u_int8_t type;
e8d9021d 2874 cert_t *new;
52b7d2ce
A
2875
2876 type = *(u_int8_t *)(gen + 1) & 0xff;
2877
2878 switch (type) {
2879 case ISAKMP_CERT_DNS:
2880 plog(LLV_WARNING, LOCATION, NULL,
2881 "CERT payload is unnecessary in DNSSEC\n");
2882 /*FALLTHRU*/
2883 case ISAKMP_CERT_PKCS7:
2884 case ISAKMP_CERT_PGP:
2885 case ISAKMP_CERT_X509SIGN:
2886 case ISAKMP_CERT_KERBEROS:
2887 case ISAKMP_CERT_SPKI:
e97d2cf9
A
2888 if (iph1->cr_p) {
2889 oakley_delcert(iph1->cr_p);
2890 iph1->cr_p = NULL;
2891 }
52b7d2ce
A
2892 c = &iph1->cr_p;
2893 break;
2894 case ISAKMP_CERT_X509KE:
2895 case ISAKMP_CERT_X509ATTR:
2896 case ISAKMP_CERT_ARL:
2897 plog(LLV_ERROR, LOCATION, NULL,
2898 "No supported such CR type %d\n", type);
2899 return -1;
2900 case ISAKMP_CERT_CRL:
2901 default:
2902 plog(LLV_ERROR, LOCATION, NULL,
2903 "Invalid CR type %d\n", type);
2904 return -1;
2905 }
2906
e8d9021d
A
2907 new = save_certbuf(gen);
2908 if (!new) {
52b7d2ce
A
2909 plog(LLV_ERROR, LOCATION, NULL,
2910 "Failed to get CR buffer.\n");
2911 return -1;
2912 }
e8d9021d 2913 *c = oakley_appendcert_to_certchain(*c, new);
52b7d2ce 2914 plog(LLV_DEBUG, LOCATION, NULL, "CR saved:\n");
e8d9021d 2915 plogdump(LLV_DEBUG, new->cert.v, new->cert.l);
52b7d2ce
A
2916
2917 return 0;
2918}
2919
2920static cert_t *
2921save_certbuf(gen)
2922 struct isakmp_gen *gen;
2923{
2924 cert_t *new;
2925
d1e348cf
A
2926 if(ntohs(gen->len) <= sizeof(*gen)){
2927 plog(LLV_ERROR, LOCATION, NULL,
2928 "Len is too small !!.\n");
2929 return NULL;
2930 }
2931
52b7d2ce
A
2932 new = oakley_newcert();
2933 if (!new) {
2934 plog(LLV_ERROR, LOCATION, NULL,
2935 "Failed to get CERT buffer.\n");
2936 return NULL;
2937 }
2938
2939 new->pl = vmalloc(ntohs(gen->len) - sizeof(*gen));
2940 if (new->pl == NULL) {
2941 plog(LLV_ERROR, LOCATION, NULL,
2942 "Failed to copy CERT from packet.\n");
2943 oakley_delcert(new);
2944 new = NULL;
2945 return NULL;
2946 }
2947 memcpy(new->pl->v, gen + 1, new->pl->l);
2948 new->type = new->pl->v[0] & 0xff;
2949 new->cert.v = new->pl->v + 1;
2950 new->cert.l = new->pl->l - 1;
2951
2952 return new;
2953}
2954
e8d9021d 2955#ifdef HAVE_OPENSSL
52b7d2ce
A
2956static cert_t *
2957save_certx509(cert)
2958 X509 *cert;
2959{
2960 cert_t *new;
2961 int len;
2962 u_char *bp;
2963
2964 new = oakley_newcert();
2965 if (!new) {
2966 plog(LLV_ERROR, LOCATION, NULL,
2967 "Failed to get CERT buffer.\n");
2968 return NULL;
2969 }
2970
2971 len = i2d_X509(cert, NULL);
2972 new->pl = vmalloc(len);
2973 if (new->pl == NULL) {
2974 plog(LLV_ERROR, LOCATION, NULL,
2975 "Failed to copy CERT from packet.\n");
2976 oakley_delcert(new);
2977 new = NULL;
2978 return NULL;
2979 }
2980 bp = (u_char *) new->pl->v;
2981 len = i2d_X509(cert, &bp);
2982 new->type = ISAKMP_CERT_X509SIGN;
2983 new->cert.v = new->pl->v;
2984 new->cert.l = new->pl->l;
2985
2986 return new;
2987}
e8d9021d 2988#endif
52b7d2ce
A
2989
2990/*
2991 * get my CR.
2992 * NOTE: No Certificate Authority field is included to CR payload at the
2993 * moment. Becuase any certificate authority are accepted without any check.
2994 * The section 3.10 in RFC2408 says that this field SHOULD not be included,
2995 * if there is no specific certificate authority requested.
2996 */
2997vchar_t *
2998oakley_getcr(iph1)
2999 struct ph1handle *iph1;
3000{
3001 vchar_t *buf;
3002
3003 buf = vmalloc(1);
3004 if (buf == NULL) {
3005 plog(LLV_ERROR, LOCATION, NULL,
3006 "failed to get cr buffer\n");
3007 return NULL;
3008 }
d1e348cf
A
3009 if(iph1->rmconf->certtype == ISAKMP_CERT_NONE) {
3010 buf->v[0] = iph1->rmconf->cacerttype;
3011 plog(LLV_DEBUG, LOCATION, NULL, "create my CR: NONE, using %s instead\n",
3012 s_isakmp_certtype(iph1->rmconf->cacerttype));
3013 } else {
3014 buf->v[0] = iph1->rmconf->certtype;
3015 plog(LLV_DEBUG, LOCATION, NULL, "create my CR: %s\n",
52b7d2ce 3016 s_isakmp_certtype(iph1->rmconf->certtype));
d1e348cf 3017 }
52b7d2ce
A
3018 if (buf->l > 1)
3019 plogdump(LLV_DEBUG, buf->v, buf->l);
3020
3021 return buf;
3022}
3023
3024/*
3025 * check peer's CR.
3026 */
3027int
3028oakley_checkcr(iph1)
3029 struct ph1handle *iph1;
3030{
3031 if (iph1->cr_p == NULL)
3032 return 0;
3033
3034 plog(LLV_DEBUG, LOCATION, iph1->remote,
3035 "peer transmitted CR: %s\n",
3036 s_isakmp_certtype(iph1->cr_p->type));
3037
3038 if (iph1->cr_p->type != iph1->rmconf->certtype) {
3039 plog(LLV_ERROR, LOCATION, iph1->remote,
3040 "such a cert type isn't supported: %d\n",
3041 (char)iph1->cr_p->type);
3042 return -1;
3043 }
3044
3045 return 0;
3046}
3047
3048/*
3049 * check to need CR payload.
3050 */
3051int
3052oakley_needcr(type)
3053 int type;
3054{
3055 switch (type) {
3056 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
3057 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
3058#ifdef ENABLE_HYBRID
3059 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
3060 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
d1e348cf
A
3061 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
3062 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
3063 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
3064 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
52b7d2ce
A
3065#endif
3066 return 1;
3067 default:
3068 return 0;
3069 }
3070 /*NOTREACHED*/
3071}
3072
85f41bec
A
3073vchar_t *
3074oakley_getpskall(iph1)
3075struct ph1handle *iph1;
3076{
3077 vchar_t *secret = NULL;
3078
3079 if (iph1->rmconf->shared_secret) {
3080
3081 switch (iph1->rmconf->secrettype) {
3082 case SECRETTYPE_KEY:
3083 /* in psk file - use KEY from remote configuration to locate it */
3084 secret = getpsk(iph1->rmconf->shared_secret->v, iph1->rmconf->shared_secret->l-1);
3085 break;
3086#if HAVE_KEYCHAIN
3087 case SECRETTYPE_KEYCHAIN:
3088 /* in the system keychain */
3089 secret = getpskfromkeychain(iph1->rmconf->shared_secret->v, iph1->etype, iph1->rmconf->secrettype, NULL);
3090 break;
3091 case SECRETTYPE_KEYCHAIN_BY_ID:
3092 /* in the system keychain - use peer id */
3093 secret = getpskfromkeychain(iph1->rmconf->shared_secret->v, iph1->etype, iph1->rmconf->secrettype, iph1->id_p);
3094 break;
3095#endif // HAVE_KEYCHAIN
3096 case SECRETTYPE_USE:
3097 /* in the remote configuration */
3098 default:
3099 /* rmconf->shared_secret is a string and contains a NULL character that must be removed */
3100 secret = vmalloc(iph1->rmconf->shared_secret->l - 1);
3101 if (secret == NULL) {
3102 plog(LLV_ERROR, LOCATION, iph1->remote, "memory error.\n");
3103 goto end;
3104 }
3105 memcpy(secret->v, iph1->rmconf->shared_secret->v, secret->l);
3106 }
3107 } else {
3108 secret = getpskbyname(iph1->id_p);
3109 if (!secret) {
3110 if (iph1->rmconf->verify_identifier) {
3111 plog(LLV_ERROR, LOCATION, iph1->remote,
3112 "couldn't find the Hybrid pskey.\n");
3113 goto end;
3114 }
3115 }
3116 }
3117 if (!secret) {
3118 plog(LLV_NOTIFY, LOCATION, iph1->remote,
3119 "couldn't find the Hybrid pskey, "
3120 "try to get one by the peer's address.\n");
3121 secret = getpskbyaddr(iph1->remote);
3122 }
3123
3124end:
3125 return secret;
3126}
3127
52b7d2ce
A
3128/*
3129 * compute SKEYID
3130 * see seciton 5. Exchanges in RFC 2409
3131 * psk: SKEYID = prf(pre-shared-key, Ni_b | Nr_b)
3132 * sig: SKEYID = prf(Ni_b | Nr_b, g^ir)
3133 * enc: SKEYID = prf(H(Ni_b | Nr_b), CKY-I | CKY-R)
3134 */
3135int
3136oakley_skeyid(iph1)
3137 struct ph1handle *iph1;
3138{
3139 vchar_t *buf = NULL, *bp;
3140 char *p;
3141 int len;
3142 int error = -1;
3143
3144 /* SKEYID */
d1e348cf 3145 switch (AUTHMETHOD(iph1)) {
52b7d2ce 3146 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
d1e348cf
A
3147#ifdef ENABLE_HYBRID
3148 case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
3149 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
3150#endif
52b7d2ce
A
3151 if (iph1->rmconf->shared_secret) {
3152
3153 switch (iph1->rmconf->secrettype) {
3154 case SECRETTYPE_KEY:
3155 /* in psk file - use KEY from remote configuration to locate it */
3156 iph1->authstr = getpsk(iph1->rmconf->shared_secret->v, iph1->rmconf->shared_secret->l-1);
3157 break;
d1e348cf 3158#if HAVE_KEYCHAIN
52b7d2ce
A
3159 case SECRETTYPE_KEYCHAIN:
3160 /* in the system keychain */
3161 iph1->authstr = getpskfromkeychain(iph1->rmconf->shared_secret->v, iph1->etype, iph1->rmconf->secrettype, NULL);
3162 break;
3163 case SECRETTYPE_KEYCHAIN_BY_ID:
3164 /* in the system keychain - use peer id */
3165 iph1->authstr = getpskfromkeychain(iph1->rmconf->shared_secret->v, iph1->etype, iph1->rmconf->secrettype, iph1->id_p);
3166 break;
85f41bec 3167#endif // HAVE_KEYCHAIN
52b7d2ce
A
3168 case SECRETTYPE_USE:
3169 /* in the remote configuration */
3170 default:
e8d9021d
A
3171 /* rmconf->shared_secret is a string and contains a NULL character that must be removed */
3172 iph1->authstr = vmalloc(iph1->rmconf->shared_secret->l - 1);
3173 if (iph1->authstr == NULL) {
3174 plog(LLV_ERROR, LOCATION, NULL, "memory error.\n");
3175 break;
3176 }
3177 memcpy(iph1->authstr->v, iph1->rmconf->shared_secret->v, iph1->authstr->l);
52b7d2ce 3178 }
52b7d2ce
A
3179 }
3180 else
52b7d2ce
A
3181 if (iph1->etype != ISAKMP_ETYPE_IDENT) {
3182 iph1->authstr = getpskbyname(iph1->id_p);
3183 if (iph1->authstr == NULL) {
3184 if (iph1->rmconf->verify_identifier) {
3185 plog(LLV_ERROR, LOCATION, iph1->remote,
3186 "couldn't find the pskey.\n");
3187 goto end;
3188 }
3189 plog(LLV_NOTIFY, LOCATION, iph1->remote,
3190 "couldn't find the proper pskey, "
3191 "try to get one by the peer's address.\n");
3192 }
3193 }
3194 if (iph1->authstr == NULL) {
3195 /*
3196 * If the exchange type is the main mode or if it's
3197 * failed to get the psk by ID, racoon try to get
3198 * the psk by remote IP address.
3199 * It may be nonsense.
3200 */
3201 iph1->authstr = getpskbyaddr(iph1->remote);
3202 if (iph1->authstr == NULL) {
3203 plog(LLV_ERROR, LOCATION, iph1->remote,
3204 "couldn't find the pskey for %s.\n",
85f41bec 3205 saddrwop2str((struct sockaddr *)iph1->remote));
52b7d2ce
A
3206 goto end;
3207 }
3208 }
3209 plog(LLV_DEBUG, LOCATION, NULL, "the psk found.\n");
3210 /* should be secret PSK */
3211 plog(LLV_DEBUG2, LOCATION, NULL, "psk: ");
3212 plogdump(LLV_DEBUG2, iph1->authstr->v, iph1->authstr->l);
3213
3214 len = iph1->nonce->l + iph1->nonce_p->l;
3215 buf = vmalloc(len);
3216 if (buf == NULL) {
3217 plog(LLV_ERROR, LOCATION, NULL,
3218 "failed to get skeyid buffer\n");
3219 goto end;
3220 }
3221 p = buf->v;
3222
3223 bp = (iph1->side == INITIATOR ? iph1->nonce : iph1->nonce_p);
3224 plog(LLV_DEBUG, LOCATION, NULL, "nonce 1: ");
3225 plogdump(LLV_DEBUG, bp->v, bp->l);
3226 memcpy(p, bp->v, bp->l);
3227 p += bp->l;
3228
3229 bp = (iph1->side == INITIATOR ? iph1->nonce_p : iph1->nonce);
3230 plog(LLV_DEBUG, LOCATION, NULL, "nonce 2: ");
3231 plogdump(LLV_DEBUG, bp->v, bp->l);
3232 memcpy(p, bp->v, bp->l);
3233 p += bp->l;
3234
3235 iph1->skeyid = oakley_prf(iph1->authstr, buf, iph1);
3236 if (iph1->skeyid == NULL)
3237 goto end;
3238 break;
3239
3240 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
3241 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
3242#ifdef ENABLE_HYBRID
3243 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
3244 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
3245 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
3246 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
d1e348cf
A
3247 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
3248 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
3249 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
3250 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
52b7d2ce
A
3251#endif
3252#ifdef HAVE_GSSAPI
3253 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
3254#endif
3255 len = iph1->nonce->l + iph1->nonce_p->l;
3256 buf = vmalloc(len);
3257 if (buf == NULL) {
3258 plog(LLV_ERROR, LOCATION, NULL,
3259 "failed to get nonce buffer\n");
3260 goto end;
3261 }
3262 p = buf->v;
3263
3264 bp = (iph1->side == INITIATOR ? iph1->nonce : iph1->nonce_p);
3265 plog(LLV_DEBUG, LOCATION, NULL, "nonce1: ");
3266 plogdump(LLV_DEBUG, bp->v, bp->l);
3267 memcpy(p, bp->v, bp->l);
3268 p += bp->l;
3269
3270 bp = (iph1->side == INITIATOR ? iph1->nonce_p : iph1->nonce);
3271 plog(LLV_DEBUG, LOCATION, NULL, "nonce2: ");
3272 plogdump(LLV_DEBUG, bp->v, bp->l);
3273 memcpy(p, bp->v, bp->l);
3274 p += bp->l;
3275
3276 iph1->skeyid = oakley_prf(buf, iph1->dhgxy, iph1);
3277 if (iph1->skeyid == NULL)
3278 goto end;
3279 break;
3280 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
3281 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
d1e348cf
A
3282#ifdef ENABLE_HYBRID
3283 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
3284 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
3285 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
3286 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
3287#endif
52b7d2ce
A
3288 plog(LLV_WARNING, LOCATION, NULL,
3289 "not supported authentication method %s\n",
3290 s_oakley_attr_method(iph1->approval->authmethod));
3291 goto end;
3292 default:
3293 plog(LLV_ERROR, LOCATION, NULL,
3294 "invalid authentication method %d\n",
3295 iph1->approval->authmethod);
3296 goto end;
3297 }
3298
3299 plog(LLV_DEBUG, LOCATION, NULL, "SKEYID computed:\n");
3300 plogdump(LLV_DEBUG, iph1->skeyid->v, iph1->skeyid->l);
3301
3302 error = 0;
3303
3304end:
3305 if (buf != NULL)
3306 vfree(buf);
3307 return error;
3308}
3309
3310/*
3311 * compute SKEYID_[dae]
3312 * see seciton 5. Exchanges in RFC 2409
3313 * SKEYID_d = prf(SKEYID, g^ir | CKY-I | CKY-R | 0)
3314 * SKEYID_a = prf(SKEYID, SKEYID_d | g^ir | CKY-I | CKY-R | 1)
3315 * SKEYID_e = prf(SKEYID, SKEYID_a | g^ir | CKY-I | CKY-R | 2)
3316 */
3317int
3318oakley_skeyid_dae(iph1)
3319 struct ph1handle *iph1;
3320{
3321 vchar_t *buf = NULL;
3322 char *p;
3323 int len;
3324 int error = -1;
3325
3326 if (iph1->skeyid == NULL) {
3327 plog(LLV_ERROR, LOCATION, NULL, "no SKEYID found.\n");
3328 goto end;
3329 }
3330
3331 /* SKEYID D */
3332 /* SKEYID_d = prf(SKEYID, g^xy | CKY-I | CKY-R | 0) */
3333 len = iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1;
3334 buf = vmalloc(len);
3335 if (buf == NULL) {
3336 plog(LLV_ERROR, LOCATION, NULL,
3337 "failed to get skeyid buffer\n");
3338 goto end;
3339 }
3340 p = buf->v;
3341
3342 memcpy(p, iph1->dhgxy->v, iph1->dhgxy->l);
3343 p += iph1->dhgxy->l;
3344 memcpy(p, (caddr_t)&iph1->index.i_ck, sizeof(cookie_t));
3345 p += sizeof(cookie_t);
3346 memcpy(p, (caddr_t)&iph1->index.r_ck, sizeof(cookie_t));
3347 p += sizeof(cookie_t);
3348 *p = 0;
3349 iph1->skeyid_d = oakley_prf(iph1->skeyid, buf, iph1);
3350 if (iph1->skeyid_d == NULL)
3351 goto end;
3352
3353 vfree(buf);
3354 buf = NULL;
3355
3356 plog(LLV_DEBUG, LOCATION, NULL, "SKEYID_d computed:\n");
d1e348cf 3357 plogdump(LLV_DEBUG, iph1->skeyid_d->v, iph1->skeyid_d->l);
52b7d2ce
A
3358
3359 /* SKEYID A */
3360 /* SKEYID_a = prf(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1) */
3361 len = iph1->skeyid_d->l + iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1;
3362 buf = vmalloc(len);
3363 if (buf == NULL) {
3364 plog(LLV_ERROR, LOCATION, NULL,
3365 "failed to get skeyid buffer\n");
3366 goto end;
3367 }
3368 p = buf->v;
3369 memcpy(p, iph1->skeyid_d->v, iph1->skeyid_d->l);
3370 p += iph1->skeyid_d->l;
3371 memcpy(p, iph1->dhgxy->v, iph1->dhgxy->l);
3372 p += iph1->dhgxy->l;
3373 memcpy(p, (caddr_t)&iph1->index.i_ck, sizeof(cookie_t));
3374 p += sizeof(cookie_t);
3375 memcpy(p, (caddr_t)&iph1->index.r_ck, sizeof(cookie_t));
3376 p += sizeof(cookie_t);
3377 *p = 1;
3378 iph1->skeyid_a = oakley_prf(iph1->skeyid, buf, iph1);
3379 if (iph1->skeyid_a == NULL)
3380 goto end;
3381
3382 vfree(buf);
3383 buf = NULL;
3384
3385 plog(LLV_DEBUG, LOCATION, NULL, "SKEYID_a computed:\n");
3386 plogdump(LLV_DEBUG, iph1->skeyid_a->v, iph1->skeyid_a->l);
3387
3388 /* SKEYID E */
3389 /* SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2) */
3390 len = iph1->skeyid_a->l + iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1;
3391 buf = vmalloc(len);
3392 if (buf == NULL) {
3393 plog(LLV_ERROR, LOCATION, NULL,
3394 "failed to get skeyid buffer\n");
3395 goto end;
3396 }
3397 p = buf->v;
3398 memcpy(p, iph1->skeyid_a->v, iph1->skeyid_a->l);
3399 p += iph1->skeyid_a->l;
3400 memcpy(p, iph1->dhgxy->v, iph1->dhgxy->l);
3401 p += iph1->dhgxy->l;
3402 memcpy(p, (caddr_t)&iph1->index.i_ck, sizeof(cookie_t));
3403 p += sizeof(cookie_t);
3404 memcpy(p, (caddr_t)&iph1->index.r_ck, sizeof(cookie_t));
3405 p += sizeof(cookie_t);
3406 *p = 2;
3407 iph1->skeyid_e = oakley_prf(iph1->skeyid, buf, iph1);
3408 if (iph1->skeyid_e == NULL)
3409 goto end;
3410
3411 vfree(buf);
3412 buf = NULL;
3413
3414 plog(LLV_DEBUG, LOCATION, NULL, "SKEYID_e computed:\n");
3415 plogdump(LLV_DEBUG, iph1->skeyid_e->v, iph1->skeyid_e->l);
3416
3417 error = 0;
3418
3419end:
3420 if (buf != NULL)
3421 vfree(buf);
3422 return error;
3423}
3424
3425/*
3426 * compute final encryption key.
3427 * see Appendix B.
3428 */
3429int
3430oakley_compute_enckey(iph1)
3431 struct ph1handle *iph1;
3432{
3433 u_int keylen, prflen;
3434 int error = -1;
3435
3436 /* RFC2409 p39 */
3437 keylen = alg_oakley_encdef_keylen(iph1->approval->enctype,
3438 iph1->approval->encklen);
3439 if (keylen == -1) {
3440 plog(LLV_ERROR, LOCATION, NULL,
3441 "invalid encryption algoritym %d, "
3442 "or invalid key length %d.\n",
3443 iph1->approval->enctype,
3444 iph1->approval->encklen);
3445 goto end;
3446 }
3447 iph1->key = vmalloc(keylen >> 3);
3448 if (iph1->key == NULL) {
3449 plog(LLV_ERROR, LOCATION, NULL,
3450 "failed to get key buffer\n");
3451 goto end;
3452 }
3453
3454 /* set prf length */
3455 prflen = alg_oakley_hashdef_hashlen(iph1->approval->hashtype);
3456 if (prflen == -1) {
3457 plog(LLV_ERROR, LOCATION, NULL,
3458 "invalid hash type %d.\n", iph1->approval->hashtype);
3459 goto end;
3460 }
3461
3462 /* see isakmp-oakley-08 5.3. */
3463 if (iph1->key->l <= iph1->skeyid_e->l) {
3464 /*
3465 * if length(Ka) <= length(SKEYID_e)
3466 * Ka = first length(K) bit of SKEYID_e
3467 */
3468 memcpy(iph1->key->v, iph1->skeyid_e->v, iph1->key->l);
3469 } else {
3470 vchar_t *buf = NULL, *res = NULL;
3471 u_char *p, *ep;
3472 int cplen;
3473 int subkey;
3474
3475 /*
3476 * otherwise,
3477 * Ka = K1 | K2 | K3
3478 * where
3479 * K1 = prf(SKEYID_e, 0)
3480 * K2 = prf(SKEYID_e, K1)
3481 * K3 = prf(SKEYID_e, K2)
3482 */
3483 plog(LLV_DEBUG, LOCATION, NULL,
3484 "len(SKEYID_e) < len(Ka) (%zu < %zu), "
3485 "generating long key (Ka = K1 | K2 | ...)\n",
3486 iph1->skeyid_e->l, iph1->key->l);
3487
3488 if ((buf = vmalloc(prflen >> 3)) == 0) {
3489 plog(LLV_ERROR, LOCATION, NULL,
3490 "failed to get key buffer\n");
3491 goto end;
3492 }
3493 p = (u_char *)iph1->key->v;
3494 ep = p + iph1->key->l;
3495
3496 subkey = 1;
3497 while (p < ep) {
3498 if (p == (u_char *)iph1->key->v) {
3499 /* just for computing K1 */
3500 buf->v[0] = 0;
3501 buf->l = 1;
3502 }
3503 res = oakley_prf(iph1->skeyid_e, buf, iph1);
3504 if (res == NULL) {
3505 vfree(buf);
3506 goto end;
3507 }
3508 plog(LLV_DEBUG, LOCATION, NULL,
3509 "compute intermediate encryption key K%d\n",
3510 subkey);
3511 plogdump(LLV_DEBUG, buf->v, buf->l);
3512 plogdump(LLV_DEBUG, res->v, res->l);
3513
3514 cplen = (res->l < ep - p) ? res->l : ep - p;
3515 memcpy(p, res->v, cplen);
3516 p += cplen;
3517
3518 buf->l = prflen >> 3; /* to cancel K1 speciality */
3519 if (res->l != buf->l) {
3520 plog(LLV_ERROR, LOCATION, NULL,
3521 "internal error: res->l=%zu buf->l=%zu\n",
3522 res->l, buf->l);
3523 vfree(res);
3524 vfree(buf);
3525 goto end;
3526 }
3527 memcpy(buf->v, res->v, res->l);
3528 vfree(res);
3529 subkey++;
3530 }
3531
3532 vfree(buf);
3533 }
3534
3535 /*
3536 * don't check any weak key or not.
3537 * draft-ietf-ipsec-ike-01.txt Appendix B.
3538 * draft-ietf-ipsec-ciph-aes-cbc-00.txt Section 2.3.
3539 */
3540#if 0
3541 /* weakkey check */
3542 if (iph1->approval->enctype > ARRAYLEN(oakley_encdef)
3543 || oakley_encdef[iph1->approval->enctype].weakkey == NULL) {
3544 plog(LLV_ERROR, LOCATION, NULL,
3545 "encryption algoritym %d isn't supported.\n",
3546 iph1->approval->enctype);
3547 goto end;
3548 }
3549 if ((oakley_encdef[iph1->approval->enctype].weakkey)(iph1->key)) {
3550 plog(LLV_ERROR, LOCATION, NULL,
3551 "weakkey was generated.\n");
3552 goto end;
3553 }
3554#endif
3555
3556 plog(LLV_DEBUG, LOCATION, NULL, "final encryption key computed:\n");
3557 plogdump(LLV_DEBUG, iph1->key->v, iph1->key->l);
3558
3559 error = 0;
3560
3561end:
3562 return error;
3563}
3564
3565/* allocated new buffer for CERT */
3566cert_t *
3567oakley_newcert()
3568{
3569 cert_t *new;
3570
3571 new = racoon_calloc(1, sizeof(*new));
3572 if (new == NULL) {
3573 plog(LLV_ERROR, LOCATION, NULL,
3574 "failed to get cert's buffer\n");
3575 return NULL;
3576 }
3577
3578 new->pl = NULL;
e8d9021d 3579 new->chain = NULL;
52b7d2ce
A
3580
3581 return new;
3582}
3583
3584/* delete buffer for CERT */
3585void
e8d9021d 3586oakley_delcert_1(cert)
52b7d2ce
A
3587 cert_t *cert;
3588{
3589 if (!cert)
3590 return;
3591 if (cert->pl)
3592 VPTRINIT(cert->pl);
3593 racoon_free(cert);
3594}
e8d9021d
A
3595
3596/* delete buffer for CERT */
3597void
3598oakley_delcert(cert)
3599 cert_t *cert;
3600{
3601 cert_t *p, *to_delete;
3602
3603 if (!cert)
3604 return;
3605
3606 for (p = cert; p;) {
3607 to_delete = p;
3608 p = p->chain;
3609 oakley_delcert_1(to_delete);
3610 }
3611}
3612
3613/* delete buffer for CERT */
3614static cert_t *
3615oakley_appendcert_to_certchain(certchain, new)
3616 cert_t *certchain;
3617 cert_t *new;
3618{
3619 cert_t *p;
3620
3621 if (!certchain)
3622 return new;
3623
3624 for (p = certchain; p; p = p->chain) {
3625 if (!p->chain) {
3626 p->chain = new;
3627 return certchain;
3628 }
3629 }
3630 return NULL;
3631}
3632
52b7d2ce
A
3633/*
3634 * compute IV and set to ph1handle
3635 * IV = hash(g^xi | g^xr)
3636 * see 4.1 Phase 1 state in draft-ietf-ipsec-ike.
3637 */
3638int
3639oakley_newiv(iph1)
3640 struct ph1handle *iph1;
3641{
3642 struct isakmp_ivm *newivm = NULL;
3643 vchar_t *buf = NULL, *bp;
3644 char *p;
3645 int len;
3646
3647 /* create buffer */
3648 len = iph1->dhpub->l + iph1->dhpub_p->l;
3649 buf = vmalloc(len);
3650 if (buf == NULL) {
3651 plog(LLV_ERROR, LOCATION, NULL,
3652 "failed to get iv buffer\n");
3653 return -1;
3654 }
3655
3656 p = buf->v;
3657
3658 bp = (iph1->side == INITIATOR ? iph1->dhpub : iph1->dhpub_p);
3659 memcpy(p, bp->v, bp->l);
3660 p += bp->l;
3661
3662 bp = (iph1->side == INITIATOR ? iph1->dhpub_p : iph1->dhpub);
3663 memcpy(p, bp->v, bp->l);
3664 p += bp->l;
3665
3666 /* allocate IVm */
3667 newivm = racoon_calloc(1, sizeof(struct isakmp_ivm));
3668 if (newivm == NULL) {
3669 plog(LLV_ERROR, LOCATION, NULL,
3670 "failed to get iv buffer\n");
3671 vfree(buf);
3672 return -1;
3673 }
3674
3675 /* compute IV */
3676 newivm->iv = oakley_hash(buf, iph1);
3677 if (newivm->iv == NULL) {
3678 vfree(buf);
3679 oakley_delivm(newivm);
3680 return -1;
3681 }
3682
3683 /* adjust length of iv */
3684 newivm->iv->l = alg_oakley_encdef_blocklen(iph1->approval->enctype);
3685 if (newivm->iv->l == -1) {
3686 plog(LLV_ERROR, LOCATION, NULL,
3687 "invalid encryption algoriym %d.\n",
3688 iph1->approval->enctype);
3689 vfree(buf);
3690 oakley_delivm(newivm);
3691 return -1;
3692 }
3693
3694 /* create buffer to save iv */
3695 if ((newivm->ive = vdup(newivm->iv)) == NULL) {
3696 plog(LLV_ERROR, LOCATION, NULL,
3697 "vdup (%s)\n", strerror(errno));
3698 vfree(buf);
3699 oakley_delivm(newivm);
3700 return -1;
3701 }
3702
3703 vfree(buf);
3704
3705 plog(LLV_DEBUG, LOCATION, NULL, "IV computed:\n");
3706 plogdump(LLV_DEBUG, newivm->iv->v, newivm->iv->l);
3707
d1e348cf
A
3708 if (iph1->ivm != NULL)
3709 oakley_delivm(iph1->ivm);
3710
52b7d2ce
A
3711 iph1->ivm = newivm;
3712
3713 return 0;
3714}
3715
3716/*
3717 * compute IV for the payload after phase 1.
3718 * It's not limited for phase 2.
3719 * if pahse 1 was encrypted.
3720 * IV = hash(last CBC block of Phase 1 | M-ID)
3721 * if phase 1 was not encrypted.
3722 * IV = hash(phase 1 IV | M-ID)
3723 * see 4.2 Phase 2 state in draft-ietf-ipsec-ike.
3724 */
3725struct isakmp_ivm *
3726oakley_newiv2(iph1, msgid)
3727 struct ph1handle *iph1;
3728 u_int32_t msgid;
3729{
3730 struct isakmp_ivm *newivm = NULL;
3731 vchar_t *buf = NULL;
3732 char *p;
3733 int len;
3734 int error = -1;
3735
3736 /* create buffer */
3737 len = iph1->ivm->iv->l + sizeof(msgid_t);
3738 buf = vmalloc(len);
3739 if (buf == NULL) {
3740 plog(LLV_ERROR, LOCATION, NULL,
3741 "failed to get iv buffer\n");
3742 goto end;
3743 }
3744
3745 p = buf->v;
3746
3747 memcpy(p, iph1->ivm->iv->v, iph1->ivm->iv->l);
3748 p += iph1->ivm->iv->l;
3749
3750 memcpy(p, &msgid, sizeof(msgid));
3751
3752 plog(LLV_DEBUG, LOCATION, NULL, "compute IV for phase2\n");
3753 plog(LLV_DEBUG, LOCATION, NULL, "phase1 last IV:\n");
3754 plogdump(LLV_DEBUG, buf->v, buf->l);
3755
3756 /* allocate IVm */
3757 newivm = racoon_calloc(1, sizeof(struct isakmp_ivm));
3758 if (newivm == NULL) {
3759 plog(LLV_ERROR, LOCATION, NULL,
3760 "failed to get iv buffer\n");
3761 goto end;
3762 }
3763
3764 /* compute IV */
3765 if ((newivm->iv = oakley_hash(buf, iph1)) == NULL)
3766 goto end;
3767
3768 /* adjust length of iv */
3769 newivm->iv->l = alg_oakley_encdef_blocklen(iph1->approval->enctype);
3770 if (newivm->iv->l == -1) {
3771 plog(LLV_ERROR, LOCATION, NULL,
3772 "invalid encryption algoriym %d.\n",
3773 iph1->approval->enctype);
3774 goto end;
3775 }
3776
3777 /* create buffer to save new iv */
3778 if ((newivm->ive = vdup(newivm->iv)) == NULL) {
3779 plog(LLV_ERROR, LOCATION, NULL, "vdup (%s)\n", strerror(errno));
3780 goto end;
3781 }
3782
3783 error = 0;
3784
3785 plog(LLV_DEBUG, LOCATION, NULL, "phase2 IV computed:\n");
3786 plogdump(LLV_DEBUG, newivm->iv->v, newivm->iv->l);
3787
3788end:
3789 if (error && newivm != NULL){
3790 oakley_delivm(newivm);
3791 newivm=NULL;
3792 }
3793 if (buf != NULL)
3794 vfree(buf);
3795 return newivm;
3796}
3797
3798void
3799oakley_delivm(ivm)
3800 struct isakmp_ivm *ivm;
3801{
3802 if (ivm == NULL)
3803 return;
3804
3805 if (ivm->iv != NULL)
3806 vfree(ivm->iv);
3807 if (ivm->ive != NULL)
3808 vfree(ivm->ive);
3809 racoon_free(ivm);
d1e348cf 3810 plog(LLV_DEBUG, LOCATION, NULL, "IV freed\n");
52b7d2ce
A
3811
3812 return;
3813}
3814
3815/*
3816 * decrypt packet.
3817 * save new iv and old iv.
3818 */
3819vchar_t *
3820oakley_do_decrypt(iph1, msg, ivdp, ivep)
3821 struct ph1handle *iph1;
3822 vchar_t *msg, *ivdp, *ivep;
3823{
3824 vchar_t *buf = NULL, *new = NULL;
3825 char *pl;
3826 int len;
3827 u_int8_t padlen;
3828 int blen;
3829 int error = -1;
3830
3831 plog(LLV_DEBUG, LOCATION, NULL, "begin decryption.\n");
3832
3833 blen = alg_oakley_encdef_blocklen(iph1->approval->enctype);
3834 if (blen == -1) {
3835 plog(LLV_ERROR, LOCATION, NULL,
3836 "invalid encryption algoriym %d.\n",
3837 iph1->approval->enctype);
3838 goto end;
3839 }
3840
3841 /* save IV for next, but not sync. */
3842 memset(ivep->v, 0, ivep->l);
3843 memcpy(ivep->v, (caddr_t)&msg->v[msg->l - blen], blen);
3844
3845 plog(LLV_DEBUG, LOCATION, NULL,
3846 "IV was saved for next processing:\n");
3847 plogdump(LLV_DEBUG, ivep->v, ivep->l);
3848
3849 pl = msg->v + sizeof(struct isakmp);
3850
3851 len = msg->l - sizeof(struct isakmp);
3852
3853 /* create buffer */
3854 buf = vmalloc(len);
3855 if (buf == NULL) {
3856 plog(LLV_ERROR, LOCATION, NULL,
3857 "failed to get buffer to decrypt.\n");
3858 goto end;
3859 }
3860 memcpy(buf->v, pl, len);
3861
3862 /* do decrypt */
3863 new = alg_oakley_encdef_decrypt(iph1->approval->enctype,
3864 buf, iph1->key, ivdp);
47612122 3865 if (new == NULL || new->v == NULL || new->l == 0) {
52b7d2ce
A
3866 plog(LLV_ERROR, LOCATION, NULL,
3867 "decryption %d failed.\n", iph1->approval->enctype);
3868 goto end;
3869 }
3870 plog(LLV_DEBUG, LOCATION, NULL, "with key:\n");
3871 plogdump(LLV_DEBUG, iph1->key->v, iph1->key->l);
3872
3873 vfree(buf);
3874 buf = NULL;
3875 if (new == NULL)
3876 goto end;
3877
3878 plog(LLV_DEBUG, LOCATION, NULL, "decrypted payload by IV:\n");
3879 plogdump(LLV_DEBUG, ivdp->v, ivdp->l);
3880
3881 plog(LLV_DEBUG, LOCATION, NULL,
3882 "decrypted payload, but not trimed.\n");
3883 plogdump(LLV_DEBUG, new->v, new->l);
3884
3885 /* get padding length */
3886 if (lcconf->pad_excltail)
3887 padlen = new->v[new->l - 1] + 1;
3888 else
3889 padlen = new->v[new->l - 1];
3890 plog(LLV_DEBUG, LOCATION, NULL, "padding len=%u\n", padlen);
3891
3892 /* trim padding */
3893 if (lcconf->pad_strict) {
3894 if (padlen > new->l) {
3895 plog(LLV_ERROR, LOCATION, NULL,
3896 "invalid padding len=%u, buflen=%zu.\n",
3897 padlen, new->l);
3898 plogdump(LLV_ERROR, new->v, new->l);
3899 goto end;
3900 }
3901 new->l -= padlen;
3902 plog(LLV_DEBUG, LOCATION, NULL, "trimmed padding\n");
3903 } else {
3904 plog(LLV_DEBUG, LOCATION, NULL, "skip to trim padding.\n");
3905 }
3906
3907 /* create new buffer */
3908 len = sizeof(struct isakmp) + new->l;
3909 buf = vmalloc(len);
3910 if (buf == NULL) {
3911 plog(LLV_ERROR, LOCATION, NULL,
3912 "failed to get buffer to decrypt.\n");
3913 goto end;
3914 }
3915 memcpy(buf->v, msg->v, sizeof(struct isakmp));
3916 memcpy(buf->v + sizeof(struct isakmp), new->v, new->l);
3917 ((struct isakmp *)buf->v)->len = htonl(buf->l);
3918
3919 plog(LLV_DEBUG, LOCATION, NULL, "decrypted.\n");
3920 plogdump(LLV_DEBUG, buf->v, buf->l);
3921
3922#ifdef HAVE_PRINT_ISAKMP_C
3923 isakmp_printpacket(buf, iph1->remote, iph1->local, 1);
3924#endif
3925
3926 error = 0;
3927
3928end:
3929 if (error && buf != NULL) {
3930 vfree(buf);
3931 buf = NULL;
3932 }
3933 if (new != NULL)
3934 vfree(new);
3935
3936 return buf;
3937}
3938
3939/*
3940 * encrypt packet.
3941 */
3942vchar_t *
3943oakley_do_encrypt(iph1, msg, ivep, ivp)
3944 struct ph1handle *iph1;
3945 vchar_t *msg, *ivep, *ivp;
3946{
3947 vchar_t *buf = 0, *new = 0;
3948 char *pl;
3949 int len;
3950 u_int padlen;
3951 int blen;
3952 int error = -1;
3953
3954 plog(LLV_DEBUG, LOCATION, NULL, "begin encryption.\n");
3955
3956 /* set cbc block length */
3957 blen = alg_oakley_encdef_blocklen(iph1->approval->enctype);
3958 if (blen == -1) {
3959 plog(LLV_ERROR, LOCATION, NULL,
3960 "invalid encryption algoriym %d.\n",
3961 iph1->approval->enctype);
3962 goto end;
3963 }
3964
3965 pl = msg->v + sizeof(struct isakmp);
3966 len = msg->l - sizeof(struct isakmp);
3967
3968 /* add padding */
3969 padlen = oakley_padlen(len, blen);
3970 plog(LLV_DEBUG, LOCATION, NULL, "pad length = %u\n", padlen);
3971
3972 /* create buffer */
3973 buf = vmalloc(len + padlen);
3974 if (buf == NULL) {
3975 plog(LLV_ERROR, LOCATION, NULL,
3976 "failed to get buffer to encrypt.\n");
3977 goto end;
3978 }
3979 if (padlen) {
3980 int i;
3981 char *p = &buf->v[len];
3982 if (lcconf->pad_random) {
3983 for (i = 0; i < padlen; i++)
3984 *p++ = eay_random() & 0xff;
3985 }
3986 }
3987 memcpy(buf->v, pl, len);
3988
3989 /* make pad into tail */
3990 if (lcconf->pad_excltail)
3991 buf->v[len + padlen - 1] = padlen - 1;
3992 else
3993 buf->v[len + padlen - 1] = padlen;
3994
3995 plogdump(LLV_DEBUG, buf->v, buf->l);
3996
3997 /* do encrypt */
3998 new = alg_oakley_encdef_encrypt(iph1->approval->enctype,
3999 buf, iph1->key, ivep);
4000 if (new == NULL) {
4001 plog(LLV_ERROR, LOCATION, NULL,
4002 "encryption %d failed.\n", iph1->approval->enctype);
4003 goto end;
4004 }
4005 plog(LLV_DEBUG, LOCATION, NULL, "with key:\n");
4006 plogdump(LLV_DEBUG, iph1->key->v, iph1->key->l);
4007
4008 vfree(buf);
4009 buf = NULL;
4010 if (new == NULL)
4011 goto end;
4012
4013 plog(LLV_DEBUG, LOCATION, NULL, "encrypted payload by IV:\n");
4014 plogdump(LLV_DEBUG, ivep->v, ivep->l);
4015
4016 /* save IV for next */
4017 memset(ivp->v, 0, ivp->l);
4018 memcpy(ivp->v, (caddr_t)&new->v[new->l - blen], blen);
4019
4020 plog(LLV_DEBUG, LOCATION, NULL, "save IV for next:\n");
4021 plogdump(LLV_DEBUG, ivp->v, ivp->l);
4022
4023 /* create new buffer */
4024 len = sizeof(struct isakmp) + new->l;
4025 buf = vmalloc(len);
4026 if (buf == NULL) {
4027 plog(LLV_ERROR, LOCATION, NULL,
4028 "failed to get buffer to encrypt.\n");
4029 goto end;
4030 }
4031 memcpy(buf->v, msg->v, sizeof(struct isakmp));
4032 memcpy(buf->v + sizeof(struct isakmp), new->v, new->l);
4033 ((struct isakmp *)buf->v)->len = htonl(buf->l);
4034
4035 error = 0;
4036
4037 plog(LLV_DEBUG, LOCATION, NULL, "encrypted.\n");
4038
4039end:
4040 if (error && buf != NULL) {
4041 vfree(buf);
4042 buf = NULL;
4043 }
4044 if (new != NULL)
4045 vfree(new);
4046
4047 return buf;
4048}
4049
4050/* culculate padding length */
4051static int
4052oakley_padlen(len, base)
4053 int len, base;
4054{
4055 int padlen;
4056
4057 padlen = base - len % base;
4058
4059 if (lcconf->pad_randomlen)
4060 padlen += ((eay_random() % (lcconf->pad_maxsize + 1) + 1) *
4061 base);
4062
4063 return padlen;
4064}
4065
52b7d2ce
A
4066/* -----------------------------------------------------------------------------
4067The base-64 encoding packs three 8-bit bytes into four 7-bit ASCII
4068characters. If the number of bytes in the original data isn't divisable
4069by three, "=" characters are used to pad the encoded data. The complete
4070set of characters used in base-64 are:
4071 'A'..'Z' => 00..25
4072 'a'..'z' => 26..51
4073 '0'..'9' => 52..61
4074 '+' => 62
4075 '/' => 63
4076 '=' => pad
4077
4078----------------------------------------------------------------------------- */
4079static const signed char base64_DecodeTable[128] = {
4080 /* 000 */ -1, -1, -1, -1, -1, -1, -1, -1,
4081 /* 010 */ -1, -1, -1, -1, -1, -1, -1, -1,
4082 /* 020 */ -1, -1, -1, -1, -1, -1, -1, -1,
4083 /* 030 */ -1, -1, -1, -1, -1, -1, -1, -1,
4084 /* ' ' */ -1, -1, -1, -1, -1, -1, -1, -1,
4085 /* '(' */ -1, -1, -1, 62, -1, -1, -1, 63,
4086 /* '0' */ 52, 53, 54, 55, 56, 57, 58, 59,
4087 /* '8' */ 60, 61, -1, -1, -1, 0, -1, -1,
4088 /* '@' */ -1, 0, 1, 2, 3, 4, 5, 6,
4089 /* 'H' */ 7, 8, 9, 10, 11, 12, 13, 14,
4090 /* 'P' */ 15, 16, 17, 18, 19, 20, 21, 22,
4091 /* 'X' */ 23, 24, 25, -1, -1, -1, -1, -1,
4092 /* '`' */ -1, 26, 27, 28, 29, 30, 31, 32,
4093 /* 'h' */ 33, 34, 35, 36, 37, 38, 39, 40,
4094 /* 'p' */ 41, 42, 43, 44, 45, 46, 47, 48,
4095 /* 'x' */ 49, 50, 51, -1, -1, -1, -1, -1
4096};
4097
4098static int base64toCFData(vchar_t *textin, CFDataRef *dataRef)
4099{
4100 uint8_t *tmpbuf;
4101 uint8_t c;
4102 int tmpbufpos = 0;
4103 int numeq = 0;
4104 int acc = 0;
4105 int cntr = 0;
4106 uint8_t *textcur = textin->v;
4107 int len = textin->l;
4108 int i;
4109
4110 tmpbuf = malloc(len); // len of result will be less than encoded len
4111 if (tmpbuf == NULL) {
4112 yyerror("memory error - could not allocate buffer for certificate reference conversion from base-64.");
4113 return -1;
4114 }
4115
4116 for (i = 0; i < len; i++) {
4117 c = *(textcur++);
4118 if (c == '=')
4119 numeq++;
4120 else if (!isspace(c))
4121 numeq = 0;
4122 if (base64_DecodeTable[c] < 0)
4123 continue;
4124 cntr++;
4125 acc <<= 6;
4126 acc += base64_DecodeTable[c];
4127 if (0 == (cntr & 0x3)) {
4128 tmpbuf[tmpbufpos++] = (acc >> 16) & 0xff;
4129 if (numeq < 2)
4130 tmpbuf[tmpbufpos++] = (acc >> 8) & 0xff;
4131 if (numeq < 1)
4132 tmpbuf[tmpbufpos++] = acc & 0xff;
4133 }
4134 }
4135 *dataRef = CFDataCreate(NULL, tmpbuf, tmpbufpos);
4136 free(tmpbuf);
4137 if (*dataRef)
4138 return 0;
4139 else
4140 return -1;
4141
4142}
e8d9021d 4143