2 * Proxmark send and receive commands
4 * Copyright (c) 2012, Roel Verdult
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the copyright holders nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 // Flags to tell where to add CRC on sent replies
39 bool g_reply_with_crc_on_usb
= false;
40 bool g_reply_with_crc_on_fpc
= true;
41 // "Session" flag, to tell via which interface next msgs should be sent: USB or FPC USART
42 bool g_reply_via_fpc
= false;
43 bool g_reply_via_usb
= false;
45 int reply_old(uint64_t cmd
, uint64_t arg0
, uint64_t arg1
, uint64_t arg2
, void *data
, size_t len
) {
46 PacketResponseOLD txcmd
= {CMD_UNKNOWN
, {0, 0, 0}, {{0}}};
48 // for (size_t i = 0; i < sizeof(PacketResponseOLD); i++)
49 // ((uint8_t *)&txcmd)[i] = 0x00;
51 // Compose the outgoing command frame
57 // Add the (optional) content to the frame, with a maximum size of PM3_CMD_DATA_SIZE
59 len
= MIN(len
, PM3_CMD_DATA_SIZE
);
60 for (size_t i
= 0; i
< len
; i
++) {
61 txcmd
.d
.asBytes
[i
] = ((uint8_t *)data
)[i
];
65 #ifdef WITH_FPC_USART_HOST
66 int resultfpc
= PM3_EUNDEF
;
68 int resultusb
= PM3_EUNDEF
;
69 // Send frame and make sure all bytes are transmitted
71 if (g_reply_via_usb
) {
72 resultusb
= usb_write((uint8_t *)&txcmd
, sizeof(PacketResponseOLD
));
75 if (g_reply_via_fpc
) {
76 #ifdef WITH_FPC_USART_HOST
77 resultfpc
= usart_writebuffer_sync((uint8_t *)&txcmd
, sizeof(PacketResponseOLD
));
79 return PM3_EDEVNOTSUPP
;
82 // we got two results, let's prioritize the faulty one and USB over FPC.
83 if (g_reply_via_usb
&& (resultusb
!= PM3_SUCCESS
)) return resultusb
;
84 #ifdef WITH_FPC_USART_HOST
85 if (g_reply_via_fpc
&& (resultfpc
!= PM3_SUCCESS
)) return resultfpc
;
90 static int reply_ng_internal(uint16_t cmd
, int16_t status
, uint8_t *data
, size_t len
, bool ng
) {
91 PacketResponseNGRaw txBufferNG
;
94 // Compose the outgoing command frame
95 txBufferNG
.pre
.magic
= RESPONSENG_PREAMBLE_MAGIC
;
96 txBufferNG
.pre
.cmd
= cmd
;
97 txBufferNG
.pre
.status
= status
;
98 txBufferNG
.pre
.ng
= ng
;
99 if (len
> PM3_CMD_DATA_SIZE
) {
100 len
= PM3_CMD_DATA_SIZE
;
102 txBufferNG
.pre
.status
= PM3_EOVFLOW
;
105 // length is only 15bit (32768)
106 txBufferNG
.pre
.length
= (len
& 0x7FFF);
108 // Add the (optional) content to the frame, with a maximum size of PM3_CMD_DATA_SIZE
110 for (size_t i
= 0; i
< len
; i
++) {
111 txBufferNG
.data
[i
] = data
[i
];
115 PacketResponseNGPostamble
*tx_post
= (PacketResponseNGPostamble
*)((uint8_t *)&txBufferNG
+ sizeof(PacketResponseNGPreamble
) + len
);
116 // Note: if we send to both FPC & USB, we'll set CRC for both if any of them require CRC
117 if ((g_reply_via_fpc
&& g_reply_with_crc_on_fpc
) || ((g_reply_via_usb
) && g_reply_with_crc_on_usb
)) {
118 uint8_t first
, second
;
119 compute_crc(CRC_14443_A
, (uint8_t *)&txBufferNG
, sizeof(PacketResponseNGPreamble
) + len
, &first
, &second
);
120 tx_post
->crc
= ((first
<< 8) | second
);
122 tx_post
->crc
= RESPONSENG_POSTAMBLE_MAGIC
;
124 txBufferNGLen
= sizeof(PacketResponseNGPreamble
) + len
+ sizeof(PacketResponseNGPostamble
);
126 #ifdef WITH_FPC_USART_HOST
127 int resultfpc
= PM3_EUNDEF
;
129 int resultusb
= PM3_EUNDEF
;
130 // Send frame and make sure all bytes are transmitted
132 if (g_reply_via_usb
) {
133 resultusb
= usb_write((uint8_t *)&txBufferNG
, txBufferNGLen
);
135 if (g_reply_via_fpc
) {
136 #ifdef WITH_FPC_USART_HOST
137 resultfpc
= usart_writebuffer_sync((uint8_t *)&txBufferNG
, txBufferNGLen
);
139 return PM3_EDEVNOTSUPP
;
142 // we got two results, let's prioritize the faulty one and USB over FPC.
143 if (g_reply_via_usb
&& (resultusb
!= PM3_SUCCESS
)) return resultusb
;
144 #ifdef WITH_FPC_USART_HOST
145 if (g_reply_via_fpc
&& (resultfpc
!= PM3_SUCCESS
)) return resultfpc
;
150 int reply_ng(uint16_t cmd
, int16_t status
, uint8_t *data
, size_t len
) {
151 return reply_ng_internal(cmd
, status
, data
, len
, true);
154 int reply_mix(uint64_t cmd
, uint64_t arg0
, uint64_t arg1
, uint64_t arg2
, void *data
, size_t len
) {
155 int16_t status
= PM3_SUCCESS
;
156 uint64_t arg
[3] = {arg0
, arg1
, arg2
};
157 if (len
> PM3_CMD_DATA_SIZE
- sizeof(arg
)) {
158 len
= PM3_CMD_DATA_SIZE
- sizeof(arg
);
159 status
= PM3_EOVFLOW
;
161 uint8_t cmddata
[PM3_CMD_DATA_SIZE
];
162 memcpy(cmddata
, arg
, sizeof(arg
));
164 memcpy(cmddata
+ sizeof(arg
), data
, (int)len
);
166 return reply_ng_internal((cmd
& 0xFFFF), status
, cmddata
, len
+ sizeof(arg
), false);
169 static int receive_ng_internal(PacketCommandNG
*rx
, uint32_t read_ng(uint8_t *data
, size_t len
), bool usb
, bool fpc
) {
170 PacketCommandNGRaw rx_raw
;
171 size_t bytes
= read_ng((uint8_t *)&rx_raw
.pre
, sizeof(PacketCommandNGPreamble
));
176 if (bytes
!= sizeof(PacketCommandNGPreamble
))
179 rx
->magic
= rx_raw
.pre
.magic
;
180 rx
->ng
= rx_raw
.pre
.ng
;
181 uint16_t length
= rx_raw
.pre
.length
;
182 rx
->cmd
= rx_raw
.pre
.cmd
;
184 if (rx
->magic
== COMMANDNG_PREAMBLE_MAGIC
) { // New style NG command
185 if (length
> PM3_CMD_DATA_SIZE
)
188 // Get the core and variable length payload
189 bytes
= read_ng((uint8_t *)&rx_raw
.data
, length
);
194 memcpy(rx
->data
.asBytes
, rx_raw
.data
, length
);
198 if (length
< sizeof(arg
))
201 memcpy(arg
, rx_raw
.data
, sizeof(arg
));
202 rx
->oldarg
[0] = arg
[0];
203 rx
->oldarg
[1] = arg
[1];
204 rx
->oldarg
[2] = arg
[2];
205 memcpy(rx
->data
.asBytes
, rx_raw
.data
+ sizeof(arg
), length
- sizeof(arg
));
206 rx
->length
= length
- sizeof(arg
);
209 bytes
= read_ng((uint8_t *)&rx_raw
.foopost
, sizeof(PacketCommandNGPostamble
));
210 if (bytes
!= sizeof(PacketCommandNGPostamble
))
213 // Check CRC, accept MAGIC as placeholder
214 rx
->crc
= rx_raw
.foopost
.crc
;
215 if (rx
->crc
!= COMMANDNG_POSTAMBLE_MAGIC
) {
216 uint8_t first
, second
;
217 compute_crc(CRC_14443_A
, (uint8_t *)&rx_raw
, sizeof(PacketCommandNGPreamble
) + length
, &first
, &second
);
218 if ((first
<< 8) + second
!= rx
->crc
)
221 g_reply_via_usb
= usb
;
222 g_reply_via_fpc
= fpc
;
223 } else { // Old style command
224 PacketCommandOLD rx_old
;
225 memcpy(&rx_old
, &rx_raw
.pre
, sizeof(PacketCommandNGPreamble
));
226 bytes
= read_ng(((uint8_t *)&rx_old
) + sizeof(PacketCommandNGPreamble
), sizeof(PacketCommandOLD
) - sizeof(PacketCommandNGPreamble
));
227 if (bytes
!= sizeof(PacketCommandOLD
) - sizeof(PacketCommandNGPreamble
))
230 g_reply_via_usb
= usb
;
231 g_reply_via_fpc
= fpc
;
235 rx
->cmd
= (rx_old
.cmd
& 0xFFFF);
236 rx
->oldarg
[0] = rx_old
.arg
[0];
237 rx
->oldarg
[1] = rx_old
.arg
[1];
238 rx
->oldarg
[2] = rx_old
.arg
[2];
239 rx
->length
= PM3_CMD_DATA_SIZE
;
240 memcpy(&rx
->data
, &rx_old
.d
.asBytes
, rx
->length
);
245 int receive_ng(PacketCommandNG
*rx
) {
247 // Check if there is a packet available
248 if (usb_poll_validate_length())
249 return receive_ng_internal(rx
, usb_read_ng
, true, false);
251 #ifdef WITH_FPC_USART_HOST
252 // Check if there is a FPC packet available
253 if (usart_rxdata_available() > 0)
254 return receive_ng_internal(rx
, usart_read_ng
, false, true);