Esempio n. 1
0
static int compare_obj_path(sc_pkcs15_object_t *obj, const sc_path_t *path)
{
	void *data = obj->data;
	
	switch (obj->type) {
	case SC_PKCS15_TYPE_CERT_X509:
		return sc_compare_path(&((struct sc_pkcs15_cert_info *) data)->path, path);
	case SC_PKCS15_TYPE_PRKEY_RSA:
	case SC_PKCS15_TYPE_PRKEY_DSA:
		return sc_compare_path(&((struct sc_pkcs15_prkey_info *) data)->path, path);
	case SC_PKCS15_TYPE_PUBKEY_RSA:
	case SC_PKCS15_TYPE_PUBKEY_DSA:
		return sc_compare_path(&((struct sc_pkcs15_pubkey_info *) data)->path, path);
	case SC_PKCS15_TYPE_AUTH_PIN:
		return sc_compare_path(&((struct sc_pkcs15_pin_info *) data)->path, path);
	case SC_PKCS15_TYPE_DATA_OBJECT:
		return sc_compare_path(&((struct sc_pkcs15_data_info *) data)->path, path);
	}
	return 0;
}
Esempio n. 2
0
int sc_pkcs15_encode_unusedspace(sc_context_t *ctx,
			 struct sc_pkcs15_card *p15card,
			 u8 **buf, size_t *buflen)
{
	sc_path_t dummy_path;
	static const struct sc_asn1_entry c_asn1_unusedspace[] = {
		{ "UnusedSpace", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
		{ NULL, 0, 0, 0, NULL, NULL }
	};
	static const struct sc_asn1_entry c_asn1_unusedspace_values[] = {
		{ "path", SC_ASN1_PATH,	SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
		{ "authId", SC_ASN1_PKCS15_ID, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL, NULL, NULL },
		{ NULL, 0, 0, 0, NULL, NULL }
	};
	struct sc_asn1_entry *asn1_unusedspace = NULL;
	struct sc_asn1_entry *asn1_values = NULL;
	int unusedspace_count = 0, r, c = 0;
	sc_pkcs15_unusedspace_t *unusedspace;

	sc_format_path("3F00", &dummy_path);
	dummy_path.index = dummy_path.count = 0;

	unusedspace = p15card->unusedspace_list;
	for ( ; unusedspace != NULL; unusedspace = unusedspace->next)
		unusedspace_count++;
	if (unusedspace_count == 0) {
		/* The standard says there has to be at least 1 entry,
		 * so we use a path with a length of 0 bytes */
		r = sc_pkcs15_add_unusedspace(p15card, &dummy_path, NULL);
		if (r)
			return r;
		unusedspace_count = 1;
	}

	asn1_unusedspace = (struct sc_asn1_entry *)
		malloc(sizeof(struct sc_asn1_entry) * (unusedspace_count + 1));
	if (asn1_unusedspace == NULL) {
		r = SC_ERROR_OUT_OF_MEMORY;
		goto err;
	}
	asn1_values = (struct sc_asn1_entry *)
		malloc(sizeof(struct sc_asn1_entry) * (unusedspace_count * 3));
	if (asn1_values == NULL) {
		r = SC_ERROR_OUT_OF_MEMORY;
		goto err;
	}

	for (unusedspace = p15card->unusedspace_list; unusedspace != NULL; unusedspace = unusedspace->next) {
		sc_copy_asn1_entry(c_asn1_unusedspace, asn1_unusedspace + c);
		sc_format_asn1_entry(asn1_unusedspace + c, asn1_values + 3*c, NULL, 1);
		sc_copy_asn1_entry(c_asn1_unusedspace_values, asn1_values + 3*c);
		sc_format_asn1_entry(asn1_values + 3*c, &unusedspace->path, NULL, 1);
		sc_format_asn1_entry(asn1_values + 3*c+1, &unusedspace->auth_id, NULL, unusedspace->auth_id.len);
		c++;
	}
	asn1_unusedspace[c].name = NULL;

	r = sc_asn1_encode(ctx, asn1_unusedspace, buf, buflen);

err:
	if (asn1_values != NULL)
		free(asn1_values);
	if (asn1_unusedspace != NULL)
		free(asn1_unusedspace);

	/* If we added the dummy entry, remove it now */
	if (unusedspace_count == 1 && sc_compare_path(&p15card->unusedspace_list->path, &dummy_path))
		sc_pkcs15_remove_unusedspace(p15card, p15card->unusedspace_list);

	return r;
}
/*
 * Instantiate template
 */
int
sc_profile_instantiate_template(sc_profile_t *profile,
		const char *template_name, const sc_path_t *base_path,
		const char *file_name, const sc_pkcs15_id_t *id,
		sc_file_t **ret)
{
	sc_card_t	*card = profile->card;
	sc_profile_t	*tmpl;
	sc_template_t	*info;
	unsigned int	idx;
	struct file_info *fi, *base_file, *match = NULL;

	for (info = profile->template_list; info; info = info->next) {
		if (!strcmp(info->name, template_name))
			break;
	}
	if (info == NULL)
		return SC_ERROR_TEMPLATE_NOT_FOUND;

	tmpl = info->data;
	idx = id->value[id->len-1];
	for (fi = profile->ef_list; fi; fi = fi->next) {
		if (fi->base_template == tmpl
		 && fi->inst_index == idx
		 && sc_compare_path(&fi->inst_path, base_path)
		 && !strcmp(fi->ident, file_name)) {
			sc_file_dup(ret, fi->file);
			if (*ret == NULL)
				return SC_ERROR_OUT_OF_MEMORY;
			return 0;
		}
	}

	if (profile->card->ctx->debug >= 2) {
		char pbuf[SC_MAX_PATH_STRING_SIZE];

		int r = sc_path_print(pbuf, sizeof(pbuf), base_path);
		if (r != SC_SUCCESS)
			pbuf[0] = '\0';

		sc_debug(profile->card->ctx,
			"Instantiating template %s at %s", template_name, pbuf);
	}

	base_file = sc_profile_find_file_by_path(profile, base_path);
	if (base_file == NULL) {
		char pbuf[SC_MAX_PATH_STRING_SIZE];

		int r = sc_path_print(pbuf, sizeof(pbuf), base_path);
		if (r != SC_SUCCESS)
			pbuf[0] = '\0';

		sc_error(card->ctx, "Directory %s not defined in profile", pbuf);
		return SC_ERROR_OBJECT_NOT_FOUND;
	}

	/* This loop relies on the fact that new files are always
	 * appended to the list, after the parent files they refer to
	 */
	assert(base_file->instance);
	for (fi = tmpl->ef_list; fi; fi = fi->next) {
		file_info	*parent, *instance;
		unsigned int	skew = 0;

		fi->instance = NULL;
		if ((parent = fi->parent) == NULL) {
			parent = base_file;
			skew = idx;
		}
		parent = parent->instance;

		instance = sc_profile_instantiate_file(profile, fi, parent, skew);
		if (instance == NULL)
			return SC_ERROR_OUT_OF_MEMORY;
		instance->base_template = tmpl;
		instance->inst_index = idx;
		instance->inst_path = *base_path;

		if (!strcmp(instance->ident, file_name))
			match = instance;
	}

	if (match == NULL) {
		sc_error(card->ctx, "No file named \"%s\" in template \"%s\"",
				file_name, template_name);
		return SC_ERROR_OBJECT_NOT_FOUND;
	}
	sc_file_dup(ret, match->file);
	if (*ret == NULL)
		return SC_ERROR_OUT_OF_MEMORY;
	return 0;
}