static int select_key_file(struct sc_pkcs15_card *p15card,
                           const struct sc_pkcs15_prkey_info *prkey,
                           sc_security_env_t *senv)
{
    sc_path_t path, file_id;
    int r;

    if (prkey->path.len < 2)
        return SC_ERROR_INVALID_ARGUMENTS;
    /* For pkcs15-emulated cards, the file_app may be NULL,
       in that case we allways assume an absolute path */
    if (prkey->path.len == 2 && p15card->file_app != NULL) {
        /* Path is relative to app. DF */
        path = p15card->file_app->path;
        file_id = prkey->path;
        sc_append_path(&path, &file_id);
    } else {
        path = prkey->path;
        memcpy(file_id.value, prkey->path.value + prkey->path.len - 2, 2);
        file_id.len = 2;
        file_id.type = SC_PATH_TYPE_FILE_ID;
    }
    senv->file_ref = file_id;
    senv->flags |= SC_SEC_ENV_FILE_REF_PRESENT;
    r = sc_select_file(p15card->card, &path, NULL);
    SC_TEST_RET(p15card->card->ctx, r, "sc_select_file() failed");

    return 0;
}
Example #2
0
static int select_key_file(struct sc_pkcs15_card *p15card,
			   const struct sc_pkcs15_prkey_info *prkey,
			   sc_security_env_t *senv)
{
	sc_context_t *ctx = p15card->card->ctx;
	sc_path_t path, file_id;
	int r;

	LOG_FUNC_CALLED(ctx);

	memset(&path, 0, sizeof(sc_path_t));
	memset(&file_id, 0, sizeof(sc_path_t));

	/* TODO: Why file_app may be NULL -- at least 3F00 has to be present?
	 * Check validity of the following assumption. */
	/* For pkcs15-emulated cards, the file_app may be NULL,
	   in that case we allways assume an absolute path */
	if (!prkey->path.len && prkey->path.aid.len)   {
		/* Private key is a SDO allocated in application DF */
		path = prkey->path;
	}
	else if (prkey->path.len == 2 && p15card->file_app != NULL) {
		/* Path is relative to app. DF */
		path = p15card->file_app->path;
		file_id = prkey->path;
		sc_append_path(&path, &file_id);
		senv->file_ref = file_id;
		senv->flags |= SC_SEC_ENV_FILE_REF_PRESENT;
	}
	else if (prkey->path.len > 2)   {
		path = prkey->path;
		memcpy(file_id.value, prkey->path.value + prkey->path.len - 2, 2);
		file_id.len = 2;
		file_id.type = SC_PATH_TYPE_FILE_ID;
		senv->file_ref = file_id;
		senv->flags |= SC_SEC_ENV_FILE_REF_PRESENT;
	}
	else   {
		LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "invalid private key path");
	}

	r = sc_select_file(p15card->card, &path, NULL);
	LOG_TEST_RET(ctx, r, "sc_select_file() failed");

	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
