Document toolboxDocument toolbox

APDU script applications for PKI cards in Identity Manager

This article includes updates for Smart ID 22.10.

An encoding description contains the information for the electronic personalization of a card. You import the encoding description from a file. This can be used in Smart ID Identity Manager.

This article describes how to use Application Protocol Data Unit (APDU) commands in an encoding description.

This feature is specific to PKI cards and still requires a PKCS#11 middleware for certain operations. RFID cards are not supported - refer to Nexus Card SDK for encoding of RFID cards.

Smart ID 20.11 introduces breaking changes to the syntax of APDU scripts. Existing scripts must be changed to the new syntax - see section PIN line format for details.

Important information regarding Smart ID 20.11

 Important information regarding Smart ID 20.11

Renamed parameters

Some encoding description parameters were renamed with Smart ID 20.11, so you must adjust any encoding description which includes APDU scripts:

  • CardOSApduFile => ApduFile
  • CardOSApduResponseCodesField => ApduResponseCodesField

Two supported channels

Since Smart ID 20.11 there are two supported channels for sending APDUs within a PKI card encoding:

  • PKCS#11 extension in CardOS middleware (used via Card SDK+JPKIEncoder only).
  • Middleware-agnostic implementation in Smart ID Desktop App with more secure challenge/response handling (new for 20.11).

Depending on your use case and PKCS#11 middleware, you have these options for APDU encodings of PKI cards:

MiddlewareCard SDK+JPKIEncoder
(with printing)
Smart ID Desktop App
(no printing)
CardOS(tick)(tick)
Other (for example Cryptovision, Nexus Personal Desktop Client)(error)(tick)

Prerequisites and features

 Prerequisites
  • APDU scripts have to be bundled in the DSZ file that is uploaded. 

    The file extension must be .apdu, otherwise encoding will fail with an error message.

  • When using CardOS middleware, its version needs to be at least 5.4W14, unless Smart ID Desktop App is used, which will also work with older versions.
  • For APDU encodings through Nexus Card SDK, you need at least Card SDK version 5.4.0.17.
 Features
  • APDU commands can either be given as full hex string or with parameterized command data read from fields.
  • APDU commands have support for challenge response algorithms.
  • Comments are allowed, starting with #.
  • Empty lines are allowed.
  • Do not do other things in the application (like requesting certificates), use dedicated applications for APDUs instead.
  • Applications reference a script by filename.
  • You can execute one script containing potentially multiple APDUs per application.
  • Authentication with challenge/response keys via APDU.
  • Format selection for most variables (hex/base64/string, hex being the default) - new in 20.11.

About APDU commands

 Spaces in APDU commands

You can have spaces in APDU commands for better readability:

RAW[OUT]:00CA018202
RAW [OUT]: 00CA0182 02  # same as above
 Configure format for variables

Smart ID 20.11 allows input and output variables (with some exceptions in PIN lines) to use a format other than hex strings.

To configure the format, set the prefix <hex> / <string> / <base64> in front of the variable name (hex is default if no prefix is given).

Example: Formats for variables
DYN[<base64>MY_RESULT]:00AABBCC;<string>FIELD_A+<base64>FIELD_B+FIELD_C;300 
# MY_RESULT will be written as base64 string							
# FIELD_A shall be interpreted as UTF-8 string							
# FIELD_B shall be interpreted as base64 string
# FIELD_C shall be interpreted as hex string (default)
 APDUs without output

The output field name is optional and can be omitted if you are not interested in the response data, for example:

Example: No output
RAW[]:00AABBCC 
RAW:00AABBCC   # also possible since 20.11
 RAW APDU line format

This format is for non-parameterized APDUs only, which are passed in full as hex-string, with the output type being configurable, see this example:

Example: Write to field MY_OUT_FIELD
RAW:00CA018202                          # no output
RAW[MY_OUT_FIELD]:00CA018202            # output as hex, default
RAW[<hex>MY_OUT_FIELD]:00CA018202       # output as hex, explicit, since 20.11
RAW[<base64>MY_OUT_FIELD]:00CA018202    # output as base64, since 20.11
RAW[<string>MY_OUT_FIELD]:00CA018202    # output as UTF-8 string, since 20.11
 DYN APDU line format

This format allows for parametrization of the APDU's command data, which can be read from fields and concatenated, for example:

Example: Command data composed of NEW_PUK and NEW_PIN field values, no return data
DYN[]:002C0001;NEW_PUK+NEW_PIN
DYN:002C0001;NEW_PUK+NEW_PIN            # skip empty brackets, since 20.11
DYN:002C0001;<hex>NEW_PUK+<hex>NEW_PIN 	# variable format, since 20.11

If a field has an empty or null value, it will resolve to an empty byte array, otherwise the field value will be parsed according to the specified input format (refer to the section "Configure format for variables").

