1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <fido.h>
4 
5 #include "hexdecoct.h"
6 #include "homework-fido2.h"
7 #include "libfido2-util.h"
8 #include "memory-util.h"
9 #include "strv.h"
10 
fido2_use_token(UserRecord * h,UserRecord * secret,const Fido2HmacSalt * salt,char ** ret)11 int fido2_use_token(
12                 UserRecord *h,
13                 UserRecord *secret,
14                 const Fido2HmacSalt *salt,
15                 char **ret) {
16 
17         _cleanup_(erase_and_freep) void *hmac = NULL;
18         size_t hmac_size;
19         Fido2EnrollFlags flags = 0;
20         int r;
21 
22         assert(h);
23         assert(secret);
24         assert(salt);
25         assert(ret);
26 
27         /* If we know the up/uv/clientPin settings used during enrollment, let's pass this on for
28          * authentication, or generate errors immediately if interactivity of the specified kind is not
29          * allowed. */
30 
31         if (salt->up > 0) {
32                 if (h->fido2_user_presence_permitted <= 0)
33                         return -EMEDIUMTYPE;
34 
35                 flags |= FIDO2ENROLL_UP;
36         } else if (salt->up < 0) /* unset? */
37                 flags |= FIDO2ENROLL_UP_IF_NEEDED; /* compat with pre-248 */
38 
39         if (salt->uv > 0) {
40                 if (h->fido2_user_verification_permitted <= 0)
41                         return -ENOCSI;
42 
43                 flags |= FIDO2ENROLL_UV;
44         } else if (salt->uv < 0)
45                 flags |= FIDO2ENROLL_UV_OMIT; /* compat with pre-248 */
46 
47         if (salt->client_pin > 0) {
48 
49                 if (strv_isempty(secret->token_pin))
50                         return -ENOANO;
51 
52                 flags |= FIDO2ENROLL_PIN;
53         } else if (salt->client_pin < 0)
54                 flags |= FIDO2ENROLL_PIN_IF_NEEDED; /* compat with pre-248 */
55 
56         r = fido2_use_hmac_hash(
57                         NULL,
58                         "io.systemd.home",
59                         salt->salt, salt->salt_size,
60                         salt->credential.id, salt->credential.size,
61                         secret->token_pin,
62                         flags,
63                         &hmac,
64                         &hmac_size);
65         if (r < 0)
66                 return r;
67 
68         r = base64mem(hmac, hmac_size, ret);
69         if (r < 0)
70                 return log_error_errno(r, "Failed to base64 encode HMAC secret: %m");
71 
72         return 0;
73 }
74