Page MenuHome GnuPG

writecert fails for ECC keys on PIV cards
Closed, ResolvedPublic

Description

I basically followed the notes on PIV in the manual page of gpg-card except that I generated a nistp256 key instead of an rsa2048 key for the digital signature key, i.e. PIV.9C.

gpg/card> generate --force --algo=nistp256 PIV.9C                      
PIV card no. yk-9074582 detected
gpg/card> list
Reader ...........: 1050:0407:X:0
Card type ........: yubikey
Card firmware ....: 5.1.2
Serial number ....: FF020001008A7796
Application type .: PIV
Version ..........: 1.0
Displayed s/n ....: yk-9074582
PIN usage policy .: app-pin
PIN retry counter : - [verified] - [?]
PIV authentication: EB6A99D61EF3BC7C7934173CD9833376D773E65D
      keyref .....: PIV.9A  (auth)
      algorithm ..: nistp256
Card authenticat. : 2AD7D08C11E0B8C98FC7BE87A7116427AD589F28
      keyref .....: PIV.9E  (auth)
      algorithm ..: nistp256
Digital signature : 541CF278539F78656A5B0176C75D5CAD58A26736
      keyref .....: PIV.9C  (sign,cert)
      algorithm ..: nistp256
Key management ...: ED6579C1360100BE92C46ECB1A1826A63614D5AB
      keyref .....: PIV.9D  (encr)
      algorithm ..: rsa2048
      used for ...: X.509
        user id ..: CN=Encryption key for yk-9074582,O=example,C=DE
        user id ..: <otto@example.net>
gpg/card>

After generating a self-signed certificate as described on the man page the attempt to write this certificate to the card failed.

$ gpg-card 
Reader ...........: 1050:0407:X:0
Card type ........: yubikey
Card firmware ....: 5.1.2
Serial number ....: FF020001008A7796
Application type .: PIV
Version ..........: 1.0
Displayed s/n ....: yk-9074582
PIN usage policy .: app-pin
PIN retry counter : - [verified] - [?]
PIV authentication: EB6A99D61EF3BC7C7934173CD9833376D773E65D
      keyref .....: PIV.9A  (auth)
      algorithm ..: nistp256
Card authenticat. : 2AD7D08C11E0B8C98FC7BE87A7116427AD589F28
      keyref .....: PIV.9E  (auth)
      algorithm ..: nistp256
Digital signature : 541CF278539F78656A5B0176C75D5CAD58A26736
      keyref .....: PIV.9C  (sign,cert)
      algorithm ..: nistp256
      used for ...: X.509
        user id ..: CN=Signing key for yk-9074582,O=example,C=DE
        user id ..: <otto@example.net>
Key management ...: ED6579C1360100BE92C46ECB1A1826A63614D5AB
      keyref .....: PIV.9D  (encr)
      algorithm ..: rsa2048
      used for ...: X.509
        user id ..: CN=Encryption key for yk-9074582,O=example,C=DE
        user id ..: <otto@example.net>

gpg/card> writecert PIV.9C < /home/ingo/dev/g10/sign-nistp256-541CF278539F78656A5B0176C75D5CAD58A26736.crt
Command 'writecert' failed: Conflicting use
gpg/card> 

I have traced down the problem. In do_writecert() (app-piv.c) the public key in the certificate is compared with the public key on the card. The problem is that the representation of the curve differs in the two S-expressions of the public key:

2020-09-10 15:05:54 scdaemon[12280] DBG: orig_pk: (public-key \n (ecc \n  (curve nistp256)\n  (q #0464ED1D5259833306831FE802E8487F5F5C879ACF671A2DD0A5C134CAC08F66D1429A27BCAFE41042E8A1ECDE2594270CB675D99AF704344ADE9344EA7350A4CD#)\n  )\n )\n
2020-09-10 15:05:54 scdaemon[12280] DBG:      pk: (public-key \n (ecc \n  (curve "1.2.840.10045.3.1.7")\n  (q #0464ED1D5259833306831FE802E8487F5F5C879ACF671A2DD0A5C134CAC08F66D1429A27BCAFE41042E8A1ECDE2594270CB675D99AF704344ADE9344EA7350A4CD#)\n  )\n )\n
2020-09-10 15:05:54 scdaemon[12280] operation writecert result: Conflicting use

I see that genkey_parse_ecc(), that is used via do_readkey() to read the public key from the card, uses "nistp256" for the curve. OTOH, app_help_pubkey_from_cert() (using ksba_cert_get_public_key()) uses the OID for the curve.