summaryrefslogtreecommitdiffstats
path: root/src/home/homework-fido2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/home/homework-fido2.c')
-rw-r--r--src/home/homework-fido2.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/home/homework-fido2.c b/src/home/homework-fido2.c
new file mode 100644
index 0000000..5c7cd52
--- /dev/null
+++ b/src/home/homework-fido2.c
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <fido.h>
+
+#include "hexdecoct.h"
+#include "homework-fido2.h"
+#include "libfido2-util.h"
+#include "memory-util.h"
+#include "strv.h"
+
+int fido2_use_token(
+ UserRecord *h,
+ UserRecord *secret,
+ const Fido2HmacSalt *salt,
+ char **ret) {
+
+ _cleanup_(erase_and_freep) void *hmac = NULL;
+ size_t hmac_size;
+ Fido2EnrollFlags flags = 0;
+ ssize_t ss;
+ int r;
+
+ assert(h);
+ assert(secret);
+ assert(salt);
+ assert(ret);
+
+ /* If we know the up/uv/clientPin settings used during enrollment, let's pass this on for
+ * authentication, or generate errors immediately if interactivity of the specified kind is not
+ * allowed. */
+
+ if (salt->up > 0) {
+ if (h->fido2_user_presence_permitted <= 0)
+ return -EMEDIUMTYPE;
+
+ flags |= FIDO2ENROLL_UP;
+ } else if (salt->up < 0) /* unset? */
+ flags |= FIDO2ENROLL_UP_IF_NEEDED; /* compat with pre-248 */
+
+ if (salt->uv > 0) {
+ if (h->fido2_user_verification_permitted <= 0)
+ return -ENOCSI;
+
+ flags |= FIDO2ENROLL_UV;
+ } else if (salt->uv < 0)
+ flags |= FIDO2ENROLL_UV_OMIT; /* compat with pre-248 */
+
+ if (salt->client_pin > 0) {
+
+ if (strv_isempty(secret->token_pin))
+ return -ENOANO;
+
+ flags |= FIDO2ENROLL_PIN;
+ } else if (salt->client_pin < 0)
+ flags |= FIDO2ENROLL_PIN_IF_NEEDED; /* compat with pre-248 */
+
+ r = fido2_use_hmac_hash(
+ NULL,
+ "io.systemd.home",
+ salt->salt, salt->salt_size,
+ salt->credential.id, salt->credential.size,
+ secret->token_pin,
+ flags,
+ &hmac,
+ &hmac_size);
+ if (r < 0)
+ return r;
+
+ ss = base64mem(hmac, hmac_size, ret);
+ if (ss < 0)
+ return log_error_errno(ss, "Failed to base64 encode HMAC secret: %m");
+
+ return 0;
+}