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 int r = -1; 123 124 if ((cred = fido_credman_rk(rk, idx)) == NULL) { 125 warnx("fido_credman_rk"); 126 return -1; 127 } 128 if (base64_encode(fido_cred_id_ptr(cred), fido_cred_id_len(cred), 129 &id) < 0 || base64_encode(fido_cred_user_id_ptr(cred), 130 fido_cred_user_id_len(cred), &user_id) < 0) { 131 warnx("output error"); 132 goto out; 133 } 134 135 type = cose_string(fido_cred_type(cred)); 136 prot = prot_string(fido_cred_prot(cred)); 137 138 printf("%02u: %s %s %s %s %s\n", (unsigned)idx, id, 139 fido_cred_display_name(cred), user_id, type, prot); 140 141 r = 0; 142 out: 143 free(user_id); 144 free(id); 145 146 return r; 147 } 148 149 int 150 credman_list_rk(const char *path, const char *rp_id) 151 { 152 fido_dev_t *dev = NULL; 153 fido_credman_rk_t *rk = NULL; 154 char *pin = NULL; 155 int r, ok = 1; 156 157 dev = open_dev(path); 158 if ((rk = fido_credman_rk_new()) == NULL) { 159 warnx("fido_credman_rk_new"); 160 goto out; 161 } 162 if ((r = fido_credman_get_dev_rk(dev, rp_id, rk, NULL)) != FIDO_OK && 163 should_retry_with_pin(dev, r)) { 164 if ((pin = get_pin(path)) == NULL) 165 goto out; 166 r = fido_credman_get_dev_rk(dev, rp_id, rk, pin); 167 freezero(pin, PINBUF_LEN); 168 pin = NULL; 169 } 170 if (r != FIDO_OK) { 171 warnx("fido_credman_get_dev_rk: %s", fido_strerr(r)); 172 goto out; 173 } 174 for (size_t i = 0; i < fido_credman_rk_count(rk); i++) 175 if (print_rk(rk, i) < 0) 176 goto out; 177 178 ok = 0; 179 out: 180 fido_credman_rk_free(&rk); 181 fido_dev_close(dev); 182 fido_dev_free(&dev); 183 184 exit(ok); 185 } 186 187 int 188 credman_print_rk(fido_dev_t *dev, const char *path, const char *rp_id, 189 const char *cred_id) 190 { 191 fido_credman_rk_t *rk = NULL; 192 const fido_cred_t *cred = NULL; 193 char *pin = NULL; 194 void *cred_id_ptr = NULL; 195 size_t cred_id_len = 0; 196 int r, ok = 1; 197 198 if ((rk = fido_credman_rk_new()) == NULL) { 199 warnx("fido_credman_rk_new"); 200 goto out; 201 } 202 if (base64_decode(cred_id, &cred_id_ptr, &cred_id_len) < 0) { 203 warnx("base64_decode"); 204 goto out; 205 } 206 if ((r = fido_credman_get_dev_rk(dev, rp_id, rk, NULL)) != FIDO_OK && 207 should_retry_with_pin(dev, r)) { 208 if ((pin = get_pin(path)) == NULL) 209 goto out; 210 r = fido_credman_get_dev_rk(dev, rp_id, rk, pin); 211 freezero(pin, PINBUF_LEN); 212 pin = NULL; 213 } 214 if (r != FIDO_OK) { 215 warnx("fido_credman_get_dev_rk: %s", fido_strerr(r)); 216 goto out; 217 } 218 219 for (size_t i = 0; i < fido_credman_rk_count(rk); i++) { 220 if ((cred = fido_credman_rk(rk, i)) == NULL || 221 fido_cred_id_ptr(cred) == NULL) { 222 warnx("output error"); 223 goto out; 224 } 225 if (cred_id_len != fido_cred_id_len(cred) || 226 memcmp(cred_id_ptr, fido_cred_id_ptr(cred), cred_id_len)) 227 continue; 228 print_cred(stdout, fido_cred_type(cred), cred); 229 ok = 0; 230 goto out; 231 } 232 233 warnx("credential not found"); 234 out: 235 free(cred_id_ptr); 236 fido_credman_rk_free(&rk); 237 fido_dev_close(dev); 238 fido_dev_free(&dev); 239 240 exit(ok); 241 } 242 243 int 244 credman_delete_rk(const char *path, const char *id) 245 { 246 fido_dev_t *dev = NULL; 247 char *pin = NULL; 248 void *id_ptr = NULL; 249 size_t id_len = 0; 250 int r, ok = 1; 251 252 dev = open_dev(path); 253 if (base64_decode(id, &id_ptr, &id_len) < 0) { 254 warnx("base64_decode"); 255 goto out; 256 } 257 if ((r = fido_credman_del_dev_rk(dev, id_ptr, id_len, 258 NULL)) != FIDO_OK && should_retry_with_pin(dev, r)) { 259 if ((pin = get_pin(path)) == NULL) 260 goto out; 261 r = fido_credman_del_dev_rk(dev, id_ptr, id_len, pin); 262 freezero(pin, PINBUF_LEN); 263 pin = NULL; 264 } 265 if (r != FIDO_OK) { 266 warnx("fido_credman_del_dev_rk: %s", fido_strerr(r)); 267 goto out; 268 } 269 270 ok = 0; 271 out: 272 free(id_ptr); 273 fido_dev_close(dev); 274 fido_dev_free(&dev); 275 276 exit(ok); 277 } 278 279 int 280 credman_update_rk(const char *path, const char *user_id, const char *cred_id, 281 const char *name, const char *display_name) 282 { 283 fido_dev_t *dev = NULL; 284 fido_cred_t *cred = NULL; 285 char *pin = NULL; 286 void *user_id_ptr = NULL; 287 void *cred_id_ptr = NULL; 288 size_t user_id_len = 0; 289 size_t cred_id_len = 0; 290 int r, ok = 1; 291 292 dev = open_dev(path); 293 if (base64_decode(user_id, &user_id_ptr, &user_id_len) < 0 || 294 base64_decode(cred_id, &cred_id_ptr, &cred_id_len) < 0) { 295 warnx("base64_decode"); 296 goto out; 297 } 298 if ((cred = fido_cred_new()) == NULL) { 299 warnx("fido_cred_new"); 300 goto out; 301 } 302 if ((r = fido_cred_set_id(cred, cred_id_ptr, cred_id_len)) != FIDO_OK) { 303 warnx("fido_cred_set_id: %s", fido_strerr(r)); 304 goto out; 305 } 306 if ((r = fido_cred_set_user(cred, user_id_ptr, user_id_len, name, 307 display_name, NULL)) != FIDO_OK) { 308 warnx("fido_cred_set_user: %s", fido_strerr(r)); 309 goto out; 310 } 311 if ((r = fido_credman_set_dev_rk(dev, cred, NULL)) != FIDO_OK && 312 should_retry_with_pin(dev, r)) { 313 if ((pin = get_pin(path)) == NULL) 314 goto out; 315 r = fido_credman_set_dev_rk(dev, cred, pin); 316 freezero(pin, PINBUF_LEN); 317 pin = NULL; 318 } 319 if (r != FIDO_OK) { 320 warnx("fido_credman_set_dev_rk: %s", fido_strerr(r)); 321 goto out; 322 } 323 324 ok = 0; 325 out: 326 free(user_id_ptr); 327 free(cred_id_ptr); 328 fido_dev_close(dev); 329 fido_dev_free(&dev); 330 fido_cred_free(&cred); 331 332 exit(ok); 333 } 334