https://bugs.kde.org/show_bug.cgi?id=514194

Marco Martin <[email protected]> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|REPORTED                    |RESOLVED
         Resolution|---                         |FIXED
      Latest Commit|                            |https://invent.kde.org/fram
                   |                            |eworks/kwallet/-/commit/307
                   |                            |db62637ac2ca78ff670d746433b
                   |                            |e9381a923b

--- Comment #4 from Marco Martin <[email protected]> ---
Git commit 307db62637ac2ca78ff670d746433be9381a923b by Marco Martin, on behalf
of Matthias Kurz.
Committed on 20/03/2026 at 09:10.
Pushed by mart into branch 'master'.

ksecretd: fix intermittent Secret Service session key mismatches with libsecret

## Summary

This MR fixes intermittent `libsecret` / Secret Service interoperability
failures in `ksecretd` that are tracked in [BUG
514194](https://bugs.kde.org/show_bug.cgi?id=514194).

The user-visible symptom is that repeated lookups sometimes fail with:

```text
libsecret-INFO: ... received an invalid or unencryptable secret
```

even though the secret was stored correctly and most lookups succeed.

## Reproducer

Store a secret once:

```bash
secret-tool store --label="some random secret" attr1 val1
```

Then repeatedly look it up:

```bash
while true; do G_MESSAGES_DEBUG=libsecret secret-tool lookup attr1 val1; sleep
0.1; done
```

Before this fix, the loop intermittently produced:

```text
libsecret-INFO: ... received an invalid or unencryptable secret
```

## Root cause

There were two separate incompatibilities in `ksecretd`'s DH/AES session
handling.

### 1. The DH shared secret width was not normalized to the 1024-bit group size

`libsecret` derives the AES session key from the Diffie-Hellman shared secret
after normalizing it to the prime width (128 bytes), see
[`egg_dh_gen_secret()` in
`egg/egg-dh-libgcrypt.c`](https://gitlab.gnome.org/GNOME/libsecret/-/blob/0.21.7/egg/egg-dh-libgcrypt.c#L186-190)
and the subsequent HKDF step in
[`response_open_session_aes()` in
`libsecret/secret-session.c`](https://gitlab.gnome.org/GNOME/libsecret/-/blob/0.21.7/libsecret/secret-session.c#L175-182).

`ksecretd` previously passed the raw QCA output directly into HKDF. If the
shared secret had leading zero bytes, QCA returned a shorter value and
ksecretd derived a different AES key than libsecret.

### 2. DH public keys were handled as signed integers instead of unsigned
big-endian values

QCA's `BigInteger` import/export uses sign-extended network byte order.

`libsecret`, on the other hand, treats the exchanged DH public keys as unsigned
values:

- it imports the peer public key with
  [`gcry_mpi_scan(..., GCRYMPI_FMT_USG,
...)`](https://gitlab.gnome.org/GNOME/libsecret/-/blob/0.21.7/egg/egg-dh-libgcrypt.c#L263-266)
- and it exports its own public key with
  [`gcry_mpi_aprint(..., GCRYMPI_FMT_USG,
...)`](https://gitlab.gnome.org/GNOME/libsecret/-/blob/0.21.7/egg/egg-dh-libgcrypt.c#L247-248)

This meant that:

- incoming client public keys could be misinterpreted when the high bit was set
- outgoing server public keys could sometimes be encoded as 129 bytes instead
of the expected unsigned 128-byte form

That again caused both sides to derive different session keys intermittently.

## Fixes in this MR

This MR applies two fixes, and both are needed:

1. Normalize the derived DH shared secret to exactly 128 bytes before HKDF
2. Normalize DH public keys to unsigned 128-byte values on both input and
output

With only one of these fixes applied, the bug could still be reproduced. With
both fixes applied, I was no longer able to reproduce the failure,
including long runs of the loop above.

## Tests

This MR includes autotest coverage for both failure modes:

- a regression test for a short DH shared secret
- a regression test for a client public key with the high bit set

## Bug

Fixes: [BUG 514194](https://bugs.kde.org/show_bug.cgi?id=514194)

M  +141  -20   src/runtime/ksecretd/autotests/fdo_secrets_test.cpp
M  +4    -0    src/runtime/ksecretd/autotests/fdo_secrets_test.h
M  +9    -7    src/runtime/ksecretd/kwalletfreedesktopservice.cpp
M  +23   -1    src/runtime/ksecretd/kwalletfreedesktopsession.cpp
M  +3    -0    src/runtime/ksecretd/kwalletfreedesktopsession.h

https://invent.kde.org/frameworks/kwallet/-/commit/307db62637ac2ca78ff670d746433be9381a923b

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to