The DYN format automatically sets the appropriate length for the input data, so do not add the input length byte(s) manually.

The expected result length is given as a decimal value, for example:

Example: No command data, expect 255 bytes of return data, write to field OUTPUT
DYN[OUTPUT]:00CA0188;;255
DYN[<hex>OUTPUT]:00CA0188;;255 # variable format, since 20.11

The expected result length will not necessarily match with the number of bytes in the output field, especially if format conversion (for example, to base64) is used.

You can have just the header plus field(s) and/or result length, for example:

DYN formatDescription
DYN:00AABBCCHeader without command-data, expect no result data, no data output field
DYN[]:00AABBCCSame as above
DYN[]:00AABBCC;;Same as above

DYN[]:00AABBCC;;0

Same as above
DYN[]:00AABBCC;FIELD_AHeader and command-data from hex FIELD_A, expect no result data
DYN[]:00AABBCC;FIELD_A;Same as above
DYN[]:00AABBCC;FIELD_A;0Same as above
DYN[MY_RESULT]:00AABBCC;FIELD_A+FIELD_B;300Header and command-data from hex FIELD_A concatenated with hex FIELD_B, expect 300 bytes result data, stored to MY_RESULT as hex
DYN[OUTPUT]:00AABBCC;;13Header without command-data, expect 13 bytes result data, stored to OUTPUT as hex

You can include fixed hex values (prefixed with 0x) in the command-data as well, for example:

DYN formatDescription
DYN:00AABBCC;0xF00D+FIELD_A+0xC0FFEE;0 Header and command-data F00D concatenated with FIELD_A concatenated with C0FFEE
 PIN line format

This custom format allows for displaying a PIN dialog where the user can choose a new PIN.

Optionally input of an existing transport PIN can be requested and/or a PIN validation rule can be specified. Specifying a PIN validation rule is highly recommended to avoid wasting cards due to repeated entering of an incorrect PIN.

The format differs between Smart ID 20.11 and earlier versions, so you have to adjust existing scripts using a PIN line:

Old format (PRIME 3.12 and lower)
PIN[OUTPUT]:TARGET_PIN_DESCRIPTION_FIELD;TRANSPORT_PIN_FIELD;VALIDATION_RULE;OLD_VALUE_OUTPUT

becomes

New format (from Smart ID 20.11)
PIN[OUTPUT,OLD_VALUE_OUTPUT]:TARGET_PIN_DESCRIPTION_FIELD;VALIDATION_RULE;TRANSPORT_PIN_FIELD

Also, you can now specify the format of the output variables to be something other than a hex string, if desired.

Description is still interpreted as plain UTF-8 strings without any conversion done.

For example:

PIN formatDescription
PIN[NEW_PIN]:SIGNATURE_NAME;

SIGNATURE_NAME describes the signature PIN,
NEW_PIN will contain the PIN chosen by the user (as hex); Dialog has new PIN + confirmation.

PIN[<string>NEW_PIN]:AUTH_NAME;reg_exp([a-zA-Z0-9]{8,12});TPINAUTH_NAME contains the name of the auth PIN,
TPIN contains transport PIN to be entered, allows 8-12 alphanumeric chars,
NEW_PIN will contain the PIN chosen by the user, as plain UTF-8 string

PIN[<hex>NEW_PIN,<base64>OLD_PIN]:AUTH_NAME;reg_exp([a-zA-Z0-9]{8,12});

AUTH_NAME contains the name of the auth PIN, allows 8-12 alphanumeric chars,
OLD_PIN will contain the old PIN entered by the user (as base64),
NEW_PIN will contain the new PIN chosen by the user (as hex),
TRANSPORT_PIN_FIELD must be empty if OLD_PIN is set

 

When using Smart ID Desktop App, a PIN entered by the user is never returned in the encoding result - it is only available to other APDU commands in the same encoding!

 CR line format (for Challenge/Response)

This custom format allows for calculating a response to a challenge based on a given key (see GET CHALLENGE / EXTERNAL AUTHENTICATION commands in the CardOS firmware docs).

It supports three C/R algorithms, none of which use any padding, so make sure the input has the proper size:

AlgorithmDescriptionInput SizeOutput Size

CMAC_AES

CMAC with AES(256) keymultiples of 16 bytes8 bytes

MAC_DES3

MAC3 / RetailMAC with 3DES keymultiples of 8 bytes8 bytes

ECB_DES3

direct encryption with 3DES key in ECB modemultiples of 8 bytesmultiples of 8 bytes

The format in an APDU script looks as follows:

CR[OUTPUT]:ALGORITHM;KEY;CHALLENGE

For example:

CR formatDescription
CR[RESPONSE]:MAC_DES3;0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;CHALLENGE

Uses fixed key, read challenge as hex, write response as hex

CR[<base64>RESPONSE]:MAC_DES3;0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;<string>CHALLENGE

