From 01c844905a49998d28e9930dcaea0bf3cdfbbbb6 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Tue, 17 Jun 2014 09:58:55 +0200 Subject: [PATCH] add ykpiv_set_mgmkey() --- lib/error.c | 1 + lib/ykpiv.c | 38 ++++++++++++++++++++++++++++++++++++++ lib/ykpiv.h | 5 +++++ lib/ykpiv.map | 1 + tool/yubico-piv-tool.c | 37 +------------------------------------ 5 files changed, 46 insertions(+), 36 deletions(-) diff --git a/lib/error.c b/lib/error.c index 6505ab6..4f5aa9a 100644 --- a/lib/error.c +++ b/lib/error.c @@ -48,6 +48,7 @@ static const err_t errors[] = { ERR (YKPIV_APPLET_ERROR, "No PIV applet found"), ERR (YKPIV_AUTHENTICATION_ERROR, "Error during authentication"), ERR (YKPIV_RANDOMNESS_ERROR, "Error getting randomness"), + ERR (YKPIV_GENERIC_ERROR, "Something went wrong."), }; /** diff --git a/lib/ykpiv.c b/lib/ykpiv.c index 7aa8b3b..62851aa 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -345,3 +345,41 @@ ykpiv_rc ykpiv_authenticate(ykpiv_state *state, unsigned const char *key) { } } } + +ykpiv_rc ykpiv_set_mgmkey(ykpiv_state *state, const unsigned char *new_key) { + APDU apdu; + unsigned char data[0xff]; + unsigned long recv_len = sizeof(data); + int sw; + size_t i; + ykpiv_rc res; + + for(i = 0; i < 3; i++) { + const_DES_cblock key_tmp; + memcpy(key_tmp, new_key + i * 8, 8); + if(DES_is_weak_key(&key_tmp) == 1) { + if(state->verbose) { + fprintf(stderr, "Won't set new key '"); + dump_hex(new_key + i, 8); + fprintf(stderr, "' since it's considered weak.\n"); + } + return YKPIV_GENERIC_ERROR; + } + } + + memset(apdu.raw, 0, sizeof(apdu)); + apdu.st.ins = YKPIV_INS_SET_MGMKEY; + apdu.st.p1 = 0xff; + apdu.st.p2 = 0xff; + apdu.st.lc = DES_KEY_SZ * 3 + 3; + apdu.st.data[0] = YKPIV_ALGO_3DES; + apdu.st.data[1] = YKPIV_KEY_CARDMGM; + apdu.st.data[2] = DES_KEY_SZ * 3; + memcpy(apdu.st.data + 3, new_key, DES_KEY_SZ * 3); + if((res = ykpiv_send_data(state, apdu.raw, data, &recv_len, &sw)) != YKPIV_OK) { + return res; + } else if(sw == 0x9000) { + return YKPIV_OK; + } + return YKPIV_GENERIC_ERROR; +} diff --git a/lib/ykpiv.h b/lib/ykpiv.h index 01d1136..7d8924a 100644 --- a/lib/ykpiv.h +++ b/lib/ykpiv.h @@ -47,6 +47,7 @@ extern "C" YKPIV_APPLET_ERROR = -4, YKPIV_AUTHENTICATION_ERROR = -5, YKPIV_RANDOMNESS_ERROR = -6, + YKPIV_GENERIC_ERROR = -7, } ykpiv_rc; const char *ykpiv_strerror(ykpiv_rc err); @@ -61,6 +62,7 @@ extern "C" ykpiv_rc ykpiv_send_data(ykpiv_state *state, unsigned char *apdu, unsigned char *data, unsigned long *recv_len, int *sw); ykpiv_rc ykpiv_authenticate(ykpiv_state *state, const unsigned char *key); + ykpiv_rc ykpiv_set_mgmkey(ykpiv_state *state, const unsigned char *new_key); #define YKPIV_ALGO_3DES 0x03; #define YKPIV_ALGO_RSA1024 0x06; @@ -75,6 +77,9 @@ extern "C" #define YKPIV_INS_AUTHENTICATE 0x87; + /* Yubico vendor specific instructions */ +#define YKPIV_INS_SET_MGMKEY 0xff; + #ifdef __cplusplus } #endif diff --git a/lib/ykpiv.map b/lib/ykpiv.map index a6812ce..20e07d9 100644 --- a/lib/ykpiv.map +++ b/lib/ykpiv.map @@ -36,6 +36,7 @@ global: ykpiv_send_data; ykpiv_transfer_data; ykpiv_authenticate; + ykpiv_set_mgmkey; local: *; diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index 3bbcd37..86f4d0c 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -256,41 +256,6 @@ generate_out: return ret; } -static bool set_mgm_key(ykpiv_state *state, unsigned const char *new_key) { - APDU apdu; - unsigned char data[0xff]; - unsigned long recv_len = sizeof(data); - int sw; - size_t i; - - for(i = 0; i < KEY_LEN; i += 8) { - const_DES_cblock key_tmp; - memcpy(key_tmp, new_key + i, 8); - if(DES_is_weak_key(&key_tmp) == 1) { - fprintf(stderr, "Won't set new key '"); - dump_hex(new_key + i, 8); - fprintf(stderr, "' since it's considered weak.\n"); - return false; - } - } - - memset(apdu.raw, 0, sizeof(apdu)); - apdu.st.ins = 0xff; - apdu.st.p1 = 0xff; - apdu.st.p2 = 0xff; - apdu.st.lc = KEY_LEN + 3; - apdu.st.data[0] = 0x03; /* 3-DES */ - apdu.st.data[1] = 0x9b; - apdu.st.data[2] = KEY_LEN; - memcpy(apdu.st.data + 3, new_key, KEY_LEN); - if(ykpiv_send_data(state, apdu.raw, data, &recv_len, &sw) != YKPIV_OK) { - return false; - } else if(sw == 0x9000) { - return true; - } - return false; -} - static bool reset(ykpiv_state *state) { APDU apdu; unsigned char data[0xff]; @@ -1240,7 +1205,7 @@ int main(int argc, char *argv[]) { unsigned char new_key[KEY_LEN]; if(parse_key(args_info.new_key_arg, new_key, verbosity) == false) { ret = EXIT_FAILURE; - } else if(set_mgm_key(state, new_key) == false) { + } else if(ykpiv_set_mgmkey(state, new_key) != YKPIV_OK) { ret = EXIT_FAILURE; } else { printf("Successfully set new management key.\n");