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

📄 pkcs15-lib.c

📁 读写Smart卡加解密接口的程序
💻 C
📖 第 1 页 / 共 4 页
字号:
voidsc_pkcs15init_set_pin_data(struct sc_profile *profile, int pin_id,				const void *value, size_t len){	sc_profile_set_secret(profile, SC_AC_SYMBOLIC, pin_id, (const u8 *) value, len);}/* * PIN verification */intdo_get_and_verify_secret(struct sc_profile *pro, struct sc_card *card,		int type, int reference,		u8 *pinbuf, size_t *pinsize,		int verify){	struct sc_pkcs15_pin_info pin_info;	struct sc_cardctl_default_key data;	const char	*ident, *label = NULL;	unsigned int	pin_id = (unsigned int) -1;	size_t		defsize = 0;	u8		defbuf[32];	int		r;	ident = "authentication data";	if (type == SC_AC_CHV) {		sc_pkcs15_object_t *pin_obj;		ident = "PIN";		memset(&pin_info, 0, sizeof(pin_info));		if (sc_profile_get_pin_id(pro, reference, &pin_id) >= 0) {			sc_profile_get_pin_info(pro, pin_id, &pin_info);		} else		if (pro->p15_card		 && sc_pkcs15_find_pin_by_reference(pro->p15_card, reference, &pin_obj) == 0) {			memcpy(&pin_info, pin_obj->data, sizeof(pin_info));		} else {			/* This is all info we have */			pin_info.reference = reference;		}	} else if (type == SC_AC_PRO) {		ident = "secure messaging key";	} else if (type == SC_AC_AUT) {		ident = "authentication key";	} else if (type == SC_AC_SYMBOLIC) {		switch (reference) {		case SC_PKCS15INIT_USER_PIN:			ident = "user PIN"; break;		case SC_PKCS15INIT_SO_PIN:			ident = "SO PIN"; break;		}		pin_id = reference;		sc_profile_get_pin_info(pro, pin_id, &pin_info);		type = SC_AC_CHV;		reference = pin_info.reference;		/* If reference is -1, this means the card issuer		 * didn't set this PIN */		if (reference == -1)			return 0;	}	/* Try to get the cached secret, e.g. CHV1 */	r = sc_profile_get_secret(pro, type, reference, pinbuf, pinsize);	if (r >= 0)		goto found;	/* If this secret is linked to a symbolic PIN, e.g. SOPIN1,	 * see if we've cached it under that name */	if (pin_id != -1) {		r = sc_profile_get_secret(pro, SC_AC_SYMBOLIC, pin_id,				pinbuf, pinsize);		if (r >= 0)			goto found;	}	if (type != SC_AC_CHV) {		/* Okay, nothing in our cache.		 * Ask the card driver whether it knows a default key		 * for this one.		 */		data.method = type;		data.key_ref = reference;		data.len = sizeof(defbuf);		data.key_data = defbuf;		if (sc_card_ctl(card, SC_CARDCTL_GET_DEFAULT_KEY, &data) >= 0)			defsize = data.len;	} else if (pro->p15_card) {		/* Get the label, if we have one */		struct sc_pkcs15_object *obj;		int r;		r = sc_pkcs15_find_pin_by_reference(pro->p15_card,					reference, &obj);		if (r >= 0 && obj->label[0])			label = obj->label;	}	if (callbacks) {		switch (type) {		case SC_AC_CHV:			if (callbacks->get_pin) {				r = callbacks->get_pin(pro, pin_id,						&pin_info, label,						pinbuf, pinsize);			}			break;		default:			if (callbacks->get_key) {				r = callbacks->get_key(pro, type, reference,						defbuf, defsize,						pinbuf, pinsize);			}			break;		}	}	if (r < 0)		return r;found:	/* We got something. Cache it */	sc_profile_set_secret(pro, type, reference, pinbuf, *pinsize);	/* If it's a PIN, pad it out */	if (type == SC_AC_CHV) {		int left = pro->pin_maxlen - *pinsize;		if (left > 0) {			memset(pinbuf + *pinsize, pro->pin_pad_char, left);			*pinsize = pro->pin_maxlen;		}		/* If it's associated with a symbolic PIN, store it under		 * the symbolic name as well */		if (pin_id != -1)			sc_profile_set_secret(pro, SC_AC_SYMBOLIC, pin_id,						pinbuf, *pinsize);	}	if (verify	 && (r = sc_verify(card, type, reference, pinbuf, *pinsize, 0)) < 0) {		p15init_error("Failed to verify %s (ref=0x%x)",				ident, reference);	}	return r;}static intdo_verify_pin(struct sc_profile *pro, struct sc_card *card,		unsigned int type, unsigned int reference){	size_t		pinsize;	u8		pinbuf[32];	pinsize = sizeof(pinbuf);	return do_get_and_verify_secret(pro, card, type, reference,			pinbuf, &pinsize, 1);}voidsc_pkcs15init_set_secret(struct sc_profile *pro,			int type, int reference,			u8 *key, size_t len){	sc_profile_set_secret(pro, type, reference, key, len);}intsc_pkcs15init_get_secret(struct sc_profile *pro, struct sc_card *card,		int type, int reference,		u8 *pinbuf, size_t *pinsize){	return do_get_and_verify_secret(pro, card, type, reference,			pinbuf, pinsize, 0);}/* * Present a single PIN to the card */intsc_pkcs15init_present_pin(struct sc_profile *profile, struct sc_card *card,		unsigned int id){	return do_verify_pin(profile, card, SC_AC_SYMBOLIC, id);}/* * Find out whether the card was initialized using an SO PIN, * and if so, set the profile information */intset_so_pin_from_card(struct sc_pkcs15_card *p15card, struct sc_profile *profile){	struct sc_pkcs15_pin_info pin;	struct sc_pkcs15_object *obj;	int		r;	r = sc_pkcs15_find_so_pin(p15card, &obj);	if (r == 0) {		pin = *(struct sc_pkcs15_pin_info *) obj->data;	} else if (r == SC_ERROR_OBJECT_NOT_FOUND) {		sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &pin);		pin.reference = -1;	} else {		return r;	}	sc_profile_set_pin_info(profile, SC_PKCS15INIT_SO_PIN, &pin);	return 0;}/* * If the user specified an auth_id, select the corresponding * PIN entry and set the reference data */static intset_user_pin_from_authid(struct sc_pkcs15_card *p15card,		struct sc_profile *profile,		struct sc_pkcs15_id *auth_id){	struct sc_pkcs15_object	*objp;	int		r;	if (auth_id->len == 0)		return 0;	r = sc_pkcs15_find_pin_by_auth_id(p15card, auth_id, &objp);	if (r < 0)		return r;	sc_profile_set_pin_info(profile, SC_PKCS15INIT_USER_PIN,			(struct sc_pkcs15_pin_info *) objp->data);	return 0;}/* * Present any authentication info as required by the file. * * XXX: There's a problem here if e.g. the SO PIN defined by * the profile is optional, and hasn't been set. In this case, * it would be better if we based our authentication on the * real ACLs of the file (i.e. the data returned by a previous * sc_select_file()). Current practice though is to prefer * checking against the ACL defined by the profile (introduced by * Juha for some reason) and I'm not sure we can change this * easily. */intsc_pkcs15init_authenticate(struct sc_profile *pro, struct sc_card *card,		struct sc_file *file, int op){	const struct sc_acl_entry *acl;	int		r = 0;#if 0	/* Fix up the file's ACLs */	if ((r = sc_pkcs15init_fixup_file(pro, file)) < 0)		return r;#endif	acl = sc_file_get_acl_entry(file, op);	for (; r == 0 && acl; acl = acl->next) {		if (acl->method == SC_AC_NEVER)			return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;		if (acl->method == SC_AC_NONE)			break;		r = do_verify_pin(pro, card, acl->method, acl->key_ref);	}	return r;}intdo_select_parent(struct sc_profile *pro, struct sc_card *card,		struct sc_file *file, struct sc_file **parent){	struct sc_path	path;	int		r;	/* Get the parent's path */	path = file->path;	if (path.len >= 2)		path.len -= 2;	if (path.len == 0)		sc_format_path("3F00", &path);	/* Select the parent DF. */	*parent = NULL;	card->ctx->log_errors = 0;	r = sc_select_file(card, &path, parent);	card->ctx->log_errors = 1;	/* If DF doesn't exist, create it (unless it's the MF,	 * but then something's badly broken anyway :-) */	if (r == SC_ERROR_FILE_NOT_FOUND && path.len != 2) {		r = sc_profile_get_file_by_path(pro, &path, parent);		if (r < 0) {			char	buffer[SC_MAX_PATH_SIZE*2+1];			size_t	n;			buffer[0] = '\0';			for (n = 0; n < path.len; n++)				sprintf(buffer+2*n, "%02x", path.value[n]);			p15init_error("profile doesn't define a DF %s");			return r;		}		if (!(r = sc_pkcs15init_create_file(pro, card, *parent)))			r = sc_select_file(card, &path, NULL);	}	return r;}intsc_pkcs15init_create_file(struct sc_profile *pro, struct sc_card *card,		struct sc_file *file){	struct sc_file	*parent = NULL;	int		r;	/* Select parent DF and verify PINs/key as necessary */	if ((r = do_select_parent(pro, card, file, &parent)) < 0	 || (r = sc_pkcs15init_authenticate(pro, card,			 	parent, SC_AC_OP_CREATE)) < 0) 		goto out;	/* Fix up the file's ACLs */	if ((r = sc_pkcs15init_fixup_file(pro, file)) < 0)		return r;	r = sc_create_file(card, file);out:	if (parent)		sc_file_free(parent);	return r;}intsc_pkcs15init_update_file(struct sc_profile *profile, struct sc_card *card,	       	struct sc_file *file, void *data, unsigned int datalen){	struct sc_file	*info = NULL;	int		r;	card->ctx->log_errors = 0;	if ((r = sc_select_file(card, &file->path, &info)) < 0) {		card->ctx->log_errors = 1;		/* Create file if it doesn't exist */		if (file->size < datalen)			file->size = datalen;		if (r != SC_ERROR_FILE_NOT_FOUND		 || (r = sc_pkcs15init_create_file(profile, card, file)) < 0		 || (r = sc_select_file(card, &file->path, &info)) < 0)			return r;	}	card->ctx->log_errors = 1;	if (info->size < datalen) {		char	buf[16];		sc_bin_to_hex(file->path.value, file->path.len, buf, sizeof(buf), 0);		p15init_error("File %s too small - please increase size in profile", buf);		sc_file_free(info);		return SC_ERROR_TOO_MANY_OBJECTS;	}	/* Present authentication info needed */	r = sc_pkcs15init_authenticate(profile, card, file, SC_AC_OP_UPDATE);	if (r >= 0 && datalen)		r = sc_update_binary(card, 0, (const u8 *) data, datalen, 0);	sc_file_free(info);	return r;}/* * Fix up all file ACLs */intsc_pkcs15init_fixup_file(struct sc_profile *profile, struct sc_file *file){	struct sc_pkcs15_pin_info so_pin, user_pin;	struct sc_acl_entry so_acl, user_acl;	unsigned int	op, needfix = 0;	/* First, loop over all ACLs to find out whether there	 * are still any symbolic references.	 */	for (op = 0; op < SC_MAX_AC_OPS; op++) {		const struct sc_acl_entry *acl;		acl = sc_file_get_acl_entry(file, op);		for (; acl; acl = acl->next) {			if (acl->method == SC_AC_SYMBOLIC)				needfix++;		}	}	if (!needfix)		return 0;	sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &so_pin);	sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &user_pin);	/* If the profile doesn't specify a SO pin, change all	 * ACLs that reference $sopin to NONE */	so_acl.method = SC_AC_CHV;	so_acl.key_ref = so_pin.reference;	if (so_acl.key_ref == -1) {		so_acl.method = SC_AC_NONE;		so_acl.key_ref = 0;	}#if 0	/* If we haven't got a user pin, barf */	user_acl.method = SC_AC_CHV;	user_acl.key_ref = user_pin.reference;#else	/* Not setting a user pin is legitimate. */	user_acl.method = SC_AC_CHV;	user_acl.key_ref = user_pin.reference;	if (user_acl.key_ref == -1) {		user_acl.method = SC_AC_NONE;		user_acl.key_ref = 0;	}#endif	return sc_pkcs15init_fixup_acls(profile, file, &so_acl, &user_acl);}/* * Fix up a file's ACLs by replacing all occurrences of a symbolic * PIN name with the real reference. */intsc_pkcs15init_fixup_acls(struct sc_profile *profile, struct sc_file *file,		struct sc_acl_entry *so_acl,		struct sc_acl_entry *user_acl){	struct sc_acl_entry acls[16];	unsigned int	op, num;	int		r = 0;	for (op = 0; r == 0 && op < SC_MAX_AC_OPS; op++) {		const struct sc_acl_entry *acl;		const char	*what;		int		added = 0;		/* First, get original ACLs */		acl = sc_file_get_acl_entry(file, op);		for (num = 0; num < 16 && acl; num++, acl = acl->next)			acls[num] = *acl;		sc_file_clear_acl_entries(file, op);		for (acl = acls; acl < acls + num; acl++) {			if (acl->method != SC_AC_SYMBOLIC)				goto next;			if (acl->key_ref == SC_PKCS15INIT_SO_PIN) {				acl = so_acl;				what = "SO PIN";			} else if (acl->key_ref == SC_PKCS15INIT_USER_PIN) {				acl = user_acl;				what = "user PIN";			} else {				p15init_error("ACL references unknown symbolic PIN %d",						acl->key_ref);				return SC_ERROR_INVALID_ARGUMENTS;			}			/* If we weren't given a replacement ACL,			 * leave the original ACL untouched */			if (acl == NULL || acl->key_ref == -1) {				p15init_error("ACL references %s, which is not defined",						what);				return SC_ERROR_INVALID_ARGUMENTS;			}			if (acl->method == SC_AC_NONE)				continue;		next:	sc_file_add_acl_entry(file, op,					acl->method, acl->key_ref);			added++;		}		if (!added)			sc_file_add_acl_entry(file, op, SC_AC_NONE, 0);	}	return r;}intsc_pkcs15init_get_pin_info(struct sc_profile *profile,		unsigned int id, struct sc_pkcs15_pin_info *pin){	sc_profile_get_pin_info(profile, id, pin);	return 0;}intsc_pkcs15init_get_manufacturer(struct sc_profile *profile, const char **res){	*res = profile->p15_card->manufacturer_id;	return 0;}intsc_pkcs15init_get_serial(struct sc_profile *profile, const char **res){	*res = profile->p15_card->serial_number;	return 0;}intsc_pkcs15init_set_serial(struct sc_profile *profile, const char *serial){	if (profile->p15_card->serial_number)		free(profile->p15_card->serial_number);	profile->p15_card->serial_number = strdup(serial);	return 0;}intsc_pkcs15init_get_label(struct sc_profile *profile, const char **res){	*res = profile->p15_card->label;	return 0;}voiddefault_error_handler(const char *fmt, ...){	va_list	ap;	va_start(ap, fmt);	vfprintf(stderr, fmt, ap);	fputs("\n", stderr);	va_end(ap);}voiddefault_debug_handler(const char *fmt, ...){	/* Nothing */}

⌨️ 快捷键说明

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