update otp_hotp() to support 6,7,8,9 digit otp's
[freeradius.git] / src / modules / rlm_eap / types / rlm_eap_psk / eap_psk_ssm.cpp
1 /* $Id$ */
2
3 /*
4  * eap_psk_ssm.cpp
5  *
6  * Implementation of the Server State Machine (SSM)
7  *
8  * 
9  * Copyright (C) France Télécom R&D (DR&D/MAPS/NSS)
10  *
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.
15  *
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.
20  * 
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
24  *
25  */
26
27
28
29 #include "autoconf.h"
30 #include "libradius.h"
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36
37 #include "radiusd.h"
38 #include "modpriv.h"
39 #include "modules.h"
40 #include "modcall.h"
41 #include "conffile.h"
42 #include "ltdl.h"
43
44
45 #include "eap_psk_ssm.h"
46 #include "AES.h"
47 #include "OMAC.h"
48 #include "EAX.h"
49 #include "SOBMMO.h"
50
51 #include "userinfo.h"
52
53
54 /*  PSK Packet Format in EAP 
55  *  --- ------ ------ -- ---
56  * 0                   1                   2                   3
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  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61  * |     Type      |   Data 
62  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-
63  */
64
65
66 int pskProcess(PSK_CONF *conf, PSK_SESSION *session, EAP_PACKET *recvPacket, EAP_PACKET *sentPacket){
67
68   // error cases
69   if(conf==NULL || session==NULL)
70     {
71       radlog(L_ERR,"rlm_eap_psk: Cannot authenticate without EAP-PSK configuration and session information");
72       return 0;
73     }
74   
75   if(recvPacket && (recvPacket->code!=PW_EAP_RESPONSE || recvPacket->type.type!=EAPPSK_TYPE))
76     {
77       radlog(L_ERR,"pskProcess: EAP-PSK Response expected");
78       return 0;
79     }  
80
81   switch(session->state)
82     {
83     case INIT: return pskInit(conf,session,sentPacket);
84     case RANDSENT:
85                 if(recvPacket) return pskRandSent(conf,session, recvPacket,sentPacket);
86     case PCHANNEL: 
87                 if(recvPacket) return pskPChannel(conf,session,recvPacket,sentPacket);
88     default:
89       radlog(L_ERR,"pskProcess: Impossible to process the EAP-PSK authentication");
90       return 0;
91     }
92
93 }
94
95
96 int pskInit(PSK_CONF *conf, PSK_SESSION *session, EAP_PACKET *sentPacket){
97
98   char hexstr[1024];
99   
100   session->nbRetry=0;
101   session->pChannelReplayCounter=0;
102   session->authStatus=PSK_STATUS_CONT;
103   session->isSupportedExt=1;
104   session->extType=0;
105   
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);
112   
113   if(sentPacket->type.data==NULL)
114     {
115       radlog(L_ERR,"pskInit: Out of memory");
116       return 0;
117     }
118   
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");
122     return 0;
123   }
124   
125   pskConvertHex((char *)sentPacket->type.data, (char *)hexstr,PSK_RANDOM_NUMBER_SIZE);
126   DEBUG2("pskInit: random number RA :");
127   DEBUG2((char *)hexstr);
128   
129   // save this value in session information
130   memcpy(session->rand_s,sentPacket->type.data,PSK_RANDOM_NUMBER_SIZE);
131   
132   session->state=RANDSENT;
133  
134   return 1;
135   
136 }
137
138
139 int pskRandSent(PSK_CONF *conf, PSK_SESSION *session, EAP_PACKET *recvPacket, EAP_PACKET *sentPacket){
140   
141   /* the received packet is shown below
142    * 
143    * 0                   1                   2                   3
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    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
148    * |  Type EAP-PSK |                                               |
149    * +-+-+-+-+-+-+-+-+                                               +
150    * |                                                               |
151    * +                                                               +
152    * |                             RAND_P                            |
153    * +                                                               +
154    * |                                                               |
155    * +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
156    * |               |                                               |
157    * +-+-+-+-+-+-+-+-+                                               +
158    * |                                                               |
159    * +                                                               +
160    * |                             MAC_P                             |
161    * +                                                               +
162    * |                                                               |
163    * +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
164    * |               |                                               |
165    * +-+-+-+-+-+-+-+-+                                               :
166    * :                              ID_P                             :
167    * :                                                               :
168    * +                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
169    * |                               |
170    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
171    */
172
173
174   psk_message_2 *psk_msg_2;
175   psk_message_3 *psk_msg_3;
176   int identitySize;
177   char hexstr[1024];
178  
179   unsigned char buffer[PSK_MAC_SIZE];
180   unsigned char *data;
181   unsigned char *ptr;
182   unsigned char buftmp[PSK_AK_SIZE+PSK_KDK_SIZE];
183   
184   //user profile
185   userinfo_t*    uinfo = NULL;
186   
187   char **psk_vals;
188   char *psk_val;
189   int i=0;
190   char **atts;
191   unsigned char privateKey[PSK_SIZE];
192
193   // for the mac calculation
194   OMAC om;
195   AES c;
196   
197   // for the key derivation
198   SOBMMO sob;
199   unsigned char *block;
200   // counter values
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};
211   
212
213   // for the pchannel
214   unsigned char nn[PSK_RANDOM_NUMBER_SIZE];
215   unsigned char eapHeader[EAP_HEADER_SIZE];
216   EAX eax;
217
218
219
220   if(recvPacket->length<(EAP_HEADER_SIZE+PSK_RANDOM_NUMBER_SIZE+PSK_MAC_SIZE+1))
221     {
222       // the packet is malformed
223       DEBUG2("pskPChannel: the packet is malformed: the authentication must fail");
224       sentPacket->code=PW_EAP_FAILURE;
225       
226       return 1;
227     }
228   
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)
233     {
234       radlog(L_ERR,"pskRandSent: Out of memory");
235       return 0;
236     }
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'; 
240
241   // search the peer identity in the user file whose path is conf->usersFilePath
242   
243   uinfo = pskGetUserInfo((char*)conf->usersFilePath, (char*)session->id_p);
244   if (uinfo)
245     {
246       
247       DEBUG2("pskRandSent: identity successfully checked");
248       DEBUG2("pskRandSent: saving peer information");
249       
250       // save keys                                                    
251       memcpy(session->ak,uinfo->AK,PSK_AK_SIZE);
252       memcpy(session->kdk,uinfo->KDK,PSK_KDK_SIZE);
253       
254       DEBUG2("pskRandSent: found user %s in %s",session->id_p, conf->usersFilePath);
255       
256       free(uinfo);
257       
258     } else {
259       
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;
264       
265       return 1;  
266     }
267   
268   // calculate the following MAC: MAC(session->ak, ID_P || conf->id_s || session->rand_s || RAND_P)
269   
270   // making the formula
271   data=(unsigned char *)malloc(strlen((char*)session->id_p)+strlen((char*)conf->id_s)+2*PSK_RANDOM_NUMBER_SIZE);
272   if(data==NULL) {
273     radlog(L_ERR,"pskRandSent: out of memory");
274     return 0;
275   }
276   ptr=data;
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);
284   
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);
288   
289   pskConvertHex((char *)(session->ak), (char *)hexstr,PSK_AK_SIZE);
290   DEBUG2("pskRandSent: AK :");
291   DEBUG2((char *)hexstr);
292
293
294   // obtain the mac
295
296   c.makeKey(session->ak,PSK_AK_SIZE,DIR_ENCRYPT);
297   om.init(&c);
298   om.update(data,strlen((char*)session->id_p)+strlen((char*)conf->id_s)+2*PSK_RANDOM_NUMBER_SIZE);
299   om.final(buffer);
300   free(data);
301   
302   pskConvertHex((char *)buffer, (char *)hexstr,PSK_MAC_SIZE);
303   DEBUG2("pskRandSent: MAC of [B||A||RA||RB] :");
304   DEBUG2((char *)hexstr);
305   
306
307   if(memcmp(buffer,psk_msg_2->mac_p,PSK_MAC_SIZE))
308     {
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;
313       
314       return 1;
315     }
316
317   
318   DEBUG2("pskRandSent: the received MAC attribute is correct");
319   
320   // KEY DERIVATION
321   
322   // initialize the sobmmo
323   sob.initialize(session->kdk,&c,psk_msg_2->rand_p,9,counterValues);
324   
325   // get the TEK
326   block=sob.getOutputBlock(1);
327   memcpy(session->tek,block,PSK_TEK_SIZE);
328   free(block);
329   
330   pskConvertHex((char *)session->tek, (char *)hexstr, PSK_TEK_SIZE);
331   DEBUG2("pskRandSent: TEK :");
332   DEBUG2((char *)hexstr);
333   
334   // get the MSK
335   for(int i=0;i<4;i++)
336     {
337       block=sob.getOutputBlock(i+2);
338       memcpy(&session->msk[i*16],block,16);
339       free(block);
340     }
341                                
342   pskConvertHex((char *)session->msk, (char *)hexstr, PSK_MSK_SIZE);
343   DEBUG2("pskRandSent: MSK :");
344   DEBUG2((char *)hexstr);
345   
346   // get the EMSK
347   for(int i=0;i<4;i++)
348     {
349       block=sob.getOutputBlock(i+6);
350       memcpy(&session->emsk[i*16],block,16);
351       free(block);
352     }
353   
354   pskConvertHex((char *)session->emsk, (char *)hexstr, PSK_EMSK_SIZE);
355   DEBUG2("pskRandSent: EMSK :");
356   DEBUG2((char *)hexstr);
357                                
358                                
359   // obtain the mac of [A||RB]
360   data=(unsigned char *)malloc(strlen((char*)conf->id_s)+PSK_RANDOM_NUMBER_SIZE);
361   if(data==NULL) {
362     radlog(L_ERR,"pskRandSent: out of memory");
363     return 0;
364   }
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);
367   
368   pskConvertHex((char *)data, (char *)hexstr,strlen((char*)conf->id_s)+PSK_RANDOM_NUMBER_SIZE);
369   DEBUG2("pskRandSent: [A||RB] :");
370   DEBUG2((char *)hexstr);
371   
372   c.makeKey(session->ak,PSK_AK_SIZE,DIR_ENCRYPT);
373   om.init(&c);
374   om.update(data,strlen((char*)conf->id_s)+PSK_RANDOM_NUMBER_SIZE);
375   om.final(buffer);
376   free(data);
377   
378   pskConvertHex((char *)&buffer, (char *)hexstr,16);
379   DEBUG2("pskRandSent: MAC of [A||RB] :");
380   DEBUG2((char *)hexstr);
381   
382
383   if(session->extType==0)
384     {
385       // standard authentication
386       
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);
393       
394       if(sentPacket->type.data==NULL)
395         {
396           radlog(L_ERR,"pskRandSent: Out of memory");
397           return 0;
398         }
399
400       psk_msg_3=(psk_message_3*)sentPacket->type.data;
401
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);
404
405       // add to sentPacket the following information: 
406       // R = DONE_SUCCESS (the R flag is equal to session->authStatus)
407       // E=0
408       psk_msg_3->nonce=htonl(session->pChannelReplayCounter);
409       
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
413
414       sentPacket->length=htons(sentPacket->length);
415       memcpy(&(eapHeader[2]),&(sentPacket->length),2);
416       sentPacket->length=ntohs(sentPacket->length);
417
418       eapHeader[4]=sentPacket->type.type;
419
420       pskConvertHex((char *)eapHeader, (char *)hexstr,EAP_HEADER_SIZE);
421       DEBUG2("pskRandSent: eapHeader :");
422       DEBUG2((char *)hexstr);
423       
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);
427
428       pskConvertHex((char *)nn, (char *)hexstr,PSK_RANDOM_NUMBER_SIZE);
429       DEBUG2("pskRandSent: nn :");
430       DEBUG2((char *)hexstr);
431
432       session->authStatus=PSK_STATUS_DONE_SUCCESS;
433
434       // EAX encryption
435       
436       eax.initialize(session->tek, PSK_TEK_SIZE, AES_BLOCKSIZE, &c);
437
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);
442        
443       // !!! BE CAREFUL !!! 
444       // the authorization isn't taken into account in this implementation
445       // that's why R=DONE_SUCCESS
446       
447     } else {
448       // extended authentication
449       
450
451       // !!!!! NOT IMPLEMENTED !!!!!!
452       return 0;
453
454       /*
455
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;
460       int resul;
461       resul=pskExtension(conf,session,PSK_STATUS_CONT,NULL,0,&payloadOut,&sizePayloadOut);
462
463       if(!resul || (sizePayloadOut<1) || (sizePayloadOut>EXT_PAYLOAD_MAX_LEN))
464         {
465           //the extension has failed
466           // the authentication must fail
467           // the sentPacket must be a EAP_Failure packet
468           return 1;
469         }
470       
471       // add to sentPacket the following information:
472       // R = CONT or DONE_FAILURE or DONE_SUCCESS thanks to session->authStatus
473       // E = 1
474       // EXT_Type=session->extType
475       // EXT_payload=payloadOut
476       
477       */
478       
479     }   
480
481   session->pChannelReplayCounter++;
482
483   session->state=PCHANNEL;
484   
485
486   return 1;
487   
488 }
489
490
491
492 int pskPChannel(PSK_CONF *conf, PSK_SESSION *session, EAP_PACKET *recvPacket, EAP_PACKET *sentPacket){
493
494   /* the received packet is shown below
495    *
496    * 0                   1                   2                   3
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    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
503    *     ...Nonce    |                                               |
504    * +-+-+-+-+-+-+-+-+                                               +
505    * |                                                               |
506    * +                                                               +
507    * |                             TAG                               |
508    * +                                                               +
509    * |                                                               |
510    * +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
511    * |               | R |E| Reserved|EXT_Type (opt)|                |
512    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++                +
513    * :                                                               :
514    * :        EXT_Payload (optional)                                 :
515    * +                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
516    * |                               |
517    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
518    *
519    * EXT_Type and EXT_Payload must be in the EAP packet when E is set to 1
520    * EXT_Payload could be null
521    *
522   */
523
524   psk_message_4 *psk_msg_4;
525
526   // for the pchannel
527   unsigned char eapHeader[EAP_HEADER_SIZE];
528   unsigned char nn[PSK_RANDOM_NUMBER_SIZE];
529   EAX eax;
530   AES c;
531   bool st;
532   unsigned char flags;
533   
534   if(recvPacket->length<(EAP_HEADER_SIZE+PSK_PCHANNEL_REPLAY_COUNTER_SIZE+PSK_MAC_SIZE+1))
535     {   
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 ########
539       
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;
543       
544       return 1;  
545     }
546   
547   
548   psk_msg_4=(psk_message_4*)recvPacket->type.data;
549
550
551   if(ntohl(psk_msg_4->nonce)!=session->pChannelReplayCounter)
552     {
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
556
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;
560       
561       return 1;  
562     }
563   
564   // decrypt the received packet with the EAX mode and check the EAP header
565
566    // calculate the EAP header
567   eapHeader[0]=recvPacket->code;
568   eapHeader[1]=recvPacket->id;
569   
570   recvPacket->length=htons(recvPacket->length);
571   memcpy(&(eapHeader[2]),&(recvPacket->length),2);
572   recvPacket->length=ntohs(recvPacket->length);
573   
574   eapHeader[4]=recvPacket->type.type;
575   
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);
579
580   // EAX encryption
581   
582   eax.initialize(session->tek, PSK_TEK_SIZE, AES_BLOCKSIZE, &c);
583     
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);
588   
589   if(!st){
590     // the decryption ends by a failure
591     
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;
595     
596     return 1;      
597   }
598
599   
600   eax.computePlaintext((byte*)&(psk_msg_4->flags),sizeof(psk_msg_4->flags),(byte*)&flags);
601   
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)))
603     {
604       // the packet is malformed
605       // the authentication must fail
606       // the sentPacket must be a EAP_Failure packet
607
608       DEBUG2("pskPChannel: the packet is malformed: the authentication must fail");
609       sentPacket->code=PW_EAP_FAILURE;
610       
611       return 1;
612      }
613   
614
615    if(session->extType==0 && ((flags & PSK_IS_EXT)==PSK_IS_EXT))
616      {
617        // error: standard authentication awaited
618        // the authentication must fail
619        // the sentPacket must be a EAP_Failure packet
620        
621        DEBUG2("pskPChannel: the packet is malformed: the authentication must fail");
622        sentPacket->code=PW_EAP_FAILURE;
623        
624        return 1;
625      }
626
627    if(session->extType!=0 && ((flags & PSK_IS_EXT)==0))
628      {
629        // error: extended authentication awaited
630        // the authentication must fail
631        // the sentPacket must be a EAP_Failure packet
632
633        DEBUG2("pskPChannel: the packet is malformed: the authentication must fail");
634        sentPacket->code=PW_EAP_FAILURE;
635
636        return 1;
637      }
638
639    if((flags & PSK_IS_EXT)==0)
640      {
641        // standard authentication
642        
643        if(((flags & PSK_STATUS_DONE_SUCCESS)==PSK_STATUS_DONE_SUCCESS) && session->authStatus==PSK_STATUS_DONE_SUCCESS)
644          {
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
648
649            sentPacket->code=PW_EAP_SUCCESS;
650
651          } else {
652            // sentPacket must be an EAP_Failure packet
653            // the EAP-PSK authentication will end after sending sentPacket
654
655            sentPacket->code=PW_EAP_FAILURE;
656
657          }
658        
659      } else {
660        // extended authentication
661
662
663        // !!!!! NOT IMPLEMENTED !!!!!
664        return 0;
665
666
667        /*              
668        if(session->isSupportedExt)
669          {
670            
671            if(recvPacket->data.EXT_Payload)
672              {
673
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)
679                int resul;
680                resul=pskExtension(conf,session,recvPacket->data.R,recvPacket->data.EXT_Payload,sizePayloadIn,&payloadOut,&sizePayloadOut); 
681                
682                if(!resul || (sizePayloadOut<1) || (sizePayloadOut>EXT_PAYLOAD_MAX_LEN))
683                  {
684                    //the extension has failed
685                    // the authentication must fail
686                    // the sentPacket must be a EAP_Failure packet
687                    return 1;
688                  }
689                
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
694                  return 1;
695                }
696                
697                // add to sentPacket the following information:
698                // R = CONT or DONE_FAILURE or DONE_SUCCESS thanks to session->authStatus
699                // E = 1
700                // EXT_Type=session->extType
701                // EXT_payload=payloadOut
702                
703              } else {
704                // the peer doesn't support the specified extension
705
706                session->isSupportedExt=0;
707
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
712                  return 1;
713                }
714                
715                // add to sentPacket the following information:
716                // R = DONE_FAILURE or DONE_SUCCESS thanks to the server policy
717                // E = 1
718                // EXT_Type=session->extType
719              }
720            
721          } else {
722            
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
727               return 1;
728
729             } else {
730               // the packet is malformed
731               // the authentication must fail
732               // the sentPacket must be a EAP_Failure packet
733               return 1;
734             }
735               
736          }
737        */
738        
739        session->pChannelReplayCounter++;
740        // use the EAX mode to encrypt the EXT_Payload and protect the EAP header
741        
742        // !!!! NOT IMPLEMENTED !!!!
743        // only standard authentication supported
744
745        session->pChannelReplayCounter++;
746        
747      }
748    
749    // stay in this state
750    return 1;
751    
752 }                       
753
754
755
756 int pskExtension(PSK_CONF *conf, PSK_SESSION *session, unsigned short receivedStatus, void *dataIn, int sizeDataIn, void **dataOut, int *sizeDataOut){
757   
758   // this functionality makes it possible to do authorization, account refilling...
759
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
761   
762   // !!! Be careful !!!
763   // dataOut mustn't be NULL
764
765   // !!!! NOT IMPLEMENTED !!!!
766   return 0;
767
768 }
769
770
771
772 /** 
773  *@memo         this function frees the session data
774  *@param        opaque, pointer to a structure which contains information session
775  */
776 void pskFreeSession(void *opaque){
777   PSK_SESSION *session;
778   
779   DEBUG2("pskFreeSession:");
780   
781   if(!opaque) return;
782   
783   session=(PSK_SESSION *)opaque;
784   if(!session) return;
785   
786   if(session->id_p) {
787     free(session->id_p);
788   }
789
790   free(session);
791   
792   opaque=NULL;
793   
794   DEBUG2("pskFreeSession: finished");
795
796 }