fixed out of bounds reads

Thanks to Eric Sesterhenn from X41 D-SEC GmbH
for reporting and suggesting security fixes.
static int piv_init(sc_card_t *card)
{
	int r = 0;
	piv_private_data_t * priv = NULL;
	sc_apdu_t apdu;
	unsigned long flags;
	unsigned long ext_flags;
	u8 yubico_version_buf[3];

	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);

	/* continue the matching get a lock and the priv */
	r = piv_match_card_continued(card);
	if (r != 1)  {
		sc_log(card->ctx,"piv_match_card_continued failed");
		piv_finish(card);
		/* tell sc_connect_card to try other drivers */
		LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_CARD);
	}
		
	priv = PIV_DATA(card);

	/* can not force the PIV driver to use non-PIV cards as tested in piv_card_match_continued */
	if (!priv || card->type == -1)
		LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_CARD);

	sc_log(card->ctx,
	       "Max send = %"SC_FORMAT_LEN_SIZE_T"u recv = %"SC_FORMAT_LEN_SIZE_T"u card->type = %d",
	       card->max_send_size, card->max_recv_size, card->type);
	card->cla = 0x00;
	if(card->name == NULL)
		card->name = card->driver->name;

	/*
	 * Set card_issues based on card type either set by piv_match_card or by opensc.conf
	 */

	switch(card->type) {
		case SC_CARD_TYPE_PIV_II_NEO:
		case SC_CARD_TYPE_PIV_II_YUBIKEY4:
			sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xFD, 0x00, 0x00);
			apdu.lc = 0;
			apdu.data = NULL;
			apdu.datalen = 0;
			apdu.resp = yubico_version_buf;
			apdu.resplen = sizeof(yubico_version_buf);
			apdu.le = apdu.resplen;
			r = sc_transmit_apdu(card, &apdu);
			priv->yubico_version = (yubico_version_buf[0]<<16) | (yubico_version_buf[1] <<8) | yubico_version_buf[2];
			sc_log(card->ctx, "Yubico card->type=%d, r=0x%08x version=0x%08x", card->type, r, priv->yubico_version);
			break;
	}

	/*
	 * Set card_issues flags based card->type and version numbers if available. 
	 *
	 * YubiKey NEO, Yubikey 4 and other devices with PIV applets, have compliance
	 * issues with the NIST 800-73-3 specs. The OpenSC developers do not have
	 * access to all the different devices or versions of the devices. 
	 * Vendor and user input is welcome on any compliance issues. 
	 *
	 * For the Yubico devices The assumption is also made that if a bug is 
	 * fixed in a Yubico version that means it is fixed on both NEO and Yubikey 4.
	 *
	 * The flags CI_CANT_USE_GETDATA_FOR_STATE and CI_DISCOVERY_USELESS
	 * may be set earlier or later then in the following code. 
	 */

	switch(card->type) {
		case SC_CARD_TYPE_PIV_II_NEO:
			priv->card_issues |= CI_NO_EC384
				| CI_VERIFY_630X
				| CI_OTHER_AID_LOSE_STATE
				| CI_LEAKS_FILE_NOT_FOUND
				| CI_NFC_EXPOSE_TOO_MUCH;
			if (priv->yubico_version  < 0x00040302)
				priv->card_issues |= CI_VERIFY_LC0_FAIL;
			break;

		case SC_CARD_TYPE_PIV_II_YUBIKEY4:
			priv->card_issues |=  CI_OTHER_AID_LOSE_STATE
				| CI_LEAKS_FILE_NOT_FOUND;
			if (priv->yubico_version  < 0x00040302)
				priv->card_issues |= CI_VERIFY_LC0_FAIL;
			break;

		case SC_CARD_TYPE_PIV_II_HIST:
			priv->card_issues |= 0;
			break;

		case SC_CARD_TYPE_PIV_II_GI_DE:
			priv->card_issues |= CI_VERIFY_LC0_FAIL
				| CI_PIV_AID_LOSE_STATE
				| CI_OTHER_AID_LOSE_STATE;;
			/* TODO may need more research */
			break;

		case SC_CARD_TYPE_PIV_II_GENERIC:
			priv->card_issues |= CI_VERIFY_LC0_FAIL
				| CI_OTHER_AID_LOSE_STATE;
			/* TODO may need more research */
			break;

		default:
		     priv->card_issues = 0; /* opensc.conf may have it wrong, continue anyway */
		     sc_log(card->ctx, "Unknown PIV card->type %d", card->type);
		     card->type = SC_CARD_TYPE_PIV_II_BASE;
	}
	sc_log(card->ctx, "PIV card-type=%d card_issues=0x%08x", card->type, priv->card_issues);

	priv->enumtag = piv_aids[0].enumtag;

	/* PKCS#11 may try to generate session keys, and get confused
	 * if SC_ALGORITHM_ONBOARD_KEY_GEN is present
	 * piv-tool can still do this, just don't tell PKCS#11
	 */

	 flags = SC_ALGORITHM_RSA_RAW;

	_sc_card_add_rsa_alg(card, 1024, flags, 0); /* mandatory */
	_sc_card_add_rsa_alg(card, 2048, flags, 0); /* optional */
	_sc_card_add_rsa_alg(card, 3072, flags, 0); /* optional */

	flags = SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_ECDSA_HASH_NONE;
	ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES;

	_sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL);
	if (!(priv->card_issues & CI_NO_EC384))
		_sc_card_add_ec_alg(card, 384, flags, ext_flags, NULL);

	/* TODO may turn off SC_CARD_CAP_ISO7816_PIN_INFO later */
	card->caps |= SC_CARD_CAP_RNG | SC_CARD_CAP_ISO7816_PIN_INFO;

	/*
	 * 800-73-3 cards may have a history object and/or a discovery object
	 * We want to process them now as this has information on what
	 * keys and certs the card has and how the pin might be used.
	 * If they fail, ignore it there are optional and introduced in
	 * NIST 800-73-3 and NIST 800-73-2 so some older cards may 
	 * not handle the request.
	 */
	piv_process_history(card);

	piv_process_discovery(card);

	priv->pstate=PIV_STATE_NORMAL;
	sc_unlock(card) ; /* obtained in piv_match */
	LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}

