summaryrefslogtreecommitdiff
path: root/examples/assert.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/assert.c')
-rw-r--r--examples/assert.c329
1 files changed, 329 insertions, 0 deletions
diff --git a/examples/assert.c b/examples/assert.c
new file mode 100644
index 0000000..a421a51
--- /dev/null
+++ b/examples/assert.c
@@ -0,0 +1,329 @@
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 <openssl/ec.h>
8
9#include <stdbool.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#ifdef HAVE_UNISTD_H
14#include <unistd.h>
15#endif
16
17#include "../openbsd-compat/openbsd-compat.h"
18
19#include "fido.h"
20#include "fido/es256.h"
21#include "fido/rs256.h"
22#include "fido/eddsa.h"
23#include "extern.h"
24
25#ifdef SIGNAL_EXAMPLE
26extern volatile sig_atomic_t got_signal;
27#endif
28
29static const unsigned char cdh[32] = {
30 0xec, 0x8d, 0x8f, 0x78, 0x42, 0x4a, 0x2b, 0xb7,
31 0x82, 0x34, 0xaa, 0xca, 0x07, 0xa1, 0xf6, 0x56,
32 0x42, 0x1c, 0xb6, 0xf6, 0xb3, 0x00, 0x86, 0x52,
33 0x35, 0x2d, 0xa2, 0x62, 0x4a, 0xbe, 0x89, 0x76,
34};
35
36static void
37usage(void)
38{
39 fprintf(stderr, "usage: assert [-t ecdsa|rsa|eddsa] [-a cred_id] "
40 "[-h hmac_secret] [-s hmac_salt] [-P pin] [-T seconds] [-puv] "
41 "<pubkey> <device>\n");
42 exit(EXIT_FAILURE);
43}
44
45static void
46verify_assert(int type, const unsigned char *authdata_ptr, size_t authdata_len,
47 const unsigned char *sig_ptr, size_t sig_len, bool up, bool uv, int ext,
48 const char *key)
49{
50 fido_assert_t *assert = NULL;
51 EC_KEY *ec = NULL;
52 RSA *rsa = NULL;
53 EVP_PKEY *eddsa = NULL;
54 es256_pk_t *es256_pk = NULL;
55 rs256_pk_t *rs256_pk = NULL;
56 eddsa_pk_t *eddsa_pk = NULL;
57 void *pk;
58 int r;
59
60 /* credential pubkey */
61 switch (type) {
62 case COSE_ES256:
63 if ((ec = read_ec_pubkey(key)) == NULL)
64 errx(1, "read_ec_pubkey");
65
66 if ((es256_pk = es256_pk_new()) == NULL)
67 errx(1, "es256_pk_new");
68
69 if (es256_pk_from_EC_KEY(es256_pk, ec) != FIDO_OK)
70 errx(1, "es256_pk_from_EC_KEY");
71
72 pk = es256_pk;
73 EC_KEY_free(ec);
74 ec = NULL;
75
76 break;
77 case COSE_RS256:
78 if ((rsa = read_rsa_pubkey(key)) == NULL)
79 errx(1, "read_rsa_pubkey");
80
81 if ((rs256_pk = rs256_pk_new()) == NULL)
82 errx(1, "rs256_pk_new");
83
84 if (rs256_pk_from_RSA(rs256_pk, rsa) != FIDO_OK)
85 errx(1, "rs256_pk_from_RSA");
86
87 pk = rs256_pk;
88 RSA_free(rsa);
89 rsa = NULL;
90
91 break;
92 case COSE_EDDSA:
93 if ((eddsa = read_eddsa_pubkey(key)) == NULL)
94 errx(1, "read_eddsa_pubkey");
95
96 if ((eddsa_pk = eddsa_pk_new()) == NULL)
97 errx(1, "eddsa_pk_new");
98
99 if (eddsa_pk_from_EVP_PKEY(eddsa_pk, eddsa) != FIDO_OK)
100 errx(1, "eddsa_pk_from_EVP_PKEY");
101
102 pk = eddsa_pk;
103 EVP_PKEY_free(eddsa);
104 eddsa = NULL;
105
106 break;
107 default:
108 errx(1, "unknown credential type %d", type);
109 }
110
111 if ((assert = fido_assert_new()) == NULL)
112 errx(1, "fido_assert_new");
113
114 /* client data hash */
115 r = fido_assert_set_clientdata_hash(assert, cdh, sizeof(cdh));
116 if (r != FIDO_OK)
117 errx(1, "fido_assert_set_clientdata_hash: %s (0x%x)",
118 fido_strerr(r), r);
119
120 /* relying party */
121 r = fido_assert_set_rp(assert, "localhost");
122 if (r != FIDO_OK)
123 errx(1, "fido_assert_set_rp: %s (0x%x)", fido_strerr(r), r);
124
125 /* authdata */
126 r = fido_assert_set_count(assert, 1);
127 if (r != FIDO_OK)
128 errx(1, "fido_assert_set_count: %s (0x%x)", fido_strerr(r), r);
129 r = fido_assert_set_authdata(assert, 0, authdata_ptr, authdata_len);
130 if (r != FIDO_OK)
131 errx(1, "fido_assert_set_authdata: %s (0x%x)", fido_strerr(r), r);
132
133 /* extension */
134 r = fido_assert_set_extensions(assert, ext);
135 if (r != FIDO_OK)
136 errx(1, "fido_assert_set_extensions: %s (0x%x)", fido_strerr(r),
137 r);
138
139 /* user presence */
140 if (up && (r = fido_assert_set_up(assert, FIDO_OPT_TRUE)) != FIDO_OK)
141 errx(1, "fido_assert_set_up: %s (0x%x)", fido_strerr(r), r);
142
143 /* user verification */
144 if (uv && (r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK)
145 errx(1, "fido_assert_set_uv: %s (0x%x)", fido_strerr(r), r);
146
147 /* sig */
148 r = fido_assert_set_sig(assert, 0, sig_ptr, sig_len);
149 if (r != FIDO_OK)
150 errx(1, "fido_assert_set_sig: %s (0x%x)", fido_strerr(r), r);
151
152 r = fido_assert_verify(assert, 0, type, pk);
153 if (r != FIDO_OK)
154 errx(1, "fido_assert_verify: %s (0x%x)", fido_strerr(r), r);
155
156 es256_pk_free(&es256_pk);
157 rs256_pk_free(&rs256_pk);
158 eddsa_pk_free(&eddsa_pk);
159
160 fido_assert_free(&assert);
161}
162
163int
164main(int argc, char **argv)
165{
166 bool up = false;
167 bool uv = false;
168 bool u2f = false;
169 fido_dev_t *dev = NULL;
170 fido_assert_t *assert = NULL;
171 const char *pin = NULL;
172 const char *hmac_out = NULL;
173 unsigned char *body = NULL;
174 long long seconds = 0;
175 size_t len;
176 int type = COSE_ES256;
177 int ext = 0;
178 int ch;
179 int r;
180
181 if ((assert = fido_assert_new()) == NULL)
182 errx(1, "fido_assert_new");
183
184 while ((ch = getopt(argc, argv, "P:T:a:h:ps:t:uv")) != -1) {
185 switch (ch) {
186 case 'P':
187 pin = optarg;
188 break;
189 case 'T':
190#ifndef SIGNAL_EXAMPLE
191 errx(1, "-T not supported");
192#endif
193 if (base10(optarg, &seconds) < 0)
194 errx(1, "base10: %s", optarg);
195 if (seconds <= 0 || seconds > 30)
196 errx(1, "-T: %s must be in (0,30]", optarg);
197 break;
198 case 'a':
199 if (read_blob(optarg, &body, &len) < 0)
200 errx(1, "read_blob: %s", optarg);
201 if ((r = fido_assert_allow_cred(assert, body,
202 len)) != FIDO_OK)
203 errx(1, "fido_assert_allow_cred: %s (0x%x)",
204 fido_strerr(r), r);
205 free(body);
206 body = NULL;
207 break;
208 case 'h':
209 hmac_out = optarg;
210 break;
211 case 'p':
212 up = true;
213 break;
214 case 's':
215 ext = FIDO_EXT_HMAC_SECRET;
216 if (read_blob(optarg, &body, &len) < 0)
217 errx(1, "read_blob: %s", optarg);
218 if ((r = fido_assert_set_hmac_salt(assert, body,
219 len)) != FIDO_OK)
220 errx(1, "fido_assert_set_hmac_salt: %s (0x%x)",
221 fido_strerr(r), r);
222 free(body);
223 body = NULL;
224 break;
225 case 't':
226 if (strcmp(optarg, "ecdsa") == 0)
227 type = COSE_ES256;
228 else if (strcmp(optarg, "rsa") == 0)
229 type = COSE_RS256;
230 else if (strcmp(optarg, "eddsa") == 0)
231 type = COSE_EDDSA;
232 else
233 errx(1, "unknown type %s", optarg);
234 break;
235 case 'u':
236 u2f = true;
237 break;
238 case 'v':
239 uv = true;
240 break;
241 default:
242 usage();
243 }
244 }
245
246 argc -= optind;
247 argv += optind;
248
249 if (argc != 2)
250 usage();
251
252 fido_init(0);
253
254 if ((dev = fido_dev_new()) == NULL)
255 errx(1, "fido_dev_new");
256
257 r = fido_dev_open(dev, argv[1]);
258 if (r != FIDO_OK)
259 errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r);
260 if (u2f)
261 fido_dev_force_u2f(dev);
262
263 /* client data hash */
264 r = fido_assert_set_clientdata_hash(assert, cdh, sizeof(cdh));
265 if (r != FIDO_OK)
266 errx(1, "fido_assert_set_clientdata_hash: %s (0x%x)",
267 fido_strerr(r), r);
268
269 /* relying party */
270 r = fido_assert_set_rp(assert, "localhost");
271 if (r != FIDO_OK)
272 errx(1, "fido_assert_set_rp: %s (0x%x)", fido_strerr(r), r);
273
274 /* extensions */
275 r = fido_assert_set_extensions(assert, ext);
276 if (r != FIDO_OK)
277 errx(1, "fido_assert_set_extensions: %s (0x%x)", fido_strerr(r),
278 r);
279
280 /* user presence */
281 if (up && (r = fido_assert_set_up(assert, FIDO_OPT_TRUE)) != FIDO_OK)
282 errx(1, "fido_assert_set_up: %s (0x%x)", fido_strerr(r), r);
283
284 /* user verification */
285 if (uv && (r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK)
286 errx(1, "fido_assert_set_uv: %s (0x%x)", fido_strerr(r), r);
287
288#ifdef SIGNAL_EXAMPLE
289 prepare_signal_handler(SIGINT);
290 if (seconds) {
291 prepare_signal_handler(SIGALRM);
292 alarm((unsigned)seconds);
293 }
294#endif
295
296 r = fido_dev_get_assert(dev, assert, pin);
297 if (r != FIDO_OK) {
298#ifdef SIGNAL_EXAMPLE
299 if (got_signal)
300 fido_dev_cancel(dev);
301#endif
302 errx(1, "fido_dev_get_assert: %s (0x%x)", fido_strerr(r), r);
303 }
304
305 r = fido_dev_close(dev);
306 if (r != FIDO_OK)
307 errx(1, "fido_dev_close: %s (0x%x)", fido_strerr(r), r);
308
309 fido_dev_free(&dev);
310
311 if (fido_assert_count(assert) != 1)
312 errx(1, "fido_assert_count: %d signatures returned",
313 (int)fido_assert_count(assert));
314
315 verify_assert(type, fido_assert_authdata_ptr(assert, 0),
316 fido_assert_authdata_len(assert, 0), fido_assert_sig_ptr(assert, 0),
317 fido_assert_sig_len(assert, 0), up, uv, ext, argv[0]);
318
319 if (hmac_out != NULL) {
320 /* extract the hmac secret */
321 if (write_blob(hmac_out, fido_assert_hmac_secret_ptr(assert, 0),
322 fido_assert_hmac_secret_len(assert, 0)) < 0)
323 errx(1, "write_blob");
324 }
325
326 fido_assert_free(&assert);
327
328 exit(0);
329}