Exemple #1
0
bool set_otp_zone (int fd, struct octet_buffer *otp_zone)
{

  assert (NULL != otp_zone);

  const unsigned int SIZE_OF_WRITE = 32;
  /* The device must be using an OTP read only mode */

  if (!is_otp_read_only_mode (fd))
    assert (false);

  /* The writes must be done in 32 bytes blocks */

  uint8_t nulls[SIZE_OF_WRITE];
  uint8_t part1[SIZE_OF_WRITE];
  uint8_t part2[SIZE_OF_WRITE];
  struct octet_buffer buf ={};
  wipe (nulls, SIZE_OF_WRITE);
  wipe (part1, SIZE_OF_WRITE);
  wipe (part2, SIZE_OF_WRITE);

  /* Simple check to make sure PACKAGE_VERSION isn't too long */
  assert (strlen (PACKAGE_VERSION) < 10);

  /* Setup the fixed OTP data zone */
  sprintf ((char *)part1, "CRYPTOTRONIX HASHLET REV: A");
  sprintf ((char *)part2, "SOFTWARE VERSION: %s", PACKAGE_VERSION);

  bool success = true;

  buf.ptr = nulls;
  buf.len = sizeof (nulls);

  /* Fill the OTP zone with blanks from their default FFFF */
  success = write32 (fd, OTP_ZONE, 0, buf);

  if (success)
    success = write32 (fd, OTP_ZONE, SIZE_OF_WRITE / sizeof (uint32_t), buf);

  /* Fill in the data */
  buf.ptr = part1;
  CTX_LOG (DEBUG, "Writing: %s", buf.ptr);
  if (success)
    success = write32 (fd, OTP_ZONE, 0, buf);
  buf.ptr = part2;
  CTX_LOG (DEBUG, "Writing: %s", buf.ptr);
  if (success)
    success = write32 (fd, OTP_ZONE, SIZE_OF_WRITE / sizeof (uint32_t), buf);

  /* Lastly, copy the OTP zone into one contiguous buffer.
     Ironically, the OTP can't be read while unlocked. */
  if (success)
    {
      otp_zone->len = SIZE_OF_WRITE * 2;
      otp_zone->ptr = malloc_wipe (otp_zone->len);
      memcpy (otp_zone->ptr, part1, SIZE_OF_WRITE);
      memcpy (otp_zone->ptr + SIZE_OF_WRITE, part2, SIZE_OF_WRITE);
    }
  return success;
}
Exemple #2
0
bool lock (int fd, enum DATA_ZONE zone, uint16_t crc)
{

  uint8_t param1 = 0;
  uint8_t param2[2];
  uint8_t response;
  bool result = false;

  if (is_locked (fd, zone))
    return true;

  memcpy (param2, &crc, sizeof (param2));

  const uint8_t CONFIG_MASK = 0;
  const uint8_t DATA_MASK = 1;

  switch (zone)
    {
    case CONFIG_ZONE:
      param1 |= CONFIG_MASK;
      break;
    case DATA_ZONE:
    case OTP_ZONE:
      param1 |= DATA_MASK;
      break;
    default:
      assert (false);
    }

  struct Command_ATSHA204 c = make_command ();

  set_opcode (&c, COMMAND_LOCK);
  set_param1 (&c, param1);
  set_param2 (&c, param2);
  set_data (&c, NULL, 0);
  set_execution_time (&c, 0, LOCK_AVG_EXEC);

  if (RSP_SUCCESS == process_command (fd, &c, &response, sizeof (response)))
    {
      if (0 == response)
        {
          result = true;
          CTX_LOG (DEBUG, "Lock Successful");
        }
      else
        {
          CTX_LOG (DEBUG, "Lock Failed");
        }
    }


  return result;

}
Exemple #3
0
struct octet_buffer get_random (int fd, bool update_seed)
{
  uint8_t *random = NULL;
  uint8_t param2[2] = {0};
  uint8_t param1 = update_seed ? 0 : 1;
  struct octet_buffer buf = {};

  random = malloc_wipe (RANDOM_RSP_LENGTH);

  struct Command_ATSHA204 c = make_command ();

  set_opcode (&c, COMMAND_RANDOM);
  set_param1 (&c, param1);
  set_param2 (&c, param2);
  set_data (&c, NULL, 0);
  set_execution_time (&c, 0, RANDOM_AVG_EXEC);

