struct octet_buffer get_otp_zone (fd) { const unsigned int SIZE_OF_OTP_ZONE = 64; const unsigned int SIZE_OF_READ = 32; const unsigned int SIZE_OF_WORD = 4; const unsigned int SECOND_WORD = (SIZE_OF_READ / SIZE_OF_WORD); struct octet_buffer buf = make_buffer (SIZE_OF_OTP_ZONE); struct octet_buffer half; int x = 0; for (x=0; x < 2; x++ ) { int addr = x * SECOND_WORD; int offset = x * SIZE_OF_READ; half = read32 (fd, OTP_ZONE, addr); if (NULL != half.ptr) { memcpy (buf.ptr + offset, half.ptr, SIZE_OF_READ); free_octet_buffer (half); } else { free_octet_buffer (buf); buf.ptr = NULL; return buf; } } return buf; }
struct octet_buffer get_check_mac_meta_data (int fd, struct mac_mode_encoding m, unsigned int data_slot) { const unsigned int DLEN = 13; struct octet_buffer result = make_buffer (DLEN); uint8_t *p = result.ptr; *p++ = COMMAND_MAC; *p++ = serialize_mac_mode (m); *p++ = data_slot; *p++ = 0; struct octet_buffer otp_zone = get_otp_zone (fd); struct octet_buffer serial = get_serial_num (fd); if (!m.use_serial_num) { unsigned int len = serial.len; free_octet_buffer (serial); serial = make_buffer (len); } if (!m.use_otp_0_10) { unsigned int len = otp_zone.len; free_octet_buffer (otp_zone); otp_zone = make_buffer (len); } const unsigned int OTP_8_10_LEN = 3; const unsigned int SN_4_7_LEN = 4; const unsigned int SN_2_3_LEN = 2; if (NULL != otp_zone.ptr && NULL != serial.ptr) { memcpy (p, &otp_zone.ptr[8], OTP_8_10_LEN); p += OTP_8_10_LEN; memcpy (p, &serial.ptr[4], SN_4_7_LEN); p += SN_4_7_LEN; memcpy (p, &serial.ptr[2], SN_2_3_LEN); } else { free_octet_buffer (result); result.ptr = NULL; } free_octet_buffer (otp_zone); free_octet_buffer (serial); return result; }
struct mac_response perform_mac (int fd, struct mac_mode_encoding m, unsigned int data_slot, struct octet_buffer challenge) { const unsigned int recv_len = 32; struct mac_response rsp = {0}; rsp.status = false; uint8_t param1 = serialize_mac_mode (m); uint8_t param2[2] = {0}; assert (data_slot <= MAX_NUM_DATA_SLOTS); if (!m.use_second_32_temp_key) assert (NULL != challenge.ptr && recv_len == challenge.len); /* Param 2 is guaranteed to be less than 15 (check above) */ param2[0] = data_slot; param2[1] = 0; rsp.mac = make_buffer (recv_len); struct Command_ATSHA204 c = make_command (); set_opcode (&c, COMMAND_MAC); set_param1 (&c, param1); set_param2 (&c, param2); /* TODO Fix for situations not sending the challlenge */ set_data (&c, challenge.ptr, challenge.len); set_execution_time (&c, 0, MAC_AVG_EXEC); if (RSP_SUCCESS == process_command (fd, &c, rsp.mac.ptr, recv_len)) { /* Perform a check mac to ensure we have the data correct */ rsp.meta = get_check_mac_meta_data (fd, m, data_slot); struct check_mac_encoding cm = {0}; rsp.status = check_mac (fd, cm, data_slot, challenge, rsp.mac, rsp.meta); } else { free_octet_buffer (rsp.mac); } return rsp; }
enum DEVICE_STATE personalize (int fd, enum DEVICE_STATE goal, struct key_container *keys) { enum DEVICE_STATE state = get_device_state (fd); if (state >= goal) return state; if (set_config_zone (fd) && lock_config_zone (fd, state)) { state = STATE_INITIALIZED; assert (get_device_state (fd) == state); struct octet_buffer otp_zone; if (set_otp_zone (fd, &otp_zone)) { struct octet_buffer data_zone; if (write_keys (fd, keys, &data_zone)) { uint16_t crc = crc_data_otp_zone (data_zone, otp_zone); if (lock (fd, DATA_ZONE, crc)) { state = STATE_PERSONALIZED; assert (get_device_state (fd) == state); } free_octet_buffer (data_zone); } free_octet_buffer (otp_zone); } } return state; }
void free_key_container (struct key_container *keys) { assert (NULL != keys); unsigned int x = 0; for (x=0; x < get_max_keys (); x++) { if (NULL != keys->keys[x].ptr) free_octet_buffer (keys->keys[x]); } free (keys); }