Example #1
0
static int gemsafe_decipher(struct sc_card *card, const u8 * crgram,
	size_t crgram_len, u8 *out, size_t outlen)
{
	int r;
	struct sc_apdu apdu;
	u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
	sc_context_t *ctx = card->ctx;

	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
	if (crgram_len > 255)
		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);

	sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x80, 0x84);
	apdu.cla |= 0x80;
	apdu.resp = rbuf;
	apdu.resplen = sizeof(rbuf);
	apdu.le      = crgram_len;

	apdu.data = crgram;
	apdu.lc   = crgram_len;
	apdu.datalen = crgram_len;
	r = sc_transmit_apdu(card, &apdu);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
	if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
		int len = apdu.resplen > outlen ? outlen : apdu.resplen;

		memcpy(out, apdu.resp, len);
		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, len);
	}
	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
}
Example #2
0
static int gp_select_applet(sc_card_t *card, const u8 *aid, size_t aid_len)
{
	int	r;
	u8	buf[SC_MAX_APDU_BUFFER_SIZE];
	struct sc_context *ctx = card->ctx;
	struct sc_apdu    apdu;

	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);

	sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xa4, 0x04, 0x00);
	apdu.lc      = aid_len;
	apdu.data    = aid;
	apdu.datalen = aid_len;
	apdu.resp    = buf;
	apdu.le      = 256;
	apdu.resplen = sizeof(buf);

	r = sc_transmit_apdu(card, &apdu);
	SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
	if (r)
		SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r);

	return SC_SUCCESS;
}
static void handle_change( sc_card_t *card, int        pin1, int        pin2,
	int        do_change, u8        *newpin, int        newlen)
{
	sc_path_t p;
	sc_file_t *f;
	struct sc_apdu a;
	u8 ref;
	int i;

	printf("\n%s %s with %s: ", do_change ? "Changing" : "Unblocking", pinlist[pin1].label, pinlist[pin2].label);

	sc_format_path(pinlist[pin1].path,&p);
	if((i=sc_select_file(card,&p,&f))<0){
		printf("\nCannot select %s, %s\n", pinlist[pin1].label, sc_strerror(i));
		return;
	}
	ref=f->prop_attr[2] | (strlen(pinlist[pin1].path)>8 ? 0x80 : 0x00);

	if(do_change){
		sc_format_apdu(card, &a, SC_APDU_CASE_3_SHORT, 0x24, 0x01, ref);
		a.data=newpin, a.lc=a.datalen=newlen;
	} else {
		sc_format_apdu(card, &a, SC_APDU_CASE_1, 0x2C, 0x03, ref);
	}
	if((i=sc_transmit_apdu(card, &a))<0){
		printf("\nsc_transmit_apdu() failed, %s\n", sc_strerror(i));
		return;
	}
	if(a.sw1!=0x90 && a.sw2!=0x00){
		printf("%02X%02X\n", a.sw1, a.sw2);
		return;
	}
	printf("OK\n");
}
Example #4
0
static int ias_compute_signature(sc_card_t *card, const u8 *data,
		size_t data_len, u8 *out, size_t outlen)
{
	sc_apdu_t	apdu;
	size_t		len;
	/*
	** XXX: Ensure sufficient space exists for the card's response
	** as the caller's buffer size may not be sufficient
	*/
	u8		rbuf[SC_MAX_APDU_BUFFER_SIZE];
	sc_context_t	*ctx = card->ctx;

	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);

	if (data_len > 64) {
		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "error: input data too long: %lu bytes\n", data_len);
		return SC_ERROR_INVALID_ARGUMENTS;
	}
	
	sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x88, 0x02, 0x00);
	apdu.data = (u8 *) data;
	apdu.lc = data_len;
	apdu.datalen = data_len;
	apdu.resp = rbuf;
	apdu.resplen = sizeof(rbuf);
	apdu.le = 256;

	LOG_TEST_RET(card->ctx, sc_transmit_apdu(card, &apdu), "APDU transmit failed");
	LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "INTERNAL AUTHENTICATE failed");

	len = apdu.resplen > outlen ? outlen : apdu.resplen;
	memcpy(out, apdu.resp, len);
	
	LOG_FUNC_RETURN(card->ctx, apdu.resplen);
}
Example #5
0
static int
iso7816_update_binary(struct sc_card *card,
		unsigned int idx, const u8 *buf, size_t count, unsigned long flags)
{
	struct sc_apdu apdu;
	int r;

	if (idx > 0x7fff) {
		sc_log(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
		return SC_ERROR_OFFSET_TOO_LARGE;
	}

	sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xD6, (idx >> 8) & 0x7F, idx & 0xFF);
	apdu.lc = count;
	apdu.datalen = count;
	apdu.data = buf;

	fixup_transceive_length(card, &apdu);
	r = sc_transmit_apdu(card, &apdu);
	LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
	LOG_TEST_RET(card->ctx, r, "Card returned error");

	LOG_FUNC_RETURN(card->ctx, count);
}
Example #6
0
static int mcrd_match_card(sc_card_t * card)
{
	int i = 0, r = 0;
	sc_apdu_t apdu;

	i = _sc_match_atr(card, mcrd_atrs, &card->type);
	if (i >= 0) {
		card->name = mcrd_atrs[i].name;
		return 1;
	}

	sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xA4, 0x04, 0x00);
	apdu.lc = sizeof(EstEID_v35_AID);
	apdu.data = EstEID_v35_AID;
	apdu.datalen = sizeof(EstEID_v35_AID);
	apdu.resplen = 0;
	apdu.le = 0;
	r = sc_transmit_apdu(card, &apdu);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
	sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "SELECT AID: %02X%02X", apdu.sw1, apdu.sw2);
	if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
	        sc_log(card->ctx, "AID found");
	        card->type = SC_CARD_TYPE_MCRD_ESTEID_V30;
	        return 1;
	}
	return 0;
}
Example #7
0
static int acos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
{
	int r;
	u8  rbuf[SC_MAX_APDU_BUFFER_SIZE];
	sc_apdu_t apdu;

	if (!serial)
		return SC_ERROR_INVALID_ARGUMENTS;
	/* see if we have cached serial number */
	if (card->serialnr.len) {
		memcpy(serial, &card->serialnr, sizeof(*serial));
		return SC_SUCCESS;
	}
	/* get serial number via GET CARD DATA */
	sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xf6, 0x00, 0x00);
	apdu.cla |= 0x80;
	apdu.resp = rbuf;
	apdu.resplen = sizeof(rbuf);
	apdu.le   = 256;
	apdu.lc   = 0;
	apdu.datalen = 0;
        r = sc_transmit_apdu(card, &apdu);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
	if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
		return SC_ERROR_INTERNAL;
	/* cache serial number */
	memcpy(card->serialnr.value, apdu.resp, MIN(apdu.resplen, SC_MAX_SERIALNR));
	card->serialnr.len = MIN(apdu.resplen, SC_MAX_SERIALNR);
	/* copy and return serial number */
	memcpy(serial, &card->serialnr, sizeof(*serial));
	return SC_SUCCESS;
}
Example #8
0
static int asepcos_akn_to_fileid(sc_card_t *card, sc_cardctl_asepcos_akn2fileid_t *p)
{
	int r;
	u8  sbuf[32], rbuf[SC_MAX_APDU_BUFFER_SIZE];
	sc_apdu_t apdu;

	sbuf[0] = p->akn & 0xff;
	sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x28, 0x02, 0x01);
	apdu.cla    |= 0x80;
	apdu.resp    = rbuf;
	apdu.resplen = sizeof(rbuf);
	apdu.le      = 256;
	apdu.lc      = 1;
	apdu.datalen = 1;
	apdu.data    = sbuf;

	r = sc_transmit_apdu(card, &apdu);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");

	if (apdu.resplen != 4)
		return SC_ERROR_INTERNAL;

	p->fileid = (apdu.resp[1] << 16) | (apdu.resp[2] << 8) | apdu.resp[3];

	return SC_SUCCESS;
}
static int iso7816_update_binary(sc_card_t *card,
				 unsigned int idx, const u8 *buf,
				size_t count, unsigned long flags)
{
	sc_apdu_t apdu;
	int r;

	assert(count <= card->max_send_size);

	if (idx > 0x7fff) {
		sc_error(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
		return SC_ERROR_OFFSET_TOO_LARGE;
	}

	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD6,
		       (idx >> 8) & 0x7F, idx & 0xFF);
	apdu.lc = count;
	apdu.datalen = count;
	apdu.data = buf;

	r = sc_transmit_apdu(card, &apdu);
	SC_TEST_RET(card->ctx, r, "APDU transmit failed");
	SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),
		    "Card returned error");
	SC_FUNC_RETURN(card->ctx, 3, count);
}
static int iso7816_read_binary(sc_card_t *card,
			       unsigned int idx, u8 *buf, size_t count,
			       unsigned long flags)
{
	sc_apdu_t apdu;
	u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE];
	int r;

	if (idx > 0x7fff) {
		sc_error(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
		return SC_ERROR_OFFSET_TOO_LARGE;
	}

	assert(count <= card->max_recv_size);
	sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xB0,
		       (idx >> 8) & 0x7F, idx & 0xFF);
	apdu.le = count;
	apdu.resplen = count;
	apdu.resp = recvbuf;

	r = sc_transmit_apdu(card, &apdu);
	SC_TEST_RET(card->ctx, r, "APDU transmit failed");
	if (apdu.resplen == 0)
		SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
	memcpy(buf, recvbuf, apdu.resplen);

	SC_FUNC_RETURN(card->ctx, 3, apdu.resplen);
}
static int iso7816_update_record(sc_card_t *card, unsigned int rec_nr,
				 const u8 *buf, size_t count,
				 unsigned long flags)
{
	sc_apdu_t apdu;
	int r;

	if (count > 256) {
		sc_error(card->ctx, "Trying to send too many bytes\n");
		return SC_ERROR_INVALID_ARGUMENTS;
	}
	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xDC, rec_nr, 0);
	apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
	if (flags & SC_RECORD_BY_REC_NR)
		apdu.p2 |= 0x04;
	
	apdu.lc = count;
	apdu.datalen = count;
	apdu.data = buf;

	r = sc_transmit_apdu(card, &apdu);
	SC_TEST_RET(card->ctx, r, "APDU transmit failed");
	SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),
		    "Card returned error");
	SC_FUNC_RETURN(card->ctx, 3, count);
}
static int iso7816_read_record(sc_card_t *card,
			       unsigned int rec_nr, u8 *buf, size_t count,
			       unsigned long flags)
{
	sc_apdu_t apdu;
	u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE];
	int r;

	sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xB2, rec_nr, 0);
	apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
	if (flags & SC_RECORD_BY_REC_NR)
		apdu.p2 |= 0x04;
	
	apdu.le = count;
	apdu.resplen = count;
	apdu.resp = recvbuf;

	r = sc_transmit_apdu(card, &apdu);
	SC_TEST_RET(card->ctx, r, "APDU transmit failed");
	if (apdu.resplen == 0)
		SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
	memcpy(buf, recvbuf, apdu.resplen);

	SC_FUNC_RETURN(card->ctx, 3, apdu.resplen);
}
Example #13
0
static int cardos_match_card(sc_card_t *card)
{
    unsigned char atr[SC_MAX_ATR_SIZE];
    int i;

    i = _sc_match_atr(card, cardos_atrs, &card->type);
    if (i < 0)
        return 0;

    memcpy(atr, card->atr.value, sizeof(atr));

    /* Do not change card type for CIE! */
    if (card->type == SC_CARD_TYPE_CARDOS_CIE_V1)
        return 1;
    if (card->type == SC_CARD_TYPE_CARDOS_M4_4)
        return 1;
    if (card->type == SC_CARD_TYPE_CARDOS_M4_2) {
        int rv;
        sc_apdu_t apdu;
        u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
        /* first check some additional ATR bytes */
        if ((atr[4] != 0xff && atr[4] != 0x02) ||
                (atr[6] != 0x10 && atr[6] != 0x0a) ||
                (atr[9] != 0x55 && atr[9] != 0x58))
            return 0;
        /* get the os version using GET DATA and compare it with
         * version in the ATR */
        sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "checking cardos version ...");
        sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x82);
        apdu.resp = rbuf;
        apdu.resplen = sizeof(rbuf);
        apdu.le = 256;
        apdu.lc = 0;
        rv = sc_transmit_apdu(card, &apdu);
        SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "APDU transmit failed");
        if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
            return 0;
        if (apdu.resp[0] != atr[10] ||
                apdu.resp[1] != atr[11])
            /* version mismatch */
            return 0;
        if (atr[11] <= 0x04) {
            sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "found cardos m4.01");
            card->type = SC_CARD_TYPE_CARDOS_M4_01;
        } else if (atr[11] == 0x08) {
            sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "found cardos v4.3b");
            card->type = SC_CARD_TYPE_CARDOS_M4_3;
        } else if (atr[11] == 0x09) {
            sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "found cardos v4.2b");
            card->type = SC_CARD_TYPE_CARDOS_M4_2B;
        } else if (atr[11] >= 0x0B) {
            sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "found cardos v4.2c or higher");
            card->type = SC_CARD_TYPE_CARDOS_M4_2C;
        } else {
            sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "found cardos m4.2");
        }
    }
    return 1;
}
Example #14
0
static int autodetect_class(sc_card_t *card)
{
	int classes[] = { 0x00, 0xC0, 0xB0, 0xA0 };
	int class_count = sizeof(classes)/sizeof(int);
	u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
	sc_apdu_t apdu;
	int i, r;

	sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "autodetecting CLA byte\n");
	for (i = 0; i < class_count; i++) {
		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "trying with 0x%02X\n", classes[i]);
		memset(&apdu, 0, sizeof(apdu));
		apdu.cla = classes[i];
		apdu.cse = SC_APDU_CASE_2_SHORT;
		apdu.ins = 0xC0;
		apdu.p1 = apdu.p2 = 0;
		apdu.datalen = 0;
		apdu.lc = 0;
		apdu.le = 256;
		apdu.resp = rbuf;
		apdu.resplen = sizeof(rbuf);
		r = sc_transmit_apdu(card, &apdu);
		SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
		if (apdu.sw1 == 0x6E)
			continue;
		if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
			break;
		if (apdu.sw1 == 0x61)
			break;
		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
			"got strange SWs: 0x%02X 0x%02X\n", apdu.sw1, apdu.sw2);
		break;
	}
	if (i == class_count)
		return -1;
	card->cla = classes[i];
	sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
		"detected CLA byte as 0x%02X\n", card->cla);
	if (apdu.resplen < 2) {
		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
			"SELECT FILE returned %d bytes\n", apdu.resplen);
		return SC_SUCCESS;
	}
	if (rbuf[0] == 0x6F) {
		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
		    "SELECT FILE seems to behave according to ISO 7816-4\n");
		return SC_SUCCESS;
	}
	if (rbuf[0] == 0x00 && rbuf[1] == 0x00) {
		struct sc_card_driver *drv;
		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
		    "SELECT FILE seems to return Schlumberger 'flex stuff\n");
		drv = sc_get_cryptoflex_driver();
		card->ops->select_file = drv->ops->select_file;
		return SC_SUCCESS;
	}
	return SC_SUCCESS;
}
Example #15
0
static int entersafe_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu,
								   u8 * key, size_t keylen,
								   int cipher,int mac)
{
	 u8 *cipher_data=0,*mac_data=0;
	 size_t cipher_data_size,mac_data_size;
	 int blocks;
	 int r=SC_SUCCESS;
	u8 *sbuf=NULL;
	size_t ssize=0;

	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);

	 assert(card);
	 assert(apdu);

	 if((cipher||mac) && (!key||(keylen!=8 && keylen!=16)))
		  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);

	r = sc_apdu_get_octets(card->ctx, apdu, &sbuf, &ssize, SC_PROTO_RAW);
	if (r == SC_SUCCESS)
		sc_apdu_log(card->ctx, SC_LOG_DEBUG_VERBOSE, sbuf, ssize, 1);
	if(sbuf)
		free(sbuf);

	 if(cipher)
	 {
		  blocks=(apdu->lc+2)/8+1;
		  cipher_data_size=blocks*8;
		  cipher_data=malloc(cipher_data_size);
		  if(!cipher_data)
		  {
			   r = SC_ERROR_OUT_OF_MEMORY;
			   goto out;
		  }

		  if((r = entersafe_cipher_apdu(card,apdu,key,keylen,cipher_data,cipher_data_size))<0)
			   goto out;
	 }
	 if(mac)
	 {	 
		  mac_data_size=apdu->lc+4;
		  mac_data=malloc(mac_data_size);
		  r = entersafe_mac_apdu(card,apdu,key,keylen,mac_data,mac_data_size);
		  if(r<0)
			   goto out;
	 }
	 
	 r = sc_transmit_apdu(card,apdu);

