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