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);
}
Beispiel #6
0
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); 
}