sap.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2012 Tieto Poland
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <stdio.h>
  15. #include <errno.h>
  16. #include <unistd.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include "parser.h"
  20. #define PADDING4(x) ((4 - ((x) & 0x03)) & 0x03)
  21. #define SAP_CONNECT_REQ 0x00
  22. #define SAP_CONNECT_RESP 0x01
  23. #define SAP_DISCONNECT_REQ 0x02
  24. #define SAP_DISCONNECT_RESP 0x03
  25. #define SAP_DISCONNECT_IND 0x04
  26. #define SAP_TRANSFER_APDU_REQ 0x05
  27. #define SAP_TRANSFER_APDU_RESP 0x06
  28. #define SAP_TRANSFER_ATR_REQ 0x07
  29. #define SAP_TRANSFER_ATR_RESP 0x08
  30. #define SAP_POWER_SIM_OFF_REQ 0x09
  31. #define SAP_POWER_SIM_OFF_RESP 0x0A
  32. #define SAP_POWER_SIM_ON_REQ 0x0B
  33. #define SAP_POWER_SIM_ON_RESP 0x0C
  34. #define SAP_RESET_SIM_REQ 0x0D
  35. #define SAP_RESET_SIM_RESP 0x0E
  36. #define SAP_TRANSFER_CARD_READER_STATUS_REQ 0x0F
  37. #define SAP_TRANSFER_CARD_READER_STATUS_RESP 0x10
  38. #define SAP_STATUS_IND 0x11
  39. #define SAP_ERROR_RESP 0x12
  40. #define SAP_SET_TRANSPORT_PROTOCOL_REQ 0x13
  41. #define SAP_SET_TRANSPORT_PROTOCOL_RESP 0x14
  42. #define SAP_PARAM_ID_MAX_MSG_SIZE 0x00
  43. #define SAP_PARAM_ID_CONN_STATUS 0x01
  44. #define SAP_PARAM_ID_RESULT_CODE 0x02
  45. #define SAP_PARAM_ID_DISCONNECT_IND 0x03
  46. #define SAP_PARAM_ID_COMMAND_APDU 0x04
  47. #define SAP_PARAM_ID_COMMAND_APDU7816 0x10
  48. #define SAP_PARAM_ID_RESPONSE_APDU 0x05
  49. #define SAP_PARAM_ID_ATR 0x06
  50. #define SAP_PARAM_ID_CARD_READER_STATUS 0x07
  51. #define SAP_PARAM_ID_STATUS_CHANGE 0x08
  52. #define SAP_PARAM_ID_TRANSPORT_PROTOCOL 0x09
  53. #define SAP_STATUS_OK 0x00
  54. #define SAP_STATUS_CONNECTION_FAILED 0x01
  55. #define SAP_STATUS_MAX_MSG_SIZE_NOT_SUPPORTED 0x02
  56. #define SAP_STATUS_MAX_MSG_SIZE_TOO_SMALL 0x03
  57. #define SAP_STATUS_OK_ONGOING_CALL 0x04
  58. #define SAP_DISCONNECTION_TYPE_GRACEFUL 0x00
  59. #define SAP_DISCONNECTION_TYPE_IMMEDIATE 0x01
  60. #define SAP_DISCONNECTION_TYPE_CLIENT 0xFF
  61. #define SAP_RESULT_OK 0x00
  62. #define SAP_RESULT_ERROR_NO_REASON 0x01
  63. #define SAP_RESULT_ERROR_NOT_ACCESSIBLE 0x02
  64. #define SAP_RESULT_ERROR_POWERED_OFF 0x03
  65. #define SAP_RESULT_ERROR_CARD_REMOVED 0x04
  66. #define SAP_RESULT_ERROR_POWERED_ON 0x05
  67. #define SAP_RESULT_ERROR_NO_DATA 0x06
  68. #define SAP_RESULT_NOT_SUPPORTED 0x07
  69. #define SAP_STATUS_CHANGE_UNKNOWN_ERROR 0x00
  70. #define SAP_STATUS_CHANGE_CARD_RESET 0x01
  71. #define SAP_STATUS_CHANGE_CARD_NOT_ACCESSIBLE 0x02
  72. #define SAP_STATUS_CHANGE_CARD_REMOVED 0x03
  73. #define SAP_STATUS_CHANGE_CARD_INSERTED 0x04
  74. #define SAP_STATUS_CHANGE_CARD_RECOVERED 0x05
  75. #define SAP_TRANSPORT_PROTOCOL_T0 0x00
  76. #define SAP_TRANSPORT_PROTOCOL_T1 0x01
  77. static const char *msg2str(uint8_t msg)
  78. {
  79. switch (msg) {
  80. case SAP_CONNECT_REQ:
  81. return "Connect Req";
  82. case SAP_CONNECT_RESP:
  83. return "Connect Resp";
  84. case SAP_DISCONNECT_REQ:
  85. return "Disconnect Req";
  86. case SAP_DISCONNECT_RESP:
  87. return "Disconnect Resp";
  88. case SAP_DISCONNECT_IND:
  89. return "Disconnect Ind";
  90. case SAP_TRANSFER_APDU_REQ:
  91. return "Transfer APDU Req";
  92. case SAP_TRANSFER_APDU_RESP:
  93. return "Transfer APDU Resp";
  94. case SAP_TRANSFER_ATR_REQ:
  95. return "Transfer ATR Req";
  96. case SAP_TRANSFER_ATR_RESP:
  97. return "Transfer ATR Resp";
  98. case SAP_POWER_SIM_OFF_REQ:
  99. return "Power SIM Off Req";
  100. case SAP_POWER_SIM_OFF_RESP:
  101. return "Power SIM Off Resp";
  102. case SAP_POWER_SIM_ON_REQ:
  103. return "Power SIM On Req";
  104. case SAP_POWER_SIM_ON_RESP:
  105. return "Power SIM On Resp";
  106. case SAP_RESET_SIM_REQ:
  107. return "Reset SIM Req";
  108. case SAP_RESET_SIM_RESP:
  109. return "Reset SIM Resp";
  110. case SAP_TRANSFER_CARD_READER_STATUS_REQ:
  111. return "Transfer Card Reader Status Req";
  112. case SAP_TRANSFER_CARD_READER_STATUS_RESP:
  113. return "Transfer Card Reader Status Resp";
  114. case SAP_STATUS_IND:
  115. return "Status Ind";
  116. case SAP_ERROR_RESP:
  117. return "Error Resp";
  118. case SAP_SET_TRANSPORT_PROTOCOL_REQ:
  119. return "Set Transport Protocol Req";
  120. case SAP_SET_TRANSPORT_PROTOCOL_RESP:
  121. return "Set Transport Protocol Resp";
  122. default:
  123. return "Reserved";
  124. }
  125. }
  126. static const char *param2str(uint8_t param)
  127. {
  128. switch (param) {
  129. case SAP_PARAM_ID_MAX_MSG_SIZE:
  130. return "MaxMsgSize";
  131. case SAP_PARAM_ID_CONN_STATUS:
  132. return "ConnectionStatus";
  133. case SAP_PARAM_ID_RESULT_CODE:
  134. return "ResultCode";
  135. case SAP_PARAM_ID_DISCONNECT_IND:
  136. return "DisconnectionType";
  137. case SAP_PARAM_ID_COMMAND_APDU:
  138. return "CommandAPDU";
  139. case SAP_PARAM_ID_COMMAND_APDU7816:
  140. return "CommandAPDU7816";
  141. case SAP_PARAM_ID_RESPONSE_APDU:
  142. return "ResponseAPDU";
  143. case SAP_PARAM_ID_ATR:
  144. return "ATR";
  145. case SAP_PARAM_ID_CARD_READER_STATUS:
  146. return "CardReaderStatus";
  147. case SAP_PARAM_ID_STATUS_CHANGE:
  148. return "StatusChange";
  149. case SAP_PARAM_ID_TRANSPORT_PROTOCOL:
  150. return "TransportProtocol";
  151. default:
  152. return "Reserved";
  153. }
  154. }
  155. static const char *status2str(uint8_t status)
  156. {
  157. switch (status) {
  158. case SAP_STATUS_OK:
  159. return "OK, Server can fulfill requirements";
  160. case SAP_STATUS_CONNECTION_FAILED:
  161. return "Error, Server unable to establish connection";
  162. case SAP_STATUS_MAX_MSG_SIZE_NOT_SUPPORTED:
  163. return "Error, Server does not support maximum message size";
  164. case SAP_STATUS_MAX_MSG_SIZE_TOO_SMALL:
  165. return "Error, maximum message size by Client is too small";
  166. case SAP_STATUS_OK_ONGOING_CALL:
  167. return "OK, ongoing call";
  168. default:
  169. return "Reserved";
  170. }
  171. }
  172. static const char *disctype2str(uint8_t disctype)
  173. {
  174. switch (disctype) {
  175. case SAP_DISCONNECTION_TYPE_GRACEFUL:
  176. return "Graceful";
  177. case SAP_DISCONNECTION_TYPE_IMMEDIATE:
  178. return "Immediate";
  179. default:
  180. return "Reserved";
  181. }
  182. }
  183. static const char *result2str(uint8_t result)
  184. {
  185. switch (result) {
  186. case SAP_RESULT_OK:
  187. return "OK, request processed correctly";
  188. case SAP_RESULT_ERROR_NO_REASON:
  189. return "Error, no reason defined";
  190. case SAP_RESULT_ERROR_NOT_ACCESSIBLE:
  191. return "Error, card not accessible";
  192. case SAP_RESULT_ERROR_POWERED_OFF:
  193. return "Error, card (already) powered off";
  194. case SAP_RESULT_ERROR_CARD_REMOVED:
  195. return "Error, card removed";
  196. case SAP_RESULT_ERROR_POWERED_ON:
  197. return "Error, card already powered on";
  198. case SAP_RESULT_ERROR_NO_DATA:
  199. return "Error, data not available";
  200. case SAP_RESULT_NOT_SUPPORTED:
  201. return "Error, not supported";
  202. default:
  203. return "Reserved";
  204. }
  205. }
  206. static const char *statuschg2str(uint8_t statuschg)
  207. {
  208. switch (statuschg) {
  209. case SAP_STATUS_CHANGE_UNKNOWN_ERROR:
  210. return "Unknown Error";
  211. case SAP_STATUS_CHANGE_CARD_RESET:
  212. return "Card reset";
  213. case SAP_STATUS_CHANGE_CARD_NOT_ACCESSIBLE:
  214. return "Card not accessible";
  215. case SAP_STATUS_CHANGE_CARD_REMOVED:
  216. return "Card removed";
  217. case SAP_STATUS_CHANGE_CARD_INSERTED:
  218. return "Card inserted";
  219. case SAP_STATUS_CHANGE_CARD_RECOVERED:
  220. return "Card recovered";
  221. default:
  222. return "Reserved";
  223. }
  224. }
  225. static const char *prot2str(uint8_t prot)
  226. {
  227. switch (prot) {
  228. case SAP_TRANSPORT_PROTOCOL_T0:
  229. return "T=0";
  230. case SAP_TRANSPORT_PROTOCOL_T1:
  231. return "T=1";
  232. default:
  233. return "Reserved";
  234. }
  235. }
  236. static void parse_parameters(int level, struct frame *frm)
  237. {
  238. uint8_t param;
  239. uint16_t len;
  240. uint8_t pv8;
  241. while (frm->len > 3) {
  242. p_indent(level, frm);
  243. param = p_get_u8(frm);
  244. p_get_u8(frm);
  245. len = p_get_u16(frm);
  246. printf("%s (0x%02x) len %d = ", param2str(param), param, len);
  247. switch (param) {
  248. case SAP_PARAM_ID_MAX_MSG_SIZE:
  249. printf("%d\n", p_get_u16(frm));
  250. break;
  251. case SAP_PARAM_ID_CONN_STATUS:
  252. pv8 = p_get_u8(frm);
  253. printf("0x%02x (%s)\n", pv8, status2str(pv8));
  254. break;
  255. case SAP_PARAM_ID_RESULT_CODE:
  256. case SAP_PARAM_ID_CARD_READER_STATUS:
  257. pv8 = p_get_u8(frm);
  258. printf("0x%02x (%s)\n", pv8, result2str(pv8));
  259. break;
  260. case SAP_PARAM_ID_DISCONNECT_IND:
  261. pv8 = p_get_u8(frm);
  262. printf("0x%02x (%s)\n", pv8, disctype2str(pv8));
  263. break;
  264. case SAP_PARAM_ID_STATUS_CHANGE:
  265. pv8 = p_get_u8(frm);
  266. printf("0x%02x (%s)\n", pv8, statuschg2str(pv8));
  267. break;
  268. case SAP_PARAM_ID_TRANSPORT_PROTOCOL:
  269. pv8 = p_get_u8(frm);
  270. printf("0x%02x (%s)\n", pv8, prot2str(pv8));
  271. break;
  272. default:
  273. printf("\n");
  274. raw_ndump(level + 1, frm, len);
  275. frm->ptr += len;
  276. frm->len -= len;
  277. }
  278. /* Skip padding */
  279. frm->ptr += PADDING4(len);
  280. frm->len -= PADDING4(len);
  281. }
  282. }
  283. void sap_dump(int level, struct frame *frm)
  284. {
  285. uint8_t msg, params;
  286. msg = p_get_u8(frm);
  287. params = p_get_u8(frm);
  288. /* Skip reserved field */
  289. p_get_u16(frm);
  290. p_indent(level, frm);
  291. printf("SAP: %s: params %d\n", msg2str(msg), params);
  292. parse_parameters(level, frm);
  293. }