int card_sync_card_to_virtual_fs_filter_cert( sc_card_t *card, struct _virtual_file_t *virtual_file, virtual_fs_t *virtual_fs, sc_pkcs15_object_t *obj )
{
  int r = SC_SUCCESS;
  struct sc_pkcs15_cert_info *cert = NULL;
  unsigned char *card_data = NULL;
  virtual_file_t  *certificate_virtual_file = NULL;
  virtual_file_t  *certificate_virtual_file_weak_link = NULL; 
  sc_path_t abs_cert_path, cert_card_path;

  SC_FUNC_CALLED(card->ctx, 1);

  /* we need to correct certificate length in path */
  cert = (struct sc_pkcs15_cert_info *) obj->data;
  if(cert) {
    /* set asn1 to map */
    r = map_id_to_der_set_item(DRVDATA(card)->cdf_card_ckaid_to_card_der_map, &cert->id, &obj->content);
    if(r != SC_SUCCESS)
      goto end;
    
    if(cert->path.len > 0) {
      certificate_virtual_file = virtual_file_new();
      if(!certificate_virtual_file) {
	r = SC_ERROR_OUT_OF_MEMORY;
	goto end;
      }
      
      memset(&abs_cert_path, 0, sizeof(struct sc_path));
      memset(&cert_card_path, 0, sizeof(struct sc_path));

      if(cert->path.len==2) {
	sc_format_path("3F005015", &abs_cert_path);
	r = sc_append_path(&abs_cert_path, &cert->path);
	if(r!=SC_SUCCESS)
	  goto end;
	sc_format_path("3F006061", &cert_card_path);
	r = sc_append_path(&cert_card_path, &cert->path);
	if(r!=SC_SUCCESS)
	  goto end;
      } else if(cert->path.len==4) {
	sc_format_path("3F00", &abs_cert_path);
	r = sc_append_path(&abs_cert_path, &cert->path);
	if(r!=SC_SUCCESS)
	  goto end;
	sc_format_path("3F00", &cert_card_path);
	r = sc_append_path(&cert_card_path, &cert->path);
	if(r!=SC_SUCCESS)
	  goto end;
        memcpy(cert->path.value, cert_card_path.value, cert_card_path.len);
        cert->path.len = 6;
      } else { 
	r = sc_append_path(&abs_cert_path, &cert->path);
	if(r!=SC_SUCCESS)
	  goto end;
	if(abs_cert_path.len==6) {
	  r = sc_append_path(&cert_card_path, &cert->path);
	  if(r!=SC_SUCCESS)
	    goto end;
	}
      }

      memcpy(&certificate_virtual_file->path, &abs_cert_path, sizeof(certificate_virtual_file->path));
      r = map_path_to_path_set_item(DRVDATA(card)->virtual_fs_to_card_path_map, &certificate_virtual_file->path, &cert_card_path);
      if(r != SC_SUCCESS)
	goto end;
      certificate_virtual_file->is_ef = 1;

      certificate_virtual_file->card_to_virtual_fs.sync_state = virtual_file_sync_state_sync_pending;
      certificate_virtual_file->card_to_virtual_fs.sync_callback = card_sync_card_to_virtual_fs_certificate_file_callback;
      certificate_virtual_file->virtual_fs_to_card.sync_state = virtual_file_sync_state_unknown;
      certificate_virtual_file->virtual_fs_to_card.sync_callback = NULL;
      
      /* append file to virtual_fs */
      r = virtual_fs_append(virtual_fs, certificate_virtual_file);
      if(r != SC_SUCCESS)
	goto end;

      /* we don't have ownership of virtual_file now,
	 so we don't need to free it */
      certificate_virtual_file_weak_link = certificate_virtual_file;
      certificate_virtual_file = NULL;
        
      /* we now synchronize file because this gets a correct size for it */
      r = virtual_file_data_synchronize(certificate_virtual_file_weak_link, card, virtual_file_sync_type_card_to_virtual_fs, DRVDATA(card)->virtual_fs);
      if (r != SC_SUCCESS) {
	sc_debug(card->ctx,SC_LOG_DEBUG_NORMAL,  "Synchronization failed\n");
	goto end;
      }
      
      /* correct length in PKCS#15 */
      cert->path.count = certificate_virtual_file_weak_link->data_size;
    } else {
      sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,"Path length is 0");
    }
  } else {
    sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,"Pointer to cert info was empty");
  }

 end:
  if(card_data) {
    free(card_data);
    card_data = NULL;
  }

  if(certificate_virtual_file) {
    virtual_file_free(certificate_virtual_file);
    certificate_virtual_file = NULL;
  }

  SC_FUNC_RETURN(card->ctx, 1, r);
}
int card_sync_card_to_virtual_fs_filter_data_object( sc_card_t *card, struct _virtual_file_t *virtual_file, virtual_fs_t *virtual_fs, sc_pkcs15_object_t *obj )
{
  int r = SC_SUCCESS;
  struct sc_pkcs15_data_info *data = NULL;
  unsigned char *card_data = NULL;
  virtual_file_t  *data_virtual_file = NULL;
  virtual_file_t  *data_virtual_file_weak_link = NULL; 
  sc_path_t abs_data_path, data_card_path, def_path;

  SC_FUNC_CALLED(card->ctx, 1);

  /* we need to correct certificate length in path */
  data = (struct sc_pkcs15_data_info *) obj->data;
  if(data) {    
    if(data->path.len > 0) {
      data_virtual_file = virtual_file_new();
      if(!data_virtual_file) {
	r = SC_ERROR_OUT_OF_MEMORY;
	goto end;
      }

      memset(&abs_data_path, 0, sizeof(struct sc_path));
      memset(&data_card_path, 0, sizeof(struct sc_path));      	
      memset(&def_path, 0, sizeof(struct sc_path));

      
      if(data->path.len == 4) {
        sc_format_path("3F00", &def_path);
   	r = sc_append_path(&def_path, &data->path);

	if(r!=SC_SUCCESS)
	  goto end;

        memcpy(data->path.value, def_path.value, def_path.len);
        data->path.len = 6;

      } else {
        memcpy(&def_path, &data->path, sizeof(data->path));
      }

      r = sc_append_path(&abs_data_path, &def_path);
      if(r!=SC_SUCCESS)
	goto end;

      if(abs_data_path.len==6) {
	r = sc_append_path(&data_card_path, &def_path);
	if(r!=SC_SUCCESS)
	  goto end;
      }      

      memcpy(&data_virtual_file->path, &abs_data_path, sizeof(data_virtual_file->path));
      r = map_path_to_path_set_item(DRVDATA(card)->virtual_fs_to_card_path_map, &data_virtual_file->path, &data_card_path);
      if(r != SC_SUCCESS)
	goto end;
      data_virtual_file->is_ef = 1;

      data_virtual_file->card_to_virtual_fs.sync_state = virtual_file_sync_state_sync_pending;
      data_virtual_file->card_to_virtual_fs.sync_callback = card_sync_card_to_virtual_fs_data_file_callback;
      data_virtual_file->virtual_fs_to_card.sync_state = virtual_file_sync_state_unknown;
      data_virtual_file->virtual_fs_to_card.sync_callback = NULL;
      
      /* append file to virtual_fs */
      r = virtual_fs_append(virtual_fs, data_virtual_file);
      if(r != SC_SUCCESS)
	goto end;

      /* we don't have ownership of virtual_file now,
	 so we don't need to free it */
      data_virtual_file_weak_link = data_virtual_file;
      data_virtual_file = NULL;
        
      /* we now synchronize file because this gets a correct size for it */
      r = virtual_file_data_synchronize(data_virtual_file_weak_link, card, virtual_file_sync_type_card_to_virtual_fs, DRVDATA(card)->virtual_fs);
      if (r != SC_SUCCESS) {
	sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Synchronization failed\n");
	goto end;
      }
      
      /* correct length in PKCS#15 */
      data->path.count = data_virtual_file_weak_link->data_size;
      obj->auth_id.value[0]=0x01;
      obj->auth_id.len=0x01;
    } else {
      sc_debug(card->ctx,SC_LOG_DEBUG_VERBOSE, "Path length is 0");
    }
  } else {
    sc_debug(card->ctx,SC_LOG_DEBUG_VERBOSE, "Pointer to data info was empty");
  }

 end:
  if(card_data) {
    free(card_data);
    card_data = NULL;
  }

  if(data_virtual_file) {
    virtual_file_free(data_virtual_file);
    data_virtual_file = NULL;
  }

  SC_FUNC_RETURN(card->ctx, 1, r);
}
int card_sync_card_to_virtual_fs_filter_pukey( sc_card_t *card, struct _virtual_file_t *virtual_file, virtual_fs_t *virtual_fs, sc_pkcs15_object_t *obj )
{
  int r = SC_SUCCESS;
  struct sc_pkcs15_pubkey_info *pukey = NULL;
  sc_path_t def_path;
  /* This flag identifies the FIRMA public key */
  u8 flag_id[1] = "F";

  SC_FUNC_CALLED(card->ctx, 1);

  memset(&def_path, 0, sizeof(struct sc_path));

  if(!card || !virtual_file)
    return SC_ERROR_INVALID_ARGUMENTS;

  pukey = (struct sc_pkcs15_pubkey_info *) obj->data;
  if(pukey) {
    /* set asn1 to map */
    r = map_id_to_der_set_item(DRVDATA(card)->pukdf_card_ckaid_to_card_der_map, &pukey->id, &obj->content);
    if(r != SC_SUCCESS)
      goto end;


    if(pukey->path.len > 0) {

      if(pukey->path.len == 4) {
        sc_format_path("3F00", &def_path);
   	r = sc_append_path(&def_path, &pukey->path);

	if(r!=SC_SUCCESS)
	  goto end;

        memcpy(pukey->path.value, def_path.value, def_path.len);
        pukey->path.len = 6;

      } else {
        memcpy(&def_path, &pukey->path, sizeof(pukey->path));      
      }

      /* append empty file */
      r = virtual_fs_append_new_virtual_file(virtual_fs, 
					     &def_path, 
					     obj->content.value, 
					     obj->content.len, 
					     obj->content.len, 
					     1, 
					     virtual_file_sync_state_unknown, 
					     NULL, 
					     virtual_file_sync_state_unknown, 
					     NULL);
      if(r != SC_SUCCESS)
	goto end;

      /* correct length in PKCS#15 */
      pukey->path.count = 0;

      /* Fixed key usage for FIRMA public key */
      if(memcmp(pukey->id.value, flag_id, 1)==0)
	pukey->usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;

    } else {
      sc_debug(card->ctx,SC_LOG_DEBUG_VERBOSE, "Path length is 0");
    }
  } else {
    sc_debug(card->ctx,SC_LOG_DEBUG_VERBOSE, "Pointer to pukey info was empty");
  }

 end:
  SC_FUNC_RETURN(card->ctx, 1, r);
}