]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/racoon/oakley.c
ipsec-258.100.1.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / oakley.c
CommitLineData
d1e348cf
A
1/* $NetBSD: oakley.c,v 1.9.6.2 2007/04/04 13:08:28 vanhu Exp $ */
2
3/* Id: oakley.c,v 1.32 2006/05/26 12:19:46 manubsd Exp */
52b7d2ce
A
4
5/*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "config.h"
35
36#include <sys/types.h>
37#include <sys/param.h>
38#include <sys/socket.h> /* XXX for subjectaltname */
39#include <netinet/in.h> /* XXX for subjectaltname */
40
e8d9021d 41#ifdef HAVE_OPENSSL
52b7d2ce 42#include <openssl/pkcs7.h>
d1e348cf 43#include <openssl/x509.h>
e8d9021d 44#endif
52b7d2ce
A
45
46#include <stdlib.h>
47#include <stdio.h>
48#include <string.h>
49#include <errno.h>
d1e348cf
A
50#include <arpa/inet.h>
51#include <TargetConditionals.h>
52b7d2ce
A
52
53#if TIME_WITH_SYS_TIME
54# include <sys/time.h>
55# include <time.h>
56#else
57# if HAVE_SYS_TIME_H
58# include <sys/time.h>
59# else
60# include <time.h>
61# endif
62#endif
d1e348cf
A
63#ifdef ENABLE_HYBRID
64#include <resolv.h>
65#endif
52b7d2ce
A
66
67#include "var.h"
68#include "misc.h"
69#include "vmbuf.h"
70#include "str2val.h"
71#include "plog.h"
72#include "debug.h"
73
74#include "isakmp_var.h"
75#include "isakmp.h"
76#ifdef ENABLE_HYBRID
77#include "isakmp_xauth.h"
78#include "isakmp_cfg.h"
79#endif
80#include "oakley.h"
52b7d2ce 81#include "localconf.h"
52b7d2ce
A
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"
52b7d2ce 90#include "crypto_cssm.h"
d1e348cf 91#if HAVE_OPENDIR
52b7d2ce
A
92#include "open_dir.h"
93#endif
94#include "dnssec.h"
95#include "sockmisc.h"
96#include "strnames.h"
97#include "gcmalloc.h"
e8d9021d 98#include <CoreFoundation/CoreFoundation.h>
d1e348cf 99#include "remoteconf.h"
fce29cd9 100#include "vpn_control.h"
e8d9021d
A
101#if TARGET_OS_EMBEDDED
102#include <Security/SecCertificate.h>
103#include <Security/SecCertificatePriv.h>
104#endif
e8d9021d 105#include "vpn_control_var.h"
65c25746
A
106#include "ikev2_rfc.h"
107#include "extern.h"
52b7d2ce
A
108
109#define OUTBOUND_SA 0
110#define INBOUND_SA 1
111
52b7d2ce
A
112#define CERT_CHECKID_FROM_PEER 0
113#define CERT_CHECKID_FROM_RMCONFIG 1
52b7d2ce 114
e8d9021d 115#ifdef HAVE_OPENSSL
52b7d2ce
A
116#define INITDHVAL(a, s, d, t) \
117do { \
e8d9021d
A
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); \
52b7d2ce 126} while(0);
e8d9021d
A
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 */
52b7d2ce
A
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
65c25746
A
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);
e8d9021d 159#ifdef HAVE_OPENSSL
65c25746 160static int check_typeofcertname (int, int);
e8d9021d 161#endif
65c25746
A
162static cert_t *save_certbuf (struct isakmp_gen *);
163static int oakley_padlen (int, int);
e8d9021d 164
65c25746
A
165static int base64toCFData (vchar_t *, CFDataRef*);
166static cert_t *oakley_appendcert_to_certchain (cert_t *, cert_t *);
52b7d2ce
A
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
65c25746 199oakley_dhgrp_free(struct dhgroup *dhgrp)
52b7d2ce 200{
65c25746
A
201 VPTRINIT(dhgrp->prime);
202 VPTRINIT(dhgrp->curve_a);
203 VPTRINIT(dhgrp->curve_b);
204 VPTRINIT(dhgrp->order);
52b7d2ce
A
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
65c25746 215oakley_check_dh_pub(vchar_t *prime, vchar_t **pub0)
52b7d2ce
A
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 ? */
65c25746 225 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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) {
65c25746 233 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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 */
e8d9021d 250#ifdef HAVE_OPENSSL
52b7d2ce 251int
e8d9021d 252oakley_dh_compute(const struct dhgroup *dh, vchar_t *pub, vchar_t *priv, vchar_t *pub_p, vchar_t **gxy)
52b7d2ce
A
253{
254#ifdef ENABLE_STATS
255 struct timeval start, end;
256#endif
257 if ((*gxy = vmalloc(dh->prime->l)) == NULL) {
65c25746 258 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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) {
65c25746 269 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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:
65c25746 276 plog(ASL_LEVEL_ERR,
52b7d2ce
A
277 "dh type %d isn't supported.\n", dh->type);
278 return -1;
279 default:
65c25746 280 plog(ASL_LEVEL_ERR,
52b7d2ce
A
281 "invalid dh type %d.\n", dh->type);
282 return -1;
283 }
284
285#ifdef ENABLE_STATS
286 gettimeofday(&end, NULL);
65c25746 287 plog(ASL_LEVEL_NOTICE, "%s(%s%d): %8.6f", __func__,
52b7d2ce
A
288 s_attr_isakmp_group(dh->type), dh->prime->l << 3,
289 timedelta(&start, &end));
290#endif
291
65c25746 292 plog(ASL_LEVEL_DEBUG, "compute DH's shared.\n");
52b7d2ce
A
293
294 return 0;
295}
e8d9021d
A
296#else
297int
65c25746 298oakley_dh_compute(const struct dhgroup *dh, vchar_t *pub_p, size_t publicKeySize, vchar_t **gxy, SecDHContext *dhC)
e8d9021d
A
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
65c25746 310 plog(ASL_LEVEL_DEBUG, "compute DH result.\n");
e8d9021d 311
65c25746 312 maxKeyLen = SecDHGetMaxKeyLength(*dhC);
e8d9021d
A
313 computed_key = vmalloc(maxKeyLen);
314 if (computed_key == NULL) {
65c25746 315 plog(ASL_LEVEL_ERR, "memory error.\n");
e8d9021d
A
316 goto fail;
317 }
318 computed_keylen = computed_key->l;
65c25746
A
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");
e8d9021d
A
322 goto fail;
323 }
324
325#ifdef ENABLE_STATS
326 gettimeofday(&end, NULL);
65c25746 327 plog(ASL_LEVEL_NOTICE, "%s(%s%d): %8.6f", __func__,
e8d9021d
A
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) {
65c25746 334 plog(ASL_LEVEL_ERR, "memory error.\n");
e8d9021d
A
335 goto fail;
336 }
337 memcpy((*gxy)->v + (maxKeyLen - computed_keylen), computed_key->v, computed_keylen);
65c25746
A
338 plog(ASL_LEVEL_DEBUG, "compute DH's shared.\n");
339 if (*dhC) {
340 SecDHDestroy(*dhC);
341 *dhC = NULL;
342 }
e8d9021d
A
343 vfree(computed_key);
344 return 0;
345
346fail:
65c25746
A
347 if (*dhC) {
348 SecDHDestroy(*dhC);
349 *dhC = NULL;
350 }
e8d9021d
A
351 vfree(*gxy);
352 vfree(computed_key);
353 return -1;
354}
355
356#endif
52b7d2ce
A
357
358/*
359 * generate values of DH
360 * IN: *dh
361 * OUT: **pub, **priv
362 */
e8d9021d 363#ifdef HAVE_OPENSSL
52b7d2ce 364int
65c25746 365oakley_dh_generate(const struct dhgroup *dh, vchar_t **pub, vchar_t **priv)
52b7d2ce
A
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) {
65c25746 374 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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:
65c25746 382 plog(ASL_LEVEL_ERR,
52b7d2ce
A
383 "dh type %d isn't supported.\n", dh->type);
384 return -1;
385 default:
65c25746 386 plog(ASL_LEVEL_ERR,
52b7d2ce
A
387 "invalid dh type %d.\n", dh->type);
388 return -1;
389 }
390
391#ifdef ENABLE_STATS
392 gettimeofday(&end, NULL);
65c25746 393 plog(ASL_LEVEL_NOTICE, "%s(%s%d): %8.6f", __func__,
52b7d2ce
A
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
65c25746
A
401 plog(ASL_LEVEL_DEBUG, "compute DH's private.\n");
402 plog(ASL_LEVEL_DEBUG, "compute DH's public.\n");
52b7d2ce
A
403
404 return 0;
405}
e8d9021d
A
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
65c25746 418 plog(ASL_LEVEL_DEBUG, "generate DH key pair.\n");
e8d9021d
A
419 *pub = NULL;
420 switch (dh->type) {
421 case OAKLEY_ATTR_GRP_TYPE_MODP:
65c25746
A
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");
e8d9021d
A
425 goto fail;
426 }
427 maxKeyLen = SecDHGetMaxKeyLength(*dhC);
428 public = vmalloc(maxKeyLen);
429 *publicKeySize = public->l;
430 if (public == NULL) {
65c25746 431 plog(ASL_LEVEL_ERR, "memory error.\n");
e8d9021d
A
432 goto fail;
433 }
65c25746
A
434 if (SecDHGenerateKeypair(*dhC, (uint8_t*)public->v, publicKeySize)) {
435 plog(ASL_LEVEL_ERR, "failed to generate dh key pair.\n");
e8d9021d
A
436 goto fail;
437 }
65c25746 438 plog(ASL_LEVEL_DEBUG, "got DH key pair.\n");
e8d9021d
A
439
440 *pub = vmalloc(maxKeyLen);
441 if (*pub == NULL) {
65c25746 442 plog(ASL_LEVEL_ERR, "memory error.\n");
e8d9021d
A
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:
65c25746 451 plog(ASL_LEVEL_ERR,
e8d9021d
A
452 "dh type %d isn't supported.\n", dh->type);
453 goto fail;
454 default:
65c25746 455 plog(ASL_LEVEL_ERR,
e8d9021d
A
456 "invalid dh type %d.\n", dh->type);
457 goto fail;
458 }
459
460#ifdef ENABLE_STATS
461 gettimeofday(&end, NULL);
65c25746 462 plog(ASL_LEVEL_NOTICE, "%s(%s%d): %8.6f", __func__,
e8d9021d
A
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) {
65c25746 468 plog(ASL_LEVEL_DEBUG, "failed DH public key size check.\n");
e8d9021d
A
469 goto fail;
470 }
471
65c25746 472 //plogdump(ASL_LEVEL_DEBUG, (*pub)->v, (*pub)->l, "compute DH's public.\n");
e8d9021d
A
473
474 vfree(public);
475 return 0;
476
477fail:
65c25746
A
478 if (*dhC) {
479 SecDHDestroy(*dhC);
480 *dhC = NULL;
481 }
e8d9021d
A
482 vfree(*pub);
483 vfree(public);
484 return -1;
485
486}
487#endif
52b7d2ce
A
488
489/*
490 * copy pre-defined dhgroup values.
491 */
492int
65c25746 493oakley_setdhgroup(int group, struct dhgroup **dhgrp)
52b7d2ce
A
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) {
65c25746 501 plog(ASL_LEVEL_ERR,
52b7d2ce
A
502 "invalid DH parameter grp=%d.\n", group);
503 return -1;
504 }
505
506 if (!g->type || !g->prime || !g->gen1) {
507 /* unsuported */
65c25746 508 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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) {
65c25746 515 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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 *
65c25746 536oakley_prf(vchar_t *key, vchar_t *buf, phase1_handle_t *iph1)
52b7d2ce
A
537{
538 vchar_t *res = NULL;
539 int type;
540
541 if (iph1->approval == NULL) {
65c25746
A
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 }
52b7d2ce 551 } else
65c25746
A
552 {
553 type = iph1->approval->hashtype;
554 }
555 res = alg_oakley_hmacdef_one(type, key, buf);
52b7d2ce 556 if (res == NULL) {
65c25746 557 plog(ASL_LEVEL_ERR,
52b7d2ce
A
558 "invalid hmac algorithm %d.\n", type);
559 return NULL;
560 }
561
562 return res;
563}
564
565/*
566 * hash
567 */
568vchar_t *
65c25746 569oakley_hash(vchar_t *buf, phase1_handle_t *iph1)
52b7d2ce
A
570{
571 vchar_t *res = NULL;
572 int type;
573
574 if (iph1->approval == NULL) {
65c25746
A
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 }
52b7d2ce
A
591
592 res = alg_oakley_hashdef_one(type, buf);
593 if (res == NULL) {
65c25746 594 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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
65c25746 607oakley_compute_keymat(phase2_handle_t *iph2, int side)
52b7d2ce
A
608{
609 int error = -1;
610
611 /* compute sharing secret of DH when PFS */
612 if (iph2->approval->pfs_group && iph2->dhpub_p) {
e8d9021d 613#ifdef HAVE_OPENSSL
52b7d2ce 614 if (oakley_dh_compute(iph2->pfsgrp, iph2->dhpub,
e8d9021d
A
615 iph2->dhpriv, iph2->dhpub_p, &iph2->dhgxy) < 0)
616#else
65c25746 617 if (oakley_dh_compute(iph2->pfsgrp, iph2->dhpub_p, iph2->publicKeySize, &iph2->dhgxy, &iph2->dhC) < 0)
e8d9021d 618#endif
52b7d2ce
A
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
65c25746 627 plog(ASL_LEVEL_DEBUG, "KEYMAT computed.\n");
52b7d2ce
A
628
629 error = 0;
630
631end:
632 return error;
633}
634
65c25746 635
52b7d2ce
A
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
65c25746 646oakley_compute_keymat_x(phase2_handle_t *iph2, int side, int sa_dir)
52b7d2ce
A
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) {
65c25746 667 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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 */
65c25746 697 //plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, "KEYMAT compute with\n");
52b7d2ce
A
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 }
65c25746 729 plog(ASL_LEVEL_DEBUG, "encklen=%d authklen=%d\n",
52b7d2ce
A
730 encklen, authklen);
731
732 dupkeymat = (encklen + authklen) / 8 / res->l;
733 dupkeymat += 2; /* safety mergin */
734 if (dupkeymat < 3)
735 dupkeymat = 3;
65c25746
A
736 //plog(ASL_LEVEL_DEBUG,
737 // "generating %zu bits of key (dupkeymat=%d)\n",
738 // dupkeymat * 8 * res->l, dupkeymat);
52b7d2ce
A
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 */
65c25746
A
754 //plog(ASL_LEVEL_DEBUG,
755 // "generating K1...K%d for KEYMAT.\n",
756 // dupkeymat + 1);
52b7d2ce
A
757
758 seed = vmalloc(prev->l + buf->l);
759 if (seed == NULL) {
65c25746 760 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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 */
d1e348cf 769 int update_prev;
52b7d2ce
A
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) {
65c25746 776 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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
d1e348cf
A
785 update_prev = (prev && prev == res) ? 1 : 0;
786
52b7d2ce
A
787 l = res->l;
788 res = vrealloc(res, l + this->l);
d1e348cf
A
789
790 if (update_prev)
791 prev = res;
792
52b7d2ce 793 if (res == NULL) {
65c25746 794 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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
65c25746 815 //plogdump(ASL_LEVEL_DEBUG, res->v, res->l, "");
52b7d2ce
A
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
52b7d2ce
A
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 *
65c25746 854oakley_compute_hash3(phase1_handle_t *iph1, u_int32_t msgid, vchar_t *body)
52b7d2ce
A
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) {
65c25746 864 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
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
52b7d2ce
A
875 /* compute HASH */
876 res = oakley_prf(iph1->skeyid_a, buf, iph1);
877 if (res == NULL)
878 goto end;
879
880 error = 0;
881
65c25746 882 //plogdump(ASL_LEVEL_DEBUG, res->v, res->l, "HASH computed:\n");
52b7d2ce
A
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 *
65c25746 901oakley_compute_hash1(phase1_handle_t *iph1, u_int32_t msgid, vchar_t *body)
52b7d2ce
A
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) {
65c25746 912 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
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
52b7d2ce
A
924 /* compute HASH */
925 res = oakley_prf(iph1->skeyid_a, buf, iph1);
926 if (res == NULL)
927 goto end;
928
929 error = 0;
930
65c25746 931 //plogdump(ASL_LEVEL_DEBUG, res->v, res->l, "HASH computed:\n");
52b7d2ce
A
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 *
65c25746 947oakley_ph1hash_common(phase1_handle_t *iph1, int sw)
52b7d2ce
A
948{
949 vchar_t *buf = NULL, *res = NULL, *bp;
950 char *p, *bp2;
951 int len, bl;
952 int error = -1;
52b7d2ce
A
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
52b7d2ce
A
961 buf = vmalloc(len);
962 if (buf == NULL) {
65c25746 963 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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
52b7d2ce
A
1006 /* compute HASH */
1007 res = oakley_prf(iph1->skeyid, buf, iph1);
1008 if (res == NULL)
1009 goto end;
1010
1011 error = 0;
1012
52b7d2ce
A
1013end:
1014 if (buf != NULL)
1015 vfree(buf);
52b7d2ce
A
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 *
65c25746 1027oakley_ph1hash_base_i(phase1_handle_t *iph1, int sw)
52b7d2ce
A
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) {
65c25746 1038 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1039 "invalid etype for this hash function\n");
1040 return NULL;
1041 }
1042
d1e348cf 1043 switch (AUTHMETHOD(iph1)) {
52b7d2ce
A
1044 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
1045 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
1046 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
d1e348cf
A
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
52b7d2ce 1055 if (iph1->skeyid == NULL) {
65c25746 1056 plog(ASL_LEVEL_ERR, "no SKEYID found.\n");
52b7d2ce
A
1057 return NULL;
1058 }
1059 hashkey = iph1->skeyid;
1060 break;
1061
52b7d2ce 1062 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
52b7d2ce 1063#ifdef ENABLE_HYBRID
52b7d2ce 1064 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
d1e348cf 1065 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
d1e348cf
A
1066 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
1067 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
52b7d2ce
A
1068#endif
1069 /* make hash for seed */
1070 len = iph1->nonce->l + iph1->nonce_p->l;
1071 buf = vmalloc(len);
1072 if (buf == NULL) {
65c25746 1073 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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:
65c25746 1097 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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) {
65c25746 1110 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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
65c25746 1132 //plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, "HASH_I with:\n");
52b7d2ce
A
1133
1134 /* compute HASH */
1135 res = oakley_prf(hashkey, buf, iph1);
1136 if (res == NULL)
1137 goto end;
1138
1139 error = 0;
1140
65c25746 1141 //plogdump(ASL_LEVEL_DEBUG, res->v, res->l, "HASH_I computed:\n");
52b7d2ce
A
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 *
65c25746 1157oakley_ph1hash_base_r(phase1_handle_t *iph1, int sw)
52b7d2ce
A
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) {
65c25746 1167 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1168 "invalid etype for this hash function\n");
1169 return NULL;
1170 }
d1e348cf
A
1171
1172 switch(AUTHMETHOD(iph1)) {
d1e348cf 1173 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
52b7d2ce 1174#ifdef ENABLE_HYBRID
d1e348cf
A
1175 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
1176 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
d1e348cf
A
1177 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
1178 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
d1e348cf 1179 case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
52b7d2ce 1180#endif
d1e348cf
A
1181 break;
1182 default:
65c25746 1183 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1184 "not supported authentication method %d\n",
1185 iph1->approval->authmethod);
1186 return NULL;
d1e348cf 1187 break;
52b7d2ce
A
1188 }
1189
1190 /* make hash for seed */
1191 len = iph1->nonce->l + iph1->nonce_p->l;
1192 buf = vmalloc(len);
1193 if (buf == NULL) {
65c25746 1194 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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) {
65c25746 1222 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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
65c25746 1249 //plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, "HASH_R with:\n");
52b7d2ce
A
1250
1251 /* compute HASH */
1252 res = oakley_prf(hash, buf, iph1);
1253 if (res == NULL)
1254 goto end;
1255
1256 error = 0;
1257
65c25746 1258 //plogdump(ASL_LEVEL_DEBUG, res->v, res->l, "HASH_R computed:\n");
52b7d2ce
A
1259
1260end:
1261 if (buf != NULL)
1262 vfree(buf);
1263 if (hash)
1264 vfree(hash);
1265 return res;
1266}
1267
e8d9021d
A
1268#if HAVE_OPENDIR
1269static int
65c25746 1270oakley_verify_userid(phase1_handle_t *iph1)
e8d9021d
A
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) {
65c25746 1277 user_id = eay_get_x509_common_name(&p->cert); //%%%%%%%% fix this
e8d9021d
A
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) {
65c25746 1289 plog(ASL_LEVEL_ERR,
e8d9021d
A
1290 "the peer is not authorized for access.\n");
1291 } else {
65c25746 1292 plog(ASL_LEVEL_ERR,
e8d9021d
A
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
52b7d2ce
A
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
65c25746 1308oakley_validate_auth(phase1_handle_t *iph1)
52b7d2ce
A
1309{
1310 vchar_t *my_hash = NULL;
1311 int result;
52b7d2ce
A
1312#ifdef ENABLE_STATS
1313 struct timeval start, end;
1314#endif
65c25746 1315 SecKeyRef publicKeyRef = NULL;
52b7d2ce
A
1316
1317#ifdef ENABLE_STATS
1318 gettimeofday(&start, NULL);
1319#endif
d1e348cf
A
1320
1321 switch (AUTHMETHOD(iph1)) {
52b7d2ce 1322 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
d1e348cf
A
1323#ifdef ENABLE_HYBRID
1324 case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
1325 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
1326#endif
52b7d2ce
A
1327 /* validate HASH */
1328 {
1329 char *r_hash;
1330
1331 if (iph1->id_p == NULL || iph1->pl_hash == NULL) {
65c25746 1332 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1333 "few isakmp message received.\n");
1334 return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1335 }
d1e348cf
A
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 {
65c25746 1340 plog(ASL_LEVEL_ERR, "No SIG was passed, "
d1e348cf
A
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
52b7d2ce
A
1347 r_hash = (caddr_t)(iph1->pl_hash + 1);
1348
65c25746
A
1349 //plogdump(ASL_LEVEL_DEBUG, r_hash,
1350 // ntohs(iph1->pl_hash->h.len) - sizeof(*iph1->pl_hash), "HASH received:\n");
52b7d2ce 1351
65c25746
A
1352 if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
1353 switch (iph1->etype) {
1354 case ISAKMP_ETYPE_IDENT:
1355 case ISAKMP_ETYPE_AGG:
52b7d2ce 1356 my_hash = oakley_ph1hash_common(iph1, VALIDATE);
65c25746
A
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);
52b7d2ce
A
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) {
65c25746 1379 plog(ASL_LEVEL_ERR, "HASH mismatched\n");
52b7d2ce
A
1380 return ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1381 }
1382
65c25746 1383 plog(ASL_LEVEL_DEBUG, "HASH for PSK validated.\n");
52b7d2ce
A
1384 }
1385 break;
52b7d2ce
A
1386 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
1387#ifdef ENABLE_HYBRID
d1e348cf 1388 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
d1e348cf
A
1389 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
1390 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
52b7d2ce
A
1391#endif
1392 {
1393 int error = 0;
1394 int certtype = 0;
1395
1396 /* validation */
1397 if (iph1->id_p == NULL) {
65c25746 1398 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1399 "no ID payload was passed.\n");
1400 return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1401 }
1402 if (iph1->sig_p == NULL) {
65c25746 1403 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1404 "no SIG payload was passed.\n");
1405 return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1406 }
1407
65c25746 1408 plog(ASL_LEVEL_DEBUG, "*** SIGN passed\n");
52b7d2ce
A
1409
1410 /* get peer's cert */
1411 switch (iph1->rmconf->getcert_method) {
1412 case ISAKMP_GETCERT_PAYLOAD:
1413 if (iph1->cert_p == NULL) {
65c25746 1414 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1415 "no peer's CERT payload found.\n");
1416 return ISAKMP_INTERNAL_ERROR;
1417 }
1418 break;
52b7d2ce 1419 default:
65c25746 1420 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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 &&
65c25746 1428 (error = oakley_check_certid(iph1)) != 0)
52b7d2ce
A
1429 return error;
1430
d1e348cf 1431#if HAVE_OPENDIR
52b7d2ce
A
1432 /* check cert common name against Open Directory authentication group */
1433 if (iph1->rmconf->cert_verification_option == VERIFICATION_OPTION_OPEN_DIR) {
e8d9021d
A
1434 if (oakley_verify_userid(iph1)) {
1435 return ISAKMP_NTYPE_AUTHENTICATION_FAILED;
52b7d2ce
A
1436 }
1437 }
d1e348cf 1438#endif /* HAVE_OPENDIR */
52b7d2ce
A
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
d1e348cf
A
1445 switch (AUTHMETHOD(iph1)) {
1446 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
52b7d2ce
A
1447 certtype = iph1->cert_p->type;
1448 break;
1449 default:
1450 break;
1451 }
1452#endif
1453 switch (certtype) {
1454 case ISAKMP_CERT_X509SIGN:
d1e348cf
A
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) {
85f41bec 1466 switch ((ALIGNED_CAST(struct sockaddr_storage *)(id_spec->id->v))->ss_family) {
d1e348cf 1467 case AF_INET:
85f41bec 1468 peers_id = inet_ntoa((ALIGNED_CAST(struct sockaddr_in *)(id_spec->id->v))->sin_addr);
d1e348cf
A
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:
65c25746 1477 plog(ASL_LEVEL_ERR,
d1e348cf
A
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 }
e8d9021d 1485 error = crypto_cssm_check_x509cert(oakley_get_peer_cert_from_certchain(iph1), iph1->cert_p, hostname, &publicKeyRef);
d1e348cf
A
1486 if (hostname)
1487 CFRelease(hostname);
1488 }
85f41bec 1489 break;
52b7d2ce
A
1490
1491 default:
65c25746 1492 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1493 "no supported certtype %d\n", certtype);
1494 return ISAKMP_INTERNAL_ERROR;
1495 }
1496 if (error != 0) {
65c25746 1497 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1498 "the peer's certificate is not verified.\n");
1499 return ISAKMP_NTYPE_INVALID_CERT_AUTHORITY;
1500 }
1501 }
1502
65c25746 1503 plog(ASL_LEVEL_DEBUG, "CERT validated\n");
52b7d2ce 1504
65c25746
A
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);
52b7d2ce
A
1527 }
1528 if (my_hash == NULL)
1529 return ISAKMP_INTERNAL_ERROR;
1530
1531
1532 certtype = iph1->rmconf->certtype;
1533#ifdef ENABLE_HYBRID
d1e348cf
A
1534 switch (AUTHMETHOD(iph1)) {
1535 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
52b7d2ce
A
1536 certtype = iph1->cert_p->type;
1537 break;
1538 default:
1539 break;
1540 }
1541#endif
1542 /* check signature */
1543 switch (certtype) {
65c25746
A
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;
52b7d2ce
A
1565 }
1566
1567 vfree(my_hash);
1568 if (error != 0) {
65c25746 1569 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1570 "Invalid SIG.\n");
1571 return ISAKMP_NTYPE_INVALID_SIGNATURE;
1572 }
65c25746 1573 plog(ASL_LEVEL_DEBUG, "SIG authenticated\n");
52b7d2ce
A
1574 }
1575 break;
1576#ifdef ENABLE_HYBRID
d1e348cf 1577 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
52b7d2ce
A
1578 {
1579 if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) {
65c25746 1580 plog(ASL_LEVEL_ERR, "No SIG was passed, "
52b7d2ce
A
1581 "hybrid auth is enabled, "
1582 "but peer is no Xauth compliant\n");
1583 return ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED;
1584 break;
1585 }
65c25746 1586 plog(ASL_LEVEL_INFO, "No SIG was passed, "
52b7d2ce
A
1587 "but hybrid auth is enabled\n");
1588
1589 return 0;
1590 break;
1591 }
52b7d2ce
A
1592#endif
1593 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
1594 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
d1e348cf
A
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
52b7d2ce 1601 if (iph1->id_p == NULL || iph1->pl_hash == NULL) {
65c25746 1602 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1603 "few isakmp message received.\n");
1604 return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1605 }
65c25746 1606 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1607 "not supported authmethod type %s\n",
1608 s_oakley_attr_method(iph1->approval->authmethod));
1609 return ISAKMP_INTERNAL_ERROR;
1610 default:
65c25746 1611 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1612 "invalid authmethod %d why ?\n",
1613 iph1->approval->authmethod);
1614 return ISAKMP_INTERNAL_ERROR;
1615 }
1616#ifdef ENABLE_STATS
1617 gettimeofday(&end, NULL);
65c25746 1618 plog(ASL_LEVEL_NOTICE, "%s(%s): %8.6f", __func__,
52b7d2ce
A
1619 s_oakley_attr_method(iph1->approval->authmethod),
1620 timedelta(&start, &end));
1621#endif
1622
1623 return 0;
1624}
1625
e8d9021d
A
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
65c25746 1641oakley_vpncontrol_notify_ike_failed_if_mycert_invalid (phase1_handle_t *iph1, int notify_initiator)
e8d9021d
A
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
85f41bec 1650 if (iph1->remote->ss_family == AF_INET)
e8d9021d
A
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
52b7d2ce
A
1666/* get my certificate
1667 * NOTE: include certificate type.
1668 */
1669int
65c25746 1670oakley_getmycert(phase1_handle_t *iph1)
52b7d2ce 1671{
fce29cd9 1672 int err;
fce29cd9 1673
52b7d2ce
A
1674 switch (iph1->rmconf->certtype) {
1675 case ISAKMP_CERT_X509SIGN:
1676 if (iph1->cert)
1677 return 0;
fce29cd9 1678 if ( !(err = get_cert_fromlocal(iph1, 1))){
e8d9021d 1679 if (oakley_vpncontrol_notify_ike_failed_if_mycert_invalid(iph1, FROM_LOCAL)) {
fce29cd9
A
1680 return -1;
1681 }
1682 }
fce29cd9 1683 return err;
52b7d2ce 1684 default:
65c25746 1685 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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
65c25746 1700get_cert_fromlocal(phase1_handle_t *iph1, int my)
52b7d2ce 1701{
52b7d2ce
A
1702 vchar_t *cert = NULL;
1703 cert_t **certpl;
52b7d2ce 1704 int error = -1;
fce29cd9 1705 cert_status_t status = CERT_STATUS_OK;
52b7d2ce 1706
65c25746 1707 if (my)
52b7d2ce 1708 certpl = &iph1->cert;
65c25746 1709 else
52b7d2ce 1710 certpl = &iph1->cert_p;
65c25746
A
1711 if (iph1->rmconf->identity_in_keychain == 0) {
1712 plog(ASL_LEVEL_ERR, "no CERT defined.\n");
52b7d2ce
A
1713 return 0;
1714 }
1715
1716 switch (iph1->rmconf->certtype) {
1717 case ISAKMP_CERT_X509SIGN:
52b7d2ce
A
1718 if (iph1->rmconf->identity_in_keychain) {
1719 CFDataRef dataRef;
1720
d1e348cf 1721 if (iph1->rmconf->keychainCertRef == NULL || base64toCFData(iph1->rmconf->keychainCertRef, &dataRef))
52b7d2ce 1722 goto end;
fce29cd9 1723 cert = crypto_cssm_get_x509cert(dataRef, &status);
65c25746 1724 plog(ASL_LEVEL_DEBUG, "done with chking cert status %d\n",status);
52b7d2ce
A
1725 CFRelease(dataRef);
1726 break;
1727 } // else fall thru
52b7d2ce 1728 default:
65c25746 1729 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1730 "not supported certtype %d\n",
1731 iph1->rmconf->certtype);
1732 goto end;
1733 }
1734
1735 if (!cert) {
65c25746 1736 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1737 "failed to get %s CERT.\n",
1738 my ? "my" : "peers");
1739 goto end;
1740 }
1741
1742 *certpl = oakley_newcert();
1743 if (!*certpl) {
65c25746 1744 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1745 "failed to get cert buffer.\n");
1746 goto end;
1747 }
1748 (*certpl)->pl = vmalloc(cert->l + 1);
1749 if ((*certpl)->pl == NULL) {
65c25746 1750 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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;
fce29cd9 1759 (*certpl)->status = status;
52b7d2ce
A
1760 (*certpl)->cert.v = (*certpl)->pl->v + 1;
1761 (*certpl)->cert.l = (*certpl)->pl->l - 1;
1762
65c25746 1763 plog(ASL_LEVEL_DEBUG, "created CERT payload\n");
e8d9021d 1764
52b7d2ce
A
1765 error = 0;
1766
1767end:
1768 if (cert != NULL)
1769 vfree(cert);
1770
1771 return error;
1772}
1773
52b7d2ce
A
1774
1775/* get signature */
1776int
65c25746 1777oakley_getsign(phase1_handle_t *iph1)
52b7d2ce 1778{
52b7d2ce
A
1779 vchar_t *privkey = NULL;
1780 int error = -1;
1781
1782 switch (iph1->rmconf->certtype) {
1783 case ISAKMP_CERT_X509SIGN:
52b7d2ce
A
1784 // cert in keychain - use cssm to sign
1785 if (iph1->rmconf->identity_in_keychain) {
1786 CFDataRef dataRef;
1787
d1e348cf 1788 if (iph1->rmconf->keychainCertRef == NULL || base64toCFData(iph1->rmconf->keychainCertRef, &dataRef))
52b7d2ce
A
1789 goto end;
1790 iph1->sig = crypto_cssm_getsign(dataRef, iph1->hash);
1791 CFRelease(dataRef);
1792 break;
1793 } // else fall thru
52b7d2ce 1794 default:
65c25746 1795 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1796 "Unknown certtype #%d\n",
1797 iph1->rmconf->certtype);
1798 goto end;
1799 }
1800
1801 if (iph1->sig == NULL) {
65c25746 1802 plog(ASL_LEVEL_ERR, "failed to sign.\n");
52b7d2ce
A
1803 goto end;
1804 }
1805
65c25746 1806 //plogdump(ASL_LEVEL_DEBUG, iph1->sig->v, iph1->sig->l, "SIGN computed:\n");
52b7d2ce
A
1807
1808 error = 0;
1809
1810end:
1811 if (privkey != NULL)
1812 vfree(privkey);
1813
1814 return error;
1815}
1816
e8d9021d 1817void
65c25746 1818oakley_verify_certid(phase1_handle_t *iph1)
e8d9021d
A
1819{
1820 if (iph1->rmconf->verify_cert &&
65c25746
A
1821 oakley_check_certid(iph1)){
1822 plog(ASL_LEVEL_DEBUG,
e8d9021d
A
1823 "Discarding CERT: does not match ID:\n");
1824 oakley_delcert(iph1->cert_p);
1825 iph1->cert_p = NULL;
1826 }
1827}
1828
1829static int
65c25746 1830oakley_check_certid_in_certchain(cert_t *certchain, int idtype, int idlen, void *id)
e8d9021d
A
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 *
65c25746 1843oakley_get_peer_cert_from_certchain(phase1_handle_t * iph1)
e8d9021d
A
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) {
65c25746 1851 plog(ASL_LEVEL_ERR, "no ID nor CERT found.\n");
e8d9021d
A
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
85f41bec 1859 id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)iph1->id_p->v;
e8d9021d
A
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}
52b7d2ce
A
1869
1870/*
1871 * compare certificate name and ID value.
1872 */
1873static int
65c25746 1874oakley_check_certid(phase1_handle_t *iph1)
52b7d2ce
A
1875{
1876 struct ipsecdoi_id_b *id_b;
1877 int idlen;
1878 u_int8_t doi_type = 255;
1879 void *peers_id = NULL;
52b7d2ce 1880
65c25746
A
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);
52b7d2ce 1892
52b7d2ce 1893}
65c25746 1894
52b7d2ce 1895static int
65c25746 1896oakley_check_certid_1(vchar_t *cert, int idtype, int idlen, void *id, cert_status_t *certStatus)
52b7d2ce
A
1897{
1898
85f41bec 1899 int len;
65c25746 1900 int error = 0;
52b7d2ce 1901
85f41bec
A
1902#if !TARGET_OS_EMBEDDED
1903 int type;
85f41bec
A
1904 char *altname = NULL;
1905#endif
1906
52b7d2ce
A
1907 switch (idtype) {
1908 case IPSECDOI_ID_DER_ASN1_DN:
e8d9021d 1909 {
65c25746
A
1910 CFDataRef subject;
1911 SecCertificateRef certificate;
1912 UInt8* namePtr;
1913
1914 certificate = crypto_cssm_x509cert_CreateSecCertificateRef(cert);
e8d9021d 1915 if (certificate == NULL) {
65c25746
A
1916 plog(ASL_LEVEL_ERR,
1917 "failed to get SecCertificateRef\n");
e8d9021d
A
1918 if (certStatus && !*certStatus) {
1919 *certStatus = CERT_STATUS_INVALID;
1920 }
e8d9021d 1921 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
65c25746
A
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 }
85f41bec
A
1953 CFRelease(certificate);
1954 CFRelease(subject);
65c25746
A
1955 return 0;
1956 }
1957 break;
e8d9021d 1958
52b7d2ce
A
1959 case IPSECDOI_ID_IPV4_ADDR:
1960 case IPSECDOI_ID_IPV6_ADDR:
1961 {
e8d9021d
A
1962#if TARGET_OS_EMBEDDED
1963 CFIndex pos, count;
1964 SecCertificateRef certificate;
1965 CFArrayRef addresses;
85f41bec 1966#define ADDRESS_BUF_SIZE 64
65c25746
A
1967
1968 certificate = crypto_cssm_x509cert_CreateSecCertificateRef(cert);
e8d9021d 1969 if (certificate == NULL) {
65c25746 1970 plog(ASL_LEVEL_ERR,
e8d9021d
A
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) {
65c25746 1979 plog(ASL_LEVEL_ERR, "failed to get subjectName\n");
e8d9021d
A
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;
85f41bec 1998 addressBuf = racoon_malloc(ADDRESS_BUF_SIZE);
e8d9021d 1999 if (addressBuf == NULL) {
65c25746 2000 plog(ASL_LEVEL_ERR, "out of memory\n");
85f41bec
A
2001 CFRelease(addresses);
2002 CFRelease(certificate);
e8d9021d
A
2003 return -1;
2004 }
85f41bec 2005 if (CFStringGetCString(address, addressBuf, ADDRESS_BUF_SIZE, kCFStringEncodingUTF8) == TRUE) {
e8d9021d
A
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
85f41bec 2010 if (!memcmp(id, numAddress, idtype == IPSECDOI_ID_IPV4_ADDR ? 32 : 128) == 0) { // found a match ?
e8d9021d
A
2011 CFRelease(addresses);
2012 CFRelease(certificate);
2013 return 0;
2014 }
2015 } else
2016 racoon_free(addressBuf);
2017 }
65c25746
A
2018 plog(ASL_LEVEL_ERR, "ID mismatched with subjectAltName.\n");
2019 plog(ASL_LEVEL_ERR,
e8d9021d 2020 "subjectAltName (expected type %s):\n", s_ipsecdoi_ident(idtype));
65c25746 2021 plogdump(ASL_LEVEL_ERR, id, idlen, "ID:\n");
e8d9021d
A
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
52b7d2ce
A
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
65c25746
A
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,
52b7d2ce
A
2041 "invalid address length passed.\n");
2042 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2043 }
2044
2045 for (pos = 1; ; pos++) {
e8d9021d 2046 if (eay_get_x509subjectaltname(cert, &altname, &type, pos, &len) !=0) {
65c25746 2047 plog(ASL_LEVEL_ERR,
52b7d2ce 2048 "failed to get subjectAltName\n");
e8d9021d
A
2049 if (certStatus && !*certStatus) {
2050 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2051 }
52b7d2ce
A
2052 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2053 }
2054
2055 /* it's the end condition of the loop. */
2056 if (!altname) {
65c25746 2057 plog(ASL_LEVEL_ERR,
e8d9021d
A
2058 "invalid subjectAltName\n");
2059 if (certStatus && !*certStatus) {
2060 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2061 }
52b7d2ce
A
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 */
65c25746 2092 plog(ASL_LEVEL_ERR,
52b7d2ce 2093 "invalid IP address in certificate.\n");
65c25746
A
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));
52b7d2ce
A
2097 racoon_free(altname);
2098 altname = NULL;
e8d9021d
A
2099 if (certStatus && !*certStatus) {
2100 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2101 }
52b7d2ce
A
2102 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2103 }
2104
2105 /* compare the addresses */
2106 error = memcmp(id, altname, idlen);
e8d9021d 2107 if (error)
52b7d2ce 2108 continue;
52b7d2ce 2109 racoon_free(altname);
52b7d2ce 2110 return 0;
e8d9021d
A
2111 }
2112 /* failed to find a match */
65c25746 2113 plog(ASL_LEVEL_ERR,
e8d9021d 2114 "ID mismatched with subjectAltName.\n");
65c25746
A
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");
e8d9021d
A
2119 racoon_free(altname);
2120 if (certStatus && !*certStatus)
2121 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
52b7d2ce 2122 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
e8d9021d
A
2123
2124#endif /* TARGET_OS_EMBEDDED */
52b7d2ce
A
2125 }
2126
e8d9021d
A
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
65c25746 2135 certificate = crypto_cssm_x509cert_CreateSecCertificateRef(cert);
e8d9021d 2136 if (certificate == NULL) {
65c25746 2137 plog(ASL_LEVEL_ERR,
e8d9021d
A
2138 "failed to get SecCertificateRef\n");
2139 if (certStatus && !*certStatus) {
2140 *certStatus = CERT_STATUS_INVALID;
2141 }
52b7d2ce
A
2142 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2143 }
e8d9021d
A
2144 names = SecCertificateCopyDNSNames(certificate);
2145 if (names == NULL) {
65c25746 2146 plog(ASL_LEVEL_ERR,
e8d9021d
A
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;
52b7d2ce 2153 }
e8d9021d 2154 count = CFArrayGetCount(names);
65c25746 2155 ID = CFStringCreateWithBytes(kCFAllocatorDefault, id, idlen, kCFStringEncodingUTF8, FALSE);
e8d9021d 2156 if (ID== NULL) {
65c25746 2157 plog(ASL_LEVEL_ERR, "memory error\n");
e8d9021d
A
2158 CFRelease(names);
2159 CFRelease(certificate);
65c25746 2160 return 0;
52b7d2ce 2161 }
e8d9021d
A
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;
52b7d2ce 2169 }
52b7d2ce 2170 }
65c25746
A
2171 plog(ASL_LEVEL_ERR, "ID mismatched with subjectAltName.\n");
2172 plog(ASL_LEVEL_ERR,
e8d9021d 2173 "subjectAltName (expected type %s):\n", s_ipsecdoi_ident(idtype));
65c25746 2174 plogdump(ASL_LEVEL_ERR, id, idlen, "ID:\n");
e8d9021d
A
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
65c25746 2192 certificate = crypto_cssm_x509cert_CreateSecCertificateRef(cert);
e8d9021d 2193 if (certificate == NULL) {
65c25746 2194 plog(ASL_LEVEL_ERR,
e8d9021d
A
2195 "failed to get SecCertificateRef\n");
2196 if (certStatus && !*certStatus) {
2197 *certStatus = CERT_STATUS_INVALID;
2198 }
52b7d2ce
A
2199 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2200 }
e8d9021d
A
2201 names = SecCertificateCopyRFC822Names(certificate);
2202 if (names == NULL) {
65c25746 2203 plog(ASL_LEVEL_ERR,
e8d9021d
A
2204 "failed to get subjectName\n");
2205 if (certStatus && !*certStatus) {
2206 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2207 }
2208 CFRelease(certificate);
52b7d2ce
A
2209 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2210 }
e8d9021d 2211 count = CFArrayGetCount(names);
65c25746 2212 ID = CFStringCreateWithBytes(kCFAllocatorDefault, id, idlen, kCFStringEncodingUTF8, FALSE);
e8d9021d 2213 if (ID == NULL) {
65c25746 2214 plog(ASL_LEVEL_ERR,
e8d9021d
A
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 }
52b7d2ce 2231 }
65c25746
A
2232 plog(ASL_LEVEL_ERR, "ID mismatched with subjectAltName.\n");
2233 plog(ASL_LEVEL_ERR,
e8d9021d 2234 "subjectAltName (expected type %s):\n", s_ipsecdoi_ident(idtype));
65c25746 2235 plogdump(ASL_LEVEL_ERR, id, idlen, "ID:\n");
e8d9021d
A
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;
52b7d2ce 2243 }
e8d9021d 2244#else
52b7d2ce
A
2245 case IPSECDOI_ID_FQDN:
2246 case IPSECDOI_ID_USER_FQDN:
2247 {
2248 int pos;
2249
2250 for (pos = 1; ; pos++) {
e8d9021d 2251 if (eay_get_x509subjectaltname(cert, &altname, &type, pos, &len) != 0) {
65c25746 2252 plog(ASL_LEVEL_ERR,
52b7d2ce 2253 "failed to get subjectAltName\n");
e8d9021d
A
2254 if (certStatus && !*certStatus) {
2255 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2256 }
52b7d2ce
A
2257 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2258 }
2259
2260 /* it's the end condition of the loop. */
2261 if (!altname) {
65c25746 2262 plog(ASL_LEVEL_ERR,
e8d9021d
A
2263 "invalid subjectAltName\n");
2264 if (certStatus && !*certStatus) {
2265 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2266 }
2267 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
52b7d2ce
A
2268 }
2269
e8d9021d
A
2270 if (check_typeofcertname(idtype, type) != 0) {
2271 /* wrong general type - skip this one */
2272 racoon_free(altname);
2273 altname = NULL;
2274 continue;
2275 }
52b7d2ce 2276
e8d9021d
A
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;
52b7d2ce 2286 racoon_free(altname);
e8d9021d 2287 return 0;
52b7d2ce 2288 }
65c25746
A
2289 plog(ASL_LEVEL_ERR, "ID mismatched with subjectAltName.\n");
2290 plog(ASL_LEVEL_ERR,
e8d9021d
A
2291 "subjectAltName (expected type %s, got type %s):\n",
2292 s_ipsecdoi_ident(idtype),
2293 s_ipsecdoi_ident(type));
65c25746
A
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");
52b7d2ce 2298 racoon_free(altname);
e8d9021d
A
2299 if (certStatus && !*certStatus)
2300 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2301 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
52b7d2ce 2302 }
e8d9021d 2303#endif
52b7d2ce 2304 default:
65c25746 2305 plog(ASL_LEVEL_ERR,
52b7d2ce 2306 "Impropper ID type passed: %s.\n",
e8d9021d 2307 s_ipsecdoi_ident(idtype));
52b7d2ce 2308 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
e8d9021d 2309 }
52b7d2ce
A
2310 /*NOTREACHED*/
2311}
e8d9021d 2312#ifdef HAVE_OPENSSL
52b7d2ce 2313static int
65c25746 2314check_typeofcertname(int doi, int genid)
52b7d2ce
A
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}
e8d9021d 2342#endif
52b7d2ce
A
2343
2344/*
2345 * save certificate including certificate type.
2346 */
2347int
65c25746 2348oakley_savecert(phase1_handle_t *iph1, struct isakmp_gen *gen)
52b7d2ce
A
2349{
2350 cert_t **c;
2351 u_int8_t type;
52b7d2ce
A
2352 type = *(u_int8_t *)(gen + 1) & 0xff;
2353
2354 switch (type) {
52b7d2ce 2355 case ISAKMP_CERT_X509SIGN:
52b7d2ce
A
2356 c = &iph1->cert_p;
2357 break;
52b7d2ce 2358 default:
65c25746 2359 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2360 "Invalid CERT type %d\n", type);
2361 return -1;
2362 }
2363
52b7d2ce 2364 if (*c) {
65c25746 2365 plog(ASL_LEVEL_WARNING,
e8d9021d 2366 "preexisting CERT payload... chaining.\n");
52b7d2ce 2367 }
52b7d2ce 2368
65c25746
A
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 }
52b7d2ce 2376
65c25746
A
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 }
52b7d2ce
A
2391
2392 return 0;
2393}
2394
2395/*
2396 * save certificate including certificate type.
2397 */
2398int
65c25746 2399oakley_savecr(phase1_handle_t *iph1, struct isakmp_gen *gen)
52b7d2ce
A
2400{
2401 cert_t **c;
2402 u_int8_t type;
e8d9021d 2403 cert_t *new;
52b7d2ce
A
2404
2405 type = *(u_int8_t *)(gen + 1) & 0xff;
2406
2407 switch (type) {
52b7d2ce 2408 case ISAKMP_CERT_X509SIGN:
e97d2cf9
A
2409 if (iph1->cr_p) {
2410 oakley_delcert(iph1->cr_p);
2411 iph1->cr_p = NULL;
2412 }
52b7d2ce
A
2413 c = &iph1->cr_p;
2414 break;
52b7d2ce 2415 default:
65c25746 2416 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2417 "Invalid CR type %d\n", type);
2418 return -1;
2419 }
2420
e8d9021d
A
2421 new = save_certbuf(gen);
2422 if (!new) {
65c25746 2423 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2424 "Failed to get CR buffer.\n");
2425 return -1;
2426 }
e8d9021d 2427 *c = oakley_appendcert_to_certchain(*c, new);
65c25746 2428 plog(ASL_LEVEL_DEBUG, "CR saved\n");
52b7d2ce
A
2429
2430 return 0;
2431}
2432
2433static cert_t *
65c25746 2434save_certbuf(struct isakmp_gen *gen)
52b7d2ce
A
2435{
2436 cert_t *new;
2437
d1e348cf 2438 if(ntohs(gen->len) <= sizeof(*gen)){
65c25746 2439 plog(ASL_LEVEL_ERR,
d1e348cf
A
2440 "Len is too small !!.\n");
2441 return NULL;
2442 }
2443
52b7d2ce
A
2444 new = oakley_newcert();
2445 if (!new) {
65c25746 2446 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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) {
65c25746 2453 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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
52b7d2ce
A
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 *
65c25746 2475oakley_getcr(phase1_handle_t *iph1)
52b7d2ce
A
2476{
2477 vchar_t *buf;
2478
2479 buf = vmalloc(1);
2480 if (buf == NULL) {
65c25746 2481 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2482 "failed to get cr buffer\n");
2483 return NULL;
2484 }
d1e348cf
A
2485 if(iph1->rmconf->certtype == ISAKMP_CERT_NONE) {
2486 buf->v[0] = iph1->rmconf->cacerttype;
65c25746 2487 plog(ASL_LEVEL_DEBUG, "create my CR: NONE, using %s instead\n",
d1e348cf
A
2488 s_isakmp_certtype(iph1->rmconf->cacerttype));
2489 } else {
2490 buf->v[0] = iph1->rmconf->certtype;
65c25746 2491 plog(ASL_LEVEL_DEBUG, "create my CR: %s\n",
52b7d2ce 2492 s_isakmp_certtype(iph1->rmconf->certtype));
d1e348cf 2493 }
65c25746
A
2494 //if (buf->l > 1)
2495 // plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, "");
52b7d2ce
A
2496
2497 return buf;
2498}
2499
2500/*
2501 * check peer's CR.
2502 */
2503int
65c25746 2504oakley_checkcr(phase1_handle_t *iph1)
52b7d2ce
A
2505{
2506 if (iph1->cr_p == NULL)
2507 return 0;
2508
65c25746 2509 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
2510 "peer transmitted CR: %s\n",
2511 s_isakmp_certtype(iph1->cr_p->type));
2512
2513 if (iph1->cr_p->type != iph1->rmconf->certtype) {
65c25746 2514 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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
65c25746 2527oakley_needcr(int type)
52b7d2ce
A
2528{
2529 switch (type) {
52b7d2ce
A
2530 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
2531#ifdef ENABLE_HYBRID
2532 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
d1e348cf
A
2533 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
2534 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
52b7d2ce
A
2535#endif
2536 return 1;
2537 default:
2538 return 0;
2539 }
2540 /*NOTREACHED*/
2541}
2542
85f41bec 2543vchar_t *
65c25746 2544oakley_getpskall(phase1_handle_t *iph1)
85f41bec
A
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) {
65c25746 2571 plog(ASL_LEVEL_ERR, "memory error.\n");
85f41bec
A
2572 goto end;
2573 }
2574 memcpy(secret->v, iph1->rmconf->shared_secret->v, secret->l);
2575 }
65c25746
A
2576 } else if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV2 ||
2577 iph1->etype != ISAKMP_ETYPE_IDENT) {
85f41bec
A
2578 secret = getpskbyname(iph1->id_p);
2579 if (!secret) {
2580 if (iph1->rmconf->verify_identifier) {
65c25746 2581 plog(ASL_LEVEL_ERR, "couldn't find pskey by peer's ID.\n");
85f41bec
A
2582 goto end;
2583 }
2584 }
2585 }
2586 if (!secret) {
65c25746 2587 plog(ASL_LEVEL_NOTICE, "try to get pskey by the peer's address.\n");
85f41bec 2588 secret = getpskbyaddr(iph1->remote);
65c25746
A
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 }
85f41bec
A
2594 }
2595
2596end:
2597 return secret;
2598}
2599
52b7d2ce
A
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
65c25746 2608oakley_skeyid(phase1_handle_t *iph1)
52b7d2ce 2609{
65c25746
A
2610 vchar_t *key = NULL;
2611 vchar_t *buf = NULL;
2612 vchar_t *bp;
52b7d2ce
A
2613 char *p;
2614 int len;
2615 int error = -1;
65c25746
A
2616
2617
52b7d2ce 2618 /* SKEYID */
d1e348cf 2619 switch (AUTHMETHOD(iph1)) {
65c25746 2620 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
d1e348cf 2621#ifdef ENABLE_HYBRID
65c25746
A
2622 case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
2623 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
d1e348cf 2624#endif
65c25746
A
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:
52b7d2ce 2662#ifdef ENABLE_HYBRID
65c25746
A
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:
52b7d2ce 2667#endif
65c25746
A
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:
d1e348cf 2693#ifdef ENABLE_HYBRID
65c25746
A
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:
d1e348cf 2698#endif
65c25746
A
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;
52b7d2ce 2708 }
65c25746
A
2709
2710 //plogdump(ASL_LEVEL_DEBUG, iph1->skeyid->v, iph1->skeyid->l, "IKEv1 SKEYID computed:\n");
2711
52b7d2ce 2712 error = 0;
65c25746 2713
52b7d2ce 2714end:
65c25746
A
2715 if (key != NULL)
2716 vfree(key);
52b7d2ce
A
2717 if (buf != NULL)
2718 vfree(buf);
2719 return error;
2720}
2721
65c25746
A
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
52b7d2ce
A
2806/*
2807 * compute SKEYID_[dae]
52b7d2ce
A
2808 */
2809int
65c25746 2810oakley_skeyid_dae(phase1_handle_t *iph1)
52b7d2ce 2811{
65c25746 2812 vchar_t *buf = NULL, *bp = NULL;
52b7d2ce
A
2813 char *p;
2814 int len;
2815 int error = -1;
2816
2817 if (iph1->skeyid == NULL) {
65c25746 2818 plog(ASL_LEVEL_ERR, "no SKEYID found.\n");
52b7d2ce
A
2819 goto end;
2820 }
65c25746
A
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 */
52b7d2ce
A
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) {
65c25746 2832 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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
65c25746 2852 //plogdump(ASL_LEVEL_DEBUG, iph1->skeyid_d->v, iph1->skeyid_d->l, "SKEYID_d computed:\n");
52b7d2ce
A
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) {
65c25746 2859 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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
65c25746 2880 //plogdump(ASL_LEVEL_DEBUG, iph1->skeyid_a->v, iph1->skeyid_a->l, "SKEYID_a computed:\n");
52b7d2ce
A
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) {
65c25746 2887 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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
65c25746 2908 //plogdump(ASL_LEVEL_DEBUG, iph1->skeyid_e->v, iph1->skeyid_e->l, "SKEYID_e computed:\n");
52b7d2ce
A
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
65c25746 2923oakley_compute_enckey(phase1_handle_t *iph1)
52b7d2ce
A
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) {
65c25746 2932 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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) {
65c25746 2941 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2942 "failed to get key buffer\n");
2943 goto end;
2944 }
65c25746
A
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 }
52b7d2ce
A
2982
2983 /* set prf length */
2984 prflen = alg_oakley_hashdef_hashlen(iph1->approval->hashtype);
2985 if (prflen == -1) {
65c25746 2986 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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
65c25746
A
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
52b7d2ce
A
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 */
65c25746 3018 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
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) {
65c25746 3024 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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 }
65c25746 3043 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
3044 "compute intermediate encryption key K%d\n",
3045 subkey);
65c25746
A
3046 //plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, "");
3047 //plogdump(ASL_LEVEL_DEBUG, res->v, res->l, "");
52b7d2ce
A
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) {
65c25746 3055 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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 */
52b7d2ce 3075
65c25746 3076 //plogdump(ASL_LEVEL_DEBUG, iph1->key->v, iph1->key->l, "final encryption key computed:\n");
52b7d2ce
A
3077
3078 error = 0;
3079
3080end:
3081 return error;
3082}
3083
3084/* allocated new buffer for CERT */
3085cert_t *
65c25746 3086oakley_newcert(void)
52b7d2ce
A
3087{
3088 cert_t *new;
3089
3090 new = racoon_calloc(1, sizeof(*new));
3091 if (new == NULL) {
65c25746 3092 plog(ASL_LEVEL_ERR,
52b7d2ce
A
3093 "failed to get cert's buffer\n");
3094 return NULL;
3095 }
3096
3097 new->pl = NULL;
e8d9021d 3098 new->chain = NULL;
52b7d2ce
A
3099
3100 return new;
3101}
3102
3103/* delete buffer for CERT */
3104void
65c25746 3105oakley_delcert_1(cert_t *cert)
52b7d2ce
A
3106{
3107 if (!cert)
3108 return;
3109 if (cert->pl)
3110 VPTRINIT(cert->pl);
3111 racoon_free(cert);
3112}
e8d9021d
A
3113
3114/* delete buffer for CERT */
3115void
65c25746 3116oakley_delcert(cert_t *cert)
e8d9021d
A
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 *
65c25746 3132oakley_appendcert_to_certchain(cert_t *certchain, cert_t *new)
e8d9021d
A
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
52b7d2ce
A
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
65c25746 3154oakley_newiv(phase1_handle_t *iph1)
52b7d2ce
A
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) {
65c25746
A
3165 plog(ASL_LEVEL_ERR,
3166 "Failed to get IV buffer\n");
52b7d2ce
A
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) {
65c25746
A
3183 plog(ASL_LEVEL_ERR,
3184 "Failed to get IV buffer\n");
52b7d2ce
A
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) {
65c25746
A
3200 plog(ASL_LEVEL_ERR,
3201 "Invalid encryption algorithm %d.\n",
52b7d2ce
A
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) {
65c25746 3210 plog(ASL_LEVEL_ERR,
52b7d2ce
A
3211 "vdup (%s)\n", strerror(errno));
3212 vfree(buf);
3213 oakley_delivm(newivm);
3214 return -1;
3215 }
3216
3217 vfree(buf);
3218
65c25746 3219 //plogdump(ASL_LEVEL_DEBUG, newivm->iv->v, newivm->iv->l, "IV computed:\n");
52b7d2ce 3220
d1e348cf
A
3221 if (iph1->ivm != NULL)
3222 oakley_delivm(iph1->ivm);
3223
52b7d2ce
A
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 *
65c25746 3239oakley_newiv2(phase1_handle_t *iph1, u_int32_t msgid)
52b7d2ce
A
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) {
65c25746
A
3251 plog(ASL_LEVEL_ERR,
3252 "Failed to get IV buffer\n");
52b7d2ce
A
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
65c25746
A
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");
52b7d2ce
A
3265
3266 /* allocate IVm */
3267 newivm = racoon_calloc(1, sizeof(struct isakmp_ivm));
3268 if (newivm == NULL) {
65c25746
A
3269 plog(ASL_LEVEL_ERR,
3270 "Failed to get IV buffer\n");
52b7d2ce
A
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) {
65c25746
A
3281 plog(ASL_LEVEL_ERR,
3282 "Invalid encryption algorithm %d.\n",
52b7d2ce
A
3283 iph1->approval->enctype);
3284 goto end;
3285 }
3286
3287 /* create buffer to save new iv */
3288 if ((newivm->ive = vdup(newivm->iv)) == NULL) {
65c25746 3289 plog(ASL_LEVEL_ERR, "vdup (%s)\n", strerror(errno));
52b7d2ce
A
3290 goto end;
3291 }
3292
3293 error = 0;
3294
65c25746 3295 //plogdump(ASL_LEVEL_DEBUG, newivm->iv->v, newivm->iv->l, "Phase 2 IV computed:\n");
52b7d2ce
A
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
65c25746
A
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
52b7d2ce 3365void
65c25746 3366oakley_delivm(struct isakmp_ivm *ivm)
52b7d2ce
A
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);
65c25746 3376 plog(ASL_LEVEL_DEBUG, "IV freed\n");
52b7d2ce
A
3377
3378 return;
3379}
3380
3381/*
3382 * decrypt packet.
3383 * save new iv and old iv.
3384 */
3385vchar_t *
65c25746 3386oakley_do_ikev1_decrypt(phase1_handle_t *iph1, vchar_t *msg, vchar_t *ivdp, vchar_t *ivep)
52b7d2ce
A
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
65c25746 3395 plog(ASL_LEVEL_DEBUG, "Begin decryption.\n");
52b7d2ce
A
3396
3397 blen = alg_oakley_encdef_blocklen(iph1->approval->enctype);
3398 if (blen == -1) {
65c25746
A
3399 plog(ASL_LEVEL_ERR,
3400 "Invalid encryption algorithm %d.\n",
52b7d2ce
A
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
65c25746 3409 plogdump(ASL_LEVEL_DEBUG, ivep->v, ivep->l, "IV was saved for next processing:\n");
52b7d2ce
A
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) {
65c25746
A
3418 plog(ASL_LEVEL_ERR,
3419 "Failed to get buffer to decrypt.\n");
52b7d2ce
A
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);
47612122 3427 if (new == NULL || new->v == NULL || new->l == 0) {
65c25746
A
3428 plog(ASL_LEVEL_ERR,
3429 "Decryption %d failed.\n", iph1->approval->enctype);
52b7d2ce
A
3430 goto end;
3431 }
65c25746 3432 //plogdump(ASL_LEVEL_DEBUG, iph1->key->v, iph1->key->l, "with key:\n");
52b7d2ce
A
3433
3434 vfree(buf);
3435 buf = NULL;
3436 if (new == NULL)
3437 goto end;
3438
65c25746 3439 plog(ASL_LEVEL_DEBUG, "decrypted payload by IV:\n");
52b7d2ce
A
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];
65c25746 3446 plog(ASL_LEVEL_DEBUG, "padding len=%u\n", padlen);
52b7d2ce
A
3447
3448 /* trim padding */
3449 if (lcconf->pad_strict) {
3450 if (padlen > new->l) {
65c25746
A
3451 plog(ASL_LEVEL_ERR, "invalid padding len=%u, buflen=%zu.\n",
3452 padlen, new->l);
52b7d2ce
A
3453 goto end;
3454 }
3455 new->l -= padlen;
65c25746 3456 plog(ASL_LEVEL_DEBUG, "trimmed padding\n");
52b7d2ce 3457 } else {
65c25746 3458 plog(ASL_LEVEL_DEBUG, "skip to trim padding.\n");
52b7d2ce
A
3459 }
3460
3461 /* create new buffer */
3462 len = sizeof(struct isakmp) + new->l;
3463 buf = vmalloc(len);
3464 if (buf == NULL) {
65c25746 3465 plog(ASL_LEVEL_ERR,
52b7d2ce
A
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
65c25746 3473 plog(ASL_LEVEL_DEBUG, "decrypted.\n");
52b7d2ce
A
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
65c25746
A
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
52b7d2ce
A
3505/*
3506 * encrypt packet.
3507 */
3508vchar_t *
65c25746 3509oakley_do_ikev1_encrypt(phase1_handle_t *iph1, vchar_t *msg, vchar_t *ivep, vchar_t *ivp)
52b7d2ce
A
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
65c25746 3518 plog(ASL_LEVEL_DEBUG, "Begin encryption.\n");
52b7d2ce
A
3519
3520 /* set cbc block length */
3521 blen = alg_oakley_encdef_blocklen(iph1->approval->enctype);
3522 if (blen == -1) {
65c25746
A
3523 plog(ASL_LEVEL_ERR,
3524 "Invalid encryption algorithm %d.\n",
52b7d2ce
A
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);
65c25746 3534 plog(ASL_LEVEL_DEBUG, "pad length = %u\n", padlen);
52b7d2ce
A
3535
3536 /* create buffer */
3537 buf = vmalloc(len + padlen);
3538 if (buf == NULL) {
65c25746
A
3539 plog(ASL_LEVEL_ERR,
3540 "Failed to get buffer to encrypt.\n");
52b7d2ce
A
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
65c25746 3559 plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, "About to encrypt %d bytes", buf->l);
52b7d2ce
A
3560
3561 /* do encrypt */
3562 new = alg_oakley_encdef_encrypt(iph1->approval->enctype,
3563 buf, iph1->key, ivep);
3564 if (new == NULL) {
65c25746
A
3565 plog(ASL_LEVEL_ERR,
3566 "Encryption %d failed.\n", iph1->approval->enctype);
52b7d2ce
A
3567 goto end;
3568 }
65c25746 3569 //plogdump(ASL_LEVEL_DEBUG, iph1->key->v, iph1->key->l, "with key:\n");
52b7d2ce
A
3570
3571 vfree(buf);
3572 buf = NULL;
3573 if (new == NULL)
3574 goto end;
3575
65c25746 3576 //plogdump(ASL_LEVEL_DEBUG, ivep->v, ivep->l, "encrypted payload by IV:\n");
52b7d2ce
A
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
65c25746 3582 //plogdump(ASL_LEVEL_DEBUG, ivp->v, ivp->l, "save IV for next:\n");
52b7d2ce
A
3583
3584 /* create new buffer */
3585 len = sizeof(struct isakmp) + new->l;
3586 buf = vmalloc(len);
3587 if (buf == NULL) {
65c25746
A
3588 plog(ASL_LEVEL_ERR,
3589 "Failed to get buffer to encrypt.\n");
52b7d2ce
A
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
65c25746 3598 plog(ASL_LEVEL_DEBUG, "Encrypted.\n");
52b7d2ce
A
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
65c25746
A
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
52b7d2ce
A
3625/* culculate padding length */
3626static int
65c25746 3627oakley_padlen(int len, int base)
52b7d2ce
A
3628{
3629 int padlen;
3630
65c25746 3631 padlen = base - (len % base);
52b7d2ce
A
3632
3633 if (lcconf->pad_randomlen)
3634 padlen += ((eay_random() % (lcconf->pad_maxsize + 1) + 1) *
3635 base);
3636
3637 return padlen;
3638}
3639
52b7d2ce
A
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;
65c25746 3680 uint8_t *textcur = (__typeof__(textcur))textin->v;
52b7d2ce
A
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}
e8d9021d 3717