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 <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 static fido_cred_t * 20 prepare_cred(FILE *in_f, int type, int flags) 21 { 22 fido_cred_t *cred = NULL; 23 struct blob cdh; 24 struct blob authdata; 25 struct blob id; 26 struct blob sig; 27 struct blob x5c; 28 char *rpid = NULL; 29 char *fmt = NULL; 30 int r; 31 32 memset(&cdh, 0, sizeof(cdh)); 33 memset(&authdata, 0, sizeof(authdata)); 34 memset(&id, 0, sizeof(id)); 35 memset(&sig, 0, sizeof(sig)); 36 memset(&x5c, 0, sizeof(x5c)); 37 38 r = base64_read(in_f, &cdh); 39 r |= string_read(in_f, &rpid); 40 r |= string_read(in_f, &fmt); 41 r |= base64_read(in_f, &authdata); 42 r |= base64_read(in_f, &id); 43 r |= base64_read(in_f, &sig); 44 if (r < 0) 45 errx(1, "input error"); 46 47 (void)base64_read(in_f, &x5c); 48 49 if (flags & FLAG_DEBUG) { 50 fprintf(stderr, "client data hash:\n"); 51 xxd(cdh.ptr, cdh.len); 52 fprintf(stderr, "relying party id: %s\n", rpid); 53 fprintf(stderr, "format: %s\n", fmt); 54 fprintf(stderr, "authenticator data:\n"); 55 xxd(authdata.ptr, authdata.len); 56 fprintf(stderr, "credential id:\n"); 57 xxd(id.ptr, id.len); 58 fprintf(stderr, "signature:\n"); 59 xxd(sig.ptr, sig.len); 60 fprintf(stderr, "x509:\n"); 61 xxd(x5c.ptr, x5c.len); 62 } 63 64 if ((cred = fido_cred_new()) == NULL) 65 errx(1, "fido_cred_new"); 66 67 if ((r = fido_cred_set_type(cred, type)) != FIDO_OK || 68 (r = fido_cred_set_clientdata_hash(cred, cdh.ptr, 69 cdh.len)) != FIDO_OK || 70 (r = fido_cred_set_rp(cred, rpid, NULL)) != FIDO_OK || 71 (r = fido_cred_set_authdata(cred, authdata.ptr, 72 authdata.len)) != FIDO_OK || 73 (r = fido_cred_set_sig(cred, sig.ptr, sig.len)) != FIDO_OK || 74 (r = fido_cred_set_fmt(cred, fmt)) != FIDO_OK) 75 errx(1, "fido_cred_set: %s", fido_strerr(r)); 76 77 if (x5c.ptr != NULL) { 78 if ((r = fido_cred_set_x509(cred, x5c.ptr, x5c.len)) != FIDO_OK) 79 errx(1, "fido_cred_set_x509: %s", fido_strerr(r)); 80 } 81 82 if (flags & FLAG_UV) { 83 if ((r = fido_cred_set_uv(cred, FIDO_OPT_TRUE)) != FIDO_OK) 84 errx(1, "fido_cred_set_uv: %s", fido_strerr(r)); 85 } 86 if (flags & FLAG_HMAC) { 87 if ((r = fido_cred_set_extensions(cred, 88 FIDO_EXT_HMAC_SECRET)) != FIDO_OK) 89 errx(1, "fido_cred_set_extensions: %s", fido_strerr(r)); 90 } 91 92 free(cdh.ptr); 93 free(authdata.ptr); 94 free(id.ptr); 95 free(sig.ptr); 96 free(x5c.ptr); 97 free(rpid); 98 free(fmt); 99 100 return (cred); 101 } 102 103 int 104 cred_verify(int argc, char **argv) 105 { 106 fido_cred_t *cred = NULL; 107 char *in_path = NULL; 108 char *out_path = NULL; 109 FILE *in_f = NULL; 110 FILE *out_f = NULL; 111 int type = COSE_ES256; 112 int flags = 0; 113 int cred_prot = -1; 114 int ch; 115 int r; 116 117 while ((ch = getopt(argc, argv, "c:dhi:o:v")) != -1) { 118 switch (ch) { 119 case 'c': 120 if ((cred_prot = base10(optarg)) < 0) 121 errx(1, "-c: invalid argument '%s'", optarg); 122 break; 123 case 'd': 124 flags |= FLAG_DEBUG; 125 break; 126 case 'h': 127 flags |= FLAG_HMAC; 128 break; 129 case 'i': 130 in_path = optarg; 131 break; 132 case 'o': 133 out_path = optarg; 134 break; 135 case 'v': 136 flags |= FLAG_UV; 137 break; 138 default: 139 usage(); 140 } 141 } 142 143 argc -= optind; 144 argv += optind; 145 146 if (argc > 1) 147 usage(); 148 149 in_f = open_read(in_path); 150 out_f = open_write(out_path); 151 152 if (argc > 0 && cose_type(argv[0], &type) < 0) 153 errx(1, "unknown type %s", argv[0]); 154 155 fido_init((flags & FLAG_DEBUG) ? FIDO_DEBUG : 0); 156 cred = prepare_cred(in_f, type, flags); 157 158 if (cred_prot > 0) { 159 r = fido_cred_set_prot(cred, cred_prot); 160 if (r != FIDO_OK) { 161 errx(1, "fido_cred_set_prot: %s", fido_strerr(r)); 162 } 163 } 164 165 if (fido_cred_x5c_ptr(cred) == NULL) { 166 if ((r = fido_cred_verify_self(cred)) != FIDO_OK) 167 errx(1, "fido_cred_verify_self: %s", fido_strerr(r)); 168 } else { 169 if ((r = fido_cred_verify(cred)) != FIDO_OK) 170 errx(1, "fido_cred_verify: %s", fido_strerr(r)); 171 } 172 173 print_cred(out_f, type, cred); 174 fido_cred_free(&cred); 175 176 fclose(in_f); 177 fclose(out_f); 178 in_f = NULL; 179 out_f = NULL; 180 181 exit(0); 182 } 183