Esempio n. 1
0
static u2fh_rc
_u2fh_register (u2fh_devs * devs,
		const char *challenge,
		const char *origin, char **response, size_t * response_len,
		u2fh_cmdflags flags)
{
  unsigned char data[V2CHALLEN + HOSIZE];
  unsigned char buf[MAXDATASIZE];
  char bd[2048];
  size_t bdlen = sizeof (bd);
  size_t len;
  int rc = U2FH_JSON_ERROR;
  char chalb64[256];
  size_t challen = sizeof (chalb64);
  int iterations = 0;

  rc = get_fixed_json_data (challenge, "challenge", chalb64, &challen);
  if (rc != U2FH_OK)
    {
      return rc;
    }

  rc = prepare_browserdata (chalb64, origin, REGISTER_TYP, bd, &bdlen);
  if (rc != U2FH_OK)
    return rc;

  sha256_buffer (bd, bdlen, data);

  prepare_origin (challenge, data + V2CHALLEN);

  /* FIXME: Support asynchronous usage, through a new u2fh_cmdflags
     flag. */

  do
    {
      struct u2fdevice *dev;
      if (iterations++ > 15)
	{
	  return U2FH_TIMEOUT_ERROR;
	}
      for (dev = devs->first; dev != NULL; dev = dev->next)
	{
	  len = MAXDATASIZE;
	  rc = send_apdu (devs, dev->id, U2F_REGISTER, data, sizeof (data),
			  flags & U2FH_REQUEST_USER_PRESENCE ? 3 : 0, buf,
			  &len);
	  if (rc != U2FH_OK)
	    {
	      return rc;
	    }
	  else if (len != 2)
	    {
	      break;
	    }
	}
      if (len != 2)
	{
	  break;
	}
      Sleep (1000);
    }
  while ((flags & U2FH_REQUEST_USER_PRESENCE)
	 && len == 2 && memcmp (buf, NOTSATISFIED, 2) == 0);

  if (len != 2)
    {
      prepare_response (buf, len - 2, bd, response, response_len);
      return U2FH_OK;
    }
  return U2FH_TRANSPORT_ERROR;
}
Esempio n. 2
0
/**
 * u2fh_authenticate:
 * @devs: a device handle, from u2fh_devs_init() and u2fh_devs_discover().
 * @challenge: string with JSON data containing the challenge.
 * @origin: U2F origin URL.
 * @response: pointer to output string with JSON data.
 * @flags: set of ORed #u2fh_cmdflags values.
 *
 * Perform the U2F Authenticate operation.
 *
 * Returns: On success %U2FH_OK (integer 0) is returned, and on errors
 * an #u2fh_rc error code.
 */
u2fh_rc
u2fh_authenticate (u2fh_devs * devs,
		   const char *challenge,
		   const char *origin, char **response, u2fh_cmdflags flags)
{
  unsigned char data[CHALLBINLEN + HOSIZE + MAXKHLEN + 1];
  unsigned char buf[MAXDATASIZE];
  char bd[2048];
  size_t bdlen = sizeof (bd);
  size_t len;
  int rc;
  char chalb64[256];
  size_t challen = sizeof (chalb64);
  char khb64[256];
  size_t kh64len = sizeof (khb64);
  base64_decodestate b64;
  size_t khlen;
  int skip_devices[devs->num_devices];
  int skipped = 0;
  int iterations = 0;

  memset (skip_devices, 0, sizeof (skip_devices));

  rc = get_fixed_json_data (challenge, "challenge", chalb64, &challen);
  if (rc != U2FH_OK)
    return rc;

  rc = prepare_browserdata (chalb64, origin, AUTHENTICATE_TYP, bd, &bdlen);
  if (rc != U2FH_OK)
    return rc;

  sha256_buffer (bd, bdlen, data);

  prepare_origin (challenge, data + CHALLBINLEN);

  /* confusion between key_handle and keyHandle */
  rc = get_fixed_json_data (challenge, "keyHandle", khb64, &kh64len);
  if (rc != U2FH_OK)
    return rc;

  base64_init_decodestate (&b64);
  khlen = base64_decode_block (khb64, kh64len,
			       data + HOSIZE + CHALLBINLEN + 1, &b64);
  data[HOSIZE + CHALLBINLEN] = khlen;

  /* FIXME: Support asynchronous usage, through a new u2fh_cmdflags
     flag. */

  do
    {
      int i;
      if (iterations++ > 15)
	{
	  return U2FH_TIMEOUT_ERROR;
	}
      for (i = 0; i < devs->num_devices; i++)
	{
	  unsigned char tmp_buf[MAXDATASIZE];
	  if (skip_devices[i] != 0)
	    {
	      continue;
	    }
	  if (!devs->devs[i].is_alive)
	    {
	      skipped++;
	      skip_devices[i] = 1;
	      continue;
	    }
	  len = MAXDATASIZE;
	  rc = send_apdu (devs, i, U2F_AUTHENTICATE, data,
			  HOSIZE + CHALLBINLEN + khlen + 1,
			  flags & U2FH_REQUEST_USER_PRESENCE ? 3 : 7, tmp_buf,
			  &len);
	  if (rc != U2FH_OK)
	    {
	      return rc;
	    }
	  else if (len != 2)
	    {
	      memcpy (buf, tmp_buf, len);
	      break;
	    }
	  else if (memcmp (tmp_buf, NOTSATISFIED, 2) != 0)
	    {
	      skipped++;
	      skip_devices[i] = 2;
	      continue;
	    }
	  memcpy (buf, tmp_buf, len);
	}
      if (len == 2 && memcmp (buf, NOTSATISFIED, 2) == 0)
	{
	  Sleep (1000);
	}
    }
  while ((flags & U2FH_REQUEST_USER_PRESENCE)
	 && len == 2 && memcmp (buf, NOTSATISFIED, 2) == 0);

  if (len == 2 && memcmp (buf, NOTSATISFIED, 2) != 0)
    {
      return U2FH_AUTHENTICATOR_ERROR;
    }
  if (len != 2)
    {
      prepare_response (buf, len - 2, bd, challenge, response);
    }

  return U2FH_OK;
}