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 //-----------------------------------------------------------------------------
23 // Flags to tell where to add CRC on sent replies
24 bool g_reply_with_crc_on_usb
= false;
25 bool g_reply_with_crc_on_fpc
= true;
26 // "Session" flag, to tell via which interface next msgs should be sent: USB or FPC USART
27 bool g_reply_via_fpc
= false;
28 bool g_reply_via_usb
= false;
30 int reply_old(uint64_t cmd
, uint64_t arg0
, uint64_t arg1
, uint64_t arg2
, const void *data
, size_t len
) {
31 PacketResponseOLD txcmd
= {CMD_UNKNOWN
, {0, 0, 0}, {{0}}};
33 for (size_t i
= 0; i
< sizeof(PacketResponseOLD
); i
++)
34 ((uint8_t *)&txcmd
)[i
] = 0x00;
36 // Compose the outgoing command frame
42 // Add the (optional) content to the frame, with a maximum size of PM3_CMD_DATA_SIZE
44 len
= MIN(len
, PM3_CMD_DATA_SIZE
);
45 for (size_t i
= 0; i
< len
; i
++) {
46 txcmd
.d
.asBytes
[i
] = ((const uint8_t *)data
)[i
];
50 #ifdef WITH_FPC_USART_HOST
51 int resultfpc
= PM3_EUNDEF
;
53 int resultusb
= PM3_EUNDEF
;
54 // Send frame and make sure all bytes are transmitted
56 if (g_reply_via_usb
) {
57 resultusb
= usb_write((uint8_t *)&txcmd
, sizeof(PacketResponseOLD
));
60 if (g_reply_via_fpc
) {
61 #ifdef WITH_FPC_USART_HOST
62 resultfpc
= usart_writebuffer_sync((uint8_t *)&txcmd
, sizeof(PacketResponseOLD
));
64 return PM3_EDEVNOTSUPP
;
67 // we got two results, let's prioritize the faulty one and USB over FPC.
68 if (g_reply_via_usb
&& (resultusb
!= PM3_SUCCESS
)) return resultusb
;
69 #ifdef WITH_FPC_USART_HOST
70 if (g_reply_via_fpc
&& (resultfpc
!= PM3_SUCCESS
)) return resultfpc
;
75 static int reply_ng_internal(uint16_t cmd
, int8_t status
, uint8_t reason
, const uint8_t *data
, size_t len
, bool ng
) {
76 PacketResponseNGRaw txBufferNG
;
79 // Compose the outgoing command frame
80 txBufferNG
.pre
.magic
= RESPONSENG_PREAMBLE_MAGIC
;
81 txBufferNG
.pre
.cmd
= cmd
;
82 txBufferNG
.pre
.status
= status
;
83 txBufferNG
.pre
.reason
= reason
;
84 txBufferNG
.pre
.ng
= ng
;
85 if (len
> PM3_CMD_DATA_SIZE
) {
86 len
= PM3_CMD_DATA_SIZE
;
88 txBufferNG
.pre
.status
= PM3_EOVFLOW
;
91 // length is only 15bit (32768)
92 txBufferNG
.pre
.length
= (len
& 0x7FFF);
94 // Add the (optional) content to the frame, with a maximum size of PM3_CMD_DATA_SIZE
96 memcpy(txBufferNG
.data
, data
, len
);
99 PacketResponseNGPostamble
*tx_post
= (PacketResponseNGPostamble
*)((uint8_t *)&txBufferNG
+ sizeof(PacketResponseNGPreamble
) + len
);
101 // Note: if we send to both FPC & USB, we'll set CRC for both if any of them require CRC
102 if ((g_reply_via_fpc
&& g_reply_with_crc_on_fpc
) || ((g_reply_via_usb
) && g_reply_with_crc_on_usb
)) {
103 uint8_t first
, second
;
104 compute_crc(CRC_14443_A
, (uint8_t *)&txBufferNG
, sizeof(PacketResponseNGPreamble
) + len
, &first
, &second
);
105 tx_post
->crc
= ((first
<< 8) | second
);
107 tx_post
->crc
= RESPONSENG_POSTAMBLE_MAGIC
;
109 txBufferNGLen
= sizeof(PacketResponseNGPreamble
) + len
+ sizeof(PacketResponseNGPostamble
);
111 #ifdef WITH_FPC_USART_HOST
112 int resultfpc
= PM3_EUNDEF
;
114 int resultusb
= PM3_EUNDEF
;
115 // Send frame and make sure all bytes are transmitted
117 if (g_reply_via_usb
) {
118 resultusb
= usb_write((uint8_t *)&txBufferNG
, txBufferNGLen
);
120 if (g_reply_via_fpc
) {
121 #ifdef WITH_FPC_USART_HOST
122 resultfpc
= usart_writebuffer_sync((uint8_t *)&txBufferNG
, txBufferNGLen
);
124 return PM3_EDEVNOTSUPP
;
127 // we got two results, let's prioritize the faulty one and USB over FPC.
128 if (g_reply_via_usb
&& (resultusb
!= PM3_SUCCESS
)) {
132 #ifdef WITH_FPC_USART_HOST
133 if (g_reply_via_fpc
&& (resultfpc
!= PM3_SUCCESS
)) {
140 int reply_ng(uint16_t cmd
, int8_t status
, const uint8_t *data
, size_t len
) {
141 return reply_ng_internal(cmd
, status
, PM3_REASON_UNKNOWN
, data
, len
, true);
144 int reply_mix(uint64_t cmd
, uint64_t arg0
, uint64_t arg1
, uint64_t arg2
, const void *data
, size_t len
) {
145 int8_t status
= PM3_SUCCESS
;
146 uint64_t arg
[3] = {arg0
, arg1
, arg2
};
147 if (len
> PM3_CMD_DATA_SIZE
- sizeof(arg
)) {
148 len
= PM3_CMD_DATA_SIZE
- sizeof(arg
);
149 status
= PM3_EOVFLOW
;
151 uint8_t cmddata
[PM3_CMD_DATA_SIZE
];
152 memcpy(cmddata
, arg
, sizeof(arg
));
154 memcpy(cmddata
+ sizeof(arg
), data
, (int)len
);
157 return reply_ng_internal((cmd
& 0xFFFF), status
, PM3_REASON_UNKNOWN
, cmddata
, len
+ sizeof(arg
), false);
160 int reply_reason(uint16_t cmd
, int8_t status
, int8_t reason
, const uint8_t *data
, size_t len
) {
161 return reply_ng_internal(cmd
, status
, reason
, data
, len
, true);
164 static int receive_ng_internal(PacketCommandNG
*rx
, uint32_t read_ng(uint8_t *data
, size_t len
), bool usb
, bool fpc
) {
166 PacketCommandNGRaw rx_raw
;
167 size_t bytes
= read_ng((uint8_t *)&rx_raw
.pre
, sizeof(PacketCommandNGPreamble
));
173 if (bytes
!= sizeof(PacketCommandNGPreamble
)) {
177 rx
->magic
= rx_raw
.pre
.magic
;
178 rx
->ng
= rx_raw
.pre
.ng
;
179 rx
->cmd
= rx_raw
.pre
.cmd
;
181 uint16_t length
= rx_raw
.pre
.length
;
183 if (rx
->magic
== COMMANDNG_PREAMBLE_MAGIC
) { // New style NG command
184 if (length
> PM3_CMD_DATA_SIZE
) {
188 // Get the core and variable length payload
189 bytes
= read_ng((uint8_t *)&rx_raw
.data
, length
);
190 if (bytes
!= length
) {
195 memcpy(rx
->data
.asBytes
, rx_raw
.data
, length
);
198 uint64_t arg
[3] = {0};
199 if (length
< sizeof(arg
)) {
203 memcpy(arg
, rx_raw
.data
, sizeof(arg
));
204 rx
->oldarg
[0] = arg
[0];
205 rx
->oldarg
[1] = arg
[1];
206 rx
->oldarg
[2] = arg
[2];
207 memcpy(rx
->data
.asBytes
, rx_raw
.data
+ sizeof(arg
), length
- sizeof(arg
));
208 rx
->length
= length
- sizeof(arg
);
212 bytes
= read_ng((uint8_t *)&rx_raw
.foopost
, sizeof(PacketCommandNGPostamble
));
213 if (bytes
!= sizeof(PacketCommandNGPostamble
)) {
217 // Check CRC, accept MAGIC as placeholder
218 rx
->crc
= rx_raw
.foopost
.crc
;
219 if (rx
->crc
!= COMMANDNG_POSTAMBLE_MAGIC
) {
220 uint8_t first
, second
;
221 compute_crc(CRC_14443_A
, (uint8_t *)&rx_raw
, sizeof(PacketCommandNGPreamble
) + length
, &first
, &second
);
222 if ((first
<< 8) + second
!= rx
->crc
) {
227 g_reply_via_usb
= usb
;
228 g_reply_via_fpc
= fpc
;
230 } else { // Old style command
231 PacketCommandOLD rx_old
;
232 memcpy(&rx_old
, &rx_raw
.pre
, sizeof(PacketCommandNGPreamble
));
233 bytes
= read_ng(((uint8_t *)&rx_old
) + sizeof(PacketCommandNGPreamble
), sizeof(PacketCommandOLD
) - sizeof(PacketCommandNGPreamble
));
234 if (bytes
!= sizeof(PacketCommandOLD
) - sizeof(PacketCommandNGPreamble
)) {
238 g_reply_via_usb
= usb
;
239 g_reply_via_fpc
= fpc
;
243 rx
->cmd
= (rx_old
.cmd
& 0xFFFF);
244 rx
->oldarg
[0] = rx_old
.arg
[0];
245 rx
->oldarg
[1] = rx_old
.arg
[1];
246 rx
->oldarg
[2] = rx_old
.arg
[2];
247 rx
->length
= PM3_CMD_DATA_SIZE
;
248 memcpy(&rx
->data
, &rx_old
.d
.asBytes
, rx
->length
);
253 int receive_ng(PacketCommandNG
*rx
) {
255 // Check if there is a packet available
256 if (usb_poll_validate_length()) {
257 return receive_ng_internal(rx
, usb_read_ng
, true, false);
260 #ifdef WITH_FPC_USART_HOST
261 // Check if there is a FPC packet available
262 if (usart_rxdata_available() > 0)
263 return receive_ng_internal(rx
, usart_read_ng
, false, true);