1/*
2 * Copyright (c) 2020 Yubico AB. All rights reserved.
3 * Use of this source code is governed by a BSD-style
4 * license that can be found in the LICENSE file.
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12#include <fido.h>
13#include <fido/config.h>
14
15#include "../openbsd-compat/openbsd-compat.h"
16#include "extern.h"
17
18int
19config_entattest(char *path)
20{
21	fido_dev_t *dev;
22	char *pin = NULL;
23	int r, ok = 1;
24
25	dev = open_dev(path);
26	if ((r = fido_dev_enable_entattest(dev, NULL)) != FIDO_OK &&
27	    should_retry_with_pin(dev, r)) {
28		if ((pin = get_pin(path)) == NULL)
29			goto out;
30		r = fido_dev_enable_entattest(dev, pin);
31		freezero(pin, PINBUF_LEN);
32		pin = NULL;
33	}
34	if (r != FIDO_OK) {
35		warnx("fido_dev_enable_entattest: %s (0x%x)",
36		    fido_strerr(r), r);
37		goto out;
38	}
39
40	ok = 0;
41out:
42	fido_dev_close(dev);
43	fido_dev_free(&dev);
44
45	exit(ok);
46}
47
48int
49config_always_uv(char *path, int toggle)
50{
51	fido_dev_t *dev;
52	char *pin = NULL;
53	int v, r, ok = 1;
54
55	dev = open_dev(path);
56	if (get_devopt(dev, "alwaysUv", &v) < 0) {
57		warnx("%s: getdevopt", __func__);
58		goto out;
59	}
60	if (v == -1) {
61		warnx("%s: option not found", __func__);
62		goto out;
63	}
64	if (v == toggle) {
65		ok = 0;
66		goto out;
67	}
68	if ((r = fido_dev_toggle_always_uv(dev, NULL)) != FIDO_OK &&
69	    should_retry_with_pin(dev, r)) {
70		if ((pin = get_pin(path)) == NULL)
71			goto out;
72		r = fido_dev_toggle_always_uv(dev, pin);
73		freezero(pin, PINBUF_LEN);
74		pin = NULL;
75	}
76	if (r != FIDO_OK) {
77		warnx("fido_dev_toggle_always_uv: %s (0x%x)",
78		    fido_strerr(r), r);
79		goto out;
80	}
81
82	ok = 0;
83out:
84	fido_dev_close(dev);
85	fido_dev_free(&dev);
86
87	exit(ok);
88}
89
90int
91config_pin_minlen(char *path, const char *pinlen)
92{
93	fido_dev_t *dev;
94	char *pin = NULL;
95	int len, r, ok = 1;
96
97	dev = open_dev(path);
98	if ((len = base10(pinlen)) < 0 || len > 63) {
99		warnx("%s: len > 63", __func__);
100		goto out;
101	}
102	if ((r = fido_dev_set_pin_minlen(dev, (size_t)len, NULL)) != FIDO_OK &&
103	    should_retry_with_pin(dev, r)) {
104		if ((pin = get_pin(path)) == NULL)
105			goto out;
106		r = fido_dev_set_pin_minlen(dev, (size_t)len, pin);
107		freezero(pin, PINBUF_LEN);
108		pin = NULL;
109	}
110	if (r != FIDO_OK) {
111		warnx("fido_dev_set_pin_minlen: %s (0x%x)", fido_strerr(r), r);
112		goto out;
113	}
114
115	ok = 0;
116out:
117	fido_dev_close(dev);
118	fido_dev_free(&dev);
119
120	exit(ok);
121}
122
123int
124config_force_pin_change(char *path)
125{
126	fido_dev_t *dev;
127	char *pin = NULL;
128	int r, ok = 1;
129
130	dev = open_dev(path);
131	if ((r = fido_dev_force_pin_change(dev, NULL)) != FIDO_OK &&
132	    should_retry_with_pin(dev, r)) {
133		if ((pin = get_pin(path)) == NULL)
134			goto out;
135		r = fido_dev_force_pin_change(dev, pin);
136		freezero(pin, PINBUF_LEN);
137		pin = NULL;
138	}
139	if (r != FIDO_OK) {
140		warnx("fido_dev_force_pin_change: %s (0x%x)", fido_strerr(r), r);
141		goto out;
142	}
143
144	ok = 0;
145out:
146	fido_dev_close(dev);
147	fido_dev_free(&dev);
148
149	exit(ok);
150}
151
152int
153config_pin_minlen_rpid(char *path, const char *rpids)
154{
155	fido_dev_t *dev;
156	char *otmp, *tmp, *cp;
157	char *pin = NULL, **rpid = NULL;
158	int r, ok = 1;
159	size_t n;
160
161	if ((tmp = strdup(rpids)) == NULL)
162		err(1, "strdup");
163	otmp = tmp;
164	for (n = 0; (cp = strsep(&tmp, ",")) != NULL; n++) {
165		if (n == SIZE_MAX || (rpid = recallocarray(rpid, n, n + 1,
166		    sizeof(*rpid))) == NULL)
167			err(1, "recallocarray");
168		if ((rpid[n] = strdup(cp)) == NULL)
169			err(1, "strdup");
170		if (*rpid[n] == '\0')
171			errx(1, "empty rpid");
172	}
173	free(otmp);
174	if (rpid == NULL || n == 0)
175		errx(1, "could not parse rp_id");
176	dev = open_dev(path);
177	if ((r = fido_dev_set_pin_minlen_rpid(dev, (const char * const *)rpid,
178	    n, NULL)) != FIDO_OK && should_retry_with_pin(dev, r)) {
179		if ((pin = get_pin(path)) == NULL)
180			goto out;
181		r = fido_dev_set_pin_minlen_rpid(dev, (const char * const *)rpid,
182		    n, pin);
183		freezero(pin, PINBUF_LEN);
184		pin = NULL;
185	}
186	if (r != FIDO_OK) {
187		warnx("fido_dev_set_pin_minlen_rpid: %s (0x%x)",
188		    fido_strerr(r), r);
189		goto out;
190	}
191
192	ok = 0;
193out:
194	fido_dev_close(dev);
195	fido_dev_free(&dev);
196
197	exit(ok);
198}
199