out:
	 if(cipher_data)
		  free(cipher_data);
	 if(mac_data)
		  free(mac_data);

	 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
}
Example #16
0
int dnie_transmit_apdu(sc_card_t * card, sc_apdu_t * apdu)
{
	int res = SC_SUCCESS;
	sc_context_t *ctx;
	cwa_provider_t *provider = NULL;
	ctx=card->ctx;
	provider = GET_DNIE_PRIV_DATA(card)->cwa_provider;
	if ((provider->status.session.state == CWA_SM_ACTIVE) &&
		(card->sm_ctx.sm_mode == SM_MODE_TRANSMIT)) {
		res = sc_transmit_apdu(card, apdu);
		LOG_TEST_RET(ctx, res, "Error in dnie_wrap_apdu process");
		res = cwa_decode_response(card, provider, apdu);
		LOG_TEST_RET(ctx, res, "Error in cwa_decode_response process");
	}
	else
		res = sc_transmit_apdu(card, apdu);
	return res;
}
static void handle_nullpin(sc_card_t *card, u8 *newpin, int newlen)
{
	sc_path_t p;
	sc_file_t *f;
	struct sc_apdu a;
	u8 ref, buf[40];
	int i;

	printf("\nSetting initial PIN-value: ");

	sc_format_path(pinlist[0].path,&p);
	if((i=sc_select_file(card,&p,&f))<0){
		printf("\nCannot select %s, %s\n", pinlist[0].label, sc_strerror(i));
		return;
	}
	ref=f->prop_attr[2];

	sc_format_apdu(card, &a, SC_APDU_CASE_1, 0x20, 0x00, f->prop_attr[2]);
	if((i=sc_transmit_apdu(card, &a))<0){
		printf("sc_transmit_apdu() failed, %s\n", sc_strerror(i));
		return;
	}
	if(a.sw1!=0x69 && a.sw2!=0x85){
		printf("global PIN is not in NullPin-state (%02X%02X)\n", a.sw1, a.sw2);
		return;
	}

	sc_format_apdu(card, &a, SC_APDU_CASE_3_SHORT, 0x24, 0x00, ref);
	for(i=0;i<6;++i) buf[i]=0;
	for(i=0;i<newlen;++i) buf[6+i]=newpin[i];
	a.data=buf, a.lc=a.datalen=6+newlen;
	if((i=sc_transmit_apdu(card, &a))<0){
		printf("sc_transmit_apdu() failed, %s\n", sc_strerror(i));
		return;
	}
	if(a.sw1!=0x90 && a.sw2!=0x00){
		printf("Error %02X%02X\n", a.sw1, a.sw2);
		return;
	}
	printf("OK\n");
}
Example #18
0
static int
iasecc_sm_se_mutual_authentication(struct sc_card *card, unsigned se_num)
{
	struct sc_context *ctx = card->ctx;
#ifdef ENABLE_SM
	struct sm_info *sm_info = &card->sm_ctx.info;
	struct iasecc_se_info se;
	struct sc_crt *crt =  &sm_info->session.cwa.params.crt_at;
	struct sc_apdu apdu;
	unsigned char sbuf[0x100];
	int rv, offs;

	memset(&se, 0, sizeof(se));

	se.reference = se_num;
	crt->usage = IASECC_UQB_AT_MUTUAL_AUTHENTICATION;
	crt->tag = IASECC_CRT_TAG_AT;

	rv = iasecc_se_get_info(card, &se);
	LOG_TEST_RET(ctx, rv, "Get SE info error");

	rv = iasecc_se_get_crt(card, &se, crt);
	LOG_TEST_RET(ctx, rv, "Cannot get authentication CRT");

	if (se.df)
		sc_file_free(se.df);

	/* MSE SET Mutual Authentication SK scheme */
	offs = 0;
	sbuf[offs++] = IASECC_CRT_TAG_ALGO;
	sbuf[offs++] = 0x01;
	sbuf[offs++] = crt->algo;
	sbuf[offs++] = IASECC_CRT_TAG_REFERENCE;
	sbuf[offs++] = 0x01;
	sbuf[offs++] = crt->refs[0];

	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xC1, 0xA4);
	apdu.data = sbuf;
	apdu.datalen = offs;
	apdu.lc = offs;

	rv = sc_transmit_apdu(card, &apdu);
	LOG_TEST_RET(ctx, rv, "SM set SE mutual auth.: APDU transmit failed");
	rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
	LOG_TEST_RET(ctx, rv, "SM set SE mutual auth.: set SE error");

	LOG_FUNC_RETURN(ctx, rv);
