summaryrefslogtreecommitdiff
path: root/tools/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/util.c')
-rw-r--r--tools/util.c364
1 files changed, 364 insertions, 0 deletions
diff --git a/tools/util.c b/tools/util.c
new file mode 100644
index 0000000..de70388
--- /dev/null
+++ b/tools/util.c
@@ -0,0 +1,364 @@
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 <fido.h>
15#include <fido/es256.h>
16#include <fido/rs256.h>
17#include <fido/eddsa.h>
18
19#include <fcntl.h>
20#include <stdint.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include "../openbsd-compat/openbsd-compat.h"
26#ifdef _MSC_VER
27#include "../openbsd-compat/posix_win.h"
28#endif
29
30#include "extern.h"
31
32void
33read_pin(const char *path, char *buf, size_t len)
34{
35 char prompt[1024];
36 int r;
37
38 r = snprintf(prompt, sizeof(prompt), "Enter PIN for %s: ", path);
39 if (r < 0 || (size_t)r >= sizeof(prompt))
40 errx(1, "snprintf");
41 if (!readpassphrase(prompt, buf, len, RPP_ECHO_OFF))
42 errx(1, "readpassphrase");
43}
44
45FILE *
46open_write(const char *file)
47{
48 int fd;
49 FILE *f;
50
51 if (file == NULL || strcmp(file, "-") == 0)
52 return (stdout);
53 if ((fd = open(file, O_WRONLY | O_CREAT, 0600)) < 0)
54 err(1, "open %s", file);
55 if ((f = fdopen(fd, "w")) == NULL)
56 err(1, "fdopen %s", file);
57
58 return (f);
59}
60
61FILE *
62open_read(const char *file)
63{
64 int fd;
65 FILE *f;
66
67 if (file == NULL || strcmp(file, "-") == 0) {
68#ifdef FIDO_FUZZ
69 setvbuf(stdin, NULL, _IONBF, 0);
70#endif
71 return (stdin);
72 }
73 if ((fd = open(file, O_RDONLY)) < 0)
74 err(1, "open %s", file);
75 if ((f = fdopen(fd, "r")) == NULL)
76 err(1, "fdopen %s", file);
77
78 return (f);
79}
80
81void
82xxd(const void *buf, size_t count)
83{
84 const uint8_t *ptr = buf;
85 size_t i;
86
87 fprintf(stderr, " ");
88
89 for (i = 0; i < count; i++) {
90 fprintf(stderr, "%02x ", *ptr++);
91 if ((i + 1) % 16 == 0 && i + 1 < count)
92 fprintf(stderr, "\n ");
93 }
94
95 fprintf(stderr, "\n");
96 fflush(stderr);
97}
98
99int
100string_read(FILE *f, char **out)
101{
102 char *line = NULL;
103 size_t linesize = 0;
104 ssize_t n;
105
106 *out = NULL;
107
108 if ((n = getline(&line, &linesize, f)) <= 0 ||
109 (size_t)n != strlen(line)) {
110 free(line);
111 return (-1);
112 }
113
114 line[n - 1] = '\0'; /* trim \n */
115 *out = line;
116
117 return (0);
118}
119
120fido_dev_t *
121open_dev(const char *path)
122{
123 fido_dev_t *dev;
124 int r;
125
126 if ((dev = fido_dev_new()) == NULL)
127 errx(1, "fido_dev_new");
128
129 r = fido_dev_open(dev, path);
130 if (r != FIDO_OK)
131 errx(1, "fido_dev_open %s: %s", path, fido_strerr(r));
132
133 return (dev);
134}
135
136EC_KEY *
137read_ec_pubkey(const char *path)
138{
139 FILE *fp = NULL;
140 EVP_PKEY *pkey = NULL;
141 EC_KEY *ec = NULL;
142
143 if ((fp = fopen(path, "r")) == NULL) {
144 warn("fopen");
145 goto fail;
146 }
147
148 if ((pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
149 warnx("PEM_read_PUBKEY");
150 goto fail;
151 }
152 if ((ec = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) {
153 warnx("EVP_PKEY_get1_EC_KEY");
154 goto fail;
155 }
156
157fail:
158 if (fp) {
159 fclose(fp);
160 }
161 if (pkey) {
162 EVP_PKEY_free(pkey);
163 }
164
165 return (ec);
166}
167
168int
169write_ec_pubkey(FILE *f, const void *ptr, size_t len)
170{
171 EVP_PKEY *pkey = NULL;
172 es256_pk_t *pk = NULL;
173 int ok = -1;
174
175 if ((pk = es256_pk_new()) == NULL) {
176 warnx("es256_pk_new");
177 goto fail;
178 }
179
180 if (es256_pk_from_ptr(pk, ptr, len) != FIDO_OK) {
181 warnx("es256_pk_from_ptr");
182 goto fail;
183 }
184
185 if ((pkey = es256_pk_to_EVP_PKEY(pk)) == NULL) {
186 warnx("es256_pk_to_EVP_PKEY");
187 goto fail;
188 }
189
190 if (PEM_write_PUBKEY(f, pkey) == 0) {
191 warnx("PEM_write_PUBKEY");
192 goto fail;
193 }
194
195 ok = 0;
196fail:
197 es256_pk_free(&pk);
198
199 if (pkey != NULL) {
200 EVP_PKEY_free(pkey);
201 }
202
203 return (ok);
204}
205
206RSA *
207read_rsa_pubkey(const char *path)
208{
209 FILE *fp = NULL;
210 EVP_PKEY *pkey = NULL;
211 RSA *rsa = NULL;
212
213 if ((fp = fopen(path, "r")) == NULL) {
214 warn("fopen");
215 goto fail;
216 }
217
218 if ((pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
219 warnx("PEM_read_PUBKEY");
220 goto fail;
221 }
222 if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) {
223 warnx("EVP_PKEY_get1_RSA");
224 goto fail;
225 }
226
227fail:
228 if (fp) {
229 fclose(fp);
230 }
231 if (pkey) {
232 EVP_PKEY_free(pkey);
233 }
234
235 return (rsa);
236}
237
238int
239write_rsa_pubkey(FILE *f, const void *ptr, size_t len)
240{
241 EVP_PKEY *pkey = NULL;
242 rs256_pk_t *pk = NULL;
243 int ok = -1;
244
245 if ((pk = rs256_pk_new()) == NULL) {
246 warnx("rs256_pk_new");
247 goto fail;
248 }
249
250 if (rs256_pk_from_ptr(pk, ptr, len) != FIDO_OK) {
251 warnx("rs256_pk_from_ptr");
252 goto fail;
253 }
254
255 if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL) {
256 warnx("rs256_pk_to_EVP_PKEY");
257 goto fail;
258 }
259
260 if (PEM_write_PUBKEY(f, pkey) == 0) {
261 warnx("PEM_write_PUBKEY");
262 goto fail;
263 }
264
265 ok = 0;
266fail:
267 rs256_pk_free(&pk);
268
269 if (pkey != NULL) {
270 EVP_PKEY_free(pkey);
271 }
272
273 return (ok);
274}
275
276EVP_PKEY *
277read_eddsa_pubkey(const char *path)
278{
279 FILE *fp = NULL;
280 EVP_PKEY *pkey = NULL;
281
282 if ((fp = fopen(path, "r")) == NULL) {
283 warn("fopen");
284 goto fail;
285 }
286
287 if ((pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
288 warnx("PEM_read_PUBKEY");
289 goto fail;
290 }
291
292fail:
293 if (fp) {
294 fclose(fp);
295 }
296
297 return (pkey);
298}
299
300int
301write_eddsa_pubkey(FILE *f, const void *ptr, size_t len)
302{
303 EVP_PKEY *pkey = NULL;
304 eddsa_pk_t *pk = NULL;
305 int ok = -1;
306
307 if ((pk = eddsa_pk_new()) == NULL) {
308 warnx("eddsa_pk_new");
309 goto fail;
310 }
311
312 if (eddsa_pk_from_ptr(pk, ptr, len) != FIDO_OK) {
313 warnx("eddsa_pk_from_ptr");
314 goto fail;
315 }
316
317 if ((pkey = eddsa_pk_to_EVP_PKEY(pk)) == NULL) {
318 warnx("eddsa_pk_to_EVP_PKEY");
319 goto fail;
320 }
321
322 if (PEM_write_PUBKEY(f, pkey) == 0) {
323 warnx("PEM_write_PUBKEY");
324 goto fail;
325 }
326
327 ok = 0;
328fail:
329 eddsa_pk_free(&pk);
330
331 if (pkey != NULL) {
332 EVP_PKEY_free(pkey);
333 }
334
335 return (ok);
336}
337
338void
339print_cred(FILE *out_f, int type, const fido_cred_t *cred)
340{
341 char *id;
342 int r;
343
344 r = base64_encode(fido_cred_id_ptr(cred), fido_cred_id_len(cred), &id);
345 if (r < 0)
346 errx(1, "output error");
347
348 fprintf(out_f, "%s\n", id);
349
350 if (type == COSE_ES256) {
351 write_ec_pubkey(out_f, fido_cred_pubkey_ptr(cred),
352 fido_cred_pubkey_len(cred));
353 } else if (type == COSE_RS256) {
354 write_rsa_pubkey(out_f, fido_cred_pubkey_ptr(cred),
355 fido_cred_pubkey_len(cred));
356 } else if (type == COSE_EDDSA) {
357 write_eddsa_pubkey(out_f, fido_cred_pubkey_ptr(cred),
358 fido_cred_pubkey_len(cred));
359 } else {
360 errx(1, "print_cred: unknown type");
361 }
362
363 free(id);
364}