 389ff92cc1
			
		
	
	
		389ff92cc1
		
			
		
	
	
	
	
		
			
			* Makefile, Scripts: new linter * About: remove ID from IC * Firmware: remove double define for DIVC/DIVR * Scripts: check folder names too. Docker: replace syntax check with make lint. * Reformat Sources and Migrate to new file naming convention * Docker: symlink clang-format-12 to clang-format * Add coding style guide
		
			
				
	
	
		
			397 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			397 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
 | |
| /******************************************************************************
 | |
|   * \attention
 | |
|   *
 | |
|   * <h2><center>© COPYRIGHT 2020 STMicroelectronics</center></h2>
 | |
|   *
 | |
|   * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
 | |
|   * You may not use this file except in compliance with the License.
 | |
|   * You may obtain a copy of the License at:
 | |
|   *
 | |
|   *        www.st.com/myliberty
 | |
|   *
 | |
|   * Unless required by applicable law or agreed to in writing, software 
 | |
|   * distributed under the License is distributed on an "AS IS" BASIS, 
 | |
|   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
 | |
|   * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 | |
|   * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
 | |
|   * See the License for the specific language governing permissions and
 | |
|   * limitations under the License.
 | |
|   *
 | |
| ******************************************************************************/
 | |
| 
 | |
| /*
 | |
|  *      PROJECT:   ST25R391x firmware
 | |
|  *      Revision:
 | |
|  *      LANGUAGE:  ISO C99
 | |
|  */
 | |
| 
 | |
| /*! \file rfal_t4t.h
 | |
|  *
 | |
|  *  \author Gustavo Patricio
 | |
|  *
 | |
|  *  \brief Provides convenience methods and definitions for T4T (ISO7816-4)
 | |
|  *  
 | |
|  *  This module provides an interface to exchange T4T APDUs according to 
 | |
|  *  NFC Forum T4T and ISO7816-4
 | |
|  *  
 | |
|  *  This implementation was based on the following specs:
 | |
|  *    - ISO/IEC 7816-4  3rd Edition 2013-04-15
 | |
|  *    - NFC Forum T4T Technical Specification 1.0 2017-08-28
 | |
|  *  
 | |
|  */
 | |
| 
 | |
| /*
 | |
|  ******************************************************************************
 | |
|  * INCLUDES
 | |
|  ******************************************************************************
 | |
|  */
 | |
| #include "rfal_t4t.h"
 | |
| #include "utils.h"
 | |
| 
 | |
| /*
 | |
|  ******************************************************************************
 | |
|  * ENABLE SWITCH
 | |
|  ******************************************************************************
 | |
|  */
 | |
| 
 | |
| #ifndef RFAL_FEATURE_T4T
 | |
| #define RFAL_FEATURE_T4T false /* T4T module configuration missing. Disabled by default */
 | |
| #endif
 | |
| 
 | |
| #if RFAL_FEATURE_T4T
 | |
| 
 | |
| /*
 | |
|  ******************************************************************************
 | |
|  * GLOBAL DEFINES
 | |
|  ******************************************************************************
 | |
|  */
 | |
| #define RFAL_T4T_OFFSET_DO 0x54U /*!< Tag value for offset BER-TLV data object          */
 | |
| #define RFAL_T4T_LENGTH_DO 0x03U /*!< Len value for offset BER-TLV data object          */
 | |
| #define RFAL_T4T_DATA_DO 0x53U /*!< Tag value for data BER-TLV data object            */
 | |
| 
 | |
| #define RFAL_T4T_MAX_LC 255U /*!< Maximum Lc value for short Lc coding              */
 | |
| /*
 | |
| ******************************************************************************
 | |
| * GLOBAL TYPES
 | |
| ******************************************************************************
 | |
| */
 | |
| 
 | |
| /*
 | |
| ******************************************************************************
 | |
| * GLOBAL MACROS
 | |
| ******************************************************************************
 | |
| */
 | |
| 
 | |
| /*
 | |
|  ******************************************************************************
 | |
|  * LOCAL VARIABLES
 | |
|  ******************************************************************************
 | |
|  */
 | |
| 
 | |
| /*
 | |
|  ******************************************************************************
 | |
|  * GLOBAL FUNCTIONS
 | |
|  ******************************************************************************
 | |
|  */
 | |
| 
 | |
| /*******************************************************************************/
 | |
