Example #1
0
/*
 * Create an empty security environment
 */
static int
incrypto34_create_sec_env(struct sc_profile *profile, struct sc_card *card,
		unsigned int se_id, unsigned int key_id)
{
	struct sc_cardctl_incrypto34_obj_info args;
	struct tlv	tlv;
	unsigned char	buffer[64];

	tlv_init(&tlv, buffer, sizeof(buffer));
	tlv_next(&tlv, 0x83);
	tlv_add(&tlv, se_id);

	tlv_next(&tlv, 0x86);
	tlv_add(&tlv, 0);
	tlv_add(&tlv, 0);

	tlv_next(&tlv, 0x8f);
	tlv_add(&tlv, key_id);
	tlv_add(&tlv, key_id);
	tlv_add(&tlv, key_id);
	tlv_add(&tlv, key_id);
	tlv_add(&tlv, key_id);
	tlv_add(&tlv, key_id);

	args.data = buffer;
	args.len = tlv_len(&tlv);
	return sc_card_ctl(card, SC_CARDCTL_INCRYPTO34_PUT_DATA_SECI, &args);
}
Example #2
0
/*
 * Create an empty security environment
 */
static int
cardos_create_sec_env(struct sc_profile *profile, sc_card_t *card,
		unsigned int se_id, unsigned int key_id)
{
	struct sc_cardctl_cardos_obj_info args;
	struct tlv	tlv;
	unsigned char	buffer[64];
	int		r;

	tlv_init(&tlv, buffer, sizeof(buffer));
	tlv_next(&tlv, 0x83);
	tlv_add(&tlv, se_id);

	tlv_next(&tlv, 0x86);
	tlv_add(&tlv, 0);
	tlv_add(&tlv, 0);

	tlv_next(&tlv, 0x8f);
	tlv_add(&tlv, key_id);
	tlv_add(&tlv, key_id);
	tlv_add(&tlv, key_id);
	tlv_add(&tlv, key_id);
	tlv_add(&tlv, key_id);
	tlv_add(&tlv, key_id);

	args.data = buffer;
	args.len = tlv_len(&tlv);

	/* ensure we are in the correct lifecycle */
	r = sc_pkcs15init_set_lifecycle(card, SC_CARDCTRL_LIFECYCLE_ADMIN);
	if (r < 0 && r != SC_ERROR_NOT_SUPPORTED)
		return r;

	return sc_card_ctl(card, SC_CARDCTL_CARDOS_PUT_DATA_SECI, &args);
}
Example #3
0
File: tlv.c Project: dtaht/hnetd
void *
tlv_nest_start(struct tlv_buf *buf, int id, int len)
{
	unsigned long offset = attr_to_offset(buf, buf->head);
	buf->head = tlv_add(buf, tlv_next(buf->head), id, len);
	return (void *) offset;
}
Example #4
0
File: tlv.c Project: dtaht/hnetd
int
tlv_buf_init(struct tlv_buf *buf, int id)
{
	if (!buf->grow)
		buf->grow = tlv_buffer_grow;

	buf->head = buf->buf;
	if (tlv_add(buf, buf->buf, id, 0) == NULL)
		return -ENOMEM;

	return 0;
}
Example #5
0
File: tlv.c Project: dtaht/hnetd
struct tlv_attr *
tlv_new(struct tlv_buf *buf, int id, int payload)
{
	struct tlv_attr *attr;

	attr = tlv_add(buf, tlv_next(buf->head), id, payload);
	if (!attr)
		return NULL;

	tlv_set_raw_len(buf->head, tlv_pad_len(buf->head) + tlv_pad_len(attr));
	return attr;
}
Example #6
0
File: tlv.c Project: dtaht/hnetd
struct tlv_attr *
tlv_put_raw(struct tlv_buf *buf, const void *ptr, int len)
{
	struct tlv_attr *attr;

	if (len < (int)sizeof(struct tlv_attr) || !ptr)
		return NULL;

	attr = tlv_add(buf, tlv_next(buf->head), 0, len - sizeof(struct tlv_attr));
	tlv_set_raw_len(buf->head, tlv_pad_len(buf->head) + len);
	memcpy(attr, ptr, len);
	return attr;
}
Example #7
0
static int
cardos_store_key_component(sc_card_t *card,
		int algorithm,
		unsigned int key_id, unsigned int pin_id,
		unsigned int num,
		const u8 *data, size_t len,
		int last, int use_prefix)
{
	struct sc_cardctl_cardos_obj_info args;
	struct tlv	tlv;
	unsigned char	buffer[256];
#ifdef SET_SM_BYTES
	unsigned int	n;
#endif
	int		r;

	/* Initialize the TLV encoder */
	tlv_init(&tlv, buffer, sizeof(buffer));

	/* Object address */
	tlv_next(&tlv, 0x83);
	tlv_add(&tlv, 0x20|num);	/* PSO, n-th component */
	tlv_add(&tlv, key_id);

	/* Object parameters */
	tlv_next(&tlv, 0x85);
	tlv_add(&tlv, CARDOS_KEY_OPTIONS|(last? 0x00 : 0x20));
	tlv_add(&tlv, CARDOS_KEY_FLAGS);
	tlv_add(&tlv, algorithm);
	tlv_add(&tlv, 0x00);
	tlv_add(&tlv, 0xFF);	/* use count */
	tlv_add(&tlv, 0xFF);	/* DEK (whatever this is) */
	tlv_add(&tlv, 0x00);
	tlv_add(&tlv, 0x00);

	/* AC bytes */
	tlv_next(&tlv, 0x86);
	tlv_add(&tlv, pin_id);	/* AC USE */
	tlv_add(&tlv, pin_id);	/* AC CHANGE */
	tlv_add(&tlv, pin_id);	/* UNKNOWN */
	tlv_add(&tlv, 0);	/* rfu */
	tlv_add(&tlv, 0);	/* rfu */
	tlv_add(&tlv, 0);	/* rfu */
#if 0
	tlv_add(&tlv, pin_id);	/* AC GENKEY */
#else
	tlv_add(&tlv, 0);
#endif

#ifdef SET_SM_BYTES
	/* it shouldn't be necessary to set the default value */
	/* SM bytes */
	tlv_next(&tlv, 0x8B);
	for (n = 0; n < 16; n++)
		tlv_add(&tlv, 0xFF);
#endif

	/* key component */
	tlv_next(&tlv, 0x8f);
	if (use_prefix != 0) {
		tlv_add(&tlv, len+1);
		tlv_add(&tlv, 0);
	}
	while (len--)
		tlv_add(&tlv, *data++);

	args.data = buffer;
	args.len = tlv_len(&tlv);

	/* ensure we are in the correct lifecycle */
	r = sc_pkcs15init_set_lifecycle(card, SC_CARDCTRL_LIFECYCLE_ADMIN);
	if (r < 0 && r != SC_ERROR_NOT_SUPPORTED)
		return r;

	return sc_card_ctl(card, SC_CARDCTL_CARDOS_PUT_DATA_OCI, &args);
}
Example #8
0
/*
 * Store a PIN or PUK
 */
