Skip to content

Instantly share code, notes, and snippets.

@pyllyukko
Last active July 3, 2026 08:31
Show Gist options
  • Select an option

  • Save pyllyukko/a1ed6baa6b638b805a30b16960399e94 to your computer and use it in GitHub Desktop.

Select an option

Save pyllyukko/a1ed6baa6b638b805a30b16960399e94 to your computer and use it in GitHub Desktop.
FINEID notes

FINEID

Card

pcsc_scan (from pcsc-tools) output:

3B 7F 96 00 00 80 31 B8 65 B0 85 04 02 1B 12 00 F6 82 90 00
	Finnish ID-card v5.0(?) (eID)
	https://dvv.fi/en/fineid-specifications

S/MIME with Mutt, gnupg-pkcs11, GPGME & mpollux

The communication flow is as follows: mutt -> gpgme -> (gpgsm) -> gpg-agent -> gnupg-pkcs11-scd -> libcryptoki -> smartcard

Prerequisites

Configuration

~/.gnupg/gpg-agent.conf:

scdaemon-program /usr/bin/gnupg-pkcs11-scd

~/.gnupg/gnupg-pkcs11-scd.conf:

providers p1
provider-p1-library /usr/lib64/libcryptoki.so

muttrc:

set crypt_use_gpgme
set smime_default_key="12345678.0" <- check your ID with the commands described below in "Usage"
set nohonor_disposition

Usage

gpgsm --learn-card

Run gpgsm --list-keys and check the ID of your cert with key usage: digitalSignature keyEncipherment dataEncipherment.

You can test whether your card is identified by running gpg-agent --server gpg-connect-agent and issuing the SCD LEARN command.

S/MIME with Mutt, OpenSSL & mpollux

Prerequisites

Determine your private key ID with pkcs11-tool --module /usr/lib64/libcryptoki.so --list-objects --type privkey. It should look like this:

Private Key Object; RSA 
  label:      todentamis- ja salausavain
  ID:         45
  Usage:      decrypt, sign

Determine the IDs of your "todentamis- ja salausvarmenne" certificate and the intermediate CA "VRK Gov. CA for Citizen Certificates - G3" certificate with the following command:

pkcs11-tool --module /usr/lib64/libcryptoki.so --list-objects --type cert

Extract the "todentamis- ja salausvarmenne" and "VRK Gov. CA for Citizen Certificates - G3" certificates from the card into separate files with (repeat and save into different files):

pkcs11-tool --module /usr/lib64/libcryptoki.so --read-object --id KEY_ID --type cert --output-file cert.der

Convert them from DER to PEM (repeat for both certificates):

openssl x509 -in cert.der -inform DER -out cert.pem -outform PEM

Configuration

OpenSSL

Create the following OpenSSL configuration (see Using the engine from the command line):

openssl_conf = openssl_init

[openssl_init]
engines = engine_section

[engine_section]
pkcs11 = pkcs11_section

[pkcs11_section]
engine_id = pkcs11
dynamic_path = /usr/lib64/engines-1.1/pkcs11.so
MODULE_PATH = /usr/lib64/libcryptoki.so
init = 0

Mutt

  • You need to disable GPGME in Mutt, so you can use the old school smime_*_commands
  • cert.pem is the extracted "todentamis- ja salausvarmenne" certificate
  • ca.pem is the "VRK Gov. CA for Citizen Certificates - G3" intermediate CA certificate
  • The key ID is hardcoded and determined in the "Determine your private key ID" part
  • smime_default_key and smime_sign_as are just dummy values so Mutt doesn't prompt you for the key ID

Add the following to your muttrc:

unset crypt_use_gpgme
set smime_default_key="12345678.0"
set nohonor_disposition
set smime_decrypt_command="OPENSSL_CONF=/path/to/openssl.conf openssl smime -decrypt -engine pkcs11 -keyform engine -inform DER -in %f -inkey 45"
set smime_sign_as="87654321.0"
set smime_sign_command="OPENSSL_CONF=/path/to/openssl.conf openssl smime -sign -engine pkcs11 -keyform engine -signer /path/to/cert.pem -certfile /path/to/ca.pem -inkey 45 -in %f -outform DER"

Usage

Mutt will ask you for a passphrase, but as this comes from mpollux you can enter anything to the prompt.

SSH

If you have #1608 patch, you can get your SSH public key with pkcs15-tool --read-ssh-key ID where ID is the ID of your "todentamis- ja salausvarmenne" certificate. You also need to have the following in /etc/opensc.conf or otherwise pkcs15-tool will not work:

app default {
	card_atr 3b:7f:96:00:00:80:31:b8:65:b0:85:04:02:1b:12:00:f6:82:90:00 {
		driver = fineid;
	}
}