| ReturnCode rfalT4TPollerComposeCAPDU(const rfalT4tCApduParam* apduParam) {
 | |
|     uint8_t hdrLen;
 | |
|     uint16_t msgIt;
 | |
| 
 | |
|     if((apduParam == NULL) || (apduParam->cApduBuf == NULL) || (apduParam->cApduLen == NULL)) {
 | |
|         return ERR_PARAM;
 | |
|     }
 | |
| 
 | |
|     msgIt = 0;
 | |
|     *(apduParam->cApduLen) = 0;
 | |
| 
 | |
|     /*******************************************************************************/
 | |
|     /* Compute Command-APDU  according to the format   T4T 1.0 5.1.2 & ISO7816-4 2013 Table 1 */
 | |
| 
 | |
|     /* Check if Data is present */
 | |
|     if(apduParam->LcFlag) {
 | |
|         if(apduParam->Lc == 0U) {
 | |
|             /* Extented field coding not supported */
 | |
|             return ERR_PARAM;
 | |
|         }
 | |
| 
 | |
|         /* Check whether requested Lc fits */
 | |
|         if((uint16_t)apduParam->Lc >
 | |
|            (uint16_t)(RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN - RFAL_T4T_LE_LEN)) {
 | |
|             return ERR_PARAM; /*  PRQA S  2880 # MISRA 2.1 - Unreachable code due to configuration option being set/unset  */
 | |
|         }
 | |
| 
 | |
|         /* Calculate the header length a place the data/body where it should be */
 | |
|         hdrLen = RFAL_T4T_MAX_CAPDU_PROLOGUE_LEN + RFAL_T4T_LC_LEN;
 | |
| 
 | |
|         /* make sure not to exceed buffer size */
 | |
|         if(((uint16_t)hdrLen + (uint16_t)apduParam->Lc +
 | |
|             (apduParam->LeFlag ? RFAL_T4T_LC_LEN : 0U)) > RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN) {
 | |
|             return ERR_NOMEM; /*  PRQA S  2880 # MISRA 2.1 - Unreachable code due to configuration option being set/unset */
 | |
|         }
 | |
|         ST_MEMMOVE(&apduParam->cApduBuf->apdu[hdrLen], apduParam->cApduBuf->apdu, apduParam->Lc);
 | |
|     }
 | |
| 
 | |
|     /* Prepend the ADPDU's header */
 | |
|     apduParam->cApduBuf->apdu[msgIt++] = apduParam->CLA;
 | |
|     apduParam->cApduBuf->apdu[msgIt++] = apduParam->INS;
 | |
|     apduParam->cApduBuf->apdu[msgIt++] = apduParam->P1;
 | |
|     apduParam->cApduBuf->apdu[msgIt++] = apduParam->P2;
 | |
| 
 | |
|     /* Check if Data field length is to be added */
 | |
|     if(apduParam->LcFlag) {
 | |
|         apduParam->cApduBuf->apdu[msgIt++] = apduParam->Lc;
 | |
|         msgIt += apduParam->Lc;
 | |
|     }
 | |
| 
 | |
|     /* Check if Expected Response Length is to be added */
 | |
|     if(apduParam->LeFlag) {
 | |
|         apduParam->cApduBuf->apdu[msgIt++] = apduParam->Le;
 | |
|     }
 | |
| 
 | |
|     *(apduParam->cApduLen) = msgIt;
 | |
| 
 | |
|     return ERR_NONE;
 | |
| }
 | |
| 
 | |
| /*******************************************************************************/
 | |
| ReturnCode rfalT4TPollerParseRAPDU(rfalT4tRApduParam* apduParam) {
 | |
|     if((apduParam == NULL) || (apduParam->rApduBuf == NULL)) {
 | |
|         return ERR_PARAM;
 | |
|     }
 | |
| 
 | |
|     if(apduParam->rcvdLen < RFAL_T4T_MAX_RAPDU_SW1SW2_LEN) {
 | |
|         return ERR_PROTO;
 | |
|     }
 | |
| 
 | |
|     apduParam->rApduBodyLen = (apduParam->rcvdLen - (uint16_t)RFAL_T4T_MAX_RAPDU_SW1SW2_LEN);
 | |
|     apduParam->statusWord = GETU16((&apduParam->rApduBuf->apdu[apduParam->rApduBodyLen]));
 | |
| 
 | |
|     /* Check SW1 SW2    T4T 1.0 5.1.3 NOTE */
 | |
|     if(apduParam->statusWord == RFAL_T4T_ISO7816_STATUS_COMPLETE) {
 | |
|         return ERR_NONE;
 | |
|     }
 | |
| 
 | |
|     return ERR_REQUEST;
 | |
| }
 | |
