10afa8e06SEd Maste /*
20afa8e06SEd Maste * Copyright (c) 2018 Yubico AB. All rights reserved.
30afa8e06SEd Maste * Use of this source code is governed by a BSD-style
40afa8e06SEd Maste * license that can be found in the LICENSE file.
5*2ccfa855SEd Maste * SPDX-License-Identifier: BSD-2-Clause
60afa8e06SEd Maste */
70afa8e06SEd Maste
80afa8e06SEd Maste #include <fido.h>
90afa8e06SEd Maste #include <stdio.h>
100afa8e06SEd Maste #include <stdlib.h>
110afa8e06SEd Maste #include <string.h>
120afa8e06SEd Maste #ifdef HAVE_UNISTD_H
130afa8e06SEd Maste #include <unistd.h>
140afa8e06SEd Maste #endif
150afa8e06SEd Maste
160afa8e06SEd Maste #include "../openbsd-compat/openbsd-compat.h"
170afa8e06SEd Maste #include "extern.h"
180afa8e06SEd Maste
190afa8e06SEd Maste static fido_cred_t *
prepare_cred(FILE * in_f,int type,int flags)200afa8e06SEd Maste prepare_cred(FILE *in_f, int type, int flags)
210afa8e06SEd Maste {
220afa8e06SEd Maste fido_cred_t *cred = NULL;
230afa8e06SEd Maste struct blob cdh;
240afa8e06SEd Maste struct blob authdata;
250afa8e06SEd Maste struct blob id;
260afa8e06SEd Maste struct blob sig;
270afa8e06SEd Maste struct blob x5c;
280afa8e06SEd Maste char *rpid = NULL;
290afa8e06SEd Maste char *fmt = NULL;
300afa8e06SEd Maste int r;
310afa8e06SEd Maste
320afa8e06SEd Maste memset(&cdh, 0, sizeof(cdh));
330afa8e06SEd Maste memset(&authdata, 0, sizeof(authdata));
340afa8e06SEd Maste memset(&id, 0, sizeof(id));
350afa8e06SEd Maste memset(&sig, 0, sizeof(sig));
360afa8e06SEd Maste memset(&x5c, 0, sizeof(x5c));
370afa8e06SEd Maste
380afa8e06SEd Maste r = base64_read(in_f, &cdh);
390afa8e06SEd Maste r |= string_read(in_f, &rpid);
400afa8e06SEd Maste r |= string_read(in_f, &fmt);
410afa8e06SEd Maste r |= base64_read(in_f, &authdata);
420afa8e06SEd Maste r |= base64_read(in_f, &id);
430afa8e06SEd Maste r |= base64_read(in_f, &sig);
440afa8e06SEd Maste if (r < 0)
450afa8e06SEd Maste errx(1, "input error");
460afa8e06SEd Maste
470afa8e06SEd Maste (void)base64_read(in_f, &x5c);
480afa8e06SEd Maste
490afa8e06SEd Maste if (flags & FLAG_DEBUG) {
500afa8e06SEd Maste fprintf(stderr, "client data hash:\n");
510afa8e06SEd Maste xxd(cdh.ptr, cdh.len);
520afa8e06SEd Maste fprintf(stderr, "relying party id: %s\n", rpid);
530afa8e06SEd Maste fprintf(stderr, "format: %s\n", fmt);
540afa8e06SEd Maste fprintf(stderr, "authenticator data:\n");
550afa8e06SEd Maste xxd(authdata.ptr, authdata.len);
560afa8e06SEd Maste fprintf(stderr, "credential id:\n");
570afa8e06SEd Maste xxd(id.ptr, id.len);
580afa8e06SEd Maste fprintf(stderr, "signature:\n");
590afa8e06SEd Maste xxd(sig.ptr, sig.len);
600afa8e06SEd Maste fprintf(stderr, "x509:\n");
610afa8e06SEd Maste xxd(x5c.ptr, x5c.len);
620afa8e06SEd Maste }
630afa8e06SEd Maste
640afa8e06SEd Maste if ((cred = fido_cred_new()) == NULL)
650afa8e06SEd Maste errx(1, "fido_cred_new");
660afa8e06SEd Maste
670afa8e06SEd Maste if ((r = fido_cred_set_type(cred, type)) != FIDO_OK ||
680afa8e06SEd Maste (r = fido_cred_set_clientdata_hash(cred, cdh.ptr,
690afa8e06SEd Maste cdh.len)) != FIDO_OK ||
700afa8e06SEd Maste (r = fido_cred_set_rp(cred, rpid, NULL)) != FIDO_OK ||
710afa8e06SEd Maste (r = fido_cred_set_authdata(cred, authdata.ptr,
720afa8e06SEd Maste authdata.len)) != FIDO_OK ||
730afa8e06SEd Maste (r = fido_cred_set_sig(cred, sig.ptr, sig.len)) != FIDO_OK ||
740afa8e06SEd Maste (r = fido_cred_set_fmt(cred, fmt)) != FIDO_OK)
750afa8e06SEd Maste errx(1, "fido_cred_set: %s", fido_strerr(r));
760afa8e06SEd Maste
770afa8e06SEd Maste if (x5c.ptr != NULL) {
780afa8e06SEd Maste if ((r = fido_cred_set_x509(cred, x5c.ptr, x5c.len)) != FIDO_OK)
790afa8e06SEd Maste errx(1, "fido_cred_set_x509: %s", fido_strerr(r));
800afa8e06SEd Maste }
810afa8e06SEd Maste
820afa8e06SEd Maste if (flags & FLAG_UV) {
830afa8e06SEd Maste if ((r = fido_cred_set_uv(cred, FIDO_OPT_TRUE)) != FIDO_OK)
840afa8e06SEd Maste errx(1, "fido_cred_set_uv: %s", fido_strerr(r));
850afa8e06SEd Maste }
860afa8e06SEd Maste if (flags & FLAG_HMAC) {
870afa8e06SEd Maste if ((r = fido_cred_set_extensions(cred,
880afa8e06SEd Maste FIDO_EXT_HMAC_SECRET)) != FIDO_OK)
890afa8e06SEd Maste errx(1, "fido_cred_set_extensions: %s", fido_strerr(r));
900afa8e06SEd Maste }
910afa8e06SEd Maste
920afa8e06SEd Maste free(cdh.ptr);
930afa8e06SEd Maste free(authdata.ptr);
940afa8e06SEd Maste free(id.ptr);
950afa8e06SEd Maste free(sig.ptr);
960afa8e06SEd Maste free(x5c.ptr);
970afa8e06SEd Maste free(rpid);
980afa8e06SEd Maste free(fmt);
990afa8e06SEd Maste
1000afa8e06SEd Maste return (cred);
1010afa8e06SEd Maste }
1020afa8e06SEd Maste
1030afa8e06SEd Maste int
cred_verify(int argc,char ** argv)1040afa8e06SEd Maste cred_verify(int argc, char **argv)
1050afa8e06SEd Maste {
1060afa8e06SEd Maste fido_cred_t *cred = NULL;
1070afa8e06SEd Maste char *in_path = NULL;
1080afa8e06SEd Maste char *out_path = NULL;
1090afa8e06SEd Maste FILE *in_f = NULL;
1100afa8e06SEd Maste FILE *out_f = NULL;
1110afa8e06SEd Maste int type = COSE_ES256;
1120afa8e06SEd Maste int flags = 0;
1130afa8e06SEd Maste int cred_prot = -1;
1140afa8e06SEd Maste int ch;
1150afa8e06SEd Maste int r;
1160afa8e06SEd Maste
1170afa8e06SEd Maste while ((ch = getopt(argc, argv, "c:dhi:o:v")) != -1) {
1180afa8e06SEd Maste switch (ch) {
1190afa8e06SEd Maste case 'c':
1200afa8e06SEd Maste if ((cred_prot = base10(optarg)) < 0)
1210afa8e06SEd Maste errx(1, "-c: invalid argument '%s'", optarg);
1220afa8e06SEd Maste break;
1230afa8e06SEd Maste case 'd':
1240afa8e06SEd Maste flags |= FLAG_DEBUG;
1250afa8e06SEd Maste break;
1260afa8e06SEd Maste case 'h':
1270afa8e06SEd Maste flags |= FLAG_HMAC;
1280afa8e06SEd Maste break;
1290afa8e06SEd Maste case 'i':
1300afa8e06SEd Maste in_path = optarg;
1310afa8e06SEd Maste break;
1320afa8e06SEd Maste case 'o':
1330afa8e06SEd Maste out_path = optarg;
1340afa8e06SEd Maste break;
1350afa8e06SEd Maste case 'v':
1360afa8e06SEd Maste flags |= FLAG_UV;
1370afa8e06SEd Maste break;
1380afa8e06SEd Maste default:
1390afa8e06SEd Maste usage();
1400afa8e06SEd Maste }
1410afa8e06SEd Maste }
1420afa8e06SEd Maste
1430afa8e06SEd Maste argc -= optind;
1440afa8e06SEd Maste argv += optind;
1450afa8e06SEd Maste
1460afa8e06SEd Maste if (argc > 1)
1470afa8e06SEd Maste usage();
1480afa8e06SEd Maste
1490afa8e06SEd Maste in_f = open_read(in_path);
1500afa8e06SEd Maste out_f = open_write(out_path);
1510afa8e06SEd Maste
1520afa8e06SEd Maste if (argc > 0 && cose_type(argv[0], &type) < 0)
1530afa8e06SEd Maste errx(1, "unknown type %s", argv[0]);
1540afa8e06SEd Maste
1550afa8e06SEd Maste fido_init((flags & FLAG_DEBUG) ? FIDO_DEBUG : 0);
1560afa8e06SEd Maste cred = prepare_cred(in_f, type, flags);
1570afa8e06SEd Maste
1580afa8e06SEd Maste if (cred_prot > 0) {
1590afa8e06SEd Maste r = fido_cred_set_prot(cred, cred_prot);
1600afa8e06SEd Maste if (r != FIDO_OK) {
1610afa8e06SEd Maste errx(1, "fido_cred_set_prot: %s", fido_strerr(r));
1620afa8e06SEd Maste }
1630afa8e06SEd Maste }
1640afa8e06SEd Maste
1650afa8e06SEd Maste if (fido_cred_x5c_ptr(cred) == NULL) {
1660afa8e06SEd Maste if ((r = fido_cred_verify_self(cred)) != FIDO_OK)
1670afa8e06SEd Maste errx(1, "fido_cred_verify_self: %s", fido_strerr(r));
1680afa8e06SEd Maste } else {
1690afa8e06SEd Maste if ((r = fido_cred_verify(cred)) != FIDO_OK)
1700afa8e06SEd Maste errx(1, "fido_cred_verify: %s", fido_strerr(r));
1710afa8e06SEd Maste }
1720afa8e06SEd Maste
1730afa8e06SEd Maste print_cred(out_f, type, cred);
1740afa8e06SEd Maste fido_cred_free(&cred);
1750afa8e06SEd Maste
1760afa8e06SEd Maste fclose(in_f);
1770afa8e06SEd Maste fclose(out_f);
1780afa8e06SEd Maste in_f = NULL;
1790afa8e06SEd Maste out_f = NULL;
1800afa8e06SEd Maste
1810afa8e06SEd Maste exit(0);
1820afa8e06SEd Maste }
183