Do note that the patch does not seem to work properly with FINEID v5, except for the pkcs15-tool part so leaving it to your opensc.conf is not recommended.

Other option to convert your certificate into SSH authorized_key is to run openssl x509 -in cert.pem -noout -pubkey | ssh-keygen -i -m PKCS8 -f /dev/stdin.

You need to have the following in your SSH client configuration (ssh_config):

Host ...
	PKCS11Provider /usr/lib64/libcryptoki.so

Then just add the public key into your authorized_key and you can authenticate with your FINEID card.

mPollux notes

mPollux stores "DigiSign WebSigner ROOT Certificate" into your ~/.pki/nssdb database. It uses a password, which you can find from ~/.digisign/Seed.txt.

See DigiSignApplication.bin:

nth   paddr      vaddr      len  size section type    string
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
2856  0x0043b520 0x0043b520 19   20   .rodata ascii   /.digisign/Seed.txt
52823 0x006d4041 0x006d4041 2288 2289 .rodata ascii   #!/bin/bash\n\npwdfile=$1\nnsdCreate=$2\n\nif [ -f /usr/lib/libcryptoki.so ]; then\n   cryptokiPath=/usr/lib/libcryptoki.so;\nelse\n   cryptokiPath=/usr/lib64/libcryptoki.so;\nfi\n\nif [ "$nsdCreate" = "true" ]; then\n   certutil -d sql:$HOME/.pki/nssdb -N -f $pwdfile\nfi\n\nif [ $? -gt 0 ]; then\n   echo nssdb creation failed\n   exit 1\nfi\n\nhostname=$(hostname)\nif [ -z "$hostname" ]; then\n   echo hostname not defined\n   exit 1\nfi\n\nrootname="DigiSign WebSigner ROOT Certificate for $hostname"\n\n#Wrong password exit status: \n#   local nssd: 2\n#   firefox and thunderbird: 3\n\n#add root certificate to nssd db sent by parameters\naddRootCertificate()\n{\n   dbPath=$1\n   isPwdFile=$2\n   exitStatus=$3\n\n   certCheck=$(certutil -d $dbPath -L | grep "$rootname")\n   if [ -n "$certCheck" ]; then\n      #remove old certificate, ignore if it doesn't exist\n      certutil -d $dbPath -D -n "$rootname"\n   fi\n\n   if [ "$isPwdFile" = "true" ]; then\n      certutil -d  $dbPath -A -t "TC,Tw,Tw" -n "$rootname" -i /etc/xdg/Fujitsu/SSLCA.cer -f $pwdfile\n   else\n      certutil -d $dbPath -A -t "TC,Tw,Tw" -n "$rootname" -i /etc/xdg/Fujitsu/SSLCA.cer\n   fi\n   if [ $? -gt 0 ]; then\n       #if certificate inset failed for some reason, certutil added incorrect data to db. Clean incorrect data from db.\n       certutil -d $dbPath -D -n "$rootname"\n       exit $exitStatus\n   fi\n   #update pkcs11.txt\n   isInFile=$(cat $dbPath/pkcs11.txt | grep -c "DigiSign PKCS#11 Module")\n\n   if [ $isInFile -eq 0 ]; then\n      echo "library=$cryptokiPath" >> $dbPath/pkcs11.txt\n\t  echo "name=DigiSign PKCS#11 Module" >> $dbPath/pkcs11.txt\n   fi\n}\n\naddRootCertificate $HOME/.pki/nssdb true 2\n\nif [ -d ~/snap/firefox ]; then\necho snap version\n   for certDB in $(find ~/snap/firefox/common/ -name "cert9.db")\n   do\n      certDir=$(dirname ${certDB});\n\t  addRootCertificate $certDir false 3\n   done\nelse\n   for certDB in $(find  ~/.mozilla* ~/.thunderbird -name "cert9.db")\n   do\n      certDir=$(dirname ${certDB});\n\t  addRootCertificate $certDir false 3\n   done\n   #we need also check cet8.db for old version of Firefox or thunderbird. More related to Ubuntu 32 version\n   for certDB in $(find  ~/.mozilla* ~/.thunderbird -name "cert8.db")\n   do\n      certDir=$(dirname ${certDB});\n\t  addRootCertificate $certDir false 3\n   done\nfi\n\nexit 0\n

Atostek ID notes

Atostek ID is the new software that is going to replace mPollux. All these notes are about the Debian package.

Version 4.4.1.0

https://files.fineid.fi/download/atostek/4.4.1.0/linux/AtostekID_DEB_4.4.1.0.deb

6fec3d89bf2ff95a2f12acd2d28563b9a4ce416d82de52e882401c4bce4ca647  AtostekID_DEB_4.4.1.0.deb