| 
 | |
| /*******************************************************************************/
 | |
| ReturnCode rfalT4TPollerComposeSelectAppl(
 | |
|     rfalIsoDepApduBufFormat* cApduBuf,
 | |
|     const uint8_t* aid,
 | |
|     uint8_t aidLen,
 | |
|     uint16_t* cApduLen) {
 | |
|     rfalT4tCApduParam cAPDU;
 | |
| 
 | |
|     /* CLA INS P1  P2   Lc  Data   Le  */
 | |
|     /* 00h A4h 00h 00h  07h AID    00h */
 | |
|     cAPDU.CLA = RFAL_T4T_CLA;
 | |
|     cAPDU.INS = (uint8_t)RFAL_T4T_INS_SELECT;
 | |
|     cAPDU.P1 = RFAL_T4T_ISO7816_P1_SELECT_BY_DF_NAME;
 | |
|     cAPDU.P2 = RFAL_T4T_ISO7816_P2_SELECT_FIRST_OR_ONLY_OCCURENCE |
 | |
|                RFAL_T4T_ISO7816_P2_SELECT_RETURN_FCI_TEMPLATE;
 | |
|     cAPDU.Lc = aidLen;
 | |
|     cAPDU.Le = 0x00;
 | |
|     cAPDU.LcFlag = true;
 | |
|     cAPDU.LeFlag = true;
 | |
|     cAPDU.cApduBuf = cApduBuf;
 | |
|     cAPDU.cApduLen = cApduLen;
 | |
| 
 | |
|     if(aidLen > 0U) {
 | |
|         ST_MEMCPY(cAPDU.cApduBuf->apdu, aid, aidLen);
 | |
|     }
 | |
| 
 | |
|     return rfalT4TPollerComposeCAPDU(&cAPDU);
 | |
| }
 | |
| 
 | |
| /*******************************************************************************/
 | |
| ReturnCode rfalT4TPollerComposeSelectFile(
 | |
|     rfalIsoDepApduBufFormat* cApduBuf,
 | |
|     const uint8_t* fid,
 | |
|     uint8_t fidLen,
 | |
|     uint16_t* cApduLen) {
 | |
|     rfalT4tCApduParam cAPDU;
 | |
| 
 | |
|     /* CLA INS P1  P2   Lc  Data   Le  */
 | |
|     /* 00h A4h 00h 0Ch  02h FID    -   */
 | |
|     cAPDU.CLA = RFAL_T4T_CLA;
 | |
|     cAPDU.INS = (uint8_t)RFAL_T4T_INS_SELECT;
 | |
|     cAPDU.P1 = RFAL_T4T_ISO7816_P1_SELECT_BY_FILEID;
 | |
|     cAPDU.P2 = RFAL_T4T_ISO7816_P2_SELECT_FIRST_OR_ONLY_OCCURENCE |
 | |
|                RFAL_T4T_ISO7816_P2_SELECT_NO_RESPONSE_DATA;
 | |
|     cAPDU.Lc = fidLen;
 | |
|     cAPDU.Le = 0x00;
 | |
|     cAPDU.LcFlag = true;
 | |
|     cAPDU.LeFlag = false;
 | |
|     cAPDU.cApduBuf = cApduBuf;
 | |
|     cAPDU.cApduLen = cApduLen;
 | |
| 
 | |
|     if(fidLen > 0U) {
 | |
|         ST_MEMCPY(cAPDU.cApduBuf->apdu, fid, fidLen);
 | |
|     }
 | |
| 
 | |
|     return rfalT4TPollerComposeCAPDU(&cAPDU);
 | |
| }
 | |
| 
 | |
| /*******************************************************************************/
 | |
