<commit_before>/*
 * card-myeid.c
 *
 * Copyright (C) 2008-2009 Aventra Ltd.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#if HAVE_CONFIG_H
#include "config.h"
#endif

#include <string.h>
#include <stdlib.h>

#include "internal.h"
#include "asn1.h"
#include "cardctl.h"
#include "types.h"

#define LOAD_KEY_MODULUS		0x80
#define LOAD_KEY_PUBLIC_EXPONENT	0x81
#define LOAD_KEY_PRIME_P		0x83
#define LOAD_KEY_PRIME_Q		0x84
#define LOAD_KEY_DP1			0x85
#define LOAD_KEY_DQ1			0x86
#define LOAD_KEY_INVQ			0x87
#define LOAD_KEY_MODE_EC_PRIV		0x87
#define LOAD_KEY_MODE_EC_PUB		0x86

#define LOAD_KEY_EC_PRIVATE	0x97
#define LOAD_KEY_EC_PUBLIC	0x96

#define LOAD_KEY_SYMMETRIC	0xa0

#define MYEID_STATE_CREATION	0x01
#define MYEID_STATE_ACTIVATED	0x07

#define MYEID_CARD_NAME_MAX_LEN		100

/* The following flags define the features supported by the card currently in use.
  They are used in 'card_supported_features' field in myeid_card_caps struct */
#define MYEID_CARD_CAP_RSA		0x01
#define MYEID_CARD_CAP_3DES		0x02
#define MYEID_CARD_CAP_AES		0x04
#define MYEID_CARD_CAP_ECC		0x08
#define MYEID_CARD_CAP_GRIDPIN		0x10
#define MYEID_CARD_CAP_PIV_EMU		0x20

#define MYEID_MAX_APDU_DATA_LEN		0xFF
#define MYEID_MAX_RSA_KEY_LEN		2048

static const char *myeid_card_name = "MyEID";
static char card_name_buf[MYEID_CARD_NAME_MAX_LEN];

static struct sc_card_operations myeid_ops;
static struct sc_card_driver myeid_drv = {
	"MyEID cards with PKCS#15 applet",
	"myeid",
	&myeid_ops,
	NULL,
	0,
	NULL
};

static const char *myeid_atrs[] = {
	"fd00:c2b6:b24b:be67:2827:688d:e6a1:6a3b:45:4D:79:45:49:44:65",
	"3B:F5:18:00:00:81:31:FE:45:4D:79:45:49:44:9A",
	"fdf8:f53e:61e4::18:44:78",
	"fc00:db20:35b:7399::5:4D:79:45:49:44:4C",
	"3B:F5:96:00:00:80:31:FE:45:4D:79:45:49:44:15", /* Infineon's chip */
	"3B:F5:96:00:00:81:31:FE:45:4D:79:45:49:44:14",
	NULL
};

typedef struct myeid_private_data {
	int card_state;

	unsigned short change_counter;
	/* the driver sets sec_env pointer in myeid_set_security_env and
	 it is used immediately in myeid_decipher to differentiate between RSA decryption and
	 ECDH key agreement. Note that this pointer is usually not valid
	 after this pair of calls and must not be used elsewhere. */
	const struct sc_security_env* sec_env;
} myeid_private_data_t;

typedef struct myeid_card_caps {
	unsigned char card_caps_ver;
	unsigned short card_supported_features;
	unsigned short max_rsa_key_length;
	unsigned short max_des_key_length;
	unsigned short max_aes_key_length;
	unsigned short max_ecc_key_length;
} myeid_card_caps_t;

static struct myeid_supported_ec_curves {
	char *curve_name;
	struct sc_object_id curve_oid;
	size_t size;
} ec_curves[] = {
	{"secp192r1", {{1, 2, 840, 10045, 3, 1, 1, -1}},192},
	/* {"secp224r1", {{1, 3, 132, 0, 33, -1}},		224}, */
	{"secp256r1", {{1, 2, 840, 10045, 3, 1, 7, -1}},256},
	{"secp384r1", {{1, 3, 132, 0, 34, -1}},		384},
	{"secp521r1", {{1, 3, 132, 0, 35, -1}},		521},
	{NULL, {{-1}}, 0},
};

static int myeid_get_info(struct sc_card *card, u8 *rbuf, size_t buflen);
static int myeid_get_card_caps(struct sc_card *card, myeid_card_caps_t* card_caps);

static int myeid_match_card(struct sc_card *card)
{
	int i, match = -1;

	for (i = 0; myeid_atrs[i] != NULL; i++)
	{
		u8 defatr[SC_MAX_ATR_SIZE];
		size_t len = sizeof(defatr);
		const char *atrp = myeid_atrs[i];

		if (sc_hex_to_bin(atrp, defatr, &len))
			continue;
		if (len != card->atr.len)
			continue;
		if (memcmp(card->atr.value, defatr, len) != 0)
			continue;
		match = i;
		break;
	}
	if (match == -1)
		return 0;

	return 1;
}

