diff --git a/.gitmodules b/.gitmodules
index 369f288f1a7..b10fda5f0a6 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -129,3 +129,6 @@
[submodule "vendor/nim-unicodedb"]
path = vendor/nim-unicodedb
url = https://github.com/nitely/nim-unicodedb
+[submodule "vendor/status-keycard-qt"]
+ path = vendor/status-keycard-qt
+ url = https://github.com/status-im/status-keycard-qt
diff --git a/BUILDING.md b/BUILDING.md
index b73621e4ed9..5ccc7166129 100644
--- a/BUILDING.md
+++ b/BUILDING.md
@@ -294,6 +294,26 @@ make run
```
🎉
+### Build Configuration Options
+
+The following environment variables can be used to customize the build:
+
+- INCLUDE_DEBUG_SYMBOLS (0,1) - Configure nim to include the debug symbols for desktop platforms.
+- KDF_ITERATIONS (number) - Configure the KDF_ITERATIONS to use for the DB encryption
+- KEYCARD_QT_SOURCE_DIR (path) - Point the build system to a local keycard-qt folder. Defaults to a new clone of the latest master in the `status-keycard-qt` build folder.
+- MONITORING (true,false) - Enable/disable qml monitoring tools. The monitoring tools provide a suite of qml introspection tools to debug data transformations. Defaults to `false`
+- NIM_SDS_SOURCE_DIR (path) - Point the build system to a local nim-sds folder. Defaults to `$(GIT_ROOT)/../nim-sds`
+- PRODUCTION_PARAMETERS (string) - Configure the production arguments for nim compilation. Defaults to `-d:production`
+- QMAKE (path to executable) - Point the build system to a different qt installation. Defaults to env configuration
+- QML_DEBUG (true,false) - Enable qml debugger and profiler. Needs DOtherSide recompilation. Defaults to `false`
+- QML_DEBUG_PORT (number) - Configure the qml debugger port. Defaults to `49152`
+- QT_ARCH (string) - Configure the Qt architecture for macOS cross-compilation. Can be used to compile Intel builds on ARM64 OS. Defaults to `$(shell uname -m)`
+- REBUILD_NIM (true,false) - Force nim recompilation
+- REBUILD_UI (true,false) - Force qrc recompilation
+- STATUS_KEYCARD_QT_SOURCE_DIR (path) - Point the build system to a local status-keycard-qt folder. Defaults to `vendor/status-keycard-qt`
+- USE_STATUS_KEYCARD_QT (0,1) - Toggle to switch between `status-keycard-go` and `status-keycard-qt`. Defaults to `0`
+- VCINSTALLDIR (path) - Visual Studio compiler installation path. Defaults to `C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\VC\\`
+
## 🐞 Troubleshooting
diff --git a/Makefile b/Makefile
index 3aa9a292566..91c47008eeb 100644
--- a/Makefile
+++ b/Makefile
@@ -40,6 +40,7 @@ GIT_ROOT ?= $(shell git rev-parse --show-toplevel 2>/dev/null || echo .)
tests-nim-linux \
status-go \
status-keycard-go \
+ status-keycard-qt \
statusq-sanity-checker \
run-statusq-sanity-checker \
statusq-tests \
@@ -248,6 +249,9 @@ NIMSDS_LIBDIR := $(NIM_SDS_SOURCE_DIR)/build
NIMSDS_LIBFILE := $(NIMSDS_LIBDIR)/libsds.$(LIB_EXT)
NIM_EXTRA_PARAMS += --passL:"-L$(NIMSDS_LIBDIR)" --passL:"-lsds"
STATUSGO_MAKE_PARAMS += NIM_SDS_SOURCE_DIR="$(NIM_SDS_SOURCE_DIR)"
+# Keycard library selection: set to 1 to use status-keycard-qt (Qt/C++), 0 for status-keycard-go (Go)
+# Default: use status-keycard-go for now (stable), switch to 1 to test status-keycard-qt
+USE_STATUS_KEYCARD_QT ?= 0
INCLUDE_DEBUG_SYMBOLS ?= false
ifeq ($(INCLUDE_DEBUG_SYMBOLS),true)
@@ -501,6 +505,59 @@ $(STATUSKEYCARDGO): | deps
$(if $(filter 1 true,$(USE_MOCKED_KEYCARD_LIB)), build-mocked-lib, build-lib) \
$(STATUSKEYCARDGO_MAKE_PARAMS) $(HANDLE_OUTPUT)
+##
+## status-keycard-qt (Qt/C++ based keycard library)
+##
+
+# Allow using local status-keycard-qt for development
+STATUS_KEYCARD_QT_SOURCE_DIR ?= vendor/status-keycard-qt
+KEYCARD_QT_SOURCE_DIR ?= ""
+
+# Determine build directory based on platform
+ifeq ($(mkspecs),macx)
+STATUS_KEYCARD_QT_BUILD_DIR := $(STATUS_KEYCARD_QT_SOURCE_DIR)/build/macos
+else ifeq ($(mkspecs),win32)
+STATUS_KEYCARD_QT_BUILD_DIR := $(STATUS_KEYCARD_QT_SOURCE_DIR)/build/windows
+else
+STATUS_KEYCARD_QT_BUILD_DIR := $(STATUS_KEYCARD_QT_SOURCE_DIR)/build/linux
+endif
+
+export STATUSKEYCARD_QT_LIB := $(STATUS_KEYCARD_QT_BUILD_DIR)/libstatus-keycard-qt.$(LIB_EXT)
+export STATUSKEYCARD_QT_LIBDIR := $(STATUS_KEYCARD_QT_BUILD_DIR)
+
+status-keycard-qt: $(STATUSKEYCARD_QT_LIB)
+$(STATUSKEYCARD_QT_LIB): | deps check-qt-dir
+ echo -e $(BUILD_MSG) "status-keycard-qt"
+ cmake -S "${STATUS_KEYCARD_QT_SOURCE_DIR}" -B "${STATUS_KEYCARD_QT_BUILD_DIR}" \
+ $(COMMON_CMAKE_CONFIG_PARAMS) \
+ -DBUILD_TESTING=OFF \
+ -DBUILD_EXAMPLES=OFF \
+ -DBUILD_SHARED_LIBS=ON \
+ -DKEYCARD_QT_SOURCE_DIR=${KEYCARD_QT_SOURCE_DIR} \
+ $(HANDLE_OUTPUT)
+ cmake --build $(STATUS_KEYCARD_QT_BUILD_DIR) --target status-keycard-qt $(HANDLE_OUTPUT)
+
+status-keycard-qt-clean:
+ echo -e "\033[92mCleaning:\033[39m status-keycard-qt"
+ rm -rf $(STATUS_KEYCARD_QT_BUILD_DIR)
+
+##
+## Keycard library selection
+##
+
+# Set the keycard library and paths based on USE_STATUS_KEYCARD_QT
+ifeq ($(USE_STATUS_KEYCARD_QT),1)
+ KEYCARD_LIB := $(STATUSKEYCARD_QT_LIB)
+ KEYCARD_LIBDIR := $(STATUSKEYCARD_QT_LIBDIR)
+ KEYCARD_LINKNAME := status-keycard-qt
+ KEYCARD_DYLIB_NAME := libstatus-keycard-qt.dylib
+else
+ KEYCARD_LIB := $(STATUSKEYCARDGO)
+ KEYCARD_LIBDIR := $(STATUSKEYCARDGO_LIBDIR)
+ KEYCARD_LINKNAME := keycard
+ KEYCARD_DYLIB_NAME := libkeycard.$(LIB_EXT)
+endif
+
QRCODEGEN := vendor/QR-Code-generator/c/libqrcodegen.a
$(QRCODEGEN): | deps
@@ -611,7 +668,7 @@ $(NIM_STATUS_CLIENT): update-qmake-previous
endif
$(NIM_STATUS_CLIENT): NIM_PARAMS += $(RESOURCES_LAYOUT)
-$(NIM_STATUS_CLIENT): $(NIM_SOURCES) | statusq dotherside check-qt-dir $(STATUSGO) $(STATUSKEYCARDGO) $(QRCODEGEN) rcc deps
+$(NIM_STATUS_CLIENT): $(NIM_SOURCES) | statusq dotherside check-qt-dir $(STATUSGO) $(KEYCARD_LIB) $(QRCODEGEN) rcc deps
echo -e $(BUILD_MSG) "$@"
$(ENV_SCRIPT) nim c $(NIM_PARAMS) \
--mm:refc \
@@ -619,8 +676,8 @@ $(NIM_STATUS_CLIENT): $(NIM_SOURCES) | statusq dotherside check-qt-dir $(STATUSG
--passL:"-lstatus" \
--passL:"-L$(STATUSQ_INSTALL_PATH)/StatusQ" \
--passL:"-lStatusQ" \
- --passL:"-L$(STATUSKEYCARDGO_LIBDIR)" \
- --passL:"-lkeycard" \
+ --passL:"-L$(KEYCARD_LIBDIR)" \
+ --passL:"-l$(KEYCARD_LINKNAME)" \
--passL:"$(QRCODEGEN)" \
--passL:"-lm" \
--parallelBuild:0 \
@@ -631,8 +688,8 @@ ifeq ($(mkspecs),macx)
@rpath/libstatus.dylib \
bin/nim_status_client
install_name_tool -change \
- libkeycard.dylib \
- @rpath/libkeycard.dylib \
+ $(KEYCARD_DYLIB_NAME) \
+ @rpath/$(KEYCARD_DYLIB_NAME) \
bin/nim_status_client
endif
@@ -850,7 +907,7 @@ zip-windows: check-pkg-target-windows $(STATUS_CLIENT_7Z)
clean-destdir:
rm -rf bin/*
-clean: | clean-common clean-destdir statusq-clean status-go-clean dotherside-clean storybook-clean clean-translations
+clean: | clean-common clean-destdir statusq-clean status-go-clean status-keycard-qt-clean dotherside-clean storybook-clean clean-translations
rm -rf bottles/* pkg/* tmp/* $(STATUSKEYCARDGO)
+ $(MAKE) -C vendor/QR-Code-generator/c/ --no-print-directory clean
@@ -868,12 +925,12 @@ run: $(RUN_TARGET)
run-linux: nim_status_client
echo -e "\033[92mRunning:\033[39m bin/nim_status_client"
- LD_LIBRARY_PATH="$(QT_LIBDIR)":"$(LIBWAKU_LIBDIR)":"$(NIMSDS_LIBDIR)":"$(STATUSGO_LIBDIR)":"$(STATUSKEYCARDGO_LIBDIR)":"$(STATUSQ_INSTALL_PATH)/StatusQ":"$(LD_LIBRARY_PATH)" \
+ LD_LIBRARY_PATH="$(QT_LIBDIR)":"$(LIBWAKU_LIBDIR)":"$(NIMSDS_LIBDIR)":"$(STATUSGO_LIBDIR)":"$(KEYCARD_LIBDIR)":"$(STATUSQ_INSTALL_PATH)/StatusQ":"$(LD_LIBRARY_PATH)" \
./bin/nim_status_client $(ARGS)
run-linux-gdb: nim_status_client
echo -e "\033[92mRunning:\033[39m bin/nim_status_client"
- LD_LIBRARY_PATH="$(QT_LIBDIR)":"$(LIBWAKU_LIBDIR)":"$(NIMSDS_LIBDIR)":"$(STATUSGO_LIBDIR)":"$(STATUSKEYCARDGO_LIBDIR)":"$(STATUSQ_INSTALL_PATH)/StatusQ":"$(LD_LIBRARY_PATH)" \
+ LD_LIBRARY_PATH="$(QT_LIBDIR)":"$(LIBWAKU_LIBDIR)":"$(NIMSDS_LIBDIR)":"$(STATUSGO_LIBDIR)":"$(KEYCARD_LIBDIR)":"$(STATUSQ_INSTALL_PATH)/StatusQ":"$(LD_LIBRARY_PATH)" \
gdb -ex=r ./bin/nim_status_client $(ARGS)
run-macos: nim_status_client
@@ -884,12 +941,13 @@ run-macos: nim_status_client
ln -fs ../../../nim_status_client ./
fileicon set bin/nim_status_client status-dev.icns
echo -e "\033[92mRunning:\033[39m bin/StatusDev.app/Contents/MacOS/nim_status_client"
+ DYLD_LIBRARY_PATH="$(STATUSGO_LIBDIR)":"$(KEYCARD_LIBDIR)":"$(STATUSQ_INSTALL_PATH)/StatusQ":"$(DYLD_LIBRARY_PATH)" \
./bin/StatusDev.app/Contents/MacOS/nim_status_client $(ARGS)
run-windows: STATUS_RC_FILE = status-dev.rc
run-windows: compile_windows_resources nim_status_client
echo -e "\033[92mRunning:\033[39m bin/nim_status_client.exe"
- PATH="$(DOTHERSIDE_LIBDIR)":"$(STATUSGO_LIBDIR)":"$(STATUSKEYCARDGO_LIBDIR)":"$(STATUSQ_INSTALL_PATH)/StatusQ":"$(PATH)" \
+ PATH="$(DOTHERSIDE_LIBDIR)":"$(STATUSGO_LIBDIR)":"$(KEYCARD_LIBDIR)":"$(STATUSQ_INSTALL_PATH)/StatusQ":"$(PATH)" \
./bin/nim_status_client.exe $(ARGS)
NIM_TEST_FILES := $(wildcard test/nim/*.nim)
@@ -908,11 +966,16 @@ endef
export PATH := $(call qmkq,QT_INSTALL_BINS):$(call qmkq,QT_HOST_BINS):$(call qmkq,QT_HOST_LIBEXECS):$(PATH)
export QTDIR := $(call qmkq,QT_INSTALL_PREFIX)
+#Force keycard support for mobile builds
+ifeq ($(USE_STATUS_KEYCARD_QT),1)
+ MOBILE_FLAGS += "FLAG_KEYCARD_ENABLED=1"
+endif
+
mobile-run: deps-common
echo -e "\033[92mRunning:\033[39m mobile app"
- $(MAKE) -C mobile run
+ $(MAKE) -C mobile run DEBUG=1 $(MOBILE_FLAGS)
-mobile-build: USE_SYSTEM_NIM=1
+mobile-build: USE_SYSTEM_NIM=1 $(MOBILE_FLAGS)
mobile-build: | deps-common
echo -e "\033[92mBuilding:\033[39m mobile app ($(or $(PACKAGE_TYPE),default))"
ifeq ($(PACKAGE_TYPE),aab)
diff --git a/mobile/DEV_SETUP.md b/mobile/DEV_SETUP.md
index f4883603abd..f48e2026ab4 100644
--- a/mobile/DEV_SETUP.md
+++ b/mobile/DEV_SETUP.md
@@ -32,6 +32,22 @@ export QTDIR=$HOME/qt/6.9.2/ios
make mobile-run
```
+Running the app requires a code sign identity. See [Signing](#signing)
+
+#### Keycard
+
+The keycard support is disabled by default in the mobile makefile for IOS. It requires a paid apple developer account to run the app with NFC enabled.
+
+To enable keycard use the `USE_STATUS_KEYCARD_QT=1` flag for the main Makefile and use a paid account by updating the `DEVELOPMENT_TEAM` flag and the bundle if (if the development team isn't Status).
+
+#### Signing
+
+By default the app isn't signed.
+
+To sign the app the `DEVELOPMENT_TEAM` flag needs to be provided. If the development team is not Status development team, then the app bundle id needs to be updated to a unique bundle id.
+
+####
+
### Android Development Setup
#### Prerequisites - can be installed using the Android Studio
diff --git a/mobile/Makefile b/mobile/Makefile
index 99a8272f90d..4d164350dd0 100644
--- a/mobile/Makefile
+++ b/mobile/Makefile
@@ -3,6 +3,18 @@
STATUS_GO_LIB := $(LIB_PATH)/libstatus$(LIB_EXT)
+# FLAG_KEYCARD_ENABLED: Controls NFC/Keycard support
+# - iOS: Default 0 (disabled) - Build without NFC, works with free Apple Developer account
+# - Android: Default 1 (enabled) - NFC support doesn't require paid account on Android
+# - Set to 1: Build with NFC support (iOS requires paid Apple Developer account)
+# - Set to 0: Build without NFC support
+# Usage: make build-ios FLAG_KEYCARD_ENABLED=1
+ifeq ($(OS),android)
+ FLAG_KEYCARD_ENABLED ?= 1
+else
+ FLAG_KEYCARD_ENABLED ?= 0
+endif
+
$(info Configuring build system for $(OS) $(ARCH) with QT $(QT_MAJOR))
# default rule
@@ -16,6 +28,7 @@ statusq: clean-statusq $(STATUS_Q_LIB)
dotherside: clean-dotherside $(DOTHERSIDE_LIB)
openssl: clean-openssl $(OPENSSL_LIB)
qrcodegen: clean-qrcodegen $(QRCODEGEN_LIB)
+status-keycard-qt: clean-status-keycard-qt $(STATUS_KEYCARD_QT_LIB)
nim-status-client: clean-nim-status-client $(NIM_STATUS_CLIENT_LIB)
status-desktop-rcc: clean-status-desktop-rcc $(STATUS_DESKTOP_RCC)
@@ -62,6 +75,11 @@ $(QRCODEGEN_LIB): $(QRCODEGEN_FILES)
@QRCODEGEN=$(QRCODEGEN) $(QRCODEGEN_SCRIPT) $(HANDLE_OUTPUT)
@echo "QRCodeGen built $(QRCODEGEN_LIB)"
+$(STATUS_KEYCARD_QT_LIB): $(STATUS_KEYCARD_QT_FILES) $(STATUS_KEYCARD_QT_SCRIPT) $(OPENSSL_LIB)
+ @echo "Building status-keycard-qt"
+ @STATUS_KEYCARD_QT=$(STATUS_KEYCARD_QT) KEYCARD_QT=$(KEYCARD_QT) BUILD_DIR=$(BUILD_PATH) $(STATUS_KEYCARD_QT_SCRIPT) $(HANDLE_OUTPUT)
+ @echo "status-keycard-qt built $(STATUS_KEYCARD_QT_LIB)"
+
$(STATUS_DESKTOP_RCC): $(STATUS_DESKTOP_UI_FILES) compile-translations
@echo "Building Status Desktop rcc"
@make -C $(STATUS_DESKTOP) rcc $(HANDLE_OUTPUT)
@@ -69,16 +87,39 @@ $(STATUS_DESKTOP_RCC): $(STATUS_DESKTOP_UI_FILES) compile-translations
$(NIM_STATUS_CLIENT_LIB): $(STATUS_DESKTOP_NIM_FILES) $(NIM_STATUS_CLIENT_SCRIPT) $(STATUS_DESKTOP_RCC) $(DOTHERSIDE_LIB) $(OPENSSL_LIB) $(STATUS_Q_LIB) $(STATUS_GO_LIB) $(QRCODEGEN_LIB)
@echo "Building Status Desktop Lib"
- @STATUS_DESKTOP=$(STATUS_DESKTOP) LIB_SUFFIX=$(LIB_SUFFIX) LIB_EXT=$(LIB_EXT) USE_QML_SERVER=$(USE_QML_SERVER) $(NIM_STATUS_CLIENT_SCRIPT) $(HANDLE_OUTPUT)
+ @STATUS_DESKTOP=$(STATUS_DESKTOP) \
+ LIB_SUFFIX=$(LIB_SUFFIX) \
+ LIB_EXT=$(LIB_EXT) \
+ USE_QML_SERVER=$(USE_QML_SERVER) \
+ BUNDLE_IDENTIFIER="$(BUNDLE_IDENTIFIER)" \
+ DEBUG=$(DEBUG) \
+ FLAG_DAPPS_ENABLED=$(FLAG_DAPPS_ENABLED) \
+ FLAG_CONNECTOR_ENABLED=$(FLAG_CONNECTOR_ENABLED) \
+ FLAG_KEYCARD_ENABLED=$(FLAG_KEYCARD_ENABLED) \
+ FLAG_SINGLE_STATUS_INSTANCE_ENABLED=$(FLAG_SINGLE_STATUS_INSTANCE_ENABLED) \
+ FLAG_BROWSER_ENABLED=$(FLAG_BROWSER_ENABLED) \
+ $(NIM_STATUS_CLIENT_SCRIPT) $(HANDLE_OUTPUT)
@echo "Status Desktop Lib built $(NIM_STATUS_CLIENT_LIB)"
# non-phony targets
-$(TARGET): $(APP_SCRIPT) $(STATUS_GO_LIB) $(STATUS_Q_LIB) $(DOTHERSIDE_LIB) $(OPENSSL_LIB) $(QRCODEGEN_LIB) $(NIM_STATUS_CLIENT_LIB) $(STATUS_DESKTOP_RCC) $(WRAPPER_APP_FILES)
+$(TARGET): $(APP_SCRIPT) $(STATUS_GO_LIB) $(STATUS_Q_LIB) $(DOTHERSIDE_LIB) $(OPENSSL_LIB) $(QRCODEGEN_LIB) $(STATUS_KEYCARD_QT_LIB) $(NIM_STATUS_CLIENT_LIB) $(STATUS_DESKTOP_RCC) $(WRAPPER_APP_FILES)
@echo "Building app"
ifeq ($(OS),android)
- @STATUS_DESKTOP=$(STATUS_DESKTOP) BUILD_TYPE=$(PACKAGE_TYPE) BIN_DIR=$(BIN_PATH) BUILD_DIR=$(BUILD_PATH) QT_MAJOR=$(QT_MAJOR) $(APP_SCRIPT) $(HANDLE_OUTPUT)
+ @STATUS_DESKTOP=$(STATUS_DESKTOP) \
+ BUILD_TYPE=$(PACKAGE_TYPE) \
+ BIN_DIR=$(BIN_PATH) \
+ BUILD_DIR=$(BUILD_PATH) \
+ QT_MAJOR=$(QT_MAJOR) \
+ FLAG_KEYCARD_ENABLED=$(FLAG_KEYCARD_ENABLED) \
+ $(APP_SCRIPT) $(HANDLE_OUTPUT)
else
- @STATUS_DESKTOP=$(STATUS_DESKTOP) BIN_DIR=$(BIN_PATH) BUILD_DIR=$(BUILD_PATH) QT_MAJOR=$(QT_MAJOR) $(APP_SCRIPT) $(HANDLE_OUTPUT)
+ @STATUS_DESKTOP=$(STATUS_DESKTOP) \
+ BIN_DIR=$(BIN_PATH) \
+ BUILD_DIR=$(BUILD_PATH) \
+ QT_MAJOR=$(QT_MAJOR) \
+ DEVELOPMENT_TEAM="$(DEVELOPMENT_TEAM)" \
+ FLAG_KEYCARD_ENABLED=$(FLAG_KEYCARD_ENABLED) \
+ $(APP_SCRIPT) $(HANDLE_OUTPUT)
endif
@echo "Built $(TARGET)"
@@ -128,7 +169,7 @@ endif
all: $(TARGET)
.PHONY: clean
-clean: clean-statusq clean-dotherside clean-openssl clean-qrcodegen clean-nim-status-client clean-status-desktop-rcc
+clean: clean-statusq clean-dotherside clean-openssl clean-qrcodegen clean-status-keycard-qt clean-nim-status-client clean-status-desktop-rcc
@echo "Cleaning"
@rm -rf $(ROOT_DIR)/bin $(ROOT_DIR)/build $(ROOT_DIR)/lib
@@ -158,6 +199,13 @@ clean-qrcodegen:
@rm -f $(QRCODEGEN_LIB)
@cd $(QRCODEGEN) && make clean
+# keycard-qt is now automatically built by status-keycard-qt via CMake FetchContent
+# Its build artifacts are cleaned as part of status-keycard-qt's build directory
+.PHONY: clean-status-keycard-qt
+clean-status-keycard-qt:
+ @rm -f $(STATUS_KEYCARD_QT_LIB)
+ @rm -rf $(STATUS_KEYCARD_QT)/build/$(OS)
+
.PHONY: clean-nim-status-client
clean-nim-status-client:
@rm -f $(NIM_STATUS_CLIENT_LIB)
diff --git a/mobile/android/qt6/AndroidManifest.xml b/mobile/android/qt6/AndroidManifest.xml
index 7305b3591a8..39f90e1954c 100644
--- a/mobile/android/qt6/AndroidManifest.xml
+++ b/mobile/android/qt6/AndroidManifest.xml
@@ -17,6 +17,7 @@
+
diff --git a/mobile/android/qt6/src/app/status/mobile/StatusQtActivity.java b/mobile/android/qt6/src/app/status/mobile/StatusQtActivity.java
index 64ebf16705f..3165138db2a 100644
--- a/mobile/android/qt6/src/app/status/mobile/StatusQtActivity.java
+++ b/mobile/android/qt6/src/app/status/mobile/StatusQtActivity.java
@@ -5,10 +5,20 @@
import android.os.Bundle;
import androidx.core.splashscreen.SplashScreen;
import java.util.concurrent.atomic.AtomicBoolean;
+import android.content.Intent;
+import android.app.PendingIntent;
+import android.nfc.NfcAdapter;
+import android.util.Log;
public class StatusQtActivity extends QtActivity {
+ private static final String TAG = "StatusQtActivity";
private static final AtomicBoolean splashShouldHide = new AtomicBoolean(false);
+ // NFC Foreground Dispatch members
+ // CRITICAL: These enable NFC detection to work immediately at app startup
+ private NfcAdapter mNfcAdapter;
+ private PendingIntent mPendingIntent;
+
// QTBUG-140897: Android 16 keyboard workaround
// Remove this line when Qt 6.10+ fixes the issue, and delete Android16KeyboardWorkaround.java
private Android16KeyboardWorkaround mKeyboardWorkaround;
@@ -25,6 +35,81 @@ public void onCreate(Bundle savedInstanceState) {
// QTBUG-140897: Install Android 16 keyboard workaround
// Remove this line when Qt 6.10+ fixes the issue
mKeyboardWorkaround = Android16KeyboardWorkaround.install(this);
+
+ // CRITICAL: Initialize NFC for Foreground Dispatch
+ // This ensures Qt NFC detection works immediately at app startup.
+ // Without this initialization, Qt's NFC detection fails until the app
+ // goes through a background→foreground cycle.
+ mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
+ if (mNfcAdapter == null) {
+ Log.d(TAG, "NFC not available on this device");
+ } else {
+ // Create a PendingIntent for NFC tag discovery
+ Intent intent = new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
+ int flags = PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT;
+ mPendingIntent = PendingIntent.getActivity(this, 0, intent, flags);
+ Log.d(TAG, "NFC Foreground Dispatch initialized");
+ }
+ }
+
+ // Track if foreground dispatch is enabled
+ private boolean mForegroundDispatchEnabled = false;
+
+ // Static reference to the current activity instance
+ private static StatusQtActivity sInstance = null;
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ sInstance = this;
+
+ Log.d(TAG, "===== onResume: Setting up NFC Foreground Dispatch =====");
+
+ // CRITICAL: Enable Foreground Dispatch here to fix Qt NFC startup issue
+ //
+ // Problem: Qt's NFC backend calls enableForegroundDispatch() during initialization,
+ // but this happens too early - before the Activity is fully ready. This causes
+ // Qt NFC detection to fail silently until the app goes background→foreground.
+ //
+ // Solution: We enable Foreground Dispatch here in onResume(), which is guaranteed
+ // to run after the Activity is fully ready. This ensures NFC detection works
+ // immediately at app startup.
+ //
+ // Note: Only enable if not already enabled to avoid disrupting active NFC connections
+ if (mNfcAdapter != null && mPendingIntent != null && !mForegroundDispatchEnabled) {
+ try {
+ mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, null);
+ mForegroundDispatchEnabled = true;
+ Log.d(TAG, "NFC Foreground Dispatch ENABLED (Qt detection will work)");
+ } catch (Exception e) {
+ Log.e(TAG, "Error enabling Foreground Dispatch: " + e.getMessage());
+ }
+ } else if (mForegroundDispatchEnabled) {
+ Log.d(TAG, "NFC Foreground Dispatch already enabled");
+ } else {
+ Log.w(TAG, "Cannot enable Foreground Dispatch - adapter or intent is null");
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ // Disable Foreground Dispatch when activity is paused
+ // This is standard Android practice to allow other apps to receive NFC events
+ if (mNfcAdapter != null && mForegroundDispatchEnabled) {
+ try {
+ mNfcAdapter.disableForegroundDispatch(this);
+ mForegroundDispatchEnabled = false;
+ Log.d(TAG, "NFC Foreground Dispatch DISABLED");
+ } catch (Exception e) {
+ Log.e(TAG, "Error disabling Foreground Dispatch: " + e.getMessage());
+ }
+ }
+
+ if (sInstance == this) {
+ sInstance = null;
+ }
}
@Override
diff --git a/mobile/ios/Info.plist b/mobile/ios/Info.plist.template
similarity index 84%
rename from mobile/ios/Info.plist
rename to mobile/ios/Info.plist.template
index ca93a55d2a3..e39f6171873 100644
--- a/mobile/ios/Info.plist
+++ b/mobile/ios/Info.plist.template
@@ -66,5 +66,18 @@
Log in securely to your account.
ITSAppUsesNonExemptEncryption
+
+
+
diff --git a/mobile/ios/Status-NoKeycard.entitlements b/mobile/ios/Status-NoKeycard.entitlements
new file mode 100644
index 00000000000..35c3f6949d0
--- /dev/null
+++ b/mobile/ios/Status-NoKeycard.entitlements
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mobile/ios/Status.entitlements b/mobile/ios/Status.entitlements
new file mode 100644
index 00000000000..8e1b20cbd2b
--- /dev/null
+++ b/mobile/ios/Status.entitlements
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ com.apple.developer.nfc.readersession.formats
+
+ TAG
+
+
+
+
+
+
+
diff --git a/mobile/scripts/Common.mk b/mobile/scripts/Common.mk
index 896787f8dad..bd8364c62dd 100644
--- a/mobile/scripts/Common.mk
+++ b/mobile/scripts/Common.mk
@@ -33,6 +33,7 @@ STATUS_GO?=$(STATUS_DESKTOP)/vendor/status-go
DOTHERSIDE?=$(STATUS_DESKTOP)/vendor/DOtherSide
OPENSSL?=$(ROOT_DIR)/vendors/openssl
QRCODEGEN?=$(STATUS_DESKTOP)/vendor/QR-Code-generator/c
+STATUS_KEYCARD_QT?=$(STATUS_DESKTOP)/vendor/status-keycard-qt
# compile macros
TARGET_PREFIX := Status
@@ -61,6 +62,7 @@ STATUS_GO_FILES := $(shell find $(STATUS_GO) -type f \( -iname '*.go' \))
DOTHERSIDE_FILES := $(shell find $(DOTHERSIDE) -type f \( -iname '*.cpp' -o -iname '*.h' \))
OPENSSL_FILES := $(shell find $(OPENSSL) -type f \( -iname '*.c' -o -iname '*.h' \))
QRCODEGEN_FILES := $(shell find $(QRCODEGEN) -type f \( -iname '*.c' -o -iname '*.h' \))
+STATUS_KEYCARD_QT_FILES := $(shell find $(STATUS_KEYCARD_QT) -type f \( -iname '*.cpp' -o -iname '*.h' \) 2>/dev/null || echo "")
WRAPPER_APP_FILES := $(shell find $(WRAPPER_APP) -type f)
# script files
@@ -69,6 +71,7 @@ STATUS_GO_SCRIPT := $(SCRIPTS_PATH)/buildStatusGo.sh
DOTHERSIDE_SCRIPT := $(SCRIPTS_PATH)/buildDOtherSide.sh
OPENSSL_SCRIPT := $(SCRIPTS_PATH)/ios/buildOpenSSL.sh
QRCODEGEN_SCRIPT := $(SCRIPTS_PATH)/buildQRCodeGen.sh
+STATUS_KEYCARD_QT_SCRIPT := $(SCRIPTS_PATH)/buildStatusKeycardQt.sh
NIM_STATUS_CLIENT_SCRIPT := $(SCRIPTS_PATH)/buildNimStatusClient.sh
APP_SCRIPT := $(SCRIPTS_PATH)/buildApp.sh
RUN_SCRIPT := $(SCRIPTS_PATH)/$(OS)/run.sh
@@ -79,6 +82,7 @@ STATUS_Q_LIB := $(LIB_PATH)/libStatusQ$(LIB_SUFFIX)$(LIB_EXT)
OPENSSL_LIB := $(LIB_PATH)/libssl_3$(LIB_EXT)
QRCODEGEN_LIB := $(LIB_PATH)/libqrcodegen.a
QZXING_LIB := $(LIB_PATH)/libqzxing.a
+STATUS_KEYCARD_QT_LIB := $(LIB_PATH)/libstatus-keycard-qt$(LIB_EXT)
NIM_STATUS_CLIENT_LIB := $(LIB_PATH)/libnim_status_client$(LIB_EXT)
STATUS_DESKTOP_RCC := $(STATUS_DESKTOP)/ui/resources.qrc
ifeq ($(OS), ios)
diff --git a/mobile/scripts/buildApp.sh b/mobile/scripts/buildApp.sh
index 3ec8de95c81..d516d344042 100755
--- a/mobile/scripts/buildApp.sh
+++ b/mobile/scripts/buildApp.sh
@@ -11,6 +11,7 @@ BUILD_DIR=${BUILD_DIR:-"$CWD/../build"}
ANDROID_ABI=${ANDROID_ABI:-"arm64-v8a"}
BUILD_TYPE=${BUILD_TYPE:-"apk"}
SIGN_IOS=${SIGN_IOS:-"false"}
+FLAG_KEYCARD_ENABLED=${FLAG_KEYCARD_ENABLED:-0}
QMAKE_BIN="${QMAKE:-qmake}"
QMAKE_CONFIG="CONFIG+=device CONFIG+=release"
@@ -33,6 +34,12 @@ fi
echo "Using version: $DESKTOP_VERSION; build version: $BUILD_VERSION"
+# Configure qmake with keycard flag
+QMAKE_DEFINES=""
+if [[ "${FLAG_KEYCARD_ENABLED}" == "1" ]]; then
+ QMAKE_DEFINES="DEFINES+=FLAG_KEYCARD_ENABLED"
+fi
+
if [[ "${OS}" == "android" ]]; then
if [[ -z "${JAVA_HOME}" ]]; then
echo "JAVA_HOME is not set. Please set JAVA_HOME to the path of your JDK 11 or later."
@@ -42,7 +49,7 @@ if [[ "${OS}" == "android" ]]; then
echo "Building for Android 35"
ANDROID_PLATFORM=android-35
- "$QMAKE_BIN" "$CWD/../wrapperApp/Status.pro" "$QMAKE_CONFIG" -spec android-clang ANDROID_ABIS="$ANDROID_ABI" APP_VARIANT="${APP_VARIANT}" VERSION="$DESKTOP_VERSION" -after
+ "$QMAKE_BIN" "$CWD/../wrapperApp/Status.pro" "$QMAKE_CONFIG" -spec android-clang ANDROID_ABIS="$ANDROID_ABI" APP_VARIANT="${APP_VARIANT}" VERSION="$DESKTOP_VERSION" ${QMAKE_DEFINES} -after
# Build the app
make -j"$(nproc)" apk_install_target
@@ -122,12 +129,35 @@ if [[ "${OS}" == "android" ]]; then
fi
fi
else
- "$QMAKE_BIN" "$CWD/../wrapperApp/Status.pro" "$QMAKE_CONFIG" -spec macx-ios-clang CONFIG+="$SDK" VERSION="$DESKTOP_VERSION" -after
+ # Generate Info.plist based on FLAG_KEYCARD_ENABLED
+ echo "Generating Info.plist (FLAG_KEYCARD_ENABLED=${FLAG_KEYCARD_ENABLED})..."
+ if [[ "${FLAG_KEYCARD_ENABLED}" == "1" ]]; then
+ # Enable NFC/Keycard support - uncomment NFC sections
+ sed -e '/$/d' \
+ "$CWD/../ios/Info.plist.template" > "$BUILD_DIR/Info.plist"
+ else
+ # Disable NFC/Keycard support - remove NFC sections entirely
+ sed '/$/d' \
+ "$CWD/../ios/Info.plist.template" > "$BUILD_DIR/Info.plist"
+ fi
+
+ "$QMAKE_BIN" "$CWD/../wrapperApp/Status.pro" "$QMAKE_CONFIG" -spec macx-ios-clang CONFIG+="$SDK" VERSION="$DESKTOP_VERSION" ${QMAKE_DEFINES} -after
+
+ # By default the app is not signed. Set the `DEVELOPMENT_TEAM` to the team ID to automatically sign the app.
+ SIGN_ARGS="CODE_SIGN_IDENTITY=\"\" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO"
+ if [[ -n "${DEVELOPMENT_TEAM}" ]]; then
+ echo "Signing Configuration: ${SIGN_ARGS} DEVELOPMENT_TEAM=${DEVELOPMENT_TEAM}"
+ /usr/libexec/PlistBuddy -c "Set :objects:*:buildSettings:DEVELOPMENT_TEAM ${DEVELOPMENT_TEAM}" "$BUILD_DIR/Status.xcodeproj/project.pbxproj" 2>/dev/null || true
+ sed -i '' "s/DEVELOPMENT_TEAM = .*;/DEVELOPMENT_TEAM = ${DEVELOPMENT_TEAM};/g" "$BUILD_DIR/Status.xcodeproj/project.pbxproj"
+ SIGN_ARGS="CODE_SIGN_STYLE=Automatic DEVELOPMENT_TEAM=${DEVELOPMENT_TEAM} -allowProvisioningUpdates"
+ fi
# Compile resources
- xcodebuild -configuration Release -target "Qt Preprocess" -sdk "$SDK" -arch "$ARCH" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO CURRENT_PROJECT_VERSION=$BUILD_VERSION | xcbeautify
- # Compile the app
- xcodebuild -configuration Release -target Status install -sdk "$SDK" -arch "$ARCH" DSTROOT="$BIN_DIR" INSTALL_PATH="/" TARGET_BUILD_DIR="$BIN_DIR" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO CURRENT_PROJECT_VERSION=$BUILD_VERSION | xcbeautify
+ echo "Signing Configuration: ${SIGN_ARGS}"
+ xcodebuild -configuration Release -target "Qt Preprocess" -sdk "$SDK" -arch "$ARCH" ${SIGN_ARGS} | xcbeautify
+
+ xcodebuild -configuration Release -target Status install -sdk "$SDK" -arch "$ARCH" DSTROOT="$BIN_DIR" INSTALL_PATH="/" TARGET_BUILD_DIR="$BIN_DIR" ${SIGN_ARGS} | xcbeautify
if [[ ! -e "$BIN_DIR/Status.app/Info.plist" ]]; then
echo "Build failed"
diff --git a/mobile/scripts/buildNimStatusClient.sh b/mobile/scripts/buildNimStatusClient.sh
index ca6aa116f9f..0f82e9e4253 100755
--- a/mobile/scripts/buildNimStatusClient.sh
+++ b/mobile/scripts/buildNimStatusClient.sh
@@ -8,6 +8,12 @@ ANDROID_ABI=${ANDROID_ABI:-"arm64-v8a"}
LIB_DIR=${LIB_DIR}
LIB_SUFFIX=${LIB_SUFFIX:-""}
OS=${OS:-"android"}
+DEBUG=${DEBUG:-0}
+FLAG_DAPPS_ENABLED=${FLAG_DAPPS_ENABLED:-0}
+FLAG_CONNECTOR_ENABLED=${FLAG_CONNECTOR_ENABLED:-0}
+FLAG_KEYCARD_ENABLED=${FLAG_KEYCARD_ENABLED:-0}
+FLAG_SINGLE_STATUS_INSTANCE_ENABLED=${FLAG_SINGLE_STATUS_INSTANCE_ENABLED:-0}
+FLAG_BROWSER_ENABLED=${FLAG_BROWSER_ENABLED:-0}
DESKTOP_VERSION=$(eval cd "$STATUS_DESKTOP" && git describe --tags --dirty="-dirty" --always)
STATUSGO_VERSION=$(eval cd "$STATUS_DESKTOP/vendor/status-go" && git describe --tags --dirty="-dirty" --always)
@@ -22,7 +28,7 @@ if [[ "$OS" == "ios" ]]; then
PLATFORM_SPECIFIC=(--app:staticlib -d:ios --os:ios)
else
PLATFORM_SPECIFIC=(--app:lib --os:android -d:android -d:androidNDK -d:chronicles_sinks=textlines[logcat],textlines[nocolors,dynamic],textlines[file,nocolors] \
- --passL="-L$LIB_DIR" --passL="-lstatus" --passL="-lStatusQ$LIB_SUFFIX" --passL="-lDOtherSide$LIB_SUFFIX" --passL="-lqrcodegen" --passL="-lqzxing" --passL="-lssl_3" --passL="-lcrypto_3" -d:taskpool)
+ --passL="-L$LIB_DIR" --passL="-lstatus" --passL="-lStatusQ$LIB_SUFFIX" --passL="-lDOtherSide$LIB_SUFFIX" --passL="-lqrcodegen" --passL="-lqzxing" --passL="-lssl_3" --passL="-lcrypto_3" --passL="-lstatus-keycard-qt" -d:taskpool)
fi
if [ -n "$USE_QML_SERVER" ]; then
@@ -37,7 +43,13 @@ cd "$STATUS_DESKTOP"
# build nim compiler with host env
# setting compile time feature flags
-FEATURE_FLAGS="FLAG_DAPPS_ENABLED=0 FLAG_CONNECTOR_ENABLED=0 FLAG_KEYCARD_ENABLED=0 FLAG_SINGLE_STATUS_INSTANCE_ENABLED=0 FLAG_BROWSER_ENABLED=0"
+FEATURE_FLAGS=(
+ FLAG_DAPPS_ENABLED=$FLAG_DAPPS_ENABLED
+ FLAG_CONNECTOR_ENABLED=$FLAG_CONNECTOR_ENABLED
+ FLAG_KEYCARD_ENABLED=$FLAG_KEYCARD_ENABLED
+ FLAG_SINGLE_STATUS_INSTANCE_ENABLED=$FLAG_SINGLE_STATUS_INSTANCE_ENABLED
+ FLAG_BROWSER_ENABLED=$FLAG_BROWSER_ENABLED
+)
# app configuration defines
APP_CONFIG_DEFINES=(
@@ -48,21 +60,28 @@ APP_CONFIG_DEFINES=(
-d:GIT_COMMIT="$(git log --pretty=format:'%h' -n 1)"
)
+NIM_FLAGS=(
+ --mm:orc
+ -d:useMalloc
+ --opt:size
+ --cc:clang
+ --cpu:"$CARCH"
+ --noMain:on
+ --clang.exe="$CC"
+ --clang.linkerexe="$CC"
+ --dynlibOverrideAll
+ --nimcache:"$STATUS_DESKTOP"/nimcache
+)
+
+if [ "$DEBUG" -eq 1 ]; then
+ NIM_FLAGS+=(-d:debug -d:nimTypeNames)
+else
+ NIM_FLAGS+=(-d:release -d:lto -d:production)
+fi
+
# build status-client with feature flags
-env $FEATURE_FLAGS ./vendor/nimbus-build-system/scripts/env.sh nim c "${PLATFORM_SPECIFIC[@]}" "${APP_CONFIG_DEFINES[@]}" ${QML_SERVER_DEFINES} \
- --mm:orc \
- -d:useMalloc \
- --opt:size \
- -d:lto \
- --cc:clang \
- --cpu:"$CARCH" \
- --noMain:on \
- -d:release \
- -d:production \
- --clang.exe="$CC" \
- --clang.linkerexe="$CC" \
- --dynlibOverrideAll \
- --nimcache:"$STATUS_DESKTOP"/nimcache \
+env "${FEATURE_FLAGS[@]}" ./vendor/nimbus-build-system/scripts/env.sh nim c "${PLATFORM_SPECIFIC[@]}" "${APP_CONFIG_DEFINES[@]}" ${QML_SERVER_DEFINES} \
+ "${NIM_FLAGS[@]}" \
"$STATUS_DESKTOP"/src/nim_status_client.nim
mkdir -p "$LIB_DIR"
diff --git a/mobile/scripts/buildStatusKeycardQt.sh b/mobile/scripts/buildStatusKeycardQt.sh
new file mode 100755
index 00000000000..f3d03b60b8e
--- /dev/null
+++ b/mobile/scripts/buildStatusKeycardQt.sh
@@ -0,0 +1,91 @@
+#!/usr/bin/env bash
+set -ef pipefail
+
+BASEDIR=$(dirname "$0")
+
+# Load common config variables
+source "${BASEDIR}/commonCmakeConfig.sh"
+
+STATUS_KEYCARD_QT=${STATUS_KEYCARD_QT:="../vendors/status-desktop"}
+KEYCARD_QT=${KEYCARD_QT:=""}
+LIB_DIR=${LIB_DIR}
+LIB_EXT=${LIB_EXT:=".a"}
+
+BUILD_DIR=${BUILD_DIR:="${STATUS_KEYCARD_QT}/build/${OS}/${ARCH}"}
+BUILD_SHARED_LIBS=ON
+
+if [[ "${LIB_EXT}" == ".a" ]]; then
+ BUILD_SHARED_LIBS=OFF
+fi
+
+echo "Building status-keycard-qt for ${ARCH} using compiler: ${CC}"
+echo "BUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}"
+
+printf 'COMMON_CMAKE_CONFIG: %s\n' "${COMMON_CMAKE_CONFIG[@]}"
+
+# Set OpenSSL paths (REQUIRED for key derivation in session_manager.cpp)
+MOBILE_ROOT="$(cd "${BASEDIR}/.." && pwd)"
+if [[ "$OS" == "android" ]]; then
+ OPENSSL_BUILD_DIR="${MOBILE_ROOT}/build/${OS}/qt6/openssl-${OS}-${ARCH}"
+elif [[ "$OS" == "ios" ]]; then
+ # iOS OpenSSL is built per-architecture
+ OPENSSL_BUILD_DIR="${MOBILE_ROOT}/build/${OS}/qt6/openssl-${OS}-${ARCH}"
+else
+ OPENSSL_BUILD_DIR="${MOBILE_ROOT}/build/${OS}/openssl-${OS}-${ARCH}"
+fi
+OPENSSL_BUILD_INCLUDE_DIR="${OPENSSL_BUILD_DIR}/include"
+OPENSSL_SOURCE_INCLUDE_DIR="${MOBILE_ROOT}/vendors/openssl/include"
+OPENSSL_CRYPTO_LIBRARY="${LIB_DIR}/libcrypto_3${LIB_EXT}"
+
+echo "OpenSSL paths:"
+echo " Build include dir: ${OPENSSL_BUILD_INCLUDE_DIR}"
+echo " Source include dir: ${OPENSSL_SOURCE_INCLUDE_DIR}"
+echo " Crypto library: ${OPENSSL_CRYPTO_LIBRARY}"
+
+# Configure with CMake
+# Use local keycard-qt for faster development builds (FetchContent will use this)
+# If KEYCARD_QT path doesn't exist, FetchContent will clone from GitHub
+if [[ -d "${KEYCARD_QT}" ]]; then
+ echo "Using local keycard-qt from: ${KEYCARD_QT}"
+ KEYCARD_QT_SOURCE_DIR_ARG="-DKEYCARD_QT_SOURCE_DIR=${KEYCARD_QT}"
+else
+ echo "Local keycard-qt not found, will fetch from GitHub"
+ KEYCARD_QT_SOURCE_DIR_ARG=""
+fi
+
+cmake -S "${STATUS_KEYCARD_QT}" -B "${BUILD_DIR}" \
+ "${COMMON_CMAKE_CONFIG[@]}" \
+ -DBUILD_TESTING=OFF \
+ -DBUILD_EXAMPLES=OFF \
+ -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} \
+ ${KEYCARD_QT_SOURCE_DIR_ARG} \
+ -DOPENSSL_BUILD_INCLUDE_DIR="${OPENSSL_BUILD_INCLUDE_DIR}" \
+ -DOPENSSL_SOURCE_INCLUDE_DIR="${OPENSSL_SOURCE_INCLUDE_DIR}" \
+ -DOPENSSL_CRYPTO_LIBRARY="${OPENSSL_CRYPTO_LIBRARY}"
+
+# Build the library
+make -C "${BUILD_DIR}" status-keycard-qt -j "$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)"
+
+# Create lib directory
+mkdir -p "${LIB_DIR}"
+
+# Find and copy the built library
+# Note: keycard-qt is built as a static library and linked into libstatus-keycard-qt,
+# so we only need to copy one library file
+STATUS_KEYCARD_QT_LIB=$(find "${BUILD_DIR}" -name "libstatus-keycard-qt${LIB_EXT}" -o -name "libstatus-keycard-qt.dylib" | grep -v "\.so\." | head -n 1)
+
+if [[ -z "${STATUS_KEYCARD_QT_LIB}" ]]; then
+ # Try alternative patterns for static library
+ STATUS_KEYCARD_QT_LIB=$(find "${BUILD_DIR}" -name "libstatus-keycard-qt.a" | head -n 1)
+fi
+
+if [[ -z "${STATUS_KEYCARD_QT_LIB}" ]]; then
+ echo "Error: Could not find status-keycard-qt library in ${BUILD_DIR}"
+ echo "Build directory contents:"
+ find "${BUILD_DIR}" -name "*.so" -o -name "*.a" -o -name "*.dylib" | head -20
+ exit 1
+fi
+
+cp "${STATUS_KEYCARD_QT_LIB}" "${LIB_DIR}/libstatus-keycard-qt${LIB_EXT}"
+echo "Copied ${STATUS_KEYCARD_QT_LIB} to ${LIB_DIR}/libstatus-keycard-qt${LIB_EXT}"
+
diff --git a/mobile/scripts/commonCmakeConfig.sh b/mobile/scripts/commonCmakeConfig.sh
index d92d627be2d..31a927a3f26 100755
--- a/mobile/scripts/commonCmakeConfig.sh
+++ b/mobile/scripts/commonCmakeConfig.sh
@@ -2,7 +2,9 @@
set -ef pipefail
ARCH=${ARCH:-"x86_64"}
-QTDIR=${QTDIR:-$(qmake -query QT_INSTALL_PREFIX)}
+# Use $QMAKE if set, otherwise fall back to system qmake
+QMAKE_BIN=${QMAKE:-qmake}
+QTDIR=${QTDIR:-$($QMAKE_BIN -query QT_INSTALL_PREFIX)}
OS=${OS:-ios}
ANDROID_NDK_ROOT=${ANDROID_NDK_ROOT:-""}
@@ -46,4 +48,9 @@ COMMON_CMAKE_CONFIG+=(
-DCMAKE_BUILD_TYPE=Release
)
+# Add Android-specific flags only for Android
+if [[ "$OS" == "android" ]]; then
+ COMMON_CMAKE_CONFIG+=(-DANDROID_PLATFORM=android-35)
+fi
+
printf 'COMMON_CMAKE_CONFIG: %s\n' "${COMMON_CMAKE_CONFIG[@]}"
diff --git a/mobile/scripts/ios/buildOpenSSL.sh b/mobile/scripts/ios/buildOpenSSL.sh
index 1aeb294fd15..4aea7bcc459 100755
--- a/mobile/scripts/ios/buildOpenSSL.sh
+++ b/mobile/scripts/ios/buildOpenSSL.sh
@@ -56,7 +56,30 @@ mkdir -p ${SSL_BUILD_DIR}
(
cd ${SSL_BUILD_DIR}
- ${OPENSSL}/Configure --release "$TARGET" $PLATFORM_CONFIG_ARGS
+
+ # - no-module: Makes legacy provider built-in to libcrypto (not a separate module)
+ # - enable-legacy: Enables legacy algorithms including DES
+ # This is required for GlobalPlatform SCP02 which uses single-DES
+ # Reference: https://github.com/openssl/openssl/discussions/25793
+
+ # Platform-specific config
+ if [[ "$OS" == "ios" ]]; then
+ # iOS uses static libraries (.a files)
+ SHARED_FLAG="no-shared"
+ else
+ # Android uses shared libraries (.so files)
+ SHARED_FLAG="shared"
+ fi
+
+ ${OPENSSL}/Configure --release "$TARGET" $PLATFORM_CONFIG_ARGS \
+ no-module \
+ enable-legacy \
+ enable-des \
+ enable-md2 \
+ enable-rc5 \
+ $SHARED_FLAG \
+ no-tests \
+ no-ui-console
# Rebuilding isn't working with the default target, so we need to clean and build again
make clean
make -j$(sysctl -n hw.ncpu) $PLATFORM_BUILD_ARGS build_libs
diff --git a/mobile/wrapperApp/Status.pro b/mobile/wrapperApp/Status.pro
index 4c974aa5397..526338ba62f 100644
--- a/mobile/wrapperApp/Status.pro
+++ b/mobile/wrapperApp/Status.pro
@@ -2,6 +2,14 @@ TEMPLATE = app
QT += quick gui qml webview svg widgets multimedia
+# Conditionally add NFC module only if keycard is enabled
+contains(DEFINES, FLAG_KEYCARD_ENABLED) {
+ message("Building with Keycard/NFC support enabled")
+ QT += nfc
+} else {
+ message("Building WITHOUT Keycard/NFC support (default for development)")
+}
+
equals(QT_MAJOR_VERSION, 6) {
message("qt 6 config!!")
QT += core5compat core
@@ -36,7 +44,10 @@ android {
$$PWD/../lib/$$LIB_PREFIX/libDOtherSide$$(LIB_SUFFIX)$$(LIB_EXT) \
$$PWD/../lib/$$LIB_PREFIX/libstatus.so \
$$PWD/../lib/$$LIB_PREFIX/libsds.so \
- $$PWD/../lib/$$LIB_PREFIX/libStatusQ$$(LIB_SUFFIX)$$(LIB_EXT) \
+ $$PWD/../lib/$$LIB_PREFIX/libStatusQ$$(LIB_SUFFIX)$$(LIB_EXT)
+ contains(DEFINES, FLAG_KEYCARD_ENABLED) {
+ ANDROID_EXTRA_LIBS += $$PWD/../lib/$$LIB_PREFIX/libstatus-keycard-qt.so
+ }
OTHER_FILES += \
$$ANDROID_PACKAGE_SOURCE_DIR/src/app/status/mobile/SecureAndroidAuthentication.java
@@ -45,18 +56,34 @@ android {
ios {
CONFIG += add_ios_ffmpeg_libraries
- QMAKE_INFO_PLIST = $$PWD/../ios/Info.plist
+ QMAKE_INFO_PLIST = $$OUT_PWD/Info.plist
QMAKE_IOS_DEPLOYMENT_TARGET=16.0
QMAKE_TARGET_BUNDLE_PREFIX = app.status
QMAKE_BUNDLE = mobile
QMAKE_ASSET_CATALOGS += $$PWD/../ios/Images.xcassets
QMAKE_IOS_LAUNCH_SCREEN = $$PWD/../ios/launch-image-universal.storyboard
- LIBS += -L$$PWD/../lib/$$LIB_PREFIX -lnim_status_client -lDOtherSideStatic -lstatusq -lstatus -lsds -lssl_3 -lcrypto_3 -lqzxing -lresolv -lqrcodegen
-
# --- iOS frameworks required by keychain_apple.mm ---
LIBS += -framework LocalAuthentication \
-framework Security \
-framework UIKit \
-framework Foundation
+
+ # Base libraries (always included)
+ LIBS += -L$$PWD/../lib/$$LIB_PREFIX -lnim_status_client -lDOtherSideStatic -lstatusq -lstatus -lsds -lssl_3 -lcrypto_3 -lqzxing -lresolv -lqrcodegen
+
+ contains(DEFINES, FLAG_KEYCARD_ENABLED) {
+ # Use entitlements with NFC support (requires paid Apple Developer account)
+ MY_ENTITLEMENTS.name = CODE_SIGN_ENTITLEMENTS
+ MY_ENTITLEMENTS.value = $$PWD/../ios/Status.entitlements
+ QMAKE_MAC_XCODE_SETTINGS += MY_ENTITLEMENTS
+
+ LIBS += -lstatus-keycard-qt -framework CoreNFC
+
+ } else {
+ # Use entitlements without NFC (allows building with free Apple account)
+ MY_ENTITLEMENTS.name = CODE_SIGN_ENTITLEMENTS
+ MY_ENTITLEMENTS.value = $$PWD/../ios/Status-NoKeycard.entitlements
+ QMAKE_MAC_XCODE_SETTINGS += MY_ENTITLEMENTS
+ }
}
diff --git a/vendor/status-keycard-qt b/vendor/status-keycard-qt
new file mode 160000
index 00000000000..40f56de84f8
--- /dev/null
+++ b/vendor/status-keycard-qt
@@ -0,0 +1 @@
+Subproject commit 40f56de84f80f45bccf2ba62fb3eee93196dbc45