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