otp-parse.c revision a10ed8c47534b4c6b6bf2711ccfe577e720a47b4
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * OTP extended response parser.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * Copyright (c) 2006 Andrey Panin <pazke@donpac.ru>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * This software is released under the MIT license.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "lib.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "buffer.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "str.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "strfuncs.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "hex-binary.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "otp.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <stdlib.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <ctype.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define IS_LWS(c) ((c) == ' ' || (c) == '\t')
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
a0166609f782da91710dea9183d1bf138538db37Tom Gundersenstatic inline const char *otp_skip_lws(const char *data)
71d35b6b5563817dfbe757ab9e3b9f018b2db491Thomas Hindoe Paaboel Andersen{
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering while (*data && IS_LWS(*data))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering data++;
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering return data;
71d35b6b5563817dfbe757ab9e3b9f018b2db491Thomas Hindoe Paaboel Andersen}
71d35b6b5563817dfbe757ab9e3b9f018b2db491Thomas Hindoe Paaboel Andersen
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poetteringstatic inline int otp_check_tail(const char *data)
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering{
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering data = otp_skip_lws(data);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
51323288fc628a5cac50914df915545d685b793eLennart Poettering return *data != 0;
71d35b6b5563817dfbe757ab9e3b9f018b2db491Thomas Hindoe Paaboel Andersen}
71d35b6b5563817dfbe757ab9e3b9f018b2db491Thomas Hindoe Paaboel Andersen
71d35b6b5563817dfbe757ab9e3b9f018b2db491Thomas Hindoe Paaboel Andersenint otp_read_hex(const char *data, const char **endptr, unsigned char *hash)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering{
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering string_t *str;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering buffer_t buf;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering unsigned int i = 0;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (data == NULL)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return -1;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering str = t_str_new(18);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering buffer_create_data(&buf, hash, OTP_HASH_SIZE);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering while (*data) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char c = *data;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (i_isxdigit(c)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering str_append_c(str, c);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (++i == OTP_HASH_SIZE * 2) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering data++;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
a0166609f782da91710dea9183d1bf138538db37Tom Gundersen }
c73ce96b569e2f10dff64b7dc0bd271972674c2aLennart Poettering } else if (!IS_LWS(c)) {
c73ce96b569e2f10dff64b7dc0bd271972674c2aLennart Poettering *endptr = data;
c73ce96b569e2f10dff64b7dc0bd271972674c2aLennart Poettering return -1;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering }
c73ce96b569e2f10dff64b7dc0bd271972674c2aLennart Poettering data++;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering }
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering *endptr = data;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen if (i < OTP_HASH_SIZE * 2)
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen return -1;
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return hex_to_binary(str_c(str), &buf);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define add_word() do { \
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering tmp = otp_lookup_word(str_c(word)); \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering buffer_append(&buf, &tmp, sizeof(tmp)); \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering count++; \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering} while (0)
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringint otp_read_words(const char *data, const char **endptr, unsigned char *hash)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering{
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering bool space = FALSE;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering unsigned int len = 0, count = 0;
d75acfb059ece4512278b8820a9103664996f1e5Lennart Poettering unsigned int parity = 0, bits[OTP_WORDS_NUMBER], tmp;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering string_t *word;
dc61b7e45d89a69f0469ab7b3289cdde7fcc55abTorstein Husebø buffer_t buf;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (data == NULL)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return -1;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering word = t_str_new(8);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
9c491563837983385bf9fa244590e76e142f4fa3Daniel Mack data = otp_skip_lws(data);
9c491563837983385bf9fa244590e76e142f4fa3Daniel Mack
9c491563837983385bf9fa244590e76e142f4fa3Daniel Mack buffer_create_data(&buf, bits, sizeof(bits));
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart Poettering
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart Poettering for (; *data && (count < OTP_WORDS_NUMBER); data++) {
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart Poettering char c = *data;
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (space) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (IS_LWS(c))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else if (i_isalpha(c)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering str_append_c(word, c);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering space = FALSE;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering len = 1;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (i_isalpha(c)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (len > OTP_MAX_WORD_LEN) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering count = 0;
3cb10d3a0b1b6a7c44f307f2abb5215104e16941Lennart Poettering break;
3cb10d3a0b1b6a7c44f307f2abb5215104e16941Lennart Poettering }
3cb10d3a0b1b6a7c44f307f2abb5215104e16941Lennart Poettering str_append_c(word, c);
8b757a38611006a751c90933d1810cccaa47e1afDaniel Mack continue;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering } else if (IS_LWS(c)) {
8b757a38611006a751c90933d1810cccaa47e1afDaniel Mack add_word();
8b757a38611006a751c90933d1810cccaa47e1afDaniel Mack str_truncate(word, 0);
8b757a38611006a751c90933d1810cccaa47e1afDaniel Mack space = TRUE;
8b757a38611006a751c90933d1810cccaa47e1afDaniel Mack continue;
f3abbe25403444688e1a1a23b9dbcc9aeefc0507Lennart Poettering }
f3abbe25403444688e1a1a23b9dbcc9aeefc0507Lennart Poettering }
f3abbe25403444688e1a1a23b9dbcc9aeefc0507Lennart Poettering break;
f3abbe25403444688e1a1a23b9dbcc9aeefc0507Lennart Poettering }
f3abbe25403444688e1a1a23b9dbcc9aeefc0507Lennart Poettering
f3abbe25403444688e1a1a23b9dbcc9aeefc0507Lennart Poettering if ((str_len(word) > 0) && (count == OTP_WORDS_NUMBER - 1))
f3abbe25403444688e1a1a23b9dbcc9aeefc0507Lennart Poettering add_word();
f3abbe25403444688e1a1a23b9dbcc9aeefc0507Lennart Poettering
f3abbe25403444688e1a1a23b9dbcc9aeefc0507Lennart Poettering if (endptr)
f3abbe25403444688e1a1a23b9dbcc9aeefc0507Lennart Poettering *endptr = data;
f3abbe25403444688e1a1a23b9dbcc9aeefc0507Lennart Poettering
8b757a38611006a751c90933d1810cccaa47e1afDaniel Mack if (count < OTP_WORDS_NUMBER)
8b757a38611006a751c90933d1810cccaa47e1afDaniel Mack return -1;
8b757a38611006a751c90933d1810cccaa47e1afDaniel Mack
8b757a38611006a751c90933d1810cccaa47e1afDaniel Mack hash[0] = bits[0] >> 3;
8b757a38611006a751c90933d1810cccaa47e1afDaniel Mack hash[1] = ((bits[0] & 7) << 5) | (bits[1] >> 6);
3cb10d3a0b1b6a7c44f307f2abb5215104e16941Lennart Poettering hash[2] = ((bits[1] & 0x3f) << 2) | (bits[2] >> 9);
3cb10d3a0b1b6a7c44f307f2abb5215104e16941Lennart Poettering hash[3] = (bits[2] >> 1) & 0xff;
3cb10d3a0b1b6a7c44f307f2abb5215104e16941Lennart Poettering hash[4] = ((bits[2] & 3) << 7) | (bits[3] >> 4);
3cb10d3a0b1b6a7c44f307f2abb5215104e16941Lennart Poettering hash[5] = ((bits[3] & 15) << 4) | (bits[4] >> 7);
3cb10d3a0b1b6a7c44f307f2abb5215104e16941Lennart Poettering hash[6] = ((bits[4] & 0x7f) << 1) | (bits[5] >> 10);
3cb10d3a0b1b6a7c44f307f2abb5215104e16941Lennart Poettering hash[7] = (bits[5] >> 2) & 0xff;
f0258e473667f44f4656dde49597b2badb9f598aLennart Poettering parity = bits[5] & 3;
f0258e473667f44f4656dde49597b2badb9f598aLennart Poettering
f0258e473667f44f4656dde49597b2badb9f598aLennart Poettering return otp_parity(hash) != parity;
f0258e473667f44f4656dde49597b2badb9f598aLennart Poettering}
f0258e473667f44f4656dde49597b2badb9f598aLennart Poettering
f0258e473667f44f4656dde49597b2badb9f598aLennart Poetteringint otp_read_new_params(const char *data, const char **endptr,
f0258e473667f44f4656dde49597b2badb9f598aLennart Poettering struct otp_state *state)
f0258e473667f44f4656dde49597b2badb9f598aLennart Poettering{
f0258e473667f44f4656dde49597b2badb9f598aLennart Poettering const char *p, *s;
3cb10d3a0b1b6a7c44f307f2abb5215104e16941Lennart Poettering char *end;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering unsigned int i = 0;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering int algo;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering s = p = data;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering while ((*p != 0) && !IS_LWS(*p)) p++;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (*p == 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return -1;
24710c48ed16be5fa461fbb303a744a907541dafLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering algo = digest_find(t_strdup_until(s, p++));
dbfbb6e776d613cb9be76d13de076d08450c9d29Daniel Mack if (algo < 0)
dbfbb6e776d613cb9be76d13de076d08450c9d29Daniel Mack return -2;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering state->algo = algo;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s = p;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering state->seq = strtol(s, &end, 10); p = end;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if ((p == s) || !IS_LWS(*p))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -3;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering p++;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering while (i_isalnum(*p) && (i < OTP_MAX_SEED_LEN))
8af5b883227ac8dfa796742b9edcc1647a5d4d6cLennart Poettering state->seed[i++] = i_tolower(*p++);
8af5b883227ac8dfa796742b9edcc1647a5d4d6cLennart Poettering state->seed[i] = 0;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *endptr = p;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poetteringint otp_parse_response(const char *data, unsigned char *hash, bool hex)
a3db237b8f1b97867395e1419f39b8ba5749b777Lennart Poettering{
a3db237b8f1b97867395e1419f39b8ba5749b777Lennart Poettering const char *end;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering int ret = hex ? otp_read_hex(data, &end, hash) :
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart Poettering otp_read_words(data, &end, hash);
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering if (ret < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return ret;
9c5e12a4314e7192e834e1b855e5e80111e636a6Tom Gundersen
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering return otp_check_tail(end);
9c5e12a4314e7192e834e1b855e5e80111e636a6Tom Gundersen}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringint otp_parse_init_response(const char *data, struct otp_state *new_state,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering unsigned char *hash, bool hex, const char **error)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering{
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *end;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int ret = hex ? otp_read_hex(data, &end, hash) :
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poettering otp_read_words(data, &end, hash);
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poettering if (ret < 0) {
d2579eec5e1b845b2cf29caddc951dc22f2abb91Lennart Poettering *error = "invalid current OTP";
d2579eec5e1b845b2cf29caddc951dc22f2abb91Lennart Poettering return ret;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering end = otp_skip_lws(end);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (*end++ != ':') {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering *error = "missing colon";
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -1;
d830ebbdf67d8cb32d33d8fdd47cf467fd6d3815Lennart Poettering }
d830ebbdf67d8cb32d33d8fdd47cf467fd6d3815Lennart Poettering
d830ebbdf67d8cb32d33d8fdd47cf467fd6d3815Lennart Poettering ret = otp_read_new_params(end, &end, new_state);
d830ebbdf67d8cb32d33d8fdd47cf467fd6d3815Lennart Poettering if (ret < 0) {
d830ebbdf67d8cb32d33d8fdd47cf467fd6d3815Lennart Poettering *error = "invalid OTP parameters";
d830ebbdf67d8cb32d33d8fdd47cf467fd6d3815Lennart Poettering return -1;
d830ebbdf67d8cb32d33d8fdd47cf467fd6d3815Lennart Poettering }
d830ebbdf67d8cb32d33d8fdd47cf467fd6d3815Lennart Poettering
f3abbe25403444688e1a1a23b9dbcc9aeefc0507Lennart Poettering end = otp_skip_lws(end);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (*end++ != ':') {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *error = "missing colon";
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ret = hex ? otp_read_hex(end, &end, new_state->hash) :
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering otp_read_words(end, &end, new_state->hash);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (ret < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *error = "invalid new OTP";
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (otp_check_tail(end) != 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *error = "trailing garbage found";
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint otp_parse_dbentry(const char *text, struct otp_state *state)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering{
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *end;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int ret;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering ret = otp_read_new_params(text, &end, state);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (ret != 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return ret;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (*end++ != ' ')
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return -1;
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek
0db4c90afd7d9c7c8884bf8b3ec459edc74a03daDaniel Mack return otp_read_hex(end, &end, state->hash);
b6c5d46b23a28b5b03601ee1e8162b1bc7c7be25Daniel Mack}
0db4c90afd7d9c7c8884bf8b3ec459edc74a03daDaniel Mack
931851e8e492a4d2715e22dcde50a5e7ccef4b49Lennart Poetteringconst char *otp_print_dbentry(const struct otp_state *state)
931851e8e492a4d2715e22dcde50a5e7ccef4b49Lennart Poettering{
51323288fc628a5cac50914df915545d685b793eLennart Poettering return t_strdup_printf("%s %d %s %s", digest_name(state->algo),
931851e8e492a4d2715e22dcde50a5e7ccef4b49Lennart Poettering state->seq, state->seed,
931851e8e492a4d2715e22dcde50a5e7ccef4b49Lennart Poettering binary_to_hex(state->hash, 8));
931851e8e492a4d2715e22dcde50a5e7ccef4b49Lennart Poettering}
51323288fc628a5cac50914df915545d685b793eLennart Poettering