view libcommon/apdu.c @ 45:9eb5460f51a6

main tools: support both pcsc and serial back ends
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 21 Mar 2021 01:56:49 +0000
parents c9ef9e91dd8e
children
line wrap: on
line source

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

extern FILE *cpipeF, *rpipeF;

u_char sim_resp_data[258];
unsigned sim_resp_data_len, sim_resp_sw;

static void
send_cmd(cmd_apdu, cmd_apdu_len)
	u_char *cmd_apdu;
	unsigned cmd_apdu_len;
{
	unsigned n;

	for (n = 0; n < cmd_apdu_len; n++)
		fprintf(cpipeF, "%02X", cmd_apdu[n]);
	putc('\n', cpipeF);
	fflush(cpipeF);
}

static
parse_response_hex_string(input)
	char *input;
{
	char *cp;

	sim_resp_data_len = 0;
	for (cp = input; *cp; cp += 2) {
		if (!isxdigit(cp[0]) || !isxdigit(cp[1])) {
			fprintf(stderr,
			"comm error: invalid hex string from back end\n");
			return(-1);
		}
		sim_resp_data[sim_resp_data_len++] =
			(decode_hex_digit(cp[0]) << 4) |
			decode_hex_digit(cp[1]);
	}
	return(0);
}

apdu_exchange(cmd_apdu, cmd_apdu_len)
	u_char *cmd_apdu;
	unsigned cmd_apdu_len;
{
	char inbuf[518], *cp;
	u_char *sw;
	int rc;

	send_cmd(cmd_apdu, cmd_apdu_len);
	if (!fgets(inbuf, sizeof inbuf, rpipeF)) {
		fprintf(stderr, "comm error: EOF reading from back end\n");
		return(-1);
	}
	cp = index(inbuf, '\n');
	if (!cp) {
		fprintf(stderr,
			"comm error: response from back end has no newline\n");
		return(-1);
	}
	*cp = '\0';
	if (!inbuf[0]) {
		fprintf(stderr,
		"comm error: response from back end is an empty line\n");
		return(-1);
	}
	if (!isxdigit(inbuf[0]) || !isxdigit(inbuf[1]) || !isxdigit(inbuf[2])
	    || !isxdigit(inbuf[3])) {
		/* we got a back end error message */
		fprintf(stderr, "%s\n", inbuf);
		return(-1);
	}
	rc = parse_response_hex_string(inbuf);
	if (rc < 0)
		return(rc);
	sim_resp_data_len -= 2;
	sw = sim_resp_data + sim_resp_data_len;
	sim_resp_sw = (sw[0] << 8) | sw[1];
	return(0);
}