]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/racoon/oakley.c
ipsec-317.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 }
1512 } else
1513 hostname = CFStringCreateWithBytes(NULL, (u_int8_t *)id_spec->id->v, id_spec->id->l, kCFStringEncodingUTF8, FALSE);
1514 }
e8d9021d 1515 error = crypto_cssm_check_x509cert(oakley_get_peer_cert_from_certchain(iph1), iph1->cert_p, hostname, &publicKeyRef);
d1e348cf
A
1516 if (hostname)
1517 CFRelease(hostname);
1518 }
85f41bec 1519 break;
52b7d2ce
A
1520
1521 default:
65c25746 1522 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1523 "no supported certtype %d\n", certtype);
1524 return ISAKMP_INTERNAL_ERROR;
1525 }
1526 if (error != 0) {
65c25746 1527 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1528 "the peer's certificate is not verified.\n");
1529 return ISAKMP_NTYPE_INVALID_CERT_AUTHORITY;
1530 }
1531 }
1532
65c25746 1533 plog(ASL_LEVEL_DEBUG, "CERT validated\n");
52b7d2ce 1534
65c25746
A
1535 if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
1536 /* compute hash */
1537 switch (iph1->etype) {
1538 case ISAKMP_ETYPE_IDENT:
1539 case ISAKMP_ETYPE_AGG:
1540 my_hash = oakley_ph1hash_common(iph1, VALIDATE);
1541 break;
1542 case ISAKMP_ETYPE_BASE:
1543 if (iph1->side == INITIATOR)
1544 my_hash = oakley_ph1hash_base_r(iph1, VALIDATE);
1545 else
1546 my_hash = oakley_ph1hash_base_i(iph1, VALIDATE);
1547 break;
1548 default:
1549 plog(ASL_LEVEL_ERR,
1550 "invalid etype %d\n", iph1->etype);
1551 return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
1552 }
52b7d2ce
A
1553 }
1554 if (my_hash == NULL)
1555 return ISAKMP_INTERNAL_ERROR;
1556
1557
1558 certtype = iph1->rmconf->certtype;
1559#ifdef ENABLE_HYBRID
d1e348cf
A
1560 switch (AUTHMETHOD(iph1)) {
1561 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
52b7d2ce
A
1562 certtype = iph1->cert_p->type;
1563 break;
1564 default:
1565 break;
1566 }
1567#endif
1568 /* check signature */
1569 switch (certtype) {
65c25746
A
1570 case ISAKMP_CERT_X509SIGN:
1571 if (publicKeyRef == NULL) {
1572 plog(ASL_LEVEL_ERR, "@@@@@@ publicKeyRef is NULL\n");
1573 }
1574 if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
1575 error = crypto_cssm_verify_x509sign(publicKeyRef, my_hash, iph1->sig_p, FALSE);
65c25746
A
1576 }
1577 if (error) {
1578 plog(ASL_LEVEL_ERR, "error verifying signature %s\n", GetSecurityErrorString(error));
1579 }
1580
1581 CFRelease(publicKeyRef);
1582 break;
1583 default:
1584 plog(ASL_LEVEL_ERR,
1585 "no supported certtype %d\n",
1586 certtype);
1587 vfree(my_hash);
1588 return ISAKMP_INTERNAL_ERROR;
52b7d2ce
A
1589 }
1590
1591 vfree(my_hash);
1592 if (error != 0) {
65c25746 1593 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1594 "Invalid SIG.\n");
1595 return ISAKMP_NTYPE_INVALID_SIGNATURE;
1596 }
65c25746 1597 plog(ASL_LEVEL_DEBUG, "SIG authenticated\n");
52b7d2ce
A
1598 }
1599 break;
1600#ifdef ENABLE_HYBRID
d1e348cf 1601 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
52b7d2ce
A
1602 {
1603 if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) {
65c25746 1604 plog(ASL_LEVEL_ERR, "No SIG was passed, "
52b7d2ce
A
1605 "hybrid auth is enabled, "
1606 "but peer is no Xauth compliant\n");
1607 return ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED;
1608 break;
1609 }
7ebaebe2 1610 plog(ASL_LEVEL_NOTICE, "No SIG was passed, "
52b7d2ce
A
1611 "but hybrid auth is enabled\n");
1612
1613 return 0;
1614 break;
1615 }
52b7d2ce
A
1616#endif
1617 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
1618 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
d1e348cf
A
1619#ifdef ENABLE_HYBRID
1620 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
1621 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
1622 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
1623 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
1624#endif
52b7d2ce 1625 if (iph1->id_p == NULL || iph1->pl_hash == NULL) {
65c25746 1626 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1627 "few isakmp message received.\n");
1628 return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1629 }
65c25746 1630 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1631 "not supported authmethod type %s\n",
1632 s_oakley_attr_method(iph1->approval->authmethod));
1633 return ISAKMP_INTERNAL_ERROR;
1634 default:
65c25746 1635 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1636 "invalid authmethod %d why ?\n",
1637 iph1->approval->authmethod);
1638 return ISAKMP_INTERNAL_ERROR;
1639 }
1640#ifdef ENABLE_STATS
1641 gettimeofday(&end, NULL);
65c25746 1642 plog(ASL_LEVEL_NOTICE, "%s(%s): %8.6f", __func__,
52b7d2ce
A
1643 s_oakley_attr_method(iph1->approval->authmethod),
1644 timedelta(&start, &end));
1645#endif
1646
1647 return 0;
1648}
1649
e8d9021d
A
1650int
1651oakley_find_status_in_certchain (cert_t *certchain, cert_status_t certStatus)
1652{
1653 cert_t *p;
1654
1655 for (p = certchain; p; p = p->chain) {
1656 if (p->status == certStatus) {
1657 return 1;
1658 }
1659 }
1660 return 0;
1661}
1662
1663static
1664int
65c25746 1665oakley_vpncontrol_notify_ike_failed_if_mycert_invalid (phase1_handle_t *iph1, int notify_initiator)
e8d9021d 1666{
7ebaebe2 1667#ifndef HAVE_OPENSSL
e8d9021d
A
1668 int premature = oakley_find_status_in_certchain(iph1->cert, CERT_STATUS_PREMATURE);
1669 int expired = oakley_find_status_in_certchain(iph1->cert, CERT_STATUS_EXPIRED);
1670 if (premature || expired) {
e8d9021d
A
1671 u_int32_t fail_reason;
1672
e8d9021d
A
1673 if (premature) {
1674 fail_reason = VPNCTL_NTYPE_LOCAL_CERT_PREMATURE;
1675 } else {
1676 fail_reason = VPNCTL_NTYPE_LOCAL_CERT_EXPIRED;
1677 }
d06a7ccb 1678 vpncontrol_notify_ike_failed(fail_reason, notify_initiator, iph1_get_remote_v4_address(iph1), 0, NULL);
e8d9021d
A
1679 return -1;
1680 }
7ebaebe2 1681#endif /* HAVE_OPENSSL */
e8d9021d
A
1682 return 0;
1683}
1684
52b7d2ce
A
1685/* get my certificate
1686 * NOTE: include certificate type.
1687 */
1688int
65c25746 1689oakley_getmycert(phase1_handle_t *iph1)
52b7d2ce 1690{
fce29cd9 1691 int err;
fce29cd9 1692
52b7d2ce
A
1693 switch (iph1->rmconf->certtype) {
1694 case ISAKMP_CERT_X509SIGN:
1695 if (iph1->cert)
1696 return 0;
fce29cd9 1697 if ( !(err = get_cert_fromlocal(iph1, 1))){
e8d9021d 1698 if (oakley_vpncontrol_notify_ike_failed_if_mycert_invalid(iph1, FROM_LOCAL)) {
fce29cd9
A
1699 return -1;
1700 }
1701 }
fce29cd9 1702 return err;
52b7d2ce 1703 default:
65c25746 1704 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1705 "Unknown certtype #%d\n",
1706 iph1->rmconf->certtype);
1707 return -1;
1708 }
1709
1710}
1711
1712/*
1713 * get a CERT from local file.
1714 * IN:
1715 * my != 0 my cert.
1716 * my == 0 peer's cert.
1717 */
1718static int
65c25746 1719get_cert_fromlocal(phase1_handle_t *iph1, int my)
52b7d2ce 1720{
52b7d2ce
A
1721 vchar_t *cert = NULL;
1722 cert_t **certpl;
52b7d2ce 1723 int error = -1;
fce29cd9 1724 cert_status_t status = CERT_STATUS_OK;
52b7d2ce 1725
65c25746 1726 if (my)
52b7d2ce 1727 certpl = &iph1->cert;
65c25746 1728 else
52b7d2ce 1729 certpl = &iph1->cert_p;
65c25746
A
1730 if (iph1->rmconf->identity_in_keychain == 0) {
1731 plog(ASL_LEVEL_ERR, "no CERT defined.\n");
52b7d2ce
A
1732 return 0;
1733 }
1734
1735 switch (iph1->rmconf->certtype) {
1736 case ISAKMP_CERT_X509SIGN:
52b7d2ce
A
1737 if (iph1->rmconf->identity_in_keychain) {
1738 CFDataRef dataRef;
1739
d1e348cf 1740 if (iph1->rmconf->keychainCertRef == NULL || base64toCFData(iph1->rmconf->keychainCertRef, &dataRef))
52b7d2ce 1741 goto end;
fce29cd9 1742 cert = crypto_cssm_get_x509cert(dataRef, &status);
65c25746 1743 plog(ASL_LEVEL_DEBUG, "done with chking cert status %d\n",status);
52b7d2ce
A
1744 CFRelease(dataRef);
1745 break;
1746 } // else fall thru
52b7d2ce 1747 default:
65c25746 1748 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1749 "not supported certtype %d\n",
1750 iph1->rmconf->certtype);
1751 goto end;
1752 }
1753
1754 if (!cert) {
65c25746 1755 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1756 "failed to get %s CERT.\n",
1757 my ? "my" : "peers");
1758 goto end;
1759 }
1760
1761 *certpl = oakley_newcert();
1762 if (!*certpl) {
65c25746 1763 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1764 "failed to get cert buffer.\n");
1765 goto end;
1766 }
1767 (*certpl)->pl = vmalloc(cert->l + 1);
1768 if ((*certpl)->pl == NULL) {
65c25746 1769 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1770 "failed to get cert buffer\n");
1771 oakley_delcert(*certpl);
1772 *certpl = NULL;
1773 goto end;
1774 }
1775 memcpy((*certpl)->pl->v + 1, cert->v, cert->l);
1776 (*certpl)->pl->v[0] = iph1->rmconf->certtype;
1777 (*certpl)->type = iph1->rmconf->certtype;
fce29cd9 1778 (*certpl)->status = status;
52b7d2ce
A
1779 (*certpl)->cert.v = (*certpl)->pl->v + 1;
1780 (*certpl)->cert.l = (*certpl)->pl->l - 1;
1781
65c25746 1782 plog(ASL_LEVEL_DEBUG, "created CERT payload\n");
e8d9021d 1783
52b7d2ce
A
1784 error = 0;
1785
1786end:
1787 if (cert != NULL)
1788 vfree(cert);
1789
1790 return error;
1791}
1792
52b7d2ce
A
1793
1794/* get signature */
1795int
65c25746 1796oakley_getsign(phase1_handle_t *iph1)
52b7d2ce 1797{
52b7d2ce
A
1798 vchar_t *privkey = NULL;
1799 int error = -1;
1800
1801 switch (iph1->rmconf->certtype) {
1802 case ISAKMP_CERT_X509SIGN:
52b7d2ce
A
1803 // cert in keychain - use cssm to sign
1804 if (iph1->rmconf->identity_in_keychain) {
1805 CFDataRef dataRef;
1806
d1e348cf 1807 if (iph1->rmconf->keychainCertRef == NULL || base64toCFData(iph1->rmconf->keychainCertRef, &dataRef))
52b7d2ce
A
1808 goto end;
1809 iph1->sig = crypto_cssm_getsign(dataRef, iph1->hash);
1810 CFRelease(dataRef);
1811 break;
1812 } // else fall thru
52b7d2ce 1813 default:
65c25746 1814 plog(ASL_LEVEL_ERR,
52b7d2ce
A
1815 "Unknown certtype #%d\n",
1816 iph1->rmconf->certtype);
1817 goto end;
1818 }
1819
1820 if (iph1->sig == NULL) {
65c25746 1821 plog(ASL_LEVEL_ERR, "failed to sign.\n");
52b7d2ce
A
1822 goto end;
1823 }
1824
65c25746 1825 //plogdump(ASL_LEVEL_DEBUG, iph1->sig->v, iph1->sig->l, "SIGN computed:\n");
52b7d2ce
A
1826
1827 error = 0;
1828
1829end:
1830 if (privkey != NULL)
1831 vfree(privkey);
1832
1833 return error;
1834}
1835
e8d9021d 1836void
65c25746 1837oakley_verify_certid(phase1_handle_t *iph1)
e8d9021d
A
1838{
1839 if (iph1->rmconf->verify_cert &&
65c25746
A
1840 oakley_check_certid(iph1)){
1841 plog(ASL_LEVEL_DEBUG,
e8d9021d
A
1842 "Discarding CERT: does not match ID:\n");
1843 oakley_delcert(iph1->cert_p);
1844 iph1->cert_p = NULL;
1845 }
1846}
1847
1848static int
65c25746 1849oakley_check_certid_in_certchain(cert_t *certchain, int idtype, int idlen, void *id)
e8d9021d
A
1850{
1851 cert_t *p;
1852
1853 for (p = certchain; p; p = p->chain) {
1854 if (oakley_check_certid_1(&p->cert, idtype, idlen, id, &p->status) == 0) {
1855 return 0;
1856 }
1857 }
1858 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
1859}
1860
1861cert_t *
65c25746 1862oakley_get_peer_cert_from_certchain(phase1_handle_t * iph1)
e8d9021d
A
1863{
1864 cert_t *p;
1865 struct ipsecdoi_id_b *id_b;
1866 int idlen;
1867 void *peers_id;
1868
1869 if (!iph1->id_p || !iph1->cert_p) {
65c25746 1870 plog(ASL_LEVEL_ERR, "no ID nor CERT found.\n");
e8d9021d
A
1871 return NULL;
1872 }
1873 if (!iph1->cert_p->chain) {
1874 // no chain: simply return the only cert
1875 return iph1->cert_p;
1876 }
1877
85f41bec 1878 id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)iph1->id_p->v;
e8d9021d
A
1879 peers_id = id_b + 1;
1880 idlen = iph1->id_p->l - sizeof(*id_b);
1881 for (p = iph1->cert_p; p; p = p->chain) {
1882 if (oakley_check_certid_1(&p->cert, id_b->type, idlen, peers_id, &p->status) == 0) {
1883 return p;
1884 }
1885 }
1886 return NULL;
1887}
52b7d2ce
A
1888
1889/*
1890 * compare certificate name and ID value.
1891 */
1892static int
65c25746 1893oakley_check_certid(phase1_handle_t *iph1)
52b7d2ce
A
1894{
1895 struct ipsecdoi_id_b *id_b;
1896 int idlen;
1897 u_int8_t doi_type = 255;
1898 void *peers_id = NULL;
52b7d2ce 1899
65c25746
A
1900 /* use ID from peer */
1901 if (iph1->id_p == NULL || iph1->cert_p == NULL) {
1902 plog(ASL_LEVEL_ERR, "no ID nor CERT found.\n");
1903 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
1904 }
1905 id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)iph1->id_p->v;
1906 doi_type = id_b->type;
1907 peers_id = id_b + 1;
1908 idlen = iph1->id_p->l - sizeof(*id_b);
1909
1910 return oakley_check_certid_in_certchain(iph1->cert_p, doi_type, idlen, peers_id);
52b7d2ce 1911
52b7d2ce 1912}
65c25746 1913
52b7d2ce 1914static int
65c25746 1915oakley_check_certid_1(vchar_t *cert, int idtype, int idlen, void *id, cert_status_t *certStatus)
52b7d2ce
A
1916{
1917
7ebaebe2 1918 int len = 0;
65c25746 1919 int error = 0;
52b7d2ce 1920
7ebaebe2 1921#ifdef HAVE_OPENSSL
85f41bec 1922 int type;
85f41bec
A
1923 char *altname = NULL;
1924#endif
1925
52b7d2ce
A
1926 switch (idtype) {
1927 case IPSECDOI_ID_DER_ASN1_DN:
e8d9021d 1928 {
65c25746
A
1929 CFDataRef subject;
1930 SecCertificateRef certificate;
7ebaebe2 1931 UInt8* namePtr = NULL;
65c25746
A
1932
1933 certificate = crypto_cssm_x509cert_CreateSecCertificateRef(cert);
e8d9021d 1934 if (certificate == NULL) {
65c25746
A
1935 plog(ASL_LEVEL_ERR,
1936 "failed to get SecCertificateRef\n");
e8d9021d
A
1937 if (certStatus && !*certStatus) {
1938 *certStatus = CERT_STATUS_INVALID;
1939 }
e8d9021d 1940 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
65c25746
A
1941 }
1942 subject = crypto_cssm_CopySubjectSequence(certificate);
1943 if (subject == NULL) {
1944 plog(ASL_LEVEL_ERR, "failed to get certificate subjectName\n");
1945 if (certStatus && !*certStatus) {
1946 *certStatus = CERT_STATUS_INVALID_SUBJNAME;
1947 }
1948 error = ISAKMP_NTYPE_INVALID_CERTIFICATE;
1949 } else {
1950 len = CFDataGetLength(subject);
1951 namePtr = (UInt8*)CFDataGetBytePtr(subject);
1952 if (namePtr) {
1953 if (idlen != len || memcmp(id, namePtr, idlen)) {
1954 plog(ASL_LEVEL_ERR, "ID mismatched with certificate subjectName\n");
1955 error =ISAKMP_NTYPE_INVALID_ID_INFORMATION;
1956 }
1957 } else {
1958 plog(ASL_LEVEL_ERR, "no certificate subjectName found\n");
1959 error = ISAKMP_NTYPE_INVALID_CERTIFICATE;
1960 }
1961 }
1962 if (error) {
1963 plog(ASL_LEVEL_ERR,
1964 "ID mismatched with certificate subjectName\n");
7ebaebe2
A
1965 if (namePtr != NULL) {
1966 plogdump(ASL_LEVEL_ERR, namePtr, len, "subjectName (type %s):\n",
1967 s_ipsecdoi_ident(idtype));
1968 } else {
1969 plog(ASL_LEVEL_ERR, "subjectName (type %s):\n", s_ipsecdoi_ident(idtype));
1970 }
65c25746
A
1971 plogdump(ASL_LEVEL_ERR, id, idlen, "ID:\n");
1972 if (certStatus && !*certStatus) {
1973 *certStatus = CERT_STATUS_INVALID_SUBJNAME;
1974 }
1975 }
85f41bec 1976 CFRelease(certificate);
d9c572c0
A
1977 if (subject != NULL) {
1978 CFRelease(subject);
1979 }
65c25746
A
1980 return 0;
1981 }
1982 break;
e8d9021d 1983
52b7d2ce
A
1984 case IPSECDOI_ID_IPV4_ADDR:
1985 case IPSECDOI_ID_IPV6_ADDR:
1986 {
7ebaebe2 1987#ifndef HAVE_OPENSSL
e8d9021d
A
1988 CFIndex pos, count;
1989 SecCertificateRef certificate;
1990 CFArrayRef addresses;
85f41bec 1991#define ADDRESS_BUF_SIZE 64
65c25746
A
1992
1993 certificate = crypto_cssm_x509cert_CreateSecCertificateRef(cert);
e8d9021d 1994 if (certificate == NULL) {
65c25746 1995 plog(ASL_LEVEL_ERR,
e8d9021d
A
1996 "failed to get SecCertificateRef\n");
1997 if (certStatus && !*certStatus) {
1998 *certStatus = CERT_STATUS_INVALID;
1999 }
2000 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2001 }
2002 addresses = SecCertificateCopyIPAddresses(certificate);
2003 if (addresses == NULL) {
65c25746 2004 plog(ASL_LEVEL_ERR, "failed to get subjectName\n");
e8d9021d
A
2005 if (certStatus && !*certStatus) {
2006 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2007 }
2008 CFRelease(certificate);
2009 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2010 }
2011 count = CFArrayGetCount(addresses);
2012 for (pos = 0; pos < count; pos++) {
2013
2014 CFStringRef address;
2015 CFIndex addressLen;
2016 char *addressBuf, numAddress[128];
2017 int result;
2018
2019 address = CFArrayGetValueAtIndex(addresses, pos);
2020 addressLen = CFStringGetLength(address);
2021 if (addressLen == 0)
2022 continue;
85f41bec 2023 addressBuf = racoon_malloc(ADDRESS_BUF_SIZE);
e8d9021d 2024 if (addressBuf == NULL) {
65c25746 2025 plog(ASL_LEVEL_ERR, "out of memory\n");
85f41bec
A
2026 CFRelease(addresses);
2027 CFRelease(certificate);
e8d9021d
A
2028 return -1;
2029 }
85f41bec 2030 if (CFStringGetCString(address, addressBuf, ADDRESS_BUF_SIZE, kCFStringEncodingUTF8) == TRUE) {
e8d9021d
A
2031 result = inet_pton(idtype == IPSECDOI_ID_IPV4_ADDR ? AF_INET : AF_INET6, addressBuf, numAddress);
2032 racoon_free(addressBuf);
2033 if (result == 0)
2034 continue; // wrong type or invalid address
85f41bec 2035 if (!memcmp(id, numAddress, idtype == IPSECDOI_ID_IPV4_ADDR ? 32 : 128) == 0) { // found a match ?
e8d9021d
A
2036 CFRelease(addresses);
2037 CFRelease(certificate);
2038 return 0;
2039 }
2040 } else
2041 racoon_free(addressBuf);
2042 }
65c25746
A
2043 plog(ASL_LEVEL_ERR, "ID mismatched with subjectAltName.\n");
2044 plog(ASL_LEVEL_ERR,
e8d9021d 2045 "subjectAltName (expected type %s):\n", s_ipsecdoi_ident(idtype));
65c25746 2046 plogdump(ASL_LEVEL_ERR, id, idlen, "ID:\n");
e8d9021d
A
2047 CFRelease(addresses);
2048 CFRelease(certificate);
2049 if (certStatus && !*certStatus) {
2050 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2051 }
2052 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2053#else
52b7d2ce
A
2054 /*
2055 * Openssl returns the IPAddress as an ASN1 octet string (binary format)
2056 * followed by a trailing NULL. 5 bytes for IPv4 and 17 bytes for IPv6
2057 */
2058 #define SUBJ_ALT_NAME_IPV4_ADDRESS_LEN 5
2059 #define SUBJ_ALT_NAME_IPV6_ADDRESS_LEN 17
2060
2061 int pos;
2062
65c25746
A
2063 if ((idtype == IPSECDOI_ID_IPV4_ADDR && idlen != sizeof(struct in_addr))
2064 || (idtype == IPSECDOI_ID_IPV6_ADDR && idlen != sizeof(struct in6_addr))) {
2065 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2066 "invalid address length passed.\n");
2067 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2068 }
2069
2070 for (pos = 1; ; pos++) {
e8d9021d 2071 if (eay_get_x509subjectaltname(cert, &altname, &type, pos, &len) !=0) {
65c25746 2072 plog(ASL_LEVEL_ERR,
52b7d2ce 2073 "failed to get subjectAltName\n");
e8d9021d
A
2074 if (certStatus && !*certStatus) {
2075 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2076 }
52b7d2ce
A
2077 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2078 }
2079
2080 /* it's the end condition of the loop. */
2081 if (!altname) {
65c25746 2082 plog(ASL_LEVEL_ERR,
e8d9021d
A
2083 "invalid subjectAltName\n");
2084 if (certStatus && !*certStatus) {
2085 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2086 }
52b7d2ce
A
2087 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2088 }
2089
2090 if (check_typeofcertname(idtype, type) != 0) {
2091 /* wrong type - skip this one */
2092 racoon_free(altname);
2093 altname = NULL;
2094 continue;
2095 }
2096
2097 if (len == SUBJ_ALT_NAME_IPV4_ADDRESS_LEN) { /* IPv4 */
2098 if (idtype != IPSECDOI_ID_IPV4_ADDR) {
2099 /* wrong IP address type - skip this one */
2100 racoon_free(altname);
2101 altname = NULL;
2102 continue;
2103 }
2104 }
2105#ifdef INET6
2106 else if (len == SUBJ_ALT_NAME_IPV6_ADDRESS_LEN) { /* IPv6 */
2107 if (idtype != IPSECDOI_ID_IPV6_ADDR) {
2108 /* wrong IP address type - skip this one */
2109 racoon_free(altname);
2110 altname = NULL;
2111 continue;
2112 }
2113 }
2114#endif
2115 else {
2116 /* invalid IP address length in certificate - bad or bogus certificate */
65c25746 2117 plog(ASL_LEVEL_ERR,
52b7d2ce 2118 "invalid IP address in certificate.\n");
65c25746
A
2119 plogdump(ASL_LEVEL_ERR, altname, len, "subjectAltName (expected type %s, got type %s):\n",
2120 s_ipsecdoi_ident(idtype),
2121 s_ipsecdoi_ident(type));
52b7d2ce
A
2122 racoon_free(altname);
2123 altname = NULL;
e8d9021d
A
2124 if (certStatus && !*certStatus) {
2125 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2126 }
52b7d2ce
A
2127 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2128 }
2129
2130 /* compare the addresses */
2131 error = memcmp(id, altname, idlen);
e8d9021d 2132 if (error)
52b7d2ce 2133 continue;
52b7d2ce 2134 racoon_free(altname);
52b7d2ce 2135 return 0;
e8d9021d
A
2136 }
2137 /* failed to find a match */
65c25746 2138 plog(ASL_LEVEL_ERR,
e8d9021d 2139 "ID mismatched with subjectAltName.\n");
65c25746
A
2140 plogdump(ASL_LEVEL_ERR, altname, len, "subjectAltName (expected type %s, got type %s):\n",
2141 s_ipsecdoi_ident(idtype),
2142 s_ipsecdoi_ident(type));
2143 plogdump(ASL_LEVEL_ERR, id, idlen, "ID:\n");
e8d9021d
A
2144 racoon_free(altname);
2145 if (certStatus && !*certStatus)
2146 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
52b7d2ce 2147 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
e8d9021d 2148
7ebaebe2 2149#endif /* HAVE_OPENSSL */
52b7d2ce
A
2150 }
2151
7ebaebe2 2152#ifndef HAVE_OPENSSL
e8d9021d
A
2153 case IPSECDOI_ID_FQDN:
2154 {
2155 CFIndex pos, count;
2156 SecCertificateRef certificate;
2157 CFArrayRef names;
2158 CFStringRef name, ID;
2159
65c25746 2160 certificate = crypto_cssm_x509cert_CreateSecCertificateRef(cert);
e8d9021d 2161 if (certificate == NULL) {
65c25746 2162 plog(ASL_LEVEL_ERR,
e8d9021d
A
2163 "failed to get SecCertificateRef\n");
2164 if (certStatus && !*certStatus) {
2165 *certStatus = CERT_STATUS_INVALID;
2166 }
52b7d2ce
A
2167 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2168 }
e8d9021d
A
2169 names = SecCertificateCopyDNSNames(certificate);
2170 if (names == NULL) {
65c25746 2171 plog(ASL_LEVEL_ERR,
e8d9021d
A
2172 "failed to get subjectName\n");
2173 if (certStatus && !*certStatus) {
2174 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2175 }
2176 CFRelease(certificate);
2177 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
52b7d2ce 2178 }
e8d9021d 2179 count = CFArrayGetCount(names);
65c25746 2180 ID = CFStringCreateWithBytes(kCFAllocatorDefault, id, idlen, kCFStringEncodingUTF8, FALSE);
e8d9021d 2181 if (ID== NULL) {
65c25746 2182 plog(ASL_LEVEL_ERR, "memory error\n");
e8d9021d
A
2183 CFRelease(names);
2184 CFRelease(certificate);
65c25746 2185 return 0;
52b7d2ce 2186 }
e8d9021d
A
2187 for (pos = 0; pos < count; pos++) {
2188 name = CFArrayGetValueAtIndex(names, pos);
2189 if (CFStringCompare(name, ID, 0) == kCFCompareEqualTo) {
2190 CFRelease(ID);
2191 CFRelease(names);
2192 CFRelease(certificate);
2193 return 0;
52b7d2ce 2194 }
52b7d2ce 2195 }
65c25746
A
2196 plog(ASL_LEVEL_ERR, "ID mismatched with subjectAltName.\n");
2197 plog(ASL_LEVEL_ERR,
e8d9021d 2198 "subjectAltName (expected type %s):\n", s_ipsecdoi_ident(idtype));
65c25746 2199 plogdump(ASL_LEVEL_ERR, id, idlen, "ID:\n");
e8d9021d
A
2200 CFRelease(ID);
2201 CFRelease(names);
2202 CFRelease(certificate);
2203 if (certStatus && !*certStatus) {
2204 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2205 }
2206 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2207 }
2208
2209 case IPSECDOI_ID_USER_FQDN:
2210 {
2211 CFIndex pos, count;
2212
2213 SecCertificateRef certificate;
2214 CFArrayRef names;
2215 CFStringRef name, ID;
2216
65c25746 2217 certificate = crypto_cssm_x509cert_CreateSecCertificateRef(cert);
e8d9021d 2218 if (certificate == NULL) {
65c25746 2219 plog(ASL_LEVEL_ERR,
e8d9021d
A
2220 "failed to get SecCertificateRef\n");
2221 if (certStatus && !*certStatus) {
2222 *certStatus = CERT_STATUS_INVALID;
2223 }
52b7d2ce
A
2224 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2225 }
e8d9021d
A
2226 names = SecCertificateCopyRFC822Names(certificate);
2227 if (names == NULL) {
65c25746 2228 plog(ASL_LEVEL_ERR,
e8d9021d
A
2229 "failed to get subjectName\n");
2230 if (certStatus && !*certStatus) {
2231 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2232 }
2233 CFRelease(certificate);
52b7d2ce
A
2234 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2235 }
e8d9021d 2236 count = CFArrayGetCount(names);
65c25746 2237 ID = CFStringCreateWithBytes(kCFAllocatorDefault, id, idlen, kCFStringEncodingUTF8, FALSE);
e8d9021d 2238 if (ID == NULL) {
65c25746 2239 plog(ASL_LEVEL_ERR,
e8d9021d
A
2240 "memory error\n");
2241 if (certStatus && !*certStatus) {
2242 *certStatus = CERT_STATUS_INVALID;
2243 }
2244 CFRelease(names);
2245 CFRelease(certificate);
2246 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2247 }
2248 for (pos = 0; pos < count; pos++) {
2249 name = CFArrayGetValueAtIndex(names, pos);
2250 if (CFStringCompare(name, ID, 0) == kCFCompareEqualTo) {
2251 CFRelease(ID);
2252 CFRelease(names);
2253 CFRelease(certificate);
2254 return 0;
2255 }
52b7d2ce 2256 }
65c25746
A
2257 plog(ASL_LEVEL_ERR, "ID mismatched with subjectAltName.\n");
2258 plog(ASL_LEVEL_ERR,
e8d9021d 2259 "subjectAltName (expected type %s):\n", s_ipsecdoi_ident(idtype));
65c25746 2260 plogdump(ASL_LEVEL_ERR, id, idlen, "ID:\n");
e8d9021d
A
2261 CFRelease(ID);
2262 CFRelease(names);
2263 CFRelease(certificate);
2264 if (certStatus && !*certStatus) {
2265 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2266 }
2267 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
52b7d2ce 2268 }
e8d9021d 2269#else
52b7d2ce
A
2270 case IPSECDOI_ID_FQDN:
2271 case IPSECDOI_ID_USER_FQDN:
2272 {
2273 int pos;
2274
2275 for (pos = 1; ; pos++) {
e8d9021d 2276 if (eay_get_x509subjectaltname(cert, &altname, &type, pos, &len) != 0) {
65c25746 2277 plog(ASL_LEVEL_ERR,
52b7d2ce 2278 "failed to get subjectAltName\n");
e8d9021d
A
2279 if (certStatus && !*certStatus) {
2280 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2281 }
52b7d2ce
A
2282 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
2283 }
2284
2285 /* it's the end condition of the loop. */
2286 if (!altname) {
65c25746 2287 plog(ASL_LEVEL_ERR,
e8d9021d
A
2288 "invalid subjectAltName\n");
2289 if (certStatus && !*certStatus) {
2290 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2291 }
2292 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
52b7d2ce
A
2293 }
2294
e8d9021d
A
2295 if (check_typeofcertname(idtype, type) != 0) {
2296 /* wrong general type - skip this one */
2297 racoon_free(altname);
2298 altname = NULL;
2299 continue;
2300 }
52b7d2ce 2301
e8d9021d
A
2302 if (idlen != strlen(altname)) {
2303 /* wrong length - skip this one */
2304 racoon_free(altname);
2305 altname = NULL;
2306 continue;
2307 }
2308 error = memcmp(id, altname, idlen);
2309 if (error)
2310 continue;
52b7d2ce 2311 racoon_free(altname);
e8d9021d 2312 return 0;
52b7d2ce 2313 }
65c25746
A
2314 plog(ASL_LEVEL_ERR, "ID mismatched with subjectAltName.\n");
2315 plog(ASL_LEVEL_ERR,
e8d9021d
A
2316 "subjectAltName (expected type %s, got type %s):\n",
2317 s_ipsecdoi_ident(idtype),
2318 s_ipsecdoi_ident(type));
65c25746
A
2319 plogdump(ASL_LEVEL_ERR, altname, len, "subjectAltName (expected type %s, got type %s):\n",
2320 s_ipsecdoi_ident(idtype),
2321 s_ipsecdoi_ident(type));
2322 plogdump(ASL_LEVEL_ERR, id, idlen, "ID:\n");
52b7d2ce 2323 racoon_free(altname);
e8d9021d
A
2324 if (certStatus && !*certStatus)
2325 *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
2326 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
52b7d2ce 2327 }
e8d9021d 2328#endif
52b7d2ce 2329 default:
65c25746 2330 plog(ASL_LEVEL_ERR,
52b7d2ce 2331 "Impropper ID type passed: %s.\n",
e8d9021d 2332 s_ipsecdoi_ident(idtype));
52b7d2ce 2333 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
e8d9021d 2334 }
52b7d2ce
A
2335 /*NOTREACHED*/
2336}
e8d9021d 2337#ifdef HAVE_OPENSSL
52b7d2ce 2338static int
65c25746 2339check_typeofcertname(int doi, int genid)
52b7d2ce
A
2340{
2341 switch (doi) {
2342 case IPSECDOI_ID_IPV4_ADDR:
2343 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
2344 case IPSECDOI_ID_IPV6_ADDR:
2345 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
2346 case IPSECDOI_ID_IPV4_ADDR_RANGE:
2347 case IPSECDOI_ID_IPV6_ADDR_RANGE:
2348 if (genid != GENT_IPADD)
2349 return -1;
2350 return 0;
2351 case IPSECDOI_ID_FQDN:
2352 if (genid != GENT_DNS)
2353 return -1;
2354 return 0;
2355 case IPSECDOI_ID_USER_FQDN:
2356 if (genid != GENT_EMAIL)
2357 return -1;
2358 return 0;
2359 case IPSECDOI_ID_DER_ASN1_DN: /* should not be passed to this function*/
2360 case IPSECDOI_ID_DER_ASN1_GN:
2361 case IPSECDOI_ID_KEY_ID:
2362 default:
2363 return -1;
2364 }
2365 /*NOTREACHED*/
2366}
e8d9021d 2367#endif
52b7d2ce
A
2368
2369/*
2370 * save certificate including certificate type.
2371 */
2372int
65c25746 2373oakley_savecert(phase1_handle_t *iph1, struct isakmp_gen *gen)
52b7d2ce
A
2374{
2375 cert_t **c;
2376 u_int8_t type;
52b7d2ce
A
2377 type = *(u_int8_t *)(gen + 1) & 0xff;
2378
2379 switch (type) {
52b7d2ce 2380 case ISAKMP_CERT_X509SIGN:
52b7d2ce
A
2381 c = &iph1->cert_p;
2382 break;
52b7d2ce 2383 default:
65c25746 2384 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2385 "Invalid CERT type %d\n", type);
2386 return -1;
2387 }
2388
52b7d2ce 2389 if (*c) {
65c25746 2390 plog(ASL_LEVEL_WARNING,
e8d9021d 2391 "preexisting CERT payload... chaining.\n");
52b7d2ce 2392 }
52b7d2ce 2393
65c25746
A
2394 cert_t *new;
2395 new = save_certbuf(gen);
2396 if (!new) {
2397 plog(ASL_LEVEL_ERR,
2398 "Failed to get CERT buffer.\n");
2399 return -1;
2400 }
52b7d2ce 2401
65c25746
A
2402 switch (new->type) {
2403 case ISAKMP_CERT_X509SIGN:
2404 /* Ignore cert if it doesn't match identity
2405 * XXX If verify cert is disabled, we still just take
2406 * the first certificate....
2407 */
2408 *c = oakley_appendcert_to_certchain(*c, new);
2409 plog(ASL_LEVEL_DEBUG, "CERT saved:\n");
2410 break;
2411 default:
2412 /* XXX */
2413 oakley_delcert(new);
2414 return 0;
2415 }
52b7d2ce
A
2416
2417 return 0;
2418}
2419
2420/*
2421 * save certificate including certificate type.
2422 */
2423int
65c25746 2424oakley_savecr(phase1_handle_t *iph1, struct isakmp_gen *gen)
52b7d2ce
A
2425{
2426 cert_t **c;
2427 u_int8_t type;
e8d9021d 2428 cert_t *new;
52b7d2ce
A
2429
2430 type = *(u_int8_t *)(gen + 1) & 0xff;
2431
2432 switch (type) {
52b7d2ce 2433 case ISAKMP_CERT_X509SIGN:
e97d2cf9
A
2434 if (iph1->cr_p) {
2435 oakley_delcert(iph1->cr_p);
2436 iph1->cr_p = NULL;
2437 }
52b7d2ce
A
2438 c = &iph1->cr_p;
2439 break;
52b7d2ce 2440 default:
65c25746 2441 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2442 "Invalid CR type %d\n", type);
2443 return -1;
2444 }
2445
e8d9021d
A
2446 new = save_certbuf(gen);
2447 if (!new) {
65c25746 2448 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2449 "Failed to get CR buffer.\n");
2450 return -1;
2451 }
e8d9021d 2452 *c = oakley_appendcert_to_certchain(*c, new);
65c25746 2453 plog(ASL_LEVEL_DEBUG, "CR saved\n");
52b7d2ce
A
2454
2455 return 0;
2456}
2457
2458static cert_t *
65c25746 2459save_certbuf(struct isakmp_gen *gen)
52b7d2ce
A
2460{
2461 cert_t *new;
2462
d1e348cf 2463 if(ntohs(gen->len) <= sizeof(*gen)){
65c25746 2464 plog(ASL_LEVEL_ERR,
d1e348cf
A
2465 "Len is too small !!.\n");
2466 return NULL;
2467 }
2468
52b7d2ce
A
2469 new = oakley_newcert();
2470 if (!new) {
65c25746 2471 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2472 "Failed to get CERT buffer.\n");
2473 return NULL;
2474 }
2475
2476 new->pl = vmalloc(ntohs(gen->len) - sizeof(*gen));
2477 if (new->pl == NULL) {
65c25746 2478 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2479 "Failed to copy CERT from packet.\n");
2480 oakley_delcert(new);
2481 new = NULL;
2482 return NULL;
2483 }
2484 memcpy(new->pl->v, gen + 1, new->pl->l);
2485 new->type = new->pl->v[0] & 0xff;
2486 new->cert.v = new->pl->v + 1;
2487 new->cert.l = new->pl->l - 1;
2488
2489 return new;
2490}
2491
52b7d2ce
A
2492/*
2493 * get my CR.
2494 * NOTE: No Certificate Authority field is included to CR payload at the
2495 * moment. Becuase any certificate authority are accepted without any check.
2496 * The section 3.10 in RFC2408 says that this field SHOULD not be included,
2497 * if there is no specific certificate authority requested.
2498 */
2499vchar_t *
65c25746 2500oakley_getcr(phase1_handle_t *iph1)
52b7d2ce
A
2501{
2502 vchar_t *buf;
2503
2504 buf = vmalloc(1);
2505 if (buf == NULL) {
65c25746 2506 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2507 "failed to get cr buffer\n");
2508 return NULL;
2509 }
d1e348cf
A
2510 if(iph1->rmconf->certtype == ISAKMP_CERT_NONE) {
2511 buf->v[0] = iph1->rmconf->cacerttype;
65c25746 2512 plog(ASL_LEVEL_DEBUG, "create my CR: NONE, using %s instead\n",
d1e348cf
A
2513 s_isakmp_certtype(iph1->rmconf->cacerttype));
2514 } else {
2515 buf->v[0] = iph1->rmconf->certtype;
65c25746 2516 plog(ASL_LEVEL_DEBUG, "create my CR: %s\n",
52b7d2ce 2517 s_isakmp_certtype(iph1->rmconf->certtype));
d1e348cf 2518 }
65c25746
A
2519 //if (buf->l > 1)
2520 // plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, "");
52b7d2ce
A
2521
2522 return buf;
2523}
2524
2525/*
2526 * check peer's CR.
2527 */
2528int
65c25746 2529oakley_checkcr(phase1_handle_t *iph1)
52b7d2ce
A
2530{
2531 if (iph1->cr_p == NULL)
2532 return 0;
2533
65c25746 2534 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
2535 "peer transmitted CR: %s\n",
2536 s_isakmp_certtype(iph1->cr_p->type));
2537
2538 if (iph1->cr_p->type != iph1->rmconf->certtype) {
65c25746 2539 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2540 "such a cert type isn't supported: %d\n",
2541 (char)iph1->cr_p->type);
2542 return -1;
2543 }
2544
2545 return 0;
2546}
2547
2548/*
2549 * check to need CR payload.
2550 */
2551int
65c25746 2552oakley_needcr(int type)
52b7d2ce
A
2553{
2554 switch (type) {
52b7d2ce
A
2555 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
2556#ifdef ENABLE_HYBRID
2557 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
d1e348cf
A
2558 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
2559 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
52b7d2ce
A
2560#endif
2561 return 1;
2562 default:
2563 return 0;
2564 }
2565 /*NOTREACHED*/
2566}
2567
85f41bec 2568vchar_t *
65c25746 2569oakley_getpskall(phase1_handle_t *iph1)
85f41bec
A
2570{
2571 vchar_t *secret = NULL;
2572
2573 if (iph1->rmconf->shared_secret) {
2574
2575 switch (iph1->rmconf->secrettype) {
2576 case SECRETTYPE_KEY:
2577 /* in psk file - use KEY from remote configuration to locate it */
2578 secret = getpsk(iph1->rmconf->shared_secret->v, iph1->rmconf->shared_secret->l-1);
2579 break;
2580#if HAVE_KEYCHAIN
2581 case SECRETTYPE_KEYCHAIN:
2582 /* in the system keychain */
2583 secret = getpskfromkeychain(iph1->rmconf->shared_secret->v, iph1->etype, iph1->rmconf->secrettype, NULL);
2584 break;
2585 case SECRETTYPE_KEYCHAIN_BY_ID:
2586 /* in the system keychain - use peer id */
2587 secret = getpskfromkeychain(iph1->rmconf->shared_secret->v, iph1->etype, iph1->rmconf->secrettype, iph1->id_p);
2588 break;
2589#endif // HAVE_KEYCHAIN
2590 case SECRETTYPE_USE:
2591 /* in the remote configuration */
2592 default:
2593 /* rmconf->shared_secret is a string and contains a NULL character that must be removed */
2594 secret = vmalloc(iph1->rmconf->shared_secret->l - 1);
2595 if (secret == NULL) {
65c25746 2596 plog(ASL_LEVEL_ERR, "memory error.\n");
85f41bec
A
2597 goto end;
2598 }
2599 memcpy(secret->v, iph1->rmconf->shared_secret->v, secret->l);
2600 }
d9c572c0 2601 } else if (iph1->etype != ISAKMP_ETYPE_IDENT) {
85f41bec
A
2602 secret = getpskbyname(iph1->id_p);
2603 if (!secret) {
2604 if (iph1->rmconf->verify_identifier) {
65c25746 2605 plog(ASL_LEVEL_ERR, "couldn't find pskey by peer's ID.\n");
85f41bec
A
2606 goto end;
2607 }
2608 }
2609 }
2610 if (!secret) {
65c25746 2611 plog(ASL_LEVEL_NOTICE, "try to get pskey by the peer's address.\n");
85f41bec 2612 secret = getpskbyaddr(iph1->remote);
65c25746
A
2613 if (!secret) {
2614 plog(ASL_LEVEL_ERR,
2615 "couldn't find the pskey by address %s.\n",
2616 saddrwop2str((struct sockaddr *)iph1->remote));
2617 }
85f41bec
A
2618 }
2619
2620end:
2621 return secret;
2622}
2623
52b7d2ce
A
2624/*
2625 * compute SKEYID
2626 * see seciton 5. Exchanges in RFC 2409
2627 * psk: SKEYID = prf(pre-shared-key, Ni_b | Nr_b)
2628 * sig: SKEYID = prf(Ni_b | Nr_b, g^ir)
2629 * enc: SKEYID = prf(H(Ni_b | Nr_b), CKY-I | CKY-R)
2630 */
2631int
65c25746 2632oakley_skeyid(phase1_handle_t *iph1)
52b7d2ce 2633{
65c25746
A
2634 vchar_t *key = NULL;
2635 vchar_t *buf = NULL;
2636 vchar_t *bp;
52b7d2ce
A
2637 char *p;
2638 int len;
2639 int error = -1;
d9c572c0 2640
52b7d2ce 2641 /* SKEYID */
d1e348cf 2642 switch (AUTHMETHOD(iph1)) {
65c25746 2643 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
d1e348cf 2644#ifdef ENABLE_HYBRID
65c25746
A
2645 case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
2646 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
d1e348cf 2647#endif
65c25746
A
2648 key = oakley_getpskall(iph1);
2649 if (key == NULL) {
2650 plog(ASL_LEVEL_ERR,
2651 "couldn't find the pskey for %s.\n",
2652 saddrwop2str((struct sockaddr *)iph1->remote));
2653 goto end;
2654 }
2655 plog(ASL_LEVEL_DEBUG, "the psk found.\n");
2656 /* should be secret PSK */
2657 plogdump(ASL_LEVEL_DEBUG, key->v, key->l, "psk: ");
2658
2659 len = iph1->nonce->l + iph1->nonce_p->l;
2660 buf = vmalloc(len);
2661 if (buf == NULL) {
2662 plog(ASL_LEVEL_ERR,
2663 "failed to get skeyid buffer\n");
2664 goto end;
2665 }
2666 p = buf->v;
2667
2668 bp = (iph1->side == INITIATOR ? iph1->nonce : iph1->nonce_p);
2669 //plogdump(ASL_LEVEL_DEBUG, bp->v, bp->l, "nonce 1: ");
2670 memcpy(p, bp->v, bp->l);
2671 p += bp->l;
2672
2673 bp = (iph1->side == INITIATOR ? iph1->nonce_p : iph1->nonce);
2674 //plogdump(ASL_LEVEL_DEBUG, bp->v, bp->l, "nonce 2: ");
2675 memcpy(p, bp->v, bp->l);
2676 p += bp->l;
2677
2678 iph1->skeyid = oakley_prf(key, buf, iph1);
2679
2680 if (iph1->skeyid == NULL)
2681 goto end;
2682 break;
2683
2684 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
52b7d2ce 2685#ifdef ENABLE_HYBRID
65c25746
A
2686 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
2687 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
2688 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
2689 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
52b7d2ce 2690#endif
65c25746
A
2691 len = iph1->nonce->l + iph1->nonce_p->l;
2692 buf = vmalloc(len);
2693 if (buf == NULL) {
2694 plog(ASL_LEVEL_ERR,
2695 "failed to get nonce buffer\n");
2696 goto end;
2697 }
2698 p = buf->v;
2699
2700 bp = (iph1->side == INITIATOR ? iph1->nonce : iph1->nonce_p);
2701 //plogdump(ASL_LEVEL_DEBUG, bp->v, bp->l, "nonce1: ");
2702 memcpy(p, bp->v, bp->l);
2703 p += bp->l;
2704
2705 bp = (iph1->side == INITIATOR ? iph1->nonce_p : iph1->nonce);
2706 //plogdump(ASL_LEVEL_DEBUG, bp->v, bp->l, "nonce2: ");
2707 memcpy(p, bp->v, bp->l);
2708 p += bp->l;
2709
2710 iph1->skeyid = oakley_prf(buf, iph1->dhgxy, iph1);
2711 if (iph1->skeyid == NULL)
2712 goto end;
2713 break;
2714 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
2715 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
d1e348cf 2716#ifdef ENABLE_HYBRID
65c25746
A
2717 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
2718 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
2719 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
2720 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
d1e348cf 2721#endif
65c25746
A
2722 plog(ASL_LEVEL_WARNING,
2723 "not supported authentication method %s\n",
2724 s_oakley_attr_method(iph1->approval->authmethod));
2725 goto end;
2726 default:
2727 plog(ASL_LEVEL_ERR,
2728 "invalid authentication method %d\n",
2729 iph1->approval->authmethod);
2730 goto end;
52b7d2ce 2731 }
65c25746
A
2732
2733 //plogdump(ASL_LEVEL_DEBUG, iph1->skeyid->v, iph1->skeyid->l, "IKEv1 SKEYID computed:\n");
2734
52b7d2ce 2735 error = 0;
65c25746 2736
52b7d2ce 2737end:
65c25746
A
2738 if (key != NULL)
2739 vfree(key);
52b7d2ce
A
2740 if (buf != NULL)
2741 vfree(buf);
2742 return error;
2743}
2744
2745/*
2746 * compute SKEYID_[dae]
52b7d2ce
A
2747 */
2748int
65c25746 2749oakley_skeyid_dae(phase1_handle_t *iph1)
52b7d2ce 2750{
d9c572c0 2751 vchar_t *buf = NULL;
52b7d2ce
A
2752 char *p;
2753 int len;
2754 int error = -1;
2755
2756 if (iph1->skeyid == NULL) {
65c25746 2757 plog(ASL_LEVEL_ERR, "no SKEYID found.\n");
52b7d2ce
A
2758 goto end;
2759 }
d9c572c0 2760
65c25746
A
2761 /*
2762 * see seciton 5. Exchanges in RFC 2409
2763 * SKEYID_d = prf(SKEYID, g^ir | CKY-I | CKY-R | 0)
2764 * SKEYID_a = prf(SKEYID, SKEYID_d | g^ir | CKY-I | CKY-R | 1)
2765 * SKEYID_e = prf(SKEYID, SKEYID_a | g^ir | CKY-I | CKY-R | 2)
2766 */
52b7d2ce
A
2767 /* SKEYID D */
2768 /* SKEYID_d = prf(SKEYID, g^xy | CKY-I | CKY-R | 0) */
2769 len = iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1;
2770 buf = vmalloc(len);
2771 if (buf == NULL) {
65c25746 2772 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2773 "failed to get skeyid buffer\n");
2774 goto end;
2775 }
2776 p = buf->v;
2777
2778 memcpy(p, iph1->dhgxy->v, iph1->dhgxy->l);
2779 p += iph1->dhgxy->l;
2780 memcpy(p, (caddr_t)&iph1->index.i_ck, sizeof(cookie_t));
2781 p += sizeof(cookie_t);
2782 memcpy(p, (caddr_t)&iph1->index.r_ck, sizeof(cookie_t));
2783 p += sizeof(cookie_t);
2784 *p = 0;
2785 iph1->skeyid_d = oakley_prf(iph1->skeyid, buf, iph1);
2786 if (iph1->skeyid_d == NULL)
2787 goto end;
2788
2789 vfree(buf);
2790 buf = NULL;
2791
65c25746 2792 //plogdump(ASL_LEVEL_DEBUG, iph1->skeyid_d->v, iph1->skeyid_d->l, "SKEYID_d computed:\n");
52b7d2ce
A
2793
2794 /* SKEYID A */
2795 /* SKEYID_a = prf(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1) */
2796 len = iph1->skeyid_d->l + iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1;
2797 buf = vmalloc(len);
2798 if (buf == NULL) {
65c25746 2799 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2800 "failed to get skeyid buffer\n");
2801 goto end;
2802 }
2803 p = buf->v;
2804 memcpy(p, iph1->skeyid_d->v, iph1->skeyid_d->l);
2805 p += iph1->skeyid_d->l;
2806 memcpy(p, iph1->dhgxy->v, iph1->dhgxy->l);
2807 p += iph1->dhgxy->l;
2808 memcpy(p, (caddr_t)&iph1->index.i_ck, sizeof(cookie_t));
2809 p += sizeof(cookie_t);
2810 memcpy(p, (caddr_t)&iph1->index.r_ck, sizeof(cookie_t));
2811 p += sizeof(cookie_t);
2812 *p = 1;
2813 iph1->skeyid_a = oakley_prf(iph1->skeyid, buf, iph1);
2814 if (iph1->skeyid_a == NULL)
2815 goto end;
2816
2817 vfree(buf);
2818 buf = NULL;
2819
65c25746 2820 //plogdump(ASL_LEVEL_DEBUG, iph1->skeyid_a->v, iph1->skeyid_a->l, "SKEYID_a computed:\n");
52b7d2ce
A
2821
2822 /* SKEYID E */
2823 /* SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2) */
2824 len = iph1->skeyid_a->l + iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1;
2825 buf = vmalloc(len);
2826 if (buf == NULL) {
65c25746 2827 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2828 "failed to get skeyid buffer\n");
2829 goto end;
2830 }
2831 p = buf->v;
2832 memcpy(p, iph1->skeyid_a->v, iph1->skeyid_a->l);
2833 p += iph1->skeyid_a->l;
2834 memcpy(p, iph1->dhgxy->v, iph1->dhgxy->l);
2835 p += iph1->dhgxy->l;
2836 memcpy(p, (caddr_t)&iph1->index.i_ck, sizeof(cookie_t));
2837 p += sizeof(cookie_t);
2838 memcpy(p, (caddr_t)&iph1->index.r_ck, sizeof(cookie_t));
2839 p += sizeof(cookie_t);
2840 *p = 2;
2841 iph1->skeyid_e = oakley_prf(iph1->skeyid, buf, iph1);
2842 if (iph1->skeyid_e == NULL)
2843 goto end;
2844
2845 vfree(buf);
2846 buf = NULL;
2847
65c25746 2848 //plogdump(ASL_LEVEL_DEBUG, iph1->skeyid_e->v, iph1->skeyid_e->l, "SKEYID_e computed:\n");
52b7d2ce
A
2849
2850 error = 0;
2851
2852end:
2853 if (buf != NULL)
2854 vfree(buf);
2855 return error;
2856}
2857
2858/*
2859 * compute final encryption key.
2860 * see Appendix B.
2861 */
2862int
65c25746 2863oakley_compute_enckey(phase1_handle_t *iph1)
52b7d2ce
A
2864{
2865 u_int keylen, prflen;
2866 int error = -1;
2867
2868 /* RFC2409 p39 */
2869 keylen = alg_oakley_encdef_keylen(iph1->approval->enctype,
2870 iph1->approval->encklen);
2871 if (keylen == -1) {
65c25746 2872 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2873 "invalid encryption algoritym %d, "
2874 "or invalid key length %d.\n",
2875 iph1->approval->enctype,
2876 iph1->approval->encklen);
2877 goto end;
2878 }
2879 iph1->key = vmalloc(keylen >> 3);
2880 if (iph1->key == NULL) {
65c25746 2881 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2882 "failed to get key buffer\n");
2883 goto end;
2884 }
2885
2886 /* set prf length */
2887 prflen = alg_oakley_hashdef_hashlen(iph1->approval->hashtype);
2888 if (prflen == -1) {
65c25746 2889 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2890 "invalid hash type %d.\n", iph1->approval->hashtype);
2891 goto end;
2892 }
2893
2894 /* see isakmp-oakley-08 5.3. */
2895 if (iph1->key->l <= iph1->skeyid_e->l) {
2896 /*
2897 * if length(Ka) <= length(SKEYID_e)
2898 * Ka = first length(K) bit of SKEYID_e
2899 */
2900 memcpy(iph1->key->v, iph1->skeyid_e->v, iph1->key->l);
2901 } else {
2902 vchar_t *buf = NULL, *res = NULL;
2903 u_char *p, *ep;
2904 int cplen;
2905 int subkey;
2906
2907 /*
2908 * otherwise,
2909 * Ka = K1 | K2 | K3
2910 * where
2911 * K1 = prf(SKEYID_e, 0)
2912 * K2 = prf(SKEYID_e, K1)
2913 * K3 = prf(SKEYID_e, K2)
2914 */
65c25746 2915 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
2916 "len(SKEYID_e) < len(Ka) (%zu < %zu), "
2917 "generating long key (Ka = K1 | K2 | ...)\n",
2918 iph1->skeyid_e->l, iph1->key->l);
2919
2920 if ((buf = vmalloc(prflen >> 3)) == 0) {
65c25746 2921 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2922 "failed to get key buffer\n");
2923 goto end;
2924 }
2925 p = (u_char *)iph1->key->v;
2926 ep = p + iph1->key->l;
2927
2928 subkey = 1;
2929 while (p < ep) {
2930 if (p == (u_char *)iph1->key->v) {
2931 /* just for computing K1 */
2932 buf->v[0] = 0;
2933 buf->l = 1;
2934 }
2935 res = oakley_prf(iph1->skeyid_e, buf, iph1);
2936 if (res == NULL) {
2937 vfree(buf);
2938 goto end;
2939 }
65c25746 2940 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
2941 "compute intermediate encryption key K%d\n",
2942 subkey);
65c25746
A
2943 //plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, "");
2944 //plogdump(ASL_LEVEL_DEBUG, res->v, res->l, "");
52b7d2ce
A
2945
2946 cplen = (res->l < ep - p) ? res->l : ep - p;
2947 memcpy(p, res->v, cplen);
2948 p += cplen;
2949
2950 buf->l = prflen >> 3; /* to cancel K1 speciality */
2951 if (res->l != buf->l) {
65c25746 2952 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2953 "internal error: res->l=%zu buf->l=%zu\n",
2954 res->l, buf->l);
2955 vfree(res);
2956 vfree(buf);
2957 goto end;
2958 }
2959 memcpy(buf->v, res->v, res->l);
2960 vfree(res);
2961 subkey++;
2962 }
2963
2964 vfree(buf);
2965 }
2966
2967 /*
2968 * don't check any weak key or not.
2969 * draft-ietf-ipsec-ike-01.txt Appendix B.
2970 * draft-ietf-ipsec-ciph-aes-cbc-00.txt Section 2.3.
2971 */
52b7d2ce 2972
65c25746 2973 //plogdump(ASL_LEVEL_DEBUG, iph1->key->v, iph1->key->l, "final encryption key computed:\n");
52b7d2ce
A
2974
2975 error = 0;
2976
2977end:
2978 return error;
2979}
2980
2981/* allocated new buffer for CERT */
2982cert_t *
65c25746 2983oakley_newcert(void)
52b7d2ce
A
2984{
2985 cert_t *new;
2986
2987 new = racoon_calloc(1, sizeof(*new));
2988 if (new == NULL) {
65c25746 2989 plog(ASL_LEVEL_ERR,
52b7d2ce
A
2990 "failed to get cert's buffer\n");
2991 return NULL;
2992 }
2993
2994 new->pl = NULL;
e8d9021d 2995 new->chain = NULL;
52b7d2ce
A
2996
2997 return new;
2998}
2999
3000/* delete buffer for CERT */
3001void
65c25746 3002oakley_delcert_1(cert_t *cert)
52b7d2ce
A
3003{
3004 if (!cert)
3005 return;
3006 if (cert->pl)
3007 VPTRINIT(cert->pl);
3008 racoon_free(cert);
3009}
e8d9021d
A
3010
3011/* delete buffer for CERT */
3012void
65c25746 3013oakley_delcert(cert_t *cert)
e8d9021d
A
3014{
3015 cert_t *p, *to_delete;
3016
3017 if (!cert)
3018 return;
3019
3020 for (p = cert; p;) {
3021 to_delete = p;
3022 p = p->chain;
3023 oakley_delcert_1(to_delete);
3024 }
3025}
3026
3027/* delete buffer for CERT */
3028static cert_t *
65c25746 3029oakley_appendcert_to_certchain(cert_t *certchain, cert_t *new)
e8d9021d
A
3030{
3031 cert_t *p;
3032
3033 if (!certchain)
3034 return new;
3035
3036 for (p = certchain; p; p = p->chain) {
3037 if (!p->chain) {
3038 p->chain = new;
3039 return certchain;
3040 }
3041 }
3042 return NULL;
3043}
3044
52b7d2ce
A
3045/*
3046 * compute IV and set to ph1handle
3047 * IV = hash(g^xi | g^xr)
3048 * see 4.1 Phase 1 state in draft-ietf-ipsec-ike.
3049 */
3050int
65c25746 3051oakley_newiv(phase1_handle_t *iph1)
52b7d2ce
A
3052{
3053 struct isakmp_ivm *newivm = NULL;
3054 vchar_t *buf = NULL, *bp;
3055 char *p;
3056 int len;
3057
3058 /* create buffer */
3059 len = iph1->dhpub->l + iph1->dhpub_p->l;
3060 buf = vmalloc(len);
3061 if (buf == NULL) {
65c25746
A
3062 plog(ASL_LEVEL_ERR,
3063 "Failed to get IV buffer\n");
52b7d2ce
A
3064 return -1;
3065 }
3066
3067 p = buf->v;
3068
3069 bp = (iph1->side == INITIATOR ? iph1->dhpub : iph1->dhpub_p);
3070 memcpy(p, bp->v, bp->l);
3071 p += bp->l;
3072
3073 bp = (iph1->side == INITIATOR ? iph1->dhpub_p : iph1->dhpub);
3074 memcpy(p, bp->v, bp->l);
3075 p += bp->l;
3076
3077 /* allocate IVm */
3078 newivm = racoon_calloc(1, sizeof(struct isakmp_ivm));
3079 if (newivm == NULL) {
65c25746
A
3080 plog(ASL_LEVEL_ERR,
3081 "Failed to get IV buffer\n");
52b7d2ce
A
3082 vfree(buf);
3083 return -1;
3084 }
3085
3086 /* compute IV */
3087 newivm->iv = oakley_hash(buf, iph1);
3088 if (newivm->iv == NULL) {
3089 vfree(buf);
3090 oakley_delivm(newivm);
3091 return -1;
3092 }
3093
3094 /* adjust length of iv */
3095 newivm->iv->l = alg_oakley_encdef_blocklen(iph1->approval->enctype);
3096 if (newivm->iv->l == -1) {
65c25746
A
3097 plog(ASL_LEVEL_ERR,
3098 "Invalid encryption algorithm %d.\n",
52b7d2ce
A
3099 iph1->approval->enctype);
3100 vfree(buf);
3101 oakley_delivm(newivm);
3102 return -1;
3103 }
3104
3105 /* create buffer to save iv */
3106 if ((newivm->ive = vdup(newivm->iv)) == NULL) {
65c25746 3107 plog(ASL_LEVEL_ERR,
52b7d2ce
A
3108 "vdup (%s)\n", strerror(errno));
3109 vfree(buf);
3110 oakley_delivm(newivm);
3111 return -1;
3112 }
3113
3114 vfree(buf);
3115
65c25746 3116 //plogdump(ASL_LEVEL_DEBUG, newivm->iv->v, newivm->iv->l, "IV computed:\n");
52b7d2ce 3117
d1e348cf
A
3118 if (iph1->ivm != NULL)
3119 oakley_delivm(iph1->ivm);
3120
52b7d2ce
A
3121 iph1->ivm = newivm;
3122
3123 return 0;
3124}
3125
3126/*
3127 * compute IV for the payload after phase 1.
3128 * It's not limited for phase 2.
3129 * if pahse 1 was encrypted.
3130 * IV = hash(last CBC block of Phase 1 | M-ID)
3131 * if phase 1 was not encrypted.
3132 * IV = hash(phase 1 IV | M-ID)
3133 * see 4.2 Phase 2 state in draft-ietf-ipsec-ike.
3134 */
3135struct isakmp_ivm *
65c25746 3136oakley_newiv2(phase1_handle_t *iph1, u_int32_t msgid)
52b7d2ce
A
3137{
3138 struct isakmp_ivm *newivm = NULL;
3139 vchar_t *buf = NULL;
3140 char *p;
3141 int len;
3142 int error = -1;
3143
3144 /* create buffer */
3145 len = iph1->ivm->iv->l + sizeof(msgid_t);
3146 buf = vmalloc(len);
3147 if (buf == NULL) {
65c25746
A
3148 plog(ASL_LEVEL_ERR,
3149 "Failed to get IV buffer\n");
52b7d2ce
A
3150 goto end;
3151 }
3152
3153 p = buf->v;
3154
3155 memcpy(p, iph1->ivm->iv->v, iph1->ivm->iv->l);
3156 p += iph1->ivm->iv->l;
3157
3158 memcpy(p, &msgid, sizeof(msgid));
3159
65c25746
A
3160 plog(ASL_LEVEL_DEBUG, "Compute IV for Phase 2\n");
3161 //plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, "Phase 1 last IV:\n");
52b7d2ce
A
3162
3163 /* allocate IVm */
3164 newivm = racoon_calloc(1, sizeof(struct isakmp_ivm));
3165 if (newivm == NULL) {
65c25746
A
3166 plog(ASL_LEVEL_ERR,
3167 "Failed to get IV buffer\n");
52b7d2ce
A
3168 goto end;
3169 }
3170
3171 /* compute IV */
3172 if ((newivm->iv = oakley_hash(buf, iph1)) == NULL)
3173 goto end;
3174
3175 /* adjust length of iv */
3176 newivm->iv->l = alg_oakley_encdef_blocklen(iph1->approval->enctype);
3177 if (newivm->iv->l == -1) {
65c25746
A
3178 plog(ASL_LEVEL_ERR,
3179 "Invalid encryption algorithm %d.\n",
52b7d2ce
A
3180 iph1->approval->enctype);
3181 goto end;
3182 }
3183
3184 /* create buffer to save new iv */
3185 if ((newivm->ive = vdup(newivm->iv)) == NULL) {
65c25746 3186 plog(ASL_LEVEL_ERR, "vdup (%s)\n", strerror(errno));
52b7d2ce
A
3187 goto end;
3188 }
3189
3190 error = 0;
3191
65c25746 3192 //plogdump(ASL_LEVEL_DEBUG, newivm->iv->v, newivm->iv->l, "Phase 2 IV computed:\n");
52b7d2ce
A
3193
3194end:
3195 if (error && newivm != NULL){
3196 oakley_delivm(newivm);
3197 newivm=NULL;
3198 }
3199 if (buf != NULL)
3200 vfree(buf);
3201 return newivm;
3202}
3203
3204void
65c25746 3205oakley_delivm(struct isakmp_ivm *ivm)
52b7d2ce
A
3206{
3207 if (ivm == NULL)
3208 return;
3209
3210 if (ivm->iv != NULL)
3211 vfree(ivm->iv);
3212 if (ivm->ive != NULL)
3213 vfree(ivm->ive);
3214 racoon_free(ivm);
65c25746 3215 plog(ASL_LEVEL_DEBUG, "IV freed\n");
52b7d2ce
A
3216
3217 return;
3218}
3219
3220/*
3221 * decrypt packet.
3222 * save new iv and old iv.
3223 */
3224vchar_t *
65c25746 3225oakley_do_ikev1_decrypt(phase1_handle_t *iph1, vchar_t *msg, vchar_t *ivdp, vchar_t *ivep)
52b7d2ce
A
3226{
3227 vchar_t *buf = NULL, *new = NULL;
3228 char *pl;
3229 int len;
3230 u_int8_t padlen;
3231 int blen;
3232 int error = -1;
3233
65c25746 3234 plog(ASL_LEVEL_DEBUG, "Begin decryption.\n");
52b7d2ce
A
3235
3236 blen = alg_oakley_encdef_blocklen(iph1->approval->enctype);
3237 if (blen == -1) {
65c25746
A
3238 plog(ASL_LEVEL_ERR,
3239 "Invalid encryption algorithm %d.\n",
52b7d2ce
A
3240 iph1->approval->enctype);
3241 goto end;
3242 }
3243
3244 /* save IV for next, but not sync. */
3245 memset(ivep->v, 0, ivep->l);
3246 memcpy(ivep->v, (caddr_t)&msg->v[msg->l - blen], blen);
3247
65c25746 3248 plogdump(ASL_LEVEL_DEBUG, ivep->v, ivep->l, "IV was saved for next processing:\n");
52b7d2ce
A
3249
3250 pl = msg->v + sizeof(struct isakmp);
3251
3252 len = msg->l - sizeof(struct isakmp);
3253
3254 /* create buffer */
3255 buf = vmalloc(len);
3256 if (buf == NULL) {
65c25746
A
3257 plog(ASL_LEVEL_ERR,
3258 "Failed to get buffer to decrypt.\n");
52b7d2ce
A
3259 goto end;
3260 }
3261 memcpy(buf->v, pl, len);
3262
3263 /* do decrypt */
3264 new = alg_oakley_encdef_decrypt(iph1->approval->enctype,
3265 buf, iph1->key, ivdp);
47612122 3266 if (new == NULL || new->v == NULL || new->l == 0) {
65c25746
A
3267 plog(ASL_LEVEL_ERR,
3268 "Decryption %d failed.\n", iph1->approval->enctype);
52b7d2ce
A
3269 goto end;
3270 }
65c25746 3271 //plogdump(ASL_LEVEL_DEBUG, iph1->key->v, iph1->key->l, "with key:\n");
52b7d2ce
A
3272
3273 vfree(buf);
3274 buf = NULL;
3275 if (new == NULL)
3276 goto end;
3277
65c25746 3278 plog(ASL_LEVEL_DEBUG, "decrypted payload by IV:\n");
52b7d2ce
A
3279
3280 /* get padding length */
3281 if (lcconf->pad_excltail)
3282 padlen = new->v[new->l - 1] + 1;
3283 else
3284 padlen = new->v[new->l - 1];
65c25746 3285 plog(ASL_LEVEL_DEBUG, "padding len=%u\n", padlen);
52b7d2ce
A
3286
3287 /* trim padding */
3288 if (lcconf->pad_strict) {
3289 if (padlen > new->l) {
65c25746
A
3290 plog(ASL_LEVEL_ERR, "invalid padding len=%u, buflen=%zu.\n",
3291 padlen, new->l);
52b7d2ce
A
3292 goto end;
3293 }
3294 new->l -= padlen;
65c25746 3295 plog(ASL_LEVEL_DEBUG, "trimmed padding\n");
52b7d2ce 3296 } else {
65c25746 3297 plog(ASL_LEVEL_DEBUG, "skip to trim padding.\n");
52b7d2ce
A
3298 }
3299
3300 /* create new buffer */
3301 len = sizeof(struct isakmp) + new->l;
3302 buf = vmalloc(len);
3303 if (buf == NULL) {
65c25746 3304 plog(ASL_LEVEL_ERR,
52b7d2ce
A
3305 "failed to get buffer to decrypt.\n");
3306 goto end;
3307 }
3308 memcpy(buf->v, msg->v, sizeof(struct isakmp));
3309 memcpy(buf->v + sizeof(struct isakmp), new->v, new->l);
3310 ((struct isakmp *)buf->v)->len = htonl(buf->l);
3311
65c25746 3312 plog(ASL_LEVEL_DEBUG, "decrypted.\n");
52b7d2ce
A
3313
3314#ifdef HAVE_PRINT_ISAKMP_C
3315 isakmp_printpacket(buf, iph1->remote, iph1->local, 1);
3316#endif
3317
3318 error = 0;
3319
3320end:
3321 if (error && buf != NULL) {
3322 vfree(buf);
3323 buf = NULL;
3324 }
3325 if (new != NULL)
3326 vfree(new);
3327
3328 return buf;
3329}
3330
65c25746
A
3331/*
3332 * decrypt packet.
3333 */
3334vchar_t *
3335oakley_do_decrypt(phase1_handle_t *iph1, vchar_t *msg, vchar_t *ivdp, vchar_t *ivep)
3336{
3337 if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
3338 return(oakley_do_ikev1_decrypt(iph1, msg, ivdp, ivep));
3339 }
d9c572c0 3340
65c25746
A
3341 plog(ASL_LEVEL_ERR, "Failed to decrypt invalid IKE version");
3342 return NULL;
3343}
3344
52b7d2ce
A
3345/*
3346 * encrypt packet.
3347 */
3348vchar_t *
65c25746 3349oakley_do_ikev1_encrypt(phase1_handle_t *iph1, vchar_t *msg, vchar_t *ivep, vchar_t *ivp)
52b7d2ce
A
3350{
3351 vchar_t *buf = 0, *new = 0;
3352 char *pl;
3353 int len;
3354 u_int padlen;
3355 int blen;
3356 int error = -1;
3357
65c25746 3358 plog(ASL_LEVEL_DEBUG, "Begin encryption.\n");
52b7d2ce
A
3359
3360 /* set cbc block length */
3361 blen = alg_oakley_encdef_blocklen(iph1->approval->enctype);
3362 if (blen == -1) {
65c25746
A
3363 plog(ASL_LEVEL_ERR,
3364 "Invalid encryption algorithm %d.\n",
52b7d2ce
A
3365 iph1->approval->enctype);
3366 goto end;
3367 }
3368
3369 pl = msg->v + sizeof(struct isakmp);
3370 len = msg->l - sizeof(struct isakmp);
3371
3372 /* add padding */
3373 padlen = oakley_padlen(len, blen);
65c25746 3374 plog(ASL_LEVEL_DEBUG, "pad length = %u\n", padlen);
52b7d2ce
A
3375
3376 /* create buffer */
3377 buf = vmalloc(len + padlen);
3378 if (buf == NULL) {
65c25746
A
3379 plog(ASL_LEVEL_ERR,
3380 "Failed to get buffer to encrypt.\n");
52b7d2ce
A
3381 goto end;
3382 }
3383 if (padlen) {
3384 int i;
3385 char *p = &buf->v[len];
3386 if (lcconf->pad_random) {
3387 for (i = 0; i < padlen; i++)
3388 *p++ = eay_random() & 0xff;
3389 }
3390 }
3391 memcpy(buf->v, pl, len);
3392
3393 /* make pad into tail */
3394 if (lcconf->pad_excltail)
3395 buf->v[len + padlen - 1] = padlen - 1;
3396 else
3397 buf->v[len + padlen - 1] = padlen;
3398
65c25746 3399 plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, "About to encrypt %d bytes", buf->l);
52b7d2ce
A
3400
3401 /* do encrypt */
3402 new = alg_oakley_encdef_encrypt(iph1->approval->enctype,
3403 buf, iph1->key, ivep);
3404 if (new == NULL) {
65c25746
A
3405 plog(ASL_LEVEL_ERR,
3406 "Encryption %d failed.\n", iph1->approval->enctype);
52b7d2ce
A
3407 goto end;
3408 }
65c25746 3409 //plogdump(ASL_LEVEL_DEBUG, iph1->key->v, iph1->key->l, "with key:\n");
52b7d2ce
A
3410
3411 vfree(buf);
3412 buf = NULL;
3413 if (new == NULL)
3414 goto end;
3415
65c25746 3416 //plogdump(ASL_LEVEL_DEBUG, ivep->v, ivep->l, "encrypted payload by IV:\n");
52b7d2ce
A
3417
3418 /* save IV for next */
3419 memset(ivp->v, 0, ivp->l);
3420 memcpy(ivp->v, (caddr_t)&new->v[new->l - blen], blen);
3421
65c25746 3422 //plogdump(ASL_LEVEL_DEBUG, ivp->v, ivp->l, "save IV for next:\n");
52b7d2ce
A
3423
3424 /* create new buffer */
3425 len = sizeof(struct isakmp) + new->l;
3426 buf = vmalloc(len);
3427 if (buf == NULL) {
65c25746
A
3428 plog(ASL_LEVEL_ERR,
3429 "Failed to get buffer to encrypt.\n");
52b7d2ce
A
3430 goto end;
3431 }
3432 memcpy(buf->v, msg->v, sizeof(struct isakmp));
3433 memcpy(buf->v + sizeof(struct isakmp), new->v, new->l);
3434 ((struct isakmp *)buf->v)->len = htonl(buf->l);
3435
3436 error = 0;
3437
65c25746 3438 plog(ASL_LEVEL_DEBUG, "Encrypted.\n");
52b7d2ce
A
3439
3440end:
3441 if (error && buf != NULL) {
3442 vfree(buf);
3443 buf = NULL;
3444 }
3445 if (new != NULL)
3446 vfree(new);
3447
3448 return buf;
3449}
3450
65c25746
A
3451/*
3452 * encrypt packet.
3453 */
3454vchar_t *
3455oakley_do_encrypt(phase1_handle_t *iph1, vchar_t *msg, vchar_t *ivep, vchar_t *ivp)
3456{
3457 if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
3458 return(oakley_do_ikev1_encrypt(iph1, msg, ivep, ivp));
3459 }
d9c572c0 3460
65c25746
A
3461 plog(ASL_LEVEL_ERR, "Failed to encrypt invalid IKE version");
3462 return NULL;
3463}
3464
52b7d2ce
A
3465/* culculate padding length */
3466static int
65c25746 3467oakley_padlen(int len, int base)
52b7d2ce
A
3468{
3469 int padlen;
3470
65c25746 3471 padlen = base - (len % base);
52b7d2ce
A
3472
3473 if (lcconf->pad_randomlen)
3474 padlen += ((eay_random() % (lcconf->pad_maxsize + 1) + 1) *
3475 base);
3476
3477 return padlen;
3478}
3479
52b7d2ce
A
3480/* -----------------------------------------------------------------------------
3481The base-64 encoding packs three 8-bit bytes into four 7-bit ASCII
3482characters. If the number of bytes in the original data isn't divisable
3483by three, "=" characters are used to pad the encoded data. The complete
3484set of characters used in base-64 are:
3485 'A'..'Z' => 00..25
3486 'a'..'z' => 26..51
3487 '0'..'9' => 52..61
3488 '+' => 62
3489 '/' => 63
3490 '=' => pad
3491
3492----------------------------------------------------------------------------- */
3493static const signed char base64_DecodeTable[128] = {
3494 /* 000 */ -1, -1, -1, -1, -1, -1, -1, -1,
3495 /* 010 */ -1, -1, -1, -1, -1, -1, -1, -1,
3496 /* 020 */ -1, -1, -1, -1, -1, -1, -1, -1,
3497 /* 030 */ -1, -1, -1, -1, -1, -1, -1, -1,
3498 /* ' ' */ -1, -1, -1, -1, -1, -1, -1, -1,
3499 /* '(' */ -1, -1, -1, 62, -1, -1, -1, 63,
3500 /* '0' */ 52, 53, 54, 55, 56, 57, 58, 59,
3501 /* '8' */ 60, 61, -1, -1, -1, 0, -1, -1,
3502 /* '@' */ -1, 0, 1, 2, 3, 4, 5, 6,
3503 /* 'H' */ 7, 8, 9, 10, 11, 12, 13, 14,
3504 /* 'P' */ 15, 16, 17, 18, 19, 20, 21, 22,
3505 /* 'X' */ 23, 24, 25, -1, -1, -1, -1, -1,
3506 /* '`' */ -1, 26, 27, 28, 29, 30, 31, 32,
3507 /* 'h' */ 33, 34, 35, 36, 37, 38, 39, 40,
3508 /* 'p' */ 41, 42, 43, 44, 45, 46, 47, 48,
3509 /* 'x' */ 49, 50, 51, -1, -1, -1, -1, -1
3510};
3511
3512static int base64toCFData(vchar_t *textin, CFDataRef *dataRef)
3513{
3514 uint8_t *tmpbuf;
3515 uint8_t c;
3516 int tmpbufpos = 0;
3517 int numeq = 0;
3518 int acc = 0;
3519 int cntr = 0;
65c25746 3520 uint8_t *textcur = (__typeof__(textcur))textin->v;
52b7d2ce
A
3521 int len = textin->l;
3522 int i;
3523
3524 tmpbuf = malloc(len); // len of result will be less than encoded len
3525 if (tmpbuf == NULL) {
3526 yyerror("memory error - could not allocate buffer for certificate reference conversion from base-64.");
3527 return -1;
3528 }
3529
3530 for (i = 0; i < len; i++) {
3531 c = *(textcur++);
3532 if (c == '=')
3533 numeq++;
3534 else if (!isspace(c))
3535 numeq = 0;
3536 if (base64_DecodeTable[c] < 0)
3537 continue;
3538 cntr++;
3539 acc <<= 6;
3540 acc += base64_DecodeTable[c];
3541 if (0 == (cntr & 0x3)) {
3542 tmpbuf[tmpbufpos++] = (acc >> 16) & 0xff;
3543 if (numeq < 2)
3544 tmpbuf[tmpbufpos++] = (acc >> 8) & 0xff;
3545 if (numeq < 1)
3546 tmpbuf[tmpbufpos++] = acc & 0xff;
3547 }
3548 }
3549 *dataRef = CFDataCreate(NULL, tmpbuf, tmpbufpos);
3550 free(tmpbuf);
3551 if (*dataRef)
3552 return 0;
3553 else
3554 return -1;
3555
3556}
e8d9021d 3557