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