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