From 1a9e62cec8bc42a5ba5d614080ad3f78a6959132 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Mon, 7 Sep 2015 15:54:57 +0200 Subject: [PATCH 1/5] drop ykpiv_connect2() and add ykpiv_list_readers() --- lib/ykpiv.c | 108 +++++++++++++++++++++++++++--------------------- lib/ykpiv.h | 3 +- lib/ykpiv.map | 4 +- ykcs11/ykcs11.c | 7 +++- 4 files changed, 69 insertions(+), 53 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index fc60d47..aac931b 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -128,23 +128,20 @@ ykpiv_rc ykpiv_disconnect(ykpiv_state *state) { } ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted) { - return ykpiv_connect2(state, wanted, NULL, 0); -} - -ykpiv_rc ykpiv_connect2(ykpiv_state *state, const char *wanted, unsigned char **readers, unsigned long *len) { unsigned long num_readers = 0; unsigned long active_protocol; char reader_buf[1024]; long rc; - int i; char *reader_ptr; - rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &state->context); - if (rc != SCARD_S_SUCCESS) { - if(state->verbose) { - fprintf (stderr, "error: SCardEstablishContext failed, rc=%08lx\n", rc); + if(SCardIsValidContext(state->context) != SCARD_S_SUCCESS) { + rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &state->context); + if (rc != SCARD_S_SUCCESS) { + if(state->verbose) { + fprintf (stderr, "error: SCardEstablishContext failed, rc=%08lx\n", rc); + } + return YKPIV_PCSC_ERROR; } - return YKPIV_PCSC_ERROR; } rc = SCardListReaders(state->context, NULL, NULL, &num_readers); @@ -170,20 +167,6 @@ ykpiv_rc ykpiv_connect2(ykpiv_state *state, const char *wanted, unsigned char ** return YKPIV_PCSC_ERROR; } - // Save available readers (aka PKCS11 slots) - if (readers != NULL) { - *readers = malloc(sizeof(char) * num_readers); - if (*readers == NULL) { - if(state->verbose) { - fprintf (stderr, "error: malloc failed"); - } - SCardReleaseContext(state->context); - return YKPIV_MEMORY_ERROR; - } - memcpy(*readers, reader_buf, num_readers); - *len = num_readers; - } - for(reader_ptr = reader_buf; *reader_ptr != '\0'; reader_ptr += strlen(reader_ptr) + 1) { if(wanted) { if(!strstr(reader_ptr, wanted)) { @@ -245,6 +228,59 @@ ykpiv_rc ykpiv_connect2(ykpiv_state *state, const char *wanted, unsigned char ** return YKPIV_GENERIC_ERROR; } +ykpiv_rc ykpiv_list_readers(ykpiv_state *state, unsigned char **readers, unsigned long *len) { + unsigned long num_readers = 0; + char reader_buf[1024]; + long rc; + + if(SCardIsValidContext(state->context) != SCARD_S_SUCCESS) { + rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &state->context); + if (rc != SCARD_S_SUCCESS) { + if(state->verbose) { + fprintf (stderr, "error: SCardEstablishContext failed, rc=%08lx\n", rc); + } + return YKPIV_PCSC_ERROR; + } + } + + rc = SCardListReaders(state->context, NULL, NULL, &num_readers); + if (rc != SCARD_S_SUCCESS) { + if(state->verbose) { + fprintf (stderr, "error: SCardListReaders failed, rc=%08lx\n", rc); + } + SCardReleaseContext(state->context); + return YKPIV_PCSC_ERROR; + } + + if (num_readers > sizeof(reader_buf)) { + num_readers = sizeof(reader_buf); + } + + rc = SCardListReaders(state->context, NULL, reader_buf, &num_readers); + if (rc != SCARD_S_SUCCESS) + { + if(state->verbose) { + fprintf (stderr, "error: SCardListReaders failed, rc=%08lx\n", rc); + } + SCardReleaseContext(state->context); + return YKPIV_PCSC_ERROR; + } + + // Save available readers (aka PKCS11 slots) + *readers = malloc(sizeof(char) * num_readers); + if (*readers == NULL) { + if(state->verbose) { + fprintf (stderr, "error: malloc failed"); + } + SCardReleaseContext(state->context); + return YKPIV_MEMORY_ERROR; + } + memcpy(*readers, reader_buf, num_readers); + *len = num_readers; + + 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) { @@ -788,27 +824,3 @@ ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id, return YKPIV_GENERIC_ERROR; } } - -ykpiv_rc ykpiv_get_reader_slot_number(ykpiv_state *state, unsigned long *slots, unsigned long *total) { - if (state == NULL) - return YKPIV_MEMORY_ERROR; - - *slots = state->n_readers; - *total = state->tot_readers_len; - - return YKPIV_OK; - -} - -ykpiv_rc ykpiv_get_reader_slot(ykpiv_state *state, unsigned long slot, char *reader) { - if (state == NULL) - return YKPIV_MEMORY_ERROR; - - if (slot >= state->n_readers) - return YKPIV_SIZE_ERROR; - - strcpy(reader, state->readers[slot]); - - return YKPIV_OK; - -} diff --git a/lib/ykpiv.h b/lib/ykpiv.h index 3de24c4..d832283 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -65,8 +65,7 @@ extern "C" ykpiv_rc ykpiv_init(ykpiv_state **state, int verbose); ykpiv_rc ykpiv_done(ykpiv_state *state); ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted); - ykpiv_rc ykpiv_connect2(ykpiv_state *state, const char *wanted, - unsigned char **readers, unsigned long *len); // Allow to return a reader string + ykpiv_rc ykpiv_list_readers(ykpiv_state *state, unsigned char **readers, unsigned long *len); ykpiv_rc ykpiv_disconnect(ykpiv_state *state); ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, const unsigned char *in_data, long in_len, diff --git a/lib/ykpiv.map b/lib/ykpiv.map index 0a09fa6..dd817b2 100644 --- a/lib/ykpiv.map +++ b/lib/ykpiv.map @@ -53,12 +53,12 @@ YKPIV_0.2.0 { global: ykpiv_decipher_data; - ykpiv_connect2; - ykpiv_sign_data2; } YKPIV_0.1.0; YKPIV_1.1.0 { global: ykpiv_set_mgmkey2; + ykpiv_list_readers; + ykpiv_sign_data2; } YKPIV_0.1.0; diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index c795d17..4997329 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -60,7 +60,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( return CKR_FUNCTION_FAILED; // TODO: better error? } - if(ykpiv_connect2(piv_state, NULL, &readers, &len) != YKPIV_OK) { + if (ykpiv_list_readers(piv_state, &readers, &len) != YKPIV_OK) { + DBG(("Unable to list readers")); + return CKR_FUNCTION_FAILED; + } + + if(ykpiv_connect(piv_state, NULL) != YKPIV_OK) { DBG(("Unable to connect to reader")); return CKR_FUNCTION_FAILED; } From 8eb7595d42923c7f979105913ae654f3742d02b1 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Tue, 8 Sep 2015 12:26:42 +0200 Subject: [PATCH 2/5] add list-readers action to tool also refactor ykpiv_list_readers() a bit --- lib/ykpiv.c | 19 ++++--------------- lib/ykpiv.h | 2 +- tool/cmdline.ggo | 2 +- tool/yubico-piv-tool.c | 22 ++++++++++++++++++++++ ykcs11/ykcs11.c | 6 +++--- 5 files changed, 31 insertions(+), 20 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index aac931b..30c3ba3 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -228,9 +228,8 @@ ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted) { return YKPIV_GENERIC_ERROR; } -ykpiv_rc ykpiv_list_readers(ykpiv_state *state, unsigned char **readers, unsigned long *len) { +ykpiv_rc ykpiv_list_readers(ykpiv_state *state, char *readers, size_t *len) { unsigned long num_readers = 0; - char reader_buf[1024]; long rc; if(SCardIsValidContext(state->context) != SCARD_S_SUCCESS) { @@ -252,11 +251,11 @@ ykpiv_rc ykpiv_list_readers(ykpiv_state *state, unsigned char **readers, unsigne return YKPIV_PCSC_ERROR; } - if (num_readers > sizeof(reader_buf)) { - num_readers = sizeof(reader_buf); + if (num_readers > *len) { + num_readers = *len; } - rc = SCardListReaders(state->context, NULL, reader_buf, &num_readers); + rc = SCardListReaders(state->context, NULL, readers, &num_readers); if (rc != SCARD_S_SUCCESS) { if(state->verbose) { @@ -266,16 +265,6 @@ ykpiv_rc ykpiv_list_readers(ykpiv_state *state, unsigned char **readers, unsigne return YKPIV_PCSC_ERROR; } - // Save available readers (aka PKCS11 slots) - *readers = malloc(sizeof(char) * num_readers); - if (*readers == NULL) { - if(state->verbose) { - fprintf (stderr, "error: malloc failed"); - } - SCardReleaseContext(state->context); - return YKPIV_MEMORY_ERROR; - } - memcpy(*readers, reader_buf, num_readers); *len = num_readers; return YKPIV_OK; diff --git a/lib/ykpiv.h b/lib/ykpiv.h index d832283..ffbee83 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -65,7 +65,7 @@ extern "C" ykpiv_rc ykpiv_init(ykpiv_state **state, int verbose); ykpiv_rc ykpiv_done(ykpiv_state *state); ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted); - ykpiv_rc ykpiv_list_readers(ykpiv_state *state, unsigned char **readers, unsigned long *len); + ykpiv_rc ykpiv_list_readers(ykpiv_state *state, char *readers, size_t *len); ykpiv_rc ykpiv_disconnect(ykpiv_state *state); ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ, const unsigned char *in_data, long in_len, diff --git a/tool/cmdline.ggo b/tool/cmdline.ggo index d777748..bdd2a7e 100644 --- a/tool/cmdline.ggo +++ b/tool/cmdline.ggo @@ -32,7 +32,7 @@ option "action" a "Action to take" values="version","generate","set-mgm-key", "reset","pin-retries","import-key","import-certificate","set-chuid", "request-certificate","verify-pin","change-pin","change-puk","unblock-pin", "selfsign-certificate","delete-certificate","read-certificate","status", - "test-signature","test-decipher" enum multiple + "test-signature","test-decipher","list-readers" enum multiple text " Multiple actions may be given at once and will be executed in order for example --action=verify-pin --action=request-certificate\n" diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index 1fcbb25..e916be1 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -1569,6 +1569,21 @@ decipher_out: return ret; } +static bool list_readers(ykpiv_state *state) { + char readers[2048]; + char *reader_ptr; + size_t len = sizeof(readers); + ykpiv_rc rc = ykpiv_list_readers(state, readers, &len); + if(rc != YKPIV_OK) { + fprintf(stderr, "Failed listing readers.\n"); + return false; + } + for(reader_ptr = readers; *reader_ptr != '\0'; reader_ptr += strlen(reader_ptr) + 1) { + printf("%s\n", reader_ptr); + } + return true; +} + int main(int argc, char *argv[]) { struct gengetopt_args_info args_info; ykpiv_state *state; @@ -1622,6 +1637,7 @@ int main(int argc, char *argv[]) { case action_arg_version: case action_arg_reset: case action_arg_status: + case action_arg_listMINUS_readers: case action__NULL: default: continue; @@ -1666,6 +1682,7 @@ int main(int argc, char *argv[]) { case action_arg_status: case action_arg_testMINUS_signature: case action_arg_testMINUS_decipher: + case action_arg_listMINUS_readers: case action__NULL: default: if(verbosity) { @@ -1850,6 +1867,11 @@ int main(int argc, char *argv[]) { ret = EXIT_FAILURE; } break; + case action_arg_listMINUS_readers: + if(list_readers(state) == false) { + ret = EXIT_FAILURE; + } + break; case action__NULL: default: fprintf(stderr, "Wrong action. %d.\n", action); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 4997329..a4e6b94 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -47,8 +47,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( ) { DIN; - CK_CHAR_PTR readers; - CK_ULONG len; + char readers[2048]; + CK_ULONG len = sizeof(readers); // TODO: check for locks and mutexes @@ -60,7 +60,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( return CKR_FUNCTION_FAILED; // TODO: better error? } - if (ykpiv_list_readers(piv_state, &readers, &len) != YKPIV_OK) { + if (ykpiv_list_readers(piv_state, readers, &len) != YKPIV_OK) { DBG(("Unable to list readers")); return CKR_FUNCTION_FAILED; } From 4bbd888f97d4077f822efe5041341d5610784da4 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Tue, 8 Sep 2015 12:29:07 +0200 Subject: [PATCH 3/5] let ykpiv_connect() call ykpiv_list_readers() --- lib/ykpiv.c | 38 +++++--------------------------------- 1 file changed, 5 insertions(+), 33 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index 30c3ba3..6e3bc35 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -128,43 +128,15 @@ ykpiv_rc ykpiv_disconnect(ykpiv_state *state) { } ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted) { - unsigned long num_readers = 0; unsigned long active_protocol; - char reader_buf[1024]; + char reader_buf[2048]; + size_t num_readers = sizeof(reader_buf); long rc; char *reader_ptr; - if(SCardIsValidContext(state->context) != SCARD_S_SUCCESS) { - rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &state->context); - if (rc != SCARD_S_SUCCESS) { - if(state->verbose) { - fprintf (stderr, "error: SCardEstablishContext failed, rc=%08lx\n", rc); - } - return YKPIV_PCSC_ERROR; - } - } - - rc = SCardListReaders(state->context, NULL, NULL, &num_readers); - if (rc != SCARD_S_SUCCESS) { - if(state->verbose) { - fprintf (stderr, "error: SCardListReaders failed, rc=%08lx\n", rc); - } - SCardReleaseContext(state->context); - return YKPIV_PCSC_ERROR; - } - - if (num_readers > sizeof(reader_buf)) { - num_readers = sizeof(reader_buf); - } - - rc = SCardListReaders(state->context, NULL, reader_buf, &num_readers); - if (rc != SCARD_S_SUCCESS) - { - if(state->verbose) { - fprintf (stderr, "error: SCardListReaders failed, rc=%08lx\n", rc); - } - SCardReleaseContext(state->context); - return YKPIV_PCSC_ERROR; + ykpiv_rc ret = ykpiv_list_readers(state, reader_buf, &num_readers); + if(ret != YKPIV_OK) { + return ret; } for(reader_ptr = reader_buf; *reader_ptr != '\0'; reader_ptr += strlen(reader_ptr) + 1) { From 49eab7dbfa78dd2f55e3bb1e27f2401ab78db4d6 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Tue, 8 Sep 2015 15:29:10 +0200 Subject: [PATCH 4/5] drop ykpiv_sign_data2() and change ykpiv_sign_data() to not pad --- lib/ykpiv.c | 17 +++-------------- tool/yubico-piv-tool.c | 33 ++++++++++++++++++++++++--------- ykcs11/ykcs11.c | 2 +- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/lib/ykpiv.c b/lib/ykpiv.c index 6e3bc35..b42aed9 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -533,7 +533,7 @@ ykpiv_rc ykpiv_hex_decode(const char *hex_in, size_t in_len, static ykpiv_rc _general_authenticate(ykpiv_state *state, const unsigned char *sign_in, size_t in_len, unsigned char *out, size_t *out_len, - unsigned char algorithm, unsigned char key, bool decipher, bool padding) { + unsigned char algorithm, unsigned char key, bool decipher) { unsigned char indata[1024]; unsigned char *dataptr = indata; unsigned char data[1024]; @@ -636,25 +636,14 @@ ykpiv_rc ykpiv_sign_data(ykpiv_state *state, unsigned char algorithm, unsigned char key) { return _general_authenticate(state, raw_in, in_len, sign_out, out_len, - algorithm, key, false, true); + algorithm, key, false); } -ykpiv_rc ykpiv_sign_data2(ykpiv_state *state, - const unsigned char *raw_in, size_t in_len, - unsigned char *sign_out, size_t *out_len, - unsigned char algorithm, unsigned char key, - int padding) { - - return _general_authenticate(state, raw_in, in_len, sign_out, out_len, - algorithm, key, false, padding); -} - - ykpiv_rc ykpiv_decipher_data(ykpiv_state *state, const unsigned char *in, size_t in_len, unsigned char *out, size_t *out_len, unsigned char algorithm, unsigned char key) { return _general_authenticate(state, in, in_len, out, out_len, - algorithm, key, true, true); + algorithm, key, true); } ykpiv_rc ykpiv_get_version(ykpiv_state *state, char *version, size_t len) { diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index e916be1..9cebb42 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -85,6 +85,25 @@ static void print_version(ykpiv_state *state, const char *output_file_name) { } } +static bool sign_data(ykpiv_state *state, const unsigned char *in, size_t len, unsigned char *out, + size_t *out_len, unsigned char algorithm, int key) { + + unsigned char signinput[1024]; + if(YKPIV_IS_RSA(algorithm)) { + size_t padlen = algorithm == YKPIV_ALGO_RSA1024 ? 128 : 256; + if(RSA_padding_add_PKCS1_type_1(signinput, padlen, in, len) == 0) { + fprintf(stderr, "Failed adding padding.\n"); + return false; + } + in = signinput; + len = padlen; + } + if(ykpiv_sign_data(state, signinput, len, out, out_len, algorithm, key) == YKPIV_OK) { + return true; + } + return false; +} + static bool generate_key(ykpiv_state *state, const char *slot, enum enum_algorithm algorithm, const char *output_file_name, enum enum_key_format key_format, enum enum_pin_policy pin_policy, @@ -692,8 +711,7 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for { unsigned char signature[1024]; size_t sig_len = sizeof(signature); - if(ykpiv_sign_data(state, signinput, len, signature, &sig_len, algorithm, key) - != YKPIV_OK) { + if(!sign_data(state, signinput, len, signature, &sig_len, algorithm, key)) { fprintf(stderr, "Failed signing request.\n"); goto request_out; } @@ -845,8 +863,7 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo { unsigned char signature[1024]; size_t sig_len = sizeof(signature); - if(ykpiv_sign_data(state, signinput, len, signature, &sig_len, algorithm, key) - != YKPIV_OK) { + if(!sign_data(state, signinput, len, signature, &sig_len, algorithm, key)) { fprintf(stderr, "Failed signing certificate.\n"); goto selfsign_out; } @@ -1122,9 +1139,8 @@ static bool sign_file(ykpiv_state *state, const char *input, const char *output, { unsigned char buf[1024]; size_t len = sizeof(buf); - ykpiv_rc rc = ykpiv_sign_data(state, hashed, hash_len, buf, &len, algo, key); - if(rc != YKPIV_OK) { - fprintf(stderr, "failed signing file: %s\n", ykpiv_strerror(rc)); + if(!sign_data(state, hashed, hash_len, buf, &len, algo, key)) { + fprintf(stderr, "failed signing file\n"); goto out; } @@ -1373,8 +1389,7 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot, } else { enc_len = data_len; } - if(ykpiv_sign_data(state, ptr, enc_len, signature, &sig_len, algorithm, key) - != YKPIV_OK) { + if(!sign_data(state, ptr, enc_len, signature, &sig_len, algorithm, key)) { fprintf(stderr, "Failed signing test data.\n"); goto test_out; } diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index a4e6b94..9b9d0cc 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1690,7 +1690,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( dump_hex(op_info.buf, op_info.buf_len, stderr, CK_TRUE); *pulSignatureLen = sizeof(op_info.buf); - if ((r = ykpiv_sign_data2(piv_state, op_info.buf, op_info.buf_len, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key_id, 0)) != YKPIV_OK) { + if ((r = ykpiv_sign_data(piv_state, op_info.buf, op_info.buf_len, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key_id)) != YKPIV_OK) { DBG(("Sign error, %s", ykpiv_strerror(r))); return CKR_FUNCTION_FAILED; } From 30ed31124414e3751be8cacfb286cb9b6b7bec4a Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Tue, 8 Sep 2015 15:33:15 +0200 Subject: [PATCH 5/5] remove ykpiv_sign_data2() from map --- lib/ykpiv.map | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/ykpiv.map b/lib/ykpiv.map index dd817b2..c647a5a 100644 --- a/lib/ykpiv.map +++ b/lib/ykpiv.map @@ -60,5 +60,4 @@ YKPIV_1.1.0 global: ykpiv_set_mgmkey2; ykpiv_list_readers; - ykpiv_sign_data2; } YKPIV_0.1.0;