1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
22 // Flags to tell where to add CRC on sent replies
23 bool g_reply_with_crc_on_usb
= false;
24 bool g_reply_with_crc_on_fpc
= true;
25 // "Session" flag, to tell via which interface next msgs should be sent: USB or FPC USART
26 bool g_reply_via_fpc
= false;
27 bool g_reply_via_usb
= false;
29 int reply_old(uint64_t cmd
, uint64_t arg0
, uint64_t arg1
, uint64_t arg2
, void *data
, size_t len
) {
30 PacketResponseOLD txcmd
= {CMD_UNKNOWN
, {0, 0, 0}, {{0}}};
32 // for (size_t i = 0; i < sizeof(PacketResponseOLD); i++)
33 // ((uint8_t *)&txcmd)[i] = 0x00;
35 // Compose the outgoing command frame
41 // Add the (optional) content to the frame, with a maximum size of PM3_CMD_DATA_SIZE
43 len
= MIN(len
, PM3_CMD_DATA_SIZE
);
44 for (size_t i
= 0; i
< len
; i
++) {
45 txcmd
.d
.asBytes
[i
] = ((uint8_t *)data
)[i
];
49 #ifdef WITH_FPC_USART_HOST
50 int resultfpc
= PM3_EUNDEF
;
52 int resultusb
= PM3_EUNDEF
;
53 // Send frame and make sure all bytes are transmitted
55 if (g_reply_via_usb
) {
56 resultusb
= usb_write((uint8_t *)&txcmd
, sizeof(PacketResponseOLD
));
59 if (g_reply_via_fpc
) {
60 #ifdef WITH_FPC_USART_HOST
61 resultfpc
= usart_writebuffer_sync((uint8_t *)&txcmd
, sizeof(PacketResponseOLD
));
63 return PM3_EDEVNOTSUPP
;
66 // we got two results, let's prioritize the faulty one and USB over FPC.
67 if (g_reply_via_usb
&& (resultusb
!= PM3_SUCCESS
)) return resultusb
;
68 #ifdef WITH_FPC_USART_HOST
69 if (g_reply_via_fpc
&& (resultfpc
!= PM3_SUCCESS
)) return resultfpc
;
74 static int reply_ng_internal(uint16_t cmd
, int16_t status
, const uint8_t *data
, size_t len
, bool ng
) {
75 PacketResponseNGRaw txBufferNG
;
78 // Compose the outgoing command frame
79 txBufferNG
.pre
.magic
= RESPONSENG_PREAMBLE_MAGIC
;
80 txBufferNG
.pre
.cmd
= cmd
;
81 txBufferNG
.pre
.status
= status
;
82 txBufferNG
.pre
.ng
= ng
;
83 if (len
> PM3_CMD_DATA_SIZE
) {
84 len
= PM3_CMD_DATA_SIZE
;
86 txBufferNG
.pre
.status
= PM3_EOVFLOW
;
89 // length is only 15bit (32768)
90 txBufferNG
.pre
.length
= (len
& 0x7FFF);
92 // Add the (optional) content to the frame, with a maximum size of PM3_CMD_DATA_SIZE
94 for (size_t i
= 0; i
< len
; i
++) {
95 txBufferNG
.data
[i
] = data
[i
];
99 PacketResponseNGPostamble
*tx_post
= (PacketResponseNGPostamble
*)((uint8_t *)&txBufferNG
+ sizeof(PacketResponseNGPreamble
) + len
);
100 // Note: if we send to both FPC & USB, we'll set CRC for both if any of them require CRC
101 if ((g_reply_via_fpc
&& g_reply_with_crc_on_fpc
) || ((g_reply_via_usb
) && g_reply_with_crc_on_usb
)) {
102 uint8_t first
, second
;
103 compute_crc(CRC_14443_A
, (uint8_t *)&txBufferNG
, sizeof(PacketResponseNGPreamble
) + len
, &first
, &second
);
104 tx_post
->crc
= ((first
<< 8) | second
);
106 tx_post
->crc
= RESPONSENG_POSTAMBLE_MAGIC
;
108 txBufferNGLen
= sizeof(PacketResponseNGPreamble
) + len
+ sizeof(PacketResponseNGPostamble
);
110 #ifdef WITH_FPC_USART_HOST
111 int resultfpc
= PM3_EUNDEF
;
113 int resultusb
= PM3_EUNDEF
;
114 // Send frame and make sure all bytes are transmitted
116 if (g_reply_via_usb
) {
117 resultusb
= usb_write((uint8_t *)&txBufferNG
, txBufferNGLen
);
119 if (g_reply_via_fpc
) {
120 #ifdef WITH_FPC_USART_HOST
121 resultfpc
= usart_writebuffer_sync((uint8_t *)&txBufferNG
, txBufferNGLen
);
123 return PM3_EDEVNOTSUPP
;
126 // we got two results, let's prioritize the faulty one and USB over FPC.
127 if (g_reply_via_usb
&& (resultusb
!= PM3_SUCCESS
)) return resultusb
;
128 #ifdef WITH_FPC_USART_HOST
129 if (g_reply_via_fpc
&& (resultfpc
!= PM3_SUCCESS
)) return resultfpc
;
134 int reply_ng(uint16_t cmd
, int16_t status
, uint8_t *data
, size_t len
) {
135 return reply_ng_internal(cmd
, status
, data
, len
, true);
138 int reply_mix(uint64_t cmd
, uint64_t arg0
, uint64_t arg1
, uint64_t arg2
, void *data
, size_t len
) {
139 int16_t status
= PM3_SUCCESS
;
140 uint64_t arg
[3] = {arg0
, arg1
, arg2
};
141 if (len
> PM3_CMD_DATA_SIZE
- sizeof(arg
)) {
142 len
= PM3_CMD_DATA_SIZE
- sizeof(arg
);
143 status
= PM3_EOVFLOW
;
145 uint8_t cmddata
[PM3_CMD_DATA_SIZE
];
146 memcpy(cmddata
, arg
, sizeof(arg
));
148 memcpy(cmddata
+ sizeof(arg
), data
, (int)len
);
150 return reply_ng_internal((cmd
& 0xFFFF), status
, cmddata
, len
+ sizeof(arg
), false);
153 static int receive_ng_internal(PacketCommandNG
*rx
, uint32_t read_ng(uint8_t *data
, size_t len
), bool usb
, bool fpc
) {
154 PacketCommandNGRaw rx_raw
;
155 size_t bytes
= read_ng((uint8_t *)&rx_raw
.pre
, sizeof(PacketCommandNGPreamble
));
160 if (bytes
!= sizeof(PacketCommandNGPreamble
))
163 rx
->magic
= rx_raw
.pre
.magic
;
164 rx
->ng
= rx_raw
.pre
.ng
;
165 uint16_t length
= rx_raw
.pre
.length
;
166 rx
->cmd
= rx_raw
.pre
.cmd
;
168 if (rx
->magic
== COMMANDNG_PREAMBLE_MAGIC
) { // New style NG command
169 if (length
> PM3_CMD_DATA_SIZE
)
172 // Get the core and variable length payload
173 bytes
= read_ng((uint8_t *)&rx_raw
.data
, length
);
178 memcpy(rx
->data
.asBytes
, rx_raw
.data
, length
);
182 if (length
< sizeof(arg
))
185 memcpy(arg
, rx_raw
.data
, sizeof(arg
));
186 rx
->oldarg
[0] = arg
[0];
187 rx
->oldarg
[1] = arg
[1];
188 rx
->oldarg
[2] = arg
[2];
189 memcpy(rx
->data
.asBytes
, rx_raw
.data
+ sizeof(arg
), length
- sizeof(arg
));
190 rx
->length
= length
- sizeof(arg
);
193 bytes
= read_ng((uint8_t *)&rx_raw
.foopost
, sizeof(PacketCommandNGPostamble
));
194 if (bytes
!= sizeof(PacketCommandNGPostamble
))
197 // Check CRC, accept MAGIC as placeholder
198 rx
->crc
= rx_raw
.foopost
.crc
;
199 if (rx
->crc
!= COMMANDNG_POSTAMBLE_MAGIC
) {
200 uint8_t first
, second
;
201 compute_crc(CRC_14443_A
, (uint8_t *)&rx_raw
, sizeof(PacketCommandNGPreamble
) + length
, &first
, &second
);
202 if ((first
<< 8) + second
!= rx
->crc
)
205 g_reply_via_usb
= usb
;
206 g_reply_via_fpc
= fpc
;
207 } else { // Old style command
208 PacketCommandOLD rx_old
;
209 memcpy(&rx_old
, &rx_raw
.pre
, sizeof(PacketCommandNGPreamble
));
210 bytes
= read_ng(((uint8_t *)&rx_old
) + sizeof(PacketCommandNGPreamble
), sizeof(PacketCommandOLD
) - sizeof(PacketCommandNGPreamble
));
211 if (bytes
!= sizeof(PacketCommandOLD
) - sizeof(PacketCommandNGPreamble
))
214 g_reply_via_usb
= usb
;
215 g_reply_via_fpc
= fpc
;
219 rx
->cmd
= (rx_old
.cmd
& 0xFFFF);
220 rx
->oldarg
[0] = rx_old
.arg
[0];
221 rx
->oldarg
[1] = rx_old
.arg
[1];
222 rx
->oldarg
[2] = rx_old
.arg
[2];
223 rx
->length
= PM3_CMD_DATA_SIZE
;
224 memcpy(&rx
->data
, &rx_old
.d
.asBytes
, rx
->length
);
229 int receive_ng(PacketCommandNG
*rx
) {
231 // Check if there is a packet available
232 if (usb_poll_validate_length())
233 return receive_ng_internal(rx
, usb_read_ng
, true, false);
235 #ifdef WITH_FPC_USART_HOST
236 // Check if there is a FPC packet available
237 if (usart_rxdata_available() > 0)
238 return receive_ng_internal(rx
, usart_read_ng
, false, true);