kormax / apple-vas

Reverse-engineering Apple VAS protocol
83 stars 9 forks source link
apple ecp hostcard nfc value-added-services vas vasup-a

Apple VAS

Overview

Apple VAS (Value-added services) is a proprietary NFC protocol that can be used for sending data from a mobile device to an NFC terminal.

Apart from reading passes, this protocol also allows reader to send a signup URL to the device, causing a signup link notification to appear on devices that do not have an appropriate pass downloaded.

Pass data is transmitted in protected form encrypted using AES-GCM. Shared key is derived via ECDH exchange with a X963KDF and is single use only.

Depending on opreation mode, one or multiple passes can be read in a single tap.

Version 1 was current at the time of writing.

Application identifier

VAS can be selected using following application id (AID):

   4f53452e5641532e3031

AID value is a HEX representation of ASCII string OSE.VAS.01.

This AID is also used by Google Smart Tap:

The ususal implementation for most readers is to select OSE.VAS.01 in order to detect what wallet provider is available on device (stored in TLV tag 50), if ApplePay is the value, then we have a device with Apple Wallet.

Modes

Operation modes

Apple VAS has multiple operation modes. Mode setting affects:

Following modes are available:

  1. VAS or payment 00:
    Operates the same as VAS and payment (Info below). Can also be called VAS over payment, meaning that a reader tries to read a loyalty pass, if it has enough balance it ends the transaction. Otherwise it tries to charge the selected payment card.
  2. VAS and payment 01:
    Also called single tap mode. In this mode reader should select a VAS applet, read loyatly info, and after that select a payment applet and finish a transaction. This mode supports reading multiple different passes in a single tap, although UI will only tell about the first one. In this mode bringing the device to the field will display a default payment card, after auth it will also display that "Pass X will be also used" under the card. ![VAS and payment]
  3. VAS only 02:
    Used when you only need to read a pass. In this mode if a phone is brought into the field before auth it will present the needed pass on the screen for authentication. This mode allows to read only one pass at a time. If you preauthenticate a payment card, a needed pass will jump in place of a payment card when you bring the device to the reader. ![VAS and payment]
  4. Payment only 03:
    Forces a payment card to appear on a screen for authentication (like any other regular NFC field), but also serves as anti-CATHAY.

Protocol modes

VAS also has a protocol MODE flag.

  1. URL:
    Value 00. In this mode the reader works as a signup terminal. Tapping a device to it will display a sign-up notification on the screen.
  2. FULL:
    Value 01. Can be used for both pass redemption and URL signup advertisment.

ECP

For correct operation all readers that implement VAS have to have properly configured ECP.

Otherwise, some UX/UI-related features:

VAS ECP frames are also sometimes referred to as VASUP-A, both refer to the same thing.

All known VAS frames use ECP format V1, and they differ in last byte only, depending on operation mode:

Name Version TCI
VAS or payment 01 00 00 00
VAS and payment 01 00 00 01
VAS only 01 00 00 02
Payment only 01 00 00 03

Payment only configuration might seem rudimentary, as phone reacts to any reader as to payment one by displaying a payment card.
But it is not the case if a chinese transit card is added to device, which this configuration helps with.

Command overview

As of version 1 following commands are available:

Command name CLA INS P1 P2 DATA LE RESPONSE DATA Notes
SELECT VAS APPLET 00 A4 04 00 VAS AID 00 BER-TLV
GET DATA 80 CA 01 MODE BER-TLV 00 BER-TLV Data format described below

Commands are executed as follows:

  1. SELECT VAS APPLET:
    Reader transmits universal VAS AID; Device response with wallet implementation name in TLV tag 50.
    If value is 4170706c65506179, which is a value of ApplePay string in ASCII-encoded form, we have a device that supports Apple VAS.
    Other than that, device return current implementation version, a nonce (which is unused), and extra information.
  2. GET DATA:
    Reader sends protocol mode flag, selected protocol version, SHA256 of pass identifier, capabilities mask, and optional signup URL and filter values.
    Device responds with encrypted pass data or an error code in FULL VAS protocol mode, and a confirmation in URL ONLY protocol mode.
    In VAS And/Or Payment operation mode, reader may send this command multiple times during the same session in order to get passes from different providers. In VAS only operation mode, this command is executed only one time.
    • After a reading session has been completed, reader should DESELECT the device and do a TRESET to signify end of the transaction.
      It is required because VAS supports operation in combination with payment cards that are implemented using other NFC modes, for instance, Type F (FeliCa).
      DESELECT + TRESET in this case tells a device that it can now update NFC controller routing and configuration to match the configuration of a pending payment pass.
      Beware that due to that reason in VAS and/or payment modes, if you've failed to a read a pass due to connectivity issue, you shouldn't do a DESELECT and TRESET, as after that a device won't route any more requests to VAS until user preemptively ends and re-authenticates the session.

