#ifndef __USB_EAP_H__
#define __USB_EAP_H__

#define CONFIG_USER_WIJET_DRV 0

#if CONFIG_USER_WIJET_DRV==1
#define		EAP_OVER_USB			1 // this must be put before include ssl.h
#endif

//#include "control.h"
#include <ssl/ssl_locl.h>
//#include <openssl/cryptlib.h>
#include <crypto/cryptlib.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/hmac.h>
#include <openssl/dh.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/tls1.h>
#include <openssl/evp.h>

#include <openssl/md5.h>

//#include "s9memory.h"
//#include "cxmemory.h"
//#include "usbd.h"

#define OPENSSL_NO_COMP                     //SSL don't support DTLS (Datagram TLS)


//typedef unsigned char           uint8_t;
//typedef unsigned char           u_int8_t;
//typedef unsigned int            uint32_t;
typedef unsigned int            FDEPTH;
//typedef unsigned short          uint16_t;

#define	FALSE					0
#define	TRUE					1
#define	TickTime				0

#define debug_printf            WIMAX_PRINT
//#define debug_printf            syslog
#define bzero(a,b)              memset(a,0,b)
#define FREE                    free
#define TEST_FLAG(var,flag)     (var & flag)

//the following debug levels send syslog message in any way 
#define DEBUG_STATE             0
#define DEBUG_NORMAL            0
#define DEBUG_AUTHTYPES         0
#define DEBUG_INT               0
#define DEBUG_EVERYTHING        0

#define TTLS_SESSION_KEY_CONST          "ttls keying material"
#define TTLS_SESSION_KEY_CONST_SIZE     20

#define EVP_MD_CTX_FLAG_NON_FIPS_ALLOW	0x0008	// Allow use of non FIPS digest 
//#define DTLS1_VERSION			        0xFEFF
#define DTLS1_BAD_VER			        0x0100

#define WIMAX_TX_EAP_PKT          0
#define WIMAX_TX_ETHERNET_PKT     1

#define WIJET_SCAN_COMPLETE     0x810E 
#define WIJET_SCAN_RESULT       0x810F 
#define WIJET_TX_EAP_PKT   	    0x0200
#define WIJET_RX_EAP_PKT     	0x8201
#define WIJET_TX_ETHERNET_PKT   0x0202
#define WIJET_RX_ETHERNET_PKT   0x8203


#define EAPTLS_START         0x20
#define EAPTLS_LENGTH_MORE   0xC0
#define EAPTLS_LENGTH_INCL   0x80
#define EAPTLS_MORE_FRAGS    0x40
#define EAPTLS_START         0x20
#define EAPTLS_ACK           0x00
#define EAPTLS_FINAL         0x00

#define EAP_REQUEST         1
#define EAP_RESPONSE        2
#define EAP_SUCCESS         3
#define EAP_FAILURE         4

#define EAP_TYPE_IDENTITY    1
#define EAP_TYPE_NOTIFY      2
#define EAP_TYPE_NAK         3
#define EAP_TYPE_TTLS       21
#define NO_EAP_AUTH         -1

#define EAP_REQUEST_ID      1
#define EAP_REQUEST_AUTH    2
#define EAP_REQUEST_NOTIFY  3

#define USER_NAME_AVP        1
#define USER_PASSWORD_AVP    2
#define CHAP_PASSWORD_AVP    3
#define CHAP_CHALLENGE_AVP   60
#define EAP_MESSAGE          79

// Defines for MS-CHAP values also from the dictionary.
#define MS_VENDOR_ATTR       311
#define MS_CHAP_RESPONSE     1
#define MS_CHAP_CHALLENGE    11
#define MS_CHAP2_RESPONSE    25

#define MANDITORY_FLAG       0x40
#define VENDOR_FLAG          0x80
#define TTLS_CHALLENGE       "ttls challenge"    // Need to generate implied challenge.
#define TTLS_CHALLENGE_SIZE  14

/* Error codes that we can get for various pieces of xsupplicant. */

// If we return >=0 then there wasn't an error.
#define XPROMPT            2    // We asked the GUI to prompt for something.
#define XDATA              1    // There is data to return.
#define XNEWESSID          3    // We have a new ESSID.
#define XINNERSUCCESS      4    // The EAP method said it was successful.
#define XENONE             0

// Error numbers -1 to -10 are socket related errors.
#define XENOSOCK          -1
#define XESOCKOP          -2
#define XENOTINT          -3
#define XENOWIRELESS      -4
#define XENOFRAMES        -5
#define XEIGNOREDFRAME    -6
#define XGOODKEYFRAME      6
#define XEBADKEY          -7
#define XNOMOREINTS        2
#define XINVALIDINT        3  // This isn't an error.  It is for situations
                              // where an interface index of 0 is invalid.

