Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages | Examples

fake_sim.c

Example of ...
/*
 * fakesim.c - part of Fake SIM application
 *
 * Copyright (C) 2003 BLADOX, s.r.o.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 */

#include <config.h>
#include <turbo/turbo.h>

#include <stdlib.h>
#include <string.h>

/*
TODO
do not reactivate active
*/
   
/* *INDENT-OFF* */

lc_char PROGMEM lc_Fake_sim[]={ 
        LC_EN("Fake SIM")
        LC_END
};

lc_char PROGMEM lc_Default[]={ 
        LC_EN("Default")
        LC_END
};

lc_char PROGMEM lc_Activate[]={ 
        LC_EN("Activate")
        LC_END
};

lc_char PROGMEM lc_Name[]={ 
        LC_EN("Name:")
        LC_END
};

lc_char PROGMEM lc_Ki[]={ 
        LC_UN("Ki:")
        LC_END
};

lc_char PROGMEM lc_IMSI[]={ 
        LC_UN("IMSI:")
        LC_END
};

/* *INDENT-ON* */

void A3A8 (u8 key[16], u8 rand[16], u8 simoutput[12]);

u8 PROGMEM ef_imsi_path[] = { 0x3F, 0x00, 0x7F, 0x20, 0x6F, 0x07 };

typedef struct _Fake_sim
{
  u8 imsi[9];
  u8 ki[16];
}
Fake_sim;

typedef struct _sims_mem
{
  SEdge *sims;
  Fake_sim *cur_sim;
}
sims_mem;

SEdge *sims;
Fake_sim *cur_sim;
u8 *get_resp_gsm;

u8 PROGMEM _ef_imsi[] = {
  0x00, 0x00, 0x00, 0x09, 0x6F, 0x07, 0x04, 0x00, 
  0x14, 0x00, 0x14, 0x01, 0x01, 0x00, 0x00
};

void fake_sim_file (File_apdu_data * fa)
{
  u8 i;

  dbsp ("FAKE_SIM_FILE\n");

  dbsp ("EF ");
  dbih (fa->ef);
  dbc ('\n');

  if (fa->ins == ME_CMD_SELECT)
  {
    u16 ef = (fa->data[0] << 8) | fa->data[1];

    if (ef == 0x6F07)
    {
      dbsp ("FAKE_IMSI_SELECT\n");
      fa->data[0] = 0x9F;
      fa->data[1] = 0x0F;
    }
    return;
  }

  if (fa->prev_ins == ME_CMD_SELECT && fa->ef == 0x6F07)
  {
    dbsp ("FAKE_IMSI\n");
    if (fa->ins == ME_CMD_GET_RESPONSE)
    {
      memcpy (fa->data, _ef_imsi, sizeof (_ef_imsi));
      fa->data[fa->p3] = 0x90;
      fa->data[fa->p3 + 1] = 0x00;
    }
    if (fa->ins == ME_CMD_READ_BINARY)
    {
      memcpy (fa->data, &cur_sim->imsi, 9);
      fa->data[fa->p3] = 0x90;
      fa->data[fa->p3 + 1] = 0x00;
    }
  }
  if (fa->prev_ins == ME_CMD_RUN_GSM_ALGORITHM
      && fa->ins == ME_CMD_GET_RESPONSE)
  {
    dbsp ("FAKE_GSM_GET_RESP\n");
    memcpy (fa->data, get_resp_gsm, 0x0c);
    fa->data[0x0c] = 0x90;
    fa->data[0x0d] = 0x00;
    free (get_resp_gsm);
    get_resp_gsm = NULL;
  }
}

void run_gsm (File_apdu_data * fa)
{
  u8 key[16];
  u8 i;
  u8 s[16];

  dbsp (">fake_sim_run_gsm\n");
  memcpy (s, fa->data, 16);
  get_resp_gsm = malloc (12);
  for (i = 0; i < 16; i++)
    key[i] = rb (&cur_sim->ki[i]);

#ifdef DEBUG
  dbsp ("KEY :");
  for (i = 0; i < 16; i++)
  {
    dbch (key[i]);
    dbc (' ');
  }
  dbc ('\n');
#endif
  
  A3A8 (key, s, get_resp_gsm);

#ifdef DEBUG
  dbsp ("RES :");
  for (i = 0; i < 16; i++)
  {
    dbch (get_resp_gsm[i]);
    dbc (' ');
  }
  dbc ('\n');
#endif
  
  //buf for get_resp
  fa->data[0] = 0x9f;
  fa->data[1] = 0x0c;
  dbsp ("<fake_sim_run_gsm\n");
}

