Some three decades ago, Bruce Schneier famously wrote:

There are two kinds of cryptography in this world: cryptography that will stop your kid sister from reading your files, and cryptography that will stop major governments from reading your files.

I remembered the quote as I came across a (minor) government using the wrong kind of cryptography. As one would expect, they do have some reasonable security protocols in place. These are complemented, rather surprisingly, by several examples of cryptography your kid sister can break. Why cannot a government tell the difference?

eID Client

Slovakia has been issuing electronic identification cards for several years. The use of electronic government services is now mandatory for some users. The government provides a set of software tools to enable the two main purposes of the eID: on-line authentication and (off-line) electronic signatures. On the positive side, the software usually does the job.

On the other hand, security software merely "working" is an incredibly low bar. A closer look reveals several improper applications of cryptography. All the issues revolve in one way or another around hard-coded cryptographic keys.

Integrity test

One of the first things the program does when started is an "integrity test". The test has apparently been in place for reasons of security, functionality & stability.

There is a text file filesHash.json that contains a list of files to check along with SHA-256 hashes of their content. A separate file filesHash.json.sig contains a 2048-bit RSA signature of filesHash.json.

The public RSA key used to verify the signature is embedded in the main executable of eID Client. Any change in any of the files included in the test will (almost) inevitably lead to a different SHA-256 hash. One would then have to edit filesHash.json and invalidate the signature. That might look reasonable, but the complete test can be disabled (as is often the case) by flipping a single bit in the main executable.

It turns out that the "integrity test" can be circumvented even without changing any executable code. The eID Client does not check the code that gets loaded, but rather what lies on disk. On some systems, there are trivial ways to start a program with a preloaded custom shared library rather than the one the application would load on its own. This of course leaves the "integrity test" intact while actually running with modified libraries.

Cross-platform signature transplant

The eID Client software is available for three platforms: GNU/Linux, Mac OS and Microsoft Windows. The RSA key pair used to sign filesHash.json is the same across the platforms. One can therefore use filesHash.json and filesHash.json.sig from a package for a different platform. In order to pass the "integrity test", simply also copy all the files referenced by the "alien" list. Because of different path & naming conventions (.dll/.dylib/.so), every filename within filesHash.json only appears on a single platform. If all the necessary files are copied from Mac OS over to Linux (say), no library gets overwritten. If you then start the Linux executable, the program will load the appropriate Linux libraries without checking them and then happily verify the integrity of all the files listed in filesHash.json meant for Mac OS.

Cross-protocol signature transplant

The eID client is typically triggered by a HTTP call from the Web browser whenever strong on-line authentication is desired. The request contains the address of the authentication server the eID client is meant to interact with. Here is an example of a one such local request:

http://localhost:15480/?tcTokenUrl=https%3A%2F%2Feidas.minv.sk%2
Fedoc%2Feac%2Finit%3FtokenId%3D316bcd6f0751d13bb340%26nodeId%3D2
%26security%3D8f2096cab4ace68e2ea0d8f42d3091c12ab3b376eb7389238c
938224b823d93bc299a618cfcb930f507d072b4fb3e70e772b79e4b99d2d8bee
03374cd349c4982bc41c7ccd11bec3c596f1ec207779744eb815936a2f870052
385f06f5854593073ae04b4006307c877cb0c3672acbd0b7f4b855a5cee6d86f
10efc07aedbe7ceb921dacce033c85e1b254d5dbc6b2c1ba168b8b2dc70b5ff4
d843d62fe7702a088e40f64c0dfef6d3fcd5019e72e57fd5b8dae0147e8f27e1
dd8c3b359732bc22b62f13a36a0517dca8b8ff8824905cec66ce5cc4e0c2d22a
da10bf8037ddd630ab133d1a4b00490656d614736fc1f2b4ece3dfc3f4900d9d
34205640f7ce46

The request contains the URL of the authentication server:

https://eidas.minv.sk/edoc/eac/init?tokenId=316bcd6f0751d13bb340&nodeId=2

and an RSA signature over the URL:

