summaryrefslogtreecommitdiff
path: root/tools/cred_make.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/cred_make.c')
-rw-r--r--tools/cred_make.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/tools/cred_make.c b/tools/cred_make.c
new file mode 100644
index 0000000..380c67a
--- /dev/null
+++ b/tools/cred_make.c
@@ -0,0 +1,221 @@
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 <fido.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#ifdef HAVE_UNISTD_H
12#include <unistd.h>
13#endif
14
15#include "../openbsd-compat/openbsd-compat.h"
16#include "extern.h"
17
18static fido_cred_t *
19prepare_cred(FILE *in_f, int type, int flags)
20{
21 fido_cred_t *cred = NULL;
22 struct blob cdh;
23 struct blob uid;
24 char *rpid = NULL;
25 char *uname = NULL;
26 int r;
27
28 memset(&cdh, 0, sizeof(cdh));
29 memset(&uid, 0, sizeof(uid));
30
31 r = base64_read(in_f, &cdh);
32 r |= string_read(in_f, &rpid);
33 r |= string_read(in_f, &uname);
34 r |= base64_read(in_f, &uid);
35 if (r < 0)
36 errx(1, "input error");
37
38 if (flags & FLAG_DEBUG) {
39 fprintf(stderr, "client data hash:\n");
40 xxd(cdh.ptr, cdh.len);
41 fprintf(stderr, "relying party id: %s\n", rpid);
42 fprintf(stderr, "user name: %s\n", uname);
43 fprintf(stderr, "user id:\n");
44 xxd(uid.ptr, uid.len);
45 }
46
47 if ((cred = fido_cred_new()) == NULL)
48 errx(1, "fido_cred_new");
49
50 if ((r = fido_cred_set_type(cred, type)) != FIDO_OK ||
51 (r = fido_cred_set_clientdata_hash(cred, cdh.ptr,
52 cdh.len)) != FIDO_OK ||
53 (r = fido_cred_set_rp(cred, rpid, NULL)) != FIDO_OK ||
54 (r = fido_cred_set_user(cred, uid.ptr, uid.len, uname, NULL,
55 NULL)) != FIDO_OK)
56 errx(1, "fido_cred_set: %s", fido_strerr(r));
57
58 if (flags & FLAG_RK) {
59 if ((r = fido_cred_set_rk(cred, FIDO_OPT_TRUE)) != FIDO_OK)
60 errx(1, "fido_cred_set_rk: %s", fido_strerr(r));
61 }
62 if (flags & FLAG_UV) {
63 if ((r = fido_cred_set_uv(cred, FIDO_OPT_TRUE)) != FIDO_OK)
64 errx(1, "fido_cred_set_uv: %s", fido_strerr(r));
65 }
66 if (flags & FLAG_HMAC) {
67 if ((r = fido_cred_set_extensions(cred,
68 FIDO_EXT_HMAC_SECRET)) != FIDO_OK)
69 errx(1, "fido_cred_set_extensions: %s", fido_strerr(r));
70 }
71
72 free(cdh.ptr);
73 free(uid.ptr);
74 free(rpid);
75 free(uname);
76
77 return (cred);
78}
79
80static void
81print_attcred(FILE *out_f, const fido_cred_t *cred)
82{
83 char *cdh = NULL;
84 char *authdata = NULL;
85 char *id = NULL;
86 char *sig = NULL;
87 char *x5c = NULL;
88 int r;
89
90 r = base64_encode(fido_cred_clientdata_hash_ptr(cred),
91 fido_cred_clientdata_hash_len(cred), &cdh);
92 r |= base64_encode(fido_cred_authdata_ptr(cred),
93 fido_cred_authdata_len(cred), &authdata);
94 r |= base64_encode(fido_cred_id_ptr(cred), fido_cred_id_len(cred),
95 &id);
96 r |= base64_encode(fido_cred_sig_ptr(cred), fido_cred_sig_len(cred),
97 &sig);
98 if (fido_cred_x5c_ptr(cred) != NULL)
99 r |= base64_encode(fido_cred_x5c_ptr(cred),
100 fido_cred_x5c_len(cred), &x5c);
101 if (r < 0)
102 errx(1, "output error");
103
104 fprintf(out_f, "%s\n", cdh);
105 fprintf(out_f, "%s\n", fido_cred_rp_id(cred));
106 fprintf(out_f, "%s\n", fido_cred_fmt(cred));
107 fprintf(out_f, "%s\n", authdata);
108 fprintf(out_f, "%s\n", id);
109 fprintf(out_f, "%s\n", sig);
110 if (x5c != NULL)
111 fprintf(out_f, "%s\n", x5c);
112
113 free(cdh);
114 free(authdata);
115 free(id);
116 free(sig);
117 free(x5c);
118}
119
120int
121cred_make(int argc, char **argv)
122{
123 fido_dev_t *dev = NULL;
124 fido_cred_t *cred = NULL;
125 char prompt[1024];
126 char pin[1024];
127 char *in_path = NULL;
128 char *out_path = NULL;
129 FILE *in_f = NULL;
130 FILE *out_f = NULL;
131 int type = COSE_ES256;
132 int flags = 0;
133 int ch;
134 int r;
135
136 while ((ch = getopt(argc, argv, "dhi:o:qruv")) != -1) {
137 switch (ch) {
138 case 'd':
139 flags |= FLAG_DEBUG;
140 break;
141 case 'h':
142 flags |= FLAG_HMAC;
143 break;
144 case 'i':
145 in_path = optarg;
146 break;
147 case 'o':
148 out_path = optarg;
149 break;
150 case 'q':
151 flags |= FLAG_QUIET;
152 break;
153 case 'r':
154 flags |= FLAG_RK;
155 break;
156 case 'u':
157 flags |= FLAG_U2F;
158 break;
159 case 'v':
160 flags |= FLAG_UV;
161 break;
162 default:
163 usage();
164 }
165 }
166
167 argc -= optind;
168 argv += optind;
169
170 if (argc < 1 || argc > 2)
171 usage();
172
173 in_f = open_read(in_path);
174 out_f = open_write(out_path);
175
176 if (argc > 1) {
177 if (strcmp(argv[1], "es256") == 0)
178 type = COSE_ES256;
179 else if (strcmp(argv[1], "rs256") == 0)
180 type = COSE_RS256;
181 else if (strcmp(argv[1], "eddsa") == 0)
182 type = COSE_EDDSA;
183 else
184 errx(1, "unknown type %s", argv[1]);
185 }
186
187 fido_init((flags & FLAG_DEBUG) ? FIDO_DEBUG : 0);
188
189 cred = prepare_cred(in_f, type, flags);
190
191 dev = open_dev(argv[0]);
192 if (flags & FLAG_U2F)
193 fido_dev_force_u2f(dev);
194
195 r = fido_dev_make_cred(dev, cred, NULL);
196 if (r == FIDO_ERR_PIN_REQUIRED && !(flags & FLAG_QUIET)) {
197 r = snprintf(prompt, sizeof(prompt), "Enter PIN for %s: ",
198 argv[0]);
199 if (r < 0 || (size_t)r >= sizeof(prompt))
200 errx(1, "snprintf");
201 if (!readpassphrase(prompt, pin, sizeof(pin), RPP_ECHO_OFF))
202 errx(1, "readpassphrase");
203 r = fido_dev_make_cred(dev, cred, pin);
204 }
205
206 explicit_bzero(pin, sizeof(pin));
207 if (r != FIDO_OK)
208 errx(1, "fido_dev_make_cred: %s", fido_strerr(r));
209 print_attcred(out_f, cred);
210
211 fido_dev_close(dev);
212 fido_dev_free(&dev);
213 fido_cred_free(&cred);
214
215 fclose(in_f);
216 fclose(out_f);
217 in_f = NULL;
218 out_f = NULL;
219
220 exit(0);
221}