Command and response data format

Select VAS

Request:

CLA INS P1 P2 DATA LE
00 A4 04 00 4f53452e5641532e3031 00

Data contains an ASCII encoded form of "OSE.VAS.01" string;

Response

SW1 SW2 DATA
90 00 6f1d50084170706c655061799f210201009f2404c05d48d09f23040000001e

Response data example:

Get data

Request:

CLA INS P1 P2 DATA LE
80 CA 01 MODE * 00

P2 flag values were described in "Protocol Modes" section;

Request data: Name Tag Length Example Notes
Protocol version 9f22 02 0100 Always 0100
SHA256 of pass id 9f25 32 03b57cdb3eca0984ba9abdc2fb45d86626d87b39d33c5c6dbbc313a6347a3146 SHA of pass type identifier, such as pass.com.passkit.pksamples.nfcdemo
Capabilities mask 9f26 04 00800002 More info below
Merchant signup URL 9f29 Variable 68747470733a2f2f6170706c652e636f6d URL pointing to a HTTPS signup json signed by pass certificate
Filter 9f2b 05 0100000000 Meaning unknown, mentioned in public configuration PDFs (look at References section). Values other than provided in example make pass reading fail. Value is optional, but if present MUST start with byte 01
Nonce 9f28 04 01000000 Meaning unknown, could be an optional tag for mobile device nonce (see tag 9f24)

Capabilities mask

Consists of 4 bytes, numbered 0-3 from left to right

Byte 0 - RFU

Byte 1:

Mentioned in some public configuration PDFs, does not impact usage

07 06 05 04 03 02 01 00 Notes
1 VAS is supported
0 Vas is unsupported
1 Authentication required
0 Authentication not required
X X X X RFU
X X Terminal type
0 0 Payment
0 1 Transit

Byte 2 - RFU

Byte 3:

Important for protocol operation

07 06 05 04 03 02 01 00 Notes
1 More passes will be requested in this reading session
0 No more passes will be requested in this reading session
X X X X X RFU
X X VAS mode (like in ECP)
0 0 VAS or payment
0 1 VAS and payment
1 0 VAS only
1 1 Payment only

Command TLV data example:

Response:

SW1 SW2 DATA
XX XX 70549f2a009f274ebeef7375094afa4824addb8abf0a59f4c5b88f7b33cd803666cdf358dc8aa2ecea863673b7e92b8f39bc744233dda87e53f2ae346eb43415e7b20a50aa41e02de9f3d533f506e29b4ed31eaa9cfa
Status words: SW1 SW2 Notes
90 00 Pass data returned (full VAS) or URL was accepted (URL only)
6a 83 Pass not selected on a screen or unavailable
62 87 Device not unlocked (Apple Wallet will open, pass will appear on a screen for authentication)

Any other status word means that a command payload was built incorrectly, or that an applet was not yet selected.

Response data example:

Symbols [ and ] depict inclusive array indices, ( and ) depict exclusive indices. Numeration is done simillarly to Python

Cryptogram Information Data TLV tag contains following concatenated data:

Decryption

After receiving the response, the next step is to decrypt it.

Due to a nature of Apple VAS protocol, decryption can be done:

In both situations, decryption is done in the following steps:

  1. First 4 bytes of cryptogram data are taken, it's the key identifier of the pass public key key_identifier.
    Key identifier is important, as depending on backend implementation, pass keys may be rolled over over time, or be diversified between pass batches.
    Even in single key situations, it can be used in order to verify that you're attempting to decrypt a correct pass and not something else.
  2. Using the key identifier, we find matching pass private key by iterating through a list of private keys (better cache them, example only):
    1. Derive public key based on private key;
    2. Get public key bytes of the X component. Only X component is needed as for ECDH Y value does not matter.
    3. Calculate key identifier by doing SHA256 over the X component. Take first 4 bytes;
    4. Compare if instance key identifier matches the pass key identifier. If it's a match, then we have the corresponding private key;
      • If no matching key is found, in Online scheme we bail out, may save data for Offline decryption. In Offline scheme we bail out for good.
  3. Using the pass private key, do ECDH exchange with device ephemeral key, receiving shared key shared_key;
  4. Shared key shared_key is used together with shared info shared_info in X963KDF algorithm in order to get the derived key derived_key;
  5. Derived key derived_key is then used via AESGCM in order to decrypt pass data.
    • If your library requires it, you can prepend any sign byte (02, 03) to the EC public key data if you want to load it into an object representation during one of the steps.

Documentation on how to generate shared information and derived keys (steps 4. 5.) is not present in this document. For that information, visit the following gist. Don't forget to thank the author.

File located at examples/implementation/decryption.py contains Python code that implements the decryption proccess.
Crypto methods are provided by cryptography library.
Correct shared info calculation is omitted, but can be reconstructed by following the link mentioned in this section before.

Notes

Personal notes

References