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 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 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