No momento, esta página não está disponível em português
Default icon

Security guidance

Mechanisms and procedures to protect the mobile payments solution.

This chapter lists the assets managed in our solution, and describes the security measures taken to protect those assets and the solution as a whole.

Assets

Name Description Protection claim
Source code Kotlin and C++ code. C and I: Obfuscated using zShield, which also adds integrity checks. Distribution access is closed, except to our merchants.
PIN CVM application Adyen SDK. C and I+
L2 kernel Level 2 kernel library. C and I: Pre-obfuscated using zShield and customized build.
Attestation data Device health data. C and I+: Encrypted and sign during transport.
Sensitive card data Track 2 data or equivalent data (account data). C and I+: Never stored on the device, immediately encrypted using DUKPT and cleared from memory for communication with the Adyen server.
PIN data PIN Data. C and I+: Never stored on the device, immediately encrypted using DUKPT and cleared from memory for communication with the Adyen server.
Cryptographic keys Check the inventory of keys. C and I: Check the inventory of keys.
Session token Authenticates the app installation and enables direct communication with Adyen servers. C and I+: Requires the merchant's private API key and SDK key signature to be generated, and is signed with an Adyen internal key for integrity.

HSM

We use Payshield 9000 and 10000 HSM machines. This enforces PCI rules for our key generation and secure encryption processes. The HSM holds the base derivation key (BDK) that is used to derive the Initial PIN Encryption Keys (IPEKs) loaded into each payment-enabled device in our mobile payments solution. This BDK is also used to generate the TR-34 block during key loading.

Cryptography

For sensitive data we use the white-box encryption library Zimperium zKeyBox interfacing with our native code. For high-level data encryption for storage and device binding we use the Android Keystore system.

Protection of cryptographic keys

To protect the cryptographic keys used in mobile payments solution, we use Zimperium zKeyBox: a library that provides an API for executing the most common cryptographic algorithms in a secure manner. The main purpose of zKeyBox is to hide and protect cryptographic keys so that they are never revealed in plain form, even during the execution of cryptographic algorithms. This makes it extremely difficult for attackers to locate, modify, and extract the cryptographic keys.

The secure properties of zKeyBox are based on white-box cryptography. This ensures that the implementation of cryptographic algorithms is secure in fully observable and modifiable execution environments. In other words, zKeyBox is designed to protect cryptographic keys in open environments where anyone could potentially gain full control over the code, memory, and storage of the COTS device.

Mobile app security mechanisms

We use various components from Zimperium zShield to protect the solution:

Obfuscation

Obfuscation is provided by zShield v2.94.1, which transforms the Java bytecode generated by our Kotlin project into native code. zShield uses a number of code obfuscation techniques, including a patented control flow flattening algorithm.
The same protections are applied to the native code.

Integrity protection

Integrity protection is a set of measures that makes it difficult to modify app code and read-only data. zShield achieves integrity protection by splitting the entire code and data section into overlapping regions that are verified at runtime. Verification is performed by numerous small pieces of code, called checks, that are automatically inserted into the protected app code. Each check calculates a checksum of a particular code or data region and compares the checksum to the expected value, which was calculated at build time.

Anti-debug protection

Anti-debug protection is a technique that allows an app to detect the presence of debugging or hooking tools, and to defend itself against those threats. zShield inserts numerous anti-debug checks of various types into the protected code.

Inlining of static functions

zShield is capable of inlining simple static functions, which means that every call of such functions is replaced with the actual function body. This increases the obfuscation level of the final protected code and makes it more difficult to trace.

String literal obfuscation

zShield provides a security feature that obfuscates a large portion of string literals in code and de-obfuscates them only just before they are actually used. This increases protection against static analysis.

Android rooting detection

zShield inserts numerous rooting detection checks of various types into the protected app. These checks execute a defense action if a rooted device is detected.

Android signature verification

zShield provides a special feature that protects Android packages against tampering by embedding the original public signing keys into the protected code.

Android resource encryption

zShield is capable of protecting arbitrary resource files of Android apps, such as text, XML, image, video, and music files. This means that these protected resources are stored in encrypted form and decrypted only at runtime when they are actually used.

Dex file encryption

As an additional layer of protection against static analysis, zShield provides the option to encrypt .dex files. This means that these files will be stored in encrypted form and decrypted only at runtime.

Binary packing

For enhanced protection against static analysis, zShield provides a security feature that allows you to pack binary code of the target app. Packing means that the code section and the read-only data section of binary code are encrypted; an appended stub decrypts them into memory only at runtime.

