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