Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/libfido2/examples/cred.c
39483 views
1
/*
2
* Copyright (c) 2018-2023 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 <errno.h>
9
#include <fido.h>
10
#include <stdbool.h>
11
#include <stdio.h>
12
#include <stdlib.h>
13
#include <string.h>
14
#ifdef HAVE_UNISTD_H
15
#include <unistd.h>
16
#endif
17
18
#include "../openbsd-compat/openbsd-compat.h"
19
#include "extern.h"
20
21
static const unsigned char cd[32] = {
22
0xf9, 0x64, 0x57, 0xe7, 0x2d, 0x97, 0xf6, 0xbb,
23
0xdd, 0xd7, 0xfb, 0x06, 0x37, 0x62, 0xea, 0x26,
24
0x20, 0x44, 0x8e, 0x69, 0x7c, 0x03, 0xf2, 0x31,
25
0x2f, 0x99, 0xdc, 0xaf, 0x3e, 0x8a, 0x91, 0x6b,
26
};
27
28
static const unsigned char user_id[32] = {
29
0x78, 0x1c, 0x78, 0x60, 0xad, 0x88, 0xd2, 0x63,
30
0x32, 0x62, 0x2a, 0xf1, 0x74, 0x5d, 0xed, 0xb2,
31
0xe7, 0xa4, 0x2b, 0x44, 0x89, 0x29, 0x39, 0xc5,
32
0x56, 0x64, 0x01, 0x27, 0x0d, 0xbb, 0xc4, 0x49,
33
};
34
35
static void
36
usage(void)
37
{
38
fprintf(stderr, "usage: cred [-t es256|es384|rs256|eddsa] [-k pubkey] "
39
"[-ei cred_id] [-P pin] [-T seconds] [-b blobkey] [-c cred_protect] [-hruv] "
40
"<device>\n");
41
exit(EXIT_FAILURE);
42
}
43
44
static void
45
verify_cred(int type, const char *fmt, const unsigned char *authdata_ptr,
46
size_t authdata_len, const unsigned char *attstmt_ptr, size_t attstmt_len,
47
bool rk, bool uv, int ext, int cred_protect, const char *key_out,
48
const char *id_out)
49
{
50
fido_cred_t *cred;
51
int r;
52
53
if ((cred = fido_cred_new()) == NULL)
54
errx(1, "fido_cred_new");
55
56
/* type */
57
r = fido_cred_set_type(cred, type);
58
if (r != FIDO_OK)
59
errx(1, "fido_cred_set_type: %s (0x%x)", fido_strerr(r), r);
60
61
/* client data */
62
r = fido_cred_set_clientdata(cred, cd, sizeof(cd));
63
if (r != FIDO_OK)
64
errx(1, "fido_cred_set_clientdata: %s (0x%x)", fido_strerr(r), r);
65
66
/* relying party */
67
r = fido_cred_set_rp(cred, "localhost", "sweet home localhost");
68
if (r != FIDO_OK)
69
errx(1, "fido_cred_set_rp: %s (0x%x)", fido_strerr(r), r);
70
71
/* authdata */
72
r = fido_cred_set_authdata(cred, authdata_ptr, authdata_len);
73
if (r != FIDO_OK)
74
errx(1, "fido_cred_set_authdata: %s (0x%x)", fido_strerr(r), r);
75
76
/* extensions */
77
r = fido_cred_set_extensions(cred, ext);
78
if (r != FIDO_OK)
79
errx(1, "fido_cred_set_extensions: %s (0x%x)", fido_strerr(r), r);
80
81
/* resident key */
82
if (rk && (r = fido_cred_set_rk(cred, FIDO_OPT_TRUE)) != FIDO_OK)
83
errx(1, "fido_cred_set_rk: %s (0x%x)", fido_strerr(r), r);
84
85
/* user verification */
86
if (uv && (r = fido_cred_set_uv(cred, FIDO_OPT_TRUE)) != FIDO_OK)
87
errx(1, "fido_cred_set_uv: %s (0x%x)", fido_strerr(r), r);
88
89
/* credProt */
90
if (cred_protect != 0 && (r = fido_cred_set_prot(cred,
91
cred_protect)) != FIDO_OK)
92
errx(1, "fido_cred_set_prot: %s (0x%x)", fido_strerr(r), r);
93
94
/* fmt */
95
r = fido_cred_set_fmt(cred, fmt);
96
if (r != FIDO_OK)
97
errx(1, "fido_cred_set_fmt: %s (0x%x)", fido_strerr(r), r);
98
99
if (!strcmp(fido_cred_fmt(cred), "none")) {
100
warnx("no attestation data, skipping credential verification");
101
goto out;
102
}
103
104
/* attestation statement */
105
r = fido_cred_set_attstmt(cred, attstmt_ptr, attstmt_len);
106
if (r != FIDO_OK)
107
errx(1, "fido_cred_set_attstmt: %s (0x%x)", fido_strerr(r), r);
108
109
r = fido_cred_verify(cred);
110
if (r != FIDO_OK)
111
errx(1, "fido_cred_verify: %s (0x%x)", fido_strerr(r), r);
112
113
out:
114
if (key_out != NULL) {
115
/* extract the credential pubkey */
116
if (type == COSE_ES256) {
117
if (write_es256_pubkey(key_out,
118
fido_cred_pubkey_ptr(cred),
119
fido_cred_pubkey_len(cred)) < 0)
120
errx(1, "write_es256_pubkey");
121
} else if (type == COSE_ES384) {
122
if (write_es384_pubkey(key_out,
123
fido_cred_pubkey_ptr(cred),
124
fido_cred_pubkey_len(cred)) < 0)
125
errx(1, "write_es384_pubkey");
126
} else if (type == COSE_RS256) {
127
if (write_rs256_pubkey(key_out,
128
fido_cred_pubkey_ptr(cred),
129
fido_cred_pubkey_len(cred)) < 0)
130
errx(1, "write_rs256_pubkey");
131
} else if (type == COSE_EDDSA) {
132
if (write_eddsa_pubkey(key_out,
133
fido_cred_pubkey_ptr(cred),
134
fido_cred_pubkey_len(cred)) < 0)
135
errx(1, "write_eddsa_pubkey");
136
}
137
}
138
139
if (id_out != NULL) {
140
/* extract the credential id */
141
if (write_blob(id_out, fido_cred_id_ptr(cred),
142
fido_cred_id_len(cred)) < 0)
143
errx(1, "write_blob");
144
}
145
146
fido_cred_free(&cred);
147
}
148
149
int
150
main(int argc, char **argv)
151
{
152
bool rk = false;
153
bool uv = false;
154
bool u2f = false;
155
fido_dev_t *dev;
156
fido_cred_t *cred = NULL;
157
const char *pin = NULL;
158
const char *blobkey_out = NULL;
159
const char *key_out = NULL;
160
const char *id_out = NULL;
161
unsigned char *body = NULL;
162
long long ms = 0;
163
size_t len;
164
int type = COSE_ES256;
165
int ext = 0;
166
int ch;
167
int r;
168
long long cred_protect = 0;
169
170
if ((cred = fido_cred_new()) == NULL)
171
errx(1, "fido_cred_new");
172
173
while ((ch = getopt(argc, argv, "P:T:b:e:hi:k:rt:uvc:")) != -1) {
174
switch (ch) {
175
case 'P':
176
pin = optarg;
177
break;
178
case 'T':
179
if (base10(optarg, &ms) < 0)
180
errx(1, "base10: %s", optarg);
181
if (ms <= 0 || ms > 30)
182
errx(1, "-T: %s must be in (0,30]", optarg);
183
ms *= 1000; /* seconds to milliseconds */
184
break;
185
case 'b':
186
ext |= FIDO_EXT_LARGEBLOB_KEY;
187
blobkey_out = optarg;
188
break;
189
case 'e':
190
if (read_blob(optarg, &body, &len) < 0)
191
errx(1, "read_blob: %s", optarg);
192
r = fido_cred_exclude(cred, body, len);
193
if (r != FIDO_OK)
194
errx(1, "fido_cred_exclude: %s (0x%x)",
195
fido_strerr(r), r);
196
free(body);
197
body = NULL;
198
break;
199
case 'h':
200
ext |= FIDO_EXT_HMAC_SECRET;
201
break;
202
case 'c':
203
if (base10(optarg, &cred_protect) < 0)
204
errx(1, "base10: %s", optarg);
205
if (cred_protect <= 0 || cred_protect > 3)
206
errx(1, "-c: %s must be in (1,3)", optarg);
207
ext |= FIDO_EXT_CRED_PROTECT;
208
break;
209
case 'i':
210
id_out = optarg;
211
break;
212
case 'k':
213
key_out = optarg;
214
break;
215
case 'r':
216
rk = true;
217
break;
218
case 't':
219
if (strcmp(optarg, "es256") == 0)
220
type = COSE_ES256;
221
else if (strcmp(optarg, "es384") == 0)
222
type = COSE_ES384;
223
else if (strcmp(optarg, "rs256") == 0)
224
type = COSE_RS256;
225
else if (strcmp(optarg, "eddsa") == 0)
226
type = COSE_EDDSA;
227
else
228
errx(1, "unknown type %s", optarg);
229
break;
230
case 'u':
231
u2f = true;
232
break;
233
case 'v':
234
uv = true;
235
break;
236
default:
237
usage();
238
}
239
}
240
241
argc -= optind;
242
argv += optind;
243
244
if (argc != 1)
245
usage();
246
247
fido_init(0);
248
249
if ((dev = fido_dev_new()) == NULL)
250
errx(1, "fido_dev_new");
251
252
r = fido_dev_open(dev, argv[0]);
253
if (r != FIDO_OK)
254
errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r);
255
if (u2f)
256
fido_dev_force_u2f(dev);
257
258
/* type */
259
r = fido_cred_set_type(cred, type);
260
if (r != FIDO_OK)
261
errx(1, "fido_cred_set_type: %s (0x%x)", fido_strerr(r), r);
262
263
/* client data */
264
r = fido_cred_set_clientdata(cred, cd, sizeof(cd));
265
if (r != FIDO_OK)
266
errx(1, "fido_cred_set_clientdata: %s (0x%x)", fido_strerr(r), r);
267
268
/* relying party */
269
r = fido_cred_set_rp(cred, "localhost", "sweet home localhost");
270
if (r != FIDO_OK)
271
errx(1, "fido_cred_set_rp: %s (0x%x)", fido_strerr(r), r);
272
273
/* user */
274
r = fido_cred_set_user(cred, user_id, sizeof(user_id), "john smith",
275
"jsmith", NULL);
276
if (r != FIDO_OK)
277
errx(1, "fido_cred_set_user: %s (0x%x)", fido_strerr(r), r);
278
279
/* extensions */
280
r = fido_cred_set_extensions(cred, ext);
281
if (r != FIDO_OK)
282
errx(1, "fido_cred_set_extensions: %s (0x%x)", fido_strerr(r), r);
283
284
/* resident key */
285
if (rk && (r = fido_cred_set_rk(cred, FIDO_OPT_TRUE)) != FIDO_OK)
286
errx(1, "fido_cred_set_rk: %s (0x%x)", fido_strerr(r), r);
287
288
/* user verification */
289
if (uv && (r = fido_cred_set_uv(cred, FIDO_OPT_TRUE)) != FIDO_OK)
290
errx(1, "fido_cred_set_uv: %s (0x%x)", fido_strerr(r), r);
291
292
/* credProt */
293
if (cred_protect != 0 && (r = fido_cred_set_prot(cred,
294
(int)cred_protect)) != FIDO_OK)
295
errx(1, "fido_cred_set_prot: %s (0x%x)", fido_strerr(r), r);
296
297
/* timeout */
298
if (ms != 0 && (r = fido_dev_set_timeout(dev, (int)ms)) != FIDO_OK)
299
errx(1, "fido_dev_set_timeout: %s (0x%x)", fido_strerr(r), r);
300
301
if ((r = fido_dev_make_cred(dev, cred, pin)) != FIDO_OK) {
302
fido_dev_cancel(dev);
303
errx(1, "fido_makecred: %s (0x%x)", fido_strerr(r), r);
304
}
305
306
r = fido_dev_close(dev);
307
if (r != FIDO_OK)
308
errx(1, "fido_dev_close: %s (0x%x)", fido_strerr(r), r);
309
310
fido_dev_free(&dev);
311
312
/* when verifying, pin implies uv */
313
if (pin)
314
uv = true;
315
316
verify_cred(type, fido_cred_fmt(cred), fido_cred_authdata_ptr(cred),
317
fido_cred_authdata_len(cred), fido_cred_attstmt_ptr(cred),
318
fido_cred_attstmt_len(cred), rk, uv, ext, fido_cred_prot(cred),
319
key_out, id_out);
320
321
if (blobkey_out != NULL) {
322
/* extract the "largeBlob" key */
323
if (write_blob(blobkey_out, fido_cred_largeblob_key_ptr(cred),
324
fido_cred_largeblob_key_len(cred)) < 0)
325
errx(1, "write_blob");
326
}
327
328
fido_cred_free(&cred);
329
330
exit(0);
331
}
332
333