Query for PIN/PUK/mgmt-key if not supplied on command line

Do not force a user to specify the PIN/PUK/mgmt-key on the command line.
Instead, query the user to supply them through stdin when required for
the requested operation.  This is both more user friendly and more
secure, since the secrets do not end up in the shell history and/or
visible to shoulder-surfers on the terminal.

Signed-off-by: Steffan Karger <steffan@karger.me>
This commit is contained in:
Steffan Karger
2015-07-30 23:52:11 +02:00
parent bc6a0d8465
commit 723fe2f405
3 changed files with 73 additions and 28 deletions
+24
View File
@@ -37,6 +37,7 @@
#include <windows.h> #include <windows.h>
#endif #endif
#include <openssl/evp.h>
#include <openssl/x509.h> #include <openssl/x509.h>
#include <ykpiv.h> #include <ykpiv.h>
@@ -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); *out_len = (unsigned int)i2d_X509_SIG(&digestInfo, &out);
return true; 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;
}
+1
View File
@@ -48,5 +48,6 @@ int get_object_id(enum enum_slot slot);
bool set_component_with_len(unsigned char**, const BIGNUM*, int); bool set_component_with_len(unsigned char**, const BIGNUM*, int);
bool prepare_rsa_signature(const unsigned char*, unsigned int, unsigned char*, bool prepare_rsa_signature(const unsigned char*, unsigned int, unsigned char*,
unsigned int*, int); unsigned int*, int);
bool read_pw(const char*, char*, size_t, int);
#endif #endif
+48 -28
View File
@@ -938,7 +938,15 @@ selfsign_out:
static bool verify_pin(ykpiv_state *state, const char *pin) { static bool verify_pin(ykpiv_state *state, const char *pin) {
int tries = -1; int tries = -1;
ykpiv_rc res; 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) { if(len > 8) {
fprintf(stderr, "Maximum 8 digits of PIN supported.\n"); 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 indata[0x10];
unsigned char data[0xff]; unsigned char data[0xff];
unsigned long recv_len = sizeof(data); 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; int sw;
size_t pin_len = strlen(pin); size_t pin_len;
size_t new_len = strlen(new_pin); 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) { if(pin_len > 8 || new_len > 8) {
fprintf(stderr, "Maximum 8 digits of PIN supported.\n"); 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) { if((sw >> 8) == 0x63) {
int tries = sw & 0xff; int tries = sw & 0xff;
fprintf(stderr, "Failed verifying %s code, now %d tries left before blocked.\n", 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) { } else if(sw == 0x6983) {
if(action == action_arg_changeMINUS_pin) { if(action == action_arg_changeMINUS_pin) {
fprintf(stderr, "The pin code is blocked, use the unblock-pin action to unblock it.\n"); 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; return EXIT_FAILURE;
} }
break; 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: case action_arg_pinMINUS_retries:
if(!args_info.pin_retries_arg || !args_info.puk_retries_arg) { 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", 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; return EXIT_FAILURE;
} }
break; 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_setMINUS_chuid:
case action_arg_version: case action_arg_version:
case action_arg_reset: case action_arg_reset:
@@ -1764,6 +1774,8 @@ int main(int argc, char *argv[]) {
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
for(i = 0; i < args_info.action_given; i++) { 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); action = *(args_info.action_arg + i);
if(verbosity) { if(verbosity) {
fprintf(stderr, "Now processing for action '%s'.\n", fprintf(stderr, "Now processing for action '%s'.\n",
@@ -1781,10 +1793,18 @@ int main(int argc, char *argv[]) {
} }
break; break;
case action_arg_setMINUS_mgmMINUS_key: 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]; unsigned char new_key[KEY_LEN];
size_t new_key_len = sizeof(new_key); 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"); fprintf(stderr, "Failed decoding new key!\n");
ret = EXIT_FAILURE; ret = EXIT_FAILURE;
} else if(ykpiv_set_mgmkey(state, new_key) != YKPIV_OK) { } else if(ykpiv_set_mgmkey(state, new_key) != YKPIV_OK) {