Source: rust-sequoia-gpg-agent
Version: 0.6.0-1
Severity: important

Dear Maintainer,

importing ecc secret keys into gpg-agent 2.4.x is broken.

When importing keys, a checksum is computed over the key material.
This checksum computation (inadvertently) changed during development
shortly before gpg-agent 2.4.0 was released.  sequoia-gpg-agent
contains a heuristic to deal with gpg-agent 2.4.x's new behavior, but
that heuristic is ineffective when doing a non-interactive import.

When doing a non-interactive import, the checksum is not checked at
import time, but only later when the key is used.  In the following, a
patched gpg-agent is used to highlight the different behavior.

First, we do an interactive import.  Observe how each (sub)key is
imported twice, with the first import failing due to a checksum
mismatch (note how the actual_csum and desired_csum differ by 8):

teythoon@europ ~ % gpg-sq --import /tmp/key.pgp
gpg: key D4BD12F1284374E0: "some...@example.org" not changed
DUMPING!!!!gpg-agent[3128335]: DBG: XXX is v4_or_later=1
gpg-agent[3128335]: DBG: XXX pubkey_algo=18
gpg-agent[3128335]: DBG: XXX is_protected=0
gpg-agent[3128335]: DBG: XXX protect_algo=0
gpg-agent[3128335]: DBG: XXX iv
gpg-agent[3128335]: DBG: XXX ivlen=0
gpg-agent[3128335]: DBG: XXX s2k_mode=0
gpg-agent[3128335]: DBG: XXX s2k_algo=0
gpg-agent[3128335]: DBG: XXX s2k_salt 70ed1f25cd7f0000
gpg-agent[3128335]: DBG: XXX s2k_count=0
gpg-agent[3128335]: DBG: XXX curve='NIST P-256'
gpg-agent[3128335]: DBG: skey(_): [520 bit]
gpg-agent[3128335]: DBG:          
041d50fc8e4e2cf05cd93269317e0b799b8deb50a56e2c8f3ec599aee990db31 \
gpg-agent[3128335]: DBG:          
e45b4a84a2eacb4883f3a1f01e2df3947d1f16a249563980567163f403eaed87 \
gpg-agent[3128335]: DBG:          bc
gpg-agent[3128335]: DBG: skey(_): [264 bit]
gpg-agent[3128335]: DBG:          
00a552dba7653e8c63ff5685ae130b9c17627874ac6bb6d2bb6904c01e780bd2 \
gpg-agent[3128335]: DBG:          97
gpg-agent[3128335]: nbits original: 264
gpg-agent[3128335]: nbytes: 33
gpg-agent[3128335]: nbits rounded up: 264
gpg-agent[3128335]: *buffer: 00
gpg-agent[3128335]: nbits corrected: 264
gpg-agent[3128335]: actual_csum: 3916
gpg-agent[3128335]: desired_csum: 3908
gpg-agent[3128335]: command 'IMPORT_KEY' failed: Checksum error
DUMPING!!!!gpg-agent[3128335]: DBG: XXX is v4_or_later=1
gpg-agent[3128335]: DBG: XXX pubkey_algo=18
gpg-agent[3128335]: DBG: XXX is_protected=0
gpg-agent[3128335]: DBG: XXX protect_algo=0
gpg-agent[3128335]: DBG: XXX iv
gpg-agent[3128335]: DBG: XXX ivlen=0
gpg-agent[3128335]: DBG: XXX s2k_mode=0
gpg-agent[3128335]: DBG: XXX s2k_algo=0
gpg-agent[3128335]: DBG: XXX s2k_salt 70ed1f25cd7f0000
gpg-agent[3128335]: DBG: XXX s2k_count=0
gpg-agent[3128335]: DBG: XXX curve='NIST P-256'
gpg-agent[3128335]: DBG: skey(_): [520 bit]
gpg-agent[3128335]: DBG:          
041d50fc8e4e2cf05cd93269317e0b799b8deb50a56e2c8f3ec599aee990db31 \
gpg-agent[3128335]: DBG:          
e45b4a84a2eacb4883f3a1f01e2df3947d1f16a249563980567163f403eaed87 \
gpg-agent[3128335]: DBG:          bc
gpg-agent[3128335]: DBG: skey(_): [264 bit]
gpg-agent[3128335]: DBG:          
00a552dba7653e8c63ff5685ae130b9c17627874ac6bb6d2bb6904c01e780bd2 \
gpg-agent[3128335]: DBG:          97
gpg-agent[3128335]: nbits original: 264
gpg-agent[3128335]: nbytes: 33
gpg-agent[3128335]: nbits rounded up: 264
gpg-agent[3128335]: *buffer: 00
gpg-agent[3128335]: nbits corrected: 264
gpg-agent[3128335]: actual_csum: 3916
gpg-agent[3128335]: desired_csum: 3916
DUMPING!!!!gpg-agent[3128335]: DBG: XXX is v4_or_later=1
gpg-agent[3128335]: DBG: XXX pubkey_algo=18
gpg-agent[3128335]: DBG: XXX is_protected=0
gpg-agent[3128335]: DBG: XXX protect_algo=0
gpg-agent[3128335]: DBG: XXX iv
gpg-agent[3128335]: DBG: XXX ivlen=0
gpg-agent[3128335]: DBG: XXX s2k_mode=0
gpg-agent[3128335]: DBG: XXX s2k_algo=0
gpg-agent[3128335]: DBG: XXX s2k_salt 70ed1f25cd7f0000
gpg-agent[3128335]: DBG: XXX s2k_count=0
gpg-agent[3128335]: DBG: XXX curve='NIST P-256'
gpg-agent[3128335]: DBG: skey(_): [520 bit]
gpg-agent[3128335]: DBG:          
041bce6ab3fcd178b64be460682d33e0bc11cf9723e82ee8aa7efe205264288d \
gpg-agent[3128335]: DBG:          
d4ac69c8f1fec07e8193fcdb6685ee6e74c17b1e997b39ce272940a6e87474ff \
gpg-agent[3128335]: DBG:          8e
gpg-agent[3128335]: DBG: skey(_): [264 bit]
gpg-agent[3128335]: DBG:          
00f6fdb74b4c0bff40a38af95e1e562910efd669eed74e62967718f9cd150ea4 \
gpg-agent[3128335]: DBG:          10
gpg-agent[3128335]: nbits original: 264
gpg-agent[3128335]: nbytes: 33
gpg-agent[3128335]: nbits rounded up: 264
gpg-agent[3128335]: *buffer: 00
gpg-agent[3128335]: nbits corrected: 264
gpg-agent[3128335]: actual_csum: 4138
gpg-agent[3128335]: desired_csum: 4130
gpg-agent[3128335]: command 'IMPORT_KEY' failed: Checksum error
DUMPING!!!!gpg-agent[3128335]: DBG: XXX is v4_or_later=1
gpg-agent[3128335]: DBG: XXX pubkey_algo=18
gpg-agent[3128335]: DBG: XXX is_protected=0
gpg-agent[3128335]: DBG: XXX protect_algo=0
gpg-agent[3128335]: DBG: XXX iv
gpg-agent[3128335]: DBG: XXX ivlen=0
gpg-agent[3128335]: DBG: XXX s2k_mode=0
gpg-agent[3128335]: DBG: XXX s2k_algo=0
gpg-agent[3128335]: DBG: XXX s2k_salt 70ed1f25cd7f0000
gpg-agent[3128335]: DBG: XXX s2k_count=0
gpg-agent[3128335]: DBG: XXX curve='NIST P-256'
gpg-agent[3128335]: DBG: skey(_): [520 bit]
gpg-agent[3128335]: DBG:          
041bce6ab3fcd178b64be460682d33e0bc11cf9723e82ee8aa7efe205264288d \
gpg-agent[3128335]: DBG:          
d4ac69c8f1fec07e8193fcdb6685ee6e74c17b1e997b39ce272940a6e87474ff \
gpg-agent[3128335]: DBG:          8e
gpg-agent[3128335]: DBG: skey(_): [264 bit]
gpg-agent[3128335]: DBG:          
00f6fdb74b4c0bff40a38af95e1e562910efd669eed74e62967718f9cd150ea4 \
gpg-agent[3128335]: DBG:          10
gpg-agent[3128335]: nbits original: 264
gpg-agent[3128335]: nbytes: 33
gpg-agent[3128335]: nbits rounded up: 264
gpg-agent[3128335]: *buffer: 00
gpg-agent[3128335]: nbits corrected: 264
gpg-agent[3128335]: actual_csum: 4138
gpg-agent[3128335]: desired_csum: 4138
gpg: key D4BD12F1284374E0: secret key imported
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1
teythoon@europ ~ % gpg-sq --armor --sign --local-user 
F5A31D60D474FC443F82B268B0F4EC4354E6D4D6 <<< hi
-----BEGIN PGP MESSAGE-----

