xref: /netbsd-src/external/bsd/libfido2/dist/tools/credman.c (revision cef8759bd76c1b621f8eab8faa6f208faabc2e15)
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 <stdbool.h>
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[1024];
26 	int r;
27 
28 	if ((metadata = fido_credman_metadata_new()) == NULL)
29 		errx(1, "fido_credman_metadata_new");
30 
31 	read_pin(path, pin, sizeof(pin));
32 	r = fido_credman_get_dev_metadata(dev, metadata, pin);
33 	explicit_bzero(pin, sizeof(pin));
34 
35 	if (r != FIDO_OK)
36 		errx(1, "fido_credman_get_dev_metadata: %s", fido_strerr(r));
37 
38 	printf("existing rk(s): %u\n",
39 	    (unsigned)fido_credman_rk_existing(metadata));
40 	printf("possible rk(s): %u\n",
41 	    (unsigned)fido_credman_rk_remaining(metadata));
42 
43 	fido_credman_metadata_free(&metadata);
44 	fido_dev_close(dev);
45 	fido_dev_free(&dev);
46 
47 	exit(0);
48 }
49 
50 static void
51 print_rp(fido_credman_rp_t *rp, size_t idx)
52 {
53 	char *rp_id_hash = NULL;
54 
55 	if (base64_encode(fido_credman_rp_id_hash_ptr(rp, idx),
56 	    fido_credman_rp_id_hash_len(rp, idx), &rp_id_hash) < 0)
57 		errx(1, "output error");
58 
59 	printf("%02u: %s %s\n", (unsigned)idx, rp_id_hash,
60 	    fido_credman_rp_id(rp, idx));
61 
62 	free(rp_id_hash);
63 	rp_id_hash = NULL;
64 }
65 
66 int
67 credman_list_rp(char *path)
68 {
69 	fido_dev_t *dev = NULL;
70 	fido_credman_rp_t *rp = NULL;
71 	char pin[1024];
72 	int r;
73 
74 	if (path == NULL)
75 		usage();
76 	if ((rp = fido_credman_rp_new()) == NULL)
77 		errx(1, "fido_credman_rp_new");
78 
79 	dev = open_dev(path);
80 	read_pin(path, pin, sizeof(pin));
81 	r = fido_credman_get_dev_rp(dev, rp, pin);
82 	explicit_bzero(pin, sizeof(pin));
83 
84 	if (r != FIDO_OK)
85 		errx(1, "fido_credman_get_dev_rp: %s", fido_strerr(r));
86 
87 	for (size_t i = 0; i < fido_credman_rp_count(rp); i++)
88 		print_rp(rp, i);
89 
90 	fido_credman_rp_free(&rp);
91 	fido_dev_close(dev);
92 	fido_dev_free(&dev);
93 
94 	exit(0);
95 }
96 
97 static void
98 print_rk(const fido_credman_rk_t *rk, size_t idx)
99 {
100 	const fido_cred_t *cred;
101 	char *id = NULL;
102 	char *user_id = NULL;
103 	const char *type;
104 
105 	if ((cred = fido_credman_rk(rk, idx)) == NULL)
106 		errx(1, "fido_credman_rk");
107 	if (base64_encode(fido_cred_id_ptr(cred), fido_cred_id_len(cred),
108 	    &id) < 0 || base64_encode(fido_cred_user_id_ptr(cred),
109 	    fido_cred_user_id_len(cred), &user_id) < 0)
110 		errx(1, "output error");
111 
112 	switch (fido_cred_type(cred)) {
113 	case COSE_EDDSA:
114 		type = "eddsa";
115 		break;
116 	case COSE_ES256:
117 		type = "es256";
118 		break;
119 	case COSE_RS256:
120 		type = "rs256";
121 		break;
122 	default:
123 		type = "unknown";
124 		break;
125 	}
126 
127 	printf("%02u: %s %s (%s) %s\n", (unsigned)idx, id,
128 	    fido_cred_display_name(cred), user_id, type);
129 
130 	free(user_id);
131 	free(id);
132 	user_id = NULL;
133 	id = NULL;
134 }
135 
136 int
137 credman_list_rk(char *path, const char *rp_id)
138 {
139 	fido_dev_t *dev = NULL;
140 	fido_credman_rk_t *rk = NULL;
141 	char pin[1024];
142 	int r;
143 
144 	if (path == NULL)
145 		usage();
146 	if ((rk = fido_credman_rk_new()) == NULL)
147 		errx(1, "fido_credman_rk_new");
148 
149 	dev = open_dev(path);
150 	read_pin(path, pin, sizeof(pin));
151 	r = fido_credman_get_dev_rk(dev, rp_id, rk, pin);
152 	explicit_bzero(pin, sizeof(pin));
153 
154 	if (r != FIDO_OK)
155 		errx(1, "fido_credman_get_dev_rk: %s", fido_strerr(r));
156 	for (size_t i = 0; i < fido_credman_rk_count(rk); i++)
157 		print_rk(rk, i);
158 
159 	fido_credman_rk_free(&rk);
160 	fido_dev_close(dev);
161 	fido_dev_free(&dev);
162 
163 	exit(0);
164 }
165 
166 int
167 credman_print_rk(fido_dev_t *dev, const char *path, char *rp_id, char *cred_id)
168 {
169 	const fido_cred_t *cred = NULL;
170 	fido_credman_rk_t *rk = NULL;
171 	char pin[1024];
172 	void *cred_id_ptr = NULL;
173 	size_t cred_id_len = 0;
174 	int r;
175 
176 	if ((rk = fido_credman_rk_new()) == NULL)
177 		errx(1, "fido_credman_rk_new");
178 	if (base64_decode(cred_id, &cred_id_ptr, &cred_id_len) < 0)
179 		errx(1, "base64_decode");
180 
181 	read_pin(path, pin, sizeof(pin));
182 	r = fido_credman_get_dev_rk(dev, rp_id, rk, pin);
183 	explicit_bzero(pin, sizeof(pin));
184 
185 	if (r != FIDO_OK)
186 		errx(1, "fido_credman_get_dev_rk: %s", fido_strerr(r));
187 
188 	for (size_t i = 0; i < fido_credman_rk_count(rk); i++) {
189 		if ((cred = fido_credman_rk(rk, i)) == NULL ||
190 		    fido_cred_id_ptr(cred) == NULL)
191 			errx(1, "output error");
192 		if (cred_id_len != fido_cred_id_len(cred) ||
193 		    memcmp(cred_id_ptr, fido_cred_id_ptr(cred), cred_id_len))
194 			continue;
195 		print_cred(stdout, fido_cred_type(cred), cred);
196 		goto out;
197 	}
198 
199 	errx(1, "credential not found");
200 
201 out:
202 	free(cred_id_ptr);
203 	cred_id_ptr = NULL;
204 
205 	fido_credman_rk_free(&rk);
206 	fido_dev_close(dev);
207 	fido_dev_free(&dev);
208 
209 	exit(0);
210 }
211 
212 int
213 credman_delete_rk(fido_dev_t *dev, const char *path, char *id)
214 {
215 	char pin[1024];
216 	void *id_ptr = NULL;
217 	size_t id_len = 0;
218 	int r;
219 
220 	if (base64_decode(id, &id_ptr, &id_len) < 0)
221 		errx(1, "base64_decode");
222 
223 	read_pin(path, pin, sizeof(pin));
224 	r = fido_credman_del_dev_rk(dev, id_ptr, id_len, pin);
225 	explicit_bzero(pin, sizeof(pin));
226 
227 	if (r != FIDO_OK)
228 		errx(1, "fido_credman_del_dev_rk: %s", fido_strerr(r));
229 
230 	free(id_ptr);
231 	id_ptr = NULL;
232 
233 	fido_dev_close(dev);
234 	fido_dev_free(&dev);
235 
236 	exit(0);
237 }
238