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 32 void 33 read_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 45 FILE * 46 open_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 61 FILE * 62 open_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 81 void 82 xxd(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 99 int 100 string_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 120 fido_dev_t * 121 open_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 136 EC_KEY * 137 read_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 157 fail: 158 if (fp) { 159 fclose(fp); 160 } 161 if (pkey) { 162 EVP_PKEY_free(pkey); 163 } 164 165 return (ec); 166 } 167 168 int 169 write_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; 196 fail: 197 es256_pk_free(&pk); 198 199 if (pkey != NULL) { 200 EVP_PKEY_free(pkey); 201 } 202 203 return (ok); 204 } 205 206 RSA * 207 read_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 227 fail: 228 if (fp) { 229 fclose(fp); 230 } 231 if (pkey) { 232 EVP_PKEY_free(pkey); 233 } 234 235 return (rsa); 236 } 237 238 int 239 write_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; 266 fail: 267 rs256_pk_free(&pk); 268 269 if (pkey != NULL) { 270 EVP_PKEY_free(pkey); 271 } 272 273 return (ok); 274 } 275 276 EVP_PKEY * 277 read_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 292 fail: 293 if (fp) { 294 fclose(fp); 295 } 296 297 return (pkey); 298 } 299 300 int 301 write_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; 328 fail: 329 eddsa_pk_free(&pk); 330 331 if (pkey != NULL) { 332 EVP_PKEY_free(pkey); 333 } 334 335 return (ok); 336 } 337 338 void 339 print_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 } 365