diff --git a/man/CMakeLists.txt b/man/CMakeLists.txt new file mode 100644 index 0000000..e83a9d7 --- /dev/null +++ b/man/CMakeLists.txt @@ -0,0 +1,417 @@ +# Copyright (c) 2018-2022 Yubico AB. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. +# SPDX-License-Identifier: BSD-2-Clause + +find_program(MANDOC_PATH mandoc) +find_program(GZIP_PATH gzip) + +message(STATUS "MANDOC_PATH: ${MANDOC_PATH}") +message(STATUS "GZIP_PATH: ${GZIP_PATH}") + +list(APPEND MAN_SOURCES + eddsa_pk_new.3 + es256_pk_new.3 + es384_pk_new.3 + fido2-assert.1 + fido2-cred.1 + fido2-token.1 + fido_init.3 + fido_assert_new.3 + fido_assert_allow_cred.3 + fido_assert_set_authdata.3 + fido_assert_verify.3 + fido_bio_dev_get_info.3 + fido_bio_enroll_new.3 + fido_bio_info_new.3 + fido_bio_template.3 + fido_cbor_info_new.3 + fido_cred_new.3 + fido_cred_exclude.3 + fido_credman_metadata_new.3 + fido_cred_set_authdata.3 + fido_cred_verify.3 + fido_dev_enable_entattest.3 + fido_dev_get_assert.3 + fido_dev_get_touch_begin.3 + fido_dev_info_manifest.3 + fido_dev_largeblob_get.3 + fido_dev_make_cred.3 + fido_dev_open.3 + fido_dev_set_io_functions.3 + fido_dev_set_pin.3 + fido_strerr.3 + rs256_pk_new.3 +) + +list(APPEND MAN_ALIAS + eddsa_pk_new eddsa_pk_free + eddsa_pk_new eddsa_pk_from_EVP_PKEY + eddsa_pk_new eddsa_pk_from_ptr + eddsa_pk_new eddsa_pk_to_EVP_PKEY + es256_pk_new es256_pk_free + es256_pk_new es256_pk_from_EC_KEY + es256_pk_new es256_pk_from_EVP_PKEY + es256_pk_new es256_pk_from_ptr + es256_pk_new es256_pk_to_EVP_PKEY + es384_pk_new es384_pk_free + es384_pk_new es384_pk_from_EC_KEY + es384_pk_new es384_pk_from_EVP_PKEY + es384_pk_new es384_pk_from_ptr + es384_pk_new es384_pk_to_EVP_PKEY + fido_assert_allow_cred fido_assert_empty_allow_list + fido_assert_new fido_assert_authdata_len + fido_assert_new fido_assert_authdata_ptr + fido_assert_new fido_assert_authdata_raw_len + fido_assert_new fido_assert_authdata_raw_ptr + fido_assert_new fido_assert_blob_len + fido_assert_new fido_assert_blob_ptr + fido_assert_new fido_assert_clientdata_hash_len + fido_assert_new fido_assert_clientdata_hash_ptr + fido_assert_new fido_assert_count + fido_assert_new fido_assert_flags + fido_assert_new fido_assert_free + fido_assert_new fido_assert_hmac_secret_len + fido_assert_new fido_assert_hmac_secret_ptr + fido_assert_new fido_assert_id_len + fido_assert_new fido_assert_id_ptr + fido_assert_new fido_assert_largeblob_key_len + fido_assert_new fido_assert_largeblob_key_ptr + fido_assert_new fido_assert_rp_id + fido_assert_new fido_assert_sigcount + fido_assert_new fido_assert_sig_len + fido_assert_new fido_assert_sig_ptr + fido_assert_new fido_assert_user_display_name + fido_assert_new fido_assert_user_icon + fido_assert_new fido_assert_user_id_len + fido_assert_new fido_assert_user_id_ptr + fido_assert_new fido_assert_user_name + fido_assert_set_authdata fido_assert_set_authdata_raw + fido_assert_set_authdata fido_assert_set_clientdata + fido_assert_set_authdata fido_assert_set_clientdata_hash + fido_assert_set_authdata fido_assert_set_count + fido_assert_set_authdata fido_assert_set_extensions + fido_assert_set_authdata fido_assert_set_hmac_salt + fido_assert_set_authdata fido_assert_set_hmac_secret + fido_assert_set_authdata fido_assert_set_rp + fido_assert_set_authdata fido_assert_set_sig + fido_assert_set_authdata fido_assert_set_up + fido_assert_set_authdata fido_assert_set_uv + fido_assert_set_authdata fido_assert_set_winhello_appid + fido_bio_dev_get_info fido_bio_dev_enroll_begin + fido_bio_dev_get_info fido_bio_dev_enroll_cancel + fido_bio_dev_get_info fido_bio_dev_enroll_continue + fido_bio_dev_get_info fido_bio_dev_enroll_remove + fido_bio_dev_get_info fido_bio_dev_get_template_array + fido_bio_dev_get_info fido_bio_dev_set_template_name + fido_bio_enroll_new fido_bio_enroll_free + fido_bio_enroll_new fido_bio_enroll_last_status + fido_bio_enroll_new fido_bio_enroll_remaining_samples + fido_bio_info_new fido_bio_info_free + fido_bio_info_new fido_bio_info_max_samples + fido_bio_info_new fido_bio_info_type + fido_bio_template fido_bio_template_array_count + fido_bio_template fido_bio_template_array_free + fido_bio_template fido_bio_template_array_new + fido_bio_template fido_bio_template_free + fido_bio_template fido_bio_template_id_len + fido_bio_template fido_bio_template_id_ptr + fido_bio_template fido_bio_template_name + fido_bio_template fido_bio_template_new + fido_bio_template fido_bio_template_set_id + fido_bio_template fido_bio_template_set_name + fido_cbor_info_new fido_cbor_info_aaguid_len + fido_cbor_info_new fido_cbor_info_aaguid_ptr + fido_cbor_info_new fido_cbor_info_algorithm_cose + fido_cbor_info_new fido_cbor_info_algorithm_count + fido_cbor_info_new fido_cbor_info_algorithm_type + fido_cbor_info_new fido_cbor_info_certs_len + fido_cbor_info_new fido_cbor_info_certs_name_ptr + fido_cbor_info_new fido_cbor_info_certs_value_ptr + fido_cbor_info_new fido_cbor_info_extensions_len + fido_cbor_info_new fido_cbor_info_extensions_ptr + fido_cbor_info_new fido_cbor_info_free + fido_cbor_info_new fido_cbor_info_fwversion + fido_cbor_info_new fido_cbor_info_maxcredbloblen + fido_cbor_info_new fido_cbor_info_maxcredcntlst + fido_cbor_info_new fido_cbor_info_maxcredidlen + fido_cbor_info_new fido_cbor_info_maxlargeblob + fido_cbor_info_new fido_cbor_info_maxmsgsiz + fido_cbor_info_new fido_cbor_info_maxrpid_minpinlen + fido_cbor_info_new fido_cbor_info_minpinlen + fido_cbor_info_new fido_cbor_info_new_pin_required + fido_cbor_info_new fido_cbor_info_options_len + fido_cbor_info_new fido_cbor_info_options_name_ptr + fido_cbor_info_new fido_cbor_info_options_value_ptr + fido_cbor_info_new fido_cbor_info_protocols_len + fido_cbor_info_new fido_cbor_info_protocols_ptr + fido_cbor_info_new fido_cbor_info_rk_remaining + fido_cbor_info_new fido_cbor_info_transports_len + fido_cbor_info_new fido_cbor_info_transports_ptr + fido_cbor_info_new fido_cbor_info_uv_attempts + fido_cbor_info_new fido_cbor_info_uv_modality + fido_cbor_info_new fido_cbor_info_versions_len + fido_cbor_info_new fido_cbor_info_versions_ptr + fido_cbor_info_new fido_dev_get_cbor_info + fido_cred_exclude fido_cred_empty_exclude_list + fido_cred_new fido_cred_aaguid_len + fido_cred_new fido_cred_aaguid_ptr + fido_cred_new fido_cred_attstmt_len + fido_cred_new fido_cred_attstmt_ptr + fido_cred_new fido_cred_authdata_len + fido_cred_new fido_cred_authdata_ptr + fido_cred_new fido_cred_authdata_raw_len + fido_cred_new fido_cred_authdata_raw_ptr + fido_cred_new fido_cred_clientdata_hash_len + fido_cred_new fido_cred_clientdata_hash_ptr + fido_cred_new fido_cred_display_name + fido_cred_new fido_cred_flags + fido_cred_new fido_cred_fmt + fido_cred_new fido_cred_free + fido_cred_new fido_cred_id_len + fido_cred_new fido_cred_id_ptr + fido_cred_new fido_cred_largeblob_key_len + fido_cred_new fido_cred_largeblob_key_ptr + fido_cred_new fido_cred_pin_minlen + fido_cred_new fido_cred_prot + fido_cred_new fido_cred_pubkey_len + fido_cred_new fido_cred_pubkey_ptr + fido_cred_new fido_cred_rp_id + fido_cred_new fido_cred_rp_name + fido_cred_new fido_cred_sigcount + fido_cred_new fido_cred_sig_len + fido_cred_new fido_cred_sig_ptr + fido_cred_new fido_cred_type + fido_cred_new fido_cred_user_id_len + fido_cred_new fido_cred_user_id_ptr + fido_cred_new fido_cred_user_name + fido_cred_new fido_cred_x5c_len + fido_cred_new fido_cred_x5c_list_count + fido_cred_new fido_cred_x5c_list_len + fido_cred_new fido_cred_x5c_list_ptr + fido_cred_new fido_cred_x5c_ptr + fido_cred_verify fido_cred_verify_self + fido_credman_metadata_new fido_credman_del_dev_rk + fido_credman_metadata_new fido_credman_get_dev_metadata + fido_credman_metadata_new fido_credman_get_dev_rk + fido_credman_metadata_new fido_credman_get_dev_rp + fido_credman_metadata_new fido_credman_metadata_free + fido_credman_metadata_new fido_credman_rk + fido_credman_metadata_new fido_credman_rk_count + fido_credman_metadata_new fido_credman_rk_existing + fido_credman_metadata_new fido_credman_rk_free + fido_credman_metadata_new fido_credman_rk_new + fido_credman_metadata_new fido_credman_rk_remaining + fido_credman_metadata_new fido_credman_rp_count + fido_credman_metadata_new fido_credman_rp_free + fido_credman_metadata_new fido_credman_rp_id + fido_credman_metadata_new fido_credman_rp_id_hash_len + fido_credman_metadata_new fido_credman_rp_id_hash_ptr + fido_credman_metadata_new fido_credman_rp_name + fido_credman_metadata_new fido_credman_rp_new + fido_credman_metadata_new fido_credman_set_dev_rk + fido_cred_set_authdata fido_cred_set_attstmt + fido_cred_set_authdata fido_cred_set_attobj + fido_cred_set_authdata fido_cred_set_authdata_raw + fido_cred_set_authdata fido_cred_set_blob + fido_cred_set_authdata fido_cred_set_clientdata + fido_cred_set_authdata fido_cred_set_clientdata_hash + fido_cred_set_authdata fido_cred_set_extensions + fido_cred_set_authdata fido_cred_set_fmt + fido_cred_set_authdata fido_cred_set_id + fido_cred_set_authdata fido_cred_set_pin_minlen + fido_cred_set_authdata fido_cred_set_prot + fido_cred_set_authdata fido_cred_set_rk + fido_cred_set_authdata fido_cred_set_rp + fido_cred_set_authdata fido_cred_set_sig + fido_cred_set_authdata fido_cred_set_type + fido_cred_set_authdata fido_cred_set_user + fido_cred_set_authdata fido_cred_set_uv + fido_cred_set_authdata fido_cred_set_x509 + fido_dev_enable_entattest fido_dev_toggle_always_uv + fido_dev_enable_entattest fido_dev_force_pin_change + fido_dev_enable_entattest fido_dev_set_pin_minlen + fido_dev_enable_entattest fido_dev_set_pin_minlen_rpid + fido_dev_get_touch_begin fido_dev_get_touch_status + fido_dev_info_manifest fido_dev_info_free + fido_dev_info_manifest fido_dev_info_manufacturer_string + fido_dev_info_manifest fido_dev_info_new + fido_dev_info_manifest fido_dev_info_path + fido_dev_info_manifest fido_dev_info_product + fido_dev_info_manifest fido_dev_info_product_string + fido_dev_info_manifest fido_dev_info_ptr + fido_dev_info_manifest fido_dev_info_set + fido_dev_info_manifest fido_dev_info_vendor + fido_dev_open fido_dev_build + fido_dev_open fido_dev_cancel + fido_dev_open fido_dev_close + fido_dev_open fido_dev_flags + fido_dev_open fido_dev_force_fido2 + fido_dev_open fido_dev_force_u2f + fido_dev_open fido_dev_free + fido_dev_open fido_dev_has_pin + fido_dev_open fido_dev_has_uv + fido_dev_open fido_dev_is_fido2 + fido_dev_open fido_dev_is_winhello + fido_dev_open fido_dev_major + fido_dev_open fido_dev_minor + fido_dev_open fido_dev_new + fido_dev_open fido_dev_new_with_info + fido_dev_open fido_dev_open_with_info + fido_dev_open fido_dev_protocol + fido_dev_open fido_dev_supports_cred_prot + fido_dev_open fido_dev_supports_credman + fido_dev_open fido_dev_supports_permissions + fido_dev_open fido_dev_supports_pin + fido_dev_open fido_dev_supports_uv + fido_dev_set_pin fido_dev_get_retry_count + fido_dev_set_pin fido_dev_get_uv_retry_count + fido_dev_set_pin fido_dev_reset + fido_dev_set_io_functions fido_dev_io_handle + fido_dev_set_io_functions fido_dev_set_sigmask + fido_dev_set_io_functions fido_dev_set_timeout + fido_dev_set_io_functions fido_dev_set_transport_functions + fido_dev_largeblob_get fido_dev_largeblob_set + fido_dev_largeblob_get fido_dev_largeblob_remove + fido_dev_largeblob_get fido_dev_largeblob_get_array + fido_dev_largeblob_get fido_dev_largeblob_set_array + fido_init fido_set_log_handler + rs256_pk_new rs256_pk_free + rs256_pk_new rs256_pk_from_ptr + rs256_pk_new rs256_pk_from_EVP_PKEY + rs256_pk_new rs256_pk_from_RSA + rs256_pk_new rs256_pk_to_EVP_PKEY +) + +list(LENGTH MAN_ALIAS MAN_ALIAS_LEN) +math(EXPR MAN_ALIAS_MAX "${MAN_ALIAS_LEN} - 2") + +# man_copy +foreach(f ${MAN_SOURCES}) + add_custom_command(OUTPUT ${f} + COMMAND cp -f ${PROJECT_SOURCE_DIR}/man/${f} . + DEPENDS ${f}) + list(APPEND COPY_FILES ${f}) +endforeach() + +# man_lint +foreach(f ${MAN_SOURCES}) + add_custom_command(OUTPUT ${f}.lint + COMMAND mandoc -T lint -W warning ${f} > ${f}.lint + DEPENDS ${f}) + list(APPEND LINT_FILES ${f}.lint) +endforeach() + +# man_html +foreach(f ${MAN_SOURCES}) + string(REGEX REPLACE "\\.[13]$" "" g ${f}) + add_custom_command(OUTPUT ${g}.html + COMMAND mandoc -T html -O man="%N.html",style=style.css -I os="Yubico AB" ${f} > ${g}.html + DEPENDS ${f}) + list(APPEND HTML_FILES ${g}.html) +endforeach() + +# man_html_partial +foreach(f ${MAN_SOURCES}) + string(REGEX REPLACE "\\.[13]$" "" g ${f}) + add_custom_command(OUTPUT ${g}.partial + COMMAND cat ${PROJECT_SOURCE_DIR}/man/dyc.css > ${g}.partial + COMMAND mandoc -T html -O man="%N.html",fragment ${f} >> ${g}.partial + DEPENDS ${f}) + list(APPEND HTML_PARTIAL_FILES ${g}.partial) +endforeach() + +# man_gzip +foreach(f ${MAN_SOURCES}) + add_custom_command(OUTPUT ${f}.gz + COMMAND gzip -cn ${f} > ${f}.gz + DEPENDS ${f}) + list(APPEND GZ_FILES ${f}.gz) +endforeach() + +macro(define_symlink_target NAME EXT) + foreach(i RANGE 0 ${MAN_ALIAS_MAX} 2) + math(EXPR j "${i} + 1") + list(GET MAN_ALIAS ${i} SRC) + list(GET MAN_ALIAS ${j} DST) + add_custom_command(OUTPUT ${DST}.${EXT} + COMMAND ln -sf ${SRC}.${EXT} ${DST}.${EXT}) + list(APPEND ${NAME}_LINK_FILES ${DST}.${EXT}) + endforeach() + add_custom_target(${NAME} DEPENDS ${${NAME}_LINK_FILES}) +endmacro() + +add_custom_target(man_copy DEPENDS ${COPY_FILES}) +add_custom_target(man_lint DEPENDS ${LINT_FILES}) +add_custom_target(man_html DEPENDS ${HTML_FILES}) +add_custom_target(man_html_partial DEPENDS ${HTML_PARTIAL_FILES}) +add_custom_target(man_gzip DEPENDS ${GZ_FILES}) + +define_symlink_target(man_symlink 3) +define_symlink_target(man_symlink_html html) +define_symlink_target(man_symlink_html_partial partial) +define_symlink_target(man_symlink_gzip 3.gz) + +add_dependencies(man_symlink man_copy) +add_dependencies(man_lint man_symlink) +add_dependencies(man_html man_lint) +add_dependencies(man_symlink_html man_html) +add_dependencies(man_html_partial man_lint) +add_dependencies(man_symlink_html_partial man_html_partial) +add_custom_target(man ALL) + +if(MANDOC_PATH) + add_dependencies(man man_symlink_html) + add_dependencies(man_gzip man_lint) + install(FILES ${PROJECT_SOURCE_DIR}/man/style.css + DESTINATION "${CMAKE_INSTALL_DOCDIR}/html") + foreach(f ${MAN_SOURCES}) + string(REGEX REPLACE "\\.[13]$" "" f ${f}) + install(FILES ${PROJECT_BINARY_DIR}/man/${f}.html + DESTINATION "${CMAKE_INSTALL_DOCDIR}/html") + endforeach() + foreach(i RANGE 0 ${MAN_ALIAS_MAX} 2) + math(EXPR j "${i} + 1") + list(GET MAN_ALIAS ${j} DST) + install(FILES ${PROJECT_BINARY_DIR}/man/${DST}.html + DESTINATION "${CMAKE_INSTALL_DOCDIR}/html") + endforeach() +endif() + +if(GZIP_PATH) + add_dependencies(man_gzip man_copy) + add_dependencies(man_symlink_gzip man_gzip) + add_dependencies(man man_symlink_gzip) + foreach(f ${MAN_SOURCES}) + if (${f} MATCHES ".1$") + install(FILES ${PROJECT_BINARY_DIR}/man/${f}.gz + DESTINATION "${CMAKE_INSTALL_MANDIR}/man1") + elseif(${f} MATCHES ".3$") + install(FILES ${PROJECT_BINARY_DIR}/man/${f}.gz + DESTINATION "${CMAKE_INSTALL_MANDIR}/man3") + endif() + endforeach() + foreach(i RANGE 0 ${MAN_ALIAS_MAX} 2) + math(EXPR j "${i} + 1") + list(GET MAN_ALIAS ${j} DST) + install(FILES ${PROJECT_BINARY_DIR}/man/${DST}.3.gz + DESTINATION "${CMAKE_INSTALL_MANDIR}/man3") + endforeach() +else() + add_dependencies(man man_symlink) + foreach(f ${MAN_SOURCES}) + if (${f} MATCHES ".1$") + install(FILES ${PROJECT_BINARY_DIR}/man/${f} + DESTINATION "${CMAKE_INSTALL_MANDIR}/man1") + elseif(${f} MATCHES ".3$") + install(FILES ${PROJECT_BINARY_DIR}/man/${f} + DESTINATION "${CMAKE_INSTALL_MANDIR}/man3") + endif() + endforeach() + foreach(i RANGE 0 ${MAN_ALIAS_MAX} 2) + math(EXPR j "${i} + 1") + list(GET MAN_ALIAS ${j} DST) + install(FILES ${PROJECT_BINARY_DIR}/man/${DST}.3 + DESTINATION "${CMAKE_INSTALL_MANDIR}/man3") + endforeach() +endif() diff --git a/man/NOTES b/man/NOTES new file mode 100644 index 0000000..5cba436 --- /dev/null +++ b/man/NOTES @@ -0,0 +1,7 @@ +To generate .partial files for https://developers.yubico.com/: + +$ make -C build man_symlink_html_partial +$ (cd build/man && pax -p p -r -w *.partial /tmp/partial) + +Use mandoc 1.14.4. Otherwise, adjust dyc.css to mandoc's HTML +output. diff --git a/man/check.sh b/man/check.sh new file mode 100644 index 0000000..d969a7a --- /dev/null +++ b/man/check.sh @@ -0,0 +1,43 @@ +#!/bin/sh -u + +# Copyright (c) 2022 Yubico AB. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. +# SPDX-License-Identifier: BSD-2-Clause + +T=$(mktemp -d) || exit 1 +find . -maxdepth 1 -type f -name '*.3' -print0 > "$T/files" + +xargs -0 awk '/^.Sh NAME/,/^.Nd/' < "$T/files" | \ + awk '/^.Nm/ { print $2 }' | sort -u > "$T/Nm" +xargs -0 awk '/^.Fn/ { print $2 }' < "$T/files" | sort -u > "$T/Fn" +(cd "$T" && diff -u Nm Fn) + +cut -c2- ../src/export.llvm | sort > "$T/exports" +(cd "$T" && diff -u Nm exports) + +awk '/^list\(APPEND MAN_SOURCES/,/^\)/' CMakeLists.txt | \ + awk '/.3$/ { print $1 }' | sort > "$T/listed_sources" +xargs -0 -n1 basename < "$T/files" | sort > "$T/actual_sources" +(cd "$T" && diff -u listed_sources actual_sources) + +awk '/^list\(APPEND MAN_ALIAS/,/^\)/' CMakeLists.txt | \ + sed '1d;$d' | awk '{ print $1, $2 }' | sort > "$T/listed_aliases" +xargs -0 grep -o "^.Fn [A-Za-z0-9_]* \"" < "$T/files" | \ + cut -c3- | sed 's/\.3:\.Fn//;s/ "//' | awk '$1 != $2' | \ + sort > "$T/actual_aliases" +(cd "$T" && diff -u listed_aliases actual_aliases) + +xargs -0 grep -hB1 "^.Fn [A-Za-z0-9_]* \"" < "$T/files" | \ + sed -E 's/^.F[tn] //;s/\*[^"\*]+"/\*"/g;s/ [^" \*]+"/"/g;/^--$/d' | \ + paste -d " " - - | sed 's/\* /\*/' | sort > "$T/documented_prototypes" +while read -r f; do + awk "/\/\*/ { next } /$f\(/,/;/" ../src/fido.h ../src/fido/*.h | \ + sed -E 's/^[ ]+//;s/[ ]+/ /' | tr '\n' ' ' | \ + sed 's/(/ "/;s/, /" "/g;s/);/"/;s/ $/\n/' +done < "$T/exports" | sort > "$T/actual_prototypes" +(cd "$T" && diff -u documented_prototypes actual_prototypes) + +(cd "$T" && rm files Nm Fn exports listed_sources actual_sources \ + listed_aliases actual_aliases documented_prototypes actual_prototypes) +rmdir -- "$T" diff --git a/man/dyc.css b/man/dyc.css new file mode 100644 index 0000000..1ff5b59 --- /dev/null +++ b/man/dyc.css @@ -0,0 +1,14 @@ + diff --git a/man/eddsa_pk_new.3 b/man/eddsa_pk_new.3 new file mode 100644 index 0000000..428d724 --- /dev/null +++ b/man/eddsa_pk_new.3 @@ -0,0 +1,146 @@ +.\" Copyright (c) 2019-2022 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: July 15 2022 $ +.Dt EDDSA_PK_NEW 3 +.Os +.Sh NAME +.Nm eddsa_pk_new , +.Nm eddsa_pk_free , +.Nm eddsa_pk_from_EVP_PKEY , +.Nm eddsa_pk_from_ptr , +.Nm eddsa_pk_to_EVP_PKEY +.Nd FIDO2 COSE EDDSA API +.Sh SYNOPSIS +.In openssl/evp.h +.In fido/eddsa.h +.Ft eddsa_pk_t * +.Fn eddsa_pk_new "void" +.Ft void +.Fn eddsa_pk_free "eddsa_pk_t **pkp" +.Ft int +.Fn eddsa_pk_from_EVP_PKEY "eddsa_pk_t *pk" "const EVP_PKEY *pkey" +.Ft int +.Fn eddsa_pk_from_ptr "eddsa_pk_t *pk" "const void *ptr" "size_t len" +.Ft EVP_PKEY * +.Fn eddsa_pk_to_EVP_PKEY "const eddsa_pk_t *pk" +.Sh DESCRIPTION +EDDSA is the name given in the CBOR Object Signing and Encryption +(COSE) RFC to EDDSA over Curve25519 with SHA-512. +The COSE EDDSA API of +.Em libfido2 +is an auxiliary API with routines to convert between the different +EDDSA public key types used in +.Em libfido2 +and +.Em OpenSSL . +.Pp +In +.Em libfido2 , +EDDSA public keys are abstracted by the +.Vt eddsa_pk_t +type. +.Pp +The +.Fn eddsa_pk_new +function returns a pointer to a newly allocated, empty +.Vt eddsa_pk_t +type. +If memory cannot be allocated, NULL is returned. +.Pp +The +.Fn eddsa_pk_free +function releases the memory backing +.Fa *pkp , +where +.Fa *pkp +must have been previously allocated by +.Fn eddsa_pk_new . +On return, +.Fa *pkp +is set to NULL. +Either +.Fa pkp +or +.Fa *pkp +may be NULL, in which case +.Fn eddsa_pk_free +is a NOP. +.Pp +The +.Fn eddsa_pk_from_EVP_PKEY +function fills +.Fa pk +with the contents of +.Fa pkey . +No references to +.Fa pkey +are kept. +.Pp +The +.Fn eddsa_pk_from_ptr +function fills +.Fa pk +with the contents of +.Fa ptr , +where +.Fa ptr +points to +.Fa len +bytes. +No references to +.Fa ptr +are kept. +.Pp +The +.Fn eddsa_pk_to_EVP_PKEY +function converts +.Fa pk +to a newly allocated +.Fa EVP_PKEY +type with a reference count of 1. +No internal references to the returned pointer are kept. +If an error occurs, +.Fn eddsa_pk_to_EVP_PKEY +returns NULL. +.Sh RETURN VALUES +The +.Fn eddsa_pk_from_EVP_PKEY +and +.Fn eddsa_pk_from_ptr +functions return +.Dv FIDO_OK +on success. +On error, a different error code defined in +.In fido/err.h +is returned. +.Sh SEE ALSO +.Xr es256_pk_new 3 , +.Xr es384_pk_new 3 , +.Xr fido_assert_verify 3 , +.Xr fido_cred_pubkey_ptr 3 , +.Xr rs256_pk_new 3 diff --git a/man/es256_pk_new.3 b/man/es256_pk_new.3 new file mode 100644 index 0000000..7d6be4d --- /dev/null +++ b/man/es256_pk_new.3 @@ -0,0 +1,164 @@ +.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: July 15 2022 $ +.Dt ES256_PK_NEW 3 +.Os +.Sh NAME +.Nm es256_pk_new , +.Nm es256_pk_free , +.Nm es256_pk_from_EC_KEY , +.Nm es256_pk_from_EVP_PKEY , +.Nm es256_pk_from_ptr , +.Nm es256_pk_to_EVP_PKEY +.Nd FIDO2 COSE ES256 API +.Sh SYNOPSIS +.In openssl/ec.h +.In fido/es256.h +.Ft es256_pk_t * +.Fn es256_pk_new "void" +.Ft void +.Fn es256_pk_free "es256_pk_t **pkp" +.Ft int +.Fn es256_pk_from_EC_KEY "es256_pk_t *pk" "const EC_KEY *ec" +.Ft int +.Fn es256_pk_from_EVP_PKEY "es256_pk_t *pk" "const EVP_PKEY *pkey" +.Ft int +.Fn es256_pk_from_ptr "es256_pk_t *pk" "const void *ptr" "size_t len" +.Ft EVP_PKEY * +.Fn es256_pk_to_EVP_PKEY "const es256_pk_t *pk" +.Sh DESCRIPTION +ES256 is the name given in the CBOR Object Signing and Encryption +(COSE) RFC to ECDSA over P-256 with SHA-256. +The COSE ES256 API of +.Em libfido2 +is an auxiliary API with routines to convert between the different +ECDSA public key types used in +.Em libfido2 +and +.Em OpenSSL . +.Pp +In +.Em libfido2 , +ES256 public keys are abstracted by the +.Vt es256_pk_t +type. +.Pp +The +.Fn es256_pk_new +function returns a pointer to a newly allocated, empty +.Vt es256_pk_t +type. +If memory cannot be allocated, NULL is returned. +.Pp +The +.Fn es256_pk_free +function releases the memory backing +.Fa *pkp , +where +.Fa *pkp +must have been previously allocated by +.Fn es256_pk_new . +On return, +.Fa *pkp +is set to NULL. +Either +.Fa pkp +or +.Fa *pkp +may be NULL, in which case +.Fn es256_pk_free +is a NOP. +.Pp +The +.Fn es256_pk_from_EC_KEY +function fills +.Fa pk +with the contents of +.Fa ec . +No references to +.Fa ec +are kept. +.Pp +The +.Fn es256_pk_from_EVP_PKEY +function fills +.Fa pk +with the contents of +.Fa pkey . +No references to +.Fa pkey +are kept. +.Pp +The +.Fn es256_pk_from_ptr +function fills +.Fa pk +with the contents of +.Fa ptr , +where +.Fa ptr +points to +.Fa len +bytes. +The +.Fa ptr +pointer may point to an uncompressed point, or to the +concatenation of the x and y coordinates. +No references to +.Fa ptr +are kept. +.Pp +The +.Fn es256_pk_to_EVP_PKEY +function converts +.Fa pk +to a newly allocated +.Fa EVP_PKEY +type with a reference count of 1. +No internal references to the returned pointer are kept. +If an error occurs, +.Fn es256_pk_to_EVP_PKEY +returns NULL. +.Sh RETURN VALUES +The +.Fn es256_pk_from_EC_KEY , +.Fn es256_pk_from_EVP_PKEY , +and +.Fn es256_pk_from_ptr +functions return +.Dv FIDO_OK +on success. +On error, a different error code defined in +.In fido/err.h +is returned. +.Sh SEE ALSO +.Xr eddsa_pk_new 3 , +.Xr es384_pk_new 3 , +.Xr fido_assert_verify 3 , +.Xr fido_cred_pubkey_ptr 3 , +.Xr rs256_pk_new 3 diff --git a/man/es384_pk_new.3 b/man/es384_pk_new.3 new file mode 100644 index 0000000..e865913 --- /dev/null +++ b/man/es384_pk_new.3 @@ -0,0 +1,164 @@ +.\" Copyright (c) 2022 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: July 15 2022 $ +.Dt ES384_PK_NEW 3 +.Os +.Sh NAME +.Nm es384_pk_new , +.Nm es384_pk_free , +.Nm es384_pk_from_EC_KEY , +.Nm es384_pk_from_EVP_PKEY , +.Nm es384_pk_from_ptr , +.Nm es384_pk_to_EVP_PKEY +.Nd FIDO2 COSE ES384 API +.Sh SYNOPSIS +.In openssl/ec.h +.In fido/es384.h +.Ft es384_pk_t * +.Fn es384_pk_new "void" +.Ft void +.Fn es384_pk_free "es384_pk_t **pkp" +.Ft int +.Fn es384_pk_from_EC_KEY "es384_pk_t *pk" "const EC_KEY *ec" +.Ft int +.Fn es384_pk_from_EVP_PKEY "es384_pk_t *pk" "const EVP_PKEY *pkey" +.Ft int +.Fn es384_pk_from_ptr "es384_pk_t *pk" "const void *ptr" "size_t len" +.Ft EVP_PKEY * +.Fn es384_pk_to_EVP_PKEY "const es384_pk_t *pk" +.Sh DESCRIPTION +ES384 is the name given in the CBOR Object Signing and Encryption +(COSE) RFC to ECDSA over P-384 with SHA-384. +The COSE ES384 API of +.Em libfido2 +is an auxiliary API with routines to convert between the different +ECDSA public key types used in +.Em libfido2 +and +.Em OpenSSL . +.Pp +In +.Em libfido2 , +ES384 public keys are abstracted by the +.Vt es384_pk_t +type. +.Pp +The +.Fn es384_pk_new +function returns a pointer to a newly allocated, empty +.Vt es384_pk_t +type. +If memory cannot be allocated, NULL is returned. +.Pp +The +.Fn es384_pk_free +function releases the memory backing +.Fa *pkp , +where +.Fa *pkp +must have been previously allocated by +.Fn es384_pk_new . +On return, +.Fa *pkp +is set to NULL. +Either +.Fa pkp +or +.Fa *pkp +may be NULL, in which case +.Fn es384_pk_free +is a NOP. +.Pp +The +.Fn es384_pk_from_EC_KEY +function fills +.Fa pk +with the contents of +.Fa ec . +No references to +.Fa ec +are kept. +.Pp +The +.Fn es384_pk_from_EVP_PKEY +function fills +.Fa pk +with the contents of +.Fa pkey . +No references to +.Fa pkey +are kept. +.Pp +The +.Fn es384_pk_from_ptr +function fills +.Fa pk +with the contents of +.Fa ptr , +where +.Fa ptr +points to +.Fa len +bytes. +The +.Fa ptr +pointer may point to an uncompressed point, or to the +concatenation of the x and y coordinates. +No references to +.Fa ptr +are kept. +.Pp +The +.Fn es384_pk_to_EVP_PKEY +function converts +.Fa pk +to a newly allocated +.Fa EVP_PKEY +type with a reference count of 1. +No internal references to the returned pointer are kept. +If an error occurs, +.Fn es384_pk_to_EVP_PKEY +returns NULL. +.Sh RETURN VALUES +The +.Fn es384_pk_from_EC_KEY , +.Fn es384_pk_from_EVP_PKEY , +and +.Fn es384_pk_from_ptr +functions return +.Dv FIDO_OK +on success. +On error, a different error code defined in +.In fido/err.h +is returned. +.Sh SEE ALSO +.Xr eddsa_pk_new 3 , +.Xr es256_pk_new 3 , +.Xr fido_assert_verify 3 , +.Xr fido_cred_pubkey_ptr 3 , +.Xr rs256_pk_new 3 diff --git a/man/fido2-assert.1 b/man/fido2-assert.1 new file mode 100644 index 0000000..882b7ab --- /dev/null +++ b/man/fido2-assert.1 @@ -0,0 +1,286 @@ +.\" Copyright (c) 2018-2023 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: July 3 2023 $ +.Dt FIDO2-ASSERT 1 +.Os +.Sh NAME +.Nm fido2-assert +.Nd get/verify a FIDO2 assertion +.Sh SYNOPSIS +.Nm +.Fl G +.Op Fl bdhpruvw +.Op Fl t Ar option +.Op Fl i Ar input_file +.Op Fl o Ar output_file +.Ar device +.Nm +.Fl V +.Op Fl dhpv +.Op Fl i Ar input_file +.Ar key_file +.Op Ar type +.Sh DESCRIPTION +.Nm +gets or verifies a FIDO2 assertion. +.Pp +The input of +.Nm +is defined by the parameters of the assertion to be obtained/verified. +See the +.Sx INPUT FORMAT +section for details. +.Pp +The output of +.Nm +is defined by the result of the selected operation. +See the +.Sx OUTPUT FORMAT +section for details. +.Pp +If an assertion is successfully obtained or verified, +.Nm +exits 0. +Otherwise, +.Nm +exits 1. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl G +Tells +.Nm +to obtain a new assertion from +.Ar device . +.It Fl V +Tells +.Nm +to verify an assertion using the PEM-encoded public key in +.Ar key_file +of type +.Ar type , +where +.Ar type +may be +.Em es256 +(denoting ECDSA over NIST P-256 with SHA-256), +.Em rs256 +(denoting 2048-bit RSA with PKCS#1.5 padding and SHA-256), or +.Em eddsa +(denoting EDDSA over Curve25519 with SHA-512). +If +.Ar type +is not specified, +.Em es256 +is assumed. +.It Fl b +Request the credential's +.Dq largeBlobKey , +a 32-byte symmetric key associated with the asserted credential. +.It Fl h +If obtaining an assertion, enable the FIDO2 hmac-secret +extension. +If verifying an assertion, check whether the extension data bit was +signed by the authenticator. +.It Fl d +Causes +.Nm +to emit debugging output on +.Em stderr . +.It Fl i Ar input_file +Tells +.Nm +to read the parameters of the assertion from +.Ar input_file +instead of +.Em stdin . +.It Fl o Ar output_file +Tells +.Nm +to write output on +.Ar output_file +instead of +.Em stdout . +.It Fl p +If obtaining an assertion, request user presence. +If verifying an assertion, check whether the user presence bit was +signed by the authenticator. +.It Fl r +Obtain an assertion using a resident credential. +If +.Fl r +is specified, +.Nm +will not expect a credential id in its input, and may output +multiple assertions. +Resident credentials are called +.Dq discoverable credentials +in CTAP 2.1. +.It Fl t Ar option +Toggles a key/value +.Ar option , +where +.Ar option +is a string of the form +.Dq key=value . +The options supported at present are: +.Bl -tag -width Ds +.It Cm up Ns = Ns Ar true|false +Asks the authenticator for user presence to be enabled or disabled. +.It Cm uv Ns = Ns Ar true|false +Asks the authenticator for user verification to be enabled or +disabled. +.It Cm pin Ns = Ns Ar true|false +Tells +.Nm +whether to prompt for a PIN and request user verification. +.El +.Pp +The +.Fl t +option may be specified multiple times. +.It Fl u +Obtain an assertion using U2F. +By default, +.Nm +will use FIDO2 if supported by the authenticator, and fallback to +U2F otherwise. +.It Fl v +If obtaining an assertion, prompt the user for a PIN and request +user verification from the authenticator. +If verifying an assertion, check whether the user verification bit +was signed by the authenticator. +.It Fl w +Tells +.Nm +that the first line of input when obtaining an assertion shall be +interpreted as unhashed client data. +This is required by Windows Hello, which calculates the client data hash +internally. +.El +.Pp +If a +.Em tty +is available, +.Nm +will use it to obtain the PIN. +Otherwise, +.Em stdin +is used. +.Sh INPUT FORMAT +The input of +.Nm +consists of base64 blobs and UTF-8 strings separated +by newline characters ('\\n'). +.Pp +When obtaining an assertion, +.Nm +expects its input to consist of: +.Pp +.Bl -enum -offset indent -compact +.It +client data hash (base64 blob); +.It +relying party id (UTF-8 string); +.It +credential id, if credential not resident (base64 blob); +.It +hmac salt, if the FIDO2 hmac-secret extension is enabled +(base64 blob); +.El +.Pp +When verifying an assertion, +.Nm +expects its input to consist of: +.Pp +.Bl -enum -offset indent -compact +.It +client data hash (base64 blob); +.It +relying party id (UTF-8 string); +.It +authenticator data (base64 blob); +.It +assertion signature (base64 blob); +.El +.Pp +UTF-8 strings passed to +.Nm +must not contain embedded newline or NUL characters. +.Sh OUTPUT FORMAT +The output of +.Nm +consists of base64 blobs and UTF-8 strings separated +by newline characters ('\\n'). +.Pp +For each generated assertion, +.Nm +outputs: +.Pp +.Bl -enum -offset indent -compact +.It +client data hash (base64 blob); +.It +relying party id (UTF-8 string); +.It +authenticator data (base64 blob); +.It +assertion signature (base64 blob); +.It +user id, if credential resident (base64 blob); +.It +hmac secret, if the FIDO2 hmac-secret extension is enabled +(base64 blob); +.It +the credential's associated 32-byte symmetric key +.Pq Dq largeBlobKey , +if requested (base64 blob). +.El +.Pp +When verifying an assertion, +.Nm +produces no output. +.Sh EXAMPLES +Assuming +.Pa cred +contains a +.Em es256 +credential created according to the steps outlined in +.Xr fido2-cred 1 , +obtain an assertion from an authenticator at +.Pa /dev/hidraw5 +and verify it: +.Pp +.Dl $ echo assertion challenge | openssl sha256 -binary | base64 > assert_param +.Dl $ echo relying party >> assert_param +.Dl $ head -1 cred >> assert_param +.Dl $ tail -n +2 cred > pubkey +.Dl $ fido2-assert -G -i assert_param /dev/hidraw5 | fido2-assert -V pubkey es256 +.Sh SEE ALSO +.Xr fido2-cred 1 , +.Xr fido2-token 1 diff --git a/man/fido2-cred.1 b/man/fido2-cred.1 new file mode 100644 index 0000000..3f181db --- /dev/null +++ b/man/fido2-cred.1 @@ -0,0 +1,297 @@ +.\" Copyright (c) 2018-2023 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: July 3 2023 $ +.Dt FIDO2-CRED 1 +.Os +.Sh NAME +.Nm fido2-cred +.Nd make/verify a FIDO2 credential +.Sh SYNOPSIS +.Nm +.Fl M +.Op Fl bdhqruvw +.Op Fl c Ar cred_protect +.Op Fl i Ar input_file +.Op Fl o Ar output_file +.Ar device +.Op Ar type +.Nm +.Fl V +.Op Fl dhv +.Op Fl c Ar cred_protect +.Op Fl i Ar input_file +.Op Fl o Ar output_file +.Op Ar type +.Sh DESCRIPTION +.Nm +makes or verifies a FIDO2 credential. +.Pp +A credential +.Ar type +may be +.Em es256 +(denoting ECDSA over NIST P-256 with SHA-256), +.Em rs256 +(denoting 2048-bit RSA with PKCS#1.5 padding and SHA-256), or +.Em eddsa +(denoting EDDSA over Curve25519 with SHA-512). +If +.Ar type +is not specified, +.Em es256 +is assumed. +.Pp +When making a credential, the authenticator may require the user +to authenticate with a PIN. +If the +.Fl q +option is not specified, +.Nm +will prompt the user for the PIN. +If a +.Em tty +is available, +.Nm +will use it to obtain the PIN. +Otherwise, +.Em stdin +is used. +.Pp +The input of +.Nm +is defined by the parameters of the credential to be made/verified. +See the +.Sx INPUT FORMAT +section for details. +.Pp +The output of +.Nm +is defined by the result of the selected operation. +See the +.Sx OUTPUT FORMAT +section for details. +.Pp +If a credential is successfully created or verified, +.Nm +exits 0. +Otherwise, +.Nm +exits 1. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl M +Tells +.Nm +to make a new credential on +.Ar device . +.It Fl V +Tells +.Nm +to verify a credential. +.It Fl b +Request the credential's +.Dq largeBlobKey , +a 32-byte symmetric key associated with the generated credential. +.It Fl c Ar cred_protect +If making a credential, set the credential's protection level to +.Ar cred_protect , +where +.Ar cred_protect +is the credential's protection level in decimal notation. +Please refer to +.In fido/param.h +for the set of possible values. +If verifying a credential, check whether the credential's protection +level was signed by the authenticator as +.Ar cred_protect . +.It Fl d +Causes +.Nm +to emit debugging output on +.Em stderr . +.It Fl h +If making a credential, enable the FIDO2 hmac-secret extension. +If verifying a credential, check whether the extension data bit was +signed by the authenticator. +.It Fl i Ar input_file +Tells +.Nm +to read the parameters of the credential from +.Ar input_file +instead of +.Em stdin . +.It Fl o Ar output_file +Tells +.Nm +to write output on +.Ar output_file +instead of +.Em stdout . +.It Fl q +Tells +.Nm +to be quiet. +If a PIN is required and +.Fl q +is specified, +.Nm +will fail. +.It Fl r +Create a resident credential. +Resident credentials are called +.Dq discoverable credentials +in CTAP 2.1. +.It Fl u +Create a U2F credential. +By default, +.Nm +will use FIDO2 if supported by the authenticator, and fallback to +U2F otherwise. +.It Fl v +If making a credential, request user verification. +If verifying a credential, check whether the user verification bit +was signed by the authenticator. +.It Fl w +Tells +.Nm +that the first line of input when making a credential shall be +interpreted as unhashed client data. +This is required by Windows Hello, which calculates the client data hash +internally. +.El +.Sh INPUT FORMAT +The input of +.Nm +consists of base64 blobs and UTF-8 strings separated +by newline characters ('\\n'). +.Pp +When making a credential, +.Nm +expects its input to consist of: +.Pp +.Bl -enum -offset indent -compact +.It +client data hash (base64 blob); +.It +relying party id (UTF-8 string); +.It +user name (UTF-8 string); +.It +user id (base64 blob). +.El +.Pp +When verifying a credential, +.Nm +expects its input to consist of: +.Pp +.Bl -enum -offset indent -compact +.It +client data hash (base64 blob); +.It +relying party id (UTF-8 string); +.It +credential format (UTF-8 string); +.It +authenticator data (base64 blob); +.It +credential id (base64 blob); +.It +attestation signature (base64 blob); +.It +attestation certificate (optional, base64 blob). +.El +.Pp +UTF-8 strings passed to +.Nm +must not contain embedded newline or NUL characters. +.Sh OUTPUT FORMAT +The output of +.Nm +consists of base64 blobs, UTF-8 strings, and PEM-encoded public +keys separated by newline characters ('\\n'). +.Pp +Upon the successful generation of a credential, +.Nm +outputs: +.Pp +.Bl -enum -offset indent -compact +.It +client data hash (base64 blob); +.It +relying party id (UTF-8 string); +.It +credential format (UTF-8 string); +.It +authenticator data (base64 blob); +.It +credential id (base64 blob); +.It +attestation signature (base64 blob); +.It +attestation certificate, if present (base64 blob). +.It +the credential's associated 32-byte symmetric key +.Pq Dq largeBlobKey , +if present (base64 blob). +.El +.Pp +Upon the successful verification of a credential, +.Nm +outputs: +.Pp +.Bl -enum -offset indent -compact +.It +credential id (base64 blob); +.It +PEM-encoded credential key. +.El +.Sh EXAMPLES +Create a new +.Em es256 +credential on +.Pa /dev/hidraw5 , +verify it, and save the id and the public key of the credential in +.Em cred : +.Pp +.Dl $ echo credential challenge | openssl sha256 -binary | base64 > cred_param +.Dl $ echo relying party >> cred_param +.Dl $ echo user name >> cred_param +.Dl $ dd if=/dev/urandom bs=1 count=32 | base64 >> cred_param +.Dl $ fido2-cred -M -i cred_param /dev/hidraw5 | fido2-cred -V -o cred +.Sh SEE ALSO +.Xr fido2-assert 1 , +.Xr fido2-token 1 +.Sh CAVEATS +Please note that +.Nm +handles Basic Attestation and Self Attestation transparently. +In the case of Basic Attestation, the validity of the authenticator's +attestation certificate is +.Em not +verified. diff --git a/man/fido2-token.1 b/man/fido2-token.1 new file mode 100644 index 0000000..65a228c --- /dev/null +++ b/man/fido2-token.1 @@ -0,0 +1,421 @@ +.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: April 11 2022 $ +.Dt FIDO2-TOKEN 1 +.Os +.Sh NAME +.Nm fido2-token +.Nd find and manage a FIDO2 authenticator +.Sh SYNOPSIS +.Nm +.Fl C +.Op Fl d +.Ar device +.Nm +.Fl D +.Op Fl d +.Fl i +.Ar cred_id +.Ar device +.Nm +.Fl D +.Fl b +.Op Fl d +.Fl k Ar key_path +.Ar device +.Nm +.Fl D +.Fl b +.Op Fl d +.Fl n Ar rp_id +.Op Fl i Ar cred_id +.Ar device +.Nm +.Fl D +.Fl e +.Op Fl d +.Fl i +.Ar template_id +.Ar device +.Nm +.Fl D +.Fl u +.Op Fl d +.Ar device +.Nm +.Fl G +.Fl b +.Op Fl d +.Fl k Ar key_path +.Ar blob_path +.Ar device +.Nm +.Fl G +.Fl b +.Op Fl d +.Fl n Ar rp_id +.Op Fl i Ar cred_id +.Ar blob_path +.Ar device +.Nm +.Fl I +.Op Fl cd +.Op Fl k Ar rp_id Fl i Ar cred_id +.Ar device +.Nm +.Fl L +.Op Fl bder +.Op Fl k Ar rp_id +.Op device +.Nm +.Fl R +.Op Fl d +.Ar device +.Nm +.Fl S +.Op Fl adefu +.Ar device +.Nm +.Fl S +.Op Fl d +.Fl i Ar template_id +.Fl n Ar template_name +.Ar device +.Nm +.Fl S +.Op Fl d +.Fl l Ar pin_length +.Ar device +.Nm +.Fl S +.Fl b +.Op Fl d +.Fl k Ar key_path +.Ar blob_path +.Ar device +.Nm +.Fl S +.Fl b +.Op Fl d +.Fl n Ar rp_id +.Op Fl i Ar cred_id +.Ar blob_path +.Ar device +.Nm +.Fl S +.Fl c +.Op Fl d +.Fl i Ar cred_id +.Fl k Ar user_id +.Fl n Ar name +.Fl p Ar display_name +.Ar device +.Nm +.Fl S +.Fl m +.Ar rp_id +.Ar device +.Nm +.Fl V +.Sh DESCRIPTION +.Nm +manages a FIDO2 authenticator. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl C Ar device +Changes the PIN of +.Ar device . +The user will be prompted for the current and new PINs. +.It Fl D Fl i Ar id Ar device +Deletes the resident credential specified by +.Ar id +from +.Ar device , +where +.Ar id +is the credential's base64-encoded id. +The user will be prompted for the PIN. +.It Fl D Fl b Fl k Ar key_path Ar device +Deletes a +.Dq largeBlob +encrypted with +.Ar key_path +from +.Ar device , +where +.Ar key_path +holds the blob's base64-encoded 32-byte AES-256 GCM encryption key. +A PIN or equivalent user-verification gesture is required. +.It Fl D Fl b Fl n Ar rp_id Oo Fl i Ar cred_id Oc Ar device +Deletes a +.Dq largeBlob +corresponding to +.Ar rp_id +from +.Ar device . +If +.Ar rp_id +has multiple credentials enrolled on +.Ar device , +the credential ID must be specified using +.Fl i Ar cred_id , +where +.Ar cred_id +is a base64-encoded blob. +A PIN or equivalent user-verification gesture is required. +.It Fl D Fl e Fl i Ar id Ar device +Deletes the biometric enrollment specified by +.Ar id +from +.Ar device , +where +.Ar id +is the enrollment's template base64-encoded id. +The user will be prompted for the PIN. +.It Fl D Fl u Ar device +Disables the CTAP 2.1 +.Dq user verification always +feature on +.Ar device . +.It Fl G Fl b Fl k Ar key_path Ar blob_path Ar device +Gets a CTAP 2.1 +.Dq largeBlob +encrypted with +.Ar key_path +from +.Ar device , +where +.Ar key_path +holds the blob's base64-encoded 32-byte AES-256 GCM encryption key. +The blob is written to +.Ar blob_path . +A PIN or equivalent user-verification gesture is required. +.It Fl G Fl b Fl n Ar rp_id Oo Fl i Ar cred_id Oc Ar blob_path Ar device +Gets a CTAP 2.1 +.Dq largeBlob +associated with +.Ar rp_id +from +.Ar device . +If +.Ar rp_id +has multiple credentials enrolled on +.Ar device , +the credential ID must be specified using +.Fl i Ar cred_id , +where +.Ar cred_id +is a base64-encoded blob. +The blob is written to +.Ar blob_path . +A PIN or equivalent user-verification gesture is required. +.It Fl I Ar device +Retrieves information on +.Ar device . +.It Fl I Fl c Ar device +Retrieves resident credential metadata from +.Ar device . +The user will be prompted for the PIN. +.It Fl I Fl k Ar rp_id Fl i Ar cred_id Ar device +Prints the credential id (base64-encoded) and public key +(PEM encoded) of the resident credential specified by +.Ar rp_id +and +.Ar cred_id , +where +.Ar rp_id +is a UTF-8 relying party id, and +.Ar cred_id +is a base64-encoded credential id. +The user will be prompted for the PIN. +.It Fl L +Produces a list of authenticators found by the operating system. +.It Fl L Fl b Ar device +Produces a list of CTAP 2.1 +.Dq largeBlobs +on +.Ar device . +A PIN or equivalent user-verification gesture is required. +.It Fl L Fl e Ar device +Produces a list of biometric enrollments on +.Ar device . +The user will be prompted for the PIN. +.It Fl L Fl r Ar device +Produces a list of relying parties with resident credentials on +.Ar device . +The user will be prompted for the PIN. +.It Fl L Fl k Ar rp_id Ar device +Produces a list of resident credentials corresponding to +relying party +.Ar rp_id +on +.Ar device . +The user will be prompted for the PIN. +.It Fl R +Performs a reset on +.Ar device . +.Nm +will NOT prompt for confirmation. +.It Fl S +Sets the PIN of +.Ar device . +The user will be prompted for the PIN. +.It Fl S Fl a Ar device +Enables CTAP 2.1 Enterprise Attestation on +.Ar device . +.It Fl S Fl b Fl k Ar key_path Ar blob_path Ar device +Sets a CTAP 2.1 +.Dq largeBlob +encrypted with +.Ar key_path +on +.Ar device , +where +.Ar key_path +holds the blob's base64-encoded 32-byte AES-256 GCM encryption key. +The blob is read from +.Fa blob_path . +A PIN or equivalent user-verification gesture is required. +.It Fl S Fl b Fl n Ar rp_id Oo Fl i Ar cred_id Oc Ar blob_path Ar device +Sets a CTAP 2.1 +.Dq largeBlob +associated with +.Ar rp_id +on +.Ar device . +The blob is read from +.Fa blob_path . +If +.Ar rp_id +has multiple credentials enrolled on +.Ar device , +the credential ID must be specified using +.Fl i Ar cred_id , +where +.Ar cred_id +is a base64-encoded blob. +A PIN or equivalent user-verification gesture is required. +.It Fl S Fl c Fl i Ar cred_id Fl k Ar user_id Fl n Ar name Fl p Ar display_name Ar device +Sets the +.Ar name +and +.Ar display_name +attributes of the resident credential identified by +.Ar cred_id +and +.Ar user_id , +where +.Ar name +and +.Ar display_name +are UTF-8 strings and +.Ar cred_id +and +.Ar user_id +are base64-encoded blobs. +A PIN or equivalent user-verification gesture is required. +.It Fl S Fl e Ar device +Performs a new biometric enrollment on +.Ar device . +The user will be prompted for the PIN. +.It Fl S Fl e Fl i Ar template_id Fl n Ar template_name Ar device +Sets the friendly name of the biometric enrollment specified by +.Ar template_id +to +.Ar template_name +on +.Ar device , +where +.Ar template_id +is base64-encoded and +.Ar template_name +is a UTF-8 string. +The user will be prompted for the PIN. +.It Fl S Fl f Ar device +Forces a PIN change on +.Ar device . +The user will be prompted for the PIN. +.It Fl S Fl l Ar pin_length Ar device +Sets the minimum PIN length of +.Ar device +to +.Ar pin_length . +The user will be prompted for the PIN. +.It Fl S Fl m Ar rp_id Ar device +Sets the list of relying party IDs that are allowed to retrieve +the minimum PIN length of +.Ar device . +Multiple IDs may be specified, separated by commas. +The user will be prompted for the PIN. +.It Fl S Fl u Ar device +Enables the CTAP 2.1 +.Dq user verification always +feature on +.Ar device . +.It Fl V +Prints version information. +.It Fl d +Causes +.Nm +to emit debugging output on +.Em stderr . +.El +.Pp +If a +.Em tty +is available, +.Nm +will use it to prompt for PINs. +Otherwise, +.Em stdin +is used. +.Pp +.Nm +exits 0 on success and 1 on error. +.Sh SEE ALSO +.Xr fido2-assert 1 , +.Xr fido2-cred 1 +.Sh CAVEATS +The actual user-flow to perform a reset is outside the scope of the +FIDO2 specification, and may therefore vary depending on the +authenticator. +Yubico authenticators do not allow resets after 5 seconds from +power-up, and expect a reset to be confirmed by the user through +touch within 30 seconds. +.Pp +An authenticator's path may contain spaces. +.Pp +Resident credentials are called +.Dq discoverable credentials +in CTAP 2.1. +.Pp +Whether the CTAP 2.1 +.Dq user verification always +feature is activated or deactivated after an authenticator reset +is vendor-specific. diff --git a/man/fido_assert_allow_cred.3 b/man/fido_assert_allow_cred.3 new file mode 100644 index 0000000..6520137 --- /dev/null +++ b/man/fido_assert_allow_cred.3 @@ -0,0 +1,80 @@ +.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: December 1 2022 $ +.Dt FIDO_ASSERT_ALLOW_CRED 3 +.Os +.Sh NAME +.Nm fido_assert_allow_cred , +.Nm fido_assert_empty_allow_list +.Nd manage allow lists in a FIDO2 assertion +.Sh SYNOPSIS +.In fido.h +.Ft int +.Fn fido_assert_allow_cred "fido_assert_t *assert" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_assert_empty_allow_list "fido_assert_t *assert" +.Sh DESCRIPTION +The +.Fn fido_assert_allow_cred +function adds +.Fa ptr +to the list of credentials allowed in +.Fa assert , +where +.Fa ptr +points to a credential ID of +.Fa len +bytes. +A copy of +.Fa ptr +is made, and no references to the passed pointer are kept. +If +.Fn fido_assert_allow_cred +fails, the existing list of allowed credentials is preserved. +.Pp +For the format of a FIDO2 credential ID, please refer to the +Web Authentication (webauthn) standard. +.Pp +The +.Fn fido_assert_empty_allow_list +function empties the list of credentials allowed in +.Fa assert . +.Sh RETURN VALUES +The error codes returned by +.Fn fido_assert_allow_cred +and +.Fn fido_assert_empty_allow_list +are defined in +.In fido/err.h . +On success, +.Dv FIDO_OK +is returned. +.Sh SEE ALSO +.Xr fido_assert_new 3 , +.Xr fido_assert_set_authdata 3 , +.Xr fido_dev_get_assert 3 diff --git a/man/fido_assert_new.3 b/man/fido_assert_new.3 new file mode 100644 index 0000000..fdc74a9 --- /dev/null +++ b/man/fido_assert_new.3 @@ -0,0 +1,293 @@ +.\" Copyright (c) 2018-2023 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: June 19 2023 $ +.Dt FIDO_ASSERT_NEW 3 +.Os +.Sh NAME +.Nm fido_assert_new , +.Nm fido_assert_free , +.Nm fido_assert_count , +.Nm fido_assert_rp_id , +.Nm fido_assert_user_display_name , +.Nm fido_assert_user_icon , +.Nm fido_assert_user_name , +.Nm fido_assert_authdata_ptr , +.Nm fido_assert_authdata_raw_ptr , +.Nm fido_assert_blob_ptr , +.Nm fido_assert_clientdata_hash_ptr , +.Nm fido_assert_hmac_secret_ptr , +.Nm fido_assert_largeblob_key_ptr , +.Nm fido_assert_user_id_ptr , +.Nm fido_assert_sig_ptr , +.Nm fido_assert_id_ptr , +.Nm fido_assert_authdata_len , +.Nm fido_assert_authdata_raw_len , +.Nm fido_assert_blob_len , +.Nm fido_assert_clientdata_hash_len , +.Nm fido_assert_hmac_secret_len , +.Nm fido_assert_largeblob_key_len , +.Nm fido_assert_user_id_len , +.Nm fido_assert_sig_len , +.Nm fido_assert_id_len , +.Nm fido_assert_sigcount , +.Nm fido_assert_flags +.Nd FIDO2 assertion API +.Sh SYNOPSIS +.In fido.h +.Ft fido_assert_t * +.Fn fido_assert_new "void" +.Ft void +.Fn fido_assert_free "fido_assert_t **assert_p" +.Ft size_t +.Fn fido_assert_count "const fido_assert_t *assert" +.Ft const char * +.Fn fido_assert_rp_id "const fido_assert_t *assert" +.Ft const char * +.Fn fido_assert_user_display_name "const fido_assert_t *assert" "size_t idx" +.Ft const char * +.Fn fido_assert_user_icon "const fido_assert_t *assert" "size_t idx" +.Ft const char * +.Fn fido_assert_user_name "const fido_assert_t *assert" "size_t idx" +.Ft const unsigned char * +.Fn fido_assert_authdata_ptr "const fido_assert_t *assert" "size_t idx" +.Ft const unsigned char * +.Fn fido_assert_authdata_raw_ptr "const fido_assert_t *assert" "size_t idx" +.Ft const unsigned char * +.Fn fido_assert_clientdata_hash_ptr "const fido_assert_t *assert" +.Ft const unsigned char * +.Fn fido_assert_blob_ptr "const fido_assert_t *assert" "size_t idx" +.Ft const unsigned char * +.Fn fido_assert_hmac_secret_ptr "const fido_assert_t *assert" "size_t idx" +.Ft const unsigned char * +.Fn fido_assert_largeblob_key_ptr "const fido_assert_t *assert" "size_t idx" +.Ft const unsigned char * +.Fn fido_assert_user_id_ptr "const fido_assert_t *assert" "size_t idx" +.Ft const unsigned char * +.Fn fido_assert_sig_ptr "const fido_assert_t *assert" "size_t idx" +.Ft const unsigned char * +.Fn fido_assert_id_ptr "const fido_assert_t *assert" "size_t idx" +.Ft size_t +.Fn fido_assert_authdata_len "const fido_assert_t *assert" "size_t idx" +.Ft size_t +.Fn fido_assert_authdata_raw_len "const fido_assert_t *assert" "size_t idx" +.Ft size_t +.Fn fido_assert_clientdata_hash_len "const fido_assert_t *assert" +.Ft size_t +.Fn fido_assert_blob_len "const fido_assert_t *assert" "size_t idx" +.Ft size_t +.Fn fido_assert_hmac_secret_len "const fido_assert_t *assert" "size_t idx" +.Ft size_t +.Fn fido_assert_largeblob_key_len "const fido_assert_t *assert" "size_t idx" +.Ft size_t +.Fn fido_assert_user_id_len "const fido_assert_t *assert" "size_t idx" +.Ft size_t +.Fn fido_assert_sig_len "const fido_assert_t *assert" "size_t idx" +.Ft size_t +.Fn fido_assert_id_len "const fido_assert_t *assert" "size_t idx" +.Ft uint32_t +.Fn fido_assert_sigcount "const fido_assert_t *assert" "size_t idx" +.Ft uint8_t +.Fn fido_assert_flags "const fido_assert_t *assert" "size_t idx" +.Sh DESCRIPTION +A FIDO2 assertion is a collection of statements, each statement a +map between a challenge, a credential, a signature, and ancillary +attributes. +In +.Em libfido2 , +a FIDO2 assertion is abstracted by the +.Vt fido_assert_t +type. +The functions described in this page allow a +.Vt fido_assert_t +type to be allocated, deallocated, and inspected. +For other operations on +.Vt fido_assert_t , +please refer to +.Xr fido_assert_set_authdata 3 , +.Xr fido_assert_allow_cred 3 , +.Xr fido_assert_verify 3 , +and +.Xr fido_dev_get_assert 3 . +.Pp +The +.Fn fido_assert_new +function returns a pointer to a newly allocated, empty +.Vt fido_assert_t +type. +If memory cannot be allocated, NULL is returned. +.Pp +The +.Fn fido_assert_free +function releases the memory backing +.Fa *assert_p , +where +.Fa *assert_p +must have been previously allocated by +.Fn fido_assert_new . +On return, +.Fa *assert_p +is set to NULL. +Either +.Fa assert_p +or +.Fa *assert_p +may be NULL, in which case +.Fn fido_assert_free +is a NOP. +.Pp +The +.Fn fido_assert_count +function returns the number of statements in +.Fa assert . +.Pp +The +.Fn fido_assert_rp_id +function returns a pointer to a NUL-terminated string holding the +relying party ID of +.Fa assert . +.Pp +The +.Fn fido_assert_user_display_name , +.Fn fido_assert_user_icon , +and +.Fn fido_assert_user_name , +functions return pointers to the user display name, icon, and +name attributes of statement +.Fa idx +in +.Fa assert . +If not NULL, the values returned by these functions point to +NUL-terminated UTF-8 strings. +The user display name, icon, and name attributes will typically +only be returned by the authenticator if user verification was +performed by the authenticator and multiple resident/discoverable +credentials were involved in the assertion. +.Pp +The +.Fn fido_assert_authdata_ptr , +.Fn fido_assert_authdata_raw_ptr , +.Fn fido_assert_clientdata_hash_ptr , +.Fn fido_assert_id_ptr , +.Fn fido_assert_user_id_ptr , +.Fn fido_assert_sig_ptr , +.Fn fido_assert_sigcount , +and +.Fn fido_assert_flags +functions return pointers to the CBOR-encoded and raw authenticator data, +client data hash, credential ID, user ID, signature, signature +count, and authenticator data flags of statement +.Fa idx +in +.Fa assert . +.Pp +The +.Fn fido_assert_hmac_secret_ptr +function returns a pointer to the hmac-secret attribute of statement +.Fa idx +in +.Fa assert . +The HMAC Secret Extension +.Pq hmac-secret +is a CTAP 2.0 extension. +Note that the resulting hmac-secret varies according to whether +user verification was performed by the authenticator. +.Pp +The +.Fn fido_assert_blob_ptr +and +.Fn fido_assert_largeblob_key_ptr +functions return pointers to the +.Dq credBlob +and +.Dq largeBlobKey +attributes of statement +.Fa idx +in +.Fa assert . +Credential Blob +.Pq credBlob +and +Large Blob Key +.Pq largeBlobKey +are CTAP 2.1 extensions. +.Pp +The +.Fn fido_assert_authdata_len , +.Fn fido_assert_authdata_raw_len , +.Fn fido_assert_clientdata_hash_len , +.Fn fido_assert_id_len , +.Fn fido_assert_user_id_len , +.Fn fido_assert_sig_len , +.Fn fido_assert_hmac_secret_len , +.Fn fido_assert_blob_len , +and +.Fn fido_assert_largeblob_key_len +functions return the length of a given attribute. +.Pp +Please note that the first statement in +.Fa assert +has an +.Fa idx +(index) value of 0. +.Pp +The authenticator data and signature parts of an assertion +statement are typically passed to a FIDO2 server for verification. +.Sh RETURN VALUES +The authenticator data returned by +.Fn fido_assert_authdata_ptr +is a CBOR-encoded byte string, as obtained from the authenticator. +.Pp +The +.Fn fido_assert_rp_id , +.Fn fido_assert_user_display_name , +.Fn fido_assert_user_icon , +.Fn fido_assert_user_name , +.Fn fido_assert_authdata_ptr , +.Fn fido_assert_clientdata_hash_ptr , +.Fn fido_assert_id_ptr , +.Fn fido_assert_user_id_ptr , +.Fn fido_assert_sig_ptr , +.Fn fido_assert_hmac_secret_ptr , +.Fn fido_assert_blob_ptr , +and +.Fn fido_assert_largeblob_key_ptr +functions may return NULL if the respective field in +.Fa assert +is not set. +If not NULL, returned pointers are guaranteed to exist until any API +function that takes +.Fa assert +without the +.Em const +qualifier is invoked. +.Sh SEE ALSO +.Xr fido_assert_allow_cred 3 , +.Xr fido_assert_set_authdata 3 , +.Xr fido_assert_verify 3 , +.Xr fido_dev_get_assert 3 , +.Xr fido_dev_largeblob_get 3 diff --git a/man/fido_assert_set_authdata.3 b/man/fido_assert_set_authdata.3 new file mode 100644 index 0000000..503e2bf --- /dev/null +++ b/man/fido_assert_set_authdata.3 @@ -0,0 +1,314 @@ +.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: April 8 2023 $ +.Dt FIDO_ASSERT_SET_AUTHDATA 3 +.Os +.Sh NAME +.Nm fido_assert_set_authdata , +.Nm fido_assert_set_authdata_raw , +.Nm fido_assert_set_clientdata , +.Nm fido_assert_set_clientdata_hash , +.Nm fido_assert_set_count , +.Nm fido_assert_set_extensions , +.Nm fido_assert_set_hmac_salt , +.Nm fido_assert_set_hmac_secret , +.Nm fido_assert_set_up , +.Nm fido_assert_set_uv , +.Nm fido_assert_set_rp , +.Nm fido_assert_set_sig , +.Nm fido_assert_set_winhello_appid +.Nd set parameters of a FIDO2 assertion +.Sh SYNOPSIS +.In fido.h +.Bd -literal +typedef enum { + FIDO_OPT_OMIT = 0, /* use authenticator's default */ + FIDO_OPT_FALSE, /* explicitly set option to false */ + FIDO_OPT_TRUE, /* explicitly set option to true */ +} fido_opt_t; +.Ed +.Ft int +.Fn fido_assert_set_authdata "fido_assert_t *assert" "size_t idx" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_assert_set_authdata_raw "fido_assert_t *assert" "size_t idx" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_assert_set_clientdata "fido_assert_t *assert" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_assert_set_clientdata_hash "fido_assert_t *assert" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_assert_set_count "fido_assert_t *assert" "size_t n" +.Ft int +.Fn fido_assert_set_extensions "fido_assert_t *assert" "int flags" +.Ft int +.Fn fido_assert_set_hmac_salt "fido_assert_t *assert" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_assert_set_hmac_secret "fido_assert_t *assert" "size_t idx" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_assert_set_up "fido_assert_t *assert" "fido_opt_t up" +.Ft int +.Fn fido_assert_set_uv "fido_assert_t *assert" "fido_opt_t uv" +.Ft int +.Fn fido_assert_set_rp "fido_assert_t *assert" "const char *id" +.Ft int +.Fn fido_assert_set_sig "fido_assert_t *assert" "size_t idx" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_assert_set_winhello_appid "fido_assert_t *assert" "const char *id" +.Sh DESCRIPTION +The +.Nm +set of functions define the various parameters of a FIDO2 +assertion, allowing a +.Fa fido_assert_t +type to be prepared for a subsequent call to +.Xr fido_dev_get_assert 3 +or +.Xr fido_assert_verify 3 . +For the complete specification of a FIDO2 assertion and the format +of its constituent parts, please refer to the Web Authentication +(webauthn) standard. +.Pp +The +.Fn fido_assert_set_count +function sets the number of assertion statements in +.Fa assert +to +.Fa n . +.Pp +The +.Fn fido_assert_set_authdata +and +.Fn fido_assert_set_sig +functions set the authenticator data and signature parts of the +statement with index +.Fa idx +of +.Fa assert +to +.Fa ptr , +where +.Fa ptr +points to +.Fa len +bytes. +A copy of +.Fa ptr +is made, and no references to the passed pointer are kept. +Please note that the first assertion statement of +.Fa assert +has an +.Fa idx +of +.Em 0 . +The authenticator data passed to +.Fn fido_assert_set_authdata +must be a CBOR-encoded byte string, as obtained from +.Fn fido_assert_authdata_ptr . +Alternatively, a raw binary blob may be passed to +.Fn fido_assert_set_authdata_raw . +.Pp +The +.Fn fido_assert_set_clientdata_hash +function sets the client data hash of +.Fa assert +to +.Fa ptr , +where +.Fa ptr +points to +.Fa len +bytes. +A copy of +.Fa ptr +is made, and no references to the passed pointer are kept. +.Pp +The +.Fn fido_assert_set_clientdata +function allows an application to set the client data hash of +.Fa assert +by specifying the assertion's unhashed client data. +This is required by Windows Hello, which calculates the client data +hash internally. +For compatibility with Windows Hello, applications should use +.Fn fido_assert_set_clientdata +instead of +.Fn fido_assert_set_clientdata_hash . +.Pp +The +.Fn fido_assert_set_rp +function sets the relying party +.Fa id +of +.Fa assert , +where +.Fa id +is a NUL-terminated UTF-8 string. +The content of +.Fa id +is copied, and no references to the passed pointer are kept. +.Pp +The +.Fn fido_assert_set_extensions +function sets the extensions of +.Fa assert +to the bitmask +.Fa flags . +At the moment, only the +.Dv FIDO_EXT_CRED_BLOB , +.Dv FIDO_EXT_HMAC_SECRET , +and +.Dv FIDO_EXT_LARGEBLOB_KEY +extensions are supported. +If +.Fa flags +is zero, the extensions of +.Fa assert +are cleared. +.Pp +The +.Fn fido_assert_set_hmac_salt +and +.Fn fido_assert_set_hmac_secret +functions set the hmac-salt and hmac-secret parts of +.Fa assert +to +.Fa ptr , +where +.Fa ptr +points to +.Fa len +bytes. +A copy of +.Fa ptr +is made, and no references to the passed pointer are kept. +The HMAC Secret +.Pq hmac-secret +Extension is a CTAP 2.0 extension. +Note that the resulting hmac-secret varies according to whether +user verification was performed by the authenticator. +The +.Fn fido_assert_set_hmac_secret +function is normally only useful when writing tests. +.Pp +The +.Fn fido_assert_set_up +and +.Fn fido_assert_set_uv +functions set the +.Fa up +(user presence) and +.Fa uv +(user verification) +attributes of +.Fa assert . +Both are +.Dv FIDO_OPT_OMIT +by default, allowing the authenticator to use its default settings. +.Pp +The +.Fn fido_assert_set_winhello_appid +function sets the U2F application +.Fa id +.Pq Dq U2F AppID +of +.Fa assert , +where +.Fa id +is a NUL-terminated UTF-8 string. +The content of +.Fa id +is copied, and no references to the passed pointer are kept. +The +.Fn fido_assert_set_winhello_appid +function is a no-op unless +.Fa assert +is passed to +.Xr fido_dev_get_assert 3 +with a device +.Fa dev +on which +.Xr fido_dev_is_winhello 3 +holds true. +In this case, +.Em libfido2 +will instruct Windows Hello to try the assertion twice, +first with the +.Fa id +passed to +.Fn fido_assert_set_rp , +and a second time with the +.Fa id +passed to +.Fn fido_assert_set_winhello_appid . +If the second assertion succeeds, +.Xr fido_assert_rp_id 3 +will point to the U2F AppID once +.Xr fido_dev_get_assert 3 +completes. +This mechanism exists in Windows Hello to ensure U2F backwards +compatibility without the application inadvertently prompting the +user twice. +Note that +.Fn fido_assert_set_winhello_appid +is not needed on platforms offering CTAP primitives, since the +authenticator can be silently probed for the existence of U2F +credentials. +.Pp +Use of the +.Nm +set of functions may happen in two distinct situations: +when asking a FIDO2 device to produce a series of assertion +statements, prior to +.Xr fido_dev_get_assert 3 +(i.e, in the context of a FIDO2 client), or when verifying assertion +statements using +.Xr fido_assert_verify 3 +(i.e, in the context of a FIDO2 server). +.Pp +For a complete description of the generation of a FIDO2 assertion +and its verification, please refer to the FIDO2 specification. +An example of how to use the +.Nm +set of functions can be found in the +.Pa examples/assert.c +file shipped with +.Em libfido2 . +.Sh RETURN VALUES +The +.Nm +functions return +.Dv FIDO_OK +on success. +The error codes returned by the +.Nm +set of functions are defined in +.In fido/err.h . +.Sh SEE ALSO +.Xr fido_assert_allow_cred 3 , +.Xr fido_assert_verify 3 , +.Xr fido_dev_get_assert 3 , +.Xr fido_dev_is_winhello 3 diff --git a/man/fido_assert_verify.3 b/man/fido_assert_verify.3 new file mode 100644 index 0000000..1b79448 --- /dev/null +++ b/man/fido_assert_verify.3 @@ -0,0 +1,104 @@ +.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: July 15 2022 $ +.Dt FIDO_ASSERT_VERIFY 3 +.Os +.Sh NAME +.Nm fido_assert_verify +.Nd verifies the signature of a FIDO2 assertion statement +.Sh SYNOPSIS +.In fido.h +.Ft int +.Fn fido_assert_verify "const fido_assert_t *assert" "size_t idx" "int cose_alg" "const void *pk" +.Sh DESCRIPTION +The +.Fn fido_assert_verify +function verifies whether the signature contained in statement index +.Fa idx +of +.Fa assert +matches the parameters of the assertion. +Before using +.Fn fido_assert_verify +in a sensitive context, the reader is strongly encouraged to make +herself familiar with the FIDO2 assertion statement process +as defined in the Web Authentication (webauthn) standard. +.Pp +A brief description follows: +.Pp +The +.Fn fido_assert_verify +function verifies whether the client data hash, relying party ID, +user presence and user verification attributes of +.Fa assert +have been attested by the holder of the private counterpart of +the public key +.Fa pk +of COSE type +.Fa cose_alg , +where +.Fa cose_alg +is +.Dv COSE_ES256 , +.Dv COSE_ES384 , +.Dv COSE_RS256 , +or +.Dv COSE_EDDSA , +and +.Fa pk +points to a +.Vt es256_pk_t , +.Vt es384_pk_t , +.Vt rs256_pk_t , +or +.Vt eddsa_pk_t +type accordingly. +.Pp +Please note that the first statement in +.Fa assert +has an +.Fa idx +of 0. +.Sh RETURN VALUES +The error codes returned by +.Fn fido_assert_verify +are defined in +.In fido/err.h . +If +statement +.Fa idx +of +.Fa assert +passes verification with +.Fa pk , +then +.Dv FIDO_OK +is returned. +.Sh SEE ALSO +.Xr fido_assert_new 3 , +.Xr fido_assert_set_authdata 3 diff --git a/man/fido_bio_dev_get_info.3 b/man/fido_bio_dev_get_info.3 new file mode 100644 index 0000000..b8fc104 --- /dev/null +++ b/man/fido_bio_dev_get_info.3 @@ -0,0 +1,145 @@ +.\" Copyright (c) 2019 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: September 13 2019 $ +.Dt FIDO_BIO_DEV_GET_INFO 3 +.Os +.Sh NAME +.Nm fido_bio_dev_get_info , +.Nm fido_bio_dev_enroll_begin , +.Nm fido_bio_dev_enroll_continue , +.Nm fido_bio_dev_enroll_cancel , +.Nm fido_bio_dev_enroll_remove , +.Nm fido_bio_dev_get_template_array , +.Nm fido_bio_dev_set_template_name +.Nd FIDO2 biometric authenticator API +.Sh SYNOPSIS +.In fido.h +.In fido/bio.h +.Ft int +.Fn fido_bio_dev_get_info "fido_dev_t *dev" "fido_bio_info_t *info" +.Ft int +.Fn fido_bio_dev_enroll_begin "fido_dev_t *dev" "fido_bio_template_t *template" "fido_bio_enroll_t *enroll" "uint32_t timeout_ms" "const char *pin" +.Ft int +.Fn fido_bio_dev_enroll_continue "fido_dev_t *dev" "const fido_bio_template_t *template" "fido_bio_enroll_t *enroll" "uint32_t timeout_ms" +.Ft int +.Fn fido_bio_dev_enroll_cancel "fido_dev_t *dev" +.Ft int +.Fn fido_bio_dev_enroll_remove "fido_dev_t *dev" "const fido_bio_template_t *template" "const char *pin" +.Ft int +.Fn fido_bio_dev_get_template_array "fido_dev_t *dev" "fido_bio_template_array_t *template_array" "const char *pin" +.Ft int +.Fn fido_bio_dev_set_template_name "fido_dev_t *dev" "const fido_bio_template_t *template" "const char *pin" +.Sh DESCRIPTION +The functions described in this page allow biometric +templates on a FIDO2 authenticator to be listed, created, +removed, and customised. +Please note that not all FIDO2 authenticators support biometric +enrollment. +For a description of the types involved, please refer to +.Xr fido_bio_info_new 3 , +.Xr fido_bio_enroll_new 3 , +and +.Xr fido_bio_template 3 . +.Pp +The +.Fn fido_bio_dev_get_info +function populates +.Fa info +with sensor information from +.Fa dev . +.Pp +The +.Fn fido_bio_dev_enroll_begin +function initiates a biometric enrollment on +.Fa dev , +instructing the authenticator to wait +.Fa timeout_ms +milliseconds. +On success, +.Fa template +and +.Fa enroll +will be populated with the newly created template's +information and enrollment status, respectively. +.Pp +The +.Fn fido_bio_dev_enroll_continue +function continues an ongoing enrollment on +.Fa dev , +instructing the authenticator to wait +.Fa timeout_ms +milliseconds. +On success, +.Fa enroll +will be updated to reflect the status of the biometric +enrollment. +.Pp +The +.Fn fido_bio_dev_enroll_cancel +function cancels an ongoing enrollment on +.Fa dev . +.Pp +The +.Fn fido_bio_dev_enroll_remove +function removes +.Fa template +from +.Fa dev . +.Pp +The +.Fn fido_bio_dev_get_template_array +function populates +.Fa template_array +with the templates currently enrolled on +.Fa dev . +.Pp +The +.Fn fido_bio_dev_set_template_name +function sets the friendly name of +.Fa template +on +.Fa dev . +.Sh RETURN VALUES +The error codes returned by +.Fn fido_bio_dev_get_info , +.Fn fido_bio_dev_enroll_begin , +.Fn fido_bio_dev_enroll_continue , +.Fn fido_bio_dev_enroll_cancel , +.Fn fido_bio_dev_enroll_remove , +.Fn fido_bio_dev_get_template_array , +and +.Fn fido_bio_dev_set_template_name +are defined in +.In fido/err.h . +On success, +.Dv FIDO_OK +is returned. +.Sh SEE ALSO +.Xr fido_bio_enroll_new 3 , +.Xr fido_bio_info_new 3 , +.Xr fido_bio_template 3 diff --git a/man/fido_bio_enroll_new.3 b/man/fido_bio_enroll_new.3 new file mode 100644 index 0000000..536ba9a --- /dev/null +++ b/man/fido_bio_enroll_new.3 @@ -0,0 +1,118 @@ +.\" Copyright (c) 2019 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: September 13 2019 $ +.Dt FIDO_BIO_ENROLL_NEW 3 +.Os +.Sh NAME +.Nm fido_bio_enroll_new , +.Nm fido_bio_enroll_free , +.Nm fido_bio_enroll_last_status , +.Nm fido_bio_enroll_remaining_samples +.Nd FIDO2 biometric enrollment API +.Sh SYNOPSIS +.In fido.h +.In fido/bio.h +.Bd -literal +#define FIDO_BIO_ENROLL_FP_GOOD 0x00 +#define FIDO_BIO_ENROLL_FP_TOO_HIGH 0x01 +#define FIDO_BIO_ENROLL_FP_TOO_LOW 0x02 +#define FIDO_BIO_ENROLL_FP_TOO_LEFT 0x03 +#define FIDO_BIO_ENROLL_FP_TOO_RIGHT 0x04 +#define FIDO_BIO_ENROLL_FP_TOO_FAST 0x05 +#define FIDO_BIO_ENROLL_FP_TOO_SLOW 0x06 +#define FIDO_BIO_ENROLL_FP_POOR_QUALITY 0x07 +#define FIDO_BIO_ENROLL_FP_TOO_SKEWED 0x08 +#define FIDO_BIO_ENROLL_FP_TOO_SHORT 0x09 +#define FIDO_BIO_ENROLL_FP_MERGE_FAILURE 0x0a +#define FIDO_BIO_ENROLL_FP_EXISTS 0x0b +#define FIDO_BIO_ENROLL_FP_DATABASE_FULL 0x0c +#define FIDO_BIO_ENROLL_NO_USER_ACTIVITY 0x0d +#define FIDO_BIO_ENROLL_NO_USER_PRESENCE_TRANSITION 0x0e +.Ed +.Ft fido_bio_enroll_t * +.Fn fido_bio_enroll_new "void" +.Ft void +.Fn fido_bio_enroll_free "fido_bio_enroll_t **enroll_p" +.Ft uint8_t +.Fn fido_bio_enroll_last_status "const fido_bio_enroll_t *enroll" +.Ft uint8_t +.Fn fido_bio_enroll_remaining_samples "const fido_bio_enroll_t *enroll" +.Sh DESCRIPTION +Ongoing FIDO2 biometric enrollments are abstracted in +.Em libfido2 +by the +.Vt fido_bio_enroll_t +type. +.Pp +The functions described in this page allow a +.Vt fido_bio_enroll_t +type to be allocated, deallocated, and inspected. +For device operations on +.Vt fido_bio_enroll_t , +please refer to +.Xr fido_bio_dev_get_info 3 . +.Pp +The +.Fn fido_bio_enroll_new +function returns a pointer to a newly allocated, empty +.Vt fido_bio_enroll_t +type. +If memory cannot be allocated, NULL is returned. +.Pp +The +.Fn fido_bio_enroll_free +function releases the memory backing +.Fa *enroll_p , +where +.Fa *enroll_p +must have been previously allocated by +.Fn fido_bio_enroll_new . +On return, +.Fa *enroll_p +is set to NULL. +Either +.Fa enroll_p +or +.Fa *enroll_p +may be NULL, in which case +.Fn fido_bio_enroll_free +is a NOP. +.Pp +The +.Fn fido_bio_enroll_last_status +function returns the enrollment status of +.Fa enroll . +.Pp +The +.Fn fido_bio_enroll_remaining_samples +function returns the number of samples left for +.Fa enroll +to complete. +.Sh SEE ALSO +.Xr fido_bio_dev_get_info 3 , +.Xr fido_bio_template 3 diff --git a/man/fido_bio_info_new.3 b/man/fido_bio_info_new.3 new file mode 100644 index 0000000..4134306 --- /dev/null +++ b/man/fido_bio_info_new.3 @@ -0,0 +1,104 @@ +.\" Copyright (c) 2019 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: September 13 2019 $ +.Dt FIDO_BIO_INFO_NEW 3 +.Os +.Sh NAME +.Nm fido_bio_info_new , +.Nm fido_bio_info_free , +.Nm fido_bio_info_type , +.Nm fido_bio_info_max_samples +.Nd FIDO2 biometric sensor information API +.Sh SYNOPSIS +.In fido.h +.In fido/bio.h +.Ft fido_bio_info_t * +.Fn fido_bio_info_new "void" +.Ft void +.Fn fido_bio_info_free "fido_bio_info_t **info_p" +.Ft uint8_t +.Fn fido_bio_info_type "const fido_bio_info_t *info" +.Ft uint8_t +.Fn fido_bio_info_max_samples "const fido_bio_info_t *info" +.Sh DESCRIPTION +Biometric sensor metadata is abstracted in +.Em libfido2 +by the +.Vt fido_bio_info_t +type. +.Pp +The functions described in this page allow a +.Vt fido_bio_info_t +type to be allocated, deallocated, and inspected. +For device operations on +.Vt fido_bio_info_t , +please refer to +.Xr fido_bio_dev_get_info 3 . +.Pp +The +.Fn fido_bio_info_new +function returns a pointer to a newly allocated, empty +.Vt fido_bio_info_t +type. +If memory cannot be allocated, NULL is returned. +.Pp +The +.Fn fido_bio_info_free +function releases the memory backing +.Fa *info_p , +where +.Fa *info_p +must have been previously allocated by +.Fn fido_bio_info_new . +On return, +.Fa *info_p +is set to NULL. +Either +.Fa info_p +or +.Fa *info_p +may be NULL, in which case +.Fn fido_bio_info_free +is a NOP. +.Pp +The +.Fn fido_bio_info_type +function returns the fingerprint sensor type, which is +.Dv 1 +for touch sensors, and +.Dv 2 +for swipe sensors. +.Pp +The +.Fn fido_bio_info_max_samples +function returns the maximum number of successful samples +required for enrollment. +.Sh SEE ALSO +.Xr fido_bio_dev_get_info 3 , +.Xr fido_bio_enroll_new 3 , +.Xr fido_bio_template 3 diff --git a/man/fido_bio_template.3 b/man/fido_bio_template.3 new file mode 100644 index 0000000..a8ff8bc --- /dev/null +++ b/man/fido_bio_template.3 @@ -0,0 +1,202 @@ +.\" Copyright (c) 2019 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: September 13 2019 $ +.Dt FIDO_BIO_TEMPLATE 3 +.Os +.Sh NAME +.Nm fido_bio_template , +.Nm fido_bio_template_array_count , +.Nm fido_bio_template_array_free , +.Nm fido_bio_template_array_new , +.Nm fido_bio_template_free , +.Nm fido_bio_template_id_len , +.Nm fido_bio_template_id_ptr , +.Nm fido_bio_template_name , +.Nm fido_bio_template_new , +.Nm fido_bio_template_set_id , +.Nm fido_bio_template_set_name +.Nd FIDO2 biometric template API +.Sh SYNOPSIS +.In fido.h +.In fido/bio.h +.Ft fido_bio_template_t * +.Fn fido_bio_template_new "void" +.Ft void +.Fn fido_bio_template_free "fido_bio_template_t **template_p" +.Ft const char * +.Fn fido_bio_template_name "const fido_bio_template_t *template" +.Ft const unsigned char * +.Fn fido_bio_template_id_ptr "const fido_bio_template_t *template" +.Ft size_t +.Fn fido_bio_template_id_len "const fido_bio_template_t *template" +.Ft int +.Fn fido_bio_template_set_id "fido_bio_template_t *template" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_bio_template_set_name "fido_bio_template_t *template" "const char *name" +.Ft fido_bio_template_array_t * +.Fn fido_bio_template_array_new "void" +.Ft void +.Fn fido_bio_template_array_free "fido_bio_template_array_t **array_p" +.Ft size_t +.Fn fido_bio_template_array_count "const fido_bio_template_array_t *array" +.Ft const fido_bio_template_t * +.Fn fido_bio_template "const fido_bio_template_array_t *array" "size_t idx" +.Sh DESCRIPTION +Existing FIDO2 biometric enrollments are abstracted in +.Em libfido2 +by the +.Vt fido_bio_template_t +and +.Vt fido_bio_template_array_t +types. +.Pp +The functions described in this page allow a +.Vt fido_bio_template_t +type to be allocated, deallocated, changed, and inspected, +and a +.Vt fido_bio_template_array_t +type to be allocated, deallocated, and inspected. +For device operations on +.Vt fido_bio_template_t +and +.Vt fido_bio_template_array_t , +please refer to +.Xr fido_bio_dev_get_info 3 . +.Pp +The +.Fn fido_bio_template_new +function returns a pointer to a newly allocated, empty +.Vt fido_bio_template_t +type. +If memory cannot be allocated, NULL is returned. +.Pp +The +.Fn fido_bio_template_free +function releases the memory backing +.Fa *template_p , +where +.Fa *template_p +must have been previously allocated by +.Fn fido_bio_template_new . +On return, +.Fa *template_p +is set to NULL. +Either +.Fa template_p +or +.Fa *template_p +may be NULL, in which case +.Fn fido_bio_template_free +is a NOP. +.Pp +The +.Fn fido_bio_template_name +function returns a pointer to a NUL-terminated string containing +the friendly name of +.Fa template , +or NULL if +.Fa template +does not have a friendly name set. +.Pp +The +.Fn fido_bio_template_id_ptr +function returns a pointer to the template id of +.Fa template , +or NULL if +.Fa template +does not have an id. +The corresponding length can be obtained by +.Fn fido_bio_template_id_len . +.Pp +The +.Fn fido_bio_template_set_name +function sets the friendly name of +.Fa template +to +.Fa name . +If +.Fa name +is NULL, the friendly name of +.Fa template +is unset. +.Pp +The +.Fn fido_bio_template_array_new +function returns a pointer to a newly allocated, empty +.Vt fido_bio_template_array_t +type. +If memory cannot be allocated, NULL is returned. +.Pp +The +.Fn fido_bio_template_array_free +function releases the memory backing +.Fa *array_p , +where +.Fa *array_p +must have been previously allocated by +.Fn fido_bio_template_array_new . +On return, +.Fa *array_p +is set to NULL. +Either +.Fa array_p +or +.Fa *array_p +may be NULL, in which case +.Fn fido_bio_template_array_free +is a NOP. +.Pp +The +.Fn fido_bio_template_array_count +function returns the number of templates in +.Fa array . +.Pp +The +.Fn fido_bio_template +function returns a pointer to the template at index +.Fa idx +in +.Fa array . +Please note that the first template in +.Fa array +has an +.Fa idx +(index) value of 0. +.Sh RETURN VALUES +The error codes returned by +.Fn fido_bio_template_set_id +and +.Fn fido_bio_template_set_name +are defined in +.In fido/err.h . +On success, +.Dv FIDO_OK +is returned. +.Sh SEE ALSO +.Xr fido_bio_dev_get_info 3 , +.Xr fido_bio_enroll_new 3 diff --git a/man/fido_cbor_info_new.3 b/man/fido_cbor_info_new.3 new file mode 100644 index 0000000..a8168c0 --- /dev/null +++ b/man/fido_cbor_info_new.3 @@ -0,0 +1,389 @@ +.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: April 22 2022 $ +.Dt FIDO_CBOR_INFO_NEW 3 +.Os +.Sh NAME +.Nm fido_cbor_info_new , +.Nm fido_cbor_info_free , +.Nm fido_dev_get_cbor_info , +.Nm fido_cbor_info_aaguid_ptr , +.Nm fido_cbor_info_extensions_ptr , +.Nm fido_cbor_info_protocols_ptr , +.Nm fido_cbor_info_transports_ptr , +.Nm fido_cbor_info_versions_ptr , +.Nm fido_cbor_info_options_name_ptr , +.Nm fido_cbor_info_options_value_ptr , +.Nm fido_cbor_info_algorithm_type , +.Nm fido_cbor_info_algorithm_cose , +.Nm fido_cbor_info_algorithm_count , +.Nm fido_cbor_info_certs_name_ptr , +.Nm fido_cbor_info_certs_value_ptr , +.Nm fido_cbor_info_certs_len , +.Nm fido_cbor_info_aaguid_len , +.Nm fido_cbor_info_extensions_len , +.Nm fido_cbor_info_protocols_len , +.Nm fido_cbor_info_transports_len , +.Nm fido_cbor_info_versions_len , +.Nm fido_cbor_info_options_len , +.Nm fido_cbor_info_maxmsgsiz , +.Nm fido_cbor_info_maxcredbloblen , +.Nm fido_cbor_info_maxcredcntlst , +.Nm fido_cbor_info_maxcredidlen , +.Nm fido_cbor_info_maxlargeblob , +.Nm fido_cbor_info_maxrpid_minpinlen , +.Nm fido_cbor_info_minpinlen , +.Nm fido_cbor_info_fwversion , +.Nm fido_cbor_info_uv_attempts , +.Nm fido_cbor_info_uv_modality , +.Nm fido_cbor_info_rk_remaining , +.Nm fido_cbor_info_new_pin_required +.Nd FIDO2 CBOR Info API +.Sh SYNOPSIS +.In fido.h +.Ft fido_cbor_info_t * +.Fn fido_cbor_info_new "void" +.Ft void +.Fn fido_cbor_info_free "fido_cbor_info_t **ci_p" +.Ft int +.Fn fido_dev_get_cbor_info "fido_dev_t *dev" "fido_cbor_info_t *ci" +.Ft const unsigned char * +.Fn fido_cbor_info_aaguid_ptr "const fido_cbor_info_t *ci" +.Ft char ** +.Fn fido_cbor_info_extensions_ptr "const fido_cbor_info_t *ci" +.Ft const uint8_t * +.Fn fido_cbor_info_protocols_ptr "const fido_cbor_info_t *ci" +.Ft char ** +.Fn fido_cbor_info_transports_ptr "const fido_cbor_info_t *ci" +.Ft char ** +.Fn fido_cbor_info_versions_ptr "const fido_cbor_info_t *ci" +.Ft char ** +.Fn fido_cbor_info_options_name_ptr "const fido_cbor_info_t *ci" +.Ft const bool * +.Fn fido_cbor_info_options_value_ptr "const fido_cbor_info_t *ci" +.Ft const char * +.Fn fido_cbor_info_algorithm_type "const fido_cbor_info_t *ci" "size_t idx" +.Ft int +.Fn fido_cbor_info_algorithm_cose "const fido_cbor_info_t *ci" "size_t idx" +.Ft size_t +.Fn fido_cbor_info_algorithm_count "const fido_cbor_info_t *ci" +.Ft char ** +.Fn fido_cbor_info_certs_name_ptr "const fido_cbor_info_t *ci" +.Ft const uint64_t * +.Fn fido_cbor_info_certs_value_ptr "const fido_cbor_info_t *ci" +.Ft size_t +.Fn fido_cbor_info_certs_len "const fido_cbor_info_t *ci" +.Ft size_t +.Fn fido_cbor_info_aaguid_len "const fido_cbor_info_t *ci" +.Ft size_t +.Fn fido_cbor_info_extensions_len "const fido_cbor_info_t *ci" +.Ft size_t +.Fn fido_cbor_info_protocols_len "const fido_cbor_info_t *ci" +.Ft size_t +.Fn fido_cbor_info_transports_len "const fido_cbor_info_t *ci" +.Ft size_t +.Fn fido_cbor_info_versions_len "const fido_cbor_info_t *ci" +.Ft size_t +.Fn fido_cbor_info_options_len "const fido_cbor_info_t *ci" +.Ft uint64_t +.Fn fido_cbor_info_maxmsgsiz "const fido_cbor_info_t *ci" +.Ft uint64_t +.Fn fido_cbor_info_maxcredbloblen "const fido_cbor_info_t *ci" +.Ft uint64_t +.Fn fido_cbor_info_maxcredcntlst "const fido_cbor_info_t *ci" +.Ft uint64_t +.Fn fido_cbor_info_maxcredidlen "const fido_cbor_info_t *ci" +.Ft uint64_t +.Fn fido_cbor_info_maxlargeblob "const fido_cbor_info_t *ci" +.Ft uint64_t +.Fn fido_cbor_info_maxrpid_minpinlen "const fido_cbor_info_t *ci" +.Ft uint64_t +.Fn fido_cbor_info_minpinlen "const fido_cbor_info_t *ci" +.Ft uint64_t +.Fn fido_cbor_info_fwversion "const fido_cbor_info_t *ci" +.Ft uint64_t +.Fn fido_cbor_info_uv_attempts "const fido_cbor_info_t *ci" +.Ft uint64_t +.Fn fido_cbor_info_uv_modality "const fido_cbor_info_t *ci" +.Ft int64_t +.Fn fido_cbor_info_rk_remaining "const fido_cbor_info_t *ci" +.Ft bool +.Fn fido_cbor_info_new_pin_required "const fido_cbor_info_t *ci" +.Sh DESCRIPTION +The +.Fn fido_cbor_info_new +function returns a pointer to a newly allocated, empty +.Vt fido_cbor_info_t +type. +If memory cannot be allocated, NULL is returned. +.Pp +The +.Fn fido_cbor_info_free +function releases the memory backing +.Fa *ci_p , +where +.Fa *ci_p +must have been previously allocated by +.Fn fido_cbor_info_new . +On return, +.Fa *ci_p +is set to NULL. +Either +.Fa ci_p +or +.Fa *ci_p +may be NULL, in which case +.Fn fido_cbor_info_free +is a NOP. +.Pp +The +.Fn fido_dev_get_cbor_info +function transmits a +.Dv CTAP_CBOR_GETINFO +command to +.Fa dev +and fills +.Fa ci +with attributes retrieved from the command's response. +The +.Fn fido_dev_get_cbor_info +function may block. +.Pp +The +.Fn fido_cbor_info_aaguid_ptr , +.Fn fido_cbor_info_extensions_ptr , +.Fn fido_cbor_info_protocols_ptr , +.Fn fido_cbor_info_transports_ptr , +and +.Fn fido_cbor_info_versions_ptr +functions return pointers to the authenticator attestation GUID, +supported extensions, PIN protocol, transports, and CTAP version +strings of +.Fa ci . +The corresponding length of a given attribute can be +obtained by +.Fn fido_cbor_info_aaguid_len , +.Fn fido_cbor_info_extensions_len , +.Fn fido_cbor_info_protocols_len , +.Fn fido_cbor_info_transports_len , +or +.Fn fido_cbor_info_versions_len . +.Pp +The +.Fn fido_cbor_info_options_name_ptr +and +.Fn fido_cbor_info_options_value_ptr +functions return pointers to the array of option names and their +respective values +in +.Fa ci . +The length of the options array is returned by +.Fn fido_cbor_info_options_len . +.Pp +The +.Fn fido_cbor_info_algorithm_count +function returns the number of supported algorithms in +.Fa ci . +The +.Fn fido_cbor_info_algorithm_cose +function returns the COSE identifier of algorithm +.Fa idx +in +.Fa ci , +or 0 if the COSE identifier is unknown or unset. +The +.Fn fido_cbor_info_algorithm_type +function returns the type of algorithm +.Fa idx +in +.Fa ci , +or NULL if the type is unset. +Please note that the first algorithm in +.Fa ci +has an +.Fa idx +(index) value of 0. +.Pp +The +.Fn fido_cbor_info_certs_name_ptr +and +.Fn fido_cbor_info_certs_value_ptr +functions return pointers to the array of certification names and their +respective values +in +.Fa ci . +The length of the certifications array is returned by +.Fn fido_cbor_info_certs_len . +.Pp +The +.Fn fido_cbor_info_maxmsgsiz +function returns the maximum message size attribute of +.Fa ci . +.Pp +The +.Fn fido_cbor_info_maxcredbloblen +function returns the maximum +.Dq credBlob +length in bytes supported by the authenticator as reported in +.Fa ci . +.Pp +The +.Fn fido_cbor_info_maxcredcntlst +function returns the maximum supported number of credentials in +a single credential ID list as reported in +.Fa ci . +.Pp +The +.Fn fido_cbor_info_maxcredidlen +function returns the maximum supported length of a credential ID +as reported in +.Fa ci . +.Pp +The +.Fn fido_cbor_info_maxrpid_minpinlen +function returns the maximum number of RP IDs that may be passed to +.Xr fido_dev_set_pin_minlen_rpid 3 , +as reported in +.Fa ci . +The minimum PIN length attribute is a CTAP 2.1 addition. +If the attribute is not advertised by the authenticator, the +.Fn fido_cbor_info_maxrpid_minpinlen +function returns zero. +.Pp +The +.Fn fido_cbor_info_maxlargeblob +function returns the maximum length in bytes of an authenticator's +serialized largeBlob array as reported in +.Fa ci . +.Pp +The +.Fn fido_cbor_info_minpinlen +function returns the minimum PIN length enforced by the +authenticator as reported in +.Fa ci . +The minimum PIN length attribute is a CTAP 2.1 addition. +If the attribute is not advertised by the authenticator, the +.Fn fido_cbor_info_minpinlen +function returns zero. +.Pp +The +.Fn fido_cbor_info_fwversion +function returns the firmware version attribute of +.Fa ci . +.Pp +The +.Fn fido_cbor_info_uv_attempts +function returns the number of UV attempts that the platform may +attempt before falling back to PIN authentication. +If 1, then all +.Xr fido_dev_get_uv_retry_count 3 +retries are handled internally by the authenticator and the +platform may only attempt non-PIN UV once. +The UV attempts attribute is a CTAP 2.1 addition. +If the attribute is not advertised by the authenticator, +the +.Fn fido_cbor_info_uv_attempts +function returns zero. +.Pp +The +.Fn fido_cbor_info_uv_modality +function returns a bitmask representing different UV modes +supported by the authenticator, as defined in the FIDO Registry of +Predefined Values and reported in +.Fa ci . +See the +.Em FIDO_UV_MODE_* +definitions in +.In fido/param.h +for the set of values defined by libfido2 and a brief description +of each. +The UV modality attribute is a CTAP 2.1 addition. +If the attribute is not advertised by the authenticator, the +.Fn fido_cbor_info_uv_modality +function returns zero. +.Pp +The +.Fn fido_cbor_info_rk_remaining +function returns the estimated number of additional +resident/discoverable credentials that can be stored on the +authenticator as reported in +.Fa ci . +The estimated number of remaining resident credentials is a +CTAP 2.1 addition. +If the attribute is not advertised by the authenticator, the +.Fn fido_cbor_info_rk_remaining +function returns -1. +.Pp +The +.Fn fido_cbor_info_new_pin_required +function returns whether a new PIN is required by the authenticator +as reported in +.Fa ci . +If +.Fn fido_cbor_info_new_pin_required +returns true, operations requiring PIN authentication will fail +until a new PIN is set on the authenticator. +The +.Xr fido_dev_set_pin 3 +function can be used to set a new PIN. +.Pp +A complete example of how to use these functions can be found in the +.Pa example/info.c +file shipped with +.Em libfido2 . +.Sh RETURN VALUES +The +.Fn fido_cbor_info_aaguid_ptr , +.Fn fido_cbor_info_extensions_ptr , +.Fn fido_cbor_info_protocols_ptr , +.Fn fido_cbor_info_transports_ptr , +.Fn fido_cbor_info_versions_ptr , +.Fn fido_cbor_info_options_name_ptr , +and +.Fn fido_cbor_info_options_value_ptr +functions return NULL if the respective field in +.Fa ci +is absent. +If not NULL, returned pointers are guaranteed to exist until any +API function that takes +.Fa ci +without the +.Em const +qualifier is invoked. +.Sh SEE ALSO +.Xr fido_dev_get_uv_retry_count 3 , +.Xr fido_dev_open 3 , +.Xr fido_dev_set_pin 3 , +.Xr fido_dev_set_pin_minlen_rpid 3 +.Rs +.%D 2021-05-25 +.%O Review Draft, Version 2.2 +.%Q FIDO Alliance +.%R FIDO Registry of Predefined Values +.%U https://fidoalliance.org/specs/common-specs/fido-registry-v2.2-rd-20210525.html +.Re diff --git a/man/fido_cred_exclude.3 b/man/fido_cred_exclude.3 new file mode 100644 index 0000000..d5e840d --- /dev/null +++ b/man/fido_cred_exclude.3 @@ -0,0 +1,93 @@ +.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: December 2 2022 $ +.Dt FIDO_CRED_EXCLUDE 3 +.Os +.Sh NAME +.Nm fido_cred_exclude , +.Nm fido_cred_empty_exclude_list +.Nd manage exclude lists in a FIDO2 credential +.Sh SYNOPSIS +.In fido.h +.Ft int +.Fn fido_cred_exclude "fido_cred_t *cred" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_cred_empty_exclude_list "fido_cred_t *cred" +.Sh DESCRIPTION +The +.Fn fido_cred_exclude +function adds +.Fa ptr +to the list of credentials excluded by +.Fa cred , +where +.Fa ptr +points to a credential ID of +.Fa len +bytes. +A copy of +.Fa ptr +is made, and no references to the passed pointer are kept. +If +.Fn fido_cred_exclude +fails, the existing list of excluded credentials is preserved. +.Pp +If +.Nm +returns success and +.Fa cred +is later passed to +.Xr fido_dev_make_cred 3 +on a device that contains the credential +denoted by +.Fa ptr , +then +.Xr fido_dev_make_cred 3 +will fail. +.Pp +For the format of a FIDO2 credential ID, please refer to the +Web Authentication (webauthn) standard. +.Pp +The +.Fn fido_cred_empty_exclude_list +function empties the list of credentials excluded by +.Fa cred . +.Sh RETURN VALUES +The error codes returned by +.Fn fido_cred_exclude +and +.Fn fido_cred_empty_exclude_list +are defined in +.In fido/err.h . +On success, +.Dv FIDO_OK +is returned. +.Sh SEE ALSO +.Xr fido_cred_new 3 , +.Xr fido_cred_set_authdata 3 , +.Xr fido_dev_make_cred 3 diff --git a/man/fido_cred_new.3 b/man/fido_cred_new.3 new file mode 100644 index 0000000..32ce768 --- /dev/null +++ b/man/fido_cred_new.3 @@ -0,0 +1,356 @@ +.\" Copyright (c) 2018-2024 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: May 23 2018 $ +.Dt FIDO_CRED_NEW 3 +.Os +.Sh NAME +.Nm fido_cred_new , +.Nm fido_cred_free , +.Nm fido_cred_pin_minlen , +.Nm fido_cred_prot , +.Nm fido_cred_fmt , +.Nm fido_cred_rp_id , +.Nm fido_cred_rp_name , +.Nm fido_cred_user_name , +.Nm fido_cred_display_name , +.Nm fido_cred_authdata_ptr , +.Nm fido_cred_authdata_raw_ptr , +.Nm fido_cred_clientdata_hash_ptr , +.Nm fido_cred_id_ptr , +.Nm fido_cred_aaguid_ptr , +.Nm fido_cred_largeblob_key_ptr , +.Nm fido_cred_pubkey_ptr , +.Nm fido_cred_sig_ptr , +.Nm fido_cred_user_id_ptr , +.Nm fido_cred_x5c_list_count , +.Nm fido_cred_x5c_list_ptr , +.Nm fido_cred_x5c_ptr , +.Nm fido_cred_attstmt_ptr , +.Nm fido_cred_authdata_len , +.Nm fido_cred_authdata_raw_len , +.Nm fido_cred_clientdata_hash_len , +.Nm fido_cred_id_len , +.Nm fido_cred_aaguid_len , +.Nm fido_cred_largeblob_key_len , +.Nm fido_cred_pubkey_len , +.Nm fido_cred_sig_len , +.Nm fido_cred_user_id_len , +.Nm fido_cred_x5c_list_len , +.Nm fido_cred_x5c_len , +.Nm fido_cred_attstmt_len , +.Nm fido_cred_type , +.Nm fido_cred_flags , +.Nm fido_cred_sigcount +.Nd FIDO2 credential API +.Sh SYNOPSIS +.In fido.h +.Ft fido_cred_t * +.Fn fido_cred_new "void" +.Ft void +.Fn fido_cred_free "fido_cred_t **cred_p" +.Ft size_t +.Fn fido_cred_pin_minlen "const fido_cred_t *cred" +.Ft int +.Fn fido_cred_prot "const fido_cred_t *cred" +.Ft const char * +.Fn fido_cred_fmt "const fido_cred_t *cred" +.Ft const char * +.Fn fido_cred_rp_id "const fido_cred_t *cred" +.Ft const char * +.Fn fido_cred_rp_name "const fido_cred_t *cred" +.Ft const char * +.Fn fido_cred_user_name "const fido_cred_t *cred" +.Ft const char * +.Fn fido_cred_display_name "const fido_cred_t *cred" +.Ft const unsigned char * +.Fn fido_cred_authdata_ptr "const fido_cred_t *cred" +.Ft const unsigned char * +.Fn fido_cred_authdata_raw_ptr "const fido_cred_t *cred" +.Ft const unsigned char * +.Fn fido_cred_clientdata_hash_ptr "const fido_cred_t *cred" +.Ft const unsigned char * +.Fn fido_cred_id_ptr "const fido_cred_t *cred" +.Ft const unsigned char * +.Fn fido_cred_aaguid_ptr "const fido_cred_t *cred" +.Ft const unsigned char * +.Fn fido_cred_largeblob_key_ptr "const fido_cred_t *cred" +.Ft const unsigned char * +.Fn fido_cred_pubkey_ptr "const fido_cred_t *cred" +.Ft const unsigned char * +.Fn fido_cred_sig_ptr "const fido_cred_t *cred" +.Ft const unsigned char * +.Fn fido_cred_user_id_ptr "const fido_cred_t *cred" +.Ft size_t +.Fn fido_cred_x5c_list_count "const fido_cred_t *cred" +.Ft const unsigned char * +.Fn fido_cred_x5c_list_ptr "const fido_cred_t *cred" "size_t idx" +.Ft const unsigned char * +.Fn fido_cred_x5c_ptr "const fido_cred_t *cred" +.Ft const unsigned char * +.Fn fido_cred_attstmt_ptr "const fido_cred_t *cred" +.Ft size_t +.Fn fido_cred_authdata_len "const fido_cred_t *cred" +.Ft size_t +.Fn fido_cred_authdata_raw_len "const fido_cred_t *cred" +.Ft size_t +.Fn fido_cred_clientdata_hash_len "const fido_cred_t *cred" +.Ft size_t +.Fn fido_cred_id_len "const fido_cred_t *cred" +.Ft size_t +.Fn fido_cred_aaguid_len "const fido_cred_t *cred" +.Ft size_t +.Fn fido_cred_largeblob_key_len "const fido_cred_t *cred" +.Ft size_t +.Fn fido_cred_pubkey_len "const fido_cred_t *cred" +.Ft size_t +.Fn fido_cred_sig_len "const fido_cred_t *cred" +.Ft size_t +.Fn fido_cred_user_id_len "const fido_cred_t *cred" +.Ft size_t +.Fn fido_cred_x5c_list_len "const fido_cred_t *cred" "size_t idx" +.Ft size_t +.Fn fido_cred_x5c_len "const fido_cred_t *cred" +.Ft size_t +.Fn fido_cred_attstmt_len "const fido_cred_t *cred" +.Ft int +.Fn fido_cred_type "const fido_cred_t *cred" +.Ft uint8_t +.Fn fido_cred_flags "const fido_cred_t *cred" +.Ft uint32_t +.Fn fido_cred_sigcount "const fido_cred_t *cred" +.Sh DESCRIPTION +FIDO2 credentials are abstracted in +.Em libfido2 +by the +.Vt fido_cred_t +type. +The functions described in this page allow a +.Vt fido_cred_t +type to be allocated, deallocated, and inspected. +For other operations on +.Vt fido_cred_t , +please refer to +.Xr fido_cred_set_authdata 3 , +.Xr fido_cred_exclude 3 , +.Xr fido_cred_verify 3 , +and +.Xr fido_dev_make_cred 3 . +.Pp +The +.Fn fido_cred_new +function returns a pointer to a newly allocated, empty +.Vt fido_cred_t +type. +If memory cannot be allocated, NULL is returned. +.Pp +The +.Fn fido_cred_free +function releases the memory backing +.Fa *cred_p , +where +.Fa *cred_p +must have been previously allocated by +.Fn fido_cred_new . +On return, +.Fa *cred_p +is set to NULL. +Either +.Fa cred_p +or +.Fa *cred_p +may be NULL, in which case +.Fn fido_cred_free +is a NOP. +.Pp +If the CTAP 2.1 +.Dv FIDO_EXT_MINPINLEN +extension is enabled on +.Fa cred , +then the +.Fn fido_cred_pin_minlen +function returns the minimum PIN length of +.Fa cred . +Otherwise, +.Fn fido_cred_pin_minlen +returns zero. +See +.Xr fido_cred_set_pin_minlen 3 +on how to enable this extension. +.Pp +If the CTAP 2.1 +.Dv FIDO_EXT_CRED_PROTECT +extension is enabled on +.Fa cred , +then the +.Fn fido_cred_prot +function returns the protection of +.Fa cred . +Otherwise, +.Fn fido_cred_prot +returns zero. +See +.Xr fido_cred_set_prot 3 +for the protection policies understood by +.Em libfido2 . +.Pp +The +.Fn fido_cred_fmt +function returns a pointer to a NUL-terminated string containing +the attestation statement format identifier of +.Fa cred , +or NULL if +.Fa cred +does not have a format set. +.Pp +The +.Fn fido_cred_rp_id , +.Fn fido_cred_rp_name , +.Fn fido_cred_user_name , +and +.Fn fido_cred_display_name +functions return pointers to NUL-terminated strings holding the +relying party ID, relying party name, user name, and user display +name attributes of +.Fa cred , +or NULL if the respective entry is not set. +.Pp +The +.Fn fido_cred_authdata_ptr , +.Fn fido_cred_authdata_raw_ptr , +.Fn fido_cred_clientdata_hash_ptr , +.Fn fido_cred_id_ptr , +.Fn fido_cred_aaguid_ptr , +.Fn fido_cred_largeblob_key_ptr , +.Fn fido_cred_pubkey_ptr , +.Fn fido_cred_sig_ptr , +.Fn fido_cred_user_id_ptr , +.Fn fido_cred_x5c_ptr , +and +.Fn fido_cred_attstmt_ptr +functions return pointers to the CBOR-encoded and raw authenticator +data, client data hash, ID, authenticator attestation GUID, +.Dq largeBlobKey , +public key, signature, user ID, x509 leaf certificate, and attestation +statement parts of +.Fa cred , +or NULL if the respective entry is not set. +.Pp +The corresponding length can be obtained by +.Fn fido_cred_authdata_len , +.Fn fido_cred_authdata_raw_len , +.Fn fido_cred_clientdata_hash_len , +.Fn fido_cred_id_len , +.Fn fido_cred_aaguid_len , +.Fn fido_cred_largeblob_key_len , +.Fn fido_cred_pubkey_len , +.Fn fido_cred_sig_len , +.Fn fido_cred_user_id_len , +.Fn fido_cred_x5c_len , +and +.Fn fido_cred_attstmt_len . +.Pp +The +.Fn fido_cred_x5c_list_count +function returns the length of the x509 certificate chain in +.Fa cred +and the +.Fn fido_cred_x5c_list_ptr +and +.Fn fido_cred_x5c_list_len +functions return a pointer to and length of the x509 certificate at index +.Fa idx +respectively. +Please note that the leaf certificate has an +.Fa idx +(index) value of 0 and calling +.Fn fido_cred_x5c_list_ptr cred 0 +and +.Fn fido_cred_x5c_list_len cred 0 +is equivalent to +.Fn fido_cred_x5c_ptr cred +and +.Fn fido_cred_x5c_len cred +respectively. +If +.Fa idx +exceeds the return value of +.Fn fido_cred_x5c_list_count , +.Fn fido_cred_x5c_list_ptr +returns NULL and +.Fn fido_cred_x5c_list_len +returns 0. +.Pp +The authenticator data, x509 certificate, and signature parts of a +credential are typically passed to a FIDO2 server for verification. +.Pp +The +.Fn fido_cred_type +function returns the COSE algorithm of +.Fa cred . +.Pp +The +.Fn fido_cred_flags +function returns the authenticator data flags of +.Fa cred . +.Pp +The +.Fn fido_cred_sigcount +function returns the authenticator data signature counter of +.Fa cred . +.Sh RETURN VALUES +The authenticator data returned by +.Fn fido_cred_authdata_ptr +is a CBOR-encoded byte string, as obtained from the authenticator. +To obtain the decoded byte string, use +.Fn fido_cred_authdata_raw_ptr . +.Pp +If not NULL, pointers returned by +.Fn fido_cred_fmt , +.Fn fido_cred_authdata_ptr , +.Fn fido_cred_clientdata_hash_ptr , +.Fn fido_cred_id_ptr , +.Fn fido_cred_aaguid_ptr , +.Fn fido_cred_largeblob_key_ptr , +.Fn fido_cred_pubkey_ptr , +.Fn fido_cred_sig_ptr , +and +.Fn fido_cred_x5c_ptr +are guaranteed to exist until any API function that takes +.Fa cred +without the +.Em const +qualifier is invoked. +.Sh SEE ALSO +.Xr fido_cred_exclude 3 , +.Xr fido_cred_set_authdata 3 , +.Xr fido_cred_set_pin_minlen 3 , +.Xr fido_cred_set_prot 3 , +.Xr fido_cred_verify 3 , +.Xr fido_credman_metadata_new 3 , +.Xr fido_dev_largeblob_get 3 , +.Xr fido_dev_make_cred 3 diff --git a/man/fido_cred_set_authdata.3 b/man/fido_cred_set_authdata.3 new file mode 100644 index 0000000..dd18802 --- /dev/null +++ b/man/fido_cred_set_authdata.3 @@ -0,0 +1,402 @@ +.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: July 15 2022 $ +.Dt FIDO_CRED_SET_AUTHDATA 3 +.Os +.Sh NAME +.Nm fido_cred_set_authdata , +.Nm fido_cred_set_authdata_raw , +.Nm fido_cred_set_attstmt , +.Nm fido_cred_set_attobj , +.Nm fido_cred_set_x509 , +.Nm fido_cred_set_sig , +.Nm fido_cred_set_id , +.Nm fido_cred_set_clientdata , +.Nm fido_cred_set_clientdata_hash , +.Nm fido_cred_set_rp , +.Nm fido_cred_set_user , +.Nm fido_cred_set_extensions , +.Nm fido_cred_set_blob , +.Nm fido_cred_set_pin_minlen , +.Nm fido_cred_set_prot , +.Nm fido_cred_set_rk , +.Nm fido_cred_set_uv , +.Nm fido_cred_set_fmt , +.Nm fido_cred_set_type +.Nd set parameters of a FIDO2 credential +.Sh SYNOPSIS +.In fido.h +.Bd -literal +typedef enum { + FIDO_OPT_OMIT = 0, /* use authenticator's default */ + FIDO_OPT_FALSE, /* explicitly set option to false */ + FIDO_OPT_TRUE, /* explicitly set option to true */ +} fido_opt_t; +.Ed +.Ft int +.Fn fido_cred_set_authdata "fido_cred_t *cred" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_cred_set_authdata_raw "fido_cred_t *cred" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_cred_set_attstmt "fido_cred_t *cred" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_cred_set_attobj "fido_cred_t *cred" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_cred_set_x509 "fido_cred_t *cred" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_cred_set_sig "fido_cred_t *cred" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_cred_set_id "fido_cred_t *cred" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_cred_set_clientdata "fido_cred_t *cred" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_cred_set_clientdata_hash "fido_cred_t *cred" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_cred_set_rp "fido_cred_t *cred" "const char *id" "const char *name" +.Ft int +.Fn fido_cred_set_user "fido_cred_t *cred" "const unsigned char *user_id" "size_t user_id_len" "const char *name" "const char *display_name" "const char *icon" +.Ft int +.Fn fido_cred_set_extensions "fido_cred_t *cred" "int flags" +.Ft int +.Fn fido_cred_set_blob "fido_cred_t *cred" "const unsigned char *ptr" "size_t len" +.Ft int +.Fn fido_cred_set_pin_minlen "fido_cred_t *cred" "size_t len" +.Ft int +.Fn fido_cred_set_prot "fido_cred_t *cred" "int prot" +.Ft int +.Fn fido_cred_set_rk "fido_cred_t *cred" "fido_opt_t rk" +.Ft int +.Fn fido_cred_set_uv "fido_cred_t *cred" "fido_opt_t uv" +.Ft int +.Fn fido_cred_set_fmt "fido_cred_t *cred" "const char *ptr" +.Ft int +.Fn fido_cred_set_type "fido_cred_t *cred" "int cose_alg" +.Sh DESCRIPTION +The +.Nm +set of functions define the various parameters of a FIDO2 +credential, allowing a +.Fa fido_cred_t +type to be prepared for a subsequent call to +.Xr fido_dev_make_cred 3 +or +.Xr fido_cred_verify 3 . +For the complete specification of a FIDO2 credential and the format +of its constituent parts, please refer to the Web Authentication +(webauthn) standard. +.Pp +The +.Fn fido_cred_set_authdata , +.Fn fido_cred_set_attstmt , +.Fn fido_cred_set_attobj , +.Fn fido_cred_set_x509 , +.Fn fido_cred_set_sig , +.Fn fido_cred_set_id , +and +.Fn fido_cred_set_clientdata_hash +functions set the authenticator data, attestation statement, +attestation object, attestation certificate, attestation signature, +id, and client data hash parts of +.Fa cred +to +.Fa ptr , +where +.Fa ptr +points to +.Fa len +bytes. +A copy of +.Fa ptr +is made, and no references to the passed pointer are kept. +.Pp +The authenticator data passed to +.Fn fido_cred_set_authdata +must be a CBOR-encoded byte string, as obtained from +.Fn fido_cred_authdata_ptr . +Alternatively, a raw binary blob may be passed to +.Fn fido_cred_set_authdata_raw . +An application calling +.Fn fido_cred_set_authdata +does not need to call +.Fn fido_cred_set_id . +The latter is meant to be used in contexts where the +credential's authenticator data is not available. +.Pp +The attestation statement passed to +.Fn fido_cred_set_attstmt +must be a CBOR-encoded map, as obtained from +.Fn fido_cred_attstmt_ptr . +An application calling +.Fn fido_cred_set_attstmt +does not need to call +.Fn fido_cred_set_x509 +or +.Fn fido_cred_set_sig . +The latter two are meant to be used in contexts where the +credential's complete attestation statement is not available or +required. +.Pp +The attestation object passed to +.Fn fido_cred_set_attobj +must be a CBOR-encoded map containing +.Dq authData , +.Dq fmt , +and +.Dq attStmt . +An application calling +.Fn fido_cred_set_attobj +does not need to call +.Fn fido_cred_set_fmt , +.Fn fido_cred_set_attstmt , +.Fn fido_cred_set_authdata , +or +.Fn fido_cred_set_authdata_raw . +.Pp +The +.Fn fido_cred_set_clientdata +function allows an application to set the client data hash of +.Fa cred +by specifying the credential's unhashed client data. +This is required by Windows Hello, which calculates the client data +hash internally. +For compatibility with Windows Hello, applications should use +.Fn fido_cred_set_clientdata +instead of +.Fn fido_cred_set_clientdata_hash . +.Pp +The +.Fn fido_cred_set_rp +function sets the relying party +.Fa id +and +.Fa name +parameters of +.Fa cred , +where +.Fa id +and +.Fa name +are NUL-terminated UTF-8 strings. +The contents of +.Fa id +and +.Fa name +are copied, and no references to the passed pointers are kept. +.Pp +The +.Fn fido_cred_set_user +function sets the user attributes of +.Fa cred , +where +.Fa user_id +points to +.Fa user_id_len +bytes and +.Fa name , +.Fa display_name , +and +.Fa icon +are NUL-terminated UTF-8 strings. +The contents of +.Fa user_id , +.Fa name , +.Fa display_name , +and +.Fa icon +are copied, and no references to the passed pointers are kept. +Previously set user attributes are flushed. +The +.Fa user_id , +.Fa name , +.Fa display_name , +and +.Fa icon +parameters may be NULL. +.Pp +The +.Fn fido_cred_set_extensions +function sets the extensions of +.Fa cred +to the bitmask +.Fa flags . +At the moment, only the +.Dv FIDO_EXT_CRED_BLOB , +.Dv FIDO_EXT_CRED_PROTECT , +.Dv FIDO_EXT_HMAC_SECRET , +.Dv FIDO_EXT_MINPINLEN , +and +.Dv FIDO_EXT_LARGEBLOB_KEY +extensions are supported. +If +.Fa flags +is zero, the extensions of +.Fa cred +are cleared. +.Pp +The +.Fn fido_cred_set_blob +function sets the +.Dq credBlob +to be stored with +.Fa cred +to the data pointed to by +.Fa ptr , +which must be +.Fa len +bytes long. +.Pp +The +.Fn fido_cred_set_pin_minlen +function enables the CTAP 2.1 +.Dv FIDO_EXT_MINPINLEN +extension on +.Fa cred +and sets the expected minimum PIN length of +.Fa cred +to +.Fa len , +where +.Fa len +is greater than zero. +If +.Fa len +is zero, the +.Dv FIDO_EXT_MINPINLEN +extension is disabled on +.Fa cred . +.Pp +The +.Fn fido_cred_set_prot +function enables the CTAP 2.1 +.Dv FIDO_EXT_CRED_PROTECT +extension on +.Fa cred +and sets the protection of +.Fa cred +to the scalar +.Fa prot . +At the moment, only the +.Dv FIDO_CRED_PROT_UV_OPTIONAL , +.Dv FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID , +and +.Dv FIDO_CRED_PROT_UV_REQUIRED +protections are supported. +If +.Fa prot +is zero, the protection of +.Fa cred +is cleared. +.Pp +The +.Fn fido_cred_set_rk +and +.Fn fido_cred_set_uv +functions set the +.Em rk +.Pq resident/discoverable key +and +.Em uv +.Pq user verification +attributes of +.Fa cred . +Both are +.Dv FIDO_OPT_OMIT +by default, allowing the authenticator to use its default settings. +.Pp +The +.Fn fido_cred_set_fmt +function sets the attestation statement format identifier of +.Fa cred +to +.Fa fmt , +where +.Fa fmt +must be +.Vt "packed" +.Pq the format used in FIDO2 , +.Vt "fido-u2f" +.Pq the format used in U2F , +.Vt "tpm" +.Pq the format used by TPM-based authenticators , +or +.Vt "none" . +A copy of +.Fa fmt +is made, and no references to the passed pointer are kept. +Note that not all authenticators support FIDO2 and therefore may only +be able to generate +.Vt fido-u2f +attestation statements. +.Pp +The +.Fn fido_cred_set_type +function sets the type of +.Fa cred to +.Fa cose_alg , +where +.Fa cose_alg +is +.Dv COSE_ES256 , +.Dv COSE_ES384 , +.Dv COSE_RS256 , +or +.Dv COSE_EDDSA . +The type of a credential may only be set once. +Note that not all authenticators support COSE_RS256, COSE_ES384, or +COSE_EDDSA. +.Pp +Use of the +.Nm +set of functions may happen in two distinct situations: +when generating a new credential on a FIDO2 device, prior to +.Xr fido_dev_make_cred 3 +(i.e, in the context of a FIDO2 client), or when validating +a generated credential using +.Xr fido_cred_verify 3 +(i.e, in the context of a FIDO2 server). +.Pp +For a complete description of the generation of a FIDO2 credential +and its verification, please refer to the FIDO2 specification. +A concrete utilisation example of the +.Nm +set of functions can be found in the +.Pa cred.c +example shipped with +.Em libfido2 . +.Sh RETURN VALUES +The error codes returned by the +.Nm +set of functions are defined in +.In fido/err.h . +On success, +.Dv FIDO_OK +is returned. +.Sh SEE ALSO +.Xr fido_cred_exclude 3 , +.Xr fido_cred_verify 3 , +.Xr fido_dev_make_cred 3 diff --git a/man/fido_cred_verify.3 b/man/fido_cred_verify.3 new file mode 100644 index 0000000..9548870 --- /dev/null +++ b/man/fido_cred_verify.3 @@ -0,0 +1,114 @@ +.\" Copyright (c) 2018-2021 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: May 23 2018 $ +.Dt FIDO_CRED_VERIFY 3 +.Os +.Sh NAME +.Nm fido_cred_verify , +.Nm fido_cred_verify_self +.Nd verify the attestation signature of a FIDO2 credential +.Sh SYNOPSIS +.In fido.h +.Ft int +.Fn fido_cred_verify "const fido_cred_t *cred" +.Ft int +.Fn fido_cred_verify_self "const fido_cred_t *cred" +.Sh DESCRIPTION +The +.Fn fido_cred_verify +and +.Fn fido_cred_verify_self +functions verify whether the attestation signature contained in +.Fa cred +matches the attributes of the credential. +Before using +.Fn fido_cred_verify +or +.Fn fido_cred_verify_self +in a sensitive context, the reader is strongly encouraged to make +herself familiar with the FIDO2 credential attestation process +as defined in the Web Authentication (webauthn) standard. +.Pp +The +.Fn fido_cred_verify +function verifies whether the client data hash, relying party ID, +credential ID, type, protection policy, minimum PIN length, and +resident/discoverable key and user verification attributes of +.Fa cred +have been attested by the holder of the private counterpart of +the public key contained in the credential's x509 certificate. +.Pp +Please note that the x509 certificate itself is not verified. +.Pp +The attestation statement formats supported by +.Fn fido_cred_verify +are +.Em packed , +.Em fido-u2f , +and +.Em tpm . +The attestation type implemented by +.Fn fido_cred_verify +is +.Em Basic Attestation . +.Pp +The +.Fn fido_cred_verify_self +function verifies whether the client data hash, relying party ID, +credential ID, type, protection policy, minimum PIN length, and +resident/discoverable key and user verification attributes of +.Fa cred +have been attested by the holder of the credential's private key. +.Pp +The attestation statement formats supported by +.Fn fido_cred_verify_self +are +.Em packed +and +.Em fido-u2f . +The attestation type implemented by +.Fn fido_cred_verify_self +is +.Em Self Attestation . +.Pp +Other attestation formats and types are not supported. +.Sh RETURN VALUES +The error codes returned by +.Fn fido_cred_verify +and +.Fn fido_cred_verify_self +are defined in +.In fido/err.h . +If +.Fa cred +passes verification, then +.Dv FIDO_OK +is returned. +.Sh SEE ALSO +.Xr fido_cred_new 3 , +.Xr fido_cred_set_authdata 3 diff --git a/man/fido_credman_metadata_new.3 b/man/fido_credman_metadata_new.3 new file mode 100644 index 0000000..122020b --- /dev/null +++ b/man/fido_credman_metadata_new.3 @@ -0,0 +1,349 @@ +.\" Copyright (c) 2019-2021 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: June 28 2019 $ +.Dt FIDO_CREDMAN_METADATA_NEW 3 +.Os +.Sh NAME +.Nm fido_credman_metadata_new , +.Nm fido_credman_rk_new , +.Nm fido_credman_rp_new , +.Nm fido_credman_metadata_free , +.Nm fido_credman_rk_free , +.Nm fido_credman_rp_free , +.Nm fido_credman_rk_existing , +.Nm fido_credman_rk_remaining , +.Nm fido_credman_rk , +.Nm fido_credman_rk_count , +.Nm fido_credman_rp_id , +.Nm fido_credman_rp_name , +.Nm fido_credman_rp_count , +.Nm fido_credman_rp_id_hash_ptr , +.Nm fido_credman_rp_id_hash_len , +.Nm fido_credman_get_dev_metadata , +.Nm fido_credman_get_dev_rk , +.Nm fido_credman_set_dev_rk , +.Nm fido_credman_del_dev_rk , +.Nm fido_credman_get_dev_rp +.Nd FIDO2 credential management API +.Sh SYNOPSIS +.In fido.h +.In fido/credman.h +.Ft fido_credman_metadata_t * +.Fn fido_credman_metadata_new "void" +.Ft fido_credman_rk_t * +.Fn fido_credman_rk_new "void" +.Ft fido_credman_rp_t * +.Fn fido_credman_rp_new "void" +.Ft void +.Fn fido_credman_metadata_free "fido_credman_metadata_t **metadata_p" +.Ft void +.Fn fido_credman_rk_free "fido_credman_rk_t **rk_p" +.Ft void +.Fn fido_credman_rp_free "fido_credman_rp_t **rp_p" +.Ft uint64_t +.Fn fido_credman_rk_existing "const fido_credman_metadata_t *metadata" +.Ft uint64_t +.Fn fido_credman_rk_remaining "const fido_credman_metadata_t *metadata" +.Ft const fido_cred_t * +.Fn fido_credman_rk "const fido_credman_rk_t *rk" "size_t idx" +.Ft size_t +.Fn fido_credman_rk_count "const fido_credman_rk_t *rk" +.Ft const char * +.Fn fido_credman_rp_id "const fido_credman_rp_t *rp" "size_t idx" +.Ft const char * +.Fn fido_credman_rp_name "const fido_credman_rp_t *rp" "size_t idx" +.Ft size_t +.Fn fido_credman_rp_count "const fido_credman_rp_t *rp" +.Ft const unsigned char * +.Fn fido_credman_rp_id_hash_ptr "const fido_credman_rp_t *rp" "size_t idx" +.Ft size_t +.Fn fido_credman_rp_id_hash_len "const fido_credman_rp_t *" "size_t idx" +.Ft int +.Fn fido_credman_get_dev_metadata "fido_dev_t *dev" "fido_credman_metadata_t *metadata" "const char *pin" +.Ft int +.Fn fido_credman_get_dev_rk "fido_dev_t *dev" "const char *rp_id" "fido_credman_rk_t *rk" "const char *pin" +.Ft int +.Fn fido_credman_set_dev_rk "fido_dev_t *dev" "fido_cred_t *cred" "const char *pin" +.Ft int +.Fn fido_credman_del_dev_rk "fido_dev_t *dev" "const unsigned char *cred_id" "size_t cred_id_len" "const char *pin" +.Ft int +.Fn fido_credman_get_dev_rp "fido_dev_t *dev" "fido_credman_rp_t *rp" "const char *pin" +.Sh DESCRIPTION +The credential management API of +.Em libfido2 +allows resident credentials on a FIDO2 authenticator to be listed, +inspected, modified, and removed. +Please note that not all FIDO2 authenticators support credential +management. +To obtain information on what an authenticator supports, please +refer to +.Xr fido_cbor_info_new 3 . +.Pp +The +.Vt fido_credman_metadata_t +type abstracts credential management metadata. +.Pp +The +.Fn fido_credman_metadata_new +function returns a pointer to a newly allocated, empty +.Vt fido_credman_metadata_t +type. +If memory cannot be allocated, NULL is returned. +.Pp +The +.Fn fido_credman_metadata_free +function releases the memory backing +.Fa *metadata_p , +where +.Fa *metadata_p +must have been previously allocated by +.Fn fido_credman_metadata_new . +On return, +.Fa *metadata_p +is set to NULL. +Either +.Fa metadata_p +or +.Fa *metadata_p +may be NULL, in which case +.Fn fido_credman_metadata_free +is a NOP. +.Pp +The +.Fn fido_credman_get_dev_metadata +function populates +.Fa metadata +with information retrieved from +.Fa dev . +A valid +.Fa pin +must be provided. +.Pp +The +.Fn fido_credman_rk_existing +function inspects +.Fa metadata +and returns the number of resident credentials on the +authenticator. +The +.Fn fido_credman_rk_remaining +function inspects +.Fa metadata +and returns the estimated number of resident credentials that can +be created on the authenticator. +.Pp +The +.Vt fido_credman_rk_t +type abstracts the set of resident credentials belonging to a +given relying party. +.Pp +The +.Fn fido_credman_rk_new +function returns a pointer to a newly allocated, empty +.Vt fido_credman_rk_t +type. +If memory cannot be allocated, NULL is returned. +.Pp +The +.Fn fido_credman_rk_free +function releases the memory backing +.Fa *rk_p , +where +.Fa *rk_p +must have been previously allocated by +.Fn fido_credman_rk_new . +On return, +.Fa *rk_p +is set to NULL. +Either +.Fa rk_p +or +.Fa *rk_p +may be NULL, in which case +.Fn fido_credman_rk_free +is a NOP. +.Pp +The +.Fn fido_credman_get_dev_rk +function populates +.Fa rk +with the set of resident credentials belonging to +.Fa rp_id +in +.Fa dev . +A valid +.Fa pin +must be provided. +.Pp +The +.Fn fido_credman_rk_count +function returns the number of resident credentials in +.Fa rk . +The +.Fn fido_credman_rk +function returns a pointer to the credential at index +.Fa idx +in +.Fa rk . +Please note that the first credential in +.Fa rk +has an +.Fa idx +(index) value of 0. +.Pp +The +.Fn fido_credman_set_dev_rk +function updates the credential pointed to by +.Fa cred +in +.Fa dev . +The credential id and user id attributes of +.Fa cred +must be set. +See +.Xr fido_cred_set_id 3 +and +.Xr fido_cred_set_user 3 +for details. +Only a credential's user attributes (name, display name) +may be updated at this time. +.Pp +The +.Fn fido_credman_del_dev_rk +function deletes the resident credential identified by +.Fa cred_id +from +.Fa dev , +where +.Fa cred_id +points to +.Fa cred_id_len +bytes. +A valid +.Fa pin +must be provided. +.Pp +The +.Vt fido_credman_rp_t +type abstracts information about a relying party. +.Pp +The +.Fn fido_credman_rp_new +function returns a pointer to a newly allocated, empty +.Vt fido_credman_rp_t +type. +If memory cannot be allocated, NULL is returned. +.Pp +The +.Fn fido_credman_rp_free +function releases the memory backing +.Fa *rp_p , +where +.Fa *rp_p +must have been previously allocated by +.Fn fido_credman_rp_new . +On return, +.Fa *rp_p +is set to NULL. +Either +.Fa rp_p +or +.Fa *rp_p +may be NULL, in which case +.Fn fido_credman_rp_free +is a NOP. +.Pp +The +.Fn fido_credman_get_dev_rp +function populates +.Fa rp +with information about relying parties with resident credentials +in +.Fa dev . +A valid +.Fa pin +must be provided. +.Pp +The +.Fn fido_credman_rp_count +function returns the number of relying parties in +.Fa rp . +.Pp +The +.Fn fido_credman_rp_id +and +.Fn fido_credman_rp_name +functions return pointers to the id and name of relying party +.Fa idx +in +.Fa rp . +If not NULL, the values returned by these functions point to +NUL-terminated UTF-8 strings. +Please note that the first relying party in +.Fa rp +has an +.Fa idx +(index) value of 0. +.Pp +The +.Fn fido_credman_rp_id_hash_ptr +function returns a pointer to the hashed id of relying party +.Fa idx +in +.Fa rp . +The corresponding length can be obtained by +.Fn fido_credman_rp_id_hash_len . +Please note that the first relying party in +.Fa rp +has an +.Fa idx +(index) value of 0. +.Sh RETURN VALUES +The +.Fn fido_credman_get_dev_metadata , +.Fn fido_credman_get_dev_rk , +.Fn fido_credman_set_dev_rk , +.Fn fido_credman_del_dev_rk , +and +.Fn fido_credman_get_dev_rp +functions return +.Dv FIDO_OK +on success. +On error, a different error code defined in +.In fido/err.h +is returned. +Functions returning pointers are not guaranteed to succeed, and +should have their return values checked for NULL. +.Sh SEE ALSO +.Xr fido_cbor_info_new 3 , +.Xr fido_cred_new 3 , +.Xr fido_dev_supports_credman 3 +.Sh CAVEATS +Resident credentials are called +.Dq discoverable credentials +in CTAP 2.1. diff --git a/man/fido_dev_enable_entattest.3 b/man/fido_dev_enable_entattest.3 new file mode 100644 index 0000000..7617f22 --- /dev/null +++ b/man/fido_dev_enable_entattest.3 @@ -0,0 +1,149 @@ +.\" Copyright (c) 2020-2022 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: March 30 2022 $ +.Dt FIDO_DEV_ENABLE_ENTATTEST 3 +.Os +.Sh NAME +.Nm fido_dev_enable_entattest , +.Nm fido_dev_toggle_always_uv , +.Nm fido_dev_force_pin_change , +.Nm fido_dev_set_pin_minlen , +.Nm fido_dev_set_pin_minlen_rpid +.Nd CTAP 2.1 configuration authenticator API +.Sh SYNOPSIS +.In fido.h +.In fido/config.h +.Ft int +.Fn fido_dev_enable_entattest "fido_dev_t *dev" "const char *pin" +.Ft int +.Fn fido_dev_toggle_always_uv "fido_dev_t *dev" "const char *pin" +.Ft int +.Fn fido_dev_force_pin_change "fido_dev_t *dev" "const char *pin" +.Ft int +.Fn fido_dev_set_pin_minlen "fido_dev_t *dev" "size_t len" "const char *pin" +.Ft int +.Fn fido_dev_set_pin_minlen_rpid "fido_dev_t *dev" "const char * const *rpid" "size_t n" "const char *pin" +.Sh DESCRIPTION +The functions described in this page allow configuration of a +CTAP 2.1 authenticator. +.Pp +The +.Fn fido_dev_enable_entattest +function enables the +.Em Enterprise Attestation +feature on +.Fa dev . +.Em Enterprise Attestation +instructs the authenticator to include uniquely identifying +information in subsequent attestation statements. +The +.Fa pin +parameter may be NULL if +.Fa dev +does not have a PIN set. +.Pp +The +.Fn fido_dev_toggle_always_uv +function toggles the +.Dq user verification always +feature on +.Fa dev . +When set, this toggle enforces user verification at the +authenticator level for all known credentials. +If +.Fa dev +supports U2F (CTAP1) and the user verification methods supported by +the authenticator do not allow protection of U2F credentials, the +U2F subsystem will be disabled by the authenticator. +The +.Fa pin +parameter may be NULL if +.Fa dev +does not have a PIN set. +.Pp +The +.Fn fido_dev_force_pin_change +function instructs +.Fa dev +to require a PIN change. +Subsequent PIN authentication attempts against +.Fa dev +will fail until its PIN is changed. +.Pp +The +.Fn fido_dev_set_pin_minlen +function sets the minimum PIN length of +.Fa dev +to +.Fa len . +Minimum PIN lengths may only be increased. +.Pp +The +.Fn fido_dev_set_pin_minlen_rpid +function sets the list of relying party identifiers +.Pq RP IDs +that are allowed to obtain the minimum PIN length of +.Fa dev +through the CTAP 2.1 +.Dv FIDO_EXT_MINPINLEN +extension. +The list of RP identifiers is denoted by +.Fa rpid , +a vector of +.Fa n +NUL-terminated UTF-8 strings. +A copy of +.Fa rpid +is made, and no reference to it or its contents is kept. +The maximum value of +.Fa n +supported by the authenticator can be obtained using +.Xr fido_cbor_info_maxrpid_minpinlen 3 . +.Pp +Configuration settings are reflected in the payload returned by the +authenticator in response to a +.Xr fido_dev_get_cbor_info 3 +call. +.Sh RETURN VALUES +The error codes returned by +.Fn fido_dev_enable_entattest , +.Fn fido_dev_toggle_always_uv , +.Fn fido_dev_force_pin_change , +.Fn fido_dev_set_pin_minlen , +and +.Fn fido_dev_set_pin_minlen_rpid +are defined in +.In fido/err.h . +On success, +.Dv FIDO_OK +is returned. +.Sh SEE ALSO +.Xr fido_cbor_info_maxrpid_minpinlen 3 , +.Xr fido_cred_pin_minlen 3 , +.Xr fido_dev_get_cbor_info 3 , +.Xr fido_dev_reset 3 diff --git a/man/fido_dev_get_assert.3 b/man/fido_dev_get_assert.3 new file mode 100644 index 0000000..bb2fc43 --- /dev/null +++ b/man/fido_dev_get_assert.3 @@ -0,0 +1,99 @@ +.\" Copyright (c) 2018 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: May 24 2018 $ +.Dt FIDO_DEV_GET_ASSERT 3 +.Os +.Sh NAME +.Nm fido_dev_get_assert +.Nd obtains an assertion from a FIDO2 device +.Sh SYNOPSIS +.In fido.h +.Ft int +.Fn fido_dev_get_assert "fido_dev_t *dev" "fido_assert_t *assert" "const char *pin" +.Sh DESCRIPTION +The +.Fn fido_dev_get_assert +function asks the FIDO2 device represented by +.Fa dev +for an assertion according to the following parameters defined in +.Fa assert : +.Pp +.Bl -dash -compact +.It +.Nm relying party ID ; +.It +.Nm client data hash ; +.It +.Nm list of allowed credential IDs ; +.It +.Nm user presence and user verification attributes . +.El +.Pp +See +.Xr fido_assert_set_authdata 3 +for information on how these values are set. +.Pp +If a PIN is not needed to authenticate the request against +.Fa dev , +then +.Fa pin +may be NULL. +Otherwise +.Fa pin +must point to a NUL-terminated UTF-8 string. +.Pp +After a successful call to +.Fn fido_dev_get_assert , +the +.Xr fido_assert_count 3 , +.Xr fido_assert_user_display_name 3 , +.Xr fido_assert_user_icon 3 , +.Xr fido_assert_user_name 3 , +.Xr fido_assert_authdata_ptr 3 , +.Xr fido_assert_user_id_ptr 3 , +.Xr fido_assert_sig_ptr 3 , +and +.Xr fido_assert_sigcount 3 +functions may be invoked on +.Fa assert +to retrieve the various attributes of the generated assertion. +.Pp +Please note that +.Fn fido_dev_get_assert +is synchronous and will block if necessary. +.Sh RETURN VALUES +The error codes returned by +.Fn fido_dev_get_assert +are defined in +.In fido/err.h . +On success, +.Dv FIDO_OK +is returned. +.Sh SEE ALSO +.Xr fido_assert_new 3 , +.Xr fido_assert_set_authdata 3 diff --git a/man/fido_dev_get_touch_begin.3 b/man/fido_dev_get_touch_begin.3 new file mode 100644 index 0000000..f015eff --- /dev/null +++ b/man/fido_dev_get_touch_begin.3 @@ -0,0 +1,96 @@ +.\" Copyright (c) 2020 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: August 5 2020 $ +.Dt FIDO_DEV_GET_TOUCH_BEGIN 3 +.Os +.Sh NAME +.Nm fido_dev_get_touch_begin , +.Nm fido_dev_get_touch_status +.Nd asynchronously wait for touch on a FIDO2 authenticator +.Sh SYNOPSIS +.In fido.h +.Ft int +.Fn fido_dev_get_touch_begin "fido_dev_t *dev" +.Ft int +.Fn fido_dev_get_touch_status "fido_dev_t *dev" "int *touched" "int ms" +.Sh DESCRIPTION +The functions described in this page allow an application to +asynchronously wait for touch on a FIDO2 authenticator. +This is useful when multiple authenticators are present and +the application needs to know which one to use. +.Pp +The +.Fn fido_dev_get_touch_begin +function initiates a touch request on +.Fa dev . +.Pp +The +.Fn fido_dev_get_touch_status +function continues an ongoing touch request on +.Fa dev , +blocking up to +.Fa ms +milliseconds. +On success, +.Fa touched +will be updated to reflect the touch request status. +If +.Fa touched +is 1, the device was touched, and the touch request is +terminated. +If +.Fa touched +is 0, the application may call +.Fn fido_dev_get_touch_status +to continue the touch request, or +.Fn fido_dev_cancel +to terminate it. +.Sh RETURN VALUES +The error codes returned by +.Fn fido_dev_get_touch_begin +and +.Fn fido_dev_get_touch_status +are defined in +.In fido/err.h . +On success, +.Dv FIDO_OK +is returned. +.Sh EXAMPLES +Please refer to +.Em examples/select.c +in +.Em libfido2's +source tree. +.Sh SEE ALSO +.Xr fido_dev_cancel 3 +.Sh CAVEATS +The +.Fn fido_dev_get_touch_status +function will cause a command to be transmitted to U2F +authenticators. +These transmissions should not exceed a frequency of 5Hz. diff --git a/man/fido_dev_info_manifest.3 b/man/fido_dev_info_manifest.3 new file mode 100644 index 0000000..a70a3cb --- /dev/null +++ b/man/fido_dev_info_manifest.3 @@ -0,0 +1,211 @@ +.\" Copyright (c) 2018 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: March 30 2022 $ +.Dt FIDO_DEV_INFO_MANIFEST 3 +.Os +.Sh NAME +.Nm fido_dev_info_manifest , +.Nm fido_dev_info_new , +.Nm fido_dev_info_free , +.Nm fido_dev_info_ptr , +.Nm fido_dev_info_path , +.Nm fido_dev_info_product , +.Nm fido_dev_info_vendor , +.Nm fido_dev_info_manufacturer_string , +.Nm fido_dev_info_product_string , +.Nm fido_dev_info_set +.Nd FIDO2 device discovery functions +.Sh SYNOPSIS +.In fido.h +.Ft int +.Fn fido_dev_info_manifest "fido_dev_info_t *devlist" "size_t ilen" "size_t *olen" +.Ft fido_dev_info_t * +.Fn fido_dev_info_new "size_t n" +.Ft void +.Fn fido_dev_info_free "fido_dev_info_t **devlist_p" "size_t n" +.Ft const fido_dev_info_t * +.Fn fido_dev_info_ptr "const fido_dev_info_t *devlist" "size_t i" +.Ft const char * +.Fn fido_dev_info_path "const fido_dev_info_t *di" +.Ft int16_t +.Fn fido_dev_info_product "const fido_dev_info_t *di" +.Ft int16_t +.Fn fido_dev_info_vendor "const fido_dev_info_t *di" +.Ft const char * +.Fn fido_dev_info_manufacturer_string "const fido_dev_info_t *di" +.Ft const char * +.Fn fido_dev_info_product_string "const fido_dev_info_t *di" +.Ft int +.Fn fido_dev_info_set "fido_dev_info_t *devlist" "size_t i" "const char *path" "const char *manufacturer" "const char *product" "const fido_dev_io_t *io" "const fido_dev_transport_t *transport" +.Sh DESCRIPTION +The +.Fn fido_dev_info_manifest +function fills +.Fa devlist +with up to +.Fa ilen +FIDO2 devices found by the underlying operating system. +Currently only USB HID devices are supported. +The number of discovered devices is returned in +.Fa olen , +where +.Fa olen +is an addressable pointer. +.Pp +The +.Fn fido_dev_info_new +function returns a pointer to a newly allocated, empty device list +with +.Fa n +available slots. +If memory is not available, NULL is returned. +.Pp +The +.Fn fido_dev_info_free +function releases the memory backing +.Fa *devlist_p , +where +.Fa *devlist_p +must have been previously allocated by +.Fn fido_dev_info_new . +The number +.Fa n +of allocated slots must also be provided. +On return, +.Fa *devlist_p +is set to NULL. +Either +.Fa devlist_p +or +.Fa *devlist_p +may be NULL, in which case +.Fn fido_dev_info_free +is a NOP. +.Pp +The +.Fn fido_dev_info_ptr +function returns a pointer to slot number +.Fa i +of +.Fa devlist . +It is the caller's responsibility to ensure that +.Fa i +is bounded. +Please note that the first slot has index 0. +.Pp +The +.Fn fido_dev_info_path +function returns the filesystem path or subsystem-specific identification +string of +.Fa di . +.Pp +The +.Fn fido_dev_info_product +function returns the product ID of +.Fa di . +.Pp +The +.Fn fido_dev_info_vendor +function returns the vendor ID of +.Fa di . +.Pp +The +.Fn fido_dev_info_manufacturer_string +function returns the manufacturer string of +.Fa di . +If +.Fa di +does not have an associated manufacturer string, +.Fn fido_dev_info_manufacturer_string +returns an empty string. +.Pp +The +.Fn fido_dev_info_product_string +function returns the product string of +.Fa di . +If +.Fa di +does not have an associated product string, +.Fn fido_dev_info_product_string +returns an empty string. +.Pp +An example of how to use the functions described in this document +can be found in the +.Pa examples/manifest.c +file shipped with +.Em libfido2 . +.Pp +The +.Fn fido_dev_info_set +function initializes an entry in a device list allocated by +.Fn fido_dev_info_new +with the specified path, manufacturer, and product strings, and with +the specified I/O handlers and, optionally, transport functions, as +described in +.Xr fido_dev_set_io_functions 3 . +The +.Fa io +argument must be specified; the +.Fa transport +argument may be +.Dv NULL . +The path, I/O handlers, and transport functions will be used +automatically by +.Xr fido_dev_new_with_info 3 +and +.Xr fido_dev_open_with_info 3 . +An application can use this, for example, to substitute mock FIDO2 +devices in testing for the real ones that +.Fn fido_dev_info_manifest +would discover. +.Sh RETURN VALUES +The +.Fn fido_dev_info_manifest +function always returns +.Dv FIDO_OK . +If a discovery error occurs, the +.Fa olen +pointer is set to 0. +.Pp +On success, the +.Fn fido_dev_info_set +function returns +.Dv FIDO_OK . +On error, a different error code defined in +.In fido/err.h +is returned. +.Pp +The pointers returned by +.Fn fido_dev_info_ptr , +.Fn fido_dev_info_path , +.Fn fido_dev_info_manufacturer_string , +and +.Fn fido_dev_info_product_string +are guaranteed to exist until +.Fn fido_dev_info_free +is called on the corresponding device list. diff --git a/man/fido_dev_largeblob_get.3 b/man/fido_dev_largeblob_get.3 new file mode 100644 index 0000000..12dd319 --- /dev/null +++ b/man/fido_dev_largeblob_get.3 @@ -0,0 +1,216 @@ +.\" Copyright (c) 2020 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: October 26 2020 $ +.Dt FIDO_LARGEBLOB_GET 3 +.Os +.Sh NAME +.Nm fido_dev_largeblob_get , +.Nm fido_dev_largeblob_set , +.Nm fido_dev_largeblob_remove , +.Nm fido_dev_largeblob_get_array , +.Nm fido_dev_largeblob_set_array +.Nd FIDO2 large blob API +.Sh SYNOPSIS +.In fido.h +.Ft int +.Fn fido_dev_largeblob_get "fido_dev_t *dev" "const unsigned char *key_ptr" "size_t key_len" "unsigned char **blob_ptr" "size_t *blob_len" +.Ft int +.Fn fido_dev_largeblob_set "fido_dev_t *dev" "const unsigned char *key_ptr" "size_t key_len" "const unsigned char *blob_ptr" "size_t blob_len" "const char *pin" +.Ft int +.Fn fido_dev_largeblob_remove "fido_dev_t *dev" "const unsigned char *key_ptr" "size_t key_len" "const char *pin" +.Ft int +.Fn fido_dev_largeblob_get_array "fido_dev_t *dev" "unsigned char **cbor_ptr" "size_t *cbor_len" +.Ft int +.Fn fido_dev_largeblob_set_array "fido_dev_t *dev" "const unsigned char *cbor_ptr" "size_t cbor_len" "const char *pin" +.Sh DESCRIPTION +The +.Dq largeBlobs +API of +.Em libfido2 +allows binary blobs residing on a CTAP 2.1 authenticator to be +read, written, and inspected. +.Dq largeBlobs +is a CTAP 2.1 extension. +.Pp +.Dq largeBlobs +are stored as elements of a CBOR array. +Confidentiality is ensured by encrypting each element with a +distinct, credential-bound 256-bit AES-GCM key. +The array is otherwise shared between different credentials and +FIDO2 relying parties. +.Pp +Retrieval of a credential's encryption key is possible during +enrollment with +.Xr fido_cred_set_extensions 3 +and +.Xr fido_cred_largeblob_key_ptr 3 , +during assertion with +.Xr fido_assert_set_extensions 3 +and +.Xr fido_assert_largeblob_key_ptr 3 , +or, in the case of a resident credential, via +.Em libfido2's +credential management API. +.Pp +The +.Dq largeBlobs +CBOR array is opaque to the authenticator. +Management of the array is left at the discretion of FIDO2 clients. +For further details on CTAP 2.1's +.Dq largeBlobs +extension, please refer to the CTAP 2.1 spec. +.Pp +The +.Fn fido_dev_largeblob_get +function retrieves the authenticator's +.Dq largeBlobs +CBOR array and, on success, returns the first blob +.Pq iterating from array index zero +that can be decrypted by +.Fa key_ptr , +where +.Fa key_ptr +points to +.Fa key_len +bytes. +On success, +.Fn fido_dev_largeblob_get +sets +.Fa blob_ptr +to the body of the decrypted blob, and +.Fa blob_len +to the length of the decrypted blob in bytes. +It is the caller's responsibility to free +.Fa blob_ptr . +.Pp +The +.Fn fido_dev_largeblob_set +function uses +.Fa key_ptr +to encrypt +.Fa blob_ptr +and inserts the result in the authenticator's +.Dq largeBlobs +CBOR array. +Insertion happens at the end of the array if no existing element +can be decrypted by +.Fa key_ptr , +or at the position of the first element +.Pq iterating from array index zero +that can be decrypted by +.Fa key_ptr . +.Fa key_len +holds the length of +.Fa key_ptr +in bytes, and +.Fa blob_len +the length of +.Fa blob_ptr +in bytes. +A +.Fa pin +or equivalent user-verification gesture is required. +.Pp +The +.Fn fido_dev_largeblob_remove +function retrieves the authenticator's +.Dq largeBlobs +CBOR array and, on success, drops the first blob +.Pq iterating from array index zero +that can be decrypted by +.Fa key_ptr , +where +.Fa key_ptr +points to +.Fa key_len +bytes. +A +.Fa pin +or equivalent user-verification gesture is required. +.Pp +The +.Fn fido_dev_largeblob_get_array +function retrieves the authenticator's +.Dq largeBlobs +CBOR array and, on success, +sets +.Fa cbor_ptr +to the body of the CBOR array, and +.Fa cbor_len +to its corresponding length in bytes. +It is the caller's responsibility to free +.Fa cbor_ptr . +.Pp +Finally, the +.Fn fido_dev_largeblob_set_array +function sets the authenticator's +.Dq largeBlobs +CBOR array to the data pointed to by +.Fa cbor_ptr , +where +.Fa cbor_ptr +points to +.Fa cbor_len +bytes. +A +.Fa pin +or equivalent user-verification gesture is required. +.Sh RETURN VALUES +The functions +.Fn fido_dev_largeblob_set , +.Fn fido_dev_largeblob_get , +.Fn fido_dev_largeblob_remove , +.Fn fido_dev_largeblob_get_array , +and +.Fn fido_dev_largeblob_set_array +return +.Dv FIDO_OK +on success. +On error, an error code defined in +.In fido/err.h +is returned. +.Sh SEE ALSO +.Xr fido_assert_largeblob_key_len 3 , +.Xr fido_assert_largeblob_key_ptr 3 , +.Xr fido_assert_set_extensions 3 , +.Xr fido_cred_largeblob_key_len 3 , +.Xr fido_cred_largeblob_key_ptr 3 , +.Xr fido_cred_set_extensions 3 , +.Xr fido_credman_get_dev_rk 3 , +.Xr fido_credman_get_dev_rp 3 , +.Xr fido_dev_get_assert 3 , +.Xr fido_dev_make_cred 3 +.Sh CAVEATS +The +.Dq largeBlobs +extension is not meant to be used to store sensitive data. +When retrieved, a credential's +.Dq largeBlobs +encryption key is transmitted in the clear, and an authenticator's +.Dq largeBlobs +CBOR array can be read without user interaction or verification. diff --git a/man/fido_dev_make_cred.3 b/man/fido_dev_make_cred.3 new file mode 100644 index 0000000..b13f9a1 --- /dev/null +++ b/man/fido_dev_make_cred.3 @@ -0,0 +1,100 @@ +.\" Copyright (c) 2018 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: May 23 2018 $ +.Dt FIDO_DEV_MAKE_CRED 3 +.Os +.Sh NAME +.Nm fido_dev_make_cred +.Nd generates a new credential on a FIDO2 device +.Sh SYNOPSIS +.In fido.h +.Ft int +.Fn fido_dev_make_cred "fido_dev_t *dev" "fido_cred_t *cred" "const char *pin" +.Sh DESCRIPTION +The +.Fn fido_dev_make_cred +function asks the FIDO2 device represented by +.Fa dev +to generate a new credential according to the following parameters +defined in +.Fa cred : +.Pp +.Bl -dash -compact +.It +.Nm type ; +.It +.Nm client data hash ; +.It +.Nm relying party ; +.It +.Nm user attributes ; +.It +.Nm list of excluded credential IDs ; +.It +.Nm resident/discoverable key and user verification attributes . +.El +.Pp +See +.Xr fido_cred_set_authdata 3 +for information on how these values are set. +.Pp +If a PIN is not needed to authenticate the request against +.Fa dev , +then +.Fa pin +may be NULL. +Otherwise +.Fa pin +must point to a NUL-terminated UTF-8 string. +.Pp +After a successful call to +.Fn fido_dev_make_cred , +the +.Xr fido_cred_authdata_ptr 3 , +.Xr fido_cred_pubkey_ptr 3 , +.Xr fido_cred_x5c_ptr 3 , +and +.Xr fido_cred_sig_ptr 3 +functions may be invoked on +.Fa cred +to retrieve the various parts of the generated credential. +.Pp +Please note that +.Fn fido_dev_make_cred +is synchronous and will block if necessary. +.Sh RETURN VALUES +The error codes returned by +.Fn fido_dev_make_cred +are defined in +.In fido/err.h . +On success, +.Dv FIDO_OK +is returned. +.Sh SEE ALSO +.Xr fido_cred_new 3 , +.Xr fido_cred_set_authdata 3 diff --git a/man/fido_dev_open.3 b/man/fido_dev_open.3 new file mode 100644 index 0000000..f839e26 --- /dev/null +++ b/man/fido_dev_open.3 @@ -0,0 +1,316 @@ +.\" Copyright (c) 2018 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: May 25 2018 $ +.Dt FIDO_DEV_OPEN 3 +.Os +.Sh NAME +.Nm fido_dev_open , +.Nm fido_dev_open_with_info , +.Nm fido_dev_close , +.Nm fido_dev_cancel , +.Nm fido_dev_new , +.Nm fido_dev_new_with_info , +.Nm fido_dev_free , +.Nm fido_dev_force_fido2 , +.Nm fido_dev_force_u2f , +.Nm fido_dev_is_fido2 , +.Nm fido_dev_is_winhello , +.Nm fido_dev_supports_credman , +.Nm fido_dev_supports_cred_prot , +.Nm fido_dev_supports_permissions , +.Nm fido_dev_supports_pin , +.Nm fido_dev_supports_uv , +.Nm fido_dev_has_pin , +.Nm fido_dev_has_uv , +.Nm fido_dev_protocol , +.Nm fido_dev_build , +.Nm fido_dev_flags , +.Nm fido_dev_major , +.Nm fido_dev_minor +.Nd FIDO2 device open/close and related functions +.Sh SYNOPSIS +.In fido.h +.Ft int +.Fn fido_dev_open "fido_dev_t *dev" "const char *path" +.Ft int +.Fn fido_dev_open_with_info "fido_dev_t *dev" +.Ft int +.Fn fido_dev_close "fido_dev_t *dev" +.Ft int +.Fn fido_dev_cancel "fido_dev_t *dev" +.Ft fido_dev_t * +.Fn fido_dev_new "void" +.Ft fido_dev_t * +.Fn fido_dev_new_with_info "const fido_dev_info_t *" +.Ft void +.Fn fido_dev_free "fido_dev_t **dev_p" +.Ft void +.Fn fido_dev_force_fido2 "fido_dev_t *dev" +.Ft void +.Fn fido_dev_force_u2f "fido_dev_t *dev" +.Ft bool +.Fn fido_dev_is_fido2 "const fido_dev_t *dev" +.Ft bool +.Fn fido_dev_is_winhello "const fido_dev_t *dev" +.Ft bool +.Fn fido_dev_supports_credman "const fido_dev_t *dev" +.Ft bool +.Fn fido_dev_supports_cred_prot "const fido_dev_t *dev" +.Ft bool +.Fn fido_dev_supports_permissions "const fido_dev_t *dev" +.Ft bool +.Fn fido_dev_supports_pin "const fido_dev_t *dev" +.Ft bool +.Fn fido_dev_supports_uv "const fido_dev_t *dev" +.Ft bool +.Fn fido_dev_has_pin "const fido_dev_t *dev" +.Ft bool +.Fn fido_dev_has_uv "const fido_dev_t *dev" +.Ft uint8_t +.Fn fido_dev_protocol "const fido_dev_t *dev" +.Ft uint8_t +.Fn fido_dev_build "const fido_dev_t *dev" +.Ft uint8_t +.Fn fido_dev_flags "const fido_dev_t *dev" +.Ft uint8_t +.Fn fido_dev_major "const fido_dev_t *dev" +.Ft uint8_t +.Fn fido_dev_minor "const fido_dev_t *dev" +.Sh DESCRIPTION +The +.Fn fido_dev_open +function opens the device pointed to by +.Fa path , +where +.Fa dev +is a freshly allocated or otherwise closed +.Vt fido_dev_t . +If +.Fa dev +claims to be FIDO2, +.Em libfido2 +will attempt to speak FIDO2 to +.Fa dev . +If that fails, +.Em libfido2 +will fallback to U2F unless the +.Dv FIDO_DISABLE_U2F_FALLBACK +flag was set in +.Xr fido_init 3 . +.Pp +The +.Fn fido_dev_open_with_info +function opens +.Fa dev +as previously allocated using +.Fn fido_dev_new_with_info . +.Pp +The +.Fn fido_dev_close +function closes the device represented by +.Fa dev . +If +.Fa dev +is already closed, +.Fn fido_dev_close +is a NOP. +.Pp +The +.Fn fido_dev_cancel +function cancels any pending requests on +.Fa dev . +.Pp +The +.Fn fido_dev_new +function returns a pointer to a newly allocated, empty +.Vt fido_dev_t . +If memory cannot be allocated, NULL is returned. +.Pp +The +.Fn fido_dev_new_with_info +function returns a pointer to a newly allocated +.Vt fido_dev_t +with +.Vt fido_dev_info_t +parameters, for use with +.Xr fido_dev_info_manifest 3 +and +.Fn fido_dev_open_with_info . +If memory cannot be allocated, NULL is returned. +.Pp +The +.Fn fido_dev_free +function releases the memory backing +.Fa *dev_p , +where +.Fa *dev_p +must have been previously allocated by +.Fn fido_dev_new . +On return, +.Fa *dev_p +is set to NULL. +Either +.Fa dev_p +or +.Fa *dev_p +may be NULL, in which case +.Fn fido_dev_free +is a NOP. +.Pp +The +.Fn fido_dev_force_fido2 +function can be used to force CTAP2 communication with +.Fa dev , +where +.Fa dev +is an open device. +.Pp +The +.Fn fido_dev_force_u2f +function can be used to force CTAP1 (U2F) communication with +.Fa dev , +where +.Fa dev +is an open device. +.Pp +The +.Fn fido_dev_is_fido2 +function returns +.Dv true +if +.Fa dev +is a FIDO2 device. +.Pp +The +.Fn fido_dev_is_winhello +function returns +.Dv true +if +.Fa dev +is a Windows Hello device. +.Pp +The +.Fn fido_dev_supports_credman +function returns +.Dv true +if +.Fa dev +supports CTAP 2.1 Credential Management. +.Pp +The +.Fn fido_dev_supports_cred_prot +function returns +.Dv true +if +.Fa dev +supports CTAP 2.1 Credential Protection. +.Pp +The +.Fn fido_dev_supports_permissions +function returns +.Dv true +if +.Fa dev +supports CTAP 2.1 UV token permissions. +.Pp +The +.Fn fido_dev_supports_pin +function returns +.Dv true +if +.Fa dev +supports CTAP 2.0 Client PINs. +.Pp +The +.Fn fido_dev_supports_uv +function returns +.Dv true +if +.Fa dev +supports a built-in user verification method. +.Pp +The +.Fn fido_dev_has_pin +function returns +.Dv true +if +.Fa dev +has a CTAP 2.0 Client PIN set. +.Pp +The +.Fn fido_dev_has_uv +function returns +.Dv true +if +.Fa dev +supports built-in user verification and its user verification +feature is configured. +.Pp +The +.Fn fido_dev_protocol +function returns the CTAPHID protocol version identifier of +.Fa dev . +.Pp +The +.Fn fido_dev_build +function returns the CTAPHID build version number of +.Fa dev . +.Pp +The +.Fn fido_dev_flags +function returns the CTAPHID capabilities flags of +.Fa dev . +.Pp +The +.Fn fido_dev_major +function returns the CTAPHID major version number of +.Fa dev . +.Pp +The +.Fn fido_dev_minor +function returns the CTAPHID minor version number of +.Fa dev . +.Pp +For the format and meaning of the CTAPHID parameters returned by +functions above, please refer to the FIDO Client to Authenticator +Protocol (CTAP) specification. +.Sh RETURN VALUES +On success, +.Fn fido_dev_open , +.Fn fido_dev_open_with_info , +and +.Fn fido_dev_close +return +.Dv FIDO_OK . +On error, a different error code defined in +.In fido/err.h +is returned. +.Sh SEE ALSO +.Xr fido_dev_info_manifest 3 , +.Xr fido_dev_set_io_functions 3 , +.Xr fido_init 3 diff --git a/man/fido_dev_set_io_functions.3 b/man/fido_dev_set_io_functions.3 new file mode 100644 index 0000000..e3e10ba --- /dev/null +++ b/man/fido_dev_set_io_functions.3 @@ -0,0 +1,261 @@ +.\" Copyright (c) 2018-2021 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: May 25 2018 $ +.Dt FIDO_DEV_SET_IO_FUNCTIONS 3 +.Os +.Sh NAME +.Nm fido_dev_set_io_functions , +.Nm fido_dev_set_sigmask , +.Nm fido_dev_set_timeout , +.Nm fido_dev_set_transport_functions , +.Nm fido_dev_io_handle +.Nd FIDO2 device I/O interface +.Sh SYNOPSIS +.In fido.h +.Bd -literal +typedef void *fido_dev_io_open_t(const char *); +typedef void fido_dev_io_close_t(void *); +typedef int fido_dev_io_read_t(void *, unsigned char *, size_t, int); +typedef int fido_dev_io_write_t(void *, const unsigned char *, size_t); + +typedef struct fido_dev_io { + fido_dev_io_open_t *open; + fido_dev_io_close_t *close; + fido_dev_io_read_t *read; + fido_dev_io_write_t *write; +} fido_dev_io_t; + +#ifdef _WIN32 +typedef int fido_sigset_t; +#else +typedef sigset_t fido_sigset_t; +#endif + +typedef int fido_dev_rx_t(struct fido_dev *, + uint8_t, unsigned char *, size_t, int); +typedef int fido_dev_tx_t(struct fido_dev *, + uint8_t, const unsigned char *, size_t); + +typedef struct fido_dev_transport { + fido_dev_rx_t *rx; + fido_dev_tx_t *tx; +} fido_dev_transport_t; +.Ed +.Pp +.Ft int +.Fn fido_dev_set_io_functions "fido_dev_t *dev" "const fido_dev_io_t *io" +.Ft int +.Fn fido_dev_set_sigmask "fido_dev_t *dev" "const fido_sigset_t *sigmask" +.Ft int +.Fn fido_dev_set_timeout "fido_dev_t *dev" "int ms" +.Ft int +.Fn fido_dev_set_transport_functions "fido_dev_t *dev" "const fido_dev_transport_t *t" +.Ft void * +.Fn fido_dev_io_handle "const fido_dev_t *dev" +.Sh DESCRIPTION +The +.Fn fido_dev_set_io_functions +function sets the I/O handlers used by +.Em libfido2 +to talk to +.Fa dev . +By default, these handlers are set to the operating system's native HID or NFC +interfaces. +They are defined as follows: +.Bl -tag -width Ds +.It Vt fido_dev_open_t +Receives a +.Vt const char * +holding a path and opens the corresponding device, returning a +non-NULL opaque pointer on success and NULL on error. +.It Vt fido_dev_close_t +Receives the opaque pointer returned by +.Vt fido_dev_open_t +and closes the device. +.It Vt fido_dev_read_t +Reads a single transmission unit (HID report, APDU) from a device. +The first parameter is the opaque pointer returned by +.Vt fido_dev_open_t . +The second parameter is the read buffer, and the third parameter +is the read buffer size. +The fourth parameter is the number of milliseconds the caller is +willing to sleep, should the call need to block. +If this value holds -1, +.Vt fido_dev_read_t +may block indefinitely. +On success, the number of bytes read is returned. +On error, -1 is returned. +.It Vt fido_dev_write_t +Writes a single transmission unit (HID report, APDU) to +.Fa dev . +The first parameter is the opaque pointer returned by +.Vt fido_dev_open_t . +The second parameter is the write buffer, and the third parameter +is the number of bytes to be written. +A +.Vt fido_dev_write_t +may block. +On success, the number of bytes written is returned. +On error, -1 is returned. +.El +.Pp +When calling +.Fn fido_dev_set_io_functions , +the +.Fa open , +.Fa close , +.Fa read , +and +.Fa write +fields of +.Fa io +may not be NULL. +.Pp +No references to +.Fa io +are held by +.Fn fido_dev_set_io_functions . +.Pp +The +.Fn fido_dev_set_sigmask +function may be used to specify a non-NULL signal mask +.Fa sigmask +to be used while +.Em libfido2's +default I/O handlers wait on +.Fa dev . +On UNIX-like operating systems, +.Vt fido_sigset_t +is defined as +.Vt sigset_t . +On Windows, +.Vt fido_sigset_t +is defined as +.Vt int +and +.Fn fido_dev_set_sigmask +is a no-op. +.Pp +No references to +.Fa sigmask +are held by +.Fn fido_dev_set_sigmask . +.Pp +The +.Fn fido_dev_set_timeout +function informs +.Em libfido2 +not to block for more than +.Fa ms +milliseconds while communicating with +.Fa dev . +If a timeout occurs, the corresponding +.Em fido_dev_* +function will fail with +.Dv FIDO_ERR_RX . +If +.Fa ms +is -1, +then +.Em libfido2 +may block indefinitely. +This is the default behaviour. +When using the Windows Hello backend, +.Fa ms +is used as a guidance and may be overwritten by the platform. +.Pp +The +.Fn fido_dev_set_transport_functions +function sets the transport functions used by +.Em libfido2 +to talk to +.Fa dev . +While the I/O handlers are responsible for sending and receiving +transmission units of initialization and continuation packets already +formatted by +.Em libfido2 , +the transport handlers are responsible for sending and receiving +the CTAPHID commands and data directly, as defined in the FIDO Client +to Authenticator Protocol (CTAP) standard. +They are defined as follows: +.Bl -tag -width Ds +.It Vt fido_dev_tx_t +Receives a device, a CTAPHID command to transmit, a data buffer to +transmit, and the length of the data buffer. +On success, 0 is returned. +On error, -1 is returned. +.It Vt fido_dev_rx_t +Receives a device, a CTAPHID command whose response the caller expects +to receive, a data buffer to receive into, the size of the data buffer +determining the maximum length of a response, and the maximum number of +milliseconds to wait for a response. +On success, the number of bytes read into the data buffer is returned. +On error, -1 is returned. +.El +.Pp +When transport functions are specified, +.Em libfido2 +will use them instead of the +.Dv read +and +.Dv write +functions of the I/O handlers. +However, the I/O handlers must still be specified to open and close the +device. +.Pp +The +.Fn fido_dev_io_handle +function returns the opaque pointer returned by the +.Dv open +function of the I/O handlers. +This is useful mainly for the transport functions, which unlike the I/O +handlers are passed the +.Vt fido_dev_t +pointer instead of the opaque I/O handle. +.Sh RETURN VALUES +On success, +.Fn fido_dev_set_io_functions , +.Fn fido_dev_set_transport_functions , +.Fn fido_dev_set_sigmask , +and +.Fn fido_dev_set_timeout +return +.Dv FIDO_OK . +On error, a different error code defined in +.In fido/err.h +is returned. +.Sh SEE ALSO +.Xr fido_dev_info_manifest 3 , +.Xr fido_dev_open 3 +.Rs +.%D 2021-06-15 +.%O Proposed Standard, Version 2.1 +.%Q FIDO Alliance +.%R Client to Authenticator Protocol (CTAP) +.%U https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html +.Re diff --git a/man/fido_dev_set_pin.3 b/man/fido_dev_set_pin.3 new file mode 100644 index 0000000..eec062d --- /dev/null +++ b/man/fido_dev_set_pin.3 @@ -0,0 +1,128 @@ +.\" Copyright (c) 2018 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: May 25 2018 $ +.Dt FIDO_DEV_SET_PIN 3 +.Os +.Sh NAME +.Nm fido_dev_set_pin , +.Nm fido_dev_get_retry_count , +.Nm fido_dev_get_uv_retry_count , +.Nm fido_dev_reset +.Nd FIDO2 device management functions +.Sh SYNOPSIS +.In fido.h +.Ft int +.Fn fido_dev_set_pin "fido_dev_t *dev" "const char *pin" "const char *oldpin" +.Ft int +.Fn fido_dev_get_retry_count "fido_dev_t *dev" "int *retries" +.Ft int +.Fn fido_dev_get_uv_retry_count "fido_dev_t *dev" "int *retries" +.Ft int +.Fn fido_dev_reset "fido_dev_t *dev" +.Sh DESCRIPTION +The +.Fn fido_dev_set_pin +function sets the PIN of device +.Fa dev +to +.Fa pin , +where +.Fa pin +is a NUL-terminated UTF-8 string. +If +.Fa oldpin +is not NULL, the device's PIN is changed from +.Fa oldpin +to +.Fa pin , +where +.Fa pin +and +.Fa oldpin +are NUL-terminated UTF-8 strings. +.Pp +The +.Fn fido_dev_get_retry_count +function fills +.Fa retries +with the number of PIN retries left in +.Fa dev +before lock-out, where +.Fa retries +is an addressable pointer. +.Pp +The +.Fn fido_dev_get_uv_retry_count +function fills +.Fa retries +with the number of built-in UV retries left in +.Fa dev +before built-in UV is disabled, where +.Fa retries +is an addressable pointer. +.Pp +The +.Fn fido_dev_reset +function performs a reset on +.Fa dev , +resetting the device's PIN and erasing credentials stored on the +device. +.Pp +Please note that +.Fn fido_dev_set_pin , +.Fn fido_dev_get_retry_count , +.Fn fido_dev_get_uv_retry_count , +and +.Fn fido_dev_reset +are synchronous and will block if necessary. +.Sh RETURN VALUES +The error codes returned by +.Fn fido_dev_set_pin , +.Fn fido_dev_get_retry_count , +.Fn fido_dev_get_uv_retry_count , +and +.Fn fido_dev_reset +are defined in +.In fido/err.h . +On success, +.Dv FIDO_OK +is returned. +.Sh SEE ALSO +.Xr fido_cbor_info_uv_attempts 3 +.Sh CAVEATS +Regarding +.Fn fido_dev_reset , +the actual user-flow to perform a reset is outside the scope of the +FIDO2 specification, and may therefore vary depending on the +authenticator. +Yubico authenticators will return +.Dv FIDO_ERR_NOT_ALLOWED +if a reset is issued later than 5 seconds after power-up, and +.Dv FIDO_ERR_ACTION_TIMEOUT +if the user fails to confirm the reset by touching the key +within 30 seconds. diff --git a/man/fido_init.3 b/man/fido_init.3 new file mode 100644 index 0000000..12437e1 --- /dev/null +++ b/man/fido_init.3 @@ -0,0 +1,95 @@ +.\" Copyright (c) 2018 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: May 25 2018 $ +.Dt FIDO_INIT 3 +.Os +.Sh NAME +.Nm fido_init , +.Nm fido_set_log_handler +.Nd initialise the FIDO2 library +.Sh SYNOPSIS +.In fido.h +.Bd -literal +typedef void fido_log_handler_t(const char *); +.Ed +.Pp +.Ft void +.Fn fido_init "int flags" +.Ft void +.Fn fido_set_log_handler "fido_log_handler_t *handler" +.Sh DESCRIPTION +The +.Fn fido_init +function initialises the +.Em libfido2 +library. +Its invocation must precede that of any other +.Em libfido2 +function in the context of the executing thread. +.Pp +If +.Dv FIDO_DEBUG +is set in +.Fa flags , +then +debug output will be emitted by +.Em libfido2 +on +.Em stderr . +Alternatively, the +.Ev FIDO_DEBUG +environment variable may be set. +.Pp +If +.Dv FIDO_DISABLE_U2F_FALLBACK +is set in +.Fa flags , +then +.Em libfido2 +will not fallback to U2F in +.Xr fido_dev_open 3 +if a device claims to support FIDO2 but fails to respond to +a CTAP 2.0 greeting. +.Pp +The +.Fn fido_set_log_handler +function causes +.Fa handler +to be called for each log line generated in the context of the +executing thread. +Lines passed to +.Fa handler +include a trailing newline character and are not printed by +.Em libfido2 +on +.Em stderr . +.Sh SEE ALSO +.Xr fido_assert_new 3 , +.Xr fido_cred_new 3 , +.Xr fido_dev_info_manifest 3 , +.Xr fido_dev_open 3 diff --git a/man/fido_strerr.3 b/man/fido_strerr.3 new file mode 100644 index 0000000..94b48bd --- /dev/null +++ b/man/fido_strerr.3 @@ -0,0 +1,50 @@ +.\" Copyright (c) 2018 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: May 25 2018 $ +.Dt FIDO_STRERR 3 +.Os +.Sh NAME +.Nm fido_strerr +.Nd FIDO2 error codes +.Sh SYNOPSIS +.In fido.h +.Ft const char * +.Fn fido_strerr "int n" +.Sh DESCRIPTION +The +.Fn fido_strerr +function translates the error code +.Fa n +into a readable string, +where +.Fa n +is an error code defined in +.In fido/err.h . +.Fn fido_strerr +never returns NULL. +Returned pointers point to static strings. diff --git a/man/rs256_pk_new.3 b/man/rs256_pk_new.3 new file mode 100644 index 0000000..0c0ab78 --- /dev/null +++ b/man/rs256_pk_new.3 @@ -0,0 +1,160 @@ +.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd $Mdocdate: July 15 2022 $ +.Dt RS256_PK_NEW 3 +.Os +.Sh NAME +.Nm rs256_pk_new , +.Nm rs256_pk_free , +.Nm rs256_pk_from_RSA , +.Nm rs256_pk_from_EVP_PKEY , +.Nm rs256_pk_from_ptr , +.Nm rs256_pk_to_EVP_PKEY +.Nd FIDO2 COSE RS256 API +.Sh SYNOPSIS +.In openssl/rsa.h +.In fido/rs256.h +.Ft rs256_pk_t * +.Fn rs256_pk_new "void" +.Ft void +.Fn rs256_pk_free "rs256_pk_t **pkp" +.Ft int +.Fn rs256_pk_from_EVP_PKEY "rs256_pk_t *pk" "const EVP_PKEY *pkey" +.Ft int +.Fn rs256_pk_from_RSA "rs256_pk_t *pk" "const RSA *rsa" +.Ft int +.Fn rs256_pk_from_ptr "rs256_pk_t *pk" "const void *ptr" "size_t len" +.Ft EVP_PKEY * +.Fn rs256_pk_to_EVP_PKEY "const rs256_pk_t *pk" +.Sh DESCRIPTION +RS256 is the name given in the CBOR Object Signing and Encryption +(COSE) RFC to PKCS#1.5 2048-bit RSA with SHA-256. +The COSE RS256 API of +.Em libfido2 +is an auxiliary API with routines to convert between the different +RSA public key types used in +.Em libfido2 +and +.Em OpenSSL . +.Pp +In +.Em libfido2 , +RS256 public keys are abstracted by the +.Vt rs256_pk_t +type. +.Pp +The +.Fn rs256_pk_new +function returns a pointer to a newly allocated, empty +.Vt rs256_pk_t +type. +If memory cannot be allocated, NULL is returned. +.Pp +The +.Fn rs256_pk_free +function releases the memory backing +.Fa *pkp , +where +.Fa *pkp +must have been previously allocated by +.Fn rs256_pk_new . +On return, +.Fa *pkp +is set to NULL. +Either +.Fa pkp +or +.Fa *pkp +may be NULL, in which case +.Fn rs256_pk_free +is a NOP. +.Pp +The +.Fn rs256_pk_from_EVP_PKEY +function fills +.Fa pk +with the contents of +.Fa pkey . +No references to +.Fa pkey +are kept. +.Pp +The +.Fn rs256_pk_from_RSA +function fills +.Fa pk +with the contents of +.Fa rsa . +No references to +.Fa rsa +are kept. +.Pp +The +.Fn rs256_pk_from_ptr +function fills +.Fa pk +with the contents of +.Fa ptr , +where +.Fa ptr +points to +.Fa len +bytes. +No references to +.Fa ptr +are kept. +.Pp +The +.Fn rs256_pk_to_EVP_PKEY +function converts +.Fa pk +to a newly allocated +.Fa EVP_PKEY +type with a reference count of 1. +No internal references to the returned pointer are kept. +If an error occurs, +.Fn rs256_pk_to_EVP_PKEY +returns NULL. +.Sh RETURN VALUES +The +.Fn rs256_pk_from_EVP_PKEY , +.Fn rs256_pk_from_RSA , +and +.Fn rs256_pk_from_ptr +functions return +.Dv FIDO_OK +on success. +On error, a different error code defined in +.In fido/err.h +is returned. +.Sh SEE ALSO +.Xr eddsa_pk_new 3 , +.Xr es256_pk_new 3 , +.Xr es384_pk_new 3 , +.Xr fido_assert_verify 3 , +.Xr fido_cred_pubkey_ptr 3 diff --git a/man/style.css b/man/style.css new file mode 100644 index 0000000..8c223fa --- /dev/null +++ b/man/style.css @@ -0,0 +1,24 @@ +* { margin: 0; padding: 0; } + +body { + font-family: monospace; + font-size: 1em; + margin: 2% auto; + max-width: 54em; +} + +ul { margin-left: 1em; } +a { color: #009900; } +.Sh { font-size: 1em; padding-top: 1em; padding-bottom: 1em; } +.foot { padding-top: 1em; } + +table.head, table.foot { width: 100%; } +td.head-rtitle, td.foot-os { text-align: right; } +td.head-vol { text-align: center; } +div.Pp { margin: 1ex 0ex; } +div.Nd, div.Bf, div.Op { display: inline; } +span.Pa, span.Ad { font-style: italic; } +span.Ms { font-weight: bold; } +dl.Bl-diag > dt { font-weight: bold; } +code.Nm, code.Fl, code.Cm, code.Ic, code.In, code.Fd, code.Fn, +code.Cd { font-weight: bold; font-family: inherit; } diff --git a/openbsd-compat/bsd-asprintf.c b/openbsd-compat/bsd-asprintf.c new file mode 100644 index 0000000..fbcb867 --- /dev/null +++ b/openbsd-compat/bsd-asprintf.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2004 Darren Tucker. + * + * Based originally on asprintf.c from OpenBSD: + * Copyright (c) 1997 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "openbsd-compat.h" + +#ifndef HAVE_ASPRINTF + +#include +#include /* for INT_MAX */ +#include +#include /* for vsnprintf */ +#include + +#define VA_COPY(dest, src) va_copy(dest, src) + +#define INIT_SZ 128 + +int +vasprintf(char **str, const char *fmt, va_list ap) +{ + int ret; + va_list ap2; + char *string, *newstr; + size_t len; + + if ((string = malloc(INIT_SZ)) == NULL) + goto fail; + + VA_COPY(ap2, ap); + ret = vsnprintf(string, INIT_SZ, fmt, ap2); + va_end(ap2); + if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */ + *str = string; + } else if (ret == INT_MAX || ret < 0) { /* Bad length */ + free(string); + goto fail; + } else { /* bigger than initial, realloc allowing for nul */ + len = (size_t)ret + 1; + if ((newstr = realloc(string, len)) == NULL) { + free(string); + goto fail; + } + VA_COPY(ap2, ap); + ret = vsnprintf(newstr, len, fmt, ap2); + va_end(ap2); + if (ret < 0 || (size_t)ret >= len) { /* failed with realloc'ed string */ + free(newstr); + goto fail; + } + *str = newstr; + } + return (ret); + +fail: + *str = NULL; + errno = ENOMEM; + return (-1); +} + +int asprintf(char **str, const char *fmt, ...) +{ + va_list ap; + int ret; + + *str = NULL; + va_start(ap, fmt); + ret = vasprintf(str, fmt, ap); + va_end(ap); + + return ret; +} +#endif diff --git a/openbsd-compat/bsd-getline.c b/openbsd-compat/bsd-getline.c new file mode 100644 index 0000000..52b44f7 --- /dev/null +++ b/openbsd-compat/bsd-getline.c @@ -0,0 +1,115 @@ +/* $NetBSD: getline.c,v 1.1.1.6 2015/01/02 20:34:27 christos Exp $ */ + +/* NetBSD: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* NETBSD ORIGINAL: external/bsd/file/dist/src/getline.c */ + +#include "openbsd-compat.h" + +#if 0 +#include "file.h" +#endif + +#if !HAVE_GETLINE +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +static ssize_t +getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) +{ + char *ptr, *eptr; + + + if (*buf == NULL || *bufsiz == 0) { + if ((*buf = malloc(BUFSIZ)) == NULL) + return -1; + *bufsiz = BUFSIZ; + } + + for (ptr = *buf, eptr = *buf + *bufsiz;;) { + int c = fgetc(fp); + if (c == -1) { + if (feof(fp)) { + ssize_t diff = (ssize_t)(ptr - *buf); + if (diff != 0) { + *ptr = '\0'; + return diff; + } + } + return -1; + } + *ptr++ = (char)c; + if (c == delimiter) { + *ptr = '\0'; + return ptr - *buf; + } + if (ptr + 2 >= eptr) { + char *nbuf; + size_t nbufsiz = *bufsiz * 2; + ssize_t d = ptr - *buf; + if ((nbuf = realloc(*buf, nbufsiz)) == NULL) + return -1; + *buf = nbuf; + *bufsiz = nbufsiz; + eptr = nbuf + nbufsiz; + ptr = nbuf + d; + } + } +} + +ssize_t +getline(char **buf, size_t *bufsiz, FILE *fp) +{ + return getdelim(buf, bufsiz, '\n', fp); +} + +#endif + +#ifdef TEST +int +main(int argc, char *argv[]) +{ + char *p = NULL; + ssize_t len; + size_t n = 0; + + while ((len = getline(&p, &n, stdin)) != -1) + (void)printf("%" SIZE_T_FORMAT "d %s", len, p); + free(p); + return 0; +} +#endif diff --git a/openbsd-compat/bsd-getpagesize.c b/openbsd-compat/bsd-getpagesize.c new file mode 100644 index 0000000..903bfc3 --- /dev/null +++ b/openbsd-compat/bsd-getpagesize.c @@ -0,0 +1,27 @@ +/* Placed in the public domain */ + +#include "openbsd-compat.h" + +#if !defined(HAVE_GETPAGESIZE) + +#ifdef HAVE_UNISTD_H +#include +#endif +#include + +int +getpagesize(void) +{ +#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) + long r = sysconf(_SC_PAGESIZE); + if (r > 0 && r < INT_MAX) + return (int)r; +#endif + /* + * This is at the lower end of common values and appropriate for + * our current use of getpagesize() in recallocarray(). + */ + return 4096; +} + +#endif /* !defined(HAVE_GETPAGESIZE) */ diff --git a/openbsd-compat/clock_gettime.c b/openbsd-compat/clock_gettime.c new file mode 100644 index 0000000..bbf978c --- /dev/null +++ b/openbsd-compat/clock_gettime.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "openbsd-compat.h" + +#if !defined(HAVE_CLOCK_GETTIME) + +#if _WIN32 +int +clock_gettime(clockid_t clock_id, struct timespec *tp) +{ + ULONGLONG ms; + + if (clock_id != CLOCK_MONOTONIC) { + errno = EINVAL; + return (-1); + } + + ms = GetTickCount64(); + tp->tv_sec = ms / 1000L; + tp->tv_nsec = (ms % 1000L) * 1000000L; + + return (0); +} +#else +#error "please provide an implementation of clock_gettime() for your platform" +#endif /* _WIN32 */ + +#endif /* !defined(HAVE_CLOCK_GETTIME) */ diff --git a/openbsd-compat/endian_win32.c b/openbsd-compat/endian_win32.c new file mode 100644 index 0000000..756c0cb --- /dev/null +++ b/openbsd-compat/endian_win32.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "openbsd-compat.h" + +#if defined(_WIN32) && !defined(HAVE_ENDIAN_H) + +/* + * Hopefully, if the endianness differs from the end result, the compiler + * optimizes these functions with some type of bswap instruction. Or, + * otherwise, to just return the input value unmodified. GCC and clang + * both does these optimization at least. This should be preferred over + * relying on some BYTE_ORDER macro, which may or may not be defined. + */ + +uint32_t +htole32(uint32_t in) +{ + uint32_t out = 0; + uint8_t *b = (uint8_t *)&out; + + b[0] = (uint8_t)((in >> 0) & 0xff); + b[1] = (uint8_t)((in >> 8) & 0xff); + b[2] = (uint8_t)((in >> 16) & 0xff); + b[3] = (uint8_t)((in >> 24) & 0xff); + + return (out); +} + +uint64_t +htole64(uint64_t in) +{ + uint64_t out = 0; + uint8_t *b = (uint8_t *)&out; + + b[0] = (uint8_t)((in >> 0) & 0xff); + b[1] = (uint8_t)((in >> 8) & 0xff); + b[2] = (uint8_t)((in >> 16) & 0xff); + b[3] = (uint8_t)((in >> 24) & 0xff); + b[4] = (uint8_t)((in >> 32) & 0xff); + b[5] = (uint8_t)((in >> 40) & 0xff); + b[6] = (uint8_t)((in >> 48) & 0xff); + b[7] = (uint8_t)((in >> 56) & 0xff); + + return (out); +} + +#endif /* WIN32 && !HAVE_ENDIAN_H */ diff --git a/openbsd-compat/err.h b/openbsd-compat/err.h new file mode 100644 index 0000000..394c7bb --- /dev/null +++ b/openbsd-compat/err.h @@ -0,0 +1,85 @@ +/* + * Public domain + * err.h compatibility shim + */ + +#ifndef _COMPAT_ERR_H +#define _COMPAT_ERR_H + +#if !defined(HAVE_ERR_H) + +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) +__declspec(noreturn) +#else +__attribute__((noreturn)) +#endif +static inline void +err(int eval, const char *fmt, ...) +{ + int sverrno = errno; + va_list ap; + + va_start(ap, fmt); + if (fmt != NULL) { + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": "); + } + va_end(ap); + fprintf(stderr, "%s\n", strerror(sverrno)); + exit(eval); +} + +#if defined(_MSC_VER) +__declspec(noreturn) +#else +__attribute__((noreturn)) +#endif +static inline void +errx(int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + if (fmt != NULL) + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + exit(eval); +} + +static inline void +warn(const char *fmt, ...) +{ + int sverrno = errno; + va_list ap; + + va_start(ap, fmt); + if (fmt != NULL) { + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": "); + } + va_end(ap); + fprintf(stderr, "%s\n", strerror(sverrno)); +} + +static inline void +warnx(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + if (fmt != NULL) + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +#endif /* !defined(HAVE_ERR_H) */ + +#endif /* _COMPAT_ERR_H */ diff --git a/openbsd-compat/explicit_bzero.c b/openbsd-compat/explicit_bzero.c new file mode 100644 index 0000000..ac64e69 --- /dev/null +++ b/openbsd-compat/explicit_bzero.c @@ -0,0 +1,57 @@ +/* OPENBSD ORIGINAL: lib/libc/string/explicit_bzero.c */ +/* $OpenBSD: explicit_bzero.c,v 1.1 2014/01/22 21:06:45 tedu Exp $ */ +/* + * Public domain. + * Written by Ted Unangst + */ + +#include "openbsd-compat.h" + +#if !defined(HAVE_EXPLICIT_BZERO) && !defined(_WIN32) + +#include + +/* + * explicit_bzero - don't let the compiler optimize away bzero + */ + +#ifdef HAVE_MEMSET_S + +void +explicit_bzero(void *p, size_t n) +{ + if (n == 0) + return; + (void)memset_s(p, n, 0, n); +} + +#else /* HAVE_MEMSET_S */ + +/* + * Indirect bzero through a volatile pointer to hopefully avoid + * dead-store optimisation eliminating the call. + */ +static void (* volatile ssh_bzero)(void *, size_t) = bzero; + +void +explicit_bzero(void *p, size_t n) +{ + if (n == 0) + return; + /* + * clang -fsanitize=memory needs to intercept memset-like functions + * to correctly detect memory initialisation. Make sure one is called + * directly since our indirection trick above successfully confuses it. + */ +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) + memset(p, 0, n); +# endif +#endif + + ssh_bzero(p, n); +} + +#endif /* HAVE_MEMSET_S */ + +#endif /* !defined(HAVE_EXPLICIT_BZERO) && !defined(_WIN32) */ diff --git a/openbsd-compat/explicit_bzero_win32.c b/openbsd-compat/explicit_bzero_win32.c new file mode 100644 index 0000000..8017aff --- /dev/null +++ b/openbsd-compat/explicit_bzero_win32.c @@ -0,0 +1,19 @@ +/* + * Public domain. + * Win32 explicit_bzero compatibility shim. + */ + +#include "openbsd-compat.h" + +#if !defined(HAVE_EXPLICIT_BZERO) && defined(_WIN32) + +#include +#include + +void +explicit_bzero(void *buf, size_t len) +{ + SecureZeroMemory(buf, len); +} + +#endif /* !defined(HAVE_EXPLICIT_BZERO) && defined(_WIN32) */ diff --git a/openbsd-compat/freezero.c b/openbsd-compat/freezero.c new file mode 100644 index 0000000..d1e0066 --- /dev/null +++ b/openbsd-compat/freezero.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "openbsd-compat.h" + +#ifndef HAVE_FREEZERO + +void +freezero(void *ptr, size_t sz) +{ + if (ptr == NULL) + return; + explicit_bzero(ptr, sz); + free(ptr); +} + +#endif /* HAVE_FREEZERO */ diff --git a/openbsd-compat/getopt.h b/openbsd-compat/getopt.h new file mode 100644 index 0000000..8eb1244 --- /dev/null +++ b/openbsd-compat/getopt.h @@ -0,0 +1,74 @@ +/* $OpenBSD: getopt.h,v 1.2 2008/06/26 05:42:04 ray Exp $ */ +/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _GETOPT_H_ +#define _GETOPT_H_ + +/* + * GNU-like getopt_long() and 4.4BSD getsubopt()/optreset extensions + */ +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +struct option { + /* name of long option */ + const char *name; + /* + * one of no_argument, required_argument, and optional_argument: + * whether option takes an argument + */ + int has_arg; + /* if not NULL, set *flag to val when option found */ + int *flag; + /* if flag not NULL, value to set *flag to; else return value */ + int val; +}; + +int getopt_long(int, char * const *, const char *, + const struct option *, int *); +int getopt_long_only(int, char * const *, const char *, + const struct option *, int *); +#ifndef _GETOPT_DEFINED_ +#define _GETOPT_DEFINED_ +int getopt(int, char * const *, const char *); +int getsubopt(char **, char * const *, char **); + +extern char *optarg; /* getopt(3) external variables */ +extern int opterr; +extern int optind; +extern int optopt; +extern int optreset; +extern char *suboptarg; /* getsubopt(3) external variable */ +#endif + +#endif /* !_GETOPT_H_ */ diff --git a/openbsd-compat/getopt_long.c b/openbsd-compat/getopt_long.c new file mode 100644 index 0000000..dabbb46 --- /dev/null +++ b/openbsd-compat/getopt_long.c @@ -0,0 +1,523 @@ +/* $OpenBSD: getopt_long.c,v 1.25 2011/03/05 22:10:11 guenther Exp $ */ +/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ + +/* + * Copyright (c) 2002 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* OPENBSD ORIGINAL: lib/libc/stdlib/getopt_long.c */ +#include "openbsd-compat.h" + +#if !defined(HAVE_GETOPT) + +#if 0 +#include +#include +#endif +#include +#include +#include +#include + +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ + +#define PRINT_ERROR ((opterr) && (*options != ':')) + +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ + +/* return values */ +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +#define EMSG "" + +static int getopt_internal(int, char * const *, const char *, + const struct option *, int *, int); +static int parse_long_options(char * const *, const char *, + const struct option *, int *, int); +static int gcd(int, int); +static void permute_args(int, int, int, char * const *); + +static char *place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ + +/* Error messages */ +static const char recargchar[] = "option requires an argument -- %c"; +static const char recargstring[] = "option requires an argument -- %s"; +static const char ambig[] = "ambiguous option -- %.*s"; +static const char noarg[] = "option doesn't take an argument -- %.*s"; +static const char illoptchar[] = "unknown option -- %c"; +static const char illoptstring[] = "unknown option -- %s"; + +/* + * Compute the greatest common divisor of a and b. + */ +static int +gcd(int a, int b) +{ + int c; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return (b); +} + +/* + * Exchange the block from nonopt_start to nonopt_end with the block + * from nonopt_end to opt_end (keeping the same order of arguments + * in each block). + */ +static void +permute_args(int panonopt_start, int panonopt_end, int opt_end, + char * const *nargv) +{ + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end+i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **) nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; + } + } +} + +/* + * parse_long_options -- + * Parse long options in argc/argv argument vector. + * Returns -1 if short_too is set and the option does not match long_options. + */ +static int +parse_long_options(char * const *nargv, const char *options, + const struct option *long_options, int *idx, int short_too) +{ + char *current_argv, *has_equal; + size_t current_argv_len; + int i, match; + + current_argv = place; + match = -1; + + optind++; + + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; + + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + break; + } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; + + if (match == -1) /* partial match */ + match = i; + else { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, + current_argv); + optopt = 0; + return (BADCH); + } + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return (BADARG); + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return (BADARG); + } + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); + } + if (PRINT_ERROR) + warnx(illoptstring, current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } else + return (long_options[match].val); +} + +/* + * getopt_internal -- + * Parse argc/argv argument vector. Called by user level routines. + */ +static int +getopt_internal(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx, int flags) +{ + char *oli; /* option letter list index */ + int optchar, short_too; + static int posixly_correct = -1; + + if (options == NULL) + return (-1); + + /* + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. + */ + if (optind == 0) + optind = optreset = 1; + + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + */ + if (posixly_correct == -1 || optreset) + posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); + if (*options == '-') + flags |= FLAG_ALLARGS; + else if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + if (*options == '+' || *options == '-') + options++; + + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; +start: + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + if (*(place = nargv[optind]) != '-' || + (place[1] == '\0' && strchr(options, '-') == NULL)) { + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return (INORDER); + } + if (!(flags & FLAG_PERMUTE)) { + /* + * If no permutation wanted, stop parsing + * at first non-option. + */ + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; + + /* + * If we have "-" do nothing, if "--" we are done. + */ + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } + + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; + if (*place == '-') + place++; /* --foo long option */ + else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ + + optchar = parse_long_options(nargv, options, long_options, + idx, short_too); + if (optchar != -1) { + place = EMSG; + return (optchar); + } + } + + if ((optchar = (int)*place++) == (int)':' || + (optchar == (int)'-' && *place != '\0') || + (oli = strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; + if (PRINT_ERROR) + warnx(illoptchar, optchar); + optopt = optchar; + return (BADCH); + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else /* white space */ + place = nargv[optind]; + optchar = parse_long_options(nargv, options, long_options, + idx, 0); + place = EMSG; + return (optchar); + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = place; + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); +} + +/* + * getopt -- + * Parse argc/argv argument vector. + * + * [eventually this will replace the BSD getopt] + */ +int +getopt(int nargc, char * const *nargv, const char *options) +{ + + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); +} + +#if 0 +/* + * getopt_long -- + * Parse argc/argv argument vector. + */ +int +getopt_long(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE)); +} + +/* + * getopt_long_only -- + * Parse argc/argv argument vector. + */ +int +getopt_long_only(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE|FLAG_LONGONLY)); +} +#endif + +#endif /* !defined(HAVE_GETOPT) */ diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h new file mode 100644 index 0000000..9f1ea3e --- /dev/null +++ b/openbsd-compat/openbsd-compat.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2018-2021 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _OPENBSD_COMPAT_H +#define _OPENBSD_COMPAT_H + +#if defined(_MSC_VER) +#include "types.h" +#endif + +#if defined(HAVE_ENDIAN_H) +#include +#endif + +#if defined(__APPLE__) && !defined(HAVE_ENDIAN_H) +#include +#define be16toh(x) OSSwapBigToHostInt16((x)) +#define htobe16(x) OSSwapHostToBigInt16((x)) +#define be32toh(x) OSSwapBigToHostInt32((x)) +#define htobe32(x) OSSwapHostToBigInt32((x)) +#define htole32(x) OSSwapHostToLittleInt32((x)) +#define htole64(x) OSSwapHostToLittleInt64((x)) +#endif /* __APPLE__ && !HAVE_ENDIAN_H */ + +#if defined(_WIN32) && !defined(HAVE_ENDIAN_H) +#include +#include +#if !defined(_MSC_VER) +#include +#endif +#define be16toh(x) ntohs((x)) +#define htobe16(x) htons((x)) +#define be32toh(x) ntohl((x)) +#define htobe32(x) htonl((x)) +uint32_t htole32(uint32_t); +uint64_t htole64(uint64_t); +#endif /* _WIN32 && !HAVE_ENDIAN_H */ + +#if (defined(__FreeBSD__) || defined(__MidnightBSD__)) && !defined(HAVE_ENDIAN_H) +#include +#endif + +#include +#include + +#if !defined(HAVE_STRLCAT) +size_t strlcat(char *, const char *, size_t); +#endif + +#if !defined(HAVE_STRLCPY) +size_t strlcpy(char *, const char *, size_t); +#endif + +#if !defined(HAVE_STRSEP) +char *strsep(char **, const char *); +#endif + +#if !defined(HAVE_RECALLOCARRAY) +void *recallocarray(void *, size_t, size_t, size_t); +#endif + +#if !defined(HAVE_EXPLICIT_BZERO) +void explicit_bzero(void *, size_t); +#endif + +#if !defined(HAVE_FREEZERO) +void freezero(void *, size_t); +#endif + +#if !defined(HAVE_GETPAGESIZE) +int getpagesize(void); +#endif + +#if !defined(HAVE_TIMINGSAFE_BCMP) +int timingsafe_bcmp(const void *, const void *, size_t); +#endif + +#if !defined(HAVE_READPASSPHRASE) +#include "readpassphrase.h" +#else +#include +#endif + +#include + +#if !defined(HAVE_ERR_H) +#include "err.h" +#else +#include +#endif + +#if !defined(HAVE_GETOPT) +#include "getopt.h" +#else +#include +#endif + +#if !defined(HAVE_GETLINE) +#include +ssize_t getline(char **, size_t *, FILE *); +#endif + +#if defined(_MSC_VER) +#define strerror_r(e, b, l) strerror_s((b), (l), (e)) +#endif + +#include "time.h" + +#if !defined(HAVE_POSIX_IOCTL) +#define IOCTL_REQ(x) (x) +#else +#define IOCTL_REQ(x) ((int)(x)) +#endif + +#if !defined(HAVE_ASPRINTF) +int asprintf(char **, const char *, ...); +#endif + +#endif /* !_OPENBSD_COMPAT_H */ diff --git a/openbsd-compat/posix_ioctl_check.c b/openbsd-compat/posix_ioctl_check.c new file mode 100644 index 0000000..599a3bf --- /dev/null +++ b/openbsd-compat/posix_ioctl_check.c @@ -0,0 +1,7 @@ +#include + +int +posix_ioctl_check(int fd) +{ + return ioctl(fd, -1, 0); +} diff --git a/openbsd-compat/posix_win.c b/openbsd-compat/posix_win.c new file mode 100644 index 0000000..eac67c2 --- /dev/null +++ b/openbsd-compat/posix_win.c @@ -0,0 +1,61 @@ +/* + * Public domain + * + * File IO compatibility shims + * Brent Cook + */ + +#define NO_REDEF_POSIX_FUNCTIONS + +#include + +#include +#include + +#include "posix_win.h" + +int +posix_open(const char *path, ...) +{ + va_list ap; + int mode = 0; + int flags; + + va_start(ap, path); + flags = va_arg(ap, int); + if (flags & O_CREAT) + mode = va_arg(ap, int); + va_end(ap); + + flags |= O_BINARY | O_NOINHERIT; + + return (open(path, flags, mode)); +} + +int +posix_close(int fd) +{ + return (close(fd)); +} + +ssize_t +posix_read(int fd, void *buf, size_t count) +{ + if (count > INT_MAX) { + errno = EINVAL; + return (-1); + } + + return (read(fd, buf, (unsigned int)count)); +} + +ssize_t +posix_write(int fd, const void *buf, size_t count) +{ + if (count > INT_MAX) { + errno = EINVAL; + return (-1); + } + + return (write(fd, buf, (unsigned int)count)); +} diff --git a/openbsd-compat/posix_win.h b/openbsd-compat/posix_win.h new file mode 100644 index 0000000..a1e0888 --- /dev/null +++ b/openbsd-compat/posix_win.h @@ -0,0 +1,47 @@ +/* + * Public domain + * + * BSD socket emulation code for Winsock2 + * Brent Cook + */ + +#ifndef _COMPAT_POSIX_WIN_H +#define _COMPAT_POSIX_WIN_H + +#ifdef _WIN32 + +#include + +#include +#include +#include +#include +#include +#include + +#if _MSC_VER >= 1900 +#include <../ucrt/fcntl.h> +#else +#include <../include/fcntl.h> +#endif + +#include "types.h" + +int posix_open(const char *path, ...); + +int posix_close(int fd); + +ssize_t posix_read(int fd, void *buf, size_t count); + +ssize_t posix_write(int fd, const void *buf, size_t count); + +#ifndef NO_REDEF_POSIX_FUNCTIONS +#define open(path, ...) posix_open(path, __VA_ARGS__) +#define close(fd) posix_close(fd) +#define read(fd, buf, count) posix_read(fd, buf, count) +#define write(fd, buf, count) posix_write(fd, buf, count) +#endif + +#endif /* _WIN32 */ + +#endif /* !_COMPAT_POSIX_WIN_H */ diff --git a/openbsd-compat/readpassphrase.c b/openbsd-compat/readpassphrase.c new file mode 100644 index 0000000..8b84190 --- /dev/null +++ b/openbsd-compat/readpassphrase.c @@ -0,0 +1,214 @@ +/* $OpenBSD: readpassphrase.c,v 1.26 2016/10/18 12:47:18 millert Exp $ */ + +/* + * Copyright (c) 2000-2002, 2007, 2010 + * Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +/* OPENBSD ORIGINAL: lib/libc/gen/readpassphrase.c */ + +#include "openbsd-compat.h" + +#ifndef HAVE_READPASSPHRASE + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include + +#ifndef _PATH_TTY +# define _PATH_TTY "/dev/tty" +#endif + +#ifndef TCSASOFT +/* If we don't have TCSASOFT define it so that ORing it it below is a no-op. */ +# define TCSASOFT 0 +#endif + +/* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */ +#if !defined(_POSIX_VDISABLE) && defined(VDISABLE) +# define _POSIX_VDISABLE VDISABLE +#endif + +static volatile sig_atomic_t signo[NSIG]; + +static void handler(int); + +char * +readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) +{ + ssize_t nr; + int input, output, save_errno, i, need_restart; + char ch, *p, *end; + struct termios term, oterm; + struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm; + struct sigaction savetstp, savettin, savettou, savepipe; + + /* I suppose we could alloc on demand in this case (XXX). */ + if (bufsiz == 0) { + errno = EINVAL; + return(NULL); + } + +restart: + for (i = 0; i < NSIG; i++) + signo[i] = 0; + need_restart = 0; + /* + * Read and write to /dev/tty if available. If not, read from + * stdin and write to stderr unless a tty is required. + */ + if ((flags & RPP_STDIN) || + (input = output = open(_PATH_TTY, O_RDWR)) == -1) { + if (flags & RPP_REQUIRE_TTY) { + errno = ENOTTY; + return(NULL); + } + input = STDIN_FILENO; + output = STDERR_FILENO; + } + + /* + * Turn off echo if possible. + * If we are using a tty but are not the foreground pgrp this will + * generate SIGTTOU, so do it *before* installing the signal handlers. + */ + if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) { + memcpy(&term, &oterm, sizeof(term)); + if (!(flags & RPP_ECHO_ON)) + term.c_lflag &= ~(ECHO | ECHONL); +#ifdef VSTATUS + if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) + term.c_cc[VSTATUS] = _POSIX_VDISABLE; +#endif + (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term); + } else { + memset(&term, 0, sizeof(term)); + term.c_lflag |= ECHO; + memset(&oterm, 0, sizeof(oterm)); + oterm.c_lflag |= ECHO; + } + + /* + * Catch signals that would otherwise cause the user to end + * up with echo turned off in the shell. Don't worry about + * things like SIGXCPU and SIGVTALRM for now. + */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; /* don't restart system calls */ + sa.sa_handler = handler; + (void)sigaction(SIGALRM, &sa, &savealrm); + (void)sigaction(SIGHUP, &sa, &savehup); + (void)sigaction(SIGINT, &sa, &saveint); + (void)sigaction(SIGPIPE, &sa, &savepipe); + (void)sigaction(SIGQUIT, &sa, &savequit); + (void)sigaction(SIGTERM, &sa, &saveterm); + (void)sigaction(SIGTSTP, &sa, &savetstp); + (void)sigaction(SIGTTIN, &sa, &savettin); + (void)sigaction(SIGTTOU, &sa, &savettou); + + if (!(flags & RPP_STDIN)) + (void)write(output, prompt, strlen(prompt)); + end = buf + bufsiz - 1; + p = buf; + while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') { + if (p < end) { + if ((flags & RPP_SEVENBIT)) + ch &= 0x7f; + if (isalpha((unsigned char)ch)) { + if ((flags & RPP_FORCELOWER)) + ch = (char)tolower((unsigned char)ch); + if ((flags & RPP_FORCEUPPER)) + ch = (char)toupper((unsigned char)ch); + } + *p++ = ch; + } + } + *p = '\0'; + save_errno = errno; + if (!(term.c_lflag & ECHO)) + (void)write(output, "\n", 1); + + /* Restore old terminal settings and signals. */ + if (memcmp(&term, &oterm, sizeof(term)) != 0) { + const int sigttou = signo[SIGTTOU]; + + /* Ignore SIGTTOU generated when we are not the fg pgrp. */ + while (tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm) == -1 && + errno == EINTR && !signo[SIGTTOU]) + continue; + signo[SIGTTOU] = sigttou; + } + (void)sigaction(SIGALRM, &savealrm, NULL); + (void)sigaction(SIGHUP, &savehup, NULL); + (void)sigaction(SIGINT, &saveint, NULL); + (void)sigaction(SIGQUIT, &savequit, NULL); + (void)sigaction(SIGPIPE, &savepipe, NULL); + (void)sigaction(SIGTERM, &saveterm, NULL); + (void)sigaction(SIGTSTP, &savetstp, NULL); + (void)sigaction(SIGTTIN, &savettin, NULL); + (void)sigaction(SIGTTOU, &savettou, NULL); + if (input != STDIN_FILENO) + (void)close(input); + + /* + * If we were interrupted by a signal, resend it to ourselves + * now that we have restored the signal handlers. + */ + for (i = 0; i < NSIG; i++) { + if (signo[i]) { + kill(getpid(), i); + switch (i) { + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + need_restart = 1; + } + } + } + if (need_restart) + goto restart; + + if (save_errno) + errno = save_errno; + return(nr == -1 ? NULL : buf); +} + +#if 0 +char * +getpass(const char *prompt) +{ + static char buf[_PASSWORD_LEN + 1]; + + return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF)); +} +#endif + +static void handler(int s) +{ + + signo[s] = 1; +} +#endif /* HAVE_READPASSPHRASE */ diff --git a/openbsd-compat/readpassphrase.h b/openbsd-compat/readpassphrase.h new file mode 100644 index 0000000..e4451f3 --- /dev/null +++ b/openbsd-compat/readpassphrase.h @@ -0,0 +1,44 @@ +/* $OpenBSD: readpassphrase.h,v 1.5 2003/06/17 21:56:23 millert Exp $ */ + +/* + * Copyright (c) 2000, 2002 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +/* OPENBSD ORIGINAL: include/readpassphrase.h */ + +#ifndef _READPASSPHRASE_H_ +#define _READPASSPHRASE_H_ + +#ifndef HAVE_READPASSPHRASE + +#include + +#define RPP_ECHO_OFF 0x00 /* Turn off echo (default). */ +#define RPP_ECHO_ON 0x01 /* Leave echo on. */ +#define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */ +#define RPP_FORCELOWER 0x04 /* Force input to lower case. */ +#define RPP_FORCEUPPER 0x08 /* Force input to upper case. */ +#define RPP_SEVENBIT 0x10 /* Strip the high bit from input. */ +#define RPP_STDIN 0x20 /* Read from stdin, not /dev/tty */ + +char * readpassphrase(const char *, char *, size_t, int); + +#endif /* HAVE_READPASSPHRASE */ + +#endif /* !_READPASSPHRASE_H_ */ diff --git a/openbsd-compat/readpassphrase_win32.c b/openbsd-compat/readpassphrase_win32.c new file mode 100644 index 0000000..968987c --- /dev/null +++ b/openbsd-compat/readpassphrase_win32.c @@ -0,0 +1,131 @@ +/* +* Author: Manoj Ampalam +* +* Author: Bryan Berns +* Modified group detection use s4u token information +* +* Copyright(c) 2016 Microsoft Corp. +* All rights reserved +* +* Misc Unix POSIX routine implementations for Windows +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met : +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and / or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define UMDF_USING_NTSTATUS +#define SECURITY_WIN32 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "openbsd-compat.h" + +#ifndef HAVE_READPASSPHRASE + +/*on error returns NULL and sets errno*/ +static wchar_t * +utf8_to_utf16(const char *utf8) +{ + int needed = 0; + wchar_t* utf16 = NULL; + if ((needed = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0)) == 0 || + (utf16 = malloc(needed * sizeof(wchar_t))) == NULL || + MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, needed) == 0) { + /* debug3("failed to convert utf8 payload:%s error:%d", utf8, GetLastError()); */ + errno = ENOMEM; + return NULL; + } + + return utf16; +} + +char * +readpassphrase(const char *prompt, char *outBuf, size_t outBufLen, int flags) +{ + size_t current_index = 0; + char ch; + wchar_t* wtmp = NULL; + + if (outBufLen == 0) { + errno = EINVAL; + return NULL; + } + + while (_kbhit()) (void)_getch(); + + wtmp = utf8_to_utf16(prompt); + if (wtmp == NULL) + errx(1, "unable to alloc memory"); + + _cputws(wtmp); + free(wtmp); + + while (current_index < outBufLen - 1) { + ch = (char)_getch(); + + if (ch == '\r') { + if (_kbhit()) (void)_getch(); /* read linefeed if its there */ + break; + } else if (ch == '\n') { + break; + } else if (ch == '\b') { /* backspace */ + if (current_index > 0) { + if (flags & RPP_ECHO_ON) + printf_s("%c \b", ch); + + current_index--; /* overwrite last character */ + } + } else if (ch == '\003') { /* exit on Ctrl+C */ + errx(1, ""); + } else { + if (flags & RPP_SEVENBIT) + ch &= 0x7f; + + if (isalpha((unsigned char)ch)) { + if(flags & RPP_FORCELOWER) + ch = (char)tolower((unsigned char)ch); + if(flags & RPP_FORCEUPPER) + ch = (char)toupper((unsigned char)ch); + } + + outBuf[current_index++] = ch; + if(flags & RPP_ECHO_ON) + printf_s("%c", ch); + } + } + + outBuf[current_index] = '\0'; + _cputs("\n"); + + return outBuf; +} + +#endif /* HAVE_READPASSPHRASE */ diff --git a/openbsd-compat/recallocarray.c b/openbsd-compat/recallocarray.c new file mode 100644 index 0000000..5d2f8d9 --- /dev/null +++ b/openbsd-compat/recallocarray.c @@ -0,0 +1,91 @@ +/* $OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $ */ +/* + * Copyright (c) 2008, 2017 Otto Moerbeek + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* OPENBSD ORIGINAL: lib/libc/stdlib/recallocarray.c */ + +#include "openbsd-compat.h" + +#if !defined(HAVE_RECALLOCARRAY) + +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +void * +recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size) +{ + size_t oldsize, newsize; + void *newptr; + + if (ptr == NULL) + return calloc(newnmemb, size); + + if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + newnmemb > 0 && SIZE_MAX / newnmemb < size) { + errno = ENOMEM; + return NULL; + } + newsize = newnmemb * size; + + if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + oldnmemb > 0 && SIZE_MAX / oldnmemb < size) { + errno = EINVAL; + return NULL; + } + oldsize = oldnmemb * size; + + /* + * Don't bother too much if we're shrinking just a bit, + * we do not shrink for series of small steps, oh well. + */ + if (newsize <= oldsize) { + size_t d = oldsize - newsize; + + if (d < oldsize / 2 && d < (size_t)getpagesize()) { + memset((char *)ptr + newsize, 0, d); + return ptr; + } + } + + newptr = malloc(newsize); + if (newptr == NULL) + return NULL; + + if (newsize > oldsize) { + memcpy(newptr, ptr, oldsize); + memset((char *)newptr + oldsize, 0, newsize - oldsize); + } else + memcpy(newptr, ptr, newsize); + + explicit_bzero(ptr, oldsize); + free(ptr); + + return newptr; +} +/* DEF_WEAK(recallocarray); */ + +#endif /* !defined(HAVE_RECALLOCARRAY) */ diff --git a/openbsd-compat/strlcat.c b/openbsd-compat/strlcat.c new file mode 100644 index 0000000..44470de --- /dev/null +++ b/openbsd-compat/strlcat.c @@ -0,0 +1,63 @@ +/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* OPENBSD ORIGINAL: lib/libc/string/strlcat.c */ + +#include "openbsd-compat.h" + +#if !defined(HAVE_STRLCAT) + +#include +#include + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} + +#endif /* !defined(HAVE_STRLCAT) */ diff --git a/openbsd-compat/strlcpy.c b/openbsd-compat/strlcpy.c new file mode 100644 index 0000000..a8b18ea --- /dev/null +++ b/openbsd-compat/strlcpy.c @@ -0,0 +1,59 @@ +/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* OPENBSD ORIGINAL: lib/libc/string/strlcpy.c */ + +#include "openbsd-compat.h" + +#if !defined(HAVE_STRLCPY) + +#include +#include + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} + +#endif /* !defined(HAVE_STRLCPY) */ diff --git a/openbsd-compat/strsep.c b/openbsd-compat/strsep.c new file mode 100644 index 0000000..578668c --- /dev/null +++ b/openbsd-compat/strsep.c @@ -0,0 +1,79 @@ +/* $OpenBSD: strsep.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* OPENBSD ORIGINAL: lib/libc/string/strsep.c */ + +#include "openbsd-compat.h" + +#if !defined(HAVE_STRSEP) + +#include +#include + +/* + * Get next token from string *stringp, where tokens are possibly-empty + * strings separated by characters from delim. + * + * Writes NULs into the string at *stringp to end tokens. + * delim need not remain constant from call to call. + * On return, *stringp points past the last NUL written (if there might + * be further tokens), or is NULL (if there are definitely no more tokens). + * + * If *stringp is NULL, strsep returns NULL. + */ +char * +strsep(char **stringp, const char *delim) +{ + char *s; + const char *spanp; + int c, sc; + char *tok; + + if ((s = *stringp) == NULL) + return (NULL); + for (tok = s;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *stringp = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} + +#endif /* !defined(HAVE_STRSEP) */ diff --git a/openbsd-compat/time.h b/openbsd-compat/time.h new file mode 100644 index 0000000..b125f73 --- /dev/null +++ b/openbsd-compat/time.h @@ -0,0 +1,61 @@ +/* + * Public domain + * sys/time.h compatibility shim + */ + +#if defined(_MSC_VER) && (_MSC_VER >= 1900) +#include <../ucrt/time.h> +#elif defined(_MSC_VER) && (_MSC_VER < 1900) +#include <../include/time.h> +#else +#include +#endif + +#ifndef _COMPAT_TIME_H +#define _COMPAT_TIME_H + +#ifndef CLOCK_MONOTONIC +#define CLOCK_MONOTONIC CLOCK_REALTIME +#endif + +#ifndef CLOCK_REALTIME +#define CLOCK_REALTIME 0 +#endif + +#ifndef HAVE_CLOCK_GETTIME +typedef int clockid_t; +int clock_gettime(clockid_t, struct timespec *); +#endif + +#ifdef HAVE_TIMESPECSUB +#include +#endif + +#ifndef HAVE_TIMESPECSUB +#define timespecadd(tsp, usp, vsp) \ + do { \ + (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \ + (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \ + if ((vsp)->tv_nsec >= 1000000000L) { \ + (vsp)->tv_sec++; \ + (vsp)->tv_nsec -= 1000000000L; \ + } \ + } while (0) + +#define timespecsub(tsp, usp, vsp) \ + do { \ + (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \ + (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \ + if ((vsp)->tv_nsec < 0) { \ + (vsp)->tv_sec--; \ + (vsp)->tv_nsec += 1000000000L; \ + } \ + } while (0) + +#define timespeccmp(tsp, usp, cmp) \ + (((tsp)->tv_sec == (usp)->tv_sec) ? \ + ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ + ((tsp)->tv_sec cmp (usp)->tv_sec)) +#endif + +#endif /* _COMPAT_TIME_H */ diff --git a/openbsd-compat/timingsafe_bcmp.c b/openbsd-compat/timingsafe_bcmp.c new file mode 100644 index 0000000..3f7b9e5 --- /dev/null +++ b/openbsd-compat/timingsafe_bcmp.c @@ -0,0 +1,35 @@ +/* $OpenBSD: timingsafe_bcmp.c,v 1.1 2010/09/24 13:33:00 matthew Exp $ */ +/* + * Copyright (c) 2010 Damien Miller. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* OPENBSD ORIGINAL: lib/libc/string/timingsafe_bcmp.c */ + +#include "openbsd-compat.h" + +#if !defined(HAVE_TIMINGSAFE_BCMP) + +int +timingsafe_bcmp(const void *b1, const void *b2, size_t n) +{ + const unsigned char *p1 = b1, *p2 = b2; + int ret = 0; + + for (; n > 0; n--) + ret |= *p1++ ^ *p2++; + return (ret != 0); +} + +#endif /* !defined(HAVE_TIMINGSAFE_BCMP) */ diff --git a/openbsd-compat/types.h b/openbsd-compat/types.h new file mode 100644 index 0000000..6170230 --- /dev/null +++ b/openbsd-compat/types.h @@ -0,0 +1,69 @@ +/* + * Public domain + * sys/types.h compatibility shim + */ + +#ifdef _MSC_VER +#if _MSC_VER >= 1900 +#include <../ucrt/sys/types.h> +#else +#include <../include/sys/types.h> +#endif +#endif + +#ifndef _COMPAT_TYPES_H +#define _COMPAT_TYPES_H + +#include + +#ifdef __MINGW32__ +#include <_bsd_types.h> +typedef uint32_t in_addr_t; +typedef uint32_t uid_t; +#endif + +#ifdef _MSC_VER +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; + +#include +typedef SSIZE_T ssize_t; + +#ifndef SSIZE_MAX +#ifdef _WIN64 +#define SSIZE_MAX _I64_MAX +#else +#define SSIZE_MAX INT_MAX +#endif +#endif + +#endif + +#if !defined(HAVE_ATTRIBUTE__BOUNDED__) && !defined(__bounded__) +# define __bounded__(x, y, z) +#endif + +#ifdef _WIN32 +#define __warn_references(sym,msg) +#else + +#ifndef __warn_references + +#ifndef __STRING +#define __STRING(x) #x +#endif + +#if defined(__GNUC__) && defined (HAS_GNU_WARNING_LONG) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) \ + "\n\t.ascii \"" msg "\"\n\t.text"); +#else +#define __warn_references(sym,msg) +#endif + +#endif /* __warn_references */ +#endif /* _WIN32 */ + +#endif /* !_COMPAT_TYPES_H */ diff --git a/regress/CMakeLists.txt b/regress/CMakeLists.txt new file mode 100644 index 0000000..246bffa --- /dev/null +++ b/regress/CMakeLists.txt @@ -0,0 +1,57 @@ +# Copyright (c) 2018-2022 Yubico AB. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. +# SPDX-License-Identifier: BSD-2-Clause + +add_custom_target(regress) + +macro(add_regress_test NAME SOURCES LIB) + add_executable(${NAME} ${SOURCES}) + add_test(${NAME} ${NAME}) + add_dependencies(regress ${NAME}) + target_link_libraries(${NAME} ${LIB}) +endmacro() + +if(MSVC AND BUILD_SHARED_LIBS) + add_custom_command(TARGET regress POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy + "${CBOR_BIN_DIRS}/${CBOR_LIBRARIES}.dll" + "${CRYPTO_BIN_DIRS}/${CRYPTO_LIBRARIES}.dll" + "${ZLIB_BIN_DIRS}/${ZLIB_LIBRARIES}.dll" + "$" + "${CMAKE_CURRENT_BINARY_DIR}") +endif() + +if(CYGWIN AND BUILD_SHARED_LIBS) + add_custom_command(TARGET regress POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy + "$" + "${CMAKE_CURRENT_BINARY_DIR}") +endif() + +if(CMAKE_CROSSCOMPILING OR (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64" AND + CMAKE_GENERATOR_PLATFORM MATCHES "^ARM.*$")) + add_custom_command(TARGET regress POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E echo + "Cross-compilation detected. Skipping regress tests.") +else() + add_custom_command(TARGET regress POST_BUILD + COMMAND "${CMAKE_CTEST_COMMAND}" --output-on-failure + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) +endif() + +add_regress_test(regress_assert assert.c ${_FIDO2_LIBRARY}) +add_regress_test(regress_cred cred.c ${_FIDO2_LIBRARY}) +add_regress_test(regress_dev dev.c ${_FIDO2_LIBRARY}) +add_regress_test(regress_eddsa eddsa.c ${_FIDO2_LIBRARY}) +add_regress_test(regress_es256 es256.c ${_FIDO2_LIBRARY}) +add_regress_test(regress_es384 es384.c ${_FIDO2_LIBRARY}) +add_regress_test(regress_rs256 rs256.c ${_FIDO2_LIBRARY}) +if(BUILD_STATIC_LIBS) + add_regress_test(regress_compress compress.c fido2) +endif() + +if(MINGW) + # needed for nanosleep() in mingw + target_link_libraries(regress_dev winpthread) +endif() diff --git a/regress/assert.c b/regress/assert.c new file mode 100644 index 0000000..ad31903 --- /dev/null +++ b/regress/assert.c @@ -0,0 +1,685 @@ +/* + * Copyright (c) 2018-2023 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + * SPDX-License-Identifier: BSD-2-Clause + */ + +#undef NDEBUG + +#include +#include + +#define _FIDO_INTERNAL + +#include +#include +#include +#include + +static int fake_dev_handle; + +static const unsigned char es256_pk[64] = { + 0x34, 0xeb, 0x99, 0x77, 0x02, 0x9c, 0x36, 0x38, + 0xbb, 0xc2, 0xae, 0xa0, 0xa0, 0x18, 0xc6, 0x64, + 0xfc, 0xe8, 0x49, 0x92, 0xd7, 0x74, 0x9e, 0x0c, + 0x46, 0x8c, 0x9d, 0xa6, 0xdf, 0x46, 0xf7, 0x84, + 0x60, 0x1e, 0x0f, 0x8b, 0x23, 0x85, 0x4a, 0x9a, + 0xec, 0xc1, 0x08, 0x9f, 0x30, 0xd0, 0x0d, 0xd7, + 0x76, 0x7b, 0x55, 0x48, 0x91, 0x7c, 0x4f, 0x0f, + 0x64, 0x1a, 0x1d, 0xf8, 0xbe, 0x14, 0x90, 0x8a, +}; + +static const unsigned char rs256_pk[259] = { + 0x9e, 0x54, 0x78, 0xb2, 0x51, 0xbe, 0x19, 0x7c, + 0xcb, 0x1a, 0x9a, 0xc3, 0x49, 0x2a, 0x2f, 0xfd, + 0x99, 0x64, 0x76, 0xc6, 0xdb, 0xca, 0x38, 0x3f, + 0xb0, 0x6a, 0xc9, 0xc0, 0x07, 0x9f, 0x5c, 0x4d, + 0xfc, 0xd1, 0x01, 0x7f, 0x69, 0x65, 0xab, 0x9c, + 0x2a, 0xc2, 0x95, 0xd9, 0x44, 0xf3, 0xea, 0x94, + 0x6b, 0x25, 0x66, 0x54, 0x81, 0xee, 0x24, 0x1d, + 0xe1, 0x7d, 0x7f, 0xbe, 0xea, 0x76, 0x90, 0x5c, + 0xbf, 0x59, 0x22, 0xd3, 0xa0, 0x68, 0x1a, 0x65, + 0x8b, 0x2f, 0xb6, 0xa8, 0x30, 0x2d, 0x26, 0x81, + 0xfa, 0x9e, 0x59, 0xec, 0x2f, 0xee, 0x59, 0x39, + 0xe2, 0x79, 0x19, 0x54, 0x54, 0xdf, 0x24, 0x83, + 0xee, 0x61, 0x5a, 0x66, 0x24, 0x2b, 0x7b, 0xfb, + 0x82, 0x66, 0xe4, 0x85, 0x18, 0x20, 0x76, 0xe5, + 0x4a, 0xb6, 0xcb, 0xec, 0x43, 0xbe, 0xfd, 0xb0, + 0x8f, 0xfd, 0x2f, 0x69, 0xda, 0x06, 0x9c, 0x09, + 0x68, 0x7a, 0x94, 0x6c, 0xb7, 0x51, 0x6d, 0x4c, + 0xf7, 0x13, 0xe8, 0xd5, 0x22, 0x6b, 0x1e, 0xba, + 0xb9, 0x85, 0xe8, 0x5f, 0xa1, 0x66, 0xe3, 0x20, + 0x75, 0x30, 0x11, 0xb5, 0xa3, 0xc3, 0xb0, 0x72, + 0x08, 0xff, 0xa3, 0xbb, 0xf1, 0x32, 0x0b, 0x06, + 0xc4, 0x12, 0xa3, 0x49, 0x30, 0x19, 0xb9, 0xfe, + 0x69, 0x0c, 0xd6, 0xe1, 0x58, 0x36, 0xe6, 0x41, + 0x22, 0x41, 0xbf, 0x96, 0x50, 0x35, 0x56, 0x0d, + 0x92, 0x8c, 0x34, 0xea, 0x28, 0x91, 0x88, 0x9e, + 0x8a, 0xaa, 0x36, 0xd0, 0x0f, 0xbe, 0x16, 0xde, + 0x9d, 0x5f, 0x7b, 0xda, 0x52, 0xf7, 0xf1, 0xb6, + 0x28, 0x10, 0x05, 0x8f, 0xb9, 0x19, 0x7a, 0xcf, + 0x18, 0x9b, 0x40, 0xcd, 0xff, 0x78, 0xea, 0x61, + 0x24, 0x3b, 0x80, 0x68, 0x04, 0x9b, 0x40, 0x07, + 0x98, 0xd4, 0x94, 0xd1, 0x18, 0x44, 0xa5, 0xed, + 0xee, 0x18, 0xc2, 0x25, 0x52, 0x66, 0x42, 0xdf, + 0x01, 0x00, 0x01, +}; + +static const unsigned char cdh[32] = { + 0xec, 0x8d, 0x8f, 0x78, 0x42, 0x4a, 0x2b, 0xb7, + 0x82, 0x34, 0xaa, 0xca, 0x07, 0xa1, 0xf6, 0x56, + 0x42, 0x1c, 0xb6, 0xf6, 0xb3, 0x00, 0x86, 0x52, + 0x35, 0x2d, 0xa2, 0x62, 0x4a, 0xbe, 0x89, 0x76, +}; + +static const unsigned char authdata[39] = { + 0x58, 0x25, 0x49, 0x96, 0x0d, 0xe5, 0x88, 0x0e, + 0x8c, 0x68, 0x74, 0x34, 0x17, 0x0f, 0x64, 0x76, + 0x60, 0x5b, 0x8f, 0xe4, 0xae, 0xb9, 0xa2, 0x86, + 0x32, 0xc7, 0x99, 0x5c, 0xf3, 0xba, 0x83, 0x1d, + 0x97, 0x63, 0x00, 0x00, 0x00, 0x00, 0x03, +}; + +static const unsigned char sig[72] = { + 0x30, 0x46, 0x02, 0x21, 0x00, 0xf6, 0xd1, 0xa3, + 0xd5, 0x24, 0x2b, 0xde, 0xee, 0xa0, 0x90, 0x89, + 0xcd, 0xf8, 0x9e, 0xbd, 0x6b, 0x4d, 0x55, 0x79, + 0xe4, 0xc1, 0x42, 0x27, 0xb7, 0x9b, 0x9b, 0xa4, + 0x0a, 0xe2, 0x47, 0x64, 0x0e, 0x02, 0x21, 0x00, + 0xe5, 0xc9, 0xc2, 0x83, 0x47, 0x31, 0xc7, 0x26, + 0xe5, 0x25, 0xb2, 0xb4, 0x39, 0xa7, 0xfc, 0x3d, + 0x70, 0xbe, 0xe9, 0x81, 0x0d, 0x4a, 0x62, 0xa9, + 0xab, 0x4a, 0x91, 0xc0, 0x7d, 0x2d, 0x23, 0x1e, +}; + +static void * +dummy_open(const char *path) +{ + (void)path; + + return (&fake_dev_handle); +} + +static void +dummy_close(void *handle) +{ + assert(handle == &fake_dev_handle); +} + +static int +dummy_read(void *handle, unsigned char *buf, size_t len, int ms) +{ + (void)handle; + (void)buf; + (void)len; + (void)ms; + + abort(); + /* NOTREACHED */ +} + +static int +dummy_write(void *handle, const unsigned char *buf, size_t len) +{ + (void)handle; + (void)buf; + (void)len; + + abort(); + /* NOTREACHED */ +} + +static fido_assert_t * +alloc_assert(void) +{ + fido_assert_t *a; + + a = fido_assert_new(); + assert(a != NULL); + + return (a); +} + +static void +free_assert(fido_assert_t *a) +{ + fido_assert_free(&a); + assert(a == NULL); +} + +static fido_dev_t * +alloc_dev(void) +{ + fido_dev_t *d; + + d = fido_dev_new(); + assert(d != NULL); + + return (d); +} + +static void +free_dev(fido_dev_t *d) +{ + fido_dev_free(&d); + assert(d == NULL); +} + +static es256_pk_t * +alloc_es256_pk(void) +{ + es256_pk_t *pk; + + pk = es256_pk_new(); + assert(pk != NULL); + + return (pk); +} + +static void +free_es256_pk(es256_pk_t *pk) +{ + es256_pk_free(&pk); + assert(pk == NULL); +} + +static rs256_pk_t * +alloc_rs256_pk(void) +{ + rs256_pk_t *pk; + + pk = rs256_pk_new(); + assert(pk != NULL); + + return (pk); +} + +static void +free_rs256_pk(rs256_pk_t *pk) +{ + rs256_pk_free(&pk); + assert(pk == NULL); +} + +static eddsa_pk_t * +alloc_eddsa_pk(void) +{ + eddsa_pk_t *pk; + + pk = eddsa_pk_new(); + assert(pk != NULL); + + return (pk); +} + +static void +free_eddsa_pk(eddsa_pk_t *pk) +{ + eddsa_pk_free(&pk); + assert(pk == NULL); +} + +static void +empty_assert(fido_dev_t *d, fido_assert_t *a, size_t idx) +{ + es256_pk_t *es256; + rs256_pk_t *rs256; + eddsa_pk_t *eddsa; + + assert(fido_assert_flags(a, idx) == 0); + assert(fido_assert_authdata_len(a, idx) == 0); + assert(fido_assert_authdata_ptr(a, idx) == NULL); + assert(fido_assert_authdata_raw_len(a, idx) == 0); + assert(fido_assert_authdata_raw_ptr(a, idx) == NULL); + assert(fido_assert_clientdata_hash_len(a) == 0); + assert(fido_assert_clientdata_hash_ptr(a) == NULL); + assert(fido_assert_id_len(a, idx) == 0); + assert(fido_assert_id_ptr(a, idx) == NULL); + assert(fido_assert_rp_id(a) == NULL); + assert(fido_assert_sig_len(a, idx) == 0); + assert(fido_assert_sig_ptr(a, idx) == NULL); + assert(fido_assert_user_display_name(a, idx) == NULL); + assert(fido_assert_user_icon(a, idx) == NULL); + assert(fido_assert_user_id_len(a, idx) == 0); + assert(fido_assert_user_id_ptr(a, idx) == NULL); + assert(fido_assert_user_name(a, idx) == NULL); + + es256 = alloc_es256_pk(); + rs256 = alloc_rs256_pk(); + eddsa = alloc_eddsa_pk(); + + fido_dev_force_u2f(d); + assert(fido_dev_get_assert(d, a, NULL) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_dev_get_assert(d, a, "") == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_assert_verify(a, idx, COSE_ES256, + NULL) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_assert_verify(a, idx, COSE_ES256, + es256) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_assert_verify(a, idx, -1, + es256) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_assert_verify(a, idx, COSE_RS256, + rs256) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_assert_verify(a, idx, COSE_EDDSA, + eddsa) == FIDO_ERR_INVALID_ARGUMENT); + + fido_dev_force_fido2(d); + assert(fido_dev_get_assert(d, a, NULL) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_dev_get_assert(d, a, "") == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_assert_verify(a, idx, COSE_ES256, + NULL) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_assert_verify(a, idx, COSE_ES256, + es256) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_assert_verify(a, idx, -1, + es256) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_assert_verify(a, idx, COSE_RS256, + rs256) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_assert_verify(a, idx, COSE_EDDSA, + eddsa) == FIDO_ERR_INVALID_ARGUMENT); + + free_es256_pk(es256); + free_rs256_pk(rs256); + free_eddsa_pk(eddsa); +} + +static void +empty_assert_tests(void) +{ + fido_assert_t *a; + fido_dev_t *d; + fido_dev_io_t io_f; + size_t i; + + memset(&io_f, 0, sizeof(io_f)); + + a = alloc_assert(); + d = alloc_dev(); + + io_f.open = dummy_open; + io_f.close = dummy_close; + io_f.read = dummy_read; + io_f.write = dummy_write; + + assert(fido_dev_set_io_functions(d, &io_f) == FIDO_OK); + + empty_assert(d, a, 0); + assert(fido_assert_count(a) == 0); + assert(fido_assert_set_count(a, 4) == FIDO_OK); + assert(fido_assert_count(a) == 4); + for (i = 0; i < 4; i++) { + empty_assert(d, a, i); + } + empty_assert(d, a, 10); + free_assert(a); + free_dev(d); +} + +static void +valid_assert(void) +{ + fido_assert_t *a; + es256_pk_t *es256; + rs256_pk_t *rs256; + eddsa_pk_t *eddsa; + + a = alloc_assert(); + es256 = alloc_es256_pk(); + rs256 = alloc_rs256_pk(); + eddsa = alloc_eddsa_pk(); + assert(es256_pk_from_ptr(es256, es256_pk, sizeof(es256_pk)) == FIDO_OK); + assert(fido_assert_set_clientdata_hash(a, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_assert_set_rp(a, "localhost") == FIDO_OK); + assert(fido_assert_set_count(a, 1) == FIDO_OK); + assert(fido_assert_set_authdata(a, 0, authdata, + sizeof(authdata)) == FIDO_OK); + assert(fido_assert_set_up(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_uv(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_sig(a, 0, sig, sizeof(sig)) == FIDO_OK); + assert(fido_assert_verify(a, 0, COSE_ES256, es256) == FIDO_OK); + assert(fido_assert_verify(a, 0, COSE_RS256, rs256) == FIDO_ERR_INVALID_SIG); + assert(fido_assert_verify(a, 0, COSE_EDDSA, eddsa) == FIDO_ERR_INVALID_SIG); + free_assert(a); + free_es256_pk(es256); + free_rs256_pk(rs256); + free_eddsa_pk(eddsa); +} + +static void +no_cdh(void) +{ + fido_assert_t *a; + es256_pk_t *pk; + + a = alloc_assert(); + pk = alloc_es256_pk(); + assert(es256_pk_from_ptr(pk, es256_pk, sizeof(es256_pk)) == FIDO_OK); + assert(fido_assert_set_rp(a, "localhost") == FIDO_OK); + assert(fido_assert_set_count(a, 1) == FIDO_OK); + assert(fido_assert_set_authdata(a, 0, authdata, + sizeof(authdata)) == FIDO_OK); + assert(fido_assert_set_up(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_uv(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_sig(a, 0, sig, sizeof(sig)) == FIDO_OK); + assert(fido_assert_verify(a, 0, COSE_ES256, + pk) == FIDO_ERR_INVALID_ARGUMENT); + free_assert(a); + free_es256_pk(pk); +} + +static void +no_rp(void) +{ + fido_assert_t *a; + es256_pk_t *pk; + + a = alloc_assert(); + pk = alloc_es256_pk(); + assert(es256_pk_from_ptr(pk, es256_pk, sizeof(es256_pk)) == FIDO_OK); + assert(fido_assert_set_clientdata_hash(a, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_assert_set_count(a, 1) == FIDO_OK); + assert(fido_assert_set_authdata(a, 0, authdata, + sizeof(authdata)) == FIDO_OK); + assert(fido_assert_set_up(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_uv(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_sig(a, 0, sig, sizeof(sig)) == FIDO_OK); + assert(fido_assert_verify(a, 0, COSE_ES256, + pk) == FIDO_ERR_INVALID_ARGUMENT); + free_assert(a); + free_es256_pk(pk); +} + +static void +no_authdata(void) +{ + fido_assert_t *a; + es256_pk_t *pk; + + a = alloc_assert(); + pk = alloc_es256_pk(); + assert(es256_pk_from_ptr(pk, es256_pk, sizeof(es256_pk)) == FIDO_OK); + assert(fido_assert_set_clientdata_hash(a, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_assert_set_rp(a, "localhost") == FIDO_OK); + assert(fido_assert_set_count(a, 1) == FIDO_OK); + assert(fido_assert_set_up(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_uv(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_sig(a, 0, sig, sizeof(sig)) == FIDO_OK); + assert(fido_assert_verify(a, 0, COSE_ES256, + pk) == FIDO_ERR_INVALID_ARGUMENT); + free_assert(a); + free_es256_pk(pk); +} + +static void +no_sig(void) +{ + fido_assert_t *a; + es256_pk_t *pk; + + a = alloc_assert(); + pk = alloc_es256_pk(); + assert(es256_pk_from_ptr(pk, es256_pk, sizeof(es256_pk)) == FIDO_OK); + assert(fido_assert_set_clientdata_hash(a, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_assert_set_rp(a, "localhost") == FIDO_OK); + assert(fido_assert_set_count(a, 1) == FIDO_OK); + assert(fido_assert_set_authdata(a, 0, authdata, + sizeof(authdata)) == FIDO_OK); + assert(fido_assert_set_up(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_uv(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_verify(a, 0, COSE_ES256, + pk) == FIDO_ERR_INVALID_ARGUMENT); + free_assert(a); + free_es256_pk(pk); +} + +static void +junk_cdh(void) +{ + fido_assert_t *a; + es256_pk_t *pk; + unsigned char *junk; + + junk = malloc(sizeof(cdh)); + assert(junk != NULL); + memcpy(junk, cdh, sizeof(cdh)); + junk[0] = (unsigned char)~junk[0]; + + a = alloc_assert(); + pk = alloc_es256_pk(); + assert(es256_pk_from_ptr(pk, es256_pk, sizeof(es256_pk)) == FIDO_OK); + assert(fido_assert_set_clientdata_hash(a, junk, sizeof(cdh)) == FIDO_OK); + assert(fido_assert_set_rp(a, "localhost") == FIDO_OK); + assert(fido_assert_set_count(a, 1) == FIDO_OK); + assert(fido_assert_set_authdata(a, 0, authdata, + sizeof(authdata)) == FIDO_OK); + assert(fido_assert_set_up(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_uv(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_sig(a, 0, sig, sizeof(sig)) == FIDO_OK); + assert(fido_assert_verify(a, 0, COSE_ES256, pk) == FIDO_ERR_INVALID_SIG); + free_assert(a); + free_es256_pk(pk); + free(junk); +} + +static void +junk_rp(void) +{ + fido_assert_t *a; + es256_pk_t *pk; + + a = alloc_assert(); + pk = alloc_es256_pk(); + assert(es256_pk_from_ptr(pk, es256_pk, sizeof(es256_pk)) == FIDO_OK); + assert(fido_assert_set_clientdata_hash(a, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_assert_set_rp(a, "potato") == FIDO_OK); + assert(fido_assert_set_count(a, 1) == FIDO_OK); + assert(fido_assert_set_authdata(a, 0, authdata, + sizeof(authdata)) == FIDO_OK); + assert(fido_assert_set_up(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_uv(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_sig(a, 0, sig, sizeof(sig)) == FIDO_OK); + assert(fido_assert_verify(a, 0, COSE_ES256, + pk) == FIDO_ERR_INVALID_PARAM); + free_assert(a); + free_es256_pk(pk); +} + +static void +junk_authdata(void) +{ + fido_assert_t *a; + unsigned char *junk; + + junk = malloc(sizeof(authdata)); + assert(junk != NULL); + memcpy(junk, authdata, sizeof(authdata)); + junk[0] = (unsigned char)~junk[0]; + + a = alloc_assert(); + assert(fido_assert_set_count(a, 1) == FIDO_OK); + assert(fido_assert_set_authdata(a, 0, junk, + sizeof(authdata)) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_assert_authdata_ptr(a, 0) == NULL); + assert(fido_assert_authdata_len(a, 0) == 0); + assert(fido_assert_authdata_raw_ptr(a, 0) == NULL); + assert(fido_assert_authdata_raw_len(a, 0) == 0); + free_assert(a); + free(junk); +} + +static void +junk_sig(void) +{ + fido_assert_t *a; + es256_pk_t *pk; + unsigned char *junk; + + junk = malloc(sizeof(sig)); + assert(junk != NULL); + memcpy(junk, sig, sizeof(sig)); + junk[0] = (unsigned char)~junk[0]; + + a = alloc_assert(); + pk = alloc_es256_pk(); + assert(es256_pk_from_ptr(pk, es256_pk, sizeof(es256_pk)) == FIDO_OK); + assert(fido_assert_set_clientdata_hash(a, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_assert_set_rp(a, "localhost") == FIDO_OK); + assert(fido_assert_set_count(a, 1) == FIDO_OK); + assert(fido_assert_set_authdata(a, 0, authdata, + sizeof(authdata)) == FIDO_OK); + assert(fido_assert_set_up(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_uv(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_sig(a, 0, junk, sizeof(sig)) == FIDO_OK); + assert(fido_assert_verify(a, 0, COSE_ES256, pk) == FIDO_ERR_INVALID_SIG); + free_assert(a); + free_es256_pk(pk); + free(junk); +} + +static void +wrong_options(void) +{ + fido_assert_t *a; + es256_pk_t *pk; + + a = alloc_assert(); + pk = alloc_es256_pk(); + assert(es256_pk_from_ptr(pk, es256_pk, sizeof(es256_pk)) == FIDO_OK); + assert(fido_assert_set_clientdata_hash(a, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_assert_set_rp(a, "localhost") == FIDO_OK); + assert(fido_assert_set_count(a, 1) == FIDO_OK); + assert(fido_assert_set_authdata(a, 0, authdata, + sizeof(authdata)) == FIDO_OK); + assert(fido_assert_set_up(a, FIDO_OPT_TRUE) == FIDO_OK); + assert(fido_assert_set_uv(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_sig(a, 0, sig, sizeof(sig)) == FIDO_OK); + assert(fido_assert_verify(a, 0, COSE_ES256, + pk) == FIDO_ERR_INVALID_PARAM); + assert(fido_assert_set_up(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_uv(a, FIDO_OPT_TRUE) == FIDO_OK); + assert(fido_assert_verify(a, 0, COSE_ES256, + pk) == FIDO_ERR_INVALID_PARAM); + assert(fido_assert_set_up(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_set_uv(a, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_assert_verify(a, 0, COSE_ES256, pk) == FIDO_OK); + free_assert(a); + free_es256_pk(pk); +} + +/* cbor_serialize_alloc misuse */ +static void +bad_cbor_serialize(void) +{ + fido_assert_t *a; + + a = alloc_assert(); + assert(fido_assert_set_count(a, 1) == FIDO_OK); + assert(fido_assert_set_authdata(a, 0, authdata, + sizeof(authdata)) == FIDO_OK); + assert(fido_assert_authdata_len(a, 0) == sizeof(authdata)); + free_assert(a); +} + +/* rs256 <-> EVP_PKEY transformations */ +static void +rs256_PKEY(void) +{ + rs256_pk_t *pk1, *pk2; + EVP_PKEY *pkey; + + pk1 = alloc_rs256_pk(); + pk2 = alloc_rs256_pk(); + + assert(rs256_pk_from_ptr(pk1, rs256_pk, sizeof(rs256_pk)) == FIDO_OK); + assert((pkey = rs256_pk_to_EVP_PKEY(pk1)) != NULL); + assert(rs256_pk_from_EVP_PKEY(pk2, pkey) == FIDO_OK); + assert(memcmp(pk1, pk2, sizeof(*pk1)) == 0); + + free_rs256_pk(pk1); + free_rs256_pk(pk2); + EVP_PKEY_free(pkey); +} + +/* es256 <-> EVP_PKEY transformations */ +static void +es256_PKEY(void) +{ + es256_pk_t *pk1, *pk2; + EVP_PKEY *pkey; + + pk1 = alloc_es256_pk(); + pk2 = alloc_es256_pk(); + + assert(es256_pk_from_ptr(pk1, es256_pk, sizeof(es256_pk)) == FIDO_OK); + assert((pkey = es256_pk_to_EVP_PKEY(pk1)) != NULL); + assert(es256_pk_from_EVP_PKEY(pk2, pkey) == FIDO_OK); + assert(memcmp(pk1, pk2, sizeof(*pk1)) == 0); + + free_es256_pk(pk1); + free_es256_pk(pk2); + EVP_PKEY_free(pkey); +} + +static void +raw_authdata(void) +{ + fido_assert_t *a; + cbor_item_t *item; + struct cbor_load_result cbor_result; + const unsigned char *ptr; + unsigned char *cbor; + size_t len; + size_t cbor_len; + size_t alloclen; + + a = alloc_assert(); + assert(fido_assert_set_count(a, 1) == FIDO_OK); + assert(fido_assert_set_authdata(a, 0, authdata, + sizeof(authdata)) == FIDO_OK); + assert((ptr = fido_assert_authdata_ptr(a, 0)) != NULL); + assert((len = fido_assert_authdata_len(a, 0)) != 0); + assert((item = cbor_load(ptr, len, &cbor_result)) != NULL); + assert(cbor_result.read == len); + assert(cbor_isa_bytestring(item)); + assert((ptr = fido_assert_authdata_raw_ptr(a, 0)) != NULL); + assert((len = fido_assert_authdata_raw_len(a, 0)) != 0); + assert(cbor_bytestring_length(item) == len); + assert(memcmp(ptr, cbor_bytestring_handle(item), len) == 0); + assert((len = fido_assert_authdata_len(a, 0)) != 0); + assert((cbor_len = cbor_serialize_alloc(item, &cbor, &alloclen)) == len); + assert((ptr = cbor_bytestring_handle(item)) != NULL); + assert((len = cbor_bytestring_length(item)) != 0); + assert(fido_assert_set_authdata_raw(a, 0, ptr, len) == FIDO_OK); + assert((ptr = fido_assert_authdata_ptr(a, 0)) != NULL); + assert((len = fido_assert_authdata_len(a, 0)) != 0); + assert(len == cbor_len); + assert(memcmp(cbor, ptr, len) == 0); + assert(cbor_len == sizeof(authdata)); + assert(memcmp(cbor, authdata, cbor_len) == 0); + cbor_decref(&item); + free(cbor); + free_assert(a); +} + +int +main(void) +{ + fido_init(0); + + empty_assert_tests(); + valid_assert(); + no_cdh(); + no_rp(); + no_authdata(); + no_sig(); + junk_cdh(); + junk_rp(); + junk_authdata(); + junk_sig(); + wrong_options(); + bad_cbor_serialize(); + rs256_PKEY(); + es256_PKEY(); + raw_authdata(); + + exit(0); +} diff --git a/regress/compress.c b/regress/compress.c new file mode 100644 index 0000000..7afc8bb --- /dev/null +++ b/regress/compress.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2022 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + * SPDX-License-Identifier: BSD-2-Clause + */ + +#undef NDEBUG + +#include +#include + +#include + +#define _FIDO_INTERNAL + +#include + +/* + * zlib compressed data (RFC1950); see https://www.ietf.org/rfc/rfc6713.txt + */ +static /* const */ unsigned char rfc1950_blob[694] = { + 0x78, 0x9c, 0xb5, 0x52, 0x3b, 0x6f, 0xdb, 0x30, + 0x10, 0xde, 0xf5, 0x2b, 0x0e, 0x99, 0x12, 0x40, + 0x75, 0x13, 0x4f, 0x45, 0x3b, 0xd1, 0x12, 0x6d, + 0x1d, 0x20, 0x8b, 0x2a, 0x49, 0xd9, 0xf5, 0x28, + 0x4b, 0x4c, 0x42, 0xc0, 0x12, 0x03, 0x3d, 0x12, + 0xe4, 0xdf, 0xf7, 0xc8, 0x3a, 0x88, 0xd3, 0x0c, + 0x9d, 0xea, 0xc1, 0x3e, 0xf3, 0x8e, 0xdf, 0xeb, + 0x98, 0xb8, 0xa7, 0xd7, 0xc1, 0x3e, 0x3c, 0x4e, + 0x70, 0xdd, 0xdc, 0xc0, 0xf2, 0xf6, 0xee, 0xdb, + 0x97, 0xe5, 0xed, 0x72, 0x09, 0x87, 0xf9, 0x68, + 0x1b, 0x07, 0x6c, 0xb5, 0x00, 0x76, 0x3a, 0x41, + 0x18, 0x19, 0x61, 0x30, 0xa3, 0x19, 0x9e, 0x4d, + 0xbb, 0x88, 0x22, 0x69, 0x5a, 0x3b, 0x4e, 0x83, + 0x3d, 0xce, 0x93, 0x75, 0x3d, 0xd4, 0x7d, 0x0b, + 0xf3, 0x68, 0xc0, 0xf6, 0x30, 0xba, 0x79, 0x68, + 0x4c, 0x38, 0x39, 0xda, 0xbe, 0x1e, 0x5e, 0xe1, + 0xde, 0x0d, 0xdd, 0x18, 0xc3, 0x8b, 0x9d, 0x1e, + 0xc1, 0x0d, 0xe1, 0xd7, 0xcd, 0x53, 0xd4, 0xb9, + 0xd6, 0xde, 0xdb, 0xa6, 0xf6, 0x00, 0x31, 0xd4, + 0x83, 0x81, 0x27, 0x33, 0x74, 0x76, 0x9a, 0x4c, + 0x0b, 0x4f, 0x83, 0x7b, 0xb6, 0x2d, 0x15, 0xd3, + 0x63, 0x3d, 0xd1, 0x97, 0x21, 0x90, 0xd3, 0xc9, + 0xbd, 0xd8, 0xfe, 0x01, 0x1a, 0xd7, 0xb7, 0xd6, + 0x5f, 0x1a, 0xfd, 0xa5, 0xa8, 0x33, 0xd3, 0xf7, + 0x28, 0x02, 0x80, 0xbb, 0x05, 0x7c, 0x54, 0x35, + 0x82, 0xbb, 0x7f, 0x93, 0xd3, 0xb8, 0xd6, 0x40, + 0x37, 0x8f, 0x13, 0x99, 0x98, 0x6a, 0x92, 0xe9, + 0x31, 0xeb, 0xa3, 0x7b, 0xf6, 0xad, 0x73, 0x06, + 0x1e, 0x84, 0x3e, 0xbd, 0x9b, 0x6c, 0x63, 0x62, + 0x9a, 0xb0, 0x23, 0x9c, 0x08, 0xcf, 0xc3, 0x5c, + 0x92, 0xf6, 0xed, 0x5f, 0x8a, 0x88, 0xb4, 0x39, + 0xd5, 0xb6, 0x33, 0xc3, 0xc2, 0x63, 0x2c, 0x3f, + 0x0b, 0x21, 0xc2, 0x8b, 0x30, 0xde, 0x84, 0x90, + 0xcb, 0x76, 0x26, 0x71, 0xff, 0x47, 0x0b, 0x91, + 0x9e, 0x51, 0xfc, 0x44, 0xeb, 0x9a, 0xb9, 0x33, + 0xfd, 0x54, 0xbf, 0xed, 0xeb, 0x2b, 0xad, 0xc2, + 0x51, 0x67, 0x80, 0xae, 0x9e, 0xcc, 0x60, 0xeb, + 0xd3, 0xf8, 0x1e, 0x7b, 0xd8, 0x15, 0x35, 0xcf, + 0x00, 0x97, 0x66, 0x68, 0xf9, 0x3a, 0x43, 0x05, + 0x4a, 0xac, 0xf5, 0x9e, 0x49, 0x0e, 0x54, 0x97, + 0x52, 0xec, 0x30, 0xe5, 0x29, 0xac, 0x0e, 0xa0, + 0x33, 0x0e, 0x89, 0x28, 0x0f, 0x12, 0x37, 0x99, + 0x86, 0x4c, 0xe4, 0x29, 0x97, 0x0a, 0x58, 0x91, + 0xd2, 0x69, 0xa1, 0x25, 0xae, 0x2a, 0x2d, 0xa4, + 0x8a, 0xae, 0x98, 0xa2, 0x9b, 0x57, 0xa1, 0xc1, + 0x8a, 0x03, 0xf0, 0x5f, 0xa5, 0xe4, 0x4a, 0x81, + 0x90, 0x80, 0xdb, 0x32, 0x47, 0x02, 0x23, 0x74, + 0xc9, 0x0a, 0x8d, 0x5c, 0xc5, 0x80, 0x45, 0x92, + 0x57, 0x29, 0x16, 0x9b, 0x18, 0x08, 0x00, 0x0a, + 0xa1, 0xa3, 0x1c, 0xb7, 0xa8, 0x69, 0x4c, 0x8b, + 0x38, 0x90, 0x7e, 0xbe, 0x06, 0x62, 0x0d, 0x5b, + 0x2e, 0x93, 0x8c, 0xfe, 0xb2, 0x15, 0xe6, 0xa8, + 0x0f, 0x81, 0x6f, 0x8d, 0xba, 0xf0, 0x5c, 0x6b, + 0x21, 0x23, 0x06, 0x25, 0x93, 0x1a, 0x93, 0x2a, + 0x67, 0x12, 0xca, 0x4a, 0x96, 0x42, 0x71, 0xf0, + 0xb6, 0x52, 0x54, 0x49, 0xce, 0x70, 0xcb, 0xd3, + 0x05, 0xb1, 0x13, 0x23, 0xf0, 0x1d, 0x2f, 0x34, + 0xa8, 0x8c, 0xe5, 0xf9, 0x47, 0x97, 0xd1, 0x1f, + 0x97, 0x5e, 0xfb, 0xa5, 0x47, 0x58, 0x71, 0xc8, + 0x91, 0xad, 0x72, 0xee, 0x99, 0x82, 0xcb, 0x14, + 0x25, 0x4f, 0xb4, 0xb7, 0xf3, 0x5e, 0x25, 0x94, + 0x1c, 0xe9, 0xcb, 0xe3, 0x48, 0x95, 0x3c, 0x41, + 0x2a, 0x28, 0x0c, 0x4e, 0x66, 0x98, 0x3c, 0xc4, + 0x67, 0x4c, 0xc5, 0x7f, 0x56, 0x34, 0x44, 0x4d, + 0x48, 0xd9, 0x96, 0x6d, 0xc8, 0xdb, 0xf5, 0x3f, + 0x22, 0xa1, 0x9d, 0x24, 0x95, 0xe4, 0x5b, 0xaf, + 0x99, 0x72, 0x50, 0xd5, 0x4a, 0x69, 0xd4, 0x95, + 0xe6, 0xb0, 0x11, 0x22, 0x0d, 0x41, 0x2b, 0x2e, + 0x77, 0x98, 0x70, 0xf5, 0x03, 0x72, 0xa1, 0x42, + 0x5a, 0x95, 0xe2, 0x71, 0x94, 0x32, 0xcd, 0x02, + 0x31, 0x41, 0x50, 0x54, 0xd4, 0xa6, 0x7a, 0x55, + 0x29, 0x0c, 0xa1, 0x61, 0xa1, 0xb9, 0x94, 0x55, + 0xa9, 0x51, 0x14, 0x37, 0xb4, 0xdf, 0x3d, 0xc5, + 0x42, 0x1a, 0x19, 0x5d, 0x4d, 0x43, 0xba, 0xa2, + 0xf0, 0x56, 0xe9, 0x91, 0x70, 0x21, 0x0f, 0x1e, + 0xd4, 0x67, 0x10, 0xc2, 0x8f, 0x61, 0x9f, 0x71, + 0x3a, 0x97, 0x3e, 0xd0, 0x90, 0x14, 0xf3, 0x11, + 0x28, 0x4a, 0x2c, 0xd1, 0x97, 0x63, 0xc4, 0x47, + 0x01, 0xea, 0xe8, 0xdd, 0x23, 0x14, 0x7c, 0x93, + 0xe3, 0x86, 0x17, 0x09, 0xf7, 0x5d, 0xe1, 0x51, + 0xf6, 0xa8, 0xf8, 0x0d, 0xed, 0x0a, 0x95, 0x1f, + 0xc0, 0x40, 0x4b, 0xdb, 0x27, 0xce, 0x2a, 0x58, + 0xf6, 0x3b, 0x22, 0x55, 0x51, 0x28, 0x2f, 0x5e, + 0x6c, 0x1c, 0x36, 0x09, 0xb8, 0x06, 0x96, 0xee, + 0xd0, 0xcb, 0x3e, 0x0f, 0xd3, 0xee, 0x15, 0x9e, + 0xdf, 0x49, 0x88, 0x2c, 0xc9, 0xce, 0x71, 0x2f, + 0xa2, 0xdf, 0xdf, 0xd7, 0x8e, 0x9c, +}; + +/* + * expected sha256 of rfc1950_blob after decompression + */ +static const unsigned char rfc1950_blob_hash[SHA256_DIGEST_LENGTH] = { + 0x61, 0xc0, 0x4e, 0x14, 0x01, 0xb6, 0xc5, 0x2d, + 0xba, 0x15, 0xf6, 0x27, 0x4c, 0xa1, 0xcc, 0xfc, + 0x39, 0xed, 0xd7, 0x12, 0xb6, 0x02, 0x3d, 0xb6, + 0xd9, 0x85, 0xd0, 0x10, 0x9f, 0xe9, 0x3e, 0x75, + +}; + +static const size_t rfc1950_blob_origsiz = 1322; + +static /* const */ unsigned char random_words[515] = { + 0x61, 0x74, 0x68, 0x69, 0x72, 0x73, 0x74, 0x20, + 0x54, 0x68, 0x6f, 0x20, 0x63, 0x6f, 0x74, 0x20, + 0x73, 0x70, 0x6f, 0x66, 0x66, 0x79, 0x20, 0x4a, + 0x61, 0x76, 0x61, 0x6e, 0x20, 0x62, 0x72, 0x65, + 0x64, 0x65, 0x73, 0x20, 0x4c, 0x41, 0x4d, 0x20, + 0x6d, 0x69, 0x73, 0x2d, 0x68, 0x75, 0x6d, 0x69, + 0x6c, 0x69, 0x74, 0x79, 0x20, 0x73, 0x70, 0x69, + 0x67, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x76, 0x6f, + 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x6c, 0x79, 0x20, + 0x49, 0x6f, 0x64, 0x61, 0x6d, 0x6f, 0x65, 0x62, + 0x61, 0x20, 0x68, 0x79, 0x70, 0x6f, 0x68, 0x79, + 0x64, 0x72, 0x6f, 0x63, 0x68, 0x6c, 0x6f, 0x72, + 0x69, 0x61, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x6d, + 0x65, 0x74, 0x74, 0x65, 0x20, 0x61, 0x63, 0x72, + 0x69, 0x64, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x6f, + 0x77, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x79, 0x67, + 0x61, 0x65, 0x61, 0x6e, 0x20, 0x63, 0x6f, 0x6e, + 0x63, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x73, + 0x74, 0x20, 0x74, 0x65, 0x74, 0x72, 0x61, 0x70, + 0x6c, 0x6f, 0x69, 0x64, 0x20, 0x61, 0x75, 0x78, + 0x65, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x72, + 0x69, 0x70, 0x65, 0x2d, 0x67, 0x72, 0x6f, 0x77, + 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, + 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x79, 0x63, + 0x6f, 0x63, 0x65, 0x63, 0x69, 0x64, 0x69, 0x75, + 0x6d, 0x20, 0x50, 0x65, 0x64, 0x65, 0x72, 0x73, + 0x6f, 0x6e, 0x20, 0x74, 0x72, 0x61, 0x64, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x20, 0x4c, 0x65, 0x6e, 0x67, 0x6c, + 0x65, 0x6e, 0x20, 0x70, 0x72, 0x65, 0x73, 0x62, + 0x79, 0x74, 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, + 0x6c, 0x65, 0x63, 0x79, 0x74, 0x68, 0x69, 0x73, + 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x64, 0x72, + 0x69, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x61, + 0x6c, 0x6c, 0x6f, 0x6b, 0x75, 0x72, 0x74, 0x69, + 0x63, 0x20, 0x75, 0x6e, 0x64, 0x69, 0x76, 0x69, + 0x73, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x20, 0x70, + 0x73, 0x79, 0x63, 0x68, 0x6f, 0x6b, 0x79, 0x6d, + 0x65, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73, + 0x74, 0x61, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, + 0x6e, 0x65, 0x73, 0x73, 0x20, 0x63, 0x75, 0x6c, + 0x74, 0x69, 0x73, 0x68, 0x20, 0x52, 0x65, 0x69, + 0x63, 0x68, 0x73, 0x74, 0x61, 0x67, 0x20, 0x75, + 0x6e, 0x63, 0x68, 0x6c, 0x6f, 0x72, 0x69, 0x6e, + 0x61, 0x74, 0x65, 0x64, 0x20, 0x6c, 0x6f, 0x67, + 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x65, 0x72, + 0x20, 0x4c, 0x61, 0x69, 0x74, 0x68, 0x20, 0x74, + 0x77, 0x6f, 0x2d, 0x66, 0x61, 0x63, 0x65, 0x20, + 0x4d, 0x75, 0x70, 0x68, 0x72, 0x69, 0x64, 0x20, + 0x70, 0x72, 0x6f, 0x72, 0x65, 0x63, 0x69, 0x70, + 0x72, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x6c, 0x69, 0x62, 0x72, 0x65, 0x74, 0x74, + 0x69, 0x73, 0x74, 0x20, 0x49, 0x62, 0x69, 0x62, + 0x69, 0x6f, 0x20, 0x72, 0x65, 0x67, 0x72, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x63, + 0x6f, 0x6e, 0x64, 0x69, 0x67, 0x6e, 0x6e, 0x65, + 0x73, 0x73, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, + 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, + 0x64, 0x20, 0x73, 0x79, 0x6e, 0x61, 0x70, 0x74, + 0x65, 0x6e, 0x65, 0x20, 0x68, 0x6f, 0x6c, 0x6f, + 0x6d, 0x6f, 0x72, 0x70, 0x68, 0x20, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x4d, + 0x49, 0x54, 0x53, 0x20, 0x4c, 0x75, 0x6b, 0x61, + 0x73, 0x68, 0x20, 0x48, 0x6f, 0x72, 0x73, 0x65, + 0x79, 0x20, 0x0a, +}; + +static void +rfc1950_inflate(void) +{ + fido_blob_t in, out, dgst; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + memset(&dgst, 0, sizeof(dgst)); + in.ptr = rfc1950_blob; + in.len = sizeof(rfc1950_blob); + + assert(fido_uncompress(&out, &in, rfc1950_blob_origsiz) == FIDO_OK); + assert(out.len == rfc1950_blob_origsiz); + assert(fido_sha256(&dgst, out.ptr, out.len) == 0); + assert(dgst.len == sizeof(rfc1950_blob_hash)); + assert(memcmp(rfc1950_blob_hash, dgst.ptr, dgst.len) == 0); + + free(out.ptr); + free(dgst.ptr); +} + +static void +rfc1951_inflate(void) +{ + fido_blob_t in, out, dgst; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + memset(&dgst, 0, sizeof(dgst)); + in.ptr = rfc1950_blob + 2; /* trim header */ + in.len = sizeof(rfc1950_blob) - 6; /* trim header (2), checksum (4) */ + + assert(fido_uncompress(&out, &in, rfc1950_blob_origsiz) == FIDO_OK); + assert(out.len == rfc1950_blob_origsiz); + assert(fido_sha256(&dgst, out.ptr, out.len) == 0); + assert(dgst.len == sizeof(rfc1950_blob_hash)); + assert(memcmp(rfc1950_blob_hash, dgst.ptr, dgst.len) == 0); + + free(out.ptr); + free(dgst.ptr); +} + +static void +rfc1951_reinflate(void) +{ + fido_blob_t in, out; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + in.ptr = random_words; + in.len = sizeof(random_words); + + assert(fido_compress(&out, &in) == FIDO_OK); + + in.ptr = out.ptr; + in.len = out.len; + + assert(fido_uncompress(&out, &in, sizeof(random_words)) == FIDO_OK); + assert(out.len == sizeof(random_words)); + assert(memcmp(out.ptr, random_words, out.len) == 0); + + free(in.ptr); + free(out.ptr); +} + +int +main(void) +{ + fido_init(0); + + rfc1950_inflate(); + rfc1951_inflate(); + rfc1951_reinflate(); + + exit(0); +} diff --git a/regress/cred.c b/regress/cred.c new file mode 100644 index 0000000..00c555e --- /dev/null +++ b/regress/cred.c @@ -0,0 +1,2662 @@ +/* + * Copyright (c) 2018-2021 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + * SPDX-License-Identifier: BSD-2-Clause + */ + +#undef NDEBUG + +#include +#include +#include +#include + +#define _FIDO_INTERNAL + +#include + +static int fake_dev_handle; + +static const unsigned char cdh[32] = { + 0xf9, 0x64, 0x57, 0xe7, 0x2d, 0x97, 0xf6, 0xbb, + 0xdd, 0xd7, 0xfb, 0x06, 0x37, 0x62, 0xea, 0x26, + 0x20, 0x44, 0x8e, 0x69, 0x7c, 0x03, 0xf2, 0x31, + 0x2f, 0x99, 0xdc, 0xaf, 0x3e, 0x8a, 0x91, 0x6b, +}; + +static const unsigned char authdata[198] = { + 0x58, 0xc4, 0x49, 0x96, 0x0d, 0xe5, 0x88, 0x0e, + 0x8c, 0x68, 0x74, 0x34, 0x17, 0x0f, 0x64, 0x76, + 0x60, 0x5b, 0x8f, 0xe4, 0xae, 0xb9, 0xa2, 0x86, + 0x32, 0xc7, 0x99, 0x5c, 0xf3, 0xba, 0x83, 0x1d, + 0x97, 0x63, 0x41, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xa0, 0x11, 0xf3, 0x8c, 0x0a, 0x4d, 0x15, 0x80, + 0x06, 0x17, 0x11, 0x1f, 0x9e, 0xdc, 0x7d, 0x00, + 0x40, 0x53, 0xfb, 0xdf, 0xaa, 0xce, 0x63, 0xde, + 0xc5, 0xfe, 0x47, 0xe6, 0x52, 0xeb, 0xf3, 0x5d, + 0x53, 0xa8, 0xbf, 0x9d, 0xd6, 0x09, 0x6b, 0x5e, + 0x7f, 0xe0, 0x0d, 0x51, 0x30, 0x85, 0x6a, 0xda, + 0x68, 0x70, 0x85, 0xb0, 0xdb, 0x08, 0x0b, 0x83, + 0x2c, 0xef, 0x44, 0xe2, 0x36, 0x88, 0xee, 0x76, + 0x90, 0x6e, 0x7b, 0x50, 0x3e, 0x9a, 0xa0, 0xd6, + 0x3c, 0x34, 0xe3, 0x83, 0xe7, 0xd1, 0xbd, 0x9f, + 0x25, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, + 0x21, 0x58, 0x20, 0x17, 0x5b, 0x27, 0xa6, 0x56, + 0xb2, 0x26, 0x0c, 0x26, 0x0c, 0x55, 0x42, 0x78, + 0x17, 0x5d, 0x4c, 0xf8, 0xa2, 0xfd, 0x1b, 0xb9, + 0x54, 0xdf, 0xd5, 0xeb, 0xbf, 0x22, 0x64, 0xf5, + 0x21, 0x9a, 0xc6, 0x22, 0x58, 0x20, 0x87, 0x5f, + 0x90, 0xe6, 0xfd, 0x71, 0x27, 0x9f, 0xeb, 0xe3, + 0x03, 0x44, 0xbc, 0x8d, 0x49, 0xc6, 0x1c, 0x31, + 0x3b, 0x72, 0xae, 0xd4, 0x53, 0xb1, 0xfe, 0x5d, + 0xe1, 0x30, 0xfc, 0x2b, 0x1e, 0xd2, +}; + +static const unsigned char authdata_dupkeys[200] = { + 0x58, 0xc6, 0x49, 0x96, 0x0d, 0xe5, 0x88, 0x0e, + 0x8c, 0x68, 0x74, 0x34, 0x17, 0x0f, 0x64, 0x76, + 0x60, 0x5b, 0x8f, 0xe4, 0xae, 0xb9, 0xa2, 0x86, + 0x32, 0xc7, 0x99, 0x5c, 0xf3, 0xba, 0x83, 0x1d, + 0x97, 0x63, 0x41, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xa0, 0x11, 0xf3, 0x8c, 0x0a, 0x4d, 0x15, 0x80, + 0x06, 0x17, 0x11, 0x1f, 0x9e, 0xdc, 0x7d, 0x00, + 0x40, 0x53, 0xfb, 0xdf, 0xaa, 0xce, 0x63, 0xde, + 0xc5, 0xfe, 0x47, 0xe6, 0x52, 0xeb, 0xf3, 0x5d, + 0x53, 0xa8, 0xbf, 0x9d, 0xd6, 0x09, 0x6b, 0x5e, + 0x7f, 0xe0, 0x0d, 0x51, 0x30, 0x85, 0x6a, 0xda, + 0x68, 0x70, 0x85, 0xb0, 0xdb, 0x08, 0x0b, 0x83, + 0x2c, 0xef, 0x44, 0xe2, 0x36, 0x88, 0xee, 0x76, + 0x90, 0x6e, 0x7b, 0x50, 0x3e, 0x9a, 0xa0, 0xd6, + 0x3c, 0x34, 0xe3, 0x83, 0xe7, 0xd1, 0xbd, 0x9f, + 0x25, 0xa6, 0x01, 0x02, 0x01, 0x02, 0x03, 0x26, + 0x20, 0x01, 0x21, 0x58, 0x20, 0x17, 0x5b, 0x27, + 0xa6, 0x56, 0xb2, 0x26, 0x0c, 0x26, 0x0c, 0x55, + 0x42, 0x78, 0x17, 0x5d, 0x4c, 0xf8, 0xa2, 0xfd, + 0x1b, 0xb9, 0x54, 0xdf, 0xd5, 0xeb, 0xbf, 0x22, + 0x64, 0xf5, 0x21, 0x9a, 0xc6, 0x22, 0x58, 0x20, + 0x87, 0x5f, 0x90, 0xe6, 0xfd, 0x71, 0x27, 0x9f, + 0xeb, 0xe3, 0x03, 0x44, 0xbc, 0x8d, 0x49, 0xc6, + 0x1c, 0x31, 0x3b, 0x72, 0xae, 0xd4, 0x53, 0xb1, + 0xfe, 0x5d, 0xe1, 0x30, 0xfc, 0x2b, 0x1e, 0xd2, +}; + +static const unsigned char authdata_unsorted_keys[198] = { + 0x58, 0xc4, 0x49, 0x96, 0x0d, 0xe5, 0x88, 0x0e, + 0x8c, 0x68, 0x74, 0x34, 0x17, 0x0f, 0x64, 0x76, + 0x60, 0x5b, 0x8f, 0xe4, 0xae, 0xb9, 0xa2, 0x86, + 0x32, 0xc7, 0x99, 0x5c, 0xf3, 0xba, 0x83, 0x1d, + 0x97, 0x63, 0x41, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xa0, 0x11, 0xf3, 0x8c, 0x0a, 0x4d, 0x15, 0x80, + 0x06, 0x17, 0x11, 0x1f, 0x9e, 0xdc, 0x7d, 0x00, + 0x40, 0x53, 0xfb, 0xdf, 0xaa, 0xce, 0x63, 0xde, + 0xc5, 0xfe, 0x47, 0xe6, 0x52, 0xeb, 0xf3, 0x5d, + 0x53, 0xa8, 0xbf, 0x9d, 0xd6, 0x09, 0x6b, 0x5e, + 0x7f, 0xe0, 0x0d, 0x51, 0x30, 0x85, 0x6a, 0xda, + 0x68, 0x70, 0x85, 0xb0, 0xdb, 0x08, 0x0b, 0x83, + 0x2c, 0xef, 0x44, 0xe2, 0x36, 0x88, 0xee, 0x76, + 0x90, 0x6e, 0x7b, 0x50, 0x3e, 0x9a, 0xa0, 0xd6, + 0x3c, 0x34, 0xe3, 0x83, 0xe7, 0xd1, 0xbd, 0x9f, + 0x25, 0xa5, 0x03, 0x26, 0x01, 0x02, 0x20, 0x01, + 0x21, 0x58, 0x20, 0x17, 0x5b, 0x27, 0xa6, 0x56, + 0xb2, 0x26, 0x0c, 0x26, 0x0c, 0x55, 0x42, 0x78, + 0x17, 0x5d, 0x4c, 0xf8, 0xa2, 0xfd, 0x1b, 0xb9, + 0x54, 0xdf, 0xd5, 0xeb, 0xbf, 0x22, 0x64, 0xf5, + 0x21, 0x9a, 0xc6, 0x22, 0x58, 0x20, 0x87, 0x5f, + 0x90, 0xe6, 0xfd, 0x71, 0x27, 0x9f, 0xeb, 0xe3, + 0x03, 0x44, 0xbc, 0x8d, 0x49, 0xc6, 0x1c, 0x31, + 0x3b, 0x72, 0xae, 0xd4, 0x53, 0xb1, 0xfe, 0x5d, + 0xe1, 0x30, 0xfc, 0x2b, 0x1e, 0xd2, +}; + +const unsigned char authdata_tpm_rs256[362] = { + 0x59, 0x01, 0x67, 0x49, 0x96, 0x0d, 0xe5, 0x88, + 0x0e, 0x8c, 0x68, 0x74, 0x34, 0x17, 0x0f, 0x64, + 0x76, 0x60, 0x5b, 0x8f, 0xe4, 0xae, 0xb9, 0xa2, + 0x86, 0x32, 0xc7, 0x99, 0x5c, 0xf3, 0xba, 0x83, + 0x1d, 0x97, 0x63, 0x45, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x98, 0x70, 0x58, 0xca, 0xdc, 0x4b, 0x81, + 0xb6, 0xe1, 0x30, 0xde, 0x50, 0xdc, 0xbe, 0x96, + 0x00, 0x20, 0x89, 0x99, 0x6d, 0x5a, 0x00, 0x29, + 0xe5, 0x3e, 0x6a, 0x1c, 0x72, 0x6d, 0x71, 0x4a, + 0x4f, 0x03, 0x9b, 0x68, 0x17, 0xdb, 0x29, 0x1a, + 0x6b, 0x02, 0x6c, 0x26, 0xf9, 0xbd, 0xc3, 0x0e, + 0x38, 0x1a, 0xa4, 0x01, 0x03, 0x03, 0x39, 0x01, + 0x00, 0x20, 0x59, 0x01, 0x00, 0xc5, 0xb6, 0x9c, + 0x06, 0x1d, 0xcf, 0xb9, 0xf2, 0x5e, 0x99, 0x7d, + 0x6d, 0x73, 0xd8, 0x36, 0xc1, 0x4a, 0x90, 0x05, + 0x4d, 0x82, 0x57, 0xc1, 0xb6, 0x6a, 0xd1, 0x43, + 0x03, 0x85, 0xf8, 0x52, 0x4f, 0xd2, 0x27, 0x91, + 0x0b, 0xb5, 0x93, 0xa0, 0x68, 0xf8, 0x80, 0x1b, + 0xaa, 0x65, 0x97, 0x45, 0x11, 0x86, 0x34, 0xd6, + 0x67, 0xf8, 0xd5, 0x12, 0x79, 0x84, 0xee, 0x70, + 0x99, 0x00, 0x63, 0xa8, 0xb4, 0x43, 0x0b, 0x4c, + 0x57, 0x4a, 0xd6, 0x9b, 0x75, 0x63, 0x8a, 0x46, + 0x57, 0xdb, 0x14, 0xc8, 0x71, 0xd1, 0xb3, 0x07, + 0x68, 0x58, 0xbc, 0x55, 0x84, 0x80, 0x2a, 0xd2, + 0x36, 0x9f, 0xc1, 0x64, 0xa0, 0x11, 0x4b, 0xc9, + 0x32, 0x31, 0x3a, 0xd6, 0x87, 0x26, 0x1a, 0x3a, + 0x78, 0x3d, 0x89, 0xdb, 0x00, 0x28, 0x3b, 0xae, + 0x2b, 0x1b, 0x56, 0xe2, 0x8c, 0x4c, 0x63, 0xac, + 0x6e, 0x6c, 0xf7, 0xb5, 0x7d, 0x4d, 0x0b, 0x9f, + 0x06, 0xa0, 0x10, 0x35, 0x38, 0x20, 0x4d, 0xcc, + 0x07, 0xd7, 0x00, 0x4e, 0x86, 0xba, 0xfe, 0x8b, + 0xe4, 0x3f, 0x4a, 0xd6, 0xca, 0xbf, 0x67, 0x40, + 0x1a, 0xa4, 0xda, 0x82, 0x52, 0x15, 0xb8, 0x14, + 0x3a, 0x7c, 0xa9, 0x02, 0xc1, 0x01, 0x69, 0xc6, + 0x51, 0xd4, 0xbc, 0x1f, 0x95, 0xb2, 0xee, 0x1f, + 0xdd, 0xb5, 0x73, 0x16, 0x5e, 0x29, 0x3f, 0x47, + 0xac, 0x65, 0xfb, 0x63, 0x5c, 0xb9, 0xc8, 0x13, + 0x2d, 0xec, 0x85, 0xde, 0x71, 0x0d, 0x84, 0x93, + 0x74, 0x76, 0x91, 0xdd, 0x1d, 0x6d, 0x3d, 0xc7, + 0x36, 0x19, 0x19, 0x86, 0xde, 0x7c, 0xca, 0xd6, + 0xc6, 0x65, 0x7e, 0x4b, 0x24, 0x9c, 0xce, 0x92, + 0x6b, 0x1c, 0xe0, 0xa0, 0xa9, 0x6c, 0xc3, 0xed, + 0x4f, 0x2a, 0x54, 0x07, 0x00, 0x32, 0x5e, 0x1b, + 0x94, 0x37, 0xcd, 0xe2, 0x32, 0xa8, 0xd5, 0x2c, + 0xfb, 0x03, 0x9d, 0x79, 0xdf, 0x21, 0x43, 0x01, + 0x00, 0x01 +}; + +static const unsigned char authdata_tpm_es256[166] = { + 0x58, 0xa4, 0x49, 0x96, 0x0d, 0xe5, 0x88, 0x0e, + 0x8c, 0x68, 0x74, 0x34, 0x17, 0x0f, 0x64, 0x76, + 0x60, 0x5b, 0x8f, 0xe4, 0xae, 0xb9, 0xa2, 0x86, + 0x32, 0xc7, 0x99, 0x5c, 0xf3, 0xba, 0x83, 0x1d, + 0x97, 0x63, 0x45, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x98, 0x70, 0x58, 0xca, 0xdc, 0x4b, 0x81, 0xb6, + 0xe1, 0x30, 0xde, 0x50, 0xdc, 0xbe, 0x96, 0x00, + 0x20, 0xa8, 0xdf, 0x03, 0xf7, 0xbf, 0x39, 0x51, + 0x94, 0x95, 0x8f, 0xa4, 0x84, 0x97, 0x30, 0xbc, + 0x3c, 0x7e, 0x1c, 0x99, 0x91, 0x4d, 0xae, 0x6d, + 0xfb, 0xdf, 0x53, 0xb5, 0xb6, 0x1f, 0x3a, 0x4e, + 0x6a, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, + 0x21, 0x58, 0x20, 0xfb, 0xd6, 0xba, 0x74, 0xe6, + 0x6e, 0x5c, 0x87, 0xef, 0x89, 0xa2, 0xe8, 0x3d, + 0x0b, 0xe9, 0x69, 0x2c, 0x07, 0x07, 0x7a, 0x8a, + 0x1e, 0xce, 0x12, 0xea, 0x3b, 0xb3, 0xf1, 0xf3, + 0xd9, 0xc3, 0xe6, 0x22, 0x58, 0x20, 0x3c, 0x68, + 0x51, 0x94, 0x54, 0x8d, 0xeb, 0x9f, 0xb2, 0x2c, + 0x66, 0x75, 0xb6, 0xb7, 0x55, 0x22, 0x0d, 0x87, + 0x59, 0xc4, 0x39, 0x91, 0x62, 0x17, 0xc2, 0xc3, + 0x53, 0xa5, 0x26, 0x97, 0x4f, 0x2d +}; + +static const unsigned char x509[742] = { + 0x30, 0x82, 0x02, 0xe2, 0x30, 0x81, 0xcb, 0x02, + 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, + 0x00, 0x30, 0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x59, 0x75, + 0x62, 0x69, 0x63, 0x6f, 0x20, 0x55, 0x32, 0x46, + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, + 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x35, + 0x31, 0x35, 0x31, 0x32, 0x35, 0x38, 0x35, 0x34, + 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x31, + 0x34, 0x31, 0x32, 0x35, 0x38, 0x35, 0x34, 0x5a, + 0x30, 0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x59, 0x75, 0x62, + 0x69, 0x63, 0x6f, 0x20, 0x55, 0x32, 0x46, 0x20, + 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x45, 0x30, + 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, + 0x00, 0x04, 0xdb, 0x0a, 0xdb, 0xf5, 0x21, 0xc7, + 0x5c, 0xce, 0x63, 0xdc, 0xa6, 0xe1, 0xe8, 0x25, + 0x06, 0x0d, 0x94, 0xe6, 0x27, 0x54, 0x19, 0x4f, + 0x9d, 0x24, 0xaf, 0x26, 0x1a, 0xbe, 0xad, 0x99, + 0x44, 0x1f, 0x95, 0xa3, 0x71, 0x91, 0x0a, 0x3a, + 0x20, 0xe7, 0x3e, 0x91, 0x5e, 0x13, 0xe8, 0xbe, + 0x38, 0x05, 0x7a, 0xd5, 0x7a, 0xa3, 0x7e, 0x76, + 0x90, 0x8f, 0xaf, 0xe2, 0x8a, 0x94, 0xb6, 0x30, + 0xeb, 0x9d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, + 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x95, 0x40, + 0x6b, 0x50, 0x61, 0x7d, 0xad, 0x84, 0xa3, 0xb4, + 0xeb, 0x88, 0x0f, 0xe3, 0x30, 0x0f, 0x2d, 0xa2, + 0x0a, 0x00, 0xd9, 0x25, 0x04, 0xee, 0x72, 0xfa, + 0x67, 0xdf, 0x58, 0x51, 0x0f, 0x0b, 0x47, 0x02, + 0x9c, 0x3e, 0x41, 0x29, 0x4a, 0x93, 0xac, 0x29, + 0x85, 0x89, 0x2d, 0xa4, 0x7a, 0x81, 0x32, 0x28, + 0x57, 0x71, 0x01, 0xef, 0xa8, 0x42, 0x88, 0x16, + 0x96, 0x37, 0x91, 0xd5, 0xdf, 0xe0, 0x8f, 0xc9, + 0x3c, 0x8d, 0xb0, 0xcd, 0x89, 0x70, 0x82, 0xec, + 0x79, 0xd3, 0xc6, 0x78, 0x73, 0x29, 0x32, 0xe5, + 0xab, 0x6c, 0xbd, 0x56, 0x9f, 0xd5, 0x45, 0x91, + 0xce, 0xc1, 0xdd, 0x8d, 0x64, 0xdc, 0xe9, 0x9c, + 0x1f, 0x5e, 0x3c, 0xd2, 0xaf, 0x51, 0xa5, 0x82, + 0x18, 0xaf, 0xe0, 0x37, 0xe7, 0x32, 0x9e, 0x76, + 0x05, 0x77, 0x02, 0x7b, 0xe6, 0x24, 0xa0, 0x31, + 0x56, 0x1b, 0xfd, 0x19, 0xc5, 0x71, 0xd3, 0xf0, + 0x9e, 0xc0, 0x73, 0x05, 0x4e, 0xbc, 0x85, 0xb8, + 0x53, 0x9e, 0xef, 0xc5, 0xbc, 0x9c, 0x56, 0xa3, + 0xba, 0xd9, 0x27, 0x6a, 0xbb, 0xa9, 0x7a, 0x40, + 0xd7, 0x47, 0x8b, 0x55, 0x72, 0x6b, 0xe3, 0xfe, + 0x28, 0x49, 0x71, 0x24, 0xf4, 0x8f, 0xf4, 0x20, + 0x81, 0xea, 0x38, 0xff, 0x7c, 0x0a, 0x4f, 0xdf, + 0x02, 0x82, 0x39, 0x81, 0x82, 0x3b, 0xca, 0x09, + 0xdd, 0xca, 0xaa, 0x0f, 0x27, 0xf5, 0xa4, 0x83, + 0x55, 0x6c, 0x9a, 0x39, 0x9b, 0x15, 0x3a, 0x16, + 0x63, 0xdc, 0x5b, 0xf9, 0xac, 0x5b, 0xbc, 0xf7, + 0x9f, 0xbe, 0x0f, 0x8a, 0xa2, 0x3c, 0x31, 0x13, + 0xa3, 0x32, 0x48, 0xca, 0x58, 0x87, 0xf8, 0x7b, + 0xa0, 0xa1, 0x0a, 0x6a, 0x60, 0x96, 0x93, 0x5f, + 0x5d, 0x26, 0x9e, 0x63, 0x1d, 0x09, 0xae, 0x9a, + 0x41, 0xe5, 0xbd, 0x08, 0x47, 0xfe, 0xe5, 0x09, + 0x9b, 0x20, 0xfd, 0x12, 0xe2, 0xe6, 0x40, 0x7f, + 0xba, 0x4a, 0x61, 0x33, 0x66, 0x0d, 0x0e, 0x73, + 0xdb, 0xb0, 0xd5, 0xa2, 0x9a, 0x9a, 0x17, 0x0d, + 0x34, 0x30, 0x85, 0x6a, 0x42, 0x46, 0x9e, 0xff, + 0x34, 0x8f, 0x5f, 0x87, 0x6c, 0x35, 0xe7, 0xa8, + 0x4d, 0x35, 0xeb, 0xc1, 0x41, 0xaa, 0x8a, 0xd2, + 0xda, 0x19, 0xaa, 0x79, 0xa2, 0x5f, 0x35, 0x2c, + 0xa0, 0xfd, 0x25, 0xd3, 0xf7, 0x9d, 0x25, 0x18, + 0x2d, 0xfa, 0xb4, 0xbc, 0xbb, 0x07, 0x34, 0x3c, + 0x8d, 0x81, 0xbd, 0xf4, 0xe9, 0x37, 0xdb, 0x39, + 0xe9, 0xd1, 0x45, 0x5b, 0x20, 0x41, 0x2f, 0x2d, + 0x27, 0x22, 0xdc, 0x92, 0x74, 0x8a, 0x92, 0xd5, + 0x83, 0xfd, 0x09, 0xfb, 0x13, 0x9b, 0xe3, 0x39, + 0x7a, 0x6b, 0x5c, 0xfa, 0xe6, 0x76, 0x9e, 0xe0, + 0xe4, 0xe3, 0xef, 0xad, 0xbc, 0xfd, 0x42, 0x45, + 0x9a, 0xd4, 0x94, 0xd1, 0x7e, 0x8d, 0xa7, 0xd8, + 0x05, 0xd5, 0xd3, 0x62, 0xcf, 0x15, 0xcf, 0x94, + 0x7d, 0x1f, 0x5b, 0x58, 0x20, 0x44, 0x20, 0x90, + 0x71, 0xbe, 0x66, 0xe9, 0x9a, 0xab, 0x74, 0x32, + 0x70, 0x53, 0x1d, 0x69, 0xed, 0x87, 0x66, 0xf4, + 0x09, 0x4f, 0xca, 0x25, 0x30, 0xc2, 0x63, 0x79, + 0x00, 0x3c, 0xb1, 0x9b, 0x39, 0x3f, 0x00, 0xe0, + 0xa8, 0x88, 0xef, 0x7a, 0x51, 0x5b, 0xe7, 0xbd, + 0x49, 0x64, 0xda, 0x41, 0x7b, 0x24, 0xc3, 0x71, + 0x22, 0xfd, 0xd1, 0xd1, 0x20, 0xb3, 0x3f, 0x97, + 0xd3, 0x97, 0xb2, 0xaa, 0x18, 0x1c, 0x9e, 0x03, + 0x77, 0x7b, 0x5b, 0x7e, 0xf9, 0xa3, 0xa0, 0xd6, + 0x20, 0x81, 0x2c, 0x38, 0x8f, 0x9d, 0x25, 0xde, + 0xe9, 0xc8, 0xf5, 0xdd, 0x6a, 0x47, 0x9c, 0x65, + 0x04, 0x5a, 0x56, 0xe6, 0xc2, 0xeb, 0xf2, 0x02, + 0x97, 0xe1, 0xb9, 0xd8, 0xe1, 0x24, 0x76, 0x9f, + 0x23, 0x62, 0x39, 0x03, 0x4b, 0xc8, 0xf7, 0x34, + 0x07, 0x49, 0xd6, 0xe7, 0x4d, 0x9a, +}; + +const unsigned char sig[70] = { + 0x30, 0x44, 0x02, 0x20, 0x54, 0x92, 0x28, 0x3b, + 0x83, 0x33, 0x47, 0x56, 0x68, 0x79, 0xb2, 0x0c, + 0x84, 0x80, 0xcc, 0x67, 0x27, 0x8b, 0xfa, 0x48, + 0x43, 0x0d, 0x3c, 0xb4, 0x02, 0x36, 0x87, 0x97, + 0x3e, 0xdf, 0x2f, 0x65, 0x02, 0x20, 0x1b, 0x56, + 0x17, 0x06, 0xe2, 0x26, 0x0f, 0x6a, 0xe9, 0xa9, + 0x70, 0x99, 0x62, 0xeb, 0x3a, 0x04, 0x1a, 0xc4, + 0xa7, 0x03, 0x28, 0x56, 0x7c, 0xed, 0x47, 0x08, + 0x68, 0x73, 0x6a, 0xb6, 0x89, 0x0d, +}; + +const unsigned char pubkey[64] = { + 0x17, 0x5b, 0x27, 0xa6, 0x56, 0xb2, 0x26, 0x0c, + 0x26, 0x0c, 0x55, 0x42, 0x78, 0x17, 0x5d, 0x4c, + 0xf8, 0xa2, 0xfd, 0x1b, 0xb9, 0x54, 0xdf, 0xd5, + 0xeb, 0xbf, 0x22, 0x64, 0xf5, 0x21, 0x9a, 0xc6, + 0x87, 0x5f, 0x90, 0xe6, 0xfd, 0x71, 0x27, 0x9f, + 0xeb, 0xe3, 0x03, 0x44, 0xbc, 0x8d, 0x49, 0xc6, + 0x1c, 0x31, 0x3b, 0x72, 0xae, 0xd4, 0x53, 0xb1, + 0xfe, 0x5d, 0xe1, 0x30, 0xfc, 0x2b, 0x1e, 0xd2, +}; + +const unsigned char pubkey_tpm_rs256[259] = { + 0xc5, 0xb6, 0x9c, 0x06, 0x1d, 0xcf, 0xb9, 0xf2, + 0x5e, 0x99, 0x7d, 0x6d, 0x73, 0xd8, 0x36, 0xc1, + 0x4a, 0x90, 0x05, 0x4d, 0x82, 0x57, 0xc1, 0xb6, + 0x6a, 0xd1, 0x43, 0x03, 0x85, 0xf8, 0x52, 0x4f, + 0xd2, 0x27, 0x91, 0x0b, 0xb5, 0x93, 0xa0, 0x68, + 0xf8, 0x80, 0x1b, 0xaa, 0x65, 0x97, 0x45, 0x11, + 0x86, 0x34, 0xd6, 0x67, 0xf8, 0xd5, 0x12, 0x79, + 0x84, 0xee, 0x70, 0x99, 0x00, 0x63, 0xa8, 0xb4, + 0x43, 0x0b, 0x4c, 0x57, 0x4a, 0xd6, 0x9b, 0x75, + 0x63, 0x8a, 0x46, 0x57, 0xdb, 0x14, 0xc8, 0x71, + 0xd1, 0xb3, 0x07, 0x68, 0x58, 0xbc, 0x55, 0x84, + 0x80, 0x2a, 0xd2, 0x36, 0x9f, 0xc1, 0x64, 0xa0, + 0x11, 0x4b, 0xc9, 0x32, 0x31, 0x3a, 0xd6, 0x87, + 0x26, 0x1a, 0x3a, 0x78, 0x3d, 0x89, 0xdb, 0x00, + 0x28, 0x3b, 0xae, 0x2b, 0x1b, 0x56, 0xe2, 0x8c, + 0x4c, 0x63, 0xac, 0x6e, 0x6c, 0xf7, 0xb5, 0x7d, + 0x4d, 0x0b, 0x9f, 0x06, 0xa0, 0x10, 0x35, 0x38, + 0x20, 0x4d, 0xcc, 0x07, 0xd7, 0x00, 0x4e, 0x86, + 0xba, 0xfe, 0x8b, 0xe4, 0x3f, 0x4a, 0xd6, 0xca, + 0xbf, 0x67, 0x40, 0x1a, 0xa4, 0xda, 0x82, 0x52, + 0x15, 0xb8, 0x14, 0x3a, 0x7c, 0xa9, 0x02, 0xc1, + 0x01, 0x69, 0xc6, 0x51, 0xd4, 0xbc, 0x1f, 0x95, + 0xb2, 0xee, 0x1f, 0xdd, 0xb5, 0x73, 0x16, 0x5e, + 0x29, 0x3f, 0x47, 0xac, 0x65, 0xfb, 0x63, 0x5c, + 0xb9, 0xc8, 0x13, 0x2d, 0xec, 0x85, 0xde, 0x71, + 0x0d, 0x84, 0x93, 0x74, 0x76, 0x91, 0xdd, 0x1d, + 0x6d, 0x3d, 0xc7, 0x36, 0x19, 0x19, 0x86, 0xde, + 0x7c, 0xca, 0xd6, 0xc6, 0x65, 0x7e, 0x4b, 0x24, + 0x9c, 0xce, 0x92, 0x6b, 0x1c, 0xe0, 0xa0, 0xa9, + 0x6c, 0xc3, 0xed, 0x4f, 0x2a, 0x54, 0x07, 0x00, + 0x32, 0x5e, 0x1b, 0x94, 0x37, 0xcd, 0xe2, 0x32, + 0xa8, 0xd5, 0x2c, 0xfb, 0x03, 0x9d, 0x79, 0xdf, + 0x01, 0x00, 0x01, +}; + +const unsigned char pubkey_tpm_es256[64] = { + 0xfb, 0xd6, 0xba, 0x74, 0xe6, 0x6e, 0x5c, 0x87, + 0xef, 0x89, 0xa2, 0xe8, 0x3d, 0x0b, 0xe9, 0x69, + 0x2c, 0x07, 0x07, 0x7a, 0x8a, 0x1e, 0xce, 0x12, + 0xea, 0x3b, 0xb3, 0xf1, 0xf3, 0xd9, 0xc3, 0xe6, + 0x3c, 0x68, 0x51, 0x94, 0x54, 0x8d, 0xeb, 0x9f, + 0xb2, 0x2c, 0x66, 0x75, 0xb6, 0xb7, 0x55, 0x22, + 0x0d, 0x87, 0x59, 0xc4, 0x39, 0x91, 0x62, 0x17, + 0xc2, 0xc3, 0x53, 0xa5, 0x26, 0x97, 0x4f, 0x2d +}; + +const unsigned char id[64] = { + 0x53, 0xfb, 0xdf, 0xaa, 0xce, 0x63, 0xde, 0xc5, + 0xfe, 0x47, 0xe6, 0x52, 0xeb, 0xf3, 0x5d, 0x53, + 0xa8, 0xbf, 0x9d, 0xd6, 0x09, 0x6b, 0x5e, 0x7f, + 0xe0, 0x0d, 0x51, 0x30, 0x85, 0x6a, 0xda, 0x68, + 0x70, 0x85, 0xb0, 0xdb, 0x08, 0x0b, 0x83, 0x2c, + 0xef, 0x44, 0xe2, 0x36, 0x88, 0xee, 0x76, 0x90, + 0x6e, 0x7b, 0x50, 0x3e, 0x9a, 0xa0, 0xd6, 0x3c, + 0x34, 0xe3, 0x83, 0xe7, 0xd1, 0xbd, 0x9f, 0x25, +}; + +const unsigned char id_tpm_rs256[32] = { + 0x89, 0x99, 0x6d, 0x5a, 0x00, 0x29, 0xe5, 0x3e, + 0x6a, 0x1c, 0x72, 0x6d, 0x71, 0x4a, 0x4f, 0x03, + 0x9b, 0x68, 0x17, 0xdb, 0x29, 0x1a, 0x6b, 0x02, + 0x6c, 0x26, 0xf9, 0xbd, 0xc3, 0x0e, 0x38, 0x1a +}; + +const unsigned char id_tpm_es256[32] = { + 0xa8, 0xdf, 0x03, 0xf7, 0xbf, 0x39, 0x51, 0x94, + 0x95, 0x8f, 0xa4, 0x84, 0x97, 0x30, 0xbc, 0x3c, + 0x7e, 0x1c, 0x99, 0x91, 0x4d, 0xae, 0x6d, 0xfb, + 0xdf, 0x53, 0xb5, 0xb6, 0x1f, 0x3a, 0x4e, 0x6a +}; + +const unsigned char attstmt_tpm_rs256[4034] = { + 0xa6, 0x63, 0x61, 0x6c, 0x67, 0x39, 0xff, 0xfe, + 0x63, 0x73, 0x69, 0x67, 0x59, 0x01, 0x00, 0x1c, + 0x09, 0x0d, 0x35, 0x97, 0x22, 0xfc, 0xfe, 0xc0, + 0x58, 0x49, 0x9e, 0xd4, 0x7e, 0x6a, 0x7d, 0xdb, + 0x6d, 0x20, 0x95, 0x5c, 0x0b, 0xd0, 0xd5, 0x72, + 0x4f, 0x15, 0x22, 0x38, 0x97, 0xb2, 0x4b, 0xd0, + 0xef, 0x31, 0x7c, 0xf2, 0x42, 0x19, 0x41, 0xa1, + 0xe2, 0xc5, 0xca, 0xc6, 0x74, 0x95, 0xcf, 0xf9, + 0x41, 0x75, 0x0b, 0x56, 0x39, 0x82, 0x78, 0xf6, + 0x59, 0xf1, 0x09, 0x96, 0x9e, 0x38, 0x7f, 0x14, + 0x9b, 0xf5, 0x36, 0xbb, 0x92, 0x32, 0xc4, 0x64, + 0xe8, 0xff, 0xb4, 0xc7, 0xcf, 0xcd, 0x17, 0x48, + 0x0f, 0x83, 0xd9, 0x44, 0x03, 0x35, 0x26, 0xad, + 0x01, 0xb7, 0x57, 0x06, 0xb3, 0x9c, 0xa0, 0x6e, + 0x2f, 0x58, 0xcb, 0x5c, 0xaa, 0x7c, 0xea, 0x7e, + 0x3f, 0xbc, 0x76, 0xc9, 0x0e, 0x52, 0x39, 0x81, + 0xa9, 0x9e, 0x37, 0x14, 0x1f, 0x50, 0x6a, 0x4f, + 0xd7, 0xfc, 0xd4, 0xfa, 0xf2, 0x18, 0x60, 0xd5, + 0xc3, 0x57, 0x7d, 0x6d, 0x05, 0x28, 0x25, 0xc3, + 0xde, 0x86, 0x85, 0x06, 0x71, 0xfb, 0x84, 0xa2, + 0x07, 0xb6, 0x77, 0xc9, 0x68, 0x41, 0x53, 0x32, + 0x4c, 0xa8, 0x4b, 0xf7, 0x08, 0x84, 0x62, 0x6c, + 0x8a, 0xb6, 0xcf, 0xc1, 0xde, 0x6b, 0x61, 0xc8, + 0xdd, 0xc0, 0x13, 0x70, 0x22, 0x28, 0xe1, 0x0f, + 0x46, 0x02, 0xc6, 0xb1, 0xfa, 0x30, 0xcb, 0xec, + 0xd1, 0x82, 0xfa, 0x51, 0xcb, 0x71, 0x5e, 0x1f, + 0x1b, 0x5f, 0xe0, 0xb0, 0x02, 0x8a, 0x7c, 0x78, + 0xd1, 0xb7, 0x4d, 0x56, 0xb0, 0x92, 0x3e, 0xda, + 0xc7, 0xb1, 0x74, 0xcf, 0x6a, 0x40, 0xeb, 0x98, + 0x1c, 0x2e, 0xf2, 0x86, 0x76, 0xf8, 0x2e, 0x6a, + 0x9f, 0x77, 0x51, 0x64, 0xce, 0xdc, 0x12, 0x85, + 0x84, 0x6b, 0x01, 0xc8, 0xeb, 0xbc, 0x57, 0x6c, + 0x32, 0x26, 0xcb, 0xb2, 0x84, 0x02, 0x2a, 0x33, + 0x15, 0xd9, 0xe3, 0x15, 0xfc, 0x3a, 0x24, 0x63, + 0x76, 0x65, 0x72, 0x63, 0x32, 0x2e, 0x30, 0x63, + 0x78, 0x35, 0x63, 0x82, 0x59, 0x05, 0xc4, 0x30, + 0x82, 0x05, 0xc0, 0x30, 0x82, 0x03, 0xa8, 0xa0, + 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x78, 0xd9, + 0xa8, 0xb2, 0x64, 0xf9, 0x4d, 0x28, 0x82, 0xc0, + 0xd3, 0x1b, 0x40, 0x3c, 0xc8, 0xd9, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x41, 0x31, + 0x3f, 0x30, 0x3d, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x36, 0x45, 0x55, 0x53, 0x2d, 0x53, 0x54, + 0x4d, 0x2d, 0x4b, 0x45, 0x59, 0x49, 0x44, 0x2d, + 0x31, 0x41, 0x44, 0x42, 0x39, 0x39, 0x34, 0x41, + 0x42, 0x35, 0x38, 0x42, 0x45, 0x35, 0x37, 0x41, + 0x30, 0x43, 0x43, 0x39, 0x42, 0x39, 0x30, 0x30, + 0x45, 0x37, 0x38, 0x35, 0x31, 0x45, 0x31, 0x41, + 0x34, 0x33, 0x43, 0x30, 0x38, 0x36, 0x36, 0x30, + 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x37, + 0x31, 0x35, 0x31, 0x31, 0x31, 0x32, 0x31, 0x33, + 0x5a, 0x17, 0x0d, 0x32, 0x35, 0x30, 0x33, 0x32, + 0x31, 0x32, 0x30, 0x32, 0x39, 0x31, 0x35, 0x5a, + 0x30, 0x00, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, + 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, + 0x01, 0x01, 0x00, 0xca, 0xbe, 0x77, 0x9f, 0x45, + 0x97, 0x17, 0x8d, 0x01, 0xe1, 0x18, 0xcc, 0xf0, + 0xb5, 0xed, 0x9a, 0xb7, 0x36, 0xac, 0x05, 0x26, + 0xbe, 0x35, 0xd9, 0x5c, 0x00, 0x5c, 0x5d, 0x8b, + 0x6f, 0x2a, 0xb8, 0xf6, 0x02, 0x4f, 0x33, 0xfe, + 0x84, 0x45, 0x4c, 0x4f, 0x7a, 0xdb, 0xa9, 0x6a, + 0x62, 0x0f, 0x19, 0x35, 0x5d, 0xd2, 0x34, 0x1a, + 0x9d, 0x73, 0x55, 0xe5, 0x3e, 0x04, 0xa2, 0xd6, + 0xbe, 0xe7, 0x5a, 0xb9, 0x16, 0x6c, 0x55, 0x18, + 0xa8, 0x4b, 0xb2, 0x37, 0xb9, 0xa3, 0x87, 0xfc, + 0x76, 0xa8, 0x55, 0xc9, 0xe7, 0x30, 0xe5, 0x0e, + 0x3c, 0x7b, 0x74, 0xd2, 0x1e, 0xa8, 0x05, 0xd5, + 0xe2, 0xe3, 0xcb, 0xaf, 0x63, 0x33, 0x12, 0xaa, + 0xfd, 0x31, 0x32, 0x71, 0x4f, 0x41, 0x96, 0x05, + 0xb5, 0x69, 0x73, 0x45, 0xbe, 0x6f, 0x90, 0xd9, + 0x10, 0x36, 0xaf, 0x7a, 0x1c, 0xf1, 0x6d, 0x14, + 0xb0, 0x1e, 0xbb, 0xae, 0x1c, 0x35, 0xec, 0x1c, + 0xb5, 0x0e, 0xf6, 0x33, 0x98, 0x13, 0x4e, 0x44, + 0x7b, 0x5c, 0x97, 0x47, 0xed, 0x4f, 0xfe, 0xbd, + 0x08, 0xd2, 0xa9, 0xc6, 0xbe, 0x8c, 0x04, 0x9e, + 0xdc, 0x3d, 0xbe, 0x98, 0xe9, 0x2a, 0xb1, 0xf4, + 0xfa, 0x45, 0xf9, 0xc8, 0x9a, 0x55, 0x85, 0x26, + 0xfc, 0x5f, 0xad, 0x00, 0x8b, 0xc8, 0x41, 0xf2, + 0x86, 0x4e, 0xba, 0x55, 0x1c, 0xb2, 0x89, 0xe8, + 0x85, 0x6e, 0x1e, 0x02, 0x9f, 0x55, 0x70, 0xbe, + 0xfd, 0xe7, 0x9f, 0xba, 0x59, 0xa0, 0x2e, 0x9a, + 0x74, 0x11, 0xe7, 0xad, 0xa9, 0xc7, 0x7b, 0x58, + 0xc4, 0x16, 0xd3, 0x35, 0xcb, 0x61, 0x00, 0xec, + 0x36, 0x4a, 0xa3, 0x51, 0xa3, 0xdd, 0x61, 0xb6, + 0xd6, 0x29, 0xcb, 0x76, 0xe1, 0xab, 0x51, 0x3a, + 0xe8, 0xbf, 0xdb, 0x09, 0x4a, 0x39, 0x96, 0xd9, + 0xac, 0x8f, 0x6c, 0x62, 0xe0, 0x03, 0x23, 0x24, + 0xbe, 0xd4, 0x83, 0x02, 0x03, 0x01, 0x00, 0x01, + 0xa3, 0x82, 0x01, 0xf3, 0x30, 0x82, 0x01, 0xef, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, + 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, + 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, + 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x6d, + 0x06, 0x03, 0x55, 0x1d, 0x20, 0x01, 0x01, 0xff, + 0x04, 0x63, 0x30, 0x61, 0x30, 0x5f, 0x06, 0x09, + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, + 0x1f, 0x30, 0x52, 0x30, 0x50, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, + 0x44, 0x1e, 0x42, 0x00, 0x54, 0x00, 0x43, 0x00, + 0x50, 0x00, 0x41, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x54, 0x00, 0x72, 0x00, 0x75, 0x00, 0x73, 0x00, + 0x74, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x50, 0x00, 0x6c, 0x00, 0x61, 0x00, + 0x74, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00, + 0x6d, 0x00, 0x20, 0x00, 0x20, 0x00, 0x49, 0x00, + 0x64, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, + 0x69, 0x00, 0x74, 0x00, 0x79, 0x30, 0x10, 0x06, + 0x03, 0x55, 0x1d, 0x25, 0x04, 0x09, 0x30, 0x07, + 0x06, 0x05, 0x67, 0x81, 0x05, 0x08, 0x03, 0x30, + 0x59, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x01, 0x01, + 0xff, 0x04, 0x4f, 0x30, 0x4d, 0xa4, 0x4b, 0x30, + 0x49, 0x31, 0x16, 0x30, 0x14, 0x06, 0x05, 0x67, + 0x81, 0x05, 0x02, 0x01, 0x0c, 0x0b, 0x69, 0x64, + 0x3a, 0x35, 0x33, 0x35, 0x34, 0x34, 0x44, 0x32, + 0x30, 0x31, 0x17, 0x30, 0x15, 0x06, 0x05, 0x67, + 0x81, 0x05, 0x02, 0x02, 0x0c, 0x0c, 0x53, 0x54, + 0x33, 0x33, 0x48, 0x54, 0x50, 0x48, 0x41, 0x48, + 0x42, 0x34, 0x31, 0x16, 0x30, 0x14, 0x06, 0x05, + 0x67, 0x81, 0x05, 0x02, 0x03, 0x0c, 0x0b, 0x69, + 0x64, 0x3a, 0x30, 0x30, 0x34, 0x39, 0x30, 0x30, + 0x30, 0x34, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, + 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xb8, + 0x5f, 0xd5, 0x67, 0xca, 0x92, 0xc4, 0x0e, 0xcf, + 0x0c, 0xd8, 0x1f, 0x6d, 0x3f, 0x03, 0x55, 0x6f, + 0x38, 0xa6, 0x51, 0x30, 0x1d, 0x06, 0x03, 0x55, + 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xd4, 0x04, + 0x64, 0xfc, 0x6e, 0x50, 0x0a, 0x56, 0x48, 0x0f, + 0x05, 0xa9, 0x00, 0xb7, 0x1d, 0x5e, 0x57, 0x08, + 0xd5, 0xdc, 0x30, 0x81, 0xb2, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, + 0x81, 0xa5, 0x30, 0x81, 0xa2, 0x30, 0x81, 0x9f, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x30, 0x02, 0x86, 0x81, 0x92, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x61, 0x7a, 0x63, 0x73, + 0x70, 0x72, 0x6f, 0x64, 0x65, 0x75, 0x73, 0x61, + 0x69, 0x6b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, + 0x68, 0x2e, 0x62, 0x6c, 0x6f, 0x62, 0x2e, 0x63, + 0x6f, 0x72, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, + 0x6f, 0x77, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x2f, + 0x65, 0x75, 0x73, 0x2d, 0x73, 0x74, 0x6d, 0x2d, + 0x6b, 0x65, 0x79, 0x69, 0x64, 0x2d, 0x31, 0x61, + 0x64, 0x62, 0x39, 0x39, 0x34, 0x61, 0x62, 0x35, + 0x38, 0x62, 0x65, 0x35, 0x37, 0x61, 0x30, 0x63, + 0x63, 0x39, 0x62, 0x39, 0x30, 0x30, 0x65, 0x37, + 0x38, 0x35, 0x31, 0x65, 0x31, 0x61, 0x34, 0x33, + 0x63, 0x30, 0x38, 0x36, 0x36, 0x30, 0x2f, 0x61, + 0x62, 0x64, 0x36, 0x31, 0x35, 0x66, 0x32, 0x2d, + 0x31, 0x35, 0x38, 0x61, 0x2d, 0x34, 0x35, 0x38, + 0x65, 0x2d, 0x61, 0x31, 0x35, 0x35, 0x2d, 0x37, + 0x63, 0x34, 0x63, 0x38, 0x63, 0x62, 0x31, 0x33, + 0x63, 0x36, 0x35, 0x2e, 0x63, 0x65, 0x72, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, + 0x02, 0x01, 0x00, 0xa2, 0x10, 0xc5, 0xbf, 0x41, + 0xa6, 0xba, 0x8c, 0x72, 0xca, 0x0f, 0x3e, 0x5e, + 0x7f, 0xe2, 0xcb, 0x60, 0xb8, 0x3f, 0xfb, 0xde, + 0x03, 0xe2, 0xfe, 0x20, 0x29, 0xdf, 0x11, 0xf5, + 0xb0, 0x50, 0x6d, 0x32, 0xe8, 0x1b, 0x05, 0xad, + 0x6b, 0x60, 0xb5, 0xed, 0xf3, 0xa4, 0x4a, 0xea, + 0x09, 0xe5, 0x65, 0x7e, 0xe0, 0xd5, 0x3a, 0x6a, + 0xdb, 0x64, 0xb7, 0x07, 0x8f, 0xa1, 0x63, 0xb3, + 0x89, 0x8a, 0xac, 0x49, 0x97, 0xa0, 0x9a, 0xa3, + 0xd3, 0x3a, 0xc2, 0x13, 0xb2, 0xbb, 0xab, 0x0d, + 0xf2, 0x35, 0xc5, 0x03, 0xde, 0x1c, 0xad, 0x6a, + 0x03, 0x0a, 0x4c, 0xe1, 0x37, 0x8f, 0xbc, 0x13, + 0xc0, 0x9a, 0x17, 0xd4, 0x2e, 0x36, 0x17, 0x51, + 0x12, 0xb0, 0x79, 0xbf, 0x9b, 0xb3, 0xb0, 0x74, + 0x25, 0x81, 0x7e, 0x21, 0x31, 0xb7, 0xc2, 0x5e, + 0xfb, 0x36, 0xab, 0xf3, 0x7a, 0x5f, 0xa4, 0x5e, + 0x8f, 0x0c, 0xbd, 0xcf, 0xf5, 0x50, 0xe7, 0x0c, + 0x51, 0x55, 0x48, 0xe6, 0x15, 0xb6, 0xd4, 0xaf, + 0x95, 0x72, 0x56, 0x94, 0xf7, 0x0e, 0xd6, 0x90, + 0xe3, 0xd3, 0x5d, 0xbd, 0x93, 0xa1, 0xbd, 0x6c, + 0xe4, 0xf2, 0x39, 0x4d, 0x54, 0x74, 0xcf, 0xf5, + 0xeb, 0x70, 0xdb, 0x4f, 0x52, 0xcd, 0x39, 0x8f, + 0x11, 0x54, 0x28, 0x06, 0x29, 0x8f, 0x23, 0xde, + 0x9e, 0x2f, 0x7b, 0xb6, 0x5f, 0xa3, 0x89, 0x04, + 0x99, 0x0a, 0xf1, 0x2d, 0xf9, 0x66, 0xd3, 0x13, + 0x45, 0xbd, 0x6c, 0x22, 0x57, 0xf5, 0xb1, 0xb9, + 0xdf, 0x5b, 0x7b, 0x1a, 0x3a, 0xdd, 0x6b, 0xc7, + 0x35, 0x88, 0xed, 0xc4, 0x09, 0x70, 0x4e, 0x5f, + 0xb5, 0x3e, 0xd1, 0x0b, 0xd0, 0xca, 0xef, 0x0b, + 0xe9, 0x8b, 0x6f, 0xc3, 0x16, 0xc3, 0x3d, 0x79, + 0x06, 0xef, 0x81, 0xf0, 0x60, 0x0b, 0x32, 0xe3, + 0x86, 0x6b, 0x92, 0x38, 0x90, 0x62, 0xed, 0x84, + 0x3a, 0xb7, 0x45, 0x43, 0x2e, 0xd0, 0x3a, 0x71, + 0x9e, 0x80, 0xcc, 0x9c, 0xac, 0x27, 0x10, 0x91, + 0xb7, 0xb2, 0xbd, 0x41, 0x40, 0xa7, 0xb7, 0xcf, + 0xe7, 0x38, 0xca, 0x68, 0xdd, 0x62, 0x09, 0xff, + 0x68, 0xce, 0xba, 0xe2, 0x07, 0x49, 0x09, 0xe7, + 0x1f, 0xdf, 0xe6, 0x26, 0xe5, 0x0f, 0xa9, 0xbf, + 0x2a, 0x5b, 0x67, 0x92, 0xa1, 0x10, 0x53, 0xb2, + 0x7a, 0x07, 0x29, 0x9d, 0xfd, 0x6d, 0xb6, 0x3b, + 0x45, 0xc1, 0x94, 0xcb, 0x1c, 0xc3, 0xce, 0xf6, + 0x8a, 0x1a, 0x81, 0x66, 0xb0, 0xa5, 0x14, 0xc7, + 0x9e, 0x1f, 0x6e, 0xb6, 0xff, 0x8b, 0x90, 0x87, + 0x3a, 0x3f, 0xa8, 0xc2, 0x2d, 0x8f, 0x6f, 0xdb, + 0xb4, 0xc4, 0x14, 0x3c, 0x1d, 0x12, 0x1d, 0x6d, + 0xcf, 0xa6, 0x04, 0x6a, 0xa8, 0x13, 0x5e, 0xf2, + 0x5e, 0x77, 0x80, 0x6b, 0x85, 0x83, 0xfe, 0xbb, + 0xeb, 0x70, 0xcb, 0x5f, 0xe4, 0x95, 0xaa, 0x0f, + 0x61, 0x36, 0x7c, 0xbb, 0x22, 0x1e, 0xba, 0x98, + 0x43, 0x52, 0x33, 0xae, 0xed, 0x5d, 0x10, 0x2c, + 0xb3, 0xa9, 0x31, 0x8e, 0x60, 0x54, 0xaf, 0x40, + 0x6d, 0x2e, 0x18, 0xc2, 0x6a, 0xf4, 0x7b, 0x9a, + 0x73, 0x0f, 0x58, 0x69, 0x23, 0xbb, 0xc4, 0x84, + 0x53, 0x30, 0xe2, 0xd6, 0x1e, 0x10, 0xc1, 0xec, + 0x82, 0x13, 0xab, 0x53, 0x86, 0xa2, 0xb9, 0xda, + 0xbb, 0x3a, 0xa2, 0xbe, 0xb0, 0x10, 0x99, 0x0e, + 0xe5, 0x9c, 0xc9, 0xf1, 0xce, 0x76, 0x46, 0xea, + 0x86, 0xaa, 0x36, 0x83, 0x99, 0x09, 0x9b, 0x30, + 0xd3, 0x26, 0xc7, 0xdf, 0x66, 0xc7, 0xf0, 0xdd, + 0x08, 0x09, 0x15, 0x15, 0x21, 0x49, 0x46, 0xd8, + 0x8a, 0x66, 0xca, 0x62, 0x9c, 0x79, 0x1d, 0x81, + 0xea, 0x5d, 0x82, 0xb0, 0xa6, 0x6b, 0x5c, 0xf5, + 0xb8, 0x8c, 0xf6, 0x16, 0x01, 0x2c, 0xf8, 0x27, + 0xf8, 0xcf, 0x88, 0xfe, 0xf3, 0xa4, 0xfc, 0x17, + 0x97, 0xe7, 0x07, 0x59, 0x06, 0xef, 0x30, 0x82, + 0x06, 0xeb, 0x30, 0x82, 0x04, 0xd3, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x13, 0x33, 0x00, 0x00, + 0x02, 0x39, 0xf9, 0xbb, 0x6a, 0x1d, 0x49, 0x64, + 0x47, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x02, 0x39, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, + 0x81, 0x8c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, + 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, + 0x65, 0x64, 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e, + 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, + 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, + 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x36, + 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x2d, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, + 0x66, 0x74, 0x20, 0x54, 0x50, 0x4d, 0x20, 0x52, + 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x32, 0x30, 0x31, 0x34, 0x30, 0x1e, + 0x17, 0x0d, 0x31, 0x39, 0x30, 0x33, 0x32, 0x31, + 0x32, 0x30, 0x32, 0x39, 0x31, 0x35, 0x5a, 0x17, + 0x0d, 0x32, 0x35, 0x30, 0x33, 0x32, 0x31, 0x32, + 0x30, 0x32, 0x39, 0x31, 0x35, 0x5a, 0x30, 0x41, + 0x31, 0x3f, 0x30, 0x3d, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x36, 0x45, 0x55, 0x53, 0x2d, 0x53, + 0x54, 0x4d, 0x2d, 0x4b, 0x45, 0x59, 0x49, 0x44, + 0x2d, 0x31, 0x41, 0x44, 0x42, 0x39, 0x39, 0x34, + 0x41, 0x42, 0x35, 0x38, 0x42, 0x45, 0x35, 0x37, + 0x41, 0x30, 0x43, 0x43, 0x39, 0x42, 0x39, 0x30, + 0x30, 0x45, 0x37, 0x38, 0x35, 0x31, 0x45, 0x31, + 0x41, 0x34, 0x33, 0x43, 0x30, 0x38, 0x36, 0x36, + 0x30, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, + 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, + 0x01, 0x00, 0xdb, 0xe2, 0x23, 0xf9, 0x86, 0x8f, + 0xa9, 0x71, 0x9f, 0x8b, 0xf9, 0x7c, 0xe9, 0x45, + 0x2d, 0x59, 0x56, 0x5e, 0x96, 0xf4, 0xdd, 0x9a, + 0x12, 0xcd, 0x90, 0x1a, 0x0c, 0xb5, 0x03, 0xbf, + 0x09, 0xbe, 0xbf, 0xf7, 0x55, 0x52, 0xe8, 0x39, + 0x4c, 0xbe, 0x2a, 0x28, 0x88, 0x78, 0x39, 0xa7, + 0xcb, 0xf9, 0x4c, 0x55, 0xd2, 0x31, 0x96, 0x3b, + 0x48, 0xa2, 0xf3, 0xf6, 0xd3, 0x1a, 0x81, 0x7f, + 0x90, 0x62, 0xab, 0xec, 0x5a, 0xc7, 0xa0, 0x7f, + 0x81, 0x32, 0x27, 0x9b, 0x29, 0x75, 0x7d, 0x1e, + 0x96, 0xc5, 0xfa, 0x0e, 0x7c, 0xe0, 0x60, 0x96, + 0x7a, 0xca, 0x94, 0xba, 0xe6, 0xb2, 0x69, 0xdd, + 0xc4, 0x7d, 0xbb, 0xd3, 0xc4, 0xb4, 0x6e, 0x00, + 0x86, 0x1f, 0x9d, 0x25, 0xe8, 0xae, 0xc7, 0x10, + 0x84, 0xdc, 0xc0, 0x34, 0x24, 0x6e, 0xf7, 0xfc, + 0xdd, 0x3d, 0x32, 0x7a, 0x43, 0x96, 0xd6, 0xc8, + 0x7b, 0xf4, 0x9b, 0x3d, 0xa7, 0x1e, 0xba, 0x4d, + 0xd0, 0x3b, 0x3d, 0x84, 0x9a, 0xd1, 0x25, 0x22, + 0x5d, 0x00, 0x44, 0xb0, 0x59, 0xb7, 0x40, 0xc5, + 0xa3, 0x53, 0x53, 0xaf, 0x8f, 0x9e, 0xfd, 0x8f, + 0x1e, 0x02, 0xd3, 0x4f, 0xf7, 0x09, 0xce, 0xc5, + 0xc6, 0x71, 0x5c, 0xe9, 0xe8, 0x7a, 0xb5, 0x6b, + 0xa4, 0xbf, 0x0b, 0xd9, 0xb6, 0xfa, 0x24, 0xb0, + 0xcd, 0x52, 0x22, 0x1d, 0x7e, 0xe8, 0x15, 0x2f, + 0x1e, 0x5e, 0xa2, 0xec, 0xd3, 0xa8, 0x02, 0x77, + 0xb9, 0x55, 0x9a, 0xcf, 0xcc, 0xd7, 0x08, 0x20, + 0xa5, 0xda, 0x39, 0x9a, 0x30, 0x76, 0x90, 0x37, + 0xa7, 0x60, 0xdf, 0x18, 0x12, 0x65, 0x17, 0xaa, + 0xdd, 0x48, 0xd5, 0x12, 0x1d, 0x4c, 0x83, 0x5d, + 0x81, 0x07, 0x1d, 0x18, 0x81, 0x40, 0x55, 0x60, + 0x8f, 0xa3, 0x6b, 0x34, 0x1e, 0xd5, 0xe6, 0xcf, + 0x52, 0x73, 0x77, 0x4a, 0x50, 0x4f, 0x1b, 0x0f, + 0x39, 0xc3, 0x0d, 0x16, 0xf9, 0xbb, 0x4c, 0x77, + 0xf6, 0x4e, 0xac, 0x9c, 0xfe, 0xe8, 0xbb, 0x52, + 0xa5, 0x0a, 0x0e, 0x9b, 0xf0, 0x0d, 0xef, 0xfb, + 0x6f, 0x89, 0x34, 0x7d, 0x47, 0xec, 0x14, 0x6a, + 0xf4, 0x0a, 0xe1, 0x60, 0x44, 0x73, 0x7b, 0xa0, + 0xab, 0x5b, 0x8c, 0x43, 0xa6, 0x05, 0x42, 0x61, + 0x46, 0xaa, 0x1c, 0xf5, 0xec, 0x2c, 0x86, 0x85, + 0x21, 0x99, 0xdf, 0x45, 0x8e, 0xf4, 0xd1, 0x1e, + 0xfb, 0xcd, 0x9b, 0x94, 0x32, 0xe0, 0xa0, 0xcc, + 0x4f, 0xad, 0xae, 0x44, 0x8b, 0x86, 0x27, 0x91, + 0xfe, 0x60, 0x9f, 0xf2, 0x63, 0x30, 0x6c, 0x5d, + 0x8d, 0xbc, 0xab, 0xd4, 0xf5, 0xa2, 0xb2, 0x74, + 0xe8, 0xd4, 0x95, 0xf2, 0xd6, 0x03, 0x8b, 0xc9, + 0xa3, 0x52, 0xe7, 0x63, 0x05, 0x64, 0x50, 0xe5, + 0x0a, 0x6a, 0xa0, 0x6c, 0x50, 0xcd, 0x37, 0x98, + 0xa8, 0x87, 0x02, 0x38, 0x5b, 0x6c, 0x02, 0x69, + 0x3d, 0x1f, 0x95, 0x74, 0x4d, 0x46, 0x76, 0x2a, + 0x9d, 0x62, 0xd4, 0xc7, 0x1b, 0xf9, 0x31, 0xa6, + 0x51, 0xee, 0x7b, 0xc8, 0xe4, 0x6e, 0x3a, 0xcf, + 0x4f, 0x4f, 0x49, 0x8a, 0xf5, 0x4f, 0x25, 0x93, + 0x23, 0x02, 0xef, 0x79, 0xa6, 0x27, 0xbe, 0x5a, + 0xe7, 0x74, 0xb7, 0xd7, 0xa8, 0xc1, 0xae, 0x55, + 0x88, 0xa4, 0xc7, 0x4d, 0xb7, 0x62, 0xf0, 0xf9, + 0x5b, 0xbf, 0x47, 0x5b, 0xfe, 0xcc, 0x0b, 0x89, + 0x19, 0x65, 0x4b, 0x6f, 0xdf, 0x4f, 0x7d, 0x4d, + 0x96, 0x42, 0x0d, 0x2a, 0xa1, 0xbd, 0x3e, 0x70, + 0x92, 0xba, 0xc8, 0x59, 0xd5, 0x1d, 0x3a, 0x98, + 0x53, 0x75, 0xa6, 0x32, 0xc8, 0x72, 0x03, 0x46, + 0x5f, 0x5c, 0x13, 0xa4, 0xdb, 0xc7, 0x55, 0x35, + 0x22, 0x0d, 0xc6, 0x17, 0x85, 0xbd, 0x46, 0x4b, + 0xfa, 0x1e, 0x49, 0xc2, 0xfe, 0x1e, 0xf9, 0x62, + 0x89, 0x56, 0x84, 0xdf, 0xa0, 0xfb, 0xfd, 0x93, + 0xa4, 0x25, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, + 0x82, 0x01, 0x8e, 0x30, 0x82, 0x01, 0x8a, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, + 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x84, 0x30, + 0x1b, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x14, + 0x30, 0x12, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, + 0x01, 0x82, 0x37, 0x15, 0x24, 0x06, 0x05, 0x67, + 0x81, 0x05, 0x08, 0x03, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x1d, 0x20, 0x04, 0x0f, 0x30, 0x0d, 0x30, + 0x0b, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, + 0x82, 0x37, 0x15, 0x1f, 0x30, 0x12, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, + 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, + 0x16, 0x04, 0x14, 0xb8, 0x5f, 0xd5, 0x67, 0xca, + 0x92, 0xc4, 0x0e, 0xcf, 0x0c, 0xd8, 0x1f, 0x6d, + 0x3f, 0x03, 0x55, 0x6f, 0x38, 0xa6, 0x51, 0x30, + 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0x7a, 0x8c, 0x0a, 0xce, + 0x2f, 0x48, 0x62, 0x17, 0xe2, 0x94, 0xd1, 0xae, + 0x55, 0xc1, 0x52, 0xec, 0x71, 0x74, 0xa4, 0x56, + 0x30, 0x70, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, + 0x69, 0x30, 0x67, 0x30, 0x65, 0xa0, 0x63, 0xa0, + 0x61, 0x86, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x3a, + 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6d, 0x69, + 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x6f, + 0x70, 0x73, 0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x4d, + 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, + 0x25, 0x32, 0x30, 0x54, 0x50, 0x4d, 0x25, 0x32, + 0x30, 0x52, 0x6f, 0x6f, 0x74, 0x25, 0x32, 0x30, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x25, 0x32, 0x30, 0x41, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x25, + 0x32, 0x30, 0x32, 0x30, 0x31, 0x34, 0x2e, 0x63, + 0x72, 0x6c, 0x30, 0x7d, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x71, + 0x30, 0x6f, 0x30, 0x6d, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x61, + 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, + 0x77, 0x77, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, + 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x6b, 0x69, 0x6f, 0x70, 0x73, 0x2f, + 0x63, 0x65, 0x72, 0x74, 0x73, 0x2f, 0x4d, 0x69, + 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x25, + 0x32, 0x30, 0x54, 0x50, 0x4d, 0x25, 0x32, 0x30, + 0x52, 0x6f, 0x6f, 0x74, 0x25, 0x32, 0x30, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x25, 0x32, 0x30, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x25, 0x32, + 0x30, 0x32, 0x30, 0x31, 0x34, 0x2e, 0x63, 0x72, + 0x74, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, + 0x03, 0x82, 0x02, 0x01, 0x00, 0x41, 0xaa, 0xfe, + 0x28, 0x6c, 0xf7, 0x6b, 0x53, 0xde, 0x77, 0xc0, + 0x80, 0x50, 0x94, 0xd9, 0xdb, 0x46, 0x8e, 0x6a, + 0x93, 0xa9, 0x10, 0x37, 0x27, 0x1f, 0xf5, 0x70, + 0xf1, 0xa8, 0xcf, 0xa1, 0x45, 0x86, 0x2a, 0xdd, + 0x8f, 0xb8, 0xb5, 0xc1, 0xe6, 0xcf, 0x8a, 0xfa, + 0x32, 0xa1, 0x4b, 0xb7, 0xa4, 0xbf, 0x0a, 0x48, + 0xcb, 0x42, 0x63, 0x71, 0xc1, 0x96, 0xb9, 0x3a, + 0x37, 0x84, 0x0e, 0x24, 0x39, 0xeb, 0x58, 0xce, + 0x3d, 0xb7, 0xa9, 0x44, 0x92, 0x59, 0xb9, 0xff, + 0xdb, 0x18, 0xbe, 0x6a, 0x5e, 0xe7, 0xce, 0xef, + 0xb8, 0x40, 0x53, 0xaf, 0xc1, 0x9b, 0xfb, 0x42, + 0x99, 0x7e, 0x9d, 0x05, 0x2b, 0x71, 0x0a, 0x7a, + 0x7a, 0x44, 0xd1, 0x31, 0xca, 0xf0, 0x5f, 0x74, + 0x85, 0xa9, 0xe2, 0xbc, 0xc8, 0x0c, 0xad, 0x57, + 0xd1, 0xe9, 0x48, 0x90, 0x88, 0x57, 0x86, 0xd7, + 0xc5, 0xc9, 0xe6, 0xb2, 0x5e, 0x5f, 0x13, 0xdc, + 0x10, 0x7f, 0xdf, 0x63, 0x8a, 0xd5, 0x9e, 0x90, + 0xc2, 0x75, 0x53, 0x1e, 0x68, 0x17, 0x2b, 0x03, + 0x29, 0x15, 0x03, 0xc5, 0x8c, 0x66, 0x3e, 0xae, + 0xbd, 0x4a, 0x32, 0x7e, 0x59, 0x89, 0x0b, 0x84, + 0xc2, 0xd9, 0x90, 0xfa, 0x02, 0x22, 0x90, 0x8d, + 0x9c, 0xb6, 0x0c, 0x4d, 0xe1, 0x28, 0x76, 0xd7, + 0x82, 0xc3, 0x36, 0xc2, 0xa3, 0x2a, 0x52, 0xe5, + 0xfe, 0x3c, 0x8f, 0xe3, 0x4b, 0xda, 0x6a, 0xdb, + 0xc0, 0x7a, 0x3c, 0x57, 0xfa, 0x85, 0x8f, 0xfb, + 0x62, 0xc3, 0xa1, 0x38, 0xce, 0x84, 0xf2, 0xba, + 0x12, 0xf4, 0x30, 0x2a, 0x4a, 0x94, 0xa9, 0x35, + 0x2c, 0x7d, 0x11, 0xc7, 0x68, 0x1f, 0x47, 0xaa, + 0x57, 0x43, 0x06, 0x70, 0x79, 0x8c, 0xb6, 0x3b, + 0x5d, 0x57, 0xf3, 0xf3, 0xc0, 0x2c, 0xc5, 0xde, + 0x41, 0x99, 0xf6, 0xdd, 0x55, 0x8a, 0xe4, 0x13, + 0xca, 0xc9, 0xec, 0x69, 0x93, 0x13, 0x48, 0xf0, + 0x5f, 0xda, 0x2e, 0xfd, 0xfb, 0xa9, 0x1b, 0x92, + 0xde, 0x49, 0x71, 0x37, 0x8c, 0x3f, 0xc2, 0x08, + 0x0a, 0x83, 0x25, 0xf1, 0x6e, 0x0a, 0xe3, 0x55, + 0x85, 0x96, 0x9a, 0x2d, 0xa2, 0xc0, 0xa1, 0xee, + 0xfe, 0x23, 0x3b, 0x69, 0x22, 0x03, 0xfd, 0xcc, + 0x8a, 0xdd, 0xb4, 0x53, 0x8d, 0x84, 0xa6, 0xac, + 0xe0, 0x1e, 0x07, 0xe5, 0xd7, 0xf9, 0xcb, 0xb9, + 0xe3, 0x9a, 0xb7, 0x84, 0x70, 0xa1, 0x93, 0xd6, + 0x02, 0x1e, 0xfe, 0xdb, 0x28, 0x7c, 0xf7, 0xd4, + 0x62, 0x6f, 0x80, 0x75, 0xc8, 0xd8, 0x35, 0x26, + 0x0c, 0xcb, 0x84, 0xed, 0xbb, 0x95, 0xdf, 0x7f, + 0xd5, 0xbb, 0x00, 0x96, 0x97, 0x32, 0xe7, 0xba, + 0xe8, 0x29, 0xb5, 0x1a, 0x51, 0x81, 0xbb, 0x04, + 0xd1, 0x21, 0x76, 0x34, 0x6d, 0x1e, 0x93, 0x96, + 0x1f, 0x96, 0x53, 0x5f, 0x5c, 0x9e, 0xf3, 0x9d, + 0x82, 0x1c, 0x39, 0x36, 0x59, 0xae, 0xc9, 0x3c, + 0x53, 0x4a, 0x67, 0x65, 0x6e, 0xbf, 0xa6, 0xac, + 0x3e, 0xda, 0xb2, 0xa7, 0x63, 0x07, 0x17, 0xe1, + 0x5b, 0xda, 0x6a, 0x31, 0x9f, 0xfb, 0xb4, 0xea, + 0xa1, 0x97, 0x08, 0x6e, 0xb2, 0x68, 0xf3, 0x72, + 0x76, 0x99, 0xe8, 0x00, 0x46, 0x88, 0x26, 0xe1, + 0x3c, 0x07, 0x2b, 0x78, 0x49, 0xda, 0x79, 0x3a, + 0xbd, 0x6f, 0xca, 0x5c, 0xa0, 0xa8, 0xed, 0x34, + 0xcc, 0xdb, 0x13, 0xe2, 0x51, 0x9b, 0x3d, 0x03, + 0xac, 0xc7, 0xf6, 0x32, 0xe1, 0x11, 0x5d, 0xe1, + 0xc5, 0xfd, 0x9e, 0x7a, 0xcd, 0x06, 0xb9, 0xe6, + 0xfc, 0xe0, 0x03, 0x31, 0xf4, 0x4a, 0xa9, 0x3b, + 0x79, 0x01, 0xb0, 0x64, 0x68, 0x9f, 0x6e, 0x76, + 0xa1, 0xcc, 0xec, 0x17, 0x41, 0x9d, 0xd4, 0x5b, + 0x4e, 0x9d, 0xe5, 0x46, 0xd4, 0x6b, 0x60, 0x2a, + 0x23, 0xb5, 0x7a, 0x89, 0x7c, 0x27, 0x96, 0x65, + 0x97, 0x56, 0xec, 0x98, 0xe3, 0x67, 0x70, 0x75, + 0x62, 0x41, 0x72, 0x65, 0x61, 0x59, 0x01, 0x36, + 0x00, 0x01, 0x00, 0x0b, 0x00, 0x06, 0x04, 0x72, + 0x00, 0x20, 0x9d, 0xff, 0xcb, 0xf3, 0x6c, 0x38, + 0x3a, 0xe6, 0x99, 0xfb, 0x98, 0x68, 0xdc, 0x6d, + 0xcb, 0x89, 0xd7, 0x15, 0x38, 0x84, 0xbe, 0x28, + 0x03, 0x92, 0x2c, 0x12, 0x41, 0x58, 0xbf, 0xad, + 0x22, 0xae, 0x00, 0x10, 0x00, 0x10, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc5, 0xb6, + 0x9c, 0x06, 0x1d, 0xcf, 0xb9, 0xf2, 0x5e, 0x99, + 0x7d, 0x6d, 0x73, 0xd8, 0x36, 0xc1, 0x4a, 0x90, + 0x05, 0x4d, 0x82, 0x57, 0xc1, 0xb6, 0x6a, 0xd1, + 0x43, 0x03, 0x85, 0xf8, 0x52, 0x4f, 0xd2, 0x27, + 0x91, 0x0b, 0xb5, 0x93, 0xa0, 0x68, 0xf8, 0x80, + 0x1b, 0xaa, 0x65, 0x97, 0x45, 0x11, 0x86, 0x34, + 0xd6, 0x67, 0xf8, 0xd5, 0x12, 0x79, 0x84, 0xee, + 0x70, 0x99, 0x00, 0x63, 0xa8, 0xb4, 0x43, 0x0b, + 0x4c, 0x57, 0x4a, 0xd6, 0x9b, 0x75, 0x63, 0x8a, + 0x46, 0x57, 0xdb, 0x14, 0xc8, 0x71, 0xd1, 0xb3, + 0x07, 0x68, 0x58, 0xbc, 0x55, 0x84, 0x80, 0x2a, + 0xd2, 0x36, 0x9f, 0xc1, 0x64, 0xa0, 0x11, 0x4b, + 0xc9, 0x32, 0x31, 0x3a, 0xd6, 0x87, 0x26, 0x1a, + 0x3a, 0x78, 0x3d, 0x89, 0xdb, 0x00, 0x28, 0x3b, + 0xae, 0x2b, 0x1b, 0x56, 0xe2, 0x8c, 0x4c, 0x63, + 0xac, 0x6e, 0x6c, 0xf7, 0xb5, 0x7d, 0x4d, 0x0b, + 0x9f, 0x06, 0xa0, 0x10, 0x35, 0x38, 0x20, 0x4d, + 0xcc, 0x07, 0xd7, 0x00, 0x4e, 0x86, 0xba, 0xfe, + 0x8b, 0xe4, 0x3f, 0x4a, 0xd6, 0xca, 0xbf, 0x67, + 0x40, 0x1a, 0xa4, 0xda, 0x82, 0x52, 0x15, 0xb8, + 0x14, 0x3a, 0x7c, 0xa9, 0x02, 0xc1, 0x01, 0x69, + 0xc6, 0x51, 0xd4, 0xbc, 0x1f, 0x95, 0xb2, 0xee, + 0x1f, 0xdd, 0xb5, 0x73, 0x16, 0x5e, 0x29, 0x3f, + 0x47, 0xac, 0x65, 0xfb, 0x63, 0x5c, 0xb9, 0xc8, + 0x13, 0x2d, 0xec, 0x85, 0xde, 0x71, 0x0d, 0x84, + 0x93, 0x74, 0x76, 0x91, 0xdd, 0x1d, 0x6d, 0x3d, + 0xc7, 0x36, 0x19, 0x19, 0x86, 0xde, 0x7c, 0xca, + 0xd6, 0xc6, 0x65, 0x7e, 0x4b, 0x24, 0x9c, 0xce, + 0x92, 0x6b, 0x1c, 0xe0, 0xa0, 0xa9, 0x6c, 0xc3, + 0xed, 0x4f, 0x2a, 0x54, 0x07, 0x00, 0x32, 0x5e, + 0x1b, 0x94, 0x37, 0xcd, 0xe2, 0x32, 0xa8, 0xd5, + 0x2c, 0xfb, 0x03, 0x9d, 0x79, 0xdf, 0x68, 0x63, + 0x65, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x58, + 0xa1, 0xff, 0x54, 0x43, 0x47, 0x80, 0x17, 0x00, + 0x22, 0x00, 0x0b, 0xdb, 0x1f, 0x74, 0x21, 0x4f, + 0xa9, 0x0d, 0x90, 0x64, 0xa2, 0x33, 0xbe, 0x3f, + 0xf1, 0x95, 0xb0, 0x4e, 0x3f, 0x02, 0xdc, 0xad, + 0xb0, 0x05, 0x13, 0xe6, 0x32, 0x5f, 0xed, 0x90, + 0x2c, 0xad, 0xc0, 0x00, 0x14, 0x58, 0x52, 0x07, + 0x5d, 0x64, 0x6c, 0x1f, 0xd1, 0x13, 0x7f, 0xc3, + 0x74, 0xf6, 0x4b, 0xe3, 0xa0, 0x2e, 0xb7, 0x71, + 0xda, 0x00, 0x00, 0x00, 0x00, 0x29, 0x3c, 0x64, + 0xdf, 0x95, 0x38, 0xba, 0x73, 0xe3, 0x57, 0x61, + 0xa0, 0x01, 0x24, 0x01, 0x08, 0xc9, 0xd6, 0xea, + 0x60, 0xe4, 0x00, 0x22, 0x00, 0x0b, 0xe1, 0x86, + 0xbb, 0x79, 0x27, 0xe5, 0x01, 0x19, 0x90, 0xb3, + 0xe9, 0x08, 0xb0, 0xee, 0xfa, 0x3a, 0x67, 0xa9, + 0xf3, 0xc8, 0x9e, 0x03, 0x41, 0x07, 0x75, 0x60, + 0xbc, 0x94, 0x0c, 0x2a, 0xb7, 0xad, 0x00, 0x22, + 0x00, 0x0b, 0x35, 0xb1, 0x72, 0xd6, 0x3c, 0xe9, + 0x85, 0xe8, 0x66, 0xed, 0x10, 0x7a, 0x5c, 0xa3, + 0xe6, 0xd9, 0x4d, 0xf0, 0x52, 0x69, 0x26, 0x14, + 0xb4, 0x36, 0x7e, 0xad, 0x76, 0x9e, 0x58, 0x68, + 0x3e, 0x91 +}; + +const unsigned char attstmt_tpm_es256[3841] = { + 0xa6, 0x63, 0x61, 0x6c, 0x67, 0x39, 0xff, 0xfe, + 0x63, 0x73, 0x69, 0x67, 0x59, 0x01, 0x00, 0x6d, + 0x11, 0x61, 0x1f, 0x45, 0xb9, 0x7f, 0x65, 0x6f, + 0x97, 0x46, 0xfe, 0xbb, 0x8a, 0x98, 0x07, 0xa3, + 0xbc, 0x67, 0x5c, 0xd7, 0x65, 0xa4, 0xf4, 0x6c, + 0x5b, 0x37, 0x75, 0xa4, 0x7f, 0x08, 0x52, 0xeb, + 0x1e, 0x12, 0xe2, 0x78, 0x8c, 0x7d, 0x94, 0xab, + 0x7b, 0xed, 0x05, 0x17, 0x67, 0x7e, 0xaa, 0x02, + 0x89, 0x6d, 0xe8, 0x6d, 0x43, 0x30, 0x99, 0xc6, + 0xf9, 0x59, 0xe5, 0x82, 0x3c, 0x56, 0x4e, 0x77, + 0x11, 0x25, 0xe4, 0x43, 0x6a, 0xae, 0x92, 0x4f, + 0x60, 0x92, 0x50, 0xf9, 0x65, 0x0e, 0x44, 0x38, + 0x3d, 0xf7, 0xaf, 0x66, 0x89, 0xc7, 0xe6, 0xe6, + 0x01, 0x07, 0x9e, 0x90, 0xfd, 0x6d, 0xaa, 0x35, + 0x51, 0x51, 0xbf, 0x54, 0x13, 0x95, 0xc2, 0x17, + 0xfa, 0x32, 0x0f, 0xa7, 0x82, 0x17, 0x58, 0x6c, + 0x3d, 0xea, 0x88, 0xd8, 0x64, 0xc7, 0xf8, 0xc2, + 0xd6, 0x1c, 0xbb, 0xea, 0x1e, 0xb3, 0xd9, 0x4c, + 0xa7, 0xce, 0x18, 0x1e, 0xcb, 0x42, 0x5f, 0xbf, + 0x44, 0xe7, 0xf1, 0x22, 0xe0, 0x5b, 0xeb, 0xff, + 0xb6, 0x1e, 0x6f, 0x60, 0x12, 0x16, 0x63, 0xfe, + 0xab, 0x5e, 0x31, 0x13, 0xdb, 0x72, 0xc6, 0x9a, + 0xf8, 0x8f, 0x19, 0x6b, 0x2e, 0xaf, 0x7d, 0xca, + 0x9f, 0xbc, 0x6b, 0x1a, 0x8b, 0x5e, 0xe3, 0x9e, + 0xaa, 0x8c, 0x79, 0x9c, 0x4e, 0xed, 0xe4, 0xff, + 0x3d, 0x12, 0x79, 0x90, 0x09, 0x61, 0x97, 0x67, + 0xbf, 0x04, 0xac, 0x37, 0xea, 0xa9, 0x1f, 0x9f, + 0x52, 0x64, 0x0b, 0xeb, 0xc3, 0x61, 0xd4, 0x13, + 0xb0, 0x84, 0xf1, 0x3c, 0x74, 0x83, 0xcc, 0xa8, + 0x1c, 0x14, 0xe6, 0x9d, 0xfe, 0xec, 0xee, 0xa1, + 0xd2, 0xc2, 0x0a, 0xa6, 0x36, 0x08, 0xbb, 0x17, + 0xa5, 0x7b, 0x53, 0x34, 0x0e, 0xc9, 0x09, 0xe5, + 0x10, 0xa6, 0x85, 0x01, 0x71, 0x66, 0xff, 0xd0, + 0x6d, 0x4b, 0x93, 0xdb, 0x81, 0x25, 0x01, 0x63, + 0x76, 0x65, 0x72, 0x63, 0x32, 0x2e, 0x30, 0x63, + 0x78, 0x35, 0x63, 0x82, 0x59, 0x05, 0xc4, 0x30, + 0x82, 0x05, 0xc0, 0x30, 0x82, 0x03, 0xa8, 0xa0, + 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x30, 0xcd, + 0xf2, 0x7e, 0x81, 0xc0, 0x43, 0x85, 0xa2, 0xd7, + 0x29, 0xef, 0xf7, 0x9f, 0xa5, 0x2b, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x41, 0x31, + 0x3f, 0x30, 0x3d, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x36, 0x45, 0x55, 0x53, 0x2d, 0x53, 0x54, + 0x4d, 0x2d, 0x4b, 0x45, 0x59, 0x49, 0x44, 0x2d, + 0x31, 0x41, 0x44, 0x42, 0x39, 0x39, 0x34, 0x41, + 0x42, 0x35, 0x38, 0x42, 0x45, 0x35, 0x37, 0x41, + 0x30, 0x43, 0x43, 0x39, 0x42, 0x39, 0x30, 0x30, + 0x45, 0x37, 0x38, 0x35, 0x31, 0x45, 0x31, 0x41, + 0x34, 0x33, 0x43, 0x30, 0x38, 0x36, 0x36, 0x30, + 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x31, + 0x30, 0x32, 0x31, 0x35, 0x30, 0x36, 0x35, 0x33, + 0x5a, 0x17, 0x0d, 0x32, 0x37, 0x30, 0x36, 0x30, + 0x33, 0x31, 0x39, 0x34, 0x30, 0x31, 0x36, 0x5a, + 0x30, 0x00, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, + 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, + 0x01, 0x01, 0x00, 0xdb, 0xd5, 0x9a, 0xfc, 0x09, + 0xa7, 0xc4, 0xa5, 0x5f, 0xbe, 0x5f, 0xa2, 0xeb, + 0xd6, 0x8e, 0xed, 0xc5, 0x67, 0xa6, 0xa7, 0xd9, + 0xb2, 0x46, 0xc6, 0xe0, 0xae, 0x0c, 0x02, 0x25, + 0x0a, 0xf2, 0xc5, 0x96, 0xdc, 0xb7, 0x0e, 0xb9, + 0x86, 0xd3, 0x51, 0xbb, 0x63, 0xf0, 0x4f, 0x8a, + 0x5e, 0xd7, 0xf7, 0xff, 0xbb, 0x29, 0xbd, 0x58, + 0xcf, 0x75, 0x02, 0x39, 0xcb, 0x80, 0xf1, 0xd4, + 0xb6, 0x75, 0x67, 0x2f, 0x27, 0x4d, 0x0c, 0xcc, + 0x18, 0x59, 0x87, 0xfa, 0x51, 0xd1, 0x80, 0xb5, + 0x1a, 0xac, 0xac, 0x29, 0x51, 0xcf, 0x27, 0xaa, + 0x74, 0xac, 0x3e, 0x59, 0x56, 0x67, 0xe4, 0x42, + 0xe8, 0x30, 0x35, 0xb2, 0xf6, 0x27, 0x91, 0x62, + 0x60, 0x42, 0x42, 0x12, 0xde, 0xfe, 0xdd, 0xee, + 0xe8, 0xa8, 0x82, 0xf9, 0xb1, 0x08, 0xd5, 0x8d, + 0x57, 0x9a, 0x29, 0xb9, 0xb4, 0xe9, 0x19, 0x1e, + 0x33, 0x7d, 0x37, 0xa0, 0xce, 0x2e, 0x53, 0x13, + 0x39, 0xb6, 0x12, 0x61, 0x63, 0xbf, 0xd3, 0x42, + 0xeb, 0x6f, 0xed, 0xc1, 0x8e, 0x26, 0xba, 0x7d, + 0x8b, 0x37, 0x7c, 0xbb, 0x42, 0x1e, 0x56, 0x76, + 0xda, 0xdb, 0x35, 0x6b, 0x80, 0xe1, 0x8e, 0x00, + 0xac, 0xd2, 0xfc, 0x22, 0x96, 0x14, 0x0c, 0xf4, + 0xe4, 0xc5, 0xad, 0x14, 0xb7, 0x4d, 0x46, 0x63, + 0x30, 0x79, 0x3a, 0x7c, 0x33, 0xb5, 0xe5, 0x2e, + 0xbb, 0x5f, 0xca, 0xf2, 0x75, 0xe3, 0x4e, 0x99, + 0x64, 0x1b, 0x26, 0x99, 0x60, 0x1a, 0x79, 0xcc, + 0x30, 0x2c, 0xb3, 0x4c, 0x59, 0xf7, 0x77, 0x59, + 0xd5, 0x90, 0x70, 0x21, 0x79, 0x8c, 0x1f, 0x79, + 0x0a, 0x12, 0x8b, 0x3b, 0x37, 0x2d, 0x97, 0x39, + 0x89, 0x92, 0x0c, 0x44, 0x7c, 0xe9, 0x9f, 0xce, + 0x6d, 0xad, 0xc5, 0xae, 0xea, 0x8e, 0x50, 0x22, + 0x37, 0xe0, 0xd1, 0x9e, 0xd6, 0xe6, 0xa8, 0xcc, + 0x21, 0xfb, 0xff, 0x02, 0x03, 0x01, 0x00, 0x01, + 0xa3, 0x82, 0x01, 0xf3, 0x30, 0x82, 0x01, 0xef, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, + 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, + 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, + 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x6d, + 0x06, 0x03, 0x55, 0x1d, 0x20, 0x01, 0x01, 0xff, + 0x04, 0x63, 0x30, 0x61, 0x30, 0x5f, 0x06, 0x09, + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, + 0x1f, 0x30, 0x52, 0x30, 0x50, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, + 0x44, 0x1e, 0x42, 0x00, 0x54, 0x00, 0x43, 0x00, + 0x50, 0x00, 0x41, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x54, 0x00, 0x72, 0x00, 0x75, 0x00, 0x73, 0x00, + 0x74, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x50, 0x00, 0x6c, 0x00, 0x61, 0x00, + 0x74, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00, + 0x6d, 0x00, 0x20, 0x00, 0x20, 0x00, 0x49, 0x00, + 0x64, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, + 0x69, 0x00, 0x74, 0x00, 0x79, 0x30, 0x10, 0x06, + 0x03, 0x55, 0x1d, 0x25, 0x04, 0x09, 0x30, 0x07, + 0x06, 0x05, 0x67, 0x81, 0x05, 0x08, 0x03, 0x30, + 0x59, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x01, 0x01, + 0xff, 0x04, 0x4f, 0x30, 0x4d, 0xa4, 0x4b, 0x30, + 0x49, 0x31, 0x16, 0x30, 0x14, 0x06, 0x05, 0x67, + 0x81, 0x05, 0x02, 0x01, 0x0c, 0x0b, 0x69, 0x64, + 0x3a, 0x35, 0x33, 0x35, 0x34, 0x34, 0x44, 0x32, + 0x30, 0x31, 0x17, 0x30, 0x15, 0x06, 0x05, 0x67, + 0x81, 0x05, 0x02, 0x02, 0x0c, 0x0c, 0x53, 0x54, + 0x33, 0x33, 0x48, 0x54, 0x50, 0x48, 0x41, 0x48, + 0x42, 0x34, 0x31, 0x16, 0x30, 0x14, 0x06, 0x05, + 0x67, 0x81, 0x05, 0x02, 0x03, 0x0c, 0x0b, 0x69, + 0x64, 0x3a, 0x30, 0x30, 0x34, 0x39, 0x30, 0x30, + 0x30, 0x34, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, + 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x45, + 0x1a, 0xec, 0xfc, 0x91, 0x70, 0xf8, 0x83, 0x8b, + 0x9c, 0x47, 0x2f, 0x0b, 0x9f, 0x07, 0xf3, 0x2f, + 0x7c, 0xa2, 0x8a, 0x30, 0x1d, 0x06, 0x03, 0x55, + 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x55, 0xa6, + 0xee, 0xe3, 0x28, 0xdd, 0x40, 0x7f, 0x21, 0xd2, + 0x7b, 0x8c, 0x69, 0x2f, 0x8c, 0x08, 0x29, 0xbc, + 0x95, 0xb8, 0x30, 0x81, 0xb2, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, + 0x81, 0xa5, 0x30, 0x81, 0xa2, 0x30, 0x81, 0x9f, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x30, 0x02, 0x86, 0x81, 0x92, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x61, 0x7a, 0x63, 0x73, + 0x70, 0x72, 0x6f, 0x64, 0x65, 0x75, 0x73, 0x61, + 0x69, 0x6b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, + 0x68, 0x2e, 0x62, 0x6c, 0x6f, 0x62, 0x2e, 0x63, + 0x6f, 0x72, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, + 0x6f, 0x77, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x2f, + 0x65, 0x75, 0x73, 0x2d, 0x73, 0x74, 0x6d, 0x2d, + 0x6b, 0x65, 0x79, 0x69, 0x64, 0x2d, 0x31, 0x61, + 0x64, 0x62, 0x39, 0x39, 0x34, 0x61, 0x62, 0x35, + 0x38, 0x62, 0x65, 0x35, 0x37, 0x61, 0x30, 0x63, + 0x63, 0x39, 0x62, 0x39, 0x30, 0x30, 0x65, 0x37, + 0x38, 0x35, 0x31, 0x65, 0x31, 0x61, 0x34, 0x33, + 0x63, 0x30, 0x38, 0x36, 0x36, 0x30, 0x2f, 0x62, + 0x36, 0x63, 0x30, 0x64, 0x39, 0x38, 0x64, 0x2d, + 0x35, 0x37, 0x38, 0x61, 0x2d, 0x34, 0x62, 0x66, + 0x62, 0x2d, 0x61, 0x32, 0x64, 0x33, 0x2d, 0x65, + 0x64, 0x66, 0x65, 0x35, 0x66, 0x38, 0x32, 0x30, + 0x36, 0x30, 0x31, 0x2e, 0x63, 0x65, 0x72, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, + 0x02, 0x01, 0x00, 0x2a, 0x08, 0x30, 0x1f, 0xfd, + 0x8f, 0x80, 0x9b, 0x4b, 0x37, 0x82, 0x61, 0x86, + 0x36, 0x57, 0x90, 0xb5, 0x1d, 0x1f, 0xa3, 0xae, + 0x68, 0xac, 0xa7, 0x96, 0x6a, 0x25, 0x5e, 0xc5, + 0x82, 0x7c, 0x36, 0x64, 0x58, 0x11, 0xcb, 0xa5, + 0xee, 0xbf, 0xc4, 0xdb, 0xa0, 0xc7, 0x82, 0x3b, + 0xa3, 0x85, 0x9b, 0xc4, 0xee, 0x07, 0x36, 0xd7, + 0xc7, 0xb6, 0x23, 0xed, 0xc2, 0x73, 0xab, 0xbe, + 0xbe, 0xee, 0x63, 0x17, 0xf9, 0xd7, 0x7a, 0x23, + 0x7b, 0xf8, 0x09, 0x7a, 0xaa, 0x7f, 0x67, 0xc3, + 0x04, 0x84, 0x71, 0x9b, 0x06, 0x9c, 0x07, 0x42, + 0x4b, 0x65, 0x41, 0x56, 0x58, 0x14, 0x92, 0xb0, + 0xb9, 0xaf, 0xa1, 0x39, 0xd4, 0x08, 0x2d, 0x71, + 0xd5, 0x6c, 0x56, 0xb9, 0x2b, 0x1e, 0xf3, 0x93, + 0xa5, 0xe9, 0xb2, 0x9b, 0x4d, 0x05, 0x2b, 0xbc, + 0xd2, 0x20, 0x57, 0x3b, 0xa4, 0x01, 0x68, 0x8c, + 0x23, 0x20, 0x7d, 0xbb, 0x71, 0xe4, 0x2a, 0x24, + 0xba, 0x75, 0x0c, 0x89, 0x54, 0x22, 0xeb, 0x0e, + 0xb2, 0xf4, 0xc2, 0x1f, 0x02, 0xb7, 0xe3, 0x06, + 0x41, 0x15, 0x6b, 0xf3, 0xc8, 0x2d, 0x5b, 0xc2, + 0x21, 0x82, 0x3e, 0xe8, 0x95, 0x40, 0x39, 0x9e, + 0x91, 0x68, 0x33, 0x0c, 0x3d, 0x45, 0xef, 0x99, + 0x79, 0xe6, 0x32, 0xc9, 0x00, 0x84, 0x36, 0xfb, + 0x0a, 0x8d, 0x41, 0x1c, 0x32, 0x64, 0x06, 0x9e, + 0x0f, 0xb5, 0x04, 0xcc, 0x08, 0xb1, 0xb6, 0x2b, + 0xcf, 0x36, 0x0f, 0x73, 0x14, 0x8e, 0x25, 0x44, + 0xb3, 0x0c, 0x34, 0x14, 0x96, 0x0c, 0x8a, 0x65, + 0xa1, 0xde, 0x8e, 0xc8, 0x9d, 0xbe, 0x66, 0xdf, + 0x06, 0x91, 0xca, 0x15, 0x0f, 0x92, 0xd5, 0x2a, + 0x0b, 0xdc, 0x4c, 0x6a, 0xf3, 0x16, 0x4a, 0x3e, + 0xb9, 0x76, 0xbc, 0xfe, 0x62, 0xd4, 0xa8, 0xcd, + 0x94, 0x78, 0x0d, 0xdd, 0x94, 0xfd, 0x5e, 0x63, + 0x57, 0x27, 0x05, 0x9c, 0xd0, 0x80, 0x91, 0x91, + 0x79, 0xe8, 0x5e, 0x18, 0x64, 0x22, 0xe4, 0x2c, + 0x13, 0x65, 0xa4, 0x51, 0x5a, 0x1e, 0x3b, 0x71, + 0x2e, 0x70, 0x9f, 0xc4, 0xa5, 0x20, 0xcd, 0xef, + 0xd8, 0x3f, 0xa4, 0xf5, 0x89, 0x8a, 0xa5, 0x4f, + 0x76, 0x2d, 0x49, 0x56, 0x00, 0x8d, 0xde, 0x40, + 0xba, 0x24, 0x46, 0x51, 0x38, 0xad, 0xdb, 0xc4, + 0x04, 0xf4, 0x6e, 0xc0, 0x29, 0x48, 0x07, 0x6a, + 0x1b, 0x26, 0x32, 0x0a, 0xfb, 0xea, 0x71, 0x2a, + 0x11, 0xfc, 0x98, 0x7c, 0x44, 0x87, 0xbc, 0x06, + 0x3a, 0x4d, 0xbd, 0x91, 0x63, 0x4f, 0x26, 0x48, + 0x54, 0x47, 0x1b, 0xbd, 0xf0, 0xf1, 0x56, 0x05, + 0xc5, 0x0f, 0x8f, 0x20, 0xa5, 0xcc, 0xfb, 0x76, + 0xb0, 0xbd, 0x83, 0xde, 0x7f, 0x39, 0x4f, 0xcf, + 0x61, 0x74, 0x52, 0xa7, 0x1d, 0xf6, 0xb5, 0x5e, + 0x4a, 0x82, 0x20, 0xc1, 0x94, 0xaa, 0x2c, 0x33, + 0xd6, 0x0a, 0xf9, 0x8f, 0x92, 0xc6, 0x29, 0x80, + 0xf5, 0xa2, 0xb1, 0xff, 0xb6, 0x2b, 0xaa, 0x04, + 0x00, 0x72, 0xb4, 0x12, 0xbb, 0xb1, 0xf1, 0x3c, + 0x88, 0xa3, 0xab, 0x49, 0x17, 0x90, 0x80, 0x59, + 0xa2, 0x96, 0x41, 0x69, 0x74, 0x33, 0x8a, 0x28, + 0x33, 0x7e, 0xb3, 0x19, 0x92, 0x28, 0xc1, 0xf0, + 0xd1, 0x82, 0xd5, 0x42, 0xff, 0xe7, 0xa5, 0x3f, + 0x1e, 0xb6, 0x4a, 0x23, 0xcc, 0x6a, 0x7f, 0x15, + 0x15, 0x52, 0x25, 0xb1, 0xca, 0x21, 0x95, 0x11, + 0x53, 0x3e, 0x1f, 0x50, 0x33, 0x12, 0x7a, 0x62, + 0xce, 0xcc, 0x71, 0xc2, 0x5f, 0x34, 0x47, 0xc6, + 0x7c, 0x71, 0xfa, 0xa0, 0x54, 0x00, 0xb2, 0xdf, + 0xc5, 0x54, 0xac, 0x6c, 0x53, 0xef, 0x64, 0x6b, + 0x08, 0x82, 0xd8, 0x16, 0x1e, 0xca, 0x40, 0xf3, + 0x1f, 0xdf, 0x56, 0x63, 0x10, 0xbc, 0xd7, 0xa0, + 0xeb, 0xee, 0xd1, 0x95, 0xe5, 0xef, 0xf1, 0x6a, + 0x83, 0x2d, 0x5a, 0x59, 0x06, 0xef, 0x30, 0x82, + 0x06, 0xeb, 0x30, 0x82, 0x04, 0xd3, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x13, 0x33, 0x00, 0x00, + 0x05, 0x23, 0xbf, 0xe8, 0xa1, 0x1a, 0x2a, 0x68, + 0xbd, 0x09, 0x00, 0x00, 0x00, 0x00, 0x05, 0x23, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, + 0x81, 0x8c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, + 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, + 0x65, 0x64, 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e, + 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, + 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, + 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x36, + 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x2d, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, + 0x66, 0x74, 0x20, 0x54, 0x50, 0x4d, 0x20, 0x52, + 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x32, 0x30, 0x31, 0x34, 0x30, 0x1e, + 0x17, 0x0d, 0x32, 0x31, 0x30, 0x36, 0x30, 0x33, + 0x31, 0x39, 0x34, 0x30, 0x31, 0x36, 0x5a, 0x17, + 0x0d, 0x32, 0x37, 0x30, 0x36, 0x30, 0x33, 0x31, + 0x39, 0x34, 0x30, 0x31, 0x36, 0x5a, 0x30, 0x41, + 0x31, 0x3f, 0x30, 0x3d, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x36, 0x45, 0x55, 0x53, 0x2d, 0x53, + 0x54, 0x4d, 0x2d, 0x4b, 0x45, 0x59, 0x49, 0x44, + 0x2d, 0x31, 0x41, 0x44, 0x42, 0x39, 0x39, 0x34, + 0x41, 0x42, 0x35, 0x38, 0x42, 0x45, 0x35, 0x37, + 0x41, 0x30, 0x43, 0x43, 0x39, 0x42, 0x39, 0x30, + 0x30, 0x45, 0x37, 0x38, 0x35, 0x31, 0x45, 0x31, + 0x41, 0x34, 0x33, 0x43, 0x30, 0x38, 0x36, 0x36, + 0x30, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, + 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, + 0x01, 0x00, 0xdb, 0x03, 0x34, 0x82, 0xfa, 0x81, + 0x1c, 0x84, 0x0b, 0xa0, 0x0e, 0x60, 0xd8, 0x9d, + 0x84, 0xf4, 0x81, 0xc4, 0xe9, 0xff, 0xcf, 0xe9, + 0xa3, 0x57, 0x53, 0x60, 0xa8, 0x19, 0xce, 0xbe, + 0xe1, 0x97, 0xee, 0x5d, 0x8c, 0x9f, 0xe4, 0xbd, + 0xef, 0xbd, 0x94, 0x14, 0xe4, 0x74, 0x41, 0x02, + 0xe9, 0x03, 0x19, 0x9f, 0xdd, 0x48, 0x2d, 0xbd, + 0xca, 0x26, 0x47, 0x2c, 0x01, 0x31, 0x5f, 0x34, + 0xef, 0x59, 0x35, 0x48, 0x36, 0x3d, 0x1e, 0xdf, + 0xd8, 0x13, 0xf0, 0xd0, 0x67, 0xc1, 0xb0, 0x47, + 0x67, 0xa2, 0xd6, 0x62, 0xc8, 0xe1, 0x00, 0x36, + 0x8b, 0x45, 0xf6, 0x3b, 0x96, 0x60, 0xa0, 0x45, + 0x26, 0xcb, 0xc7, 0x0b, 0x5b, 0x97, 0xd1, 0xaf, + 0x54, 0x25, 0x7a, 0x67, 0xe4, 0x2a, 0xd8, 0x9d, + 0x53, 0x05, 0xbd, 0x12, 0xac, 0xa2, 0x8e, 0x95, + 0xb4, 0x2a, 0xca, 0x89, 0x93, 0x64, 0x97, 0x25, + 0xdc, 0x1f, 0xa9, 0xe0, 0x55, 0x07, 0x38, 0x1d, + 0xee, 0x02, 0x90, 0x22, 0xf5, 0xad, 0x4e, 0x5c, + 0xf8, 0xc5, 0x1f, 0x9e, 0x84, 0x7e, 0x13, 0x47, + 0x52, 0xa2, 0x36, 0xf9, 0xf6, 0xbf, 0x76, 0x9e, + 0x0f, 0xdd, 0x14, 0x99, 0xb9, 0xd8, 0x5a, 0x42, + 0x3d, 0xd8, 0xbf, 0xdd, 0xb4, 0x9b, 0xbf, 0x6a, + 0x9f, 0x89, 0x13, 0x75, 0xaf, 0x96, 0xd2, 0x72, + 0xdf, 0xb3, 0x80, 0x6f, 0x84, 0x1a, 0x9d, 0x06, + 0x55, 0x09, 0x29, 0xea, 0xa7, 0x05, 0x31, 0xec, + 0x47, 0x3a, 0xcf, 0x3f, 0x9c, 0x2c, 0xbd, 0xd0, + 0x7d, 0xe4, 0x75, 0x5b, 0x33, 0xbe, 0x12, 0x86, + 0x09, 0xcf, 0x66, 0x9a, 0xeb, 0xf8, 0xf8, 0x72, + 0x91, 0x88, 0x4a, 0x5e, 0x89, 0x62, 0x6a, 0x94, + 0xdc, 0x48, 0x37, 0x13, 0xd8, 0x91, 0x02, 0xe3, + 0x42, 0x41, 0x7c, 0x2f, 0xe3, 0xb6, 0x0f, 0xb4, + 0x96, 0x06, 0x80, 0xca, 0x28, 0x01, 0x6f, 0x4b, + 0xcd, 0x28, 0xd4, 0x2c, 0x94, 0x7e, 0x40, 0x7e, + 0xdf, 0x01, 0xe5, 0xf2, 0x33, 0xd4, 0xda, 0xf4, + 0x1a, 0x17, 0xf7, 0x5d, 0xcb, 0x66, 0x2c, 0x2a, + 0xeb, 0xe1, 0xb1, 0x4a, 0xc3, 0x85, 0x63, 0xb2, + 0xac, 0xd0, 0x3f, 0x1a, 0x8d, 0xa5, 0x0c, 0xee, + 0x4f, 0xde, 0x74, 0x9c, 0xe0, 0x5a, 0x10, 0xc7, + 0xb8, 0xe4, 0xec, 0xe7, 0x73, 0xa6, 0x41, 0x42, + 0x37, 0xe1, 0xdf, 0xb9, 0xc7, 0xb5, 0x14, 0xa8, + 0x80, 0x95, 0xa0, 0x12, 0x67, 0x99, 0xf5, 0xba, + 0x25, 0x0a, 0x74, 0x86, 0x71, 0x9c, 0x7f, 0x59, + 0x97, 0xd2, 0x3f, 0x10, 0xfe, 0x6a, 0xb9, 0xe4, + 0x47, 0x36, 0xfb, 0x0f, 0x50, 0xee, 0xfc, 0x87, + 0x99, 0x7e, 0x36, 0x64, 0x1b, 0xc7, 0x13, 0xb3, + 0x33, 0x18, 0x71, 0xa4, 0xc3, 0xb0, 0xfc, 0x45, + 0x37, 0x11, 0x40, 0xb3, 0xde, 0x2c, 0x9f, 0x0a, + 0xcd, 0xaf, 0x5e, 0xfb, 0xd5, 0x9c, 0xea, 0xd7, + 0x24, 0x19, 0x3a, 0x92, 0x80, 0xa5, 0x63, 0xc5, + 0x3e, 0xdd, 0x51, 0xd0, 0x9f, 0xb8, 0x5e, 0xd5, + 0xf1, 0xfe, 0xa5, 0x93, 0xfb, 0x7f, 0xd9, 0xb8, + 0xb7, 0x0e, 0x0d, 0x12, 0x71, 0xf0, 0x52, 0x9d, + 0xe9, 0xd0, 0xd2, 0x8b, 0x38, 0x8b, 0x85, 0x83, + 0x98, 0x24, 0x88, 0xe8, 0x42, 0x30, 0x83, 0x12, + 0xef, 0x09, 0x96, 0x2f, 0x21, 0x81, 0x05, 0x30, + 0x0c, 0xbb, 0xba, 0x21, 0x39, 0x16, 0x12, 0xe8, + 0x4b, 0x7b, 0x7a, 0x66, 0xb8, 0x22, 0x2c, 0x71, + 0xaf, 0x59, 0xa1, 0xfc, 0x61, 0xf1, 0xb4, 0x5e, + 0xfc, 0x43, 0x19, 0x45, 0x6e, 0xa3, 0x45, 0xe4, + 0xcb, 0x66, 0x5f, 0xe0, 0x57, 0xf6, 0x0a, 0x30, + 0xa3, 0xd6, 0x51, 0x24, 0xc9, 0x07, 0x55, 0x82, + 0x4a, 0x66, 0x0e, 0x9d, 0xb2, 0x2f, 0x84, 0x56, + 0x6c, 0x3e, 0x71, 0xef, 0x9b, 0x35, 0x4d, 0x72, + 0xdc, 0x46, 0x2a, 0xe3, 0x7b, 0x13, 0x20, 0xbf, + 0xab, 0x77, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, + 0x82, 0x01, 0x8e, 0x30, 0x82, 0x01, 0x8a, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, + 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x84, 0x30, + 0x1b, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x14, + 0x30, 0x12, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, + 0x01, 0x82, 0x37, 0x15, 0x24, 0x06, 0x05, 0x67, + 0x81, 0x05, 0x08, 0x03, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x1d, 0x20, 0x04, 0x0f, 0x30, 0x0d, 0x30, + 0x0b, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, + 0x82, 0x37, 0x15, 0x1f, 0x30, 0x12, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, + 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, + 0x16, 0x04, 0x14, 0x45, 0x1a, 0xec, 0xfc, 0x91, + 0x70, 0xf8, 0x83, 0x8b, 0x9c, 0x47, 0x2f, 0x0b, + 0x9f, 0x07, 0xf3, 0x2f, 0x7c, 0xa2, 0x8a, 0x30, + 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0x7a, 0x8c, 0x0a, 0xce, + 0x2f, 0x48, 0x62, 0x17, 0xe2, 0x94, 0xd1, 0xae, + 0x55, 0xc1, 0x52, 0xec, 0x71, 0x74, 0xa4, 0x56, + 0x30, 0x70, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, + 0x69, 0x30, 0x67, 0x30, 0x65, 0xa0, 0x63, 0xa0, + 0x61, 0x86, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x3a, + 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6d, 0x69, + 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x6f, + 0x70, 0x73, 0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x4d, + 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, + 0x25, 0x32, 0x30, 0x54, 0x50, 0x4d, 0x25, 0x32, + 0x30, 0x52, 0x6f, 0x6f, 0x74, 0x25, 0x32, 0x30, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x25, 0x32, 0x30, 0x41, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x25, + 0x32, 0x30, 0x32, 0x30, 0x31, 0x34, 0x2e, 0x63, + 0x72, 0x6c, 0x30, 0x7d, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x71, + 0x30, 0x6f, 0x30, 0x6d, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x61, + 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, + 0x77, 0x77, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, + 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x6b, 0x69, 0x6f, 0x70, 0x73, 0x2f, + 0x63, 0x65, 0x72, 0x74, 0x73, 0x2f, 0x4d, 0x69, + 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x25, + 0x32, 0x30, 0x54, 0x50, 0x4d, 0x25, 0x32, 0x30, + 0x52, 0x6f, 0x6f, 0x74, 0x25, 0x32, 0x30, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x25, 0x32, 0x30, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x25, 0x32, + 0x30, 0x32, 0x30, 0x31, 0x34, 0x2e, 0x63, 0x72, + 0x74, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, + 0x03, 0x82, 0x02, 0x01, 0x00, 0x48, 0x24, 0x32, + 0xe8, 0xd6, 0x38, 0xda, 0x65, 0xec, 0x1b, 0x18, + 0x8e, 0x37, 0x07, 0xd5, 0x18, 0x5a, 0xc8, 0xb9, + 0xbb, 0x24, 0x8a, 0x4d, 0xa1, 0x3c, 0x9e, 0x46, + 0x76, 0xcf, 0xa5, 0xdf, 0xd7, 0x61, 0xba, 0x05, + 0x89, 0x3c, 0x13, 0xc2, 0x1f, 0x71, 0xe3, 0xec, + 0x5d, 0x54, 0x9e, 0xd9, 0x01, 0x5a, 0x10, 0x3b, + 0x17, 0x75, 0xde, 0xa1, 0x45, 0xbf, 0x1d, 0x1b, + 0x41, 0x21, 0x42, 0x68, 0x22, 0x6b, 0xbb, 0xcb, + 0x11, 0x04, 0xd2, 0xae, 0x86, 0xcf, 0x73, 0x5a, + 0xf2, 0x80, 0x18, 0x00, 0xf0, 0xd6, 0x6c, 0x5a, + 0x1e, 0xb3, 0x4d, 0x30, 0x02, 0x4a, 0x6a, 0x03, + 0x36, 0x42, 0xde, 0xb2, 0x52, 0x55, 0xff, 0x71, + 0xeb, 0x7b, 0x8b, 0x55, 0x6c, 0xdf, 0x05, 0x35, + 0x47, 0x70, 0x53, 0xfb, 0x6c, 0xba, 0x06, 0xb2, + 0x61, 0x86, 0xdc, 0x2a, 0x64, 0x81, 0x24, 0x79, + 0x46, 0x73, 0x04, 0x55, 0x59, 0xed, 0xd6, 0x06, + 0x61, 0x15, 0xf9, 0x8d, 0x78, 0x39, 0x7b, 0x84, + 0x7a, 0x40, 0x45, 0x13, 0x1a, 0x91, 0x71, 0x8f, + 0xd1, 0x4f, 0x78, 0x10, 0x68, 0x9b, 0x15, 0x79, + 0x3f, 0x79, 0x2d, 0x9b, 0xc7, 0x5d, 0xa3, 0xcf, + 0xa9, 0x14, 0xb0, 0xc4, 0xdb, 0xa9, 0x45, 0x6a, + 0x6e, 0x60, 0x45, 0x0b, 0x14, 0x25, 0xc7, 0x74, + 0xd0, 0x36, 0xaf, 0xc5, 0xbd, 0x4f, 0x7b, 0xc0, + 0x04, 0x43, 0x85, 0xbb, 0x06, 0x36, 0x77, 0x26, + 0x02, 0x23, 0x0b, 0xf8, 0x57, 0x8f, 0x1f, 0x27, + 0x30, 0x95, 0xff, 0x83, 0x23, 0x2b, 0x49, 0x33, + 0x43, 0x62, 0x87, 0x5d, 0x27, 0x12, 0x1a, 0x68, + 0x7b, 0xba, 0x2d, 0xf6, 0xed, 0x2c, 0x26, 0xb5, + 0xbb, 0xe2, 0x6f, 0xc2, 0x61, 0x17, 0xfc, 0x72, + 0x14, 0x57, 0x2c, 0x2c, 0x5a, 0x92, 0x13, 0x41, + 0xc4, 0x7e, 0xb5, 0x64, 0x5b, 0x86, 0x57, 0x13, + 0x14, 0xff, 0xf5, 0x04, 0xb9, 0x3d, 0x2d, 0xc3, + 0xe9, 0x75, 0x1f, 0x68, 0x0b, 0xb5, 0x76, 0xe1, + 0x7d, 0xe3, 0xb0, 0x14, 0xa8, 0x45, 0x05, 0x98, + 0x81, 0x32, 0xc1, 0xf5, 0x49, 0x4d, 0x58, 0xa4, + 0xee, 0xd8, 0x84, 0xba, 0x65, 0x07, 0x8d, 0xf7, + 0x9a, 0xff, 0x7d, 0xa5, 0xbc, 0x9a, 0xed, 0x4a, + 0x5d, 0xa4, 0x97, 0x4b, 0x4d, 0x31, 0x90, 0xb5, + 0x7d, 0x28, 0x77, 0x25, 0x88, 0x1c, 0xbf, 0x78, + 0x22, 0xb2, 0xb5, 0x5c, 0x9a, 0xc9, 0x63, 0x17, + 0x96, 0xe9, 0xc2, 0x52, 0x30, 0xb8, 0x9b, 0x37, + 0x69, 0x1a, 0x6a, 0x66, 0x76, 0x18, 0xac, 0xc0, + 0x48, 0xee, 0x46, 0x5b, 0xbe, 0x6a, 0xd5, 0x72, + 0x07, 0xdc, 0x7d, 0x05, 0xbe, 0x76, 0x7d, 0xa5, + 0x5e, 0x53, 0xb5, 0x47, 0x80, 0x58, 0xf0, 0xaf, + 0x6f, 0x4e, 0xc0, 0xf1, 0x1e, 0x37, 0x64, 0x15, + 0x42, 0x96, 0x18, 0x3a, 0x89, 0xc8, 0x14, 0x48, + 0x89, 0x5c, 0x12, 0x88, 0x98, 0x0b, 0x7b, 0x4e, + 0xce, 0x1c, 0xda, 0xd5, 0xa4, 0xd3, 0x32, 0x32, + 0x74, 0x5b, 0xcc, 0xfd, 0x2b, 0x02, 0xfb, 0xae, + 0xd0, 0x5a, 0x4c, 0xc9, 0xc1, 0x35, 0x19, 0x90, + 0x5f, 0xca, 0x14, 0xeb, 0x4c, 0x17, 0xd7, 0xe3, + 0xe2, 0x5d, 0xb4, 0x49, 0xaa, 0xf0, 0x50, 0x87, + 0xc3, 0x20, 0x00, 0xda, 0xe9, 0x04, 0x80, 0x64, + 0xac, 0x9f, 0xcd, 0x26, 0x41, 0x48, 0xe8, 0x4c, + 0x46, 0xcc, 0x5b, 0xd7, 0xca, 0x4c, 0x1b, 0x43, + 0x43, 0x1e, 0xbd, 0x94, 0xe7, 0xa7, 0xa6, 0x86, + 0xe5, 0xd1, 0x78, 0x29, 0xa2, 0x40, 0xc5, 0xc5, + 0x47, 0xb6, 0x6d, 0x53, 0xde, 0xac, 0x97, 0x74, + 0x24, 0x57, 0xcc, 0x05, 0x93, 0xfd, 0x52, 0x35, + 0x29, 0xd5, 0xe0, 0xfa, 0x23, 0x0d, 0xd7, 0xaa, + 0x8b, 0x07, 0x4b, 0xf6, 0x64, 0xc7, 0xad, 0x3c, + 0xa1, 0xb5, 0xc5, 0x70, 0xaf, 0x46, 0xfe, 0x9a, + 0x82, 0x4d, 0x75, 0xb8, 0x6d, 0x67, 0x70, 0x75, + 0x62, 0x41, 0x72, 0x65, 0x61, 0x58, 0x76, 0x00, + 0x23, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x72, 0x00, + 0x20, 0x9d, 0xff, 0xcb, 0xf3, 0x6c, 0x38, 0x3a, + 0xe6, 0x99, 0xfb, 0x98, 0x68, 0xdc, 0x6d, 0xcb, + 0x89, 0xd7, 0x15, 0x38, 0x84, 0xbe, 0x28, 0x03, + 0x92, 0x2c, 0x12, 0x41, 0x58, 0xbf, 0xad, 0x22, + 0xae, 0x00, 0x10, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x10, 0x00, 0x20, 0xfb, 0xd6, 0xba, 0x74, 0xe6, + 0x6e, 0x5c, 0x87, 0xef, 0x89, 0xa2, 0xe8, 0x3d, + 0x0b, 0xe9, 0x69, 0x2c, 0x07, 0x07, 0x7a, 0x8a, + 0x1e, 0xce, 0x12, 0xea, 0x3b, 0xb3, 0xf1, 0xf3, + 0xd9, 0xc3, 0xe6, 0x00, 0x20, 0x3c, 0x68, 0x51, + 0x94, 0x54, 0x8d, 0xeb, 0x9f, 0xb2, 0x2c, 0x66, + 0x75, 0xb6, 0xb7, 0x55, 0x22, 0x0d, 0x87, 0x59, + 0xc4, 0x39, 0x91, 0x62, 0x17, 0xc2, 0xc3, 0x53, + 0xa5, 0x26, 0x97, 0x4f, 0x2d, 0x68, 0x63, 0x65, + 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x58, 0xa1, + 0xff, 0x54, 0x43, 0x47, 0x80, 0x17, 0x00, 0x22, + 0x00, 0x0b, 0x73, 0xbe, 0xb7, 0x40, 0x82, 0xc0, + 0x49, 0x9a, 0xf7, 0xf2, 0xd0, 0x79, 0x6c, 0x88, + 0xf3, 0x56, 0x7b, 0x7a, 0x7d, 0xcd, 0x70, 0xd1, + 0xbc, 0x41, 0x88, 0x48, 0x51, 0x03, 0xf3, 0x58, + 0x3e, 0xb8, 0x00, 0x14, 0x9f, 0x57, 0x39, 0x67, + 0xa8, 0x7b, 0xd8, 0xf6, 0x9e, 0x75, 0xc9, 0x85, + 0xab, 0xe3, 0x55, 0xc7, 0x9c, 0xf6, 0xd8, 0x4f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x1c, 0x12, + 0xfd, 0xc6, 0x05, 0xc6, 0x2b, 0xf5, 0xe9, 0x88, + 0x01, 0x1f, 0x70, 0x8d, 0x98, 0x2a, 0x04, 0x21, + 0x30, 0x00, 0x22, 0x00, 0x0b, 0xf4, 0xfd, 0x9a, + 0x33, 0x55, 0x21, 0x08, 0x27, 0x48, 0x55, 0x01, + 0x56, 0xf9, 0x0b, 0x4e, 0x47, 0x55, 0x08, 0x2e, + 0x3c, 0x91, 0x3d, 0x6e, 0x53, 0xcf, 0x08, 0xe9, + 0x0a, 0x4b, 0xc9, 0x7e, 0x99, 0x00, 0x22, 0x00, + 0x0b, 0x51, 0xd3, 0x38, 0xfe, 0xaa, 0xda, 0xc6, + 0x68, 0x84, 0x39, 0xe7, 0xb1, 0x03, 0x22, 0x5e, + 0xc4, 0xd3, 0xf1, 0x0c, 0xec, 0x35, 0x5d, 0x50, + 0xa3, 0x9d, 0xab, 0xa1, 0x7b, 0x61, 0x51, 0x8f, + 0x4e +}; + +const unsigned char x509_0_tpm_es256[1476] = { + 0x30, 0x82, 0x05, 0xc0, 0x30, 0x82, 0x03, 0xa8, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x30, + 0xcd, 0xf2, 0x7e, 0x81, 0xc0, 0x43, 0x85, 0xa2, + 0xd7, 0x29, 0xef, 0xf7, 0x9f, 0xa5, 0x2b, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x41, + 0x31, 0x3f, 0x30, 0x3d, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x36, 0x45, 0x55, 0x53, 0x2d, 0x53, + 0x54, 0x4d, 0x2d, 0x4b, 0x45, 0x59, 0x49, 0x44, + 0x2d, 0x31, 0x41, 0x44, 0x42, 0x39, 0x39, 0x34, + 0x41, 0x42, 0x35, 0x38, 0x42, 0x45, 0x35, 0x37, + 0x41, 0x30, 0x43, 0x43, 0x39, 0x42, 0x39, 0x30, + 0x30, 0x45, 0x37, 0x38, 0x35, 0x31, 0x45, 0x31, + 0x41, 0x34, 0x33, 0x43, 0x30, 0x38, 0x36, 0x36, + 0x30, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x31, + 0x31, 0x30, 0x32, 0x31, 0x35, 0x30, 0x36, 0x35, + 0x33, 0x5a, 0x17, 0x0d, 0x32, 0x37, 0x30, 0x36, + 0x30, 0x33, 0x31, 0x39, 0x34, 0x30, 0x31, 0x36, + 0x5a, 0x30, 0x00, 0x30, 0x82, 0x01, 0x22, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, + 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, + 0x82, 0x01, 0x01, 0x00, 0xdb, 0xd5, 0x9a, 0xfc, + 0x09, 0xa7, 0xc4, 0xa5, 0x5f, 0xbe, 0x5f, 0xa2, + 0xeb, 0xd6, 0x8e, 0xed, 0xc5, 0x67, 0xa6, 0xa7, + 0xd9, 0xb2, 0x46, 0xc6, 0xe0, 0xae, 0x0c, 0x02, + 0x25, 0x0a, 0xf2, 0xc5, 0x96, 0xdc, 0xb7, 0x0e, + 0xb9, 0x86, 0xd3, 0x51, 0xbb, 0x63, 0xf0, 0x4f, + 0x8a, 0x5e, 0xd7, 0xf7, 0xff, 0xbb, 0x29, 0xbd, + 0x58, 0xcf, 0x75, 0x02, 0x39, 0xcb, 0x80, 0xf1, + 0xd4, 0xb6, 0x75, 0x67, 0x2f, 0x27, 0x4d, 0x0c, + 0xcc, 0x18, 0x59, 0x87, 0xfa, 0x51, 0xd1, 0x80, + 0xb5, 0x1a, 0xac, 0xac, 0x29, 0x51, 0xcf, 0x27, + 0xaa, 0x74, 0xac, 0x3e, 0x59, 0x56, 0x67, 0xe4, + 0x42, 0xe8, 0x30, 0x35, 0xb2, 0xf6, 0x27, 0x91, + 0x62, 0x60, 0x42, 0x42, 0x12, 0xde, 0xfe, 0xdd, + 0xee, 0xe8, 0xa8, 0x82, 0xf9, 0xb1, 0x08, 0xd5, + 0x8d, 0x57, 0x9a, 0x29, 0xb9, 0xb4, 0xe9, 0x19, + 0x1e, 0x33, 0x7d, 0x37, 0xa0, 0xce, 0x2e, 0x53, + 0x13, 0x39, 0xb6, 0x12, 0x61, 0x63, 0xbf, 0xd3, + 0x42, 0xeb, 0x6f, 0xed, 0xc1, 0x8e, 0x26, 0xba, + 0x7d, 0x8b, 0x37, 0x7c, 0xbb, 0x42, 0x1e, 0x56, + 0x76, 0xda, 0xdb, 0x35, 0x6b, 0x80, 0xe1, 0x8e, + 0x00, 0xac, 0xd2, 0xfc, 0x22, 0x96, 0x14, 0x0c, + 0xf4, 0xe4, 0xc5, 0xad, 0x14, 0xb7, 0x4d, 0x46, + 0x63, 0x30, 0x79, 0x3a, 0x7c, 0x33, 0xb5, 0xe5, + 0x2e, 0xbb, 0x5f, 0xca, 0xf2, 0x75, 0xe3, 0x4e, + 0x99, 0x64, 0x1b, 0x26, 0x99, 0x60, 0x1a, 0x79, + 0xcc, 0x30, 0x2c, 0xb3, 0x4c, 0x59, 0xf7, 0x77, + 0x59, 0xd5, 0x90, 0x70, 0x21, 0x79, 0x8c, 0x1f, + 0x79, 0x0a, 0x12, 0x8b, 0x3b, 0x37, 0x2d, 0x97, + 0x39, 0x89, 0x92, 0x0c, 0x44, 0x7c, 0xe9, 0x9f, + 0xce, 0x6d, 0xad, 0xc5, 0xae, 0xea, 0x8e, 0x50, + 0x22, 0x37, 0xe0, 0xd1, 0x9e, 0xd6, 0xe6, 0xa8, + 0xcc, 0x21, 0xfb, 0xff, 0x02, 0x03, 0x01, 0x00, + 0x01, 0xa3, 0x82, 0x01, 0xf3, 0x30, 0x82, 0x01, + 0xef, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, + 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, + 0x80, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, + 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, + 0x6d, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x01, 0x01, + 0xff, 0x04, 0x63, 0x30, 0x61, 0x30, 0x5f, 0x06, + 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, + 0x15, 0x1f, 0x30, 0x52, 0x30, 0x50, 0x06, 0x08, + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, + 0x30, 0x44, 0x1e, 0x42, 0x00, 0x54, 0x00, 0x43, + 0x00, 0x50, 0x00, 0x41, 0x00, 0x20, 0x00, 0x20, + 0x00, 0x54, 0x00, 0x72, 0x00, 0x75, 0x00, 0x73, + 0x00, 0x74, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, + 0x00, 0x20, 0x00, 0x50, 0x00, 0x6c, 0x00, 0x61, + 0x00, 0x74, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, + 0x00, 0x6d, 0x00, 0x20, 0x00, 0x20, 0x00, 0x49, + 0x00, 0x64, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, + 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x30, 0x10, + 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x09, 0x30, + 0x07, 0x06, 0x05, 0x67, 0x81, 0x05, 0x08, 0x03, + 0x30, 0x59, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x01, + 0x01, 0xff, 0x04, 0x4f, 0x30, 0x4d, 0xa4, 0x4b, + 0x30, 0x49, 0x31, 0x16, 0x30, 0x14, 0x06, 0x05, + 0x67, 0x81, 0x05, 0x02, 0x01, 0x0c, 0x0b, 0x69, + 0x64, 0x3a, 0x35, 0x33, 0x35, 0x34, 0x34, 0x44, + 0x32, 0x30, 0x31, 0x17, 0x30, 0x15, 0x06, 0x05, + 0x67, 0x81, 0x05, 0x02, 0x02, 0x0c, 0x0c, 0x53, + 0x54, 0x33, 0x33, 0x48, 0x54, 0x50, 0x48, 0x41, + 0x48, 0x42, 0x34, 0x31, 0x16, 0x30, 0x14, 0x06, + 0x05, 0x67, 0x81, 0x05, 0x02, 0x03, 0x0c, 0x0b, + 0x69, 0x64, 0x3a, 0x30, 0x30, 0x34, 0x39, 0x30, + 0x30, 0x30, 0x34, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x45, 0x1a, 0xec, 0xfc, 0x91, 0x70, 0xf8, 0x83, + 0x8b, 0x9c, 0x47, 0x2f, 0x0b, 0x9f, 0x07, 0xf3, + 0x2f, 0x7c, 0xa2, 0x8a, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x55, + 0xa6, 0xee, 0xe3, 0x28, 0xdd, 0x40, 0x7f, 0x21, + 0xd2, 0x7b, 0x8c, 0x69, 0x2f, 0x8c, 0x08, 0x29, + 0xbc, 0x95, 0xb8, 0x30, 0x81, 0xb2, 0x06, 0x08, + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, + 0x04, 0x81, 0xa5, 0x30, 0x81, 0xa2, 0x30, 0x81, + 0x9f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x30, 0x02, 0x86, 0x81, 0x92, 0x68, 0x74, + 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x61, 0x7a, 0x63, + 0x73, 0x70, 0x72, 0x6f, 0x64, 0x65, 0x75, 0x73, + 0x61, 0x69, 0x6b, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x73, 0x68, 0x2e, 0x62, 0x6c, 0x6f, 0x62, 0x2e, + 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x77, 0x69, 0x6e, + 0x64, 0x6f, 0x77, 0x73, 0x2e, 0x6e, 0x65, 0x74, + 0x2f, 0x65, 0x75, 0x73, 0x2d, 0x73, 0x74, 0x6d, + 0x2d, 0x6b, 0x65, 0x79, 0x69, 0x64, 0x2d, 0x31, + 0x61, 0x64, 0x62, 0x39, 0x39, 0x34, 0x61, 0x62, + 0x35, 0x38, 0x62, 0x65, 0x35, 0x37, 0x61, 0x30, + 0x63, 0x63, 0x39, 0x62, 0x39, 0x30, 0x30, 0x65, + 0x37, 0x38, 0x35, 0x31, 0x65, 0x31, 0x61, 0x34, + 0x33, 0x63, 0x30, 0x38, 0x36, 0x36, 0x30, 0x2f, + 0x62, 0x36, 0x63, 0x30, 0x64, 0x39, 0x38, 0x64, + 0x2d, 0x35, 0x37, 0x38, 0x61, 0x2d, 0x34, 0x62, + 0x66, 0x62, 0x2d, 0x61, 0x32, 0x64, 0x33, 0x2d, + 0x65, 0x64, 0x66, 0x65, 0x35, 0x66, 0x38, 0x32, + 0x30, 0x36, 0x30, 0x31, 0x2e, 0x63, 0x65, 0x72, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, + 0x82, 0x02, 0x01, 0x00, 0x2a, 0x08, 0x30, 0x1f, + 0xfd, 0x8f, 0x80, 0x9b, 0x4b, 0x37, 0x82, 0x61, + 0x86, 0x36, 0x57, 0x90, 0xb5, 0x1d, 0x1f, 0xa3, + 0xae, 0x68, 0xac, 0xa7, 0x96, 0x6a, 0x25, 0x5e, + 0xc5, 0x82, 0x7c, 0x36, 0x64, 0x58, 0x11, 0xcb, + 0xa5, 0xee, 0xbf, 0xc4, 0xdb, 0xa0, 0xc7, 0x82, + 0x3b, 0xa3, 0x85, 0x9b, 0xc4, 0xee, 0x07, 0x36, + 0xd7, 0xc7, 0xb6, 0x23, 0xed, 0xc2, 0x73, 0xab, + 0xbe, 0xbe, 0xee, 0x63, 0x17, 0xf9, 0xd7, 0x7a, + 0x23, 0x7b, 0xf8, 0x09, 0x7a, 0xaa, 0x7f, 0x67, + 0xc3, 0x04, 0x84, 0x71, 0x9b, 0x06, 0x9c, 0x07, + 0x42, 0x4b, 0x65, 0x41, 0x56, 0x58, 0x14, 0x92, + 0xb0, 0xb9, 0xaf, 0xa1, 0x39, 0xd4, 0x08, 0x2d, + 0x71, 0xd5, 0x6c, 0x56, 0xb9, 0x2b, 0x1e, 0xf3, + 0x93, 0xa5, 0xe9, 0xb2, 0x9b, 0x4d, 0x05, 0x2b, + 0xbc, 0xd2, 0x20, 0x57, 0x3b, 0xa4, 0x01, 0x68, + 0x8c, 0x23, 0x20, 0x7d, 0xbb, 0x71, 0xe4, 0x2a, + 0x24, 0xba, 0x75, 0x0c, 0x89, 0x54, 0x22, 0xeb, + 0x0e, 0xb2, 0xf4, 0xc2, 0x1f, 0x02, 0xb7, 0xe3, + 0x06, 0x41, 0x15, 0x6b, 0xf3, 0xc8, 0x2d, 0x5b, + 0xc2, 0x21, 0x82, 0x3e, 0xe8, 0x95, 0x40, 0x39, + 0x9e, 0x91, 0x68, 0x33, 0x0c, 0x3d, 0x45, 0xef, + 0x99, 0x79, 0xe6, 0x32, 0xc9, 0x00, 0x84, 0x36, + 0xfb, 0x0a, 0x8d, 0x41, 0x1c, 0x32, 0x64, 0x06, + 0x9e, 0x0f, 0xb5, 0x04, 0xcc, 0x08, 0xb1, 0xb6, + 0x2b, 0xcf, 0x36, 0x0f, 0x73, 0x14, 0x8e, 0x25, + 0x44, 0xb3, 0x0c, 0x34, 0x14, 0x96, 0x0c, 0x8a, + 0x65, 0xa1, 0xde, 0x8e, 0xc8, 0x9d, 0xbe, 0x66, + 0xdf, 0x06, 0x91, 0xca, 0x15, 0x0f, 0x92, 0xd5, + 0x2a, 0x0b, 0xdc, 0x4c, 0x6a, 0xf3, 0x16, 0x4a, + 0x3e, 0xb9, 0x76, 0xbc, 0xfe, 0x62, 0xd4, 0xa8, + 0xcd, 0x94, 0x78, 0x0d, 0xdd, 0x94, 0xfd, 0x5e, + 0x63, 0x57, 0x27, 0x05, 0x9c, 0xd0, 0x80, 0x91, + 0x91, 0x79, 0xe8, 0x5e, 0x18, 0x64, 0x22, 0xe4, + 0x2c, 0x13, 0x65, 0xa4, 0x51, 0x5a, 0x1e, 0x3b, + 0x71, 0x2e, 0x70, 0x9f, 0xc4, 0xa5, 0x20, 0xcd, + 0xef, 0xd8, 0x3f, 0xa4, 0xf5, 0x89, 0x8a, 0xa5, + 0x4f, 0x76, 0x2d, 0x49, 0x56, 0x00, 0x8d, 0xde, + 0x40, 0xba, 0x24, 0x46, 0x51, 0x38, 0xad, 0xdb, + 0xc4, 0x04, 0xf4, 0x6e, 0xc0, 0x29, 0x48, 0x07, + 0x6a, 0x1b, 0x26, 0x32, 0x0a, 0xfb, 0xea, 0x71, + 0x2a, 0x11, 0xfc, 0x98, 0x7c, 0x44, 0x87, 0xbc, + 0x06, 0x3a, 0x4d, 0xbd, 0x91, 0x63, 0x4f, 0x26, + 0x48, 0x54, 0x47, 0x1b, 0xbd, 0xf0, 0xf1, 0x56, + 0x05, 0xc5, 0x0f, 0x8f, 0x20, 0xa5, 0xcc, 0xfb, + 0x76, 0xb0, 0xbd, 0x83, 0xde, 0x7f, 0x39, 0x4f, + 0xcf, 0x61, 0x74, 0x52, 0xa7, 0x1d, 0xf6, 0xb5, + 0x5e, 0x4a, 0x82, 0x20, 0xc1, 0x94, 0xaa, 0x2c, + 0x33, 0xd6, 0x0a, 0xf9, 0x8f, 0x92, 0xc6, 0x29, + 0x80, 0xf5, 0xa2, 0xb1, 0xff, 0xb6, 0x2b, 0xaa, + 0x04, 0x00, 0x72, 0xb4, 0x12, 0xbb, 0xb1, 0xf1, + 0x3c, 0x88, 0xa3, 0xab, 0x49, 0x17, 0x90, 0x80, + 0x59, 0xa2, 0x96, 0x41, 0x69, 0x74, 0x33, 0x8a, + 0x28, 0x33, 0x7e, 0xb3, 0x19, 0x92, 0x28, 0xc1, + 0xf0, 0xd1, 0x82, 0xd5, 0x42, 0xff, 0xe7, 0xa5, + 0x3f, 0x1e, 0xb6, 0x4a, 0x23, 0xcc, 0x6a, 0x7f, + 0x15, 0x15, 0x52, 0x25, 0xb1, 0xca, 0x21, 0x95, + 0x11, 0x53, 0x3e, 0x1f, 0x50, 0x33, 0x12, 0x7a, + 0x62, 0xce, 0xcc, 0x71, 0xc2, 0x5f, 0x34, 0x47, + 0xc6, 0x7c, 0x71, 0xfa, 0xa0, 0x54, 0x00, 0xb2, + 0xdf, 0xc5, 0x54, 0xac, 0x6c, 0x53, 0xef, 0x64, + 0x6b, 0x08, 0x82, 0xd8, 0x16, 0x1e, 0xca, 0x40, + 0xf3, 0x1f, 0xdf, 0x56, 0x63, 0x10, 0xbc, 0xd7, + 0xa0, 0xeb, 0xee, 0xd1, 0x95, 0xe5, 0xef, 0xf1, + 0x6a, 0x83, 0x2d, 0x5a +}; + +const unsigned char x509_1_tpm_es256[1775] = { + 0x30, 0x82, 0x06, 0xeb, 0x30, 0x82, 0x04, 0xd3, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x33, + 0x00, 0x00, 0x05, 0x23, 0xbf, 0xe8, 0xa1, 0x1a, + 0x2a, 0x68, 0xbd, 0x09, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x23, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, + 0x00, 0x30, 0x81, 0x8c, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x13, 0x0a, 0x57, 0x61, 0x73, 0x68, + 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, + 0x07, 0x52, 0x65, 0x64, 0x6d, 0x6f, 0x6e, 0x64, + 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, + 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, + 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x2d, 0x4d, 0x69, 0x63, 0x72, 0x6f, + 0x73, 0x6f, 0x66, 0x74, 0x20, 0x54, 0x50, 0x4d, + 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x34, + 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x36, + 0x30, 0x33, 0x31, 0x39, 0x34, 0x30, 0x31, 0x36, + 0x5a, 0x17, 0x0d, 0x32, 0x37, 0x30, 0x36, 0x30, + 0x33, 0x31, 0x39, 0x34, 0x30, 0x31, 0x36, 0x5a, + 0x30, 0x41, 0x31, 0x3f, 0x30, 0x3d, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x36, 0x45, 0x55, 0x53, + 0x2d, 0x53, 0x54, 0x4d, 0x2d, 0x4b, 0x45, 0x59, + 0x49, 0x44, 0x2d, 0x31, 0x41, 0x44, 0x42, 0x39, + 0x39, 0x34, 0x41, 0x42, 0x35, 0x38, 0x42, 0x45, + 0x35, 0x37, 0x41, 0x30, 0x43, 0x43, 0x39, 0x42, + 0x39, 0x30, 0x30, 0x45, 0x37, 0x38, 0x35, 0x31, + 0x45, 0x31, 0x41, 0x34, 0x33, 0x43, 0x30, 0x38, + 0x36, 0x36, 0x30, 0x30, 0x82, 0x02, 0x22, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, + 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, + 0x82, 0x02, 0x01, 0x00, 0xdb, 0x03, 0x34, 0x82, + 0xfa, 0x81, 0x1c, 0x84, 0x0b, 0xa0, 0x0e, 0x60, + 0xd8, 0x9d, 0x84, 0xf4, 0x81, 0xc4, 0xe9, 0xff, + 0xcf, 0xe9, 0xa3, 0x57, 0x53, 0x60, 0xa8, 0x19, + 0xce, 0xbe, 0xe1, 0x97, 0xee, 0x5d, 0x8c, 0x9f, + 0xe4, 0xbd, 0xef, 0xbd, 0x94, 0x14, 0xe4, 0x74, + 0x41, 0x02, 0xe9, 0x03, 0x19, 0x9f, 0xdd, 0x48, + 0x2d, 0xbd, 0xca, 0x26, 0x47, 0x2c, 0x01, 0x31, + 0x5f, 0x34, 0xef, 0x59, 0x35, 0x48, 0x36, 0x3d, + 0x1e, 0xdf, 0xd8, 0x13, 0xf0, 0xd0, 0x67, 0xc1, + 0xb0, 0x47, 0x67, 0xa2, 0xd6, 0x62, 0xc8, 0xe1, + 0x00, 0x36, 0x8b, 0x45, 0xf6, 0x3b, 0x96, 0x60, + 0xa0, 0x45, 0x26, 0xcb, 0xc7, 0x0b, 0x5b, 0x97, + 0xd1, 0xaf, 0x54, 0x25, 0x7a, 0x67, 0xe4, 0x2a, + 0xd8, 0x9d, 0x53, 0x05, 0xbd, 0x12, 0xac, 0xa2, + 0x8e, 0x95, 0xb4, 0x2a, 0xca, 0x89, 0x93, 0x64, + 0x97, 0x25, 0xdc, 0x1f, 0xa9, 0xe0, 0x55, 0x07, + 0x38, 0x1d, 0xee, 0x02, 0x90, 0x22, 0xf5, 0xad, + 0x4e, 0x5c, 0xf8, 0xc5, 0x1f, 0x9e, 0x84, 0x7e, + 0x13, 0x47, 0x52, 0xa2, 0x36, 0xf9, 0xf6, 0xbf, + 0x76, 0x9e, 0x0f, 0xdd, 0x14, 0x99, 0xb9, 0xd8, + 0x5a, 0x42, 0x3d, 0xd8, 0xbf, 0xdd, 0xb4, 0x9b, + 0xbf, 0x6a, 0x9f, 0x89, 0x13, 0x75, 0xaf, 0x96, + 0xd2, 0x72, 0xdf, 0xb3, 0x80, 0x6f, 0x84, 0x1a, + 0x9d, 0x06, 0x55, 0x09, 0x29, 0xea, 0xa7, 0x05, + 0x31, 0xec, 0x47, 0x3a, 0xcf, 0x3f, 0x9c, 0x2c, + 0xbd, 0xd0, 0x7d, 0xe4, 0x75, 0x5b, 0x33, 0xbe, + 0x12, 0x86, 0x09, 0xcf, 0x66, 0x9a, 0xeb, 0xf8, + 0xf8, 0x72, 0x91, 0x88, 0x4a, 0x5e, 0x89, 0x62, + 0x6a, 0x94, 0xdc, 0x48, 0x37, 0x13, 0xd8, 0x91, + 0x02, 0xe3, 0x42, 0x41, 0x7c, 0x2f, 0xe3, 0xb6, + 0x0f, 0xb4, 0x96, 0x06, 0x80, 0xca, 0x28, 0x01, + 0x6f, 0x4b, 0xcd, 0x28, 0xd4, 0x2c, 0x94, 0x7e, + 0x40, 0x7e, 0xdf, 0x01, 0xe5, 0xf2, 0x33, 0xd4, + 0xda, 0xf4, 0x1a, 0x17, 0xf7, 0x5d, 0xcb, 0x66, + 0x2c, 0x2a, 0xeb, 0xe1, 0xb1, 0x4a, 0xc3, 0x85, + 0x63, 0xb2, 0xac, 0xd0, 0x3f, 0x1a, 0x8d, 0xa5, + 0x0c, 0xee, 0x4f, 0xde, 0x74, 0x9c, 0xe0, 0x5a, + 0x10, 0xc7, 0xb8, 0xe4, 0xec, 0xe7, 0x73, 0xa6, + 0x41, 0x42, 0x37, 0xe1, 0xdf, 0xb9, 0xc7, 0xb5, + 0x14, 0xa8, 0x80, 0x95, 0xa0, 0x12, 0x67, 0x99, + 0xf5, 0xba, 0x25, 0x0a, 0x74, 0x86, 0x71, 0x9c, + 0x7f, 0x59, 0x97, 0xd2, 0x3f, 0x10, 0xfe, 0x6a, + 0xb9, 0xe4, 0x47, 0x36, 0xfb, 0x0f, 0x50, 0xee, + 0xfc, 0x87, 0x99, 0x7e, 0x36, 0x64, 0x1b, 0xc7, + 0x13, 0xb3, 0x33, 0x18, 0x71, 0xa4, 0xc3, 0xb0, + 0xfc, 0x45, 0x37, 0x11, 0x40, 0xb3, 0xde, 0x2c, + 0x9f, 0x0a, 0xcd, 0xaf, 0x5e, 0xfb, 0xd5, 0x9c, + 0xea, 0xd7, 0x24, 0x19, 0x3a, 0x92, 0x80, 0xa5, + 0x63, 0xc5, 0x3e, 0xdd, 0x51, 0xd0, 0x9f, 0xb8, + 0x5e, 0xd5, 0xf1, 0xfe, 0xa5, 0x93, 0xfb, 0x7f, + 0xd9, 0xb8, 0xb7, 0x0e, 0x0d, 0x12, 0x71, 0xf0, + 0x52, 0x9d, 0xe9, 0xd0, 0xd2, 0x8b, 0x38, 0x8b, + 0x85, 0x83, 0x98, 0x24, 0x88, 0xe8, 0x42, 0x30, + 0x83, 0x12, 0xef, 0x09, 0x96, 0x2f, 0x21, 0x81, + 0x05, 0x30, 0x0c, 0xbb, 0xba, 0x21, 0x39, 0x16, + 0x12, 0xe8, 0x4b, 0x7b, 0x7a, 0x66, 0xb8, 0x22, + 0x2c, 0x71, 0xaf, 0x59, 0xa1, 0xfc, 0x61, 0xf1, + 0xb4, 0x5e, 0xfc, 0x43, 0x19, 0x45, 0x6e, 0xa3, + 0x45, 0xe4, 0xcb, 0x66, 0x5f, 0xe0, 0x57, 0xf6, + 0x0a, 0x30, 0xa3, 0xd6, 0x51, 0x24, 0xc9, 0x07, + 0x55, 0x82, 0x4a, 0x66, 0x0e, 0x9d, 0xb2, 0x2f, + 0x84, 0x56, 0x6c, 0x3e, 0x71, 0xef, 0x9b, 0x35, + 0x4d, 0x72, 0xdc, 0x46, 0x2a, 0xe3, 0x7b, 0x13, + 0x20, 0xbf, 0xab, 0x77, 0x02, 0x03, 0x01, 0x00, + 0x01, 0xa3, 0x82, 0x01, 0x8e, 0x30, 0x82, 0x01, + 0x8a, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, + 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, + 0x84, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x1d, 0x25, + 0x04, 0x14, 0x30, 0x12, 0x06, 0x09, 0x2b, 0x06, + 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x24, 0x06, + 0x05, 0x67, 0x81, 0x05, 0x08, 0x03, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x0f, 0x30, + 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x2b, 0x06, 0x01, + 0x04, 0x01, 0x82, 0x37, 0x15, 0x1f, 0x30, 0x12, + 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, + 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, + 0x01, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, + 0x0e, 0x04, 0x16, 0x04, 0x14, 0x45, 0x1a, 0xec, + 0xfc, 0x91, 0x70, 0xf8, 0x83, 0x8b, 0x9c, 0x47, + 0x2f, 0x0b, 0x9f, 0x07, 0xf3, 0x2f, 0x7c, 0xa2, + 0x8a, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, + 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x7a, 0x8c, + 0x0a, 0xce, 0x2f, 0x48, 0x62, 0x17, 0xe2, 0x94, + 0xd1, 0xae, 0x55, 0xc1, 0x52, 0xec, 0x71, 0x74, + 0xa4, 0x56, 0x30, 0x70, 0x06, 0x03, 0x55, 0x1d, + 0x1f, 0x04, 0x69, 0x30, 0x67, 0x30, 0x65, 0xa0, + 0x63, 0xa0, 0x61, 0x86, 0x5f, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, + 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, + 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, + 0x69, 0x6f, 0x70, 0x73, 0x2f, 0x63, 0x72, 0x6c, + 0x2f, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, + 0x66, 0x74, 0x25, 0x32, 0x30, 0x54, 0x50, 0x4d, + 0x25, 0x32, 0x30, 0x52, 0x6f, 0x6f, 0x74, 0x25, + 0x32, 0x30, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x25, 0x32, 0x30, + 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x25, 0x32, 0x30, 0x32, 0x30, 0x31, 0x34, + 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x7d, 0x06, 0x08, + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, + 0x04, 0x71, 0x30, 0x6f, 0x30, 0x6d, 0x06, 0x08, + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, + 0x86, 0x61, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6d, 0x69, 0x63, + 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x6f, 0x70, + 0x73, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x73, 0x2f, + 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, + 0x74, 0x25, 0x32, 0x30, 0x54, 0x50, 0x4d, 0x25, + 0x32, 0x30, 0x52, 0x6f, 0x6f, 0x74, 0x25, 0x32, + 0x30, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x25, 0x32, 0x30, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, + 0x25, 0x32, 0x30, 0x32, 0x30, 0x31, 0x34, 0x2e, + 0x63, 0x72, 0x74, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, + 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x48, + 0x24, 0x32, 0xe8, 0xd6, 0x38, 0xda, 0x65, 0xec, + 0x1b, 0x18, 0x8e, 0x37, 0x07, 0xd5, 0x18, 0x5a, + 0xc8, 0xb9, 0xbb, 0x24, 0x8a, 0x4d, 0xa1, 0x3c, + 0x9e, 0x46, 0x76, 0xcf, 0xa5, 0xdf, 0xd7, 0x61, + 0xba, 0x05, 0x89, 0x3c, 0x13, 0xc2, 0x1f, 0x71, + 0xe3, 0xec, 0x5d, 0x54, 0x9e, 0xd9, 0x01, 0x5a, + 0x10, 0x3b, 0x17, 0x75, 0xde, 0xa1, 0x45, 0xbf, + 0x1d, 0x1b, 0x41, 0x21, 0x42, 0x68, 0x22, 0x6b, + 0xbb, 0xcb, 0x11, 0x04, 0xd2, 0xae, 0x86, 0xcf, + 0x73, 0x5a, 0xf2, 0x80, 0x18, 0x00, 0xf0, 0xd6, + 0x6c, 0x5a, 0x1e, 0xb3, 0x4d, 0x30, 0x02, 0x4a, + 0x6a, 0x03, 0x36, 0x42, 0xde, 0xb2, 0x52, 0x55, + 0xff, 0x71, 0xeb, 0x7b, 0x8b, 0x55, 0x6c, 0xdf, + 0x05, 0x35, 0x47, 0x70, 0x53, 0xfb, 0x6c, 0xba, + 0x06, 0xb2, 0x61, 0x86, 0xdc, 0x2a, 0x64, 0x81, + 0x24, 0x79, 0x46, 0x73, 0x04, 0x55, 0x59, 0xed, + 0xd6, 0x06, 0x61, 0x15, 0xf9, 0x8d, 0x78, 0x39, + 0x7b, 0x84, 0x7a, 0x40, 0x45, 0x13, 0x1a, 0x91, + 0x71, 0x8f, 0xd1, 0x4f, 0x78, 0x10, 0x68, 0x9b, + 0x15, 0x79, 0x3f, 0x79, 0x2d, 0x9b, 0xc7, 0x5d, + 0xa3, 0xcf, 0xa9, 0x14, 0xb0, 0xc4, 0xdb, 0xa9, + 0x45, 0x6a, 0x6e, 0x60, 0x45, 0x0b, 0x14, 0x25, + 0xc7, 0x74, 0xd0, 0x36, 0xaf, 0xc5, 0xbd, 0x4f, + 0x7b, 0xc0, 0x04, 0x43, 0x85, 0xbb, 0x06, 0x36, + 0x77, 0x26, 0x02, 0x23, 0x0b, 0xf8, 0x57, 0x8f, + 0x1f, 0x27, 0x30, 0x95, 0xff, 0x83, 0x23, 0x2b, + 0x49, 0x33, 0x43, 0x62, 0x87, 0x5d, 0x27, 0x12, + 0x1a, 0x68, 0x7b, 0xba, 0x2d, 0xf6, 0xed, 0x2c, + 0x26, 0xb5, 0xbb, 0xe2, 0x6f, 0xc2, 0x61, 0x17, + 0xfc, 0x72, 0x14, 0x57, 0x2c, 0x2c, 0x5a, 0x92, + 0x13, 0x41, 0xc4, 0x7e, 0xb5, 0x64, 0x5b, 0x86, + 0x57, 0x13, 0x14, 0xff, 0xf5, 0x04, 0xb9, 0x3d, + 0x2d, 0xc3, 0xe9, 0x75, 0x1f, 0x68, 0x0b, 0xb5, + 0x76, 0xe1, 0x7d, 0xe3, 0xb0, 0x14, 0xa8, 0x45, + 0x05, 0x98, 0x81, 0x32, 0xc1, 0xf5, 0x49, 0x4d, + 0x58, 0xa4, 0xee, 0xd8, 0x84, 0xba, 0x65, 0x07, + 0x8d, 0xf7, 0x9a, 0xff, 0x7d, 0xa5, 0xbc, 0x9a, + 0xed, 0x4a, 0x5d, 0xa4, 0x97, 0x4b, 0x4d, 0x31, + 0x90, 0xb5, 0x7d, 0x28, 0x77, 0x25, 0x88, 0x1c, + 0xbf, 0x78, 0x22, 0xb2, 0xb5, 0x5c, 0x9a, 0xc9, + 0x63, 0x17, 0x96, 0xe9, 0xc2, 0x52, 0x30, 0xb8, + 0x9b, 0x37, 0x69, 0x1a, 0x6a, 0x66, 0x76, 0x18, + 0xac, 0xc0, 0x48, 0xee, 0x46, 0x5b, 0xbe, 0x6a, + 0xd5, 0x72, 0x07, 0xdc, 0x7d, 0x05, 0xbe, 0x76, + 0x7d, 0xa5, 0x5e, 0x53, 0xb5, 0x47, 0x80, 0x58, + 0xf0, 0xaf, 0x6f, 0x4e, 0xc0, 0xf1, 0x1e, 0x37, + 0x64, 0x15, 0x42, 0x96, 0x18, 0x3a, 0x89, 0xc8, + 0x14, 0x48, 0x89, 0x5c, 0x12, 0x88, 0x98, 0x0b, + 0x7b, 0x4e, 0xce, 0x1c, 0xda, 0xd5, 0xa4, 0xd3, + 0x32, 0x32, 0x74, 0x5b, 0xcc, 0xfd, 0x2b, 0x02, + 0xfb, 0xae, 0xd0, 0x5a, 0x4c, 0xc9, 0xc1, 0x35, + 0x19, 0x90, 0x5f, 0xca, 0x14, 0xeb, 0x4c, 0x17, + 0xd7, 0xe3, 0xe2, 0x5d, 0xb4, 0x49, 0xaa, 0xf0, + 0x50, 0x87, 0xc3, 0x20, 0x00, 0xda, 0xe9, 0x04, + 0x80, 0x64, 0xac, 0x9f, 0xcd, 0x26, 0x41, 0x48, + 0xe8, 0x4c, 0x46, 0xcc, 0x5b, 0xd7, 0xca, 0x4c, + 0x1b, 0x43, 0x43, 0x1e, 0xbd, 0x94, 0xe7, 0xa7, + 0xa6, 0x86, 0xe5, 0xd1, 0x78, 0x29, 0xa2, 0x40, + 0xc5, 0xc5, 0x47, 0xb6, 0x6d, 0x53, 0xde, 0xac, + 0x97, 0x74, 0x24, 0x57, 0xcc, 0x05, 0x93, 0xfd, + 0x52, 0x35, 0x29, 0xd5, 0xe0, 0xfa, 0x23, 0x0d, + 0xd7, 0xaa, 0x8b, 0x07, 0x4b, 0xf6, 0x64, 0xc7, + 0xad, 0x3c, 0xa1, 0xb5, 0xc5, 0x70, 0xaf, 0x46, + 0xfe, 0x9a, 0x82, 0x4d, 0x75, 0xb8, 0x6d +}; + + +/* + * Security Key By Yubico + * 5.1.X + * f8a011f3-8c0a-4d15-8006-17111f9edc7d + */ +const unsigned char aaguid[16] = { + 0xf8, 0xa0, 0x11, 0xf3, 0x8c, 0x0a, 0x4d, 0x15, + 0x80, 0x06, 0x17, 0x11, 0x1f, 0x9e, 0xdc, 0x7d, +}; + +/* + * Windows Hello by Microsoft + */ +const unsigned char aaguid_tpm[16] = { + 0x08, 0x98, 0x70, 0x58, 0xca, 0xdc, 0x4b, 0x81, + 0xb6, 0xe1, 0x30, 0xde, 0x50, 0xdc, 0xbe, 0x96, +}; + +const char rp_id[] = "localhost"; +const char rp_name[] = "sweet home localhost"; + +static void * +dummy_open(const char *path) +{ + (void)path; + + return (&fake_dev_handle); +} + +static void +dummy_close(void *handle) +{ + assert(handle == &fake_dev_handle); +} + +static int +dummy_read(void *handle, unsigned char *buf, size_t len, int ms) +{ + (void)handle; + (void)buf; + (void)len; + (void)ms; + + abort(); + /* NOTREACHED */ +} + +static int +dummy_write(void *handle, const unsigned char *buf, size_t len) +{ + (void)handle; + (void)buf; + (void)len; + + abort(); + /* NOTREACHED */ +} + +static fido_cred_t * +alloc_cred(void) +{ + fido_cred_t *c; + + c = fido_cred_new(); + assert(c != NULL); + + return (c); +} + +static void +free_cred(fido_cred_t *c) +{ + fido_cred_free(&c); + assert(c == NULL); +} + +static fido_dev_t * +alloc_dev(void) +{ + fido_dev_t *d; + + d = fido_dev_new(); + assert(d != NULL); + + return (d); +} + +static void +free_dev(fido_dev_t *d) +{ + fido_dev_free(&d); + assert(d == NULL); +} + +static void +empty_cred(void) +{ + fido_cred_t *c; + fido_dev_t *d; + fido_dev_io_t io_f; + + c = alloc_cred(); + assert(fido_cred_authdata_len(c) == 0); + assert(fido_cred_authdata_ptr(c) == NULL); + assert(fido_cred_authdata_raw_len(c) == 0); + assert(fido_cred_authdata_raw_ptr(c) == NULL); + assert(fido_cred_clientdata_hash_len(c) == 0); + assert(fido_cred_clientdata_hash_ptr(c) == NULL); + assert(fido_cred_flags(c) == 0); + assert(fido_cred_fmt(c) == NULL); + assert(fido_cred_id_len(c) == 0); + assert(fido_cred_id_ptr(c) == NULL); + assert(fido_cred_prot(c) == 0); + assert(fido_cred_pubkey_len(c) == 0); + assert(fido_cred_pubkey_ptr(c) == NULL); + assert(fido_cred_rp_id(c) == NULL); + assert(fido_cred_rp_name(c) == NULL); + assert(fido_cred_sig_len(c) == 0); + assert(fido_cred_sig_ptr(c) == NULL); + assert(fido_cred_x5c_len(c) == 0); + assert(fido_cred_x5c_ptr(c) == NULL); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_ARGUMENT); + + memset(&io_f, 0, sizeof(io_f)); + + io_f.open = dummy_open; + io_f.close = dummy_close; + io_f.read = dummy_read; + io_f.write = dummy_write; + + d = alloc_dev(); + + fido_dev_force_u2f(d); + assert(fido_dev_set_io_functions(d, &io_f) == FIDO_OK); + assert(fido_dev_make_cred(d, c, NULL) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_dev_make_cred(d, c, "") == FIDO_ERR_UNSUPPORTED_OPTION); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_ARGUMENT); + + fido_dev_force_fido2(d); + assert(fido_dev_set_io_functions(d, &io_f) == FIDO_OK); + assert(fido_dev_make_cred(d, c, NULL) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_dev_make_cred(d, c, "") == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_ARGUMENT); + + free_cred(c); + free_dev(d); +} + +static void +valid_cred(void) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_x509(c, x509, sizeof(x509)) == FIDO_OK); + assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); + assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_OK); + assert(fido_cred_prot(c) == 0); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); + assert(fido_cred_id_len(c) == sizeof(id)); + assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); + free_cred(c); +} + +static void +no_cdh(void) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_x509(c, x509, sizeof(x509)) == FIDO_OK); + assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); + assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); + assert(fido_cred_id_len(c) == sizeof(id)); + assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); + free_cred(c); +} + +static void +no_rp_id(void) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_x509(c, x509, sizeof(x509)) == FIDO_OK); + assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); + assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); + assert(fido_cred_id_len(c) == sizeof(id)); + assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); + free_cred(c); +} + +static void +no_rp_name(void) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, NULL) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_x509(c, x509, sizeof(x509)) == FIDO_OK); + assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); + assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_OK); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); + assert(fido_cred_id_len(c) == sizeof(id)); + assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); + free_cred(c); +} + +static void +no_authdata(void) +{ + fido_cred_t *c; + unsigned char *unset; + + unset = calloc(1, sizeof(aaguid)); + assert(unset != NULL); + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_x509(c, x509, sizeof(x509)) == FIDO_OK); + assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); + assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_cred_pubkey_len(c) == 0); + assert(fido_cred_pubkey_ptr(c) == NULL); + assert(fido_cred_id_len(c) == 0); + assert(fido_cred_id_ptr(c) == NULL); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), unset, sizeof(aaguid)) == 0); + free_cred(c); + free(unset); +} + +static void +no_x509(void) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); + assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); + assert(fido_cred_id_len(c) == sizeof(id)); + assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); + free_cred(c); +} + +static void +no_sig(void) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_x509(c, x509, sizeof(x509)) == FIDO_OK); + assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); + assert(fido_cred_id_len(c) == sizeof(id)); + assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); + free_cred(c); +} + +static void +no_fmt(void) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_x509(c, x509, sizeof(x509)) == FIDO_OK); + assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); + assert(fido_cred_id_len(c) == sizeof(id)); + assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); + free_cred(c); +} + +static void +wrong_options(void) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_TRUE) == FIDO_OK); + assert(fido_cred_set_x509(c, x509, sizeof(x509)) == FIDO_OK); + assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); + assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_PARAM); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); + assert(fido_cred_id_len(c) == sizeof(id)); + assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); + free_cred(c); +} + +static void +junk_cdh(void) +{ + fido_cred_t *c; + unsigned char *junk; + + junk = malloc(sizeof(cdh)); + assert(junk != NULL); + memcpy(junk, cdh, sizeof(cdh)); + junk[0] = (unsigned char)~junk[0]; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, junk, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_x509(c, x509, sizeof(x509)) == FIDO_OK); + assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); + assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_SIG); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); + assert(fido_cred_id_len(c) == sizeof(id)); + assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); + free_cred(c); + free(junk); +} + +static void +junk_fmt(void) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_x509(c, x509, sizeof(x509)) == FIDO_OK); + assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); + assert(fido_cred_set_fmt(c, "junk") == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_ARGUMENT); + free_cred(c); +} + +static void +junk_rp_id(void) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, "potato", rp_name) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_x509(c, x509, sizeof(x509)) == FIDO_OK); + assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); + assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_PARAM); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); + assert(fido_cred_id_len(c) == sizeof(id)); + assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); + free_cred(c); +} + +static void +junk_rp_name(void) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, "potato") == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_x509(c, x509, sizeof(x509)) == FIDO_OK); + assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); + assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_OK); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); + assert(fido_cred_id_len(c) == sizeof(id)); + assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); + free_cred(c); +} + +static void +junk_authdata(void) +{ + fido_cred_t *c; + unsigned char *junk; + unsigned char *unset; + + junk = malloc(sizeof(authdata)); + assert(junk != NULL); + memcpy(junk, authdata, sizeof(authdata)); + junk[0] = (unsigned char)~junk[0]; + + unset = calloc(1, sizeof(aaguid)); + assert(unset != NULL); + + c = alloc_cred(); + assert(fido_cred_set_authdata(c, junk, + sizeof(authdata)) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_cred_authdata_len(c) == 0); + assert(fido_cred_authdata_ptr(c) == NULL); + assert(fido_cred_authdata_raw_len(c) == 0); + assert(fido_cred_authdata_raw_ptr(c) == NULL); + assert(fido_cred_flags(c) == 0); + assert(fido_cred_fmt(c) == NULL); + assert(fido_cred_id_len(c) == 0); + assert(fido_cred_id_ptr(c) == NULL); + assert(fido_cred_pubkey_len(c) == 0); + assert(fido_cred_pubkey_ptr(c) == NULL); + assert(fido_cred_rp_id(c) == NULL); + assert(fido_cred_rp_name(c) == NULL); + assert(fido_cred_sig_len(c) == 0); + assert(fido_cred_sig_ptr(c) == NULL); + assert(fido_cred_x5c_len(c) == 0); + assert(fido_cred_x5c_ptr(c) == NULL); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), unset, sizeof(aaguid)) == 0); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_ARGUMENT); + free_cred(c); + free(junk); + free(unset); +} + +static void +junk_sig(void) +{ + fido_cred_t *c; + unsigned char *junk; + + junk = malloc(sizeof(sig)); + assert(junk != NULL); + memcpy(junk, sig, sizeof(sig)); + junk[0] = (unsigned char)~junk[0]; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_x509(c, x509, sizeof(x509)) == FIDO_OK); + assert(fido_cred_set_sig(c, junk, sizeof(sig)) == FIDO_OK); + assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_SIG); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); + assert(fido_cred_id_len(c) == sizeof(id)); + assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); + free_cred(c); + free(junk); +} + +static void +junk_x509(void) +{ + fido_cred_t *c; + unsigned char *junk; + + junk = malloc(sizeof(x509)); + assert(junk != NULL); + memcpy(junk, x509, sizeof(x509)); + junk[0] = (unsigned char)~junk[0]; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_x509(c, junk, sizeof(x509)) == FIDO_OK); + assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); + assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_SIG); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); + assert(fido_cred_id_len(c) == sizeof(id)); + assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); + free_cred(c); + free(junk); +} + +/* github issue #6 */ +static void +invalid_type(void) +{ + fido_cred_t *c; + unsigned char *unset; + + unset = calloc(1, sizeof(aaguid)); + assert(unset != NULL); + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_RS256) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_x509(c, x509, sizeof(x509)) == FIDO_OK); + assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); + assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_cred_pubkey_len(c) == 0); + assert(fido_cred_pubkey_ptr(c) == NULL); + assert(fido_cred_id_len(c) == 0); + assert(fido_cred_id_ptr(c) == NULL); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), unset, sizeof(aaguid)) == 0); + free_cred(c); + free(unset); +} + +/* cbor_serialize_alloc misuse */ +static void +bad_cbor_serialize(void) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_authdata_len(c) == sizeof(authdata)); + free_cred(c); +} + +static void +duplicate_keys(void) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata_dupkeys, + sizeof(authdata_dupkeys)) == FIDO_ERR_INVALID_ARGUMENT); + free_cred(c); +} + +static void +unsorted_keys(void) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata_unsorted_keys, + sizeof(authdata_unsorted_keys)) == FIDO_ERR_INVALID_ARGUMENT); + free_cred(c); +} + +static void +wrong_credprot(void) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_x509(c, x509, sizeof(x509)) == FIDO_OK); + assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); + assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); + assert(fido_cred_set_prot(c, FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_PARAM); + free_cred(c); +} + +static void +raw_authdata(void) +{ + fido_cred_t *c; + cbor_item_t *item; + struct cbor_load_result cbor_result; + const unsigned char *ptr; + unsigned char *cbor; + size_t len; + size_t cbor_len; + size_t alloclen; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert((ptr = fido_cred_authdata_ptr(c)) != NULL); + assert((len = fido_cred_authdata_len(c)) != 0); + assert((item = cbor_load(ptr, len, &cbor_result)) != NULL); + assert(cbor_result.read == len); + assert(cbor_isa_bytestring(item)); + assert((ptr = fido_cred_authdata_raw_ptr(c)) != NULL); + assert((len = fido_cred_authdata_raw_len(c)) != 0); + assert(cbor_bytestring_length(item) == len); + assert(memcmp(ptr, cbor_bytestring_handle(item), len) == 0); + assert((len = fido_cred_authdata_len(c)) != 0); + assert((cbor_len = cbor_serialize_alloc(item, &cbor, &alloclen)) == len); + assert((ptr = cbor_bytestring_handle(item)) != NULL); + assert((len = cbor_bytestring_length(item)) != 0); + assert(fido_cred_set_authdata_raw(c, ptr, len) == FIDO_OK); + assert((ptr = fido_cred_authdata_ptr(c)) != NULL); + assert((len = fido_cred_authdata_len(c)) != 0); + assert(len == cbor_len); + assert(memcmp(cbor, ptr, len) == 0); + assert(cbor_len == sizeof(authdata)); + assert(memcmp(cbor, authdata, cbor_len) == 0); + cbor_decref(&item); + free(cbor); + free_cred(c); +} + +static void +fmt_none(void) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_fmt(c, "none") == FIDO_OK); + assert(fido_cred_verify(c) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_cred_prot(c) == 0); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); + assert(fido_cred_id_len(c) == sizeof(id)); + assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); + free_cred(c); +} + +static void +valid_tpm_rs256_cred(bool xfail) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_RS256) == FIDO_OK); + assert(fido_cred_set_clientdata(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata_tpm_rs256, sizeof(authdata_tpm_rs256)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_TRUE) == FIDO_OK); + assert(fido_cred_set_fmt(c, "tpm") == FIDO_OK); + assert(fido_cred_set_attstmt(c, attstmt_tpm_rs256, sizeof(attstmt_tpm_rs256)) == FIDO_OK); + // XXX: RHEL9 has deprecated SHA-1 for signing. + assert(fido_cred_verify(c) == (xfail ? FIDO_ERR_INVALID_SIG : FIDO_OK)); + assert(fido_cred_prot(c) == 0); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey_tpm_rs256)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey_tpm_rs256, sizeof(pubkey_tpm_rs256)) == 0); + assert(fido_cred_id_len(c) == sizeof(id_tpm_rs256)); + assert(memcmp(fido_cred_id_ptr(c), id_tpm_rs256, sizeof(id_tpm_rs256)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid_tpm)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid_tpm, sizeof(aaguid_tpm)) == 0); + free_cred(c); +} + +static void +valid_tpm_es256_cred(bool xfail) +{ + fido_cred_t *c; + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_authdata(c, authdata_tpm_es256, sizeof(authdata_tpm_es256)) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_TRUE) == FIDO_OK); + assert(fido_cred_set_fmt(c, "tpm") == FIDO_OK); + assert(fido_cred_set_attstmt(c, attstmt_tpm_es256, sizeof(attstmt_tpm_es256)) == FIDO_OK); + assert(fido_cred_x5c_list_count(c) == 2); + assert(fido_cred_x5c_list_len(c, 0) == sizeof(x509_0_tpm_es256)); + assert(memcmp(fido_cred_x5c_list_ptr(c, 0), x509_0_tpm_es256, sizeof(x509_0_tpm_es256)) == 0); + assert(fido_cred_x5c_list_len(c, 1) == sizeof(x509_1_tpm_es256)); + assert(memcmp(fido_cred_x5c_list_ptr(c, 1), x509_1_tpm_es256, sizeof(x509_1_tpm_es256)) == 0); + assert(fido_cred_x5c_list_len(c, 2) == 0); + assert(fido_cred_x5c_list_ptr(c, 2) == NULL); + // XXX: RHEL9 has deprecated SHA-1 for signing. + assert(fido_cred_verify(c) == (xfail ? FIDO_ERR_INVALID_SIG : FIDO_OK)); + assert(fido_cred_prot(c) == 0); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey_tpm_es256)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey_tpm_es256, sizeof(pubkey_tpm_es256)) == 0); + assert(fido_cred_id_len(c) == sizeof(id_tpm_es256)); + assert(memcmp(fido_cred_id_ptr(c), id_tpm_es256, sizeof(id_tpm_es256)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid_tpm)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid_tpm, sizeof(aaguid_tpm)) == 0); + free_cred(c); +} + +static void +push_kv(cbor_item_t *map, const char *key, cbor_item_t *value) +{ + struct cbor_pair kv; + cbor_item_t *tmp; + + memset(&kv, 0, sizeof(kv)); + assert(map != NULL && key != NULL && value != NULL); + assert((tmp = cbor_build_string(key)) != NULL); + /* XXX transfers ownership */ + kv.key = cbor_move(tmp); + kv.value = cbor_move(value); + assert(cbor_map_add(map, kv)); +} + +static void +attestation_object(void) +{ + struct cbor_load_result cbor; + unsigned char *attobj = NULL; + size_t len, alloclen = 0; + cbor_item_t *map; + fido_cred_t *c; + + assert((map = cbor_new_definite_map(3)) != NULL); + push_kv(map, "fmt", cbor_build_string("tpm")); + push_kv(map, "attStmt", cbor_load(attstmt_tpm_es256, + sizeof(attstmt_tpm_es256), &cbor)); + push_kv(map, "authData", cbor_load(authdata_tpm_es256, + sizeof(authdata_tpm_es256), &cbor)); + assert((len = cbor_serialize_alloc(map, &attobj, &alloclen))); + cbor_decref(&map); + + c = alloc_cred(); + assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); + assert(fido_cred_set_clientdata(c, cdh, sizeof(cdh)) == FIDO_OK); + assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); + assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK); + assert(fido_cred_set_uv(c, FIDO_OPT_TRUE) == FIDO_OK); + assert(fido_cred_set_attobj(c, attobj, len) == FIDO_OK); + assert(strcmp(fido_cred_fmt(c), "tpm") == 0); + assert(fido_cred_attstmt_len(c) == sizeof(attstmt_tpm_es256)); + assert(memcmp(fido_cred_attstmt_ptr(c), attstmt_tpm_es256, sizeof(attstmt_tpm_es256)) == 0); + assert(fido_cred_authdata_len(c) == sizeof(authdata_tpm_es256)); + assert(memcmp(fido_cred_authdata_ptr(c), authdata_tpm_es256, sizeof(authdata_tpm_es256)) == 0); + assert(fido_cred_pubkey_len(c) == sizeof(pubkey_tpm_es256)); + assert(memcmp(fido_cred_pubkey_ptr(c), pubkey_tpm_es256, sizeof(pubkey_tpm_es256)) == 0); + assert(fido_cred_id_len(c) == sizeof(id_tpm_es256)); + assert(memcmp(fido_cred_id_ptr(c), id_tpm_es256, sizeof(id_tpm_es256)) == 0); + assert(fido_cred_aaguid_len(c) == sizeof(aaguid_tpm)); + assert(memcmp(fido_cred_aaguid_ptr(c), aaguid_tpm, sizeof(aaguid_tpm)) == 0); + free_cred(c); + free(attobj); +} + +int +main(void) +{ + bool xfail = getenv("FIDO_REGRESS_RS1_XFAIL") != NULL; + + fido_init(0); + + empty_cred(); + valid_cred(); + no_cdh(); + no_rp_id(); + no_rp_name(); + no_authdata(); + no_x509(); + no_sig(); + no_fmt(); + junk_cdh(); + junk_fmt(); + junk_rp_id(); + junk_rp_name(); + junk_authdata(); + junk_x509(); + junk_sig(); + wrong_options(); + invalid_type(); + bad_cbor_serialize(); + duplicate_keys(); + unsorted_keys(); + wrong_credprot(); + raw_authdata(); + fmt_none(); + valid_tpm_rs256_cred(xfail); + valid_tpm_es256_cred(xfail); + attestation_object(); + + exit(0); +} diff --git a/regress/dev.c b/regress/dev.c new file mode 100644 index 0000000..0ba552b --- /dev/null +++ b/regress/dev.c @@ -0,0 +1,439 @@ +/* + * Copyright (c) 2019-2022 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + * SPDX-License-Identifier: BSD-2-Clause + */ + +#undef NDEBUG + +#include +#include +#include + +#define _FIDO_INTERNAL + +#include + +#include "../fuzz/wiredata_fido2.h" + +#define REPORT_LEN (64 + 1) + +static uint8_t ctap_nonce[8]; +static uint8_t *wiredata_ptr; +static size_t wiredata_len; +static int fake_dev_handle; +static int initialised; +static long interval_ms; + +#if defined(_MSC_VER) +static int +nanosleep(const struct timespec *rqtp, struct timespec *rmtp) +{ + if (rmtp != NULL) { + errno = EINVAL; + return (-1); + } + + Sleep((DWORD)(rqtp->tv_sec * 1000) + (DWORD)(rqtp->tv_nsec / 1000000)); + + return (0); +} +#endif + +static void * +dummy_open(const char *path) +{ + (void)path; + + return (&fake_dev_handle); +} + +static void +dummy_close(void *handle) +{ + assert(handle == &fake_dev_handle); +} + +static int +dummy_read(void *handle, unsigned char *ptr, size_t len, int ms) +{ + struct timespec tv; + size_t n; + long d; + + assert(handle == &fake_dev_handle); + assert(ptr != NULL); + assert(len == REPORT_LEN - 1); + + if (wiredata_ptr == NULL) + return (-1); + + if (!initialised) { + assert(wiredata_len >= REPORT_LEN - 1); + memcpy(&wiredata_ptr[7], &ctap_nonce, sizeof(ctap_nonce)); + initialised = 1; + } + + if (ms >= 0 && ms < interval_ms) + d = ms; + else + d = interval_ms; + + if (d) { + tv.tv_sec = d / 1000; + tv.tv_nsec = (d % 1000) * 1000000; + if (nanosleep(&tv, NULL) == -1) + err(1, "nanosleep"); + } + + if (d != interval_ms) + return (-1); /* timeout */ + + if (wiredata_len < len) + n = wiredata_len; + else + n = len; + + memcpy(ptr, wiredata_ptr, n); + wiredata_ptr += n; + wiredata_len -= n; + + return ((int)n); +} + +static int +dummy_write(void *handle, const unsigned char *ptr, size_t len) +{ + struct timespec tv; + + assert(handle == &fake_dev_handle); + assert(ptr != NULL); + assert(len == REPORT_LEN); + + if (!initialised) + memcpy(&ctap_nonce, &ptr[8], sizeof(ctap_nonce)); + + if (interval_ms) { + tv.tv_sec = interval_ms / 1000; + tv.tv_nsec = (interval_ms % 1000) * 1000000; + if (nanosleep(&tv, NULL) == -1) + err(1, "nanosleep"); + } + + return ((int)len); +} + +static uint8_t * +wiredata_setup(const uint8_t *data, size_t len) +{ + const uint8_t ctap_init_data[] = { WIREDATA_CTAP_INIT }; + + assert(wiredata_ptr == NULL); + assert(SIZE_MAX - len > sizeof(ctap_init_data)); + assert((wiredata_ptr = malloc(sizeof(ctap_init_data) + len)) != NULL); + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:6386) +#endif + memcpy(wiredata_ptr, ctap_init_data, sizeof(ctap_init_data)); +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + + if (len) + memcpy(wiredata_ptr + sizeof(ctap_init_data), data, len); + + wiredata_len = sizeof(ctap_init_data) + len; + + return (wiredata_ptr); +} + +static void +wiredata_clear(uint8_t **wiredata) +{ + free(*wiredata); + *wiredata = NULL; + wiredata_ptr = NULL; + wiredata_len = 0; + initialised = 0; +} + +/* gh#56 */ +static void +open_iff_ok(void) +{ + fido_dev_t *dev = NULL; + fido_dev_io_t io; + + memset(&io, 0, sizeof(io)); + + io.open = dummy_open; + io.close = dummy_close; + io.read = dummy_read; + io.write = dummy_write; + + assert((dev = fido_dev_new()) != NULL); + assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); + assert(fido_dev_open(dev, "dummy") == FIDO_ERR_RX); + assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT); + + fido_dev_free(&dev); +} + +static void +reopen(void) +{ + const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO }; + uint8_t *wiredata; + fido_dev_t *dev = NULL; + fido_dev_io_t io; + + memset(&io, 0, sizeof(io)); + + io.open = dummy_open; + io.close = dummy_close; + io.read = dummy_read; + io.write = dummy_write; + + wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data)); + assert((dev = fido_dev_new()) != NULL); + assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); + assert(fido_dev_open(dev, "dummy") == FIDO_OK); + assert(fido_dev_close(dev) == FIDO_OK); + wiredata_clear(&wiredata); + + wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data)); + assert(fido_dev_open(dev, "dummy") == FIDO_OK); + assert(fido_dev_close(dev) == FIDO_OK); + fido_dev_free(&dev); + wiredata_clear(&wiredata); +} + +static void +double_open(void) +{ + const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO }; + uint8_t *wiredata; + fido_dev_t *dev = NULL; + fido_dev_io_t io; + + memset(&io, 0, sizeof(io)); + + io.open = dummy_open; + io.close = dummy_close; + io.read = dummy_read; + io.write = dummy_write; + + wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data)); + assert((dev = fido_dev_new()) != NULL); + assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); + assert(fido_dev_open(dev, "dummy") == FIDO_OK); + assert(fido_dev_open(dev, "dummy") == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_dev_close(dev) == FIDO_OK); + fido_dev_free(&dev); + wiredata_clear(&wiredata); +} + +static void +double_close(void) +{ + const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO }; + uint8_t *wiredata; + fido_dev_t *dev = NULL; + fido_dev_io_t io; + + memset(&io, 0, sizeof(io)); + + io.open = dummy_open; + io.close = dummy_close; + io.read = dummy_read; + io.write = dummy_write; + + wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data)); + assert((dev = fido_dev_new()) != NULL); + assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); + assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_dev_open(dev, "dummy") == FIDO_OK); + assert(fido_dev_close(dev) == FIDO_OK); + assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT); + fido_dev_free(&dev); + wiredata_clear(&wiredata); +} + +static void +is_fido2(void) +{ + const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO }; + uint8_t *wiredata; + fido_dev_t *dev = NULL; + fido_dev_io_t io; + + memset(&io, 0, sizeof(io)); + + io.open = dummy_open; + io.close = dummy_close; + io.read = dummy_read; + io.write = dummy_write; + + wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data)); + assert((dev = fido_dev_new()) != NULL); + assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); + assert(fido_dev_open(dev, "dummy") == FIDO_OK); + assert(fido_dev_is_fido2(dev) == true); + assert(fido_dev_supports_pin(dev) == true); + fido_dev_force_u2f(dev); + assert(fido_dev_is_fido2(dev) == false); + assert(fido_dev_supports_pin(dev) == false); + assert(fido_dev_close(dev) == FIDO_OK); + wiredata_clear(&wiredata); + + wiredata = wiredata_setup(NULL, 0); + assert(fido_dev_open(dev, "dummy") == FIDO_OK); + assert(fido_dev_is_fido2(dev) == false); + assert(fido_dev_supports_pin(dev) == false); + fido_dev_force_fido2(dev); + assert(fido_dev_is_fido2(dev) == true); + assert(fido_dev_supports_pin(dev) == false); + assert(fido_dev_close(dev) == FIDO_OK); + fido_dev_free(&dev); + wiredata_clear(&wiredata); +} + +static void +has_pin(void) +{ + const uint8_t set_pin_data[] = { + WIREDATA_CTAP_CBOR_INFO, + WIREDATA_CTAP_CBOR_AUTHKEY, + WIREDATA_CTAP_CBOR_STATUS, + WIREDATA_CTAP_CBOR_STATUS + }; + uint8_t *wiredata; + fido_dev_t *dev = NULL; + fido_dev_io_t io; + + memset(&io, 0, sizeof(io)); + + io.open = dummy_open; + io.close = dummy_close; + io.read = dummy_read; + io.write = dummy_write; + + wiredata = wiredata_setup(set_pin_data, sizeof(set_pin_data)); + assert((dev = fido_dev_new()) != NULL); + assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); + assert(fido_dev_open(dev, "dummy") == FIDO_OK); + assert(fido_dev_has_pin(dev) == false); + assert(fido_dev_set_pin(dev, "top secret", NULL) == FIDO_OK); + assert(fido_dev_has_pin(dev) == true); + assert(fido_dev_reset(dev) == FIDO_OK); + assert(fido_dev_has_pin(dev) == false); + assert(fido_dev_close(dev) == FIDO_OK); + fido_dev_free(&dev); + wiredata_clear(&wiredata); +} + +static void +timeout_rx(void) +{ + const uint8_t timeout_rx_data[] = { + WIREDATA_CTAP_CBOR_INFO, + WIREDATA_CTAP_KEEPALIVE, + WIREDATA_CTAP_KEEPALIVE, + WIREDATA_CTAP_KEEPALIVE, + WIREDATA_CTAP_KEEPALIVE, + WIREDATA_CTAP_KEEPALIVE, + WIREDATA_CTAP_CBOR_STATUS + }; + uint8_t *wiredata; + fido_dev_t *dev = NULL; + fido_dev_io_t io; + + memset(&io, 0, sizeof(io)); + + io.open = dummy_open; + io.close = dummy_close; + io.read = dummy_read; + io.write = dummy_write; + + wiredata = wiredata_setup(timeout_rx_data, sizeof(timeout_rx_data)); + assert((dev = fido_dev_new()) != NULL); + assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); + assert(fido_dev_open(dev, "dummy") == FIDO_OK); + assert(fido_dev_set_timeout(dev, 3 * 1000) == FIDO_OK); + interval_ms = 1000; + assert(fido_dev_reset(dev) == FIDO_ERR_RX); + assert(fido_dev_close(dev) == FIDO_OK); + fido_dev_free(&dev); + wiredata_clear(&wiredata); + interval_ms = 0; +} + +static void +timeout_ok(void) +{ + const uint8_t timeout_ok_data[] = { + WIREDATA_CTAP_CBOR_INFO, + WIREDATA_CTAP_KEEPALIVE, + WIREDATA_CTAP_KEEPALIVE, + WIREDATA_CTAP_KEEPALIVE, + WIREDATA_CTAP_KEEPALIVE, + WIREDATA_CTAP_KEEPALIVE, + WIREDATA_CTAP_CBOR_STATUS + }; + uint8_t *wiredata; + fido_dev_t *dev = NULL; + fido_dev_io_t io; + + memset(&io, 0, sizeof(io)); + + io.open = dummy_open; + io.close = dummy_close; + io.read = dummy_read; + io.write = dummy_write; + + wiredata = wiredata_setup(timeout_ok_data, sizeof(timeout_ok_data)); + assert((dev = fido_dev_new()) != NULL); + assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); + assert(fido_dev_open(dev, "dummy") == FIDO_OK); + assert(fido_dev_set_timeout(dev, 30 * 1000) == FIDO_OK); + interval_ms = 1000; + assert(fido_dev_reset(dev) == FIDO_OK); + assert(fido_dev_close(dev) == FIDO_OK); + fido_dev_free(&dev); + wiredata_clear(&wiredata); + interval_ms = 0; +} + +static void +timeout_misc(void) +{ + fido_dev_t *dev; + + assert((dev = fido_dev_new()) != NULL); + assert(fido_dev_set_timeout(dev, -2) == FIDO_ERR_INVALID_ARGUMENT); + assert(fido_dev_set_timeout(dev, 3 * 1000) == FIDO_OK); + assert(fido_dev_set_timeout(dev, -1) == FIDO_OK); + fido_dev_free(&dev); +} + +int +main(void) +{ + fido_init(0); + + open_iff_ok(); + reopen(); + double_open(); + double_close(); + is_fido2(); + has_pin(); + timeout_rx(); + timeout_ok(); + timeout_misc(); + + exit(0); +} diff --git a/regress/eddsa.c b/regress/eddsa.c new file mode 100644 index 0000000..f97f97c --- /dev/null +++ b/regress/eddsa.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2022 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + * SPDX-License-Identifier: BSD-2-Clause + */ + +#undef NDEBUG + +#include +#include + +#define _FIDO_INTERNAL + +#include +#include + +#include +#include + +#define ASSERT_NOT_NULL(e) assert((e) != NULL) +#define ASSERT_NULL(e) assert((e) == NULL) +#define ASSERT_INVAL(e) assert((e) == FIDO_ERR_INVALID_ARGUMENT) +#define ASSERT_OK(e) assert((e) == FIDO_OK) + +static const char ecdsa[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOwiq14c80b7C1Jzsx5w1zMvk2GgW\n" +"5kfGMOKXjwF/U+51ZfBDKehs3ivdeXAJBkxIh7E3iA32s+HyNqk+ntl9fg==\n" +"-----END PUBLIC KEY-----\n"; + +static const char eddsa[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MCowBQYDK2VwAyEADt/RHErAxAHxH9FUmsjOhQ2ALl6Y8nE0m3zQxkEE2iM=\n" +"-----END PUBLIC KEY-----\n"; + +static const unsigned char eddsa_raw[] = { + 0x0e, 0xdf, 0xd1, 0x1c, 0x4a, 0xc0, 0xc4, 0x01, + 0xf1, 0x1f, 0xd1, 0x54, 0x9a, 0xc8, 0xce, 0x85, + 0x0d, 0x80, 0x2e, 0x5e, 0x98, 0xf2, 0x71, 0x34, + 0x9b, 0x7c, 0xd0, 0xc6, 0x41, 0x04, 0xda, 0x23, +}; + +static EVP_PKEY * +EVP_PKEY_from_PEM(const char *ptr, size_t len) +{ + BIO *bio = NULL; + EVP_PKEY *pkey = NULL; + + if ((bio = BIO_new(BIO_s_mem())) == NULL) { + warnx("BIO_new"); + goto out; + } + if (len > INT_MAX || BIO_write(bio, ptr, (int)len) != (int)len) { + warnx("BIO_write"); + goto out; + } + if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) + warnx("PEM_read_bio_PUBKEY"); +out: + BIO_free(bio); + + return pkey; +} + +static int +eddsa_pk_cmp(const char *ptr, size_t len) +{ + EVP_PKEY *pkA = NULL; + EVP_PKEY *pkB = NULL; + eddsa_pk_t *k = NULL; + int r, ok = -1; + + if ((pkA = EVP_PKEY_from_PEM(ptr, len)) == NULL) { + warnx("EVP_PKEY_from_PEM"); + goto out; + } + if ((k = eddsa_pk_new()) == NULL) { + warnx("eddsa_pk_new"); + goto out; + } + if ((r = eddsa_pk_from_EVP_PKEY(k, pkA)) != FIDO_OK) { + warnx("eddsa_pk_from_EVP_PKEY: 0x%x", r); + goto out; + } + if ((pkB = eddsa_pk_to_EVP_PKEY(k)) == NULL) { + warnx("eddsa_pk_to_EVP_PKEY"); + goto out; + } + if ((r = EVP_PKEY_cmp(pkA, pkB)) != 1) { + warnx("EVP_PKEY_cmp: %d", r); + goto out; + } + + ok = 0; +out: + EVP_PKEY_free(pkA); + EVP_PKEY_free(pkB); + eddsa_pk_free(&k); + + return ok; +} + +static void +invalid_key(void) +{ + EVP_PKEY *pkey; + eddsa_pk_t *pk; + + ASSERT_NOT_NULL((pkey = EVP_PKEY_from_PEM(ecdsa, sizeof(ecdsa)))); + ASSERT_NOT_NULL((pk = eddsa_pk_new())); + ASSERT_INVAL(eddsa_pk_from_EVP_PKEY(pk, pkey)); + + EVP_PKEY_free(pkey); + eddsa_pk_free(&pk); +} + +static void +valid_key(void) +{ + EVP_PKEY *pkeyA = NULL; + EVP_PKEY *pkeyB = NULL; + eddsa_pk_t *pkA = NULL; + eddsa_pk_t *pkB = NULL; + +#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3070000f + /* incomplete support; test what we can */ + ASSERT_NULL(EVP_PKEY_from_PEM(eddsa, sizeof(eddsa))); + ASSERT_NOT_NULL((pkB = eddsa_pk_new())); + ASSERT_INVAL(eddsa_pk_from_ptr(pkB, eddsa_raw, sizeof(eddsa_raw))); + ASSERT_NULL(eddsa_pk_to_EVP_PKEY((const eddsa_pk_t *)eddsa_raw)); + assert(eddsa_pk_cmp(eddsa, sizeof(eddsa)) < 0); +#else + ASSERT_NOT_NULL((pkeyA = EVP_PKEY_from_PEM(eddsa, sizeof(eddsa)))); + ASSERT_NOT_NULL((pkA = eddsa_pk_new())); + ASSERT_NOT_NULL((pkB = eddsa_pk_new())); + ASSERT_OK(eddsa_pk_from_EVP_PKEY(pkA, pkeyA)); + ASSERT_OK(eddsa_pk_from_ptr(pkB, eddsa_raw, sizeof(eddsa_raw))); + ASSERT_NOT_NULL((pkeyB = eddsa_pk_to_EVP_PKEY((const eddsa_pk_t *)eddsa_raw))); + assert(EVP_PKEY_cmp(pkeyA, pkeyB) == 1); + assert(eddsa_pk_cmp(eddsa, sizeof(eddsa)) == 0); +#endif + + EVP_PKEY_free(pkeyA); + EVP_PKEY_free(pkeyB); + eddsa_pk_free(&pkA); + eddsa_pk_free(&pkB); +} + +int +main(void) +{ + fido_init(0); + + invalid_key(); + valid_key(); + + exit(0); +} diff --git a/regress/es256.c b/regress/es256.c new file mode 100644 index 0000000..3a62a41 --- /dev/null +++ b/regress/es256.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2022 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + * SPDX-License-Identifier: BSD-2-Clause + */ + +#undef NDEBUG + +#include +#include + +#define _FIDO_INTERNAL + +#include +#include + +#include +#include + +#define ASSERT_NOT_NULL(e) assert((e) != NULL) +#define ASSERT_NULL(e) assert((e) == NULL) +#define ASSERT_INVAL(e) assert((e) == FIDO_ERR_INVALID_ARGUMENT) +#define ASSERT_OK(e) assert((e) == FIDO_OK) + +static const char short_x[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAAeeHTZj4LEbt7Czs+u5gEZJfnGE\n" +"6Z+YLe4AYu7SoGY7IH/2jKifsA7w+lkURL4DL63oEjd3f8foH9bX4eaVug==\n" +"-----END PUBLIC KEY-----"; + +static const char short_y[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEL8CWUP1r0tpJ5QmkzLc69O74C/Ti\n" +"83hTiys/JFNVkp0ArW3pKt5jNRrgWSZYE4S/D3AMtpqifFXz/FLCzJqojQ==\n" +"-----END PUBLIC KEY-----\n"; + +static const char p256k1[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEU1y8c0Jg9FGr3vYChpEo9c4dpkijriYM\n" +"QzU/DeskC89hZjLNH1Sj8ra2MsBlVGGJTNPCZSyx8Jo7ERapxdN7UQ==\n" +"-----END PUBLIC KEY-----\n"; + +static const char p256v1[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOwiq14c80b7C1Jzsx5w1zMvk2GgW\n" +"5kfGMOKXjwF/U+51ZfBDKehs3ivdeXAJBkxIh7E3iA32s+HyNqk+ntl9fg==\n" +"-----END PUBLIC KEY-----\n"; + +static const unsigned char p256k1_raw[] = { + 0x04, 0x53, 0x5c, 0xbc, 0x73, 0x42, 0x60, 0xf4, + 0x51, 0xab, 0xde, 0xf6, 0x02, 0x86, 0x91, 0x28, + 0xf5, 0xce, 0x1d, 0xa6, 0x48, 0xa3, 0xae, 0x26, + 0x0c, 0x43, 0x35, 0x3f, 0x0d, 0xeb, 0x24, 0x0b, + 0xcf, 0x61, 0x66, 0x32, 0xcd, 0x1f, 0x54, 0xa3, + 0xf2, 0xb6, 0xb6, 0x32, 0xc0, 0x65, 0x54, 0x61, + 0x89, 0x4c, 0xd3, 0xc2, 0x65, 0x2c, 0xb1, 0xf0, + 0x9a, 0x3b, 0x11, 0x16, 0xa9, 0xc5, 0xd3, 0x7b, + 0x51, +}; + +static const unsigned char p256v1_raw[] = { + 0x04, 0x3b, 0x08, 0xaa, 0xd7, 0x87, 0x3c, 0xd1, + 0xbe, 0xc2, 0xd4, 0x9c, 0xec, 0xc7, 0x9c, 0x35, + 0xcc, 0xcb, 0xe4, 0xd8, 0x68, 0x16, 0xe6, 0x47, + 0xc6, 0x30, 0xe2, 0x97, 0x8f, 0x01, 0x7f, 0x53, + 0xee, 0x75, 0x65, 0xf0, 0x43, 0x29, 0xe8, 0x6c, + 0xde, 0x2b, 0xdd, 0x79, 0x70, 0x09, 0x06, 0x4c, + 0x48, 0x87, 0xb1, 0x37, 0x88, 0x0d, 0xf6, 0xb3, + 0xe1, 0xf2, 0x36, 0xa9, 0x3e, 0x9e, 0xd9, 0x7d, + 0x7e, +}; + +static EVP_PKEY * +EVP_PKEY_from_PEM(const char *ptr, size_t len) +{ + BIO *bio = NULL; + EVP_PKEY *pkey = NULL; + + if ((bio = BIO_new(BIO_s_mem())) == NULL) { + warnx("BIO_new"); + goto out; + } + if (len > INT_MAX || BIO_write(bio, ptr, (int)len) != (int)len) { + warnx("BIO_write"); + goto out; + } + if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) + warnx("PEM_read_bio_PUBKEY"); +out: + BIO_free(bio); + + return pkey; +} + +static int +es256_pk_cmp(const char *ptr, size_t len) +{ + EVP_PKEY *pkA = NULL; + EVP_PKEY *pkB = NULL; + es256_pk_t *k = NULL; + int r, ok = -1; + + if ((pkA = EVP_PKEY_from_PEM(ptr, len)) == NULL) { + warnx("EVP_PKEY_from_PEM"); + goto out; + } + if ((k = es256_pk_new()) == NULL) { + warnx("es256_pk_new"); + goto out; + } + if ((r = es256_pk_from_EVP_PKEY(k, pkA)) != FIDO_OK) { + warnx("es256_pk_from_EVP_PKEY: 0x%x", r); + goto out; + } + if ((pkB = es256_pk_to_EVP_PKEY(k)) == NULL) { + warnx("es256_pk_to_EVP_PKEY"); + goto out; + } + if ((r = EVP_PKEY_cmp(pkA, pkB)) != 1) { + warnx("EVP_PKEY_cmp: %d", r); + goto out; + } + + ok = 0; +out: + EVP_PKEY_free(pkA); + EVP_PKEY_free(pkB); + es256_pk_free(&k); + + return ok; +} + +static void +short_coord(void) +{ + assert(es256_pk_cmp(short_x, sizeof(short_x)) == 0); + assert(es256_pk_cmp(short_y, sizeof(short_y)) == 0); +} + +static void +invalid_curve(const unsigned char *raw, size_t raw_len) +{ + EVP_PKEY *pkey; + es256_pk_t *pk; + + ASSERT_NOT_NULL((pkey = EVP_PKEY_from_PEM(p256k1, sizeof(p256k1)))); + ASSERT_NOT_NULL((pk = es256_pk_new())); + ASSERT_INVAL(es256_pk_from_EVP_PKEY(pk, pkey)); + ASSERT_INVAL(es256_pk_from_ptr(pk, raw, raw_len)); + ASSERT_NULL(es256_pk_to_EVP_PKEY((const es256_pk_t *)raw)); + + EVP_PKEY_free(pkey); + es256_pk_free(&pk); +} + +static void +full_coord(void) +{ + assert(es256_pk_cmp(p256v1, sizeof(p256v1)) == 0); +} + +static void +valid_curve(const unsigned char *raw, size_t raw_len) +{ + EVP_PKEY *pkeyA; + EVP_PKEY *pkeyB; + es256_pk_t *pkA; + es256_pk_t *pkB; + + ASSERT_NOT_NULL((pkeyA = EVP_PKEY_from_PEM(p256v1, sizeof(p256v1)))); + ASSERT_NOT_NULL((pkA = es256_pk_new())); + ASSERT_NOT_NULL((pkB = es256_pk_new())); + ASSERT_OK(es256_pk_from_EVP_PKEY(pkA, pkeyA)); + ASSERT_OK(es256_pk_from_ptr(pkB, raw, raw_len)); + ASSERT_NOT_NULL((pkeyB = es256_pk_to_EVP_PKEY(pkB))); + assert(EVP_PKEY_cmp(pkeyA, pkeyB) == 1); + + EVP_PKEY_free(pkeyA); + EVP_PKEY_free(pkeyB); + es256_pk_free(&pkA); + es256_pk_free(&pkB); +} + +int +main(void) +{ + fido_init(0); + + short_coord(); + full_coord(); + + invalid_curve(p256k1_raw, sizeof(p256k1_raw)); /* uncompressed */ + invalid_curve(p256k1_raw + 1, sizeof(p256k1_raw) - 1); /* libfido2 */ + valid_curve(p256v1_raw, sizeof(p256v1_raw)); /* uncompressed */ + valid_curve(p256v1_raw + 1, sizeof(p256v1_raw) - 1); /* libfido2 */ + + exit(0); +} diff --git a/regress/es384.c b/regress/es384.c new file mode 100644 index 0000000..b55ce01 --- /dev/null +++ b/regress/es384.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2022 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + * SPDX-License-Identifier: BSD-2-Clause + */ + +#undef NDEBUG + +#include +#include + +#define _FIDO_INTERNAL + +#include +#include + +#include +#include + +#define ASSERT_NOT_NULL(e) assert((e) != NULL) +#define ASSERT_NULL(e) assert((e) == NULL) +#define ASSERT_INVAL(e) assert((e) == FIDO_ERR_INVALID_ARGUMENT) +#define ASSERT_OK(e) assert((e) == FIDO_OK) + +static const char short_x[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEAAZ/VVCUmFU6aH9kJdDnUHCCglkatFTX\n" +"onMwIvNYyS8BW/HOoZiOQLs2Hg+qifwaP1pHKILzCVfFmWuZMhxhtmjNXFuOPDnS\n" +"Wa1PMdkCoWXA2BbXxnqL9v36gIOcFBil\n" +"-----END PUBLIC KEY-----"; + +static const char short_y[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEuDpRBAg87cnWVhxbWnaWlnj100w9pm5k\n" +"6T4eYToISaIhEK70TnGwULHX0+qHCYEGACOM7B/ZJbqjo6I7MIXaKZLemGi+tqvy\n" +"ajBAsTVSyrYBLQjTMMcaFmYmsxvFx7pK\n" +"-----END PUBLIC KEY-----\n"; + +static const char brainpoolP384r1[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MHowFAYHKoZIzj0CAQYJKyQDAwIIAQELA2IABFKswbBzqqyZ4h1zz8rivqHzJxAO\n" +"XC2aLyC9x5gwBM7GVu8k6jkX7VypRpg3yyCneiIQ+vVCNXgbDchJ0cPVuhwm3Zru\n" +"AK49dezUPahWF0YiJRFVeV+KyB/MEaaZvinzqw==\n" +"-----END PUBLIC KEY-----\n"; + +static const char secp384r1[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEdJN9DoqPtTNAOmjnECHBIqnJgyBW0rct\n" +"tbUSqQjb6UG2lldmrQJbgCP/ywuXvkkJl4yfXxOr0UP3rgcnqTVA1/46s2TG+R5u\n" +"NSQbCM1JPQuvTyFlAn5mdR8ZJJ8yPBQm\n" +"-----END PUBLIC KEY-----\n"; + +static const unsigned char brainpoolP384r1_raw[] = { + 0x04, 0x52, 0xac, 0xc1, 0xb0, 0x73, 0xaa, 0xac, + 0x99, 0xe2, 0x1d, 0x73, 0xcf, 0xca, 0xe2, 0xbe, + 0xa1, 0xf3, 0x27, 0x10, 0x0e, 0x5c, 0x2d, 0x9a, + 0x2f, 0x20, 0xbd, 0xc7, 0x98, 0x30, 0x04, 0xce, + 0xc6, 0x56, 0xef, 0x24, 0xea, 0x39, 0x17, 0xed, + 0x5c, 0xa9, 0x46, 0x98, 0x37, 0xcb, 0x20, 0xa7, + 0x7a, 0x22, 0x10, 0xfa, 0xf5, 0x42, 0x35, 0x78, + 0x1b, 0x0d, 0xc8, 0x49, 0xd1, 0xc3, 0xd5, 0xba, + 0x1c, 0x26, 0xdd, 0x9a, 0xee, 0x00, 0xae, 0x3d, + 0x75, 0xec, 0xd4, 0x3d, 0xa8, 0x56, 0x17, 0x46, + 0x22, 0x25, 0x11, 0x55, 0x79, 0x5f, 0x8a, 0xc8, + 0x1f, 0xcc, 0x11, 0xa6, 0x99, 0xbe, 0x29, 0xf3, + 0xab, +}; + +static const unsigned char secp384r1_raw[] = { + 0x04, 0x74, 0x93, 0x7d, 0x0e, 0x8a, 0x8f, 0xb5, + 0x33, 0x40, 0x3a, 0x68, 0xe7, 0x10, 0x21, 0xc1, + 0x22, 0xa9, 0xc9, 0x83, 0x20, 0x56, 0xd2, 0xb7, + 0x2d, 0xb5, 0xb5, 0x12, 0xa9, 0x08, 0xdb, 0xe9, + 0x41, 0xb6, 0x96, 0x57, 0x66, 0xad, 0x02, 0x5b, + 0x80, 0x23, 0xff, 0xcb, 0x0b, 0x97, 0xbe, 0x49, + 0x09, 0x97, 0x8c, 0x9f, 0x5f, 0x13, 0xab, 0xd1, + 0x43, 0xf7, 0xae, 0x07, 0x27, 0xa9, 0x35, 0x40, + 0xd7, 0xfe, 0x3a, 0xb3, 0x64, 0xc6, 0xf9, 0x1e, + 0x6e, 0x35, 0x24, 0x1b, 0x08, 0xcd, 0x49, 0x3d, + 0x0b, 0xaf, 0x4f, 0x21, 0x65, 0x02, 0x7e, 0x66, + 0x75, 0x1f, 0x19, 0x24, 0x9f, 0x32, 0x3c, 0x14, + 0x26, +}; + +static EVP_PKEY * +EVP_PKEY_from_PEM(const char *ptr, size_t len) +{ + BIO *bio = NULL; + EVP_PKEY *pkey = NULL; + + if ((bio = BIO_new(BIO_s_mem())) == NULL) { + warnx("BIO_new"); + goto out; + } + if (len > INT_MAX || BIO_write(bio, ptr, (int)len) != (int)len) { + warnx("BIO_write"); + goto out; + } + if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) + warnx("PEM_read_bio_PUBKEY"); +out: + BIO_free(bio); + + return pkey; +} + +static int +es384_pk_cmp(const char *ptr, size_t len) +{ + EVP_PKEY *pkA = NULL; + EVP_PKEY *pkB = NULL; + es384_pk_t *k = NULL; + int r, ok = -1; + + if ((pkA = EVP_PKEY_from_PEM(ptr, len)) == NULL) { + warnx("EVP_PKEY_from_PEM"); + goto out; + } + if ((k = es384_pk_new()) == NULL) { + warnx("es384_pk_new"); + goto out; + } + if ((r = es384_pk_from_EVP_PKEY(k, pkA)) != FIDO_OK) { + warnx("es384_pk_from_EVP_PKEY: 0x%x", r); + goto out; + } + if ((pkB = es384_pk_to_EVP_PKEY(k)) == NULL) { + warnx("es384_pk_to_EVP_PKEY"); + goto out; + } + if ((r = EVP_PKEY_cmp(pkA, pkB)) != 1) { + warnx("EVP_PKEY_cmp: %d", r); + goto out; + } + + ok = 0; +out: + EVP_PKEY_free(pkA); + EVP_PKEY_free(pkB); + es384_pk_free(&k); + + return ok; +} + +static void +short_coord(void) +{ + assert(es384_pk_cmp(short_x, sizeof(short_x)) == 0); + assert(es384_pk_cmp(short_y, sizeof(short_y)) == 0); +} + +static void +invalid_curve(const unsigned char *raw, size_t raw_len) +{ + EVP_PKEY *pkey; + es384_pk_t *pk; + + pkey = EVP_PKEY_from_PEM(brainpoolP384r1, sizeof(brainpoolP384r1)); + if (pkey == NULL) + return; /* assume no brainpool support in libcrypto */ + ASSERT_NOT_NULL((pk = es384_pk_new())); + ASSERT_INVAL(es384_pk_from_EVP_PKEY(pk, pkey)); + ASSERT_INVAL(es384_pk_from_ptr(pk, raw, raw_len)); + ASSERT_NULL(es384_pk_to_EVP_PKEY((const es384_pk_t *)raw)); + + EVP_PKEY_free(pkey); + es384_pk_free(&pk); +} + +static void +full_coord(void) +{ + assert(es384_pk_cmp(secp384r1, sizeof(secp384r1)) == 0); +} + +static void +valid_curve(const unsigned char *raw, size_t raw_len) +{ + EVP_PKEY *pkeyA; + EVP_PKEY *pkeyB; + es384_pk_t *pkA; + es384_pk_t *pkB; + + ASSERT_NOT_NULL((pkeyA = EVP_PKEY_from_PEM(secp384r1, sizeof(secp384r1)))); + ASSERT_NOT_NULL((pkA = es384_pk_new())); + ASSERT_NOT_NULL((pkB = es384_pk_new())); + ASSERT_OK(es384_pk_from_EVP_PKEY(pkA, pkeyA)); + ASSERT_OK(es384_pk_from_ptr(pkB, raw, raw_len)); + ASSERT_NOT_NULL((pkeyB = es384_pk_to_EVP_PKEY(pkB))); + assert(EVP_PKEY_cmp(pkeyA, pkeyB) == 1); + + EVP_PKEY_free(pkeyA); + EVP_PKEY_free(pkeyB); + es384_pk_free(&pkA); + es384_pk_free(&pkB); +} + +int +main(void) +{ + fido_init(0); + + short_coord(); + full_coord(); + + invalid_curve(brainpoolP384r1_raw, sizeof(brainpoolP384r1_raw)); /* uncompressed */ + invalid_curve(brainpoolP384r1_raw + 1, sizeof(brainpoolP384r1_raw) - 1); /* libfido2 */ + valid_curve(secp384r1_raw, sizeof(secp384r1_raw)); /* uncompressed */ + valid_curve(secp384r1_raw + 1, sizeof(secp384r1_raw) - 1); /* libfido2 */ + + exit(0); +} diff --git a/regress/rs256.c b/regress/rs256.c new file mode 100644 index 0000000..799396f --- /dev/null +++ b/regress/rs256.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2022 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + * SPDX-License-Identifier: BSD-2-Clause + */ + +#undef NDEBUG + +#include +#include + +#define _FIDO_INTERNAL + +#include +#include + +#include +#include + +#define ASSERT_NOT_NULL(e) assert((e) != NULL) +#define ASSERT_NULL(e) assert((e) == NULL) +#define ASSERT_INVAL(e) assert((e) == FIDO_ERR_INVALID_ARGUMENT) +#define ASSERT_OK(e) assert((e) == FIDO_OK) + +static char rsa1024[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCw92gn9Ku/bEfFj1AutaZyltpf\n" +"zzXrg70kQFymNq+spMt/HlxKiImw8TZU08zWW4ZLE/Ch4JYjMW6ETAdQFhSC63Ih\n" +"Wecui0JJ1f+2CsUVg+h7lO1877LZYUpdNiJrbqMb5Yc4N3FPtvdl3NoLIIQsF76H\n" +"VRvpjQgkWipRfZ97JQIDAQAB\n" +"-----END PUBLIC KEY-----"; + +static char rsa2048[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApvIq/55ZodBIxzo/8BnE\n" +"UQN1fo1hmJ6V20hQHSzJq5tHyxRCcvKikuJ1ZvR4RdZlEzdTdbEfMBdZ8sxve0/U\n" +"yYEjH92CG0vgTCYuUaFLJTaWZSvWa96G8Lw+V4VyNFDRCM7sflOaSVH5pAsz8OEc\n" +"TLZfM4NhnDsJAM+mQ6X7Tza0sczPchgDA+9KByXo/VIqyuBQs17rlKC2reMa8NkY\n" +"rBRQZJLNzi68d5/BHH1flGWE1l8wJ9dr1Ex93H/KdzX+7/28TWUC98nneUo8RfRx\n" +"FwUt/EInDMHOORCaCHSs28U/9IUyMjqLB1rxKhIp09yGXMiTrrT+p+Pcn8dO01HT\n" +"vQIDAQAB\n" +"-----END PUBLIC KEY-----"; + +static char rsa3072[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAwZunKrMs/o92AniLPNTF\n" +"Ta4EYfhy5NDmMvQvRFT/eTYItLrOTPmYMap68KLyZYmgz/AdaxAL/992QWre7XTY\n" +"gqLwtZT+WsSu7xPHWKTTXrlVohKBeLHQ0I7Zy0NSMUxhlJEMrBAjSyFAS86zWm5w\n" +"ctC3pNCqfUKugA07BVj+d5Mv5fziwgMR86kuhkVuMYfsR4IYwX4+va0pyLzxx624\n" +"s9nJ107g+A+3MUk4bAto3lruFeeZPUI2AFzFQbGg5By6VtvVi3gKQ7lUNtAr0Onu\n" +"I6Fb+yz8sbFcvDpJcu5CXW20GrKMVP4KY5pn2LCajWuZjBl/dXWayPfm4UX5Y2O4\n" +"73tzPpUBNwnEdz79His0v80Vmvjwn5IuF2jAoimrBNPJFFwCCuVNy8kgj2vllk1l\n" +"RvLOG6hf8VnlDb40QZS3QAQ09xFfF+xlVLb8cHH6wllaAGEM230TrmawpC7xpz4Z\n" +"sTuwJwI0AWEi//noMsRz2BuF2fCp//aORYJQU2S8kYk3AgMBAAE=\n" +"-----END PUBLIC KEY-----"; + +static const unsigned char rsa2048_raw[] = { + 0xa6, 0xf2, 0x2a, 0xff, 0x9e, 0x59, 0xa1, 0xd0, + 0x48, 0xc7, 0x3a, 0x3f, 0xf0, 0x19, 0xc4, 0x51, + 0x03, 0x75, 0x7e, 0x8d, 0x61, 0x98, 0x9e, 0x95, + 0xdb, 0x48, 0x50, 0x1d, 0x2c, 0xc9, 0xab, 0x9b, + 0x47, 0xcb, 0x14, 0x42, 0x72, 0xf2, 0xa2, 0x92, + 0xe2, 0x75, 0x66, 0xf4, 0x78, 0x45, 0xd6, 0x65, + 0x13, 0x37, 0x53, 0x75, 0xb1, 0x1f, 0x30, 0x17, + 0x59, 0xf2, 0xcc, 0x6f, 0x7b, 0x4f, 0xd4, 0xc9, + 0x81, 0x23, 0x1f, 0xdd, 0x82, 0x1b, 0x4b, 0xe0, + 0x4c, 0x26, 0x2e, 0x51, 0xa1, 0x4b, 0x25, 0x36, + 0x96, 0x65, 0x2b, 0xd6, 0x6b, 0xde, 0x86, 0xf0, + 0xbc, 0x3e, 0x57, 0x85, 0x72, 0x34, 0x50, 0xd1, + 0x08, 0xce, 0xec, 0x7e, 0x53, 0x9a, 0x49, 0x51, + 0xf9, 0xa4, 0x0b, 0x33, 0xf0, 0xe1, 0x1c, 0x4c, + 0xb6, 0x5f, 0x33, 0x83, 0x61, 0x9c, 0x3b, 0x09, + 0x00, 0xcf, 0xa6, 0x43, 0xa5, 0xfb, 0x4f, 0x36, + 0xb4, 0xb1, 0xcc, 0xcf, 0x72, 0x18, 0x03, 0x03, + 0xef, 0x4a, 0x07, 0x25, 0xe8, 0xfd, 0x52, 0x2a, + 0xca, 0xe0, 0x50, 0xb3, 0x5e, 0xeb, 0x94, 0xa0, + 0xb6, 0xad, 0xe3, 0x1a, 0xf0, 0xd9, 0x18, 0xac, + 0x14, 0x50, 0x64, 0x92, 0xcd, 0xce, 0x2e, 0xbc, + 0x77, 0x9f, 0xc1, 0x1c, 0x7d, 0x5f, 0x94, 0x65, + 0x84, 0xd6, 0x5f, 0x30, 0x27, 0xd7, 0x6b, 0xd4, + 0x4c, 0x7d, 0xdc, 0x7f, 0xca, 0x77, 0x35, 0xfe, + 0xef, 0xfd, 0xbc, 0x4d, 0x65, 0x02, 0xf7, 0xc9, + 0xe7, 0x79, 0x4a, 0x3c, 0x45, 0xf4, 0x71, 0x17, + 0x05, 0x2d, 0xfc, 0x42, 0x27, 0x0c, 0xc1, 0xce, + 0x39, 0x10, 0x9a, 0x08, 0x74, 0xac, 0xdb, 0xc5, + 0x3f, 0xf4, 0x85, 0x32, 0x32, 0x3a, 0x8b, 0x07, + 0x5a, 0xf1, 0x2a, 0x12, 0x29, 0xd3, 0xdc, 0x86, + 0x5c, 0xc8, 0x93, 0xae, 0xb4, 0xfe, 0xa7, 0xe3, + 0xdc, 0x9f, 0xc7, 0x4e, 0xd3, 0x51, 0xd3, 0xbd, + 0x01, 0x00, 0x01, +}; + +static EVP_PKEY * +EVP_PKEY_from_PEM(const char *ptr, size_t len) +{ + BIO *bio = NULL; + EVP_PKEY *pkey = NULL; + + if ((bio = BIO_new(BIO_s_mem())) == NULL) { + warnx("BIO_new"); + goto out; + } + if (len > INT_MAX || BIO_write(bio, ptr, (int)len) != (int)len) { + warnx("BIO_write"); + goto out; + } + if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) + warnx("PEM_read_bio_PUBKEY"); +out: + BIO_free(bio); + + return pkey; +} + +static int +rs256_pk_cmp(const char *ptr, size_t len) +{ + EVP_PKEY *pkA = NULL; + EVP_PKEY *pkB = NULL; + rs256_pk_t *k = NULL; + int r, ok = -1; + + if ((pkA = EVP_PKEY_from_PEM(ptr, len)) == NULL) { + warnx("EVP_PKEY_from_PEM"); + goto out; + } + if ((k = rs256_pk_new()) == NULL) { + warnx("rs256_pk_new"); + goto out; + } + if ((r = rs256_pk_from_EVP_PKEY(k, pkA)) != FIDO_OK) { + warnx("rs256_pk_from_EVP_PKEY: 0x%x", r); + goto out; + } + if ((pkB = rs256_pk_to_EVP_PKEY(k)) == NULL) { + warnx("rs256_pk_to_EVP_PKEY"); + goto out; + } + if ((r = EVP_PKEY_cmp(pkA, pkB)) != 1) { + warnx("EVP_PKEY_cmp: %d", r); + goto out; + } + + ok = 0; +out: + EVP_PKEY_free(pkA); + EVP_PKEY_free(pkB); + rs256_pk_free(&k); + + return ok; +} + +static void +invalid_size(const char *pem) +{ + EVP_PKEY *pkey; + rs256_pk_t *pk; + + ASSERT_NOT_NULL((pkey = EVP_PKEY_from_PEM(pem, strlen(pem)))); + ASSERT_NOT_NULL((pk = rs256_pk_new())); + ASSERT_INVAL(rs256_pk_from_EVP_PKEY(pk, pkey)); + + EVP_PKEY_free(pkey); + rs256_pk_free(&pk); +} + +static void +valid_size(const char *pem, const unsigned char *raw, size_t raw_len) +{ + EVP_PKEY *pkeyA; + EVP_PKEY *pkeyB; + rs256_pk_t *pkA; + rs256_pk_t *pkB; + + ASSERT_NOT_NULL((pkeyA = EVP_PKEY_from_PEM(pem, strlen(pem)))); + ASSERT_NOT_NULL((pkA = rs256_pk_new())); + ASSERT_NOT_NULL((pkB = rs256_pk_new())); + ASSERT_OK(rs256_pk_from_EVP_PKEY(pkA, pkeyA)); + ASSERT_OK(rs256_pk_from_ptr(pkB, raw, raw_len)); + ASSERT_NOT_NULL((pkeyB = rs256_pk_to_EVP_PKEY(pkB))); + assert(EVP_PKEY_cmp(pkeyA, pkeyB) == 1); + assert(rs256_pk_cmp(pem, strlen(pem)) == 0); + + EVP_PKEY_free(pkeyA); + EVP_PKEY_free(pkeyB); + rs256_pk_free(&pkA); + rs256_pk_free(&pkB); +} + +int +main(void) +{ + fido_init(0); + + invalid_size(rsa1024); + invalid_size(rsa3072); + valid_size(rsa2048, rsa2048_raw, sizeof(rsa2048_raw)); + + exit(0); +}