zongqiang.zhang | 0c6a088 | 2019-08-07 14:48:21 +0800 | [diff] [blame] | 1 | #include "../nec_apdu.h" |
| 2 | #include "sp_des.h" |
| 3 | #include "sp_constant.h" |
| 4 | #include "sp_util.h" |
| 5 | #include "sp_card.h" |
| 6 | |
| 7 | static uint8* prcv_buff = NULL; |
| 8 | static uint8 rcv_len = 0; |
| 9 | |
| 10 | uint16 sp_select_sfi(uint8 sfi[2]) |
| 11 | { |
| 12 | uint16 ret; |
| 13 | uint8 cmd_buff[10]; |
| 14 | |
| 15 | cmd_buff[0] = 0x00; //CLA |
| 16 | cmd_buff[1] = 0xA4; //INS |
| 17 | cmd_buff[2] = 0x00; //P1 |
| 18 | cmd_buff[3] = 0x00; //P2 |
| 19 | cmd_buff[4] = 0x02; //Lc |
| 20 | memcpy(cmd_buff + 5, sfi, 2); |
| 21 | |
| 22 | ret = card_cpu_exchange(cmd_buff, 2 + 5, 0, &prcv_buff, &rcv_len); |
| 23 | if(ret != RETCODE_OK) |
| 24 | { |
| 25 | return ret; |
| 26 | } |
| 27 | return 0; |
| 28 | } |
| 29 | |
| 30 | uint16 sp_select_adf(void) |
| 31 | { |
| 32 | uint16 ret; |
| 33 | uint8 cmd_buff[] = {"\x00\xA4\x04\x00\x0F\xD1\x56\x00\x00\x01\xBD\xF0\xCA\xCB\xB4\xEF\xD6\xA7\xB8\xB6"}; |
| 34 | ret = card_cpu_exchange(cmd_buff, sizeof(cmd_buff) - 1, 0, &prcv_buff, &rcv_len); |
| 35 | if(ret != RETCODE_OK) |
| 36 | { |
| 37 | return ret; |
| 38 | } |
| 39 | return 0; |
| 40 | } |
| 41 | |
| 42 | uint8 sp_card_request(sp_card_t* cardpcd) |
| 43 | { |
| 44 | |
| 45 | uint8 sak; |
| 46 | uint8 snr[8]; |
| 47 | |
| 48 | if(!card_request(&sak, snr)) |
| 49 | { |
| 50 | if((sak & 0x20)) |
| 51 | { |
| 52 | if(!card_cpu_mode()) |
| 53 | { |
| 54 | Delay_ms(200); |
guangcheng.qin | 0b456a3 | 2019-08-08 16:53:12 +0800 | [diff] [blame] | 55 | if(sp_select_sfi("\x3f\x00") == 0) |
zongqiang.zhang | 0c6a088 | 2019-08-07 14:48:21 +0800 | [diff] [blame] | 56 | { |
| 57 | sp_select_adf(); |
guangcheng.qin | 323c1b1 | 2019-09-23 10:06:08 +0800 | [diff] [blame] | 58 | cardpcd->cardphyid[0] = snr[0]; |
| 59 | cardpcd->cardphyid[1] = snr[1]; |
| 60 | cardpcd->cardphyid[2] = snr[2]; |
| 61 | cardpcd->cardphyid[3] = snr[3]; |
zongqiang.zhang | 0c6a088 | 2019-08-07 14:48:21 +0800 | [diff] [blame] | 62 | cardpcd->cardtype = TAG_TYPE_CPU; |
| 63 | return 0; |
| 64 | } |
| 65 | } |
| 66 | } |
| 67 | else |
| 68 | { |
| 69 | cardpcd->cardtype = TAG_TYPE_UNKONWN; |
guangcheng.qin | 0b456a3 | 2019-08-08 16:53:12 +0800 | [diff] [blame] | 70 | return 1; |
zongqiang.zhang | 0c6a088 | 2019-08-07 14:48:21 +0800 | [diff] [blame] | 71 | } |
| 72 | } |
| 73 | return 1; |
| 74 | } |
| 75 | |
| 76 | int8 sp_check_cpu_exist(void) |
| 77 | { |
| 78 | return card_cpu_exist(); |
| 79 | } |
| 80 | |
guangcheng.qin | 0b456a3 | 2019-08-08 16:53:12 +0800 | [diff] [blame] | 81 | static uint16 sp_select_adf15() |
| 82 | { |
| 83 | uint16 ret = 0; |
| 84 | uint8* temp_buff = NULL; |
| 85 | uint8 buff_len = 0; |
| 86 | uint8 cmd_buff[] = {"\x00\xA4\x00\x00\x02\x3F\x00"}; |
| 87 | ret = card_cpu_exchange(cmd_buff, sizeof(cmd_buff)-1, 0, &temp_buff, &buff_len); |
| 88 | if(ret != RETCODE_OK) |
| 89 | { |
| 90 | return ret; |
| 91 | } |
| 92 | return 0; |
| 93 | } |
| 94 | |
| 95 | static uint16 sp_read_binary_file(uint8 out[]) |
| 96 | { |
| 97 | uint16 ret = 0; |
| 98 | uint8* temp_buff = NULL; |
| 99 | uint8 buff_len = 0; |
| 100 | uint8 cmd_buff[5] = {"\x00\xB0\x95\x00\x47"}; |
| 101 | ret = card_cpu_exchange(cmd_buff, sizeof(cmd_buff), 0, &temp_buff, &buff_len); |
| 102 | if(ret != RETCODE_OK) |
| 103 | { |
| 104 | return ret; |
| 105 | } |
| 106 | MEMCPY(out, temp_buff, buff_len); |
| 107 | return 0; |
| 108 | } |
zongqiang.zhang | 0c6a088 | 2019-08-07 14:48:21 +0800 | [diff] [blame] | 109 | static uint16 sp_cpu_read(sp_card_t* card) |
| 110 | { |
| 111 | uint16 ret = 0; |
guangcheng.qin | 0b456a3 | 2019-08-08 16:53:12 +0800 | [diff] [blame] | 112 | uint8 buff[72]; |
| 113 | uint8 offset = 0; |
| 114 | MEMCLEAR(buff, sizeof(buff)); |
| 115 | ret = sp_select_adf15(); |
| 116 | if(ret) |
| 117 | { |
| 118 | return ret; |
| 119 | |
| 120 | } |
| 121 | ret = sp_read_binary_file(buff); |
| 122 | if(ret) |
| 123 | { |
| 124 | return ret; |
| 125 | } |
zongqiang.zhang | 0c6a088 | 2019-08-07 14:48:21 +0800 | [diff] [blame] | 126 | MEMCLEAR(card->citizen_cardno, sizeof(card->citizen_cardno)); |
guangcheng.qin | 0b456a3 | 2019-08-08 16:53:12 +0800 | [diff] [blame] | 127 | offset += 31; |
| 128 | MEMCPY(card->citizen_cardno, buff+offset, sizeof(card->citizen_cardno)); |
| 129 | offset += 12; |
| 130 | offset += 18; |
| 131 | MEMCPY(card->expiredate, buff+offset, 4); |
zongqiang.zhang | 0c6a088 | 2019-08-07 14:48:21 +0800 | [diff] [blame] | 132 | return ret; |
| 133 | } |
| 134 | |
| 135 | uint16 sp_card_read(sp_card_t* card) |
| 136 | { |
| 137 | switch(card->cardtype) |
| 138 | { |
| 139 | case TAG_TYPE_CPU: |
| 140 | return sp_cpu_read(card); |
| 141 | default: |
| 142 | return 1; |
| 143 | } |
| 144 | } |