// Error numbers -11 through -20 are for misc. errors.
#define XECONFIGFILEFAIL  -11
#define XECONFIGPARSEFAIL -12 
#define XENOTHING_TO_DO   -13
#define XEBADCONFIG       -14
#define XEBADPACKETSIZE   -15
#define XEINVALIDEAP      -16
#define XEGENERROR        -17
#define XENOTSUPPORTED    -18
#define XECONFIGALREADYLOADED -19
#define XEINNERFAILED     -20

// Error numbers -21 through -30 are memory related errors.
#define XEMALLOC          -21   // Malloc error.
#define XENOBUFFER        -22   // There was a buffer that was empty when it
                                // shouldn't have been!
#define XENOUSERDATA      -23   // Our userdata structure was NULL!

// Skip -31 through -40 for possible use later.

// Error numbers -41 through -50 are key generation errors.
#define XENOKEYSUPPORT    -41

// Error numbers -100 through -200 are EAP specific errors.
// Error messages for EAP-MD5
#define XEMD5LEN         -100

// Error messages for EAP-TLS
#define XETLSINIT        -105
#define XETLSSTARTFAIL   -106
#define XETLSBADFLAGS    -107
#define XETLSCERTLOAD    -108
#define XETLSNOCTX       -109
#define XTLSNEEDDATA      105

// Error message for TLS based methods other than EAP-TLS.
#define XEBADCN          -130
#define XETLSCRYPTFAIL   -131
#define XEPHASE2FAILURE  -132

// Error messages for MS-CHAPv2
#define XEMSCHAPV2LEN     -110

// Error messages for EAP-SIM
#define XESIMNOATMAC      -115
#define XESIMBADLEN       -116
#define XESIMBADTYPE      -117
#define XESIMBADMAC       -118
#define XESIMBADCMD       -119
#define XESIMBADMODE      -120
#define XESIMGENERR       -121
#define XEAKASYNCFAIL     -122

// Error message for EAP-TNC
#define XEINVALIDFLAGSVER -130
#define XETNCLIBFAILURE   -131

// Error message for LEAP
#define XELEAP            -140

typedef enum 
{
    RES_UNSET, 
    RES_YES, 
    RES_NO
} sess_res;

typedef enum 
{
    TTLS_PHASE2_UNDEFINED,
    TTLS_PHASE2_PAP,
	TTLS_PHASE2_CHAP,
	TTLS_PHASE2_MSCHAP,
	TTLS_PHASE2_MSCHAPV2,
    TTLS_PHASE2_EAP_MD5 
} ttls_phase2_type;


#if 0 //fanny : already defined in openssl-0.9.8e/ssl/ssl_locl.h:523
//macro for implementing a TLS method
#define IMPLEMENT_tls1_meth_func(func_name, s_accept, s_connect, s_get_meth) \
SSL_METHOD *func_name(void)  \
{ \
	static SSL_METHOD func_name##_data= { \
		TLS1_VERSION, \
		tls1_new, \
		tls1_clear, \
		tls1_free, \
		s_accept, \
		s_connect, \
		ssl3_read, \
		ssl3_peek, \
		ssl3_write, \
		ssl3_shutdown, \
		ssl3_renegotiate, \
		ssl3_renegotiate_check, \
		ssl3_ctrl, \
		ssl3_ctx_ctrl, \
		ssl3_get_cipher_by_char, \
		ssl3_put_cipher_by_char, \
		ssl3_pending, \
		ssl3_num_ciphers, \
		ssl3_get_cipher, \
		s_get_meth, \
		tls1_default_timeout, \
		&TLSv1_enc_data, \
		ssl_undefined_void_function, \
		ssl3_callback_ctrl, \
		ssl3_ctx_callback_ctrl, \
		ssl3_get_message, \
		ssl3_read_bytes, \
		ssl3_write_bytes, \
		ssl3_dispatch_alert, \
    }; \
	return &func_name##_data; \
}
#endif

struct eap_header {
    uint8_t  eap_code;
    uint8_t  eap_identifier;
    uint16_t eap_length;
    uint8_t  eap_type;
}__attribute__ ((packed));
//__attribute__ ((aligned(4)));



struct generic_eap_data {
    void *eap_conf_data;        // Pointer to the configuration information for
                                // the EAP type we are going to use.

    void *eap_data;             // Pointer to EAP type specific state data.

    char *identity;             // Pointer to parent's ID

    char *tempPwd;              // Pointer to a temporary password.

    int eapid;                  // The EAP ID of the packet we are working with.

    int eapNum;                 // The EAP type we are working with.

    int need_password;          // The EAP method should set this to 1 when it
                                // requires a password, or other challenge data
                                // from a GUI interface.

    char *eaptype;              // When a password is needed, the EAP handler
                                // should identify itself by putting a text
                                // version of it's name here.  Otherwise, it 
                                // this variable should be NULL.

    char *eapchallenge;         // When an EAP method requires some sort of 
                                // challenge be displayed to the user in order 
                                // for them to generate the proper password data.
  
};