| ReturnCode rfalT4TPollerComposeSelectFileV1Mapping(
 | |
|     rfalIsoDepApduBufFormat* cApduBuf,
 | |
|     const uint8_t* fid,
 | |
|     uint8_t fidLen,
 | |
|     uint16_t* cApduLen) {
 | |
|     rfalT4tCApduParam cAPDU;
 | |
| 
 | |
|     /* CLA INS P1  P2   Lc  Data   Le  */
 | |
|     /* 00h A4h 00h 00h  02h FID    -   */
 | |
|     cAPDU.CLA = RFAL_T4T_CLA;
 | |
|     cAPDU.INS = (uint8_t)RFAL_T4T_INS_SELECT;
 | |
|     cAPDU.P1 = RFAL_T4T_ISO7816_P1_SELECT_BY_FILEID;
 | |
|     cAPDU.P2 = RFAL_T4T_ISO7816_P2_SELECT_FIRST_OR_ONLY_OCCURENCE |
 | |
|                RFAL_T4T_ISO7816_P2_SELECT_RETURN_FCI_TEMPLATE;
 | |
|     cAPDU.Lc = fidLen;
 | |
|     cAPDU.Le = 0x00;
 | |
|     cAPDU.LcFlag = true;
 | |
|     cAPDU.LeFlag = false;
 | |
|     cAPDU.cApduBuf = cApduBuf;
 | |
|     cAPDU.cApduLen = cApduLen;
 | |
| 
 | |
|     if(fidLen > 0U) {
 | |
|         ST_MEMCPY(cAPDU.cApduBuf->apdu, fid, fidLen);
 | |
|     }
 | |
| 
 | |
|     return rfalT4TPollerComposeCAPDU(&cAPDU);
 | |
| }
 | |
| 
 | |
| /*******************************************************************************/
 | |
| ReturnCode rfalT4TPollerComposeReadData(
 | |
|     rfalIsoDepApduBufFormat* cApduBuf,
 | |
|     uint16_t offset,
 | |
|     uint8_t expLen,
 | |
|     uint16_t* cApduLen) {
 | |
|     rfalT4tCApduParam cAPDU;
 | |
| 
 | |
|     /* CLA INS P1  P2   Lc  Data   Le  */
 | |
|     /* 00h B0h [Offset] -   -      len */
 | |
|     cAPDU.CLA = RFAL_T4T_CLA;
 | |
|     cAPDU.INS = (uint8_t)RFAL_T4T_INS_READBINARY;
 | |
|     cAPDU.P1 = (uint8_t)((offset >> 8U) & 0xFFU);
 | |
|     cAPDU.P2 = (uint8_t)((offset >> 0U) & 0xFFU);
 | |
|     cAPDU.Le = expLen;
 | |
|     cAPDU.LcFlag = false;
 | |
|     cAPDU.LeFlag = true;
 | |
|     cAPDU.cApduBuf = cApduBuf;
 | |
|     cAPDU.cApduLen = cApduLen;
 | |
| 
 | |
|     return rfalT4TPollerComposeCAPDU(&cAPDU);
 | |
| }
 | |
| 
 | |
| /*******************************************************************************/
 | |
| ReturnCode rfalT4TPollerComposeReadDataODO(
 | |
|     rfalIsoDepApduBufFormat* cApduBuf,
 | |
|     uint32_t offset,
 | |
|     uint8_t expLen,
 | |
|     uint16_t* cApduLen) {
 | |
|     rfalT4tCApduParam cAPDU;
 | |
|     uint8_t dataIt;
 | |
| 
 | |
|     /* CLA INS P1  P2  Lc  Data         Le */
 | |
|     /* 00h B1h 00h 00h Lc  54 03 xxyyzz len */
 | |
|     /*                          [Offset]    */
 | |
|     cAPDU.CLA = RFAL_T4T_CLA;
 | |
|     cAPDU.INS = (uint8_t)RFAL_T4T_INS_READBINARY_ODO;
 | |
|     cAPDU.P1 = 0x00U;
 | |
|     cAPDU.P2 = 0x00U;
 | |
|     cAPDU.Le = expLen;
 | |
|     cAPDU.LcFlag = true;
 | |
|     cAPDU.LeFlag = true;
 | |
|     cAPDU.cApduBuf = cApduBuf;
 | |
|     cAPDU.cApduLen = cApduLen;
 | |
| 
 | |
|     dataIt = 0U;
 | |
|     cApduBuf->apdu[dataIt++] = RFAL_T4T_OFFSET_DO;
 | |
|     cApduBuf->apdu[dataIt++] = RFAL_T4T_LENGTH_DO;
 | |
|     cApduBuf->apdu[dataIt++] = (uint8_t)(offset >> 16U);
 | |
|     cApduBuf->apdu[dataIt++] = (uint8_t)(offset >> 8U);
 | |
|     cApduBuf->apdu[dataIt++] = (uint8_t)(offset);
 | |
|     cAPDU.Lc = dataIt;
 | |
| 
 | |
|     return rfalT4TPollerComposeCAPDU(&cAPDU);
 | |
| }
 | |
