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