Home | History | Annotate | Line # | Download | only in tools
      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