From 066e2b91ffe594dbfd0eabe55c3ec7f0f587309a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Thu, 15 Aug 2013 15:21:31 +0000 Subject: [PATCH] Record the last successful use of a TOTP key. Also add commented-out logic to prevent reuse of the same code or an earlier code within the window, and make some minor type adjustments. git-svn-id: svn+ssh://svn.openpam.org/svn/openpam/trunk@693 185d5e19-27fe-0310-9dcf-9bff6b9f3609 --- include/security/oath.h | 4 ++-- include/security/oath_types.h | 1 + lib/liboath/oath_hotp.c | 4 ++-- lib/liboath/oath_totp.c | 16 ++++++++++++++-- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/include/security/oath.h b/include/security/oath.h index 7dfed25..ae9ea98 100644 --- a/include/security/oath.h +++ b/include/security/oath.h @@ -45,11 +45,11 @@ char *oath_key_to_uri(const struct oath_key *); struct oath_key *oath_dummy_key(enum oath_mode, enum oath_hash, unsigned int); unsigned int oath_hotp(const uint8_t *, size_t, uint64_t, unsigned int); -int oath_hotp_current(struct oath_key *); +unsigned int oath_hotp_current(struct oath_key *); int oath_hotp_match(struct oath_key *, unsigned int, int); unsigned int oath_totp(const uint8_t *, size_t, unsigned int); -int oath_totp_match(const struct oath_key *, unsigned int, int); unsigned int oath_totp_current(const struct oath_key *); +int oath_totp_match(struct oath_key *, unsigned int, int); #endif diff --git a/include/security/oath_types.h b/include/security/oath_types.h index 84324db..8877f41 100644 --- a/include/security/oath_types.h +++ b/include/security/oath_types.h @@ -41,6 +41,7 @@ struct oath_key { unsigned int digits; uint64_t counter; unsigned int timestep; /* in seconds */ + uint64_t lastuse; /* housekeeping */ unsigned int mapped:1; diff --git a/lib/liboath/oath_hotp.c b/lib/liboath/oath_hotp.c index 28d0d63..e3df98e 100644 --- a/lib/liboath/oath_hotp.c +++ b/lib/liboath/oath_hotp.c @@ -92,7 +92,7 @@ oath_hotp(const uint8_t *K, size_t Klen, uint64_t seq, unsigned int Digit) /* * Computes the current code for the given key and advances the counter. */ -int +unsigned int oath_hotp_current(struct oath_key *k) { unsigned int code; @@ -111,7 +111,7 @@ oath_hotp_current(struct oath_key *k) /* * Compares the code provided by the user with expected values within a * given window. Returns 1 if there was a match, 0 if not, and -1 if an - * error occurred. + * error occurred. Also advances the counter if there was a match. */ int oath_hotp_match(struct oath_key *k, unsigned int response, int window) diff --git a/lib/liboath/oath_totp.c b/lib/liboath/oath_totp.c index 4c3e2c4..195e8d5 100644 --- a/lib/liboath/oath_totp.c +++ b/lib/liboath/oath_totp.c @@ -67,8 +67,13 @@ oath_totp_current(const struct oath_key *k) return (code); } +/* + * Compares the code provided by the user with expected values within a + * given window. Returns 1 if there was a match, 0 if not, and -1 if an + * error occurred. + */ int -oath_totp_match(const struct oath_key *k, unsigned int response, int window) +oath_totp_match(struct oath_key *k, unsigned int response, int window) { unsigned int code; uint64_t seq; @@ -85,9 +90,16 @@ oath_totp_match(const struct oath_key *k, unsigned int response, int window) seq = time(NULL) / k->timestep; dummy = (strcmp(k->label, OATH_DUMMY_LABEL) == 0); for (int i = -window; i <= window; ++i) { +#if OATH_TOTP_PREVENT_REUSE + /* XXX disabled for now, should be a key parameter? */ + if (seq + i <= k->lastuse) + continue; +#endif code = oath_hotp(k->key, k->keylen, seq + i, k->digits); - if (code == response && !dummy) + if (code == response && !dummy) { + k->lastuse = seq; return (1); + } } return (0); }