Move verify and resync into the library.

This commit is contained in:
Dag-Erling Smørgrav 2018-08-03 13:50:06 +02:00
parent d5dc054392
commit 6bd043cac5
10 changed files with 240 additions and 38 deletions

View file

@ -45,6 +45,7 @@
#include <cryb/ctype.h>
#include <cryb/oath.h>
#include <cryb/otp.h>
#include <cryb/strlcmp.h>
#define MAX_KEYURI_SIZE 4096
@ -267,7 +268,7 @@ otpkey_verify(int argc, char *argv[])
{
oath_key key;
unsigned long counter;
unsigned int response;
unsigned long response;
char *end;
int match, ret;
@ -278,27 +279,18 @@ otpkey_verify(int argc, char *argv[])
response = strtoul(*argv, &end, 10);
if (end == *argv || *end != '\0')
response = UINT_MAX; /* never valid */
switch (key.mode) {
case om_hotp:
if (key.mode == om_hotp)
counter = key.counter;
match = oath_hotp_match(&key, response, HOTP_WINDOW);
if (verbose && match > 0 && key.counter > counter + 1)
warnx("skipped %lu codes", key.counter - counter - 1);
break;
case om_totp:
match = oath_totp_match(&key, response, TOTP_WINDOW);
break;
default:
match = -1;
}
/* oath_*_match() return -1 on error, 0 on failure, 1 on success */
match = otp_verify(&key, response);
if (match < 0) {
warnx("OATH error");
match = 0;
}
if (verbose)
warnx("response: %u %s", response,
match ? "matched" : "did not match");
if (verbose) {
warnx("response %s", match ? "matched" : "did not match");
if (key.mode == om_hotp && key.counter > counter + 1)
warnx("skipped %lu codes", key.counter - counter - 1);
}
ret = match ? readonly ? RET_SUCCESS : otpkey_save(&key) : RET_FAILURE;
oath_key_destroy(&key);
return (ret);
@ -365,7 +357,7 @@ otpkey_resync(int argc, char *argv[])
{
oath_key key;
unsigned long counter;
unsigned int response[3];
unsigned long response[3];
char *end;
int i, match, n, ret, w;
@ -381,31 +373,18 @@ otpkey_resync(int argc, char *argv[])
w -= n;
if ((ret = otpkey_load(&key)) != RET_SUCCESS)
return (ret);
switch (key.mode) {
case om_hotp:
/* this should be a library function */
if (key.mode == om_hotp)
counter = key.counter;
match = 0;
while (key.counter < counter + w && match == 0) {
match = oath_hotp_match(&key, response[0],
counter + w - key.counter - 1);
if (match <= 0)
break;
for (i = 1; i < n && match > 0; ++i)
match = oath_hotp_match(&key, response[i], 0);
}
if (verbose && match > 0)
warnx("skipped %lu codes", key.counter - counter);
break;
default:
match = -1;
}
match = otp_resync(&key, response, n);
if (match < 0) {
warnx("OATH error");
match = 0;
}
if (verbose)
if (verbose) {
warnx("resynchronization %s", match ? "succeeded" : "failed");
if (counter > key.counter + 1)
warnx("skipped %lu codes", key.counter - counter);
}
ret = match ? readonly ? RET_SUCCESS : otpkey_save(&key) : RET_FAILURE;
oath_key_destroy(&key);
return (ret);

View file

@ -38,6 +38,12 @@ CRYB_BEGIN
const char *cryb_otp_version(void);
#define otp_verify cryb_otp_verify
#define otp_resync cryb_otp_resync
int otp_verify(oath_key *, unsigned long);
int otp_resync(oath_key *, unsigned long *, unsigned int);
CRYB_END
#endif

View file

@ -3,6 +3,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
lib_LTLIBRARIES = libcryb-otp.la
libcryb_otp_la_SOURCES = \
cryb_otp_resync.c \
cryb_otp_verify.c \
\
cryb_otp.c

View file

@ -29,9 +29,10 @@
#include "cryb/impl.h"
#include <stddef.h>
#include <stdint.h>
#include <unistd.h>
#include <cryb/oath.h>
#include <cryb/otp.h>
static const char *cryb_otp_version_string = PACKAGE_VERSION;

40
lib/otp/cryb_otp_impl.h Normal file
View file

@ -0,0 +1,40 @@
/*-
* Copyright (c) 2018 The University of Oslo
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef CRYB_OTP_IMPL_H_INCLUDED
#define CRYB_OTP_IMPL_H_INCLUDED
/* XXX hardcoded windows */
#define HOTP_WINDOW 9
#define TOTP_WINDOW 2
struct otp_store {
};
#endif

96
lib/otp/cryb_otp_resync.c Normal file
View file

@ -0,0 +1,96 @@
/*-
* Copyright (c) 2013-2018 The University of Oslo
* Copyright (c) 2016-2018 Dag-Erling Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "cryb/impl.h"
#include <stddef.h>
#include <stdint.h>
#include <cryb/assert.h>
#include <cryb/oath.h>
#include <cryb/otp.h>
#include "cryb_otp_impl.h"
/*
* Resynchronize a desynchronized event-mode key.
*
* XXX review carefully for off-by-one errors, and write unit tests
*/
static int
otp_resync_recursive(oath_key *key, unsigned long *response,
unsigned int n, unsigned int w)
{
uint64_t first, prev, last;
int ret;
first = key->counter;
last = first + w;
while (w > 0) {
prev = key->counter;
ret = oath_hotp_match(key, response[0], last - key->counter);
if (ret < 1)
return (ret);
assertf(key->counter > prev, "counter did not advance");
w -= key->counter - prev;
if (n == 1)
return (key->counter - prev);
prev = key->counter;
ret = otp_resync_recursive(key, response + 1, n - 1, w);
if (ret > 0)
return (ret);
key->counter = prev;
}
return (0);
}
int
otp_resync(oath_key *key, unsigned long *response, unsigned int n)
{
unsigned int i, w;
int ret;
/* only applicable to RFC 4226 HOTP for now */
/* note: n == 1 is identical to otp_verify() */
if (key->mode != om_hotp || n < 1)
return (-1);
/* compute window size based on number of responses */
for (i = 0, w = 1; i < n; ++i)
w = w * (HOTP_WINDOW + 1);
/* recursive search within window */
ret = otp_resync_recursive(key, response, n, w);
/* ... */
return (ret);
}

75
lib/otp/cryb_otp_verify.c Normal file
View file

@ -0,0 +1,75 @@
/*-
* Copyright (c) 2013-2018 The University of Oslo
* Copyright (c) 2016-2018 Dag-Erling Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "cryb/impl.h"
#include <stddef.h>
#include <stdint.h>
#include <cryb/assert.h>
#include <cryb/oath.h>
#include <cryb/otp.h>
#include "cryb_otp_impl.h"
/*
* Check whether a given response is correct for the given keyfile.
*/
int
otp_verify(oath_key *key, unsigned long response)
{
uint64_t prev;
int ret;
switch (key->mode) {
case om_hotp:
prev = key->counter;
ret = oath_hotp_match(key, response, HOTP_WINDOW);
assertf(key->counter >= prev, "counter went backwads");
if (ret > 0) {
assertf(key->counter > prev, "counter did not advance");
ret = key->counter - prev - 1;
}
break;
case om_totp:
prev = key->lastused;
ret = oath_totp_match(key, response, TOTP_WINDOW);
assertf(key->lastused >= prev, "lastused went backwards");
if (ret > 0) {
assertf(key->lastused > prev, "lastused did not advance");
ret = key->lastused - prev / key->timestep;
}
break;
default:
ret = -1;
}
/* oath_*_ret() return -1 on error, 0 on failure, 1 on success */
return (ret);
}

View file

@ -33,6 +33,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <cryb/oath.h>
#include <cryb/otp.h>
static void

View file

@ -36,6 +36,7 @@
#include <security/pam_modules.h>
#include <security/pam_appl.h>
#include <cryb/oath.h>
#include <cryb/otp.h>
int

View file

@ -33,6 +33,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <cryb/oath.h>
#include <cryb/otp.h>
static void