No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / ipsec-tools / src / racoon / oakley.c
blob2110a6585fd787381f3efe91f258c28b847851b5
1 /* $NetBSD: oakley.c,v 1.16 2009/08/18 08:21:12 vanhu Exp $ */
3 /* Id: oakley.c,v 1.32 2006/05/26 12:19:46 manubsd Exp */
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.
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.
34 #include "config.h"
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 */
41 #include <openssl/pkcs7.h>
42 #include <openssl/x509.h>
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <errno.h>
49 #if TIME_WITH_SYS_TIME
50 # include <sys/time.h>
51 # include <time.h>
52 #else
53 # if HAVE_SYS_TIME_H
54 # include <sys/time.h>
55 # else
56 # include <time.h>
57 # endif
58 #endif
59 #ifdef ENABLE_HYBRID
60 #include <resolv.h>
61 #endif
63 #include "var.h"
64 #include "misc.h"
65 #include "vmbuf.h"
66 #include "str2val.h"
67 #include "plog.h"
68 #include "debug.h"
70 #include "isakmp_var.h"
71 #include "isakmp.h"
72 #ifdef ENABLE_HYBRID
73 #include "isakmp_xauth.h"
74 #include "isakmp_cfg.h"
75 #endif
76 #include "oakley.h"
77 #include "admin.h"
78 #include "privsep.h"
79 #include "localconf.h"
80 #include "remoteconf.h"
81 #include "policy.h"
82 #include "handler.h"
83 #include "ipsec_doi.h"
84 #include "algorithm.h"
85 #include "dhgroup.h"
86 #include "sainfo.h"
87 #include "proposal.h"
88 #include "crypto_openssl.h"
89 #include "dnssec.h"
90 #include "sockmisc.h"
91 #include "strnames.h"
92 #include "gcmalloc.h"
93 #include "rsalist.h"
95 #ifdef HAVE_GSSAPI
96 #include "gssapi.h"
97 #endif
99 #define OUTBOUND_SA 0
100 #define INBOUND_SA 1
102 #define INITDHVAL(a, s, d, t) \
103 do { \
104 vchar_t buf; \
105 buf.v = str2val((s), 16, &buf.l); \
106 memset(&a, 0, sizeof(struct dhgroup)); \
107 a.type = (t); \
108 a.prime = vdup(&buf); \
109 a.gen1 = 2; \
110 a.gen2 = 0; \
111 racoon_free(buf.v); \
112 } while(0);
114 struct dhgroup dh_modp768;
115 struct dhgroup dh_modp1024;
116 struct dhgroup dh_modp1536;
117 struct dhgroup dh_modp2048;
118 struct dhgroup dh_modp3072;
119 struct dhgroup dh_modp4096;
120 struct dhgroup dh_modp6144;
121 struct dhgroup dh_modp8192;
124 static int oakley_check_dh_pub __P((vchar_t *, vchar_t **));
125 static int oakley_compute_keymat_x __P((struct ph2handle *, int, int));
126 static int oakley_check_certid __P((struct ph1handle *iph1));
127 static int check_typeofcertname __P((int, int));
128 static int oakley_padlen __P((int, int));
129 static int get_plainrsa_fromlocal __P((struct ph1handle *, int));
131 int oakley_get_certtype(cert)
132 vchar_t *cert;
134 if (cert == NULL)
135 return ISAKMP_CERT_NONE;
137 return cert->v[0];
140 static vchar_t *
141 dump_isakmp_payload(gen)
142 struct isakmp_gen *gen;
144 vchar_t p;
146 if (ntohs(gen->len) <= sizeof(*gen)) {
147 plog(LLV_ERROR, LOCATION, NULL,
148 "Len is too small !!.\n");
149 return NULL;
152 p.v = (caddr_t) (gen + 1);
153 p.l = ntohs(gen->len) - sizeof(*gen);
155 return vdup(&p);
158 static vchar_t *
159 dump_x509(cert)
160 X509 *cert;
162 vchar_t *pl;
163 u_char *bp;
164 int len;
166 len = i2d_X509(cert, NULL);
168 pl = vmalloc(len + 1);
169 if (pl == NULL) {
170 plog(LLV_ERROR, LOCATION, NULL,
171 "Failed to copy CERT from packet.\n");
172 return NULL;
175 pl->v[0] = ISAKMP_CERT_X509SIGN;
176 bp = (u_char *) &pl->v[1];
177 i2d_X509(cert, &bp);
179 return pl;
185 oakley_get_defaultlifetime()
187 return OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
191 oakley_dhinit()
193 /* set DH MODP */
194 INITDHVAL(dh_modp768, OAKLEY_PRIME_MODP768,
195 OAKLEY_ATTR_GRP_DESC_MODP768, OAKLEY_ATTR_GRP_TYPE_MODP);
196 INITDHVAL(dh_modp1024, OAKLEY_PRIME_MODP1024,
197 OAKLEY_ATTR_GRP_DESC_MODP1024, OAKLEY_ATTR_GRP_TYPE_MODP);
198 INITDHVAL(dh_modp1536, OAKLEY_PRIME_MODP1536,
199 OAKLEY_ATTR_GRP_DESC_MODP1536, OAKLEY_ATTR_GRP_TYPE_MODP);
200 INITDHVAL(dh_modp2048, OAKLEY_PRIME_MODP2048,
201 OAKLEY_ATTR_GRP_DESC_MODP2048, OAKLEY_ATTR_GRP_TYPE_MODP);
202 INITDHVAL(dh_modp3072, OAKLEY_PRIME_MODP3072,
203 OAKLEY_ATTR_GRP_DESC_MODP3072, OAKLEY_ATTR_GRP_TYPE_MODP);
204 INITDHVAL(dh_modp4096, OAKLEY_PRIME_MODP4096,
205 OAKLEY_ATTR_GRP_DESC_MODP4096, OAKLEY_ATTR_GRP_TYPE_MODP);
206 INITDHVAL(dh_modp6144, OAKLEY_PRIME_MODP6144,
207 OAKLEY_ATTR_GRP_DESC_MODP6144, OAKLEY_ATTR_GRP_TYPE_MODP);
208 INITDHVAL(dh_modp8192, OAKLEY_PRIME_MODP8192,
209 OAKLEY_ATTR_GRP_DESC_MODP8192, OAKLEY_ATTR_GRP_TYPE_MODP);
211 return 0;
214 void
215 oakley_dhgrp_free(dhgrp)
216 struct dhgroup *dhgrp;
218 if (dhgrp->prime)
219 vfree(dhgrp->prime);
220 if (dhgrp->curve_a)
221 vfree(dhgrp->curve_a);
222 if (dhgrp->curve_b)
223 vfree(dhgrp->curve_b);
224 if (dhgrp->order)
225 vfree(dhgrp->order);
226 racoon_free(dhgrp);
230 * RFC2409 5
231 * The length of the Diffie-Hellman public value MUST be equal to the
232 * length of the prime modulus over which the exponentiation was
233 * performed, prepending zero bits to the value if necessary.
235 static int
236 oakley_check_dh_pub(prime, pub0)
237 vchar_t *prime, **pub0;
239 vchar_t *tmp;
240 vchar_t *pub = *pub0;
242 if (prime->l == pub->l)
243 return 0;
245 if (prime->l < pub->l) {
246 /* what should i do ? */
247 plog(LLV_ERROR, LOCATION, NULL,
248 "invalid public information was generated.\n");
249 return -1;
252 /* prime->l > pub->l */
253 tmp = vmalloc(prime->l);
254 if (tmp == NULL) {
255 plog(LLV_ERROR, LOCATION, NULL,
256 "failed to get DH buffer.\n");
257 return -1;
259 memcpy(tmp->v + prime->l - pub->l, pub->v, pub->l);
261 vfree(*pub0);
262 *pub0 = tmp;
264 return 0;
268 * compute sharing secret of DH
269 * IN: *dh, *pub, *priv, *pub_p
270 * OUT: **gxy
273 oakley_dh_compute(dh, pub, priv, pub_p, gxy)
274 const struct dhgroup *dh;
275 vchar_t *pub, *priv, *pub_p, **gxy;
277 #ifdef ENABLE_STATS
278 struct timeval start, end;
279 #endif
280 if ((*gxy = vmalloc(dh->prime->l)) == NULL) {
281 plog(LLV_ERROR, LOCATION, NULL,
282 "failed to get DH buffer.\n");
283 return -1;
286 #ifdef ENABLE_STATS
287 gettimeofday(&start, NULL);
288 #endif
289 switch (dh->type) {
290 case OAKLEY_ATTR_GRP_TYPE_MODP:
291 if (eay_dh_compute(dh->prime, dh->gen1, pub, priv, pub_p, gxy) < 0) {
292 plog(LLV_ERROR, LOCATION, NULL,
293 "failed to compute dh value.\n");
294 return -1;
296 break;
297 case OAKLEY_ATTR_GRP_TYPE_ECP:
298 case OAKLEY_ATTR_GRP_TYPE_EC2N:
299 plog(LLV_ERROR, LOCATION, NULL,
300 "dh type %d isn't supported.\n", dh->type);
301 return -1;
302 default:
303 plog(LLV_ERROR, LOCATION, NULL,
304 "invalid dh type %d.\n", dh->type);
305 return -1;
308 #ifdef ENABLE_STATS
309 gettimeofday(&end, NULL);
310 syslog(LOG_NOTICE, "%s(%s%zu): %8.6f", __func__,
311 s_attr_isakmp_group(dh->type), dh->prime->l << 3,
312 timedelta(&start, &end));
313 #endif
315 plog(LLV_DEBUG, LOCATION, NULL, "compute DH's shared.\n");
316 plogdump(LLV_DEBUG, (*gxy)->v, (*gxy)->l);
318 return 0;
322 * generate values of DH
323 * IN: *dh
324 * OUT: **pub, **priv
327 oakley_dh_generate(dh, pub, priv)
328 const struct dhgroup *dh;
329 vchar_t **pub, **priv;
331 #ifdef ENABLE_STATS
332 struct timeval start, end;
333 gettimeofday(&start, NULL);
334 #endif
335 switch (dh->type) {
336 case OAKLEY_ATTR_GRP_TYPE_MODP:
337 if (eay_dh_generate(dh->prime, dh->gen1, dh->gen2, pub, priv) < 0) {
338 plog(LLV_ERROR, LOCATION, NULL,
339 "failed to compute dh value.\n");
340 return -1;
342 break;
344 case OAKLEY_ATTR_GRP_TYPE_ECP:
345 case OAKLEY_ATTR_GRP_TYPE_EC2N:
346 plog(LLV_ERROR, LOCATION, NULL,
347 "dh type %d isn't supported.\n", dh->type);
348 return -1;
349 default:
350 plog(LLV_ERROR, LOCATION, NULL,
351 "invalid dh type %d.\n", dh->type);
352 return -1;
355 #ifdef ENABLE_STATS
356 gettimeofday(&end, NULL);
357 syslog(LOG_NOTICE, "%s(%s%zu): %8.6f", __func__,
358 s_attr_isakmp_group(dh->type), dh->prime->l << 3,
359 timedelta(&start, &end));
360 #endif
362 if (oakley_check_dh_pub(dh->prime, pub) != 0)
363 return -1;
365 plog(LLV_DEBUG, LOCATION, NULL, "compute DH's private.\n");
366 plogdump(LLV_DEBUG, (*priv)->v, (*priv)->l);
367 plog(LLV_DEBUG, LOCATION, NULL, "compute DH's public.\n");
368 plogdump(LLV_DEBUG, (*pub)->v, (*pub)->l);
370 return 0;
374 * copy pre-defined dhgroup values.
377 oakley_setdhgroup(group, dhgrp)
378 int group;
379 struct dhgroup **dhgrp;
381 struct dhgroup *g;
383 *dhgrp = NULL; /* just make sure, initialize */
385 g = alg_oakley_dhdef_group(group);
386 if (g == NULL) {
387 plog(LLV_ERROR, LOCATION, NULL,
388 "invalid DH parameter grp=%d.\n", group);
389 return -1;
392 if (!g->type || !g->prime || !g->gen1) {
393 /* unsuported */
394 plog(LLV_ERROR, LOCATION, NULL,
395 "unsupported DH parameters grp=%d.\n", group);
396 return -1;
399 *dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
400 if (*dhgrp == NULL) {
401 plog(LLV_ERROR, LOCATION, NULL,
402 "failed to get DH buffer.\n");
403 return 0;
406 /* set defined dh vlaues */
407 memcpy(*dhgrp, g, sizeof(*g));
408 (*dhgrp)->prime = vdup(g->prime);
410 return 0;
414 * PRF
416 * NOTE: we do not support prf with different input/output bitwidth,
417 * so we do not implement RFC2409 Appendix B (DOORAK-MAC example) in
418 * oakley_compute_keymat(). If you add support for such prf function,
419 * modify oakley_compute_keymat() accordingly.
421 vchar_t *
422 oakley_prf(key, buf, iph1)
423 vchar_t *key, *buf;
424 struct ph1handle *iph1;
426 vchar_t *res = NULL;
427 int type;
429 if (iph1->approval == NULL) {
431 * it's before negotiating hash algorithm.
432 * We use md5 as default.
434 type = OAKLEY_ATTR_HASH_ALG_MD5;
435 } else
436 type = iph1->approval->hashtype;
438 res = alg_oakley_hmacdef_one(type, key, buf);
439 if (res == NULL) {
440 plog(LLV_ERROR, LOCATION, NULL,
441 "invalid hmac algorithm %d.\n", type);
442 return NULL;
445 return res;
449 * hash
451 vchar_t *
452 oakley_hash(buf, iph1)
453 vchar_t *buf;
454 struct ph1handle *iph1;
456 vchar_t *res = NULL;
457 int type;
459 if (iph1->approval == NULL) {
461 * it's before negotiating hash algorithm.
462 * We use md5 as default.
464 type = OAKLEY_ATTR_HASH_ALG_MD5;
465 } else
466 type = iph1->approval->hashtype;
468 res = alg_oakley_hashdef_one(type, buf);
469 if (res == NULL) {
470 plog(LLV_ERROR, LOCATION, NULL,
471 "invalid hash algorithm %d.\n", type);
472 return NULL;
475 return res;
479 * compute KEYMAT
480 * see seciton 5.5 Phase 2 - Quick Mode in isakmp-oakley-05.
483 oakley_compute_keymat(iph2, side)
484 struct ph2handle *iph2;
485 int side;
487 int error = -1;
489 /* compute sharing secret of DH when PFS */
490 if (iph2->approval->pfs_group && iph2->dhpub_p) {
491 if (oakley_dh_compute(iph2->pfsgrp, iph2->dhpub,
492 iph2->dhpriv, iph2->dhpub_p, &iph2->dhgxy) < 0)
493 goto end;
496 /* compute keymat */
497 if (oakley_compute_keymat_x(iph2, side, INBOUND_SA) < 0
498 || oakley_compute_keymat_x(iph2, side, OUTBOUND_SA) < 0)
499 goto end;
501 plog(LLV_DEBUG, LOCATION, NULL, "KEYMAT computed.\n");
503 error = 0;
505 end:
506 return error;
510 * compute KEYMAT.
511 * KEYMAT = prf(SKEYID_d, protocol | SPI | Ni_b | Nr_b).
512 * If PFS is desired and KE payloads were exchanged,
513 * KEYMAT = prf(SKEYID_d, g(qm)^xy | protocol | SPI | Ni_b | Nr_b)
515 * NOTE: we do not support prf with different input/output bitwidth,
516 * so we do not implement RFC2409 Appendix B (DOORAK-MAC example).
518 static int
519 oakley_compute_keymat_x(iph2, side, sa_dir)
520 struct ph2handle *iph2;
521 int side;
522 int sa_dir;
524 vchar_t *buf = NULL, *res = NULL, *bp;
525 char *p;
526 int len;
527 int error = -1;
528 int pfs = 0;
529 int dupkeymat; /* generate K[1-dupkeymat] */
530 struct saproto *pr;
531 struct satrns *tr;
532 int encklen, authklen, l;
534 pfs = ((iph2->approval->pfs_group && iph2->dhgxy) ? 1 : 0);
536 len = pfs ? iph2->dhgxy->l : 0;
537 len += (1
538 + sizeof(u_int32_t) /* XXX SPI size */
539 + iph2->nonce->l
540 + iph2->nonce_p->l);
541 buf = vmalloc(len);
542 if (buf == NULL) {
543 plog(LLV_ERROR, LOCATION, NULL,
544 "failed to get keymat buffer.\n");
545 goto end;
548 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
549 p = buf->v;
551 /* if PFS */
552 if (pfs) {
553 memcpy(p, iph2->dhgxy->v, iph2->dhgxy->l);
554 p += iph2->dhgxy->l;
557 p[0] = pr->proto_id;
558 p += 1;
560 memcpy(p, (sa_dir == INBOUND_SA ? &pr->spi : &pr->spi_p),
561 sizeof(pr->spi));
562 p += sizeof(pr->spi);
564 bp = (side == INITIATOR ? iph2->nonce : iph2->nonce_p);
565 memcpy(p, bp->v, bp->l);
566 p += bp->l;
568 bp = (side == INITIATOR ? iph2->nonce_p : iph2->nonce);
569 memcpy(p, bp->v, bp->l);
570 p += bp->l;
572 /* compute IV */
573 plog(LLV_DEBUG, LOCATION, NULL, "KEYMAT compute with\n");
574 plogdump(LLV_DEBUG, buf->v, buf->l);
576 /* res = K1 */
577 res = oakley_prf(iph2->ph1->skeyid_d, buf, iph2->ph1);
578 if (res == NULL)
579 goto end;
581 /* compute key length needed */
582 encklen = authklen = 0;
583 switch (pr->proto_id) {
584 case IPSECDOI_PROTO_IPSEC_ESP:
585 for (tr = pr->head; tr; tr = tr->next) {
586 l = alg_ipsec_encdef_keylen(tr->trns_id,
587 tr->encklen);
588 if (l > encklen)
589 encklen = l;
591 l = alg_ipsec_hmacdef_hashlen(tr->authtype);
592 if (l > authklen)
593 authklen = l;
595 break;
596 case IPSECDOI_PROTO_IPSEC_AH:
597 for (tr = pr->head; tr; tr = tr->next) {
598 l = alg_ipsec_hmacdef_hashlen(tr->trns_id);
599 if (l > authklen)
600 authklen = l;
602 break;
603 default:
604 break;
606 plog(LLV_DEBUG, LOCATION, NULL, "encklen=%d authklen=%d\n",
607 encklen, authklen);
609 dupkeymat = (encklen + authklen) / 8 / res->l;
610 dupkeymat += 2; /* safety mergin */
611 if (dupkeymat < 3)
612 dupkeymat = 3;
613 plog(LLV_DEBUG, LOCATION, NULL,
614 "generating %zu bits of key (dupkeymat=%d)\n",
615 dupkeymat * 8 * res->l, dupkeymat);
616 if (0 < --dupkeymat) {
617 vchar_t *prev = res; /* K(n-1) */
618 vchar_t *seed = NULL; /* seed for Kn */
619 size_t l;
622 * generating long key (isakmp-oakley-08 5.5)
623 * KEYMAT = K1 | K2 | K3 | ...
624 * where
625 * src = [ g(qm)^xy | ] protocol | SPI | Ni_b | Nr_b
626 * K1 = prf(SKEYID_d, src)
627 * K2 = prf(SKEYID_d, K1 | src)
628 * K3 = prf(SKEYID_d, K2 | src)
629 * Kn = prf(SKEYID_d, K(n-1) | src)
631 plog(LLV_DEBUG, LOCATION, NULL,
632 "generating K1...K%d for KEYMAT.\n",
633 dupkeymat + 1);
635 seed = vmalloc(prev->l + buf->l);
636 if (seed == NULL) {
637 plog(LLV_ERROR, LOCATION, NULL,
638 "failed to get keymat buffer.\n");
639 if (prev && prev != res)
640 vfree(prev);
641 goto end;
644 while (dupkeymat--) {
645 vchar_t *this = NULL; /* Kn */
646 int update_prev;
648 memcpy(seed->v, prev->v, prev->l);
649 memcpy(seed->v + prev->l, buf->v, buf->l);
650 this = oakley_prf(iph2->ph1->skeyid_d, seed,
651 iph2->ph1);
652 if (!this) {
653 plog(LLV_ERROR, LOCATION, NULL,
654 "oakley_prf memory overflow\n");
655 if (prev && prev != res)
656 vfree(prev);
657 vfree(this);
658 vfree(seed);
659 goto end;
662 update_prev = (prev && prev == res) ? 1 : 0;
664 l = res->l;
665 res = vrealloc(res, l + this->l);
667 if (update_prev)
668 prev = res;
670 if (res == NULL) {
671 plog(LLV_ERROR, LOCATION, NULL,
672 "failed to get keymat buffer.\n");
673 if (prev && prev != res)
674 vfree(prev);
675 vfree(this);
676 vfree(seed);
677 goto end;
679 memcpy(res->v + l, this->v, this->l);
681 if (prev && prev != res)
682 vfree(prev);
683 prev = this;
684 this = NULL;
687 if (prev && prev != res)
688 vfree(prev);
689 vfree(seed);
692 plogdump(LLV_DEBUG, res->v, res->l);
694 if (sa_dir == INBOUND_SA)
695 pr->keymat = res;
696 else
697 pr->keymat_p = res;
698 res = NULL;
701 error = 0;
703 end:
704 if (error) {
705 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
706 if (pr->keymat) {
707 vfree(pr->keymat);
708 pr->keymat = NULL;
710 if (pr->keymat_p) {
711 vfree(pr->keymat_p);
712 pr->keymat_p = NULL;
717 if (buf != NULL)
718 vfree(buf);
719 if (res)
720 vfree(res);
722 return error;
725 #if notyet
727 * NOTE: Must terminate by NULL.
729 vchar_t *
730 oakley_compute_hashx(struct ph1handle *iph1, ...)
732 vchar_t *buf, *res;
733 vchar_t *s;
734 caddr_t p;
735 int len;
737 va_list ap;
739 /* get buffer length */
740 va_start(ap, iph1);
741 len = 0;
742 while ((s = va_arg(ap, vchar_t *)) != NULL) {
743 len += s->l
745 va_end(ap);
747 buf = vmalloc(len);
748 if (buf == NULL) {
749 plog(LLV_ERROR, LOCATION, NULL,
750 "failed to get hash buffer\n");
751 return NULL;
754 /* set buffer */
755 va_start(ap, iph1);
756 p = buf->v;
757 while ((s = va_arg(ap, char *)) != NULL) {
758 memcpy(p, s->v, s->l);
759 p += s->l;
761 va_end(ap);
763 plog(LLV_DEBUG, LOCATION, NULL, "HASH with: \n");
764 plogdump(LLV_DEBUG, buf->v, buf->l);
766 /* compute HASH */
767 res = oakley_prf(iph1->skeyid_a, buf, iph1);
768 vfree(buf);
769 if (res == NULL)
770 return NULL;
772 plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n");
773 plogdump(LLV_DEBUG, res->v, res->l);
775 return res;
777 #endif
780 * compute HASH(3) prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b)
781 * see seciton 5.5 Phase 2 - Quick Mode in isakmp-oakley-05.
783 vchar_t *
784 oakley_compute_hash3(iph1, msgid, body)
785 struct ph1handle *iph1;
786 u_int32_t msgid;
787 vchar_t *body;
789 vchar_t *buf = 0, *res = 0;
790 int len;
791 int error = -1;
793 /* create buffer */
794 len = 1 + sizeof(u_int32_t) + body->l;
795 buf = vmalloc(len);
796 if (buf == NULL) {
797 plog(LLV_DEBUG, LOCATION, NULL,
798 "failed to get hash buffer\n");
799 goto end;
802 buf->v[0] = 0;
804 memcpy(buf->v + 1, (char *)&msgid, sizeof(msgid));
806 memcpy(buf->v + 1 + sizeof(u_int32_t), body->v, body->l);
808 plog(LLV_DEBUG, LOCATION, NULL, "HASH with: \n");
809 plogdump(LLV_DEBUG, buf->v, buf->l);
811 /* compute HASH */
812 res = oakley_prf(iph1->skeyid_a, buf, iph1);
813 if (res == NULL)
814 goto end;
816 error = 0;
818 plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n");
819 plogdump(LLV_DEBUG, res->v, res->l);
821 end:
822 if (buf != NULL)
823 vfree(buf);
824 return res;
828 * compute HASH type of prf(SKEYID_a, M-ID | buffer)
829 * e.g.
830 * for quick mode HASH(1):
831 * prf(SKEYID_a, M-ID | SA | Ni [ | KE ] [ | IDci | IDcr ])
832 * for quick mode HASH(2):
833 * prf(SKEYID_a, M-ID | Ni_b | SA | Nr [ | KE ] [ | IDci | IDcr ])
834 * for Informational exchange:
835 * prf(SKEYID_a, M-ID | N/D)
837 vchar_t *
838 oakley_compute_hash1(iph1, msgid, body)
839 struct ph1handle *iph1;
840 u_int32_t msgid;
841 vchar_t *body;
843 vchar_t *buf = NULL, *res = NULL;
844 char *p;
845 int len;
846 int error = -1;
848 /* create buffer */
849 len = sizeof(u_int32_t) + body->l;
850 buf = vmalloc(len);
851 if (buf == NULL) {
852 plog(LLV_DEBUG, LOCATION, NULL,
853 "failed to get hash buffer\n");
854 goto end;
857 p = buf->v;
859 memcpy(buf->v, (char *)&msgid, sizeof(msgid));
860 p += sizeof(u_int32_t);
862 memcpy(p, body->v, body->l);
864 plog(LLV_DEBUG, LOCATION, NULL, "HASH with:\n");
865 plogdump(LLV_DEBUG, buf->v, buf->l);
867 /* compute HASH */
868 res = oakley_prf(iph1->skeyid_a, buf, iph1);
869 if (res == NULL)
870 goto end;
872 error = 0;
874 plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n");
875 plogdump(LLV_DEBUG, res->v, res->l);
877 end:
878 if (buf != NULL)
879 vfree(buf);
880 return res;
884 * compute phase1 HASH
885 * main/aggressive
886 * I-digest = prf(SKEYID, g^i | g^r | CKY-I | CKY-R | SAi_b | ID_i1_b)
887 * R-digest = prf(SKEYID, g^r | g^i | CKY-R | CKY-I | SAi_b | ID_r1_b)
888 * for gssapi, also include all GSS tokens, and call gss_wrap on the result
890 vchar_t *
891 oakley_ph1hash_common(iph1, sw)
892 struct ph1handle *iph1;
893 int sw;
895 vchar_t *buf = NULL, *res = NULL, *bp;
896 char *p, *bp2;
897 int len, bl;
898 int error = -1;
899 #ifdef HAVE_GSSAPI
900 vchar_t *gsstokens = NULL;
901 #endif
903 /* create buffer */
904 len = iph1->dhpub->l
905 + iph1->dhpub_p->l
906 + sizeof(cookie_t) * 2
907 + iph1->sa->l
908 + (sw == GENERATE ? iph1->id->l : iph1->id_p->l);
910 #ifdef HAVE_GSSAPI
911 if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
912 if (iph1->gi_i != NULL && iph1->gi_r != NULL) {
913 bp = (sw == GENERATE ? iph1->gi_i : iph1->gi_r);
914 len += bp->l;
916 if (sw == GENERATE)
917 gssapi_get_itokens(iph1, &gsstokens);
918 else
919 gssapi_get_rtokens(iph1, &gsstokens);
920 if (gsstokens == NULL)
921 return NULL;
922 len += gsstokens->l;
924 #endif
926 buf = vmalloc(len);
927 if (buf == NULL) {
928 plog(LLV_ERROR, LOCATION, NULL,
929 "failed to get hash buffer\n");
930 goto end;
933 p = buf->v;
935 bp = (sw == GENERATE ? iph1->dhpub : iph1->dhpub_p);
936 memcpy(p, bp->v, bp->l);
937 p += bp->l;
939 bp = (sw == GENERATE ? iph1->dhpub_p : iph1->dhpub);
940 memcpy(p, bp->v, bp->l);
941 p += bp->l;
943 if (iph1->side == INITIATOR)
944 bp2 = (sw == GENERATE ?
945 (char *)&iph1->index.i_ck : (char *)&iph1->index.r_ck);
946 else
947 bp2 = (sw == GENERATE ?
948 (char *)&iph1->index.r_ck : (char *)&iph1->index.i_ck);
949 bl = sizeof(cookie_t);
950 memcpy(p, bp2, bl);
951 p += bl;
953 if (iph1->side == INITIATOR)
954 bp2 = (sw == GENERATE ?
955 (char *)&iph1->index.r_ck : (char *)&iph1->index.i_ck);
956 else
957 bp2 = (sw == GENERATE ?
958 (char *)&iph1->index.i_ck : (char *)&iph1->index.r_ck);
959 bl = sizeof(cookie_t);
960 memcpy(p, bp2, bl);
961 p += bl;
963 bp = iph1->sa;
964 memcpy(p, bp->v, bp->l);
965 p += bp->l;
967 bp = (sw == GENERATE ? iph1->id : iph1->id_p);
968 memcpy(p, bp->v, bp->l);
969 p += bp->l;
971 #ifdef HAVE_GSSAPI
972 if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
973 if (iph1->gi_i != NULL && iph1->gi_r != NULL) {
974 bp = (sw == GENERATE ? iph1->gi_i : iph1->gi_r);
975 memcpy(p, bp->v, bp->l);
976 p += bp->l;
978 memcpy(p, gsstokens->v, gsstokens->l);
979 p += gsstokens->l;
981 #endif
983 plog(LLV_DEBUG, LOCATION, NULL, "HASH with:\n");
984 plogdump(LLV_DEBUG, buf->v, buf->l);
986 /* compute HASH */
987 res = oakley_prf(iph1->skeyid, buf, iph1);
988 if (res == NULL)
989 goto end;
991 error = 0;
993 plog(LLV_DEBUG, LOCATION, NULL, "HASH (%s) computed:\n",
994 iph1->side == INITIATOR ? "init" : "resp");
995 plogdump(LLV_DEBUG, res->v, res->l);
997 end:
998 if (buf != NULL)
999 vfree(buf);
1000 #ifdef HAVE_GSSAPI
1001 if (gsstokens != NULL)
1002 vfree(gsstokens);
1003 #endif
1004 return res;
1008 * compute HASH_I on base mode.
1009 * base:psk,rsa
1010 * HASH_I = prf(SKEYID, g^xi | CKY-I | CKY-R | SAi_b | IDii_b)
1011 * base:sig
1012 * HASH_I = prf(hash(Ni_b | Nr_b), g^xi | CKY-I | CKY-R | SAi_b | IDii_b)
1014 vchar_t *
1015 oakley_ph1hash_base_i(iph1, sw)
1016 struct ph1handle *iph1;
1017 int sw;
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;
1026 /* sanity check */
1027 if (iph1->etype != ISAKMP_ETYPE_BASE) {
1028 plog(LLV_ERROR, LOCATION, NULL,
1029 "invalid etype for this hash function\n");
1030 return NULL;
1033 switch (iph1->approval->authmethod) {
1034 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
1035 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
1036 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
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 OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
1043 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
1044 #endif
1045 if (iph1->skeyid == NULL) {
1046 plog(LLV_ERROR, LOCATION, NULL, "no SKEYID found.\n");
1047 return NULL;
1049 hashkey = iph1->skeyid;
1050 break;
1052 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
1053 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
1054 #ifdef HAVE_GSSAPI
1055 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
1056 #endif
1057 #ifdef ENABLE_HYBRID
1058 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
1059 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
1060 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
1061 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
1062 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
1063 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
1064 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
1065 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
1066 #endif
1067 /* make hash for seed */
1068 len = iph1->nonce->l + iph1->nonce_p->l;
1069 buf = vmalloc(len);
1070 if (buf == NULL) {
1071 plog(LLV_ERROR, LOCATION, NULL,
1072 "failed to get hash buffer\n");
1073 goto end;
1075 p = buf->v;
1077 bp = (sw == GENERATE ? iph1->nonce_p : iph1->nonce);
1078 memcpy(p, bp->v, bp->l);
1079 p += bp->l;
1081 bp = (sw == GENERATE ? iph1->nonce : iph1->nonce_p);
1082 memcpy(p, bp->v, bp->l);
1083 p += bp->l;
1085 hash = oakley_hash(buf, iph1);
1086 if (hash == NULL)
1087 goto end;
1088 vfree(buf);
1089 buf = NULL;
1091 hashkey = hash;
1092 break;
1094 default:
1095 plog(LLV_ERROR, LOCATION, NULL,
1096 "not supported authentication method %d\n",
1097 iph1->approval->authmethod);
1098 return NULL;
1102 len = (sw == GENERATE ? iph1->dhpub->l : iph1->dhpub_p->l)
1103 + sizeof(cookie_t) * 2
1104 + iph1->sa->l
1105 + (sw == GENERATE ? iph1->id->l : iph1->id_p->l);
1106 buf = vmalloc(len);
1107 if (buf == NULL) {
1108 plog(LLV_ERROR, LOCATION, NULL,
1109 "failed to get hash buffer\n");
1110 goto end;
1112 p = buf->v;
1114 bp = (sw == GENERATE ? iph1->dhpub : iph1->dhpub_p);
1115 memcpy(p, bp->v, bp->l);
1116 p += bp->l;
1118 memcpy(p, &iph1->index.i_ck, sizeof(cookie_t));
1119 p += sizeof(cookie_t);
1120 memcpy(p, &iph1->index.r_ck, sizeof(cookie_t));
1121 p += sizeof(cookie_t);
1123 memcpy(p, iph1->sa->v, iph1->sa->l);
1124 p += iph1->sa->l;
1126 bp = (sw == GENERATE ? iph1->id : iph1->id_p);
1127 memcpy(p, bp->v, bp->l);
1128 p += bp->l;
1130 plog(LLV_DEBUG, LOCATION, NULL, "HASH_I with:\n");
1131 plogdump(LLV_DEBUG, buf->v, buf->l);
1133 /* compute HASH */
1134 res = oakley_prf(hashkey, buf, iph1);
1135 if (res == NULL)
1136 goto end;
1138 error = 0;
1140 plog(LLV_DEBUG, LOCATION, NULL, "HASH_I computed:\n");
1141 plogdump(LLV_DEBUG, res->v, res->l);
1143 end:
1144 if (hash != NULL)
1145 vfree(hash);
1146 if (buf != NULL)
1147 vfree(buf);
1148 return res;
1152 * compute HASH_R on base mode for signature method.
1153 * base:
1154 * HASH_R = prf(hash(Ni_b | Nr_b), g^xi | g^xr | CKY-I | CKY-R | SAi_b | IDii_b)
1156 vchar_t *
1157 oakley_ph1hash_base_r(iph1, sw)
1158 struct ph1handle *iph1;
1159 int sw;
1161 vchar_t *buf = NULL, *res = NULL, *bp;
1162 vchar_t *hash = NULL;
1163 char *p;
1164 int len;
1165 int error = -1;
1167 /* sanity check */
1168 if (iph1->etype != ISAKMP_ETYPE_BASE) {
1169 plog(LLV_ERROR, LOCATION, NULL,
1170 "invalid etype for this hash function\n");
1171 return NULL;
1174 switch (iph1->approval->authmethod) {
1175 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
1176 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
1177 #ifdef ENABLE_HYBRID
1178 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
1179 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
1180 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
1181 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
1182 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
1183 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
1184 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
1185 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
1186 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
1187 #endif
1188 break;
1189 default:
1190 plog(LLV_ERROR, LOCATION, NULL,
1191 "not supported authentication method %d\n",
1192 iph1->approval->authmethod);
1193 return NULL;
1194 break;
1197 /* make hash for seed */
1198 len = iph1->nonce->l + iph1->nonce_p->l;
1199 buf = vmalloc(len);
1200 if (buf == NULL) {
1201 plog(LLV_ERROR, LOCATION, NULL,
1202 "failed to get hash buffer\n");
1203 goto end;
1205 p = buf->v;
1207 bp = (sw == GENERATE ? iph1->nonce_p : iph1->nonce);
1208 memcpy(p, bp->v, bp->l);
1209 p += bp->l;
1211 bp = (sw == GENERATE ? iph1->nonce : iph1->nonce_p);
1212 memcpy(p, bp->v, bp->l);
1213 p += bp->l;
1215 hash = oakley_hash(buf, iph1);
1216 if (hash == NULL)
1217 goto end;
1218 vfree(buf);
1219 buf = NULL;
1221 /* make really hash */
1222 len = (sw == GENERATE ? iph1->dhpub_p->l : iph1->dhpub->l)
1223 + (sw == GENERATE ? iph1->dhpub->l : iph1->dhpub_p->l)
1224 + sizeof(cookie_t) * 2
1225 + iph1->sa->l
1226 + (sw == GENERATE ? iph1->id_p->l : iph1->id->l);
1227 buf = vmalloc(len);
1228 if (buf == NULL) {
1229 plog(LLV_ERROR, LOCATION, NULL,
1230 "failed to get hash buffer\n");
1231 goto end;
1233 p = buf->v;
1236 bp = (sw == GENERATE ? iph1->dhpub_p : iph1->dhpub);
1237 memcpy(p, bp->v, bp->l);
1238 p += bp->l;
1240 bp = (sw == GENERATE ? iph1->dhpub : iph1->dhpub_p);
1241 memcpy(p, bp->v, bp->l);
1242 p += bp->l;
1244 memcpy(p, &iph1->index.i_ck, sizeof(cookie_t));
1245 p += sizeof(cookie_t);
1246 memcpy(p, &iph1->index.r_ck, sizeof(cookie_t));
1247 p += sizeof(cookie_t);
1249 memcpy(p, iph1->sa->v, iph1->sa->l);
1250 p += iph1->sa->l;
1252 bp = (sw == GENERATE ? iph1->id_p : iph1->id);
1253 memcpy(p, bp->v, bp->l);
1254 p += bp->l;
1256 plog(LLV_DEBUG, LOCATION, NULL, "HASH_R with:\n");
1257 plogdump(LLV_DEBUG, buf->v, buf->l);
1259 /* compute HASH */
1260 res = oakley_prf(hash, buf, iph1);
1261 if (res == NULL)
1262 goto end;
1264 error = 0;
1266 plog(LLV_DEBUG, LOCATION, NULL, "HASH_R computed:\n");
1267 plogdump(LLV_DEBUG, res->v, res->l);
1269 end:
1270 if (buf != NULL)
1271 vfree(buf);
1272 if (hash)
1273 vfree(hash);
1274 return res;
1278 * compute each authentication method in phase 1.
1279 * OUT:
1280 * 0: OK
1281 * -1: error
1282 * other: error to be reply with notification.
1283 * the value is notification type.
1286 oakley_validate_auth(iph1)
1287 struct ph1handle *iph1;
1289 vchar_t *my_hash = NULL;
1290 int result;
1291 #ifdef HAVE_GSSAPI
1292 vchar_t *gsshash = NULL;
1293 #endif
1294 #ifdef ENABLE_STATS
1295 struct timeval start, end;
1296 #endif
1298 #ifdef ENABLE_STATS
1299 gettimeofday(&start, NULL);
1300 #endif
1302 switch (iph1->approval->authmethod) {
1303 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
1304 #ifdef ENABLE_HYBRID
1305 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
1306 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
1307 #endif
1308 /* validate HASH */
1310 char *r_hash;
1312 if (iph1->id_p == NULL || iph1->pl_hash == NULL) {
1313 plog(LLV_ERROR, LOCATION, iph1->remote,
1314 "few isakmp message received.\n");
1315 return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1317 #ifdef ENABLE_HYBRID
1318 if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I &&
1319 ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0))
1321 plog(LLV_ERROR, LOCATION, NULL, "No SIG was passed, "
1322 "hybrid auth is enabled, "
1323 "but peer is no Xauth compliant\n");
1324 return ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED;
1325 break;
1327 #endif
1328 r_hash = (caddr_t)(iph1->pl_hash + 1);
1330 plog(LLV_DEBUG, LOCATION, NULL, "HASH received:\n");
1331 plogdump(LLV_DEBUG, r_hash,
1332 ntohs(iph1->pl_hash->h.len) - sizeof(*iph1->pl_hash));
1334 switch (iph1->etype) {
1335 case ISAKMP_ETYPE_IDENT:
1336 case ISAKMP_ETYPE_AGG:
1337 my_hash = oakley_ph1hash_common(iph1, VALIDATE);
1338 break;
1339 case ISAKMP_ETYPE_BASE:
1340 if (iph1->side == INITIATOR)
1341 my_hash = oakley_ph1hash_common(iph1, VALIDATE);
1342 else
1343 my_hash = oakley_ph1hash_base_i(iph1, VALIDATE);
1344 break;
1345 default:
1346 plog(LLV_ERROR, LOCATION, NULL,
1347 "invalid etype %d\n", iph1->etype);
1348 return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
1350 if (my_hash == NULL)
1351 return ISAKMP_INTERNAL_ERROR;
1353 result = memcmp(my_hash->v, r_hash, my_hash->l);
1354 vfree(my_hash);
1356 if (result) {
1357 plog(LLV_ERROR, LOCATION, NULL, "HASH mismatched\n");
1358 return ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1361 plog(LLV_DEBUG, LOCATION, NULL, "HASH for PSK validated.\n");
1363 break;
1364 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
1365 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
1366 #ifdef ENABLE_HYBRID
1367 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
1368 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
1369 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
1370 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
1371 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
1372 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
1373 #endif
1375 int error = 0;
1376 int certtype;
1378 /* validation */
1379 if (iph1->id_p == NULL) {
1380 plog(LLV_ERROR, LOCATION, iph1->remote,
1381 "no ID payload was passed.\n");
1382 return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1384 if (iph1->sig_p == NULL) {
1385 plog(LLV_ERROR, LOCATION, iph1->remote,
1386 "no SIG payload was passed.\n");
1387 return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1390 plog(LLV_DEBUG, LOCATION, NULL, "SIGN passed:\n");
1391 plogdump(LLV_DEBUG, iph1->sig_p->v, iph1->sig_p->l);
1393 /* get peer's cert */
1394 certtype = oakley_get_certtype(iph1->rmconf->peerscert);
1395 switch (certtype) {
1396 case ISAKMP_CERT_NONE:
1397 /* expect to receive one from peer */
1398 if (iph1->cert_p == NULL) {
1399 plog(LLV_ERROR, LOCATION, NULL,
1400 "no peer's CERT payload found.\n");
1401 return ISAKMP_INTERNAL_ERROR;
1403 /* verify the cert if needed */
1404 if (!iph1->rmconf->verify_cert)
1405 break;
1407 switch (oakley_get_certtype(iph1->cert_p)) {
1408 case ISAKMP_CERT_X509SIGN: {
1409 char path[MAXPATHLEN];
1410 char *ca;
1412 if (iph1->rmconf->cacertfile != NULL) {
1413 getpathname(path, sizeof(path),
1414 LC_PATHTYPE_CERT,
1415 iph1->rmconf->cacertfile);
1416 ca = path;
1417 } else {
1418 ca = NULL;
1421 error = eay_check_x509cert(
1422 iph1->cert_p,
1423 lcconf->pathinfo[LC_PATHTYPE_CERT],
1424 ca, 0);
1425 break;
1427 default:
1428 plog(LLV_ERROR, LOCATION, NULL,
1429 "peers_cert certtype %d was not expected\n",
1430 certtype);
1431 return ISAKMP_INTERNAL_ERROR;
1434 if (error != 0) {
1435 plog(LLV_ERROR, LOCATION, NULL,
1436 "the peer's certificate is not verified.\n");
1437 return ISAKMP_NTYPE_INVALID_CERT_AUTHORITY;
1439 break;
1440 case ISAKMP_CERT_X509SIGN:
1441 if (iph1->rmconf->peerscert == NULL) {
1442 plog(LLV_ERROR, LOCATION, NULL,
1443 "no peer's CERT file found.\n");
1444 return ISAKMP_INTERNAL_ERROR;
1446 /* don't use received cert */
1447 if (iph1->cert_p != NULL) {
1448 vfree(iph1->cert_p);
1449 iph1->cert_p = NULL;
1451 /* copy from remoteconf instead */
1452 iph1->cert_p = vdup(iph1->rmconf->peerscert);
1453 break;
1454 case ISAKMP_CERT_PLAINRSA:
1455 if (get_plainrsa_fromlocal(iph1, 0))
1456 return ISAKMP_INTERNAL_ERROR;
1457 break;
1458 case ISAKMP_CERT_DNS:
1459 /* don't use received cert */
1460 if (iph1->cert_p != NULL) {
1461 vfree(iph1->cert_p);
1462 iph1->cert_p = NULL;
1465 iph1->cert_p = dnssec_getcert(iph1->id_p);
1466 if (iph1->cert_p == NULL) {
1467 plog(LLV_ERROR, LOCATION, NULL,
1468 "no CERT RR found.\n");
1469 return ISAKMP_INTERNAL_ERROR;
1471 break;
1472 default:
1473 plog(LLV_ERROR, LOCATION, NULL,
1474 "invalid certificate type: %d\n",
1475 oakley_get_certtype(iph1->rmconf->peerscert));
1476 return ISAKMP_INTERNAL_ERROR;
1479 /* compare ID payload and certificate name */
1480 if ((error = oakley_check_certid(iph1)) != 0)
1481 return error;
1483 /* Generate a warning if verify_cert */
1484 if (iph1->rmconf->verify_cert) {
1485 plog(LLV_DEBUG, LOCATION, NULL,
1486 "CERT validated\n");
1487 } else {
1488 plog(LLV_WARNING, LOCATION, NULL,
1489 "CERT validation disabled by configuration\n");
1492 /* compute hash */
1493 switch (iph1->etype) {
1494 case ISAKMP_ETYPE_IDENT:
1495 case ISAKMP_ETYPE_AGG:
1496 my_hash = oakley_ph1hash_common(iph1, VALIDATE);
1497 break;
1498 case ISAKMP_ETYPE_BASE:
1499 if (iph1->side == INITIATOR)
1500 my_hash = oakley_ph1hash_base_r(iph1, VALIDATE);
1501 else
1502 my_hash = oakley_ph1hash_base_i(iph1, VALIDATE);
1503 break;
1504 default:
1505 plog(LLV_ERROR, LOCATION, NULL,
1506 "invalid etype %d\n", iph1->etype);
1507 return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
1509 if (my_hash == NULL)
1510 return ISAKMP_INTERNAL_ERROR;
1512 /* check signature */
1513 certtype = oakley_get_certtype(iph1->cert_p);
1514 if (certtype == ISAKMP_CERT_NONE)
1515 certtype = oakley_get_certtype(iph1->rmconf->peerscert);
1516 switch (certtype) {
1517 case ISAKMP_CERT_X509SIGN:
1518 case ISAKMP_CERT_DNS:
1519 error = eay_check_x509sign(my_hash,
1520 iph1->sig_p,
1521 iph1->cert_p);
1522 break;
1523 case ISAKMP_CERT_PLAINRSA:
1524 iph1->rsa_p = rsa_try_check_rsasign(my_hash,
1525 iph1->sig_p, iph1->rsa_candidates);
1526 error = iph1->rsa_p ? 0 : -1;
1527 break;
1528 default:
1529 plog(LLV_ERROR, LOCATION, NULL,
1530 "cannot check signature for certtype %d\n",
1531 certtype);
1532 vfree(my_hash);
1533 return ISAKMP_INTERNAL_ERROR;
1536 vfree(my_hash);
1537 if (error != 0) {
1538 plog(LLV_ERROR, LOCATION, NULL,
1539 "Invalid SIG.\n");
1540 return ISAKMP_NTYPE_INVALID_SIGNATURE;
1542 plog(LLV_DEBUG, LOCATION, NULL, "SIG authenticated\n");
1544 break;
1545 #ifdef ENABLE_HYBRID
1546 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
1547 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
1549 if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) {
1550 plog(LLV_ERROR, LOCATION, NULL, "No SIG was passed, "
1551 "hybrid auth is enabled, "
1552 "but peer is no Xauth compliant\n");
1553 return ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED;
1554 break;
1556 plog(LLV_INFO, LOCATION, NULL, "No SIG was passed, "
1557 "but hybrid auth is enabled\n");
1559 return 0;
1560 break;
1562 #endif
1563 #ifdef HAVE_GSSAPI
1564 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
1565 /* check if we're not into XAUTH_PSKEY_I instead */
1566 #ifdef ENABLE_HYBRID
1567 if (iph1->rmconf->xauth)
1568 break;
1569 #endif
1570 switch (iph1->etype) {
1571 case ISAKMP_ETYPE_IDENT:
1572 case ISAKMP_ETYPE_AGG:
1573 my_hash = oakley_ph1hash_common(iph1, VALIDATE);
1574 break;
1575 default:
1576 plog(LLV_ERROR, LOCATION, NULL,
1577 "invalid etype %d\n", iph1->etype);
1578 return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
1581 if (my_hash == NULL) {
1582 if (gssapi_more_tokens(iph1))
1583 return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
1584 else
1585 return ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1588 gsshash = gssapi_unwraphash(iph1);
1589 if (gsshash == NULL) {
1590 vfree(my_hash);
1591 return ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1594 result = memcmp(my_hash->v, gsshash->v, my_hash->l);
1595 vfree(my_hash);
1596 vfree(gsshash);
1598 if (result) {
1599 plog(LLV_ERROR, LOCATION, NULL, "HASH mismatched\n");
1600 return ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1602 plog(LLV_DEBUG, LOCATION, NULL, "hash compared OK\n");
1603 break;
1604 #endif
1605 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
1606 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
1607 #ifdef ENABLE_HYBRID
1608 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
1609 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
1610 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
1611 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
1612 #endif
1613 if (iph1->id_p == NULL || iph1->pl_hash == NULL) {
1614 plog(LLV_ERROR, LOCATION, iph1->remote,
1615 "few isakmp message received.\n");
1616 return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1618 plog(LLV_ERROR, LOCATION, iph1->remote,
1619 "not supported authmethod type %s\n",
1620 s_oakley_attr_method(iph1->approval->authmethod));
1621 return ISAKMP_INTERNAL_ERROR;
1622 default:
1623 plog(LLV_ERROR, LOCATION, iph1->remote,
1624 "invalid authmethod %d why ?\n",
1625 iph1->approval->authmethod);
1626 return ISAKMP_INTERNAL_ERROR;
1628 #ifdef ENABLE_STATS
1629 gettimeofday(&end, NULL);
1630 syslog(LOG_NOTICE, "%s(%s): %8.6f", __func__,
1631 s_oakley_attr_method(iph1->approval->authmethod),
1632 timedelta(&start, &end));
1633 #endif
1635 return 0;
1638 /* get my certificate
1639 * NOTE: include certificate type.
1642 oakley_getmycert(iph1)
1643 struct ph1handle *iph1;
1645 switch (oakley_get_certtype(iph1->rmconf->mycert)) {
1646 case ISAKMP_CERT_X509SIGN:
1647 if (iph1->cert)
1648 return 0;
1649 iph1->cert = vdup(iph1->rmconf->mycert);
1650 break;
1651 case ISAKMP_CERT_PLAINRSA:
1652 if (iph1->rsa)
1653 return 0;
1654 return get_plainrsa_fromlocal(iph1, 1);
1655 default:
1656 plog(LLV_ERROR, LOCATION, NULL,
1657 "Unknown certtype #%d\n",
1658 oakley_get_certtype(iph1->rmconf->mycert));
1659 return -1;
1662 return 0;
1665 static int
1666 get_plainrsa_fromlocal(iph1, my)
1667 struct ph1handle *iph1;
1668 int my;
1670 char path[MAXPATHLEN];
1671 vchar_t *cert = NULL;
1672 char *certfile;
1673 int error = -1;
1675 iph1->rsa_candidates = rsa_lookup_keys(iph1, my);
1676 if (!iph1->rsa_candidates ||
1677 rsa_list_count(iph1->rsa_candidates) == 0) {
1678 plog(LLV_ERROR, LOCATION, NULL,
1679 "%s RSA key not found for %s\n",
1680 my ? "Private" : "Public",
1681 saddr2str_fromto("%s <-> %s",
1682 iph1->local, iph1->remote));
1683 goto end;
1686 if (my && rsa_list_count(iph1->rsa_candidates) > 1) {
1687 plog(LLV_WARNING, LOCATION, NULL,
1688 "More than one (=%lu) private "
1689 "PlainRSA key found for %s\n",
1690 rsa_list_count(iph1->rsa_candidates),
1691 saddr2str_fromto("%s <-> %s",
1692 iph1->local, iph1->remote));
1693 plog(LLV_WARNING, LOCATION, NULL,
1694 "This may have unpredictable results, "
1695 "i.e. wrong key could be used!\n");
1696 plog(LLV_WARNING, LOCATION, NULL,
1697 "Consider using only one single private "
1698 "key for all peers...\n");
1700 if (my) {
1701 iph1->rsa = ((struct rsa_key *)
1702 genlist_next(iph1->rsa_candidates, NULL))->rsa;
1704 genlist_free(iph1->rsa_candidates, NULL);
1705 iph1->rsa_candidates = NULL;
1707 if (iph1->rsa == NULL)
1708 goto end;
1711 error = 0;
1713 end:
1714 return error;
1717 /* get signature */
1719 oakley_getsign(iph1)
1720 struct ph1handle *iph1;
1722 char path[MAXPATHLEN];
1723 vchar_t *privkey = NULL;
1724 int error = -1;
1726 switch (oakley_get_certtype(iph1->rmconf->mycert)) {
1727 case ISAKMP_CERT_X509SIGN:
1728 case ISAKMP_CERT_DNS:
1729 if (iph1->rmconf->myprivfile == NULL) {
1730 plog(LLV_ERROR, LOCATION, NULL, "no cert defined.\n");
1731 goto end;
1734 /* make private file name */
1735 getpathname(path, sizeof(path),
1736 LC_PATHTYPE_CERT,
1737 iph1->rmconf->myprivfile);
1738 privkey = privsep_eay_get_pkcs1privkey(path);
1739 if (privkey == NULL) {
1740 plog(LLV_ERROR, LOCATION, NULL,
1741 "failed to get private key.\n");
1742 goto end;
1744 plog(LLV_DEBUG2, LOCATION, NULL, "private key:\n");
1745 plogdump(LLV_DEBUG2, privkey->v, privkey->l);
1746 iph1->sig = eay_get_x509sign(iph1->hash, privkey);
1747 break;
1748 case ISAKMP_CERT_PLAINRSA:
1749 iph1->sig = eay_get_rsasign(iph1->hash, iph1->rsa);
1750 break;
1751 default:
1752 plog(LLV_ERROR, LOCATION, NULL,
1753 "Unknown certtype #%d\n",
1754 oakley_get_certtype(iph1->rmconf->mycert));
1755 goto end;
1758 if (iph1->sig == NULL) {
1759 plog(LLV_ERROR, LOCATION, NULL, "failed to sign.\n");
1760 goto end;
1763 plog(LLV_DEBUG, LOCATION, NULL, "SIGN computed:\n");
1764 plogdump(LLV_DEBUG, iph1->sig->v, iph1->sig->l);
1766 error = 0;
1768 end:
1769 if (privkey != NULL)
1770 vfree(privkey);
1772 return error;
1776 * compare certificate name and ID value.
1778 static int
1779 oakley_check_certid(iph1)
1780 struct ph1handle *iph1;
1782 struct ipsecdoi_id_b *id_b;
1783 vchar_t *name = NULL;
1784 char *altname = NULL;
1785 int idlen, type;
1786 int error;
1788 if (iph1->rmconf == NULL || iph1->rmconf->verify_cert == FALSE)
1789 return 0;
1791 if (iph1->id_p == NULL || iph1->cert_p == NULL) {
1792 plog(LLV_ERROR, LOCATION, NULL, "no ID nor CERT found.\n");
1793 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
1796 id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
1797 idlen = iph1->id_p->l - sizeof(*id_b);
1799 switch (id_b->type) {
1800 case IPSECDOI_ID_DER_ASN1_DN:
1801 name = eay_get_x509asn1subjectname(iph1->cert_p);
1802 if (!name) {
1803 plog(LLV_ERROR, LOCATION, NULL,
1804 "failed to get subjectName\n");
1805 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
1807 if (idlen != name->l) {
1808 plog(LLV_ERROR, LOCATION, NULL,
1809 "Invalid ID length in phase 1.\n");
1810 vfree(name);
1811 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
1813 error = memcmp(id_b + 1, name->v, idlen);
1814 vfree(name);
1815 if (error != 0) {
1816 plog(LLV_ERROR, LOCATION, NULL,
1817 "ID mismatched with ASN1 SubjectName.\n");
1818 plogdump(LLV_DEBUG, id_b + 1, idlen);
1819 plogdump(LLV_DEBUG, name->v, idlen);
1820 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
1822 return 0;
1823 case IPSECDOI_ID_IPV4_ADDR:
1824 case IPSECDOI_ID_IPV6_ADDR:
1827 * converting to binary from string because openssl return
1828 * a string even if object is a binary.
1829 * XXX fix it ! access by ASN.1 directly without.
1831 struct addrinfo hints, *res;
1832 caddr_t a = NULL;
1833 int pos;
1835 for (pos = 1; ; pos++) {
1836 if (eay_get_x509subjectaltname(iph1->cert_p,
1837 &altname, &type, pos) !=0) {
1838 plog(LLV_ERROR, LOCATION, NULL,
1839 "failed to get subjectAltName\n");
1840 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
1843 /* it's the end condition of the loop. */
1844 if (!altname) {
1845 plog(LLV_ERROR, LOCATION, NULL,
1846 "no proper subjectAltName.\n");
1847 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
1850 if (check_typeofcertname(id_b->type, type) == 0)
1851 break;
1853 /* next name */
1854 racoon_free(altname);
1855 altname = NULL;
1857 memset(&hints, 0, sizeof(hints));
1858 hints.ai_family = PF_UNSPEC;
1859 hints.ai_socktype = SOCK_RAW;
1860 hints.ai_flags = AI_NUMERICHOST;
1861 error = getaddrinfo(altname, NULL, &hints, &res);
1862 if (error != 0) {
1863 plog(LLV_ERROR, LOCATION, NULL,
1864 "no proper subjectAltName.\n");
1865 racoon_free(altname);
1866 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
1868 switch (res->ai_family) {
1869 case AF_INET:
1870 a = (caddr_t)&((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr;
1871 break;
1872 #ifdef INET6
1873 case AF_INET6:
1874 a = (caddr_t)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr.s6_addr;
1875 break;
1876 #endif
1877 default:
1878 plog(LLV_ERROR, LOCATION, NULL,
1879 "family not supported: %d.\n", res->ai_family);
1880 racoon_free(altname);
1881 freeaddrinfo(res);
1882 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
1884 error = memcmp(id_b + 1, a, idlen);
1885 freeaddrinfo(res);
1886 vfree(name);
1887 if (error != 0) {
1888 plog(LLV_ERROR, LOCATION, NULL,
1889 "ID mismatched with subjectAltName.\n");
1890 plogdump(LLV_DEBUG, id_b + 1, idlen);
1891 plogdump(LLV_DEBUG, a, idlen);
1892 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
1894 return 0;
1896 case IPSECDOI_ID_FQDN:
1897 case IPSECDOI_ID_USER_FQDN:
1899 int pos;
1901 for (pos = 1; ; pos++) {
1902 if (eay_get_x509subjectaltname(iph1->cert_p,
1903 &altname, &type, pos) != 0){
1904 plog(LLV_ERROR, LOCATION, NULL,
1905 "failed to get subjectAltName\n");
1906 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
1909 /* it's the end condition of the loop. */
1910 if (!altname) {
1911 plog(LLV_ERROR, LOCATION, NULL,
1912 "no proper subjectAltName.\n");
1913 return ISAKMP_NTYPE_INVALID_CERTIFICATE;
1916 if (check_typeofcertname(id_b->type, type) == 0)
1917 break;
1919 /* next name */
1920 racoon_free(altname);
1921 altname = NULL;
1923 if (idlen != strlen(altname)) {
1924 plog(LLV_ERROR, LOCATION, NULL,
1925 "Invalid ID length in phase 1.\n");
1926 racoon_free(altname);
1927 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
1929 if (check_typeofcertname(id_b->type, type) != 0) {
1930 plog(LLV_ERROR, LOCATION, NULL,
1931 "ID type mismatched. ID: %s CERT: %s.\n",
1932 s_ipsecdoi_ident(id_b->type),
1933 s_ipsecdoi_ident(type));
1934 racoon_free(altname);
1935 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
1937 error = memcmp(id_b + 1, altname, idlen);
1938 if (error) {
1939 plog(LLV_ERROR, LOCATION, NULL, "ID mismatched.\n");
1940 plogdump(LLV_DEBUG, id_b + 1, idlen);
1941 plogdump(LLV_DEBUG, altname, idlen);
1942 racoon_free(altname);
1943 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
1945 racoon_free(altname);
1946 return 0;
1948 default:
1949 plog(LLV_ERROR, LOCATION, NULL,
1950 "Inpropper ID type passed: %s.\n",
1951 s_ipsecdoi_ident(id_b->type));
1952 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
1954 /*NOTREACHED*/
1957 static int
1958 check_typeofcertname(doi, genid)
1959 int doi, genid;
1961 switch (doi) {
1962 case IPSECDOI_ID_IPV4_ADDR:
1963 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
1964 case IPSECDOI_ID_IPV6_ADDR:
1965 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
1966 case IPSECDOI_ID_IPV4_ADDR_RANGE:
1967 case IPSECDOI_ID_IPV6_ADDR_RANGE:
1968 if (genid != GENT_IPADD)
1969 return -1;
1970 return 0;
1971 case IPSECDOI_ID_FQDN:
1972 if (genid != GENT_DNS)
1973 return -1;
1974 return 0;
1975 case IPSECDOI_ID_USER_FQDN:
1976 if (genid != GENT_EMAIL)
1977 return -1;
1978 return 0;
1979 case IPSECDOI_ID_DER_ASN1_DN: /* should not be passed to this function*/
1980 case IPSECDOI_ID_DER_ASN1_GN:
1981 case IPSECDOI_ID_KEY_ID:
1982 default:
1983 return -1;
1985 /*NOTREACHED*/
1989 * save certificate including certificate type.
1992 oakley_savecert(iph1, gen)
1993 struct ph1handle *iph1;
1994 struct isakmp_gen *gen;
1996 vchar_t **c;
1997 u_int8_t type;
1998 STACK_OF(X509) *certs=NULL;
1999 PKCS7 *p7;
2001 type = *(u_int8_t *)(gen + 1) & 0xff;
2003 switch (type) {
2004 case ISAKMP_CERT_DNS:
2005 plog(LLV_WARNING, LOCATION, NULL,
2006 "CERT payload is unnecessary in DNSSEC. "
2007 "ignore this CERT payload.\n");
2008 return 0;
2009 case ISAKMP_CERT_PKCS7:
2010 case ISAKMP_CERT_PGP:
2011 case ISAKMP_CERT_X509SIGN:
2012 case ISAKMP_CERT_KERBEROS:
2013 case ISAKMP_CERT_SPKI:
2014 c = &iph1->cert_p;
2015 break;
2016 case ISAKMP_CERT_CRL:
2017 c = &iph1->crl_p;
2018 break;
2019 case ISAKMP_CERT_X509KE:
2020 case ISAKMP_CERT_X509ATTR:
2021 case ISAKMP_CERT_ARL:
2022 plog(LLV_ERROR, LOCATION, NULL,
2023 "No supported such CERT type %d\n", type);
2024 return -1;
2025 default:
2026 plog(LLV_ERROR, LOCATION, NULL,
2027 "Invalid CERT type %d\n", type);
2028 return -1;
2031 /* XXX choice the 1th cert, ignore after the cert. */
2032 /* XXX should be processed. */
2033 if (*c) {
2034 plog(LLV_WARNING, LOCATION, NULL,
2035 "ignore 2nd CERT payload.\n");
2036 return 0;
2039 if (type == ISAKMP_CERT_PKCS7) {
2040 u_char *bp;
2041 int i;
2043 /* Skip the header */
2044 bp = (u_char *)(gen + 1);
2045 /* And the first byte is the certificate type,
2046 * we know that already
2048 bp++;
2049 p7 = d2i_PKCS7(NULL, (void *)&bp,
2050 ntohs(gen->len) - sizeof(*gen) - 1);
2052 if (!p7) {
2053 plog(LLV_ERROR, LOCATION, NULL,
2054 "Failed to parse PKCS#7 CERT.\n");
2055 return -1;
2058 /* Copied this from the openssl pkcs7 application;
2059 * there"s little by way of documentation for any of
2060 * it. I can only presume it"s correct.
2063 i = OBJ_obj2nid(p7->type);
2064 switch (i) {
2065 case NID_pkcs7_signed:
2066 certs=p7->d.sign->cert;
2067 break;
2068 case NID_pkcs7_signedAndEnveloped:
2069 certs=p7->d.signed_and_enveloped->cert;
2070 break;
2071 default:
2072 break;
2075 if (!certs) {
2076 plog(LLV_ERROR, LOCATION, NULL,
2077 "CERT PKCS#7 bundle contains no certs.\n");
2078 PKCS7_free(p7);
2079 return -1;
2082 for (i = 0; i < sk_X509_num(certs); i++) {
2083 int len;
2084 u_char *bp;
2085 X509 *cert = sk_X509_value(certs,i);
2087 plog(LLV_DEBUG, LOCATION, NULL,
2088 "Trying PKCS#7 cert %d.\n", i);
2090 /* We'll just try each cert in turn */
2091 *c = dump_x509(cert);
2093 if (!*c) {
2094 plog(LLV_ERROR, LOCATION, NULL,
2095 "Failed to get CERT buffer.\n");
2096 continue;
2099 /* Ignore cert if it doesn't match identity
2100 * XXX If verify cert is disabled, we still just take
2101 * the first certificate....
2103 if (oakley_check_certid(iph1)) {
2104 plog(LLV_DEBUG, LOCATION, NULL,
2105 "Discarding CERT: does not match ID.\n");
2106 vfree((*c));
2107 *c = NULL;
2108 continue;
2112 char *p = eay_get_x509text(*c);
2113 plog(LLV_DEBUG, LOCATION, NULL, "CERT saved:\n");
2114 plogdump(LLV_DEBUG, (*c)->v, (*c)->l);
2115 plog(LLV_DEBUG, LOCATION, NULL, "%s",
2116 p ? p : "\n");
2117 racoon_free(p);
2119 break;
2121 PKCS7_free(p7);
2122 } else {
2123 *c = dump_isakmp_payload(gen);
2124 if (!*c) {
2125 plog(LLV_ERROR, LOCATION, NULL,
2126 "Failed to get CERT buffer.\n");
2127 return -1;
2130 switch (type) {
2131 case ISAKMP_CERT_PGP:
2132 case ISAKMP_CERT_X509SIGN:
2133 case ISAKMP_CERT_KERBEROS:
2134 case ISAKMP_CERT_SPKI:
2135 /* Ignore cert if it doesn't match identity
2136 * XXX If verify cert is disabled, we still just take
2137 * the first certificate....
2139 if (oakley_check_certid(iph1)){
2140 plog(LLV_DEBUG, LOCATION, NULL,
2141 "Discarding CERT: does not match ID.\n");
2142 vfree((*c));
2143 *c = NULL;
2144 return 0;
2148 char *p = eay_get_x509text(*c);
2149 plog(LLV_DEBUG, LOCATION, NULL, "CERT saved:\n");
2150 plogdump(LLV_DEBUG, (*c)->v, (*c)->l);
2151 plog(LLV_DEBUG, LOCATION, NULL, "%s", p ? p : "\n");
2152 racoon_free(p);
2154 break;
2155 case ISAKMP_CERT_CRL:
2156 plog(LLV_DEBUG, LOCATION, NULL, "CRL saved:\n");
2157 plogdump(LLV_DEBUG, (*c)->v, (*c)->l);
2158 break;
2159 case ISAKMP_CERT_X509KE:
2160 case ISAKMP_CERT_X509ATTR:
2161 case ISAKMP_CERT_ARL:
2162 default:
2163 /* XXX */
2164 vfree(*c);
2165 *c = NULL;
2166 return 0;
2170 return 0;
2174 * save certificate including certificate type.
2177 oakley_savecr(iph1, gen)
2178 struct ph1handle *iph1;
2179 struct isakmp_gen *gen;
2181 vchar_t *cert;
2182 vchar_t **c;
2183 u_int8_t type;
2185 type = *(u_int8_t *)(gen + 1) & 0xff;
2186 switch (type) {
2187 case ISAKMP_CERT_DNS:
2188 plog(LLV_WARNING, LOCATION, NULL,
2189 "CERT payload is unnecessary in DNSSEC\n");
2190 /*FALLTHRU*/
2191 case ISAKMP_CERT_PKCS7:
2192 case ISAKMP_CERT_PGP:
2193 case ISAKMP_CERT_X509SIGN:
2194 case ISAKMP_CERT_KERBEROS:
2195 case ISAKMP_CERT_SPKI:
2196 c = &iph1->cr_p;
2197 break;
2198 case ISAKMP_CERT_X509KE:
2199 case ISAKMP_CERT_X509ATTR:
2200 case ISAKMP_CERT_ARL:
2201 plog(LLV_ERROR, LOCATION, NULL,
2202 "No supported such CR type %d\n", type);
2203 return -1;
2204 case ISAKMP_CERT_CRL:
2205 default:
2206 plog(LLV_ERROR, LOCATION, NULL,
2207 "Invalid CR type %d\n", type);
2208 return -1;
2211 /* Already found an acceptable CR? */
2212 if (*c != NULL)
2213 return 0;
2215 cert = dump_isakmp_payload(gen);
2216 if (cert == NULL) {
2217 plog(LLV_ERROR, LOCATION, NULL,
2218 "Failed to get CR buffer.\n");
2219 return -1;
2222 plog(LLV_DEBUG, LOCATION, NULL, "CR received:\n");
2223 plogdump(LLV_DEBUG, cert->v, cert->l);
2225 *c = cert;
2226 if (resolveph1rmconf(iph1) == 0) {
2227 /* Found unique match */
2228 plog(LLV_DEBUG, LOCATION, NULL, "CR saved.\n");
2229 } else {
2230 /* Still ambiguous or matches nothing, ignore this CR */
2231 *c = NULL;
2232 vfree(cert);
2234 return 0;
2238 * Add a single CR.
2240 struct append_cr_ctx {
2241 struct ph1handle *iph1;
2242 struct payload_list *plist;
2245 static int
2246 oakley_append_rmconf_cr(rmconf, ctx)
2247 struct remoteconf *rmconf;
2248 void *ctx;
2250 struct append_cr_ctx *actx = (struct append_cr_ctx *) ctx;
2251 vchar_t *buf, *asn1dn = NULL;
2252 int type;
2254 /* Do we want to send CR about this? */
2255 if (rmconf->send_cr == FALSE)
2256 return 0;
2258 if (rmconf->peerscert != NULL) {
2259 type = oakley_get_certtype(rmconf->peerscert);
2260 asn1dn = eay_get_x509asn1issuername(rmconf->peerscert);
2261 } else if (rmconf->cacert != NULL) {
2262 type = oakley_get_certtype(rmconf->cacert);
2263 asn1dn = eay_get_x509asn1subjectname(rmconf->cacert);
2264 } else
2265 return 0;
2267 if (asn1dn == NULL) {
2268 plog(LLV_ERROR, LOCATION, actx->iph1->remote,
2269 "Failed to get CR ASN1 DN from certificate\n");
2270 return 0;
2273 buf = vmalloc(1 + asn1dn->l);
2274 if (buf == NULL)
2275 goto err;
2277 buf->v[0] = type;
2278 memcpy(&buf->v[1], asn1dn->v, asn1dn->l);
2280 plog(LLV_DEBUG, LOCATION, actx->iph1->remote,
2281 "appending CR: %s\n",
2282 s_isakmp_certtype(buf->v[0]));
2283 plogdump(LLV_DEBUG, buf->v, buf->l);
2285 actx->plist = isakmp_plist_append(actx->plist, buf, ISAKMP_NPTYPE_CR);
2287 err:
2288 vfree(asn1dn);
2289 return 0;
2293 * Append list of acceptable CRs.
2294 * RFC2048 3.10
2296 struct payload_list *
2297 oakley_append_cr(plist, iph1)
2298 struct payload_list *plist;
2299 struct ph1handle *iph1;
2301 struct append_cr_ctx ctx;
2302 struct rmconfselector sel;
2304 ctx.iph1 = iph1;
2305 ctx.plist = plist;
2306 if (iph1->rmconf == NULL) {
2307 rmconf_selector_from_ph1(&sel, iph1);
2308 enumrmconf(&sel, oakley_append_rmconf_cr, &ctx);
2309 } else {
2310 oakley_append_rmconf_cr(iph1->rmconf, &ctx);
2313 return ctx.plist;
2317 * check peer's CR.
2320 oakley_checkcr(iph1)
2321 struct ph1handle *iph1;
2323 int type;
2325 if (iph1->cr_p == NULL)
2326 return 0;
2328 plog(LLV_DEBUG, LOCATION, iph1->remote,
2329 "peer transmitted CR: %s\n",
2330 s_isakmp_certtype(oakley_get_certtype(iph1->cr_p)));
2332 type = oakley_get_certtype(iph1->cr_p);
2333 if (type != oakley_get_certtype(iph1->rmconf->mycert)) {
2334 plog(LLV_ERROR, LOCATION, iph1->remote,
2335 "such a cert type isn't supported: %d\n",
2336 type);
2337 return -1;
2340 return 0;
2344 * check to need CR payload.
2347 oakley_needcr(type)
2348 int type;
2350 switch (type) {
2351 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
2352 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
2353 #ifdef ENABLE_HYBRID
2354 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
2355 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
2356 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
2357 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
2358 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
2359 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
2360 #endif
2361 return 1;
2362 default:
2363 return 0;
2365 /*NOTREACHED*/
2369 * compute SKEYID
2370 * see seciton 5. Exchanges in RFC 2409
2371 * psk: SKEYID = prf(pre-shared-key, Ni_b | Nr_b)
2372 * sig: SKEYID = prf(Ni_b | Nr_b, g^ir)
2373 * enc: SKEYID = prf(H(Ni_b | Nr_b), CKY-I | CKY-R)
2376 oakley_skeyid(iph1)
2377 struct ph1handle *iph1;
2379 vchar_t *buf = NULL, *bp;
2380 char *p;
2381 int len;
2382 int error = -1;
2384 /* SKEYID */
2385 switch (iph1->approval->authmethod) {
2386 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
2387 #ifdef ENABLE_HYBRID
2388 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
2389 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
2390 #endif
2391 if (iph1->etype != ISAKMP_ETYPE_IDENT) {
2392 iph1->authstr = getpskbyname(iph1->id_p);
2393 if (iph1->authstr == NULL) {
2394 if (iph1->rmconf->verify_identifier) {
2395 plog(LLV_ERROR, LOCATION, iph1->remote,
2396 "couldn't find the pskey.\n");
2397 goto end;
2399 plog(LLV_NOTIFY, LOCATION, iph1->remote,
2400 "couldn't find the proper pskey, "
2401 "try to get one by the peer's address.\n");
2404 if (iph1->authstr == NULL) {
2406 * If the exchange type is the main mode or if it's
2407 * failed to get the psk by ID, racoon try to get
2408 * the psk by remote IP address.
2409 * It may be nonsense.
2411 iph1->authstr = getpskbyaddr(iph1->remote);
2412 if (iph1->authstr == NULL) {
2413 plog(LLV_ERROR, LOCATION, iph1->remote,
2414 "couldn't find the pskey for %s.\n",
2415 saddrwop2str(iph1->remote));
2416 goto end;
2419 plog(LLV_DEBUG, LOCATION, NULL, "the psk found.\n");
2420 /* should be secret PSK */
2421 plog(LLV_DEBUG2, LOCATION, NULL, "psk: ");
2422 plogdump(LLV_DEBUG2, iph1->authstr->v, iph1->authstr->l);
2424 len = iph1->nonce->l + iph1->nonce_p->l;
2425 buf = vmalloc(len);
2426 if (buf == NULL) {
2427 plog(LLV_ERROR, LOCATION, NULL,
2428 "failed to get skeyid buffer\n");
2429 goto end;
2431 p = buf->v;
2433 bp = (iph1->side == INITIATOR ? iph1->nonce : iph1->nonce_p);
2434 plog(LLV_DEBUG, LOCATION, NULL, "nonce 1: ");
2435 plogdump(LLV_DEBUG, bp->v, bp->l);
2436 memcpy(p, bp->v, bp->l);
2437 p += bp->l;
2439 bp = (iph1->side == INITIATOR ? iph1->nonce_p : iph1->nonce);
2440 plog(LLV_DEBUG, LOCATION, NULL, "nonce 2: ");
2441 plogdump(LLV_DEBUG, bp->v, bp->l);
2442 memcpy(p, bp->v, bp->l);
2443 p += bp->l;
2445 iph1->skeyid = oakley_prf(iph1->authstr, buf, iph1);
2446 if (iph1->skeyid == NULL)
2447 goto end;
2448 break;
2450 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
2451 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
2452 #ifdef ENABLE_HYBRID
2453 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
2454 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
2455 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
2456 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
2457 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
2458 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
2459 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
2460 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
2461 #endif
2462 #ifdef HAVE_GSSAPI
2463 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
2464 #endif
2465 len = iph1->nonce->l + iph1->nonce_p->l;
2466 buf = vmalloc(len);
2467 if (buf == NULL) {
2468 plog(LLV_ERROR, LOCATION, NULL,
2469 "failed to get nonce buffer\n");
2470 goto end;
2472 p = buf->v;
2474 bp = (iph1->side == INITIATOR ? iph1->nonce : iph1->nonce_p);
2475 plog(LLV_DEBUG, LOCATION, NULL, "nonce1: ");
2476 plogdump(LLV_DEBUG, bp->v, bp->l);
2477 memcpy(p, bp->v, bp->l);
2478 p += bp->l;
2480 bp = (iph1->side == INITIATOR ? iph1->nonce_p : iph1->nonce);
2481 plog(LLV_DEBUG, LOCATION, NULL, "nonce2: ");
2482 plogdump(LLV_DEBUG, bp->v, bp->l);
2483 memcpy(p, bp->v, bp->l);
2484 p += bp->l;
2486 iph1->skeyid = oakley_prf(buf, iph1->dhgxy, iph1);
2487 if (iph1->skeyid == NULL)
2488 goto end;
2489 break;
2490 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
2491 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
2492 #ifdef ENABLE_HYBRID
2493 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
2494 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
2495 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
2496 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
2497 #endif
2498 plog(LLV_WARNING, LOCATION, NULL,
2499 "not supported authentication method %s\n",
2500 s_oakley_attr_method(iph1->approval->authmethod));
2501 goto end;
2502 default:
2503 plog(LLV_ERROR, LOCATION, NULL,
2504 "invalid authentication method %d\n",
2505 iph1->approval->authmethod);
2506 goto end;
2509 plog(LLV_DEBUG, LOCATION, NULL, "SKEYID computed:\n");
2510 plogdump(LLV_DEBUG, iph1->skeyid->v, iph1->skeyid->l);
2512 error = 0;
2514 end:
2515 if (buf != NULL)
2516 vfree(buf);
2517 return error;
2521 * compute SKEYID_[dae]
2522 * see seciton 5. Exchanges in RFC 2409
2523 * SKEYID_d = prf(SKEYID, g^ir | CKY-I | CKY-R | 0)
2524 * SKEYID_a = prf(SKEYID, SKEYID_d | g^ir | CKY-I | CKY-R | 1)
2525 * SKEYID_e = prf(SKEYID, SKEYID_a | g^ir | CKY-I | CKY-R | 2)
2528 oakley_skeyid_dae(iph1)
2529 struct ph1handle *iph1;
2531 vchar_t *buf = NULL;
2532 char *p;
2533 int len;
2534 int error = -1;
2536 if (iph1->skeyid == NULL) {
2537 plog(LLV_ERROR, LOCATION, NULL, "no SKEYID found.\n");
2538 goto end;
2541 /* SKEYID D */
2542 /* SKEYID_d = prf(SKEYID, g^xy | CKY-I | CKY-R | 0) */
2543 len = iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1;
2544 buf = vmalloc(len);
2545 if (buf == NULL) {
2546 plog(LLV_ERROR, LOCATION, NULL,
2547 "failed to get skeyid buffer\n");
2548 goto end;
2550 p = buf->v;
2552 memcpy(p, iph1->dhgxy->v, iph1->dhgxy->l);
2553 p += iph1->dhgxy->l;
2554 memcpy(p, (caddr_t)&iph1->index.i_ck, sizeof(cookie_t));
2555 p += sizeof(cookie_t);
2556 memcpy(p, (caddr_t)&iph1->index.r_ck, sizeof(cookie_t));
2557 p += sizeof(cookie_t);
2558 *p = 0;
2559 iph1->skeyid_d = oakley_prf(iph1->skeyid, buf, iph1);
2560 if (iph1->skeyid_d == NULL)
2561 goto end;
2563 vfree(buf);
2564 buf = NULL;
2566 plog(LLV_DEBUG, LOCATION, NULL, "SKEYID_d computed:\n");
2567 plogdump(LLV_DEBUG, iph1->skeyid_d->v, iph1->skeyid_d->l);
2569 /* SKEYID A */
2570 /* SKEYID_a = prf(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1) */
2571 len = iph1->skeyid_d->l + iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1;
2572 buf = vmalloc(len);
2573 if (buf == NULL) {
2574 plog(LLV_ERROR, LOCATION, NULL,
2575 "failed to get skeyid buffer\n");
2576 goto end;
2578 p = buf->v;
2579 memcpy(p, iph1->skeyid_d->v, iph1->skeyid_d->l);
2580 p += iph1->skeyid_d->l;
2581 memcpy(p, iph1->dhgxy->v, iph1->dhgxy->l);
2582 p += iph1->dhgxy->l;
2583 memcpy(p, (caddr_t)&iph1->index.i_ck, sizeof(cookie_t));
2584 p += sizeof(cookie_t);
2585 memcpy(p, (caddr_t)&iph1->index.r_ck, sizeof(cookie_t));
2586 p += sizeof(cookie_t);
2587 *p = 1;
2588 iph1->skeyid_a = oakley_prf(iph1->skeyid, buf, iph1);
2589 if (iph1->skeyid_a == NULL)
2590 goto end;
2592 vfree(buf);
2593 buf = NULL;
2595 plog(LLV_DEBUG, LOCATION, NULL, "SKEYID_a computed:\n");
2596 plogdump(LLV_DEBUG, iph1->skeyid_a->v, iph1->skeyid_a->l);
2598 /* SKEYID E */
2599 /* SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2) */
2600 len = iph1->skeyid_a->l + iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1;
2601 buf = vmalloc(len);
2602 if (buf == NULL) {
2603 plog(LLV_ERROR, LOCATION, NULL,
2604 "failed to get skeyid buffer\n");
2605 goto end;
2607 p = buf->v;
2608 memcpy(p, iph1->skeyid_a->v, iph1->skeyid_a->l);
2609 p += iph1->skeyid_a->l;
2610 memcpy(p, iph1->dhgxy->v, iph1->dhgxy->l);
2611 p += iph1->dhgxy->l;
2612 memcpy(p, (caddr_t)&iph1->index.i_ck, sizeof(cookie_t));
2613 p += sizeof(cookie_t);
2614 memcpy(p, (caddr_t)&iph1->index.r_ck, sizeof(cookie_t));
2615 p += sizeof(cookie_t);
2616 *p = 2;
2617 iph1->skeyid_e = oakley_prf(iph1->skeyid, buf, iph1);
2618 if (iph1->skeyid_e == NULL)
2619 goto end;
2621 vfree(buf);
2622 buf = NULL;
2624 plog(LLV_DEBUG, LOCATION, NULL, "SKEYID_e computed:\n");
2625 plogdump(LLV_DEBUG, iph1->skeyid_e->v, iph1->skeyid_e->l);
2627 error = 0;
2629 end:
2630 if (buf != NULL)
2631 vfree(buf);
2632 return error;
2636 * compute final encryption key.
2637 * see Appendix B.
2640 oakley_compute_enckey(iph1)
2641 struct ph1handle *iph1;
2643 u_int keylen, prflen;
2644 int error = -1;
2646 /* RFC2409 p39 */
2647 keylen = alg_oakley_encdef_keylen(iph1->approval->enctype,
2648 iph1->approval->encklen);
2649 if (keylen == -1) {
2650 plog(LLV_ERROR, LOCATION, NULL,
2651 "invalid encryption algorithm %d, "
2652 "or invalid key length %d.\n",
2653 iph1->approval->enctype,
2654 iph1->approval->encklen);
2655 goto end;
2657 iph1->key = vmalloc(keylen >> 3);
2658 if (iph1->key == NULL) {
2659 plog(LLV_ERROR, LOCATION, NULL,
2660 "failed to get key buffer\n");
2661 goto end;
2664 /* set prf length */
2665 prflen = alg_oakley_hashdef_hashlen(iph1->approval->hashtype);
2666 if (prflen == -1) {
2667 plog(LLV_ERROR, LOCATION, NULL,
2668 "invalid hash type %d.\n", iph1->approval->hashtype);
2669 goto end;
2672 /* see isakmp-oakley-08 5.3. */
2673 if (iph1->key->l <= iph1->skeyid_e->l) {
2675 * if length(Ka) <= length(SKEYID_e)
2676 * Ka = first length(K) bit of SKEYID_e
2678 memcpy(iph1->key->v, iph1->skeyid_e->v, iph1->key->l);
2679 } else {
2680 vchar_t *buf = NULL, *res = NULL;
2681 u_char *p, *ep;
2682 int cplen;
2683 int subkey;
2686 * otherwise,
2687 * Ka = K1 | K2 | K3
2688 * where
2689 * K1 = prf(SKEYID_e, 0)
2690 * K2 = prf(SKEYID_e, K1)
2691 * K3 = prf(SKEYID_e, K2)
2693 plog(LLV_DEBUG, LOCATION, NULL,
2694 "len(SKEYID_e) < len(Ka) (%zu < %zu), "
2695 "generating long key (Ka = K1 | K2 | ...)\n",
2696 iph1->skeyid_e->l, iph1->key->l);
2698 if ((buf = vmalloc(prflen >> 3)) == 0) {
2699 plog(LLV_ERROR, LOCATION, NULL,
2700 "failed to get key buffer\n");
2701 goto end;
2703 p = (u_char *)iph1->key->v;
2704 ep = p + iph1->key->l;
2706 subkey = 1;
2707 while (p < ep) {
2708 if (p == (u_char *)iph1->key->v) {
2709 /* just for computing K1 */
2710 buf->v[0] = 0;
2711 buf->l = 1;
2713 res = oakley_prf(iph1->skeyid_e, buf, iph1);
2714 if (res == NULL) {
2715 vfree(buf);
2716 goto end;
2718 plog(LLV_DEBUG, LOCATION, NULL,
2719 "compute intermediate encryption key K%d\n",
2720 subkey);
2721 plogdump(LLV_DEBUG, buf->v, buf->l);
2722 plogdump(LLV_DEBUG, res->v, res->l);
2724 cplen = (res->l < ep - p) ? res->l : ep - p;
2725 memcpy(p, res->v, cplen);
2726 p += cplen;
2728 buf->l = prflen >> 3; /* to cancel K1 speciality */
2729 if (res->l != buf->l) {
2730 plog(LLV_ERROR, LOCATION, NULL,
2731 "internal error: res->l=%zu buf->l=%zu\n",
2732 res->l, buf->l);
2733 vfree(res);
2734 vfree(buf);
2735 goto end;
2737 memcpy(buf->v, res->v, res->l);
2738 vfree(res);
2739 subkey++;
2742 vfree(buf);
2746 * don't check any weak key or not.
2747 * draft-ietf-ipsec-ike-01.txt Appendix B.
2748 * draft-ietf-ipsec-ciph-aes-cbc-00.txt Section 2.3.
2750 #if 0
2751 /* weakkey check */
2752 if (iph1->approval->enctype > ARRAYLEN(oakley_encdef)
2753 || oakley_encdef[iph1->approval->enctype].weakkey == NULL) {
2754 plog(LLV_ERROR, LOCATION, NULL,
2755 "encryption algorithm %d isn't supported.\n",
2756 iph1->approval->enctype);
2757 goto end;
2759 if ((oakley_encdef[iph1->approval->enctype].weakkey)(iph1->key)) {
2760 plog(LLV_ERROR, LOCATION, NULL,
2761 "weakkey was generated.\n");
2762 goto end;
2764 #endif
2766 plog(LLV_DEBUG, LOCATION, NULL, "final encryption key computed:\n");
2767 plogdump(LLV_DEBUG, iph1->key->v, iph1->key->l);
2769 error = 0;
2771 end:
2772 return error;
2776 * compute IV and set to ph1handle
2777 * IV = hash(g^xi | g^xr)
2778 * see 4.1 Phase 1 state in draft-ietf-ipsec-ike.
2781 oakley_newiv(iph1)
2782 struct ph1handle *iph1;
2784 struct isakmp_ivm *newivm = NULL;
2785 vchar_t *buf = NULL, *bp;
2786 char *p;
2787 int len;
2789 /* create buffer */
2790 len = iph1->dhpub->l + iph1->dhpub_p->l;
2791 buf = vmalloc(len);
2792 if (buf == NULL) {
2793 plog(LLV_ERROR, LOCATION, NULL,
2794 "failed to get iv buffer\n");
2795 return -1;
2798 p = buf->v;
2800 bp = (iph1->side == INITIATOR ? iph1->dhpub : iph1->dhpub_p);
2801 memcpy(p, bp->v, bp->l);
2802 p += bp->l;
2804 bp = (iph1->side == INITIATOR ? iph1->dhpub_p : iph1->dhpub);
2805 memcpy(p, bp->v, bp->l);
2806 p += bp->l;
2808 /* allocate IVm */
2809 newivm = racoon_calloc(1, sizeof(struct isakmp_ivm));
2810 if (newivm == NULL) {
2811 plog(LLV_ERROR, LOCATION, NULL,
2812 "failed to get iv buffer\n");
2813 vfree(buf);
2814 return -1;
2817 /* compute IV */
2818 newivm->iv = oakley_hash(buf, iph1);
2819 if (newivm->iv == NULL) {
2820 vfree(buf);
2821 oakley_delivm(newivm);
2822 return -1;
2825 /* adjust length of iv */
2826 newivm->iv->l = alg_oakley_encdef_blocklen(iph1->approval->enctype);
2827 if (newivm->iv->l == -1) {
2828 plog(LLV_ERROR, LOCATION, NULL,
2829 "invalid encryption algorithm %d.\n",
2830 iph1->approval->enctype);
2831 vfree(buf);
2832 oakley_delivm(newivm);
2833 return -1;
2836 /* create buffer to save iv */
2837 if ((newivm->ive = vdup(newivm->iv)) == NULL) {
2838 plog(LLV_ERROR, LOCATION, NULL,
2839 "vdup (%s)\n", strerror(errno));
2840 vfree(buf);
2841 oakley_delivm(newivm);
2842 return -1;
2845 vfree(buf);
2847 plog(LLV_DEBUG, LOCATION, NULL, "IV computed:\n");
2848 plogdump(LLV_DEBUG, newivm->iv->v, newivm->iv->l);
2850 iph1->ivm = newivm;
2852 return 0;
2856 * compute IV for the payload after phase 1.
2857 * It's not limited for phase 2.
2858 * if pahse 1 was encrypted.
2859 * IV = hash(last CBC block of Phase 1 | M-ID)
2860 * if phase 1 was not encrypted.
2861 * IV = hash(phase 1 IV | M-ID)
2862 * see 4.2 Phase 2 state in draft-ietf-ipsec-ike.
2864 struct isakmp_ivm *
2865 oakley_newiv2(iph1, msgid)
2866 struct ph1handle *iph1;
2867 u_int32_t msgid;
2869 struct isakmp_ivm *newivm = NULL;
2870 vchar_t *buf = NULL;
2871 char *p;
2872 int len;
2873 int error = -1;
2875 /* create buffer */
2876 len = iph1->ivm->iv->l + sizeof(msgid_t);
2877 buf = vmalloc(len);
2878 if (buf == NULL) {
2879 plog(LLV_ERROR, LOCATION, NULL,
2880 "failed to get iv buffer\n");
2881 goto end;
2884 p = buf->v;
2886 memcpy(p, iph1->ivm->iv->v, iph1->ivm->iv->l);
2887 p += iph1->ivm->iv->l;
2889 memcpy(p, &msgid, sizeof(msgid));
2891 plog(LLV_DEBUG, LOCATION, NULL, "compute IV for phase2\n");
2892 plog(LLV_DEBUG, LOCATION, NULL, "phase1 last IV:\n");
2893 plogdump(LLV_DEBUG, buf->v, buf->l);
2895 /* allocate IVm */
2896 newivm = racoon_calloc(1, sizeof(struct isakmp_ivm));
2897 if (newivm == NULL) {
2898 plog(LLV_ERROR, LOCATION, NULL,
2899 "failed to get iv buffer\n");
2900 goto end;
2903 /* compute IV */
2904 if ((newivm->iv = oakley_hash(buf, iph1)) == NULL)
2905 goto end;
2907 /* adjust length of iv */
2908 newivm->iv->l = alg_oakley_encdef_blocklen(iph1->approval->enctype);
2909 if (newivm->iv->l == -1) {
2910 plog(LLV_ERROR, LOCATION, NULL,
2911 "invalid encryption algorithm %d.\n",
2912 iph1->approval->enctype);
2913 goto end;
2916 /* create buffer to save new iv */
2917 if ((newivm->ive = vdup(newivm->iv)) == NULL) {
2918 plog(LLV_ERROR, LOCATION, NULL, "vdup (%s)\n", strerror(errno));
2919 goto end;
2922 error = 0;
2924 plog(LLV_DEBUG, LOCATION, NULL, "phase2 IV computed:\n");
2925 plogdump(LLV_DEBUG, newivm->iv->v, newivm->iv->l);
2927 end:
2928 if (error && newivm != NULL){
2929 oakley_delivm(newivm);
2930 newivm=NULL;
2932 if (buf != NULL)
2933 vfree(buf);
2934 return newivm;
2937 void
2938 oakley_delivm(ivm)
2939 struct isakmp_ivm *ivm;
2941 if (ivm == NULL)
2942 return;
2944 if (ivm->iv != NULL)
2945 vfree(ivm->iv);
2946 if (ivm->ive != NULL)
2947 vfree(ivm->ive);
2948 racoon_free(ivm);
2949 plog(LLV_DEBUG, LOCATION, NULL, "IV freed\n");
2951 return;
2955 * decrypt packet.
2956 * save new iv and old iv.
2958 vchar_t *
2959 oakley_do_decrypt(iph1, msg, ivdp, ivep)
2960 struct ph1handle *iph1;
2961 vchar_t *msg, *ivdp, *ivep;
2963 vchar_t *buf = NULL, *new = NULL;
2964 char *pl;
2965 int len;
2966 u_int8_t padlen;
2967 int blen;
2968 int error = -1;
2970 plog(LLV_DEBUG, LOCATION, NULL, "begin decryption.\n");
2972 blen = alg_oakley_encdef_blocklen(iph1->approval->enctype);
2973 if (blen == -1) {
2974 plog(LLV_ERROR, LOCATION, NULL,
2975 "invalid encryption algorithm %d.\n",
2976 iph1->approval->enctype);
2977 goto end;
2980 /* save IV for next, but not sync. */
2981 memset(ivep->v, 0, ivep->l);
2982 memcpy(ivep->v, (caddr_t)&msg->v[msg->l - blen], blen);
2984 plog(LLV_DEBUG, LOCATION, NULL,
2985 "IV was saved for next processing:\n");
2986 plogdump(LLV_DEBUG, ivep->v, ivep->l);
2988 pl = msg->v + sizeof(struct isakmp);
2990 len = msg->l - sizeof(struct isakmp);
2992 /* create buffer */
2993 buf = vmalloc(len);
2994 if (buf == NULL) {
2995 plog(LLV_ERROR, LOCATION, NULL,
2996 "failed to get buffer to decrypt.\n");
2997 goto end;
2999 memcpy(buf->v, pl, len);
3001 /* do decrypt */
3002 new = alg_oakley_encdef_decrypt(iph1->approval->enctype,
3003 buf, iph1->key, ivdp);
3004 if (new == NULL || new->v == NULL || new->l == 0) {
3005 plog(LLV_ERROR, LOCATION, NULL,
3006 "decryption %d failed.\n", iph1->approval->enctype);
3007 goto end;
3009 plog(LLV_DEBUG, LOCATION, NULL, "with key:\n");
3010 plogdump(LLV_DEBUG, iph1->key->v, iph1->key->l);
3012 vfree(buf);
3013 buf = NULL;
3015 plog(LLV_DEBUG, LOCATION, NULL, "decrypted payload by IV:\n");
3016 plogdump(LLV_DEBUG, ivdp->v, ivdp->l);
3018 plog(LLV_DEBUG, LOCATION, NULL,
3019 "decrypted payload, but not trimed.\n");
3020 plogdump(LLV_DEBUG, new->v, new->l);
3022 /* get padding length */
3023 if (lcconf->pad_excltail)
3024 padlen = new->v[new->l - 1] + 1;
3025 else
3026 padlen = new->v[new->l - 1];
3027 plog(LLV_DEBUG, LOCATION, NULL, "padding len=%u\n", padlen);
3029 /* trim padding */
3030 if (lcconf->pad_strict) {
3031 if (padlen > new->l) {
3032 plog(LLV_ERROR, LOCATION, NULL,
3033 "invalied padding len=%u, buflen=%zu.\n",
3034 padlen, new->l);
3035 plogdump(LLV_ERROR, new->v, new->l);
3036 goto end;
3038 new->l -= padlen;
3039 plog(LLV_DEBUG, LOCATION, NULL, "trimmed padding\n");
3040 } else {
3041 plog(LLV_DEBUG, LOCATION, NULL, "skip to trim padding.\n");
3044 /* create new buffer */
3045 len = sizeof(struct isakmp) + new->l;
3046 buf = vmalloc(len);
3047 if (buf == NULL) {
3048 plog(LLV_ERROR, LOCATION, NULL,
3049 "failed to get buffer to decrypt.\n");
3050 goto end;
3052 memcpy(buf->v, msg->v, sizeof(struct isakmp));
3053 memcpy(buf->v + sizeof(struct isakmp), new->v, new->l);
3054 ((struct isakmp *)buf->v)->len = htonl(buf->l);
3056 plog(LLV_DEBUG, LOCATION, NULL, "decrypted.\n");
3057 plogdump(LLV_DEBUG, buf->v, buf->l);
3059 #ifdef HAVE_PRINT_ISAKMP_C
3060 isakmp_printpacket(buf, iph1->remote, iph1->local, 1);
3061 #endif
3063 error = 0;
3065 end:
3066 if (error && buf != NULL) {
3067 vfree(buf);
3068 buf = NULL;
3070 if (new != NULL)
3071 vfree(new);
3073 return buf;
3077 * encrypt packet.
3079 vchar_t *
3080 oakley_do_encrypt(iph1, msg, ivep, ivp)
3081 struct ph1handle *iph1;
3082 vchar_t *msg, *ivep, *ivp;
3084 vchar_t *buf = 0, *new = 0;
3085 char *pl;
3086 int len;
3087 u_int padlen;
3088 int blen;
3089 int error = -1;
3091 plog(LLV_DEBUG, LOCATION, NULL, "begin encryption.\n");
3093 /* set cbc block length */
3094 blen = alg_oakley_encdef_blocklen(iph1->approval->enctype);
3095 if (blen == -1) {
3096 plog(LLV_ERROR, LOCATION, NULL,
3097 "invalid encryption algorithm %d.\n",
3098 iph1->approval->enctype);
3099 goto end;
3102 pl = msg->v + sizeof(struct isakmp);
3103 len = msg->l - sizeof(struct isakmp);
3105 /* add padding */
3106 padlen = oakley_padlen(len, blen);
3107 plog(LLV_DEBUG, LOCATION, NULL, "pad length = %u\n", padlen);
3109 /* create buffer */
3110 buf = vmalloc(len + padlen);
3111 if (buf == NULL) {
3112 plog(LLV_ERROR, LOCATION, NULL,
3113 "failed to get buffer to encrypt.\n");
3114 goto end;
3116 if (padlen) {
3117 int i;
3118 char *p = &buf->v[len];
3119 if (lcconf->pad_random) {
3120 for (i = 0; i < padlen; i++)
3121 *p++ = eay_random() & 0xff;
3124 memcpy(buf->v, pl, len);
3126 /* make pad into tail */
3127 if (lcconf->pad_excltail)
3128 buf->v[len + padlen - 1] = padlen - 1;
3129 else
3130 buf->v[len + padlen - 1] = padlen;
3132 plogdump(LLV_DEBUG, buf->v, buf->l);
3134 /* do encrypt */
3135 new = alg_oakley_encdef_encrypt(iph1->approval->enctype,
3136 buf, iph1->key, ivep);
3137 if (new == NULL) {
3138 plog(LLV_ERROR, LOCATION, NULL,
3139 "encryption %d failed.\n", iph1->approval->enctype);
3140 goto end;
3142 plog(LLV_DEBUG, LOCATION, NULL, "with key:\n");
3143 plogdump(LLV_DEBUG, iph1->key->v, iph1->key->l);
3145 vfree(buf);
3146 buf = NULL;
3148 plog(LLV_DEBUG, LOCATION, NULL, "encrypted payload by IV:\n");
3149 plogdump(LLV_DEBUG, ivep->v, ivep->l);
3151 /* save IV for next */
3152 memset(ivp->v, 0, ivp->l);
3153 memcpy(ivp->v, (caddr_t)&new->v[new->l - blen], blen);
3155 plog(LLV_DEBUG, LOCATION, NULL, "save IV for next:\n");
3156 plogdump(LLV_DEBUG, ivp->v, ivp->l);
3158 /* create new buffer */
3159 len = sizeof(struct isakmp) + new->l;
3160 buf = vmalloc(len);
3161 if (buf == NULL) {
3162 plog(LLV_ERROR, LOCATION, NULL,
3163 "failed to get buffer to encrypt.\n");
3164 goto end;
3166 memcpy(buf->v, msg->v, sizeof(struct isakmp));
3167 memcpy(buf->v + sizeof(struct isakmp), new->v, new->l);
3168 ((struct isakmp *)buf->v)->len = htonl(buf->l);
3170 error = 0;
3172 plog(LLV_DEBUG, LOCATION, NULL, "encrypted.\n");
3174 end:
3175 if (error && buf != NULL) {
3176 vfree(buf);
3177 buf = NULL;
3179 if (new != NULL)
3180 vfree(new);
3182 return buf;
3185 /* culculate padding length */
3186 static int
3187 oakley_padlen(len, base)
3188 int len, base;
3190 int padlen;
3192 padlen = base - len % base;
3194 if (lcconf->pad_randomlen)
3195 padlen += ((eay_random() % (lcconf->pad_maxsize + 1) + 1) *
3196 base);
3198 return padlen;