view sw/sniff-dec/command.c @ 45:b0524d1dc6ef

simtrace3-sniff-dec: implement command decoding
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 31 Aug 2023 09:32:48 +0000
parents 118a12e9483b
children 5268246520de
line wrap: on
line source

/*
 * Here we implement decoding of command APDU exchanges.
 */

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "state.h"

extern char linebuf[];
extern int lineno;
extern unsigned rx_byte;
extern int state;

static char cmd_start_timestamp[18];
static int cmd_start_line;
static char data_start_timestamp[18];
static int data_start_line;
static char sw1_timestamp[18];
static int sw1_line;

static u_char cmd_hdr[5];
static unsigned hdr_byte_count;
static unsigned data_total, data_sofar, data_thistime;
static u_char data_buf[256], sw1;

void
start_cmd_header()
{
	strcpy(cmd_start_timestamp, linebuf);
	cmd_start_line = lineno;
	cmd_hdr[0] = rx_byte;
	hdr_byte_count = 1;
	state = STATE_CMD_HDR;
}

static void
print_cmd_hdr()
{
	unsigned n;

	printf("%s line %d: CMD", cmd_start_timestamp, cmd_start_line);
	for (n = 0; n < 5; n++)
		printf(" %02X", cmd_hdr[n]);
	putchar('\n');
}

void
cmd_hdr_byte_in()
{
	cmd_hdr[hdr_byte_count++] = rx_byte;
	if (hdr_byte_count < 5)
		return;
	print_cmd_hdr();
	if ((cmd_hdr[1] & 0xF0) == 0x60 || (cmd_hdr[1] & 0xF0) == 0x90) {
		printf(" ERROR: INS byte is invalid!\n");
		state = STATE_ERROR;
		return;
	}
	if (cmd_hdr[4])
		data_total = cmd_hdr[4];
	else
		data_total = 256;
	data_sofar = 0;
	state = STATE_CMD_PROC;
}

static void
print_data()
{
	unsigned n;

	printf("%s line %d: DATA\n", data_start_timestamp, data_start_line);
	for (n = 0; n < data_sofar; n++) {
		printf(" %02X", data_buf[n]);
		if ((n & 15) == 15 || n == data_sofar - 1)
			putchar('\n');
	}
}

static void
handle_sw1()
{
	strcpy(sw1_timestamp, linebuf);
	sw1_line = lineno;
	sw1 = rx_byte;
	if (data_sofar)
		print_data();
	state = STATE_CMD_SW;
}

void
handle_ack(single)
{
	if (data_sofar >= data_total) {
		printf("%s line %d: ERROR: ACK for more data than possible\n",
			linebuf, lineno);
		state = STATE_ERROR;
		return;
	}
	if (!data_sofar) {
		strcpy(data_start_timestamp, linebuf);
		data_start_line = lineno;
	}
	if (single)
		data_thistime = 1;
	else
		data_thistime = data_total - data_sofar;
	state = STATE_CMD_DATA;
}

void
cmd_proc_byte_in()
{
	if (rx_byte == 0x60)
		return;
	if ((rx_byte & 0xF0) == 0x60 || (rx_byte & 0xF0) == 0x90) {
		handle_sw1();
		return;
	}
	if (rx_byte == cmd_hdr[1]) {
		handle_ack(0);
		return;
	}
	if (rx_byte == (cmd_hdr[1] ^ 0xFF)) {
		handle_ack(1);
		return;
	}
	printf("%s line %d: ERROR: invalid procedure byte\n", linebuf, lineno);
	state = STATE_ERROR;
}

void
cmd_data_byte_in()
{
	data_buf[data_sofar++] = rx_byte;
	data_thistime--;
	if (data_thistime)
		return;
	state = STATE_CMD_PROC;
}

void
cmd_sw2_byte_in()
{
	printf("%s line %d: SW %02X %02X\n", sw1_timestamp, sw1_line, sw1,
		rx_byte);
	state = STATE_READY_FOR_CMD;
}