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