  if (RSP_SUCCESS == process_command (fd, &c, random, RANDOM_RSP_LENGTH))
    {
      buf.ptr = random;
      buf.len = RANDOM_RSP_LENGTH;
    }
  else
    CTX_LOG (DEBUG, "Random command failed");

  return buf;



}
Exemple #4
0
void Context::handleSignal(Signal::Type stype) {
    CTX_LOG(info, "Requesting shutdown in response to " << Signal::typeAsString(stype));
    // Try to keep this minimal. Post the shutdown process rather than
    // actually running it here. This makes the extent of the signal
    // handling known completely in this method, whereas calling
    // shutdown can cause a cascade of cleanup.
    ioService->post( std::tr1::bind(&Context::shutdown, this), "Context::shutdown" );
}
Exemple #5
0
void Context::shutdown() {
    CTX_LOG(info, "Handling shutdown request");

    Signal::unregisterHandler(mSignalHandler);

    this->stop();
    for(std::vector<Service*>::iterator it = mServices.begin(); it != mServices.end(); it++)
        (*it)->stop();

    // If the original thread wasn't running this context as well, then it won't
    // be able to wait for the worker threads it created.
    if (mExecutionThreadsType != IncludeOriginal)
        cleanupWorkerThreads();
}
Exemple #6
0
bool record_keys (struct key_container *keys)
{
  assert (NULL != keys);

  bool result = false;
  FILE *f = NULL;

  struct passwd *pw = getpwuid (getuid ());
  assert (NULL != pw);

  const char *home = pw->pw_dir;
  unsigned int filename_len = strlen (home) + strlen (KEY_STORE) + 1;
  char *filename = (char *)malloc_wipe (filename_len);
  strcpy (filename, home);
  strcat (filename, KEY_STORE);


  if ((f = fopen (filename, "w")) != NULL)
    {

      fprintf (f, "# Hashlet key store written from version: %s\n",
               PACKAGE_VERSION);

      unsigned int x = 0;
      for (x=0; x< get_max_keys (); x++)
        {
          fprintf (f, "key_slot_%02u    ",x);

          unsigned int y = 0;
          for (y=0; y < keys->keys[x].len; y++)
            {
              fprintf (f, "%02X", keys->keys[x].ptr[y]);
            }

          fprintf (f, "%s", "\n");
        }

      fclose (f);
      result = true;
    }
  else
    {
      CTX_LOG (INFO, "Failed to open %s", filename);
      perror ("Error");
    }

  free_wipe ((uint8_t *)filename, filename_len);
  return result;
}
Exemple #7
0
unsigned int serialize_command (struct Command_ATSHA204 *c, uint8_t **serialized)
{
  unsigned int total_len = 0;
  unsigned int crc_len = 0;
  unsigned int crc_offset = 0;
  uint8_t *data;
  uint16_t *crc;


  assert (NULL != c);
  assert (NULL != serialized);

  total_len = sizeof (c->command) + sizeof (c->count) +sizeof (c->opcode) +
    sizeof (c->param1) + sizeof (c->param2) + c->data_len + sizeof (c->checksum);

  crc_len = total_len - sizeof (c->command) - sizeof (c->checksum);

  crc_offset = total_len - sizeof (c->checksum);

  c->count = total_len - sizeof (c->command);

  data = (uint8_t*)malloc (total_len);

  assert (NULL != data);

  print_command (c);

  CTX_LOG (DEBUG,
           "Total len: %d, count: %d, CRC_LEN: %d, CRC_OFFSET: %d\n",
           total_len, c->count, crc_len, crc_offset);

  /* copy over the command */
  data[0] = c->command;
  data[1] = c->count;
  data[2] = c->opcode;
  data[3] = c->param1;
  data[4] = c->param2[0];
  data[5] = c->param2[1];
  if (c->data_len > 0)
    memcpy (&data[6], c->data, c->data_len);

  crc = (uint16_t *)&data[crc_offset];
  *crc = calculate_crc16 (&data[1], crc_len);

  *serialized = data;

  return total_len;

}
Exemple #8
0
enum STATUS_RESPONSE get_status_response(const uint8_t *rsp)
{
  const unsigned int OFFSET_TO_CRC = 2;
  const unsigned int OFFSET_TO_RSP = 1;
  const unsigned int STATUS_LENGTH = 4;

  if (!is_crc_16_valid (rsp, STATUS_LENGTH - CRC_16_LEN, rsp + OFFSET_TO_CRC))
    {
      CTX_LOG (DEBUG, "CRC Fail in status response");
      return RSP_COMM_ERROR;
    }

