]> git.saurik.com Git - apple/network_cmds.git/blame - racoon.tproj/isakmp_base.c
network_cmds-176.tar.gz
[apple/network_cmds.git] / racoon.tproj / isakmp_base.c
CommitLineData
ac2f15b3 1/* $KAME: isakmp_base.c,v 1.48 2001/12/12 15:29:13 sakane Exp $ */
7ba0088d
A
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/* Base Exchange (Base Mode) */
33
34#include <sys/types.h>
35#include <sys/param.h>
36
37#include <stdlib.h>
38#include <stdio.h>
39#include <string.h>
40#include <errno.h>
41#if TIME_WITH_SYS_TIME
42# include <sys/time.h>
43# include <time.h>
44#else
45# if HAVE_SYS_TIME_H
46# include <sys/time.h>
47# else
48# include <time.h>
49# endif
50#endif
51
52#include "var.h"
53#include "misc.h"
54#include "vmbuf.h"
55#include "plog.h"
56#include "sockmisc.h"
57#include "schedule.h"
58#include "debug.h"
59
60#include "localconf.h"
61#include "remoteconf.h"
62#include "isakmp_var.h"
63#include "isakmp.h"
64#include "oakley.h"
65#include "handler.h"
66#include "ipsec_doi.h"
67#include "crypto_openssl.h"
68#include "pfkey.h"
69#include "isakmp_base.h"
70#include "isakmp_inf.h"
71#include "vendorid.h"
72
73/* %%%
74 * begin Identity Protection Mode as initiator.
75 */
76/*
77 * send to responder
78 * psk: HDR, SA, Idii, Ni_b
79 * sig: HDR, SA, Idii, Ni_b
80 * rsa: HDR, SA, [HASH(1),] <IDii_b>Pubkey_r, <Ni_b>Pubkey_r
81 * rev: HDR, SA, [HASH(1),] <Ni_b>Pubkey_r, <IDii_b>Ke_i
82 */
83int
84base_i1send(iph1, msg)
85 struct ph1handle *iph1;
86 vchar_t *msg; /* must be null */
87{
88 struct isakmp_gen *gen;
89 caddr_t p;
90 int tlen;
91 int error = -1;
92
93 /* validity check */
94 if (msg != NULL) {
95 plog(LLV_ERROR, LOCATION, NULL,
96 "msg has to be NULL in this function.\n");
97 goto end;
98 }
99 if (iph1->status != PHASE1ST_START) {
100 plog(LLV_ERROR, LOCATION, NULL,
101 "status mismatched %d.\n", iph1->status);
102 goto end;
103 }
104
105 /* create isakmp index */
106 memset(&iph1->index, 0, sizeof(iph1->index));
107 isakmp_newcookie((caddr_t)&iph1->index, iph1->remote, iph1->local);
108
109 /* make ID payload into isakmp status */
110 if (ipsecdoi_setid1(iph1) < 0)
111 goto end;
112
113 /* create SA payload for my proposal */
114 iph1->sa = ipsecdoi_setph1proposal(iph1->rmconf->proposal);
115 if (iph1->sa == NULL)
116 goto end;
117
118 /* generate NONCE value */
119 iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
120 if (iph1->nonce == NULL)
121 goto end;
122
123 /* create buffer to send isakmp payload */
124 tlen = sizeof(struct isakmp)
125 + sizeof(*gen) + iph1->sa->l
126 + sizeof(*gen) + iph1->id->l
127 + sizeof(*gen) + iph1->nonce->l;
128
129 iph1->sendbuf = vmalloc(tlen);
130 if (iph1->sendbuf == NULL) {
131 plog(LLV_ERROR, LOCATION, NULL,
132 "failed to get buffer to send.\n");
133 goto end;
134 }
135
136 /* set isakmp header */
137 p = set_isakmp_header(iph1->sendbuf, iph1, ISAKMP_NPTYPE_SA);
138 if (p == NULL)
139 goto end;
140
141 /* set SA payload to propose */
142 p = set_isakmp_payload(p, iph1->sa, ISAKMP_NPTYPE_ID);
143
144 /* create isakmp ID payload */
145 p = set_isakmp_payload(p, iph1->id, ISAKMP_NPTYPE_NONCE);
146
147 /* create isakmp NONCE payload */
148 p = set_isakmp_payload(p, iph1->nonce, ISAKMP_NPTYPE_NONE);
149
150#ifdef HAVE_PRINT_ISAKMP_C
151 isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
152#endif
153
154 /* send the packet, add to the schedule to resend */
155 iph1->retry_counter = iph1->rmconf->retry_counter;
156 if (isakmp_ph1resend(iph1) == -1)
157 goto end;
158
159 iph1->status = PHASE1ST_MSG1SENT;
160
161 error = 0;
162
163end:
164
165 return error;
166}
167
168/*
169 * receive from responder
170 * psk: HDR, SA, Idir, Nr_b
171 * sig: HDR, SA, Idir, Nr_b, [ CR ]
172 * rsa: HDR, SA, <IDir_b>PubKey_i, <Nr_b>PubKey_i
173 * rev: HDR, SA, <Nr_b>PubKey_i, <IDir_b>Ke_r
174 */
175int
176base_i2recv(iph1, msg)
177 struct ph1handle *iph1;
178 vchar_t *msg;
179{
180 vchar_t *pbuf = NULL;
181 struct isakmp_parse_t *pa;
182 vchar_t *satmp = NULL;
183 int error = -1;
184
185 /* validity check */
186 if (iph1->status != PHASE1ST_MSG1SENT) {
187 plog(LLV_ERROR, LOCATION, NULL,
188 "status mismatched %d.\n", iph1->status);
189 goto end;
190 }
191
192 /* validate the type of next payload */
193 pbuf = isakmp_parse(msg);
194 if (pbuf == NULL)
195 goto end;
196 pa = (struct isakmp_parse_t *)pbuf->v;
197
198 /* SA payload is fixed postion */
199 if (pa->type != ISAKMP_NPTYPE_SA) {
200 plog(LLV_ERROR, LOCATION, iph1->remote,
201 "received invalid next payload type %d, "
202 "expecting %d.\n",
203 pa->type, ISAKMP_NPTYPE_SA);
204 goto end;
205 }
206 if (isakmp_p2ph(&satmp, pa->ptr) < 0)
207 goto end;
208 pa++;
209
210 for (/*nothing*/;
211 pa->type != ISAKMP_NPTYPE_NONE;
212 pa++) {
213
214 switch (pa->type) {
215 case ISAKMP_NPTYPE_NONCE:
216 if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0)
217 goto end;
218 break;
219 case ISAKMP_NPTYPE_ID:
220 if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
221 goto end;
222 break;
223 case ISAKMP_NPTYPE_VID:
224 (void)check_vendorid(pa->ptr);
225 break;
226 default:
227 /* don't send information, see ident_r1recv() */
228 plog(LLV_ERROR, LOCATION, iph1->remote,
229 "ignore the packet, "
230 "received unexpecting payload type %d.\n",
231 pa->type);
232 goto end;
233 }
234 }
235
236 if (iph1->nonce_p == NULL || iph1->id_p == NULL) {
237 plog(LLV_ERROR, LOCATION, iph1->remote,
238 "few isakmp message received.\n");
239 goto end;
240 }
241
242 /* verify identifier */
243 if (ipsecdoi_checkid1(iph1) != 0) {
244 plog(LLV_ERROR, LOCATION, iph1->remote,
245 "invalid ID payload.\n");
246 goto end;
247 }
248
249 /* check SA payload and set approval SA for use */
250 if (ipsecdoi_checkph1proposal(satmp, iph1) < 0) {
251 plog(LLV_ERROR, LOCATION, iph1->remote,
252 "failed to get valid proposal.\n");
253 /* XXX send information */
254 goto end;
255 }
256 if (iph1->sa_ret) {
257 vfree(iph1->sa_ret);
258 iph1->sa_ret = NULL;
259 }
260
261 iph1->status = PHASE1ST_MSG2RECEIVED;
262
263 error = 0;
264
265end:
266 if (pbuf)
267 vfree(pbuf);
268 if (satmp)
269 vfree(satmp);
270
271 if (error) {
272 VPTRINIT(iph1->nonce_p);
273 VPTRINIT(iph1->id_p);
274 }
275
276 return error;
277}
278
279/*
280 * send to responder
281 * psk: HDR, KE, HASH_I
282 * sig: HDR, KE, [ CR, ] [CERT,] SIG_I
283 * rsa: HDR, KE, HASH_I
284 * rev: HDR, <KE>Ke_i, HASH_I
285 */
286int
287base_i2send(iph1, msg)
288 struct ph1handle *iph1;
289 vchar_t *msg;
290{
291 struct isakmp_gen *gen;
292 caddr_t p;
293 vchar_t *vid = NULL;
294 int tlen;
295 int need_cert = 0;
296 int error = -1;
297
298 /* validity check */
299 if (iph1->status != PHASE1ST_MSG2RECEIVED) {
300 plog(LLV_ERROR, LOCATION, NULL,
301 "status mismatched %d.\n", iph1->status);
302 goto end;
303 }
304
305 /* fix isakmp index */
306 memcpy(&iph1->index.r_ck, &((struct isakmp *)msg->v)->r_ck,
307 sizeof(cookie_t));
308
309 /* generate DH public value */
310 if (oakley_dh_generate(iph1->approval->dhgrp,
311 &iph1->dhpub, &iph1->dhpriv) < 0)
312 goto end;
313
314 /* generate SKEYID to compute hash if not signature mode */
315 if (iph1->approval->authmethod != OAKLEY_ATTR_AUTH_METHOD_RSASIG
316 && iph1->approval->authmethod != OAKLEY_ATTR_AUTH_METHOD_DSSSIG) {
317 if (oakley_skeyid(iph1) < 0)
318 goto end;
319 }
320
321 /* generate HASH to send */
322 plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_I\n");
323 iph1->hash = oakley_ph1hash_base_i(iph1, GENERATE);
324 if (iph1->hash == NULL)
325 goto end;
326
327 /* create buffer to send isakmp payload */
328 tlen = sizeof(struct isakmp);
329
330 switch (iph1->approval->authmethod) {
331 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
332 tlen += sizeof(*gen) + iph1->dhpub->l
333 + sizeof(*gen) + iph1->hash->l;
334 if ((vid = set_vendorid(iph1->approval->vendorid)) != NULL)
335 tlen += sizeof(*gen) + vid->l;
336
337 iph1->sendbuf = vmalloc(tlen);
338 if (iph1->sendbuf == NULL) {
339 plog(LLV_ERROR, LOCATION, NULL,
340 "failed to get buffer to send.\n");
341 goto end;
342 }
343
344 /* set isakmp header */
345 p = set_isakmp_header(iph1->sendbuf, iph1, ISAKMP_NPTYPE_KE);
346 if (p == NULL)
347 goto end;
348
349 /* create isakmp KE payload */
350 p = set_isakmp_payload(p, iph1->dhpub, ISAKMP_NPTYPE_HASH);
351
352 /* create isakmp HASH payload */
353 p = set_isakmp_payload(p, iph1->hash,
354 vid ? ISAKMP_NPTYPE_VID : ISAKMP_NPTYPE_NONE);
355
356 /* append vendor id, if needed */
357 if (vid)
358 p = set_isakmp_payload(p, vid, ISAKMP_NPTYPE_NONE);
359 break;
360#ifdef HAVE_SIGNING_C
361 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
362 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
363 /* XXX if there is CR or not ? */
364
365 if (oakley_getmycert(iph1) < 0)
366 goto end;
367
368 if (oakley_getsign(iph1) < 0)
369 goto end;
370
371 if (iph1->cert && iph1->rmconf->send_cert)
372 need_cert = 1;
373
374 tlen += sizeof(*gen) + iph1->dhpub->l
375 + sizeof(*gen) + iph1->sig->l;
376 if (need_cert)
377 tlen += sizeof(*gen) + iph1->cert->pl->l;
378
379 iph1->sendbuf = vmalloc(tlen);
380 if (iph1->sendbuf == NULL) {
381 plog(LLV_ERROR, LOCATION, NULL,
382 "failed to get buffer to send.\n");
383 goto end;
384 }
385
386 /* set isakmp header */
387 p = set_isakmp_header(iph1->sendbuf, iph1, ISAKMP_NPTYPE_KE);
388 if (p == NULL)
389 goto end;
390
391 /* create isakmp KE payload */
392 p = set_isakmp_payload(p, iph1->dhpub, need_cert
393 ? ISAKMP_NPTYPE_CERT
394 : ISAKMP_NPTYPE_SIG);
395
396 /* add CERT payload if there */
397 if (need_cert)
398 p = set_isakmp_payload(p, iph1->cert->pl, ISAKMP_NPTYPE_SIG);
399 /* add SIG payload */
400 p = set_isakmp_payload(p, iph1->sig, ISAKMP_NPTYPE_NONE);
401 break;
402#endif
403 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
404 /* ... */
405 break;
406 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
407 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
408 tlen += sizeof(*gen) + iph1->hash->l;
409 break;
410 }
411
412#ifdef HAVE_PRINT_ISAKMP_C
413 isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
414#endif
415
416 /* send the packet, add to the schedule to resend */
417 iph1->retry_counter = iph1->rmconf->retry_counter;
418 if (isakmp_ph1resend(iph1) == -1)
419 goto end;
420
421 /* the sending message is added to the received-list. */
422 if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
423 plog(LLV_ERROR , LOCATION, NULL,
424 "failed to add a response packet to the tree.\n");
425 goto end;
426 }
427
428 iph1->status = PHASE1ST_MSG2SENT;
429
430 error = 0;
431
432end:
433 if (vid)
434 vfree(vid);
435 return error;
436}
437
438/*
439 * receive from responder
440 * psk: HDR, KE, HASH_R
441 * sig: HDR, KE, [CERT,] SIG_R
442 * rsa: HDR, KE, HASH_R
443 * rev: HDR, <KE>_Ke_r, HASH_R
444 */
445int
446base_i3recv(iph1, msg)
447 struct ph1handle *iph1;
448 vchar_t *msg;
449{
450 vchar_t *pbuf = NULL;
451 struct isakmp_parse_t *pa;
452 int error = -1;
453
454 /* validity check */
455 if (iph1->status != PHASE1ST_MSG2SENT) {
456 plog(LLV_ERROR, LOCATION, NULL,
457 "status mismatched %d.\n", iph1->status);
458 goto end;
459 }
460
461 /* validate the type of next payload */
462 pbuf = isakmp_parse(msg);
463 if (pbuf == NULL)
464 goto end;
465
466 for (pa = (struct isakmp_parse_t *)pbuf->v;
467 pa->type != ISAKMP_NPTYPE_NONE;
468 pa++) {
469
470 switch (pa->type) {
471 case ISAKMP_NPTYPE_KE:
472 if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0)
473 goto end;
474 break;
475 case ISAKMP_NPTYPE_HASH:
476 iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
477 break;
478#ifdef HAVE_SIGNING_C
479 case ISAKMP_NPTYPE_CERT:
480 if (oakley_savecert(iph1, pa->ptr) < 0)
481 goto end;
482 break;
483 case ISAKMP_NPTYPE_SIG:
484 if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0)
485 goto end;
486 break;
487#endif
488 case ISAKMP_NPTYPE_VID:
489 (void)check_vendorid(pa->ptr);
490 break;
491 default:
492 /* don't send information, see ident_r1recv() */
493 plog(LLV_ERROR, LOCATION, iph1->remote,
494 "ignore the packet, "
495 "received unexpecting payload type %d.\n",
496 pa->type);
497 goto end;
498 }
499 }
500
501 /* payload existency check */
502 /* validate authentication value */
503 {
504 int type;
505 type = oakley_validate_auth(iph1);
506 if (type != 0) {
507 if (type == -1) {
508 /* message printed inner oakley_validate_auth() */
509 goto end;
510 }
511 isakmp_info_send_n1(iph1, type, NULL);
512 goto end;
513 }
514 }
515
516 /* compute sharing secret of DH */
517 if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub,
518 iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0)
519 goto end;
520
521 /* generate SKEYID to compute hash if signature mode */
522 if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_RSASIG
523 || iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_DSSSIG) {
524 if (oakley_skeyid(iph1) < 0)
525 goto end;
526 }
527
528 /* generate SKEYIDs & IV & final cipher key */
529 if (oakley_skeyid_dae(iph1) < 0)
530 goto end;
531 if (oakley_compute_enckey(iph1) < 0)
532 goto end;
533 if (oakley_newiv(iph1) < 0)
534 goto end;
535
536 /* see handler.h about IV synchronization. */
537 memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->iv->l);
538
539 /* set encryption flag */
540 iph1->flags |= ISAKMP_FLAG_E;
541
542 iph1->status = PHASE1ST_MSG3RECEIVED;
543
544 error = 0;
545
546end:
547 if (pbuf)
548 vfree(pbuf);
549
550 if (error) {
551 VPTRINIT(iph1->dhpub_p);
552 oakley_delcert(iph1->cert_p);
553 iph1->cert_p = NULL;
554 oakley_delcert(iph1->crl_p);
555 iph1->crl_p = NULL;
556 VPTRINIT(iph1->sig_p);
557 }
558
559 return error;
560}
561
562/*
563 * status update and establish isakmp sa.
564 */
565int
566base_i3send(iph1, msg)
567 struct ph1handle *iph1;
568 vchar_t *msg;
569{
570 int error = -1;
571
572 /* validity check */
573 if (iph1->status != PHASE1ST_MSG3RECEIVED) {
574 plog(LLV_ERROR, LOCATION, NULL,
575 "status mismatched %d.\n", iph1->status);
576 goto end;
577 }
578
579 iph1->status = PHASE1ST_ESTABLISHED;
580
581 error = 0;
582
583end:
584 return error;
585}
586
587/*
588 * receive from initiator
589 * psk: HDR, SA, Idii, Ni_b
590 * sig: HDR, SA, Idii, Ni_b
591 * rsa: HDR, SA, [HASH(1),] <IDii_b>Pubkey_r, <Ni_b>Pubkey_r
592 * rev: HDR, SA, [HASH(1),] <Ni_b>Pubkey_r, <IDii_b>Ke_i
593 */
594int
595base_r1recv(iph1, msg)
596 struct ph1handle *iph1;
597 vchar_t *msg;
598{
599 vchar_t *pbuf = NULL;
600 struct isakmp_parse_t *pa;
601 int error = -1;
602
603 /* validity check */
604 if (iph1->status != PHASE1ST_START) {
605 plog(LLV_ERROR, LOCATION, NULL,
606 "status mismatched %d.\n", iph1->status);
607 goto end;
608 }
609
610 /* validate the type of next payload */
611 /*
612 * NOTE: XXX even if multiple VID, we'll silently ignore those.
613 */
614 pbuf = isakmp_parse(msg);
615 if (pbuf == NULL)
616 goto end;
617 pa = (struct isakmp_parse_t *)pbuf->v;
618
619 /* check the position of SA payload */
620 if (pa->type != ISAKMP_NPTYPE_SA) {
621 plog(LLV_ERROR, LOCATION, iph1->remote,
622 "received invalid next payload type %d, "
623 "expecting %d.\n",
624 pa->type, ISAKMP_NPTYPE_SA);
625 goto end;
626 }
627 if (isakmp_p2ph(&iph1->sa, pa->ptr) < 0)
628 goto end;
629 pa++;
630
631 for (/*nothing*/;
632 pa->type != ISAKMP_NPTYPE_NONE;
633 pa++) {
634
635 switch (pa->type) {
636 case ISAKMP_NPTYPE_NONCE:
637 if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0)
638 goto end;
639 break;
640 case ISAKMP_NPTYPE_ID:
641 if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
642 goto end;
643 break;
644 case ISAKMP_NPTYPE_VID:
645 (void)check_vendorid(pa->ptr);
646 break;
647 default:
648 /* don't send information, see ident_r1recv() */
649 plog(LLV_ERROR, LOCATION, iph1->remote,
650 "ignore the packet, "
651 "received unexpecting payload type %d.\n",
652 pa->type);
653 goto end;
654 }
655 }
656
657 if (iph1->nonce_p == NULL || iph1->id_p == NULL) {
658 plog(LLV_ERROR, LOCATION, iph1->remote,
659 "few isakmp message received.\n");
660 goto end;
661 }
662
663 /* verify identifier */
664 if (ipsecdoi_checkid1(iph1) != 0) {
665 plog(LLV_ERROR, LOCATION, iph1->remote,
666 "invalid ID payload.\n");
667 goto end;
668 }
669
670 /* check SA payload and set approval SA for use */
671 if (ipsecdoi_checkph1proposal(iph1->sa, iph1) < 0) {
672 plog(LLV_ERROR, LOCATION, iph1->remote,
673 "failed to get valid proposal.\n");
674 /* XXX send information */
675 goto end;
676 }
677
678 iph1->status = PHASE1ST_MSG1RECEIVED;
679
680 error = 0;
681
682end:
683 if (pbuf)
684 vfree(pbuf);
685
686 if (error) {
687 VPTRINIT(iph1->sa);
688 VPTRINIT(iph1->nonce_p);
689 VPTRINIT(iph1->id_p);
690 }
691
692 return error;
693}
694
695/*
696 * send to initiator
697 * psk: HDR, SA, Idir, Nr_b
698 * sig: HDR, SA, Idir, Nr_b, [ CR ]
699 * rsa: HDR, SA, <IDir_b>PubKey_i, <Nr_b>PubKey_i
700 * rev: HDR, SA, <Nr_b>PubKey_i, <IDir_b>Ke_r
701 */
702int
703base_r1send(iph1, msg)
704 struct ph1handle *iph1;
705 vchar_t *msg;
706{
707 struct isakmp_gen *gen;
708 caddr_t p;
709 int tlen;
710 int error = -1;
711
712 /* validity check */
713 if (iph1->status != PHASE1ST_MSG1RECEIVED) {
714 plog(LLV_ERROR, LOCATION, NULL,
715 "status mismatched %d.\n", iph1->status);
716 goto end;
717 }
718
719 /* set responder's cookie */
720 isakmp_newcookie((caddr_t)&iph1->index.r_ck, iph1->remote, iph1->local);
721
722 /* make ID payload into isakmp status */
723 if (ipsecdoi_setid1(iph1) < 0)
724 goto end;
725
726 /* generate NONCE value */
727 iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
728 if (iph1->nonce == NULL)
729 goto end;
730
731 /* create buffer to send isakmp payload */
732 tlen = sizeof(struct isakmp)
733 + sizeof(*gen) + iph1->sa_ret->l
734 + sizeof(*gen) + iph1->id->l
735 + sizeof(*gen) + iph1->nonce->l;
736
737 iph1->sendbuf = vmalloc(tlen);
738 if (iph1->sendbuf == NULL) {
739 plog(LLV_ERROR, LOCATION, NULL,
740 "failed to get buffer to send.\n");
741 goto end;
742 }
743
744 /* set isakmp header */
745 p = set_isakmp_header(iph1->sendbuf, iph1, ISAKMP_NPTYPE_SA);
746 if (p == NULL)
747 goto end;
748
749 /* set SA payload to reply */
750 p = set_isakmp_payload(p, iph1->sa_ret, ISAKMP_NPTYPE_ID);
751
752 /* create isakmp ID payload */
753 p = set_isakmp_payload(p, iph1->id, ISAKMP_NPTYPE_NONCE);
754
755 /* create isakmp NONCE payload */
756 p = set_isakmp_payload(p, iph1->nonce, ISAKMP_NPTYPE_NONE);
757
758#ifdef HAVE_PRINT_ISAKMP_C
759 isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
760#endif
761
762 /* send the packet, add to the schedule to resend */
763 iph1->retry_counter = iph1->rmconf->retry_counter;
764 if (isakmp_ph1resend(iph1) == -1)
765 goto end;
766
767 /* the sending message is added to the received-list. */
768 if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
769 plog(LLV_ERROR , LOCATION, NULL,
770 "failed to add a response packet to the tree.\n");
771 goto end;
772 }
773
774 iph1->status = PHASE1ST_MSG1SENT;
775
776 error = 0;
777
778end:
779 if (iph1->sa_ret) {
780 vfree(iph1->sa_ret);
781 iph1->sa_ret = NULL;
782 }
783
784 return error;
785}
786
787/*
788 * receive from initiator
789 * psk: HDR, KE, HASH_I
790 * sig: HDR, KE, [ CR, ] [CERT,] SIG_I
791 * rsa: HDR, KE, HASH_I
792 * rev: HDR, <KE>Ke_i, HASH_I
793 */
794int
795base_r2recv(iph1, msg)
796 struct ph1handle *iph1;
797 vchar_t *msg;
798{
799 vchar_t *pbuf = NULL;
800 struct isakmp_parse_t *pa;
801 int error = -1;
802
803 /* validity check */
804 if (iph1->status != PHASE1ST_MSG1SENT) {
805 plog(LLV_ERROR, LOCATION, NULL,
806 "status mismatched %d.\n", iph1->status);
807 goto end;
808 }
809
810 /* validate the type of next payload */
811 pbuf = isakmp_parse(msg);
812 if (pbuf == NULL)
813 goto end;
814
815 iph1->pl_hash = NULL;
816
817 for (pa = (struct isakmp_parse_t *)pbuf->v;
818 pa->type != ISAKMP_NPTYPE_NONE;
819 pa++) {
820
821 switch (pa->type) {
822 case ISAKMP_NPTYPE_KE:
823 if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0)
824 goto end;
825 break;
826 case ISAKMP_NPTYPE_HASH:
827 iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
828 break;
829#ifdef HAVE_SIGNING_C
830 case ISAKMP_NPTYPE_CERT:
831 if (oakley_savecert(iph1, pa->ptr) < 0)
832 goto end;
833 break;
834 case ISAKMP_NPTYPE_SIG:
835 if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0)
836 goto end;
837 break;
838#endif
839 case ISAKMP_NPTYPE_VID:
840 (void)check_vendorid(pa->ptr);
841 break;
842 default:
843 /* don't send information, see ident_r1recv() */
844 plog(LLV_ERROR, LOCATION, iph1->remote,
845 "ignore the packet, "
846 "received unexpecting payload type %d.\n",
847 pa->type);
848 goto end;
849 }
850 }
851
852 /* generate DH public value */
853 if (oakley_dh_generate(iph1->approval->dhgrp,
854 &iph1->dhpub, &iph1->dhpriv) < 0)
855 goto end;
856
857 /* compute sharing secret of DH */
858 if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub,
859 iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0)
860 goto end;
861
862 /* generate SKEYID */
863 if (oakley_skeyid(iph1) < 0)
864 goto end;
865
866 /* payload existency check */
867 /* validate authentication value */
868 {
869 int type;
870 type = oakley_validate_auth(iph1);
871 if (type != 0) {
872 if (type == -1) {
873 /* message printed inner oakley_validate_auth() */
874 goto end;
875 }
876 isakmp_info_send_n1(iph1, type, NULL);
877 goto end;
878 }
879 }
880
881 iph1->status = PHASE1ST_MSG2RECEIVED;
882
883 error = 0;
884
885end:
886 if (pbuf)
887 vfree(pbuf);
888
889 if (error) {
890 VPTRINIT(iph1->dhpub_p);
891 oakley_delcert(iph1->cert_p);
892 iph1->cert_p = NULL;
893 oakley_delcert(iph1->crl_p);
894 iph1->crl_p = NULL;
895 VPTRINIT(iph1->sig_p);
896 }
897
898 return error;
899}
900
901/*
902 * send to initiator
903 * psk: HDR, KE, HASH_R
904 * sig: HDR, KE, [CERT,] SIG_R
905 * rsa: HDR, KE, HASH_R
906 * rev: HDR, <KE>_Ke_r, HASH_R
907 */
908int
909base_r2send(iph1, msg)
910 struct ph1handle *iph1;
911 vchar_t *msg;
912{
913 struct isakmp_gen *gen;
914 char *p;
915 vchar_t *vid = NULL;
916 int tlen;
917 int need_cert = 0;
918 int error = -1;
919
920 /* validity check */
921 if (iph1->status != PHASE1ST_MSG2RECEIVED) {
922 plog(LLV_ERROR, LOCATION, NULL,
923 "status mismatched %d.\n", iph1->status);
924 goto end;
925 }
926
927 /* generate HASH to send */
928 plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_I\n");
929 switch (iph1->approval->authmethod) {
930 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
931 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
932 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
933 iph1->hash = oakley_ph1hash_common(iph1, GENERATE);
934 break;
935 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
936 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
937 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
938 iph1->hash = oakley_ph1hash_base_r(iph1, GENERATE);
939 break;
940 default:
941 plog(LLV_ERROR, LOCATION, NULL,
942 "invalid authentication method %d\n",
943 iph1->approval->authmethod);
944 goto end;
945 }
946 if (iph1->hash == NULL)
947 goto end;
948
949 /* create HDR;KE;NONCE payload */
950 tlen = sizeof(struct isakmp);
951
952 switch (iph1->approval->authmethod) {
953 case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
954 tlen += sizeof(*gen) + iph1->dhpub->l
955 + sizeof(*gen) + iph1->hash->l;
956 if ((vid = set_vendorid(iph1->approval->vendorid)) != NULL)
957 tlen += sizeof(*gen) + vid->l;
958
959 iph1->sendbuf = vmalloc(tlen);
960 if (iph1->sendbuf == NULL) {
961 plog(LLV_ERROR, LOCATION, NULL,
962 "failed to get iph1->sendbuf to send.\n");
963 goto end;
964 }
965
966 /* set isakmp header */
967 p = set_isakmp_header(iph1->sendbuf, iph1, ISAKMP_NPTYPE_KE);
968 if (p == NULL)
969 goto end;
970
971 /* create isakmp KE payload */
972 p = set_isakmp_payload(p, iph1->dhpub, ISAKMP_NPTYPE_HASH);
973
974 /* create isakmp HASH payload */
975 p = set_isakmp_payload(p, iph1->hash,
976 vid ? ISAKMP_NPTYPE_VID : ISAKMP_NPTYPE_NONE);
977
978 /* append vendor id, if needed */
979 if (vid)
980 p = set_isakmp_payload(p, vid, ISAKMP_NPTYPE_NONE);
981 break;
982#ifdef HAVE_SIGNING_C
983 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
984 case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
985 /* XXX if there is CR or not ? */
986
987 if (oakley_getmycert(iph1) < 0)
988 goto end;
989
990 if (oakley_getsign(iph1) < 0)
991 goto end;
992
993 if (iph1->cert && iph1->rmconf->send_cert)
994 need_cert = 1;
995
996 tlen += sizeof(*gen) + iph1->dhpub->l
997 + sizeof(*gen) + iph1->sig->l;
998 if (need_cert)
999 tlen += sizeof(*gen) + iph1->cert->pl->l;
1000
1001 iph1->sendbuf = vmalloc(tlen);
1002 if (iph1->sendbuf == NULL) {
1003 plog(LLV_ERROR, LOCATION, NULL,
1004 "failed to get buffer to send.\n");
1005 goto end;
1006 }
1007
1008 /* set isakmp header */
1009 p = set_isakmp_header(iph1->sendbuf, iph1, ISAKMP_NPTYPE_KE);
1010 if (p == NULL)
1011 goto end;
1012
1013 /* create isakmp KE payload */
1014 p = set_isakmp_payload(p, iph1->dhpub, need_cert
1015 ? ISAKMP_NPTYPE_CERT
1016 : ISAKMP_NPTYPE_SIG);
1017
1018 /* add CERT payload if there */
1019 if (need_cert)
1020 p = set_isakmp_payload(p, iph1->cert->pl, ISAKMP_NPTYPE_SIG);
1021 /* add SIG payload */
1022 p = set_isakmp_payload(p, iph1->sig, ISAKMP_NPTYPE_NONE);
1023 break;
1024#endif
1025 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
1026 /* ... */
1027 break;
1028 case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
1029 case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
1030 tlen += sizeof(*gen) + iph1->hash->l;
1031 break;
1032 }
1033
1034#ifdef HAVE_PRINT_ISAKMP_C
1035 isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
1036#endif
1037
1038 /* send HDR;KE;NONCE to responder */
1039 if (isakmp_send(iph1, iph1->sendbuf) < 0)
1040 goto end;
1041
1042 /* the sending message is added to the received-list. */
1043 if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
1044 plog(LLV_ERROR , LOCATION, NULL,
1045 "failed to add a response packet to the tree.\n");
1046 goto end;
1047 }
1048
1049 /* generate SKEYIDs & IV & final cipher key */
1050 if (oakley_skeyid_dae(iph1) < 0)
1051 goto end;
1052 if (oakley_compute_enckey(iph1) < 0)
1053 goto end;
1054 if (oakley_newiv(iph1) < 0)
1055 goto end;
1056
1057 /* set encryption flag */
1058 iph1->flags |= ISAKMP_FLAG_E;
1059
1060 iph1->status = PHASE1ST_ESTABLISHED;
1061
1062 error = 0;
1063
1064end:
1065 if (vid)
1066 vfree(vid);
1067 return error;
1068}