Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pcsc support to libnfc #79

Merged
merged 1 commit into from
Jul 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Taskfile.dist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ env:
GO111MODULE: on
GOPROXY: https://goproxy.io,direct
CGO_ENABLED: 1
CGO_LDFLAGS: -lnfc -lusb -lcurses
CGO_LDFLAGS: -lpcsclite -lnfc -lusb -lcurses

dotenv: [".env"]

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/stretchr/testify v1.9.0 // indirect
go.bug.st/serial v1.6.2 // indirect
golang.org/x/term v0.22.0 // indirect
)

Expand All @@ -42,6 +41,7 @@ require (
github.com/hsanjuan/go-ndef v0.0.1
github.com/rs/zerolog v1.31.0
github.com/wizzomafizzo/mrext v0.0.0-20240705120538-5efdc40f9c08
go.bug.st/serial v1.6.2
go.etcd.io/bbolt v1.3.9
golang.org/x/sync v0.7.0
)
34 changes: 29 additions & 5 deletions scripts/linux_arm64/build/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,39 @@ RUN apt-get install -y ca-certificates openssl && \
# install go and app dependencies
RUN apt-get install build-essential git curl wget ncurses-dev -y && \
apt-get install golang-doc golang-go golang-src golang -y
RUN mkdir /internal

# install pcsc-lite and ccid dependencies
RUN apt-get install -y flex libusb-1.0-0-dev zlib1g-dev
# install custom version of pcsc-lite
RUN cd /internal && \
wget https://pcsclite.apdu.fr/files/pcsc-lite-2.0.0.tar.bz2 && \
tar xf pcsc-lite-2.0.0.tar.bz2 && \
cd pcsc-lite-2.0.0 && \
./configure --disable-libsystemd --disable-libudev -enable-static && \
make -j "$(nproc)" && \
make install
# install custom version of ccid
RUN cd /internal && \
wget https://ccid.apdu.fr/files/ccid-1.5.4.tar.bz2 && \
tar xf ccid-1.5.4.tar.bz2 && \
cd ccid-1.5.4 && \
./configure -enable-static && \
make -j "$(nproc)" && \
make install

# install libnfc dependencies
RUN apt-get install -y libusb-dev libtool autoconf automake
# install custom version of libnfc
RUN mkdir /internal && cd /internal && \
git clone --depth 1 https://github.com/sam1902/libnfc && \
cd libnfc && \
RUN cd /internal && \
git clone --depth 1 https://github.com/nfc-tools/libnfc.git
# apply patches
COPY patches/pcsc-initiator_poll_target.patch /internal/libnfc/pcsc-initiator_poll_target.patch
RUN cd /internal/libnfc && \
patch -p1 < pcsc-initiator_poll_target.patch
# build and install libnfc
RUN cd /internal/libnfc && \
autoreconf -vis && \
./configure && \
./configure --with-drivers=all && \
make -j "$(nproc)" && \
make install

Expand Down
90 changes: 90 additions & 0 deletions scripts/linux_arm64/build/patches/pcsc-initiator_poll_target.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
From 1e5cd05357b11381f5505f345afa4892804986f7 Mon Sep 17 00:00:00 2001
From: Roberto Jung Drebes <[email protected]>
Date: Wed, 29 May 2024 15:54:42 -0400
Subject: [PATCH] initiator_poll_target for PCSC

---
libnfc/drivers/pcsc.c | 42 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 38 insertions(+), 4 deletions(-)

diff --git a/libnfc/drivers/pcsc.c b/libnfc/drivers/pcsc.c
index 106d99ac..0bae4ed8 100644
--- a/libnfc/drivers/pcsc.c
+++ b/libnfc/drivers/pcsc.c
@@ -176,7 +176,8 @@ static int pcsc_get_status(struct nfc_device *pnd, int *target_present, uint8_t

data->last_error = SCardStatus(data->hCard, NULL, &reader_len, &state, &protocol, atr, &dw_atr_len);
if (data->last_error != SCARD_S_SUCCESS
- && data->last_error != SCARD_W_RESET_CARD) {
+ && data->last_error != SCARD_W_RESET_CARD
+ && data->last_error != SCARD_W_REMOVED_CARD) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Get status failed");
return NFC_EIO;
}
@@ -193,7 +194,8 @@ static int pcsc_reconnect(struct nfc_device *pnd, DWORD share_mode, DWORD protoc

data->last_error = SCardReconnect(data->hCard, share_mode, protocol, disposition, &data->ioCard.dwProtocol);
if (data->last_error != SCARD_S_SUCCESS
- && data->last_error != SCARD_W_RESET_CARD) {
+ && data->last_error != SCARD_W_RESET_CARD
+ && data->last_error != SCARD_E_NO_SMARTCARD) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reconnect failed");
return NFC_EIO;
}
@@ -882,6 +884,38 @@ static int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t
return resp_len;
}

