agent: Disrepancy of handling MPI for the interpretation of signed and unsigned
Open, WishlistPublic

Description

In gpg-agent, reading and processing MPI assumes unsigned integer using default mode ("+").
But writing uses "%m", which is signed integer.

This works, as long as the MPI value is positive.

But there are two problems:
(1) When the MPI value is negative, it results wrong value, undetected.
(2) Representation may have extra leading zero octet.

This should be fixed like:
(1) When writing, make sure the value is positive and results error when it's not. DETECT INVALID VALUE.
(2) Use %M without leading zero octet.
(3) For backward compatibility (in the existing file), keep the support of allowing extra leading zero octet when reading.

The fix #1 would cause problem for SSH, as "mpint" in the SSH specification assumes signed integer, but I believe negative value is never in use in the implementations.

gniibe created this task.May 27 2020, 3:03 AM
gniibe updated the task description. (Show Details)

Exactly same problem is there in libgcrypt.
In the definitions of curves, it uses negative constant internally in some specific places, but for other parts, we have same problems.

gniibe edited projects, added gpgagent, libgcrypt; removed OpenPGP.May 27 2020, 3:08 AM
gniibe updated the task description. (Show Details)
gniibe added a comment.EditedJun 2 2020, 8:05 AM

Change of gpg-agent for ECC-SOS

Change: when parsing private key data, use /d (interpret as an opaque
octed sequence), so that no removal of leading zero bytes occurs.

But this change will expose hidden issue(s) of the inconsistency of
signed/unsigned MPI representation handling in GnuPG and libgcrypt,
which currently does: adding a leading zero byte at write as signed
data and ignoring a leading zero byte at read (with no check of this
additional zero-byte or not).

So, another change of fixup when reading keys:

Existing cleartext keys may have 'd' with leading zero byte (a single
leading zero byte, because of the lax signedness problem). This
leading zero byte should be removed before the parsing private key
data.

It would be also good to fixup removed zeros for 'd' of Ed25519/EdDSA.

(Existing keys with encrypted 'd' never has 'd' with leading zero
bytes when decrypted, because the leading zero bytes were already
ignored when encrypted.)

a test case:

Prepare cleartext private keys with MSB=1, export them into OpenPGP
format (by gpg --export-secret-key). Make sure no leading zero-byte
in the result.