2 * Copyright (c) 2018-2022 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
8 #include <openssl/sha.h>
9 #include <openssl/x509.h>
17 #include "fido/es256.h"
18 #include "fallthrough.h"
20 #define U2F_PACE_MS (100)
24 usleep(unsigned int usec)
33 delay_ms(unsigned int ms, int *ms_remain)
35 if (*ms_remain > -1 && (unsigned int)*ms_remain < ms)
36 ms = (unsigned int)*ms_remain;
38 if (ms > UINT_MAX / 1000) {
39 fido_log_debug("%s: ms=%u", __func__, ms);
43 if (usleep(ms * 1000) < 0) {
44 fido_log_error(errno, "%s: usleep", __func__);
49 *ms_remain -= (int)ms;
55 sig_get(fido_blob_t *sig, const unsigned char **buf, size_t *len)
57 sig->len = *len; /* consume the whole buffer */
58 if ((sig->ptr = calloc(1, sig->len)) == NULL ||
59 fido_buf_read(buf, len, sig->ptr, sig->len) < 0) {
60 fido_log_debug("%s: fido_buf_read", __func__);
69 x5c_get(fido_blob_t *x5c, const unsigned char **buf, size_t *len)
74 if (*len > LONG_MAX) {
75 fido_log_debug("%s: invalid len %zu", __func__, *len);
79 /* find out the certificate's length */
80 const unsigned char *end = *buf;
81 if ((cert = d2i_X509(NULL, &end, (long)*len)) == NULL || end <= *buf ||
82 (x5c->len = (size_t)(end - *buf)) >= *len) {
83 fido_log_debug("%s: d2i_X509", __func__);
87 /* read accordingly */
88 if ((x5c->ptr = calloc(1, x5c->len)) == NULL ||
89 fido_buf_read(buf, len, x5c->ptr, x5c->len) < 0) {
90 fido_log_debug("%s: fido_buf_read", __func__);
100 fido_blob_reset(x5c);
106 authdata_fake(const char *rp_id, uint8_t flags, uint32_t sigcount,
107 fido_blob_t *fake_cbor_ad)
110 cbor_item_t *item = NULL;
113 memset(&ad, 0, sizeof(ad));
115 if (SHA256((const void *)rp_id, strlen(rp_id),
116 ad.rp_id_hash) != ad.rp_id_hash) {
117 fido_log_debug("%s: sha256", __func__);
121 ad.flags = flags; /* XXX translate? */
122 ad.sigcount = sigcount;
124 if ((item = cbor_build_bytestring((const unsigned char *)&ad,
125 sizeof(ad))) == NULL) {
126 fido_log_debug("%s: cbor_build_bytestring", __func__);
130 if (fake_cbor_ad->ptr != NULL ||
131 (fake_cbor_ad->len = cbor_serialize_alloc(item, &fake_cbor_ad->ptr,
133 fido_log_debug("%s: cbor_serialize_alloc", __func__);
143 /* TODO: use u2f_get_touch_begin & u2f_get_touch_status instead */
145 send_dummy_register(fido_dev_t *dev, int *ms)
147 iso7816_apdu_t *apdu = NULL;
148 unsigned char *reply = NULL;
149 unsigned char challenge[SHA256_DIGEST_LENGTH];
150 unsigned char application[SHA256_DIGEST_LENGTH];
153 /* dummy challenge & application */
154 memset(&challenge, 0xff, sizeof(challenge));
155 memset(&application, 0xff, sizeof(application));
157 if ((apdu = iso7816_new(0, U2F_CMD_REGISTER, 0, 2 *
158 SHA256_DIGEST_LENGTH)) == NULL ||
159 iso7816_add(apdu, &challenge, sizeof(challenge)) < 0 ||
160 iso7816_add(apdu, &application, sizeof(application)) < 0) {
161 fido_log_debug("%s: iso7816", __func__);
162 r = FIDO_ERR_INTERNAL;
166 if ((reply = malloc(FIDO_MAXMSG)) == NULL) {
167 fido_log_debug("%s: malloc", __func__);
168 r = FIDO_ERR_INTERNAL;
173 if (fido_tx(dev, CTAP_CMD_MSG, iso7816_ptr(apdu),
174 iso7816_len(apdu), ms) < 0) {
175 fido_log_debug("%s: fido_tx", __func__);
179 if (fido_rx(dev, CTAP_CMD_MSG, reply, FIDO_MAXMSG, ms) < 2) {
180 fido_log_debug("%s: fido_rx", __func__);
184 if (delay_ms(U2F_PACE_MS, ms) != 0) {
185 fido_log_debug("%s: delay_ms", __func__);
189 } while (((reply[0] << 8) | reply[1]) == SW_CONDITIONS_NOT_SATISFIED);
194 freezero(reply, FIDO_MAXMSG);
200 key_lookup(fido_dev_t *dev, const char *rp_id, const fido_blob_t *key_id,
203 iso7816_apdu_t *apdu = NULL;
204 unsigned char *reply = NULL;
205 unsigned char challenge[SHA256_DIGEST_LENGTH];
206 unsigned char rp_id_hash[SHA256_DIGEST_LENGTH];
210 if (key_id->len > UINT8_MAX || rp_id == NULL) {
211 fido_log_debug("%s: key_id->len=%zu, rp_id=%p", __func__,
212 key_id->len, (const void *)rp_id);
213 r = FIDO_ERR_INVALID_ARGUMENT;
217 memset(&challenge, 0xff, sizeof(challenge));
218 memset(&rp_id_hash, 0, sizeof(rp_id_hash));
220 if (SHA256((const void *)rp_id, strlen(rp_id),
221 rp_id_hash) != rp_id_hash) {
222 fido_log_debug("%s: sha256", __func__);
223 r = FIDO_ERR_INTERNAL;
227 key_id_len = (uint8_t)key_id->len;
229 if ((apdu = iso7816_new(0, U2F_CMD_AUTH, U2F_AUTH_CHECK, (uint16_t)(2 *
230 SHA256_DIGEST_LENGTH + sizeof(key_id_len) + key_id_len))) == NULL ||
231 iso7816_add(apdu, &challenge, sizeof(challenge)) < 0 ||
232 iso7816_add(apdu, &rp_id_hash, sizeof(rp_id_hash)) < 0 ||
233 iso7816_add(apdu, &key_id_len, sizeof(key_id_len)) < 0 ||
234 iso7816_add(apdu, key_id->ptr, key_id_len) < 0) {
235 fido_log_debug("%s: iso7816", __func__);
236 r = FIDO_ERR_INTERNAL;
240 if ((reply = malloc(FIDO_MAXMSG)) == NULL) {
241 fido_log_debug("%s: malloc", __func__);
242 r = FIDO_ERR_INTERNAL;
246 if (fido_tx(dev, CTAP_CMD_MSG, iso7816_ptr(apdu),
247 iso7816_len(apdu), ms) < 0) {
248 fido_log_debug("%s: fido_tx", __func__);
252 if (fido_rx(dev, CTAP_CMD_MSG, reply, FIDO_MAXMSG, ms) != 2) {
253 fido_log_debug("%s: fido_rx", __func__);
258 switch ((reply[0] << 8) | reply[1]) {
259 case SW_CONDITIONS_NOT_SATISFIED:
260 *found = 1; /* key exists */
263 *found = 0; /* key does not exist */
267 r = FIDO_ERR_INTERNAL;
274 freezero(reply, FIDO_MAXMSG);
280 parse_auth_reply(fido_blob_t *sig, fido_blob_t *ad, const char *rp_id,
281 const unsigned char *reply, size_t len)
286 if (len < 2 || ((reply[len - 2] << 8) | reply[len - 1]) != SW_NO_ERROR) {
287 fido_log_debug("%s: unexpected sw", __func__);
288 return (FIDO_ERR_RX);
293 if (fido_buf_read(&reply, &len, &flags, sizeof(flags)) < 0 ||
294 fido_buf_read(&reply, &len, &sigcount, sizeof(sigcount)) < 0) {
295 fido_log_debug("%s: fido_buf_read", __func__);
296 return (FIDO_ERR_RX);
299 if (sig_get(sig, &reply, &len) < 0) {
300 fido_log_debug("%s: sig_get", __func__);
301 return (FIDO_ERR_RX);
304 if (authdata_fake(rp_id, flags, sigcount, ad) < 0) {
305 fido_log_debug("%s; authdata_fake", __func__);
306 return (FIDO_ERR_RX);
313 do_auth(fido_dev_t *dev, const fido_blob_t *cdh, const char *rp_id,
314 const fido_blob_t *key_id, fido_blob_t *sig, fido_blob_t *ad, int *ms)
316 iso7816_apdu_t *apdu = NULL;
317 unsigned char *reply = NULL;
318 unsigned char rp_id_hash[SHA256_DIGEST_LENGTH];
327 if (cdh->len != SHA256_DIGEST_LENGTH || key_id->len > UINT8_MAX ||
329 r = FIDO_ERR_INVALID_ARGUMENT;
333 memset(&rp_id_hash, 0, sizeof(rp_id_hash));
335 if (SHA256((const void *)rp_id, strlen(rp_id),
336 rp_id_hash) != rp_id_hash) {
337 fido_log_debug("%s: sha256", __func__);
338 r = FIDO_ERR_INTERNAL;
342 key_id_len = (uint8_t)key_id->len;
344 if ((apdu = iso7816_new(0, U2F_CMD_AUTH, U2F_AUTH_SIGN, (uint16_t)(2 *
345 SHA256_DIGEST_LENGTH + sizeof(key_id_len) + key_id_len))) == NULL ||
346 iso7816_add(apdu, cdh->ptr, cdh->len) < 0 ||
347 iso7816_add(apdu, &rp_id_hash, sizeof(rp_id_hash)) < 0 ||
348 iso7816_add(apdu, &key_id_len, sizeof(key_id_len)) < 0 ||
349 iso7816_add(apdu, key_id->ptr, key_id_len) < 0) {
350 fido_log_debug("%s: iso7816", __func__);
351 r = FIDO_ERR_INTERNAL;
355 if ((reply = malloc(FIDO_MAXMSG)) == NULL) {
356 fido_log_debug("%s: malloc", __func__);
357 r = FIDO_ERR_INTERNAL;
362 if (fido_tx(dev, CTAP_CMD_MSG, iso7816_ptr(apdu),
363 iso7816_len(apdu), ms) < 0) {
364 fido_log_debug("%s: fido_tx", __func__);
368 if ((reply_len = fido_rx(dev, CTAP_CMD_MSG, reply,
369 FIDO_MAXMSG, ms)) < 2) {
370 fido_log_debug("%s: fido_rx", __func__);
374 if (delay_ms(U2F_PACE_MS, ms) != 0) {
375 fido_log_debug("%s: delay_ms", __func__);
379 } while (((reply[0] << 8) | reply[1]) == SW_CONDITIONS_NOT_SATISFIED);
381 if ((r = parse_auth_reply(sig, ad, rp_id, reply,
382 (size_t)reply_len)) != FIDO_OK) {
383 fido_log_debug("%s: parse_auth_reply", __func__);
389 freezero(reply, FIDO_MAXMSG);
395 cbor_blob_from_ec_point(const uint8_t *ec_point, size_t ec_point_len,
396 fido_blob_t *cbor_blob)
398 es256_pk_t *pk = NULL;
399 cbor_item_t *pk_cbor = NULL;
403 /* only handle uncompressed points */
404 if (ec_point_len != 65 || ec_point[0] != 0x04) {
405 fido_log_debug("%s: unexpected format", __func__);
409 if ((pk = es256_pk_new()) == NULL ||
410 es256_pk_set_x(pk, &ec_point[1]) < 0 ||
411 es256_pk_set_y(pk, &ec_point[33]) < 0) {
412 fido_log_debug("%s: es256_pk_set", __func__);
416 if ((pk_cbor = es256_pk_encode(pk, 0)) == NULL) {
417 fido_log_debug("%s: es256_pk_encode", __func__);
421 if ((cbor_blob->len = cbor_serialize_alloc(pk_cbor, &cbor_blob->ptr,
422 &alloc_len)) != 77) {
423 fido_log_debug("%s: cbor_serialize_alloc", __func__);
432 cbor_decref(&pk_cbor);
438 encode_cred_attstmt(int cose_alg, const fido_blob_t *x5c,
439 const fido_blob_t *sig, fido_blob_t *out)
441 cbor_item_t *item = NULL;
442 cbor_item_t *x5c_cbor = NULL;
443 const uint8_t alg_cbor = (uint8_t)(-cose_alg - 1);
444 struct cbor_pair kv[3];
448 memset(&kv, 0, sizeof(kv));
449 memset(out, 0, sizeof(*out));
451 if ((item = cbor_new_definite_map(3)) == NULL) {
452 fido_log_debug("%s: cbor_new_definite_map", __func__);
456 if ((kv[0].key = cbor_build_string("alg")) == NULL ||
457 (kv[0].value = cbor_build_negint8(alg_cbor)) == NULL ||
458 !cbor_map_add(item, kv[0])) {
459 fido_log_debug("%s: alg", __func__);
463 if ((kv[1].key = cbor_build_string("sig")) == NULL ||
464 (kv[1].value = fido_blob_encode(sig)) == NULL ||
465 !cbor_map_add(item, kv[1])) {
466 fido_log_debug("%s: sig", __func__);
470 if ((kv[2].key = cbor_build_string("x5c")) == NULL ||
471 (kv[2].value = cbor_new_definite_array(1)) == NULL ||
472 (x5c_cbor = fido_blob_encode(x5c)) == NULL ||
473 !cbor_array_push(kv[2].value, x5c_cbor) ||
474 !cbor_map_add(item, kv[2])) {
475 fido_log_debug("%s: x5c", __func__);
479 if ((out->len = cbor_serialize_alloc(item, &out->ptr,
481 fido_log_debug("%s: cbor_serialize_alloc", __func__);
489 if (x5c_cbor != NULL)
490 cbor_decref(&x5c_cbor);
492 for (size_t i = 0; i < nitems(kv); i++) {
494 cbor_decref(&kv[i].key);
496 cbor_decref(&kv[i].value);
503 encode_cred_authdata(const char *rp_id, const uint8_t *kh, uint8_t kh_len,
504 const uint8_t *pubkey, size_t pubkey_len, fido_blob_t *out)
506 fido_authdata_t authdata;
507 fido_attcred_raw_t attcred_raw;
509 fido_blob_t authdata_blob;
510 cbor_item_t *authdata_cbor = NULL;
516 memset(&pk_blob, 0, sizeof(pk_blob));
517 memset(&authdata, 0, sizeof(authdata));
518 memset(&authdata_blob, 0, sizeof(authdata_blob));
519 memset(out, 0, sizeof(*out));
522 fido_log_debug("%s: NULL rp_id", __func__);
526 if (cbor_blob_from_ec_point(pubkey, pubkey_len, &pk_blob) < 0) {
527 fido_log_debug("%s: cbor_blob_from_ec_point", __func__);
531 if (SHA256((const void *)rp_id, strlen(rp_id),
532 authdata.rp_id_hash) != authdata.rp_id_hash) {
533 fido_log_debug("%s: sha256", __func__);
537 authdata.flags = (CTAP_AUTHDATA_ATT_CRED | CTAP_AUTHDATA_USER_PRESENT);
538 authdata.sigcount = 0;
540 memset(&attcred_raw.aaguid, 0, sizeof(attcred_raw.aaguid));
541 attcred_raw.id_len = htobe16(kh_len);
543 len = authdata_blob.len = sizeof(authdata) + sizeof(attcred_raw) +
544 kh_len + pk_blob.len;
545 ptr = authdata_blob.ptr = calloc(1, authdata_blob.len);
547 fido_log_debug("%s: ptr=%p, len=%zu", __func__, (void *)ptr, len);
549 if (authdata_blob.ptr == NULL)
552 if (fido_buf_write(&ptr, &len, &authdata, sizeof(authdata)) < 0 ||
553 fido_buf_write(&ptr, &len, &attcred_raw, sizeof(attcred_raw)) < 0 ||
554 fido_buf_write(&ptr, &len, kh, kh_len) < 0 ||
555 fido_buf_write(&ptr, &len, pk_blob.ptr, pk_blob.len) < 0) {
556 fido_log_debug("%s: fido_buf_write", __func__);
560 if ((authdata_cbor = fido_blob_encode(&authdata_blob)) == NULL) {
561 fido_log_debug("%s: fido_blob_encode", __func__);
565 if ((out->len = cbor_serialize_alloc(authdata_cbor, &out->ptr,
567 fido_log_debug("%s: cbor_serialize_alloc", __func__);
574 cbor_decref(&authdata_cbor);
576 fido_blob_reset(&pk_blob);
577 fido_blob_reset(&authdata_blob);
583 parse_register_reply(fido_cred_t *cred, const unsigned char *reply, size_t len)
595 memset(&x5c, 0, sizeof(x5c));
596 memset(&sig, 0, sizeof(sig));
597 memset(&ad, 0, sizeof(ad));
598 memset(&stmt, 0, sizeof(stmt));
602 if (len < 2 || ((reply[len - 2] << 8) | reply[len - 1]) != SW_NO_ERROR) {
603 fido_log_debug("%s: unexpected sw", __func__);
610 if (fido_buf_read(&reply, &len, &dummy, sizeof(dummy)) < 0 ||
612 fido_log_debug("%s: reserved byte", __func__);
616 /* pubkey + key handle */
617 if (fido_buf_read(&reply, &len, &pubkey, sizeof(pubkey)) < 0 ||
618 fido_buf_read(&reply, &len, &kh_len, sizeof(kh_len)) < 0 ||
619 (kh = calloc(1, kh_len)) == NULL ||
620 fido_buf_read(&reply, &len, kh, kh_len) < 0) {
621 fido_log_debug("%s: fido_buf_read", __func__);
626 if (x5c_get(&x5c, &reply, &len) < 0 ||
627 sig_get(&sig, &reply, &len) < 0) {
628 fido_log_debug("%s: x5c || sig", __func__);
633 if (encode_cred_attstmt(COSE_ES256, &x5c, &sig, &stmt) < 0) {
634 fido_log_debug("%s: encode_cred_attstmt", __func__);
639 if (encode_cred_authdata(cred->rp.id, kh, kh_len, pubkey,
640 sizeof(pubkey), &ad) < 0) {
641 fido_log_debug("%s: encode_cred_authdata", __func__);
645 if (fido_cred_set_fmt(cred, "fido-u2f") != FIDO_OK ||
646 fido_cred_set_authdata(cred, ad.ptr, ad.len) != FIDO_OK ||
647 fido_cred_set_attstmt(cred, stmt.ptr, stmt.len) != FIDO_OK) {
648 fido_log_debug("%s: fido_cred_set", __func__);
649 r = FIDO_ERR_INTERNAL;
655 freezero(kh, kh_len);
656 fido_blob_reset(&x5c);
657 fido_blob_reset(&sig);
658 fido_blob_reset(&ad);
659 fido_blob_reset(&stmt);
665 u2f_register(fido_dev_t *dev, fido_cred_t *cred, int *ms)
667 iso7816_apdu_t *apdu = NULL;
668 unsigned char rp_id_hash[SHA256_DIGEST_LENGTH];
669 unsigned char *reply = NULL;
674 if (cred->rk == FIDO_OPT_TRUE || cred->uv == FIDO_OPT_TRUE) {
675 fido_log_debug("%s: rk=%d, uv=%d", __func__, cred->rk,
677 return (FIDO_ERR_UNSUPPORTED_OPTION);
680 if (cred->type != COSE_ES256 || cred->cdh.ptr == NULL ||
681 cred->rp.id == NULL || cred->cdh.len != SHA256_DIGEST_LENGTH) {
682 fido_log_debug("%s: type=%d, cdh=(%p,%zu)" , __func__,
683 cred->type, (void *)cred->cdh.ptr, cred->cdh.len);
684 return (FIDO_ERR_INVALID_ARGUMENT);
687 for (size_t i = 0; i < cred->excl.len; i++) {
688 if ((r = key_lookup(dev, cred->rp.id, &cred->excl.ptr[i],
689 &found, ms)) != FIDO_OK) {
690 fido_log_debug("%s: key_lookup", __func__);
694 if ((r = send_dummy_register(dev, ms)) != FIDO_OK) {
695 fido_log_debug("%s: send_dummy_register",
699 return (FIDO_ERR_CREDENTIAL_EXCLUDED);
703 memset(&rp_id_hash, 0, sizeof(rp_id_hash));
705 if (SHA256((const void *)cred->rp.id, strlen(cred->rp.id),
706 rp_id_hash) != rp_id_hash) {
707 fido_log_debug("%s: sha256", __func__);
708 return (FIDO_ERR_INTERNAL);
711 if ((apdu = iso7816_new(0, U2F_CMD_REGISTER, 0, 2 *
712 SHA256_DIGEST_LENGTH)) == NULL ||
713 iso7816_add(apdu, cred->cdh.ptr, cred->cdh.len) < 0 ||
714 iso7816_add(apdu, rp_id_hash, sizeof(rp_id_hash)) < 0) {
715 fido_log_debug("%s: iso7816", __func__);
716 r = FIDO_ERR_INTERNAL;
720 if ((reply = malloc(FIDO_MAXMSG)) == NULL) {
721 fido_log_debug("%s: malloc", __func__);
722 r = FIDO_ERR_INTERNAL;
727 if (fido_tx(dev, CTAP_CMD_MSG, iso7816_ptr(apdu),
728 iso7816_len(apdu), ms) < 0) {
729 fido_log_debug("%s: fido_tx", __func__);
733 if ((reply_len = fido_rx(dev, CTAP_CMD_MSG, reply,
734 FIDO_MAXMSG, ms)) < 2) {
735 fido_log_debug("%s: fido_rx", __func__);
739 if (delay_ms(U2F_PACE_MS, ms) != 0) {
740 fido_log_debug("%s: delay_ms", __func__);
744 } while (((reply[0] << 8) | reply[1]) == SW_CONDITIONS_NOT_SATISFIED);
746 if ((r = parse_register_reply(cred, reply,
747 (size_t)reply_len)) != FIDO_OK) {
748 fido_log_debug("%s: parse_register_reply", __func__);
753 freezero(reply, FIDO_MAXMSG);
759 u2f_authenticate_single(fido_dev_t *dev, const fido_blob_t *key_id,
760 fido_assert_t *fa, size_t idx, int *ms)
767 memset(&sig, 0, sizeof(sig));
768 memset(&ad, 0, sizeof(ad));
770 if ((r = key_lookup(dev, fa->rp_id, key_id, &found, ms)) != FIDO_OK) {
771 fido_log_debug("%s: key_lookup", __func__);
776 fido_log_debug("%s: not found", __func__);
777 r = FIDO_ERR_CREDENTIAL_EXCLUDED;
781 if (fido_blob_set(&fa->stmt[idx].id, key_id->ptr, key_id->len) < 0) {
782 fido_log_debug("%s: fido_blob_set", __func__);
783 r = FIDO_ERR_INTERNAL;
787 if (fa->up == FIDO_OPT_FALSE) {
788 fido_log_debug("%s: checking for key existence only", __func__);
789 r = FIDO_ERR_USER_PRESENCE_REQUIRED;
793 if ((r = do_auth(dev, &fa->cdh, fa->rp_id, key_id, &sig, &ad,
795 fido_log_debug("%s: do_auth", __func__);
799 if (fido_assert_set_authdata(fa, idx, ad.ptr, ad.len) != FIDO_OK ||
800 fido_assert_set_sig(fa, idx, sig.ptr, sig.len) != FIDO_OK) {
801 fido_log_debug("%s: fido_assert_set", __func__);
802 r = FIDO_ERR_INTERNAL;
808 fido_blob_reset(&sig);
809 fido_blob_reset(&ad);
815 u2f_authenticate(fido_dev_t *dev, fido_assert_t *fa, int *ms)
821 if (fa->uv == FIDO_OPT_TRUE || fa->allow_list.ptr == NULL) {
822 fido_log_debug("%s: uv=%d, allow_list=%p", __func__, fa->uv,
823 (void *)fa->allow_list.ptr);
824 return (FIDO_ERR_UNSUPPORTED_OPTION);
827 if ((r = fido_assert_set_count(fa, fa->allow_list.len)) != FIDO_OK) {
828 fido_log_debug("%s: fido_assert_set_count", __func__);
832 for (size_t i = 0; i < fa->allow_list.len; i++) {
833 switch ((r = u2f_authenticate_single(dev,
834 &fa->allow_list.ptr[i], fa, nfound, ms))) {
838 case FIDO_ERR_USER_PRESENCE_REQUIRED:
842 if (r != FIDO_ERR_CREDENTIAL_EXCLUDED) {
843 fido_log_debug("%s: u2f_authenticate_single",
847 /* ignore credentials that don't exist */
851 fa->stmt_len = nfound;
854 return (FIDO_ERR_NO_CREDENTIALS);
856 return (FIDO_ERR_USER_PRESENCE_REQUIRED);
862 u2f_get_touch_begin(fido_dev_t *dev, int *ms)
864 iso7816_apdu_t *apdu = NULL;
865 const char *clientdata = FIDO_DUMMY_CLIENTDATA;
866 const char *rp_id = FIDO_DUMMY_RP_ID;
867 unsigned char *reply = NULL;
868 unsigned char clientdata_hash[SHA256_DIGEST_LENGTH];
869 unsigned char rp_id_hash[SHA256_DIGEST_LENGTH];
872 memset(&clientdata_hash, 0, sizeof(clientdata_hash));
873 memset(&rp_id_hash, 0, sizeof(rp_id_hash));
875 if (SHA256((const void *)clientdata, strlen(clientdata),
876 clientdata_hash) != clientdata_hash || SHA256((const void *)rp_id,
877 strlen(rp_id), rp_id_hash) != rp_id_hash) {
878 fido_log_debug("%s: sha256", __func__);
879 return (FIDO_ERR_INTERNAL);
882 if ((apdu = iso7816_new(0, U2F_CMD_REGISTER, 0, 2 *
883 SHA256_DIGEST_LENGTH)) == NULL ||
884 iso7816_add(apdu, clientdata_hash, sizeof(clientdata_hash)) < 0 ||
885 iso7816_add(apdu, rp_id_hash, sizeof(rp_id_hash)) < 0) {
886 fido_log_debug("%s: iso7816", __func__);
887 r = FIDO_ERR_INTERNAL;
891 if ((reply = malloc(FIDO_MAXMSG)) == NULL) {
892 fido_log_debug("%s: malloc", __func__);
893 r = FIDO_ERR_INTERNAL;
897 if (dev->attr.flags & FIDO_CAP_WINK) {
898 fido_tx(dev, CTAP_CMD_WINK, NULL, 0, ms);
899 fido_rx(dev, CTAP_CMD_WINK, reply, FIDO_MAXMSG, ms);
902 if (fido_tx(dev, CTAP_CMD_MSG, iso7816_ptr(apdu),
903 iso7816_len(apdu), ms) < 0) {
904 fido_log_debug("%s: fido_tx", __func__);
912 freezero(reply, FIDO_MAXMSG);
918 u2f_get_touch_status(fido_dev_t *dev, int *touched, int *ms)
920 unsigned char *reply;
924 if ((reply = malloc(FIDO_MAXMSG)) == NULL) {
925 fido_log_debug("%s: malloc", __func__);
926 r = FIDO_ERR_INTERNAL;
930 if ((reply_len = fido_rx(dev, CTAP_CMD_MSG, reply, FIDO_MAXMSG,
932 fido_log_debug("%s: fido_rx", __func__);
933 r = FIDO_OK; /* ignore */
937 switch ((reply[reply_len - 2] << 8) | reply[reply_len - 1]) {
938 case SW_CONDITIONS_NOT_SATISFIED:
939 if ((r = u2f_get_touch_begin(dev, ms)) != FIDO_OK) {
940 fido_log_debug("%s: u2f_get_touch_begin", __func__);
949 fido_log_debug("%s: unexpected sw", __func__);
956 freezero(reply, FIDO_MAXMSG);