xref: /freebsd-src/contrib/libfido2/tools/cred_verify.c (revision 2ccfa855b2fc331819953e3de1b1c15ce5b95a7e)
10afa8e06SEd Maste /*
20afa8e06SEd Maste  * Copyright (c) 2018 Yubico AB. All rights reserved.
30afa8e06SEd Maste  * Use of this source code is governed by a BSD-style
40afa8e06SEd Maste  * license that can be found in the LICENSE file.
5*2ccfa855SEd Maste  * SPDX-License-Identifier: BSD-2-Clause
60afa8e06SEd Maste  */
70afa8e06SEd Maste 
80afa8e06SEd Maste #include <fido.h>
90afa8e06SEd Maste #include <stdio.h>
100afa8e06SEd Maste #include <stdlib.h>
110afa8e06SEd Maste #include <string.h>
120afa8e06SEd Maste #ifdef HAVE_UNISTD_H
130afa8e06SEd Maste #include <unistd.h>
140afa8e06SEd Maste #endif
150afa8e06SEd Maste 
160afa8e06SEd Maste #include "../openbsd-compat/openbsd-compat.h"
170afa8e06SEd Maste #include "extern.h"
180afa8e06SEd Maste 
190afa8e06SEd Maste static fido_cred_t *
prepare_cred(FILE * in_f,int type,int flags)200afa8e06SEd Maste prepare_cred(FILE *in_f, int type, int flags)
210afa8e06SEd Maste {
220afa8e06SEd Maste 	fido_cred_t *cred = NULL;
230afa8e06SEd Maste 	struct blob cdh;
240afa8e06SEd Maste 	struct blob authdata;
250afa8e06SEd Maste 	struct blob id;
260afa8e06SEd Maste 	struct blob sig;
270afa8e06SEd Maste 	struct blob x5c;
280afa8e06SEd Maste 	char *rpid = NULL;
290afa8e06SEd Maste 	char *fmt = NULL;
300afa8e06SEd Maste 	int r;
310afa8e06SEd Maste 
320afa8e06SEd Maste 	memset(&cdh, 0, sizeof(cdh));
330afa8e06SEd Maste 	memset(&authdata, 0, sizeof(authdata));
340afa8e06SEd Maste 	memset(&id, 0, sizeof(id));
350afa8e06SEd Maste 	memset(&sig, 0, sizeof(sig));
360afa8e06SEd Maste 	memset(&x5c, 0, sizeof(x5c));
370afa8e06SEd Maste 
380afa8e06SEd Maste 	r = base64_read(in_f, &cdh);
390afa8e06SEd Maste 	r |= string_read(in_f, &rpid);
400afa8e06SEd Maste 	r |= string_read(in_f, &fmt);
410afa8e06SEd Maste 	r |= base64_read(in_f, &authdata);
420afa8e06SEd Maste 	r |= base64_read(in_f, &id);
430afa8e06SEd Maste 	r |= base64_read(in_f, &sig);
440afa8e06SEd Maste 	if (r < 0)
450afa8e06SEd Maste 		errx(1, "input error");
460afa8e06SEd Maste 
470afa8e06SEd Maste 	(void)base64_read(in_f, &x5c);
480afa8e06SEd Maste 
490afa8e06SEd Maste 	if (flags & FLAG_DEBUG) {
500afa8e06SEd Maste 		fprintf(stderr, "client data hash:\n");
510afa8e06SEd Maste 		xxd(cdh.ptr, cdh.len);
520afa8e06SEd Maste 		fprintf(stderr, "relying party id: %s\n", rpid);
530afa8e06SEd Maste 		fprintf(stderr, "format: %s\n", fmt);
540afa8e06SEd Maste 		fprintf(stderr, "authenticator data:\n");
550afa8e06SEd Maste 		xxd(authdata.ptr, authdata.len);
560afa8e06SEd Maste 		fprintf(stderr, "credential id:\n");
570afa8e06SEd Maste 		xxd(id.ptr, id.len);
580afa8e06SEd Maste 		fprintf(stderr, "signature:\n");
590afa8e06SEd Maste 		xxd(sig.ptr, sig.len);
600afa8e06SEd Maste 		fprintf(stderr, "x509:\n");
610afa8e06SEd Maste 		xxd(x5c.ptr, x5c.len);
620afa8e06SEd Maste 	}
630afa8e06SEd Maste 
640afa8e06SEd Maste 	if ((cred = fido_cred_new()) == NULL)
650afa8e06SEd Maste 		errx(1, "fido_cred_new");
660afa8e06SEd Maste 
670afa8e06SEd Maste 	if ((r = fido_cred_set_type(cred, type)) != FIDO_OK ||
680afa8e06SEd Maste 	    (r = fido_cred_set_clientdata_hash(cred, cdh.ptr,
690afa8e06SEd Maste 	    cdh.len)) != FIDO_OK ||
700afa8e06SEd Maste 	    (r = fido_cred_set_rp(cred, rpid, NULL)) != FIDO_OK ||
710afa8e06SEd Maste 	    (r = fido_cred_set_authdata(cred, authdata.ptr,
720afa8e06SEd Maste 	    authdata.len)) != FIDO_OK ||
730afa8e06SEd Maste 	    (r = fido_cred_set_sig(cred, sig.ptr, sig.len)) != FIDO_OK ||
740afa8e06SEd Maste 	    (r = fido_cred_set_fmt(cred, fmt)) != FIDO_OK)
750afa8e06SEd Maste 		errx(1, "fido_cred_set: %s", fido_strerr(r));
760afa8e06SEd Maste 
770afa8e06SEd Maste 	if (x5c.ptr != NULL) {
780afa8e06SEd Maste 		if ((r = fido_cred_set_x509(cred, x5c.ptr, x5c.len)) != FIDO_OK)
790afa8e06SEd Maste 			errx(1, "fido_cred_set_x509: %s", fido_strerr(r));
800afa8e06SEd Maste 	}
810afa8e06SEd Maste 
820afa8e06SEd Maste 	if (flags & FLAG_UV) {
830afa8e06SEd Maste 		if ((r = fido_cred_set_uv(cred, FIDO_OPT_TRUE)) != FIDO_OK)
840afa8e06SEd Maste 			errx(1, "fido_cred_set_uv: %s", fido_strerr(r));
850afa8e06SEd Maste 	}
860afa8e06SEd Maste 	if (flags & FLAG_HMAC) {
870afa8e06SEd Maste 		if ((r = fido_cred_set_extensions(cred,
880afa8e06SEd Maste 		    FIDO_EXT_HMAC_SECRET)) != FIDO_OK)
890afa8e06SEd Maste 			errx(1, "fido_cred_set_extensions: %s", fido_strerr(r));
900afa8e06SEd Maste 	}
910afa8e06SEd Maste 
920afa8e06SEd Maste 	free(cdh.ptr);
930afa8e06SEd Maste 	free(authdata.ptr);
940afa8e06SEd Maste 	free(id.ptr);
950afa8e06SEd Maste 	free(sig.ptr);
960afa8e06SEd Maste 	free(x5c.ptr);
970afa8e06SEd Maste 	free(rpid);
980afa8e06SEd Maste 	free(fmt);
990afa8e06SEd Maste 
1000afa8e06SEd Maste 	return (cred);
1010afa8e06SEd Maste }
1020afa8e06SEd Maste 
1030afa8e06SEd Maste int
cred_verify(int argc,char ** argv)1040afa8e06SEd Maste cred_verify(int argc, char **argv)
1050afa8e06SEd Maste {
1060afa8e06SEd Maste 	fido_cred_t *cred = NULL;
1070afa8e06SEd Maste 	char *in_path = NULL;
1080afa8e06SEd Maste 	char *out_path = NULL;
1090afa8e06SEd Maste 	FILE *in_f = NULL;
1100afa8e06SEd Maste 	FILE *out_f = NULL;
1110afa8e06SEd Maste 	int type = COSE_ES256;
1120afa8e06SEd Maste 	int flags = 0;
1130afa8e06SEd Maste 	int cred_prot = -1;
1140afa8e06SEd Maste 	int ch;
1150afa8e06SEd Maste 	int r;
1160afa8e06SEd Maste 
1170afa8e06SEd Maste 	while ((ch = getopt(argc, argv, "c:dhi:o:v")) != -1) {
1180afa8e06SEd Maste 		switch (ch) {
1190afa8e06SEd Maste 		case 'c':
1200afa8e06SEd Maste 			if ((cred_prot = base10(optarg)) < 0)
1210afa8e06SEd Maste 				errx(1, "-c: invalid argument '%s'", optarg);
1220afa8e06SEd Maste 			break;
1230afa8e06SEd Maste 		case 'd':
1240afa8e06SEd Maste 			flags |= FLAG_DEBUG;
1250afa8e06SEd Maste 			break;
1260afa8e06SEd Maste 		case 'h':
1270afa8e06SEd Maste 			flags |= FLAG_HMAC;
1280afa8e06SEd Maste 			break;
1290afa8e06SEd Maste 		case 'i':
1300afa8e06SEd Maste 			in_path = optarg;
1310afa8e06SEd Maste 			break;
1320afa8e06SEd Maste 		case 'o':
1330afa8e06SEd Maste 			out_path = optarg;
1340afa8e06SEd Maste 			break;
1350afa8e06SEd Maste 		case 'v':
1360afa8e06SEd Maste 			flags |= FLAG_UV;
1370afa8e06SEd Maste 			break;
1380afa8e06SEd Maste 		default:
1390afa8e06SEd Maste 			usage();
1400afa8e06SEd Maste 		}
1410afa8e06SEd Maste 	}
1420afa8e06SEd Maste 
1430afa8e06SEd Maste 	argc -= optind;
1440afa8e06SEd Maste 	argv += optind;
1450afa8e06SEd Maste 
1460afa8e06SEd Maste 	if (argc > 1)
1470afa8e06SEd Maste 		usage();
1480afa8e06SEd Maste 
1490afa8e06SEd Maste 	in_f = open_read(in_path);
1500afa8e06SEd Maste 	out_f = open_write(out_path);
1510afa8e06SEd Maste 
1520afa8e06SEd Maste 	if (argc > 0 && cose_type(argv[0], &type) < 0)
1530afa8e06SEd Maste 		errx(1, "unknown type %s", argv[0]);
1540afa8e06SEd Maste 
1550afa8e06SEd Maste 	fido_init((flags & FLAG_DEBUG) ? FIDO_DEBUG : 0);
1560afa8e06SEd Maste 	cred = prepare_cred(in_f, type, flags);
1570afa8e06SEd Maste 
1580afa8e06SEd Maste 	if (cred_prot > 0) {
1590afa8e06SEd Maste 		r = fido_cred_set_prot(cred, cred_prot);
1600afa8e06SEd Maste 		if (r != FIDO_OK) {
1610afa8e06SEd Maste 			errx(1, "fido_cred_set_prot: %s", fido_strerr(r));
1620afa8e06SEd Maste 		}
1630afa8e06SEd Maste 	}
1640afa8e06SEd Maste 
1650afa8e06SEd Maste 	if (fido_cred_x5c_ptr(cred) == NULL) {
1660afa8e06SEd Maste 		if ((r = fido_cred_verify_self(cred)) != FIDO_OK)
1670afa8e06SEd Maste 			errx(1, "fido_cred_verify_self: %s", fido_strerr(r));
1680afa8e06SEd Maste 	} else {
1690afa8e06SEd Maste 		if ((r = fido_cred_verify(cred)) != FIDO_OK)
1700afa8e06SEd Maste 			errx(1, "fido_cred_verify: %s", fido_strerr(r));
1710afa8e06SEd Maste 	}
1720afa8e06SEd Maste 
1730afa8e06SEd Maste 	print_cred(out_f, type, cred);
1740afa8e06SEd Maste 	fido_cred_free(&cred);
1750afa8e06SEd Maste 
1760afa8e06SEd Maste 	fclose(in_f);
1770afa8e06SEd Maste 	fclose(out_f);
1780afa8e06SEd Maste 	in_f = NULL;
1790afa8e06SEd Maste 	out_f = NULL;
1800afa8e06SEd Maste 
1810afa8e06SEd Maste 	exit(0);
1820afa8e06SEd Maste }
183