Mysterious private key

A mysterious private key is embedded within the binary:

nth   paddr      vaddr      len  size section type    string
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
2197  0x005735a1 0x005735a1 3500 3501 .rodata ascii   -----BEGIN ENCRYPTED PRIVATE KEY-----\r\n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\r\n-----END ENCRYPTED PRIVATE KEY-----\r\n

Couldn't find any code referencing it and apparently the installCA function does generate it's own keys.

installCA function

You can find a reference string:

nth   paddr      vaddr      len  size section type    string
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
471   0x0056521c 0x0056521c 27   28   .rodata ascii   Entering installCA function

From there you can find the function:

address            noret size  nbbs edges    cc cost          min bound range max bound          calls locals args xref frame name
================== ===== ===== ===== ===== ===== ==== ================== ===== ================== ===== ====== ==== ==== ===== ====
0x000000000013c180     0 7025   256   418   164 2394 0x000000000013c180  7279 0x000000000013ddef   288   31      1    1   520 fcn.0013c180

PKCS #12 password

I dislike the idea of having random private keys stored on my computer and not knowing how to unlock them.

When you run the binary with the -installCA parameter, it creates this AID-ERASMARTCARD-EHOITO-FI-CA CA certificate for you into ~/.local/share/Atostek Oy/Atostek ID/ directory. The password for the PKCS #12 file is DyCpu4fB4y4WdsnCG6k3. The password is the same between different machines (e.g. not using any instance specific attributes to generate a unique one). You can breakpoint PKCS12_create to catch it.

You can see the password loaded into the r12 register before calling the function at 0x0013e430:

            0x0013ca7a      4c8b6590       mov r12, qword [rbp - 0x70]

The -installSCSCA parameter installs another cert (AID_SCSCA) and the password for that is Le3svzKWE2OD4cgWzXan.

The deobfuscation function (for installCA) is as follows:

