original files of m241

This commit is contained in:
neelimap
2026-07-30 11:19:44 +05:30
parent 170c2b3f3a
commit afc7070c1f
12254 changed files with 7655111 additions and 0 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,164 @@
/*
******************************************************************************
* INTERPEAK INTERNAL API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_aka.h,v $ $Revision: 1.4 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_aka.h,v $
* $Author: hchowdhu $ $Date: 2010-06-28 22:03:11 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#if !defined(IPEAP_AKA_H) && defined(IPEAP_USE_EAP_AKA)
#define IPEAP_AKA_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include "ipeap.h"
#include "ipeap_h.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPEAP_AKA_VERSION 1
/* Non-skippable attributes (0-127) */
#define IPEAP_AKA_AT_RAND 1
#define IPEAP_AKA_AT_AUTN 2
#define IPEAP_AKA_AT_RES 3
#define IPEAP_AKA_AT_AUTS 4
#define IPEAP_AKA_AT_PADDING 6
#define IPEAP_AKA_AT_PERMANENT_ID_REQ 10
#define IPEAP_AKA_AT_MAC 11
#define IPEAP_AKA_AT_NOTIFICATION 12
#define IPEAP_AKA_AT_ANY_ID_REQ 13
#define IPEAP_AKA_AT_IDENTITY 14
#define IPEAP_AKA_AT_VERSION_LIST 15
#define IPEAP_AKA_AT_SELECTED_VERSION 16
#define IPEAP_AKA_AT_FULLAUTH_ID_REQ 17
#define IPEAP_AKA_AT_COUNTER 19
#define IPEAP_AKA_AT_COUNTER_TOO_SMALL 20
#define IPEAP_AKA_AT_NONCE_S 21
#define IPEAP_AKA_AT_CLIENT_ERROR_CODE 22
/* Skippable attributes (128-) */
#define IPEAP_AKA_AT_IV 129
#define IPEAP_AKA_AT_ENCR_DATA 130
#define IPEAP_AKA_AT_NEXT_PSEUDONYM 132
#define IPEAP_AKA_AT_NEXT_REAUTH_ID 133
#define IPEAP_AKA_AT_CHECKCODE 134
#define IPEAP_AKA_AT_RESULT_IND 135
/* Subtypes */
#define IPEAP_AKA_SUBTYPE_CHALLENGE 1
#define IPEAP_AKA_SUBTYPE_AUTHENTICATION_REJECT 2
#define IPEAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE 4
#define IPEAP_AKA_SUBTYPE_IDENTITY 5
#define IPEAP_AKA_SUBTYPE_NOTIFICATION 12
#define IPEAP_AKA_SUBTYPE_REAUTHENTICATION 13
#define IPEAP_AKA_SUBTYPE_CLIENT_ERROR 14
/* AT_CLIENT_ERROR_CODE values */
#define IPEAP_AKA_UNABLE_TO_PROCESS_PACKET 0
#define IPEAP_AKA_UNSUPPORTED_VERSION 1
#define IPEAP_AKA_INSUFFICIENT_NUM_OF_CHAL 2
#define IPEAP_AKA_RAND_NOT_FRESH 3
/* AT_NOTIFICATION values */
#define IPEAP_AKA_FAILURE_AFTER_AUTH 0x0000
#define IPEAP_AKA_TEMPORARILY_DENIED 0x0402
#define IPEAP_AKA_NOT_SUBSCRIBED 0x0407
#define IPEAP_AKA_FAILURE_BEFORE_AUTH 0x4000
#define IPEAP_AKA_SUCCESS 0x8000
/* Constants */
#define IPEAP_AKA_HEADER_LEN 8
#define IPEAP_AKA_RAND_LEN 16
#define IPEAP_AKA_AUTN_LEN 16
#define IPEAP_AKA_AUTS_LEN 14
#define IPEAP_AKA_NONCE_S_LEN 16
#define IPEAP_AKA_MAC_LEN 16
#define IPEAP_AKA_CHECKCODE_LEN 20
#define IPEAP_AKA_RES_LEN 16
#define IPEAP_AKA_IK_LEN 16
#define IPEAP_AKA_CK_LEN 16
#define IPEAP_AKA_K_AUTH_LEN 16
#define IPEAP_AKA_K_ENCR_LEN 16
#define IPEAP_AKA_MSK_LEN 64
#define IPEAP_AKA_SESSION_ID_LEN (1 + IPEAP_AKA_RAND_LEN + IPEAP_AKA_AUTN_LEN)
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_aka_methods_get
*===========================================================================
* Description: Return a structure containing pointer to all functions
* required by EAP.
* Parameters:
* Returns:
*/
IP_PUBLIC Ipeap_methods*
ipeap_aka_methods_get(void);
/*
*===========================================================================
* ipeap_aka_get_identity
*===========================================================================
* Description: Read identity from card (IMSI number).
* Parameters: identity - buffer that will receive the null-terminated
* identity.
* identityLen - Size of identity buffer.
* Returns: IPCOM_SUCCESS
* IPCOM_ERR_FAILED
*/
IP_PUBLIC Ip_err
ipeap_aka_get_identity(char *identity, Ip_u32 identityLen);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,555 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_common_tls.c,v $ $Revision: 1.6.10.2 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_common_tls.c,v $
* $Author: jli7 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include "ipeap_common_tls.h"
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include "ipeap.h"
#include "ipeap_h.h"
#include <openssl/err.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_tls_suppl_ctx_free
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipeap_tls_suppl_ctx_free(Ipeap_tls_suppl_ctx *ctx)
{
if(!ctx)
return;
if(ctx->ssl_ctx)
SSL_CTX_free(ctx->ssl_ctx);
if(ctx->ssl)
SSL_free(ctx->ssl);
ipcom_memset(ctx, 0, sizeof(Ipeap_tls_suppl_ctx));
ipcom_free(ctx);
}
/*
*===========================================================================
* ipeap_tls_suppl_setup_ssl
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_tls_suppl_setup_ssl(Ipeap_tls_suppl_ctx *ctx)
{
ctx->ssl = SSL_new(ctx->ssl_ctx);
if(!ctx->ssl)
{
IPCOM_LOG0(ERR, "ipeap_tls_suppl_setup_ssl :: SSL_new() failed");
return IPCOM_ERR_FAILED;
}
SSL_set_connect_state(ctx->ssl);
(void)SSL_set_options(ctx->ssl, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE);
ctx->in_bio = BIO_new(BIO_s_mem());
ctx->out_bio = BIO_new(BIO_s_mem());
if(!ctx->in_bio || !ctx->out_bio)
{
if(ctx->in_bio)
(void)BIO_free(ctx->in_bio);
if(ctx->out_bio)
(void)BIO_free(ctx->out_bio);
IPCOM_LOG0(ERR, "ipeap_tls_suppl_setup_ssl :: BIO_s_mem() failed");
return IPCOM_ERR_FAILED;
}
SSL_set_bio(ctx->ssl, ctx->in_bio, ctx->out_bio);
return IPCOM_SUCCESS;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_common_tls_ctx_new
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ipeap_tls_suppl_ctx*
ipeap_common_tls_ctx_new(void)
{
Ipeap_tls_suppl_ctx *tls_suppl_ctx = IP_NULL;
EVP_PKEY *tls_key = IP_NULL;
X509 *tls_cert = IP_NULL;
tls_suppl_ctx = ipcom_malloc(sizeof(Ipeap_tls_suppl_ctx));
if(!tls_suppl_ctx)
return IP_NULL;
ipcom_memset(tls_suppl_ctx, 0, sizeof(Ipeap_tls_suppl_ctx));
tls_suppl_ctx->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
if(!tls_suppl_ctx->ssl_ctx)
{
IPCOM_LOG0(ERR, "ipeap_tls_suppl_init :: SSL_CTX_new() failed");
goto error;
}
/* Load server key */
tls_key = ipeap_load_tls_key();
if(tls_key)
{
/* load server cert */
tls_cert = ipeap_load_tls_cert();
if(tls_cert)
{
/* Check that key and cert match */
if(X509_check_private_key(tls_cert, tls_key) != 1)
{
IPCOM_LOG0(ERR, "ipeap_tls_suppl_init :: X509_check_private_key() failed");
goto error;
}
if(!SSL_CTX_use_PrivateKey(tls_suppl_ctx->ssl_ctx, tls_key))
{
IPCOM_LOG0(ERR, "ipeap_tls_suppl_init :: SSL_CTX_use_PrivateKey() failed");
goto error;
}
if(!SSL_CTX_use_certificate(tls_suppl_ctx->ssl_ctx, tls_cert))
{
IPCOM_LOG0(ERR, "ipeap_tls_suppl_init :: SSL_CTX_use_certificate() failed");
goto error;
}
}
else
{
IPCOM_LOG0(WARNING, "No TLS X509 certificate loaded by ipwebs_load_tls_cert()");
}
}
else
{
IPCOM_LOG0(WARNING, "No TLS key loaded by ipeap_load_tls_key()");
}
if(tls_key)
EVP_PKEY_free(tls_key);
if(tls_cert)
X509_free(tls_cert);
/* Load CA certificates */
if(ipeap_load_ca_certs(tls_suppl_ctx->ssl_ctx->cert_store) == IPCOM_SUCCESS)
SSL_CTX_set_verify(tls_suppl_ctx->ssl_ctx, SSL_VERIFY_PEER, ipeap_tls_cert_verify);
else
{
IPCOM_LOG0(WARNING, "No TLS trusted certs loaded by ipeap_load_ca_certs(). Peer certificate validation turned off");
}
if(ipeap_tls_suppl_setup_ssl(tls_suppl_ctx) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "ipeap_tls_suppl_init :: ipeap_tls_suppl_setup_ssl() failed");
goto error;
}
return tls_suppl_ctx;
error:
ipeap_tls_suppl_ctx_free(tls_suppl_ctx);
if(tls_key)
EVP_PKEY_free(tls_key);
if(tls_cert)
X509_free(tls_cert);
return IP_NULL;
}
/*
*===========================================================================
* ipeap_common_tls_handle_frag_and_handshake
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipeap_common_tls_handle_frag_and_handshake(Ipeap_ctx *ctx, Ipeap_tls_suppl_ctx *tls_suppl_ctx, Ipeap_pkt *in_pkt, Ipeap_pkt *out_pkt)
{
Ipeap_tls_msg *msg;
int msg_len;
int rc;
int ssl_rc;
msg = IPEAP_PKT2TLSMSG(in_pkt);
ip_assert(msg->code == IPEAP_MSG_REQUEST);
/* Are we sending a fragmented packet? */
if(tls_suppl_ctx->frag_tot_len > 0)
return ipeap_common_tls_make_out_frag_pkt(tls_suppl_ctx, out_pkt, IPEAP_MSG_RESPONSE, msg->id, ctx->meth_id);
/* Write received data to SSL's input BIO */
if(msg->flags & IPEAP_TLS_FLAG_LEN_INCL)
msg_len = IP_GET_NTOHS(&msg->length) - 10; /* Remove header length*/
else
msg_len = IP_GET_NTOHS(&msg->length) - 6; /* Remove header length*/
if(msg_len > 0)
{
if(msg->flags & IPEAP_TLS_FLAG_LEN_INCL)
rc = BIO_write(tls_suppl_ctx->in_bio, msg->u.len_present.data, msg_len);
else
rc = BIO_write(tls_suppl_ctx->in_bio, msg->u.data, msg_len);
if(rc != msg_len)
{
IPCOM_LOG3(ERR, "%sFailed to write EAP fragment to SSL BIO, rc: %d, msg_len: %d",
ctx->syslog_prefix, rc, msg_len);
return IPCOM_ERR_FAILED;
}
}
/* If this is a fragmented packet, wait for remaining fragments to arrive */
if(msg->flags & IPEAP_TLS_FLAG_MORE_FRAG)
{
rc = ipeap_tls_pkt_set_header(out_pkt, IPEAP_PKT_RESPONSE, msg->id, 6, ctx->meth_id, 0);
out_pkt->end += 6;
if(rc != IPCOM_SUCCESS)
return rc;
return IPEAP_PENDING_SEND_OUT_PKT;
}
/* TODO: It should be possible to reset existing SSL context */
if(SSL_get_state(tls_suppl_ctx->ssl) == SSL_ST_OK)
{
if(msg->flags & IPEAP_TLS_FLAG_START)
{
IPCOM_LOG1(INFO, "%sRenegotiating SSL", ctx->syslog_prefix);
SSL_free(tls_suppl_ctx->ssl);
if(ipeap_tls_suppl_setup_ssl(tls_suppl_ctx) != IPCOM_SUCCESS)
{
IPCOM_LOG1(ERR, "%sipeap_tls_suppl_setup_ssl() failed", ctx->syslog_prefix);
return IPCOM_ERR_FAILED;
}
ctx->state = IPEAP_STATE_HANDSHAKE;
}
else
/* TLS handshake completed => we have received application data over the TLS connection */
return IPEAP_TLS_DATA_AVAILABLE;
}
ssl_rc = SSL_do_handshake(tls_suppl_ctx->ssl);
if(ssl_rc == 1)
{
IPCOM_LOG1(INFO, "%sTLS handshake successfully completed", ctx->syslog_prefix);
return IPEAP_TLS_HANDSHAKE_COMPLETE;
}
if(ssl_rc <= 0 && SSL_get_error(tls_suppl_ctx->ssl, ssl_rc) == SSL_ERROR_WANT_READ)
rc = ipeap_common_tls_make_out_frag_pkt(tls_suppl_ctx, out_pkt, IPEAP_MSG_RESPONSE, msg->id, ctx->meth_id);
else
{
IPCOM_LOG3(ERR, "%sTLS handshake failed, SSL_get_error(): %d, %s",
ctx->syslog_prefix, SSL_get_error(tls_suppl_ctx->ssl, ssl_rc),
ERR_error_string(ERR_get_error(), IP_NULL));
if(BIO_pending(tls_suppl_ctx->out_bio) > 0)
/* There is data in the out_bio, most likely an SSL alert. Send it to peer */
rc = ipeap_common_tls_make_out_frag_pkt(tls_suppl_ctx, out_pkt, IPEAP_MSG_RESPONSE, msg->id, ctx->meth_id);
else
{
/* No SSL data to send, make an empty ack packet */
rc = ipeap_tls_pkt_set_header(out_pkt, IPEAP_PKT_RESPONSE, msg->id, 6, ctx->meth_id, 0);
out_pkt->end += 6;
rc = IPEAP_PENDING_SEND_OUT_PKT;
}
}
ERR_clear_error();
ERR_remove_state(0);
return rc;
}
/*
*===========================================================================
* ipeap_tls_pkt_set_header
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipeap_tls_pkt_set_header(Ipeap_pkt *pkt, Ip_u8 code, Ip_u8 id, Ip_u16 len, Ip_u8 type, Ip_u8 flags)
{
Ip_err rc;
Ipeap_tls_msg* msg;
rc = ipeap_pkt_set_header(pkt, code, id, len, type);
if(rc != IPCOM_SUCCESS)
return rc;
msg = IPEAP_PKT2TLSMSG(pkt);
msg->flags = flags;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_common_tls_make_out_frag_pkt
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipeap_common_tls_make_out_frag_pkt(Ipeap_tls_suppl_ctx *ctx, Ipeap_pkt *pkt, Ip_u8 code, Ip_u8 id, Ip_u8 meth_id)
{
Ipeap_tls_msg* msg;
int bytes_left_to_send;
int tls_data_len;
Ip_u8 *out_buf;
Ip_err rc;
Ip_u8 flags = 0;
int header_size = 6;
msg = IPEAP_PKT2TLSMSG(pkt);
bytes_left_to_send = (int)BIO_ctrl_pending(ctx->out_bio);
if(bytes_left_to_send > IPEAP_MTU && ctx->frag_tot_len == 0)
{
/* This message must be fragmented and this is the first fragment */
ctx->frag_tot_len = bytes_left_to_send;
}
if(bytes_left_to_send > IPEAP_MTU)
flags |= IPEAP_TLS_FLAG_MORE_FRAG;
if(ctx->frag_tot_len != 0)
{
flags |= IPEAP_TLS_FLAG_LEN_INCL;
header_size = 10;
IP_SET_HTONL(msg->u.len_present.len, ctx->frag_tot_len);
out_buf = msg->u.len_present.data;
}
else
out_buf = msg->u.data;
tls_data_len = IP_MIN(bytes_left_to_send, IPEAP_MTU-header_size);
tls_data_len = IP_MIN(tls_data_len, IPEAP_PKT_GET_SPACE_LEFT(pkt));
if(BIO_read(ctx->out_bio, out_buf, tls_data_len) != tls_data_len)
{
IPCOM_LOG1(ERR, "ipeap_common_tls_make_out_frag_pkt :: failed to read %d bytes from out_bio", tls_data_len);
return IPCOM_ERR_FAILED;
}
rc = ipeap_tls_pkt_set_header(pkt, code, id, (Ip_u16)(tls_data_len+header_size), meth_id, flags);
if(rc != IPCOM_SUCCESS)
return rc;
if(flags & IPEAP_TLS_FLAG_LEN_INCL)
IP_SET_HTONL(msg->u.len_present.len, ctx->frag_tot_len);
if(BIO_ctrl_pending(ctx->out_bio) == 0)
ctx->frag_tot_len = 0; /* This is the last fragment, reset frag_tot_len */
pkt->end += header_size + tls_data_len; /* Add header and payload to length */
return IPEAP_PENDING_SEND_OUT_PKT;
}
/*
*===========================================================================
* ipeap_common_tls_ctx_free
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipeap_common_tls_ctx_free(Ipeap_tls_suppl_ctx *tls_suppl_ctx)
{
if(tls_suppl_ctx->ssl)
SSL_free(tls_suppl_ctx->ssl);
if(tls_suppl_ctx->ssl_ctx)
SSL_CTX_free(tls_suppl_ctx->ssl_ctx);
ipcom_free(tls_suppl_ctx);
ERR_clear_error();
ERR_remove_state(0);
}
/*
*===========================================================================
* ipeap_tls_common_generate_key
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_err
ipeap_tls_common_generate_key(Ipeap_tls_suppl_ctx *tls_suppl_ctx, const char* label, Ip_u8* key, int key_len)
{
Ip_u8 tmp_buf[2*SSL3_RANDOM_SIZE+40];
Ip_u8* tmp_out;
ip_assert(tls_suppl_ctx);
ip_assert(ipcom_strlen(label) < 40);
tmp_out = ipcom_malloc((Ip_size_t)key_len);
if(!tmp_out)
return IPCOM_ERR_FAILED;
ipcom_memcpy(tmp_buf, label, ipcom_strlen(label));
ipcom_memcpy(tmp_buf+ipcom_strlen(label), tls_suppl_ctx->ssl->s3->client_random, SSL3_RANDOM_SIZE);
ipcom_memcpy(tmp_buf+ipcom_strlen(label)+SSL3_RANDOM_SIZE, tls_suppl_ctx->ssl->s3->server_random, SSL3_RANDOM_SIZE);
#ifdef _WRS_CONFIG_COMPONENT_IPCRYPTO_OPENSSL_1_0_2
ipssl_tls1_PRF(TLS1_PRF,
tmp_buf, (int)ipcom_strlen(label)+2*SSL3_RANDOM_SIZE,
NULL, 0, NULL, 0, NULL, 0, NULL, 0,
tls_suppl_ctx->ssl->session->master_key, tls_suppl_ctx->ssl->session->master_key_length,
key, tmp_out, key_len);
#else
ipssl_tls1_PRF(EVP_md5(), EVP_sha1(),
tmp_buf, (int)ipcom_strlen(label)+2*SSL3_RANDOM_SIZE,
tls_suppl_ctx->ssl->session->master_key, tls_suppl_ctx->ssl->session->master_key_length,
key, tmp_out, key_len);
#endif
ipcom_free(tmp_out);
return IPCOM_SUCCESS;
}
IP_GLOBAL Ip_err
ipeap_tls_common_generate_session_id(Ipeap_tls_suppl_ctx *tls_suppl_ctx,Ip_u8 eap_type,Ip_u8 *session_id,Ip_u32 *session_id_len)
{
if (*session_id_len < IPEAP_TLS_SESSION_ID_LEN)
{
IPCOM_LOG3(ERR, "ipeap_tls_common_generate_session_id - not enough buffer is available to hold "
"the Session_Id for 0x%x , (%d wanted), (%d given )",eap_type,IPEAP_TLS_SESSION_ID_LEN , *session_id_len );
return IPCOM_ERR_INVALID_ARG;
}
if(eap_type!=IPEAP_TYPE_TLS && eap_type!= IPEAP_TYPE_TTLS && eap_type!=IPEAP_TYPE_PEAP)
{
IPCOM_LOG1(ERR, "ipeap_tls_common_generate_session_id - not a valid EAP TYPE 0x%x",eap_type);
return IPCOM_ERR_INVALID_ARG;
}
ipcom_memset(session_id, 0,*session_id_len);
session_id[0] = eap_type;
session_id += 1;
ipcom_memcpy(session_id, tls_suppl_ctx->ssl->s3->client_random, SSL3_RANDOM_SIZE);
ipcom_memcpy(session_id+SSL3_RANDOM_SIZE, tls_suppl_ctx->ssl->s3->server_random, SSL3_RANDOM_SIZE);
*session_id_len = IPEAP_TLS_SESSION_ID_LEN;
return IPCOM_SUCCESS;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,149 @@
/*
******************************************************************************
* INTERPEAK INTERNAL API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_common_tls.h,v $ $Revision: 1.4.12.1 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_common_tls.h,v $
* $Author: jli7 $ $Date: 2015-01-30 03:27:26 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#ifndef IPEAP_COMMON_TLS_H
#define IPEAP_COMMON_TLS_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#ifdef IPCRYPTO
#define IPCOM_USE_CLIB_PROTO
#endif
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_syslog.h>
#ifdef IPSSL
#include <ipssl.h>
#endif
#include <openssl/ssl.h>
#include "ipeap.h"
#include "ipeap_h.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPEAP_TLS_FLAG_LEN_INCL 0x80
#define IPEAP_TLS_FLAG_MORE_FRAG 0x40
#define IPEAP_TLS_FLAG_START 0x20
#define IPEAP_TLS_HANDSHAKE_COMPLETE 100
#define IPEAP_TLS_DATA_AVAILABLE 101
#define IPEAP_PKT2TLSMSG(pkt) ((Ipeap_tls_msg*)(&((pkt)->data[(pkt)->start])))
#define IPEAP_TLS_SESSION_ID_LEN (1 + 2*SSL3_RANDOM_SIZE)
/* copied from openssl/ssl_locl.h */
#define SSL_HANDSHAKE_MAC_MD5 0x10
#define SSL_HANDSHAKE_MAC_SHA 0x20
#define TLS1_PRF_DGST_SHIFT 10
#define TLS1_PRF_MD5 (SSL_HANDSHAKE_MAC_MD5 << TLS1_PRF_DGST_SHIFT)
#define TLS1_PRF_SHA1 (SSL_HANDSHAKE_MAC_SHA << TLS1_PRF_DGST_SHIFT)
#define TLS1_PRF (TLS1_PRF_MD5 | TLS1_PRF_SHA1)
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ipeap_tls_suppl_ctx_st
{
SSL_CTX *ssl_ctx;
SSL *ssl;
BIO *in_bio;
BIO *out_bio;
int frag_tot_len;
} Ipeap_tls_suppl_ctx;
typedef struct Ipeap_tls_msg_st
{
Ip_u8 code;
Ip_u8 id;
Ip_u16 length;
Ip_u8 type;
Ip_u8 flags;
union {
struct {
Ip_u8 len[4];
Ip_u8 data[1];
} len_present;
Ip_u8 data[1];
} u;
Ip_u8 pad;
} Ipeap_tls_msg;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ipeap_tls_suppl_ctx* ipeap_common_tls_ctx_new(void);
IP_GLOBAL void ipeap_common_tls_ctx_free(Ipeap_tls_suppl_ctx *ctx);
IP_GLOBAL Ip_err ipeap_common_tls_handle_frag_and_handshake(Ipeap_ctx *ctx, Ipeap_tls_suppl_ctx *tls_suppl_ctx, Ipeap_pkt *in_pkt, Ipeap_pkt *out_pkt);
IP_GLOBAL Ip_err ipeap_common_tls_make_out_frag_pkt(Ipeap_tls_suppl_ctx *ctx, Ipeap_pkt *pkt, Ip_u8 code, Ip_u8 id, Ip_u8 meth_id);
IP_GLOBAL Ip_err ipeap_tls_pkt_set_header(Ipeap_pkt *pkt, Ip_u8 code, Ip_u8 id, Ip_u16 len, Ip_u8 type, Ip_u8 flags);
IP_GLOBAL Ip_err
ipeap_tls_common_generate_key(Ipeap_tls_suppl_ctx *tls_suppl_ctx, const char* label, Ip_u8* key, int key_len);
IP_GLOBAL Ip_err
ipeap_tls_common_generate_session_id(Ipeap_tls_suppl_ctx *tls_suppl_ctx,Ip_u8 eap_type,Ip_u8 *session_id,Ip_u32 *session_id_len);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,478 @@
/* ipeap_gtc.c - EAP GTC implementation */
/*
* Copyright (c) 2008 Wind River Systems, Inc.
*
* The right to copy, distribute, modify, or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*
*/
/*
modification history
--------------------
01d,21may10,hfc update eap as per requirement WIND00198105
01c,25mar08,mry Adding a missing return code
01b,28feb08,mry Code Inspection Changes
01a,04Feb08,mry Created
*/
/*
DESCRIPTION
This library contains the EAP GTC implementation as described in RFC 3748.
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_syslog.h>
#include "ipeap.h"
#include "ipeap_h.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPEAP_GTC_HEADER_LEN 5
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef enum {
IPEAP_GTC_WAIT_FOR_CHALLENGE = 0,
IPEAP_GTC_WAIT_FOR_USER_INPUT,
IPEAP_GTC_WAIT_FOR_SUCCESS,
IPEAP_GTC_AUTHENTICATED
} Ipeap_gtc_state;
typedef struct Ipeap_gtc_ctx_st
{
Ipeap_gtc_state state;
Ip_u8 msg_id; /* msg Id of last received request */
} Ipeap_gtc_ctx;
typedef struct Ipeap_gtc_msg_st
{
Ip_u8 code;
Ip_u8 id;
Ip_u16 length;
Ip_u8 type;
Ip_u8 type_data[1]; /* displayable msg of size 1 or more octets based on message length */
} Ipeap_gtc_msg;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_STATIC Ip_err ipeap_gtc_process_msg(struct Ipeap_ctx_st *ctx,
struct Ipeap_pkt_st *in_pkt,
struct Ipeap_pkt_st *reply_pkt);
IP_STATIC Ip_err ipeap_gtc_init(struct Ipeap_ctx_st *ctx);
IP_STATIC Ip_err ipeap_gtc_free(Ipeap_ctx *ctx);
IP_STATIC Ip_err ipeap_gtc_handle_user_input(Ipeap_ctx* ctx,
Ipeap_user_input* ui,
struct Ipeap_pkt_st *reply_pkt);
IP_PUBLIC Ip_err ipeap_gtc_display_status(struct Ipeap_ctx_st* ctx, char *str);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
IP_STATIC Ipeap_methods ipeap_gtc_methods =
{
ipeap_gtc_process_msg,
ipeap_gtc_init,
ipeap_gtc_free,
IP_NULL,
ipeap_gtc_handle_user_input,
ipeap_gtc_display_status,
IP_NULL
};
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_gtc_init
*===========================================================================
* Description: Initialize EAP gtc context.
* Parameters: ctx - The EAP gtc context.
* Returns:
* IPCOM_SUCCESS
* IPCOM_ERR_NO_MEMORY
* IPCOM_ERR_INVALID_ARG
*/
IP_STATIC Ip_err
ipeap_gtc_init(Ipeap_ctx* ctx)
{
Ip_err err = IPCOM_SUCCESS;
Ipeap_gtc_ctx* gtc_ctx = IP_NULL;
gtc_ctx = ipcom_calloc(1, sizeof(*gtc_ctx));
if (IP_NULL == gtc_ctx)
{
IPCOM_LOG1(CRIT, "%sEAP-GTC :: Out of memory", ctx->syslog_prefix);
err = IPCOM_ERR_NO_MEMORY;
}
else
{
ctx->mech_data = gtc_ctx;
ctx->state = IPEAP_STATE_INIT;
gtc_ctx->state = IPEAP_GTC_WAIT_FOR_CHALLENGE;
}
return err;
}
/*
*===========================================================================
* ipeap_gtc_free
*===========================================================================
* Description: Free EAP gtc context.
* Parameters: ctx - The EAP context.
* Returns: IPCOM_SUCCESS
*/
IP_STATIC Ip_err
ipeap_gtc_free(Ipeap_ctx* ctx)
{
Ipeap_gtc_ctx* gtc_ctx = IP_NULL;
if ((ctx != IP_NULL) && (ctx->mech_data != IP_NULL))
{
gtc_ctx = (Ipeap_gtc_ctx*)ctx->mech_data;
ipcom_free(gtc_ctx);
ctx->mech_data = IP_NULL;
}
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_gtc_get_msg_from_pkt
*===========================================================================
*/
IP_STATIC Ipeap_gtc_msg*
ipeap_gtc_get_msg_from_pkt(Ipeap_pkt* pkt)
{
return (Ipeap_gtc_msg*)(pkt->data + pkt->start);
}
/*
*===========================================================================
* ipeap_gtc_get_msg_max_size
*===========================================================================
*/
IP_STATIC Ip_u32
ipeap_gtc_get_msg_max_size(Ipeap_pkt* pkt)
{
if ((pkt->end - pkt->start) >= pkt->max_len)
return 0;
return (Ip_u32)(pkt->max_len - (pkt->end - pkt->start));
}
/*
*===========================================================================
* ipeap_gtc_get_msg_typedata_len
*===========================================================================
*/
IP_STATIC Ip_u32
ipeap_gtc_get_msg_typedata_len(Ipeap_pkt* pkt)
{
return (Ip_u32)(pkt->end - pkt->start - IPEAP_GTC_HEADER_LEN);
}
/*
*===========================================================================
* ipeap_gtc_suppl_process_msg
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_gtc_process_request(Ipeap_ctx *ctx, Ipeap_pkt *in_pkt, Ipeap_pkt *out_pkt)
{
Ip_u8 *prompt_msg;
Ip_u32 max_len, prompt_len;
Ip_err err = IPEAP_DROPPED_PKT;
Ipeap_gtc_msg* in_msg = IP_NULL;
Ipeap_gtc_ctx* gtc_ctx = (Ipeap_gtc_ctx*)ctx->mech_data;
if (gtc_ctx->state == IPEAP_GTC_AUTHENTICATED) {
/* redundant message, drop */
IPCOM_LOG1(ERR, "%sEAP-GTC :: packet received after success. dropping.", ctx->syslog_prefix);
return IPEAP_DROPPED_PKT;
}
ctx->state = IPEAP_STATE_HANDSHAKE;
/* Convert packet to message */
in_msg = ipeap_gtc_get_msg_from_pkt(in_pkt);
max_len = ipeap_gtc_get_msg_max_size(out_pkt);
if (max_len == 0)
{
IPCOM_LOG1(ERR, "%sEAP-GTC :: Buffer too small", ctx->syslog_prefix);
err = IPEAP_DROPPED_PKT;
}
else if (in_msg->type != IPEAP_TYPE_GTC)
{
IPCOM_LOG1(ERR, "%sEAP-GTC :: Only type GTC challenge is supported", ctx->syslog_prefix);
err = IPEAP_DROPPED_PKT;
}
else
{
gtc_ctx->msg_id = in_msg->id; /* Save msg id for when we send response */
gtc_ctx->state = IPEAP_GTC_WAIT_FOR_USER_INPUT;
/* We need to get user input. We (ab)use the out_pkt as a store to pass back the challenge prompt */
max_len = ipeap_gtc_get_msg_max_size(out_pkt);
prompt_len = ipeap_gtc_get_msg_typedata_len(in_pkt);
if (prompt_len > max_len-1)
prompt_len = max_len-1;
prompt_msg = (Ip_u8 *)ipeap_gtc_get_msg_from_pkt(out_pkt);
if (prompt_len)
memcpy(prompt_msg, in_msg->type_data, prompt_len);
prompt_msg[prompt_len] ='\0';
out_pkt->end = out_pkt->start + (int)prompt_len + 1;
err = IPEAP_PENDING_USER_INPUT;
}
return err;
}
/*
*===========================================================================
* ipeap_gtc_process_success
*===========================================================================
* Description: Process a success message.
* Parameters: ctx - The EAP context.
* Returns:
* IPEAP_SUCCESS
*/
IP_STATIC Ip_err
ipeap_gtc_process_success(Ipeap_ctx* ctx)
{
Ipeap_gtc_ctx* gtc_ctx = (Ipeap_gtc_ctx*)ctx->mech_data;
if (gtc_ctx->state != IPEAP_GTC_WAIT_FOR_SUCCESS) {
/* redundant message, drop */
IPCOM_LOG1(ERR, "%sEAP-GTC :: unexpected success packet. dropping.", ctx->syslog_prefix);
return IPEAP_DROPPED_PKT;
}
ctx->state = IPEAP_STATE_AUTHENTICATED;
gtc_ctx->state = IPEAP_GTC_AUTHENTICATED;
return IPEAP_SUCCESS;
}
/*
*===========================================================================
* ipeap_gtc_process_msg
*===========================================================================
* Description: Process a message.
* Parameters: ctx - The EAP context.
* in_pkt - The request packet (message).
* out_pkt - The created response packet (message).
* Returns:
* IPEAP_SUCCESS
* IPEAP_PENDING_SEND_OUT_PKT
* IPEAP_FAILURE
* IPEAP_DROPPED_PKT
*/
IP_STATIC Ip_err
ipeap_gtc_process_msg(
Ipeap_ctx* ctx,
Ipeap_pkt* in_pkt,
Ipeap_pkt* out_pkt)
{
Ip_err err = IPEAP_FAILURE;
Ipeap_gtc_msg* msg = IP_NULL;
msg = ipeap_gtc_get_msg_from_pkt(in_pkt);
/* Sanity check, always at least 4 bytes size */
if ((in_pkt->end - in_pkt->start) < 4)
{
IPCOM_LOG1(ERR, "%sEAP-GTC :: Bad in packet", ctx->syslog_prefix);
return IPEAP_DROPPED_PKT;
}
switch (msg->code)
{
case IPEAP_MSG_REQUEST:
IPCOM_LOG1(DEBUG, "%sEAP-GTC :: Received request message", ctx->syslog_prefix);
err = ipeap_gtc_process_request(ctx, in_pkt, out_pkt);
break;
case IPEAP_MSG_RESPONSE:
IPCOM_LOG1(ERR, "%sEAP-GTC :: Received response message, dropping message", ctx->syslog_prefix);
err = IPEAP_DROPPED_PKT;
break;
case IPEAP_MSG_FAILURE:
IPCOM_LOG1(ERR, "%sEAP-GTC :: Received failure message, resetting state", ctx->syslog_prefix);
(void)ipeap_gtc_free(ctx);
ctx->state = IPEAP_STATE_INIT;
ctx->cb = IP_NULL;
err = IPEAP_FAILURE;
break;
case IPEAP_MSG_SUCCESS:
IPCOM_LOG1(INFO, "%sEAP-GTC :: Received EAP success", ctx->syslog_prefix);
err = ipeap_gtc_process_success(ctx);
break;
default:
IPCOM_LOG2(ERR, "%sEAP-GTC :: Received unknown message type: %d, dropping message", ctx->syslog_prefix, msg->code);
err = IPEAP_DROPPED_PKT;
break;
}
return err;
}
/*
*===========================================================================
* ipeap_gtc_handle_user_input
*===========================================================================
*/
IP_STATIC Ip_err
ipeap_gtc_handle_user_input(Ipeap_ctx* ctx, Ipeap_user_input* ui, Ipeap_pkt* out_pkt) {
Ip_err err = IPEAP_FAILURE;
Ipeap_gtc_msg* out_msg = IP_NULL;
Ipeap_gtc_ctx* gtc_ctx = (Ipeap_gtc_ctx*)ctx->mech_data;
Ip_u32 max_len = 0, resp_len = 0;
if (gtc_ctx->state != IPEAP_GTC_WAIT_FOR_USER_INPUT) {
IPCOM_LOG2(ERR, "EAP-GTC: Unexpected user input in state %d", ctx->syslog_prefix, gtc_ctx->state);
return IPCOM_ERR_FAILED;
}
if (ui->ui_type != IPEAP_UI_CHALLENGE_RESP_STRING) {
IPCOM_LOG1(ERR, "EAP-GTC: Invalid user input type", ctx->syslog_prefix);
return IPCOM_ERR_INVALID_ARG;
}
/* Build a response packet */
resp_len = (Ip_u32)strlen(ui->ui_data.challenge_resp_str) ;
/* Convert packet to message */
out_msg = ipeap_gtc_get_msg_from_pkt(out_pkt);
max_len = ipeap_gtc_get_msg_max_size(out_pkt);
if (max_len < (IPEAP_GTC_HEADER_LEN+resp_len))
{
IPCOM_LOG1(ERR, "%sEAP-GTC :: Buffer too small for out packet", ctx->syslog_prefix);
err = IPEAP_DROPPED_PKT;
}
else
{
out_msg->code = IPEAP_MSG_RESPONSE;
out_msg->id = gtc_ctx->msg_id; /* Response id from last received msg */
out_msg->type = IPEAP_TYPE_GTC;
out_msg->length = (Ip_u16)(IPEAP_GTC_HEADER_LEN + resp_len);
ipcom_memcpy(out_msg->type_data, ui->ui_data.challenge_resp_str, resp_len);
out_pkt->end = out_pkt->start + out_msg->length;
out_msg->length = ip_htons(out_msg->length);
gtc_ctx->state = IPEAP_GTC_WAIT_FOR_SUCCESS;
err = IPEAP_PENDING_SEND_OUT_PKT;
}
return err;
}
/*
*===========================================================================
* ipeap_gtc_methods_get
*===========================================================================
*/
IP_PUBLIC Ipeap_methods*
ipeap_gtc_methods_get(void)
{
return &ipeap_gtc_methods;
}
/*
*===========================================================================
* Ipeap_gtc_state_name
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC char *Ipeap_gtc_state_name(int state) {
if (state == IPEAP_GTC_WAIT_FOR_CHALLENGE)
return "IPEAP_GTC_WAIT_FOR_CHALLENGE";
else if (state == IPEAP_GTC_WAIT_FOR_USER_INPUT)
return "IPEAP_GTC_WAIT_FOR_USER_INPUT";
else if (state == IPEAP_GTC_WAIT_FOR_SUCCESS)
return "IPEAP_GTC_WAIT_FOR_SUCCESS";
else if (state == IPEAP_GTC_AUTHENTICATED)
return "IPEAP_GTC_AUTHENTICATED";
return "UNKNOWN STATE";
}
/*
*===========================================================================
* ipeap_gtc_display_status
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipeap_gtc_display_status(struct Ipeap_ctx_st* ctx, char *str) {
Ipeap_gtc_ctx* gtc_ctx = (Ipeap_gtc_ctx*)ctx->mech_data;
ipcom_printf(" GTC state = %s\n", Ipeap_gtc_state_name(gtc_ctx->state));
return IPCOM_SUCCESS;
}
+189
View File
@@ -0,0 +1,189 @@
/*
******************************************************************************
* INTERPEAK INTERNAL API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_h.h,v $ $Revision: 1.11 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_h.h,v $
* $Author: ulf $ $Date: 2009-06-08 11:05:00 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#ifndef IPEAP_H_H
#define IPEAP_H_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipeap.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPEAP
#define IPCOM_SYSLOG_PRIORITY IPEAP_SYSLOG_PRIORITY
#define IPEAP_MAX_MECH 9
#define IPEAP_MAX_VENDOR_SPECIFIC 1
#define IPEAP_MSG_REQUEST 1
#define IPEAP_MSG_RESPONSE 2
#define IPEAP_MSG_SUCCESS 3
#define IPEAP_MSG_FAILURE 4
#define IPEAP_MTU 1020
/* Radius attribute definitions */
#define IPEAP_RAD_ATTR_USER_NAME ((Ip_u32) 1)
#define IPEAP_RAD_ATTR_PW ((Ip_u32) 2)
#define IPEAP_RAD_ATTR_CHAP_PW ((Ip_u32) 3)
#define IPEAP_RAD_ATTR_REPLY_MSG ((Ip_u32) 18)
#define IPEAP_RAD_ATTR_CHAP_CHALLANGE ((Ip_u32) 60)
#define IPEAP_RAD_ATTR_EAP_MSG ((Ip_u32) 79)
/* MSCHAPv2 Radius attribute definitions */
#define IPEAP_RAD_ATTR_MS_CHAP_ERROR ((Ip_u32) 2)
#define IPEAP_RAD_ATTR_MS_CHAP_CHALLENGE ((Ip_u32) 11)
#define IPEAP_RAD_ATTR_MS_CHAP2_RESPONSE ((Ip_u32) 25)
#define IPEAP_RAD_ATTR_MS_CHAP2_SUCCESS ((Ip_u32) 26)
#define IPEAP_RAD_ATTR_MS_CHAP2_CPW ((Ip_u32) 27)
#define IPEAP_PKT2MSG(pkt) ((Ipeap_msg*)(&((pkt)->data[(pkt)->start])))
#define IPEAP_PKT_GET_LEN(pkt) ((pkt)->end-(pkt)->start)
#define IPEAP_PKT_GET_SPACE_LEFT(pkt) ((pkt)->max_len-(pkt)->end)
#define IPEAP_PKT_GET_END_PTR(pkt) (&((pkt)->data[(pkt)->end]))
#define IPEAP_PKT_GET_START_PTR(pkt) (&((pkt)->data[(pkt)->start]))
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ipeap_mech_entry_st
{
Ipeap_methods* methods;
Ip_bool enabled;
Ip_u8 id;
Ipeap_vendor_id vendor_id;
Ipeap_vendor_type vendor_type;
} Ipeap_mech_entry;
typedef struct Ipeap_msg_st
{
Ip_u8 code;
Ip_u8 id;
Ip_u16 length;
Ip_u8 type;
Ip_u8 data[1];
} Ipeap_msg;
typedef struct Ipeap_expanded_msg_st
{
Ip_u8 code;
Ip_u8 id;
Ip_u16 length;
Ip_u8 type;
Ipeap_vendor_id vendor_id;
Ipeap_vendor_type vendor_type;
Ip_u8 data[1];
} Ipeap_expanded_msg;
struct Ipeap_ctx_st
{
int mode;
int state;
char identity[IPEAP_IDENTITY_MAX_LEN];
char syslog_prefix[16];
Ip_u8 meth_id;
Ipeap_vendor_id vendor_id; /* for expanded type EAP methods */
Ipeap_vendor_type vendor_type; /* for expanded type EAP methods */
Ipeap_methods* cb;
struct Ipeap_mech_entry_st *mech_map;
Ip_bool method_locked; /* No other method other than already selected one can be negotiated */
/* Resend data */
Ip_u8 last_recv_pkt_hdr[5]; /* This is the header from the last packet we received from the peer */
Ipeap_pkt last_sent_pkt; /* This is the last packet we sent to the peer */
void* mech_data;
};
typedef struct Ipeap_ctx_st Ipeap_ctx;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ip_err ipeap_pkt_set_header(Ipeap_pkt* pkt, Ip_u8 code, Ip_u8 id, Ip_u16 len, Ip_u8 type);
IP_GLOBAL Ip_err ipeap_make_identity_response(Ipeap_ctx* ctx, Ipeap_pkt* in_pkt, Ipeap_pkt* out_pkt);
IP_GLOBAL Ip_err ipeap_make_nak_response(Ipeap_ctx* ctx, Ipeap_pkt* in_pkt, Ipeap_pkt* out_pkt);
IP_GLOBAL Ip_err ipeap_make_expanded_nak_response(Ipeap_ctx* ctx, Ipeap_pkt* in_pkt, Ipeap_pkt* out_pkt);
IP_GLOBAL Ip_err ipeap_make_notification_response(Ipeap_ctx* ctx, Ipeap_pkt* in_pkt, Ipeap_pkt* out_pkt);
IP_GLOBAL Ipeap_methods* ipeap_mech_cb_get(Ipeap_ctx* ctx, Ip_u8 mech_id,
Ipeap_vendor_id vendor_id,
Ipeap_vendor_type vendor_type);
IP_GLOBAL Ipeap_pkt* ipeap_pkt_new(int size);
IP_GLOBAL void ipeap_pkt_free(Ipeap_pkt *pkt);
IP_GLOBAL void ipeap_mschapv2_generate_nt_response(Ip_u8 *auth_challenge, Ip_u8 *peer_challenge,
Ip_u8 *username, Ip_size_t username_len,
Ip_u8 *password, Ip_size_t password_len,
Ip_u8 *response);
IP_GLOBAL void ipeap_mschapv2_generate_authenticator_response(Ip_u8 *password, Ip_size_t password_len,
Ip_u8 *nt_response,
Ip_u8 *peer_challenge,
Ip_u8 *auth_challenge,
Ip_u8 *username, Ip_size_t username_len,
Ip_u8 *response);
IP_GLOBAL void ipeap_mschapv2_buf_bin2hex(Ip_u8 *bin_buf, Ip_size_t bin_len, char *hex_buf);
IP_GLOBAL char *Ipeap_type_name(int type, Ipeap_vendor_id *vendor_id, Ipeap_vendor_type vendor_type);
#ifdef IP_DEBUG
IP_GLOBAL const char* ipeap_code_str(Ip_u8 code);
#endif
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,727 @@
/* ipeap_leap.c - EAP LEAP implementation */
/*
* Copyright (c) 2008 Wind River Systems, Inc.
*
* The right to copy, distribute, modify, or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*
*/
/*
modification history
--------------------
01e,13dec10,mry Fix defect WIND00246269.
01d,08jul10,hfc Add secure keyDB support
01c,21may10,hfc update eap as per requirement WIND00198105
01b,25mar08,mry Adding a missing return code
01a,28Feb08,mry Created
*/
/*
DESCRIPTION
This library contains the EAP LEAP implementation.
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#ifdef IPMCRYPTO
#include <ip/openssl/md5.h>
#else
#include <openssl/md5.h>
#endif
/*
#include <openssl/ssl.h>
*/
#include "ipeap.h"
#include "ipeap_h.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPEAP_LEAP_HEADER_LEN 8
#define IPEAP_LEAP_CHALLENGE_SIZE (8)
#define IPEAP_LEAP_CHALLENGE_MSG_SIZE (IPEAP_LEAP_HEADER_LEN+IPEAP_LEAP_CHALLENGE_SIZE)
#define IPEAP_LEAP_RESPONSE_SIZE (24)
#define IPEAP_LEAP_RESPONSE_MSG_SIZE (IPEAP_LEAP_HEADER_LEN+IPEAP_LEAP_RESPONSE_SIZE)
#define IPEAP_LEAP_PASSWORD_HASH_SIZE (16)
#define IPEAP_LEAP_VERSION (1)
#define IPEAP_LEAP_UNUSED (0)
#define IPEAP_LEAP_SESSION_KEY_SIZE (16)
#define IPEAP_LEAP_SESSION_KEY_INPUT_SIZE (LEAP_PASSWORD_HASH_SIZE \
+ 2*LEAP_CHALLENGE_SIZE \
+ 2*LEAP_RESPONSE_SIZE)
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef enum {
IPEAP_LEAP_WAIT_FOR_CHALLENGE = 0,
IPEAP_LEAP_WAIT_FOR_SUCCESS,
IPEAP_LEAP_WAIT_FOR_RESPONSE,
IPEAP_LEAP_AUTHENTICATED
} Ipeap_leap_state;
typedef struct Ipeap_leap_ctx_st
{
Ipeap_leap_state state;
Ip_u8* user; /* leap username */
Ip_u8* pw; /* leap password */
Ip_u8 passwordHash[IPEAP_LEAP_PASSWORD_HASH_SIZE]; /* Hashed password */
Ip_u8 doublyHashedPW[IPEAP_LEAP_PASSWORD_HASH_SIZE]; /* Doubly Hashed password */
Ip_u8 challenge1[IPEAP_LEAP_CHALLENGE_SIZE]; /* Challenge to Supp */
Ip_u8 response1[IPEAP_LEAP_RESPONSE_SIZE]; /* Supp's response */
Ip_u8 challenge2[IPEAP_LEAP_CHALLENGE_SIZE]; /* Challenge to Auth */
Ip_u8 response2[IPEAP_LEAP_RESPONSE_SIZE]; /* Auth. response */
} Ipeap_leap_ctx;
typedef struct Ipeap_leap_msg_st
{
Ip_u8 code;
Ip_u8 id;
Ip_u16 length;
Ip_u8 type;
char version; /* version of LEAP, (0x01) */
char unused; /* unused, (0x00) */
char dataSize; /* size of data to follow */
Ip_u8 type_data[1]; /* beginning of data */
} Ipeap_leap_msg;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
extern IP_GLOBAL void ipeap_mschapv2_nt_password_hash(Ip_u8 *password, Ip_size_t password_len, Ip_u8 *password_hash);
extern IP_GLOBAL void ipeap_mschapv2_challenge_response(Ip_u8 *challenge, Ip_u8 *password_hash, Ip_u8 * response);
extern IP_GLOBAL void ipeap_mschapv2_hash_nt_password_hash(Ip_u8 *password_hash, Ip_u8 *password_hash_hash);
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_STATIC Ip_err ipeap_leap_process_msg(struct Ipeap_ctx_st *ctx,
struct Ipeap_pkt_st *in_pkt,
struct Ipeap_pkt_st *reply_pkt);
IP_STATIC Ip_err ipeap_leap_init(struct Ipeap_ctx_st *ctx);
IP_STATIC Ip_err ipeap_leap_free(Ipeap_ctx *ctx);
IP_STATIC Ip_err ipeap_leap_get_key(struct Ipeap_ctx_st* ctx, Ip_u8* key, int key_len);
IP_PUBLIC Ip_err ipeap_leap_display_status(struct Ipeap_ctx_st* ctx, char *str);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
IP_STATIC Ipeap_methods ipeap_leap_methods =
{
ipeap_leap_process_msg,
ipeap_leap_init,
ipeap_leap_free,
ipeap_leap_get_key,
IP_NULL,
ipeap_leap_display_status,
IP_NULL
};
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_leap_load_config
*===========================================================================
* Description: Load configuration from system variables.
* Parameters:
* Returns:
* IPCOM_SUCCESS
* IPCOM_ERR_INVALID_ARG
*/
IP_STATIC Ip_err
ipeap_leap_load_config(Ipeap_leap_ctx* leap_ctx)
{
Ip_err rc = IPCOM_SUCCESS ;
int pass_len = 128;
char* leap_pass_id = IP_NULL;
if(!leap_ctx)
{
IPCOM_LOG0(DEBUG, "ipeap_leap_load_config :: NULL leap_ctx");
return IPCOM_ERR_FAILED;
}
leap_ctx->user = (Ip_u8 *)ipcom_sysvar_get("ipeap.leap.user", IP_NULL, IP_NULL);
if(!leap_ctx->user)
{
IPCOM_LOG0(ERR, "EAP-LEAP: ipeap.leap.user sysvar not set");
goto err_out;
}
#ifdef IPCOM_USE_KEY_DB
if(ipcom_sysvar_get_as_int("ipeap.privacy", 0)==1)
{
leap_ctx->pw = ipcom_calloc(1,pass_len);
if (!leap_ctx->pw)
{
IPCOM_LOG0(ERR, "EAP-LEAP: out of memory");
goto err_out;
}
if(ipcom_sysvar_get_as_int("ipeap.privacy.retrieve.keydbid", 0)==1)
{
leap_pass_id = ipcom_sysvar_get("ipeap.leap.pw", IP_NULL, IP_NULL);
}
if ((rc = ipcom_key_db_buf_get(leap_pass_id ? leap_pass_id : LEAP_PASS_ID,leap_ctx->pw, &pass_len)) != IPCOM_SUCCESS)
{
ipcom_memset(leap_ctx->pw,0,pass_len);
IPCOM_LOG0(ERR, "EAP-LEAP: Unable to retrieve password ");
if(rc == IPCOM_ERR_NOT_FOUND)
IPCOM_LOG1(ERR, "EAP-LEAP: key ID %s does not exist",
leap_pass_id ? leap_pass_id : LEAP_PASS_ID);
if(rc == IPCOM_ERR_NO_MEMORY)
IPCOM_LOG0(ERR, "EAP-LEAP: out of memory while retrieving password from "
"secureDB");
goto err_out;
}
if(leap_pass_id)
ipcom_free(leap_pass_id);
}
else
#endif
leap_ctx->pw = (Ip_u8 *)ipcom_sysvar_get("ipeap.leap.pw", IP_NULL, IP_NULL);
if(!leap_ctx->pw)
{
IPCOM_LOG0(ERR, "EAP-LEAP: ipeap.leap.pw sysvar not set");
goto err_out;
}
return IPCOM_SUCCESS;
err_out:
if(leap_ctx->user) {
ipcom_free(leap_ctx->user);
leap_ctx->user = IP_NULL;
}
if(leap_ctx->pw) {
ipcom_free(leap_ctx->pw);
leap_ctx->pw = IP_NULL;
}
if(leap_pass_id)
ipcom_free(leap_pass_id);
return IPCOM_ERR_FAILED;
}
/*
*===========================================================================
* ipeap_leap_init
*===========================================================================
* Description: Initialize EAP leap context.
* Parameters: ctx - The EAP leap context.
* Returns:
* IPCOM_SUCCESS
* IPCOM_ERR_NO_MEMORY
* IPCOM_ERR_INVALID_ARG
*/
IP_STATIC Ip_err
ipeap_leap_init(Ipeap_ctx* ctx)
{
Ip_err err = IPCOM_SUCCESS;
Ipeap_leap_ctx* leap_ctx = IP_NULL;
leap_ctx = ipcom_calloc(1, sizeof(*leap_ctx));
if (IP_NULL == leap_ctx)
{
IPCOM_LOG1(CRIT, "%sEAP-LEAP :: Out of memory", ctx->syslog_prefix);
err = IPCOM_ERR_NO_MEMORY;
}
else if (IPCOM_SUCCESS != (err = ipeap_leap_load_config(leap_ctx)))
{
ipcom_free(leap_ctx);
IPCOM_LOG1(ERR, "%sEAP-LEAP :: Failed to load config", ctx->syslog_prefix);
}
else
{
ctx->mech_data = leap_ctx;
ctx->state = IPEAP_STATE_INIT;
leap_ctx->state = IPEAP_LEAP_WAIT_FOR_CHALLENGE;
}
return err;
}
/*
*===========================================================================
* ipeap_leap_free
*===========================================================================
* Description: Free EAP leap context.
* Parameters: ctx - The EAP context.
* Returns: IPCOM_SUCCESS
*/
IP_STATIC Ip_err
ipeap_leap_free(Ipeap_ctx* ctx)
{
Ipeap_leap_ctx* leap_ctx = IP_NULL;
if ((ctx != IP_NULL) && (ctx->mech_data != IP_NULL))
{
leap_ctx = (Ipeap_leap_ctx*)ctx->mech_data;
if(leap_ctx->user)
ipcom_free(leap_ctx->user);
if(leap_ctx->pw)
ipcom_free(leap_ctx->pw);
ipcom_free(leap_ctx);
ctx->mech_data = IP_NULL;
}
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_leap_get_msg_from_pkt
*===========================================================================
*/
IP_STATIC Ipeap_leap_msg*
ipeap_leap_get_msg_from_pkt(Ipeap_pkt* pkt)
{
return (Ipeap_leap_msg*)(pkt->data + pkt->start);
}
/*
*===========================================================================
* ipeap_leap_get_msg_max_size
*===========================================================================
*/
IP_STATIC Ip_u32
ipeap_leap_get_msg_max_size(Ipeap_pkt* pkt)
{
if ((pkt->end - pkt->start) >= pkt->max_len)
return 0;
return (Ip_u32)(pkt->max_len - (pkt->end - pkt->start));
}
/*
*===========================================================================
* ipeap_leap_get_msg_typedata_len
*===========================================================================
*/
#if 0
IP_STATIC Ip_u32
ipeap_leap_get_msg_typedata_len(Ipeap_pkt* pkt)
{
return (pkt->end - pkt->start - IPEAP_LEAP_HEADER_LEN);
}
#endif
/*
*===========================================================================
* ipeap_leap_gen_challenge
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipeap_leap_gen_challenge(Ip_u8* buf)
{
int i;
long* ptr;
long rnd;
for(i=0; i<(IPEAP_LEAP_CHALLENGE_SIZE/4); i++)
{
ptr = (long*)&buf[i];
rnd = ipcom_random();
IP_SET_32ON8(ptr, rnd);
}
}
/*
*===========================================================================
* ipeap_leap_process_request
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_leap_process_request(Ipeap_ctx *ctx, Ipeap_pkt *in_pkt, Ipeap_pkt *out_pkt)
{
Ipeap_leap_ctx* leap_ctx = (Ipeap_leap_ctx*)ctx->mech_data;
Ipeap_leap_msg* in_msg = IP_NULL;
Ipeap_leap_msg* out_msg = IP_NULL;
Ip_u32 max_len;
Ip_size_t pwlen;
ip_assert(leap_ctx);
if (leap_ctx->state != IPEAP_LEAP_WAIT_FOR_CHALLENGE) {
/* redundant message, drop */
IPCOM_LOG1(ERR, "%sEAP-LEAP :: unexpected request packet. dropping.", ctx->syslog_prefix);
return IPEAP_DROPPED_PKT;
}
out_msg = ipeap_leap_get_msg_from_pkt(out_pkt);
max_len = ipeap_leap_get_msg_max_size(out_pkt);
if (max_len < IPEAP_LEAP_RESPONSE_MSG_SIZE) {
IPCOM_LOG2(CRIT, "ipeap_leap_process_request:: Buffer too small for out packet(is %d, need %d). dropping.",
max_len, IPEAP_LEAP_RESPONSE_MSG_SIZE);
return IPEAP_DROPPED_PKT;
}
in_msg = ipeap_leap_get_msg_from_pkt(in_pkt);
if (in_msg->type != IPEAP_TYPE_LEAP) {
IPCOM_LOG2(CRIT, "%sEAP-LEAP :: unexpected EAP Request of type %d. dropping.", ctx->syslog_prefix, in_msg->type);
return IPEAP_DROPPED_PKT;
}
if (in_msg->version != IPEAP_LEAP_VERSION) {
IPCOM_LOG2(CRIT, "%sEAP-LEAP :: unsupported version (%d) in EAP Request. dropping.", ctx->syslog_prefix, in_msg->version);
return IPEAP_DROPPED_PKT;
}
if (in_msg->dataSize != IPEAP_LEAP_CHALLENGE_SIZE) {
IPCOM_LOG2(CRIT, "%sEAP-LEAP :: invalid datasize (%d) in EAP-LEAP Request. dropping.", ctx->syslog_prefix, in_msg->dataSize);
return IPEAP_DROPPED_PKT;
}
/* Calculate password hash and challenge response */
pwlen = ipcom_strlen((char *)leap_ctx->pw);
ipeap_mschapv2_nt_password_hash(leap_ctx->pw, pwlen, leap_ctx->passwordHash);
ipcom_memcpy(leap_ctx->challenge1, in_msg->type_data, IPEAP_LEAP_CHALLENGE_SIZE);
ipeap_mschapv2_challenge_response(leap_ctx->challenge1, leap_ctx->passwordHash, leap_ctx->response1);
/* create eap response containing challenge response */
out_msg->code = IPEAP_MSG_RESPONSE;
out_msg->id = in_msg->id;
out_msg->type = IPEAP_TYPE_LEAP;
out_msg->length = IPEAP_LEAP_RESPONSE_MSG_SIZE+(Ip_u16)strlen((char *)leap_ctx->user);
out_msg->version = IPEAP_LEAP_VERSION;
out_msg->unused = IPEAP_LEAP_UNUSED;
out_msg->dataSize = IPEAP_LEAP_RESPONSE_SIZE;
ipcom_memcpy(out_msg->type_data, leap_ctx->response1, IPEAP_LEAP_RESPONSE_SIZE);
ipcom_memcpy(out_msg->type_data+IPEAP_LEAP_RESPONSE_SIZE, leap_ctx->user, (Ip_size_t)strlen((char *)leap_ctx->user));
out_pkt->end = out_pkt->start + out_msg->length;
out_msg->length = ip_htons(out_msg->length);
/* Update state */
ctx->state = IPEAP_STATE_HANDSHAKE;
leap_ctx->state = IPEAP_LEAP_WAIT_FOR_SUCCESS;
return IPEAP_PENDING_SEND_OUT_PKT;
}
/*
*===========================================================================
* ipeap_leap_process_success
*===========================================================================
* Description: Process a success message.
* Parameters: ctx - The EAP context.
* Returns:
* IPEAP_SUCCESS
*/
IP_STATIC Ip_err
ipeap_leap_process_success(Ipeap_ctx* ctx, Ipeap_pkt *in_pkt, Ipeap_pkt *out_pkt)
{
Ipeap_leap_ctx* leap_ctx = (Ipeap_leap_ctx*)ctx->mech_data;
Ipeap_leap_msg* in_msg = IP_NULL;
Ipeap_leap_msg *out_msg = IP_NULL;
Ip_u32 max_len;
ip_assert(leap_ctx);
if (leap_ctx->state != IPEAP_LEAP_WAIT_FOR_SUCCESS) {
/* redundant message, drop */
IPCOM_LOG1(ERR, "%sEAP-LEAP :: unexpected success packet. dropping.", ctx->syslog_prefix);
return IPEAP_DROPPED_PKT;
}
out_msg = ipeap_leap_get_msg_from_pkt(out_pkt);
max_len = ipeap_leap_get_msg_max_size(out_pkt);
if (max_len < IPEAP_LEAP_CHALLENGE_MSG_SIZE) {
IPCOM_LOG2(CRIT, "ipeap_leap_process_request:: Buffer too small for out packet (is %d, need %d). dropping.",
max_len, IPEAP_LEAP_CHALLENGE_MSG_SIZE);
return IPEAP_DROPPED_PKT;
}
in_msg = ipeap_leap_get_msg_from_pkt(in_pkt);
/* Create a Request with the challenge to the auth */
ipeap_leap_gen_challenge(leap_ctx->challenge2);
out_msg->code = IPEAP_MSG_REQUEST;
out_msg->id = in_msg->id;
out_msg->type = IPEAP_TYPE_LEAP;
out_msg->length = IPEAP_LEAP_CHALLENGE_MSG_SIZE+(Ip_u16)strlen((char *)leap_ctx->user);
out_msg->version = IPEAP_LEAP_VERSION;
out_msg->unused = IPEAP_LEAP_UNUSED;
out_msg->dataSize = IPEAP_LEAP_CHALLENGE_SIZE;
ipcom_memcpy(out_msg->type_data, leap_ctx->challenge2, IPEAP_LEAP_CHALLENGE_SIZE);
ipcom_memcpy(out_msg->type_data+IPEAP_LEAP_CHALLENGE_SIZE, leap_ctx->user, (Ip_size_t)strlen((char *)leap_ctx->user));
out_pkt->end = out_pkt->start + out_msg->length;
out_msg->length = ip_htons(out_msg->length);
leap_ctx->state = IPEAP_LEAP_WAIT_FOR_RESPONSE;
return IPEAP_PENDING_SEND_OUT_PKT;
}
/*
*===========================================================================
* ipeap_leap_process_response
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_leap_process_response(Ipeap_ctx *ctx, Ipeap_pkt *in_pkt, Ipeap_pkt *out_pkt)
{
Ipeap_leap_ctx* leap_ctx = (Ipeap_leap_ctx*)ctx->mech_data;
Ipeap_leap_msg* in_msg = IP_NULL;
ip_assert(leap_ctx);
if (leap_ctx->state != IPEAP_LEAP_WAIT_FOR_RESPONSE) {
/* redundant message, drop */
IPCOM_LOG1(ERR, "%sEAP-LEAP :: unexpected response packet. dropping.", ctx->syslog_prefix);
return IPEAP_DROPPED_PKT;
}
in_msg = ipeap_leap_get_msg_from_pkt(in_pkt);
if (in_msg->type != IPEAP_TYPE_LEAP) {
IPCOM_LOG2(CRIT, "%sEAP-LEAP :: unexpected EAP Response of type %d. dropping.", ctx->syslog_prefix, in_msg->type);
return IPEAP_DROPPED_PKT;
}
if (in_msg->version != IPEAP_LEAP_VERSION) {
IPCOM_LOG2(CRIT, "%sEAP-LEAP :: unsupported version (%d) in EAP Response. dropping.", ctx->syslog_prefix, in_msg->version);
return IPEAP_DROPPED_PKT;
}
if (in_msg->dataSize != IPEAP_LEAP_RESPONSE_SIZE) {
IPCOM_LOG2(CRIT, "%sEAP-LEAP :: invalid datasize (%d) in EAP-LEAP Response. dropping.", ctx->syslog_prefix, in_msg->dataSize);
return IPEAP_DROPPED_PKT;
}
/* Compute the password double hash and corresponding challenge hash and compare to auth response */
ipeap_mschapv2_hash_nt_password_hash(leap_ctx->passwordHash, leap_ctx->doublyHashedPW);
ipeap_mschapv2_challenge_response(leap_ctx->challenge2, leap_ctx->doublyHashedPW, leap_ctx->response2);
if (ipcom_memcmp(leap_ctx->response2, in_msg->type_data, IPEAP_LEAP_RESPONSE_SIZE) != 0) {
IPCOM_LOG1(INFO, "%sEAP-LEAP :: Invalid authenticator response. Failing authentication.", ctx->syslog_prefix);
(void)ipeap_leap_free(ctx);
ctx->state = IPEAP_STATE_INIT;
ctx->cb = IP_NULL;
return IPEAP_FAILURE;
}
IPCOM_LOG1(INFO, "%sEAP-LEAP :: Authenticator response verified. Authentication successful.", ctx->syslog_prefix);
ctx->state = IPEAP_STATE_AUTHENTICATED;
leap_ctx->state = IPEAP_LEAP_AUTHENTICATED;
return IPEAP_SUCCESS;
}
/*
*===========================================================================
* ipeap_leap_process_msg
*===========================================================================
* Description: Process a message.
* Parameters: ctx - The EAP context.
* in_pkt - The request packet (message).
* out_pkt - The created response packet (message).
* Returns:
* IPEAP_SUCCESS
* IPEAP_PENDING_SEND_OUT_PKT
* IPEAP_FAILURE
* IPEAP_DROPPED_PKT
*/
IP_STATIC Ip_err
ipeap_leap_process_msg(
Ipeap_ctx* ctx,
Ipeap_pkt* in_pkt,
Ipeap_pkt* out_pkt)
{
Ip_err err = IPEAP_FAILURE;
Ipeap_leap_msg* msg = IP_NULL;
msg = ipeap_leap_get_msg_from_pkt(in_pkt);
/* Sanity check, always at least 4 bytes size */
if ((in_pkt->end - in_pkt->start) < 4)
{
IPCOM_LOG1(ERR, "%sEAP-LEAP :: Bad in packet", ctx->syslog_prefix);
return IPEAP_DROPPED_PKT;
}
switch (msg->code)
{
case IPEAP_MSG_REQUEST:
IPCOM_LOG1(DEBUG, "%sEAP-LEAP :: Received request message", ctx->syslog_prefix);
err = ipeap_leap_process_request(ctx, in_pkt, out_pkt);
break;
case IPEAP_MSG_RESPONSE:
IPCOM_LOG1(DEBUG, "%sEAP-LEAP :: Received response message", ctx->syslog_prefix);
err = ipeap_leap_process_response(ctx, in_pkt, out_pkt);
break;
case IPEAP_MSG_FAILURE:
IPCOM_LOG1(ERR, "%sEAP-LEAP :: Received failure message, resetting state", ctx->syslog_prefix);
(void)ipeap_leap_free(ctx);
ctx->state = IPEAP_STATE_INIT;
ctx->cb = IP_NULL;
err = IPEAP_FAILURE;
break;
case IPEAP_MSG_SUCCESS:
IPCOM_LOG1(INFO, "%sEAP-LEAP :: Received EAP success", ctx->syslog_prefix);
err = ipeap_leap_process_success(ctx, in_pkt, out_pkt);
break;
default:
IPCOM_LOG2(ERR, "%sEAP-LEAP :: Received unknown message type: %d, dropping message", ctx->syslog_prefix, msg->code);
err = IPEAP_DROPPED_PKT;
break;
}
return err;
}
/*
*===========================================================================
* ipeap_leap__get_key
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_leap_get_key(struct Ipeap_ctx_st* ctx, Ip_u8* key, int key_len)
{
Ipeap_leap_ctx* leap_ctx = (Ipeap_leap_ctx*)ctx->mech_data;
MD5_CTX md_ctx = {0};
if (leap_ctx->state != IPEAP_LEAP_AUTHENTICATED) {
IPCOM_LOG0(ERR, "ipeap_leap_get_key :: LEAP not in autenticated state yet, cannot retrieve session key.");
return IPCOM_ERR_FAILED;
}
if (key_len < MD5_DIGEST_LENGTH)
{
IPCOM_LOG1(ERR, "%sEAP-LEAP :: Buffer too small for key", ctx->syslog_prefix);
return IPCOM_ERR_INVALID_ARG;
}
#ifdef OPENSSL_FIPS
if (FIPS_mode())
{
IPCOM_LOG0(WARNING, "ipeap : MD5 is not supported when FIPS mode is enabled!\n");
return IPCOM_ERR_NOT_SUPPORTED;
}
#endif
MD5_Init(&md_ctx);
MD5_Update(&md_ctx, &leap_ctx->doublyHashedPW , sizeof(leap_ctx->doublyHashedPW));
MD5_Update(&md_ctx, &leap_ctx->challenge2 , sizeof(leap_ctx->challenge2));
MD5_Update(&md_ctx, &leap_ctx->response2 , sizeof(leap_ctx->response2));
MD5_Update(&md_ctx, &leap_ctx->challenge1 , sizeof(leap_ctx->challenge1));
MD5_Update(&md_ctx, &leap_ctx->response1 , sizeof(leap_ctx->response1));
MD5_Final(key, &md_ctx);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_leap_methods_get
*===========================================================================
*/
IP_PUBLIC Ipeap_methods*
ipeap_leap_methods_get(void)
{
return &ipeap_leap_methods;
}
/*
*===========================================================================
* Ipeap_leap_state_name
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC char *Ipeap_leap_state_name(int state) {
if (state == IPEAP_LEAP_WAIT_FOR_CHALLENGE)
return "IPEAP_LEAP_WAIT_FOR_CHALLENGE";
else if (state == IPEAP_LEAP_WAIT_FOR_SUCCESS)
return "IPEAP_LEAP_WAIT_FOR_SUCCESS";
else if (state == IPEAP_LEAP_WAIT_FOR_RESPONSE)
return "IPEAP_LEAP_WAIT_FOR_RESPONSE";
else if (state == IPEAP_LEAP_AUTHENTICATED)
return "IPEAP_LEAP_AUTHENTICATED";
return "UNKNOWN STATE";
}
/*
*===========================================================================
* ipeap_leap_display_status
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipeap_leap_display_status(struct Ipeap_ctx_st* ctx, char *str) {
Ipeap_leap_ctx* leap_ctx = (Ipeap_leap_ctx*)ctx->mech_data;
ipcom_printf(" LEAP state = %s\n", Ipeap_leap_state_name(leap_ctx->state));
return IPCOM_SUCCESS;
}
@@ -0,0 +1,576 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_md5.c,v $ $Revision: 1.11.12.1 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_md5.c,v $
* $Author: svc-cmnet $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
/*
modification history
--------------------
01a,08jul10,hfc Add secure keyDB support
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#ifdef IPMCRYPTO
#include <ip/openssl/md5.h>
#else
#include <openssl/md5.h>
#endif
#include "ipeap.h"
#include "ipeap_h.h"
#include "ipeap_md5.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPEAP_MD5_MAX_SECRET 128
#define IPEAP_MD5_HEADER_LEN 5
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ipeap_md5_ctx_st
{
char secret[IPEAP_MD5_MAX_SECRET];
} Ipeap_md5_ctx;
typedef struct Ipeap_md5_info_st
{
Ip_u8* value;
Ip_u32 valueLen;
Ip_u8* name;
Ip_u32 nameLen;
} Ipeap_md5_info;
typedef struct Ipeap_md5_msg_st
{
Ip_u8 code;
Ip_u8 id;
Ip_u16 length;
Ip_u8 type;
Ip_u8 value_size;
Ip_u8 value[1];
} Ipeap_md5_msg;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
*===========================================================================
* ipeap_md5_init
*===========================================================================
* Description: Initialize an EAP MD5 exchange.
* Parameters: ctx - The eap context structure.
* Returns:
* IPCOM_SUCCESS
* IPCOM_ERR_FAILED
*/
IP_STATIC Ip_err
ipeap_md5_init(
Ipeap_ctx* ctx);
/*
*===========================================================================
* ipeap_md5_free
*===========================================================================
* Description: Free an EAP MD5 exchange.
* Parameters:
* Returns:
* IPCOM_SUCCESS
* IPCOM_ERR_FAILED
*/
IP_STATIC Ip_err
ipeap_md5_free(
Ipeap_ctx* ctx);
/*
*===========================================================================
* ipeap_md5_process_msg
*===========================================================================
* Description: Process EAP MD5 messages
* Parameters: in_pkt - The incoming message
* out_pkt - Will receive the eventual outgoing message
* Returns:
* IPEAP_PENDING_SEND_OUT_PKT
* IPEAP_DROPPED_PKT
* IPEAP_SUCCESS
* IPEAP_FAILURE
*/
IP_STATIC Ip_err
ipeap_md5_process_msg(
Ipeap_ctx* ctx,
Ipeap_pkt* in_pkt,
Ipeap_pkt* out_pkt);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
IP_STATIC Ipeap_methods ipeap_md5_methods =
{
ipeap_md5_process_msg,
ipeap_md5_init,
ipeap_md5_free,
IP_NULL,
IP_NULL,
IP_NULL,
IP_NULL
};
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_md5_get_msg_from_pkt
*===========================================================================
*/
IP_STATIC Ipeap_md5_msg*
ipeap_md5_get_msg_from_pkt(Ipeap_pkt* pkt)
{
return (Ipeap_md5_msg*)(pkt->data + pkt->start);
}
/*
*===========================================================================
* ipeap_md5_get_msg_max_size
*===========================================================================
*/
IP_STATIC Ip_u32
ipeap_md5_get_msg_max_size(Ipeap_pkt* pkt)
{
if ((pkt->end - pkt->start) >= pkt->max_len)
return 0;
return (Ip_u32)(pkt->max_len - (pkt->end - pkt->start));
}
/*
*===========================================================================
* ipeap_md5_get_msg_info
*===========================================================================
*/
IP_STATIC Ip_bool
ipeap_md5_get_msg_info(Ipeap_md5_msg* msg, Ipeap_md5_info* info)
{
/* Sanity check */
if ((msg->value_size + IPEAP_MD5_HEADER_LEN + 1) > ip_htons(msg->length))
return IP_FALSE;
info->valueLen = msg->value_size;
info->value = msg->value;
info->nameLen = ip_htons(msg->length) - (info->valueLen + IPEAP_MD5_HEADER_LEN + 1);
if (info->nameLen == 0)
info->name = IP_NULL;
else
info->name = info->value + info->valueLen;
return IP_TRUE;
}
/*
*===========================================================================
* ipeap_md5_load_config
*===========================================================================
* Description: Load configuration from system variables.
* Parameters:
* Returns:
* IPCOM_SUCCESS
* IPCOM_ERR_INVALID_ARG
*/
IP_STATIC Ip_err
ipeap_md5_load_config(
Ipeap_md5_ctx* md5_ctx)
{
Ip_err err = IPCOM_SUCCESS;
char* p = IP_NULL;
char* md5_pass_id = IP_NULL;
Ip_size_t n = 0;
n = sizeof(md5_ctx->secret);
#ifdef IPCOM_USE_KEY_DB
if(ipcom_sysvar_get_as_int("ipeap.privacy", 0)==1)
{
if(ipcom_sysvar_get_as_int("ipeap.privacy.retrieve.keydbid", 0)==1)
{
md5_pass_id = ipcom_sysvar_get("ipeap.md5.secret", IP_NULL, IP_NULL);
}
if ((err = ipcom_key_db_buf_get(md5_pass_id ? md5_pass_id : MD5_PASS_ID,(Ip_u8*)md5_ctx->secret, (int *)&n)) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "IPEAP-MD5 :: Unable to retrieve password ");
if(err == IPCOM_ERR_NOT_FOUND)
IPCOM_LOG1(ERR, "IPEAP-MD5 :: key ID %s does not exist",
md5_pass_id ? md5_pass_id : MD5_PASS_ID);
if(err == IPCOM_ERR_NO_MEMORY)
IPCOM_LOG0(ERR, "IPEAP-MD5 :: out of memory while retrieving ket id");
err= IPCOM_ERR_FAILED;
}
if(md5_pass_id)
ipcom_free(md5_pass_id);
return err;
}
else
#endif /* IPCOM_USE_KEY_DB */
p = ipcom_sysvar_get("ipeap.md5.secret", md5_ctx->secret, &n);
if (IP_NULL == p)
{
IPCOM_LOG0(ERR, "IPEAP-MD5 :: System variable 'ipeap.md5.secret' missing");
err = IPCOM_ERR_INVALID_ARG;
}
return err;
}
/*
*===========================================================================
* ipeap_md5_generate_challenge_response
*===========================================================================
* Description: Generate EAP MD5 challenge response
* Parameters:
* Returns:
* IP_TRUE - Challenge successfully generated
* IP_FALSE - Failed to generate challenge
*/
IP_STATIC Ip_bool
ipeap_md5_generate_challenge_response(
Ipeap_md5_ctx* md5_ctx,
Ipeap_md5_msg* in_msg,
Ipeap_md5_msg* out_msg,
Ip_u32 out_max)
{
Ip_bool success = IP_FALSE;
Ipeap_md5_info info = {0};
MD5_CTX md_ctx = {0};
if ((Ip_u32)(16 + out_msg->length + 1) > out_max)
{
IPCOM_LOG0(ERR, "EAP-MD5 :: Buffer too small for out packet");
}
else if (!ipeap_md5_get_msg_info(in_msg, &info))
{
IPCOM_LOG0(ERR, "EAP-MD5 :: Failed to decode request");
}
else
{
#ifdef OPENSSL_FIPS
if (FIPS_mode())
{
IPCOM_LOG0(WARNING, "ipeap : MD5 is not supported when FIPS mode is enabled!\n");
return IP_FALSE;
}
#endif
out_msg->value_size = (Ip_u8)16;
MD5_Init(&md_ctx);
MD5_Update(&md_ctx, &in_msg->id, 1);
MD5_Update(&md_ctx, md5_ctx->secret, ipcom_strlen(md5_ctx->secret));
MD5_Update(&md_ctx, info.value, info.valueLen);
MD5_Final(out_msg->value, &md_ctx);
success = IP_TRUE;
out_msg->length += 16 + 1;
}
return success;
}
/*
*===========================================================================
* ipeap_md5_init
*===========================================================================
* Description: Initialize EAP MD5 context.
* Parameters: ctx - The EAP MD5 context.
* Returns:
* IPCOM_SUCCESS
* IPCOM_ERR_NO_MEMORY
* IPCOM_ERR_INVALID_ARG
*/
IP_STATIC Ip_err
ipeap_md5_init(
Ipeap_ctx* ctx)
{
Ip_err err = IPCOM_SUCCESS;
Ipeap_md5_ctx* md5_ctx = IP_NULL;
md5_ctx = ipcom_calloc(1, sizeof(*md5_ctx));
if (IP_NULL == md5_ctx)
{
IPCOM_LOG1(CRIT, "%sEAP-MD5 :: Out of memory", ctx->syslog_prefix);
err = IPCOM_ERR_NO_MEMORY;
}
else if (IPCOM_SUCCESS != (err = ipeap_md5_load_config(md5_ctx)))
{
ipcom_free(md5_ctx);
IPCOM_LOG1(ERR, "%sEAP-MD5 :: Failed to load config", ctx->syslog_prefix);
}
else
{
ctx->mech_data = md5_ctx;
ctx->state = IPEAP_STATE_INIT;
}
return err;
}
/*
*===========================================================================
* ipeap_md5_free
*===========================================================================
* Description: Free EAP MD5 context.
* Parameters: ctx - The EAP context.
* Returns: IPCOM_SUCCESS
*/
IP_STATIC Ip_err
ipeap_md5_free(
Ipeap_ctx* ctx)
{
Ipeap_md5_ctx* md5_ctx = IP_NULL;
if ((ctx != IP_NULL) && (ctx->mech_data != IP_NULL))
{
md5_ctx = (Ipeap_md5_ctx*)ctx->mech_data;
ipcom_free(md5_ctx);
ctx->mech_data = IP_NULL;
}
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_md5_process_request
*===========================================================================
* Description: Process a request message.
* Parameters: ctx - The EAP context.
* in_pkt - The request packet (message).
* out_pkt - The created response packet (message).
* Returns:
* IPEAP_PENDING_SEND_OUT_PKT
* IPEAP_DROPPED_PKT
*/
IP_STATIC Ip_err
ipeap_md5_process_request(
Ipeap_ctx* ctx,
Ipeap_pkt* in_pkt,
Ipeap_pkt* out_pkt)
{
Ip_err err = IPEAP_PENDING_SEND_OUT_PKT;
Ipeap_md5_ctx* md5_ctx = IP_NULL;
Ipeap_md5_msg* in_msg = IP_NULL;
Ipeap_md5_msg* out_msg = IP_NULL;
Ip_u32 max_len = 0;
ctx->state = IPEAP_STATE_HANDSHAKE;
md5_ctx = (Ipeap_md5_ctx*)ctx->mech_data;
/* Convert packet to message */
in_msg = ipeap_md5_get_msg_from_pkt(in_pkt);
out_msg = ipeap_md5_get_msg_from_pkt(out_pkt);
max_len = ipeap_md5_get_msg_max_size(out_pkt);
if (max_len < IPEAP_MD5_HEADER_LEN)
{
IPCOM_LOG1(ERR, "%sEAP-MD5 :: Buffer too small for out packet", ctx->syslog_prefix);
err = IPEAP_DROPPED_PKT;
}
else if (in_msg->type != IPEAP_TYPE_MD5_CHALLENGE)
{
IPCOM_LOG1(ERR, "%sEAP-MD5 :: Only type MD5 challenge is supported", ctx->syslog_prefix);
err = IPEAP_DROPPED_PKT;
}
else
{
/* Response id and type always same as request */
out_msg->code = IPEAP_MSG_RESPONSE;
out_msg->id = in_msg->id;
out_msg->type = in_msg->type;
out_msg->length = IPEAP_MD5_HEADER_LEN;
if (!ipeap_md5_generate_challenge_response(md5_ctx, in_msg, out_msg, max_len))
{
IPCOM_LOG1(ERR, "%sEAP-MD5 :: Failed to generate challenge response", ctx->syslog_prefix);
err = IPEAP_DROPPED_PKT;
}
else
{
out_pkt->end = out_pkt->start + out_msg->length;
out_msg->length = ip_htons(out_msg->length);
err = IPEAP_PENDING_SEND_OUT_PKT;
}
}
return err;
}
/*
*===========================================================================
* ipeap_md5_process_success
*===========================================================================
* Description: Process a success message.
* Parameters: ctx - The EAP context.
* Returns:
* IPEAP_SUCCESS
*/
IP_STATIC Ip_err
ipeap_md5_process_success(
Ipeap_ctx* ctx)
{
ctx->state = IPEAP_STATE_AUTHENTICATED;
return IPEAP_SUCCESS;
}
/*
*===========================================================================
* ipeap_md5_process_msg
*===========================================================================
* Description: Process a message.
* Parameters: ctx - The EAP context.
* in_pkt - The request packet (message).
* out_pkt - The created response packet (message).
* Returns:
* IPEAP_SUCCESS
* IPEAP_PENDING_SEND_OUT_PKT
* IPEAP_FAILURE
* IPEAP_DROPPED_PKT
*/
IP_STATIC Ip_err
ipeap_md5_process_msg(
Ipeap_ctx* ctx,
Ipeap_pkt* in_pkt,
Ipeap_pkt* out_pkt)
{
Ip_err err = IPEAP_FAILURE;
Ipeap_md5_msg* msg = IP_NULL;
msg = ipeap_md5_get_msg_from_pkt(in_pkt);
/* Sanity check, always at least 4 bytes size */
if ((in_pkt->end - in_pkt->start) < 4)
{
IPCOM_LOG1(ERR, "%sEAP-MD5 :: Bad in packet", ctx->syslog_prefix);
return IPEAP_DROPPED_PKT;
}
switch (msg->code)
{
case IPEAP_MSG_REQUEST:
IPCOM_LOG1(DEBUG, "%sEAP-MD5 :: Received request message", ctx->syslog_prefix);
err = ipeap_md5_process_request(ctx, in_pkt, out_pkt);
break;
case IPEAP_MSG_RESPONSE:
IPCOM_LOG1(ERR, "%sEAP-MD5 :: Received response message, dropping message", ctx->syslog_prefix);
err = IPEAP_DROPPED_PKT;
break;
case IPEAP_MSG_FAILURE:
IPCOM_LOG1(ERR, "%sEAP-MD5 :: Received failure message, resetting state", ctx->syslog_prefix);
(void)ipeap_md5_free(ctx);
ctx->state = IPEAP_STATE_INIT;
ctx->cb = IP_NULL;
err = IPEAP_FAILURE;
break;
case IPEAP_MSG_SUCCESS:
IPCOM_LOG1(INFO, "%sEAP-MD5 :: Received EAP success", ctx->syslog_prefix);
err = ipeap_md5_process_success(ctx);
break;
default:
IPCOM_LOG2(ERR, "%sEAP-MD5 :: Received unknown message type: %d, dropping message", ctx->syslog_prefix, msg->code);
err = IPEAP_DROPPED_PKT;
break;
}
return err;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_md5_methods_get
*===========================================================================
*/
IP_PUBLIC Ipeap_methods*
ipeap_md5_methods_get(void)
{
return &ipeap_md5_methods;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,84 @@
/*
******************************************************************************
* INTERPEAK INTERNAL API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_md5.h,v $ $Revision: 1.2 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_md5.h,v $
* $Author: roger $ $Date: 2005-10-25 08:24:25 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#if !defined(IPEAP_MD5_H) && defined(IPEAP_USE_EAP_MD5)
#define IPEAP_MD5_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include "ipeap.h"
#include "ipeap_h.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_md5_methods_get
*===========================================================================
* Description: Return a structure containing pointer to all functions
* required by EAP.
* Parameters:
* Returns:
*/
IP_PUBLIC Ipeap_methods*
ipeap_md5_methods_get(void);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,947 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_peap.c,v $ $Revision: 1.11 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_peap.c,v $
* $Author: hchowdhu $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <openssl/ssl.h>
#include "ipeap.h"
#include "ipeap_h.h"
#include "ipeap_common_tls.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPEAP_PEAP_VERSION_MASK 3
#define IPEAP_PEAP_GET_VERSION(flags) (flags & IPEAP_PEAP_VERSION_MASK)
#define IPEAP_PEAP_SET_VERSION(flags, version) (((flags) & IPEAP_PEAP_VERSION_MASK) | (version))
#define IPEAP_PEAP_VERSION_NOTSET (-1)
/* Min/Max supported versions + defaults values if sysvar configs are absent or incorrect */
#define IPEAP_PEAP_MIN_VERSION 0
#define IPEAP_PEAP_MAX_VERSION 1
#define IPEAP_PEAP_START_MASK 0x20
#define IPEAP_PEAP_IS_START(flags) (flags & IPEAP_PEAP_START_MASK)
#define IPEAP_PEAP_V0_AVP_TYPE_ACK_RESULT 3
#define IPEAP_PEAP_V0_AVP_TYPE_STATUS_SUCCESS 1
#define IPEAP_PEAP_V0_AVP_TYPE_STATUS_FAILURE 2
#define IPEAP_PEAP_V1_PRF_LABEL_DEFAULT "client EAP encryption"
#define IPEAP_PEAP_V1_PRF_LABEL_ALT "client PEAP encryption"
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ipeap_peap_ctx_st
{
int min_ver, max_ver, curr_ver; /* Min/Max/negotiated version */
Ipeap_tls_suppl_ctx* tls_ctx;
Ipeap_ctx* phase2_ctx;
char peap_prefix[16];
Ip_u8 msg_id; /* msg Id of last received request */
char peapv1_prf_label[32];
} Ipeap_peap_ctx;
typedef struct Ipeap_peap_msg_st
{
Ip_u8 code;
Ip_u8 id;
Ip_u16 length;
Ip_u8 type;
Ip_u8 flags; /* flags & version */
Ip_u8 data[1];
} Ipeap_peap_msg;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_STATIC Ip_err ipeap_peap_suppl_process_msg(struct Ipeap_ctx_st *ctx,
struct Ipeap_pkt_st *in_pkt,
struct Ipeap_pkt_st *reply_pkt);
IP_STATIC Ip_err ipeap_peap_suppl_init(struct Ipeap_ctx_st *ctx);
IP_STATIC Ip_err ipeap_peap_suppl_free(Ipeap_ctx *ctx);
IP_STATIC Ip_err ipeap_peap_suppl_get_key(struct Ipeap_ctx_st* ctx, Ip_u8* key, int key_len);
IP_STATIC Ip_err ipeap_peap_handle_v0(Ipeap_ctx *ctx, Ipeap_pkt *in_pkt, Ipeap_pkt *out_pkt);
IP_STATIC Ip_err ipeap_peap_handle_v1(Ipeap_ctx *ctx, Ipeap_pkt *in_pkt, Ipeap_pkt *out_pkt);
IP_STATIC Ip_err ipeap_peap_check_ver(Ipeap_ctx *ctx, Ipeap_pkt *in_pkt, Ipeap_pkt *out_pkt);
IP_STATIC Ip_err ipeap_peap_get_avp(Ip_u8 *buf, int buf_len, Ip_bool *mandatory, Ip_u16 *type, Ip_u8 *avp, Ip_u16 *avp_len);
IP_STATIC Ip_err ipeap_peap_put_avp(Ip_u8 *buf, int buf_len, Ip_bool mandatory, Ip_u16 type, Ip_u8 *avp, Ip_u16 avp_len);
IP_PUBLIC Ip_err ipeap_peap_suppl_display_status(struct Ipeap_ctx_st* ctx, char *str);
IP_STATIC Ip_err ipeap_peap_handle_user_input(Ipeap_ctx* ctx,
Ipeap_user_input* ui,
struct Ipeap_pkt_st *reply_pkt);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
IP_STATIC Ipeap_methods ipeap_peap_suppl_methods =
{
ipeap_peap_suppl_process_msg,
ipeap_peap_suppl_init,
ipeap_peap_suppl_free,
ipeap_peap_suppl_get_key,
ipeap_peap_handle_user_input,
ipeap_peap_suppl_display_status,
IP_NULL
};
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_peap_load_config
*===========================================================================
* Description: Load configuration from system variables.
* Parameters:
* Returns:
* IPCOM_SUCCESS
* IPCOM_ERR_INVALID_ARG
*/
IP_STATIC Ip_err
ipeap_peap_load_config(Ipeap_peap_ctx* peap_ctx)
{
Ip_err err = IPCOM_SUCCESS;
Ip_size_t len = sizeof(peap_ctx->peapv1_prf_label);
if (!ipcom_sysvar_get("ipeap.peap.v1.prf_label", peap_ctx->peapv1_prf_label, &len)) {
IPCOM_LOG1(WARNING, "%sfailed to retrieve ipeap.peap.v1.prf_label sysvar", peap_ctx->peap_prefix);
err = IPCOM_ERR_FAILED;
} else if ((ipcom_strcmp(peap_ctx->peapv1_prf_label, IPEAP_PEAP_V1_PRF_LABEL_DEFAULT) != 0) &&
(ipcom_strcmp(peap_ctx->peapv1_prf_label, IPEAP_PEAP_V1_PRF_LABEL_ALT) != 0)) {
IPCOM_LOG2(WARNING, "%sInvalid ipeap.peap.v1.prf_label sysvar value: \"%s\"", peap_ctx->peap_prefix, peap_ctx->peapv1_prf_label);
err = IPCOM_ERR_FAILED;
}
if (err == IPCOM_ERR_FAILED) {
ipcom_strncpy(peap_ctx->peapv1_prf_label, IPEAP_PEAP_V1_PRF_LABEL_DEFAULT, sizeof(peap_ctx->peapv1_prf_label));
err = IPCOM_SUCCESS;
}
IPCOM_LOG2(INFO, "%sSetting peapv1 prf label to: \"%s\"", peap_ctx->peap_prefix, peap_ctx->peapv1_prf_label);
peap_ctx->min_ver = ipcom_sysvar_get_as_int("ipeap.peap.min_version", IPEAP_PEAP_MIN_VERSION);
peap_ctx->max_ver = ipcom_sysvar_get_as_int("ipeap.peap.max_version", IPEAP_PEAP_MAX_VERSION);
if ((peap_ctx->min_ver < IPEAP_PEAP_MIN_VERSION) ||
(peap_ctx->max_ver > IPEAP_PEAP_MAX_VERSION) ||
(peap_ctx->min_ver > peap_ctx->max_ver)) {
IPCOM_LOG3(ERR, "%sInvalid version configuration, using default values: (min_ver=%d, max_ver=%d)",
peap_ctx->peap_prefix, IPEAP_PEAP_MIN_VERSION, IPEAP_PEAP_MAX_VERSION);
peap_ctx->min_ver = IPEAP_PEAP_MIN_VERSION;
peap_ctx->max_ver = IPEAP_PEAP_MAX_VERSION;
err = IPCOM_ERR_INVALID_ARG;
}
return err;
}
/*
*===========================================================================
* ipeap_ttls_suppl_process_msg
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_peap_suppl_process_msg(Ipeap_ctx *ctx, Ipeap_pkt *in_pkt, Ipeap_pkt *out_pkt)
{
Ip_err rc = IPCOM_SUCCESS;
Ipeap_tls_msg *msg;
Ipeap_peap_ctx* peap_ctx;
msg = IPEAP_PKT2TLSMSG(in_pkt);
peap_ctx = (Ipeap_peap_ctx*)ctx->mech_data;
ip_assert(peap_ctx);
ip_assert(peap_ctx->tls_ctx);
switch(msg->code)
{
case IPEAP_MSG_REQUEST:
if (msg->type != IPEAP_TYPE_PEAP)
{
IPCOM_LOG1(CRIT, "%s: Not a PEAP message!", peap_ctx->peap_prefix);
return IPEAP_DROPPED_PKT;
}
/* 1st we need to make sure we support the PEAP version sent in the 1st EAP-REQUEST
* or negotiate a version
*/
rc = ipeap_peap_check_ver(ctx, in_pkt, out_pkt);
if (rc != IPCOM_SUCCESS)
return rc;
rc = ipeap_common_tls_handle_frag_and_handshake(ctx, peap_ctx->tls_ctx, in_pkt, out_pkt);
switch(rc)
{
case IPEAP_TLS_HANDSHAKE_COMPLETE:
/* Send empty response packet, wait for EAP packets over the TLS tunnel */
if(IPEAP_PKT_GET_SPACE_LEFT(out_pkt) < 6)
{
IPCOM_LOG2(ERR, "%stoo small out pkt: space left: %d", peap_ctx->peap_prefix, IPEAP_PKT_GET_SPACE_LEFT(out_pkt));
return IPCOM_ERR_INVALID_ARG;
}
rc = ipeap_tls_pkt_set_header(out_pkt, IPEAP_PKT_RESPONSE, msg->id, 6, ctx->meth_id, (Ip_u8)peap_ctx->curr_ver);
if(rc != IPCOM_SUCCESS)
return rc;
out_pkt->end += 6;
return IPEAP_PENDING_SEND_OUT_PKT;
case IPEAP_TLS_DATA_AVAILABLE:
/* An EAP packet is received over the TLS tunnel. Process */
switch (peap_ctx->curr_ver) {
case 0:
return ipeap_peap_handle_v0(ctx, in_pkt, out_pkt);
case 1:
return ipeap_peap_handle_v1(ctx, in_pkt, out_pkt);
default:
IPCOM_LOG2(CRIT, "%sunexpected curr_ver %d", peap_ctx->peap_prefix, peap_ctx->curr_ver);
return IPEAP_DROPPED_PKT;
}
default:
{
/* Need to set the proper flags */
Ipeap_tls_msg* msg = IPEAP_PKT2TLSMSG(out_pkt);
msg->flags = (Ip_u8)IPEAP_PEAP_SET_VERSION(msg->flags, peap_ctx->curr_ver);
break;
}
}
break;
case IPEAP_MSG_RESPONSE:
IPCOM_LOG1(ERR, "%sreceived response msg, dropping msg", peap_ctx->peap_prefix);
return IPEAP_DROPPED_PKT;
case IPEAP_MSG_FAILURE:
IPCOM_LOG1(INFO, "%sreceived EAP failure", peap_ctx->peap_prefix);
return IPEAP_FAILURE;
case IPEAP_MSG_SUCCESS:
ctx->state = IPEAP_STATE_AUTHENTICATED;
IPCOM_LOG1(INFO, "%sreceived EAP success", peap_ctx->peap_prefix);
return IPEAP_SUCCESS;
default:
IPCOM_LOG1(ERR, "%sreceived unknown msg type: %d, dropping msg", peap_ctx->peap_prefix);
return IPEAP_DROPPED_PKT;
}
return rc;
}
/*
*===========================================================================
* ipeap_peap_suppl_init
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_peap_suppl_init(Ipeap_ctx *eap_ctx)
{
Ipeap_peap_ctx *peap_ctx;
const char* peap_prefix = "PEAP: ";
peap_ctx = ipcom_malloc(sizeof(Ipeap_peap_ctx));
if(!peap_ctx)
return IPCOM_ERR_NO_MEMORY;
ipcom_memset(peap_ctx, 0, sizeof(Ipeap_peap_ctx));
ipeap_peap_load_config(peap_ctx);
peap_ctx->curr_ver = IPEAP_PEAP_VERSION_NOTSET;
eap_ctx->mech_data = peap_ctx;
strncpy(peap_ctx->peap_prefix, peap_prefix, sizeof(peap_ctx->peap_prefix));
peap_ctx->tls_ctx = ipeap_common_tls_ctx_new();
if(!peap_ctx->tls_ctx)
{
ipcom_free(peap_ctx);
return IPCOM_ERR_FAILED;
}
peap_ctx->phase2_ctx = ipeap_ctx_new(IPEAP_MODE_SUPPLICANT);
if(!peap_ctx->phase2_ctx)
{
IPCOM_LOG1(ERR, "%sfailed to allocate inner EAP context", peap_ctx->peap_prefix);
(void)ipeap_peap_suppl_free(eap_ctx);
return IPCOM_ERR_FAILED;
}
if(ipcom_strlen(eap_ctx->syslog_prefix)+ipcom_strlen(peap_prefix) < sizeof(eap_ctx->syslog_prefix))
{
ipcom_strcpy(peap_ctx->phase2_ctx->syslog_prefix, eap_ctx->syslog_prefix);
ipcom_strcat(peap_ctx->phase2_ctx->syslog_prefix, peap_prefix);
}
else
{
ipcom_strcpy(peap_ctx->phase2_ctx->syslog_prefix, "<trunc>");
ipcom_strcat(peap_ctx->phase2_ctx->syslog_prefix, peap_prefix);
}
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_peap_suppl_free
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_peap_suppl_free(Ipeap_ctx *ctx)
{
Ipeap_peap_ctx* peap_ctx = ctx->mech_data;
ip_assert(peap_ctx);
if(peap_ctx)
{
if(peap_ctx->phase2_ctx)
ipeap_ctx_free(peap_ctx->phase2_ctx);
if(peap_ctx->tls_ctx)
ipeap_common_tls_ctx_free(peap_ctx->tls_ctx);
ipcom_free(peap_ctx);
}
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_peap_handle_v0
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_peap_handle_v0(Ipeap_ctx *ctx, Ipeap_pkt *in_pkt, Ipeap_pkt *out_pkt)
{
Ip_err rc = IPCOM_ERR_FAILED;
Ipeap_tls_msg *msg;
Ipeap_msg *inner_msg;
Ipeap_msg *inner_out_msg;
Ipeap_pkt* tunneled_in_pkt = IP_NULL;
Ipeap_pkt* tunneled_out_pkt = IP_NULL;
int ssl_rc;
Ip_bool reconstruct_hdr = IP_TRUE;
Ipeap_peap_ctx *peap_ctx;
peap_ctx = (Ipeap_peap_ctx*)ctx->mech_data;
msg = IPEAP_PKT2TLSMSG(in_pkt);
tunneled_in_pkt = ipeap_pkt_new(IPEAP_MTU);
if(!tunneled_in_pkt)
{
IPCOM_LOG1(ERR, "%sout of memory", peap_ctx->peap_prefix);
return IPCOM_ERR_NO_MEMORY;
}
tunneled_out_pkt = ipeap_pkt_new(IPEAP_MTU);
if(!tunneled_out_pkt)
{
IPCOM_LOG1(ERR, "%sout of memory", peap_ctx->peap_prefix);
rc = IPCOM_ERR_NO_MEMORY;
goto cleanup;
}
/* In PEAPv0 the code, type and identifier fields are omitted in all packets
* except for EAP extension packets (type 33). Leave some room in
* tunneled_in_pkt to enable the missing field to be re-created from the
* outer packet. */
tunneled_in_pkt->start += 4;
tunneled_in_pkt->end += 4;
ssl_rc = SSL_read(peap_ctx->tls_ctx->ssl,
IPEAP_PKT_GET_END_PTR(tunneled_in_pkt),
IPEAP_PKT_GET_SPACE_LEFT(tunneled_in_pkt));
if(ssl_rc < 0)
{
IPCOM_LOG1(ERR, "%sfailed to read inner EAP packet", peap_ctx->peap_prefix);
goto cleanup;
}
tunneled_in_pkt->end += ssl_rc;
inner_msg = IPEAP_PKT2MSG(tunneled_in_pkt);
if(IPEAP_PKT_GET_LEN(tunneled_in_pkt)>=5)
{
/* Assume a full header is received and make some checks if this is the case */
if(inner_msg->code == IPEAP_PKT_REQUEST && inner_msg->type == IPEAP_TYPE_EXTENSIONS)
reconstruct_hdr = IP_FALSE;
/* Freeradius sends a full request-identity in PEAPv0 */
else if(IPEAP_PKT_GET_LEN(tunneled_in_pkt)==5
&& inner_msg->code == IPEAP_PKT_REQUEST
&& inner_msg->type == IPEAP_TYPE_IDENTITY)
{
reconstruct_hdr = IP_FALSE;
}
}
if(reconstruct_hdr)
{
tunneled_in_pkt->start -= 4;
inner_msg = IPEAP_PKT2MSG(tunneled_in_pkt);
inner_msg->code = msg->code;
inner_msg->id = msg->id;
inner_msg->length = ip_htons(ssl_rc+4);
}
IPCOM_LOG5(DEBUG2, "%sreceived inner packet, code: %d, id: %d, len: %d, type: %d",
peap_ctx->peap_prefix, inner_msg->code, inner_msg->id, ip_ntohs(inner_msg->length), inner_msg->type);
/* Process pkt */
if(inner_msg->type != IPEAP_TYPE_EXTENSIONS)
{
rc = ipeap_process_pkt(peap_ctx->phase2_ctx, tunneled_in_pkt, tunneled_out_pkt);
tunneled_out_pkt->start += 4;
}
else
{
/* Handle extensions packet */
Ip_bool mandatory;
Ip_u16 avp_type;
Ip_u16 avp_len;
Ip_u16 status;
Ip_u8* avp_buf;
int avp_buf_len;
avp_buf = &IPEAP_PKT_GET_START_PTR(tunneled_in_pkt)[5];
avp_buf_len = IPEAP_PKT_GET_LEN(tunneled_in_pkt)-5;
avp_len = sizeof(status);
if(ipeap_peap_get_avp(avp_buf, avp_buf_len, &mandatory, &avp_type, (Ip_u8*)&status, &avp_len) != IPCOM_SUCCESS)
{
IPCOM_LOG1(ERR, "%sfailed to unpack AVP in extension packet", peap_ctx->peap_prefix);
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
if(avp_type != IPEAP_PEAP_V0_AVP_TYPE_ACK_RESULT)
{
IPCOM_LOG2(ERR, "%sUnexpected AVP type received in extension packet: %d", peap_ctx->peap_prefix, avp_type);
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
IPCOM_LOG2(DEBUG, "%sReceived extension packet, status: %d", peap_ctx->peap_prefix, ip_ntohs(status));
switch(ip_ntohs(status))
{
case IPEAP_PEAP_V0_AVP_TYPE_STATUS_SUCCESS:
case IPEAP_PEAP_V0_AVP_TYPE_STATUS_FAILURE:
inner_out_msg = IPEAP_PKT2MSG(tunneled_out_pkt);
(void)ipeap_pkt_set_header(tunneled_out_pkt, IPEAP_MSG_RESPONSE, inner_msg->id, 11, IPEAP_TYPE_EXTENSIONS);
tunneled_out_pkt->end += 5;
if(ipeap_peap_put_avp(inner_out_msg->data, IPEAP_PKT_GET_SPACE_LEFT(tunneled_out_pkt), mandatory,
avp_type, (Ip_u8*)&status, 2) != IPCOM_SUCCESS)
{
IPCOM_LOG1(ERR, "%sfailed to put status AVP in extension packet", peap_ctx->peap_prefix);
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
tunneled_out_pkt->end += 6;
rc = IPEAP_PENDING_SEND_OUT_PKT;
break;
default:
IPCOM_LOG2(ERR, "%sUnexpected status received in extension packet: %d", peap_ctx->peap_prefix, status);
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
}
if(rc == IPEAP_PENDING_SEND_OUT_PKT)
{
ssl_rc = SSL_write(peap_ctx->tls_ctx->ssl,
IPEAP_PKT_GET_START_PTR(tunneled_out_pkt),
IPEAP_PKT_GET_LEN(tunneled_out_pkt));
if(ssl_rc != IPEAP_PKT_GET_LEN(tunneled_out_pkt))
{
IPCOM_LOG3(ERR, "%sfailed to write inner EAP packet, len: %d, ssl_rc: %d",
peap_ctx->peap_prefix, IPEAP_PKT_GET_LEN(tunneled_out_pkt), ssl_rc);
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
rc = ipeap_common_tls_make_out_frag_pkt(peap_ctx->tls_ctx, out_pkt, IPEAP_MSG_RESPONSE, msg->id, IPEAP_TYPE_PEAP);
}
cleanup:
if(tunneled_in_pkt)
ipeap_pkt_free(tunneled_in_pkt);
if(tunneled_out_pkt)
ipeap_pkt_free(tunneled_out_pkt);
return rc;
}
/*
*===========================================================================
* ipeap_peap_handle_v1
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_peap_handle_v1(Ipeap_ctx *ctx, Ipeap_pkt *in_pkt, Ipeap_pkt *out_pkt)
{
Ip_err rc = IPCOM_ERR_FAILED;
Ipeap_tls_msg *in_msg, *out_msg;
Ipeap_msg *inner_msg;
Ipeap_pkt* tunneled_in_pkt = IP_NULL;
Ipeap_pkt* tunneled_out_pkt = IP_NULL;
int ssl_rc;
Ipeap_peap_ctx *peap_ctx;
peap_ctx = (Ipeap_peap_ctx*)ctx->mech_data;
in_msg = IPEAP_PKT2TLSMSG(in_pkt);
peap_ctx->msg_id = in_msg->id; /* Save msg id for when we send response */
tunneled_in_pkt = ipeap_pkt_new(IPEAP_MTU);
if(!tunneled_in_pkt)
{
IPCOM_LOG1(ERR, "%sout of memory", peap_ctx->peap_prefix);
return IPCOM_ERR_NO_MEMORY;
}
tunneled_out_pkt = ipeap_pkt_new(IPEAP_MTU);
if(!tunneled_out_pkt)
{
IPCOM_LOG1(ERR, "%sout of memory", peap_ctx->peap_prefix);
rc = IPCOM_ERR_NO_MEMORY;
goto cleanup;
}
ssl_rc = SSL_read(peap_ctx->tls_ctx->ssl,
IPEAP_PKT_GET_END_PTR(tunneled_in_pkt),
IPEAP_PKT_GET_SPACE_LEFT(tunneled_in_pkt));
if(ssl_rc < 0)
{
IPCOM_LOG1(ERR, "%sfailed to read inner EAP packet", peap_ctx->peap_prefix);
goto cleanup;
}
tunneled_in_pkt->end += ssl_rc;
inner_msg = IPEAP_PKT2MSG(tunneled_in_pkt);
IPCOM_LOG5(DEBUG2, "%sreceived inner packet, code: %d, id: %d, len: %d, type: %d",
peap_ctx->peap_prefix, inner_msg->code, inner_msg->id, ip_ntohs(inner_msg->length), inner_msg->type);
/* Process pkt */
rc = ipeap_process_pkt(peap_ctx->phase2_ctx, tunneled_in_pkt, tunneled_out_pkt);
if(rc == IPEAP_PENDING_SEND_OUT_PKT)
{
ssl_rc = SSL_write(peap_ctx->tls_ctx->ssl,
IPEAP_PKT_GET_START_PTR(tunneled_out_pkt),
IPEAP_PKT_GET_LEN(tunneled_out_pkt));
if(ssl_rc != IPEAP_PKT_GET_LEN(tunneled_out_pkt))
{
IPCOM_LOG3(ERR, "%sfailed to write inner EAP packet, len: %d, ssl_rc: %d",
peap_ctx->peap_prefix, IPEAP_PKT_GET_LEN(tunneled_out_pkt), ssl_rc);
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
rc = ipeap_common_tls_make_out_frag_pkt(peap_ctx->tls_ctx, out_pkt, IPEAP_MSG_RESPONSE, in_msg->id, IPEAP_TYPE_PEAP);
out_msg = IPEAP_PKT2TLSMSG(out_pkt);
out_msg->flags = (Ip_u8)IPEAP_PEAP_SET_VERSION(out_msg->flags, peap_ctx->curr_ver);
} else if (rc == IPEAP_SUCCESS) {
/* for PEAPv1, we need to monitor for an inner EAP success and reply with an unencrypted (non-tunneled) response */
if(IPEAP_PKT_GET_SPACE_LEFT(out_pkt) < 6)
{
IPCOM_LOG2(ERR, "%stoo small out pkt: space left: %d", peap_ctx->peap_prefix, IPEAP_PKT_GET_SPACE_LEFT(out_pkt));
return IPCOM_ERR_INVALID_ARG;
}
rc = ipeap_tls_pkt_set_header(out_pkt, IPEAP_PKT_RESPONSE, in_msg->id, 6, ctx->meth_id, (Ip_u8)peap_ctx->curr_ver);
if(rc != IPCOM_SUCCESS)
return rc;
out_pkt->end += 6;
rc = IPEAP_PENDING_SEND_OUT_PKT;
}
cleanup:
if(tunneled_in_pkt)
ipeap_pkt_free(tunneled_in_pkt);
if(tunneled_out_pkt)
ipeap_pkt_free(tunneled_out_pkt);
return rc;
}
/*
*===========================================================================
* ipeap_peap_check_ver
*===========================================================================
* Description:
* Checks the version and performs version negotiation if necessary.
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_peap_check_ver(Ipeap_ctx *ctx, Ipeap_pkt *in_pkt, Ipeap_pkt *out_pkt)
{
Ip_err rc = IPCOM_ERR_FAILED;
Ipeap_peap_msg *msg;
Ipeap_peap_ctx *peap_ctx;
int version;
const char* peapv0_prefix = "PEAPv0: ";
const char* peapv1_prefix = "PEAPv1: ";
const char* peap_prefix;
peap_ctx = (Ipeap_peap_ctx*)ctx->mech_data;
msg = (Ipeap_peap_msg *)IPEAP_PKT2MSG(in_pkt);
version = IPEAP_PEAP_GET_VERSION(msg->flags);
if (peap_ctx->curr_ver != IPEAP_PEAP_VERSION_NOTSET) {
/* A version was negotiated/set, so verify we are still using this version */
if (version != peap_ctx->curr_ver) {
IPCOM_LOG3(CRIT, "%s: ipeap_peap_check_ver :: wrong PEAP version %d (expecting %d)!",
peap_ctx->peap_prefix, version, peap_ctx->curr_ver);
rc = IPEAP_DROPPED_PKT;
} else {
rc = IPCOM_SUCCESS;
}
return rc;
}
/* We never negotiated/set a version, so do so now */
if (msg->code != IPEAP_MSG_REQUEST)
{
IPCOM_LOG1(CRIT, "%s: ipeap_peap_check_ver :: Got non EAP REQUEST before negotiating PEAP version!", peap_ctx->peap_prefix);
return IPEAP_DROPPED_PKT;
}
if ((version >= peap_ctx->min_ver) && (version <= peap_ctx->max_ver)) {
peap_ctx->curr_ver = version;
rc = IPCOM_SUCCESS;
if (peap_ctx->curr_ver == 0)
peap_prefix = peapv0_prefix;
else if (peap_ctx->curr_ver == 1)
peap_prefix = peapv1_prefix;
else
return rc;
strncpy(peap_ctx->peap_prefix, peap_prefix, sizeof(peap_ctx->peap_prefix));
if(ipcom_strlen(ctx->syslog_prefix)+ipcom_strlen(peap_prefix) < sizeof(ctx->syslog_prefix))
{
ipcom_strcpy(peap_ctx->phase2_ctx->syslog_prefix, ctx->syslog_prefix);
ipcom_strcat(peap_ctx->phase2_ctx->syslog_prefix, peap_prefix);
}
else
{
ipcom_strcpy(peap_ctx->phase2_ctx->syslog_prefix, "<trunc>");
ipcom_strcat(peap_ctx->phase2_ctx->syslog_prefix, peap_prefix);
}
return rc;
}
/* server version not supported */
if (version < peap_ctx->min_ver) {
/* Since according to "draft-josefsson-pppext-eap-tls-eap-05.txt",
* the server sends us its highest supported version,
* in this case we will not be able to come to an agreement so
* we send a NAK suggesting alternate methods
*/
if(IPEAP_PKT_GET_SPACE_LEFT(out_pkt) < 3)
{
IPCOM_LOG2(ERR, "%stoo small out pkt: space left: %d", peap_ctx->peap_prefix, IPEAP_PKT_GET_SPACE_LEFT(out_pkt));
return IPCOM_ERR_INVALID_ARG;
}
IPCOM_LOG3(ERR, "%sserver PEAP version %d lower than min supported version %d. Sending NAK.",
peap_ctx->peap_prefix, version, peap_ctx->min_ver);
ipeap_mech_type_set_enabled(ctx, msg->type, IP_FALSE); /* disable this EAP temporarily for this ctx to avoid endless negotiation loop */
ipeap_make_nak_response(ctx, in_pkt, out_pkt);
ipeap_mech_type_set_enabled(ctx, msg->type, IP_TRUE); /* Reenable this EAP */
return IPEAP_PENDING_SEND_OUT_PKT;
}
/* Server's version is higher than our max, so indicate highest version we support */
if(IPEAP_PKT_GET_SPACE_LEFT(out_pkt) < 6)
{
IPCOM_LOG2(ERR, "%stoo small out pkt: space left: %d", peap_ctx->peap_prefix, IPEAP_PKT_GET_SPACE_LEFT(out_pkt));
return IPCOM_ERR_INVALID_ARG;
}
rc = ipeap_tls_pkt_set_header(out_pkt, IPEAP_PKT_RESPONSE, msg->id, 6, ctx->meth_id, (Ip_u8)peap_ctx->max_ver);
if(rc != IPCOM_SUCCESS)
return rc;
out_pkt->end += 6;
rc = IPEAP_PENDING_SEND_OUT_PKT;
return rc;
}
/*
*===========================================================================
* ipeap_peap_suppl_get_key
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_peap_suppl_get_key(struct Ipeap_ctx_st* ctx, Ip_u8* key, int key_len)
{
Ipeap_peap_ctx* peap_ctx;
peap_ctx = (Ipeap_peap_ctx*)ctx->mech_data;
if (peap_ctx->curr_ver == 0) {
return ipeap_tls_common_generate_key(peap_ctx->tls_ctx, "client EAP encryption", key, key_len);
}
return ipeap_tls_common_generate_key(peap_ctx->tls_ctx, peap_ctx->peapv1_prf_label, key, key_len);
}
/*
*===========================================================================
* ipeap_peap_get_avp
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_peap_get_avp(Ip_u8 *buf, int buf_len, Ip_bool *mandatory, Ip_u16 *type, Ip_u8 *avp, Ip_u16 *avp_len)
{
Ip_u16 tmp_type;
Ip_u16 tmp_len;
if(buf_len < 4)
return IPCOM_ERR_INVALID_ARG;
tmp_len = IP_GET_NTOHS(buf+2);
if(tmp_len > *avp_len)
return IPCOM_ERR_INVALID_ARG;
if(tmp_len > (buf_len-4))
return IPCOM_ERR_FAILED;;
if(*buf & 0x80)
*mandatory = IP_TRUE;
else
*mandatory = IP_FALSE;
tmp_type = IP_GET_NTOHS(buf);
tmp_type = (Ip_u16)(tmp_type & 0x3fff); /* Remove mandatory and reserved bits */
*type = tmp_type;
*avp_len = tmp_len;
ipcom_memcpy(avp, buf+4, tmp_len);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_peap_put_avp
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_peap_put_avp(Ip_u8 *buf, int buf_len, Ip_bool mandatory, Ip_u16 type, Ip_u8 *avp, Ip_u16 avp_len)
{
if(buf_len < (avp_len+4))
return IPCOM_ERR_INVALID_ARG;
ipcom_memset(buf, 0, (Ip_size_t)(avp_len+4));
IP_SET_HTONS(buf, type);
if(mandatory)
buf[0] |= 0x80;
IP_SET_HTONS(buf+2, avp_len);
ipcom_memcpy(buf+4,avp, avp_len);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_peap_handle_user_input
*===========================================================================
*/
IP_STATIC Ip_err
ipeap_peap_handle_user_input(Ipeap_ctx* ctx, Ipeap_user_input* ui, Ipeap_pkt* out_pkt) {
Ip_err rc = IPCOM_ERR_FAILED;
Ipeap_tls_msg *out_msg;
Ipeap_pkt* tunneled_out_pkt = IP_NULL;
int ssl_rc;
Ipeap_peap_ctx* peap_ctx = (Ipeap_peap_ctx*)ctx->mech_data;
if (peap_ctx->curr_ver != 1) {
IPCOM_LOG1(ERR, "%s doesn't support user input", peap_ctx->peap_prefix);
return IPCOM_ERR_FAILED;
}
if (!peap_ctx->phase2_ctx) {
IPCOM_LOG1(ERR, "%sNo inner type to handle user input", peap_ctx->peap_prefix);
return IPCOM_ERR_FAILED;
}
tunneled_out_pkt = ipeap_pkt_new(IPEAP_MTU);
if(!tunneled_out_pkt)
{
IPCOM_LOG1(ERR, "%sout of memory", peap_ctx->peap_prefix);
rc = IPCOM_ERR_NO_MEMORY;
goto cleanup;
}
rc = ipeap_handle_user_input(peap_ctx->phase2_ctx, ui, tunneled_out_pkt);
if (rc != IPEAP_PENDING_SEND_OUT_PKT)
goto cleanup;
ssl_rc = SSL_write(peap_ctx->tls_ctx->ssl,
IPEAP_PKT_GET_START_PTR(tunneled_out_pkt),
IPEAP_PKT_GET_LEN(tunneled_out_pkt));
if(ssl_rc != IPEAP_PKT_GET_LEN(tunneled_out_pkt))
{
IPCOM_LOG3(ERR, "%sfailed to write inner EAP packet, len: %d, ssl_rc: %d",
peap_ctx->peap_prefix, IPEAP_PKT_GET_LEN(tunneled_out_pkt), ssl_rc);
rc = IPCOM_ERR_FAILED;
goto cleanup;
}
rc = ipeap_common_tls_make_out_frag_pkt(peap_ctx->tls_ctx, out_pkt, IPEAP_MSG_RESPONSE, peap_ctx->msg_id, IPEAP_TYPE_PEAP);
out_msg = IPEAP_PKT2TLSMSG(out_pkt);
out_msg->flags = (Ip_u8)IPEAP_PEAP_SET_VERSION(out_msg->flags, peap_ctx->curr_ver);
cleanup:
if(tunneled_out_pkt)
ipeap_pkt_free(tunneled_out_pkt);
return rc;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_peap_suppl_methods_get
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ipeap_methods*
ipeap_peap_suppl_methods_get(void)
{
return &ipeap_peap_suppl_methods;
}
/*
*===========================================================================
* ipeap_peap_suppl_display_status
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipeap_peap_suppl_display_status(struct Ipeap_ctx_st* ctx, char *str) {
Ipeap_peap_ctx* peap_ctx;
peap_ctx = (Ipeap_peap_ctx*)ctx->mech_data;
ipcom_printf("%s", peap_ctx->peap_prefix);
if (peap_ctx->phase2_ctx) {
ipeap_display_status((struct Ipeap_ctx_st*)peap_ctx->phase2_ctx, "Inner ");
} else
ipcom_printf("INNER EAP NOT CREATED\n");
return IPCOM_SUCCESS;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,153 @@
/*
******************************************************************************
* INTERPEAK INTERNAL API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_sim.h,v $ $Revision: 1.2 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_sim.h,v $
* $Author: roger $ $Date: 2005-10-25 08:24:25 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#if !defined(IPEAP_SIM_H) && defined(IPEAP_USE_EAP_SIM)
#define IPEAP_SIM_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include "ipeap.h"
#include "ipeap_h.h"
#include "ipeap_sim_util.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPEAP_SIM_VERSION 1
/* Non-skippable attributes (0-127) */
#define IPEAP_SIM_AT_RAND 1
#define IPEAP_SIM_AT_PADDING 6 /* only encrypted */
#define IPEAP_SIM_AT_NONCE_MT 7 /* only send */
#define IPEAP_SIM_AT_PERMANENT_ID_REQ 10
#define IPEAP_SIM_AT_MAC 11
#define IPEAP_SIM_AT_NOTIFICATION 12
#define IPEAP_SIM_AT_ANY_ID_REQ 13
#define IPEAP_SIM_AT_IDENTITY 14 /* only send */
#define IPEAP_SIM_AT_VERSION_LIST 15
#define IPEAP_SIM_AT_SELECTED_VERSION 16
#define IPEAP_SIM_AT_FULLAUTH_ID_REQ 17
#define IPEAP_SIM_AT_COUNTER 19 /* only encrypted */
#define IPEAP_SIM_AT_COUNTER_TOO_SMALL 20 /* only encrypted */
#define IPEAP_SIM_AT_NONCE_S 21 /* only encrypted */
#define IPEAP_SIM_AT_CLIENT_ERROR_CODE 22 /* only send */
#define IPEAP_SIM_AT_IV 129
#define IPEAP_SIM_AT_ENCR_DATA 130
#define IPEAP_SIM_AT_NEXT_PSEUDONYM 132 /* only encrypted */
#define IPEAP_SIM_AT_NEXT_REAUTH_ID 133 /* only encrypted */
#define IPEAP_SIM_AT_RESULT_IND 135
/* Subtypes */
#define IPEAP_SIM_SUBTYPE_START 10
#define IPEAP_SIM_SUBTYPE_CHALLENGE 11
#define IPEAP_SIM_SUBTYPE_NOTIFICATION 12
#define IPEAP_SIM_SUBTYPE_REAUTHENTICATION 13
#define IPEAP_SIM_SUBTYPE_CLIENT_ERROR 14
/* AT_CLIENT_ERROR_CODE values */
#define IPEAP_SIM_UNABLE_TO_PROCESS_PACKET 0
#define IPEAP_SIM_UNSUPPORTED_VERSION 1
#define IPEAP_SIM_INSUFFICIENT_NUM_OF_CHAL 2
#define IPEAP_SIM_RAND_NOT_FRESH 3
/* AT_NOTIFICATION values */
#define IPEAP_SIM_FAILURE_AFTER_AUTH 0x0000
#define IPEAP_SIM_TEMPORARILY_DENIED 0x0402
#define IPEAP_SIM_NOT_SUBSCRIBED 0x0407
#define IPEAP_SIM_FAILURE_BEFORE_AUTH 0x4000
#define IPEAP_SIM_SUCCESS 0x8000
/* Constants */
#define IPEAP_SIM_HEADER_LEN 8
#define IPEAP_SIM_NONCE_MT_LEN 16
#define IPEAP_SIM_NONCE_S_LEN 16
#define IPEAP_SIM_RAND_LEN 16
#define IPEAP_SIM_K_AUTH_LEN 16
#define IPEAP_SIM_K_ENCR_LEN 16
#define IPEAP_SIM_MSK_LEN 64
#define IPEAP_SIM_MAC_LEN 16
#define IPEAP_SIM_IV_LEN 16
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_sim_methods_get
*===========================================================================
* Description: Return a structure containing pointer to all functions
* required by EAP.
* Parameters:
* Returns:
*/
IP_PUBLIC Ipeap_methods*
ipeap_sim_methods_get(void);
/*
*===========================================================================
* ipeap_sim_get_identity
*===========================================================================
* Description: Read identity from card (IMSI number).
* Parameters:
* Returns: IPCOM_SUCCESS
* IPCOM_ERR_FAILED
*/
IP_PUBLIC Ip_err
ipeap_sim_get_identity(char* identity, Ip_u32 identityLen);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,183 @@
/*
******************************************************************************
* INTERPEAK INTERNAL API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_sim_card.h,v $ $Revision: 1.4 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_sim_card.h,v $
* $Author: dbush $ $Date: 2008-04-06 21:35:02 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#if !defined(IPEAP_SIM_CARD_H) && \
(defined(IPEAP_USE_EAP_SIM) || defined(IPEAP_USE_EAP_AKA))
#define IPEAP_SIM_CARD_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include "ipeap_sim_reader.h"
#include "ipeap.h"
#include "ipeap_h.h"
#include "ipeap_sim_util.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPEAP_SIM_CARD_GSM 1
#define IPEAP_SIM_CARD_USIM 2
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ipeap_sim_card_st
{
Ip_u32 sim_type;
SCARDCONTEXT ctx;
Ip_u32 protocol;
SCARDHANDLE card;
CARD_IO_REQUEST send_pci;
CARD_IO_REQUEST recv_pci;
} Ipeap_sim_card;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_sim_card_init
*===========================================================================
* Description: Open a GSM SIM card connection.
* Parameters: type - Type of card. Set to IPEAP_SIM_CARD_GSM or
* IPEAP_SIM_CARD_USIM. Set to 0 type should be detected.
* pin - Optional pin buffer, will be used if needed.
* pin_len - Length of pin buffer
* Returns: A card context structure or IP_NULL if failure.
*/
IP_GLOBAL Ipeap_sim_card*
ipeap_sim_card_initialize(
Ip_u8 type,
Ip_u8* pin,
Ip_u32 pinLen);
/*
*===========================================================================
* ipeap_sim_card_finalize
*===========================================================================
* Description: Close the GSM card connection.
* Parameters: ctx - The context structure recevied at initialize
* Returns:
*/
IP_GLOBAL void
ipeap_sim_card_finalize(
Ipeap_sim_card* ctx);
/*
*===========================================================================
* ipeap_sim_card_get_imsi
*===========================================================================
* Description: Read IMSI number from a GSM SIM card.
* Parameters: ctx - a context received from initialize.
* imsi - buffer that will receive the imsi number.
* imsi_len - length of imsi buffer
* Returns: IPCOM_SUCCESS
* IPCOM_ERR_FAILED
*/
IP_GLOBAL Ip_err
ipeap_sim_card_get_imsi(
Ipeap_sim_card* ctx,
char* imsi,
Ip_u32 imsiLen);
/*
*===========================================================================
* ipeap_sim_card_gsm_auth
*===========================================================================
* Description: Get authentication data from GSM card based on random number.
* Parameters: ctx - a context received from initialize.
* rand - a random number buffer (16 bytes)
* sres - buffer that will receive sres data (4 bytes)
* kc - buffer that will receive kc data (8 bytes)
* Returns: IPCOM_SUCCESS
* IPCOM_ERR_FAILED
*/
IP_GLOBAL Ip_err
ipeap_sim_card_gsm_auth(
Ipeap_sim_card* ctx,
Ip_u8* rand,
Ip_u8* sres,
Ip_u8* kc);
/*
*===========================================================================
* ipeap_sim_card_umts_auth
*===========================================================================
* Description: Get authentication data from UMTS card based on random number.
* Parameters: ctx - a context received from initialize.
* rand - buffer for rand data (16 bytes)
* autn - buffer for autn data (16 bytes)
* res - buffer that will receive res data (4-16 bytes)
* res_len - will receive length of res buffer
* ik - buffer that will receive ik data (16 bytes)
* ck - buffer that will receive ck data (16 bytes)
* auts - buffer that may receive auts data (14 bytes). Have been
* set if *reslen = 0.
* Returns: IPCOM_SUCCESS
* IPCOM_ERR_FAILED
*/
IP_GLOBAL Ip_err
ipeap_sim_card_umts_auth(
Ipeap_sim_card* ctx,
Ip_u8* rand,
Ip_u8* autn,
Ip_u8* res,
Ip_u32* res_len,
Ip_u8* ik,
Ip_u8* ck,
Ip_u8* auts);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,376 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_sim_reader.c,v $ $Revision: 1.7 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_sim_reader.c,v $
* $Author: hchowdhu $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include "ipeap.h"
#include "ipeap_h.h"
#include "ipeap_sim.h"
#include "ipeap_sim_reader.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/* Windows have unicode and ansi version in parallell, so all with "char"
* arguments, have A or W appended. */
#if defined(_WIN32)
#define PCSCAPI __stdcall
#define SCardListReaders SCardListReadersA
#define SCardConnect SCardConnectA
#else
#define PCSCAPI
#endif
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
#ifdef IPEAP_USE_PCSC
/*
*===========================================================================
* SCardEstablishContext
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_u32 PCSCAPI
SCardEstablishContext(
Ip_u32 dwScope,
const void* pvReserved1,
const void* pvReserved2,
LPSCARDCONTEXT phContext);
/*
*===========================================================================
* SCardReleaseContext
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_u32 PCSCAPI
SCardReleaseContext(
SCARDCONTEXT hContext);
/*
*===========================================================================
* SCardListReaders
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_u32 PCSCAPI
SCardListReaders(
SCARDCONTEXT hContext,
const char* mszGroups,
char* mszReaders,
Ip_u32* pcchReaders);
/*
*===========================================================================
* SCardConnect
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_u32 PCSCAPI
SCardConnect(
SCARDCONTEXT hContext,
const char* szReader,
Ip_u32 dwShareMode,
Ip_u32 dwPreferredProtocols,
LPSCARDHANDLE phCard,
Ip_u32* pdwActiveProtocol);
/*
*===========================================================================
* SCardDisconnect
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_u32 PCSCAPI
SCardDisconnect(
SCARDHANDLE hCard,
Ip_u32 dwDisposition);
/*
*===========================================================================
* SCardTransmit
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_u32 PCSCAPI
SCardTransmit(
SCARDHANDLE hCard,
LPCCARD_IO_REQUEST pioSendPci,
const Ip_u8* pbSendBuffer,
Ip_u32 cbSendLength,
LPCARD_IO_REQUEST pioRecvPci,
Ip_u8* pbRecvBuffer,
Ip_u32* pcbRecvLength);
#endif /* IPEAP_USE_PCSC */
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_reader_establish_context
*===========================================================================
*/
IP_GLOBAL Ip_u32
ipeap_reader_establish_context(
Ip_u32 dwScope,
const void* pvReserved1,
const void* pvReserved2,
LPSCARDCONTEXT phContext)
{
Ip_u32 err = 0xffffffff;
#ifdef IPEAP_USE_PCSC
err = SCardEstablishContext(dwScope, pvReserved1, pvReserved2, phContext);
#else
(void)dwScope;
(void)pvReserved1;
(void)pvReserved2;
(void)phContext;
IPCOM_LOG0(ERR, "ipeap_reader_establish_context - PC/SC unsupported");
#endif
return err;
}
/*
*===========================================================================
* ipeap_reader_release_context
*===========================================================================
*/
IP_GLOBAL Ip_u32
ipeap_reader_release_context(
SCARDCONTEXT hContext)
{
Ip_u32 err = 0xffffffff;
#ifdef IPEAP_USE_PCSC
err = SCardReleaseContext(hContext);
#else
(void)hContext;
IPCOM_LOG0(ERR, "ipeap_reader_release_context - PC/SC unsupported");
#endif
return err;
}
/*
*===========================================================================
* ipeap_reader_list_readers
*===========================================================================
*/
IP_GLOBAL Ip_u32
ipeap_reader_list_readers(
SCARDCONTEXT hContext,
const char* mszGroups,
char* mszReaders,
Ip_u32* pcchReaders)
{
Ip_u32 err = 0xffffffff;
#ifdef IPEAP_USE_PCSC
err = SCardListReaders(hContext, mszGroups, mszReaders, pcchReaders);
#else
(void)hContext;
(void)mszGroups;
(void)mszReaders;
(void)pcchReaders;
IPCOM_LOG0(ERR, "ipeap_reader_list_readers - PC/SC unsupported");
#endif
return err;
}
/*
*===========================================================================
* ipeap_reader_connect
*===========================================================================
*/
IP_GLOBAL Ip_u32
ipeap_reader_connect(
SCARDCONTEXT hContext,
const char* szReader,
Ip_u32 dwShareMode,
Ip_u32 dwPreferredProtocols,
LPSCARDHANDLE phCard,
Ip_u32* pdwActiveProtocol)
{
Ip_u32 err = 0xffffffff;
#ifdef IPEAP_USE_PCSC
err = SCardConnect(hContext,
szReader,
dwShareMode,
dwPreferredProtocols,
phCard,
pdwActiveProtocol);
#else
(void)hContext;
(void)szReader;
(void)dwShareMode;
(void)dwPreferredProtocols;
(void)phCard;
(void)pdwActiveProtocol;
IPCOM_LOG0(ERR, "ipeap_reader_connect - PC/SC unsupported");
#endif
return err;
}
/*
*===========================================================================
* ipeap_reader_disconnect
*===========================================================================
*/
IP_GLOBAL Ip_u32
ipeap_reader_disconnect(
SCARDHANDLE hCard,
Ip_u32 dwDisposition)
{
Ip_u32 err = 0xffffffff;
#ifdef IPEAP_USE_PCSC
err = SCardDisconnect(hCard, dwDisposition);
#else
(void)hCard;
(void)dwDisposition;
IPCOM_LOG0(ERR, "ipeap_reader_disconnect - PC/SC unsupported");
#endif
return err;
}
/*
*===========================================================================
* ipeap_reader_transmit
*===========================================================================
*/
IP_GLOBAL Ip_u32
ipeap_reader_transmit(
SCARDHANDLE hCard,
LPCCARD_IO_REQUEST pioSendPci,
const Ip_u8* pbSendBuffer,
Ip_u32 cbSendLength,
LPCARD_IO_REQUEST pioRecvPci,
Ip_u8* pbRecvBuffer,
Ip_u32* pcbRecvLength)
{
Ip_u32 err = 0xffffffff;
#ifdef IPEAP_USE_PCSC
err = SCardTransmit(hCard,
(void*)pioSendPci,
pbSendBuffer,
cbSendLength,
(void*)pioRecvPci,
pbRecvBuffer,
pcbRecvLength);
#else
(void)hCard;
(void)pioSendPci;
(void)pbSendBuffer;
(void)cbSendLength;
(void)pioRecvPci;
(void)pbRecvBuffer;
(void)pcbRecvLength;
IPCOM_LOG0(ERR, "ipeap_reader_transmit - PC/SC unsupported");
#endif
return err;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,263 @@
/*
******************************************************************************
* INTERPEAK INTERNAL API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_sim_reader.h,v $ $Revision: 1.3 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_sim_reader.h,v $
* $Author: dbush $ $Date: 2008-04-06 21:35:02 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#if !defined(IPEAP_SIM_READER_H) && \
(defined(IPEAP_USE_EAP_SIM) || defined(IPEAP_USE_EAP_AKA))
#define IPEAP_SIM_READER_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#ifndef SCARD_S_SUCCESS
#define SCARD_S_SUCCESS 0x00000000
#define SCARD_E_CANCELLED 0x80100002
#define SCARD_E_CANT_DISPOSE 0x8010000E
#define SCARD_E_INSUFFICIENT_BUFFER 0x80100008
#define SCARD_E_INVALID_ATR 0x80100015
#define SCARD_E_INVALID_HANDLE 0x80100003
#define SCARD_E_INVALID_PARAMETER 0x80100004
#define SCARD_E_INVALID_TARGET 0x80100005
#define SCARD_E_INVALID_VALUE 0x80100011
#define SCARD_E_NO_MEMORY 0x80100006
#define SCARD_F_COMM_ERROR 0x80100013
#define SCARD_F_INTERNAL_ERROR 0x80100001
#define SCARD_F_UNKNOWN_ERROR 0x80100014
#define SCARD_F_WAITED_TOO_LONG 0x80100007
#define SCARD_E_UNKNOWN_READER 0x80100009
#define SCARD_E_TIMEOUT 0x8010000A
#define SCARD_E_SHARING_VIOLATION 0x8010000B
#define SCARD_E_NO_SMARTCARD 0x8010000C
#define SCARD_E_UNKNOWN_CARD 0x8010000D
#define SCARD_E_PROTO_MISMATCH 0x8010000F
#define SCARD_E_NOT_READY 0x80100010
#define SCARD_E_SYSTEM_CANCELLED 0x80100012
#define SCARD_E_NOT_TRANSACTED 0x80100016
#define SCARD_E_READER_UNAVAILABLE 0x80100017
#define SCARD_W_UNSUPPORTED_CARD 0x80100065
#define SCARD_W_UNRESPONSIVE_CARD 0x80100066
#define SCARD_W_UNPOWERED_CARD 0x80100067
#define SCARD_W_RESET_CARD 0x80100068
#define SCARD_W_REMOVED_CARD 0x80100069
#define SCARD_W_INSERTED_CARD 0x8010006A
#define SCARD_E_UNSUPPORTED_FEATURE 0x8010001F
#define SCARD_E_PCI_TOO_SMALL 0x80100019
#define SCARD_E_READER_UNSUPPORTED 0x8010001A
#define SCARD_E_DUPLICATE_READER 0x8010001B
#define SCARD_E_CARD_UNSUPPORTED 0x8010001C
#define SCARD_E_NO_SERVICE 0x8010001D
#define SCARD_E_SERVICE_STOPPED 0x8010001E
#endif
#ifndef SCARD_SCOPE_USER
#define SCARD_SCOPE_USER 0x0000 /* Scope in user space */
#define SCARD_SCOPE_TERMINAL 0x0001 /* Scope in terminal */
#define SCARD_SCOPE_SYSTEM 0x0002 /* Scope in system */
#define SCARD_SCOPE_GLOBAL 0x0003 /* Scope is global */
#endif
#ifndef SCARD_PROTOCOL_T0
#define SCARD_PROTOCOL_T0 0x0001 /* T=0 active protocol. */
#define SCARD_PROTOCOL_T1 0x0002 /* T=1 active protocol. */
#endif
#ifndef SCARD_SHARE_EXCLUSIVE
#define SCARD_SHARE_EXCLUSIVE 0x0001 /* Exclusive mode only */
#define SCARD_SHARE_SHARED 0x0002 /* Shared mode only */
#define SCARD_SHARE_DIRECT 0x0003 /* Raw mode only */
#endif
#ifndef SCARD_LEAVE_CARD
#define SCARD_LEAVE_CARD 0x0000 /* Do nothing on close */
#define SCARD_RESET_CARD 0x0001 /* Reset on close */
#define SCARD_UNPOWER_CARD 0x0002 /* Power down on close */
#define SCARD_EJECT_CARD 0x0003 /* Eject on close */
#endif
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
#ifndef SCARDCONTEXT
typedef Ip_u32 SCARDCONTEXT;
typedef SCARDCONTEXT *PSCARDCONTEXT, *LPSCARDCONTEXT;
#endif
#ifndef SCARDHANDLE
typedef Ip_u32 SCARDHANDLE;
typedef SCARDHANDLE *PSCARDHANDLE, *LPSCARDHANDLE;
#endif
typedef struct
{
Ip_u32 dwProtocol; /* Protocol identifier */
Ip_u32 cbPciLength; /* Protocol Control Information Length */
} CARD_IO_REQUEST, *LPCARD_IO_REQUEST;
typedef const CARD_IO_REQUEST *LPCCARD_IO_REQUEST;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_reader_establish_context
*===========================================================================
* Description: Establish a connection with PC/SC.
* Parameters: dwScope - Scope of connection
* pvReserved1 - Must be set to IP_NULL
* pvReserved2 - Must be set to IP_NULL
* phContext - Will get handle to contect if succesful.
* Returns: PC/SC error code
*/
IP_GLOBAL Ip_u32
ipeap_reader_establish_context(
Ip_u32 dwScope,
const void* pvReserved1,
const void* pvReserved2,
LPSCARDCONTEXT phContext);
/*
*===========================================================================
* ipeap_reader_release_context
*===========================================================================
* Description: Release a connection with PC/SC.
* Parameters: hContext - Handle to existing context.
* Returns: PC/SC error code
*/
IP_GLOBAL Ip_u32
ipeap_reader_release_context(
SCARDCONTEXT hContext);
/*
*===========================================================================
* ipeap_reader_list_readers
*===========================================================================
* Description: List available PC/SC readers. Will return a list of strings
* separated with 0. The last string will end with two 0. May
* ask for length of needed buffer: set mszReaders to IP_NULL.
* Parameters: hContext - Handle to existing context.
* mszGroups - Reader group.
* mszReaders - Buffer for reader strings.
* pcchReaders - Length of reader strings buffer.
* Returns: PC/SC error code
*/
IP_GLOBAL Ip_u32
ipeap_reader_list_readers(
SCARDCONTEXT hContext,
const char* mszGroups,
char* mszReaders,
Ip_u32* pcchReaders);
/*
*===========================================================================
* ipeap_reader_connect
*===========================================================================
* Description: Open a connection with a card in a PC/SC reader.
* Parameters: hContext - Handle to existing context.
* szReader - The reader name to connect.
* dwShareMode - Share mode for the connection.
* dwPreferredProtocols - Prefered protocol used for the
* connection.
* phCard - Will receive a handle to the card if successful.
* pdwActiveProtocol - Will receive the protocol used if
* successful.
* Returns: PC/SC error code
*/
IP_GLOBAL Ip_u32
ipeap_reader_connect(
SCARDCONTEXT hContext,
const char* szReader,
Ip_u32 dwShareMode,
Ip_u32 dwPreferredProtocols,
LPSCARDHANDLE phCard,
Ip_u32* pdwActiveProtocol);
/*
*===========================================================================
* ipeap_reader_disconnect
*===========================================================================
* Description: Close a connection with a card in a PC/SC reader.
* Parameters: hCard - Handle to card context.
* dwDisposition - How should the connection be closed.
* Returns: PC/SC error code
*/
IP_GLOBAL Ip_u32
ipeap_reader_disconnect(
SCARDHANDLE hCard,
Ip_u32 dwDisposition);
/*
*===========================================================================
* ipeap_reader_transmit
*===========================================================================
* Description: Transmit a command towards a card in a PC/SC reader.
* Parameters: hCard - Handle to card context.
* pioSendPci - Send protocol control information
* pbSendBuffer - Send command buffer
* cbSendLength - Send command buffer length
* pioRecvPci - Receive protocol control information
* pbRecvBuffer - Receive command buffer
* pcbRecvLength - Receive command buffer length
* Returns: PC/SC error code
*/
IP_GLOBAL Ip_u32
ipeap_reader_transmit(
SCARDHANDLE hCard,
LPCCARD_IO_REQUEST pioSendPci,
const Ip_u8* pbSendBuffer,
Ip_u32 cbSendLength,
LPCARD_IO_REQUEST pioRecvPci,
Ip_u8* pbRecvBuffer,
Ip_u32* pcbRecvLength);
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,381 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_sim_test.c,v $ $Revision: 1.12 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_sim_test.c,v $
* $Author: hchowdhu $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_time.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <openssl/md5.h>
#include <openssl/rand.h>
#include "ipeap_sim.h"
#include "ipeap.h"
#include "ipeap_h.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ipeap_sim_test_st
{
Ip_u8* req;
Ip_u32 req_len;
Ip_u8* res;
Ip_u32 res_len;
} Ipeap_sim_test;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_PUBLIC Ip_bool ipeap_sim_test_vector(void);
IP_PUBLIC Ip_bool ipeap_sim_test(void);
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/* Test data from documentation */
const char IDENTITY[] = "1244070100000001@eapsim.foo";
static Ip_u8 REQ1[] =
{
0x01,0x00,0x00,0x05,0x01
};
#define REQ1_LEN sizeof(REQ1)
static Ip_u8 RES1[] =
{
0x02,0x00,0x00,0x20,0x01,0x31,0x32,0x34,
0x34,0x30,0x37,0x30,0x31,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x31,0x40,0x65,0x61,
0x70,0x73,0x69,0x6d,0x2e,0x66,0x6f,0x6f
};
#define RES1_LEN sizeof(RES1)
static Ip_u8 REQ2[] =
{
0x01,0x01,0x00,0x10,0x12,0x0a,0x00,0x00,
0x0f,0x02,0x00,0x02,0x00,0x01,0x00,0x00
};
#define REQ2_LEN sizeof(REQ2)
static Ip_u8 RES2[] =
{
0x02,0x01,0x00,0x20,0x12,0x0a,0x00,0x00,
0x07,0x05,0x00,0x00,0x01,0x23,0x45,0x67,
0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,
0x76,0x54,0x32,0x10,0x10,0x01,0x00,0x01
};
#define RES2_LEN sizeof(RES2)
static Ip_u8 REQ3[] =
{
0x01,0x02,0x01,0x18,0x12,0x0b,0x00,0x00,
0x01,0x0d,0x00,0x00,0x10,0x11,0x12,0x13,
0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,
0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,
0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,
0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,
0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,
0x3c,0x3d,0x3e,0x3f,0x81,0x05,0x00,0x00,
0x9e,0x18,0xb0,0xc2,0x9a,0x65,0x22,0x63,
0xc0,0x6e,0xfb,0x54,0xdd,0x00,0xa8,0x95,
0x82,0x2d,0x00,0x00,0x55,0xf2,0x93,0x9b,
0xbd,0xb1,0xb1,0x9e,0xa1,0xb4,0x7f,0xc0,
0xb3,0xe0,0xbe,0x4c,0xab,0x2c,0xf7,0x37,
0x2d,0x98,0xe3,0x02,0x3c,0x6b,0xb9,0x24,
0x15,0x72,0x3d,0x58,0xba,0xd6,0x6c,0xe0,
0x84,0xe1,0x01,0xb6,0x0f,0x53,0x58,0x35,
0x4b,0xd4,0x21,0x82,0x78,0xae,0xa7,0xbf,
0x2c,0xba,0xce,0x33,0x10,0x6a,0xed,0xdc,
0x62,0x5b,0x0c,0x1d,0x5a,0xa6,0x7a,0x41,
0x73,0x9a,0xe5,0xb5,0x79,0x50,0x97,0x3f,
0xc7,0xff,0x83,0x01,0x07,0x3c,0x6f,0x95,
0x31,0x50,0xfc,0x30,0x3e,0xa1,0x52,0xd1,
0xe1,0x0a,0x2d,0x1f,0x4f,0x52,0x26,0xda,
0xa1,0xee,0x90,0x05,0x47,0x22,0x52,0xbd,
0xb3,0xb7,0x1d,0x6f,0x0c,0x3a,0x34,0x90,
0x31,0x6c,0x46,0x92,0x98,0x71,0xbd,0x45,
0xcd,0xfd,0xbc,0xa6,0x11,0x2f,0x07,0xf8,
0xbe,0x71,0x79,0x90,0xd2,0x5f,0x6d,0xd7,
0xf2,0xb7,0xb3,0x20,0xbf,0x4d,0x5a,0x99,
0x2e,0x88,0x03,0x31,0xd7,0x29,0x94,0x5a,
0xec,0x75,0xae,0x5d,0x43,0xc8,0xed,0xa5,
0xfe,0x62,0x33,0xfc,0xac,0x49,0x4e,0xe6,
0x7a,0x0d,0x50,0x4d,0x0b,0x05,0x00,0x00,
0xfe,0xf3,0x24,0xac,0x39,0x62,0xb5,0x9f,
0x3b,0xd7,0x82,0x53,0xae,0x4d,0xcb,0x6a
};
#define REQ3_LEN sizeof(REQ3)
static Ip_u8 RES3[] =
{
0x02,0x02,0x00,0x1c,0x12,0x0b,0x00,0x00,
0x0b,0x05,0x00,0x00,0xf5,0x6d,0x64,0x33,
0xe6,0x8e,0xd2,0x97,0x6a,0xc1,0x19,0x37,
0xfc,0x3d,0x11,0x54
};
#define RES3_LEN sizeof(RES3)
static Ip_u8 REQ4[] =
{
0x03,0x02,0x00,0x04
};
#define REQ4_LEN sizeof(REQ4)
static Ip_u8 REQ5[] =
{
0x01,0x00,0x00,0x05,0x01
};
#define REQ5_LEN sizeof(REQ5)
static Ip_u8 RES5[] =
{
0x02,0x00,0x00,0x56,0x01,0x59,0x32,0x34,
0x66,0x4e,0x53,0x72,0x7a,0x38,0x42,0x50,
0x32,0x37,0x34,0x6a,0x4f,0x4a,0x61,0x46,
0x31,0x37,0x57,0x66,0x78,0x49,0x38,0x59,
0x4f,0x37,0x51,0x58,0x30,0x30,0x70,0x4d,
0x58,0x6b,0x39,0x58,0x4d,0x4d,0x56,0x4f,
0x77,0x37,0x62,0x72,0x6f,0x61,0x4e,0x68,
0x54,0x63,0x7a,0x75,0x46,0x71,0x35,0x33,
0x61,0x45,0x70,0x4f,0x6b,0x6b,0x33,0x4c,
0x30,0x64,0x6d,0x40,0x65,0x61,0x70,0x73,
0x69,0x6d,0x2e,0x66,0x6f,0x6f
};
#define RES5_LEN sizeof(RES5)
static Ip_u8 REQ6[] =
{
0x01,0x01,0x00,0xa4,0x12,0x0d,0x00,0x00,
0x81,0x05,0x00,0x00,0xd5,0x85,0xac,0x77,
0x86,0xb9,0x03,0x36,0x65,0x7c,0x77,0xb4,
0x65,0x75,0xb9,0xc4,0x82,0x1d,0x00,0x00,
0x68,0x62,0x91,0xa9,0xd2,0xab,0xc5,0x8c,
0xaa,0x32,0x94,0xb6,0xe8,0x5b,0x44,0x84,
0x6c,0x44,0xe5,0xdc,0xb2,0xde,0x8b,0x9e,
0x80,0xd6,0x9d,0x49,0x85,0x8a,0x5d,0xb8,
0x4c,0xdc,0x1c,0x9b,0xc9,0x5c,0x01,0xb9,
0x6b,0x6e,0xca,0x31,0x34,0x74,0xae,0xa6,
0xd3,0x14,0x16,0xe1,0x9d,0xaa,0x9d,0xf7,
0x0f,0x05,0x00,0x88,0x41,0xca,0x80,0x14,
0x96,0x4d,0x3b,0x30,0xa4,0x9b,0xcf,0x43,
0xe4,0xd3,0xf1,0x8e,0x86,0x29,0x5a,0x4a,
0x2b,0x38,0xd9,0x6c,0x97,0x05,0xc2,0xbb,
0xb0,0x5c,0x4a,0xac,0xe9,0x7d,0x5e,0xaf,
0xf5,0x64,0x04,0x6c,0x8b,0xd3,0x0b,0xc3,
0x9b,0xe5,0xe1,0x7a,0xce,0x2b,0x10,0xa6,
0x0b,0x05,0x00,0x00,0x48,0x3a,0x17,0x99,
0xb8,0x3d,0x7c,0xd3,0xd0,0xa1,0xe4,0x01,
0xd9,0xee,0x47,0x70
};
#define REQ6_LEN sizeof(REQ6)
static Ip_u8 RES6[] =
{
0x02,0x01,0x00,0x44,0x12,0x0d,0x00,0x00,
0x81,0x05,0x00,0x00,0xcd,0xf7,0xff,0xa6,
0x5d,0xe0,0x4c,0x02,0x6b,0x56,0xc8,0x6b,
0x76,0xb1,0x02,0xea,0x82,0x05,0x00,0x00,
0xb6,0xed,0xd3,0x82,0x79,0xe2,0xa1,0x42,
0x3c,0x1a,0xfc,0x5c,0x45,0x5c,0x7d,0x56,
0x0b,0x05,0x00,0x00,0xfa,0xf7,0x6b,0x71,
0xfb,0xe2,0xd2,0x55,0xb9,0x6a,0x35,0x66,
0xc9,0x15,0xc6,0x17
};
#define RES6_LEN sizeof(RES6)
static Ip_u8 REQ7[] =
{
0x03,0x02,0x00,0x04
};
#define REQ7_LEN sizeof(REQ7)
static Ipeap_sim_test EAP_SIM_TEST[] =
{
{REQ1, REQ1_LEN, RES1, RES1_LEN},
{REQ2, REQ2_LEN, RES2, RES2_LEN},
{REQ3, REQ3_LEN, RES3, RES3_LEN},
{REQ4, REQ4_LEN, IP_NULL, 0},
{REQ5, REQ5_LEN, RES5, RES5_LEN},
{REQ6, REQ6_LEN, RES6, RES6_LEN},
{REQ7, REQ7_LEN, IP_NULL, 0},
{IP_NULL, 0, IP_NULL, 0}
};
/*
*===========================================================================
* ipeap_sim_test_vector
*===========================================================================
*/
IP_PUBLIC Ip_bool
ipeap_sim_test_vector(void)
{
Ip_bool ok = IP_FALSE;
Ip_err err = IPCOM_SUCCESS;
Ipeap_ctx* ctx = IP_NULL;
Ipeap_pkt* pkt_in = IP_NULL;
Ipeap_pkt* pkt_out = IP_NULL;
Ip_u32 i = 0;
Ip_u8* req = IP_NULL;
Ip_u32 req_len = 0;
Ip_u8* res = IP_NULL;
Ip_u32 res_len = 0;
Ip_bool is_test = IP_TRUE;
(void)ipcom_sysvar_set("ipeap.sim", "1", IPCOM_SYSVAR_FLAG_OVERWRITE);
if(is_test)
(void)ipcom_sysvar_set("ipeap.sim.test", "1" , IPCOM_SYSVAR_FLAG_OVERWRITE);
(void)ipcom_sysvar_set("ipeap.sim.pin", "7575", IPCOM_SYSVAR_FLAG_OVERWRITE);
(void)ipcom_sysvar_set("ipeap.sim.realm", "eapsim.foo", IPCOM_SYSVAR_FLAG_OVERWRITE);
(void)ipcom_sysvar_set("ipeap.sim.reader", "omnikey cardman 4040 0", IPCOM_SYSVAR_FLAG_OVERWRITE);
if ((IP_NULL == (ctx = ipeap_ctx_new(IPEAP_MODE_SUPPLICANT))) ||
(IP_NULL == (pkt_in = ipeap_alloc_pkt(384))) ||
(IP_NULL == (pkt_out = ipeap_alloc_pkt(128))))
{
IPCOM_LOG0(ERR, "ipeap_sim_test - out of memory");
goto cleanup;
}
(void)ipcom_sysvar_set("ipeap.identity", IDENTITY, IPCOM_SYSVAR_FLAG_OVERWRITE);
(void)ipeap_ctx_set_identity_from_sysvar(ctx);
while (IP_NULL != EAP_SIM_TEST[i].req)
{
req = EAP_SIM_TEST[i].req;
req_len = EAP_SIM_TEST[i].req_len;
res = EAP_SIM_TEST[i].res;
res_len = EAP_SIM_TEST[i].res_len;
i++;
IPCOM_LOG1(INFO, "ipeap_sim_test - TEST %d ...", i);
ipcom_memset(pkt_in->data, 0xdd, (Ip_size_t)pkt_in->max_len);
if (IPCOM_SUCCESS != (err = ipeap_set_pkt_data(pkt_in, req, req_len)))
{
IPCOM_LOG1(ERR, "ipeap_sim_test - failed to set data for test (%d)", i);
goto cleanup;
}
pkt_out->start = 32;
pkt_out->end = 32;
ipcom_memset(pkt_out->data, 0xdd, (Ip_size_t)pkt_out->max_len);
err = ipeap_process_pkt(ctx, pkt_in, pkt_out);
if ((IPEAP_PENDING_SEND_OUT_PKT != err) &&
(IPEAP_SUCCESS != err))
{
IPCOM_LOG1(ERR, "ipeap_sim_test - failed to proccess request %d", i);
goto cleanup;
}
else if ((IPEAP_SUCCESS == err) && (res_len != 0))
{
IPCOM_LOG1(ERR, "ipeap_sim_test - success to early, expecting a response for %d", i);
goto cleanup;
}
if ((IPEAP_PENDING_SEND_OUT_PKT == err) &&
(is_test) &&
!ipeap_compare_pkt_data(pkt_out, res, res_len))
{
IPCOM_LOG1(ERR, "ipeap_sim_test - response %d not as expected", i);
goto cleanup;
}
IPCOM_LOG1(INFO, "ipeap_sim_test - TEST %d ... SUCCESS", i);
}
ok = IP_TRUE;
cleanup:
ipeap_ctx_free(ctx);
ipeap_free_pkt(pkt_in);
ipeap_free_pkt(pkt_out);
return ok;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_sim_test
*===========================================================================
*/
IP_PUBLIC Ip_bool
ipeap_sim_test(void)
{
Ip_bool ok = IP_FALSE;
ok = ipeap_sim_test_vector();
return ok;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,83 @@
/*
******************************************************************************
* INTERPEAK INTERNAL API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_sim_test.h,v $ $Revision: 1.4 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_sim_test.h,v $
* $Author: hchowdhu $ $Date: 2010-06-28 22:04:14 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#if !defined(IPEAP_SIM_TEST_H)
#define IPEAP_SIM_TEST_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_sim_test
*===========================================================================
* Description: Run test vectors for EAP SIM or EAP AKA.
* Parameters:
* Returns: TRUE if test successful (FALSE otherwise)
*/
IP_PUBLIC Ip_bool
ipeap_sim_test(void);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,767 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_sim_util.c,v $ $Revision: 1.21 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_sim_util.c,v $
* $Author: hchowdhu $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_syslog.h>
#include <openssl/rand.h>
#include <openssl/aes.h>
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include "ipeap.h"
#include "ipeap_h.h"
#include "ipeap_sim.h"
#include "ipeap_sim_util.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#ifndef AES_BLOCK_SIZE
#define AES_BLOCK_SIZE 16
#endif
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
*===========================================================================
* ipeap_sim_sha1_transform
*===========================================================================
* Description: Make a sha-1 transform
* Parameters: state - the current state
* data - data buffer to transform
* Returns:
*/
IP_STATIC void
ipeap_sim_sha1_transform(Ip_u8* state, Ip_u8 data[64]);
/*
*===========================================================================
* ipeap_sim_get_cipher
*===========================================================================
* Description: Get cipher context from cipher name and key length
* Parameters: name - the cipher name
* key_len - key lengths in bytes
* Returns: Cipher context or IP_NULL
*/
#ifndef IPMCRYPTO
IP_STATIC const EVP_CIPHER *
ipeap_sim_get_cipher(const char *name, Ip_u32 key_len);
#endif /* !IPMCRYPTO */
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_sim_sha1_transform
*===========================================================================
*/
IP_STATIC void
ipeap_sim_sha1_transform(Ip_u8* state, Ip_u8 data[64])
{
SHA_CTX ctx;
ipcom_memset(&ctx, 0, sizeof(ctx));
ipcom_memcpy(&ctx.h0, state, 4);
ipcom_memcpy(&ctx.h1, state+4, 4);
ipcom_memcpy(&ctx.h2, state+8, 4);
ipcom_memcpy(&ctx.h3, state+12, 4);
ipcom_memcpy(&ctx.h4, state+16, 4);
SHA1_Transform(&ctx, data);
ipcom_memcpy(state, &ctx.h0, 4);
ipcom_memcpy(state+4, &ctx.h1, 4);
ipcom_memcpy(state+8, &ctx.h2, 4);
ipcom_memcpy(state+12, &ctx.h3, 4);
ipcom_memcpy(state+16, &ctx.h4, 4);
return;
}
/*
*===========================================================================
* ipeap_sim_get_cipher
*===========================================================================
*/
#ifndef IPMCRYPTO
IP_STATIC const EVP_CIPHER *
ipeap_sim_get_cipher(const char *name, Ip_u32 key_len)
{
const EVP_CIPHER *cipher = IP_NULL;
char alg_name[32] = {0};
ipcom_snprintf(alg_name, sizeof(alg_name), "%s%d", name, key_len*8);
cipher = EVP_get_cipherbyname(alg_name);
if (cipher == IP_NULL)
IPCOM_LOG1(ERR, "ipeap_sim_get_cipher: %s not found", name);
return cipher;
}
#endif /* !IPMCRYPTO */
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ip_alloc_value
*===========================================================================
*/
IP_GLOBAL Ip_err
ip_alloc_value(Ip_value* value, Ip_u32 len)
{
value->p = ipcom_calloc(1, len);
if (IP_NULL == value->p)
return IPCOM_ERR_FAILED;
value->n = len;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ip_free_value
*===========================================================================
*/
IP_GLOBAL void
ip_free_value(Ip_value* value)
{
if (IP_NULL != value->p)
ipcom_free(value->p);
value->p = IP_NULL;
value->n = 0;
return;
}
/*
*===========================================================================
* ip_set_value
*===========================================================================
*/
IP_GLOBAL Ip_err
ip_set_value(Ip_value* value, Ip_u8* ptr, Ip_u32 len)
{
Ip_err err = IPCOM_SUCCESS;
ip_free_value(value);
if (IPCOM_SUCCESS != (err = ip_alloc_value(value, len)))
return err;
ipcom_memcpy(value->p, ptr, len);
value->n = len;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ip_append_value
*===========================================================================
*/
IP_GLOBAL Ip_err
ip_append_value(Ip_value* value, Ip_u8* ptr, Ip_u32 len)
{
value->p = ipcom_realloc(value->p, value->n + len);
if (IP_NULL == value->p)
return IPCOM_ERR_FAILED;
ipcom_memcpy(value->p + value->n, ptr, len);
value->n += len;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_alloc_pkt
*===========================================================================
*/
IP_GLOBAL Ipeap_pkt*
ipeap_alloc_pkt(Ip_u32 size)
{
Ipeap_pkt* pkt = IP_NULL;
pkt = (Ipeap_pkt*)ipcom_calloc(1, size+sizeof(*pkt));
if (IP_NULL != pkt)
{
pkt->start = 0;
pkt->end = 0;
pkt->max_len = (int)size;
pkt->data = (Ip_u8*)pkt + sizeof(*pkt);
}
return pkt;
}
/*
*===========================================================================
* ipeap_free_pkt
*===========================================================================
*/
IP_GLOBAL void
ipeap_free_pkt(Ipeap_pkt* pkt)
{
if (IP_NULL != pkt)
ipcom_free(pkt);
return;
}
/*
*===========================================================================
* ipeap_set_pkt_data
*===========================================================================
*/
IP_GLOBAL Ip_err
ipeap_set_pkt_data(Ipeap_pkt* pkt, Ip_u8* data, Ip_u32 len)
{
if ((IP_NULL == pkt) ||
((pkt->start + (int)len) > pkt->max_len))
return IPCOM_ERR_FAILED;
ipcom_memcpy(pkt->data+pkt->start, data, len);
pkt->end = pkt->start + (int)len;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_get_pkt_data_size
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_u32
ipeap_get_pkt_data_size(
Ipeap_pkt* pkt)
{
return (Ip_u32)(pkt->max_len - pkt->end);
}
/*
*===========================================================================
* ipeap_get_pkt_data_buffer
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_u8*
ipeap_get_pkt_data_buffer(
Ipeap_pkt* pkt)
{
return (Ip_u8*)pkt->data + pkt->start;
}
/*
*===========================================================================
* ipeap_compare_pkt_data
*===========================================================================
*/
IP_GLOBAL Ip_bool
ipeap_compare_pkt_data(Ipeap_pkt* pkt, Ip_u8* data, Ip_u32 len)
{
if ((IP_NULL == pkt) ||
((pkt->end - pkt->start) != (int)len) ||
(ipcom_memcmp(pkt->data+pkt->start, data, len) != 0))
return IP_FALSE;
return IP_TRUE;
}
/*
*===========================================================================
* ipeap_memory_to_string
*===========================================================================
*/
IP_GLOBAL char*
ipeap_memory_to_string(const Ip_u8* ptr, Ip_u32 size, Ip_u8 alignment)
{
static const char hex_char[] = "0123456789abcdef";
static const int byte_per_row = 32;
char* buf;
int row_size;
int i, j, k = 0;
int ws_per_row;
int full_rows, blr;
ws_per_row = byte_per_row / alignment;
row_size = 2 * byte_per_row + ws_per_row;
full_rows = (int)size / byte_per_row;
blr = (int)size % byte_per_row;
buf = ipcom_malloc( (Ip_size_t)(full_rows * row_size + 2 * blr + blr / alignment + 1) );
if (IP_NULL == buf)
return IP_NULL;
for (i = 0; i <= full_rows; i++)
{
k = 0;
for (j = 0; j < (i == full_rows ? blr : byte_per_row); j++)
{
if (j != 0 && j % alignment == 0)
buf[i * row_size + 2 * j + k++] = ' ';
buf[i * row_size + 2 * j + k] =
hex_char[ptr[i * byte_per_row + j] >> 4];
buf[i * row_size + 2 * j + k + 1] =
hex_char[ptr[i * byte_per_row + j] & 0x0F];
}
buf[i * row_size + 2 * j + k] = '\n';
}
buf[full_rows * row_size + 2 * blr + k] = '\0';
return buf;
}
/*
*===========================================================================
* ipeap_print_memory
*===========================================================================
*/
IP_GLOBAL void
ipeap_print_memory(
const char* prefix,
const Ip_u8* data,
Ip_u32 len)
{
char* hex_mem = IP_NULL;
hex_mem = ipeap_memory_to_string(data, len, 4);
if (hex_mem == IP_NULL)
{
IPCOM_LOG0(CRIT, "ipeap_print_memory: out of memory");
}
else
{
/* Make sure fit into syslog buffer */
if ((ipcom_strlen(hex_mem) + ipcom_strlen(prefix)) >= IPCOM_SYSLOG_MAX_SIZE)
{
len = IPCOM_SYSLOG_MAX_SIZE - (Ip_u32)ipcom_strlen(prefix);
hex_mem[len-4] = '.';
hex_mem[len-3] = '.';
hex_mem[len-2] = '.';
hex_mem[len-1] = 0;
}
IPCOM_LOG2(DEBUG2, "%s%s", prefix, hex_mem);
ipcom_free(hex_mem);
}
return;
}
/*
*===========================================================================
* ipeap_sim_prf
*===========================================================================
*/
IP_GLOBAL Ip_err
ipeap_sim_prf(
Ip_u8* key,
Ip_u32 key_len,
Ip_u8* buf,
Ip_u32 buf_len)
{
Ip_u8 xkey[64] = {0};
Ip_u32 t[5] = {0};
Ip_u32 _t[5] = {0};
Ip_s32 i = 0;
Ip_s32 j = 0;
Ip_s32 m = 0;
Ip_s32 k = 0;
Ip_u8* xpos = buf;
Ip_u32 carry = 0;
/* See section 6.4
*
* Key derivation is based on the random number generation specified in
* NIST Federal Information Processing Standards (FIPS) Publication
* 186-2 [PRF]. The pseudo-random number generator is specified in the
* change notice 1 (2001 October 5) of [PRF] (Algorithm 1) */
if (key_len >= 64)
{
IPCOM_LOG1(ERR, "ipeap_sim_prf: key too long (%d >= 64)", key_len);
return IPCOM_ERR_FAILED;
}
ipcom_memcpy(xkey, key, key_len);
ipcom_memset(xkey + key_len, 0, 64 - key_len);
t[0] = 0x67452301;
t[1] = 0xEFCDAB89;
t[2] = 0x98BADCFE;
t[3] = 0x10325476;
t[4] = 0xC3D2E1F0;
m = (Ip_s32)buf_len / 40;
for (j = 0; j < m; j++)
{
for (i = 0; i < 2; i++)
{
ipcom_memcpy(_t, t, 20);
ipeap_sim_sha1_transform((Ip_u8*)_t, xkey);
_t[0] = (Ip_u32)ip_htonl(_t[0]);
_t[1] = (Ip_u32)ip_htonl(_t[1]);
_t[2] = (Ip_u32)ip_htonl(_t[2]);
_t[3] = (Ip_u32)ip_htonl(_t[3]);
_t[4] = (Ip_u32)ip_htonl(_t[4]);
ipcom_memcpy(xpos, _t, 20);
carry = 1;
for (k = 19; k >= 0; k--)
{
carry += (Ip_u32)(xkey[k] + xpos[k]);
xkey[k] = (Ip_u8)carry;
carry >>= 8;
}
xpos += 20;
}
}
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_sim_generate_mac
*===========================================================================
*/
IP_GLOBAL Ip_err
ipeap_sim_generate_mac(
Ip_u8* key,
Ip_u32 key_len,
Ip_u8* data1,
Ip_u32 data1_len,
Ip_u8* data2,
Ip_u32 data2_len,
Ip_u8* mac,
Ip_u32 mac_len)
{
const EVP_MD* evp_md = IP_NULL;
HMAC_CTX ctx = {0};
unsigned int hmac_len = 0;
Ip_u8* hmac = IP_NULL;
evp_md = EVP_get_digestbyname("sha1");
if (IP_NULL == evp_md)
{
IPCOM_LOG0(ERR, "ipeap_sim_generate_mac: sha1 algorithm not available");
return IPCOM_ERR_FAILED;
}
hmac_len = (unsigned int)EVP_MD_size(evp_md);
if (hmac_len < mac_len)
{
IPCOM_LOG2(ERR, "ipeap_sim_generate_mac: bad mac length (%d < %d)", hmac_len, mac_len);
return IPCOM_ERR_FAILED;
}
hmac = ipcom_malloc(hmac_len);
if (IP_NULL == hmac)
{
IPCOM_LOG0(ERR, "ipeap_sim_generate_mac: out of memory");
return IPCOM_ERR_FAILED;
}
HMAC_CTX_init(&ctx);
HMAC_Init(&ctx, key, (int)key_len, evp_md);
if (data1_len > 0)
HMAC_Update(&ctx, data1, data1_len);
if (data2_len > 0)
HMAC_Update(&ctx, data2, data2_len);
HMAC_Final(&ctx, hmac, (unsigned int*)&hmac_len);
HMAC_CTX_cleanup(&ctx);
ipcom_memcpy(mac, hmac, mac_len);
ipcom_free(hmac);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_sim_verify_mac
*===========================================================================
*/
IP_GLOBAL Ip_err
ipeap_sim_verify_mac(
Ip_u8* key,
Ip_u32 key_len,
Ip_u8* data1,
Ip_u32 data1_len,
Ip_u8* data2,
Ip_u32 data2_len,
Ip_u8* mac,
Ip_u32 mac_len)
{
Ip_err err = IPCOM_SUCCESS;
Ip_u8* tmp = IP_NULL;
tmp = ipcom_malloc(mac_len);
if (IP_NULL == tmp)
return IPCOM_ERR_FAILED;
err = ipeap_sim_generate_mac(key,
key_len,
data1,
data1_len,
data2,
data2_len,
tmp,
mac_len);
if (IPCOM_SUCCESS != err)
{
IPCOM_LOG0(ERR, "ipeap_sim_verify_mac: failed to generate mac");
ipcom_free(tmp);
return err;
}
if (ipcom_memcmp(tmp, mac, mac_len) != 0)
{
IPCOM_LOG0(ERR, "ipeap_sim_verify_mac: bad mac value");
ipcom_free(tmp);
return IPCOM_ERR_FAILED;
}
ipcom_free(tmp);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_sim_aes_cbc_encrypt
*===========================================================================
*/
IP_GLOBAL Ip_err
ipeap_sim_aes_cbc_encrypt(
Ip_u8* key,
Ip_u32 key_len,
Ip_u8* iv,
Ip_u32 iv_len,
Ip_u8* data,
Ip_u32 data_len)
{
Ip_err err = IPCOM_ERR_FAILED;
if (data_len == 0)
{
err = IPCOM_SUCCESS;
}
else if ((iv_len == AES_BLOCK_SIZE) && ((data_len % AES_BLOCK_SIZE) == 0))
{
#if defined(IPMCRYPTO)
AES_KEY ctx;
ipcom_memset(&ctx, 0, sizeof(ctx));
if (AES_set_encrypt_key(key, key_len*8, &ctx) < 0)
{
IPCOM_LOG0(ERR, "ipeap_sim_aes_cbc_encrypt: failed to set key");
err = IPCOM_ERR_FAILED;
}
else
{
err = IPCOM_SUCCESS;
AES_cbc_encrypt(data, data, data_len, &ctx, iv, AES_ENCRYPT);
}
#else /* defined (IPCRYPTO) */
const EVP_CIPHER *cipher = IP_NULL;
EVP_CIPHER_CTX ctx;
if ((cipher = ipeap_sim_get_cipher("aes", key_len)) != IP_NULL)
{
EVP_CIPHER_CTX_init(&ctx);
if (EVP_EncryptInit(&ctx, cipher, key, iv) &&
EVP_CIPHER_CTX_set_padding(&ctx, 0) &&
EVP_EncryptUpdate(&ctx, data, (int*)&data_len, data, (int)data_len))
{
err = IPCOM_SUCCESS;
}
else
{
IPCOM_LOG0(ERR, "ipeap_sim_aes_cbc_encrypt: failed to encrypt");
}
(void)EVP_CIPHER_CTX_cleanup(&ctx);
}
#endif
}
return err;
}
/*
*===========================================================================
* ipeap_sim_aes_cbc_decrypt
*===========================================================================
*/
IP_GLOBAL Ip_err
ipeap_sim_aes_cbc_decrypt(
Ip_u8* key,
Ip_u32 key_len,
Ip_u8* iv,
Ip_u32 iv_len,
Ip_u8* data,
Ip_u32 data_len)
{
Ip_err err = IPCOM_ERR_FAILED;
if (data_len == 0)
{
err = IPCOM_SUCCESS;
}
else if ((iv_len == AES_BLOCK_SIZE) && ((data_len % AES_BLOCK_SIZE) == 0))
{
#if defined(IPMCRYPTO)
AES_KEY ctx;
ipcom_memset(&ctx, 0, sizeof(ctx));
if (AES_set_decrypt_key(key, key_len*8, &ctx) < 0)
{
IPCOM_LOG0(ERR, "ipeap_sim_aes_cbc_decrypt: failed to set key");
err = IPCOM_ERR_FAILED;
}
else
{
err = IPCOM_SUCCESS;
AES_cbc_encrypt(data, data, data_len, &ctx, iv, AES_DECRYPT);
}
#else /* defined (IPCRYPTO) */
const EVP_CIPHER *cipher = IP_NULL;
EVP_CIPHER_CTX ctx;
if ((cipher = ipeap_sim_get_cipher("aes", key_len)) != IP_NULL)
{
EVP_CIPHER_CTX_init(&ctx);
if (EVP_DecryptInit(&ctx, cipher, key, iv) &&
EVP_CIPHER_CTX_set_padding(&ctx, 0) &&
EVP_DecryptUpdate(&ctx, data, (int*)&data_len, data, (int)data_len))
{
err = IPCOM_SUCCESS;
}
else
{
IPCOM_LOG0(ERR, "ipeap_sim_aes_cbc_decrypt: failed to decrypt");
}
(void)EVP_CIPHER_CTX_cleanup(&ctx);
}
#endif
}
return err;
}
/*
*===========================================================================
* ipeap_sim_algorithm_test
*===========================================================================
*/
IP_GLOBAL Ip_err
ipeap_sim_algorithm_test(void)
{
Ip_err err = IPCOM_SUCCESS;
#ifdef IP_DEBUG
Ip_u8 IV[16] = {0};
Ip_u8 KEY[16] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
Ip_u8 MSG[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
Ip_u8 ENC[16] = {0x69,0xC4,0xE0,0xD8,0x6A,0x7B,0x04,0x30,0xD8,0xCD,0xB7,0x80,0x70,0xB4,0xC5,0x5A};
Ip_u8 tmp[16] = {0};
ipcom_memcpy(tmp, MSG, sizeof(MSG));
if (IPCOM_SUCCESS != (err = ipeap_sim_aes_cbc_encrypt(
KEY, sizeof(KEY),
IV, sizeof(IV),
tmp, sizeof(tmp))))
{
IPCOM_LOG0(ERR, "ipeap_sim_algorithm_test - AES encrypt not available");
}
else if (ipcom_memcmp(ENC, tmp, sizeof(ENC)) != 0)
{
IPCOM_LOG0(ERR, "ipeap_sim_algorithm_test - AES bad encrypt value");
err = IPCOM_ERR_FAILED;
}
else if (IPCOM_SUCCESS != (err = ipeap_sim_aes_cbc_decrypt(
KEY, sizeof(KEY),
IV, sizeof(IV),
tmp, sizeof(tmp))))
{
IPCOM_LOG0(ERR, "ipeap_sim_algorithm_test - AES decrypt not available");
}
else if (ipcom_memcmp(MSG, tmp, sizeof(MSG)) != 0)
{
IPCOM_LOG0(ERR, "ipeap_sim_algorithm_test - AES bad decrypt value");
err = IPCOM_ERR_FAILED;
}
#endif /* IP_DEBUG */
return err;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,364 @@
/*
******************************************************************************
* INTERPEAK INTERNAL API HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_sim_util.h,v $ $Revision: 1.5 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_sim_util.h,v $
* $Author: hchowdhu $ $Date: 2010-06-28 22:03:54 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
#if !defined(IPEAP_SIM_UTIL_H)
#define IPEAP_SIM_UTIL_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ip_value_st
{
Ip_u8* p;
Ip_u32 n;
} Ip_value;
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ip_alloc_value
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_err
ip_alloc_value(
Ip_value* value,
Ip_u32 len);
/*
*===========================================================================
* ip_free_value
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL void
ip_free_value(
Ip_value* value);
/*
*===========================================================================
* ip_set_value
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_err
ip_set_value(
Ip_value* value,
Ip_u8* ptr,
Ip_u32 len);
/*
*===========================================================================
* ip_append_value
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_err
ip_append_value(
Ip_value* value,
Ip_u8* ptr,
Ip_u32 len);
/*
*===========================================================================
* ipeap_alloc_pkt
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ipeap_pkt*
ipeap_alloc_pkt(
Ip_u32 size);
/*
*===========================================================================
* ipeap_free_pkt
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL void
ipeap_free_pkt(
Ipeap_pkt* pkt);
/*
*===========================================================================
* ipeap_set_pkt_data
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_err
ipeap_set_pkt_data(
Ipeap_pkt* pkt,
Ip_u8* data,
Ip_u32 len);
/*
*===========================================================================
* ipeap_get_pkt_data_size
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_u32
ipeap_get_pkt_data_size(
Ipeap_pkt* pkt);
/*
*===========================================================================
* ipeap_get_pkt_data_buffer
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_u8*
ipeap_get_pkt_data_buffer(
Ipeap_pkt* pkt);
/*
*===========================================================================
* ipeap_compare_pkt_data
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_bool
ipeap_compare_pkt_data(
Ipeap_pkt* pkt,
Ip_u8* data,
Ip_u32 len);
/*
*===========================================================================
* ipeap_memory_to_string
*===========================================================================
* Description: Convert a byte array to a hexadecimal string.
* Parameters: ptr - pointer to a buffer
* size - size of buffer
* alignment - number of bytes between white space
* Returns: A string allocated with ipcom_malloc
*/
IP_GLOBAL char*
ipeap_memory_to_string(
const Ip_u8* ptr,
Ip_u32 size,
Ip_u8 alignment);
/*
*===========================================================================
* ipeap_print_memory
*===========================================================================
* Description: Print a byte array to sys log (level DEBUG2).
* Parameters: prefix - Starting string of print out.
* data - pointer to buffer
* len - length of buffer
* Returns:
*/
IP_GLOBAL void
ipeap_print_memory(
const char* prefix,
const Ip_u8* data,
Ip_u32 len);
/*
*===========================================================================
* ipeap_sim_prf
*===========================================================================
* Description: Pseudo-random-function for EAP SIM.
* Parameters: key - buffer to key value
* key_len - length of key buffer
* buf - buffer for generated value
* buf_len - length of buffer for generated value
* Returns: IPCOM_SUCCESS
* IPCOM_ERR_FAILED
*/
IP_GLOBAL Ip_err
ipeap_sim_prf(
Ip_u8* key,
Ip_u32 key_len,
Ip_u8* buf,
Ip_u32 buf_len);
/*
*===========================================================================
* ipeap_sim_generate_mac
*===========================================================================
* Description: Generate EAP SIM mac value from data.
* Parameters: key - mac key buffer
* key_len - length of mac key buffer
* dataX - data buffer to generate mac for.
* dataX_len - length of data buffer
* mac - buffer for generated mac
* mac_len - length of mac buffer
* Returns: IPCOM_SUCCESS
* IPCOM_ERR_FAILED
*/
IP_GLOBAL Ip_err
ipeap_sim_generate_mac(
Ip_u8* key,
Ip_u32 key_len,
Ip_u8* data1,
Ip_u32 data1_len,
Ip_u8* data2,
Ip_u32 data2_len,
Ip_u8* mac,
Ip_u32 mac_len);
/*
*===========================================================================
* ipeap_sim_verify_mac
*===========================================================================
* Description: Verify EAP SIM mac value for specified data.
* Parameters: key - mac key buffer
* key_len - length of mac key buffer
* dataX - data buffer to verify mac for.
* dataX_len - length of data buffer
* mac - buffer for mac data
* mac_len - length of mac buffer
* Returns: IPCOM_SUCCESS
* IPCOM_ERR_FAILED
*/
IP_GLOBAL Ip_err
ipeap_sim_verify_mac(
Ip_u8* key,
Ip_u32 key_len,
Ip_u8* data1,
Ip_u32 data1_len,
Ip_u8* data2,
Ip_u32 data2_len,
Ip_u8* mac,
Ip_u32 mac_len);
/*
*===========================================================================
* ipeap_sim_aes_cbc_encrypt
*===========================================================================
* Description: Encrypt with AES algorithm
* Parameters: key - buffer for key value
* key_len - length of key buffer
* iv - buffer for iv
* iv_len - length of iv buffer
* data - data buffer to be encrypted
* data_len - length of data buffer
* Returns: IPCOM_SUCCESS
* IPCOM_ERR_FAILED
*/
IP_GLOBAL Ip_err
ipeap_sim_aes_cbc_encrypt(
Ip_u8* key,
Ip_u32 key_len,
Ip_u8* iv,
Ip_u32 iv_len,
Ip_u8* data,
Ip_u32 data_len);
/*
*===========================================================================
* ipeap_sim_aes_cbc_decrypt
*===========================================================================
* Description: Decrypt with AES algorithm
* Parameters: key - buffer for key value
* key_len - length of key buffer
* iv - buffer for iv
* iv_len - length of iv buffer
* data - data buffer to be decrypted
* data_len - length of data buffer
* Returns: IPCOM_SUCCESS
* IPCOM_ERR_FAILED
*/
IP_GLOBAL Ip_err
ipeap_sim_aes_cbc_decrypt(
Ip_u8* key,
Ip_u32 key_len,
Ip_u8* iv,
Ip_u32 iv_len,
Ip_u8* data,
Ip_u32 data_len);
/*
*===========================================================================
* ipeap_sim_algorithm_test
*===========================================================================
* Description: Check algorithms used by mechanism
* Parameters:
* Returns: IPCOM_SUCCESS
* IPCOM_ERR_FAILED
*/
IP_GLOBAL Ip_err
ipeap_sim_algorithm_test(void);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
@@ -0,0 +1,321 @@
/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipeap_tls.c,v $ $Revision: 1.20.12.1 $
* $Source: /home/interpeak/CVSRoot/ipeap/src/ipeap_tls.c,v $
* $Author: hxu4 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Roger Boden <roger@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_syslog.h>
#include <openssl/ssl.h>
#include "ipeap.h"
#include "ipeap_h.h"
#include "ipeap_common_tls.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_STATIC Ip_err ipeap_tls_suppl_process_msg(struct Ipeap_ctx_st *ctx,
struct Ipeap_pkt_st *in_pkt,
struct Ipeap_pkt_st *reply_pkt);
IP_STATIC Ip_err ipeap_tls_suppl_get_key(struct Ipeap_ctx_st* ctx, Ip_u8* key, int key_len);
IP_STATIC Ip_err ipeap_tls_suppl_init(struct Ipeap_ctx_st *ctx);
IP_STATIC Ip_err ipeap_tls_suppl_free(Ipeap_ctx *ctx);
IP_STATIC Ip_err ipeap_tls_suppl_get_session_id(Ipeap_ctx *ctx,Ip_u8 *session_id,Ip_u32 *session_id_len);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
IP_STATIC Ipeap_methods ipeap_tls_suppl_methods =
{
ipeap_tls_suppl_process_msg,
ipeap_tls_suppl_init,
ipeap_tls_suppl_free,
ipeap_tls_suppl_get_key,
IP_NULL,
IP_NULL,
ipeap_tls_suppl_get_session_id
};
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_tls_suppl_init
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_tls_suppl_init(Ipeap_ctx *ctx)
{
Ipeap_tls_suppl_ctx* tls_ctx;
tls_ctx = ipeap_common_tls_ctx_new();
if(!tls_ctx)
return IPCOM_ERR_FAILED;
ctx->mech_data = tls_ctx;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_tls_suppl_free
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_tls_suppl_free(Ipeap_ctx *ctx)
{
Ipeap_tls_suppl_ctx* tls_ctx;
tls_ctx = (Ipeap_tls_suppl_ctx*)ctx->mech_data;
ipeap_common_tls_ctx_free(tls_ctx);
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_tls_suppl_get_key
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_tls_suppl_get_key(struct Ipeap_ctx_st* ctx, Ip_u8* key, int key_len)
{
Ipeap_tls_suppl_ctx *tls_ctx;
tls_ctx = (Ipeap_tls_suppl_ctx*)ctx->mech_data;
return ipeap_tls_common_generate_key(tls_ctx, "client EAP encryption", key, key_len);
}
/*
*===========================================================================
* ipeap_tls_suppl_process_msg
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_tls_suppl_process_msg(Ipeap_ctx *ctx, Ipeap_pkt *in_pkt, Ipeap_pkt *out_pkt)
{
Ip_err rc;
Ipeap_tls_msg *msg;
Ipeap_tls_suppl_ctx* tls_ctx;
msg = IPEAP_PKT2TLSMSG(in_pkt);
tls_ctx = (Ipeap_tls_suppl_ctx*)ctx->mech_data;
switch(msg->code)
{
case IPEAP_MSG_REQUEST:
rc = ipeap_common_tls_handle_frag_and_handshake(ctx, tls_ctx, in_pkt, out_pkt);
switch(rc)
{
case IPEAP_PENDING_SEND_OUT_PKT:
break;
case IPEAP_TLS_HANDSHAKE_COMPLETE:
rc = ipeap_tls_pkt_set_header(out_pkt, IPEAP_PKT_RESPONSE, msg->id, 6, ctx->meth_id, 0);
out_pkt->end += 6;
if(rc != IPCOM_SUCCESS)
return rc;
return IPEAP_PENDING_SEND_OUT_PKT;
case IPEAP_TLS_DATA_AVAILABLE:
IPCOM_LOG0(ERR, "EAP-TLS :: Application data received in TLS handshake");
return IPCOM_ERR_FAILED;
default:
IPCOM_LOG1(ERR, "EAP-TLS :: Unexpected return code from ipeap_common_tls_handle_frag_and_handshake(): %d", rc);
return IPCOM_ERR_FAILED;
}
break;
case IPEAP_MSG_RESPONSE:
IPCOM_LOG0(ERR, "EAP-TLS :: received response msg, dropping msg");
return IPEAP_DROPPED_PKT;
case IPEAP_MSG_FAILURE:
IPCOM_LOG0(ERR, "EAP-TLS :: received EAP failure");
return IPEAP_FAILURE;
case IPEAP_MSG_SUCCESS:
ctx->state = IPEAP_STATE_AUTHENTICATED;
IPCOM_LOG0(INFO, "EAP-TLS ::Received EAP success");
return IPEAP_SUCCESS;
default:
IPCOM_LOG1(ERR, "EAP-TLS :: received unknown msg type: %d, dropping msg", msg->code);
return IPEAP_DROPPED_PKT;
}
return rc;
}
/*
*===========================================================================
* ipeap_tls_suppl_get_session_id
*===========================================================================
*
*/
IP_STATIC Ip_err
ipeap_tls_suppl_get_session_id(
Ipeap_ctx *ctx,
Ip_u8 *session_id,
Ip_u32 *session_id_len
)
{
Ip_err rc = IPCOM_SUCCESS;
Ipeap_tls_suppl_ctx *tls_ctx = IP_NULL;
IPCOM_LOG0(DEBUG, "IPEAP-TLS :: Get Session-Id :: ");
if(!ctx)
{
IPCOM_LOG0(ERR, "ipeap_tls_suppl_get_session_id - NULL EAP ctx");
return IPCOM_ERR_INVALID_ARG;
}
tls_ctx = (Ipeap_tls_suppl_ctx*)ctx->mech_data;
if(!tls_ctx)
{
IPCOM_LOG0(ERR, "ipeap_tls_suppl_get_session_id - NULL EAP-TLS ctx");
return IPCOM_ERR_FAILED;
}
rc = ipeap_tls_common_generate_session_id(tls_ctx,IPEAP_TYPE_TLS,session_id,session_id_len);
return rc;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_tls_suppl_methods_get
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ipeap_methods*
ipeap_tls_suppl_methods_get(void)
{
return &ipeap_tls_suppl_methods;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,844 @@
/* ipeap_wsc.c - EAP WSC implementation */
/*
* Copyright (c) 2008 Wind River Systems, Inc.
*
* The right to copy, distribute, modify, or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*
*/
/*
modification history
--------------------
01g,18mar09,dwb Adding IPWPS macros
01e,26feb09,dwb More work for fragmentation support
01d,17feb09,dwb Adding fragmentation support
01c,12feb09,dwb Ongoing development for wsc message handling
01b,03feb09,dwb EAP WPS Implementation
01a,24Dec08,mry Created
*/
/* DESCRIPTION:
* ===========
* This library contains the EAP WSC implementation as described in
* "WiFi Protected Setup Specification, v1.0h, Dec 2006".
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipeap_config.h"
#ifdef IPEAP_USE_EAP_WSC
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_syslog.h>
#include "ipeap.h"
#include "ipeap_h.h"
#ifdef IPWPS
#include "ipwps_private_api.h"
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPEAP_WSC_HEADER_LEN 14
#define IPEAP_TYPE_WSC IPEAP_TYPE_EXPANDED
#define IPEAP_WSC_VENDOR_TYPE IPEAP_VT_WSC_SIMPLE_CONFIG
#define IPEAP_WSC_START 0x01
#define IPEAP_WSC_ACK 0x02
#define IPEAP_WSC_NACK 0x03
#define IPEAP_WSC_MSG 0x04
#define IPEAP_WSC_DONE 0x05
#define IPEAP_WSC_FRAG_ACK 0x06
#define IPEAP_WSC_FLAGS_MF 0x01 /* More Fragments */
#define IPEAP_WSC_FLAGS_LF 0x02 /* Length Field */
/* 0x04 to 0x80 are reserved */
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef enum {
IPEAP_WSC_STATE_TBD = 0
} Ipeap_wsc_state;
typedef struct Ipeap_wsc_ctx_st
{
Ipeap_wsc_state state;
char peer_identity[IPEAP_IDENTITY_MAX_LEN];
Ip_u8 msg_id;
Ip_u8 opcode;
#ifdef IPWPS
Ipwps_proto_data wsc_msg;
Ipwps_proto_data *resp_data;
#endif
Ip_u16 msg_data_tot;
Ip_u32 frag_bytes_sent;
} Ipeap_wsc_ctx;
typedef struct Ipeap_wsc_msg_hdr_st {
Ipeap_expanded_pkt_hdr exp_eap_hdr;
Ip_u8 opcode;
Ip_u8 flags;
} Ipeap_wsc_msg_hdr;
typedef struct Ipeap_wsc_msg_st
{
Ipeap_wsc_msg_hdr hdr;
Ip_u8 msg_data[1];
} Ipeap_wsc_msg;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
IP_EXTERN Ipeap_vendor_id ipeap_wsc_vendor_id;
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_STATIC Ip_err ipeap_wsc_process_msg(struct Ipeap_ctx_st *ctx,
struct Ipeap_pkt_st *in_pkt,
struct Ipeap_pkt_st *reply_pkt);
IP_STATIC Ip_err ipeap_wsc_init(struct Ipeap_ctx_st *ctx);
IP_STATIC Ip_err ipeap_wsc_free(Ipeap_ctx *ctx);
IP_PUBLIC Ip_err ipeap_wsc_display_status(struct Ipeap_ctx_st* ctx, char *str);
#ifdef IPWPS
IP_STATIC Ip_err ipeap_wsc_assemble_wsc_msg(struct Ipeap_ctx_st* ctx,
Ipeap_wsc_msg *in_msg, Ip_u8 **msg_data, Ip_u16 *msg_len,
Ipeap_pkt* out_pkt);
IP_STATIC Ip_err ipeap_wsc_fragment_wsc_msg(struct Ipeap_ctx_st* ctx,
Ipwps_proto_data **wsc_resp_data, Ip_u8 opcode, Ipeap_pkt* out_pkt);
IP_STATIC Ip_err
ipeap_wsc_packet_set_wsc_header(Ip_u16 len, Ip_u8 opcode, Ip_u8 flags,
Ipeap_pkt* out_pkt);
IP_STATIC Ip_err ipeap_wsc_eap_failure(struct Ipeap_ctx_st* ctx,
Ipeap_pkt* out_pkt);
#endif
/*
*
****************************************************************************
* 8 DATA
****************************************************************************
*/
IP_STATIC Ipeap_methods ipeap_wsc_methods =
{
ipeap_wsc_process_msg,
ipeap_wsc_init,
ipeap_wsc_free,
IP_NULL,
IP_NULL,
ipeap_wsc_display_status,
IP_NULL
};
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipeap_wsc_init
*===========================================================================
* Description: Initialize EAP wsc context.
* Parameters: ctx - The EAP wsc context.
* Returns:
* IPCOM_SUCCESS
* IPCOM_ERR_NO_MEMORY
* IPCOM_ERR_INVALID_ARG
*/
IP_STATIC Ip_err
ipeap_wsc_init(Ipeap_ctx* ctx)
{
#ifndef IPWPS
/* EAP WSC is not supported without WPS support being included */
IPCOM_LOG1(CRIT, "%sEAP-WSC :: Cannot use EAP-WSC since WPS support missing.", ctx->syslog_prefix);
return IPCOM_ERR_NOT_SUPPORTED;
#else
Ip_err err = IPCOM_SUCCESS;
Ipeap_wsc_ctx* wsc_ctx = IP_NULL;
wsc_ctx = ipcom_calloc(1, sizeof(*wsc_ctx));
if (IP_NULL == wsc_ctx)
{
IPCOM_LOG1(CRIT, "%sEAP-WSC :: Out of memory", ctx->syslog_prefix);
err = IPCOM_ERR_NO_MEMORY;
}
else
{
ctx->mech_data = wsc_ctx;
ctx->state = IPEAP_STATE_INIT;
wsc_ctx->state = IPEAP_WSC_STATE_TBD;
wsc_ctx->msg_id = 1;
wsc_ctx->wsc_msg.len = 0;
wsc_ctx->msg_data_tot = 0;
wsc_ctx->resp_data = IP_NULL;
}
return err;
#endif
}
/*
*===========================================================================
* ipeap_wsc_free
*===========================================================================
* Description: Free EAP wsc context.
* Parameters: ctx - The EAP context.
* Returns: IPCOM_SUCCESS
*/
IP_STATIC Ip_err
ipeap_wsc_free(Ipeap_ctx* ctx)
{
Ipeap_wsc_ctx* wsc_ctx = IP_NULL;
if ((ctx != IP_NULL) && (ctx->mech_data != IP_NULL))
{
wsc_ctx = (Ipeap_wsc_ctx*)ctx->mech_data;
ipcom_free(wsc_ctx);
ctx->mech_data = IP_NULL;
}
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_wsc_process_msg
*===========================================================================
* Description: Process a message.
* Parameters: ctx - The EAP context.
* in_pkt - The request packet (message).
* out_pkt - The created response packet (message).
* Returns:
* IPEAP_SUCCESS
* IPEAP_PENDING_SEND_OUT_PKT
* IPEAP_FAILURE
* IPEAP_DROPPED_PKT
*/
IP_STATIC Ip_err
ipeap_wsc_process_msg(
Ipeap_ctx* ctx,
Ipeap_pkt* in_pkt,
Ipeap_pkt* out_pkt)
{
#ifndef IPWPS
return IPEAP_DROPPED_PKT;
#else
Ip_err err = IPEAP_FAILURE;
Ipeap_wsc_msg* in_msg = IP_NULL;
Ipeap_wsc_ctx* wsc_ctx = (Ipeap_wsc_ctx*)ctx->mech_data;
#ifdef IPWPS
Ipwps_wsc_proto_msg *event_data = IP_NULL;
Ipwps_proto_data *resp_data = IP_NULL;
Ipwps_wsc_rc event_rc = IPWPS_WSC_RC_NOT_SET;
#endif
ip_assert(wsc_ctx);
in_msg = (Ipeap_wsc_msg*)IPEAP_PKT2MSG(in_pkt);
/* Sanity check, always at least 4 bytes size */
if ((in_pkt->end - in_pkt->start) < 4)
{
IPCOM_LOG1(ERR, "%sEAP-WSC :: Bad in packet", ctx->syslog_prefix);
return IPEAP_DROPPED_PKT;
}
switch (in_msg->hdr.exp_eap_hdr.code)
{
case IPEAP_MSG_REQUEST:
case IPEAP_MSG_RESPONSE:
{
Ip_u16 len = 0;
int event = -1;
Ip_u8 *msg_data = IP_NULL;
Ip_u8 wsc_opcode;
#if 0
Ipeap_wsc_msg_hdr *wsc_msg_hdr;
wsc_msg_hdr =
(Ipeap_wsc_msg_hdr *)IPEAP_PKT2MSG(out_pkt);
#endif
/* Fix up the eap code and id */
if(in_msg->hdr.exp_eap_hdr.code == IPEAP_MSG_REQUEST) {
(void)ipeap_pkt_set_header(out_pkt, IPEAP_PKT_RESPONSE,
in_msg->hdr.exp_eap_hdr.id, IPEAP_WSC_HEADER_LEN,
IPEAP_TYPE_EXPANDED);
} else {
/* Validate the id */
if(in_msg->hdr.exp_eap_hdr.id != wsc_ctx->msg_id) {
IPCOM_LOG1(DEBUG, "%sEAP-WSC :: Id mismatch!",
ctx->syslog_prefix);
return IPEAP_DROPPED_PKT;
}
wsc_ctx->msg_id++;
if((err = ipeap_pkt_set_header(out_pkt, IPEAP_PKT_REQUEST,
wsc_ctx->msg_id, IPEAP_WSC_HEADER_LEN,
IPEAP_TYPE_EXPANDED)) != IPCOM_SUCCESS)
return IPEAP_DROPPED_PKT;
}
if ( (in_msg->hdr.exp_eap_hdr.type == IPEAP_TYPE_IDENTITY) &&
(in_msg->hdr.exp_eap_hdr.code == IPEAP_MSG_RESPONSE) ) {
len = IP_GET_NTOHS(&in_msg->hdr.exp_eap_hdr.len);
len -= IPEAP_PKT_HDR_LEN;
if (len >= IPEAP_IDENTITY_MAX_LEN)
len = IPEAP_IDENTITY_MAX_LEN-1;
ipcom_memcpy(wsc_ctx->peer_identity,
((Ipeap_msg *)in_msg)->data, len);
wsc_ctx->peer_identity[len] = '\0';
IPCOM_LOG2(DEBUG2, "%sEAP-WSC :: Received EAP"
" Response/Identity (%s). Passing to IPWPS"
" module.\n",
ctx->syslog_prefix, wsc_ctx->peer_identity);
len++;
msg_data = (Ip_u8 *)wsc_ctx->peer_identity;
event = IPWPS_WSC_EVENT_RCV_ID_RESP;
} else if ( in_msg->hdr.exp_eap_hdr.type ==
IPEAP_TYPE_EXPANDED ) {
/* Note, this will send the frag ack */
if((err = ipeap_wsc_assemble_wsc_msg(ctx, in_msg, &msg_data, &len,
out_pkt)) != IPCOM_SUCCESS)
return err;
switch (in_msg->hdr.opcode) {
case IPEAP_WSC_START:
event = IPWPS_WSC_EVENT_RCV_WSC_START;
break;
case IPEAP_WSC_ACK:
event = IPWPS_WSC_EVENT_RCV_WSC_ACK;
break;
case IPEAP_WSC_NACK:
event = IPWPS_WSC_EVENT_RCV_WSC_NACK;
break;
case IPEAP_WSC_MSG:
event = IPWPS_WSC_EVENT_RCV_WSC_MSG;
break;
case IPEAP_WSC_DONE:
event = IPWPS_WSC_EVENT_RCV_WSC_DONE;
break;
case IPEAP_WSC_FRAG_ACK:
IPCOM_LOG1(DEBUG2, "\n\n%sEAP-WSC :: ********** Received Frag ACK"
" Message **********\n\n",ctx->syslog_prefix);
return ipeap_wsc_fragment_wsc_msg(ctx, IP_NULL, 0, out_pkt);
default:
err = IPEAP_FAILURE;
break;
}
} else {
IPCOM_LOG2(ERR, "%sEAP-WSC :: Received unexptected"
" request/response type: %d, dropping message",
ctx->syslog_prefix, in_msg->hdr.exp_eap_hdr.type);
return IPEAP_DROPPED_PKT;
}
if( (event >= IPWPS_WSC_EVENT_RCV_ID_RESP) &&
(event <= IPWPS_WSC_EVENT_RCV_EAP_FAIL) ) {
event_data = ipwps_create_proto_msg_data(event,len, msg_data);
}
if (event_data) {
err = ipwps_handle_wsc_event(event_data, &event_rc,
&resp_data);
if ((err < 0) || (event_rc < 0)) {
err = ipeap_wsc_eap_failure(ctx, out_pkt);
}
} else {
IPCOM_LOG1(ERR, "%sEAP-WSC :: Failed to allocate wps event "
"data structure.", ctx->syslog_prefix);
err = ipeap_wsc_eap_failure(ctx, out_pkt);
}
if(err == IPCOM_SUCCESS) {
switch(event_rc) {
case IPWPS_WSC_RC_OK:
break;
case IPWPS_WSC_RC_SEND_WSC_START:
wsc_opcode = IPEAP_WSC_START;
break;
case IPWPS_WSC_RC_SEND_WSC_ACK:
wsc_opcode = IPEAP_WSC_ACK;
break;
case IPWPS_WSC_RC_SEND_WSC_NACK:
wsc_opcode = IPEAP_WSC_NACK;
break;
case IPWPS_WSC_RC_SEND_WSC_MSG:
wsc_opcode = IPEAP_WSC_MSG;
break;
case IPWPS_WSC_RC_SEND_WSC_DONE:
wsc_opcode = IPEAP_WSC_DONE;
break;
default:
wsc_opcode = IPEAP_WSC_START;
break;
}
/* Frame up the packet to be sent */
if( (event_rc > IPWPS_WSC_RC_OK) &&
(event_rc < IPWPS_WSC_RC_TERMINATE_EAP) ) {
err = ipeap_wsc_fragment_wsc_msg(ctx, &resp_data,
wsc_opcode, out_pkt);
/* Terminate the conversation */
} else if ( (event_rc == IPWPS_WSC_RC_TERMINATE_EAP) ||
(event_rc < 0) ) {
err = ipeap_wsc_eap_failure(ctx, out_pkt);
} else if (event_rc == IPWPS_WSC_RC_OK) {
/* DO Nothing */
IPCOM_LOG1(ERR, "%sEAP-WSC :: IPWPS_WSC_RC_OK event type: doing nothing", ctx->syslog_prefix);
err = IPEAP_DROPPED_PKT;
} else {
IPCOM_LOG2(ERR, "%sEAP-WSC :: unknown event type: %d,"
" dropping message", ctx->syslog_prefix,
in_msg->hdr.exp_eap_hdr.code);
err = IPEAP_DROPPED_PKT;
}
} else if (err != IPCOM_SUCCESS) {
IPCOM_LOG3(ERR, "%sEAP-WSC :: ipwps_handle_wsc_event not"
" successful, err = %d, event_rc = %d",
ctx->syslog_prefix, err, event_rc);
err = IPEAP_FAILURE;
}
if(resp_data) {
ipcom_free(resp_data);
}
break;
}
case IPEAP_MSG_FAILURE:
IPCOM_LOG1(DEBUG2, "%sEAP-WSC :: Received EAP FAILURE. Passing to"
" IPWPS module.",ctx->syslog_prefix);
event_data =
ipwps_create_proto_msg_data(IPWPS_WSC_EVENT_RCV_EAP_FAIL, 0,
IP_NULL);
err = ipwps_handle_wsc_event(event_data, &event_rc, &resp_data);
if(resp_data) {
ipcom_free(resp_data);
}
break;
case IPEAP_MSG_SUCCESS:
IPCOM_LOG1(ERR, "%sEAP-WSC :: Received Unexpected EAP SUCCESS, dropping.",
ctx->syslog_prefix);
err = IPEAP_DROPPED_PKT;
break;
default:
IPCOM_LOG2(ERR, "%sEAP-WSC :: Received unknown message type: %d, dropping message",
ctx->syslog_prefix, in_msg->hdr.exp_eap_hdr.code);
err = IPEAP_DROPPED_PKT;
break;
}
if (event_data)
ipcom_free(event_data);
return err;
#endif
}
/*
*===========================================================================
* ipeap_wsc_methods_get
*===========================================================================
*/
IP_PUBLIC Ipeap_methods*
ipeap_wsc_methods_get(void)
{
return &ipeap_wsc_methods;
}
/*
*===========================================================================
* Ipeap_wsc_state_name
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC char *Ipeap_wsc_state_name(int state) {
return "UNKNOWN STATE";
}
/*
*===========================================================================
* ipeap_wsc_display_status
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
ipeap_wsc_display_status(struct Ipeap_ctx_st* ctx, char *str) {
Ipeap_wsc_ctx* wsc_ctx = (Ipeap_wsc_ctx*)ctx->mech_data;
ipcom_printf(" WSC state = %s\n", Ipeap_wsc_state_name(wsc_ctx->state));
return IPCOM_SUCCESS;
}
#ifdef IPWPS
/*
*===========================================================================
* ipeap_wsc_assemble_wsc_msg
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err ipeap_wsc_assemble_wsc_msg(struct Ipeap_ctx_st* ctx,
Ipeap_wsc_msg *in_msg, Ip_u8 **wsc_data, Ip_u16 *wsc_len, Ipeap_pkt* out_pkt)
{
Ip_u16 len;
Ip_err err;
#if 0
Ipeap_wsc_msg_hdr *wsc_msg_hdr;
#endif
Ip_u8 *msg_data = IP_NULL;
Ipeap_wsc_ctx* wsc_ctx = (Ipeap_wsc_ctx*)ctx->mech_data;
#if 0
wsc_msg_hdr =
(Ipeap_wsc_msg_hdr *)IPEAP_PKT2MSG(out_pkt);
#endif
len = IP_GET_NTOHS(&in_msg->hdr.exp_eap_hdr.len);
if (len < IPEAP_PKT_HDR_LEN+1) {
IPCOM_LOG1(DEBUG, "%sEAP-WSC :: Received BAD EAP"
" packet. Dropping.\n",
ctx->syslog_prefix);
return IPEAP_DROPPED_PKT;
}
len -= IPEAP_WSC_HEADER_LEN;
msg_data = (Ip_u8 *)(((Ip_u8 *)in_msg)+IPEAP_WSC_HEADER_LEN);
/* This is not a fragmented message so we're done */
if( (wsc_ctx->msg_data_tot == 0) &&
!(in_msg->hdr.flags & IPEAP_WSC_FLAGS_MF) ) {
IPCOM_LOG1(DEBUG2, "%sEAP-WSC :: ********** Received non-fragmented"
" Message **********",ctx->syslog_prefix);
*wsc_data = msg_data;
*wsc_len = len;
return IPCOM_SUCCESS;
/* Process wsc message fragments */
} else if (in_msg->hdr.flags & IPEAP_WSC_FLAGS_MF) {
/* If this was the first fragment, the LF should be set */
if(in_msg->hdr.flags & IPEAP_WSC_FLAGS_LF) {
IPCOM_LOG1(DEBUG2, "%sEAP-WSC :: ********** Received first "
"message fragment **********",ctx->syslog_prefix);
len-=2;
wsc_ctx->wsc_msg.len = IP_GET_NTOHS(msg_data);
msg_data+=2;
/* Not first fragment but not the last */
} else {
IPCOM_LOG1(DEBUG2, "%sEAP-WSC :: ********** Received middle fragment"
" **********",ctx->syslog_prefix);
}
/* Frag Ack for both of the above situations */
if((err = ipeap_wsc_packet_set_wsc_header(IPEAP_WSC_HEADER_LEN,
IPEAP_WSC_FRAG_ACK,0,out_pkt)) != IPCOM_SUCCESS)
return err;
IPCOM_LOG1(DEBUG2, "%sEAP-WSC :: ********** Sending FRAG ACK"
" Message **********",
ctx->syslog_prefix);
err = IPEAP_PENDING_SEND_OUT_PKT;
/* Check if this is the last fragment */
} else {
IPCOM_LOG1(DEBUG2, "%sEAP-WSC :: ********** Received last fragment"
" **********",ctx->syslog_prefix);
/* Validate that we haven't got too many bytes */
if ((wsc_ctx->msg_data_tot+len) != wsc_ctx->wsc_msg.len) {
IPCOM_LOG3(ERR,"%sEAP-WSC :: Expected %d bytes but have"
" received (%d bytes)",
ctx->syslog_prefix,wsc_ctx->wsc_msg.len,
wsc_ctx->msg_data_tot);
return IPEAP_DROPPED_PKT;
}
/* Release the message data */
*wsc_data = &wsc_ctx->wsc_msg.data[0];
*wsc_len = wsc_ctx->wsc_msg.len;
err = IPCOM_SUCCESS;
}
/* Concat the fragment */
if(len <= (IPWPS_PROTO_MSG_DATALEN_MAX-wsc_ctx->msg_data_tot)) {
IPCOM_LOG3(DEBUG2, "%sEAP-WSC :: ********** Concating %d bytes of"
" data, msg_data_tot: %d **********",ctx->syslog_prefix,
len,wsc_ctx->msg_data_tot);
ipcom_memcpy(&wsc_ctx->wsc_msg.data[wsc_ctx->msg_data_tot],
msg_data,len);
wsc_ctx->msg_data_tot += len;
/* Reset */
if(wsc_ctx->msg_data_tot == wsc_ctx->wsc_msg.len) {
IPCOM_LOG1(DEBUG2, "%sEAP-WSC :: ********** Resetting"
" msg_data_tot **********",ctx->syslog_prefix);
wsc_ctx->msg_data_tot = 0;
wsc_ctx->wsc_msg.len = 0;
}
} else {
/* Reset */
wsc_ctx->msg_data_tot = 0;
wsc_ctx->wsc_msg.len = 0;
}
return err;
}
/*
*===========================================================================
* ipeap_wsc_fragment_wsc_msg
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_wsc_fragment_wsc_msg(struct Ipeap_ctx_st* ctx, Ipwps_proto_data **wsc_resp_data,
Ip_u8 opcode, Ipeap_pkt* out_pkt)
{
Ip_err err;
Ip_u8 flags = 0;
Ipwps_proto_data *resp_data = IP_NULL;
Ip_u16 resp_data_len = 0;
Ip_u32 resp_data_tot = 0;
Ip_u16 header_size = IPEAP_WSC_HEADER_LEN;
Ipeap_wsc_msg_hdr *wsc_stub;
Ipeap_wsc_ctx* wsc_ctx = (Ipeap_wsc_ctx*)ctx->mech_data;
wsc_stub = (Ipeap_wsc_msg_hdr *)IPEAP_PKT2MSG(out_pkt);
/* Check for response data or data in the fragment buffer */
if(wsc_resp_data != IP_NULL) {
resp_data = *wsc_resp_data;
if(resp_data != IP_NULL) resp_data_len += resp_data->len;
resp_data_tot = resp_data_len;
} else if (wsc_ctx->resp_data != IP_NULL) {
resp_data_len += (wsc_ctx->resp_data->len - wsc_ctx->frag_bytes_sent);
}
/* We have response data. Fragment it if necessary */
if( resp_data_len > IPEAP_MTU ) {
resp_data_len = IP_MIN(resp_data_len, IPEAP_MTU-header_size);
resp_data_len = IP_MIN(resp_data_len, IPEAP_PKT_GET_SPACE_LEFT(out_pkt));
/* This is the first fragment */
if((wsc_ctx->resp_data == IP_NULL) && (resp_data != IP_NULL)) {
/* This message must be fragmented and this is the first
* fragment. Place the total resp_data length at the end
* of the header */
wsc_ctx->frag_bytes_sent = 0;
flags |= IPEAP_WSC_FLAGS_LF;
IP_SET_HTONS((Ip_u8 *)(((Ip_u8 *)wsc_stub)+
IPEAP_WSC_HEADER_LEN),resp_data_tot);
wsc_ctx->resp_data = resp_data;
wsc_ctx->opcode = opcode;
header_size+=2;
resp_data_len-=2;
ipcom_memcpy((Ip_u8 *)(((Ip_u8 *)wsc_stub)+header_size),
&(resp_data->data[0]),resp_data_len);
*wsc_resp_data = IP_NULL;
IPCOM_LOG1(DEBUG2, "%sEAP-WSC :: ********** Sending First Fragment"
" **********",
ctx->syslog_prefix);
} else if(wsc_ctx->resp_data != IP_NULL) {
ipcom_memcpy((Ip_u8 *)(((Ip_u8 *)wsc_stub)+header_size),
&(wsc_ctx->resp_data->data[wsc_ctx->frag_bytes_sent]),
resp_data_len);
opcode = wsc_ctx->opcode;
IPCOM_LOG1(DEBUG2, "%sEAP-WSC :: ********** Sending Middle Fragment"
" **********",
ctx->syslog_prefix);
}
flags |= IPEAP_WSC_FLAGS_MF;
wsc_ctx->frag_bytes_sent += resp_data_len;
/* This is the last fragment */
} else if (wsc_ctx->resp_data != IP_NULL) {
ipcom_memcpy((Ip_u8 *)(((Ip_u8 *)wsc_stub)+header_size),
&(wsc_ctx->resp_data->data[wsc_ctx->frag_bytes_sent]),
resp_data_len);
opcode = wsc_ctx->opcode;
ipcom_free(wsc_ctx->resp_data);
wsc_ctx->resp_data = IP_NULL;
wsc_ctx->frag_bytes_sent = 0;
IPCOM_LOG1(DEBUG2, "%sEAP-WSC :: ********** Sending Last Fragment"
" **********",
ctx->syslog_prefix);
ipcom_free(wsc_ctx->resp_data);
/* No fragmentation is required */
} else if (resp_data_len > 0) {
IPCOM_LOG1(DEBUG2, "%sEAP-WSC :: ********** Sending Non-Fragment"
" **********",
ctx->syslog_prefix);
ipcom_memcpy((Ip_u8 *)(((Ip_u8 *)wsc_stub)+header_size),
&(resp_data->data[0]), resp_data_len);
}
if((err = ipeap_wsc_packet_set_wsc_header(header_size+resp_data_len,opcode,
flags,out_pkt)) != IPCOM_SUCCESS)
return err;
return IPEAP_PENDING_SEND_OUT_PKT;
}
/*
*===========================================================================
* ipeap_wsc_packet_set_header
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipeap_wsc_packet_set_wsc_header(Ip_u16 len, Ip_u8 opcode, Ip_u8 flags,
Ipeap_pkt* out_pkt)
{
Ipeap_wsc_msg_hdr *wsc_stub;
if(out_pkt->max_len - out_pkt->start < 4)
return IPEAP_FAILURE;
wsc_stub = (Ipeap_wsc_msg_hdr *)IPEAP_PKT2MSG(out_pkt);
wsc_stub->exp_eap_hdr.type = IPEAP_TYPE_EXPANDED;
IP_SET_HTONS(&wsc_stub->exp_eap_hdr.len,len);
ipcom_memcpy(&wsc_stub->exp_eap_hdr.vendor_id.smi, &ipeap_wsc_vendor_id,
IPEAP_VENDOR_ID_LEN);
IP_SET_HTONL(&wsc_stub->exp_eap_hdr.vendor_type,
IPEAP_VT_WSC_SIMPLE_CONFIG);
wsc_stub->opcode = opcode;
wsc_stub->flags = flags;
out_pkt->end += len;
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* ipeap_wsc_eap_failure
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err ipeap_wsc_eap_failure(struct Ipeap_ctx_st* ctx, Ipeap_pkt* out_pkt)
{
Ipeap_wsc_msg_hdr * wsc_msg_hdr =
(Ipeap_wsc_msg_hdr *)IPEAP_PKT2MSG(out_pkt);
IPCOM_LOG1(DEBUG2, "%sEAP-WSC :: Sending EAP-Failure",
ctx->syslog_prefix);
if(ipeap_pkt_set_header(out_pkt, IPEAP_MSG_FAILURE,
wsc_msg_hdr->exp_eap_hdr.id, IPEAP_PKT_HDR_LEN-1,
IPEAP_TYPE_UNDEFINED) != IPCOM_SUCCESS) {
return IPEAP_FAILURE;
}
out_pkt->end += IPEAP_PKT_HDR_LEN-1;
/* Free the contexts */
if(ctx->cb && ctx->cb->free)
(void)ctx->cb->free(ctx);
ctx->cb = IP_NULL;
return IPEAP_PENDING_SEND_OUT_PKT;
}
#endif
#endif