libnfc  1.7.0-rc7
mifare.c
Go to the documentation of this file.
1 /*-
2  * Free/Libre Near Field Communication (NFC) library
3  *
4  * Libnfc historical contributors:
5  * Copyright (C) 2009 Roel Verdult
6  * Copyright (C) 2009-2013 Romuald Conty
7  * Copyright (C) 2010-2012 Romain Tartière
8  * Copyright (C) 2010-2013 Philippe Teuwen
9  * Copyright (C) 2012-2013 Ludovic Rousseau
10  * Additional contributors of this file:
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  * 1) Redistributions of source code must retain the above copyright notice,
15  * this list of conditions and the following disclaimer.
16  * 2 )Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in the
18  * documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  * Note that this license only applies on the examples, NFC library itself is under LGPL
33  *
34  */
39 #include "mifare.h"
40 
41 #include <string.h>
42 
43 #include <nfc/nfc.h>
44 
58 bool
59 nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param *pmp)
60 {
61  uint8_t abtRx[265];
62  size_t szParamLen;
63  uint8_t abtCmd[265];
64  //bool bEasyFraming;
65 
66  abtCmd[0] = mc; // The MIFARE Classic command
67  abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
68 
69  switch (mc) {
70  // Read and store command have no parameter
71  case MC_READ:
72  case MC_STORE:
73  szParamLen = 0;
74  break;
75 
76  // Authenticate command
77  case MC_AUTH_A:
78  case MC_AUTH_B:
79  szParamLen = sizeof(struct mifare_param_auth);
80  break;
81 
82  // Data command
83  case MC_WRITE:
84  szParamLen = sizeof(struct mifare_param_data);
85  break;
86 
87  // Value command
88  case MC_DECREMENT:
89  case MC_INCREMENT:
90  case MC_TRANSFER:
91  szParamLen = sizeof(struct mifare_param_value);
92  break;
93 
94  // Please fix your code, you never should reach this statement
95  default:
96  return false;
97  break;
98  }
99 
100  // When available, copy the parameter bytes
101  if (szParamLen)
102  memcpy(abtCmd + 2, (uint8_t *) pmp, szParamLen);
103 
104  // FIXME: Save and restore bEasyFraming
105  // bEasyFraming = nfc_device_get_property_bool (pnd, NP_EASY_FRAMING, &bEasyFraming);
106  if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true) < 0) {
107  nfc_perror(pnd, "nfc_device_set_property_bool");
108  return false;
109  }
110  // Fire the mifare command
111  int res;
112  if ((res = nfc_initiator_transceive_bytes(pnd, abtCmd, 2 + szParamLen, abtRx, sizeof(abtRx), -1)) < 0) {
113  if (res == NFC_ERFTRANS) {
114  // "Invalid received frame", usual means we are
115  // authenticated on a sector but the requested MIFARE cmd (read, write)
116  // is not permitted by current acces bytes;
117  // So there is nothing to do here.
118  } else {
119  nfc_perror(pnd, "nfc_initiator_transceive_bytes");
120  }
121  // XXX nfc_device_set_property_bool (pnd, NP_EASY_FRAMING, bEasyFraming);
122  return false;
123  }
124  /* XXX
125  if (nfc_device_set_property_bool (pnd, NP_EASY_FRAMING, bEasyFraming) < 0) {
126  nfc_perror (pnd, "nfc_device_set_property_bool");
127  return false;
128  }
129  */
130 
131  // When we have executed a read command, copy the received bytes into the param
132  if (mc == MC_READ) {
133  if (res == 16) {
134  memcpy(pmp->mpd.abtData, abtRx, 16);
135  } else {
136  return false;
137  }
138  }
139  // Command succesfully executed
140  return true;
141 }