blob: 7d67d72a9a88904f6efcdf1400a05206039f4dc3 [file] [log] [blame]
/**
* @file smComSocket_linux.c
* @author NXP Semiconductors
* @version 1.0
* @par License
*
* Copyright 2016,2020 NXP
* SPDX-License-Identifier: Apache-2.0
*
* @par Description
*
*/
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <assert.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <time.h>
#include <netdb.h>
#include "smCom.h"
#include "smComSocket.h"
#include "sm_printf.h"
#include "sm_types.h"
#include "nxLog_smCom.h"
#include "nxEnsure.h"
// Enable define of LOG_SOCK to echo APDU cmd/rsp
// #define LOG_SOCK
// Enable define of CHECK_ON_ATR to enable check on returned ATR (don't enable this when using the Smart Card Server ...)
// #define CHECK_ON_ATR
#define REMOTE_JC_SHELL_HEADER_LEN (4)
#define REMOTE_JC_SHELL_MSG_TYPE_APDU_DATA (0x01)
#include "sm_apdu.h"
#define MAX_BUF_SIZE (MAX_APDU_BUF_LENGTH)
typedef struct
{
int sockfd;
char * ipString;
} socket_Context_t;
static socket_Context_t sockCtx;
static socket_Context_t* pSockCtx = (socket_Context_t *)&sockCtx;
static U32 smComSocket_GetATR(U8* pAtr, U16* atrLen);
U16 smComSocket_Close()
{
if (pSockCtx->ipString != NULL)
free(pSockCtx->ipString);
pSockCtx->ipString = NULL;
close(pSockCtx->sockfd);
return SW_OK;
}
U16 smComSocket_Open(void** conn_ctx, U8 *pIpAddrString, U16 portNo, U8* pAtr, U16* atrLen)
{
int portno;
int nAtr = 0;
struct sockaddr_in serv_addr;
struct hostent *server;
U16 sw = SMCOM_COM_FAILED;
ENSURE_OR_GO_EXIT(pIpAddrString != NULL);
portno = portNo;
pSockCtx->sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (pSockCtx->sockfd < 0)
{
printf("ERROR opening socket");
return SMCOM_COM_FAILED;
}
pSockCtx->ipString = malloc(strlen((char*)pIpAddrString)+1);
strcpy(pSockCtx->ipString, (char*)pIpAddrString);
server = gethostbyname(pSockCtx->ipString);
if (server == NULL)
{
fprintf(stderr,"ERROR, no such host: %s\r\n", pSockCtx->ipString);
return SMCOM_COM_FAILED;
}
memset((char *) &serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
memcpy((char *)&serv_addr.sin_addr.s_addr,
(char *)server->h_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(pSockCtx->sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
{
printf("ERROR connecting\r\n");
return SMCOM_PROTOCOL_FAILED;
}
sw = smCom_Init(smComSocket_Transceive, smComSocket_TransceiveRaw);
if (sw != SMCOM_OK)
goto exit;
nAtr = smComSocket_GetATR(pAtr, atrLen);
#ifdef CHECK_ON_ATR
// Be aware that the smart card server (java app on PC) does not return the ATR value
// Do not enable this code when using the smart card server
if (nAtr == 0)
{
sw = SMCOM_NO_ATR;
}
#endif
exit:
return sw;
}
/**
Remote JC Terminal spec:
Wait for card (MTY=0x00)
The payload contains four bytes denoting the time in milliseconds the remote part will wait for card insertion.
The bytes are sent in big endian format.
The reply message contains the full ATR as payload.
A reply message with 0 bytes length means that the terminal could not trigger an ATR (reason might be retrieved using MTY=3 or MTY=2.
*/
static U32 smComSocket_GetATR(U8* pAtr, U16* atrLen)
{
return smComSocket_GetATRFD(sockCtx.sockfd, pAtr, atrLen);
}
U32 smComSocket_Transceive(void* conn_ctx, apdu_t * pApdu)
{
return smComSocket_TransceiveFD(pSockCtx->sockfd, pApdu);
}
U32 smComSocket_TransceiveRaw(void* conn_ctx, U8 * pTx, U16 txLen, U8 * pRx, U32 * pRxLen)
{
return smComSocket_TransceiveRawFD(pSockCtx->sockfd, pTx, txLen, pRx, pRxLen);
}