예제 #1
0
/*
 * Initialize profile
 */
struct sc_profile *
sc_profile_new(void)
{
	struct sc_pkcs15_card *p15card;
	struct sc_profile *pro;

	pro = (struct sc_profile *) calloc(1, sizeof(*pro));
	if (pro == NULL)
		return NULL;
	pro->p15_spec = p15card = sc_pkcs15_card_new();

	pro->protect_certificates = 1;
	pro->pkcs15.do_last_update = 1;

	if (p15card) {
		p15card->label = strdup("OpenSC Card");
		p15card->manufacturer_id = strdup("OpenSC Project");
		p15card->serial_number = strdup("0000");
		p15card->flags = SC_PKCS15_CARD_FLAG_EID_COMPLIANT;
		p15card->version = 1;

		/* Set up EF(TokenInfo) and EF(ODF) */
		p15card->file_tokeninfo = init_file(SC_FILE_TYPE_WORKING_EF);
		p15card->file_odf = init_file(SC_FILE_TYPE_WORKING_EF);
		p15card->file_unusedspace = init_file(SC_FILE_TYPE_WORKING_EF);
	}

	/* Assume card does RSA natively, but no DSA */
	pro->rsa_access_flags = DEF_PRKEY_RSA_ACCESS;
	pro->dsa_access_flags = DEF_PRKEY_DSA_ACCESS;
	pro->pin_encoding = 0x01;
	pro->pin_minlen = 4;
	pro->pin_maxlen = 8;
	pro->keep_public_key = 1;

	return pro;
}
예제 #2
0
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);
}
예제 #3
0
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);
}
예제 #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); 
}