static int piv_init(sc_card_t *card)
{
	int r = 0;
	piv_private_data_t * priv = NULL;
	sc_apdu_t apdu;
	unsigned long flags;
	unsigned long ext_flags;
	u8 yubico_version_buf[3];

	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);

	/* continue the matching get a lock and the priv */
	r = piv_match_card_continued(card);
	if (r != 1)  {
		sc_log(card->ctx,"piv_match_card_continued failed");
		piv_finish(card);
		/* tell sc_connect_card to try other drivers */
		LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_CARD);
	}
		
	priv = PIV_DATA(card);

	/* can not force the PIV driver to use non-PIV cards as tested in piv_card_match_continued */
	if (!priv || card->type == -1)
		LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_CARD);

	sc_log(card->ctx,
	       "Max send = %"SC_FORMAT_LEN_SIZE_T"u recv = %"SC_FORMAT_LEN_SIZE_T"u card->type = %d",
	       card->max_send_size, card->max_recv_size, card->type);
	card->cla = 0x00;
	if(card->name == NULL)
		card->name = card->driver->name;

	/*
	 * Set card_issues based on card type either set by piv_match_card or by opensc.conf
	 */

	switch(card->type) {
		case SC_CARD_TYPE_PIV_II_NEO:
		case SC_CARD_TYPE_PIV_II_YUBIKEY4:
			sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xFD, 0x00, 0x00);
			apdu.lc = 0;
			apdu.data = NULL;
			apdu.datalen = 0;
			apdu.resp = yubico_version_buf;
			apdu.resplen = sizeof(yubico_version_buf);
			apdu.le = apdu.resplen;
			r = sc_transmit_apdu(card, &apdu);
			priv->yubico_version = (yubico_version_buf[0]<<16) | (yubico_version_buf[1] <<8) | yubico_version_buf[2];
			sc_log(card->ctx, "Yubico card->type=%d, r=0x%08x version=0x%08x", card->type, r, priv->yubico_version);
			break;
	}

	/*
	 * Set card_issues flags based card->type and version numbers if available. 
	 *
	 * YubiKey NEO, Yubikey 4 and other devices with PIV applets, have compliance
	 * issues with the NIST 800-73-3 specs. The OpenSC developers do not have
	 * access to all the different devices or versions of the devices. 
	 * Vendor and user input is welcome on any compliance issues. 
	 *
	 * For the Yubico devices The assumption is also made that if a bug is 
	 * fixed in a Yubico version that means it is fixed on both NEO and Yubikey 4.
	 *
	 * The flags CI_CANT_USE_GETDATA_FOR_STATE and CI_DISCOVERY_USELESS
	 * may be set earlier or later then in the following code. 
	 */

	switch(card->type) {
		case SC_CARD_TYPE_PIV_II_NEO:
			priv->card_issues |= CI_NO_EC384
				| CI_VERIFY_630X
				| CI_OTHER_AID_LOSE_STATE
				| CI_LEAKS_FILE_NOT_FOUND
				| CI_NFC_EXPOSE_TOO_MUCH;
			if (priv->yubico_version  < 0x00040302)
				priv->card_issues |= CI_VERIFY_LC0_FAIL;
			break;

		case SC_CARD_TYPE_PIV_II_YUBIKEY4:
			priv->card_issues |=  CI_OTHER_AID_LOSE_STATE
				| CI_LEAKS_FILE_NOT_FOUND;
			if (priv->yubico_version  < 0x00040302)
				priv->card_issues |= CI_VERIFY_LC0_FAIL;
			break;

		case SC_CARD_TYPE_PIV_II_HIST:
			priv->card_issues |= 0;
			break;

		case SC_CARD_TYPE_PIV_II_GI_DE:
			priv->card_issues |= CI_VERIFY_LC0_FAIL
				| CI_PIV_AID_LOSE_STATE
				| CI_OTHER_AID_LOSE_STATE;;
			/* TODO may need more research */
			break;

		case SC_CARD_TYPE_PIV_II_GENERIC:
			priv->card_issues |= CI_VERIFY_LC0_FAIL
				| CI_OTHER_AID_LOSE_STATE;
			/* TODO may need more research */
			break;

		default:
		     priv->card_issues = 0; /* opensc.conf may have it wrong, continue anyway */
		     sc_log(card->ctx, "Unknown PIV card->type %d", card->type);
		     card->type = SC_CARD_TYPE_PIV_II_BASE;
	}
	sc_log(card->ctx, "PIV card-type=%d card_issues=0x%08x", card->type, priv->card_issues);

	priv->enumtag = piv_aids[0].enumtag;

	/* PKCS#11 may try to generate session keys, and get confused
	 * if SC_ALGORITHM_ONBOARD_KEY_GEN is present
	 * piv-tool can still do this, just don't tell PKCS#11
	 */

	 flags = SC_ALGORITHM_RSA_RAW;

	_sc_card_add_rsa_alg(card, 1024, flags, 0); /* mandatory */
	_sc_card_add_rsa_alg(card, 2048, flags, 0); /* optional */
	_sc_card_add_rsa_alg(card, 3072, flags, 0); /* optional */

	flags = SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_ECDSA_HASH_NONE;
	ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES;

	_sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL);
	if (!(priv->card_issues & CI_NO_EC384))
		_sc_card_add_ec_alg(card, 384, flags, ext_flags, NULL);

	/* TODO may turn off SC_CARD_CAP_ISO7816_PIN_INFO later */
	card->caps |= SC_CARD_CAP_RNG | SC_CARD_CAP_ISO7816_PIN_INFO;

	/*
	 * 800-73-3 cards may have a history object and/or a discovery object
	 * We want to process them now as this has information on what
	 * keys and certs the card has and how the pin might be used.
	 * If they fail, ignore it there are optional and introduced in
	 * NIST 800-73-3 and NIST 800-73-2 so some older cards may 
	 * not handle the request.
	 */
	piv_process_history(card);

	piv_process_discovery(card);

	priv->pstate=PIV_STATE_NORMAL;
	sc_unlock(card) ; /* obtained in piv_match */
	LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