b16 hextoint (char x)
{
  if (x >= 'a' && x <= 'f')
    return x - 'a' + 10;
  else if (x >= 'A' && x <= 'F')
    return x - 'A' + 10;
  else if (x >= '0' && x <= '9')
    return x - '0';
  return -1;
}

SNodeP fake_sim_n;
SNodeP fake_sim_n_3;
SNodeP fake_sim_n_4;
SNodeP fake_sim_n_5;
SNodeP fake_sim_n_6;

u8 fake_sim_ctx (SCtx * ctx, u8 action)
{
  if (action == APP_ENTER)
  {
    dbsp (">fake_sim_ctx\n");
    spider_append_r (ctx, &fake_sim_n_5);
    spider_append_r (ctx, &fake_sim_n_3);
    dbsp ("<fake_sim_ctx\n");
  }
  else if (action == APP_LEAVE)
  {
    spider_clear_r (ctx);
  }
}

u8 *insert_sim (u8 * name, u8 imsi[9], u8 ki[16])
{
  Fake_sim *s;
  SNode *n;
  SEdge *e;
  u8 *t;
  u8 l = strlen (name) + 1;
  sims_mem *p;

  dbsp (">insert_sim\n");
  s = emalloc (sizeof (Fake_sim));
  if (s == NULL)
    return NULL;
  n = emalloc (sizeof (SNode));
  if (n == NULL)
    goto X1;
  e = emalloc (sizeof (SEdge));
  if (e == NULL)
    goto X2;
  t = emalloc (l);
  if (t == NULL)
    goto X3;

  memcpy (&s->imsi, imsi, 9);
  memcpy (&s->ki, ki, 16);

  memcpy (t, name, l);
  ww (&n->text, t);
  ww (&n->cb, fake_sim_ctx);
  ww (&n->p, s);

  ww (&e->f, &fake_sim_n);
  ww (&e->t, n);
  wb (&e->source, MEM_F_P | MEM_T_E);
  ww (&e->next, sims);
  sims = e;
  p = app_data ();
  ww (&p->sims, sims);
  dbsp ("<insert_sim\n");
  return s;
X3:
  dbsp ("<insert_sim_3\n");
  efree (e);
X2:
  dbsp ("<insert_sim_2\n");
  efree (n);
X1:
  dbsp ("<insert_sim_1\n");
  efree (s);
  return NULL;
}

u8 fake_sim_new (SCtx * ctx, u8 action)
{
  if (action == APP_ENTER)
  {
    u8 i, j, k;
    u8 name[16];
    u8 imsi[9];
    u8 ki[16];
    u8 *res;
    b16 x;

    // name
    res = get_input (locale (lc_Name), 1, 15, NULL, Q_GET_INPUT_ALPHABET);
    if (res == ENULL)
      return APP_END;
    if (res == NULL)
      return APP_BACK;
    j = res[0] - 1;
    res++;                      //len
    res++;                      //dcs
    memcpy (name, res, j);
    name[j] = '\0';

    // IMSI
  X3:
    res = get_input (locale (lc_IMSI), 18, 18, NULL, Q_GET_INPUT_ALPHABET);
    if (res == ENULL)
      return APP_END;
    if (res == NULL)
      return APP_BACK;
    j = res[0] - 1;
    res++;                      //len
    res++;                      //dcs
    for (i = 0; i < 9; i++)
    {
      x = hextoint (res[2 * i]);
      if (x == -1)
      {
        perror (ERR_BAD_INPUT);
        goto X3;
      }
      j = x << 4;
      x = hextoint (res[2 * i + 1]);
      if (x == -1)
      {
        perror (ERR_BAD_INPUT);
        goto X3;
      }
      k = x;
      imsi[i] = j | k;
    }

    // Ki
  X4:
    res = get_input (locale (lc_Ki), 32, 32, NULL, Q_GET_INPUT_ALPHABET);
    if (res == ENULL)
      return APP_END;
    if (res == NULL)
      return APP_BACK;
    j = res[0] - 1;
    res++;                      //len
    res++;                      //dcs
    for (i = 0; i < 16; i++)
    {
      x = hextoint (res[2 * i]);
      if (x == -1)
      {
        perror (ERR_BAD_INPUT);
        goto X3;
      }
      j = x << 4;
      x = hextoint (res[2 * i + 1]);
      if (x == -1)
      {
        perror (ERR_BAD_INPUT);
        goto X3;
      }
      k = x;
      ki[i] = j | k;
    }
    // SMSC...
    res = insert_sim (name, imsi, ki);
    if (res == NULL)
      perror (ERR_NO_EEPROM);
    else
      ctx->eE = sims;
    return APP_BACK;
  }
}