xA0DAAoTsPTsQ1Tm1NYBywliAAAAAABoaQrCvQQAEwoAbwWCaA9SkwkQsPTsQ1Tm
1NZHFAAAAAAAHgAgc2FsdEBub3RhdGlvbnMuc2VxdW9pYS1wZ3Aub3JnYlv/Jy1T
XqfUEjs/77Vhmac4/lgFwt/ARNQCtOybP60WIQT1ox1g1HT8RD+Csmiw9OxDVObU
1gAAcqoBAJsL9U768p4vNGaSsYlZkErcoIU/c2xbhlbI9ShM0Cf6AQCC626Kl4ez
c17yzTSlPlNLuB5r56YyZyHsbpTJuNlnwQ==
=nw7v
-----END PGP MESSAGE-----

Now, we do a non-interactive import:

teythoon@europ ~ % rm $GNUPGHOME/private-keys-v1.d/*
zsh: sure you want to delete all the files in 
/tmp/tmp.aUYEK4L0US/private-keys-v1.d [yn]? y
teythoon@europ ~ % gpg-sq --import --batch /tmp/key.pgp
gpg: key D4BD12F1284374E0: "some...@example.org" not changed
DUMPING!!!!gpg-agent[3128335]: DBG: XXX is v4_or_later=1
gpg-agent[3128335]: DBG: XXX pubkey_algo=18
gpg-agent[3128335]: DBG: XXX is_protected=0
gpg-agent[3128335]: DBG: XXX protect_algo=0
gpg-agent[3128335]: DBG: XXX iv
gpg-agent[3128335]: DBG: XXX ivlen=0
gpg-agent[3128335]: DBG: XXX s2k_mode=0
gpg-agent[3128335]: DBG: XXX s2k_algo=0
gpg-agent[3128335]: DBG: XXX s2k_salt 70dd9f24cd7f0000
gpg-agent[3128335]: DBG: XXX s2k_count=0
gpg-agent[3128335]: DBG: XXX curve='NIST P-256'
gpg-agent[3128335]: DBG: skey(_): [520 bit]
gpg-agent[3128335]: DBG:          
041d50fc8e4e2cf05cd93269317e0b799b8deb50a56e2c8f3ec599aee990db31 \
gpg-agent[3128335]: DBG:          
e45b4a84a2eacb4883f3a1f01e2df3947d1f16a249563980567163f403eaed87 \
gpg-agent[3128335]: DBG:          bc
gpg-agent[3128335]: DBG: skey(_): [264 bit]
gpg-agent[3128335]: DBG:          
00a552dba7653e8c63ff5685ae130b9c17627874ac6bb6d2bb6904c01e780bd2 \
gpg-agent[3128335]: DBG:          97
DUMPING!!!!gpg-agent[3128335]: DBG: XXX is v4_or_later=1
gpg-agent[3128335]: DBG: XXX pubkey_algo=18
gpg-agent[3128335]: DBG: XXX is_protected=0
gpg-agent[3128335]: DBG: XXX protect_algo=0
gpg-agent[3128335]: DBG: XXX iv
gpg-agent[3128335]: DBG: XXX ivlen=0
gpg-agent[3128335]: DBG: XXX s2k_mode=0
gpg-agent[3128335]: DBG: XXX s2k_algo=0
gpg-agent[3128335]: DBG: XXX s2k_salt 70dd9f24cd7f0000
gpg-agent[3128335]: DBG: XXX s2k_count=0
gpg-agent[3128335]: DBG: XXX curve='NIST P-256'
gpg-agent[3128335]: DBG: skey(_): [520 bit]
gpg-agent[3128335]: DBG:          
041bce6ab3fcd178b64be460682d33e0bc11cf9723e82ee8aa7efe205264288d \
gpg-agent[3128335]: DBG:          
d4ac69c8f1fec07e8193fcdb6685ee6e74c17b1e997b39ce272940a6e87474ff \
gpg-agent[3128335]: DBG:          8e
gpg-agent[3128335]: DBG: skey(_): [264 bit]
gpg-agent[3128335]: DBG:          
00f6fdb74b4c0bff40a38af95e1e562910efd669eed74e62967718f9cd150ea4 \
gpg-agent[3128335]: DBG:          10
gpg: key D4BD12F1284374E0: secret key imported
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1
teythoon@europ ~ % gpg-sq --armor --sign --local-user 
F5A31D60D474FC443F82B268B0F4EC4354E6D4D6 <<< hi
-----BEGIN PGP MESSAGE-----

gpg-agent[3128335]: DBG: XXX is v4_or_later=1
gpg-agent[3128335]: DBG: XXX pubkey_algo=18
gpg-agent[3128335]: DBG: XXX is_protected=0
gpg-agent[3128335]: DBG: XXX protect_algo=0
gpg-agent[3128335]: DBG: XXX iv
gpg-agent[3128335]: DBG: XXX ivlen=0
gpg-agent[3128335]: DBG: XXX s2k_mode=0
gpg-agent[3128335]: DBG: XXX s2k_algo=0
gpg-agent[3128335]: DBG: XXX s2k_salt a0d89f24cd7f0000
gpg-agent[3128335]: DBG: XXX s2k_count=0
gpg-agent[3128335]: DBG: XXX curve='NIST P-256'
gpg-agent[3128335]: DBG: skey(_): [520 bit]
gpg-agent[3128335]: DBG:          
041bce6ab3fcd178b64be460682d33e0bc11cf9723e82ee8aa7efe205264288d \
gpg-agent[3128335]: DBG:          
d4ac69c8f1fec07e8193fcdb6685ee6e74c17b1e997b39ce272940a6e87474ff \
gpg-agent[3128335]: DBG:          8e
gpg-agent[3128335]: DBG: skey(_): [264 bit]
gpg-agent[3128335]: DBG:          
00f6fdb74b4c0bff40a38af95e1e562910efd669eed74e62967718f9cd150ea4 \
gpg-agent[3128335]: DBG:          10
gpg-agent[3128335]: nbits original: 264
gpg-agent[3128335]: nbytes: 33
gpg-agent[3128335]: nbits rounded up: 264
gpg-agent[3128335]: *buffer: 00
gpg-agent[3128335]: nbits corrected: 264
gpg-agent[3128335]: actual_csum: 4138
gpg-agent[3128335]: desired_csum: 4130
gpg-agent[3128335]: failed to convert unprotected openpgp key: Checksum error
gpg-agent[3128335]: failed to read the secret key
gpg-agent[3128335]: command 'PKSIGN' failed: Checksum error
xA0DAAoTsPTsQ1Tm1NYBywliAAAAAABogpg: Operation failed: Checksum error <GPG 
Agent>

Note how the import succeeds, but the checksum mismatch is detected
when the key is used.

-- System Information:
Debian Release: trixie/sid
  APT prefers testing
  APT policy: (900, 'testing'), (700, 'unstable'), (500, 'testing-debug'), 
(500, 'stable-debug'), (500, 'proposed-updates-debug'), (400, 'stable'), (1, 
'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 6.12.19-amd64 (SMP w/20 CPU threads; PREEMPT)
Kernel taint flags: TAINT_WARN
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), 
LANGUAGE=en_US:en
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Reply via email to