static int
myeid_select_aid(struct sc_card *card, struct sc_aid *aid, unsigned char *out, size_t *out_len)
{
	struct sc_apdu apdu;
	unsigned char apdu_resp[SC_MAX_APDU_BUFFER_SIZE];
	int rv;

	/* Select application (deselect previously selected application) */
	sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0x04, 0x00);
	apdu.lc = aid->len;
	apdu.data = aid->value;
	apdu.datalen = aid->len;
	apdu.resplen = sizeof(apdu_resp);
	apdu.resp = apdu_resp;<commit_msg>MyEID: detect card from ATR historical data instead of full ATR<commit_after>/*
 * card-myeid.c
 *
 * Copyright (C) 2008-2009 Aventra Ltd.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#if HAVE_CONFIG_H
#include "config.h"
#endif

#include <string.h>
#include <stdlib.h>

#include "internal.h"
#include "asn1.h"
#include "cardctl.h"
#include "types.h"

#define LOAD_KEY_MODULUS		0x80
#define LOAD_KEY_PUBLIC_EXPONENT	0x81
#define LOAD_KEY_PRIME_P		0x83
#define LOAD_KEY_PRIME_Q		0x84
#define LOAD_KEY_DP1			0x85
#define LOAD_KEY_DQ1			0x86
#define LOAD_KEY_INVQ			0x87
#define LOAD_KEY_MODE_EC_PRIV		0x87
#define LOAD_KEY_MODE_EC_PUB		0x86

#define LOAD_KEY_EC_PRIVATE	0x97
#define LOAD_KEY_EC_PUBLIC	0x96

#define LOAD_KEY_SYMMETRIC	0xa0

#define MYEID_STATE_CREATION	0x01
#define MYEID_STATE_ACTIVATED	0x07

#define MYEID_CARD_NAME_MAX_LEN		100

/* The following flags define the features supported by the card currently in use.
  They are used in 'card_supported_features' field in myeid_card_caps struct */
#define MYEID_CARD_CAP_RSA		0x01
#define MYEID_CARD_CAP_3DES		0x02
#define MYEID_CARD_CAP_AES		0x04
#define MYEID_CARD_CAP_ECC		0x08
#define MYEID_CARD_CAP_GRIDPIN		0x10
#define MYEID_CARD_CAP_PIV_EMU		0x20

#define MYEID_MAX_APDU_DATA_LEN		0xFF
#define MYEID_MAX_RSA_KEY_LEN		2048

static const char *myeid_card_name = "MyEID";
static char card_name_buf[MYEID_CARD_NAME_MAX_LEN];

static struct sc_card_operations myeid_ops;
static struct sc_card_driver myeid_drv = {
	"MyEID cards with PKCS#15 applet",
	"myeid",
	&myeid_ops,
	NULL,
	0,
	NULL
};

typedef struct myeid_private_data {
	int card_state;

	unsigned short change_counter;
	/* the driver sets sec_env pointer in myeid_set_security_env and
	 it is used immediately in myeid_decipher to differentiate between RSA decryption and
	 ECDH key agreement. Note that this pointer is usually not valid
	 after this pair of calls and must not be used elsewhere. */
	const struct sc_security_env* sec_env;
} myeid_private_data_t;

typedef struct myeid_card_caps {
	unsigned char card_caps_ver;
	unsigned short card_supported_features;
	unsigned short max_rsa_key_length;
	unsigned short max_des_key_length;
	unsigned short max_aes_key_length;
	unsigned short max_ecc_key_length;
} myeid_card_caps_t;

static struct myeid_supported_ec_curves {
	char *curve_name;
	struct sc_object_id curve_oid;
	size_t size;
} ec_curves[] = {
	{"secp192r1", {{1, 2, 840, 10045, 3, 1, 1, -1}},192},
	/* {"secp224r1", {{1, 3, 132, 0, 33, -1}},		224}, */
	{"secp256r1", {{1, 2, 840, 10045, 3, 1, 7, -1}},256},
	{"secp384r1", {{1, 3, 132, 0, 34, -1}},		384},
	{"secp521r1", {{1, 3, 132, 0, 35, -1}},		521},
	{NULL, {{-1}}, 0},
};

static int myeid_get_info(struct sc_card *card, u8 *rbuf, size_t buflen);
static int myeid_get_card_caps(struct sc_card *card, myeid_card_caps_t* card_caps);

static int myeid_match_card(struct sc_card *card)
{
	/* Normally the historical bytes are exactly "MyEID", but there might
	 * be some historic units which have a small prefix byte sequence. */
	if (card->reader->atr_info.hist_bytes_len >= 5 &&
	    !memcmp(&card->reader->atr_info.hist_bytes[card->reader->atr_info.hist_bytes_len - 5], "MyEID", 5)) {
		card->type = SC_CARD_TYPE_MYEID_GENERIC;
		return 1;
	}
	return 0;
}

static int
myeid_select_aid(struct sc_card *card, struct sc_aid *aid, unsigned char *out, size_t *out_len)
{
	struct sc_apdu apdu;
	unsigned char apdu_resp[SC_MAX_APDU_BUFFER_SIZE];
	int rv;

	/* Select application (deselect previously selected application) */
	sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0x04, 0x00);
	apdu.lc = aid->len;
	apdu.data = aid->value;
	apdu.datalen = aid->len;
	apdu.resplen = sizeof(apdu_resp);
	apdu.resp = apdu_resp;
{'fraction_non_alphanumeric': 0.09904886848146933, 'fraction_numerical': 0.06023832950694217, 'mean_word_length': 5.050264550264551, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1045723', 'n_tokens_mistral': 4018, 'n_tokens_neox': 3667, 'n_words': 1008}