  return *(rsp + OFFSET_TO_RSP);

}
Exemple #9
0
enum STATUS_RESPONSE send_and_receive (int fd, uint8_t *send_buf,
                                       unsigned int send_buf_len,
                                       uint8_t *recv_buf,
                                       unsigned int recv_buf_len,
                                       struct timespec *wait_time)
{
  struct timespec tim_rem;
  enum STATUS_RESPONSE rsp = RSP_AWAKE;
  const unsigned int NUM_RETRIES = 10;
  unsigned int x = 0;
  ssize_t result = 0;

  assert (NULL != send_buf);
  assert (NULL != recv_buf);
  assert (NULL != wait_time);

  /* Send the data at first.  During a read, if the device responds
  with an "I'm Awake" flag, we've lost synchronization, so send the
  data again in that case only.  Arbitrarily retry this procedure
  NUM_RETRIES times */
  for (x=0; x < NUM_RETRIES && rsp == RSP_AWAKE; x++)
    {
      print_hex_string ("Sending", send_buf, send_buf_len);

      result = i2c_write (fd,send_buf,send_buf_len);

      if (result > 1)
        {
          do
            {
              nanosleep (wait_time , &tim_rem);
            }
          while ((rsp = read_and_validate (fd, recv_buf, recv_buf_len))
                 == RSP_NAK);
          CTX_LOG (DEBUG, "Command Response: %s", status_to_string (rsp));
        }
      else
        {
          perror ("Send failed\n");
          exit (1);
        }


    }

  return rsp;
}
Exemple #10
0
bool wakeup(int fd)
{

  uint32_t wakeup = 0;
  unsigned char buf[4] = {0};
  bool awake = false;

  /* The assumption here that the fd is the i2c fd.  Of course, it may
   * not be, so this may loop for a while (read forever).  This should
   * probably try for only so often before quitting.
  */

  /* Perform a basic check to see if this fd is open.  This does not
     guarantee it is the correct fd */

  if(fcntl(fd, F_GETFD) < 0)
    perror("Invalid FD.\n");

  while (!awake)
    {
      if (write(fd,&wakeup,sizeof(wakeup)) > 1)
        {

          CTX_LOG(DEBUG, "%s", "Device is awake.");
          // Using I2C Read
          if (read(fd,buf,sizeof(buf)) <= 0)
            {
              /* ERROR HANDLING: i2c transaction failed */
              perror("Failed to read from the i2c bus.\n");
            }
          else
            {
              assert(is_crc_16_valid(buf, 2, buf+2));
              awake = true;
            }
        }
    }

  return awake;

}
Exemple #11
0
Context::Context(const String& name_, Network::IOService* ios, Network::IOStrand* strand, Trace::Trace* _trace, const Time& epoch, const Duration& simlen)
 : name(name_),
   ioService(ios),
   mainStrand(strand),
   profiler(NULL),
   timeSeries(NULL),
   mFinishedTimer( Network::IOTimer::create(ios) ),
   mTrace(_trace),
   mCommander(NULL),
   mEpoch(epoch),
   mLastSimTime(Time::null()),
   mSimDuration(simlen),
   mKillThread(),
   mKillService(NULL),
   mKillTimer(),
   mStopRequested(false)
{
    CTX_LOG(info, "Creating context");
  Breakpad::init();
  profiler = new TimeProfiler(this, name);
}
Exemple #12
0
void Context::run(uint32 nthreads, ExecutionThreads exthreads) {
    CTX_LOG(info, "Starting context execution with " << nthreads << " threads");

    mExecutionThreadsType = exthreads;

    uint32 nworkers = (exthreads == IncludeOriginal ? nthreads-1 : nthreads);
    // Start workers
    for(uint32 i = 0; i < nworkers; i++) {
        mWorkerThreads.push_back(
            new Thread( name + " Worker " + boost::lexical_cast<String>(i), std::tr1::bind(&Context::workerThread, this) )
        );
    }

    // Run
    if (exthreads == IncludeOriginal) {
        ioService->run();
        cleanupWorkerThreads();

        // If we exited gracefully, call shutdown automatically to clean everything
        // up, make sure stop() methods get called, etc.
        if (!mStopRequested.read())
           this->shutdown();
    }
}
Exemple #13
0
Context::~Context() {
    CTX_LOG(info, "Destroying context");
    delete profiler;
}
Exemple #14
0
enum STATUS_RESPONSE read_and_validate (int fd, uint8_t *buf, unsigned int len)
{

