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