Uses fixed key, read challenge as UTF-8 string, write response as base64 (since Smart ID 20.11)

CR[RESPONSE]:MAC_DES3;KEY_FIELD;CHALLENGEUses key from KEY_FIELD

A suitable challenge can be acquired as follows:

DYN[CHALLENGE]:00840000;;16 # get 16 bytes challenge, store in CHALLENGE var as hex

Each challenge is valid within the same session until it is used by an authentication command or replaced with a new challenge.

For some keys it may not possible to immediately authenticate with the new key after changing it.

 Response data format

Since Smart ID 20.11, response data can be returned as UTF-8 string or base64 string instead of hex, so you do not have to do such conversion in the process anymore.

Refer to section "Configure format for variables" for details.

Examples of APDU scripts

The examples below are valid for Smart ID 20.11 and are not backwards compatible.

 Example scripts

Read version and patch

read_version_and_patch.apdu
# this is an APDU script
 
RAW[CARDOS_VERSION]:00CA018202  # read CardOS version into field CARDOS_VERSION
DYN[PACKAGE_INFO]:00CA0188;;255 # read package info into field PACKAGE_INFO

Write ef gdo (Elementary File Global Data Object)

write_ef_gdo.apdu
# this is an APDU script (written for a specific card profile, yours may vary)
 
RAW:00A4080C022F02                        # select EF GDO file
DYN:00D60000;HELLO+CARDOS_VERSION+WORLD;  # write values of fields HELLO, CARDOS_VERSION
                                          # and WORLD (concatenated) to selected file

Change key

change_key.apdu
# this is an APDU script (written for a specific card profile, yours may vary)
# this changes the 3DES key with ID 8
# from the default FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 
# to the value of the NEW_KEY field
 
DYN[CHALLENGE]:00840000;;16              # get 16 bytes challenge
CR[RESPONSE]:MAC_DES3;0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;CHALLENGE # calc
                                                                                   # response
DYN:008200 08;RESPONSE;                # EXTERNAL AUTHENTICATE APDU for keyId 8
DYN:902410 08;0x8F18+NEW_KEY           # change key with keyId 8 to NEW_KEY with options 8F18

Encodings using APDU scripts

The examples below are valid for Smart ID 20.11 (dropping the prefix CardOS from APDU parameter names) and are not backwards compatible. Also they are configured for exclusive use with Smart ID Desktop App (Devices=8711).

 Example encodings

These are example encoding using the script examples above (set the "read" flag on CARDOS_VERSION, PACKAGE_VERSION and APDU_RESPONSE_CODES_*, as those provide output. The Application_X section represents an application, that is, one part of the chip that should be encoded in a certain way.

  1. Define like this is the encoding description:

    [Encoding]
    Type=1024,Chip
    Devices=8711
     
    [Fields]
    APDU_RESPONSE_CODES_A=
    APDU_RESPONSE_CODES_B=
    APDU_RESPONSE_CODES_C=
    NEW_KEY=
    HELLO=
    WORLD=
    CARDOS_VERSION=
    PACKAGE_INFO=
     
    [Description]
    PKCS11LibraryWindows32=cardos11.dll
    PKCS11LibraryWindows64=cardos11_64.dll
    ApplicationList=ABC
     
    [Application_A]
    ApduFile=read_version_and_patch.apdu
    ApduResponseCodesField=APDU_RESPONSE_CODES_A
     
    [Application_B]
    ApduFile=write_ef_gdo.apdu
    ApduResponseCodesField=APDU_RESPONSE_CODES_B
     
    [Application_C]
    ApduFile=change_key.apd
    ApduResponseCodesField=APDU_RESPONSE_CODES_C
  2. Specify the correct order in ApplicationList=, especially if one script depends on the output of another.

  3. It is optional to set the ApduResponseCodesField for execution, but it is needed if you want to process the result code data.
    Result code data uses the following format:

    hexResponseCodeOfFirst;hexResponseCodeOfSecond;etc.

    For example, these are the values if all scripts in the above encoding returned code 0x9000:

    APDU_RESPONSE_CODES_A
    9000;
    APDU_RESPONSE_CODES_B
    9000;9000;

    There is no response code for the CR command from the third script, as it does not execute an APDU:

    APDU_RESPONSE_CODES_C
    9000;;9000;9000;

Although the maximum length of command- and result data for APDUs is 65535, there is a limit of 2000 chars on string process variables in Identity Manager. For example, when using hex format (2 chars per byte), keep command data and result lengths to ~950 bytes to be on the safe side.

Also, the cards themselves may limit this further (for example, 382 bytes max on the tested cards).

Related information


Copyright 2024 Technology Nexus Secured Business Solutions AB. All rights reserved.
Contact Nexus | https://www.nexusgroup.com | Disclaimer | Terms & Conditions