8f2096cab4ace68e2ea0d8f42d3091c12ab3b376eb7389238c938224b823d93b
c299a618cfcb930f507d072b4fb3e70e772b79e4b99d2d8bee03374cd349c498
2bc41c7ccd11bec3c596f1ec207779744eb815936a2f870052385f06f5854593
073ae04b4006307c877cb0c3672acbd0b7f4b855a5cee6d86f10efc07aedbe7c
eb921dacce033c85e1b254d5dbc6b2c1ba168b8b2dc70b5ff4d843d62fe7702a
088e40f64c0dfef6d3fcd5019e72e57fd5b8dae0147e8f27e1dd8c3b359732bc
22b62f13a36a0517dca8b8ff8824905cec66ce5cc4e0c2d22ada10bf8037ddd6
30ab133d1a4b00490656d614736fc1f2b4ece3dfc3f4900d9d34205640f7ce46

This is a useful (and necessary) feature. The eID client will only act upon requests known to originate from a legitimate government authentication server.

For some reason, the key used to compute the signatures here is the same as the key used to sign filesHash.json. Therefore if you put the URL in the one file and the signature in the other, the integrity test will succeed. The fact that the JSON file is not properly formatted does not cause an error. The software will instead extract an empty list of files to check and then happily iterate over it. All the hash values of all the files will (inevitably) match.

Web service authorization

On-line authentication using the eID is performed by reading the personal information from the chip. The card enforces Extended Access Control (EACv1; BSI TR-03110) and only discloses the information to properly authenticated terminals. One such terminal is the authentication server operated by the government. Strong public-key cryptography is used to establish a secure channel between the remote server and the chip of the eID. The personal computer the card reader is connected to merely pushes the (encrypted) bits back and forth between the actual participants in the protocols (Chip Authentication & Terminal Authentication; BSI TR-03110-1). At no point can the computer access the personal information read from the chip, unless the remote terminal chooses to reveal some of it.

The eID Client does come with the option to simply view the data in the chip. The digital photograph of the card holder, if present, can be extracted off-line after entering the Card Access Number (CAN). Other personal information must be read remotely by the authentication server and is then presented on screen. In contrast to actual on-line authentication that typically requires entering a PIN code, viewing the data on the card was possible without entering any codes. Since about May 2023, the eID Client has required a PIN to display the data.

One could argue that displaying the information without requiring any PIN codes is fine, the data shown on screen can also be read from the card with bare eyes after all. Yet the chip and all the protocols around it are designed to only ever reveal personal information to authorized parties. A Web service that reads data from any ID without the need to enter any codes renders Extended Access Control rather useless.

The access to the Web service was in fact somewhat restricted. When about to read data from the ID, the initial HTTP request sent by the client contained the following header:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhd
WQiOiJlaWQtYXBpLWd3IiwiY2xpZW50X2lkIjoiZUlEX2tsaWVudCIsImlhdCI6M
TY4NzAwMDQ3MywiaXNzIjoiZUlEX2tsaWVudCIsIm5vbmNlIjoicHNGTm8xTi9VL
zd5dGlFZkdNajkvQ2Nubkt4anQ3ZzVCRGkxVXdzakltRT0ifQ.3TEM0tSfFIXOIt
rbANSW2jvosF6ENyUFAyP4Mkk_32I

It is a JSON Web Token that decodes as:

{'aud': 'eid-api-gw',
 'client_id': 'eID_klient',
 'iat': 1687000473,
 'iss': 'eID_klient',
 'nonce': 'psFNo1N/U/7ytiEfGMj9/CcnnKxjt7g5BDi1UwsjImE='}

The token carries an (HMAC SHA-256) authentication code. In earlier versions, the MAC key was a fixed 256-bit string hard-coded in the eID Client executable. As such keys are usually trivial to extract, anybody was able to generate valid "authorization headers" and access the service.

Recent versions of the eID Client have switched from a fixed HMAC key to a variable key that is a function of a hard-coded 256-bit seed, time and some of the data to be authenticated. This variant is equally insecure.

The remote terminal allowing to read data from the IDs without entering any PIN has essentially been taken off-line. Yet such access to the cards remains possible, the chips are programmed that way. This behaviour is deliberate and documented:

Some service providers are authorized to verify identity without entering your PIN.

