summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authornicoo <nicoo@debian.org>2020-02-12 13:42:22 +0100
committerNicolas Braud-Santoni <nicolas@braud-santoni.eu>2020-02-12 13:42:22 +0100
commitc79050aa44b8836d836c5dd22a383a073c28b74b (patch)
tree7bcca9fabd7718bf87ca600a6594f57b76d8de7d /examples
Import upstream release 1.3.0
Closes: #951184
Diffstat (limited to 'examples')
-rw-r--r--examples/CMakeLists.txt44
-rw-r--r--examples/README.adoc81
-rw-r--r--examples/assert.c329
-rw-r--r--examples/cred.c303
-rw-r--r--examples/extern.h32
-rw-r--r--examples/info.c216
-rw-r--r--examples/manifest.c45
-rw-r--r--examples/reset.c64
-rw-r--r--examples/retries.c52
-rw-r--r--examples/setpin.c59
-rw-r--r--examples/util.c415
11 files changed, 1640 insertions, 0 deletions
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
new file mode 100644
index 0000000..957311e
--- /dev/null
+++ b/examples/CMakeLists.txt
@@ -0,0 +1,44 @@
1# Copyright (c) 2018 Yubico AB. All rights reserved.
2# Use of this source code is governed by a BSD-style
3# license that can be found in the LICENSE file.
4
5list(APPEND COMPAT_SOURCES
6 ../openbsd-compat/getopt_long.c
7 ../openbsd-compat/strlcat.c
8 ../openbsd-compat/strlcpy.c
9)
10
11if(WIN32)
12 list(APPEND COMPAT_SOURCES ../openbsd-compat/posix_win.c)
13endif()
14
15# drop -rdynamic
16set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
17
18# manifest
19add_executable(manifest manifest.c ${COMPAT_SOURCES})
20target_link_libraries(manifest fido2)
21
22# info
23add_executable(info info.c ${COMPAT_SOURCES})
24target_link_libraries(info fido2)
25
26# reset
27add_executable(reset reset.c util.c ${COMPAT_SOURCES})
28target_link_libraries(reset fido2)
29
30# cred
31add_executable(cred cred.c util.c ${COMPAT_SOURCES})
32target_link_libraries(cred fido2)
33
34# assert
35add_executable(assert assert.c util.c ${COMPAT_SOURCES})
36target_link_libraries(assert fido2)
37
38# setpin
39add_executable(setpin setpin.c ${COMPAT_SOURCES})
40target_link_libraries(setpin fido2)
41
42# retries
43add_executable(retries retries.c ${COMPAT_SOURCES})
44target_link_libraries(retries fido2)
diff --git a/examples/README.adoc b/examples/README.adoc
new file mode 100644
index 0000000..091c6bc
--- /dev/null
+++ b/examples/README.adoc
@@ -0,0 +1,81 @@
1= Examples
2
3=== Definitions
4
5The following definitions are used in the description below:
6
7- <device>
8
9 The file system path or subsystem-specific identification string of a
10 FIDO device.
11
12- <pin>, [oldpin]
13
14 Strings passed directly in the executed command's argument vector.
15
16- <cred_id>
17
18 The file system path of a file containing a FIDO credential ID in
19 binary representation.
20
21- <pubkey>
22
23 The file system path of a file containing a NIST P-256 public key in
24 PEM format.
25
26=== Description
27
28The following examples are provided:
29
30- manifest
31
32 Prints a list of configured FIDO devices.
33
34- info <device>
35
36 Prints information about <device>.
37
38- reset <device>
39
40 Performs a factory reset on <device>.
41
42- setpin <pin> [oldpin] <device>
43
44 Configures <pin> as the new PIN of <device>. If [oldpin] is provided,
45 the device's PIN is changed from [oldpin] to <pin>.
46
47- cred [-t ecdsa|rsa|eddsa] [-k pubkey] [-ei cred_id] [-P pin] [-T seconds]
48 [-hruv] <device>
49
50 Creates a new credential on <device> and verify that the credential
51 was signed by the authenticator. The device's attestation certificate
52 is not verified. If option -k is specified, the credential's public
53 key is stored in <pubkey>. If option -i is specified, the credential
54 ID is stored in <cred_id>. The -e option may be used to add <cred_id>
55 to the list of excluded credentials. If option -h is specified,
56 the hmac-secret FIDO2 extension is enabled on the generated
57 credential. If option -r is specified, the generated credential
58 will involve a resident key. User verification may be requested
59 through the -v option. If option -u is specified, the credential
60 is generated using U2F (CTAP1) instead of FIDO2 (CTAP2) commands.
61 The -T option may be used to enforce a timeout of <seconds>.
62
63- assert [-t ecdsa|rsa|eddsa] [-a cred_id] [-h hmac_secret] [-s hmac_salt]
64 [-P pin] [-T seconds] [-puv] <pubkey> <device>
65
66 Asks <device> for a FIDO2 assertion corresponding to [cred_id],
67 which may be omitted for resident keys. The obtained assertion
68 is verified using <pubkey>. The -p option requests that the user
69 be present. User verification may be requested through the -v
70 option. If option -u is specified, the assertion is generated using
71 U2F (CTAP1) instead of FIDO2 (CTAP2) commands. If option -s is
72 specified, a FIDO2 hmac-secret is requested from the authenticator,
73 and the contents of <hmac_salt> are used as the salt. If option -h
74 is specified, the resulting hmac-secret is stored in <hmac_secret>.
75 The -T option may be used to enforce a timeout of <seconds>.
76
77- retries <device>
78 Get the number of PIN attempts left on <device> before lockout.
79
80Debugging is possible through the use of the FIDO_DEBUG environment variable.
81If set, libfido2 will produce a log of its transactions with the authenticator.
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}
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}
diff --git a/examples/extern.h b/examples/extern.h
new file mode 100644
index 0000000..578b8c4
--- /dev/null
+++ b/examples/extern.h
@@ -0,0 +1,32 @@
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#ifndef _EXTERN_H_
8#define _EXTERN_H_
9
10#include <openssl/ec.h>
11#include <openssl/evp.h>
12#include <openssl/rsa.h>
13
14#ifdef HAVE_SIGNAL_H
15#include <signal.h>
16#endif
17
18/* util.c */
19EC_KEY *read_ec_pubkey(const char *);
20RSA *read_rsa_pubkey(const char *);
21EVP_PKEY *read_eddsa_pubkey(const char *);
22int base10(const char *, long long *);
23int read_blob(const char *, unsigned char **, size_t *);
24int write_blob(const char *, const unsigned char *, size_t);
25int write_ec_pubkey(const char *, const void *, size_t);
26int write_rsa_pubkey(const char *, const void *, size_t);
27int write_eddsa_pubkey(const char *, const void *, size_t);
28#ifdef SIGNAL_EXAMPLE
29void prepare_signal_handler(int);
30#endif
31
32#endif /* _EXTERN_H_ */
diff --git a/examples/info.c b/examples/info.c
new file mode 100644
index 0000000..e79729c
--- /dev/null
+++ b/examples/info.c
@@ -0,0 +1,216 @@
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 <stdint.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14
15#include "../openbsd-compat/openbsd-compat.h"
16
17#include "fido.h"
18
19/*
20 * Pretty-print a device's capabilities flags and return the result.
21 */
22static void
23format_flags(char *ret, size_t retlen, uint8_t flags)
24{
25 memset(ret, 0, retlen);
26
27 if (flags & FIDO_CAP_WINK) {
28 if (strlcat(ret, "wink,", retlen) >= retlen)
29 goto toolong;
30 } else {
31 if (strlcat(ret, "nowink,", retlen) >= retlen)
32 goto toolong;
33 }
34
35 if (flags & FIDO_CAP_CBOR) {
36 if (strlcat(ret, " cbor,", retlen) >= retlen)
37 goto toolong;
38 } else {
39 if (strlcat(ret, " nocbor,", retlen) >= retlen)
40 goto toolong;
41 }
42
43 if (flags & FIDO_CAP_NMSG) {
44 if (strlcat(ret, " nomsg", retlen) >= retlen)
45 goto toolong;
46 } else {
47 if (strlcat(ret, " msg", retlen) >= retlen)
48 goto toolong;
49 }
50
51 return;
52toolong:
53 strlcpy(ret, "toolong", retlen);
54}
55
56/*
57 * Print a FIDO device's attributes on stdout.
58 */
59static void
60print_attr(const fido_dev_t *dev)
61{
62 char flags_txt[128];
63
64 printf("proto: 0x%02x\n", fido_dev_protocol(dev));
65 printf("major: 0x%02x\n", fido_dev_major(dev));
66 printf("minor: 0x%02x\n", fido_dev_minor(dev));
67 printf("build: 0x%02x\n", fido_dev_build(dev));
68
69 format_flags(flags_txt, sizeof(flags_txt), fido_dev_flags(dev));
70 printf("caps: 0x%02x (%s)\n", fido_dev_flags(dev), flags_txt);
71}
72
73/*
74 * Auxiliary function to print an array of strings on stdout.
75 */
76static void
77print_str_array(const char *label, char * const *sa, size_t len)
78{
79 if (len == 0)
80 return;
81
82 printf("%s strings: ", label);
83
84 for (size_t i = 0; i < len; i++)
85 printf("%s%s", i > 0 ? ", " : "", sa[i]);
86
87 printf("\n");
88}
89
90/*
91 * Auxiliary function to print (char *, bool) pairs on stdout.
92 */
93static void
94print_opt_array(const char *label, char * const *name, const bool *value,
95 size_t len)
96{
97 if (len == 0)
98 return;
99
100 printf("%s: ", label);
101
102 for (size_t i = 0; i < len; i++)
103 printf("%s%s%s", i > 0 ? ", " : "",
104 value[i] ? "" : "no", name[i]);
105
106 printf("\n");
107}
108
109/*
110 * Auxiliary function to print an authenticator's AAGUID on stdout.
111 */
112static void
113print_aaguid(const unsigned char *buf, size_t buflen)
114{
115 printf("aaguid: ");
116
117 while (buflen--)
118 printf("%02x", *buf++);
119
120 printf("\n");
121}
122
123/*
124 * Auxiliary function to print an authenticator's maximum message size on
125 * stdout.
126 */
127static void
128print_maxmsgsiz(uint64_t maxmsgsiz)
129{
130 printf("maxmsgsiz: %d\n", (int)maxmsgsiz);
131}
132
133/*
134 * Auxiliary function to print an array of bytes on stdout.
135 */
136static void
137print_byte_array(const char *label, const uint8_t *ba, size_t len)
138{
139 if (len == 0)
140 return;
141
142 printf("%s: ", label);
143
144 for (size_t i = 0; i < len; i++)
145 printf("%s%u", i > 0 ? ", " : "", (unsigned)ba[i]);
146
147 printf("\n");
148}
149
150static void
151getinfo(const char *path)
152{
153 fido_dev_t *dev;
154 fido_cbor_info_t *ci;
155 int r;
156
157 fido_init(0);
158
159 if ((dev = fido_dev_new()) == NULL)
160 errx(1, "fido_dev_new");
161 if ((r = fido_dev_open(dev, path)) != FIDO_OK)
162 errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r);
163
164 print_attr(dev);
165
166 if (fido_dev_is_fido2(dev) == false)
167 goto end;
168 if ((ci = fido_cbor_info_new()) == NULL)
169 errx(1, "fido_cbor_info_new");
170 if ((r = fido_dev_get_cbor_info(dev, ci)) != FIDO_OK)
171 errx(1, "fido_dev_get_cbor_info: %s (0x%x)", fido_strerr(r), r);
172
173 /* print supported protocol versions */
174 print_str_array("version", fido_cbor_info_versions_ptr(ci),
175 fido_cbor_info_versions_len(ci));
176
177 /* print supported extensions */
178 print_str_array("extension", fido_cbor_info_extensions_ptr(ci),
179 fido_cbor_info_extensions_len(ci));
180
181 /* print aaguid */
182 print_aaguid(fido_cbor_info_aaguid_ptr(ci),
183 fido_cbor_info_aaguid_len(ci));
184
185 /* print supported options */
186 print_opt_array("options", fido_cbor_info_options_name_ptr(ci),
187 fido_cbor_info_options_value_ptr(ci),
188 fido_cbor_info_options_len(ci));
189
190 /* print maximum message size */
191 print_maxmsgsiz(fido_cbor_info_maxmsgsiz(ci));
192
193 /* print supported pin protocols */
194 print_byte_array("pin protocols", fido_cbor_info_protocols_ptr(ci),
195 fido_cbor_info_protocols_len(ci));
196
197 fido_cbor_info_free(&ci);
198end:
199 if ((r = fido_dev_close(dev)) != FIDO_OK)
200 errx(1, "fido_dev_close: %s (0x%x)", fido_strerr(r), r);
201
202 fido_dev_free(&dev);
203}
204
205int
206main(int argc, char **argv)
207{
208 if (argc != 2) {
209 fprintf(stderr, "usage: info <device>\n");
210 exit(EXIT_FAILURE);
211 }
212
213 getinfo(argv[1]);
214
215 exit(0);
216}
diff --git a/examples/manifest.c b/examples/manifest.c
new file mode 100644
index 0000000..895447a
--- /dev/null
+++ b/examples/manifest.c
@@ -0,0 +1,45 @@
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
13#include "../openbsd-compat/openbsd-compat.h"
14
15#include "fido.h"
16
17int
18main(void)
19{
20 fido_dev_info_t *devlist;
21 size_t ndevs;
22 int r;
23
24 fido_init(0);
25
26 if ((devlist = fido_dev_info_new(64)) == NULL)
27 errx(1, "fido_dev_info_new");
28
29 if ((r = fido_dev_info_manifest(devlist, 64, &ndevs)) != FIDO_OK)
30 errx(1, "fido_dev_info_manifest: %s (0x%x)", fido_strerr(r), r);
31
32 for (size_t i = 0; i < ndevs; i++) {
33 const fido_dev_info_t *di = fido_dev_info_ptr(devlist, i);
34 printf("%s: vendor=0x%04x, product=0x%04x (%s %s)\n",
35 fido_dev_info_path(di),
36 (uint16_t)fido_dev_info_vendor(di),
37 (uint16_t)fido_dev_info_product(di),
38 fido_dev_info_manufacturer_string(di),
39 fido_dev_info_product_string(di));
40 }
41
42 fido_dev_info_free(&devlist, ndevs);
43
44 exit(0);
45}
diff --git a/examples/reset.c b/examples/reset.c
new file mode 100644
index 0000000..36a7de2
--- /dev/null
+++ b/examples/reset.c
@@ -0,0 +1,64 @@
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/*
8 * Perform a factory reset on a given authenticator.
9 */
10
11#include <openssl/ec.h>
12
13#include <stdbool.h>
14#include <stdint.h>
15#include <stdio.h>
16#include <stdlib.h>
17
18#include "../openbsd-compat/openbsd-compat.h"
19
20#include "fido.h"
21#include "extern.h"
22
23#ifdef SIGNAL_EXAMPLE
24extern volatile sig_atomic_t got_signal;
25#endif
26
27int
28main(int argc, char **argv)
29{
30 fido_dev_t *dev;
31 int r;
32
33 if (argc != 2) {
34 fprintf(stderr, "usage: reset <device>\n");
35 exit(EXIT_FAILURE);
36 }
37
38 fido_init(0);
39
40 if ((dev = fido_dev_new()) == NULL)
41 errx(1, "fido_dev_new");
42
43 if ((r = fido_dev_open(dev, argv[1])) != FIDO_OK)
44 errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r);
45
46#ifdef SIGNAL_EXAMPLE
47 prepare_signal_handler(SIGINT);
48#endif
49
50 if ((r = fido_dev_reset(dev)) != FIDO_OK) {
51#ifdef SIGNAL_EXAMPLE
52 if (got_signal)
53 fido_dev_cancel(dev);
54#endif
55 errx(1, "fido_reset: %s (0x%x)", fido_strerr(r), r);
56 }
57
58 if ((r = fido_dev_close(dev)) != FIDO_OK)
59 errx(1, "fido_dev_close: %s (0x%x)", fido_strerr(r), r);
60
61 fido_dev_free(&dev);
62
63 exit(0);
64}
diff --git a/examples/retries.c b/examples/retries.c
new file mode 100644
index 0000000..3ed7558
--- /dev/null
+++ b/examples/retries.c
@@ -0,0 +1,52 @@
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/*
8 * Get an authenticator's number of PIN attempts left.
9 */
10
11#include <openssl/ec.h>
12
13#include <stdbool.h>
14#include <stdio.h>
15#include <stdlib.h>
16
17#include "../openbsd-compat/openbsd-compat.h"
18
19#include "fido.h"
20
21int
22main(int argc, char **argv)
23{
24 fido_dev_t *dev;
25 int n;
26 int r;
27
28 if (argc != 2) {
29 fprintf(stderr, "usage: retries <device>\n");
30 exit(EXIT_FAILURE);
31 }
32
33 fido_init(0);
34
35 if ((dev = fido_dev_new()) == NULL)
36 errx(1, "fido_dev_new");
37
38 if ((r = fido_dev_open(dev, argv[1])) != FIDO_OK)
39 errx(1, "fido_open: %s (0x%x)", fido_strerr(r), r);
40
41 if ((r = fido_dev_get_retry_count(dev, &n)) != FIDO_OK)
42 errx(1, "fido_get_retries: %s (0x%x)", fido_strerr(r), r);
43
44 if ((r = fido_dev_close(dev)) != FIDO_OK)
45 errx(1, "fido_close: %s (0x%x)", fido_strerr(r), r);
46
47 fido_dev_free(&dev);
48
49 printf("%d\n", n);
50
51 exit(0);
52}
diff --git a/examples/setpin.c b/examples/setpin.c
new file mode 100644
index 0000000..75d3d4a
--- /dev/null
+++ b/examples/setpin.c
@@ -0,0 +1,59 @@
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/*
8 * Configure a PIN on a given authenticator.
9 */
10
11#include <openssl/ec.h>
12
13#include <stdbool.h>
14#include <stdint.h>
15#include <stdio.h>
16#include <stdlib.h>
17
18#include "../openbsd-compat/openbsd-compat.h"
19
20#include "fido.h"
21
22static void
23setpin(const char *path, const char *pin, const char *oldpin)
24{
25 fido_dev_t *dev;
26 int r;
27
28 fido_init(0);
29
30 if ((dev = fido_dev_new()) == NULL)
31 errx(1, "fido_dev_new");
32
33 if ((r = fido_dev_open(dev, path)) != FIDO_OK)
34 errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r);
35
36 if ((r = fido_dev_set_pin(dev, pin, oldpin)) != FIDO_OK)
37 errx(1, "fido_setpin: %s (0x%x)", fido_strerr(r), r);
38
39 if ((r = fido_dev_close(dev)) != FIDO_OK)
40 errx(1, "fido_dev_close: %s (0x%x)", fido_strerr(r), r);
41
42 fido_dev_free(&dev);
43}
44
45int
46main(int argc, char **argv)
47{
48 if (argc < 3 || argc > 4) {
49 fprintf(stderr, "usage: setpin <pin> [oldpin] <device>\n");
50 exit(EXIT_FAILURE);
51 }
52
53 if (argc == 3)
54 setpin(argv[2], argv[1], NULL);
55 else
56 setpin(argv[3], argv[1], argv[2]);
57
58 exit(0);
59}
diff --git a/examples/util.c b/examples/util.c
new file mode 100644
index 0000000..2f6a845
--- /dev/null
+++ b/examples/util.c
@@ -0,0 +1,415 @@
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 <sys/types.h>
8#include <sys/stat.h>
9
10#include <openssl/ec.h>
11#include <openssl/evp.h>
12#include <openssl/pem.h>
13
14#include <errno.h>
15#include <fcntl.h>
16#include <limits.h>
17#include <stdbool.h>
18#include <stdlib.h>
19#include <string.h>
20#ifdef HAVE_SIGNAL_H
21#include <signal.h>
22#endif
23#ifdef HAVE_UNISTD_H
24#include <unistd.h>
25#endif
26#ifdef _MSC_VER
27#include "../openbsd-compat/posix_win.h"
28#endif
29
30#include "../openbsd-compat/openbsd-compat.h"
31
32#include "fido.h"
33#include "fido/es256.h"
34#include "fido/rs256.h"
35#include "fido/eddsa.h"
36#include "extern.h"
37
38#ifdef SIGNAL_EXAMPLE
39volatile sig_atomic_t got_signal = 0;
40
41static void
42signal_handler(int signo)
43{
44 (void)signo;
45 got_signal = 1;
46}
47
48void
49prepare_signal_handler(int signo)
50{
51 struct sigaction sa;
52
53 memset(&sa, 0, sizeof(sa));
54
55 sigemptyset(&sa.sa_mask);
56 sa.sa_handler = signal_handler;
57
58 if (sigaction(signo, &sa, NULL) < 0)
59 err(1, "sigaction");
60}
61#endif
62
63int
64base10(const char *str, long long *ll)
65{
66 char *ep;
67
68 *ll = strtoll(str, &ep, 10);
69 if (str == ep || *ep != '\0')
70 return (-1);
71 else if (*ll == LLONG_MIN && errno == ERANGE)
72 return (-1);
73 else if (*ll == LLONG_MAX && errno == ERANGE)
74 return (-1);
75
76 return (0);
77}
78
79int
80write_blob(const char *path, const unsigned char *ptr, size_t len)
81{
82 int fd, ok = -1;
83 ssize_t n;
84
85 if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) < 0) {
86 warn("open %s", path);
87 goto fail;
88 }
89
90 if ((n = write(fd, ptr, len)) < 0) {
91 warn("write");
92 goto fail;
93 }
94 if ((size_t)n != len) {
95 warnx("write");
96 goto fail;
97 }
98
99 ok = 0;
100fail:
101 if (fd != -1) {
102 close(fd);
103 }
104
105 return (ok);
106}
107
108int
109read_blob(const char *path, unsigned char **ptr, size_t *len)
110{
111 int fd, ok = -1;
112 struct stat st;
113 ssize_t n;
114
115 *ptr = NULL;
116 *len = 0;
117
118 if ((fd = open(path, O_RDONLY)) < 0) {
119 warn("open %s", path);
120 goto fail;
121 }
122 if (fstat(fd, &st) < 0) {
123 warn("stat %s", path);
124 goto fail;
125 }
126 if (st.st_size < 0) {
127 warnx("stat %s: invalid size", path);
128 goto fail;
129 }
130 *len = (size_t)st.st_size;
131 if ((*ptr = malloc(*len)) == NULL) {
132 warn("malloc");
133 goto fail;
134 }
135 if ((n = read(fd, *ptr, *len)) < 0) {
136 warn("read");
137 goto fail;
138 }
139 if ((size_t)n != *len) {
140 warnx("read");
141 goto fail;
142 }
143
144 ok = 0;
145fail:
146 if (fd != -1) {
147 close(fd);
148 }
149 if (ok < 0) {
150 free(*ptr);
151 *ptr = NULL;
152 *len = 0;
153 }
154
155 return (ok);
156}
157
158EC_KEY *
159read_ec_pubkey(const char *path)
160{
161 FILE *fp = NULL;
162 EVP_PKEY *pkey = NULL;
163 EC_KEY *ec = NULL;
164
165 if ((fp = fopen(path, "r")) == NULL) {
166 warn("fopen");
167 goto fail;
168 }
169
170 if ((pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
171 warnx("PEM_read_PUBKEY");
172 goto fail;
173 }
174 if ((ec = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) {
175 warnx("EVP_PKEY_get1_EC_KEY");
176 goto fail;
177 }
178
179fail:
180 if (fp != NULL) {
181 fclose(fp);
182 }
183 if (pkey != NULL) {
184 EVP_PKEY_free(pkey);
185 }
186
187 return (ec);
188}
189
190int
191write_ec_pubkey(const char *path, const void *ptr, size_t len)
192{
193 FILE *fp = NULL;
194 EVP_PKEY *pkey = NULL;
195 es256_pk_t *pk = NULL;
196 int fd = -1;
197 int ok = -1;
198
199 if ((pk = es256_pk_new()) == NULL) {
200 warnx("es256_pk_new");
201 goto fail;
202 }
203
204 if (es256_pk_from_ptr(pk, ptr, len) != FIDO_OK) {
205 warnx("es256_pk_from_ptr");
206 goto fail;
207 }
208
209 if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) < 0) {
210 warn("open %s", path);
211 goto fail;
212 }
213
214 if ((fp = fdopen(fd, "w")) == NULL) {
215 warn("fdopen");
216 goto fail;
217 }
218 fd = -1; /* owned by fp now */
219
220 if ((pkey = es256_pk_to_EVP_PKEY(pk)) == NULL) {
221 warnx("es256_pk_to_EVP_PKEY");
222 goto fail;
223 }
224
225 if (PEM_write_PUBKEY(fp, pkey) == 0) {
226 warnx("PEM_write_PUBKEY");
227 goto fail;
228 }
229
230 ok = 0;
231fail:
232 es256_pk_free(&pk);
233
234 if (fp != NULL) {
235 fclose(fp);
236 }
237 if (fd != -1) {
238 close(fd);
239 }
240 if (pkey != NULL) {
241 EVP_PKEY_free(pkey);
242 }
243
244 return (ok);
245}
246
247RSA *
248read_rsa_pubkey(const char *path)
249{
250 FILE *fp = NULL;
251 EVP_PKEY *pkey = NULL;
252 RSA *rsa = NULL;
253
254 if ((fp = fopen(path, "r")) == NULL) {
255 warn("fopen");
256 goto fail;
257 }
258
259 if ((pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
260 warnx("PEM_read_PUBKEY");
261 goto fail;
262 }
263 if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) {
264 warnx("EVP_PKEY_get1_RSA");
265 goto fail;
266 }
267
268fail:
269 if (fp != NULL) {
270 fclose(fp);
271 }
272 if (pkey != NULL) {
273 EVP_PKEY_free(pkey);
274 }
275
276 return (rsa);
277}
278
279int
280write_rsa_pubkey(const char *path, const void *ptr, size_t len)
281{
282 FILE *fp = NULL;
283 EVP_PKEY *pkey = NULL;
284 rs256_pk_t *pk = NULL;
285 int fd = -1;
286 int ok = -1;
287
288 if ((pk = rs256_pk_new()) == NULL) {
289 warnx("rs256_pk_new");
290 goto fail;
291 }
292
293 if (rs256_pk_from_ptr(pk, ptr, len) != FIDO_OK) {
294 warnx("rs256_pk_from_ptr");
295 goto fail;
296 }
297
298 if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) < 0) {
299 warn("open %s", path);
300 goto fail;
301 }
302
303 if ((fp = fdopen(fd, "w")) == NULL) {
304 warn("fdopen");
305 goto fail;
306 }
307 fd = -1; /* owned by fp now */
308
309 if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL) {
310 warnx("rs256_pk_to_EVP_PKEY");
311 goto fail;
312 }
313
314 if (PEM_write_PUBKEY(fp, pkey) == 0) {
315 warnx("PEM_write_PUBKEY");
316 goto fail;
317 }
318
319 ok = 0;
320fail:
321 rs256_pk_free(&pk);
322
323 if (fp != NULL) {
324 fclose(fp);
325 }
326 if (fd != -1) {
327 close(fd);
328 }
329 if (pkey != NULL) {
330 EVP_PKEY_free(pkey);
331 }
332
333 return (ok);
334}
335
336EVP_PKEY *
337read_eddsa_pubkey(const char *path)
338{
339 FILE *fp = NULL;
340 EVP_PKEY *pkey = NULL;
341
342 if ((fp = fopen(path, "r")) == NULL) {
343 warn("fopen");
344 goto fail;
345 }
346
347 if ((pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
348 warnx("PEM_read_PUBKEY");
349 goto fail;
350 }
351
352fail:
353 if (fp) {
354 fclose(fp);
355 }
356
357 return (pkey);
358}
359
360int
361write_eddsa_pubkey(const char *path, const void *ptr, size_t len)
362{
363 FILE *fp = NULL;
364 EVP_PKEY *pkey = NULL;
365 eddsa_pk_t *pk = NULL;
366 int fd = -1;
367 int ok = -1;
368
369 if ((pk = eddsa_pk_new()) == NULL) {
370 warnx("eddsa_pk_new");
371 goto fail;
372 }
373
374 if (eddsa_pk_from_ptr(pk, ptr, len) != FIDO_OK) {
375 warnx("eddsa_pk_from_ptr");
376 goto fail;
377 }
378
379 if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) < 0) {
380 warn("open %s", path);
381 goto fail;
382 }
383
384 if ((fp = fdopen(fd, "w")) == NULL) {
385 warn("fdopen");
386 goto fail;
387 }
388 fd = -1; /* owned by fp now */
389
390 if ((pkey = eddsa_pk_to_EVP_PKEY(pk)) == NULL) {
391 warnx("eddsa_pk_to_EVP_PKEY");
392 goto fail;
393 }
394
395 if (PEM_write_PUBKEY(fp, pkey) == 0) {
396 warnx("PEM_write_PUBKEY");
397 goto fail;
398 }
399
400 ok = 0;
401fail:
402 eddsa_pk_free(&pk);
403
404 if (fp != NULL) {
405 fclose(fp);
406 }
407 if (fd != -1) {
408 close(fd);
409 }
410 if (pkey != NULL) {
411 EVP_PKEY_free(pkey);
412 }
413
414 return (ok);
415}