keys added via gpg-agent's ssh-agent interface are stored in private-keys-v1.d/ with a trailing null byte
Closed, ResolvedPublic

Description

On an amd64 system, running gpg-agent 2.2.15, i noticed that the files stored in private-keys-v1.d/ have a trailing NUL byte after their S-expression if they were created by import via ssh-add . Keys generated by GnuPG itself do not have the trailing NUL byte. nettle's sexp-conv treats the files with the trailing NUL byte as broken, with an error message "Invalid token". Stripping the trailing NUL byte seems to have no adverse effects.

I assume this is a bug in the agent's ssh import code, but i haven't tracked it down.

0 dkg@alice:/tmp/cdtemp.IlxrE0$ export GNUPGHOME=$(pwd)
0 dkg@alice:/tmp/cdtemp.IlxrE0$ gpg --pinentry-mode=loopback --passphrase '' --quick-gen-key 'test key from gpg' ed25519 auth
gpg: keybox '/tmp/cdtemp.IlxrE0/pubring.kbx' created
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: /tmp/cdtemp.IlxrE0/trustdb.gpg: trustdb created
gpg: key 30295D1AAE529868 marked as ultimately trusted
gpg: directory '/tmp/cdtemp.IlxrE0/openpgp-revocs.d' created
gpg: revocation certificate stored as '/tmp/cdtemp.IlxrE0/openpgp-revocs.d/8918715EF536CF29472A3D7030295D1AAE529868.rev'
public and secret key created and signed.

pub   ed25519 2019-05-11 [CA] [expires: 2021-05-10]
      8918715EF536CF29472A3D7030295D1AAE529868
uid                      test key from gpg

0 dkg@alice:/tmp/cdtemp.IlxrE0$ ssh-keygen -t ed25519 -N '' -f ssh_key -C 'test key from ssh'
Generating public/private ed25519 key pair.
Your identification has been saved in ssh_key.
Your public key has been saved in ssh_key.pub.
The key fingerprint is:
SHA256:hsMJQ2x+DCMWnKEYaVwZeI6BKM+U8sVJ1x6NXZxMXio test key from ssh
The key's randomart image is:
+--[ED25519 256]--+
|=o=@=... + =o..  |
|BBB+O.  + o.+o   |
|=B==o+ . .E o    |
| .+..+oo.  .     |
|     .= S        |
|       o         |
|                 |
|                 |
|                 |
+----[SHA256]-----+
0 dkg@alice:/tmp/cdtemp.IlxrE0$ export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
0 dkg@alice:/tmp/cdtemp.IlxrE0$ ssh-add ssh_key
Identity added: ssh_key (test key from ssh)
0 dkg@alice:/tmp/cdtemp.IlxrE0$ for x in private-keys-v1.d/*.key; do echo $x; hd < $x; sexp-conv < $x; done
private-keys-v1.d/26749A62CC50C71F09533483A71497C49D881EDE.key
00000000  28 31 31 3a 70 72 69 76  61 74 65 2d 6b 65 79 28  |(11:private-key(|
00000010  33 3a 65 63 63 28 35 3a  63 75 72 76 65 37 3a 45  |3:ecc(5:curve7:E|
00000020  64 32 35 35 31 39 29 28  35 3a 66 6c 61 67 73 35  |d25519)(5:flags5|
00000030  3a 65 64 64 73 61 29 28  31 3a 71 33 33 3a 40 d7  |:eddsa)(1:q33:@.|
00000040  38 2a bb fd d5 a3 e1 4a  9d 9d d4 2f 78 33 7c 0c  |8*.....J.../x3|.|
00000050  8f 5f 02 8b a1 c3 f8 ed  d1 ca 42 10 2c a8 a8 29  |._........B.,..)|
00000060  28 31 3a 64 33 32 3a 17  67 21 6f 40 19 c4 12 61  |(1:d32:.g!o@...a|
00000070  cd 0b e9 9f e7 e1 ff c4  7a d1 82 20 89 be 91 18  |........z.. ....|
00000080  e1 8f 4e b6 b3 38 0f 29  29 28 37 3a 63 6f 6d 6d  |..N..8.))(7:comm|
00000090  65 6e 74 31 37 3a 74 65  73 74 20 6b 65 79 20 66  |ent17:test key f|
000000a0  72 6f 6d 20 73 73 68 29  29 00                    |rom ssh)).|
000000aa
(private-key (ecc (curve Ed25519)
                  (flags eddsa)
                  (q |QNc4Krv91aPhSp2d1C94M3wMj18Ci6HD+O3RykIQLKio|)
                  (d |F2chb0AZxBJhzQvpn+fh/8R60YIgib6RGOGPTrazOA8=|))
             (comment "test key from ssh"))
Invalid token.
private-keys-v1.d/6791E0D4EC233F51D3CF548070524F915E98E511.key
00000000  28 31 31 3a 70 72 69 76  61 74 65 2d 6b 65 79 28  |(11:private-key(|
00000010  33 3a 65 63 63 28 35 3a  63 75 72 76 65 37 3a 45  |3:ecc(5:curve7:E|
00000020  64 32 35 35 31 39 29 28  35 3a 66 6c 61 67 73 35  |d25519)(5:flags5|
00000030  3a 65 64 64 73 61 29 28  31 3a 71 33 33 3a 40 5b  |:eddsa)(1:q33:@[|
00000040  3e 87 61 6f 70 44 c9 4f  cd 60 b0 6f 2e c8 cc 7f  |>.aopD.O.`.o....|
00000050  2f cd 7d 90 48 ad fb f2  2f 89 e9 26 fc cb 7d 29  |/.}.H.../..&..})|
00000060  28 31 3a 64 33 32 3a 35  40 8e e0 e1 ed 24 d1 dc  |(1:d32:5@....$..|
00000070  f6 fd ef 96 7f bd 2e 53  82 77 e8 8b 9f a7 4e 05  |.......S.w....N.|
00000080  0b ae 25 5f 63 d0 82 29  29 29                    |..%_c..)))|
0000008a
(private-key (ecc (curve Ed25519)
                  (flags eddsa)
                  (q |QFs+h2FvcETJT81gsG8uyMx/L819kEit+/Iviekm/Mt9|)
                  (d |NUCO4OHtJNHc9v3vln+9LlOCd+iLn6dOBQuuJV9j0II=|)))
0 dkg@alice:/tmp/cdtemp.IlxrE0$

Related Objects

dkg created this task.May 12 2019, 12:37 AM
werner triaged this task as Normal priority.May 12 2019, 8:16 PM
werner added a subscriber: werner.

I often put an extra nul byte at the end of binary data so that accidental printing the data (e.g. in gdb) assures that there is a string terminator. But right, it should not go out to a file.

gniibe claimed this task.May 21 2019, 8:48 AM
gniibe added a subscriber: gniibe.

I located the bug in agent/command-ssh.c.
Our practice is two calls of gcry_sexp_sprint; One to determine the length including last NUL byte, and another to actually fills the buffer.
The first call return +1 for NUL byte.
The second call fills NUL at the end, but returns +0 length (length sans last NUL).

I'm going to fix this.

werner closed this task as Resolved.May 21 2019, 9:16 AM

Also fixed for 2.2