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