diff --git a/Control/cardreader_interface.c b/Control/cardreader_interface.c index ce7310947f508a1929b8e6a3967b560aad57456b..eb09d687a3877cb875c23df79c1f246b13b98ef0 100644 --- a/Control/cardreader_interface.c +++ b/Control/cardreader_interface.c @@ -13,7 +13,7 @@ #define CARD_AUTH_APPLET_NAME "\x23\x23\x00\x42\x42" #define CARD_STATUS_SUCCESS 0x9000 - +//#define CARDREADER_DEBUG /** Card auth protcol * 1. Host -> Card: CARD_CMD_SELECT_APPLET @@ -239,7 +239,9 @@ void cardreader_auth_request(){ cardreader_card_message_t msg = {CARDREADER_MSG_TYPE_CARD}; memcpy(&msg.header, CARD_CMD_AUTH, sizeof(ISO7816_APDU_Header)); memcpy(&msg.body, keystore_get_salt(), sizeof(SALT)); +#ifdef CARDREADER_DEBUG MGMT_transmit_buffer_hex((uint8_t*)&msg, 1+sizeof(ISO7816_APDU_Header)+sizeof(SALT)); +#endif transport_send_message((uint8_t*)&msg, 1+sizeof(ISO7816_APDU_Header)+sizeof(SALT)); } @@ -248,14 +250,19 @@ uint8_t cardreader_auth_request_result(uint8_t* msg_buffer, uint8_t length){ uint8_t ret = check_card_status(msg_buffer, length, sizeof(HASH)+sizeof(SALT)); if (!ret) {cardreader_display_show_result(0); return 0;} +#ifdef CARDREADER_DEBUG printf_P(PSTR("Msg Response: ")); MGMT_transmit_buffer_hex(msg_buffer, length); printf_P(PSTR("\n")); +#endif uint8_t* keyhash = CARD_RESULT_BODY(msg_buffer); memcpy(card_challenge, (CARD_RESULT_BODY(msg_buffer) + sizeof(HASH)), sizeof(SALT)); - printf_P(PSTR("Card Response: ")); MGMT_transmit_buffer_hex(keyhash, sizeof(HASH)); + printf_P(PSTR("Card Response: ")); +#ifdef CARDREADER_DEBUG + MGMT_transmit_buffer_hex(keyhash, sizeof(HASH)); +#endif keyslot_index = keystore_find_key(keyhash); if (keyslot_index == -1){ @@ -266,8 +273,10 @@ uint8_t cardreader_auth_request_result(uint8_t* msg_buffer, uint8_t length){ } printf_P(PSTR(" Valid! (Slot: %i) :)\n"), keyslot_index); +#ifdef CARDREADER_DEBUG printf_P(PSTR("Card Challange: ")); MGMT_transmit_buffer_hex(card_challenge, sizeof(SALT)); printf_P(PSTR("\n")); +#endif cardreader_display_show_result(1); return 1; @@ -284,21 +293,27 @@ void cardreader_update_key(){ cardreader_display_write_sz_P(PSTR("Updating Key...")); keystore_gen_keydelta(new_key_delta); +#ifdef CARDREADER_DEBUG printf_P(PSTR("KeyDelta: ")); MGMT_transmit_buffer_hex(new_key_delta, sizeof(KEY)); +#endif memcpy(&msg.body, new_key_delta, sizeof(KEY)); uint8_t ret = keystore_calc_keyhash(keyslot_index, card_challenge, card_challenge_response); if (ret){ +#ifdef CARDREADER_DEBUG printf_P(PSTR("\nChallange Response: ")); MGMT_transmit_buffer_hex(card_challenge_response, sizeof(HASH)); +#endif memcpy(((uint8_t*)(&msg.body)) + sizeof(KEY), card_challenge_response, sizeof(HASH)); +#ifdef CARDREADER_DEBUG printf_P(PSTR(" ")); MGMT_transmit_buffer_hex((uint8_t*)&msg, 1+sizeof(ISO7816_APDU_Header)+ sizeof(KEY)+sizeof(HASH)); +#endif transport_send_message((uint8_t*)&msg, 1+sizeof(ISO7816_APDU_Header)+ sizeof(KEY)+sizeof(HASH)); } else { - + printf_P(PSTR("Failed to calculate key hash.\n")); } } @@ -333,6 +348,36 @@ uint8_t cardreader_update_key_result(uint8_t* msg_buffer, uint8_t length){ return 1; } +uint8_t cardreader_init_card_key(KEY key){ + cardreader_card_message_t msg = {CARDREADER_MSG_TYPE_CARD}; + memcpy(&msg.header, CARD_CMD_INIT_KEY, sizeof(ISO7816_APDU_Header)); + memcpy(&msg.body, key, sizeof(KEY)); + transport_send_message((uint8_t*)&msg, 1+sizeof(ISO7816_APDU_Header)+ sizeof(KEY)); + + uint8_t card_status[4]; + uint16_t length = transport_receive_message(&card_status, 4, 3000); + if (TRANSPORT_IS_ERROR(length)){ + printf_P(PSTR("Transport Error %04x\n"), length); + return 0; + } else { + return check_card_status(card_status, length, 0); + } +} + +uint8_t cardreader_clear_card_key(void){ + cardreader_card_message_t msg = {CARDREADER_MSG_TYPE_CARD}; + memcpy(&msg.header, CARD_CMD_CLEAR_KEY, sizeof(ISO7816_APDU_Header)); + transport_send_message((uint8_t*)&msg, 1+sizeof(ISO7816_APDU_Header)); + + uint8_t card_status[4]; + uint16_t length = transport_receive_message(&card_status, 4, 3000); + if (TRANSPORT_IS_ERROR(length)){ + printf_P(PSTR("Transport Error %04x\n"), length); + return 0; + } else { + return check_card_status(card_status, length, 0); + } +} void cardreader_timeout(void){ printf_P(PSTR(" Timeout\n")); diff --git a/Control/cardreader_interface.h b/Control/cardreader_interface.h index 0ab374d866708f4756da3468f5a2991ca9ea8f65..8843bdf5d341f2531639f2ee408d220099178243 100644 --- a/Control/cardreader_interface.h +++ b/Control/cardreader_interface.h @@ -21,3 +21,6 @@ void card_power_request_pin_changed(uint8_t power_request); void cardreader_process(void); void cardreader_tick(void); + +uint8_t cardreader_init_card_key(KEY key); +uint8_t cardreader_clear_card_key(void); \ No newline at end of file diff --git a/Control/keystore.c b/Control/keystore.c index 126dc2e861175d40280298181bd2b35667c95f35..0f26e4314e1f0860e988c1a0115bf7f5a2269d1c 100644 --- a/Control/keystore.c +++ b/Control/keystore.c @@ -4,6 +4,11 @@ void keystore_update_hashes(SALT salt); uint8_t keystore_read_key(uint16_t index, KEY key); uint8_t keystore_write_key(uint16_t index, KEY key); +uint8_t keystore_read_backup_key(uint16_t index, KEY key); +uint8_t keystore_write_backup_key(uint16_t index, KEY key); +uint8_t keystore_eeprom_read(uint8_t eeprom, uint16_t offset, uint8_t* buffer, uint8_t length); +uint8_t keystore_eeprom_write(uint8_t eeprom, uint16_t offset, uint8_t* buffer, uint8_t length); + void xor(uint8_t* src1dest, uint8_t* src2, uint8_t length); static SALT salt; @@ -34,7 +39,7 @@ int16_t keystore_find_key(HASH keyhash){ for (uint16_t index = 0; index < KEY_COUNT; index++){ //TODO: No need to compare for empty keyslots. - if (memcmp(hashes[index], keyhash, sizeof(HASH_HEAD)) == 0){ + if (memcmp(&(hashes[index]), keyhash, sizeof(HASH_HEAD)) == 0){ if (keystore_read_slot_status(index) == KEYSLOT_USED){ if (keystore_calc_keyhash(index, salt, refhash)){ if (memcmp(refhash, keyhash, sizeof(HASH)) == 0){ @@ -60,6 +65,7 @@ void keystore_gen_keydelta(KEY keydelta){ uint8_t keystore_update_slot(uint16_t index, KEY keydelta){ KEY key; if (!keystore_read_key(index, key)) return 0; + keystore_write_backup_key(index, key); //Backup old key. xor(key, keydelta, sizeof(KEY)); if (!keystore_write_key(index, key)) return 0; return 1; @@ -74,19 +80,57 @@ void keystore_update_hashes(SALT salt){ for (uint16_t index = 0; index < KEY_COUNT; index++){ wdt_reset(); //this may take a while, keep the Watchdog happy. +#ifdef KEYSTORE_DEBUG printf_P(PSTR("Debug: Slot %03i: "), index); +#endif uint8_t slot_status = keystore_read_slot_status(index); if (slot_status == KEYSLOT_USED || slot_status == KEYSLOT_DISABLED){ keystore_read_key(index, buffer); +#ifdef KEYSTORE_DEBUG printf_P(PSTR("K:")); - MGMT_transmit_buffer_hex(buffer, 20); + MGMT_transmit_buffer_hex(buffer, 8); +#endif - sha1(&fullhash, buffer, (sizeof(KEY) + sizeof(SALT))*8); - memcpy(hashes[index], fullhash, sizeof(HASH_HEAD)); + sha1(fullhash, buffer, (sizeof(KEY) + sizeof(SALT))*8); + memcpy(&(hashes[index]), fullhash, sizeof(HASH_HEAD)); +#ifdef KEYSTORE_DEBUG printf_P(PSTR(" H:")); - MGMT_transmit_buffer_hex(fullhash, sizeof(HASH_HEAD)); + MGMT_transmit_buffer_hex(&hashes[index], sizeof(HASH_HEAD)); + + if (slot_status == KEYSLOT_DISABLED){ + printf_P(PSTR(" (Disabled)")); + } + + printf_P(PSTR("\n")); + + } else if (slot_status == KEYSLOT_EMPTY){ + printf_P(PSTR("Empty\n")); + } else if (slot_status == KEYSLOT_ERROR){ + printf_P(PSTR("Read Error\n")); + } else { + printf_P(PSTR("Unknown (%02x)\n"), slot_status); +#endif + } + } +} + +void keystore_list(void){ + KEY key; + for (uint16_t index = 0; index < KEY_COUNT; index++){ + wdt_reset(); //this may take a while, keep the Watchdog happy. + + printf_P(PSTR("Slot %03i: "), index); + uint8_t slot_status = keystore_read_slot_status(index); + if (slot_status == KEYSLOT_USED || slot_status == KEYSLOT_DISABLED){ + keystore_read_key(index, key); + + printf_P(PSTR("K:")); + MGMT_transmit_buffer_hex(key, 8); + + printf_P(PSTR(" H:")); + MGMT_transmit_buffer_hex(&(hashes[index]), sizeof(HASH_HEAD)); if (slot_status == KEYSLOT_DISABLED){ printf_P(PSTR(" (Disabled)")); @@ -109,13 +153,31 @@ uint8_t keystore_calc_keyhash(uint16_t index, SALT salt, HASH keyhash){ uint8_t ret = keystore_read_key(index, buffer); if (ret == 0) return 0; memcpy(buffer+sizeof(KEY), salt, sizeof(SALT)); +#ifdef KEYSTORE_DEBUG printf_P(PSTR("sha1(")); MGMT_transmit_buffer_hex(buffer, sizeof(SALT)+sizeof(KEY)); printf_P(PSTR(")\n")); +#endif sha1(keyhash, buffer, (sizeof(SALT)+sizeof(KEY))*8); return 1; } +uint8_t keystore_restore_slot(uint16_t index){ + KEY key; + if (!keystore_read_backup_key(index, key)) return 0; + if (!keystore_write_key(index, key)) return 0; + + uint8_t status; + if (!keystore_eeprom_read(KEY_BACKUP_EEPROM, EEPROM_TABLE_OFFSET + index, &status, sizeof(uint8_t))) return 0; + if (!keystore_eeprom_write(KEY_MAIN_EEPROM, EEPROM_TABLE_OFFSET + index, &status, sizeof(uint8_t))) return 0; + + if (status == KEYSLOT_USED || status == KEYSLOT_DISABLED){ + keystore_calc_keyhash(index, salt, &hashes[index]); + } + + return 1; +} + void xor(uint8_t* src1dest, uint8_t* src2, uint8_t length){ for (uint8_t i = 0; i < length; i++){ src1dest[i] ^= src2[i]; @@ -151,7 +213,7 @@ uint8_t keystore_init_slot(uint16_t index, KEY keyout){ HASH fullhash; sha1(&fullhash, keyout, (sizeof(KEY) + sizeof(SALT))*8); - memcpy(hashes[index], fullhash, sizeof(HASH_HEAD)); + memcpy(&hashes[index], fullhash, sizeof(HASH_HEAD)); return 1; } @@ -173,7 +235,7 @@ uint8_t keystore_init_slot_empty(uint16_t index, KEY keyout){ HASH fullhash; sha1(&fullhash, keyout, (sizeof(KEY) + sizeof(SALT))*8); - memcpy(hashes[index], fullhash, sizeof(HASH_HEAD)); + memcpy(&hashes[index], fullhash, sizeof(HASH_HEAD)); return 1; } @@ -200,59 +262,62 @@ uint8_t keystore_enable_slot(uint16_t index){ uint8_t keystore_read_slot_status(uint16_t index){ uint8_t key_status = KEYSLOT_ERROR; - uint8_t ret; - i2c_master_set_speed(I2C_BITRATE_REG_1M); - ret = i2c_master_read(KEY_MAIN_EEPROM, EEPROM_TABLE_OFFSET + index, sizeof(uint16_t), &key_status, sizeof(uint8_t)); - if (ret != I2C_SUCCESS) { - printf_P(PSTR("Key status read error %02x, retry...\n"), ret); - ret = i2c_master_read(KEY_MAIN_EEPROM, EEPROM_TABLE_OFFSET + index, sizeof(uint16_t), &key_status, sizeof(uint8_t)); - if (ret != I2C_SUCCESS) printf_P(PSTR("Key status read error %02x (fatal)\n"), ret); - } - return (ret == I2C_SUCCESS) ? key_status : KEYSLOT_ERROR; + uint8_t ret = keystore_eeprom_read(KEY_MAIN_EEPROM, EEPROM_TABLE_OFFSET + index, &key_status, sizeof(uint8_t)); + return (ret == 1) ? key_status : KEYSLOT_ERROR; } uint8_t keystore_write_slot_status(uint16_t index, uint8_t key_status){ - uint8_t ret; - EEPROM_WRITE_PROTECT_PORT &= ~EEPROM_WRITE_PROTECT_MAIN; - - i2c_master_set_speed(I2C_BITRATE_REG_1M); - ret = i2c_master_write(KEY_MAIN_EEPROM, EEPROM_TABLE_OFFSET + index, sizeof(uint16_t), &key_status, sizeof(uint8_t)); - if (ret != 0) { - printf_P(PSTR("Key status write error %02x, retry...\n"), ret); - ret = i2c_master_write(KEY_MAIN_EEPROM, EEPROM_TABLE_OFFSET + index, sizeof(uint16_t), &key_status, 1); - if (ret != I2C_SUCCESS) printf_P(PSTR("Key status write error %02x (fatal)\n"), ret); - } - - EEPROM_WRITE_PROTECT_PORT |= EEPROM_WRITE_PROTECT_MAIN; - - return (ret == I2C_SUCCESS) ? key_status : KEYSLOT_ERROR; + uint8_t ret = keystore_eeprom_write(KEY_MAIN_EEPROM, EEPROM_TABLE_OFFSET + index, &key_status, sizeof(uint8_t)); + keystore_eeprom_write(KEY_BACKUP_EEPROM, EEPROM_TABLE_OFFSET + index, &key_status, sizeof(uint8_t)); + return (ret == 1) ? key_status : KEYSLOT_ERROR; } uint8_t keystore_read_key(uint16_t index, KEY key){ + return keystore_eeprom_read(KEY_MAIN_EEPROM, EEPROM_KEY_OFFSET + (index * sizeof(KEY)), key, sizeof(KEY)); +} +uint8_t keystore_read_backup_key(uint16_t index, KEY key){ + return keystore_eeprom_read(KEY_BACKUP_EEPROM, EEPROM_KEY_OFFSET + (index * sizeof(KEY)), key, sizeof(KEY)); +} + +uint8_t keystore_write_key(uint16_t index, KEY key){ + return keystore_eeprom_write(KEY_MAIN_EEPROM, EEPROM_KEY_OFFSET + (index * sizeof(KEY)), key, sizeof(KEY)); +} +uint8_t keystore_write_backup_key(uint16_t index, KEY key){ + return keystore_eeprom_write(KEY_BACKUP_EEPROM, EEPROM_KEY_OFFSET + (index * sizeof(KEY)), key, sizeof(KEY)); +} + +uint8_t keystore_eeprom_read(uint8_t eeprom, uint16_t offset, uint8_t* buffer, uint8_t length){ uint8_t ret; i2c_master_set_speed(I2C_BITRATE_REG_1M); - ret = i2c_master_read(KEY_MAIN_EEPROM, EEPROM_KEY_OFFSET + (index * sizeof(KEY)), sizeof(uint16_t), key, sizeof(KEY)); + ret = i2c_master_read(eeprom, offset, sizeof(uint16_t), buffer, length); if (ret != I2C_SUCCESS) { - printf_P(PSTR("Key read error %02x, retry...\n"), ret); - ret = i2c_master_read(KEY_MAIN_EEPROM, EEPROM_KEY_OFFSET + (index * sizeof(KEY)), sizeof(uint16_t), key, sizeof(KEY)); - if (ret != I2C_SUCCESS) printf_P(PSTR("Key read error %02x (fatal)\n"), ret); + printf_P(PSTR("EEPROM %02x read error %02x, retry...\n"), eeprom, ret); + ret = i2c_master_read(eeprom, offset, sizeof(uint16_t), buffer, length); + if (ret != I2C_SUCCESS) printf_P(PSTR("EEPROM %02x read error %02x (fatal)\n"), eeprom, ret); } return (ret == I2C_SUCCESS); } -uint8_t keystore_write_key(uint16_t index, KEY key){ +uint8_t keystore_eeprom_write(uint8_t eeprom, uint16_t offset, uint8_t* buffer, uint8_t length){ uint8_t ret; - EEPROM_WRITE_PROTECT_PORT &= ~EEPROM_WRITE_PROTECT_MAIN; + uint8_t write_protect_flag; + if (eeprom == KEY_MAIN_EEPROM){ + write_protect_flag = EEPROM_WRITE_PROTECT_MAIN; + } else { + write_protect_flag = EEPROM_WRITE_PROTECT_BACKUP; + } + + EEPROM_WRITE_PROTECT_PORT &= ~write_protect_flag; i2c_master_set_speed(I2C_BITRATE_REG_1M); - ret = i2c_master_write(KEY_MAIN_EEPROM, EEPROM_KEY_OFFSET + (index * sizeof(KEY)), sizeof(uint16_t), key, sizeof(KEY)); + ret = i2c_master_write(eeprom, offset, sizeof(uint16_t), buffer, length); if (ret != I2C_SUCCESS) { - printf_P(PSTR("Key write error %02x, retry...\n"), ret); - ret = i2c_master_write(KEY_MAIN_EEPROM, EEPROM_KEY_OFFSET + (index * sizeof(KEY)), sizeof(uint16_t), key, sizeof(KEY)); - if (ret != I2C_SUCCESS) printf_P(PSTR("Key write error %02x (fatal)\n"), ret); + printf_P(PSTR("EEPROM %02x Write error %02x, retry...\n"), eeprom, ret); + ret = i2c_master_write(eeprom, offset, sizeof(uint16_t), buffer, length); + if (ret != I2C_SUCCESS) printf_P(PSTR("EEPROM %02x write error %02x (fatal)\n"), eeprom, ret); } - EEPROM_WRITE_PROTECT_PORT |= EEPROM_WRITE_PROTECT_MAIN; + EEPROM_WRITE_PROTECT_PORT |= write_protect_flag; return (ret == I2C_SUCCESS); -} +} \ No newline at end of file diff --git a/Control/keystore.h b/Control/keystore.h index 0cf8e3ddd7b1ac7c4fa6c317472690ff5a6c6f3c..3ef2ec3f948df31f516f8cd6c240c2a4c5645e75 100644 --- a/Control/keystore.h +++ b/Control/keystore.h @@ -14,6 +14,8 @@ #define KEY_COUNT 32 //eeprom has space for 1008 keys, but RAM for hash precalc is limited. +// #define KEYSTORE_DEBUG + #define EEPROM_TABLE_OFFSET 0 //table listing used and unused keyslots #define EEPROM_KEY_OFFSET 1024 //keys start here @@ -54,6 +56,11 @@ int16_t keystore_find_key(HASH keyhash); */ void keystore_update_salt(void); +/** + * List keystore content (stubs) + */ +void keystore_list(void); + /** * Generates a byte string of sizeof(KEY) length which is used to update * the card key. new_key = current_key XOR keydelta @@ -119,3 +126,17 @@ uint8_t keystore_write_slot_status(uint16_t index, uint8_t key_status); * @return KEYSLOT_USED, KEYSLOT_EMPTY or KEYSLOT_ERROR */ uint8_t keystore_read_slot_status(uint16_t index); + +/** + * Reads the key of a keyslot + * @param index number of the keyslot to read + * @param key buffer for the key + * @return 1 if read successful, 0 otherwise. + */ +uint8_t keystore_read_key(uint16_t index, KEY key); + +/** + * Restores the key slot content to the last successful auth key + * @param index number of the keyslot to restore + */ +uint8_t keystore_restore_slot(uint16_t index); \ No newline at end of file diff --git a/Control/shell/shell.c b/Control/shell/shell.c index ca78d02debc4a9643d190bc25ad251d319324542..cedda17b1a2a8a688c6d4ee1b5b196afbc86485f 100644 --- a/Control/shell/shell.c +++ b/Control/shell/shell.c @@ -2,6 +2,7 @@ #include "../ds1307.h" #include "../log.h" #include "../door.h" +#include "../cardreader_interface.h" #define SHELL_LOGIN_PROMPT "\nMezu Login: " @@ -18,6 +19,7 @@ void cmd_keyslot_clear(readline_parsed_cmd_t* cmd); void cmd_keyslot_list(readline_parsed_cmd_t* cmd); void cmd_keyslot_disable(readline_parsed_cmd_t* cmd); void cmd_keyslot_enable(readline_parsed_cmd_t* cmd); +void cmd_keyslot_restore(readline_parsed_cmd_t* cmd); void cmd_lock(readline_parsed_cmd_t* cmd); void cmd_unlock(readline_parsed_cmd_t* cmd); void cmd_logout(readline_parsed_cmd_t* cmd); @@ -26,23 +28,28 @@ void cmd_keyslot_alarm_stop(readline_parsed_cmd_t* cmd); void cmd_reset(readline_parsed_cmd_t* cmd); void cmd_date(readline_parsed_cmd_t* cmd); void cmd_show_log(readline_parsed_cmd_t* cmd); - -readline_supported_cmd_t readline_commands[] = {{"help" , 0, 0, cmd_help}, - {"logout" , 0, 0, cmd_logout}, - {"exit" , 0, 0, cmd_logout}, - {"passwd" , 0, 1, cmd_passwd}, - {"unlock" , 0, 0, cmd_unlock}, - {"lock" , 0, 1, cmd_lock}, - {"status" , 0, 0, cmd_status}, - {"reset" , 0, 0, cmd_reset}, - {"initks" , 0, 2, cmd_keyslot_init}, - {"clearks" , 1, 1, cmd_keyslot_clear}, - {"disableks", 1, 1, cmd_keyslot_disable}, - {"enableks" , 1, 1, cmd_keyslot_enable}, - {"urusai" , 0, 0, cmd_keyslot_alarm_stop}, - {"ls" , 0, 0, cmd_keyslot_list}, - {"date" , 0, 2, cmd_date}, - {"log" , 0, 0, cmd_show_log}, +void cmd_card_init_key(readline_parsed_cmd_t* cmd); +void cmd_card_clear_key(readline_parsed_cmd_t* cmd); + +readline_supported_cmd_t readline_commands[] = {{"help" , 0, 0, cmd_help}, + {"logout" , 0, 0, cmd_logout}, + {"exit" , 0, 0, cmd_logout}, + {"passwd" , 0, 1, cmd_passwd}, + {"unlock" , 0, 0, cmd_unlock}, + {"lock" , 0, 1, cmd_lock}, + {"status" , 0, 0, cmd_status}, + {"reset" , 0, 0, cmd_reset}, + {"initks" , 0, 2, cmd_keyslot_init}, + {"clearks" , 1, 1, cmd_keyslot_clear}, + {"disableks" , 1, 1, cmd_keyslot_disable}, + {"enableks" , 1, 1, cmd_keyslot_enable}, + {"restoreks" , 1, 1, cmd_keyslot_restore}, + {"urusai" , 0, 0, cmd_keyslot_alarm_stop}, + {"ls" , 0, 0, cmd_keyslot_list}, + {"date" , 0, 2, cmd_date}, + {"log" , 0, 0, cmd_show_log}, + {"initcardkey" , 1, 1, cmd_card_init_key}, + {"clearcardkey", 0, 0, cmd_card_clear_key}, {0,0,0,0}}; #define SHELL_STATE_READ_USER 0 @@ -143,11 +150,19 @@ unlock - Unlock door\n\ status - Display system status\n\ reset - Reset controller\n\ passwd [user] - Change user password\n\ -initks x - Initialize keyslot x with a new random key\n\ -clearks x - Clear keyslot x (delete key)\n\ +initks x - Initialize keyslot x with a new random key\n\ +clearks x - Clear keyslot x (delete key)\n\ +disableks x - Disable keyslot x (but keep key)\n\ +enableks x - Enable a disabled keyslot\n\ +restoreks x - Restore keyslot content from last valid key\n\ ls - List keyslots (only key stubs)\n\ +initcardkey x - Program the key of keyslot x on the card in the cardreader\n\ +clearcardkey - Clear the key of the card currently in the cardreader\n\ +date [dd-mm-yy] hh:mm:ss - Set system date and time\n\ +log - Show systemlog\n\ urusai - Turn Alarm off\n\ -logout - Exit shell\n")); +logout - Exit shell\n\ +quit - Exit shell\n")); } void cmd_keyslot_init(readline_parsed_cmd_t* cmd){ @@ -200,7 +215,7 @@ void cmd_keyslot_init(readline_parsed_cmd_t* cmd){ KEY new_key; if (keystore_init_slot(keyslot_index, new_key)){ - printf_P(PSTR("Success\nNew key: ")); + printf_P(PSTR("Slot %i initialized\nNew key: "), keyslot_index); MGMT_transmit_buffer_hex(new_key, sizeof(KEY)); printf_P(PSTR("\n")); } else { @@ -212,9 +227,9 @@ void cmd_keyslot_disable(readline_parsed_cmd_t* cmd){ uint16_t keyslot_index; char* endptr; keyslot_index = strtol(cmd->args[0], &endptr, 10); - printf_P(PSTR("Keyslot '%s' %i\n"), cmd->args[0], keyslot_index); +// printf_P(PSTR("Keyslot '%s' %i\n"), cmd->args[0], keyslot_index); if (*endptr != 0){//number parsing didn't reach the end of the string - printf_P(PSTR("Usage: clearks index\n")); + printf_P(PSTR("Usage: disableks index\n")); } if (keystore_disable_slot(keyslot_index)){ @@ -227,9 +242,9 @@ void cmd_keyslot_enable(readline_parsed_cmd_t* cmd){ uint16_t keyslot_index; char* endptr; keyslot_index = strtol(cmd->args[0], &endptr, 10); - printf_P(PSTR("Keyslot '%s' %i\n"), cmd->args[0], keyslot_index); +// printf_P(PSTR("Keyslot '%s' %i\n"), cmd->args[0], keyslot_index); if (*endptr != 0){//number parsing didn't reach the end of the string - printf_P(PSTR("Usage: clearks index\n")); + printf_P(PSTR("Usage: enableks index\n")); } if (keystore_enable_slot(keyslot_index)){ @@ -243,7 +258,7 @@ void cmd_keyslot_clear(readline_parsed_cmd_t* cmd){ uint16_t keyslot_index; char* endptr; keyslot_index = strtol(cmd->args[0], &endptr, 10); - printf_P(PSTR("Keyslot '%s' %i\n"), cmd->args[0], keyslot_index); +// printf_P(PSTR("Keyslot '%s' %i\n"), cmd->args[0], keyslot_index); if (*endptr != 0){//number parsing didn't reach the end of the string printf_P(PSTR("Usage: clearks index\n")); } @@ -255,38 +270,25 @@ void cmd_keyslot_clear(readline_parsed_cmd_t* cmd){ } } +void cmd_keyslot_restore(readline_parsed_cmd_t* cmd){ + uint16_t keyslot_index; + char* endptr; + keyslot_index = strtol(cmd->args[0], &endptr, 10); +// printf_P(PSTR("Keyslot '%s' %i\n"), cmd->args[0], keyslot_index); + if (*endptr != 0){//number parsing didn't reach the end of the string + printf_P(PSTR("Usage: restoreks index\n")); + } + + if (keystore_restore_slot(keyslot_index)){ + printf_P(PSTR("OK\n")); + } else { + printf_P(PSTR("Failed\n")); + } + +} -extern HASH hashes[KEY_COUNT]; void cmd_keyslot_list(readline_parsed_cmd_t* cmd){ - KEY key; - for (uint16_t index = 0; index < KEY_COUNT; index++){ - wdt_reset(); //this may take a while, keep the Watchdog happy. - - printf_P(PSTR("Slot %03i: "), index); - uint8_t slot_status = keystore_read_slot_status(index); - if (slot_status == KEYSLOT_USED || slot_status == KEYSLOT_DISABLED){ - keystore_read_key(index, key); - - printf_P(PSTR("K:")); - MGMT_transmit_buffer_hex(key, 20); - - printf_P(PSTR(" H:")); - MGMT_transmit_buffer_hex(hashes[index], sizeof(HASH_HEAD)); - - if (slot_status == KEYSLOT_DISABLED){ - printf_P(PSTR(" (Disabled)")); - } - - printf_P(PSTR("\n")); - - } else if (slot_status == KEYSLOT_EMPTY){ - printf_P(PSTR("Empty\n")); - } else if (slot_status == KEYSLOT_ERROR){ - printf_P(PSTR("Read Error\n")); - } else { - printf_P(PSTR("Unknown (%02x)\n"), slot_status); - } - } + keystore_list(); } void cmd_lock(readline_parsed_cmd_t* cmd){ @@ -391,6 +393,34 @@ void cmd_date(readline_parsed_cmd_t* cmd){ printf_P(PSTR("\n")); } +void cmd_card_init_key(readline_parsed_cmd_t* cmd){ + uint16_t keyslot_index; + char* endptr; + keyslot_index = strtol(cmd->args[0], &endptr, 10); + if (*endptr != 0){//number parsing didn't reach the end of the string + printf_P(PSTR("Usage: initcardkey index\n")); + } + + uint8_t slot_status = keystore_read_slot_status(keyslot_index); + if (slot_status == KEYSLOT_USED || slot_status == KEYSLOT_DISABLED){ + printf_P(PSTR("Programming Keyslot %i -> Card:"),keyslot_index); + + KEY key; + if (keystore_read_key(keyslot_index, key)){ + cardreader_init_card_key(key); + } else { + printf_P(PSTR("Key read error\n")); + } + } else { + printf_P(PSTR("Invalid keyslot %i\n"), keyslot_index); + } +} +void cmd_card_clear_key(readline_parsed_cmd_t* cmd){ + printf_P(PSTR("Clearing card key:")); + cardreader_clear_card_key(); +} + + uint8_t shell_find_user(char* username){ uint8_t i = 0; while (users[i]){