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; }
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; }