static int
cardos_store_pin(sc_profile_t *profile, sc_card_t *card,
		sc_pkcs15_pin_info_t *pin_info, int puk_id,
		const u8 *pin, size_t pin_len)
{
	struct sc_cardctl_cardos_obj_info args;
	unsigned char	buffer[256];
	unsigned char	pinpadded[256];
	struct tlv	tlv;
	unsigned int	attempts, minlen, maxlen;
	int		r;

	/* We need to do padding because pkcs15-lib.c does it.
	 * Would be nice to have a flag in the profile that says
	 * "no padding required". */
	maxlen = MIN(profile->pin_maxlen, sizeof(pinpadded));
	if (pin_len > maxlen) {
		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "invalid pin length: %u (max %u)\n",
		         pin_len, maxlen);
		return SC_ERROR_INVALID_ARGUMENTS;
	}
	memcpy(pinpadded, pin, pin_len);
	while (pin_len < maxlen)
		pinpadded[pin_len++] = profile->pin_pad_char;
	pin = pinpadded;

	attempts = pin_info->tries_left;
	minlen = pin_info->min_length;

	tlv_init(&tlv, buffer, sizeof(buffer));

	/* object address: class, id */
	tlv_next(&tlv, 0x83);
	tlv_add(&tlv, 0x00);		/* class byte: usage TEST, k=0 */
	tlv_add(&tlv, pin_info->reference);

	/* parameters */
	tlv_next(&tlv, 0x85);
	tlv_add(&tlv, 0x02);		/* options byte */
	tlv_add(&tlv, attempts & 0xf);	/* flags byte */
	tlv_add(&tlv, CARDOS_ALGO_PIN);	/* algorithm = pin-test */
	tlv_add(&tlv, attempts & 0xf);	/* errcount = attempts */

	/* usecount: not documented, but seems to work like this:
	 *  -	value of 0xff means pin can be presented any number
	 *	of times
	 *  -	anything less: max # of times before BS object is blocked.
	 */
	tlv_add(&tlv, 0xff);

	/* DEK: not documented, no idea what it means */
	tlv_add(&tlv, 0xff);

	/* ARA counter: number of times the test object can be used before
	 *              another verification is required (~ user consent)
	 *              (0x00 unlimited usage)
	 */
	tlv_add(&tlv, 0x00);

	tlv_add(&tlv, minlen);			/* minlen */

	/* AC conditions */
	tlv_next(&tlv, 0x86);
	tlv_add(&tlv, 0x00);			/* use: always */
	tlv_add(&tlv, pin_info->reference);	/* change: PIN */
	tlv_add(&tlv, puk_id);			/* unblock: PUK */

	/* data: PIN */
	tlv_next(&tlv, 0x8f);
	while (pin_len--)
		tlv_add(&tlv, *pin++);

	args.data = buffer;
	args.len = tlv_len(&tlv);

	/* ensure we are in the correct lifecycle */
	r = sc_pkcs15init_set_lifecycle(card, SC_CARDCTRL_LIFECYCLE_ADMIN);
	if (r < 0 && r != SC_ERROR_NOT_SUPPORTED)
		return r;

	return sc_card_ctl(card, SC_CARDCTL_CARDOS_PUT_DATA_OCI, &args);
}
Example #9
0
static int
incrypto34_store_key_component(struct sc_card *card,
		int algorithm,
		unsigned int key_id, unsigned int pin_id,
		unsigned int num,
		const u8 *data, size_t len,
		int last)
{
	int	r;
	struct sc_cardctl_incrypto34_obj_info args;
	struct tlv	tlv;
	unsigned char	buffer[256];
	unsigned int	n;

	/* Initialize the TLV encoder */
	tlv_init(&tlv, buffer, sizeof(buffer));

	/* Object address */
	tlv_next(&tlv, 0x83);
	tlv_add(&tlv, 0x20|num);	/* PSO, n-th component */
	tlv_add(&tlv, key_id);

	/* Object parameters */
	tlv_next(&tlv, 0x85);
	tlv_add(&tlv, INCRYPTO34_KEY_OPTIONS|(last? 0x00 : 0x20));
	tlv_add(&tlv, INCRYPTO34_KEY_FLAGS);
	tlv_add(&tlv, algorithm);
	tlv_add(&tlv, 0x0F);    /* Error Counter*/
	tlv_add(&tlv, 0xFF);	/* use count */
	tlv_add(&tlv, 0xFF);	/* RFU */
	tlv_add(&tlv, 0x00);    /* RFU */
	tlv_add(&tlv, 0x00);    /* RFU */

	/* AC bytes */
	tlv_next(&tlv, 0x86);
	tlv_add(&tlv, pin_id);	/* AC USE */
	tlv_add(&tlv, pin_id);	/* AC CHANGE */
	tlv_add(&tlv, 0xFF);	/* AC_UNBLOCK */
	tlv_add(&tlv, 0xFF);	/* RFU */
	tlv_add(&tlv, 0xFF);    /* RFU */
	tlv_add(&tlv, 0xFF);	/* RFU */
	tlv_add(&tlv, 0);  /* AC_GENKEY */
	tlv_add(&tlv, 0xFF);    /* RFU */
	tlv_add(&tlv, 0xFF);    /* RFU */
	tlv_add(&tlv, 0xFF);    /* RFU */

	/* SM bytes */
	tlv_next(&tlv, 0x8B);
	for (n = 0; n < 16; n++)
		tlv_add(&tlv, 0xFF);

	/* key component */
	tlv_next(&tlv, 0x8f);
	tlv_add(&tlv, len+1);
	tlv_add(&tlv, 0);
	while (len--)
		tlv_add(&tlv, *data++);


	args.data = buffer;
	args.len = tlv_len(&tlv);
	r = sc_card_ctl(card, SC_CARDCTL_INCRYPTO34_PUT_DATA_OCI, &args);
	return r;
}
Example #10
0
/*
 * Store a PIN or PUK
 */
