diff --git a/tool/util.c b/tool/util.c index 5f17d3b..44686b1 100644 --- a/tool/util.c +++ b/tool/util.c @@ -37,6 +37,7 @@ #include #endif +#include #include #include @@ -238,3 +239,26 @@ bool prepare_rsa_signature(const unsigned char *in, unsigned int in_len, unsigne *out_len = (unsigned int)i2d_X509_SIG(&digestInfo, &out); return true; } + +bool read_pw(const char *name, char *pwbuf, size_t pwbuflen, int verify) { + #define READ_PW_PROMPT_BASE "Enter %s: " + char prompt[sizeof(READ_PW_PROMPT_BASE) + 32] = {0}; + int ret; + + if (pwbuflen < 1) { + fprintf(stderr, "Failed to read %s: buffer too small.", name); + return false; + } + + ret = snprintf(prompt, sizeof(prompt), READ_PW_PROMPT_BASE, name); + if (ret < 0 || ((unsigned int) ret) > (sizeof(prompt)-1)) { + fprintf(stderr, "Failed to read %s: snprintf failed.\n", name); + return false; + } + + if (0 != EVP_read_pw_string(pwbuf, pwbuflen-1, prompt, verify)) { + fprintf(stderr, "Retrieving %s failed.\n", name); + return false; + } + return true; +} diff --git a/tool/util.h b/tool/util.h index 8c9cc01..a3ecf8a 100644 --- a/tool/util.h +++ b/tool/util.h @@ -48,5 +48,6 @@ int get_object_id(enum enum_slot slot); bool set_component_with_len(unsigned char**, const BIGNUM*, int); bool prepare_rsa_signature(const unsigned char*, unsigned int, unsigned char*, unsigned int*, int); +bool read_pw(const char*, char*, size_t, int); #endif diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index 80a45bb..a1b278d 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -938,7 +938,15 @@ selfsign_out: static bool verify_pin(ykpiv_state *state, const char *pin) { int tries = -1; ykpiv_rc res; - int len = strlen(pin); + int len; + char pinbuf[9] = {0}; + if(!pin) { + if (!read_pw("PIN", pinbuf, sizeof(pinbuf), false)) { + return false; + } + pin = pinbuf; + } + len = strlen(pin); if(len > 8) { fprintf(stderr, "Maximum 8 digits of PIN supported.\n"); @@ -967,9 +975,28 @@ static bool change_pin(ykpiv_state *state, enum enum_action action, const char * unsigned char indata[0x10]; unsigned char data[0xff]; unsigned long recv_len = sizeof(data); + char pinbuf[9] = {0}; + char new_pinbuf[9] = {0}; + const char *name = action == action_arg_changeMINUS_pin ? "pin" : "puk"; + const char *new_name = action == action_arg_changeMINUS_pin ? "new pin" : "new puk"; int sw; - size_t pin_len = strlen(pin); - size_t new_len = strlen(new_pin); + size_t pin_len; + size_t new_len; + + if(!pin) { + if (!read_pw(name, pinbuf, sizeof(pinbuf), false)) { + return false; + } + pin = pinbuf; + } + if(!new_pin) { + if (!read_pw(new_name, new_pinbuf, sizeof(new_pinbuf), true)) { + return false; + } + new_pin = new_pinbuf; + } + pin_len = strlen(pin); + new_len = strlen(new_pin); if(pin_len > 8 || new_len > 8) { fprintf(stderr, "Maximum 8 digits of PIN supported.\n"); @@ -996,7 +1023,7 @@ static bool change_pin(ykpiv_state *state, enum enum_action action, const char * if((sw >> 8) == 0x63) { int tries = sw & 0xff; fprintf(stderr, "Failed verifying %s code, now %d tries left before blocked.\n", - action == action_arg_changeMINUS_pin ? "pin" : "puk", tries); + name, tries); } else if(sw == 0x6983) { if(action == action_arg_changeMINUS_pin) { fprintf(stderr, "The pin code is blocked, use the unblock-pin action to unblock it.\n"); @@ -1657,28 +1684,6 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } break; - case action_arg_changeMINUS_pin: - case action_arg_changeMINUS_puk: - case action_arg_unblockMINUS_pin: - if(!args_info.new_pin_arg) { - fprintf(stderr, "The '%s' action needs a new-pin (-N).\n", - cmdline_parser_action_values[action]); - return EXIT_FAILURE; - } - case action_arg_verifyMINUS_pin: - if(!args_info.pin_arg) { - fprintf(stderr, "The '%s' action needs a pin (-P).\n", - cmdline_parser_action_values[action]); - return EXIT_FAILURE; - } - break; - case action_arg_setMINUS_mgmMINUS_key: - if(!args_info.new_key_arg) { - fprintf(stderr, "The '%s' action needs the new-key (-n) argument.\n", - cmdline_parser_action_values[action]); - return EXIT_FAILURE; - } - break; case action_arg_pinMINUS_retries: if(!args_info.pin_retries_arg || !args_info.puk_retries_arg) { fprintf(stderr, "The '%s' action needs both --pin-retries and --puk-retries arguments.\n", @@ -1686,6 +1691,11 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } break; + case action_arg_changeMINUS_pin: + case action_arg_changeMINUS_puk: + case action_arg_unblockMINUS_pin: + case action_arg_verifyMINUS_pin: + case action_arg_setMINUS_mgmMINUS_key: case action_arg_setMINUS_chuid: case action_arg_version: case action_arg_reset: @@ -1764,6 +1774,8 @@ int main(int argc, char *argv[]) { OpenSSL_add_all_algorithms(); for(i = 0; i < args_info.action_given; i++) { + char new_keybuf[KEY_LEN*2+1] = {0}; + char *new_mgm_key = args_info.new_key_arg; action = *(args_info.action_arg + i); if(verbosity) { fprintf(stderr, "Now processing for action '%s'.\n", @@ -1781,10 +1793,18 @@ int main(int argc, char *argv[]) { } break; case action_arg_setMINUS_mgmMINUS_key: - if(strlen(args_info.new_key_arg) == (KEY_LEN * 2)){ + if(!new_mgm_key) { + if(!read_pw("new management key", new_keybuf, sizeof(new_keybuf), true)) { + fprintf(stderr, "Failed to read management key from stdin,\n"); + ret = EXIT_FAILURE; + break; + } + new_mgm_key = new_keybuf; + } + if(strlen(new_mgm_key) == (KEY_LEN * 2)){ unsigned char new_key[KEY_LEN]; size_t new_key_len = sizeof(new_key); - if(ykpiv_hex_decode(args_info.new_key_arg, strlen(args_info.new_key_arg), new_key, &new_key_len) != YKPIV_OK) { + if(ykpiv_hex_decode(new_mgm_key, strlen(new_mgm_key), new_key, &new_key_len) != YKPIV_OK) { fprintf(stderr, "Failed decoding new key!\n"); ret = EXIT_FAILURE; } else if(ykpiv_set_mgmkey(state, new_key) != YKPIV_OK) {