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

📄 pkcs15-gpk.c

📁 读写Smart卡加解密接口的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * GPK 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 "pkcs15-init.h"#include "profile.h"#define GPK_MAX_PINS		8#define GPK_FTYPE_SECRET_CODE	0x21#define GPK_FTYPE_PUBLIC_KEY	0x2C/* * Key components (for storing private keys) */struct pkcomp {	unsigned char	tag;	u8 *		data;	unsigned int	size;};struct pkpart {	struct pkcomp	components[7];	unsigned int	count;	unsigned int	size;};struct pkdata {	unsigned int	algo;	unsigned int	usage;	struct pkpart _public, _private;	unsigned int	bits, bytes;};/* * Local functions */static int	gpk_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);static int	gpk_new_file(struct sc_profile *, struct sc_card *,			unsigned int, unsigned int,			struct sc_file **);static int	gpk_encode_rsa_key(struct sc_profile *,			struct sc_pkcs15_prkey_rsa *, struct pkdata *,			struct sc_pkcs15_prkey_info *);static int	gpk_encode_dsa_key(struct sc_profile *,			struct sc_pkcs15_prkey_dsa *, struct pkdata *,			struct sc_pkcs15_prkey_info *);static int	gpk_store_pk(struct sc_profile *, struct sc_card *,			struct sc_file *, struct pkdata *);static void	error(struct sc_profile *, const char *, ...);static void	debug(struct sc_profile *, const char *, ...);/* * Erase the card */static intgpk_erase_card(struct sc_profile *pro, struct sc_card *card){	int	locked;	if (sc_card_ctl(card, SC_CARDCTL_GPK_IS_LOCKED, &locked) == 0	 && locked) {		error(pro,			"This card is already personalized, unable to "			"create PKCS#15 structure.");		return SC_ERROR_NOT_SUPPORTED;	}	return sc_card_ctl(card, SC_CARDCTL_ERASE_CARD, NULL);}/* * Lock a file operation */static intgpk_lock(struct sc_card *card, struct sc_file *file, unsigned int op){	struct sc_cardctl_gpk_lock	args;	args.file = file;	args.operation = op;	return sc_card_ctl(card, SC_CARDCTL_GPK_LOCK, &args);}/* * Lock the pin file */static intgpk_lock_pinfile(struct sc_profile *profile, struct sc_card *card,		struct sc_file *pinfile){	struct sc_path	path;	struct sc_file	*parent = NULL;	int		r;	/* Select the parent DF */	path = pinfile->path;	if (path.len >= 2)		path.len -= 2;	if (path.len == 0)		sc_format_path("3F00", &path);	if ((r = sc_select_file(card, &path, &parent)) < 0)		return r;	/* Present PINs etc as necessary */	r = sc_pkcs15init_authenticate(profile, card, parent, SC_AC_OP_LOCK);	if (r >= 0)		r = gpk_lock(card, pinfile, SC_AC_OP_WRITE);	sc_file_free(parent);	return r;}/* * Initialize pin file */static intgpk_init_pinfile(struct sc_profile *profile, struct sc_card *card,		struct sc_file *file){	struct sc_pkcs15_pin_info sopin_info, pin_info;	const struct sc_acl_entry *acl;	unsigned char	buffer[GPK_MAX_PINS * 8], *blk;	struct sc_file	*pinfile;	unsigned int	so_attempts[2], user_attempts[2];	unsigned int	npins, i, j, cks;	int		r;	/* Set defaults */	sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &sopin_info);	so_attempts[0] = sopin_info.tries_left;	sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PUK, &pin_info);	so_attempts[1] = pin_info.tries_left;	sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &pin_info);	user_attempts[0] = pin_info.tries_left;	sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PUK, &pin_info);	user_attempts[1] = pin_info.tries_left;	sc_file_dup(&pinfile, file);	/* Create the PIN file. */	acl = sc_file_get_acl_entry(pinfile, SC_AC_OP_WRITE);	if (acl->method != SC_AC_NEVER) {		error(profile, "PIN file most be protected by WRITE=NEVER");		return SC_ERROR_INVALID_ARGUMENTS;	}	sc_file_add_acl_entry(pinfile, SC_AC_OP_WRITE, SC_AC_NONE, 0);	if (pinfile->size == 0)		pinfile->size = GPK_MAX_PINS * 8;	/* Now create the file */	if ((r = sc_pkcs15init_create_file(profile, card, pinfile)) < 0	 || (r = sc_select_file(card, &pinfile->path, NULL)) < 0)		goto out;	/* Set up the PIN file contents.	 * We assume the file will contain pairs of PINs/PUKs */	npins = pinfile->size / 8;	memset(buffer, 0, sizeof(buffer));	for (i = 0, blk = buffer; i < npins; blk += 8, i += 1) {		/* Determine the number of PIN/PUK presentation		 * attempts. If the profile defines a SO PIN,		 * it will be stored in the first PIN/PUK pair.		 */		blk[0] = user_attempts[i & 1];		if (i < 2 && so_attempts[0])			blk[0] = so_attempts[i & 1];		if ((i & 1) == 0) {			/* This is a PIN. If there's room in the file,			 * the next will be a PUK so take note of the			 * unlock code */			if (i + 1 < npins)				blk[2] = 0x8 | (i + 1);		}		/* Compute the CKS */		for (j = 0, cks = 0; j < 8; j++)			cks ^= blk[j];		blk[3] = ~cks;	}	r = sc_write_binary(card, 0, buffer, npins * 8, 0);	if (r >= 0)		r = gpk_lock_pinfile(profile, card, pinfile);out:	sc_file_free(pinfile);	return r;}/* * Initialize the Application DF and pin file */static intgpk_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_pkcs15_pin_info sopin_info;	struct sc_file	*pinfile;	int		r, locked;	if (sc_card_ctl(card, SC_CARDCTL_GPK_IS_LOCKED, &locked) == 0	 && locked) {		error(profile,			"This card is already personalized, unable to "			"create PKCS#15 structure.");		return SC_ERROR_NOT_SUPPORTED;	}	/* Profile must define a "pinfile" */	if (sc_profile_get_file(profile, "pinfile", &pinfile) < 0) {		error(profile, "Profile doesn't define a \"pinfile\"");		return SC_ERROR_NOT_SUPPORTED;	}	/* Create the application DF */	r = sc_pkcs15init_create_file(profile, card, profile->df_info->file);	/* Create the PIN file */	if (r >= 0)		r = gpk_init_pinfile(profile, card, pinfile);	sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &sopin_info);	if (r >= 0 && pin_len) {		r = gpk_new_pin(profile, card, &sopin_info, 0,				pin, pin_len,				puk, puk_len);		if (r >= 0)			sc_profile_set_pin_info(profile, SC_PKCS15INIT_SO_PIN,					&sopin_info);	}	sc_file_free(pinfile);	return r;}/* * Store a PIN */static intgpk_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){	unsigned char	nulpin[8];	int		r;	/* Profile must define a "pinfile" */	if (sc_profile_get_path(profile, "pinfile", &info->path) < 0) {		error(profile, "Profile doesn't define a \"pinfile\"");		return SC_ERROR_INVALID_ARGUMENTS;	}	if (info->path.len > 2)		info->path.len -= 2;	r = sc_select_file(card, &info->path, NULL);	if (r < 0)		return r;	index <<= 2;	if (index >= GPK_MAX_PINS)		return SC_ERROR_TOO_MANY_OBJECTS;	if (puk == NULL || puk_len == 0) {		puk = pin;		puk_len = pin_len;	}	/* Current PIN is 00:00:00:00:00:00:00:00 */	memset(nulpin, 0, sizeof(nulpin));	r = sc_change_reference_data(card, SC_AC_CHV,			0x8 | index,			nulpin, sizeof(nulpin),			pin, pin_len, NULL);	if (r < 0)		return r;	/* Current PUK is 00:00:00:00:00:00:00:00 */	r = sc_change_reference_data(card, SC_AC_CHV,			0x8 | (index + 1),			nulpin, sizeof(nulpin),			puk, puk_len, NULL);	info->reference = 0x8 | index;	return r;}/* * Store a private key */static intgpk_new_key(struct sc_profile *profile, struct sc_card *card,		struct sc_pkcs15_prkey *key, unsigned int index,		struct sc_pkcs15_prkey_info *info){	struct sc_file	*keyfile = NULL;	struct pkdata	data;	int		r;	switch (key->algorithm) {	case SC_ALGORITHM_RSA:		r = gpk_new_file(profile, card, 				SC_PKCS15_TYPE_PRKEY_RSA, index,				&keyfile);		if (r >= 0)			r = gpk_encode_rsa_key(profile, &key->u.rsa,					&data, info);		break;	case SC_ALGORITHM_DSA:		r = gpk_new_file(profile, card, 				SC_PKCS15_TYPE_PRKEY_DSA, index,				&keyfile);		if (r >= 0)			r = gpk_encode_dsa_key(profile, &key->u.dsa,					&data, info);		break;	default:		return SC_ERROR_NOT_SUPPORTED;	}	/* Fix up PIN references in file ACL */	if (r >= 0)		r = sc_pkcs15init_fixup_file(profile, keyfile);	if (r >= 0)		r = gpk_store_pk(profile, card, keyfile, &data);	if (keyfile) {		info->path = keyfile->path;		sc_file_free(keyfile);	}	return r;}/* * Allocate a file */static intgpk_new_file(struct sc_profile *profile, struct sc_card *card,		unsigned int type, unsigned int num,		struct sc_file **out){	struct sc_file	*file;	struct sc_path	*p;	char		name[64], *tag, *desc;	desc = tag = NULL;	while (1) {		switch (type) {		case SC_PKCS15_TYPE_PRKEY_RSA:			desc = "RSA private key";			tag = "private-key";			break;		case SC_PKCS15_TYPE_PUBKEY_RSA:			desc = "RSA public key";			tag = "public-key";			break;#ifdef SC_PKCS15_TYPE_PRKEY_DSA		case SC_PKCS15_TYPE_PRKEY_DSA:			desc = "DSA private key";			tag = "private-key";			break;		case SC_PKCS15_TYPE_PUBKEY_DSA:			desc = "DSA public key";			tag = "public-key";			break;#endif		case SC_PKCS15_TYPE_PRKEY:			desc = "extractable private key";			tag = "extractable-key";			break;		case SC_PKCS15_TYPE_CERT:			desc = "certificate";			tag = "certificate";			break;		case SC_PKCS15_TYPE_DATA_OBJECT:			desc = "data object";			tag = "data";			break;		}		if (tag)			break;		/* If this is a specific type such as		 * SC_PKCS15_TYPE_CERT_FOOBAR, fall back to		 * the generic class (SC_PKCS15_TYPE_CERT)		 */		if (!(type & ~SC_PKCS15_TYPE_CLASS_MASK)) {			error(profile, "File type not supported by card driver");			return SC_ERROR_INVALID_ARGUMENTS;		}		type &= SC_PKCS15_TYPE_CLASS_MASK;	}	snprintf(name, sizeof(name), "template-%s", tag);	if (sc_profile_get_file(profile, name, &file) < 0) {		error(profile, "Profile doesn't define %s template (%s)\n",				desc, name);		return SC_ERROR_NOT_SUPPORTED;	}	/* Now construct file from template */	file->id += num;	p = &file->path;	*p = profile->df_info->file->path;	p->value[p->len++] = file->id >> 8;	p->value[p->len++] = file->id;	*out = file;	return 0;}/* * GPK public/private key file handling is hideous. * 600 lines of coke sweat and tears... *//* * Create the PK file * XXX: Handle the UPDATE ACL = NEVER case just like for EFsc files */static intgpk_pkfile_create(struct sc_profile *profile, struct sc_card *card,		struct sc_file *file){	struct sc_file	*found = NULL;	int		r;	card->ctx->log_errors = 0;	r = sc_select_file(card, &file->path, &found);	card->ctx->log_errors = 1;	if (r == SC_ERROR_FILE_NOT_FOUND) {		r = sc_pkcs15init_create_file(profile, card, file);		if (r >= 0)			r = sc_select_file(card, &file->path, &found);	} else {		/* XXX: make sure the file has correct type and size? */	}	if (r >= 0)		r = sc_pkcs15init_authenticate(profile, card,					file, SC_AC_OP_UPDATE);	if (found)		sc_file_free(found);	return r;}static intgpk_pkfile_keybits(unsigned int bits, unsigned char *p){	switch (bits) {	case  512: *p = 0x00; return 0;	case  768: *p = 0x10; return 0;	case 1024: *p = 0x11; return 0;	}	return SC_ERROR_NOT_SUPPORTED;}static intgpk_pkfile_keyalgo(unsigned int algo, unsigned char *p){	switch (algo) {	case SC_ALGORITHM_RSA: *p = 0x00; return 0;	case SC_ALGORITHM_DSA: *p = 0x01; return 0;

⌨️ 快捷键说明

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