Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rastegari-mrr authored Nov 24, 2021
1 parent d33fc52 commit beff5eb
Show file tree
Hide file tree
Showing 6 changed files with 571 additions and 0 deletions.
99 changes: 99 additions & 0 deletions example/Functions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Functions.c
*
* Created on: Nov 20, 2021
* Author: mrras
*/
#include "Functions.h"
#include "SmartCard.h"
#include "main.h"

static void delay();
static void setClockOutput();
static void setIOInput();
static void setIOOutput();
static void setResetOutput();
static bool readIO();
static void writeIO(bool value);
static void writeClock(bool value);
static void writeReset(bool value);
static void oneMiliDelay();

using namespace smartCards;

smartCard sc(delay, setClockOutput, setResetOutput, setIOInput, setIOOutput,
writeClock, writeIO, writeReset, readIO, oneMiliDelay);

void initSmartCard(uint8_t *data) {
uint8_t d;
auto t = sc.initialize(data);
if (t == SmartCard_Results::OK) {
auto r = sc.authenticate(0xFF, 0xFF, 0xFF);
if (r == SmartCardAuth_Results::PSCVerified) {
for (int i = 0; i < 256; ++i) {
t = sc.writeMainMemory(i, i);
}
for (int i = 0; i < 256; ++i) {
t = sc.readMainMemory(i, &d);
}
}
}
}

static void delay() {
asm("nop");
}

static void setClockOutput() {
//TODO: set clock pin as output
}

static void setIOInput() {
GPIO_InitTypeDef GPIO_InitStruct = { 0 };
GPIO_InitStruct.Pin = SMARTCARD_IO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(SMARTCARD_IO_GPIO_Port, &GPIO_InitStruct);
}

static void setIOOutput() {
GPIO_InitTypeDef GPIO_InitStruct = { 0 };
GPIO_InitStruct.Pin = SMARTCARD_IO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(SMARTCARD_IO_GPIO_Port, &GPIO_InitStruct);
}

static void setResetOutput() {
//TODO: set reset pin as output
}

static bool readIO() {
return (SMARTCARD_IO_GPIO_Port->IDR & SMARTCARD_IO_Pin) != 0x00U;
}

static void writeIO(bool value) {
if (value)
SMARTCARD_IO_GPIO_Port->BSRR = SMARTCARD_IO_Pin;
else
SMARTCARD_IO_GPIO_Port->BSRR = (uint32_t) SMARTCARD_IO_Pin << 16;
}

static void writeClock(bool value) {
if (value)
SMARTCARD_CLOCK_GPIO_Port->BSRR = SMARTCARD_CLOCK_Pin;
else
SMARTCARD_CLOCK_GPIO_Port->BSRR = (uint32_t) SMARTCARD_CLOCK_Pin << 16;
}

static void writeReset(bool value) {
if (value)
SMARTCARD_RESET_GPIO_Port->BSRR = SMARTCARD_RESET_Pin;
else
SMARTCARD_RESET_GPIO_Port->BSRR = (uint32_t) SMARTCARD_RESET_Pin << 16;
}

static void oneMiliDelay() {
HAL_Delay(1);
}
23 changes: 23 additions & 0 deletions example/Functions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Functions.h
*
* Created on: Nov 20, 2021
* Author: mrras
*/

#ifndef MYDRIVERS_FUNCTIONS_H_
#define MYDRIVERS_FUNCTIONS_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "stdint.h"

void initSmartCard(uint8_t *data);

#ifdef __cplusplus
}
#endif

#endif /* MYDRIVERS_FUNCTIONS_H_ */
197 changes: 197 additions & 0 deletions source/SLE4442.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
/*
* SLE4442.cpp
*
* Created on: ۲ آذر ۱۴۰۰
* Author: mrras
*/

#include <SLE4442.h>

namespace smartCards {

/**
* @brief SLE4442 class (max clock : 50KHz, minimum pulse width: 9us)
* @param delayFunction : function which make 10us delay
* @retval None
*/
SLE4442::SLE4442() :
m_readRefresh(true) {
}

/**
* @brief Initialize the smart card
* @param data : returns the first four bytes in main memory
* @retval None
*/
bool SLE4442::initialize(uint8_t *data) const {
uint32_t *d = reinterpret_cast<uint32_t*>(data);
uint8_t tmp;
m_setResetOutput();
m_setClockOutput();
m_setIOInput();
m_writeReset(false);
m_writeClock(false);
m_writeReset(true);
m_oneMiliDelay(); // A little extra wait time for this
m_writeClock(true);
m_delay();
m_writeClock(false);
m_delay();
m_oneMiliDelay(); // A little extra wait time for this
m_writeReset(false);
m_delay();
*d = m_readIO();
for (int index = 0; index < 4; index++) {
tmp = read();
*d |= static_cast<uint32_t>(tmp) << (index * 8 + 1);
}
return d[0] != 0xFF;
}

uint8_t SLE4442::read() const {
uint8_t data = 0;
m_setIOInput();
m_writeClock(true);
m_delay();
for (int i = 0; i < 8; i++) {
data = data >> 1;
m_writeClock(false);
m_delay();
m_writeClock(true);
m_delay();
if (m_readIO()) {
data += 0x80;
}
}
return data;
}

void SLE4442::process() const {
m_setIOInput();
m_writeClock(false);
m_delay();
while (m_readIO() == false) {
m_writeClock(true);
m_delay();
m_writeClock(false);
m_delay();
}
}

void SLE4442::sendCommand(uint8_t command, uint8_t address,
uint8_t data) const {
//Output(CLOCK);
m_writeClock(true);
m_delay();
m_setIOOutput();
m_writeIO(false);
write(command);
write(address);
write(data);
m_writeClock(false);
m_delay();
m_writeIO(false);
m_writeClock(true);
m_delay();
m_writeIO(true);

if (command == UpdateMain || command == UpdateProtection
|| command == CompareData || command == UpdateSecurity)
process();
}

void SLE4442::write(uint8_t data) const {
uint8_t command = data;
bool temp = 0;

for (int i = 0; i < 8; i++) {
temp = command & 0x01;
command = command >> 1;
m_writeClock(false);
m_delay();
if (temp != 0)
m_writeIO(true);
else
m_writeIO(false);
m_writeClock(true);
m_delay();
}
}

/**
* @brief Authenticate the smart card(authentication (valid or invalid) is remain until card has power)
* @param None
* @retval The authentication code :
* 0x00 : Card is locked
* 0x01 : Invalid PSC, one try remaining
* 0x03 : Invalid PSC, two tries remaining
* 0x07 : PSC verified, you may now write data to the card (Authentication is OK)
* else : Unable to Authenticate
*/
uint8_t SLE4442::authenticate(uint8_t password1, uint8_t password2,
uint8_t password3) const {
uint8_t data;

uint8_t errCounter = readSecurity();

errCounter = errCounter & 0x07;
data = errCounter >> 1;

sendCommand(UpdateSecurity, 0x00, data);
sendCommand(CompareData, 0x01, password1);
sendCommand(CompareData, 0x02, password2);
sendCommand(CompareData, 0x03, password3);

sendCommand(UpdateSecurity, 0x00, 0x07);

errCounter = readSecurity();

return errCounter;
}

void SLE4442::writeMainMemory(uint8_t location, uint8_t value) {
m_readRefresh = true;
sendCommand(UpdateMain, location, value);
}

uint8_t SLE4442::readMainMemory(uint8_t location) {
if (m_readRefresh) {
m_readRefresh = false;
sendCommand(ReadMain, 0x00, 0x00);
for (int i = 0; i < 256; i++)
m_readBuffer[i] = read();
}
return m_readBuffer[location];
}

void SLE4442::readProtectedMemory(uint8_t *values) {
sendCommand(ReadProtection, 0x00, 0x00);
for (int i = 0; i < 32; i++)
values[i] = read();
}

void SLE4442::writeProtectedMemory(uint8_t location, uint8_t value) {
sendCommand(UpdateProtection, location, value);
}

void SLE4442::writeSecuredMemory(uint8_t location, uint8_t value) {
sendCommand(UpdateSecurity, location, value);
}

uint8_t SLE4442::readSecurity() const {
sendCommand(ReadSecurity, 0x00, 0x00);
uint8_t errCounter = read();

sendCommand(ReadSecurity, 0x01, 0x00);
read();

sendCommand(ReadSecurity, 0x02, 0x00);
read();

sendCommand(ReadSecurity, 0x03, 0x00);
read();

return errCounter;
}

} /* namespace smartCards */
68 changes: 68 additions & 0 deletions source/SLE4442.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* SLE4442.h
*
* Created on: ۲ آذر ۱۴۰۰
* Author: mrras
*/

#ifndef MYDRIVERS_SLE4442_H_
#define MYDRIVERS_SLE4442_H_

#include "stdint.h"

#define DEVICE_ADDRESS 0xA0 // Device Address
#define ACK 0 // ACK
#define NAK 1 // NAK

#define ReadMain 0x30 // Read main memory
#define ReadProtection 0x34 // Read protection bit
#define ReadSecurity 0x31 // Read PSC
#define UpdateMain 0x38 // Update main memory
#define UpdateSecurity 0x39 // Update PSC
#define UpdateProtection 0x3C // Update Protection bits
#define CompareData 0x33 // Compare Verification Data

namespace smartCards {

class SLE4442 {
public:
SLE4442();

protected:
void (*m_delay)();
void (*m_setClockOutput)();
void (*m_setResetOutput)();
void (*m_setIOInput)();
void (*m_setIOOutput)();
void (*m_writeClock)(bool value);
void (*m_writeIO)(bool value);
void (*m_writeReset)(bool value);
bool (*m_readIO)();
void (*m_oneMiliDelay)();


bool initialize(uint8_t *data) const;
uint8_t authenticate(uint8_t password1 = 0xFF, uint8_t password2 = 0xFF,
uint8_t password3 = 0xFF) const;

uint8_t readMainMemory(uint8_t location);
void writeMainMemory(uint8_t location, uint8_t value);

void readProtectedMemory(uint8_t *values);
void writeProtectedMemory(uint8_t location, uint8_t value);

void writeSecuredMemory(uint8_t location, uint8_t value);

private:
bool m_readRefresh;
uint8_t m_readBuffer[256];
uint8_t read() const;
void write(uint8_t data) const;
void process() const;
void sendCommand(uint8_t command, uint8_t address, uint8_t data) const;
uint8_t readSecurity() const;
};

} /* namespace smartCards */

#endif /* MYDRIVERS_SLE4442_H_ */
Loading

0 comments on commit beff5eb

Please sign in to comment.