195dbdf32Schristos /*
295dbdf32Schristos * Copyright (c) 2020 Yubico AB. All rights reserved.
395dbdf32Schristos * Use of this source code is governed by a BSD-style
495dbdf32Schristos * license that can be found in the LICENSE file.
5*2d40c451Schristos * SPDX-License-Identifier: BSD-2-Clause
695dbdf32Schristos */
795dbdf32Schristos
895dbdf32Schristos #include <stdio.h>
995dbdf32Schristos #include <stdlib.h>
1095dbdf32Schristos #include <string.h>
1195dbdf32Schristos
1295dbdf32Schristos #include <fido.h>
1395dbdf32Schristos #include <fido/config.h>
1495dbdf32Schristos
1595dbdf32Schristos #include "../openbsd-compat/openbsd-compat.h"
1695dbdf32Schristos #include "extern.h"
1795dbdf32Schristos
1895dbdf32Schristos int
config_entattest(char * path)1995dbdf32Schristos config_entattest(char *path)
2095dbdf32Schristos {
2195dbdf32Schristos fido_dev_t *dev;
2295dbdf32Schristos char *pin = NULL;
2395dbdf32Schristos int r, ok = 1;
2495dbdf32Schristos
2595dbdf32Schristos dev = open_dev(path);
2695dbdf32Schristos if ((r = fido_dev_enable_entattest(dev, NULL)) != FIDO_OK &&
2795dbdf32Schristos should_retry_with_pin(dev, r)) {
2895dbdf32Schristos if ((pin = get_pin(path)) == NULL)
2995dbdf32Schristos goto out;
3095dbdf32Schristos r = fido_dev_enable_entattest(dev, pin);
3195dbdf32Schristos freezero(pin, PINBUF_LEN);
3295dbdf32Schristos pin = NULL;
3395dbdf32Schristos }
3495dbdf32Schristos if (r != FIDO_OK) {
3595dbdf32Schristos warnx("fido_dev_enable_entattest: %s (0x%x)",
3695dbdf32Schristos fido_strerr(r), r);
3795dbdf32Schristos goto out;
3895dbdf32Schristos }
3995dbdf32Schristos
4095dbdf32Schristos ok = 0;
4195dbdf32Schristos out:
4295dbdf32Schristos fido_dev_close(dev);
4395dbdf32Schristos fido_dev_free(&dev);
4495dbdf32Schristos
4595dbdf32Schristos exit(ok);
4695dbdf32Schristos }
4795dbdf32Schristos
4895dbdf32Schristos int
config_always_uv(char * path,int toggle)4995dbdf32Schristos config_always_uv(char *path, int toggle)
5095dbdf32Schristos {
5195dbdf32Schristos fido_dev_t *dev;
5295dbdf32Schristos char *pin = NULL;
5395dbdf32Schristos int v, r, ok = 1;
5495dbdf32Schristos
5595dbdf32Schristos dev = open_dev(path);
5695dbdf32Schristos if (get_devopt(dev, "alwaysUv", &v) < 0) {
5795dbdf32Schristos warnx("%s: getdevopt", __func__);
5895dbdf32Schristos goto out;
5995dbdf32Schristos }
6095dbdf32Schristos if (v == -1) {
6195dbdf32Schristos warnx("%s: option not found", __func__);
6295dbdf32Schristos goto out;
6395dbdf32Schristos }
6495dbdf32Schristos if (v == toggle) {
6595dbdf32Schristos ok = 0;
6695dbdf32Schristos goto out;
6795dbdf32Schristos }
6895dbdf32Schristos if ((r = fido_dev_toggle_always_uv(dev, NULL)) != FIDO_OK &&
6995dbdf32Schristos should_retry_with_pin(dev, r)) {
7095dbdf32Schristos if ((pin = get_pin(path)) == NULL)
7195dbdf32Schristos goto out;
7295dbdf32Schristos r = fido_dev_toggle_always_uv(dev, pin);
7395dbdf32Schristos freezero(pin, PINBUF_LEN);
7495dbdf32Schristos pin = NULL;
7595dbdf32Schristos }
7695dbdf32Schristos if (r != FIDO_OK) {
7795dbdf32Schristos warnx("fido_dev_toggle_always_uv: %s (0x%x)",
7895dbdf32Schristos fido_strerr(r), r);
7995dbdf32Schristos goto out;
8095dbdf32Schristos }
8195dbdf32Schristos
8295dbdf32Schristos ok = 0;
8395dbdf32Schristos out:
8495dbdf32Schristos fido_dev_close(dev);
8595dbdf32Schristos fido_dev_free(&dev);
8695dbdf32Schristos
8795dbdf32Schristos exit(ok);
8895dbdf32Schristos }
8995dbdf32Schristos
9095dbdf32Schristos int
config_pin_minlen(char * path,const char * pinlen)9195dbdf32Schristos config_pin_minlen(char *path, const char *pinlen)
9295dbdf32Schristos {
9395dbdf32Schristos fido_dev_t *dev;
9495dbdf32Schristos char *pin = NULL;
9595dbdf32Schristos int len, r, ok = 1;
9695dbdf32Schristos
9795dbdf32Schristos dev = open_dev(path);
9895dbdf32Schristos if ((len = base10(pinlen)) < 0 || len > 63) {
9995dbdf32Schristos warnx("%s: len > 63", __func__);
10095dbdf32Schristos goto out;
10195dbdf32Schristos }
10295dbdf32Schristos if ((r = fido_dev_set_pin_minlen(dev, (size_t)len, NULL)) != FIDO_OK &&
10395dbdf32Schristos should_retry_with_pin(dev, r)) {
10495dbdf32Schristos if ((pin = get_pin(path)) == NULL)
10595dbdf32Schristos goto out;
10695dbdf32Schristos r = fido_dev_set_pin_minlen(dev, (size_t)len, pin);
10795dbdf32Schristos freezero(pin, PINBUF_LEN);
10895dbdf32Schristos pin = NULL;
10995dbdf32Schristos }
11095dbdf32Schristos if (r != FIDO_OK) {
11195dbdf32Schristos warnx("fido_dev_set_pin_minlen: %s (0x%x)", fido_strerr(r), r);
11295dbdf32Schristos goto out;
11395dbdf32Schristos }
11495dbdf32Schristos
11595dbdf32Schristos ok = 0;
11695dbdf32Schristos out:
11795dbdf32Schristos fido_dev_close(dev);
11895dbdf32Schristos fido_dev_free(&dev);
11995dbdf32Schristos
12095dbdf32Schristos exit(ok);
12195dbdf32Schristos }
12295dbdf32Schristos
12395dbdf32Schristos int
config_force_pin_change(char * path)12495dbdf32Schristos config_force_pin_change(char *path)
12595dbdf32Schristos {
12695dbdf32Schristos fido_dev_t *dev;
12795dbdf32Schristos char *pin = NULL;
12895dbdf32Schristos int r, ok = 1;
12995dbdf32Schristos
13095dbdf32Schristos dev = open_dev(path);
13195dbdf32Schristos if ((r = fido_dev_force_pin_change(dev, NULL)) != FIDO_OK &&
13295dbdf32Schristos should_retry_with_pin(dev, r)) {
13395dbdf32Schristos if ((pin = get_pin(path)) == NULL)
13495dbdf32Schristos goto out;
13595dbdf32Schristos r = fido_dev_force_pin_change(dev, pin);
13695dbdf32Schristos freezero(pin, PINBUF_LEN);
13795dbdf32Schristos pin = NULL;
13895dbdf32Schristos }
13995dbdf32Schristos if (r != FIDO_OK) {
14095dbdf32Schristos warnx("fido_dev_force_pin_change: %s (0x%x)", fido_strerr(r), r);
14195dbdf32Schristos goto out;
14295dbdf32Schristos }
14395dbdf32Schristos
14495dbdf32Schristos ok = 0;
14595dbdf32Schristos out:
14695dbdf32Schristos fido_dev_close(dev);
14795dbdf32Schristos fido_dev_free(&dev);
14895dbdf32Schristos
14995dbdf32Schristos exit(ok);
15095dbdf32Schristos }
151*2d40c451Schristos
152*2d40c451Schristos int
config_pin_minlen_rpid(char * path,const char * rpids)153*2d40c451Schristos config_pin_minlen_rpid(char *path, const char *rpids)
154*2d40c451Schristos {
155*2d40c451Schristos fido_dev_t *dev;
156*2d40c451Schristos char *otmp, *tmp, *cp;
157*2d40c451Schristos char *pin = NULL, **rpid = NULL;
158*2d40c451Schristos int r, ok = 1;
159*2d40c451Schristos size_t n;
160*2d40c451Schristos
161*2d40c451Schristos if ((tmp = strdup(rpids)) == NULL)
162*2d40c451Schristos err(1, "strdup");
163*2d40c451Schristos otmp = tmp;
164*2d40c451Schristos for (n = 0; (cp = strsep(&tmp, ",")) != NULL; n++) {
165*2d40c451Schristos if (n == SIZE_MAX || (rpid = recallocarray(rpid, n, n + 1,
166*2d40c451Schristos sizeof(*rpid))) == NULL)
167*2d40c451Schristos err(1, "recallocarray");
168*2d40c451Schristos if ((rpid[n] = strdup(cp)) == NULL)
169*2d40c451Schristos err(1, "strdup");
170*2d40c451Schristos if (*rpid[n] == '\0')
171*2d40c451Schristos errx(1, "empty rpid");
172*2d40c451Schristos }
173*2d40c451Schristos free(otmp);
174*2d40c451Schristos if (rpid == NULL || n == 0)
175*2d40c451Schristos errx(1, "could not parse rp_id");
176*2d40c451Schristos dev = open_dev(path);
177*2d40c451Schristos if ((r = fido_dev_set_pin_minlen_rpid(dev, (const char * const *)rpid,
178*2d40c451Schristos n, NULL)) != FIDO_OK && should_retry_with_pin(dev, r)) {
179*2d40c451Schristos if ((pin = get_pin(path)) == NULL)
180*2d40c451Schristos goto out;
181*2d40c451Schristos r = fido_dev_set_pin_minlen_rpid(dev, (const char * const *)rpid,
182*2d40c451Schristos n, pin);
183*2d40c451Schristos freezero(pin, PINBUF_LEN);
184*2d40c451Schristos pin = NULL;
185*2d40c451Schristos }
186*2d40c451Schristos if (r != FIDO_OK) {
187*2d40c451Schristos warnx("fido_dev_set_pin_minlen_rpid: %s (0x%x)",
188*2d40c451Schristos fido_strerr(r), r);
189*2d40c451Schristos goto out;
190*2d40c451Schristos }
191*2d40c451Schristos
192*2d40c451Schristos ok = 0;
193*2d40c451Schristos out:
194*2d40c451Schristos fido_dev_close(dev);
195*2d40c451Schristos fido_dev_free(&dev);
196*2d40c451Schristos
197*2d40c451Schristos exit(ok);
198*2d40c451Schristos }
199