static int
incrypto34_store_pin(sc_profile_t *profile, sc_card_t *card,
		sc_pkcs15_auth_info_t *auth_info, int puk_id,
		const u8 *pin, size_t pin_len)
{
	struct sc_cardctl_incrypto34_obj_info args;
	unsigned char	buffer[256];
	unsigned char	pinpadded[16];
	struct tlv	tlv;
	unsigned int	attempts, minlen, maxlen;

	if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
		return SC_ERROR_OBJECT_NOT_VALID;

	/* We need to do padding because pkcs15-lib.c does it.
	 * Would be nice to have a flag in the profile that says
	 * "no padding required". */
	maxlen = MIN(profile->pin_maxlen, sizeof(pinpadded));
	if (pin_len > maxlen)
		pin_len = maxlen;
	memcpy(pinpadded, pin, pin_len);
	while (pin_len < maxlen)
		pinpadded[pin_len++] = profile->pin_pad_char;
	pin = pinpadded;

	attempts = auth_info->tries_left;
	minlen = auth_info->attrs.pin.min_length;

	tlv_init(&tlv, buffer, sizeof(buffer));

	/* object address: class, id */
	tlv_next(&tlv, 0x83);
	tlv_add(&tlv, 0x00);		/* class byte: usage TEST, k=0 */
	tlv_add(&tlv, auth_info->attrs.pin.reference);

	/* parameters */
	tlv_next(&tlv, 0x85);
	tlv_add(&tlv, 0x02);		/* options byte */
	tlv_add(&tlv, attempts & 0xf);	/* flags byte */
	tlv_add(&tlv, INCRYPTO34_ALGO_PIN);	/* algorithm = pin-test */
	tlv_add(&tlv, attempts & 0xf);	/* errcount = attempts */

	/* usecount: not documented, but seems to work like this:
	 *  -	value of 0xff means pin can be presented any number
	 *	of times
	 *  -	anything less: max # of times before BS object is blocked.
	 */
	tlv_add(&tlv, 0xff);

	/* DEK: RFU */
	tlv_add(&tlv, 0x00);

	/* ARA counter: the number of times the PIN can be used before the he must be verified
	again (0 or ff for unlimited usage) */
	tlv_add(&tlv, 0x00);

	tlv_add(&tlv, minlen);			/* minlen */

	/* AC conditions */
	tlv_next(&tlv, 0x86);
	tlv_add(&tlv, 0x00);			/* use: always */
	tlv_add(&tlv, auth_info->attrs.pin.reference);	/* change: PIN */
	tlv_add(&tlv, puk_id);			/* unblock: PUK */
	tlv_add(&tlv, 0xFF);			/*RFU*/
	tlv_add(&tlv, 0xFF);			/*RFU*/
	tlv_add(&tlv, 0xFF);			/*RFU*/
	tlv_add(&tlv, 0xFF);			/*unused on pins*/
	tlv_add(&tlv, 0xFF);			/*RFU*/
	tlv_add(&tlv, 0xFF);			/*RFU*/
	tlv_add(&tlv, 0xFF);			/*RFU*/


	/* data: PIN */
	tlv_next(&tlv, 0x8f);
	while (pin_len--)
		tlv_add(&tlv, *pin++);

	args.data = buffer;
	args.len = tlv_len(&tlv);

	return sc_card_ctl(card, SC_CARDCTL_INCRYPTO34_PUT_DATA_OCI, &args);
}