| 
 | |
| /*******************************************************************************/
 | |
| ReturnCode rfalT4TPollerComposeWriteData(
 | |
|     rfalIsoDepApduBufFormat* cApduBuf,
 | |
|     uint16_t offset,
 | |
|     const uint8_t* data,
 | |
|     uint8_t dataLen,
 | |
|     uint16_t* cApduLen) {
 | |
|     rfalT4tCApduParam cAPDU;
 | |
| 
 | |
|     /* CLA INS P1  P2   Lc  Data   Le  */
 | |
|     /* 00h D6h [Offset] len Data   -   */
 | |
|     cAPDU.CLA = RFAL_T4T_CLA;
 | |
|     cAPDU.INS = (uint8_t)RFAL_T4T_INS_UPDATEBINARY;
 | |
|     cAPDU.P1 = (uint8_t)((offset >> 8U) & 0xFFU);
 | |
|     cAPDU.P2 = (uint8_t)((offset >> 0U) & 0xFFU);
 | |
|     cAPDU.Lc = dataLen;
 | |
|     cAPDU.LcFlag = true;
 | |
|     cAPDU.LeFlag = false;
 | |
|     cAPDU.cApduBuf = cApduBuf;
 | |
|     cAPDU.cApduLen = cApduLen;
 | |
| 
 | |
|     if(dataLen > 0U) {
 | |
|         ST_MEMCPY(cAPDU.cApduBuf->apdu, data, dataLen);
 | |
|     }
 | |
| 
 | |
|     return rfalT4TPollerComposeCAPDU(&cAPDU);
 | |
| }
 | |
| 
 | |
| /*******************************************************************************/
 | |
| ReturnCode rfalT4TPollerComposeWriteDataODO(
 | |
|     rfalIsoDepApduBufFormat* cApduBuf,
 | |
|     uint32_t offset,
 | |
|     const uint8_t* data,
 | |
|     uint8_t dataLen,
 | |
|     uint16_t* cApduLen) {
 | |
|     rfalT4tCApduParam cAPDU;
 | |
|     uint8_t dataIt;
 | |
| 
 | |
|     /* CLA INS P1  P2   Lc  Data                     Le  */
 | |
|     /* 00h D7h 00h 00h  len 54 03 xxyyzz 53 Ld data  -   */
 | |
|     /*                           [offset]     [data]     */
 | |
|     cAPDU.CLA = RFAL_T4T_CLA;
 | |
|     cAPDU.INS = (uint8_t)RFAL_T4T_INS_UPDATEBINARY_ODO;
 | |
|     cAPDU.P1 = 0x00U;
 | |
|     cAPDU.P2 = 0x00U;
 | |
|     cAPDU.LcFlag = true;
 | |
|     cAPDU.LeFlag = false;
 | |
|     cAPDU.cApduBuf = cApduBuf;
 | |
|     cAPDU.cApduLen = cApduLen;
 | |
| 
 | |
|     dataIt = 0U;
 | |
|     cApduBuf->apdu[dataIt++] = RFAL_T4T_OFFSET_DO;
 | |
|     cApduBuf->apdu[dataIt++] = RFAL_T4T_LENGTH_DO;
 | |
|     cApduBuf->apdu[dataIt++] = (uint8_t)(offset >> 16U);
 | |
|     cApduBuf->apdu[dataIt++] = (uint8_t)(offset >> 8U);
 | |
|     cApduBuf->apdu[dataIt++] = (uint8_t)(offset);
 | |
|     cApduBuf->apdu[dataIt++] = RFAL_T4T_DATA_DO;
 | |
|     cApduBuf->apdu[dataIt++] = dataLen;
 | |
| 
 | |
|     if((((uint32_t)dataLen + (uint32_t)dataIt) >= RFAL_T4T_MAX_LC) ||
 | |
|        (((uint32_t)dataLen + (uint32_t)dataIt) >= RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN)) {
 | |
|         return (ERR_NOMEM);
 | |
|     }
 | |
| 
 | |
|     if(dataLen > 0U) {
 | |
|         ST_MEMCPY(&cAPDU.cApduBuf->apdu[dataIt], data, dataLen);
 | |
|     }
 | |
|     dataIt += dataLen;
 | |
|     cAPDU.Lc = dataIt;
 | |
| 
 | |
|     return rfalT4TPollerComposeCAPDU(&cAPDU);
 | |
| }
 | |
| 
 | |
| #endif /* RFAL_FEATURE_T4T */
 |