#else
	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
	return SC_ERROR_NOT_SUPPORTED;
#endif
}
Example #19
0
static int incrypto34_list_files(sc_card_t *card, u8 *buf, size_t buflen)
{
	sc_apdu_t apdu;
	u8 rbuf[256];
	int r;
	size_t fids;
	u8 offset;

	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);

	fids=0;
	offset=0;

	/* INS 0xFC: SCAN DF*/
	/* P1 0x00: list both DF and EF */
	/* P2 0x00/0x01: first/next element */
	/* LE 0x03*/
	/*
		returns 3 bytes: FILE_TYPE + FID_HI_BYTE + FID_LO_BYTE
	*/

get_next_part:
	sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xFC, 0x00, offset?0x01:0x00);
	apdu.cla = 0xB0;
	apdu.le = 3;
	apdu.resplen = sizeof(rbuf);
	apdu.resp = rbuf;

	r = sc_transmit_apdu(card, &apdu);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
	if (apdu.sw1 == 0x6a && apdu.sw2 == 0x82)
		goto end; /* no more files */

	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "DIRECTORY command returned error");

	if (apdu.resplen >= 3
		&& ((rbuf[0] >= 0x01 && rbuf[0] <= 0x07) || 0x38 == rbuf[0])
		&& fids + 2 >= buflen)
	{
		buf[fids++] = rbuf[1];
		buf[fids++] = rbuf[2];
	}

	++offset;
	goto get_next_part;

