⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pkcs15-etoken.c

📁 读写Smart卡加解密接口的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * eToken PRO specific operation for PKCS15 initialization * * Copyright (C) 2002 Olaf Kirch <okir@lst.de> * * 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 */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <sys/types.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <stdarg.h>#include <opensc/opensc.h>#include <opensc/cardctl.h>#include <opensc/scrandom.h>#include "pkcs15-init.h"#include "profile.h"#ifndef MIN# define MIN(a, b)	(((a) < (b))? (a) : (b))#endifstruct tlv {	unsigned char *		base;	unsigned char *		end;	unsigned char *		current;	unsigned char *		next;};#define RSAKEY_MAX_BITS		1024#define RSAKEY_MAX_SIZE		(RSAKEY_MAX_BITS/8)struct rsakey {	struct bignum {		size_t		len;		u8		data[RSAKEY_MAX_SIZE];	}			n, d;};/* * Local functions */static int	etoken_new_file(struct sc_profile *, struct sc_card *,			unsigned int, unsigned int,			struct sc_file **);static void	error(struct sc_profile *, const char *, ...);/* Object IDs for PIN objects. * SO PIN = 0x01, SO PUK = 0x02 * each user pin is 2*N+1, each corresponding PUK is 2*N+2 */#define ETOKEN_PIN_ID(idx)	(((idx) << 1) + 0x01)#define ETOKEN_PUK_ID(idx)	(((idx) << 1) + 0x02)#define ETOKEN_MAX_PINS		0x10#define ETOKEN_KEY_ID(idx)	(0x40 + (idx))#define ETOKEN_SE_ID(idx)	(0x40 + (idx))#define ETOKEN_AC_NEVER		0xFF#define ETOKEN_ALGO_RSA			0x08#define ETOKEN_ALGO_RSA_PURE		0x0C#define ETOKEN_ALGO_RSA_SIG		0x88#define ETOKEN_ALGO_RSA_PURE_SIG	0x8C#define ETOKEN_ALGO_RSA_SIG_SHA1	0xC8#define ETOKEN_ALGO_RSA_PURE_SIG_SHA1	0xCC#define ETOKEN_SIGN_RSA			ETOKEN_ALGO_RSA_PURE_SIG#define ETOKEN_DECIPHER_RSA		ETOKEN_ALGO_RSA_PURE#define ETOKEN_ALGO_PIN			0x87static inline voidtlv_init(struct tlv *tlv, u8 *base, size_t size){	tlv->base = base;	tlv->end = base + size;	tlv->current = tlv->next = base;}static inline voidtlv_next(struct tlv *tlv, u8 tag){	assert(tlv->next + 2 < tlv->end);	tlv->current = tlv->next;	*(tlv->next++) = tag;	*(tlv->next++) = 0;}static inline voidtlv_add(struct tlv *tlv, u8 val){	assert(tlv->next + 1 < tlv->end);	*(tlv->next++) = val;	tlv->current[1]++;}static size_ttlv_len(struct tlv *tlv){	return tlv->next - tlv->base;}/* * Try to delete pkcs15 structure * This is not quite the same as erasing the whole token, but * it's close enough to be useful. */static intetoken_erase(struct sc_profile *profile, struct sc_card *card){	return sc_pkcs15init_erase_card_recursively(card, profile, -1);}/* * Initialize pin file */static intetoken_store_pin(struct sc_profile *profile, struct sc_card *card,		int pin_type, unsigned int pin_id, unsigned int puk_id,		const u8 *pin, size_t pin_len){	struct sc_pkcs15_pin_info params;	struct sc_cardctl_etoken_obj_info args;	unsigned char	buffer[256];	unsigned char	pinpadded[16];	struct tlv	tlv;	unsigned int	attempts, minlen, maxlen;	/* 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;	sc_profile_get_pin_info(profile, pin_type, &params);	attempts = params.tries_left;	minlen = params.min_length;	/* Set the profile's PIN reference */	params.reference = pin_id;	params.path = profile->df_info->file->path;	sc_profile_set_pin_info(profile, pin_type, &params);	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_id);	/* parameters */	tlv_next(&tlv, 0x85);	tlv_add(&tlv, 0x02);		/* options byte */	tlv_add(&tlv, attempts & 0xf);	/* flags byte */	tlv_add(&tlv, ETOKEN_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, 0x00);	/* ARA counter: not documented, no idea what it means */	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_id);		/* 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);	return sc_card_ctl(card, SC_CARDCTL_ETOKEN_PUT_DATA_OCI, &args);}/* * Create an empty security environment */static intetoken_create_sec_env(struct sc_profile *profile, struct sc_card *card,		unsigned int se_id, unsigned int key_id){	struct sc_cardctl_etoken_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_ETOKEN_PUT_DATA_SECI, &args);}/* * Initialize the Application DF and pin file */static intetoken_init_app(struct sc_profile *profile, struct sc_card *card,		const unsigned char *pin, size_t pin_len,		const unsigned char *puk, size_t puk_len){	struct sc_file	*df = profile->df_info->file;	int		r;	/* Create the application DF */	r = sc_pkcs15init_create_file(profile, card, df);	if (r >= 0)		r = sc_select_file(card, &df->path, NULL);	/* Create the PIN objects.	 * First, the SO pin and PUK. Don't create objects for	 * these if none specified. */	if (pin && pin_len) {		u8	puk_id = ETOKEN_AC_NEVER;		if (r >= 0 && puk && puk_len) {			puk_id = ETOKEN_PUK_ID(0);			r = etoken_store_pin(profile, card,					SC_PKCS15INIT_SO_PUK,					puk_id, ETOKEN_AC_NEVER,					puk, puk_len);		}		if (r >= 0) {			r = etoken_store_pin(profile, card,					SC_PKCS15INIT_SO_PIN,					ETOKEN_PIN_ID(0), puk_id,					pin, pin_len);		}	}	/* Create a default security environment for this DF.	 * This SE autometically becomes the current SE when the	 * DF is selected. */	if (r >= 0)		r = etoken_create_sec_env(profile, card, 0x01, 0x00);	return r;}/* * Store a PIN */static intetoken_new_pin(struct sc_profile *profile, struct sc_card *card,		struct sc_pkcs15_pin_info *info, unsigned int index,		const u8 *pin, size_t pin_len,		const u8 *puk, size_t puk_len){	struct sc_file	*df = profile->df_info->file;	unsigned int	puk_id = ETOKEN_AC_NEVER, pin_id;	int		r;	if (!pin || !pin_len)		return SC_ERROR_INVALID_ARGUMENTS;	r = sc_select_file(card, &df->path, NULL);	if (r < 0)		return r;	if (index >= ETOKEN_MAX_PINS)		return SC_ERROR_TOO_MANY_OBJECTS;	if (puk && puk_len) {		puk_id = ETOKEN_PUK_ID(index);		r = etoken_store_pin(profile, card,				SC_PKCS15INIT_USER_PUK,				puk_id, ETOKEN_AC_NEVER,				puk, puk_len);	}	if (r >= 0) {		pin_id = ETOKEN_PIN_ID(index);		r = etoken_store_pin(profile, card,				SC_PKCS15INIT_USER_PIN,				pin_id, puk_id,				pin, pin_len);		info->reference = pin_id;		info->path = df->path;	}	return r;}/* * Determine the key algorithm based on the intended usage * Note that CardOS/M4 does not support keys that can be used * for signing _and_ decipherment */#define USAGE_ANY_SIGN		(SC_PKCS15_PRKEY_USAGE_SIGN)#define USAGE_ANY_DECIPHER	(SC_PKCS15_PRKEY_USAGE_DECRYPT|\				 SC_PKCS15_PRKEY_USAGE_UNWRAP)static intetoken_key_algorithm(unsigned int usage, int *algop){	int	sign = 0, decipher = 0;	if (usage & USAGE_ANY_SIGN) {		*algop = ETOKEN_SIGN_RSA;		sign++;	}	if (usage & USAGE_ANY_DECIPHER) {		*algop = ETOKEN_DECIPHER_RSA;		decipher++;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -