void
yubikey_parse (const uint8_t token[32],
	       const uint8_t key[16], yubikey_token_t out)
{
  memset (out, 0, sizeof (*out));
  yubikey_modhex_decode ((void *) out, (char *) token, sizeof (*out));
  yubikey_aes_decrypt ((void *) out, key);
}
/**
 * @see const string hex2Modhex(const string& p2Modhex) const;
 * @param p2Hex what to decode.
 * @return input from Modhex decoded.
 *
 */
const string YubikoOtpKeyConfig::modhex2Hex(const std::string& p2Hex) {
	const unsigned long mySz = p2Hex.size();
	const unsigned long mySz2 = mySz / 2;
	vector<uint8_t> myBytes(mySz2, uint8_t(0));
	yubikey_modhex_decode(reinterpret_cast<char*>(&myBytes[0]), p2Hex.c_str(),
			mySz2);
	string myPubId(mySz + 1, '\0');
	yubikey_hex_encode(&myPubId[0], reinterpret_cast<char*>(&myBytes[0]),
			mySz2);
	myPubId.resize(mySz);
	return myPubId;
}
Esempio n. 3
0
static void
modhex_test1 (void)
{
  char buf[1024];
  char buf2[1024];

  yubikey_modhex_encode (buf, "test", 4);
  printf ("modhex-encode(\"test\") = %s\n", buf);
  assert (strcmp (buf, "ifhgieif") == 0);
  printf ("Modhex-1.1 success\n");

  printf ("modhex-decode(\"%s\") = ", buf);
  yubikey_modhex_decode (buf2, buf, sizeof (buf2));
  printf ("%.*s\n", 4, buf2);
  assert (memcmp (buf2, "test", 4) == 0);
  printf ("Modhex-1.2 success\n");
}
Esempio n. 4
0
int
yubikey_parse(const uint8_t *password, const uint8_t key[YUBIKEY_KEY_SIZE],
    yubikey_token_t out, int index)
{
	wchar_t *wpassword, *pp;
	char token[YUBIKEY_TOKEN_SIZE + 1], *lc_ctype;
	int len;

	if (index < 0 || index >= YUBIKEY_KEYMAP_COUNT)
		return -1;

	len = strlen(password);
	pp = wpassword = malloc(sizeof(wchar_t) * (len + 1));
	if (pp == NULL)
		return ENOMEM;
	
	memset(out, 0, sizeof(*out));
	memset(token, 0, YUBIKEY_TOKEN_SIZE + 1);

	lc_ctype = getenv("LC_CTYPE");
	setlocale(LC_CTYPE, lc_ctype ? lc_ctype : "C.UTF-8");
	len = mbstowcs(wpassword, password, len);
	if (len < 0) {
		return errno;
	}
	setlocale(LC_CTYPE, "C");

	if (len > YUBIKEY_TOKEN_SIZE)
		pp = pp + len - YUBIKEY_TOKEN_SIZE;
	if (len < YUBIKEY_TOKEN_SIZE)
		return EMSGSIZE;
	
	if (yubikey_keymap_decode(pp, token, index))
		return EINVAL;
	yubikey_modhex_decode((void *)out, token, sizeof(*out));
	yubikey_aes_decrypt((void *)out, key);
	return 0;
}
static int hex_modhex_decode(unsigned char *result, size_t *resultlen,
			     const char *str, size_t strl,
			     size_t minsize, size_t maxsize,
			     bool primarily_modhex)
{
	if (strl >= 2) {
		if (strncmp(str, "m:", 2) == 0
		    || strncmp(str, "M:", 2) == 0) {
			str += 2;
			strl -= 2;
			primarily_modhex = true;
		} else if (strncmp(str, "h:", 2) == 0
			   || strncmp(str, "H:", 2) == 0) {
			str += 2;
			strl -= 2;
			primarily_modhex = false;
		}
	}

	if ((strl % 2 != 0) || (strl < minsize) || (strl > maxsize)) {
		return -1;
	}

	*resultlen = strl / 2;
	if (primarily_modhex) {
		if (yubikey_modhex_p(str)) {
			yubikey_modhex_decode((char *)result, str, strl);
			return 1;
		}
	} else {
		if (yubikey_hex_p(str)) {
			yubikey_hex_decode((char *)result, str, strl);
			return 1;
		}
	}

	return 0;
}
int YubiKeyUtil::hexModhexDecode(unsigned char *result, size_t *resultLen,
                                 const char *str, size_t strLen,
                                 size_t minSize, size_t maxSize,
                                 bool modhex)
{
    if ((strLen % 2 != 0) || (strLen < minSize) || (strLen > maxSize)) {
        return -1;
    }

    *resultLen = strLen / 2;
    if (modhex) {
        if (yubikey_modhex_p(str)) {
            yubikey_modhex_decode((char *)result, str, strLen);
            return 1;
        }
    } else {
        if (yubikey_hex_p(str)) {
            yubikey_hex_decode((char *)result, str, strLen);
            return 1;
        }
    }

    return 0;
}
Esempio n. 7
0
int
main (int argc, char *argv[])
{
    uint8_t buf[128];
    uint8_t key[YUBIKEY_KEY_SIZE];
    char *aeskey, *token;
    yubikey_token_st tok;

    /* Parse command line parameters. */
    if (argc <= 2)
    {
        printf ("Usage: %s <aeskey> <token>\n", argv[0]);
        printf (" AESKEY:\tHex encoded AES-key.\n");
        printf (" TOKEN:\t\tModHex encoded token.\n");
        return EXIT_FAILURE;
    }

    aeskey = argv[1];
    token = argv[2];

    if (strlen (aeskey) != 32)
    {
        printf ("error: Hex encoded AES-key must be 32 characters.\n");
        return EXIT_FAILURE;
    }

    if (strlen (token) > 32)
    {
        printf ("warning: overlong token, ignoring prefix: %.*s\n",
                (int) strlen (token) - 32, token);
        token = token + (strlen (token) - 32);
    }

    if (strlen (token) != 32)
    {
        printf ("error: ModHex encoded token must be 32 characters.\n");
        return EXIT_FAILURE;
    }

    /* Debug. */
    printf ("Input:\n");
    printf ("  token: %s\n", token);

    yubikey_modhex_decode ((char *) key, token, YUBIKEY_KEY_SIZE);

    {
        size_t i;
        printf ("          ");
        for (i = 0; i < YUBIKEY_KEY_SIZE; i++)
            printf ("%02x ", key[i] & 0xFF);
        printf ("\n");
    }

    printf ("  aeskey: %s\n", aeskey);

    yubikey_hex_decode ((char *) key, aeskey, YUBIKEY_KEY_SIZE);

    {
        size_t i;
        printf ("          ");
        for (i = 0; i < YUBIKEY_KEY_SIZE; i++)
            printf ("%02x ", key[i] & 0xFF);
        printf ("\n");
    }

    /* Pack up dynamic password, decrypt it and verify checksum */
    yubikey_parse ((uint8_t *) token, key, &tok);

    printf ("Output:\n");
    {
        size_t i;
        printf ("          ");
        for (i = 0; i < YUBIKEY_BLOCK_SIZE; i++)
            printf ("%02x ", ((uint8_t *) & tok)[i] & 0xFF);
        printf ("\n");
    }

    printf ("\nStruct:\n");
    /* Debug */
    {
        size_t i;
        printf ("  uid: ");
        for (i = 0; i < YUBIKEY_UID_SIZE; i++)
            printf ("%02x ", tok.uid[i] & 0xFF);
        printf ("\n");
    }
    printf ("  counter: %d (0x%04x)\n", tok.ctr, tok.ctr);
    printf ("  timestamp (low): %d (0x%04x)\n", tok.tstpl, tok.tstpl);
    printf ("  timestamp (high): %d (0x%02x)\n", tok.tstph, tok.tstph);
    printf ("  session use: %d (0x%02x)\n", tok.use, tok.use);
    printf ("  random: %d (0x%02x)\n", tok.rnd, tok.rnd);
    printf ("  crc: %d (0x%04x)\n", tok.crc, tok.crc);

    printf ("\nDerived:\n");
    printf ("  cleaned counter: %d (0x%04x)\n",
            yubikey_counter (tok.ctr), yubikey_counter (tok.ctr));
    yubikey_modhex_encode ((char *) buf, (char *) tok.uid, YUBIKEY_UID_SIZE);
    printf ("  modhex uid: %s\n", buf);
    printf ("  triggered by caps lock: %s\n",
            yubikey_capslock (tok.ctr) ? "yes" : "no");
    printf ("  crc: %04X\n", yubikey_crc16 ((void *) &tok, YUBIKEY_KEY_SIZE));

    printf ("  crc check: ");
    if (yubikey_crc_ok_p ((uint8_t *) & tok))
    {
        printf ("ok\n");
        return EXIT_SUCCESS;
    }

    printf ("fail\n");
    return EXIT_FAILURE;
}
Esempio n. 8
0
int
main (void)
{
  char buf[1024];
  size_t i;
  int rc;
  yubikey_token_st tok;


  /* Test Modhex */
  yubikey_modhex_encode (buf, "test", 4);
  printf ("modhex-encode(\"test\") = %s\n", buf);
  if (strcmp (buf, "ifhgieif") != 0)
    {
      printf ("ModHex failure\n");
      return 1;
    }
  printf ("Modhex-1 success\n");

  printf ("modhex-decode(\"%s\") = ", buf);
  yubikey_modhex_decode (buf, buf, strlen ((char *) buf));
  printf ("%.*s\n", 4, buf);
  if (memcmp (buf, "test", 4) != 0)
    {
      printf ("ModHex failure\n");
      return 1;
    }
  printf ("Modhex-2 success\n");

  strcpy (buf, "cbdefghijklnrtuv");
  rc = yubikey_modhex_p (buf);
  printf ("hex-p(\"%s\") = %d\n", buf, rc);
  if (!rc)
    {
      printf ("Hex_p failure\n");
      return 1;
    }
  printf ("Hex-3 success\n");

  strcpy (buf, "0123Xabc");
  rc = yubikey_hex_p (buf);
  printf ("hex-p(\"%s\") = %d\n", buf, rc);
  if (rc)
    {
      printf ("Hex_p failure\n");
      return 1;
    }
  printf ("Hex-3 success\n");

  /* Test Hex */

  yubikey_hex_encode (buf, "test", 4);
  printf ("hex-encode(\"test\") = %s\n", buf);
  if (strcmp (buf, "74657374") != 0)
    {
      printf ("Hex failure\n");
      return 1;
    }
  printf ("Hex-1 success\n");

  printf ("hex-decode(\"%s\") = ", buf);
  yubikey_hex_decode (buf, buf, strlen ((char *) buf));
  printf ("%.*s\n", 4, buf);
  if (memcmp (buf, "test", 4) != 0)
    {
      printf ("Hex failure\n");
      return 1;
    }
  printf ("Hex-2 success\n");

  strcpy (buf, "0123456789abcdef");
  rc = yubikey_hex_p (buf);
  printf ("hex-p(\"%s\") = %d\n", buf, rc);
  if (!rc)
    {
      printf ("Hex_p failure\n");
      return 1;
    }
  printf ("Hex-3 success\n");

  strcpy (buf, "0123Xabc");
  rc = yubikey_hex_p (buf);
  printf ("hex-p(\"%s\") = %d\n", buf, rc);
  if (rc)
    {
      printf ("Hex_p failure\n");
      return 1;
    }
  printf ("Hex-3 success\n");

  /* Test AES */

  {
    uint8_t buf[1024];
    char out[1024];
    uint8_t key[16 + 1];

    memcpy (buf, "0123456789abcdef\0", 17);
    memcpy (key, "abcdef0123456789\0", 17);
    printf ("aes-decrypt (data=%s, key=%s)\n => ", (char *) buf,
	    (char *) key);
    yubikey_aes_decrypt (buf, key);
    for (i = 0; i < 16; i++)
      printf ("%02x", buf[i] & 0xFF);
    printf ("\n");

    if (memcmp (buf,
		"\x83\x8a\x46\x7f\x34\x63\x95\x51"
		"\x75\x5b\xd3\x2a\x4a\x2f\x15\xe1", 16) != 0)
      {
	printf ("AES failure\n");
	return 1;
      }
    printf ("AES-1 success\n");

    yubikey_aes_encrypt (buf, key);
    if (memcmp (buf, "0123456789abcdef", 16) != 0)
      {
	printf ("AES encryption failure\n");
	return 1;
      }
    printf ("AES-2 success\n");

    /* Test OTP */

    memcpy ((void *) &tok,
	    "\x16\xe1\xe5\xd9\xd3\x99\x10\x04\x45\x20\x07\xe3\x02\x00\x00",
	    16);
    memcpy (key, "abcdef0123456789", 16);

    yubikey_generate ((void *) &tok, key, out);
    yubikey_parse ((uint8_t *) out, key, &tok);

    if (memcmp
	(&tok, "\x16\xe1\xe5\xd9\xd3\x99\x10\x04\x45\x20\x07\xe3\x02\x00\x00",
	 16) != 0)
      {
	printf ("OTP generation - parse failure\n");
	return 1;
      }
    printf ("OTP-1 success\n");
  }

  return 0;
}
static int yubikey_auth_core(myConf_t *myConf, REQUEST *request)
{
    int passLen = 0, session = 0, counter = 0, i = 0;
    MD5_CTX ctx;
    int result = 0;
    char *filename = "/usr/local/etc/raddb/yubico/users";

    //get password by removing the last 32 characters of the password
    if (strlen(request->password->vp_strvalue) <= 32)
    {
        DEBUG("rlm_yubikey: Password too short.");
        return RLM_MODULE_REJECT;
    }

    passLen = strlen(request->password->vp_strvalue) - 32;
    strncpy(myConf->pass, request->password->vp_strvalue, passLen);
    myConf->pass[passLen] = '\0';
    strncpy(myConf->token, request->password->vp_strvalue + passLen, 32);
    myConf->token[32] = '\0';

    //md5 stuff
    MD5Init(&ctx);
    DEBUG("rlm_yubikey: length: %d, string: %s", passLen, myConf->pass);
    MD5Update(&ctx, (unsigned char *)myConf->pass, passLen);
    MD5Final(&ctx);
    MD5toString(&ctx, myConf->md5ComputedString);
    myConf->md5ComputedString[32] = '\0';
    DEBUG("rlm_yubikey: MD5string of your pass: %s", myConf->md5ComputedString);
    DEBUG("rlm_yubikey: Username: %s", request->username->vp_strvalue);

    //read file
    result = config_read_file(&(myConf->config), filename);
    if (result != CONFIG_TRUE)
    {
        DEBUG("rlm_yubikey: Failed to parse configuration file: config_read_file (&config, filename);");
        DEBUG("config_error_text()= %s and config_error_line()=%d", config_error_text(&(myConf->config)), config_error_line(&(myConf->config)));
        return RLM_MODULE_FAIL;
    }

    //parse file
    myConf->config_setting = config_lookup(&(myConf->config), USERS_PATH);
    if (myConf->config_setting == NULL)
    {
        DEBUG("rlm_yubikey: Failed to parse configuration file: config_lookup failed to find the users node");
        return RLM_MODULE_FAIL;
    }

    //go through the list of users
    for (i = 0; i < config_setting_length(myConf->config_setting); i++)
    {
        DEBUG("Trying i: %d", i);
        config_setting_t *tmpSetting = NULL;
        tmpSetting = config_setting_get_elem(myConf->config_setting, i);
        if (tmpSetting == NULL)
        {
            DEBUG("rlm_yubikey: Failed to parse configuration file: config_setting_get_elem(config_setting,i);");
            return RLM_MODULE_FAIL;
        }

        if ((config_setting_get_string_elem(tmpSetting, 0) == NULL) ||
                (config_setting_get_string_elem(tmpSetting, 1) == NULL) ||
                (config_setting_get_string_elem(tmpSetting, 2) == NULL))
        {
            DEBUG("rlm_yubikey: Failed to parse configuration file while reading the username/password/aeskey triplet ");
            return RLM_MODULE_FAIL;
        }

        //check usernames are equal
        if (strcmp(request->username->vp_strvalue, config_setting_get_string_elem(tmpSetting, 0)) != 0)
        {
            //users do not match. No need to debug this
            //Go to next iteration
            continue;
        }

        //check passwords are equal
        if (strcmp(myConf->md5ComputedString, config_setting_get_string_elem(tmpSetting, 1)) != 0)
        {
            //passwords do not match. We debug
            DEBUG("rlm_yubikey: Password does not match for user %s", request->username->vp_strvalue);
            //Go to next iteration
            continue;
        }

        //check aes stuff - mostly copied from the ykdebug.c that comes with the low-level yubikey library
        uint8_t buf[128];
        const char *aeskey = config_setting_get_string_elem(tmpSetting, 2);
        char *token = myConf->token;
        uint8_t key[YUBIKEY_KEY_SIZE];
        yubikey_token_st tok;

        yubikey_modhex_decode((char*) key, token, YUBIKEY_KEY_SIZE);
        DEBUG("rlm_yubikey:  aeskey: %s", aeskey);

        yubikey_hex_decode((char*) key, aeskey, YUBIKEY_KEY_SIZE);

        /* Pack up dynamic password, decrypt it and verify checksum */
        yubikey_parse((uint8_t*) token, key, &tok);

        DEBUG("rlm_yubikey: Struct:");
        size_t i;
        char *tmp = (char*) malloc(1024);
        for (i = 0; i < YUBIKEY_UID_SIZE; i++)
        {
            sprintf(tmp + i, "%c ", tok.uid[i] & 0xFF);
        }
        tmp[YUBIKEY_UID_SIZE + i] = 0;
        DEBUG("rlm_yubikey:   uid:%s", tmp);
        free(tmp);

        DEBUG("rlm_yubikey:   counter: %d (0x%04x)", tok.ctr, tok.ctr);
        DEBUG("rlm_yubikey:   timestamp (low): %d (0x%04x)", tok.tstpl, tok.tstpl);
        DEBUG("rlm_yubikey:   timestamp (high): %d (0x%02x)", tok.tstph, tok.tstph);
        DEBUG("rlm_yubikey:   session use: %d (0x%02x)", tok.use, tok.use);
        DEBUG("rlm_yubikey:   random: %d (0x%02x)", tok.rnd, tok.rnd);
        DEBUG("rlm_yubikey:   crc: %d (0x%04x)", tok.crc, tok.crc);
        DEBUG("rlm_yubikey: Derived:");
        DEBUG("rlm_yubikey:   cleaned counter: %d (0x%04x)",yubikey_counter(tok.ctr), yubikey_counter(tok.ctr));

        yubikey_modhex_encode((char*) buf, (char*) tok.uid, YUBIKEY_UID_SIZE);

        DEBUG("rlm_yubikey:   modhex uid: %s", buf);
        DEBUG("rlm_yubikey:   triggered by caps lock: %s", yubikey_capslock(tok.ctr) ? "yes" : "no");
        DEBUG("rlm_yubikey:   crc: %04X", yubikey_crc16((void*) & tok, YUBIKEY_KEY_SIZE));
        DEBUG("rlm_yubikey:   crc check: ");
        if (yubikey_crc_ok_p((uint8_t*) & tok))
        {
            DEBUG("rlm_yubikey:   ok");

            char *tmppath = KEYS_PATH;
            char *path = (char*) malloc(strlen(tmppath) + 32 + 1);
            strcpy(path, tmppath);
            strcat(path, aeskey);


            myConf->config_setting = config_lookup(&(myConf->config), path);
            if (myConf->config_setting == NULL)
            {
                DEBUG("rlm_yubikey: Error parsing file: %s not found", path);
                return RLM_MODULE_FAIL;
            }

            //checking counter and session and update them if necessary
            counter = config_setting_get_int_elem(myConf->config_setting, 0);
            session = config_setting_get_int_elem(myConf->config_setting, 1);
            DEBUG("rlm_yubikey: Read counter: %d, session: %d", counter, session);

            if ((tok.ctr < counter)||((tok.ctr == counter) && (tok.use <= session)))
            {
                DEBUG("rlm_yubikey: someone tried to login with an old generated hash");
                return RLM_MODULE_REJECT;
            }

            //updating config file with counter and session
            config_setting_set_int_elem(myConf->config_setting, 0, tok.ctr);
            config_setting_set_int_elem(myConf->config_setting, 1, tok.use);


            DEBUG("rlm_yubikey: Written element: %ld", config_setting_get_int_elem(myConf->config_setting, 0));
            DEBUG("rlm_yubikey: Written element: %ld", config_setting_get_int_elem(myConf->config_setting, 1));
            if (CONFIG_FALSE == config_write_file(&(myConf->config), filename))
            {
                DEBUG("rlm_yubikey: Failed to write the file.");
                return RLM_MODULE_FAIL;
            }

            return RLM_MODULE_OK;
        }
        DEBUG("rlm_yubikey:   fail");
    }
    DEBUG("rlm_yubikey: Authenticating with password %s", request->password->vp_strvalue);
    return RLM_MODULE_REJECT;
}