Skip to content

Commit

Permalink
Add support for moving and deleting keys (#463)
Browse files Browse the repository at this point in the history
Add support for moving and deleting keys
  • Loading branch information
aveenismail authored Jan 23, 2024
1 parent a3f649a commit 6ef10ab
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 1 deletion.
30 changes: 30 additions & 0 deletions lib/ykpiv.c
Original file line number Diff line number Diff line change
Expand Up @@ -2205,3 +2205,33 @@ static ykpiv_rc _ykpiv_auth_deauthenticate(ykpiv_state *state) {

return res;
}

//static bool check_version(ykpiv_state *state, uint8_t major, uint8_t minor) {
// return state->ver.major > major || (state->ver.major == major && state->ver.minor >= minor);
//}

// if to_slot is set to 0xff, the key will be deleted
ykpiv_rc ykpiv_move_key(ykpiv_state *state, const unsigned char from_slot, const unsigned char to_slot) {
// if(!check_version(state, 5, 7)) {
// DBG("Move key operation available with firmware version 5.7.0 or higher");
// return YKPIV_NOT_SUPPORTED;
// }
ykpiv_rc res = YKPIV_OK;
unsigned char data[256] = {0};
unsigned long recv_len = sizeof(data);
int sw = 0;
unsigned char adpu[] = {0, YKPIV_INS_MOVE_KEY, to_slot, from_slot};
DBG("Moving key from slot %x to slot %x", from_slot, to_slot);

if ((res = _ykpiv_transfer_data(state, adpu, NULL, 0, data, &recv_len, &sw)) != YKPIV_OK) {
return res;
}
res = ykpiv_translate_sw(sw);
if (res != YKPIV_OK) {
DBG("Failed to move key");
} else {
DBG("Key moved from slot %x to %x", from_slot, to_slot);
}

return res;
}
3 changes: 3 additions & 0 deletions lib/ykpiv.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ extern "C"
ykpiv_rc ykpiv_attest(ykpiv_state *state, const unsigned char key, unsigned char *data, size_t *data_len);
ykpiv_rc ykpiv_get_metadata(ykpiv_state *state, const unsigned char key, unsigned char *data, size_t *data_len);

ykpiv_rc ykpiv_move_key(ykpiv_state *state, const unsigned char from_slot, const unsigned char to_slot);

/**
* Return the number of PIN attempts remaining before PIN is locked.
*
Expand Down Expand Up @@ -708,6 +710,7 @@ extern "C"
#define YKPIV_INS_AUTHENTICATE 0x87
#define YKPIV_INS_GET_DATA 0xcb
#define YKPIV_INS_PUT_DATA 0xdb
#define YKPIV_INS_MOVE_KEY 0xf6
#define YKPIV_INS_SELECT_APPLICATION 0xa4
#define YKPIV_INS_GET_RESPONSE_APDU 0xc0

Expand Down
10 changes: 9 additions & 1 deletion tool/cmdline.ggo
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,19 @@ option "action" a "Action to take" values="version","generate","set-mgm-key",
"request-certificate","verify-pin","change-pin","change-puk","unblock-pin",
"selfsign-certificate","delete-certificate","read-certificate","status",
"test-signature","test-decipher","list-readers","set-ccc","write-object",
"read-object","attest" enum multiple
"read-object","attest", "move-key", "delete-key" 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"
option "slot" s "What key slot to operate on" values="9a","9c","9d","9e","82","83","84","85","86","87","88","89","8a","8b","8c","8d","8e","8f","90","91","92","93","94","95","f9" enum optional
text "
9a is for PIV Authentication
9c is for Digital Signature (PIN always checked)
9d is for Key Management
9e is for Card Authentication (PIN never checked)
82-95 is for Retired Key Management
f9 is for Attestation\n"
option "to-slot" - "What slot to move an existing key to" values="9a","9c","9d","9e","82","83","84","85","86","87","88","89","8a","8b","8c","8d","8e","8f","90","91","92","93","94","95","f9" enum optional
text "
9a is for PIV Authentication
9c is for Digital Signature (PIN always checked)
Expand Down
41 changes: 41 additions & 0 deletions tool/yubico-piv-tool.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,19 @@ static EVP_PKEY* wrap_public_key(ykpiv_state *state, int algorithm, EVP_PKEY *pu
}
#endif

static bool move_key(ykpiv_state *state, int from_slot, int to_slot) {
bool ret = false;
ykpiv_rc res;

res = ykpiv_move_key(state, (uint8_t) (from_slot & 0xFF), (uint8_t) (to_slot & 0xFF));
if (res != YKPIV_OK) {
fprintf(stderr, "Failed to move key.\n");
} else {
ret = true;
}
return ret;
}

static bool generate_key(ykpiv_state *state, enum enum_slot slot,
enum enum_algorithm algorithm, const char *output_file_name,
enum enum_key_format key_format, enum enum_pin_policy pin_policy,
Expand Down Expand Up @@ -2201,13 +2214,22 @@ int main(int argc, char *argv[]) {
case action_arg_testMINUS_signature:
case action_arg_testMINUS_decipher:
case action_arg_attest:
case action_arg_deleteMINUS_key:
if(args_info.slot_arg == slot__NULL) {
fprintf(stderr, "The '%s' action needs a slot (-s) to operate on.\n",
cmdline_parser_action_values[action]);
cmdline_parser_free(&args_info);
return EXIT_FAILURE;
}
break;
case action_arg_moveMINUS_key:
if(args_info.slot_arg == slot__NULL || args_info.to_slot_arg == to_slot__NULL) {
fprintf(stderr, "The '%s' action needs both a slot (-s) to operate on and a --to-slot to move the key to.\n",
cmdline_parser_action_values[action]);
cmdline_parser_free(&args_info);
return EXIT_FAILURE;
}
break;
case action_arg_pinMINUS_retries:
if(!args_info.pin_retries_given || !args_info.puk_retries_given) {
fprintf(stderr, "The '%s' action needs both --pin-retries and --puk-retries arguments.\n",
Expand Down Expand Up @@ -2296,6 +2318,8 @@ int main(int argc, char *argv[]) {
case action_arg_setMINUS_ccc:
case action_arg_deleteMINUS_certificate:
case action_arg_writeMINUS_object:
case action_arg_moveMINUS_key:
case action_arg_deleteMINUS_key:
if(!authed) {
if(verbosity) {
fprintf(stderr, "Authenticating since action '%s' needs that.\n", cmdline_parser_action_values[action]);
Expand Down Expand Up @@ -2588,6 +2612,23 @@ int main(int argc, char *argv[]) {
ret = EXIT_FAILURE;
}
break;
case action_arg_moveMINUS_key: {
int from_slot = get_slot_hex(args_info.slot_arg);
int to_slot = get_slot_hex((enum enum_slot) args_info.to_slot_arg);
if (move_key(state, from_slot, to_slot) == false) {
ret = EXIT_FAILURE;
} else {
fprintf(stderr, "Successfully moved key.\n");
}
break;
}
case action_arg_deleteMINUS_key:
if(move_key(state, get_slot_hex(args_info.slot_arg), 0xFF) == false) {
ret = EXIT_FAILURE;
} else {
fprintf(stderr, "Successfully deleted key.\n");
}
break;
case action__NULL:
default:
fprintf(stderr, "Wrong action. %d.\n", action);
Expand Down

0 comments on commit 6ef10ab

Please sign in to comment.