end:
	r = fids;

	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
}
Example #20
0
static int do_apdu(int argc, char **argv)
{
	sc_apdu_t apdu;
	u8 buf[SC_MAX_APDU_BUFFER_SIZE * 2];
	u8 rbuf[SC_MAX_APDU_BUFFER_SIZE * 2];
	size_t len, i;
	int r;

	if (argc < 1)
		return usage(do_apdu);

	for (i = 0, len = 0; i < (unsigned) argc; i++)   {
		size_t len0 = strlen(argv[i]);

		if ((r = parse_string_or_hexdata(argv[i], buf + len, &len0)) < 0) {
			fprintf(stderr, "error parsing %s: %s\n", argv[i], sc_strerror(r));
			return r;
		};
		len += len0;
	}

	r = sc_bytes2apdu(card->ctx, buf, len, &apdu);
	if (r) {
		fprintf(stderr, "Invalid APDU: %s\n", sc_strerror(r));
		return 2;
	}

	apdu.resp = rbuf;
	apdu.resplen = sizeof(rbuf);

	printf("Sending: ");
	util_hex_dump(stdout, buf, len, " ");
	printf("\n");
	r = sc_transmit_apdu(card, &apdu);
	if (r) {
		fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r));
		return 1;
	}
	printf("Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2,
	       apdu.resplen ? ":" : "");
	if (apdu.resplen)
		util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1);

	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
	if (r)
		printf("Failure: %s\n", sc_strerror(r));
	else
		printf("Success!\n");

	return 0;
}
Example #21
0
static int belpic_select_file(sc_card_t *card,
			      const sc_path_t *in_path, sc_file_t **file_out)
{
	sc_context_t *ctx;
	sc_apdu_t apdu;
	u8 pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf;
	int r, pathlen;
	sc_file_t *file = NULL;

	assert(card != NULL && in_path != NULL);
	ctx = card->ctx;
	memcpy(path, in_path->value, in_path->len);
	pathlen = in_path->len;

	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x08, 0x0C);

	apdu.lc = pathlen;
	apdu.data = path;
	apdu.datalen = pathlen;

	apdu.resplen = 0;
	apdu.le = 0;

	r = sc_transmit_apdu(card, &apdu);

	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Select File APDU transmit failed");

	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
	if (r)
		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);

	next_idx = (size_t)-1;		/* reset */

	if (file_out != NULL) {
		file = sc_file_new();
		file->path = *in_path;
		if (pathlen >= 2)
			file->id = (in_path->value[pathlen - 2] << 8) | in_path->value[pathlen - 1];
		file->size = BELPIC_MAX_FILE_SIZE;
		file->shareable = 1;
		file->ef_structure = SC_FILE_EF_TRANSPARENT;
		if (pathlen == 2 && memcmp("\x3F\x00", in_path->value, 2) == 0)
			file->type = SC_FILE_TYPE_DF;
		else
			file->type = SC_FILE_TYPE_WORKING_EF;
		*file_out = file;
	}

	return 0;
}
Example #22
0
static int gemsafe_restore_security_env(struct sc_card *card, int se_num)
{
    int r;
    struct sc_apdu apdu;

    SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);

    sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0x73, (u8) se_num);

    r = sc_transmit_apdu(card, &apdu);
    SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");

    return sc_check_sw(card, apdu.sw1, apdu.sw2);
}
Example #23
0
static int cardos_have_verifyrc_package(sc_card_t *card)
{
	sc_apdu_t apdu;
        u8        rbuf[SC_MAX_APDU_BUFFER_SIZE];
        int       r;
	const u8  *p = rbuf, *q;
	size_t    len, tlen = 0, ilen = 0;

	sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x88);
	apdu.resp    = rbuf;
	apdu.resplen = sizeof(rbuf);
	apdu.lc = 0;
	apdu.le = 256;
	r = sc_transmit_apdu(card, &apdu);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");

	if ((len = apdu.resplen) == 0)
		/* looks like no package has been installed  */
		return 0;

	while (len != 0) {
		p = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen);
		if (p == NULL)
			return 0;
		if (card->type == SC_CARD_TYPE_CARDOS_M4_3)	{
			/* the verifyRC package on CardOS 4.3B use Manufacturer ID 0x01	*/
			/* and Package Number 0x07					*/
			q = sc_asn1_find_tag(card->ctx, p, tlen, 0x01, &ilen);
			if (q == NULL || ilen != 4)
				return 0;
			if (q[0] == 0x07)
				return 1;
		} else if (card->type == SC_CARD_TYPE_CARDOS_M4_4)	{
			/* the verifyRC package on CardOS 4.4 use Manufacturer ID 0x03	*/
			/* and Package Number 0x02					*/
			q = sc_asn1_find_tag(card->ctx, p, tlen, 0x03, &ilen);
			if (q == NULL || ilen != 4)
				return 0;
			if (q[0] == 0x02)
				return 1;
		} else	{
			return 0;
		}
		p   += tlen;
		len -= tlen + 2;
	}

	return 0;
}
Example #24
0
File: sm.c Project: AktivCo/OpenSC
int
sc_sm_single_transmit(struct sc_card *card, struct sc_apdu *apdu)
{
	struct sc_context *ctx  = card->ctx;
	struct sc_apdu *sm_apdu = NULL;
	int rv;

	LOG_FUNC_CALLED(ctx);
	sc_log(ctx, "SM_MODE:%X", card->sm_ctx.sm_mode);
	if (!card->sm_ctx.ops.get_sm_apdu || !card->sm_ctx.ops.free_sm_apdu)
		LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);

	/* get SM encoded APDU */
	rv = card->sm_ctx.ops.get_sm_apdu(card, apdu, &sm_apdu);
	if (rv == SC_ERROR_SM_NOT_APPLIED)   {
		/* SM wrap of this APDU is ignored by card driver.
		 * Send plain APDU to the reader driver */
		rv = card->reader->ops->transmit(card->reader, apdu);
		LOG_FUNC_RETURN(ctx, rv);
	} else {
		if (rv < 0)
			sc_sm_stop(card);
	}
	LOG_TEST_RET(ctx, rv, "get SM APDU error");

	/* check if SM APDU is still valid */
	rv = sc_check_apdu(card, sm_apdu);
	if (rv < 0)   {
		card->sm_ctx.ops.free_sm_apdu(card, apdu, &sm_apdu);
		sc_sm_stop(card);
		LOG_TEST_RET(ctx, rv, "cannot validate SM encoded APDU");
	}

	/* send APDU flagged as NO_SM */
	sm_apdu->flags |= SC_APDU_FLAGS_NO_SM | SC_APDU_FLAGS_NO_RETRY_WL;
	rv = sc_transmit_apdu(card, sm_apdu);
	if (rv < 0) {
		card->sm_ctx.ops.free_sm_apdu(card, apdu, &sm_apdu);
		sc_sm_stop(card);
		LOG_TEST_RET(ctx, rv, "unable to transmit APDU");
	}

	/* decode SM answer and free temporary SM related data */
	rv = card->sm_ctx.ops.free_sm_apdu(card, apdu, &sm_apdu);
	if (rv < 0)
		sc_sm_stop(card);

	LOG_FUNC_RETURN(ctx, rv);
}
Example #25
0
/* sets the security attribute of a EF/DF
 */
