int sc_pkcs15_unbind(struct sc_pkcs15_card *p15card) { assert(p15card != NULL && p15card->magic == SC_PKCS15_CARD_MAGIC); SC_FUNC_CALLED(p15card->card->ctx, 1); if (p15card->dll_handle) lt_dlclose(p15card->dll_handle); sc_pkcs15_card_free(p15card); return 0; }
void sc_profile_free(struct sc_profile *profile) { struct auth_info *ai; struct pin_info *pi; sc_macro_t *mi; sc_template_t *ti; if (profile->name) free(profile->name); free_file_list(&profile->ef_list); while ((ai = profile->auth_list) != NULL) { profile->auth_list = ai->next; free(ai); } while ((ti = profile->template_list) != NULL) { profile->template_list = ti->next; if (ti->data) sc_profile_free(ti->data); if (ti->name) free(ti->name); free(ti); } while ((mi = profile->macro_list) != NULL) { profile->macro_list = mi->next; if (mi->name) free(mi->name); free(mi); } while ((pi = profile->pin_list) != NULL) { profile->pin_list = pi->next; if (pi->file_name) free(pi->file_name); free(pi); } if (profile->p15_spec) sc_pkcs15_card_free(profile->p15_spec); memset(profile, 0, sizeof(*profile)); free(profile); }
int card_sync_virtual_fs_to_card_any_df( sc_card_t *card, struct _virtual_file_t *virtual_file, virtual_fs_t *virtual_fs, int type ) { int r = SC_SUCCESS; sc_pkcs15_card_t *temp_pkcs15_card = NULL; sc_pkcs15_object_t *obj = NULL; card_pkcs15_df_t p15_df; sc_pkcs15_df_t df; u8 *translated_buf = NULL; size_t translated_bufsize = 0; u8 *card_buf = NULL; size_t card_bufsize = 0; SC_FUNC_CALLED(card->ctx, 1); if(!card || !virtual_file) return SC_ERROR_INVALID_ARGUMENTS; /* init p15_df structure */ memset(&p15_df, 0, sizeof(p15_df)); p15_df.type = type; /* virtualfs keeps buffer ownership */ p15_df.data = virtual_file->data; p15_df.data_len = virtual_file->data_size; p15_df.file_len = virtual_file->data_size; p15_df.filled_len = virtual_file->data_size; /* We parse PKCS#15 using a standard parser */ r = card_parse_standard_pkcs15(card, &p15_df, &df, &temp_pkcs15_card); if(r != SC_SUCCESS) { if (card->ctx->debug) sc_debug(card->ctx,SC_LOG_DEBUG_VERBOSE, "Parsing of standard PKCS#15 failed\n"); goto end; } /* we need to correct some PKCS#15 data */ for(obj = temp_pkcs15_card->obj_list; obj != NULL; obj = obj->next) { switch(obj->type & SC_PKCS15_TYPE_CLASS_MASK) { case SC_PKCS15_TYPE_CERT: { r = card_sync_virtual_fs_to_card_filter_cert(card, virtual_file, virtual_fs, obj); } break; case SC_PKCS15_TYPE_PRKEY: { r = card_sync_virtual_fs_to_card_filter_prkey(card, virtual_file, virtual_fs, obj); } break; case SC_PKCS15_TYPE_PUBKEY: { r = card_sync_virtual_fs_to_card_filter_pukey(card, virtual_file, virtual_fs, obj); } break; default: /* ignore this object */ break; } } if(r != SC_SUCCESS) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Object filtering failed\n"); goto end; } /* We encode PKCS#15 using DNIe PKCS#15 */ r = sc_pkcs15_card_encode_df(card->ctx, temp_pkcs15_card, &df, &translated_buf, &translated_bufsize); if(r != SC_SUCCESS) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "DNIe PKCS#15 encoding failed\n"); goto end; } card_bufsize = translated_bufsize+1; card_buf = (u8 *) malloc(card_bufsize); if(!card_buf) { r = SC_ERROR_OUT_OF_MEMORY; goto end; } memcpy(card_buf, translated_buf, translated_bufsize); card_buf[translated_bufsize] = 0x00; r = card_helper_update_file( card, &virtual_file->path, card_buf, card_bufsize); if(r != SC_SUCCESS) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "DNIe PKCS#15 encoding failed\n"); goto end; } end: if(translated_buf) { memset(translated_buf, 0, translated_bufsize); free(translated_buf); translated_buf = NULL; translated_bufsize = 0; } if(card_buf) { memset(card_buf, 0, card_bufsize); free(card_buf); card_buf = NULL; card_bufsize = 0; } if(temp_pkcs15_card) { /* set to NULL without freeing because we reused structure */ temp_pkcs15_card->card = NULL; /* now free temp structure */ sc_pkcs15_card_free(temp_pkcs15_card); temp_pkcs15_card = NULL; } SC_FUNC_RETURN(card->ctx, 1, r); }
int card_sync_card_to_virtual_fs_any_df( sc_card_t *card, struct _virtual_file_t *virtual_file, virtual_fs_t *virtual_fs, int type ) { int r = SC_SUCCESS; unsigned char *encoded_pkcs15 = NULL; size_t encoded_pkcs15_size = 0; sc_pkcs15_card_t *temp_pkcs15_card = NULL; sc_pkcs15_object_t *obj = NULL; unsigned char *card_data = NULL; size_t card_data_length = 0; SC_FUNC_CALLED(card->ctx, 1); if(!card || !virtual_file) return SC_ERROR_INVALID_ARGUMENTS; /* get file */ r = card_helper_read_file(card, &virtual_file->path, &card_data, &card_data_length); if(r < 0) goto end; /* create a new pkcs15_card structure */ temp_pkcs15_card = sc_pkcs15_card_new(); if(!temp_pkcs15_card) { r = SC_ERROR_OUT_OF_MEMORY; goto end; } /* we set some important fields */ temp_pkcs15_card->card = card; temp_pkcs15_card->file_app = sc_file_new(); if (!temp_pkcs15_card->file_app) { r = SC_ERROR_OUT_OF_MEMORY; goto end; } sc_format_path("3F00", &temp_pkcs15_card->file_app->path); temp_pkcs15_card->tokeninfo->flags=SC_PKCS15_TOKEN_PRN_GENERATION | SC_PKCS15_TOKEN_EID_COMPLIANT; /* Convert card df read to a list of same type of pkcs15 objects. This function uses our internal card decoding parser. */ r = sc_pkcs15_parse_card_df( temp_pkcs15_card, type, card_data, card_data_length ); if(r != SC_SUCCESS) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Card parsing failed\n"); goto end; } /* we need to correct some PKCS#15 data */ for(obj = temp_pkcs15_card->obj_list; obj != NULL; obj = obj->next) { switch(obj->type & SC_PKCS15_TYPE_CLASS_MASK) { case SC_PKCS15_TYPE_CERT: r = card_sync_card_to_virtual_fs_filter_cert(card, virtual_file, virtual_fs, obj); break; case SC_PKCS15_TYPE_PRKEY: r = card_sync_card_to_virtual_fs_filter_prkey(card, virtual_file, virtual_fs, obj); break; case SC_PKCS15_TYPE_PUBKEY: r = card_sync_card_to_virtual_fs_filter_pukey(card, virtual_file, virtual_fs, obj); break; case SC_PKCS15_TYPE_AUTH: if(obj->data) { sc_pkcs15_pin_info_t * pin=obj->data; /* remove security officer pin */ pin->flags &= (~SC_PKCS15_PIN_FLAG_SO_PIN); sc_format_path("3F00", &pin->path); pin->stored_length= (pin->max_length>pin->stored_length) ? pin->max_length : pin->stored_length; } break; case SC_PKCS15_TYPE_DATA_OBJECT: r = card_sync_card_to_virtual_fs_filter_data_object(card, virtual_file, virtual_fs, obj); break; default: /* ignore this object */ break; } } if(r != SC_SUCCESS) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Object filtering failed\n"); goto end; } /* generate pkcs#15 stream for the appropiate object type */ r = sc_standard_pkcs15_encode_any_df( card->ctx, temp_pkcs15_card, type, /* encode only specific objects type */ &encoded_pkcs15, &encoded_pkcs15_size ); if(r != SC_SUCCESS) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Standard PKCS#15 encoding failed\n"); goto end; } r = virtual_file_data_update(virtual_file, 0, encoded_pkcs15, encoded_pkcs15_size); if(r == SC_SUCCESS) { /* add a trailing 0 */ r = virtual_file_data_update(virtual_file, encoded_pkcs15_size, (const unsigned char *)"\0", 1); } end: if(card_data) { free(card_data); card_data = NULL; } if(temp_pkcs15_card) { /* set to NULL without freeing because we reused structure */ temp_pkcs15_card->card = NULL; /* now free temp structure */ sc_pkcs15_card_free(temp_pkcs15_card); temp_pkcs15_card = NULL; } if(encoded_pkcs15) { free(encoded_pkcs15); encoded_pkcs15 = NULL; } SC_FUNC_RETURN(card->ctx, 1, r); }
int sc_pkcs15_bind(sc_card_t *card, struct sc_pkcs15_card **p15card_out) { struct sc_pkcs15_card *p15card = NULL; sc_context_t *ctx; scconf_block *conf_block = NULL, **blocks; int i, r, emu_first, enable_emu; assert(sc_card_valid(card) && p15card_out != NULL); ctx = card->ctx; SC_FUNC_CALLED(ctx, 1); p15card = sc_pkcs15_card_new(); if (p15card == NULL) return SC_ERROR_OUT_OF_MEMORY; p15card->card = card; for (i = 0; ctx->conf_blocks[i] != NULL; i++) { blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i], "framework", "pkcs15"); if (blocks && blocks[0] != NULL) conf_block = blocks[0]; free(blocks); } if (conf_block) { p15card->opts.use_cache = scconf_get_bool(conf_block, "use_caching", 0); } r = sc_lock(card); if (r) { sc_error(ctx, "sc_lock() failed: %s\n", sc_strerror(r)); sc_pkcs15_card_free(p15card); SC_FUNC_RETURN(ctx, 1, r); } enable_emu = scconf_get_bool(conf_block, "enable_pkcs15_emulation", 1); if (enable_emu) { emu_first = scconf_get_bool(conf_block, "try_emulation_first", 0); if (emu_first || sc_pkcs15_is_emulation_only(card)) { r = sc_pkcs15_bind_synthetic(p15card); if (r == SC_SUCCESS) goto done; r = sc_pkcs15_bind_internal(p15card); if (r < 0) goto error; } else { r = sc_pkcs15_bind_internal(p15card); if (r == SC_SUCCESS) goto done; r = sc_pkcs15_bind_synthetic(p15card); if (r < 0) goto error; } } else { r = sc_pkcs15_bind_internal(p15card); if (r < 0) goto error; } done: *p15card_out = p15card; sc_unlock(card); return 0; error: sc_unlock(card); sc_pkcs15_card_free(p15card); SC_FUNC_RETURN(ctx, 1, r); }
int card_helper_create_cert_file(sc_card_t *card, struct _virtual_file_t *virtual_file, size_t fcert_len, struct _virtual_file_t **certificate_virtual_file) { int r = SC_SUCCESS; sc_path_t fcert_path; sc_pkcs15_unusedspace_t *unused_space=NULL; sc_pkcs15_card_t *temp_p15card = NULL; int old_use_virtual_fs; /*!< backup of use_virtual_fs */ assert(card!=NULL && virtual_file!=NULL && certificate_virtual_file!=NULL); SC_FUNC_CALLED(card->ctx, 1); /* we backup use_virtual_fs */ old_use_virtual_fs = card_is_virtual_fs_active(card); /* we want to use card without virtual fs */ card_set_virtual_fs_state(card, 0); if(*certificate_virtual_file) { virtual_file_free(*certificate_virtual_file); *certificate_virtual_file = NULL; } memset(&fcert_path, 0, sizeof(struct sc_path)); /* 2. Look for a suitable file on UnusedSpace struct which fits the final certificate file size. 2.1 If found, take file's path to reuse it. 2.2 If not, create a file on Certificate Directory with final certificate len as its size */ /* we create a fake p15card structure */ temp_p15card = sc_pkcs15_card_new(); temp_p15card->card = card; r = sc_find_free_unusedspace( temp_p15card, fcert_len, &unused_space ); if (r!=SC_SUCCESS) goto chccf_end; if(unused_space) { /* we got a path */ r = sc_path_set_dnie ( &fcert_path, unused_space->path.type, unused_space->path.value, unused_space->path.len, unused_space->path.index, unused_space->path.count ); if (r!=SC_SUCCESS) goto chccf_end; } else { sc_path_t temp_path; /* move to certificate DF */ sc_format_path("3F006061", &temp_path); r = card_select_file(card, &temp_path, NULL); if(r != SC_SUCCESS) goto chccf_end; /* we start at 0x7001 file ID */ sc_format_path("7001", &fcert_path); do { r = card_create_cert_file( card, &fcert_path, fcert_len ); if (r == SC_ERROR_OBJECT_ALREADY_EXISTS) { fcert_path.value[1]++; } if(r!=SC_SUCCESS && r!=SC_ERROR_OBJECT_ALREADY_EXISTS) goto chccf_end; } while (r!=SC_SUCCESS); r = SC_SUCCESS; } /* create certificate file into vfs */ r = virtual_fs_append_new_virtual_file( DRVDATA(card)->virtual_fs, &fcert_path, virtual_file->data, virtual_file->data_size, virtual_file->data_size, 1, virtual_file_sync_state_synced, card_sync_card_to_virtual_fs_certificate_file_callback, virtual_file_sync_state_sync_pending, card_sync_virtual_fs_to_card_certificate_file_callback ); if(r != SC_SUCCESS) goto chccf_end; /* retrieve just created virtual file */ *certificate_virtual_file = virtual_fs_find_by_path( DRVDATA(card)->virtual_fs, &fcert_path ); chccf_end: /* we restore use_virtual_fs */ card_set_virtual_fs_state(card, old_use_virtual_fs); if (unused_space) { /* Delete UnusedSpace object if reused and also frees reserved memory */ sc_pkcs15_remove_unusedspace(temp_p15card, unused_space); } if (temp_p15card) { /* set to NULL without freeing because we reused structure */ temp_p15card->card = NULL; /* now free temp structure */ sc_pkcs15_card_free(temp_p15card); temp_p15card = NULL; } SC_FUNC_RETURN(card->ctx, 1, r); }