+static int
+pcsc_initiator_poll_target(struct nfc_device *pnd,
+ const nfc_modulation *pnmModulations, const size_t szModulations,
+ const uint8_t uiPollNr, const uint8_t uiPeriod,
+ nfc_target *pnt)
+{
+ static int periodFactor = 150000;
+ int period = uiPeriod * periodFactor;
+
+ if (pnd == NULL)
+ return 0;
+
+ for (int j = 0; j < uiPollNr; j++)
+ {
+ for (unsigned int i = 0; i < szModulations; i++)
+ {
+ const nfc_modulation nm = pnmModulations[i];
+
+ nfc_target nt;
+ int res = pcsc_initiator_select_passive_target(pnd, nm, 0, 0, &nt);
+ if (res > 0 && pnt)
+ {
+ memcpy(pnt, &nt, sizeof(nfc_target));
+ return res;
+ }
+ }
+ usleep(period);
+ }
+
+ return 0;
+}
+
static int pcsc_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt)
{
uint8_t atr[MAX_ATR_SIZE];
@@ -938,7 +972,7 @@ static int pcsc_device_set_property_bool(struct nfc_device *pnd, const nfc_prope
case NP_ACTIVATE_FIELD:
if (bEnable == false) {
struct pcsc_data *data = pnd->driver_data;
- pcsc_reconnect(pnd, data->dwShareMode, data->ioCard.dwProtocol, SCARD_RESET_CARD);
+ pcsc_reconnect(pnd, data->dwShareMode, data->ioCard.dwProtocol, SCARD_LEAVE_CARD);
}
return NFC_SUCCESS;
default:
@@ -1053,7 +1087,7 @@ const struct nfc_driver pcsc_driver = {
.initiator_init = pcsc_initiator_init,
.initiator_init_secure_element = NULL, // No secure-element support
.initiator_select_passive_target = pcsc_initiator_select_passive_target,
- .initiator_poll_target = NULL,
+ .initiator_poll_target = pcsc_initiator_poll_target,
.initiator_select_dep_target = NULL,
.initiator_deselect_target = NULL,
.initiator_transceive_bytes = pcsc_initiator_transceive_bytes,
34 changes: 29 additions & 5 deletions scripts/mister/build/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,39 @@ RUN apt-get install -y ca-certificates openssl && \
# install go and app dependencies
RUN apt-get install build-essential git curl wget ncurses-dev -y && \
apt-get install golang-doc/bullseye-backports golang-go/bullseye-backports golang-src/bullseye-backports golang/bullseye-backports -y
RUN mkdir /internal

# install pcsc-lite and ccid dependencies
RUN apt-get install -y flex libusb-1.0-0-dev zlib1g-dev
# install custom version of pcsc-lite
RUN cd /internal && \
wget https://pcsclite.apdu.fr/files/pcsc-lite-2.0.0.tar.bz2 && \
tar xf pcsc-lite-2.0.0.tar.bz2 && \
cd pcsc-lite-2.0.0 && \
./configure --disable-libsystemd --disable-libudev -enable-static && \
make -j "$(nproc)" && \
make install
# install custom version of ccid
RUN cd /internal && \
wget https://ccid.apdu.fr/files/ccid-1.5.4.tar.bz2 && \
tar xf ccid-1.5.4.tar.bz2 && \
cd ccid-1.5.4 && \
./configure -enable-static && \
make -j "$(nproc)" && \
make install

# install libnfc dependencies
RUN apt-get install -y libusb-dev libtool autoconf automake
# install custom version of libnfc
RUN mkdir /internal && cd /internal && \
git clone --depth 1 https://github.com/sam1902/libnfc && \
cd libnfc && \
RUN cd /internal && \
git clone --depth 1 https://github.com/nfc-tools/libnfc.git
# apply patches
COPY patches/pcsc-initiator_poll_target.patch /internal/libnfc/pcsc-initiator_poll_target.patch
RUN cd /internal/libnfc && \
patch -p1 < pcsc-initiator_poll_target.patch
# build and install libnfc
RUN cd /internal/libnfc && \
autoreconf -vis && \
./configure && \
./configure --with-drivers=all && \
make -j "$(nproc)" && \
make install

Expand Down
7 changes: 6 additions & 1 deletion scripts/mister/build/build.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#!/bin/bash

GO111MODULE=on GOPROXY=https://goproxy.io,direct CGO_ENABLED=1 CGO_LDFLAGS="-lnfc -lusb -lcurses" go build \
export GO111MODULE=on
export GOPROXY=https://goproxy.io,direct
export CGO_ENABLED=1
export CGO_LDFLAGS="-lpcsclite -lnfc -lusb -lcurses"

go build \
--ldflags "-linkmode external -extldflags -static -s -w" \
-o _build/mister_arm/tapto.sh ./cmd/mister
67 changes: 0 additions & 67 deletions scripts/mister/build/patches/acr122u-fix.patch

This file was deleted.

90 changes: 90 additions & 0 deletions scripts/mister/build/patches/pcsc-initiator_poll_target.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
From 1e5cd05357b11381f5505f345afa4892804986f7 Mon Sep 17 00:00:00 2001
From: Roberto Jung Drebes <[email protected]>
Date: Wed, 29 May 2024 15:54:42 -0400
Subject: [PATCH] initiator_poll_target for PCSC

---
libnfc/drivers/pcsc.c | 42 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 38 insertions(+), 4 deletions(-)

diff --git a/libnfc/drivers/pcsc.c b/libnfc/drivers/pcsc.c
index 106d99ac..0bae4ed8 100644
--- a/libnfc/drivers/pcsc.c
+++ b/libnfc/drivers/pcsc.c
@@ -176,7 +176,8 @@ static int pcsc_get_status(struct nfc_device *pnd, int *target_present, uint8_t

data->last_error = SCardStatus(data->hCard, NULL, &reader_len, &state, &protocol, atr, &dw_atr_len);
if (data->last_error != SCARD_S_SUCCESS
- && data->last_error != SCARD_W_RESET_CARD) {
+ && data->last_error != SCARD_W_RESET_CARD
+ && data->last_error != SCARD_W_REMOVED_CARD) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Get status failed");
return NFC_EIO;
}
@@ -193,7 +194,8 @@ static int pcsc_reconnect(struct nfc_device *pnd, DWORD share_mode, DWORD protoc

data->last_error = SCardReconnect(data->hCard, share_mode, protocol, disposition, &data->ioCard.dwProtocol);
if (data->last_error != SCARD_S_SUCCESS
- && data->last_error != SCARD_W_RESET_CARD) {
+ && data->last_error != SCARD_W_RESET_CARD
+ && data->last_error != SCARD_E_NO_SMARTCARD) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Reconnect failed");
return NFC_EIO;
}
@@ -882,6 +884,38 @@ static int pcsc_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t
return resp_len;
}

+static int
+pcsc_initiator_poll_target(struct nfc_device *pnd,
+ const nfc_modulation *pnmModulations, const size_t szModulations,
+ const uint8_t uiPollNr, const uint8_t uiPeriod,
+ nfc_target *pnt)
+{
+ static int periodFactor = 150000;
+ int period = uiPeriod * periodFactor;
+
+ if (pnd == NULL)
+ return 0;
+
+ for (int j = 0; j < uiPollNr; j++)
+ {
+ for (unsigned int i = 0; i < szModulations; i++)
+ {
+ const nfc_modulation nm = pnmModulations[i];
+
+ nfc_target nt;
+ int res = pcsc_initiator_select_passive_target(pnd, nm, 0, 0, &nt);
+ if (res > 0 && pnt)
+ {
+ memcpy(pnt, &nt, sizeof(nfc_target));
+ return res;
+ }
+ }
+ usleep(period);
+ }
+
+ return 0;
+}
+
static int pcsc_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt)
{
uint8_t atr[MAX_ATR_SIZE];
@@ -938,7 +972,7 @@ static int pcsc_device_set_property_bool(struct nfc_device *pnd, const nfc_prope
case NP_ACTIVATE_FIELD:
if (bEnable == false) {
struct pcsc_data *data = pnd->driver_data;
- pcsc_reconnect(pnd, data->dwShareMode, data->ioCard.dwProtocol, SCARD_RESET_CARD);
+ pcsc_reconnect(pnd, data->dwShareMode, data->ioCard.dwProtocol, SCARD_LEAVE_CARD);
}
return NFC_SUCCESS;
default:
@@ -1053,7 +1087,7 @@ const struct nfc_driver pcsc_driver = {
.initiator_init = pcsc_initiator_init,
.initiator_init_secure_element = NULL, // No secure-element support
.initiator_select_passive_target = pcsc_initiator_select_passive_target,
- .initiator_poll_target = NULL,
+ .initiator_poll_target = pcsc_initiator_poll_target,
.initiator_select_dep_target = NULL,
.initiator_deselect_target = NULL,
.initiator_transceive_bytes = pcsc_initiator_transceive_bytes,
Loading