Home | History | Annotate | Line # | Download | only in tools
util.c revision 1.1
      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