Пример #1
0
int sc_pkcs15_parse_unusedspace(const u8 * buf, size_t buflen, struct sc_pkcs15_card *card)
{
	const u8 *p = buf;
	size_t left = buflen;
	int r;
	sc_path_t path, dummy_path;
	sc_pkcs15_id_t auth_id;
	struct sc_asn1_entry asn1_unusedspace[] = {
		{ "UnusedSpace", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
		{ NULL, 0, 0, 0, NULL, NULL }
	};
	struct sc_asn1_entry 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 }
	};

	/* Clean the list if already present */
	while (card->unusedspace_list)
		sc_pkcs15_remove_unusedspace(card, card->unusedspace_list);

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

	sc_format_asn1_entry(asn1_unusedspace, asn1_unusedspace_values, NULL, 1);
	sc_format_asn1_entry(asn1_unusedspace_values, &path, NULL, 1);
	sc_format_asn1_entry(asn1_unusedspace_values+1, &auth_id, NULL, 0);

	while (left > 0) {
		memset(&auth_id, 0, sizeof(auth_id));
		r = sc_asn1_decode(card->card->ctx, asn1_unusedspace, p, left, &p, &left);
		if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
			break;
		if (r < 0)
			return r;
		/* If the path length is 0, it's a dummy path then don't add it.
		 * If the path length isn't included (-1) then it's against the standard
		 *   but we'll just ignore it instead of returning an error. */
		if (path.count > 0) {
			r = sc_pkcs15_make_absolute_path(&card->file_app->path, &path);
			if (r < 0)
				return r;
			r = sc_pkcs15_add_unusedspace(card, &path, &auth_id);
			if (r)
				return r;
		}
	}

	card->unusedspace_read = 1;

	return 0;
}
Пример #2
0
void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card)
{
	if (p15card == NULL)
		return;
	assert(p15card->magic == SC_PKCS15_CARD_MAGIC);
	while (p15card->obj_list)
		sc_pkcs15_remove_object(p15card, p15card->obj_list);
	while (p15card->df_list)
		sc_pkcs15_remove_df(p15card, p15card->df_list);
	while (p15card->unusedspace_list)
		sc_pkcs15_remove_unusedspace(p15card, p15card->unusedspace_list);
	p15card->unusedspace_read = 0;
	if (p15card->file_app != NULL)
		sc_file_free(p15card->file_app);
	if (p15card->file_tokeninfo != NULL)
		sc_file_free(p15card->file_tokeninfo);
	if (p15card->file_odf != NULL)
		sc_file_free(p15card->file_odf);
	if (p15card->file_unusedspace != NULL)
		sc_file_free(p15card->file_unusedspace);
	p15card->magic = 0;
	if (p15card->label != NULL)
		free(p15card->label);
	if (p15card->serial_number != NULL)
		free(p15card->serial_number);
	if (p15card->manufacturer_id != NULL)
		free(p15card->manufacturer_id);
	if (p15card->last_update != NULL)
		free(p15card->last_update);
	if (p15card->preferred_language != NULL)
		free(p15card->preferred_language);
	if (p15card->seInfo != NULL) {
		size_t i;
		for (i = 0; i < p15card->num_seInfo; i++)
			free(p15card->seInfo[i]);
		free(p15card->seInfo);
	}
	free(p15card);
}
Пример #3
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;
}
Пример #4
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); 
}