Path: blob/main/contrib/libfido2/examples/assert.c
39536 views
/*1* Copyright (c) 2018-2022 Yubico AB. All rights reserved.2* Use of this source code is governed by a BSD-style3* license that can be found in the LICENSE file.4* SPDX-License-Identifier: BSD-2-Clause5*/67#include <fido.h>8#include <fido/es256.h>9#include <fido/es384.h>10#include <fido/rs256.h>11#include <fido/eddsa.h>1213#include <stdbool.h>14#include <stdio.h>15#include <stdlib.h>16#include <string.h>17#ifdef HAVE_UNISTD_H18#include <unistd.h>19#endif2021#include "../openbsd-compat/openbsd-compat.h"22#include "extern.h"2324static const unsigned char cd[32] = {250xec, 0x8d, 0x8f, 0x78, 0x42, 0x4a, 0x2b, 0xb7,260x82, 0x34, 0xaa, 0xca, 0x07, 0xa1, 0xf6, 0x56,270x42, 0x1c, 0xb6, 0xf6, 0xb3, 0x00, 0x86, 0x52,280x35, 0x2d, 0xa2, 0x62, 0x4a, 0xbe, 0x89, 0x76,29};3031static void32usage(void)33{34fprintf(stderr, "usage: assert [-t es256|es384|rs256|eddsa] "35"[-a cred_id] [-h hmac_secret] [-s hmac_salt] [-P pin] "36"[-T seconds] [-b blobkey] [-puv] <pubkey> <device>\n");37exit(EXIT_FAILURE);38}3940static void41verify_assert(int type, const unsigned char *authdata_ptr, size_t authdata_len,42const unsigned char *sig_ptr, size_t sig_len, bool up, bool uv, int ext,43const char *key)44{45fido_assert_t *assert = NULL;46EC_KEY *ec = NULL;47RSA *rsa = NULL;48EVP_PKEY *eddsa = NULL;49es256_pk_t *es256_pk = NULL;50es384_pk_t *es384_pk = NULL;51rs256_pk_t *rs256_pk = NULL;52eddsa_pk_t *eddsa_pk = NULL;53void *pk;54int r;5556/* credential pubkey */57switch (type) {58case COSE_ES256:59if ((ec = read_ec_pubkey(key)) == NULL)60errx(1, "read_ec_pubkey");6162if ((es256_pk = es256_pk_new()) == NULL)63errx(1, "es256_pk_new");6465if (es256_pk_from_EC_KEY(es256_pk, ec) != FIDO_OK)66errx(1, "es256_pk_from_EC_KEY");6768pk = es256_pk;69EC_KEY_free(ec);70ec = NULL;7172break;73case COSE_ES384:74if ((ec = read_ec_pubkey(key)) == NULL)75errx(1, "read_ec_pubkey");7677if ((es384_pk = es384_pk_new()) == NULL)78errx(1, "es384_pk_new");7980if (es384_pk_from_EC_KEY(es384_pk, ec) != FIDO_OK)81errx(1, "es384_pk_from_EC_KEY");8283pk = es384_pk;84EC_KEY_free(ec);85ec = NULL;8687break;88case COSE_RS256:89if ((rsa = read_rsa_pubkey(key)) == NULL)90errx(1, "read_rsa_pubkey");9192if ((rs256_pk = rs256_pk_new()) == NULL)93errx(1, "rs256_pk_new");9495if (rs256_pk_from_RSA(rs256_pk, rsa) != FIDO_OK)96errx(1, "rs256_pk_from_RSA");9798pk = rs256_pk;99RSA_free(rsa);100rsa = NULL;101102break;103case COSE_EDDSA:104if ((eddsa = read_eddsa_pubkey(key)) == NULL)105errx(1, "read_eddsa_pubkey");106107if ((eddsa_pk = eddsa_pk_new()) == NULL)108errx(1, "eddsa_pk_new");109110if (eddsa_pk_from_EVP_PKEY(eddsa_pk, eddsa) != FIDO_OK)111errx(1, "eddsa_pk_from_EVP_PKEY");112113pk = eddsa_pk;114EVP_PKEY_free(eddsa);115eddsa = NULL;116117break;118default:119errx(1, "unknown credential type %d", type);120}121122if ((assert = fido_assert_new()) == NULL)123errx(1, "fido_assert_new");124125/* client data hash */126r = fido_assert_set_clientdata(assert, cd, sizeof(cd));127if (r != FIDO_OK)128errx(1, "fido_assert_set_clientdata: %s (0x%x)", fido_strerr(r), r);129130/* relying party */131r = fido_assert_set_rp(assert, "localhost");132if (r != FIDO_OK)133errx(1, "fido_assert_set_rp: %s (0x%x)", fido_strerr(r), r);134135/* authdata */136r = fido_assert_set_count(assert, 1);137if (r != FIDO_OK)138errx(1, "fido_assert_set_count: %s (0x%x)", fido_strerr(r), r);139r = fido_assert_set_authdata(assert, 0, authdata_ptr, authdata_len);140if (r != FIDO_OK)141errx(1, "fido_assert_set_authdata: %s (0x%x)", fido_strerr(r), r);142143/* extension */144r = fido_assert_set_extensions(assert, ext);145if (r != FIDO_OK)146errx(1, "fido_assert_set_extensions: %s (0x%x)", fido_strerr(r),147r);148149/* user presence */150if (up && (r = fido_assert_set_up(assert, FIDO_OPT_TRUE)) != FIDO_OK)151errx(1, "fido_assert_set_up: %s (0x%x)", fido_strerr(r), r);152153/* user verification */154if (uv && (r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK)155errx(1, "fido_assert_set_uv: %s (0x%x)", fido_strerr(r), r);156157/* sig */158r = fido_assert_set_sig(assert, 0, sig_ptr, sig_len);159if (r != FIDO_OK)160errx(1, "fido_assert_set_sig: %s (0x%x)", fido_strerr(r), r);161162r = fido_assert_verify(assert, 0, type, pk);163if (r != FIDO_OK)164errx(1, "fido_assert_verify: %s (0x%x)", fido_strerr(r), r);165166es256_pk_free(&es256_pk);167es384_pk_free(&es384_pk);168rs256_pk_free(&rs256_pk);169eddsa_pk_free(&eddsa_pk);170171fido_assert_free(&assert);172}173174int175main(int argc, char **argv)176{177bool up = false;178bool uv = false;179bool u2f = false;180fido_dev_t *dev = NULL;181fido_assert_t *assert = NULL;182const char *pin = NULL;183const char *blobkey_out = NULL;184const char *hmac_out = NULL;185unsigned char *body = NULL;186long long ms = 0;187size_t len;188int type = COSE_ES256;189int ext = 0;190int ch;191int r;192193if ((assert = fido_assert_new()) == NULL)194errx(1, "fido_assert_new");195196while ((ch = getopt(argc, argv, "P:T:a:b:h:ps:t:uv")) != -1) {197switch (ch) {198case 'P':199pin = optarg;200break;201case 'T':202if (base10(optarg, &ms) < 0)203errx(1, "base10: %s", optarg);204if (ms <= 0 || ms > 30)205errx(1, "-T: %s must be in (0,30]", optarg);206ms *= 1000; /* seconds to milliseconds */207break;208case 'a':209if (read_blob(optarg, &body, &len) < 0)210errx(1, "read_blob: %s", optarg);211if ((r = fido_assert_allow_cred(assert, body,212len)) != FIDO_OK)213errx(1, "fido_assert_allow_cred: %s (0x%x)",214fido_strerr(r), r);215free(body);216body = NULL;217break;218case 'b':219ext |= FIDO_EXT_LARGEBLOB_KEY;220blobkey_out = optarg;221break;222case 'h':223hmac_out = optarg;224break;225case 'p':226up = true;227break;228case 's':229ext |= FIDO_EXT_HMAC_SECRET;230if (read_blob(optarg, &body, &len) < 0)231errx(1, "read_blob: %s", optarg);232if ((r = fido_assert_set_hmac_salt(assert, body,233len)) != FIDO_OK)234errx(1, "fido_assert_set_hmac_salt: %s (0x%x)",235fido_strerr(r), r);236free(body);237body = NULL;238break;239case 't':240if (strcmp(optarg, "es256") == 0)241type = COSE_ES256;242else if (strcmp(optarg, "es384") == 0)243type = COSE_ES384;244else if (strcmp(optarg, "rs256") == 0)245type = COSE_RS256;246else if (strcmp(optarg, "eddsa") == 0)247type = COSE_EDDSA;248else249errx(1, "unknown type %s", optarg);250break;251case 'u':252u2f = true;253break;254case 'v':255uv = true;256break;257default:258usage();259}260}261262argc -= optind;263argv += optind;264265if (argc != 2)266usage();267268fido_init(0);269270if ((dev = fido_dev_new()) == NULL)271errx(1, "fido_dev_new");272273r = fido_dev_open(dev, argv[1]);274if (r != FIDO_OK)275errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r);276if (u2f)277fido_dev_force_u2f(dev);278279/* client data hash */280r = fido_assert_set_clientdata(assert, cd, sizeof(cd));281if (r != FIDO_OK)282errx(1, "fido_assert_set_clientdata: %s (0x%x)", fido_strerr(r), r);283284/* relying party */285r = fido_assert_set_rp(assert, "localhost");286if (r != FIDO_OK)287errx(1, "fido_assert_set_rp: %s (0x%x)", fido_strerr(r), r);288289/* extensions */290r = fido_assert_set_extensions(assert, ext);291if (r != FIDO_OK)292errx(1, "fido_assert_set_extensions: %s (0x%x)", fido_strerr(r),293r);294295/* user presence */296if (up && (r = fido_assert_set_up(assert, FIDO_OPT_TRUE)) != FIDO_OK)297errx(1, "fido_assert_set_up: %s (0x%x)", fido_strerr(r), r);298299/* user verification */300if (uv && (r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK)301errx(1, "fido_assert_set_uv: %s (0x%x)", fido_strerr(r), r);302303/* timeout */304if (ms != 0 && (r = fido_dev_set_timeout(dev, (int)ms)) != FIDO_OK)305errx(1, "fido_dev_set_timeout: %s (0x%x)", fido_strerr(r), r);306307if ((r = fido_dev_get_assert(dev, assert, pin)) != FIDO_OK) {308fido_dev_cancel(dev);309errx(1, "fido_dev_get_assert: %s (0x%x)", fido_strerr(r), r);310}311312r = fido_dev_close(dev);313if (r != FIDO_OK)314errx(1, "fido_dev_close: %s (0x%x)", fido_strerr(r), r);315316fido_dev_free(&dev);317318if (fido_assert_count(assert) != 1)319errx(1, "fido_assert_count: %d signatures returned",320(int)fido_assert_count(assert));321322/* when verifying, pin implies uv */323if (pin)324uv = true;325326verify_assert(type, fido_assert_authdata_ptr(assert, 0),327fido_assert_authdata_len(assert, 0), fido_assert_sig_ptr(assert, 0),328fido_assert_sig_len(assert, 0), up, uv, ext, argv[0]);329330if (hmac_out != NULL) {331/* extract the hmac secret */332if (write_blob(hmac_out, fido_assert_hmac_secret_ptr(assert, 0),333fido_assert_hmac_secret_len(assert, 0)) < 0)334errx(1, "write_blob");335}336337if (blobkey_out != NULL) {338/* extract the hmac secret */339if (write_blob(blobkey_out,340fido_assert_largeblob_key_ptr(assert, 0),341fido_assert_largeblob_key_len(assert, 0)) < 0)342errx(1, "write_blob");343}344345fido_assert_free(&assert);346347exit(0);348}349350351