╭ 82: fcn.0013e1f0 (int64_t arg1);
│ `- args(rdi)
│           0x0013e1f0      53             push rbx
│           0x0013e1f1      31d2           xor edx, edx
│           0x0013e1f3      4889fb         mov rbx, rdi                ; arg1
│           0x0013e1f6      4c8d05a372..   lea r8, str.xYue6hgg5ImeRot68oYdAdding_certificate ; 0x5654a0 ; "xYue6hgg5ImeRot68oYdAdding certificate"
│           0x0013e1fd      488d357c72..   lea rsi, [0x00565480]
│           0x0013e204      4883ec20       sub rsp, 0x20
│           0x0013e208      4889e1         mov rcx, rsp
│           ; CODE XREF from fcn.0013e1f0 @ 0x13e227(x)
│       ╭─> 0x0013e20b      66410f6e0410   movd xmm0, dword [r8 + rdx]
│       ╎   0x0013e211      660f6e0c16     movd xmm1, dword [rsi + rdx]
│       ╎   0x0013e216      660fefc1       pxor xmm0, xmm1
│       ╎   0x0013e21a      660f7e0411     movd dword [rcx + rdx], xmm0
│       ╎   0x0013e21f      4883c204       add rdx, 4
│       ╎   0x0013e223      4883fa14       cmp rdx, 0x14
│       ╰─< 0x0013e227      75e2           jne 0x13e20b
│           0x0013e229      4889df         mov rdi, rbx
│           0x0013e22c      be14000000     mov esi, 0x14
│           0x0013e231      4889ca         mov rdx, rcx
│           0x0013e234      e8976ef9ff     call sym.imp.QString::fromLatin1_QByteArrayView_ ; QString::fromLatin1(QByteArrayView)
│           0x0013e239      4883c420       add rsp, 0x20
│           0x0013e23d      4889d8         mov rax, rbx
│           0x0013e240      5b             pop rbx
╰           0x0013e241      c3             ret

The XOR key is this:

nth   paddr      vaddr      len  size section type    string
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
497   0x005654a0 0x005654a0 39   40   .rodata ascii   xYue6hgg5ImeRot68oYdAdding certificate

The obfuscated password is here:

- offset -  4041 4243 4445 4647 4849 4A4B 4C4D 4E4F  0123456789ABCDEF
0x0013c240  4889 8568 feff ffe8 0491 f9ff 488b 75a0  H..h........H.u.
0x0013c250  488b 5598                                H.U.

You can deobfuscate the "secret" with r2 -n -qc 'e io.cache=true; b 20; s 0x565480; wox `p8 20 @ 0x5654a0`; ps' atostekid.

For the installSCSCA the deobfuscation function is here:

address            noret size  nbbs edges    cc cost          min bound range max bound          calls locals args xref frame name
================== ===== ===== ===== ===== ===== ==== ================== ===== ================== ===== ====== ==== ==== ===== ====
0x0000000000219220     0   82     3     3     2   27 0x0000000000219220    82 0x0000000000219272     1    0      1    4    40 fcn.00219220

Deobfuscate with: r2 -n -qc 'e io.cache=true; b 20; s 0x56fac0; wox `p8 20 @ 0x56fae0`; ps' atostekid.

Version 4.5.0.0

https://files.fineid.fi/download/atostek/4.5.0.0/linux/AtostekID_DEB_4.5.0.0.deb

14d2e980e27e8bdd0a27a3bec925864018540ae3f09baf146f19c4986890b3e4  AtostekID_DEB_4.5.0.0.deb

The installation manual states the following:

Atostek ID -sovellus tukee kaikkia ylläpidettyjä Linux-käyttöjärjestelmän Debian- ja Red Hat -distribuutioita.

So it should work in supported Debian distributions, yet it doesn't work in Debian 13. The version string in the .deb package has 4.5.0.0-Debian12.

installCA

installCA function:

address            noret size  nbbs edges    cc cost          min bound range max bound          calls locals args xref frame name
================== ===== ===== ===== ===== ===== ==== ================== ===== ================== ===== ====== ==== ==== ===== ====
0x0000000000146500     0 7718   264   428   168 2451 0x0000000000146500  7917 0x00000000001483ed   289   36      1    1   552 fcn.00146500

XOR key:

nth   paddr      vaddr      len  size section type    string
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
498   0x00599400 0x00599400 38   40   .rodata ascii   xYue6hgg5ImeRot68oYdAdding certificate

CA-side deobfuscation helper:

// fcn.00148910
r10 = "xYue6hgg5ImeRot68oYdAdding certificate"     // XOR key
r9  = 0x005993e0                                    // ciphertext
r8  = rsp                                           // 20-byte scratch buffer
for (rdx = 0; rdx != 0x14; rdx += 4) {
    xmm0 = *(uint32_t*)(r10 + rdx);
    xmm1 = *(uint32_t*)(r9  + rdx);
    xmm0 ^= xmm1;
    *(uint32_t*)(r8 + rdx) = xmm0;
}
QString::fromLatin1(rsp, 0x14);

So the 20 ciphertext bytes live at 0x005993e0 and the 20-byte XOR key at 0x00599400 (the leading part of the "xYue…" string).

Deobfuscate with: r2 -n -qc 'e io.cache=true; b 20; s 0x5993e0; wox p8 20 @ 0x599400; ps' /usr/bin/atostekid

installSCSCA

The byte-wise XOR loop pattern (cmp rdx, 0x14 ; jne …) matches at exactly two places in the binary:

0x00148964    (inside fcn.00148910 — the installCA deobfuscator, above)
0x00247cd4    (inside a second function starting at 0x00247c80)

The second one uses byte-wise movzx/xor/mov byte rather than the movd/pxor SSE variant, but it is functionally identical:

0x00247c95   lea r10, [0x005a4260]     ; source #1
0x00247c9c   lea r9,  [0x005a4240]     ; source #2
0x00247cb7   mov r8, rsp               ; 20-byte scratch buffer
loop:
0x00247cc0   movzx ecx, byte [r10 + rdx]
0x00247cc5   movzx esi, byte [r9  + rdx]
0x00247cca   xor   ecx, esi
0x00247ccc   mov   byte [r8 + rdx], cl
0x00247cd0   add   rdx, 1
0x00247cd4   cmp   rdx, 0x14
0x00247cd8   jne   loop

"Ciphertext":

0x005a4240  ea 55 f2 e4 07 76 ec 2e  15 87 6e 0d f1 cb 85 9f    (ciphertext, 20 bytes)
0x005a4250  a9 91 8c f7 00 00 00 00  00 00 00 00 00 00 00 00
0x005a4260  a6 30 c1 97 71 0c a7 79  50 b5 21 49 c5 a8 e2 c8    (XOR key, 20 bytes)
0x005a4270  d3 c9 ed 99 "Atostek ID Local SCS CA\x00Subject name doe…"

So the SCSCA XOR key blob at 0x005a4260 is followed immediately by the printable string Atostek ID Local SCS CA — mirroring the way the installCA XOR key blob at 0x00599400 is immediately followed by Adding certificate. In both cases the 20 "key" bytes and the adjacent human-readable string are stored as a single .rodata literal.

Deobfuscate with: r2 -n -qc 'e io.cache=true; b 20; s 0x5a4260; wox p8 20 @ 0x5a4240; ps' /usr/bin/atostekid

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment