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