Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/passkey_child/passkey_child.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ int main(int argc, const char *argv[])
ERROR("Error getting assertion data.\n");
goto done;
}
} else if (data.action == ACTION_GET_DEVINFO) {
ret = get_device_info(&data);
if (ret != EOK) {
ERROR("Error getting device information.\n");
goto done;
}
} else if (data.action == ACTION_VERIFY_ASSERT) {
ret = verify_assert_data(&data);
if (ret == EOK) {
Expand Down
16 changes: 16 additions & 0 deletions src/passkey_child/passkey_child.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ enum action_opt {
ACTION_REGISTER,
ACTION_AUTHENTICATE,
ACTION_GET_ASSERT,
ACTION_GET_DEVINFO,
ACTION_VERIFY_ASSERT
};

Expand Down Expand Up @@ -540,6 +541,21 @@ print_assert_data(const char *key_handle, const char *crypto_challenge,
errno_t
get_assert_data(struct passkey_data *data);

/**
* @brief Obtain device information
*
* Obtain information of the device supporting one of the handles in parameters
*
* @param[in] data passkey data
*
* @return 0 if a device is available
* create file /var/run/passkey-pinonly or passkey-pinuv
* error code otherwise.
*/
errno_t
get_device_info(struct passkey_data *data);


/**
* @brief Verify assertion data
*
Expand Down
177 changes: 151 additions & 26 deletions src/passkey_child/passkey_child_assert.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <jansson.h>
#include <termios.h>
#include <stdio.h>
#include <fcntl.h>
#include <fido/es256.h>
#include <fido/rs256.h>
#include <fido/eddsa.h>
Expand Down Expand Up @@ -67,7 +68,7 @@ set_assert_client_data_hash(const struct passkey_data *data,
ret, fido_strerr(ret));
goto done;
}
} else {
} else if (data->action == ACTION_GET_ASSERT) {
crypto_challenge = sss_base64_decode(tmp_ctx, data->crypto_challenge,
&crypto_challenge_len);
if (crypto_challenge == NULL) {
Expand All @@ -93,6 +94,16 @@ set_assert_client_data_hash(const struct passkey_data *data,
goto done;
}
}
else {
memset(cdh, 0, sizeof(cdh));
ret = fido_assert_set_clientdata_hash(_assert, cdh, sizeof(cdh));
if (ret != FIDO_OK) {
DEBUG(SSSDBG_OP_FAILURE,
"fido_assert_set_clientdata_hash failed [%d]: %s.\n",
ret, fido_strerr(ret));
goto done;
}
}

done:
talloc_free(tmp_ctx);
Expand Down Expand Up @@ -329,6 +340,27 @@ reset_public_key(struct pk_data_t *_pk_data)
return EOK;
}

#define DOPIN "/var/run/passkey-dopin"

static
errno_t enable_dopin()
{
int fd = creat (DOPIN, (mode_t)0000);
DEBUG(SSSDBG_TRACE_LIBS, "enable_dopin file [%s] fd=[%d], errno: [%d].\n",
DOPIN , fd, (fd == -1)? errno : 0);
close(fd);
return EOK;
}

static
errno_t disable_dopin()
{
int ret = remove(DOPIN);
DEBUG(SSSDBG_TRACE_LIBS, "disable_dopin [%d]\n", ret);
return EOK;
}
#undef DOPIN

errno_t
request_assert(struct passkey_data *data, fido_dev_t *dev,
fido_assert_t *_assert)
Expand All @@ -337,7 +369,7 @@ request_assert(struct passkey_data *data, fido_dev_t *dev,
char *pin = NULL;
bool has_pin;
bool has_uv;
errno_t ret;
errno_t ret = FIDO_OK;

tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
Expand All @@ -347,54 +379,147 @@ request_assert(struct passkey_data *data, fido_dev_t *dev,

has_pin = fido_dev_has_pin(dev);
has_uv = fido_dev_has_uv(dev);

if (has_pin == true && data->user_verification != FIDO_OPT_FALSE) {
ret = passkey_recv_pin(tmp_ctx, STDIN_FILENO, &pin);
if (ret != EOK) {
DEBUG(SSSDBG_TRACE_FUNC, "PIN is missing: try UV\n");
ret = FIDO_ERR_PIN_REQUIRED;
/* and try UV that will reset the ret code.
*/
} else {
/* DEBUG(SSSDBG_TRACE_FUNC, "Proceed with PIN [%s]\n", pin); */
/* ------------- */
ret = fido_dev_get_assert(dev, _assert, pin);
if (ret != FIDO_OK) {
DEBUG(SSSDBG_OP_FAILURE, "fido_dev_get_assert PIN failed [%d]: %s.\n",
ret, fido_strerr(ret));
goto done;
}
DEBUG(SSSDBG_TRACE_FUNC, "fido_dev_get_assert PIN succeeded.\n");

/* error or not: finished */
goto done;
}
}

if (has_uv == true && data->user_verification != FIDO_OPT_FALSE) {
ret = fido_dev_get_assert(dev, _assert, NULL);
if (ret != FIDO_OK && has_pin == true) {
DEBUG(SSSDBG_OP_FAILURE,
"fido_dev_get_assert failed [%d]: %s. "
"Falling back to PIN authentication.\n",
"fido_dev_get_assert UV failed [%d]: %s. "
"User shall fall back to PIN authentication.\n",
ret, fido_strerr(ret));
} else if (ret != FIDO_OK) {
DEBUG(SSSDBG_OP_FAILURE, "fido_dev_get_assert failed [%d]: %s.\n",
DEBUG(SSSDBG_OP_FAILURE, "fido_dev_get_assert UV failed [%d]: %s.\n",
ret, fido_strerr(ret));
goto done;
} else {
DEBUG(SSSDBG_TRACE_FUNC, "fido_dev_get_assert succeeded.\n");
goto done;
DEBUG(SSSDBG_TRACE_FUNC, "fido_dev_get_assert UV succeeded.\n");
}
goto done;
}

if (has_pin == true && data->user_verification != FIDO_OPT_FALSE) {
ret = passkey_recv_pin(tmp_ctx, STDIN_FILENO, &pin);
if (ret != EOK) {
goto done;
}
}

ret = fido_dev_get_assert(dev, _assert, pin);
/* (no has_pin , no has_uv) or verification = FIDO_OPT_FALSE */
ret = fido_dev_get_assert(dev, _assert, NULL);
if (ret != FIDO_OK) {
DEBUG(SSSDBG_OP_FAILURE, "fido_dev_get_assert failed [%d]: %s.\n",
ret, fido_strerr(ret));
goto done;
}

ret = fido_assert_set_uv(_assert, data->user_verification);
if (ret != FIDO_OK) {
DEBUG(SSSDBG_OP_FAILURE,
"fido_assert_set_uv failed [%d]: %s.\n",
ret, fido_strerr(ret));
goto done;
DEBUG(SSSDBG_OP_FAILURE, "(no pin, no uv) fido_dev_get_assert failed [%d]: %s.\n",
ret, fido_strerr(ret));
}

done:
if (ret == FIDO_OK) {
ret = fido_assert_set_uv(_assert, data->user_verification);
if (ret != FIDO_OK) {
DEBUG(SSSDBG_OP_FAILURE,
"fido_assert_set_uv failed [%d]: %s.\n",
ret, fido_strerr(ret));
}
}
if (pin != NULL) {
sss_erase_mem_securely(pin, strlen(pin));
}
talloc_free(tmp_ctx);

if (ret == FIDO_OK && has_uv == true) {
/* PIN or UV has been OK */
(void)disable_dopin();
} else if (ret == FIDO_ERR_PIN_REQUIRED || ret == FIDO_ERR_UV_INVALID ||
ret == FIDO_ERR_PIN_INVALID || ret == FIDO_ERR_UV_BLOCKED) {
(void)enable_dopin();
}
return ret;
}

/*
*
* errno_t
* request_assert(struct passkey_data *data, fido_dev_t *dev,
* fido_assert_t *_assert)
* {
* TALLOC_CTX *tmp_ctx = NULL;
* char *pin = NULL;
* bool has_pin;
* bool has_uv;
* errno_t ret;
*
* tmp_ctx = talloc_new(NULL);
* if (tmp_ctx == NULL) {
* DEBUG(SSSDBG_OP_FAILURE, "talloc_new() failed.\n");
* return ENOMEM;
* }
*
* has_pin = fido_dev_has_pin(dev);
* has_uv = fido_dev_has_uv(dev);
* if (has_uv == true && data->user_verification != FIDO_OPT_FALSE) {
* ret = fido_dev_get_assert(dev, _assert, NULL);
* if (ret != FIDO_OK && has_pin == true) {
* DEBUG(SSSDBG_OP_FAILURE,
* "fido_dev_get_assert failed [%d]: %s. "
* "Falling back to PIN authentication.\n",
* ret, fido_strerr(ret));
* } else if (ret != FIDO_OK) {
* DEBUG(SSSDBG_OP_FAILURE, "fido_dev_get_assert failed [%d]: %s.\n",
* ret, fido_strerr(ret));
* goto done;
* } else {
* DEBUG(SSSDBG_TRACE_FUNC, "fido_dev_get_assert succeeded.\n");
* goto done;
* }
* }
*
* if (has_pin == true && data->user_verification != FIDO_OPT_FALSE) {
* ret = passkey_recv_pin(tmp_ctx, STDIN_FILENO, &pin);
* if (ret != EOK) {
* goto done;
* }
* }
*
* ret = fido_deev_get_assert(dev, _assert, pin);
* if (ret != FIDO_OK) {
* DEBUG(SSSDBG_OP_FAILURE, "fido_dev_get_assert failed [%d]: %s.\n",
* ret, fido_strerr(ret));
* goto done;
* }
*
* ret = fido_assert_set_uv(_assert, data->user_verification);
* if (ret != FIDO_OK) {
* DEBUG(SSSDBG_OP_FAILURE,
* "fido_assert_set_uv failed [%d]: %s.\n",
* ret, fido_strerr(ret));
* goto done;
* }
*
* done:
* if (pin != NULL) {
* sss_erase_mem_securely(pin, strlen(pin));
* }
* talloc_free(tmp_ctx);
*
* return ret;
* }
*/

errno_t
verify_assert(struct pk_data_t *pk_data, fido_assert_t *assert)
{
Expand Down
Loading