  uint8_t* tmp = NULL;
  const int PAYLOAD_LEN_SIZE = 1;
  const int CRC_SIZE = 2;
  enum STATUS_RESPONSE status = RSP_COMM_ERROR;
  unsigned int recv_buf_len = 0;
  bool crc_valid;
  unsigned int crc_offset;
  int read_bytes;
  const unsigned int STATUS_RSP = 4;

  assert (NULL != buf);

  recv_buf_len = len + PAYLOAD_LEN_SIZE + CRC_SIZE;

  crc_offset = recv_buf_len - 2;

  /* The buffer that comes back has a length byte at the front and a
   * two byte crc at the end. */
  tmp = malloc_wipe (recv_buf_len);

  read_bytes = i2c_read (fd, tmp, recv_buf_len);

  /* First Case: We've read the buffer and it's a status packet */

  if (read_bytes == recv_buf_len && tmp[0] == STATUS_RSP)
  {
      print_hex_string ("Status RSP", tmp, tmp[0]);
      status = get_status_response (tmp);
      CTX_LOG (DEBUG, status_to_string (status));
  }

  /* Second case: We received the expected message length */
  else if (read_bytes == recv_buf_len && tmp[0] == recv_buf_len)
    {
      print_hex_string ("Received RSP", tmp, recv_buf_len);

      crc_valid = is_crc_16_valid (tmp, tmp[0] - CRC_16_LEN, tmp + crc_offset);

      if (true == crc_valid)
        {
          wipe (buf, len);
          memcpy (buf, &tmp[1], len);
          status = RSP_SUCCESS;

        }
      else
        {
          perror ("CRC FAIL!\n");
        }
    }
  else
    {
      CTX_LOG (DEBUG,"Read failed, retrying");
      status = RSP_NAK;

    }

  free_wipe (tmp, recv_buf_len);

