This commit is contained in:
emersonl
2017-05-26 15:34:03 -07:00
committed by Klas Lindfors
parent c05d879968
commit 6882bc5c7c
+37 -22
View File
@@ -274,6 +274,35 @@ ykpiv_rc ykpiv_list_readers(ykpiv_state *state, char *readers, size_t *len) {
return YKPIV_OK;
}
static ykpiv_rc _begin_transaction(ykpiv_state *state) {
long rc;
ykpiv_rc res;
rc = SCardBeginTransaction(state->card);
if((rc & 0xFFFFFFFF) == SCARD_W_RESET_CARD) {
if((res = _reconnect(state)) != YKPIV_OK) {
return res;
}
return _begin_transaction(state);
}
if(rc != SCARD_S_SUCCESS) {
if(state->verbose) {
fprintf(stderr, "error: Failed to begin pcsc transaction, rc=%08lx\n", rc);
}
return YKPIV_PCSC_ERROR;
}
return YKPIV_OK;
}
static ykpiv_rc _end_transaction(ykpiv_state *state) {
long rc = SCardEndTransaction(state->card, SCARD_LEAVE_CARD);
if(rc != SCARD_S_SUCCESS && state->verbose) {
fprintf(stderr, "error: Failed to end pcsc transaction, rc=%08lx\n", rc);
return YKPIV_PCSC_ERROR;
}
return YKPIV_OK;
}
ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ,
const unsigned char *in_data, long in_len,
unsigned char *out_data, unsigned long *out_len, int *sw) {
@@ -282,23 +311,11 @@ ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ,
ykpiv_rc res;
long rc;
*out_len = 0;
unsigned long active_protocol;
BeginTransaction:
rc = SCardBeginTransaction(state->card);
if((rc & 0xFFFFFFFF) == SCARD_W_RESET_CARD) {
res = _reconnect(state);
if(res != YKPIV_OK) {
res = _begin_transaction(state);
if (res != YKPIV_OK) {
return res;
}
goto BeginTransaction;
}
if(rc != SCARD_S_SUCCESS) {
if(state->verbose) {
fprintf(stderr, "error: Failed to begin pcsc transaction, rc=%08lx\n", rc);
}
return YKPIV_PCSC_ERROR;
}
do {
size_t this_size = 0xff;
unsigned char data[261];
@@ -319,14 +336,17 @@ BeginTransaction:
memcpy(apdu.st.data, in_ptr, this_size);
res = send_data(state, &apdu, data, &recv_len, sw);
if(res != YKPIV_OK) {
_end_transaction(state);
return res;
} else if(*sw != SW_SUCCESS && *sw >> 8 != 0x61) {
_end_transaction(state);
return YKPIV_OK;
}
if(*out_len + recv_len - 2 > max_out) {
if(state->verbose) {
fprintf(stderr, "Output buffer to small, wanted to write %lu, max was %lu.\n", *out_len + recv_len - 2, max_out);
}
_end_transaction(state);
return YKPIV_SIZE_ERROR;
}
if(out_data) {
@@ -349,8 +369,10 @@ BeginTransaction:
apdu.st.ins = 0xc0;
res = send_data(state, &apdu, data, &recv_len, sw);
if(res != YKPIV_OK) {
_end_transaction(state);
return res;
} else if(*sw != SW_SUCCESS && *sw >> 8 != 0x61) {
_end_transaction(state);
return YKPIV_OK;
}
if(*out_len + recv_len - 2 > max_out) {
@@ -362,14 +384,7 @@ BeginTransaction:
*out_len += recv_len - 2;
}
}
rc = SCardEndTransaction(state->card, SCARD_LEAVE_CARD);
if(rc != SCARD_S_SUCCESS) {
if(state->verbose) {
fprintf(stderr, "error: Failed to end pcsc transaction, rc=%08lx\n", rc);
}
return YKPIV_PCSC_ERROR;
}
return YKPIV_OK;
return _end_transaction(state);
}
static ykpiv_rc send_data(ykpiv_state *state, APDU *apdu,