7#ifndef LOGICALACCESS_SAMISO7816CARDPROVIDER_HPP
8#define LOGICALACCESS_SAMISO7816CARDPROVIDER_HPP
18#include <openssl/rand.h>
25#include <boost/interprocess/shared_memory_object.hpp>
26#include <boost/interprocess/mapped_region.hpp>
27#include <boost/interprocess/sync/named_mutex.hpp>
28#include <boost/thread/thread_time.hpp>
36#define DEFAULT_SAM_CLA 0x80
40#define CMD_SAMISO7816 "SAMISO7816"
43%
template(SAMKeyEntrySETAV1Commands) SAMCommands<KeyEntryAV1Information, SETAV1>;
44%
template(SAMKeyEntrySETAV2Commands) SAMCommands<KeyEntryAV2Information, SETAV2>;
50template <
typename T,
typename S>
103 d_LastSessionIV.resize(16);
110 d_LastSessionIV.resize(16);
130 std::shared_ptr<ISO7816ReaderCardAdapter> getISO7816ReaderCardAdapter()
132 return std::dynamic_pointer_cast<ISO7816ReaderCardAdapter>(
133 this->getReaderCardAdapter());
137 bool =
true)
override
139 return getISO7816ReaderCardAdapter()->sendCommand(cmd);
144 unsigned char cmd[] = {d_cla, 0x60, 0x00, 0x00, 0x00};
151 if (result.size() == 33 && result[31] == 0x90 && result[32] == 0x00)
152 memcpy(&info, &result[0],
sizeof(info));
161 unsigned char p1 = 0x00;
168 datawithlength[0] = (
unsigned char)(data.size() & 0xff0000);
169 datawithlength[1] = (
unsigned char)(data.size() & 0x00ff00);
170 datawithlength[2] = (
unsigned char)(data.size() & 0x0000ff);
172 datawithlength.insert(datawithlength.end(), data.begin(), data.end());
174 unsigned char cmd[] = {
175 d_cla, 0xdd, p1, 0x00, (
unsigned char)(datawithlength.size()), 0x00};
177 cmd_vector.insert(cmd_vector.end() - 1, datawithlength.begin(),
178 datawithlength.end());
182 if (result.size() >= 2 && result[result.size() - 2] != 0x90 &&
183 ((p1 == 0x00 && result[result.size() - 1] != 0x00) ||
184 (p1 == 0xaf && result[result.size() - 1] != 0xaf)))
187 return ByteVector(result.begin(), result.end() - 2);
192 unsigned char p1 = 0x00;
196 unsigned char cmd[] = {d_cla, 0xed, p1, 0x00, (
unsigned char)(data.size()), 0x00};
198 cmd_vector.insert(cmd_vector.end() - 1, data.begin(), data.end());
201 if (result.size() >= 2 && result[result.size() - 2] != 0x90 &&
202 ((p1 == 0x00 && result[result.size() - 1] != 0x00) ||
203 (p1 == 0xaf && result[result.size() - 1] != 0xaf)))
206 return ByteVector(result.begin(), result.end() - 2);
209 void disableKeyEntry(
unsigned char keyno)
override
211 unsigned char cmd[] = {d_cla, 0xd8, keyno, 0x00};
216 if (result.size() >= 2 &&
217 (result[result.size() - 2] != 0x90 || result[result.size() - 1] != 0x00))
219 "disableKeyEntry failed.");
224 unsigned char cmd[] = {d_cla, 0xd5, 0x00, 0x00, 0x00};
229 if (result.size() >= 2 &&
230 (result[result.size() - 2] != 0x90 || result[result.size() - 1] != 0x00))
233 return ByteVector(result.begin(), result.end() - 2);
240 "loadInitVector need a 16 or 8 bytes vector");
243 0x80, 0x71, 0x00, 0x00,
static_cast<unsigned char>(iv.size()),
245 loadInitVector.insert(loadInitVector.end(), iv.begin(), iv.end());
247 transmit(loadInitVector);
250 std::string getSAMTypeFromSAM()
override
252 unsigned char cmd[] = {d_cla, 0x60, 0x00, 0x00, 0x00};
257 if (result.size() > 3)
259 if (result[result.size() - 3] == 0xA1)
261 if (result[result.size() - 3] == 0xA2)
263 if (result[result.size() - 3] == 0xA3)
269 virtual std::shared_ptr<SAMDESfireCrypto> getCrypto()
273 virtual void setCrypto(std::shared_ptr<SAMDESfireCrypto> t)
278 void lockUnlock(std::shared_ptr<DESFireKey> masterKey,
SAMLockUnlock state,
279 unsigned char keyno,
unsigned char unlockkeyno,
280 unsigned char unlockkeyversion)
override
282 unsigned char p1_part1 = state;
289 data_p1[1] = masterKey->getKeyVersion();
294 data_p1.insert(data_p1.end(), maxChainBlocks.begin(), maxChainBlocks.end());
299 data_p1.push_back(unlockkeyno);
300 data_p1.push_back(unlockkeyversion);
303 auto result = this->getISO7816ReaderCardAdapter()->sendAPDUCommand(
304 d_cla, 0x10, p1_part1, 0x00, le, data_p1, 0x00);
305 if (result.getData().size() != 12 || result.getSW1() != 0x90 || result.getSW2() != 0xAF)
309 masterKey->getData() + masterKey->getLength());
315 rnd2.push_back(p1_part1);
316 rnd2.insert(rnd2.end(), data_p1.begin() + 2, data_p1.end());
321 rnd2.push_back(0x00);
325 rnd2.resize(rnd2.size() + 3);
330 truncateMacBuffer(macHost);
333 if (RAND_bytes(&rnd1[0],
static_cast<int>(rnd1.size())) != 1)
336 "Cannot retrieve cryptographically strong bytes");
340 data_p2.insert(data_p2.end(), macHost.begin(), macHost.begin() + 8);
341 data_p2.insert(data_p2.end(), rnd1.begin(), rnd1.end());
343 result = this->getISO7816ReaderCardAdapter()->sendAPDUCommand(
344 d_cla, 0x10, 0x00, 0x00, 0x14, data_p2, 0x00);
345 if (result.getData().size() != 24 || result.getSW1() != 0x90 ||
346 result.getSW2() != 0xAF)
350 rnd1.insert(rnd1.end(), rnd2.begin() + 12, rnd2.end());
353 truncateMacBuffer(macHost);
355 for (
unsigned char x = 0; x < 8; ++x)
357 if (macHost[x] != result.getData()[x])
359 "lockUnlock P2 CMAC from SAM is Wrong.");
363 generateAuthEncKey(keycipher, rnd1, rnd2);
367 if (RAND_bytes(&rndA[0],
static_cast<int>(rndA.size())) != 1)
370 "Cannot retrieve cryptographically strong bytes");
376 std::shared_ptr<openssl::InitializationVector> iv(
380 ByteVector encRndB(result.getData().begin() + 8, result.getData().end());
383 cipher->decipher(encRndB, dencRndB, *symkey.get(), *iv.get(),
false);
387 rndB1.insert(rndB1.begin(), dencRndB.begin() + 2,
388 dencRndB.begin() + dencRndB.size());
389 rndB1.push_back(dencRndB[0]);
390 rndB1.push_back(dencRndB[1]);
393 dataHost.insert(dataHost.end(), rndA.begin(), rndA.end());
394 dataHost.insert(dataHost.end(), rndB1.begin(), rndB1.end());
398 cipher->cipher(dataHost, encHost, *symkey.get(), *iv.get(),
false);
400 result = this->getISO7816ReaderCardAdapter()->sendAPDUCommand(
401 d_cla, 0x10, 0x00, 0x00, 0x20, encHost, 0x00);
402 if (result.getData().size() != 16 || result.getSW1() != 0x90 ||
403 result.getSW2() != 0x00)
409 cipher->decipher(result.getData(), SAMrndA, *symkey.get(), *iv.get(),
false);
410 SAMrndA.insert(SAMrndA.begin(), SAMrndA.end() - 2, SAMrndA.end());
412 if (!equal(SAMrndA.begin(), SAMrndA.begin() + 16, rndA.begin()))
414 "lockUnlock P3 RndA from SAM is invalide.");
417 void selectApplication(
ByteVector aid)
override
419 unsigned char cmd[] = {d_cla, 0x5a, 0x00, 0x00, 0x03};
421 cmd_vector.insert(cmd_vector.end(), aid.begin(), aid.end());
425 if (result.size() >= 2 &&
426 (result[result.size() - 2] != 0x90 || result[result.size() - 1] != 0x00))
428 "selectApplication failed.");
451 keyCompMeth |= diversifycation.
diversifyNew == 0x01 ? 0x02 : 0x00;
453 data.insert(data.end(), diversifycation.
divInput,
457 unsigned char cmd[] = {
458 d_cla, 0xc4, keyCompMeth, cfg, (
unsigned char)(data.size()), 0x00};
460 cmd_vector.insert(cmd_vector.end() - 1, data.begin(), data.end());
464 if (result.size() >= 2 &&
465 (result[result.size() - 2] != 0x90 || result[result.size() - 1] != 0x00))
468 sprintf(tmp,
"changeKeyPICC failed (%x %x).", result[result.size() - 2],
469 result[result.size() - 1]);
473 return ByteVector(result.begin(), result.end() - 2);
477 std::shared_ptr<SAMDESfireCrypto> d_crypto;
491 static void truncateMacBuffer(
ByteVector &data)
493 unsigned char truncateCount = 0;
494 unsigned char count = 1;
496 while (count < data.size())
498 data[truncateCount] = data[count];
508 copy(rnd1.begin() + 7, rnd1.begin() + 12, SV1a.begin());
509 copy(rnd2.begin() + 7, rnd2.begin() + 12, SV1a.begin() + 5);
510 copy(rnd1.begin(), rnd1.begin() + 5, SV1a.begin() + 10);
512 for (
unsigned char x = 0; x <= 4; ++x)
514 SV1a[x + 10] ^= rnd2[x];
522 std::shared_ptr<openssl::InitializationVector> iv(
527 cipher->cipher(SV1a, d_authKey, *symkey.get(), *iv.get(),
false);
AES initialization vector class.
A liblogicalaccess exception class.
Definition: myexception.hpp:22
Definition: samcommands.hpp:61
The SAMISO7816 commands class.
Definition: samiso7816commands.hpp:52
SAMISO7816Commands()
Constructor.
Definition: samiso7816commands.hpp:57
AES cipher class.
Definition: aes_cipher.hpp:24
An AES initialization vector.
Definition: aes_initialization_vector.hpp:28
static AESInitializationVector createFromData(const ByteVector &data)
Create an IV from data.
Definition: aes_initialization_vector.cpp:25
An AES symmetric key.
Definition: aes_symmetric_key.hpp:30
static AESSymmetricKey createFromData(const ByteVector &data)
Create a symmetric key from the specified data.
Definition: aes_symmetric_key.cpp:20
static ByteVector cmac(const ByteVector &key, std::string crypto, const ByteVector &data, const ByteVector &iv={}, int padding_size=0)
Definition: cmac.cpp:21
Default ISO7816 reader/card adapter.
std::vector< uint8_t > ByteVector
Definition: lla_fwd.hpp:80
#define THROW_EXCEPTION_WITH_LOG(type, msg,...)
Definition: logs.hpp:237
#define EXCEPTION_ASSERT_WITH_LOG(condition, type, msg,...)
Definition: logs.hpp:246
SAMLockUnlock
Definition: samcommands.hpp:49
@ SwitchAV2Mode
Definition: samcommands.hpp:53
@ LockWithSpecifyingKey
Definition: samcommands.hpp:52
@ NO_DIV
Definition: sambasickeyentry.hpp:58
@ SAMAV2
Definition: sambasickeyentry.hpp:58
#define DEFAULT_SAM_CLA
Definition: samav1iso7816commands.hpp:25
#define CMD_SAMISO7816
Definition: samiso7816commands.hpp:40
Definition: samcommands.hpp:42
Definition: sambasickeyentry.hpp:61
unsigned char * divInput
Definition: sambasickeyentry.hpp:63
NXPKeyDiversificationType divType
Definition: sambasickeyentry.hpp:62
unsigned char diversifyNew
Definition: sambasickeyentry.hpp:66
unsigned char diversifyCurrent
Definition: sambasickeyentry.hpp:65
unsigned char divInputSize
Definition: sambasickeyentry.hpp:64
Definition: sambasickeyentry.hpp:48
unsigned char newKeySlotV
Definition: sambasickeyentry.hpp:55
unsigned char oldKeyInvolvement
Definition: sambasickeyentry.hpp:51
unsigned char newKeySlotNo
Definition: sambasickeyentry.hpp:54
unsigned char desfireNumber
Definition: sambasickeyentry.hpp:49
unsigned char currentKeySlotV
Definition: sambasickeyentry.hpp:53
unsigned char currentKeySlotNo
Definition: sambasickeyentry.hpp:52
unsigned char isMasterKey
Definition: sambasickeyentry.hpp:50
Symmetric key base class.