8. Auth V2
Auth V2 is legitimately good. If you’re here because you want to try and understand the protocol to attack it, I can save you some time: you can’t. With that out of the way, back to the article
Auth V2 requires an non-Lv3 keychip (that is, equipt with an A7 security processor rather than N2) running at least firmware 2.10
Auth V2 (aka auth20) is a multi-step authentication process wherein the server performs a challenge-response process against the keychip using a nonce.
Requests are made on port 443 to
https://op.auth.sys-all.net. A valid certificate must be presented for a subdomain of
auth.sys-all.net. An additional root CA is trusted explicitly, alongside the base system certificate store:
8.1 High level: What is Auth V2?
Standard ALL.Net authentication uses the store IP address and keychip serial number to authenticate the client.
Auth V2 solves a number of problems:
- A legitimate keychip must be present, regardless of software modifications performed to the arcade machine
- The keychip needs to be able to validate the server’s identity
- The server needs to be able to validate the keychip’s identity
- Games need a way to validate the initialisation data (importantly, the game server URI)
- No part of the protocol can be vulnerable to replay attacks
All cabinet-side processing of Auth V2 is performed within the keychip, and all communication is encrypted in transit (using the “allnet key”). The keychip drivers serve as a proxy, and perform no other processing. The required functionality for this was added in firmware version 2.10.
The keychip presents the server with a nonce, which the server is expected to encrypt with a key (called the “server key”) and return encrypted to the keychip. Using this, the keychip is able to validate the authenticity of the server. The keychip will then encrypt a nonce the server sent with a key (called the “keychip key”), which is returned to the server. The server validates this data, and finally returns standard initialisation data, however additionally includes a signature that games can use to validate its authenticity.
While the cryptography used is symmetric (AES) and requires pre-shared keys, these keys are stored within the security processor on the keychip and cannot be extracted.
Shared knowledge of the unique (allnet key, server key, keychip key) tuple is required for authentication to be possible. This tuple is different for every keychip. There is no derivation algorithm for the keychip key; it is quite literally 16 bytes from
The keychip first validates the server’s authenticity before encrypting the nonce to reply to the server. For this reason, a malicious request cannot be made to the keychip requesting it encrypt a nonce to then be used against a legitimate server. The auth server challenge nonce is generated internally in the keychip, and contributes to the final 16 bytes of the packet, the encrypted form of which is used as the communication IV. As such, replay attacks are not possible.
8.2 Brief cryptanalysis
All cryptography here is using AES in CBC mode with no padding. The ability to control the IV therefore allows a potential attacker to manipulate the decryption of the first 16 bytes of data.
This would potentially allow for manipulation of the keychip ID during a replay attack. The handshaking process, and use of multiple nonces during the process, mitigates the ability for replay attacks, rendering this form of manipulation useless.
The IV to encrypt nonces using is decided by the issuer of the nonce, and therefore cannot be controlled by the other party. As both parties take turns issuing an (IV, nonce) pair, controlling the IVs here is only possible if both parties are malicious in which case we’re just rekeying a complete custom implementation rather than attacking anything!
An initial request is made to
/net/certify. This request contains a url-encoded
The server will then use the server key associated with the specified keychip to encrypt the nonce. The following response structure is then formed:
This structure is transmitted to the client as
packet_data=base64(encrypt(response)), using the final 16 bytes of the encrypted request as the IV.