yincheng.zhong
2024-08-20 7744fffacb03dc81cc9dbaf9f5d86a0f21e79c03
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#ifndef _7816_3_T1_T1_H_
#define _7816_3_T1_T1_H_
 
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
 
#include "se_common.h"
 
#define CRC_PRESET 0xFFFF
#define CRC_POLYNOMIAL 0x8408
 
#define T1_DEFAULT_IFS 0xFE
 
// Node address device to card
#define NAD_D2C 0x5A
// Node address card to device
#define NAD_C2DT 0xA5
 
// T1 prologue field length and offset [start]
#define T1_HEADER_LEN 0x03
// ext frame's length is 2 bytes, refer to "GPC APDU Transport over SPI / I2C Version 1.0"
// The LEN and CRC fields shall have their Most Significant Byte sent first (i.e. big-endian order).
#define T1_EXT_HEADER_LEN 0x04
// T1 protocol frame LRC length is 1 byte
#define T1_LRC_LEN 0x01
// T1 protocol frame CRC length is 2 bytes
#define T1_CRC_LEN 0x02
 
#define T1_NAD_OFFSET 0x00
#define T1_PCB_OFFSET 0x01
#define T1_FRAME_LEN_OFFSET 0x02
#define T1_FRAME_LEN_OFFSET2 0x03
// T1 prologue field length and offset [end]
 
// T1 flags bit for masking [start]
#define T1_CHAINING_MASK 0x20
#define T1_S_BLOCK_REQ_MASK 0xC0
#define T1_S_BLOCK_RSP_MASK 0xE0
#define T1_I_BLOCK_SEQ_NO_MASK 0x40
#define T1_R_BLOCK_SEQ_NO_MASK 0x10
 
#define T1_S_BLOCK_SUB_TYPE_MASK 0x3F
 
// reference to ATR definition field: capbilities
#define T1_EXT_HEADER_LEN_MASK 0x04
 
typedef enum
{
    LRC = 0x00,
    CRC = 0x01,
    CHK_INVALID,
} chk_code_types;
 
/* atr info: ISO7816 ATR Information bytes
 * This structure holds ATR information bytes, contains ATR length.
 */
typedef struct
{
    uint8_t len;          // ATR length in bytes
    uint8_t vendor_ID[5]; // Vendor_ID according to ISO7816-5
    uint8_t dll_IC;       // Data Link Layer - Interface Character
    uint8_t bgt[2];       // Minimum guard time in milliseconds for
                          // T=1 blocks sent in opposite directions.
 
    uint8_t bwt[2]; // Maximum allowed command processing
                    // time in milliseconds before card has sent either
                    // command response or S(WTX) requesting processing time extension
 
    uint8_t max_freq[2];  // Max supported  clock frequency in kHz
    uint8_t checksum;     // Checksum (0 = LRC / 1 = CRC)
    uint8_t default_IFSC; // Default IFS size--Recommended value is 0x0102(258), APDU(256) + sw1sw2(2)
 
    uint8_t num_channels;   // Number of logical connections supported
    uint8_t max_IFSC[2];    // Maximum size of IFS supported
    uint8_t capbilities[2]; // Bitmap to indicate various features supported by SE
                            // Bit-1: SE Data Available Line supported.
                            // Bit-2: SE Data available polarity. 1 - Data available GPIO will be pulled HIGH when SE response is ready
                            // Bit 3: SE chip reset S-blk command supported
                            // Bit-4: Extended frame length feature supported
                            // Bit-5: Support for more than one logical channel
                            // Bit 6 to 16: Reserved for future use
} atr_info;
 
typedef struct
{
    uint8_t lsb : 1;  // PCB: lsb
    uint8_t bit2 : 1; // PCB: bit2
    uint8_t bit3 : 1; // PCB: bit3
    uint8_t bit4 : 1; // PCB: bit4
    uint8_t bit5 : 1; // PCB: bit5
    uint8_t bit6 : 1; // PCB: bit6
    uint8_t bit7 : 1; // PCB: bit7
    uint8_t msb : 1;  // PCB: msb
} T1_pcb_bits;
 
/** T1 Frame types **/
typedef enum
{
    FRAME_TYPE_INVALID_MIN, // Frame type: INVALID
    IFRAME,                 // Frame type: I-frame
    RFRAME,                 // Frame type: R-frame
    SFRAME,                 // Frame type: S-frame
    FRAME_TYPE_INVALID_MAX, // Frame type: INVALID
} T1_frame_types;
 
