libnfc  1.4.2
mifare.c
1 /*-
2  * Public platform independent Near Field Communication (NFC) library examples
3  *
4  * Copyright (C) 2009, Roel Verdult
5  * Copyright (C) 2010, Romuald Conty, Romain Tartière
6  *
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 notice,
10  * 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  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  *
27  * Note that this license only applies on the examples, NFC library itself is under LGPL
28  *
29  */
30 
31 #include "mifare.h"
32 
33 #include <string.h>
34 
35 #include <nfc/nfc.h>
36 
50 bool
51 nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param * pmp)
52 {
53  byte_t abtRx[265];
54  size_t szRx;
55  size_t szParamLen;
56  byte_t abtCmd[265];
57  bool bEasyFraming;
58 
59  // Make sure we are dealing with a active device
60  if (!pnd->bActive)
61  return false;
62 
63  abtCmd[0] = mc; // The MIFARE Classic command
64  abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
65 
66  switch (mc) {
67  // Read and store command have no parameter
68  case MC_READ:
69  case MC_STORE:
70  szParamLen = 0;
71  break;
72 
73  // Authenticate command
74  case MC_AUTH_A:
75  case MC_AUTH_B:
76  szParamLen = sizeof (mifare_param_auth);
77  break;
78 
79  // Data command
80  case MC_WRITE:
81  szParamLen = sizeof (mifare_param_data);
82  break;
83 
84  // Value command
85  case MC_DECREMENT:
86  case MC_INCREMENT:
87  case MC_TRANSFER:
88  szParamLen = sizeof (mifare_param_value);
89  break;
90 
91  // Please fix your code, you never should reach this statement
92  default:
93  return false;
94  break;
95  }
96 
97  // When available, copy the parameter bytes
98  if (szParamLen)
99  memcpy (abtCmd + 2, (byte_t *) pmp, szParamLen);
100 
101  bEasyFraming = pnd->bEasyFraming;
102  if (!nfc_configure (pnd, NDO_EASY_FRAMING, true)) {
103  nfc_perror (pnd, "nfc_configure");
104  return false;
105  }
106  // Fire the mifare command
107  if (!nfc_initiator_transceive_bytes (pnd, abtCmd, 2 + szParamLen, abtRx, &szRx)) {
108  if (pnd->iLastError == EINVRXFRAM) {
109  // "Invalid received frame" AKA EINVRXFRAM, usual means we are
110  // authenticated on a sector but the requested MIFARE cmd (read, write)
111  // is not permitted by current acces bytes;
112  // So there is nothing to do here.
113  } else {
114  nfc_perror (pnd, "nfc_initiator_transceive_bytes");
115  }
116  nfc_configure (pnd, NDO_EASY_FRAMING, bEasyFraming);
117  return false;
118  }
119  if (!nfc_configure (pnd, NDO_EASY_FRAMING, bEasyFraming)) {
120  nfc_perror (pnd, "nfc_configure");
121  return false;
122  }
123 
124  // When we have executed a read command, copy the received bytes into the param
125  if (mc == MC_READ) {
126  if (szRx == 16) {
127  memcpy (pmp->mpd.abtData, abtRx, 16);
128  } else {
129  return false;
130  }
131  }
132  // Command succesfully executed
133  return true;
134 }