6 * Implementation of the Server State Machine (SSM)
9 * Copyright (C) France Télécom R&D (DR&D/MAPS/NSS)
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "libradius.h"
45 #include "eap_psk_ssm.h"
54 /* PSK Packet Format in EAP
55 * --- ------ ------ -- ---
57 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
58 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 * | Code | Identifier | Length |
60 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-
66 int pskProcess(PSK_CONF *conf, PSK_SESSION *session, EAP_PACKET *recvPacket, EAP_PACKET *sentPacket){
69 if(conf==NULL || session==NULL)
71 radlog(L_ERR,"rlm_eap_psk: Cannot authenticate without EAP-PSK configuration and session information");
75 if(recvPacket && (recvPacket->code!=PW_EAP_RESPONSE || recvPacket->type.type!=EAPPSK_TYPE))
77 radlog(L_ERR,"pskProcess: EAP-PSK Response expected");
81 switch(session->state)
83 case INIT: return pskInit(conf,session,sentPacket);
85 if(recvPacket) return pskRandSent(conf,session, recvPacket,sentPacket);
87 if(recvPacket) return pskPChannel(conf,session,recvPacket,sentPacket);
89 radlog(L_ERR,"pskProcess: Impossible to process the EAP-PSK authentication");
96 int pskInit(PSK_CONF *conf, PSK_SESSION *session, EAP_PACKET *sentPacket){
101 session->pChannelReplayCounter=0;
102 session->authStatus=PSK_STATUS_CONT;
103 session->isSupportedExt=1;
106 sentPacket->code=PW_EAP_REQUEST;
107 sentPacket->length=PSK_RANDOM_NUMBER_SIZE+EAP_HEADER_SIZE;
108 sentPacket->type.type=EAPPSK_TYPE;
109 sentPacket->type.length=PSK_RANDOM_NUMBER_SIZE;
110 sentPacket->type.data=NULL;
111 sentPacket->type.data=(unsigned char*)malloc(PSK_RANDOM_NUMBER_SIZE);
113 if(sentPacket->type.data==NULL)
115 radlog(L_ERR,"pskInit: Out of memory");
119 // generate a 128-bit random value and put this value in session->rand_s
120 if(!pskGetRandomBytes(sentPacket->type.data,PSK_RANDOM_NUMBER_SIZE)) {
121 radlog(L_ERR,"pskInit: problem during random number generation");
125 pskConvertHex((char *)sentPacket->type.data, (char *)hexstr,PSK_RANDOM_NUMBER_SIZE);
126 DEBUG2("pskInit: random number RA :");
127 DEBUG2((char *)hexstr);
129 // save this value in session information
130 memcpy(session->rand_s,sentPacket->type.data,PSK_RANDOM_NUMBER_SIZE);
132 session->state=RANDSENT;
139 int pskRandSent(PSK_CONF *conf, PSK_SESSION *session, EAP_PACKET *recvPacket, EAP_PACKET *sentPacket){
141 /* the received packet is shown below
144 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
145 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
146 * | Code=2 | Identifier | Length |
147 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
149 * +-+-+-+-+-+-+-+-+ +
155 * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
157 * +-+-+-+-+-+-+-+-+ +
163 * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
165 * +-+-+-+-+-+-+-+-+ :
168 * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
170 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
174 psk_message_2 *psk_msg_2;
175 psk_message_3 *psk_msg_3;
179 unsigned char buffer[PSK_MAC_SIZE];
182 unsigned char buftmp[PSK_AK_SIZE+PSK_KDK_SIZE];
185 userinfo_t* uinfo = NULL;
191 unsigned char privateKey[PSK_SIZE];
193 // for the mac calculation
197 // for the key derivation
199 unsigned char *block;
201 unsigned char counterValues[]={
202 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
203 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,
204 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
205 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,
206 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,
207 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,
208 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
209 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,
210 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09};
214 unsigned char nn[PSK_RANDOM_NUMBER_SIZE];
215 unsigned char eapHeader[EAP_HEADER_SIZE];
220 if(recvPacket->length<(EAP_HEADER_SIZE+PSK_RANDOM_NUMBER_SIZE+PSK_MAC_SIZE+1))
222 // the packet is malformed
223 DEBUG2("pskPChannel: the packet is malformed: the authentication must fail");
224 sentPacket->code=PW_EAP_FAILURE;
229 // retrieve the identity of the peer, ID_P
230 identitySize=recvPacket->length-(EAP_HEADER_SIZE+PSK_RANDOM_NUMBER_SIZE+PSK_MAC_SIZE);
231 session->id_p=(unsigned char *)malloc(identitySize+1);
232 if(session->id_p==NULL)
234 radlog(L_ERR,"pskRandSent: Out of memory");
237 psk_msg_2=(psk_message_2*)recvPacket->type.data;
238 memcpy(session->id_p,&(psk_msg_2->id_p),identitySize);
239 session->id_p[identitySize]='\0';
241 // search the peer identity in the user file whose path is conf->usersFilePath
243 uinfo = pskGetUserInfo((char*)conf->usersFilePath, (char*)session->id_p);
247 DEBUG2("pskRandSent: identity successfully checked");
248 DEBUG2("pskRandSent: saving peer information");
251 memcpy(session->ak,uinfo->AK,PSK_AK_SIZE);
252 memcpy(session->kdk,uinfo->KDK,PSK_KDK_SIZE);
254 DEBUG2("pskRandSent: found user %s in %s",session->id_p, conf->usersFilePath);
260 // the peer identity wasn't found
261 DEBUG2("pskRandSent: the peer identity isn't valid");
262 DEBUG2("pskRandSent: the authentication must fail");
263 sentPacket->code=PW_EAP_FAILURE;
268 // calculate the following MAC: MAC(session->ak, ID_P || conf->id_s || session->rand_s || RAND_P)
270 // making the formula
271 data=(unsigned char *)malloc(strlen((char*)session->id_p)+strlen((char*)conf->id_s)+2*PSK_RANDOM_NUMBER_SIZE);
273 radlog(L_ERR,"pskRandSent: out of memory");
277 memcpy(ptr,session->id_p,strlen((char*)session->id_p));
278 ptr+=strlen((char*)session->id_p);
279 memcpy(ptr,conf->id_s,strlen((char*)conf->id_s));
280 ptr+=strlen((char*)conf->id_s);
281 memcpy(ptr,session->rand_s,PSK_RANDOM_NUMBER_SIZE);
282 ptr+=PSK_RANDOM_NUMBER_SIZE;
283 memcpy(ptr,psk_msg_2->rand_p,PSK_RANDOM_NUMBER_SIZE);
285 pskConvertHex((char *)data, (char *)hexstr,strlen((char*)session->id_p)+strlen((char*)conf->id_s)+2*PSK_RANDOM_NUMBER_SIZE);
286 DEBUG2("pskRandSent: [B||A||RA||RB] :");
287 DEBUG2((char *)hexstr);
289 pskConvertHex((char *)(session->ak), (char *)hexstr,PSK_AK_SIZE);
290 DEBUG2("pskRandSent: AK :");
291 DEBUG2((char *)hexstr);
296 c.makeKey(session->ak,PSK_AK_SIZE,DIR_ENCRYPT);
298 om.update(data,strlen((char*)session->id_p)+strlen((char*)conf->id_s)+2*PSK_RANDOM_NUMBER_SIZE);
302 pskConvertHex((char *)buffer, (char *)hexstr,PSK_MAC_SIZE);
303 DEBUG2("pskRandSent: MAC of [B||A||RA||RB] :");
304 DEBUG2((char *)hexstr);
307 if(memcmp(buffer,psk_msg_2->mac_p,PSK_MAC_SIZE))
309 // the received MAC attribute is not correct
310 DEBUG2("pskRandSent: the received MAC attribute isn't correct");
311 DEBUG2("pskRandSent: the authentication must fail");
312 sentPacket->code=PW_EAP_FAILURE;
318 DEBUG2("pskRandSent: the received MAC attribute is correct");
322 // initialize the sobmmo
323 sob.initialize(session->kdk,&c,psk_msg_2->rand_p,9,counterValues);
326 block=sob.getOutputBlock(1);
327 memcpy(session->tek,block,PSK_TEK_SIZE);
330 pskConvertHex((char *)session->tek, (char *)hexstr, PSK_TEK_SIZE);
331 DEBUG2("pskRandSent: TEK :");
332 DEBUG2((char *)hexstr);
337 block=sob.getOutputBlock(i+2);
338 memcpy(&session->msk[i*16],block,16);
342 pskConvertHex((char *)session->msk, (char *)hexstr, PSK_MSK_SIZE);
343 DEBUG2("pskRandSent: MSK :");
344 DEBUG2((char *)hexstr);
349 block=sob.getOutputBlock(i+6);
350 memcpy(&session->emsk[i*16],block,16);
354 pskConvertHex((char *)session->emsk, (char *)hexstr, PSK_EMSK_SIZE);
355 DEBUG2("pskRandSent: EMSK :");
356 DEBUG2((char *)hexstr);
359 // obtain the mac of [A||RB]
360 data=(unsigned char *)malloc(strlen((char*)conf->id_s)+PSK_RANDOM_NUMBER_SIZE);
362 radlog(L_ERR,"pskRandSent: out of memory");
365 memcpy(data,conf->id_s,strlen((char*)conf->id_s));
366 memcpy(data+strlen((char*)conf->id_s),psk_msg_2->rand_p,PSK_RANDOM_NUMBER_SIZE);
368 pskConvertHex((char *)data, (char *)hexstr,strlen((char*)conf->id_s)+PSK_RANDOM_NUMBER_SIZE);
369 DEBUG2("pskRandSent: [A||RB] :");
370 DEBUG2((char *)hexstr);
372 c.makeKey(session->ak,PSK_AK_SIZE,DIR_ENCRYPT);
374 om.update(data,strlen((char*)conf->id_s)+PSK_RANDOM_NUMBER_SIZE);
378 pskConvertHex((char *)&buffer, (char *)hexstr,16);
379 DEBUG2("pskRandSent: MAC of [A||RB] :");
380 DEBUG2((char *)hexstr);
383 if(session->extType==0)
385 // standard authentication
387 sentPacket->code=PW_EAP_REQUEST;
388 sentPacket->length=EAP_HEADER_SIZE+2*PSK_MAC_SIZE+PSK_PCHANNEL_REPLAY_COUNTER_SIZE+1;
389 sentPacket->type.type=EAPPSK_TYPE;
390 sentPacket->type.length=2*PSK_MAC_SIZE+PSK_PCHANNEL_REPLAY_COUNTER_SIZE+1;
391 sentPacket->type.data=NULL;
392 sentPacket->type.data=(unsigned char*)malloc(2*PSK_MAC_SIZE+PSK_PCHANNEL_REPLAY_COUNTER_SIZE+1);
394 if(sentPacket->type.data==NULL)
396 radlog(L_ERR,"pskRandSent: Out of memory");
400 psk_msg_3=(psk_message_3*)sentPacket->type.data;
402 // add to sentPacket the following MAC: MAC(session->AK, conf->id_s || RAND_P)
403 memcpy(psk_msg_3->mac_s,buffer,PSK_MAC_SIZE);
405 // add to sentPacket the following information:
406 // R = DONE_SUCCESS (the R flag is equal to session->authStatus)
408 psk_msg_3->nonce=htonl(session->pChannelReplayCounter);
410 // calculate the EAP header
411 eapHeader[0]=sentPacket->code;
412 eapHeader[1]=(recvPacket->id)+1; // we suppose that the identifier is incremented by 1
414 sentPacket->length=htons(sentPacket->length);
415 memcpy(&(eapHeader[2]),&(sentPacket->length),2);
416 sentPacket->length=ntohs(sentPacket->length);
418 eapHeader[4]=sentPacket->type.type;
420 pskConvertHex((char *)eapHeader, (char *)hexstr,EAP_HEADER_SIZE);
421 DEBUG2("pskRandSent: eapHeader :");
422 DEBUG2((char *)hexstr);
424 // the replay counter is the least significant bytes of the nonce !
425 memset(nn,0,PSK_RANDOM_NUMBER_SIZE);
426 memcpy(&nn[PSK_RANDOM_NUMBER_SIZE-PSK_PCHANNEL_REPLAY_COUNTER_SIZE],&(psk_msg_3->nonce),PSK_PCHANNEL_REPLAY_COUNTER_SIZE);
428 pskConvertHex((char *)nn, (char *)hexstr,PSK_RANDOM_NUMBER_SIZE);
429 DEBUG2("pskRandSent: nn :");
430 DEBUG2((char *)hexstr);
432 session->authStatus=PSK_STATUS_DONE_SUCCESS;
436 eax.initialize(session->tek, PSK_TEK_SIZE, AES_BLOCKSIZE, &c);
438 eax.provideNonce((byte*)nn,PSK_RANDOM_NUMBER_SIZE);
439 eax.provideHeader((byte*)eapHeader,EAP_HEADER_SIZE);
440 eax.computeCiphertext((byte*)&(session->authStatus),sizeof(session->authStatus),(byte*)&(psk_msg_3->flags));
441 eax.computeTag((byte*)psk_msg_3->tag);
443 // !!! BE CAREFUL !!!
444 // the authorization isn't taken into account in this implementation
445 // that's why R=DONE_SUCCESS
448 // extended authentication
451 // !!!!! NOT IMPLEMENTED !!!!!!
456 // call the extension which must update the session->authStatus, i.e. the result of the EAP-PSK authentication
457 // see the pskExtension function declaration for more details
458 void *payloadOut=NULL;
459 int sizePayloadOut=0;
461 resul=pskExtension(conf,session,PSK_STATUS_CONT,NULL,0,&payloadOut,&sizePayloadOut);
463 if(!resul || (sizePayloadOut<1) || (sizePayloadOut>EXT_PAYLOAD_MAX_LEN))
465 //the extension has failed
466 // the authentication must fail
467 // the sentPacket must be a EAP_Failure packet
471 // add to sentPacket the following information:
472 // R = CONT or DONE_FAILURE or DONE_SUCCESS thanks to session->authStatus
474 // EXT_Type=session->extType
475 // EXT_payload=payloadOut
481 session->pChannelReplayCounter++;
483 session->state=PCHANNEL;
492 int pskPChannel(PSK_CONF *conf, PSK_SESSION *session, EAP_PACKET *recvPacket, EAP_PACKET *sentPacket){
494 /* the received packet is shown below
497 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
498 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
499 * | Code=2 | Identifier | Length |
500 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
501 * | Type EAP-PSK | Nonce... :
502 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
504 * +-+-+-+-+-+-+-+-+ +
510 * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
511 * | | R |E| Reserved|EXT_Type (opt)| |
512 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++ +
514 * : EXT_Payload (optional) :
515 * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
517 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
519 * EXT_Type and EXT_Payload must be in the EAP packet when E is set to 1
520 * EXT_Payload could be null
524 psk_message_4 *psk_msg_4;
527 unsigned char eapHeader[EAP_HEADER_SIZE];
528 unsigned char nn[PSK_RANDOM_NUMBER_SIZE];
534 if(recvPacket->length<(EAP_HEADER_SIZE+PSK_PCHANNEL_REPLAY_COUNTER_SIZE+PSK_MAC_SIZE+1))
536 // the packet is malformed
537 // the session->nbRetry isn't incremented
538 // sentPacket must be the previous request sent by the server ###### PB TIMER ########
540 DEBUG2("pskPChannel: receiving a invalid EAP-PSK packet: the packet is malformed");
541 DEBUG2("pskPChannel: the authentication must fail");
542 sentPacket->code=PW_EAP_FAILURE;
548 psk_msg_4=(psk_message_4*)recvPacket->type.data;
551 if(ntohl(psk_msg_4->nonce)!=session->pChannelReplayCounter)
553 // the received packet isn't awaited
554 // the session->nbRetry isn't incremented
555 // sentPacket must be the previous request sent by the server
557 DEBUG2("pskPChannel: receiving a invalid EAP-PSK packet: the replay counter isn't valid");
558 DEBUG2("pskPChannel: the authentication must fail");
559 sentPacket->code=PW_EAP_FAILURE;
564 // decrypt the received packet with the EAX mode and check the EAP header
566 // calculate the EAP header
567 eapHeader[0]=recvPacket->code;
568 eapHeader[1]=recvPacket->id;
570 recvPacket->length=htons(recvPacket->length);
571 memcpy(&(eapHeader[2]),&(recvPacket->length),2);
572 recvPacket->length=ntohs(recvPacket->length);
574 eapHeader[4]=recvPacket->type.type;
576 // the replay counter is the least significant bytes of the nonce !
577 memset(nn,0,PSK_RANDOM_NUMBER_SIZE);
578 memcpy(&nn[PSK_RANDOM_NUMBER_SIZE-PSK_PCHANNEL_REPLAY_COUNTER_SIZE],&(psk_msg_4->nonce),PSK_PCHANNEL_REPLAY_COUNTER_SIZE);
582 eax.initialize(session->tek, PSK_TEK_SIZE, AES_BLOCKSIZE, &c);
584 eax.provideNonce((byte*)nn,PSK_RANDOM_NUMBER_SIZE);
585 eax.provideHeader((byte*)eapHeader,EAP_HEADER_SIZE);
586 eax.provideCiphertext((byte*)&(psk_msg_4->flags),sizeof(psk_msg_4->flags));
587 st=eax.checkTag((byte*)psk_msg_4->tag);
590 // the decryption ends by a failure
592 DEBUG2("pskPChannel: receiving a invalid EAP-PSK packet: the decryption fails");
593 DEBUG2("pskPChannel: the authentication must fail");
594 sentPacket->code=PW_EAP_FAILURE;
600 eax.computePlaintext((byte*)&(psk_msg_4->flags),sizeof(psk_msg_4->flags),(byte*)&flags);
602 if((((flags & PSK_IS_EXT)==PSK_IS_EXT) && recvPacket->length<(EAP_HEADER_SIZE+PSK_PCHANNEL_REPLAY_COUNTER_SIZE+PSK_MAC_SIZE+2)) || (((flags & PSK_IS_EXT)==0) && recvPacket->length!=(EAP_HEADER_SIZE+PSK_PCHANNEL_REPLAY_COUNTER_SIZE+PSK_MAC_SIZE+1)))
604 // the packet is malformed
605 // the authentication must fail
606 // the sentPacket must be a EAP_Failure packet
608 DEBUG2("pskPChannel: the packet is malformed: the authentication must fail");
609 sentPacket->code=PW_EAP_FAILURE;
615 if(session->extType==0 && ((flags & PSK_IS_EXT)==PSK_IS_EXT))
617 // error: standard authentication awaited
618 // the authentication must fail
619 // the sentPacket must be a EAP_Failure packet
621 DEBUG2("pskPChannel: the packet is malformed: the authentication must fail");
622 sentPacket->code=PW_EAP_FAILURE;
627 if(session->extType!=0 && ((flags & PSK_IS_EXT)==0))
629 // error: extended authentication awaited
630 // the authentication must fail
631 // the sentPacket must be a EAP_Failure packet
633 DEBUG2("pskPChannel: the packet is malformed: the authentication must fail");
634 sentPacket->code=PW_EAP_FAILURE;
639 if((flags & PSK_IS_EXT)==0)
641 // standard authentication
643 if(((flags & PSK_STATUS_DONE_SUCCESS)==PSK_STATUS_DONE_SUCCESS) && session->authStatus==PSK_STATUS_DONE_SUCCESS)
645 // sentPacket must be an EAP_Success packet
646 // indicate to the lower layer that the MSK and the EMSK are ready
647 // the EAP-PSK authentication will end after sending sentPacket
649 sentPacket->code=PW_EAP_SUCCESS;
652 // sentPacket must be an EAP_Failure packet
653 // the EAP-PSK authentication will end after sending sentPacket
655 sentPacket->code=PW_EAP_FAILURE;
660 // extended authentication
663 // !!!!! NOT IMPLEMENTED !!!!!
668 if(session->isSupportedExt)
671 if(recvPacket->data.EXT_Payload)
674 // call the extension which must update the session->authStatus, i.e. the result of the EAP-PSK authentication
675 // see the pskExtension function declaration for more details
676 void *payloadOut=NULL;
677 int sizePayloadOut=0;
678 int sizePayloadIn=recvPacket->length-27; // (27=5+16+4+1+1)
680 resul=pskExtension(conf,session,recvPacket->data.R,recvPacket->data.EXT_Payload,sizePayloadIn,&payloadOut,&sizePayloadOut);
682 if(!resul || (sizePayloadOut<1) || (sizePayloadOut>EXT_PAYLOAD_MAX_LEN))
684 //the extension has failed
685 // the authentication must fail
686 // the sentPacket must be a EAP_Failure packet
690 if(recvPacket->data.R != CONT) {
691 // sentPacket must be an EAP_Success packet or an EAP_Failure packet thanks to the server policy and the received R flag
692 // indicate to the lower layer that the MSK and the EMSK are ready in case an EAP_Success packet must be sent
693 // the EAP-PSK authentication will end after sending sentPacket
697 // add to sentPacket the following information:
698 // R = CONT or DONE_FAILURE or DONE_SUCCESS thanks to session->authStatus
700 // EXT_Type=session->extType
701 // EXT_payload=payloadOut
704 // the peer doesn't support the specified extension
706 session->isSupportedExt=0;
708 if(recvPacket->data.R != CONT) {
709 // sentPacket must be an EAP_Success packet or an EAP_Failure packet thanks to the server policy and the received R flag
710 // indicate to the lower layer that the MSK and the EMSK are ready in case of an EAP_Success packet must be sent
711 // the EAP-PSK authentication will end after sending sentPacket
715 // add to sentPacket the following information:
716 // R = DONE_FAILURE or DONE_SUCCESS thanks to the server policy
718 // EXT_Type=session->extType
723 if(recvPacket->data.R != CONT && recvPacket->data.EXT_Payload==NULL) {
724 // sentPacket must be an EAP_Success packet or an EAP_Failure packet thanks to the server policy and the received R flag
725 // indicate to the lower layer that the MSK and the EMSK are ready in case of an EAP_Success packet must be sent
726 // the EAP-PSK authentication will end after sending sentPacket
730 // the packet is malformed
731 // the authentication must fail
732 // the sentPacket must be a EAP_Failure packet
739 session->pChannelReplayCounter++;
740 // use the EAX mode to encrypt the EXT_Payload and protect the EAP header
742 // !!!! NOT IMPLEMENTED !!!!
743 // only standard authentication supported
745 session->pChannelReplayCounter++;
749 // stay in this state
756 int pskExtension(PSK_CONF *conf, PSK_SESSION *session, unsigned short receivedStatus, void *dataIn, int sizeDataIn, void **dataOut, int *sizeDataOut){
758 // this functionality makes it possible to do authorization, account refilling...
760 // this function must update the session->authStatus variable thanks to its policy, the received R flag, i.e. the receivedStatus variable, and the received data
762 // !!! Be careful !!!
763 // dataOut mustn't be NULL
765 // !!!! NOT IMPLEMENTED !!!!
773 *@memo this function frees the session data
774 *@param opaque, pointer to a structure which contains information session
776 void pskFreeSession(void *opaque){
777 PSK_SESSION *session;
779 DEBUG2("pskFreeSession:");
783 session=(PSK_SESSION *)opaque;
794 DEBUG2("pskFreeSession: finished");