-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmifare.c
141 lines (126 loc) · 4.93 KB
/
mifare.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*-
* Public platform independent Near Field Communication (NFC) library examples
*
* Copyright (C) 2009 Roel Verdult
* Copyright (C) 2010 Romain Tartière
* Copyright (C) 2010, 2011, 2013 Romuald Conty
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2 )Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Note that this license only applies on the examples, NFC library itself is under LGPL
*
*/
/**
* @file mifare.c
* @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc
*/
/*
* This implementation was written based on information provided by the
* following document:
*
* MIFARE Classic Specification
* MF1ICS50
* Functional specification
* Rev. 5.3 - 29 January 2008
* http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf
*/
#include "mifare.h"
#include <string.h>
#include <nfc/nfc.h>
/**
* @brief Execute a MIFARE Classic command
* @return Returns NFC_SUCCESS if action was successfully performed; otherwise returns error code (negative value).
* @param pmp Some commands need additional information. This information should be supplied in the mifare_param union.
*
* The specified MIFARE command will be executed on the tag. There are
* different commands possible, they all require the destination block number.
*
* @note There are three different types of information (Authenticate, Data and Value).
*
* First an authentication must take place using Key A or B. It requires a 48 bit Key (6 bytes) and the UID.
* After a successful authentication it will be possible to execute other commands (e.g. Read/Write).
*
* Like libnfc's functions, this one returns negative value on error (libnfc's
* error code) but two of them need a special attention in this context (MIFARE
* Classic):
* - NFC_EMFCAUTHFAIL, "MIFARE authentication failed", means key is not valid
* on specified sector.
* - NFC_ERFTRANS, "Invalid received frame", when occurs on MIFARE command
* read or write after a successful authentication, means permissions allowed
* by current acces bytes are not sufficient to process the command.
*/
int
nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param *pmp)
{
uint8_t abtRx[265];
size_t szParamLen;
uint8_t abtCmd[265];
abtCmd[0] = mc; // The MIFARE Classic command
abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
switch (mc) {
// Read and store command have no parameter
case MC_READ:
case MC_STORE:
szParamLen = 0;
break;
// Authenticate command
case MC_AUTH_A:
case MC_AUTH_B:
szParamLen = sizeof(struct mifare_param_auth);
break;
// Data command
case MC_WRITE:
szParamLen = sizeof(struct mifare_param_data);
break;
// Value command
case MC_DECREMENT:
case MC_INCREMENT:
case MC_TRANSFER:
szParamLen = sizeof(struct mifare_param_value);
break;
// Please fix your code, you never should reach this statement
default:
return NFC_EINVARG;
break;
}
// When available, copy the parameter bytes
if (szParamLen)
memcpy(abtCmd + 2, (uint8_t *) pmp, szParamLen);
// FIXME: Save and restore bEasyFraming
int res;
if ((res = nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true)) < 0) {
return res;
}
// Fire the mifare command
if ((res = nfc_initiator_transceive_bytes(pnd, abtCmd, 2 + szParamLen, abtRx, sizeof(abtRx), -1)) < 0) {
return res;
}
// When we have executed a read command, copy the received bytes into the param
if (mc == MC_READ) {
if (res == 16) {
memcpy(pmp->mpd.abtData, abtRx, 16);
} else {
return NFC_EINVARG;
}
}
// Command succesfully executed
return NFC_SUCCESS;
}