struct tls_vars {
    SSL_CTX *ctx;              // Our OpenSSL context.
    SSL *ssl;                  // typedef struct ssl_st SSL; typedef struct ssl_ctx_st SSL_CTX;
    ENGINE *engine;
    BIO *ssl_in, *ssl_out;
    int resume;                // Should we attempt to resume this connection?
    int resuming;              // Are we in the process of resuming?

    int verify_mode;           // This should be set to SSL_VERIFY_PEER to 
                               // verify the peer certificate, and set to 
                               // SSL_VERIFY_NONE to ignore verification.

    int cnexact;               // Should be the same as the cnexact value for
                               // TTLS or PEAP, depending on which one we are
                               // using.

    char *cncheck;             // Should be the same as the cncheck .....
    char *tlsoutdata, *sessionkeyconst;
    int tlsoutsize,tlsoutptr,sessionkeylen;
    char *phase2data;
    int phase;                 // Which phase are we in?

    int cert_loaded;           // This should be set to TRUE when the user
                               // certificate is loaded.  This allows us to
                               // clear out thisint->tempPwd so that it can
                               // be used by a phase 2 type.

  // This next value needs some explaining.  With TTLS, as soon as the
  // the TLS piece is completed, we are expected to send back a response that
  // contains the inner authentication.  I choose to refer to this as a 
  // "quick" response.  With PEAP, we should simply ACK the final piece of
  // the TLS handshake, and wait for the RADIUS server to send us an inner
  // EAP Request Identity.  This is *not* a quick response.
  int quickResponse;    //false only for PEAP?
};



struct config_ttls_phase2  
{ 
    ttls_phase2_type phase2_type;
    void *phase2_data;
    struct config_ttls_phase2 *next;
};

struct config_mschapv2
{
    char *username;
    char *password;
};


// The items in this structure need to match those in config_eap_tls up to 
// the random_file item, or else things may have problems.
struct config_eap_ttls
{
    char * user_cert;
    char * root_cert;
    char * root_dir;
    char * crl_dir;
    char * user_key;
    char * user_key_pass;
    sess_res session_resume;
    int  chunk_size;
    char *random_file;

    char *cncheck;
    int  cnexact;

    ttls_phase2_type phase2_type;      // the type to actually do in phase 2
    struct config_ttls_phase2 *phase2; // all phase 2 types we support 
    struct generic_eap_data *phase2_eap_data; //used only by EAP-MD5 phase 2
};

struct interface_data
{
    uint8_t *keyingMaterial;                // Hold any keying material generated by
                                            // an EAP type.  Should be NULL if there
                                            // isn't any!

    char keyingLength;                      // Normal EAP methods will return 32 bytes
                                            // of keying material.  Goofy EAP methods
                                            // like LEAP use less material.

    char *tempPassword;                     // Temporary password.
       
    struct generic_eap_data *activemethod;  // This is used to hook the currently active "phase 1" to.  
    char * identity;                        // EAP identity
    struct config_eap_ttls eap_conf_data;   // configuration information 
	struct config_ttls_phase2  conf_phase2; // phase 2 methods we support, it is a link list of "struct config_ttls_phase2"
	struct config_mschapv2    mschap2_data; // user name & password


    uint8_t * sendframe;                    // point to the frame to be sent
    int send_size;                          // size of the frame to be sent 

    uint8_t * recvframe;                    // point to the frame received 
    int recv_size;                          // size of the received frame

    uint8_t tx_usb_header_len;              //proprietary Tx USB header length
    uint8_t rx_usb_header_len;              //proprietary Rx USB header length
	int (* send_to_usb)(unsigned char * buf, int len, int type);   //dongle's "send to USB" method
	int (* send_key_to_dongle)(unsigned char * buf); //dongle's "send key to dongle" method
	int (* connect)(void);                 //dongle's connect method
	int (* disconnect)(void);                 //dongle's disconnect method
};



struct eap_type_handler {
    int eap_auth_type;
    char *eapname;
    int (*eap_auth_setup)(struct generic_eap_data *);
    int (*eap_auth_handlers)(struct generic_eap_data *, uint8_t *, int, uint8_t *, int*);
    int (*eap_auth_get_keys)(struct interface_data *);
    int (*eap_auth_failed)(struct generic_eap_data *);
    int (*eap_auth_cleanup)(struct generic_eap_data *);
};



typedef char (*phase2_call)(struct generic_eap_data *thisint, uint8_t *in, int in_size, char *out, int *out_size);

int ttls_do_phase2(struct generic_eap_data *thisint, char *in, int in_size, char *out, int *out_size);
void WIMAX_DUMP_BUFFER(int do_syslog, unsigned char * buf, int len);
void WIMAX_PRINT(int do_syslog, const char *format, ...);
int xsup_assert(int condition, char *desc, int flag);


#endif
