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

📄 pkcs15-lib.c

📁 读写Smart卡加解密接口的程序
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Initialize Cards according to PKCS#15. * * This is a fill in the blanks sort of exercise. You need a * profile that describes characteristics of your card, and the * application specific layout on the card. This program will * set up the card according to this specification (including * PIN initialization etc) and create the corresponding PKCS15 * structure. * * There are a very few tasks that are too card specific to have * a generic implementation; that is how PINs and keys are stored * on the card. These should be implemented in pkcs15-<cardname>.c * * 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 <stdio.h>#include <stdlib.h>#include <ctype.h>#include <stdarg.h>#include <string.h>#include <limits.h>#ifdef HAVE_STRINGS_H#include <strings.h>#endif#include <assert.h>#ifdef HAVE_OPENSSL#include <openssl/bn.h>#include <openssl/evp.h>#include <openssl/pem.h>#include <openssl/err.h>#include <openssl/rand.h>#include <openssl/rsa.h>#include <openssl/pkcs12.h>#endif#include <opensc/pkcs15.h>#include "profile.h"#include "pkcs15-init.h"#include <opensc/cardctl.h>/* Default ID for new key/pin */#define DEFAULT_ID		0x45#define DEFAULT_PRKEY_FLAGS	0x1d#define DEFAULT_PUBKEY_FLAGS	0x02#define DEFAULT_CERT_FLAGS	0x02#define DEFAULT_DATA_FLAGS	0x03/* Handle encoding of PKCS15 on the card */typedef int	(*pkcs15_encoder)(struct sc_context *,			struct sc_pkcs15_card *, u8 **, size_t *);static int	sc_pkcs15init_store_data(struct sc_pkcs15_card *,			struct sc_profile *, unsigned int,			sc_pkcs15_der_t *, struct sc_path *);static size_t	sc_pkcs15init_keybits(sc_pkcs15_bignum_t *);static int	sc_pkcs15init_update_dir(struct sc_pkcs15_card *,			struct sc_profile *profile,			struct sc_app_info *app);static int	sc_pkcs15init_update_tokeninfo(struct sc_pkcs15_card *,			struct sc_profile *profile);static int	sc_pkcs15init_update_odf(struct sc_pkcs15_card *,			struct sc_profile *profile);static int	sc_pkcs15init_add_object(struct sc_pkcs15_card *,			struct sc_profile *profile,			unsigned int df_type,			struct sc_pkcs15_object *);static int	sc_pkcs15init_map_usage(unsigned long, int);static int	set_so_pin_from_card(struct sc_pkcs15_card *,			struct sc_profile *);static int	set_user_pin_from_authid(struct sc_pkcs15_card *,			struct sc_profile *, struct sc_pkcs15_id *);static int	do_select_parent(struct sc_profile *, struct sc_card *,			struct sc_file *, struct sc_file **);static int	aodf_add_pin(struct sc_pkcs15_card *, struct sc_profile *,			const struct sc_pkcs15_pin_info *, const char *);static int	check_key_compatibility(struct sc_pkcs15_card *,			struct sc_pkcs15_prkey *, unsigned int,			unsigned int, unsigned int);static int	prkey_fixup(sc_pkcs15_prkey_t *);static int	prkey_bits(sc_pkcs15_prkey_t *);static int	prkey_pkcs15_algo(sc_pkcs15_prkey_t *);static int	select_id(struct sc_pkcs15_card *, int, struct sc_pkcs15_id *);static struct sc_pkcs15_df * find_df_by_type(struct sc_pkcs15_card *, int);static void	default_error_handler(const char *fmt, ...);static void	default_debug_handler(const char *fmt, ...);/* Card specific functions */extern struct sc_pkcs15init_operations	sc_pkcs15init_gpk_operations;extern struct sc_pkcs15init_operations	sc_pkcs15init_miocos_operations;extern struct sc_pkcs15init_operations	sc_pkcs15init_cflex_operations;extern struct sc_pkcs15init_operations	sc_pkcs15init_etoken_operations;static struct sc_pkcs15init_callbacks default_callbacks = {	default_error_handler,	default_debug_handler};static struct sc_pkcs15init_callbacks *callbacks = &default_callbacks;#define p15init_error	callbacks->error#define p15init_debug	callbacks->debug/* * Set the application callbacks */voidsc_pkcs15init_set_callbacks(struct sc_pkcs15init_callbacks *cb){	callbacks = cb;}/* Returns 1 if the a profile was found in the card's card_driver block *   in the config file, or 0 otherwise. * card_prof_name is a PATH_MAX -sized buffer that will hold the profile name */static int get_profile_from_config(struct sc_card *card, char *card_prof_name){	struct sc_context *ctx = card->ctx;	const char *tmp;	scconf_block **blocks, *blk;	int i;	for (i = 0; ctx->conf_blocks[i]; i++) {		blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i],					"card_driver", card->driver->short_name);		blk = blocks[0];		free(blocks);		if (blk == NULL)			continue;		tmp = scconf_get_str(blk, "profile", NULL);		if (tmp != NULL) {			strncpy(card_prof_name, tmp, PATH_MAX);			return 1;		}	}	return 0;}/* * Set up profile */intsc_pkcs15init_bind(struct sc_card *card, const char *name,		const char *card_profile_name, struct sc_profile **result){	struct sc_profile *profile;	const char	*driver = card->driver->short_name;	char		card_prof_name[PATH_MAX];	int		r;	/* Put the card into administrative mode */	r = sc_pkcs15init_set_lifecycle(card, SC_CARDCTRL_LIFECYCLE_ADMIN);	if (r < 0 && r != SC_ERROR_NOT_SUPPORTED)		return r;	profile = sc_profile_new();	profile->cbs = callbacks;	if (!strcasecmp(driver, "GPK"))		profile->ops = &sc_pkcs15init_gpk_operations;	else if (!strcasecmp(driver, "MioCOS"))		profile->ops = &sc_pkcs15init_miocos_operations;	else if (!strcasecmp(driver, "flex"))		profile->ops = &sc_pkcs15init_cflex_operations;	else if (!strcasecmp(driver, "eToken"))		profile->ops = &sc_pkcs15init_etoken_operations;	else {		p15init_error("Unsupported card driver %s", driver);		sc_profile_free(profile);		return SC_ERROR_NOT_SUPPORTED;	}	/* 1. Use card_profile_name if present,	 * 2. otherwise look in the config file, or	 * 3. otherwise use the default profile name.	 */	if (card_profile_name != NULL)		strcpy(card_prof_name, card_profile_name);         /* 1 */	else if (!get_profile_from_config(card, card_prof_name)) /* 2 */			strcpy(card_prof_name, driver);            /* 3 */	if ((r = sc_profile_load(profile, name)) < 0	 || (r = sc_profile_load(profile, card_prof_name)) < 0	 || (r = sc_profile_finish(profile)) < 0) {		fprintf(stderr,			"Failed to load profile: %s\n",			sc_strerror(r));		sc_profile_free(profile);		return r;	}	*result = profile;	if (r == 0)		*result = profile;	return r;}voidsc_pkcs15init_unbind(struct sc_profile *profile){	sc_profile_free(profile);}/* * Set the card's lifecycle */intsc_pkcs15init_set_lifecycle(sc_card_t *card, int lcycle){	return sc_card_ctl(card, SC_CARDCTL_LIFECYCLE_SET, &lcycle);}/* * Erase the card */intsc_pkcs15init_erase_card(struct sc_card *card, struct sc_profile *profile){	if (profile->ops->erase_card == NULL)		return SC_ERROR_NOT_SUPPORTED;	return profile->ops->erase_card(profile, card);}intsc_pkcs15init_erase_card_recursively(struct sc_card *card, 		struct sc_profile *profile,		int so_pin_ref){	struct sc_pkcs15_card *p15orig = profile->p15_card;	struct sc_pkcs15_pin_info sopin, temp;	struct sc_file	*df = profile->df_info->file, *dir;	int		r;	/* Frob: need to tell the upper layers about the SO PIN id */	sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &sopin);	if (so_pin_ref != -1) {		temp = sopin;		temp.reference = so_pin_ref;		sc_profile_set_pin_info(profile, SC_PKCS15INIT_SO_PIN, &temp);	} else {		struct sc_pkcs15_card *p15card = NULL;		card->ctx->log_errors = 0;		if (sc_pkcs15_bind(card, &p15card) >= 0) {			set_so_pin_from_card(p15card, profile);			profile->p15_card = p15card;		}		card->ctx->log_errors = 1;	}	/* Delete EF(DIR). This may not be very nice	 * against other applications that use this file, but	 * extremely useful for testing :)	 * Note we need to delete if before the DF because we create	 * it *after* the DF. Some cards (e.g. the cryptoflex) want	 * us to delete file in reverse order of creation.	 * */	if (sc_profile_get_file(profile, "DIR", &dir) >= 0) {		r = sc_pkcs15init_rmdir(card, profile, dir);		sc_file_free(dir);		if (r < 0 && r != SC_ERROR_FILE_NOT_FOUND)			goto out;	}	card->ctx->log_errors = 0;	r = sc_select_file(card, &df->path, &df);	card->ctx->log_errors = 1;	if (r >= 0) {		r = sc_pkcs15init_rmdir(card, profile, df);		sc_file_free(df);	}	if (r == SC_ERROR_FILE_NOT_FOUND)		r = 0;	/* Unfrob the SO pin reference, and return */out:	sc_profile_set_pin_info(profile, SC_PKCS15INIT_SO_PIN, &sopin);	sc_profile_forget_secrets(profile, SC_AC_CHV, -1);	sc_free_apps(card);	if (profile->p15_card != p15orig) {		sc_pkcs15_unbind(profile->p15_card);		profile->p15_card = p15orig;	}	return r;}/* * Try to delete a file (and, in the DF case, its contents). * Note that this will not work if a pkcs#15 file's ERASE AC * references a pin other than the SO pin. */intsc_pkcs15init_rmdir(struct sc_card *card, struct sc_profile *profile,		struct sc_file *df){	u8		buffer[1024];	struct sc_path	path;	struct sc_file	*file, *parent;	int		r = 0, nfids;#if 0	if (card->ctx->debug) {		int	n;		printf("%s(", __FUNCTION__);		path = df->path;		for (n = 0; n < path.len; n++)			printf("%02x", path.value[n]);		printf(")\n");	}#endif	if (df == NULL)		return SC_ERROR_INTERNAL;	if (df->type == SC_FILE_TYPE_DF) {		r = sc_pkcs15init_authenticate(profile, card, df,				SC_AC_OP_LIST_FILES);		if (r < 0)			return r;		card->ctx->log_errors = 0;		r = sc_list_files(card, buffer, sizeof(buffer));		card->ctx->log_errors = 1;		if (r < 0)			return r;		path = df->path;		path.len += 2;		nfids = r / 2;		while (r >= 0 && nfids--) {			path.value[path.len-2] = buffer[2*nfids];			path.value[path.len-1] = buffer[2*nfids+1];			r = sc_select_file(card, &path, &file);			if (r < 0) {				if (r == SC_ERROR_FILE_NOT_FOUND)					continue;				break;			}			r = sc_pkcs15init_rmdir(card, profile, file);			sc_file_free(file);		}		if (r < 0)			return r;	}	/* Select the parent DF */	path = df->path;	path.len -= 2;	r = sc_select_file(card, &path, &parent);	if (r < 0)		return r;	r = sc_pkcs15init_authenticate(profile, card, parent, SC_AC_OP_DELETE);	sc_file_free(parent);	if (r < 0)		return r;	r = sc_pkcs15init_authenticate(profile, card, df, SC_AC_OP_ERASE);	if (r < 0)		return r;	memset(&path, 0, sizeof(path));	path.type = SC_PATH_TYPE_FILE_ID;	path.value[0] = df->id >> 8;	path.value[1] = df->id & 0xFF;	path.len = 2;	card->ctx->log_errors = 0;	r = sc_delete_file(card, &path);	card->ctx->log_errors = 1;	return r;}/* * Initialize the PKCS#15 application */intsc_pkcs15init_add_app(struct sc_card *card, struct sc_profile *profile,		struct sc_pkcs15init_initargs *args){	struct sc_pkcs15_card *p15card = profile->p15_card;	struct sc_pkcs15_pin_info pin_info;	struct sc_app_info *app;	int	r;	p15card->card = card;	if (card->app_count >= SC_MAX_CARD_APPS) {		p15init_error("Too many applications on this card.");		return SC_ERROR_TOO_MANY_OBJECTS;	}	/* If the profile requires an SO PIN, check min/max length */	sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &pin_info);	if (args->so_pin_len == 0) {		/* Mark the SO PIN as "not set" */		pin_info.reference = -1;		sc_profile_set_pin_info(profile,				SC_PKCS15INIT_SO_PIN, &pin_info);	} else	if (args->so_pin_len && args->so_pin_len < pin_info.min_length) {		p15init_error("SO PIN too short (min length %u)",				pin_info.min_length);		return SC_ERROR_WRONG_LENGTH;	}	if (args->so_pin_len > pin_info.max_length)		args->so_pin_len = pin_info.max_length;	sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PUK, &pin_info);	if (args->so_puk_len && args->so_puk_len < pin_info.min_length) {		p15init_error("SO PUK too short (min length %u)",				pin_info.min_length);		return SC_ERROR_WRONG_LENGTH;	}	if (args->so_puk_len > pin_info.max_length)		args->so_puk_len = pin_info.max_length;	/* Create the application DF and store the PINs */	r = profile->ops->init_app(profile, card,			args->so_pin, args->so_pin_len,			args->so_puk, args->so_puk_len);	if (r < 0)		return r;	/* Store the PKCS15 information on the card	 * We cannot use sc_pkcs15_create() because it makes	 * all sorts of assumptions about DF and EF names, and	 * doesn't work if secure messaging is required for the	 * MF (which is the case with the GPK) */	app = (struct sc_app_info *) calloc(1, sizeof(*app));	app->path = p15card->file_app->path;	if (p15card->file_app->namelen <= SC_MAX_AID_SIZE) {		app->aid_len = p15card->file_app->namelen;		memcpy(app->aid, p15card->file_app->name, app->aid_len);	}	if (args->serial)		sc_pkcs15init_set_serial(profile, args->serial);	if (args->label) {		if (p15card->label)			free(p15card->label);		p15card->label = strdup(args->label);	}	app->label = strdup(p15card->label);	/* XXX: encode the DDO? */	/* See if we've set an SO PIN */	sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &pin_info);	if (pin_info.reference != -1 && args->so_pin_len) {		sc_profile_set_secret(profile, SC_AC_SYMBOLIC,				SC_PKCS15INIT_SO_PIN,				args->so_pin, args->so_pin_len);		pin_info.flags |= SC_PKCS15_PIN_FLAG_SO_PIN;		r = aodf_add_pin(p15card, profile, &pin_info,				"Security Officer PIN");	} else {		r = sc_pkcs15init_add_object(p15card, profile,				SC_PKCS15_AODF, NULL);	}	if (r >= 0)		r = sc_pkcs15init_update_dir(p15card, profile, app);	if (r >= 0)		r = sc_pkcs15init_update_tokeninfo(p15card, profile);	return r;}/* * Store a PIN/PUK pair */intsc_pkcs15init_store_pin(struct sc_pkcs15_card *p15card,			struct sc_profile *profile,			struct sc_pkcs15init_pinargs *args){	struct sc_pkcs15_pin_info pin_info;	struct sc_card	*card = p15card->card;	int		r, index;	/* No auth_id given: select one */	if (args->auth_id.len == 0) {		struct sc_pkcs15_object *dummy;		unsigned int	n;		args->auth_id.len = 1;		card->ctx->log_errors = 0;		for (n = 1, r = 0; n < 256; n++) {			args->auth_id.value[0] = n;			r = sc_pkcs15_find_pin_by_auth_id(p15card,					&args->auth_id, &dummy);			if (r == SC_ERROR_OBJECT_NOT_FOUND)				break;		}		card->ctx->log_errors = 1;		if (r != SC_ERROR_OBJECT_NOT_FOUND) {			p15init_error("No auth_id specified for new PIN");			return SC_ERROR_INVALID_ARGUMENTS;		}	} else {		struct sc_pkcs15_object *dummy;		/* Make sure we don't get duplicate PIN IDs */		card->ctx->log_errors = 0;		r = sc_pkcs15_find_pin_by_auth_id(p15card,				&args->auth_id, &dummy);		if (r != SC_ERROR_OBJECT_NOT_FOUND) {			p15init_error("There already is a PIN with this ID.");			return SC_ERROR_INVALID_ARGUMENTS;		}	}	sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &pin_info);	pin_info.auth_id = args->auth_id;	/* Get the number of PINs we already have */	index = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH,				NULL, 0);	/* Set the SO PIN reference from card */	if ((r = set_so_pin_from_card(p15card, profile)) < 0)		return r;	/* Now store the PINs */	r = profile->ops->new_pin(profile, card, &pin_info, index,			args->pin, args->pin_len,			args->puk, args->puk_len);	/* Fix up any ACLs referring to the user pin */

⌨️ 快捷键说明

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