static int asepcos_set_sec_attributes(sc_card_t *card, const u8 *data, size_t len,
	int is_ef)
{
	int r, type = is_ef != 0 ? 0x02 : 0x04;
	sc_apdu_t apdu;

	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x8a, type, 0xab);
	apdu.cla    |= 0x80;
	apdu.lc      = len;
	apdu.datalen = len;
	apdu.data    = data;
	r = sc_transmit_apdu(card, &apdu);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
	return sc_check_sw(card, apdu.sw1, apdu.sw2);
}
Example #26
0
static int belpic_logout(sc_card_t *card)
{
	sc_apdu_t apdu;
	int r;

	sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0xE6, 0x00, 0x00);
	apdu.cla = 0x80;

	r = sc_transmit_apdu(card, &apdu);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "LOGOFF: APDU transmit failed");

	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "LOGOFF returned error");

	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
}
Example #27
0
/* returns the currently selected DF (if a EF is currently selected
 * it returns the path from the MF to the DF in which the EF is
 * located.
 * @param  card  sc_card_t object to use
 * @param  path  OUT path from the MF to the current DF
 * @return SC_SUCCESS on success and an error value otherwise
 */
static int asepcos_get_current_df_path(sc_card_t *card, sc_path_t *path)
{
	int r;
	sc_apdu_t apdu;
	u8        rbuf[SC_MAX_APDU_BUFFER_SIZE];

	sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x83); 
	apdu.resp    = rbuf;
	apdu.resplen = sizeof(rbuf);
	apdu.le      = 256;

	r = sc_transmit_apdu(card, &apdu);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
	if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
		return sc_check_sw(card, apdu.sw1, apdu.sw2);
	return asepcos_tlvpath_to_scpath(path, apdu.resp, apdu.resplen);
}
Example #28
0
static int
iasecc_sm_cmd(struct sc_card *card, struct sc_remote_data *rdata)
{
#define AUTH_SM_APDUS_MAX 12
#define ENCODED_APDUS_MAX_LENGTH (AUTH_SM_APDUS_MAX * (SC_MAX_APDU_BUFFER_SIZE * 2 + 64) + 32)
	struct sc_context *ctx = card->ctx;
#ifdef ENABLE_SM
	struct sm_info *sm_info = &card->sm_ctx.info;
	struct sm_cwa_session *session = &sm_info->session.cwa;
	struct sc_remote_apdu *rapdu = NULL;
	int rv;

	LOG_FUNC_CALLED(ctx);
	if (!card->sm_ctx.module.ops.get_apdus)
		LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);

	rv =  card->sm_ctx.module.ops.get_apdus(ctx, sm_info, session->mdata, session->mdata_len, rdata);
	LOG_TEST_RET(ctx, rv, "iasecc_sm_cmd() 'GET APDUS' failed");

	sc_log(ctx, "iasecc_sm_cmd() %i remote APDUs to transmit", rdata->length);
	for (rapdu = rdata->data; rapdu; rapdu = rapdu->next)   {
		struct sc_apdu *apdu = &rapdu->apdu;

		sc_log(ctx, "iasecc_sm_cmd() apdu->ins:0x%X, resplen %i", apdu->ins, apdu->resplen);
		if (!apdu->ins)
			break;
		rv = sc_transmit_apdu(card, apdu);
		if (rv < 0)   {
			sc_log(ctx, "iasecc_sm_cmd() APDU transmit error rv:%i", rv);
			break;
		}

		rv = sc_check_sw(card, apdu->sw1, apdu->sw2);
		if (rv < 0 && !(rapdu->flags & SC_REMOTE_APDU_FLAG_NOT_FATAL))   {
			sc_log(ctx, "iasecc_sm_cmd() APDU error rv:%i", rv);
			break;
		}
		sc_log(ctx, "iasecc_sm_cmd() apdu->resplen %i", apdu->resplen);
	}

	LOG_FUNC_RETURN(ctx, rv);
