MIKAI
Library to modify content of a Mykey
srix.c
Go to the documentation of this file.
1 /*
2  * @author Lilz <https://telegram.me/Lilz73>
3  * @copyright 2020-2021 Lilz <https://telegram.me/Lilz73>
4  * @license MIKAI LICENSE
5  *
6  * This file is part of MIKAI.
7  *
8  * MIKAI is free software: you can redistribute it and/or modify
9  * it under the terms of the MIKAI License, as published by
10  * Lilz along with this program and available on "MIKAI Download" Telegram channel
11  * <https://telegram.me/mikaidownload>.
12  *
13  * MIKAI is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY.
15  *
16  * You should have received a copy of the MIKAI License along
17  * with MIKAI.
18  * If not, see <https://telegram.me/mikaidownload>.
19  */
20 
21 #include <string.h>
22 #include <mikai-error.h>
23 #include "srix.h"
24 #include <reader/reader.h>
25 
29 struct Srix {
30  union {
31  struct {
32  uint32_t otp[5]; /* 0-4 Resettable OTP bits */
33  uint32_t counter[2]; /* 5-6 Count down counter */
34  uint32_t lockable[9]; /* 7-15 Lockable EEPROM */
35  uint32_t generic[112]; /* 16-127 EEPROM */
36  };
37  uint32_t eeprom[SRIX4K_BLOCKS]; /* SRIX4K EEPROM */
38  };
39  uint64_t uid; /* SRIX UID */
40  SrixFlag blockFlags; /* Modified block flags */
41  NfcReader *reader; /* NFC Reader */
42 };
43 
49 static MikaiError getUid(Srix *target) {
50  /* Get UID as byte array */
51  uint8_t uidBytes[SRIX_UID_LENGTH];
52 
53  MikaiError error = NfcGetUid(target->reader, uidBytes);
54  if (MIKAI_IS_ERROR(error)) {
55  return error;
56  }
57 
58  /* Check manufacturer code (datasheet of SRIX4K and ST25TB04K) */
59  if (uidBytes[7] != 0xD0 || uidBytes[6] != 0x02) {
60  return MIKAI_ERROR(MIKAI_NFC_ERROR, "invalid tag manufacturer code");
61  }
62 
63  /* Convert UID to uint64 */
64  target->uid = (uint64_t) uidBytes[7] << 56U | (uint64_t) uidBytes[6] << 48U | (uint64_t) uidBytes[5] << 40U |
65  (uint64_t) uidBytes[4] << 32U | (uint64_t) uidBytes[3] << 24U | (uint64_t) uidBytes[2] << 16U |
66  (uint64_t) uidBytes[1] << 8U | (uint64_t) uidBytes[0];
67 
68  return MIKAI_NO_ERROR;
69 }
70 
76 static MikaiError readBlocks(Srix *target) {
77  if (!target->reader) {
78  return MIKAI_ERROR(MIKAI_SRIX_ERROR, "nfc reader hasn't been initialized");
79  }
80 
81  for (uint8_t i = 0; i < SRIX4K_BLOCKS; i++) {
82  uint8_t readBlock[SRIX_BLOCK_LENGTH];
83 
84  MikaiError error = NfcReadBlock(target->reader, (SrixBlock *) readBlock, i);
85  if (MIKAI_IS_ERROR(error)) {
86  return error;
87  }
88 
89  target->eeprom[i] = readBlock[0] << 24 | readBlock[1] << 16 | readBlock[2] << 8 | readBlock[3];
90  }
91 
92  return MIKAI_NO_ERROR;
93 }
94 
102 static MikaiError srixWriteGroup(Srix *target, uint32_t *groupPointer, uint8_t groupSize) {
103  for (uint64_t i = 0; i < groupSize; i++) {
104  if (srixFlagGet(&target->blockFlags, groupPointer + i - target->eeprom)) {
105  const uint8_t writeBlock[] = {
106  groupPointer[i] >> 24,
107  groupPointer[i] >> 16,
108  groupPointer[i] >> 8,
109  groupPointer[i]
110  };
111 
112  MikaiError error = NfcWriteBlock(target->reader, (SrixBlock *) writeBlock,
113  groupPointer + i - target->eeprom);
114  if (MIKAI_IS_ERROR(error)) {
115  return error;
116  }
117  }
118  }
119 
120  return MIKAI_NO_ERROR;
121 }
122 
124  Srix *created = malloc(sizeof(Srix));
125  if (!created) {
126  return (void *) 0;
127  }
128 
129  created->reader = NfcReaderNew();
130 
131  return created;
132 }
133 
134 void SrixDelete(Srix target[static 1]) {
135  NfcCloseReader(target->reader);
136  free(target->reader);
137  free(target);
138 }
139 
140 size_t NfcGetReadersCount(Srix target[static 1]) {
141  return NfcUpdateReaders(target->reader);
142 }
143 
144 char *NfcGetDescription(Srix *target, int reader) {
145  return NfcGetReaderDescription(target->reader, reader);
146 }
147 
148 MikaiError SrixNfcInit(Srix target[static 1], int reader) {
149  target->blockFlags = SRIX_FLAG_INIT;
150  NfcCloseReader(target->reader);
151  NfcInitReader(target->reader, reader);
152 
153  /* Get SRIX4K UID & EEPROM */
154  MikaiError error = getUid(target);
155  if (MIKAI_IS_ERROR(error)) {
156  NfcCloseReader(target->reader);
157  return error;
158  }
159 
160  error = readBlocks(target);
161  if (MIKAI_IS_ERROR(error)) {
162  NfcCloseReader(target->reader);
163  }
164 
165  return error;
166 }
167 
168 void SrixMemoryInit(Srix target[static 1], uint32_t eeprom[const static SRIX4K_BLOCKS], uint64_t uid) {
169  if (target->lockable[0] != 0) {
170  /* If memory has been already initialized (Key ID not null), copy only generic blocks */
171  memcpy(target->generic, eeprom + 16, SRIX4K_BYTES - 16 * SRIX_BLOCK_LENGTH);
172 
173  /* If already initialized, flag all generic blocks */
174  for (uint8_t i = 16; i < 128; i++) {
175  srixFlagAdd(&target->blockFlags, i);
176  }
177  } else {
178  memcpy(target->eeprom, eeprom, SRIX4K_BLOCKS * SRIX_BLOCK_LENGTH);
179  }
180 
181  target->uid = uid;
182 }
183 
184 uint64_t SrixGetUid(Srix target[static 1]) {
185  return target->uid;
186 }
187 
188 uint32_t *SrixGetBlock(Srix target[static 1], uint8_t blockNum) {
189  return (blockNum < SRIX4K_BLOCKS) ? (target->eeprom + blockNum) : 0;
190 }
191 
192 void SrixModifyBlock(Srix target[static 1], const uint32_t block, const uint8_t blockNum) {
193  target->eeprom[blockNum] = block;
194  srixFlagAdd(&target->blockFlags, blockNum);
195 }
196 
197 MikaiError SrixWriteBlocks(Srix target[static 1]) {
198  if (!target->reader) {
199  return MIKAI_ERROR(MIKAI_SRIX_ERROR, "NFC reader hasn't been initialized");
200  }
201 
202  /* Counter blocks */
203  MikaiError error = srixWriteGroup(target, target->counter, sizeof(target->counter) / sizeof(uint32_t));
204  if (MIKAI_IS_ERROR(error)) {
205  return error;
206  }
207 
208  /* OTP blocks */
209  error = srixWriteGroup(target, target->otp, sizeof(target->otp) / sizeof(uint32_t));
210  if (MIKAI_IS_ERROR(error)) {
211  return error;
212  }
213 
214  /* Lockable blocks */
215  error = srixWriteGroup(target, target->lockable, sizeof(target->lockable) / sizeof(uint32_t));
216  if (MIKAI_IS_ERROR(error)) {
217  return error;
218  }
219 
220  /* Generic blocks */
221  error = srixWriteGroup(target, target->generic, sizeof(target->generic) / sizeof(uint32_t));
222  if (MIKAI_IS_ERROR(error)) {
223  return error;
224  }
225 
226  target->blockFlags = SRIX_FLAG_INIT;
227  return MIKAI_NO_ERROR;
228 }
SrixFlag
Struct that represents the modified blocks in a SRIX tag.
Definition: srix-flag.h:30
NfcGetReadersCount
size_t NfcGetReadersCount(Srix target[static 1])
Definition: srix.c:140
NfcInitReader
MikaiError NfcInitReader(NfcReader reader[static 1], int selection)
Definition: reader.c:141
SRIX4K_BYTES
#define SRIX4K_BYTES
Definition: mikai.h:31
SrixModifyBlock
void SrixModifyBlock(Srix target[static 1], const uint32_t block, const uint8_t blockNum)
Definition: srix.c:192
NfcReaderNew
NfcReader * NfcReaderNew()
Allocate a nfc reader and set its default values.
Definition: reader.c:113
SrixNfcInit
MikaiError SrixNfcInit(Srix target[static 1], int reader)
Definition: srix.c:148
SrixBlock
Single SRIX block.
Definition: reader.h:34
srixFlagAdd
void srixFlagAdd(SrixFlag flag[static 1], uint8_t block)
Definition: srix-flag.c:23
SrixDelete
void SrixDelete(Srix target[static 1])
Definition: srix.c:134
NfcCloseReader
void NfcCloseReader(NfcReader reader[static 1])
Definition: reader.c:128
SrixNew
Srix * SrixNew()
Create a new Srix and set its default values.
Definition: srix.c:123
mikai-error.h
Srix::blockFlags
SrixFlag blockFlags
Definition: srix.c:40
MIKAI_NFC_ERROR
@ MIKAI_NFC_ERROR
Definition: mikai-error.h:32
NfcReadBlock
MikaiError NfcReadBlock(NfcReader reader[static 1], SrixBlock block[static 1], const uint8_t blockNum)
Definition: reader.c:173
Srix::eeprom
uint32_t eeprom[SRIX4K_BLOCKS]
Definition: srix.c:37
MIKAI_NO_ERROR
#define MIKAI_NO_ERROR
Definition: mikai-error.h:45
Srix
Generic SRIX4K tag.
Definition: srix.c:29
SRIX_FLAG_INIT
#define SRIX_FLAG_INIT
Definition: srix-flag.h:34
MikaiError
Error structure that contains a description message.
Definition: mikai-error.h:40
MIKAI_IS_ERROR
#define MIKAI_IS_ERROR(isError)
Definition: mikai-error.h:47
srix.h
NfcReader
Struct that represents a NFC Reader.
Definition: reader.h:41
Srix::reader
NfcReader * reader
Definition: srix.c:41
SrixMemoryInit
void SrixMemoryInit(Srix target[static 1], uint32_t eeprom[const static SRIX4K_BLOCKS], uint64_t uid)
Definition: srix.c:168
NfcUpdateReaders
size_t NfcUpdateReaders(NfcReader reader[static 1])
Definition: reader.c:132
MIKAI_SRIX_ERROR
@ MIKAI_SRIX_ERROR
Definition: mikai-error.h:33
NfcWriteBlock
MikaiError NfcWriteBlock(NfcReader reader[static 1], SrixBlock block[static 1], const uint8_t blockNum)
Definition: reader.c:188
SrixGetBlock
uint32_t * SrixGetBlock(Srix target[static 1], uint8_t blockNum)
Definition: srix.c:188
NfcGetReaderDescription
char * NfcGetReaderDescription(NfcReader reader[static 1], int selection)
Definition: reader.c:137
SRIX_UID_LENGTH
#define SRIX_UID_LENGTH
Definition: mikai.h:29
SRIX4K_BLOCKS
#define SRIX4K_BLOCKS
Definition: mikai.h:30
reader.h
Srix::otp
uint32_t otp[5]
Definition: srix.c:32
srixFlagGet
bool srixFlagGet(SrixFlag flag[static 1], uint8_t block)
Definition: srix-flag.c:39
SRIX_BLOCK_LENGTH
#define SRIX_BLOCK_LENGTH
Definition: mikai.h:28
Srix::lockable
uint32_t lockable[9]
Definition: srix.c:34
MIKAI_ERROR
#define MIKAI_ERROR(type, errorMessage)
Definition: mikai-error.h:46
SrixGetUid
uint64_t SrixGetUid(Srix target[static 1])
Definition: srix.c:184
SrixWriteBlocks
MikaiError SrixWriteBlocks(Srix target[static 1])
Definition: srix.c:197
Srix::uid
uint64_t uid
Definition: srix.c:39
Srix::counter
uint32_t counter[2]
Definition: srix.c:33
NfcGetDescription
char * NfcGetDescription(Srix *target, int reader)
Function that return specified nfc reader description (connection string).
Definition: srix.c:144
NfcGetUid
MikaiError NfcGetUid(NfcReader reader[static 1], uint8_t uid[const static SRIX_UID_LENGTH])
Definition: reader.c:162
Srix::generic
uint32_t generic[112]
Definition: srix.c:35