xref: /freebsd-src/contrib/libfido2/tools/assert_verify.c (revision 2ccfa855b2fc331819953e3de1b1c15ce5b95a7e)
10afa8e06SEd Maste /*
2*2ccfa855SEd Maste  * Copyright (c) 2018-2022 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 <fido/es256.h>
10*2ccfa855SEd Maste #include <fido/es384.h>
110afa8e06SEd Maste #include <fido/rs256.h>
120afa8e06SEd Maste #include <fido/eddsa.h>
130afa8e06SEd Maste 
140afa8e06SEd Maste #include <stdio.h>
150afa8e06SEd Maste #include <stdlib.h>
160afa8e06SEd Maste #include <string.h>
170afa8e06SEd Maste #ifdef HAVE_UNISTD_H
180afa8e06SEd Maste #include <unistd.h>
190afa8e06SEd Maste #endif
200afa8e06SEd Maste 
210afa8e06SEd Maste #include "../openbsd-compat/openbsd-compat.h"
220afa8e06SEd Maste #include "extern.h"
230afa8e06SEd Maste 
240afa8e06SEd Maste static fido_assert_t *
prepare_assert(FILE * in_f,int flags)250afa8e06SEd Maste prepare_assert(FILE *in_f, int flags)
260afa8e06SEd Maste {
270afa8e06SEd Maste 	fido_assert_t *assert = NULL;
280afa8e06SEd Maste 	struct blob cdh;
290afa8e06SEd Maste 	struct blob authdata;
300afa8e06SEd Maste 	struct blob sig;
310afa8e06SEd Maste 	char *rpid = NULL;
320afa8e06SEd Maste 	int r;
330afa8e06SEd Maste 
340afa8e06SEd Maste 	memset(&cdh, 0, sizeof(cdh));
350afa8e06SEd Maste 	memset(&authdata, 0, sizeof(authdata));
360afa8e06SEd Maste 	memset(&sig, 0, sizeof(sig));
370afa8e06SEd Maste 
380afa8e06SEd Maste 	r = base64_read(in_f, &cdh);
390afa8e06SEd Maste 	r |= string_read(in_f, &rpid);
400afa8e06SEd Maste 	r |= base64_read(in_f, &authdata);
410afa8e06SEd Maste 	r |= base64_read(in_f, &sig);
420afa8e06SEd Maste 	if (r < 0)
430afa8e06SEd Maste 		errx(1, "input error");
440afa8e06SEd Maste 
450afa8e06SEd Maste 	if (flags & FLAG_DEBUG) {
460afa8e06SEd Maste 		fprintf(stderr, "client data hash:\n");
470afa8e06SEd Maste 		xxd(cdh.ptr, cdh.len);
480afa8e06SEd Maste 		fprintf(stderr, "relying party id: %s\n", rpid);
490afa8e06SEd Maste 		fprintf(stderr, "authenticator data:\n");
500afa8e06SEd Maste 		xxd(authdata.ptr, authdata.len);
510afa8e06SEd Maste 		fprintf(stderr, "signature:\n");
520afa8e06SEd Maste 		xxd(sig.ptr, sig.len);
530afa8e06SEd Maste 	}
540afa8e06SEd Maste 
550afa8e06SEd Maste 	if ((assert = fido_assert_new()) == NULL)
560afa8e06SEd Maste 		errx(1, "fido_assert_new");
570afa8e06SEd Maste 	if ((r = fido_assert_set_count(assert, 1)) != FIDO_OK)
580afa8e06SEd Maste 		errx(1, "fido_assert_count: %s", fido_strerr(r));
590afa8e06SEd Maste 
600afa8e06SEd Maste 	if ((r = fido_assert_set_clientdata_hash(assert, cdh.ptr,
610afa8e06SEd Maste 	    cdh.len)) != FIDO_OK ||
620afa8e06SEd Maste 	    (r = fido_assert_set_rp(assert, rpid)) != FIDO_OK ||
630afa8e06SEd Maste 	    (r = fido_assert_set_authdata(assert, 0, authdata.ptr,
640afa8e06SEd Maste 	    authdata.len)) != FIDO_OK ||
650afa8e06SEd Maste 	    (r = fido_assert_set_sig(assert, 0, sig.ptr, sig.len)) != FIDO_OK)
660afa8e06SEd Maste 		errx(1, "fido_assert_set: %s", fido_strerr(r));
670afa8e06SEd Maste 
680afa8e06SEd Maste 	if (flags & FLAG_UP) {
690afa8e06SEd Maste 		if ((r = fido_assert_set_up(assert, FIDO_OPT_TRUE)) != FIDO_OK)
700afa8e06SEd Maste 			errx(1, "fido_assert_set_up: %s", fido_strerr(r));
710afa8e06SEd Maste 	}
720afa8e06SEd Maste 	if (flags & FLAG_UV) {
730afa8e06SEd Maste 		if ((r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK)
740afa8e06SEd Maste 			errx(1, "fido_assert_set_uv: %s", fido_strerr(r));
750afa8e06SEd Maste 	}
760afa8e06SEd Maste 	if (flags & FLAG_HMAC) {
770afa8e06SEd Maste 		if ((r = fido_assert_set_extensions(assert,
780afa8e06SEd Maste 		    FIDO_EXT_HMAC_SECRET)) != FIDO_OK)
790afa8e06SEd Maste 			errx(1, "fido_assert_set_extensions: %s",
800afa8e06SEd Maste 			    fido_strerr(r));
810afa8e06SEd Maste 	}
820afa8e06SEd Maste 
830afa8e06SEd Maste 	free(cdh.ptr);
840afa8e06SEd Maste 	free(authdata.ptr);
850afa8e06SEd Maste 	free(sig.ptr);
860afa8e06SEd Maste 	free(rpid);
870afa8e06SEd Maste 
880afa8e06SEd Maste 	return (assert);
890afa8e06SEd Maste }
900afa8e06SEd Maste 
910afa8e06SEd Maste static void *
load_pubkey(int type,const char * file)920afa8e06SEd Maste load_pubkey(int type, const char *file)
930afa8e06SEd Maste {
940afa8e06SEd Maste 	EC_KEY *ec = NULL;
950afa8e06SEd Maste 	RSA *rsa = NULL;
960afa8e06SEd Maste 	EVP_PKEY *eddsa = NULL;
970afa8e06SEd Maste 	es256_pk_t *es256_pk = NULL;
98*2ccfa855SEd Maste 	es384_pk_t *es384_pk = NULL;
990afa8e06SEd Maste 	rs256_pk_t *rs256_pk = NULL;
1000afa8e06SEd Maste 	eddsa_pk_t *eddsa_pk = NULL;
1010afa8e06SEd Maste 	void *pk = NULL;
1020afa8e06SEd Maste 
103*2ccfa855SEd Maste 	switch (type) {
104*2ccfa855SEd Maste 	case COSE_ES256:
1050afa8e06SEd Maste 		if ((ec = read_ec_pubkey(file)) == NULL)
1060afa8e06SEd Maste 			errx(1, "read_ec_pubkey");
1070afa8e06SEd Maste 		if ((es256_pk = es256_pk_new()) == NULL)
1080afa8e06SEd Maste 			errx(1, "es256_pk_new");
1090afa8e06SEd Maste 		if (es256_pk_from_EC_KEY(es256_pk, ec) != FIDO_OK)
1100afa8e06SEd Maste 			errx(1, "es256_pk_from_EC_KEY");
1110afa8e06SEd Maste 		pk = es256_pk;
1120afa8e06SEd Maste 		EC_KEY_free(ec);
113*2ccfa855SEd Maste 		break;
114*2ccfa855SEd Maste 	case COSE_ES384:
115*2ccfa855SEd Maste 		if ((ec = read_ec_pubkey(file)) == NULL)
116*2ccfa855SEd Maste 			errx(1, "read_ec_pubkey");
117*2ccfa855SEd Maste 		if ((es384_pk = es384_pk_new()) == NULL)
118*2ccfa855SEd Maste 			errx(1, "es384_pk_new");
119*2ccfa855SEd Maste 		if (es384_pk_from_EC_KEY(es384_pk, ec) != FIDO_OK)
120*2ccfa855SEd Maste 			errx(1, "es384_pk_from_EC_KEY");
121*2ccfa855SEd Maste 		pk = es384_pk;
122*2ccfa855SEd Maste 		EC_KEY_free(ec);
123*2ccfa855SEd Maste 		break;
124*2ccfa855SEd Maste 	case COSE_RS256:
1250afa8e06SEd Maste 		if ((rsa = read_rsa_pubkey(file)) == NULL)
1260afa8e06SEd Maste 			errx(1, "read_rsa_pubkey");
1270afa8e06SEd Maste 		if ((rs256_pk = rs256_pk_new()) == NULL)
1280afa8e06SEd Maste 			errx(1, "rs256_pk_new");
1290afa8e06SEd Maste 		if (rs256_pk_from_RSA(rs256_pk, rsa) != FIDO_OK)
1300afa8e06SEd Maste 			errx(1, "rs256_pk_from_RSA");
1310afa8e06SEd Maste 		pk = rs256_pk;
1320afa8e06SEd Maste 		RSA_free(rsa);
133*2ccfa855SEd Maste 		break;
134*2ccfa855SEd Maste 	case COSE_EDDSA:
1350afa8e06SEd Maste 		if ((eddsa = read_eddsa_pubkey(file)) == NULL)
1360afa8e06SEd Maste 			errx(1, "read_eddsa_pubkey");
1370afa8e06SEd Maste 		if ((eddsa_pk = eddsa_pk_new()) == NULL)
1380afa8e06SEd Maste 			errx(1, "eddsa_pk_new");
1390afa8e06SEd Maste 		if (eddsa_pk_from_EVP_PKEY(eddsa_pk, eddsa) != FIDO_OK)
1400afa8e06SEd Maste 			errx(1, "eddsa_pk_from_EVP_PKEY");
1410afa8e06SEd Maste 		pk = eddsa_pk;
1420afa8e06SEd Maste 		EVP_PKEY_free(eddsa);
143*2ccfa855SEd Maste 		break;
144*2ccfa855SEd Maste 	default:
145*2ccfa855SEd Maste 		errx(1, "invalid type %d", type);
1460afa8e06SEd Maste 	}
1470afa8e06SEd Maste 
1480afa8e06SEd Maste 	return (pk);
1490afa8e06SEd Maste }
1500afa8e06SEd Maste 
1510afa8e06SEd Maste int
assert_verify(int argc,char ** argv)1520afa8e06SEd Maste assert_verify(int argc, char **argv)
1530afa8e06SEd Maste {
1540afa8e06SEd Maste 	fido_assert_t *assert = NULL;
1550afa8e06SEd Maste 	void *pk = NULL;
1560afa8e06SEd Maste 	char *in_path = NULL;
1570afa8e06SEd Maste 	FILE *in_f = NULL;
1580afa8e06SEd Maste 	int type = COSE_ES256;
1590afa8e06SEd Maste 	int flags = 0;
1600afa8e06SEd Maste 	int ch;
1610afa8e06SEd Maste 	int r;
1620afa8e06SEd Maste 
1630afa8e06SEd Maste 	while ((ch = getopt(argc, argv, "dhi:pv")) != -1) {
1640afa8e06SEd Maste 		switch (ch) {
1650afa8e06SEd Maste 		case 'd':
1660afa8e06SEd Maste 			flags |= FLAG_DEBUG;
1670afa8e06SEd Maste 			break;
1680afa8e06SEd Maste 		case 'h':
1690afa8e06SEd Maste 			flags |= FLAG_HMAC;
1700afa8e06SEd Maste 			break;
1710afa8e06SEd Maste 		case 'i':
1720afa8e06SEd Maste 			in_path = optarg;
1730afa8e06SEd Maste 			break;
1740afa8e06SEd Maste 		case 'p':
1750afa8e06SEd Maste 			flags |= FLAG_UP;
1760afa8e06SEd Maste 			break;
1770afa8e06SEd Maste 		case 'v':
1780afa8e06SEd Maste 			flags |= FLAG_UV;
1790afa8e06SEd Maste 			break;
1800afa8e06SEd Maste 		default:
1810afa8e06SEd Maste 			usage();
1820afa8e06SEd Maste 		}
1830afa8e06SEd Maste 	}
1840afa8e06SEd Maste 
1850afa8e06SEd Maste 	argc -= optind;
1860afa8e06SEd Maste 	argv += optind;
1870afa8e06SEd Maste 
1880afa8e06SEd Maste 	if (argc < 1 || argc > 2)
1890afa8e06SEd Maste 		usage();
1900afa8e06SEd Maste 
1910afa8e06SEd Maste 	in_f = open_read(in_path);
1920afa8e06SEd Maste 
1930afa8e06SEd Maste 	if (argc > 1 && cose_type(argv[1], &type) < 0)
1940afa8e06SEd Maste 		errx(1, "unknown type %s", argv[1]);
1950afa8e06SEd Maste 
1960afa8e06SEd Maste 	fido_init((flags & FLAG_DEBUG) ? FIDO_DEBUG : 0);
1970afa8e06SEd Maste 
1980afa8e06SEd Maste 	pk = load_pubkey(type, argv[0]);
1990afa8e06SEd Maste 	assert = prepare_assert(in_f, flags);
2000afa8e06SEd Maste 	if ((r = fido_assert_verify(assert, 0, type, pk)) != FIDO_OK)
2010afa8e06SEd Maste 		errx(1, "fido_assert_verify: %s", fido_strerr(r));
2020afa8e06SEd Maste 	fido_assert_free(&assert);
2030afa8e06SEd Maste 
2040afa8e06SEd Maste 	fclose(in_f);
2050afa8e06SEd Maste 	in_f = NULL;
2060afa8e06SEd Maste 
2070afa8e06SEd Maste 	exit(0);
2080afa8e06SEd Maste }
209