xref: /freebsd/contrib/libfido2/tools/pin.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
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 <stdbool.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #ifdef HAVE_UNISTD_H
13 #include <unistd.h>
14 #endif
15 
16 #include "../openbsd-compat/openbsd-compat.h"
17 #include "extern.h"
18 
19 int
20 pin_set(char *path)
21 {
22 	fido_dev_t *dev = NULL;
23 	char prompt[1024];
24 	char pin1[1024];
25 	char pin2[1024];
26 	int r;
27 	int status = 1;
28 
29 	dev = open_dev(path);
30 
31 	r = snprintf(prompt, sizeof(prompt), "Enter new PIN for %s: ", path);
32 	if (r < 0 || (size_t)r >= sizeof(prompt)) {
33 		warnx("snprintf");
34 		goto out;
35 	}
36 
37 	if (!readpassphrase(prompt, pin1, sizeof(pin1), RPP_ECHO_OFF)) {
38 		warnx("readpassphrase");
39 		goto out;
40 	}
41 
42 	r = snprintf(prompt, sizeof(prompt), "Enter the same PIN again: ");
43 	if (r < 0 || (size_t)r >= sizeof(prompt)) {
44 		warnx("snprintf");
45 		goto out;
46 	}
47 
48 	if (!readpassphrase(prompt, pin2, sizeof(pin2), RPP_ECHO_OFF)) {
49 		warnx("readpassphrase");
50 		goto out;
51 	}
52 
53 	if (strcmp(pin1, pin2) != 0) {
54 		fprintf(stderr, "PINs do not match. Try again.\n");
55 		goto out;
56 	}
57 
58 	if ((r = fido_dev_set_pin(dev, pin1, NULL)) != FIDO_OK) {
59 		warnx("fido_dev_set_pin: %s", fido_strerr(r));
60 		goto out;
61 	}
62 
63 	fido_dev_close(dev);
64 	fido_dev_free(&dev);
65 
66 	status = 0;
67 out:
68 	explicit_bzero(pin1, sizeof(pin1));
69 	explicit_bzero(pin2, sizeof(pin2));
70 
71 	exit(status);
72 }
73 
74 int
75 pin_change(char *path)
76 {
77 	fido_dev_t *dev = NULL;
78 	char prompt[1024];
79 	char pin0[1024];
80 	char pin1[1024];
81 	char pin2[1024];
82 	int r;
83 	int status = 1;
84 
85 	if (path == NULL)
86 		usage();
87 
88 	dev = open_dev(path);
89 
90 	r = snprintf(prompt, sizeof(prompt), "Enter current PIN for %s: ", path);
91 	if (r < 0 || (size_t)r >= sizeof(prompt)) {
92 		warnx("snprintf");
93 		goto out;
94 	}
95 
96 	if (!readpassphrase(prompt, pin0, sizeof(pin0), RPP_ECHO_OFF)) {
97 		warnx("readpassphrase");
98 		goto out;
99 	}
100 
101 	r = snprintf(prompt, sizeof(prompt), "Enter new PIN for %s: ", path);
102 	if (r < 0 || (size_t)r >= sizeof(prompt)) {
103 		warnx("snprintf");
104 		goto out;
105 	}
106 
107 	if (!readpassphrase(prompt, pin1, sizeof(pin1), RPP_ECHO_OFF)) {
108 		warnx("readpassphrase");
109 		goto out;
110 	}
111 
112 	r = snprintf(prompt, sizeof(prompt), "Enter the same PIN again: ");
113 	if (r < 0 || (size_t)r >= sizeof(prompt)) {
114 		warnx("snprintf");
115 		goto out;
116 	}
117 
118 	if (!readpassphrase(prompt, pin2, sizeof(pin2), RPP_ECHO_OFF)) {
119 		warnx("readpassphrase");
120 		goto out;
121 	}
122 
123 	if (strcmp(pin1, pin2) != 0) {
124 		fprintf(stderr, "PINs do not match. Try again.\n");
125 		goto out;
126 	}
127 
128 	if ((r = fido_dev_set_pin(dev, pin1, pin0)) != FIDO_OK) {
129 		warnx("fido_dev_set_pin: %s", fido_strerr(r));
130 		goto out;
131 	}
132 
133 	fido_dev_close(dev);
134 	fido_dev_free(&dev);
135 
136 	status = 0;
137 out:
138 	explicit_bzero(pin0, sizeof(pin0));
139 	explicit_bzero(pin1, sizeof(pin1));
140 	explicit_bzero(pin2, sizeof(pin2));
141 
142 	exit(status);
143 }
144