Home | History | Annotate | Line # | Download | only in tools
      1      1.1  christos /*
      2      1.1  christos  * Copyright (c) 2019 Yubico AB. All rights reserved.
      3      1.1  christos  * Use of this source code is governed by a BSD-style
      4      1.1  christos  * license that can be found in the LICENSE file.
      5  1.1.1.5  christos  * SPDX-License-Identifier: BSD-2-Clause
      6      1.1  christos  */
      7      1.1  christos 
      8      1.1  christos #include <fido.h>
      9      1.1  christos #include <fido/credman.h>
     10      1.1  christos 
     11      1.1  christos #include <stdio.h>
     12      1.1  christos #include <stdlib.h>
     13      1.1  christos #include <string.h>
     14      1.1  christos #ifdef HAVE_UNISTD_H
     15      1.1  christos #include <unistd.h>
     16      1.1  christos #endif
     17      1.1  christos 
     18      1.1  christos #include "../openbsd-compat/openbsd-compat.h"
     19      1.1  christos #include "extern.h"
     20      1.1  christos 
     21      1.1  christos int
     22      1.1  christos credman_get_metadata(fido_dev_t *dev, const char *path)
     23      1.1  christos {
     24      1.1  christos 	fido_credman_metadata_t *metadata = NULL;
     25  1.1.1.3  christos 	char *pin = NULL;
     26  1.1.1.3  christos 	int r, ok = 1;
     27      1.1  christos 
     28  1.1.1.3  christos 	if ((metadata = fido_credman_metadata_new()) == NULL) {
     29  1.1.1.3  christos 		warnx("fido_credman_metadata_new");
     30  1.1.1.3  christos 		goto out;
     31  1.1.1.3  christos 	}
     32  1.1.1.3  christos 	if ((r = fido_credman_get_dev_metadata(dev, metadata,
     33  1.1.1.3  christos 	    NULL)) != FIDO_OK && should_retry_with_pin(dev, r)) {
     34  1.1.1.3  christos 		if ((pin = get_pin(path)) == NULL)
     35  1.1.1.3  christos 			goto out;
     36  1.1.1.3  christos 		r = fido_credman_get_dev_metadata(dev, metadata, pin);
     37  1.1.1.3  christos 		freezero(pin, PINBUF_LEN);
     38  1.1.1.3  christos 		pin = NULL;
     39  1.1.1.3  christos 	}
     40  1.1.1.3  christos 	if (r != FIDO_OK) {
     41  1.1.1.3  christos 		warnx("fido_credman_get_dev_metadata: %s", fido_strerr(r));
     42  1.1.1.3  christos 		goto out;
     43  1.1.1.3  christos 	}
     44      1.1  christos 
     45      1.1  christos 	printf("existing rk(s): %u\n",
     46      1.1  christos 	    (unsigned)fido_credman_rk_existing(metadata));
     47  1.1.1.2  christos 	printf("remaining rk(s): %u\n",
     48      1.1  christos 	    (unsigned)fido_credman_rk_remaining(metadata));
     49      1.1  christos 
     50  1.1.1.3  christos 	ok = 0;
     51  1.1.1.3  christos out:
     52      1.1  christos 	fido_credman_metadata_free(&metadata);
     53      1.1  christos 	fido_dev_close(dev);
     54      1.1  christos 	fido_dev_free(&dev);
     55      1.1  christos 
     56  1.1.1.3  christos 	exit(ok);
     57      1.1  christos }
     58      1.1  christos 
     59  1.1.1.3  christos static int
     60      1.1  christos print_rp(fido_credman_rp_t *rp, size_t idx)
     61      1.1  christos {
     62      1.1  christos 	char *rp_id_hash = NULL;
     63      1.1  christos 
     64      1.1  christos 	if (base64_encode(fido_credman_rp_id_hash_ptr(rp, idx),
     65  1.1.1.3  christos 	    fido_credman_rp_id_hash_len(rp, idx), &rp_id_hash) < 0) {
     66  1.1.1.3  christos 		warnx("output error");
     67  1.1.1.3  christos 		return -1;
     68  1.1.1.3  christos 	}
     69      1.1  christos 	printf("%02u: %s %s\n", (unsigned)idx, rp_id_hash,
     70      1.1  christos 	    fido_credman_rp_id(rp, idx));
     71      1.1  christos 	free(rp_id_hash);
     72  1.1.1.3  christos 
     73  1.1.1.3  christos 	return 0;
     74      1.1  christos }
     75      1.1  christos 
     76      1.1  christos int
     77  1.1.1.3  christos credman_list_rp(const char *path)
     78      1.1  christos {
     79      1.1  christos 	fido_credman_rp_t *rp = NULL;
     80  1.1.1.3  christos 	fido_dev_t *dev = NULL;
     81  1.1.1.3  christos 	char *pin = NULL;
     82  1.1.1.3  christos 	int r, ok = 1;
     83      1.1  christos 
     84      1.1  christos 	dev = open_dev(path);
     85  1.1.1.3  christos 	if ((rp = fido_credman_rp_new()) == NULL) {
     86  1.1.1.3  christos 		warnx("fido_credman_rp_new");
     87  1.1.1.3  christos 		goto out;
     88  1.1.1.3  christos 	}
     89  1.1.1.3  christos 	if ((r = fido_credman_get_dev_rp(dev, rp, NULL)) != FIDO_OK &&
     90  1.1.1.3  christos 	    should_retry_with_pin(dev, r)) {
     91  1.1.1.3  christos 		if ((pin = get_pin(path)) == NULL)
     92  1.1.1.3  christos 			goto out;
     93  1.1.1.3  christos 		r = fido_credman_get_dev_rp(dev, rp, pin);
     94  1.1.1.3  christos 		freezero(pin, PINBUF_LEN);
     95  1.1.1.3  christos 		pin = NULL;
     96  1.1.1.3  christos 	}
     97  1.1.1.3  christos 	if (r != FIDO_OK) {
     98  1.1.1.3  christos 		warnx("fido_credman_get_dev_rp: %s", fido_strerr(r));
     99  1.1.1.3  christos 		goto out;
    100  1.1.1.3  christos 	}
    101      1.1  christos 	for (size_t i = 0; i < fido_credman_rp_count(rp); i++)
    102  1.1.1.3  christos 		if (print_rp(rp, i) < 0)
    103  1.1.1.3  christos 			goto out;
    104      1.1  christos 
    105  1.1.1.3  christos 	ok = 0;
    106  1.1.1.3  christos out:
    107      1.1  christos 	fido_credman_rp_free(&rp);
    108      1.1  christos 	fido_dev_close(dev);
    109      1.1  christos 	fido_dev_free(&dev);
    110      1.1  christos 
    111  1.1.1.3  christos 	exit(ok);
    112      1.1  christos }
    113      1.1  christos 
    114  1.1.1.3  christos static int
    115      1.1  christos print_rk(const fido_credman_rk_t *rk, size_t idx)
    116      1.1  christos {
    117      1.1  christos 	const fido_cred_t *cred;
    118      1.1  christos 	char *id = NULL;
    119      1.1  christos 	char *user_id = NULL;
    120      1.1  christos 	const char *type;
    121  1.1.1.2  christos 	const char *prot;
    122  1.1.1.6  christos 	int r = -1;
    123      1.1  christos 
    124  1.1.1.3  christos 	if ((cred = fido_credman_rk(rk, idx)) == NULL) {
    125  1.1.1.3  christos 		warnx("fido_credman_rk");
    126  1.1.1.3  christos 		return -1;
    127  1.1.1.3  christos 	}
    128      1.1  christos 	if (base64_encode(fido_cred_id_ptr(cred), fido_cred_id_len(cred),
    129      1.1  christos 	    &id) < 0 || base64_encode(fido_cred_user_id_ptr(cred),
    130  1.1.1.3  christos 	    fido_cred_user_id_len(cred), &user_id) < 0) {
    131  1.1.1.3  christos 		warnx("output error");
    132  1.1.1.6  christos 		goto out;
    133  1.1.1.3  christos 	}
    134      1.1  christos 
    135  1.1.1.2  christos 	type = cose_string(fido_cred_type(cred));
    136  1.1.1.2  christos 	prot = prot_string(fido_cred_prot(cred));
    137      1.1  christos 
    138  1.1.1.2  christos 	printf("%02u: %s %s %s %s %s\n", (unsigned)idx, id,
    139  1.1.1.2  christos 	    fido_cred_display_name(cred), user_id, type, prot);
    140      1.1  christos 
    141  1.1.1.6  christos 	r = 0;
    142  1.1.1.6  christos out:
    143      1.1  christos 	free(user_id);
    144      1.1  christos 	free(id);
    145  1.1.1.3  christos 
    146  1.1.1.6  christos 	return r;
    147      1.1  christos }
    148      1.1  christos 
    149      1.1  christos int
    150  1.1.1.3  christos credman_list_rk(const char *path, const char *rp_id)
    151      1.1  christos {
    152      1.1  christos 	fido_dev_t *dev = NULL;
    153      1.1  christos 	fido_credman_rk_t *rk = NULL;
    154  1.1.1.3  christos 	char *pin = NULL;
    155  1.1.1.3  christos 	int r, ok = 1;
    156      1.1  christos 
    157      1.1  christos 	dev = open_dev(path);
    158  1.1.1.3  christos 	if ((rk = fido_credman_rk_new()) == NULL) {
    159  1.1.1.3  christos 		warnx("fido_credman_rk_new");
    160  1.1.1.3  christos 		goto out;
    161  1.1.1.3  christos 	}
    162  1.1.1.3  christos 	if ((r = fido_credman_get_dev_rk(dev, rp_id, rk, NULL)) != FIDO_OK &&
    163  1.1.1.3  christos 	    should_retry_with_pin(dev, r)) {
    164  1.1.1.3  christos 		if ((pin = get_pin(path)) == NULL)
    165  1.1.1.3  christos 			goto out;
    166  1.1.1.3  christos 		r = fido_credman_get_dev_rk(dev, rp_id, rk, pin);
    167  1.1.1.3  christos 		freezero(pin, PINBUF_LEN);
    168  1.1.1.3  christos 		pin = NULL;
    169  1.1.1.3  christos 	}
    170  1.1.1.3  christos 	if (r != FIDO_OK) {
    171  1.1.1.3  christos 		warnx("fido_credman_get_dev_rk: %s", fido_strerr(r));
    172  1.1.1.3  christos 		goto out;
    173  1.1.1.3  christos 	}
    174      1.1  christos 	for (size_t i = 0; i < fido_credman_rk_count(rk); i++)
    175  1.1.1.3  christos 		if (print_rk(rk, i) < 0)
    176  1.1.1.3  christos 			goto out;
    177      1.1  christos 
    178  1.1.1.3  christos 	ok = 0;
    179  1.1.1.3  christos out:
    180      1.1  christos 	fido_credman_rk_free(&rk);
    181      1.1  christos 	fido_dev_close(dev);
    182      1.1  christos 	fido_dev_free(&dev);
    183      1.1  christos 
    184  1.1.1.3  christos 	exit(ok);
    185      1.1  christos }
    186      1.1  christos 
    187      1.1  christos int
    188  1.1.1.3  christos credman_print_rk(fido_dev_t *dev, const char *path, const char *rp_id,
    189  1.1.1.3  christos     const char *cred_id)
    190      1.1  christos {
    191      1.1  christos 	fido_credman_rk_t *rk = NULL;
    192  1.1.1.3  christos 	const fido_cred_t *cred = NULL;
    193  1.1.1.3  christos 	char *pin = NULL;
    194      1.1  christos 	void *cred_id_ptr = NULL;
    195      1.1  christos 	size_t cred_id_len = 0;
    196  1.1.1.3  christos 	int r, ok = 1;
    197      1.1  christos 
    198  1.1.1.3  christos 	if ((rk = fido_credman_rk_new()) == NULL) {
    199  1.1.1.3  christos 		warnx("fido_credman_rk_new");
    200  1.1.1.3  christos 		goto out;
    201  1.1.1.3  christos 	}
    202  1.1.1.3  christos 	if (base64_decode(cred_id, &cred_id_ptr, &cred_id_len) < 0) {
    203  1.1.1.3  christos 		warnx("base64_decode");
    204  1.1.1.3  christos 		goto out;
    205  1.1.1.3  christos 	}
    206  1.1.1.3  christos 	if ((r = fido_credman_get_dev_rk(dev, rp_id, rk, NULL)) != FIDO_OK &&
    207  1.1.1.3  christos 	    should_retry_with_pin(dev, r)) {
    208  1.1.1.3  christos 		if ((pin = get_pin(path)) == NULL)
    209  1.1.1.3  christos 			goto out;
    210  1.1.1.3  christos 		r = fido_credman_get_dev_rk(dev, rp_id, rk, pin);
    211  1.1.1.3  christos 		freezero(pin, PINBUF_LEN);
    212  1.1.1.3  christos 		pin = NULL;
    213  1.1.1.3  christos 	}
    214  1.1.1.3  christos 	if (r != FIDO_OK) {
    215  1.1.1.3  christos 		warnx("fido_credman_get_dev_rk: %s", fido_strerr(r));
    216  1.1.1.3  christos 		goto out;
    217  1.1.1.3  christos 	}
    218      1.1  christos 
    219      1.1  christos 	for (size_t i = 0; i < fido_credman_rk_count(rk); i++) {
    220      1.1  christos 		if ((cred = fido_credman_rk(rk, i)) == NULL ||
    221  1.1.1.3  christos 		    fido_cred_id_ptr(cred) == NULL) {
    222  1.1.1.3  christos 			warnx("output error");
    223  1.1.1.3  christos 			goto out;
    224  1.1.1.3  christos 		}
    225      1.1  christos 		if (cred_id_len != fido_cred_id_len(cred) ||
    226      1.1  christos 		    memcmp(cred_id_ptr, fido_cred_id_ptr(cred), cred_id_len))
    227      1.1  christos 			continue;
    228      1.1  christos 		print_cred(stdout, fido_cred_type(cred), cred);
    229  1.1.1.3  christos 		ok = 0;
    230      1.1  christos 		goto out;
    231      1.1  christos 	}
    232      1.1  christos 
    233  1.1.1.3  christos 	warnx("credential not found");
    234      1.1  christos out:
    235      1.1  christos 	free(cred_id_ptr);
    236      1.1  christos 	fido_credman_rk_free(&rk);
    237      1.1  christos 	fido_dev_close(dev);
    238      1.1  christos 	fido_dev_free(&dev);
    239      1.1  christos 
    240  1.1.1.3  christos 	exit(ok);
    241      1.1  christos }
    242      1.1  christos 
    243      1.1  christos int
    244  1.1.1.3  christos credman_delete_rk(const char *path, const char *id)
    245      1.1  christos {
    246  1.1.1.3  christos 	fido_dev_t *dev = NULL;
    247  1.1.1.3  christos 	char *pin = NULL;
    248      1.1  christos 	void *id_ptr = NULL;
    249      1.1  christos 	size_t id_len = 0;
    250  1.1.1.3  christos 	int r, ok = 1;
    251      1.1  christos 
    252  1.1.1.3  christos 	dev = open_dev(path);
    253  1.1.1.3  christos 	if (base64_decode(id, &id_ptr, &id_len) < 0) {
    254  1.1.1.3  christos 		warnx("base64_decode");
    255  1.1.1.3  christos 		goto out;
    256  1.1.1.3  christos 	}
    257  1.1.1.3  christos 	if ((r = fido_credman_del_dev_rk(dev, id_ptr, id_len,
    258  1.1.1.3  christos 	    NULL)) != FIDO_OK && should_retry_with_pin(dev, r)) {
    259  1.1.1.3  christos 		if ((pin = get_pin(path)) == NULL)
    260  1.1.1.3  christos 			goto out;
    261  1.1.1.3  christos 		r = fido_credman_del_dev_rk(dev, id_ptr, id_len, pin);
    262  1.1.1.3  christos 		freezero(pin, PINBUF_LEN);
    263  1.1.1.3  christos 		pin = NULL;
    264  1.1.1.3  christos 	}
    265  1.1.1.3  christos 	if (r != FIDO_OK) {
    266  1.1.1.3  christos 		warnx("fido_credman_del_dev_rk: %s", fido_strerr(r));
    267  1.1.1.3  christos 		goto out;
    268  1.1.1.3  christos 	}
    269      1.1  christos 
    270  1.1.1.3  christos 	ok = 0;
    271  1.1.1.3  christos out:
    272      1.1  christos 	free(id_ptr);
    273      1.1  christos 	fido_dev_close(dev);
    274      1.1  christos 	fido_dev_free(&dev);
    275      1.1  christos 
    276  1.1.1.3  christos 	exit(ok);
    277      1.1  christos }
    278  1.1.1.4  christos 
    279  1.1.1.4  christos int
    280  1.1.1.4  christos credman_update_rk(const char *path, const char *user_id, const char *cred_id,
    281  1.1.1.4  christos     const char *name, const char *display_name)
    282  1.1.1.4  christos {
    283  1.1.1.4  christos 	fido_dev_t *dev = NULL;
    284  1.1.1.4  christos 	fido_cred_t *cred = NULL;
    285  1.1.1.4  christos 	char *pin = NULL;
    286  1.1.1.4  christos 	void *user_id_ptr = NULL;
    287  1.1.1.4  christos 	void *cred_id_ptr = NULL;
    288  1.1.1.4  christos 	size_t user_id_len = 0;
    289  1.1.1.4  christos 	size_t cred_id_len = 0;
    290  1.1.1.4  christos 	int r, ok = 1;
    291  1.1.1.4  christos 
    292  1.1.1.4  christos 	dev = open_dev(path);
    293  1.1.1.4  christos 	if (base64_decode(user_id, &user_id_ptr, &user_id_len) < 0 ||
    294  1.1.1.4  christos 	    base64_decode(cred_id, &cred_id_ptr, &cred_id_len) < 0) {
    295  1.1.1.4  christos 		warnx("base64_decode");
    296  1.1.1.4  christos 		goto out;
    297  1.1.1.4  christos 	}
    298  1.1.1.4  christos 	if ((cred = fido_cred_new()) == NULL) {
    299  1.1.1.4  christos 		warnx("fido_cred_new");
    300  1.1.1.4  christos 		goto out;
    301  1.1.1.4  christos 	}
    302  1.1.1.4  christos 	if ((r = fido_cred_set_id(cred, cred_id_ptr, cred_id_len)) != FIDO_OK) {
    303  1.1.1.4  christos 		warnx("fido_cred_set_id: %s",  fido_strerr(r));
    304  1.1.1.4  christos 		goto out;
    305  1.1.1.4  christos 	}
    306  1.1.1.4  christos 	if ((r = fido_cred_set_user(cred, user_id_ptr, user_id_len, name,
    307  1.1.1.4  christos 	    display_name, NULL)) != FIDO_OK) {
    308  1.1.1.4  christos 		warnx("fido_cred_set_user: %s", fido_strerr(r));
    309  1.1.1.4  christos 		goto out;
    310  1.1.1.4  christos 	}
    311  1.1.1.4  christos 	if ((r = fido_credman_set_dev_rk(dev, cred, NULL)) != FIDO_OK &&
    312  1.1.1.4  christos 	    should_retry_with_pin(dev, r)) {
    313  1.1.1.4  christos 		if ((pin = get_pin(path)) == NULL)
    314  1.1.1.4  christos 			goto out;
    315  1.1.1.4  christos 		r = fido_credman_set_dev_rk(dev, cred, pin);
    316  1.1.1.4  christos 		freezero(pin, PINBUF_LEN);
    317  1.1.1.4  christos 		pin = NULL;
    318  1.1.1.4  christos 	}
    319  1.1.1.4  christos 	if (r != FIDO_OK) {
    320  1.1.1.4  christos 		warnx("fido_credman_set_dev_rk: %s", fido_strerr(r));
    321  1.1.1.4  christos 		goto out;
    322  1.1.1.4  christos 	}
    323  1.1.1.4  christos 
    324  1.1.1.4  christos 	ok = 0;
    325  1.1.1.4  christos out:
    326  1.1.1.4  christos 	free(user_id_ptr);
    327  1.1.1.4  christos 	free(cred_id_ptr);
    328  1.1.1.4  christos 	fido_dev_close(dev);
    329  1.1.1.4  christos 	fido_dev_free(&dev);
    330  1.1.1.4  christos 	fido_cred_free(&cred);
    331  1.1.1.4  christos 
    332  1.1.1.4  christos 	exit(ok);
    333  1.1.1.4  christos }
    334