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 <fido/es256.h> 9 #include <fido/rs256.h> 10 #include <fido/eddsa.h> 11 12 #include <stdbool.h> 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #ifdef HAVE_UNISTD_H 17 #include <unistd.h> 18 #endif 19 20 #include "../openbsd-compat/openbsd-compat.h" 21 #include "extern.h" 22 23 static fido_assert_t * 24 prepare_assert(FILE *in_f, int flags) 25 { 26 fido_assert_t *assert = NULL; 27 struct blob cdh; 28 struct blob authdata; 29 struct blob sig; 30 char *rpid = NULL; 31 int r; 32 33 memset(&cdh, 0, sizeof(cdh)); 34 memset(&authdata, 0, sizeof(authdata)); 35 memset(&sig, 0, sizeof(sig)); 36 37 r = base64_read(in_f, &cdh); 38 r |= string_read(in_f, &rpid); 39 r |= base64_read(in_f, &authdata); 40 r |= base64_read(in_f, &sig); 41 if (r < 0) 42 errx(1, "input error"); 43 44 if (flags & FLAG_DEBUG) { 45 fprintf(stderr, "client data hash:\n"); 46 xxd(cdh.ptr, cdh.len); 47 fprintf(stderr, "relying party id: %s\n", rpid); 48 fprintf(stderr, "authenticator data:\n"); 49 xxd(authdata.ptr, authdata.len); 50 fprintf(stderr, "signature:\n"); 51 xxd(sig.ptr, sig.len); 52 } 53 54 if ((assert = fido_assert_new()) == NULL) 55 errx(1, "fido_assert_new"); 56 if ((r = fido_assert_set_count(assert, 1)) != FIDO_OK) 57 errx(1, "fido_assert_count: %s", fido_strerr(r)); 58 59 if ((r = fido_assert_set_clientdata_hash(assert, cdh.ptr, 60 cdh.len)) != FIDO_OK || 61 (r = fido_assert_set_rp(assert, rpid)) != FIDO_OK || 62 (r = fido_assert_set_authdata(assert, 0, authdata.ptr, 63 authdata.len)) != FIDO_OK || 64 (r = fido_assert_set_sig(assert, 0, sig.ptr, sig.len)) != FIDO_OK) 65 errx(1, "fido_assert_set: %s", fido_strerr(r)); 66 67 if (flags & FLAG_UP) { 68 if ((r = fido_assert_set_up(assert, FIDO_OPT_TRUE)) != FIDO_OK) 69 errx(1, "fido_assert_set_up: %s", fido_strerr(r)); 70 } 71 if (flags & FLAG_UV) { 72 if ((r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK) 73 errx(1, "fido_assert_set_uv: %s", fido_strerr(r)); 74 } 75 if (flags & FLAG_HMAC) { 76 if ((r = fido_assert_set_extensions(assert, 77 FIDO_EXT_HMAC_SECRET)) != FIDO_OK) 78 errx(1, "fido_assert_set_extensions: %s", 79 fido_strerr(r)); 80 } 81 82 free(cdh.ptr); 83 free(authdata.ptr); 84 free(sig.ptr); 85 free(rpid); 86 87 return (assert); 88 } 89 90 static void * 91 load_pubkey(int type, const char *file) 92 { 93 EC_KEY *ec = NULL; 94 RSA *rsa = NULL; 95 EVP_PKEY *eddsa = NULL; 96 es256_pk_t *es256_pk = NULL; 97 rs256_pk_t *rs256_pk = NULL; 98 eddsa_pk_t *eddsa_pk = NULL; 99 void *pk = NULL; 100 101 if (type == COSE_ES256) { 102 if ((ec = read_ec_pubkey(file)) == NULL) 103 errx(1, "read_ec_pubkey"); 104 if ((es256_pk = es256_pk_new()) == NULL) 105 errx(1, "es256_pk_new"); 106 if (es256_pk_from_EC_KEY(es256_pk, ec) != FIDO_OK) 107 errx(1, "es256_pk_from_EC_KEY"); 108 109 pk = es256_pk; 110 EC_KEY_free(ec); 111 } else if (type == COSE_RS256) { 112 if ((rsa = read_rsa_pubkey(file)) == NULL) 113 errx(1, "read_rsa_pubkey"); 114 if ((rs256_pk = rs256_pk_new()) == NULL) 115 errx(1, "rs256_pk_new"); 116 if (rs256_pk_from_RSA(rs256_pk, rsa) != FIDO_OK) 117 errx(1, "rs256_pk_from_RSA"); 118 119 pk = rs256_pk; 120 RSA_free(rsa); 121 } else if (type == COSE_EDDSA) { 122 if ((eddsa = read_eddsa_pubkey(file)) == NULL) 123 errx(1, "read_eddsa_pubkey"); 124 if ((eddsa_pk = eddsa_pk_new()) == NULL) 125 errx(1, "eddsa_pk_new"); 126 if (eddsa_pk_from_EVP_PKEY(eddsa_pk, eddsa) != FIDO_OK) 127 errx(1, "eddsa_pk_from_EVP_PKEY"); 128 129 pk = eddsa_pk; 130 EVP_PKEY_free(eddsa); 131 } 132 133 return (pk); 134 } 135 136 int 137 assert_verify(int argc, char **argv) 138 { 139 fido_assert_t *assert = NULL; 140 void *pk = NULL; 141 char *in_path = NULL; 142 FILE *in_f = NULL; 143 int type = COSE_ES256; 144 int flags = 0; 145 int ch; 146 int r; 147 148 while ((ch = getopt(argc, argv, "dhi:pv")) != -1) { 149 switch (ch) { 150 case 'd': 151 flags |= FLAG_DEBUG; 152 break; 153 case 'h': 154 flags |= FLAG_HMAC; 155 break; 156 case 'i': 157 in_path = optarg; 158 break; 159 case 'p': 160 flags |= FLAG_UP; 161 break; 162 case 'v': 163 flags |= FLAG_UV; 164 break; 165 default: 166 usage(); 167 } 168 } 169 170 argc -= optind; 171 argv += optind; 172 173 if (argc < 1 || argc > 2) 174 usage(); 175 176 in_f = open_read(in_path); 177 178 if (argc > 1 && cose_type(argv[1], &type) < 0) 179 errx(1, "unknown type %s", argv[1]); 180 181 fido_init((flags & FLAG_DEBUG) ? FIDO_DEBUG : 0); 182 183 pk = load_pubkey(type, argv[0]); 184 assert = prepare_assert(in_f, flags); 185 if ((r = fido_assert_verify(assert, 0, type, pk)) != FIDO_OK) 186 errx(1, "fido_assert_verify: %s", fido_strerr(r)); 187 fido_assert_free(&assert); 188 189 fclose(in_f); 190 in_f = NULL; 191 192 exit(0); 193 } 194