diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..ac5ea99 Binary files /dev/null and b/.DS_Store differ diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..fe5ea28 --- /dev/null +++ b/.clang-format @@ -0,0 +1,300 @@ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ + +#http://clang.llvm.org/docs/ClangFormatStyleOptions.html + +# The style used for all options not specifically set in the configuration. +# This option is supported only in the clang-format configuration (both within +# -style='{...}' and the .clang-format file). +# LLVM A style complying with the LLVM coding standards +# Google A style complying with Google’s C++ style guide +# Chromium A style complying with Chromium’s style guide +# Mozilla A style complying with Mozilla’s style guide +# WebKit A style complying with WebKit’s style guide +BasedOnStyle: Webkit + +# The extra indent or outdent of access modifiers, e.g. public:. +AccessModifierOffset: -4 + +# If true, horizontally aligns arguments after an open bracket. +# This applies to round brackets (parentheses), angle brackets and square +# brackets. This will result in formattings like code +# someLongFunction(argument1, argument2); endcode +AlignAfterOpenBracket: AlwaysBreak + +# If true, aligns escaped newlines as far left as possible. Otherwise puts them +# into the right-most column. +#AlignEscapedNewlinesLeft + +# If true, horizontally align operands of binary and ternary expressions. +AlignOperands: true + +# If true, aligns trailing comments. +AlignTrailingComments: true + +# Allow putting all parameters of a function declaration onto the next line even +# if BinPackParameters is false. +AllowAllParametersOfDeclarationOnNextLine: true + +# Allows contracting simple braced statements to a single line. +# E.g., this allows if (a) { return; } to be put on a single line. +AllowShortBlocksOnASingleLine: false + +# If true, short case labels will be contracted to a single line. +AllowShortCaseLabelsOnASingleLine: false + +# Dependent on the value, int f() { return 0; } can be put on a single line. +# SFS_None (in configuration: None) Never merge functions into a single line. +# SFS_Inline (in configuration: Inline) Only merge functions defined inside a +# class. +# SFS_Empty (in configuration: Empty) Only merge empty functions. +# SFS_All (in configuration: All) Merge all functions fitting on a single line. +AllowShortFunctionsOnASingleLine: None + +# If true, if (a) return; can be put on a single line. +#AllowShortIfStatementsOnASingleLine: false + +# If true, while (true) continue; can be put on a single line. +AllowShortLoopsOnASingleLine: true + +# If true, always break after function definition return types. +# More truthfully called ‘break before the identifier following the type in a +# function definition’. +# PenaltyReturnTypeOnItsOwnLine becomes irrelevant. +AlwaysBreakAfterDefinitionReturnType: All + +# If true, always break before multiline string literals. +AlwaysBreakBeforeMultilineStrings: false + +# If true, always break after the template<...> of a template declaration. +AlwaysBreakTemplateDeclarations: true + +# If false, a function call’s arguments will either be all on the same line or +# will have one line each. +BinPackArguments: false + +# If false, a function call’s arguments will either be all +# on the same line or will have one line each. +BinPackParameters: false + +# The way to wrap binary operators. +# BOS_None (in configuration: None) Break after operators. +# BOS_NonAssignment (in configuration: NonAssignment) Break before operators +# that aren’t assignments. +# BOS_All (in configuration: All) Break before operators. +#BreakBeforeBinaryOperators: None + +# The brace breaking style to use. +# BS_Attach (in configuration: Attach) Always attach braces to surrounding +# context. +# BS_Linux (in configuration: Linux) Like Attach, but break before braces on +# function, namespace and class definitions. +# BS_Stroustrup (in configuration: Stroustrup) Like Attach, but break before +# function definitions, and ‘else’. +# BS_Allman (in configuration: Allman) Always break before braces. +# BS_GNU (in configuration: GNU) Always break before braces and add an extra +# level of indentation to braces of control statements, not to those of class, +# function or other definitions. +BreakBeforeBraces: Attach + +# If true, ternary operators will be placed after line breaks. +BreakBeforeTernaryOperators: true + +# Always break constructor initializers before commas and align the commas with +# the colon. +BreakConstructorInitializersBeforeComma: true + +# The column limit. +# A column limit of 0 means that there is no column limit. In this case, +# clang-format will respect the input’s line breaking decisions within +# statements unless they contradict other rules. +ColumnLimit: 80 + +# A regular expression that describes comments with special meaning, which +# should not be split into lines or otherwise changed. +CommentPragmas: "\/*(.*)*\/" + +# If the constructor initializers don’t fit on a line, put each initializer on +# its own line. +#ConstructorInitializerAllOnOneLineOrOnePerLine: false + +# The number of characters to use for indentation of constructor initializer +# lists. +ConstructorInitializerIndentWidth: 0 + +# Indent width for line continuations. +#ContinuationIndentWidth: 4 + +# If true, format braced lists as best suited for C++11 braced lists. +# Important differences: - No spaces inside the braced list. - No line break +# before the closing brace. - Indentation with the continuation indent, not with +# the block indent. +# Fundamentally, C++11 braced lists are formatted exactly like function calls +# would be formatted in their place. If the braced list follows a name (e.g. a +# type or variable name), clang-format formats as if the {} were the parentheses +# of a function call with that name. If there is no name, a zero-length name is +# assumed. +Cpp11BracedListStyle: true + +# If true, analyze the formatted file for the most common alignment of & and *. +# Point +#DerivePointerAlignment: false + +# Disables formatting at all. +#DisableFormat: false + +# If true, clang-format detects whether function calls and definitions are +# formatted with one parameter per line. +# Each call can be bin-packed, one-per-line or inconclusive. If it is +# inconclusive, e.g. completely on one line, but a decision needs to be made, +# clang-format analyzes whether there are other bin-packed cases in the input +# file and act accordingly. +# NOTE: This is an experimental flag, that might go away or be renamed. Do not +# use this in config files, etc. Use at your own risk. +ExperimentalAutoDetectBinPacking: false + +# A vector of macros that should be interpreted as foreach loops instead of as +# function calls. +# These are expected to be macros of the form: code +# FOREACH(, ...) endcode +# For example: BOOST_FOREACH. +#ForEachMacros (std::vector) + +# Indent case labels one level from the switch statement. +# When false, use the same indentation level as for the switch statement. Switch +# statement body is always indented one level more than case labels. +IndentCaseLabels: false + +# The number of columns to use for indentation. +IndentWidth: 4 + +# Indent if a function definition or declaration is wrapped after the type. +#IndentWrappedFunctionNames: false + +# If true, empty lines at the start of blocks are kept. +KeepEmptyLinesAtTheStartOfBlocks: false + +# Language, this format style is targeted at. +# LK_None (in configuration: None) Do not use. +# LK_Cpp (in configuration: Cpp) Should be used for C, C++, ObjectiveC, +# ObjectiveC++. +# LK_Java (in configuration: Java) Should be used for Java. +# LK_JavaScript (in configuration: JavaScript) Should be used for JavaScript. +# LK_Proto (in configuration: Proto) Should be used for Protocol Buffers +# (https://developers.google.com/protocol-buffers/). +Language: Cpp + +# The maximum number of consecutive empty lines to keep. +#MaxEmptyLinesToKeep: 0 + +# The indentation used for namespaces. +# NI_None (in configuration: None) Don’t indent in namespaces. +# NI_Inner (in configuration: Inner) Indent only in inner namespaces (nested in +# other namespaces). +# NI_All (in configuration: All) Indent in all namespaces. +NamespaceIndentation: None + +# The number of characters to use for indentation of ObjC blocks. +#ObjCBlockIndentWidth: 4 + +# Add a space after @property in Objective-C, i.e. use \@property (readonly) +# instead of \@property(readonly). +#ObjCSpaceAfterProperty: false + +# Add a space in front of an Objective-C protocol list, i.e. use Foo +# instead of Foo. +#ObjCSpaceBeforeProtocolList: false + +# The penalty for breaking a function call after “call(”. +#PenaltyBreakBeforeFirstCallParameter (unsigned) + +# The penalty for each line break introduced inside a comment. +#PenaltyBreakComment (unsigned) + +# The penalty for breaking before the first <<. +#PenaltyBreakFirstLessLess (unsigned) + +# The penalty for each line break introduced inside a string literal. +#PenaltyBreakString (unsigned) + +# The penalty for each character outside of the column limit. +#PenaltyExcessCharacter (unsigned) + +# Penalty for putting the return type of a function onto its own line. +#PenaltyReturnTypeOnItsOwnLine (unsigned) + +# If true, analyze the formatted file for the most common alignment of & and *. +# PointerAlignment is then used only as fallback. +PointerAlignment: Left + +# If true, a space may be inserted after C style casts. +SpaceAfterCStyleCast: false + +# If false, spaces will be removed before assignment operators. +SpaceBeforeAssignmentOperators: true + +# Defines in which cases to put a space before opening parentheses. +# SBPO_Never (in configuration: Never) Never put a space before opening +# parentheses. +# SBPO_ControlStatements (in configuration: ControlStatements) Put a space +# before opening parentheses only after control statement keywords +# (for/if/while...). +# SBPO_Always (in configuration: Always) Always put a space before opening +# parentheses, except when it’s prohibited by the syntax rules (in function-like +# macro definitions) or when determined by other style rules (after unary +# operators, opening parentheses, etc.) +SpaceBeforeParens: ControlStatements + +# If true, spaces may be inserted into ‘()’. +SpaceInEmptyParentheses: false + +# The number of spaces before trailing line comments (// - comments). +# This does not affect trailing block comments (/**/ - comments) as those +# commonly have different usage patterns and a number of special cases. +SpacesBeforeTrailingComments: 2 + +# If true, spaces will be inserted after ‘<’ and before ‘>’ in template argument +# lists +SpacesInAngles: false + +# If true, spaces may be inserted into C style casts. +SpacesInCStyleCastParentheses: false + +# If true, spaces are inserted inside container literals (e.g. ObjC and +# Javascript array and dict literals). +SpacesInContainerLiterals: false + +# If true, spaces will be inserted after ‘(‘ and before ‘)’. +SpacesInParentheses: false + +# If true, spaces will be inserted after ‘[‘ and before ‘]’. +SpacesInSquareBrackets: false + +# Format compatible with this standard, e.g. use A > instead of A> +# for LS_Cpp03. +# LS_Cpp03 (in configuration: Cpp03) Use C++03-compatible syntax. +# LS_Cpp11 (in configuration: Cpp11) Use features of C++11 (e.g. A> +# instead of A >). +# LS_Auto (in configuration: Auto) Automatic detection based on the input. +Standard: Cpp11 + +# The number of columns used for tab stops. +TabWidth: 4 + +# The way to use tab characters in the resulting file. +# UT_Never (in configuration: Never) Never use tab. +# UT_ForIndentation (in configuration: ForIndentation) Use tabs only for +# indentation. +# UT_Always (in configuration: Always) Use tabs whenever we need to fill +# whitespace that spans at least from one tab stop to the next one. +UseTab: Never + +# Indent code enclosed in an extern block +IndentExternBlock: NoIndent diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..7adfeed --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,14 @@ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ + +Checks: '-checks=-*,clang-analyzer-*,-clang-analyzer-cplusplus*' +WarningsAsErrors: true +HeaderFilterRegex: '.*' +FormatStyle: webkit diff --git a/.cppcheck.suppress b/.cppcheck.suppress new file mode 100644 index 0000000..8ce873d --- /dev/null +++ b/.cppcheck.suppress @@ -0,0 +1,4 @@ +cstyleCast +missingInclude +unusedStructMember +throwInEntryPoint diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 0000000..c6f311b --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,15 @@ +name: Build and Test code + +on: + push: + branches: + - main + pull_request: + + +jobs: + call-reusable-workflow: + uses: eclipse-keyple/keyple-actions/.github/workflows/reusable-cpp-build-and-test.yml@main # NOSONAR - Same organization, trusted source + with: + test_executable_name: '' + extra_linux_deps: 'libpcsclite-dev' diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dece72d --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# Build directories +build +out + +# IDE files and directories +CMakeSettings.json +/.vscode/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..e0a7e96 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,47 @@ +#************************************************************************************************** +#* Copyright (c) 2024 Calypso Networks Association https://calypsonet.org/ * +#* * +#* This program and the accompanying materials are made available under the * +#* terms of the MIT License which is available at https://opensource.org/licenses/MIT. * +#* * +#* SPDX-License-Identifier: MIT * +#**************************************************************************************************/ + +fail_fast: false + +repos: + + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.3.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + args: [--markdown-linebreak-ext=md] + + - repo: https://github.com/pocc/pre-commit-hooks + rev: master + hooks: + - id: clang-tidy + name: clang-tidy + entry: clang-tidy -p=build + --system-headers + --fix-errors + + # Code formatting (see .clang-format for config used). + - id: clang-format + name: clang-format + args: [-i] + + # Static code analysis (for C++ files). + - id: cppcheck + name: cppcheck + args: [--enable=all, + --error-exitcode=1, + --language=c++, + --suppressions-list=./.cppcheck.suppress] + files: \.(cpp|hpp)$ + + # Coding style analysis. Based on Google C++ code style. + # cpplint configuration can be found in CPPLINT.cfg. + - id: cpplint diff --git a/CMakeLists.txt b/CMakeLists.txt index d3adf30..c4357a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,27 +1,31 @@ -# ************************************************************************************************* -# Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * -# * -# See the NOTICE file(s) distributed with this work for additional information regarding * -# copyright ownership. * -# * -# This program and the accompanying materials are made available under the terms of the Eclipse * -# Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * -# * -# SPDX-License-Identifier: EPL-2.0 * -# *************************************************************************************************/ - -PROJECT(KeypleCppExample C CXX) -CMAKE_MINIMUM_REQUIRED(VERSION 3.0) - -SET(CMAKE_PROJECT_VERSION_MAJOR "2022") -SET(CMAKE_PROJECT_VERSION_MINOR "11") -SET(CMAKE_PROJECT_VERSION_PATCH "17") -SET(CMAKE_PROJECT_VERSION_TWEAK "2") +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# See the NOTICE file(s) distributed with this work for additional * +# information regarding copyright ownership. * +# * +# This program and the accompanying materials are made available under the * +# terms of the Eclipse * +# * +# Public License 2.0 which is available at * +# http://www.eclipse.org/legal/epl-2.0 * +# * +# SPDX-License-Identifier: EPL-2.0 * +# *****************************************************************************/ + +CMAKE_MINIMUM_REQUIRED(VERSION 3.24) + +PROJECT(KeypleCppExample + VERSION 2024.04.18 + LANGUAGES C CXX) + +SET(CMAKE_PROJECT_VERSION_MAJOR "2024") +SET(CMAKE_PROJECT_VERSION_MINOR "04") +SET(CMAKE_PROJECT_VERSION_PATCH "18") SET(CMAKE_PROJECT_VERSION "${CMAKE_PROJECT_VERSION_MAJOR}. ${CMAKE_PROJECT_VERSION_MINOR}. - ${CMAKE_PROJECT_VERSION_PATCH}. - ${CMAKE_PROJECT_VERSION_TWEAK}") + ${CMAKE_PROJECT_VERSION_PATCH}") SET(PACKAGE_NAME "KeypleCppExample") SET(PACKAGE_VERSION ${CMAKE_PROJECT_VERSION}) @@ -42,21 +46,20 @@ ENDIF() SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +# Include deps +INCLUDE("CMakeLists.txt.keyple-card-calypso") +INCLUDE("CMakeLists.txt.keyple-card-generic") +INCLUDE("CMakeLists.txt.keyple-common") +INCLUDE("CMakeLists.txt.keyple-plugin") +INCLUDE("CMakeLists.txt.keyple-plugin-stub") +INCLUDE("CMakeLists.txt.keyple-plugin-pcsc") +INCLUDE("CMakeLists.txt.keyple-service") +INCLUDE("CMakeLists.txt.keyple-util") +INCLUDE("CMakeLists.txt.keypop-card") +INCLUDE("CMakeLists.txt.keypop-reader") + # Add projects ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/Example_Card_Calypso) ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/Example_Plugin_PCSC) ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/Example_Service) ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/Example_Service_Resource) - -# Dependencies (for later use): -# -# calypsonet-terminal-reader-cpp-api:1.1.+ -# calypsonet-terminal-calypso-cpp-api:1.4.+ -# -# keyple-common-cpp-api:2.0.+ -# keyple-service-cpp-lib:2.1.1 -# keyple-service-resource-cpp-lib:2.0.2 -# keyple-plugin-pcsc-cpp-lib:2.1.0 -# keyple-plugin-stub-cpp-lib:2.1.0 -# keyple-card-calypso-cpp-lib:2.2.5 -# keyple-util-cpp-lib:2.+ diff --git a/CMakeLists.txt.keyple-card-calypso b/CMakeLists.txt.keyple-card-calypso new file mode 100644 index 0000000..8fc60db --- /dev/null +++ b/CMakeLists.txt.keyple-card-calypso @@ -0,0 +1,40 @@ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ + +# FetchContent added in CMake 3.11, downloads during the configure step +# FetchContent_MakeAvailable was added in CMake 3.14; simpler usage +INCLUDE(FetchContent) + +IF(NOT EXISTS "${CMAKE_BINARY_DIR}/_deps/keyplecardcalypsocpplib-src") + + MESSAGE("-- > Fetching keyple card calypso from keyple cpp example") + + # Checkout Keyple Card Calypso Cpp Lib dependency + FetchContent_Declare( + + KeypleCardCalypsoCppLib + + DOWNLOAD_EXTRACT_TIMESTAMP true + GIT_REPOSITORY https://github.com/eclipse-keyple/keyple-card-calypso-cpp-lib + GIT_TAG develop-3.2.2 + ) + +ELSE() + + FetchContent_Declare( + + KeypleCardCalypsoCppLib + + SOURCE_DIR ${CMAKE_BINARY_DIR}/_deps/keyplecardcalypsocpplib-src + ) + +ENDIF() + +FetchContent_MakeAvailable(KeypleCardCalypsoCppLib) diff --git a/CMakeLists.txt.keyple-card-generic b/CMakeLists.txt.keyple-card-generic new file mode 100644 index 0000000..33eebf5 --- /dev/null +++ b/CMakeLists.txt.keyple-card-generic @@ -0,0 +1,40 @@ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ + +# FetchContent added in CMake 3.11, downloads during the configure step +# FetchContent_MakeAvailable was added in CMake 3.14; simpler usage +INCLUDE(FetchContent) + +IF(NOT EXISTS "${CMAKE_BINARY_DIR}/_deps/keyplecardgenericcpplib-src") + + MESSAGE("-- > Fetching keyple card generic from keyple cpp example") + + # Checkout Keyple Card Generic Cpp Lib dependency + FetchContent_Declare( + + KeypleCardGenericCppLib + + DOWNLOAD_EXTRACT_TIMESTAMP true + GIT_REPOSITORY https://github.com/eclipse-keyple/keyple-card-generic-cpp-lib + GIT_TAG develop-3.1.2 + ) + +ELSE() + + FetchContent_Declare( + + KeypleCardGenericCppLib + + SOURCE_DIR ${CMAKE_BINARY_DIR}/_deps/keyplecardgenericcpplib-src + ) + +ENDIF() + +FetchContent_MakeAvailable(KeypleCardGenericCppLib) diff --git a/CMakeLists.txt.keyple-common b/CMakeLists.txt.keyple-common new file mode 100644 index 0000000..42b7e6e --- /dev/null +++ b/CMakeLists.txt.keyple-common @@ -0,0 +1,40 @@ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ + +# FetchContent added in CMake 3.11, downloads during the configure step +# FetchContent_MakeAvailable was added in CMake 3.14; simpler usage +INCLUDE(FetchContent) + +IF(NOT EXISTS "${CMAKE_BINARY_DIR}/_deps/keyplecommoncppapi-src") + + MESSAGE("-- > Fetching keyple common from keyple cpp example") + + # Checkout Keyple Plugin Cpp Api dependency + FetchContent_Declare( + + KeypleCommonCppApi + + DOWNLOAD_EXTRACT_TIMESTAMP true + GIT_REPOSITORY https://github.com/eclipse-keyple/keyple-common-cpp-api + GIT_TAG develop-2.0.2 + ) + +ELSE() + + FetchContent_Declare( + + KeypleCommonCppApi + + SOURCE_DIR ${CMAKE_BINARY_DIR}/_deps/keyplecommoncppapi-src + ) + +ENDIF() + +FetchContent_MakeAvailable(KeypleCommonCppApi) diff --git a/CMakeLists.txt.keyple-plugin b/CMakeLists.txt.keyple-plugin new file mode 100644 index 0000000..cd9bb5d --- /dev/null +++ b/CMakeLists.txt.keyple-plugin @@ -0,0 +1,40 @@ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ + +# FetchContent added in CMake 3.11, downloads during the configure step +# FetchContent_MakeAvailable was added in CMake 3.14; simpler usage +INCLUDE(FetchContent) + +IF(NOT EXISTS "${CMAKE_BINARY_DIR}/_deps/keypleplugincppapi-src") + + MESSAGE("-- > Fetching keyple plugin from keyple cpp example") + + # Checkout Keyple Plugin Cpp Api dependency + FetchContent_Declare( + + KeyplePluginCppApi + + DOWNLOAD_EXTRACT_TIMESTAMP true + GIT_REPOSITORY https://github.com/eclipse-keyple/keyple-plugin-cpp-api + GIT_TAG develop-2.3.2 + ) + +ELSE() + + FetchContent_Declare( + + KeyplePluginCppApi + + SOURCE_DIR ${CMAKE_BINARY_DIR}/_deps/keypleplugincppapi-src + ) + +ENDIF() + +FetchContent_MakeAvailable(KeyplePluginCppApi) diff --git a/CMakeLists.txt.keyple-plugin-pcsc b/CMakeLists.txt.keyple-plugin-pcsc new file mode 100644 index 0000000..ae6f8ad --- /dev/null +++ b/CMakeLists.txt.keyple-plugin-pcsc @@ -0,0 +1,40 @@ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ + +# FetchContent added in CMake 3.11, downloads during the configure step +# FetchContent_MakeAvailable was added in CMake 3.14; simpler usage +INCLUDE(FetchContent) + +IF(NOT EXISTS "${CMAKE_BINARY_DIR}/_deps/keyplepluginpcsccpplib-src") + + MESSAGE("-- > Fetching keyple plugin pcsc from keyple cpp example") + + # Checkout Keyple Plugin Pcsc Cpp Lib dependency + FetchContent_Declare( + + KeyplePluginPcscCppLib + + DOWNLOAD_EXTRACT_TIMESTAMP true + GIT_REPOSITORY https://github.com/eclipse-keyple/keyple-plugin-pcsc-cpp-lib + GIT_TAG develop-2.5.2 + ) + +ELSE() + + FetchContent_Declare( + + KeyplePluginPcscCppLib + + SOURCE_DIR ${CMAKE_BINARY_DIR}/_deps/keyplepluginpcsccpplib-src + ) + +ENDIF() + +FetchContent_MakeAvailable(KeyplePluginPcscCppLib) diff --git a/CMakeLists.txt.keyple-plugin-stub b/CMakeLists.txt.keyple-plugin-stub new file mode 100644 index 0000000..de8970b --- /dev/null +++ b/CMakeLists.txt.keyple-plugin-stub @@ -0,0 +1,40 @@ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ + +# FetchContent added in CMake 3.11, downloads during the configure step +# FetchContent_MakeAvailable was added in CMake 3.14; simpler usage +INCLUDE(FetchContent) + +IF(NOT EXISTS "${CMAKE_BINARY_DIR}/_deps/keyplepluginstubcpplib-src") + + MESSAGE("-- > Fetching keyple plugin stub from keyple cpp example") + + # Checkout Keyple Plugin Stub Cpp Lib dependency + FetchContent_Declare( + + KeyplePluginStubCppLib + + DOWNLOAD_EXTRACT_TIMESTAMP true + GIT_REPOSITORY https://github.com/eclipse-keyple/keyple-plugin-stub-cpp-lib + GIT_TAG develop-2.2.1 + ) + +ELSE() + + FetchContent_Declare( + + KeyplePluginStubCppLib + + SOURCE_DIR ${CMAKE_BINARY_DIR}/_deps/keyplepluginstubcpplib-src + ) + +ENDIF() + +FetchContent_MakeAvailable(KeyplePluginStubCppLib) diff --git a/CMakeLists.txt.keyple-service b/CMakeLists.txt.keyple-service new file mode 100644 index 0000000..c0367fe --- /dev/null +++ b/CMakeLists.txt.keyple-service @@ -0,0 +1,40 @@ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ + +# FetchContent added in CMake 3.11, downloads during the configure step +# FetchContent_MakeAvailable was added in CMake 3.14; simpler usage +INCLUDE(FetchContent) + +IF(NOT EXISTS "${CMAKE_BINARY_DIR}/_deps/keypleservicecpplib-src") + + MESSAGE("-- > Fetching keyple service from keyple cpp example") + + # Checkout Keyple Service Cpp Lib dependency + FetchContent_Declare( + + KeypleServiceCppLib + + DOWNLOAD_EXTRACT_TIMESTAMP true + GIT_REPOSITORY https://github.com/eclipse-keyple/keyple-service-cpp-lib + GIT_TAG fix-executor + ) + +ELSE() + + FetchContent_Declare( + + KeypleServiceCppLib + + SOURCE_DIR ${CMAKE_BINARY_DIR}/_deps/keypleservicecpplib-src + ) + +ENDIF() + +FetchContent_MakeAvailable(KeypleServiceCppLib) diff --git a/CMakeLists.txt.keyple-util b/CMakeLists.txt.keyple-util new file mode 100644 index 0000000..65ff4cf --- /dev/null +++ b/CMakeLists.txt.keyple-util @@ -0,0 +1,44 @@ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ + +# FetchContent added in CMake 3.11, downloads during the configure step +# FetchContent_MakeAvailable was added in CMake 3.14; simpler usage +INCLUDE(FetchContent) + +IF(NOT EXISTS "${CMAKE_BINARY_DIR}/_deps/keypleutilcpplib-src") + + MESSAGE("-- > Fetching keyple util from keyple cpp example") + + # FetchContent added in CMake 3.11, downloads during the configure step + # FetchContent_MakeAvailable was added in CMake 3.14; simpler usage + INCLUDE(FetchContent) + + # Checkout Keyple Util Cpp Lib dependency + FetchContent_Declare( + + KeypleUtilCppLib + + DOWNLOAD_EXTRACT_TIMESTAMP true + GIT_REPOSITORY https://github.com/eclipse-keyple/keyple-util-cpp-lib + GIT_TAG develop-2.4.0 + ) + +ELSE() + + FetchContent_Declare( + + KeypleUtilCppLib + + SOURCE_DIR ${CMAKE_BINARY_DIR}/_deps/keypleutilcpplib-src + ) + +ENDIF() + +FetchContent_MakeAvailable(KeypleUtilCppLib) diff --git a/CMakeLists.txt.keypop-card b/CMakeLists.txt.keypop-card new file mode 100644 index 0000000..79794ba --- /dev/null +++ b/CMakeLists.txt.keypop-card @@ -0,0 +1,40 @@ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ + +# FetchContent added in CMake 3.11, downloads during the configure step +# FetchContent_MakeAvailable was added in CMake 3.14; simpler usage +INCLUDE(FetchContent) + +IF(NOT EXISTS "${CMAKE_BINARY_DIR}/_deps/keypopcardcppapi-src") + + MESSAGE("-- > Fetching keypop card from keyple cpp example") + + # Checkout Keypop Card Cpp Api dependency + FetchContent_Declare( + + KeypopCardCppApi + + DOWNLOAD_EXTRACT_TIMESTAMP true + GIT_REPOSITORY https://github.com/eclipse-keypop/keypop-card-cpp-api + GIT_TAG develop-2.0.1 + ) + +ELSE() + + FetchContent_Declare( + + KeypopCardCppApi + + SOURCE_DIR ${CMAKE_BINARY_DIR}/_deps/keypopcardcppapi-src + ) + +ENDIF() + +FetchContent_MakeAvailable(KeypopCardCppApi) diff --git a/CMakeLists.txt.keypop-reader b/CMakeLists.txt.keypop-reader new file mode 100644 index 0000000..0fc9622 --- /dev/null +++ b/CMakeLists.txt.keypop-reader @@ -0,0 +1,40 @@ +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# This program and the accompanying materials are made available under the * +# terms of the MIT License which is available at * +# https://opensource.org/licenses/MIT. * +# * +# SPDX-License-Identifier: MIT * +# *****************************************************************************/ + +# FetchContent added in CMake 3.11, downloads during the configure step +# FetchContent_MakeAvailable was added in CMake 3.14; simpler usage +INCLUDE(FetchContent) + +IF(NOT EXISTS "${CMAKE_BINARY_DIR}/_deps/keypopreadercppapi-src") + + MESSAGE("-- > Fetching keypop reader from keyple cpp example") + + # Checkout Keypop Reader Cpp Api dependency + FetchContent_Declare( + + KeypopReaderCppApi + + DOWNLOAD_EXTRACT_TIMESTAMP true + GIT_REPOSITORY https://github.com/eclipse-keypop/keypop-reader-cpp-api + GIT_TAG 2.1.0 + ) + +ELSE() + + FetchContent_Declare( + + KeypopReaderCppApi + + SOURCE_DIR ${CMAKE_BINARY_DIR}/_deps/keypopreadercppapi-src + ) + +ENDIF() + +FetchContent_MakeAvailable(KeypopReaderCppApi) diff --git a/CPPLINT.cfg b/CPPLINT.cfg new file mode 100644 index 0000000..c277a75 --- /dev/null +++ b/CPPLINT.cfg @@ -0,0 +1,18 @@ +#****************************************************************************** +#* Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +#* * +#* See the NOTICE file(s) distributed with this work for additional * +#* information regarding copyright ownership. * +#* * +#* This program and the accompanying materials are made available under the * +#* terms of the Eclipse * +#* * +#* Eclipse Distribution License 1.0 which is available at * +#* https://www.eclipse.org/org/documents/edl-v10.php * +#* * +#* SPDX-License-Identifier: BSD-3-Clause * +#******************************************************************************/ + +set noparent +filter=-whitespace/indent,-build/c++11,-runtime/references,-whitespace/braces,-whitespace/blank_line,-runtime/string,-build/include_subdir +linelength=80 diff --git a/Example_Card_Calypso/CMakeLists.txt b/Example_Card_Calypso/CMakeLists.txt index eed323b..fd2f71f 100644 --- a/Example_Card_Calypso/CMakeLists.txt +++ b/Example_Card_Calypso/CMakeLists.txt @@ -1,225 +1,394 @@ -# ************************************************************************************************* -# Copyright (c) 2021 Calypso Networks Association https://calypsonet.org/ * -# * -# See the NOTICE file(s) distributed with this work for additional information regarding * -# copyright ownership. * -# * -# This program and the accompanying materials are made available under the terms of the Eclipse * -# Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * -# * -# SPDX-License-Identifier: EPL-2.0 * -# *************************************************************************************************/ - - -SET(CALYPSONET_CALYPSO_DIR "../../calypsonet-terminal-calypso-cpp-api") -SET(CALYPSONET_CARD_DIR "../../calypsonet-terminal-card-cpp-api") -SET(CALYPSONET_READER_DIR "../../calypsonet-terminal-reader-cpp-api") -SET(KEYPLE_CALYPSO_DIR "../../keyple-card-calypso-cpp-lib") -SET(KEYPLE_COMMON_DIR "../../keyple-common-cpp-api") -SET(KEYPLE_PLUGIN_DIR "../../keyple-plugin-cpp-api") -SET(KEYPLE_PCSC_DIR "../../keyple-plugin-pcsc-cpp-lib") -SET(KEYPLE_RESOURCE_DIR "../../keyple-service-resource-cpp-lib") -SET(KEYPLE_SERVICE_DIR "../../keyple-service-cpp-lib") -SET(KEYPLE_STUB_DIR "../../keyple-plugin-stub-cpp-lib") -SET(KEYPLE_UTIL_DIR "../../keyple-util-cpp-lib") - -SET(KEYPLE_CALYPSO_LIB "keyplecardcalypsocpplib") -SET(KEYPLE_PCSC_LIB "keyplepluginpcsccpplib") -SET(KEYPLE_RESOURCE_LIB "keypleserviceresourcecpplib") -SET(KEYPLE_SERVICE_LIB "keypleservicecpplib") -SET(KEYPLE_STUB_LIB "keyplepluginstubcpplib") -SET(KEYPLE_UTIL_LIB "keypleutilcpplib") +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# See the NOTICE file(s) distributed with this work for additional * +# information regarding copyright ownership. * +# * +# This program and the accompanying materials are made available under the * +# terms of the Eclipse Distribution License 1.0 which is available at * +# https://www.eclipse.org/org/documents/edl-v10.php * +# * +# SPDX-License-Identifier: BSD-3-Clause * +# *****************************************************************************/ + INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/spi + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/ +) - ${CALYPSONET_CALYPSO_DIR}/src/main - ${CALYPSONET_CALYPSO_DIR}/src/main/card - ${CALYPSONET_CALYPSO_DIR}/src/main/sam - ${CALYPSONET_CALYPSO_DIR}/src/main/spi - ${CALYPSONET_CALYPSO_DIR}/src/main/transaction +SET(USECASE1 UseCase1_ExplicitSelectionAid) +SET(USECASE1_STUB ${USECASE1}_Stub) +ADD_EXECUTABLE( - ${CALYPSONET_CARD_DIR}/src/main - ${CALYPSONET_CARD_DIR}/src/main/spi + ${USECASE1_STUB} - ${CALYPSONET_READER_DIR}/src/main - ${CALYPSONET_READER_DIR}/src/main/selection - ${CALYPSONET_READER_DIR}/src/main/selection/spi - ${CALYPSONET_READER_DIR}/src/main/spi + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/StubSmartCardFactory.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE1}/Main_ExplicitSelectionAid_Stub.cpp +) +TARGET_LINK_LIBRARIES( - ${KEYPLE_CALYPSO_DIR}/src/main + ${USECASE1_STUB} - ${KEYPLE_CARD_DIR}/src/main + Keyple::Card::Generic + Keyple::Plugin::Stub + Keyple::Service + Keyple::Util + Keyple::Card::Calypso +) - ${KEYPLE_COMMON_DIR}/src/main +SET(USECASE1_PCSC ${USECASE1}_Pcsc) +ADD_EXECUTABLE( + + ${USECASE1_PCSC} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE1}/Main_ExplicitSelectionAid_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE1_PCSC} - ${KEYPLE_PCSC_DIR}/src/main + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Util + Keyple::Card::Calypso +) - ${KEYPLE_PLUGIN_DIR}/src/main - ${KEYPLE_PLUGIN_DIR}/src/main/spi - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader/observable/ - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader/observable/state/insertion - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader/observable/state/processing - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader/observable/state/removal +SET(USECASE2 UseCase2_ScheduledSelection) +SET(USECASE2_STUB ${USECASE2}_Stub) +ADD_EXECUTABLE( - ${KEYPLE_RESOURCE_DIR}/src/main - ${KEYPLE_RESOURCE_DIR}/src/main/spi + ${USECASE2_STUB} - ${KEYPLE_SERVICE_DIR}/src/main - ${KEYPLE_SERVICE_DIR}/src/main/cpp - ${KEYPLE_SERVICE_DIR}/src/main/spi + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/StubSmartCardFactory.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE2}/CardReaderObserver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE2}/Main_ScheduledSelection_Stub.cpp +) +TARGET_LINK_LIBRARIES( - ${KEYPLE_STUB_DIR}/src/main - ${KEYPLE_STUB_DIR}/src/main/spi + ${USECASE2_STUB} - ${KEYPLE_UTIL_DIR}/src/main - ${KEYPLE_UTIL_DIR}/src/main/cpp - ${KEYPLE_UTIL_DIR}/src/main/cpp/exception - ${KEYPLE_UTIL_DIR}/src/main/protocol + Keyple::Card::Generic + Keyple::Plugin::Stub + Keyple::Service + Keyple::Util + Keyple::Card::Calypso ) -IF(APPLE OR UNIX) - SET(THREAD_LIB pthread) -ELSE() -ENDIF(APPLE OR UNIX) +SET(USECASE2_PCSC ${USECASE2}_Pcsc) +ADD_EXECUTABLE( -SET(USECASE1 UseCase1_ExplicitSelectionAid) -SET(USECASE1_STUB ${USECASE1}_Stub) -ADD_EXECUTABLE(${USECASE1_STUB} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/StubSmartCardFactory.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE1}/Main_ExplicitSelectionAid_Stub.cpp) -TARGET_LINK_LIBRARIES(${USECASE1_STUB} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_STUB_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${THREAD_LIB}) + ${USECASE2_PCSC} -SET(USECASE1_PCSC ${USECASE1}_Pcsc) -ADD_EXECUTABLE(${USECASE1_PCSC} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE1}/Main_ExplicitSelectionAid_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE1_PCSC} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${KEYPLE_RESOURCE_LIB} ${THREAD_LIB}) + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE2}/CardReaderObserver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE2}/Main_ScheduledSelection_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( -SET(USECASE2 UseCase2_ScheduledSelection) -SET(USECASE2_STUB ${USECASE2}_Stub) -ADD_EXECUTABLE(${USECASE2_STUB} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/StubSmartCardFactory.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE2}/CardReaderObserver.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE2}/Main_ScheduledSelection_Stub.cpp) -TARGET_LINK_LIBRARIES(${USECASE2_STUB} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_STUB_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${KEYPLE_RESOURCE_LIB} ${THREAD_LIB}) + ${USECASE2_PCSC} -SET(USECASE2_PCSC ${USECASE2}_Pcsc) -ADD_EXECUTABLE(${USECASE2_PCSC} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE2}/CardReaderObserver.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE2}/Main_ScheduledSelection_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE2_PCSC} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${KEYPLE_RESOURCE_LIB} ${THREAD_LIB}) + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Util + Keyple::Card::Calypso +) SET(USECASE3 UseCase3_Rev1Selection) SET(USECASE3_PCSC ${USECASE3}_Pcsc) -ADD_EXECUTABLE(${USECASE3_PCSC} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE3}/Main_Rev1Selection_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE3_PCSC} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${KEYPLE_RESOURCE_LIB} ${THREAD_LIB}) +ADD_EXECUTABLE( + + ${USECASE3_PCSC} + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE3}/Main_Rev1Selection_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE3_PCSC} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Util + Keyple::Card::Calypso +) SET(USECASE4 UseCase4_CardAuthentication) SET(USECASE4_STUB ${USECASE4}_Stub) -ADD_EXECUTABLE(${USECASE4_STUB} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/StubSmartCardFactory.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE4}/Main_CardAuthentication_Stub.cpp) -TARGET_LINK_LIBRARIES(${USECASE4_STUB} ${KEYPLE_CARD_LIB} ${KEYPLE_STUB_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${KEYPLE_RESOURCE_LIB} ${THREAD_LIB}) +ADD_EXECUTABLE( + + ${USECASE4_STUB} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/StubSmartCardFactory.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE4}/Main_CardAuthentication_Stub.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE4_STUB} + + Keyple::Card::Generic + Keyple::Plugin::Stub + Keyple::Service + Keyple::Service::Resource + Keyple::Util + Keyple::Card::Calypso + Keyple::Card::Calypso::Crypto::LegacySam +) SET(USECASE4_PCSC ${USECASE4}_Pcsc) -ADD_EXECUTABLE(${USECASE4_PCSC} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE4}/Main_CardAuthentication_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE4_PCSC} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${KEYPLE_RESOURCE_LIB} ${THREAD_LIB}) +ADD_EXECUTABLE( + + ${USECASE4_PCSC} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE4}/Main_CardAuthentication_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE4_PCSC} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Service::Resource + Keyple::Util + Keyple::Card::Calypso + Keyple::Card::Calypso::Crypto::LegacySam +) SET(USECASE4_PCSC_SAM_RESOURCE ${USECASE4}_Pcsc_SamResourceService) -ADD_EXECUTABLE(${USECASE4_PCSC_SAM_RESOURCE} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE4}/Main_CardAuthentication_Pcsc_SamResourceService.cpp) -TARGET_LINK_LIBRARIES(${USECASE4_PCSC_SAM_RESOURCE} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${KEYPLE_RESOURCE_LIB} ${THREAD_LIB}) +ADD_EXECUTABLE( + + ${USECASE4_PCSC_SAM_RESOURCE} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE4}/Main_CardAuthentication_Pcsc_SamResourceService.cpp +) +TARGET_LINK_LIBRARIES( + ${USECASE4_PCSC_SAM_RESOURCE} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Service::Resource + Keyple::Util + Keyple::Card::Calypso + Keyple::Card::Calypso::Crypto::LegacySam +) SET(USECASE5 UseCase5_MultipleSession) SET(USECASE5_PCSC ${USECASE5}_Pcsc) -ADD_EXECUTABLE(${USECASE5_PCSC} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE5}/Main_MultipleSession_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE5_PCSC} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${KEYPLE_RESOURCE_LIB} ${THREAD_LIB}) +ADD_EXECUTABLE( + + ${USECASE5_PCSC} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE5}/Main_MultipleSession_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE5_PCSC} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Service::Resource + Keyple::Util + Keyple::Card::Calypso + Keyple::Card::Calypso::Crypto::LegacySam +) SET(USECASE6 UseCase6_VerifyPin) SET(USECASE6_PCSC ${USECASE6}_Pcsc) -ADD_EXECUTABLE(${USECASE6_PCSC} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE6}/Main_VerifyPin_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE6_PCSC} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${KEYPLE_RESOURCE_LIB} ${THREAD_LIB}) +ADD_EXECUTABLE( + + ${USECASE6_PCSC} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE6}/Main_VerifyPin_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE6_PCSC} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Service::Resource + Keyple::Util + Keyple::Card::Calypso + Keyple::Card::Calypso::Crypto::LegacySam +) SET(USECASE7 UseCase7_StoredValue_SimpleReloading) SET(USECASE7_PCSC ${USECASE7}_Pcsc) -ADD_EXECUTABLE(${USECASE7_PCSC} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE7}/Main_StoredValue_SimpleReloading_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE7_PCSC} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${KEYPLE_RESOURCE_LIB} ${THREAD_LIB}) +ADD_EXECUTABLE( + + ${USECASE7_PCSC} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE7}/Main_StoredValue_SimpleReloading_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE7_PCSC} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Service::Resource + Keyple::Util + Keyple::Card::Calypso + Keyple::Card::Calypso::Crypto::LegacySam +) SET(USECASE8 UseCase8_StoredValue_DebitInSession) SET(USECASE8_PCSC ${USECASE8}_Pcsc) -ADD_EXECUTABLE(${USECASE8_PCSC} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE8}/Main_StoredValue_DebitInSession_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE8_PCSC} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${KEYPLE_RESOURCE_LIB} ${THREAD_LIB}) +ADD_EXECUTABLE( + + ${USECASE8_PCSC} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE8}/Main_StoredValue_DebitInSession_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE8_PCSC} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Service::Resource + Keyple::Util + Keyple::Card::Calypso + Keyple::Card::Calypso::Crypto::LegacySam +) SET(USECASE9 UseCase9_ChangePin) SET(USECASE9_PCSC ${USECASE9}_Pcsc) -ADD_EXECUTABLE(${USECASE9_PCSC} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE9}/Main_ChangePin_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE9_PCSC} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${KEYPLE_RESOURCE_LIB} ${THREAD_LIB}) +ADD_EXECUTABLE( + + ${USECASE9_PCSC} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE9}/Main_ChangePin_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE9_PCSC} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Service::Resource + Keyple::Util + Keyple::Card::Calypso + Keyple::Card::Calypso::Crypto::LegacySam +) SET(USECASE10 UseCase10_SessionTrace_TN313) SET(USECASE10_PCSC ${USECASE10}_Pcsc) -ADD_EXECUTABLE(${USECASE10_PCSC} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE10}/CardReaderObserver.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE10}/Main_SessionTrace_TN313_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE10_PCSC} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${KEYPLE_RESOURCE_LIB} ${THREAD_LIB}) +ADD_EXECUTABLE( + + ${USECASE10_PCSC} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE10}/CardReaderObserver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE10}/Main_SessionTrace_TN313_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE10_PCSC} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Service::Resource + Keyple::Util + Keyple::Card::Calypso + Keyple::Card::Calypso::Crypto::LegacySam +) SET(USECASE11 UseCase11_DataSigning) SET(USECASE11_PCSC ${USECASE11}_Pcsc) -ADD_EXECUTABLE(${USECASE11_PCSC} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE11}/Main_DataSigning_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE11_PCSC} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${KEYPLE_RESOURCE_LIB} ${THREAD_LIB}) +ADD_EXECUTABLE( + + ${USECASE11_PCSC} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE11}/Main_DataSigning_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE11_PCSC} + + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Service::Resource + Keyple::Util + Keyple::Card::Calypso + Keyple::Card::Calypso::Crypto::LegacySam +) SET(USECASE12 UseCase12_PerformanceMeasurement_EmbeddedValidation) SET(USECASE12_PCSC ${USECASE12}_Pcsc) -ADD_EXECUTABLE(${USECASE12_PCSC} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE12}/Main_PerformanceMeasurement_EmbeddedValidation_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE12_PCSC} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${KEYPLE_RESOURCE_LIB} ${THREAD_LIB}) +ADD_EXECUTABLE( + + ${USECASE12_PCSC} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE12}/Main_PerformanceMeasurement_EmbeddedValidation_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE12_PCSC} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Service::Resource + Keyple::Util + Keyple::Card::Calypso + Keyple::Card::Calypso::Crypto::LegacySam +) SET(USECASE13 UseCase13_PerformanceMeasurement_DistributedReloading) SET(USECASE13_PCSC ${USECASE13}_Pcsc) -ADD_EXECUTABLE(${USECASE13_PCSC} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE13}/Main_PerformanceMeasurement_DistributedReloading_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE13_PCSC} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB} ${KEYPLE_CALYPSO_LIB} ${KEYPLE_RESOURCE_LIB} ${THREAD_LIB}) +ADD_EXECUTABLE( + + ${USECASE13_PCSC} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/CalypsoConstants.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE13}/Main_PerformanceMeasurement_DistributedReloading_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE13_PCSC} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Service::Resource + Keyple::Util + Keyple::Card::Calypso + Keyple::Card::Calypso::Crypto::LegacySam +) diff --git a/Example_Card_Calypso/src/main/UseCase10_SessionTrace_TN313/CardReaderObserver.cpp b/Example_Card_Calypso/src/main/UseCase10_SessionTrace_TN313/CardReaderObserver.cpp index 8fd9e93..375419f 100644 --- a/Example_Card_Calypso/src/main/UseCase10_SessionTrace_TN313/CardReaderObserver.cpp +++ b/Example_Card_Calypso/src/main/UseCase10_SessionTrace_TN313/CardReaderObserver.cpp @@ -1,156 +1,195 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -#include "CardReaderObserver.h" - -/* Calypsonet Terminal Calypso */ -#include "CalypsoCard.h" -#include "CardTransactionManager.h" - -/* Calypsonet Terminal Reader */ -#include "ObservableCardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Util */ -#include "System.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" - -using namespace calypsonet::terminal::calypso::card; -using namespace calypsonet::terminal::calypso::transaction; -using namespace calypsonet::terminal::reader; -using namespace keyple::card::calypso; -using namespace keyple::core::service; -using namespace keyple::core::util::cpp; - -const std::string CardReaderObserver::ANSI_RESET = "\u001B[0m"; -const std::string CardReaderObserver::ANSI_BLACK = "\u001B[30m"; -const std::string CardReaderObserver::ANSI_RED = "\u001B[31m"; -const std::string CardReaderObserver::ANSI_GREEN = "\u001B[32m"; -const std::string CardReaderObserver::ANSI_YELLOW = "\u001B[33m"; -const std::string CardReaderObserver::ANSI_BLUE = "\u001B[34m"; -const std::string CardReaderObserver::ANSI_PURPLE = "\u001B[35m"; -const std::string CardReaderObserver::ANSI_CYAN = "\u001B[36m"; -const std::string CardReaderObserver::ANSI_WHITE = "\u001B[37m"; - -CardReaderObserver::CardReaderObserver(std::shared_ptr cardReader, - std::shared_ptr cardSelectionManager, - std::shared_ptr cardSecuritySetting) -: mCardReader(cardReader), - mCardSecuritySetting(cardSecuritySetting), - mCardSelectionManager(cardSelectionManager) {} - -void CardReaderObserver::onReaderEvent(const std::shared_ptr event) -{ +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include "CardReaderObserver.hpp" + +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keypop/calypso/card/WriteAccessLevel.hpp" +#include "keypop/calypso/card/card/CalypsoCard.hpp" +#include "keypop/calypso/card/cpp/SecureRegularModeTransactionManagerBase.hpp" +#include "keypop/calypso/card/transaction/SecureSymmetricCryptoTransactionManager.hpp" +#include "keypop/reader/ChannelControl.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::core::util::HexUtil; +using keypop::calypso::card::WriteAccessLevel; +using keypop::calypso::card::card::CalypsoCard; +using keypop::calypso::card::cpp::SecureRegularModeTransactionManagerBase; +using keypop::calypso::card::transaction:: + SecureSymmetricCryptoTransactionManager; +using keypop::reader::ChannelControl; +using keypop::reader::selection::spi::SmartCard; + +/* File identifiers */ +static const std::uint8_t SFI_ENVIRONMENT_AND_HOLDER = 0x07; +static const std::uint8_t SFI_EVENT_LOG = 0x08; +static const std::uint8_t SFI_CONTRACT_LIST = 0x1E; +static const std::uint8_t SFI_CONTRACTS = 0x09; +static const int RECORD_SIZE = 29; + +static const std::string ANSI_RESET = "\033[0m"; +static const std::string ANSI_RED = "\033[31m"; +static const std::string ANSI_GREEN = "\033[32m"; + +CardReaderObserver::CardReaderObserver( + std::shared_ptr plugin, + std::shared_ptr cardReader, + std::shared_ptr cardSelectionManager, + std::shared_ptr cardSecuritySetting) +: mPlugin(plugin) +, mCardReader(cardReader) +, mCardSelectionManager(cardSelectionManager) +, mCardSecuritySetting(cardSecuritySetting) +, mCalypsoCardApiFactory( + CalypsoExtensionService::getInstance()->getCalypsoCardApiFactory()) +, mNewEventRecord( + HexUtil::toByteArray( + "8013C8EC55667788112233445566778811223344556677881122334455")) { +} + +void +CardReaderObserver::onReaderEvent( + const std::shared_ptr event) { switch (event->getType()) { - case CardReaderEvent::Type::CARD_MATCHED: - { + case CardReaderEvent::CARD_MATCHED: { /* Read the current time used later to compute the transaction time */ - const unsigned long long timeStamp = System::currentTimeMillis(); - + const auto timeStamp = std::chrono::steady_clock::now(); try { /* The selection matched, get the resulting CalypsoCard */ - auto calypsoCard = - std::dynamic_pointer_cast( - mCardSelectionManager - ->parseScheduledCardSelectionsResponse( - event->getScheduledCardSelectionsResponse()) - ->getActiveSmartCard()); + const std::shared_ptr smartCard( + mCardSelectionManager + ->parseScheduledCardSelectionsResponse( + event->getScheduledCardSelectionsResponse()) + ->getActiveSmartCard()); + auto calypsoCard + = std::dynamic_pointer_cast(smartCard); /* - * Create a transaction manager, open a Secure Session, read Environment, Event Log and - * Contract List. + * Create a transaction manager, open a Secure Session, read + * Environment, Event Log and Contract List. + * Specifying expected response lengths in read commands serves + * as a protective measure for legacy cards. + * + * The keypop API declares + * createSecureRegularModeTransactionManager() as returning a + * SecureRegularModeTransactionManagerBase, which does not itself + * expose prepareOpenSecureSession() (it's only declared on + * SecureSymmetricCryptoTransactionManager, a sibling + * interface implemented by the same concrete object). A + * downcast is required to reach it. */ - std::shared_ptr cardTransactionManager = - CalypsoExtensionService::getInstance() - ->createCardTransaction(mCardReader, calypsoCard, mCardSecuritySetting); - cardTransactionManager->prepareReadRecords(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_SIZE) - .prepareReadRecords(CalypsoConstants::SFI_EVENT_LOG, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_SIZE) - .prepareReadRecords(CalypsoConstants::SFI_CONTRACT_LIST, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_SIZE) - .processOpening(WriteAccessLevel::DEBIT); - - /* - * Place for the analysis of the context and the list of contracts + std::unique_ptr + cardTransactionManagerBase( + mCalypsoCardApiFactory + ->createSecureRegularModeTransactionManager( + mCardReader, calypsoCard, mCardSecuritySetting)); + + auto cardTransactionManager + = dynamic_cast*>( + cardTransactionManagerBase.get()); + + cardTransactionManager + ->prepareOpenSecureSession(WriteAccessLevel::DEBIT) + .prepareReadRecords( + SFI_ENVIRONMENT_AND_HOLDER, 1, 1, RECORD_SIZE) + .prepareReadRecords(SFI_EVENT_LOG, 1, 1, RECORD_SIZE) + .prepareReadRecords(SFI_CONTRACT_LIST, 1, 1, RECORD_SIZE) + .processCommands(ChannelControl::KEEP_OPEN); + + /* Place for the analysis of the context and the list of contracts */ - /* Read the elected contract */ - cardTransactionManager->prepareReadRecords(CalypsoConstants::SFI_CONTRACTS, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_SIZE) - .processCommands(); - /* - * Place for the analysis of the contracts + * Read the elected contract. + * Specifying expected response lengths in read commands serves + * as a protective measure for legacy cards. */ + cardTransactionManagerBase + ->prepareReadRecords(SFI_CONTRACTS, 1, 1, RECORD_SIZE) + .processCommands(ChannelControl::KEEP_OPEN); + + /* Place for the analysis of the contracts */ /* Add an event record and close the Secure Session */ - cardTransactionManager->prepareAppendRecord(CalypsoConstants::SFI_EVENT_LOG, - mNewEventRecord) - .processClosing(); + cardTransactionManagerBase + ->prepareAppendRecord(SFI_EVENT_LOG, mNewEventRecord) + .prepareCloseSecureSession() + .processCommands(ChannelControl::CLOSE_AFTER); /* Display transaction time */ - mLogger->info("%Transaction succeeded. Execution time: % ms%\n", - ANSI_GREEN, - System::currentTimeMillis() - timeStamp, - ANSI_RESET); - - } catch (const Exception& e) { - mLogger->error("%Transaction failed with exception: %%\n", - ANSI_RED, - e.getMessage(), - ANSI_RESET); - } + const auto elapsedMs + = std::chrono::duration_cast( + std::chrono::steady_clock::now() - timeStamp) + .count(); + mLogger->info( + "%Transaction succeeded. Execution time: % ms%\n", + ANSI_GREEN, + elapsedMs, + ANSI_RESET); + + /* Optimization: preload the SAM challenge for the next transaction + */ + mCardSecuritySetting->initCryptoContextForNextTransaction(); + + } catch (const std::exception& e) { + mLogger->error( + "%Transaction failed with exception: %%\n", + ANSI_RED, + e.what(), + ANSI_RESET); } - break; + } break; - case CardReaderEvent::Type::CARD_INSERTED: - mLogger->error("CARD_INSERTED event: should not have occurred because of the MATCHED_ONLY " \ - "selection mode chosen\n"); + case CardReaderEvent::CARD_INSERTED: + mLogger->error( + "CARD_INSERTED event: should not have occurred because of the " + "MATCHED_ONLY selection mode chosen\n"); break; - case CardReaderEvent::Type::CARD_REMOVED: + case CardReaderEvent::CARD_REMOVED: mLogger->info("Card removed\n"); break; + default: break; } - if (event->getType() == CardReaderEvent::Type::CARD_INSERTED || - event->getType() == CardReaderEvent::Type::CARD_MATCHED) { - + if (event->getType() == CardReaderEvent::CARD_INSERTED + || event->getType() == CardReaderEvent::CARD_MATCHED) { /* - * Informs the underlying layer of the end of the card processing, in order to manage the - * removal sequence. - */ - std::dynamic_pointer_cast(mCardReader)->finalizeCardProcessing(); + * Informs the underlying layer of the end of the card processing, in + * order to manage the removal sequence. + */ + mCardReader->finalizeCardProcessing(); } } -void CardReaderObserver::onReaderObservationError(const std::string& pluginName, - const std::string& readerName, - const std::shared_ptr e) -{ - mLogger->error("An exception occurred in plugin '%', reader '%'\n", pluginName, readerName, e); +void +CardReaderObserver::onReaderObservationError( + const std::string& pluginName, + const std::string& readerName, + const std::shared_ptr e) { + mLogger->error( + "An exception occurred in plugin '%', reader '%'\n", + pluginName, + readerName, + e); } diff --git a/Example_Card_Calypso/src/main/UseCase10_SessionTrace_TN313/CardReaderObserver.h b/Example_Card_Calypso/src/main/UseCase10_SessionTrace_TN313/CardReaderObserver.h deleted file mode 100644 index 0b84d3c..0000000 --- a/Example_Card_Calypso/src/main/UseCase10_SessionTrace_TN313/CardReaderObserver.h +++ /dev/null @@ -1,106 +0,0 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -#pragma once - -/* Calypsonet Terminal Calypso */ -#include "CardSecuritySetting.h" - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" -#include "CardReaderObserverSpi.h" -#include "CardReaderObservationExceptionHandlerSpi.h" -#include "CardSelectionManager.h" - -/* Keyple Core Util */ -#include "HexUtil.h" -#include "LoggerFactory.h" - -using namespace calypsonet::terminal::calypso::transaction; -using namespace calypsonet::terminal::reader; -using namespace calypsonet::terminal::reader::selection; -using namespace calypsonet::terminal::reader::spi; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; - -/** - * (package-private) - * - *

A reader Observer handles card event such as CARD_INSERTED, CARD_MATCHED, CARD_REMOVED - */ -class CardReaderObserver final -: public CardReaderObserverSpi, public CardReaderObservationExceptionHandlerSpi { -public: - /** - * (package-private)
- * Constructor. - * - * @param cardReader The card reader. - * @param cardSelectionManager The card selection manager. - * @param cardSecuritySetting The card security settings. - */ - CardReaderObserver(std::shared_ptr cardReader, - std::shared_ptr cardSelectionManager, - std::shared_ptr cardSecuritySetting); - - /** - * {@inheritDoc} - */ - void onReaderEvent(const std::shared_ptr event) override; - - /** - * {@inheritDoc} - */ - void onReaderObservationError(const std::string& pluginName, - const std::string& readerName, - const std::shared_ptr e) override; - -private: - /** - * - */ - const std::unique_ptr mLogger = LoggerFactory::getLogger(typeid(CardReaderObserver)); - - /** - * - */ - std::shared_ptr mCardReader; - - /** - * - */ - std::shared_ptr mCardSecuritySetting; - - /** - * - */ - std::shared_ptr mCardSelectionManager; - - /** - * - */ - const std::vector mNewEventRecord = - HexUtil::toByteArray("8013C8EC55667788112233445566778811223344556677881122334455"); - - /** - * - */ - static const std::string ANSI_RESET; - static const std::string ANSI_BLACK; - static const std::string ANSI_RED; - static const std::string ANSI_GREEN; - static const std::string ANSI_YELLOW; - static const std::string ANSI_BLUE; - static const std::string ANSI_PURPLE; - static const std::string ANSI_CYAN; - static const std::string ANSI_WHITE; -}; diff --git a/Example_Card_Calypso/src/main/UseCase10_SessionTrace_TN313/CardReaderObserver.hpp b/Example_Card_Calypso/src/main/UseCase10_SessionTrace_TN313/CardReaderObserver.hpp new file mode 100644 index 0000000..996f16a --- /dev/null +++ b/Example_Card_Calypso/src/main/UseCase10_SessionTrace_TN313/CardReaderObserver.hpp @@ -0,0 +1,115 @@ +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#pragma once + +#include +#include +#include +#include + +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/transaction/SymmetricCryptoSecuritySetting.hpp" +#include "keypop/reader/CardReaderEvent.hpp" +#include "keypop/reader/ObservableCardReader.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/spi/CardReaderObservationExceptionHandlerSpi.hpp" +#include "keypop/reader/spi/CardReaderObserverSpi.hpp" + +using keyple::core::service::Plugin; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::transaction::SymmetricCryptoSecuritySetting; +using keypop::reader::CardReaderEvent; +using keypop::reader::ObservableCardReader; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::spi::CardReaderObservationExceptionHandlerSpi; +using keypop::reader::spi::CardReaderObserverSpi; + +/** + * A reader Observer handles card event such as CARD_INSERTED, CARD_MATCHED, + * CARD_REMOVED. Executes the TN313 Secure Session transaction scenario upon a + * CARD_MATCHED event. + */ +class CardReaderObserver final +: public CardReaderObserverSpi, + public CardReaderObservationExceptionHandlerSpi { +public: + /** + * Constructor. + * + * @param plugin The plugin. + * @param cardReader The card reader. + * @param cardSelectionManager The card selection manager. + * @param cardSecuritySetting The card security settings. + */ + CardReaderObserver( + std::shared_ptr plugin, + std::shared_ptr cardReader, + std::shared_ptr cardSelectionManager, + std::shared_ptr cardSecuritySetting); + + /** + * {@inheritDoc} + */ + void onReaderEvent(const std::shared_ptr event) override; + + /** + * {@inheritDoc} + */ + void onReaderObservationError( + const std::string& pluginName, + const std::string& readerName, + const std::shared_ptr e) override; + +private: + /** + * + */ + const std::unique_ptr mLogger + = LoggerFactory::getLogger(typeid(CardReaderObserver)); + + /** + * + */ + std::shared_ptr mPlugin; + + /** + * + */ + std::shared_ptr mCardReader; + + /** + * + */ + std::shared_ptr mCardSelectionManager; + + /** + * + */ + std::shared_ptr mCardSecuritySetting; + + /** + * + */ + std::shared_ptr mCalypsoCardApiFactory; + + /** + * + */ + const std::vector mNewEventRecord; +}; diff --git a/Example_Card_Calypso/src/main/UseCase10_SessionTrace_TN313/Main_SessionTrace_TN313_Pcsc.cpp b/Example_Card_Calypso/src/main/UseCase10_SessionTrace_TN313/Main_SessionTrace_TN313_Pcsc.cpp index 8dfb064..54da9ce 100644 --- a/Example_Card_Calypso/src/main/UseCase10_SessionTrace_TN313/Main_SessionTrace_TN313_Pcsc.cpp +++ b/Example_Card_Calypso/src/main/UseCase10_SessionTrace_TN313/Main_SessionTrace_TN313_Pcsc.cpp @@ -1,245 +1,383 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Core Util */ -#include "ContactCardCommonProtocol.h" -#include "HexUtil.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" -#include "StringUtils.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPlugin.h" -#include "PcscPluginFactory.h" -#include "PcscPluginFactoryBuilder.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "CardReaderObserver.h" -#include "ConfigurationUtil.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::calypso; -using namespace keyple::core::service; -using namespace keyple::core::service::resource; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::core::util::protocol; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamUtil.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactProtocol.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/WriteAccessLevel.hpp" +#include "keypop/calypso/card/card/CalypsoCardSelectionExtension.hpp" +#include "keypop/calypso/card/transaction/SymmetricCryptoSecuritySetting.hpp" +#include "keypop/calypso/crypto/legacysam/LegacySamApiFactory.hpp" +#include "keypop/calypso/crypto/legacysam/sam/LegacySam.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ObservableCardReader.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" + +#include "../common/ConfigurationUtil.hpp" +#include "CardReaderObserver.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamUtil; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keyple::plugin::pcsc::PcscSupportedContactProtocol; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::WriteAccessLevel; +using keypop::calypso::card::card::CalypsoCardSelectionExtension; +using keypop::calypso::card::transaction::SymmetricCryptoSecuritySetting; +using keypop::calypso::crypto::legacysam::LegacySamApiFactory; +using keypop::calypso::crypto::legacysam::sam::LegacySam; +using keypop::reader::CardReader; +using keypop::reader::ObservableCardReader; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::IsoCardSelector; /** - * Use Case Calypso 10 – Calypso Secure Session Trace - Technical Note #313 (PC/SC) - * - *

This an implementation of the Calypso Secure Session described the technical note #313 - * defining a typical usage of a Calypso card and allowing performances comparison. - * - *

Scenario: - * - *

    - *
  • Schedule a selection scenario over an observable reader to target a specific card (here a - * Calypso card characterized by its AID) and including the reading of a file record. - *
  • Attempts to select a Calypso SAM (C1) in the contact reader. - *
  • Start the observation and wait for a card insertion. - *
  • Within the reader event handler: - *
      - *
    • Do the TN313 transaction scenario. - *
    • Close the physical channel. - *
    - *
- * - *

Any unexpected behavior will result in runtime exceptions. + * Handles the execution of Calypso Secure Session Trace as defined in + * Technical Note #313 (PC/SC) using an observable reader and Calypso card + * extension service. */ - -class Main_SessionTrace_TN313_Pcsc{}; -const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_SessionTrace_TN313_Pcsc)); - -static std::string cardReaderRegex = ConfigurationUtil::CARD_READER_NAME_REGEX; -static std::string samReaderRegex = ConfigurationUtil::SAM_READER_NAME_REGEX; -static std::string cardAid = CalypsoConstants::AID; -static bool isVerbose; +class Main_SessionTrace_TN313_Pcsc { }; +static std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_SessionTrace_TN313_Pcsc)); + +/* A regular expression for matching common contactless card readers. Adapt as + * needed. */ +static const std::string CARD_READER_NAME_REGEX + = ".*ASK LoGO.*|.*Contactless.*"; +/* A regular expression for matching common SAM readers. Adapt as needed. */ +static const std::string SAM_READER_NAME_REGEX = ".*Identive.*|.*HID.*|.*SAM.*"; +static const std::string ISO_CARD_PROTOCOL = "ISO_14443_4_CARD"; +static const std::string SAM_PROTOCOL = "ISO_7816_3_T0"; +static std::string cardReaderRegex = CARD_READER_NAME_REGEX; +static std::string samReaderRegex = SAM_READER_NAME_REGEX; + +/** AID: Keyple test kit profile 1, Application 2 */ +static const std::string AID = "315449432E49434131"; + +static std::string cardAid = AID; + +/* The plugin used to manage the readers. */ +static std::shared_ptr plugin; +/* The reader used to communicate with the card. */ +static std::shared_ptr cardReader; +/* The reader used to communicate with the SAM. */ +static std::shared_ptr samReader; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* + * The Calypso factory used to create the selection extension and transaction + * managers. + */ +static std::shared_ptr calypsoCardApiFactory; +/* The security settings for the card transaction. */ +static std::shared_ptr + symmetricCryptoSecuritySetting; /** - * Displays the expected options + * Displays the expected options and exits. */ -static void displayUsageAndExit() -{ +static void +displayUsageAndExit() { std::cout << "Available options:" << std::endl; - std::cout << " -d, --default use default values (is equivalent to -a=" \ - << CalypsoConstants::AID << " -c=" << ConfigurationUtil::CARD_READER_NAME_REGEX \ - << " -s=" << ConfigurationUtil::SAM_READER_NAME_REGEX << ")" << std::endl; - std::cout << " -a, --aid=\"APPLICATION_AID\" between 5 and 16 hex bytes (e.g. \"315449432E" \ - << "49434131\")" << std::endl; - std::cout << " -c, --card=\"CARD_READER_REGEX\" regular expression matching the card reader n" \ - << "ame (e.g. \"ASK Logo.*\")" << std::endl; - std::cout << " -s, --sam=\"SAM_READER_REGEX\" regular expression matching the SAM reader na" \ - << "me (e.g. \"HID.*\")" << std::endl; - std::cout << " -v, --verbose set the log level to TRACE" << std::endl; - std::cout << "PC/SC protocol is set to `\"ANY\" ('*') for the SAM reader, \"T1\" ('T=1') for " \ - "the card reader." << std::endl; - - exit(-1); + std::cout << " -d, --default use default values (is " + "equivalent to -a=\"" + << AID << "\" -c=\"" << CARD_READER_NAME_REGEX << "\" -s=\"" + << SAM_READER_NAME_REGEX << "\")" << std::endl; + std::cout << " -a, --aid=\"APPLICATION_AID\" between 5 and 16 hex " + "bytes (e.g. \"315449432E49434131\")" + << std::endl; + std::cout << " -c, --card=\"CARD_READER_REGEX\" regular expression " + "matching the card reader name (e.g. \"ASK Logo.*\")" + << std::endl; + std::cout << " -s, --sam=\"SAM_READER_REGEX\" regular expression " + "matching the SAM reader name (e.g. \"HID.*\")" + << std::endl; + std::cout << "PC/SC protocol is set to `\"ANY\" ('*') for the SAM " + "reader, \"T1\" ('T=1') for the card reader." + << std::endl; + + exit(1); } /** - * Analyses the command line and sets the specified parameters. - * - * @param args The command line arguments + * Splits a "key=value" argument into its two parts, handling additional + * options such as the AID, the card reader regex and the SAM reader regex. */ -static void parseCommandLine(int argc, char **argv) -{ - /* Command line arguments analysis */ - if (argc > 1) { - - std::vector args; - for (int i = 1; i < argc; i++) { - args.push_back(argv[i]); - } +static void +parseAdditionalArguments(const std::string& arg) { + const std::string::size_type pos = arg.find('='); + if (pos == std::string::npos) { + displayUsageAndExit(); + return; + } + + const std::string argKey = arg.substr(0, pos); + const std::string argValue = arg.substr(pos + 1); - /* At least one argument */ - for (const auto& arg : args) { - std::cout << "arg: " << arg << std::endl; - if (arg == "-d" || arg == "--default") { - break; - } - - if (arg == "-v" || arg == "--verbose") { - isVerbose = true; - continue; - } - - const std::vector argument = StringUtils::split(arg, "="); - if (argument.size() != 2) { - displayUsageAndExit(); - } - - if (argument[0] == "-a" || argument[0] == "--aid") { - cardAid = argument[1]; - if (argument[1].length() < 10 || - argument[1].length() > 32 || - !HexUtil::isValid(argument[1])) { - std::cout << "Invalid AID"; - displayUsageAndExit(); - } - - } else if (argument[0] == "-c" || argument[0] == "--card") { - cardReaderRegex = argument[1]; - - } else if (argument[0] == "-s" || argument[0] == "--sam") { - samReaderRegex = argument[1]; - - } else { - displayUsageAndExit(); - } + if (argKey == "-a" || argKey == "--aid") { + if (argValue.length() < 10 || argValue.length() > 32 + || !HexUtil::isValid(argValue)) { + std::cout << "Invalid AID" << std::endl; + displayUsageAndExit(); + return; } + cardAid = argValue; + } else if (argKey == "-c" || argKey == "--card") { + cardReaderRegex = argValue; + } else if (argKey == "-s" || argKey == "--sam") { + samReaderRegex = argValue; } else { displayUsageAndExit(); } } +/** + * Analyses the command line and sets the specified parameters. + */ +static void +parseCommandLine(int argc, char** argv) { + if (argc == 1) { + displayUsageAndExit(); + return; + } -int main(int argc, char **argv) -{ - parseCommandLine(argc, argv); + for (int i = 1; i < argc; i++) { + const std::string arg(argv[i]); + if (arg == "-d" || arg == "--default") { + break; + } - Logger::setLoggerLevel(isVerbose ? Logger::Level::logTrace : Logger::Level::logInfo); + parseAdditionalArguments(arg); + } +} - logger->info("=============== UseCase Calypso #10: session trace TN313 ==================\n"); +/** + * Initializes the Keyple service. + */ +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); + plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} - logger->info("Using parameters:\n"); - logger->info(" AID=%\n", cardAid); - logger->info(" CARD_READER_REGEX=%\n", cardReaderRegex); - logger->info(" SAM_READER_REGEX=%\n", samReaderRegex); +/** + * Initializes the card reader with specific configurations. + */ +static void +initCardReader() { + cardReader = ConfigurationUtil::getReader( + plugin, + cardReaderRegex, + true, + PcscReader::IsoProtocol::T1, + PcscReader::SharingMode::SHARED, + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ISO_CARD_PROTOCOL); +} + +/** + * Initializes the SAM reader with specific configurations. + */ +static void +initSamReader() { + samReader = ConfigurationUtil::getReader( + plugin, + samReaderRegex, + false, + PcscReader::IsoProtocol::ANY, + PcscReader::SharingMode::SHARED, + PcscSupportedContactProtocol::ISO_7816_3_T0.getName(), + SAM_PROTOCOL); +} - /* Get the instance of the SmartCardService */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); +/** + * Initializes the Calypso card extension service. + */ +static void +initCalypsoCardExtensionService() { + std::shared_ptr calypsoExtensionService( + CalypsoExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + calypsoExtensionService); + calypsoCardApiFactory = calypsoExtensionService->getCalypsoCardApiFactory(); +} - /* Register the PcscPlugin */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); +/** + * Selects the SAM C1 for the transaction. + */ +static std::shared_ptr +selectSam(std::shared_ptr reader) { + std::shared_ptr samSelectionManager( + readerApiFactory->createCardSelectionManager()); - /* Get the Calypso card extension service */ - std::shared_ptr calypsoCardService = - CalypsoExtensionService::getInstance(); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByPowerOnData( + LegacySamUtil::buildPowerOnDataFilter( + LegacySam::ProductType::SAM_C1, "")); - /* Verify that the extension's API level is consistent with the current service */ - smartCardService->checkCardExtension(calypsoCardService); + std::shared_ptr legacySamApiFactory( + LegacySamExtensionService::getInstance()->getLegacySamApiFactory()); - /* Get the card and SAM readers whose name matches the provided regexs */ - auto cardReader = ConfigurationUtil::getCardReader(plugin, cardReaderRegex); - auto samReader = ConfigurationUtil::getSamReader(plugin, samReaderRegex); + samSelectionManager->prepareSelection( + cardSelector, legacySamApiFactory->createLegacySamSelectionExtension()); - /* Get the Calypso SAM SmartCard after selection. */ - std::shared_ptr calypsoSam = ConfigurationUtil::getSam(samReader); + const std::shared_ptr samSelectionResult( + samSelectionManager->processCardSelectionScenario(reader)); - logger->info("= SAM = %\n", calypsoSam); + if (samSelectionResult->getActiveSmartCard() == nullptr) { + throw IllegalStateException("The selection of the SAM failed."); + } + + return std::dynamic_pointer_cast( + samSelectionResult->getActiveSmartCard()); +} + +/** + * Initializes the security settings for the transaction. + */ +static void +initSecuritySetting() { + std::shared_ptr sam(selectSam(samReader)); + + symmetricCryptoSecuritySetting + = calypsoCardApiFactory->createSymmetricCryptoSecuritySetting( + LegacySamExtensionService::getInstance() + ->getLegacySamApiFactory() + ->createSymmetricCryptoCardTransactionManagerFactory( + samReader, sam)); + symmetricCryptoSecuritySetting + ->assignDefaultKif(WriteAccessLevel::PERSONALIZATION, 0x21) + .assignDefaultKif(WriteAccessLevel::LOAD, 0x27) + .assignDefaultKif(WriteAccessLevel::DEBIT, 0x30) + .enableRatificationMechanism(); + + /* Optimization: preload the SAM challenge for the next transaction */ + symmetricCryptoSecuritySetting->initCryptoContextForNextTransaction(); +} + +int +main(int argc, char** argv) { + parseCommandLine(argc, argv); + + logger->info( + "= UseCase Calypso #10: session trace TN313 ==================\n"); + logger->info("Using parameters:\n"); + logger->info(" AID=%\n", cardAid); + logger->info(" CARD_READER_REGEX=%\n", cardReaderRegex); + logger->info(" SAM_READER_REGEX=%\n", samReaderRegex); + + /* Initialize the context */ + initKeypleService(); + initCalypsoCardExtensionService(); + initCardReader(); + initSamReader(); + initSecuritySetting(); logger->info("Select application with AID = '%'\n", cardAid); /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); + + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(cardAid); /* * Create a card selection using the Calypso card extension. - * Select the card and read the record 1 of the file ENVIRONMENT_AND_HOLDER + * Select the card and read the record 1 of the file + * ENVIRONMENT_AND_HOLDER. Prepare the selection by adding the created + * Calypso selection to the card selection scenario. */ - std::shared_ptr cardSelection = calypsoCardService->createCardSelection(); - cardSelection->acceptInvalidatedCard() - .filterByCardProtocol(ConfigurationUtil::ISO_CARD_PROTOCOL) - .filterByDfName(cardAid); - - /* Prepare the selection by adding the created Calypso selection to the card selection scenario. */ - cardSelectionManager->prepareSelection(cardSelection); + std::unique_ptr + calypsoCardSelectionExtension( + calypsoCardApiFactory->createCalypsoCardSelectionExtension()); + calypsoCardSelectionExtension->acceptInvalidatedCard(); + cardSelectionManager->prepareSelection( + cardSelector, std::move(calypsoCardSelectionExtension)); /* - * Schedule the selection scenario, request notification only if the card matches the selection - * case. + * Schedule the selection scenario, request notification only if the card + * matches the selection case. */ - auto observable = std::dynamic_pointer_cast(cardReader); + auto observableCardReader + = std::dynamic_pointer_cast(cardReader); cardSelectionManager->scheduleCardSelectionScenario( - observable, - ObservableCardReader::DetectionMode::REPEATING, + observableCardReader, ObservableCardReader::NotificationMode::MATCHED_ONLY); - /* Create security settings that reference the SAM */ - std::shared_ptr cardSecuritySetting = - CalypsoExtensionService::getInstance()->createCardSecuritySetting(); - cardSecuritySetting->assignDefaultKif(WriteAccessLevel::PERSONALIZATION, 0x21) - .assignDefaultKif(WriteAccessLevel::LOAD, 0x27) - .assignDefaultKif(WriteAccessLevel::DEBIT, 0x30) - .setControlSamResource(samReader, calypsoSam); - /* Create and add a card observer for this reader */ - auto cardReaderObserver = - std::make_shared(cardReader, cardSelectionManager, cardSecuritySetting); - observable->setReaderObservationExceptionHandler(cardReaderObserver); - observable->addObserver(cardReaderObserver); - observable->startCardDetection(ObservableCardReader::DetectionMode::REPEATING); - + auto cardReaderObserver = std::make_shared( + plugin, + observableCardReader, + cardSelectionManager, + symmetricCryptoSecuritySetting); + + observableCardReader->setReaderObservationExceptionHandler( + cardReaderObserver); + observableCardReader->addObserver(cardReaderObserver); + observableCardReader->startCardDetection( + ObservableCardReader::DetectionMode::REPEATING); logger->info("Wait for a card...\n"); - while(1); + logger->info("Press ENTER to exit...\n"); + std::string line; + std::getline(std::cin, line); + logger->info("Exit in progress...\n"); + + /* Unregister plugin */ + SmartCardServiceProvider::getService()->unregisterPlugin(plugin->getName()); + + logger->info("Exit program\n"); + + return 0; } diff --git a/Example_Card_Calypso/src/main/UseCase11_DataSigning/Main_DataSigning_Pcsc.cpp b/Example_Card_Calypso/src/main/UseCase11_DataSigning/Main_DataSigning_Pcsc.cpp index 145de52..45038f8 100644 --- a/Example_Card_Calypso/src/main/UseCase11_DataSigning/Main_DataSigning_Pcsc.cpp +++ b/Example_Card_Calypso/src/main/UseCase11_DataSigning/Main_DataSigning_Pcsc.cpp @@ -1,373 +1,499 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" -#include "ConfigurableCardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Core Util */ -#include "HexUtil.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" -#include "StringUtils.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPlugin.h" -#include "PcscPluginFactory.h" -#include "PcscPluginFactoryBuilder.h" -#include "PcscReader.h" -#include "PcscSupportedContactProtocol.h" -#include "PcscSupportedContactlessProtocol.h" - -/* Keyple Core Resource */ -#include "CardResource.h" -#include "CardResourceServiceProvider.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "ConfigurationUtil.h" - -using namespace keyple::card::calypso; -using namespace keyple::core::service; -using namespace keyple::core::service::resource; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include +#include + +#include "keyple/card/calypso/crypto/legacysam/LegacySamExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamUtil.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/service/resource/CardResource.hpp" +#include "keyple/core/service/resource/CardResourceProfileConfigurator.hpp" +#include "keyple/core/service/resource/CardResourceService.hpp" +#include "keyple/core/service/resource/CardResourceServiceProvider.hpp" +#include "keyple/core/service/resource/PluginsConfigurator.hpp" +#include "keyple/core/service/resource/spi/CardResourceProfileExtension.hpp" +#include "keyple/core/service/resource/spi/ReaderConfiguratorSpi.hpp" +#include "keyple/core/service/spi/PluginObservationExceptionHandlerSpi.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/Exception.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keypop/calypso/crypto/legacysam/LegacySamApiFactory.hpp" +#include "keypop/calypso/crypto/legacysam/sam/LegacySam.hpp" +#include "keypop/calypso/crypto/legacysam/sam/LegacySamSelectionExtension.hpp" +#include "keypop/calypso/crypto/legacysam/transaction/BasicSignatureComputationData.hpp" +#include "keypop/calypso/crypto/legacysam/transaction/BasicSignatureVerificationData.hpp" +#include "keypop/calypso/crypto/legacysam/transaction/FreeTransactionManager.hpp" +#include "keypop/calypso/crypto/legacysam/transaction/SamTraceabilityMode.hpp" +#include "keypop/calypso/crypto/legacysam/transaction/TraceableSignatureComputationData.hpp" +#include "keypop/calypso/crypto/legacysam/transaction/TraceableSignatureVerificationData.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/spi/CardReaderObservationExceptionHandlerSpi.hpp" + +using keyple::card::calypso::crypto::legacysam::LegacySamExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamUtil; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::service::resource::CardResource; +using keyple::core::service::resource::CardResourceProfileConfigurator; +using keyple::core::service::resource::CardResourceService; +using keyple::core::service::resource::CardResourceServiceProvider; +using keyple::core::service::resource::PluginsConfigurator; +using keyple::core::service::resource::spi::CardResourceProfileExtension; +using keyple::core::service::resource::spi::ReaderConfiguratorSpi; +using keyple::core::service::spi::PluginObservationExceptionHandlerSpi; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::Exception; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keypop::calypso::crypto::legacysam::LegacySamApiFactory; +using keypop::calypso::crypto::legacysam::sam::LegacySam; +using keypop::calypso::crypto::legacysam::sam::LegacySamSelectionExtension; +using keypop::calypso::crypto::legacysam::transaction:: + BasicSignatureComputationData; +using keypop::calypso::crypto::legacysam::transaction:: + BasicSignatureVerificationData; +using keypop::calypso::crypto::legacysam::transaction::FreeTransactionManager; +using keypop::calypso::crypto::legacysam::transaction::SamTraceabilityMode; +using keypop::calypso::crypto::legacysam::transaction:: + TraceableSignatureComputationData; +using keypop::calypso::crypto::legacysam::transaction:: + TraceableSignatureVerificationData; +using keypop::reader::CardReader; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::spi::CardReaderObservationExceptionHandlerSpi; /** - *

Use Case Calypso 11 – Calypso Card data signing (PC/SC)

+ * Handles the execution of Calypso Legacy SAM data signing using an SAM + * resource service and the Legacy SAM extension service. * - *

We demonstrate here how to generate and verify data signature. - * - *

Only a contact reader is required for the Calypso SAM. - * - *

Scenario:

- * - *
    - *
  • Sets up the card resource service to provide a Calypso SAM (C1). - *
  • The card resource service is configured and started to observe the connection/disconnection - * of readers and the insertion/removal of cards. - *
  • A command line menu allows you to take and release a SAM resource and select a signature - * process. - *
  • The log and console printouts show the operation of the card resource service and the - * signature processes results. - *
- * - * All results are logged with slf4j. - * - *

Any unexpected behavior will result in runtime exceptions. + *

This class demonstrates the process of generating and verifying data + * signatures with a Calypso Legacy SAM, utilizing a contact reader and the + * card resource service for Calypso SAM (C1). */ +class Main_DataSigning_Pcsc { }; +static std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_DataSigning_Pcsc)); -class Main_DataSigning_Pcsc{}; -const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_DataSigning_Pcsc)); - -static const std::string SAM_RESOURCE = "SAM_RESOURCE"; -static const std::string READER_NAME_REGEX = ".*Ident.*"; -static const uint8_t KIF_BASIC = 0xEC; -static const uint8_t KVC_BASIC = 0x85; +static const std::string SAM_READER_NAME_REGEX = ".*Ident.*"; +static const std::uint8_t KIF_BASIC = 0xEC; +static const std::uint8_t KVC_BASIC = 0x85; static const std::string KIF_BASIC_STR = HexUtil::toHex(KIF_BASIC); static const std::string KVC_BASIC_STR = HexUtil::toHex(KVC_BASIC); -static const uint8_t KIF_TRACEABLE = 0x2B; -static const uint8_t KVC_TRACEABLE = 0x19; +static const std::uint8_t KIF_TRACEABLE = 0x2B; +static const std::uint8_t KVC_TRACEABLE = 0x19; static const std::string KIF_TRACEABLE_STR = HexUtil::toHex(KIF_TRACEABLE); static const std::string KVC_TRACEABLE_STR = HexUtil::toHex(KVC_TRACEABLE); static const std::string DATA_TO_SIGN = "00112233445566778899AABBCCDDEEFF"; +/* + * The name of the SAM resource provided by the Card Resource Manager and used + * during the card transaction. + */ +static const std::string SAM_PROFILE_NAME = "SAM C1"; + +/* The plugin used to manage the readers. */ +static std::shared_ptr plugin; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* The Legacy SAM factory used to create the signature data and transaction + * managers. */ +static std::shared_ptr legacySamApiFactory; +/* The Card Resource Service to manage SAM resources. */ +static std::shared_ptr cardResourceService; + /** - * Reader configurator used by the card resource service to set up the SAM reader with the - * required settings. + * Reader configurator used by the card resource service to set up the SAM + * reader with the required settings. */ class ReaderConfigurator final : public ReaderConfiguratorSpi { public: - /** {@inheritDoc} */ - void setupReader(const std::shared_ptr reader) override - { - /* Configure the reader with parameters suitable for contact operations */ + /** + * {@inheritDoc} + */ + void + setupReader(std::shared_ptr reader) override { + /* Configure the reader with parameters suitable for contact operations + */ try { - std::dynamic_pointer_cast(reader) - ->activateProtocol(PcscSupportedContactProtocol::ISO_7816_3_T0.getName(), - ConfigurationUtil::SAM_PROTOCOL); - - std::shared_ptr readerExtension = + auto readerExtension = std::dynamic_pointer_cast( SmartCardServiceProvider::getService() ->getPlugin(reader) - ->getReaderExtension(typeid(KeypleReaderExtension), reader->getName()); - - auto pcscReader = std::dynamic_pointer_cast(readerExtension); - if (pcscReader) { - pcscReader->setContactless(false) - .setIsoProtocol(PcscReader::IsoProtocol::ANY) - .setSharingMode(PcscReader::SharingMode::SHARED); + ->getReaderExtension( + typeid(PcscReader), reader->getName())); + if (readerExtension != nullptr) { + readerExtension->setContactless(false) + .setIsoProtocol(PcscReader::IsoProtocol::ANY) + .setSharingMode(PcscReader::SharingMode::SHARED); } - } catch (const Exception& e) { - mLogger->error("Exception raised while setting up the reader %\n", - reader->getName(), - e); + mLogger->error( + "Exception raised while setting up the reader %\n", + reader->getName(), + e); } } +private: /** - * (private)
- * Constructor. + * */ - ReaderConfigurator() {} - -private: - const std::unique_ptr mLogger = LoggerFactory::getLogger(typeid(ReaderConfigurator)); + const std::unique_ptr mLogger + = LoggerFactory::getLogger(typeid(ReaderConfigurator)); }; -/** Class implementing the exception handler SPIs for plugin and reader monitoring. */ +/** + * Class implementing the exception handler SPIs for plugin and reader + * monitoring. + */ class PluginAndReaderExceptionHandler final -: public PluginObservationExceptionHandlerSpi, public CardReaderObservationExceptionHandlerSpi { +: public PluginObservationExceptionHandlerSpi, + public CardReaderObservationExceptionHandlerSpi { public: - void onPluginObservationError(const std::string& pluginName, const std::shared_ptr e) - override - { - logger->error("An exception occurred while monitoring the plugin '%'.\n", pluginName, e); + /** + * {@inheritDoc} + */ + void + onPluginObservationError( + const std::string& pluginName, + const std::unique_ptr e) override { + mLogger->error( + "An exception occurred while monitoring the plugin '%'\n", + pluginName, + e->getMessage()); } - void onReaderObservationError(const std::string& pluginName, - const std::string& readerName, - const std::shared_ptr e) override - { - logger->error("An exception occurred while monitoring the reader '%/%'.\n", - pluginName, - readerName, - e); + /** + * {@inheritDoc} + */ + void + onReaderObservationError( + const std::string& pluginName, + const std::string& readerName, + const std::shared_ptr e) override { + mLogger->error( + "An exception occurred while monitoring the reader '%/%'\n", + pluginName, + readerName, + e); } + +private: + /** + * + */ + const std::unique_ptr mLogger + = LoggerFactory::getLogger(typeid(PluginAndReaderExceptionHandler)); }; -static char getInput() -{ - std::cout << "Options:" << std::endl; - std::cout << " '1': Get a SAM resource" << std::endl; - std::cout << " '2': Release a SAM resource" << std::endl; - std::cout << " '3': Basic signature generation and verification" << std::endl; - std::cout << " '4': Traceable signature generation and verification" << std::endl; - std::cout << " 'q': quit" << std::endl; - std::cout << "Select an option: " << std::endl; +/** + * Initializes the Keyple service. + */ +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); + plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} - return static_cast(getchar()); +/** + * Initializes the Legacy SAM extension service. + */ +static void +initLegacySamExtensionService() { + std::shared_ptr legacySamExtensionService( + LegacySamExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + legacySamExtensionService); + legacySamApiFactory = legacySamExtensionService->getLegacySamApiFactory(); } -int main() -{ - /* Get the instance of the SmartCardService */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); +/** + * Initializes the SAM Resource Service making a SAM resource available under + * the SAM_PROFILE_NAME name. + */ +static void +initSamResourceService() { + /* Create a card resource extension expecting a SAM "C1" */ + std::shared_ptr samSelection( + legacySamApiFactory->createLegacySamSelectionExtension()); + + std::shared_ptr samCardResourceExtension( + LegacySamExtensionService::getInstance() + ->createLegacySamResourceProfileExtension(samSelection)); + + /* Get the card resource service */ + cardResourceService = CardResourceServiceProvider::getService(); + + auto pluginAndReaderExceptionHandler + = std::make_shared(); + + /* + * Configure the card resource service: + * - allocation mode is blocking with a 100 milliseconds cycle and a 10 + * seconds timeout. + * - the readers are searched in the PC/SC plugin, the observation of the + * plugin (for the connection/disconnection of readers) and of the + * readers (for the insertion/removal of cards) is activated. + */ + cardResourceService->getConfigurator() + ->withBlockingAllocationMode(100, 10000) + .withPlugins( + PluginsConfigurator::builder() + ->addPluginWithMonitoring( + plugin, + std::make_shared(), + pluginAndReaderExceptionHandler, + pluginAndReaderExceptionHandler) + .withUsageTimeout(5000) + .build()) + .withCardResourceProfiles( + {CardResourceProfileConfigurator::builder( + SAM_PROFILE_NAME, samCardResourceExtension) + ->withReaderNameRegex(SAM_READER_NAME_REGEX) + .build()}) + .configure(); + cardResourceService->start(); - /* Register the PcscPlugin, get the corresponding PC/SC plugin in return */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); + /* Verify if the card resource is available */ + std::shared_ptr cardResource( + cardResourceService->getCardResource(SAM_PROFILE_NAME)); + + if (cardResource == nullptr) { + throw IllegalStateException( + "Failed to retrieve a SAM card resource. No card resource found " + "for profile '" + + SAM_PROFILE_NAME + "' with reader matching '" + + SAM_READER_NAME_REGEX + "' in plugin '" + plugin->getName() + + "'."); + } - /* Get the Calypso card extension service */ - std::shared_ptr calypsoCardService = - CalypsoExtensionService::getInstance(); + /* Release the card resource */ + cardResourceService->releaseCardResource(cardResource); +} - /* Verify that the extension's API level is consistent with the current service */ - smartCardService->checkCardExtension(calypsoCardService); +static std::shared_ptr +acquireSamResource(const std::string& cardResourceName) { + std::shared_ptr cardResource( + cardResourceService->getCardResource(cardResourceName)); + if (cardResource != nullptr) { + logger->info( + "A SAM resource is available: reader %, smart card %\n", + cardResource->getReader()->getName(), + cardResource->getSmartCard()); + } else { + logger->info("SAM resource is not available\n"); + } - /* Create a SAM resource extension expecting a SAM having power-on data matching the regex */ - std::shared_ptr samSelection = - CalypsoExtensionService::getInstance()->createSamSelection(); - samSelection->filterByProductType(CalypsoSam::ProductType::SAM_C1); + return cardResource; +} - std::shared_ptr cardResourceExtension = - CalypsoExtensionService::getInstance()->createSamResourceProfileExtension(samSelection); +static void +releaseSamResource(std::shared_ptr cardResource) { + if (cardResource != nullptr) { + logger->info("Release SAM resource.\n"); + cardResourceService->releaseCardResource(cardResource); + } else { + logger->error("SAM resource is not available\n"); + } +} - /* Get the service */ - std::shared_ptr cardResourceService = - CardResourceServiceProvider::getService(); +static void +performBasicSignature(std::shared_ptr cardResource) { + if (cardResource == nullptr) { + logger->error("No SAM resource.\n"); + return; + } - auto pluginAndReaderExceptionHandler = std::make_shared(); + std::shared_ptr freeTransactionManager( + legacySamApiFactory->createFreeTransactionManager( + cardResource->getReader(), + std::dynamic_pointer_cast( + cardResource->getSmartCard()))); + + logger->info( + "Signing: data='%' with the key %/%\n", + DATA_TO_SIGN, + KIF_BASIC_STR, + KVC_BASIC_STR); + + std::shared_ptr + basicSignatureComputationData( + legacySamApiFactory->createBasicSignatureComputationData()); + basicSignatureComputationData->setData( + HexUtil::toByteArray(DATA_TO_SIGN), KIF_BASIC, KVC_BASIC); + freeTransactionManager->prepareComputeSignature( + basicSignatureComputationData); + freeTransactionManager->processCommands(); + const std::string signatureHex( + HexUtil::toHex(basicSignatureComputationData->getSignature())); + logger->info("signature='%'\n", signatureHex); + + logger->info( + "Verifying: data='%', signature='%' with the key %/%\n", + DATA_TO_SIGN, + signatureHex, + KIF_BASIC_STR, + KVC_BASIC_STR); + + std::shared_ptr + basicSignatureVerificationData( + legacySamApiFactory->createBasicSignatureVerificationData()); + basicSignatureVerificationData->setData( + HexUtil::toByteArray(DATA_TO_SIGN), + HexUtil::toByteArray(signatureHex), + KIF_BASIC, + KVC_BASIC); + freeTransactionManager->prepareVerifySignature( + basicSignatureVerificationData); + freeTransactionManager->processCommands(); + const bool isSignatureValid + = basicSignatureVerificationData->isSignatureValid(); + logger->info("Signature is valid: '%'\n", isSignatureValid); +} - std::shared_ptr samTransactionManager = nullptr; +static void +performTraceableSignature(std::shared_ptr cardResource) { + if (cardResource == nullptr) { + logger->error("No SAM resource.\n"); + return; + } - /* Configure the card resource */ - cardResourceService->getConfigurator() - ->withBlockingAllocationMode(100, 10000) - .withPlugins(PluginsConfigurator::builder() - ->addPluginWithMonitoring( - plugin, - std::make_shared(), - pluginAndReaderExceptionHandler, - pluginAndReaderExceptionHandler) - .withUsageTimeout(5000) - .build()) - .withCardResourceProfiles( - {CardResourceProfileConfigurator::builder(SAM_RESOURCE, - cardResourceExtension) - ->withReaderNameRegex(READER_NAME_REGEX) - .build()}) - .configure(); + std::shared_ptr freeTransactionManager( + legacySamApiFactory->createFreeTransactionManager( + cardResource->getReader(), + std::dynamic_pointer_cast( + cardResource->getSmartCard()))); + + logger->info( + "Signing: data='%' with the key %/%\n", + DATA_TO_SIGN, + KIF_TRACEABLE_STR, + KVC_TRACEABLE_STR); + + std::shared_ptr + traceableSignatureComputationData( + legacySamApiFactory->createTraceableSignatureComputationData()); + traceableSignatureComputationData + ->setData( + HexUtil::toByteArray(DATA_TO_SIGN), KIF_TRACEABLE, KVC_TRACEABLE) + .withSamTraceabilityMode(0, SamTraceabilityMode::FULL_SERIAL_NUMBER); + freeTransactionManager->prepareComputeSignature( + traceableSignatureComputationData); + freeTransactionManager->processCommands(); + const std::string signatureHex( + HexUtil::toHex(traceableSignatureComputationData->getSignature())); + const std::string signedDataHex( + HexUtil::toHex(traceableSignatureComputationData->getSignedData())); + logger->info("signature='%'\n", signatureHex); + logger->info("signed data='%'\n", signedDataHex); + + logger->info( + "Verifying: data='%', signature='%' with the key %/%\n", + signedDataHex, + signatureHex, + KIF_TRACEABLE_STR, + KVC_TRACEABLE_STR); + + std::shared_ptr + traceableSignatureVerificationData( + legacySamApiFactory->createTraceableSignatureVerificationData()); + traceableSignatureVerificationData + ->setData( + HexUtil::toByteArray(signedDataHex), + HexUtil::toByteArray(signatureHex), + KIF_TRACEABLE, + KVC_TRACEABLE) + .withSamTraceabilityMode( + 0, SamTraceabilityMode::FULL_SERIAL_NUMBER, nullptr); + freeTransactionManager->prepareVerifySignature( + traceableSignatureVerificationData); + freeTransactionManager->processCommands(); + const bool isSignatureValid + = traceableSignatureVerificationData->isSignatureValid(); + logger->info("Signature is valid: '%'\n", isSignatureValid); +} - cardResourceService->start(); +static char +getInput() { + std::cout << "Options:" << std::endl; + std::cout << " '1': Get a SAM resource" << std::endl; + std::cout << " '2': Release a SAM resource" << std::endl; + std::cout << " '3': Basic signature generation and verification" + << std::endl; + std::cout << " '4': Traceable signature generation and verification" + << std::endl; + std::cout << " 'q': quit" << std::endl; + std::cout << "Select an option: " << std::endl; - std::shared_ptr samSecuritySetting = - CalypsoExtensionService::getInstance()->createSamSecuritySetting(); + return static_cast(getchar()); +} - bool isSignatureValid; - std::string signatureHex; +int +main() { + /* Initialize the context */ + initKeypleService(); + initLegacySamExtensionService(); + initSamResourceService(); bool loop = true; std::shared_ptr cardResource = nullptr; + while (loop) { - char c = getInput(); - switch (c) { + const char input = getInput(); + switch (input) { case '1': - cardResource = cardResourceService->getCardResource(SAM_RESOURCE); - if (cardResource != nullptr) { - logger->info("A SAM resource is available: reader %, smart card %\n", - cardResource->getReader()->getName(), - cardResource->getSmartCard()); - } else { - logger->info("SAM resource is not available\n"); - } + cardResource = acquireSamResource(SAM_PROFILE_NAME); break; - case '2': - if (cardResource != nullptr) { - logger->info("Release SAM resource.\n"); - cardResourceService->releaseCardResource(cardResource); - } else { - logger->error("SAM resource is not available\n"); - } + releaseSamResource(cardResource); break; - case '3': - { - if (cardResource == nullptr) { - logger->error("No SAM resource.\n"); - break; - } - samTransactionManager = - CalypsoExtensionService::getInstance() - ->createSamTransaction( - cardResource->getReader(), - std::dynamic_pointer_cast(cardResource->getSmartCard()), - samSecuritySetting); - - logger->info("Signing: data='%' with the key %/%\n", - DATA_TO_SIGN, - KIF_BASIC_STR, - KVC_BASIC_STR); - - std::shared_ptr basicSignatureComputationData = - CalypsoExtensionService::getInstance()->createBasicSignatureComputationData(); - basicSignatureComputationData->setData(HexUtil::toByteArray(DATA_TO_SIGN), - KIF_BASIC, - KVC_BASIC); - samTransactionManager->prepareComputeSignature(basicSignatureComputationData); - samTransactionManager->processCommands(); - signatureHex = HexUtil::toHex(basicSignatureComputationData->getSignature()); - - logger->info("signature='%'\n", signatureHex); - - logger->info("Verifying: data='%', signature='%' with the key %/%\n", - DATA_TO_SIGN, - signatureHex, - KIF_BASIC_STR, - KVC_BASIC_STR); - - std::shared_ptr basicSignatureVerificationData = - CalypsoExtensionService::getInstance()->createBasicSignatureVerificationData(); - basicSignatureVerificationData->setData(HexUtil::toByteArray(DATA_TO_SIGN), - HexUtil::toByteArray(signatureHex), - KIF_BASIC, - KVC_BASIC); - samTransactionManager->prepareVerifySignature(basicSignatureVerificationData); - samTransactionManager->processCommands(); - isSignatureValid = basicSignatureVerificationData->isSignatureValid(); - - logger->info("Signature is valid: '%'\n", isSignatureValid); - } + performBasicSignature(cardResource); break; - case '4': - { - if (cardResource == nullptr) { - logger->error("No SAM resource."); - break; - } - - samTransactionManager = - CalypsoExtensionService::getInstance() - ->createSamTransaction( - cardResource->getReader(), - std::dynamic_pointer_cast(cardResource->getSmartCard()), - samSecuritySetting); - - logger->info("Signing: data='%' with the key %/%\n", - DATA_TO_SIGN, - KIF_TRACEABLE_STR, - KVC_TRACEABLE_STR); - - std::shared_ptr traceableSignatureComputationData = - CalypsoExtensionService::getInstance()->createTraceableSignatureComputationData(); - traceableSignatureComputationData->setData(HexUtil::toByteArray(DATA_TO_SIGN), - KIF_TRACEABLE, - KVC_TRACEABLE) - .withSamTraceabilityMode(0, true); - samTransactionManager->prepareComputeSignature(traceableSignatureComputationData); - samTransactionManager->processCommands(); - signatureHex = HexUtil::toHex(traceableSignatureComputationData->getSignature()); - const std::string signedDataHex = - HexUtil::toHex(traceableSignatureComputationData->getSignedData()); - - logger->info("signature='%'\n", signatureHex); - logger->info("signed data='%'\n", signedDataHex); - - logger->info("Verifying: data='%', signature='%' with the key %/%\n", - signedDataHex, - signatureHex, - KIF_TRACEABLE_STR, - KVC_TRACEABLE_STR); - - std::shared_ptr traceableSignatureVerificationData = - CalypsoExtensionService::getInstance()->createTraceableSignatureVerificationData(); - traceableSignatureVerificationData->setData(HexUtil::toByteArray(signedDataHex), - HexUtil::toByteArray(signatureHex), - KIF_TRACEABLE, - KVC_TRACEABLE) - .withSamTraceabilityMode(0, true, false); - samTransactionManager->prepareVerifySignature(traceableSignatureVerificationData); - samTransactionManager->processCommands(); - isSignatureValid = traceableSignatureVerificationData->isSignatureValid(); - - logger->info("Signature is valid: '%'\n", isSignatureValid); - } + performTraceableSignature(cardResource); break; - case 'q': loop = false; break; - default: break; } } /* Unregister plugin */ - smartCardService->unregisterPlugin(plugin->getName()); + SmartCardServiceProvider::getService()->unregisterPlugin(plugin->getName()); logger->info("Exit program.\n"); + + return 0; } diff --git a/Example_Card_Calypso/src/main/UseCase12_PerformanceMeasurement_EmbeddedValidation/Main_PerformanceMeasurement_EmbeddedValidation_Pcsc.cpp b/Example_Card_Calypso/src/main/UseCase12_PerformanceMeasurement_EmbeddedValidation/Main_PerformanceMeasurement_EmbeddedValidation_Pcsc.cpp index 3a00681..16c9e90 100644 --- a/Example_Card_Calypso/src/main/UseCase12_PerformanceMeasurement_EmbeddedValidation/Main_PerformanceMeasurement_EmbeddedValidation_Pcsc.cpp +++ b/Example_Card_Calypso/src/main/UseCase12_PerformanceMeasurement_EmbeddedValidation/Main_PerformanceMeasurement_EmbeddedValidation_Pcsc.cpp @@ -1,161 +1,320 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - - /* Calypsonet Terminal Reader */ -#include "CardReader.h" -#include "CardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Util */ -#include "HexUtil.h" -#include "LoggerFactory.h" -#include "System.h" -#include "Thread.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPlugin.h" -#include "PcscPluginFactory.h" -#include "PcscPluginFactoryBuilder.h" - -/* Keyple Service Resource */ -#include "CardResourceProfileConfigurator.h" -#include "CardResourceService.h" -#include "CardResourceServiceProvider.h" -#include "PluginsConfigurator.h" - -/* Keyple Core Common */ -#include "KeyplePluginExtension.h" -#include "KeypleReaderExtension.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "ConfigurationUtil.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::calypso; -using namespace keyple::core::common; -using namespace keyple::core::service; -using namespace keyple::core::service::resource; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::plugin::pcsc; - - /** - * Use Case Calypso 12 � Performance measurement: embedded validation (PC/SC) - * - *

This code is dedicated to performance measurement for an embedded validation type - * transaction. - * - *

It implements the scenario described here: - * - *

Any unexpected behavior will result in runtime exceptions. - */ -class Main_PerformanceMeasurement_EmbeddedValidation_Pcsc {}; -const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_PerformanceMeasurement_EmbeddedValidation_Pcsc)); - -/* User interface management */ -static const std::string RESET = "\u001B[0m"; -static const std::string RED = "\u001B[31m"; -static const std::string GREEN = "\u001B[32m"; -static const std::string YELLOW = "\u001B[33m"; - -/* Operating parameters */ -static const std::string cardReaderRegex = - ".*ASK LoGO.*|.*Contactless.*|.*ACR122U.*|.*00 01.*|.*5x21-CL 0.*"; -static const std::string samReaderRegex = - ".*Identive.*|.*HID.*|.*SAM.*|.*00 00.*|.*5x21 0.*"; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamUtil.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactProtocol.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/WriteAccessLevel.hpp" +#include "keypop/calypso/card/card/CalypsoCard.hpp" +#include "keypop/calypso/card/card/CalypsoCardSelectionExtension.hpp" +#include "keypop/calypso/card/card/ElementaryFile.hpp" +#include "keypop/calypso/card/card/FileData.hpp" +#include "keypop/calypso/card/cpp/SecureRegularModeTransactionManagerBase.hpp" +#include "keypop/calypso/card/transaction/SecureSymmetricCryptoTransactionManager.hpp" +#include "keypop/calypso/card/transaction/SymmetricCryptoSecuritySetting.hpp" +#include "keypop/calypso/crypto/legacysam/LegacySamApiFactory.hpp" +#include "keypop/calypso/crypto/legacysam/sam/LegacySam.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ChannelControl.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +#include "../common/ConfigurationUtil.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamUtil; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keyple::plugin::pcsc::PcscSupportedContactProtocol; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::WriteAccessLevel; +using keypop::calypso::card::card::CalypsoCard; +using keypop::calypso::card::card::CalypsoCardSelectionExtension; +using keypop::calypso::card::cpp::SecureRegularModeTransactionManagerBase; +using keypop::calypso::card::transaction:: + SecureSymmetricCryptoTransactionManager; +using keypop::calypso::card::transaction::SymmetricCryptoSecuritySetting; +using keypop::calypso::crypto::legacysam::LegacySamApiFactory; +using keypop::calypso::crypto::legacysam::sam::LegacySam; +using keypop::reader::CardReader; +using keypop::reader::ChannelControl; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::selection::spi::SmartCard; + +/** + * Use Case Calypso 12 - Performance measurement: embedded validation (PC/SC) + * + *

This code is dedicated to performance measurement for an embedded + * validation type transaction. + */ +class Main_PerformanceMeasurement_EmbeddedValidation_Pcsc { }; +static std::unique_ptr logger = LoggerFactory::getLogger( + typeid(Main_PerformanceMeasurement_EmbeddedValidation_Pcsc)); + +static const std::string ANSI_RESET = "\033[0m"; +static const std::string ANSI_RED = "\033[31m"; +static const std::string ANSI_GREEN = "\033[32m"; +static const std::string ANSI_YELLOW = "\033[33m"; + +/* Operating parameters. Edit as needed to match your setup. */ +static const std::string cardReaderRegex + = ConfigurationUtil::CARD_READER_NAME_REGEX; +static const std::string samReaderRegex + = ConfigurationUtil::SAM_READER_NAME_REGEX; + +/** AID: Keyple test kit profile 1, Application 2 */ static const std::string cardAid = "315449432E49434131"; + static const int counterDecrement = 1; -static const std::string logLevel = "INFO"; -static const std::vector newEventRecord = - HexUtil::toByteArray("1122334455667788112233445566778811223344556677881122334455"); -static std::string builtDate = __DATE__; -static std::string builtTime = __TIME__; - -int main() -{ - logger->info("%=============== Performance measurement: validation transaction "\ - "==============\n", GREEN); +static const std::vector newEventRecord( + HexUtil::toByteArray( + "8013C8EC55667788112233445566778811223344556677881122334455")); + +static const std::uint8_t SFI_ENVIRONMENT_AND_HOLDER = 0x07; +static const std::uint8_t SFI_EVENT_LOG = 0x08; +static const std::uint8_t SFI_CONTRACT_LIST = 0x1E; +static const std::uint8_t SFI_CONTRACTS = 0x09; +static const std::uint8_t SFI_COUNTERS = 0x19; +static const int RECORD_SIZE = 29; + +/* The plugin used to manage the readers. */ +static std::shared_ptr plugin; +/* The reader used to communicate with the card. */ +static std::shared_ptr cardReader; +/* The reader used to communicate with the SAM. */ +static std::shared_ptr samReader; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* + * The Calypso factory used to create the selection extension and transaction + * managers. + */ +static std::shared_ptr calypsoCardApiFactory; +/* The security settings for the card transaction. */ +static std::shared_ptr + symmetricCryptoSecuritySetting; + +/** + * Initializes the Keyple service. + */ +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); + plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} + +/** + * Initializes the card reader with specific configurations. + */ +static void +initCardReader() { + cardReader = ConfigurationUtil::getReader( + plugin, + cardReaderRegex, + true, + PcscReader::IsoProtocol::T1, + PcscReader::SharingMode::SHARED, + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ConfigurationUtil::ISO_CARD_PROTOCOL); +} + +/** + * Initializes the SAM reader with specific configurations. + */ +static void +initSamReader() { + samReader = ConfigurationUtil::getReader( + plugin, + samReaderRegex, + false, + PcscReader::IsoProtocol::ANY, + PcscReader::SharingMode::SHARED, + PcscSupportedContactProtocol::ISO_7816_3_T0.getName(), + ConfigurationUtil::SAM_PROTOCOL); +} + +/** + * Initializes the Calypso card extension service. + */ +static void +initCalypsoCardExtensionService() { + std::shared_ptr calypsoExtensionService( + CalypsoExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + calypsoExtensionService); + calypsoCardApiFactory = calypsoExtensionService->getCalypsoCardApiFactory(); +} + +/** + * Selects the SAM C1 for the transaction. + */ +static std::shared_ptr +selectSam(std::shared_ptr reader) { + std::shared_ptr samSelectionManager( + readerApiFactory->createCardSelectionManager()); + + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByPowerOnData( + LegacySamUtil::buildPowerOnDataFilter( + LegacySam::ProductType::SAM_C1, "")); + + std::shared_ptr legacySamApiFactory( + LegacySamExtensionService::getInstance()->getLegacySamApiFactory()); + + samSelectionManager->prepareSelection( + cardSelector, legacySamApiFactory->createLegacySamSelectionExtension()); + + const std::shared_ptr samSelectionResult( + samSelectionManager->processCardSelectionScenario(reader)); + + if (samSelectionResult->getActiveSmartCard() == nullptr) { + throw IllegalStateException("The selection of the SAM failed."); + } + + return std::dynamic_pointer_cast( + samSelectionResult->getActiveSmartCard()); +} + +/** + * Initializes the security settings for the transaction. + */ +static void +initSecuritySetting() { + std::shared_ptr sam(selectSam(samReader)); + + symmetricCryptoSecuritySetting + = calypsoCardApiFactory->createSymmetricCryptoSecuritySetting( + LegacySamExtensionService::getInstance() + ->getLegacySamApiFactory() + ->createSymmetricCryptoCardTransactionManagerFactory( + samReader, sam)); + symmetricCryptoSecuritySetting->enableRatificationMechanism(); + + /* Optimization: preload the SAM challenge for the next transaction */ + symmetricCryptoSecuritySetting->initCryptoContextForNextTransaction(); +} + +/** + * Selects the Calypso card for the transaction based on the specified + * Application Identifier (AID). + */ +static std::shared_ptr +selectCard(std::shared_ptr reader, const std::string& aid) { + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(aid); + + std::unique_ptr + calypsoCardSelectionExtension( + calypsoCardApiFactory->createCalypsoCardSelectionExtension()); + calypsoCardSelectionExtension->acceptInvalidatedCard(); + cardSelectionManager->prepareSelection( + cardSelector, std::move(calypsoCardSelectionExtension)); + + const std::shared_ptr selectionResult( + cardSelectionManager->processCardSelectionScenario(reader)); + + if (selectionResult->getActiveSmartCard() == nullptr) { + return nullptr; + } + + const std::shared_ptr card( + selectionResult->getActiveSmartCard()); + + return std::dynamic_pointer_cast(card); +} + +int +main() { + logger->info( + "%=============== Performance measurement: validation transaction " + "===============\n", + ANSI_GREEN); logger->info("Using parameters:\n"); logger->info(" CARD_READER_REGEX=%\n", cardReaderRegex); logger->info(" SAM_READER_REGEX=%\n", samReaderRegex); logger->info(" AID=%\n", cardAid); logger->info(" Counter decrement=%\n", counterDecrement); - logger->info(" log level=%\n", logLevel); - logger->info("Build data: %s %s%s\n", builtDate, builtTime, RESET); - - /* Get the main Keyple service */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); - - /* Register the PcscPlugin */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); - - /* Get the card and SAM readers whose name matches the provided regexs */ - std::shared_ptr cardReader = - ConfigurationUtil::getCardReader(plugin, ConfigurationUtil::CARD_READER_NAME_REGEX); - std::shared_ptr samReader = - ConfigurationUtil::getSamReader(plugin, ConfigurationUtil::SAM_READER_NAME_REGEX); - - /* Get the Calypso card extension service */ - std::shared_ptr calypsoCardService = - CalypsoExtensionService::getInstance(); - - /* Verify that the extension's API level is consistent with the current service. */ - smartCardService->checkCardExtension(calypsoCardService); - - /* Get the Calypso SAM SmartCard after selection. */ - std::shared_ptr calypsoSam = ConfigurationUtil::getSam(samReader); - - /* Create a card selection manager. */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); - - /* - * Create a card selection using the Calypso card extension. - * Select the card and read the record 1 of the file ENVIRONMENT_AND_HOLDER - * Prepare the selection by adding the selection to the card selection - * scenario. - */ - std::shared_ptr selection = calypsoCardService->createCardSelection(); - selection->acceptInvalidatedCard() - .filterByCardProtocol(ConfigurationUtil::ISO_CARD_PROTOCOL) - .filterByDfName(cardAid); - cardSelectionManager->prepareSelection(selection); - - std::shared_ptr cardSecuritySetting = - CalypsoExtensionService::getInstance()->createCardSecuritySetting(); - cardSecuritySetting->setControlSamResource(samReader, calypsoSam); - cardSecuritySetting->enableRatificationMechanism(); - - while (true) { - logger->info("%########################################################%\n", YELLOW, RESET); - logger->info("%## Press ENTER when the card is in the reader's field ##%\n", YELLOW, RESET); - logger->info("%## (or press 'q' + ENTER to exit) ##%\n", YELLOW, RESET); - logger->info("%########################################################%\n", YELLOW, RESET); + logger->info("%\n", ANSI_RESET); - char key = static_cast(getchar()); + /* Initialize the context */ + initKeypleService(); + initCalypsoCardExtensionService(); + initCardReader(); + initSamReader(); + initSecuritySetting(); - if (key == 'q') { + while (true) { + std::cout << std::endl + << ANSI_YELLOW + << "########################################################" + << ANSI_RESET << std::endl; + std::cout << ANSI_YELLOW + << "## Press ENTER when the card is in the reader's field ##" + << ANSI_RESET << std::endl; + std::cout << ANSI_YELLOW + << "## (or press 'q' + ENTER to exit) ##" + << ANSI_RESET << std::endl; + std::cout << ANSI_YELLOW + << "########################################################" + << ANSI_RESET << std::endl; + + std::string input; + std::getline(std::cin, input); + + if (input.find('q') != std::string::npos + || input.find('Q') != std::string::npos) { break; } @@ -164,111 +323,117 @@ int main() logger->info("Starting validation transaction...\n"); logger->info("Select application with AID = '%'\n", cardAid); - /* Read the current time used later to compute the transaction time */ - long timeStamp = System::currentTimeMillis(); + /* Read the current time used later to compute the transaction + * time */ + const auto timeStamp = std::chrono::steady_clock::now(); - /* Process the card selection scenario */ - std::shared_ptr cardSelectionResult = - cardSelectionManager->processCardSelectionScenario(cardReader); - auto calypsoCard = - std::dynamic_pointer_cast( - cardSelectionResult->getActiveSmartCard()); + std::shared_ptr calypsoCard( + selectCard(cardReader, cardAid)); if (calypsoCard == nullptr) { throw IllegalStateException("Card selection failed!"); } /* - * Create a transaction manager, open a Secure Session, read Environmentand Event - * Log. + * Create a transaction manager, open a Secure Session, read + * Environment and Event Log. + * Specifying expected response lengths in read commands + * serves as a protective measure for legacy cards. + * + * The keypop API declares + * createSecureRegularModeTransactionManager() as returning a + * SecureRegularModeTransactionManagerBase, which does not + * itself expose prepareOpenSecureSession() (it's only + * declared on SecureSymmetricCryptoTransactionManager, a + * sibling interface implemented by the same concrete + * object). A downcast is required to reach it. */ - std::shared_ptr cardTransactionManager = - CalypsoExtensionService::getInstance() - ->createCardTransaction(cardReader, calypsoCard, cardSecuritySetting); - cardTransactionManager->prepareReadRecords(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_SIZE) - .prepareReadRecords(CalypsoConstants::SFI_EVENT_LOG, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_SIZE) - .processOpening(WriteAccessLevel::DEBIT); - - const std::vector environmentAndHolderData = - calypsoCard->getFileBySfi(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER) - ->getData() - ->getContent(CalypsoConstants::RECORD_NUMBER_1); - - const std::vector eventLogData = - calypsoCard->getFileBySfi(CalypsoConstants::SFI_EVENT_LOG) - ->getData() - ->getContent(CalypsoConstants::RECORD_NUMBER_1); - - /* TODO Place here the analysis of the contextand the last event log */ - - /* Read the contract list */ - cardTransactionManager->prepareReadRecords(CalypsoConstants::SFI_CONTRACT_LIST, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_SIZE) - .processCommands(); - - const std::vector contractListData = - calypsoCard->getFileBySfi(CalypsoConstants::SFI_CONTRACT_LIST) - ->getData() - ->getContent(CalypsoConstants::RECORD_NUMBER_1); + std::unique_ptr + cardTransactionManagerBase( + calypsoCardApiFactory + ->createSecureRegularModeTransactionManager( + cardReader, + calypsoCard, + symmetricCryptoSecuritySetting)); + + auto cardTransactionManager + = dynamic_cast*>( + cardTransactionManagerBase.get()); - /* TODO Place here the analysis of the contract list */ + cardTransactionManager + ->prepareOpenSecureSession(WriteAccessLevel::DEBIT) + .prepareReadRecords( + SFI_ENVIRONMENT_AND_HOLDER, 1, 1, RECORD_SIZE) + .prepareReadRecords(SFI_EVENT_LOG, 1, 1, RECORD_SIZE) + .processCommands(ChannelControl::KEEP_OPEN); - /* Read the elected contract */ - cardTransactionManager->prepareReadRecords(CalypsoConstants::SFI_CONTRACTS, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_SIZE) - .processCommands(); + /* TODO Place here the analysis of the context and the last + * event log */ - const std::vector contractData = - calypsoCard->getFileBySfi(CalypsoConstants::SFI_CONTRACTS) - ->getData() - ->getContent(CalypsoConstants::RECORD_NUMBER_1); + /* + * Read the contract list. + * Specifying expected response lengths in read commands + * serves as a protective measure for legacy cards. + */ + cardTransactionManagerBase + ->prepareReadRecords(SFI_CONTRACT_LIST, 1, 1, RECORD_SIZE) + .processCommands(ChannelControl::KEEP_OPEN); + + /* TODO Place here the analysis of the contract list */ + + /* + * Read the elected contract. + * Specifying expected response lengths in read commands + * serves as a protective measure for legacy cards. + */ + cardTransactionManagerBase + ->prepareReadRecords(SFI_CONTRACTS, 1, 1, RECORD_SIZE) + .processCommands(ChannelControl::KEEP_OPEN); /* TODO Place here the analysis of the contract */ /* Read the contract counter */ - cardTransactionManager->prepareReadCounter(CalypsoConstants::SFI_COUNTERS, 1) - .processCommands(); + cardTransactionManagerBase->prepareReadCounter(SFI_COUNTERS, 1) + .processCommands(ChannelControl::KEEP_OPEN); - // const int counterValue = - // *(calypsoCard->getFileBySfi(CalypsoConstants::SFI_CONTRACT_LIST) - // ->getData() - // ->getContentAsCounterValue(1)); - - /* TODO Place here the preparation of the card's content update */ + /* TODO Place here the preparation of the card's content update + */ /* Add an event record and close the Secure Session */ - cardTransactionManager - ->prepareDecreaseCounter(CalypsoConstants::SFI_COUNTERS, 1, counterDecrement) - .prepareAppendRecord(CalypsoConstants::SFI_EVENT_LOG, newEventRecord) - .prepareReleaseCardChannel() - .processClosing(); + cardTransactionManagerBase + ->prepareDecreaseCounter(SFI_COUNTERS, 1, counterDecrement) + .prepareAppendRecord(SFI_EVENT_LOG, newEventRecord) + .prepareCloseSecureSession() + .processCommands(ChannelControl::KEEP_OPEN); /* Display transaction time */ - logger->info("%Transaction succeeded. Execution time: % ms%\n", - GREEN, - System::currentTimeMillis() - timeStamp, - RESET); - - } catch (const Exception& e) { - logger->error("%Transaction failed with exception: %%\n", - RED, - e.getMessage(), - RESET); + const auto elapsedMs + = std::chrono::duration_cast( + std::chrono::steady_clock::now() - timeStamp) + .count(); + logger->info( + "%Transaction succeeded. Execution time: % ms%\n", + ANSI_GREEN, + elapsedMs, + ANSI_RESET); + + /* Optimization: preload the SAM challenge for the next + * transaction */ + symmetricCryptoSecuritySetting + ->initCryptoContextForNextTransaction(); + } catch (const std::exception& e) { + logger->info( + "%Transaction failed with exception: %%\n", + ANSI_RED, + e.what(), + ANSI_RESET); } - } else { - logger->info("%No card detected%\n", RED, RESET); + logger->info("%No card detected%\n", ANSI_RED, ANSI_RESET); } } logger->info("Exiting the program on user's request.\n"); + + return 0; } diff --git a/Example_Card_Calypso/src/main/UseCase13_PerformanceMeasurement_DistributedReloading/Main_PerformanceMeasurement_DistributedReloading_Pcsc.cpp b/Example_Card_Calypso/src/main/UseCase13_PerformanceMeasurement_DistributedReloading/Main_PerformanceMeasurement_DistributedReloading_Pcsc.cpp index 66cfcf6..fdd6686 100644 --- a/Example_Card_Calypso/src/main/UseCase13_PerformanceMeasurement_DistributedReloading/Main_PerformanceMeasurement_DistributedReloading_Pcsc.cpp +++ b/Example_Card_Calypso/src/main/UseCase13_PerformanceMeasurement_DistributedReloading/Main_PerformanceMeasurement_DistributedReloading_Pcsc.cpp @@ -1,179 +1,323 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - - /* Calypsonet Terminal Reader */ -#include "CardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Util */ -#include "HexUtil.h" -#include "LoggerFactory.h" -#include "System.h" -#include "Thread.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPlugin.h" -#include "PcscPluginFactory.h" -#include "PcscPluginFactoryBuilder.h" - -/* Keyple Service Resource */ -#include "CardResourceProfileConfigurator.h" -#include "CardResourceService.h" -#include "CardResourceServiceProvider.h" -#include "PluginsConfigurator.h" - -/* Keyple Core Common */ -#include "KeyplePluginExtension.h" -#include "KeypleReaderExtension.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "ConfigurationUtil.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::calypso; -using namespace keyple::core::common; -using namespace keyple::core::service; -using namespace keyple::core::service::resource; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamUtil.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactProtocol.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/WriteAccessLevel.hpp" +#include "keypop/calypso/card/card/CalypsoCard.hpp" +#include "keypop/calypso/card/card/CalypsoCardSelectionExtension.hpp" +#include "keypop/calypso/card/card/ElementaryFile.hpp" +#include "keypop/calypso/card/card/FileData.hpp" +#include "keypop/calypso/card/cpp/SecureRegularModeTransactionManagerBase.hpp" +#include "keypop/calypso/card/transaction/SecureSymmetricCryptoTransactionManager.hpp" +#include "keypop/calypso/card/transaction/SymmetricCryptoSecuritySetting.hpp" +#include "keypop/calypso/crypto/legacysam/LegacySamApiFactory.hpp" +#include "keypop/calypso/crypto/legacysam/sam/LegacySam.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ChannelControl.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +#include "../common/ConfigurationUtil.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamUtil; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keyple::plugin::pcsc::PcscSupportedContactProtocol; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::WriteAccessLevel; +using keypop::calypso::card::card::CalypsoCard; +using keypop::calypso::card::card::CalypsoCardSelectionExtension; +using keypop::calypso::card::cpp::SecureRegularModeTransactionManagerBase; +using keypop::calypso::card::transaction:: + SecureSymmetricCryptoTransactionManager; +using keypop::calypso::card::transaction::SymmetricCryptoSecuritySetting; +using keypop::calypso::crypto::legacysam::LegacySamApiFactory; +using keypop::calypso::crypto::legacysam::sam::LegacySam; +using keypop::reader::CardReader; +using keypop::reader::ChannelControl; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::selection::spi::SmartCard; /** - * Use Case Calypso 12 � Performance measurement: reloading (PC/SC) + * Use Case Calypso 13 - Performance measurement: distributed reloading + * (PC/SC) * - *

This code is dedicated to performance measurement for a reloading type transaction. - * - *

It implements the scenario described here: - * - *

Any unexpected behavior will result in runtime exceptions. + *

This code is dedicated to performance measurement for a reloading type + * transaction. */ -class Main_PerformanceMeasurement_DistributedReloading_Pcsc {}; -const std::unique_ptr logger = -LoggerFactory::getLogger(typeid(Main_PerformanceMeasurement_DistributedReloading_Pcsc)); - -/* User interface management */ -static const std::string RESET = "\u001B[0m"; -static const std::string RED = "\u001B[31m"; -static const std::string GREEN = "\u001B[32m"; -static const std::string YELLOW = "\u001B[33m"; - -/* Operating parameters */ -static const std::string cardReaderRegex = - ".*ASK LoGO.*|.*Contactless.*|.*ACR122U.*|.*00 01.*|.*5x21-CL 0.*"; -static const std::string samReaderRegex = - ".*Identive.*|.*HID.*|.*SAM.*|.*00 00.*|.*5x21 0.*"; +class Main_PerformanceMeasurement_DistributedReloading_Pcsc { }; +static std::unique_ptr logger = LoggerFactory::getLogger( + typeid(Main_PerformanceMeasurement_DistributedReloading_Pcsc)); + +static const std::string ANSI_RESET = "\033[0m"; +static const std::string ANSI_RED = "\033[31m"; +static const std::string ANSI_GREEN = "\033[32m"; +static const std::string ANSI_YELLOW = "\033[33m"; + +/* Operating parameters. Edit as needed to match your setup. */ +static const std::string cardReaderRegex + = ConfigurationUtil::CARD_READER_NAME_REGEX; +static const std::string samReaderRegex + = ConfigurationUtil::SAM_READER_NAME_REGEX; + +/** AID: Keyple test kit profile 1, Application 2 */ static const std::string cardAid = "315449432E49434131"; -static const int counterIncrement = 10; -static const std::string logLevel = "INFO"; -static const std::vector newContractListRecord = - HexUtil::toByteArray("00112233445566778899AABBCCDDEEFF00112233445566778899AABBCC"); -static const std::vector newContractRecord = -HexUtil::toByteArray("AABBCCDDEEFFAABBCCDDEEFFAABBCCDDEEFFAABBCCDDEEFFAABBCCDDEE"); -static std::string builtDate = __DATE__; -static std::string builtTime = __TIME__; - -int main() -{ - logger->info("%=============== Performance measurement: validation transaction "\ - "===============\n", GREEN); + +static const int counterIncrement = 1; +static const std::vector newContractListRecord( + HexUtil::toByteArray( + "1E00000000000000000000000000000000000000000000000000000000")); +static const std::vector newContractRecord( + HexUtil::toByteArray( + "0900000000000000000000000000000000000000000000000000000000")); + +static const std::uint8_t SFI_ENVIRONMENT_AND_HOLDER = 0x07; +static const std::uint8_t SFI_CONTRACT_LIST = 0x1E; +static const std::uint8_t SFI_CONTRACTS = 0x09; +static const std::uint8_t SFI_COUNTERS = 0x19; +static const int RECORD_SIZE = 29; + +/* The plugin used to manage the readers. */ +static std::shared_ptr plugin; +/* The reader used to communicate with the card. */ +static std::shared_ptr cardReader; +/* The reader used to communicate with the SAM. */ +static std::shared_ptr samReader; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* + * The Calypso factory used to create the selection extension and transaction + * managers. + */ +static std::shared_ptr calypsoCardApiFactory; +/* The security settings for the card transaction. */ +static std::shared_ptr + symmetricCryptoSecuritySetting; + +/** + * Initializes the Keyple service. + */ +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); + plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} + +/** + * Initializes the card reader with specific configurations. + */ +static void +initCardReader() { + cardReader = ConfigurationUtil::getReader( + plugin, + cardReaderRegex, + true, + PcscReader::IsoProtocol::T1, + PcscReader::SharingMode::SHARED, + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ConfigurationUtil::ISO_CARD_PROTOCOL); +} + +/** + * Initializes the SAM reader with specific configurations. + */ +static void +initSamReader() { + samReader = ConfigurationUtil::getReader( + plugin, + samReaderRegex, + false, + PcscReader::IsoProtocol::ANY, + PcscReader::SharingMode::SHARED, + PcscSupportedContactProtocol::ISO_7816_3_T0.getName(), + ConfigurationUtil::SAM_PROTOCOL); +} + +/** + * Initializes the Calypso card extension service. + */ +static void +initCalypsoCardExtensionService() { + std::shared_ptr calypsoExtensionService( + CalypsoExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + calypsoExtensionService); + calypsoCardApiFactory = calypsoExtensionService->getCalypsoCardApiFactory(); +} + +/** + * Selects the SAM C1 for the transaction. + */ +static std::shared_ptr +selectSam(std::shared_ptr reader) { + std::shared_ptr samSelectionManager( + readerApiFactory->createCardSelectionManager()); + + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByPowerOnData( + LegacySamUtil::buildPowerOnDataFilter( + LegacySam::ProductType::SAM_C1, "")); + + std::shared_ptr legacySamApiFactory( + LegacySamExtensionService::getInstance()->getLegacySamApiFactory()); + + samSelectionManager->prepareSelection( + cardSelector, legacySamApiFactory->createLegacySamSelectionExtension()); + + const std::shared_ptr samSelectionResult( + samSelectionManager->processCardSelectionScenario(reader)); + + if (samSelectionResult->getActiveSmartCard() == nullptr) { + throw IllegalStateException("The selection of the SAM failed."); + } + + return std::dynamic_pointer_cast( + samSelectionResult->getActiveSmartCard()); +} + +/** + * Initializes the security settings for the transaction. + */ +static void +initSecuritySetting() { + std::shared_ptr sam(selectSam(samReader)); + + symmetricCryptoSecuritySetting + = calypsoCardApiFactory->createSymmetricCryptoSecuritySetting( + LegacySamExtensionService::getInstance() + ->getLegacySamApiFactory() + ->createSymmetricCryptoCardTransactionManagerFactory( + samReader, sam)); + symmetricCryptoSecuritySetting->enableRatificationMechanism(); +} + +/** + * Selects the Calypso card for the transaction based on the specified + * Application Identifier (AID), add additional read commands to retrieve the + * "Environment and Holder" and "Contract List" files. + */ +static std::shared_ptr +selectCard(std::shared_ptr reader, const std::string& aid) { + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(aid); + + std::unique_ptr + calypsoCardSelectionExtension( + calypsoCardApiFactory->createCalypsoCardSelectionExtension()); + calypsoCardSelectionExtension->acceptInvalidatedCard() + .prepareReadRecord(SFI_ENVIRONMENT_AND_HOLDER, 1) + .prepareReadRecord(SFI_CONTRACT_LIST, 1); + cardSelectionManager->prepareSelection( + cardSelector, std::move(calypsoCardSelectionExtension)); + + const std::shared_ptr selectionResult( + cardSelectionManager->processCardSelectionScenario(reader)); + + if (selectionResult->getActiveSmartCard() == nullptr) { + return nullptr; + } + + const std::shared_ptr card( + selectionResult->getActiveSmartCard()); + + return std::dynamic_pointer_cast(card); +} + +int +main() { + logger->info( + "%=============== Performance measurement: validation transaction " + "===============\n", + ANSI_GREEN); logger->info("Using parameters:\n"); logger->info(" CARD_READER_REGEX=%\n", cardReaderRegex); logger->info(" SAM_READER_REGEX=%\n", samReaderRegex); logger->info(" AID=%\n", cardAid); logger->info(" Counter increment=%\n", counterIncrement); - logger->info(" log level=%\n", logLevel); - logger->info("Build data: %s %s%s\n", builtDate, builtTime, RESET); - - /* Get the main Keyple service */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); - - /* Register the PcscPlugin */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); - - /* Get the card readers whose name matches the provided regex */ - std::shared_ptr cardReader = - ConfigurationUtil::getCardReader(plugin, ConfigurationUtil::CARD_READER_NAME_REGEX); - - /* Get the Calypso card extension service */ - std::shared_ptr calypsoCardService = - CalypsoExtensionService::getInstance(); - - /* Verify that the extension's API level is consistent with the current service. */ - smartCardService->checkCardExtension(calypsoCardService); - - /* Get the core card selection manager. */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); - - /* - * Create a card selection using the Calypso card extension. - * Select the card and read the record 1 of the file ENVIRONMENT_AND_HOLDER - * Prepare the selection by adding the selection to the card selection - * scenario. - */ - std::shared_ptr selection = calypsoCardService->createCardSelection(); - selection->acceptInvalidatedCard() - .filterByCardProtocol(ConfigurationUtil::ISO_CARD_PROTOCOL) - .filterByDfName(cardAid) - .prepareReadRecord(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER, - CalypsoConstants::RECORD_NUMBER_1) - .prepareReadRecord(CalypsoConstants::SFI_CONTRACT_LIST, - CalypsoConstants::RECORD_NUMBER_1); - cardSelectionManager->prepareSelection(selection); - - /* Configure the card resource service for the targeted SAM. */ - ConfigurationUtil::setupCardResourceService(plugin, - samReaderRegex, CalypsoConstants::SAM_PROFILE_NAME); - - /* - * Create security settings that reference the same SAM profile requested from the card resource - * service. - */ - std::shared_ptr samResource = - CardResourceServiceProvider::getService() - ->getCardResource(CalypsoConstants::SAM_PROFILE_NAME); - - if (samResource == nullptr) { - throw IllegalStateException("No SAM resource available."); - } - - logger->info("Calypso SAM = %\n", samResource->getSmartCard()); + logger->info("%\n", ANSI_RESET); - std::shared_ptr cardSecuritySetting = - CalypsoExtensionService::getInstance()->createCardSecuritySetting(); - cardSecuritySetting->setControlSamResource( - samResource->getReader(), - std::dynamic_pointer_cast(samResource->getSmartCard())); + /* Initialize the context */ + initKeypleService(); + initCalypsoCardExtensionService(); + initCardReader(); + initSamReader(); + initSecuritySetting(); while (true) { - logger->info("%########################################################%\n", YELLOW, RESET); - logger->info("%## Press ENTER when the card is in the reader's field ##%\n", YELLOW, RESET); - logger->info("%## (or press 'q' + ENTER to exit) ##%\n", YELLOW, RESET); - logger->info("%########################################################%\n", YELLOW, RESET); - - char key = static_cast(getchar()); - - if (key == 'q') { + std::cout << std::endl + << ANSI_YELLOW + << "########################################################" + << ANSI_RESET << std::endl; + std::cout << ANSI_YELLOW + << "## Press ENTER when the card is in the reader's field ##" + << ANSI_RESET << std::endl; + std::cout << ANSI_YELLOW + << "## (or press 'q' + ENTER to exit) ##" + << ANSI_RESET << std::endl; + std::cout << ANSI_YELLOW + << "########################################################" + << ANSI_RESET << std::endl; + + std::string input; + std::getline(std::cin, input); + + if (input.find('q') != std::string::npos + || input.find('Q') != std::string::npos) { break; } @@ -182,114 +326,106 @@ int main() logger->info("Starting reloading transaction...\n"); logger->info("Select application with AID = '%'\n", cardAid); - /* Read the current time used later to compute the transaction time */ - long timeStamp = System::currentTimeMillis(); + /* Read the current time used later to compute the transaction + * time */ + const auto timeStamp = std::chrono::steady_clock::now(); - /* Process the card selection scenario */ - std::shared_ptr cardSelectionResult = - cardSelectionManager->processCardSelectionScenario(cardReader); - auto calypsoCard = - std::dynamic_pointer_cast( - cardSelectionResult->getActiveSmartCard()); + std::shared_ptr calypsoCard( + selectCard(cardReader, cardAid)); if (calypsoCard == nullptr) { throw IllegalStateException("Card selection failed!"); } - std::vector environmentAndHolderData = - calypsoCard->getFileBySfi(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER) - ->getData() - ->getContent(CalypsoConstants::RECORD_NUMBER_1); - - std::vector contractListData = - calypsoCard->getFileBySfi(CalypsoConstants::SFI_CONTRACT_LIST) - ->getData() - ->getContent(CalypsoConstants::RECORD_NUMBER_1); + /* TODO Place here the pre-analysis of the context and the + * contract list */ - /* TODO Place here the analysis of the contextand the last event log */ + const int nbContractRecordsToRead + = calypsoCard->getProductType() + == CalypsoCard::ProductType::BASIC + ? 1 + : 2; + const int nbCountersToRead + = calypsoCard->getProductType() + == CalypsoCard::ProductType::BASIC + ? 1 + : 2; /* - * Create a transaction manager, open a Secure Session, read Environmentand Event - * Log. + * Create a transaction manager, open a Secure Session, read + * Environment and Event Log. + * Specifying expected response lengths in read commands + * serves as a protective measure for legacy cards. + * + * The keypop API declares + * createSecureRegularModeTransactionManager() as returning a + * SecureRegularModeTransactionManagerBase, which does not + * itself expose prepareOpenSecureSession() (it's only + * declared on SecureSymmetricCryptoTransactionManager, a + * sibling interface implemented by the same concrete + * object). A downcast is required to reach it. */ - std::shared_ptr cardTransactionManager = - CalypsoExtensionService::getInstance() - ->createCardTransaction(cardReader, calypsoCard, cardSecuritySetting); - cardTransactionManager->prepareReadRecords(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_SIZE) - .prepareReadRecords(CalypsoConstants::SFI_CONTRACT_LIST, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_SIZE) - .prepareReadRecords(CalypsoConstants::SFI_CONTRACTS, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_NUMBER_2, - CalypsoConstants::RECORD_SIZE) - .prepareReadCounter(CalypsoConstants::SFI_COUNTERS, 2) - .processOpening(WriteAccessLevel::LOAD); - - environmentAndHolderData = - calypsoCard->getFileBySfi(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER) - ->getData() - ->getContent(CalypsoConstants::RECORD_NUMBER_1); - - contractListData = calypsoCard->getFileBySfi(CalypsoConstants::SFI_CONTRACT_LIST) - ->getData() - ->getContent(CalypsoConstants::RECORD_NUMBER_1); - - const std::vector contract1Data = - calypsoCard->getFileBySfi(CalypsoConstants::SFI_CONTRACTS) - ->getData() - ->getContent(CalypsoConstants::RECORD_NUMBER_1); - - const std::vector contract2Data = - calypsoCard->getFileBySfi(CalypsoConstants::SFI_CONTRACTS) - ->getData() - ->getContent(CalypsoConstants::RECORD_NUMBER_2); - - // const int counter1Value = - // *(calypsoCard->getFileBySfi(CalypsoConstants::SFI_CONTRACT_LIST) - // ->getData() - // ->getContentAsCounterValue(1)); - - // const int counter2Value = - // *(calypsoCard->getFileBySfi(CalypsoConstants::SFI_CONTRACT_LIST) - // ->getData() - // ->getContentAsCounterValue(2)); + std::unique_ptr + cardTransactionManagerBase( + calypsoCardApiFactory + ->createSecureRegularModeTransactionManager( + cardReader, + calypsoCard, + symmetricCryptoSecuritySetting)); + + auto cardTransactionManager + = dynamic_cast*>( + cardTransactionManagerBase.get()); + + cardTransactionManager + ->prepareOpenSecureSession(WriteAccessLevel::LOAD) + .prepareReadRecords( + SFI_ENVIRONMENT_AND_HOLDER, 1, 1, RECORD_SIZE) + .prepareReadRecords(SFI_CONTRACT_LIST, 1, 1, RECORD_SIZE) + .prepareReadRecords( + SFI_CONTRACTS, 1, nbContractRecordsToRead, RECORD_SIZE) + .prepareReadCounter(SFI_COUNTERS, nbCountersToRead) + .processCommands(ChannelControl::KEEP_OPEN); /* - * TODO Place here the analysis of the context, the contract list, the contracts, - * the counters and the preparation of the card's content update + * TODO Place here the analysis of the context, the contract + * list, the contracts, the counters and the preparation of + * the card's content update */ - /* Update contract listand contract, increase counterand close the Secure Session */ - cardTransactionManager->prepareUpdateRecord(CalypsoConstants::SFI_CONTRACT_LIST, - CalypsoConstants::RECORD_NUMBER_1, - newContractListRecord) - .prepareUpdateRecord(CalypsoConstants::SFI_CONTRACTS, - CalypsoConstants::RECORD_NUMBER_1, - newContractRecord) - .prepareIncreaseCounter(CalypsoConstants::SFI_COUNTERS, - 1, - counterIncrement) - .prepareReleaseCardChannel() - .processClosing(); + /* Update contract list and contract, increase counter and close + * the Secure Session */ + cardTransactionManagerBase + ->prepareUpdateRecord( + SFI_CONTRACT_LIST, 1, newContractListRecord) + .prepareUpdateRecord(SFI_CONTRACTS, 1, newContractRecord) + .prepareIncreaseCounter(SFI_COUNTERS, 1, counterIncrement) + .prepareCloseSecureSession() + .processCommands(ChannelControl::CLOSE_AFTER); /* Display transaction time */ - logger->info("%Transaction succeeded. Execution time: % ms%\n", - GREEN, - System::currentTimeMillis() - timeStamp, - RESET); - - } catch (const Exception& e) { - logger->error("%Transaction failed with exception: %%\n", - RED, - e.getMessage(), - RESET); + const auto elapsedMs + = std::chrono::duration_cast( + std::chrono::steady_clock::now() - timeStamp) + .count(); + logger->info( + "%Transaction succeeded. Execution time: % ms%\n", + ANSI_GREEN, + elapsedMs, + ANSI_RESET); + } catch (const std::exception& e) { + logger->info( + "%Transaction failed with exception: %%\n", + ANSI_RED, + e.what(), + ANSI_RESET); } + } else { + logger->info("%No card detected%\n", ANSI_RED, ANSI_RESET); } } logger->info("Exiting the program on user's request.\n"); + + return 0; } diff --git a/Example_Card_Calypso/src/main/UseCase1_ExplicitSelectionAid/Main_ExplicitSelectionAid_Pcsc.cpp b/Example_Card_Calypso/src/main/UseCase1_ExplicitSelectionAid/Main_ExplicitSelectionAid_Pcsc.cpp index 9581ef4..3216169 100644 --- a/Example_Card_Calypso/src/main/UseCase1_ExplicitSelectionAid/Main_ExplicitSelectionAid_Pcsc.cpp +++ b/Example_Card_Calypso/src/main/UseCase1_ExplicitSelectionAid/Main_ExplicitSelectionAid_Pcsc.cpp @@ -1,147 +1,212 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Core Util */ -#include "HexUtil.h" -#include "ContactCardCommonProtocol.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" -#include "StringUtils.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPlugin.h" -#include "PcscPluginFactory.h" -#include "PcscPluginFactoryBuilder.h" -#include "PcscReader.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "ConfigurationUtil.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::calypso; -using namespace keyple::core::service; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::core::util::protocol; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/card/CalypsoCard.hpp" +#include "keypop/calypso/card/card/CalypsoCardSelectionExtension.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +#include "../common/ConfigurationUtil.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::card::CalypsoCard; +using keypop::calypso::card::card::CalypsoCardSelectionExtension; +using keypop::reader::CardReader; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::selection::spi::SmartCard; /** - *

Use Case Calypso 1 – Explicit Selection Aid (PC/SC)

+ * Handles the process of explicit selection of a Calypso card using the + * PC/SC plugin, without implementing the observation of the reader. Ensure + * the Calypso card is inserted before launching the program. * - *

We demonstrate here the direct selection of a Calypso card inserted in a reader. No - * observation of the reader is implemented in this example, so the card must be present in the - * reader before the program is launched. + *

This class demonstrates the explicit selection of a Calypso card, + * including the initialization of the card selection manager after verifying + * the presence of an ISO 14443-4 card in the reader, and the attempt to + * select the specified Calypso card characterized by its AID. * - *

Scenario:

+ *

Key Functionalities

* *
    - *
  • Checks if an ISO 14443-4 card is in the reader, enables the card selection manager. - *
  • Attempts to select the specified card (here a Calypso card characterized by its AID) with - * an AID-based application selection scenario, including reading a file record. - *
  • Output the collected data (FCI, ATR and file record content). + *
  • Check for an ISO 14443-4 card in the reader and enable the card + * selection manager. + *
  • Attempt to select a specified Calypso card using AID-based + * application selection scenario. + *
  • Read and output the collected data including Calypso serial number + * and file record content. *
- * - *

Any unexpected behavior will result in a runtime exceptions. */ -class Main_ExplicitSelectionAid_Pcsc {}; -static std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_ExplicitSelectionAid_Pcsc)); - -int main() -{ - /* Get the instance of the SmartCardService */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); - - /* Register the PcscPlugin, get the corresponding PC/SC plugin in return */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); - - /* Get the Calypso card extension service */ - std::shared_ptr calypsoCardService = - CalypsoExtensionService::getInstance(); +class Main_ExplicitSelectionAid_Pcsc { }; +static std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_ExplicitSelectionAid_Pcsc)); + +/** AID: Keyple test kit profile 1, Application 2 */ +static const std::string AID = "315449432E49434131"; + +/* File identifiers */ +static const std::uint8_t SFI_ENVIRONMENT_AND_HOLDER = 0x07; + +/* The plugin used to manage the reader. */ +static std::shared_ptr plugin; +/* The reader used to communicate with the card. */ +static std::shared_ptr cardReader; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* + * The Calypso factory used to create the selection extension and transaction + * managers. + */ +static std::shared_ptr calypsoCardApiFactory; - /* Verify that the extension's API level is consistent with the current service. */ - smartCardService->checkCardExtension(calypsoCardService); +/** + * Initializes the Keyple service. + * + *

Gets an instance of the smart card service, registers the PC/SC plugin, + * and prepares the reader API factory for use. + */ +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); + plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} - /* Get the contactless reader whose name matches the provided regex */ - std::shared_ptr cardReader = - ConfigurationUtil::getCardReader(plugin, ConfigurationUtil::CARD_READER_NAME_REGEX); +/** + * Initializes the card reader with specific configurations. + * + *

Prepares the card reader using a predefined set of configurations, + * including the card reader name regex, ISO protocol, and sharing mode. + */ +static void +initCardReader() { + cardReader = ConfigurationUtil::getReader( + plugin, + ConfigurationUtil::CARD_READER_NAME_REGEX, + true, + PcscReader::IsoProtocol::T1, + PcscReader::SharingMode::SHARED, + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ConfigurationUtil::ISO_CARD_PROTOCOL); +} - logger->info("=============== " \ - "UseCase Calypso #1: AID based explicit selection " \ - "=================="); +/** + * Initializes the Calypso card extension service. + */ +static void +initCalypsoCardExtensionService() { + std::shared_ptr calypsoExtensionService( + CalypsoExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + calypsoExtensionService); + calypsoCardApiFactory = calypsoExtensionService->getCalypsoCardApiFactory(); +} + +int +main() { + logger->info( + "= UseCase Calypso #1: AID based explicit selection " + "==================\n"); + + /* Initialize the context */ + initKeypleService(); + initCardReader(); + initCalypsoCardExtensionService(); /* Check if a card is present in the reader */ if (!cardReader->isCardPresent()) { throw IllegalStateException("No card is present in the reader."); } - logger->info("= #### Select application with AID = '%'\n", CalypsoConstants::AID); - - /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); - - /* - * Create a card selection using the Calypso card extension. - * Prepare the selection by adding the created Calypso card selection to the card selection - * scenario. - */ - std::shared_ptr selection = calypsoCardService->createCardSelection(); - selection->filterByDfName(CalypsoConstants::AID) - .acceptInvalidatedCard() - .prepareReadRecord(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER, - CalypsoConstants::RECORD_NUMBER_1); - cardSelectionManager->prepareSelection(selection); + logger->info("= #### Select application with AID = '%'\n", AID); + + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(AID); + std::unique_ptr + calypsoCardSelectionExtension( + calypsoCardApiFactory->createCalypsoCardSelectionExtension()); + calypsoCardSelectionExtension->acceptInvalidatedCard().prepareReadRecord( + SFI_ENVIRONMENT_AND_HOLDER, 1); + cardSelectionManager->prepareSelection( + cardSelector, std::move(calypsoCardSelectionExtension)); /* Actual card communication: run the selection scenario */ - const std::shared_ptr selectionResult = - cardSelectionManager->processCardSelectionScenario(cardReader); + const std::shared_ptr selectionResult + = cardSelectionManager->processCardSelectionScenario(cardReader); /* Check the selection result */ if (selectionResult->getActiveSmartCard() == nullptr) { - throw IllegalStateException("The selection of the application '" + - CalypsoConstants::AID + - "' failed."); + throw IllegalStateException( + "The selection of the application '" + AID + "' failed."); } /* Get the SmartCard resulting of the selection */ - const auto calypsoCard = - std::dynamic_pointer_cast(selectionResult->getActiveSmartCard()); + const std::shared_ptr card( + selectionResult->getActiveSmartCard()); + auto calypsoCard = std::dynamic_pointer_cast(card); logger->info("= SmartCard = %\n", calypsoCard); - const std::string csn = HexUtil::toHex(calypsoCard->getApplicationSerialNumber()); + const std::string csn( + HexUtil::toHex(calypsoCard->getApplicationSerialNumber())); logger->info("Calypso Serial Number = %\n", csn); - const std::string sfiEnvHolder = HexUtil::toHex(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER); - logger->info("File SFI %h, rec 1: FILE_CONTENT = %\n", - sfiEnvHolder, - calypsoCard->getFileBySfi(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER)); + const std::string sfiEnvHolder(HexUtil::toHex(SFI_ENVIRONMENT_AND_HOLDER)); + logger->info( + "File SFI %h, rec 1: FILE_CONTENT = %\n", + sfiEnvHolder, + calypsoCard->getFileBySfi(SFI_ENVIRONMENT_AND_HOLDER)); logger->info("= #### End of the Calypso card processing\n"); return 0; -} \ No newline at end of file +} diff --git a/Example_Card_Calypso/src/main/UseCase1_ExplicitSelectionAid/Main_ExplicitSelectionAid_Stub.cpp b/Example_Card_Calypso/src/main/UseCase1_ExplicitSelectionAid/Main_ExplicitSelectionAid_Stub.cpp index db3fb7f..5f61383 100644 --- a/Example_Card_Calypso/src/main/UseCase1_ExplicitSelectionAid/Main_ExplicitSelectionAid_Stub.cpp +++ b/Example_Card_Calypso/src/main/UseCase1_ExplicitSelectionAid/Main_ExplicitSelectionAid_Stub.cpp @@ -1,160 +1,225 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" -#include "ConfigurableCardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Core Util */ -#include "HexUtil.h" -#include "ContactCardCommonProtocol.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" -#include "StringUtils.h" - -/* Keyple Plugin Stub */ -#include "StubPlugin.h" -#include "StubPluginFactoryBuilder.h" -#include "StubReader.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "ConfigurationUtil.h" -#include "StubSmartCardFactory.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::calypso; -using namespace keyple::core::service; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::core::util::protocol; -using namespace keyple::plugin::stub; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/stub/StubPluginFactoryBuilder.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/card/CalypsoCard.hpp" +#include "keypop/calypso/card/card/CalypsoCardSelectionExtension.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +#include "../common/StubSmartCardFactory.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::stub::StubPluginFactoryBuilder; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::card::CalypsoCard; +using keypop::calypso::card::card::CalypsoCardSelectionExtension; +using keypop::reader::CardReader; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::selection::spi::SmartCard; /** - *

Use Case Calypso 1 – Explicit Selection Aid (Stub)

+ * Handles the process of explicit selection of a Calypso card using the Stub + * plugin, without implementing the observation of the reader. Ensure the + * Calypso card is inserted before launching the program. * - *

We demonstrate here the direct selection of a Calypso card inserted in a reader. No - * observation of the reader is implemented in this example, so the card must be present in the - * reader before the program is launched. + *

This class demonstrates the explicit selection of a Calypso card, + * including the initialization of the card selection manager after verifying + * the presence of an ISO 14443-4 card in the reader, and the attempt to select + * the specified Calypso card characterized by its AID. * - *

Scenario:

+ *

It also demonstrates how to retrieve and output collected data such as + * serial number and file record content after the selection scenario based on + * AID. + * + *

Key Functionalities

* *
    - *
  • Checks if an ISO 14443-4 card is in the reader, enables the card selection manager. - *
  • Attempts to select the specified card (here a Calypso card characterized by its AID) with - * an AID-based application selection scenario, including reading a file record. - *
  • Output the collected data (FCI, ATR and file record content). + *
  • Check for an ISO 14443-4 card in the reader and enable the card + * selection manager. + *
  • Attempt to select a specified Calypso card using AID-based application + * selection scenario. + *
  • Read and output the collected data including Calypso serial number and + * file record content. *
- * - * All results are logged with slf4j. - * - *

Any unexpected behavior will result in a runtime exceptions. */ -class Main_ExplicitSelectionAid_Stub {}; -static std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_ExplicitSelectionAid_Stub)); +class Main_ExplicitSelectionAid_Stub { }; +static std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_ExplicitSelectionAid_Stub)); static const std::string CARD_READER_NAME = "Stub card reader"; -int main() -{ - /* Get the instance of the SmartCardService */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); +/** AID: Keyple test kit profile 1, Application 2 */ +static const std::string AID = "315449432E49434131"; + +/* File identifiers */ +static const std::uint8_t SFI_ENVIRONMENT_AND_HOLDER = 0x07; + +/* The plugin used to manage the reader. */ +static std::shared_ptr plugin; +/* The reader used to communicateate with the card. */ +static std::shared_ptr cardReader; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* + * The Calypso factory used to create the selection extension and transaction + * managers. + */ +static std::shared_ptr calypsoCardApiFactory; + +/** + * Initializes the Keyple service. + * + *

Gets an instance of the smart card service, registers the Stub plugin, and + * prepares the + * reader API factory for use. + * + *

Retrieves the {@link ReaderApiFactory}. + */ +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); /* - * Register the StubPlugin with the SmartCardService, plug a Calypso card stub - * get the corresponding generic plugin in return. + * Register the StubPlugin with the SmartCardService and plug in stubs for a + * Calypso card. */ - std::shared_ptr pluginFactory = + plugin = smartCardService->registerPlugin( StubPluginFactoryBuilder::builder() - ->withStubReader(CARD_READER_NAME, true, StubSmartCardFactory::getStubCard()) - .build(); - std::shared_ptr plugin = smartCardService->registerPlugin(pluginFactory); - - std::shared_ptr cardReader = plugin->getReader(CARD_READER_NAME); - - std::dynamic_pointer_cast(cardReader) - ->activateProtocol(ConfigurationUtil::ISO_CARD_PROTOCOL, - ConfigurationUtil::ISO_CARD_PROTOCOL); + ->withStubReader( + CARD_READER_NAME, true, StubSmartCardFactory::getStubCard()) + .build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} - /* Get the Calypso card extension service */ - auto calypsoCardService = CalypsoExtensionService::getInstance(); - - /* Verify that the extension's API level is consistent with the current service */ - smartCardService->checkCardExtension(calypsoCardService); +/** + * Initializes the card reader with specific configurations. + * + *

Prepares the card reader using a predefined set of configurations, + * including the card reader name regex, ISO protocol, and sharing mode. + */ +static void +initCardReader() { + cardReader = plugin->getReader(CARD_READER_NAME); +} - logger->info("=============== " \ - "UseCase Calypso #1: AID based explicit selection " \ - "==================\n"); +/** + * Initializes the Calypso card extension service. + * + *

Retrieves the {@link CalypsoCardApiFactory}. + */ +static void +initCalypsoCardExtensionService() { + std::shared_ptr calypsoExtensionService( + CalypsoExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + calypsoExtensionService); + calypsoCardApiFactory = calypsoExtensionService->getCalypsoCardApiFactory(); +} + +int +main() { + logger->info( + "= UseCase Calypso #1: AID based explicit selection " + "==================\n"); + + /* Initialize the context */ + initKeypleService(); + initCardReader(); + initCalypsoCardExtensionService(); + + logger->info( + "=============== " + "UseCase Calypso #1: AID based explicit selection " + "==================\n"); /* Check if a card is present in the reader */ if (!cardReader->isCardPresent()) { throw IllegalStateException("No card is present in the reader."); } - logger->info("= #### Select application with AID = '%'\n", CalypsoConstants::AID); - - /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); - - /* - * Create a card selection using the Calypso card extension. - * Prepare the selection by adding the created Calypso card selection to the card selection - * scenario. - */ - std::shared_ptr cardSelection = calypsoCardService->createCardSelection(); - cardSelection->filterByDfName(CalypsoConstants::AID) - .acceptInvalidatedCard() - .prepareReadRecord( - CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER, - CalypsoConstants::RECORD_NUMBER_1); - cardSelectionManager->prepareSelection(cardSelection); + logger->info("= #### Select application with AID = '%'\n", AID); + + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(AID); + std::unique_ptr + calypsoCardSelectionExtension( + calypsoCardApiFactory->createCalypsoCardSelectionExtension()); + calypsoCardSelectionExtension->acceptInvalidatedCard().prepareReadRecord( + SFI_ENVIRONMENT_AND_HOLDER, 1); + cardSelectionManager->prepareSelection( + cardSelector, std::move(calypsoCardSelectionExtension)); /* Actual card communication: run the selection scenario */ - const std::shared_ptr selectionResult = - cardSelectionManager->processCardSelectionScenario(cardReader); + const std::shared_ptr selectionResult + = cardSelectionManager->processCardSelectionScenario(cardReader); /* Check the selection result */ if (selectionResult->getActiveSmartCard() == nullptr) { - throw IllegalStateException("The selection of the application '" + - CalypsoConstants::AID + - "' failed."); + throw IllegalStateException( + "The selection of the application '" + AID + "' failed."); } /* Get the SmartCard resulting of the selection */ - const std::shared_ptr card = selectionResult->getActiveSmartCard(); + const std::shared_ptr card( + selectionResult->getActiveSmartCard()); auto calypsoCard = std::dynamic_pointer_cast(card); logger->info("= SmartCard = %\n", calypsoCard); - const std::string csn = HexUtil::toHex(calypsoCard->getApplicationSerialNumber()); + const std::string csn( + HexUtil::toHex(calypsoCard->getApplicationSerialNumber())); logger->info("Calypso Serial Number = %\n", csn); - const std::string sfiEnvHolder = HexUtil::toHex(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER); - logger->info("File SFI %h, rec 1: FILE_CONTENT = %\n", - sfiEnvHolder, - calypsoCard->getFileBySfi(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER)); + const std::string sfiEnvHolder(HexUtil::toHex(SFI_ENVIRONMENT_AND_HOLDER)); + logger->info( + "File SFI %h, rec 1: FILE_CONTENT = %\n", + sfiEnvHolder, + calypsoCard->getFileBySfi(SFI_ENVIRONMENT_AND_HOLDER)); logger->info("= #### End of the Calypso card processing\n"); return 0; -} \ No newline at end of file +} diff --git a/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/CardReaderObserver.cpp b/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/CardReaderObserver.cpp index f5c692c..6fe1e76 100644 --- a/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/CardReaderObserver.cpp +++ b/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/CardReaderObserver.cpp @@ -1,93 +1,95 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ -#include "CardReaderObserver.h" +#include "CardReaderObserver.hpp" -/* Calypsonet Terminal Calypso */ -#include "CalypsoCard.h" +#include +#include -/* Calypsonet Terminal Reader */ -#include "ObservableCardReader.h" +#include "keyple/core/util/HexUtil.hpp" +#include "keypop/calypso/card/card/CalypsoCard.hpp" -/* Keyple Core Util */ -#include "HexUtil.h" -#include "StringUtils.h" +using keyple::core::util::HexUtil; +using keypop::calypso::card::card::CalypsoCard; -/* Keyple Cpp Examples */ -#include "CalypsoConstants.h" +/* File identifiers */ +static const std::uint8_t SFI_ENVIRONMENT_AND_HOLDER = 0x07; -/* Keyple Core Service */ -#include "ObservableReader.h" - -using namespace calypsonet::terminal::calypso::card; -using namespace calypsonet::terminal::reader; -using namespace keyple::core::service; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; - -CardReaderObserver::CardReaderObserver(std::shared_ptr reader, - std::shared_ptr cardSelectionManager) -: mReader(reader), mCardSelectionManager(cardSelectionManager) {} +CardReaderObserver::CardReaderObserver( + std::shared_ptr reader, + std::shared_ptr cardSelectionManager) +: mReader(reader) +, mCardSelectionManager(cardSelectionManager) { +} -void CardReaderObserver::onReaderEvent(const std::shared_ptr event) -{ +void +CardReaderObserver::onReaderEvent( + const std::shared_ptr event) { switch (event->getType()) { - case CardReaderEvent::Type::CARD_MATCHED: - { - auto calypsoCard = - std::dynamic_pointer_cast( - mCardSelectionManager->parseScheduledCardSelectionsResponse( - event->getScheduledCardSelectionsResponse()) - ->getActiveSmartCard()); + case CardReaderEvent::CARD_MATCHED: { + auto calypsoCard = std::dynamic_pointer_cast( + mCardSelectionManager + ->parseScheduledCardSelectionsResponse( + event->getScheduledCardSelectionsResponse()) + ->getActiveSmartCard()); - mLogger->info("Observer notification: card selection was successful and produced the smart" \ - " card = %\n", - calypsoCard); - mLogger->info("Calypso Serial Number = %\n", - HexUtil::toHex(calypsoCard->getApplicationSerialNumber())); + mLogger->info( + "Observer notification: card selection was successful and " + "produced the smart card = %\n", + calypsoCard); + mLogger->info( + "Calypso Serial Number = %\n", + HexUtil::toHex(calypsoCard->getApplicationSerialNumber())); mLogger->info("Data read during the scheduled selection process:\n"); - mLogger->info("File %h, rec 1: FILE_CONTENT = %\n", - StringUtils::format("%02X", CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER), - calypsoCard->getFileBySfi(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER)); + mLogger->info( + "File %h, rec 1: FILE_CONTENT = %\n", + HexUtil::toHex(SFI_ENVIRONMENT_AND_HOLDER), + calypsoCard->getFileBySfi(SFI_ENVIRONMENT_AND_HOLDER)); mLogger->info("= #### End of the card processing\n"); - } + } break; + case CardReaderEvent::CARD_INSERTED: + mLogger->error( + "CARD_INSERTED event: should not have occurred because of the " + "MATCHED_ONLY selection mode chosen.\n"); break; - - case CardReaderEvent::Type::CARD_INSERTED: - mLogger->error("CARD_INSERTED event: should not have occurred because of the MATCHED_ONLY" \ - " selection mode chosen."); - break; - - case CardReaderEvent::Type::CARD_REMOVED: - mLogger->trace("There is no card inserted anymore. Return to the waiting state..."); + case CardReaderEvent::CARD_REMOVED: + mLogger->trace( + "There is no card inserted anymore. Return to the waiting " + "state...\n"); break; default: break; } - if (event->getType() == CardReaderEvent::Type::CARD_INSERTED || - event->getType() == CardReaderEvent::Type::CARD_MATCHED) { + if (event->getType() == CardReaderEvent::CARD_INSERTED + || event->getType() == CardReaderEvent::CARD_MATCHED) { /* - * Informs the underlying layer of the end of the card processing, in order to manage the - * removal sequence. + * Informs the underlying layer of the end of the card processing, in + * order to manage the removal sequence. */ - std::dynamic_pointer_cast(mReader)->finalizeCardProcessing(); + mReader->finalizeCardProcessing(); } } -void CardReaderObserver::onReaderObservationError(const std::string& pluginName, - const std::string& readerName, - const std::shared_ptr e) -{ - mLogger->error("An exception occurred in plugin '%', reader '%'\n", pluginName, readerName, e); +void +CardReaderObserver::onReaderObservationError( + const std::string& pluginName, + const std::string& readerName, + const std::shared_ptr e) { + mLogger->error( + "An exception occurred in plugin '%', reader '%'\n", + pluginName, + readerName, + e); } diff --git a/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/CardReaderObserver.h b/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/CardReaderObserver.h deleted file mode 100644 index 299666d..0000000 --- a/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/CardReaderObserver.h +++ /dev/null @@ -1,75 +0,0 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -#pragma once - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" -#include "CardReaderObserverSpi.h" -#include "CardReaderObservationExceptionHandlerSpi.h" -#include "CardSelectionManager.h" - -/* Keyple Core Util */ -#include "LoggerFactory.h" - -using namespace calypsonet::terminal::reader; -using namespace calypsonet::terminal::reader::selection; -using namespace calypsonet::terminal::reader::spi; -using namespace keyple::core::util::cpp; - -/** - * A reader Observer handles card event such as CARD_INSERTED, CARD_MATCHED, CARD_REMOVED - */ -class CardReaderObserver final -: public CardReaderObserverSpi, public CardReaderObservationExceptionHandlerSpi { -public: - /** - * (package-private)
- * Constructor. - * - *

Note: the reader is provided here for convenience but could also be retrieved from the - * SmartCardService with its name and that of the plugin both present in the CardReaderEvent. - * - * @param reader The card reader. - * @param cardSelectionManager The card selection manager. - */ - CardReaderObserver(std::shared_ptr reader, - std::shared_ptr cardSelectionManager); - - /** - * {@inheritDoc} ConfigurationUtil.getSamReader(plugin, ConfigurationUtil.SAM_READER_NAME_REGEX) - */ - void onReaderEvent(const std::shared_ptr event) override; - - /** - * {@inheritDoc} ConfigurationUtil.getSamReader(plugin, ConfigurationUtil.SAM_READER_NAME_REGEX) - */ - void onReaderObservationError(const std::string& pluginName, - const std::string& readerName, - const std::shared_ptr e) override; - -private: - /** - * - */ - const std::unique_ptr mLogger = LoggerFactory::getLogger(typeid(CardReaderObserver)); - - /** - * - */ - std::shared_ptr mReader; - - /** - * - */ - std::shared_ptr mCardSelectionManager; -}; diff --git a/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/CardReaderObserver.hpp b/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/CardReaderObserver.hpp new file mode 100644 index 0000000..3562c2f --- /dev/null +++ b/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/CardReaderObserver.hpp @@ -0,0 +1,90 @@ +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#pragma once + +#include +#include + +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keypop/reader/CardReaderEvent.hpp" +#include "keypop/reader/ObservableCardReader.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/spi/CardReaderObservationExceptionHandlerSpi.hpp" +#include "keypop/reader/spi/CardReaderObserverSpi.hpp" + +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keypop::reader::CardReaderEvent; +using keypop::reader::ObservableCardReader; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::spi::CardReaderObservationExceptionHandlerSpi; +using keypop::reader::spi::CardReaderObserverSpi; + +/** + * A reader Observer handles card event such as CARD_INSERTED, CARD_MATCHED, + * CARD_REMOVED + */ +class CardReaderObserver : public CardReaderObserverSpi, + public CardReaderObservationExceptionHandlerSpi { +public: + /** + * Constructor. + * + *

Note: the reader is provided here for convenience but could also be + * retrieved from the SmartCardService with its name and that of the plugin + * both present in the CardReaderEvent. + * + * @param reader The card reader. + * @param cardSelectionManager The card selection manager. + */ + CardReaderObserver( + std::shared_ptr reader, + std::shared_ptr cardSelectionManager); + + /** + * + */ + virtual ~CardReaderObserver() = default; + + /** + * {@inheritDoc} + */ + void onReaderEvent(const std::shared_ptr event) override; + + /** + * {@inheritDoc} + */ + void onReaderObservationError( + const std::string& pluginName, + const std::string& readerName, + const std::shared_ptr e) override; + +private: + /** + * + */ + const std::unique_ptr mLogger + = LoggerFactory::getLogger(typeid(CardReaderObserver)); + + /** + * + */ + std::shared_ptr mReader; + + /** + * + */ + std::shared_ptr mCardSelectionManager; +}; diff --git a/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/Main_ScheduledSelection_Pcsc.cpp b/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/Main_ScheduledSelection_Pcsc.cpp index 31523dc..f7f4a08 100644 --- a/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/Main_ScheduledSelection_Pcsc.cpp +++ b/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/Main_ScheduledSelection_Pcsc.cpp @@ -1,145 +1,199 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Core Util */ -#include "ByteArrayUtil.h" -#include "ContactCardCommonProtocol.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" -#include "StringUtils.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPlugin.h" -#include "PcscPluginFactory.h" -#include "PcscPluginFactoryBuilder.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "CardReaderObserver.h" -#include "ConfigurationUtil.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::calypso; -using namespace keyple::core::service; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::core::util::protocol; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/card/CalypsoCardSelectionExtension.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ObservableCardReader.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" + +#include "../common/ConfigurationUtil.hpp" +#include "CardReaderObserver.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::card::CalypsoCardSelectionExtension; +using keypop::reader::CardReader; +using keypop::reader::ObservableCardReader; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::IsoCardSelector; /** - *

Use Case Generic 2 – Scheduled Selection (PC/SC)

+ * Handles the process of a Calypso card selection using the PC/SC plugin and + * a scheduled selection scenario. * - *

We demonstrate here the selection of a Calypso card using a scheduled scenario. The selection - * operations are prepared in advance with the card selection manager and the Calypso extension - * service, then the reader is observed. When a card is inserted, the prepared selection scenario is - * executed and the observer is notified of a card insertion event including the selection data - * collected during the selection process. - * - *

Scenario:

- * - *
    - *
  • Schedule a selection scenario over an observable reader to target a specific card (here a - * Calypso card characterized by its AID) and including the reading of a file record. - *
  • Start the observation and wait for a card insertion. - *
  • Within the reader event handler: - *
      - *
    • Output collected card data (FCI and ATR). - *
    • Close the physical channel. - *
    - *
- * - * All results are logged with slf4j. + *

This class demonstrates the advanced selection of a Calypso card, where + * the selection operations are prepared ahead of time. Using the card + * selection manager and Calypso extension service, a scheduled scenario is + * created and the reader is set to observation mode. Upon card insertion, + * the prepared selection scenario is automatically executed, and the + * observer is notified with the selection data collected. + */ +class Main_ScheduledSelection_Pcsc { }; +static std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_ScheduledSelection_Pcsc)); + +/** AID: Keyple test kit profile 1, Application 2 */ +static const std::string AID = "315449432E49434131"; + +/* File identifiers */ +static const std::uint8_t SFI_ENVIRONMENT_AND_HOLDER = 0x07; + +/* The plugin used to manage the reader. */ +static std::shared_ptr plugin; +/* The reader used to communicate with the card. */ +static std::shared_ptr cardReader; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* + * The Calypso factory used to create the selection extension and transaction + * managers. + */ +static std::shared_ptr calypsoCardApiFactory; + +/** + * Initializes the Keyple service. * - *

Any unexpected behavior will result in runtime exceptions. + *

Gets an instance of the smart card service, registers the PC/SC plugin, + * and prepares the reader API factory for use. */ -class Main_ScheduledSelection_Pcsc {}; -static const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_ScheduledSelection_Pcsc)); +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); + plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} -int main() -{ - /* Get the instance of the SmartCardService */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); +/** + * Initializes the card reader with specific configurations. + */ +static void +initCardReader() { + cardReader = ConfigurationUtil::getReader( + plugin, + ConfigurationUtil::CARD_READER_NAME_REGEX, + true, + PcscReader::IsoProtocol::T1, + PcscReader::SharingMode::SHARED, + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ConfigurationUtil::ISO_CARD_PROTOCOL); +} - /* Register the PcscPlugin, get the corresponding generic plugin in return */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); +/** + * Initializes the Calypso card extension service. + */ +static void +initCalypsoCardExtensionService() { + std::shared_ptr calypsoExtensionService( + CalypsoExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + calypsoExtensionService); + calypsoCardApiFactory = calypsoExtensionService->getCalypsoCardApiFactory(); +} - /* Get the Calypso card extension service */ - std::shared_ptr calypsoCardService = - CalypsoExtensionService::getInstance(); +int +main() { + logger->info( + "= UseCase Generic #2: scheduled selection ==================\n"); - /* Verify that the extension's API level is consistent with the current service */ - smartCardService->checkCardExtension(calypsoCardService); + /* Initialize the context */ + initKeypleService(); + initCardReader(); + initCalypsoCardExtensionService(); - /* Get the contactless reader whose name matches the provided regex */ - std::shared_ptr cardReader = - ConfigurationUtil::getCardReader(plugin, ConfigurationUtil::CARD_READER_NAME_REGEX); + logger->info("= #### Select application with AID = '%'\n", AID); - logger->info("=============== UseCase Generic #2: scheduled selection ==================\n"); - logger->info("= #### Select application with AID = '%'\n", CalypsoConstants::AID); + /* Retrieve the core card selection manager from the Reader API factory */ + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); - /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + /* Create an ISO card selector and set a filter by the specific AID */ + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(AID); /* - * Create a card selection using the Calypso card extension. - * Select the card and read the record 1 of the file ENVIRONMENT_AND_HOLDER + * Initialize a Calypso card selection extension read the record 1 of the + * file ENVIRONMENT_AND_HOLDER. */ - std::shared_ptr selection = calypsoCardService->createCardSelection(); - selection->acceptInvalidatedCard() - .filterByCardProtocol(ConfigurationUtil::ISO_CARD_PROTOCOL) - .filterByDfName(CalypsoConstants::AID) - .prepareReadRecord(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER, - CalypsoConstants::RECORD_NUMBER_1); + std::unique_ptr + calypsoCardSelectionExtension( + calypsoCardApiFactory->createCalypsoCardSelectionExtension()); + calypsoCardSelectionExtension->acceptInvalidatedCard().prepareReadRecord( + SFI_ENVIRONMENT_AND_HOLDER, 1); /* - * Prepare the selection by adding the created Calypso selection to the card selection scenario. + * Prepare the card selection scenario by associating the card selector + * with the Calypso card selection extension. */ - cardSelectionManager->prepareSelection(selection); + cardSelectionManager->prepareSelection( + cardSelector, std::move(calypsoCardSelectionExtension)); /* - * Schedule the selection scenario, request notification only if the card matches the selection - * case. + * Schedule the card selection scenario with a configuration to notify only + * if a card matches the selection criteria. */ - auto observable = std::dynamic_pointer_cast(cardReader); + auto observableCardReader + = std::dynamic_pointer_cast(cardReader); cardSelectionManager->scheduleCardSelectionScenario( - observable, - ObservableCardReader::DetectionMode::REPEATING, + observableCardReader, ObservableCardReader::NotificationMode::MATCHED_ONLY); - /* Create and add an observer for this reader */ - auto cardReaderObserver = - std::make_shared(cardReader, cardSelectionManager); - observable->setReaderObservationExceptionHandler(cardReaderObserver); - observable->addObserver(cardReaderObserver); - observable->startCardDetection(ObservableCardReader::DetectionMode::REPEATING); - - logger->info("= #### Wait for a card. The default AID based selection to be processed as soon" \ - " as the card is detected\n"); - - while(1); + /* + * Establish a card reader observer to manage card reader events and + * errors and initiate the card detection process. + */ + auto cardReaderObserver = std::make_shared( + observableCardReader, cardSelectionManager); + observableCardReader->setReaderObservationExceptionHandler( + cardReaderObserver); + observableCardReader->addObserver(cardReaderObserver); + observableCardReader->startCardDetection( + ObservableCardReader::DetectionMode::REPEATING); + + logger->info( + "= #### Wait for a card. The default AID based selection to be " + "processed as soon as the card is detected.\n"); + + /* The program will remain active indefinitely until interrupted (CTRL-C to + * exit) */ + while (true) { + } } - diff --git a/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/Main_ScheduledSelection_Stub.cpp b/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/Main_ScheduledSelection_Stub.cpp index e8c7a53..d8b9712 100644 --- a/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/Main_ScheduledSelection_Stub.cpp +++ b/Example_Card_Calypso/src/main/UseCase2_ScheduledSelection/Main_ScheduledSelection_Stub.cpp @@ -1,182 +1,222 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" -#include "ConfigurableCardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "ObservableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Core Util */ -#include "ByteArrayUtil.h" -#include "ContactCardCommonProtocol.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" -#include "StringUtils.h" -#include "Thread.h" - -/* Keyple Plugin Stub */ -#include "StubPlugin.h" -#include "StubPluginFactoryBuilder.h" -#include "StubReader.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "CardReaderObserver.h" -#include "ConfigurationUtil.h" -#include "StubSmartCardFactory.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::calypso; -using namespace keyple::core::service; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::core::util::protocol; -using namespace keyple::plugin::stub; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/plugin/stub/StubPluginFactoryBuilder.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/card/CalypsoCardSelectionExtension.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ObservableCardReader.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" + +#include "../common/StubSmartCardFactory.hpp" +#include "CardReaderObserver.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::plugin::stub::StubPluginFactoryBuilder; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::card::CalypsoCardSelectionExtension; +using keypop::reader::CardReader; +using keypop::reader::ObservableCardReader; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::IsoCardSelector; /** - *

Use Case Generic 2 – Scheduled Selection (Stub)

+ * Handles the process of a Calypso card selection using the Stub plugin and a + * scheduled selection scenario. * - *

We demonstrate here the selection of a Calypso card using a scheduled scenario. The selection - * operations are prepared in advance with the card selection manager and the Calypso extension - * service, then the reader is observed. When a card is inserted, the prepared selection scenario is - * executed and the observer is notified of a card insertion event including the selection data - * collected during the selection process. + *

This class demonstrates the advanced selection of a Calypso card, where + * the selection operations are prepared ahead of time. Using the card + * selection manager and Calypso extension service, a scheduled scenario is + * created and the reader is set to observation mode. Upon card insertion, the + * prepared selection scenario is automatically executed, and the observer is + * notified with the selection data collected. * - *

Scenario:

+ *

The class also highlights the utility of scheduling selection + * operations in advance for efficient and automated card processing upon + * insertion, minimizing the latency between card detection and data + * availability. + * + *

Key Functionalities

* *
    - *
  • Schedule a selection scenario over an observable reader to target a specific card (here a - * Calypso card characterized by its AID) and including the reading of a file record. - *
  • Start the observation and wait for a card insertion. - *
  • Simulate the card insertion. - *
  • Within the reader event handler: - *
      - *
    • Output collected card data (FCI and ATR). - *
    • Close the physical channel. - *
    + *
  • Prepare a scheduled selection scenario targeting a specific Calypso + * card using its AID, and include operations to read a file record. + *
  • Initiate the observation of the reader for card insertion events. + *
  • Handle card insertion events by executing the prepared selection + * scenario, collecting, and outputting card data such as FCI and ATR. + *
  • Close the physical channel after data collection to ensure resource + * availability and security. *
- * - * All results are logged with slf4j. - * - *

Any unexpected behavior will result in runtime exceptions. */ -class Main_ScheduledSelection_Stub {}; -static std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_ScheduledSelection_Stub)); +class Main_ScheduledSelection_Stub { }; +static std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_ScheduledSelection_Stub)); static const std::string CARD_READER_NAME = "Stub card reader"; -int main() -{ - /* Get the instance of the SmartCardService */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); +/** AID: Keyple test kit profile 1, Application 2 */ +static const std::string AID = "315449432E49434131"; + +/* File identifiers */ +static const std::uint8_t SFI_ENVIRONMENT_AND_HOLDER = 0x07; + +/* The plugin used to manage the reader. */ +static std::shared_ptr plugin; +/* The reader used to communicate with the card. */ +static std::shared_ptr cardReader; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* + * The Calypso factory used to create the selection extension and transaction + * managers. + */ +static std::shared_ptr calypsoCardApiFactory; + +/** + * Initializes the Keyple service. + * + *

Gets an instance of the smart card service, registers the Stub plugin, and + * prepares the reader API factory for use. + * + *

Retrieves the {@link ReaderApiFactory}. + */ +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); /* - * Register the StubPlugin with the SmartCardService, plug a Calypso card stub - * get the corresponding generic plugin in return. + * Register the StubPlugin with the SmartCardService and plug in stubs for a + * Calypso card. */ - std::shared_ptr pluginFactory = + plugin = smartCardService->registerPlugin( StubPluginFactoryBuilder::builder() - ->withStubReader(CARD_READER_NAME, true, nullptr) - .withMonitoringCycleDuration(100) - .build(); - std::shared_ptr plugin = smartCardService->registerPlugin(pluginFactory); + ->withStubReader( + CARD_READER_NAME, true, StubSmartCardFactory::getStubCard()) + .build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} - /* Get the Calypso card extension service */ - auto calypsoCardService = CalypsoExtensionService::getInstance(); +/** + * Initializes the card reader with specific configurations. + * + *

Prepares the card reader using a predefined set of configurations, + * including the card reader name regex, ISO protocol, and sharing mode. + */ +static void +initCardReader() { + cardReader = plugin->getReader(CARD_READER_NAME); +} - /* Verify that the extension's API level is consistent with the current service */ - smartCardService->checkCardExtension(calypsoCardService); +/** + * Initializes the Calypso card extension service. + * + *

Retrieves the {@link CalypsoCardApiFactory}. + */ +static void +initCalypsoCardExtensionService() { + std::shared_ptr calypsoExtensionService( + CalypsoExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + calypsoExtensionService); + calypsoCardApiFactory = calypsoExtensionService->getCalypsoCardApiFactory(); +} + +int +main() { + logger->info( + "= UseCase Generic #2: scheduled selection ==================\n"); - std::shared_ptr cardReader = plugin->getReader(CARD_READER_NAME); + /* Initialize the context */ + initKeypleService(); + initCardReader(); + initCalypsoCardExtensionService(); - /* Activate the ISO14443 card protocol */ - std::dynamic_pointer_cast(cardReader) - ->activateProtocol(ConfigurationUtil::ISO_CARD_PROTOCOL, - ConfigurationUtil::ISO_CARD_PROTOCOL); + logger->info("= #### Select application with AID = '%'\n", AID); - logger->info("=============== " \ - "UseCase Generic #2: scheduled selection " \ - "==================\n"); - logger->info("= #### Select application with AID = '%'\n", CalypsoConstants::AID); + /* Retrieve the core card selection manager from the Reader API factory */ + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); - /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + /* Create an ISO card selector and set a filter by the specific AID */ + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(AID); /* - * Create a card selection using the Calypso card extension. - * Select the card and read the record 1 of the file ENVIRONMENT_AND_HOLDER + * Initialize a Calypso card selection extension read the record 1 of the + * file ENVIRONMENT_AND_HOLDER. */ - std::shared_ptr cardSelection = calypsoCardService->createCardSelection(); - cardSelection->acceptInvalidatedCard() - .filterByCardProtocol(ConfigurationUtil::ISO_CARD_PROTOCOL) - .filterByDfName(CalypsoConstants::AID) - .prepareReadRecord(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER, - CalypsoConstants::RECORD_NUMBER_1); + std::unique_ptr + calypsoCardSelectionExtension( + calypsoCardApiFactory->createCalypsoCardSelectionExtension()); + calypsoCardSelectionExtension->acceptInvalidatedCard().prepareReadRecord( + SFI_ENVIRONMENT_AND_HOLDER, 1); /* - * Prepare the selection by adding the created Calypso selection to the card selection scenario + * Prepare the card selection scenario by associating the card selector + * with the Calypso card selection extension. */ - cardSelectionManager->prepareSelection(cardSelection); + cardSelectionManager->prepareSelection( + cardSelector, std::move(calypsoCardSelectionExtension)); /* - * Schedule the selection scenario, request notification only if the card matches the selection - * case. + * Schedule the card selection scenario with a configuration to notify only + * if a card matches the selection criteria. */ - auto observableReader = std::dynamic_pointer_cast(cardReader); + auto observableCardReader + = std::dynamic_pointer_cast(cardReader); cardSelectionManager->scheduleCardSelectionScenario( - observableReader, - ObservableCardReader::DetectionMode::REPEATING, + observableCardReader, ObservableCardReader::NotificationMode::MATCHED_ONLY); - /* Create and add an observer for this reader */ - auto cardReaderObserver = std::make_shared(cardReader,cardSelectionManager); - observableReader->setReaderObservationExceptionHandler(cardReaderObserver); - observableReader->addObserver(cardReaderObserver); - observableReader->startCardDetection(ObservableCardReader::DetectionMode::REPEATING); - - logger->info("= #### Wait for a card. The default AID based selection to be processed as soon" \ - " as the card is detected\n"); - - /* Wait a while. */ - Thread::sleep(100); - - logger->info("Insert stub card\n"); - std::dynamic_pointer_cast( - plugin->getReaderExtension(typeid(StubReader), CARD_READER_NAME)) - ->insertCard(StubSmartCardFactory::getStubCard()); - - /* Wait a while. */ - Thread::sleep(1000); - - logger->info("Remove stub card\n"); - std::dynamic_pointer_cast( - plugin->getReaderExtension(typeid(StubReader), CARD_READER_NAME)) - ->removeCard(); - - /* Unregister plugin */ - smartCardService->unregisterPlugin(plugin->getName()); - - logger->info("Exit program\n"); - - return 0; + /* + * Establish a card reader observer to manage card reader events and + * errors and initiate the card detection process. + */ + auto cardReaderObserver = std::make_shared( + observableCardReader, cardSelectionManager); + observableCardReader->setReaderObservationExceptionHandler( + cardReaderObserver); + observableCardReader->addObserver(cardReaderObserver); + observableCardReader->startCardDetection( + ObservableCardReader::DetectionMode::REPEATING); + + logger->info( + "= #### Wait for a card. The default AID based selection to be " + "processed as soon as the card is detected.\n"); + + /* The program will remain active indefinitely until interrupted (CTRL-C to + * exit) */ + while (true) { + } } diff --git a/Example_Card_Calypso/src/main/UseCase3_Rev1Selection/Main_Rev1Selection_Pcsc.cpp b/Example_Card_Calypso/src/main/UseCase3_Rev1Selection/Main_Rev1Selection_Pcsc.cpp index f67705a..dd608c5 100644 --- a/Example_Card_Calypso/src/main/UseCase3_Rev1Selection/Main_Rev1Selection_Pcsc.cpp +++ b/Example_Card_Calypso/src/main/UseCase3_Rev1Selection/Main_Rev1Selection_Pcsc.cpp @@ -1,167 +1,215 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" -#include "ConfigurableCardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Core Util */ -#include "ContactCardCommonProtocol.h" -#include "HexUtil.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" -#include "StringUtils.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPlugin.h" -#include "PcscPluginFactory.h" -#include "PcscPluginFactoryBuilder.h" -#include "PcscSupportedContactlessProtocol.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "ConfigurationUtil.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::calypso; -using namespace keyple::core::service; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::core::util::protocol; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/card/CalypsoCard.hpp" +#include "keypop/calypso/card/card/CalypsoCardSelectionExtension.hpp" +#include "keypop/calypso/card/transaction/FreeTransactionManager.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ChannelControl.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/BasicCardSelector.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +#include "../common/ConfigurationUtil.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::card::CalypsoCard; +using keypop::calypso::card::card::CalypsoCardSelectionExtension; +using keypop::calypso::card::transaction::FreeTransactionManager; +using keypop::reader::CardReader; +using keypop::reader::ChannelControl; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::BasicCardSelector; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::spi::SmartCard; /** - *

Use Case ‘Calypso 3 – Selection a Calypso card Revision 1 (BPRIME protocol) (PC/SC)

+ * Handles the process of explicit selection of a Calypso card Revision 1 + * using the PC/SC plugin, without implementing the observation of the + * reader. Ensure the Calypso card is inserted before launching the program. * - *

We demonstrate here the direct selection of a Calypso card Revision 1 (Innovatron / B Prime - * protocol) inserted in a reader. No observation of the reader is implemented in this example, so - * the card must be present in the reader before the program is launched. - * - *

No AID is used here, the reading of the card data is done without any prior card selection - * command as defined in the ISO standard. - * - *

The card selection (in the Keyple sense, i.e. retained to continue processing) is based on the - * protocol. - * - *

Scenario:

- * - *
    - *
  • Check if a ISO B Prime (Innovatron protocol) card is in the reader. - *
  • Send 2 additional APDUs to the card (one following the selection step, one after the - * selection, within a card transaction [without security here]). - *
- * - *

Any unexpected behavior will result in runtime exceptions. + *

This class demonstrates the use of the protocol filtering in the + * selection phase for card having no AID. */ -class Main_Rev1Selection_Pcsc {}; -static const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_Rev1Selection_Pcsc)); - -int main() -{ - /* Get the instance of the SmartCardService */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); - - /* Register the PcscPlugin, get the corresponding generic plugin in return */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); +class Main_Rev1Selection_Pcsc { }; +static std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_Rev1Selection_Pcsc)); + +/* File identifiers */ +static const std::uint8_t SFI_ENVIRONMENT_AND_HOLDER = 0x07; +static const std::uint8_t SFI_EVENT_LOG = 0x08; + +/* The plugin used to manage the reader. */ +static std::shared_ptr plugin; +/* The reader used to communicate with the card. */ +static std::shared_ptr cardReader; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* + * The Calypso factory used to create the selection extension and transaction + * managers. + */ +static std::shared_ptr calypsoCardApiFactory; - /* Get the contactless reader whose name matches the provided regex */ - std::shared_ptr cardReader = - ConfigurationUtil::getCardReader(plugin, ConfigurationUtil::CARD_READER_NAME_REGEX); +/** + * Initializes the Keyple service. + */ +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); + plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} - /* Activate Innovatron protocol. */ - std::dynamic_pointer_cast(cardReader) - ->activateProtocol(PcscSupportedContactlessProtocol::INNOVATRON_B_PRIME_CARD.getName(), - ConfigurationUtil::INNOVATRON_CARD_PROTOCOL); +/** + * Initializes the card reader with specific configurations. + */ +static void +initCardReader() { + cardReader = ConfigurationUtil::getReader( + plugin, + ConfigurationUtil::CARD_READER_NAME_REGEX, + true, + PcscReader::IsoProtocol::T1, + PcscReader::SharingMode::SHARED, + PcscSupportedContactlessProtocol::INNOVATRON_B_PRIME_CARD.getName(), + ConfigurationUtil::INNOVATRON_CARD_PROTOCOL); +} - /* Get the Calypso card extension service */ - std::shared_ptr calypsoCardService = - CalypsoExtensionService::getInstance(); +/** + * Initializes the Calypso card extension service. + */ +static void +initCalypsoCardExtensionService() { + std::shared_ptr calypsoExtensionService( + CalypsoExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + calypsoExtensionService); + calypsoCardApiFactory = calypsoExtensionService->getCalypsoCardApiFactory(); +} - /* Verify that the extension's API level is consistent with the current service */ - smartCardService->checkCardExtension(calypsoCardService); +int +main() { + logger->info( + "= UseCase Calypso #3: selection of a rev1 card " + "==================\n"); - logger->info("=============== " \ - "UseCase Calypso #3: selection of a rev1 card " \ - "==================\n"); - logger->info("= Card Reader NAME = %\n", cardReader->getName()); + /* Initialize the context */ + initKeypleService(); + initCardReader(); + initCalypsoCardExtensionService(); /* Check if a card is present in the reader */ if (!cardReader->isCardPresent()) { throw IllegalStateException("No card is present in the reader."); } - logger->info("= #### Select the card by its INNOVATRON protocol (no AID)\n"); + logger->info( + "= #### Select the card by its INNOVATRON protocol (no AID)\n"); /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); + + std::shared_ptr cardSelector( + readerApiFactory->createBasicCardSelector()); + cardSelector->filterByCardProtocol( + ConfigurationUtil::INNOVATRON_CARD_PROTOCOL); /* * Create a card selection using the Calypso card extension. - * Prepare the selection by adding the created Calypso card selection to the card selection - * scenario. No AID is defined, only the card protocol will be used to define the selection - * case. + * No AID is defined, only the card protocol will be used to define the + * selection case. */ - std::shared_ptr selection = calypsoCardService->createCardSelection(); - selection->acceptInvalidatedCard() - .filterByCardProtocol(ConfigurationUtil::INNOVATRON_CARD_PROTOCOL) - .prepareReadRecord(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER, - CalypsoConstants::RECORD_NUMBER_1); + std::unique_ptr + calypsoCardSelectionExtension( + calypsoCardApiFactory->createCalypsoCardSelectionExtension()); + calypsoCardSelectionExtension->acceptInvalidatedCard().prepareReadRecord( + SFI_ENVIRONMENT_AND_HOLDER, 1); + cardSelectionManager->prepareSelection( + cardSelector, std::move(calypsoCardSelectionExtension)); /* Actual card communication: run the selection scenario */ - const std::shared_ptr selectionResult = - cardSelectionManager->processCardSelectionScenario(cardReader); + const std::shared_ptr selectionResult( + cardSelectionManager->processCardSelectionScenario(cardReader)); /* Check the selection result */ if (selectionResult->getActiveSmartCard() == nullptr) { - throw IllegalStateException("The selection of the B Prime card failed."); + throw IllegalStateException( + "The selection of the B Prime card failed."); } /* Get the SmartCard resulting of the selection */ - const auto calypsoCard = - std::dynamic_pointer_cast(selectionResult->getActiveSmartCard()); + const std::shared_ptr card( + selectionResult->getActiveSmartCard()); + auto calypsoCard = std::dynamic_pointer_cast(card); logger->info("= SmartCard = %\n", calypsoCard); - const std::string csn = HexUtil::toHex(calypsoCard->getApplicationSerialNumber()); + const std::string csn( + HexUtil::toHex(calypsoCard->getApplicationSerialNumber())); logger->info("Calypso Serial Number = %\n", csn); - /* Performs file reads using the card transaction manager in non-secure mode */ - std::shared_ptr extension = - calypsoCardService->createCardTransactionWithoutSecurity(cardReader, calypsoCard); - extension->prepareReadRecord(CalypsoConstants::SFI_EVENT_LOG, 1) - .prepareReleaseCardChannel() - .processCommands(); - - const std::string sfiEnvHolder = HexUtil::toHex(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER); - logger->info("File %h, rec 1: FILE_CONTENT = %\n", - sfiEnvHolder, - calypsoCard->getFileBySfi(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER)); - - const std::string sfiEventLog = HexUtil::toHex(CalypsoConstants::SFI_EVENT_LOG); - logger->info("File %h, rec 1: FILE_CONTENT = %\n", - sfiEventLog, - calypsoCard->getFileBySfi(CalypsoConstants::SFI_EVENT_LOG)); + /* Performs file reads using the card transaction manager in non-secure mode + */ + calypsoCardApiFactory->createFreeTransactionManager(cardReader, calypsoCard) + ->prepareReadRecord(SFI_EVENT_LOG, 1) + .processCommands(ChannelControl::CLOSE_AFTER); + + const std::string sfiEnvHolder(HexUtil::toHex(SFI_ENVIRONMENT_AND_HOLDER)); + logger->info( + "File %h, rec 1: FILE_CONTENT = %\n", + sfiEnvHolder, + calypsoCard->getFileBySfi(SFI_ENVIRONMENT_AND_HOLDER)); + + const std::string sfiEventLog(HexUtil::toHex(SFI_EVENT_LOG)); + logger->info( + "File %h, rec 1: FILE_CONTENT = %\n", + sfiEventLog, + calypsoCard->getFileBySfi(SFI_EVENT_LOG)); logger->info("= #### End of the Calypso card processing\n"); diff --git a/Example_Card_Calypso/src/main/UseCase4_CardAuthentication/Main_CardAuthentication_Pcsc.cpp b/Example_Card_Calypso/src/main/UseCase4_CardAuthentication/Main_CardAuthentication_Pcsc.cpp index 23791a7..ecbda78 100644 --- a/Example_Card_Calypso/src/main/UseCase4_CardAuthentication/Main_CardAuthentication_Pcsc.cpp +++ b/Example_Card_Calypso/src/main/UseCase4_CardAuthentication/Main_CardAuthentication_Pcsc.cpp @@ -1,187 +1,335 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Core Util */ -#include "ContactCardCommonProtocol.h" -#include "ContactlessCardCommonProtocol.h" -#include "HexUtil.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" -#include "StringUtils.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPlugin.h" -#include "PcscPluginFactory.h" -#include "PcscPluginFactoryBuilder.h" -#include "PcscReader.h" -#include "PcscSupportedContactlessProtocol.h" -#include "PcscSupportedContactProtocol.h" - -/* Keyple Core Resource */ -#include "CardResource.h" -#include "CardResourceServiceProvider.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "ConfigurationUtil.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::calypso; -using namespace keyple::core::service; -using namespace keyple::core::service::resource; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::core::util::protocol; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamUtil.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactProtocol.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/WriteAccessLevel.hpp" +#include "keypop/calypso/card/card/CalypsoCard.hpp" +#include "keypop/calypso/card/card/CalypsoCardSelectionExtension.hpp" +#include "keypop/calypso/card/cpp/SecureRegularModeTransactionManagerBase.hpp" +#include "keypop/calypso/card/transaction/SecureSymmetricCryptoTransactionManager.hpp" +#include "keypop/calypso/card/transaction/SymmetricCryptoSecuritySetting.hpp" +#include "keypop/calypso/crypto/legacysam/LegacySamApiFactory.hpp" +#include "keypop/calypso/crypto/legacysam/sam/LegacySam.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ChannelControl.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +#include "../common/ConfigurationUtil.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamUtil; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keyple::plugin::pcsc::PcscSupportedContactProtocol; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::WriteAccessLevel; +using keypop::calypso::card::card::CalypsoCard; +using keypop::calypso::card::card::CalypsoCardSelectionExtension; +using keypop::calypso::card::cpp::SecureRegularModeTransactionManagerBase; +using keypop::calypso::card::transaction:: + SecureSymmetricCryptoTransactionManager; +using keypop::calypso::card::transaction::SymmetricCryptoSecuritySetting; +using keypop::calypso::crypto::legacysam::LegacySamApiFactory; +using keypop::calypso::crypto::legacysam::sam::LegacySam; +using keypop::reader::CardReader; +using keypop::reader::ChannelControl; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::selection::spi::SmartCard; /** - *

Use Case Calypso 4 – Calypso Card authentication (PC/SC)

+ * Handles the process of a Calypso card authentication using the PC/SC + * plugin and the Calypso Card Extension Service. * - *

We demonstrate here the authentication of a Calypso card using a Secure Session in which a - * file from the card is read. The read is certified by verifying the signature of the card by a - * Calypso SAM. + *

This class demonstrates the card authentication process, including the + * initialization of the Smart Card Service, registering the PC/SC plugin, + * checking the compatibility of the Calypso card extension service, and + * performing operations with the Keypop Reader and Calypso Card APIs. * - *

Two readers are required for this example: a contactless reader for the Calypso Card, a - * contact reader for the Calypso SAM. - * - *

Scenario:

- * - *
    - *
  • Sets up the card resource service to provide a Calypso SAM (C1). - *
  • Checks if an ISO 14443-4 card is in the reader, enables the card selection manager. - *
  • Attempts to select the specified card (here a Calypso card characterized by its AID) with - * an AID-based application selection scenario. - *
  • Creates a CardTransactionManager using CardSecuritySetting referencing the selected SAM. - *
  • Read a file record in Secure Session. - *
- * - * All results are logged with slf4j. - * - *

Any unexpected behavior will result in runtime exceptions. - * - * @since 2.0.0 + *

The class also demonstrates how to retrieve the card and SAM readers + * using regular expressions to match their names and how to operate the + * security of transactions using SAM. + */ +class Main_CardAuthentication_Pcsc { }; +static std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_CardAuthentication_Pcsc)); + +/** AID: Keyple test kit profile 1, Application 2 */ +static const std::string AID = "315449432E49434131"; + +/* File identifiers */ +static const std::uint8_t SFI_ENVIRONMENT_AND_HOLDER = 0x07; +static const int RECORD_SIZE = 29; + +/* The plugin used to manage the readers. */ +static std::shared_ptr plugin; +/* The reader used to communicate with the card. */ +static std::shared_ptr cardReader; +/* The reader used to communicate with the SAM. */ +static std::shared_ptr samReader; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* + * The Calypso factory used to create the selection extension and transaction + * managers. */ -class Main_CardAuthentication_Pcsc {}; -static const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_CardAuthentication_Pcsc)); +static std::shared_ptr calypsoCardApiFactory; +/* The security settings for the card transaction. */ +static std::shared_ptr + symmetricCryptoSecuritySetting; -int main() -{ - /* Get the instance of the SmartCardService */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); +/** + * Initializes the Keyple service. + * + *

Gets an instance of the smart card service, registers the PC/SC plugin, + * and prepares the reader API factory for use. + */ +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); + plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} - /* Register the PcscPlugin, get the corresponding generic plugin in return */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); +/** + * Initializes the card reader with specific configurations. + */ +static void +initCardReader() { + cardReader = ConfigurationUtil::getReader( + plugin, + ConfigurationUtil::CARD_READER_NAME_REGEX, + true, + PcscReader::IsoProtocol::T1, + PcscReader::SharingMode::SHARED, + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ConfigurationUtil::ISO_CARD_PROTOCOL); +} - /* Get the Calypso card extension service */ - std::shared_ptr calypsoCardService = - CalypsoExtensionService::getInstance(); +/** + * Initializes the SAM reader with specific configurations. + */ +static void +initSamReader() { + samReader = ConfigurationUtil::getReader( + plugin, + ConfigurationUtil::SAM_READER_NAME_REGEX, + false, + PcscReader::IsoProtocol::ANY, + PcscReader::SharingMode::SHARED, + PcscSupportedContactProtocol::ISO_7816_3_T0.getName(), + ConfigurationUtil::SAM_PROTOCOL); +} - /* Verify that the extension's API level is consistent with the current service */ - smartCardService->checkCardExtension(calypsoCardService); +/** + * Initializes the Calypso card extension service. + */ +static void +initCalypsoCardExtensionService() { + std::shared_ptr calypsoExtensionService( + CalypsoExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + calypsoExtensionService); + calypsoCardApiFactory = calypsoExtensionService->getCalypsoCardApiFactory(); +} - /* Get the card and SAM readers whose name matches the provided regexs */ - std::shared_ptr cardReader = - ConfigurationUtil::getCardReader(plugin, ConfigurationUtil::CARD_READER_NAME_REGEX); - std::shared_ptr samReader = - ConfigurationUtil::getSamReader(plugin, ConfigurationUtil::SAM_READER_NAME_REGEX); +/** + * Selects the SAM C1 for the transaction. + * + *

Creates a SAM selection manager, prepares the selection, and processes + * the SAM selection scenario. + * + * @param reader The card reader used to communicate with the SAM. + * @return The selected SAM for the transaction. + */ +static std::shared_ptr +selectSam(std::shared_ptr reader) { + std::shared_ptr samSelectionManager( + readerApiFactory->createCardSelectionManager()); - logger->info("=============== " \ - "UseCase Calypso #4: Calypso card authentication " \ - "==================\n"); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByPowerOnData( + LegacySamUtil::buildPowerOnDataFilter( + LegacySam::ProductType::SAM_C1, "")); - /* Check if a card is present in the reader */ - if (!cardReader->isCardPresent()) { - throw IllegalStateException("No card is present in the reader."); - } + std::shared_ptr legacySamApiFactory( + LegacySamExtensionService::getInstance()->getLegacySamApiFactory()); - /* Get the Calypso SAM SmartCard after selection. */ - std::shared_ptr calypsoSam = ConfigurationUtil::getSam(samReader); + samSelectionManager->prepareSelection( + cardSelector, legacySamApiFactory->createLegacySamSelectionExtension()); - logger->info("= SAM = %\n", calypsoSam); + const std::shared_ptr samSelectionResult( + samSelectionManager->processCardSelectionScenario(reader)); - logger->info("= #### Select application with AID = '%'.\n", CalypsoConstants::AID); + if (samSelectionResult->getActiveSmartCard() == nullptr) { + throw IllegalStateException("The selection of the SAM failed."); + } - /* Create a card selection manager. */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + return std::dynamic_pointer_cast( + samSelectionResult->getActiveSmartCard()); +} - /* - * Create a card selection using the Calypso card extension. - * Prepare the selection by adding the created Calypso card selection to the card selection - * scenario. - */ - std::shared_ptr cardSelection = calypsoCardService->createCardSelection(); - cardSelection->acceptInvalidatedCard().filterByDfName(CalypsoConstants::AID); - cardSelectionManager->prepareSelection(cardSelection); +/** + * Initializes the security settings for the transaction. + * + *

Selects the SAM and sets up the symmetric crypto security setting for + * securing the transaction. + */ +static void +initSecuritySetting() { + std::shared_ptr sam(selectSam(samReader)); + + symmetricCryptoSecuritySetting + = calypsoCardApiFactory->createSymmetricCryptoSecuritySetting( + LegacySamExtensionService::getInstance() + ->getLegacySamApiFactory() + ->createSymmetricCryptoCardTransactionManagerFactory( + samReader, sam)); +} - /* Actual card communication: run the selection scenario */ - const std::shared_ptr selectionResult = - cardSelectionManager->processCardSelectionScenario(cardReader); +/** + * Selects the Calypso card for the transaction based on the specified + * Application Identifier (AID). + * + * @param reader The reader used to communicate with the card. + * @param aid The Application Identifier (AID) used to select the application + * on the card. + * @return The selected Calypso card ready for the transaction. + */ +static std::shared_ptr +selectCard(std::shared_ptr reader, const std::string& aid) { + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(aid); + + std::unique_ptr + calypsoCardSelectionExtension( + calypsoCardApiFactory->createCalypsoCardSelectionExtension()); + cardSelectionManager->prepareSelection( + cardSelector, std::move(calypsoCardSelectionExtension)); + + const std::shared_ptr selectionResult( + cardSelectionManager->processCardSelectionScenario(reader)); - /* Check the selection result */ if (selectionResult->getActiveSmartCard() == nullptr) { - throw IllegalStateException("The selection of the application '" + - CalypsoConstants::AID + - "' failed."); + throw IllegalStateException( + "The selection of the application '" + aid + "' failed."); } - /* Get the SmartCard resulting of the selection */ - const std::shared_ptr card = selectionResult->getActiveSmartCard(); - auto calypsoCard = std::dynamic_pointer_cast(card); - - logger->info("= SmartCard = %\n", calypsoCard); + const std::shared_ptr card( + selectionResult->getActiveSmartCard()); - const std::string csn = HexUtil::toHex(calypsoCard->getApplicationSerialNumber()); - logger->info("Calypso Serial Number = %\n", - HexUtil::toHex(calypsoCard->getApplicationSerialNumber())); + return std::dynamic_pointer_cast(card); +} - /* Create security settings that reference the SAM */ - std::shared_ptr cardSecuritySetting = - CalypsoExtensionService::getInstance()->createCardSecuritySetting(); - cardSecuritySetting->setControlSamResource(samReader, calypsoSam); +int +main() { + logger->info( + "= UseCase Calypso #4: Calypso card authentication " + "==================\n"); - /* Performs file reads using the card transaction manager in secure mode. */ - calypsoCardService->createCardTransaction(cardReader, calypsoCard, cardSecuritySetting) - ->prepareReadRecords(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_SIZE) - .processOpening(WriteAccessLevel::DEBIT) - .prepareReleaseCardChannel() - .processClosing(); + /* Initialize the context */ + initKeypleService(); + initCalypsoCardExtensionService(); + initCardReader(); + initSamReader(); + initSecuritySetting(); - logger->info("The Secure Session ended successfully, the card is authenticated and the data " \ - "read are certified\n"); + /* Check the card presence */ + if (!cardReader->isCardPresent()) { + throw IllegalStateException("No card is present in the reader."); + } - const std::string sfiEnvHolder = HexUtil::toHex(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER); - logger->info("File %h, rec 1: FILE_CONTENT = %\n", - sfiEnvHolder, - calypsoCard->getFileBySfi(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER)); + /* Select the card */ + std::shared_ptr calypsoCard = selectCard(cardReader, AID); - logger->info("= #### End of the Calypso card processing\n"); + /* + * Execute the transaction: the environment file is read within a secure + * session to ensure data authenticity. + * Specifying expected response lengths in read commands serves as a + * protective measure for legacy cards. + * + * The keypop API declares createSecureRegularModeTransactionManager() as + * returning a SecureRegularModeTransactionManagerBase, which does not + * itself expose prepareOpenSecureSession() (it's only declared on + * SecureSymmetricCryptoTransactionManager, a sibling interface + * implemented by the same concrete object). A downcast is required to + * reach it. + */ + std::unique_ptr + cardTransactionManager( + calypsoCardApiFactory->createSecureRegularModeTransactionManager( + cardReader, calypsoCard, symmetricCryptoSecuritySetting)); + + dynamic_cast*>(cardTransactionManager.get()) + ->prepareOpenSecureSession(WriteAccessLevel::DEBIT) + .prepareReadRecords(SFI_ENVIRONMENT_AND_HOLDER, 1, 1, RECORD_SIZE) + .prepareCloseSecureSession() + .processCommands(ChannelControl::CLOSE_AFTER); + + logger->info( + "The secure session has ended successfully; the card is " + "authenticated, and the read data is certified.\n"); + + const std::string csn( + HexUtil::toHex(calypsoCard->getApplicationSerialNumber())); + logger->info("Calypso Serial Number = %\n", csn); + + const std::string sfiEnvHolder(HexUtil::toHex(SFI_ENVIRONMENT_AND_HOLDER)); + logger->info( + "File SFI %h, rec 1: FILE_CONTENT = %\n", + sfiEnvHolder, + calypsoCard->getFileBySfi(SFI_ENVIRONMENT_AND_HOLDER)); return 0; } diff --git a/Example_Card_Calypso/src/main/UseCase4_CardAuthentication/Main_CardAuthentication_Pcsc_SamResourceService.cpp b/Example_Card_Calypso/src/main/UseCase4_CardAuthentication/Main_CardAuthentication_Pcsc_SamResourceService.cpp index 2e0c616..05a6705 100644 --- a/Example_Card_Calypso/src/main/UseCase4_CardAuthentication/Main_CardAuthentication_Pcsc_SamResourceService.cpp +++ b/Example_Card_Calypso/src/main/UseCase4_CardAuthentication/Main_CardAuthentication_Pcsc_SamResourceService.cpp @@ -1,201 +1,420 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Core Util */ -#include "ContactCardCommonProtocol.h" -#include "ContactlessCardCommonProtocol.h" -#include "HexUtil.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" -#include "StringUtils.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPlugin.h" -#include "PcscPluginFactory.h" -#include "PcscPluginFactoryBuilder.h" - -/* Keyple Core Resource */ -#include "CardResource.h" -#include "CardResourceServiceProvider.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "ConfigurationUtil.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::calypso; -using namespace keyple::core::service; -using namespace keyple::core::service::resource; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::core::util::protocol; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamUtil.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/service/resource/CardResource.hpp" +#include "keyple/core/service/resource/CardResourceProfileConfigurator.hpp" +#include "keyple/core/service/resource/CardResourceService.hpp" +#include "keyple/core/service/resource/CardResourceServiceProvider.hpp" +#include "keyple/core/service/resource/PluginsConfigurator.hpp" +#include "keyple/core/service/resource/spi/CardResourceProfileExtension.hpp" +#include "keyple/core/service/resource/spi/ReaderConfiguratorSpi.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/Exception.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/WriteAccessLevel.hpp" +#include "keypop/calypso/card/card/CalypsoCard.hpp" +#include "keypop/calypso/card/card/CalypsoCardSelectionExtension.hpp" +#include "keypop/calypso/card/cpp/SecureRegularModeTransactionManagerBase.hpp" +#include "keypop/calypso/card/transaction/SecureSymmetricCryptoTransactionManager.hpp" +#include "keypop/calypso/card/transaction/SymmetricCryptoSecuritySetting.hpp" +#include "keypop/calypso/crypto/legacysam/LegacySamApiFactory.hpp" +#include "keypop/calypso/crypto/legacysam/sam/LegacySam.hpp" +#include "keypop/calypso/crypto/legacysam/sam/LegacySamSelectionExtension.hpp" +#include "keypop/calypso/crypto/legacysam/spi/LegacySamDynamicUnlockDataProviderSpi.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ChannelControl.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +#include "../common/ConfigurationUtil.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamUtil; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::service::resource::CardResource; +using keyple::core::service::resource::CardResourceProfileConfigurator; +using keyple::core::service::resource::CardResourceService; +using keyple::core::service::resource::CardResourceServiceProvider; +using keyple::core::service::resource::PluginsConfigurator; +using keyple::core::service::resource::spi::CardResourceProfileExtension; +using keyple::core::service::resource::spi::ReaderConfiguratorSpi; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::Exception; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::WriteAccessLevel; +using keypop::calypso::card::card::CalypsoCard; +using keypop::calypso::card::card::CalypsoCardSelectionExtension; +using keypop::calypso::card::cpp::SecureRegularModeTransactionManagerBase; +using keypop::calypso::card::transaction:: + SecureSymmetricCryptoTransactionManager; +using keypop::calypso::card::transaction::SymmetricCryptoSecuritySetting; +using keypop::calypso::crypto::legacysam::LegacySamApiFactory; +using keypop::calypso::crypto::legacysam::sam::LegacySam; +using keypop::calypso::crypto::legacysam::sam::LegacySamSelectionExtension; +using keypop::calypso::crypto::legacysam::spi:: + LegacySamDynamicUnlockDataProviderSpi; +using keypop::reader::CardReader; +using keypop::reader::ChannelControl; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::selection::spi::SmartCard; /** - *

Use Case Calypso 4 – Calypso Card authentication (PC/SC)

- * - *

We demonstrate here the authentication of a Calypso card using a Secure Session in which a - * file from the card is read. The read is certified by verifying the signature of the card by a - * Calypso SAM. - * - *

Two readers are required for this example: a contactless reader for the Calypso Card, a - * contact reader for the Calypso SAM. - * - *

Scenario:

- * - *
    - *
  • Sets up the card resource service to provide a Calypso SAM (C1). - *
  • Checks if an ISO 14443-4 card is in the reader, enables the card selection manager. - *
  • Attempts to select the specified card (here a Calypso card characterized by its AID) with - * an AID-based application selection scenario. - *
  • Creates a CardTransactionManager using CardSecuritySetting referencing the - * SAM profile defined in the card resource service. - *
  • Read a file record in Secure Session. - *
- * - *

Any unexpected behavior will result in runtime exceptions. + * Handles the process of a Calypso card authentication using the PC/SC + * plugin, the Calypso Card Extension Service, and the Card Resource Service + * to manage the SAM. */ -class Main_CardAuthentication_Pcsc_SamResourceService {}; -static const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_CardAuthentication_Pcsc_SamResourceService)); +class Main_CardAuthentication_Pcsc_SamResourceService { }; +static std::unique_ptr logger = LoggerFactory::getLogger( + typeid(Main_CardAuthentication_Pcsc_SamResourceService)); -int main() -{ - /* Get the instance of the SmartCardService */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); +/** AID: Keyple test kit profile 1, Application 2 */ +static const std::string AID = "315449432E49434131"; - /* Register the PcscPlugin, get the corresponding generic plugin in return */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); +/* File identifiers */ +static const std::uint8_t SFI_ENVIRONMENT_AND_HOLDER = 0x07; +static const int RECORD_SIZE = 29; - /* Get the Calypso card extension service */ - std::shared_ptr calypsoCardService = - CalypsoExtensionService::getInstance(); +/* + * The name of the SAM resource provided by the Card Resource Manager and used + * during the card transaction. + */ +static const std::string SAM_PROFILE_NAME = "SAM C1"; + +/* The plugin used to manage the readers. */ +static std::shared_ptr plugin; +/* The reader used to communicate with the card. */ +static std::shared_ptr cardReader; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* + * The Calypso factory used to create the selection extension and transaction + * managers. + */ +static std::shared_ptr calypsoCardApiFactory; +/* The security settings for the card transaction. */ +static std::shared_ptr + symmetricCryptoSecuritySetting; + +/** + * Provides the dynamic unlock data expected by the SAM. + */ +class DynamicUnlockDataProvider final +: public LegacySamDynamicUnlockDataProviderSpi { +public: + /** + * {@inheritDoc} + */ + const std::vector& + getUnlockData( + const std::vector& samSerialNumber, + const std::vector& samChallenge) const override { + mLogger->debug( + "DynamicUnlockDataProvider.getUnlockData: samSerialNumber = " + "%\n", + HexUtil::toHex(samSerialNumber)); + mLogger->debug( + "DynamicUnlockDataProvider.getUnlockData: samChallenge = %\n", + HexUtil::toHex(samChallenge)); + + return mUnlockData; + } - /* Verify that the extension's API level is consistent with the current service */ - smartCardService->checkCardExtension(calypsoCardService); +private: + /** + * + */ + const std::unique_ptr mLogger + = LoggerFactory::getLogger(typeid(DynamicUnlockDataProvider)); - /* Get the contactless reader whose name matches the provided regex */ - std::shared_ptr cardReader = - ConfigurationUtil::getCardReader(plugin, ConfigurationUtil::CARD_READER_NAME_REGEX); + /** + * + */ + const std::vector mUnlockData + = HexUtil::toByteArray("0011223344556677"); +}; - /* - * Configure the card resource service to provide an adequate SAM for future secure operations. - * We suppose here, we use an Identive contact PC/SC reader as card reader. +/** + * Reader configurator used by the card resource service to set up the SAM + * reader with the required settings. + */ +class ReaderConfigurator final : public ReaderConfiguratorSpi { +public: + /** + * {@inheritDoc} */ - ConfigurationUtil::setupCardResourceService(plugin, - ConfigurationUtil::SAM_READER_NAME_REGEX, - CalypsoConstants::SAM_PROFILE_NAME); + void + setupReader(std::shared_ptr reader) override { + /* Configure the reader with parameters suitable for contact operations + */ + try { + auto readerExtension = std::dynamic_pointer_cast( + SmartCardServiceProvider::getService() + ->getPlugin(reader) + ->getReaderExtension( + typeid(PcscReader), reader->getName())); + if (readerExtension != nullptr) { + readerExtension->setContactless(false) + .setIsoProtocol(PcscReader::IsoProtocol::ANY) + .setSharingMode(PcscReader::SharingMode::SHARED); + } + } catch (const Exception& e) { + mLogger->error( + "Exception raised while setting up the reader %\n", + reader->getName(), + e); + } + } - logger->info("=============== " \ - "UseCase Calypso #4: Calypso card authentication " \ - "==================\n"); +private: + /** + * + */ + const std::unique_ptr mLogger + = LoggerFactory::getLogger(typeid(ReaderConfigurator)); +}; - /* Check if a card is present in the reader */ - if (!cardReader->isCardPresent()) { - throw IllegalStateException("No card is present in the reader."); +/** + * Initializes the Keyple service. + */ +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); + plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} + +/** + * Initializes the card reader with specific configurations. + */ +static void +initCardReader() { + cardReader = ConfigurationUtil::getReader( + plugin, + ConfigurationUtil::CARD_READER_NAME_REGEX, + true, + PcscReader::IsoProtocol::T1, + PcscReader::SharingMode::SHARED, + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ConfigurationUtil::ISO_CARD_PROTOCOL); +} + +/** + * Initializes the SAM Resource Service making a SAM resource available under + * the SAM_PROFILE_NAME name. + */ +static void +initSamResourceService() { + std::shared_ptr legacySamApiFactory( + LegacySamExtensionService::getInstance()->getLegacySamApiFactory()); + + /* Create a card resource extension expecting a SAM "C1" */ + std::shared_ptr samSelection( + legacySamApiFactory->createLegacySamSelectionExtension()); + samSelection + ->setDynamicUnlockDataProvider( + std::make_shared()) + .prepareReadAllCountersStatus(); + + std::shared_ptr samCardResourceExtension( + LegacySamExtensionService::getInstance() + ->createLegacySamResourceProfileExtension( + samSelection, + LegacySamUtil::buildPowerOnDataFilter( + LegacySam::ProductType::SAM_C1, ""))); + + /* Get the card resource service */ + std::shared_ptr cardResourceService( + CardResourceServiceProvider::getService()); + + /* Set up a basic configuration without plugin/reader observation */ + cardResourceService->getConfigurator() + ->withPlugins( + PluginsConfigurator::builder() + ->addPlugin(plugin, std::make_shared()) + .build()) + .withCardResourceProfiles( + {CardResourceProfileConfigurator::builder( + SAM_PROFILE_NAME, samCardResourceExtension) + ->withReaderNameRegex(ConfigurationUtil::SAM_READER_NAME_REGEX) + .build()}) + .configure(); + cardResourceService->start(); + + /* Verify if the card resource is available */ + std::shared_ptr cardResource( + cardResourceService->getCardResource(SAM_PROFILE_NAME)); + + if (cardResource == nullptr) { + throw IllegalStateException( + "Failed to retrieve a SAM card resource. No card resource found " + "for profile '" + + SAM_PROFILE_NAME + "' with reader matching '" + + ConfigurationUtil::SAM_READER_NAME_REGEX + "' in plugin '" + + plugin->getName() + "'."); } - logger->info("= #### Select application with AID = '%'\n", CalypsoConstants::AID); + /* Release the card resource */ + cardResourceService->releaseCardResource(cardResource); +} - /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); +/** + * Initializes the security settings for the transaction. + */ +static void +initSecuritySetting() { + std::shared_ptr samResource( + CardResourceServiceProvider::getService()->getCardResource( + SAM_PROFILE_NAME)); + + symmetricCryptoSecuritySetting + = calypsoCardApiFactory->createSymmetricCryptoSecuritySetting( + LegacySamExtensionService::getInstance() + ->getLegacySamApiFactory() + ->createSymmetricCryptoCardTransactionManagerFactory( + samResource->getReader(), + std::dynamic_pointer_cast( + samResource->getSmartCard()))); +} - /* - * Create a card selection using the Calypso card extension. - * Prepare the selection by adding the created Calypso card selection to the card selection - * scenario. - */ - auto cardSelection = calypsoCardService->createCardSelection(); - cardSelection->acceptInvalidatedCard().filterByDfName(CalypsoConstants::AID); - cardSelectionManager->prepareSelection(cardSelection); +/** + * Initializes the Calypso card extension service. + */ +static void +initCalypsoCardExtensionService() { + std::shared_ptr calypsoExtensionService( + CalypsoExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + calypsoExtensionService); + calypsoCardApiFactory = calypsoExtensionService->getCalypsoCardApiFactory(); +} - /* Actual card communication: run the selection scenario. */ - std::shared_ptr selectionResult = - cardSelectionManager->processCardSelectionScenario(cardReader); +/** + * Selects the Calypso card for the transaction based on the specified + * Application Identifier (AID). + */ +static std::shared_ptr +selectCard(std::shared_ptr reader, const std::string& aid) { + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(aid); + + std::unique_ptr + calypsoCardSelectionExtension( + calypsoCardApiFactory->createCalypsoCardSelectionExtension()); + cardSelectionManager->prepareSelection( + cardSelector, std::move(calypsoCardSelectionExtension)); + + const std::shared_ptr selectionResult( + cardSelectionManager->processCardSelectionScenario(reader)); - /* Check the selection result. */ if (selectionResult->getActiveSmartCard() == nullptr) { - throw IllegalStateException("The selection of the application " + - CalypsoConstants::AID + - " failed."); + throw IllegalStateException( + "The selection of the application '" + aid + "' failed."); } - /* Get the SmartCard resulting of the selection. */ - std::shared_ptr calypsoCard = - std::dynamic_pointer_cast(selectionResult->getActiveSmartCard()); + const std::shared_ptr card( + selectionResult->getActiveSmartCard()); - logger->info("= SmartCard = %\n", calypsoCard); + return std::dynamic_pointer_cast(card); +} - const std::string csn = HexUtil::toHex(calypsoCard->getApplicationSerialNumber()); - logger->info("Calypso Serial Number = %\n", csn); +int +main() { + logger->info( + "= UseCase Calypso #4: Calypso card authentication (Card Resource " + "Service) ==================\n"); - /* - * Create security settings that reference the same SAM profile requested from the card resource - * service. - */ - std::shared_ptr samResource = - CardResourceServiceProvider::getService() - ->getCardResource(CalypsoConstants::SAM_PROFILE_NAME); - std::shared_ptr cardSecuritySetting = - CalypsoExtensionService::getInstance()->createCardSecuritySetting(); - cardSecuritySetting->setControlSamResource( - samResource->getReader(), - std::dynamic_pointer_cast(samResource->getSmartCard())); - - try { - /* Performs file reads using the card transaction manager in secure mode. */ - calypsoCardService->createCardTransaction(cardReader, calypsoCard, cardSecuritySetting) - ->prepareReadRecords(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_SIZE) - .processOpening(WriteAccessLevel::DEBIT) - .prepareReleaseCardChannel() - .processClosing(); - - } catch (const Exception& e) { - (void)e; - } + /* Initialize the context */ + initKeypleService(); + initCalypsoCardExtensionService(); + initCardReader(); + initSamResourceService(); + initSecuritySetting(); - /* Finally */ - try { - CardResourceServiceProvider::getService()->releaseCardResource(samResource); - } catch (const RuntimeException& e) { - logger->error("Error during the card resource release: %\n", e.getMessage(), e); + /* Check the card presence */ + if (!cardReader->isCardPresent()) { + throw IllegalStateException("No card is present in the reader."); } - logger->info("The Secure Session ended successfully, the card is authenticated and the data " \ - "read are certified\n"); + /* Select the card */ + std::shared_ptr calypsoCard = selectCard(cardReader, AID); - const std::string sfiEnvHolder = HexUtil::toHex(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER); - logger->info("File %h, rec 1: FILE_CONTENT = %\n", - sfiEnvHolder, - calypsoCard->getFileBySfi(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER)); + /* + * Execute the transaction: the environment file is read within a secure + * session to ensure data authenticity. + */ + std::unique_ptr + cardTransactionManager( + calypsoCardApiFactory->createSecureRegularModeTransactionManager( + cardReader, calypsoCard, symmetricCryptoSecuritySetting)); + + dynamic_cast*>(cardTransactionManager.get()) + ->prepareOpenSecureSession(WriteAccessLevel::DEBIT) + .prepareReadRecords(SFI_ENVIRONMENT_AND_HOLDER, 1, 1, RECORD_SIZE) + .prepareCloseSecureSession() + .processCommands(ChannelControl::CLOSE_AFTER); + + logger->info( + "The secure session has ended successfully; the card is " + "authenticated, and the read data is certified.\n"); + + const std::string csn( + HexUtil::toHex(calypsoCard->getApplicationSerialNumber())); + logger->info("Calypso Serial Number = %\n", csn); - logger->info("= #### End of the Calypso card processing.\n"); + const std::string sfiEnvHolder(HexUtil::toHex(SFI_ENVIRONMENT_AND_HOLDER)); + logger->info( + "File SFI %h, rec 1: FILE_CONTENT = %\n", + sfiEnvHolder, + calypsoCard->getFileBySfi(SFI_ENVIRONMENT_AND_HOLDER)); return 0; } diff --git a/Example_Card_Calypso/src/main/UseCase4_CardAuthentication/Main_CardAuthentication_Stub.cpp b/Example_Card_Calypso/src/main/UseCase4_CardAuthentication/Main_CardAuthentication_Stub.cpp index c8fea92..6247814 100644 --- a/Example_Card_Calypso/src/main/UseCase4_CardAuthentication/Main_CardAuthentication_Stub.cpp +++ b/Example_Card_Calypso/src/main/UseCase4_CardAuthentication/Main_CardAuthentication_Stub.cpp @@ -1,209 +1,388 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "ObservableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Core Service Resource */ -#include "CardResource.h" -#include "CardResourceServiceProvider.h" - -/* Keyple Core Util */ -#include "ContactCardCommonProtocol.h" -#include "ContactlessCardCommonProtocol.h" -#include "HexUtil.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" -#include "StringUtils.h" -#include "Thread.h" - -/* Keyple Plugin Stub */ -#include "StubPlugin.h" -#include "StubPluginFactoryBuilder.h" -#include "StubReader.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "ConfigurationUtil.h" -#include "StubSmartCardFactory.h" - -using namespace keyple::card::calypso; -using namespace keyple::core::service; -using namespace keyple::core::service::resource; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::core::util::protocol; -using namespace keyple::plugin::stub; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamExtensionService.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/service/resource/CardResource.hpp" +#include "keyple/core/service/resource/CardResourceProfileConfigurator.hpp" +#include "keyple/core/service/resource/CardResourceService.hpp" +#include "keyple/core/service/resource/CardResourceServiceProvider.hpp" +#include "keyple/core/service/resource/PluginsConfigurator.hpp" +#include "keyple/core/service/resource/spi/CardResourceProfileExtension.hpp" +#include "keyple/core/service/resource/spi/ReaderConfiguratorSpi.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/stub/StubPluginFactoryBuilder.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/WriteAccessLevel.hpp" +#include "keypop/calypso/card/card/CalypsoCard.hpp" +#include "keypop/calypso/card/card/CalypsoCardSelectionExtension.hpp" +#include "keypop/calypso/card/cpp/SecureRegularModeTransactionManagerBase.hpp" +#include "keypop/calypso/card/transaction/SecureSymmetricCryptoTransactionManager.hpp" +#include "keypop/calypso/card/transaction/SymmetricCryptoSecuritySetting.hpp" +#include "keypop/calypso/crypto/legacysam/LegacySamApiFactory.hpp" +#include "keypop/calypso/crypto/legacysam/sam/LegacySam.hpp" +#include "keypop/calypso/crypto/legacysam/sam/LegacySamSelectionExtension.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ChannelControl.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +#include "../common/StubSmartCardFactory.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamExtensionService; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::service::resource::CardResource; +using keyple::core::service::resource::CardResourceProfileConfigurator; +using keyple::core::service::resource::CardResourceService; +using keyple::core::service::resource::CardResourceServiceProvider; +using keyple::core::service::resource::PluginsConfigurator; +using keyple::core::service::resource::spi::CardResourceProfileExtension; +using keyple::core::service::resource::spi::ReaderConfiguratorSpi; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::stub::StubPluginFactoryBuilder; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::WriteAccessLevel; +using keypop::calypso::card::card::CalypsoCard; +using keypop::calypso::card::card::CalypsoCardSelectionExtension; +using keypop::calypso::card::cpp::SecureRegularModeTransactionManagerBase; +using keypop::calypso::card::transaction:: + SecureSymmetricCryptoTransactionManager; +using keypop::calypso::card::transaction::SymmetricCryptoSecuritySetting; +using keypop::calypso::crypto::legacysam::LegacySamApiFactory; +using keypop::calypso::crypto::legacysam::sam::LegacySam; +using keypop::calypso::crypto::legacysam::sam::LegacySamSelectionExtension; +using keypop::reader::CardReader; +using keypop::reader::ChannelControl; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::selection::spi::SmartCard; /** - *

Use Case Calypso 4 – Calypso Card authentication (Stub)

+ * Handles the process of a Calypso card authentication using the Stub plugin + * and the Calypso Card Extension Service. The Stub plugin is used to simulate + * card and reader hardware for testing and development purposes. * - *

We demonstrate here the authentication of a Calypso card using a Secure Session in which a - * file from the card is read. The read is certified by verifying the signature of the card by a - * Calypso SAM. + *

This class demonstrates the card authentication process, including the + * initialization of the Smart Card Service, registering the Stub plugin, + * checking the compatibility of the Calypso card extension service, and + * performing operations with the Keypop Reader and Calypso Card APIs. * - *

Two readers are required for this example: a contactless reader for the Calypso Card, a - * contact reader for the Calypso SAM. + *

The class also demonstrates how to set up the Card Resource Service to + * manage the SAM and how to operate the security of transactions. * - *

Scenario:

+ *

Key Functionalities

* *
    - *
  • Sets up the card resource service to provide a Calypso SAM (C1). - *
  • Checks if an ISO 14443-4 card is in the reader, enables the card selection manager. - *
  • Attempts to select the specified card (here a Calypso card characterized by its AID) with - * an AID-based application selection scenario. - *
  • Creates a {@link CardTransactionManager} using {@link CardSecuritySetting} referencing the - * SAM profile defined in the card resource service. - *
  • Read a file record in Secure Session. + *
  • Initialization of the Smart Card Service and registering the Stub + * plugin. + *
  • Configuration of the card and SAM readers. + *
  • Selection of the card and the SAM. + *
  • Authentication of the Calypso Card by reading its content in a secure + * session. *
- * - *

Any unexpected behavior will result in runtime exceptions. */ -class Main_CardAuthentication_Stub {}; -static const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_CardAuthentication_Stub)); +class Main_CardAuthentication_Stub { }; +static std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_CardAuthentication_Stub)); static const std::string CARD_READER_NAME = "Stub card reader"; static const std::string SAM_READER_NAME = "Stub SAM reader"; -int main() -{ - /* Get the instance of the SmartCardService */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); +/** AID: Keyple test kit profile 1, Application 2 */ +static const std::string AID = "315449432E49434131"; - /* - * Register the StubPlugin with the SmartCardService, plug a Calypso card stub - * get the corresponding generic plugin in return. - */ - std::shared_ptr pluginFactory = - StubPluginFactoryBuilder::builder() - ->withStubReader(CARD_READER_NAME, true, StubSmartCardFactory::getStubCard()) - .withStubReader(SAM_READER_NAME, false, StubSmartCardFactory::getStubSam()) - .build(); - std::shared_ptr plugin = smartCardService->registerPlugin(pluginFactory); +/* File identifiers */ +static const std::uint8_t SFI_ENVIRONMENT_AND_HOLDER = 0x07; +static const int RECORD_SIZE = 29; - /* Get the Calypso card extension service */ - auto calypsoCardService = CalypsoExtensionService::getInstance(); +/* + * The name of the SAM resource provided by the Card Resource Manager and used + * during the card transaction. + */ +static const std::string SAM_PROFILE_NAME = "SAM C1"; + +/* The plugin used to manage the readers. */ +static std::shared_ptr plugin; +/* The reader used to communicate with the card. */ +static std::shared_ptr cardReader; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* + * The Calypso factory used to create the selection extension and transaction + * managers. + */ +static std::shared_ptr calypsoCardApiFactory; +/* The security settings for the card transaction. */ +static std::shared_ptr + symmetricCryptoSecuritySetting; - /* Verify that the extension's API level is consistent with the current service */ - smartCardService->checkCardExtension(calypsoCardService); +/** + * Reader configurator used by the card resource service to set up the SAM + * reader with the required settings. + */ +class ReaderConfigurator final : public ReaderConfiguratorSpi { +public: + /** + * {@inheritDoc} + */ + void + setupReader(std::shared_ptr /* reader */) override { + /* No specific configuration in the case of a Stub reader */ + } +}; - /* Get and set up the card reader */ - std::shared_ptr cardReader = plugin->getReader(CARD_READER_NAME); +/** + * Initializes the Keyple service. + * + *

Gets an instance of the smart card service, registers the Stub plugin, + * and prepares the reader API factory for use. + * + *

Retrieves the {@link ReaderApiFactory}. + */ +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); /* - * Configure the card resource service to provide an adequate SAM for future secure operations + * Register the StubPlugin with the SmartCardService and plug in stubs for + * both a Calypso card and a Calypso SAM. */ - ConfigurationUtil::setupCardResourceService(plugin, - SAM_READER_NAME, - CalypsoConstants::SAM_PROFILE_NAME); + plugin = smartCardService->registerPlugin( + StubPluginFactoryBuilder::builder() + ->withStubReader( + CARD_READER_NAME, true, StubSmartCardFactory::getStubCard()) + .withStubReader( + SAM_READER_NAME, false, StubSmartCardFactory::getStubSam()) + .build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} - logger->info("=============== " \ - "UseCase Calypso #4: Calypso card authentication " \ - "==================\n"); +/** + * Initializes the card reader with specific configurations. + */ +static void +initCardReader() { + cardReader = plugin->getReader(CARD_READER_NAME); +} - /* Check if a card is present in the reader */ - if (!cardReader->isCardPresent()) { - throw IllegalStateException("No card is present in the reader."); - } +/** + * Initializes the Calypso card extension service. + * + *

Retrieves the {@link CalypsoCardApiFactory}. + */ +static void +initCalypsoCardExtensionService() { + std::shared_ptr calypsoExtensionService( + CalypsoExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + calypsoExtensionService); + calypsoCardApiFactory = calypsoExtensionService->getCalypsoCardApiFactory(); +} - logger->info("= #### Select application with AID = '%'\n", CalypsoConstants::AID); +/** + * Initializes the SAM Resource Service making a SAM resource available under + * the SAM_PROFILE_NAME name. + */ +static void +initSamResourceService() { + /* Retrieve the Legacy SAM factory to create the SAM selection and profile + * extensions */ + std::shared_ptr legacySamApiFactory( + LegacySamExtensionService::getInstance()->getLegacySamApiFactory()); + + /* Create a card resource extension expecting a SAM "C1" */ + std::shared_ptr samSelection( + legacySamApiFactory->createLegacySamSelectionExtension()); + + std::shared_ptr samCardResourceExtension( + LegacySamExtensionService::getInstance() + ->createLegacySamResourceProfileExtension(samSelection)); + + /* Get the card resource service */ + std::shared_ptr cardResourceService( + CardResourceServiceProvider::getService()); + + /* Set up a basic configuration without plugin/reader observation */ + cardResourceService->getConfigurator() + ->withPlugins( + PluginsConfigurator::builder() + ->addPlugin(plugin, std::make_shared()) + .build()) + .withCardResourceProfiles( + {CardResourceProfileConfigurator::builder( + SAM_PROFILE_NAME, samCardResourceExtension) + ->withReaderNameRegex(SAM_READER_NAME) + .build()}) + .configure(); + cardResourceService->start(); + + /* Verify if the card resource is available */ + std::shared_ptr cardResource( + cardResourceService->getCardResource(SAM_PROFILE_NAME)); + + if (cardResource == nullptr) { + throw IllegalStateException( + "Failed to retrieve a SAM card resource. No card resource found " + "for profile '" + + SAM_PROFILE_NAME + "' with reader matching '" + SAM_READER_NAME + + "' in plugin '" + plugin->getName() + "'."); + } - /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + /* Release the card resource */ + cardResourceService->releaseCardResource(cardResource); +} - /* - * Create a card selection using the Calypso card extension. - * Prepare the selection by adding the created Calypso card selection to the card selection - * scenario. - */ - std::shared_ptr cardSelection = calypsoCardService->createCardSelection(); - cardSelection->acceptInvalidatedCard() - .filterByDfName(CalypsoConstants::AID); - cardSelectionManager->prepareSelection(cardSelection); +/** + * Initializes the security settings for the transaction. + * + *

Uses the Card Resource Service to retrieve the SAM reader, the SAM, and + * sets up the symmetric crypto security setting for securing the transaction. + */ +static void +initSecuritySetting() { + std::shared_ptr samResource( + CardResourceServiceProvider::getService()->getCardResource( + SAM_PROFILE_NAME)); + + symmetricCryptoSecuritySetting + = calypsoCardApiFactory->createSymmetricCryptoSecuritySetting( + LegacySamExtensionService::getInstance() + ->getLegacySamApiFactory() + ->createSymmetricCryptoCardTransactionManagerFactory( + samResource->getReader(), + std::dynamic_pointer_cast( + samResource->getSmartCard()))); +} - /* Actual card communication: run the selection scenario */ - const std::shared_ptr selectionResult = - cardSelectionManager->processCardSelectionScenario(cardReader); +/** + * Selects the Calypso card for the transaction based on the specified + * Application Identifier (AID). + * + * @param reader The reader used to communicate with the card. + * @param aid The Application Identifier (AID) used to select the application + * on the card. + * @return The selected Calypso card ready for the transaction. + */ +static std::shared_ptr +selectCard(std::shared_ptr reader, const std::string& aid) { + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(aid); + + std::unique_ptr + calypsoCardSelectionExtension( + calypsoCardApiFactory->createCalypsoCardSelectionExtension()); + cardSelectionManager->prepareSelection( + cardSelector, std::move(calypsoCardSelectionExtension)); + + const std::shared_ptr selectionResult( + cardSelectionManager->processCardSelectionScenario(reader)); - /* Check the selection result */ if (selectionResult->getActiveSmartCard() == nullptr) { - throw IllegalStateException("The selection of the application '" + - CalypsoConstants::AID + - "' failed."); + throw IllegalStateException( + "The selection of the application '" + aid + "' failed."); } - /* Get the SmartCard resulting of the selection */ - const std::shared_ptr card = selectionResult->getActiveSmartCard(); - auto calypsoCard = std::dynamic_pointer_cast(card); + const std::shared_ptr card( + selectionResult->getActiveSmartCard()); - logger->info("= SmartCard = %\n", calypsoCard); + return std::dynamic_pointer_cast(card); +} - const std::string csn = HexUtil::toHex(calypsoCard->getApplicationSerialNumber()); - logger->info("Calypso Serial Number = %\n", csn); +int +main() { + logger->info( + "= UseCase Calypso #4: Calypso card authentication (Stub, Card " + "Resource Service) ==================\n"); - /* - * Create security settings that reference the same SAM profile requested from the card resource - * service. - */ - std::shared_ptr samResource = - CardResourceServiceProvider::getService() - ->getCardResource(CalypsoConstants::SAM_PROFILE_NAME); - - std::shared_ptr cardSecuritySetting = - CalypsoExtensionService::getInstance()->createCardSecuritySetting(); - cardSecuritySetting->setControlSamResource(samResource->getReader(), - std::dynamic_pointer_cast( - samResource->getSmartCard())); - - //try { - /* Performs file reads using the card transaction manager in secure mode */ - std::shared_ptr cardTransaction = - calypsoCardService->createCardTransaction(cardReader, calypsoCard, cardSecuritySetting); - cardTransaction->prepareReadRecords(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_NUMBER_1, - CalypsoConstants::RECORD_SIZE) - .processOpening(WriteAccessLevel::DEBIT) - .prepareReleaseCardChannel() - .processClosing(); - //} finally { - try { - CardResourceServiceProvider::getService()->releaseCardResource(samResource); - } catch (const RuntimeException& e) { - logger->error("Error during the card resource release: %\n", e.getMessage(), e); + /* Initialize the context */ + initKeypleService(); + initCalypsoCardExtensionService(); + initCardReader(); + initSamResourceService(); + initSecuritySetting(); + + /* Check the card presence */ + if (!cardReader->isCardPresent()) { + throw IllegalStateException("No card is present in the reader."); } - //} - logger->info("The Secure Session ended successfully, the card is authenticated and the data " \ - "read are certified\n"); + /* Select the card */ + std::shared_ptr calypsoCard = selectCard(cardReader, AID); - const std::string sfiEnvHolder = HexUtil::toHex(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER); - logger->info("File %h, rec 1: FILE_CONTENT = %\n", - sfiEnvHolder, - calypsoCard->getFileBySfi(CalypsoConstants::SFI_ENVIRONMENT_AND_HOLDER)); + /* + * Execute the transaction: the environment file is read within a secure + * session to ensure data authenticity. + * Specifying expected response lengths in read commands serves as a + * protective measure for legacy cards. + * + * The keypop API declares createSecureRegularModeTransactionManager() as + * returning a SecureRegularModeTransactionManagerBase, which does not + * itself expose prepareOpenSecureSession() (it's only declared on + * SecureSymmetricCryptoTransactionManager, a sibling interface + * implemented by the same concrete object). A downcast is required to + * reach it. + */ + std::unique_ptr + cardTransactionManager( + calypsoCardApiFactory->createSecureRegularModeTransactionManager( + cardReader, calypsoCard, symmetricCryptoSecuritySetting)); + + dynamic_cast*>(cardTransactionManager.get()) + ->prepareOpenSecureSession(WriteAccessLevel::DEBIT) + .prepareReadRecords(SFI_ENVIRONMENT_AND_HOLDER, 1, 1, RECORD_SIZE) + .prepareCloseSecureSession() + .processCommands(ChannelControl::CLOSE_AFTER); + + logger->info( + "The secure session has ended successfully; the card is " + "authenticated, and the read data is certified.\n"); + + const std::string csn( + HexUtil::toHex(calypsoCard->getApplicationSerialNumber())); + logger->info("Calypso Serial Number = %\n", csn); - logger->info("= #### End of the Calypso card processing\n"); + const std::string sfiEnvHolder(HexUtil::toHex(SFI_ENVIRONMENT_AND_HOLDER)); + logger->info( + "File SFI %h, rec 1: FILE_CONTENT = %\n", + sfiEnvHolder, + calypsoCard->getFileBySfi(SFI_ENVIRONMENT_AND_HOLDER)); return 0; } diff --git a/Example_Card_Calypso/src/main/UseCase5_MultipleSession/Main_MultipleSession_Pcsc.cpp b/Example_Card_Calypso/src/main/UseCase5_MultipleSession/Main_MultipleSession_Pcsc.cpp index c1852e7..15f90a9 100644 --- a/Example_Card_Calypso/src/main/UseCase5_MultipleSession/Main_MultipleSession_Pcsc.cpp +++ b/Example_Card_Calypso/src/main/UseCase5_MultipleSession/Main_MultipleSession_Pcsc.cpp @@ -1,189 +1,339 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" -#include "ConfigurableCardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Core Util */ -#include "HexUtil.h" -#include "ContactCardCommonProtocol.h" -#include "ContactlessCardCommonProtocol.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" -#include "StringUtils.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPlugin.h" -#include "PcscPluginFactory.h" -#include "PcscPluginFactoryBuilder.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "ConfigurationUtil.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::calypso; -using namespace keyple::core::service; -using namespace keyple::core::service::resource; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::core::util::protocol; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamUtil.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactProtocol.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/WriteAccessLevel.hpp" +#include "keypop/calypso/card/card/CalypsoCard.hpp" +#include "keypop/calypso/card/card/CalypsoCardSelectionExtension.hpp" +#include "keypop/calypso/card/cpp/SecureRegularModeTransactionManagerBase.hpp" +#include "keypop/calypso/card/transaction/SecureSymmetricCryptoTransactionManager.hpp" +#include "keypop/calypso/card/transaction/SymmetricCryptoSecuritySetting.hpp" +#include "keypop/calypso/crypto/legacysam/LegacySamApiFactory.hpp" +#include "keypop/calypso/crypto/legacysam/sam/LegacySam.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ChannelControl.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +#include "../common/ConfigurationUtil.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamUtil; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keyple::plugin::pcsc::PcscSupportedContactProtocol; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::WriteAccessLevel; +using keypop::calypso::card::card::CalypsoCard; +using keypop::calypso::card::card::CalypsoCardSelectionExtension; +using keypop::calypso::card::cpp::SecureRegularModeTransactionManagerBase; +using keypop::calypso::card::transaction:: + SecureSymmetricCryptoTransactionManager; +using keypop::calypso::card::transaction::SymmetricCryptoSecuritySetting; +using keypop::calypso::crypto::legacysam::LegacySamApiFactory; +using keypop::calypso::crypto::legacysam::sam::LegacySam; +using keypop::reader::CardReader; +using keypop::reader::ChannelControl; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::selection::spi::SmartCard; /** - *

Use Case Calypso 5 – Multiple sessions (PC/SC)

+ * Handles the process of executing multiple sessions on a Calypso card using + * the PC/SC plugin, particularly to bypass the card's modification buffer + * limitation. * - *

We demonstrate here a simple way to bypass the card modification buffer limitation by using - * the multiple session mode. - * - *

Scenario:

- * - *
    - *
  • Sets up the card resource service to provide a Calypso SAM (C1). - *
  • Checks if an ISO 14443-4 card is in the reader, enables the card selection manager. - *
  • Attempts to select the specified card (here a Calypso card characterized by its AID) with - * an AID-based application selection scenario. - *
  • Creates a CardTransactionManager using CardSecuritySetting referencing the selected SAM. - *
  • Prepares and executes a number of modification commands that exceeds the number of commands - * allowed by the card's modification buffer size. - *
- * - * All results are logged with slf4j. - * - *

Any unexpected behavior will result in runtime exceptions. + *

This class illustrates a technique to overcome the restriction imposed + * by the modification buffer size of a Calypso card by utilizing multiple + * session mode. + */ +class Main_MultipleSession_Pcsc { }; +static std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_MultipleSession_Pcsc)); + +/** AID: Keyple test kit profile 1, Application 2 */ +static const std::string AID = "315449432E49434131"; + +/* File identifiers */ +static const std::uint8_t SFI_EVENT_LOG = 0x08; + +static const std::string EVENT_LOG_DATA_FILL + = "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCC"; + +/* The plugin used to manage the readers. */ +static std::shared_ptr plugin; +/* The reader used to communicate with the card. */ +static std::shared_ptr cardReader; +/* The reader used to communicate with the SAM. */ +static std::shared_ptr samReader; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* + * The Calypso factory used to create the selection extension and transaction + * managers. */ -class Main_MultipleSession_Pcsc {}; -static const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_MultipleSession_Pcsc)); +static std::shared_ptr calypsoCardApiFactory; +/* The security settings for the card transaction. */ +static std::shared_ptr + symmetricCryptoSecuritySetting; -int main() -{ - /* Get the instance of the SmartCardService */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); +/** + * Initializes the Keyple service. + */ +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); + plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} - /* Register the PcscPlugin, get the corresponding generic plugin in return */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); +/** + * Initializes the card reader with specific configurations. + */ +static void +initCardReader() { + cardReader = ConfigurationUtil::getReader( + plugin, + ConfigurationUtil::CARD_READER_NAME_REGEX, + true, + PcscReader::IsoProtocol::T1, + PcscReader::SharingMode::SHARED, + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ConfigurationUtil::ISO_CARD_PROTOCOL); +} - /* Get the Calypso card extension service */ - std::shared_ptr calypsoCardService = - CalypsoExtensionService::getInstance(); +/** + * Initializes the SAM reader with specific configurations. + */ +static void +initSamReader() { + samReader = ConfigurationUtil::getReader( + plugin, + ConfigurationUtil::SAM_READER_NAME_REGEX, + false, + PcscReader::IsoProtocol::ANY, + PcscReader::SharingMode::SHARED, + PcscSupportedContactProtocol::ISO_7816_3_T0.getName(), + ConfigurationUtil::SAM_PROTOCOL); +} - /* Verify that the extension's API level is consistent with the current service */ - smartCardService->checkCardExtension(calypsoCardService); +/** + * Initializes the Calypso card extension service. + */ +static void +initCalypsoCardExtensionService() { + std::shared_ptr calypsoExtensionService( + CalypsoExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + calypsoExtensionService); + calypsoCardApiFactory = calypsoExtensionService->getCalypsoCardApiFactory(); +} - /* Get the card and SAM readers whose name matches the provided regexs */ - std::shared_ptr cardReader = - ConfigurationUtil::getCardReader(plugin, ConfigurationUtil::CARD_READER_NAME_REGEX); - std::shared_ptr samReader = - ConfigurationUtil::getSamReader(plugin, ConfigurationUtil::SAM_READER_NAME_REGEX); +/** + * Selects the SAM C1 for the transaction. + */ +static std::shared_ptr +selectSam(std::shared_ptr reader) { + std::shared_ptr samSelectionManager( + readerApiFactory->createCardSelectionManager()); - logger->info("=============== UseCase Calypso #5: multiple sessions ==================\n"); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByPowerOnData( + LegacySamUtil::buildPowerOnDataFilter( + LegacySam::ProductType::SAM_C1, "")); - /* Check if a card is present in the reader */ - if (!cardReader->isCardPresent()) { - throw IllegalStateException("No card is present in the reader."); - } + std::shared_ptr legacySamApiFactory( + LegacySamExtensionService::getInstance()->getLegacySamApiFactory()); - /* Get the Calypso SAM SmartCard after selection. */ - std::shared_ptr calypsoSam = ConfigurationUtil::getSam(samReader); + samSelectionManager->prepareSelection( + cardSelector, legacySamApiFactory->createLegacySamSelectionExtension()); - logger->info("= SAM = %\n", calypsoSam); + const std::shared_ptr samSelectionResult( + samSelectionManager->processCardSelectionScenario(reader)); - logger->info("= #### Select application with AID = '%'\n", CalypsoConstants::AID); + if (samSelectionResult->getActiveSmartCard() == nullptr) { + throw IllegalStateException("The selection of the SAM failed."); + } - /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + return std::dynamic_pointer_cast( + samSelectionResult->getActiveSmartCard()); +} - /* - * Create a card selection using the Calypso card extension. - * Prepare the selection by adding the created Calypso card selection to the card selection - * scenario. - */ - std::shared_ptr cardSelection = calypsoCardService->createCardSelection(); - cardSelection->acceptInvalidatedCard() - .filterByDfName(CalypsoConstants::AID); - cardSelectionManager->prepareSelection(cardSelection); +/** + * Initializes the security settings for the transaction. + */ +static void +initSecuritySetting() { + std::shared_ptr sam(selectSam(samReader)); + + symmetricCryptoSecuritySetting + = calypsoCardApiFactory->createSymmetricCryptoSecuritySetting( + LegacySamExtensionService::getInstance() + ->getLegacySamApiFactory() + ->createSymmetricCryptoCardTransactionManagerFactory( + samReader, sam)); +} - /* Actual card communication: run the selection scenario */ - const std::shared_ptr selectionResult = - cardSelectionManager->processCardSelectionScenario(cardReader); +/** + * Selects the Calypso card for the transaction based on the specified + * Application Identifier (AID). + */ +static std::shared_ptr +selectCard(std::shared_ptr reader, const std::string& aid) { + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(aid); + + std::unique_ptr + calypsoCardSelectionExtension( + calypsoCardApiFactory->createCalypsoCardSelectionExtension()); + calypsoCardSelectionExtension->acceptInvalidatedCard(); + cardSelectionManager->prepareSelection( + cardSelector, std::move(calypsoCardSelectionExtension)); + + const std::shared_ptr selectionResult( + cardSelectionManager->processCardSelectionScenario(reader)); - /* Check the selection result */ if (selectionResult->getActiveSmartCard() == nullptr) { - throw IllegalStateException("The selection of the application '" + - CalypsoConstants::AID + - "' failed."); + throw IllegalStateException( + "The selection of the application '" + aid + "' failed."); } - /* Get the SmartCard resulting of the selection */ - const std::shared_ptr card = selectionResult->getActiveSmartCard(); - auto calypsoCard = std::dynamic_pointer_cast(card); + const std::shared_ptr card( + selectionResult->getActiveSmartCard()); + + return std::dynamic_pointer_cast(card); +} + +int +main() { + logger->info( + "= UseCase Calypso #5: multiple sessions ==================\n"); + + /* Initialize the context */ + initKeypleService(); + initCalypsoCardExtensionService(); + initCardReader(); + initSamReader(); + initSecuritySetting(); + + /* Check the card presence */ + if (!cardReader->isCardPresent()) { + throw IllegalStateException("No card is present in the reader."); + } + + /* Select the card */ + std::shared_ptr calypsoCard = selectCard(cardReader, AID); logger->info("= SmartCard = %\n", calypsoCard); - const std::string csn = HexUtil::toHex(calypsoCard->getApplicationSerialNumber()); + const std::string csn( + HexUtil::toHex(calypsoCard->getApplicationSerialNumber())); logger->info("Calypso Serial Number = %\n", csn); - /* Create security settings that reference the SAM */ - std::shared_ptr cardSecuritySetting = - CalypsoExtensionService::getInstance()->createCardSecuritySetting(); - cardSecuritySetting->setControlSamResource(samReader, calypsoSam); - cardSecuritySetting->enableMultipleSession(); + /* Enable the multiple session mode (disabled by default) */ + symmetricCryptoSecuritySetting->enableMultipleSession(); - /* Performs file reads using the card transaction manager in non-secure mode. */ - std::shared_ptr cardTransaction = - calypsoCardService->createCardTransaction(cardReader, calypsoCard, cardSecuritySetting); + /* + * The keypop API declares createSecureRegularModeTransactionManager() as + * returning a SecureRegularModeTransactionManagerBase, which does not + * itself expose prepareOpenSecureSession() (it's only declared on + * SecureSymmetricCryptoTransactionManager, a sibling interface + * implemented by the same concrete object). A downcast is required to + * reach it. + */ + std::unique_ptr + cardTransactionManagerBase( + calypsoCardApiFactory->createSecureRegularModeTransactionManager( + cardReader, calypsoCard, symmetricCryptoSecuritySetting)); + + auto cardTransaction = dynamic_cast*>( + cardTransactionManagerBase.get()); - cardTransaction->processOpening(WriteAccessLevel::DEBIT); + cardTransaction->prepareOpenSecureSession(WriteAccessLevel::DEBIT); /* - * Compute the number of append records (29 bytes) commands that will overflow the card - * modifications buffer. Each append records will consume 35 (29 + 6) bytes in the - * buffer. + * Compute the number of append records (29 bytes) commands that will + * overflow the card modifications buffer. Each append records will + * consume 35 (29 + 6) bytes in the buffer. * * We'll send one more command to demonstrate the MULTIPLE mode */ - const int modificationsBufferSize = 430; /* Not all Calypso card have this buffer size */ + /* Note: not all Calypso card have this buffer size */ + const int modificationsBufferSize = 430; + const int nbCommands = (modificationsBufferSize / 35) + 1; - logger->info("==== Send % Append Record commands. Modifications buffer capacity = % bytes" \ - " i.e. % 29-byte commands ====\n", - nbCommands, - modificationsBufferSize, - modificationsBufferSize / 35); + logger->info( + "==== Send % Append Record commands. Modifications buffer capacity " + "= % bytes i.e. % 29-byte commands ====\n", + nbCommands, + modificationsBufferSize, + modificationsBufferSize / 35); - for (int i = 0; i < nbCommands; i++) { + const std::vector eventLogDataFill( + HexUtil::toByteArray(EVENT_LOG_DATA_FILL)); - cardTransaction->prepareAppendRecord(CalypsoConstants::SFI_EVENT_LOG, - HexUtil::toByteArray( - CalypsoConstants::EVENT_LOG_DATA_FILL)); + for (int i = 0; i < nbCommands; i++) { + cardTransaction->prepareAppendRecord(SFI_EVENT_LOG, eventLogDataFill); } - cardTransaction->prepareReleaseCardChannel().processClosing(); + cardTransaction->prepareCloseSecureSession().processCommands( + ChannelControl::CLOSE_AFTER); - logger->info("The secure session has ended successfully, all data has been written to the " \ - "card's memory\n"); + logger->info( + "The secure session has ended successfully, all data has been " + "written to the card's memory.\n"); logger->info("= #### End of the Calypso card processing\n"); diff --git a/Example_Card_Calypso/src/main/UseCase6_VerifyPin/Main_VerifyPin_Pcsc.cpp b/Example_Card_Calypso/src/main/UseCase6_VerifyPin/Main_VerifyPin_Pcsc.cpp index 5a3aaba..144f0a2 100644 --- a/Example_Card_Calypso/src/main/UseCase6_VerifyPin/Main_VerifyPin_Pcsc.cpp +++ b/Example_Card_Calypso/src/main/UseCase6_VerifyPin/Main_VerifyPin_Pcsc.cpp @@ -1,212 +1,370 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Core Util */ -#include "ContactCardCommonProtocol.h" -#include "ContactlessCardCommonProtocol.h" -#include "HexUtil.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" -#include "StringUtils.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPlugin.h" -#include "PcscPluginFactory.h" -#include "PcscPluginFactoryBuilder.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "ConfigurationUtil.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::calypso; -using namespace keyple::core::service; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::core::util::protocol; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamUtil.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactProtocol.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/WriteAccessLevel.hpp" +#include "keypop/calypso/card/card/CalypsoCard.hpp" +#include "keypop/calypso/card/card/CalypsoCardSelectionExtension.hpp" +#include "keypop/calypso/card/cpp/SecureRegularModeTransactionManagerBase.hpp" +#include "keypop/calypso/card/transaction/FreeTransactionManager.hpp" +#include "keypop/calypso/card/transaction/InvalidPinException.hpp" +#include "keypop/calypso/card/transaction/SecureSymmetricCryptoTransactionManager.hpp" +#include "keypop/calypso/card/transaction/SymmetricCryptoSecuritySetting.hpp" +#include "keypop/calypso/crypto/legacysam/LegacySamApiFactory.hpp" +#include "keypop/calypso/crypto/legacysam/sam/LegacySam.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ChannelControl.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +#include "../common/ConfigurationUtil.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamUtil; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keyple::plugin::pcsc::PcscSupportedContactProtocol; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::WriteAccessLevel; +using keypop::calypso::card::card::CalypsoCard; +using keypop::calypso::card::card::CalypsoCardSelectionExtension; +using keypop::calypso::card::cpp::SecureRegularModeTransactionManagerBase; +using keypop::calypso::card::transaction::FreeTransactionManager; +using keypop::calypso::card::transaction::InvalidPinException; +using keypop::calypso::card::transaction:: + SecureSymmetricCryptoTransactionManager; +using keypop::calypso::card::transaction::SymmetricCryptoSecuritySetting; +using keypop::calypso::crypto::legacysam::LegacySamApiFactory; +using keypop::calypso::crypto::legacysam::sam::LegacySam; +using keypop::reader::CardReader; +using keypop::reader::ChannelControl; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::selection::spi::SmartCard; /** - *

Use Case Calypso 6 – Calypso Card Verify PIN (PC/SC)

- * - *

We demonstrate here the various operations around the PIN code checking. - * - *

Scenario:

- * - *
    - *
  • Checks if an ISO 14443-4 card is in the reader, enables the card selection manager. - *
  • Attempts to select a Calypso SAM (C1) in the contact reader. - *
  • Attempts to select the specified card (here a Calypso card characterized by its AID) with - * an AID-based application selection scenario. - *
  • Creates a CardTransactionManager without security. - *
  • Verify the PIN code in plain mode with the correct code, display the remaining attempts - * counter. - *
  • Creates a CardTransactionManager using CardSecuritySetting referencing the - * selected SAM. - *
  • Verify the PIN code in session in encrypted mode with the code, display the remaining - * attempts counter. - *
  • Verify the PIN code in session in encrypted mode with a bad code, display the remaining - * attempts counter. - *
  • Cancel the card transaction, re-open a new one. - *
  • Verify the PIN code in session in encrypted mode with the code, display the remaining - * attempts counter. - *
  • Close the card transaction. - *
- * - *

Any unexpected behavior will result in runtime exceptions. + * Manages the process of verifying the PIN code of a Calypso card using the + * PC/SC plugin, demonstrating both plain and encrypted PIN verification + * methods. */ -class Main_VerifyPin_Pcsc {}; -static const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_VerifyPin_Pcsc)); +class Main_VerifyPin_Pcsc { }; +static std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_VerifyPin_Pcsc)); + +/** AID: Keyple test kit profile 1, Application 2 */ +static const std::string AID = "315449432E49434131"; + +static const std::vector PIN_OK = {0x30, 0x30, 0x30, 0x30}; +static const std::vector PIN_KO = {0x30, 0x30, 0x30, 0x31}; +static const std::uint8_t PIN_VERIFICATION_CIPHERING_KEY_KIF = 0x30; +static const std::uint8_t PIN_VERIFICATION_CIPHERING_KEY_KVC = 0x79; + +/* The plugin used to manage the readers. */ +static std::shared_ptr plugin; +/* The reader used to communicate with the card. */ +static std::shared_ptr cardReader; +/* The reader used to communicate with the SAM. */ +static std::shared_ptr samReader; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* + * The Calypso factory used to create the selection extension and transaction + * managers. + */ +static std::shared_ptr calypsoCardApiFactory; +/* The security settings for the card transaction. */ +static std::shared_ptr + symmetricCryptoSecuritySetting; -int main() -{ - /* Get the instance of the SmartCardService */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); +/** + * Initializes the Keyple service. + */ +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); + plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} - /* Register the PcscPlugin, get the corresponding generic plugin in return */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); +/** + * Initializes the card reader with specific configurations. + */ +static void +initCardReader() { + cardReader = ConfigurationUtil::getReader( + plugin, + ConfigurationUtil::CARD_READER_NAME_REGEX, + true, + PcscReader::IsoProtocol::T1, + PcscReader::SharingMode::SHARED, + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ConfigurationUtil::ISO_CARD_PROTOCOL); +} - /* Get the Calypso card extension service */ - std::shared_ptr calypsoCardService = - CalypsoExtensionService::getInstance(); +/** + * Initializes the SAM reader with specific configurations. + */ +static void +initSamReader() { + samReader = ConfigurationUtil::getReader( + plugin, + ConfigurationUtil::SAM_READER_NAME_REGEX, + false, + PcscReader::IsoProtocol::ANY, + PcscReader::SharingMode::SHARED, + PcscSupportedContactProtocol::ISO_7816_3_T0.getName(), + ConfigurationUtil::SAM_PROTOCOL); +} - /* Verify that the extension's API level is consistent with the current service */ - smartCardService->checkCardExtension(calypsoCardService); +/** + * Initializes the Calypso card extension service. + */ +static void +initCalypsoCardExtensionService() { + std::shared_ptr calypsoExtensionService( + CalypsoExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + calypsoExtensionService); + calypsoCardApiFactory = calypsoExtensionService->getCalypsoCardApiFactory(); +} - /* Get the card and SAM readers whose name matches the provided regexs */ - std::shared_ptr cardReader = - ConfigurationUtil::getCardReader(plugin, ConfigurationUtil::CARD_READER_NAME_REGEX); - std::shared_ptr samReader = - ConfigurationUtil::getSamReader(plugin, ConfigurationUtil::SAM_READER_NAME_REGEX); +/** + * Selects the SAM C1 for the transaction. + */ +static std::shared_ptr +selectSam(std::shared_ptr reader) { + std::shared_ptr samSelectionManager( + readerApiFactory->createCardSelectionManager()); - logger->info("=============== " \ - "UseCase Calypso #5: Calypso card Verify PIN " \ - "================== \n"); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByPowerOnData( + LegacySamUtil::buildPowerOnDataFilter( + LegacySam::ProductType::SAM_C1, "")); - /* Check if a card is present in the reader */ - if (!cardReader->isCardPresent()) { - throw IllegalStateException("No card is present in the reader."); - } + std::shared_ptr legacySamApiFactory( + LegacySamExtensionService::getInstance()->getLegacySamApiFactory()); - /* Get the Calypso SAM SmartCard after selection. */ - std::shared_ptr calypsoSam = ConfigurationUtil::getSam(samReader); + samSelectionManager->prepareSelection( + cardSelector, legacySamApiFactory->createLegacySamSelectionExtension()); - logger->info("= SAM = %\n", calypsoSam); + const std::shared_ptr samSelectionResult( + samSelectionManager->processCardSelectionScenario(reader)); - logger->info("= #### Select application with AID = '%'\n", CalypsoConstants::AID); + if (samSelectionResult->getActiveSmartCard() == nullptr) { + throw IllegalStateException("The selection of the SAM failed."); + } - /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + return std::dynamic_pointer_cast( + samSelectionResult->getActiveSmartCard()); +} - /* - * Create a card selection using the Calypso card extension. - * Prepare the selection by adding the created Calypso card selection to the card selection - * scenario. - */ - std::shared_ptr cardSelection = calypsoCardService->createCardSelection(); - cardSelection->acceptInvalidatedCard() - .filterByDfName(CalypsoConstants::AID); - cardSelectionManager->prepareSelection(cardSelection); +/** + * Initializes the security settings for the transaction. + */ +static void +initSecuritySetting() { + std::shared_ptr sam(selectSam(samReader)); + + symmetricCryptoSecuritySetting + = calypsoCardApiFactory->createSymmetricCryptoSecuritySetting( + LegacySamExtensionService::getInstance() + ->getLegacySamApiFactory() + ->createSymmetricCryptoCardTransactionManagerFactory( + samReader, sam)); +} - /* Actual card communication: run the selection scenario */ - const std::shared_ptr selectionResult = - cardSelectionManager->processCardSelectionScenario(cardReader); +/** + * Selects the Calypso card for the transaction based on the specified + * Application Identifier (AID). + */ +static std::shared_ptr +selectCard(std::shared_ptr reader, const std::string& aid) { + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(aid); + + std::unique_ptr + calypsoCardSelectionExtension( + calypsoCardApiFactory->createCalypsoCardSelectionExtension()); + calypsoCardSelectionExtension->acceptInvalidatedCard(); + cardSelectionManager->prepareSelection( + cardSelector, std::move(calypsoCardSelectionExtension)); + + const std::shared_ptr selectionResult( + cardSelectionManager->processCardSelectionScenario(reader)); - /* Check the selection result */ if (selectionResult->getActiveSmartCard() == nullptr) { - throw IllegalStateException("The selection of the application '" + - CalypsoConstants::AID + - "' failed."); + throw IllegalStateException( + "The selection of the application '" + aid + "' failed."); } - /* Get the SmartCard resulting of the selection */ - const std::shared_ptr card = selectionResult->getActiveSmartCard(); - auto calypsoCard = std::dynamic_pointer_cast(card); + const std::shared_ptr card( + selectionResult->getActiveSmartCard()); + + return std::dynamic_pointer_cast(card); +} + +int +main() { + logger->info( + "= UseCase Calypso #6: Calypso card Verify PIN ==================\n"); + + /* Initialize the context */ + initKeypleService(); + initCalypsoCardExtensionService(); + initCardReader(); + initSamReader(); + initSecuritySetting(); + + /* Verify if a card is present in the reader */ + if (!cardReader->isCardPresent()) { + throw IllegalStateException("No card is present in the reader."); + } + + /* Select the card */ + std::shared_ptr calypsoCard = selectCard(cardReader, AID); logger->info("= SmartCard = %\n", calypsoCard); - const std::string csn = HexUtil::toHex(calypsoCard->getApplicationSerialNumber()); + const std::string csn( + HexUtil::toHex(calypsoCard->getApplicationSerialNumber())); logger->info("Calypso Serial Number = %\n", csn); - /* Create security settings that reference the SAM */ - std::shared_ptr cardSecuritySetting = - CalypsoExtensionService::getInstance()->createCardSecuritySetting(); - cardSecuritySetting->setControlSamResource(samReader, calypsoSam); - cardSecuritySetting->setPinVerificationCipheringKey( - CalypsoConstants::PIN_VERIFICATION_CIPHERING_KEY_KIF, - CalypsoConstants::PIN_VERIFICATION_CIPHERING_KEY_KVC); + /* Instantiate a Free Transaction manager to operate PIN verification + * without encryption */ + std::unique_ptr freeTransactionManager( + calypsoCardApiFactory->createFreeTransactionManager( + cardReader, calypsoCard)); + + /* Verify the PIN in plain mode without initiating a secure session */ + freeTransactionManager->prepareVerifyPin(PIN_OK).processCommands( + ChannelControl::KEEP_OPEN); + logger->info( + "Remaining attempts #1: %\n", calypsoCard->getPinAttemptRemaining()); - /* Create the card transaction manager in secure mode. */ - std::shared_ptr cardTransaction = - calypsoCardService->createCardTransactionWithoutSecurity(cardReader, calypsoCard); + /* Add the key identifiers needed for ciphering the PIN */ + symmetricCryptoSecuritySetting->setPinVerificationCipheringKey( + PIN_VERIFICATION_CIPHERING_KEY_KIF, PIN_VERIFICATION_CIPHERING_KEY_KVC); - /* Verification of the PIN (correct) out of a secure session in plain mode */ - cardTransaction->processVerifyPin(CalypsoConstants::PIN_OK); - logger->info("Remaining attempts #1: %\n", calypsoCard->getPinAttemptRemaining()); + /* + * Instantiate a Secure Regular Mode Transaction Manager to handle + * encrypted PIN verification and secure operations. + * + * The keypop API declares createSecureRegularModeTransactionManager() as + * returning a SecureRegularModeTransactionManagerBase, which does not + * itself expose prepareOpenSecureSession() (it's only declared on + * SecureSymmetricCryptoTransactionManager, a sibling interface + * implemented by the same concrete object). A downcast is required to + * reach it. + */ + std::unique_ptr + secureRegularModeTransactionManagerBase( + calypsoCardApiFactory->createSecureRegularModeTransactionManager( + cardReader, calypsoCard, symmetricCryptoSecuritySetting)); - /* Create a secured card transaction */ - cardTransaction = calypsoCardService->createCardTransaction(cardReader, - calypsoCard, - cardSecuritySetting); + auto secureRegularModeTransactionManager + = dynamic_cast*>( + secureRegularModeTransactionManagerBase.get()); - /* Verification of the PIN (correct) out of a secure session in encrypted mode */ - cardTransaction->processVerifyPin(CalypsoConstants::PIN_OK); + /* Verify the PIN in encrypted mode, outside a secure session */ + secureRegularModeTransactionManager->prepareVerifyPin(PIN_OK) + .processCommands(ChannelControl::KEEP_OPEN); /* Log the current counter value (should be 3) */ - logger->info("Remaining attempts #2: %\n", calypsoCard->getPinAttemptRemaining()); - - /* Verification of the PIN (incorrect) inside a secure session */ - cardTransaction->processOpening(WriteAccessLevel::DEBIT); + logger->info( + "Remaining attempts #2: %\n", calypsoCard->getPinAttemptRemaining()); + /* + * Attempt PIN verification with an incorrect PIN within a secure session, + * handle exceptions and cancel the session if necessary. + */ + secureRegularModeTransactionManager->prepareOpenSecureSession( + WriteAccessLevel::DEBIT); try { - /* Create a secured card transaction */ - cardTransaction->processVerifyPin(CalypsoConstants::PIN_KO); - } catch (const Exception& ex) { - logger->error("PIN Exception: %\n", ex.getMessage()); + secureRegularModeTransactionManager->prepareVerifyPin(PIN_KO) + .processCommands(ChannelControl::KEEP_OPEN); + } catch (const InvalidPinException& ex) { + logger->error("PIN Exception: %\n", ex.what()); + secureRegularModeTransactionManager->prepareCancelSecureSession() + .processCommands(ChannelControl::KEEP_OPEN); } /* Log the current counter value (should be 2) */ - logger->error("Remaining attempts #3: %\n", calypsoCard->getPinAttemptRemaining()); + logger->error( + "Remaining attempts #3: %\n", calypsoCard->getPinAttemptRemaining()); - /* Verification of the PIN (correct) inside a secure session with reading of the counter */ - cardTransaction->prepareCheckPinStatus(); - cardTransaction->processOpening(WriteAccessLevel::DEBIT); + /* Initiate a secure session, verify the PIN correctly, and then close the + * session */ + secureRegularModeTransactionManager + ->prepareOpenSecureSession(WriteAccessLevel::DEBIT) + .prepareCheckPinStatus() + .processCommands(ChannelControl::KEEP_OPEN); /* Log the current counter value (should be 2) */ - logger->info("Remaining attempts #4: %\n", calypsoCard->getPinAttemptRemaining()); + logger->info( + "Remaining attempts #4: %\n", calypsoCard->getPinAttemptRemaining()); - cardTransaction->processVerifyPin(CalypsoConstants::PIN_OK); - cardTransaction->prepareReleaseCardChannel(); - cardTransaction->processClosing(); + secureRegularModeTransactionManager->prepareVerifyPin(PIN_OK) + .prepareCloseSecureSession() + .processCommands(ChannelControl::CLOSE_AFTER); /* Log the current counter value (should be 3) */ - logger->info("Remaining attempts #5: %\n", calypsoCard->getPinAttemptRemaining()); + logger->info( + "Remaining attempts #5: %\n", calypsoCard->getPinAttemptRemaining()); - logger->info("The Secure Session ended successfully, the PIN has been verified\n"); + logger->info( + "The Secure Session ended successfully, the PIN has been " + "verified.\n"); logger->info("= #### End of the Calypso card processing\n"); diff --git a/Example_Card_Calypso/src/main/UseCase7_StoredValue_SimpleReloading/Main_StoredValue_SimpleReloading_Pcsc.cpp b/Example_Card_Calypso/src/main/UseCase7_StoredValue_SimpleReloading/Main_StoredValue_SimpleReloading_Pcsc.cpp index 5b58290..ce168fc 100644 --- a/Example_Card_Calypso/src/main/UseCase7_StoredValue_SimpleReloading/Main_StoredValue_SimpleReloading_Pcsc.cpp +++ b/Example_Card_Calypso/src/main/UseCase7_StoredValue_SimpleReloading/Main_StoredValue_SimpleReloading_Pcsc.cpp @@ -1,174 +1,317 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Core Util */ -#include "HexUtil.h" -#include "ContactCardCommonProtocol.h" -#include "ContactlessCardCommonProtocol.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" -#include "StringUtils.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPlugin.h" -#include "PcscPluginFactory.h" -#include "PcscPluginFactoryBuilder.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "ConfigurationUtil.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::calypso; -using namespace keyple::core::service; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::core::util::protocol; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamUtil.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactProtocol.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/card/CalypsoCard.hpp" +#include "keypop/calypso/card/card/CalypsoCardSelectionExtension.hpp" +#include "keypop/calypso/card/cpp/SecureRegularModeTransactionManagerBase.hpp" +#include "keypop/calypso/card/transaction/SecureSymmetricCryptoTransactionManager.hpp" +#include "keypop/calypso/card/transaction/SvAction.hpp" +#include "keypop/calypso/card/transaction/SvOperation.hpp" +#include "keypop/calypso/card/transaction/SymmetricCryptoSecuritySetting.hpp" +#include "keypop/calypso/crypto/legacysam/LegacySamApiFactory.hpp" +#include "keypop/calypso/crypto/legacysam/sam/LegacySam.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ChannelControl.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +#include "../common/ConfigurationUtil.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamUtil; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keyple::plugin::pcsc::PcscSupportedContactProtocol; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::card::CalypsoCard; +using keypop::calypso::card::card::CalypsoCardSelectionExtension; +using keypop::calypso::card::cpp::SecureRegularModeTransactionManagerBase; +using keypop::calypso::card::transaction:: + SecureSymmetricCryptoTransactionManager; +using keypop::calypso::card::transaction::SvAction; +using keypop::calypso::card::transaction::SvOperation; +using keypop::calypso::card::transaction::SymmetricCryptoSecuritySetting; +using keypop::calypso::crypto::legacysam::LegacySamApiFactory; +using keypop::calypso::crypto::legacysam::sam::LegacySam; +using keypop::reader::CardReader; +using keypop::reader::ChannelControl; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::selection::spi::SmartCard; /** - *

Use Case Calypso 7 – Calypso Card Stored Value reloading (PC/SC)

+ * Handles the process of reloading the Stored Value (SV) of a Calypso card + * using the PC/SC plugin and the Calypso Card Extension Service. * - *

We demonstrate here the reloading of the Stored Value counter of a Calypso card. - * - *

Scenario:

- * - *
    - *
  • Checks if an ISO 14443-4 card is in the reader, enables the card selection manager. - *
  • Attempts to select a Calypso SAM (C1) in the contact reader. - *
  • Attempts to select the specified card (here a Calypso card characterized by its AID) with - * an AID-based application selection scenario. - *
  • Creates a CardTransactionManager using CardSecuritySetting referencing the selected SAM. - *
  • Displays the Stored Value status, reloads the Store Value without opening a Secure Session. - *
- * - *

Any unexpected behavior will result in runtime exceptions. + *

This class demonstrates the SV reloading process outside a Secure + * Session. */ -class Main_StoredValue_SimpleReloading_Pcsc {}; -static const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_StoredValue_SimpleReloading_Pcsc)); +class Main_StoredValue_SimpleReloading_Pcsc { }; +static std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_StoredValue_SimpleReloading_Pcsc)); + +/** AID: Keyple test kit profile 1, Application 2 */ +static const std::string AID = "315449432E49434131"; + +/* The plugin used to manage the readers. */ +static std::shared_ptr plugin; +/* The reader used to communicate with the card. */ +static std::shared_ptr cardReader; +/* The reader used to communicate with the SAM. */ +static std::shared_ptr samReader; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* + * The Calypso factory used to create the selection extension and transaction + * managers. + */ +static std::shared_ptr calypsoCardApiFactory; +/* The security settings for the card transaction. */ +static std::shared_ptr + symmetricCryptoSecuritySetting; -int main() -{ - /* Get the instance of the SmartCardService */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); +/** + * Initializes the Keyple service. + */ +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); + plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} - /* Register the PcscPlugin, get the corresponding generic plugin in return */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); +/** + * Initializes the card reader with specific configurations. + */ +static void +initCardReader() { + cardReader = ConfigurationUtil::getReader( + plugin, + ConfigurationUtil::CARD_READER_NAME_REGEX, + true, + PcscReader::IsoProtocol::T1, + PcscReader::SharingMode::SHARED, + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ConfigurationUtil::ISO_CARD_PROTOCOL); +} - /* Get the Calypso card extension service */ - std::shared_ptr calypsoCardService = - CalypsoExtensionService::getInstance(); +/** + * Initializes the SAM reader with specific configurations. + */ +static void +initSamReader() { + samReader = ConfigurationUtil::getReader( + plugin, + ConfigurationUtil::SAM_READER_NAME_REGEX, + false, + PcscReader::IsoProtocol::ANY, + PcscReader::SharingMode::SHARED, + PcscSupportedContactProtocol::ISO_7816_3_T0.getName(), + ConfigurationUtil::SAM_PROTOCOL); +} - /* Verify that the extension's API level is consistent with the current service */ - smartCardService->checkCardExtension(calypsoCardService); +/** + * Initializes the Calypso card extension service. + */ +static void +initCalypsoCardExtensionService() { + std::shared_ptr calypsoExtensionService( + CalypsoExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + calypsoExtensionService); + calypsoCardApiFactory = calypsoExtensionService->getCalypsoCardApiFactory(); +} - /* Get the card and SAM readers whose name matches the provided regexs */ - std::shared_ptr cardReader = - ConfigurationUtil::getCardReader(plugin, ConfigurationUtil::CARD_READER_NAME_REGEX); - std::shared_ptr samReader = - ConfigurationUtil::getSamReader(plugin, ConfigurationUtil::SAM_READER_NAME_REGEX); +/** + * Selects the SAM C1 for the transaction. + */ +static std::shared_ptr +selectSam(std::shared_ptr reader) { + std::shared_ptr samSelectionManager( + readerApiFactory->createCardSelectionManager()); - logger->info("=============== UseCase Calypso #7: Stored Value reloading ==================\n"); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByPowerOnData( + LegacySamUtil::buildPowerOnDataFilter( + LegacySam::ProductType::SAM_C1, "")); - /* Check if a card is present in the reader */ - if (!cardReader->isCardPresent()) { - throw IllegalStateException("No card is present in the reader."); - } + std::shared_ptr legacySamApiFactory( + LegacySamExtensionService::getInstance()->getLegacySamApiFactory()); - /* Get the Calypso SAM SmartCard after selection. */ - std::shared_ptr calypsoSam = ConfigurationUtil::getSam(samReader); + samSelectionManager->prepareSelection( + cardSelector, legacySamApiFactory->createLegacySamSelectionExtension()); - logger->info("= SAM = %\n", calypsoSam); + const std::shared_ptr samSelectionResult( + samSelectionManager->processCardSelectionScenario(reader)); - logger->info("= #### Select application with AID = '%'\n", CalypsoConstants::AID); + if (samSelectionResult->getActiveSmartCard() == nullptr) { + throw IllegalStateException("The selection of the SAM failed."); + } - /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + return std::dynamic_pointer_cast( + samSelectionResult->getActiveSmartCard()); +} - /* - * Create a card selection using the Calypso card extension. - * Prepare the selection by adding the created Calypso card selection to the card selection - * scenario. - */ - std::shared_ptr cardSelection = calypsoCardService->createCardSelection(); - cardSelection->acceptInvalidatedCard() - .filterByDfName(CalypsoConstants::AID); - cardSelectionManager->prepareSelection(cardSelection); +/** + * Initializes the security settings for the transaction. + */ +static void +initSecuritySetting() { + std::shared_ptr sam(selectSam(samReader)); + + symmetricCryptoSecuritySetting + = calypsoCardApiFactory->createSymmetricCryptoSecuritySetting( + LegacySamExtensionService::getInstance() + ->getLegacySamApiFactory() + ->createSymmetricCryptoCardTransactionManagerFactory( + samReader, sam)); +} - /* Actual card communication: run the selection scenario */ - const std::shared_ptr selectionResult = - cardSelectionManager->processCardSelectionScenario(cardReader); +/** + * Selects the Calypso card for the transaction based on the specified + * Application Identifier (AID). + */ +static std::shared_ptr +selectCard(std::shared_ptr reader, const std::string& aid) { + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(aid); + + std::unique_ptr + calypsoCardSelectionExtension( + calypsoCardApiFactory->createCalypsoCardSelectionExtension()); + calypsoCardSelectionExtension->acceptInvalidatedCard(); + cardSelectionManager->prepareSelection( + cardSelector, std::move(calypsoCardSelectionExtension)); + + const std::shared_ptr selectionResult( + cardSelectionManager->processCardSelectionScenario(reader)); - /* Check the selection result */ if (selectionResult->getActiveSmartCard() == nullptr) { - throw IllegalStateException("The selection of the application '" + - CalypsoConstants::AID + - "' failed."); + throw IllegalStateException( + "The selection of the application '" + aid + "' failed."); } - /* Get the SmartCard resulting of the selection */ - const std::shared_ptr card = selectionResult->getActiveSmartCard(); - auto calypsoCard = std::dynamic_pointer_cast(card); + const std::shared_ptr card( + selectionResult->getActiveSmartCard()); + + return std::dynamic_pointer_cast(card); +} + +int +main() { + logger->info( + "= UseCase Calypso #7: Stored Value reloading ==================\n"); + + /* Initialize the context */ + initKeypleService(); + initCalypsoCardExtensionService(); + initCardReader(); + initSamReader(); + initSecuritySetting(); + + /* Check the card presence */ + if (!cardReader->isCardPresent()) { + throw IllegalStateException("No card is present in the reader."); + } + + /* Select the card */ + std::shared_ptr calypsoCard = selectCard(cardReader, AID); logger->info("= SmartCard = %\n", calypsoCard); - const std::string csn = HexUtil::toHex(calypsoCard->getApplicationSerialNumber()); + const std::string csn( + HexUtil::toHex(calypsoCard->getApplicationSerialNumber())); logger->info("Calypso Serial Number = %\n", csn); - /* Create security settings that reference the SAM */ - std::shared_ptr cardSecuritySetting = - CalypsoExtensionService::getInstance()->createCardSecuritySetting(); - cardSecuritySetting->setControlSamResource(samReader, calypsoSam); - /* - * Performs file reads using the card transaction manager in non-secure mode. - * Prepare the command to retrieve the SV status with the two debit and reload logs. + * Instantiate a transaction manager to operate the SV operations. + * + * The keypop API declares createSecureRegularModeTransactionManager() as + * returning a SecureRegularModeTransactionManagerBase, which does not + * itself expose prepareSvGet() (it's only declared on + * SecureSymmetricCryptoTransactionManager, a sibling interface + * implemented by the same concrete object). A downcast is required to + * reach it. */ - std::shared_ptr cardTransaction = - calypsoCardService->createCardTransaction(cardReader, calypsoCard, cardSecuritySetting); + std::unique_ptr + cardTransactionManagerBase( + calypsoCardApiFactory->createSecureRegularModeTransactionManager( + cardReader, calypsoCard, symmetricCryptoSecuritySetting)); + + auto cardTransaction = dynamic_cast*>( + cardTransactionManagerBase.get()); + cardTransaction->prepareSvGet(SvOperation::RELOAD, SvAction::DO) - .processCommands(); + .processCommands(ChannelControl::KEEP_OPEN); /* Display the current SV status */ logger->info("Current SV status (SV Get for RELOAD):\n"); logger->info(". Balance = %\n", calypsoCard->getSvBalance()); - logger->info(". Last Transaction Number = %\n", calypsoCard->getSvLastTNum()); - + logger->info( + ". Last Transaction Number = %\n", calypsoCard->getSvLastTNum()); logger->info(". Debit log record = %\n", calypsoCard->getSvLoadLogRecord()); - /* Reloading with 2 units */ - cardTransaction->prepareSvReload(2); - - /* Execute the command and close the communication after */ - cardTransaction->prepareReleaseCardChannel(); - cardTransaction->processCommands(); + /* + * Reloading with 2 units. + * Execute the command and close the communication channel after. + */ + cardTransaction->prepareSvReload(2).processCommands( + ChannelControl::CLOSE_AFTER); - logger->info("The Secure Session ended successfully, the stored value has been reloaded by 2 " \ - "units\n"); + logger->info( + "The Secure Session ended successfully, the stored value has been " + "reloaded by 2 units.\n"); logger->info("= #### End of the Calypso card processing\n"); diff --git a/Example_Card_Calypso/src/main/UseCase8_StoredValue_DebitInSession/Main_StoredValue_DebitInSession_Pcsc.cpp b/Example_Card_Calypso/src/main/UseCase8_StoredValue_DebitInSession/Main_StoredValue_DebitInSession_Pcsc.cpp index ca7d7bb..cc05483 100644 --- a/Example_Card_Calypso/src/main/UseCase8_StoredValue_DebitInSession/Main_StoredValue_DebitInSession_Pcsc.cpp +++ b/Example_Card_Calypso/src/main/UseCase8_StoredValue_DebitInSession/Main_StoredValue_DebitInSession_Pcsc.cpp @@ -1,172 +1,324 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Core Util */ -#include "HexUtil.h" -#include "ContactCardCommonProtocol.h" -#include "ContactlessCardCommonProtocol.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" -#include "StringUtils.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPlugin.h" -#include "PcscPluginFactory.h" -#include "PcscPluginFactoryBuilder.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "ConfigurationUtil.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::calypso; -using namespace keyple::core::service; -using namespace keyple::core::service::resource; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::core::util::protocol; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamUtil.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactProtocol.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/WriteAccessLevel.hpp" +#include "keypop/calypso/card/card/CalypsoCard.hpp" +#include "keypop/calypso/card/card/CalypsoCardSelectionExtension.hpp" +#include "keypop/calypso/card/cpp/SecureRegularModeTransactionManagerBase.hpp" +#include "keypop/calypso/card/transaction/SecureSymmetricCryptoTransactionManager.hpp" +#include "keypop/calypso/card/transaction/SvAction.hpp" +#include "keypop/calypso/card/transaction/SvOperation.hpp" +#include "keypop/calypso/card/transaction/SymmetricCryptoSecuritySetting.hpp" +#include "keypop/calypso/crypto/legacysam/LegacySamApiFactory.hpp" +#include "keypop/calypso/crypto/legacysam/sam/LegacySam.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ChannelControl.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +#include "../common/ConfigurationUtil.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamUtil; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keyple::plugin::pcsc::PcscSupportedContactProtocol; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::WriteAccessLevel; +using keypop::calypso::card::card::CalypsoCard; +using keypop::calypso::card::card::CalypsoCardSelectionExtension; +using keypop::calypso::card::cpp::SecureRegularModeTransactionManagerBase; +using keypop::calypso::card::transaction:: + SecureSymmetricCryptoTransactionManager; +using keypop::calypso::card::transaction::SvAction; +using keypop::calypso::card::transaction::SvOperation; +using keypop::calypso::card::transaction::SymmetricCryptoSecuritySetting; +using keypop::calypso::crypto::legacysam::LegacySamApiFactory; +using keypop::calypso::crypto::legacysam::sam::LegacySam; +using keypop::reader::CardReader; +using keypop::reader::ChannelControl; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::selection::spi::SmartCard; /** - *

Use Case Calypso 4 – Calypso Card authentication (PC/SC)

+ * Handles the process of debiting the Stored Value (SV) of a Calypso card + * using the PC/SC plugin and the Calypso Card Extension Service. * - *

We demonstrate here the debit of the Stored Value counter of a Calypso card. - * - *

Scenario:

- * - *
    - *
  • Checks if an ISO 14443-4 card is in the reader, enables the card selection manager. - *
  • Attempts to select a Calypso SAM (C1) in the contact reader. - *
  • Attempts to select the specified card (here a Calypso card characterized by its AID) with - * an AID-based application selection scenario. - *
  • Creates a {@link CardTransactionManager} using {@link CardSecuritySetting} referencing the - * SAM profile defined in the card resource service. - *
  • Displays the Stored Value status, debits the Store Value within a Secure Session. - *
- * - *

Any unexpected behavior will result in runtime exceptions. + *

This class demonstrates the SV debit process inside a Secure Session. */ -class Main_StoredValue_DebitInSession_Pcsc {}; -static const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_StoredValue_DebitInSession_Pcsc)); +class Main_StoredValue_DebitInSession_Pcsc { }; +static std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_StoredValue_DebitInSession_Pcsc)); + +/** AID: Keyple test kit profile 1, Application 2 */ +static const std::string AID = "315449432E49434131"; + +/* The plugin used to manage the readers. */ +static std::shared_ptr plugin; +/* The reader used to communicate with the card. */ +static std::shared_ptr cardReader; +/* The reader used to communicate with the SAM. */ +static std::shared_ptr samReader; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* + * The Calypso factory used to create the selection extension and transaction + * managers. + */ +static std::shared_ptr calypsoCardApiFactory; +/* The security settings for the card transaction. */ +static std::shared_ptr + symmetricCryptoSecuritySetting; -int main() -{ - /* Get the instance of the SmartCardService */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); +/** + * Initializes the Keyple service. + */ +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); + plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} - /* Register the PcscPlugin, get the corresponding generic plugin in return */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); +/** + * Initializes the card reader with specific configurations. + */ +static void +initCardReader() { + cardReader = ConfigurationUtil::getReader( + plugin, + ConfigurationUtil::CARD_READER_NAME_REGEX, + true, + PcscReader::IsoProtocol::T1, + PcscReader::SharingMode::SHARED, + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ConfigurationUtil::ISO_CARD_PROTOCOL); +} - /* Get the Calypso card extension service */ - std::shared_ptr calypsoCardService = - CalypsoExtensionService::getInstance(); +/** + * Initializes the SAM reader with specific configurations. + */ +static void +initSamReader() { + samReader = ConfigurationUtil::getReader( + plugin, + ConfigurationUtil::SAM_READER_NAME_REGEX, + false, + PcscReader::IsoProtocol::ANY, + PcscReader::SharingMode::SHARED, + PcscSupportedContactProtocol::ISO_7816_3_T0.getName(), + ConfigurationUtil::SAM_PROTOCOL); +} - /* Verify that the extension's API level is consistent with the current service */ - smartCardService->checkCardExtension(calypsoCardService); +/** + * Initializes the Calypso card extension service. + */ +static void +initCalypsoCardExtensionService() { + std::shared_ptr calypsoExtensionService( + CalypsoExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + calypsoExtensionService); + calypsoCardApiFactory = calypsoExtensionService->getCalypsoCardApiFactory(); +} - /* Get the card and SAM readers whose name matches the provided regexs */ - std::shared_ptr cardReader = - ConfigurationUtil::getCardReader(plugin, ConfigurationUtil::CARD_READER_NAME_REGEX); - std::shared_ptr samReader = - ConfigurationUtil::getSamReader(plugin, ConfigurationUtil::SAM_READER_NAME_REGEX); +/** + * Selects the SAM C1 for the transaction. + */ +static std::shared_ptr +selectSam(std::shared_ptr reader) { + std::shared_ptr samSelectionManager( + readerApiFactory->createCardSelectionManager()); - logger->info("=============== UseCase Calypso #8: Stored Value debit ==================\n"); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByPowerOnData( + LegacySamUtil::buildPowerOnDataFilter( + LegacySam::ProductType::SAM_C1, "")); - /* Check if a card is present in the reader */ - if (!cardReader->isCardPresent()) { - throw IllegalStateException("No card is present in the reader."); - } + std::shared_ptr legacySamApiFactory( + LegacySamExtensionService::getInstance()->getLegacySamApiFactory()); - /* Get the Calypso SAM SmartCard after selection. */ - std::shared_ptr calypsoSam = ConfigurationUtil::getSam(samReader); + samSelectionManager->prepareSelection( + cardSelector, legacySamApiFactory->createLegacySamSelectionExtension()); - logger->info("= SAM = %\n", calypsoSam); + const std::shared_ptr samSelectionResult( + samSelectionManager->processCardSelectionScenario(reader)); - logger->info("= #### Select application with AID = '%'\n", CalypsoConstants::AID); + if (samSelectionResult->getActiveSmartCard() == nullptr) { + throw IllegalStateException("The selection of the SAM failed."); + } - /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + return std::dynamic_pointer_cast( + samSelectionResult->getActiveSmartCard()); +} - /* - * Create a card selection using the Calypso card extension. - * Prepare the selection by adding the created Calypso card selection to the card selection - * scenario. - */ - std::shared_ptr cardSelection = calypsoCardService->createCardSelection(); - cardSelection->acceptInvalidatedCard() - .filterByDfName(CalypsoConstants::AID); - cardSelectionManager->prepareSelection(cardSelection); +/** + * Initializes the security settings for the transaction. + */ +static void +initSecuritySetting() { + std::shared_ptr sam(selectSam(samReader)); + + symmetricCryptoSecuritySetting + = calypsoCardApiFactory->createSymmetricCryptoSecuritySetting( + LegacySamExtensionService::getInstance() + ->getLegacySamApiFactory() + ->createSymmetricCryptoCardTransactionManagerFactory( + samReader, sam)); +} - /* Actual card communication: run the selection scenario */ - const std::shared_ptr selectionResult = - cardSelectionManager->processCardSelectionScenario(cardReader); +/** + * Selects the Calypso card for the transaction based on the specified + * Application Identifier (AID). + */ +static std::shared_ptr +selectCard(std::shared_ptr reader, const std::string& aid) { + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(aid); + + std::unique_ptr + calypsoCardSelectionExtension( + calypsoCardApiFactory->createCalypsoCardSelectionExtension()); + calypsoCardSelectionExtension->acceptInvalidatedCard(); + cardSelectionManager->prepareSelection( + cardSelector, std::move(calypsoCardSelectionExtension)); + + const std::shared_ptr selectionResult( + cardSelectionManager->processCardSelectionScenario(reader)); - /* Check the selection result */ if (selectionResult->getActiveSmartCard() == nullptr) { - throw IllegalStateException("The selection of the application '" + - CalypsoConstants::AID + - "' failed."); + throw IllegalStateException( + "The selection of the application '" + aid + "' failed."); } - /* Get the SmartCard resulting of the selection */ - const std::shared_ptr card = selectionResult->getActiveSmartCard(); - auto calypsoCard = std::dynamic_pointer_cast(card); + const std::shared_ptr card( + selectionResult->getActiveSmartCard()); + + return std::dynamic_pointer_cast(card); +} + +int +main() { + logger->info( + "= UseCase Calypso #8: Stored Value debit ==================\n"); + + /* Initialize the context */ + initKeypleService(); + initCalypsoCardExtensionService(); + initCardReader(); + initSamReader(); + initSecuritySetting(); + + /* Check the card presence */ + if (!cardReader->isCardPresent()) { + throw IllegalStateException("No card is present in the reader."); + } + + /* Select the card */ + std::shared_ptr calypsoCard = selectCard(cardReader, AID); logger->info("= SmartCard = %\n", calypsoCard); - const std::string csn = HexUtil::toHex(calypsoCard->getApplicationSerialNumber()); + const std::string csn( + HexUtil::toHex(calypsoCard->getApplicationSerialNumber())); logger->info("Calypso Serial Number = %\n", csn); - /* Create security settings that reference the SAM */ - std::shared_ptr cardSecuritySetting = - CalypsoExtensionService::getInstance()->createCardSecuritySetting(); - cardSecuritySetting->setControlSamResource(samReader, calypsoSam); - cardSecuritySetting->enableSvLoadAndDebitLog(); + /* Request the two debit and reload logs */ + symmetricCryptoSecuritySetting->enableSvLoadAndDebitLog(); + + /* + * Instantiate a transaction manager to operate the SV operations. + * + * The keypop API declares createSecureRegularModeTransactionManager() as + * returning a SecureRegularModeTransactionManagerBase, which does not + * itself expose prepareOpenSecureSession()/prepareSvGet() (they're only + * declared on SecureSymmetricCryptoTransactionManager, a sibling + * interface implemented by the same concrete object). A downcast is + * required to reach them. + */ + std::unique_ptr + cardTransactionManagerBase( + calypsoCardApiFactory->createSecureRegularModeTransactionManager( + cardReader, calypsoCard, symmetricCryptoSecuritySetting)); + + auto cardTransaction = dynamic_cast*>( + cardTransactionManagerBase.get()); - /* Performs file reads using the card transaction manager in non-secure mode. */ - std::shared_ptr cardTransaction = - calypsoCardService->createCardTransaction(cardReader, calypsoCard, cardSecuritySetting); + cardTransaction->prepareOpenSecureSession(WriteAccessLevel::DEBIT); cardTransaction->prepareSvGet(SvOperation::DEBIT, SvAction::DO) - .processOpening(WriteAccessLevel::DEBIT); + .processCommands(ChannelControl::KEEP_OPEN); /* Display the current SV status */ logger->info("Current SV status (SV Get for DEBIT):\n"); logger->info(". Balance = %\n", calypsoCard->getSvBalance()); - logger->info(". Last Transaction Number = %\n", calypsoCard->getSvLastTNum()); + logger->info( + ". Last Transaction Number = %\n", calypsoCard->getSvLastTNum()); - /* Display the load and debit records. */ + /* Display the load and debit records */ logger->info(". Load log record = %\n", calypsoCard->getSvLoadLogRecord()); - logger->info(". Debit log record = %\n", calypsoCard->getSvDebitLogLastRecord()); + logger->info( + ". Debit log record = %\n", calypsoCard->getSvDebitLogLastRecord()); /* Prepare an SV Debit of 2 units */ - cardTransaction->prepareSvDebit(2).prepareReleaseCardChannel().processClosing(); + cardTransaction->prepareSvDebit(2) + .prepareCloseSecureSession() + .processCommands(ChannelControl::CLOSE_AFTER); - logger->info("The Secure Session ended successfully, the stored value has been debited by 2 " \ - "units\n"); + logger->info( + "The Secure Session ended successfully, the stored value has been " + "debited by 2 units.\n"); logger->info("= #### End of the Calypso card processing\n"); diff --git a/Example_Card_Calypso/src/main/UseCase9_ChangePin/Main_ChangePin_Pcsc.cpp b/Example_Card_Calypso/src/main/UseCase9_ChangePin/Main_ChangePin_Pcsc.cpp index 2caa261..1790adf 100644 --- a/Example_Card_Calypso/src/main/UseCase9_ChangePin/Main_ChangePin_Pcsc.cpp +++ b/Example_Card_Calypso/src/main/UseCase9_ChangePin/Main_ChangePin_Pcsc.cpp @@ -1,194 +1,331 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" - -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" - -/* Keyple Core Util */ -#include "HexUtil.h" -#include "ContactCardCommonProtocol.h" -#include "ContactlessCardCommonProtocol.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" -#include "StringUtils.h" -#include "Thread.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPlugin.h" -#include "PcscPluginFactory.h" -#include "PcscPluginFactoryBuilder.h" - -/* Keyple Cpp Example */ -#include "CalypsoConstants.h" -#include "ConfigurationUtil.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::calypso; -using namespace keyple::core::service; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::core::util::protocol; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "keyple/card/calypso/CalypsoExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamExtensionService.hpp" +#include "keyple/card/calypso/crypto/legacysam/LegacySamUtil.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/Thread.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactProtocol.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/calypso/card/CalypsoCardApiFactory.hpp" +#include "keypop/calypso/card/card/CalypsoCard.hpp" +#include "keypop/calypso/card/card/CalypsoCardSelectionExtension.hpp" +#include "keypop/calypso/card/cpp/SecureRegularModeTransactionManagerBase.hpp" +#include "keypop/calypso/card/transaction/SymmetricCryptoSecuritySetting.hpp" +#include "keypop/calypso/crypto/legacysam/LegacySamApiFactory.hpp" +#include "keypop/calypso/crypto/legacysam/sam/LegacySam.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ChannelControl.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +#include "../common/ConfigurationUtil.hpp" + +using keyple::card::calypso::CalypsoExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamExtensionService; +using keyple::card::calypso::crypto::legacysam::LegacySamUtil; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::Thread; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keyple::plugin::pcsc::PcscSupportedContactProtocol; +using keypop::calypso::card::CalypsoCardApiFactory; +using keypop::calypso::card::card::CalypsoCard; +using keypop::calypso::card::card::CalypsoCardSelectionExtension; +using keypop::calypso::card::cpp::SecureRegularModeTransactionManagerBase; +using keypop::calypso::card::transaction::SymmetricCryptoSecuritySetting; +using keypop::calypso::crypto::legacysam::LegacySamApiFactory; +using keypop::calypso::crypto::legacysam::sam::LegacySam; +using keypop::reader::CardReader; +using keypop::reader::ChannelControl; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::selection::spi::SmartCard; /** - *

Use Case Calypso 9 – Calypso Card Change PIN (PC/SC)

+ * Manages the process of changing the PIN code of a Calypso card using the + * PC/SC plugin, demonstrating both plain and encrypted PIN verification + * methods. * - *

We demonstrate here the various operations around the PIN code checking. - * - *

Scenario:

- * - *
    - *
  • Checks if an ISO 14443-4 card is in the reader, enables the card selection manager. - *
  • Attempts to select a Calypso SAM (C1) in the contact reader. - *
  • Attempts to select the specified card (here a Calypso card characterized by its AID) with - * an AID-based application selection scenario. - *
  • Creates a CardTransactionManager using CardSecuritySetting referencing the selected SAM. - *
  • Ask for the new PIN code. - *
  • Change the PIN code. - *
  • Verify the PIN code. - *
  • Close the card transaction. - *
- * - *

Any unexpected behavior will result in runtime exceptions. + * Warning: On recent Windows versions, delayed PIN entry can + * cause loss of communication with the smart card (the card is reset after 5 + * seconds of inactivity). */ -class Main_ChangePin_Pcsc {}; -static const std::unique_ptr logger = LoggerFactory::getLogger(typeid(Main_ChangePin_Pcsc)); +class Main_ChangePin_Pcsc { }; +static std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_ChangePin_Pcsc)); + +/** AID: Keyple test kit profile 1, Application 2 */ +static const std::string AID = "315449432E49434131"; + +static const std::uint8_t PIN_MODIFICATION_CIPHERING_KEY_KIF = 0x21; +static const std::uint8_t PIN_MODIFICATION_CIPHERING_KEY_KVC = 0x79; +static const std::uint8_t PIN_VERIFICATION_CIPHERING_KEY_KIF = 0x30; +static const std::uint8_t PIN_VERIFICATION_CIPHERING_KEY_KVC = 0x79; + +/* The plugin used to manage the readers. */ +static std::shared_ptr plugin; +/* The reader used to communicate with the card. */ +static std::shared_ptr cardReader; +/* The reader used to communicate with the SAM. */ +static std::shared_ptr samReader; +/* The factory used to create the selection manager and card selectors. */ +static std::shared_ptr readerApiFactory; +/* + * The Calypso factory used to create the selection extension and transaction + * managers. + */ +static std::shared_ptr calypsoCardApiFactory; +/* The security settings for the card transaction. */ +static std::shared_ptr + symmetricCryptoSecuritySetting; -int main() -{ - /* Get the instance of the SmartCardService */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); +/** + * Initializes the Keyple service. + */ +static void +initKeypleService() { + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); + plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} - /* Register the PcscPlugin, get the corresponding generic plugin in return */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); +/** + * Initializes the card reader with specific configurations. + */ +static void +initCardReader() { + cardReader = ConfigurationUtil::getReader( + plugin, + ConfigurationUtil::CARD_READER_NAME_REGEX, + true, + PcscReader::IsoProtocol::T1, + PcscReader::SharingMode::SHARED, + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ConfigurationUtil::ISO_CARD_PROTOCOL); +} - /* Get the Calypso card extension service */ - std::shared_ptr calypsoCardService = CalypsoExtensionService::getInstance(); +/** + * Initializes the SAM reader with specific configurations. + */ +static void +initSamReader() { + samReader = ConfigurationUtil::getReader( + plugin, + ConfigurationUtil::SAM_READER_NAME_REGEX, + false, + PcscReader::IsoProtocol::ANY, + PcscReader::SharingMode::SHARED, + PcscSupportedContactProtocol::ISO_7816_3_T0.getName(), + ConfigurationUtil::SAM_PROTOCOL); +} - /* Verify that the extension's API level is consistent with the current service */ - smartCardService->checkCardExtension(calypsoCardService); +/** + * Initializes the Calypso card extension service. + */ +static void +initCalypsoCardExtensionService() { + std::shared_ptr calypsoExtensionService( + CalypsoExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + calypsoExtensionService); + calypsoCardApiFactory = calypsoExtensionService->getCalypsoCardApiFactory(); +} - /* Get the card and SAM readers whose name matches the provided regexs */ - std::shared_ptr cardReader = - ConfigurationUtil::getCardReader(plugin, ConfigurationUtil::CARD_READER_NAME_REGEX); - std::shared_ptr samReader = - ConfigurationUtil::getSamReader(plugin, ConfigurationUtil::SAM_READER_NAME_REGEX); +/** + * Selects the SAM C1 for the transaction. + */ +static std::shared_ptr +selectSam(std::shared_ptr reader) { + std::shared_ptr samSelectionManager( + readerApiFactory->createCardSelectionManager()); - logger->info("=============== " - "UseCase Calypso #5: Calypso card Verify PIN " - "==================\n"); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByPowerOnData( + LegacySamUtil::buildPowerOnDataFilter( + LegacySam::ProductType::SAM_C1, "")); - /* Check if a card is present in the reader */ - if (!cardReader->isCardPresent()) { - throw IllegalStateException("No card is present in the reader."); - } + std::shared_ptr legacySamApiFactory( + LegacySamExtensionService::getInstance()->getLegacySamApiFactory()); - /* Get the Calypso SAM SmartCard after selection. */ - std::shared_ptr calypsoSam = ConfigurationUtil::getSam(samReader); + samSelectionManager->prepareSelection( + cardSelector, legacySamApiFactory->createLegacySamSelectionExtension()); - logger->info("= SAM = %\n", calypsoSam); + const std::shared_ptr samSelectionResult( + samSelectionManager->processCardSelectionScenario(reader)); - logger->info("= #### Select application with AID = '%'\n", CalypsoConstants::AID); + if (samSelectionResult->getActiveSmartCard() == nullptr) { + throw IllegalStateException("The selection of the SAM failed."); + } - /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + return std::dynamic_pointer_cast( + samSelectionResult->getActiveSmartCard()); +} - /* - * Create a card selection using the Calypso card extension. - * Prepare the selection by adding the created Calypso card selection to the card selection - * scenario. - */ - std::shared_ptr cardSelection = calypsoCardService->createCardSelection(); - cardSelection->acceptInvalidatedCard() - .filterByDfName(CalypsoConstants::AID); - cardSelectionManager->prepareSelection(cardSelection); +/** + * Initializes the security settings for the transaction. + */ +static void +initSecuritySetting() { + std::shared_ptr sam(selectSam(samReader)); + + symmetricCryptoSecuritySetting + = calypsoCardApiFactory->createSymmetricCryptoSecuritySetting( + LegacySamExtensionService::getInstance() + ->getLegacySamApiFactory() + ->createSymmetricCryptoCardTransactionManagerFactory( + samReader, sam)); +} - /* Actual card communication: run the selection scenario */ - const std::shared_ptr selectionResult = - cardSelectionManager->processCardSelectionScenario(cardReader); +/** + * Selects the Calypso card for the transaction based on the specified + * Application Identifier (AID). + */ +static std::shared_ptr +selectCard(std::shared_ptr reader, const std::string& aid) { + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(aid); + + std::unique_ptr + calypsoCardSelectionExtension( + calypsoCardApiFactory->createCalypsoCardSelectionExtension()); + calypsoCardSelectionExtension->acceptInvalidatedCard(); + cardSelectionManager->prepareSelection( + cardSelector, std::move(calypsoCardSelectionExtension)); + + const std::shared_ptr selectionResult( + cardSelectionManager->processCardSelectionScenario(reader)); - /* Check the selection result */ if (selectionResult->getActiveSmartCard() == nullptr) { - throw IllegalStateException("The selection of the application '" + - CalypsoConstants::AID + - "' failed."); + throw IllegalStateException( + "The selection of the application '" + aid + "' failed."); } - /* Get the SmartCard resulting of the selection */ - const std::shared_ptr card = selectionResult->getActiveSmartCard(); - auto calypsoCard = std::dynamic_pointer_cast(card); + const std::shared_ptr card( + selectionResult->getActiveSmartCard()); + + return std::dynamic_pointer_cast(card); +} + +int +main() { + logger->info( + "= UseCase Calypso #9: Calypso card Change PIN ==================\n"); + + /* Initialize the context */ + initKeypleService(); + initCalypsoCardExtensionService(); + initCardReader(); + initSamReader(); + initSecuritySetting(); + + /* Verify if a card is present in the reader */ + if (!cardReader->isCardPresent()) { + throw IllegalStateException("No card is present in the reader."); + } + + /* Select the card */ + std::shared_ptr calypsoCard = selectCard(cardReader, AID); logger->info("= SmartCard = %\n", calypsoCard); - const std::string csn = HexUtil::toHex(calypsoCard->getApplicationSerialNumber()); + const std::string csn( + HexUtil::toHex(calypsoCard->getApplicationSerialNumber())); logger->info("Calypso Serial Number = %\n", csn); - /* Create security settings that reference the SAM */ - std::shared_ptr cardSecuritySetting = - CalypsoExtensionService::getInstance()->createCardSecuritySetting(); - cardSecuritySetting->setControlSamResource(samReader, calypsoSam); - cardSecuritySetting->setPinVerificationCipheringKey( - CalypsoConstants::PIN_VERIFICATION_CIPHERING_KEY_KIF, - CalypsoConstants::PIN_VERIFICATION_CIPHERING_KEY_KVC); - cardSecuritySetting->setPinModificationCipheringKey( - CalypsoConstants::PIN_MODIFICATION_CIPHERING_KEY_KIF, - CalypsoConstants::PIN_MODIFICATION_CIPHERING_KEY_KVC); - - /* Create the card transaction manager in secure mode. */ - std::shared_ptr cardTransaction = - calypsoCardService->createCardTransaction(cardReader, calypsoCard, cardSecuritySetting); + /* Add the key identifiers needed for ciphering the PIN */ + symmetricCryptoSecuritySetting + ->setPinVerificationCipheringKey( + PIN_VERIFICATION_CIPHERING_KEY_KIF, + PIN_VERIFICATION_CIPHERING_KEY_KVC) + .setPinModificationCipheringKey( + PIN_MODIFICATION_CIPHERING_KEY_KIF, + PIN_MODIFICATION_CIPHERING_KEY_KVC); + + /* + * Instantiate a Secure Regular Mode Transaction Manager to handle + * encrypted PIN verification and secure operations. + */ + std::unique_ptr cardTransaction( + calypsoCardApiFactory->createSecureRegularModeTransactionManager( + cardReader, calypsoCard, symmetricCryptoSecuritySetting)); /* Short delay to allow logs to be displayed before the prompt */ Thread::sleep(2000); std::string inputString; - std::vector newPinCode(4); + std::vector newPinCode; bool validPinCodeEntered = false; - do { - std::cout << "Enter new PIN code (4 numeric digits): "; - std::cin >> inputString; - - if (!StringUtils::matches(inputString, "[0-9]{4}")) { + std::cout << "Enter new PIN code (4 numeric digits):"; + std::getline(std::cin, inputString); + if (!std::regex_match(inputString, std::regex("[0-9]{4}"))) { std::cout << "Invalid PIN code." << std::endl; } else { - newPinCode = std::vector(inputString.c_str(), inputString.c_str() + 4); + newPinCode.assign(inputString.begin(), inputString.end()); validPinCodeEntered = true; } - } while (!validPinCodeEntered); /* Change the PIN (correct) */ - cardTransaction->processChangePin(newPinCode); + cardTransaction->prepareChangePin(newPinCode) + .processCommands(ChannelControl::KEEP_OPEN); logger->info("PIN code value successfully updated to %\n", inputString); /* Verification of the PIN */ - cardTransaction->processVerifyPin(newPinCode); - logger->info("Remaining attempts: %\n", calypsoCard->getPinAttemptRemaining()); + cardTransaction->prepareVerifyPin(newPinCode) + .processCommands(ChannelControl::CLOSE_AFTER); + logger->info( + "Remaining attempts: %\n", calypsoCard->getPinAttemptRemaining()); logger->info("PIN % code successfully presented.\n", inputString); - cardTransaction->prepareReleaseCardChannel(); - logger->info("= #### End of the Calypso card processing\n"); return 0; diff --git a/Example_Card_Calypso/src/main/common/ConfigurationUtil.cpp b/Example_Card_Calypso/src/main/common/ConfigurationUtil.cpp index 8598165..38194e8 100644 --- a/Example_Card_Calypso/src/main/common/ConfigurationUtil.cpp +++ b/Example_Card_Calypso/src/main/common/ConfigurationUtil.cpp @@ -1,219 +1,54 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ -#include "ConfigurationUtil.h" +#include "ConfigurationUtil.hpp" -#include -#include +#include +#include -/* Keyple Card Calypso */ -#include "CalypsoExtensionService.h" +#include "keypop/reader/ConfigurableCardReader.hpp" -/* Keyple Core Common */ -#include "KeypleReaderExtension.h" +using keypop::reader::ConfigurableCardReader; -/* Keyple Core Service */ -#include "ConfigurableReader.h" - -/* Keyple Core Util */ -#include "Exception.h" -#include "IllegalStateException.h" - -/* Keyple Plugin Pcsc */ -#include "PcscReader.h" -#include "PcscSupportedContactProtocol.h" -#include "PcscSupportedContactlessProtocol.h" - -/* Keyple Service Resource */ -#include "CardResourceServiceProvider.h" -#include "CardResourceProfileConfigurator.h" - -using namespace keyple::card::calypso; -using namespace keyple::core::common; -using namespace keyple::core::service::resource; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::plugin::pcsc; - -/* READER CONFIGURATOR -------------------------------------------------------------------------- */ - -ConfigurationUtil::ReaderConfigurator::ReaderConfigurator() {} - -void ConfigurationUtil::ReaderConfigurator::setupReader(std::shared_ptr cardReader) -{ - /* Configure the reader with parameters suitable for contactless operations */ - try { - std::shared_ptr readerExtension = - SmartCardServiceProvider::getService() - ->getPlugin(cardReader) - ->getReaderExtension(typeid(KeypleReaderExtension), cardReader->getName()); - auto pcscReader = std::dynamic_pointer_cast(readerExtension); - if (pcscReader) { - pcscReader->setContactless(false) - .setIsoProtocol(PcscReader::IsoProtocol::ANY) - .setSharingMode(PcscReader::SharingMode::SHARED); - } - - } catch (const Exception& e) { - mLogger->error("Exception raised while setting up the reader %\n", - cardReader->getName(), - e); - } -} - -/* CONFIGURATION UTIL --------------------------------------------------------------------------- */ - -const std::string ConfigurationUtil::CARD_READER_NAME_REGEX = - ".*ASK LoGO.*|.*Contactless.*|.*ACR122U.*|.*00 01.*|.*5x21-CL 0.*"; -const std::string ConfigurationUtil::SAM_READER_NAME_REGEX = - ".*Identive.*|.*HID.*|.*SAM.*|.*00 00.*|.*5x21 0.*"; -const std::string ConfigurationUtil::SAM_PROTOCOL = "ISO_7816_3_T0"; const std::string ConfigurationUtil::ISO_CARD_PROTOCOL = "ISO_14443_4_CARD"; -const std::string ConfigurationUtil::INNOVATRON_CARD_PROTOCOL = "INNOVATRON_B_PRIME_CARD"; - -const std::unique_ptr ConfigurationUtil::mLogger = - LoggerFactory::getLogger(typeid(ConfigurationUtil)); - -ConfigurationUtil::ConfigurationUtil() {} - -const std::string ConfigurationUtil::getReaderName(std::shared_ptr plugin, - const std::string& readerNameRegex) -{ - std::string name = ""; - const std::regex nameRegex(readerNameRegex); - - for (const auto& readerName : plugin->getReaderNames()) { - if (std::regex_match(readerName, nameRegex)) { - mLogger->info("Card reader, plugin; %, name: %\n", plugin->getName(), readerName); - name = readerName; - return name; - } - } - - std::stringstream ss; - ss << "Reader '" << readerNameRegex << "' not found in plugin '" << plugin->getName() << "'"; - throw IllegalStateException(ss.str()); -} - -std::shared_ptr ConfigurationUtil::getCardReader(std::shared_ptr plugin, - const std::string& readerNameRegex) -{ - /* Get the contactless reader whose name matches the provided regex */ - const std::string pcscContactlessReaderName = getReaderName(plugin, readerNameRegex); - std::shared_ptr cardReader = plugin->getReader(pcscContactlessReaderName); - - /* Configure the reader with parameters suitable for contactless operations. */ - std::shared_ptr reader = - std::dynamic_pointer_cast( - plugin->getReaderExtension(typeid(PcscReader), pcscContactlessReaderName)); - reader->setContactless(true) - .setIsoProtocol(PcscReader::IsoProtocol::T1) - .setSharingMode(PcscReader::SharingMode::SHARED); - - std::dynamic_pointer_cast(cardReader) - ->activateProtocol(PcscSupportedContactlessProtocol::ISO_14443_4.getName(), - ISO_CARD_PROTOCOL); - - return cardReader; -} - -std::shared_ptr ConfigurationUtil::getSamReader(std::shared_ptr plugin, - const std::string& readerNameRegex) -{ - /* Get the contact reader dedicated for Calypso SAM whose name matches the provided regex */ - const std::string pcscContactReaderName = getReaderName(plugin, readerNameRegex); - std::shared_ptr samReader = plugin->getReader(pcscContactReaderName); - - /* Configure the Calypso SAM reader with parameters suitable for contactless operations. */ - std::shared_ptr reader = - std::dynamic_pointer_cast( - plugin->getReaderExtension(typeid(PcscReader), pcscContactReaderName)); - reader->setContactless(false) - .setIsoProtocol(PcscReader::IsoProtocol::ANY) - .setSharingMode(PcscReader::SharingMode::SHARED); - - std::dynamic_pointer_cast(samReader) - ->activateProtocol(PcscSupportedContactProtocol::ISO_7816_3_T0.getName(), SAM_PROTOCOL); - - return samReader; -} - -std::shared_ptr ConfigurationUtil::getSam(std::shared_ptr samReader) -{ - /* Create a SAM selection manager. */ - std::shared_ptr samSelectionManager = - SmartCardServiceProvider::getService()->createCardSelectionManager(); - - /* Create a SAM selection using the Calypso card extension. */ - samSelectionManager->prepareSelection( - CalypsoExtensionService::getInstance()->createSamSelection()); - - /* SAM communication: run the selection scenario. */ - std::shared_ptr samSelectionResult = - samSelectionManager->processCardSelectionScenario(samReader); - - /* Check the selection result. */ - if (samSelectionResult->getActiveSmartCard() == nullptr) { - throw IllegalStateException("The selection of the SAM failed."); - } +const std::string ConfigurationUtil::INNOVATRON_CARD_PROTOCOL + = "INNOVATRON_B_PRIME_CARD"; +const std::string ConfigurationUtil::SAM_PROTOCOL = "ISO_7816_3_T0"; - /* Get the Calypso SAM SmartCard resulting of the selection. */ - return std::dynamic_pointer_cast(samSelectionResult->getActiveSmartCard()); +const std::string ConfigurationUtil::CARD_READER_NAME_REGEX + = ".*ASK LoGO.*|.*Contactless.*|.*ACR122U.*|.*00 01.*|.*5x21-CL 0.*"; +const std::string ConfigurationUtil::SAM_READER_NAME_REGEX + = ".*Identive.*|.*HID.*|.*00 00.*|.*5x21 0.*"; + +std::shared_ptr +ConfigurationUtil::getReader( + std::shared_ptr plugin, + const std::string& readerNameRegex, + bool isContactless, + const PcscReader::IsoProtocol& isoProtocol, + const PcscReader::SharingMode sharingMode, + const std::string& physicalProtocolName, + const std::string& logicalProtocolName) { + std::shared_ptr reader(plugin->findReader(readerNameRegex)); + + std::dynamic_pointer_cast( + plugin->getReaderExtension(typeid(PcscReader), reader->getName())) + ->setContactless(isContactless) + .setIsoProtocol(isoProtocol) + .setSharingMode(sharingMode); + + std::dynamic_pointer_cast(reader)->activateProtocol( + physicalProtocolName, logicalProtocolName); + + return reader; } - -void ConfigurationUtil::setupCardResourceService(std::shared_ptr plugin, - const std::string& readerNameRegex, - const std::string& samProfileName) -{ - /* Create a card resource extension expecting a SAM "C1" */ - std::shared_ptr samSelection = - CalypsoExtensionService::getInstance()->createSamSelection(); - samSelection->filterByProductType(CalypsoSam::ProductType::SAM_C1); - - std::shared_ptr samCardResourceExtension = - CalypsoExtensionService::getInstance()->createSamResourceProfileExtension(samSelection); - - /* Get the service */ - std::shared_ptr cardResourceService = - CardResourceServiceProvider::getService(); - - /* Create a minimalist configuration (no plugin/reader observation) */ - cardResourceService - ->getConfigurator() - ->withPlugins( - PluginsConfigurator::builder() - ->addPlugin(plugin, std::shared_ptr(new ReaderConfigurator())) - .build()) - .withCardResourceProfiles( - {CardResourceProfileConfigurator::builder(samProfileName, samCardResourceExtension) - ->withReaderNameRegex(readerNameRegex) - .build()}) - .configure(); - cardResourceService->start(); - - /* Verify the resource availability */ - std::shared_ptr cardResource = - cardResourceService->getCardResource(samProfileName); - - if (cardResource == nullptr) { - std::stringstream ss; - ss << "Unable to retrieve a SAM card resource for profile '" - << samProfileName - << "' from reader '" - << readerNameRegex - << "' in plugin '" - << plugin->getName() << "'"; - throw IllegalStateException(ss.str()); - } - - /* Release the resource */ - cardResourceService->releaseCardResource(cardResource); -} \ No newline at end of file diff --git a/Example_Card_Calypso/src/main/common/ConfigurationUtil.h b/Example_Card_Calypso/src/main/common/ConfigurationUtil.h deleted file mode 100644 index 8805b32..0000000 --- a/Example_Card_Calypso/src/main/common/ConfigurationUtil.h +++ /dev/null @@ -1,140 +0,0 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -#pragma once - -/* Calypsonet Terminal Calypso */ -#include "CalypsoSam.h" - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" - -/* Keyple Core Service */ -#include "Plugin.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Core Util */ -#include "LoggerFactory.h" - -/* Keyple Service Resource */ -#include "ReaderConfiguratorSpi.h" - -using namespace calypsonet::terminal::calypso::sam; -using namespace calypsonet::terminal::reader; -using namespace keyple::core::service; -using namespace keyple::core::service::resource::spi; -using namespace keyple::core::util::cpp; - -/** - * Utility class providing methods for configuring readers and the card resource service used across - * several examples. - */ -class ConfigurationUtil { -public: - /** - * Common reader identifiers - * These two regular expressions can be modified to fit the names of the readers used to run - * these examples. - */ - static const std::string CARD_READER_NAME_REGEX; - static const std::string SAM_READER_NAME_REGEX; - static const std::string SAM_PROTOCOL; - static const std::string ISO_CARD_PROTOCOL; - static const std::string INNOVATRON_CARD_PROTOCOL; - - static const std::string getReaderName(std::shared_ptr plugin, - const std::string& readerNameRegex); - - /** - * Retrieves the contactless card reader the first available reader in the provided plugin whose - * name matches the provided regular expression. - * - * @param plugin The plugin to which the reader belongs. - * @param readerNameRegex A regular expression matching the targeted reader. - * @return The found card reader. - * @throw IllegalStateException If the reader is not found. - */ - static std::shared_ptr getCardReader(std::shared_ptr plugin, - const std::string& readerNameRegex); - - /** - * Retrieves the contact SAM reader the first available reader in the provided plugin whose name - * matches the provided regular expression. - * - * @param plugin The plugin to which the reader belongs. - * @param readerNameRegex A regular expression matching the targeted reader. - * @return The found SAM reader. - * @throw IllegalStateException If the reader is not found. - */ - static std::shared_ptr getSamReader(std::shared_ptr plugin, - const std::string& readerNameRegex); - - /** - * Attempts to select a SAM and return the {@link CalypsoSam} in case of success. - * - * @param samReader The reader in which the SAM is inserted - * @return A {@link CalypsoSam}. - * @throw IllegalStateException when the selection of the SAM failed. - */ - static std::shared_ptr getSam(std::shared_ptr samReader); - - /** - * Set up the CardResourceService to provide a Calypso SAM C1 resource when requested. - * - * @param plugin The plugin to which the SAM reader belongs. - * @param readerNameRegex A regular expression matching the expected SAM reader name. - * @param samProfileName A string defining the SAM profile. - * @throw IllegalStateException If the expected card resource is not found. - */ - static void setupCardResourceService(std::shared_ptr plugin, - const std::string& readerNameRegex, - const std::string& samProfileName); - -private: - /* - * Reader configurator used by the card resource service to set up the SAM reader with the - * required settings. - */ - class ReaderConfigurator final : public ReaderConfiguratorSpi { - public: - friend class ConfigurationUtil; - - /** - * {@inheritDoc} - */ - void setupReader(std::shared_ptr cardReader) override; - - private: - /** - * - */ - const std::unique_ptr mLogger = - LoggerFactory::getLogger(typeid(ReaderConfigurator)); - - /** - * (private)
- * Constructor. - */ - ReaderConfigurator(); - }; - - /** - * - */ - static const std::unique_ptr mLogger; - - /** - * (private)
- * Constructor. - */ - ConfigurationUtil(); -}; diff --git a/Example_Card_Calypso/src/main/common/ConfigurationUtil.hpp b/Example_Card_Calypso/src/main/common/ConfigurationUtil.hpp new file mode 100644 index 0000000..e612757 --- /dev/null +++ b/Example_Card_Calypso/src/main/common/ConfigurationUtil.hpp @@ -0,0 +1,95 @@ +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#pragma once + +#include +#include + +#include "keyple/core/service/Plugin.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keypop/reader/CardReader.hpp" + +using keyple::core::service::Plugin; +using keyple::plugin::pcsc::PcscReader; +using keypop::reader::CardReader; + +/** + * Utility class providing methods for configuring PC/SC readers used across + * the Calypso card examples. + * + *

The two regular expressions below can be edited to match the names of + * the PC/SC readers actually used to run these examples (contactless reader + * for the Calypso card, contact reader for the Calypso SAM). + */ +class ConfigurationUtil final { +public: + /** + * + */ + static const std::string ISO_CARD_PROTOCOL; + + /** + * + */ + static const std::string INNOVATRON_CARD_PROTOCOL; + + /** + * + */ + static const std::string SAM_PROTOCOL; + + /** + * + */ + static const std::string CARD_READER_NAME_REGEX; + + /** + * + */ + static const std::string SAM_READER_NAME_REGEX; + + /** + * Configures and returns a card reader based on the provided parameters. + * + *

It finds the reader name by matching with a regular expression, then + * configures the reader with the specified settings. + * + * @param plugin The plugin used to interact with the card reader. + * @param readerNameRegex The regular expression to match the card + * reader's name. + * @param isContactless A boolean indicating whether the card reader is + * contactless. + * @param isoProtocol The ISO protocol used by the card reader. + * @param sharingMode The sharing mode of the PC/SC reader. + * @param physicalProtocolName The name of the protocol used by the reader + * to communicate with the card. + * @param logicalProtocolName The name of the protocol known by the + * application. + * @return The configured card reader. + */ + static std::shared_ptr getReader( + std::shared_ptr plugin, + const std::string& readerNameRegex, + bool isContactless, + const PcscReader::IsoProtocol& isoProtocol, + const PcscReader::SharingMode sharingMode, + const std::string& physicalProtocolName, + const std::string& logicalProtocolName); + +private: + /** + * Constructor. + */ + ConfigurationUtil() = default; +}; diff --git a/Example_Card_Calypso/src/main/common/StubSmartCardFactory.cpp b/Example_Card_Calypso/src/main/common/StubSmartCardFactory.cpp index f34c402..484239f 100644 --- a/Example_Card_Calypso/src/main/common/StubSmartCardFactory.cpp +++ b/Example_Card_Calypso/src/main/common/StubSmartCardFactory.cpp @@ -1,82 +1,87 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ -#include "StubSmartCardFactory.h" +#include "StubSmartCardFactory.hpp" -#include "ConfigurationUtil.h" +#include +#include -/* Keyple Core Util */ -#include "HexUtil.h" +#include "keyple/core/util/HexUtil.hpp" -/* Keyple Plugin Stub */ -#include "StubSmartCard.h" +using keyple::core::util::HexUtil; -using namespace keyple::core::util; -using namespace keyple::plugin::stub; +const std::string StubSmartCardFactory::CARD_POWER_ON_DATA + = "3B888001000000009171710098"; +const std::string StubSmartCardFactory::SAM_POWER_ON_DATA + = "3B3F9600805A0080C120000012345678829000"; +const std::string StubSmartCardFactory::ISO_CARD_PROTOCOL = "ISO_14443_4_CARD"; +const std::string StubSmartCardFactory::SAM_PROTOCOL = "ISO_7816_3_T0"; -const std::string StubSmartCardFactory::CARD_POWER_ON_DATA = "3B888001000000009171710098"; -const std::string StubSmartCardFactory::SAM_POWER_ON_DATA = - "3B3F9600805A0080C120000012345678829000"; +std::shared_ptr StubSmartCardFactory::mStubCard + = StubSmartCard::builder() + ->withPowerOnData(HexUtil::toByteArray(CARD_POWER_ON_DATA)) + .withProtocol(ISO_CARD_PROTOCOL) + /* Select application */ + .withSimulatedCommand( + "00A4040009315449432E4943413100", + "6F238409315449432E49434131A516BF0C13C70800000000AABBCCDD53070A3C" + "23051410019000") + /* Read records */ + .withSimulatedCommand( + "00B2013C00", + "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCC9000") + /* Open secure session */ + .withSimulatedCommand( + "008A0B39040011223300", + "0308D1810030791D00112233445566778899AABBCCDDEEFF0011223344556677" + "8899AABBCC9000") + /* Close secure session */ + .withSimulatedCommand("008E8000041234567800", "876543219000") + /* Ping command (used by the card removal procedure) */ + .withSimulatedCommand("00C0000000", "9000") + .build(); -std::shared_ptr StubSmartCardFactory::mStubCard = - StubSmartCard::builder() - ->withPowerOnData(HexUtil::toByteArray(CARD_POWER_ON_DATA)) - .withProtocol(ConfigurationUtil::ISO_CARD_PROTOCOL) - /* Select application */ - .withSimulatedCommand( - "00A4040009315449432E4943413100", - "6F238409315449432E49434131A516BF0C13C70800000000AABBCCDD53070A3C2305141" \ - "0019000") - /* Read records */ - .withSimulatedCommand( - "00B2013C00", - "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCC9000") - /* Open secure session */ - .withSimulatedCommand( - "008A0B39040011223300", - "0308D1810030791D00112233445566778899AABBCCDDEEFF00112233445566778899AAB" \ - "BCC9000") - /* Close secure session */ - .withSimulatedCommand("008E8000041234567800", "876543219000") - /* Ping command (used by the card removal procedure) */ - .withSimulatedCommand("00C0000000", "9000") - .build(); +std::shared_ptr StubSmartCardFactory::mStubSam + = StubSmartCard::builder() + ->withPowerOnData(HexUtil::toByteArray(SAM_POWER_ON_DATA)) + .withProtocol(SAM_PROTOCOL) + /* Select diversifier */ + .withSimulatedCommand("801400000800000000AABBCCDD", "9000") + /* Get challenge */ + .withSimulatedCommand( + "8084000008", + "0011223344556677" + "9000") + /* Digest init */ + .withSimulatedCommand( + "808A00FF2730790308D1810030791D00112233445566778899AABBCCDDEEFF00" + "112233445566778899AABBCC", + "9000") + /* Digest close */ + .withSimulatedCommand("808E000004", "123456789000") + /* Digest authenticate */ + .withSimulatedCommand("808200000487654321", "9000") + .build(); -std::shared_ptr StubSmartCardFactory::mStubSam = - StubSmartCard::builder() - ->withPowerOnData(HexUtil::toByteArray(SAM_POWER_ON_DATA)) - .withProtocol(ConfigurationUtil::SAM_PROTOCOL) - /* Select diversifier */ - .withSimulatedCommand("801400000800000000AABBCCDD", "9000") - /* Get challenge */ - .withSimulatedCommand("8084000004", "001122339000") - /* Digest init */ - .withSimulatedCommand("808A00FF2730790308D1810030791D00112233445566778899AABBCCDDEEFF0011" \ - "2233445566778899AABBCC", - "9000") - /* Digest close */ - .withSimulatedCommand("808E000004", "123456789000") - /* Digest authenticate */ - .withSimulatedCommand("808200000487654321", "9000") - .build(); - -StubSmartCardFactory::StubSmartCardFactory() {} +StubSmartCardFactory::StubSmartCardFactory() { +} -std::shared_ptr StubSmartCardFactory::getStubCard() -{ +std::shared_ptr +StubSmartCardFactory::getStubCard() { return mStubCard; } -std::shared_ptr StubSmartCardFactory::getStubSam() -{ +std::shared_ptr +StubSmartCardFactory::getStubSam() { return mStubSam; -} \ No newline at end of file +} diff --git a/Example_Card_Calypso/src/main/common/StubSmartCardFactory.h b/Example_Card_Calypso/src/main/common/StubSmartCardFactory.hpp similarity index 58% rename from Example_Card_Calypso/src/main/common/StubSmartCardFactory.h rename to Example_Card_Calypso/src/main/common/StubSmartCardFactory.hpp index 6866d5f..2d6b263 100644 --- a/Example_Card_Calypso/src/main/common/StubSmartCardFactory.h +++ b/Example_Card_Calypso/src/main/common/StubSmartCardFactory.hpp @@ -1,24 +1,24 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ #pragma once #include #include -/* Keyple Plugin Stub */ -#include "StubSmartCard.h" +#include "keyple/plugin/stub/StubSmartCard.hpp" -using namespace keyple::plugin::stub; +using keyple::plugin::stub::StubSmartCard; /** * Factory for a Calypso Card emulation via a smart card stub @@ -44,25 +44,22 @@ class StubSmartCardFactory { * */ static const std::string CARD_POWER_ON_DATA; + static const std::string SAM_POWER_ON_DATA; + static const std::string ISO_CARD_PROTOCOL; + static const std::string SAM_PROTOCOL; /** * */ static std::shared_ptr mStubCard; - /** - * - */ - static const std::string SAM_POWER_ON_DATA; - /** * */ static std::shared_ptr mStubSam; /** - * (private)
* Constructor */ StubSmartCardFactory(); -}; \ No newline at end of file +}; diff --git a/Example_Plugin_PCSC/CMakeLists.txt b/Example_Plugin_PCSC/CMakeLists.txt index 9901cd9..78bacbf 100644 --- a/Example_Plugin_PCSC/CMakeLists.txt +++ b/Example_Plugin_PCSC/CMakeLists.txt @@ -1,86 +1,82 @@ -# ************************************************************************************************* -# Copyright (c) 2021 Calypso Networks Association https://calypsonet.org/ * -# * -# See the NOTICE file(s) distributed with this work for additional information regarding * -# copyright ownership. * -# * -# This program and the accompanying materials are made available under the terms of the Eclipse * -# Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * -# * -# SPDX-License-Identifier: EPL-2.0 * -# *************************************************************************************************/ - - -SET(CALYPSONET_CARD_DIR "../../calypsonet-terminal-card-cpp-api") -SET(CALYPSONET_READER_DIR "../../calypsonet-terminal-reader-cpp-api") -SET(KEYPLE_CARD_DIR "../../keyple-card-generic-cpp-lib") -SET(KEYPLE_COMMON_DIR "../../keyple-common-cpp-api") -SET(KEYPLE_PLUGIN_DIR "../../keyple-plugin-cpp-api") -SET(KEYPLE_PCSC_DIR "../../keyple-plugin-pcsc-cpp-lib") -SET(KEYPLE_RESOURCE_DIR "../../keyple-service-resource-cpp-lib") -SET(KEYPLE_SERVICE_DIR "../../keyple-service-cpp-lib") -SET(KEYPLE_UTIL_DIR "../../keyple-util-cpp-lib") - -SET(KEYPLE_CARD_LIB "keyplecardgenericcpplib") -SET(KEYPLE_UTIL_LIB "keypleutilcpplib") -SET(KEYPLE_SERVICE_LIB "keypleservicecpplib") -SET(KEYPLE_PCSC_LIB "keyplepluginpcsccpplib") +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# See the NOTICE file(s) distributed with this work for additional * +# information regarding copyright ownership. * +# * +# This program and the accompanying materials are made available under the * +# terms of the Eclipse Distribution License 1.0 which is available at * +# https://www.eclipse.org/org/documents/edl-v10.php * +# * +# SPDX-License-Identifier: BSD-3-Clause * +# *****************************************************************************/ INCLUDE_DIRECTORIES( - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common - ${CALYPSONET_CARD_DIR}/src/main - ${CALYPSONET_CARD_DIR}/src/main/spi +) - ${CALYPSONET_READER_DIR}/src/main - ${CALYPSONET_READER_DIR}/src/main/selection - ${CALYPSONET_READER_DIR}/src/main/selection/spi - ${CALYPSONET_READER_DIR}/src/main/spi +SET(USECASE1 UseCase1_ReaderTypeAutoIdentification) +ADD_EXECUTABLE( - ${KEYPLE_COMMON_DIR}/src/main + ${USECASE1} - ${KEYPLE_CARD_DIR}/src/main + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE1}/Main_ReaderTypeAutoIdentification_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( - ${KEYPLE_PCSC_DIR}/src/main + ${USECASE1} - ${KEYPLE_PLUGIN_DIR}/src/main - ${KEYPLE_PLUGIN_DIR}/src/main/spi - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader/observable/ - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader/observable/state/insertion - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader/observable/state/processing - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader/observable/state/removal + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Util +) - ${KEYPLE_RESOURCE_DIR}/src/main - ${KEYPLE_RESOURCE_DIR}/src/main/spi +SET(USECASE2 UseCase2_ExplicitReaderType) +ADD_EXECUTABLE( - ${KEYPLE_SERVICE_DIR}/src/main - ${KEYPLE_SERVICE_DIR}/src/main/cpp - ${KEYPLE_SERVICE_DIR}/src/main/spi + ${USECASE2} - ${KEYPLE_UTIL_DIR}/src/main - ${KEYPLE_UTIL_DIR}/src/main/cpp - ${KEYPLE_UTIL_DIR}/src/main/cpp/exception - ${KEYPLE_UTIL_DIR}/src/main/protocol + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE2}/Main_ExplicitReaderType_Pcsc.cpp ) +TARGET_LINK_LIBRARIES( -SET(USECASE1 UseCase1_ReaderTypeAutoIdentification) -ADD_EXECUTABLE(${USECASE1} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE1}/Main_ReaderTypeAutoIdentification_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE1} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB}) + ${USECASE2} -SET(USECASE2 UseCase2_ExplicitReaderType) -ADD_EXECUTABLE(${USECASE2} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE2}/Main_ExplicitReaderType_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE2} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB}) + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Util +) SET(USECASE3 UseCase3_ChangeProtocolRules) -ADD_EXECUTABLE(${USECASE3} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE3}/Main_ChangeProtocolRules_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE3} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB}) +ADD_EXECUTABLE( + + ${USECASE3} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE3}/Main_ChangeProtocolRules_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE3} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Util +) SET(USECASE4 UseCase4_TransmitControl) -ADD_EXECUTABLE(${USECASE4} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE4}/Main_TransmitControl_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE4} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB}) +ADD_EXECUTABLE( + + ${USECASE4} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE4}/Main_TransmitControl_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE4} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Util +) diff --git a/Example_Plugin_PCSC/src/main/UseCase1_ReaderTypeAutoIdentification/Main_ReaderTypeAutoIdentification_Pcsc.cpp b/Example_Plugin_PCSC/src/main/UseCase1_ReaderTypeAutoIdentification/Main_ReaderTypeAutoIdentification_Pcsc.cpp index 1232645..7e467be 100644 --- a/Example_Plugin_PCSC/src/main/UseCase1_ReaderTypeAutoIdentification/Main_ReaderTypeAutoIdentification_Pcsc.cpp +++ b/Example_Plugin_PCSC/src/main/UseCase1_ReaderTypeAutoIdentification/Main_ReaderTypeAutoIdentification_Pcsc.cpp @@ -1,91 +1,104 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ -/* Calypsonet Terminal Reader */ -#include "CardReader.h" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keypop/reader/CardReader.hpp" -/* Keyple Core Util */ -#include "LoggerFactory.h" - -/* Keyple Core Service */ -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPluginFactoryBuilder.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::core::util::cpp; -using namespace keyple::core::service; -using namespace keyple::plugin::pcsc; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keypop::reader::CardReader; /** *

Use Case PC/SC 1 – Automatic reader type identification (PC/SC)

* - *

We demonstrate here how to configure the PC/SC plugin to have an automatic detection of the - * type of reader (contact/non-contact) from its name. + *

We demonstrate here how to configure the PC/SC plugin to have an automatic + * detection of the type of reader (contact/non-contact) from its name. * *

Scenario:

* *
    - *
  • Configure the plugin (via its factory builder) to specify two regular expressions to apply - * to the reader names. - *
  • The first regular expression defines the names of readers that are of the contactless type. - *
  • The second regular expression defines the names of readers that are of the contact type. + *
  • Configure the plugin (via its factory builder) to specify two regular + * expressions to apply to the reader names. + *
  • The first regular expression defines the names of readers that are of + * the contactless type. + *
  • The second regular expression defines the names of readers that are of + * the contact type. *
  • Display the types of all connected readers. *
* - *

Note #1: not all applications need to know what type of reader it is. This - * parameter is only required if the application or card extension intends to call the - * CardReader::isContactless() method. + *

Note #1: not all applications need to know what type of + * reader it is. This parameter is only required if the application or card + * extension intends to call the CardReader::isContactless() method. * - *

Note #2:: the Keyple Calypso Card extension requires this knowledge. + *

Note #2:: the Keyple Calypso Card extension requires this + * knowledge. * - *

Note #2:: In a production application, these regular expressions must be - * adapted to the names of the devices used. - * - *

All results are logged with slf4j. + *

Note #2:: In a production application, these regular + * expressions must be adapted to the names of the devices used. * *

Any unexpected behavior will result in runtime exceptions. * * @since 2.0.0 */ -class Main_ReaderTypeAutoIdentification_Pcsc {}; -static const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_ReaderTypeAutoIdentification_Pcsc)); +class Main_ReaderTypeAutoIdentification_Pcsc { }; +static const std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_ReaderTypeAutoIdentification_Pcsc)); + +static const std::string contactlessFilter = ".*ASK LoGO.*|" + ".*HID OMNIKEY 5427 CK.*|" + ".*contactless.*|" + ".*00 01.*|" + ".*5x21-CL 0.*"; + +static const std::string contactFilter = ".*Identive.*|" + ".*HID Global OMNIKEY 3x21.*|" + "(?=contact)(?!contactless)|" + ".*00 00.*|" + ".*5x21 0.*"; -int main() -{ +int +main() { /* Get the instance of the SmartCardService (singleton pattern) */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); + std::shared_ptr smartCardService + = SmartCardServiceProvider::getService(); /* - * Register the PcscPlugin with the SmartCardService, set the two regular expression matching - * the expected devices, get the corresponding generic plugin in return. + * Register the PcscPlugin with the SmartCardService, set the two regular + * expression matching the expected devices, get the corresponding generic + * plugin in return. */ - std::shared_ptr plugin = - smartCardService->registerPlugin( - PcscPluginFactoryBuilder::builder() - ->useContactlessReaderIdentificationFilter( - ".*ASK LoGO.*|.*HID OMNIKEY 5427 CK.*|.*contactless.*|.*00 01.*|.*5x21-CL 0.*") - .useContactReaderIdentificationFilter( - ".*Identive.*|.*HID Global OMNIKEY 3x21.*|(?=contact)(?!contactless)|.*00 00.*|.*5x21 0.*") - .build()); + std::shared_ptr plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder() + ->useContactlessReaderIdentificationFilter(contactlessFilter) + .useContactReaderIdentificationFilter(contactFilter) + .build()); /* Log the type of each reader */ for (const auto& reader : plugin->getReaders()) { - logger->info("The reader '%' is a '%' type\n", + logger->info( + "The reader '%' is a '%' type\n", reader->getName(), - reader->isContactless() ? std::string("contactless") : std::string("contact")); + reader->isContactless() ? std::string("contactless") + : std::string("contact")); } return 0; diff --git a/Example_Plugin_PCSC/src/main/UseCase2_ExplicitReaderType/Main_ExplicitReaderType_Pcsc.cpp b/Example_Plugin_PCSC/src/main/UseCase2_ExplicitReaderType/Main_ExplicitReaderType_Pcsc.cpp index 7638c0f..4c75ac0 100644 --- a/Example_Plugin_PCSC/src/main/UseCase2_ExplicitReaderType/Main_ExplicitReaderType_Pcsc.cpp +++ b/Example_Plugin_PCSC/src/main/UseCase2_ExplicitReaderType/Main_ExplicitReaderType_Pcsc.cpp @@ -1,94 +1,98 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ -/* Calypsonet Terminal Reader */ -#include "CardReader.h" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keypop/reader/CardReader.hpp" -/* Keyple Core Util */ -#include "LoggerFactory.h" - -/* Keyple Core Service */ -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPluginFactoryBuilder.h" -#include "PcscReader.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::core::util::cpp; -using namespace keyple::core::service; -using namespace keyple::plugin::pcsc; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keypop::reader::CardReader; /** *

Use Case PC/SC 2 – Automatic reader type identification (PC/SC)

* - *

We demonstrate here how to configure the PC/SC plugin to allow explicit setting of - * contact/contactless type for a reader. + *

We demonstrate here how to configure the PC/SC plugin to allow explicit + * setting of contact/contactless type for a reader. * *

Scenario:

* *
    - *
  • Configure the plugin (via its factory builder) without specifying regular expressions. + *
  • Configure the plugin (via its factory builder) without specifying + * regular expressions. *
  • Set the 'contactless' type for all connected readers. *
  • Display the types of all connected readers. *
* - *

Note #1: not all applications need to know what type of reader it is. This - * parameter is only required if the application or card extension intends to call the - * CardReader::isContactless() method. - * - *

Note #2:: the Keyple Calypso Card extension requires this knowledge. + *

Note #1: not all applications need to know what type of + * reader it is. This parameter is only required if the application or card + * extension intends to call the CardReader::isContactless() method. * - *

Note #2:: in a production application, this setting must be applied to the - * relevant reader. + *

Note #2:: the Keyple Calypso Card extension requires this + * knowledge. * - *

All results are logged with slf4j. + *

Note #2:: in a production application, this setting must + * be applied to the relevant reader. * *

Any unexpected behavior will result in runtime exceptions. * * @since 2.0.0 */ -class Main_ExplicitReaderType_Pcsc {}; -static const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_ExplicitReaderType_Pcsc)); +class Main_ExplicitReaderType_Pcsc { }; +static const std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_ExplicitReaderType_Pcsc)); -int main() -{ +int +main() { /* Get the instance of the SmartCardService (singleton pattern) */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); + std::shared_ptr smartCardService + = SmartCardServiceProvider::getService(); /* - * Register the PcscPlugin with the SmartCardService, set the two regular expression matching - * the expected devices, get the corresponding generic plugin in return. + * Register the PcscPlugin with the SmartCardService, set the two regular + * expression matchine the expected devices, get the corresponding generic + * plugin in return. */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); + std::shared_ptr plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); /* - * Set the contactless type to all connected readers through the specific method provided by - * PC/SC reader's extension. + * Set the contactless type to all connected readers through the specific + * method provided by PC/SC reader's extension. */ for (auto& reader : plugin->getReaders()) { std::dynamic_pointer_cast( plugin->getReaderExtension(typeid(PcscReader), reader->getName())) - ->setContactless(true); + ->setContactless(true); } /* Log the type of each connected reader */ for (const auto& reader : plugin->getReaders()) { - logger->info("The reader '%' is a '%' type\n", + logger->info( + "The reader '%' is a '%' type\n", reader->getName(), - reader->isContactless() ? std::string("contactless") : std::string("contact")); + reader->isContactless() ? std::string("contactless") + : std::string("contact")); } return 0; diff --git a/Example_Plugin_PCSC/src/main/UseCase3_ChangeProtocolRules/Main_ChangeProtocolRules_Pcsc.cpp b/Example_Plugin_PCSC/src/main/UseCase3_ChangeProtocolRules/Main_ChangeProtocolRules_Pcsc.cpp index f7b581d..476f403 100644 --- a/Example_Plugin_PCSC/src/main/UseCase3_ChangeProtocolRules/Main_ChangeProtocolRules_Pcsc.cpp +++ b/Example_Plugin_PCSC/src/main/UseCase3_ChangeProtocolRules/Main_ChangeProtocolRules_Pcsc.cpp @@ -1,111 +1,118 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" -#include "ConfigurableCardReader.h" - -/* Keyple Core Util */ -#include "LoggerFactory.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPluginFactoryBuilder.h" -#include "PcscReader.h" - -/* Keyple Card Generic */ -#include "GenericExtensionService.h" - -/* Keyple Core Common */ -#include "KeypleCardExtension.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::generic; -using namespace keyple::core::common; -using namespace keyple::core::util::cpp; -using namespace keyple::core::service; -using namespace keyple::plugin::pcsc; +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include "keyple/card/generic/GenericExtensionService.hpp" +#include "keyple/core/common/KeypleCardExtension.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ConfigurableCardReader.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" + +using keyple::card::generic::GenericExtensionService; +using keyple::core::common::KeypleCardExtension; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keypop::reader::CardReader; +using keypop::reader::ConfigurableCardReader; +using keypop::reader::ReaderApiFactory; /** *

Use Case PC/SC 3 – Change of a protocol identification rule (PC/SC)

* - *

Here we demonstrate how to add a protocol rule to target a specific card technology by - * applying a regular expression on the ATR provided by the reader. + *

Here we demonstrate how to add a protocol rule to target a specific card + * technology by applying a regular expression on the ATR provided by the + * reader. * - *

This feature of the PC/SC plugin is useful for extending the set of rules already supported, - * but also for solving compatibility issues with some readers producing ATRs that do not work with - * the built-in rules. + *

This feature of the PC/SC plugin is useful for extending the set of rules + * already supported, but also for solving compatibility issues with some + * readers producing ATRs that do not work with the built-in rules. * *

Scenario:

* *
    - *
  • Configure the plugin to add a new protocol rule targeting Mifare Classic 4K cards. - *
  • Attempts to select a Mifare Classic 4K card with a protocol based selection. + *
  • Configure the plugin to add a new protocol rule targeting Mifare + * Classic 4K cards. + *
  • Attempts to select a Mifare Classic 4K card with a protocol based + * selection. *
  • Display the selection result. *
* - * In a real application, these regular expressions must be customized to the names of the devices - * used. - * - *

All results are logged with slf4j. + * In a real application, these regular expressions must be customized to the + * names of the devices used. * *

Any unexpected behavior will result in runtime exceptions. * * @since 2.0.0 */ -class Main_ChangeProtocolRules_Pcsc {}; -static const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_ChangeProtocolRules_Pcsc)); +class Main_ChangeProtocolRules_Pcsc { }; +static const std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_ChangeProtocolRules_Pcsc)); -static const std::string READER_PROTOCOL_MIFARE_CLASSIC_4_K = "MIFARE_CLASSIC_4K"; +static const std::string READER_PROTOCOL_MIFARE_CLASSIC_4_K + = "MIFARE_CLASSIC_4K"; static const std::string CARD_PROTOCOL_MIFARE_CLASSIC_4_K = "MIFARE_CLASSIC_4K"; -int main() -{ +int +main() { /* Get the instance of the SmartCardService (singleton pattern) */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); + auto smartCardService(SmartCardServiceProvider::getService()); /* - * Register the PcscPlugin with the SmartCardService, set the two regular expression matching - * the expected devices, get the corresponding generic plugin in return. + * Register the PcscPlugin with the SmartCardService, set the two regular + * expression matching the expected devices, get the corresponding generic + * plugin in return. + */ + auto factory(PcscPluginFactoryBuilder::builder() + ->updateProtocolIdentificationRule( + READER_PROTOCOL_MIFARE_CLASSIC_4_K, + "3B8F8001804F0CA0000003060300020000000069") + .build()); + auto plugin(smartCardService->registerPlugin(factory)); + + /* + * Get the first available reader (we assume that a single contactless + * reader is connected). */ - std::shared_ptr plugin = - smartCardService->registerPlugin( - PcscPluginFactoryBuilder::builder() - ->updateProtocolIdentificationRule( - READER_PROTOCOL_MIFARE_CLASSIC_4_K, "3B8F8001804F0CA0000003060300020000000069") - .build()); - - /* Get the first available reader (we assume that a single contactless reader is connected) */ std::shared_ptr reader = plugin->getReaders()[1]; - std::dynamic_pointer_cast(reader) - ->activateProtocol(READER_PROTOCOL_MIFARE_CLASSIC_4_K, CARD_PROTOCOL_MIFARE_CLASSIC_4_K); + std::dynamic_pointer_cast(reader)->activateProtocol( + READER_PROTOCOL_MIFARE_CLASSIC_4_K, CARD_PROTOCOL_MIFARE_CLASSIC_4_K); /* Configure the reader for contactless operations */ std::dynamic_pointer_cast( plugin->getReaderExtension(typeid(PcscReader), reader->getName())) - ->setContactless(true) - .setIsoProtocol(PcscReader::IsoProtocol::T1) - .setSharingMode(PcscReader::SharingMode::SHARED); + ->setContactless(true) + .setIsoProtocol(PcscReader::IsoProtocol::T1) + .setSharingMode(PcscReader::SharingMode::SHARED); /* Get the generic card extension service */ - std::shared_ptr cardExtension = GenericExtensionService::getInstance(); + auto cardExtension = GenericExtensionService::getInstance(); - /* Verify that the extension's API level is consistent with the current service */ + /* + * Verify that the extension's API level is consistent with the current + * service. + */ smartCardService->checkCardExtension(cardExtension); /* Check if a card is present in the reader */ @@ -114,25 +121,27 @@ int main() return -1; } + /* Retrieve the reader API factory. */ + std::shared_ptr readerApiFactory( + smartCardService->getReaderApiFactory()); + /* Get the core card selection manager */ - std::unique_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + auto cardSelectionManager(readerApiFactory->createCardSelectionManager()); - /* - * Create a card selection using the generic card extension without specifying any filter - * (protocol/ATR/DFName). - */ - std::shared_ptr cardSelection = cardExtension->createCardSelection(); - cardSelection->filterByCardProtocol(CARD_PROTOCOL_MIFARE_CLASSIC_4_K); + /* Create a generic card selection with a MIFARE CLASSIC protocol filter. */ + auto cardSelector(readerApiFactory->createBasicCardSelector()); + cardSelector->filterByCardProtocol(CARD_PROTOCOL_MIFARE_CLASSIC_4_K); /* - * Prepare the selection by adding the created generic selection to the card selection scenario. + * Prepare the selection by adding the created generic selection to the card + * selection scenario. */ - cardSelectionManager->prepareSelection(cardSelection); + cardSelectionManager->prepareSelection( + cardSelector, cardExtension->createGenericCardSelectionExtension()); /* Actual card communication: run the selection scenario */ - const std::shared_ptr selectionResult = - cardSelectionManager->processCardSelectionScenario(reader); + const auto selectionResult + = cardSelectionManager->processCardSelectionScenario(reader); /* Check the selection result */ if (selectionResult->getActiveSmartCard() == nullptr) { @@ -141,7 +150,7 @@ int main() } /* Get the SmartCard resulting of the selection */ - std::shared_ptr smartCard = selectionResult->getActiveSmartCard(); + const auto smartCard = selectionResult->getActiveSmartCard(); logger->info("= SmartCard = %\n", smartCard); diff --git a/Example_Plugin_PCSC/src/main/UseCase4_TransmitControl/Main_TransmitControl_Pcsc.cpp b/Example_Plugin_PCSC/src/main/UseCase4_TransmitControl/Main_TransmitControl_Pcsc.cpp index 3440d1c..59d9be8 100644 --- a/Example_Plugin_PCSC/src/main/UseCase4_TransmitControl/Main_TransmitControl_Pcsc.cpp +++ b/Example_Plugin_PCSC/src/main/UseCase4_TransmitControl/Main_TransmitControl_Pcsc.cpp @@ -1,122 +1,149 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" - -/* Keyple Core Util */ -#include "HexUtil.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" -#include "StringUtils.h" -#include "Thread.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "ObservableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPluginFactoryBuilder.h" -#include "PcscReader.h" - -/* Keyple Card Generic */ -#include "GenericExtensionService.h" - -/* Keyple Core Common */ -#include "KeypleCardExtension.h" - -using namespace keyple::card::generic; -using namespace keyple::core::common; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::service; -using namespace keyple::plugin::pcsc; +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include +#include + +#include "keyple/card/generic/GenericExtensionService.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardServiceAdapter.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/StringUtils.hpp" +#include "keyple/core/util/cpp/Thread.hpp" +#include "keyple/core/util/cpp/exception/Exception.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keypop/reader/CardReaderEvent.hpp" +#include "keypop/reader/ObservableCardReader.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/spi/CardReaderObservationExceptionHandlerSpi.hpp" +#include "keypop/reader/spi/CardReaderObserverSpi.hpp" + +using keyple::card::generic::GenericExtensionService; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardServiceAdapter; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::StringUtils; +using keyple::core::util::cpp::Thread; +using keyple::core::util::cpp::exception::Exception; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keypop::reader::CardReaderEvent; +using keypop::reader::ObservableCardReader; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::spi::CardReaderObservationExceptionHandlerSpi; +using keypop::reader::spi::CardReaderObserverSpi; /** *

Use Case PC/SC 4 – Transmit control command to the connected reader

* - *

Here we demonstrate how to transmit specific commands to a reader using the Transmit Control - * mechanism offered by PC/SC. + *

Here we demonstrate how to transmit specific commands to a reader using + * the Transmit Control mechanism offered by PC/SC. * - *

This function of the PC/SC plugin is useful to access specific features of the reader such as - * setting parameters, controlling LEDs, a buzzer or any other proprietary function defined by the - * reader manufacturer. + *

This function of the PC/SC plugin is useful to access specific features of + * the reader such as setting parameters, controlling LEDs, a buzzer or any + * other proprietary function defined by the reader manufacturer. * - *

Here, we show its use to change the color of the RGB LEDs and activate the buzzer of a - * SpringCard "Puck One" reader. + *

Here, we show its use to change the color of the RGB LEDs and activate the + * buzzer of a SpringCard "Puck One" reader. * *

Scenario

* *
    *
  • Connect a Puck One reader *
  • Run the program: the LED turns yellow - *
  • Present a card that matches the AID: the LED turns green as long as the card is present, - * and blue when the card is removed - *
  • Present a card that does not match the AID: the LED turns red as long as the card is - * present, and blue when the card is removed + *
  • Present a card that matches the AID: the LED turns green as long as the + * card is present, and blue when the card is removed + *
  • Present a card that does not match the AID: the LED turns red as long + * as the card is present, and blue when the card is removed *
* *

Any unexpected behavior will result in runtime exceptions. * * @since 2.1.0 */ -class Main_TransmitControl_Pcsc {}; -static const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_TransmitControl_Pcsc)); +class Main_TransmitControl_Pcsc { }; +static const std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_TransmitControl_Pcsc)); static const std::string AID = "315449432E49434131"; -static const std::vector CMD_SET_LED_RED = HexUtil::toByteArray("581E010000"); -static const std::vector CMD_SET_LED_GREEN = HexUtil::toByteArray("581E000100"); -static const std::vector CMD_SET_LED_BLUE = HexUtil::toByteArray("581E000001"); -static const std::vector CMD_SET_LED_YELLOW = HexUtil::toByteArray("581E010100"); -static const std::vector CMD_BUZZER_200MS = HexUtil::toByteArray("589300C8"); +static const std::vector CMD_SET_LED_RED + = HexUtil::toByteArray("581E010000"); +static const std::vector CMD_SET_LED_GREEN + = HexUtil::toByteArray("581E000100"); +static const std::vector CMD_SET_LED_BLUE + = HexUtil::toByteArray("581E000001"); +static const std::vector CMD_SET_LED_YELLOW + = HexUtil::toByteArray("581E010100"); +static const std::vector CMD_BUZZER_200MS + = HexUtil::toByteArray("589300C8"); /** Card observer class. */ -class CardObserver final -: public CardReaderObserverSpi, public CardReaderObservationExceptionHandlerSpi { +class CardObserver final : public CardReaderObserverSpi, + public CardReaderObservationExceptionHandlerSpi { public: /** * Constructor * * @param pcscReader The PcscReader is use. */ - CardObserver(const std::shared_ptr pcscReader) : mPcscReader(pcscReader) {} + explicit CardObserver(const std::shared_ptr pcscReader) + : mPcscReader(pcscReader) { + } /** * Changes the LED color depending on the event type. * * @param event The current event. */ - void onReaderEvent(const std::shared_ptr event) override - { + void + onReaderEvent(const std::shared_ptr event) override { try { switch (event->getType()) { case CardReaderEvent::CARD_INSERTED: - mPcscReader->transmitControlCommand(mPcscReader->getIoctlCcidEscapeCommandId(), - CMD_BUZZER_200MS); - mPcscReader->transmitControlCommand(mPcscReader->getIoctlCcidEscapeCommandId(), - CMD_SET_LED_RED); + mPcscReader->transmitControlCommand( + mPcscReader->getIoctlCcidEscapeCommandId(), + CMD_BUZZER_200MS); + mPcscReader->transmitControlCommand( + mPcscReader->getIoctlCcidEscapeCommandId(), + CMD_SET_LED_RED); break; case CardReaderEvent::CARD_MATCHED: - mPcscReader->transmitControlCommand(mPcscReader->getIoctlCcidEscapeCommandId(), - CMD_BUZZER_200MS); - mPcscReader->transmitControlCommand(mPcscReader->getIoctlCcidEscapeCommandId(), - CMD_SET_LED_GREEN); + mPcscReader->transmitControlCommand( + mPcscReader->getIoctlCcidEscapeCommandId(), + CMD_BUZZER_200MS); + mPcscReader->transmitControlCommand( + mPcscReader->getIoctlCcidEscapeCommandId(), + CMD_SET_LED_GREEN); break; case CardReaderEvent::CARD_REMOVED: - mPcscReader->transmitControlCommand(mPcscReader->getIoctlCcidEscapeCommandId(), - CMD_SET_LED_BLUE); + mPcscReader->transmitControlCommand( + mPcscReader->getIoctlCcidEscapeCommandId(), + CMD_SET_LED_BLUE); break; case CardReaderEvent::UNAVAILABLE: break; @@ -124,58 +151,71 @@ class CardObserver final /* Finally block */ if (event->getType() != CardReaderEvent::Type::CARD_REMOVED) { - /* Indicates the end of the card processing (not needed for a removal event) */ + /* + * Indicates the end of the card processing (not needed for a + * removal event). + */ std::dynamic_pointer_cast( - SmartCardServiceProvider::getService()->getPlugins()[0] - ->getReader(event->getReaderName())) - ->finalizeCardProcessing(); + SmartCardServiceProvider::getService() + ->getPlugins()[0] + ->getReader(event->getReaderName())) + ->finalizeCardProcessing(); } - } catch (const Exception& e) { - - (void)e; - + } catch (const Exception&) { /* Finally block */ if (event->getType() != CardReaderEvent::Type::CARD_REMOVED) { - /* Indicates the end of the card processing (not needed for a removal event) */ + /* + * Indicates the end of the card processing (not needed for a + * removal event). + */ std::dynamic_pointer_cast( - SmartCardServiceProvider::getService()->getPlugins()[0] - ->getReader(event->getReaderName())) - ->finalizeCardProcessing(); + SmartCardServiceProvider::getService() + ->getPlugins()[0] + ->getReader(event->getReaderName())) + ->finalizeCardProcessing(); } } } - void onReaderObservationError(const std::string& pluginName, - const std::string& readerName, - std::shared_ptr e) override - { - logger->error("An exception occurred in plugin '%', reader '%'\n", - pluginName, - readerName, - e); + void + onReaderObservationError( + const std::string& pluginName, + const std::string& readerName, + const std::shared_ptr e) override { + logger->error( + "An exception occurred in plugin '%', reader '%'\n", + pluginName, + readerName, + e); } private: std::shared_ptr mPcscReader; }; -int main() -{ +int +main() { /* Get the instance of the SmartCardService (singleton pattern) */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); /* - * Register the PcscPlugin with the SmartCardService, set the two regular expression matching - * the expected devices, get the corresponding generic plugin in return. + * Register the PcscPlugin with the SmartCardService, set the two regular + * expression matching the expected devices, get the corresponding generic + * plugin in return. */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); + std::shared_ptr plugin(smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build())); - /* Get the contactless reader (we assume that a SpringCard Puck One reader is connected) */ + /* + * Get the contactless reader (we assume that a SpringCard Puck One reader + * is connected). + */ std::shared_ptr reader = nullptr; for (const auto& r : plugin->getReaders()) { - if (StringUtils::contains(StringUtils::tolower(r->getName()), "contactless")) { + if (StringUtils::contains( + StringUtils::tolower(r->getName()), "contactless")) { reader = std::dynamic_pointer_cast(r); } } @@ -184,51 +224,61 @@ int main() throw IllegalStateException("Reader not found"); } - std::shared_ptr pcscReader = + std::shared_ptr pcscReader( std::dynamic_pointer_cast( - plugin->getReaderExtension(typeid(PcscReader), reader->getName())); + plugin->getReaderExtension(typeid(PcscReader), reader->getName()))); /* Change the LED color to yellow when no card is connected */ for (int i = 0; i < 3; i++) { - pcscReader->transmitControlCommand(pcscReader->getIoctlCcidEscapeCommandId(), - CMD_SET_LED_YELLOW); + pcscReader->transmitControlCommand( + pcscReader->getIoctlCcidEscapeCommandId(), CMD_SET_LED_YELLOW); Thread::sleep(200); - pcscReader->transmitControlCommand(pcscReader->getIoctlCcidEscapeCommandId(), - CMD_SET_LED_BLUE); + pcscReader->transmitControlCommand( + pcscReader->getIoctlCcidEscapeCommandId(), CMD_SET_LED_BLUE); Thread::sleep(200); } /* Get the generic card extension service */ - std::shared_ptr genericExtensionService = - GenericExtensionService::getInstance(); + std::shared_ptr cardExtension + = GenericExtensionService::getInstance(); /* Check the extension */ - smartCardService->checkCardExtension(genericExtensionService); + smartCardService->checkCardExtension(cardExtension); + + /* Retrieve the reader API factory. */ + std::shared_ptr readerApiFactory( + smartCardService->getReaderApiFactory()); /* Get the core card selection manager */ - std::unique_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); - /* Create a card selection using the generic card extension. */ - std::shared_ptr cardSelection = - genericExtensionService->createCardSelection(); - cardSelection->filterByDfName(AID); + /* + * Create a card selection using the generic card extension without + * specifying any filter (protocol/ATR/DFName). + */ + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(AID); - /* Prepare the selection by adding the created selection to the card selection scenario. */ - cardSelectionManager->prepareSelection(cardSelection); + /* + * Prepare the selection by adding the created generic selection to the card + * selection scenario. + */ + cardSelectionManager->prepareSelection( + cardSelector, cardExtension->createGenericCardSelectionExtension()); /* Schedule the selection scenario, always notify card presence. */ cardSelectionManager->scheduleCardSelectionScenario( - reader, - ObservableCardReader::DetectionMode::REPEATING, - ObservableCardReader::NotificationMode::ALWAYS); + reader, ObservableCardReader::NotificationMode::ALWAYS); - auto cardObserver = std::make_shared(pcscReader); + auto cardObserver(std::make_shared(pcscReader)); reader->setReaderObservationExceptionHandler(cardObserver); reader->addObserver(cardObserver); reader->startCardDetection(ObservableCardReader::DetectionMode::REPEATING); /* Wait indefinitely. CTRL-C to exit. */ - while (1); + while (1) { + } } diff --git a/Example_Service/CMakeLists.txt b/Example_Service/CMakeLists.txt index f5ca311..49e3dbb 100644 --- a/Example_Service/CMakeLists.txt +++ b/Example_Service/CMakeLists.txt @@ -1,111 +1,147 @@ -# ************************************************************************************************* -# Copyright (c) 2021 Calypso Networks Association https://calypsonet.org/ * -# * -# See the NOTICE file(s) distributed with this work for additional information regarding * -# copyright ownership. * -# * -# This program and the accompanying materials are made available under the terms of the Eclipse * -# Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * -# * -# SPDX-License-Identifier: EPL-2.0 * -# *************************************************************************************************/ - - -SET(CALYPSONET_CARD_DIR "../../calypsonet-terminal-card-cpp-api") -SET(CALYPSONET_READER_DIR "../../calypsonet-terminal-reader-cpp-api") -SET(KEYPLE_CARD_DIR "../../keyple-card-generic-cpp-lib") -SET(KEYPLE_COMMON_DIR "../../keyple-common-cpp-api") -SET(KEYPLE_PLUGIN_DIR "../../keyple-plugin-cpp-api") -SET(KEYPLE_PCSC_DIR "../../keyple-plugin-pcsc-cpp-lib") -SET(KEYPLE_RESOURCE_DIR "../../keyple-service-resource-cpp-lib") -SET(KEYPLE_SERVICE_DIR "../../keyple-service-cpp-lib") -SET(KEYPLE_UTIL_DIR "../../keyple-util-cpp-lib") - -SET(KEYPLE_CARD_LIB "keyplecardgenericcpplib") -SET(KEYPLE_PCSC_LIB "keyplepluginpcsccpplib") -SET(KEYPLE_SERVICE_LIB "keypleservicecpplib") -SET(KEYPLE_UTIL_LIB "keypleutilcpplib") +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# See the NOTICE file(s) distributed with this work for additional * +# information regarding copyright ownership. * +# * +# This program and the accompanying materials are made available under the * +# terms of the Eclipse Distribution License 1.0 which is available at * +# https://www.eclipse.org/org/documents/edl-v10.php * +# * +# SPDX-License-Identifier: BSD-3-Clause * +# *****************************************************************************/ INCLUDE_DIRECTORIES( - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common - ${CALYPSONET_CARD_DIR}/src/main - ${CALYPSONET_CARD_DIR}/src/main/spi + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/ +) - ${CALYPSONET_READER_DIR}/src/main - ${CALYPSONET_READER_DIR}/src/main/selection - ${CALYPSONET_READER_DIR}/src/main/selection/spi - ${CALYPSONET_READER_DIR}/src/main/spi +SET(USECASE1 UseCase1_BasicSelection) +ADD_EXECUTABLE( - ${KEYPLE_COMMON_DIR}/src/main + ${USECASE1} - ${KEYPLE_CARD_DIR}/src/main + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE1}/Main_BasicSelection_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( - ${KEYPLE_PCSC_DIR}/src/main + ${USECASE1} - ${KEYPLE_PLUGIN_DIR}/src/main - ${KEYPLE_PLUGIN_DIR}/src/main/spi - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader/observable/ - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader/observable/state/insertion - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader/observable/state/processing - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader/observable/state/removal + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Util +) - ${KEYPLE_RESOURCE_DIR}/src/main - ${KEYPLE_RESOURCE_DIR}/src/main/spi +SET(USECASE2 UseCase2_ProtocolBasedSelection) +ADD_EXECUTABLE( - ${KEYPLE_SERVICE_DIR}/src/main - ${KEYPLE_SERVICE_DIR}/src/main/cpp - ${KEYPLE_SERVICE_DIR}/src/main/spi + ${USECASE2} - ${KEYPLE_UTIL_DIR}/src/main - ${KEYPLE_UTIL_DIR}/src/main/cpp - ${KEYPLE_UTIL_DIR}/src/main/cpp/exception - ${KEYPLE_UTIL_DIR}/src/main/protocol + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE2}/Main_ProtocolBasedSelection_Pcsc.cpp ) +TARGET_LINK_LIBRARIES( -SET(USECASE1 UseCase1_BasicSelection) -ADD_EXECUTABLE(${USECASE1} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE1}/Main_BasicSelection_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE1} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB}) + ${USECASE2} -SET(USECASE2 UseCase2_ProtocolBasedSelection) -ADD_EXECUTABLE(${USECASE2} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE2}/Main_ProtocolBasedSelection_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE2} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB}) + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Util +) SET(USECASE3 UseCase3_AidBasedSelection) -ADD_EXECUTABLE(${USECASE3} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE3}/Main_AidBasedSelection_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE3} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB}) +ADD_EXECUTABLE( + + ${USECASE3} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE3}/Main_AidBasedSelection_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE3} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Util +) SET(USECASE4 UseCase4_ScheduledSelection) -ADD_EXECUTABLE(${USECASE4} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE4}/CardReaderObserver.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE4}/Main_ScheduledSelection_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE4} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB}) +ADD_EXECUTABLE( + + ${USECASE4} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE4}/CardReaderObserver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE4}/Main_ScheduledSelection_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE4} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Util +) SET(USECASE5 UseCase5_SequentialMultiSelection) -ADD_EXECUTABLE(${USECASE5} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE5}/Main_SequentialMultiSelection_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE5} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB}) +ADD_EXECUTABLE( + + ${USECASE5} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE5}/Main_SequentialMultiSelection_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE5} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Util +) SET(USECASE6 UseCase6_GroupedMultiSelection) -ADD_EXECUTABLE(${USECASE6} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE6}/Main_GroupedMultiSelection_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE6} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB}) +ADD_EXECUTABLE( + + ${USECASE6} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE6}/Main_GroupedMultiSelection_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE6} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Util +) SET(USECASE7 UseCase7_PluginAndReaderObservation) -ADD_EXECUTABLE(${USECASE7} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE7}/PluginObserver.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE7}/ReaderObserver.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE7}/Main_PluginAndReaderObservation_Pcsc.cpp) -TARGET_LINK_LIBRARIES(${USECASE7} ${KEYPLE_CARD_LIB} ${KEYPLE_PCSC_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_UTIL_LIB}) +ADD_EXECUTABLE( + + ${USECASE7} + + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common/ConfigurationUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE7}/PluginObserver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE7}/ReaderObserver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE7}/Main_PluginAndReaderObservation_Pcsc.cpp +) +TARGET_LINK_LIBRARIES( + + ${USECASE7} + + Keyple::Card::Generic + Keyple::Plugin::Pcsc + Keyple::Service + Keyple::Util +) diff --git a/Example_Service/src/main/UseCase1_BasicSelection/Main_BasicSelection_Pcsc.cpp b/Example_Service/src/main/UseCase1_BasicSelection/Main_BasicSelection_Pcsc.cpp index a418945..3891cfa 100644 --- a/Example_Service/src/main/UseCase1_BasicSelection/Main_BasicSelection_Pcsc.cpp +++ b/Example_Service/src/main/UseCase1_BasicSelection/Main_BasicSelection_Pcsc.cpp @@ -1,156 +1,235 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" -#include "ConfigurableCardReader.h" - -/* Keyple Card Generic */ -#include "GenericExtensionService.h" - -/* Keyple Core Util */ -#include "HexUtil.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" - -/* Keyple Core Service */ -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPluginFactoryBuilder.h" -#include "PcscReader.h" -#include "PcscSupportedContactlessProtocol.h" - -/* Keyple Cpp Example */ -#include "ConfigurationUtil.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::generic; -using namespace keyple::core::service; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include + +#include "keyple/card/generic/ChannelControl.hpp" +#include "keyple/card/generic/GenericExtensionService.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ConfigurableCardReader.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +using keyple::card::generic::ChannelControl; +using keyple::card::generic::GenericExtensionService; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keypop::reader::CardReader; +using keypop::reader::ConfigurableCardReader; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::spi::SmartCard; /** *

Use Case Generic 1 – Basic Selection (PC/SC)

* - *

We demonstrate here a selection of cards without any condition related to the card itself. Any - * card able to communicate with the reader must lead to a "selected" state.
+ *

We demonstrate here a selection of cards without any condition related to + * the card itself. Any card able to communicate with the reader must lead to a + * "selected" state.
* Note that in this case, no APDU "select application" is sent to the card.
- * However, upon selection, an APDU command specific to Global Platform compliant cards is sent to - * the card and may fail depending on the type of card presented. + * However, upon selection, an APDU command specific to Global Platform + * compliant cards is sent to the card and may fail depending on the type of + * card presented. * *

Scenario:

* *
    - *
  • Check if a ISO 14443-4 card is in the reader, select a card (a GlobalPlatform compliant - * card is expected here [e.g. EMV card or Javacard]). + *
  • Check if a ISO 14443-4 card is in the reader, select a card (a + * GlobalPlatform compliant card is expected here [e.g. EMV card or + * Javacard]). *
  • Run a selection scenario without filter. *
  • Output the collected smart card data (power-on data). - *
  • Send a additional APDUs to the card (get Card Production Life Cycle data [CPLC]). + *
  • Send a additional APDUs to the card (get Card Production Life Cycle + * data [CPLC]). *
* *

Any unexpected behavior will result in runtime exceptions. * * @since 2.0.0 */ -class Main_BasicSelection_Pcsc {}; -const std::unique_ptr logger = LoggerFactory::getLogger(typeid(Main_BasicSelection_Pcsc)); - -int main() -{ - /* Get the instance of the SmartCardService (singleton pattern) */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); - - /* - * Register the PcscPlugin with the SmartCardService, get the corresponding generic plugin in - * return. - */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); - - /* Get the generic card extension service */ - std::shared_ptr genericCardService = - GenericExtensionService::getInstance(); - - /* Verify that the extension's API level is consistent with the current service */ - smartCardService->checkCardExtension(genericCardService); - - const std::string pcscContactlessReaderName = - ConfigurationUtil::getCardReaderName(plugin, - ConfigurationUtil::CONTACTLESS_READER_NAME_REGEX); - std::shared_ptr cardReader = plugin->getReader(pcscContactlessReaderName); - - /* Configure the reader with parameters suitable for contactless operations. */ - std::dynamic_pointer_cast( - plugin->getReaderExtension(typeid(PcscReader), pcscContactlessReaderName)) - ->setContactless(true) - .setIsoProtocol(PcscReader::IsoProtocol::T1) - .setSharingMode(PcscReader::SharingMode::SHARED); - std::dynamic_pointer_cast(cardReader) - ->activateProtocol(PcscSupportedContactlessProtocol::ISO_14443_4.getName(), - ConfigurationUtil::ISO_CARD_PROTOCOL); - - logger->info("=============== " \ - "UseCase Generic #1: basic card selection " \ - "==================\n"); - - /* Check if a card is present in the reader */ - if (!cardReader->isCardPresent()) { - logger->error("No card is present in the reader\n"); - return 0; - } +class Main_BasicSelection_Pcsc { }; +const std::unique_ptr + logger(LoggerFactory::getLogger(typeid(Main_BasicSelection_Pcsc))); - logger->info("= #### Select the card with no conditions\n"); +static std::shared_ptr plugin; +static std::shared_ptr readerApiFactory; +static std::shared_ptr cardReader; - /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); +static const std::string CONTACTLESS_READER_NAME_REGEX + = ".*ASK LoGO.*|.*Contactless.*|.*00 01.*"; +static const std::string ISO_CARD_PROTOCOL = "ISO_14443_4_CARD"; - /* - * Create a card selection using the generic card extension without specifying any filter - * (protocol/power-on data/DFName). - */ - std::shared_ptr cardSelection = genericCardService->createCardSelection(); +/** + * Initializes the Keyple service. + * + *

Gets an instance of the smart card service, registers the PC/SC plugin, + * and prepares the reader API factory for use. + * + *

Retrieves the ReaderApiFactory. + */ +static void +initKeypleService() { + const auto smartCardService(SmartCardServiceProvider::getService()); + plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} - /* - * Prepare the selection by adding the created generic selection to the card selection scenario - */ - cardSelectionManager->prepareSelection(cardSelection); +/** + * Initializes the generic card extension service. + */ +static void +initGenericCardExtensionService() { + const auto genericExtensionService(GenericExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + genericExtensionService); +} - /* Actual card communication: run the selection scenario */ - std::shared_ptr selectionResult = - cardSelectionManager->processCardSelectionScenario(cardReader); +/** + * Configures and returns a card reader based on the provided parameters. + * + *

It finds the reader name by matching with a regular expression, then + * configures the reader with the specified settings. + * + * @param plugin The plugin used to interact with the card reader. + * @param readerNameRegex The regular expression to match the card reader's + * name. + * @param isContactless A boolean indicating whether the card reader is + * contactless. + * @param isoProtocol The ISO protocol used by the card reader. + * @param sharingMode The sharing mode of the PC/SC reader. + * @param physicalProtocolName The name of the protocol used by the reader to + * communicate with card. + * @param logicalProtocolName The name of the protocol known by the application. + * @return The configured card reader. + */ +static std::shared_ptr +getReader( + std::shared_ptr _plugin, + const std::string& readerNameRegex, + const bool isContactless, + const PcscReader::IsoProtocol isoProtocol, + const PcscReader::SharingMode sharingMode, + const std::string& physicalProtocolName, + const std::string& logicalProtocolName) { + const auto reader(_plugin->findReader(readerNameRegex)); + + auto pcscReader(std::dynamic_pointer_cast( + _plugin->getReaderExtension(typeid(PcscReader), reader->getName()))); + + pcscReader->setContactless(isContactless) + .setIsoProtocol(isoProtocol) + .setSharingMode(sharingMode); + + std::dynamic_pointer_cast(reader)->activateProtocol( + physicalProtocolName, logicalProtocolName); + + return reader; +} + +/** + * Initializes the card reader with specific configurations. + * + *

Prepares the card reader using a predefined set of configurations, + * including the card reader name regex, ISO protocol, and sharing mode. + */ +static void +initCardReader() { + cardReader = getReader( + plugin, + CONTACTLESS_READER_NAME_REGEX, + true, + PcscReader::IsoProtocol::T1, + PcscReader::SharingMode::EXCLUSIVE, + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ISO_CARD_PROTOCOL); +} + +/** + * Selects any card for the transaction. + * + *

Creates a card selection manager, prepares the selection using no filter. + * + * @param reader The reader used to communicate with the card. + * @return The selected smart card ready for the transaction. + * @throws IllegalStateException if the selection of the application fails. + */ +static std::shared_ptr +selectCard(std::shared_ptr reader) { + auto cardSelectionManager(readerApiFactory->createCardSelectionManager()); + auto cardSelector(readerApiFactory->createIsoCardSelector()); + auto genericCardSelectionExtension( + GenericExtensionService::getInstance() + ->createGenericCardSelectionExtension()); + + cardSelectionManager->prepareSelection( + cardSelector, genericCardSelectionExtension); + + std::shared_ptr selectionResult( + cardSelectionManager->processCardSelectionScenario(reader)); - /* Check the selection result */ if (selectionResult->getActiveSmartCard() == nullptr) { - throw IllegalStateException("The selection of the card failed."); + throw new IllegalStateException("The selection of the card failed."); } - /* Get the SmartCard resulting of the selection */ - std::shared_ptr smartCard = selectionResult->getActiveSmartCard(); + return selectionResult->getActiveSmartCard(); +} + +int +main() { + Logger::setLoggerLevel(Logger::Level::logTrace); + logger->info("= UseCase Generic #1: basic card selection ==============\n"); + + initKeypleService(); + initGenericCardExtensionService(); + initCardReader(); + + /* Check the card presence */ + if (!cardReader->isCardPresent()) { + throw IllegalStateException("No card is present in the reader."); + } + + logger->info("= #### Select the card with no conditions\n"); + + std::shared_ptr smartCard(selectCard(cardReader)); logger->info("= SmartCard = %\n", smartCard); /* Execute an APDU to get CPLC Data (cf. Global Platform Specification) */ const std::vector cplcApdu = HexUtil::toByteArray("80CA9F7F00"); - const std::vector apduResponses = - genericCardService->createCardTransaction(cardReader, smartCard) - ->prepareApdu(cplcApdu) - .prepareReleaseChannel() - .processApdusToHexStrings(); + const std::vector apduResponses + = GenericExtensionService::getInstance() + ->createCardTransaction(cardReader, smartCard) + ->prepareApdu(cplcApdu) + .processApdusToHexStrings(ChannelControl::CLOSE_AFTER); logger->info("CPLC Data: '%'\n", apduResponses[0]); diff --git a/Example_Service/src/main/UseCase2_ProtocolBasedSelection/Main_ProtocolBasedSelection_Pcsc.cpp b/Example_Service/src/main/UseCase2_ProtocolBasedSelection/Main_ProtocolBasedSelection_Pcsc.cpp index cb25824..d7ea631 100644 --- a/Example_Service/src/main/UseCase2_ProtocolBasedSelection/Main_ProtocolBasedSelection_Pcsc.cpp +++ b/Example_Service/src/main/UseCase2_ProtocolBasedSelection/Main_ProtocolBasedSelection_Pcsc.cpp @@ -1,57 +1,65 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" -#include "ConfigurableCardReader.h" - -/* Keyple Card Generic */ -#include "GenericCardSelectionAdapter.h" -#include "GenericExtensionService.h" - - /* Keyple Core Util */ -#include "LoggerFactory.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPluginFactoryBuilder.h" -#include "PcscReader.h" -#include "PcscSupportedContactlessProtocol.h" - -/* Keyple Cpp Example */ -#include "ConfigurationUtil.h" - -using namespace keyple::card::generic; -using namespace keyple::core::service; -using namespace keyple::core::util::cpp; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include + +#include "../common/ConfigurationUtil.hpp" + +#include "keyple/card/generic/GenericExtensionService.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ConfigurableCardReader.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +using keyple::card::generic::GenericExtensionService; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keypop::reader::CardReader; +using keypop::reader::ConfigurableCardReader; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::spi::SmartCard; /** *

Use Case Generic 2 – Protocol Based Selection (PC/SC)

* - *

We demonstrate here a selection of cards with the only condition being the type of - * communication protocol they use, in this case the Mifare Classic. Any card of the Mifare Classic - * type must lead to a "selected" status, any card using another protocol must be ignored.
+ *

We demonstrate here a selection of cards with the only condition being the + * type of ommunication protocol they use, in this case the Mifare Classic. Any + * card of the Mifare Classic type must lead to a "selected" status, any card + * using another protocol must be ignored.
* Note that in this case, no APDU "select application" is sent to the card. * *

Scenario:

* *
    - *
  • Check if a ISO 14443-4 card is in the reader, select a card (a Mifare Classic card is - * expected here). + *
  • Check if a ISO 14443-4 card is in the reader, select a card (a Mifare + * Classic card is expected here). *
  • Run a selection scenario with the MIFARE CLASSIC protocol filter. *
  • Output the collected smart card data (power-on data). *
@@ -62,89 +70,164 @@ using namespace keyple::plugin::pcsc; * * @since 2.0.0 */ -class Main_ProtocolBasedSelection_Pcsc {}; -const std::string MIFARE_CLASSIC = "MIFARE_CLASSIC"; -const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_ProtocolBasedSelection_Pcsc)); - -int main() -{ - /* Get the instance of the SmartCardService (singleton pattern) */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); - - /* - * Register the PcscPlugin with the SmartCardService, get the corresponding generic plugin in - * return. - */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); - - /* Get the generic card extension service */ - std::shared_ptr genericCardService = - GenericExtensionService::getInstance(); - - /* Verify that the extension's API level is consistent with the current service */ - smartCardService->checkCardExtension(genericCardService); - - /* Get the contactless reader whose name matches the provided regex */ - const std::string pcscContactlessReaderName = - ConfigurationUtil::getCardReaderName(plugin, - ConfigurationUtil::CONTACTLESS_READER_NAME_REGEX); - std::shared_ptr cardReader = plugin->getReader(pcscContactlessReaderName); - - /* Configure the reader with parameters suitable for contactless operations. */ - std::dynamic_pointer_cast( - plugin->getReaderExtension(typeid(PcscReader), pcscContactlessReaderName)) - ->setContactless(true) - .setIsoProtocol(PcscReader::IsoProtocol::T1) - .setSharingMode(PcscReader::SharingMode::SHARED); - std::dynamic_pointer_cast(cardReader) - ->activateProtocol(PcscSupportedContactlessProtocol::ISO_14443_4.getName(), - ConfigurationUtil::ISO_CARD_PROTOCOL); - std::dynamic_pointer_cast(cardReader) - ->activateProtocol(MIFARE_CLASSIC, MIFARE_CLASSIC); - - logger->info("=============== " \ - "UseCase Generic #2: protocol based card selection " \ - "==================\n"); +class Main_ProtocolBasedSelection_Pcsc { }; +const std::unique_ptr + logger(LoggerFactory::getLogger(typeid(Main_ProtocolBasedSelection_Pcsc))); - /* Check if a card is present in the reader */ - if (!cardReader->isCardPresent()) { - logger->error("No card is present in the reader\n"); - return 0; - } +static std::shared_ptr plugin; +static std::shared_ptr readerApiFactory; +static std::shared_ptr cardReader; + +static const std::string CONTACTLESS_READER_NAME_REGEX + = ".*ASK LoGO.*|.*Contactless.*|.*00 01.*"; +static const std::string ISO_CARD_PROTOCOL = "ISO_14443_4_CARD"; +static const std::string MIFARE_CLASSIC_PROTOCOL = "MIFARE_CLASSIC_CARD"; - logger->info("= #### Select the card if the protocol is '%'\n", MIFARE_CLASSIC); +/** + * Initializes the Keyple service. + * + *

Gets an instance of the smart card service, registers the PC/SC plugin, + * and prepares the reader API factory for use. + * + *

Retrieves the ReaderApiFactory. + */ +static void +initKeypleService() { + const auto smartCardService(SmartCardServiceProvider::getService()); + plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); + readerApiFactory = smartCardService->getReaderApiFactory(); +} + +/** + * Initializes the generic card extension service. + */ +static void +initGenericCardExtensionService() { + const auto genericExtensionService(GenericExtensionService::getInstance()); + SmartCardServiceProvider::getService()->checkCardExtension( + genericExtensionService); +} + +/** + * Configures and returns a card reader based on the provided parameters. + * + *

It finds the reader name by matching with a regular expression, then + * configures the reader with the specified settings. + * + * @param plugin The plugin used to interact with the card reader. + * @param readerNameRegex The regular expression to match the card reader's + * name. + * @param isContactless A boolean indicating whether the card reader is + * contactless. + * @param isoProtocol The ISO protocol used by the card reader. + * @param sharingMode The sharing mode of the PC/SC reader. + * @param physicalProtocolName The name of the protocol used by the reader to + * communicate with card. + * @param logicalProtocolName The name of the protocol known by the application. + * @return The configured card reader. + */ +static std::shared_ptr +getReader( + std::shared_ptr _plugin, + const std::string& readerNameRegex, + const bool isContactless, + const PcscReader::IsoProtocol isoProtocol, + const PcscReader::SharingMode sharingMode) { + const auto reader(_plugin->findReader(readerNameRegex)); + + auto pcscReader(std::dynamic_pointer_cast( + _plugin->getReaderExtension(typeid(PcscReader), reader->getName()))); + + pcscReader->setContactless(isContactless) + .setIsoProtocol(isoProtocol) + .setSharingMode(sharingMode); + + std::dynamic_pointer_cast(reader)->activateProtocol( + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ISO_CARD_PROTOCOL); + + std::dynamic_pointer_cast(reader)->activateProtocol( + PcscSupportedContactlessProtocol::MIFARE_CLASSIC.getName(), + MIFARE_CLASSIC_PROTOCOL); + + return reader; +} - /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); +/** + * Initializes the card reader with specific configurations. + * + *

Prepares the card reader using a predefined set of configurations, + * including the card reader name regex, ISO protocol, and sharing mode. + */ +static void +initCardReader() { + cardReader = getReader( + plugin, + CONTACTLESS_READER_NAME_REGEX, + true, + PcscReader::IsoProtocol::T1, + PcscReader::SharingMode::EXCLUSIVE); +} - /* Create a card selection using the generic card extension and specifying a Mifare filter. */ - std::shared_ptr cardSelection = genericCardService->createCardSelection(); - cardSelection->filterByCardProtocol(MIFARE_CLASSIC); +/** + * Selects any card for the transaction. + * + *

Creates a card selection manager, prepares the selection using no filter. + * + * @param reader The reader used to communicate with the card. + * @return The selected smart card ready for the transaction. + * @throws IllegalStateException if the selection of the application fails. + */ +static std::shared_ptr +selectCard(std::shared_ptr reader) { + auto cardSelectionManager(readerApiFactory->createCardSelectionManager()); + auto cardSelector(readerApiFactory->createBasicCardSelector()); + cardSelector->filterByCardProtocol(MIFARE_CLASSIC_PROTOCOL); + auto genericCardSelectionExtension( + GenericExtensionService::getInstance() + ->createGenericCardSelectionExtension()); - /* - * Prepare the selection by adding the created generic selection to the card selection scenario - */ - cardSelectionManager->prepareSelection(cardSelection); + cardSelectionManager->prepareSelection( + cardSelector, genericCardSelectionExtension); - /* Actual card communication: run the selection scenario */ - std::shared_ptr selectionResult = - cardSelectionManager->processCardSelectionScenario(cardReader); + std::shared_ptr selectionResult( + cardSelectionManager->processCardSelectionScenario(reader)); - /* Check the selection result */ if (selectionResult->getActiveSmartCard() == nullptr) { - logger->error("The selection of the card failed\n"); + throw new IllegalStateException("The selection of the card failed."); + } + + return selectionResult->getActiveSmartCard(); +} + +int +main() { + logger->info("= UseCase Generic #2: protocol based card selection " + "==================\n"); + + initKeypleService(); + initGenericCardExtensionService(); + initCardReader(); + + /* Check if a card is present in the reader */ + if (!cardReader->isCardPresent()) { + logger->error("No card is present in the reader.\n"); return 0; } - /* Get the SmartCard resulting of the selection */ - std::shared_ptr smartCard = selectionResult->getActiveSmartCard(); + logger->info( + "= #### Select the card if the protocol is '%'.\n", + MIFARE_CLASSIC_PROTOCOL); - logger->info("= SmartCard = %\n", smartCard); + std::shared_ptr smartCard(selectCard(cardReader)); + if (smartCard == nullptr) { + logger->error("The selection of the card failed.\n"); + return 0; + } - logger->info("= #### End of the generic card processing\n"); + logger->info("= SmartCard = %\n", smartCard); + logger->info("= #### End of the generic card processing.\n"); return 0; } diff --git a/Example_Service/src/main/UseCase3_AidBasedSelection/Main_AidBasedSelection_Pcsc.cpp b/Example_Service/src/main/UseCase3_AidBasedSelection/Main_AidBasedSelection_Pcsc.cpp index aaa35e5..9300f0b 100644 --- a/Example_Service/src/main/UseCase3_AidBasedSelection/Main_AidBasedSelection_Pcsc.cpp +++ b/Example_Service/src/main/UseCase3_AidBasedSelection/Main_AidBasedSelection_Pcsc.cpp @@ -1,58 +1,73 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" -#include "ConfigurableCardReader.h" - -/* Keyple Card Generic */ -#include "GenericExtensionService.h" - -/* Keyple Core Util */ -#include "ByteArrayUtil.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" - -/* Keyple Core Service */ -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPluginFactoryBuilder.h" -#include "PcscReader.h" -#include "PcscSupportedContactlessProtocol.h" - -/* Keyple Cpp Example */ -#include "ConfigurationUtil.h" - -using namespace keyple::card::generic; -using namespace keyple::core::service; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include + +#include "common/ConfigurationUtil.hpp" + +#include "keyple/card/generic/ChannelControl.hpp" +#include "keyple/card/generic/GenericExtensionService.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ConfigurableCardReader.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/selection/spi/SmartCard.hpp" + +using keyple::card::generic::ChannelControl; +using keyple::card::generic::GenericExtensionService; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keypop::reader::CardReader; +using keypop::reader::ConfigurableCardReader; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::selection::spi::SmartCard; /** *

Use Case Generic 3 – AID Based Selection (PC/SC)

* - *

We present here a selection of cards including the transmission of a "select application" APDU - * targeting a specific DF Name. Any card with an application whose DF Name starts with the provided - * AID should lead to a "selected" state, any card with another DF Name should be ignored. + *

We present here a selection of cards including the transmission of a + * "select application" APDU targeting a specific DF Name. Any card with an + * application whose DF Name starts with the provided AID should lead to a + * "selected" state, any card with another DF Name should be ignored. * *

Scenario:

* *
    - *
  • Check if a ISO 14443-4 card is in the reader, select a card with the specified AID (here - * the EMV PPSE AID). + *
  • Check if a ISO 14443-4 card is in the reader, select a card with the + * specified AID (here the EMV PPSE AID). *
  • Run a selection scenario with the DF Name filter. *
  • Output the collected smart card data (power-on data). *
@@ -63,47 +78,52 @@ using namespace keyple::plugin::pcsc; * * @since 2.0.0 */ -class Main_AidBasedSelection_Pcsc {}; -const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_AidBasedSelection_Pcsc)); +class Main_AidBasedSelection_Pcsc { }; +const std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_AidBasedSelection_Pcsc)); -int main() -{ +int +main() { /* Get the instance of the SmartCardService (singleton pattern) */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); /* - * Register the PcscPlugin with the SmartCardService, get the corresponding generic plugin in - * return. + * Register the PcscPlugin with the SmartCardService, get the corresponding + * generic plugin in return. */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); + std::shared_ptr plugin(smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build())); /* Get the generic card extension service */ - std::shared_ptr genericCardService = - GenericExtensionService::getInstance(); + std::shared_ptr genericCardService( + GenericExtensionService::getInstance()); - /* Verify that the extension's API level is consistent with the current service */ + /* + * Verify that the extension's API level is consistent with the current + * service + */ smartCardService->checkCardExtension(genericCardService); /* Get the contactless reader whose name matches the provided regex */ - const std::string pcscContactlessReaderName = - ConfigurationUtil::getCardReaderName(plugin, - ConfigurationUtil::CONTACTLESS_READER_NAME_REGEX); - std::shared_ptr cardReader = plugin->getReader(pcscContactlessReaderName); + std::shared_ptr cardReader( + plugin->findReader(ConfigurationUtil::CONTACTLESS_READER_NAME_REGEX)); - /* Configure the reader with parameters suitable for contactless operations. */ + /* + * Configure the reader with parameters suitable for contactless operations. + */ std::dynamic_pointer_cast( - plugin->getReaderExtension(typeid(PcscReader), pcscContactlessReaderName)) - ->setContactless(true) - .setIsoProtocol(PcscReader::IsoProtocol::T1) - .setSharingMode(PcscReader::SharingMode::SHARED); + plugin->getReaderExtension(typeid(PcscReader), cardReader->getName())) + ->setContactless(true) + .setIsoProtocol(PcscReader::IsoProtocol::T1) + .setSharingMode(PcscReader::SharingMode::SHARED); std::dynamic_pointer_cast(cardReader) - ->activateProtocol(PcscSupportedContactlessProtocol::ISO_14443_4.getName(), - ConfigurationUtil::ISO_CARD_PROTOCOL); + ->activateProtocol( + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ConfigurationUtil::ISO_CARD_PROTOCOL); - logger->info("=============== " \ - "UseCase Generic #3: AID based card selection " \ + logger->info("=============== " + "UseCase Generic #3: AID based card selection " "==================\n"); /* Check if a card is present in the reader */ @@ -112,25 +132,37 @@ int main() return 0; } - logger->info("= #### Select the card if its DF Name matches '%'\n", - ConfigurationUtil::AID_EMV_PPSE); + logger->info( + "= #### Select the card if its DF Name matches '%'\n", + ConfigurationUtil::AID_EMV_PPSE); + + auto readerApiFactory(smartCardService->getReaderApiFactory()); /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + std::shared_ptr cardSelectionManager + = readerApiFactory->createCardSelectionManager(); - /* Create a card selection using the generic card extension and specifying a DfName filter. */ - std::shared_ptr cardSelection = genericCardService->createCardSelection(); - cardSelection->filterByDfName(ConfigurationUtil::AID_EMV_PPSE); + /* + * Create a card selection using the generic card extension and specifying a + * DfName filter. + */ + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(ConfigurationUtil::AID_EMV_PPSE); /* - * Prepare the selection by adding the created generic selection to the card selection scenario + * Prepare the selection by adding the created generic selection to the card + * selection scenario. */ - cardSelectionManager->prepareSelection(cardSelection); + auto genericCardSelectionExtension( + GenericExtensionService::getInstance() + ->createGenericCardSelectionExtension()); + cardSelectionManager->prepareSelection( + cardSelector, genericCardSelectionExtension); /* Actual card communication: run the selection scenario */ - std::shared_ptr selectionResult = - cardSelectionManager->processCardSelectionScenario(cardReader); + std::shared_ptr selectionResult + = cardSelectionManager->processCardSelectionScenario(cardReader); /* Check the selection result */ if (selectionResult->getActiveSmartCard() == nullptr) { @@ -139,7 +171,8 @@ int main() } /* Get the SmartCard resulting of the selection */ - std::shared_ptr smartCard = selectionResult->getActiveSmartCard(); + std::shared_ptr smartCard + = selectionResult->getActiveSmartCard(); logger->info("= SmartCard = %\n", smartCard); diff --git a/Example_Service/src/main/UseCase4_ScheduledSelection/CardReaderObserver.cpp b/Example_Service/src/main/UseCase4_ScheduledSelection/CardReaderObserver.cpp index acdb18c..2cf9b50 100644 --- a/Example_Service/src/main/UseCase4_ScheduledSelection/CardReaderObserver.cpp +++ b/Example_Service/src/main/UseCase4_ScheduledSelection/CardReaderObserver.cpp @@ -1,66 +1,83 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ -#include "CardReaderObserver.h" +#include "CardReaderObserver.hpp" -using namespace keyple::core::service; +#include +#include -CardReaderObserver::CardReaderObserver(std::shared_ptr observableCardReader, - std::shared_ptr cardSelectionManager) -: mObservableCardReader(observableCardReader), mCardSelectionManager(cardSelectionManager) {} +#include "keypop/reader/selection/spi/SmartCard.hpp" -void CardReaderObserver::onReaderEvent(const std::shared_ptr event) -{ +using keypop::reader::selection::spi::SmartCard; + +CardReaderObserver::CardReaderObserver( + std::shared_ptr observableCardReader, + std::shared_ptr cardSelectionManager) +: mObservableCardReader(observableCardReader) +, mCardSelectionManager(cardSelectionManager) { +} + +void +CardReaderObserver::onReaderEvent( + const std::shared_ptr event) { switch (event->getType()) { - case CardReaderEvent::CARD_MATCHED: - { + case CardReaderEvent::CARD_MATCHED: { /* The selection has one target, get the result at index 0 */ - const std::shared_ptr smartCard = - mCardSelectionManager->parseScheduledCardSelectionsResponse( - event->getScheduledCardSelectionsResponse()) - ->getActiveSmartCard(); + const std::shared_ptr smartCard( + mCardSelectionManager + ->parseScheduledCardSelectionsResponse( + event->getScheduledCardSelectionsResponse()) + ->getActiveSmartCard()); - mLogger->info("Observer notification: the selection of the card has succeeded and return " \ - "the SmartCard = %\n", - smartCard); + mLogger->info( + "Observer notification: the selection of the card has succeeded " + "and return the SmartCard = %\n", + smartCard); mLogger->info("= #### End of the card processing\n"); - } - break; + } break; case CardReaderEvent::CARD_INSERTED: - mLogger->error("CARD_INSERTED event: should not have occurred due to the MATCHED_ONLY " \ - "selection mode\n"); + mLogger->error( + "CARD_INSERTED event: should not have occurred due to the " + "MATCHED_ONLY selection mode\n"); break; case CardReaderEvent::CARD_REMOVED: - mLogger->trace("There is no card inserted anymore. Return to the waiting state...\n"); + mLogger->trace( + "There is no card inserted anymore. Return to the waiting " + "state...\n"); break; default: break; } - if (event->getType() == CardReaderEvent::CARD_INSERTED || - event->getType() == CardReaderEvent::CARD_MATCHED) { - + if (event->getType() == CardReaderEvent::CARD_INSERTED + || event->getType() == CardReaderEvent::CARD_MATCHED) { /* - * Informs the underlying layer of the end of the card processing, in order to manage the - * removal sequence. - */ + * Informs the underlying layer of the end of the card processing, in + * order to manage the removal sequence. + */ mObservableCardReader->finalizeCardProcessing(); } } -void CardReaderObserver::onReaderObservationError(const std::string& pluginName, - const std::string& readerName, - const std::shared_ptr e) -{ - mLogger->error("An exception occurred in plugin '%', reader '%'\n", pluginName, readerName, e); -} \ No newline at end of file +void +CardReaderObserver::onReaderObservationError( + const std::string& pluginName, + const std::string& readerName, + const std::shared_ptr e) { + mLogger->error( + "An exception occurred in plugin '%', reader '%'\n", + pluginName, + readerName, + e); +} diff --git a/Example_Service/src/main/UseCase4_ScheduledSelection/CardReaderObserver.h b/Example_Service/src/main/UseCase4_ScheduledSelection/CardReaderObserver.h deleted file mode 100644 index 65e593d..0000000 --- a/Example_Service/src/main/UseCase4_ScheduledSelection/CardReaderObserver.h +++ /dev/null @@ -1,85 +0,0 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -#pragma once - -/* Calypsonet Terminal Reader */ -#include "CardReaderObservationExceptionHandlerSpi.h" -#include "CardReaderObserverSpi.h" -#include "CardSelectionManager.h" -#include "ObservableCardReader.h" - -/* Keyple Core Util */ -#include "LoggerFactory.h" - -/* Keyple Core Service */ -#include "Reader.h" - -using namespace calypsonet::terminal::reader::selection; -using namespace calypsonet::terminal::reader::spi; -using namespace keyple::core::service; -using namespace keyple::core::util::cpp; - -/** - * (package-private)
- * Implements the reader observation SPIs.
- * A reader Observer to handle card events such as CARD_INSERTED, CARD_MATCHED, CARD_REMOVED - * - * @since 2.0.0.0 - */ -class CardReaderObserver : -public CardReaderObserverSpi, -public CardReaderObservationExceptionHandlerSpi { -public: - /** - * - */ - CardReaderObserver(std::shared_ptr observableCardReader, - std::shared_ptr cardSelectionManager); - - /** - * - */ - virtual ~CardReaderObserver() = default; - - /** - * {@inheritDoc} - * - * @since 2.0.0 - */ - void onReaderEvent(const std::shared_ptr event) override; - - /** - * {@inheritDoc} - * - * @since 2.0.0 - */ - void onReaderObservationError(const std::string& pluginName, - const std::string& readerName, - const std::shared_ptr e) override; - -private: - /** - * - */ - const std::unique_ptr mLogger = LoggerFactory::getLogger(typeid(CardReaderObserver)); - - /** - * - */ - std::shared_ptr mObservableCardReader; - - /** - * - */ - std::shared_ptr mCardSelectionManager; -}; diff --git a/Example_Service/src/main/UseCase4_ScheduledSelection/CardReaderObserver.hpp b/Example_Service/src/main/UseCase4_ScheduledSelection/CardReaderObserver.hpp new file mode 100644 index 0000000..d82f964 --- /dev/null +++ b/Example_Service/src/main/UseCase4_ScheduledSelection/CardReaderObserver.hpp @@ -0,0 +1,87 @@ +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#pragma once + +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keypop/reader/CardReaderEvent.hpp" +#include "keypop/reader/ObservableCardReader.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/spi/CardReaderObservationExceptionHandlerSpi.hpp" +#include "keypop/reader/spi/CardReaderObserverSpi.hpp" + +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keypop::reader::CardReaderEvent; +using keypop::reader::ObservableCardReader; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::spi::CardReaderObservationExceptionHandlerSpi; +using keypop::reader::spi::CardReaderObserverSpi; + +/** + * Implements the reader observation SPIs.
+ * A reader Observer to handle card events such as CARD_INSERTED, CARD_MATCHED, + * CARD_REMOVED + * + * @since 2.0.0.0 + */ +class CardReaderObserver : public CardReaderObserverSpi, + public CardReaderObservationExceptionHandlerSpi { +public: + /** + * + */ + CardReaderObserver( + std::shared_ptr observableCardReader, + std::shared_ptr cardSelectionManager); + + /** + * + */ + virtual ~CardReaderObserver() = default; + + /** + * {@inheritDoc} + * + * @since 2.0.0 + */ + void onReaderEvent(const std::shared_ptr event) override; + + /** + * {@inheritDoc} + * + * @since 2.0.0 + */ + void onReaderObservationError( + const std::string& contextInfo, + const std::string& readerName, + const std::shared_ptr e) override; + +private: + /** + * + */ + const std::unique_ptr mLogger + = LoggerFactory::getLogger(typeid(CardReaderObserver)); + + /** + * + */ + std::shared_ptr mObservableCardReader; + + /** + * + */ + std::shared_ptr mCardSelectionManager; +}; diff --git a/Example_Service/src/main/UseCase4_ScheduledSelection/Main_ScheduledSelection_Pcsc.cpp b/Example_Service/src/main/UseCase4_ScheduledSelection/Main_ScheduledSelection_Pcsc.cpp index 4462b14..2002137 100644 --- a/Example_Service/src/main/UseCase4_ScheduledSelection/Main_ScheduledSelection_Pcsc.cpp +++ b/Example_Service/src/main/UseCase4_ScheduledSelection/Main_ScheduledSelection_Pcsc.cpp @@ -1,55 +1,64 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "ConfigurableCardReader.h" - -/* Keyple Card Generic */ -#include "GenericCardSelectionAdapter.h" -#include "GenericExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "ObservableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Plugin Pcsc */ -#include "PcscSupportedContactlessProtocol.h" -#include "PcscPluginFactoryBuilder.h" -#include "PcscReader.h" - -/* Keyple Cpp Example */ -#include "ConfigurationUtil.h" -#include "CardReaderObserver.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::generic; -using namespace keyple::core::service; -using namespace keyple::core::util::cpp; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include + +#include "CardReaderObserver.hpp" +#include "common/ConfigurationUtil.hpp" + +#include "keyple/card/generic/GenericExtensionService.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/reader/ConfigurableCardReader.hpp" +#include "keypop/reader/ObservableCardReader.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" + +using keyple::card::generic::GenericExtensionService; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keypop::reader::ConfigurableCardReader; +using keypop::reader::ObservableCardReader; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::IsoCardSelector; /** *

Use Case Generic 4 – Scheduled Selection (PC/SC)

* - *

We present here a selection of ISO-14443-4 cards including the transmission of a "select - * application" APDU targeting EMV banking cards (AID PPSE). Any contactless EMV card should lead to + *

We present here a selection of ISO-14443-4 cards including the + * transmission of a "select application" APDU targeting EMV banking cards + * (AID PPSE). Any contactless EMV card should lead to * a "selected" state, any card with another DF Name should be ignored. * *

Scenario:

* *
    - *
  • Schedule a selection scenario over an observable reader to target a specific card (here a - * EMV contactless card). + *
  • Schedule a selection scenario over an observable reader to target a + * specific card (here a EMV contactless card). *
  • Start the observation and wait for a card. *
  • Within the reader event handler: *
      @@ -58,90 +67,103 @@ using namespace keyple::plugin::pcsc; *
    *
* - * All results are logged with slf4j. - * *

Any unexpected behavior will result in runtime exceptions. */ -class Main_ScheduledSelection_Pcsc {}; -const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_ScheduledSelection_Pcsc)); +class Main_ScheduledSelection_Pcsc { }; +const std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_ScheduledSelection_Pcsc)); + +int +main() { + logger->setLoggerLevel(Logger::Level::logTrace); -int main() -{ /* Get the instance of the SmartCardService (singleton pattern) */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); /* - * Register the PcscPlugin with the SmartCardService, get the corresponding generic plugin in - * return. + * Register the PcscPlugin with the SmartCardService, get the corresponding + * generic plugin in return. */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); + std::shared_ptr plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); /* Get the generic card extension service */ - std::shared_ptr genericCardService = - GenericExtensionService::getInstance(); + std::shared_ptr genericCardService( + GenericExtensionService::getInstance()); - /* Verify that the extension's API level is consistent with the current service. */ + /* + * Verify that the extension's API level is consistent with the current + * service. + */ smartCardService->checkCardExtension(genericCardService); /* Get the contactless reader whose name matches the provided regex */ - const std::string pcscContactlessReaderName = - ConfigurationUtil::getCardReaderName(plugin, - ConfigurationUtil::CONTACTLESS_READER_NAME_REGEX); - auto observableCardReader = - std::dynamic_pointer_cast( - plugin->getReader(pcscContactlessReaderName)); - - /* Configure the reader with parameters suitable for contactless operations. */ + auto observableCardReader = std::dynamic_pointer_cast( + plugin->findReader(ConfigurationUtil::CONTACTLESS_READER_NAME_REGEX)); + + /* + * Configure the reader with parameters suitable for contactless operations. + */ std::dynamic_pointer_cast( - plugin->getReaderExtension(typeid(PcscReader), pcscContactlessReaderName)) - ->setContactless(true) - .setIsoProtocol(PcscReader::IsoProtocol::T1) - .setSharingMode(PcscReader::SharingMode::SHARED); + plugin->getReaderExtension( + typeid(PcscReader), observableCardReader->getName())) + ->setContactless(true) + .setIsoProtocol(PcscReader::IsoProtocol::T1) + .setSharingMode(PcscReader::SharingMode::SHARED); + std::dynamic_pointer_cast(observableCardReader) - ->activateProtocol(PcscSupportedContactlessProtocol::ISO_14443_4.getName(), - ConfigurationUtil::ISO_CARD_PROTOCOL); + ->activateProtocol( + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ConfigurationUtil::ISO_CARD_PROTOCOL); - logger->info("=============== " \ - "UseCase Generic #4: scheduled AID based selection " \ + logger->info("=============== " + "UseCase Generic #4: scheduled AID based selection " "===============\n"); - logger->info("= #### Select application with AID = '%'\n", ConfigurationUtil::AID_EMV_PPSE); + logger->info( + "= #### Select application with AID = '%'\n", + ConfigurationUtil::AID_EMV_PPSE); + + std::shared_ptr readerApiFactory( + smartCardService->getReaderApiFactory()); /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + std::shared_ptr cardSelectionManager + = readerApiFactory->createCardSelectionManager(); + /* Create a card selection using the generic card extension */ - std::shared_ptr cardSelection = genericCardService->createCardSelection(); - cardSelection->filterByCardProtocol(ConfigurationUtil::ISO_CARD_PROTOCOL); - cardSelection->filterByDfName(ConfigurationUtil::AID_EMV_PPSE); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByCardProtocol(ConfigurationUtil::ISO_CARD_PROTOCOL); + cardSelector->filterByDfName(ConfigurationUtil::AID_EMV_PPSE); /* - * Prepare the selection by adding the created generic selection to the card selection scenario + * Prepare the selection by adding the created generic selection to the card + * selection scenario */ - cardSelectionManager->prepareSelection(cardSelection); + cardSelectionManager->prepareSelection( + cardSelector, + GenericExtensionService::getInstance() + ->createGenericCardSelectionExtension()); /* Schedule the selection scenario */ cardSelectionManager->scheduleCardSelectionScenario( observableCardReader, - ObservableCardReader::DetectionMode::REPEATING, ObservableCardReader::NotificationMode::MATCHED_ONLY); /* Create and add an observer */ - auto cardReaderObserver = - std::make_shared(observableCardReader, cardSelectionManager); - observableCardReader->setReaderObservationExceptionHandler(cardReaderObserver); + auto cardReaderObserver = std::make_shared( + observableCardReader, cardSelectionManager); + observableCardReader->setReaderObservationExceptionHandler( + cardReaderObserver); observableCardReader->addObserver(cardReaderObserver); - observableCardReader->startCardDetection(ObservableCardReader::DetectionMode::REPEATING); - - logger->info("= #### Wait for a card. The AID based selection scenario will be processed as " \ - "soon as a card is detected\n"); - - /* Unregister plugin */ - smartCardService->unregisterPlugin(plugin->getName()); + observableCardReader->startCardDetection( + ObservableCardReader::DetectionMode::REPEATING); - logger->info("Exit program\n"); + logger->info( + "= #### Wait for a card. The AID based selection scenario will be " + "processed as soon as a card is detected\n"); - return 0; + while (true); } diff --git a/Example_Service/src/main/UseCase5_SequentialMultiSelection/Main_SequentialMultiSelection_Pcsc.cpp b/Example_Service/src/main/UseCase5_SequentialMultiSelection/Main_SequentialMultiSelection_Pcsc.cpp index 10122b2..9606a1a 100644 --- a/Example_Service/src/main/UseCase5_SequentialMultiSelection/Main_SequentialMultiSelection_Pcsc.cpp +++ b/Example_Service/src/main/UseCase5_SequentialMultiSelection/Main_SequentialMultiSelection_Pcsc.cpp @@ -1,62 +1,78 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" -#include "ConfigurableCardReader.h" - -/* Keyple Card Generic */ -#include "GenericCardSelectionAdapter.h" -#include "GenericExtensionService.h" - -/* Keyple Core Util */ -#include "HexUtil.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "ObservableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPluginFactoryBuilder.h" -#include "PcscReader.h" -#include "PcscSupportedContactlessProtocol.h" - -/* Keyple Cpp Example */ -#include "ConfigurationUtil.h" - -using namespace keyple::card::generic; -using namespace keyple::core::service; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::core::util::cpp::exception; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include + +#include "common/ConfigurationUtil.hpp" + +#include "keyple/card/generic/GenericCardSelectionExtension.hpp" +#include "keyple/card/generic/GenericExtensionService.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ConfigurableCardReader.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/FileOccurrence.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/selection/spi/IsoSmartCard.hpp" + +using keyple::card::generic::GenericCardSelectionExtension; +using keyple::card::generic::GenericExtensionService; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keypop::reader::CardReader; +using keypop::reader::ConfigurableCardReader; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::FileOccurrence; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::selection::spi::IsoSmartCard; /** - *

Use Case Generic 5 – Sequential selections based on an AID prefix (PC/SC)

+ *

Use Case Generic 5 – Sequential selections based on an AID prefix + * (PC/SC)

* - *

We demonstrate here the selection of two applications in a single card, with both applications - * selected sequentially using the same AID and the "FIRST" and "NEXT" navigation options.
- * The result of the first selection is available to the application before the second selection is - * executed. + *

We demonstrate here the selection of two applications in a single card, + * with both applications selected sequentially using the same AID and the + * "FIRST" and "NEXT" navigation options.
+ * The result of the first selection is available to the application before the + * second selection is executed. * *

Scenario:

* *
    - *
  • Check if a ISO 14443-4 card is in the reader, select a card (here a card having two - * applications whose DF Names are prefixed by a specific AID [see AID_KEYPLE_PREFIX]). + *
  • Check if a ISO 14443-4 card is in the reader, select a card (here a + * card having two applications whose DF Names are prefixed by a specific + * AID [see AID_KEYPLE_PREFIX]). *
  • Run an AID based application selection scenario (first occurrence). *
  • Output collected smart card data (FCI and power-on data). *
  • Run an AID based application selection scenario (next occurrence). @@ -69,126 +85,149 @@ using namespace keyple::plugin::pcsc; * * @since 2.0.0 */ -class Main_SequentialMultiSelection_Pcsc {}; -const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_SequentialMultiSelection_Pcsc)); +class Main_SequentialMultiSelection_Pcsc { }; +const std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_SequentialMultiSelection_Pcsc)); /** - * Performs the selection for the provided reader and logs its result. - * - *

    The card selection manager must have been previously assigned a selection case. - * - * @param cardReader The reader. - * @param cardSelectionsService The card selection manager. - * @param index An int indicating the selection rank. - */ -static void doAndAnalyseSelection(std::shared_ptr cardReader, - std::shared_ptr cardSelectionsService, - const int index) -{ - std::shared_ptr cardSelectionsResult = - cardSelectionsService->processCardSelectionScenario(cardReader); + * Performs the selection for the provided reader and logs its result. + * + *

    The card selection manager must have been previously assigned a + * selection case. + * + * @param cardReader The reader. + * @param cardSelectionsService The card selection manager. + * @param index An int indicating the selection rank. + */ +static void +doAndAnalyseSelection( + std::shared_ptr cardReader, + std::shared_ptr cardSelectionsService, + const int index) { + std::shared_ptr cardSelectionsResult( + cardSelectionsService->processCardSelectionScenario(cardReader)); + if (cardSelectionsResult->getActiveSmartCard() != nullptr) { - std::shared_ptr smartCard = cardSelectionsResult->getActiveSmartCard(); + std::shared_ptr isoSmartCard( + std::dynamic_pointer_cast( + cardSelectionsResult->getActiveSmartCard())); logger->info("The card matched the selection %\n", index); - const std::string& powerOnData = smartCard->getPowerOnData(); - const std::string selectApplicationResponse = - HexUtil::toHex(smartCard->getSelectApplicationResponse()); - - logger->info("Selection status for case %: \n" \ - "\t\tpower-on data: %\n" \ - "\t\tSelect Application response: %\n", - index, - powerOnData, - selectApplicationResponse); + const std::string& powerOnData = isoSmartCard->getPowerOnData(); + const std::string selectApplicationResponse + = HexUtil::toHex(isoSmartCard->getSelectApplicationResponse()); + + logger->info( + "Selection status for case %: \n" + "\t\tpower-on data: %\n" + "\t\tSelect Application response: %\n", + index, + powerOnData, + selectApplicationResponse); } else { logger->info("The selection did not match for case %\n", index); } } -int main() -{ +int +main() { logger->setLoggerLevel(Logger::Level::logTrace); /* Get the instance of the SmartCardService (singleton pattern) */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); /* - * Register the PcscPlugin with the SmartCardService, get the corresponding generic plugin in - * return. + * Register the PcscPlugin with the SmartCardService, get the corresponding + * generic plugin in return. */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); + std::shared_ptr plugin = smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build()); /* Get the generic card extension service */ - std::shared_ptr genericCardService = - GenericExtensionService::getInstance(); + std::shared_ptr genericCardService + = GenericExtensionService::getInstance(); - /* Verify that the extension's API level is consistent with the current service */ + /* + * Verify that the extension's API level is consistent with the current + * service. + */ smartCardService->checkCardExtension(genericCardService); /* Get the contactless reader whose name matches the provided regex */ - const std::string pcscContactlessReaderName = - ConfigurationUtil::getCardReaderName(plugin, - ConfigurationUtil::CONTACTLESS_READER_NAME_REGEX); - std::shared_ptr cardReader = plugin->getReader(pcscContactlessReaderName); + std::shared_ptr cardReader( + plugin->findReader(ConfigurationUtil::CONTACTLESS_READER_NAME_REGEX)); - /* Configure the reader with parameters suitable for contactless operations. */ + /* + * Configure the reader with parameters suitable for contactless operations. + */ std::dynamic_pointer_cast( - plugin->getReaderExtension(typeid(PcscReader), pcscContactlessReaderName)) - ->setContactless(true) - .setIsoProtocol(PcscReader::IsoProtocol::T1) - .setSharingMode(PcscReader::SharingMode::SHARED); + plugin->getReaderExtension(typeid(PcscReader), cardReader->getName())) + ->setContactless(true) + .setIsoProtocol(PcscReader::IsoProtocol::T1) + .setSharingMode(PcscReader::SharingMode::SHARED); std::dynamic_pointer_cast(cardReader) - ->activateProtocol(PcscSupportedContactlessProtocol::ISO_14443_4.getName(), - ConfigurationUtil::ISO_CARD_PROTOCOL); + ->activateProtocol( + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ConfigurationUtil::ISO_CARD_PROTOCOL); - logger->info("=============== " \ - "UseCase Generic #5: sequential selections based on an AID prefix " \ + logger->info("=============== " + "UseCase Generic #5: sequential selections based on an AID " + "prefix " "==============="); /* Check if a card is present in the reader */ if (!cardReader->isCardPresent()) { - throw IllegalStateException("No card is present in the reader."); + throw IllegalStateException("No card is present in the reader."); } - logger->info("= #### Select application with AID = '%'\n", - ConfigurationUtil::AID_KEYPLE_PREFIX); + logger->info( + "= #### Select application with AID = '%'\n", + ConfigurationUtil::AID_KEYPLE_PREFIX); - /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + std::shared_ptr readerApiFactory( + smartCardService->getReaderApiFactory()); + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); /* - * AID based selection: get the first application occurrence matching the AID, keep the - * physical channel open + * AID based selection: get the first application occurrence matching the + * AID, keep the physical channel open */ - std::shared_ptr cardSelection = genericCardService->createCardSelection(); - cardSelection->filterByDfName(ConfigurationUtil::AID_KEYPLE_PREFIX); - cardSelection->setFileOccurrence(GenericCardSelection::FileOccurrence::FIRST); + std::shared_ptr cardSelector( + readerApiFactory->createIsoCardSelector()); + cardSelector->filterByDfName(ConfigurationUtil::AID_KEYPLE_PREFIX); + cardSelector->setFileOccurrence(FileOccurrence::FIRST); + + std::shared_ptr genericCardSelectionExtension + = GenericExtensionService::getInstance() + ->createGenericCardSelectionExtension(); /* - * Prepare the selection by adding the created generic selection to the card selection scenario + * Prepare the selection by adding the created generic selection to the card + * selection scenario. */ - cardSelectionManager->prepareSelection(cardSelection); + cardSelectionManager->prepareSelection( + cardSelector, genericCardSelectionExtension); /* Do the selection and display the result */ doAndAnalyseSelection(cardReader, cardSelectionManager, 1); /* - * New selection: get the next application occurrence matching the same AID, close the - * physical channel after + * New selection: get the next application occurrence matching the same AID, + * Close the physical channel after. */ - cardSelection = genericCardService->createCardSelection(); - cardSelection->filterByDfName(ConfigurationUtil::AID_KEYPLE_PREFIX); - cardSelection->setFileOccurrence(GenericCardSelection::FileOccurrence::NEXT); + cardSelector = readerApiFactory->createIsoCardSelector(); + cardSelector->filterByDfName(ConfigurationUtil::AID_KEYPLE_PREFIX); + cardSelector->setFileOccurrence(FileOccurrence::NEXT); /* - * Prepare the selection by adding the created generic selection to the card selection scenario. + * Prepare the selection by adding the created generic selection to the card + * selection scenario. */ - cardSelectionManager->prepareSelection(cardSelection); + cardSelectionManager->prepareSelection( + cardSelector, genericCardSelectionExtension); /* Close the channel after the selection */ cardSelectionManager->prepareReleaseChannel(); diff --git a/Example_Service/src/main/UseCase6_GroupedMultiSelection/Main_GroupedMultiSelection_Pcsc.cpp b/Example_Service/src/main/UseCase6_GroupedMultiSelection/Main_GroupedMultiSelection_Pcsc.cpp index dca0333..595d540 100644 --- a/Example_Service/src/main/UseCase6_GroupedMultiSelection/Main_GroupedMultiSelection_Pcsc.cpp +++ b/Example_Service/src/main/UseCase6_GroupedMultiSelection/Main_GroupedMultiSelection_Pcsc.cpp @@ -1,68 +1,80 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" -#include "ConfigurableCardReader.h" - -/* Keyple Core Util */ -#include "HexUtil.h" -#include "IllegalStateException.h" -#include "LoggerFactory.h" - -/* Keyple Card Generic */ -#include "GenericCardSelectionAdapter.h" -#include "GenericExtensionService.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "ObservableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPluginFactoryBuilder.h" -#include "PcscReader.h" -#include "PcscSupportedContactlessProtocol.h" - -/* Keyple Cpp Example */ -#include "ConfigurationUtil.h" - -/* Calypsonet Terminal Reader */ -#include "CardSelectionManager.h" - -using namespace calypsonet::terminal::reader; -using namespace calypsonet::terminal::reader::selection; -using namespace keyple::card::generic; -using namespace keyple::core::service; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::plugin::pcsc; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include + +#include "common/ConfigurationUtil.hpp" + +#include "keyple/card/generic/GenericCardSelectionExtension.hpp" +#include "keyple/card/generic/GenericExtensionService.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/IllegalStateException.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ConfigurableCardReader.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/CardSelectionManager.hpp" +#include "keypop/reader/selection/CardSelectionResult.hpp" +#include "keypop/reader/selection/FileOccurrence.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/selection/spi/IsoSmartCard.hpp" + +using keyple::card::generic::GenericCardSelectionExtension; +using keyple::card::generic::GenericExtensionService; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::IllegalStateException; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keypop::reader::CardReader; +using keypop::reader::ConfigurableCardReader; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::CardSelectionManager; +using keypop::reader::selection::CardSelectionResult; +using keypop::reader::selection::FileOccurrence; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::selection::spi::IsoSmartCard; /** - *

    Use Case Generic 6 – Grouped selections based on an AID prefix (PC/SC)

    + *

    Use Case Generic 6 – Grouped selections based on an AID prefix + * (PC/SC)

    * - *

    We demonstrate here the selection of two applications in a single card, with both applications - * selected using the same AID and the "FIRST" and "NEXT" navigation options but grouped in the same - * selection process.
    - * Both selection results are available in the {@link CardSelectionResult} object returned by the - * execution of the selection scenario. + *

    We demonstrate here the selection of two applications in a single card, + * with both applications selected using the same AID and the "FIRST" and "NEXT" + * navigation options but grouped in the same selection process.
    + * Both selection results are available in the CardSelectionResult object + * returned by the execution of the selection scenario. * *

    Scenario:

    * *
      - *
    • Check if a ISO 14443-4 card is in the reader, select a card (here a card having two - * applications whose DF Names are prefixed by a specific AID [see AID_KEYPLE_PREFIX]). - *
    • Run a double AID based application selection scenario (first and next occurrence). + *
    • Check if a ISO 14443-4 card is in the reader, select a card (here a + * card having two applications whose DF Names are prefixed by a specific + * AID [see AID_KEYPLE_PREFIX]). + *
    • Run a double AID based application selection scenario (first and next + * occurrence). *
    • Output collected of all smart cards data (FCI and power-on data). *
    * @@ -72,107 +84,129 @@ using namespace keyple::plugin::pcsc; * * @since 2.0.0 */ -class Main_GroupedMultiSelection_Pcsc {}; -const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_GroupedMultiSelection_Pcsc)); +class Main_GroupedMultiSelection_Pcsc { }; +const std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_GroupedMultiSelection_Pcsc)); -int main() -{ +int +main() { /* Get the instance of the SmartCardService (singleton pattern) */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); /* - * Register the PcscPlugin with the SmartCardService, get the corresponding generic plugin in - * return. + * Register the PcscPlugin with the SmartCardService, get the corresponding + * generic plugin in return. */ - std::shared_ptr plugin = - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build()); + std::shared_ptr plugin(smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build())); /* Get the generic card extension service */ - std::shared_ptr genericCardService = - GenericExtensionService::getInstance(); + std::shared_ptr genericCardService + = GenericExtensionService::getInstance(); - /* Verify that the extension's API level is consistent with the current service */ + /* + * Verify that the extension's API level is consistent with the current + * service. + */ smartCardService->checkCardExtension(genericCardService); /* Get the contactless reader whose name matches the provided regex */ - const std::string pcscContactlessReaderName = - ConfigurationUtil::getCardReaderName(plugin, - ConfigurationUtil::CONTACTLESS_READER_NAME_REGEX); - std::shared_ptr cardReader = plugin->getReader(pcscContactlessReaderName); + std::shared_ptr cardReader( + plugin->findReader(ConfigurationUtil::CONTACTLESS_READER_NAME_REGEX)); - /* Configure the reader with parameters suitable for contactless operations. */ + /* + * Configure the reader with parameters suitable for contactless operations. + */ std::dynamic_pointer_cast( - plugin->getReaderExtension(typeid(PcscReader), pcscContactlessReaderName)) - ->setContactless(true) - .setIsoProtocol(PcscReader::IsoProtocol::T1) - .setSharingMode(PcscReader::SharingMode::SHARED); + plugin->getReaderExtension(typeid(PcscReader), cardReader->getName())) + ->setContactless(true) + .setIsoProtocol(PcscReader::IsoProtocol::T1) + .setSharingMode(PcscReader::SharingMode::SHARED); std::dynamic_pointer_cast(cardReader) - ->activateProtocol(PcscSupportedContactlessProtocol::ISO_14443_4.getName(), - ConfigurationUtil::ISO_CARD_PROTOCOL); + ->activateProtocol( + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ConfigurationUtil::ISO_CARD_PROTOCOL); - logger->info("=============== " \ - "UseCase Generic #6: Grouped selections based on an AID prefix " \ + logger->info("=============== " + "UseCase Generic #6: Grouped selections based on an AID " + "prefix " "===============\n"); /* Check if a card is present in the reader */ if (!cardReader->isCardPresent()) { - throw IllegalStateException("No card is present in the reader."); + throw IllegalStateException("No card is present in the reader."); } - logger->info("= #### Select application with AID = '%'\n", - ConfigurationUtil::AID_KEYPLE_PREFIX); + logger->info( + "= #### Select application with AID = '%'\n", + ConfigurationUtil::AID_KEYPLE_PREFIX); - /* Get the core card selection manager */ - std::shared_ptr cardSelectionManager = - smartCardService->createCardSelectionManager(); + std::shared_ptr readerApiFactory( + smartCardService->getReaderApiFactory()); + std::shared_ptr cardSelectionManager( + readerApiFactory->createCardSelectionManager()); - /* Set the multiple selection mode */ - cardSelectionManager->setMultipleSelectionMode(); + std::shared_ptr genericCardSelectionExtension + = GenericExtensionService::getInstance() + ->createGenericCardSelectionExtension(); /* - * First selection: get the first application occurrence matching the AID, keep the - * physical channel open. - * Prepare the selection by adding the created generic selection to the card selection scenario. + * AID based selection: get the first application occurrence matching the + * AID, keep the physical channel open. + * Prepare the selection by adding the created generic selection to the card + * selection scenario. */ - std::shared_ptr cardSelection = genericCardService->createCardSelection(); - cardSelection->filterByDfName(ConfigurationUtil::AID_KEYPLE_PREFIX); - cardSelection->setFileOccurrence(GenericCardSelection::FileOccurrence::FIRST); - cardSelectionManager->prepareSelection(cardSelection); + std::shared_ptr cardSelector1( + readerApiFactory->createIsoCardSelector()); + cardSelector1->filterByDfName(ConfigurationUtil::AID_KEYPLE_PREFIX); + cardSelector1->setFileOccurrence(FileOccurrence::FIRST); + + /* + * Prepare the selection by adding the created generic selection to the card + * selection scenario. + */ + cardSelectionManager->prepareSelection( + cardSelector1, genericCardSelectionExtension); + + std::shared_ptr cardSelector2( + readerApiFactory->createIsoCardSelector()); + cardSelector1->filterByDfName(ConfigurationUtil::AID_KEYPLE_PREFIX); + cardSelector1->setFileOccurrence(FileOccurrence::NEXT); /* - * Second selection: get the next application occurrence matching the same AID, close the - * physical channel after. - * Prepare the selection by adding the created generic selection to the card selection scenario. + * Prepare the selection by adding the created generic selection to the card + * selection scenario. */ - cardSelection = genericCardService->createCardSelection(); - cardSelection->filterByDfName(ConfigurationUtil::AID_KEYPLE_PREFIX); - cardSelection->setFileOccurrence(GenericCardSelection::FileOccurrence::NEXT); - cardSelectionManager->prepareSelection(cardSelection); + cardSelectionManager->prepareSelection( + cardSelector2, genericCardSelectionExtension); /* Close the channel after the selection */ cardSelectionManager->prepareReleaseChannel(); - std::shared_ptr cardSelectionsResult = - cardSelectionManager->processCardSelectionScenario(cardReader); + std::shared_ptr cardSelectionsResult + = cardSelectionManager->processCardSelectionScenario(cardReader); /* Log the result */ for (const auto& entry : cardSelectionsResult->getSmartCards()) { - std::shared_ptr smartCard = entry.second; + std::shared_ptr smartCard( + std::dynamic_pointer_cast(entry.second)); const std::string& powerOnData = smartCard->getPowerOnData(); - const std::string selectApplicationResponse = - HexUtil::toHex(smartCard->getSelectApplicationResponse()); - const std::string selectionIsActive = - smartCard == cardSelectionsResult->getActiveSmartCard() ? "true" : "false"; - - logger->info("Selection status for selection (indexed %): \n" \ - "\t\tActive smart card: %\n" \ - "\t\tpower-on data: %\n" \ - "\t\tSelect Application response: %\n", - entry.first, - selectionIsActive, - powerOnData, - selectApplicationResponse); + const std::string selectApplicationResponse + = HexUtil::toHex(smartCard->getSelectApplicationResponse()); + const std::string selectionIsActive + = smartCard == cardSelectionsResult->getActiveSmartCard() ? "true" + : "false"; + + logger->info( + "Selection status for selection (indexed %): \n" + "\t\tActive smart card: %\n" + "\t\tpower-on data: %\n" + "\t\tSelect Application response: %\n", + entry.first, + selectionIsActive, + powerOnData, + selectApplicationResponse); } logger->info("= #### End of the generic card processing\n"); diff --git a/Example_Service/src/main/UseCase7_PluginAndReaderObservation/Main_PluginAndReaderObservation_Pcsc.cpp b/Example_Service/src/main/UseCase7_PluginAndReaderObservation/Main_PluginAndReaderObservation_Pcsc.cpp index 0411bac..a87e3d3 100644 --- a/Example_Service/src/main/UseCase7_PluginAndReaderObservation/Main_PluginAndReaderObservation_Pcsc.cpp +++ b/Example_Service/src/main/UseCase7_PluginAndReaderObservation/Main_PluginAndReaderObservation_Pcsc.cpp @@ -1,57 +1,40 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ -/* Calypsonet Terminal Reader */ -#include "ObservableCardReader.h" +#include "PluginObserver.hpp" -/* Keyple Core Util */ -#include "LoggerFactory.h" +#include "keyple/core/service/ObservablePlugin.hpp" +#include "keyple/plugin/pcsc/PcscPluginFactoryBuilder.hpp" -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "ObservablePlugin.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Plugin Pcsc */ -#include "PcscPluginFactoryBuilder.h" - -/* Calypsonet Terminal Reader */ -#include "CardSelectionManager.h" - -/* Examples */ -#include "PluginObserver.h" - -using namespace calypsonet::terminal::reader::selection; -using namespace keyple::core::service; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::plugin::pcsc; +using keyple::core::service::ObservablePlugin; +using keyple::plugin::pcsc::PcscPluginFactoryBuilder; /** * * *

    Use Case Generic 7 – plugin and reader observation (PC/SC)

    * - *

    We demonstrate here the monitoring of an {@link ObservablePlugin} to be notified of reader - * connection/disconnection, and also the monitoring of an ObservableCardReader to be notified - * of card insertion/removal. + *

    We demonstrate here the monitoring of an {@link ObservablePlugin} to be + * notified of reader connection/disconnection, and also the monitoring of an + * ObservableCardReader to be notified of card insertion/removal. * *

    Scenario:

    * *
      - *
    • Launch the monitoring of the plugin, display potential already connected reader and already - * inserted cards. - *
    • Display any further reader connection/disconnection or card insertion/removal. + *
    • Launch the monitoring of the plugin, display potential already + * connected reader and already inserted cards. + *
    • Display any further reader connection/disconnection or card + * insertion/removal. *
    • Automatically observe newly connected readers. *
    * @@ -61,38 +44,40 @@ using namespace keyple::plugin::pcsc; * * @since 2.0.0 */ -class Main_PluginAndReaderObservation_Pcsc {}; -const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_PluginAndReaderObservation_Pcsc)); +class Main_PluginAndReaderObservation_Pcsc { }; +const std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_PluginAndReaderObservation_Pcsc)); -int main() -{ +int +main() { /* Get the instance of the SmartCardService (singleton pattern) */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); + std::shared_ptr smartCardService( + SmartCardServiceProvider::getService()); /* - * Register the PcscPlugin with the SmartCardService, get the corresponding generic plugin in - * return. + * Register the PcscPlugin with the SmartCardService, get the corresponding + * generic plugin in return. */ - std::shared_ptr plugin = - std::dynamic_pointer_cast( - smartCardService->registerPlugin(PcscPluginFactoryBuilder::builder()->build())); + std::shared_ptr plugin + = std::dynamic_pointer_cast( + smartCardService->registerPlugin( + PcscPluginFactoryBuilder::builder()->build())); /* - * We add an observer to each plugin (only one in this example) the readers observers will be - * added dynamically upon plugin events notification. Nevertheless, here we provide the plugin - * observer with the readers already present at startup in order to assign them a reader - * observer. + * We add an observer to each plugin (only one in this example) the readers + * observers will be added dynamically upon plugin events notification. + * Nevertheless, here we provide the plugin observer with the readers + * already present at startup in order to assign them a reader observer. */ logger->info("Add observer PLUGINNAME = %\n", plugin->getName()); /* C++: hack */ - const std::vector> readers = plugin->getReaders(); - std::vector> cardReaders; - for (const auto& reader : readers) { - cardReaders.push_back(std::dynamic_pointer_cast(reader)); - } - auto pluginObserver = std::make_shared(cardReaders); - auto observable = std::dynamic_pointer_cast(plugin); + // const std::vector> readers = + // plugin->getReaders(); std::vector> + // cardReaders; for (const auto& reader : readers) { + // cardReaders.push_back(std::dynamic_pointer_cast(reader)); + // } + auto pluginObserver(std::make_shared(plugin->getReaders())); + auto observable(std::dynamic_pointer_cast(plugin)); observable->setPluginObservationExceptionHandler(pluginObserver); observable->addObserver(pluginObserver); diff --git a/Example_Service/src/main/UseCase7_PluginAndReaderObservation/PluginObserver.cpp b/Example_Service/src/main/UseCase7_PluginAndReaderObservation/PluginObserver.cpp index 5b3e95c..2b9b66c 100644 --- a/Example_Service/src/main/UseCase7_PluginAndReaderObservation/PluginObserver.cpp +++ b/Example_Service/src/main/UseCase7_PluginAndReaderObservation/PluginObserver.cpp @@ -1,129 +1,151 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -#include "PluginObserver.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "ObservableReader.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Plugin Pcsc */ -#include "PcscReader.h" -#include "PcscSupportedContactlessProtocol.h" - -/* Keyple Cpp Example */ -#include "ConfigurationUtil.h" - -using namespace keyple::core::service; -using namespace keyple::plugin::pcsc; - -PluginObserver::PluginObserver(const std::vector>& initialReaders) -{ - mReaderObserver = std::make_shared(); +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include "PluginObserver.hpp" + +#include +#include +#include + +#include "common/ConfigurationUtil.hpp" + +#include "keyple/core/common/KeypleReaderExtension.hpp" +#include "keyple/plugin/pcsc/PcscReader.hpp" +#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp" +#include "keypop/reader/ConfigurableCardReader.hpp" +#include "keypop/reader/ObservableCardReader.hpp" + +using keyple::core::common::KeypleReaderExtension; +using keyple::plugin::pcsc::PcscReader; +using keyple::plugin::pcsc::PcscSupportedContactlessProtocol; +using keypop::reader::ConfigurableCardReader; +using keypop::reader::ObservableCardReader; + +PluginObserver::PluginObserver( + const std::vector>& initialReaders) +: mReaderObserver(std::make_shared()) { for (const auto& reader : initialReaders) { - if (std::dynamic_pointer_cast(reader) != nullptr) { + if (std::dynamic_pointer_cast(reader) + != nullptr) { addObserver(reader); } } } -void PluginObserver::onPluginEvent(const std::shared_ptr event) -{ +void +PluginObserver::onPluginEvent(const std::shared_ptr event) { for (const auto& readerName : event->getReaderNames()) { /* We retrieve the reader object from its name */ - std::shared_ptr reader = - SmartCardServiceProvider::getService()->getPlugin(event->getPluginName()) - ->getReader(readerName); + std::shared_ptr reader + = SmartCardServiceProvider::getService() + ->getPlugin(event->getPluginName()) + ->getReader(readerName); - mLogger->info("PluginEvent: PLUGINNAME = %, READERNAME = %, Type = %\n", - event->getPluginName(), - readerName, - event->getType()); + mLogger->info( + "PluginEvent: PLUGINNAME = %, READERNAME = %, Type = %\n", + event->getPluginName(), + readerName, + event->getType()); switch (event->getType()) { case PluginEvent::Type::READER_CONNECTED: /* - * We are informed here of a connection of a reader. We add an observer to this reader - * if this is possible. + * We are informed here of a connection of a reader. We add an + * observer to this reader if this is possible. */ mLogger->info("New reader! READERNAME = %\n", readerName); - /* Configure the reader with parameters suitable for contactless operations */ + /* + * Configure the reader with parameters suitable for contactless + * operations. + */ setupReader(reader); - if (std::dynamic_pointer_cast(reader) != nullptr) { + if (std::dynamic_pointer_cast(reader)) { addObserver(reader); } break; case PluginEvent::Type::READER_DISCONNECTED: /* - * We are informed here of a disconnection of a reader. The reader object still exists - * but will be removed from the reader list right after. Thus, we can properly remove - * the observer attached to this reader before the list update. + * We are informed here of a disconnection of a reader. The reader + * object still exists but will be removed from the reader list + * right after. Thus, we can properly remove the observer attached + * to this reader before the list update. */ mLogger->info("Reader removed. READERNAME = %\n", readerName); - if (std::dynamic_pointer_cast(reader) != nullptr) { - mLogger->info("Clear observers of READERNAME = %\n", readerName); - std::dynamic_pointer_cast(reader)->clearObservers(); + if (std::dynamic_pointer_cast(reader)) { + mLogger->info( + "Clear observers of READERNAME = %\n", readerName); + std::dynamic_pointer_cast(reader) + ->clearObservers(); } break; default: - mLogger->info("Unexpected reader event. EVENT = %\n", event->getType()); + mLogger->info( + "Unexpected reader event. EVENT = %\n", event->getType()); break; } } } -void PluginObserver::onPluginObservationError(const std::string& pluginName, - const std::shared_ptr e) -{ - mLogger->error("An exception occurred in plugin '%': %\n", pluginName, e); +void +PluginObserver::onPluginObservationError( + const std::string& pluginName, std::unique_ptr e) { + mLogger->error( + "An exception occurred in plugin '%': %\n", + pluginName, + e->getMessage()); } -void PluginObserver::setupReader(std::shared_ptr cardReader) -{ +void +PluginObserver::setupReader(std::shared_ptr cardReader) { try { - std::shared_ptr readerExtension = - SmartCardServiceProvider::getService() - ->getPlugin(cardReader) - ->getReaderExtension(typeid(KeypleReaderExtension), cardReader->getName()); + std::shared_ptr readerExtension + = SmartCardServiceProvider::getService() + ->getPlugin(cardReader) + ->getReaderExtension( + typeid(KeypleReaderExtension), cardReader->getName()); if (std::dynamic_pointer_cast(readerExtension)) { std::dynamic_pointer_cast(readerExtension) ->setContactless(true) - .setIsoProtocol(PcscReader::IsoProtocol::T1) - .setSharingMode(PcscReader::SharingMode::SHARED); - } + .setIsoProtocol(PcscReader::IsoProtocol::T1) + .setSharingMode(PcscReader::SharingMode::SHARED); + } } catch (const Exception& e) { - mLogger->error("Exception raised while setting up the reader %\n", - cardReader->getName(), - e); + mLogger->error( + "Exception raised while setting up the reader %\n", + cardReader->getName(), + e); } /* Activate the ISO14443 card protocol */ - auto configurable = std::dynamic_pointer_cast(cardReader); - configurable->activateProtocol(PcscSupportedContactlessProtocol::ISO_14443_4.getName(), - ConfigurationUtil::ISO_CARD_PROTOCOL); + auto configurable + = std::dynamic_pointer_cast(cardReader); + configurable->activateProtocol( + PcscSupportedContactlessProtocol::ISO_14443_4.getName(), + ConfigurationUtil::ISO_CARD_PROTOCOL); } -void PluginObserver::addObserver(std::shared_ptr reader) -{ +void +PluginObserver::addObserver(std::shared_ptr reader) { mLogger->info("Add observer READERNAME = %\n", reader->getName()); auto observer = std::dynamic_pointer_cast(reader); observer->setReaderObservationExceptionHandler(mReaderObserver); observer->addObserver(mReaderObserver); - observer->startCardDetection(ObservableCardReader::DetectionMode::REPEATING); + observer->startCardDetection( + ObservableCardReader::DetectionMode::REPEATING); } diff --git a/Example_Service/src/main/UseCase7_PluginAndReaderObservation/PluginObserver.h b/Example_Service/src/main/UseCase7_PluginAndReaderObservation/PluginObserver.h deleted file mode 100644 index 7b79226..0000000 --- a/Example_Service/src/main/UseCase7_PluginAndReaderObservation/PluginObserver.h +++ /dev/null @@ -1,99 +0,0 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -#pragma once - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" -#include "ConfigurableCardReader.h" - -/* Keyple Core Service */ -#include "PluginObservationExceptionHandlerSpi.h" -#include "PluginObserverSpi.h" -#include "Reader.h" - -/* Keyple Core Util */ -#include "LoggerFactory.h" - -/* Examples */ -#include "ReaderObserver.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::core::service; -using namespace keyple::core::service::spi; -using namespace keyple::core::util::cpp; - -/** - * (package-private)
    - * Implements the plugin observation SPIs. A plugin Observer to handle reader events such as - * READER_CONNECTED or READER_DISCONNECTED. - * - * @since 2.0.0 - */ -class PluginObserver : public PluginObserverSpi, public PluginObservationExceptionHandlerSpi { -public: - /** - * - */ - virtual ~PluginObserver() = default; - - /** - * (package-private)
    - * Constructor. - * - *

    Add an observer to all provided readers that are observable. - * - * @param initialReaders The readers connected before the plugin is observed. - * @since 2.0.0 - */ - PluginObserver(const std::vector>& initialReaders); - - /** - * {@inheritDoc} - * - * @since 2.0.0 - */ - void onPluginEvent(const std::shared_ptr event) override; - - /** - * {@inheritDoc} - * - * @since 2.0.0 - */ - void onPluginObservationError(const std::string& pluginName, const std::shared_ptr e) - override; - -private: - /** - * - */ - const std::unique_ptr mLogger = LoggerFactory::getLogger(typeid(PluginObserver)); - - /** - * - */ - std::shared_ptr mReaderObserver; - - /** - * Configure the reader to handle ISO14443-4 contactless cards - * - * @param reader The reader. - */ - void setupReader(std::shared_ptr cardReader); - - /** - * Add the unique observer to the provided observable reader. - * - * @param reader An observable reader - */ - void addObserver(std::shared_ptr reader); -}; \ No newline at end of file diff --git a/Example_Service/src/main/UseCase7_PluginAndReaderObservation/PluginObserver.hpp b/Example_Service/src/main/UseCase7_PluginAndReaderObservation/PluginObserver.hpp new file mode 100644 index 0000000..e0f89eb --- /dev/null +++ b/Example_Service/src/main/UseCase7_PluginAndReaderObservation/PluginObserver.hpp @@ -0,0 +1,105 @@ +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#pragma once + +#include +#include +#include + +#include "ReaderObserver.hpp" + +#include "keyple/core/service/PluginEvent.hpp" +#include "keyple/core/service/spi/PluginObservationExceptionHandlerSpi.hpp" +#include "keyple/core/service/spi/PluginObserverSpi.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/exception/Exception.hpp" +#include "keypop/reader/CardReader.hpp" + +using keyple::core::service::PluginEvent; +using keyple::core::service::spi::PluginObservationExceptionHandlerSpi; +using keyple::core::service::spi::PluginObserverSpi; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::exception::Exception; +using keypop::reader::CardReader; + +/** + * Implements the plugin observation SPIs. A plugin Observer to handle reader + * events such as READER_CONNECTED or READER_DISCONNECTED. + * + * @since 2.0.0 + */ +class PluginObserver : public PluginObserverSpi, + public PluginObservationExceptionHandlerSpi { +public: + /** + * + */ + virtual ~PluginObserver() = default; + + /** + * (package-private)
    + * Constructor. + * + *

    Add an observer to all provided readers that are observable. + * + * @param initialReaders The readers connected before the plugin is + * observed. + * @since 2.0.0 + */ + explicit PluginObserver( + const std::vector>& initialReaders); + + /** + * {@inheritDoc} + * + * @since 2.0.0 + */ + void onPluginEvent(const std::shared_ptr event) override; + + /** + * {@inheritDoc} + * + * @since 2.0.0 + */ + void onPluginObservationError( + const std::string& pluginName, std::unique_ptr e) override; + +private: + /** + * + */ + const std::unique_ptr mLogger + = LoggerFactory::getLogger(typeid(PluginObserver)); + + /** + * + */ + std::shared_ptr mReaderObserver; + + /** + * Configure the reader to handle ISO14443-4 contactless cards + * + * @param reader The reader. + */ + void setupReader(std::shared_ptr cardReader); + + /** + * Add the unique observer to the provided observable reader. + * + * @param reader An observable reader + */ + void addObserver(std::shared_ptr reader); +}; diff --git a/Example_Service/src/main/UseCase7_PluginAndReaderObservation/ReaderObserver.cpp b/Example_Service/src/main/UseCase7_PluginAndReaderObservation/ReaderObserver.cpp index 134e3ab..d3c4328 100644 --- a/Example_Service/src/main/UseCase7_PluginAndReaderObservation/ReaderObserver.cpp +++ b/Example_Service/src/main/UseCase7_PluginAndReaderObservation/ReaderObserver.cpp @@ -1,46 +1,51 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ -#include "ReaderObserver.h" +#include "ReaderObserver.hpp" -/* Keyple Core Service */ -#include "SmartCardServiceProvider.h" +#include "keypop/reader/ObservableCardReader.hpp" -using namespace keyple::core::service; +using keypop::reader::ObservableCardReader; -void ReaderObserver::onReaderEvent(const std::shared_ptr event) -{ +void +ReaderObserver::onReaderEvent(const std::shared_ptr event) { /* Just log the event */ - const std::string pluginName = - smartCardService->getPlugin(smartCardService->getReader(event->getReaderName())) - ->getName(); - mLogger->info("Event: PLUGINNAME = %, READERNAME = %, EVENT = %\n", - pluginName, - event->getReaderName(), - event->getType()); + const std::string pluginName + = smartCardService + ->getPlugin(smartCardService->getReader(event->getReaderName())) + ->getName(); + mLogger->info( + "Event: PLUGINNAME = %, READERNAME = %, EVENT = %\n", + pluginName, + event->getReaderName(), + event->getType()); if (event->getType() != CardReaderEvent::Type::CARD_REMOVED) { std::dynamic_pointer_cast( - smartCardService->getPlugin(pluginName)->getReader(event->getReaderName())) - ->finalizeCardProcessing(); + smartCardService->getPlugin(pluginName) + ->getReader(event->getReaderName())) + ->finalizeCardProcessing(); } } -void ReaderObserver::onReaderObservationError(const std::string& pluginName, - const std::string& readerName, - const std::shared_ptr e) -{ - mLogger->error("An exception occurred in plugin '%', reader '%': %\n", - pluginName, - readerName, - e); +void +ReaderObserver::onReaderObservationError( + const std::string& pluginName, + const std::string& readerName, + const std::shared_ptr e) { + mLogger->error( + "An exception occurred in plugin '%', reader '%': %\n", + pluginName, + readerName, + e); } diff --git a/Example_Service/src/main/UseCase7_PluginAndReaderObservation/ReaderObserver.h b/Example_Service/src/main/UseCase7_PluginAndReaderObservation/ReaderObserver.h deleted file mode 100644 index 77535fa..0000000 --- a/Example_Service/src/main/UseCase7_PluginAndReaderObservation/ReaderObserver.h +++ /dev/null @@ -1,72 +0,0 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -#pragma once - -/* Calypsonet Terminal Reader */ -#include "CardReaderEvent.h" -#include "CardReaderObservationExceptionHandlerSpi.h" -#include "CardReaderObserverSpi.h" -#include "ObservableCardReader.h" - -/* Keyple Core Service */ -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Core Util */ -#include "LoggerFactory.h" - -using namespace calypsonet::terminal::reader; -using namespace calypsonet::terminal::reader::spi; -using namespace keyple::core::util::cpp; -using namespace keyple::core::service; - -/** - * (package-private)
    - * Implements the reader observation SPIs.
    - * A reader Observer to handle card events such as CARD_INSERTED, CARD_MATCHED, CARD_REMOVED - * - * @since 2.0.0 - */ -class ReaderObserver -: public CardReaderObserverSpi, public CardReaderObservationExceptionHandlerSpi { -public: - /** - * - */ - virtual ~ReaderObserver() = default; - - /** - * - */ - void onReaderEvent(const std::shared_ptr event) override; - - - /** - * - */ - void onReaderObservationError(const std::string& pluginName, - const std::string& readerName, - const std::shared_ptr e) override; - -private: - /** - * - */ - const std::unique_ptr mLogger = LoggerFactory::getLogger(typeid(ReaderObserver)); - - /** - * - */ - const std::shared_ptr smartCardService = - SmartCardServiceProvider::getService(); -}; diff --git a/Example_Service/src/main/UseCase7_PluginAndReaderObservation/ReaderObserver.hpp b/Example_Service/src/main/UseCase7_PluginAndReaderObservation/ReaderObserver.hpp new file mode 100644 index 0000000..7d44007 --- /dev/null +++ b/Example_Service/src/main/UseCase7_PluginAndReaderObservation/ReaderObserver.hpp @@ -0,0 +1,75 @@ +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#pragma once + +#include +#include + +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keypop/reader/CardReaderEvent.hpp" +#include "keypop/reader/spi/CardReaderObservationExceptionHandlerSpi.hpp" +#include "keypop/reader/spi/CardReaderObserverSpi.hpp" + +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keypop::reader::CardReaderEvent; +using keypop::reader::spi::CardReaderObservationExceptionHandlerSpi; +using keypop::reader::spi::CardReaderObserverSpi; + +/** + * Implements the reader observation SPIs.
    + * A reader Observer to handle card events such as CARD_INSERTED, CARD_MATCHED, + * CARD_REMOVED + * + * @since 2.0.0 + */ +class ReaderObserver : public CardReaderObserverSpi, + public CardReaderObservationExceptionHandlerSpi { +public: + /** + * + */ + virtual ~ReaderObserver() = default; + + /** + * + */ + void onReaderEvent(const std::shared_ptr event) override; + + /** + * + */ + void onReaderObservationError( + const std::string& pluginName, + const std::string& readerName, + const std::shared_ptr e) override; + +private: + /** + * + */ + const std::unique_ptr mLogger + = LoggerFactory::getLogger(typeid(ReaderObserver)); + + /** + * + */ + const std::shared_ptr smartCardService + = SmartCardServiceProvider::getService(); +}; diff --git a/Example_Service/src/main/common/ConfigurationUtil.cpp b/Example_Service/src/main/common/ConfigurationUtil.cpp index 5f3ffb1..6f56770 100644 --- a/Example_Service/src/main/common/ConfigurationUtil.cpp +++ b/Example_Service/src/main/common/ConfigurationUtil.cpp @@ -1,53 +1,28 @@ -/************************************************************************************************** - * Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -#include "ConfigurationUtil.h" - -#include -#include - -/* Keyple Core Util */ -#include "IllegalStateException.h" - -using namespace keyple::core::service; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp::exception; - -const std::string ConfigurationUtil::AID_EMV_PPSE = "325041592E5359532E4444463031"; +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include "common/ConfigurationUtil.hpp" + +#include + +const std::string ConfigurationUtil::AID_EMV_PPSE + = "325041592E5359532E4444463031"; const std::string ConfigurationUtil::AID_KEYPLE_PREFIX = "315449432E"; const std::string ConfigurationUtil::ISO_CARD_PROTOCOL = "ISO_14443_4_CARD"; -const std::string ConfigurationUtil::CONTACTLESS_READER_NAME_REGEX = - ".*ASK LoGO.*|.*Contactless.*|.*ACR122U.*|.*00 01.*|.*5x21-CL 0.*"; -const std::string ConfigurationUtil::CONTACT_READER_NAME_REGEX = - ".*Identive.*|.*HID.*|.*00 00.*|.*5x21 0.*"; - -const std::unique_ptr ConfigurationUtil::mLogger = - LoggerFactory::getLogger(typeid(ConfigurationUtil)); - -const std::string ConfigurationUtil::getCardReaderName(std::shared_ptr plugin, - const std::string& readerNameRegex) -{ - std::string name = ""; - const std::regex nameRegex(readerNameRegex); - - for (const auto& readerName : plugin->getReaderNames()) { - if (std::regex_match(readerName, nameRegex)) { - mLogger->info("Card reader, plugin; %, name: %\n", plugin->getName(), readerName); - name = readerName; - return name; - } - } +const std::string ConfigurationUtil::CONTACTLESS_READER_NAME_REGEX + = ".*ASK LoGO.*|.*Contactless.*|.*ACR122U.*|.*00 01.*|.*5x21-CL 0.*"; +const std::string ConfigurationUtil::CONTACT_READER_NAME_REGEX + = ".*Identive.*|.*HID.*|.*00 00.*|.*5x21 0.*"; - std::stringstream ss; - ss << "Reader '" << readerNameRegex << "' not found in plugin '" << plugin->getName() << "'"; - throw IllegalStateException(ss.str()); -} +const std::unique_ptr ConfigurationUtil::mLogger + = LoggerFactory::getLogger(typeid(ConfigurationUtil)); diff --git a/Example_Service/src/main/common/ConfigurationUtil.h b/Example_Service/src/main/common/ConfigurationUtil.h deleted file mode 100644 index f187ea0..0000000 --- a/Example_Service/src/main/common/ConfigurationUtil.h +++ /dev/null @@ -1,80 +0,0 @@ -/************************************************************************************************** - * Copyright (c) 2021 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -#pragma once - -#include - -/* Keyple Core Util */ -#include "LoggerFactory.h" - -/* Keyple Core Service */ -#include "Plugin.h" - -using namespace keyple::core::service; -using namespace keyple::core::util::cpp; - -/** - * Utility class providing methods for configuring readers and the card resource service used across - * several examples. - * - * @since 2.0.0 - */ -class ConfigurationUtil final { -public: - /** - * - */ - static const std::string AID_EMV_PPSE; - - /** - * - */ - static const std::string AID_KEYPLE_PREFIX; - - /** - * - */ - static const std::string ISO_CARD_PROTOCOL; - - /* - * Common reader identifiers - * These two regular expressions can be modified to fit the names of the readers used to run - * these examples. - */ - static const std::string CONTACTLESS_READER_NAME_REGEX; - static const std::string CONTACT_READER_NAME_REGEX; - - /** - * Retrieves the name of the first available reader in the provided plugin whose name matches - * the provided regular expression. - * - * @param plugin The plugin to which the reader belongs. - * @param readerNameRegex A regular expression matching the targeted reader. - * @return The name of the found reader. - * @throws IllegalStateException If the reader is not found. - */ - static const std::string getCardReaderName(std::shared_ptr plugin, - const std::string& readerNameRegex); - -private: - /** - * - */ - static const std::unique_ptr mLogger; - - /** - * (private)
    - * Constructor. - */ - ConfigurationUtil() {} -}; diff --git a/Example_Service/src/main/common/ConfigurationUtil.hpp b/Example_Service/src/main/common/ConfigurationUtil.hpp new file mode 100644 index 0000000..6bc6709 --- /dev/null +++ b/Example_Service/src/main/common/ConfigurationUtil.hpp @@ -0,0 +1,67 @@ +/* **************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#pragma once + +#include +#include + +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" + +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; + +/** + * Utility class providing methods for configuring readers and the card resource + * service used across several examples. + * + * @since 2.0.0 + */ +class ConfigurationUtil final { +public: + /** + * + */ + static const std::string AID_EMV_PPSE; + + /** + * + */ + static const std::string AID_KEYPLE_PREFIX; + + /** + * + */ + static const std::string ISO_CARD_PROTOCOL; + + /* + * Common reader identifiers + * These two regular expressions can be modified to fit the names of the + * readers used to run these examples. + */ + static const std::string CONTACTLESS_READER_NAME_REGEX; + static const std::string CONTACT_READER_NAME_REGEX; + +private: + /** + * + */ + static const std::unique_ptr mLogger; + + /** + * Constructor. + */ + ConfigurationUtil() { + } +}; diff --git a/Example_Service_Resource/CMakeLists.txt b/Example_Service_Resource/CMakeLists.txt index 6a2ceef..06242e4 100644 --- a/Example_Service_Resource/CMakeLists.txt +++ b/Example_Service_Resource/CMakeLists.txt @@ -1,82 +1,41 @@ -# ************************************************************************************************* -# Copyright (c) 2023 Calypso Networks Association https://calypsonet.org/ * -# * -# See the NOTICE file(s) distributed with this work for additional information regarding * -# copyright ownership. * -# * -# This program and the accompanying materials are made available under the terms of the Eclipse * -# Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * -# * -# SPDX-License-Identifier: EPL-2.0 * -# *************************************************************************************************/ - - -SET(CALYPSONET_CARD_DIR "../../calypsonet-terminal-card-cpp-api") -SET(CALYPSONET_READER_DIR "../../calypsonet-terminal-reader-cpp-api") -SET(KEYPLE_CARD_DIR "../../keyple-card-generic-cpp-lib") -SET(KEYPLE_COMMON_DIR "../../keyple-common-cpp-api") -SET(KEYPLE_PLUGIN_DIR "../../keyple-plugin-cpp-api") -SET(KEYPLE_PCSC_DIR "../../keyple-plugin-pcsc-cpp-lib") -SET(KEYPLE_STUB_DIR "../../keyple-plugin-stub-cpp-lib") -SET(KEYPLE_RESOURCE_DIR "../../keyple-service-resource-cpp-lib") -SET(KEYPLE_SERVICE_DIR "../../keyple-service-cpp-lib") -SET(KEYPLE_UTIL_DIR "../../keyple-util-cpp-lib") - -SET(KEYPLE_STUB_LIB "keyplepluginstubcpplib") -SET(KEYPLE_PCSC_LIB "keyplepluginpcsccpplib") -SET(KEYPLE_CARD_LIB "keyplecardgenericcpplib") -SET(KEYPLE_SERVICE_LIB "keypleservicecpplib") -SET(KEYPLE_RESOURCE_LIB "keypleserviceresourcecpplib") -SET(KEYPLE_UTIL_LIB "keypleutilcpplib") +# ***************************************************************************** +# Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * +# * +# See the NOTICE file(s) distributed with this work for additional * +# information regarding copyright ownership. * +# * +# This program and the accompanying materials are made available under the * +# terms of the Eclipse * +# * +# Public License 2.0 which is available at * +# http://www.eclipse.org/legal/epl-2.0 * +# * +# SPDX-License-Identifier: EPL-2.0 * +# *****************************************************************************/ INCLUDE_DIRECTORIES( - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/common - - ${CALYPSONET_CARD_DIR}/src/main - ${CALYPSONET_CARD_DIR}/src/main/spi - - ${CALYPSONET_READER_DIR}/src/main - ${CALYPSONET_READER_DIR}/src/main/selection - ${CALYPSONET_READER_DIR}/src/main/selection/spi - ${CALYPSONET_READER_DIR}/src/main/spi - - ${KEYPLE_COMMON_DIR}/src/main - - ${KEYPLE_CARD_DIR}/src/main - ${KEYPLE_PCSC_DIR}/src/main +) - ${KEYPLE_PLUGIN_DIR}/src/main - ${KEYPLE_PLUGIN_DIR}/src/main/spi - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader/observable/ - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader/observable/state/insertion - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader/observable/state/processing - ${KEYPLE_PLUGIN_DIR}/src/main/spi/reader/observable/state/removal +SET(USECASE1 UseCase1_CardResourceService) +SET(USECASE1_STUB ${USECASE1}_Stub) +ADD_EXECUTABLE( - ${KEYPLE_RESOURCE_DIR}/src/main - ${KEYPLE_RESOURCE_DIR}/src/main/spi + ${USECASE1_STUB} - ${KEYPLE_SERVICE_DIR}/src/main - ${KEYPLE_SERVICE_DIR}/src/main/cpp - ${KEYPLE_SERVICE_DIR}/src/main/spi + ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE1}/Main_CardResourceService_Stub.cpp +) +TARGET_LINK_LIBRARIES( - ${KEYPLE_UTIL_DIR}/src/main - ${KEYPLE_UTIL_DIR}/src/main/cpp - ${KEYPLE_UTIL_DIR}/src/main/cpp/exception - ${KEYPLE_UTIL_DIR}/src/main/protocol + ${USECASE1_STUB} - ${KEYPLE_STUB_DIR}/src/main - ${KEYPLE_STUB_DIR}/src/main/spi + Keyple::Card::Generic + Keyple::Plugin::Stub + Keyple::Service + Keyple::Service::Resource + Keyple::Util ) -SET(USECASE1 UseCase1_CardResourceService) -SET(USECASE1_STUB ${USECASE1}_Stub) -ADD_EXECUTABLE(${USECASE1_STUB} - ${CMAKE_CURRENT_SOURCE_DIR}/src/main/${USECASE1}/Main_CardResourceService_Stub.cpp) -TARGET_LINK_LIBRARIES(${USECASE1_STUB} ${KEYPLE_CARD_LIB} ${KEYPLE_STUB_LIB} ${KEYPLE_SERVICE_LIB} ${KEYPLE_RESOURCE_LIB} ${KEYPLE_UTIL_LIB}) - IF(APPLE) TARGET_LINK_LIBRARIES(${USECASE1_STUB} pthread) ELSEIF(UNIX) diff --git a/Example_Service_Resource/src/main/UseCase1_CardResourceService/Main_CardResourceService_Stub.cpp b/Example_Service_Resource/src/main/UseCase1_CardResourceService/Main_CardResourceService_Stub.cpp index d8cc3b9..3be42c2 100644 --- a/Example_Service_Resource/src/main/UseCase1_CardResourceService/Main_CardResourceService_Stub.cpp +++ b/Example_Service_Resource/src/main/UseCase1_CardResourceService/Main_CardResourceService_Stub.cpp @@ -1,103 +1,131 @@ -/************************************************************************************************** - * Copyright (c) 2022 Calypso Networks Association https://calypsonet.org/ * - * * - * See the NOTICE file(s) distributed with this work for additional information regarding * - * copyright ownership. * - * * - * This program and the accompanying materials are made available under the terms of the Eclipse * - * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 * - * * - * SPDX-License-Identifier: EPL-2.0 * - **************************************************************************************************/ - -/* Calypsonet Terminal Reader */ -#include "CardReader.h" -#include "ConfigurableCardReader.h" - -/* Keyple Core Util */ -#include "HexUtil.h" -#include "LoggerFactory.h" -#include "Thread.h" - -/* Keyple Core Service */ -#include "ConfigurableReader.h" -#include "SmartCardService.h" -#include "SmartCardServiceProvider.h" - -/* Keyple Service Resource */ -#include "CardResourceProfileConfigurator.h" -#include "CardResourceService.h" -#include "CardResourceServiceProvider.h" -#include "PluginsConfigurator.h" - -/* Keyple Plugin Stub */ -#include "StubPlugin.h" -#include "StubPluginFactoryBuilder.h" -#include "StubReader.h" - -/* Keyple Card Generic */ -#include "GenericCardSelectionAdapter.h" -#include "GenericExtensionService.h" - -/* Keyple Core Common */ -#include "KeyplePluginExtension.h" -#include "KeypleReaderExtension.h" - -using namespace calypsonet::terminal::reader; -using namespace keyple::card::generic; -using namespace keyple::core::common; -using namespace keyple::core::service; -using namespace keyple::core::service::resource; -using namespace keyple::core::util; -using namespace keyple::core::util::cpp; -using namespace keyple::plugin::stub; +/****************************************************************************** + * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ * + * * + * See the NOTICE file(s) distributed with this work for additional * + * information regarding copyright ownership. * + * * + * This program and the accompanying materials are made available under the * + * terms of the Eclipse * + * * + * Eclipse Distribution License 1.0 which is available at * + * https://www.eclipse.org/org/documents/edl-v10.php * + * * + * SPDX-License-Identifier: BSD-3-Clause * + ******************************************************************************/ + +#include +#include +#include + +#include "keyple/card/generic/GenericCardSelectionExtension.hpp" +#include "keyple/card/generic/GenericExtensionService.hpp" +#include "keyple/core/service/Plugin.hpp" +#include "keyple/core/service/SmartCardService.hpp" +#include "keyple/core/service/SmartCardServiceProvider.hpp" +#include "keyple/core/service/resource/CardResource.hpp" +#include "keyple/core/service/resource/CardResourceProfileConfigurator.hpp" +#include "keyple/core/service/resource/CardResourceService.hpp" +#include "keyple/core/service/resource/CardResourceServiceProvider.hpp" +#include "keyple/core/service/resource/PluginsConfigurator.hpp" +#include "keyple/core/service/resource/spi/CardResourceProfileExtension.hpp" +#include "keyple/core/service/resource/spi/ReaderConfiguratorSpi.hpp" +#include "keyple/core/service/spi/PluginObservationExceptionHandlerSpi.hpp" +#include "keyple/core/util/HexUtil.hpp" +#include "keyple/core/util/cpp/Logger.hpp" +#include "keyple/core/util/cpp/LoggerFactory.hpp" +#include "keyple/core/util/cpp/Thread.hpp" +#include "keyple/core/util/cpp/exception/Exception.hpp" +#include "keyple/plugin/stub/StubPlugin.hpp" +#include "keyple/plugin/stub/StubPluginFactoryBuilder.hpp" +#include "keyple/plugin/stub/StubReader.hpp" +#include "keyple/plugin/stub/StubSmartCard.hpp" +#include "keypop/reader/CardReader.hpp" +#include "keypop/reader/ConfigurableCardReader.hpp" +#include "keypop/reader/ReaderApiFactory.hpp" +#include "keypop/reader/selection/IsoCardSelector.hpp" +#include "keypop/reader/spi/CardReaderObservationExceptionHandlerSpi.hpp" + +using keyple::card::generic::GenericCardSelectionExtension; +using keyple::card::generic::GenericExtensionService; +using keyple::core::service::Plugin; +using keyple::core::service::SmartCardService; +using keyple::core::service::SmartCardServiceProvider; +using keyple::core::service::resource::CardResource; +using keyple::core::service::resource::CardResourceProfileConfigurator; +using keyple::core::service::resource::CardResourceService; +using keyple::core::service::resource::CardResourceServiceProvider; +using keyple::core::service::resource::PluginsConfigurator; +using keyple::core::service::resource::spi::CardResourceProfileExtension; +using keyple::core::service::resource::spi::ReaderConfiguratorSpi; +using keyple::core::service::spi::PluginObservationExceptionHandlerSpi; +using keyple::core::util::HexUtil; +using keyple::core::util::cpp::Logger; +using keyple::core::util::cpp::LoggerFactory; +using keyple::core::util::cpp::Thread; +using keyple::core::util::cpp::exception::Exception; +using keyple::plugin::stub::StubPlugin; +using keyple::plugin::stub::StubPluginFactoryBuilder; +using keyple::plugin::stub::StubReader; +using keyple::plugin::stub::StubSmartCard; +using keypop::reader::CardReader; +using keypop::reader::ConfigurableCardReader; +using keypop::reader::ReaderApiFactory; +using keypop::reader::selection::IsoCardSelector; +using keypop::reader::spi::CardReaderObservationExceptionHandlerSpi; /** *

    Use Case "resource service 1" – Card resource service (Stub)

    * - *

    We demonstrate here the usage of the card resource service with a local pool of Stub readers. + *

    We demonstrate here the usage of the card resource service with a local + * pool of Stub readers. * *

    Scenario:

    * *
      - *
    • The card resource service is configured and started to observe the connection/disconnection - * of readers and the insertion/removal of cards. - *
    • A command line menu allows you to take and release the two defined types of card resources. - *
    • The log and console printouts show the operation of the card resource service. + *
    • The card resource service is configured and started to observe the + * connection/disconnection of readers and the insertion/removal of cards. + *
    • A command line menu allows you to take and release the two defined + * types of card resources. + *
    • The log and console printouts show the operation of the card resource + * service. *
    * - * All results are logged with slf4j. - * *

    Any unexpected behavior will result in runtime exceptions. * * @since 2.0.0 */ -class Main_CardResourceService_Stub {}; -const std::unique_ptr logger = - LoggerFactory::getLogger(typeid(Main_CardResourceService_Stub)); +class Main_CardResourceService_Stub { }; +const std::unique_ptr logger + = LoggerFactory::getLogger(typeid(Main_CardResourceService_Stub)); static const std::string READER_A = "READER_A"; static const std::string READER_B = "READER_B"; static const std::string ATR_CARD_A = "3B3F9600805A4880C120501711AABBCC829000"; static const std::string ATR_CARD_B = "3B3F9600805A4880C120501722AABBCC829000"; -static const std::string ATR_REGEX_A = "^3B3F9600805A4880C120501711[0-9A-F]{6}829000$"; -static const std::string ATR_REGEX_B = "^3B3F9600805A4880C120501722[0-9A-F]{6}829000$"; +static const std::string ATR_REGEX_A + = "^3B3F9600805A4880C120501711[0-9A-F]{6}829000$"; +static const std::string ATR_REGEX_B + = "^3B3F9600805A4880C120501722[0-9A-F]{6}829000$"; static const std::string RESOURCE_A = "RESOURCE_A"; static const std::string RESOURCE_B = "RESOURCE_B"; static const std::string READER_NAME_REGEX_A = ".*_A"; static const std::string READER_NAME_REGEX_B = ".*_B"; static const std::string SAM_PROTOCOL = "ISO_7816_3_T0"; +static std::shared_ptr readerApiFactory + = SmartCardServiceProvider::getService()->getReaderApiFactory(); + /** - * Reader configurator used by the card resource service to set up the SAM reader with the required - * settings. + * Reader configurator used by the card resource service to set up the SAM + * reader with the required settings. */ class ReaderConfigurator : public ReaderConfiguratorSpi { public: /** * Constructor. */ - ReaderConfigurator() {} + ReaderConfigurator() { + } /** * @@ -107,14 +135,21 @@ class ReaderConfigurator : public ReaderConfiguratorSpi { /** * {@inheritDoc} */ - void setupReader(std::shared_ptr reader) override { - /* Configure the reader with parameters suitable for contactless operations */ + void + setupReader(std::shared_ptr reader) override { + /* + * Configure the reader with parameters suitable for contactless + * operations. + */ try { std::dynamic_pointer_cast(reader) ->activateProtocol(SAM_PROTOCOL, SAM_PROTOCOL); } catch (const Exception& e) { - logger->error("Exception raised while setting up the reader %\n", reader->getName(), e); + logger->error( + "Exception raised while setting up the reader %\n", + reader->getName(), + e); } } @@ -122,11 +157,13 @@ class ReaderConfigurator : public ReaderConfiguratorSpi { /** * */ - const std::unique_ptr logger = LoggerFactory::getLogger(typeid(ReaderConfigurator)); + const std::unique_ptr logger + = LoggerFactory::getLogger(typeid(ReaderConfigurator)); }; /** - * Class implementing the exception handler SPIs for plugin and reader monitoring + * Class implementing the exception handler SPIs for plugin and reader + * monitoring. */ class PluginAndReaderExceptionHandler : public PluginObservationExceptionHandlerSpi, @@ -140,28 +177,40 @@ class PluginAndReaderExceptionHandler /** * */ - void onPluginObservationError(const std::string& pluginName, const std::shared_ptr e) - override - { - logger->error("An exception occurred while monitoring the plugin '%'\n", pluginName, e); + void + onPluginObservationError( + const std::string& pluginName, + const std::unique_ptr e) override { + logger->error( + "An exception occurred while monitoring the plugin '%'\n", + pluginName, + e->getMessage()); } /** * */ - void onReaderObservationError(const std::string& pluginName, - const std::string& readerName, - const std::shared_ptr e) override - { - logger->error("An exception occurred while monitoring the reader '%/%' (%)\n", - pluginName, - readerName, - e); + void + onReaderObservationError( + const std::string& pluginName, + const std::string& readerName, + const std::shared_ptr e) override { + logger->error( + "An exception occurred while monitoring the reader '%/%' (%)\n", + pluginName, + readerName, + e); } }; -static char getInput() -{ +/** + * This method prompts the user to select an option from a menu and returns the + * selected option as a char. + * + * @return The selected option as a char + */ +static char +getInput() { std::cout << "Options:" << std::endl; std::cout << " '1': Insert stub card A" << std::endl; std::cout << " '2': Remove stub card A" << std::endl; @@ -177,96 +226,120 @@ static char getInput() return static_cast(getchar()); } -int main() -{ +int +main() { /* Get the instance of the SmartCardService (singleton pattern) */ - std::shared_ptr smartCardService = SmartCardServiceProvider::getService(); + std::shared_ptr smartCardService + = SmartCardServiceProvider::getService(); /* - * Register the StubPlugin with the SmartCardService, get the corresponding generic plugin in - * return. + * Register the StubPlugin with the SmartCardService, get the corresponding + * generic plugin in return. */ - std::shared_ptr plugin = - smartCardService->registerPlugin(StubPluginFactoryBuilder::builder()->build()); + std::shared_ptr plugin = smartCardService->registerPlugin( + StubPluginFactoryBuilder::builder()->build()); /* Get the generic card extension service */ - std::shared_ptr cardExtension = GenericExtensionService::getInstance(); + std::shared_ptr cardExtension + = GenericExtensionService::getInstance(); - /* Verify that the extension's API level is consistent with the current service */ + /* + * Verify that the extension's API level is consistent with the current + * service + */ smartCardService->checkCardExtension(cardExtension); - logger->info("=============== " \ - "UseCase Resource Service #1: card resource service " \ - "==================\n"); + logger->info( + "=============== " + "UseCase Resource Service #1: card resource service " + "==================\n"); /* - * Create a card resource extension A expecting a card having power-on data matching the regex - * A. + * Create a card resource extension A expecting a card having power-on data + * matching the regex A. */ - std::shared_ptr cardSelectionA = - GenericExtensionService::getInstance()->createCardSelection(); - cardSelectionA->filterByPowerOnData(ATR_REGEX_A); + std::shared_ptr cardSelectorA + = readerApiFactory->createIsoCardSelector(); + cardSelectorA->filterByPowerOnData(ATR_REGEX_A); + + std::shared_ptr genericCardSelectionExtension + = GenericExtensionService::getInstance() + ->createGenericCardSelectionExtension(); - std::shared_ptr cardResourceExtensionA = - GenericExtensionService::getInstance()->createCardResourceProfileExtension(cardSelectionA); + std::shared_ptr cardResourceExtensionA + = GenericExtensionService::getInstance() + ->createCardResourceProfileExtension( + cardSelectorA, genericCardSelectionExtension); /* - * Create a card resource extension B expecting a card having power-on data matching the regex - * B. + * Create a card resource extension B expecting a card having power-on data + * matching the regex B. */ - std::shared_ptr cardSelectionB = - GenericExtensionService::getInstance()->createCardSelection(); - cardSelectionB->filterByPowerOnData(ATR_REGEX_B); + std::shared_ptr cardSelectorB + = readerApiFactory->createIsoCardSelector(); + cardSelectorB->filterByPowerOnData(ATR_REGEX_B); - std::shared_ptr cardResourceExtensionB = - GenericExtensionService::getInstance()->createCardResourceProfileExtension(cardSelectionB); + std::shared_ptr cardResourceExtensionB + = GenericExtensionService::getInstance() + ->createCardResourceProfileExtension( + cardSelectorB, genericCardSelectionExtension); /* Get the service */ - std::shared_ptr cardResourceService = CardResourceServiceProvider::getService(); + std::shared_ptr cardResourceService + = CardResourceServiceProvider::getService(); - auto pluginAndReaderExceptionHandler = std::make_shared(); + auto pluginAndReaderExceptionHandler + = std::make_shared(); /* * Configure the card resource service: - * - allocation mode is blocking with a 100 milliseconds cycle and a 10 seconds timeout. - * - the readers are searched in the Stub plugin, the observation of the plugin (for the - * connection/disconnection of readers) and of the readers (for the insertion/removal of cards) - * is activated. - * - two card resource profiles A and B are defined, each expecting a specific card - * characterized by its power-on data and placed in a specific reader. + * - allocation mode is blocking with a 100 milliseconds cycle and a 10 + * seconds timeout. + * - the readers are searched in the Stub plugin, the observation of the + * plugin (for the connection/disconnection of readers) and of the readers + * (for the insertion/removal of cards) is activated. + * - two card resource profiles A and B are defined, each expecting a + * specific card characterized by its power-on data and placed in a + * specific reader. * - the timeout for using the card's resources is set at 5 seconds. */ - cardResourceService->getConfigurator()->withBlockingAllocationMode(100, 10000) - .withPlugins( - PluginsConfigurator::builder() - ->addPluginWithMonitoring( - plugin, - std::make_shared(), - pluginAndReaderExceptionHandler, - pluginAndReaderExceptionHandler) - .withUsageTimeout(5000) - .build()) - .withCardResourceProfiles({ - CardResourceProfileConfigurator::builder( - RESOURCE_A, cardResourceExtensionA) - ->withReaderNameRegex(READER_NAME_REGEX_A) - .build(), - CardResourceProfileConfigurator::builder( - RESOURCE_B, cardResourceExtensionB) - ->withReaderNameRegex(READER_NAME_REGEX_B) - .build()}) - .configure(); + cardResourceService->getConfigurator() + ->withBlockingAllocationMode(100, 10000) + .withPlugins( + PluginsConfigurator::builder() + ->addPluginWithMonitoring( + plugin, + std::make_shared(), + pluginAndReaderExceptionHandler, + pluginAndReaderExceptionHandler) + .withUsageTimeout(5000) + .build()) + .withCardResourceProfiles( + {CardResourceProfileConfigurator::builder( + RESOURCE_A, cardResourceExtensionA) + ->withReaderNameRegex(READER_NAME_REGEX_A) + .build(), + CardResourceProfileConfigurator::builder( + RESOURCE_B, cardResourceExtensionB) + ->withReaderNameRegex(READER_NAME_REGEX_B) + .build()}) + .configure(); + cardResourceService->start(); - std::dynamic_pointer_cast(plugin->getExtension(typeid(StubPlugin))) + std::dynamic_pointer_cast( + plugin->getExtension(typeid(StubPlugin))) ->plugReader(READER_A, true, nullptr); - std::dynamic_pointer_cast(plugin->getExtension(typeid(StubPlugin))) + std::dynamic_pointer_cast( + plugin->getExtension(typeid(StubPlugin))) ->plugReader(READER_B, true, nullptr); /* Sleep for a moment to let the readers being detected */ Thread::sleep(2000); - logger->info("= #### Connect/disconnect readers, insert/remove cards, watch the log\n"); + logger->info( + "= #### Connect/disconnect readers, insert/remove cards, watch the " + "log\n"); bool loop = true; std::shared_ptr cardResourceA = nullptr; @@ -278,16 +351,16 @@ int main() case '1': std::dynamic_pointer_cast( plugin->getReaderExtension(typeid(StubReader), READER_A)) - ->insertCard( - StubSmartCard::builder() - ->withPowerOnData(HexUtil::toByteArray(ATR_CARD_A)) - .withProtocol(SAM_PROTOCOL) - .build()); + ->insertCard( + StubSmartCard::builder() + ->withPowerOnData(HexUtil::toByteArray(ATR_CARD_A)) + .withProtocol(SAM_PROTOCOL) + .build()); break; case '2': std::dynamic_pointer_cast( plugin->getReaderExtension(typeid(StubReader), READER_A)) - ->removeCard(); + ->removeCard(); break; case '3': std::dynamic_pointer_cast( @@ -295,20 +368,21 @@ int main() ->insertCard( StubSmartCard::builder() ->withPowerOnData(HexUtil::toByteArray(ATR_CARD_B)) - .withProtocol(SAM_PROTOCOL) - .build()); + .withProtocol(SAM_PROTOCOL) + .build()); break; case '4': std::dynamic_pointer_cast( plugin->getReaderExtension(typeid(StubReader), READER_B)) - ->removeCard(); + ->removeCard(); break; case '5': cardResourceA = cardResourceService->getCardResource(RESOURCE_A); if (cardResourceA != nullptr) { - logger->info("Card resource A is available: reader %, smart card %\n", - cardResourceA->getReader()->getName(), - cardResourceA->getSmartCard()); + logger->info( + "Card resource A is available: reader %, smart card %\n", + cardResourceA->getReader()->getName(), + cardResourceA->getSmartCard()); } else { logger->info("Card resource A is not available\n"); } @@ -324,9 +398,10 @@ int main() case '7': cardResourceB = cardResourceService->getCardResource(RESOURCE_B); if (cardResourceB != nullptr) { - logger->info("Card resource B is available: reader %, smart card %\n", - cardResourceB->getReader()->getName(), - cardResourceB->getSmartCard()); + logger->info( + "Card resource B is available: reader %, smart card %\n", + cardResourceB->getReader()->getName(), + cardResourceB->getSmartCard()); } else { logger->info("Card resource B is not available\n"); } @@ -353,4 +428,4 @@ int main() logger->info("Exit program\n"); return 0; -} \ No newline at end of file +}