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 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8 #include <fido.h>
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 #include "extern.h"
19
20 int
pin_set(char * path)21 pin_set(char *path)
22 {
23 fido_dev_t *dev = NULL;
24 char prompt[1024];
25 char pin1[128];
26 char pin2[128];
27 int r;
28 int status = 1;
29
30 dev = open_dev(path);
31
32 r = snprintf(prompt, sizeof(prompt), "Enter new PIN for %s: ", path);
33 if (r < 0 || (size_t)r >= sizeof(prompt)) {
34 warnx("snprintf");
35 goto out;
36 }
37
38 if (!readpassphrase(prompt, pin1, sizeof(pin1), RPP_ECHO_OFF)) {
39 warnx("readpassphrase");
40 goto out;
41 }
42
43 r = snprintf(prompt, sizeof(prompt), "Enter the same PIN again: ");
44 if (r < 0 || (size_t)r >= sizeof(prompt)) {
45 warnx("snprintf");
46 goto out;
47 }
48
49 if (!readpassphrase(prompt, pin2, sizeof(pin2), RPP_ECHO_OFF)) {
50 warnx("readpassphrase");
51 goto out;
52 }
53
54 if (strcmp(pin1, pin2) != 0) {
55 fprintf(stderr, "PINs do not match. Try again.\n");
56 goto out;
57 }
58
59 if (strlen(pin1) < 4 || strlen(pin1) > 63) {
60 fprintf(stderr, "invalid PIN length\n");
61 goto out;
62 }
63
64 if ((r = fido_dev_set_pin(dev, pin1, NULL)) != FIDO_OK) {
65 warnx("fido_dev_set_pin: %s", fido_strerr(r));
66 goto out;
67 }
68
69 fido_dev_close(dev);
70 fido_dev_free(&dev);
71
72 status = 0;
73 out:
74 explicit_bzero(pin1, sizeof(pin1));
75 explicit_bzero(pin2, sizeof(pin2));
76
77 exit(status);
78 }
79
80 int
pin_change(char * path)81 pin_change(char *path)
82 {
83 fido_dev_t *dev = NULL;
84 char prompt[1024];
85 char pin0[128];
86 char pin1[128];
87 char pin2[128];
88 int r;
89 int status = 1;
90
91 if (path == NULL)
92 usage();
93
94 dev = open_dev(path);
95
96 r = snprintf(prompt, sizeof(prompt), "Enter current PIN for %s: ", path);
97 if (r < 0 || (size_t)r >= sizeof(prompt)) {
98 warnx("snprintf");
99 goto out;
100 }
101
102 if (!readpassphrase(prompt, pin0, sizeof(pin0), RPP_ECHO_OFF)) {
103 warnx("readpassphrase");
104 goto out;
105 }
106
107 if (strlen(pin0) < 4 || strlen(pin0) > 63) {
108 warnx("invalid PIN length");
109 goto out;
110 }
111
112 r = snprintf(prompt, sizeof(prompt), "Enter new PIN for %s: ", path);
113 if (r < 0 || (size_t)r >= sizeof(prompt)) {
114 warnx("snprintf");
115 goto out;
116 }
117
118 if (!readpassphrase(prompt, pin1, sizeof(pin1), RPP_ECHO_OFF)) {
119 warnx("readpassphrase");
120 goto out;
121 }
122
123 r = snprintf(prompt, sizeof(prompt), "Enter the same PIN again: ");
124 if (r < 0 || (size_t)r >= sizeof(prompt)) {
125 warnx("snprintf");
126 goto out;
127 }
128
129 if (!readpassphrase(prompt, pin2, sizeof(pin2), RPP_ECHO_OFF)) {
130 warnx("readpassphrase");
131 goto out;
132 }
133
134 if (strcmp(pin1, pin2) != 0) {
135 fprintf(stderr, "PINs do not match. Try again.\n");
136 goto out;
137 }
138
139 if (strlen(pin1) < 4 || strlen(pin1) > 63) {
140 fprintf(stderr, "invalid PIN length\n");
141 goto out;
142 }
143
144 if ((r = fido_dev_set_pin(dev, pin1, pin0)) != FIDO_OK) {
145 warnx("fido_dev_set_pin: %s", fido_strerr(r));
146 goto out;
147 }
148
149 fido_dev_close(dev);
150 fido_dev_free(&dev);
151
152 status = 0;
153 out:
154 explicit_bzero(pin0, sizeof(pin0));
155 explicit_bzero(pin1, sizeof(pin1));
156 explicit_bzero(pin2, sizeof(pin2));
157
158 exit(status);
159 }
160