Title: How to check if your smartcard's GPG key is in cache PART 3
Date: 2017-03-13 17:05
Category: gpg
Tags: gpg, unix, CLI, gpg-agent, awk, regex, smartcard
###GPG SmartCard Cache Checking
By 'broad', I just wish to point out that you *could* build the check around a specific key-grip if you cared to.
And recently I got around to ordering a 'traditional' smartcard from [kernel concepts].
While I've had and used a [yubikey neo] for a while with my laptop/phone, I have been utilizing an on laptop subkey for 'convenience'.
The local subkey was handling my `pass` ([password store]) datebase, and in the past my `cryptshotr` keyfile.
####Personal Desires
My reason for getting a classic style smartcard are as follows:
###Hands on
After getting the card I trimmed the edge down so that it barely sticks out from the laptop.
####Multiple SmartCard Woes
To set up my new card, I pulled a copy of my non-stub laptop keys (encryption, signature, and authentication) out of secure storage, and ran a `export GNUPGHOME=...` to point at the copy.
Once my keys and configurations are finished on the new card and I was back to my normal keyring (temp dir having been shreaded), I ran into an issue where it kept asking for the yubikey by serial...
Unfortunately running `gpg --card-edit` and `fetch` did not help.
To fix this I ran good old `gpg-connect-agent 'keyinfo --list' /bye 2>/dev/null` (from the previous posts: [Part1], [Part2]) to identify the key-grips, and deleted the three offending `/.gnupg/private-keys-v1.d/KEY_GRIP_HERE.key` files.
After they were cleared out, I was successfully about to `gpg --card-edit` and `fetch` from the new key.
####Verifying Functionality
While testing that the keys on the smartcard worked, I also checked on my previous cache check solution.
Sadly I found that `gpg-connect-agent 'keyinfo --list' /bye 2>/dev/null` doesn't show the smartcard status.
While reading thought the output of `gpg-connect-agent 'help' /bye`, and each individual help page, I see `scd`.
:::bash
~ -> gpg-connect-agent 'help scd' /bye
# SCD
#
# This is a general quote command to redirect everything to the
# SCdaemon.
OK
####Alice Falling Down the Rabbit Hole
So now, here I am in my `bash` shell, sending commands to the `gpg-agent` shell, sending commands to the `scdaemon` shell.
:::bash
~ -> gpg-connect-agent 'scd help' /bye
# NOP
# CANCEL
# OPTION
# BYE
# AUTH
# RESET
# END
# HELP
# SERIALNO [--demand=] []
# LEARN [--force] [--keypairinfo]
# READCERT |
# READKEY [--advanced]
# SETDATA [--append]
# PKSIGN [--hash=[rmd160|sha{1,224,256,384,512}|md5]]
# PKAUTH
# PKDECRYPT
# INPUT
# OUTPUT
# GETATTR
# SETATTR
# WRITECERT
# WRITEKEY [--force]
# GENKEY [--force] [--timestamp=]
# RANDOM
# PASSWD [--reset] [--nullpin]
# CHECKPIN
# LOCK [--wait]
# UNLOCK
# GETINFO
# RESTART
# DISCONNECT
# APDU [--[dump-]atr] [--more] [--exlen[=N]] [hexstring]
# KILLSCD
OK
While reading through the help pages on each of these, `GETINFO` looks promising.
:::bash
~ -> gpg-connect-agent 'scd help getinfo' /bye
# GETINFO
#
# Multi purpose command to return certain information.
# Supported values of WHAT are:
#
# version - Return the version of the program.
# pid - Return the process id of the server.
#
# socket_name - Return the name of the socket.
#
# status - Return the status of the current reader (in the future, may
# also return the status of all readers). The status is a list of
# one-character flags. The following flags are currently defined:
# 'u' Usable card present. This is the normal state during operation.
# 'r' Card removed. A reset is necessary.
# These flags are exclusive.
#
# reader_list - Return a list of detected card readers. Does
# currently only work with the internal CCID driver.
#
# deny_admin - Returns OK if admin commands are not allowed or
# GPG_ERR_GENERAL if admin commands are allowed.
#
# app_list - Return a list of supported applications. One
# application per line, fields delimited by colons,
# first field is the name.
#
# card_list - Return a list of serial numbers of active cards,
# using a status response.
OK
Upon testing, I find that `gpg-connect-agent 'scd getinfo card_list' /bye` is a seemingly reliable way of seeing if a smartcard key is in cache.
:::bash
~ -> gpg-connect-agent 'scd getinfo card_list' /bye
S SERIALNO REDACTEDREDACTEDREDACTEDREDACTED
OK
:::bash
~ -> gpg-connect-agent 'scd getinfo card_list' /bye
OK
###Implementing
The following is a tasty little piece of awk that check is any smartcard is listed as active, and returns '`1`' if yes.
:::bash
gpg-connect-agent 'scd getinfo card_list' /bye 2>/dev/null | awk 'BEGIN {CH=0} /SERIALNO/ {if($0!=""){CH=1}} END {print CH}'
And for a cherry on top, there is a *'oneliner'* that will check if either a local key or a smartcard is cached:
:::bash
{ gpg-connect-agent 'keyinfo --list' /bye 2>/dev/null; gpg-connect-agent 'scd getinfo card_list' /bye 2>/dev/null; } | awk 'BEGIN{CH=0} /^S/ {if($7==1){CH=1}; if($2=="SERIALNO"){CH=1}} END{if($0!=""){print CH} else {print "none"}}'
###Bonus: Pictures of smartcards in a Thinkpad.
Because it is ***impossible*** to find a picture of a smartcard in a Thinkpad laptop on the internet, here is my x260 with a card in it.
* normal

* trimmed

###Links
[kernel concepts]
[yubikey neo]
[password store]
[Part1]
[Part2]
[kernel concepts]: http://shop.kernelconcepts.de/
[yubikey neo]: https://www.yubico.com/products/yubikey-hardware/yubikey-neo/
[password store]: https://www.passwordstore.org/
[Part1]: {filename}007-gpg_cache_check.md
[Part2]: {filename}009-gpg_cache_check_part2.md