/** T1 S-Frame sub-types **/
typedef enum
{
    RESYNC_REQ = 0x00,        // Re-synchronisation request between host and ESE
    RESYNC_RSP = 0x20,        // Re-synchronisation response between host and ESE
    IFS_REQ = 0x01,           // IFSC size request
    IFS_RSP = 0x21,           // IFSC size response
    ABORT_REQ = 0x02,         // Abort request
    ABORT_RSP = 0x22,         // Abort response
    WTX_REQ = 0x03,           // WTX request
    WTX_RSP = 0x23,           // WTX response
    CIP_REQ = 0x04,           // Interface reset request(Communication Interface Parameters request)
    CIP_RSP = 0x24,           // Interface reset response(Communication Interface Parameters response)
    PROP_END_APDU_REQ = 0x05, // Proprietary Enf of APDU request
    PROP_END_APDU_RSP = 0x25, // Proprietary Enf of APDU response
    HARD_RESET_REQ = 0x06,    // Chip reset request
    HARD_RESET_RSP = 0x26,    // Chip reset request
    ATR_REQ = 0x07,           // ATR request
    ATR_RSP = 0x27,           // ATR response
    SFRAME_TYPE_INVALID,      // Invalid request
} Sframe_types;
 
/** T1 R-Frame sub-types **/
typedef enum
{
    RACK = 0x00,                // R-frame Acknowledgement frame indicator, an error-free acknowledgement
    RNACK_PARITY_ERROR = 0x01,  // R-frame Negative-Acknowledgement frame indicator,
                                //        a redundancy code error or a character parity error.
    RNACK_OTHER_ERROR = 0x02,   // R-frame Negative-Acknowledgement frame indicator, other errors.
    RNACK_INVALID_ERROR = 0xFF, // Invalid R-block request
} Rframe_types;
 
typedef enum
{
    STATE_IDEL = 0,
    I_BLK,
    R_ACK,
    R_PARITY_ERR,
    R_OTHER_ERR,
    S_RESYNC_REQ,
    S_IFS_REQ,
    S_IFS_RSP,
    S_ABORT_REQ,
    S_ABORT_RSP,
    S_WTX_REQ,
    S_WTX_RSP,
    S_CIP_REQ,
    S_PROP_END_APDU_REQ,
    S_ATR_REQ,
} T1_transmit_receive_state;
 
/** T1 protocol param **/
typedef struct
{
    bool is_device_chaining;
    bool is_card_chaining;
 
    uint8_t recovery_cnt;
 
    uint8_t resync_CIP_req_cnt;
 
    uint8_t blk_retry_cnt;
 
    uint8_t wtx_cnt;
 
    uint8_t wtx_info;
 
    T1_frame_types tx_frame_type;
    Sframe_types tx_sub_Sframe_type;
    Rframe_types tx_sub_Rframe_type;
 
    // for recovery
    T1_frame_types last_rx_frame_type;
    Sframe_types last_rx_sub_Sframe_type;
    Rframe_types last_rx_sub_Rframe_type;
    T1_pcb_bits last_rx_pcb_bits;
 
    // only I-block used
    uint8_t *p_data_tx;
    uint16_t tx_len;
    uint8_t *p_data_tx_part;
    uint16_t tx_len_part;
    uint16_t tx_data_offset;
    // end only I-block used
} T1_params;
 
ESESTATUS t1_transmit_receive_apdu(uint8_t *p_cmd_apdu, uint16_t cmd_len);
ESESTATUS t1_CIP_req(void);
ESESTATUS t1_ATR_req(void);
ESESTATUS t1_IFSD_req(void);
ESESTATUS t1_prop_end_apdu_req(void);
ESESTATUS t1_receive_data_and_get(uint8_t **pp_Data, uint16_t *data_len);
 
extern uint32_t g_recv_total_len;
extern uint8_t gp_data_rx[270];
extern atr_info g_atr;
 
ESESTATUS response_process(void);
ESESTATUS Transmit_receive_process(void);
ESESTATUS t1_send_Sframe(void);
ESESTATUS t1_send_Iframe(void);
ESESTATUS t1_send_Rframe(void);
ESESTATUS t1_chk_epilogue(uint8_t *p_data, uint16_t offset, uint16_t len);
ESESTATUS t1_decode_frame(uint16_t data_len);
uint8_t get_header_len(bool contains_epilogue);
ESESTATUS init_Iframe_from_cmd_apdu(uint8_t *p_cmd_apdu, uint16_t cmd_len);
void deinit_Iframe_from_cmd_apdu(void);
ESESTATUS do_T1_recovery_at_undecode(void);
ESESTATUS t1_transmit_only_apdu(uint8_t *p_cmd_apdu, uint16_t cmd_len);
ESESTATUS t1_receive_only_apdu(void);
 
#endif /* _T1PROTOCOL_H_ */