diff --git a/src/commands.c b/src/commands.c index dacc03cd..0bb928d3 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1857,9 +1857,9 @@ int yh_com_open_yksession(yubihsm_context *ctx, Argument *argv, uint8_t host_challenge[YH_EC_P256_PUBKEY_LEN] = {0}; size_t host_challenge_len = sizeof(host_challenge); - ykhsmauthrc = ykhsmauth_get_challenge_ex(ctx->state, argv[1].s, - argv[2].x, argv[2].len, - host_challenge, &host_challenge_len); + ykhsmauthrc = + ykhsmauth_get_challenge_ex(ctx->state, argv[1].s, argv[2].x, argv[2].len, + host_challenge, &host_challenge_len); if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Failed to get host challenge from the YubiKey: %s\n", ykhsmauth_strerror(ykhsmauthrc)); diff --git a/ykhsmauth/ykhsmauth.c b/ykhsmauth/ykhsmauth.c index 34a82b4a..62e2ec55 100644 --- a/ykhsmauth/ykhsmauth.c +++ b/ykhsmauth/ykhsmauth.c @@ -296,9 +296,8 @@ ykhsmauth_rc ykhsmauth_list_readers(ykhsmauth_state *state, char *readers, return YKHSMAUTHR_SUCCESS; } -ykhsmauth_rc ykhsmauth_get_version(ykhsmauth_state *state, char *version, - size_t len) { - if (state == NULL || version == NULL) { +ykhsmauth_rc ykhsmauth_get_version_ex(ykhsmauth_state *state, uint8_t *major, uint8_t *minor, uint8_t *patch) { + if (state == NULL || major == NULL || minor == NULL || patch == NULL) { return YKHSMAUTHR_INVALID_PARAMS; } @@ -312,17 +311,33 @@ ykhsmauth_rc ykhsmauth_get_version(ykhsmauth_state *state, char *version, YKHSMAUTHR_SUCCESS) { return res; } else if (sw == SW_SUCCESS && recv_len == 3) { - int result = snprintf(version, len, "%d.%d.%d", data[0], data[1], data[2]); + *major = data[0]; + *minor = data[1]; + *patch = data[2]; + return YKHSMAUTHR_SUCCESS; + } else { + return translate_error(sw, NULL); + } +} + +ykhsmauth_rc ykhsmauth_get_version(ykhsmauth_state *state, char *version, + size_t len) { + if (version == NULL) { + return YKHSMAUTHR_INVALID_PARAMS; + } + + uint8_t v[3] = {0}; + ykhsmauth_rc res = ykhsmauth_get_version_ex(state, &v[0], &v[1], &v[2]); + if(res == YKHSMAUTHR_SUCCESS) { + int result = snprintf(version, len, "%d.%d.%d", v[0], v[1], v[2]); if (result < 0) { if (state->verbose) { fprintf(stderr, "Version buffer too small\n"); } return YKHSMAUTHR_GENERIC_ERROR; } - return YKHSMAUTHR_SUCCESS; - } else { - return translate_error(sw, NULL); } + return res; } ykhsmauth_rc ykhsmauth_put(ykhsmauth_state *state, const uint8_t *mgmkey, @@ -603,18 +618,31 @@ ykhsmauth_rc ykhsmauth_get_challenge_ex(ykhsmauth_state *state, const char *labe return YKHSMAUTHR_INVALID_PARAMS; } + ykhsmauth_rc rc; + APDU apdu = {{0, YKHSMAUTH_INS_GET_CHALLENGE, 0, 0, 0, {0}}}; add_tag(&apdu, YKHSMAUTH_TAG_LABEL, label, strlen(label), 0); if(cpw && cpw_len) { - add_tag(&apdu, YKHSMAUTH_TAG_PW, cpw, cpw_len, YKHSMAUTH_PW_LEN - cpw_len); + uint8_t major = 0, minor = 0, patch = 0; + rc = ykhsmauth_get_version_ex(state, &major, &minor, &patch); + if(rc != YKHSMAUTHR_SUCCESS) { + fprintf(stderr, "Unable to YubiKey version\n"); + return false; + } + + if (major > 5 || (major == 5 && minor > 7) || + (major == 5 && minor == 7 && patch >= 1)) { + add_tag(&apdu, YKHSMAUTH_TAG_PW, cpw, cpw_len, + YKHSMAUTH_PW_LEN - cpw_len); + } } unsigned char data[256] = {0}; DWORD recv_len = sizeof(data); uint16_t sw = 0; - ykhsmauth_rc rc = send_data(state, &apdu, data, &recv_len, &sw); + rc = send_data(state, &apdu, data, &recv_len, &sw); if (rc != YKHSMAUTHR_SUCCESS) { return rc; } else if (sw != SW_SUCCESS) { diff --git a/ykhsmauth/ykhsmauth.h b/ykhsmauth/ykhsmauth.h index 98246eee..a5e33614 100644 --- a/ykhsmauth/ykhsmauth.h +++ b/ykhsmauth/ykhsmauth.h @@ -143,6 +143,8 @@ ykhsmauth_rc ykhsmauth_list_readers(ykhsmauth_state *state, char *readers, size_t *len); ykhsmauth_rc ykhsmauth_disconnect(ykhsmauth_state *state); +ykhsmauth_rc ykhsmauth_get_version_ex(ykhsmauth_state *state, uint8_t *major, + uint8_t *minor, uint8_t *patch); ykhsmauth_rc ykhsmauth_get_version(ykhsmauth_state *state, char *version, size_t len); diff --git a/yubihsm-auth/main.c b/yubihsm-auth/main.c index 46e2f8b7..b11db2c5 100644 --- a/yubihsm-auth/main.c +++ b/yubihsm-auth/main.c @@ -383,8 +383,26 @@ static bool get_challenge(ykhsmauth_state *state, char *label, char *credpasswor return false; } - ykhsmauth_rc ykhsmauthrc = - ykhsmauth_get_challenge_ex(state, label_parsed, cpw_parsed, cpw_parsed_len, challenge, &challenge_len); + ykhsmauth_rc ykhsmauthrc; + + uint8_t major = 0, minor = 0, patch = 0; + ykhsmauthrc = ykhsmauth_get_version_ex(state, &major, &minor, &patch); + if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { + fprintf(stderr, "Unable to get YubiKey firmware version: %s\n", + ykhsmauth_strerror(ykhsmauthrc)); + return false; + } + + if (major < 5 || (major == 5 && minor < 7) || + (major == 5 && minor == 7 && patch < 1)) { + ykhsmauthrc = + ykhsmauth_get_challenge(state, label_parsed, challenge, &challenge_len); + } else { + ykhsmauthrc = + ykhsmauth_get_challenge_ex(state, label_parsed, cpw_parsed, + cpw_parsed_len, challenge, &challenge_len); + } + if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Unable to get challenge: %s\n", ykhsmauth_strerror(ykhsmauthrc));