xref: /freebsd/contrib/libfido2/tools/credman.c (revision 069ac184)
1 /*
2  * Copyright (c) 2019 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 <fido.h>
9 #include <fido/credman.h>
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #ifdef HAVE_UNISTD_H
15 #include <unistd.h>
16 #endif
17 
18 #include "../openbsd-compat/openbsd-compat.h"
19 #include "extern.h"
20 
21 int
22 credman_get_metadata(fido_dev_t *dev, const char *path)
23 {
24 	fido_credman_metadata_t *metadata = NULL;
25 	char *pin = NULL;
26 	int r, ok = 1;
27 
28 	if ((metadata = fido_credman_metadata_new()) == NULL) {
29 		warnx("fido_credman_metadata_new");
30 		goto out;
31 	}
32 	if ((r = fido_credman_get_dev_metadata(dev, metadata,
33 	    NULL)) != FIDO_OK && should_retry_with_pin(dev, r)) {
34 		if ((pin = get_pin(path)) == NULL)
35 			goto out;
36 		r = fido_credman_get_dev_metadata(dev, metadata, pin);
37 		freezero(pin, PINBUF_LEN);
38 		pin = NULL;
39 	}
40 	if (r != FIDO_OK) {
41 		warnx("fido_credman_get_dev_metadata: %s", fido_strerr(r));
42 		goto out;
43 	}
44 
45 	printf("existing rk(s): %u\n",
46 	    (unsigned)fido_credman_rk_existing(metadata));
47 	printf("remaining rk(s): %u\n",
48 	    (unsigned)fido_credman_rk_remaining(metadata));
49 
50 	ok = 0;
51 out:
52 	fido_credman_metadata_free(&metadata);
53 	fido_dev_close(dev);
54 	fido_dev_free(&dev);
55 
56 	exit(ok);
57 }
58 
59 static int
60 print_rp(fido_credman_rp_t *rp, size_t idx)
61 {
62 	char *rp_id_hash = NULL;
63 
64 	if (base64_encode(fido_credman_rp_id_hash_ptr(rp, idx),
65 	    fido_credman_rp_id_hash_len(rp, idx), &rp_id_hash) < 0) {
66 		warnx("output error");
67 		return -1;
68 	}
69 	printf("%02u: %s %s\n", (unsigned)idx, rp_id_hash,
70 	    fido_credman_rp_id(rp, idx));
71 	free(rp_id_hash);
72 
73 	return 0;
74 }
75 
76 int
77 credman_list_rp(const char *path)
78 {
79 	fido_credman_rp_t *rp = NULL;
80 	fido_dev_t *dev = NULL;
81 	char *pin = NULL;
82 	int r, ok = 1;
83 
84 	dev = open_dev(path);
85 	if ((rp = fido_credman_rp_new()) == NULL) {
86 		warnx("fido_credman_rp_new");
87 		goto out;
88 	}
89 	if ((r = fido_credman_get_dev_rp(dev, rp, NULL)) != FIDO_OK &&
90 	    should_retry_with_pin(dev, r)) {
91 		if ((pin = get_pin(path)) == NULL)
92 			goto out;
93 		r = fido_credman_get_dev_rp(dev, rp, pin);
94 		freezero(pin, PINBUF_LEN);
95 		pin = NULL;
96 	}
97 	if (r != FIDO_OK) {
98 		warnx("fido_credman_get_dev_rp: %s", fido_strerr(r));
99 		goto out;
100 	}
101 	for (size_t i = 0; i < fido_credman_rp_count(rp); i++)
102 		if (print_rp(rp, i) < 0)
103 			goto out;
104 
105 	ok = 0;
106 out:
107 	fido_credman_rp_free(&rp);
108 	fido_dev_close(dev);
109 	fido_dev_free(&dev);
110 
111 	exit(ok);
112 }
113 
114 static int
115 print_rk(const fido_credman_rk_t *rk, size_t idx)
116 {
117 	const fido_cred_t *cred;
118 	char *id = NULL;
119 	char *user_id = NULL;
120 	const char *type;
121 	const char *prot;
122 
123 	if ((cred = fido_credman_rk(rk, idx)) == NULL) {
124 		warnx("fido_credman_rk");
125 		return -1;
126 	}
127 	if (base64_encode(fido_cred_id_ptr(cred), fido_cred_id_len(cred),
128 	    &id) < 0 || base64_encode(fido_cred_user_id_ptr(cred),
129 	    fido_cred_user_id_len(cred), &user_id) < 0) {
130 		warnx("output error");
131 		return -1;
132 	}
133 
134 	type = cose_string(fido_cred_type(cred));
135 	prot = prot_string(fido_cred_prot(cred));
136 
137 	printf("%02u: %s %s %s %s %s\n", (unsigned)idx, id,
138 	    fido_cred_display_name(cred), user_id, type, prot);
139 
140 	free(user_id);
141 	free(id);
142 
143 	return 0;
144 }
145 
146 int
147 credman_list_rk(const char *path, const char *rp_id)
148 {
149 	fido_dev_t *dev = NULL;
150 	fido_credman_rk_t *rk = NULL;
151 	char *pin = NULL;
152 	int r, ok = 1;
153 
154 	dev = open_dev(path);
155 	if ((rk = fido_credman_rk_new()) == NULL) {
156 		warnx("fido_credman_rk_new");
157 		goto out;
158 	}
159 	if ((r = fido_credman_get_dev_rk(dev, rp_id, rk, NULL)) != FIDO_OK &&
160 	    should_retry_with_pin(dev, r)) {
161 		if ((pin = get_pin(path)) == NULL)
162 			goto out;
163 		r = fido_credman_get_dev_rk(dev, rp_id, rk, pin);
164 		freezero(pin, PINBUF_LEN);
165 		pin = NULL;
166 	}
167 	if (r != FIDO_OK) {
168 		warnx("fido_credman_get_dev_rk: %s", fido_strerr(r));
169 		goto out;
170 	}
171 	for (size_t i = 0; i < fido_credman_rk_count(rk); i++)
172 		if (print_rk(rk, i) < 0)
173 			goto out;
174 
175 	ok = 0;
176 out:
177 	fido_credman_rk_free(&rk);
178 	fido_dev_close(dev);
179 	fido_dev_free(&dev);
180 
181 	exit(ok);
182 }
183 
184 int
185 credman_print_rk(fido_dev_t *dev, const char *path, const char *rp_id,
186     const char *cred_id)
187 {
188 	fido_credman_rk_t *rk = NULL;
189 	const fido_cred_t *cred = NULL;
190 	char *pin = NULL;
191 	void *cred_id_ptr = NULL;
192 	size_t cred_id_len = 0;
193 	int r, ok = 1;
194 
195 	if ((rk = fido_credman_rk_new()) == NULL) {
196 		warnx("fido_credman_rk_new");
197 		goto out;
198 	}
199 	if (base64_decode(cred_id, &cred_id_ptr, &cred_id_len) < 0) {
200 		warnx("base64_decode");
201 		goto out;
202 	}
203 	if ((r = fido_credman_get_dev_rk(dev, rp_id, rk, NULL)) != FIDO_OK &&
204 	    should_retry_with_pin(dev, r)) {
205 		if ((pin = get_pin(path)) == NULL)
206 			goto out;
207 		r = fido_credman_get_dev_rk(dev, rp_id, rk, pin);
208 		freezero(pin, PINBUF_LEN);
209 		pin = NULL;
210 	}
211 	if (r != FIDO_OK) {
212 		warnx("fido_credman_get_dev_rk: %s", fido_strerr(r));
213 		goto out;
214 	}
215 
216 	for (size_t i = 0; i < fido_credman_rk_count(rk); i++) {
217 		if ((cred = fido_credman_rk(rk, i)) == NULL ||
218 		    fido_cred_id_ptr(cred) == NULL) {
219 			warnx("output error");
220 			goto out;
221 		}
222 		if (cred_id_len != fido_cred_id_len(cred) ||
223 		    memcmp(cred_id_ptr, fido_cred_id_ptr(cred), cred_id_len))
224 			continue;
225 		print_cred(stdout, fido_cred_type(cred), cred);
226 		ok = 0;
227 		goto out;
228 	}
229 
230 	warnx("credential not found");
231 out:
232 	free(cred_id_ptr);
233 	fido_credman_rk_free(&rk);
234 	fido_dev_close(dev);
235 	fido_dev_free(&dev);
236 
237 	exit(ok);
238 }
239 
240 int
241 credman_delete_rk(const char *path, const char *id)
242 {
243 	fido_dev_t *dev = NULL;
244 	char *pin = NULL;
245 	void *id_ptr = NULL;
246 	size_t id_len = 0;
247 	int r, ok = 1;
248 
249 	dev = open_dev(path);
250 	if (base64_decode(id, &id_ptr, &id_len) < 0) {
251 		warnx("base64_decode");
252 		goto out;
253 	}
254 	if ((r = fido_credman_del_dev_rk(dev, id_ptr, id_len,
255 	    NULL)) != FIDO_OK && should_retry_with_pin(dev, r)) {
256 		if ((pin = get_pin(path)) == NULL)
257 			goto out;
258 		r = fido_credman_del_dev_rk(dev, id_ptr, id_len, pin);
259 		freezero(pin, PINBUF_LEN);
260 		pin = NULL;
261 	}
262 	if (r != FIDO_OK) {
263 		warnx("fido_credman_del_dev_rk: %s", fido_strerr(r));
264 		goto out;
265 	}
266 
267 	ok = 0;
268 out:
269 	free(id_ptr);
270 	fido_dev_close(dev);
271 	fido_dev_free(&dev);
272 
273 	exit(ok);
274 }
275 
276 int
277 credman_update_rk(const char *path, const char *user_id, const char *cred_id,
278     const char *name, const char *display_name)
279 {
280 	fido_dev_t *dev = NULL;
281 	fido_cred_t *cred = NULL;
282 	char *pin = NULL;
283 	void *user_id_ptr = NULL;
284 	void *cred_id_ptr = NULL;
285 	size_t user_id_len = 0;
286 	size_t cred_id_len = 0;
287 	int r, ok = 1;
288 
289 	dev = open_dev(path);
290 	if (base64_decode(user_id, &user_id_ptr, &user_id_len) < 0 ||
291 	    base64_decode(cred_id, &cred_id_ptr, &cred_id_len) < 0) {
292 		warnx("base64_decode");
293 		goto out;
294 	}
295 	if ((cred = fido_cred_new()) == NULL) {
296 		warnx("fido_cred_new");
297 		goto out;
298 	}
299 	if ((r = fido_cred_set_id(cred, cred_id_ptr, cred_id_len)) != FIDO_OK) {
300 		warnx("fido_cred_set_id: %s",  fido_strerr(r));
301 		goto out;
302 	}
303 	if ((r = fido_cred_set_user(cred, user_id_ptr, user_id_len, name,
304 	    display_name, NULL)) != FIDO_OK) {
305 		warnx("fido_cred_set_user: %s", fido_strerr(r));
306 		goto out;
307 	}
308 	if ((r = fido_credman_set_dev_rk(dev, cred, NULL)) != FIDO_OK &&
309 	    should_retry_with_pin(dev, r)) {
310 		if ((pin = get_pin(path)) == NULL)
311 			goto out;
312 		r = fido_credman_set_dev_rk(dev, cred, pin);
313 		freezero(pin, PINBUF_LEN);
314 		pin = NULL;
315 	}
316 	if (r != FIDO_OK) {
317 		warnx("fido_credman_set_dev_rk: %s", fido_strerr(r));
318 		goto out;
319 	}
320 
321 	ok = 0;
322 out:
323 	free(user_id_ptr);
324 	free(cred_id_ptr);
325 	fido_dev_close(dev);
326 	fido_dev_free(&dev);
327 	fido_cred_free(&cred);
328 
329 	exit(ok);
330 }
331