Cross-checking of shared libraries

One way how bad actors can attack an app is by replacing or modifying the shared libraries that the app uses. zShield provides a feature called cross-checking of shared libraries that makes this type of attack significantly more difficult.

PIN capture and handling

We use Zimperium Secure PIN to protect PIN entry. Secure PIN is a set of tools to implement secure graphical user interface (GUI) based PIN entry in Android applications. The core principle of Secure PIN is to ensure protection of the entry and processing of PINs. The protections provided by Zimperium Secure PIN include:

  • Protection against screen recording and capture.
  • The PIN entry screen detects loss in foreground and overlays. This enables us to cancel PIN entry if there is a switch to a different application.
  • PIN digits are masked while the shopper enters their PIN in the PIN pad UI. Only “*” is shown to the shopper.
  • PIN digits are not stored in plaintext in RAM.
  • The Secure PIN UI does not rely on standard buttons of the Android operating system. Instead, a custom implementation is used.
  • There is no haptic, audible, or visual feedback that could reveal which digit the shopper is entering.

When the shopper enters their PIN, the PIN is immediately encrypted into an ISO Format 4 PIN block with a freshly generated surrogate (fake) PAN and a freshly derived DUKPT. All cryptographic operations happen within the Zimperium zKeyBox component. The PIN and all related keys and buffers are cleared from RAM. The PIN never exists in plaintext in RAM, and is never cached or stored persistently.

Hardware backed key attestation

During the authorization phase, the SDK performs hardware backed key attestation on the generated key pair. Therefore a session cannot be started on a tampered device. The SDK generates a certificate with an attestation challenge which is checked by the backend for any flags indicating that the device bootloader is unlocked or that the key was not generated in a trusted execution environment.

Secure storage

Any information the SDK needs to store locally, is first hashed for an integrity check, and then encrypted using the Android Keystore system . This applies to information like:

  • Installation UUID
  • Kernel configuration
  • Merchant configuration

For storing sensitive assets like current DUKPT states, we added an additional layer of encryption. A DUKPT state is only generated and updated inside the white-box library and then exported in a protected format (encrypted under the white-box key). Whenever we export this state, we generate a new AES-128 key and encrypt the DUKPT state with it, returning to the native code a blob of data that contains an Encrypt(protected DUKPT)+protected AES key.

The Kotlin code then encrypts this blob of data again using the default storage mechanism described above, with an integrity check and encrypted using the Android Keystore system.

Backend security mechanisms

Our backend is certified under several security standards, such as PCI-DSS, PCI-PIN, and P2PE.

Monitoring and attestation

To scan for security issues at runtime, the security module includes Zimperium zDefend Monitoring. This third-party SDK works both with and without network connectivity, and includes ZDefend Console.
For more information, see Monitoring and attestation.

Device binding

Device Binding is achieved using the Android Keystore system. If an attacker tries to clone the hosting app to a different device, the app will not work because the Keystore keys will be missing.

Tamper detection and response

Whenever a threat of significant severity is detected by either our monitoring system or one of the code protection measures, the transaction is blocked locally. All threats are reported to the monitoring system. The monitoring system is checked by checkoutpos, which handles the payment processing. This means that checkoutpos can block transactions from a compromised device. When any threats are detected, the SDK clears DUKPT states.

Secure installation

The installation source is validated by Zimperium zDefend. This component reports a threat if the application has been sideloaded or installed from untrusted sources.

Secure communication with the Adyen backend

We ensure secure communications between the SDK and the Adyen backend in the following ways:

  • As explained in Mutual authentication, we establish a secure session between the SDK and the Adyen backend.
  • All data is transported and protected in a secure channel. In addition to the secure channel, all requests coming from the Adyen SDK are signed by the Device key pair, to enforce the authenticity of the request.
  • We enforce TLS 1.2, and we detect any downgrading attacks on the TLS protocol.

Forced updates

Our backend will deny transactions if we consider the SDK version to be too old. We check the SDK version using the embedded SDK key, which is unique per SDK version.

Baseline definition and requirements

As part of our baseline acceptance, only supported devices will be able to integrate our SDK. For platform and device requirements refer to Supported devices and operating system versions.

Whenever Android stops supporting security patches for an accepted operating system (OS) version, we remove that OS version from the accepted baseline. This means that the SDK will not be able to perform transactions on a device with an OS version that we no longer accept.

We keep track of newly disclosed OS vulnerabilities and react to them by adapting the OS baseline support.

Secure development

Every merge request requires passing static analysis, unit tests, and code review approval from at least one other developer.