diff --git a/cmdline.ggo b/cmdline.ggo index c63a818..28bfd7f 100644 --- a/cmdline.ggo +++ b/cmdline.ggo @@ -27,7 +27,7 @@ option "verbose" v "Print more information" int optional default="0" argoptional option "reader" r "Only use a matching reader" string optional default="Yubikey" option "key" k "Authentication key to use" string optional default="010203040506070801020304050607080102030405060708" -option "action" a "Action to take" values="version","generate","set-mgm-key","reset","pin-retries","import-key","import-certificate" enum multiple +option "action" a "Action to take" values="version","generate","set-mgm-key","reset","pin-retries","import-key","import-certificate","set-chuid" enum multiple option "slot" s "What key slot to operate on" values="9a","9c","9d","9e" enum optional option "algorithm" A "What algorithm to use" values="RSA1024","RSA2048","ECCP256" enum optional default="RSA2048" option "new-key" n "New authentication key to use" string optional diff --git a/yubico-piv-tool.c b/yubico-piv-tool.c index 88b55c9..caa1ff4 100644 --- a/yubico-piv-tool.c +++ b/yubico-piv-tool.c @@ -35,6 +35,7 @@ #include #include #include +#include #if BACKEND_PCSC #if defined HAVE_PCSC_WINSCARD_H @@ -52,6 +53,19 @@ unsigned const char aid[] = { }; #define AID_LEN 5 +/* FASC-N containing F9999F9999F999999F0F1F0000000000300001E encoded in + * 4-bit BCD with 1 bit parity. run through the tools/fasc.pl script to get + * bytes. */ +unsigned const char chuid_tmpl[] = { + 0x5c, 0x03, 0x5f, 0xc1, 0x02, 0x53, 0x3b, 0x30, 0x19, 0xd4, 0xe7, 0x39, 0xea, + 0x73, 0x9c, 0xf5, 0x39, 0xce, 0x73, 0x9e, 0x83, 0xa8, 0x68, 0x21, 0x08, 0x42, + 0x10, 0x84, 0x21, 0x38, 0x42, 0x10, 0xc3, 0xf9, 0x34, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x35, 0x08, 0x32, 0x30, 0x33, 0x30, 0x30, 0x31, 0x30, 0x31, 0x3e, 0x00, 0xfe, + 0x00, +}; +#define CHUID_GUID_OFFS 35 + #define KEY_LEN 24 union u_APDU { @@ -766,6 +780,37 @@ import_cert_out: return ret; } +static bool set_chuid(SCARDHANDLE *card, int verbose) { + APDU apdu; + unsigned char data[0xff]; + unsigned char *dataptr = apdu.st.data; + unsigned long recv_len = sizeof(data); + int sw; + + memset(apdu.raw, 0, sizeof(apdu)); + memcpy(apdu.st.data, chuid_tmpl, sizeof(chuid_tmpl)); + dataptr += CHUID_GUID_OFFS; + if(RAND_pseudo_bytes(dataptr, 0x10) == -1) { + fprintf(stderr, "error: no randomness.\n"); + return false; + } + if(verbose) { + fprintf(stderr, "Setting the GUID to: "); + dump_hex(dataptr, 0x10); + fprintf(stderr, "\n"); + } + apdu.st.ins = 0xdb; + apdu.st.p1 = 0x3f; + apdu.st.p2 = 0xff; + apdu.st.lc = sizeof(chuid_tmpl); + sw = send_data(card, &apdu, sizeof(chuid_tmpl) + 5, data, &recv_len, verbose); + if(sw != 0x9000) { + fprintf(stderr, "Failed setting CHUID.\n"); + return false; + } + return true; +} + static int send_data(SCARDHANDLE *card, APDU *apdu, unsigned int send_len, unsigned char *data, unsigned long *recv_len, int verbose) { long rc; @@ -976,7 +1021,11 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } break; - + case action_arg_setMINUS_chuid: + if(set_chuid(&card, verbosity) == false) { + return EXIT_FAILURE; + } + printf("Successfully set new CHUID.\n"); break; case action__NULL: default: