xref: /netbsd-src/external/bsd/libfido2/dist/tools/assert_verify.c (revision 2d40c4512a84c0d064ec30a492c5e2a14d230bc3)
1ba9bdd8bSchristos /*
2*2d40c451Schristos  * Copyright (c) 2018-2022 Yubico AB. All rights reserved.
3ba9bdd8bSchristos  * Use of this source code is governed by a BSD-style
4ba9bdd8bSchristos  * license that can be found in the LICENSE file.
5*2d40c451Schristos  * SPDX-License-Identifier: BSD-2-Clause
6ba9bdd8bSchristos  */
7ba9bdd8bSchristos 
8ba9bdd8bSchristos #include <fido.h>
9ba9bdd8bSchristos #include <fido/es256.h>
10*2d40c451Schristos #include <fido/es384.h>
11ba9bdd8bSchristos #include <fido/rs256.h>
12ba9bdd8bSchristos #include <fido/eddsa.h>
13ba9bdd8bSchristos 
14ba9bdd8bSchristos #include <stdio.h>
15ba9bdd8bSchristos #include <stdlib.h>
16ba9bdd8bSchristos #include <string.h>
17ba9bdd8bSchristos #ifdef HAVE_UNISTD_H
18ba9bdd8bSchristos #include <unistd.h>
19ba9bdd8bSchristos #endif
20ba9bdd8bSchristos 
21ba9bdd8bSchristos #include "../openbsd-compat/openbsd-compat.h"
22ba9bdd8bSchristos #include "extern.h"
23ba9bdd8bSchristos 
24ba9bdd8bSchristos static fido_assert_t *
prepare_assert(FILE * in_f,int flags)25ba9bdd8bSchristos prepare_assert(FILE *in_f, int flags)
26ba9bdd8bSchristos {
27ba9bdd8bSchristos 	fido_assert_t *assert = NULL;
28ba9bdd8bSchristos 	struct blob cdh;
29ba9bdd8bSchristos 	struct blob authdata;
30ba9bdd8bSchristos 	struct blob sig;
31ba9bdd8bSchristos 	char *rpid = NULL;
32ba9bdd8bSchristos 	int r;
33ba9bdd8bSchristos 
34ba9bdd8bSchristos 	memset(&cdh, 0, sizeof(cdh));
35ba9bdd8bSchristos 	memset(&authdata, 0, sizeof(authdata));
36ba9bdd8bSchristos 	memset(&sig, 0, sizeof(sig));
37ba9bdd8bSchristos 
38ba9bdd8bSchristos 	r = base64_read(in_f, &cdh);
39ba9bdd8bSchristos 	r |= string_read(in_f, &rpid);
40ba9bdd8bSchristos 	r |= base64_read(in_f, &authdata);
41ba9bdd8bSchristos 	r |= base64_read(in_f, &sig);
42ba9bdd8bSchristos 	if (r < 0)
43ba9bdd8bSchristos 		errx(1, "input error");
44ba9bdd8bSchristos 
45ba9bdd8bSchristos 	if (flags & FLAG_DEBUG) {
46ba9bdd8bSchristos 		fprintf(stderr, "client data hash:\n");
47ba9bdd8bSchristos 		xxd(cdh.ptr, cdh.len);
48ba9bdd8bSchristos 		fprintf(stderr, "relying party id: %s\n", rpid);
49ba9bdd8bSchristos 		fprintf(stderr, "authenticator data:\n");
50ba9bdd8bSchristos 		xxd(authdata.ptr, authdata.len);
51ba9bdd8bSchristos 		fprintf(stderr, "signature:\n");
52ba9bdd8bSchristos 		xxd(sig.ptr, sig.len);
53ba9bdd8bSchristos 	}
54ba9bdd8bSchristos 
55ba9bdd8bSchristos 	if ((assert = fido_assert_new()) == NULL)
56ba9bdd8bSchristos 		errx(1, "fido_assert_new");
57ba9bdd8bSchristos 	if ((r = fido_assert_set_count(assert, 1)) != FIDO_OK)
58ba9bdd8bSchristos 		errx(1, "fido_assert_count: %s", fido_strerr(r));
59ba9bdd8bSchristos 
60ba9bdd8bSchristos 	if ((r = fido_assert_set_clientdata_hash(assert, cdh.ptr,
61ba9bdd8bSchristos 	    cdh.len)) != FIDO_OK ||
62ba9bdd8bSchristos 	    (r = fido_assert_set_rp(assert, rpid)) != FIDO_OK ||
63ba9bdd8bSchristos 	    (r = fido_assert_set_authdata(assert, 0, authdata.ptr,
64ba9bdd8bSchristos 	    authdata.len)) != FIDO_OK ||
65ba9bdd8bSchristos 	    (r = fido_assert_set_sig(assert, 0, sig.ptr, sig.len)) != FIDO_OK)
66ba9bdd8bSchristos 		errx(1, "fido_assert_set: %s", fido_strerr(r));
67ba9bdd8bSchristos 
68ba9bdd8bSchristos 	if (flags & FLAG_UP) {
69ba9bdd8bSchristos 		if ((r = fido_assert_set_up(assert, FIDO_OPT_TRUE)) != FIDO_OK)
70ba9bdd8bSchristos 			errx(1, "fido_assert_set_up: %s", fido_strerr(r));
71ba9bdd8bSchristos 	}
72ba9bdd8bSchristos 	if (flags & FLAG_UV) {
73ba9bdd8bSchristos 		if ((r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK)
74ba9bdd8bSchristos 			errx(1, "fido_assert_set_uv: %s", fido_strerr(r));
75ba9bdd8bSchristos 	}
76ba9bdd8bSchristos 	if (flags & FLAG_HMAC) {
77ba9bdd8bSchristos 		if ((r = fido_assert_set_extensions(assert,
78ba9bdd8bSchristos 		    FIDO_EXT_HMAC_SECRET)) != FIDO_OK)
79ba9bdd8bSchristos 			errx(1, "fido_assert_set_extensions: %s",
80ba9bdd8bSchristos 			    fido_strerr(r));
81ba9bdd8bSchristos 	}
82ba9bdd8bSchristos 
83ba9bdd8bSchristos 	free(cdh.ptr);
84ba9bdd8bSchristos 	free(authdata.ptr);
85ba9bdd8bSchristos 	free(sig.ptr);
86ba9bdd8bSchristos 	free(rpid);
87ba9bdd8bSchristos 
88ba9bdd8bSchristos 	return (assert);
89ba9bdd8bSchristos }
90ba9bdd8bSchristos 
91ba9bdd8bSchristos static void *
load_pubkey(int type,const char * file)92ba9bdd8bSchristos load_pubkey(int type, const char *file)
93ba9bdd8bSchristos {
94ba9bdd8bSchristos 	EC_KEY *ec = NULL;
95ba9bdd8bSchristos 	RSA *rsa = NULL;
96ba9bdd8bSchristos 	EVP_PKEY *eddsa = NULL;
97ba9bdd8bSchristos 	es256_pk_t *es256_pk = NULL;
98*2d40c451Schristos 	es384_pk_t *es384_pk = NULL;
99ba9bdd8bSchristos 	rs256_pk_t *rs256_pk = NULL;
100ba9bdd8bSchristos 	eddsa_pk_t *eddsa_pk = NULL;
101ba9bdd8bSchristos 	void *pk = NULL;
102ba9bdd8bSchristos 
103*2d40c451Schristos 	switch (type) {
104*2d40c451Schristos 	case COSE_ES256:
105ba9bdd8bSchristos 		if ((ec = read_ec_pubkey(file)) == NULL)
106ba9bdd8bSchristos 			errx(1, "read_ec_pubkey");
107ba9bdd8bSchristos 		if ((es256_pk = es256_pk_new()) == NULL)
108ba9bdd8bSchristos 			errx(1, "es256_pk_new");
109ba9bdd8bSchristos 		if (es256_pk_from_EC_KEY(es256_pk, ec) != FIDO_OK)
110ba9bdd8bSchristos 			errx(1, "es256_pk_from_EC_KEY");
111ba9bdd8bSchristos 		pk = es256_pk;
112ba9bdd8bSchristos 		EC_KEY_free(ec);
113*2d40c451Schristos 		break;
114*2d40c451Schristos 	case COSE_ES384:
115*2d40c451Schristos 		if ((ec = read_ec_pubkey(file)) == NULL)
116*2d40c451Schristos 			errx(1, "read_ec_pubkey");
117*2d40c451Schristos 		if ((es384_pk = es384_pk_new()) == NULL)
118*2d40c451Schristos 			errx(1, "es384_pk_new");
119*2d40c451Schristos 		if (es384_pk_from_EC_KEY(es384_pk, ec) != FIDO_OK)
120*2d40c451Schristos 			errx(1, "es384_pk_from_EC_KEY");
121*2d40c451Schristos 		pk = es384_pk;
122*2d40c451Schristos 		EC_KEY_free(ec);
123*2d40c451Schristos 		break;
124*2d40c451Schristos 	case COSE_RS256:
125ba9bdd8bSchristos 		if ((rsa = read_rsa_pubkey(file)) == NULL)
126ba9bdd8bSchristos 			errx(1, "read_rsa_pubkey");
127ba9bdd8bSchristos 		if ((rs256_pk = rs256_pk_new()) == NULL)
128ba9bdd8bSchristos 			errx(1, "rs256_pk_new");
129ba9bdd8bSchristos 		if (rs256_pk_from_RSA(rs256_pk, rsa) != FIDO_OK)
130ba9bdd8bSchristos 			errx(1, "rs256_pk_from_RSA");
131ba9bdd8bSchristos 		pk = rs256_pk;
132ba9bdd8bSchristos 		RSA_free(rsa);
133*2d40c451Schristos 		break;
134*2d40c451Schristos 	case COSE_EDDSA:
135ba9bdd8bSchristos 		if ((eddsa = read_eddsa_pubkey(file)) == NULL)
136ba9bdd8bSchristos 			errx(1, "read_eddsa_pubkey");
137ba9bdd8bSchristos 		if ((eddsa_pk = eddsa_pk_new()) == NULL)
138ba9bdd8bSchristos 			errx(1, "eddsa_pk_new");
139ba9bdd8bSchristos 		if (eddsa_pk_from_EVP_PKEY(eddsa_pk, eddsa) != FIDO_OK)
140ba9bdd8bSchristos 			errx(1, "eddsa_pk_from_EVP_PKEY");
141ba9bdd8bSchristos 		pk = eddsa_pk;
142ba9bdd8bSchristos 		EVP_PKEY_free(eddsa);
143*2d40c451Schristos 		break;
144*2d40c451Schristos 	default:
145*2d40c451Schristos 		errx(1, "invalid type %d", type);
146ba9bdd8bSchristos 	}
147ba9bdd8bSchristos 
148ba9bdd8bSchristos 	return (pk);
149ba9bdd8bSchristos }
150ba9bdd8bSchristos 
151ba9bdd8bSchristos int
assert_verify(int argc,char ** argv)152ba9bdd8bSchristos assert_verify(int argc, char **argv)
153ba9bdd8bSchristos {
154ba9bdd8bSchristos 	fido_assert_t *assert = NULL;
155ba9bdd8bSchristos 	void *pk = NULL;
156ba9bdd8bSchristos 	char *in_path = NULL;
157ba9bdd8bSchristos 	FILE *in_f = NULL;
158ba9bdd8bSchristos 	int type = COSE_ES256;
159ba9bdd8bSchristos 	int flags = 0;
160ba9bdd8bSchristos 	int ch;
161ba9bdd8bSchristos 	int r;
162ba9bdd8bSchristos 
163ba9bdd8bSchristos 	while ((ch = getopt(argc, argv, "dhi:pv")) != -1) {
164ba9bdd8bSchristos 		switch (ch) {
165ba9bdd8bSchristos 		case 'd':
166ba9bdd8bSchristos 			flags |= FLAG_DEBUG;
167ba9bdd8bSchristos 			break;
168ba9bdd8bSchristos 		case 'h':
169ba9bdd8bSchristos 			flags |= FLAG_HMAC;
170ba9bdd8bSchristos 			break;
171ba9bdd8bSchristos 		case 'i':
172ba9bdd8bSchristos 			in_path = optarg;
173ba9bdd8bSchristos 			break;
174ba9bdd8bSchristos 		case 'p':
175ba9bdd8bSchristos 			flags |= FLAG_UP;
176ba9bdd8bSchristos 			break;
177ba9bdd8bSchristos 		case 'v':
178ba9bdd8bSchristos 			flags |= FLAG_UV;
179ba9bdd8bSchristos 			break;
180ba9bdd8bSchristos 		default:
181ba9bdd8bSchristos 			usage();
182ba9bdd8bSchristos 		}
183ba9bdd8bSchristos 	}
184ba9bdd8bSchristos 
185ba9bdd8bSchristos 	argc -= optind;
186ba9bdd8bSchristos 	argv += optind;
187ba9bdd8bSchristos 
188ba9bdd8bSchristos 	if (argc < 1 || argc > 2)
189ba9bdd8bSchristos 		usage();
190ba9bdd8bSchristos 
191ba9bdd8bSchristos 	in_f = open_read(in_path);
192ba9bdd8bSchristos 
1931fc1e710Schristos 	if (argc > 1 && cose_type(argv[1], &type) < 0)
194ba9bdd8bSchristos 		errx(1, "unknown type %s", argv[1]);
195ba9bdd8bSchristos 
196ba9bdd8bSchristos 	fido_init((flags & FLAG_DEBUG) ? FIDO_DEBUG : 0);
197ba9bdd8bSchristos 
198ba9bdd8bSchristos 	pk = load_pubkey(type, argv[0]);
199ba9bdd8bSchristos 	assert = prepare_assert(in_f, flags);
200ba9bdd8bSchristos 	if ((r = fido_assert_verify(assert, 0, type, pk)) != FIDO_OK)
201ba9bdd8bSchristos 		errx(1, "fido_assert_verify: %s", fido_strerr(r));
202ba9bdd8bSchristos 	fido_assert_free(&assert);
203ba9bdd8bSchristos 
204ba9bdd8bSchristos 	fclose(in_f);
205ba9bdd8bSchristos 	in_f = NULL;
206ba9bdd8bSchristos 
207ba9bdd8bSchristos 	exit(0);
208ba9bdd8bSchristos }
209