GnuPG gpg-agent KEYTOCARD Invalid time (memory overwritten)

Bug #2067089 reported by brightearthy
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
gnupg2 (Ubuntu)
Confirmed
Undecided
Unassigned

Bug Description

OS: Ubuntu 24.04 LTS
HW: Raspberry Pi Arm64
Related packages:
  - gnupg2 2.4.4-2ubuntu17
  - libassuan0:arm64 2.5.6-1build1

When I am trying to fully generate and transfer a new set of GPG private keys to my new YubiKey 5 security key, following this guide: https://github.com/drduh/YubiKey-Guide. I encountered bellow error when running `gpg --pinentry-mode=loopback --edit-key ${KEYID}` with the `keytocard`command:

```
gpg: KEYTOCARD failed: Invalid time
```

After some digging around, attaching gdb to the running `gpg-agent` process. I found that after the function call to `agent_key_from_file` from `gnupg/agent/command.c:3278`, which communicated the client and acquired master certify key passphrase, the memory used by `argv` variable in `cmd_keytocard` function has been wiped to zeros. This caused later usage of the variable to fail, resulted in a timestamp conversion error with code `GPG_ERR_INV_TIME`.

```
(gdb) bt
#0 agent_key_from_file (ctrl=0xaaab192410e0, cache_nonce=0x0, desc_text=0x0,
    grip=0xffff8440e740 "__________________________________________________________________",
    shadow_info=0xffff8440e6d0, cache_mode=CACHE_MODE_IGNORE, lookup_ttl=0x0, result=0xffff8440e6d8, r_passphrase=0x0,
    r_timestamp=0xffff8440e6c8) at ../../agent/findkey.c:1368
#1 0x0000aaaae369a538 in cmd_keytocard (ctx=0xffff7c027b40, line=<optimized out>) at ../../agent/command.c:3278
#2 0x0000ffff8471a288 in dispatch_command (ctx=ctx@entry=0xffff7c027b40,
    line=0xffff7c027c9a "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", line@entry=0xffff7c027c90 "KEYTOCARD",
    linelen=<optimized out>) at ../../src/assuan-handler.c:676
#3 0x0000ffff8471a8e0 in process_request (ctx=0xffff7c027b40) at ../../src/assuan-handler.c:872
#4 assuan_process (ctx=0xffff7c027b40) at ../../src/assuan-handler.c:895
#5 0x0000aaaae36bcfb8 in start_command_handler.constprop.0 (ctrl=ctrl@entry=0xaaab192410e0, fd=11, listen_fd=-1)
    at ../../agent/command.c:4460
#6 0x0000aaaae368da70 in do_start_connection_thread (ctrl=0xaaab192410e0) at ../../agent/gpg-agent.c:2860
#7 0x0000ffff846e1bf4 in thread_start (startup_arg=<optimized out>) at ../../src/npth.c:306
#8 0x0000ffff8455597c in start_thread (arg=0xffff84893080) at ./nptl/pthread_create.c:447
#9 0x0000ffff845bba4c in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone3.S:76
(gdb) frame 1
#1 0x0000aaaae369a538 in cmd_keytocard (ctx=0xffff7c027b40, line=<optimized out>) at ../../agent/command.c:3278
3278 err = agent_key_from_file (ctrl, NULL, ctrl->server_local->keydesc, grip,
(gdb) p argv
$16 = {0xffff7c027c9a "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 0xffff7c027cc3 "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
  0xffff7c027ce4 "OPENPGP.1", 0xffff7c027cee "20240524T123456", 0xaaaae36c6a80 "Assuan processing failed: %s\n"}
(gdb) watch *0xffff7c027c9a
Hardware watchpoint 9: *0xffff7c027c9a
(gdb) c
Continuing.
Downloading source file /build/libassuan-Uieq6Z/libassuan-2.5.6/build/src/../../src/assuan-inquire.c

Thread 2 "gpg-agent" hit Hardware watchpoint 9: *0xffff7c027c9a

Old value = 111111111
New value = 222222222
0x0000ffff8471afd4 in assuan_inquire (ctx=ctx@entry=0xffff7c027b40, keyword=keyword@entry=0xaaaae36c2820 "PASSPHRASE",
    r_buffer=r_buffer@entry=0xffff8440dff8, r_length=r_length@entry=0xffff8440dff0, maxlen=maxlen@entry=255)
    at ../../src/assuan-inquire.c:263
263 wipememory (ctx->inbound.line, LINELENGTH);
(gdb) bt
#0 0x0000ffff8471afd4 in assuan_inquire (ctx=ctx@entry=0xffff7c027b40,
    keyword=keyword@entry=0xaaaae36c2820 "PASSPHRASE", r_buffer=r_buffer@entry=0xffff8440dff8,
    r_length=r_length@entry=0xffff8440dff0, maxlen=maxlen@entry=255) at ../../src/assuan-inquire.c:263
#1 0x0000aaaae36a1e2c in pinentry_loopback (ctrl=0xff, max_length=255, size=0xffff8440dff0, buffer=0xffff8440dff8,
    keyword=0xaaaae36c2820 "PASSPHRASE") at ../../agent/command.c:4507
#2 agent_askpin (ctrl=ctrl@entry=0xaaab192410e0, desc_text=desc_text@entry=0x0, prompt_text=prompt_text@entry=0x0,
    initial_errtext=initial_errtext@entry=0x0, pininfo=pininfo@entry=0xffff844677d0,
    keyinfo=keyinfo@entry=0xffff8440e538 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    cache_mode=cache_mode@entry=CACHE_MODE_IGNORE) at ../../agent/call-pinentry.c:1453
#3 0x0000aaaae36aa2f0 in agent_askpin (cache_mode=CACHE_MODE_IGNORE,
    keyinfo=0xffff8440e538 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", pininfo=0xffff844677d0, initial_errtext=0x0,
    prompt_text=0x0, desc_text=0x0, ctrl=0xaaab192410e0) at ../../agent/call-pinentry.c:1440
#4 unprotect (r_passphrase=0x0, lookup_ttl=0x0, cache_mode=CACHE_MODE_IGNORE, grip=<optimized out>,
    keybuf=0xffff8440e4d0, desc_text=0x0, cache_nonce=0x0, ctrl=0xaaab192410e0) at ../../agent/findkey.c:959
#5 agent_key_from_file (ctrl=0xaaab192410e0, cache_nonce=0x0, desc_text=<optimized out>, grip=<optimized out>,
    shadow_info=<optimized out>, cache_mode=CACHE_MODE_IGNORE, lookup_ttl=0x0, result=0xffff8440e6d8,
    r_passphrase=0x0, r_timestamp=0xffff8440e6c8) at ../../agent/findkey.c:1520
#6 0x0000aaaae369a538 in cmd_keytocard (ctx=0xffff7c027b40, line=<optimized out>) at ../../agent/command.c:3278
#7 0x0000ffff8471a288 in dispatch_command (ctx=ctx@entry=0xffff7c027b40, line=0xffff7c027c9a "",
    line@entry=0xffff7c027c90 "", linelen=<optimized out>) at ../../src/assuan-handler.c:676
#8 0x0000ffff8471a8e0 in process_request (ctx=0xffff7c027b40) at ../../src/assuan-handler.c:872
#9 assuan_process (ctx=0xffff7c027b40) at ../../src/assuan-handler.c:895
#10 0x0000aaaae36bcfb8 in start_command_handler.constprop.0 (ctrl=ctrl@entry=0xaaab192410e0, fd=11, listen_fd=-1)
    at ../../agent/command.c:4460
#11 0x0000aaaae368da70 in do_start_connection_thread (ctrl=0xaaab192410e0) at ../../agent/gpg-agent.c:2860
#12 0x0000ffff846e1bf4 in thread_start (startup_arg=<optimized out>) at ../../src/npth.c:306
#13 0x0000ffff8455597c in start_thread (arg=0xffff84893080) at ./nptl/pthread_create.c:447
#14 0x0000ffff845bba4c in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone3.S:76
(gdb) frame 6
#6 0x0000aaaae369a538 in cmd_keytocard (ctx=0xffff7c027b40, line=<optimized out>) at ../../agent/command.c:3278
3278 err = agent_key_from_file (ctrl, NULL, ctrl->server_local->keydesc, grip,
(gdb) p argv
$17 = {0xffff7c027c9a "", 0xffff7c027cc3 "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY", 0xffff7c027ce4 "OPENPGP.1",
  0xffff7c027cee "20240524T123456", 0xaaaae36c6a80 "Assuan processing failed: %s\n"}
(gdb) frame 0
#0 0x0000ffff8471afd4 in assuan_inquire (ctx=ctx@entry=0xffff7c027b40,
    keyword=keyword@entry=0xaaaae36c2820 "PASSPHRASE", r_buffer=r_buffer@entry=0xffff8440dff8,
    r_length=r_length@entry=0xffff8440dff0, maxlen=maxlen@entry=255) at ../../src/assuan-inquire.c:263
263 wipememory (ctx->inbound.line, LINELENGTH);
(gdb) p ctx->inbound.line
$18 = '\000' <repeats 11 times>, "AAAAAAAAAAAAAAAAAAAA\000END\nXXXXXXXXXXXXXX\000YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\000OPENPGP.1\00020240524T123456", '\000' <repeats 892 times>
```

I can see from the last print result, the passphrase (AAA...) from the client is already overwritten part of the Key ID (XXX...) in the same line buffer. The `argv` variable in the context of the `cmd_keytocard` function is also using the same underlying buffer. I have no in-depth knowledge of how GnuPG is implemented. It seems to be either the gnupg2 or libassuan0 issue, possibly also related to `--pinentry-mode=loopback`. Hope someone can classify this bug properly and help fix it for good. Thanks.

Tags: arm64 gnupg2
information type: Private Security → Public
Changed in gnupg2 (Ubuntu):
status: New → Confirmed
Revision history for this message
Sebastien Bacher (seb128) wrote :

Thank you for your bug report. Seems you are not the only one, it's discussed also on https://www.reddit.com/r/yubikey/comments/1b5pjzq/strange_gpg_error_when_using_keytocard/ and might be worth reporting upstream on https://dev.gnupg.org/maniphest/task/edit/form/3/

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.