  return status;
}
Exemple #15
0
void print_command (struct Command_ATSHA204 *c)
{
  assert (NULL != c);

  const char* opcode = NULL;

  CTX_LOG (DEBUG, "*** Printing Command ***");
  CTX_LOG (DEBUG, "Command: 0x%02X", c->command);
  CTX_LOG (DEBUG, "Count: 0x%02X", c->count);
  CTX_LOG (DEBUG, "OpCode: 0x%02X", c->opcode);

  switch (c->opcode)
    {
    case COMMAND_DERIVE_KEY:
      opcode = "Command Derive Key";
      break;
    case COMMAND_DEV_REV:
      opcode = "Command Dev Rev";
      break;
    case COMMAND_GEN_DIG:
      opcode = "Command Generate Digest";
      break;
    case COMMAND_HMAC:
      opcode = "Command HMAC";
      break;
    case COMMAND_CHECK_MAC:
      opcode = "Command Check MAC";
      break;
    case COMMAND_LOCK:
      opcode = "Command Lock";
      break;
    case COMMAND_MAC:
      opcode = "Command MAC";
      break;
    case COMMAND_NONCE:
      opcode = "Command NONCE";
      break;
    case COMMAND_PAUSE:
      opcode = "Command Pause";
      break;
    case COMMAND_RANDOM:
      opcode = "Command Random";
      break;
    case COMMAND_READ:
      opcode = "Command Read";
      break;
    case COMMAND_UPDATE_EXTRA:
      opcode = "Command Update Extra";
      break;
    case COMMAND_WRITE:
      opcode = "Command Write";
      break;
    default:
      assert (false);
    }
  CTX_LOG (DEBUG,"%s", opcode);
  CTX_LOG (DEBUG,"param1: 0x%02X", c->param1);
  CTX_LOG (DEBUG,"param2: 0x%02X 0x%02X", c->param2[0], c->param2[1]);
  if (c->data_len > 0)
    print_hex_string ("Data", c->data, c->data_len);
  CTX_LOG (DEBUG,"CRC: 0x%02X 0x%02X", c->checksum[0], c->checksum[1]);
  CTX_LOG (DEBUG,"Wait time: %ld seconds %lu nanoseconds",
          c->exec_time.tv_sec, c->exec_time.tv_nsec);



}
Exemple #16
0
/* Parse a single option. */
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
  /* Get the input argument from argp_parse, which we
     know is a pointer to our arguments structure. */
  struct arguments *arguments = state->input;
  int slot;
  long int address_arg;

  switch (key)
    {
    case 'a':

      /* TODO: Not working as expected */
      address_arg = strtol (arg,NULL,16);
      if (0 != address_arg)
        {
          arguments->address = address_arg;
          CTX_LOG (DEBUG, "Using address %u", address_arg);
        }
      else
        CTX_LOG (INFO, "Address not recognized, using default");

      break;
    case 'b':
      arguments->bus = arg;
      break;
    case 'B':
      arguments->bytes = atoi(arg);
      break;
    case 'q': case 's':
      arguments->silent = 1;
      break;
    case 'v':
      arguments->verbose = 1;
      set_log_level (DEBUG);
      break;
    case 'f':
      arguments->input_file = arg;
      break;
    case OPT_UPDATE_SEED:
      arguments->update_seed = true;
      break;
    case 'k':
      slot = atoi (arg);
      if (slot < 0 || slot > 15)
        argp_usage (state);

      arguments->key_slot = slot;
      break;
    case 'c':
      if (!is_hex_arg (arg, 64))
        {
          fprintf (stderr, "%s\n", "Invalid Challenge.");
          argp_usage (state);
        }
      else
        arguments->challenge = arg;
      break;
    case 'w':
      if (!is_hex_arg (arg, 64))
        {
          fprintf (stderr, "%s\n", "Invalid Data.");
          argp_usage (state);
        }
      else
        arguments->write_data = arg;
      break;
    case 'r':
      if (!is_hex_arg (arg, 64))
        {
          fprintf (stderr, "%s\n", "Invalid Challenge Response.");
          argp_usage (state);
        }
      else
        arguments->challenge_rsp = arg;
      break;
    case 'm':
      if (!is_hex_arg (arg, 26))
        {
          fprintf (stderr, "%s\n", "Invalid Meta Data.");
          argp_usage (state);
        }
      else
        arguments->meta = arg;
      break;
    case ARGP_KEY_ARG:
      if (state->arg_num > NUM_ARGS)
        {
          /* Too many arguments. */
          argp_usage (state);
        }
      else
        {
          arguments->args[state->arg_num] = arg;
        }

      break;

    case ARGP_KEY_END:
      if (state->arg_num < NUM_ARGS)
        /* Not enough arguments. */
        argp_usage (state);
      break;

    default:
      return ARGP_ERR_UNKNOWN;
    }
  return 0;
}
Exemple #17
0
bool write_keys (int fd, struct key_container *keys,
                 struct octet_buffer *data_zone)
{
  assert (NULL != data_zone);
  assert (STATE_INITIALIZED == get_device_state (fd));
  bool free_keys = false;

#define KEY_LEN 32
  const unsigned int TEST_KEY_1 = 14;
  const unsigned int TEST_KEY_2 = 15;

  struct octet_buffer test_key_14 = make_buffer (KEY_LEN);
  memset(test_key_14.ptr, 0xAA, KEY_LEN);
  struct octet_buffer test_key_15 = make_buffer (KEY_LEN);
  memset(test_key_15.ptr, 0xBB, KEY_LEN);

  int x = 0;
  /* If there are no keys, which is the case when we are personalizing
     a device from scratch, create some new keys */
  if (NULL == keys)
    {
      keys = make_key_container ();
      for (x=0; x < get_max_keys (); x++)
        {
          if (TEST_KEY_1 == x)
            {
              keys->keys[x] = test_key_14;
            }
          else if (TEST_KEY_2 == x)
            {
              keys->keys[x] = test_key_15;
            }
          else
            {
              keys->keys[x] = get_random (fd, false);
            }
        }

      free_keys = true;
    }

  bool status = true;

  for (x=0; x < get_max_keys () && status; x++)
    {
      const unsigned int WORD_OFFSET = 8;
      unsigned int addr = WORD_OFFSET * x;
      status = write32 (fd, DATA_ZONE, addr, keys->keys[x], NULL);
    }

  if (status)
    {
      data_zone->len = get_max_keys () * keys->keys[0].len;
      data_zone->ptr = malloc_wipe (data_zone->len);

      for (x=0; x < get_max_keys (); x++)
        {
          CTX_LOG(DEBUG, "Writing key %u", x);
          unsigned int offset = x * keys->keys[x].len;
          memcpy(data_zone->ptr + offset, keys->keys[x].ptr, keys->keys[x].len);
        }

      status = record_keys (keys);

    }


  if (free_keys)
    free_key_container (keys);

  return status;

}