keystore.h 3.75 KiB
#pragma once
#include <string.h>
#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include <../common/i2c_master.h>
#include <../common/sha1/sha1.h>
#include "../common/cardreader_interface-common.h"
#include "random.h"
#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
#define KEYSLOT_USED 0xBB
#define KEYSLOT_EMPTY 0xFF
#define KEYSLOT_DISABLED 0xDD
#define KEYSLOT_ERROR 0x00
#define KEY_MAIN_EEPROM 0xa0
#define KEY_BACKUP_EEPROM 0xa2
#define EEPROM_WRITE_PROTECT_PORT PORTD
#define EEPROM_WRITE_PROTECT_DDR DDRD
#define EEPROM_WRITE_PROTECT_MAIN (1 << 6)
#define EEPROM_WRITE_PROTECT_BACKUP (1 << 7)
typedef uint8_t HASH_HEAD[4];
/**
* Initializes the Keystore (including I²C, RNG)
*/
void keystore_init(void);
/**
* Returns the current salt of the keystore
* After 3 queries a new salt will be generated
*/
uint8_t* keystore_get_salt(void);
/**
* Looks for key matching to the given key hash
* The keyhash is SHA1(key + salt)
*/
int16_t keystore_find_key(HASH keyhash);
/**
* Generates a new salt
*/
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
*
* @param keydelta: will be filled with sizeof(KEY) random bytes.
*/
void keystore_gen_keydelta(KEY keydelta);
/**
* Updates the given keyslot with new_key = current_key XOR keydelta
* @param index number of the keyslot to update
* @param keydelta xor of old and new key. Must be sizeof(KEY) bytes long
*/
uint8_t keystore_update_slot(uint16_t index, KEY keydelta);
/**
* Calculates sha1(key + salt) for the key in the given keyslot
* @param index number of the keyslot to calculate the hash for
* @param salt salt used for hash calc
* @param keyhash result will be written here (must be sizeof(HASH) in length)
*/
uint8_t keystore_calc_keyhash(uint16_t index, SALT salt, HASH keyhash);
/**
* Returns the number of the first empty slot in the keystore
* or 0xFFFF if the keystore if full
*/
uint16_t keystore_find_empty_slot(void);
/**
* Initializes a slot with a new, random key.
* @param index number of the keyslot to initialize
* @param keyout the generated key will be written here (must be sizeof(KEY) in length)
*/
uint8_t keystore_init_slot(uint16_t index, KEY keyout);
/**
* Clears the given keyslot (sets it to unused state)
*/
uint8_t keystore_clear_slot(uint16_t index);
/**
* Disables the given keyslot (sets it from USED to DISABLED state)
*/
uint8_t keystore_disable_slot(uint16_t index);
/**
* Disables the given keyslot (sets it from DISABLED to USED state)
*/
uint8_t keystore_enable_slot(uint16_t index);
/**
* Updates the status of a keyslot.
* @param index number of the keyslot to update
* @param key_status new status of the slot: KEYSLOT_USED or KEYSLOT_EMPTY
*/
uint8_t keystore_write_slot_status(uint16_t index, uint8_t key_status);
/**
* Returns the status of a keyslot.
* @param index number of the keyslot to read
* @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);