diff --git a/lib/internal.c b/lib/internal.c index adf7e59..9e6c33b 100644 --- a/lib/internal.c +++ b/lib/internal.c @@ -2,8 +2,14 @@ #ifdef _WINDOWS #include #include +#include +#define WIN32_NO_STATUS +#include #else #include +#include +#include +#include #endif #include @@ -274,7 +280,7 @@ des_rc des_encrypt(des_key* key, const unsigned char* in, const size_t inlen, un #else /* openssl returns void */ - DES_ecb3_encrypt(in, out, &(key->ks1), &(key->ks2), &(key->ks3), 1); + DES_ecb3_encrypt((const_DES_cblock *)in, (DES_cblock*)out, &(key->ks1), &(key->ks2), &(key->ks3), 1); #endif @@ -306,7 +312,7 @@ des_rc des_decrypt(des_key* key, const unsigned char* in, const size_t inlen, un #else /* openssl returns void */ - DES_ecb3_encrypt(in, out, &(key->ks1), &(key->ks2), &(key->ks3), 0); + DES_ecb3_encrypt((const_DES_cblock*)in, (DES_cblock*)out, &(key->ks1), &(key->ks2), &(key->ks3), 0); #endif @@ -372,7 +378,6 @@ bool yk_des_is_weak_key(const unsigned char *key, const size_t cb_key) { } prng_rc prng_generate(unsigned char *buffer, const size_t cb_req) { - // TREV TODO: ykpiv.c needs to use this prng_rc rc = PRNG_OK; #ifdef _WINDOWS @@ -399,17 +404,6 @@ prng_rc prng_generate(unsigned char *buffer, const size_t cb_req) { return rc; } -// TREV TODO: what to do with this? - -#ifdef _WINDOWS -#include -#define WIN32_NO_STATUS -#include -#include -#else -#include -#endif - pkcs5_rc pkcs5_pbkdf2_sha1(const unsigned char* password, const size_t cb_password, const unsigned char* salt, const size_t cb_salt, unsigned long long iterations, unsigned char* key, const size_t cb_key) { pkcs5_rc rc = PKCS5_OK; diff --git a/lib/internal.h b/lib/internal.h index 1244f85..66ab628 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -132,6 +132,7 @@ des_rc des_encrypt(des_key* key, const unsigned char* in, const size_t inlen, un des_rc des_decrypt(des_key* key, const unsigned char* in, const size_t inlen, unsigned char* out, size_t* outlen); bool yk_des_is_weak_key(const unsigned char *key, const size_t cb_key); pkcs5_rc pkcs5_pbkdf2_sha1(const unsigned char* password, const size_t cb_password, const unsigned char* salt, const size_t cb_salt, unsigned long long iterations, unsigned char* key, const size_t cb_key); +prng_rc prng_generate(unsigned char *buffer, const size_t cb_req); #ifdef __cplusplus } diff --git a/lib/ykpiv.c b/lib/ykpiv.c index cfa7a96..02ab7f6 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -156,7 +156,7 @@ ykpiv_rc ykpiv_init_with_allocator(ykpiv_state **state, int verbose, const ykpiv s->pin = NULL; s->allocator = *allocator; s->verbose = verbose; - s->context = SCARD_E_INVALID_HANDLE; // TREV TODO -1 on Windows + s->context = SCARD_E_INVALID_HANDLE; *state = s; return YKPIV_OK; } @@ -167,8 +167,7 @@ ykpiv_rc ykpiv_init(ykpiv_state **state, int verbose) { ykpiv_rc ykpiv_done(ykpiv_state *state) { ykpiv_disconnect(state); - if (state->pin) - _ykpiv_free(state, state->pin); + _cache_pin(state, NULL, 0); _ykpiv_free(state, state); return YKPIV_OK; } @@ -234,7 +233,7 @@ ykpiv_rc _ykpiv_ensure_application_selected(ykpiv_state *state) { return res; } -static ykpiv_rc _connect_internal(ykpiv_state *state, uintptr_t context, uintptr_t card) { +static ykpiv_rc _connect_internal(ykpiv_state *state, uint64_t context, uint64_t card) { ykpiv_rc res = YKPIV_OK; if (NULL == state) { @@ -272,7 +271,12 @@ static ykpiv_rc _connect_internal(ykpiv_state *state, uintptr_t context, uintptr return res; } +ykpiv_rc ykpiv_connect_with_card(ykpiv_state *state, uint64_t context, uint64_t card) { + return _connect_internal(state, context, card); +} + ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted) { + // TREV TODO: use _connect_internal unsigned long active_protocol; char reader_buf[2048]; size_t num_readers = sizeof(reader_buf); @@ -330,7 +334,6 @@ static ykpiv_rc reconnect(ykpiv_state *state) { long rc; ykpiv_rc res; int tries; - if(state->verbose) { fprintf(stderr, "trying to reconnect to current reader.\n"); } @@ -884,6 +887,29 @@ ykpiv_rc ykpiv_get_version(ykpiv_state *state, char *version, size_t len) { } } +ykpiv_rc _cache_pin(ykpiv_state *state, const char *pin, size_t len) { +#ifdef DISABLE_PIN_CACHE + // Some embedded applications of this library may not want to keep the PIN + // data in RAM for security reasons. + return YKPIV_OK; +#else + if (!state) + return YKPIV_ARGUMENT_ERROR; + if (state->pin) { + _ykpiv_free(state, state->pin); + state->pin = NULL; + } + if (pin && len > 0) { + state->pin = _ykpiv_alloc(state, len * sizeof(char) + 1); + if (state->pin == NULL) { + return YKPIV_MEMORY_ERROR; + } + memcpy(state->pin, pin, len + 1); + } + return YKPIV_OK; +#endif +} + ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, int *tries) { // TREV TODO: pin len? APDU apdu; @@ -914,14 +940,9 @@ ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, int *tries) { if((res = _send_data(state, &apdu, data, &recv_len, &sw)) != YKPIV_OK) { return res; } else if(sw == SW_SUCCESS) { - if (pin) { - _ykpiv_free(state, state->pin); - state->pin = _ykpiv_alloc(state, len * sizeof(char) + 1); - if (state->pin == NULL) { - return YKPIV_MEMORY_ERROR; - } - memcpy(state->pin, pin, len + 1); - } + // Intentionally ignore errors. If the PIN fails to save, it will only + // be a problem if a reconnect is attempted. Failure deferred until then. + _cache_pin(state, pin, len + 1); if (tries) *tries = (sw & 0xf); return YKPIV_OK; } else if((sw >> 8) == 0x63) { @@ -1026,12 +1047,9 @@ static ykpiv_rc change_pin_internal(ykpiv_state *state, int action, const char * ykpiv_rc ykpiv_change_pin(ykpiv_state *state, const char * current_pin, size_t current_pin_len, const char * new_pin, size_t new_pin_len, int *tries) { ykpiv_rc res = change_pin_internal(state, CHREF_ACT_CHANGE_PIN, current_pin, current_pin_len, new_pin, new_pin_len, tries); if (res == YKPIV_OK && new_pin != NULL) { - _ykpiv_free(state, state->pin); - state->pin = _ykpiv_alloc(state, new_pin_len * sizeof(char) + 1); - if (state->pin == NULL) { - return YKPIV_MEMORY_ERROR; - } - memcpy(state->pin, new_pin, new_pin_len + 1); + // Intentionally ignore errors. If the PIN fails to save, it will only + // be a problem if a reconnect is attempted. Failure deferred until then. + _cache_pin(state, new_pin, new_pin_len + 1); } return res; } @@ -1252,16 +1270,11 @@ ykpiv_rc ykpiv_done2(ykpiv_state *state, bool disconnect) { // TODO: why is this needed? windows unit tests pass without it if (disconnect) ykpiv_disconnect(state); - if (state->pin) - _ykpiv_free(state, state->pin); + _cache_pin(state, NULL, 0); _ykpiv_free(state, state); return YKPIV_OK; } -ykpiv_rc ykpiv_init2(ykpiv_state **state, int verbose, const ykpiv_allocator *allocator) { - return ykpiv_init_with_allocator(state, verbose, allocator); -} - ykpiv_rc ykpiv_verify_select(ykpiv_state *state, const uint8_t *pin, const size_t pin_len, int *tries, bool force_select) { ykpiv_rc res = YKPIV_OK; if (YKPIV_OK != (res = _ykpiv_begin_transaction(state))) goto Cleanup; @@ -1277,7 +1290,3 @@ Cleanup: _ykpiv_end_transaction(state); return res; } - -ykpiv_rc ykpiv_connect2(ykpiv_state *state, uintptr_t context, uintptr_t card) { - return _connect_internal(state, context, card); -} diff --git a/lib/ykpiv.h b/lib/ykpiv.h index 9ad8df1..b0f3081 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -452,11 +452,11 @@ extern "C" ykpiv_rc ykpiv_util_block_puk(ykpiv_state *state); + ykpiv_rc ykpiv_connect_with_card(ykpiv_state *state, uint64_t context, uint64_t card); + // TREV TODO: remove ykpiv_rc ykpiv_done2(ykpiv_state *state, bool disconnect); - ykpiv_rc ykpiv_init2(ykpiv_state **state, int verbose, const ykpiv_allocator *allocator); ykpiv_rc ykpiv_verify_select(ykpiv_state *state, const uint8_t *pin, const size_t pin_len, int *tries, bool force_select); - ykpiv_rc ykpiv_connect2(ykpiv_state *state, uintptr_t context, uintptr_t card); #ifdef __cplusplus }