From b3cbfb5560a077a4034d5e7f48b7a71fb0febe4a Mon Sep 17 00:00:00 2001 From: Trevor Bentley Date: Mon, 23 Oct 2017 15:32:17 +0200 Subject: [PATCH] Some documentation and cleanup of ykpiv.h --- lib/ykpiv.c | 6 +- lib/ykpiv.h | 360 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 211 insertions(+), 155 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index 592261e..01723f9 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -205,7 +205,7 @@ ykpiv_rc _ykpiv_select_application(ykpiv_state *state) { ykpiv_rc res; memset(apdu.raw, 0, sizeof(apdu)); - apdu.st.ins = 0xa4; + apdu.st.ins = YKPIV_INS_SELECT_APPLICATION; apdu.st.p1 = 0x04; apdu.st.lc = sizeof(aid); memcpy(apdu.st.data, aid, sizeof(aid)); @@ -286,7 +286,7 @@ static ykpiv_rc _ykpiv_connect(ykpiv_state *state, uint64_t context, uint64_t ca return res; } -ykpiv_rc ykpiv_connect_with_external_card(ykpiv_state *state, uint64_t context, uint64_t card, bool select) { +ykpiv_rc ykpiv_connect_with_external_card(ykpiv_state *state, uint64_t context, uint64_t card) { return _ykpiv_connect(state, context, card); } @@ -506,7 +506,7 @@ ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, } memset(apdu.raw, 0, sizeof(apdu.raw)); - apdu.st.ins = 0xc0; + apdu.st.ins = YKPIV_INS_GET_RESPONSE_APDU; res = _send_data(state, &apdu, data, &recv_len, sw); if(res != YKPIV_OK) { goto Cleanup; diff --git a/lib/ykpiv.h b/lib/ykpiv.h index 64e348e..f41367b 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -102,7 +102,6 @@ extern "C" ykpiv_rc ykpiv_sign_data(ykpiv_state *state, const unsigned char *sign_in, size_t in_len, unsigned char *sign_out, size_t *out_len, unsigned char algorithm, unsigned char key); - // TODO (TREV): minidriver has ykpiv_sign_data2 ykpiv_rc ykpiv_decipher_data(ykpiv_state *state, const unsigned char *enc_in, size_t in_len, unsigned char *enc_out, size_t *out_len, unsigned char algorithm, unsigned char key); @@ -120,7 +119,7 @@ extern "C" ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id, unsigned char *data, unsigned long *len); ykpiv_rc ykpiv_set_mgmkey2(ykpiv_state *state, const unsigned char *new_key, - const unsigned char touch); + const unsigned char touch); ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id, unsigned char *indata, size_t len); ykpiv_rc ykpiv_import_private_key(ykpiv_state *state, const unsigned char key, unsigned char algorithm, @@ -131,151 +130,45 @@ extern "C" const unsigned char *qinv, size_t qinv_len, const unsigned char *ec_data, unsigned char ec_data_len, const unsigned char pin_policy, const unsigned char touch_policy); - // TREV TODO: document that this only works when NOT verified, as per spec (NIST SP 800-73-3 part 2 page 11) + + /** + * Return the number of PIN attempts remaining before PIN is locked. + * + * **NOTE:** If PIN is already verified, calling ykpiv_get_pin_retries() will unverify the PIN. + * + * @param state State handle from ykpiv_init() + * @param tries Set to number of attempts remaining + * + * @return Error code + */ ykpiv_rc ykpiv_get_pin_retries(ykpiv_state *state, int* tries); - // TREV TODO: document that 0 == successful no-op. + + /** + * Set number of attempts before locking for PIN and PUK codes. + * + * **NOTE:** If either \p pin_tries or \p puk_tries is 0, ykpiv_set_pin_retries() immediately returns YKPIV_OK. + * + * @param state State handle from ykpiv_init() + * @param pin_tries Number of attempts to permit for PIN code + * @param puk_tries Number of attempts to permit for PUK code + * + * @return Error code + */ ykpiv_rc ykpiv_set_pin_retries(ykpiv_state *state, int pin_tries, int puk_tries); + ykpiv_rc ykpiv_attest(ykpiv_state *state, const unsigned char key, unsigned char *data, size_t *data_len); -#define YKPIV_ALGO_TAG 0x80 -#define YKPIV_ALGO_3DES 0x03 -#define YKPIV_ALGO_RSA1024 0x06 -#define YKPIV_ALGO_RSA2048 0x07 -#define YKPIV_ALGO_ECCP256 0x11 -#define YKPIV_ALGO_ECCP384 0x14 - -#define YKPIV_KEY_AUTHENTICATION 0x9a -#define YKPIV_KEY_CARDMGM 0x9b -#define YKPIV_KEY_SIGNATURE 0x9c -#define YKPIV_KEY_KEYMGM 0x9d -#define YKPIV_KEY_CARDAUTH 0x9e -#define YKPIV_KEY_RETIRED1 0x82 -#define YKPIV_KEY_RETIRED2 0x83 -#define YKPIV_KEY_RETIRED3 0x84 -#define YKPIV_KEY_RETIRED4 0x85 -#define YKPIV_KEY_RETIRED5 0x86 -#define YKPIV_KEY_RETIRED6 0x87 -#define YKPIV_KEY_RETIRED7 0x88 -#define YKPIV_KEY_RETIRED8 0x89 -#define YKPIV_KEY_RETIRED9 0x8a -#define YKPIV_KEY_RETIRED10 0x8b -#define YKPIV_KEY_RETIRED11 0x8c -#define YKPIV_KEY_RETIRED12 0x8d -#define YKPIV_KEY_RETIRED13 0x8e -#define YKPIV_KEY_RETIRED14 0x8f -#define YKPIV_KEY_RETIRED15 0x90 -#define YKPIV_KEY_RETIRED16 0x91 -#define YKPIV_KEY_RETIRED17 0x92 -#define YKPIV_KEY_RETIRED18 0x93 -#define YKPIV_KEY_RETIRED19 0x94 -#define YKPIV_KEY_RETIRED20 0x95 -#define YKPIV_KEY_ATTESTATION 0xf9 - -#define YKPIV_OBJ_CAPABILITY 0x5fc107 -#define YKPIV_OBJ_CHUID 0x5fc102 -#define YKPIV_OBJ_AUTHENTICATION 0x5fc105 /* cert for 9a key */ -#define YKPIV_OBJ_FINGERPRINTS 0x5fc103 -#define YKPIV_OBJ_SECURITY 0x5fc106 -#define YKPIV_OBJ_FACIAL 0x5fc108 -#define YKPIV_OBJ_PRINTED 0x5fc109 -#define YKPIV_OBJ_SIGNATURE 0x5fc10a /* cert for 9c key */ -#define YKPIV_OBJ_KEY_MANAGEMENT 0x5fc10b /* cert for 9d key */ -#define YKPIV_OBJ_CARD_AUTH 0x5fc101 /* cert for 9e key */ -#define YKPIV_OBJ_DISCOVERY 0x7e -#define YKPIV_OBJ_KEY_HISTORY 0x5fc10c -#define YKPIV_OBJ_IRIS 0x5fc121 - -#define YKPIV_OBJ_RETIRED1 0x5fc10d -#define YKPIV_OBJ_RETIRED2 0x5fc10e -#define YKPIV_OBJ_RETIRED3 0x5fc10f -#define YKPIV_OBJ_RETIRED4 0x5fc110 -#define YKPIV_OBJ_RETIRED5 0x5fc111 -#define YKPIV_OBJ_RETIRED6 0x5fc112 -#define YKPIV_OBJ_RETIRED7 0x5fc113 -#define YKPIV_OBJ_RETIRED8 0x5fc114 -#define YKPIV_OBJ_RETIRED9 0x5fc115 -#define YKPIV_OBJ_RETIRED10 0x5fc116 -#define YKPIV_OBJ_RETIRED11 0x5fc117 -#define YKPIV_OBJ_RETIRED12 0x5fc118 -#define YKPIV_OBJ_RETIRED13 0x5fc119 -#define YKPIV_OBJ_RETIRED14 0x5fc11a -#define YKPIV_OBJ_RETIRED15 0x5fc11b -#define YKPIV_OBJ_RETIRED16 0x5fc11c -#define YKPIV_OBJ_RETIRED17 0x5fc11d -#define YKPIV_OBJ_RETIRED18 0x5fc11e -#define YKPIV_OBJ_RETIRED19 0x5fc11f -#define YKPIV_OBJ_RETIRED20 0x5fc120 - -#define YKPIV_OBJ_ATTESTATION 0x5fff01 - -#define YKPIV_OBJ_MAX_SIZE 3072 - -#define YKPIV_INS_VERIFY 0x20 -#define YKPIV_INS_CHANGE_REFERENCE 0x24 -#define YKPIV_INS_RESET_RETRY 0x2c -#define YKPIV_INS_GENERATE_ASYMMETRIC 0x47 -#define YKPIV_INS_AUTHENTICATE 0x87 -#define YKPIV_INS_GET_DATA 0xcb -#define YKPIV_INS_PUT_DATA 0xdb - // TREV TODO: why aren't all of them here? ex: select app (0xa4) - -/* sw is status words, see NIST special publication 800-73-4, section 5.6 */ -#define SW_SUCCESS 0x9000 -#define SW_ERR_SECURITY_STATUS 0x6982 -#define SW_ERR_AUTH_BLOCKED 0x6983 -#define SW_ERR_INCORRECT_PARAM 0x6a80 -/* this is a custom sw for yubikey */ -#define SW_ERR_INCORRECT_SLOT 0x6b00 -#define SW_ERR_NOT_SUPPORTED 0x6d00 - - /* Yubico vendor specific instructions */ -#define YKPIV_INS_SET_MGMKEY 0xff -#define YKPIV_INS_IMPORT_KEY 0xfe -#define YKPIV_INS_GET_VERSION 0xfd -#define YKPIV_INS_RESET 0xfb -#define YKPIV_INS_SET_PIN_RETRIES 0xfa -#define YKPIV_INS_ATTEST 0xf9 - -#define YKPIV_PINPOLICY_TAG 0xaa -#define YKPIV_PINPOLICY_DEFAULT 0 -#define YKPIV_PINPOLICY_NEVER 1 -#define YKPIV_PINPOLICY_ONCE 2 -#define YKPIV_PINPOLICY_ALWAYS 3 - -#define YKPIV_TOUCHPOLICY_TAG 0xab -#define YKPIV_TOUCHPOLICY_DEFAULT 0 -#define YKPIV_TOUCHPOLICY_NEVER 1 -#define YKPIV_TOUCHPOLICY_ALWAYS 2 -#define YKPIV_TOUCHPOLICY_CACHED 3 - -#define YKPIV_IS_EC(a) ((a == YKPIV_ALGO_ECCP256 || a == YKPIV_ALGO_ECCP384)) -#define YKPIV_IS_RSA(a) ((a == YKPIV_ALGO_RSA1024 || a == YKPIV_ALGO_RSA2048)) - -#define YKPIV_RETRIES_DEFAULT 3 -#define YKPIV_RETRIES_MAX 0xff - -#define YKPIV_CERTINFO_UNCOMPRESSED 0 -#define YKPIV_CERTINFO_GZIP 1 // -// UTIL +// HIGH-LEVEL UTIL API // -#define YKPIV_ATR_NEO_R3 "\x3b\xfc\x13\x00\x00\x81\x31\xfe\x15\x59\x75\x62\x69\x6b\x65\x79\x4e\x45\x4f\x72\x33\xe1" -#define YKPIV_ATR_YK4 "\x3b\xf8\x13\x00\x00\x81\x31\xfe\x15\x59\x75\x62\x69\x6b\x65\x79\x34\xd4" - -#define DEVTYPE_UNKNOWN 0x00000000 -#define DEVTYPE_NEO 0x4E450000 //"NE" -#define DEVTYPE_YK 0x594B0000 //"YK" -#define DEVTYPE_NEOr3 (DEVTYPE_NEO | 0x00007233) //"r3" -#define DEVTYPE_YK4 (DEVTYPE_YK | 0x00000034) // "4" - typedef uint32_t ykpiv_devmodel; /** * Card identifier */ - #define YKPIV_CARDID_SIZE 16 +#define YKPIV_CARDID_SIZE 16 typedef struct { uint8_t data[YKPIV_CARDID_SIZE]; } ykpiv_cardid; @@ -283,7 +176,7 @@ extern "C" /** * Card Capability */ - #define YKPIV_CCCID_SIZE 14 +#define YKPIV_CCCID_SIZE 14 typedef struct { uint8_t data[YKPIV_CCCID_SIZE]; } ykpiv_cccid; @@ -367,14 +260,14 @@ extern "C" } ykpiv_mgm; #pragma pack(pop) - /** - * Get current PIV applet administration configuration state - * - * @param state [in] state - * @param config [out] output ykpiv_config struct with current applet data - * - * @return ykpiv_rc error code - */ + /** + * Get current PIV applet administration configuration state + * + * @param state [in] state + * @param config [out] output ykpiv_config struct with current applet data + * + * @return ykpiv_rc error code + */ ykpiv_rc ykpiv_util_get_config(ykpiv_state *state, ykpiv_config *config); /** @@ -425,14 +318,14 @@ extern "C" ykpiv_rc ykpiv_util_set_protected_mgm(ykpiv_state *state, ykpiv_mgm *mgm); /** - * Reset PIV applet - * - * The user pin and puk must be blocked to call this function. - * - * @param state state - * - * @return ykpiv_rc error code - */ + * Reset PIV applet + * + * The user pin and puk must be blocked to call this function. + * + * @param state state + * + * @return ykpiv_rc error code + */ ykpiv_rc ykpiv_util_reset(ykpiv_state *state); /** @@ -509,10 +402,173 @@ extern "C" */ uint32_t ykpiv_util_slot_object(uint8_t slot); - ykpiv_rc ykpiv_connect_with_exteral_card(ykpiv_state *state, uint64_t context, uint64_t card, bool select); + /** + * Variant of ykpiv_connect() that accepts a card context obtained externally. + * + * Not for generic use. Use ykpiv_connect() instead. + * + * @param state State handle + * @param context Card context returned from SCardConnect() or equivalent. + * @param card Card ID returned from SCardConnect() or equivalent. + * + * @return Error code + */ + ykpiv_rc ykpiv_connect_with_external_card(ykpiv_state *state, uint64_t context, uint64_t card); + + /** + * Variant of ykpiv_done() for external cards connected with ykpiv_connect_with_external_card() + * + * Card is not disconnected, unlike with normal calls to ykpiv_done(). + * + * @param state State handle + * + * @return Error code + */ ykpiv_rc ykpiv_done_with_external_card(ykpiv_state *state); + + /** + * Variant of ykpiv_verify() that optionally selects the PIV applet first. + * + * @param state State handle + * @param pin PIN code to verify with + * @param pin_len Length of \p pin + * @param tries Set to number of attempts remaining (if non-NULL) + * @param force_select Whether to select the PIV applet before verifying. + * + * @return Error code + */ ykpiv_rc ykpiv_verify_select(ykpiv_state *state, const char *pin, const size_t pin_len, int *tries, bool force_select); +#define YKPIV_ALGO_TAG 0x80 +#define YKPIV_ALGO_3DES 0x03 +#define YKPIV_ALGO_RSA1024 0x06 +#define YKPIV_ALGO_RSA2048 0x07 +#define YKPIV_ALGO_ECCP256 0x11 +#define YKPIV_ALGO_ECCP384 0x14 + +#define YKPIV_KEY_AUTHENTICATION 0x9a +#define YKPIV_KEY_CARDMGM 0x9b +#define YKPIV_KEY_SIGNATURE 0x9c +#define YKPIV_KEY_KEYMGM 0x9d +#define YKPIV_KEY_CARDAUTH 0x9e +#define YKPIV_KEY_RETIRED1 0x82 +#define YKPIV_KEY_RETIRED2 0x83 +#define YKPIV_KEY_RETIRED3 0x84 +#define YKPIV_KEY_RETIRED4 0x85 +#define YKPIV_KEY_RETIRED5 0x86 +#define YKPIV_KEY_RETIRED6 0x87 +#define YKPIV_KEY_RETIRED7 0x88 +#define YKPIV_KEY_RETIRED8 0x89 +#define YKPIV_KEY_RETIRED9 0x8a +#define YKPIV_KEY_RETIRED10 0x8b +#define YKPIV_KEY_RETIRED11 0x8c +#define YKPIV_KEY_RETIRED12 0x8d +#define YKPIV_KEY_RETIRED13 0x8e +#define YKPIV_KEY_RETIRED14 0x8f +#define YKPIV_KEY_RETIRED15 0x90 +#define YKPIV_KEY_RETIRED16 0x91 +#define YKPIV_KEY_RETIRED17 0x92 +#define YKPIV_KEY_RETIRED18 0x93 +#define YKPIV_KEY_RETIRED19 0x94 +#define YKPIV_KEY_RETIRED20 0x95 +#define YKPIV_KEY_ATTESTATION 0xf9 + +#define YKPIV_OBJ_CAPABILITY 0x5fc107 +#define YKPIV_OBJ_CHUID 0x5fc102 +#define YKPIV_OBJ_AUTHENTICATION 0x5fc105 /* cert for 9a key */ +#define YKPIV_OBJ_FINGERPRINTS 0x5fc103 +#define YKPIV_OBJ_SECURITY 0x5fc106 +#define YKPIV_OBJ_FACIAL 0x5fc108 +#define YKPIV_OBJ_PRINTED 0x5fc109 +#define YKPIV_OBJ_SIGNATURE 0x5fc10a /* cert for 9c key */ +#define YKPIV_OBJ_KEY_MANAGEMENT 0x5fc10b /* cert for 9d key */ +#define YKPIV_OBJ_CARD_AUTH 0x5fc101 /* cert for 9e key */ +#define YKPIV_OBJ_DISCOVERY 0x7e +#define YKPIV_OBJ_KEY_HISTORY 0x5fc10c +#define YKPIV_OBJ_IRIS 0x5fc121 + +#define YKPIV_OBJ_RETIRED1 0x5fc10d +#define YKPIV_OBJ_RETIRED2 0x5fc10e +#define YKPIV_OBJ_RETIRED3 0x5fc10f +#define YKPIV_OBJ_RETIRED4 0x5fc110 +#define YKPIV_OBJ_RETIRED5 0x5fc111 +#define YKPIV_OBJ_RETIRED6 0x5fc112 +#define YKPIV_OBJ_RETIRED7 0x5fc113 +#define YKPIV_OBJ_RETIRED8 0x5fc114 +#define YKPIV_OBJ_RETIRED9 0x5fc115 +#define YKPIV_OBJ_RETIRED10 0x5fc116 +#define YKPIV_OBJ_RETIRED11 0x5fc117 +#define YKPIV_OBJ_RETIRED12 0x5fc118 +#define YKPIV_OBJ_RETIRED13 0x5fc119 +#define YKPIV_OBJ_RETIRED14 0x5fc11a +#define YKPIV_OBJ_RETIRED15 0x5fc11b +#define YKPIV_OBJ_RETIRED16 0x5fc11c +#define YKPIV_OBJ_RETIRED17 0x5fc11d +#define YKPIV_OBJ_RETIRED18 0x5fc11e +#define YKPIV_OBJ_RETIRED19 0x5fc11f +#define YKPIV_OBJ_RETIRED20 0x5fc120 + +#define YKPIV_OBJ_ATTESTATION 0x5fff01 + +#define YKPIV_OBJ_MAX_SIZE 3072 + +#define YKPIV_INS_VERIFY 0x20 +#define YKPIV_INS_CHANGE_REFERENCE 0x24 +#define YKPIV_INS_RESET_RETRY 0x2c +#define YKPIV_INS_GENERATE_ASYMMETRIC 0x47 +#define YKPIV_INS_AUTHENTICATE 0x87 +#define YKPIV_INS_GET_DATA 0xcb +#define YKPIV_INS_PUT_DATA 0xdb +#define YKPIV_INS_SELECT_APPLICATION 0xa4 +#define YKPIV_INS_GET_RESPONSE_APDU 0xc0 + +/* sw is status words, see NIST special publication 800-73-4, section 5.6 */ +#define SW_SUCCESS 0x9000 +#define SW_ERR_SECURITY_STATUS 0x6982 +#define SW_ERR_AUTH_BLOCKED 0x6983 +#define SW_ERR_INCORRECT_PARAM 0x6a80 +/* this is a custom sw for yubikey */ +#define SW_ERR_INCORRECT_SLOT 0x6b00 +#define SW_ERR_NOT_SUPPORTED 0x6d00 + +/* Yubico vendor specific instructions */ +#define YKPIV_INS_SET_MGMKEY 0xff +#define YKPIV_INS_IMPORT_KEY 0xfe +#define YKPIV_INS_GET_VERSION 0xfd +#define YKPIV_INS_RESET 0xfb +#define YKPIV_INS_SET_PIN_RETRIES 0xfa +#define YKPIV_INS_ATTEST 0xf9 + +#define YKPIV_PINPOLICY_TAG 0xaa +#define YKPIV_PINPOLICY_DEFAULT 0 +#define YKPIV_PINPOLICY_NEVER 1 +#define YKPIV_PINPOLICY_ONCE 2 +#define YKPIV_PINPOLICY_ALWAYS 3 + +#define YKPIV_TOUCHPOLICY_TAG 0xab +#define YKPIV_TOUCHPOLICY_DEFAULT 0 +#define YKPIV_TOUCHPOLICY_NEVER 1 +#define YKPIV_TOUCHPOLICY_ALWAYS 2 +#define YKPIV_TOUCHPOLICY_CACHED 3 + +#define YKPIV_IS_EC(a) ((a == YKPIV_ALGO_ECCP256 || a == YKPIV_ALGO_ECCP384)) +#define YKPIV_IS_RSA(a) ((a == YKPIV_ALGO_RSA1024 || a == YKPIV_ALGO_RSA2048)) + +#define YKPIV_RETRIES_DEFAULT 3 +#define YKPIV_RETRIES_MAX 0xff + +#define YKPIV_CERTINFO_UNCOMPRESSED 0 +#define YKPIV_CERTINFO_GZIP 1 + +#define YKPIV_ATR_NEO_R3 "\x3b\xfc\x13\x00\x00\x81\x31\xfe\x15\x59\x75\x62\x69\x6b\x65\x79\x4e\x45\x4f\x72\x33\xe1" +#define YKPIV_ATR_YK4 "\x3b\xf8\x13\x00\x00\x81\x31\xfe\x15\x59\x75\x62\x69\x6b\x65\x79\x34\xd4" + +#define DEVTYPE_UNKNOWN 0x00000000 +#define DEVTYPE_NEO 0x4E450000 //"NE" +#define DEVTYPE_YK 0x594B0000 //"YK" +#define DEVTYPE_NEOr3 (DEVTYPE_NEO | 0x00007233) //"r3" +#define DEVTYPE_YK4 (DEVTYPE_YK | 0x00000034) // "4" + #ifdef __cplusplus } #endif