summaryrefslogtreecommitdiff
path: root/examples/cred.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/cred.c')
-rw-r--r--examples/cred.c303
1 files changed, 303 insertions, 0 deletions
diff --git a/examples/cred.c b/examples/cred.c
new file mode 100644
index 0000000..e471f7e
--- /dev/null
+++ b/examples/cred.c
@@ -0,0 +1,303 @@
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#include <openssl/pem.h>
9
10#include <errno.h>
11#include <stdbool.h>
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
21#include "fido.h"
22#include "extern.h"
23
24#ifdef SIGNAL_EXAMPLE
25extern volatile sig_atomic_t got_signal;
26#endif
27
28static const unsigned char cdh[32] = {
29 0xf9, 0x64, 0x57, 0xe7, 0x2d, 0x97, 0xf6, 0xbb,
30 0xdd, 0xd7, 0xfb, 0x06, 0x37, 0x62, 0xea, 0x26,
31 0x20, 0x44, 0x8e, 0x69, 0x7c, 0x03, 0xf2, 0x31,
32 0x2f, 0x99, 0xdc, 0xaf, 0x3e, 0x8a, 0x91, 0x6b,
33};
34
35static const unsigned char user_id[32] = {
36 0x78, 0x1c, 0x78, 0x60, 0xad, 0x88, 0xd2, 0x63,
37 0x32, 0x62, 0x2a, 0xf1, 0x74, 0x5d, 0xed, 0xb2,
38 0xe7, 0xa4, 0x2b, 0x44, 0x89, 0x29, 0x39, 0xc5,
39 0x56, 0x64, 0x01, 0x27, 0x0d, 0xbb, 0xc4, 0x49,
40};
41
42static void
43usage(void)
44{
45 fprintf(stderr, "usage: cred [-t ecdsa|rsa|eddsa] [-k pubkey] "
46 "[-ei cred_id] [-P pin] [-T seconds] [-hruv] <device>\n");
47 exit(EXIT_FAILURE);
48}
49
50static void
51verify_cred(int type, const char *fmt, const unsigned char *authdata_ptr,
52 size_t authdata_len, const unsigned char *x509_ptr, size_t x509_len,
53 const unsigned char *sig_ptr, size_t sig_len, bool rk, bool uv, int ext,
54 const char *key_out, const char *id_out)
55{
56 fido_cred_t *cred;
57 int r;
58
59 if ((cred = fido_cred_new()) == NULL)
60 errx(1, "fido_cred_new");
61
62 /* type */
63 r = fido_cred_set_type(cred, type);
64 if (r != FIDO_OK)
65 errx(1, "fido_cred_set_type: %s (0x%x)", fido_strerr(r), r);
66
67 /* client data hash */
68 r = fido_cred_set_clientdata_hash(cred, cdh, sizeof(cdh));
69 if (r != FIDO_OK)
70 errx(1, "fido_cred_set_clientdata_hash: %s (0x%x)",
71 fido_strerr(r), r);
72
73 /* relying party */
74 r = fido_cred_set_rp(cred, "localhost", "sweet home localhost");
75 if (r != FIDO_OK)
76 errx(1, "fido_cred_set_rp: %s (0x%x)", fido_strerr(r), r);
77
78 /* authdata */
79 r = fido_cred_set_authdata(cred, authdata_ptr, authdata_len);
80 if (r != FIDO_OK)
81 errx(1, "fido_cred_set_authdata: %s (0x%x)", fido_strerr(r), r);
82
83 /* extensions */
84 r = fido_cred_set_extensions(cred, ext);
85 if (r != FIDO_OK)
86 errx(1, "fido_cred_set_extensions: %s (0x%x)", fido_strerr(r), r);
87
88 /* resident key */
89 if (rk && (r = fido_cred_set_rk(cred, FIDO_OPT_TRUE)) != FIDO_OK)
90 errx(1, "fido_cred_set_rk: %s (0x%x)", fido_strerr(r), r);
91
92 /* user verification */
93 if (uv && (r = fido_cred_set_uv(cred, FIDO_OPT_TRUE)) != FIDO_OK)
94 errx(1, "fido_cred_set_uv: %s (0x%x)", fido_strerr(r), r);
95
96 /* x509 */
97 r = fido_cred_set_x509(cred, x509_ptr, x509_len);
98 if (r != FIDO_OK)
99 errx(1, "fido_cred_set_x509: %s (0x%x)", fido_strerr(r), r);
100
101 /* sig */
102 r = fido_cred_set_sig(cred, sig_ptr, sig_len);
103 if (r != FIDO_OK)
104 errx(1, "fido_cred_set_sig: %s (0x%x)", fido_strerr(r), r);
105
106 /* fmt */
107 r = fido_cred_set_fmt(cred, fmt);
108 if (r != FIDO_OK)
109 errx(1, "fido_cred_set_fmt: %s (0x%x)", fido_strerr(r), r);
110
111 r = fido_cred_verify(cred);
112 if (r != FIDO_OK)
113 errx(1, "fido_cred_verify: %s (0x%x)", fido_strerr(r), r);
114
115 if (key_out != NULL) {
116 /* extract the credential pubkey */
117 if (type == COSE_ES256) {
118 if (write_ec_pubkey(key_out, fido_cred_pubkey_ptr(cred),
119 fido_cred_pubkey_len(cred)) < 0)
120 errx(1, "write_ec_pubkey");
121 } else if (type == COSE_RS256) {
122 if (write_rsa_pubkey(key_out, fido_cred_pubkey_ptr(cred),
123 fido_cred_pubkey_len(cred)) < 0)
124 errx(1, "write_rsa_pubkey");
125 } else if (type == COSE_EDDSA) {
126 if (write_eddsa_pubkey(key_out, fido_cred_pubkey_ptr(cred),
127 fido_cred_pubkey_len(cred)) < 0)
128 errx(1, "write_eddsa_pubkey");
129 }
130 }
131
132 if (id_out != NULL) {
133 /* extract the credential id */
134 if (write_blob(id_out, fido_cred_id_ptr(cred),
135 fido_cred_id_len(cred)) < 0)
136 errx(1, "write_blob");
137 }
138
139 fido_cred_free(&cred);
140}
141
142int
143main(int argc, char **argv)
144{
145 bool rk = false;
146 bool uv = false;
147 bool u2f = false;
148 fido_dev_t *dev;
149 fido_cred_t *cred = NULL;
150 const char *pin = NULL;
151 const char *key_out = NULL;
152 const char *id_out = NULL;
153 unsigned char *body = NULL;
154 long long seconds = 0;
155 size_t len;
156 int type = COSE_ES256;
157 int ext = 0;
158 int ch;
159 int r;
160
161 if ((cred = fido_cred_new()) == NULL)
162 errx(1, "fido_cred_new");
163
164 while ((ch = getopt(argc, argv, "P:T:e:hi:k:rt:uv")) != -1) {
165 switch (ch) {
166 case 'P':
167 pin = optarg;
168 break;
169 case 'T':
170#ifndef SIGNAL_EXAMPLE
171 errx(1, "-T not supported");
172#endif
173 if (base10(optarg, &seconds) < 0)
174 errx(1, "base10: %s", optarg);
175 if (seconds <= 0 || seconds > 30)
176 errx(1, "-T: %s must be in (0,30]", optarg);
177 break;
178 case 'e':
179 if (read_blob(optarg, &body, &len) < 0)
180 errx(1, "read_blob: %s", optarg);
181 r = fido_cred_exclude(cred, body, len);
182 if (r != FIDO_OK)
183 errx(1, "fido_cred_exclude: %s (0x%x)",
184 fido_strerr(r), r);
185 free(body);
186 body = NULL;
187 break;
188 case 'h':
189 ext = FIDO_EXT_HMAC_SECRET;
190 break;
191 case 'i':
192 id_out = optarg;
193 break;
194 case 'k':
195 key_out = optarg;
196 break;
197 case 'r':
198 rk = true;
199 break;
200 case 't':
201 if (strcmp(optarg, "ecdsa") == 0)
202 type = COSE_ES256;
203 else if (strcmp(optarg, "rsa") == 0)
204 type = COSE_RS256;
205 else if (strcmp(optarg, "eddsa") == 0)
206 type = COSE_EDDSA;
207 else
208 errx(1, "unknown type %s", optarg);
209 break;
210 case 'u':
211 u2f = true;
212 break;
213 case 'v':
214 uv = true;
215 break;
216 default:
217 usage();
218 }
219 }
220
221 argc -= optind;
222 argv += optind;
223
224 if (argc != 1)
225 usage();
226
227 fido_init(0);
228
229 if ((dev = fido_dev_new()) == NULL)
230 errx(1, "fido_dev_new");
231
232 if ((r = fido_dev_open(dev, argv[0])) != FIDO_OK)
233 errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r);
234 if (u2f)
235 fido_dev_force_u2f(dev);
236
237 /* type */
238 r = fido_cred_set_type(cred, type);
239 if (r != FIDO_OK)
240 errx(1, "fido_cred_set_type: %s (0x%x)", fido_strerr(r), r);
241
242 /* client data hash */
243 r = fido_cred_set_clientdata_hash(cred, cdh, sizeof(cdh));
244 if (r != FIDO_OK)
245 errx(1, "fido_cred_set_clientdata_hash: %s (0x%x)",
246 fido_strerr(r), r);
247
248 /* relying party */
249 r = fido_cred_set_rp(cred, "localhost", "sweet home localhost");
250 if (r != FIDO_OK)
251 errx(1, "fido_cred_set_rp: %s (0x%x)", fido_strerr(r), r);
252
253 /* user */
254 r = fido_cred_set_user(cred, user_id, sizeof(user_id), "john smith",
255 "jsmith", NULL);
256 if (r != FIDO_OK)
257 errx(1, "fido_cred_set_user: %s (0x%x)", fido_strerr(r), r);
258
259 /* extensions */
260 r = fido_cred_set_extensions(cred, ext);
261 if (r != FIDO_OK)
262 errx(1, "fido_cred_set_extensions: %s (0x%x)", fido_strerr(r), r);
263
264 /* resident key */
265 if (rk && (r = fido_cred_set_rk(cred, FIDO_OPT_TRUE)) != FIDO_OK)
266 errx(1, "fido_cred_set_rk: %s (0x%x)", fido_strerr(r), r);
267
268 /* user verification */
269 if (uv && (r = fido_cred_set_uv(cred, FIDO_OPT_TRUE)) != FIDO_OK)
270 errx(1, "fido_cred_set_uv: %s (0x%x)", fido_strerr(r), r);
271
272#ifdef SIGNAL_EXAMPLE
273 prepare_signal_handler(SIGINT);
274 if (seconds) {
275 prepare_signal_handler(SIGALRM);
276 alarm((unsigned)seconds);
277 }
278#endif
279
280 r = fido_dev_make_cred(dev, cred, pin);
281 if (r != FIDO_OK) {
282#ifdef SIGNAL_EXAMPLE
283 if (got_signal)
284 fido_dev_cancel(dev);
285#endif
286 errx(1, "fido_makecred: %s (0x%x)", fido_strerr(r), r);
287 }
288
289 r = fido_dev_close(dev);
290 if (r != FIDO_OK)
291 errx(1, "fido_dev_close: %s (0x%x)", fido_strerr(r), r);
292
293 fido_dev_free(&dev);
294
295 verify_cred(type, fido_cred_fmt(cred), fido_cred_authdata_ptr(cred),
296 fido_cred_authdata_len(cred), fido_cred_x5c_ptr(cred),
297 fido_cred_x5c_len(cred), fido_cred_sig_ptr(cred),
298 fido_cred_sig_len(cred), rk, uv, ext, key_out, id_out);
299
300 fido_cred_free(&cred);
301
302 exit(0);
303}