#else
	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
	return SC_ERROR_NOT_SUPPORTED;
#endif
}
Example #29
0
static int mcrd_set_decipher_key_ref(sc_card_t * card, int key_reference)
{
	sc_apdu_t apdu;
	sc_path_t path;
	int r;
	u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
	u8 keyref_data[SC_ESTEID_KEYREF_FILE_RECLEN];
	assert(card != NULL);

	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xB8);
	/* track the active keypair  */
	sc_format_path("0033", &path);
	r = sc_select_file(card, &path, NULL);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Can't select keyref info file 0x0033");
	r = sc_read_record(card, 1, keyref_data,
			   SC_ESTEID_KEYREF_FILE_RECLEN, SC_RECORD_BY_REC_NR);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Can't read keyref info file!");

	sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
		 "authkey reference 0x%02x%02x\n",
		 keyref_data[9], keyref_data[10]);

	sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
		 "signkey reference 0x%02x%02x\n",
		 keyref_data[19], keyref_data[20]);

	sbuf[0] = 0x83;
	sbuf[1] = 0x03;
	sbuf[2] = 0x80;
	switch (key_reference) {
	case 1:
		sbuf[3] = keyref_data[9];
		sbuf[4] = keyref_data[10];
		break;
	case 2:
		sbuf[3] = keyref_data[19];
		sbuf[4] = keyref_data[20];
		break;
	}
	apdu.data = sbuf;
	apdu.lc = 5;
	apdu.datalen = 5;
	r = sc_transmit_apdu(card, &apdu);
	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
}
Example #30
0
static int npa_logout(sc_card_t *card)
{
    struct sc_apdu apdu;

    sc_sm_stop(card);

    if (card->reader->capabilities & SC_READER_CAP_PACE_GENERIC) {
        /* If PACE is done between reader and card, SM is transparent to us as
         * it ends at the reader. With CLA=0x0C we provoque a SM error to
         * disable SM on the reader. */
        sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0xA4, 0x00, 0x00);
        apdu.cla = 0x0C;
        sc_transmit_apdu(card, &apdu);
        /* ignore result */
    }
    return sc_select_file(card, sc_get_mf_path(), NULL);
}