Chip access control

The most recent generation of the ID issued since December 2022 supports contactless operation. Such cards almost always require secure messaging (ISO/IEC 7816-4, also see BSI TR-03110-3 Appendix F) setup at the very beginning of any interaction. This makes sense, as wireless communication is easier to eavesdrop on.

There are two ways to establish the initial secure channel with the card: Basic Access Control (BAC; ICAO Doc 9303 Part 11) and Password Authenticated Connection Establishment (PACE; BSI TR-03310-2). BAC uses information from the machine readable zone (MRZ), in particular the document number, date of birth and date of expiry to derive encryption keys. Only those with physical access to the document should be able to read the necessary information. The protocol only uses symmetric primitives (3DES). PACE, a modern successor of BAC, employs public-key cryptography (ECDHE) to establish strong keys even if the shared secret has low entropy.

Several (if not all) generations of the Slovak eID have supported PACE, including the most recent one. It is therefore rather surprising that the new cards (sometimes) actually make use of BAC. Why run BAC when PACE is available? It turns out that the BAC the Slovak eID uses is rather special. Instead of the information from the MRZ that is guaranteed to be unique to a particular card, the special version uses the same fixed key for all the cards. Given the nature of BAC, the knowledge of this key allows one to decrypt any past transcript of the protocol. The key is embedded in the executable of the eID Client and therefore public. This version of BAC cannot possibly provide any benefit at all.

Maybe the design is in place to enable the execution of Extended Access Control and reading of personal information without the need for any codes. Now the liberal Web service (see above) has been shut down, the current generation of eIDs is the first one, where PACE (usually) precedes Chip & Terminal Authentication. This is a mere (server-side) software "fix", the chips remain programmed the old way.

I wonder whether the fixed BAC key can facilitate card tracking. In any case, some service providers might be authorized to read personal information from your ID whenever it is in range.

PIN encryption

The card comes with several PIN codes that have to be entered to confirm various sensitive operations. There is a separate GUI application called Virtual keyboard in charge of prompting the user for a code and forwarding the input to the module interacting with the card. The transmission of the PIN code to the caller is encrypted and has the following form:

-{WBCvDgMuNDiCP85evglH0w==}-

The ciphertext is the same every time the code is entered. Even without knowing how the encryption works, the encrypted form can be used in a simple replay attack. If you capture the encrypted PIN, you can later reuse it without ever learning the value. Given both the user PIN and the signature PIN must consist of six decimal digits, there are precisely one million possible ciphertexts. By successively entering PIN codes, one can build a complete table of plaintext-ciphertext pairs:

000000    -{QKqbHj1c7xWMGFRbn7eoYw==}-
000001    -{vQ0Za98xVf3wyG7gVrG8HQ==}-
000002    -{BCilvRN+SaMmn6niyjgYXw==}-
000003    -{4t95dOqe6QZN8aCVFA1cgQ==}-
000004    -{SHCAmSXoJ2BNMA0kiYrn5w==}-
000005    -{TqjpXE2t4hMksWs0yyF/tw==}-
  ⋮                     ⋮
999999    -{Uw9fyHSENx3TaNSs2nSkMg==}-

Without knowing the key or even the encryption algorithm, any ciphertext can be decrypted by simply looking it up in the table.

The ciphertexts are in fact the result of AES in ECB mode with PKCS #7 padding. The 256-bit key is hard-coded in the executables. There is nothing useful this kind of encryption could possibly achieve.

Conclusion

At its core, the Slovak eID platform is probably fine thanks to secure hardware and the strong cryptography used within EAC. In terms of security, most of the problems I describe do not matter.

The bad cryptography does not contribute anything, therefore little would be lost if no cryptography were used instead. Still, bad cryptography can be worse than none at all, as it offers a false sense of security. It also results in a lot of code that needs to be written, tested, debugged, maintained, documented and supported.

Most importantly, the mere presence of bad cryptography erodes trust. How do we know whether all the other (important) cryptography was implemented properly? The government cannot simply establish trust by decree. Comprehensive publication of specification and source code might help. The information has been withheld "for security reasons". There is another fundamental distinction the government appears unable to draw, that between security and obscurity.