summaryrefslogtreecommitdiffstats
path: root/src/home/homework-fido2.c
blob: 5c7cd52e1b8869b04c76269fa29ee85e8ef8bea1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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;
}