u8 fake_sim_activate_default (SCtx * ctx, u8 action)
{
  if (action == APP_ENTER)
  {
    unreg_file (ef_imsi_path, 3);
    unreg_action (ACTION_RUN_GSM_ALGORITHM);
    cur_sim = 0;
    ww (&((sims_mem *) app_data ())->cur_sim, cur_sim);
    change_imsi ();
    return APP_BACK;
  }
}

u8 fake_sim_delete (SCtx * ctx, u8 action)
{
}

u8 fake_sim_activate (SCtx * ctx, u8 action)
{
  if (action == APP_ENTER)
  {
    if (cur_sim == 0)
    {
      reg_file (ef_imsi_path, 3);
      reg_action (ACTION_RUN_GSM_ALGORITHM);
    }
    cur_sim = rw (&ctx->parent->f->p);
    ww (&((sims_mem *) app_data ())->cur_sim, cur_sim);
    change_imsi ();
    return APP_BACK;
  }
}

u8 fake_sim_view (SCtx * ctx, u8 action)
{
  if (action == APP_ENTER)
  {
    u8 *s = buf_B ();
    u8 *r = s;
    u8 i;
    u8 l;
    Fake_sim *sim;

    sim = rw (&ctx->parent->f->p);
    r = sprints (r, locale (lc_IMSI));
    r = sprintc (r, '\n');
    for (i = 0; i < 9; i++)
    {
      r = sprintch (r, rb (&sim->imsi[i]));
    }
    r = sprintc (r, '\n');
    r = sprints (r, locale (lc_Ki));
    r = sprintc (r, '\n');
    for (i = 0; i < 16; i++)
    {
      r = sprintch (r, rb (&sim->ki[i]));
    }
    r = sprintc (r, '\0');
    if (display_text (s, NULL) == APP_END)
      return APP_END;
    return APP_BACK;
  }
}

u8 fake_sim_edit (SCtx * ctx, u8 action)
{
}

SNodeP fake_sim_n = { lc_Fake_sim, NULL };
SNodeP fake_sim_n_1 = { LC_NEW, fake_sim_new };
SNodeP fake_sim_n_2 = { lc_Default, NULL };
SNodeP fake_sim_n_3 = { lc_Activate, fake_sim_activate };
SNodeP fake_sim_n_4 =
  { LC_DELETE, not_implemented /*fake_sim_delete */  };
SNodeP fake_sim_n_5 = { LC_VIEW, fake_sim_view };
SNodeP fake_sim_n_6 = { LC_EDIT, not_implemented /*fake_sim_edit */  };
SNodeP fake_sim_n_7 = { lc_Activate, fake_sim_activate_default };

SEdgeP fake_sim_edges_p[]={
        {&fake_sim_n,&fake_sim_n_1},    // Fake_sim->New
        {&fake_sim_n,&fake_sim_n_2},    // Fake_sim->Default
        {&fake_sim_n_2,&fake_sim_n_7},  // Default->Activate
        NULL
};

void fake_sim (void *x)
{
  SCtx *c = spider_init ();

  if (c == NULL)
    return;

  c->n = &fake_sim_n;
  c->eP = &fake_sim_edges_p;
  c->eE = sims;

  spider (c);
}

void turbo_handler (u8 action, void *data)
{
  switch (action)
  {
    case ACTION_APP_REGISTER:
      {
        sims_mem *p = emalloc (sizeof (sims_mem));

        sims = 0;
        ww (&p->sims, 0);
        ww (&p->cur_sim, 0);
        reg_app_data (p);
      }
      break;
    case ACTION_APP_UNREGISTER:
      {
        SEdge *e = sims;
        SNode *n;

        while (e != NULL)
        {
          n = rw (&e->t);
          efree (rw (&n->p));
          efree (rw (&n->text));
          efree (n);
          sims = e;
          e = rw (&sims->next);
          efree (sims);
        }
      }
      break;
    case ACTION_APP_INIT:
      {
        sims_mem *p = app_data ();

        sims = rw (&p->sims);
        cur_sim = rw (&p->cur_sim);
        if (cur_sim)
        {
          reg_file (ef_imsi_path, 3);
          reg_action (ACTION_RUN_GSM_ALGORITHM);
        }
      }
      break;
    case ACTION_INSERT_MENU:
      insert_menu (locale (lc_Fake_sim));
      break;
    case ACTION_MENU_SELECTION:
      stk_thread (fake_sim, NULL);
      break;
    case ACTION_RUN_GSM_ALGORITHM:
      run_gsm (data);
      break;
    case ACTION_FILE_APDU:
      fake_sim_file (data);
      break;
    default:
      break;
  }
}


Copyright © 2004-2006 BLADOX
Turbo version 1.2