1*6cc4e57dSanton /* $OpenBSD: yubikey.c,v 1.6 2017/09/16 08:07:15 anton Exp $ */
25e4064a0Sdhill
35e4064a0Sdhill /*
45e4064a0Sdhill * Written by Simon Josefsson <simon@josefsson.org>.
55e4064a0Sdhill * Copyright (c) 2006, 2007, 2008, 2009 Yubico AB
65e4064a0Sdhill * Copyright (c) 2010 Daniel Hartmeier <daniel@benzedrine.cx>
75e4064a0Sdhill * All rights reserved.
85e4064a0Sdhill *
95e4064a0Sdhill * Redistribution and use in source and binary forms, with or without
105e4064a0Sdhill * modification, are permitted provided that the following conditions are
115e4064a0Sdhill * met:
125e4064a0Sdhill *
135e4064a0Sdhill * * Redistributions of source code must retain the above copyright
145e4064a0Sdhill * notice, this list of conditions and the following disclaimer.
155e4064a0Sdhill *
165e4064a0Sdhill * * Redistributions in binary form must reproduce the above
175e4064a0Sdhill * copyright notice, this list of conditions and the following
185e4064a0Sdhill * disclaimer in the documentation and/or other materials provided
195e4064a0Sdhill * with the distribution.
205e4064a0Sdhill *
215e4064a0Sdhill * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
225e4064a0Sdhill * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
235e4064a0Sdhill * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
245e4064a0Sdhill * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
255e4064a0Sdhill * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
265e4064a0Sdhill * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
275e4064a0Sdhill * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
285e4064a0Sdhill * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
295e4064a0Sdhill * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
305e4064a0Sdhill * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
315e4064a0Sdhill * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
325e4064a0Sdhill *
335e4064a0Sdhill */
345e4064a0Sdhill
356e526c06Shalex #include <ctype.h>
363ef0233cSmcbride #include <stdlib.h>
373ef0233cSmcbride #include <wchar.h>
383ef0233cSmcbride #include <locale.h>
393ef0233cSmcbride #include <errno.h>
406e526c06Shalex
415e4064a0Sdhill #include "yubikey.h"
423ef0233cSmcbride #include "keymaps.h"
435e4064a0Sdhill
445e4064a0Sdhill static const uint8_t RC[] = {
455e4064a0Sdhill 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
465e4064a0Sdhill };
475e4064a0Sdhill
485e4064a0Sdhill static const uint8_t rijndael_sbox[] = {
495e4064a0Sdhill 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
505e4064a0Sdhill 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
515e4064a0Sdhill 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
525e4064a0Sdhill 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
535e4064a0Sdhill 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
545e4064a0Sdhill 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
555e4064a0Sdhill 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
565e4064a0Sdhill 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
575e4064a0Sdhill 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
585e4064a0Sdhill 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
595e4064a0Sdhill 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
605e4064a0Sdhill 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
615e4064a0Sdhill 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
625e4064a0Sdhill 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
635e4064a0Sdhill 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
645e4064a0Sdhill 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
655e4064a0Sdhill 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
665e4064a0Sdhill 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
675e4064a0Sdhill 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
685e4064a0Sdhill 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
695e4064a0Sdhill 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
705e4064a0Sdhill 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
715e4064a0Sdhill 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
725e4064a0Sdhill 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
735e4064a0Sdhill 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
745e4064a0Sdhill 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
755e4064a0Sdhill 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
765e4064a0Sdhill 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
775e4064a0Sdhill 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
785e4064a0Sdhill 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
795e4064a0Sdhill 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
805e4064a0Sdhill 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
815e4064a0Sdhill };
825e4064a0Sdhill
835e4064a0Sdhill static const uint8_t rijndael_inv_sbox[] = {
845e4064a0Sdhill 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
855e4064a0Sdhill 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
865e4064a0Sdhill 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
875e4064a0Sdhill 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
885e4064a0Sdhill 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
895e4064a0Sdhill 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
905e4064a0Sdhill 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
915e4064a0Sdhill 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
925e4064a0Sdhill 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
935e4064a0Sdhill 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
945e4064a0Sdhill 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
955e4064a0Sdhill 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
965e4064a0Sdhill 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
975e4064a0Sdhill 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
985e4064a0Sdhill 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
995e4064a0Sdhill 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
1005e4064a0Sdhill 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
1015e4064a0Sdhill 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
1025e4064a0Sdhill 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
1035e4064a0Sdhill 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
1045e4064a0Sdhill 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
1055e4064a0Sdhill 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
1065e4064a0Sdhill 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
1075e4064a0Sdhill 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
1085e4064a0Sdhill 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
1095e4064a0Sdhill 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
1105e4064a0Sdhill 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
1115e4064a0Sdhill 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
1125e4064a0Sdhill 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
1135e4064a0Sdhill 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
1145e4064a0Sdhill 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
1155e4064a0Sdhill 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
1165e4064a0Sdhill };
1175e4064a0Sdhill
1185e4064a0Sdhill static inline uint8_t
xtime(uint8_t b)1195e4064a0Sdhill xtime(uint8_t b)
1205e4064a0Sdhill {
1215e4064a0Sdhill return (b & 0x80) ? ((b << 1) ^ 0x1b) : (b << 1);
1225e4064a0Sdhill }
1235e4064a0Sdhill
1245e4064a0Sdhill #define NUMBER_OF_ROUNDS 10
1255e4064a0Sdhill
1265e4064a0Sdhill void
yubikey_aes_decrypt(uint8_t * state,const uint8_t * key)1275e4064a0Sdhill yubikey_aes_decrypt(uint8_t *state, const uint8_t *key)
1285e4064a0Sdhill {
1295e4064a0Sdhill uint8_t i, j, round_key[0x10];
1305e4064a0Sdhill uint8_t a02x, a13x;
1315e4064a0Sdhill uint8_t a02xx, a13xx;
1325e4064a0Sdhill uint8_t k1, k2;
1335e4064a0Sdhill
1345e4064a0Sdhill memcpy(round_key, key, sizeof(round_key));
1355e4064a0Sdhill for (i = 0; i < NUMBER_OF_ROUNDS; i++) {
1365e4064a0Sdhill round_key[0] ^= RC[i];
1375e4064a0Sdhill
1385e4064a0Sdhill round_key[0] ^= rijndael_sbox[round_key[13]];
1395e4064a0Sdhill round_key[1] ^= rijndael_sbox[round_key[14]];
1405e4064a0Sdhill round_key[2] ^= rijndael_sbox[round_key[15]];
1415e4064a0Sdhill round_key[3] ^= rijndael_sbox[round_key[12]];
1425e4064a0Sdhill
1435e4064a0Sdhill for (j = 4; j < 16; j++)
1445e4064a0Sdhill round_key[j] ^= round_key[j - 4];
1455e4064a0Sdhill }
1465e4064a0Sdhill for (i = 0; i < 0x10; i++)
1475e4064a0Sdhill state[i] ^= round_key[i];
1485e4064a0Sdhill
1495e4064a0Sdhill for (i = 1; i <= NUMBER_OF_ROUNDS; i++) {
1505e4064a0Sdhill /* inv_byte_sub_shift_row(); */
1515e4064a0Sdhill
1525e4064a0Sdhill /* First row: 0 shift, 0 4 8 12 */
1535e4064a0Sdhill state[0] = rijndael_inv_sbox[state[0]];
1545e4064a0Sdhill state[4] = rijndael_inv_sbox[state[4]];
1555e4064a0Sdhill state[8] = rijndael_inv_sbox[state[8]];
1565e4064a0Sdhill state[12] = rijndael_inv_sbox[state[12]];
1575e4064a0Sdhill
1585e4064a0Sdhill /* Second row: -1 shift, 1 5 9 13 */
1595e4064a0Sdhill j = state[13];
1605e4064a0Sdhill state[13] = rijndael_inv_sbox[state[9]];
1615e4064a0Sdhill state[9] = rijndael_inv_sbox[state[5]];
1625e4064a0Sdhill state[5] = rijndael_inv_sbox[state[1]];
1635e4064a0Sdhill state[1] = rijndael_inv_sbox[j];
1645e4064a0Sdhill
1655e4064a0Sdhill /* Third row: -2 shift, 2 6 10 14 */
1665e4064a0Sdhill j = state[2];
1675e4064a0Sdhill state[2] = rijndael_inv_sbox[state[10]];
1685e4064a0Sdhill state[10] = rijndael_inv_sbox[j];
1695e4064a0Sdhill j = state[6];
1705e4064a0Sdhill state[6] = rijndael_inv_sbox[state[14]];
1715e4064a0Sdhill state[14] = rijndael_inv_sbox[j];
1725e4064a0Sdhill
1735e4064a0Sdhill /* Fourth row: -3 shift, 3 7 11 15 */
1745e4064a0Sdhill j = state[3];
1755e4064a0Sdhill state[3] = rijndael_inv_sbox[state[7]];
1765e4064a0Sdhill state[7] = rijndael_inv_sbox[state[11]];
1775e4064a0Sdhill state[11] = rijndael_inv_sbox[state[15]];
1785e4064a0Sdhill state[15] = rijndael_inv_sbox[j];
1795e4064a0Sdhill
1805e4064a0Sdhill /* get_inv_round_key(i); */
1815e4064a0Sdhill
1825e4064a0Sdhill for (j = 15; j > 3; j--)
1835e4064a0Sdhill round_key[j] ^= round_key[j - 4];
1845e4064a0Sdhill
1855e4064a0Sdhill round_key[0] ^= (RC[NUMBER_OF_ROUNDS - i] ^
1865e4064a0Sdhill rijndael_sbox[round_key[13]]);
1875e4064a0Sdhill
1885e4064a0Sdhill round_key[1] ^= rijndael_sbox[round_key[14]];
1895e4064a0Sdhill round_key[2] ^= rijndael_sbox[round_key[15]];
1905e4064a0Sdhill round_key[3] ^= rijndael_sbox[round_key[12]];
1915e4064a0Sdhill
1925e4064a0Sdhill for (j = 0; j < 16; j++)
1935e4064a0Sdhill state[j] ^= round_key[j];
1945e4064a0Sdhill if (i != NUMBER_OF_ROUNDS) {
1955e4064a0Sdhill /* inv_mix_column(); */
1965e4064a0Sdhill
1975e4064a0Sdhill for (j = 0; j < 16; j += 4) {
1985e4064a0Sdhill k1 = state[j] ^ state[j + 2];
1995e4064a0Sdhill a02x = xtime(k1);
2005e4064a0Sdhill k2 = state[j + 1] ^ state[j + 3];
2015e4064a0Sdhill a13x = xtime(k2);
2025e4064a0Sdhill
2035e4064a0Sdhill k1 ^= (k2 ^ xtime(state[j + 1] ^ state[j + 2]));
2045e4064a0Sdhill k2 = k1;
2055e4064a0Sdhill
2065e4064a0Sdhill a02xx = xtime(a02x);
2075e4064a0Sdhill a13xx = xtime(a13x);
2085e4064a0Sdhill
2095e4064a0Sdhill
2105e4064a0Sdhill k1 ^= (xtime(a02xx ^ a13xx) ^ a02xx);
2115e4064a0Sdhill k2 ^= (xtime(a02xx ^ a13xx) ^ a13xx);
2125e4064a0Sdhill
2135e4064a0Sdhill state[j] ^= (k1 ^ a02x);
2145e4064a0Sdhill state[j + 1] ^= k2;
2155e4064a0Sdhill state[j + 2] ^= (k1 ^ a13x);
2165e4064a0Sdhill state[j + 3] ^= (k2 ^ a02x ^ a13x);
2175e4064a0Sdhill }
2185e4064a0Sdhill }
2195e4064a0Sdhill
2205e4064a0Sdhill }
2215e4064a0Sdhill }
2225e4064a0Sdhill
2235e4064a0Sdhill uint16_t
yubikey_crc16(const uint8_t * buf,size_t buf_size)2245e4064a0Sdhill yubikey_crc16(const uint8_t *buf, size_t buf_size)
2255e4064a0Sdhill {
2265e4064a0Sdhill uint16_t m_crc = 0xffff;
2275e4064a0Sdhill
2285e4064a0Sdhill while (buf_size--) {
2295e4064a0Sdhill int i, j;
2305e4064a0Sdhill
2315e4064a0Sdhill m_crc ^= (uint8_t)*buf++ & 0xFF;
2325e4064a0Sdhill for (i = 0; i < 8; i++) {
2335e4064a0Sdhill j = m_crc & 1;
2345e4064a0Sdhill m_crc >>= 1;
2355e4064a0Sdhill if (j)
2365e4064a0Sdhill m_crc ^= 0x8408;
2375e4064a0Sdhill }
2385e4064a0Sdhill }
2395e4064a0Sdhill return m_crc;
2405e4064a0Sdhill }
2415e4064a0Sdhill
2425e4064a0Sdhill static const char hex_trans[] = "0123456789abcdef";
2435e4064a0Sdhill
2445e4064a0Sdhill void
yubikey_hex_encode(char * dst,const char * src,size_t srcSize)2455e4064a0Sdhill yubikey_hex_encode(char *dst, const char *src, size_t srcSize)
2465e4064a0Sdhill {
2475e4064a0Sdhill while (srcSize--) {
2485e4064a0Sdhill *dst++ = hex_trans[(*src >> 4) & 0xf];
2495e4064a0Sdhill *dst++ = hex_trans[*src++ & 0xf];
2505e4064a0Sdhill }
2515e4064a0Sdhill *dst = '\0';
2525e4064a0Sdhill }
2535e4064a0Sdhill
2545e4064a0Sdhill void
yubikey_hex_decode(char * dst,const char * src,size_t dstSize)2555e4064a0Sdhill yubikey_hex_decode(char *dst, const char *src, size_t dstSize)
2565e4064a0Sdhill {
2575e4064a0Sdhill char b;
2585e4064a0Sdhill int flag = 0;
2595e4064a0Sdhill char *p1;
2605e4064a0Sdhill
2615e4064a0Sdhill for (; *src && dstSize > 0; src++) {
2626e526c06Shalex p1 = strchr(hex_trans, tolower((unsigned char)*src));
2636e526c06Shalex if (p1 == NULL)
2645e4064a0Sdhill b = 0;
2655e4064a0Sdhill else
2665e4064a0Sdhill b = (char)(p1 - hex_trans);
2675e4064a0Sdhill if ((flag = !flag))
2685e4064a0Sdhill *dst = b;
2695e4064a0Sdhill else {
2705e4064a0Sdhill *dst = (*dst << 4) | b;
2715e4064a0Sdhill dst++;
2725e4064a0Sdhill dstSize--;
2735e4064a0Sdhill }
2745e4064a0Sdhill }
2755e4064a0Sdhill while (dstSize--)
2765e4064a0Sdhill *dst++ = 0;
2775e4064a0Sdhill }
2785e4064a0Sdhill
2795e4064a0Sdhill static const char modhex_trans[] = "cbdefghijklnrtuv";
2805e4064a0Sdhill
2815e4064a0Sdhill void
yubikey_modhex_decode(char * dst,const char * src,size_t dstSize)2825e4064a0Sdhill yubikey_modhex_decode(char *dst, const char *src, size_t dstSize)
2835e4064a0Sdhill {
2845e4064a0Sdhill char b;
2855e4064a0Sdhill int flag = 0;
2865e4064a0Sdhill char *p1;
2875e4064a0Sdhill
2885e4064a0Sdhill for (; *src && dstSize > 0; src++) {
2896e526c06Shalex p1 = strchr(modhex_trans, tolower((unsigned char)*src));
2906e526c06Shalex if (p1 == NULL)
2915e4064a0Sdhill b = 0;
2925e4064a0Sdhill else
2935e4064a0Sdhill b = (char)(p1 - modhex_trans);
2945e4064a0Sdhill
2955e4064a0Sdhill if ((flag = !flag))
2965e4064a0Sdhill *dst = b;
2975e4064a0Sdhill else {
2985e4064a0Sdhill *dst = (*dst << 4) | b;
2995e4064a0Sdhill dst++;
3005e4064a0Sdhill dstSize--;
3015e4064a0Sdhill }
3025e4064a0Sdhill }
3035e4064a0Sdhill while (dstSize--)
3045e4064a0Sdhill *dst++ = 0;
3055e4064a0Sdhill }
3065e4064a0Sdhill
3073ef0233cSmcbride uint8_t
yubikey_keymap_decode(wchar_t * wpassword,char * token,int index)3083ef0233cSmcbride yubikey_keymap_decode(wchar_t *wpassword, char *token, int index)
3095e4064a0Sdhill {
3103ef0233cSmcbride int c, j, found;
3113ef0233cSmcbride for (j=0; j<YUBIKEY_TOKEN_SIZE; j++) {
3123ef0233cSmcbride found = 0;
3133ef0233cSmcbride for (c=0; c<16; c++) {
3143ef0233cSmcbride if (wpassword[j] == keymaps[index][c]) {
3153ef0233cSmcbride token[j] = modhex_trans[c];
3163ef0233cSmcbride found++;
3173ef0233cSmcbride break;
3183ef0233cSmcbride }
3193ef0233cSmcbride }
3203ef0233cSmcbride if (found == 0)
3213ef0233cSmcbride return 1;
3223ef0233cSmcbride }
3233ef0233cSmcbride return 0;
3243ef0233cSmcbride }
3253ef0233cSmcbride
3263ef0233cSmcbride int
yubikey_parse(const uint8_t * password,const uint8_t key[YUBIKEY_KEY_SIZE],yubikey_token_t out,int index)3273ef0233cSmcbride yubikey_parse(const uint8_t *password, const uint8_t key[YUBIKEY_KEY_SIZE],
3283ef0233cSmcbride yubikey_token_t out, int index)
3293ef0233cSmcbride {
3303ef0233cSmcbride wchar_t *wpassword, *pp;
3313ef0233cSmcbride char token[YUBIKEY_TOKEN_SIZE + 1], *lc_ctype;
332*6cc4e57dSanton size_t len;
333*6cc4e57dSanton int rc = 0;
3343ef0233cSmcbride
3353ef0233cSmcbride if (index < 0 || index >= YUBIKEY_KEYMAP_COUNT)
3363ef0233cSmcbride return -1;
3373ef0233cSmcbride
3383ef0233cSmcbride len = strlen(password);
33900f782e3Sderaadt pp = wpassword = reallocarray(NULL, len + 1, sizeof(wchar_t));
3403ef0233cSmcbride if (pp == NULL)
3413ef0233cSmcbride return ENOMEM;
3423ef0233cSmcbride
3435e4064a0Sdhill memset(out, 0, sizeof(*out));
3443ef0233cSmcbride memset(token, 0, YUBIKEY_TOKEN_SIZE + 1);
3453ef0233cSmcbride
3463ef0233cSmcbride lc_ctype = getenv("LC_CTYPE");
3473ef0233cSmcbride setlocale(LC_CTYPE, lc_ctype ? lc_ctype : "C.UTF-8");
3483ef0233cSmcbride len = mbstowcs(wpassword, password, len);
349*6cc4e57dSanton if (len == (size_t)-1) {
350*6cc4e57dSanton rc = errno;
351*6cc4e57dSanton goto ret;
3523ef0233cSmcbride }
3533ef0233cSmcbride setlocale(LC_CTYPE, "C");
3543ef0233cSmcbride
3553ef0233cSmcbride if (len > YUBIKEY_TOKEN_SIZE)
3563ef0233cSmcbride pp = pp + len - YUBIKEY_TOKEN_SIZE;
357*6cc4e57dSanton if (len < YUBIKEY_TOKEN_SIZE) {
358*6cc4e57dSanton rc = EMSGSIZE;
359*6cc4e57dSanton goto ret;
360*6cc4e57dSanton }
3613ef0233cSmcbride
362*6cc4e57dSanton if (yubikey_keymap_decode(pp, token, index)) {
363*6cc4e57dSanton rc = EINVAL;
364*6cc4e57dSanton goto ret;
365*6cc4e57dSanton }
3663ef0233cSmcbride yubikey_modhex_decode((void *)out, token, sizeof(*out));
3675e4064a0Sdhill yubikey_aes_decrypt((void *)out, key);
368*6cc4e57dSanton
369*6cc4e57dSanton ret:
370*6cc4e57dSanton freezero(wpassword, (len + 1) * sizeof(wchar_t));
371*6cc4e57dSanton return rc;
3725e4064a0Sdhill }
373